gigatron/rom/Contrib/xxxbxxx/bricks.vasm
2025-01-28 19:17:01 +03:00

913 lines
31 KiB
Plaintext

%include macros/gigatron.i
; ===========================================
; BRICKS (BREAKOUT CLONE)
; ===========================================
; --- mem layout ---
vars EQU 0x00B0
consts EQU 0x0082 ; skip 0x80 - reserved!!
data EQU 0x10c0 ; (unused vram)
entry_point EQU 0x0200
subroutines0 EQU 0x0300
subroutines1 EQU 0x0400
subroutines2 EQU 0x0500
subroutines3 EQU 0x0600
subroutines4 EQU 0x20c0 ; (unused vram)
; 0x700 --> reserved (sound)
; 5 last bytes of 0x200 x300 x400 --> reserved (sound)
; --- vars ---
scratch EQU vars + 0x00
x0 EQU vars + 0x02
y0 EQU vars + 0x03
xy0 EQU x0
x1 EQU vars + 0x04
y1 EQU vars + 0x05
xy1 EQU x1
padx EQU vars + 0x06
speedpad EQU vars + 0x08
ballx EQU vars + 0x0A
bally EQU vars + 0x0C
speedx EQU vars + 0x0E
speedy EQU vars + 0x10
nextballx EQU vars + 0x12
nextbally EQU vars + 0x14
brokencount EQU vars + 0x16
brokenseq EQU vars + 0x18
vb_PrevFrame EQU vars + 0x1E
; --- subroutines args & locals ---
PrintText_Str EQU vars + 0x20
PrintText_Pos EQU vars + 0x22
_pt_tt EQU vars + 0x24
_pt_ii EQU vars + 0x25
_pt_Char EQU vars + 0x26
DrawBrick_xy EQU vars + 0x20
DrawBrick_col EQU vars + 0x22
_db_i EQU vars + 0x24
_db_j EQU vars + 0x26
BreakBrick_xy EQU vars + 0x28 ; also used as local var in mainloop.
_bb_i EQU vars + 0x22
_bb_j EQU vars + 0x24
_pt_key EQU vars + 0x22
; --- constants ---
giga_vram_y EQU 0x08
speedupy EQU 10 ; 0.04
initspeedy EQU 154 ; 0.6
buttonRight EQU 1
buttonLeft EQU 2
buttonDown EQU 4
buttonUp EQU 8
buttonStart EQU 16
buttonSelect EQU 32
buttonB EQU 64
buttonA EQU 128
; 16-bit constants in RAM (no wordimmediate opcodes)
cst_FF00 EQU consts
cst_FF00 DW $FF00 ; for byte to word sign extension
cst_00FF DW $00FF
maxspeedpad DW $0200 ; 2.0
maxpadx DW $7F00 ; 127.0
minpadx DW $2300 ; 35.0
speedxmin DW $FE80 ; -1.5 (ball speed)
speedxrange DW $0100 ; (-0.5+1.5) speed in [-1.5;-.5] [.5;1.5]
speedxmax DW $0180 ; 1.5
speedymax DW $0200 ; 2.0
twopix_white DW $3F3F ; board lines
twopix_black DW $0000 ; board background
twopix_blue DW $3030 ; pad color
twopix_darkblue DW $2020 ; pad color dark
ball_line1 DW $2A3F ; white corner on grey ball (lighting effect , and highlight the active pixel)
ball_line2 DW $2A2A
_soundChan1val EQU giga_soundChan1+2 ; (DW do not support expressions)
_soundChan2val EQU giga_soundChan2+2
_soundChan3val EQU giga_soundChan3+2
_soundChan4val EQU giga_soundChan4+2
soundChan1 DW _soundChan1val
soundChan2 DW _soundChan2val
soundChan3 DW _soundChan3val
soundChan4 DW _soundChan4val
; --- data ------------
string_lives EQU data + 0x00
string_lives DB 10 '3 '
string_score DB 3 '000'
string_gameover DB 10 'Game Over!'
string_victory DB 10 'Break Out!'
; 14x8 bricks grid
bricksx EQU data + 0x0100
bricksx DB 32 39 46 53 60 67 74 81 88 95 102 109 116 123
bricksy DW 0x2000 0x2300 0x2600 0x2900 0x2C00 0x2F00 0x3200 0x3500
brickscol DB 0x03 0x03 0x0B 0x0B 0x0C 0x0C 0x0F 0x0F
BounceTable0 EQU data + 0x0200
BounceTable EQU BounceTable0 + 0x0E ; offset 0 is the center of the the table.
BounceTable0 DW 0xFF80 0xFFB0 0xFFB0 0 0 0 0 0 0 0 0X0050 0X0050 0x0080
;BounceTable0 DW 0xFF60 0xFF80 0xFF80 0XFFC0 0 0 0 0 0 0X0040 0X0080 0X0080 0x00A0
############################################################################################################
################################## PAGE BREAK ##############################################################
############################################################################################################
entry_point CALL DrawBoard
CALL InitAudio
restart LDWI 80*256 ; init pad
STW padx
LDI 0
STW speedpad
STW brokencount
CALL ResetScore
CALL DrawBricks
CALL InitRound
mainloop LDI 1
CALL WaitVBlanks
; -- move pad --
LD giga_buttonState
XORI $FF ; NOT
ANDI buttonRight + buttonLeft
BEQ noinput
LDW speedpad
BNE skipinit
LDI 240 ; initial speed as soon a button pressed
skipinit ADDI 16 ; 256/16==16 frames to reach fullspeed
STW speedpad
SUBW maxspeedpad
BLE dobuttons
LDW maxspeedpad
STW speedpad
dobuttons LD giga_buttonState
ANDI buttonRight
BNE rightdone
LDW padx
ADDW speedpad
STW padx
SUBW maxpadx
BLE rightdone
LDW maxpadx
STW padx
rightdone LD giga_buttonState
ANDI buttonLeft
BNE inputdone
LDW padx
SUBW speedpad
STW padx
SUBW minpadx
BGE inputdone
LDW minpadx
STW padx
BRA inputdone
noinput LDI 0
STW speedpad
inputdone CALL DrawBall ; Erase cur ball
CALL DrawPad
; -- update ball --
LDW ballx
ADDW speedx
STW nextballx
LD nextballx+1
ST BreakBrick_xy
LD bally+1
ST BreakBrick_xy+1
LDW BreakBrick_xy
PEEK
BEQ xbounceskip
ANDI 0x30 ; bricks are not blue..
BNE notbrickx
CALL BreakBrick
notbrickx LDI 0
SUBW speedx
STW speedx
LDW ballx
STW nextballx
xbounceskip LDW bally
ADDW speedy
STW nextbally
LD nextballx+1
ST BreakBrick_xy
LD nextbally+1
ST BreakBrick_xy+1
LDW BreakBrick_xy
PEEK
BEQ ybounceskip
ANDI 0x30 ; bricks are not blue..
BNE notbricky
CALL BreakBrick
notbricky LD nextbally+1
SUBI giga_vram_y+100
BLT notpadbounce
LDI 30
CALL PlayTone
CALL BouncePad
notpadbounce LDI 0
SUBW speedy
STW speedy
LDW bally
STW nextbally
ybounceskip LDW nextballx
STW ballx
LDW nextbally
STW bally
CALL DrawBall
LD bally+1
SUBI giga_vram_y+114
BLT mainloop
; ball dropped..
balllost LDW brokenseq
BEQ balllost2
SUBI 1
STW brokenseq
ADDI 35
CALL PlayTone
CALL WaitVBlanks
BRA balllost
; add a screen shake?
balllost2 CALL DecrementLives
BLE gameover
CALL InitRound
LDI 42
CALL WaitVBlanks
BRA mainloop
gameover CALL GameOver
BRA restart
############################################################################################################
################################## PAGE BREAK ##############################################################
############################################################################################################
subroutines0 RET
; ===== DrawBricks ============================================================================
DrawOneBrick LDW DrawBrick_col
DOKE DrawBrick_xy
INC DrawBrick_xy
INC DrawBrick_xy
DOKE DrawBrick_xy
INC DrawBrick_xy
INC DrawBrick_xy
DOKE DrawBrick_xy
INC DrawBrick_xy
INC DrawBrick_xy
ANDI $15 ; darken color 2A: little darker 15: very dark,
POKE DrawBrick_xy ; fill in borders so that the ball doesn't squeeze in between bricks
LDWI 0x0100-6 ; next line
ADDW DrawBrick_xy
STW DrawBrick_xy
LDW DrawBrick_col
DOKE DrawBrick_xy
INC DrawBrick_xy
INC DrawBrick_xy
DOKE DrawBrick_xy
INC DrawBrick_xy
INC DrawBrick_xy
DOKE DrawBrick_xy
INC DrawBrick_xy
INC DrawBrick_xy
ANDI $2A ; darken color
POKE DrawBrick_xy ; fill in borders so that the ball doesn't squeeze in between bricks
RET
DrawBricks PUSH
LDI 7
STW _db_j
_db_loopj LDI 13
STW _db_i
_db_loopi LDWI bricksy
ADDW _db_j
ADDW _db_j
DEEK
STW DrawBrick_xy
LDWI bricksx
ADDW _db_i
PEEK
ADDW DrawBrick_xy
STW DrawBrick_xy
LDWI brickscol
ADDW _db_j
PEEK
ST DrawBrick_col
ST DrawBrick_col+1
CALL DrawOneBrick
LD _db_i
SUBI 1
ST _db_i
BGE _db_loopi
LD _db_j
SUBI 1
ST _db_j
BGE _db_loopj
POP
RET
; ===== DrawPad =============================================================================
DrawPad LDI giga_vram_y+110
ST y0
ADDI 1
ST y1
LD padx+1
SUBI 2+6
ST x0
ST x1
LDW twopix_black
DOKE xy0
DOKE xy1
INC x0
INC x0
INC x1
INC x1
LDW twopix_darkblue
DOKE xy0
DOKE xy1
INC x0
INC x0
INC x1
INC x1
LDW twopix_blue
DOKE xy0
DOKE xy1
INC x0
INC x0
INC x1
INC x1
DOKE xy0
DOKE xy1
INC x0
INC x0
INC x1
INC x1
DOKE xy0
DOKE xy1
INC x0
INC x0
INC x1
INC x1
DOKE xy0
DOKE xy1
INC x0
INC x0
INC x1
INC x1
LDW twopix_darkblue
DOKE xy0
DOKE xy1
INC x0
INC x0
INC x1
INC x1
LDW twopix_black
DOKE xy0
DOKE xy1
RET
############################################################################################################
################################## PAGE BREAK ##############################################################
############################################################################################################
subroutines1 RET
; Find the brick containing the position BreakBrick_xy, clears it, and increment score
BreakBrick PUSH
LD BreakBrick_xy
STW scratch
LDI 13
STW _bb_i
_bb_loopi LDWI bricksx
ADDW _bb_i
PEEK
SUBW scratch
BGT _bb_nexti
ADDI 7
BLE _bb_nexti
LDI 7
STW _bb_j
_bb_loopj LDWI bricksy
ADDW _bb_j
ADDW _bb_j
DEEK
STW DrawBrick_xy
SUBW BreakBrick_xy
BGT _bb_nextj
ADDI $FF ; +0x200
ADDI $FF
ADDI 2
BLE _bb_nextj
; found the brick!
LDWI bricksx
ADDW _bb_i
PEEK
ADDW DrawBrick_xy
STW DrawBrick_xy
LDW twopix_black
STW DrawBrick_col
CALL DrawOneBrick
CALL IncrementScore
INC brokencount
INC brokenseq
LDW brokenseq
SUBI 5+28
BLT _bb_playtone
LDI 5+28
STW brokenseq
_bb_playtone LDI 35
ADDW brokenseq
CALL PlayTone
POP
RET
_bb_nextj LD _bb_j
SUBI 1
ST _bb_j
BGE _bb_loopj
POP
RET
_bb_nexti LD _bb_i
SUBI 1
ST _bb_i
BGE _bb_loopi
POP
RET
; ===== ClearBottom =============================================================================
ClearBottom LDI 20
ST x0
_cb_loopx LDI giga_vram_y+110
ST y0
LDW twopix_black
DOKE xy0
INC y0
DOKE xy0
INC y0
DOKE xy0
INC y0
DOKE xy0
INC y0
DOKE xy0
INC y0
DOKE xy0
INC y0
DOKE xy0
INC y0
DOKE xy0
INC y0
DOKE xy0
INC y0
DOKE xy0
LD x0
ADDI 2
ST x0
SUBI 172
BNE _cb_loopx
RET
; ===== Init =============================================================================
InitRound PUSH
CALL ClearBottom
CALL DrawPad
LDWI 80*256+127 ; 80.5
STW ballx
LDWI giga_vram + (50*256+127) ; 50.5
STW bally
LDI initspeedy
STW speedy
LDWI SYS_Random_34 ; Get random number and update entropy
STW giga_sysFn
SYS 0xFD ; 270 - 34/2 = 0xFD
BGT _ib_positive ; get the random number in the range -2.0 .. 2.0
ORW cst_FF00
BRA _ib_clamp
_ib_positive ANDW cst_00FF
_ib_clamp STW speedx
CALL ClampBallSpeed
CALL DrawBall
LDI 5
STW brokenseq
POP
RET
############################################################################################################
################################## PAGE BREAK ##############################################################
############################################################################################################
subroutines2 RET
; ===== DrawBall =============================================================================
DrawBall LD ballx+1
ST scratch
LD bally+1
ST scratch+1
LDW scratch
DEEK
XORW ball_line1
DOKE scratch
INC scratch+1
LDW scratch
DEEK
XORW ball_line2
DOKE scratch
RET
; ===== DrawBoard =============================================================================
DrawBoard LDI giga_vram_y-1
ST y0
_db_nextline INC y0
LD y0
ST y1
SUBI giga_vram_y+120
BEQ _db_done
LDI 80 ; screen center
ST x0
; compute center section color
LD y0
SUBI giga_vram_y+0
ANDI 0xFE ; lines 0 + 1
BEQ _db_whitemid
LD y0
SUBI giga_vram_y+16
ANDI 0xFE ; lines 16+17
BEQ _db_whitemid
_db_blackmid LDW twopix_black
STW scratch
BRA _db_center
_db_whitemid LDW twopix_white
STW scratch
BRA _db_center
_db_center LDI 160
SUBW x0
ST x1 ; (=> xy1 xy0 symetric from center line.)
LDW scratch ; center color (white on separator lines and black otherwise)
DOKE xy0
DOKE xy1
INC x0
INC x0
LD x0
SUBI 80+50
BNE _db_center
_db_edge LDI 160
SUBW x0
ST x1
LDW twopix_white
DOKE xy0
DOKE xy1
INC x0
INC x0
_db_border LDI 160
SUBW x0
ST x1
LDW twopix_black
DOKE xy0
DOKE xy1
INC x0
INC x0
LD x0
SUBI 162
BNE _db_border
BRA _db_nextline
_db_done RET
; ===== BouncePad =============================================================================
ClampBallSpeed LDW speedx
; gprintf("clamp x,y before = %04x,%04x", *speedx, *speedy)
BGE _cbs_speedx_pos
_cbs_speedx_neg SUBW speedxmin
BGT _cbs_xn1
LDW speedxmin
STW speedx
BRA _cbs_speedy
_cbs_xn1 SUBW speedxrange
BLE _cbs_speedy
LDW speedxmin
ADDW speedxrange
STW speedx
BRA _cbs_speedy
_cbs_speedx_pos SUBW speedxmax
BLT _cbs_xn2
LDW speedxmax
STW speedx
BRA _cbs_speedy
_cbs_xn2 ADDW speedxrange
BGE _cbs_speedy
LDW speedxmax
SUBW speedxrange
STW speedx
_cbs_speedy LDW speedy ; assert speedy>0
SUBW speedymax
BLE _cbs_ret
LDW speedymax
STW speedy
; gprintf("clamp x,y after = %04x,%04x", *speedx, *speedy)
_cbs_ret RET
BouncePad LDWI giga_vram+$6B00
STW bally ; force ball above the pad => little impulsion effect.
; (and workaround a bug when you move the pad on the ball after the collision detextion)
LDW nextballx ; x direction control
SUBW padx
STW scratch
BLT _bp_div256neg
LD scratch+1
BRA _bp_div256done
_bp_div256neg LD scratch+1
ORW cst_FF00 ; sign extend
_bp_div256done LSLW ; x2
STW scratch ; tointeger(nextballx-padx) * 2 --> offset in BounceTable
LDWI BounceTable
ADDW scratch
DEEK
ADDW speedx
STW speedx
; speed ball up slightly
LDW speedy
ADDI speedupy
STW speedy
BRA ClampBallSpeed
;RET ; tail call
############################################################################################################
################################## PAGE BREAK ##############################################################
############################################################################################################
subroutines3 RET
; ===== WaitVBlanks =============================================================================
WaitVBlanks ST scratch
_wvb_wait LD giga_frameCount
SUBW vb_PrevFrame
BEQ _wvb_wait
LD giga_frameCount
STW vb_PrevFrame
LD scratch
SUBI 1
BNE WaitVBlanks
RET
; ===== DrawScore =============================================================================
DrawScore PUSH
LDWI string_lives
STW PrintText_Str
LDWI giga_vram + (0x0300 + 34)
STW PrintText_Pos
CALL PrintText
LDWI string_score
STW PrintText_Str
LDWI giga_vram + (0x0800 + 100)
STW PrintText_Pos
CALL PrintText
POP
RET
; ===== ResetScore =============================================================================
ResetScore LDWI string_lives+1
STW scratch
LDI 48+3 ; 48 = '0'
POKE scratch
LDWI string_score+1
STW scratch
LDI 48+0 ; 48 = '0'
POKE scratch
INC scratch
POKE scratch
INC scratch
POKE scratch
INC scratch
BRA DrawScore
; ===== IncrementScore and draw ================================================================
IncrementScore LDWI string_score+3
STW scratch
PEEK
ADDI 1
POKE scratch
SUBI 48+9 ; '9'
BLE DrawScore
LDI 48+0 ; '0'
POKE scratch
LDWI string_score+2
STW scratch
PEEK
ADDI 1
POKE scratch
SUBI 48+9 ; '9'
BLE DrawScore
LDI 48+0 ; '0'
POKE scratch
LDWI string_score+1
STW scratch
PEEK
ADDI 1
POKE scratch
BRA DrawScore
; ===== Decrement lives and draw and return gameover ================================================================
DecrementLives PUSH
LDWI string_lives+1
STW scratch
PEEK
SUBI 1
POKE scratch
CALL DrawScore
LDWI string_lives+1
STW scratch
PEEK
SUBI 48+0 ; '0'
POP
RET
; ===== PrintText =============================================================================
%MACRO LoopCounter _counter _label
LD _counter
SUBI 0x01
ST _counter
BNE _label
%ENDM
; prints text using the inbuilt font and SYS routine
PrintText LDWI SYS_VDrawBits_134 ; setup 8 vertical pixel SYS routine
STW giga_sysFn
LDI 0x00 ; background colour
ST giga_sysArg0
LDI 0x3F ; foreground colour
ST giga_sysArg1
LDW PrintText_Str ; first byte is length
PEEK
ST _pt_tt
INC PrintText_Str
_pt_chr LDW PrintText_Str
PEEK
SUBI 32 ; (char - 32)*5 + 0x0700
STW _pt_Char
LSLW
LSLW
ADDW _pt_Char
STW scratch
LDWI giga_text32
ADDW scratch
STW scratch ; text font slice base address for chars 32-81
LDW _pt_Char
SUBI 50
BLT _pt_draw
LDW scratch
ADDI 0x06
STW scratch ; text font slice base address for chars 82+
_pt_draw LDI 0x05
ST _pt_ii
_pt_slice LDW PrintText_Pos
STW giga_sysArg4 ; xy
LDW scratch ; text font slice base address
LUP 0x00 ; get ROM slice
ST giga_sysArg2
SYS 0xCB ; draw vertical slice, SYS_VDrawBits_134, 270 - 134/2 = 0xCB
INC scratch ; next vertical slice
INC PrintText_Pos ; next x
LoopCounter _pt_ii _pt_slice
INC PrintText_Str ; next char
INC PrintText_Pos ; 1 pixel space between chars
LoopCounter _pt_tt _pt_chr
RET
############################################################################################################
################################## PAGE BREAK ##############################################################
############################################################################################################
InitAudio EQU subroutines4+0x0000
InitAudio2 EQU subroutines4+0x0100
PlayTone EQU subroutines4+0x0200
GameOver EQU subroutines4+0x0300
; ===== InitAudio =============================================================================
InitAudio PUSH
LDWI giga_soundChan1+4
STW scratch
LDI 0
DOKE scratch
LDWI giga_soundChan2+4
STW scratch
LDI 0
DOKE scratch
LDWI giga_soundChan3+4
STW scratch
LDI 0
DOKE scratch
LDWI giga_soundChan4+4
STW scratch
LDI 0
DOKE scratch
CALL InitAudio2
POP
RET
InitAudio2 LDWI giga_soundChan1
STW scratch
LDWI 0x0100 ; 0 "Noise", 1 Triangle, 2 Pulse, 3 Sawtooth
DOKE scratch
LDWI giga_soundChan2
STW scratch
LDWI 0x0200 ; 0 "Noise", 1 Triangle, 2 Pulse, 3 Sawtooth
DOKE scratch
LDWI giga_soundChan3
STW scratch
LDWI 0x0000 ; 0 "Noise", 1 Triangle, 2 Pulse, 3 Sawtooth
DOKE scratch
LDWI giga_soundChan4
STW scratch
LDWI 0x0000 ; 0 "Noise", 1 Triangle, 2 Pulse, 3 Sawtooth
DOKE scratch
RET
; ===== PlayTone =============================================================================
PlayTone LSLW
STW scratch
LDWI giga_notesTable
ADDW scratch
STW scratch
LUP 0x00 ; get ROM midi note low byte
ST _pt_key
LDW scratch
LUP 0x01 ; get ROM midi note high byte
ST _pt_key + 1
LDW _pt_key
DOKE soundChan1
DOKE soundChan2
LDI 0
DOKE soundChan3
DOKE soundChan4
LDI 3
ST giga_soundTimer
RET
; ===== GameOver =============================================================================
GameOver PUSH
LD brokencount
SUBI 14*8
BGE _go_victory
_go_defeat LDWI string_gameover
BRA _go_printtext
_go_victory LDWI string_victory
_go_printtext STW PrintText_Str
LDWI giga_vram + (0x0300+34)
STW PrintText_Pos
CALL PrintText
_go_wait LDI 1
CALL WaitVBlanks
LD giga_buttonState
ANDI buttonA
BNE _go_wait
POP
RET
_startAddress_ EQU entry_point
_callTable_ EQU 0x007E
_singleStepWatch_ EQU giga_frameCount
_cpuUsageAddressA_ EQU subroutines3
_cpuUsageAddressB_ EQU subroutines3+0x10 ; WaitVBlank