Problem
"An emulator frontend in Electron" invites an immediate and reasonable objection, and the README doesn't answer it. A reader arrives at the frame-pacing claim in ## Features already primed to disbelieve it.
The objection is also mostly aimed at the wrong thing, which is worth saying out loud.
Proposal
A short, dry, self-aware section placed directly after ## Features, where the skepticism actually lands. It should concede real ground rather than being defensive — the humor only works if the accounting is honest.
The objection that's wrong: no JavaScript runs per frame. Cores are native behind an N-API addon, the loop is in its own utility process, frames cross via a lock-free double-buffered SharedArrayBuffer (shared-frame-protocol.ts) and audio via an SPSC ring buffer. V8 is not on the hot path.
The costs that are real:
- Input is forwarded renderer → main → utility process over IPC, per event (
preload.ts:107, core-worker.ts:692). Video and audio got shared memory; input did not. The control block has seven slots and none of them are for input.
- The loop spin-waits the last 2ms of every frame (
SPIN_THRESHOLD_MS) because timer granularity can't hit a 16.67ms deadline.
- Baseline memory is a browser engine before a ROM loads.
- Distribution is a signed app plus a per-architecture native addon plus core binaries.
Acceptance criteria
Notes
Overlaps #329 (Why GameLord positioning) — this covers the "why should I believe it works" half. #329 can stay scoped to the "why would I want it" half.
Problem
"An emulator frontend in Electron" invites an immediate and reasonable objection, and the README doesn't answer it. A reader arrives at the frame-pacing claim in
## Featuresalready primed to disbelieve it.The objection is also mostly aimed at the wrong thing, which is worth saying out loud.
Proposal
A short, dry, self-aware section placed directly after
## Features, where the skepticism actually lands. It should concede real ground rather than being defensive — the humor only works if the accounting is honest.The objection that's wrong: no JavaScript runs per frame. Cores are native behind an N-API addon, the loop is in its own utility process, frames cross via a lock-free double-buffered
SharedArrayBuffer(shared-frame-protocol.ts) and audio via an SPSC ring buffer. V8 is not on the hot path.The costs that are real:
preload.ts:107,core-worker.ts:692). Video and audio got shared memory; input did not. The control block has seven slots and none of them are for input.SPIN_THRESHOLD_MS) because timer granularity can't hit a 16.67ms deadline.Acceptance criteria
.claude/rules/inspiration-language.md)Notes
Overlaps #329 (Why GameLord positioning) — this covers the "why should I believe it works" half. #329 can stay scoped to the "why would I want it" half.