Imported dolphin/si
This commit is contained in:
parent
9267fa627d
commit
e957d339b0
3 changed files with 884 additions and 0 deletions
|
|
@ -4408,6 +4408,17 @@ SectorSizeTable = .data:0x8013E060; // type:object size:0x20 scope:local
|
||||||
LatencyTable = .data:0x8013E080; // type:object size:0x20 scope:local
|
LatencyTable = .data:0x8013E080; // type:object size:0x20 scope:local
|
||||||
Si = .data:0x8013E0A0; // type:object size:0x14 scope:local data:4byte
|
Si = .data:0x8013E0A0; // type:object size:0x14 scope:local data:4byte
|
||||||
Type = .data:0x8013E0B4; // type:object size:0x10 scope:local
|
Type = .data:0x8013E0B4; // type:object size:0x10 scope:local
|
||||||
|
@464 = .data:0x8013E0C4; // type:object size:0x9 scope:local data:string
|
||||||
|
lbl_8013E0D0 = .data:0x8013E0D0; // type:object size:0xF scope:local data:string
|
||||||
|
lbl_8013E0E0 = .data:0x8013E0E0; // type:object size:0xF scope:local data:string
|
||||||
|
lbl_8013E0F0 = .data:0x8013E0F0; // type:object size:0xD scope:local data:string
|
||||||
|
lbl_8013E100 = .data:0x8013E100; // type:object size:0xA scope:local data:string
|
||||||
|
lbl_8013E10C = .data:0x8013E10C; // type:object size:0x10 scope:local data:string
|
||||||
|
lbl_8013E11C = .data:0x8013E11C; // type:object size:0x14 scope:local data:string
|
||||||
|
lbl_8013E130 = .data:0x8013E130; // type:object size:0x12 scope:local data:string
|
||||||
|
lbl_8013E144 = .data:0x8013E144; // type:object size:0x14 scope:local data:string
|
||||||
|
lbl_8013E158 = .data:0x8013E158; // type:object size:0x9 scope:local data:string
|
||||||
|
lbl_8013E164 = .data:0x8013E164; // type:object size:0x9 scope:local data:string
|
||||||
XYNTSC = .data:0x8013E170; // type:object size:0x30 scope:local
|
XYNTSC = .data:0x8013E170; // type:object size:0x30 scope:local
|
||||||
XYPAL = .data:0x8013E1A0; // type:object size:0x30 scope:local
|
XYPAL = .data:0x8013E1A0; // type:object size:0x30 scope:local
|
||||||
__vt__Q23std9exception = .data:0x8013E208; // type:object size:0x10 scope:weak
|
__vt__Q23std9exception = .data:0x8013E208; // type:object size:0x10 scope:weak
|
||||||
|
|
|
||||||
817
src/dolphin/si/SIBios.c
Normal file
817
src/dolphin/si/SIBios.c
Normal file
|
|
@ -0,0 +1,817 @@
|
||||||
|
#include <dolphin/OSRtcPriv.h>
|
||||||
|
#include <dolphin/hw_regs.h>
|
||||||
|
#include <dolphin/os.h>
|
||||||
|
#include <dolphin/sipriv.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern OSTime __OSGetSystemTime();
|
||||||
|
|
||||||
|
typedef struct SIControl {
|
||||||
|
s32 chan;
|
||||||
|
u32 poll;
|
||||||
|
u32 inputBytes;
|
||||||
|
void *input;
|
||||||
|
SICallback callback;
|
||||||
|
} SIControl;
|
||||||
|
|
||||||
|
static SIControl Si = {
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct SIComm_s {
|
||||||
|
u32 tcint : 1;
|
||||||
|
u32 tcintmsk : 1;
|
||||||
|
u32 comerr : 1;
|
||||||
|
u32 rdstint : 1;
|
||||||
|
u32 rdstintmsk : 1;
|
||||||
|
u32 pad0 : 4;
|
||||||
|
u32 outlngth : 7;
|
||||||
|
u32 pad1 : 1;
|
||||||
|
u32 inlngth : 7;
|
||||||
|
u32 pad2 : 5;
|
||||||
|
u32 channel : 2;
|
||||||
|
u32 tstart : 1;
|
||||||
|
} SIComm_s;
|
||||||
|
|
||||||
|
typedef union SIComm_u {
|
||||||
|
u32 val;
|
||||||
|
SIComm_s f;
|
||||||
|
} SIComm_u;
|
||||||
|
|
||||||
|
static SIPacket Packet[SI_MAX_CHAN];
|
||||||
|
static OSAlarm Alarm[SI_MAX_CHAN];
|
||||||
|
static u32 Type[SI_MAX_CHAN] = {
|
||||||
|
SI_ERROR_NO_RESPONSE,
|
||||||
|
SI_ERROR_NO_RESPONSE,
|
||||||
|
SI_ERROR_NO_RESPONSE,
|
||||||
|
SI_ERROR_NO_RESPONSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static OSTime TypeTime[SI_MAX_CHAN];
|
||||||
|
static OSTime XferTime[SI_MAX_CHAN];
|
||||||
|
|
||||||
|
static SITypeAndStatusCallback TypeCallback[SI_MAX_CHAN][4];
|
||||||
|
static __OSInterruptHandler RDSTHandler[4];
|
||||||
|
|
||||||
|
u32 __PADFixBits;
|
||||||
|
|
||||||
|
static BOOL __SITransfer(s32 chan, void *output, u32 outputBytes, void *input, u32 inputBytes, SICallback callback);
|
||||||
|
|
||||||
|
static BOOL InputBufferValid[SI_MAX_CHAN];
|
||||||
|
static u32 InputBuffer[SI_MAX_CHAN][2];
|
||||||
|
static vu32 InputBufferVcount[SI_MAX_CHAN];
|
||||||
|
|
||||||
|
static BOOL SIGetResponseRaw(s32 chan);
|
||||||
|
static void GetTypeCallback(s32 chan, u32 error, OSContext *context);
|
||||||
|
|
||||||
|
BOOL SIBusy()
|
||||||
|
{
|
||||||
|
return Si.chan != -1 ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL SIIsChanBusy(s32 chan)
|
||||||
|
{
|
||||||
|
return (Packet[chan].chan != -1 || Si.chan == chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SIClearTCInterrupt()
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
reg = __SIRegs[13];
|
||||||
|
reg |= 0x80000000;
|
||||||
|
reg &= ~0x00000001;
|
||||||
|
__SIRegs[13] = reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIInit(void)
|
||||||
|
{
|
||||||
|
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_INTERRUPT_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))
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SISync(void)
|
||||||
|
{
|
||||||
|
BOOL enabled;
|
||||||
|
u32 sr;
|
||||||
|
|
||||||
|
while (__SIRegs[13] & 1)
|
||||||
|
;
|
||||||
|
|
||||||
|
enabled = OSDisableInterrupts();
|
||||||
|
sr = CompleteTransfer();
|
||||||
|
|
||||||
|
SITransferNext(SI_MAX_CHAN);
|
||||||
|
|
||||||
|
OSRestoreInterrupts(enabled);
|
||||||
|
|
||||||
|
return sr;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SISetCommand(s32 chan, u32 command)
|
||||||
|
{
|
||||||
|
__SIRegs[3 * chan] = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SIGetCommand(s32 chan)
|
||||||
|
{
|
||||||
|
return __SIRegs[3 * chan];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SITransferCommands(void)
|
||||||
|
{
|
||||||
|
__SIRegs[14] = 0x80000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AlarmHandler(OSAlarm *alarm, OSContext *context)
|
||||||
|
{
|
||||||
|
#pragma unused(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SIDecodeType(u32 type)
|
||||||
|
{
|
||||||
|
u32 error;
|
||||||
|
|
||||||
|
error = type & 0xff;
|
||||||
|
type &= ~0xff;
|
||||||
|
|
||||||
|
if (error & SI_ERROR_NO_RESPONSE) {
|
||||||
|
return SI_ERROR_NO_RESPONSE;
|
||||||
|
}
|
||||||
|
if (error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_COLLISION | SI_ERROR_UNKNOWN)) {
|
||||||
|
return SI_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
return SI_ERROR_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type & SI_TYPE_MASK) == SI_TYPE_N64) {
|
||||||
|
switch (type & 0xffff0000) {
|
||||||
|
case SI_N64_CONTROLLER:
|
||||||
|
case SI_N64_MIC:
|
||||||
|
case SI_N64_KEYBOARD:
|
||||||
|
case SI_N64_MOUSE:
|
||||||
|
case SI_GBA:
|
||||||
|
return type & 0xffff0000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return SI_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type & SI_TYPE_MASK) != SI_TYPE_GC) {
|
||||||
|
|
||||||
|
return SI_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
switch (type & 0xffff0000) {
|
||||||
|
case SI_GC_CONTROLLER:
|
||||||
|
case SI_GC_STEERING:
|
||||||
|
return type & 0xffff0000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type & 0xffe00000) == SI_GC_KEYBOARD) {
|
||||||
|
return SI_GC_KEYBOARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type & SI_GC_WIRELESS) && !(type & SI_WIRELESS_IR)) {
|
||||||
|
if ((type & SI_GC_WAVEBIRD) == SI_GC_WAVEBIRD) {
|
||||||
|
return SI_GC_WAVEBIRD;
|
||||||
|
}
|
||||||
|
else if (!(type & SI_WIRELESS_STATE)) {
|
||||||
|
return SI_GC_RECEIVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type & SI_GC_CONTROLLER) == SI_GC_CONTROLLER) {
|
||||||
|
return SI_GC_CONTROLLER;
|
||||||
|
}
|
||||||
|
return SI_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SIProbe(s32 chan)
|
||||||
|
{
|
||||||
|
return SIDecodeType(SIGetType(chan));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *SIGetTypeString(u32 type)
|
||||||
|
{
|
||||||
|
switch (SIDecodeType(type)) {
|
||||||
|
case SI_ERROR_NO_RESPONSE:
|
||||||
|
return "No response";
|
||||||
|
case SI_N64_CONTROLLER:
|
||||||
|
return "N64 controller";
|
||||||
|
case SI_N64_MIC:
|
||||||
|
return "N64 microphone";
|
||||||
|
case SI_N64_KEYBOARD:
|
||||||
|
return "N64 keyboard";
|
||||||
|
case SI_N64_MOUSE:
|
||||||
|
return "N64 mouse";
|
||||||
|
case SI_GBA:
|
||||||
|
return "GameBoy Advance";
|
||||||
|
case SI_GC_CONTROLLER:
|
||||||
|
return "Standard controller";
|
||||||
|
case SI_GC_RECEIVER:
|
||||||
|
return "Wireless receiver";
|
||||||
|
case SI_GC_WAVEBIRD:
|
||||||
|
return "WaveBird controller";
|
||||||
|
case SI_GC_KEYBOARD:
|
||||||
|
return "Keyboard";
|
||||||
|
case SI_GC_STEERING:
|
||||||
|
return "Steering";
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/dolphin/si/SISamplingRate.c
Normal file
56
src/dolphin/si/SISamplingRate.c
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include "dolphin/sipriv.h"
|
||||||
|
#include "dolphin/vi.h"
|
||||||
|
#include "dolphin/hw_regs.h"
|
||||||
|
|
||||||
|
#pragma dont_inline on
|
||||||
|
static u32 SamplingRate;
|
||||||
|
|
||||||
|
typedef struct XY {
|
||||||
|
u16 line;
|
||||||
|
u8 count;
|
||||||
|
} XY;
|
||||||
|
|
||||||
|
static XY XYNTSC[12] = {
|
||||||
|
{263 - 17, 2}, {15, 18}, {30, 9}, {44, 6}, {52, 5}, {65, 4},
|
||||||
|
{87, 3}, {87, 3}, {87, 3}, {131, 2}, {131, 2}, {131, 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
static XY XYPAL[12] = {
|
||||||
|
{313 - 17, 2}, {15, 21}, {29, 11}, {45, 7}, {52, 6}, {63, 5},
|
||||||
|
{78, 4}, {104, 3}, {104, 3}, {104, 3}, {104, 3}, {156, 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
void SISetSamplingRate(u32 msec) {
|
||||||
|
XY* xy;
|
||||||
|
BOOL enabled;
|
||||||
|
|
||||||
|
if (msec > 11) {
|
||||||
|
msec = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled = OSDisableInterrupts();
|
||||||
|
|
||||||
|
SamplingRate = msec;
|
||||||
|
|
||||||
|
switch (VIGetTvFormat()) {
|
||||||
|
case VI_NTSC:
|
||||||
|
case VI_MPAL:
|
||||||
|
case VI_EURGB60:
|
||||||
|
xy = XYNTSC;
|
||||||
|
break;
|
||||||
|
case VI_PAL:
|
||||||
|
xy = XYPAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OSReport("SISetSamplingRate: unknown TV format. Use default.");
|
||||||
|
msec = 0;
|
||||||
|
xy = XYNTSC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SISetXY((__VIRegs[54] & 1 ? 2u : 1u) * xy[msec].line, xy[msec].count);
|
||||||
|
OSRestoreInterrupts(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIRefreshSamplingRate() { SISetSamplingRate(SamplingRate); }
|
||||||
|
#pragma dont_inline reset
|
||||||
Loading…
Add table
Add a link
Reference in a new issue