;-- routine for testing if it is possible to place the block on position x,y --
test movlw 4 ;131 cycles
movwf counter2 ;hitcounter = 4
movwf counter0 ;test 4 bits
movlw currbl ;point at current block
movwf fsr ;with fsr
testl movfw blockx
addwf indf,w
incf fsr
movwf x ;x = x0 + blockdiffx
movfw blocky
addwf indf,w
incf fsr
movwf y ;y = y0 + blockdiffy
movfw fsr
movwf counter1 ;save fsr
call getbit ;get bit
andwf indf,w ;test bit
skpnz
decf counter0
movfw counter1 ;restore fsr
movwf fsr
decfsz counter2
goto testl
movf counter0 ;set Z if ok
return
;################### HERE STARTS THE MAIN THREAD OF TETRIS ####################
tetrismain call vertsync ;do vertical retrace
btfsc stuff,gameover
goto nogame
call createnext ;create the preview image (line 0)
call remblock ;hide the preview image (line 1)
call createcurrent ;create the current image (line 2)
call remblock ;hide the current image (line 3)
;----------------------------- make block fall -------------------------------
call hsync ;horizontal sync (line 4)
btfsc blockstuff,hsfall ;check for high speed fall (drop)
goto fall
decfsz fallcnt ;decrease fallcounter
goto nofall ;if not zero, then dont fall
fall
movfw points ;calculate speed from the most
sublw 0xa ;significant digit of the score
movwf fallcnt
rlf fallcnt
rlf fallcnt
incf blocky ;move block down
call test ;check if it was ok
skpnz
goto fallok ;if ok, skip the newblock below
movlw 0x0B
delay
decf blocky
call showblock ;make the old block visible (line 5)
call hsync ;horizontal sync (line 6)
newblock clrf blockstuff
movlw 0x9
movwf blockx ;blockx = 9
movlw 0x1
movwf blocky ;blocky = 1
movfw nextblocktyp
movwf blocktyp ;blocktyp = nexttyp
movfw random
movwf nextblocktyp ;nexttyp = random
clrf angle ;angle = 0
call incpoints ;add one point
bcf blockstuff,hsfall
movfw y0
sublw 1
skpnz ;if y = 1 then
bsf stuff,gameover ;game over
btfss left1p,left1b ;check left
bsf blockstuff,goleft
btfss right1p,right1b ;check right
bsf blockstuff,goright
btfss fire1p,fire1b ;check fire (rotate)
bsf blockstuff,rotate
btfss down1p,down1b ;check down (drop)
bsf blockstuff,drop
btfss stuff,1 ;rotate last time ?
goto norotate ;yes, wait for release
btfsc blockstuff,rotate ;check rotate
bsf blockstuff,rotat ;if rotate start rotate
btfsc blockstuff,rotate ;check rotate
bcf stuff,1 ;if rotation then remember it
nop
norotater bcf blockstuff,rotate ;clear rotation indicator
btfss stuff,2 ;down last time ?
goto nofallu ;yes, wait for release
btfsc blockstuff,drop ;check down
bsf blockstuff,hsfall ;if down start fall
btfsc blockstuff,drop ;check down
bcf stuff,2 ;if down then remember it
nop
nofallur bcf blockstuff,drop ;and clear down indicator
bcf blockstuff,goleft ;clear move left indicator
bcf blockstuff,goright ;clear move right indicator
;---------------- search for filled line in the 8 first lines ---------------
bcf porta,0 ;start sync (line 12)
dnop
dnop
movlw 8 ;check the first 8 lines this scanline
movwf counter0
movlw buffer ;set up pointer to screen buffer
movwf fsr
clrf line
dnop
bsf porta,0 ;end sync
movlw 6 ;wait for 6 uS
delay
clrf remline
remfilledl11 movfw indf ;get first byte of line
incf fsr ;move pointer to next byte
sublw 0xF0 ;is it "filled" ?
skpz
goto nofilled11 ;nope, we're outa here
movfw indf ;get second byte of line
incf fsr ;move pointer to next byte (next line)
sublw 0xFF ;is it "filled" ?
skpz
goto nofilled21 ;nope, we're outa here
movfw line
movwf remline ;save line nr
nop
nofilledr1 incf line ;count up line nr
decfsz counter0
goto remfilledl11
;------------ search for filled line in the following 7 lines -------------
remfilledl12 movfw indf ;get first byte of line
incf fsr ;move pointer to next byte
sublw 0xF0 ;is it "filled" ?
skpz
goto nofilled12 ;nope, we're outa here
movfw indf ;get second byte of line
incf fsr ;move pointer to next byte (next line)
sublw 0xFF ;is it "filled" ?
skpz
goto nofilled22 ;nope, we're outa here
movfw line
movwf remline ;save line nr
nop
nofilledr2 incf line ;count up line nr
decfsz counter0
goto remfilledl12
movlw 0x0B ;wait for 12 uS
delay
; ---------- if one line is going to be removed, add lots of points -----------
; --------------- remove line part 1: if neccessary, remove 15 blocks ---------
bcf porta,0 ;start sync (line 15)
movlw 0x10 ;remove all crap at top of screen
movwf buffer
movlw 0x80
movwf buffer + 1
dnop
movfw remline
addwf remline,w
movwf counter0 ;half lines to be removed = 2*remline
addlw buffer + 1 ;start pointer = 2*remline + buffer base + 1
movwf fsr
bsf porta,0 ;end sync
movlw 0xF
subwf counter0,w
movwf counter2
movwf counter3
btfsc counter2,7 ;do we only have to move less than 15 blocks ?
goto remshort ;yes, skip this part
movlw 0xF ;else remove 15 lines first
movwf counter0
remfilledl21 decf fsr ;move blocks two steps in buffer
decf fsr
movfw indf ;get data at fsr - 2
incf fsr ;move back again
incf fsr
movwf indf ;put it at fsr
decf fsr ;point to next block to move
decfsz counter0
goto remfilledl21
movlw 0x7 ;wait 7us for line to end
delay
; --------------- remove line part 2: remove the other blocks -------------
movfw indf ;get left byte of gfx
movwf portb ;start showing first bit
movlw 7 ;set up counter for next 7 bits
movwf counter0
incf fsr ;point at right gfx byte
db0 bcf portb,0 ;one black vertical line between the blocks
rrf portb ;show next bit
decfsz counter0 ;keep on looping, showing all bits
goto db0
movfw indf ;get right byte of gfx
bcf portb,0 ;one black vertical line between the blocks
movwf portb ;start showing first bit
movlw 7 ;set up counter for next 7 bits
movwf counter0
decf fsr ;point at left gfxbyte again
db1 bcf portb,0 ;one black vertical line between the blocks
rrf portb ;show next bit
decfsz counter0 ;keep on looping, showing all bits
goto db1
movlw 0xF - 5
bcf portb,0 ;set level to black
delay ;for 16us
call sound
nop
movlw 2 ;prepare for 2 emptylines
movwf counter1
decfsz counter3
goto tml1 ;do all 12 lines
bcf porta,0
call ell2 ;do 2 emptylines
dnop
incf fsr ;point at next line (each line is 2 bytes)
incf fsr
decfsz counter2 ;do all 16 blocklines
goto tml0
bcf stuff,3 ;clear x-mirror flag
bcf stuff,4 ;clear y-mirror flag
btfsc angle,1 ;if angle = 2 or 3
bsf stuff,4 ;then set y-mirror flag
movfw angle
xorlw 1 ;if angle = 1
skpnz
bsf stuff,3 ;then set x-mirror flag
xorlw 1+2 ;if angle = 2
skpnz
bsf stuff,3 ;then set x-mirror flag
clrc
rlf blocktyp,w ;pointer = blocktyp * 2
call blocks ;get x-blockinfo from pointer
movwf counter0 ;save x-blockinfo
clrc
rlf blocktyp,w
addlw 1 ;pointer = blocktyp * 2 + 1
call blocks ;get y-blockinfo from pointer
movwf counter1 ;save y-blockinfo
btfss angle,0 ;if angle = 1, or angle = 3
goto mbnoswap
xorwf counter0,w ;then swap x and y blockinfo
xorwf counter1
xorwf counter0
mbnoswapr movlw 4
movwf counter2 ;we have 4 coordinat pairs per block
movlw currbl
movwf fsr ;setup pointer to image buffer
mbl0 movfw counter0 ;get x-blockinfo
call convert ;convert the two first bits into a coordinat value
btfsc stuff,3 ;if x-mirror flag = 1
sublw 0 ;then make the x-coordinate negative
movwf indf ;save x-coordinate in image buffer
incf fsr ;move pointer to next position in image buffer
movfw counter1 ;get y-block info
call convert ;convert the two first bits into a coordinate value
btfsc stuff,4 ;if y-mirror flag = 1
sublw 0 ;then make the y-coordinate negative
movwf indf ;save y-coordinate in image buffer
incf fsr ;move pointer to next position in image buffer
rrf counter0 ;rotate x-blockinfo to the next two bits
rrf counter0
rrf counter1 ;rotate y-blockinfo to the next two bits
rrf counter1
decfsz counter2 ;do all 4 coordinate pairs
goto mbl0
return
sound bsf porta,4 ;set sound output to 1
btfss stuff,6 ;check sound state
bcf porta,4 ;if soundstate is 0 then sound output should be 0
movfw m_freq ;get current frequency
decfsz m_cnt ;decrease sound counter, check if it becomes zero
goto soundsk
movwf m_cnt ;if zero, set music counter to current frequency
btfsc stuff,6
goto skstuff
nop
bsf stuff,6
return
skstuff bcf stuff,6
return
soundsk dnop
dnop
return
;------------------------ Set frequency (music routine) -----------------------
music call hsync
movlw 0x36 ;prepare for some long delay or something
decfsz m_songcnt ;update music counter
goto nochnote ;if not zero, dont update
bsf status,rp0 ;setup some eeprom read stuff
bsf eecon1,rd
bcf status,rp0
movf m_freq ;check current frequency
skpz
goto pause ;if freq is not zero, make a pause
movfw eedata ;get one note
andlw 0x3F ;mask out frequenvy
movwf m_freq ;store it
swapf eedata,w ;get note + length, swap upper and lower part into w
andlw 0xC ;mask out length
movwf counter3
clrc
rrf counter3 ;rotate down the length
rrf counter3
clrc
rrf points,w
movwf delaycnt
clrc
rlf delaycnt
addwf delaycnt,w ;points/2*3
addwf counter3,w ;points/2*3 + shortlength
call getlength ;get real length
movwf m_songcnt
incf eeadr ;next song position
movfw eeadr
sublw 0x34 ;end of song ?
skpnz
clrf eeadr ;if so, restart song
movlw 0x2B ;this delay is not very critical
nochnote delay
return