Skip to content

Releases: logdog2325/pokebridge

v0.6.1 - second-scan fix, item picker, nickname editor

27 May 20:25

Choose a tag to compare

⚠️ Back up your saves first

Always back up .gci files with GCMM before using "Save to memory card." Self-verify still runs, but no undo if a bug slips past.

What's new since v0.6

🐛 The "second memcard scan" freeze — actually fixed this time

v0.6 fixed the cold-boot scan freeze. A tester immediately found the next one: scan once, do anything else (e.g. load from SD), then try to scan again → freeze. Root cause turned out to be much deeper than EXI lock state:

  1. The SD adapter sits on EXI channel 2 (SD2SP2 / serial port 2), not channel 0 or 1 as we'd assumed. v0.6's EXI_Unlock drain ran on the wrong channels.
  2. libogc's __exi_setinterrupts(EXI_CHANNEL_2) masks the channel 0 EXI IRQ on every channel-2 unlock, and only re-unmasks if a debugger is attached.
  3. CARD_Mount's state machine sleeps on that channel 0 EXI IRQ via LWP_ThreadSleep. With the IRQ masked, it never wakes. Freeze.
  4. fatUnmount("sd") doesn't release libfat's disc backend state — sdgecko_doUnmount(drv) is the missing call. GCMM does this between every SD/memcard switch.

The fix in pb_fat_release_for_card:

fatUnmount("sd");
sdgecko_doUnmount(0); sdgecko_doUnmount(1); sdgecko_doUnmount(2);
for (chn = 0..2) EXI_Unlock drain;
__UnmaskIrq(IRQ_EXI0_EXI);   // <-- THE FIX
EXI_ProbeReset();
// 2 vsync settle (was 30, no longer needed once cleanup is correct)

Diagnosed by reading libogc/exi.c lines 121-138 (the IRQ-share bug), libfat/source/disc.c lines 86-91 (the "sd" → gcsd2 mapping), and gcmm/source/main.c (the canonical SD-then-memcard recipe).

🆕 Held item editor (was a clear-to-zero button)

The "Held item" field in the editor was a clear-only stub. Now it opens a proper paged picker with a curated Gen 3 hold-item list:

  • All 43 Gen 3 berries (Cheri through Enigma)
  • All hold items 180-225: BrightPowder, White Herb, Macho Brace, Exp. Share, Quick Claw, Soothe Bell, Mental Herb, Choice Band, King's Rock, Silver Powder, Amulet Coin, Cleanse Tag, Soul Dew, Deep Sea Tooth/Scale, Smoke Ball, Everstone, Focus Band, Lucky Egg, Scope Lens, Metal Coat, Leftovers, Dragon Scale, Light Ball, the seven type-boost items, Shell Bell, Sea/Lax Incense, Up-Grade, Lucky Punch, Metal Powder, Thick Club, Stick
  • L/R pages, A equips, Y clears

Per-game legality filtering: items 175 (Enigma Berry) and 226 (Stick) are hidden when editing XD/Colosseum saves because those games reject them. Verified via PKHeX's ItemStorage3{RS,E,FRLG,Colo,XD} tables — everything else in the curated list is universal across all five games.

🆕 Nickname editor

New "Nickname" field at the bottom of the edit list. Opens an on-screen keyboard:

  • 4×8 grid, 3 layouts cycled via X (A-Z / a-z / 0-9 + .-!?)
  • D-Pad moves the cursor, A appends, L deletes, R inserts space
  • START confirms, B cancels
  • Pre-fills with the current nickname so you can backspace + edit

Writes back to the right place per format:

  • PK3 (Gen 3 GBA): writes Gen 3 charset to p->nickname
  • XK3 (XD): writes UTF-16 BE to raw + 0x4E and 0x64
  • CK3 (Colosseum): writes UTF-16 BE to raw + 0x2E and 0x44

🆕 EV editor: Gen 3 legal caps (carried over from v0.6 but undocumented)

