.export init .feature c_comments numL := $02 ; low byte of a 16-bit number numH := $03 ; low byte of a 16-bit number num2L := $04 num2H := $05 GETIN := $ffe4 CHROUT := $ffd2 CLRCHN := $e544 DEAD := $20 ALIVE := $a0 ; one byte for each cell, 1000 bytes because 40x25 screen; is identical to ; screen memory (i.e. $a0 is alive and $20 is dead) ; initialisation: clear screen and set num $00 init: ; clear screen lda #$93 jsr CHROUT ldy #$00 lda #$00 sta numH sta numL jsr CLRCHN jmp loop ; main loop ; num stores offset from grid loop: jsr GETIN beq loop cmp #$1d ; right arrow beq if_right cmp #$9d ; left arrow beq if_left cmp #$91 ; up arrow beq if_up cmp #$11 ; down arrow beq if_down cmp #$2d ; reset if - pressed beq if_reset cmp #$20 ; fill cell if space pressed beq if_space cmp #$0d ; stop handling input and start life if return pressed beq if_return cmp #$30 ; end program if 0 pressed bne loop jmp end if_right: jsr inc_num jmp loop if_left: jsr dec_num jmp loop if_up: lda #40 jsr s16b jmp loop if_down: lda #40 jsr a16b jmp loop if_reset: lda #$93 jsr CHROUT jmp loop if_space: lda numL sta num2L lda numH clc adc #$04 sta num2H ldy #$00 lda (num2L),y cmp #ALIVE beq if_cell_filled jmp if_cell_empty if_cell_filled: lda #DEAD jsr print_byte jmp loop if_cell_empty: lda #ALIVE jsr print_byte jmp loop ; num is screen_mem; num2 is generation buffer, X is number of neighbours if_return: ;jsr sleep jsr copy_to_prev lda #$00 sta numL lda #$04 sta numH lda #$00 sta num2L lda #$c0 sta num2H ; as per wikipedia, i'll just count the number of alive neighbours and the ; cell itself, if the sum is 3 then it will be alive, if 4 then it'll retain ; its state, otherwise it dies. X is number of neighbours life_loop: ldx #$00 lda #41 ; cell to top left of current is row above minus 1 jsr s16b2 jsr cmp_row lda #40 ; go back to cell left of current jsr a16b2 jsr cmp_row lda #40 ; go to cell below cell left of current jsr a16b2 jsr cmp_row ldy #$00 cpx #$03 beq if_to_live cpx #$04 bne if_to_die jmp if_retains if_to_live: lda #ALIVE sta (numL),y jmp if_retains if_to_die: lda #DEAD sta (numL),y if_retains: lda #38 ; go to right of current; restores num2 to original and increments jsr s16b2 jsr inc_num lda numH cmp #$07 bne life_loop lda numL cmp #$e9 bne life_loop jmp if_return ; print byte in A at location in screen_mem+num; destroys Y; num2 is expected ; to be $0400 (screen_mem zero location) and is set to that at the end print_byte: tay lda numH pha clc adc #$04 sta numH tya ldy #$00 sta (numL),y pla sta numH rts ; adds A to num a16b: clc adc numL sta numL lda #$00 adc numH sta numH rts ; adds A to num2 a16b2: clc adc num2L sta num2L lda #$00 adc num2H sta num2H rts ; subtracts A from num s16b: pha txa pha lda numL tsx inx inx sec sbc $0100,x sta numL lda numH sbc #$00 sta numH pla tax pla rts ; might change functions to take from stack but this is easier for now as I ; only have 2 16 bit numbers to deal with anyways ; subtracts A from num2 s16b2: pha txa pha lda num2L tsx inx inx sec sbc $0100,x sta num2L lda num2H sbc #$00 sta num2H pla tax pla rts inc_num: inc numL beq inc_H rts inc_H: inc numH rts inc_num2: inc num2L beq inc_H2 rts inc_H2: inc num2H rts dec_num: pha dec numL lda numL cmp #$ff beq dec_H pla rts dec_H: dec numH pla rts ; num stores address in screen_mem; num2 stores address in generation buffer ; destroys A and Y copy_to_prev: lda #$00 sta numL lda #$04 sta numH lda #$00 sta num2L lda #$c0 sta num2H ldy #$00 copy_to_prev_loop: lda (numL),y sta (num2L),y ; might inline them instead of having subroutines for more speed, will see ; if it makes difference if i have time jsr inc_num jsr inc_num2 lda numH cmp #$07 bne copy_to_prev_loop lda numL cmp #$e9 ; e9 instead of e8 because last position is 07e8 but number is ; increased before copying so it will be e8 before the number at e8 is copied bne copy_to_prev_loop rts ; compare three numbers in a row in num2 with ALIVE and DEAD, increase X ; accordingly cmp_row: ldy #$00 cmp_row_loop: ; y will be between 0-2 to take into account row lda (num2L),y cmp #ALIVE beq if_alive jmp else_alive if_alive: inx else_alive: iny cpy #$03 bne cmp_row_loop rts sleep: pha lda #$00 ldx #$00 ldy #$00 sleep_y_loop: iny jmp sleep_loop sleep_x_loop: inx sleep_loop: adc #$01 cmp #$ff bne sleep_loop cpx #$ff bne sleep_x_loop ;cpy #$ff ;bne sleep_y_loop pla rts end: brk