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:

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.