Skip to content

Commit bb2a7b7

Browse files
gc: sticky-cache GCN detection to ride out GBA-disconnect transients
After a GBA cable pull, libogc's SI_GetType walks through transient values where bits 27-28 land on SI_TYPE_GC (sometimes with SI_GC_STANDARD set, sometimes not) before settling on NO_RESPONSE. The bare "(raw_type & SI_TYPE_MASK) == SI_TYPE_GC" fallback at the bottom of the per-port priority chain was latching that as a real GameCube controller, so the port re-labelled itself "GCN" for the window between the gba_state debounce expiring and libogc reaching NO_RESPONSE. Previously the same transients latched as "Wheel" and got the sticky-cache treatment in wheel_chan; this is the same problem one slot over. Fix: add gc_chan[4] parallel to kbd_chan/wheel_chan. - Latch true when (t & SI_TYPE_MASK) == SI_TYPE_GC && SI_GC_STANDARD set && no NO_RESPONSE. SI_GC_STANDARD covers wired controllers and Wavebird (which is GC | WIRELESS | STANDARD | ...). - Clear on NO_RESPONSE or on any definitive non-controller GC reading (keyboard, wheel) or a non-GC family type altogether. - Replace the bare-type fallback in the display priority chain with gc_chan[i]. Drops the unused raw_type local that the old fallback referenced. Tested on hardware: GBA disconnect now settles to "None" instead of flickering through GCN.
1 parent 3ad831c commit bb2a7b7

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

gc/ppc/main.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,14 @@ int main(int argc, char **argv) {
547547
// raw-type comparison flickers the port to "Wheel" for empty/
548548
// disconnected slots. Require a NO_RESPONSE-free read to latch.
549549
static bool wheel_chan[4] = {false, false, false, false};
550+
// Same sticky-cache treatment for standard GameCube controllers (wired
551+
// + Wavebird-over-receiver). After a GBA disconnect libogc's
552+
// SI_GetType walks through transients where the high bits land on
553+
// (SI_TYPE_GC | something) without SI_GC_STANDARD set; a bare
554+
// "(t & SI_TYPE_MASK) == SI_TYPE_GC" fallback latches that as GCN.
555+
// Require SI_GC_STANDARD + no NO_RESPONSE to set; clear on any
556+
// definitive non-controller GC reading or NORESP.
557+
static bool gc_chan[4] = {false, false, false, false};
550558
for (int i = 0; i < 4; i++) {
551559
u32 t = SI_GetType(i);
552560
u32 hi = (t & ~0xffff) & ~0x001F0000;
@@ -564,6 +572,14 @@ int main(int argc, char **argv) {
564572
(t & SI_TYPE_MASK) == SI_TYPE_GC)) {
565573
wheel_chan[i] = false;
566574
}
575+
if ((t & SI_TYPE_MASK) == SI_TYPE_GC && (t & SI_GC_STANDARD) &&
576+
!(t & SI_ERROR_NO_RESPONSE)) {
577+
gc_chan[i] = true;
578+
} else if ((t & SI_ERROR_NO_RESPONSE) ||
579+
(hi != 0 && ((t & SI_TYPE_MASK) != SI_TYPE_GC ||
580+
!(t & SI_GC_STANDARD)))) {
581+
gc_chan[i] = false;
582+
}
567583
}
568584

569585
// Detect any activity — wakes the screensaver and resets the idle timer.
@@ -653,7 +669,6 @@ int main(int argc, char **argv) {
653669
int base_row = 7;
654670
for (int i = 0; i < 4; i++) {
655671
pad_snap_t snap = {0};
656-
u32 raw_type = SI_GetType(i);
657672
// If our state machine knows this channel hosts a GBA (idle/booted/
658673
// retry/failed), force the GBA display path regardless of what
659674
// libogc's SI_GetType currently reports — during/after multiboot
@@ -694,7 +709,7 @@ int main(int argc, char **argv) {
694709
// angle / pedals is TODO (would mirror the keyboard's bespoke
695710
// poll path).
696711
snap.style = STYLE_WHEEL;
697-
} else if ((raw_type & SI_TYPE_MASK) == SI_TYPE_GC) {
712+
} else if (gc_chan[i]) {
698713
snap_gc(&snap, i, keysHeld[i]);
699714
}
700715
// STYLE_NONE leaves all zeros, including style="None"

0 commit comments

Comments
 (0)