; game of life coded by at67, original algorithm by John Conway vram EQU 0x0800 buffer0 EQU 0x08A0 buffer1 EQU 0x08C0 cells0 EQU 0x30 cells1 EQU 0x32 x EQU 0x34 y EQU 0x35 i EQU 0x36 j EQU 0x37 neighbours EQU 0x38 cell EQU 0x39 cbase0 EQU 0x3A cbase1 EQU 0x3C vbase EQU 0x3E pixels EQU 0x40 xy_addr EQU 0x42 x_add_addr EQU 0x44 y_add_addr EQU 0x46 one EQU 0x48 test EQU 0x4A watch EQU 0x4C scratch EQU 0x4E mask EQU 0x50 ones EQU 0x52 gliders EQU 0x54 lut_modify EQU 0x56 _startAddress_ EQU 0x0200 ; entry point for the code, if this is missing defaults to 0x0200 _callTable_ EQU 0x007E ; 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 watch ; the single step debugger watches this variable location to decide when to step, ; choose a variable that is updated often data EQU 0x08A2 ; custom address for constant data space defined with DB and/or DW n_lut EQU 0x0060 n_l_t EQU 0x0300 get_cell EQU 0x0400 LDI 0x00 ; look up table that is used to evaluate neighbour counts ST n_lut ST n_lut+1 ST n_lut+2 ; self modifying code updates this location with previous generation cell ST n_lut+4 ST n_lut+5 ST n_lut+6 ST n_lut+7 ST n_lut+8 LDI 0xFF ST n_lut+3 LDWI vram STW vbase ; vram base address STW pixels ; pixel address LDWI buffer0 STW cbase0 LDWI buffer1 STW cbase1 LDWI 0x1F1F STW mask LDWI 0x0001 STW one LDWI 0x0100 STW ones LDWI lut + 1 ; self modifying address STW lut_modify clear LDI 0x00 ; clear screen and array POKE vbase LDW vbase ADDW one STW vbase LD vbase+1 SUBI 0x80 BLT clear LDWI 0x08A2 STW gliders LDI 0x05 ST i init LDW gliders ; glider STW test LDI 0xFF POKE test LDW ones ADDW test STW test LDI 0xFF POKE test LDW ones ADDW test STW test LDI 0xFF POKE test LD test SUBI 0x01 ST test LDI 0xFF POKE test LDW test SUBW ones STW test LD test SUBI 0x01 ST test LDI 0xFF POKE test LD gliders ADDI 0x04 ST gliders LD i SUBI 0x01 ST i BGT init LDWI 0x354A ; position in screen to render life STW vbase LDI 0x00 ST i ST j CALL n_l_t n_l_t LDI 0x00 ; reset neighbour count ST neighbours LD i ; -1, -1 neighbour SUBI 0x01 ST i LD j SUBI 0x01 ST j ;CALL get_cell LDW i ANDW mask ADDW cbase0 PEEK BEQ n_m_t INC neighbours n_m_t INC i ; 0, -1 neighbour ;CALL get_cell LDW i ANDW mask ADDW cbase0 PEEK BEQ n_r_t INC neighbours n_r_t INC i ; 1, -1 neighbour ;CALL get_cell LDW i ANDW mask ADDW cbase0 PEEK BEQ n_r_m INC neighbours n_r_m INC j ; 1, 0 neighbour ;CALL get_cell LDW i ANDW mask ADDW cbase0 PEEK BEQ n_r_b INC neighbours n_r_b INC j ; 1, 1 neighbour ;CALL get_cell LDW i ANDW mask ADDW cbase0 PEEK BEQ n_m_b INC neighbours n_m_b LD i ; 0, 1 neighbour SUBI 0x01 ST i ;CALL get_cell LDW i ANDW mask ADDW cbase0 PEEK BEQ n_l_b INC neighbours n_l_b LD i ; -1, 1 neighbour SUBI 0x01 ST i ;CALL get_cell LDW i ANDW mask ADDW cbase0 PEEK BEQ n_l_m INC neighbours n_l_m LD j ; -1, 0 neighbour SUBI 0x01 ST j ;CALL get_cell LDW i ANDW mask ADDW cbase0 PEEK BEQ cell00 INC neighbours cell00 INC i ;CALL get_cell00 ; 0, 0 cell LDW i ADDW cbase0 STW cells0 PEEK ST cell ST 0x62 ;CALL set_cells LDW i ADDW cbase1 STW cells1 LD neighbours ADDI 0x60 POKE lut_modify ; lut_modify points to operand in "LD n_lut" lut LD 0x60 ; self modifying code ;check_3 LD neighbours ; SUBI 0x03 ; BNE check_<2 ; LDI 0xFF ; birth ; BRA draw ;check_<2 LD neighbours ; SUBI 0x02 ; BGE check_>3 ; LDI 0x00 ; death ; BRA draw ;check_>3 LD neighbours ; SUBI 0x03 ; BLE old_cell ; LDI 0x00 ; death ; BRA draw ;old_cell LD cell draw POKE cells1 ST cell ;CALL draw_1x1 ;CALL draw_2x2 LDW i ADDW vbase STW pixels LD cell POKE pixels LD i ; inc i ADDI 0x01 ANDI 0x1F ST i BNE n_l_t LD j ; inc j ADDI 0x01 ANDI 0x1F ST j BNE n_l_t LDW cbase0 ; toggle buffers between 0x08A0 and 0x08C0 STW test LDW cbase1 STW cbase0 LDW test STW cbase1 BRA n_l_t get_cell LDW i ;LD i ;ANDI 0x1F ;ST xy_addr ;LD j ;ANDI 0x1F ;ST xy_addr+1 ;LDW xy_addr ;ADDW cbase0 ;STW cells0 ;PEEK ANDW mask ADDW cbase0 STW cells0 PEEK RET get_cell00 LD i ST xy_addr LD j ST xy_addr+1 LDW xy_addr ADDW cbase0 STW cells0 RET set_cells LD i ST xy_addr LD j ST xy_addr+1 LDW xy_addr ADDW cbase1 STW cells1 RET draw_1x1 LD i ST xy_addr LD j ST xy_addr+1 LDW xy_addr ADDW vbase STW pixels LD cell POKE pixels RET draw_2x2 LD i LSLW ST xy_addr LD j LSLW ST xy_addr+1 LDW xy_addr ADDW vbase STW pixels STW scratch LD cell POKE pixels INC pixels POKE pixels LDW scratch STW pixels INC pixels+1 LD cell POKE pixels INC pixels POKE pixels RET ; an example of how to define your own data data DB 0xFF 0xFF 0xFF