-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy pathpad.c
164 lines (143 loc) · 3.81 KB
/
pad.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <__mem.h>
#include <dolphin/os/OSContext.h>
#include <dolphin/os/OSInterrupt.h>
#include <dolphin/os/OSRtc.h>
#include <dolphin/os/OSSerial.h>
#include <dolphin/pad/pad.h>
#include <dolphin/sipriv.h>
#include <MetroTRK/intrinsics.h>
#define PAD_CHAN0_BIT 0x80000000
extern PADStatus Origin[];
extern u32 XPatchBits;
extern u32 AnalogMode;
extern u32 EnabledBits;
extern s32 ResettingChan;
extern u32 ResettingBits;
extern u32 WaitingBits;
extern u32 CheckingBits;
extern u32 PendingBits;
static void PADEnable(s32 chan)
{
u32 cmd;
u32 chanBit;
u32 data[2];
chanBit = PAD_CHAN0_BIT >> chan;
EnabledBits |= chanBit;
SIGetResponse(chan, data);
cmd = (0x40 << 16) | AnalogMode;
SISetCommand(chan, cmd);
SIEnablePolling(EnabledBits);
}
static void PADDisable(s32 chan)
{
bool enabled;
u32 chanBit;
enabled = OSDisableInterrupts();
chanBit = PAD_CHAN0_BIT >> chan;
SIDisablePolling(chanBit);
EnabledBits &= ~chanBit;
WaitingBits &= ~chanBit;
CheckingBits &= ~chanBit;
PendingBits &= ~chanBit;
OSSetWirelessID(chan, 0);
OSRestoreInterrupts(enabled);
}
static void DoReset(void)
{
u32 chanBit;
ResettingChan = __cntlzw(ResettingBits);
if (ResettingChan == 32) {
return;
}
chanBit = PAD_CHAN0_BIT >> ResettingChan;
ResettingBits &= ~chanBit;
memset(&Origin[ResettingChan], 0, sizeof(PADStatus));
SIGetTypeAsync(ResettingChan, PADTypeAndStatusCallback);
}
void UpdateOrigin(s32 arg0)
{
PADStatus* origin = &Origin[arg0];
u32 temp_r4 = AnalogMode & 0x700;
u32 bit = PAD_CHAN0_BIT >> arg0;
switch (temp_r4) {
case 0x0:
case 0x500:
case 0x600:
case 0x700:
origin->triggerLeft &= ~0xF;
origin->triggerRight &= ~0xF;
origin->analogA &= ~0xF;
origin->analogB &= ~0xF;
break;
case 0x100:
origin->substickX &= ~0xF;
origin->substickY &= ~0xF;
origin->analogA &= ~0xF;
origin->analogB &= ~0xF;
break;
case 0x200:
origin->substickX &= ~0xF;
origin->substickY &= ~0xF;
origin->triggerLeft &= ~0xF;
origin->triggerRight &= ~0xF;
break;
case 0x300:
case 0x400:
break;
}
origin->stickX -= 0x80;
origin->stickY -= 0x80;
origin->substickX -= 0x80;
origin->substickY -= 0x80;
if ((XPatchBits & bit) && origin->stickX > 0x40 &&
(SIGetType(arg0) & 0xFFFF0000) == 0x9000000)
{
origin->stickX = 0U;
}
}
inline void foo(s32 chan)
{
/// @todo @c sp1C is a struct.
u32 sp1C[6];
EnabledBits |= PAD_CHAN0_BIT >> chan;
SIGetResponse(chan, sp1C + 3);
SISetCommand(chan, AnalogMode | 0x400000);
}
void PADOriginCallback(s32 unused0, s32 arg1)
{
if (!(arg1 & 0xF)) {
UpdateOrigin(ResettingChan);
foo(ResettingChan);
SIEnablePolling(EnabledBits);
}
ResettingChan = __cntlzw(ResettingBits);
if (ResettingChan != 32) {
ResettingBits &= ~(PAD_CHAN0_BIT >> ResettingChan);
memset(&Origin[ResettingChan], 0, sizeof(Origin[0]));
SIGetTypeAsync(ResettingChan, &PADTypeAndStatusCallback);
}
}
void PADOriginUpdateCallback(s32 chan, u32 error, OSContext* context)
{
if (!(EnabledBits & (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);
}
}
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 |= PAD_CHAN0_BIT >> ResettingChan;
}
DoReset();
}