DM2 Reverse Engineering

Dungeon Master II: Skullkeep (DM2) is reimplemented in Firestaff at source-level parity against skproject, a reconstructed C++ decompilation of the original DOS/Atari-ST/Amiga/FM Towns codebase. This page indexes the skproject reference material, the corresponding Firestaff module registry, the hex-offset disassembly modules, the GDAT graphics format, DUNGEON.DAT differences from DM1, and the current symbol-audit and lane status.

Current Macintosh boundary

The large English retail ZIP is the supported Macintosh input. Firestaff reads it in memory, preserving its HFS layout and resource ownership. This is a real-media route, not complete Macintosh playability: GAME_LOAD/Resume, the dynamic Control/Event pointer-drag owner, full MIDI scheduling and Japanese/French runtime proof remain open. The platform status matrix is the canonical per-platform summary; DOSBox SKSAVE files are DOS evidence and must not be presented as Macintosh saves.

1. skproject Source File Map

Firestaff comments and headers cite skproject .cpp files as their source of truth. The list below was generated with:

grep -roh 'c_[a-z_]*\.cpp' src/dm2/ include/dm2_* | sort -u

56 distinct skproject files are referenced across src/dm2/ and include/dm2_*. The reference count is the number of times the filename appears in Firestaff source/header text (a rough proxy for how many Firestaff modules cite that file).

skproject file Subsystem References
c_ai.cpp Creature/monster AI decision logic 764
c_record.cpp Dungeon record graph (linked records, DBn types) 271
c_creature.cpp Creature instance state and behavior 271
c_tim_proc.cpp Timer/event process handlers 256
c_querydb.cpp GDAT/record query database (QUERY_* accessors) 248
c_hero.cpp Champion/hero state and stats 151
c_gui_vp.cpp Viewport GUI rendering 137
c_events.cpp Event dispatch/queueing 121
c_weather.cpp Outdoor weather simulation 86
c_gui_draw.cpp GUI drawing primitives 78
c_gfx_str.cpp Graphics string/text rendering 74
c_sound.cpp Sound engine 65
c_moverec.cpp Movement record bookkeeping 55
c_timer.cpp Timer subsystem 54
c_gdatfile.cpp GRAPHICS.DAT file I/O 53
c_sfx.cpp Sound effects playback 52
c_item.cpp Item instance state 44
c_savegame.cpp Save/load serialization 40
c_map.cpp Map/level record management 38
c_xrect.cpp Extended rectangle math 37
c_light.cpp Lighting calculations 32
c_random.cpp RNG 28
c_gfx_decode.cpp Graphics decode (RLE/packed formats) 26
c_gfx_main.cpp Graphics subsystem entry points 25
c_gfx_blit.cpp Blitting routines 24
c_combat.cpp Combat resolution 24
c_loadlevel.cpp Level loading 23
c_image.cpp Image record handling 23
c_input.cpp Input handling 18
c_dialog.cpp Dialog boxes 17
c_move.cpp Movement mechanics 16
c_dballoc.cpp Dungeon-data block allocator 16
c_tmouse.cpp Mouse/text-mouse handling 15
c_cloud.cpp Cloud/weather objects 12
c_engage.cpp Engage command (spell/action triggers) 10
c_bkgrnd.cpp Background rendering 10
c_render.cpp Render pipeline 6
c_alloc.cpp Memory allocator 6
c_addon.cpp Add-on/expansion data 6
c_eventqueue.cpp Event queue 5
c_shop.cpp Shop/vendor logic 4
c_gfx_pal.cpp Palette handling 4
c_trigger.cpp Trigger objects 3
c_sensor.cpp Sensor objects 3
c_music_wav.cpp Music/WAV playback 3
c_mcursor.cpp Mouse cursor 3
c_keybd.cpp Keyboard input 3
c_gfx_bmp.cpp Bitmap graphics 3
c_clickrect.cpp Clickable rectangles 3
c_buttons.cpp Button widgets 3
c_actuator.cpp Actuator objects 3
c_npc.cpp NPC handling 2
c_gfx_pixel.cpp Pixel-level graphics ops 2
c_allegro.cpp Allegro host-layer shim 2
c_str.cpp String utilities 1
c_rect.cpp Rectangle math 1

Central reference files

Two files are not part of the 56-file per-module list above but are the two central skproject reference files cited pervasively across the codebase:

File Role References
SkWinCore.cpp Monolithic core: houses most of the hex-offset-addressed decompiled routines (_0aaf_*, _1031_*, _1c9a_*, _2759_*, _2e62_*, _0cee_*, etc.) that the symbol audit tracks individually 832
SkGlobal.cpp Global tables and constants (direction tables, shared globals) referenced by AI, viewport, and creature logic 24

2. Module Registry

src/dm2/ contains 271 source files (.c) implementing the DM2 runtime. They group into the following subsystems (grouping by filename prefix; a file may touch more than one area but is listed under its primary prefix).

