406 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			406 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
; **************************************************************************************************
 | 
						|
; **************************************************************************************************
 | 
						|
;  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!
 | 
						|
; **************************************************************************************************
 | 
						|
; **************************************************************************************************
 | 
						|
 | 
						|
; game of life coded by at67, original algorithm by John Conway
 | 
						|
; 32X32 runs about 2 fps on a 6.25MHz Gigatron TTL
 | 
						|
; more optimisation: neighbour count buffer is generated from alive cells in cell buffer, pointer arithmetic with offsets,
 | 
						|
; a look up table to evalute neighbours count and a SYS function to plot the 2x2 pixels.
 | 
						|
; this world has boundaries
 | 
						|
 | 
						|
 | 
						|
vram        EQU     0x0800
 | 
						|
buff0       EQU     0x09A0
 | 
						|
buff1       EQU     0x09D0
 | 
						|
 | 
						|
sysFn       EQU     0x22
 | 
						|
 | 
						|
cells0      EQU     0x30
 | 
						|
cells1      EQU     0x32
 | 
						|
i           EQU     0x34
 | 
						|
j           EQU     0x35
 | 
						|
neighbours  EQU     0x36
 | 
						|
cell        EQU     0x37
 | 
						|
n_address   EQU     0x38
 | 
						|
buffer0     EQU     0x3A
 | 
						|
buffer1     EQU     0x3C
 | 
						|
generation  EQU     0x3E
 | 
						|
vbase       EQU     0x40
 | 
						|
pixels      EQU     0x42
 | 
						|
pattern     EQU     0x44
 | 
						|
gliders     EQU     0x46
 | 
						|
lut_modify  EQU     0x48
 | 
						|
j_one       EQU     0x4A
 | 
						|
offset0     EQU     0x4C
 | 
						|
offset1     EQU     0x4E
 | 
						|
offset2     EQU     0x50
 | 
						|
offset3     EQU     0x52
 | 
						|
offset4     EQU     0x54
 | 
						|
offset5     EQU     0x56
 | 
						|
offset6     EQU     0x58
 | 
						|
offset7     EQU     0x5A
 | 
						|
scratch     EQU     0x5C
 | 
						|
 | 
						|
screen_w    EQU     160
 | 
						|
screen_h    EQU     120
 | 
						|
bounds      EQU     46      ; determines max size of world, limited by available ram in blank scanlines,
 | 
						|
                            ; using bytes per cell, 1 pixel world boundary and two buffers means 46*46 is maximum size
 | 
						|
 | 
						|
                                        
 | 
						|
_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     neighbours  ; the single step debugger watches this variable location to decide when to step,
 | 
						|
                                        ; choose a variable that is updated often
 | 
						|
 | 
						|
SYS_DrawPixel2x2_32 EQU     0x2300      ; 2x2 pixel plot, native code that is defined with either DBR or DWR is written to ROM at this address
 | 
						|
 | 
						|
SYS_ClearRow32_56   EQU     0x2400      ; clear 32 pixels at a time, native code that is defined with either DBR or DWR is written to ROM at this address
 | 
						|
 | 
						|
                                        
 | 
						|
n_lut       EQU     0x60
 | 
						|
n_lut_cell  EQU     0x62
 | 
						|
 | 
						|
counts      EQU     0x0300
 | 
						|
 | 
						|
 | 
						|
            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    buff0
 | 
						|
            STW     buffer0
 | 
						|
            LDWI    buff1
 | 
						|
            STW     buffer1
 | 
						|
            
 | 
						|
            LDWI    lut + 1     ; self modifying address
 | 
						|
            STW     lut_modify
 | 
						|
            LDWI    0x0100
 | 
						|
            STW     j_one
 | 
						|
            
 | 
						|
;clear       LDI     0x00        ; clear screen and buffers
 | 
						|
;            POKE    vbase
 | 
						|
;            LDWI    0x0001
 | 
						|
;            ADDW    vbase
 | 
						|
;            STW     vbase
 | 
						|
;            LD      vbase+1
 | 
						|
;            SUBI    0x80
 | 
						|
;            BLT     clear
 | 
						|
 | 
						|
            
 | 
						|
            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    0x09A3
 | 
						|
            STW     gliders
 | 
						|
 | 
						|
            LDI     0x06        ; number of gliders
 | 
						|
            ST      i
 | 
						|
 | 
						|
