Experimental native PC runtime and source port for Kingdom Hearts 358/2 Days, developed alongside khdays-decomp.
Warning
This project is in early development. The native asset pipeline — textures, 2D/UI graphics, fonts, models, animation, text, and audio — works, along with a mod-override system and a game filesystem. The game's front-end now runs natively (boot logos → title and menus → character select) with its real assets, music, and timings. It is not playable yet: gameplay itself is the next milestone.
Important
This repository does not contain a ROM, game assets, audio, video, text dumps, proprietary SDK files, or copyrighted game binaries. Users will be required to provide their own legally obtained copy of the game.
The two repositories have different purposes:
khdays-decompreconstructs Nintendo DS code that compiles byte-for-byte to the original game.khdays-portadapts understood game code and behavior to a portable runtime for modern systems.
Matching and reverse-engineering work belongs in khdays-decomp. Platform abstractions, native rendering, input, audio, filesystem work, quality-of-life features, and other PC-specific changes belong here.
The port should consume a pinned revision of the decompilation rather than turning the matching repository into a collection of platform-specific #ifdef blocks.
Phases 0–3 are complete — the bootstrap, the user-data pipeline, the platform runtime, and the full asset/rendering pipeline. Work is now on Phase 4 — game flow. What runs today:
Asset pipeline — every asset type decodes to a neutral, engine-independent form:
- TEX0 textures → RGBA
- 2D/UI graphics: NCLR palettes + NCGR tiles + NSCR tilemaps composed to RGBA (
--render-tiles,--render-bg) - NFTR bitmap fonts, with text rendering (
--render-text) - MDL0 models with bones and skinning → a neutral, animation-ready mesh
- NSBCA skeletal animation, GPU-skinned per frame; environment maps (NSBMD)
- Message text from the
db_<lang>.p2container and the UI.s/.s.zstring tables (--message-info,--dump-messages,--dump-strings) - Audio: SDAT wave archives → PCM (PCM8/PCM16/IMA-ADPCM), and an SSEQ software synthesizer for sequenced music
Rendering & audio (SDL3)
- GPU renderer: depth-tested, textured, GPU-skinned, orbit camera, plays any NSBCA
- Audio output: sound effects (
--play-sound) and synthesized music (--play-sequence)
Modding — drop-in overrides resolved before the DS asset (see Modding):
- Textures (PNG/BMP, HD), rigged models (glTF, animated by the DS skeleton), text, sound effects, music samples, 2D graphics, fonts, and raw files
Phase 4 — game flow (in progress)
- Game filesystem:
khdays::vfsresolves NitroFS game paths (mods → unpacked → decompressed → raw) (--vfs-resolve) - Scene/task frame loop (
khdays::game) reproducing the decompiled backbone — object state machines, an id→scene table with pending-id transitions, running in a native SDL window with input (--game;--game-demoheadless).Game::bootmirrors the DSBootTask_Constructexactly. - Boot logos (scene 1, ov000) — three real screen pairs from
ttl/ttl.p2, with the DS's own timings (91 frames per pair: 32 fade-in / 27 hold / 32 fade-out) fading both screens through black via the master brightness - Title and menus — the real 3D KH logo over the character illustration, hosting every menu level (MODO HISTORIA / MODO MISIÓN → NUEVA PARTIDA / CARGAR or UN JUGADOR / MULTIJUGADOR) with the real localized textures at the exact DS positions, playing the real title BGM (an SDAT STRM stream) through the neutral
game::MusicPlayer - Character select (scene 7, ov06) — the 13-portrait grid from
UI/mlt/res.p2, laid out and shaded (greyscale, colour when selected) exactly as the DS does - In-window options overlay (Dear ImGui): volume, remappable controls, stacked/side-by-side screen layout, fullscreen — persisted between runs
- Gameplay (scene 2, ov002) — currently a placeholder marking the reached game-owned state
- The save-file screen (layout known; needs a save system) and the attract cutscene (blocked on MobiClip)
Scene identification is verified against the running game (emulator savestates) rather than assumed — which corrected an earlier wrong model: ov000 is the entire front-end (logos, title, all menu levels, save-file screen), ov06 is the character select, and ov012 is the movie player.
Phase 4 is decomp-gated: it reimplements understood game behavior as
khdays-decomp names each
subsystem, so it advances subsystem by subsystem. See
docs/ROADMAP.md for the full plan.
docs/ROADMAP.md— milestones and phase plan.docs/ARCHITECTURE.md— the neutral-format layering (importers → resource layer → engine).docs/MODDING.md— replacing textures, models, text, sound, 2D graphics, fonts, and raw files via themods/folder.docs/NATIVE_MESH_DECODER.md— MDL0 geometry/skinning decode to the neutral mesh.docs/NATIVE_TEX0_RUNTIME.md— TEX0 texture decoding.docs/NATIVE_MDL0_INSPECTOR.md— the--model-infoinspector.docs/PLATFORM_RUNTIME.md— the SDL3 platform runtime.docs/MESSAGE_DATA_P2.md— thedb_<lang>.p2message-container format.
- Build a native, portable runtime for the game.
- Preserve the behavior of the original game where practical.
- Keep PC-specific code separate from the matching Nintendo DS decompilation.
- Require user-provided game data instead of distributing copyrighted content.
- Support modern input, rendering, audio, display resolutions, and debugging tools over time.
- Document formats and behavior discovered during reverse engineering.
- Distributing the game, a pre-patched ROM, extracted assets, or proprietary development tools.
- Replacing or weakening the byte-matching goals of
khdays-decomp. - Claiming affiliation with or endorsement by the original rights holders.
- Treating guessed or unverified code as completed reverse engineering.
khdays-port/
├── CMakeLists.txt
├── include/
│ └── khdays/
│ └── port.h
├── src/
│ └── main.cpp
├── external/
│ └── khdays-decomp/ # pinned Git submodule
├── platform/
│ ├── common/
│ └── pc/
├── game/
│ └── ported/ # adapted, understood game code
├── tools/
│ ├── verify_rom/
│ └── extract_data/
├── docs/
│ └── ROADMAP.md
└── data/ # local generated data; never committed
The directories beyond the current bootstrap files should be added when they contain real code. Avoid committing empty architecture for systems that have not been designed yet.
Requirements:
- CMake 4.2 or newer
- A C++20 compiler:
- Visual Studio 2026 on Windows
- Clang or GCC on Linux
- Apple Clang on macOS
Configure and build:
cmake -S . -B build
cmake --build build --config ReleaseRun on Windows with a multi-config generator:
.\build\Release\khdays-port.exeRun on Linux or macOS with a single-config generator:
./build/khdays-portRun this from the repository root:
git submodule add https://github.com/Yokimitsuro/khdays-decomp external/khdays-decomp
git submodule update --init --recursive
git add .gitmodules external/khdays-decomp
git commit -m "build: pin khdays-decomp as a submodule"Do not automatically track the latest decompilation commit during normal builds. Update the pinned revision deliberately, test the port, and record the decomp commit in the port commit message or pull request.
The first useful milestone is not “boot the entire game.” It is:
- Accept a local
.ndspath. - Calculate and display its cryptographic hash.
- Reject unsupported revisions cleanly.
- Extract required files into ignored local storage.
- Open a native window.
- Load and visualize one texture, model, or map resource.
- Port one self-contained function or subsystem and compare its behavior against the original game.
This creates a legal, testable pipeline before attempting the boot flow, overlays, graphics emulation, audio, or gameplay.
Because the runtime decodes DS assets into neutral, open formats before anything
reaches the engine, replacing content is a supported feature rather than byte
hacking. Drop open-format files into a mods/ folder and the resource layer
resolves them ahead of the original DS asset:
- Textures — a PNG/BMP under
mods/<Mod>/textures/**/<name>.pngoverrides a DS texture. UVs are normalized by the original DS size, so higher-resolution (HD) replacements map correctly and are not downscaled. - Models — a rigged glTF at
mods/<Mod>/models/<ds_name>.gltfreplaces a DS model's geometry and is animated by the DS skeleton: joints are matched to DS bones by name, so existing DS animations play on higher-poly geometry with no animation authoring. - Text — a
mods/<Mod>/text/<name>.txtfile retranslates or rewords the game's decoded UTF-8 strings (db_<lang>.p2story/menu text andUI/**/*.s.ztables), onekey = valueline per string. - Sound — a WAV at
mods/<Mod>/sounds/<wave_archive>_<swav>.wavreplaces a decoded game waveform (sound effects / voice clips). - 2D graphics & fonts — a PNG/BMP at
mods/<Mod>/graphics/<screen>.pngredraws a UI background, and an NFTR atmods/<Mod>/fonts/<name>.nftrswaps a font.
Mods only ever contain your own edits — never copyrighted game data — and
mods/ is git-ignored. See docs/MODDING.md for the folder
layout and the export/edit workflow.
Read CONTRIBUTING.md before opening a pull request.
Contributions must not include copyrighted game data, ROMs, proprietary Nintendo/Metrowerks tools, or code copied from projects with incompatible licenses.
Original port code in this repository is licensed under the MIT License.
Code imported or adapted from khdays-decomp remains subject to that project's CC0 1.0 dedication. Third-party components retain their own licenses. See THIRD_PARTY_NOTICES.md.
The MIT license applies only to the contributors' original work. It does not grant rights to the original game, its assets, names, characters, trademarks, or other copyrighted material.
This is an unofficial fan-made reverse-engineering and preservation project. It is not affiliated with, sponsored by, or endorsed by Square Enix, Disney, Nintendo, h.a.n.d., or any other rights holder. All trademarks and original game content belong to their respective owners.