Releases: apiad/retrokix
v1.3.1 — Pokemon Yellow fix
Full Changelog: v1.3.0...v1.3.1
v1.3.0 — Game Boy + Game Boy Color
Full Changelog: v1.2.0...v1.3.0
v1.2.0 — stream QoS
Full Changelog: v1.1.0...v1.2.0
v1.1.0 — the game-hub release
Full Changelog: v1.0.0...v1.1.0
v1.0.0
Full Changelog: v0.20.0...v1.0.0
v0.20.0 — Three consoles
Third console lands: SNES via snes9x.
Highlights
- SNES support — bundled snes9x_libretro.so, runtime auto-picks
the core from the ROM extension (.sfc, .smc, .swc, .fig). `retrokix
browse` shows a third console badge color (amber #f59e0b) and
merges 4,122 No-Intro SNES entries + 51,561 cheats into the
unified library. - ~50 SNES classics added to the default browse cohort: Super
Mario World, A Link to the Past, Super Metroid, Chrono Trigger,
FFVI, Earthbound, Mega Man X 1-3, DKC 1-3, Star Fox, Castlevania
IV, Contra III, Killer Instinct, Secret of Mana, Seiken Densetsu
3, and more.
Upgrade path
```
pip install -U retrokix
retrokix download "super mario world"
retrokix play "mario world"
```
Coming next
A snapshot extension refresh is running in the background; the
top-100 marquee on apiad.github.io/retrokix will reshuffle to
include SNES titles once the Wikipedia-pageviews snapshot is
republished (couple of hours).
v0.19.0 — Retro consoles you can drive
First release under the retrokix name (was gbax).
Highlights
- NES support via bundled FCEUmm core — the runtime picks a core
from the ROM extension;retrokix browseshows a per-row console
badge and merges both libraries. - Wikipedia-fame ranking — 10,000+ ROM groups across GBA + NES
are scored by Wikipedia 12-month pageviews and shown with a 0–5
star column. Year-of-release category filter rejects franchise hubs
and shared-name non-games at resolve-time. - gbax → retrokix rename — old GitHub URLs auto-redirect; the
gbaxPyPI project is yanked.
Upgrade path
```
pip install retrokix
```
The CLI binary is now `retrokix` (was `gbax`). The env var that
points at a custom libretro core is now `RETROKIX_CORE_PATH` (was
`GBAX_CORE_PATH`).
v0.17.0 — browser play surface
Headline
The browser is now a first-class play surface. Boot Pokémon Emerald, scan a QR to your phone, and you're playing on the couch — no SDL window, no install on the phone.
gbax play emerald --no-sdl
# auto-opens http://127.0.0.1:8420/stream?mode=controller in your default browserWhat's new since v0.16.0
Browser stream (the big one)
GET /stream— self-contained HTML page with a stylish GBA-bezel viewer. Dark theme, status / fps / KB-per-frame HUD, 🔇/🔊 audio toggle.?mode=viewerjust watches;?mode=controlleradds the on-screen pad.WS /stream/ws— bidirectional WebSocket.- Server → client: framebuffer bytes. Default is raw RGBA8888 (240×160×4 = 153,600 B/frame, pixel-perfect, ~4.5 MB/s @ 30 fps).
?format=jpeg&quality=92switches to JPEG for constrained links. - Client → server:
{"type":"buttons","buttons":[...]}to drive input,{"type":"fast_forward","on":true}to TURBO. Sameruntime.set_buttonspath the SDL keyboard, USB gamepad, and couch already use — set-union all the way down.
- Server → client: framebuffer bytes. Default is raw RGBA8888 (240×160×4 = 153,600 B/frame, pixel-perfect, ~4.5 MB/s @ 30 fps).
WS /stream/audio/ws— live PCM s16le stereo @ 32 kHz via a newAudioBusfan-out. Browser decodes through an inlineAudioWorkletring buffer; click toggles, auto-resumes on first user gesture for iOS/Safari autoplay policy.- On-screen controller: D-pad, A/B (offset GBA style), L/R shoulders poking out the bezel, Select/Start pills, TURBO pill. Pointer Events handle multi-touch; keyboard shortcuts mirror the SDL play loop (arrows / X / Z / A / S / Enter / RShift). Dock layout flips between portrait (controls beneath the screen) and landscape (controls flanking the screen) — buttons never overlap the canvas.
gbax play --no-sdl
Skip the SDL window entirely. Runs a 60 Hz daemon thread, hosts the FastAPI server on the main thread, pops http://127.0.0.1:8420/stream?mode=controller in the user's default browser. Listen is implicit. The browser tab is the console.
Audio fixes
- Fast-forward dysync fixed. While
fast_forwardis set (local L-Shift, browser TURBO, or both),_on_audiomutes. Chipmunk audio gone. On the falling edge the SDL audio queue is cleared so the first normal samples don't sit behind a silence buffer. - New
gbax.api.audio_bus.AudioBus— many-producer many-consumer thread-safe PCM fan-out. Bounded per-subscriber queues; slow viewers drop chunks instead of blocking the play thread.
Gamepad support (USB / Bluetooth)
Plug in any pad SDL2's GameController DB recognizes (XInput, DualShock/DualSense, 8BitDo, Steam Controller, generic clones — most things with a USB connector). Multiple pads + the keyboard + the HTTP API + the browser combine via set-union. Hot-plug works. Default layout in docs/cli.md.
The couch — peer-to-peer plugin events
A new substrate for cross-instance plugin events. Two gbax instances on the same machine (or eventually across the internet) become "peers" in a "room" and trade typed events through a tiny broker.
gbax.couch.Broker+gbax.couch.Client— async Unix-socket fanout, capability-filtered receive.gbax.couch.handle.CouchHandle— sync façade the SDL play loop uses.gbax couch broker / send / listen / whoami / room-codeCLI.- Plugin API:
p.emit_couch("…"),@p.on_couch_event("…"),ctx.couch. Receive handlers fire on the SDL thread so they can safely touch the runtime. - Persistent identity at
~/.gbax/identity.json. Wireguard-style three-word room codes viagbax couch room-code(spunky-lilac-buck). - Demo plugin:
gbax.plugins.pokemon.emerald_couch— press G to gift a Master Ball to your first peer.
gbax browse — interactive ROM picker
gbax browse [<query>] — Textual TUI over the bundled 3,555-entry No-Intro index. Live filter as you type, ↑/↓ to navigate, Enter to download. Variants collapse into groups with (+N) badges; multi-variant groups open a modal picker. ROMs already in ~/.gbax/roms/ get a green ●. Empty search shows a curated list of ~100 famous GBA titles.
Landing page redesign
https://apiad.github.io/gbax/ — rotating 10-game screenshot showcase, three-audience cards, ascii art GBA bezel as the hero, and a 'Three commands' / 'Or, point-and-click' install path.
Try it
pip install --upgrade gbax
gbax download "pokemon emerald"
gbax play emerald --no-sdlMigrating from v0.16.0
No breaking changes. gbax play keeps the same CLI; --no-sdl is opt-in. All existing HTTP endpoints unchanged. Plugin API gained additions (emit_couch, @on_couch_event, ctx.couch); old plugins keep working.
Full diff
v0.16.0 — pokemon plugin suite (slice 1)
Refactor of the Emerald plugin into a namespace package with two complementary plugins and a shared logic library.
Migration (clean break): the --plugin argument changes:
- Old:
--plugin gbax.plugins.emerald_party - New:
--plugin gbax.plugins.pokemon.emerald --plugin gbax.plugins.pokemon.emerald_driver
Or for info-only sessions (no automation): --plugin gbax.plugins.pokemon.emerald alone.
This is slice 1 of 7 — the scaffolding step. Same behavior as v0.15.10, just reorganized. Slice 2 will rewrite the auto-fight using gMain.callback2 scene detection (replacing the ambiguous phase byte that caused the round 4-7 stuck loops).
Spec: vault/Atlas/Architecture/2026-06-10-pokemon-emerald-companion-suite.md.
v0.15.10 — forced-switch retry + longer settles
Two fixes for the forced-switch handler that was failing silently:
- Retry up to 3 times. The previous
forced_switch_attemptedflag was one-shot — if the first attempt failed (menu transient timing), we never retried and the advance loop fell through to normal handlers, looping on phase 5 pressing A on Lotad. - Longer settles. Live-walked the exact sequence manually with the wider settles (80/30/20/120/300 frames) and it worked. Bumped the auto handler to match.