# Dusk Engine - Status Snapshot This is a point-in-time inventory of the codebase's maturity, test coverage, and known gaps. It is not auto-maintained -- re-survey periodically (or whenever picking a new roadmap milestone) rather than trusting it blindly. See `ROADMAP.md` for the ordered feature milestones this status feeds into, and `CLAUDE.md` for coding conventions. Last surveyed: 2026-07-31, at commit `8f8fa8f8`. ## Core engine (`src/dusk/`) | Subsystem | Maturity | Notes | |------------|------------------------------------|-------| | asset | Mature, fully wired | Model loading's "async" path is actually synchronous (`assetmodelloader.h`) -- only real stub found in core. | | script | Mature for its current scope | Registered modules: `modulePlatform`, `moduleComponent`/`moduleComponentList` (typed Position/Physics/Renderable wrappers), `moduleEntity`, `moduleScene` (with `Scene.set()` module lifecycle), `moduleMesh`, `moduleTime`, `moduleRequire` (CommonJS-style `require()`/`module.exports`). Entry point is `scripts/init.js`, which does `require('./overworldscene.js')` + `Scene.set()`. Has unit tests (`test/script/`). | | entity | Mature | Engine-level prefab lists are empty sentinels; all real prefabs live in `duskrpg`. | | scene | Mature | Same prefab-delegation pattern as entity. No JSON serialize/deserialize (removed by design). | | save | Mature, but undocumented | Slot-based, yyjson + CRC32, platform stream hooks. Not covered in `CLAUDE.md`, no tests. | | network | Connection-state layer only | HTTP client + connection state machine; no multiplayer/replication protocol (expected -- that's roadmap items 8-17). Not covered in `CLAUDE.md`, has HTTP tests only. | | physics | Mature, recently churned | Recent revert/re-disable of "old ent code" suggests component wiring around physics isn't fully settled. Well tested. | | animation | Early/mid-stage | Keyframes + easing only, no blend trees or state machines. Terse commit history ("ANIM") suggests still iterating. | | display | Most mature/battle-tested | Backbone of the engine; dominated by platform optimization commits. | | ui | Actively churning, perf pass done | Widget framework has had features added and ripped out repeatedly (story/battle UI added then removed). No JS bindings yet (from-scratch surface if that's picked up). Sprite-cache pass landed for slider/tab/frame/textbox (see roadmap item 4 below); still no scripted pointer/hit-testing. Has unit tests for the new caching logic (`test/ui/`), but nothing exercises actual draw calls -- see below. | | console | Small, finished for its scope | Fixed-size cached mesh (no more alloc/free churn), same pattern the rest of `ui/` now follows. | | event | Clean, small, finished | Pub/sub, rebuilt to replace the old input system. | | game | Intentionally header-only | Real implementation lives in `duskrpg/game/game.c`. | ### UI rendering performance (roadmap item 4) First pass landed 2026-07-31: `uislider`/`uitab` now cache their non-text quads (track/fill/markers, tab background) relative to origin and only rebuild on state change, translating into position at draw time. `uiframe.c` grew `uiFrameDrawCached()`, which skips rebuilding its 9-slice sprites when x/y/width/height match the last call; wired into the confirm dialog, settings panel, and textbox (each owns its own `uiframecache_t`). `uitextbox` no longer does one `spriteBatchBuffer` call per visible glyph -- it builds a per-page glyph cache once and slices a prefix by scroll each frame. `uiconsole` dropped its alloc/free vertex buffer for a fixed 512-glyph array. `uifps` skips its label rebuild when the formatted FPS string hasn't changed. Still open: every widget still issues its own `spriteBatchBuffer` call per material/color, so a row of alternating highlighted/plain widgets still forces a GPU flush per widget (color is applied via material, not per-vertex) -- that's the next real win if PSP framerate is still an issue. No scripted pointer/hit-testing exists either; input is still 100% gamepad/keyboard directional-focus (`ui/focus/`). Test coverage caveat: `test/ui/` and `test/display/test_spritebatchsprite.c` cover the new caching *logic* (geometry math, exercised by constructing widget structs directly) but cannot exercise `uiXxxDraw()`/`uiFrameDraw()` themselves -- those need `FONT_DEFAULT`/`UI_FRAME`'s GL texture, which needs a live GL context this test binary doesn't have (confirmed: calling `fontInitDefault()` in a test asserts in `texturegl.c`). This is true of the whole rendering layer, not something newly introduced -- there's no GL-backed test harness anywhere in the repo yet. ## Game layer (`src/duskrpg/`) Actively maintained, not orphaned (despite an old "remove rpg" commit deep in history) -- last touched the same day as this survey. - **cutscene/** -- actively developed, matches `CLAUDE.md`'s documented recipe exactly. 16 registered item types. - **entity/, scene/** -- overworld player/camera/interactable components and prefabs, active. - **item/** -- `item.c`/`inventory.c`/`backpack.c` built via a working `item.json` -> `itemdef.h` codegen pipeline. `itemgive.c/h` exist on disk but are explicitly excluded from the CMake build pending textbox UI restoration -- **that UI (`ui/textbox/`) is already restored**, so this looks like an overdue follow-up, not a real blocker. - **input/** -- headers only, no implementation. Contains the one genuine TODO found in the whole `duskrpg` tree: `// TODO: Wiimote, USB Keyboard, probably more.` - **ui/** -- textbox restored and built; `uitestlabel.c/h` is an intentional smoke-test scaffold, not dead code. ## Platform layers | Platform | Status | |--------------|--------| | duskgl / dusksdl2 | Complete, shared by Linux/Knulli/PSP, no gaps found. | | dusklinux | Complete, well-trodden. | | duskpsp | Complete for current design. The historical dialog/tearing bug (see memory `project_psp_dialog_tearing` etc.) was **not fixed -- the dialog-based connect UI was removed entirely** (commit `d7982599`, "Simplified PSP network") in favor of a silent profile-based connect. Revisit if the dialog UX is still wanted. | | duskdolphin (GameCube/Wii) | Functional, not a stub -- real GX-based display/mesh/shader/texture. Wii input uses only the GameCube `PAD_*` library; no WPAD/Wiimote support (`inputdolphin.h` has `#error "Wii not implemented"` gated behind macros that are never defined, so currently dormant, not a live build break). `networkdolphin.c` hardcodes a static IP as an explicit temporary workaround for a suspected DHCP-related memory-corruption bug in `if_config()` -- root cause still open. | | vita | **Referenced by `scripts/build-vita.sh` and `docker/vita/` but no `cmake/targets/vita.cmake` exists** -- the build target is broken/unfinished at the CMake level. | ### CI coverage gap `.github/workflows/test.yml` only builds+tests Linux, on PRs to `main`. `build.yml` builds all other platforms (PSP, Knulli, GameCube, Wii + ISO variants) but **only on tag push** (release time). Vita and Dolphin aren't in CI at all. Net effect: regressions on 4+ platforms can land silently until a release tag is cut. ## Test coverage gaps Core `src/dusk/` subsystems with **zero** unit tests: `console`, `engine`, `event`, `game`, `input`, `log`, `save`, `script` (+ all JS module bindings), `system`, `ui` (entire widget framework). `src/duskrpg/` has almost no test coverage: `test/item/test_inventory.c` exists but **`add_subdirectory(item)` is commented out in `test/CMakeLists.txt`**, so even that one test never runs. `cutscene`, `entity`, `game`, `input`, `scene`, `ui` under `duskrpg` have no tests at all. No stale tests were found referencing deleted systems (old JSON serialize/deserialize, old event/cutscene modules) -- the test suite is internally consistent with current code, just incomplete in coverage. ## Build/tooling gaps worth knowing about - `assetsraw/` -> `assets/` (chunk JSON -> `.dcf`) is a manual/editor-only step (`tools.asset.chunk`), not part of the CMake build -- committed `.dcf` files can silently drift from their raw source. - Several Python tool packages exist but aren't wired into any build: `tools/color/csv/`, `tools/asset/chunk_json/`, `tools/asset/dmf/`, `tools/asset/tiles/`, `tools/input/csv/`. Some may be superseded by `tools/color.py`/`tools/item.py`; worth a pass to confirm which are live vs leftover.