What's Changed
- feat(a8-web): add on-screen keyboard to the mobile OSD by @cyco130 in #3
- Acid800 accuracy improvements + dual-region CI by @cyco130 in #4
- feat: core-owned trapping, suspend primitive, and headless host by @cyco130 in #5
- fix(a8): latch P/M graphics across the full visible region (fixes River Raid PAL crash) by @cyco130 in #6
- fix(a8-web): report logical emulated FPS, not RAF observation rate by @cyco130 in #7
- feat(a8-web): add muted turbo mode (run unthrottled) by @cyco130 in #8
- feat(a8-web): /docs reference pages and keyboard lab by @cyco130 in #9
- feat(a8-web): ship the keyboard lab in the production build by @cyco130 in #10
- feat(a8-web): command palette by @cyco130 in #11
- Disk write support and attachment management by @cyco130 in #12
- Centralize user-facing strings in a messages catalog by @cyco130 in #13
- Toasts for config and media changes by @cyco130 in #14
- feat(a8-web): emit hashed assets to /_app/assets and add a 404 page by @cyco130 in #15
- feat(a8-web): add a full-screen toggle (command + double-click) by @cyco130 in #16
- feat(a8-web): replace UI glyphs with an SVG icon sprite by @cyco130 in #17
- ci: Cloudflare Pages deploy (gated prod, PR previews, cleanup) by @cyco130 in #18
- feat(a8-web): SPA routing (real URLs, deep-linkable panels, docs/labs as routes) by @cyco130 in #25
- fix(deps): update all non-major dependencies by @renovate[bot] in #20
- chore(deps): update actions/cache action to v6 by @renovate[bot] in #21
- chore(deps): update actions/checkout action to v7 by @renovate[bot] in #22
- chore(deps): update actions/github-script action to v9 by @renovate[bot] in #23
- chore(deps): update dependency @babel/core to v8 by @renovate[bot] in #24
- feat: rom selector by @cyco130 in #26
- a8-web image library: uploads, browsing, and disk write-back by @cyco130 in #27
- a8-web: machine-state persistence + recents by @cyco130 in #28
- a8-web: library view rework — pills, per-type tables, filtering, item details by @cyco130 in #29
- a8-web: faster, leaner bulk import by @cyco130 in #31
- a8-web: library item editing + smarter firmware preferences by @cyco130 in #32
- a8-web: library tags by @cyco130 in #33
- feat(a8-web): library zip import/export by @cyco130 in #34
- feat(a8-web): command press/release model + machine-config page by @cyco130 in #35
- feat(a8-web): configurable keyboard bindings — editor, modes, and layout-aware chords by @cyco130 in #37
- feat(a8-web): expand built-in keyboard layouts and localize the picker by @cyco130 in #36
- feat(a8-web): keyboard shortcut & command-label polish by @cyco130 in #38
- Gamepad support for a8-web by @cyco130 in #39
- fix(a8-web): stop swallowing unbound keys like F12 by @cyco130 in #40
- feat(a8-web): MDX docs subapp, prerendered to static HTML by @cyco130 in #41
- docs: refresh contributor/user notes; add design.md for a8 and a8-web by @cyco130 in #42
- fix(cli): full-range RAND; drop sfotty's dead microcode tokens by @cyco130 in #43
- fix(a8): CHACTL, ANTIC mode 3, and PF2 hires collisions by @cyco130 in #44
- fix(a8): XEX loader presents a completed boot; Reset re-boots the disk by @cyco130 in #45
- feat(a8-web): per-device gamepad remapping by @cyco130 in #46
- feat(a8-web): favorites game picker with gamepad navigation by @cyco130 in #47
- feat(a8-web): display settings — overscan, parametric palette, frame blending by @cyco130 in #48
- fix(a8): ANTIC/GTIA accuracy arc — beam-anchored pipeline, GTIA modes, 40→48 Acid800 by @cyco130 in #49
- fix(a8): IRQ latency, virtual DMA, and the playfield start/stop engine — 50→53 Acid800 by @cyco130 in #50
- fix(a8): player/missile DMA only fetches within the visible region by @cyco130 in #51
- fix(a8): GTIA write-timing anchor — color and P/M position writes a color clock earlier, luminance bit 0 dropped by @cyco130 in #52
- CLI revival, MMU/video perf arc, cartridge architecture, and the unknown-ROM flow by @cyco130 in #53
- fix(a8): SIO trap no longer fires with the OS ROM banked out by @cyco130 in #54
- feat(a8): connectors and devices - joystick ports, console panel, cartridge slot, keyboard by @cyco130 in #55
- refactor: cycle() naming, two-phase Mmu, surface-first member ordering by @cyco130 in #56
- fix(a8-web): Break key never registered - hold the KR2 line instead of a zero-length pulse by @cyco130 in #57
Full Changelog: 0.2.1...0.3.0