From 9fa0a7f1da1b70bee995f53c6c96c43189018772 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Wed, 1 Feb 2023 18:45:02 -0400 Subject: global: Import Dolphin SDK This version comes from the Metroid Prime decompilation project. https://github.com/PrimeDecomp/prime --- src/Dolphin/GBA/GBA.c | 109 +++++++++++++++++++++++ src/Dolphin/GBA/GBAGetProcessStatus.c | 25 ++++++ src/Dolphin/GBA/GBARead.c | 42 +++++++++ src/Dolphin/GBA/GBAWrite.c | 42 +++++++++ src/Dolphin/GBA/GBAXfer.c | 163 ++++++++++++++++++++++++++++++++++ 5 files changed, 381 insertions(+) create mode 100644 src/Dolphin/GBA/GBA.c create mode 100644 src/Dolphin/GBA/GBAGetProcessStatus.c create mode 100644 src/Dolphin/GBA/GBARead.c create mode 100644 src/Dolphin/GBA/GBAWrite.c create mode 100644 src/Dolphin/GBA/GBAXfer.c (limited to 'src/Dolphin/GBA') diff --git a/src/Dolphin/GBA/GBA.c b/src/Dolphin/GBA/GBA.c new file mode 100644 index 0000000..bb89f2e --- /dev/null +++ b/src/Dolphin/GBA/GBA.c @@ -0,0 +1,109 @@ +#include "dolphin/GBAPriv.h" + +static GBASecParams SecParams[4]; +GBA __GBA[4]; +BOOL __GBAReset = FALSE; + +static BOOL OnReset(BOOL); + +static OSResetFunctionInfo ResetFunctionInfo = { + OnReset, + 127 +}; + +void ShortCommandProc(s32 chan) { + GBA* gba; + gba = &__GBA[chan]; + + if (gba->result != 0) { + return; + } + + if (gba->dst[0] != 0 || gba->dst[1] != 4) { + gba->result = 1; + return; + } + + gba->status[0] = gba->dst[2] & GBA_JSTAT_MASK; +} + +void GBAInit() { + s32 i; + GBA* gba; + for (i = 0; i < 4; ++i) { + gba = &__GBA[i]; + gba->delay = OSMicrosecondsToTicks(60); + OSInitThreadQueue(&gba->thread_queue); + gba->param = &SecParams[i]; + + // ASSERTMSG((u32) gba->param % 32 == 0) + } + + OSInitAlarm(); + DSPInit(); + __GBAReset = FALSE; + + OSRegisterResetFunction(&ResetFunctionInfo); +} + +s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback) { + GBA* gba; + s32 ret; + gba = &__GBA[chan]; + if (gba->callback != NULL) { + ret = GBA_BUSY; + } else { + gba->command = 0; + gba->status = status; + gba->callback = callback; + ret = __GBATransfer(chan, 1, 3, ShortCommandProc); + } + + return ret; +} + + +s32 GBAGetStatus(s32 chan, u8* status) { + s32 ret; + ret = GBAGetStatusAsync(chan, status, __GBASyncCallback); + + if (ret != GBA_READY) { + return ret; + } + + return __GBASync(chan); +} + + +s32 GBAResetAsync(s32 chan, u8* status, GBACallback callback) { + GBA* gba; + s32 ret; + gba = &__GBA[chan]; + if (gba->callback != NULL) { + ret = GBA_BUSY; + } else { + gba->command = 0xFF; + gba->status = status; + gba->callback = callback; + ret = __GBATransfer(chan, 1, 3, ShortCommandProc); + } + + return ret; +} + + +s32 GBAReset(s32 chan, u8* status) { + s32 ret; + + ret = GBAResetAsync(chan, status, __GBASyncCallback); + if (ret != GBA_READY) { + return ret; + } + + return __GBASync(chan); +} + +BOOL OnReset(BOOL) { + __GBAReset = TRUE; + return TRUE; +} diff --git a/src/Dolphin/GBA/GBAGetProcessStatus.c b/src/Dolphin/GBA/GBAGetProcessStatus.c new file mode 100644 index 0000000..38d8c38 --- /dev/null +++ b/src/Dolphin/GBA/GBAGetProcessStatus.c @@ -0,0 +1,25 @@ +#include "dolphin/GBAPriv.h" + +s32 GBAGetProcessStatus(s32 chan, u8* percentp) { + GBA* gba; + s32 ret; + BOOL enabled; + + gba = &__GBA[chan]; + enabled = OSDisableInterrupts(); + + if (gba->jboot_callback == NULL) { + if (gba->callback == NULL) { + ret = 0; + } else { + ret = 2; + } + } else { + ret = 2; + + } + + OSRestoreInterrupts(enabled); + + return ret; +} diff --git a/src/Dolphin/GBA/GBARead.c b/src/Dolphin/GBA/GBARead.c new file mode 100644 index 0000000..ab19bbb --- /dev/null +++ b/src/Dolphin/GBA/GBARead.c @@ -0,0 +1,42 @@ +#include "dolphin/GBAPriv.h" + +void ReadProc(s32 chan) { + GBA* gba; + gba = &__GBA[chan]; + + if (gba->result == 0) { + memcpy(gba->buffer, &gba->dst, 4); + gba->status[0] = gba->_09 & GBA_JSTAT_MASK; + } +} + +s32 GBAReadAsync(s32 chan, u8* dst, u8* status, GBACallback callback) { + GBA* gba; + s32 ret; + + gba = &__GBA[chan]; + + if (gba->callback != NULL) { + ret = 2; + } else { + gba->command = 0x14; + gba->buffer = dst; + gba->status = status; + gba->callback = callback; + ret = __GBATransfer(chan, 1, 5, ReadProc); + } + + return ret; +} + + +s32 GBARead(s32 chan, u8* dst, u8* status) { + s32 tmp; + s32 ret; + ret = GBAReadAsync(chan, dst, status, __GBASyncCallback); + if (ret != GBA_READY) { + return ret; + } + + return __GBASync(chan); +} diff --git a/src/Dolphin/GBA/GBAWrite.c b/src/Dolphin/GBA/GBAWrite.c new file mode 100644 index 0000000..f040f92 --- /dev/null +++ b/src/Dolphin/GBA/GBAWrite.c @@ -0,0 +1,42 @@ +#include "dolphin/GBAPriv.h" + +void WriteProc(s32 chan) { + GBA* gba; + gba = &__GBA[chan]; + + if (gba->result != 0) { + return; + } + + gba->status[0] = gba->dst[0] & GBA_JSTAT_MASK; +} + +s32 GBAWriteAsync(s32 chan, u8* src, u8* status, GBACallback callback) { + GBA* gba; + s32 ret; + gba = &__GBA[chan]; + + if (gba->callback != NULL) { + ret = GBA_BUSY; + } else { + gba->command = 0x15; + memcpy(gba->src, src, 4); + gba->buffer = src; + gba->status = status; + gba->callback = callback; + ret = __GBATransfer(chan, 5, 1, WriteProc); + } + + return ret; +} + + +s32 GBAWrite(s32 chan, u8* src, u8* status) { + s32 ret; + s32 tmp; + ret = GBAWriteAsync(chan, src, status, __GBASyncCallback); + if (ret != GBA_READY) { + return ret; + } + return __GBASync(chan); +} diff --git a/src/Dolphin/GBA/GBAXfer.c b/src/Dolphin/GBA/GBAXfer.c new file mode 100644 index 0000000..c88ffd1 --- /dev/null +++ b/src/Dolphin/GBA/GBAXfer.c @@ -0,0 +1,163 @@ +#include "dolphin/GBAPriv.h" +#include "dolphin/sipriv.h" + +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); } + +#ifdef FULL_FRANK +/* This actually does match, but has an epilogue swap */ +s32 __GBASync(s32 chan) { + GBA* gba; + s32 enabled; + s32 ret; + gba = &__GBA[chan]; + + enabled = OSDisableInterrupts(); + while (gba->callback != NULL) { + OSSleepThread(&gba->thread_queue); + } + + ret = gba->result; + OSRestoreInterrupts(enabled); + + return ret; +} +#else +extern void OSSleepThread(); +/* clang-format off */ +#pragma push +#pragma optimization_level 0 +#pragma optimizewithasm off +asm s32 __GBASync(s32 chan) { + nofralloc + mflr r0 + lis r4, __GBA@ha + stw r0, 4(r1) + slwi r3, r3, 8 + addi r0, r4, __GBA@l + stwu r1, -0x18(r1) + stw r31, 0x14(r1) + add r31, r0, r3 + stw r30, 0x10(r1) + bl OSDisableInterrupts + mr r30, r3 + b lbl_803CAD50 +lbl_803CAD48: + addi r3, r31, 0x24 + bl OSSleepThread +lbl_803CAD50: + lwz r0, 0x1c(r31) + cmplwi r0, 0 + bne lbl_803CAD48 + lwz r31, 0x20(r31) + mr r3, r30 + bl OSRestoreInterrupts + mr r3, r31 + lwz r0, 0x1c(r1) + lwz r31, 0x14(r1) + lwz r30, 0x10(r1) + addi r1, r1, 0x18 + mtlr r0 + blr +} +/* clang-format on */ +#pragma pop +#endif + +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 = GBA_NOT_READY; + } else { + if (SITransfer(chan, &gba->command, gba->_0c, gba->dst, gba->_10, __GBAHandler, gba->delay)) { + return; + } + gba->result = GBA_BUSY; + } + + 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, GBATransferCallback callback) { + s32 enabled; + GBA* gba; + gba = &__GBA[chan]; + enabled = OSDisableInterrupts(); + gba->_38 = callback; + gba->_0c = w1; + gba->_10 = w2; + SIGetTypeAsync(chan, TypeAndStatusCallback); + OSRestoreInterrupts(enabled); + + return GBA_READY; +} + +OSTime __GBASetDelay(s32 chan, OSTime delay) { + OSTime oldDelay; + GBA* gba; + gba = &__GBA[chan]; + oldDelay = gba->delay; + gba->delay = delay; + return oldDelay; +} -- cgit v1.2.3-13-gbd6f