; ************************************************************************************************** ; ************************************************************************************************** ; 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 %include ../include/gigatron.i vram EQU 0x0800 buff0 EQU 0x08B0 buff1 EQU 0x08D0 REENTER EQU 0x03CB rand EQU 0x06 videoY EQU 0x09 frameCount EQU 0x0E sysFn EQU 0x22 srcAddr EQU 0x30 dstAddr EQU 0x32 backBuffer EQU 0x34 spriteData EQU 0x36 vbase EQU 0x38 pixels EQU 0x3A frame EQU 0x3C xyPos EQU 0x3E xyPosHi EQU 0x40 xyVel EQU 0x42 xyVelHi EQU 0x44 colour EQU 0x46 i EQU 0x48 j EQU 0x4A k EQU 0x4C delay EQU 0x4E one EQU 0x50 mask1 EQU 0x52 mask2 EQU 0x54 scratch EQU 0x56 rowBuffer0 EQU 0x70 rowBuffer1 EQU 0x74 rowBuffer2 EQU 0x78 rowBuffer3 EQU 0x7C pixelsArray EQU 0x90 xyPosArray EQU 0xB0 xyVelArray EQU 0xD0 xExtent EQU 0x9C yExtent EQU 0x74 numSprites EQU 4 _startAddress_ EQU 0x0200 ; entry point for the code, if this is missing defaults to 0x0200 _callTable_ EQU 0x008E ; 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_SpriteCopy_118 EQU 0x2300 ; 16 pixel memory copy start EQU 0x200 loopinit EQU 0x300 vblank0 EQU 0x400 fillSprites EQU 0x500 start LDWI vram STW vbase ; vram base address LDWI buff0 STW spriteData LDWI buff1 STW backBuffer LDWI xyPosArray STW xyPos LDWI xyPosArray + 1 STW xyPosHi LDWI xyVelArray STW xyVel LDWI xyVelArray + 1 STW xyVelHi LDWI pixelsArray STW pixels LDWI SYS_SpriteCopy_118 STW sysFn ; fill sprite data CALL fillSprites ; doesn't return, does a far jump to constants ; 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 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 randpos LDW rand ANDW mask1 ORW mask2 DOKE xyPos ADDW vbase ; generate vram address 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 LDWI buff0 STW spriteData LDWI buff1 STW backBuffer LDI 0x00 ST i xbounds LDW xyPos ; x position bounds checking PEEK BEQ xflip SUBI xExtent BLT ybounds xflip LDW xyVel PEEK XORI 0xFE ; flip x velocity POKE xyVel ybounds LDW xyPosHi ; y position bounds checking PEEK BEQ yflip SUBI yExtent BLT velocity yflip LDW xyVelHi PEEK XORI 0xFE ; flip y velocity POKE xyVelHi velocity LDW xyPos ; xpos += xvel PEEK ST scratch LDW xyVel PEEK ADDW scratch POKE xyPos LDW xyPosHi ; ypos += yvel PEEK ST scratch LDW xyVelHi PEEK ADDW scratch POKE xyPosHi LDW xyPos DEEK ADDW vbase ; generate vram address DOKE pixels save STW srcAddr LDW backBuffer STW dstAddr SYS 118 INC xyPos ; increment array pointers INC xyPos INC xyPosHi INC xyPosHi INC xyVel INC xyVel INC xyVelHi INC xyVelHi INC pixels INC pixels LD backBuffer + 1 ADDI 0x04 ST backBuffer + 1 INC i LD i SUBI numSprites BLT xbounds LDWI pixelsArray STW pixels LDI 0x00 ST k draw LDW pixels DEEK STW dstAddr LDW spriteData STW srcAddr SYS 118 INC pixels INC pixels LD spriteData + 1 ADDI 0x04 ST spriteData + 1 INC k LD k SUBI numSprites BLT draw ;CALL vblank0 ;CALL vblank1 CALL vblank2 LDWI buff1 STW backBuffer LDWI pixelsArray STW pixels LDI 0x00 ST i restore LDW backBuffer STW srcAddr LDW pixels DEEK STW dstAddr SYS 118 INC pixels INC pixels LD backBuffer + 1 ADDI 0x04 ST backBuffer + 1 INC i LD i SUBI numSprites BLT restore 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 waitScanln LD videoY STW scratch ADDW videoY STW scratch LDW xyPosHi ; ypos PEEK SUBW scratch BGT waitScanln RET fillsprite LDI 0x00 ST j fill_i LDI 0x00 ST i fill_c LD i LD colour POKE spriteData INC spriteData INC i LD i SUBI 0x04 BLT fill_c LDI buff0 ST spriteData LD spriteData + 1 ADDI 0x01 ST spriteData + 1 INC j LD j SUBI 0x04 BLT fill_i RET fillSprites LDI 0x1F ST colour LDWI 0x08B0 STW spriteData CALL fillsprite LDI 0x30 ST colour LDWI 0x0CB0 STW spriteData CALL fillsprite LDI 0x0C ST colour LDWI 0x10B0 STW spriteData CALL fillsprite LDI 0x03 ST colour LDWI 0x14B0 STW spriteData CALL fillsprite LDI 0x0F ST colour LDWI 0x18B0 STW spriteData CALL fillsprite LDI 0x3C ST colour LDWI 0x1CB0 STW spriteData CALL fillsprite LDI 0x33 ST colour LDWI 0x20B0 STW spriteData CALL fillsprite LDI 0x1A ST colour LDWI 0x24B0 STW spriteData CALL fillsprite LDI 0x5F ST colour LDWI 0x28B0 STW spriteData CALL fillsprite LDI 0x63 ST colour LDWI 0x2CB0 STW spriteData CALL fillsprite LDI 0x7A ST colour LDWI 0x30B0 STW spriteData CALL fillsprite LDI 0x07 ST colour LDWI 0x34B0 STW spriteData CALL fillsprite LDI 0x00 ST colour LDWI 0x38B0 STW spriteData CALL fillsprite LDI 0x25 ST colour LDWI 0x3CB0 STW spriteData CALL fillsprite LDI 0x52 ST colour LDWI 0x40B0 STW spriteData CALL fillsprite LDI 0x36 ST colour LDWI 0x44B0 STW spriteData CALL fillsprite CALL constants ; 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 SYS_SpriteCopy_118 .LD [srcAddr],X ; src line 0 .LD [srcAddr + 1],Y .LD [Y,X] .ST [rowBuffer0 + 0] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer0 + 1] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer0 + 2] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer0 + 3] .LD [srcAddr],X ; src line1 .LD 0x01 .ADDA [srcAddr + 1],Y .LD [Y,X] .ST [rowBuffer1 + 0] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer1 + 1] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer1 + 2] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer1 + 3] .LD [srcAddr],X ; src line2 .LD 0x02 .ADDA [srcAddr + 1],Y .LD [Y,X] .ST [rowBuffer2 + 0] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer2 + 1] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer2 + 2] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer2 + 3] .LD [srcAddr],X ; src line3 .LD 0x03 .ADDA [srcAddr + 1],Y .LD [Y,X] .ST [rowBuffer3 + 0] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer3 + 1] .ST [Y,X++] ; hack increment .LD [Y,X] .ST [rowBuffer3 + 2] .ST [Y,X++] ; hack increment .LD [Y,X] ;.LD [Y,X++] .ST [rowBuffer3 + 3] .LD [dstAddr],X ; dst line 0 .LD [dstAddr + 1],Y .LD [rowBuffer0 + 0] .ST [Y,X++] .LD [rowBuffer0 + 1] .ST [Y,X++] .LD [rowBuffer0 + 2] .ST [Y,X++] .LD [rowBuffer0 + 3] .ST [Y,X++] .LD [dstAddr],X ; dst line 1 .LD 0x01 .ADDA [dstAddr + 1],Y .LD [rowBuffer1 + 0] .ST [Y,X++] .LD [rowBuffer1 + 1] .ST [Y,X++] .LD [rowBuffer1 + 2] .ST [Y,X++] .LD [rowBuffer1 + 3] .ST [Y,X++] .LD [dstAddr],X ; dst line 2 .LD 0x02 .ADDA [dstAddr + 1],Y .LD [rowBuffer2 + 0] .ST [Y,X++] .LD [rowBuffer2 + 1] .ST [Y,X++] .LD [rowBuffer2 + 2] .ST [Y,X++] .LD [rowBuffer2 + 3] .ST [Y,X++] .LD [dstAddr],X ; dst line 3 .LD 0x03 .ADDA [dstAddr + 1],Y .LD [rowBuffer3 + 0] .ST [Y,X++] .LD [rowBuffer3 + 1] .ST [Y,X++] .LD [rowBuffer3 + 2] .ST [Y,X++] .LD [rowBuffer3 + 3] .ST [Y,X++] .LD REENTER >>8,y .JMP y,REENTER .LD 0xC5 ; 0 - ((14 + number of instructions + 3) / 2), odd(14 + number of instructions) = true