EVs are properly capped per Gen 3 rules:

  • 252 per stat (anything 253-255 is wasted — stats only update on multiples of 4)
  • 510 total across all six stats
  • Running total + remaining displayed; increments past 510 get clamped to whatever room is left
  • "AT TOTAL LIMIT" flash when capped

Status

Format Read Edit Write Create
Gen 3 GBA (Ruby/Sapphire/Emerald/FireRed/LeafGreen)
pokeemerald-expansion ROM hacks
Pokémon XD: Gale of Darkness (SD + memcard) ✅ (Phase 1)
Pokémon Colosseum (SD + memcard) ✅ (Phase 1)
GBA cart over link cable 🟡 ported, blocked by SI-mod hardware n/a n/a n/a
Pokémon Box: Ruby & Sapphire 🟡 memcard detection only

Install

Drop the attached pokebridge.dol onto your Swiss SD at sd:/apps/pokebridge/boot.dol and boot via Swiss. Works on real GameCube + Wii in GC mode.

Credits

PKHeX (XK3/CK3 byte layouts, item legality, EV rules), Suloku's GCMM (the sdgecko_doUnmount recipe for the second-scan freeze), Extrems (libasnd/libcard diagnosis), devkitPro (libogc + the source that let us actually find the IRQ-mask bug).

v0.6 - Pokemon creator (XD + Colosseum + Gen 3), EV legality, cold-boot scan fix

27 May 19:58

Choose a tag to compare

⚠️ Back up your saves first

v0.6 carries forward v0.5's memory-card writeback. Always back up your .gci files with GCMM before using "Save to memory card." The self-verify step still runs, but there's no undo if a bug slips past.

What's new since v0.5

🆕 Pokemon creator for empty slots — XD and Colosseum

The Phase 1 creator (added late in v0.5 for GBA Gen 3) now covers Pokemon XD and Pokemon Colosseum too. Press A on any empty box or party slot → confirm → pick species → drops into the regular editor for tweaks.

  • pb_xk3_create_default builds a full 196-byte XK3 record (XD)
  • pb_ck3_create_default builds a full 312-byte CK3 record (Colosseum)
  • Defaults: level 5, Tackle, IVs/EVs 0, friendship 70, Poké Ball, no shadow status, English NTSC-U
  • Inherits your save's OT name / TID / SID so the mon shows as yours
  • Auto-nicknames with the species name (matches what the games do for freshly caught mons)
  • National-dex → XD/Colosseum internal species ID via PKHeX's Table3NationalToInternal (the games share this table)
  • Validity bits set correctly (XK3 0x1D XDPKMFLAGS, CK3 0xCD) so XD/Colo won't reject the record
  • ShadowID = 0, so no Purification table entanglement

XD and Colosseum load these without complaint. PKHeX will flag them as illegal (no encounter generator match), and they'll be quarantined by Pokemon HOME. Phase 2 ports PKHeX's MethodH/E PID-IV generators for HOME-eligible creation.

🆕 EV editor enforces Gen 3 legal caps

