One byte chooses the screen, the way Mario's does

A title that waits for Start, the jump lesson’s square to play with, and a pause that freezes it, with Start moving between them. The program is 313 instructions in 701 bytes, built and checked the same way.

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

On the screen

frame 100
frame 100
frame 250
frame 250
frame 420
frame 420
frame 600
frame 600

One byte chooses what runs

Super Mario Bros. keeps which screen it is on in one byte of memory and, every frame, calls a routine that takes an address from a table placed right after the call, the entry chosen by that byte. The autopsy names that routine a jump engine. This cartridge does the same with its own byte: 0 is the title, 1 playing, 2 paused. Then we ran the autopsy over our own cartridge, the same tools that went over the games, to see whether they would recognise what we wrote.

this cartridgeSuper Mario Bros.
values the screen byte took, in order0, 1, 2, 10, 1, 3, 0
a jump engine found by the autopsyyesyes
the table chosen by the screen byte: entries, taken in the run3, 34, 3
stretches the run was cut into by which routines ran419
changes of the screen byte where a stretch began3 of 32 of 3
bytes of memory changing a frame: before the pause, while paused5, 041, 9

What the autopsy said of it

It found the engine and the table, and the table’s choosing byte was ours. The stretches it cut the run into, knowing nothing of screens, began where the screen byte changed 3 times out of 3. While paused, 0 bytes of memory changed a frame, outside the stack and the sprites’ page: the pause is nothing but the entry that only waits for Start.

As written

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

;; What runs this frame, by the screen: the table after the call.
screen:
    LDA $40
    JSR engine
    .word on_title
    .word on_play
    .word on_pause
;; The jump engine: A is the entry. The call's return address, taken off
;; the stack, is one byte short of the table that follows the call; the
;; entry's two bytes are an address, and the jump goes there. Each entry
;; ends with RTS, which returns past the call to `screen`: the engine
;; took its own return address off the stack, so the one left on top is
;; main's. (Reached from main directly, there would be none, and the RTS
;; would go wherever the stack's next two bytes said.)
engine:
    ASL A
    TAY
    PLA
    STA $04
    PLA
    STA $05
    INY
    LDA ($04),Y
    STA $06
    INY
    LDA ($04),Y
    STA $07
    JMP ($06)

All the lessons