Hooks Overview - drizztdourden08/relic-of-the-past GitHub Wiki
Game Hooks Reference for the CโJS boundary
This section documents every function that crosses the boundary between the WebAssembly game
core and the TypeScript app: the Wasm* exports JS calls into, and the GameHook_* callbacks the
game fires out to JS. If you want to read or drive the running game, this is the surface.
New to the bridge? Read Architecture โ The WASM Bridge first for the mental model; this section is the exhaustive catalogue.
Two directions
flowchart LR
JS["JS bridge & renderer"]
C["C game core (WASM)"]
JS -->|"ccall('Wasm...') ยท 79 exports ยท JS drives/reads"| C
C -->|"EM_ASM(window.__on...) ยท 3 events ยท game notifies JS"| JS
- JS โ C: every export is a C function marked
EMSCRIPTEN_KEEPALIVE. JS reaches it through a thin wrapper inapps/web/src/lib/game/, the bridge, viamod.ccall(name, ret, argTypes, args). - C โ JS: the game core fires
GameHook_*functions at gameplay events; the JS-facing ones useEM_ASMto call awindow.__on*callback the renderer registered.
Returning data: the HEAPU8 pointer convention
C cannot hand a struct to JS. Instead, a query writes into a static byte buffer and returns its
address (return (int)buf;). JS reads the bytes out of the WASM heap:
const ptr = mod.ccall('WasmGetInventoryState', 'number', [], []);
const view = mod.HEAPU8.subarray(ptr, ptr + 40); // copy/parse the documented layout
Multi-byte values are little-endian (lo, hi). Buffers are static and reused, so read and parse
immediately instead of holding the pointer across frames. Each function page below gives the exact
byte-by-byte layout.
The 2-place rule (adding a function)
A new boundary function touches two places; miss one and it won't be callable:
- C impl in
core/game-hooks/*.c(orcore/wasm-build/emscripten_*.c) markedEMSCRIPTEN_KEEPALIVE. - JS wrapper: the
ccallsite inapps/web/src/lib/game/.
Full procedure: the add-wasm-function skill and Contributing โ Adding a WASM Function.
Export note.
EMSCRIPTEN_KEEPALIVEboth retains and exports a symbol, so it is the single source of truth for what's callable; the build files carry no explicitEXPORTED_FUNCTIONSlist. A hand-maintained list once lived in bothbuild.batandMakefileand drifted; since it was redundant withKEEPALIVE, it has been removed.Headless / automation exports. A few exports (
WasmInitHeadless,WasmSetInputMode,WasmLoadSram,WasmGetFeatures,WasmGetPpuRenderFlags,WasmGetRoomCollisionTypeForRoom) are driven by the headless /--commandstartup path (Node scripts,--auto-state/--screenshot/--dump-*) instead of the interactive renderer, so they have no rendererccallby design and dead-code sweeps should not flag them.
The catalogue (79 exports, by category)
| Category | Count | Page | Source |
|---|---|---|---|
| State Queries for Inventory & Progress | 9 | โ | state_queries.c, ui_state.c |
| State Queries for Rooms & Collision | 15 | โ | state_queries.c, state_queries_grids.c, state_queries_rooms.c, state_queries_room_exits.c |
| State Queries for Navigation Tables | 6 | โ | state_queries_tables.c |
| State Queries for Sprites | 4 | โ | state_queries_sprites.c, state_queries_grids.c |
| Cheats & Commands | 21 | โ | cheats.c, check_triggers.c, emscripten_api.c |
| Rendering & Settings | 12 | โ | emscripten_api.c |
| Audio | 3 | โ | emscripten_api.c |
| Save / Load / I-O | 7 | โ | emscripten_io.c |
| Item Overrides | 2 | โ | item_overrides.c |
| CโJS callbacks | 14 | โ | haptic_events.c, game_hooks.c, check_triggers.c, item_overrides.c, cheats.c |
Conventions used on every page
- Source: the
core/...file plus the C signature, verified against the source, not paraphrased. - Bridge: the
lib/game/...module that owns theccallwrapper. - Returns: for buffer-returning queries, the byte layout (offsets are bytes;
u16 = lo,hi). - Pointers are into
mod.HEAPU8;voidexports take effect on the next frame.