DOSKUTSU is a faithful port of Cave Story (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's DOS backend, DJGPP, and CWSDPMI.
The name is a portmanteau of DOS and Doukutsu Monogatari (Cave Story's original Japanese title).
DOSKUTSU exists for preservation and the engineering challenge of running Cave Story on a 1990s MS-DOS PC.
Status | Quickstart | Download | Game Assets | Requirements | Usage | Configuration | Building | How It's Developed | Components and License
![]() |
![]() |
| Title Screen | Opening Transmission |
![]() |
![]() |
| First Lab Room | First Cave |
![]() |
![]() |
| SETUP.EXE Main Menu | SETUP.EXE Sound Configuration |
captures from DOSBox-X running DOSKUTSU.EXE and SETUP.EXE
DOSKUTSU plays the full game, start to finish.
Frame rate depends on the hardware and how music is played:
| Hardware | Music | Frame rate |
|---|---|---|
| Pentium-class (reference PC) | MIDI (OPL3) | ~30 fps |
| Pentium-class (reference PC) | Organya software synth | ~21 fps |
| 486-class (Am5x86-133) | MIDI (OPL3) | ~23 fps, playable |
| 486-class (486DX2-66) | MIDI (OPL3) | ~12 fps, playable but choppy |
| 486-class (486DX2-50) | MIDI (OPL3) | ~8 fps, marginal - runs slightly slow |
Cave 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, which advances game logic on a fixed 50 Hz clock independent of the render rate.
As 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 for details; each fix has a killswitch if needed.
The 1.0.1 ship configuration, benchmarked with a fixed input recording across four CPUs on the same board (video card: Cirrus CL-GD5430):
| CPU | fps (median) |
|---|---|
| Pentium OverDrive 83 | ~33 |
| Am5x86-133 | ~32 |
| 486DX2-66 | ~19 |
| 486DX2-50 | ~15 |
The 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.
Cave 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.
It is on by default as of 1.0; set SDL_HINT_DOSKUTSU_FIXED_TIMESTEP=0 to use the legacy frame-coupled loop.
The 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.
MIDI plays through a hardware synthesizer, off the CPU. Two settings shape it:
| Setting | Environment variable | Options | Picks |
|---|---|---|---|
| Synthesizer | SDL_HINT_DOSKUTSU_AUDIO_BACKEND |
auto (default), wb, opl3, organya, adlib |
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). adlib: native OPL2 FM for a machine with an AdLib/OPL card but no Sound Blaster (or a PicoGUS in /mode adlib); music is clocked off the PIT timer instead of the SB interrupt. Music only -- a DAC-less AdLib card has no sound effects (see docs/CONFIG.md). |
| 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 |
| GM variant | SDL_HINT_DOSKUTSU_AUDIO_MIDI_GM_VARIANT |
v1, v2 |
an org2mid-converted General MIDI variant |
From nothing to playing, in five steps:
- Get the binaries. Download the latest
doskutsu-cf-<version>.zipfrom Download and unzip it -- or build from source. It gives youDOSKUTSU.EXE,SETUP.EXE,CWSDPMI.EXE, and the engineDATA\. - Add the game data. DOSKUTSU ships no Cave Story content. Extract it from your own 2004 freeware
Doukutsu.exeintoDATA\-- the quick path in ASSETS.md is the shortest route. (Like a Doom source port: the engine is here, you bring the game data.) - Put it on a DOS system. Copy the whole folder to a CF card or hard disk on a Pentium-class DOS PC -- or mount it in DOSBox-X to try it on a modern machine first.
- Configure sound. Run
SETUPonce; it detects your sound card and lets you test it before you play. - Play. Run
DOSKUTSU.
More detail at each step: Download, Game Assets, Building, Usage, Configuration.
Pre-built bundles are published on the Releases page (Forgejo, mirrored to Codeberg and GitHub).
Each release is a single doskutsu-cf-<version>.zip containing DOSKUTSU.EXE, SETUP.EXE, the CWSDPMI.EXE DPMI host, the license texts, and NXEngine-evo's GPLv3 engine support data. It does not include Cave Story game content -- the maps, sprites, music, and SFX come from your own copy of Pixel's 2004 freeware Doukutsu.exe (see Game Assets). The engine is the program; the game data is yours to supply, exactly the way a Doom source port ships without an IWAD.
Prefer to build the exact source you see here? make dist produces the identical bundle -- see Building.
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.
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:
scripts/fetch-cs-pxt.pyis the one-shot orchestrator. It fetches the 2004 EN freeware bundle from cavestory.one (SHA-256-pinned), extractsDoukutsu.exeto 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.scripts/extract-pxt.pyis the canonical extractor, transcribed from NXEngine-evo's ownextract/extractpxt.cpp. It operates on file offsets inDoukutsu.exeand emits ASCII Pixtone parameter files.
The same posture applies as the broader Cave Story port community (NXEngine-evo, doukutsu-rs): the engine code is open source; the game data is user-supplied freeware.
Recommended
- CPU: Pentium 75 MHz or faster
- RAM: 16 MB
- Video: VESA 1.2+ with 320x240 support
- Sound: Sound Blaster 16 or compatible
- OS: MS-DOS 6.22 or compatible
- Disk: 10 MB free
Minimum
- CPU: 486DX2-66 with FPU
- RAM: 8 MB
- Video: VESA 1.2+
- Sound: Sound Blaster 16 or compatible
- OS: MS-DOS 6.22 or compatible
- Disk: 10 MB free
DOSKUTSU.EXE, the CWSDPMI host, and the Cave Story data all live together in one directory:
C:\DOSKUTSU\
DOSKUTSU.EXE the game
SETUP.EXE hardware / sound configurator (run once before first play)
CWSDPMI.EXE the DPMI host - must sit beside DOSKUTSU.EXE
DOSKUTSU.CFG written by SETUP.EXE (optional; the game runs without it)
DATA\ Cave Story assets, user-extracted (see Game Assets)
Quick setup:
- Get
DOSKUTSU.EXE- build it (Building) or take it from a release bundle. - Get
CWSDPMI.EXE. The build tooling fetches it automatically (from its upstream, at a pinned checksum) viamake fetch-binaries, whichmake installandmake distrun; it is not a manual download. Release bundles already include it. - Extract the Cave Story data into
DATA\(Game Assets). - Copy the whole directory to the DOS machine.
- The DOS machine needs a standard DJGPP-compatible boot environment:
HIMEM.SYSloaded,NOEMS, a SB16-compatibleBLASTERvariable set, and a VESA 1.2+ video BIOS (a software VESA driver works as a fallback).
Before the first play, run SETUP (or SETUP.BAT) to detect your hardware and
configure sound -- see Configuration. Then run the game from
the game directory:
C:\DOSKUTSU> SETUP (once, to configure)
C:\DOSKUTSU> DOSKUTSU (play)
The title screen appears within a few seconds. Controls follow NXEngine-evo's defaults:
| Key | Action |
|---|---|
| Arrow keys | Move / navigate menus |
| Z | Jump / confirm |
| X | Fire / cancel |
| A / S | Cycle weapons |
| Q | Inventory |
| W | Map |
| Escape | Pause menu |
| F11 | Toggle fullscreen (no-op on DOS; always fullscreen) |
These are the defaults - keyboard keys are remappable and a gameport joystick /
flightstick is supported (2 axes + 4 buttons). Configure both in SETUP.EXE
under Input: remap keys, assign buttons, calibrate the stick, and invert the
Y axis if its pitch reads backwards. (1.2.0+)
The easy way is SETUP.EXE - a classic DOS-style configurator. Run it before
your first play (or whenever your hardware changes):
C:\DOSKUTSU> SETUP
SETUP detects your machine (CPU, memory, sound card from your BLASTER
variable, WaveBlaster / OPL3, video), recommends settings, and lets you choose
the music backend and volumes, the Sound Blaster port / IRQ / DMA, performance
mode, and input (remap the keyboard, assign / calibrate a gameport joystick).
It can play the real Polar Star sound effect and
Title theme through your chosen backend so you can confirm sound works before
launching the game, then writes DOSKUTSU.CFG, which the game loads at startup.
Auto-detect recommends OPL3 FM music (works on any Sound Blaster); a
WaveBlaster daughterboard is never selected automatically - pick it yourself in
SETUP if you have one. Settings precedence is environment variable >
DOSKUTSU.CFG > built-in default, with one deliberate exception: a BLASTER
line written by SETUP is authoritative and overrides an ambient SET BLASTER.
docs/SETUP.md is the full SETUP + DOSKUTSU.CFG reference.
You can also skip SETUP and configure DOSKUTSU directly through DOS environment
variables - the music backend, the Fixed-Timestep game-speed mode, audio
quality, and hardware-compatibility fallbacks - set with SET in AUTOEXEC.BAT
or at the DOS prompt. docs/CONFIG.md is the complete
environment-variable reference: every option with its values, defaults, usage
examples, and performance impact.
Full build documentation in docs/BUILDING.md: prerequisites, DJGPP cross-compiler install, the four-stage build (SDL3, SDL3_mixer, SDL3_image, NXEngine-evo), DOSBox-X testing, common errors.
Short version, once DJGPP is installed -- the one-command path:
git clone ssh://git@forgejo.ecliptik.com/ecliptik/doskutsu.git
cd doskutsu
./scripts/bootstrap.sh # verify prereqs, fetch upstreams, apply patches, buildOr run the stages yourself:
./scripts/setup-symlinks.sh # one-time: link tools/djgpp (only if using the ~/emulators hub)
./scripts/fetch-sources.sh # clone the upstream repos at pinned SHAs
./scripts/apply-patches.sh # apply DOS-port patches
make # orchestrate all four build stages
make smoke-fast # headless DOSBox-X smoke (fast config)
make setup # build SETUP.EXE (the configurator)
make setup-test # host-side SETUP unit testsmake dist bundles the game, CWSDPMI.EXE, and the live-audio SETUP.EXE
(built with its audio backend linked in) into a ready-to-deploy archive.
DOSKUTSU is developed agentically with Claude Code.
- Claude Code authors the patches across the SDL3 DOS backend, the NXEngine-evo engine, the build system, scripts, and docs. They land as
patches/<vendor>/NNNN-*.patchfiles in this repository. - Human developers drive testing and iteration: TAS replays, real-hardware playthroughs, bug reports, and deciding what to fix next.
- Workspace-local patches only. This project does not contribute patches upstream to libsdl-org/SDL, libsdl-org/SDL_mixer, libsdl-org/SDL_image, or nxengine/nxengine-evo.
DOSKUTSU's own source - the build system, scripts, and documentation - is MIT-licensed (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.
Each component below is listed with its purpose, license, and whether it links into DOSKUTSU.EXE:
| Component | Purpose | License | In DOSKUTSU.EXE |
|---|---|---|---|
| DOSKUTSU port source (this repo) | Build system, patches, scripts, docs | MIT | n/a - source, not the binary |
| NXEngine-evo | The C++11 re-implementation of the Cave Story engine | GPLv3 | Yes - governs the binary |
| SDL3 | Platform layer; its DOS backend is what makes the port possible | zlib | Yes |
| SDL3_mixer | Audio mixing | zlib | Yes |
| SDL3_image | Image loading | zlib | Yes |
| DJGPP libc | 32-bit DOS C runtime, by DJ Delorie | GPL + runtime exception | Yes - the exception permits static linking |
| CWSDPMI | DPMI host, by Charles W. Sandmann | freeware, redistributable | No - ships alongside as a separate program |
| Cave Story game data | Maps, sprites, music, and SFX, by Daisuke Amaya (2004) | freeware, 2004 terms | User extracted, not redistributed |
Built with the DJGPP toolchain (installed via build-djgpp by Andrew Wu), tested with DOSBox-X and real hardware.
Full attribution detail: THIRD-PARTY.md.





