Dungeon Master II: Skullkeep Technical Reference
Status reviewed 2026-09-12. DM2 has bounded source-owned routes from DOS, Amiga, FM Towns and Macintosh real media. Full campaign parity, native non-DOS saves and some combat/UI owners remain active work.
Scope
DM2 V1 follows skproject, DMWeb format notes and the retained disassembly
evidence. It is independent from the DM1/CSB compatibility path. Each
edition requires its own authenticated data pair. The Japanese FM Towns
edition retains its own disc as its only data owner: a GDAT-keyed localisation
bridge supplies canonical text for the selected language and never requires a
PC-English GRAPHICS.DAT companion.
Verified real-media launch matrix
The following checks use the supplied original ZIPs directly in bounded memory. They do not extract a game installation, invoke an emulator, or replace unavailable source material with generated art. They establish native boot/menu/new-game and the listed bounded runtime path; they are not a claim of complete visual or gameplay parity.
| Edition | Verified native route | Bounded runtime evidence |
|---|---|---|
| DOS English | CLI boot, M12 admission, M11 new game | pit render, spell cast, SKSAVE1 resume/WIELD, archive resume, all 30 archive members and PAL8/PCM streams |
| DOS French | CLI boot | authenticated French archive admission |
| Amiga | CLI boot, M12 admission, M11 title/new game | source title and entrance/new-game route |
| FM Towns Japanese | CLI boot, M12 admission, M11 title/gameplay | packed media, title, menu selection and bounded movement |
Focused real-media cases cover the stated boundaries. A passing startup or runtime slice is not a visual-parity claim: title palette/timing, menu handoff, HUD, viewport, mouse/touch input, audio and dungeon composition each need their own edition-owned evidence. Macintosh DM2 demo support is intentionally absent; it is not a fallback for any of the routes above.
Boot and GDAT
An incomplete profile remains at the launcher and does not clear the viewport or paint generated floor/ceiling art. The boot receipt records source identity, typed GDAT sections, title/menu, HUD, dungeon, and no-fallback readiness.
The GDAT pipeline exposes dtPalIRGB, dtPalette16, dt07 interface/title
records, Rect14 placement, map GRAPHICSSET values, and map-chip assets. The
viewport resolves raw GDAT addresses before decode. Missing mandatory material
is a no-draw receipt, never a substitute. Wall cache keys include graphics
style to prevent material leakage between maps.
Runtime
M10 owns party, door, item, creature, projectile, actuator, and dungeon state. The viewport consumes typed plans. Outdoor routes pass the active source sky, ground, and weather state; indoor routes are clear. Rain, mist, and thunder do not create procedural pixels without a verified original overlay asset.
Feature queue status (Q-DM2-01 through Q-DM2-10)
The ten DM2 feature lanes have focused coverage:
| Lane | Scope | Evidence |
|---|---|---|
| Q-DM2-01 | GDAT core renderer | 58 GDAT source files, 76 tests (69 wired), 100% pass |
| Q-DM2-02 | GDAT material families | Wall tiles, door variants, stairs, pit, palette, material pairs tested |
| Q-DM2-03 | Creature renderer | 22 creature tests pass |
| Q-DM2-04 | G1 map and c_record runtime | 19 G1 tests pass |
| Q-DM2-05 | SKSAVE interop | 4 save tests pass |
| Q-DM2-06 | Menu, title and audio | 5 startup + 2 menu + 4 sound tests |
| Q-DM2-07 | Party, inventory and spells | 5 spell + 1 champion tests |
| Q-DM2-08 | Creature AI and combat | 3 combat + 7 projectile tests |
| Q-DM2-09 | CCM and world scripts | 5 CCM tests pass |
| Q-DM2-10 | Outdoor scenes and end-to-end play | 3 outdoor + 13 weather tests pass |
The work continues as continuous lanes (Lane A through E) rather than discrete queue items. Active lanes:
- Lane A — SkWinCore symbol audit. Closes
MISSINGrows indocs/reference/audits/SKPROJECT_DM2_NAMED_SYMBOL_AUDIT.tsvin small batches, source-locking eachskproject/SKULLWINsymbol againstSKWIN/SkWinCore.cppandSkGlobal.cppbefore implementation. The current disposition is the TSV itself; do not copy a historical row count into a status summary. - Lane B — Audible playback backend.
dm2_v1_sound_bind_gdat_loader()wiresDM2_PLAY_MUSIC,DM2_PLAY_SOUND, andDM2_QUERY_SND_ENTRY_INDEXto real GDAT sound data with an SDL3 mixing backend (6000 Hz U8 mono stream, additivesdlAudMix-shaped mixing). M11 binds the described backend immediately after an authenticated DM2 boot handoff, before a resume or new-game route can publish live runtime state; failed boot does not bind it. See DM2 GDAT Internals for the PCM decode and voice-allocation detail. The remaining work is broader source-capture comparison and platform-specific audible behavior, not the M11 binding itself. - Lane C — Real-data startup/dungeon gate repair. Fixed the DM2
real-data gate tests (2 failing as of v3.0.181, was 13) by refining the
g1_w0_chains_disabledflag: real PC G1DUNGEON.DATdisablesw0chain traversal (proven game data, not next-links), while synthetic skproject test fixtures preservew0chain traversal so existing fixture-based tests keep working.record_graph_completeis now enabled for skproject-loaded fixtures, unblocking wall-gfx/actuator/3D93B chain traversal in those fixtures. - Lane D — Creature/cloud real-data passes. Source-locked the
_4976_5aa4occupancy grid andDRAW_FLYING_ITEMselection rules againstSKWIN/SkWinCore.cpp(QUERY_CREATURE_5x5_POS,DRAW_STATIC_OBJECT’s occupancy walk,DRAW_FLYING_ITEM) andSkGlobal.cpptables. See DM2 GDAT Internals for the creature V5 animation chain and occupancy-grid detail. - Lane E — Real-data combat and drops mechanics. New
dm2_v1_drops_resolve_gdat_creature_drops()reads the eleven-entry per-creature drop table from real GDAT data and resolves proven drop words with RNG-gated selection, matchingSkWinCore.cpp’s creature-death drop route. Covers the defense route and combat-drop resolution path. The verified CREATURES→v1d296c AIDefinition defense byte is retained in the combat receipt, while the complete champion/hand/CMDSTR/RNG damage owner remains fail-closed. Tested bytest_dm2_v1_drops_gdat_real_data(skip-safe against real data).
DOS SKSAVE1 WIELD boundary
The supplied original PC-DOS archive contains the real data/sksave0 through
data/sksave3 .dat/.bak slots. Firestaff reads those members directly
from the ZIP; it does not unpack or rewrite them. The source-owned
SKSAVE1.DAT resume regression commits the original save and reaches one
real WIELD calculation with these recorded inputs:
item=0x140c creature=0x1116 power=26
dexterity=21 strength=48 skill=4
defense=170 armor=175 map difficulty=8 party power=11
result=miss, raw damage=0, final damage=0, applied HP damage=0
This is a useful ownership proof: the command, item, creature, stats and GDAT defense values are all read from the admitted original session. It is not a proof of a kill or a creature drop. The supplied route is a miss, and there is no matching original command/RNG trace for a hit; Firestaff therefore does not turn a generated command search into a retail death/drop claim. The post-death deallocation and drop path remains closed until an authentic input-to-CD/RAM trace supplies that missing evidence.
Source reference for all DM2 work: skproject
(SKULLWIN/SkWinCore.cpp, SkGlobal.cpp, plus the per-file c_*.cpp
modules named in the symbol audit).
Verification
cmake --build build --target test_dm2_v1_boot_profile_smoke \
test_dm2_v1_runtime_handoff_smoke test_dm2_v1_weather_no_synthetic_overlay \
--parallel
./build/test_dm2_v1_boot_profile_smoke
./build/test_dm2_v1_runtime_handoff_smoke
./build/test_dm2_v1_weather_no_synthetic_overlay
Real-data gate and lane-specific tests:
cmake --build build --target test_dm2_v1_drops_gdat_real_data \
test_dm2_v1_creature_occupancy_flying_item test_dm2_v1_sound_gdat_real_data \
--parallel
./build/test_dm2_v1_drops_gdat_real_data
./build/test_dm2_v1_creature_occupancy_flying_item
./build/test_dm2_v1_sound_gdat_real_data
For the GDAT record chain, interface tables, and host receipts, see DM2 GDAT Internals.