mirror of https://github.com/zeldaret/tp.git
798 lines
21 KiB
C
798 lines
21 KiB
C
//
|
|
// Generated By: dol2asm
|
|
// Translation Unit: SIBios
|
|
//
|
|
|
|
#include "dolphin/si/SIBios.h"
|
|
#include "dol2asm.h"
|
|
#include "dolphin/si/SISamplingRate.h"
|
|
#include "dolphin/vi/vi.h"
|
|
|
|
/* 803D11B8-803D11FC 02E2D8 0044+00 4/3 0/0 0/0 .data @1 */
|
|
SECTION_DATA static char lit_1[] =
|
|
"<< Dolphin SDK - SI\trelease build: Apr 5 2004 04:14:16 (0x2301) >>";
|
|
|
|
/* 804509C8-804509D0 -00001 0004+04 1/1 0/0 0/0 .sdata __SIVersion */
|
|
SECTION_SDATA static char* __SIVersion = lit_1;
|
|
|
|
//
|
|
// Forward References:
|
|
//
|
|
|
|
static u32 CompleteTransfer(void);
|
|
BOOL __SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes,
|
|
SICallback callback);
|
|
static void AlarmHandler(OSAlarm* alarm, OSContext* context);
|
|
static void GetTypeCallback(s32 chan, u32 error, OSContext* context);
|
|
|
|
//
|
|
// External References:
|
|
//
|
|
|
|
u32 VIGetCurrentLine();
|
|
|
|
//
|
|
// Declarations:
|
|
//
|
|
|
|
/* 803D11FC-803D1210 02E31C 0014+00 8/11 0/0 0/0 .data Si */
|
|
static SIControl Si = {
|
|
-1, 0, 0, NULL, NULL,
|
|
};
|
|
|
|
/* ############################################################################################## */
|
|
/* 803D1210-803D1220 02E330 0010+00 5/5 0/0 0/0 .data Type */
|
|
static u32 Type[SI_MAX_CHAN] = {
|
|
SI_ERROR_NO_RESPONSE,
|
|
SI_ERROR_NO_RESPONSE,
|
|
SI_ERROR_NO_RESPONSE,
|
|
SI_ERROR_NO_RESPONSE,
|
|
};
|
|
|
|
/* 80344BA0-80344BC0 33F4E0 0020+00 0/0 1/1 0/0 .text SIBusy */
|
|
BOOL SIBusy() {
|
|
return Si.chan != -1 ? TRUE : FALSE;
|
|
}
|
|
|
|
/* ############################################################################################## */
|
|
/* 8044C630-8044C6B0 079350 0080+00 9/9 0/0 0/0 .bss Packet */
|
|
static SIPacket Packet[SI_MAX_CHAN];
|
|
|
|
/* 80344BC0-80344BFC 33F500 003C+00 0/0 1/1 0/0 .text SIIsChanBusy */
|
|
BOOL SIIsChanBusy(s32 chan) {
|
|
return (Packet[chan].chan != -1 || Si.chan == chan);
|
|
}
|
|
|
|
/* ############################################################################################## */
|
|
/* 8044C6B0-8044C750 0793D0 00A0+00 1/1 0/0 0/0 .bss Alarm */
|
|
static OSAlarm Alarm[SI_MAX_CHAN];
|
|
|
|
/* 8044C750-8044C770 079470 0020+00 2/2 0/0 0/0 .bss TypeTime */
|
|
static OSTime TypeTime[SI_MAX_CHAN];
|
|
|
|
/* 8044C770-8044C790 079490 0020+00 1/1 0/0 0/0 .bss XferTime */
|
|
static OSTime XferTime[SI_MAX_CHAN];
|
|
|
|
static inline void SIClearTCInterrupt() {
|
|
u32 reg;
|
|
|
|
reg = __SIRegs[13];
|
|
reg |= 0x80000000;
|
|
reg &= ~0x00000001;
|
|
__SIRegs[13] = reg;
|
|
}
|
|
|
|
/* 80344BFC-80344EF8 33F53C 02FC+00 1/1 0/0 0/0 .text CompleteTransfer */
|
|
static u32 CompleteTransfer() {
|
|
u32 sr;
|
|
u32 i;
|
|
u32 rLen;
|
|
u8* input;
|
|
|
|
sr = __SIRegs[14];
|
|
|
|
SIClearTCInterrupt();
|
|
|
|
if (Si.chan != -1) {
|
|
XferTime[Si.chan] = __OSGetSystemTime();
|
|
|
|
input = Si.input;
|
|
|
|
rLen = Si.inputBytes / 4;
|
|
for (i = 0; i < rLen; i++) {
|
|
*(u32*)input = __SIRegs[32 + i];
|
|
input += 4;
|
|
}
|
|
|
|
rLen = Si.inputBytes & 3;
|
|
if (rLen) {
|
|
u32 temp = __SIRegs[32 + i];
|
|
for (i = 0; i < rLen; i++) {
|
|
*input++ = (u8)((temp >> ((3 - i) * 8)) & 0xff);
|
|
}
|
|
}
|
|
|
|
if (__SIRegs[13] & 0x20000000) {
|
|
sr >>= 8 * (3 - Si.chan);
|
|
sr &= 0xf;
|
|
|
|
if ((sr & SI_ERROR_NO_RESPONSE) && !(Type[Si.chan] & SI_ERROR_BUSY)) {
|
|
Type[Si.chan] = SI_ERROR_NO_RESPONSE;
|
|
}
|
|
if (sr == 0) {
|
|
sr = SI_ERROR_COLLISION;
|
|
}
|
|
} else {
|
|
TypeTime[Si.chan] = __OSGetSystemTime();
|
|
sr = 0;
|
|
}
|
|
|
|
Si.chan = -1;
|
|
}
|
|
return sr;
|
|
}
|
|
|
|
/* ############################################################################################## */
|
|
/* 8044C790-8044C7D0 0794B0 0040+00 1/1 0/0 0/0 .bss TypeCallback */
|
|
static SITypeAndStatusCallback TypeCallback[SI_MAX_CHAN][4];
|
|
|
|
/* 8044C7D0-8044C7E0 0794F0 0010+00 2/3 0/0 0/0 .bss RDSTHandler */
|
|
static OSInterruptHandler RDSTHandler[4];
|
|
|
|
/* 8044C7E0-8044C7F0 079500 0010+00 0/0 0/0 0/0 .bss InputBufferValid */
|
|
#pragma push
|
|
#pragma force_active on
|
|
static BOOL InputBufferValid[SI_MAX_CHAN];
|
|
#pragma pop
|
|
|
|
/* 8044C7F0-8044C810 079510 0020+00 0/0 0/0 0/0 .bss InputBuffer */
|
|
#pragma push
|
|
#pragma force_active on
|
|
static u32 InputBuffer[SI_MAX_CHAN][2];
|
|
#pragma pop
|
|
|
|
/* 8044C810-8044C820 079530 0010+00 0/2 0/0 0/0 .bss InputBufferVcount */
|
|
#pragma push
|
|
#pragma force_active on
|
|
static volatile u32 InputBufferVcount[SI_MAX_CHAN];
|
|
#pragma pop
|
|
|
|
inline void SITransferNext(s32 chan) {
|
|
int i;
|
|
SIPacket* packet;
|
|
|
|
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
|
++chan;
|
|
chan %= SI_MAX_CHAN;
|
|
packet = &Packet[chan];
|
|
if (packet->chan != -1 && packet->fire <= __OSGetSystemTime()) {
|
|
if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input,
|
|
packet->inputBytes, packet->callback)) {
|
|
OSCancelAlarm(&Alarm[chan]);
|
|
packet->chan = -1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 804516F0-804516F4 000BF0 0004+00 1/1 0/0 0/0 .sbss cmdTypeAndStatus$78 */
|
|
static u8 cmdTypeAndStatus_78[4];
|
|
|
|
/* 80344EF8-8034523C 33F838 0344+00 1/1 0/0 0/0 .text SIInterruptHandler */
|
|
static void SIInterruptHandler(OSInterrupt interrupt, OSContext* context) {
|
|
u32 reg;
|
|
|
|
reg = __SIRegs[13];
|
|
|
|
if ((reg & 0xc0000000) == 0xc0000000) {
|
|
s32 chan;
|
|
u32 sr;
|
|
SICallback callback;
|
|
|
|
chan = Si.chan;
|
|
sr = CompleteTransfer();
|
|
callback = Si.callback;
|
|
Si.callback = 0;
|
|
|
|
SITransferNext(chan);
|
|
|
|
if (callback) {
|
|
callback(chan, sr, context);
|
|
}
|
|
|
|
sr = __SIRegs[14];
|
|
sr &= 0xf000000 >> (8 * chan);
|
|
__SIRegs[14] = sr;
|
|
|
|
if (Type[chan] == SI_ERROR_BUSY && !SIIsChanBusy(chan)) {
|
|
static u32 cmdTypeAndStatus = 0 << 24;
|
|
SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, GetTypeCallback,
|
|
OSMicrosecondsToTicks(65));
|
|
}
|
|
}
|
|
|
|
if ((reg & 0x18000000) == 0x18000000) {
|
|
int i;
|
|
u32 vcount;
|
|
u32 x;
|
|
|
|
vcount = VIGetCurrentLine() + 1;
|
|
x = (Si.poll & 0x03ff0000) >> 16;
|
|
|
|
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
|
if (SIGetResponseRaw(i)) {
|
|
InputBufferVcount[i] = vcount;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
|
if (!(Si.poll & (SI_CHAN0_BIT >> (31 - 7 + i)))) {
|
|
continue;
|
|
}
|
|
if (InputBufferVcount[i] == 0 || InputBufferVcount[i] + (x / 2) < vcount) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
|
InputBufferVcount[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
if (RDSTHandler[i]) {
|
|
RDSTHandler[i](interrupt, context);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 8034523C-803452D4 33FB7C 0098+00 2/2 0/0 0/0 .text SIEnablePollingInterrupt */
|
|
static BOOL SIEnablePollingInterrupt(BOOL enable) {
|
|
BOOL enabled;
|
|
BOOL rc;
|
|
u32 reg;
|
|
int i;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
reg = __SIRegs[13];
|
|
rc = (reg & 0x08000000) ? TRUE : FALSE;
|
|
if (enable) {
|
|
reg |= 0x08000000;
|
|
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
|
InputBufferVcount[i] = 0;
|
|
}
|
|
} else {
|
|
reg &= ~0x08000000;
|
|
}
|
|
reg &= ~0x80000001;
|
|
__SIRegs[13] = reg;
|
|
OSRestoreInterrupts(enabled);
|
|
return rc;
|
|
}
|
|
|
|
/* 803452D4-803453A0 33FC14 00CC+00 0/0 1/1 0/0 .text SIRegisterPollingHandler */
|
|
BOOL SIRegisterPollingHandler(OSInterruptHandler handler) {
|
|
BOOL enabled;
|
|
int i;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
for (i = 0; i < 4; ++i) {
|
|
if (RDSTHandler[i] == handler) {
|
|
OSRestoreInterrupts(enabled);
|
|
return TRUE;
|
|
}
|
|
}
|
|
for (i = 0; i < 4; ++i) {
|
|
if (RDSTHandler[i] == 0) {
|
|
RDSTHandler[i] = handler;
|
|
SIEnablePollingInterrupt(TRUE);
|
|
OSRestoreInterrupts(enabled);
|
|
return TRUE;
|
|
}
|
|
}
|
|
OSRestoreInterrupts(enabled);
|
|
return FALSE;
|
|
}
|
|
|
|
/* 803453A0-80345494 33FCE0 00F4+00 0/0 1/1 0/0 .text SIUnregisterPollingHandler */
|
|
BOOL SIUnregisterPollingHandler(OSInterruptHandler handler) {
|
|
BOOL enabled;
|
|
int i;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
for (i = 0; i < 4; ++i) {
|
|
if (RDSTHandler[i] == handler) {
|
|
RDSTHandler[i] = 0;
|
|
for (i = 0; i < 4; ++i) {
|
|
if (RDSTHandler[i]) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == 4) {
|
|
SIEnablePollingInterrupt(FALSE);
|
|
}
|
|
OSRestoreInterrupts(enabled);
|
|
return TRUE;
|
|
break;
|
|
}
|
|
}
|
|
OSRestoreInterrupts(enabled);
|
|
return FALSE;
|
|
}
|
|
|
|
/* 80345494-80345548 33FDD4 00B4+00 0/0 1/1 0/0 .text SIInit */
|
|
void SIInit(void) {
|
|
OSRegisterVersion(__SIVersion);
|
|
|
|
Packet[0].chan = Packet[1].chan = Packet[2].chan = Packet[3].chan = -1;
|
|
|
|
Si.poll = 0;
|
|
SISetSamplingRate(0);
|
|
|
|
while (__SIRegs[13] & 1)
|
|
;
|
|
|
|
__SIRegs[13] = 0x80000000;
|
|
|
|
__OSSetInterruptHandler(OS_INTR_PI_SI, SIInterruptHandler);
|
|
__OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_SI);
|
|
|
|
SIGetType(0);
|
|
SIGetType(1);
|
|
SIGetType(2);
|
|
SIGetType(3);
|
|
}
|
|
|
|
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
|
|
|
|
/* 80345548-80345754 33FE88 020C+00 3/3 0/0 0/0 .text __SITransfer */
|
|
static BOOL __SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes,
|
|
SICallback callback) {
|
|
BOOL enabled;
|
|
u32 rLen;
|
|
u32 i;
|
|
u32 sr;
|
|
SIComm_u comcsr;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
if (Si.chan != -1) {
|
|
OSRestoreInterrupts(enabled);
|
|
return FALSE;
|
|
}
|
|
|
|
sr = __SIRegs[14];
|
|
sr &= (0xf000000) >> (8 * chan);
|
|
__SIRegs[14] = sr;
|
|
|
|
Si.chan = chan;
|
|
Si.callback = callback;
|
|
Si.inputBytes = inputBytes;
|
|
Si.input = input;
|
|
|
|
rLen = ROUND(outputBytes, 4) / 4;
|
|
for (i = 0; i < rLen; i++) {
|
|
__SIRegs[32 + i] = ((u32*)output)[i];
|
|
}
|
|
|
|
comcsr.val = __SIRegs[13];
|
|
comcsr.f.tcint = 1;
|
|
comcsr.f.tcintmsk = callback ? 1 : 0;
|
|
comcsr.f.outlngth = (outputBytes == SI_MAX_COMCSR_OUTLNGTH) ? 0 : outputBytes;
|
|
comcsr.f.inlngth = (inputBytes == SI_MAX_COMCSR_INLNGTH) ? 0 : inputBytes;
|
|
comcsr.f.channel = chan;
|
|
comcsr.f.tstart = 1;
|
|
__SIRegs[13] = comcsr.val;
|
|
|
|
OSRestoreInterrupts(enabled);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 80345754-803457D0 340094 007C+00 1/1 1/1 0/0 .text SIGetStatus */
|
|
u32 SIGetStatus(s32 chan) {
|
|
BOOL enabled;
|
|
u32 sr;
|
|
int chanShift;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
sr = __SIRegs[14];
|
|
chanShift = 8 * (SI_MAX_CHAN - 1 - chan);
|
|
sr >>= chanShift;
|
|
if (sr & SI_ERROR_NO_RESPONSE) {
|
|
if (!(Type[chan] & SI_ERROR_BUSY)) {
|
|
Type[chan] = SI_ERROR_NO_RESPONSE;
|
|
}
|
|
}
|
|
OSRestoreInterrupts(enabled);
|
|
return sr;
|
|
}
|
|
|
|
/* 803457D0-803457E4 340110 0014+00 0/0 4/4 0/0 .text SISetCommand */
|
|
void SISetCommand(s32 chan, u32 command) {
|
|
__SIRegs[3 * chan] = command;
|
|
}
|
|
|
|
/* 803457E4-803457F4 340124 0010+00 0/0 1/1 0/0 .text SITransferCommands */
|
|
void SITransferCommands(void) {
|
|
__SIRegs[14] = 0x80000000;
|
|
}
|
|
|
|
/* 803457F4-80345860 340134 006C+00 0/0 1/1 0/0 .text SISetXY */
|
|
// needs compiler epilogue patch
|
|
u32 SISetXY(u32 x, u32 y) {
|
|
u32 poll;
|
|
BOOL enabled;
|
|
|
|
poll = x << 16;
|
|
poll |= y << 8;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
Si.poll &= ~(0x03ff0000 | 0x0000ff00);
|
|
Si.poll |= poll;
|
|
poll = Si.poll;
|
|
__SIRegs[12] = poll;
|
|
OSRestoreInterrupts(enabled);
|
|
return poll;
|
|
}
|
|
|
|
/* 80345860-803458FC 3401A0 009C+00 0/0 3/3 0/0 .text SIEnablePolling */
|
|
u32 SIEnablePolling(u32 poll) {
|
|
BOOL enabled;
|
|
u32 en;
|
|
|
|
if (poll == 0) {
|
|
return Si.poll;
|
|
}
|
|
|
|
enabled = OSDisableInterrupts();
|
|
|
|
poll >>= (31 - 7);
|
|
en = poll & 0xf0;
|
|
|
|
poll &= (en >> 4) | 0x03fffff0;
|
|
|
|
poll &= ~0x03ffff00;
|
|
|
|
Si.poll &= ~(en >> 4);
|
|
|
|
Si.poll |= poll;
|
|
|
|
poll = Si.poll;
|
|
|
|
SITransferCommands();
|
|
|
|
__SIRegs[12] = poll;
|
|
|
|
OSRestoreInterrupts(enabled);
|
|
|
|
return poll;
|
|
}
|
|
|
|
/* 803458FC-80345968 34023C 006C+00 0/0 6/6 0/0 .text SIDisablePolling */
|
|
u32 SIDisablePolling(u32 poll) {
|
|
BOOL enabled;
|
|
|
|
if (poll == 0) {
|
|
return Si.poll;
|
|
}
|
|
|
|
enabled = OSDisableInterrupts();
|
|
|
|
poll >>= (31 - 7);
|
|
poll &= 0xf0;
|
|
|
|
poll = Si.poll & ~poll;
|
|
|
|
__SIRegs[12] = poll;
|
|
Si.poll = poll;
|
|
|
|
OSRestoreInterrupts(enabled);
|
|
return poll;
|
|
}
|
|
|
|
/* 80345968-80345A3C 3402A8 00D4+00 1/1 0/0 0/0 .text SIGetResponseRaw */
|
|
static BOOL SIGetResponseRaw(s32 chan) {
|
|
u32 sr;
|
|
|
|
sr = SIGetStatus(chan);
|
|
if (sr & SI_ERROR_RDST) {
|
|
InputBuffer[chan][0] = __SIRegs[3 * chan + 1];
|
|
InputBuffer[chan][1] = __SIRegs[3 * chan + 2];
|
|
InputBufferValid[chan] = TRUE;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/* 80345A3C-80345B00 34037C 00C4+00 0/0 4/4 0/0 .text SIGetResponse */
|
|
BOOL SIGetResponse(s32 chan, void* data) {
|
|
BOOL rc;
|
|
BOOL enabled;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
SIGetResponseRaw(chan);
|
|
rc = InputBufferValid[chan];
|
|
InputBufferValid[chan] = FALSE;
|
|
if (rc) {
|
|
((u32*)data)[0] = InputBuffer[chan][0];
|
|
((u32*)data)[1] = InputBuffer[chan][1];
|
|
}
|
|
OSRestoreInterrupts(enabled);
|
|
return rc;
|
|
}
|
|
|
|
/* 80345B00-80345B8C 340440 008C+00 1/1 0/0 0/0 .text AlarmHandler */
|
|
static void AlarmHandler(OSAlarm* alarm, OSContext* context) {
|
|
s32 chan;
|
|
SIPacket* packet;
|
|
|
|
chan = alarm - Alarm;
|
|
packet = &Packet[chan];
|
|
if (packet->chan != -1) {
|
|
if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input,
|
|
packet->inputBytes, packet->callback)) {
|
|
packet->chan = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 80345B8C-80345CF8 3404CC 016C+00 3/3 3/3 0/0 .text SITransfer */
|
|
BOOL SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes,
|
|
SICallback callback, OSTime delay) {
|
|
BOOL enabled;
|
|
SIPacket* packet = &Packet[chan];
|
|
OSTime now;
|
|
OSTime fire;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
if (packet->chan != -1 || Si.chan == chan) {
|
|
OSRestoreInterrupts(enabled);
|
|
return FALSE;
|
|
}
|
|
|
|
now = __OSGetSystemTime();
|
|
if (delay == 0) {
|
|
fire = now;
|
|
} else {
|
|
fire = XferTime[chan] + delay;
|
|
}
|
|
if (now < fire) {
|
|
delay = fire - now;
|
|
OSSetAlarm(&Alarm[chan], delay, AlarmHandler);
|
|
} else if (__SITransfer(chan, output, outputBytes, input, inputBytes, callback)) {
|
|
OSRestoreInterrupts(enabled);
|
|
return TRUE;
|
|
}
|
|
|
|
packet->chan = chan;
|
|
packet->output = output;
|
|
packet->outputBytes = outputBytes;
|
|
packet->input = input;
|
|
packet->inputBytes = inputBytes;
|
|
packet->callback = callback;
|
|
packet->fire = fire;
|
|
|
|
OSRestoreInterrupts(enabled);
|
|
return TRUE;
|
|
}
|
|
|
|
/* ############################################################################################## */
|
|
/* 804516F4-804516F8 000BF4 0004+00 1/1 0/0 0/0 .sbss cmdTypeAndStatus$372 */
|
|
static u8 cmdTypeAndStatus_372[4];
|
|
|
|
/* 804516F8-80451700 000BF8 0004+04 1/1 1/1 0/0 .sbss __PADFixBits */
|
|
extern u32 __PADFixBits;
|
|
u32 __PADFixBits;
|
|
|
|
static inline void CallTypeAndStatusCallback(s32 chan, u32 type) {
|
|
SITypeAndStatusCallback callback;
|
|
int i;
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
callback = TypeCallback[chan][i];
|
|
if (callback) {
|
|
TypeCallback[chan][i] = 0;
|
|
callback(chan, type);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 80345CF8-80345F90 340638 0298+00 2/2 0/0 0/0 .text GetTypeCallback */
|
|
static void GetTypeCallback(s32 chan, u32 error, OSContext* context) {
|
|
static u32 cmdFixDevice[SI_MAX_CHAN];
|
|
u32 type;
|
|
u32 chanBit;
|
|
BOOL fix;
|
|
u32 id;
|
|
|
|
Type[chan] &= ~SI_ERROR_BUSY;
|
|
Type[chan] |= error;
|
|
TypeTime[chan] = __OSGetSystemTime();
|
|
|
|
type = Type[chan];
|
|
|
|
chanBit = SI_CHAN0_BIT >> chan;
|
|
fix = (BOOL)(__PADFixBits & chanBit);
|
|
__PADFixBits &= ~chanBit;
|
|
|
|
if ((error &
|
|
(SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)) ||
|
|
(type & SI_TYPE_MASK) != SI_TYPE_DOLPHIN || !(type & SI_GC_WIRELESS) ||
|
|
(type & SI_WIRELESS_IR))
|
|
{
|
|
OSSetWirelessID(chan, 0);
|
|
CallTypeAndStatusCallback(chan, Type[chan]);
|
|
return;
|
|
}
|
|
|
|
id = (u32)(OSGetWirelessID(chan) << 8);
|
|
|
|
if (fix && (id & SI_WIRELESS_FIX_ID)) {
|
|
cmdFixDevice[chan] = 0x4Eu << 24 | (id & SI_WIRELESS_TYPE_ID) | SI_WIRELESS_FIX_ID;
|
|
Type[chan] = SI_ERROR_BUSY;
|
|
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, GetTypeCallback, 0);
|
|
return;
|
|
}
|
|
|
|
if (type & SI_WIRELESS_FIX_ID) {
|
|
if ((id & SI_WIRELESS_TYPE_ID) != (type & SI_WIRELESS_TYPE_ID)) {
|
|
if (!(id & SI_WIRELESS_FIX_ID)) {
|
|
id = type & SI_WIRELESS_TYPE_ID;
|
|
id |= SI_WIRELESS_FIX_ID;
|
|
OSSetWirelessID(chan, (u16)((id >> 8) & 0xffff));
|
|
}
|
|
|
|
cmdFixDevice[chan] = 0x4E << 24 | id;
|
|
Type[chan] = SI_ERROR_BUSY;
|
|
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, GetTypeCallback, 0);
|
|
return;
|
|
}
|
|
} else if (type & SI_WIRELESS_RECEIVED) {
|
|
id = type & SI_WIRELESS_TYPE_ID;
|
|
id |= SI_WIRELESS_FIX_ID;
|
|
|
|
OSSetWirelessID(chan, (u16)((id >> 8) & 0xffff));
|
|
|
|
cmdFixDevice[chan] = 0x4E << 24 | id;
|
|
Type[chan] = SI_ERROR_BUSY;
|
|
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, GetTypeCallback, 0);
|
|
return;
|
|
} else {
|
|
OSSetWirelessID(chan, 0);
|
|
}
|
|
|
|
CallTypeAndStatusCallback(chan, Type[chan]);
|
|
}
|
|
|
|
/* 80345F90-80346154 3408D0 01C4+00 2/2 3/3 0/0 .text SIGetType */
|
|
u32 SIGetType(s32 chan) {
|
|
static u32 cmdTypeAndStatus;
|
|
BOOL enabled;
|
|
u32 type;
|
|
OSTime diff;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
|
|
type = Type[chan];
|
|
diff = __OSGetSystemTime() - TypeTime[chan];
|
|
if (Si.poll & (0x80 >> chan)) {
|
|
if (type != SI_ERROR_NO_RESPONSE) {
|
|
TypeTime[chan] = __OSGetSystemTime();
|
|
OSRestoreInterrupts(enabled);
|
|
return type;
|
|
} else {
|
|
type = Type[chan] = SI_ERROR_BUSY;
|
|
}
|
|
} else if (diff <= OSMillisecondsToTicks(50) && type != SI_ERROR_NO_RESPONSE) {
|
|
OSRestoreInterrupts(enabled);
|
|
return type;
|
|
} else if (diff <= OSMillisecondsToTicks(75)) {
|
|
Type[chan] = SI_ERROR_BUSY;
|
|
} else {
|
|
type = Type[chan] = SI_ERROR_BUSY;
|
|
}
|
|
TypeTime[chan] = __OSGetSystemTime();
|
|
|
|
SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, GetTypeCallback,
|
|
OSMicrosecondsToTicks(65));
|
|
|
|
OSRestoreInterrupts(enabled);
|
|
return type;
|
|
}
|
|
|
|
/* 80346154-80346290 340A94 013C+00 0/0 6/6 0/0 .text SIGetTypeAsync */
|
|
u32 SIGetTypeAsync(s32 chan, SITypeAndStatusCallback callback) {
|
|
BOOL enabled;
|
|
u32 type;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
type = SIGetType(chan);
|
|
if (Type[chan] & SI_ERROR_BUSY) {
|
|
int i;
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
if (TypeCallback[chan][i] == callback) {
|
|
break;
|
|
}
|
|
if (TypeCallback[chan][i] == 0) {
|
|
TypeCallback[chan][i] = callback;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
callback(chan, type);
|
|
}
|
|
OSRestoreInterrupts(enabled);
|
|
return type;
|
|
}
|
|
|
|
/* ############################################################################################## */
|
|
/* 803D1220-803D122C 02E340 000C+00 0/0 0/0 0/0 .data @457 */
|
|
|
|
// All of these strings are from the stripped `SIGetTypeString` function
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_457[] = "No response";
|
|
#pragma pop
|
|
|
|
/* 803D122C-803D123C 02E34C 000F+01 0/0 0/0 0/0 .data @459 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_459[] = "N64 controller";
|
|
#pragma pop
|
|
|
|
/* 803D123C-803D124C 02E35C 000F+01 0/0 0/0 0/0 .data @460 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_460[] = "N64 microphone";
|
|
#pragma pop
|
|
|
|
/* 803D124C-803D125C 02E36C 000D+03 0/0 0/0 0/0 .data @461 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_461[] = "N64 keyboard";
|
|
#pragma pop
|
|
|
|
/* 803D125C-803D1268 02E37C 000A+02 0/0 0/0 0/0 .data @462 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_462[] = "N64 mouse";
|
|
#pragma pop
|
|
|
|
/* 803D1268-803D1278 02E388 0010+00 0/0 0/0 0/0 .data @463 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_463[] = "GameBoy Advance";
|
|
#pragma pop
|
|
|
|
/* 803D1278-803D128C 02E398 0014+00 0/0 0/0 0/0 .data @464 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_464[] = "Standard controller";
|
|
#pragma pop
|
|
|
|
/* 803D128C-803D12A0 02E3AC 0012+02 0/0 0/0 0/0 .data @465 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_465[] = "Wireless receiver";
|
|
#pragma pop
|
|
|
|
/* 803D12A0-803D12B4 02E3C0 0014+00 0/0 0/0 0/0 .data @466 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_466[] = "WaveBird controller";
|
|
#pragma pop
|
|
|
|
/* 803D12B4-803D12C0 02E3D4 0009+03 0/0 0/0 0/0 .data @467 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_467[] = "Keyboard";
|
|
#pragma pop
|
|
|
|
/* 803D12C0-803D12D0 02E3E0 0009+07 0/0 0/0 0/0 .data @468 */
|
|
#pragma push
|
|
#pragma force_active on
|
|
SECTION_DATA static char lit_468[] = "Steering";
|
|
#pragma pop
|