Words that crawl up the screen, the way Zelda's story does

An about screen for our square: a few lines of our own, crawling up the screen and starting again when they run out. Play it and read along. The program is 221 instructions in 663 bytes, built and checked the same way.

Play it here The cartridge, to play anywhere that plays NES cartridges: about.nes

On the screen

frame 300
frame 300
frame 500
frame 500
frame 700
frame 700
frame 1100
frame 1,100

One row for every row it moves

Leave the title of The Legend of Zelda alone and it tells you its story, the words creeping up the screen. The console holds two screens of background, stacked one above the other on this board, and the game simply scrolls down through them and round again, one pixel every second frame. It never redraws the screen: each time the words have moved up by one row’s height, 8 pixels, it writes a single new row of 32 tiles into the row about to come into view, plus a few colour bytes now and then for the words it shows in colour. That is all the drawing a whole story needs. This cartridge does the same with our own words, in one colour.

this cartridgeThe Legend of Zelda
pixels the words move, and frames between moves1, every 21, every 2
rows written, and frames apart74, every 1680, every 16
pixels of crawl for each row written88
colour bytes written0152
other tiles written00
the picture is splitnono
pixels crawled in the frames measured590 in 1,182638 in 1,278

As written

The part of the program this lesson is about. The whole program is a plain text file: about.s

;; Every second frame the scroll moves down one pixel, round from 479 to
;; 0; each time it is a whole row down, the next row is made ready.
crawl:
    LDA $42
    EOR #$01
    STA $42
    BNE crawled
    INC $40
    BNE carried
    INC $41
carried:
    LDA $41
    BEQ within
    LDA $40
    CMP #$E0
    BCC within
    LDA #$00
    STA $40
    STA $41
within:
;; The register's view: within the top screen below 240, else the lower.
    LDA $41
    BNE lower
    LDA $40
    CMP #$F0
    BCS lower
    STA $47
    LDA #$00
    STA $48
    JMP view
lower:
    SEC
    LDA $40
    SBC #$F0
    STA $47
    LDA #$02
    STA $48
view:
    LDA $40
    AND #$07
    BNE crawled
    JSR prepare
crawled:
    RTS
;; The row 240 below the scroll, which comes into view as it next moves:
;; its place (counting down both screens, round at 480), and in it a line
;; of the words, centred, or the gap between two lines.
prepare:
    CLC
    LDA $40
    ADC #$F0
    STA $45
    LDA $41
    ADC #$00
    STA $46
    BEQ first
    LDA $45
    CMP #$E0
    BCC first
    SBC #$E0
    STA $45
    LDA #$00
    STA $46
first:
;; $45/$46 is now 0 to 479. Below 240 it is the top screen ($2000),
;; else the lower ($2800), 240 less.
    LDA #$20
    STA $49
    LDA $46
    BNE second
    LDA $45
    CMP #$F0
    BCC place
second:
    SEC
    LDA $45
    SBC #$F0
    STA $45
    LDA #$28
    STA $49
place:
;; The row's address: the screen's, and 32 for each 8 pixels.
    LDA $45
    AND #$F8
    ASL A
    ASL A
    STA $46
    LDA $45
    LSR A
    LSR A
    LSR A
    LSR A
    LSR A
    LSR A
    ORA $49
    STA $45
    LDA #$00
    LDX #$1F
blank:
    STA $0300,X
    DEX
    BPL blank
    LDA $43
    EOR #$01
    STA $43
    BEQ ready
;; A line: its length, then its letters, placed in the middle. A length
;; of $FF is the end of the words, and they start again.
    LDY #$00
    LDA ($20),Y
    CMP #$FF
    BNE line
    LDA wordslo
    STA $20
    LDA wordshi
    STA $21
    LDA ($20),Y
line:
    TAX
    LDA #$20
    SEC
    STX $4A
    SBC $4A
    LSR A
    TAX
    LDY #$00
copy:
    CPY $4A
    BEQ copied
    INY
    LDA ($20),Y
    STA $0300,X
    INX
    JMP copy
copied:
    INY
    TYA
    CLC
    ADC $20
    STA $20
    LDA $21
    ADC #$00
    STA $21

All the lessons