glider      LDW     gliders     
 | 
						|
            STW     pattern
 | 
						|
            LDI     0xFF        
 | 
						|
            POKE    pattern
 | 
						|
            LDW     j_one
 | 
						|
            ADDW    pattern
 | 
						|
            STW     pattern
 | 
						|
            LDI     0xFF
 | 
						|
            POKE    pattern
 | 
						|
            LDW     j_one
 | 
						|
            ADDW    pattern
 | 
						|
            STW     pattern
 | 
						|
            LDI     0xFF
 | 
						|
            POKE    pattern
 | 
						|
            LD      pattern
 | 
						|
            SUBI    0x01
 | 
						|
            ST      pattern
 | 
						|
            LDI     0xFF
 | 
						|
            POKE    pattern
 | 
						|
            LDW     pattern
 | 
						|
            SUBW    j_one
 | 
						|
            STW     pattern
 | 
						|
            LD      pattern
 | 
						|
            SUBI    0x01
 | 
						|
            ST      pattern
 | 
						|
            LDI     0xFF
 | 
						|
            POKE    pattern
 | 
						|
            
 | 
						|
            LD      gliders     ; gap between gliders
 | 
						|
            ADDI    0x05
 | 
						|
            ST      gliders
 | 
						|
            
 | 
						|
            LD      i
 | 
						|
            SUBI    0x01
 | 
						|
            ST      i
 | 
						|
            BGT     glider
 | 
						|
                        
 | 
						|
            LDWI    0x0001
 | 
						|
            STW     j_one
 | 
						|
            STW     generation
 | 
						|
 | 
						|
            LDI     (screen_w - bounds*2)/0b10          ; position in screen to render life
 | 
						|
            ST      vbase
 | 
						|
            LDI     (screen_h - bounds*0q2)/0x0002 + 8  ; expressions can use equates and use the same number handling as equates
 | 
						|
            ST      vbase+1
 | 
						|
            
 | 
						|
            LDI     bounds
 | 
						|
            ST      i
 | 
						|
            ST      j
 | 
						|
 | 
						|
            LDWI    0x0101      ; -ve
 | 
						|
            STW     offset0
 | 
						|
            LDWI    0x0100      ; -ve
 | 
						|
            STW     offset1
 | 
						|
            LDWI    0x00FF      ; -ve
 | 
						|
            STW     offset2
 | 
						|
            LDWI    0x0001      ; +ve
 | 
						|
            STW     offset3
 | 
						|
            LDWI    0x0101      ; +ve
 | 
						|
            STW     offset4
 | 
						|
            LDWI    0x0100      ; +ve
 | 
						|
            STW     offset5
 | 
						|
            LDWI    0x00FF      ; +ve
 | 
						|
            STW     offset6
 | 
						|
            LDWI    0x0001      ; -ve
 | 
						|
            STW     offset7
 | 
						|
            
 | 
						|
            LDWI    SYS_DrawPixel2x2_32
 | 
						|
            STW     sysFn
 | 
						|
 | 
						|
            CALL    counts      ; jump across a page boundary
 | 
						|
            
 | 
						|
 | 
						|
; counts buffer            
 | 
						|
counts      LDW     i           ; buffer0
 | 
						|
            ADDW    buffer0
 | 
						|
            PEEK                ; get buffer0 cell
 | 
						|
            BEQ     continue
 | 
						|
 | 
						|
            LDW     i           ; buffer1
 | 
						|
            ADDW    buffer1
 | 
						|
            STW     cells1
 | 
						|
            
 | 
						|
            SUBW    offset0     ; -1, -1 neighbour
 | 
						|
            STW     n_address
 | 
						|
            PEEK
 | 
						|
            ADDI    0x01
 | 
						|
            POKE    n_address
 | 
						|
            
 | 
						|
            LDW     cells1      
 | 
						|
            SUBW    offset1     ; 0, -1 neighbour
 | 
						|
            STW     n_address
 | 
						|
            PEEK
 | 
						|
            ADDI    0x01
 | 
						|
            POKE    n_address
 | 
						|
 | 
						|
            LDW     cells1      
 | 
						|
            SUBW    offset2     ; 1, -1 neighbour
 | 
						|
            STW     n_address
 | 
						|
            PEEK
 | 
						|
            ADDI    0x01
 | 
						|
            POKE    n_address
 | 
						|
 | 
						|
            LDW     cells1      
 | 
						|
            ADDW    offset3     ; 1, 0 neighbour
 | 
						|
            STW     n_address
 | 
						|
            PEEK
 | 
						|
            ADDI    0x01
 | 
						|
            POKE    n_address
 | 
						|
            
 | 
						|
            LDW     cells1      
 | 
						|
            ADDW    offset4     ; 1, 1 neighbour
 | 
						|
            STW     n_address
 | 
						|
            PEEK
 | 
						|
            ADDI    0x01
 | 
						|
            POKE    n_address
 | 
						|
            
 | 
						|
            LDW     cells1      
 | 
						|
            ADDW    offset5     ; 0, 1 neighbour
 | 
						|
            STW     n_address
 | 
						|
            PEEK
 | 
						|
            ADDI    0x01
 | 
						|
            POKE    n_address
 | 
						|
            
 | 
						|
            LDW     cells1      
 | 
						|
            ADDW    offset6     ; -1, 1 neighbour
 | 
						|
            STW     n_address
 | 
						|
            PEEK
 | 
						|
            ADDI    0x01
 | 
						|
            POKE    n_address
 | 
						|
            
 | 
						|
            LDW     cells1      
 | 
						|
            SUBW    offset7     ; -1, 0 neighbour
 | 
						|
            STW     n_address
 | 
						|
            PEEK
 | 
						|
            ADDI    0x01
 | 
						|
            POKE    n_address
 | 
						|
 | 
						|
