Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
8.5 KiB
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.cbuilt via a workingitem.json->itemdef.hcodegen pipeline.itemgive.c/hexist 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
duskrpgtree:// TODO: Wiimote, USB Keyboard, probably more. - ui/ -- textbox restored and built;
uitestlabel.c/his 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.dcffiles 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 bytools/color.py/tools/item.py; worth a pass to confirm which are live vs leftover.