diff --git a/demos/life-src/life-src.lm b/demos/life-src/life-src.lm index 209a8eb..ce4e712 100644 --- a/demos/life-src/life-src.lm +++ b/demos/life-src/life-src.lm @@ -2,11 +2,9 @@ ; UNKNOWN AUTHOR ; DISASSEMBLED BY ANTONINO PORCINO, 14TH SEP 2022 -ECHO = $FFEF ; character echo routine in woz monitor +ECHO = $FFEF ; character echo routine in Woz monitor KEY_DATA = $D010 ; read key KEY_CTRL = $D011 ; control port -DSP_DATA = $D012 ; write ascii -DSP_CTRL = $D013 ; control port ; zero page variables @@ -17,9 +15,18 @@ PTR4 = $F8 ; $F8-$F9 CELLCOUNT = $F9 ; also PTR4 high byte RND = $FA ; $FA-$FB random seed +; ; board geometry is 40x24 = 960 bytes +; there are two boards stored in memory: ; primary board: $2440-$27FF ; secondary board: $2840-$2BFF +; +; the boards contains the actual characters that are printed on +; the screen: live cell ("*"), dead cell (" ") and top/bottom border ("-") +; + +BOARD = $2440 +BOARDEND = $2800 ROW0 = $2440 ROW1 = $2468 @@ -30,11 +37,11 @@ DEADCELL = $A0 ; " " (space character) ALIVECELL = $AA ; "*" FRAMECELL = $AD ; "-" - ORG $2000 ; -; quickly resets the primary board ($2400-$27FF) +; clears the primary board ($2400-$27FF) +; bug: the area between $2400-$243F is cleared as well ; LDX #$00 LDA #DEADCELL ; dead cell character @@ -46,106 +53,128 @@ L2004 STA $2400,X ; bug: this should be $2440 BNE L2004 ; -; prints welcome message (56 characters) -; X is zero from previous BNE +; prints the welcome message (56 characters) +; (X is zero from previous BNE) +; L2013 LDA MESSAGE,X JSR ECHO INX - CPX #$38 ; prints 56 chars + CPX #56 ; prints 56 characters of the message BNE L2013 -; read and print string from keyboard until ENTER is pressed -; string is simply discarded, the purpose is to increment the -; random seed in $FA-RND+1 +; +; read and print from keyboard until ENTER is pressed +; typed characters are simply discarded, the purpose +; is to increment the random seed in $FA-FB (RND variable) +; L201E JSR RDKEY CMP #$8D ; enter key BNE L201E ; -; fills the board with a random number of cells (from 32 to 95) -; bug: also fills out of screen area between $2400 and $243F +; fills the board with a random number of live cells (from 32 to 95) +; bug: also writes out of the screen area between $2400 and $243F ; - JSR GETRAND ; gets a random number + JSR GETRAND ; gets a random number (0-255) in A AND #$3F ; ranges it $00-$3F - ADC #$20 ; ranges it $20-$5F (TODO: why carry is not cleared?) - STA CELLCOUNT ; number of cells to write betwen $20-$5F (32-95) + ADC #$20 ; ranges it $20-$5F (why carry is not cleared?) + STA CELLCOUNT ; number of cells to generate betwen $20-$5F (32-95) - LDY #$00 -L2030 JSR GETRAND ; gets a random number + LDY #$00 ; keeps Y to 0 for "STA(),Y" instruction +L2030 JSR GETRAND ; gets a random number in A AND #$03 ; ranges it 0-3 CLC - ADC #$24 - STA PTR1+1 ; high byte ranges from $24-$27 - LDA RND - STA PTR1 ; PTR1 points randomly $2400-$27FF + ADC #BOARD/256 ; board high byte ($24) + STA PTR1+1 ; high byte now ranges from $24-$27 + LDA RND ; get random number directly from seed + STA PTR1 ; PTR1 now points randomly to $2400-$27FF LDA #ALIVECELL ; alive cell character ("*") STA (PTR1),Y ; set cell "ON" - DEC CELLCOUNT ; decrement cell count + DEC CELLCOUNT ; decrement cell counter BNE L2030 ; loop until all cells are written +; ;$2046 ; main game loop -MAINLOOP LDA #$24 - STA PTR4+1 - LDA #$40 - STA PTR4 ; PTR4 = $2440 +; +MAINLOOP LDA #BOARD/256 ; + STA PTR4+1 ; + LDA #BOARD%256 ; + STA PTR4 ; sets PTR4 to $2440 ; ; marks top and bottom lines of the board to avoid out of bound checks ; - LDX #$27 ; $27=39, counts 40 characters backward - LDA #FRAMECELL ; $AD = board limit character ("-") -L2052 STA $27D8,X ; write bottom line of the board - STA $2440,X ; write top line of the board - DEX ; decrement 40 charc counter + LDX #39 ; counts 40 characters backward + LDA #FRAMECELL ; board frame character ("-") +L2052 STA ROW23,X ; write bottom line of the board + STA ROW0 ,X ; write top line of the board + DEX ; decrement char counter BPL L2052 ; loop if X >= 0 -; loop that prints the whole board from $2440 to $2800 - +; +; prints the whole board from $2440 to $2800 +; Y is already zero from above +; L205B LDA (PTR4),Y JSR ECHO INC PTR4 BNE L205B INC PTR4+1 LDA PTR4+1 - CMP #$28 + CMP #BOARDEND/256 BNE L205B +; ; reads the keyboard between each screen printout +; JSR RDKEY -; copy true board into "working" board (copies $2440-$2800 into $2840-...) +; +; copy primary board into secondary board (copies $2440-$27FF into $2840-$2BFF) +; LDY #$00 - JSR SETPTRS ; PTR1=$2440, PTR2=$2840 -L2074 LDA (PTR1),Y - STA (PTR2),Y + JSR SETPTRS ; set board pointers: PTR1=$2440 (primary), PTR2=$2840 (secondary) +L2074 LDA (PTR1),Y ; read from primary + STA (PTR2),Y ; write into secondary INC PTR1 INC PTR2 BNE L2074 INC PTR1+1 INC PTR2+1 LDA PTR1+1 - CMP #$28 + CMP #BOARDEND/256 ; check end of the board BNE L2074 - JSR ZEROBOARD ; fills the primary board all with zeros +; +; once the primary board is copied, it's used to count the number of +; nearby cells around a live cell, so it's all set to 0 +; + JSR ZEROBOARD ; -; scans the secondary board does some computation and writes on the primary board +; scans the secondary board: for every live cell increment by one +; the nearby cells in the primary board +; +; nearby cells are scanned using Y-indexing with the following Y values: +; +; -41 -40 -39 +; -1 * +1 +; 39 40 41 ; L208B LDY #$00 - LDA (PTR2),Y + LDA (PTR2),Y ; read cell in the secondary board CMP #ALIVECELL ; is cell alive? BNE L209D ; if no go next cell - LDY #$27 ; yes it's alive - JSR L2114 ; ?? - LDY #$01 - JSR L211D ; ?? + LDY #39 ; yes it's alive, start Y indexing from 39 + JSR SUM6CELLS ; sum cells with Y offsets: +/-39, +/-40, +/-41 (row above and below the live cell) + LDY #1 + JSR SUMYCELLS ; sum cells with Y offsets: +/-1 (left/right of live cell) ; increment PTR1 and PTR2 to next cell L209D INC PTR1 @@ -154,47 +183,56 @@ L209D INC PTR1 INC PTR1+1 INC PTR2+1 LDA PTR1+1 - CMP #$28 ; check end of the board + CMP #BOARDEND/256 ; check end of the board BNE L208B ; -; ??? does something with top and bottom rows of the board +; sums the score from bottom row into top, and top into bottom +; this "wraps" the playfield making it like a toroid (sort of) +; ; ROW1 = ROW1 + ROW23 ; ROW22 = ROW22 + ROW0 -; why?? ; CLC - LDX #$27 ; count 40 characters (1 row) + LDX #39 ; count 40 characters (1 row) L20B0 LDA ROW23,X ADC ROW1,X STA ROW1,X LDA ROW0,X - ADC ROW22,X + ADC ROW22,X ; (due to low score, carry it's always zero, no need to CLC) STA ROW22,X DEX BPL L20B0 - JSR SETPTRS +; +; the actual GAME OF LIFE computation (Conway's rules) +; here secondary buffer contains the old board ("*" or " ") +; and primary buffer contains the number of nearby cells for each cell that is alive +; + + JSR SETPTRS ; start from top of the boards L20C8 LDY #$00 LDA (PTR1),Y - CMP #$02 ; ? two cells around - BNE L20D4 - LDA (PTR2),Y - BNE L20DE -L20D4 CMP #$03 ; ? three cells around - BNE L20DC - LDA #ALIVECELL ; set next cell alive + CMP #2 ; two cells nearby? + BNE L20D4 ; if not checks for three + LDA (PTR2),Y ; yes two cells around: it survives to next round BNE L20DE +L20D4 CMP #3 ; three cells nearby? + BNE L20DC ; if not then it's dead cell + LDA #ALIVECELL ; else it's alive (does not matter if it was alive or not) + BNE L20DE ; anything else is dead cell L20DC LDA #DEADCELL ; set next cell dead -L20DE STA (PTR1),Y +L20DE STA (PTR1),Y ; write the cell on the board + INC PTR1 INC PTR2 BNE L20C8 INC PTR1+1 INC PTR2+1 LDA PTR2+1 - CMP #$2C + CMP #$2C ; check end of the secondary board (ends at $2C00) BNE L20C8 + JMP MAINLOOP ; set pointers to: @@ -224,15 +262,14 @@ L2108 LDA KEY_CTRL JSR ECHO RTS -; ??? - -L2114 JSR L211D +; $2114 +SUM6CELLS JSR SUMYCELLS INY CPY #$2A - BNE L2114 + BNE SUM6CELLS RTS - -L211D ; increment cell at (PTR1),Y +;$211D +SUMYCELLS ; increment cell at (PTR1),Y CLC LDA (PTR1),Y ADC #$01 @@ -293,9 +330,9 @@ L2167 STA (PTR1),Y BNE L2167 INC PTR1+1 LDX PTR1+1 - CPX #$28 ; check end of the board + CPX #BOARDEND/256 ; check end of the board BNE L2167 - JSR SETPTRS ; reset correct pointers on exit + JSR SETPTRS ; reset correct pointers on exit RTS L2179: