1988 · Systems Editoriale (Commodore 64 Club)

Mr. Hat

This minisite was contributed by air, jankfoundry. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/mr-hat with me to Gold.

Eleven rooms, most with their own copy of the same game loop, and under them the remains of the game it was built from: Lupenio, by Francesco Chiola and Andrea Cucchetto, with its keys, its doors and its ending still in memory, switched off.

01 · The rooms

Eleven rooms, rebuilt from memory

The labyrinth of the magazine's blurb is eleven single screens in four stages. Each one is drawn here from the game's own memory and the video chip's registers, as one frame of the running game.

Ten blocks of code serve the eleven rooms: rooms 4 and 7 share one, built by $9000 according to the entry code. A block holds a set-up routine that draws the room and places the sprites, usually an interrupt handler that moves its guardians (room 10 has none of its own), and a main loop that reads the joystick and applies the room's rules. The room number lives at $100C (0 for room 1; $10 and $11 for rooms 10 and 11), and the room Mr Hat leaves writes an entry code to $4ACD that the next room reads to put him in the right doorway.

Most of the main loops are copies of one template. Rooms 6 and 8's loops are 278 bytes each and differ in 54 of them: all but one in the addresses called, jumped or branched to, and the last a JSR in room 6 where room 8 has a JMP. Rooms 1 and 3 walk Mr Hat with code of their own instead of the shared walk routines. What a room adds is its own floors, hazards, guardians and objects.

The exits found in the room code. A line joins two rooms when one room's code sets up the other. Press a room to show it above.

02 · Music

Music: the title tune, played by the game's own player

One tune plays on the title screen and again under the ending: a melody on a pulse voice, a fast trill on a triangle voice and a bass, about 37 seconds before it loops.

The player at $C080-$C373, ported line by line and run through the site's model of the SID. Checked against the game's own code run in a 6502 simulator: every SID write of 6,000 interrupts, in order, across two ends of the song, with no difference. The game paces the player with CIA 1's timer A, 61.7 times a second; this page runs it once or twice per PAL frame to match, so writes that fall inside one frame land together.

The player is a small sequencer. A song is a list of positions, each position plays a range of patterns, and each pattern plays a range of note blocks, 16 steps for each voice. A note byte is an index into a 95-entry frequency table ($C374, $C3D3), $64 releases the voice, and 0 lets the note ring on. Notes carry no length and no instrument: a step lasts the pattern's tempo, and the pattern sets all three voices' sound at once.

ByteWhat the song holds
$C43D = 1the song is one position long, so only patterns 1 and 2 play. The order table names patterns 3 to 13 and blocks up to 39, most of which are not in the image.
$C443+1 = 8tempo: eight interrupts a step, about 0.13 seconds
$CA44/$CA84 = $3E6Athe timer latch each pattern sets: 61.7 interrupts a second on PAL
$C439 = 0a switch nothing turns on: set, the player would read the keyboard (F7 all voices, 1, 2 or 3 one voice alone) and call an editor routine at $CB51 that is now note data. The text MUZA1 at $CAF4 is the editor's too.

The frequency table sits about a quarter of a semitone flat at the PAL clock: its A4 is $1CD6, 433.5 Hz.

03 · Music

Music: the in-play tune, and a tune the game never plays

Play has its own music, on one voice: a short loop that runs in every room, and a longer tune whose player nothing in the game reaches.

Both players ported and run through the site's model of the SID, at the 61.7 interrupts a second the game runs in play. Checked against the game's own code in a 6502 simulator, 3,000 calls of each, every SID write in order: no difference. One triangle voice with a short pluck is much quieter than the title tune's three, so this player plays it four times louder. Nothing in the game plays the second tune. The only jump to its player at $89D0 is the one at $8A00, which nothing reaches, and the only other code that touches it resets its pointers when a game starts ($92C7).

The two players are twins. Each plays voice 3 alone on a triangle wave, the in-play tune one note every 8 interrupts and the unused one every 8 or 16 (once 32), from three tables read through pointers kept inside the code's own operands: the in-play tune's at $8C90, $8D30 and $8D90 (95 notes), the unused one's at $8A60, $8B00 and $8B90 (105 notes). The unused tune sends its first column to the voice's frequency low byte. The in-play player sends the same column to $D022 instead, a colour register that shows nothing in this screen mode, so its notes sound at the high byte alone, in steps of 256. The column's values change between repeats of the same note ($2188, $2164, $213D), which a tuning would not do; they may have been meant as colours all along.

The player runs at the end of the interrupt that every room's handler finishes with ($8215, $BF30, $B530, $8C00), so the tune plays in all eleven rooms; recorded in the emulator, its pointer moved on in rooms 1, 2, 3, 5, 8, 9 and 11. It starts again from its first note while Mr Hat dies, and F1 switches it off and on (see "Odds and ends").

