{"id":50660616,"url":"https://github.com/ecliptik/doskutsu","last_synced_at":"2026-06-08T02:05:11.050Z","repository":{"id":353878268,"uuid":"1221260317","full_name":"ecliptik/doskutsu","owner":"ecliptik","description":"A port of Cave Story to DOS using SDL","archived":false,"fork":false,"pushed_at":"2026-05-25T16:51:23.000Z","size":1937,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T18:30:39.073Z","etag":null,"topics":["cave-story","dosbox","msdos","retrocomputing","retrogaming","sdl"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ecliptik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-26T00:50:37.000Z","updated_at":"2026-05-25T16:51:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ecliptik/doskutsu","commit_stats":null,"previous_names":["ecliptik/doskutsu"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ecliptik/doskutsu","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecliptik%2Fdoskutsu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecliptik%2Fdoskutsu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecliptik%2Fdoskutsu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecliptik%2Fdoskutsu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ecliptik","download_url":"https://codeload.github.com/ecliptik/doskutsu/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecliptik%2Fdoskutsu/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34044920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cave-story","dosbox","msdos","retrocomputing","retrogaming","sdl"],"created_at":"2026-06-08T02:05:10.058Z","updated_at":"2026-06-08T02:05:11.043Z","avatar_url":"https://github.com/ecliptik.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DOSKUTSU\n\nDOSKUTSU is a faithful port of [Cave Story](https://www.cavestory.org/) (Doukutsu Monogatari) to MS-DOS 6.22 on retro Pentium-class hardware. It plays Daisuke \"Pixel\" Amaya's 2004 freeware classic on real 1990s-era PCs via [SDL3](https://www.libsdl.org/)'s [DOS backend](https://github.com/libsdl-org/SDL/pull/15377), [DJGPP](https://www.delorie.com/djgpp/), and [CWSDPMI](https://en.wikipedia.org/wiki/DOS_Protected_Mode_Interface).\n\nThe name is a portmanteau of **DOS** and **Doukutsu Monogatari** (Cave Story's original Japanese title).\n\nDOSKUTSU exists for preservation and the engineering challenge of running Cave Story on a 1990s MS-DOS PC.\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"#status\"\u003eStatus\u003c/a\u003e | \u003ca href=\"#game-assets\"\u003eGame Assets\u003c/a\u003e | \u003ca href=\"#requirements\"\u003eRequirements\u003c/a\u003e | \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e | \u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e | \u003ca href=\"#building\"\u003eBuilding\u003c/a\u003e | \u003ca href=\"#how-this-project-is-developed\"\u003eHow It's Developed\u003c/a\u003e | \u003ca href=\"#components-and-license\"\u003eComponents and License\u003c/a\u003e\n\u003c/p\u003e\n\n### Screenshots\n\n| | |\n|:---:|:---:|\n| \u003cimg src=\"docs/screenshots/doskutsu-title.png\" alt=\"DOSKUTSU title screen running in DOSBox-X\" width=\"100%\"\u003e | \u003cimg src=\"docs/screenshots/doskutsu-intro-dialogue.png\" alt=\"Opening dialogue: From somewhere, a transmission...\" width=\"100%\"\u003e |\n| **Title Screen** | **Opening Transmission** |\n| \u003cimg src=\"docs/screenshots/doskutsu-first-room.png\" alt=\"First lab room with Quote and the broken teleporter\" width=\"100%\"\u003e | \u003cimg src=\"docs/screenshots/doskutsu-first-cave.png\" alt=\"First Cave with Quote, HUD, and a Heart pickup\" width=\"100%\"\u003e |\n| **First Lab Room** | **First Cave** |\n\n\u003cp align=\"center\"\u003ecaptures from DOSBox-X running \u003ccode\u003eDOSKUTSU.EXE\u003c/code\u003e\u003c/p\u003e\n\n---\n\n## Status\n\nDOSKUTSU plays the full game, start to finish.\n\nFrame rate depends on the hardware and how music is played:\n\n| Hardware | Music | Frame rate |\n|---|---|---|\n| Pentium-class (reference PC) | MIDI (OPL3) | ~30 fps |\n| Pentium-class (reference PC) | Organya software synth | ~21 fps |\n| 486-class (Am5x86-133) | MIDI (OPL3) | ~23 fps, playable |\n| 486-class (486DX2-66) | MIDI (OPL3) | ~12 fps, playable but choppy |\n| 486-class (486DX2-50) | MIDI (OPL3) | ~8 fps, marginal - runs slightly slow |\n\nCave Story runs at 50 fps; the reference PC's hardware limits fully-detailed rendering to about 30 fps. It still plays at the correct 50 Hz speed through [Fixed-Timestep mode](#fixed-timestep-mode), which advances game logic on a fixed 50 Hz clock independent of the render rate.\n\nAs of 1.0.1, the 486-class audio bugs are fixed and on by default: SFX no longer stutter on rapid fire, music tempo holds steady, and SFX play at the correct pitch and a balanced level against the music. See the [changelog](CHANGELOG.md) for details; each fix has a killswitch if needed.\n\n### Cross-CPU benchmark (1.0.1, Cirrus CL-GD5430)\n\nThe 1.0.1 ship configuration, benchmarked with a fixed input recording across four CPUs on the same board (video card: Cirrus CL-GD5430):\n\n| CPU | fps (median) |\n|---|---|\n| Pentium OverDrive 83 | ~33 |\n| Am5x86-133 | ~32 |\n| 486DX2-66 | ~19 |\n| 486DX2-50 | ~15 |\n\nThe audio fixes did not cost frame rate. This benchmark uses a lighter scene than the heavy-music figures in the table above, so the two are not directly comparable; it is recorded as the Cirrus baseline for an upcoming video-card comparison.\n\n### Fixed-Timestep mode\n\nCave Story's engine advances game logic once per rendered frame, so at 30 fps the game also runs at about 60% speed - sluggish. Fixed-Timestep mode decouples the two: logic advances on a fixed 50 Hz clock regardless of frame rate, so the game plays at its intended speed even though the screen draws fewer frames. The motion is less smooth; the speed is correct.\n\nIt is on by default as of 1.0; set `SDL_HINT_DOSKUTSU_FIXED_TIMESTEP=0` to use the legacy frame-coupled loop.\n\n### Audio backends\n\nThe soundtrack plays with either Cave Story's original Organya synthesizer or with MIDI. Organya is more faithful to the original, but has a significant performance impact; MIDI is recommended and the default for playing on DOS.\n\nMIDI plays through a hardware synthesizer, off the CPU. Two settings shape it:\n\n| Setting | Environment variable | Options | Picks |\n|---|---|---|---|\n| Synthesizer | `SDL_HINT_DOSKUTSU_AUDIO_BACKEND` | `auto` (default), `wb`, `opl3`, `organya` | `auto`: probe WaveBlaster daughterboard first, fall back to OPL3 FM; explicit values force a specific backend. `wb`: WaveBlaster / DreamBlaster-class wavetable daughterboard on the SB16 WaveBlaster header (validated on Vibra16S CT2490 + DreamBlaster S2). `opl3`: the SB16 / Sound Blaster Pro 2 OPL3 FM chip. `organya`: software synthesis of Pixel's original Cave Story tracker format (higher CPU cost). |\n| MIDI source | `SDL_HINT_DOSKUTSU_AUDIO_MIDI_SOURCE` | `wiimidi` (default), `orgmid` | `wiimidi`: the WiiWare arrangement, which tracks the original closely. `orgmid`: the Hart legacy `.mid` set |\n| GM variant | `SDL_HINT_DOSKUTSU_AUDIO_MIDI_GM_VARIANT` | `v1`, `v2` | an `org2mid`-converted General MIDI variant |\n\n---\n\n## Game Assets\n\n**DOSKUTSU does not include any Cave Story game data.** The binary built from this repository plays nothing on its own. Users supply their own copy of the 2004 EN freeware assets, extracted from the canonical `Doukutsu.exe`.\n\n[docs/ASSETS.md](./docs/ASSETS.md) is the canonical, complete asset procedure - follow it start to finish; it covers fetching the freeware bundle and extracting the full data tree (maps, sprites, music, SFX) plus the expected directory layout. The two scripts below automate only the Pixtone-SFX slice of that workflow; running them alone does not produce a playable `DATA\\` tree:\n\n- `scripts/fetch-cs-pxt.py` is the one-shot orchestrator. It fetches the 2004 EN freeware bundle from [cavestory.one](https://www.cavestory.one/downloads/cavestoryen.zip) (SHA-256-pinned), extracts `Doukutsu.exe` to a tempdir, runs the Pixtone parameter extractor, and cleans up. The freeware archive does not persist on the user's machine after the script completes.\n- `scripts/extract-pxt.py` is the canonical extractor, transcribed from NXEngine-evo's own `extract/extractpxt.cpp`. It operates on file offsets in `Doukutsu.exe` and emits ASCII Pixtone parameter files.\n\nThe same posture applies as the broader Cave Story port community ([NXEngine-evo](https://github.com/nxengine/nxengine-evo), [doukutsu-rs](https://github.com/doukutsu-rs/doukutsu-rs)): the engine code is open source; the game data is user-supplied freeware.\n\n---\n\n## Requirements\n\n**Recommended**\n\n- CPU: Pentium 75 MHz or faster\n- RAM: 16 MB\n- Video: VESA 1.2+ with 320x240 support\n- Sound: Sound Blaster 16 or compatible\n- OS: MS-DOS 6.22 or compatible\n- Disk: 10 MB free\n\n**Minimum**\n\n- CPU: 486DX2-66 with FPU\n- RAM: 8 MB\n- Video: VESA 1.2+\n- Sound: Sound Blaster 16 or compatible\n- OS: MS-DOS 6.22 or compatible\n- Disk: 10 MB free\n\n---\n\n## Usage\n\n`DOSKUTSU.EXE`, the CWSDPMI host, and the Cave Story data all live together in one directory:\n\n```\nC:\\DOSKUTSU\\\n  DOSKUTSU.EXE     the game\n  CWSDPMI.EXE      the DPMI host - must sit beside DOSKUTSU.EXE\n  DATA\\            Cave Story assets, user-extracted (see Game Assets)\n```\n\nQuick setup:\n\n1. Get `DOSKUTSU.EXE` - build it ([Building](#building)) or take it from a release bundle.\n2. Get `CWSDPMI.EXE`. The build tooling fetches it automatically (from its upstream, at a pinned checksum) via `make fetch-binaries`, which `make install` and `make dist` run; it is not a manual download. Release bundles already include it.\n3. Extract the Cave Story data into `DATA\\` ([Game Assets](#game-assets)).\n4. Copy the whole directory to the DOS machine.\n5. The DOS machine needs a standard DJGPP-compatible boot environment: `HIMEM.SYS` loaded, `NOEMS`, a SB16-compatible `BLASTER` variable set, and a VESA 1.2+ video BIOS (a software VESA driver works as a fallback).\n\nRun it from the game directory:\n\n```\nC:\\DOSKUTSU\u003e DOSKUTSU\n```\n\nThe title screen appears within a few seconds. Controls follow NXEngine-evo's defaults:\n\n| Key | Action |\n|---|---|\n| Arrow keys | Move / navigate menus |\n| Z | Jump / confirm |\n| X | Fire / cancel |\n| A / S | Cycle weapons |\n| Q | Inventory |\n| W | Map |\n| Escape | Pause menu |\n| F11 | Toggle fullscreen (no-op on DOS; always fullscreen) |\n\n---\n\n## Configuration\n\nDOSKUTSU is configured through DOS environment variables - the music backend, the Fixed-Timestep game-speed mode, audio quality, and hardware-compatibility fallbacks. Set them with `SET` in `AUTOEXEC.BAT` or at the DOS prompt.\n\n[docs/CONFIG.md](./docs/CONFIG.md) is the complete reference: every option with its values, defaults, usage examples, and performance impact.\n\n---\n\n## Building\n\nFull build documentation in [docs/BUILDING.md](./docs/BUILDING.md): prerequisites, DJGPP cross-compiler install, the four-stage build (SDL3, SDL3_mixer, SDL3_image, NXEngine-evo), DOSBox-X testing, common errors.\n\nShort version, once DJGPP is installed:\n\n```bash\ngit clone ssh://git@forgejo.ecliptik.com/ecliptik/doskutsu.git\ncd doskutsu\n./scripts/setup-symlinks.sh     # one-time: link tools/djgpp to the emulators hub\n./scripts/fetch-sources.sh      # clone the upstream repos at pinned SHAs\n./scripts/apply-patches.sh      # apply DOS-port patches\nmake                            # orchestrate all four build stages\nmake smoke-fast                 # headless DOSBox-X smoke (fast config)\n```\n\n---\n\n## How This Project Is Developed\n\nDOSKUTSU is developed agentically with [Claude Code](https://claude.com/code).\n\n- **Claude Code authors the patches** across the SDL3 DOS backend, the NXEngine-evo engine, the build system, scripts, and docs. They land as `patches/\u003cvendor\u003e/NNNN-*.patch` files in this repository.\n- **Human developers drive testing and iteration**: TAS replays, real-hardware playthroughs, bug reports, and deciding what to fix next.\n- **Workspace-local patches only.** This project does not contribute patches upstream to [libsdl-org/SDL](https://github.com/libsdl-org/SDL), [libsdl-org/SDL_mixer](https://github.com/libsdl-org/SDL_mixer), [libsdl-org/SDL_image](https://github.com/libsdl-org/SDL_image), or [nxengine/nxengine-evo](https://github.com/nxengine/nxengine-evo).\n\n---\n\n## Components and License\n\nDOSKUTSU's own source - the build system, scripts, and documentation - is **MIT-licensed** ([LICENSE](./LICENSE)). The shipped `DOSKUTSU.EXE` is **GPLv3**: it statically links NXEngine-evo, which is GPLv3, and that license governs the combined binary. The DOS-port patches under `patches/` are derivative works of their upstreams and carry those upstreams' licenses: GPLv3 for the NXEngine-evo patches, zlib for the SDL3 patches. Redistributed bundles carry the GPLv3 license text and a pointer back to this repository.\n\nEach component below is listed with its purpose, license, and whether it links into `DOSKUTSU.EXE`:\n\n| Component | Purpose | License | In `DOSKUTSU.EXE` |\n|---|---|---|---|\n| [DOSKUTSU port source](./LICENSE) (this repo) | Build system, patches, scripts, docs | MIT | n/a - source, not the binary |\n| [NXEngine-evo](https://github.com/nxengine/nxengine-evo) | The C++11 re-implementation of the Cave Story engine | [GPLv3](https://github.com/nxengine/nxengine-evo/blob/master/LICENSE) | **Yes - governs the binary** |\n| [SDL3](https://www.libsdl.org/) | Platform layer; its [DOS backend](https://github.com/libsdl-org/SDL/pull/15377) is what makes the port possible | [zlib](https://github.com/libsdl-org/SDL/blob/main/LICENSE.txt) | Yes |\n| [SDL3_mixer](https://github.com/libsdl-org/SDL_mixer) | Audio mixing | [zlib](https://github.com/libsdl-org/SDL_mixer/blob/main/LICENSE.txt) | Yes |\n| [SDL3_image](https://github.com/libsdl-org/SDL_image) | Image loading | [zlib](https://github.com/libsdl-org/SDL_image/blob/main/LICENSE.txt) | Yes |\n| [DJGPP](https://www.delorie.com/djgpp/) libc | 32-bit DOS C runtime, by DJ Delorie | [GPL + runtime exception](https://www.delorie.com/djgpp/v2faq/faq11_2.html) | Yes - the exception permits static linking |\n| [CWSDPMI](https://www.delorie.com/pub/djgpp/current/v2misc/) | DPMI host, by Charles W. Sandmann | [freeware, redistributable](./vendor/cwsdpmi/cwsdpmi.doc) | No - ships alongside as a separate program |\n| [Cave Story](https://www.cavestory.org/) game data | Maps, sprites, music, and SFX, by Daisuke Amaya (2004) | [freeware, 2004 terms](https://www.cavestory.org/) | User extracted, not redistributed |\n\nBuilt with the [DJGPP](https://www.delorie.com/djgpp/) toolchain (installed via [build-djgpp](https://github.com/andrewwutw/build-djgpp) by Andrew Wu), tested with [DOSBox-X](https://dosbox-x.com/) and real hardware.\n\nFull attribution detail: [THIRD-PARTY.md](./THIRD-PARTY.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fecliptik%2Fdoskutsu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fecliptik%2Fdoskutsu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fecliptik%2Fdoskutsu/lists"}