Host-independent browser library and release bundle for retro game runtimes. It owns runtime lifecycle, adapters, checkpoint codecs, bridge assets and pinned core release inputs. It owns game-specific configuration, implementation selection, content identities and dependency declarations. Host applications own users, databases, review, storage and HTTP authorization.
Supported targets, Provider Module architecture and core integration guides are maintained in the docs directory.
Game configuration, fingerprints, dependency preparation and the offline host tool are described in Runtime module. Managed game acquisition and cache/bridge ownership are described in Content I/O v1.
Hosts integrate the generated Provider Bundle. A Bundle exports one client.mjs:
export const providerId = "retrom-runtime";
export const providerVersion = "0.46.0"; // derived from release tag v0.46.0
export const providerApiVersion = 1;
export async function createRuntime(
value: unknown,
host: RuntimeHostV1,
): Promise<PlayerRuntimeV1>;The host validates a Launch Envelope V1, verifies the module URL and SHA-256 against the active Bundle, imports the module, checks the exported identity and calls createRuntime.
The immutable GitHub tag is the only release version source. Tag v0.46.0 produces both retrom-runtime-provider-0.46.0.tar.gz and emulatorjs-provider-0.46.0.tar.gz, plus an offline retrom-runtime-host-tool-0.46.0.tar.gz; manifests, client exports and release metadata all use 0.46.0. There is no maintained package version or per-Provider version in source. The repository is private to npm publishing; GitHub archives are the release artifacts.
Formal builds require a validated annotated tag at the released commit and RETROM_PROVIDER_BUILD_MODE=release. Untagged candidate builds use 0.0.0-dev. Every build emits runtime-inputs.json with the actual source-tree SHA, offline host tool and both verified Provider archive/client hashes. Candidates have release: null; tagged releases include the real tag and commit. PFB clients receive the installed base's verified manifest version.
Transport the host-tool archive and both Provider archives as three flat basenames alongside runtime-inputs.json. Provider records retain their providerId/archive paths; consumers take the validated basename for local-directory or HTTPS transport. The tracked descriptor fixes identity; a transport URL does not select hashes or source.
npm ci
npm run lint
npm run typecheck
npm test
npm run build
npm run package:checkBefore publishing a release tag, also run:
npm run provider:input:check
npm run provider:build
npm run provider:check
npm run release:buildThe ONS checkpoint implementation is pinned to the published immutable
retrom-core-0.7.7beta-r6 release. VecX is pinned to
retrom-core-g8f671cc9d737-r2. Normal builds download and verify the declared
release assets; no unpublished core archive transport is needed. The ONS
checkpoint-ready JavaScript binding is checked against the actual Wasm export
before packaging. Local PFB core candidates remain explicit development inputs
and do not replace these release pins.
For PFB upstream-sync validation, Butterscotch candidates include their metadata parser pair for integrity verification, but only the game runner and license override the installed Provider. The metadata tools are outside its public asset closure. EasyRPG candidates use the existing two-file JS/Wasm release contract; the installed Provider retains its separately collected license notices. These local inputs do not change release pins or Target declarations.
MIT
Each Target owns its host shortcut policy through hostKeyboardShortcuts. The public
PlayerRuntimeV1.getInputCapabilities() exposes the allowed PAUSE / MENU shortcuts;
setHostShortcutPolicy() selects explicit keyboard bindings and HOST_SHORTCUT events cross same-origin
and isolated game windows uniformly. Null policy disables interception; see the Provider Module guide.
The Host leaves undeclared shortcuts with the game and configures null while its overlays own input.
J2ME standard gamepads use the following phone actions. The Provider owns gamepad polling in the game frame and preserves the Host's input filter; the core owns physical keyboard input.
| Standard control | Phone action |
|---|---|
| D-pad / left stick | Up, down, left, right |
| A | Fire / confirm |
| B / Select | Right soft key |
| X / Start | Left soft key |
| Y | 1 |
| L1 / R1 | 3 / 7 |
| L2 / R2 | 9 / 0 |
| L3 / R3 | * / # |
Direction and Fire actions are separate from numeric keys 2, 4, 6, 8 and 5. Physical keyboard digits 0–9, star, hash and the core's existing soft-key bindings remain available. Start+Select chords remain reserved by the Host filter; gamepad keys are released on suppression, focus loss, pause, disconnection and exit.
The offline host tool's batch-content-bios-requirements command accepts up to 100 ordered items with directory, config, files, host-owned locators, optional installed biosFiles, and an optional allowed coreId (directory default otherwise). Each result has {biosRequirements, missingRomMembers, crcWarnings, error}; arrays are always present and errors are stable codes. Review reads entry/selected Parent ZIP directories and installed firmware evidence against the paired DAT. Required game/Parent/BIOS gaps or wrong sizes prevent publication; named, correctly sized CRC differences remain warnings for manual approval and optional trial play. optional and NO_DUMP entries are excluded; BAD_DUMP with a known CRC remains required. Firmware ownership is separate, unused ancestor ROMs are not required, and each core uses only its own saved romSet. These completeness facts are audit-only: prepareRuntime retains its existing launch checks. Review never assembles resources, rewrites original archives, or requires a browser trial. Failed inspection is unknown, never an empty successful result.
python3 scripts/arcade-facts.py --refresh --dat CORE=PATH regenerates required ROM facts and searchable labels from the exact DAT digest pinned in arcade-provenance.json. MAME and other XML DAT generators share optional/default BIOS/NO_DUMP semantics; refresh never imports DAT into a database. FBNeo's paired required-only DAT excludes BRF_OPT at export.
EmulatorJS launches collect bounded native output with RetroArch logging enabled independently of the EmulatorJS debug console. The same diagnostic buffer is used by MAME Current and preserves required-member and fatal messages through subsequent progress output. Copyright banners, ordinary notices and recoverable fallbacks are excluded. Fatal events retain sanitized core reasons and runtime traces after teardown; host presentation should show the failure category and CORE evidence, keeping RUNTIME traces in diagnostics. Collection does not change DAT acceptance, core bytes, game files, or checkpoint identity.
dos-entry-candidates accepts config, immutable files and host-owned locators, then returns {entries: string[]} from the selected DOS ZIP/DOSZ archive. Entries retain their complete safe paths, include .exe, .com and .bat without case restrictions, and are deduplicated and sorted by UTF-8 path. The query ignores any existing entryPath and does not prepare a Run, so a replaced archive can offer new choices even when its previous program is absent.
A checkpoint availability with requiredAction: "SELECT_PROGRAM" tells the host to show
program selection guidance. Provider-private Target options are interpreted only inside
the Provider.
The siglus platform/core/Target accepts an original directory containing
Scene.pck and Gameexe.dat (or Gameexe.ini). The language option is
explicit: configuration selects chs when both scene.chs and gameexe.chs
exist at the selected root, otherwise original. CHS overlays those resource
pairs and matching .g01 images without modifying source files. Patch DLLs
are never executed. Games requiring other patch behavior need separate validation.
The Target supports ON_DEMAND_AND_PRELOAD, using the same public Content I/O
Range readers and persistent cache as RPGMaker. Mounting the directory registers
only paths and sizes. Native file reads request bounded ranges as needed; explicit
full preload fills the same cache before startup. The core's synchronous file API
waits through WebAssembly JSPI (Suspending and promising), which the browser
must support. The bridge implements no separate downloader or resource cache.
Individual compressed files are still read whole by native decoders; embedded movie
PCM has a 64 MiB cap. Movie video frames are decoded incrementally.
Standard controls use the shared pointer cursor (directions
and left stick move, A confirms through the left mouse button, B uses right mouse).
Checkpoint semantics are GAME_SAVE: save using the game's native menu, synchronize
the complete save archive, import before a new instance starts, and load using the
game's menu. Settings alone do not qualify as progress. The adapter uses a fresh
per-instance overlay; the public Host owns user isolation, persistence and one gzip
layer. An acknowledgement applies only to the exported revision after persistence.
The core comes from the immutable retrom-core-g5f358ef1360b-r2 release of
retrom-project/siglus_rs. The source declaration pins the commit and every asset's
size and SHA-256. Complete dependency notices accompany the Provider; the core
Release also provides the exact corresponding source and rebuild/relink inputs.