메뉴
HN
Hacker News • 54일 전

캡틴 바이블 DOS 게임 리버스 엔지니어링 프로젝트

IMP
4/10
핵심 요약

1990년대 DOS 게임인 '어둠의 돔: 캡틴 바이블'을 리버스 엔지니어링하고 이를 현대 환경에서 구동하기 위한 오픈소스 프로젝트입니다. QEMU 기반의 DOS 에뮬레이션 환경부터 시작해, 게임 데이터를 분석하고 Rust(표준 라이브러리만 사용)와 SDL3 기반의 클린룸(Clean-room) 엔진을 구현하여 게임을 현대 OS에서 호환 구동하는 것을 목표로 합니다.

번역된 본문

이 저장소에는 1990년대 DOS 게임인 '어둠의 돔: 캡틴 바이블(Captain Bible in the Dome of Darkness)'을 리버스 엔지니어링하기 위한 재현 가능한 환경과 연구 노트가 포함되어 있습니다. 원본 게임 파일은 CB/ 디렉터리에 위치해야 하며, Git에서는 의도적으로 이를 무시하도록 설정되어 있습니다. FreeDOS/QEMU 환경과 계획된 정적 및 동적 분석이 완료되었습니다. 두 권의 공개된 문서의 소스는 docs/ 및 spec/ 폴더 아래에 있습니다. 실시간으로 업데이트되는 체크리스트는 PLAN.md를, 전체 활동 로그는 docs/src/progress-log.md를 참조하십시오.

문서화: 리버스 엔지니어링 문서는 연구 과정, 증거, 복구된 포맷, 실행 파일 분석 및 프로젝트 진행 상황을 기록합니다. 클린룸 엔진 명세는 DOS 프로그램의 내부 구조에 의존하지 않고 엔진을 구현하기 위한 게임 메커니즘과 이식 가능한 호환성 계약을 정의합니다.

요구 사항: qemu-system-i386 및 qemu-img가 포함된 QEMU, mtools(mformat, mcopy, mmd, mdir, mtype), unzip, Python 3, Pillow(ART / PAL 렌더링용), DOS 추적을 위한 C 컴파일러, pkg-config 및 GLib 개발 헤더, POSIX 셸, mdBook(연구 및 명세 문서용), Rizin(제공된 심볼 스크립트 및 추가 디스어셈블리용), 현재 안정적인 Rust 툴체인, SDL3, pkg-config(클린룸 엔진용). 이 설정은 macOS/Apple Silicon 환경에서 QEMU 11.0.2 및 mdBook 0.5.3을 사용하여 개발 및 테스트되었습니다.

게임 실행: 저장소의 루트 디렉터리에서 다음을 실행합니다: ./run.sh 이 스크립트는 QEMU를 열고 캡틴 바이블을 자동으로 시작합니다. 처음 실행하면 build/captain-bible/captain-bible.img 경로에 영구적인 플레이 이미지가 생성됩니다. 게임 저장 데이터는 해당 이미지에 기록되며 이후 실행 시에도 계속 사용할 수 있습니다. macOS에서는 확대/축소 자동 맞춤(zoom-to-fit=on) 기능이 활성화된 QEMU의 Cocoa 디스플레이를 사용합니다. QEMU가 열리기 전에 스크립트는 호스트 이미지 파일명과 게스트 경로인 C:\CBDOME\CB.EXE를 모두 출력합니다. 이 게임은 마우스와 키보드 입력을 모두 지원합니다. QEMU가 마우스 포인터를 잠금(capture) 현상이 발생하면, macOS에서 Control-Option-G를 눌러 해제할 수 있습니다. 보류 중인 저장 기록이 완전히 깨끗하게 마무리되도록 QEMU 창을 닫기 전에 반드시 게임 내 Escape 메뉴를 통해 종료하십시오. QEMU는 여전히 게임에 Sound Blaster 16 및 AdLib 하드웨어를 인식시키지만, 오디오 백엔드는 소리가 나지 않는 none으로 사용합니다. 호스트에서 게임 오디오가 억제되는 동안에도 Cocoa 창은 계속 표시됩니다.

QEMU를 열지 않고 이미지를 준비하거나 확인하려면: ./run.sh --setup-only 현재 CB/ 디렉터리에서 플레이 이미지를 다시 생성하려면: ./run.sh --rebuild --rebuild는 영구적인 플레이 이미지를 대체하므로 해당 이미지 내부에만 저장되었던 기존 게임 저장 데이터는 모두 초기화(삭제)됩니다.

동일한 게임 데이터와 저장 상태에서 난수(RNG) 생성 순서와 액션이 완벽히 일치하는 DOS와 Rust 환경 간의 비교를 위해서는, 서명되지 않은 16비트 초기 상태로 DOS를 시작하십시오: ./run.sh --rng-seed 1 실행 스크립트는 build/ 디렉터리 아래에 패치된 실행 파일을 재구성하고, 이를 일회용 플레이 이미지 복제본(clone)에만 고유하게 배치한 다음, 게스트 복사본을 검증하고 QEMU 스냅샷 기록을 켜서 복제본을 실행합니다. 원본 CB/CB.EXE 파일은 절대 수정하지 않습니다. 정상적인 플레이 이미지가 생성된 이후에는, 명시적으로 --rebuild를 요청하지 않는 한 결정론적 실행(deterministic run)은 이미지를 변경하지 않고 그대로 둡니다. 플레이 이미지의 기존 사본 대신 CB/의 최신 파일을 사용하여 비교를 진행하려면 먼저 Rebuild를 실행해야 합니다. 일반 실행 시 QEMU가 종료되면 실행 시마다 만들어진 복제본은 자동으로 삭제됩니다. 반면 --setup-only는 출력된 디렉터리를 검사할 수 있도록 유지합니다.

Rust 엔진: 클린룸(Clean-room) 네이티브 구현체는 rust-engine 디렉터리에 있습니다. 이는 원본 CB/ 데이터 디렉터리를 그대로 소비하며, Rust 표준 라이브러리만 사용하는 엔진 코어와 터미널 및 SDL3 프론트엔드를 포함합니다. SDL3와 pkg-config는 필수 빌드 요구 사항입니다. 제공된 전체 리소스 세트를 검증하고 기본 SDL3 프론트엔드를 시작하려면 다음을 실행하십시오: cd rust-engine cargo run --release -- --data ../CB --validate cargo run --release -- --data ../CB cargo run --release -- --data ../CB --rng-seed 1 터미널이나 결정론적 틱(deterministic tick) 프론트엔드를 사용하려면 --headless를 전달하십시오. SDL3 설정, 조작법, 결정론적 스모크(Smoke) 실행, 텍스트 내보내기, 테스트 및 현재 호스트 프론트엔드의 제한 사항은 엔진 README를 참조하십시오.

FreeDOS 재빌드: 기본 운영 체제 이미지는 고정되어...

원문 보기
원문 보기 (영어)
Captain Bible Reverse Engineering 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.