From 0a0354dcd43c02f19465d5322a5e3ebfda4bc861 Mon Sep 17 00:00:00 2001 From: nino-porcino Date: Sun, 30 Oct 2022 11:40:49 +0100 Subject: [PATCH] update life-src.asm --- .gitignore | 2 +- demos/life-src/life-src.asm | 379 ++++++++++++++++++++++++++++++++++++ 2 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 demos/life-src/life-src.asm diff --git a/.gitignore b/.gitignore index ccc2762..b42a814 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,4 @@ packets*.wav !demos/anagram/out/hangman.woz !demos/anagram/out/anagram.prg !demos/anagram/out/hangman.prg - +!demos/life-src/life-src.asm diff --git a/demos/life-src/life-src.asm b/demos/life-src/life-src.asm new file mode 100644 index 0000000..f97cae5 --- /dev/null +++ b/demos/life-src/life-src.asm @@ -0,0 +1,379 @@ +; LIFE FOR APPLE-1 +; UNKNOWN AUTHOR +; DISASSEMBLED BY ANTONINO PORCINO, 14TH SEP 2022 + +ECHO = $FFEF ; character echo routine in Woz monitor +KEY_DATA = $D010 ; read key +KEY_CTRL = $D011 ; control port + +; zero page variables + +PTR1 = $F0 ; $F0-$F1 +PTR2 = $F2 ; $F2-$F3 +PTR3 = $F6 ; $F6-$F7 +PTR4 = $F8 ; $F8-$F9 +CELLCOUNT = $F9 ; also PTR4 high byte +RND = $FA ; $FA-$FB random seed +TMP = $F6 ; also PTR3 low byte + +; +; board geometry is 40x24 = 960 bytes +; there are two boards stored in memory: +; primary board: $2440-$27FF +; secondary board: $2840-$2BFF +; +; the boards contain the actual characters that are printed on +; the screen: live cell ("*"), dead cell (" ") and top/bottom border ("-") +; + +BOARD = $2440 ; address of the primary board in memory +BOARDEND = $2800 ; end address of the board, for bound checking + +ROW0 = $2440 ; address of topmost row in the board (row 0) +ROW1 = $2468 ; address of second row +ROW22 = $27B0 ; address of 23nd row +ROW23 = $27D8 ; address of bottom row in the board (row 23) + +DEADCELL = $A0 ; " " (space character) +ALIVECELL = $AA ; "*" +FRAMECELL = $AD ; "-" + + ORG $2000 + +; +; clears the primary board ($2400-$27FF) +; bug: the area between $2400-$243F is cleared as well +; + LDX #$00 + LDA #DEADCELL ; dead cell character +L2004 STA $2400,X ; bug: this should be $2440 + STA $2500,X + STA $2600,X + STA $2700,X + INX + BNE L2004 + +; +; prints the welcome message (56 characters) +; (X is zero from previous BNE) +; + +L2013 LDA MESSAGE,X + JSR ECHO + INX + CPX #56 ; prints 56 characters of the message + BNE L2013 + +; +; 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 + +; +; randomly calculate how many cells to draw at the start of the game +; it's a random number from 32 to 95, stored into "CELLCOUNT" variable +; + + JSR GETRAND ; gets a random number (0-255) in A + AND #$3F ; ranges it $00-$3F + ADC #$20 ; ranges it $20-$5F (carry is not cleared though) + STA CELLCOUNT ; number of cells to generate betwen $20-$5F (32-95) + +; +; fills the board with the number live cells in "CELLCOUNT" +; bug: also writes out of the screen area between $2400 and $243F +; + 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 #BOARD/256 ; board high byte $24 + rnd(0-3) + STA PTR1+1 ; high byte now ranges from $24 to $27 + LDA RND ; gets random number directly from seed + STA PTR1 ; PTR1 now points randomly to $2400-$27FF + LDA #ALIVECELL ; alive cell character ("*") + STA (PTR1),Y ; writes on the board (set cell "ON") + DEC CELLCOUNT ; decrements cell counter + BNE L2030 ; loops until all cells are written (counter reches 0) + +; +;$2046 +; main game loop +; +MAINLOOP LDA #BOARD/256 ; + STA PTR4+1 ; + LDA #BOARD%256 ; + STA PTR4 ; sets PTR4 to $2440 (primary board) + +; +; draws a line of dashes ("-") on top and bottom rows +; + + LDX #39 ; counts 40 characters backward + LDA #FRAMECELL ; board frame character ("-") +L2052 STA ROW23,X ; writes bottom line of the board + STA ROW0 ,X ; writes top line of the board + DEX ; decrements char counter + BPL L2052 ; loops if X >= 0 + +; +; prints the whole board from $2440 to $2800 +; Y is already zero from above +; +L205B LDA (PTR4),Y ; reads character from board + JSR ECHO ; prints it by the echo routine in Woz monitor + INC PTR4 ; + BNE L205B ; + INC PTR4+1 ; increments pointer PTR4 + LDA PTR4+1 + CMP #BOARDEND/256 ; checks end of the board + BNE L205B + +; +; reads the keyboard between each game epoch +; + JSR RDKEY + +; +; copy primary board into secondary board (copies $2440-$27FF into $2840-$2BFF) +; + LDY #$00 + JSR SETPTRS ; sets board pointers: PTR1=$2440 (primary), PTR2=$2840 (secondary) +L2074 LDA (PTR1),Y ; reads from primary + STA (PTR2),Y ; and writes into secondary + INC PTR1 + INC PTR2 + BNE L2074 + INC PTR1+1 + INC PTR2+1 ; increments pointers PTR1, PTR2 + LDA PTR1+1 + CMP #BOARDEND/256 ; checks end of the board + BNE L2074 + +; +; once the primary board is copied onto secondary, the primary is used to count +; the number of nearby cells around a live cell, so it needs to be filled with 0's +; + JSR ZEROBOARD + +; +; 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 ; keeps Y to 0 for "LDA(),Y" instruction + LDA (PTR2),Y ; reads cell in the secondary board + CMP #ALIVECELL ; is cell alive? + BNE L209D ; if no goes next cell + LDY #39 ; yes it's alive, starts Y indexing from 39 + JSR SUM6CELLS ; sums cells with Y offsets: +/-39, +/-40, +/-41 (row above and below the live cell) + LDY #1 + JSR SUMYCELLS ; sums cells with Y offsets: +/-1 (left/right of live cell) + + ; increments PTR1 and PTR2 to next cell +L209D INC PTR1 + INC PTR2 + BNE L208B + INC PTR1+1 + INC PTR2+1 + LDA PTR1+1 + CMP #BOARDEND/256 ; checks end of the board + BNE L208B + +; +; sums the primary board accumulated score from bottom row into top, and top into bottom +; this actaully "wraps" the playfield making it like a toroid (sort of) +; +; does: ROW1 = ROW1 + ROW23 +; ROW22 = ROW22 + ROW0 +; + CLC ; keeps carry clear for ADC below + LDX #39 ; counts 40 characters (1 row) +L20B0 LDA ROW23,X ; reads 24th row + ADC ROW1,X + STA ROW1,X ; and sums into 2nd + LDA ROW0,X ; reads first row + ADC ROW22,X ; and sums into row 23rd (note: numbers are small, carry always 0, no need to CLC again) + STA ROW22,X + DEX + BPL L20B0 + +; +; the actual GAME OF LIFE computation (Conway's rules) +; at this point the secondary board contains the board ("*" or " ") of the last epoch; +; primary board contains the number of nearby cells for each cell that is alive +; + + JSR SETPTRS ; starts from top of the boards +L20C8 LDY #$00 ; keeps Y to 0 for "LDA (),Y" + LDA (PTR1),Y ; reads number of nearby cells + CMP #2 ; two cells nearby? + BNE L20D4 ; if not checks for three + LDA (PTR2),Y ; yes two cells nearby: cells survives to next round + BNE WRITECELL +L20D4 CMP #3 ; three cells nearby? + BNE SETDEAD ; if not then it's dead cell + LDA #ALIVECELL ; else it's alive (does not matter if it was alive or not) + BNE WRITECELL ; cheap jump to WRITECELL +SETDEAD LDA #DEADCELL ; sets next cell dead +WRITECELL STA (PTR1),Y ; writes the cell on the board + + ; increments pointers to next cell + INC PTR1 + INC PTR2 + BNE L20C8 + INC PTR1+1 + INC PTR2+1 + LDA PTR2+1 + CMP #$2C ; checsk end of the secondary board (which ends at $2C00) + BNE L20C8 + + JMP MAINLOOP ; loops forever to the next epoch of the game + +; +; subroutine that set pointers to point to primary and secondary boards: +; PTR1 = $2440 (primary board) +; PTR2 = $2840 (secondary board) +; +; $20F3 +SETPTRS LDA #$24 + STA PTR1+1 + LDA #$28 + STA PTR2+1 + LDA #$40 + STA PTR1 + STA PTR2 + RTS + +; $2102 +; +; subroutine that reads a key and displays it on the terminal +; returns key in A +; increments a 16 bit counter that works like a random number seed generator +; +RDKEY INC RND + BNE L2108 + INC RND+1 ; increments RND as a 16 bit number +L2108 LDA KEY_CTRL ; Apple-1 keyboard status port + BPL RDKEY ; if key not pressed reads it again + LDA KEY_DATA ; reads the actual key code from Apple-1 keyboard data port + JSR ECHO ; displays it in on screen + RTS + +; $2114 +; +; this subroutine loops over Y=39, 40, 41 +; and calls another soubroutine that increments +; cell at +/- Y values +; +SUM6CELLS JSR SUMYCELLS + INY + CPY #42 ; is it 42? (starts at 39, ends at 41) + BNE SUM6CELLS ; no, loops to next Y value + RTS + +;$211D +; +; subroutine that increments PTR1 at +/- Y +; e.g.: INC (PTR1),+Y +; INC (PTR1),-Y + +SUMYCELLS + ; increments cell at (PTR1),Y + CLC + LDA (PTR1),Y + ADC #$01 ; increments by one + STA (PTR1),Y + + STY CELLCOUNT ; saves Y into unused location CELLCOUNT + + ; PTR3 = PTR1 - Y + SEC + LDA PTR1 + SBC CELLCOUNT + STA PTR3 + LDA PTR1+1 + SBC #$00 + STA PTR3+1 + + ; increments cell at (PTR3),Y e.g. (PTR1-Y) + LDY #$00 + LDA (PTR3),Y + CLC + ADC #$01 ; increments by one + STA (PTR3),Y + LDY CELLCOUNT ; restores Y + RTS +; +;$213F +; +; advances the random number generator +; and loads a random number into A +; uses a sort of a linear feedback shift register +; +GETRAND LDA RND+1 + STA TMP + LDA RND + ASL A + ROL TMP + ASL A + ROL TMP ; [TMP|A] = [TMP|A] << 2 + CLC + ADC RND + PHA + LDA TMP + ADC RND+1 + STA RND+1 + PLA + ADC #$11 + STA RND + LDA RND+1 + ADC #$36 + STA RND+1 ; RND = RND + $3611 + C + RTS + +;$2161 +; +;fills the primary board ($2440-$27FF) with $00 +; +ZEROBOARD JSR SETPTRS ; initialized the pointers + LDA #$00 ; value to fill + TAY ; keeps Y to 0 for STA(),Y +L2167 STA (PTR1),Y + INC PTR1 + BNE L2167 + INC PTR1+1 + LDX PTR1+1 + CPX #BOARDEND/256 ; check end of the board + BNE L2167 + JSR SETPTRS ; reset correct pointers on exit + RTS + +L2179: + DB $A0 ; unused byte + +; $2180 +; welcome message +MESSAGE: + DB $A0,$A0,$A0,$A0,$A0,$A0,$8D,$8D + DB $8D,$8D,$C3,$CF,$CE,$D7,$C1,$D9 + DB $A7,$D3,$A0,$C7,$C1,$CD,$C5,$A0 + DB $CF,$C6,$A0,$CC,$C9,$C6,$C5,$8D + DB $8D,$D0,$CC,$C5,$C1,$D3,$C5,$A0 + DB $D4,$D9,$D0,$C5,$A0,$D9,$CF,$D5 + DB $D2,$A0,$C6,$D5,$CC,$CC,$A0,$CE + DB $C1,$CD,$C5,$AE,$8D,$8D,$00 + +// $21B9 +