update life-src.asm

This commit is contained in:
nino-porcino 2022-10-30 11:40:49 +01:00
parent 5bc71a3cfe
commit 0a0354dcd4
2 changed files with 380 additions and 1 deletions

2
.gitignore vendored
View File

@ -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

379
demos/life-src/life-src.asm Normal file
View File

@ -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