Subsystem Prefixes Purpose
AI/creatures c_ai, c_creature, creature_ai_*, dm2_v1_ai_*, dm2_v1_creature_* Monster decision logic, spawn, occupancy, AI state machines
Combat c_combat, combat_damage, dm2_v1_combat_* Attack resolution, damage, wound/kill mechanics
Graphics/viewport c_gfx_*, c_gui_*, c_render, c_bkgrnd, dm2_v1_viewport_* Frame rendering, GUI drawing, background composition
GDAT data c_gdatfile, c_image, dm2_v1_gdat_* GRAPHICS.DAT record decode and typed-image access
Dungeon/records c_record, c_dballoc, c_querydb, c_map, c_loadlevel, dm2_v1_dungeon_loader, dm2_v1_record_pool_* Record graph, DUNGEON.DAT loading, query database
Champions/hero c_hero, champion_*, dm2_v1_champion_* Champion stats, state, and progression
Items/inventory c_item, c_shop, dm2_v1_item_* Item instances, inventory, shop transactions
Events/timers c_events, c_eventqueue, c_timer, c_tim_proc, dm2_v1_event_* Scheduled events, timer processes
Movement c_move, c_moverec, dm2_v1_move_* Party/creature movement and collision
Input/UI c_input, c_buttons, c_clickrect, c_keybd, c_mcursor, c_tmouse, c_dialog User input handling, dialogs, cursors
Audio c_sound, c_sfx, c_music_wav, dm2_v1_sound, dm2_v1_fmtowns_cdda_* Sound effects, music playback, CD audio
Sensors/actuators c_sensor, c_actuator, c_trigger, dm2_v1_sensor_* Dungeon sensor/actuator/trigger objects
Weather/outdoor c_weather, c_cloud Outdoor weather simulation
CCM scripts ccm_* Compiled Command/script (CCM) interpreter
Save/load c_savegame, dm2_v1_savegame_* Original-format DOS savegame read/write
Misc c_alloc, c_str, c_random, c_rect, c_xrect, c_light, c_npc, c_addon, c_engage Allocator, string, RNG, geometry, lighting, NPC, engage-command utilities

Verify current counts with:

ls src/dm2/*.c | wc -l          # 271
ls src/dm2/*.c | grep -c '^c_'  # skproject-named modules

3. Hex-Offset Modules

Three Firestaff modules are named after raw disassembly offset labels from the original SkWinCore.cpp binary rather than skproject’s own filenames. These labels come directly from the address ranges the reconstructed source uses for otherwise-unnamed static functions:

Firestaff file Offset label Notes
src/dm2/dm2_v1_0aaf_pc34_compat.c _0aaf_* GDAT 0x1a text-list builder, dialogue background routing
src/dm2/dm2_v1_1031_pc34_compat.c _1031_* Rectangle resolve and related UI-geometry helpers
src/dm2/dm2_v1_1c9a_pc34_compat.c _1c9a_* Creature AI pointer resolution and tile-lookup helpers

These correspond to symbol-audit families (e.g. DM2_0aaf_0067, DM2_1031_01d5, DM2_1c9a_02c3 in docs/reference/audits/SKPROJECT_DM2_NAMED_SYMBOL_AUDIT.tsv) whose source_file column reads SKULLWIN/c_0aaf.cpp, SKULLWIN/c_1031.cpp, and SKULLWIN/c_1c9a.cpp — skproject’s own naming for functions it could only address by original binary offset, not by a recovered symbol name.

4. GDAT File Format

Full internals are documented in docs/wiki/DM2-GDAT-Internals.md; summary:

5. DM2 DUNGEON.DAT Differences from DM1

DM2’s dungeon format (G1) diverges from DM1’s in ways proven by corpus analysis (DM2-001) rather than assumed from DM1 conventions:

6. Symbol Audit Status

Two audit files track skproject symbol coverage:

Current status breakdown in the named-symbol audit:

Status Count
IMPLEMENTED_PARITY 1,118
NOT_APPLICABLE_ARCH 560
NONAPPLICABLE 73

There are no rows currently marked MISSING in the audit — the backlog has been fully drained by successive Lane A batches. That backlog was large and tracked in TODO.md release notes; it shrank in stages: 899 → 891 → 883 → 867 → 851 MISSING rows across cycles 14–16, continuing through subsequent Lane A batches (c_querydb.cpp, c_1c9a.cpp, c_0aaf.cpp, c_1031.cpp) until zero MISSING rows remained. SYMBOL_DISPOSITIONS.tsv separately excludes symbols tied to host ABIs that Firestaff intentionally does not emulate: GEM AES trap ABI (68 rows), GEM VDI workstation ABI (23 rows), Amiga-host device/interrupt/display boundaries (22 rows), original exception/vector/assembly-stub entries (18 rows), and Atari ST/PRIM linker aliases (18 rows).

7. Lane Status

DM2 (and cross-game) work is organized into parallel development lanes, each tracked per-cycle in TODO.md/DONE.md:

Lane Focus
Lane A DM2 SkWinCore symbol audit batches — closing MISSING rows in SKPROJECT_DM2_NAMED_SYMBOL_AUDIT.tsv file by file (c_querydb.cpp, c_1c9a.cpp, c_0aaf.cpp, c_1031.cpp, etc.)
Lane B DM2 real-data audio/spell backends — e.g. DM2-008 GDAT sound backend, audible playback backend, DM2-007 spell handlers
Lane C DM2 real-data startup/dungeon/viewport work — boot/dungeon gate repair, DRAW_ITEM and viewport renderer expansion
Lane D Nexus (Sega Saturn) real-data gameplay — creature spawn/combat, HUD integration, altar/AI/sensors/door animation
Lane E Theron’s Quest (PC Engine) and DM2 combat/drops mechanics — real Track 02 object decode, multi-level progression, DM2 combat/drop follow-ups

Each lane commits on its own lane branch per cycle; cycles are numbered sequentially in TODO.md (recent entries around cycle 16–17). Lane assignments are not fixed to one game forever — e.g. Lane E has covered both Theron’s Quest object decode and DM2 combat/drops mechanics in different cycles.

8. FM Towns CD Audio

DM2’s FM Towns release uses CD-DA (Red Book audio) tracks for music instead of the DOS SONG.DAT/Adlib driver. Firestaff’s pipeline:

References