Skip to content

Releases: logdog2325/dolphin-xd-netplay

OrreLink v1.5.13

OrreLink v1.5.13 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 07 Sep 00:46

Pre-release for testing. Supersedes v1.5.12. Not netplay-compatible with earlier versions.

Fixed — Android crash at team preview (host on the Thor)

The app aborted when a finger moved on the GBA screen during team preview. Every touch event re-registered the touch-overlay input override, rewriting a callback the emulation thread reads thousands of times a second without a lock; a poll landing in the rewrite window called an empty callback and the process died. Fixed in the core: those writers now take the same lock the pad poll holds, so a re-registration can never be observed half-done. The bug predates the recent releases; team preview just made it easy to hit.

Fixed — GBA controls on Windows (joiners had nothing mapped)

The launcher's GBA controls row only ever set up the first GBA slot, did not apply the binding to the running controller until a restart, and counted a mapping to an unplugged device as "mapped" — so a joiner could see a green row and still have no input. Use defaults now binds the keyboard explicitly on every GBA slot, applies it immediately, and the checklist only says mapped when the device really exists. Which slot is yours: GBA 1 when you join, GBA 2 when you host (the host also owns the GameCube controller, which takes the first slot). Until now the copy said GBA 1 for everyone.

The defaults are now WASD for the D-pad (A = X, B = Z, L = Q, R = E, Start = Enter, Select = Backspace). If you already had the old T/G/F/H keys saved, press Use defaults once to switch. A new Change GBA controls… button opens the GBA mapping window directly — Dolphin's own Controllers window hides it unless a port is set to GBA — and applies your mapping to every slot, so it holds whether you join or host.

New — Share Log on desktop

A Share Log… button at the bottom of the launcher saves the newest session log where you choose (Desktop by default) and opens that folder — the Windows log lives in a hidden AppData folder nobody could find. The README now gives the real paths for the by-hand route.

Platform File
Android (AYN Thor etc.) OrreLink-v1.5.13.apk
macOS (Apple Silicon) OrreLink-v1.5.13-macOS-arm64.zip
Windows x64 OrreLink-v1.5.13-win64.zip
Linux x86_64 OrreLink-v1.5.13-linux-x86_64.AppImage
Android debug symbols (not needed to play; for reading crash logs) OrreLink-v1.5.13-android-symbols.zip

OrreLink v1.5.12

OrreLink v1.5.12 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 06 Sep 19:51

Superseded by v1.5.13 — fixes the Android crash at team preview, GBA controls on Windows (WASD defaults, Change GBA controls… button), adds Share Log on desktop.

Pre-release for testing. Supersedes v1.5.11. Not netplay-compatible with earlier versions.

Fixed — battles ran at half speed in mixed-architecture rooms

v1.5.11's deterministic clock counted one video field per pass of XD's main loop — but XD runs one pass per two fields in battle, so battles ran at half speed while menus were normal. The clock now follows the SDK's own VI retrace count, sampled once per pass right after the retrace wait (a point that cannot straddle the recompiler skew), so battle timing matches hardware and every time-derived value stays identical on both machines. Dual core is turned off for the duration of a clock room (the successful 1.5.11 test already ran single core); the chat notice says so.

Fixed — imported teams had base happiness

Showdown imports set friendship to the species base value, so Return hit for a fraction of its power. Imports now assume maximum happiness unless the paste says otherwise: a Happiness: N line is honoured (0–255) on desktop and Android — Happiness: 0 for Frustration users.

New — the in-game location picker follows your Battle Style pick

When the host chooses a battle location in OrreLink, XD's own stage row on the VS-mode setup screen is pinned and shown blank, the same way the rules row is when a format is pinned, so the picker cannot contradict the host's choice. Left/right slides and snaps back. No location chosen: stock behaviour.

Logs

  • xd lines carry lf= (fields, 60/s everywhere) and new pf= (passes, 30/s in battle); xdclk gains S= F= R= dn=; the boot line gains xd_clock_v=2; corepolicy gains cpu_thread=.
Platform File
Android (AYN Thor etc.) OrreLink-v1.5.12.apk
macOS (Apple Silicon) OrreLink-v1.5.12-macOS-arm64.zip
Windows x64 OrreLink-v1.5.12-win64.zip
Linux x86_64 OrreLink-v1.5.12-linux-x86_64.AppImage

OrreLink v1.5.11

OrreLink v1.5.11 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 06 Sep 02:30

Superseded by v1.5.12 — fixes the half-speed battles in mixed-architecture rooms, gives imported teams max happiness, and pins the in-game stage row to the chosen location. Use that one.

