diff --git a/include/dolphin/GBAPriv.h b/include/dolphin/GBAPriv.h index 24295e57..355d163c 100644 --- a/include/dolphin/GBAPriv.h +++ b/include/dolphin/GBAPriv.h @@ -9,6 +9,9 @@ #ifdef __cplusplus extern "C" { #endif + +typedef void (*GBATransferCallback)(s32 chan); + typedef struct GBASecParams { u8 data[0x40]; } GBASecParams; @@ -28,7 +31,7 @@ typedef struct GBA { s32 result; OSThreadQueue thread_queue; OSTime delay; - GBACallback _38; + GBATransferCallback _38; s32 _3c; s32 palette_color; s32 palette_speed; @@ -43,14 +46,14 @@ typedef struct GBA { char data4[0x100u - 0xfcu]; } GBA; - extern GBA __GBA[4]; extern BOOL __GBAReset; -//void __GBAHandler(s32 chan, s32 ret); +// void __GBAHandler(s32 chan, s32 ret); void __GBASyncCallback(s32 chan, s32 ret); s32 __GBASync(s32 chan); OSTime __GBASetDelay(s32 chan, OSTime delay); +s32 __GBATransfer(s32 chan, s32 w1, s32 w2, GBATransferCallback callback); #ifdef __cplusplus } diff --git a/include/dolphin/os/OSContext.h b/include/dolphin/os/OSContext.h index acca3026..0c94c06c 100644 --- a/include/dolphin/os/OSContext.h +++ b/include/dolphin/os/OSContext.h @@ -33,6 +33,7 @@ typedef struct OSContext { void OSSaveContext(OSContext* context); void OSClearContext(OSContext* context); +OSContext* OSGetCurrentContext(); void OSSetCurrentContext(OSContext* context); #ifdef __cplusplus diff --git a/src/Dolphin/GBA/GBA.c b/src/Dolphin/GBA/GBA.c index 8b75c2e1..908f5d56 100644 --- a/src/Dolphin/GBA/GBA.c +++ b/src/Dolphin/GBA/GBA.c @@ -11,7 +11,7 @@ static OSResetFunctionInfo ResetFunctionInfo = { 127 }; -void ShortCommandProc(s32 chan, s32 ret) { +void ShortCommandProc(s32 chan) { GBA* gba; gba = &__GBA[chan]; diff --git a/src/Dolphin/GBA/GBARead.c b/src/Dolphin/GBA/GBARead.c index 4f0b2a5d..3fc58b8e 100644 --- a/src/Dolphin/GBA/GBARead.c +++ b/src/Dolphin/GBA/GBARead.c @@ -1,6 +1,6 @@ #include "dolphin/GBAPriv.h" -void ReadProc(s32 chan, s32 ret) { +void ReadProc(s32 chan) { GBA* gba; gba = &__GBA[chan]; diff --git a/src/Dolphin/GBA/GBAWrite.c b/src/Dolphin/GBA/GBAWrite.c index 7c910cf0..3e5ad95d 100644 --- a/src/Dolphin/GBA/GBAWrite.c +++ b/src/Dolphin/GBA/GBAWrite.c @@ -1,6 +1,6 @@ #include "dolphin/GBAPriv.h" -void WriteProc(s32 chan, s32 ret) { +void WriteProc(s32 chan) { GBA* gba; gba = &__GBA[chan]; diff --git a/src/Dolphin/GBA/GBAXfer.c b/src/Dolphin/GBA/GBAXfer.c index 18736cc4..59a25c12 100644 --- a/src/Dolphin/GBA/GBAXfer.c +++ b/src/Dolphin/GBA/GBAXfer.c @@ -1,17 +1,47 @@ #include "dolphin/GBAPriv.h" #include "dolphin/sipriv.h" -void __GBAHandler() { - +void __GBAHandler(s32 chan, u32 sr, OSContext* context) { + int tmp; + GBA* gba; + OSContext tmpCtx; + GBACallback callback; + GBATransferCallback xferCallback; + gba = &__GBA[chan]; + if (__GBAReset != 0) { + return; + } + + if ((sr & 0xf)) { + gba->result = 1; + } else { + gba->result = 0; + } + + if (gba->_38 != NULL) { + xferCallback = gba->_38; + gba->_38 = NULL; + xferCallback(chan); + } + + if (gba->callback == NULL) { + return; + } + + OSClearContext(&tmpCtx); + OSSetCurrentContext(&tmpCtx); + callback = gba->callback; + gba->callback = NULL; + callback(chan, gba->result); + OSClearContext(&tmpCtx); + OSSetCurrentContext(context); } -void __GBASyncCallback(s32 chan, s32 ret) { - OSWakeupThread(&__GBA[chan].thread_queue); -} +void __GBASyncCallback(s32 chan, s32 ret) { OSWakeupThread(&__GBA[chan].thread_queue); } s32 __GBASync(s32 chan) { GBA* gba; - s32 enabled; + s32 enabled; s32 ret; gba = &__GBA[chan]; @@ -27,10 +57,46 @@ s32 __GBASync(s32 chan) { } void TypeAndStatusCallback(s32 chan, u32 type) { + s32 tmp; + GBA* gba; + OSContext* context; + GBACallback callback; + GBATransferCallback xferCallback; + OSContext tmpContext; + gba = &__GBA[chan]; + if (__GBAReset != 0) { + return; + } + if ((type & 0xFF) != 0 || (type & 0xffff0000) != 0x40000) { + gba->result = 1; + } else { + if (SITransfer(chan, &gba->command, gba->_0c, gba->dst, gba->_10, __GBAHandler, gba->delay)) { + return; + } + gba->result = 2; + } + + if (gba->_38 != NULL) { + xferCallback = gba->_38; + gba->_38 = NULL; + xferCallback(chan); + } + + if (gba->callback != NULL) { + context = OSGetCurrentContext(); + OSClearContext(&tmpContext); + OSSetCurrentContext(&tmpContext); + callback = gba->callback; + gba->callback = NULL; + callback(chan, gba->result); + OSClearContext(&tmpContext); + OSSetCurrentContext(context); + __OSReschedule(); + } } -s32 __GBATransfer(s32 chan, s32 w1, s32 w2, GBACallback callback) { +s32 __GBATransfer(s32 chan, s32 w1, s32 w2, GBATransferCallback callback) { s32 enabled; GBA* gba; gba = &__GBA[chan];