Liber VII · Capitulum VI

The cover

An image composed line by line like a program of writes.

Redrawn for the TIA

Converting the loading screen was attempted in 42 ways, simulated with a model of the TIA: the title was legible and the rest came out as smudges. The cover was composed by hand, thinking about what each TIA object can paint: the wall and the windows in playfield; the sky with one background colour per line; the moon with the two players side by side; the stars and the spire with the ball; the title in the 48-pixel window with a gradient per line; the flames with three copies of a player and the candles with a 4-pixel missile; the quill with missile 0 shifted diagonally with HMOVE; the habit and the armchair with the background. Each object is reused several times per frame, and its RES goes on a line where it does not paint.

The cover with the menu in Stella with debug colours, fields 0 and 1
The cover with the menu. It is not interlaced: both fields are identical. Quill in orange (missile 0), candles in green (missile 1), stars in blue (ball), wall, abbey and menu arrows in purple (playfield).
Stella debug colours: player 0, missile 0, player 1, missile 1, playfield, ball and background. Field 0 on the left and field 1 on the right.

One program per line

There is no bitmap and no drawing loop. Each visible line is a list of writes to the TIA, each with its cycle, and in the ROM it takes one count byte and three per instruction: prior wait, operation and register, value. The ARM reads the triplet and injects it, calculating nothing. The generator (in Python) describes each line in layers, compiles it to writes with a scheduler like the room's, and simulates the result with the times measured in Stella. With that, the Stella image and the simulator's match pixel for pixel. The background can only change every 9 pixels or more, so dynamic programming chooses the colour runs, counting only the pixels where the background is visible.

Without bus stuffing, each write costs 5 cycles (or 3 if the value is already in A, X or Y): about 12 fit per line. The current program has from 1 to 15 writes per line, 7.1 on average.

Colours, compression and menu

The colours are calibrated for NTSC. In PAL 50 and PAL 60 the program is decompressed into RAM and the values that end up in a colour register are translated, including those that pass through lda, ldx or ldy. The program is compressed with a custom LZSS (2 KB window, optimal splitting by dynamic programming) and decompressed once, over the RAM holding the game's line data, which the cover does not use.

When the button is pressed, the last 53 lines (63 with EXIT) turn into a menu in a 48-pixel window without bus stuffing, with the narrow scoreboard font: the labels of the four settings (system, language, mode and HMOVE), the chosen one in yellow and, below it, its value in white. Values do not wrap around at the ends, and blinking arrows show which way the value can change. They are reflected playfield: PF1 is rewritten mid-line so that only the arrow on that side appears.