GitHub - peterkelly/captain-bible-re: Reverse engineering of Bridgestone Multimedia Group's 1994 classic, "Captain Bible in the Dome of Darkness"
Pangram verdict · v3.3
We believe this text is mainly AI, with some human-written content.
AI likelihood · overall
AIArticle text · 1,356 words · 1 segments analyzed
This repository contains a reproducible environment and research notes for reverse-engineering Captain Bible in the Dome of Darkness, a DOS game from the 1990s. The original game files are expected in CB/ and are intentionally ignored by Git. The FreeDOS/QEMU environment and the planned static and dynamic analysis are complete. The sources for the two published books are under docs/ and spec/. See PLAN.md for the living checklist and docs/src/progress-log.md for the complete activity log. Documentation Reverse-engineering documentation records the research process, evidence, recovered formats, executable analysis, and project progress. Clean-room engine specification defines the game mechanics and portable compatibility contract for implementing an engine without relying on the DOS program's internals. Requirements QEMU with qemu-system-i386 and qemu-img mtools (mformat, mcopy, mmd, mdir, and mtype) unzip Python 3 Pillow (for ART/PAL rendering) A C compiler, pkg-config, and GLib development headers for DOS tracing A POSIX shell mdBook (for the research and specification books) Rizin (for the supplied symbol script and further disassembly) A current stable Rust toolchain, SDL3, and pkg-config (for the clean-room engine) The setup is being developed and tested with QEMU 11.0.2 and mdBook 0.5.3 on macOS/Apple Silicon. Running the game From the repository root, run: ./run.sh The script opens QEMU and starts Captain Bible automatically. On its first run, it creates a persistent play image at build/captain-bible/captain-bible.img. Saved games are written to that image and remain available on later runs. On macOS, the game uses QEMU's visible Cocoa display with zoom-to-fit=on. Before QEMU opens, the script prints both the host image filename and the guest path C:\CBDOME\CB.EXE. The game supports both mouse and keyboard input. If QEMU captures the pointer, use Control-Option-G to release it on macOS. Exit through the game's Escape menu before closing QEMU so pending save writes complete cleanly. QEMU still presents Sound Blaster 16 and AdLib hardware to the game, but uses the silent none audio backend. The Cocoa window remains visible while game audio is suppressed on the host. To prepare or check the images without opening QEMU: ./run.sh --setup-only To recreate the play image from the current CB/ directory: ./run.sh --rebuild --rebuild replaces the persistent play image and therefore resets any saved games held only inside it. For RNG-aligned, action-for-action DOS/Rust comparisons against the same game data and save state, start DOS with an unsigned 16-bit initial state: ./run.sh --rng-seed 1 The launcher reconstructs a patched executable under build/, places it only in a unique disposable clone of the play image, verifies the guest copy, and runs the clone with QEMU snapshot writes. It never modifies CB/CB.EXE. Once the normal play image exists, deterministic runs leave it unchanged unless --rebuild is also requested explicitly. Rebuild first when the comparison must use newer files from CB/ rather than the play image's existing copy. The normal launch removes its per-run clone after QEMU exits; --setup-only retains the printed directory for inspection. Rust engine The clean-room native implementation lives in rust-engine. It consumes the same original CB/ data directory and includes a standard-library-only engine core plus terminal and SDL3 frontends. SDL3 and pkg-config are hard build requirements. Validate the complete shipped resource set and start the default SDL3 frontend with: cd rust-engine cargo run --release -- --data ../CB --validate cargo run --release -- --data ../CB cargo run --release -- --data ../CB --rng-seed 1 Pass --headless for the terminal or deterministic tick frontend. See the engine README for SDL3 setup, controls, deterministic smoke runs, text export, tests, and current host-frontend limitations. Rebuilding FreeDOS The base operating-system image is constructed noninteractively from the official FreeDOS 1.4 LiteUSB distribution: tools/setup_freedos_image.py The result is build/freedos/freedos.img. The builder verifies the published SHA-256, preserves the source boot code, constructs a new FAT16 partition, and copies the FreeDOS filesystem with mtools. It does not run or automate the FreeDOS installer. The current workspace image also contains the complete game at C:\CBDOME, added after the base image was built. If you boot that image directly, run: CD \CBDOME CB Rebuilding the base image removes that manual game copy. Running ./run.sh will still create or use the separate game-bearing play image automatically. Run its focused unit tests with: python3 -m unittest discover -s tests -v Executable analysis CB.EXE is a 16-bit MZ executable compressed with Microsoft EXEPACK. Generate the independently verified unpacked executable and, when the recorded QEMU dump is present, compare it with the relocated process image: tools/analyze_cb_exe.py CB/CB.EXE \ --output build/analysis/CB_UNPACKED.EXE \ --memory-dump build/dumps/title-physical-1m.bin \ --load-segment 0x627 Load the current high-confidence names into Rizin with: rizin -b 16 -i analysis/cb.rz build/analysis/CB_UNPACKED.EXE Audit all 140 named functions, 134 distinct BIN handlers, and 9 data symbols against the Rizin script, with per-entry confidence and evidence, using: tools/inspect_symbol_map.py Independently compare all 145 opcode dispatch entries and operand-reader paths with the decoder, all 134 distinct handler symbols, and all 25,829 shipped commands using: tools/audit_bin_opcodes.py The checked per-opcode result is analysis/opcode-audit.tsv. The generated executable and memory dumps remain under ignored build/. Research results, address conventions, function names, command-line behavior, and the recovered save layout are in the mdBook source. Inspect the installed Miles AIL/MIDPAK OPL timbre library with: tools/inspect_midpak_ad.py CB/SOUND.4 tools/inspect_midpak_ad.py CB/SOUND.4 --list The sound-driver chapter maps all 34 game-side int 66h sites and the DIGPAK and MIDPAK service contracts. ./run.sh --trace-dos records both DOS int 21h and driver int 66h calls and returns while keeping the Cocoa window visible and host audio silent. Extracting DD1.DAT The main resource archive has a recovered 24-byte directory format and custom LZW-family compression. List or extract its 369 members with: tools/extract_dd1.py --list CB/DD1.DAT tools/extract_dd1.py \ --extract RUN.ART \ --output build/dd1/RUN.ART \ CB/DD1.DAT tools/extract_dd1.py --extract-all build/dd1/all CB/DD1.DAT All-member output is prefixed with each directory index so repeated archive names remain distinct. The extractor validates the directory, payload magic, compressed stream, expanded size, and exact input consumption. Format details and the corresponding executable routines are in the mdBook's DD1.DAT chapter. Rendering artwork Extracted ART resources contain 12-byte frame descriptors followed by row-major eight-bit pixels. Their colors come from separate 768-byte VGA PAL resources. Inspect or render them with: tools/render_art.py build/dd1/all/003_LOGO.ART --list tools/render_art.py \ build/dd1/all/003_LOGO.ART \ --palette build/dd1/all/002_LOGO.PAL \ --canvas --scale 2 \ --output build/graphics/logo.png The renderer can also write one frame with --frame or every frame with --all-frames. Palette index 0 is transparent by default for sprite previews; use --opaque-zero when reproducing an opaque draw. The mdBook graphics chapter documents the format and its byte-for-byte correlation with QEMU VGA memory. Generate an annotated contact sheet of every full-screen ART frame, with PAL associations inferred from the scene programs: tools/render_fullscreen_gallery.py \ CB/DD1.DAT \ --output build/graphics/full-screen-gallery.png Use --scale 2 for a nearest-neighbor enlarged sheet. Inspecting scene bytecode The 62 extracted BIN resources contain scene programs. The recovered decoder knows the operand layout and dispatch effect of all 145 opcodes. It assigns semantic names to every value, including conservative low-level names for the 23 values absent from the shipped scripts: tools/inspect_bin.py build/dd1/all/005_INTRO.BIN tools/inspect_bin.py build/dd1/all/001_LOGO.BIN --objects tools/inspect_bin.py build/dd1/all/327_BOSS.BIN --choices tools/inspect_bin.py \ build/dd1/all/337_COMBAT7.BIN --animations --actions tools/inspect_bin.py \ build/dd1/all/334_ROOM3.BIN --start 0x0c96 --limit 0x1754 Most resources are code from beginning to end. CP2.BIN has a data trailer, and ROOM3.BIN has three command regions separated by zero-filled reserved blocks, so those regions require explicit --start and --limit values. The mdBook scene-bytecode chapter describes the interpreter, command schema, startup sequence, QEMU memory correlation, and complete opcode catalog. It also records the corrected two-word layout of opcode 0x69, which removes 11 phantom commands from the linear corpus, and the independent executable-CFG audit of every declared operand path. The --objects view summarizes the display records defined in linear command order, including thread/animation types and direct objects' coordinates, scale, flags, frame, and ART slot. See the scene-display-object chapter for the live ten-byte layout and control-flow caveat. The --choices view lists dialogue-choice source offsets, absolute branch targets, and inline text. See the conversation-flow chapter for its six-byte runtime table, study-Bible integration, and live QEMU correlation. The --animations view groups each animation header with its contiguous nine-byte steps; --actions lists screen coordinates, absolute targets, selectors, and recovered combat and hall-action labels. The combat-runtime chapter documents their runtime tables, BIN scheduler, action outcome branches, faith effects, shared victory/retreat epilogue, and map transitions. Patch both scene-name fields—and, when needed, both coordinate copies—in a