tp/libs/dolphin/pad/Pad.c

847 lines
25 KiB
C

//
// Generated By: dol2asm
// Translation Unit: Pad
//
#include "dolphin/pad/Pad.h"
#include "MSL_C/MSL_Common/Src/string.h"
#include "dol2asm.h"
#include "dolphin/si/SIBios.h"
#include "dolphin/si/SISamplingRate.h"
u8 UnkVal : (OS_BASE_CACHED | 0x30e3);
u16 __OSWirelessPadFixMode : (OS_BASE_CACHED | 0x30E0);
/* 80450A20-80450A24 -00001 0004+00 1/1 0/0 0/0 .sdata __PADVersion */
static char* __PADVersion = "<< Dolphin SDK - PAD\trelease build: Apr 5 2004 04:14:49 (0x2301) >>";
//
// Forward References:
//
static void UpdateOrigin(s32 chan);
static void SPEC0_MakeStatus(s32 chan, PADStatus* status, u32 data[2]);
static void SPEC1_MakeStatus(s32 chan, PADStatus* status, u32 data[2]);
static void SPEC2_MakeStatus(s32 chan, PADStatus* status, u32 data[2]);
static s32 OnReset(s32 final);
static void SamplingHandler(OSInterrupt interrupt, OSContext* context);
static PADSamplingCallback PADSetSamplingCallback(PADSamplingCallback callback);
BOOL __PADDisableRecalibration(BOOL disable);
//
// External References:
//
void __shr2i();
extern u32 __PADFixBits;
//
// Declarations:
//
/* ############################################################################################## */
/* 8044CB70-8044CB80 079890 0010+00 3/3 0/0 0/0 .bss Type */
static u32 Type[4];
/* 8044CB80-8044CBB0 0798A0 0030+00 8/8 0/0 0/0 .bss Origin */
static volatile PADStatus Origin[4];
/* 80450A24-80450A28 0004A4 0004+00 7/7 0/0 0/0 .sdata ResettingChan */
SECTION_SDATA static s32 ResettingChan = 0x00000020;
/* 80450A28-80450A2C 0004A8 0004+00 1/1 0/0 0/0 .sdata XPatchBits */
SECTION_SDATA static u32 XPatchBits = PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT;
/* 80450A2C-80450A30 0004AC 0004+00 7/7 0/0 0/0 .sdata AnalogMode */
SECTION_SDATA static u32 AnalogMode = 0x00000300;
/* 8034E2B4-8034E458 348BF4 01A4+00 2/2 0/0 0/0 .text UpdateOrigin */
static void UpdateOrigin(s32 chan) {
PADStatus* origin;
u32 chanBit = (u32)PAD_CHAN0_BIT >> chan;
origin = &Origin[chan];
switch (AnalogMode & 0x00000700u) {
case 0x00000000u:
case 0x00000500u:
case 0x00000600u:
case 0x00000700u:
origin->trigger_left &= ~15;
origin->trigger_right &= ~15;
origin->analog_a &= ~15;
origin->analog_b &= ~15;
break;
case 0x00000100u:
origin->substick_x &= ~15;
origin->substick_y &= ~15;
origin->analog_a &= ~15;
origin->analog_b &= ~15;
break;
case 0x00000200u:
origin->substick_x &= ~15;
origin->substick_y &= ~15;
origin->trigger_left &= ~15;
origin->trigger_right &= ~15;
break;
case 0x00000300u:
break;
case 0x00000400u:
break;
}
origin->stick_x -= 128;
origin->stick_y -= 128;
origin->substick_x -= 128;
origin->substick_y -= 128;
if (XPatchBits & chanBit) {
if (64 < origin->stick_x && (SIGetType(chan) & 0xFFFF0000) == SI_GC_CONTROLLER) {
origin->stick_x = 0;
}
}
}
/* ############################################################################################## */
/* 80451848-8045184C 000D48 0004+00 1/1 0/0 0/0 .sbss Initialized */
static BOOL Initialized;
/* 8045184C-80451850 000D4C 0004+00 10/10 0/0 0/0 .sbss EnabledBits */
static u32 EnabledBits;
/* 80451850-80451854 000D50 0004+00 7/7 0/0 0/0 .sbss ResettingBits */
static u32 ResettingBits;
inline void PADEnable(s32 chan) {
u32 cmd;
u32 chanBit;
u32 data[2];
chanBit = (u32)PAD_CHAN0_BIT >> chan;
EnabledBits |= chanBit;
SIGetResponse(chan, data);
cmd = (0x40 << 16) | AnalogMode;
SISetCommand(chan, cmd);
SIEnablePolling(EnabledBits);
}
inline void DoReset(void) {
u32 chanBit;
ResettingChan = __cntlzw(ResettingBits);
if (ResettingChan == 32) {
return;
}
chanBit = (u32)PAD_CHAN0_BIT >> ResettingChan;
ResettingBits &= ~chanBit;
memset(&Origin[ResettingChan], 0, sizeof(PADStatus));
SIGetTypeAsync(ResettingChan, PADTypeAndStatusCallback);
}
/* 8034E458-8034E51C 348D98 00C4+00 1/1 0/0 0/0 .text PADOriginCallback */
static void PADOriginCallback(s32 chan, u32 error, OSContext* context) {
if (!(error &
(SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) {
UpdateOrigin(ResettingChan);
PADEnable(ResettingChan);
}
DoReset();
}
/* ############################################################################################## */
/* 80451854-80451858 000D54 0004+00 4/4 0/0 0/0 .sbss RecalibrateBits */
static u32 RecalibrateBits;
/* 80451858-8045185C 000D58 0004+00 7/7 0/0 0/0 .sbss WaitingBits */
static u32 WaitingBits;
/* 8045185C-80451860 000D5C 0004+00 6/6 0/0 0/0 .sbss CheckingBits */
static u32 CheckingBits;
/* 80451860-80451864 000D60 0004+00 6/6 0/0 0/0 .sbss PendingBits */
static u32 PendingBits;
/* 80451864-80451868 000D64 0004+00 6/6 0/0 0/0 .sbss BarrelBits */
static u32 BarrelBits;
inline void PADDisable(s32 chan) {
BOOL enabled;
u32 chanBit;
enabled = OSDisableInterrupts();
chanBit = (u32)PAD_CHAN0_BIT >> chan;
SIDisablePolling(chanBit);
EnabledBits &= ~chanBit;
WaitingBits &= ~chanBit;
CheckingBits &= ~chanBit;
PendingBits &= ~chanBit;
BarrelBits &= ~chanBit;
OSSetWirelessID(chan, 0);
OSRestoreInterrupts(enabled);
}
/* 8034E51C-8034E5E8 348E5C 00CC+00 2/2 0/0 0/0 .text PADOriginUpdateCallback */
static void PADOriginUpdateCallback(s32 chan, u32 error, OSContext* context) {
if (!(EnabledBits & ((u32)PAD_CHAN0_BIT >> chan))) {
return;
}
if (!(error &
(SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) {
UpdateOrigin(chan);
}
if (error & SI_ERROR_NO_RESPONSE) {
PADDisable(chan);
}
}
/* 8034E5E8-8034E6C0 348F28 00D8+00 1/1 0/0 0/0 .text PADProbeCallback */
static void PADProbeCallback(s32 chan, u32 error, OSContext* context) {
if (!(error &
(SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) {
PADEnable(ResettingChan);
WaitingBits |= (u32)PAD_CHAN0_BIT >> ResettingChan;
}
DoReset();
}
/* ############################################################################################## */
/* 80450A30-80450A34 0004B0 0004+00 4/4 0/0 0/0 .sdata Spec */
SECTION_SDATA static u32 Spec = 5;
/* 80450A34-80450A38 -00001 0004+00 2/2 0/0 0/0 .sdata MakeStatus */
SECTION_SDATA static void (*MakeStatus)(s32, PADStatus*, u32[2]) = SPEC2_MakeStatus;
/* 80450A38-80450A3C 0004B8 0004+00 3/3 0/0 0/0 .sdata CmdReadOrigin */
SECTION_SDATA static f32 CmdReadOrigin = 8.0f;
/* 80450A3C-80450A40 0004BC 0004+00 1/1 0/0 0/0 .sdata CmdCalibrate */
SECTION_SDATA static f32 CmdCalibrate = 32.0f;
/* 8044CBB0-8044CBC0 0798D0 0010+00 0/1 0/0 0/0 .bss CmdProbeDevice */
#pragma push
#pragma force_active on
static u32 CmdProbeDevice[4];
#pragma pop
/* 8034E6C0-8034E9EC 349000 032C+00 4/4 0/0 0/0 .text PADTypeAndStatusCallback */
static void PADTypeAndStatusCallback(s32 chan, u32 type) {
u32 chanBit;
u32 recalibrate;
BOOL rc = TRUE;
u32 error;
chanBit = (u32)PAD_CHAN0_BIT >> ResettingChan;
error = type & 0xFF;
recalibrate = RecalibrateBits & chanBit;
RecalibrateBits &= ~chanBit;
if (error &
(SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)) {
DoReset();
return;
}
type &= ~0xFF;
Type[ResettingChan] = type;
if ((type & SI_TYPE_MASK) != SI_TYPE_GC || !(type & SI_GC_STANDARD)) {
DoReset();
return;
}
if (Spec < PAD_SPEC_2) {
PADEnable(ResettingChan);
DoReset();
return;
}
if (!(type & SI_GC_WIRELESS) || (type & SI_WIRELESS_IR)) {
if (recalibrate) {
rc = SITransfer(ResettingChan, &CmdCalibrate, 3, &Origin[ResettingChan], 10,
PADOriginCallback, 0);
} else {
rc = SITransfer(ResettingChan, &CmdReadOrigin, 1, &Origin[ResettingChan], 10,
PADOriginCallback, 0);
}
} else if ((type & SI_WIRELESS_FIX_ID) && (type & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT &&
!(type & SI_WIRELESS_LITE)) {
if (type & SI_WIRELESS_RECEIVED) {
rc = SITransfer(ResettingChan, &CmdReadOrigin, 1, &Origin[ResettingChan], 10,
PADOriginCallback, 0);
} else {
rc = SITransfer(ResettingChan, &CmdProbeDevice[ResettingChan], 3,
&Origin[ResettingChan], 8, PADProbeCallback, 0);
}
}
if (!rc) {
PendingBits |= chanBit;
DoReset();
return;
}
}
/* 8034E9EC-8034EB2C 34932C 0140+00 1/1 0/0 0/0 .text PADReceiveCheckCallback */
static void PADReceiveCheckCallback(s32 chan, u32 type) {
u32 error;
u32 chanBit;
chanBit = (u32)PAD_CHAN0_BIT >> chan;
if (!(EnabledBits & chanBit)) {
return;
}
error = type & 0xFF;
type &= ~0xFF;
WaitingBits &= ~chanBit;
CheckingBits &= ~chanBit;
if (!(error &
(SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)) &&
(type & SI_GC_WIRELESS) && (type & SI_WIRELESS_FIX_ID) && (type & SI_WIRELESS_RECEIVED) &&
!(type & SI_WIRELESS_IR) && (type & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT &&
!(type & SI_WIRELESS_LITE)) {
SITransfer(chan, &CmdReadOrigin, 1, &Origin[chan], 10, PADOriginUpdateCallback, 0);
} else {
PADDisable(chan);
}
}
/* 8034EB2C-8034EC3C 34946C 0110+00 2/2 1/1 0/0 .text PADReset */
BOOL PADReset(u32 mask) {
BOOL enabled;
u32 diableBits;
enabled = OSDisableInterrupts();
mask |= PendingBits;
PendingBits = 0;
mask &= ~(WaitingBits | CheckingBits);
ResettingBits |= mask;
diableBits = ResettingBits & EnabledBits;
EnabledBits &= ~mask;
BarrelBits &= ~mask;
if (Spec == PAD_SPEC_4) {
RecalibrateBits |= mask;
}
SIDisablePolling(diableBits);
if (ResettingChan == 32) {
DoReset();
}
OSRestoreInterrupts(enabled);
return TRUE;
}
/* 8034EC3C-8034ED50 34957C 0114+00 1/1 1/1 0/0 .text PADRecalibrate */
BOOL PADRecalibrate(u32 mask) {
BOOL enabled;
u32 disableBits;
enabled = OSDisableInterrupts();
mask |= PendingBits;
PendingBits = 0;
mask &= ~(WaitingBits | CheckingBits);
ResettingBits |= mask;
disableBits = ResettingBits & EnabledBits;
EnabledBits &= ~mask;
BarrelBits &= ~mask;
if (!(UnkVal & 0x40)) {
RecalibrateBits |= mask;
}
SIDisablePolling(disableBits);
if (ResettingChan == 32) {
DoReset();
}
OSRestoreInterrupts(enabled);
return TRUE;
}
/* ############################################################################################## */
/* 803D1B90-803D1BA0 -00001 0010+00 1/1 0/0 0/0 .data ResetFunctionInfo */
SECTION_DATA static OSResetFunctionInfo ResetFunctionInfo = {
OnReset,
0x0000007F,
NULL,
NULL,
};
/* 80451868-8045186C 000D68 0004+00 3/3 0/0 0/0 .sbss SamplingCallback */
static void (*SamplingCallback)(void);
/* 8045186C-80451870 000D6C 0004+00 1/1 0/0 0/0 .sbss recalibrated$388 */
static BOOL recalibrated;
/* 80451870-80451878 000D70 0004+04 2/2 1/1 0/0 .sbss __PADSpec */
extern u32 __PADSpec;
u32 __PADSpec;
/* 8034ED50-8034EEA0 349690 0150+00 0/0 1/1 0/0 .text PADInit */
BOOL PADInit() {
s32 chan;
if (Initialized) {
return TRUE;
}
OSRegisterVersion(__PADVersion);
if (__PADSpec) {
PADSetSpec(__PADSpec);
}
Initialized = TRUE;
if (__PADFixBits != 0) {
OSTime time = OSGetTime();
__OSWirelessPadFixMode = (u16)((((time)&0xffff) + ((time >> 16) & 0xffff) +
((time >> 32) & 0xffff) + ((time >> 48) & 0xffff)) &
0x3fffu);
RecalibrateBits = PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT;
}
for (chan = 0; chan < SI_MAX_CHAN; ++chan) {
CmdProbeDevice[chan] =
(0x4D << 24) | (chan << 22) | ((__OSWirelessPadFixMode & 0x3fffu) << 8);
}
SIRefreshSamplingRate();
OSRegisterResetFunction(&ResetFunctionInfo);
return PADReset(PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT);
}
#define offsetof(type, memb) ((u32) & ((type*)0)->memb)
/* 8034EEA0-8034F1A0 3497E0 0300+00 0/0 1/1 0/0 .text PADRead */
u32 PADRead(PADStatus* status) {
BOOL enabled;
s32 chan;
u32 data[2];
u32 chanBit;
u32 sr;
int chanShift;
u32 motor;
enabled = OSDisableInterrupts();
motor = 0;
for (chan = 0; chan < SI_MAX_CHAN; chan++, status++) {
chanBit = (u32)PAD_CHAN0_BIT >> chan;
chanShift = 8 * (SI_MAX_CHAN - 1 - chan);
if (PendingBits & chanBit) {
PADReset(0);
status->error = PAD_ERR_NOT_READY;
memset(status, 0, offsetof(PADStatus, error));
continue;
}
if ((ResettingBits & chanBit) || ResettingChan == chan) {
status->error = PAD_ERR_NOT_READY;
memset(status, 0, offsetof(PADStatus, error));
continue;
}
if (!(EnabledBits & chanBit)) {
status->error = (s8)PAD_ERR_NO_CONTROLLER;
memset(status, 0, offsetof(PADStatus, error));
continue;
}
if (SIIsChanBusy(chan)) {
status->error = PAD_ERR_TRANSFER;
memset(status, 0, offsetof(PADStatus, error));
continue;
}
sr = SIGetStatus(chan);
if (sr & SI_ERROR_NO_RESPONSE) {
SIGetResponse(chan, data);
if (WaitingBits & chanBit) {
status->error = (s8)PAD_ERR_NONE;
memset(status, 0, offsetof(PADStatus, error));
if (!(CheckingBits & chanBit)) {
CheckingBits |= chanBit;
SIGetTypeAsync(chan, PADReceiveCheckCallback);
}
continue;
}
PADDisable(chan);
status->error = (s8)PAD_ERR_NO_CONTROLLER;
memset(status, 0, offsetof(PADStatus, error));
continue;
}
if (!(SIGetType(chan) & SI_GC_NOMOTOR)) {
motor |= chanBit;
}
if (!SIGetResponse(chan, data)) {
status->error = PAD_ERR_TRANSFER;
memset(status, 0, offsetof(PADStatus, error));
continue;
}
if (data[0] & 0x80000000) {
status->error = PAD_ERR_TRANSFER;
memset(status, 0, offsetof(PADStatus, error));
continue;
}
MakeStatus(chan, status, data);
// Check and clear PAD_ORIGIN bit
if (status->button & 0x2000) {
status->error = PAD_ERR_TRANSFER;
memset(status, 0, offsetof(PADStatus, error));
// Get origin. It is okay if the following transfer fails
// since the PAD_ORIGIN bit remains until the read origin
// command complete.
SITransfer(chan, &CmdReadOrigin, 1, &Origin[chan], 10, PADOriginUpdateCallback, 0);
continue;
}
status->error = PAD_ERR_NONE;
// Clear PAD_INTERFERE bit
status->button &= ~0x0080;
}
OSRestoreInterrupts(enabled);
return motor;
}
/* 8034F1A0-8034F258 349AE0 00B8+00 0/0 2/2 0/0 .text PADControlMotor */
void PADControlMotor(s32 chan, u32 command) {
BOOL enabled;
u32 chanBit;
enabled = OSDisableInterrupts();
chanBit = (u32)PAD_CHAN0_BIT >> chan;
if ((EnabledBits & chanBit) && !(SIGetType(chan) & SI_GC_NOMOTOR)) {
if (Spec < PAD_SPEC_2 && command == PAD_MOTOR_STOP_HARD) {
command = PAD_MOTOR_STOP;
}
if (UnkVal & 0x20) {
command = PAD_MOTOR_STOP;
}
SISetCommand(chan, (0x40 << 16) | AnalogMode | (command & (0x00000001 | 0x00000002)));
SITransferCommands();
}
OSRestoreInterrupts(enabled);
}
/* 8034F258-8034F2B8 349B98 0060+00 1/1 1/1 0/0 .text PADSetSpec */
void PADSetSpec(u32 spec) {
__PADSpec = 0;
switch (spec) {
case PAD_SPEC_0:
MakeStatus = SPEC0_MakeStatus;
break;
case PAD_SPEC_1:
MakeStatus = SPEC1_MakeStatus;
break;
case PAD_SPEC_2:
case PAD_SPEC_3:
case PAD_SPEC_4:
case PAD_SPEC_5:
MakeStatus = SPEC2_MakeStatus;
break;
}
Spec = spec;
}
/* 8034F2B8-8034F42C 349BF8 0174+00 1/1 0/0 0/0 .text SPEC0_MakeStatus */
static void SPEC0_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) {
status->button = 0;
status->button |= ((data[0] >> 16) & 0x0008) ? PAD_BUTTON_A : 0;
status->button |= ((data[0] >> 16) & 0x0020) ? PAD_BUTTON_B : 0;
status->button |= ((data[0] >> 16) & 0x0100) ? PAD_BUTTON_X : 0;
status->button |= ((data[0] >> 16) & 0x0001) ? PAD_BUTTON_Y : 0;
status->button |= ((data[0] >> 16) & 0x0010) ? PAD_BUTTON_START : 0;
status->stick_x = (s8)(data[1] >> 16);
status->stick_y = (s8)(data[1] >> 24);
status->substick_x = (s8)(data[1]);
status->substick_y = (s8)(data[1] >> 8);
status->trigger_left = (u8)(data[0] >> 8);
status->trigger_right = (u8)data[0];
status->analog_a = 0;
status->analog_b = 0;
if (170 <= status->trigger_left) {
status->button |= PAD_TRIGGER_L;
}
if (170 <= status->trigger_right) {
status->button |= PAD_TRIGGER_R;
}
status->stick_x -= 128;
status->stick_y -= 128;
status->substick_x -= 128;
status->substick_y -= 128;
}
/* 8034F42C-8034F5A0 349D6C 0174+00 1/1 0/0 0/0 .text SPEC1_MakeStatus */
static void SPEC1_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) {
status->button = 0;
status->button |= ((data[0] >> 16) & 0x0080) ? PAD_BUTTON_A : 0;
status->button |= ((data[0] >> 16) & 0x0100) ? PAD_BUTTON_B : 0;
status->button |= ((data[0] >> 16) & 0x0020) ? PAD_BUTTON_X : 0;
status->button |= ((data[0] >> 16) & 0x0010) ? PAD_BUTTON_Y : 0;
status->button |= ((data[0] >> 16) & 0x0200) ? PAD_BUTTON_START : 0;
status->stick_x = (s8)(data[1] >> 16);
status->stick_y = (s8)(data[1] >> 24);
status->substick_x = (s8)(data[1]);
status->substick_y = (s8)(data[1] >> 8);
status->trigger_left = (u8)(data[0] >> 8);
status->trigger_right = (u8)data[0];
status->analog_a = 0;
status->analog_b = 0;
if (170 <= status->trigger_left) {
status->button |= PAD_TRIGGER_L;
}
if (170 <= status->trigger_right) {
status->button |= PAD_TRIGGER_R;
}
status->stick_x -= 128;
status->stick_y -= 128;
status->substick_x -= 128;
status->substick_y -= 128;
}
inline s8 ClampS8(s8 var, s8 org) {
if (0 < org) {
s8 min = (s8)(-128 + org);
if (var < min) {
var = min;
}
} else if (org < 0) {
s8 max = (s8)(127 + org);
if (max < var) {
var = max;
}
}
return var -= org;
}
inline u8 ClampU8(u8 var, u8 org) {
if (var < org) {
var = org;
}
return var -= org;
}
#define PAD_ALL \
(PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_DOWN | PAD_BUTTON_UP | PAD_TRIGGER_Z | \
PAD_TRIGGER_R | PAD_TRIGGER_L | PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_Y | \
PAD_BUTTON_MENU | 0x2000 | 0x0080)
/* 8034F5A0-8034FA10 349EE0 0470+00 2/1 0/0 0/0 .text SPEC2_MakeStatus */
// lis and stw instruction order
#ifdef NONMATCHING
static void SPEC2_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) {
u32 type;
PADStatus* origin;
u32 chanBit;
status->button = (u16)((data[0] >> 16) & PAD_ALL);
status->stick_x = (s8)(data[0] >> 8);
status->stick_y = (s8)(data[0]);
switch (AnalogMode & 0x00000700) {
case 0x00000000:
case 0x00000500:
case 0x00000600:
case 0x00000700:
status->substick_x = (s8)(data[1] >> 24);
status->substick_y = (s8)(data[1] >> 16);
status->trigger_left = (u8)(((data[1] >> 12) & 0x0f) << 4);
status->trigger_right = (u8)(((data[1] >> 8) & 0x0f) << 4);
status->analog_a = (u8)(((data[1] >> 4) & 0x0f) << 4);
status->analog_b = (u8)(((data[1] >> 0) & 0x0f) << 4);
break;
case 0x00000100:
status->substick_x = (s8)(((data[1] >> 28) & 0x0f) << 4);
status->substick_y = (s8)(((data[1] >> 24) & 0x0f) << 4);
status->trigger_left = (u8)(data[1] >> 16);
status->trigger_right = (u8)(data[1] >> 8);
status->analog_a = (u8)(((data[1] >> 4) & 0x0f) << 4);
status->analog_b = (u8)(((data[1] >> 0) & 0x0f) << 4);
break;
case 0x00000200:
status->substick_x = (s8)(((data[1] >> 28) & 0x0f) << 4);
status->substick_y = (s8)(((data[1] >> 24) & 0x0f) << 4);
status->trigger_left = (u8)(((data[1] >> 20) & 0x0f) << 4);
status->trigger_right = (u8)(((data[1] >> 16) & 0x0f) << 4);
status->analog_a = (u8)(data[1] >> 8);
status->analog_b = (u8)(data[1] >> 0);
break;
case 0x00000300:
status->substick_x = (s8)(data[1] >> 24);
status->substick_y = (s8)(data[1] >> 16);
status->trigger_left = (u8)(data[1] >> 8);
status->trigger_right = (u8)(data[1] >> 0);
status->analog_a = 0;
status->analog_b = 0;
break;
case 0x00000400:
status->substick_x = (s8)(data[1] >> 24);
status->substick_y = (s8)(data[1] >> 16);
status->trigger_left = 0;
status->trigger_right = 0;
status->analog_a = (u8)(data[1] >> 8);
status->analog_b = (u8)(data[1] >> 0);
break;
}
status->stick_x -= 128;
status->stick_y -= 128;
status->substick_x -= 128;
status->substick_y -= 128;
type = Type[chan];
if (((type & (0xffff0000u)) == SI_GC_CONTROLLER) && ((status->button & 0x80) ^ 0x80)) {
BarrelBits |= ((u32)PAD_CHAN0_BIT >> chan);
status->stick_x = 0;
status->stick_y = 0;
status->substick_x = 0;
status->substick_y = 0;
} else {
BarrelBits &= ~((u32)PAD_CHAN0_BIT >> chan);
origin = &Origin[chan];
status->stick_x = ClampS8(status->stick_x, origin->stick_x);
status->stick_y = ClampS8(status->stick_y, origin->stick_y);
status->substick_x = ClampS8(status->substick_x, origin->substick_x);
status->substick_y = ClampS8(status->substick_y, origin->substick_y);
status->trigger_left = ClampU8(status->trigger_left, origin->trigger_left);
status->trigger_right = ClampU8(status->trigger_right, origin->trigger_right);
}
}
#else
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
static asm void SPEC2_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) {
nofralloc
#include "asm/dolphin/pad/Pad/SPEC2_MakeStatus.s"
}
#pragma pop
#endif
/* 8034FA10-8034FA84 34A350 0074+00 0/0 2/2 0/0 .text PADSetAnalogMode */
void PADSetAnalogMode(u32 mode) {
BOOL enabled;
u32 mask;
enabled = OSDisableInterrupts();
AnalogMode = mode << 8;
mask = EnabledBits;
EnabledBits &= ~mask;
WaitingBits &= ~mask;
CheckingBits &= ~mask;
SIDisablePolling(mask);
OSRestoreInterrupts(enabled);
}
inline BOOL PADSync(void) {
return ResettingBits == 0 && ResettingChan == 32 && !SIBusy();
}
/* 8034FA84-8034FB40 34A3C4 00BC+00 1/0 0/0 0/0 .text OnReset */
static s32 OnReset(s32 f) {
static BOOL recalibrated = FALSE;
BOOL sync;
if (SamplingCallback) {
PADSetSamplingCallback(NULL);
}
if (!f) {
sync = PADSync();
if (!recalibrated && sync) {
recalibrated =
PADRecalibrate(PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT);
return FALSE;
}
return sync;
} else {
recalibrated = FALSE;
}
return TRUE;
}
/* 8034FB40-8034FBA0 34A480 0060+00 1/1 0/0 0/0 .text SamplingHandler */
static void SamplingHandler(OSInterrupt interrupt, OSContext* context) {
OSContext exceptionContext;
if (SamplingCallback) {
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
SamplingCallback();
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
}
/* 8034FBA0-8034FBF4 34A4E0 0054+00 1/1 0/0 0/0 .text PADSetSamplingCallback */
PADSamplingCallback PADSetSamplingCallback(PADSamplingCallback callback) {
PADSamplingCallback prev;
prev = SamplingCallback;
SamplingCallback = callback;
if (callback) {
SIRegisterPollingHandler(SamplingHandler);
} else {
SIUnregisterPollingHandler(SamplingHandler);
}
return prev;
}
/* 8034FBF4-8034FC70 34A534 007C+00 0/0 1/1 0/0 .text __PADDisableRecalibration */
BOOL __PADDisableRecalibration(BOOL disable) {
BOOL enabled;
BOOL prev;
enabled = OSDisableInterrupts();
prev = (UnkVal & 0x40) ? TRUE : FALSE;
UnkVal &= ~0x40;
if (disable) {
UnkVal |= 0x40;
}
OSRestoreInterrupts(enabled);
return prev;
}