04 · Sprites

Mr Hat, frame by frame

Everything that moves is a hardware sprite. Mr Hat has three frames for each direction of walking, two for climbing, one for crouching and one for dying, which the game then eats away.

Drawn from the sprite shapes at $0900-$0FFF with room 1's colours (sprite 4: dark grey $D02B, red $D025 and light green $D026, multicolour). The walk changes frame every nine one-pixel steps ($5340, $5370). The death is the game's own routine, $A877, run in a 6502 simulator: $1DDD copies the death shape from $ACD8, $A92D steps the colour 256 times, and $A8F0 ANDs each byte of the shape once with the raster line, four bytes a pass, 16 passes of about 84 ms. In the simulator the raster comes from the cycle count with no interrupts, so a real death's mask differs.

All 28 sprite shapes, pointers $24 to $3F, each in the colours of the first recorded room that shows it. Mr Hat's own frames, $27, $2A and $2C-$33, take his colours from room 1 (in play they go in sprite 4's pointer $07FC; the title's cast shows $2C on sprite 0, $B7A6); the rest that no recorded frame showed are drawn in white and greys, two bits a pixel.

05 · Controls

Every move is one exact joystick value, so diagonals do nothing

Fire jumps and up only climbs. Every test compares the whole joystick byte with one value, and no test has a diagonal's value.

Press directions and fire to build the byte the game reads from $DC00, CIA 1's port A, where joystick port 2 pulls a bit low for each switch closed. The actions are the room loops' tests, such as $438D in room 1 and $76E3 in room 9.

A jump runs in three phases of 21 one-pixel steps: up and forward, level, down and forward, 63 pixels across and 21 up. Fire with a direction ($67 or $6B) jumps too, the way he faces whichever direction is held, from standing as well as straight after a jump. Down crouches, climbs down and, standing over a treasure, takes it.

06 · Death

Death by touch, read from one register

The game asks the video chip which sprites overlap, through the collision register $D01E, and compares the answer with a list of exact values. Each test has its own list. It never reads $D01F, the register for sprites touching the scenery.

