Game module format

A native game is a WebAssembly module that exports its linear memory as memory along with the functions detailed below. All parameters and return values are 32-bit integers, and all pointers are byte offsets into linear memory. The Rust and C SDKs implement this interface automatically; use this reference when inspecting the ABI or targeting it from another language.

Required exports

ExportWhat it does
wg_init(seed: u32)Starts a new run seeded with a random 32-bit integer.
wg_frame(buttons: u32, dt_ms: i32) -> u32Advances the simulation by dt_ms milliseconds with the given button bitmask held, renders the frame, and returns event flags. When dt_ms is 0, renders the current state without advancing the simulation.
wg_fb() -> ptrReturns the byte offset of the RGBA framebuffer in linear memory.
wg_w() -> i32, wg_h() -> i32Returns the framebuffer width and height in pixels.
wg_score() -> i32Returns the player's current score.
wg_state() -> ptr, wg_state_size() -> i32Returns the address and byte length of the serialized game state buffer.
wg_state_loaded() -> i32Called after the host copies a saved state into the wg_state() buffer; return 1 to accept the state or 0 to reject it.

Frames

After calling wg_init, the host page invokes wg_frame once per display refresh with the elapsed time in milliseconds since the previous frame (clamped to at most 100 ms) and the current button bitmask. Brief taps pressed and released between refreshes are latched so they still register on the next frame. The loop pauses automatically while a host overlay is open or the browser tab is hidden; when the host needs to redraw the canvas without advancing gameplay (such as after resizing the viewport or restoring a save state), it calls wg_frame with dt_ms = 0.

Buttons

Controller inputs are passed as a bitmask combining keyboard bindings, on-screen touch controls, and connected gamepads:

BitButtonKeys
1UpArrow Up, W
2DownArrow Down, S
4LeftArrow Left, A
8RightArrow Right, D
16ASpace, Z
32BX, U, Backspace
64StartEnter, P

Events and sound

The bitmask returned by wg_frame signals gameplay events to the host page, which synthesizes a matching sound effect for each flag:

BitEventWhen
1BlipMinor movement or UI step
2HitItem collected or point scored
4LoseLife or attempt lost
8Game overRun ended; the host page reads wg_score()
16LevelStage or level cleared
32WinCombined with Game over: the run was won

The picture

The framebuffer consists of wg_w() * wg_h() 4-byte pixels in RGBA byte order (0xAABBGGRR as a 32-bit little-endian word, with alpha set to 255). By default, the host scales the framebuffer to fit the stage while preserving its aspect ratio; modules that export wg_resize receive the stage's exact device-pixel dimensions instead so they can render crisply at any resolution.

Saves

All persistent state for a run must reside within the contiguous memory block returned by wg_state. The host copies those bytes directly for Resume snapshots, manual save slots, and cloud saves, and writes them back into memory when restoring. Before restoring, the host verifies that the byte length matches wg_state_size() and then calls wg_state_loaded—store a version tag inside your state struct and return 0 if any fields are out of range so outdated or corrupted saves are safely rejected.

Optional exports

The host page invokes these hooks automatically whenever a module exports them.

ExportWhat it does
wg_resize(w, h)Resizes the framebuffer to w × h device pixels (up to ~2.4 million pixels); the host re-queries wg_w() and wg_h() afterward.
wg_dpr(d)Passes the device pixel ratio multiplied by 100 prior to wg_resize(), for games that scale UI elements in CSS pixels.
wg_drawn() -> i32Returns 1 if the most recent wg_frame() modified the framebuffer; when omitted, the host uploads the framebuffer every frame.
wg_mouse(x, y, buttons)Passes pointer coordinates in framebuffer pixels and active button bits (1 = left, 2 = right, 4 = middle, 8 = touch), or (-1, -1) when the pointer leaves the canvas.
wg_pointer(x)Simplified horizontal pointer input for paddle games (x in framebuffer pixels, or -1 when outside the canvas).
wg_wheel(d)Passes vertical scroll wheel delta in hundredths of a line (positive values scroll down).
wg_pinch(x, y, d)Passes two-finger pinch midpoint and finger distance in framebuffer pixels (d = 0 when lifted).
wg_key(code) -> i32Passes direct keyboard input: lowercase ASCII code, physical digit row (or + 0x100 with Shift held), 8 (Backspace), 127 (Delete), 13 (Enter), or 0xF700–0xF703 (arrow keys). Return 1 if consumed, or 0 to let the key fall through to standard button mapping.
wg_lang(code) -> i32Passes the active page language before wg_init() as a two-byte little-endian ASCII code ("zt" for Traditional Chinese). The return value is ignored.

Modules that export wg_option delegate their start, pause, and game-over screens to the host page. Because option names, post-game stat labels, and level-select metadata are defined in the site catalog, the standalone test player displays the generic host overlays without custom option selectors or stat rows.

ExportWhat it does
wg_option(i, v) -> i32Sets option i to choice index v for the next wg_init() call (pass v < 0 to query the current value). Exporting this function delegates start, pause, and game-over overlays to the host page and routes the Start key to the host pause menu.
wg_over() -> i32Returns 1 once the current run has ended in victory or defeat.
wg_won() -> i32Returns 1 if the completed run ended in victory.
wg_stat(i) -> i32Returns post-game statistic i for display on the game-over overlay (return -1 to hide that row).
wg_best(v) -> i32Receives the player's personal best score from the host page for games that render their own high-score display.
wg_reached(), wg_cleared(), wg_level_score()Reports level progression for level-select menus: highest reached level, most recently cleared level, and the score earned on that level.

Screen-reader board accessibility hooks (wg_a11y_*) are documented in wg.h, and two-player online room hooks (wg_net_*) are documented in flipside.c.

Imports

A module may optionally import a single host function, env.wg_panic(msg: ptr, len: i32), which halts execution and displays the UTF-8 error message alongside the WebAssembly call stack on the crash screen. Modules that declare any other imports are rejected at load time, ensuring games remain sandboxed from the DOM, network, and local filesystem.