453 lines
16 KiB
Plaintext
453 lines
16 KiB
Plaintext
%include ../include/gigatron.i
|
|
|
|
; 0x30 -> 0x38 Vars
|
|
; 0x3A -> 0x45 Midi
|
|
; 0x4A -> 0x96 CallTable *DO NOT* pull CallTable above 0xBE, future ROMS will *NOT* work as the CallTable is preloaded and will conflict with future loading mechanisms
|
|
; 0x98 -> 0xE5 Vars
|
|
; 0xE6 -> 0xFF Stack The amount of stack space you will require depends on how many nested CALLS you make, 28 bytes allows for upto 14 nested calls
|
|
|
|
kk EQU 0x30
|
|
ll EQU kk + 0x01
|
|
mm EQU kk + 0x02
|
|
nn EQU kk + 0x03
|
|
tt EQU kk + 0x04
|
|
buttonStatePrev EQU kk + 0x05
|
|
refresh EQU kk + 0x06
|
|
blocked EQU kk + 0x07
|
|
tetrominoNext EQU kk + 0x08
|
|
|
|
midiStreamPtr EQU 0x3A
|
|
midiCommand EQU midiStreamPtr + 0x02
|
|
midiChannel EQU midiStreamPtr + 0x04
|
|
midiDelay EQU midiStreamPtr + 0x06
|
|
midiNote EQU midiStreamPtr + 0x08
|
|
midiScratch EQU midiStreamPtr + 0x0A
|
|
|
|
xx EQU 0x98
|
|
yy EQU xx + 0x01
|
|
ii EQU xx + 0x02
|
|
jj EQU xx + 0x03
|
|
|
|
index EQU xx + 0x04
|
|
rotation EQU xx + 0x06
|
|
indexNext EQU xx + 0x08
|
|
rotationNext EQU xx + 0x0A
|
|
tx EQU xx + 0x0C
|
|
ty EQU xx + 0x0E
|
|
tw EQU xx + 0x10
|
|
th EQU xx + 0x12
|
|
tu EQU xx + 0x14
|
|
tv EQU xx + 0x16
|
|
ox EQU xx + 0x18
|
|
oy EQU xx + 0x1A
|
|
ov EQU xx + 0x1C
|
|
oindex EQU xx + 0x1E
|
|
orotation EQU xx + 0x20
|
|
tetrominoLut EQU xx + 0x22
|
|
tetrominoBase EQU xx + 0x24
|
|
colour EQU xx + 0x26
|
|
result EQU xx + 0x28
|
|
frameCounter EQU xx + 0x2A
|
|
frameCountPrev EQU xx + 0x2C
|
|
frameTicks EQU xx + 0x2E
|
|
frameTicksLevel EQU xx + 0x30
|
|
rand EQU xx + 0x32
|
|
scratch EQU xx + 0x34
|
|
vbase EQU xx + 0x36
|
|
xScroll EQU xx + 0x38
|
|
tbase EQU xx + 0x3A
|
|
dbase EQU xx + 0x3C
|
|
textStr EQU xx + 0x3E
|
|
textPos EQU xx + 0x40
|
|
textChr EQU xx + 0x42
|
|
numLines EQU xx + 0x44
|
|
scoreDelta EQU xx + 0x46
|
|
scoreLevel EQU xx + 0x48
|
|
scoreUpdate EQU xx + 0x4A
|
|
scoreScratch EQU xx + 0x4C
|
|
|
|
xTetris EQU 10
|
|
yTetris EQU 20
|
|
xPixels EQU xTetris*4
|
|
yPixels EQU yTetris*4
|
|
xOffset EQU (giga_xres - xPixels) / 2
|
|
yOffset EQU (giga_yres - yPixels) / 2
|
|
maxLines EQU 4
|
|
maxLevel EQU 8
|
|
maxTicks EQU 50
|
|
deltaTicks EQU 5
|
|
scorePos EQU 0x6D44
|
|
levelPos EQU 0x6D5F
|
|
highPos EQU 0x1644
|
|
multPos EQU 0x6D3A
|
|
fgColourB EQU 0xFF
|
|
bgColourB EQU 0x15
|
|
bgColourW EQU 0x1515
|
|
|
|
_startAddress_ EQU 0x0200 ; entry point for the code, if this is missing defaults to 0x0200
|
|
|
|
_callTable_ EQU 0x0096 ; call addresses are automatically stored here by the assembler, it grows downwards
|
|
; *NOTE* gt1 spec only allows for one zero page segment, .vasm files use this for the call table
|
|
; do *NOT* make this address higher than 0x00BE, it will conflict with future ROM loading mechanisms
|
|
; do *NOT* define constants, (DB or DW), between 0x30 -> 0x44 and 0xc0 -> 0xFF, these addresses are
|
|
; used by the loader and the vCPU stack, you can create variables in these areas as long as you don't
|
|
; corrupt your nested CALL return addresses on the stack
|
|
|
|
_singleStepWatch_ EQU frameCounter ; the single step debugger watches this variable location to decide when to step,
|
|
; choose a variable that is updated often
|
|
_cpuUsageAddressA_ EQU 0x0600 ; these two addresses are used to build an exclusion zone around vCPU code that will not be counted
|
|
_cpuUsageAddressB_ EQU 0x0620 ; in the vCPU usage meter, (almost always used to exclude your VBlank polling loop)
|
|
|
|
|
|
%include midi_scores.i
|
|
%include tetromino.i
|
|
|
|
scoringLut EQU tetromino_I + 0x0700
|
|
levellingLut EQU tetromino_I + 0x0705
|
|
scoringLut DB 10 25 50 100
|
|
levellingLut DW 250 750 1000 2000 4000 8000 16000 32000 64000
|
|
|
|
score_string EQU 0x7FA1
|
|
high_string EQU 0x7FA8
|
|
level_string EQU 0x7FAF
|
|
mult_string EQU 0x7FB2
|
|
score_string DB 6 '000000'
|
|
high_string DB 6 '000000'
|
|
;level_string DB 7 'LEVEL 0'
|
|
; TODO: build a complete font set, right now ':' = 'L' and ';' = 'x'
|
|
level_string DB 2 ':0'
|
|
mult_string DB 2 ';1'
|
|
|
|
|
|
; tetromino_I gets an extra slot to make rand easier to implement, this also means tetromino_I will appear statistically more often,
|
|
; replace with which ever tetromino you want to favour
|
|
tetromino_lut EQU 0x08E0
|
|
tetromino_lut DW tetromino_I tetromino_J tetromino_L tetromino_O tetromino_S tetromino_T tetromino_Z tetromino_I
|
|
|
|
|
|
entry_point EQU 0x0200
|
|
handleInput EQU entry_point + 0x0100
|
|
updateScore EQU entry_point + 0x0200 ; too big to store in unused area of video memory
|
|
incrementScore EQU entry_point + 0x0300 ; too big to store in unused area of video memory
|
|
waitVBlank EQU entry_point + 0x0400
|
|
|
|
|
|
; storing subroutines in unused areas of video memory
|
|
clearBoard EQU 0x15A1
|
|
clearScreen EQU clearBoard + 0x0100
|
|
clearScreen_0 EQU clearBoard + 0x0200
|
|
setTetrisBlock EQU clearBoard + 0x0300
|
|
drawTetromino EQU clearBoard + 0x0400
|
|
drawNextTet EQU clearBoard + 0x0500
|
|
drawTetrisField EQU clearBoard + 0x0600
|
|
drawTFtopH EQU clearBoard + 0x0700
|
|
drawTFbotH EQU clearBoard + 0x0800
|
|
eraseTetromino EQU clearBoard + 0x0900
|
|
eraseTrCorner EQU clearBoard + 0x0A00
|
|
getTetrisBlock EQU clearBoard + 0x0B00
|
|
checkTetromino EQU clearBoard + 0x0C00
|
|
spawnTetromino EQU clearBoard + 0x0D00
|
|
updateTetromino EQU clearBoard + 0x0E00
|
|
checkLines EQU clearBoard + 0x0F00
|
|
moveLines EQU clearBoard + 0x1000
|
|
shakeScreen EQU clearBoard + 0x1100
|
|
printText EQU clearBoard + 0x1200
|
|
printDigits EQU clearBoard + 0x1300
|
|
updateHighScore EQU clearBoard + 0x1400
|
|
resetLevel EQU clearBoard + 0x1500
|
|
resetScore EQU clearBoard + 0x1600
|
|
incrementLevel EQU clearBoard + 0x1700
|
|
loadTetromino EQU clearBoard + 0x1800
|
|
resetAudio EQU clearBoard + 0x1900
|
|
playMidi EQU clearBoard + 0x1A00
|
|
midiStartNote EQU clearBoard + 0x1B00
|
|
midiSegment EQU clearBoard + 0x1C00
|
|
|
|
|
|
%include macros.i
|
|
%include clear_board.i
|
|
%include draw_tetromino.i
|
|
%include erase_tetromino.i
|
|
%include check_tetromino.i
|
|
%include spawn_tetromino.i
|
|
%include check_lines.i
|
|
%include print_text.i
|
|
%include update_score.i
|
|
%include digit_font.i
|
|
%include audio.i
|
|
|
|
|
|
entry_point LDWI giga_vram
|
|
STW vbase ; vram base address
|
|
LDWI giga_text32
|
|
STW tbase ; text font base address, (ROM)
|
|
LDWI digit_font0
|
|
STW dbase ; tiny digit font base address, (RAM)
|
|
LDWI giga_videoTable + 1
|
|
STW xScroll
|
|
|
|
CALL resetAudio
|
|
CALL clearScreen
|
|
CALL drawTetrisField
|
|
|
|
restart CALL resetLevel
|
|
CALL resetScore
|
|
CALL clearBoard
|
|
|
|
LDWI 0x0000
|
|
STW scoreDelta
|
|
STW scoreLevel
|
|
STW frameCounter
|
|
|
|
LDWI maxTicks
|
|
STW frameTicksLevel
|
|
STW frameTicks
|
|
|
|
LD giga_rand0
|
|
ST tetrominoNext
|
|
|
|
LDI 0x00
|
|
ST blocked
|
|
|
|
LD giga_frameCount
|
|
STW frameCountPrev
|
|
|
|
LDWI tetromino_lut
|
|
STW tetrominoLut
|
|
|
|
CALL spawnTetromino
|
|
|
|
LD giga_frameCount ; Start checking midi stream immediately
|
|
ST midiDelay
|
|
|
|
; main update loop
|
|
update ST scratch
|
|
CALL saveTetromino
|
|
|
|
; wait for VBlank
|
|
vBlank CALL waitVBlank
|
|
CALL playMidi
|
|
|
|
; input
|
|
CALL handleInput
|
|
ST refresh
|
|
XORI 0xFB ; down
|
|
BEQ frame_count1
|
|
LD refresh ; all other input
|
|
BNE erase
|
|
|
|
; reset frameTicks
|
|
LDW frameTicksLevel
|
|
STW frameTicks
|
|
|
|
; frameTicks defines speed of tetrominoes
|
|
frame_count1 LDW frameCounter
|
|
ADDI 0x01
|
|
STW frameCounter
|
|
SUBW frameTicks
|
|
BLT vBlank
|
|
|
|
; don't allow input to override timing
|
|
LDI 0x00
|
|
ST refresh
|
|
|
|
; erase old tetromino
|
|
erase LD blocked
|
|
BNE check_txl
|
|
CALL eraseTetromino
|
|
|
|
; if(tx < 0 - tu) tx = 0 - tu;
|
|
check_txl LDW tx
|
|
ADDW tu
|
|
BGE check_txr
|
|
LDWI 0x00
|
|
SUBW tu
|
|
STW tx
|
|
BRA frame_count0
|
|
|
|
; if(tx > TETRIS_XEXT - tw - tu) tx = TETRIS_XEXT - tw - tu;
|
|
check_txr LDW tx
|
|
ADDW tw
|
|
ADDW tu
|
|
SUBI xTetris
|
|
BLE frame_count0
|
|
LDWI xTetris
|
|
SUBW tw
|
|
SUBW tu
|
|
STW tx
|
|
|
|
; if(frameCount >= frameTick)
|
|
frame_count0 LDW frameCounter
|
|
SUBW frameTicks
|
|
BLT check_blocks
|
|
LDWI 0x0000
|
|
STW frameCounter
|
|
LDI 0x00 ; reset flicker control
|
|
ST blocked
|
|
|
|
; gravity
|
|
INC ty
|
|
|
|
; if(y > TETRIS_YEXT - h)
|
|
LDW ty
|
|
ADDW th
|
|
SUBI yTetris
|
|
BLE check_blocks
|
|
|
|
; draw floor tetromino
|
|
LD ty
|
|
SUBI 0x01
|
|
ST ty
|
|
CALL drawTetromino
|
|
|
|
; spawn new tetromino
|
|
CALL spawnTetromino
|
|
LDI 0xFF ; control flicker
|
|
ST blocked
|
|
BRA update
|
|
|
|
; check new tetromino position
|
|
check_blocks CALL checkTetromino ; checks tetromino for occupied blocks, returns result, 0 = empty, 1 = game over, >1 = blocked
|
|
LDW result
|
|
BEQ draw_new
|
|
|
|
; check for game over
|
|
SUBI 0x01
|
|
BNE check_blocked
|
|
CALL resetAudio
|
|
LDWI game_overMidi00 ; game over music
|
|
STW midiStreamPtr
|
|
BRA restart
|
|
|
|
; check for fall blocked whilst input active, (but not drop)
|
|
check_blocked LD refresh
|
|
BEQ fall_blocked
|
|
|
|
; load old tetromino
|
|
CALL loadTetromino
|
|
BRA draw_new
|
|
|
|
; draw falling blocked tetromino at previous y position
|
|
fall_blocked LD ty
|
|
SUBI 0x01
|
|
ST ty
|
|
CALL drawTetromino
|
|
|
|
; spawn new tetromino
|
|
CALL spawnTetromino
|
|
BRA update
|
|
|
|
draw_new CALL drawTetromino
|
|
BRA update
|
|
|
|
|
|
; load tetromino state
|
|
loadTetromino LDW ox
|
|
STW tx
|
|
LDW oy
|
|
STW ty
|
|
LDW ov ; vertical offset in tetris block units
|
|
STW tv
|
|
LDW oindex
|
|
STW index
|
|
LDW orotation
|
|
STW rotation
|
|
RET
|
|
|
|
; save tetromino state
|
|
saveTetromino LDW tx
|
|
STW ox
|
|
LDW ty
|
|
STW oy
|
|
LDW tv ; vertical offset in tetris block units
|
|
STW ov
|
|
LDW index
|
|
STW oindex
|
|
LDW rotation
|
|
STW orotation
|
|
RET
|
|
|
|
|
|
; handle input, returns 0x00 if nothing was handled, otherwise returns input
|
|
handleInput LD giga_buttonState ; 0xFF is no input
|
|
XORI 0xFF
|
|
BNE handleI_down
|
|
ST buttonStatePrev ; return 0x00
|
|
RET
|
|
|
|
; level triggered buttons
|
|
handleI_down LD giga_buttonState
|
|
XORI 0xFB ; down
|
|
BNE handleI_event
|
|
LDWI 2
|
|
STW frameTicks
|
|
LD giga_buttonState
|
|
RET
|
|
|
|
; edge triggering
|
|
handleI_event LD buttonStatePrev ; only handle new events
|
|
BEQ handleI_left
|
|
LD 0x00
|
|
RET
|
|
|
|
; edge triggered buttons
|
|
handleI_left LD giga_buttonState
|
|
ST buttonStatePrev
|
|
XORI 0xFD ; left
|
|
BNE handleI_right
|
|
|
|
LDW tx ; tx--
|
|
SUBI 0x01
|
|
STW tx
|
|
LD giga_buttonState
|
|
RET
|
|
|
|
handleI_right LD giga_buttonState
|
|
XORI 0xFE ; right
|
|
BNE handleI_up
|
|
|
|
LDW tx ; tx++
|
|
ADDI 0x01
|
|
STW tx
|
|
LD giga_buttonState
|
|
RET
|
|
|
|
handleI_up LD giga_buttonState
|
|
XORI 0xF7 ; up
|
|
BNE handleI_exit
|
|
|
|
LDW rotation
|
|
STW scratch
|
|
ADDI 0x10 ; rotation table's are separated by 16 bytes
|
|
ANDI 0x30 ; 4 rotation patterns
|
|
STW rotation
|
|
PUSH
|
|
CALL updateTetromino
|
|
POP
|
|
|
|
; check rotation
|
|
LDW ty ; if(ty > TETRIS_YEXT - th - tv)
|
|
ADDW th
|
|
ADDW tv
|
|
SUBI yTetris
|
|
BLE handleI_exit
|
|
|
|
; restore rotation
|
|
LDW scratch
|
|
STW rotation
|
|
PUSH
|
|
CALL updateTetromino
|
|
POP
|
|
LD 0x00
|
|
RET
|
|
|
|
handleI_exit LD giga_buttonState
|
|
RET
|
|
|
|
|
|
waitVBlank LD giga_frameCount
|
|
SUBW frameCountPrev
|
|
BEQ waitVBlank
|
|
LD giga_frameCount
|
|
STW frameCountPrev
|
|
RET |