Choose a test, then tick the sprites that overlap Mr Hat (sprite 4) in one frame. The video chip sets one bit for every sprite in any overlap. $55B0, the test in every room but 1, 3 and 10 (each step through $5590, $BB10 and $8E10, and on the ladders of rooms 5, 6 and 9 and room 8's shaft), kills on $11, $12, $14, $18, $50 or $90, and tests $18 twice. Room 1's $1F70 takes the same values but $50 and $90, and adds $58: sprites 3 and 6 together. Room 3's ladder test $5028 takes $14 and $18. $4C40 calls $B666, which kills on $90, then tests a second read of the register for $14 and $18; the widget treats both reads as one. None takes $30, so sprite 5, the lift cabin, is harmless.

Two guardians touching him in the same frame set three bits, and only one pair appears in any list: sprites 3 and 6 in room 1. Any other pair lets him live for that frame. A live attempt could not stage it, because the rooms switch their guardian sprites on and off from frame to frame, and a frame with only one of them on him would kill. Most fixed hazards are positions: $BB10 kills on a room's deadly spots only when Mr Hat stands at an exact height, $B4 on a bottom floor and $5C on an upper one.

The death itself ($A877, animated in section 04) swaps in a death shape, sinks him to the floor line, flashes him and dissolves him, using the raster line as a random mask. Then a lives mark goes. The four marks at the bottom right are colour cells $07B9, $07BA, $07E1 and $07E2; a lost life recolours one grey on grey.

07 · Score

Points come a thousand at a time

The score has six digits, and the lowest three never move. The only routine that adds to it, $41DA, steps the thousands digit in the bitmap and carries; $8042 draws 000000 at the start of each game.

RoutineCalls of the +1,000 stepScore after, from 000000
$8AD01001000
$120E10010000
$121920020000
$122425025000
$122F50050000
$123A75075000

Each adder run in a 6502 simulator on a snapshot of room 1, with the score's digits read back from the bitmap (the 20,000 and 50,000 adders were read from the code). The digits are drawn from glyphs at $1600, and there is no carry past the hundred-thousands digit.

Treasures pay 10,000 to 75,000; a key or a door 2,000; and there are two 5,000-point pickups ($5C2F, $6C3D) that look impossible to take. A treasure is taken by standing on it and pulling the stick down. A taken object stays gone for the rest of the game: room objects because their colour is kept inside the room's own set-up code and overwritten when taken, the treasures and switches through flags at $1371-$1389. Both are reset when a new game starts.

08 · Light

Secret: a candle in room 2 lights two other rooms

Rooms 6 and 9 are drawn black until the candle is taken in room 2. Room 9's objects are still there in the dark; room 6 draws its television and treasures only when lit ($5ED8, $BDE2), and its treasures can only be taken then ($8F1E).

Both rooms drawn from memory, with the flag $22 as each set-up found it: 0 at the start of a game, $40 once $5519 has run in room 2. Room 6's set-up is at $5E10, room 9's darkening at $7440.

The dark changes room 6's rules as well as its picture. A stretch of the bottom floor kills only while the room is dark, and a 10,000-point bonus at X $108 counts only while its colour cell $06A0 is anything but $CC ($63B0). Set up in the emulator, the dark room holds $00 there and the lit one $CC; taking the bonus was not tried. The room's treasures work the other way round: they appear and can be taken only when lit. Nothing found records that the bonus was taken, so it may count again on a later dark visit; that was not tested either.

09 · Bug

Bug: a wrong digit the game depends on

The routine at $1020 stores a value at $40BB, takes its low half back from $40BB, and takes its high half from $400B.

$1020  STA $40BB
$1023  LDA $40BB
$1026  AND #$0F
$1028  STA $1009
$102B  LDA $400B     ; not $40BB
$102E  AND #$F0

$400B is not a variable. It is the second byte of an STA $07FC in the code at $400A, and it reads $FC in every snapshot of the game. So the high half always comes back as $F0. The caller, $A97C, asks whether Mr Hat stands at a given spot, and its flag byte's high half says whether the spot is on the right half of the screen, past X 255. It compares the returned value with $10, which never matches, so the check of the X high bit at $A986 never runs.

Of the 42 spots the game tests this way, 18 pass the flag $01, which never asks for the check. The other 24 pass $10 or $11 (one of them, $AB47, only on two of its three paths), but 23 of their callers have already tested the X high bit themselves (through $1200) and chosen a half. Four call only when Mr Hat is on the right half, and behave the same with or without the slip. Nineteen call only when he is on the left half: they match there only because the check never runs, and with the slip fixed they could never match. One more, $AB47, is not gated. So the slip is load-bearing, and what the flag was meant for is open.

A second slip is a store that lost its index. $18B3 writes STA $2BF8 inside a copy loop, where its twin at $916A has STA $35D8,Y, so that drawing puts each 48-byte row of it into a single byte.

10 · Leftovers

Secret: Lupenio is still inside

Chiola and Andrea Cucchetto wrote Lupenio for the publisher SIPE before Mr. Hat, and players have noticed that the two share rooms and jumps. The image shows how much: Lupenio's text, its keys and doors, and its ending are all still in memory.


    

Nothing prints either text. The only pointer to the ending is a pair of immediate loads at $7E19 and $7E1D, inside a routine that plays a tune, prints the text and jumps to $8000, which waits for F1 and restarts with a bonus. That routine is reached only from a jump at $7CF7 that follows an unconditional jump elsewhere. It also calls $A000, which is now all zeros. Live code still writes into the text: losing the last life sets the '2' of "200.000 PUNTI".

"Each key opens one door and one only" survives as code too. Room 9 keeps two doors that test for keys carried in from rooms 6 and 8, and a 20,000-point treasure. Their tests look for colours that nothing ever writes: the calls that drew them were replaced with INC $D022, and the treasure's colours go to $D022, a register that does nothing in the hires bitmap mode the game plays in. The image has 119 writes to $D022 in all, several of them where a colour store or a call belongs. Who switched them off is unknown. They are in the copy the magazine shipped.

Room 9 with the light on, drawn from memory twice: as the game sets it up, and with five instructions put back, the two fills (JSR $56ED at $71CF and $794A) and the treasure's colour stores at $73CF-$73D9, sent to the cells the room's own tests read ($06A3, $06CB, $06F3, two columns each). The doors' and the treasure's shapes were in the bitmap all along, drawn in colours that hide them. Both frames match the emulator's picture in every pixel. Which instructions were there before is a reconstruction; whether the room plays with them back was not tried.

11 · The end

Secret: in this copy the Golden Hat needs nothing

The Golden Hat is a 3×3-cell bitmap at $7C00, drawn at the bottom left of room 11. By design, reaching it takes an object from room 5. In this copy that object cannot be taken, and the game can be finished without it.

WONDERFUL / YOU HAVE FINISHED YOUR MISSION

The end screen in VICE, reached with Mr Hat carrying nothing ($F5 = $81). He was set on room 11's bottom floor and walked left; the route there by play was not tried.

Room 11's rules ($8265) push Mr Hat back to the right on the bottom floor unless he is at X $B8 or more, or the block at colour cell $061A is open ($CC). Carrying room 5's object ($F5 = $EE, set at $5CD7) opens the block and is worth 10,000. On the floor to the left of X $80, $7CC0 hands the interrupt back to the KERNAL, sets $1018 and runs the title routine, which sees the flag and draws "WONDERFUL / YOU HAVE FINISHED YOUR MISSION" ($BFA8, text at $B7D8) to the title tune, waits for fire and starts again.

Two of the switched-off colour stores decide it. Room 5's set-up stores the colour $2C that the object's pickup tests for into $D022 ($586B) instead of the object's cells, so the cell stays the corridor's grey and the pickup never fires. Tried live: standing on the spot with the stick down took nothing, and with that one cell poked to $2C the object was taken at once. Room 11's set-up loads the parameters for filling the block and never calls the fill, so its cell keeps the corridor's $CC, which is what "open" looks like. The two cancel out.

12 · Odds and ends

A music switch, a monitor and a frozen game

F1 switches the in-play music off and on. $7C70, at the end of every room's interrupt, flips $1019 when the KERNAL's key byte reads F1. While the flag is set, the interrupt stops short of $8C33, which plays the in-play tune. The guardians keep moving. The tune and its silent twin are in section 03.

A machine-code monitor rides along. $97ED-$9FFF is Jim Butterfield's Supermon, 2,067 bytes with its fifteen commands, patched so that its start-up call to SETMSG also sets $01 back to $36. No instruction outside it refers to it and no vector points into it.

The game here is a snapshot. The magazine's disk holds it as a freezer backup: a freezer, typically a cartridge, stopped the game on its title screen and saved memory, and a depacker in front of it restores the video and sound chips, the timers and colour memory, then returns into the title's fire loop at $1773. The game's own start is still there, a BASIC line 10 SYS 2157 at $0801, and restarting at $086D rebuilds the same machine, except that the title set-up then copies the damaged font of section 13, so even the first title shows the broken I. Section 14 has the disk.

13 · Bug

Bug: after the first game, the title's I breaks

Play one game to the end and the title comes back with a broken I in "WITH", "SNAILY" and "KNIFFY". The game never writes to its font. The damage was already in the copy the magazine shipped, and the first title hides it.

The title's letters are two cells high, drawn from a font kept at $CE00-$CFFF. Every time the title is set up, $CDC0 copies the whole font to $2800, where the video chip reads it. In the image, 14 bytes of the source are wrong: $CE48-$CE55, the top half of the I and most of the J's. The copy at $2800 still holds the letters. Someone set up the title, then something wrote over those 14 bytes, and the freezer saved both.

So the first title, which the freezer restores as it was, is right. Start the game cold from its entry instead, and the title set-up copies the damaged font at once. After a game over, $4475 returns to the title routine, $CDC0 copies the font again, and the damaged bytes reach the screen. The end message goes through the same set-up, so a player who finishes the game reads "YOU HAVE FINISHED YOUR MISSION" with all four I's broken. The title has no J.

Nothing in the game writes to the font: no instruction stores to $CE00-$CFFF, directly or through an index or a pointer. In the emulator, a store checkpoint on the font page caught nothing through a whole game, and the next title showed the broken letters. Who or what wrote the 14 bytes before the freeze is unknown.

The title screen as it first appears

The first title.

The title after a game over, with broken letters

After a game over.

14 · The copy studied here

A magazine disk, a frozen game, and a fixed version by botowrap

The copy studied here is side B of the disk of Commodore 64 Club issue 14, which reprinted Mr. Hat with Hawk Mission, Dalto and a Sprite Scanner utility. Issue 6, in September 1988, had carried it before; that copy was not examined.

The disk's directory has a small loader for each game, MR HAT, HAWK MISSION and DALTO, which differ only in the two letters of the file they load: MH, HM, DA. Each one blacks out the screen, installs a fast loader with its drive code kept under the I/O area, prints "MH",8: behind four spaces at the top of the screen, and puts HOME and shifted RUN/STOP into the keyboard buffer. Back at BASIC, the cursor goes home and shifted RUN/STOP types LOAD over the spaces, then RUN. MH is the frozen game of section 12, and DA starts with the same depacker.

The analysis began from a tape image in the GameBase collection. Its one file is MH byte for byte, and both give the same 64 KB of memory at the game's first instruction, so every address on this site holds for the disk.

A fixed version by botowrap unpacks the game and starts it at its own entry, $086D, rather than resuming a frozen title. Compared with the disk's game restarted the same way, no instruction differs. Two graphics do. The 14 font bytes are put back, equal to the clean copy at $2848, and after a game over the title stays right. The ladder gets new side rails: $4802, the one 24-byte row that the ladders of rooms 2, 3, 5, 6, 8, 9, 10 and 11 are copied from.

The original's side cells change from row to row and draw ragged rails with stray pixels; botowrap's are three straight rails a side, with the rung carried through them. That pattern is nowhere in the original, so it is a redraw. Whether the original's ladder was damaged, like the font, or drawn that way is open. Nothing in the game writes to it, and any damage would have had to spare the rung's 8 bytes between the two side cells.