The EV editor now respects what's actually legal in Gen 3:

  • Per-stat max: 252 (anything 253-255 is wasted — stats only update on multiples of 4)
  • Total max: 510 across all six stats
  • Increments that would overflow the total are clamped to whatever room is left
  • Running Total X / 510 and Remaining Y displayed prominently
  • "AT TOTAL LIMIT" flash when capped, "Near limit" warning within 8 of cap
  • Progress bars now scale to 252 (so maxing a stat fills the bar)
  • A button: max selected stat (252 if room, otherwise whatever's left)
  • START: zero selected stat (frees up total)

You can still hit 510 exactly via legal spreads like 252/252/6 or 252/252/4 = 508.

🐛 Cold-boot memory-card scan fix (the big one)

v0.5 had a tester-reported bug where the first memcard scan after a fresh power-on would freeze on slot A. Running GCMM first to back up a save unfroze it, but that was an awful workaround.

Root cause, diagnosed via real-hardware testing:

  • libaesnd init on cold-boot EXI state breaks subsequent CARD_Mount. Even though the research says libaesnd should coexist with libcard, on a fresh EXI bus the DSP init disturbs the controller in a way CARD_Mount can't recover from.
  • After GCMM has touched the bus, EXI is "warmed up" enough that AESND init no longer breaks it.

Fix: defer pb_audio_init until after the user's first menu action. The flow is:

  1. Boot → menu appears silent
  2. User picks first action (memcard scan, demo load, etc.)
  3. Action completes → return to main menu → AESND inits → music starts on the first playlist track
  4. Subsequent memcard ops pause/resume music via the existing AESND_Pause path

You lose music for ~3 seconds at boot. You gain a memcard scan that works on cold power-on without GCMM warmup.

Also added (defense in depth, didn't hurt to have):

  • CARD_Probe before CARD_Mount — skip empty slots immediately instead of hanging
  • EXI_Unlock drain + EXI_Detach before each memcard op — clears any libfat-held lock state on the shared EXI channel
  • 500 ms VSync settle between the unlock and the mount — EXI debounce
  • Per-slot UI feedback — "Scanning slot A..." / "Scanning slot B..." renders before each attempt, so freezes show exactly which slot is the problem (helped pin down the root cause)

🐛 Explicit Swiss reload-stub jump on exit

Picking "Exit" from the main menu was returning to the GameCube IPL (boot logo) instead of Swiss. Plain return 0 from main() only invokes the STUBHAXX magic check in modern libogc (~2021+); older devkitPPC builds just SYS_HOTRESET to IPL.

Fix: check for the reload stub at 0x80001800 (STUBHAXX magic at 0x80001804..0x8000180B, or legacy PSO-SDload mfmsr r3 instruction at 0x80001800) and jump explicitly. Falls back to SYS_HOTRESET if no stub present.

The confirm screen now reads stub state and shows "Return to Swiss?" vs "Return to GameCube IPL?" accurately.

Status

Format Read Edit Write Create
Gen 3 GBA (Ruby/Sapphire/Emerald/FireRed/LeafGreen)
pokeemerald-expansion ROM hacks (Seaglass, Lazarus, etc.)
Pokémon XD: Gale of Darkness (SD + memcard) ✅ (Phase 1)
Pokémon Colosseum (SD + memcard) ✅ (Phase 1)
GBA cart over link cable 🟡 ported, blocked by SI-mod hardware n/a n/a n/a
Pokémon Box: Ruby & Sapphire 🟡 memcard detection only

Install

Drop the attached pokebridge.dol onto your Swiss SD at sd:/apps/pokebridge/boot.dol and boot via Swiss. Works on real GameCube hardware and Wii in GameCube mode (Nintendont, Swiss-r, disc-channel backcompat).

Credits

PKHeX (XK3/CK3 byte layouts + species mapping table), Suloku's GCMM (the EXI_Unlock + Detach + retry recipe that fixed cold-boot scan), Extrems (libasnd-vs-libcard diagnosis), TuxSH's PkmGCTools, and devkitPro.

v0.5 - Memcard writeback, music, safer exit

27 May 17:00

Choose a tag to compare

⬆ Superseded by v0.6

v0.6 carries every feature of v0.5 plus the Pokemon creator for XD/Colosseum, Gen 3 EV legality caps, the cold-boot memcard scan fix, and the proper Swiss exit. Grab v0.6 unless you specifically need this build.


⚠️ Back up your saves first

v0.5 introduces direct memory-card writeback. Always back up your .gci files with GCMM first. The bytes you write replace what's on the card with no undo.

What's in v0.5

Memory-card writeback (XD + Colosseum)

After the v0.4 scan/read path, you can now save edited Pokémon back to the physical memory card via "Save to memory card" in the memcard submenu.

  • Self-verify before write: PokéBridge re-parses its own re-encrypted output before touching CARD_Write. If our checksum/encryption logic produces a save we can't even round-trip ourselves, we refuse to write and tell you instead of stomping the card.
  • PKHeX-correct body checksum: the body checksum at slot 0x10..0x20 is stored in PKHeX's reverse word order (a prerelease build got this wrong and corrupted a tester save).
  • GCMM-canonical I/O pattern: CARD_SetGamecode/SetCompany + CARD_Open, matching Suloku's GCMM. Sector-aligned writes via CARD_GetSectorSize.
  • Pokémon Box is detection-only — parser not implemented yet.

Background music

  • 3-track playlist (Title / Match Intro / Colosseum) loops gaplessly via libaesnd + a software timer that advances tracks at each track's natural duration.
  • Why libaesnd, not libasnd? libasnd's DSP task spin-loops on mailbox handshakes in IRQ context and races EXI completion, deadlocking CARD_Mount. Diagnosed publicly by Extrems. Swiss / Wii64 / pcsxgc all use libaesnd for the same reason.
  • BYO songs: drop WAVs in data/ and run python3 tools/embed_audio.py {title,match,colosseum} data/your_song.wav. The embed tool byte-swaps 16-bit PCM to BE for the GameCube DSP.
  • Audio headers are gitignored; setup_assets.sh writes silent stubs if you skip them.

Exit-to-loader UX

  • Picking "Exit" shows a confirmation screen, then returns to Swiss / IPL.
  • START is a global exit shortcut from the main menu.

Install

Drop the attached pokebridge.dol onto your Swiss SD at sd:/apps/pokebridge/boot.dol.

PokéBridge v0.4.3 — Joybus debug screen

27 May 02:23

Choose a tag to compare

Diagnostic-only release in response to ongoing link-cable testing where multiple GBAs sit on the GAME BOY splash without being detected.

Added: Joybus debug screen

Hold the Z trigger while selecting "Read GBA cart via link cable" from the main menu. Instead of the normal flow you'll get a live SI debug screen that prints the raw SI_GetTypeAsync response for all 4 controller ports, refreshed every frame.

What the values mean:

  • 0x00000000 — no device on this port, silent bus
  • 0x80 or bit 8 set — device responding but BIOS not ready (retry)
  • bit 0x40000 set — GBA detected!
  • 0x09000000 etc — GameCube controller

Plug your GBA in (no cart, powered on, official DOL-011 cable) and watch the values. If all 4 ports stay 0x00000000, the SI bus isn't seeing the cable at all. If a port toggles 0x80 / bit 8, the GBA is on the bus but its BIOS isn't reporting ready. Either way, the readings tell us exactly where to look.

Clarification on GBA splash behavior

Earlier release notes claimed the GBA should transition from the GAME BOY splash to a gradient/swirl multiboot wait screen — this was wrong. The GAME BOY splash IS the multiboot wait state for most BIOS revisions; the gradient/swirl is the loading screen during multiboot transfer (after packets have already arrived).

So "GBA sitting on GAME BOY" is the correct state to start the dump from. The bug PokéBridge is hitting is upstream of multiboot — we're not detecting that a GBA is on the bus at all.

Files

pokebridge-v0.4.3-release.dol — drop into sd:/apps/pokebridge/boot.dol.

No other changes from v0.4.2. All Gen 3 / XD / Colosseum read/edit/write paths unchanged.

PokéBridge v0.4.2 — looser ROM-hack cart handling

27 May 01:28

Choose a tag to compare

Patch release in service of ROM-hack carts on the link-cable path.

Loosened

  • Longer timeouts on cart handshake, size detection, and dump start (now ~10s each). Flash carts (EZ-Flash, Everdrive GBA, etc.) take longer than retail SRAM to respond on first contact.
  • Larger save buffer (516 KB, up from 129 KB) to cover the full GBA SRAM range. ROM hacks with custom-engine larger saves now fit.
  • No game ID filtering. Non-standard cart headers ("BPRX" instead of "BPRE", custom company IDs, gbasize of -1, etc.) pass through to the downstream parser instead of being rejected upstream.
  • Raw save auto-saved to SD before parsing. Every successful dump is written to sd:/pokebridge/saves/cart_<game_id>.sav immediately, so even if the parser rejects the data, the user still has a usable .sav for PKHeX or other tools.

Notes for ROM hack testers

If your hack is based on pokeemerald, pokefirered, or pokeruby (incl. pokeemerald-expansion), the save format itself is unchanged — only the species/move/item IDs differ. PokéBridge's parser handles that range automatically and the legalizer maps non-Gen-3 species back to Gen 3 analogues.

If your hack uses a custom save engine that doesn't follow Gen 3's 14-section / 4096-byte structure, the parser will reject it — but you'll still get the raw .sav file on the SD card via the auto-save step.

Files

pokebridge-v0.4.2-release.dol — drop into sd:/apps/pokebridge/boot.dol.

PokéBridge v0.4.1 — link cable detection fix

27 May 01:25

Choose a tag to compare

Minor patch release in response to tester feedback from gc-forever.

Fixed

  • GBA link cable detection now polls all 4 ports continuously with retries on transient "not ready" responses, up to 30 seconds while you finish powering on the GBA. Previous v0.4 bailed after a fraction of a second, before the GBA BIOS finished its splash and entered multiboot wait.
  • Replaced the link-cable screen with a live polling UI (progress counter, clearer instructions, things-to-check hints on timeout).

Note for testers

The GBA needs to be in raw BIOS multiboot mode — power it on with NO cart inserted, wait until it transitions from the GAMEBOY splash to the gradient/swirl screen (5-15 seconds), then PokéBridge will detect it. Pokemon Box's cart-side link protocol is different and won't be comparable.

If anyone with a GBA-to-GameCube link cable (DOL-011, not a GBA-GBA cable) can try this and report whether the dumper-side ROM transfer succeeds, I'd really appreciate it.

Files

pokebridge-v0.4.1-release.dol — drop into sd:/apps/pokebridge/boot.dol.

All v0.4 features (Gen 3 + XD + Colosseum read/edit/write, 1025 species sprites, etc.) are unchanged.

PokéBridge v0.4 — initial public release

26 May 18:31

Choose a tag to compare

First public release of PokéBridge.

What's in the box

  • Reads + edits + writes Gen 3 GBA saves (Ruby/Sapphire/Emerald/FireRed/LeafGreen) and pokeemerald-expansion ROM hacks (Seaglass, Lazarus, etc.)
  • Reads + edits + encrypted-writeback for Pokémon XD: Gale of Darkness and Pokémon Colosseum (.gci files extracted from a memory card)
  • Full Pokémon Box: Ruby & Sapphire-inspired SDL2 graphics UI
  • All 1025 species + shiny sprites (4bpp + palette compressed, ~2 MB)
  • Per-Pokémon editor: IVs, EVs, moves (354-move picker), nature, shiny toggle, friendship, held item
  • Legalizer that exports HOME-eligible .pk3 files (ROM-hack species/moves remapped to nearest Gen 3 analogue)
  • Box art preview for all 8 mainstream Gen 3-era games
  • GBA cart save read via link cable (FIX94 multiboot port; untested without a cable)

Installation

Download pokebridge-v0.4-release.dol, rename to boot.dol, place on your Swiss-formatted SD card at sd:/apps/pokebridge/boot.dol. Drop save files into sd:/pokebridge/saves/. Boot via Swiss → select the .dol.

Building from source

See BUILDING.md — needs devkitPPC + devkitARM + Python with Pillow.

Credits

Standing on the shoulders of PKHeX (kwsch), FIX94's gba-link-cable-dumper, pokeemerald-expansion (rh-hideout), and devkitPro. Full attribution in CREDITS.md.

GPL-3.0 licensed. "Pokémon" is a trademark of Nintendo / Game Freak / The Pokémon Company.