-
-
Notifications
You must be signed in to change notification settings - Fork 4
FMTowns Technical Reference
This page documents the FM Towns platform internals as recovered by Firestaff's byte-verified disassembly of all 11 shipping binaries across the three Dungeon Master FM Towns titles. Every address, size, and hash listed here is verified against the original disc images.
For per-game guides see DM1 FM Towns Guide, CSB FM Towns Guide, DM2 FM Towns Guide.
- Platform overview
- Disc images and real-data hashes
- Phar Lap 386|DOS-Extender binary format
- Real-mode bridge (fs:[slot] call sites)
- TBIOS integration
- Hardware I/O ports
- GRAPHICS.DAT container formats
- Cross-game byte-identical payloads
- SYM1 symbol tables
- Sound API (SND_* functions)
- CD audio track mapping
- Menu system internals
- Font system
- ISO 9660 disc layout
- Implementation status
Three Dungeon Master titles were published for the Fujitsu FM Towns:
| Game | Binary | Publisher | Year |
|---|---|---|---|
| Dungeon Master | EDM.EXP / JDM.EXP | Fujitsu (HMA-240) | 1992 |
| Chaos Strikes Back | CHTWE.EXP / CHTWJ.EXP | Victor Entertainment | 1990 |
| Dungeon Master II: Skullkeep | SKULL.EXP | Victor Entertainment | 1993 |
All three run as 32-bit Phar Lap 386|DOS-Extender protected-mode applications under TownsOS. They share a common runtime architecture: identical Phar Lap bridge layout, identical Watcom C runtime, and significant byte-identical data payloads across games.
| File | Size (bytes) | SHA-256 |
|---|---|---|
EDM.EXP |
310,518 | c888470d39aa449eac85438b598158492d2c981008cc6b427c52f2c73001ecb6 |
JDM.EXP |
290,221 | 1db4f049def0eef52a20a4758a1ce3e204f9f5a9ec04a57eef1245fdeede0bae |
TMENU.EXP |
235,476 | 0ab2833cc47651dfe40b85bbd0881a433b22f75819a4df5bbb13fdd80aba7dc1 |
DATA/GRAPHICS.DAT |
396,970 | d08049d026d8810cfcf9e6a898968bc74df98a3255de1402cc3884e245e03487 |
DATA/DUNGEON.DAT |
33,423 | 3c744aa501211fc202586e8ccbed2a02783fd52453ce49c9951bfafc4d4bcc58 |
| File | Size (bytes) | SHA-256 |
|---|---|---|
CHTWE.EXP |
283,936 | 7edbdd6f088eaa7a82afd8a78c5ae32c0b3be7e023d261419277ea588c183e0d |
CHTWJ.EXP |
284,416 | c2add7b7c152e1b7be50b407828807b7005bbd36e2b4b96dbc1dd51703d86da6 |
SWITCHTW.EXP |
90,456 | 8aee9553ce6827a97b972b1e8c6df373f1f36cf34d4fde280390d9d1fae6b020 |
ANIMTW.EXP |
124,161 | 92635f3d5d98df79aba14761ee0e5761d696ef31e8c5de0a263df4641d077388 |
TMENU.EXP |
243,212 | 902576b5ee48dba82ad62103079631e901bf11a5e588d615ae36c627d6cd7b7a |
UTILE.EXP |
152,387 | ca1d68453981f22e72f16247e2a097525350a8eda1c04224fe859d5fded1c073 |
CDATA/GRAPHICS.DAT |
402,274 | 08cceb0c7003da3f286dc5805748f7e391a65f2ad85099c3d9adb49afc4cc723 |
CDATA/DUNGEON.DAT |
2,098 | b9dbada2954a343edba05f5c0c1a58682db49261d7fb5da79d80f720271748ad |
CDATA/MINI.DAT |
42,776 | 37dc4397408d59b58b573f250b6da997a387f9e15966c1993ca5ada87641fb43 |
| File | Size (bytes) | SHA-256 |
|---|---|---|
SKULL.EXP |
374,416 | 068218bb31a7ed3700974394cbf11cb51c9a9da694511e748114b5dd7ee07671 |
TWANIM.EXP |
72,184 | f82e5332694b25764c6f904b800e737dcba9bece6b851dbc90c80b0a6934e9cd |
DATA/GRAPHICS.DAT |
2,783,791 | 634e70044d7ee8e845221b444c04061f0d9ff7c1493feb0f0426303f23733624 |
DATA/DUNGEON.DAT |
37,954 | d1d608a1d59aaba683a381f52613fa42af5a4be61d287f56fa3a4cdd4d8234b4 |
DATA/CD.DAT |
40 | 8352b17349219aa14f6bfb9dce8c459b5d602c7b71cb2c18a41dea088fa46783 |
All FM Towns executables are Phar Lap P3 level-1 32-bit protected-mode binaries.
Offset Size Field
0x000 0x180 P3 header (magic "P3", entry point, memory layout)
0x180 0x080 Reserved / alignment
0x200 ... Load image (flat-model code + data)
The load image starts at file offset 0x200. All vaddrs in the
project are relative to this load base. The entry point (init_eip)
is stored in the P3 header and varies per binary.
| Binary | Game | File size | Init EIP | SYM1 offset | SYM1 size | TBIOS calls | Total bridge calls |
|---|---|---|---|---|---|---|---|
| EDM.EXP | DM1 | 310,518 | 0x42a48 | 0x46b41 | 0x51b5 | 70 | 93 |
| JDM.EXP | DM1 | 290,221 | 0x42cb4 | — | — | 70 | 93 |
| TMENU.EXP | DM1 | 235,476 | 0x9408 | — | — | 70 | 92 |
| CHTWE.EXP | CSB | 283,936 | 0x2619c | — | — | 17 | 30 |
| CHTWJ.EXP | CSB | 284,416 | 0x26348 | — | — | 17 | 30 |
| SWITCHTW.EXP | CSB | 90,456 | 0x14a88 | — | — | 13 | 26 |
| ANIMTW.EXP | CSB | 124,161 | 0x1cfbc | — | — | 13 | 15 |
| TMENU.EXP | CSB | 243,212 | 0x18c2c | 0x33a92 | 31,610 | 26 | 49 |
| UTILE.EXP | CSB | 152,387 | 0xfe00 | — | — | 17 | 30 |
| SKULL.EXP | DM2 | 374,416 | 0x5741c | — | — | 17 | 29 |
| TWANIM.EXP | DM2 | 72,184 | 0x10470 | — | — | 13 | 15 |
All 11 binaries use the identical 4-slot Phar Lap bridge layout — a platform-wide TownsOS/Phar Lap runtime convention.
Protected-to-real-mode transition uses selector 0x110 (Phar Lap
real-mode data selector):
push fs
push 0x110
pop fs
call far ptr fs:[slot] ; opcode 64 ff 1d <disp32>
pop fs| Slot | Purpose | Typical calls/binary |
|---|---|---|
fs:[0x20] |
TBIOS (mouse/keyboard/timer/video) | 13–70 |
fs:[0x40] |
Phar Lap secondary dispatch | 0–20 |
fs:[0x48] |
Timing/exit (rare) | 0–1 |
fs:[0x80] |
Hardware init (rare) | 1–8 |
502 total call sites enumerated across all 11 binaries. Every
exact vaddr is recorded in
docs/fmtowns/pharlap_call_sites.json.
Key finding: A hosted BIOS integration needs only the 4 fs: slots
plus hardware port 0x04E9 to run game code. Every other real-mode
transition routes through these four dispatch points.
8 known TBIOS revisions, identified by 4× 8-byte string fields at fixed ROM offsets:
| ID | Version | Date | ROM offset |
|---|---|---|---|
| V31L22A | V31L22A | 1989-03-08 | 0x1F750 |
| V31L23A | V31L23A | 1990-09-21 | 0x1F3D0 |
| V31L31_90 | V31L31 | 1990-11-21 | 0x1F3D0 |
| V31L31_91 | V31L31 | 1991-10-05 | 0x100000 |
| V31L31_92 | V31L31 | 1992-10-16 | 0x100000 |
| V31L31_93 | V31L31 | 1993-01-07 | 0x100000 |
| V31L35 | V31L35 | 1993-10-15 | 0x100000 |
| V31L35_94 | V31L35 | 1994-12-03 | 0x100000 |
DM1 HMA-240 targets V31L31_92 or later. Reference ROM: FMT_F20.ROM (Fujitsu FM Towns II F20).
The fmtowns_bios_host.h contract:
-
Register bundle
fmtowns_bios_regs_t: eax/ebx/ecx/edx + esi/edi/ebp + ds/es/fs/flags -
Slot dispatcher maps
fmtowns_bios_slot_tenum (0x20, 0x40, 0x48, 0x80) -
Dedicated glyph fetch:
tbios_fetch_sjis_glyph(16×16 mono bitmap, caller-owned buffer ≥ 32 bytes) -
Fail-closed default: every slot returns
FMTOWNS_BIOS_HOST_UNBOUNDuntil a host is bound - Status codes: OK, UNBOUND, BAD_SLOT, BAD_ARGS, UNSUPPORTED, FAILED
Option A — Tsugaru subprocess (fmtowns_tsugaru_bridge.h):
- C-ABI vtable with init/shutdown + per-slot dispatchers + I/O port r/w
- Version-suffixed symbol prevents ABI mismatch
- Separate
libfirestaff_tsugaru_bridge.{dylib,so,dll} - Required:
init,shutdown,call_tbios - Optional:
call_secondary,call_timing,call_hardware_init,io_port_read_u8,io_port_write_u8
Option B — Minimal TBIOS shim (fmtowns_tbios_shim.h):
- Reads real FMT_F20.ROM via
fmtowns_tbios_shim_load_rom_pc34 - Validates ROM via "V" + digit / "towns" / "tbios" signature check
- Only populates
tbios_fetch_sjis_glyph— all other slots return UNSUPPORTED - ANK 8×16 glyphs at ROM offset
0x3d800(16 bytes/glyph) - JIS X 0208 16×16 glyphs at ROM offset
0x40000(32 bytes/glyph) - Standard Shift-JIS → JIS row/col conversion
| Port | Name | Used by |
|---|---|---|
0x04E9 |
SOUND_INT_REASON | All 8 game binaries (DM1 + CSB + DM2) |
0x0A0A |
RS232C_MODEM_CONTROL | TMENU.EXP (DM1) only |
0x3180 |
CMOS_BOOT_DEV_FLAG | TMENU.EXP (DM1) only |
0x3182 |
CMOS_DEF_BOOT_DEV_TYPE | TMENU.EXP (DM1) only |
0x3184 |
CMOS_DEF_BOOT_DEV_UNIT | TMENU.EXP (DM1) only |
Key finding: every non-launcher game binary across all three games
touches exactly one hardware port directly (0x04E9). All other
hardware access goes through the Phar Lap fs:[0x20] TBIOS dispatch.
| Port | Name |
|---|---|
0x600 |
TOWNSIO_KEYBOARD_DATA (polled scancode) |
0x602 |
TOWNSIO_KEYBOARD_STATUS_CMD |
0x604 |
TOWNSIO_KEYBOARD_IRQ |
Three distinct container formats identified by the first word:
| Game | Signature | Format | Asset count | File size | Record unit |
|---|---|---|---|---|---|
| DM1 | 0x023f |
Legacy | 575 | 396,970 | u16 size |
| CSB | 0x8001 |
Extended v1 | 728 | 402,274 | u32 record |
| DM2 | 0x8004 |
Extended v4 | 3,407 | 2,783,791 | u32 record |
Format flag: high bit of word0 — 0x0xxx = legacy (word0 is
asset count), 0x8xxx = extended (low 15 bits = version, word1 =
count).
+0 : u16 asset_count (575 = 0x023f)
+2 : u16 size_table[count] (per-asset byte size)
+2+2N : u16 size_table2[count] (mirror of primary)
+2+4N : raw payloads, back-to-back
INDEX_TO_FILE_OFFSET(i) = 2 + count*4 + sum(size_table[0..i-1])
+0 : u16 width_pixels
+2 : u16 height_pixels
Padded width: (width + 0x1f) & ~0x1f. RLE compression with 4 modes
driven by control-byte bits 7/6/5/4. Nibble packing is 4bpp.
Same layout as DM1 legacy but with a 2-byte signature prefix (0x8001)
before the asset count word. Parsed via dm1_v1_fmtowns_pic_library_open_pc34
with a 2-byte skip.
Container word 0x8004, 3,407 entries. 320×200 native resolution
(same as DOS VGA). DM2 DOS uses v5 (0x8005) with 5,624 entries.
Per-record layout differs from v1 and needs an independent decoder.
| Payload | Size | DM1 vaddr | CSB vaddr | DM2 vaddr |
|---|---|---|---|---|
| Menu font raster | 768 B | asset 557 | GDAT 0x50f1a | GDAT 0x2f5a3 |
| CHAR geometry (7 words) | 14 B | 0x26c8a | 0x2c94c | 0x1f6 |
| ICON geometry (4 words) | 8 B | 0x26c68 | 0x2c938 | 0x1de |
| SPELL_COSTS | 32 B | 0x24388 | 0x29f64 | 0x3bb0 |
| SPELL_MULT | 8 B | 0x243a0 | 0x29f7c | 0x3bc8 |
| Phar Lap 4-slot bridge | — | ✓ | ✓ | ✓ |
| Direct I/O port 0x04E9 | — | ✓ | ✓ | ✓ |
| Payload | Size | DM1 vaddr | CSB vaddr |
|---|---|---|---|
| OICON descriptor | 1,344 B | 0x224db | 0x27f77 |
| PLAYER_COLOR | 8 B | 0x291b8 | 0x2d164 |
| ICON_PAL | 6 B | 0x28f44 | 0x2cd8a |
| DYNA_BUTTONS pool | ≥ 500 B | 0x24194 | 0x29d50 |
- 9 ranges DM1-to-DM2 (largest: 32,015 bytes at DM2 file offset 0x006928)
- 10 ranges CSB-to-DM2
- All three link the same Phar Lap + Watcom C runtime + TownsOS glue blob
Phar Lap P3 binaries may contain a SYM1 debug symbol section appended after the load image.
+0 : 4 bytes "SYM1" magic
+4 : u16 version (0x000e)
+6 : u16 flags (0x0014)
+8 : u32 checksum
+12 : entries[]
Each entry:
+0 : u8 name_length
+1 : char[] ASCII name (Watcom C leading underscore)
+N : u32 LE vaddr
+N+4: u16 type (always 0x0001)
File offset 0x46b41, size 0x51b5 bytes. Key verified symbols:
| Symbol | Vaddr | Purpose |
|---|---|---|
_DRAW_DMENU |
0x4620 | Main menu renderer |
_DRAW_ICN_BUTTON |
0x44f0 | Icon button draw dispatch |
_GET_LABEL |
0x43e4 | Label pool walker |
_SND_INIT |
0x212db | Sound system init |
_SND_KEY_ON |
0x21367 | Sound key-on |
_SND_PCM_PLAY |
0x215d4 | PCM playback start |
File offset 0x33a92, size 31,610 bytes. Contains TownsOS launcher
symbols (CD_Drive_Reset, CHAR_SIZE, CARET_ONOFF) and Japanese
developer names (BED_hentai, zahyouXY) not present in DM1.
JDM.EXP, TMENU.EXP (DM1), all CSB game binaries, and both DM2 binaries have no SYM1 section.
36 byte-verified entry points recovered from EDM.EXP SYM1, at vaddrs in the range 0x212db–0x219c8.
| Function | Vaddr | Purpose |
|---|---|---|
SND_INIT |
0x212db | Initialise sound system |
SND_END |
0x21342 | Shut down sound system |
SND_KEY_ON |
0x21367 | Start a note |
SND_KEY_OFF |
0x21384 | Release a note |
SND_KEY_ABORT |
0x2143f | Hard-stop a note |
SND_PAN_SET |
0x21399 | Set stereo pan |
SND_INST_CHANGE |
0x213b3 | Switch instrument |
SND_INST_WRITE |
0x213cd | Write instrument data |
SND_INST_READ |
0x213ec | Read instrument data |
SND_PITCH_CHANGE |
0x2140b | Pitch bend |
SND_VOLUME_CHANGE |
0x21425 | Volume change |
| Function | Vaddr |
|---|---|
SND_FM_READ_STATUS |
0x21454 |
SND_FM_WRITE_DATA |
0x21461 |
SND_FM_WRITE_SAVE_DATA |
0x2147e |
SND_FM_READ_SAVE_DATA |
0x2149b |
SND_FM_TIMER_A_SET |
0x214bd |
SND_FM_TIMER_B_SET |
0x214d7 |
SND_FM_TIMER_A_START |
0x214f1 |
SND_FM_TIMER_B_START |
0x214fc |
SND_FM_LFO_SET |
0x21507 |
| Function | Vaddr |
|---|---|
SND_PCM_WAVE_SET |
0x2151c |
SND_PCM_MODE_SET |
0x2153b |
SND_PCM_SOUND_SET |
0x21550 |
SND_PCM_SOUND_DELETE |
0x21565 |
SND_PCM_REC |
0x2157a |
SND_PCM_REC2 |
0x215b0 |
SND_PCM_PLAY |
0x215d4 |
SND_PCM_REC_STOP |
0x215f6 |
SND_PCM_PLAY_STOP |
0x21601 |
SND_PCM_STATUS |
0x21616 |
SND_PCM_ABORT |
0x2162d |
| Function | Vaddr |
|---|---|
SND_ELEVOL_SET |
0x21940 |
SND_ELEVOL_INIT |
0x2195d |
SND_ELEVOL_READ |
0x21968 |
SND_ELEVOL_MUTE |
0x21991 |
SND_ELEVOL_ALL_MUTE |
0x219c8 |
No CDDA-specific SND_* functions — CD audio uses TBIOS CD-ROM system calls directly.
| Track | Assignment |
|---|---|
| 02 | Title screen / main theme |
| 03 | Hall of Champions |
| 04 | Unused |
| 05 | Entrance dungeon + map 6 |
| 06 | Maps 1–2 |
| 07 | Unused |
| 08 | Maps 3–4 |
| 09 | Map 5 |
| 10 | Map 7 |
| 11 | Maps 8–9 |
| 12 | Map 10 |
| 13 | Game Over |
| 14 | Map 11 |
| 15 | Map 12 |
| 16 | Map 13 |
| 17 | Maps 14–15 |
| 18 | Game Won / credits |
| 19 | Ambient / exploration |
| 20 | Silence (20 seconds) |
Uses dm2_v1_fmtowns_cdda_music with a CD.DAT lookup table
(40 bytes, SHA-256 8352b173...).
Poll-dispatch loop at vaddr 0x943b:
loop:
call SETUP2 ; 0x9aac
call POLL_RESUME ; 0x99ec
call POLL_MAIN ; 0xc8e0 (TownsOS input poll)
cmp [ACTIVE], 0 ; flag at 0x557c
je POLL_MAIN
call EVENT_DISPATCH ; 0xbfac
jmp SETUP2TBIOS_POLL at 0xa130 uses mov ax, 0x250f; int 0x21 (Phar Lap
real-mode switch) + call fs:[0x20] to poll TownsOS.
| Component | Address | Layout |
|---|---|---|
| Queue head | 0x5890 | — |
| Event records | 0x575c + slot × 8 | 8-byte records |
| Text pool | 0x3bca + 2 + slot × 10 | 10-byte entries |
| Handler table | 0x5510 + event_id × 4 | Function pointers |
| Field | Address | Size |
|---|---|---|
| Mouse X | 0x2e72 | word |
| Mouse Y low | 0x2e74 | byte |
| Mouse Y mid | 0x2e75 | byte |
| Mouse Y high | 0x2e76 | byte |
8-byte structure at EDM.EXP vaddr 0x2418c:
- Bytes 1–3: label indices for buttons 0–2 (
0xFF= disabled) - Panel colour selection: byte 3 == 0xFF → colour 0x4D; byte 2 == 0xFF → colour 0x4F; default 0x0B
NUL-separated pool at EDM.EXP 0x24194, walked by GET_LABEL (0x43e4).
44 real English entries (indices 0–43), 11 empty padding entries (44–54).
Japanese pool at JDM.EXP 0x243bc: 44 Shift-JIS entries (336 bytes vs
289 bytes English).
| Index | English | Japanese |
|---|---|---|
| 1 | BLOCK | sakegiru |
| 2 | CHOP | tatakikiru |
| 20 | FIREBALL | kaendan |
| 33 | SPELLSHIELD | jumonbougo |
224 × 6-byte records at EDM.EXP 0x224db. Byte 0 = KIND field:
0 = generic LOAD_ICON path, non-zero = THING_ICON path. 77
THING-classified, 147 generic. DRAW_ICN_BUTTON at 0x44f0 dispatches
based on this.
23 linked blocks, 994 total records. Head pointer at 0x28f08. Each
record: { u16 type, u16 parent, i16 a, i16 b }.
Key regions:
- Region 10: menu panel size (87×45 px, type=9 SIZE node)
- Region 11: clear-area anchor at (319, 77), parent=region 10
Scaling: GET_SCL_COORD: result = source * scale / 10000
| Symbol | Vaddr | Purpose |
|---|---|---|
| MENU_OWNER | 0x24156 | Current menu owner |
| NUM_DYNABTNS | 0x24158 | Active button count |
| REDRAW_MENU | 0x2415a | Redraw flag |
| MENU_ICONS | 0x2415c | Icon state |
| ARMR_OPTS | 0x24160 | Armour options |
| MSE_STATE | 0x25848 | Mouse hide depth counter |
| PICKING_CHARACTER | 0x29418 | Character selection flag |
| PARTY_RESTING | 0x2941a | Rest state |
| PARTY_SIZE | 0x29424 | Party member count |
| SCREEN | 0x31290 | Framebuffer descriptor ptr |
| PLAYER base | 0x26158 | Stride 319 bytes, 6 slots |
PLAYER record offsets: +0x34 = presence word, +0xd5 =
OICON_INDEX (sentinel 0xffff → fallback 0xc9).
GRAPHICS.DAT asset 557. Layout: 6 rows × 128 ASCII-indexed 8-pixel glyphs:
raster[row * 128 + ascii_byte]
Bit 7 = leftmost pixel, bit 0 = rightmost. Only 5 bit columns visible (right-aligned 5-bit glyph, MSB first). Byte-identical across all three games.
| Constant | Value | Unit |
|---|---|---|
| CHAR_X_SIZE | 5 | pixels (glyph body width) |
| CHAR_Y_SIZE | 6 | pixels (glyph body height) |
| CHAR_X_SPC | 1 | pixels (horizontal spacing) |
| CHAR_Y_SPC | 1 | pixels (vertical spacing) |
| CHAR_X_WID | 6 | pixels (per-char advance) |
| CHAR_Y_HYT | 7 | pixels (per-line height) |
| SCR_X_SIZE | 320 | pixels (screen width) |
| ICON_X_SIZE | 16 | pixels |
| ICON_Y_SIZE | 16 | pixels |
| ICON_SIZE | 256 | bytes (16×16) |
- Japanese disc
JDATA/GRAPHICS.DATasset 557 is byte-identical toDATA/GRAPHICS.DATasset 557 — same ASCII font - No game-owned Shift-JIS glyphs on disc — all kanji delegates to TownsOS TBIOS platform font ROM at runtime
- ASCII bytes (0x00–0x7f) use shared rasteriser; Shift-JIS pairs (lead 0x81–0x9f/0xe0–0xfc + trail 0x40–0x7e/0x80–0xfc) are fail-closed without TBIOS
-
sjis_glyph_drawcallback slot allows a Tsugaru-backed shim
Software implementation of TownsOS EGB primitives:
-
EGB_RECTANGLE/EGB_PAINTMODE 0x20(fill rect) -
EGB_PUTBLOCK/EGB_PUTBLOCKCOLOR(block copy with optional masking via WRITEMODE 6) - FILL_RECT at EDM.EXP 0x1fccc, PIX_BLOT at 0x1fe7c
DM1 HMA-240: MODE1/2048 data track, PVD at sector 16.
/EDM.EXP English game executable
/JDM.EXP Japanese game executable
/TMENU.EXP Launcher
/DATA/GRAPHICS.DAT English graphics (575 assets)
/DATA/DUNGEON.DAT English dungeon
/JDATA/GRAPHICS.DAT Japanese graphics
/JDATA/DUNGEON.DAT Japanese dungeon
/AUTOEXEC.BAT Boot route
/TMENU.ICN Launcher icon
/TMENU.INF Launcher info
Track 01 BIN: 5,056,800 bytes, 2,150 sectors. Stripped ISO: 4,403,200 bytes. Audio tracks 02–20 provide CDDA music.
- All cross-game shared payloads (font, geometry, spells, OICON, DYNA_BUTTONS)
- Complete DM1 SYM1 symbol table (1,174 entries)
- Complete CSB TMENU SYM1 symbol table (1,724 entries)
- 36 SND_* function entry points
- 502 Phar Lap bridge call sites across 11 binaries
- All real-data SHA-256 hashes
- GRAPHICS.DAT format classifier and DM1 legacy decoder
- Menu font rasteriser with round-trip test
- TBIOS shim (Shift-JIS glyphs via ROM)
- Tsugaru bridge contract
- DM1 CDDA track mapping (19 tracks)
- DM2 HMP-to-CDDA mapping via CD.DAT
- ISO 9660 extractor
- TMENU event system schema
- EGB rectangle/putblock shim
- JDM font contract
- Menu BSS symbol layer
- OICON descriptor (224 × 6 bytes)
- Region registry (23 blocks, 994 records)
- Direct I/O port audit (all games)
- TBIOS version fingerprint detector (8 revisions)
- Extended-format GRAPHICS.DAT per-record decoders (CSB 0x8001 payload, DM2 0x8004 payload)
- TownsOS BIOS runtime execution (requires Tsugaru integration or expanded shim)
- Independent CSB menu-render pipeline (CSB has its own region table)
- DM2 OICON/DYNA_BUTTONS recovery (independent from DM1)
- CDDA playback integration (track selection wired, actual audio stream pending)
- Atari ST and Amiga FM Towns variants
- JDM Shift-JIS glyph bitmaps (not on disc — delegates to TBIOS)