Skip to content

Add joybus support and boot to bios#319

Open
ubergeek77 wants to merge 1 commit intolibretro:masterfrom
ubergeek77:feature/joybus
Open

Add joybus support and boot to bios#319
ubergeek77 wants to merge 1 commit intolibretro:masterfrom
ubergeek77:feature/joybus

Conversation

@ubergeek77
Copy link

This PR was motivated by me really wanting to use the AYN Thor's second screen to play GBA games and connect them to Dolphin. Dolphin Android doesn't support the integrated mGBA, but it secretly supports the GBA (TCP) controller type via an .ini setting. So I figured, the JoyBus code is there in this core, and it already works on Dolphin Android - why not make it usable?

So I did! I think it speaks for itself:

https://youtu.be/ovBZBhBkX_4

Technical notes about this PR:

  • When the setting is enabled, the core will try connecting to Dolphin every 60 frames. This doesn't require a core restart, it can be enabled/disabled at any time even with a game running.

  • A previous draft of this had no platform-specific macros, and builds for PS2 and Wii would fail. I could have fixed them, but I wanted to avoid accidental platform-specific networking quirks on platforms that can't even use this feature. So now this feature is off by default and enabled for platforms where it makes sense.

  • src/platform/libretro/libretro.c

    • I saw a TODO to set RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME. I left the TODO as-is, since I'm not sure what the intent behind the TODO was, and I only conditionally set this to true anyway. Booting to BIOS works fine now, so if it would be cleaner to set this for all platforms, I can change the PR to do that.
    • I add a core_init label so the "boot to bios" branch can jump to it without needing a ROM loaded.
  • src/gba/sio/dolphin.c

    • _processCommand would previously return 0 if there was no active connection. This doesn't matter for full ROMs, but on the GBA BIOS, dol->active seems to usually or always be false, so this return makes Dolphin kill the connection immediately.
    • Making JOY_RESET and JOY_POLL respond like they do in sio.c's GBASIOJOYSendCommand makes the connection stable and multiboot games work fine.
    • I don't claim to be an expert on GBA protocol specifics (is this change good?), but in my trial runs it's been very reliable. Without this change I could not get multiboot ROMs loaded, but with this change, the BIOS connection is stable and now multiboot works.
    • If it's a good change, then I might PR it to upstream mGBA as well, since the issue is also there on desktop mGBA.

Usage notes about this feature:

  • With this version of the core, you can now boot to the BIOS at any time. If you don't have a BIOS it will fail to load. If you have a BIOS but disable it in the core settings, it will show a white screen.
  • The JoyBus protocol is very latency sensitive as we well know. On localhost, it's generally fine, but you should expect at least some stutter. But games without real-time communication (Animal Island, Tiny Chao Garden) work great!
  • As shown in the video, real-time games like the Tingle Tuner in Wind Waker work pretty well, but with some stutter. Just idling doesn't seem to stutter though, so you can still walk around with little to no stuttering. But it will still stutter if the GC has a lot of updates to to send to the GBA.
  • Dolphin (not this core) seems to have an issue where it will just stop listening for JoyBus after you close a game and open a new one. It's ittermittent, but I've observed this on desktop and Android. Not sure what causes it, but completely closing/reopening Dolphin fixes it.

@hizzlekizzle
Copy link

Oh man, this is a welcome addition! I'll see if I can get some eyes on it.

@endrift
Copy link
Collaborator

endrift commented Feb 26, 2026

  • _processCommand would previously return 0 if there was no active connection. This doesn't matter for full ROMs, but on the GBA BIOS, dol->active seems to usually or always be false, so this return makes Dolphin kill the connection immediately.
  • Making JOY_RESET and JOY_POLL respond like they do in sio.c's GBASIOJOYSendCommand makes the connection stable and multiboot games work fine.
  • I don't claim to be an expert on GBA protocol specifics (is this change good?), but in my trial runs it's been very reliable. Without this change I could not get multiboot ROMs loaded, but with this change, the BIOS connection is stable and now multiboot works.
  • If it's a good change, then I might PR it to upstream mGBA as well, since the issue is also there on desktop mGBA.

No one had reported this issue to me previously. I should take a look.

@ubergeek77
Copy link
Author

Thanks for the warm reception! Let me know how I can help :)

@endrift Here's a quick 30 second example of that issue:

https://youtu.be/bwEuMUWuDdg

@hizzlekizzle
Copy link

if the non-libretro-specific bits are also needed and accepted upstream, that would be an ideal place to start, so we don't run into more problems down the line maintaining downstream changes to the codebase.

@ubergeek77
Copy link
Author

Thankfully the only thing that's non-libretro in this PR is pretty simple, it's just this:

diff --git a/src/gba/sio/dolphin.c b/src/gba/sio/dolphin.c
index 0bb783e76..4cce68b2f 100644
--- a/src/gba/sio/dolphin.c
+++ b/src/gba/sio/dolphin.c
@@ -203,7 +203,14 @@ int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate) {
        }
 
        if (!dol->active) {
-               return 0;
+               /* GBA BIOS: respond so Dolphin doesn't kill the connection */
+               if (buffer[0] == JOY_RESET || buffer[0] == JOY_POLL) {
+                       buffer[1] = 0x00;
+                       buffer[2] = 0x04;
+                       buffer[3] = 0x00;
+                       SocketSend(dol->data, &buffer[1], 3);
+               }
+               return bitsOnLine * CYCLES_PER_BIT - cyclesLate;
        }
 
        int sent = GBASIOJOYSendCommand(&dol->d, buffer[0], &buffer[1]);

I thought it'd be kinda rude to silently PR it to mgba at the same time as this PR, so I wanted to get some feedback here first from people more familiar with the protocol. It seems fine, it's taken partially from sio.c's connection code, and I even debugged mGBA desktop to sanity check those three bytes, but with a legacy protocol there's really no telling without an expert opinion :p

But if you want to get the discussion started over there, I can go PR just this bit now, let me know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants