; ************************************************************************************************** ; ************************************************************************************************** ; THIS WILL NOT RUN ON REAL HARDWARE UNLESS YOU BURN THE NATIVE CODE AT THE BOTTOM ; OF THIS FILE INTO THE GIGATRONS ROM AT THE CORRECT ADDRESS, EMULATION ONLY! ; ************************************************************************************************** ; ************************************************************************************************** ; sprite test vram EQU 0x0800 hscroll EQU 0x0101 REENTER EQU 0x03CB rand EQU 0x06 videoY EQU 0x09 frameCount EQU 0x0E sysFn EQU 0x22 dstAddr EQU 0x30 vbase EQU 0x32 pixels EQU 0x34 frame EQU 0x36 xyPos EQU 0x38 xyPosHi EQU 0x3A xyVel EQU 0x3C xyVelHi EQU 0x3E i EQU 0x40 j EQU 0x42 k EQU 0x44 delay EQU 0x46 one EQU 0x48 mask1 EQU 0x4A mask2 EQU 0x4C scratch EQU 0x4E pixelsArray EQU 0x60 xyPosArray EQU 0x82 xyVelArray EQU 0xA2 sysFnArray EQU 0xC2 hscrollAddr EQU 0xE2 xExtent EQU 0x96 yExtent EQU 0x6e numSprites EQU 16 _startAddress_ EQU 0x0200 ; entry point for the code, if this is missing defaults to 0x0200 _callTable_ EQU 0x005E ; 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 k ; the single step debugger watches this variable location to decide when to step, ; choose a variable that is updated often SYS_BlinkyBlast_142 EQU 0x2300 ; 10x10 pixel blast, sprite data is embedded in instructions SYS_ClearRow32_56 EQU 0x2400 ; clear 32 pixels at a time start EQU 0x200 loopinit EQU 0x300 vblank0 EQU 0x400 ; vram base address start LDWI vram STW vbase ; horizontal scroll address LDWI hscroll STW hscrollAddr LDWI xyPosArray STW xyPos LDWI xyPosArray + 1 STW xyPosHi LDWI xyVelArray STW xyVel LDWI xyVelArray + 1 STW xyVelHi LDWI pixelsArray STW pixels ; clear screen, (including hidden areas), fast LDWI SYS_ClearRow32_56 ; clears 32 row pixels at a time STW sysFn clear SYS 56 LDWI 0x0020 ADDW vbase STW vbase LD vbase+1 SUBI 0x7F BLT clear LDI 0x08 ; finish off last row ST i last_row SYS 56 LDWI 0x0020 ADDW vbase STW vbase LD i SUBI 0x01 ST i BGT last_row LDWI SYS_BlinkyBlast_142 STW sysFn LDWI vram STW vbase ; constants constants LDWI 0x3F7F STW mask1 LDWI 0x0707 STW mask2 LDI 0x00 ST i LDWI 0x0001 STW one LDWI 192 STW delay ; vblank counter LD frameCount STW frame ; random positions init LD rand ANDI 0x03 BEQ case0 SUBI 0x01 BEQ case1 SUBI 0x01 BEQ case2 SUBI 0x01 BEQ case3 case0 LDWI 0x0101 DOKE xyVel BRA randpos case1 LDWI 0x01FF DOKE xyVel BRA randpos case2 LDWI 0xFF01 DOKE xyVel BRA randpos case3 LDWI 0xFFFF DOKE xyVel ; generate vram address randpos LDW rand ANDW mask1 ORW mask2 DOKE xyPos ADDW vbase DOKE pixels INC xyPos INC xyPos INC xyVel INC xyVel INC pixels INC pixels CALL vblank0 INC i LD i SUBI numSprites BLT init CALL loopinit ; main loop loopinit LDWI xyPosArray STW xyPos LDWI xyPosArray + 1 STW xyPosHi LDWI xyVelArray STW xyVel LDWI xyVelArray + 1 STW xyVelHi LDWI pixelsArray STW pixels LDI 0x00 ST i ; x position bounds checking xbounds LDW xyPos PEEK BEQ xflip SUBI xExtent BLT ybounds ; flip x velocity xflip LDW xyVel PEEK XORI 0xFE POKE xyVel ; y position bounds checking ybounds LDW xyPosHi PEEK BEQ yflip SUBI yExtent BLT velocity ; flip y velocity yflip LDW xyVelHi PEEK XORI 0xFE POKE xyVelHi ; xpos += xvel velocity LDW xyPos PEEK ST scratch LDW xyVel PEEK ADDW scratch POKE xyPos ; ypos += yvel LDW xyPosHi PEEK ST scratch LDW xyVelHi PEEK ADDW scratch POKE xyPosHi ; generate vram address LDW xyPos DEEK ADDW vbase DOKE pixels ; increment array pointers INC xyPos INC xyPos INC xyPosHi INC xyPosHi INC xyVel INC xyVel INC xyVelHi INC xyVelHi INC pixels INC pixels ; do it for numSprites INC i LD i SUBI numSprites BLT xbounds LDWI pixelsArray STW pixels LDI 0x00 ST k ; scroll playfield LD frameCount POKE hscrollAddr ; draw sprite draw LDW pixels DEEK STW dstAddr SYS 142 INC pixels INC pixels INC k LD k SUBI numSprites BLT draw CALL vblank1 BRA loopinit ; subroutines vblank0 LD frameCount SUBW frame BEQ vblank0 LD frameCount STW frame RET vblank1 LD videoY ANDI 0x01 BEQ vblank1 RET vblank2 LD 0x0000 STW i loopdelay LDW i ADDW one STW i SUBW delay BLT loopdelay RET ; native code routines that are written into the emulator's fake ROM using either the DBR/DWR commands or the native instruction set ; the native instruction assembler has access to the same functionality as the vasm assembler, (labels, equates, mutables, etc). ; it's only caveats are: ; 1: each instruction is prefaced with a period to clearly differentiate it from a vasm instruction ; 2: you cannot mix and match vasm instructions with native instructions within the same segment, (in reality they are executed in ; completely different parts of the memory map, i.e. native in fake ROM and vasm in RAM) ; 3: you must follow the SYS calling conventions exactly ; accumulator holds [dstAddr + 1] for entire sprite blast SYS_BlinkyBlast_142 .LD [dstAddr],X ; dst line 0 .LD [dstAddr + 1] .ADDA $00,Y .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 1 .ADDA $01,Y .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 2 .ADDA $02,Y .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 3 .ADDA $03,Y .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $FF,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $FF,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 4 .ADDA $04,Y .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $FF,[Y,X++] .ST $30,[Y,X++] .ST $FF,[Y,X++] .ST $FF,[Y,X++] .ST $30,[Y,X++] .ST $FF,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 5 .ADDA $05,Y .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $FF,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $FF,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 6 .ADDA $06,Y .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 7 .ADDA $07,Y .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 8 .ADDA $08,Y .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .ST $03,[Y,X++] .ST $00,[Y,X++] .LD [dstAddr],X ; dst line 9 .ADDA $09,Y .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .ST $00,[Y,X++] .NOP ; pad instructions so odd(14 + number of instructions) = true .LD REENTER >>8,y .JMP y,REENTER .LD 0xB9 ; 0 - ((14 + number of instructions + 3) / 2), odd(14 + number of instructions) = true SYS_ClearRow32_56 .LD [vbase],X .LD [vbase+1],Y .LD 0x00 .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .ST [Y,X++] .NOP ; pad instructions so odd(14 + number of instructions) = true .LD REENTER >>8,y .JMP y,REENTER .LD 0xE4 ; 0 - ((14 + number of instructions + 3) / 2), odd(14 + number of instructions) = true