From cfb739628749eddf8af27038e83e6e19543b96be Mon Sep 17 00:00:00 2001 From: NewGBAXL <81663474+NewGBAXL@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:29:19 -0500 Subject: [PATCH 1/2] Support Force Feedback Wheel Loosen arbitrary pad filtering, implement PAD_ControlForce(), add aliases and state defines --- include/ogc/pad.h | 19 +++++++++++++++++-- libogc/pad.c | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/include/ogc/pad.h b/include/ogc/pad.h index 83636fae..2ad89d79 100644 --- a/include/ogc/pad.h +++ b/include/ogc/pad.h @@ -19,6 +19,9 @@ #define PAD_MOTOR_RUMBLE 1 #define PAD_MOTOR_STOP_HARD 2 +#define PAD_FORCE_ON 3 +#define PAD_FORCE_OFF 2 + #define PAD_ERR_NONE 0 #define PAD_ERR_NO_CONTROLLER -1 #define PAD_ERR_NOT_READY -2 @@ -31,6 +34,7 @@ #define PAD_TRIGGER_Z 0x0010 #define PAD_TRIGGER_R 0x0020 #define PAD_TRIGGER_L 0x0040 +#define PAD_PEDAL_CONNECT 0x0080 #define PAD_BUTTON_A 0x0100 #define PAD_BUTTON_B 0x0200 #define PAD_BUTTON_X 0x0400 @@ -48,8 +52,16 @@ typedef struct _padstatus { u16 button; s8 stickX; s8 stickY; - s8 substickX; - s8 substickY; + union { + struct { + s8 substickX; + s8 substickY; + }; + struct { + s8 gas; + s8 brake; + }; + }; u8 triggerL; u8 triggerR; u8 analogA; @@ -96,6 +108,9 @@ u8 PAD_TriggerR(s32 chan); u8 PAD_AnalogA(s32 chan); u8 PAD_AnalogB(s32 chan); +#define PAD_Gas(chan) PAD_SubStickX(chan) +#define PAD_Brake(chan) PAD_SubStickY(chan) + sampling_callback PAD_SetSamplingCallback(sampling_callback cb); /*+----------------------------------------------------------------------------------------------+*/ diff --git a/libogc/pad.c b/libogc/pad.c index ceaa99b0..91126ec2 100644 --- a/libogc/pad.c +++ b/libogc/pad.c @@ -386,7 +386,7 @@ static void __pad_typeandstatuscallback(s32 chan,u32 type) __pad_type[__pad_resettingchan] = (type&~0xff); if(((type&SI_TYPE_MASK)-SI_TYPE_GC) - || !(type&SI_GC_STANDARD)) { + || (type == SI_GC_RECEIVER)) { __pad_doreset(); return; } @@ -437,6 +437,12 @@ static void __pad_enable(u32 chan) #endif __pad_enabledbits |= PAD_CHAN_BIT(chan); SI_GetResponse(chan,(void*)buf); + if (SI_GetType(chan) != SI_GC_KEYBOARD) { + SI_SetCommand(chan, (__pad_analogmode | 0x00400000)); + } + else { + SI_SetCommand(chan, 0x00540000); //Keyboard-specific polling command + } SI_SetCommand(chan,(__pad_analogmode|0x00400000)); SI_EnablePolling(__pad_enabledbits); } @@ -617,7 +623,9 @@ u32 PAD_Read(PADStatus *status) #ifdef _PAD_DEBUG printf("PAD_Read(%08x %08x)\n",buf[0],buf[1]); #endif - __pad_makestatus(chan,buf,&status[chan]); + if (type != SI_GC_KEYBOARD) { + __pad_makestatus(chan, buf, &status[chan]); + } #ifdef _PAD_DEBUG printf("PAD_Read(%08x)\n",status[chan].button); #endif @@ -833,6 +841,33 @@ void PAD_ControlMotor(s32 chan,u32 cmd) _CPU_ISR_Restore(level); } +void PAD_ControlForce(s32 chan, u32 cmd, s32 intensity) +{ + u32 level; + u32 mask, type; + + if (intensity >= 0x80) { + cmd |= 0x100; + } + else if (intensity > -0x80) { + cmd |= intensity + 0x80; + } + cmd &= 0x7FF; + + _CPU_ISR_Disable(level); + + mask = PAD_CHAN_BIT(chan); + if (__pad_enabledbits & mask) { + type = SI_GetType(chan); + if (type == SI_GC_STEERING) { + cmd |= 0x300000; + SI_SetCommand(chan, cmd); + SI_TransferCommands(); + } + } + _CPU_ISR_Restore(level); +} + void PAD_SetSamplingRate(u32 samplingrate) { SI_SetSamplingRate(samplingrate); From f0fb0832a65c958ad5750bd298f6cbe0ab6d6656 Mon Sep 17 00:00:00 2001 From: NewGBAXL <81663474+NewGBAXL@users.noreply.github.com> Date: Wed, 25 Feb 2026 12:08:11 -0500 Subject: [PATCH 2/2] Remove FF Wheel aliases --- include/ogc/pad.h | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/include/ogc/pad.h b/include/ogc/pad.h index 2ad89d79..01ff5f3b 100644 --- a/include/ogc/pad.h +++ b/include/ogc/pad.h @@ -52,16 +52,8 @@ typedef struct _padstatus { u16 button; s8 stickX; s8 stickY; - union { - struct { - s8 substickX; - s8 substickY; - }; - struct { - s8 gas; - s8 brake; - }; - }; + s8 substickX; + s8 substickY; u8 triggerL; u8 triggerR; u8 analogA; @@ -108,9 +100,6 @@ u8 PAD_TriggerR(s32 chan); u8 PAD_AnalogA(s32 chan); u8 PAD_AnalogB(s32 chan); -#define PAD_Gas(chan) PAD_SubStickX(chan) -#define PAD_Brake(chan) PAD_SubStickY(chan) - sampling_callback PAD_SetSamplingCallback(sampling_callback cb); /*+----------------------------------------------------------------------------------------------+*/