Skip to content

Releases: apiad/retrokix

v1.3.1 — Pokemon Yellow fix

17 Jun 19:38

Choose a tag to compare

v1.3.0 — Game Boy + Game Boy Color

17 Jun 19:21

Choose a tag to compare

v1.2.0 — stream QoS

17 Jun 14:42

Choose a tag to compare

v1.1.0 — the game-hub release

16 Jun 23:36

Choose a tag to compare

v1.0.0

16 Jun 20:28

Choose a tag to compare

Full Changelog: v0.20.0...v1.0.0

v0.20.0 — Three consoles

16 Jun 18:07

Choose a tag to compare

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

16 Jun 16:53

Choose a tag to compare

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 browse shows 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
    gbax PyPI 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

13 Jun 21:46

Choose a tag to compare

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 browser

What'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=viewer just watches; ?mode=controller adds 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=92 switches to JPEG for constrained links.
    • Client → server: {"type":"buttons","buttons":[...]} to drive input, {"type":"fast_forward","on":true} to TURBO. Same runtime.set_buttons path the SDL keyboard, USB gamepad, and couch already use — set-union all the way down.
  • WS /stream/audio/ws — live PCM s16le stereo @ 32 kHz via a new AudioBus fan-out. Browser decodes through an inline AudioWorklet ring 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_forward is set (local L-Shift, browser TURBO, or both), _on_audio mutes. 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-code CLI.
  • 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 via gbax 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-sdl

Migrating 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...v0.17.0

v0.16.0 — pokemon plugin suite (slice 1)

11 Jun 01:14

Choose a tag to compare

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

10 Jun 23:19

Choose a tag to compare

Two fixes for the forced-switch handler that was failing silently:

  1. Retry up to 3 times. The previous forced_switch_attempted flag 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.
  2. 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.