Pre-release for testing. Supersedes v1.5.10. Not netplay-compatible with earlier versions.

Mixed-architecture rooms keep their recompilers — XD's clock is served deterministically instead

v1.5.10 fixed the Mac-vs-Windows desync by putting both machines on the Cached Interpreter, which turned out to be far too slow to play. This build removes the cause instead of the recompilers.

XD gets its time from exactly two functions, OSGetTick and OSGetTime. The two recompilers split code into blocks differently, and Dolphin's clock only advances at block ends, so those two functions returned values a few dozen cycles apart on the two machines — and XD builds its GBA link key from one of them (the first differing byte in the v1.5.9 logs, off by exactly the skew) and seeds its battle RNG from the other. In a room that mixes Apple Silicon or Android with Windows or Linux, OrreLink now replaces those two functions with a clock that is a pure function of the game's own frame counter plus a per-session value the host picks and syncs. Every time-derived value — link key, RNG seed, frame-pacing deltas — is then identical on both machines while each runs its own recompiler at full speed. Call sites that need real time (alarms, audio, save timestamps, reset) still get it; the ones that feed game state get the frame-exact value; the RNG seed and link key are host-synced constants.

  • Chat at Start: "Mixed CPU architectures (arm64 + x86_64): recompilers stay on; OrreLink serves XD's clock this battle …". The main menu is skipped in these rooms (the hook needs the game loaded directly).
  • Same-architecture rooms (Mac ↔ Thor, Windows ↔ Linux) and solo play are untouched: the clock is never installed there, and the boot line proves it (xd_clock=off).
  • ForceCommonCoreOnMixedArch is now an opt-in "safest" mode (default off) that reproduces v1.5.10's Cached Interpreter behaviour, for A/B testing.
  • Also pinned in mixed rooms: accurate NaN handling (x86 and ARM default NaNs have opposite signs).
  • The netplay time-base desync detector tolerates the few-tick recompiler skew when the clock is on, so it only fires on a real divergence.