continue    LD      i           ; dec i
 | 
						|
            SUBI    0x01
 | 
						|
            ST      i
 | 
						|
            BGE     counts
 | 
						|
            LDI     bounds
 | 
						|
            ST      i
 | 
						|
 | 
						|
            LD      j           ; dec j
 | 
						|
            SUBI    0x01
 | 
						|
            ST      j
 | 
						|
            BGE     counts
 | 
						|
            LDI     bounds
 | 
						|
            ST      j
 | 
						|
       
 | 
						|
 | 
						|
generate    LDW     i           ; buffer1
 | 
						|
            ADDW    buffer1
 | 
						|
            STW     cells1
 | 
						|
            PEEK
 | 
						|
            ST      neighbours  ; get neighbours count
 | 
						|
            LDI     0x00
 | 
						|
            POKE    cells1      ; reset neighbours count
 | 
						|
            
 | 
						|
            LDW     i           ; buffer0
 | 
						|
            ADDW    buffer0
 | 
						|
            STW     cells0
 | 
						|
            PEEK                ; get cell
 | 
						|
            ST      n_lut_cell  ; save cell into neighbours lut
 | 
						|
 | 
						|
            LD      neighbours  ; lut evaluates neighbours count
 | 
						|
            ADDI    n_lut
 | 
						|
            POKE    lut_modify  ; lut_modify points to operand in "LD n_lut"
 | 
						|
lut         LD      n_lut       ; get new cell using self modifying code
 | 
						|
 | 
						|
            POKE    cells0      ; save new cell
 | 
						|
            ST      cell            
 | 
						|
            
 | 
						|
            LDW     i           ; draw cell 2x2
 | 
						|
            LSLW
 | 
						|
            ADDW    vbase
 | 
						|
            STW     pixels
 | 
						|
        
 | 
						|
            SYS     32
 | 
						|
           
 | 
						|
                       
 | 
						|
            LD      i           ; dec i
 | 
						|
            SUBI    0x01
 | 
						|
            ST      i
 | 
						|
            BGE     generate
 | 
						|
            LDI     bounds
 | 
						|
            ST      i
 | 
						|
 | 
						|
            LD      j           ; dec j
 | 
						|
            SUBI    0x01
 | 
						|
            ST      j
 | 
						|
            BGE     generate
 | 
						|
            LDI     bounds
 | 
						|
            ST      j
 | 
						|
            
 | 
						|
            LDW     generation
 | 
						|
            ADDW    j_one
 | 
						|
            STW     generation
 | 
						|
            
 | 
						|
            BRA     counts 
 | 
						|
            
 | 
						|
 | 
						|
; these are native code routines that are written into ROM using the DBR command, (Define Byte ROM), at the equate defined
 | 
						|
; above: this native code is specific to this vCPU asm module with the input registers that it accepts
 | 
						|
;SYS_ClearRow32_56       DBR $11 $40 $15 $41 $00 $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00
 | 
						|
;                        DBR $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00
 | 
						|
;                        DBR $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00
 | 
						|
;                        DBR $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $DE $00 $14 $03 $E0 $CB $00 $E4
 | 
						|
;SYS_DrawPixel2x2_32     DBR $01 $37 $11 $42 $15 $43 $DE $00 $CE $00 $11 $42 $00 $01 $95 $43 $01 $37 $DE $00 $CE $00 $14 $03 $E0 $CB $00 $F0
 | 
						|
 | 
						|
SYS_DrawPixel2x2_32     .LD     [0x37]
 | 
						|
                        .LD     [0x42],X
 | 
						|
                        .LD     [0x43],Y
 | 
						|
                        .ST     [Y,X++]
 | 
						|
                        .ST     [Y,X]
 | 
						|
                        .LD     [0x42],X
 | 
						|
                        .LD     0x01
 | 
						|
                        .ADDA   [0x43],Y
 | 
						|
                        .LD     [0x37]
 | 
						|
                        .ST     [Y,X++]
 | 
						|
                        .ST     [Y,X]
 | 
						|
                        .NOP                ; pad instructions so odd(14 + number of instructions) = true
 | 
						|
                        .LD     0x03,Y
 | 
						|
                        .JMP    Y,0xCB
 | 
						|
                        .LD     0xF0        ; 0 - ((14 + number of instructions + 3) / 2), odd(14 + number of instructions) = true
 | 
						|
                        
 | 
						|
SYS_ClearRow32_56       .LD     [0x40],X
 | 
						|
                        .LD     [0x41],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     0x03,Y
 | 
						|
                        .JMP    Y,0xCB
 | 
						|
                        .LD     0xE4        ; 0 - ((14 + number of instructions + 3) / 2), odd(14 + number of instructions) = true
 | 
						|
                         |