Professional Documents
Culture Documents
Usagi Moves Assembly Code Listing
Usagi Moves Assembly Code Listing
-----------------------------------
07.07.2023 by sirhadisen
Notes:
- For a manual test run, load all modules, set $E4 to #$01, and start with G038F
(or with SYS 911, but from program mode the latter only works if RTS exits the
initializers instead of BRK!)
- To edit bank switching region (Basic interpreter is banked out to use $A500-), do
not forget POKE 2040, 128 to see the 32K RAM under the ROM.
- ! mark lines that use addresses, or their low or high bytes, which depend on the
structure and relative or absolute placement of routines or cache regions. This
includes all relative jumps and pieces of self-modifying code.
- <...> denotes names of jump, read and write addresses within a routine that
change frequently during code development
*** 1) Routines in the tape buffer (erased during soft reset) ***
--- $0357-$038B Universal RAM-access stub, which IRQ detour address in the high-
RAM region (JSR $#### statement) must have been set in advance
-- skip IRQ-extension unless skipping counter has reached 0, in which case it is
reset to #$04
.0357 dec $d3
!.0359 bne $<ende>
.035b lda #$04
.035d sta $d3
-- detect key strokes with SCNKEY GETIN and cache in $E5
(https://github.com/cc65/cc65/issues/324)
.035f php
.0360 jsr $ff9f
.0363 jsr $ffe4
?? idea: compare with $E5 in order to change key stroke recognition behavior
.0366 cmp #$00
?? idea: use POKE to change !!byte 6C to 6A in order to change key stroke
recognition behavior
!.0368 bne $036c
.036a sta $e5
.036c plp
-- raster line synchronization for music
- line #$10 seems to be a good balance for musik speed; should probably be derived
from music idler with LSR
.036d lda #$10
.036f cmp $ff1d
!.0372 bne $036f
.0374 - .037a nop
-- bank-Switching ROM->RAM
.037a sta $ff3f
-- jump address is set in the initialization routine, so modify it there
.037e jsr $0000
-- bank-Switching RAM->ROM
.0381 sta $ff3e
-- if $E4 = #$00, do an RTS, as the stub only serves a single execution, otherwise
resume with system-IRQ tasks at $CE0E
.0384 lda $e4
!.0386 bne $<ende>
.0388 rts
<ende>.0389 jmp $ce0e
--- $A590-$A61C Drawing routine (can only handle rectangular frames with an even
number of up to 254 cells!)
-- set target TED base address (lb hb) to upper left corner according to offsets of
row and column $DD and $E0
-- 1. initialize base address at $a5??-$a5??+1 for indirect addressing according to
column offset (self-modifying code!!)
-- self-modifying code!!
!.a590 lda #$0c
!.a592 sta $<4++>
!.a595 lda $e0
!.a597 sta $<4+>
-- 2. 2-byte-add (row offset + height - 1)-times #$28 to start in last row
-- Note: I neglect the -1 for simplicity, meaning the minimal offset is 1, which
has the advantage that usagyuuun cannot hurt its ears
.a59a clc
.a59b lda $dc
.a59d adc $dd
.a59f tax
<1>.a5a0 clc
!.a5a1 lda $<4+>
.a5a4 adc #$28
-- self-modifying code!!
!.a5a6 sta $<4+>
!.a5a9 lda $<4++>
.a5ac adc #$00
-- self-modifying code!!
!.a5ae sta $<4++>
.a5b1 dex
!.a5b2 bne $<1>
-- copy base address to other lda and sta statements
!.a5b4 jsr $a630
-- 3. loop over frame data at ($DE),Y and copy to TED memory address row-wise
backwards: outer loop over rows of the frame, inner loop over columns of the frame
-- initialize Y as character counter with width*height = $DB*$DC, which must be <
#$FF
.a5b7 ldy $dc
.a5b9 lda #$00
<2>.a5bb clc
.a5bc adc $db
.a5be dey
!.a5bf bne $<2>
.a5c1 tay
-- initialize column offset X with frame width
<10>.a5c2 ldx $db
-- skip memorization of background if the routine was called to restore the
background ($E7 = #$01)
<12>.a5c4 lda $e7
!.a5c6 bne $<11>
-- memorize background (from TED memory at self-modified indirect address) in
restoration cache
<7>.a5c8 lda $0000,x
!.a5cb sta $a680,y
<8>.a5ce lda $0000,x
!.a5d1 sta $a780,y
-- if the routine was not called to restore the background, do character checks but
do not restore attribute bytes
-- otherwise, do it the other way around
-- retrieve frame data
.a5d4 lda ($de),y
-- skip transparent cells (#$20) and replace untransparent white (#$2E) with #$20
.a5d6 cmp #$20
!.a5d8 beq $<6>
.a5da cmp #$2e
!.a5dc bne $<4>
.a5de lda #$20
!.a5e0 jmp $<4>
-- restore attribute byte in TED memory from cache at !! $a780
!<11>.a5e3 lda $a780,y
<5>.a5e6 sta $0000,x
-- retrieve frame data
.a5e9 lda ($de),y
-- write character to the TED memory at self-modified indirect address
<4>.a5eb sta $0000,x
<6>.a5ee dey
!.a5ef beq $<9>
.a5f1 dex
!.a5f2 bne $<12>
-- subtract #$28 from the TED base to adjust it to the left boarder of the previous
row (= "new line backwards")
-- self-modifying code!!
.a5f4 sec
!.a5f5 lda $<4+>
.a5f8 sbc #$28
!.a5fa sta $<4+>
!.a5fd sta $<5+>
!.a600 sta $<7+>
!.a603 sta $<8+>
!.a606 lda $<4++>
.a609 sbc #$00
!.a60b sta $<4++>
!.a60e sta $<7++>
.a611 sbc #$04
!.a613 sta $<5++>
!.a616 sta $<8++>
!.a619 jmp $<10>
<9>.a61c rts
--- $A630-$A64B Copy TED base address to other STA and LDA statements
-- self-modifying code!!
!.a630 lda $<4+>
!.a633 sta $<5+>
!.a636 sta $<7+>
-- lb is identical for character and attribute addresses
!.a639 sta $<8+>
!.a63c lda $<4++>
!.a63f sta $<7++>
-- hb of attribute address = character address minus #$04
.a642 sec
!.a643 sbc #$04
!.a645 sta $<5++>
!.a648 sta $<8++>
.a64b rts
??Clarify: Why is the move still executed when pressing up? Should it be skipped if
$e5 is 0, or everything that is not left or right?