1988 · Systems Editoriale (Commodore 64 Club)

About this page

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.

Footprint

Every byte of the C64's 64 KB, one pixel each, 512 to a row. Lit pixels are what this game is: its code, graphics, level data, sound, text, tables and variables, exactly where they sit in memory. Dim areas are screen and working memory; dark is unused.

WhatBytesOf 64 KB
Program42,98265.6 %
Code30,55046.6 %
Graphics5,1637.9 %
Level data10.0 %
Sound4,0506.2 %
Text1,0831.7 %
Tables1,9363.0 %
Variables1990.3 %
Screen, bitmap, colour, stack, I/O13,31220.3 %
ROM the game runs under8,19212.5 %
Unused1,0501.6 %

Status

Tiersilver
Coverage100 % of the bytes the game uses have a description
Build analysedCommodore 64 Club issue 14, disk side B (a freezer backup of the title screen)
Copyagent-draft
Toolshost: Linux 6.8 x86_64, Ubuntu 24.04 desktop with sixteen cores; the emulator ran under xvfb-run (no display in the agent's shell), emulator: VICE, release v3.13.1, v3.13.1-linux-x86_64-gui.zip, MCP on port 6511 (KIT_VICE_PORT); 6512 for the comparison of versions on 4 October 2026, disassembler: regenerator2000 0.9.20, python: 3.12.3, node: 20.19.5, subagents: nine annotation agents on disjoint address ranges and one page verifier, all claude-opus-5-5; one research agent for the web sources only, on the Agent tool's `sonnet` alias, exact model id not stated, widget tests: node 20.19.5: the title tune's port checked against the game's player in kit/c64/cpu6502.js, write by write (work/music-test.js); the point adders run in the simulator (work/scoretest.js), browser check: Chromium headless shell 1243 (Playwright's cache), a full-page screenshot of the built page
Modelclaude-opus-5-5
Kit version0.0.46

Contributors

Other places to love this game

What the game does, and where we found it

Read this before annotating code. What the game is documented to do, with verification status against the binary. Statuses: open (documented, not found yet), traced (in the code, could not be exercised; say what was tried), confirmed (in the code, consistent with the emulator), live (observed directly), differs (the code does something else). "Absent" is not a status.

Sources, all read on 30 September 2026 (work/research.md has the notes, source by source). No C64-Wiki page exists for the game (English and German both 404), and no manual beyond the magazine's blurb was found.

Features

FeatureStatusWhere
Joystick in port 2livethe title waits for $DC00 = $6F at $1770; every room loop reads $DC00
Fire on the title starts the gamelive$1770-$1788
Title screen "SYSTEMS PRESENTS A NEW GAME WITH": Mr Hat, Octopus, Snaily, Dynky (so spelt), Kniffy, "and all others"live$B683 draws it from the screen codes at $C000-$C058; reference/title.png
Title musicconfirmedthe player $C080-$C373 from the title's interrupt $C0AF; register activity seen, no sound in the session
Walk left and rightlive$5340/$5370 and each room's copies, about 2.4 pixels a frame
Fire jumps, the way Mr Hat faceslivefrom standing in room 1, fire held: sprite Y 204 to 183, 13 frames, back, again while held; $DC00 = $6F at $438D and in every room loop but room 10's (a ladder loop); three phases of 21 steps
Stick uplivedoes nothing on a floor (20 frames held in room 1); climbs ladders and rides lifts ($4B20, $4000, $8265)
Stick down: crouch, climb down, take a treasuretraced$7D compared in the room loops and in $8E10, $B100-$B4BB; not tried live
Touching a guardian kills ("everything you touch kills you", Lemon64)livein room 1, Mr Hat sank into the floor and restarted at the room's entry (reference/death.png, reference/room01-respawn.png); $D01E read as exact values at $55B0, death $A877
Deadly spots in the roomstraced$BB10, by position and exact standing height; room 6's dark-only hazard
Lives, four marks at the bottom rightlive$07B9, $07BA, $07E1, $07E2: one recoloured to $CC per death (by the code, two for a death in room 3; not tried); after five deaths in room 1 the title came back
Game overliveafter the last life $4475 returns to the title, which waits for fire for a new game; there is no game-over screen of its own
After a game over, the title's I is brokenlivethe title set-up $CDC0 copies the font again from $CE00, whose $CE48-$CE55 are damaged in the image; the I in "WITH", "SNAILY" and "KNIFFY", and in the end message, shows noise in its top half (reference/title-after-game-over.png, reference/end-screen.png); botowrap's fixed version puts the bytes back (facts.md, "Versions")
Status line: SCORE, ROOM, STAGElivebitmap rows 23-24, glyphs at $1600; reference/stage1-room1.png
Score in thousandslive$41DA/$8AD0 step the thousands digit; the 1,000, 10,000, 25,000 and 75,000 adders run in the simulator gave exactly those scores (work/scoretest.js); the 20,000 and 50,000 adders by the code
Eleven rooms in four stages (web screenshots reach ROOM 10, STAGE 4)liverooms 1-11 drawn by starting each set-up (reference/room02-setup.png to room11-setup.png); stage 1 room 1, stage 2 rooms 2-5, stage 3 rooms 6-9, stage 4 rooms 10-11 (rooms 4 and 7 keep the STAGE digit of the room before, so started from room 1 they show STAGE 1)
Room 1: three floors and a LIFTtracedthe lift ride $4000 moves Mr Hat and sprite 5 56 pixels a floor; not ridden live
Ladderstraced$4B20; rooms 2, 3, 5, 6, 9, 10, 11, and room 8's shaft
Guardians: Octopus, Snaily, Dinky, Kniffy and otherslivethey move in room 1 (sprites 0, 1, 7); each room's IRQ moves its own (facts.md, "Guardians")
Treasures worth pointstraced$8E10, $B100-$B4BB: 10,000 to 75,000 each, taken with the stick down
Keys and doors (Lupenio's text: "each key opens one door and one only")tracedroom 9's two doors, which test for the objects carried from rooms 6 and 8, can never open: their fills were patched out (facts.md, "Leftovers")
Colour-coded switches opening barriers in other roomstraced$B2E0-$B4BB, five switch and barrier pairs (facts.md, "Barriers and switches")
The candle lights the dark roomsliverooms 6 and 9 dark with $22 = 0, lit with $22 = $40 (reference/room06-lit-setup.png, room09-lit-setup.png); $5519 sets it when room 2's candle is taken (traced)
Immunitytracedthe objects of rooms 3 and 7 call $1250, which writes RTS over the death $A877 and the life loss $4C52 until $100F reaches $FE
The Golden Hat, the goal, and the endlivedrawn in room 11 ($7C00, $7C50); $7CC0, with Mr Hat level with it on the bottom floor, anywhere left of X $80, shows "WONDERFUL / YOU HAVE FINISHED YOUR MISSION" ($BFA8, $B7D8) and starts a new game. Seen live (reference/end-screen.png, work/room11win.py), with Mr Hat placed on that floor carrying nothing. By design the way needs room 5's object to open a block; in this copy that object cannot be taken (tried live), and the block is open from the start because its fill was patched out (facts.md, "The end")
RUN/STOPtracedthe game never calls the KERNAL's STOP; the vector at $0328 holds the KERNAL default $F6ED in every game snapshot. The tape's loader writes $E1 to $0328 ($A220), but the freezer's restore puts the saved value back

Beyond the documentation

Found in the code, not in the manual.

Open questions

How the analysed state was reached

How to get from the contributor's own copy to the analysed state. Someone else must be able to follow this exactly.

The image

mr hat (original).D64 (174,848 bytes, a 35-track disk without error bytes; SHA-256 49d5f88c98dff47d0a18055f3072a62c773499d51a2f0ec7b1d8c9e41d314d61, MD5 7059c4b03ecfe42cf2db70eb72c79c96), the contributor's own copy, in work/original.d64. The disk is named COMMODORE CLUB, ID 64, and its directory holds seven programs: three loaders of 5 blocks, MR HAT, HAWK MISSION and DALTO, the 7-block SPRITE SCANNER, and the three games they load, HM (189 blocks), MH (114) and DA (109). That is the side B of Commodore 64 Club issue 14 that the German C64-Wiki lists (read 4 October 2026: "Seite B: Mr Hat, Hawk Mission, Dalto, Sprite Scanner"), the magazine's second printing of the game; issue 6, the first (September 1988), was a disk with a COVER menu and other programs, and no copy of it was examined.

MR HAT loads at $0801 (1,253 bytes, SYS 3223). It blacks out the screen, installs a fast loader (drive code kept under the I/O area at $D000, the KERNAL's LOAD vector $0330 pointed at $0144), prints "MH",8: at the top of the screen behind four spaces, and puts HOME and shifted RUN/STOP ($13, $83) in the keyboard buffer: back at BASIC, the cursor goes home, shifted RUN/STOP types LOAD over the spaces with a RETURN and then RUN. The three loaders are the same file but for the two letters of the name ($0CCA-$0CCB).

MH loads at $0801-$78F9 (28,921 bytes); its BASIC line is 1001 SYS2066. It is a freezer backup (kit/skills/c64/c64-reference, "Freezer-cartridge backups"): a packed image of the running game, saved while it sat on its title screen and repacked with a depacker of its own. So the magazine shipped the game as a frozen image. The original program is still inside it: at $0801 the unpacked image holds the game's own BASIC line, 10 SYS 2157 followed by the text SYSTEM EDITOR<<<E **, and SYS 2157 is $086D, the game's entry (below). Who froze it is unknown; no intro, trainer or credit appears on screen. DA starts with the same depacker (its first 43 bytes are MH's), HM with another.

The analysis was first made from mrhat.t64 (29,017 bytes, SHA-256 1825d07c0490dd00191599178e403336a0048749c751a45bbe1599ab0c5f875b), a T64 tape archive that the contributor took from the GameBase collection, whose name field reads ASS PRESENTS:. Its one program, MR. HAT, is MH byte for byte, and the two give the same memory: started from the disk and stopped at $1773, the machine's RAM equals handover.vsf's in all 65,536 bytes, so the listing, built from that snapshot, is the disk's. Everything below holds for both.

From power-on to play

  1. Power-cycle the emulator (vice_machine_reset, mode: hard), resume it, and wait for READY..
  2. vice_autostart work/original.d64 (the first program, MR HAT; the directory's first entry is an empty separator). The loader runs, LOAD "MH",8 and RUN follow by themselves, and the depacker starts. Autostart turns warp mode on; turn it off (vice_machine_config_set, WarpMode 0). work/mrhat.t64 gives the same machine: VICE loads the tape file through its traps and types RUN.
  3. After about fifteen seconds of unpacking, the title appears: "SYSTEMS PRESENTS A NEW GAME WITH" over the cast (Mr Hat, Octopus, Snaily, Dinky, Kniffy, "and all others") with music.
  4. Fire on joystick port 2 starts play. The title waits in a loop at $1770 for $DC00 to read exactly $6F (fire alone). Room 1 of stage 1 appears at once, in bitmap mode, with SCORE, ROOM and STAGE on the bottom line and a LIFE panel on the right. The stick moves Mr Hat (hardware sprite 4) along the bottom floor.

work/versions/bootcmp.py does steps 1 and 2 for any of the three copies and stops at the game's first instruction ($1773 for the disk and the tape, $086D for botowrap's fixed version, which starts cold); work/boot.py is the tape's. Snapshots in work/, each saved without ROMs:

FileState
handover.vsfa stopping checkpoint on $1770-$1776 after the freezer's resume, from a power-cycled machine: the game's first instruction, $1773, with the stack it was frozen with. The disassembler and the listing are built from this one.
restart-title.vsfdespite its name, not a restart: a stop at $1773 that never passed the title set-up $CDC0 (a real restart copies the damaged font to $2848; here $2848 is clean), differing from handover.vsf only in $00A2 and $C438, two counters
versions/d64-restart.vsfthe real restart: the disk's machine, PC set to $086D and SP to $F6, stopped again at $1773 after the title set-up ran; differs from handover.vsf in $2848-$2855 (the damaged font, copied) and $C436 (a music counter) only, outside zero page, the stack and the RAM under I/O
versions/d64-entry.vsfthe same stop, reached from the disk: identical to handover.vsf in all 65,536 bytes of RAM
title.vsfthe title screen, running
play-room1.vsfroom 1 of stage 1, a second of play
entry.vsf, entry2.vsf, resume.vsfthe depacker at $0690, the freezer restore at $0948, and the first IRQ after the resume; for the loader only

The emulator was vice-mcp v3.13.1 (release zip, Linux x86_64, under xvfb-run), PAL, 6581 SID. check-emulator on 30 September 2026: 56 of 57 passed; warp failed (78 passes a second in warp against 51 at normal speed, where the check wants over 100). Nothing below depends on warp.

Steady state

The game keeps the KERNAL and I/O banked in: $01 reads $36 in the title and in play (RAM at $A000-$BFFF, I/O at $D000, KERNAL at $E000), and it hooks the KERNAL's IRQ vector. On the title $0314 holds $C0AF (the music), in play $1C00, which jumps to $AAB2. The RAM copies of the hardware vectors at $FFFA-$FFFF are zero, which is harmless with the KERNAL banked in. The video chip uses bank 0 ($DD00 = $C7): on the title, text mode with the screen at $0400 and characters at $2800 ($D018 = $1B); in play, bitmap mode ($D011 = $3B) with the bitmap at $2000 and colours at $0400.

Compared byte for byte with handover.vsf, play-room1.vsf differs in the screen ($0400-$07FF), the bitmap and the title's character set ($2000-$3F4A, redrawn by the room), zero page, the stack, and a few scattered variables ($100C, $1371-$1383, $1C12, $1E06, $41DD-$4261, $4ACD, $64F0-$64F9, $8C58-$8C64, $C434-$C438). The program is not reloaded: the game is one file, and no JSR or JMP to the KERNAL's LOAD ($FFD5), SETLFS or SETNAM is in the image. Because play overwrites the title's character set, the hand-over is the image to read, not a play snapshot.

No page of handover.vsf holds VICE's $00/$FF power-up pattern. The all-zero ranges are $2000-$27FF and $2A00-$3EFF (the bitmap, filled by play), $A000-$A0FF, and $D100-$FFFF, which lies under I/O and the KERNAL. A restart from $086D (versions/d64-restart.vsf) rebuilt the same memory but for the font's copy and a music counter, so the freezer lost nothing the start-up needs; whether it lost anything the game reads later is checked with store and execute checkpoints on those ranges during play (features.md).

The loader, in a paragraph

SYS 2066 runs $0812, which copies a depacker to $00FA-$01A0 and $0334-$03D9 and runs it, unpacking the image upwards from $0801 to $A231. A stub at $A220 sets the STOP vector's low byte ($0328 = $E1, so RUN/STOP is ignored), prints CHR$(142) and CHR$(8) (upper case, case switch locked) and jumps to $081B, a second depacker that banks everything to RAM ($01 = $34) and runs a byte-stream decoder in zero page ($0008-$00B4, bytes XORed with $12). The stream calls out to $0690 (in what becomes screen memory), which checks two marker bytes on the stack and goes on to $0948: the freezer's restore. It copies $0200-$05FF into colour RAM, $0607-$0635 into the VIC registers, $0637-$0653 into the SID and $0660-$067F into the two CIAs, restarts the decoder for the rest of memory, and ends in a routine on the stack page ($01C4-$01EA) that copies zero page back from the RAM under the I/O area, sets $00 = $2F and $01 = $36, and returns with RTI to $1773 with A = $7F, X = $50. The game resumes in its title's fire loop, called from $16EE in the title routine $16A3, which $0876 calls from the entry $086D, which BASIC's SYS called.

The symbol map for this game is symbols.json; the listing behind the Source tab is listing.json. Write-ups, facts and symbol maps are CC BY-SA 4.0. The game itself is not hosted here.