Logs

  • Boot line gains xd_clock=on/off xd_clock_cfg= xd_salt= xd_seed= xd_period=.
  • xd lines gain lf= (XD's frame counter) and lt= (the logical time base) so two logs line up frame-for-frame; xdclk lines on the link events record the clock state.
  • A 30–60 second boot-plus-link capture on both machines is enough to prove the fix: the cpu lines must agree on everything but core/arch, the first xd line's seed=/lf=/lt= must match, and the link-key JoyBus write (15 dd …) must be byte-identical.
Platform File
Android (AYN Thor etc.) OrreLink-v1.5.11.apk
macOS (Apple Silicon) OrreLink-v1.5.11-macOS-arm64.zip
Windows x64 OrreLink-v1.5.11-win64.zip
Linux x86_64 OrreLink-v1.5.11-linux-x86_64.AppImage

OrreLink v1.5.10

OrreLink v1.5.10 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 05 Sep 19:04

Superseded by v1.5.11 — mixed-architecture rooms keep their recompilers (the Cached Interpreter was too slow); XD's clock is served deterministically instead. Use that one.

Pre-release for testing. Supersedes v1.5.9. Not netplay-compatible with earlier versions.

Fixed — Mac-vs-Windows (and any mixed-CPU) rooms desynced

A macOS host and a Windows guest played the same match and got different results: an attack missed on one machine and hit on the other. Both logs, aligned by link-cable command sequence instead of by time, show why:

  • The host sends its CPU core setting to the room. A Mac (Apple Silicon) host sends the ARM64 recompiler; a Windows build cannot construct that core, and Dolphin silently fell back to the x86-64 recompiler with no message anywhere. So the two machines were running XD on two different recompilers.
  • Two recompilers split code into blocks differently, and Dolphin only advances its clock at block boundaries, so the two machines' clocks drift apart by a few dozen cycles — visible in the logs well before the first GBA link.
  • XD reads that clock. The GBA link key is built from it at every key exchange (OSGetTick & 0xFFFFFF), and that is exactly where the two logs first differ: one byte, seconds into the session, off by precisely the 4 timer ticks the clock skew predicts. The battle RNG seed is also clock-derived (once, at boot). Which of the clock-dependent paths flipped the accuracy roll — the boot seed, the number of RNG calls before the move, or the GBA-side timing — is what the new log lines below will pin from the next test; every one of them disappears once both machines run the same core.

Fix: every player now tells the host its CPU architecture. If a room mixes architectures (Apple Silicon or Android with Windows or Linux), the host puts everyone on the Cached Interpreter — the one core all four builds share, with identical timing and arithmetic — and says so in chat. Rooms that don't mix (Mac ↔ Thor, Windows ↔ Linux) keep their fast recompilers, exactly as before. The Cached Interpreter is slower than a recompiler; on an Apple Silicon Mac and a recent Windows laptop XD should still hold full speed, and netplay throttles to the slower side. If it can't hold up, the host can set ForceCommonCoreOnMixedArch = False under [NetPlay] in Dolphin.ini to opt out (with the desync risk back).

Also closed while in there: the launcher's "Practice vs dummy" (which feeds fake GBA input locally) is now forced off inside any netplay room; a guest that is ever handed a core it can't build now says so in chat and uses the Cached Interpreter instead of a silent fallback; one accuracy setting (accurate_fmadds) was never actually transmitted to guests and is now forced on for everyone; one cache-accuracy setting that was never synchronized is now pinned; and the interpreter is compiled with floating-point contraction off so ARM64 and x86-64 builds compute identical bits.

New — logs that can prove a desync in one match

Every session log now records, on every machine:

  • cpu ... at boot: the core that actually ran (not just the one that was requested), the architecture, and every determinism-relevant setting. v1.5.9's Windows log would have read core_cfg=4 core_eff="JIT64".
  • xd ... lines during the link and battle: XD's RNG seed, the link-key generator state, and checksums of the battle state, keyed by link-command sequence number so two players' logs line up exactly. The first differing line names the moment and the kind of divergence.
  • ar ... at boot: the full set of Action Replay lines that will run (the host's Battle Style/format block on both the host and every guest), plus a send/receive checksum, so "was the host's block applied on the guest" is a one-line diff.

diff <(grep ' xd ' host.log | sed -E 's/^t=[0-9]+ //') <(grep ' xd ' guest.log | sed -E 's/^t=[0-9]+ //') should be empty for a clean match.

Fixed — launcher taller than the screen (Windows laptops)

The launcher's content now lives in a scroll area and the window opens no taller than the screen's working area. On a large screen it looks exactly as before; on a 768-px laptop it opens fitting the screen with a scrollbar instead of hanging off the bottom where Windows won't let it be dragged up. The Team Editor is capped the same way.

Platform File
Android (AYN Thor etc.) OrreLink-v1.5.10.apk
macOS (Apple Silicon) OrreLink-v1.5.10-macOS-arm64.zip
Windows x64 OrreLink-v1.5.10-win64.zip
Linux x86_64 OrreLink-v1.5.10-linux-x86_64.AppImage

OrreLink v1.5.9

OrreLink v1.5.9 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 01 Sep 22:51

Superseded by v1.5.10 — fixes the desync between different CPU architectures (Mac/Android vs Windows/Linux rooms), adds the logs that prove a match, and fits the launcher on small screens. Use that one.

Pre-release for testing. Supersedes v1.5.8. Not netplay-compatible with earlier versions.

Shorter, and it fits — community feedback

  • The Battle Style note and the Team Editor's slot note said everything twice. They now say it once: one line each on the launcher, two on the editor.
  • The "Models marked (no portrait)…" explainer is gone everywhere (launcher, Submit Team sheet, Android). The (no portrait) tag on each model is the explanation.
  • Desktop: notes no longer get clipped when the window opens shorter than its content. A word-wrapped label in Qt reports a one-line minimum height, so when the launcher opened at the two-thirds-of-screen height Qt clamps first shows to, the note rows were the only thing with slack and got squashed — hence "I have to stretch the window to read it". Every note now uses the size policy upstream Dolphin uses for the same thing, so it wraps correctly at any window size. Same fix applied in the Team Editor.
  • Tooltips carry the detail that left the visible text (host name field, raise-to-100 checkbox and button, trainer model).

GBA link progress: logged, not shown

v1.5.8 put the link phases ("negotiating", "uploading client 40%", "client starting") on screen. Per the field ask, those lines now go only to the gba_detect log (link-progress events, one per phase and one per 10% of the upload, counted per lock so rematches read right) — nothing is drawn during the connection screen. Detection itself is unchanged from 1.5.8, which connected every time in testing.

Platform File
Android (AYN Thor etc.) OrreLink-v1.5.9.apk
macOS (Apple Silicon) OrreLink-v1.5.9-macOS-arm64.zip
Windows x64 OrreLink-v1.5.9-win64.zip
Linux x86_64 OrreLink-v1.5.9-linux-x86_64.AppImage

OrreLink v1.5.8

OrreLink v1.5.8 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 01 Sep 21:15

Superseded by v1.5.9 — shorter notes that no longer clip, no portrait explainer, link progress logged instead of shown. Use that one.

Pre-release for testing. Supersedes v1.5.7. Not netplay-compatible with earlier versions.

New — the host can finally set their in-game name

The bundled Emerald saves ship as Player1 / Player2, and the only place a host could change that was the Team Editor's name field — which is why hosts were "always Player 1" while joiners got the name from their Submit Team sheet. The room now has a host-side counterpart: a trainer name field next to the chat on desktop, a Your trainer name card on Android. It writes the name into your GBA port 2 save on the spot (and re-stamps your party's OT names so nothing reads as traded), so the next battle shows it.

New — "No music" battle music

No music (silent battle) is now the first entry in the Battle Style music picker. It writes the game's own "start nothing" value into the VS battle-music table, which the sound engine checks for before it touches the music stream — so no stream is started, nothing can fault, and cries and hit sounds are untouched (they go through a separate path). Host-only, like every music pick.

New — "Raise to Lv. 100", opt-in only

  • Team Editor: a Raise all to Lv. 100 button, shown only when the selected format is a level-100 format. Stats are recomputed from each Pokémon's IVs, EVs and nature; moves, items and identity are untouched.
  • Submit Team (joiners): a Raise my team to Lv. 100 checkbox. The host applies it when injecting your team — and only if the host's format is level-100.

It never lowers a Pokémon. "Level 100 or lower" is legal, so a Lv. 70 team stays Lv. 70 unless you ask; a Lv. 50 format never touches levels at all (leveling down would break legality).

New — the GBA link tells you what it is doing

The ~45-second wait on XD's GBA Connection screen is a fixed cost: XD uploads a ~108 KB client program to each GBA in turn over the link cable (4 s handshake + upload + boot per socket). The screen now shows GBA port 2: link found, negotiating (~4 s), then uploading client 40% (~12 s left), then client starting — so you can tell "working" from "stuck" and stop pressing B into a live upload. Detection logic itself is unchanged.

Clarified — the first screen says who owns what

The launcher's Battle Style section now leads with HOST-ONLY: format, music and location come from whoever hosts; a joiner sets everything they control (team, trainer model, and now name) in the next window. Same copy on all platforms.

Also

  • The GitHub landing page now actually describes OrreLink (formats table, editor, Submit Team, Battle Style, what is and is not shared, the real GBA link timing).
Platform File
Android (AYN Thor etc.) OrreLink-v1.5.8.apk
macOS (Apple Silicon) OrreLink-v1.5.8-macOS-arm64.zip
Windows x64 OrreLink-v1.5.8-win64.zip
Linux x86_64 OrreLink-v1.5.8-linux-x86_64.AppImage

OrreLink v1.5.7

OrreLink v1.5.7 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 01 Sep 20:31

Superseded by v1.5.8 — host trainer name in the room, No music, raise-to-100, GBA link progress. Use that one.

Pre-release for testing. Supersedes v1.5.6 (whose team-preview fix is field-confirmed and carried forward). Not netplay-compatible with earlier versions.

Who controls what — now written where you look for it

Two questions from the community, answered in the app itself on every platform:

  • Team Editor slots. The editor's role selector now says it plainly: the Guest — GBA port 3 slot is only ever played in a room you host — it is the fallback team for a guest who never submits one. In a room you join, nothing from your editor is used: the host's saves replace yours at Start, and your team goes to the host through Submit Team instead. "Use my save" in that sheet sends the party from your Host — GBA port 2 slot.
  • Battle Style ownership. The launcher's Battle Style section now states which picks are the host's and which are yours: battle music and location are host-only (they travel with the host's synced settings), while trainer models are per player — a joiner picks theirs inside the Submit Team sheet, which beats the host's fallback dropdown.

Nothing about the battle itself changed in this build — it is the v1.5.6 engine with the clarity copy the community asked for.

Platform File
Android (AYN Thor etc.) OrreLink-v1.5.7.apk
macOS (Apple Silicon) OrreLink-v1.5.7-macOS-arm64.zip
Windows x64 OrreLink-v1.5.7-win64.zip
Linux x86_64 OrreLink-v1.5.7-linux-x86_64.AppImage

OrreLink v1.5.6

OrreLink v1.5.6 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 01 Sep 07:10

Superseded by v1.5.7 — same engine plus the who-controls-what clarity copy. Use that one.

Pre-release for testing. Supersedes v1.5.5. Not netplay-compatible with earlier versions.

Fixed — team-preview mugshots (the actual mechanism, finally)

A complete map of every portrait-drawing path in the game binary found why five straight patches missed: the preview mugshot bypasses the entire menu/element system they targeted. It is drawn by a low-level graphics routine with its own per-player texture pointer. The fix is a single branch: that routine's own built-in "no texture → draw nothing" path (what vanilla runs for an empty side) is now taken unconditionally in format sessions — one code write covering every preview layout (6v6, 3v3, 4-player), immune to reloads and races.

This release also removes the five inert patch layers from the failed attempts — they targeted lookalike screens and were pure risk. What ships is only field-proven machinery plus this one line.

Expected result: mugshot corners show the plain empty-side plate; Pokémon panels, names, icons and the connection screen's busts unchanged.

Reminder: the first boot after installing is slow to detect GBAs (cold shader cache — diagnosed, not a bug). Give it one patient boot.

Platform File
Android (AYN Thor etc.) OrreLink-v1.5.6.apk
macOS (Apple Silicon) OrreLink-v1.5.6-macOS-arm64.zip
Windows x64 OrreLink-v1.5.6-win64.zip
Linux x86_64 OrreLink-v1.5.6-linux-x86_64.AppImage

OrreLink v1.5.5

OrreLink v1.5.5 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 01 Sep 05:26

Superseded by v1.5.6 — fixes the mugshots at the actual drawing routine. Test on 1.5.6.

Pre-release for testing. Supersedes v1.5.4. Not netplay-compatible with earlier versions.

Fixed — team-preview mugshots, for real this time

The previous four attempts all failed for one reason, now identified: the game has several near-identical "VS preview" screens, each with its own drawing module, and every earlier patch targeted a lookalike — not the screen GBA-vs-GBA sessions actually use. This release disables the fifteen portrait-drawing calls inside the correct screen's own code (each one byte-verified against a clean disc image before shipping). Code patches of this kind cannot be raced or reloaded — the failure mode behind every previous miss.

Expected result: the mugshot boxes on team preview stay empty; Pokémon pictures, names and icons remain; the connection screen's matching busts are unchanged.

Also worth knowing — the GBA detection "regression" was diagnosed

A tick-by-tick comparison of the session logs shows the slow GBA detection after updating is cold shader-cache compilation on the first boot, not a bug in the builds: the detection handshake is bit-identical to healthy sessions, it just needs more retry windows while shaders compile. First boot after any update can take up to ~90 seconds to detect; every later boot links at normal speed (~40s). Give a fresh install one patient first boot.

Everything from 1.5.x is included: the six formats with working pick-4/pick-3, Hoenn singles, game-enforced clauses, the leftover-data security fix, and the launcher parity work.

Platform File
Android (AYN Thor etc.) OrreLink-v1.5.5.apk
macOS (Apple Silicon) OrreLink-v1.5.5-macOS-arm64.zip
Windows x64 OrreLink-v1.5.5-win64.zip
Linux x86_64 OrreLink-v1.5.5-linux-x86_64.AppImage

OrreLink v1.5.4

OrreLink v1.5.4 Pre-release
Pre-release

Choose a tag to compare

@logdog2325 logdog2325 released this 01 Sep 01:05

Superseded by v1.5.5 — the mugshot fix targeting the correct screen module. Test on 1.5.5.

Pre-release for testing. Supersedes v1.5.3. Not netplay-compatible with earlier versions.

Fixed — the team-preview faces are gone at the source

The faces survived three earlier patches because the screen has a hidden third drawing path: a per-frame routine that re-selects each player's portrait dynamically from a table of all fourteen bust images (which is why one side could show May while the other showed the default trainer — and why blanking individual images could never cover every case). v1.5.4 retargets exactly that routine's four dispatch entries at the game's own no-op — the old routine exists exactly four times in the entire binary, so there is provably no path left that can put a face on this screen.

What you'll see: each corner of the preview shows the game's plain "empty side" plate — the same thing vanilla shows for a side with no save. Pokémon pictures, party icons, and names are untouched, and the connection screen's bust handling is unchanged.

Everything from 1.5.x is included: the six formats with working pick-4/pick-3, Hoenn singles, game-enforced clauses, the leftover-data security fix, and the launcher parity work.

Platform File
Android (AYN Thor etc.) OrreLink-v1.5.4.apk
macOS (Apple Silicon) OrreLink-v1.5.4-macOS-arm64.zip
Windows x64 OrreLink-v1.5.4-win64.zip
Linux x86_64 OrreLink-v1.5.4-linux-x86_64.AppImage