mirror of https://github.com/PrimeDecomp/prime.git
126 lines
2.6 KiB
C
126 lines
2.6 KiB
C
#include "dolphin/GBAPriv.h"
|
|
#include "dolphin/sipriv.h"
|
|
|
|
static void __GBAHandler(s32 chan, u32 error, OSContext* context) {
|
|
GBAControl* gba;
|
|
GBATransferCallback proc;
|
|
GBACallback callback;
|
|
OSContext exceptionContext;
|
|
|
|
gba = &__GBA[chan];
|
|
if (__GBAReset != 0) {
|
|
return;
|
|
}
|
|
|
|
if ((error & 0xf)) {
|
|
gba->ret = 1;
|
|
} else {
|
|
gba->ret = 0;
|
|
}
|
|
|
|
if (gba->proc != NULL) {
|
|
proc = gba->proc;
|
|
gba->proc = NULL;
|
|
proc(chan);
|
|
}
|
|
|
|
if (gba->callback == NULL) {
|
|
return;
|
|
}
|
|
|
|
OSClearContext(&exceptionContext);
|
|
OSSetCurrentContext(&exceptionContext);
|
|
callback = gba->callback;
|
|
gba->callback = NULL;
|
|
callback(chan, gba->ret);
|
|
OSClearContext(&exceptionContext);
|
|
OSSetCurrentContext(context);
|
|
}
|
|
|
|
void __GBASyncCallback(s32 chan, s32 ret) {
|
|
GBAControl* gba = &__GBA[chan];
|
|
OSWakeupThread(&gba->threadQueue);
|
|
}
|
|
|
|
s32 __GBASync(s32 chan) {
|
|
GBAControl* gba;
|
|
s32 ret;
|
|
s32 enabled;
|
|
gba = &__GBA[chan];
|
|
|
|
enabled = OSDisableInterrupts();
|
|
while (gba->callback != NULL) {
|
|
OSSleepThread(&gba->threadQueue);
|
|
}
|
|
|
|
ret = gba->ret;
|
|
OSRestoreInterrupts(enabled);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void TypeAndStatusCallback(s32 chan, u32 type) {
|
|
GBAControl* gba;
|
|
GBATransferCallback proc;
|
|
GBACallback callback;
|
|
OSContext exceptionContext;
|
|
OSContext* context;
|
|
|
|
gba = &__GBA[chan];
|
|
if (__GBAReset != 0) {
|
|
return;
|
|
}
|
|
|
|
ASSERT(!(type & SI_ERROR_BUSY));
|
|
if ((type & 0xFF) != 0 || (type & 0xffff0000) != 0x40000) {
|
|
gba->ret = GBA_NOT_READY;
|
|
} else {
|
|
if (SITransfer(chan, gba->output, gba->outputBytes, gba->input, gba->inputBytes, __GBAHandler,
|
|
gba->delay)) {
|
|
return;
|
|
}
|
|
gba->ret = GBA_BUSY;
|
|
}
|
|
|
|
if (gba->proc != NULL) {
|
|
proc = gba->proc;
|
|
gba->proc = NULL;
|
|
proc(chan);
|
|
}
|
|
|
|
if (gba->callback != NULL) {
|
|
context = OSGetCurrentContext();
|
|
OSClearContext(&exceptionContext);
|
|
OSSetCurrentContext(&exceptionContext);
|
|
callback = gba->callback;
|
|
gba->callback = NULL;
|
|
callback(chan, gba->ret);
|
|
OSClearContext(&exceptionContext);
|
|
OSSetCurrentContext(context);
|
|
__OSReschedule();
|
|
}
|
|
}
|
|
|
|
s32 __GBATransfer(s32 chan, s32 w1, s32 w2, GBATransferCallback callback) {
|
|
s32 enabled;
|
|
GBAControl* gba;
|
|
gba = &__GBA[chan];
|
|
enabled = OSDisableInterrupts();
|
|
gba->proc = callback;
|
|
gba->outputBytes = w1;
|
|
gba->inputBytes = w2;
|
|
SIGetTypeAsync(chan, TypeAndStatusCallback);
|
|
OSRestoreInterrupts(enabled);
|
|
|
|
return GBA_READY;
|
|
}
|
|
|
|
OSTime __GBASetDelay(s32 chan, OSTime delay) {
|
|
OSTime oldDelay;
|
|
GBAControl* gba;
|
|
gba = &__GBA[chan];
|
|
oldDelay = gba->delay;
|
|
gba->delay = delay;
|
|
return oldDelay;
|
|
}
|