From b0e6d06c72373ebd72ea5f527d025b6c0a4eca4a Mon Sep 17 00:00:00 2001 From: h0504 Date: Tue, 27 Oct 2026 08:25:31 +0900 Subject: [PATCH 1/7] Add Rev 1 Dolphin SDK sources Rev 1 links a newer SDK build than Rev 0 (OS/GX/AR Nov 26 2003, DVD Sep 16 2003, PAD Aug 6 2003), the same build Pikmin 2 uses. Add a Rev-1-only copy under src/static/GAEJ01_01/dolphin, starting from the Rev 0 attempt and porting the newer code (CARD permission checks and font encoding, DVD, GX 0x5B0-byte GXData, OS, PAD, VI, ...). Private headers stay next to the sources so include/dolphin is untouched. Co-Authored-By: Claude Opus 5.5 --- .../dolphin/OdemuExi2/DebuggerDriver.c | 322 ++++ src/static/GAEJ01_01/dolphin/ai/ai.c | 372 ++++ .../GAEJ01_01/dolphin/amcstubs/AmcExi2Stubs.c | 29 + src/static/GAEJ01_01/dolphin/ar/__ar.h | 13 + src/static/GAEJ01_01/dolphin/ar/ar.c | 386 ++++ src/static/GAEJ01_01/dolphin/ar/arq.c | 159 ++ src/static/GAEJ01_01/dolphin/base/PPCArch.c | 160 ++ src/static/GAEJ01_01/dolphin/card/CARDBios.c | 830 ++++++++ src/static/GAEJ01_01/dolphin/card/CARDBlock.c | 168 ++ src/static/GAEJ01_01/dolphin/card/CARDCheck.c | 362 ++++ .../GAEJ01_01/dolphin/card/CARDCreate.c | 124 ++ .../GAEJ01_01/dolphin/card/CARDDelete.c | 106 ++ src/static/GAEJ01_01/dolphin/card/CARDDir.c | 94 + .../GAEJ01_01/dolphin/card/CARDFormat.c | 154 ++ src/static/GAEJ01_01/dolphin/card/CARDMount.c | 410 ++++ src/static/GAEJ01_01/dolphin/card/CARDNet.c | 120 ++ src/static/GAEJ01_01/dolphin/card/CARDOpen.c | 176 ++ src/static/GAEJ01_01/dolphin/card/CARDRaw.c | 79 + src/static/GAEJ01_01/dolphin/card/CARDRdwr.c | 100 + src/static/GAEJ01_01/dolphin/card/CARDRead.c | 178 ++ .../GAEJ01_01/dolphin/card/CARDRename.c | 71 + src/static/GAEJ01_01/dolphin/card/CARDStat.c | 166 ++ .../GAEJ01_01/dolphin/card/CARDStatEx.c | 119 ++ .../GAEJ01_01/dolphin/card/CARDUnlock.c | 401 ++++ src/static/GAEJ01_01/dolphin/card/CARDWrite.c | 122 ++ src/static/GAEJ01_01/dolphin/card/__card.h | 101 + src/static/GAEJ01_01/dolphin/db/db.c | 44 + src/static/GAEJ01_01/dolphin/dsp/__dsp.h | 12 + src/static/GAEJ01_01/dolphin/dsp/dsp.c | 64 + src/static/GAEJ01_01/dolphin/dvd/__dvd.h | 59 + src/static/GAEJ01_01/dolphin/dvd/dvd.c | 1349 +++++++++++++ src/static/GAEJ01_01/dolphin/dvd/dvdFatal.c | 12 + src/static/GAEJ01_01/dolphin/dvd/dvderror.c | 78 + src/static/GAEJ01_01/dolphin/dvd/dvdfs.c | 665 +++++++ src/static/GAEJ01_01/dolphin/dvd/dvdidutils.c | 53 + src/static/GAEJ01_01/dolphin/dvd/dvdlow.c | 559 ++++++ src/static/GAEJ01_01/dolphin/dvd/dvdqueue.c | 166 ++ src/static/GAEJ01_01/dolphin/dvd/fstload.c | 86 + src/static/GAEJ01_01/dolphin/exi/EXIAd16.c | 93 + src/static/GAEJ01_01/dolphin/exi/EXIBios.c | 768 ++++++++ src/static/GAEJ01_01/dolphin/exi/EXIUart.c | 196 ++ src/static/GAEJ01_01/dolphin/gba/GBA.c | 102 + .../dolphin/gba/GBAGetProcessStatus.c | 40 + src/static/GAEJ01_01/dolphin/gba/GBAJoyBoot.c | 385 ++++ src/static/GAEJ01_01/dolphin/gba/GBARead.c | 40 + src/static/GAEJ01_01/dolphin/gba/GBAWrite.c | 37 + src/static/GAEJ01_01/dolphin/gba/GBAXfer.c | 123 ++ src/static/GAEJ01_01/dolphin/gx/GXAttr.c | 482 +++++ src/static/GAEJ01_01/dolphin/gx/GXBump.c | 202 ++ .../GAEJ01_01/dolphin/gx/GXDisplayList.c | 77 + src/static/GAEJ01_01/dolphin/gx/GXDraw.c | 558 ++++++ src/static/GAEJ01_01/dolphin/gx/GXFifo.c | 351 ++++ src/static/GAEJ01_01/dolphin/gx/GXFrameBuf.c | 452 +++++ src/static/GAEJ01_01/dolphin/gx/GXGeometry.c | 120 ++ src/static/GAEJ01_01/dolphin/gx/GXInit.c | 562 ++++++ src/static/GAEJ01_01/dolphin/gx/GXLight.c | 336 ++++ src/static/GAEJ01_01/dolphin/gx/GXMisc.c | 322 ++++ src/static/GAEJ01_01/dolphin/gx/GXPerf.c | 307 +++ src/static/GAEJ01_01/dolphin/gx/GXPixel.c | 262 +++ src/static/GAEJ01_01/dolphin/gx/GXSave.c | 522 +++++ src/static/GAEJ01_01/dolphin/gx/GXStubs.c | 6 + src/static/GAEJ01_01/dolphin/gx/GXTev.c | 379 ++++ src/static/GAEJ01_01/dolphin/gx/GXTexture.c | 613 ++++++ src/static/GAEJ01_01/dolphin/gx/GXTransform.c | 289 +++ src/static/GAEJ01_01/dolphin/gx/GXVerifRAS.c | 575 ++++++ src/static/GAEJ01_01/dolphin/gx/GXVerifXF.c | 947 +++++++++ src/static/GAEJ01_01/dolphin/gx/GXVerify.c | 300 +++ src/static/GAEJ01_01/dolphin/gx/GXVert.c | 85 + src/static/GAEJ01_01/dolphin/gx/__gx.h | 1695 +++++++++++++++++ src/static/GAEJ01_01/dolphin/mtx/mtx.c | 619 ++++++ src/static/GAEJ01_01/dolphin/mtx/mtx44.c | 88 + src/static/GAEJ01_01/dolphin/mtx/mtxvec.c | 103 + src/static/GAEJ01_01/dolphin/mtx/vec.c | 171 ++ .../GAEJ01_01/dolphin/odenotstub/odenotstub.c | 5 + src/static/GAEJ01_01/dolphin/os/OS.c | 619 ++++++ src/static/GAEJ01_01/dolphin/os/OSAlarm.c | 235 +++ src/static/GAEJ01_01/dolphin/os/OSAlloc.c | 389 ++++ src/static/GAEJ01_01/dolphin/os/OSArena.c | 20 + .../GAEJ01_01/dolphin/os/OSAudioSystem.c | 108 ++ src/static/GAEJ01_01/dolphin/os/OSCache.c | 285 +++ src/static/GAEJ01_01/dolphin/os/OSContext.c | 606 ++++++ src/static/GAEJ01_01/dolphin/os/OSError.c | 218 +++ src/static/GAEJ01_01/dolphin/os/OSFont.c | 505 +++++ src/static/GAEJ01_01/dolphin/os/OSInterrupt.c | 424 +++++ src/static/GAEJ01_01/dolphin/os/OSLink.c | 490 +++++ src/static/GAEJ01_01/dolphin/os/OSMemory.c | 216 +++ src/static/GAEJ01_01/dolphin/os/OSMessage.c | 74 + src/static/GAEJ01_01/dolphin/os/OSMutex.c | 255 +++ src/static/GAEJ01_01/dolphin/os/OSReboot.c | 139 ++ src/static/GAEJ01_01/dolphin/os/OSReset.c | 226 +++ src/static/GAEJ01_01/dolphin/os/OSResetSW.c | 92 + src/static/GAEJ01_01/dolphin/os/OSRtc.c | 278 +++ src/static/GAEJ01_01/dolphin/os/OSSemaphore.c | 56 + src/static/GAEJ01_01/dolphin/os/OSStopwatch.c | 48 + src/static/GAEJ01_01/dolphin/os/OSSync.c | 35 + src/static/GAEJ01_01/dolphin/os/OSThread.c | 843 ++++++++ src/static/GAEJ01_01/dolphin/os/OSTime.c | 170 ++ src/static/GAEJ01_01/dolphin/os/__os.h | 131 ++ .../GAEJ01_01/dolphin/os/__ppc_eabi_init.cpp | 71 + src/static/GAEJ01_01/dolphin/os/__start.c | 211 ++ src/static/GAEJ01_01/dolphin/pad/Pad.c | 809 ++++++++ src/static/GAEJ01_01/dolphin/pad/Padclamp.c | 168 ++ src/static/GAEJ01_01/dolphin/si/SIBios.c | 784 ++++++++ .../GAEJ01_01/dolphin/si/SISamplingRate.c | 124 ++ src/static/GAEJ01_01/dolphin/vi/__vi.h | 100 + src/static/GAEJ01_01/dolphin/vi/vi.c | 1063 +++++++++++ 106 files changed, 30473 insertions(+) create mode 100644 src/static/GAEJ01_01/dolphin/OdemuExi2/DebuggerDriver.c create mode 100644 src/static/GAEJ01_01/dolphin/ai/ai.c create mode 100644 src/static/GAEJ01_01/dolphin/amcstubs/AmcExi2Stubs.c create mode 100644 src/static/GAEJ01_01/dolphin/ar/__ar.h create mode 100644 src/static/GAEJ01_01/dolphin/ar/ar.c create mode 100644 src/static/GAEJ01_01/dolphin/ar/arq.c create mode 100644 src/static/GAEJ01_01/dolphin/base/PPCArch.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDBios.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDBlock.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDCheck.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDCreate.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDDelete.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDDir.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDFormat.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDMount.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDNet.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDOpen.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDRaw.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDRdwr.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDRead.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDRename.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDStat.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDStatEx.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDUnlock.c create mode 100644 src/static/GAEJ01_01/dolphin/card/CARDWrite.c create mode 100644 src/static/GAEJ01_01/dolphin/card/__card.h create mode 100644 src/static/GAEJ01_01/dolphin/db/db.c create mode 100644 src/static/GAEJ01_01/dolphin/dsp/__dsp.h create mode 100644 src/static/GAEJ01_01/dolphin/dsp/dsp.c create mode 100644 src/static/GAEJ01_01/dolphin/dvd/__dvd.h create mode 100644 src/static/GAEJ01_01/dolphin/dvd/dvd.c create mode 100644 src/static/GAEJ01_01/dolphin/dvd/dvdFatal.c create mode 100644 src/static/GAEJ01_01/dolphin/dvd/dvderror.c create mode 100644 src/static/GAEJ01_01/dolphin/dvd/dvdfs.c create mode 100644 src/static/GAEJ01_01/dolphin/dvd/dvdidutils.c create mode 100644 src/static/GAEJ01_01/dolphin/dvd/dvdlow.c create mode 100644 src/static/GAEJ01_01/dolphin/dvd/dvdqueue.c create mode 100644 src/static/GAEJ01_01/dolphin/dvd/fstload.c create mode 100644 src/static/GAEJ01_01/dolphin/exi/EXIAd16.c create mode 100644 src/static/GAEJ01_01/dolphin/exi/EXIBios.c create mode 100644 src/static/GAEJ01_01/dolphin/exi/EXIUart.c create mode 100644 src/static/GAEJ01_01/dolphin/gba/GBA.c create mode 100644 src/static/GAEJ01_01/dolphin/gba/GBAGetProcessStatus.c create mode 100644 src/static/GAEJ01_01/dolphin/gba/GBAJoyBoot.c create mode 100644 src/static/GAEJ01_01/dolphin/gba/GBARead.c create mode 100644 src/static/GAEJ01_01/dolphin/gba/GBAWrite.c create mode 100644 src/static/GAEJ01_01/dolphin/gba/GBAXfer.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXAttr.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXBump.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXDisplayList.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXDraw.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXFifo.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXFrameBuf.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXGeometry.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXInit.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXLight.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXMisc.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXPerf.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXPixel.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXSave.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXStubs.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXTev.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXTexture.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXTransform.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXVerifRAS.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXVerifXF.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXVerify.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/GXVert.c create mode 100644 src/static/GAEJ01_01/dolphin/gx/__gx.h create mode 100644 src/static/GAEJ01_01/dolphin/mtx/mtx.c create mode 100644 src/static/GAEJ01_01/dolphin/mtx/mtx44.c create mode 100644 src/static/GAEJ01_01/dolphin/mtx/mtxvec.c create mode 100644 src/static/GAEJ01_01/dolphin/mtx/vec.c create mode 100644 src/static/GAEJ01_01/dolphin/odenotstub/odenotstub.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OS.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSAlarm.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSAlloc.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSArena.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSAudioSystem.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSCache.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSContext.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSError.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSFont.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSInterrupt.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSLink.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSMemory.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSMessage.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSMutex.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSReboot.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSReset.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSResetSW.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSRtc.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSSemaphore.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSStopwatch.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSSync.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSThread.c create mode 100644 src/static/GAEJ01_01/dolphin/os/OSTime.c create mode 100644 src/static/GAEJ01_01/dolphin/os/__os.h create mode 100644 src/static/GAEJ01_01/dolphin/os/__ppc_eabi_init.cpp create mode 100644 src/static/GAEJ01_01/dolphin/os/__start.c create mode 100644 src/static/GAEJ01_01/dolphin/pad/Pad.c create mode 100644 src/static/GAEJ01_01/dolphin/pad/Padclamp.c create mode 100644 src/static/GAEJ01_01/dolphin/si/SIBios.c create mode 100644 src/static/GAEJ01_01/dolphin/si/SISamplingRate.c create mode 100644 src/static/GAEJ01_01/dolphin/vi/__vi.h create mode 100644 src/static/GAEJ01_01/dolphin/vi/vi.c diff --git a/src/static/GAEJ01_01/dolphin/OdemuExi2/DebuggerDriver.c b/src/static/GAEJ01_01/dolphin/OdemuExi2/DebuggerDriver.c new file mode 100644 index 00000000..398103e7 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/OdemuExi2/DebuggerDriver.c @@ -0,0 +1,322 @@ +#include +#include +#include + +static __OSInterruptHandler MTRCallback; +// not __OSInterruptHandler because f u that's why +static void (*DBGCallback)(u32, OSContext*); +static u32 SendMailData; +static s32 RecvDataLeng; +static u8* pEXIInputFlag; +static u8 EXIInputFlag; + +static u8 SendCount = 0x80; + +static void DBGHandler(__OSInterrupt interrupt, OSContext* context); +static void MWCallback(u32 interrupt, OSContext* context); +static void DBGEXIInit(void); +static BOOL DBGEXISelect(u32); +static BOOL DBGEXIDeselect(void); +static BOOL DBGReadStatus(void*); +static BOOL DBGWrite(u32, u32*, s32); +static BOOL DBGRead(u32, u32*, s32); +static BOOL DBGWriteMailbox(u32); +static BOOL DBGReadMailbox(void*); +static BOOL DBGEXIImm(void*, s32, u32); + +static void DBGEXIInit(void) +{ + __OSMaskInterrupts(0x18000); + __EXIRegs[10] = 0; +} + +static BOOL DBGEXISelect(u32 v) +{ + u32 regs = __EXIRegs[10]; + regs &= 0x405; + regs |= 0x80 | (v << 4); + __EXIRegs[10] = regs; + return TRUE; +} + +static BOOL DBGEXIDeselect(void) +{ + __EXIRegs[10] &= 0x405; + return TRUE; +} + +static BOOL DBGEXISync(void) +{ + while (__EXIRegs[13] & 1) + ; + return TRUE; +} + +static BOOL DBGEXIImm(void* data, s32 byte_size, u32 write) +{ + u32 writeVal; + u32 readVal; + int i; + + if (write) { + writeVal = 0; + for (i = 0; i < byte_size; ++i) { + u8* nextWordPtr = (u8*)data + i; + writeVal |= *nextWordPtr << ((3 - i) << 3); + } + __EXIRegs[14] = writeVal; + } + + __EXIRegs[13] = 1 | (write << 2) | ((byte_size - 1U) << 4); + + DBGEXISync(); + if (!write) { + u8* dataPtr = (u8*)data; + readVal = __EXIRegs[14]; + for (i = 0; i < byte_size; ++i) { + *dataPtr++ = readVal >> ((3 - i) << 3); + } + } + + return TRUE; +} + +static BOOL DBGReadMailbox(void* param1) +{ + BOOL error = FALSE; + u32 local_c; + + if (!DBGEXISelect(4)) { + return FALSE; + } + + local_c = 0x60000000; + error |= !DBGEXIImm((u8*)&local_c, 2, 1); + error |= !DBGEXISync(); + error |= !DBGEXIImm(param1, sizeof(param1), 0); + error |= !DBGEXISync(); + error |= !DBGEXIDeselect(); + + return !error; +} + +static BOOL DBGWriteMailbox(u32 param_1) +{ + BOOL error = FALSE; + u32 value; + + if (!DBGEXISelect(4)) { + return FALSE; + } + + value = (param_1 & 0x1fffffff) | 0xc0000000; + error |= !DBGEXIImm((u8*)&value, sizeof(value), 1); + error |= !DBGEXISync(); + error |= !DBGEXIDeselect(); + + return !error; +} + +static BOOL DBGRead(u32 param1, u32* data, s32 byte_size) +{ + BOOL error = FALSE; + u32* dataPtr = (u32*)data; + u32 writeValue; + u32 readValue; + + if (!DBGEXISelect(4)) { + return FALSE; + } + + writeValue = (u32)(param1 << 8) & 0x1fffc00 | 0x20000000; + error |= !DBGEXIImm((u8*)&writeValue, sizeof(writeValue), 1); + error |= !DBGEXISync(); + + while (byte_size != 0) { + error |= !DBGEXIImm((u8*)&readValue, sizeof(readValue), 0); + error |= !DBGEXISync(); + + *dataPtr++ = readValue; + + byte_size -= 4; + if (byte_size < 0) { + byte_size = 0; + } + } + error |= !DBGEXIDeselect(); + + return !error; +} + +static BOOL DBGWrite(u32 param1, u32* data, s32 byte_size) +{ + BOOL error = FALSE; + u32* dataPtr = (u32*)data; + u32 value; + u32 nextWord; + + if (!DBGEXISelect(4)) { + return FALSE; + } + + value = (param1 & 0x1fffc) << 8 | 0xa0000000; + error = !DBGEXIImm((u8*)&value, sizeof(value), 1); + error |= !DBGEXISync(); + + while (byte_size != 0) { + nextWord = *dataPtr++; + + error |= !DBGEXIImm((u8*)&nextWord, sizeof(nextWord), 1); + error |= !DBGEXISync(); + + byte_size -= 4; + if (byte_size < 0) + byte_size = 0; + } + + error |= !DBGEXIDeselect(); + + return !error; +} + +static BOOL DBGReadStatus(void* param_1) +{ + BOOL error = FALSE; + u32 value; + + if (!DBGEXISelect(4)) { + return FALSE; + } + + value = 0x40000000; + error |= !DBGEXIImm((u8*)&value, 2, 1); + error |= !DBGEXISync(); + error |= !DBGEXIImm(param_1, sizeof(param_1), 0); + error |= !DBGEXISync(); + error |= !DBGEXIDeselect(); + + return !error; +} + +static void MWCallback(u32 interrupt, OSContext* context) +{ + EXIInputFlag = 1; + if (MTRCallback) { + (*MTRCallback)(0, context); + } +} + +static void DBGHandler(__OSInterrupt interrupt, OSContext* context) +{ + __PIRegs[0] = 0x1000; + if (DBGCallback) { + (*DBGCallback)(interrupt, context); + } +} + +static void CheckMailBox(void) +{ + u32 local_8[2]; + + DBGReadStatus(local_8); + if (local_8[0] & 1) { + DBGReadMailbox(local_8); + local_8[0] &= ~0xE0000000; + if ((local_8[0] & 0x1f000000) == 0x1f000000) { + SendMailData = local_8[0]; + RecvDataLeng = local_8[0] & 0x7fff; + EXIInputFlag = 1; + } + } +} + +void DBInitComm(volatile u8** param_1, __OSInterruptHandler param_2) +{ + BOOL enabled; + + enabled = OSDisableInterrupts(); + pEXIInputFlag = &EXIInputFlag; + *param_1 = pEXIInputFlag; + MTRCallback = param_2; + DBGEXIInit(); + OSRestoreInterrupts(enabled); +} + +void DBInitInterrupts(void) +{ + __OSMaskInterrupts(0x18000); + __OSMaskInterrupts(0x40); + DBGCallback = MWCallback; + __OSSetInterruptHandler(0x19, DBGHandler); + __OSUnmaskInterrupts(0x40); +} + +u32 DBQueryData(void) +{ + BOOL enable; + + EXIInputFlag = 0; + if (RecvDataLeng == 0) { + enable = OSDisableInterrupts(); + CheckMailBox(); + OSRestoreInterrupts(enable); + } + return RecvDataLeng; +} + +int DBRead(void* param1, u32 param2) +{ + BOOL enabled; + u32 lVar3; + + enabled = OSDisableInterrupts(); + if (SendMailData & 0x10000) { + lVar3 = 0x1000; + } else { + lVar3 = 0; + } + DBGRead(lVar3 + 0x1e000, param1, param2 + 3U & 0xfffffffc); + RecvDataLeng = 0; + EXIInputFlag = 0; + OSRestoreInterrupts(enabled); + return 0; +} + +int DBWrite(const void* data, u32 size) +{ + u32 value; + u32 busyFlag; + BOOL enabled; + + enabled = OSDisableInterrupts(); + do { + DBGReadStatus(&busyFlag); + } while (busyFlag & 2); + + ++SendCount; + + value = ((SendCount & 1) ? 0x1000 : 0); + while (!DBGWrite(value | 0x1c000, data, ALIGN_NEXT(size, 4))) + ; + + do { + DBGReadStatus(&busyFlag); + } while (busyFlag & 2); + + value = (SendCount << 0x10) | 0x1f000000 | size; + while (!DBGWriteMailbox(value)) + ; + + do { + while (!DBGReadStatus(&busyFlag)) + ; + } while (busyFlag & 2); + + OSRestoreInterrupts(enabled); + + return 0; +} + +void DBOpen(void) { } + +void DBClose(void) { } diff --git a/src/static/GAEJ01_01/dolphin/ai/ai.c b/src/static/GAEJ01_01/dolphin/ai/ai.c new file mode 100644 index 00000000..a95f4145 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/ai/ai.c @@ -0,0 +1,372 @@ +#include +#include +#include +#include +#include + +#ifndef GET_REG_FIELD +#define GET_REG_FIELD(reg, size, shift) ((int)((reg) >> (shift)) & ((1 << (size)) - 1)) +#endif + +#ifndef SET_REG_FIELD +#define SET_REG_FIELD(line, reg, size, shift, val) \ +do { \ + ASSERTMSGLINE(line, ((u32)(val) & ~((1 << (size)) - 1)) == 0, "GX Internal: Register field out of range"); \ + (reg) = ((u32)(reg) & ~(((1 << (size)) - 1) << (shift))) | ((u32)(val) << (shift)); \ +} while (0) +#endif + +void OSRegisterVersion(const char* id); + +char* __AIVersion = "<< Dolphin SDK - AI\trelease build: Apr 17 2003 12:33:54 (0x2301) >>"; + +static AISCallback __AIS_Callback; +static AIDCallback __AID_Callback; +static u8* __CallbackStack; +static u8* __OldStack; +static volatile BOOL __AI_init_flag; +static volatile BOOL __AID_Active; +static OSTime bound_32KHz; +static OSTime bound_48KHz; +static OSTime min_wait; +static OSTime max_wait; +static OSTime buffer; + +struct STRUCT_TIMELOG { + OSTime t_start; + OSTime t1; + OSTime t2; + OSTime t3; + OSTime t4; + OSTime t_end; +}; + +#if DEBUG +struct STRUCT_TIMELOG profile; +#endif + +static void __AI_set_stream_sample_rate(u32 rate); +static void __AIDHandler(__OSInterrupt interrupt, OSContext* context); +static void __AISHandler(__OSInterrupt interrupt, OSContext* context); +static void __AICallbackStackSwitch(void* cb); +static void __AI_SRC_INIT(void); + +AIDCallback AIRegisterDMACallback(AIDCallback callback) +{ + AIDCallback old_callback; + BOOL old; + + old_callback = __AID_Callback; + old = OSDisableInterrupts(); + __AID_Callback = callback; + OSRestoreInterrupts(old); + return old_callback; +} + +void AIInitDMA(u32 start_addr, u32 length) +{ + BOOL old; + + old = OSDisableInterrupts(); + __DSPRegs[24] = (__DSPRegs[24] & 0xFFFFFC00) | (start_addr >> 16); + __DSPRegs[25] = (__DSPRegs[25] & 0xFFFF001F) | (start_addr & 0xFFFF); + ASSERTMSGLINE(0x12E, (length & 0x1F) == 0, + "AIStartDMA: length must be multiple of 32 bytes"); + __DSPRegs[27] = (__DSPRegs[27] & 0xFFFF8000) | ((length >> 5) & 0xFFFF); + OSRestoreInterrupts(old); +} + +void AIStartDMA(void) { __DSPRegs[27] = __DSPRegs[27] | 0x8000; } + +void AIStopDMA(void) { __DSPRegs[27] = __DSPRegs[27] & ~0x8000; } + +BOOL AICheckInit(void) { return __AI_init_flag; } + +u32 AIGetStreamSampleCount(void) { + return __AIRegs[2]; +} + +void AIResetStreamSampleCount(void) +{ + __AIRegs[0] = (__AIRegs[0] & ~0x20) | 0x20; +} + +inline void AISetStreamTrigger(u32 trigger) { __AIRegs[3] = trigger; } + +u32 AIGetStreamTrigger(void) { + return __AIRegs[3]; +} + +void AISetStreamPlayState(u32 state) +{ + BOOL old; + u8 vol_left; + u8 vol_right; + + if (state != AIGetStreamPlayState()) { + if (AIGetStreamSampleRate() == 0 && state == AI_STREAM_START) { + vol_left = AIGetStreamVolRight(); + vol_right = AIGetStreamVolLeft(); + AISetStreamVolRight(0); + AISetStreamVolLeft(0); + old = OSDisableInterrupts(); + __AI_SRC_INIT(); + SET_REG_FIELD(0, __AIRegs[0], 1, 5, 1); + SET_REG_FIELD(0, __AIRegs[0], 1, 0, AI_STREAM_START); + OSRestoreInterrupts(old); + AISetStreamVolLeft(vol_left); + AISetStreamVolRight(vol_right); + return; + } + SET_REG_FIELD(0x27F, __AIRegs[0], 1, 0, state); + } +} + +u32 AIGetStreamPlayState(void) { return __AIRegs[0] & 1; } + +void AISetDSPSampleRate(u32 rate) +{ + BOOL old; + u32 play_state; + u32 afr_state; + u8 vol_left; + u8 vol_right; + + if (rate != AIGetDSPSampleRate()) { + __AIRegs[0] = (__AIRegs[0] & 0xFFFFFFBF); + if (rate == AI_SAMPLERATE_32KHZ) { + vol_left = AIGetStreamVolLeft(); + vol_right = AIGetStreamVolRight(); + play_state = AIGetStreamPlayState(); + afr_state = AIGetStreamSampleRate(); + AISetStreamVolLeft(0U); + AISetStreamVolRight(0U); + old = OSDisableInterrupts(); + __AI_SRC_INIT(); + SET_REG_FIELD(0x2D8, __AIRegs[0], 1, 5, 1); + SET_REG_FIELD(0x2D9, __AIRegs[0], 1, 1, afr_state); + SET_REG_FIELD(0x2DA, __AIRegs[0], 1, 0, play_state); + __AIRegs[0] |= 0x40; + OSRestoreInterrupts(old); + AISetStreamVolLeft(vol_left); + AISetStreamVolRight(vol_right); + } + } +} + +u32 AIGetDSPSampleRate(void) { return GET_REG_FIELD(__AIRegs[0], 1, 6) ^ 1; } + +void AISetStreamSampleRate(u32 rate) +{ + if (rate == AI_SAMPLERATE_48KHZ) { + __AI_set_stream_sample_rate(rate); + return; + } +#if DEBUG + OSReport("AISetStreamSampleRate(): OBSOLETED. Only 48KHz streaming from " + "disk is supported!\n"); +#endif +} + +static void __AI_set_stream_sample_rate(u32 rate) +{ + BOOL old; + u32 play_state; + u8 vol_left; + u8 vol_right; + u32 dsp_src_state; + + if (rate != AIGetStreamSampleRate()) { + play_state = AIGetStreamPlayState(); + vol_left = AIGetStreamVolLeft(); + vol_right = AIGetStreamVolRight(); + AISetStreamVolRight(0); + AISetStreamVolLeft(0); + dsp_src_state = __AIRegs[0] & 0x40; + SET_REG_FIELD(0, __AIRegs[0], 1, 6, 0); + old = OSDisableInterrupts(); + __AI_SRC_INIT(); + __AIRegs[0] |= dsp_src_state; + SET_REG_FIELD(0x368, __AIRegs[0], 1, 5, 1); + SET_REG_FIELD(0x369, __AIRegs[0], 1, 1, rate); + OSRestoreInterrupts(old); + AISetStreamPlayState(play_state); + AISetStreamVolLeft(vol_left); + AISetStreamVolRight(vol_right); + } +} + +u32 AIGetStreamSampleRate(void) { return GET_REG_FIELD(__AIRegs[0], 1, 1); } + +void AISetStreamVolLeft(u8 vol) +{ + SET_REG_FIELD(0x3A3, __AIRegs[1], 8, 0, vol); +} + +u8 AIGetStreamVolLeft(void) { return GET_REG_FIELD(__AIRegs[1], 8, 0); } + +void AISetStreamVolRight(u8 vol) +{ + SET_REG_FIELD(0x3CC, __AIRegs[1], 8, 8, vol); +} + +u8 AIGetStreamVolRight(void) { return (__AIRegs[1] & (0xFF << 8)) >> 8; } + +void AIInit(u8* stack) +{ + if (__AI_init_flag != TRUE) { + OSRegisterVersion(__AIVersion); + bound_32KHz = OSNanosecondsToTicks(31524); + bound_48KHz = OSNanosecondsToTicks(42024); + min_wait = OSNanosecondsToTicks(42000); + max_wait = OSNanosecondsToTicks(63000); + buffer = OSNanosecondsToTicks(3000); + AISetStreamVolRight(0); + AISetStreamVolLeft(0); + AISetStreamTrigger(0); + AIResetStreamSampleCount(); + __AI_set_stream_sample_rate(AI_SAMPLERATE_48KHZ); + AISetDSPSampleRate(AI_SAMPLERATE_32KHZ); +#if DEBUG + OSReport("AIInit(): DSP is 32KHz\n"); +#endif + __AIS_Callback = NULL; + __AID_Callback = NULL; + __CallbackStack = stack; + if (stack) { + ASSERTMSGLINE(0x444, ((u32)stack & 7) != 0, + "AIInit: stack must be 8-byte aligned"); + } + __OSSetInterruptHandler(5, __AIDHandler); + __OSUnmaskInterrupts(0x04000000); + __OSSetInterruptHandler(8, __AISHandler); + __OSUnmaskInterrupts(0x800000); + __AI_init_flag = TRUE; + } +} + +void AIReset(void) { __AI_init_flag = FALSE; } + +static void __AISHandler(__OSInterrupt interrupt, OSContext* context) +{ + OSContext exceptionContext; + + __AIRegs[0] |= 8; + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + if (__AIS_Callback) { + __AIS_Callback(__AIRegs[2]); + } + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +static void __AIDHandler(__OSInterrupt interrupt, OSContext* context) +{ + OSContext exceptionContext; + u16 tmp; + + tmp = __DSPRegs[5]; + tmp = (tmp & ~0xA0) | 8; + __DSPRegs[5] = tmp; + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + if (__AID_Callback && !__AID_Active) { + __AID_Active = TRUE; + if (__CallbackStack) { + __AICallbackStackSwitch(__AID_Callback); + } else { + __AID_Callback(); + } + __AID_Active = FALSE; + } + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +static asm void __AICallbackStackSwitch(register void* cb) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + mflr r0 + stw r0, 0x4(r1) + stwu r1, -0x18(r1) + stw r31, 0x14(r1) + mr r31, r3 + lis r5, __OldStack@ha + addi r5, r5, __OldStack@l + stw r1, 0x0(r5) + lis r5, __CallbackStack@ha + addi r5, r5, __CallbackStack@l + lwz r1, 0x0(r5) + subi r1, r1, 0x8 + mtlr r31 + blrl + lis r5, __OldStack@ha + addi r5, r5, __OldStack@l + lwz r1, 0x0(r5) + lwz r0, 0x1c(r1) + lwz r31, 0x14(r1) + addi r1, r1, 0x18 + mtlr r0 + blr +#endif // clang-format on +} + +void __AI_SRC_INIT(void) +{ + OSTime rising_32khz = 0; + OSTime rising_48khz = 0; + OSTime diff = 0; + OSTime t1 = 0; + OSTime temp; + u32 temp0; + u32 temp1; + u32 done = 0; + u32 volume = 0; + u32 Init_Cnt = 0; + u32 walking = 0; + + walking = 0; + Init_Cnt = 0; + temp = 0; + +#if DEBUG + profile.t_start = OSGetTime(); +#endif + + while (!done) { + SET_REG_FIELD(0, __AIRegs[0], 1, 5, 1); + SET_REG_FIELD(0, __AIRegs[0], 1, 1, 0); + SET_REG_FIELD(0, __AIRegs[0], 1, 0, AI_STREAM_START); + temp0 = __AIRegs[2]; + while (temp0 == __AIRegs[2]) { } + rising_32khz = OSGetTime(); + SET_REG_FIELD(0, __AIRegs[0], 1, 1, 1); + SET_REG_FIELD(0, __AIRegs[0], 1, 0, AI_STREAM_START); + temp1 = __AIRegs[2]; + while (temp1 == __AIRegs[2]) { } + rising_48khz = OSGetTime(); + diff = rising_48khz - rising_32khz; + SET_REG_FIELD(0, __AIRegs[0], 1, 1, 0); + SET_REG_FIELD(0, __AIRegs[0], 1, 0, AI_STREAM_STOP); + if (diff < bound_32KHz - buffer) { + temp = min_wait; + done = 1; + Init_Cnt++; + } else if (diff >= bound_32KHz + buffer + && diff < bound_48KHz - buffer) { + temp = max_wait; + done = 1; + Init_Cnt++; + } else { + done = 0; + walking = 1; + Init_Cnt++; + } + } + while (rising_48khz + temp > OSGetTime()) { } +#if DEBUG + profile.t_end = OSGetTime(); +#endif +} diff --git a/src/static/GAEJ01_01/dolphin/amcstubs/AmcExi2Stubs.c b/src/static/GAEJ01_01/dolphin/amcstubs/AmcExi2Stubs.c new file mode 100644 index 00000000..600e63b2 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/amcstubs/AmcExi2Stubs.c @@ -0,0 +1,29 @@ +#include "types.h" + +void EXI2_Init(void){ + +} +void EXI2_EnableInterrupts(void){ + +} +u8 EXI2_Poll(void){ + return 0; +} + +u8 EXI2_ReadN(void){ + return 0; +} + +u8 EXI2_WriteN(void){ + return 0; +} + +void EXI2_Reserve(void){ + +} +void EXI2_Unreserve(void){ + +} +u8 AMC_IsStub(void){ + return 1; +} \ No newline at end of file diff --git a/src/static/GAEJ01_01/dolphin/ar/__ar.h b/src/static/GAEJ01_01/dolphin/ar/__ar.h new file mode 100644 index 00000000..f7dd6a18 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/ar/__ar.h @@ -0,0 +1,13 @@ +#ifndef _DOLPHIN_AR_INTERNAL_H_ +#define _DOLPHIN_AR_INTERNAL_H_ + +#include + +void __ARQPopTaskQueueHi(void); +void __ARQServiceQueueLo(void); +void __ARQCallbackHack(u32 pointerToARQRequest); +void __ARQInterruptServiceRoutine(void); +void __ARQInitTempQueue(void); +void __ARQPushTempQueue(struct ARQRequest* task); + +#endif // _DOLPHIN_AR_INTERNAL_H_ diff --git a/src/static/GAEJ01_01/dolphin/ar/ar.c b/src/static/GAEJ01_01/dolphin/ar/ar.c new file mode 100644 index 00000000..5ec37314 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/ar/ar.c @@ -0,0 +1,386 @@ +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/ar/__ar.h" + +void OSRegisterVersion(const char* id); + +char* __ARVersion = "<< Dolphin SDK - AR\trelease build: Nov 26 2003 05:19:42 (0x2301) >>"; + +static void (*__AR_Callback)(); +static u32 __AR_Size; +static u32 __AR_InternalSize; +static u32 __AR_ExpansionSize; + +static u32 __AR_StackPointer; +static u32 __AR_FreeBlocks; +static u32* __AR_BlockLength; + +static volatile BOOL __AR_init_flag = FALSE; + +static void __ARHandler(__OSInterrupt interrupt, OSContext* context); +static void __ARChecksize(void); +static void __ARClearArea(u32 start_addr, u32 length); + +ARQCallback ARRegisterDMACallback(ARQCallback callback) +{ + ARQCallback oldCb; + BOOL enabled; + oldCb = __AR_Callback; + enabled = OSDisableInterrupts(); + __AR_Callback = callback; + OSRestoreInterrupts(enabled); + return oldCb; +} + +u32 ARGetDMAStatus() +{ + BOOL enabled; + u32 val; + enabled = OSDisableInterrupts(); + val = __DSPRegs[DSP_CONTROL_STATUS] & 0x0200; + OSRestoreInterrupts(enabled); + return val; +} + +void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length) +{ + BOOL enabled; + + enabled = OSDisableInterrupts(); + + // Set main mem address + __DSPRegs[DSP_ARAM_DMA_MM_HI] = (u16)(__DSPRegs[DSP_ARAM_DMA_MM_HI] & ~0x3ff) | (u16)(mainmem_addr >> 16); + __DSPRegs[DSP_ARAM_DMA_MM_LO] = (u16)(__DSPRegs[DSP_ARAM_DMA_MM_LO] & ~0xffe0) | (u16)(mainmem_addr & 0xffff); + + // Set ARAM address + __DSPRegs[DSP_ARAM_DMA_ARAM_HI] = (u16)(__DSPRegs[DSP_ARAM_DMA_ARAM_HI] & ~0x3ff) | (u16)(aram_addr >> 16); + __DSPRegs[DSP_ARAM_DMA_ARAM_LO] = (u16)(__DSPRegs[DSP_ARAM_DMA_ARAM_LO] & ~0xffe0) | (u16)(aram_addr & 0xffff); + + // Set DMA buffer size + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_HI] & ~0x8000) | (type << 15)); + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)(__DSPRegs[DSP_ARAM_DMA_SIZE_HI] & ~0x3ff) | (u16)(length >> 16); + __DSPRegs[DSP_ARAM_DMA_SIZE_LO] = (u16)(__DSPRegs[DSP_ARAM_DMA_SIZE_LO] & ~0xffe0) | (u16)(length & 0xffff); + + OSRestoreInterrupts(enabled); +} + +u32 ARAlloc(u32 length) +{ + u32 oldStackPtr; + BOOL enabled; + + enabled = OSDisableInterrupts(); + oldStackPtr = __AR_StackPointer; + __AR_StackPointer += length; + *__AR_BlockLength = length; + __AR_BlockLength++; + __AR_FreeBlocks--; + OSRestoreInterrupts(enabled); + + return oldStackPtr; +} + +u32 ARInit(u32* stack_index_addr, u32 num_entries) +{ + BOOL old; + u16 refresh; + + if (__AR_init_flag == TRUE) { + return __AR_ARAM_USR_BASE_ADDR; + } + + OSRegisterVersion(__ARVersion); + + old = OSDisableInterrupts(); + + __AR_Callback = NULL; + + __OSSetInterruptHandler(__OS_INTERRUPT_DSP_ARAM, __ARHandler); + __OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_ARAM); + + __AR_StackPointer = __AR_ARAM_USR_BASE_ADDR; + __AR_FreeBlocks = num_entries; + __AR_BlockLength = stack_index_addr; + + refresh = (u16)(__DSPRegs[DSP_ARAM_REFRESH] & 0xFF); + + __DSPRegs[DSP_ARAM_REFRESH] = (u16)((__DSPRegs[DSP_ARAM_REFRESH] & ~0xFF) | (refresh & 0xFF)); + + __ARChecksize(); + + __AR_init_flag = TRUE; + + OSRestoreInterrupts(old); + + return __AR_StackPointer; +} + +u32 ARGetBaseAddress() +{ + return __AR_ARAM_USR_BASE_ADDR; +} + +u32 ARGetSize() +{ + return __AR_Size; +} + +void __ARHandler(__OSInterrupt interrupt, OSContext* context) +{ + OSContext exceptionContext; + u16 tmp; + + tmp = __DSPRegs[DSP_CONTROL_STATUS]; + tmp = (u16)((tmp & ~(0x80 | 0x8)) | 0x20); + __DSPRegs[DSP_CONTROL_STATUS] = tmp; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + + if (__AR_Callback) { + (*__AR_Callback)(); + } + + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +void __ARClearInterrupt() +{ + u16 tmp; + tmp = __DSPRegs[DSP_CONTROL_STATUS]; + tmp = (u16)((tmp & ~(0x80 | 0x8)) | 0x20); + __DSPRegs[DSP_CONTROL_STATUS] = tmp; +} + +u16 __ARGetInterruptStatus() +{ + return ((u16)(__DSPRegs[DSP_CONTROL_STATUS] & 0x20)); +} + +static void __ARWaitForDMA() +{ + while (__DSPRegs[DSP_CONTROL_STATUS] & 0x0200) { } +} + +static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length) +{ + // Main mem address + __DSPRegs[DSP_ARAM_DMA_MM_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_MM_HI] & ~0x03ff) | (u16)(mmem_addr >> 16)); + __DSPRegs[DSP_ARAM_DMA_MM_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_MM_LO] & ~0xffe0) | (u16)(mmem_addr & 0xffff)); + + // ARAM address + __DSPRegs[DSP_ARAM_DMA_ARAM_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_ARAM_HI] & ~0x03ff) | (u16)(aram_addr >> 16)); + __DSPRegs[DSP_ARAM_DMA_ARAM_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_ARAM_LO] & ~0xffe0) | (u16)(aram_addr & 0xffff)); + + // DMA buffer size + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)(__DSPRegs[DSP_ARAM_DMA_SIZE_HI] & ~0x8000); + + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_HI] & ~0x03ff) | (u16)(length >> 16)); + __DSPRegs[DSP_ARAM_DMA_SIZE_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_LO] & ~0xffe0) | (u16)(length & 0xffff)); + + __ARWaitForDMA(); + + __ARClearInterrupt(); +} + +static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length) +{ + // Main mem address + __DSPRegs[DSP_ARAM_DMA_MM_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_MM_HI] & ~0x03ff) | (u16)(mmem_addr >> 16)); + __DSPRegs[DSP_ARAM_DMA_MM_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_MM_LO] & ~0xffe0) | (u16)(mmem_addr & 0xffff)); + + // ARAM address + __DSPRegs[DSP_ARAM_DMA_ARAM_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_ARAM_HI] & ~0x03ff) | (u16)(aram_addr >> 16)); + __DSPRegs[DSP_ARAM_DMA_ARAM_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_ARAM_LO] & ~0xffe0) | (u16)(aram_addr & 0xffff)); + + // DMA buffer size + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)(__DSPRegs[DSP_ARAM_DMA_SIZE_HI] | 0x8000); + + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_HI] & ~0x03ff) | (u16)(length >> 16)); + __DSPRegs[DSP_ARAM_DMA_SIZE_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_LO] & ~0xffe0) | (u16)(length & 0xffff)); + + __ARWaitForDMA(); + + __ARClearInterrupt(); +} + +void __ARChecksize() +{ + u8 test_data_pad[0x20 + 31]; + u8 dummy_data_pad[0x20 + 31]; + u8 buffer_pad[0x20 + 31]; + + u8 save_pad_1[0x20 + 31]; + u8 save_pad_2[0x20 + 31]; + u8 save_pad_3[0x20 + 31]; + u8 save_pad_4[0x20 + 31]; + u8 save_pad_5[0x20 + 31]; + + u32* test_data; + u32* dummy_data; + u32* buffer; + u32* save1; + u32* save2; + u32* save3; + u32* save4; + u32* save5; + + u16 ARAM_mode = 0; + u32 ARAM_size = 0; + + u32 i; + + while (!(__DSPRegs[DSP_ARAM_MODE] & 1)) { } + + ARAM_mode = 3; + ARAM_size = __AR_InternalSize = 0x1000000; + __DSPRegs[DSP_ARAM_SIZE] = (u16)((__DSPRegs[DSP_ARAM_SIZE] & ~(0x7 | 0x38)) | 0x20 | 2 | 1); + + test_data = (u32*)(OSRoundUp32B((u32)(test_data_pad))); + dummy_data = (u32*)(OSRoundUp32B((u32)(dummy_data_pad))); + buffer = (u32*)(OSRoundUp32B((u32)(buffer_pad))); + + save1 = (u32*)(OSRoundUp32B((u32)(save_pad_1))); + save2 = (u32*)(OSRoundUp32B((u32)(save_pad_2))); + save3 = (u32*)(OSRoundUp32B((u32)(save_pad_3))); + save4 = (u32*)(OSRoundUp32B((u32)(save_pad_4))); + save5 = (u32*)(OSRoundUp32B((u32)(save_pad_5))); + + for (i = 0; i < 8; i++) { + *(test_data + i) = 0xDEADBEEF; + *(dummy_data + i) = 0xBAD0BAD0; + } + + DCFlushRange((void*)test_data, 0x20); + DCFlushRange((void*)dummy_data, 0x20); + + __AR_ExpansionSize = 0; + + DCInvalidateRange((void*)save1, 0x20); + __ARReadDMA((u32)save1, ARAM_size + 0, 0x20); + PPCSync(); + + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0000000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + + DCInvalidateRange((void*)save2, 0x20); + __ARReadDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + PPCSync(); + + DCInvalidateRange((void*)save3, 0x20); + __ARReadDMA((u32)save3, ARAM_size + 0x1000000, 0x20); + PPCSync(); + + DCInvalidateRange((void*)save4, 0x20); + __ARReadDMA((u32)save4, ARAM_size + 0x0000200, 0x20); + PPCSync(); + + DCInvalidateRange((void*)save5, 0x20); + __ARReadDMA((u32)save5, ARAM_size + 0x0400000, 0x20); + PPCSync(); + + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x0200000, 0x20); + + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0200000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + + ARAM_mode |= 0 << 1; + ARAM_size += 0x0200000; + __AR_ExpansionSize = 0x0200000; + } else { + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x1000000, 0x20); + + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x1000000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + __ARWriteDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + + ARAM_mode |= 4 << 1; + ARAM_size += 0x0400000; + __AR_ExpansionSize = 0x0400000; + } else { + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x0000200, 0x20); + + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0000200, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + __ARWriteDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + __ARWriteDMA((u32)save3, ARAM_size + 0x1000000, 0x20); + + ARAM_mode |= 8 << 1; + ARAM_size += 0x0800000; + __AR_ExpansionSize = 0x0800000; + } else { + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x0400000, 0x20); + + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0400000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + __ARWriteDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + __ARWriteDMA((u32)save3, ARAM_size + 0x1000000, 0x20); + __ARWriteDMA((u32)save4, ARAM_size + 0x0000200, 0x20); + + ARAM_mode |= 12 << 1; + ARAM_size += 0x1000000; + __AR_ExpansionSize = 0x1000000; + } else { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + __ARWriteDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + __ARWriteDMA((u32)save3, ARAM_size + 0x1000000, 0x20); + __ARWriteDMA((u32)save4, ARAM_size + 0x0000200, 0x20); + __ARWriteDMA((u32)save5, ARAM_size + 0x0400000, 0x20); + + ARAM_mode |= 16 << 1; + ARAM_size += 0x2000000; + __AR_ExpansionSize = 0x2000000; + } + } + } + } + __DSPRegs[DSP_ARAM_SIZE] = (u16)((__DSPRegs[DSP_ARAM_SIZE] & ~(0x7 | 0x38)) | ARAM_mode); + } + + *(u32*)OSPhysicalToUncached(0x00D0) = ARAM_size; + + __AR_Size = ARAM_size; +} diff --git a/src/static/GAEJ01_01/dolphin/ar/arq.c b/src/static/GAEJ01_01/dolphin/ar/arq.c new file mode 100644 index 00000000..ddf23df9 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/ar/arq.c @@ -0,0 +1,159 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/ar/__ar.h" + +void OSRegisterVersion(const char* id); + +const char* __ARQVersion = "<< Dolphin SDK - ARQ\trelease build: Nov 26 2003 05:19:43 (0x2301) >>"; + +static struct ARQRequest* __ARQRequestQueueHi; +static struct ARQRequest* __ARQRequestTailHi; +static struct ARQRequest* __ARQRequestQueueLo; +static struct ARQRequest* __ARQRequestTailLo; +static struct ARQRequest* __ARQRequestPendingHi; +static struct ARQRequest* __ARQRequestPendingLo; +static ARQCallback __ARQCallbackHi; +static ARQCallback __ARQCallbackLo; +static u32 __ARQChunkSize; +static volatile BOOL __ARQ_init_flag = FALSE; + +inline void __ARQPopTaskQueueHi(void) +{ + if (__ARQRequestQueueHi) { + if (__ARQRequestQueueHi->type == 0) { + ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->source, + __ARQRequestQueueHi->dest, __ARQRequestQueueHi->length); + } else { + ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->dest, + __ARQRequestQueueHi->source, + __ARQRequestQueueHi->length); + } + __ARQCallbackHi = __ARQRequestQueueHi->callback; + __ARQRequestPendingHi = __ARQRequestQueueHi; + __ARQRequestQueueHi = __ARQRequestQueueHi->next; + } +} + +void __ARQServiceQueueLo(void) +{ + if (__ARQRequestPendingLo == 0 && __ARQRequestQueueLo) { + __ARQRequestPendingLo = __ARQRequestQueueLo; + __ARQRequestQueueLo = __ARQRequestQueueLo->next; + } + if (__ARQRequestPendingLo) { + if (__ARQRequestPendingLo->length <= __ARQChunkSize) { + if (__ARQRequestPendingLo->type == 0) { + ARStartDMA( + __ARQRequestPendingLo->type, __ARQRequestPendingLo->source, + __ARQRequestPendingLo->dest, __ARQRequestPendingLo->length); + } else { + ARStartDMA(__ARQRequestPendingLo->type, + __ARQRequestPendingLo->dest, + __ARQRequestPendingLo->source, + __ARQRequestPendingLo->length); + } + __ARQCallbackLo = __ARQRequestPendingLo->callback; + } else if (__ARQRequestPendingLo->type == 0) { + ARStartDMA(__ARQRequestPendingLo->type, + __ARQRequestPendingLo->source, + __ARQRequestPendingLo->dest, __ARQChunkSize); + } else { + ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->dest, + __ARQRequestPendingLo->source, __ARQChunkSize); + } + __ARQRequestPendingLo->length -= __ARQChunkSize; + __ARQRequestPendingLo->source += __ARQChunkSize; + __ARQRequestPendingLo->dest += __ARQChunkSize; + } +} + +void __ARQCallbackHack(u32 unused) { } + +void __ARQInterruptServiceRoutine() +{ + if (__ARQCallbackHi) { + __ARQCallbackHi((u32)__ARQRequestPendingHi); + __ARQRequestPendingHi = NULL; + __ARQCallbackHi = NULL; + } else if (__ARQCallbackLo) { + __ARQCallbackLo((u32)__ARQRequestPendingLo); + __ARQRequestPendingLo = NULL; + __ARQCallbackLo = NULL; + } + __ARQPopTaskQueueHi(); + if (__ARQRequestPendingHi == 0) { + __ARQServiceQueueLo(); + } +} + +void ARQInit(void) +{ + if (__ARQ_init_flag == TRUE) { + return; + } + + OSRegisterVersion(__ARQVersion); + + __ARQRequestQueueHi = __ARQRequestQueueLo = NULL; + __ARQChunkSize = ARQ_CHUNK_SIZE_DEFAULT; + ARRegisterDMACallback(__ARQInterruptServiceRoutine); + __ARQRequestPendingHi = NULL; + __ARQRequestPendingLo = NULL; + __ARQCallbackHi = NULL; + __ARQCallbackLo = NULL; + + __ARQ_init_flag = TRUE; +} + +void ARQPostRequest(struct ARQRequest* request, u32 owner, u32 type, + u32 priority, u32 source, u32 dest, u32 length, + ARQCallback callback) +{ + int level; + + ASSERTLINE(0x1A9, request); + ASSERTLINE(0x1AA, (type == ARQ_TYPE_MRAM_TO_ARAM) + || (type == ARQ_TYPE_ARAM_TO_MRAM)); + ASSERTLINE(0x1AB, (priority == ARQ_PRIORITY_LOW) + || (priority == ARQ_PRIORITY_HIGH)); + ASSERTLINE(0x1AE, (length % ARQ_DMA_ALIGNMENT) == 0); + request->next = NULL; + request->owner = owner; + request->type = type; + request->source = source; + request->dest = dest; + request->length = length; + if (callback) { + request->callback = callback; + } else { + request->callback = __ARQCallbackHack; + } + level = OSDisableInterrupts(); + switch (priority) { + case ARQ_PRIORITY_LOW: + if (__ARQRequestQueueLo) { + __ARQRequestTailLo->next = request; + } else { + __ARQRequestQueueLo = request; + } + __ARQRequestTailLo = request; + break; + case ARQ_PRIORITY_HIGH: + if (__ARQRequestQueueHi) { + __ARQRequestTailHi->next = request; + } else { + __ARQRequestQueueHi = request; + } + __ARQRequestTailHi = request; + break; + } + if ((__ARQRequestPendingHi == 0) && (__ARQRequestPendingLo == 0)) { + __ARQPopTaskQueueHi(); + if (__ARQRequestPendingHi == 0) { + __ARQServiceQueueLo(); + } + } + OSRestoreInterrupts(level); +} diff --git a/src/static/GAEJ01_01/dolphin/base/PPCArch.c b/src/static/GAEJ01_01/dolphin/base/PPCArch.c new file mode 100644 index 00000000..a3cebd6e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/base/PPCArch.c @@ -0,0 +1,160 @@ +#include "dolphin/BASE/ppcarch.h" + +union FpscrUnion { + f64 f; + struct { + u32 fpscr_pad; + u32 fpscr; + } u; +}; + +asm u32 PPCMfmsr(void){ + nofralloc + mfmsr r3 + blr +} + +asm void PPCMtmsr(register u32 value){ + nofralloc + mtmsr value + blr +} + +asm u32 PPCMfhid0(void){ + nofralloc + mfspr r3, 0x3f0 + blr +} + +asm void PPCMthid0(register u32 value) { + nofralloc + mtspr 0x3f0, value + blr +} + +asm u32 PPCMfl2cr(void) { + nofralloc + mfspr r3, 0x3f9 + blr +} + +asm void PPCMtl2cr(register u32 value) { + nofralloc + mtspr 0x3f9, value + blr +} +asm void PPCMtdec(register u32 value) { + nofralloc + mtspr 0x16, value + blr +} + +asm void PPCSync(void){ + nofralloc + sc + blr +} + +asm void PPCHalt(void){ + nofralloc + sync + +loop: + nop + li r3, 0 + nop + b loop +} + +asm void PPCMtmmcr0(register u32 newMmcr0){ + nofralloc + mtspr 952, newMmcr0 + blr +} + +asm void PPCMtmmcr1(register u32 newMmcr1){ + nofralloc + mtspr 956, newMmcr1 + blr +} + +asm void PPCMtpmc1(register u32 newPmc1){ + nofralloc + mtspr 953, newPmc1 + blr +} + +asm void PPCMtpmc2(register u32 newPmc2){ + nofralloc + mtspr 954, newPmc2 + blr +} + +asm void PPCMtpmc3(register u32 newPmc3){ + nofralloc + mtspr 957, newPmc3 + blr +} + +asm void PPCMtpmc4(register u32 newPmc4){ + nofralloc + mtspr 958, newPmc4 + blr +} + +u32 PPCMffpscr(void){ + union FpscrUnion m; + + asm { + mffs fp31 + stfd fp31, m.f; + } + + return m.u.fpscr; +} + +void PPCMtfpscr(register u32 newFPSCR){ + union FpscrUnion m; + + asm { + li r4, 0 + stw r4, m.u.fpscr_pad; + stw newFPSCR, m.u.fpscr + lfd fp31, m.f + mtfsf 0xff, fp31 + } +} +asm u32 PPCMfhid2(void){ + nofralloc + mfspr r3, 0x398 + blr +} + +asm void PPCMthid2(u32 register value){ + nofralloc + mtspr 0x398, value + blr +} +asm u32 PPCMfwpar(void){ + nofralloc + sync + mfspr r3, 0x399 + blr +} + +asm void PPCMtwpar(u32 register value){ + nofralloc + mtspr 0x399, value + blr +} + +void PPCDisableSpeculation(void) { + PPCMthid0(PPCMfhid0() | (1 << (31 - 22))); +} + +asm void PPCSetFpNonIEEEMode(void){ + nofralloc + mtfsb1 0x1D + blr +} + \ No newline at end of file diff --git a/src/static/GAEJ01_01/dolphin/card/CARDBios.c b/src/static/GAEJ01_01/dolphin/card/CARDBios.c new file mode 100644 index 00000000..4fd972f8 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDBios.c @@ -0,0 +1,830 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +const char* __CARDVersion = "<< Dolphin SDK - CARD release build: Apr 17 2003 12:34:19 (0x2301) >>"; + +struct CARDControl __CARDBlock[2]; + +DVDDiskID __CARDDiskNone; + +static u16 __CARDEncode; + +void OSRegisterVersion(const char* id); + +// functions +static void TimeoutHandler(OSAlarm *alarm, OSContext *context); +static void SetupTimeoutAlarm(CARDControl *card); +static s32 Retry(s32 chan); +static void UnlockedCallback(s32 chan, s32 result); +static BOOL OnReset(BOOL f); + +static OSResetFunctionInfo ResetFunctionInfo = {OnReset, 127}; + +void __CARDDefaultApiCallback(s32 chan, s32 result) {} + +void __CARDSyncCallback(s32 chan, s32 result) { + struct CARDControl * card; + + card = &__CARDBlock[chan]; + OSWakeupThread(&card->threadQueue); +} + +void __CARDExtHandler(s32 chan, OSContext *context) { + CARDControl *card; + CARDCallback callback; + + ASSERTLINE(200, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (card->attached) + { + ASSERTLINE(207, card->txCallback == 0); + card->attached = FALSE; + EXISetExiCallback(chan, 0); + OSCancelAlarm(&card->alarm); + callback = card->exiCallback; + + if (callback) + { + card->exiCallback = 0; + callback(chan, CARD_RESULT_NOCARD); + } + + if (card->result != CARD_RESULT_BUSY) { + card->result = CARD_RESULT_NOCARD; + } + + callback = card->extCallback; + if (callback && CARD_MAX_MOUNT_STEP <= card->mountStep) + { + card->extCallback = 0; + callback(chan, CARD_RESULT_NOCARD); + } + } +} + +void __CARDExiHandler(s32 chan, OSContext *context) { + CARDControl *card; + CARDCallback callback; + u8 status; + s32 result; + + ASSERTLINE(251, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + + OSCancelAlarm(&card->alarm); + + if (!card->attached) + { + return; + } + + if (!EXILock(chan, 0, 0)) + { + result = CARD_RESULT_FATAL_ERROR; + goto fatal; + } + + if ((result = __CARDReadStatus(chan, &status)) < 0 || (result = __CARDClearStatus(chan)) < 0) + { + goto error; + } + + if ((result = (status & 0x18) ? CARD_RESULT_IOERROR : CARD_RESULT_READY) == + CARD_RESULT_IOERROR && + --card->retry > 0) + { + result = Retry(chan); + if (result >= 0) + { + return; + } + goto fatal; + } + +error: + EXIUnlock(chan); + +fatal: + callback = card->exiCallback; + if (callback) + { + card->exiCallback = 0; + callback(chan, result); + } +} + +void __CARDTxHandler(s32 chan, OSContext *context) { + CARDControl *card; + CARDCallback callback; + int err; + + ASSERTLINE(333, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + err = !EXIDeselect(chan); + !EXIUnlock(chan); + callback = card->txCallback; + if (callback) + { + card->txCallback = NULL; + callback(chan, !err && (EXIProbe(chan)) ? CARD_RESULT_READY : CARD_RESULT_NOCARD); + } +} + +void __CARDUnlockedHandler(s32 chan, OSContext *context) { + CARDControl *card; + CARDCallback callback; + + ASSERTLINE(380, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + callback = card->unlockCallback; + if (callback) + { + card->unlockCallback = 0; + callback(chan, EXIProbe(chan) ? CARD_RESULT_UNLOCKED : CARD_RESULT_NOCARD); + } +} + +s32 __CARDEnableInterrupt(s32 chan, BOOL enable) { + BOOL err; + u32 cmd; + + ASSERTLINE(399, 0 <= chan && chan < 2); + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = enable ? 0x81010000 : 0x81000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 2, 1, NULL); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +s32 __CARDReadStatus(s32 chan, u8 *status) { + BOOL err; + u32 cmd; + + ASSERTLINE(418, 0 <= chan && chan < 2); + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = 0x83000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 2, 1, NULL); + err |= !EXISync(chan); + err |= !EXIImm(chan, status, 1, 0, NULL); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +s32 __CARDClearStatus(s32 chan) { + BOOL err; + u32 cmd; + + ASSERTLINE(439, 0 <= chan && chan < 2); + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = 0x89000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 1, 1, 0); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +long __CARDSleep(long chan) { + int err; + unsigned long cmd; + + ASSERTLINE(458, 0 <= chan && chan < 2); + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + cmd = 0x88000000; + err = 0; + err |= !EXIImm(chan, &cmd, 1, 1, 0); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + + if(err) { + return CARD_RESULT_NOCARD; + } + return CARD_RESULT_READY; +} + +long __CARDWakeup(long chan) { + int err; + unsigned long cmd; + + ASSERTLINE(477, 0 <= chan && chan < 2); + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + cmd = 0x87000000; + err = 0; + err |= !EXIImm(chan, &cmd, 1, 1, 0); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + + if(err) { + return CARD_RESULT_NOCARD; + } + return CARD_RESULT_READY; +} + +static void TimeoutHandler(OSAlarm *alarm, OSContext *context) { + s32 chan; + CARDControl *card; + CARDCallback callback; + for (chan = 0; chan < 2; ++chan) + { + card = &__CARDBlock[chan]; + if (alarm == &card->alarm) + { + break; + } + } + + ASSERTLINE(525, 0 <= chan && chan < 2); + + if (card->attached) { + EXISetExiCallback(chan, NULL); + callback = card->exiCallback; + if (callback) + { + card->exiCallback = 0; + callback(chan, CARD_RESULT_IOERROR); + } + } +} + +static void SetupTimeoutAlarm(CARDControl *card) { + OSCancelAlarm(&card->alarm); + switch (card->cmd[0]) + { + case 0xF2: + OSSetAlarm(&card->alarm, OSMillisecondsToTicks(100), + TimeoutHandler); + break; + case 0xF3: + break; + case 0xF4: + case 0xF1: + OSSetAlarm(&card->alarm, OSSecondsToTicks((OSTime)2) * (card->sectorSize / (int)CARD_SYSTEM_BLOCK_SIZE), + TimeoutHandler); + break; + } +} + +static s32 Retry(s32 chan) { + CARDControl *card; + + ASSERTLINE(593, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!EXISelect(chan, 0, 4)) + { + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + SetupTimeoutAlarm(card); + + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1)) + { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + if (card->cmd[0] == 0x52 && + !EXIImmEx(chan, (u8 *)card->workArea + sizeof(CARDID), card->latency, 1)) + { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + if (card->mode == 0xffffffff) + { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_READY; + } + + if (!EXIDma(chan, card->buffer, (s32)((card->cmd[0] == 0x52) ? 512 : 128), card->mode, + __CARDTxHandler)) + { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + return CARD_RESULT_READY; +} + +static void UnlockedCallback(s32 chan, s32 result) { + CARDCallback callback; + CARDControl *card; + + ASSERTLINE(657, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (result >= 0) + { + card->unlockCallback = UnlockedCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) + { + result = CARD_RESULT_READY; + } + else + { + card->unlockCallback = 0; + result = Retry(chan); + } + } + + if (result < 0) + { + switch (card->cmd[0]) + { + case 0x52: + callback = card->txCallback; + if (callback) + { + card->txCallback = NULL; + callback(chan, result); + } + + break; + case 0xF2: + case 0xF4: + case 0xF1: + callback = card->exiCallback; + if (callback) + { + card->exiCallback = 0; + callback(chan, result); + } + break; + } + } +} + +static s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallback) { + BOOL enabled; + CARDControl *card; + s32 result; + + enabled = OSDisableInterrupts(); + ASSERTLINE(723, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!card->attached) + { + result = CARD_RESULT_NOCARD; + } + else + { + + if (txCallback) + { + card->txCallback = txCallback; + } + if (exiCallback) + { + card->exiCallback = exiCallback; + } + card->unlockCallback = UnlockedCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) + { + result = CARD_RESULT_BUSY; + } + else + { + card->unlockCallback = 0; + + if (!EXISelect(chan, 0, 4)) + { + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } + else + { + SetupTimeoutAlarm(card); + result = CARD_RESULT_READY; + } + } + } + + OSRestoreInterrupts(enabled); + return result; +} + +#define AD1(x) ((u8)(((x) >> 17) & 0x7f)) +#define AD1EX(x) ((u8)(AD1(x) | 0x80)); +#define AD2(x) ((u8)(((x) >> 9) & 0xff)) +#define AD3(x) ((u8)(((x) >> 7) & 0x03)) +#define BA(x) ((u8)((x)&0x7f)) + +s32 __CARDReadSegment(s32 chan, CARDCallback callback) { + CARDControl *card; + s32 result; + + ASSERTLINE(785, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + ASSERTLINE(787, card->addr % CARD_SEG_SIZE == 0); + ASSERTLINE(788, card->addr < (u32) card->size * 1024 * 1024 / 8); + card->cmd[0] = 0x52; + card->cmd[1] = AD1(card->addr); + card->cmd[2] = AD2(card->addr); + card->cmd[3] = AD3(card->addr); + card->cmd[4] = BA(card->addr); + card->cmdlen = 5; + card->mode = 0; + card->retry = 0; + + result = __CARDStart(chan, callback, 0); + if (result == CARD_RESULT_BUSY) + { + result = CARD_RESULT_READY; + } + else if (result >= 0) + { + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1) || + !EXIImmEx(chan, (u8 *)card->workArea + sizeof(CARDID), card->latency, + 1) || // XXX use DMA if possible + !EXIDma(chan, card->buffer, 512, card->mode, __CARDTxHandler)) + { + card->txCallback = NULL; + EXIDeselect(chan); + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } else { + result = CARD_RESULT_READY; + } + } + + return result; +} + +s32 __CARDWritePage(s32 chan, CARDCallback callback) { + CARDControl *card; + s32 result; + + ASSERTLINE(842, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + ASSERTLINE(844, card->addr % CARD_PAGE_SIZE == 0); + ASSERTLINE(845, card->addr < (u32) card->size * 1024 * 1024 / 8); + card->cmd[0] = 0xF2; + card->cmd[1] = AD1(card->addr); + card->cmd[2] = AD2(card->addr); + card->cmd[3] = AD3(card->addr); + card->cmd[4] = BA(card->addr); + card->cmdlen = 5; + card->mode = 1; + card->retry = 3; + + result = __CARDStart(chan, 0, callback); + if (result == CARD_RESULT_BUSY) + { + result = CARD_RESULT_READY; + } + else if (result >= 0) + { + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1) || + !EXIDma(chan, card->buffer, 128, card->mode, __CARDTxHandler)) + { + card->exiCallback = 0; + EXIDeselect(chan); + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } + else + { + result = CARD_RESULT_READY; + } + } + + return result; +} + +long __CARDErase(long chan, void (* callback)(long, long)) { + struct CARDControl * card; + s32 result; + + ASSERTLINE(894, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + card->cmd[0] = 0xF4; + card->cmd[1] = 0; + card->cmd[2] = 0; + card->cmdlen = 3; + card->mode = -1; + card->retry = 3; + result = __CARDStart(chan, 0, callback); + if (result == CARD_RESULT_BUSY) + { + result = CARD_RESULT_READY; + } + else if (result >= 0) + { + if (EXIImmEx(chan, &card->cmd, card->cmdlen, 1) == 0) + { + result = CARD_RESULT_NOCARD; + card->exiCallback = NULL; + } + else + { + result = CARD_RESULT_READY; + } + EXIDeselect(chan); + EXIUnlock(chan); + } + + return result; +} + +s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback) { + CARDControl *card; + s32 result; + + ASSERTLINE(942, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + ASSERTLINE(944, addr % card->sectorSize == 0); + ASSERTLINE(945, addr < (u32) card->size * 1024 * 1024 / 8); + card->cmd[0] = 0xF1; + card->cmd[1] = AD1(addr); + card->cmd[2] = AD2(addr); + card->cmdlen = 3; + card->mode = -1; + card->retry = 3; + + result = __CARDStart(chan, 0, callback); + + if (result == CARD_RESULT_BUSY) + { + result = CARD_RESULT_READY; + } + else if (result >= 0) + { + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1)) + { + result = CARD_RESULT_NOCARD; + card->exiCallback = NULL; + } else { + result = CARD_RESULT_READY; + } + + EXIDeselect(chan); + EXIUnlock(chan); + } + return result; +} + +void CARDInit(void) { + int chan; + + if (__CARDBlock[0].diskID && __CARDBlock[1].diskID) { + return; + } + + __CARDEncode = OSGetFontEncode(); + + OSRegisterVersion(__CARDVersion); + + DSPInit(); + OSInitAlarm(); + + for (chan = 0; chan < 2; ++chan) + { + CARDControl *card = &__CARDBlock[chan]; + + card->result = CARD_RESULT_NOCARD; + OSInitThreadQueue(&card->threadQueue); + OSCreateAlarm(&card->alarm); + } + __CARDSetDiskID((void*)OSPhysicalToCached(0)); + + OSRegisterResetFunction(&ResetFunctionInfo); +} + +u16 __CARDGetFontEncode(void) { + return __CARDEncode; +} + +void __CARDSetDiskID(DVDDiskID* diskID) { + __CARDBlock[0].diskID = diskID ? diskID : &__CARDDiskNone; + __CARDBlock[1].diskID = diskID ? diskID : &__CARDDiskNone; +} + +const DVDDiskID* CARDGetDiskID(s32 chan) { + ASSERTLINE(1047, 0 <= chan && chan < 2); + return __CARDBlock[chan].diskID; +} + +s32 CARDSetDiskID(s32 chan, const DVDDiskID* diskID) { + BOOL enabled; + CARDControl* card; + + card = &__CARDBlock[chan]; + ASSERTLINE(1068, 0 <= chan && chan < 2); + enabled = OSDisableInterrupts(); + + if (card->result == CARD_RESULT_BUSY) { + return CARD_RESULT_BUSY; + } + + card->diskID = diskID ? diskID : (DVDDiskID*)OSPhysicalToCached(0); + OSRestoreInterrupts(enabled); + return CARD_RESULT_READY; +} + +s32 __CARDGetControlBlock(s32 chan, CARDControl **pcard) { + BOOL enabled; + s32 result; + CARDControl *card; + card = &__CARDBlock[chan]; + + if (chan < 0 || chan >= 2 || !card->diskID) + { + return CARD_RESULT_FATAL_ERROR; + } + + enabled = OSDisableInterrupts(); + if (!card->attached) + { + result = CARD_RESULT_NOCARD; + } + else if (card->result == CARD_RESULT_BUSY) + { + result = CARD_RESULT_BUSY; + } + else + { + card->result = CARD_RESULT_BUSY; + result = CARD_RESULT_READY; + card->apiCallback = NULL; + *pcard = card; + } + OSRestoreInterrupts(enabled); + return result; +} + +s32 __CARDPutControlBlock(CARDControl *card, s32 result) { + BOOL enabled; + + ASSERTLINE(1138, result != CARD_RESULT_BUSY); + + enabled = OSDisableInterrupts(); + if (card->attached) { + card->result = result; + } else if (card->result == CARD_RESULT_BUSY) { + card->result = result; + } + OSRestoreInterrupts(enabled); + return result; +} + +s32 CARDGetResultCode(s32 chan) { + CARDControl *card; + + ASSERTLINE(1171, 0 <= chan && chan < 2); + + if (chan < 0 || chan >= 2) + { + return CARD_RESULT_FATAL_ERROR; + } + card = &__CARDBlock[chan]; + return card->result; +} + +s32 CARDFreeBlocks(s32 chan, s32 *byteNotUsed, s32 *filesNotUsed) { + CARDControl *card; + s32 result; + u16 *fat; + CARDDir *dir; + CARDDir *ent; + u16 fileNo; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + { + return result; + } + + fat = __CARDGetFatBlock(card); + dir = __CARDGetDirBlock(card); + if (fat == 0 || dir == 0) + { + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + if (byteNotUsed) { + *byteNotUsed = (s32)(card->sectorSize * fat[CARD_FAT_FREEBLOCKS]); + } + + if (filesNotUsed) { + *filesNotUsed = 0; + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) + { + ent = &dir[fileNo]; + if (ent->fileName[0] == 0xff) + { + ++*filesNotUsed; + } + } + } + + return __CARDPutControlBlock(card, CARD_RESULT_READY); +} + +long CARDGetEncoding(long chan, unsigned short * encode) { + struct CARDControl * card; + struct CARDID * id; + long result; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + id = card->workArea; + *encode = id->encode; + return __CARDPutControlBlock(card, 0); +} + +long CARDGetMemSize(long chan, unsigned short * size) { + struct CARDControl * card; + long result; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + *size = card->size; + return __CARDPutControlBlock(card, 0); +} + +// @hack +#pragma force_active on +s32 CARDGetSectorSize(s32 chan, u32 *size) { + struct CARDControl *card; + long result; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + { + return result; + } + *size = card->sectorSize; + return __CARDPutControlBlock(card, 0); +} +#pragma force_active reset + +s32 __CARDSync(s32 chan) { + CARDControl *block; + s32 result; + s32 enabled; + + block = &__CARDBlock[chan]; + enabled = OSDisableInterrupts(); + while ((result = CARDGetResultCode(chan)) == -1) + { + OSSleepThread(&block->threadQueue); + } + OSRestoreInterrupts(enabled); + return result; +} + +static BOOL OnReset(BOOL f) { + if (!f) + { + if (CARDUnmount(0) == CARD_RESULT_BUSY || CARDUnmount(1) == CARD_RESULT_BUSY) + { + return FALSE; + } + } + + return TRUE; +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDBlock.c b/src/static/GAEJ01_01/dolphin/card/CARDBlock.c new file mode 100644 index 00000000..80427083 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDBlock.c @@ -0,0 +1,168 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +static void WriteCallback(s32 chan, s32 result); +static void EraseCallback(s32 chan, s32 result); + +void *__CARDGetFatBlock(CARDControl *card) { + ASSERTLINE(0x39, card->currentFat); + return card->currentFat; +} + +static void WriteCallback(s32 chan, s32 result) { + CARDControl *card; + CARDCallback callback; + u16 *fat0; + u16 *fat1; + + card = &__CARDBlock[chan]; + + if (result >= 0) + { + fat0 = (u16 *)((u8 *)card->workArea + 0x6000); + fat1 = (u16 *)((u8 *)card->workArea + 0x8000); + + ASSERTLINE(0x52, card->currentFat); + if (card->currentFat == fat0) + { + card->currentFat = fat1; + memcpy(fat1, fat0, 0x2000); + } + else + { + ASSERTLINE(0x5A, card->currentFat == fat1); + card->currentFat = fat0; + memcpy(fat0, fat1, 0x2000); + } + } + + if (!card->apiCallback) + __CARDPutControlBlock(card, result); + + callback = card->eraseCallback; + if (callback) + { + card->eraseCallback = NULL; + callback(chan, result); + } +} + +static void EraseCallback(s32 chan, s32 result) { + CARDControl *card = &__CARDBlock[chan]; + CARDCallback callback; + u16 *fat; + u32 addr; + + if (result < 0) + goto error; + + fat = __CARDGetFatBlock(card); + addr = ((u32)fat - (u32)card->workArea) / CARD_SYSTEM_BLOCK_SIZE * card->sectorSize; + result = __CARDWrite(chan, addr, CARD_SYSTEM_BLOCK_SIZE, fat, WriteCallback); + if (result < 0) + goto error; + + return; + +error: + if (!card->apiCallback) + __CARDPutControlBlock(card, result); + callback = card->eraseCallback; + if (callback) + { + card->eraseCallback = NULL; + callback(chan, result); + } +} + +s32 __CARDAllocBlock(s32 chan, u32 cBlock, CARDCallback callback) { + CARDControl *card; + u16 *fat; + u16 iBlock; + u16 startBlock; + u16 prevBlock; + u16 count; + + ASSERTLINE(0xB6, 0 < cBlock); + ASSERTLINE(0xB7, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!card->attached) + return CARD_RESULT_NOCARD; + + fat = __CARDGetFatBlock(card); + if (fat[3] < cBlock) + return CARD_RESULT_INSSPACE; + + fat[3] -= cBlock; + startBlock = 0xFFFF; + iBlock = fat[4]; + count = 0; + while (0 < cBlock) + { + if (card->cBlock - 5 < ++count) + return CARD_RESULT_BROKEN; + + iBlock++; + if (!CARDIsValidBlockNo(card, iBlock)) + iBlock = 5; + + if (fat[iBlock] == 0x0000u) + { + if (startBlock == 0xFFFF) + startBlock = iBlock; + else + fat[prevBlock] = iBlock; + prevBlock = iBlock; + fat[iBlock] = 0xFFFF; + --cBlock; + } + } + fat[4] = iBlock; + card->startBlock = startBlock; + + return __CARDUpdateFatBlock(chan, fat, callback); +} + +s32 __CARDFreeBlock(s32 chan, u16 nBlock, CARDCallback callback) { + CARDControl *card; + u16 *fat; + u16 nextBlock; + + ASSERTLINE(0xFD, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!card->attached) + return CARD_RESULT_NOCARD; + + fat = __CARDGetFatBlock(card); + while (nBlock != 0xFFFF) + { + if (!CARDIsValidBlockNo(card, nBlock)) + return CARD_RESULT_BROKEN; + + nextBlock = fat[nBlock]; + fat[nBlock] = 0; + nBlock = nextBlock; + ++fat[3]; + } + + return __CARDUpdateFatBlock(chan, fat, callback); +} + +s32 __CARDUpdateFatBlock(s32 chan, u16 *fat, CARDCallback callback) { + CARDControl *card; + u32 addr; + + ASSERTLINE(0x127, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + ++fat[2]; + __CARDCheckSum(fat + 2, 0x1FFC, fat, fat + 1); + DCStoreRange(fat, 0x2000); + card->eraseCallback = callback; + addr = (((char*)fat - (char*)card->workArea) / 8192u) * card->sectorSize; + return __CARDEraseSector(chan, addr, EraseCallback); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDCheck.c b/src/static/GAEJ01_01/dolphin/card/CARDCheck.c new file mode 100644 index 00000000..0f8eef44 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDCheck.c @@ -0,0 +1,362 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +static s32 VerifyID(CARDControl *card); +static s32 VerifyDir(CARDControl *card, int *outCurrent); +static s32 VerifyFAT(CARDControl *card, int *outCurrent); + +void __CARDCheckSum(void *ptr, int length, u16 *checksum, u16 *checksumInv) { + u16 *p; + int i; + + ASSERTLINE(78, length % sizeof(u16) == 0); + + length /= sizeof(u16); + *checksum = *checksumInv = 0; + for (i = 0, p = ptr; i < length; i++, p++) + { + *checksum += *p; + *checksumInv += ~*p; + } + if (*checksum == 0xffff) + *checksum = 0; + if (*checksumInv == 0xffff) + *checksumInv = 0; +} + +static s32 VerifyID(CARDControl *card) { + CARDID *id; + u16 checksum; + u16 checksumInv; + OSSramEx *sramEx; + OSTime rand; + int i; + + id = card->workArea; + + if (id->deviceID != 0 || id->size != card->size) + return CARD_RESULT_BROKEN; + + __CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &checksum, &checksumInv); + if (id->checkSum != checksum || id->checkSumInv != checksumInv) + return CARD_RESULT_BROKEN; + + rand = *(OSTime *)&id->serial[12]; + sramEx = __OSLockSramEx(); + for (i = 0; i < 12; i++) + { + rand = (rand * 1103515245 + 12345) >> 16; + if (id->serial[i] != (u8)(sramEx->flashID[card - __CARDBlock][i] + rand)) + { + __OSUnlockSramEx(FALSE); + return CARD_RESULT_BROKEN; + } + rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF; + } + + __OSUnlockSramEx(FALSE); + + if (id->encode != __CARDGetFontEncode()) + return CARD_RESULT_ENCODING; + + return CARD_RESULT_READY; +} + +static s32 VerifyDir(CARDControl *card, int *outCurrent) { + CARDDir *dir[2]; + CARDDirCheck *check[2]; + u16 checkSum; + u16 checkSumInv; + int i; + int errors; + int current; + + current = errors = 0; + for (i = 0; i < 2; i++) + { + dir[i] = (CARDDir *)((u8 *)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE); + check[i] = CARDGetDirCheck(dir[i]); + __CARDCheckSum(dir[i], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv); + if (check[i]->checkSum != checkSum || check[i]->checkSumInv != checkSumInv) + { + ++errors; + current = i; + card->currentDir = 0; + } + } + + if (0 == errors) + { + if (card->currentDir == 0) + { + if ((check[0]->checkCode - check[1]->checkCode) < 0) + current = 0; + else + current = 1; + card->currentDir = dir[current]; + memcpy(dir[current], dir[current ^ 1], CARD_SYSTEM_BLOCK_SIZE); + } + else + { + current = (card->currentDir == dir[0]) ? 0 : 1; + } + } + if (outCurrent) + *outCurrent = current; + return errors; +} + +static s32 VerifyFAT(CARDControl *card, int *outCurrent) { + u16 *fat[2]; + u16 *fatp; + u16 nBlock; + u16 cFree; + int i; + u16 checkSum; + u16 checkSumInv; + int errors; + int current; + + current = errors = 0; + for (i = 0; i < 2; i++) + { + fatp = fat[i] = (u16 *)((u8 *)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE); + + __CARDCheckSum(&fatp[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv); + if (fatp[CARD_FAT_CHECKSUM] != checkSum || fatp[CARD_FAT_CHECKSUMINV] != checkSumInv) + { + ++errors; + current = i; + card->currentFat = 0; + continue; + } + + cFree = 0; + for (nBlock = CARD_NUM_SYSTEM_BLOCK; nBlock < card->cBlock; nBlock++) + { + if (fatp[nBlock] == CARD_FAT_AVAIL) + cFree++; + } + if (cFree != fatp[CARD_FAT_FREEBLOCKS]) + { + ++errors; + current = i; + card->currentFat = 0; + continue; + } + } + + if (0 == errors) + { + if (card->currentFat == 0) + { + if (((s16)fat[0][CARD_FAT_CHECKCODE] - (s16)fat[1][CARD_FAT_CHECKCODE]) < 0) + current = 0; + else + current = 1; + card->currentFat = fat[current]; + memcpy(fat[current], fat[current ^ 1], CARD_SYSTEM_BLOCK_SIZE); + } + else + current = (card->currentFat == fat[0]) ? 0 : 1; + } + if (outCurrent) + *outCurrent = current; + return errors; +} + +s32 __CARDVerify(CARDControl *card) { + s32 result; + int errors; + + result = VerifyID(card); + if (result < 0) + return result; + + errors = VerifyDir(card, NULL); + errors += VerifyFAT(card, NULL); + switch (errors) + { + case 0: + ASSERTLINE(297, card->currentDir); + ASSERTLINE(298, card->currentFat); + return CARD_RESULT_READY; + case 1: return CARD_RESULT_BROKEN; + default: return CARD_RESULT_BROKEN; + } +} + +s32 CARDCheckExAsync(s32 chan, s32* xferBytes, CARDCallback callback) { + CARDControl *card; + CARDDir *dir[2]; + u16 *fat[2]; + u16 *map; + s32 result; + int errors; + int currentFat; + int currentDir; + s32 fileNo; + u16 iBlock; + u16 cBlock; + u16 cFree; + BOOL updateFat = FALSE; + BOOL updateDir = FALSE; + BOOL updateOrphan = FALSE; + + ASSERTLINE(342, 0 <= chan && chan < 2); + + if (xferBytes) + { + *xferBytes = 0; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + result = VerifyID(card); + if (result < 0) + return __CARDPutControlBlock(card, result); + + errors = VerifyDir(card, ¤tDir); + errors += VerifyFAT(card, ¤tFat); + if (1 < errors) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + + dir[0] = (CARDDir *)((u8 *)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE); + dir[1] = (CARDDir *)((u8 *)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE); + fat[0] = (u16 *)((u8 *)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE); + fat[1] = (u16 *)((u8 *)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE); + + ASSERTLINE(373, errors == 0 || errors == 1); + + switch (errors) + { + case 0: + ASSERTLINE(377, card->currentDir); + ASSERTLINE(378, card->currentFat); + break; + case 1: + if (!card->currentDir) + { + ASSERTLINE(383, card->currentFat); + card->currentDir = dir[currentDir]; + memcpy(dir[currentDir], dir[currentDir ^ 1], CARD_SYSTEM_BLOCK_SIZE); + updateDir = TRUE; + } + else + { + ASSERTLINE(390, !card->currentFat); + card->currentFat = fat[currentFat]; + memcpy(fat[currentFat], fat[currentFat ^ 1], CARD_SYSTEM_BLOCK_SIZE); + updateFat = TRUE; + } + break; + } + + map = fat[currentFat ^ 1]; + memset(map, 0, CARD_SYSTEM_BLOCK_SIZE); + + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) + { + CARDDir *ent; + + ent = &card->currentDir[fileNo]; + if (ent->gameName[0] == 0xff) + continue; + + for (iBlock = ent->startBlock, cBlock = 0; iBlock != 0xFFFF && cBlock < ent->length; + iBlock = card->currentFat[iBlock], ++cBlock) + { + if (!CARDIsValidBlockNo(card, iBlock) || 1 < ++map[iBlock]) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + if (cBlock != ent->length || iBlock != 0xFFFF) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + cFree = 0; + for (iBlock = CARD_NUM_SYSTEM_BLOCK; iBlock < card->cBlock; iBlock++) + { + u16 nextBlock; + + nextBlock = card->currentFat[iBlock]; + if (map[iBlock] == 0) + { + if (nextBlock != CARD_FAT_AVAIL) + { + card->currentFat[iBlock] = CARD_FAT_AVAIL; + updateOrphan = TRUE; + } + cFree++; + } + else if (!CARDIsValidBlockNo(card, nextBlock) && nextBlock != 0xFFFF) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + if (cFree != card->currentFat[CARD_FAT_FREEBLOCKS]) + { + card->currentFat[CARD_FAT_FREEBLOCKS] = cFree; + updateOrphan = TRUE; + } + if (updateOrphan) + { + __CARDCheckSum(&card->currentFat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), + &card->currentFat[CARD_FAT_CHECKSUM], &card->currentFat[CARD_FAT_CHECKSUMINV]); + } + + memcpy(fat[currentFat ^ 1], fat[currentFat], CARD_SYSTEM_BLOCK_SIZE); + + if (updateDir) + { + if (xferBytes) + { + *xferBytes = CARD_SYSTEM_BLOCK_SIZE; + } + return __CARDUpdateDir(chan, callback); + } + + if (updateFat | updateOrphan) + { + if (xferBytes) + { + *xferBytes = CARD_SYSTEM_BLOCK_SIZE; + } + return __CARDUpdateFatBlock(chan, card->currentFat, callback); + } + + __CARDPutControlBlock(card, CARD_RESULT_READY); + + if (callback) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + (*callback)(chan, CARD_RESULT_READY); + OSRestoreInterrupts(enabled); + } + + return CARD_RESULT_READY; +} + +s32 CARDCheckAsync(s32 chan, CARDCallback callback) { + s32 xferBytes; + + return CARDCheckExAsync(chan, &xferBytes, callback); +} + +s32 CARDCheckEx(s32 chan, s32* xferBytes) { + s32 result = CARDCheckExAsync(chan, xferBytes, __CARDSyncCallback); + + if (result < 0 || xferBytes == 0) { + return result; + } + return __CARDSync(chan); +} + +s32 CARDCheck(s32 chan) { + s32 xferBytes; + + return CARDCheckEx(chan, &xferBytes); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDCreate.c b/src/static/GAEJ01_01/dolphin/card/CARDCreate.c new file mode 100644 index 00000000..b760cd61 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDCreate.c @@ -0,0 +1,124 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +static void CreateCallbackFat(long chan, long result); + +static void CreateCallbackFat(long chan, long result) { + struct CARDControl * card; + struct CARDDir * dir; + struct CARDDir * ent; + void (* callback)(long, long); + + card = &__CARDBlock[chan]; + callback = card->apiCallback; + card->apiCallback = NULL; + + if (result >= 0) { + dir = __CARDGetDirBlock(card); + ent = &dir[card->freeNo]; + memcpy(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)); + memcpy(ent->company, card->diskID->company, sizeof(ent->company)); + ent->permission = 4; + ent->copyTimes = 0; + ASSERTLINE(108, CARDIsValidBlockNo(card, card->startBlock)); + ent->startBlock = (u16) card->startBlock; + ent->bannerFormat = 0; + ent->iconAddr = -1; + ent->iconFormat = 0; + ent->iconSpeed = 0; + ent->commentAddr = -1; + ent->iconSpeed = (ent->iconSpeed & ~CARD_STAT_SPEED_MASK) | CARD_STAT_SPEED_FAST; + card->fileInfo->offset = 0; + card->fileInfo->iBlock = ent->startBlock; + ent->time = OSTicksToSeconds(OSGetTime()); + result = __CARDUpdateDir(chan, callback); + if (result < 0) { + goto after; + } + } else { +after:; + __CARDPutControlBlock(card, result); + if (callback) { + callback(chan, result); + } + } +} + +s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo, + CARDCallback callback) { + CARDControl* card; + CARDDir* dir; + CARDDir* ent; + u16 fileNo; + u16 freeNo; + u16* fat; + s32 result; + + ASSERTLINE(172, 0 <= chan && chan < 2); + ASSERTLINE(173, strlen(fileName) <= CARD_FILENAME_MAX); + + if (strlen(fileName) > (u32)CARD_FILENAME_MAX) { + return CARD_RESULT_NAMETOOLONG; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + + ASSERTLINE(185, 0 < size && (size % card->sectorSize) == 0); + + if (size <= 0 || (size % card->sectorSize) != 0) { + return CARD_RESULT_FATAL_ERROR; + } + + freeNo = (u16)-1; + dir = __CARDGetDirBlock(card); + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) { + ent = &dir[fileNo]; + if (ent->gameName[0] == 0xff) { + if (freeNo == (u16)-1) { + freeNo = fileNo; + } + } else if (memcmp(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)) == 0 && + memcmp(ent->company, card->diskID->company, sizeof(ent->company)) == 0 && + __CARDCompareFileName(ent, fileName)) { + return __CARDPutControlBlock(card, CARD_RESULT_EXIST); + } + } + if (freeNo == (u16)-1) { + return __CARDPutControlBlock(card, CARD_RESULT_NOENT); + } + + fat = __CARDGetFatBlock(card); + if (card->sectorSize * fat[CARD_FAT_FREEBLOCKS] < size) { + return __CARDPutControlBlock(card, CARD_RESULT_INSSPACE); + } + + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + card->freeNo = freeNo; + ent = &dir[freeNo]; + ent->length = (u16)(size / card->sectorSize); + strncpy((char *)ent->fileName, fileName, CARD_FILENAME_MAX); + + card->fileInfo = fileInfo; + fileInfo->chan = chan; + fileInfo->fileNo = freeNo; + + result = __CARDAllocBlock(chan, size / card->sectorSize, CreateCallbackFat); + if (result < 0) { + return __CARDPutControlBlock(card, result); + } + return result; +} + +long CARDCreate(long chan, const char * fileName, unsigned long size, struct CARDFileInfo * fileInfo) { + long result = CARDCreateAsync(chan, fileName, size, fileInfo, __CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDDelete.c b/src/static/GAEJ01_01/dolphin/card/CARDDelete.c new file mode 100644 index 00000000..8c872a8a --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDDelete.c @@ -0,0 +1,106 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +// functions +static void DeleteCallback(s32 chan, s32 result); + +static void DeleteCallback(s32 chan, s32 result) { + CARDControl *card; + CARDCallback callback; + + card = &__CARDBlock[chan]; + callback = card->apiCallback; + card->apiCallback = NULL; + + if (result < 0) + goto error; + + result = __CARDFreeBlock(chan, card->startBlock, callback); + if (result < 0) + goto error; + return; + +error: + __CARDPutControlBlock(card, result); + if (callback) + callback(chan, result); +} + +s32 CARDFastDeleteAsync(s32 chan, s32 fileNo, CARDCallback callback) { + CARDControl *card; + CARDDir *dir; + CARDDir *ent; + s32 result; + + ASSERTLINE(127, 0 <= fileNo && fileNo < CARD_MAX_FILE); + ASSERTLINE(128, 0 <= chan && chan < 2); + + if (fileNo < 0 || CARD_MAX_FILE <= fileNo) + return CARD_RESULT_FATAL_ERROR; + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + result = __CARDAccess(card, ent); + if (result < 0) + return __CARDPutControlBlock(card, result); + if (__CARDIsOpened(card, fileNo)) + return __CARDPutControlBlock(card, CARD_RESULT_BUSY); + card->startBlock = ent->startBlock; + memset(ent, 0xff, sizeof(CARDDir)); + + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + result = __CARDUpdateDir(chan, DeleteCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +long CARDFastDelete(long chan, long fileNo) { + long result = CARDFastDeleteAsync(chan, fileNo, __CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(chan); +} + +s32 CARDDeleteAsync(s32 chan, const char *fileName, CARDCallback callback) { + CARDControl *card; + s32 fileNo; + s32 result; + CARDDir *dir; + CARDDir *ent; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + result = __CARDGetFileNo(card, fileName, &fileNo); + if (result < 0) + return __CARDPutControlBlock(card, result); + if (__CARDIsOpened(card, fileNo)) + return __CARDPutControlBlock(card, CARD_RESULT_BUSY); + + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + card->startBlock = ent->startBlock; + memset(ent, 0xff, sizeof(CARDDir)); + + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + result = __CARDUpdateDir(chan, DeleteCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +s32 CARDDelete(s32 chan, const char *fileName) { + s32 result = CARDDeleteAsync(chan, fileName, __CARDSyncCallback); + + if (result < 0) + return result; + return __CARDSync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDDir.c b/src/static/GAEJ01_01/dolphin/card/CARDDir.c new file mode 100644 index 00000000..88f4346c --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDDir.c @@ -0,0 +1,94 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +static void WriteCallback(s32 chan, s32 result); +static void EraseCallback(s32 chan, s32 result); + +CARDDir *__CARDGetDirBlock(CARDControl* card) { + ASSERTLINE(0x36, card->currentDir); + return card->currentDir; +} + +static void WriteCallback(s32 chan, s32 result) { + CARDControl *card = &__CARDBlock[chan]; + CARDCallback callback; + + if (result >= 0) + { + CARDDir *dir0 = (CARDDir*)((u8*)card->workArea + 0x2000); + CARDDir *dir1 = (CARDDir*)((u8*)card->workArea + 0x4000); + + ASSERTLINE(0x4F, card->currentDir); + + if (card->currentDir == dir0) + { + card->currentDir = dir1; + memcpy(dir1, dir0, 0x2000); + } + else + { + ASSERTLINE(0x57, card->currentDir == dir1); + card->currentDir = dir0; + memcpy(dir0, dir1, 0x2000); + } + } + + if (!card->apiCallback) + __CARDPutControlBlock(card, result); + callback = card->eraseCallback; + if (callback) + { + card->eraseCallback = NULL; + callback(chan, result); + } +} + +static void EraseCallback(s32 chan, s32 result) { + CARDControl *card = &__CARDBlock[chan]; + CARDCallback callback; + CARDDir *dir; + u32 addr; + + if (result >= 0) + { + dir = __CARDGetDirBlock(card); + addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize; + result = __CARDWrite(chan, addr, 0x2000, dir, WriteCallback); + if (result >= 0) + return; + } + + if (!card->apiCallback) + __CARDPutControlBlock(card, result); + callback = card->eraseCallback; + if (callback) + { + card->eraseCallback = NULL; + callback(chan, result); + } +} + +s32 __CARDUpdateDir(s32 chan, CARDCallback callback) { + CARDControl *card; + CARDDirCheck *check; + u32 addr; + CARDDir *dir; + + ASSERTLINE(0xAD, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!card->attached) + return CARD_RESULT_NOCARD; + + dir = __CARDGetDirBlock(card); + check = CARDGetDirCheck(dir); + ++check->checkCode; + __CARDCheckSum(dir, 0x2000 - sizeof(u32), &check->checkSum, &check->checkSumInv); + DCStoreRange(dir, 0x2000); + + card->eraseCallback = callback; + addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize; + return __CARDEraseSector(chan, addr, EraseCallback); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDFormat.c b/src/static/GAEJ01_01/dolphin/card/CARDFormat.c new file mode 100644 index 00000000..325793b5 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDFormat.c @@ -0,0 +1,154 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +// functions +static void FormatCallback(s32 chan, s32 result); + +static void FormatCallback(s32 chan, s32 result) { + CARDControl *card; + CARDCallback callback; + + card = &__CARDBlock[chan]; + if (result < 0) + goto error; + + ++card->formatStep; + if (card->formatStep < CARD_NUM_SYSTEM_BLOCK) + { + result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback); + if (result >= 0) + return; + } + else if (card->formatStep < 2 * CARD_NUM_SYSTEM_BLOCK) + { + int step = card->formatStep - CARD_NUM_SYSTEM_BLOCK; + result = __CARDWrite(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE, + (u8 *)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), FormatCallback); + if (result >= 0) + return; + } + else + { + card->currentDir = (CARDDir *)((u8 *)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE); + memcpy(card->currentDir, (u8 *)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE); + card->currentFat = (u16 *)((u8 *)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE); + memcpy(card->currentFat, (u8 *)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE); + } + +error: + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(124, callback); + callback(chan, result); +} + +s32 __CARDFormatRegionAsync(s32 chan, u16 encode, CARDCallback callback) { + CARDControl *card; + CARDID *id; + CARDDir *dir; + u16 *fat; + s16 i; + s32 result; + OSSram *sram; + OSSramEx *sramEx; + u16 dvdstatus; + OSTime time; + OSTime rand; + + ASSERTLINE(158, encode == CARD_ENCODE_ANSI || encode == CARD_ENCODE_SJIS); + ASSERTLINE(159, 0 <= chan && chan < 2); + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + id = (CARDID *)card->workArea; + memset(id, 0xff, CARD_SYSTEM_BLOCK_SIZE); + dvdstatus = __VIRegs[55]; + + id->encode = encode; + + sram = __OSLockSram(); + *(u32 *)&id->serial[20] = sram->counterBias; + *(u32 *)&id->serial[24] = sram->language; + __OSUnlockSram(FALSE); + + rand = time = OSGetTime(); + + sramEx = __OSLockSramEx(); + for (i = 0; i < 12; i++) + { + rand = (rand * 1103515245 + 12345) >> 16; + id->serial[i] = (u8)(sramEx->flashID[chan][i] + rand); + rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF; + } + __OSUnlockSramEx(FALSE); + + *(u32 *)&id->serial[28] = dvdstatus; + *(OSTime *)&id->serial[12] = time; + + id->deviceID = 0; + id->size = card->size; + __CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &id->checkSum, &id->checkSumInv); + + for (i = 0; i < 2; i++) + { + CARDDirCheck *check; + + dir = (CARDDir *)((u8 *)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE); + memset(dir, 0xff, CARD_SYSTEM_BLOCK_SIZE); + check = CARDGetDirCheck(dir); + check->checkCode = i; + __CARDCheckSum(dir, CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &check->checkSum, &check->checkSumInv); + } + for (i = 0; i < 2; i++) + { + fat = (u16 *)((u8 *)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE); + memset(fat, 0x00, CARD_SYSTEM_BLOCK_SIZE); + fat[CARD_FAT_CHECKCODE] = (u16)i; + fat[CARD_FAT_FREEBLOCKS] = (u16)(card->cBlock - CARD_NUM_SYSTEM_BLOCK); + fat[CARD_FAT_LASTSLOT] = CARD_NUM_SYSTEM_BLOCK - 1; + __CARDCheckSum(&fat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &fat[CARD_FAT_CHECKSUM], + &fat[CARD_FAT_CHECKSUMINV]); + } + + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + DCStoreRange(card->workArea, CARD_WORKAREA_SIZE); + + card->formatStep = 0; + result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +s32 __CARDFormatRegion(s32 chan, u16 encode) { + s32 result; + + result = __CARDFormatRegionAsync(chan, encode, __CARDSyncCallback); + if (result < 0) { + return result; + } + + return __CARDSync(chan); +} + +s32 CARDFormatAsync(s32 chan, CARDCallback callback) { + return __CARDFormatRegionAsync(chan, __CARDGetFontEncode(), callback); +} + +// @hack +#pragma force_active on +long CARDFormat(long chan) { + long result = __CARDFormatRegionAsync(chan, __CARDGetFontEncode(), __CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(chan); +} +#pragma force_active reset diff --git a/src/static/GAEJ01_01/dolphin/card/CARDMount.c b/src/static/GAEJ01_01/dolphin/card/CARDMount.c new file mode 100644 index 00000000..00834da1 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDMount.c @@ -0,0 +1,410 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +typedef void (*EXICallback)(s32 chan, OSContext *context); + +static s32 SectorSizeTable[8] = +{ + 8 * 1024, 16 * 1024, 32 * 1024, 64 * 1024, 128 * 1024, 256 * 1024, 0, 0, +}; + +static s32 LatencyTable[8] = +{ + 4, 8, 16, 32, 64, 128, 256, 512, +}; + +// functions +static s32 DoMount(s32 chan); +static void DoUnmount(s32 chan, s32 result); + +static BOOL IsCard(u32 id) +{ + u32 size; + s32 sectorSize; + if (id & (0xFFFF0000) && (id != 0x80000004 || __CARDVendorID == 0xFFFF)) { + return FALSE; + } + + if ((id & 3) != 0) { + return FALSE; + } + + size = id & 0xfc; + switch (size) { + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + break; + default: + return FALSE; + break; + } + + sectorSize = SectorSizeTable[(id & 0x00003800) >> 11]; + if (sectorSize == 0) { + return FALSE; + } + + if ((size * 1024 * 1024 / 8) / sectorSize < 8) { + return FALSE; + } + + return TRUE; +} + +void __CARDDisable(BOOL disable) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + + __gUnknown800030E3 &= 0x7F; + if (disable) { + __gUnknown800030E3 |= 0x80; + } + + OSRestoreInterrupts(enabled); +} + +int CARDProbe(long chan) { + if (__gUnknown800030E3 & 0x80) { + return FALSE; + } + + return EXIProbe(chan); +} + +s32 CARDProbeEx(s32 chan, s32 *memSize, s32 *sectorSize) { + u32 id; + CARDControl *card; + BOOL enabled; + s32 result; + BOOL probe; + + if (chan < 0 || 2 <= chan) + return CARD_RESULT_FATAL_ERROR; + + if (__gUnknown800030E3 & 0x80) + { + return CARD_RESULT_NOCARD; + } + + card = &__CARDBlock[chan]; + enabled = OSDisableInterrupts(); + probe = EXIProbeEx(chan); + if (probe == -1) + { + result = CARD_RESULT_NOCARD; + } + else if (probe == 0) + { + result = CARD_RESULT_BUSY; + } + else if (card->attached) + { + if (card->mountStep < 1) + result = CARD_RESULT_BUSY; + else + { + if (memSize) { + *memSize = card->size; + } + + if (sectorSize) { + *sectorSize = card->sectorSize; + } + + result = CARD_RESULT_READY; + } + } + else if ((EXIGetState(chan) & 8)) + result = CARD_RESULT_WRONGDEVICE; + else if (!EXIGetID(chan, 0, &id)) + result = CARD_RESULT_BUSY; + else if (IsCard(id)) + { + if (memSize) { + *memSize = (s32)(id & 0xfc); + } + + if (sectorSize) { + *sectorSize = SectorSizeTable[(id & 0x00003800) >> 11]; + } + + result = CARD_RESULT_READY; + } + else + { + result = CARD_RESULT_WRONGDEVICE; + } + + OSRestoreInterrupts(enabled); + return result; +} + +static s32 DoMount(s32 chan) { + CARDControl *card; + u32 id; + u8 status; + s32 result; + struct OSSramEx *sram; + int i; + u8 checkSum; + int step; + u16 vendorID; + + ASSERTLINE(335, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (card->mountStep == 0) + { + if (EXIGetID(chan, 0, &id) == 0) { + result = CARD_RESULT_NOCARD; + } else if (IsCard(id)) { + result = CARD_RESULT_READY; + } else { + result = CARD_RESULT_WRONGDEVICE; + } + + if (result < 0) { + goto error; + } + + card->cid = id; + card->size = (u16)(id & 0xFC); + card->sectorSize = SectorSizeTable[(id & 0x00003800) >> 11]; + card->cBlock = (u16)((card->size * 1024 * 1024 / 8) / card->sectorSize); + card->latency = LatencyTable[(id & 0x00000700) >> 8]; + + result = __CARDClearStatus(chan); + if (result < 0) + goto error; + result = __CARDReadStatus(chan, &status); + if (result < 0) + goto error; + if (!EXIProbe(chan)) + { + result = CARD_RESULT_NOCARD; + goto error; + } + + if (!(status & 0x40)) + { + result = __CARDUnlock(chan, card->id); + if (result < 0) + goto error; + + checkSum = 0; + sram = __OSLockSramEx(); + for (i = 0; i < 12; i++) + { + sram->flashID[chan][i] = card->id[i]; + checkSum += card->id[i]; + } + sram->flashIDCheckSum[chan] = (u8)~checkSum; + __OSUnlockSramEx(TRUE); + + return result; + } + else + { + card->mountStep = 1; + + checkSum = 0; + sram = __OSLockSramEx(); + for (i = 0; i < 12; i++) + checkSum += sram->flashID[chan][i]; + + __OSUnlockSramEx(FALSE); + if (sram->flashIDCheckSum[chan] != (u8)~checkSum) + { + result = CARD_RESULT_IOERROR; + goto error; + } + } + } + + if (card->mountStep == 1) + { + if (((card->cid == 0x80000004))) { + sram = __OSLockSramEx(); + vendorID = *(u16*)sram->flashID[chan]; + __OSUnlockSramEx(FALSE); + + if (__CARDVendorID == 0xFFFF || (vendorID != __CARDVendorID)) { + result = CARD_RESULT_WRONGDEVICE; + goto error; + } + } + + card->mountStep = 2; + + result = __CARDEnableInterrupt(chan, TRUE); + if (result < 0) + goto error; + + EXISetExiCallback(chan, __CARDExiHandler); + EXIUnlock(chan); + DCInvalidateRange(card->workArea, CARD_WORKAREA_SIZE); + } + + step = card->mountStep - 2; + result = __CARDRead(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE, + (u8 *)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), __CARDMountCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; + +error: + EXIUnlock(chan); + DoUnmount(chan, result); + return result; +} + +void __CARDMountCallback(s32 chan, s32 result) { + CARDControl *card; + CARDCallback callback; + + ASSERTLINE(512, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + switch (result) + { + case CARD_RESULT_READY: + if (++card->mountStep < CARD_MAX_MOUNT_STEP) + { + result = DoMount(chan); + if (0 <= result) + return; + } + else + result = __CARDVerify(card); + break; + case CARD_RESULT_UNLOCKED: + card->unlockCallback = __CARDMountCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) { + return; + } + card->unlockCallback = NULL; + + result = DoMount(chan); + if (result >= 0) + return; + break; + case CARD_RESULT_IOERROR: + case CARD_RESULT_NOCARD: DoUnmount(chan, result); break; + } + + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(554, callback); + callback(chan, result); +} + +s32 CARDMountAsync(s32 chan, void *workArea, CARDCallback detachCallback, CARDCallback attachCallback) { + CARDControl *card; + BOOL enabled; + + ASSERTLINE(586, workArea && ((u32) workArea % 32 == 0)); + ASSERTLINE(587, 0 <= chan && chan < 2); + + if (chan < 0 || 2 <= chan) + return CARD_RESULT_FATAL_ERROR; + + if (__gUnknown800030E3 & 0x80) { + return CARD_RESULT_NOCARD; + } + + card = &__CARDBlock[chan]; + + enabled = OSDisableInterrupts(); + if (card->result == CARD_RESULT_BUSY) + { + OSRestoreInterrupts(enabled); + return CARD_RESULT_BUSY; + } + + if (!card->attached && (EXIGetState(chan) & 0x08)) + { + OSRestoreInterrupts(enabled); + return CARD_RESULT_WRONGDEVICE; + } + + card->result = CARD_RESULT_BUSY; + card->workArea = workArea; + card->extCallback = detachCallback; + card->apiCallback = attachCallback ? attachCallback : __CARDDefaultApiCallback; + card->exiCallback = 0; + + if (!card->attached && !EXIAttach(chan, __CARDExtHandler)) + { + card->result = CARD_RESULT_NOCARD; + OSRestoreInterrupts(enabled); + return CARD_RESULT_NOCARD; + } + + card->mountStep = 0; + card->attached = TRUE; + EXISetExiCallback(chan, 0); + OSCancelAlarm(&card->alarm); + + card->currentDir = 0; + card->currentFat = 0; + + OSRestoreInterrupts(enabled); + + card->unlockCallback = __CARDMountCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) + return CARD_RESULT_READY; + + card->unlockCallback = 0; + return DoMount(chan); +} + +s32 CARDMount(s32 chan, void *workArea, CARDCallback detachCallback) { + s32 result = CARDMountAsync(chan, workArea, detachCallback, __CARDSyncCallback); + + if (result < 0) + return result; + return __CARDSync(chan); +} + +static void DoUnmount(s32 chan, s32 result) { + CARDControl *card; + BOOL enabled; + + ASSERTLINE(692, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + enabled = OSDisableInterrupts(); + if (card->attached) + { + EXISetExiCallback(chan, 0); + EXIDetach(chan); + OSCancelAlarm(&card->alarm); + card->attached = FALSE; + card->result = result; + card->mountStep = 0; + } + OSRestoreInterrupts(enabled); +} + +s32 CARDUnmount(s32 chan) { + CARDControl *card; + s32 result; + + ASSERTLINE(727, 0 <= chan && chan < 2); + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + DoUnmount(chan, CARD_RESULT_NOCARD); + return CARD_RESULT_READY; +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDNet.c b/src/static/GAEJ01_01/dolphin/card/CARDNet.c new file mode 100644 index 00000000..a58b9823 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDNet.c @@ -0,0 +1,120 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +u16 __CARDVendorID = 0xFFFF; +u8 __CARDPermMask = 0x1C; + +u16 CARDSetVendorID(u16 vendorID) { + u16 prevID; + + prevID = __CARDVendorID; + __CARDVendorID = vendorID; + return prevID; +} + +u16 CARDGetVendorID(void) { + return __CARDVendorID; +} + +s32 CARDGetSerialNo(s32 chan, u64* serialNo) { + CARDControl* card; + s32 result; + CARDID* id; + u64 code; + int i; + + ASSERTLINE(95, 0 <= chan && chan < 2); + + if (!(0 <= chan && chan < 2)) { + return CARD_RESULT_FATAL_ERROR; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + + id = (CARDID*)card->workArea; + for (code = 0, i = 0; i < sizeof(id->serial) / sizeof(u64); ++i) { + code ^= *(u64*)&id->serial[sizeof(u64) * i]; + } + *serialNo = code; + + return __CARDPutControlBlock(card, CARD_RESULT_READY); +} + +s32 CARDGetUniqueCode(s32 chan, u64* uniqueCode) { + CARDControl* card; + s32 result; + OSSramEx* sram; + + ASSERTLINE(136, 0 <= chan && chan < 2); + + if (0 > chan || chan >= 2) { + return CARD_RESULT_FATAL_ERROR; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + + sram = __OSLockSramEx(); + memcpy(uniqueCode, sram->flashID[chan] + 4, 8); + __OSUnlockSramEx(FALSE); + return __CARDPutControlBlock(card, CARD_RESULT_READY); +} + +s32 CARDGetAttributes(s32 chan, s32 fileNo, u8* attr) { + CARDDir dirent; + s32 result; + + result = __CARDGetStatusEx(chan, fileNo, &dirent); + if (result == CARD_RESULT_READY) { + *attr = dirent.permission; + } + + return result; +} + +#define CARDCheckAttr(attr, flag) ((u32)(attr & flag) != 0) + +s32 CARDSetAttributesAsync(s32 chan, s32 fileNo, u8 attr, CARDCallback callback) { + CARDDir dirent; + s32 result; + + if (attr & ~__CARDPermMask) { + return CARD_RESULT_NOPERM; + } + + result = __CARDGetStatusEx(chan, fileNo, &dirent); + if (result < CARD_RESULT_READY) { + return result; + } + + if ((CARDCheckAttr(dirent.permission, 0x20) && !CARDCheckAttr(attr, 0x20)) || (CARDCheckAttr(dirent.permission, 0x40) && !CARDCheckAttr(attr, 0x40))) { + return CARD_RESULT_NOPERM; + } + + if ((CARDCheckAttr(attr, 0x20) && CARDCheckAttr(attr, 0x40)) || (CARDCheckAttr(attr, 0x20) && CARDCheckAttr(dirent.permission, 0x40)) || (CARDCheckAttr(attr, 0x40) && CARDCheckAttr(dirent.permission, 0x20))) { + return CARD_RESULT_NOPERM; + } + + dirent.permission = attr; + return __CARDSetStatusExAsync(chan, fileNo, &dirent, callback); +} + +s32 CARDSetAttributes(s32 chan, s32 fileNo, u8 attr) { + s32 result; + + result = CARDSetAttributesAsync(chan, fileNo, attr, __CARDSyncCallback); + if (result < CARD_RESULT_READY) { + return result; + } + + return __CARDSync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDOpen.c b/src/static/GAEJ01_01/dolphin/card/CARDOpen.c new file mode 100644 index 00000000..a87f0dcc --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDOpen.c @@ -0,0 +1,176 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +BOOL __CARDCompareFileName(CARDDir *ent, const char *fileName) { + char *entName = (char*)ent->fileName; + char c1; + char c2; + int n = CARD_FILENAME_MAX; + + while (--n >= 0) + { + if ((c1 = *entName++) != (c2 = *fileName++)) + return FALSE; + else if (c2 == '\0') + return TRUE; + } + + if (*fileName == '\0') + return TRUE; + return FALSE; +} + +s32 __CARDAccess(CARDControl* card, CARDDir *ent) { + const DVDDiskID* diskID = card->diskID; + + if (ent->gameName[0] == 0xFF) + return CARD_RESULT_NOFILE; + + if (diskID == &__CARDDiskNone + || (memcmp(ent->gameName, diskID->gameName, sizeof(ent->gameName)) == 0 + && memcmp(ent->company, diskID->company, sizeof(ent->company)) == 0)) + return CARD_RESULT_READY; + + return CARD_RESULT_NOPERM; +} + +s32 __CARDIsWritable(CARDControl* card, CARDDir *ent) { + const DVDDiskID* diskID = card->diskID; + s32 result; + u8 perm; + + result = __CARDAccess(card, ent); + if (result == CARD_RESULT_NOPERM) + { + perm = ent->permission & __CARDPermMask; + if (perm & 0x20 && (memcmp(ent->gameName, __CARDDiskNone.gameName, sizeof(ent->gameName)) == 0 + && memcmp(ent->company, __CARDDiskNone.company, sizeof(ent->company)) == 0)) + return CARD_RESULT_READY; + else if (perm & 0x40 && (memcmp(ent->gameName, __CARDDiskNone.gameName, sizeof(ent->gameName)) == 0 + && memcmp(ent->company, diskID->company, sizeof(ent->company)) == 0)) + return CARD_RESULT_READY; + } + return result; +} + +s32 __CARDIsReadable(CARDControl* card, CARDDir *ent) { + s32 result = __CARDIsWritable(card, ent); + + if (result == CARD_RESULT_NOPERM && (ent->permission & 0x4)) + return CARD_RESULT_READY; + return result; +} + +s32 __CARDGetFileNo(CARDControl* card, const char* fileName, s32* pfileNo) { + CARDDir *dir; + CARDDir *ent; + s32 fileNo; + s32 result; + + if (!card->attached) + return CARD_RESULT_NOCARD; + + dir = __CARDGetDirBlock(card); + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) + { + ent = &dir[fileNo]; + result = __CARDAccess(card, ent); + + if (result < 0) + continue; + if (__CARDCompareFileName(ent, fileName)) + { + *pfileNo = fileNo; + return CARD_RESULT_READY; + } + } + return CARD_RESULT_NOFILE; +} + +s32 CARDFastOpen(s32 chan, s32 fileNo, CARDFileInfo *fileInfo) { + CARDControl *card; + CARDDir *dir; + CARDDir *ent; + s32 result; + + ASSERTLINE(278, 0 <= fileNo && fileNo < CARD_MAX_FILE); + ASSERTLINE(279, 0 <= chan && chan < 2); + + if (fileNo < 0 || fileNo >= CARD_MAX_FILE) + return CARD_RESULT_FATAL_ERROR; + + fileInfo->chan = -1; + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + result = __CARDIsReadable(card, ent); + if (0 <= result) + { + if (!CARDIsValidBlockNo(card, ent->startBlock)) + result = CARD_RESULT_BROKEN; + else + { + fileInfo->chan = chan; + fileInfo->fileNo = fileNo; + fileInfo->offset = 0; + fileInfo->iBlock = ent->startBlock; + } + } + return __CARDPutControlBlock(card, result); +} + +s32 CARDOpen(s32 chan, const char *fileName, CARDFileInfo *fileInfo) { + CARDControl *card; + s32 result; + CARDDir *dir; + CARDDir *ent; + s32 fileNo; + + ASSERTLINE(286, 0 <= chan && chan < 2); + + fileInfo->chan = -1; + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + result = __CARDGetFileNo(card, fileName, &fileNo); + if (result >= 0) + { + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + if (!CARDIsValidBlockNo(card, ent->startBlock)) + result = CARD_RESULT_BROKEN; + else + { + fileInfo->chan = chan; + fileInfo->fileNo = fileNo; + fileInfo->offset = 0; + fileInfo->iBlock = ent->startBlock; + } + } + return __CARDPutControlBlock(card, result); +} + +s32 CARDClose(CARDFileInfo *fileInfo) { + CARDControl *card; + s32 result; + + ASSERTLINE(330, 0 <= fileInfo->chan && fileInfo->chan < 2); + ASSERTLINE(331, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); + + result = __CARDGetControlBlock(fileInfo->chan, &card); + if (result < 0) + return result; + + fileInfo->chan = -1; + return __CARDPutControlBlock(card, CARD_RESULT_READY); +} + +BOOL __CARDIsOpened(CARDControl *card, s32 fileNo) { + return FALSE; +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDRaw.c b/src/static/GAEJ01_01/dolphin/card/CARDRaw.c new file mode 100644 index 00000000..51a3b633 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDRaw.c @@ -0,0 +1,79 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +long __CARDRawReadAsync(long chan, void * buf, long length, long offset, void (* callback)(long, long)) { + struct CARDControl * card; + long result; + + ASSERTLINE(59, buf && ((u32) buf % 32) == 0); + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return __CARDPutControlBlock(card, result); + } + ASSERTLINE(67, 0 < length && (length % CARD_SEG_SIZE) == 0 && length < CARD_MAX_SIZE); + ASSERTLINE(68, (offset % card->sectorSize) == 0); + DCInvalidateRange(buf, length); + result = __CARDRead(chan, offset, length, buf, callback); + if (result < 0) { + __CARDPutControlBlock(card, result); + } + return result; +} + +long __CARDRawRead(long chan, void * buf, long length, long offset) { + long result = __CARDRawReadAsync(chan, buf, length, offset, &__CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(chan); +} + +static void EraseCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + + card = &__CARDBlock[chan]; + callback = card->apiCallback; + card->apiCallback = 0; + __CARDPutControlBlock(card, result); + ASSERTLINE(117, callback); + (*callback)(chan, result); +} + +s32 __CARDRawEraseAsync(s32 chan, s32 offset, CARDCallback callback) { + CARDControl* card; + s32 result; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return __CARDPutControlBlock(card, result); + } + + if (offset % card->sectorSize) { + return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR); + } + + if ((card->size * 1024 * 1024) / 8 <= offset) { + return __CARDPutControlBlock(card, CARD_RESULT_LIMIT); + } + + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + result = __CARDEraseSector(chan, offset, EraseCallback); + if (result < 0) { + __CARDPutControlBlock(card, result); + } + return result; +} + +s32 __CARDRawErase(s32 chan, s32 offset) { + s32 result = __CARDRawEraseAsync(chan, offset, __CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDRdwr.c b/src/static/GAEJ01_01/dolphin/card/CARDRdwr.c new file mode 100644 index 00000000..02acaac6 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDRdwr.c @@ -0,0 +1,100 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +// functions +static void BlockReadCallback(long chan, long result); +static void BlockWriteCallback(long chan, long result); + +static void BlockReadCallback(long chan, long result) { + struct CARDControl * card; + void (* callback)(long, long); + + card = &__CARDBlock[chan]; + + if ((result >= 0)) { + card->xferred += 0x200; + card->addr += 0x200; + ((u8*)card->buffer) += 0x200; + + if (--card->repeat > 0) { + result = __CARDReadSegment(chan, BlockReadCallback); + if (result >= 0) { + return; + } + } + } + if (!card->apiCallback) { + __CARDPutControlBlock(card, result); + } + callback = card->xferCallback; + if (callback) { + card->xferCallback = NULL; + callback(chan, result); + } +} + +long __CARDRead(long chan, unsigned long addr, long length, void * dst, void (* callback)(long, long)) { + struct CARDControl * card; + + ASSERTLINE(0x58, 0 < length && length % CARD_SEG_SIZE == 0); + ASSERTLINE(0x59, 0 <= chan && chan < 2); + card = &__CARDBlock[chan]; + if (card->attached == 0) { + return CARD_RESULT_NOCARD; + } + card->xferCallback = callback; + card->repeat = (length / 512u); + card->addr = addr; + card->buffer = dst; + return __CARDReadSegment(chan, BlockReadCallback); +} + +static void BlockWriteCallback(long chan, long result) { + struct CARDControl * card; + void (* callback)(long, long); + + card = &__CARDBlock[chan]; + if (result >= 0) { + card->xferred += 0x80; + card->addr += 0x80; + ((u8*)card->buffer) += 0x80; + + if (--card->repeat > 0) { + result = __CARDWritePage(chan, BlockWriteCallback); + if (result >= 0) { + return; + } + } + } + if (!card->apiCallback) { + __CARDPutControlBlock(card, result); + } + callback = card->xferCallback; + if (callback) { + card->xferCallback = NULL; + callback(chan, result); + } +} + +long __CARDWrite(long chan, unsigned long addr, long length, void * dst, void (* callback)(long, long)) { + struct CARDControl * card; + + ASSERTLINE(0x95, 0 < length && length % CARD_PAGE_SIZE == 0); + ASSERTLINE(0x96, 0 <= chan && chan < 2); + card = &__CARDBlock[chan]; + if (card->attached == 0) { + return CARD_RESULT_NOCARD; + } + card->xferCallback = callback; + card->repeat = (length / 128u); + card->addr = addr; + card->buffer = dst; + return __CARDWritePage(chan, BlockWriteCallback); +} + +long CARDGetXferredBytes(long chan) { + ASSERTLINE(0xB4, 0 <= chan && chan < 2); + return __CARDBlock[chan].xferred; +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDRead.c b/src/static/GAEJ01_01/dolphin/card/CARDRead.c new file mode 100644 index 00000000..60366b8f --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDRead.c @@ -0,0 +1,178 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) + +// functions +static void ReadCallback(s32 chan, s32 result); + +s32 __CARDSeek(CARDFileInfo *fileInfo, s32 length, s32 offset, CARDControl **pcard) { + CARDControl *card; + CARDDir *dir; + CARDDir *ent; + s32 result; + u16 *fat; + + ASSERTLINE(95, 0 <= fileInfo->chan && fileInfo->chan < 2); + ASSERTLINE(96, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); + + result = __CARDGetControlBlock(fileInfo->chan, &card); + if (result < 0) + return result; + + ASSERTLINE(103, CARDIsValidBlockNo(card, fileInfo->iBlock)); + ASSERTLINE(104, fileInfo->offset < card->cBlock * card->sectorSize); + + if (!CARDIsValidBlockNo(card, fileInfo->iBlock) || card->cBlock * card->sectorSize <= fileInfo->offset) + return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR); + + dir = __CARDGetDirBlock(card); + ent = &dir[fileInfo->fileNo]; + + ASSERTLINE(114, ent->gameName[0] != 0xff); + + if (ent->length * card->sectorSize <= offset || ent->length * card->sectorSize < offset + length) + return __CARDPutControlBlock(card, CARD_RESULT_LIMIT); + + card->fileInfo = fileInfo; + fileInfo->length = length; + if (offset < fileInfo->offset) + { + fileInfo->offset = 0; + fileInfo->iBlock = ent->startBlock; + if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + fat = __CARDGetFatBlock(card); + while (fileInfo->offset < TRUNC(offset, card->sectorSize)) + { + fileInfo->offset += card->sectorSize; + fileInfo->iBlock = fat[fileInfo->iBlock]; + if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + fileInfo->offset = offset; + + *pcard = card; + return CARD_RESULT_READY; +} + +static void ReadCallback(s32 chan, s32 result) { + CARDControl *card; + CARDCallback callback; + u16 *fat; + CARDFileInfo *fileInfo; + s32 length; + + card = &__CARDBlock[chan]; + if (result < 0) + goto error; + + fileInfo = card->fileInfo; + if (fileInfo->length < 0) + { + result = CARD_RESULT_CANCELED; + goto error; + } + + length = TRUNC(fileInfo->offset + card->sectorSize, card->sectorSize) - fileInfo->offset; + fileInfo->length -= length; + if (fileInfo->length <= 0) + goto error; + + fat = __CARDGetFatBlock(card); + fileInfo->offset += length; + fileInfo->iBlock = fat[fileInfo->iBlock]; + if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) + { + result = CARD_RESULT_BROKEN; + goto error; + } + + ASSERTLINE(196, OFFSET(fileInfo->length, CARD_SEG_SIZE) == 0); + ASSERTLINE(197, OFFSET(fileInfo->offset, card->sectorSize) == 0); + + result = __CARDRead(chan, card->sectorSize * (u32)fileInfo->iBlock, + (fileInfo->length < card->sectorSize) ? fileInfo->length : card->sectorSize, card->buffer, + ReadCallback); + if (result < 0) + goto error; + + return; + +error: + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(214, callback); + callback(chan, result); +} + +s32 CARDReadAsync(CARDFileInfo *fileInfo, void *buf, s32 length, s32 offset, CARDCallback callback) { + CARDControl *card; + s32 result; + CARDDir *dir; + CARDDir *ent; + + ASSERTLINE(247, buf && OFFSET(buf, 32) == 0); + ASSERTLINE(248, OFFSET(offset, CARD_SEG_SIZE) == 0); + ASSERTLINE(249, 0 < length && OFFSET(length, CARD_SEG_SIZE) == 0); + + if (OFFSET(offset, CARD_SEG_SIZE) != 0 || OFFSET(length, CARD_SEG_SIZE) != 0) + return CARD_RESULT_FATAL_ERROR; + result = __CARDSeek(fileInfo, length, offset, &card); + if (result < 0) + return result; + + dir = __CARDGetDirBlock(card); + ent = &dir[fileInfo->fileNo]; + result = __CARDIsReadable(card, ent); + if (result < 0) + return __CARDPutControlBlock(card, result); + + DCInvalidateRange(buf, (u32)length); + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + + offset = (s32)OFFSET(fileInfo->offset, card->sectorSize); + length = (length < card->sectorSize - offset) ? length : card->sectorSize - offset; + result = __CARDRead(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock + offset, length, buf, ReadCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +long CARDRead(struct CARDFileInfo * fileInfo, void * buf, long length, long offset) { + long result = CARDReadAsync(fileInfo, buf, length, offset, __CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(fileInfo->chan); +} + +s32 CARDCancel(CARDFileInfo *fileInfo) { + BOOL intrEnabled; + s32 result; + CARDControl *card; + + ASSERTLINE(339, 0 <= fileInfo->chan && fileInfo->chan < 2); + ASSERTLINE(340, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); + + intrEnabled = OSDisableInterrupts(); + + card = &__CARDBlock[fileInfo->chan]; + result = CARD_RESULT_READY; + if (!card->attached) + result = CARD_RESULT_NOCARD; + else if (card->result == CARD_RESULT_BUSY && card->fileInfo == fileInfo) + { + fileInfo->length = -1; + result = CARD_RESULT_CANCELED; + } + OSRestoreInterrupts(intrEnabled); + return result; +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDRename.c b/src/static/GAEJ01_01/dolphin/card/CARDRename.c new file mode 100644 index 00000000..fb900e57 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDRename.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +s32 CARDRenameAsync(s32 chan, const char *old, const char *new, CARDCallback callback) { + CARDControl* card; + CARDDir* dir; + CARDDir* ent; + s32 result; + int fileNo; + int newNo; + int oldNo; + + ASSERTLINE(80, 0 <= chan && chan < 2); + ASSERTLINE(81, *old != 0xff && *new != 0xff); + ASSERTLINE(82, *old != 0x00 && *new != 0x00); + + if (old[0] == 0xFF || new[0] == 0xFF || old[0] == 0 || new[0] == 0) + return CARD_RESULT_FATAL_ERROR; + if (CARD_FILENAME_MAX < (u32)strlen(old) || CARD_FILENAME_MAX < (u32)strlen(new)) + return CARD_RESULT_NAMETOOLONG; + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + newNo = oldNo = -1; + dir = __CARDGetDirBlock(card); + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) + { + ent = &dir[fileNo]; + if (ent->gameName[0] == 0xFF) + continue; + + if (memcmp(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)) != 0 + || memcmp(ent->company, card->diskID->company, sizeof(ent->company)) != 0) + continue; + + if (__CARDCompareFileName(ent, old)) + oldNo = fileNo; + if (__CARDCompareFileName(ent, new)) + newNo = fileNo; + } + + if (oldNo == -1) + return __CARDPutControlBlock(card, CARD_RESULT_NOFILE); + if (newNo != -1) + return __CARDPutControlBlock(card, CARD_RESULT_EXIST); + + ent = &dir[oldNo]; + result = __CARDIsWritable(card, ent); + if (result < 0) + return __CARDPutControlBlock(card, result); + + strncpy((char*)ent->fileName, new, CARD_FILENAME_MAX); + ent->time = (u32)OSTicksToSeconds(OSGetTime()); + + result = __CARDUpdateDir(chan, callback); + if (result < 0) + __CARDPutControlBlock(card, result); + + return result; +} + +s32 CARDRename(s32 chan, const char *oldName, const char *newName) { + s32 result = CARDRenameAsync(chan, oldName, newName, __CARDSyncCallback); + + if (result < 0) + return result; + return __CARDSync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDStat.c b/src/static/GAEJ01_01/dolphin/card/CARDStat.c new file mode 100644 index 00000000..ad91f29a --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDStat.c @@ -0,0 +1,166 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +// functions +static void UpdateIconOffsets(CARDDir *ent, CARDStat *stat); + +static void UpdateIconOffsets(CARDDir *ent, CARDStat *stat) { + u32 offset; + BOOL iconTlut; + int i; + + offset = ent->iconAddr; + if (offset == 0xffffffff) + { + stat->bannerFormat = 0; + stat->iconFormat = 0; + stat->iconSpeed = 0; + offset = 0; + } + + iconTlut = FALSE; + switch (CARDGetBannerFormat(ent)) + { + case CARD_STAT_BANNER_C8: + stat->offsetBanner = offset; + offset += CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT; + stat->offsetBannerTlut = offset; + offset += 2 * 256; + break; + case CARD_STAT_BANNER_RGB5A3: + stat->offsetBanner = offset; + offset += 2 * CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT; + stat->offsetBannerTlut = 0xffffffff; + break; + default: + stat->offsetBanner = 0xffffffff; + stat->offsetBannerTlut = 0xffffffff; + break; + } + for (i = 0; i < CARD_ICON_MAX; ++i) + { + switch (CARDGetIconFormat(ent, i)) + { + case CARD_STAT_ICON_C8: + stat->offsetIcon[i] = offset; + offset += CARD_ICON_WIDTH * CARD_ICON_HEIGHT; + iconTlut = TRUE; + break; + case CARD_STAT_ICON_RGB5A3: + stat->offsetIcon[i] = offset; + offset += 2 * CARD_ICON_WIDTH * CARD_ICON_HEIGHT; + break; + default: + stat->offsetIcon[i] = 0xffffffff; + break; + } + } + if (iconTlut) + { + stat->offsetIconTlut = offset; + offset += 2 * 256; + } + else + { + stat->offsetIconTlut = 0xffffffff; + } + stat->offsetData = offset; +} + +s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat *stat) { + CARDControl *card; + CARDDir *dir; + CARDDir *ent; + s32 result; + + ASSERTLINE(169, 0 <= chan && chan < 2); + ASSERTLINE(170, 0 <= fileNo && fileNo < CARD_MAX_FILE); + + if (fileNo < 0 || CARD_MAX_FILE <= fileNo) + return CARD_RESULT_FATAL_ERROR; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + result = __CARDIsReadable(card, ent); + + if (result >= 0) + { + memcpy(stat->gameName, ent->gameName, sizeof(stat->gameName)); + memcpy(stat->company, ent->company, sizeof(stat->company)); + stat->length = (u32)ent->length * card->sectorSize; + memcpy(stat->fileName, ent->fileName, CARD_FILENAME_MAX); + stat->time = ent->time; + + stat->bannerFormat = ent->bannerFormat; + stat->iconAddr = ent->iconAddr; + stat->iconFormat = ent->iconFormat; + stat->iconSpeed = ent->iconSpeed; + stat->commentAddr = ent->commentAddr; + + UpdateIconOffsets(ent, stat); + } + return __CARDPutControlBlock(card, result); +} + +s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat *stat, CARDCallback callback) { + CARDControl *card; + CARDDir *dir; + CARDDir *ent; + s32 result; + + ASSERTLINE(232, 0 <= fileNo && fileNo < CARD_MAX_FILE); + ASSERTLINE(233, 0 <= chan && chan < 2); + ASSERTMSGLINE(241, stat->iconAddr == 0xffffffff || stat->iconAddr < CARD_READ_SIZE, "CARDSetStatus[Async](): stat->iconAddr must be 0xffffffff or less than CARD_READ_SIZE."); + ASSERTMSGLINE(244, stat->commentAddr == 0xffffffff || (stat->commentAddr & 0x1FFF) <= 8128, "CARDSetStatus[Async](): comment strings (set by stat->commentAddr) must not cross 8KB byte boundary."); + + if (fileNo < 0 || CARD_MAX_FILE <= fileNo || + (stat->iconAddr != 0xffffffff && CARD_READ_SIZE <= stat->iconAddr) || + (stat->commentAddr != 0xffffffff && + CARD_SYSTEM_BLOCK_SIZE - CARD_COMMENT_SIZE < stat->commentAddr % CARD_SYSTEM_BLOCK_SIZE)) + { + return CARD_RESULT_FATAL_ERROR; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + result = __CARDIsWritable(card, ent); + if (result < 0) + return __CARDPutControlBlock(card, result); + + ent->bannerFormat = stat->bannerFormat; + ent->iconAddr = stat->iconAddr; + ent->iconFormat = stat->iconFormat; + ent->iconSpeed = stat->iconSpeed; + ent->commentAddr = stat->commentAddr; + UpdateIconOffsets(ent, stat); + + if (ent->iconAddr == 0xffffffff) { + ent->iconSpeed = (ent->iconSpeed & ~CARD_STAT_SPEED_MASK) | CARD_STAT_SPEED_FAST; + } + + ent->time = (u32)OSTicksToSeconds(OSGetTime()); + result = __CARDUpdateDir(chan, callback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +long CARDSetStatus(long chan, long fileNo, struct CARDStat * stat) { + long result = CARDSetStatusAsync(chan, fileNo, stat, __CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDStatEx.c b/src/static/GAEJ01_01/dolphin/card/CARDStatEx.c new file mode 100644 index 00000000..38865c7a --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDStatEx.c @@ -0,0 +1,119 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +long __CARDGetStatusEx(long chan, long fileNo, struct CARDDir * dirent) { + ASSERTLINE(76, 0 <= chan && chan < 2); + ASSERTLINE(77, 0 <= fileNo && fileNo < CARD_MAX_FILE); + + if ((fileNo < 0) || (fileNo >= CARD_MAX_FILE)) { + return CARD_RESULT_FATAL_ERROR; + } + + { + struct CARDControl * card; + struct CARDDir * dir; + struct CARDDir * ent; + long result = __CARDGetControlBlock(chan, &card); + + if (result < 0) { + return result; + } + + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + result = __CARDIsReadable(card, ent); + if (result >= 0) { + memcpy(dirent, ent, 0x40); + } + return __CARDPutControlBlock(card, result); + } +} + +long __CARDSetStatusExAsync(long chan, long fileNo, struct CARDDir * dirent, void (* callback)(long, long)) { + struct CARDControl * card; + struct CARDDir * dir; + struct CARDDir * ent; + long result; + unsigned char * p; + long i; + + ASSERTLINE(137, 0 <= fileNo && fileNo < CARD_MAX_FILE); + ASSERTLINE(138, 0 <= chan && chan < 2); + ASSERTLINE(139, *dirent->fileName != 0xff && *dirent->fileName != 0x00); + ASSERTMSGLINE(147, dirent->iconAddr == 0xffffffff || dirent->iconAddr < CARD_READ_SIZE, "CARDSetStatus[Async](): stat->iconAddr must be 0xffffffff or less than CARD_READ_SIZE."); + ASSERTMSGLINE(150, dirent->commentAddr == 0xffffffff || (dirent->commentAddr & 0x1FFF) <= 8128, "CARDSetStatus[Async](): comment strings (set by stat->commentAddr) must not cross 8KB byte boundary."); + + if ((fileNo < 0) || (fileNo >= CARD_MAX_FILE) || ((u8) dirent->fileName[0] == 0xFF) || ((u8) dirent->fileName[0] == 0)) { + return CARD_RESULT_FATAL_ERROR; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + result = __CARDIsWritable(card, ent); + if (result < 0) { + return __CARDPutControlBlock(card, result); + } + for(p = dirent->fileName; p < (u8*)&dirent->time; p++) { + if (*p != 0) { + continue; + } + while ((++p) < (u8*)&dirent->time) { + *p = 0; + } + break; + } + + if (dirent->permission & 0x20) { + memset(dirent->gameName, 0, sizeof(dirent->gameName)); + memset(dirent->company, 0, sizeof(dirent->company)); + } + + if (dirent->permission & 0x40) { + memset(dirent->gameName, 0, sizeof(dirent->gameName)); + } + + if ((memcmp(&ent->fileName, &dirent->fileName, 32) != 0) || (memcmp(ent->gameName, dirent->gameName, 4) != 0) || (memcmp(ent->company, dirent->company, 2) != 0)) { + for(i = 0; i < CARD_MAX_FILE; i++) { + if (i != fileNo) { + struct CARDDir * ent = &dir[i]; // sure, just redeclare ent again... + if (((u8) ent->gameName[0] != 0xFF) + && (memcmp(&ent->gameName, &dirent->gameName, 4) == 0) + && (memcmp(&ent->company, &dirent->company, 2) == 0) + && (memcmp(&ent->fileName, &dirent->fileName, 0x20) == 0)) { + return __CARDPutControlBlock(card, -7); + } + } + } + memcpy(&ent->fileName, &dirent->fileName, 0x20); + memcpy(&ent->gameName, &dirent->gameName, 4); + memcpy(&ent->company, &dirent->company, 2); + } + ent->time = dirent->time; + ent->bannerFormat = dirent->bannerFormat; + ent->iconAddr = dirent->iconAddr; + ent->iconFormat = dirent->iconFormat; + ent->iconSpeed = dirent->iconSpeed; + ent->commentAddr = dirent->commentAddr; + ent->permission = dirent->permission; + ent->copyTimes = dirent->copyTimes; + result = __CARDUpdateDir(chan, callback); + if (result < 0) { + __CARDPutControlBlock(card, result); + } + return result; +} + +long __CARDSetStatusEx(long chan, long fileNo, struct CARDDir * dirent) { + long result = __CARDSetStatusExAsync(chan, fileNo, dirent, &__CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDUnlock.c b/src/static/GAEJ01_01/dolphin/card/CARDUnlock.c new file mode 100644 index 00000000..d7d534bf --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDUnlock.c @@ -0,0 +1,401 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +static u8 CardData[352] ATTRIBUTE_ALIGN(32) = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0xFF, 0x00, 0x21, 0x13, 0x06, 0x12, 0x03, 0x12, 0x04, + 0x13, 0x05, 0x00, 0x92, 0x00, 0xFF, 0x00, 0x88, 0xFF, 0xFF, 0x00, 0x89, 0xFF, 0xFF, 0x00, 0x8A, 0xFF, 0xFF, 0x00, + 0x8B, 0xFF, 0xFF, 0x8F, 0x00, 0x02, 0xBF, 0x00, 0x88, 0x16, 0xFC, 0xDC, 0xD1, 0x16, 0xFD, 0x00, 0x00, 0x16, 0xFB, + 0x00, 0x01, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x03, 0x80, 0xFF, 0x00, 0x02, 0x94, 0x00, 0x27, 0x02, 0xBF, 0x00, + 0x8E, 0x1F, 0xDF, 0x24, 0xFF, 0x02, 0x40, 0x0F, 0xFF, 0x00, 0x98, 0x04, 0x00, 0x00, 0x9A, 0x00, 0x10, 0x00, 0x99, + 0x00, 0x00, 0x8E, 0x00, 0x02, 0xBF, 0x00, 0x94, 0x02, 0xBF, 0x86, 0x44, 0x02, 0xBF, 0x00, 0x88, 0x16, 0xFC, 0xDC, + 0xD1, 0x16, 0xFD, 0x00, 0x03, 0x16, 0xFB, 0x00, 0x01, 0x8F, 0x00, 0x02, 0xBF, 0x00, 0x8E, 0x03, 0x80, 0xCD, 0xD1, + 0x02, 0x94, 0x00, 0x48, 0x27, 0xFF, 0x03, 0x80, 0x00, 0x01, 0x02, 0x95, 0x00, 0x5A, 0x03, 0x80, 0x00, 0x02, 0x02, + 0x95, 0x80, 0x00, 0x02, 0x9F, 0x00, 0x48, 0x00, 0x21, 0x8E, 0x00, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, + 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC5, 0xFF, 0xFF, 0x03, + 0x40, 0x0F, 0xFF, 0x1C, 0x9F, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC7, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC6, + 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC0, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x20, 0xFF, 0x03, 0x40, 0x0F, + 0xFF, 0x1F, 0x5F, 0x02, 0xBF, 0x00, 0x8E, 0x21, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x23, 0xFF, 0x12, 0x05, 0x12, 0x06, + 0x02, 0x9F, 0x80, 0xB5, 0x00, 0x21, 0x27, 0xFC, 0x03, 0xC0, 0x80, 0x00, 0x02, 0x9D, 0x00, 0x88, 0x02, 0xDF, 0x27, + 0xFE, 0x03, 0xC0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x8E, 0x02, 0xDF, 0x2E, 0xCE, 0x2C, 0xCF, 0x00, 0xF8, 0xFF, 0xCD, + 0x00, 0xF9, 0xFF, 0xC9, 0x00, 0xFA, 0xFF, 0xCB, 0x26, 0xC9, 0x02, 0xC0, 0x00, 0x04, 0x02, 0x9D, 0x00, 0x9C, 0x02, + 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +// functions +static u32 exnor_1st(u32 data, u32 rshift); +static u32 exnor(u32 data, u32 lshift); +static u32 bitrev(u32 data); +static s32 ReadArrayUnlock(s32 chan, u32 data, void *rbuf, s32 rlen, s32 mode); +static u32 GetInitVal(void); +static s32 DummyLen(void); +static void InitCallback(void * _task); +static void DoneCallback(void * _task); + +static u32 exnor_1st(u32 data, u32 rshift) { + u32 wk; + u32 work; + u32 i; + + work = data; + for (i = 0; i < rshift; i++) + { + wk = ~(work ^ (work >> 7) ^ (work >> 15) ^ (work >> 23)); + work = (work >> 1) | ((wk << 30) & 0x40000000); + } + return work; +} + +static u32 exnor(u32 data, u32 lshift) { + u32 wk; + u32 work; + u32 i; + + work = data; + for (i = 0; i < lshift; i++) + { + // 1bit Left Shift + wk = ~(work ^ (work << 7) ^ (work << 15) ^ (work << 23)); + work = (work << 1) | ((wk >> 30) & 0x00000002); + } + return work; +} + +static u32 bitrev(u32 data) { + u32 wk; + u32 i; + u32 k = 0; + u32 j = 1; + + wk = 0; + for (i = 0; i < 32; i++) + { + if (i > 15) + { + if (i == 31) + wk |= (((data & (0x01 << 31)) >> 31) & 0x01); + else + { + wk |= ((data & (0x01 << i)) >> j); + j += 2; + } + } + else + { + wk |= ((data & (0x01 << i)) << (31 - i - k)); + k++; + } + } + return wk; +} + +#define SEC_AD1(x) ((u8)(((x) >> 29) & 0x03)) +#define SEC_AD2(x) ((u8)(((x) >> 21) & 0xff)) +#define SEC_AD3(x) ((u8)(((x) >> 19) & 0x03)) +#define SEC_BA(x) ((u8)(((x) >> 12) & 0x7f)) + +static s32 ReadArrayUnlock(s32 chan, u32 data, void *rbuf, s32 rlen, s32 mode) { + CARDControl *card; + BOOL err; + u8 cmd[5]; + + ASSERTLINE(213, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!EXISelect(chan, 0, 4)) + return CARD_RESULT_NOCARD; + + data &= 0xfffff000; + memset(cmd, 0, 5); + cmd[0] = 0x52; + if (mode == 0) + { + cmd[1] = SEC_AD1(data); + cmd[2] = SEC_AD2(data); + cmd[3] = SEC_AD3(data); + cmd[4] = SEC_BA(data); + } + else + { + cmd[1] = (u8)((data & 0xff000000) >> 24); + cmd[2] = (u8)((data & 0x00ff0000) >> 16); + } + + err = FALSE; + err |= !EXIImmEx(chan, cmd, 5, 1); + err |= !EXIImmEx(chan, (u8 *)card->workArea + (u32)sizeof(CARDID), card->latency, 1); + err |= !EXIImmEx(chan, rbuf, rlen, 0); + err |= !EXIDeselect(chan); + + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +static u32 GetInitVal(void) { + u32 tmp; + u32 tick; + + tick = OSGetTick(); + srand(tick); + tmp = 0x7fec8000; + tmp |= rand(); + tmp &= 0xfffff000; + return tmp; +} + +static s32 DummyLen(void) { + u32 tick; + u32 wk; + s32 tmp; + u32 max; + + wk = 1; + max = 0; + tick = OSGetTick(); + srand(tick); + + tmp = rand(); + tmp &= 0x0000001f; + tmp += 1; + while ((tmp < 4) && (max < 10)) + { + tick = OSGetTick(); + tmp = (s32)(tick << wk); + wk++; + if (wk > 16) + wk = 1; + srand((u32)tmp); + tmp = rand(); + tmp &= 0x0000001f; + tmp += 1; + max++; + } + if (tmp < 4) + tmp = 4; + + return tmp; +} + +s32 __CARDUnlock(s32 chan, u8 flashID[12]) { + u32 init_val; + u32 data; + + s32 dummy; + s32 rlen; + u32 rshift; + + u8 fsts; + u32 wk, wk1; + u32 Ans1 = 0; + u32 Ans2 = 0; + u32 *dp; + u8 rbuf[64]; + u32 para1A = 0; + u32 para1B = 0; + u32 para2A = 0; + u32 para2B = 0; + + CARDControl *card; + DSPTaskInfo *task; + CARDDecParam *param; + u8 *input; + u8 *output; + + card = &__CARDBlock[chan]; + task = &card->task; + param = (CARDDecParam *)card->workArea; + input = (u8 *)((u8 *)param + sizeof(CARDDecParam)); + input = (u8 *)OSRoundUp32B(input); + output = input + 32; + + fsts = 0; + init_val = GetInitVal(); + + dummy = DummyLen(); + rlen = dummy; + if (ReadArrayUnlock(chan, init_val, rbuf, rlen, 0) < 0) + return CARD_RESULT_NOCARD; + + rshift = (u32)(dummy * 8 + 1); + wk = exnor_1st(init_val, rshift); + wk1 = ~(wk ^ (wk >> 7) ^ (wk >> 15) ^ (wk >> 23)); + card->scramble = (wk | ((wk1 << 31) & 0x80000000)); + card->scramble = bitrev(card->scramble); + dummy = DummyLen(); + rlen = 20 + dummy; + data = 0; + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) + return CARD_RESULT_NOCARD; + + dp = (u32 *)rbuf; + para1A = *dp++; + para1B = *dp++; + Ans1 = *dp++; + para2A = *dp++; + para2B = *dp++; + para1A = (para1A ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + para1B = (para1B ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + Ans1 ^= card->scramble; + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + para2A = (para2A ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + para2B = (para2B ^ card->scramble); + rshift = (u32)(dummy * 8); + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + rshift = 32 + 1; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + *(u32 *)&input[0] = para2A; + *(u32 *)&input[4] = para2B; + + param->inputAddr = input; + param->inputLength = 8; + param->outputAddr = output; + param->aramAddr = 0; + + DCFlushRange(input, 8); + DCInvalidateRange(output, 4); + DCFlushRange(param, sizeof(CARDDecParam)); + + task->priority = 255; + task->iram_mmem_addr = (u16 *)OSCachedToPhysical(CardData); + task->iram_length = 0x160; + task->iram_addr = 0; + task->dsp_init_vector = 0x10; + task->init_cb = InitCallback; + task->res_cb = NULL; + task->done_cb = DoneCallback; + task->req_cb = NULL; + DSPAddTask(task); + + dp = (u32 *)flashID; + *dp++ = para1A; + *dp++ = para1B; + *dp = Ans1; + + return CARD_RESULT_READY; +} + +static void InitCallback(void *_task) +{ + s32 chan; + CARDControl *card; + DSPTaskInfo *task; + CARDDecParam *param; + + task = _task; + for (chan = 0; chan < 2; ++chan) + { + card = &__CARDBlock[chan]; + if ((DSPTaskInfo *)&card->task == task) + break; + } + + ASSERTLINE(487, 0 <= chan && chan < 2); + + param = (CARDDecParam *)card->workArea; + + DSPSendMailToDSP(0xff000000); + while (DSPCheckMailToDSP()) + ; + + DSPSendMailToDSP((u32)param); + while (DSPCheckMailToDSP()) + ; +} + +static void DoneCallback(void *_task) +{ + u8 rbuf[64]; + u32 data; + s32 dummy; + s32 rlen; + u32 rshift; + + u8 unk; + u32 wk, wk1; + u32 Ans2; + + s32 chan; + CARDControl *card; + s32 result; + DSPTaskInfo *task; + CARDDecParam *param; + + u8 *input; + u8 *output; + task = _task; + for (chan = 0; chan < 2; ++chan) + { + card = &__CARDBlock[chan]; + if ((DSPTaskInfo *)&card->task == task) + break; + } + + ASSERTLINE(536, 0 <= chan && chan < 2); + + param = (CARDDecParam *)card->workArea; + input = (u8 *)((u8 *)param + sizeof(CARDDecParam)); + input = (u8 *)OSRoundUp32B(input); + output = input + 32; + + Ans2 = *(u32 *)output; + dummy = DummyLen(); + rlen = dummy; + data = ((Ans2 ^ card->scramble) & 0xffff0000); + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) + { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + + rshift = (u32)((dummy + 4 + card->latency) * 8 + 1); + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + dummy = DummyLen(); + rlen = dummy; + data = (((Ans2 << 16) ^ card->scramble) & 0xffff0000); + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) + { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + result = __CARDReadStatus(chan, &unk); + if (!EXIProbe(chan)) + { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + if (result == CARD_RESULT_READY && !(unk & 0x40)) + { + EXIUnlock(chan); + result = CARD_RESULT_IOERROR; + } + __CARDMountCallback(chan, result); +} diff --git a/src/static/GAEJ01_01/dolphin/card/CARDWrite.c b/src/static/GAEJ01_01/dolphin/card/CARDWrite.c new file mode 100644 index 00000000..35652b16 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/CARDWrite.c @@ -0,0 +1,122 @@ +#include +#include + +// internal includes +#include "../src/static/GAEJ01_01/dolphin/card/__card.h" + +// functions +static void WriteCallback(long chan, long result); +static void EraseCallback(long chan, long result); + +static void WriteCallback(long chan, long result) { + struct CARDControl * card; + void (* callback)(long, long); + unsigned short * fat; + struct CARDDir * dir; + struct CARDDir * ent; + struct CARDFileInfo * fileInfo; + + card = &__CARDBlock[chan]; + if (result >= 0) { + fileInfo = card->fileInfo; + if (fileInfo->length < 0) { + result = CARD_RESULT_CANCELED; + goto after; + } + fileInfo->length -= card->sectorSize; + if (fileInfo->length <= 0) { + dir = __CARDGetDirBlock(card); + ent = dir + fileInfo->fileNo; + ent->time = OSGetTime()/(__OSBusClock/4); + callback = card->apiCallback; + card->apiCallback = NULL; + result = __CARDUpdateDir(chan, callback); + goto check; + } else { + fat = __CARDGetFatBlock(card); + fileInfo->offset += card->sectorSize; + fileInfo->iBlock = fat[fileInfo->iBlock]; + if ((fileInfo->iBlock < 5) || (fileInfo->iBlock >= card->cBlock)) { + result = CARD_RESULT_BROKEN; + goto after; + } + result = __CARDEraseSector(chan, card->sectorSize * fileInfo->iBlock, EraseCallback); +check:; + if (result < 0) { + goto after; + } + } + } else { +after:; + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(128, callback); + callback(chan, result); + } +} + +static void EraseCallback(long chan, long result) { + struct CARDControl * card; + void (* callback)(long, long); + struct CARDFileInfo * fileInfo; + + card = &__CARDBlock[chan]; + if (result >= 0) { + fileInfo = card->fileInfo; + ASSERTLINE(155, OFFSET(fileInfo->offset, card->sectorSize) == 0); + result = __CARDWrite(chan, card->sectorSize * fileInfo->iBlock, card->sectorSize, card->buffer, WriteCallback); + if (result < 0) { + goto after; + } + } else { +after:; + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(169, callback); + callback(chan, result); + } +} + +long CARDWriteAsync(struct CARDFileInfo * fileInfo, const void * buf, long length, long offset, void (* callback)(long, long)) { + struct CARDControl * card; + long result; + struct CARDDir * dir; + struct CARDDir * ent; + + ASSERTLINE(204, buf && ((u32) buf % 32) == 0); + ASSERTLINE(205, 0 < length); + result = __CARDSeek(fileInfo, length, offset, &card); + if (result < 0) { + return result; + } + ASSERTLINE(211, OFFSET(offset, card->sectorSize) == 0); + ASSERTLINE(212, OFFSET(length, card->sectorSize) == 0); + + if (OFFSET(offset, card->sectorSize) != 0 || OFFSET(length, card->sectorSize) != 0) + return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR); + + dir = __CARDGetDirBlock(card); + ent = &dir[fileInfo->fileNo]; + result = __CARDIsWritable(card, ent); + if (result < 0) + return __CARDPutControlBlock(card, result); + + DCStoreRange((void *)buf, (u32)length); + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + card->buffer = (void *)buf; + result = __CARDEraseSector(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock, EraseCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +long CARDWrite(struct CARDFileInfo * fileInfo, const void * buf, long length, long offset) { + long result = CARDWriteAsync(fileInfo, buf, length, offset, __CARDSyncCallback); + + if (result < 0) { + return result; + } + return __CARDSync(fileInfo->chan); +} diff --git a/src/static/GAEJ01_01/dolphin/card/__card.h b/src/static/GAEJ01_01/dolphin/card/__card.h new file mode 100644 index 00000000..c4772b31 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/card/__card.h @@ -0,0 +1,101 @@ +#ifndef _DOLPHIN_CARD_INTERNAL_H_ +#define _DOLPHIN_CARD_INTERNAL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CARDIsValidBlockNo(card, iBlock) (CARD_NUM_SYSTEM_BLOCK <= (iBlock) && (iBlock) < (card)->cBlock) + +// CARDStatEx.c +long __CARDGetStatusEx(long chan, long fileNo, struct CARDDir * dirent); +long __CARDSetStatusExAsync(long chan, long fileNo, struct CARDDir * dirent, void (* callback)(long, long)); +long __CARDSetStatusEx(long chan, long fileNo, struct CARDDir * dirent); + +// CARDUnlock.c +// s32 __CARDUnlock(s32 chan, u8 flashID[12]); + +// CARDRead.c +s32 __CARDSeek(CARDFileInfo *fileInfo, s32 length, s32 offset, CARDControl **pcard); + +// CARDRdwr.c +long __CARDRead(long chan, unsigned long addr, long length, void * dst, void (* callback)(long, long)); +long __CARDWrite(long chan, unsigned long addr, long length, void * dst, void (* callback)(long, long)); + +// CARDRaw.c +long __CARDRawReadAsync(long chan, void * buf, long length, long offset, void (* callback)(long, long)); +long __CARDRawRead(long chan, void * buf, long length, long offset); + +// CARDOpen.c +BOOL __CARDCompareFileName(CARDDir *ent, const char *fileName); +s32 __CARDAccess(CARDControl* card, CARDDir *ent); +s32 __CARDIsWritable(CARDControl* card, CARDDir *ent); +s32 __CARDIsReadable(CARDControl* card, CARDDir *ent); +s32 __CARDGetFileNo(CARDControl* card, const char* fileName, s32* pfileNo); +BOOL __CARDIsOpened(CARDControl *card, s32 fileNo); + +// CARDNet.c +u16 CARDSetVendorID(u16 vendorID); +u16 CARDGetVendorID(void); +s32 CARDGetSerialNo(s32 chan, u64* serialNo); +s32 CARDGetUniqueCode(s32 chan, u64* uniqueCode); + +extern u16 __CARDVendorID; +extern u8 __CARDPermMask; + +// CARDMount.c +void __CARDDisable(BOOL disable); +void __CARDMountCallback(s32 chan, s32 result); + +// CARDFormat.c +s32 CARDFormatAsync(s32 chan, CARDCallback callback); + +// CARDDir.c +CARDDir *__CARDGetDirBlock(CARDControl* card); +s32 __CARDUpdateDir(s32 chan, CARDCallback callback); + +// CARDCheck.c +void __CARDCheckSum(void *ptr, int length, u16 *checksum, u16 *checksumInv); +s32 __CARDVerify(CARDControl *card); + +// CARDBlock.c +void *__CARDGetFatBlock(CARDControl *card); +s32 __CARDAllocBlock(s32 chan, u32 cBlock, CARDCallback callback); +s32 __CARDFreeBlock(s32 chan, u16 nBlock, CARDCallback callback); +s32 __CARDUpdateFatBlock(s32 chan, u16 *fat, CARDCallback callback); + +// CARDBios.c +extern struct CARDControl __CARDBlock[2]; + +extern DVDDiskID __CARDDiskNone; + +void __CARDDefaultApiCallback(s32 chan, s32 result); +void __CARDSyncCallback(s32 chan, s32 result); +void __CARDExtHandler(s32 chan, OSContext *context); +void __CARDExiHandler(s32 chan, OSContext *context); +void __CARDTxHandler(s32 chan, OSContext *context); +void __CARDUnlockedHandler(s32 chan, OSContext *context); +int __CARDReadNintendoID(s32 chan, u32 *id); +s32 __CARDEnableInterrupt(s32 chan, BOOL enable); +s32 __CARDReadStatus(s32 chan, u8 *status); +s32 __CARDClearStatus(s32 chan); +long __CARDSleep(long chan); +long __CARDWakeup(long chan); +s32 __CARDReadSegment(s32 chan, CARDCallback callback); +s32 __CARDWritePage(s32 chan, CARDCallback callback); +long __CARDErase(long chan, void (* callback)(long, long)); +s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback); +u16 __CARDGetFontEncode(void); +void __CARDSetDiskID(DVDDiskID *id); +s32 __CARDGetControlBlock(s32 chan, CARDControl **pcard); +s32 __CARDPutControlBlock(CARDControl *card, s32 result); +s32 __CARDSync(s32 chan); + +#ifdef __cplusplus +} +#endif + +#endif // _DOLPHIN_CARD_INTERNAL_H_ diff --git a/src/static/GAEJ01_01/dolphin/db/db.c b/src/static/GAEJ01_01/dolphin/db/db.c new file mode 100644 index 00000000..433c2916 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/db/db.c @@ -0,0 +1,44 @@ +#include +#include +#include + +BOOL DBVerbose; +struct DBInterface* __DBInterface; + +void DBInit(void) +{ + __DBInterface = OSPhysicalToCached(0x40); + __DBInterface->ExceptionDestination + = (void*)OSCachedToPhysical(__DBExceptionDestination); + DBVerbose = TRUE; +} + +void __DBExceptionDestinationAux(void) +{ + u32* contextAddr; + OSContext* context; + + contextAddr = (void*)0xC0; + context = OSPhysicalToCached(*contextAddr); + OSReport("DBExceptionDestination\n"); + OSDumpContext(context); + PPCHalt(); +} + +asm void __DBExceptionDestination(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc + mfmsr r3 + ori r3, r3, 0x30 + mtmsr r3 + b __DBExceptionDestinationAux +#endif // clang-format on +} + +BOOL __DBIsExceptionMarked(__OSException exception) +{ + u32 mask = (1 << exception); + return __DBInterface->exceptionMask & mask; +} + +void DBPrintf(char* str, ...) { } diff --git a/src/static/GAEJ01_01/dolphin/dsp/__dsp.h b/src/static/GAEJ01_01/dolphin/dsp/__dsp.h new file mode 100644 index 00000000..5342f990 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dsp/__dsp.h @@ -0,0 +1,12 @@ +extern DSPTaskInfo* __DSP_curr_task; +extern DSPTaskInfo* __DSP_last_task; +extern DSPTaskInfo* __DSP_first_task; +extern DSPTaskInfo* __DSP_tmp_task; + +void __DSPHandler(__OSInterrupt, OSContext*); +void __DSP_exec_task(DSPTaskInfo*, DSPTaskInfo*); +void __DSP_boot_task(DSPTaskInfo*); +void __DSP_insert_task(DSPTaskInfo*); +void __DSP_add_task(DSPTaskInfo* task); +void __DSP_remove_task(DSPTaskInfo* task); +void __DSP_debug_printf(const char* fmt, ...); diff --git a/src/static/GAEJ01_01/dolphin/dsp/dsp.c b/src/static/GAEJ01_01/dolphin/dsp/dsp.c new file mode 100644 index 00000000..a6c227cb --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dsp/dsp.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/dsp/__dsp.h" + +#define BUILD_DATE "Dec 17 2001" +#define BUILD_TIME "18:25:00" + +u32 DSPCheckMailToDSP(void) { return (__DSPRegs[0] & (1 << 15)) >> 15; } + +u32 DSPCheckMailFromDSP(void) { return (__DSPRegs[2] & (1 << 15)) >> 15; } + +u32 DSPReadMailFromDSP(void) { return (__DSPRegs[2] << 16) | __DSPRegs[3]; } + +void DSPSendMailToDSP(u32 mail) +{ + __DSPRegs[0] = mail >> 16; + __DSPRegs[1] = mail & 0xFFFF; +} + +// void DSPAssertInt(void) +// { +// BOOL old; +// u16 tmp; + +// old = OSDisableInterrupts(); +// tmp = __DSPRegs[5]; +// tmp = (tmp & ~0xA8) | 2; +// __DSPRegs[5] = tmp; +// OSRestoreInterrupts(old); +// } + +// static int __DSP_init_flag; + +// void DSPInit(void) +// { +// BOOL old; +// u16 tmp; + +// __DSP_debug_printf("DSPInit(): Build Date: %s %s\n", BUILD_DATE, +// BUILD_TIME); + +// if (__DSP_init_flag == 1) +// return; + +// old = OSDisableInterrupts(); +// __OSSetInterruptHandler(7, __DSPHandler); +// __OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_DSP); + +// tmp = __DSPRegs[5]; +// tmp = (tmp & ~0xA8) | 0x800; +// __DSPRegs[5] = tmp; + +// tmp = __DSPRegs[5]; +// __DSPRegs[5] = tmp = tmp & ~0xAC; + +// __DSP_first_task = __DSP_last_task = __DSP_curr_task = __DSP_tmp_task +// = NULL; +// __DSP_init_flag = 1; + +// OSRestoreInterrupts(old); +// } diff --git a/src/static/GAEJ01_01/dolphin/dvd/__dvd.h b/src/static/GAEJ01_01/dolphin/dvd/__dvd.h new file mode 100644 index 00000000..5d63f2a0 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/__dvd.h @@ -0,0 +1,59 @@ +#ifndef _DOLPHIN_DVD_INTERNAL_H_ +#define _DOLPHIN_DVD_INTERNAL_H_ + +#include + +// dvd.c +BOOL DVDReadAbsAsyncPrio(DVDCommandBlock* block, void* addr, s32 length, s32 offset, DVDCBCallback callback, s32 prio); +BOOL DVDSeekAbsAsyncPrio(DVDCommandBlock* block, s32 offset, DVDCBCallback callback, s32 prio); +BOOL DVDReadAbsAsyncForBS(DVDCommandBlock* block, void* addr, s32 length, s32 offset, DVDCBCallback callback); +BOOL DVDReadDiskID(DVDCommandBlock* block, DVDDiskID* diskID, DVDCBCallback callback); +BOOL DVDPrepareStreamAbsAsync(DVDCommandBlock* block, u32 length, u32 offset, DVDCBCallback callback); +BOOL DVDCancelStreamAsync(DVDCommandBlock* block, DVDCBCallback callback); +BOOL DVDInquiryAsync(DVDCommandBlock* block, DVDDriveInfo* info, DVDCBCallback callback); +BOOL __DVDTestAlarm(OSAlarm* alarm); +void __DVDAudioBufferConfig(struct DVDCommandBlock * block, unsigned long enable, unsigned long size, void (* callback)(long, struct DVDCommandBlock *)); +void __DVDPrepareResetAsync(DVDCBCallback callback); + +// dvdFatal.c +void __DVDPrintFatalMessage(void); + +// dvderror.c +void __DVDStoreErrorCode(u32 error); + +// dvdfs.c +extern struct OSThreadQueue __DVDThreadQueue; +extern unsigned long __DVDLongFileNameFlag; + +void __DVDFSInit(); + +// dvdlow.c +void __DVDInitWA(void); +void __DVDInterruptHandler(short unused, struct OSContext * context); +void __DVDLowSetWAType(u32 type, u32 location); +BOOL DVDLowRead(void* addr, u32 length, u32 offset, DVDLowCallback callback); +BOOL DVDLowSeek(u32 offset, DVDLowCallback callback); +BOOL DVDLowWaitCoverClose(DVDLowCallback callback); +BOOL DVDLowReadDiskID(DVDDiskID* diskID, DVDLowCallback callback); +BOOL DVDLowStopMotor(DVDLowCallback callback); +BOOL DVDLowRequestError(DVDLowCallback callback); +BOOL DVDLowInquiry(DVDDriveInfo* info, DVDLowCallback callback); +BOOL DVDLowAudioStream(u32 subcmd, u32 length, u32 offset, DVDLowCallback callback); +BOOL DVDLowRequestAudioStatus(u32 subcmd, DVDLowCallback callback); +BOOL DVDLowAudioBufferConfig(BOOL enable, u32 size, DVDLowCallback callback); +void DVDLowReset(void); +BOOL DVDLowBreak(void); +BOOL __DVDLowTestAlarm(OSAlarm* alarm); + +// dvdqueue.c +void __DVDClearWaitingQueue(); +int __DVDPushWaitingQueue(long prio, struct DVDCommandBlock * block); +struct DVDCommandBlock * __DVDPopWaitingQueue(); +int __DVDCheckWaitingQueue(); +int __DVDDequeueWaitingQueue(struct DVDCommandBlock * block); +int __DVDIsBlockInWaitingQueue(struct DVDCommandBlock * block); + +// fstload.c +void __fstLoad(); + +#endif // _DOLPHIN_DVD_INTERNAL_H_ diff --git a/src/static/GAEJ01_01/dolphin/dvd/dvd.c b/src/static/GAEJ01_01/dolphin/dvd/dvd.c new file mode 100644 index 00000000..86d52f57 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/dvd.c @@ -0,0 +1,1349 @@ +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" + +const char* __DVDVersion = "<< Dolphin SDK - DVD\trelease build: Sep 16 2003 09:50:54 (0x2301) >>"; + +typedef void (*stateFunc)(DVDCommandBlock* block); + +static DVDBB2 BB2 ATTRIBUTE_ALIGN(32); +static DVDDiskID CurrDiskID ATTRIBUTE_ALIGN(32); +static DVDCommandBlock* executing; +static DVDDiskID* IDShouldBe; +static OSBootInfo* bootInfo; +static BOOL autoInvalidation = TRUE; +static volatile BOOL PauseFlag = FALSE; +static volatile BOOL PausingFlag = FALSE; +static volatile BOOL AutoFinishing = FALSE; +static volatile BOOL FatalErrorFlag = FALSE; +static vu32 CurrCommand; +static vu32 Canceling = FALSE; +static DVDCBCallback CancelCallback; +static vu32 ResumeFromHere = 0; +static vu32 CancelLastError; +static vu32 LastError; +static vs32 NumInternalRetry = 0; +static volatile BOOL ResetRequired; +static volatile BOOL FirstTimeInBootrom = FALSE; + +static DVDCommandBlock DummyCommandBlock; +static OSAlarm ResetAlarm; + +static BOOL DVDInitialized = FALSE; + +static void defaultOptionalCommandChecker(DVDCommandBlock* block, DVDLowCallback cb); +static DVDOptionalCommandChecker checkOptionalCommand = defaultOptionalCommandChecker; + +static stateFunc LastState; + +static void stateReadingFST(); +static void cbForStateReadingFST(u32 intType); +static void cbForStateError(u32 intType); +static void stateTimeout(); +static void stateGettingError(); +static u32 CategorizeError(u32 error); +static void cbForStateGettingError(u32 intType); +static void cbForUnrecoveredError(u32 intType); +static void cbForUnrecoveredErrorRetry(u32 intType); +static void stateGoToRetry(); +static void cbForStateGoToRetry(u32 intType); +static void stateCheckID(); +static void stateCheckID3(DVDCommandBlock* block); +static void stateCheckID2a(DVDCommandBlock* block); +static void cbForStateCheckID2a(u32 intType); +static void stateCheckID2(DVDCommandBlock* block); +static void cbForStateCheckID1(u32 intType); +static void cbForStateCheckID2(u32 intType); +static void cbForStateCheckID3(u32 intType); +static void AlarmHandler(OSAlarm* alarm, OSContext* context); +static void stateCoverClosed(); +static void stateCoverClosed_CMD(DVDCommandBlock* block); +static void cbForStateCoverClosed(u32 intType); +static void stateMotorStopped(); +static void cbForStateMotorStopped(u32 intType); +static void stateReady(); +static void stateBusy(DVDCommandBlock* block); +static void cbForStateBusy(u32 intType); +static void cbForCancelStreamSync(s32 result, DVDCommandBlock* block); +static void cbForCancelSync(s32 result, DVDCommandBlock* block); + +static void defaultOptionalCommandChecker(DVDCommandBlock* block, DVDLowCallback cb) { +} + +void DVDInit() { + if (DVDInitialized) { + return; + } + + OSRegisterVersion(__DVDVersion); + DVDInitialized = TRUE; + __DVDFSInit(); + __DVDClearWaitingQueue(); + __DVDInitWA(); + bootInfo = (OSBootInfo*)OSPhysicalToCached(0x0000); + IDShouldBe = &bootInfo->DVDDiskID; + __OSSetInterruptHandler(21, __DVDInterruptHandler); + __OSUnmaskInterrupts(0x400); + OSInitThreadQueue(&__DVDThreadQueue); + __DIRegs[0] = 42; + __DIRegs[1] = 0; + if (bootInfo->magic == 0xE5207C22) { + OSReport("load fst\n"); + __fstLoad(); + } else if (bootInfo->magic != 0x0D15EA5E) { + FirstTimeInBootrom = TRUE; + } +} + +static void stateReadingFST() { + LastState = (stateFunc)stateReadingFST; + + if (bootInfo->FSTMaxLength < BB2.FSTLength) { + OSErrorLine(650, "DVDChangeDisk(): FST in the new disc is too big. "); + } + + DVDLowRead(bootInfo->FSTLocation, OSRoundUp32B(BB2.FSTLength), BB2.FSTPosition, cbForStateReadingFST); +} + +static u32 DmaCommand[1] = { 0xFFFFFFFF }; + +static void cbForStateReadingFST(u32 intType) { + DVDCommandBlock* finished; + + if (intType == 16) { + executing->state = -1; + stateTimeout(); + } else if (intType & 1) { + NumInternalRetry = 0; + __DVDFSInit(); + finished = executing; + executing = &DummyCommandBlock; + finished->state = 0; + if (finished->callback) { + (finished->callback)(0, finished); + } + stateReady(); + } else { + stateGettingError(); + } +} + +static void cbForStateError(u32 intType) { + DVDCommandBlock* finished; + + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + __DVDPrintFatalMessage(); + + FatalErrorFlag = TRUE; + finished = executing; + executing = &DummyCommandBlock; + if (finished->callback) { + (finished->callback)(-1, finished); + } + + if (Canceling) { + Canceling = FALSE; + if (CancelCallback) + (CancelCallback)(0, finished); + } + + stateReady(); +} + +static void stateError(u32 error) { + __DVDStoreErrorCode(error); + DVDLowStopMotor(cbForStateError); +} + +static void stateTimeout() { + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); +} + +static void stateGettingError() { + DVDLowRequestError(cbForStateGettingError); +} + +static u32 CategorizeError(u32 error) { + if (error == 0x20400) { + LastError = error; + return 1; + } + + error &= 0xffffff; + + if ((error == 0x62800) || (error == 0x23a00) || (error == 0xb5a01)) { + return 0; + } + + ++NumInternalRetry; + if (NumInternalRetry == 2) { + if (error == LastError) { + LastError = error; + return 1; + } else { + LastError = error; + return 2; + } + } else { + LastError = error; + + if ((error == 0x31100) || (executing->command == 5)) { + return 2; + } else { + return 3; + } + } +} + +static BOOL CheckCancel(u32 resume) { + DVDCommandBlock* finished; + + if (Canceling) { + ResumeFromHere = resume; + Canceling = FALSE; + + finished = executing; + executing = &DummyCommandBlock; + + finished->state = 10; + if (finished->callback) + (*finished->callback)(-3, finished); + if (CancelCallback) + (CancelCallback)(0, finished); + stateReady(); + return TRUE; + } + return FALSE; +} + +static void cbForStateGettingError(u32 intType) { + u32 error; + u32 status; + u32 errorCategory; + u32 resume; + + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + if (intType & 2) { + executing->state = -1; + stateError(0x1234567); + return; + } + + error = __DIRegs[8]; + status = error & 0xff000000; + + errorCategory = CategorizeError(error); + + if (errorCategory == 1) { + executing->state = -1; + stateError(error); + return; + } + + if ((errorCategory == 2) || (errorCategory == 3)) { + resume = 0; + } else { + if (status == 0x01000000) + resume = 4; + else if (status == 0x02000000) + resume = 6; + else if (status == 0x03000000) + resume = 3; + else + resume = 5; + } + + if (CheckCancel(resume)) + return; + + if (errorCategory == 2) { + __DVDStoreErrorCode(error); + stateGoToRetry(); + return; + } + + if (errorCategory == 3) { + if ((error & 0x00ffffff) == 0x00031100) { + DVDLowSeek(executing->offset, cbForUnrecoveredError); + } else { + LastState(executing); + } + return; + } + + if (status == 0x01000000) { + executing->state = 5; + stateMotorStopped(); + return; + } else if (status == 0x02000000) { + executing->state = 3; + stateCoverClosed(); + return; + } else if (status == 0x03000000) { + executing->state = 4; + stateMotorStopped(); + return; + } else { + executing->state = -1; + stateError(0x1234567); + return; + } +} + +static void cbForUnrecoveredError(u32 intType) { + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + if (intType & 1) { + stateGoToRetry(); + return; + } + + DVDLowRequestError(cbForUnrecoveredErrorRetry); +} + +static void cbForUnrecoveredErrorRetry(u32 intType) { + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } + + executing->state = -1; + + if (intType & 2) { + __DVDStoreErrorCode(0x1234567); + DVDLowStopMotor(cbForStateError); + return; + } + + __DVDStoreErrorCode(__DIRegs[8]); + DVDLowStopMotor(cbForStateError); +} + +static void stateGoToRetry() { + DVDLowStopMotor(cbForStateGoToRetry); +} + +static void cbForStateGoToRetry(u32 intType) { + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + if (intType & 2) { + executing->state = -1; + stateError(0x1234567); + return; + } + + NumInternalRetry = 0; + + if ((CurrCommand == 4) || (CurrCommand == 5) || (CurrCommand == 13) || (CurrCommand == 15)) { + ResetRequired = TRUE; + } + + if (!CheckCancel(2)) { + executing->state = 11; + stateMotorStopped(); + } +} + +static void stateCheckID() { + switch (CurrCommand) { + case 3: + if (DVDCompareDiskID(&CurrDiskID, executing->id)) { + memcpy(IDShouldBe, &CurrDiskID, sizeof(DVDDiskID)); + executing->state = 1; + DCInvalidateRange(&BB2, sizeof(DVDBB2)); + LastState = stateCheckID2a; + stateCheckID2a(executing); + } else { + DVDLowStopMotor(cbForStateCheckID1); + } + break; + default: + if (memcmp(&CurrDiskID, IDShouldBe, sizeof(DVDDiskID))) { + DVDLowStopMotor(cbForStateCheckID1); + } else { + LastState = stateCheckID3; + stateCheckID3(executing); + } + break; + } +} + +static void stateCheckID3(DVDCommandBlock* block) { + DVDLowAudioBufferConfig(IDShouldBe->streaming, 10, cbForStateCheckID3); +} + +static void stateCheckID2a(DVDCommandBlock* block) { + DVDLowAudioBufferConfig(IDShouldBe->streaming, 10, cbForStateCheckID2a); +} + +static void cbForStateCheckID2a(u32 intType) { + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + } else if (intType & 1) { + NumInternalRetry = 0; + stateCheckID2(executing); + } else { + DVDLowRequestError(cbForStateGettingError); + } +} + +static void stateCheckID2(DVDCommandBlock* block) { + DVDLowRead(&BB2, OSRoundUp32B(sizeof(DVDBB2)), 0x420, cbForStateCheckID2); +} + +static void cbForStateCheckID1(u32 intType) { + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + if (intType & 2) { + executing->state = -1; + stateError(0x1234567); + return; + } + + NumInternalRetry = 0; + + if (!CheckCancel(1)) { + executing->state = 6; + stateMotorStopped(); + } +} + +static void cbForStateCheckID2(u32 intType) { + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + if (intType & 1) { + NumInternalRetry = 0; + stateReadingFST(); + } else { + stateGettingError(); + } +} + +static void cbForStateCheckID3(u32 intType) { + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + if (intType & 1) { + NumInternalRetry = 0; + + if (!CheckCancel(0)) { + executing->state = 1; + stateBusy(executing); + } + } else { + stateGettingError(); + } +} + +static void AlarmHandler(OSAlarm* alarm, OSContext* context) { + DVDReset(); + DCInvalidateRange(&CurrDiskID, sizeof(DVDDiskID)); + LastState = stateCoverClosed_CMD; + stateCoverClosed_CMD(executing); +} + +static void stateCoverClosed() { + DVDCommandBlock* finished; + + switch (CurrCommand) { + case 4: + case 5: + case 13: + case 15: + __DVDClearWaitingQueue(); + finished = executing; + executing = &DummyCommandBlock; + if (finished->callback) { + (finished->callback)(-4, finished); + } + stateReady(); + break; + default: + DVDReset(); + OSCreateAlarm(&ResetAlarm); + OSSetAlarm(&ResetAlarm, OSMillisecondsToTicks(1150), AlarmHandler); + break; + } +} + +static void stateCoverClosed_CMD(DVDCommandBlock* block) { + DVDLowReadDiskID(&CurrDiskID, cbForStateCoverClosed); +} + +static void cbForStateCoverClosed(u32 intType) { + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + if (intType & 1) { + NumInternalRetry = 0; + stateCheckID(); + } else { + stateGettingError(); + } +} + +static void stateMotorStopped() { + DVDLowWaitCoverClose(cbForStateMotorStopped); +} + +static void cbForStateMotorStopped(u32 intType) { + __DIRegs[1] = 0; + executing->state = 3; + stateCoverClosed(); +} + +static void stateReady() { + DVDCommandBlock* finished; + + if (!__DVDCheckWaitingQueue()) { + executing = NULL; + return; + } + + if (PauseFlag) { + PausingFlag = TRUE; + executing = NULL; + return; + } + + executing = __DVDPopWaitingQueue(); + + if (FatalErrorFlag) { + executing->state = -1; + finished = executing; + executing = &DummyCommandBlock; + if (finished->callback) { + (finished->callback)(-1, finished); + } + stateReady(); + return; + } + + CurrCommand = executing->command; + + if (ResumeFromHere) { + switch (ResumeFromHere) { + case 2: + executing->state = 11; + stateMotorStopped(); + break; + case 3: + executing->state = 4; + stateMotorStopped(); + break; + case 4: + executing->state = 5; + stateMotorStopped(); + break; + case 1: + case 7: + case 6: + executing->state = 3; + stateCoverClosed(); + break; + case 5: + executing->state = -1; + stateError(CancelLastError); + break; + } + + ResumeFromHere = 0; + } else { + executing->state = 1; + stateBusy(executing); + } +} + +#define DVDMIN(a, b) (((a) > (b)) ? (b) : (a)) + +static void stateBusy(DVDCommandBlock* block) { + DVDCommandBlock* finished; + + LastState = stateBusy; + + switch (block->command) { + case 5: + __DIRegs[1] = __DIRegs[1]; + block->currTransferSize = sizeof(DVDDiskID); + DVDLowReadDiskID(block->addr, cbForStateBusy); + break; + case 1: + case 4: + if (!block->length) { + finished = executing; + executing = &DummyCommandBlock; + finished->state = 0; + if (finished->callback) { + finished->callback(0, finished); + } + stateReady(); + } else { + __DIRegs[1] = __DIRegs[1]; + block->currTransferSize = DVDMIN(block->length - block->transferredSize, 0x80000); + DVDLowRead((void*)((u8*)block->addr + block->transferredSize), block->currTransferSize, + block->offset + block->transferredSize, cbForStateBusy); + } + break; + case 2: + __DIRegs[1] = __DIRegs[1]; + DVDLowSeek(block->offset, cbForStateBusy); + break; + case 3: + DVDLowStopMotor(cbForStateBusy); + break; + case 15: + DVDLowStopMotor(cbForStateBusy); + break; + case 6: + __DIRegs[1] = __DIRegs[1]; + if (AutoFinishing) { + executing->currTransferSize = 0; + DVDLowRequestAudioStatus(0, cbForStateBusy); + } else { + executing->currTransferSize = 1; + DVDLowAudioStream(0, block->length, block->offset, cbForStateBusy); + } + break; + case 7: + __DIRegs[1] = __DIRegs[1]; + DVDLowAudioStream(0x10000, 0, 0, cbForStateBusy); + break; + case 8: + __DIRegs[1] = __DIRegs[1]; + AutoFinishing = TRUE; + DVDLowAudioStream(0, 0, 0, cbForStateBusy); + break; + case 9: + __DIRegs[1] = __DIRegs[1]; + DVDLowRequestAudioStatus(0, cbForStateBusy); + break; + case 10: + __DIRegs[1] = __DIRegs[1]; + DVDLowRequestAudioStatus(0x10000, cbForStateBusy); + break; + case 11: + __DIRegs[1] = __DIRegs[1]; + DVDLowRequestAudioStatus(0x20000, cbForStateBusy); + break; + case 12: + __DIRegs[1] = __DIRegs[1]; + DVDLowRequestAudioStatus(0x30000, cbForStateBusy); + break; + case 13: + __DIRegs[1] = __DIRegs[1]; + DVDLowAudioBufferConfig(block->offset, block->length, cbForStateBusy); + break; + case 14: + __DIRegs[1] = __DIRegs[1]; + block->currTransferSize = sizeof(DVDDriveInfo); + DVDLowInquiry(block->addr, cbForStateBusy); + break; + default: + checkOptionalCommand(block, cbForStateBusy); + break; + } +} + +static u32 ImmCommand[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + +static BOOL IsImmCommandWithResult(u32 command) { + u32 i; + + if (command == 9 || command == 10 || command == 11 || command == 12) { + return TRUE; + } + + for (i = 0; i < sizeof(ImmCommand) / sizeof(ImmCommand[0]); i++) { + if (command == ImmCommand[i]) + return TRUE; + } + + return FALSE; +} + +static BOOL IsDmaCommand(u32 command) { + u32 i; + + if (command == 1 || command == 4 || command == 5 || command == 14) + return TRUE; + + for (i = 0; i < sizeof(DmaCommand) / sizeof(DmaCommand[0]); i++) { + if (command == DmaCommand[i]) + return TRUE; + } + + return FALSE; +} + +static void cbForStateBusy(u32 intType) { + DVDCommandBlock* finished; + + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + + if ((CurrCommand == 3) || (CurrCommand == 15)) { + if (intType & 2) { + executing->state = -1; + stateError(0x1234567); + return; + } + + NumInternalRetry = 0; + + if (CurrCommand == 15) { + ResetRequired = TRUE; + } + + if (CheckCancel(7)) { + return; + } + + executing->state = 7; + stateMotorStopped(); + return; + } + + if (IsDmaCommand(CurrCommand)) { + executing->transferredSize += executing->currTransferSize - __DIRegs[6]; + } + + if (intType & 8) { + Canceling = FALSE; + finished = executing; + executing = &DummyCommandBlock; + + finished->state = 10; + if (finished->callback) { + (*finished->callback)(-3, finished); + } + if (CancelCallback) { + (CancelCallback)(0, finished); + } + stateReady(); + return; + } + + if (intType & 1) { + NumInternalRetry = 0; + + if (CheckCancel(0)) + return; + + if (IsDmaCommand(CurrCommand)) { + if (executing->transferredSize != executing->length) { + stateBusy(executing); + return; + } + + finished = executing; + executing = &DummyCommandBlock; + + finished->state = 0; + if (finished->callback) { + (finished->callback)((s32)finished->transferredSize, finished); + } + stateReady(); + } else if (IsImmCommandWithResult(CurrCommand)) { + s32 result; + + if ((CurrCommand == 11) || (CurrCommand == 10)) { + result = (s32)(__DIRegs[8] << 2); + } else { + result = (s32)__DIRegs[8]; + } + finished = executing; + executing = &DummyCommandBlock; + + finished->state = 0; + if (finished->callback) { + (finished->callback)(result, finished); + } + stateReady(); + } else if (CurrCommand == 6) { + if (executing->currTransferSize == 0) { + if (__DIRegs[8] & 1) { + finished = executing; + executing = &DummyCommandBlock; + + finished->state = 9; + if (finished->callback) { + (finished->callback)(-2, finished); + } + stateReady(); + } else { + AutoFinishing = FALSE; + executing->currTransferSize = 1; + DVDLowAudioStream(0, executing->length, executing->offset, cbForStateBusy); + } + } else { + finished = executing; + executing = &DummyCommandBlock; + + finished->state = 0; + if (finished->callback) { + (finished->callback)(0, finished); + } + stateReady(); + } + } else { + finished = executing; + executing = &DummyCommandBlock; + + finished->state = 0; + if (finished->callback) { + (finished->callback)(0, finished); + } + stateReady(); + } + } else { + if (CurrCommand == 14) { + executing->state = -1; + stateError(0x01234567); + return; + } + + if ((CurrCommand == 1 || CurrCommand == 4 || CurrCommand == 5 || CurrCommand == 14) + && (executing->transferredSize == executing->length)) { + if (CheckCancel(0)) { + return; + } + finished = executing; + executing = &DummyCommandBlock; + + finished->state = 0; + if (finished->callback) { + (finished->callback)((s32)finished->transferredSize, finished); + } + stateReady(); + return; + } + + stateGettingError(); + } +} + +static BOOL issueCommand(s32 prio, DVDCommandBlock* block) { + BOOL level; + BOOL result; + + if (autoInvalidation && (block->command == 1 || block->command == 4 || block->command == 5 || block->command == 14)) { + DCInvalidateRange(block->addr, block->length); + } + + level = OSDisableInterrupts(); + + block->state = 2; + result = __DVDPushWaitingQueue(prio, block); + + if ((executing == NULL) && (PauseFlag == FALSE)) { + stateReady(); + } + + OSRestoreInterrupts(level); + + return result; +} + +BOOL DVDReadAbsAsyncPrio(DVDCommandBlock* block, void* addr, s32 length, s32 offset, DVDCBCallback callback, s32 prio) { + BOOL idle; + + block->command = 1; + block->addr = addr; + block->length = length; + block->offset = offset; + block->transferredSize = 0; + block->callback = callback; + + idle = issueCommand(prio, block); + return idle; +} + +BOOL DVDSeekAbsAsyncPrio(DVDCommandBlock* block, s32 offset, DVDCBCallback callback, s32 prio) { + BOOL idle; + + block->command = 2; + block->offset = offset; + block->callback = callback; + + idle = issueCommand(prio, block); + return idle; +} + +BOOL DVDReadAbsAsyncForBS(DVDCommandBlock* block, void* addr, s32 length, s32 offset, DVDCBCallback callback) { + BOOL idle; + + block->command = 4; + block->addr = addr; + block->length = length; + block->offset = offset; + block->transferredSize = 0; + block->callback = callback; + + idle = issueCommand(2, block); + return idle; +} + +BOOL DVDReadDiskID(DVDCommandBlock* block, DVDDiskID* diskID, DVDCBCallback callback) { + BOOL idle; + + block->command = 5; + block->addr = diskID; + block->length = sizeof(DVDDiskID); + block->offset = 0; + block->transferredSize = 0; + block->callback = callback; + + idle = issueCommand(2, block); + return idle; +} + +BOOL DVDPrepareStreamAbsAsync(DVDCommandBlock* block, u32 length, u32 offset, DVDCBCallback callback) { + BOOL idle; + + block->command = 6; + block->length = length; + block->offset = offset; + block->callback = callback; + + idle = issueCommand(1, block); + return idle; +} + +BOOL DVDCancelStreamAsync(DVDCommandBlock* block, DVDCBCallback callback) { + BOOL idle; + + block->command = 7; + block->callback = callback; + idle = issueCommand(1, block); + return idle; +} + +s32 DVDCancelStream(DVDCommandBlock* block) { + BOOL result; + s32 state; + BOOL enabled; + s32 retVal; + + result = DVDCancelStreamAsync(block, cbForCancelStreamSync); + + if (result == FALSE) { + return -1; + } + + enabled = OSDisableInterrupts(); + + while (TRUE) { + state = ((volatile DVDCommandBlock*)block)->state; + + if (state == 0 || state == -1 || state == 10) { + retVal = (s32)block->transferredSize; + break; + } + + OSSleepThread(&__DVDThreadQueue); + } + + OSRestoreInterrupts(enabled); + return retVal; +} + +static void cbForCancelStreamSync(s32 result, DVDCommandBlock* block) { + block->transferredSize = (u32)result; + OSWakeupThread(&__DVDThreadQueue); +} + +BOOL DVDChangeDiskAsync(DVDCommandBlock* block, DVDDiskID* id, DVDCBCallback callback) { + BOOL idle; + + if (id->company[0] == '\0' && id->company[1] == '\0') { + OSErrorLine(2287, "DVDChangeDiskAsync(): You can't specify NULL to company name. \n"); + } + + block->command = 3; + block->id = id; + block->callback = callback; + + DCInvalidateRange(bootInfo->FSTLocation, bootInfo->FSTMaxLength); + + idle = issueCommand(2, block); + return idle; +} + +BOOL DVDInquiryAsync(DVDCommandBlock* block, DVDDriveInfo* info, DVDCBCallback callback) { + BOOL idle; + + block->command = 14; + block->addr = (void*)info; + block->length = sizeof(DVDDriveInfo); + block->transferredSize = 0; + block->callback = callback; + + idle = issueCommand(2, block); + return idle; +} + +void DVDReset() { + DVDLowReset(); + __DIRegs[0] = 42; + __DIRegs[1] = __DIRegs[1]; + ResetRequired = FALSE; + ResumeFromHere = 0; +} + +s32 DVDGetCommandBlockStatus(const DVDCommandBlock* block) { + BOOL enabled; + s32 retVal; + + enabled = OSDisableInterrupts(); + + if (block->state == 3) { + retVal = 1; + } else { + retVal = block->state; + } + + OSRestoreInterrupts(enabled); + return retVal; +} + +s32 DVDGetDriveStatus() { + BOOL enabled; + s32 retVal; + + enabled = OSDisableInterrupts(); + + if (FatalErrorFlag) { + retVal = DVD_STATE_FATAL_ERROR; + } else if (PausingFlag) { + retVal = DVD_STATE_PAUSING; + } else { + if (executing == NULL) { + retVal = DVD_STATE_END; + } else if (executing == &DummyCommandBlock) { + retVal = DVD_STATE_END; + } else { + retVal = DVDGetCommandBlockStatus(executing); + } + } + + OSRestoreInterrupts(enabled); + return retVal; +} + +BOOL DVDSetAutoInvalidation(BOOL autoInval) { + BOOL prev; + + prev = autoInvalidation; + autoInvalidation = autoInval; + return prev; +} + +void DVDPause() { + BOOL level; + + level = OSDisableInterrupts(); + PauseFlag = TRUE; + if (executing == NULL) { + PausingFlag = TRUE; + } + OSRestoreInterrupts(level); +} + +void DVDResume() { + BOOL level; + + level = OSDisableInterrupts(); + PauseFlag = FALSE; + if (PausingFlag) { + PausingFlag = FALSE; + stateReady(); + } + OSRestoreInterrupts(level); +} + +BOOL DVDCancelAsync(DVDCommandBlock* block, DVDCBCallback callback) { + BOOL enabled; + DVDLowCallback old; + DVDCommandBlock* finished; + + enabled = OSDisableInterrupts(); + + switch (block->state) { + case -1: + case 0: + case 10: + if (callback) + (*callback)(0, block); + break; + case 1: + if (Canceling) { + OSRestoreInterrupts(enabled); + return FALSE; + } + + Canceling = TRUE; + CancelCallback = callback; + if (block->command == 4 || block->command == 1) { + DVDLowBreak(); + } + break; + case 2: + __DVDDequeueWaitingQueue(block); + block->state = 10; + if (block->callback) + (block->callback)(-3, block); + if (callback) + (*callback)(0, block); + break; + case 3: + switch (block->command) { + case 5: + case 4: + case 13: + case 15: + if (callback) + (*callback)(0, block); + break; + default: + if (Canceling) { + OSRestoreInterrupts(enabled); + return FALSE; + } + Canceling = TRUE; + CancelCallback = callback; + break; + } + break; + case 4: + case 5: + case 6: + case 7: + case 11: + old = DVDLowClearCallback(); + if (old != cbForStateMotorStopped) { + OSRestoreInterrupts(enabled); + return FALSE; + } + + if (block->state == 4) + ResumeFromHere = 3; + if (block->state == 5) + ResumeFromHere = 4; + if (block->state == 6) + ResumeFromHere = 1; + if (block->state == 11) + ResumeFromHere = 2; + if (block->state == 7) + ResumeFromHere = 7; + + finished = executing; + executing = &DummyCommandBlock; + block->state = 10; + if (block->callback) { + (block->callback)(-3, block); + } + if (callback) { + (callback)(0, block); + } + stateReady(); + break; + } + + OSRestoreInterrupts(enabled); + return TRUE; +} + +s32 DVDCancel(volatile DVDCommandBlock* block) { + BOOL result; + s32 state; + u32 command; + BOOL enabled; + + result = DVDCancelAsync((DVDCommandBlock*)block, cbForCancelSync); + + if (result == FALSE) { + return -1; + } + + enabled = OSDisableInterrupts(); + + for (;;) { + state = block->state; + + if ((state == 0) || (state == -1) || (state == 10)) { + break; + } + + if (state == 3) { + command = block->command; + + if ((command == 4) || (command == 5) || (command == 13) || (command == 15)) { + break; + } + } + + OSSleepThread(&__DVDThreadQueue); + } + + OSRestoreInterrupts(enabled); + return 0; +} + +static void cbForCancelSync(s32 result, DVDCommandBlock* block) { + OSWakeupThread(&__DVDThreadQueue); +} + +BOOL DVDCancelAllAsync(DVDCBCallback callback) { + BOOL enabled; + DVDCommandBlock* p; + BOOL retVal; + + enabled = OSDisableInterrupts(); + DVDPause(); + + while ((p = __DVDPopWaitingQueue()) != 0) { + DVDCancelAsync(p, NULL); + } + + if (executing) + retVal = DVDCancelAsync(executing, callback); + else { + retVal = TRUE; + if (callback) + (*callback)(0, NULL); + } + + DVDResume(); + OSRestoreInterrupts(enabled); + return retVal; +} + +DVDDiskID* DVDGetCurrentDiskID() { + return (DVDDiskID*)OSPhysicalToCached(0); +} + +BOOL DVDCheckDisk() { + BOOL enabled; + s32 result; + s32 state; + u32 coverReg; + + enabled = OSDisableInterrupts(); + + if (FatalErrorFlag) { + state = -1; + } else if (PausingFlag) { + state = 8; + } else { + if (executing == NULL) { + state = 0; + } else if (executing == &DummyCommandBlock) { + state = 0; + } else { + state = executing->state; + } + } + + switch (state) { + case 1: + case 9: + case 10: + case 2: + result = TRUE; + break; + case -1: + case 11: + case 7: + case 3: + case 4: + case 5: + case 6: + result = FALSE; + break; + case 0: + case 8: + coverReg = __DIRegs[1]; + if (((coverReg >> 2) & 1) || (coverReg & 1)) { + result = FALSE; + } else if (ResumeFromHere != 0) { + result = FALSE; + } else { + result = TRUE; + } + } + + OSRestoreInterrupts(enabled); + + return result; +} + +void __DVDPrepareResetAsync(DVDCBCallback callback) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + + __DVDClearWaitingQueue(); + + if (Canceling) { + CancelCallback = callback; + } else { + if (executing) { + executing->callback = NULL; + } + + DVDCancelAllAsync(callback); + } + + OSRestoreInterrupts(enabled); +} + +BOOL __DVDTestAlarm(OSAlarm* alarm) { + return (alarm == &ResetAlarm) ? TRUE : __DVDLowTestAlarm(alarm); +} diff --git a/src/static/GAEJ01_01/dolphin/dvd/dvdFatal.c b/src/static/GAEJ01_01/dolphin/dvd/dvdFatal.c new file mode 100644 index 00000000..9da9993f --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/dvdFatal.c @@ -0,0 +1,12 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" + +static void (*FatalFunc)(); + +void __DVDPrintFatalMessage(void) { + if (FatalFunc) { + (*FatalFunc)(); + } +} diff --git a/src/static/GAEJ01_01/dolphin/dvd/dvderror.c b/src/static/GAEJ01_01/dolphin/dvd/dvderror.c new file mode 100644 index 00000000..fcf8bd3a --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/dvderror.c @@ -0,0 +1,78 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" + +static u32 ErrorTable[18] = { + 0x00000000, + 0x00023A00, + 0x00062800, + 0x00030200, + 0x00031100, + 0x00052000, + 0x00052001, + 0x00052100, + 0x00052400, + 0x00052401, + 0x00052402, + 0x000B5A01, + 0x00056300, + 0x00020401, + 0x00020400, + 0x00040800, + 0x00100007, + 0x00000000, +}; + +#define DIDNT_MATCH 29 + +static u8 ErrorCode2Num(u32 errorCode) { + u32 i; + + for (i = 0; i < 18; i++) { + if (errorCode == ErrorTable[i]) { + ASSERTLINE(0x49, i < DIDNT_MATCH); + return i; + } + } + + if (errorCode >= 0x100000 && errorCode <= 0x100008) { + return 17; + } + + return DIDNT_MATCH; +} + +static u8 Convert(u32 error) { + u32 statusCode; + u32 errorCode; + u8 errorNum; + + if (error == 0x01234567) { + return -1; + } else if (error == 0x01234568) { + return -2; + } + + statusCode = (error >> 24) & 0xFF; + errorCode = error & 0x00FFFFFF; + errorNum = ErrorCode2Num(errorCode); + if (statusCode >= 6) { + statusCode = 6; + } + + return statusCode * 30 + errorNum; +} + +void __DVDStoreErrorCode(u32 error) +{ + OSSramEx* sram; + u8 num; + + num = Convert(error); + sram = __OSLockSramEx(); + sram->dvdErrorCode = num; + __OSUnlockSramEx(TRUE); +} diff --git a/src/static/GAEJ01_01/dolphin/dvd/dvdfs.c b/src/static/GAEJ01_01/dolphin/dvd/dvdfs.c new file mode 100644 index 00000000..a7fe6bb6 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/dvdfs.c @@ -0,0 +1,665 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" + +struct FSTEntry { + /* 0x00 */ u32 isDirAndStringOff; + /* 0x04 */ u32 parentOrPosition; + /* 0x08 */ u32 nextEntryOrLength; +}; + +// .sbss +static struct OSBootInfo_s * BootInfo; // size: 0x4, address: 0x0 +static struct FSTEntry * FstStart; // size: 0x4, address: 0x4 +static char * FstStringStart; // size: 0x4, address: 0x8 +static unsigned long MaxEntryNum; // size: 0x4, address: 0xC +static unsigned long currentDirectory; // size: 0x4, address: 0x10 +struct OSThreadQueue __DVDThreadQueue; // size: 0x8, address: 0x18 +unsigned long __DVDLongFileNameFlag; // size: 0x4, address: 0x14 + +// functions +static BOOL isSame(const char* path, const char* string); +static u32 myStrncpy(char* dest, char* src, u32 maxlen); +static u32 entryToPath(u32 entry, char* path, u32 maxlen); +static BOOL DVDConvertEntrynumToPath(s32 entrynum, char* path, u32 maxlen); +static void cbForReadAsync(s32 result, DVDCommandBlock* block); +static void cbForReadSync(); +static void cbForSeekAsync(long result, struct DVDCommandBlock * block); +static void cbForSeekSync(); +static void cbForPrepareStreamAsync(s32 result, DVDCommandBlock* block); +static void cbForPrepareStreamSync(); + +void __DVDFSInit() { + BootInfo = (void*)OSPhysicalToCached(0); + FstStart = BootInfo->FSTLocation; + if (FstStart) { + MaxEntryNum = FstStart->nextEntryOrLength; + FstStringStart = (char*)FstStart + (MaxEntryNum * 0xC); + } +} + +/* For convenience */ +#define entryIsDir(i) (((FstStart[i].isDirAndStringOff & 0xff000000) == 0) ? FALSE : TRUE) +#define stringOff(i) (FstStart[i].isDirAndStringOff & ~0xff000000) +#define parentDir(i) (FstStart[i].parentOrPosition) +#define nextDir(i) (FstStart[i].nextEntryOrLength) +#define filePosition(i) (FstStart[i].parentOrPosition) +#define fileLength(i) (FstStart[i].nextEntryOrLength) + +static BOOL isSame(const char* path, const char* string) { + while (*string != '\0') { + if (tolower(*path++) != tolower(*string++)) { + return FALSE; + } + } + + if ((*path == '/') || (*path == '\0')) { + return TRUE; + } + + return FALSE; +} + +s32 DVDConvertPathToEntrynum(char* pathPtr) { + const char* ptr; + char* stringPtr; + BOOL isDir; + u32 length; + u32 dirLookAt; + u32 i; + const char* origPathPtr = pathPtr; + const char* extentionStart; + BOOL illegal; + BOOL extention; + + ASSERTMSGLINE(0x133, pathPtr, "DVDConvertPathToEntrynum(): null pointer is specified "); + + dirLookAt = currentDirectory; + + while (1) { + if (*pathPtr == '\0') { + return (s32)dirLookAt; + } else if (*pathPtr == '/') { + dirLookAt = 0; + pathPtr++; + continue; + } else if (*pathPtr == '.') { + if (*(pathPtr + 1) == '.') { + if (*(pathPtr + 2) == '/') { + dirLookAt = parentDir(dirLookAt); + pathPtr += 3; + continue; + } else if (*(pathPtr + 2) == '\0') { + return (s32)parentDir(dirLookAt); + } + } else if (*(pathPtr + 1) == '/') { + pathPtr += 2; + continue; + } else if (*(pathPtr + 1) == '\0') { + return (s32)dirLookAt; + } + } + + if (__DVDLongFileNameFlag == 0) { + extention = FALSE; + illegal = FALSE; + + for (ptr = pathPtr; (*ptr != '\0') && (*ptr != '/'); ptr++) { + if (*ptr == '.') { + if ((ptr - pathPtr > 8) || (extention == TRUE)) { + illegal = TRUE; + break; + } + extention = TRUE; + extentionStart = ptr + 1; + + } else if (*ptr == ' ') + illegal = TRUE; + } + + if ((extention == TRUE) && (ptr - extentionStart > 3)) + illegal = TRUE; + + if (illegal) + OSPanic(__FILE__, 0x183, + "DVDConvertEntrynumToPath(possibly DVDOpen or DVDChangeDir or DVDOpenDir): " + "specified directory or file (%s) doesn't match standard 8.3 format. This is a " + "temporary restriction and will be removed soon\n", + origPathPtr); + } else { + for (ptr = pathPtr; (*ptr != '\0') && (*ptr != '/'); ptr++) + ; + } + + isDir = (*ptr == '\0') ? FALSE : TRUE; + length = (u32)(ptr - pathPtr); + + ptr = pathPtr; + + for (i = dirLookAt + 1; i < nextDir(dirLookAt); i = entryIsDir(i) ? nextDir(i) : (i + 1)) { + if ((entryIsDir(i) == FALSE) && (isDir == TRUE)) { + continue; + } + + stringPtr = FstStringStart + stringOff(i); + + if (isSame(ptr, stringPtr) == TRUE) { + goto next_hier; + } + } + + return -1; + +next_hier: + if (!isDir) { + return (s32)i; + } + + dirLookAt = i; + pathPtr += length + 1; + } +} + +BOOL DVDFastOpen(s32 entrynum, DVDFileInfo* fileInfo) { + ASSERTMSGLINE(0x1BC, fileInfo, "DVDFastOpen(): null pointer is specified to file info address "); + ASSERTMSG1LINE(0x1BF, (entrynum >= 0) && ((u32) entrynum < (u32) MaxEntryNum), "DVDFastOpen(): specified entry number '%d' is out of range ", entrynum); + ASSERTMSG1LINE(0x1C2, !entryIsDir(entrynum), "DVDFastOpen(): entry number '%d' is assigned to a directory ", entrynum); + + if ((entrynum < 0) || (entrynum >= MaxEntryNum) || entryIsDir(entrynum)) { + return FALSE; + } + + fileInfo->startAddr = filePosition(entrynum); + fileInfo->length = fileLength(entrynum); + fileInfo->callback = (DVDCallback)NULL; + fileInfo->cb.state = DVD_STATE_END; + + return TRUE; +} + +BOOL DVDOpen(char* fileName, DVDFileInfo* fileInfo) { + s32 entry; + char currentDir[128]; + + ASSERTMSGLINE(0x1E0, fileName, "DVDOpen(): null pointer is specified to file name "); + ASSERTMSGLINE(0x1E1, fileInfo, "DVDOpen(): null pointer is specified to file info address "); + + entry = DVDConvertPathToEntrynum(fileName); + + if (0 > entry) { + DVDGetCurrentDir(currentDir, 128); + OSReport("Warning: DVDOpen(): file '%s' was not found under %s.\n", fileName, currentDir); + return FALSE; + } + + if (entryIsDir(entry)) { + ASSERTMSG1LINE(0x1EF, !entryIsDir(entry), "DVDOpen(): directory '%s' is specified as a filename ", fileName); + return FALSE; + } + + fileInfo->startAddr = filePosition(entry); + fileInfo->length = fileLength(entry); + fileInfo->callback = (DVDCallback)NULL; + fileInfo->cb.state = DVD_STATE_END; + + return TRUE; +} + +BOOL DVDClose(DVDFileInfo* fileInfo) { + ASSERTMSGLINE(0x207, fileInfo, "DVDClose(): null pointer is specified to file info address "); + DVDCancel(&(fileInfo->cb)); + return TRUE; +} + +static u32 myStrncpy(char* dest, char* src, u32 maxlen) { + u32 i = maxlen; + + while ((i > 0) && (*src != 0)) { + *dest++ = *src++; + i--; + } + + return (maxlen - i); +} + +static u32 entryToPath(u32 entry, char* path, u32 maxlen) { + char* name; + u32 loc; + + if (entry == 0) { + return 0; + } + + name = FstStringStart + stringOff(entry); + + loc = entryToPath(parentDir(entry), path, maxlen); + + if (loc == maxlen) { + return loc; + } + + *(path + loc++) = '/'; + + loc += myStrncpy(path + loc, name, maxlen - loc); + + return loc; +} + +static BOOL DVDConvertEntrynumToPath(s32 entrynum, char* path, u32 maxlen) { + u32 loc; + + ASSERTMSG1LINE(0x263, (entrynum >= 0) && (entrynum < MaxEntryNum), "DVDConvertEntrynumToPath: specified entrynum(%d) is out of range ", entrynum); + ASSERTMSG1LINE(0x265, maxlen > 1, "DVDConvertEntrynumToPath: maxlen should be more than 1 (%d is specified)", maxlen); + ASSERTMSGLINE(0x26A, entryIsDir(entrynum), "DVDConvertEntrynumToPath: cannot convert an entry num for a file to path "); + + loc = entryToPath((u32)entrynum, path, maxlen); + + if (loc == maxlen) { + path[maxlen - 1] = '\0'; + return FALSE; + } + + if (entryIsDir(entrynum)) { + if (loc == maxlen - 1) { + path[loc] = '\0'; + return FALSE; + } + + path[loc++] = '/'; + } + + path[loc] = '\0'; + return TRUE; +} + +BOOL DVDGetCurrentDir(char* path, u32 maxlen) { + ASSERTMSG1LINE(0x294, (maxlen > 1), "DVDGetCurrentDir: maxlen should be more than 1 (%d is specified)", maxlen); + return DVDConvertEntrynumToPath((s32)currentDirectory, path, maxlen); +} + +BOOL DVDChangeDir(char* dirName) { + s32 entry; + char currentDir[128]; + + ASSERTMSGLINE(0x2AA, dirName, "DVDChangeDir(): null pointer is specified to directory name "); + entry = DVDConvertPathToEntrynum(dirName); + ASSERTMSG2LINE(0x2B2, entry >= 0, "DVDChangeDir(): directory '%s' is not found under %s ", dirName, (DVDGetCurrentDir(currentDir, 128), currentDir)); + ASSERTMSG1LINE(0x2B6, entryIsDir(entry), "DVDChangeDir(): file '%s' is specified as a directory name ", dirName); + + if ((entry < 0) || (entryIsDir(entry) == FALSE)) { + return FALSE; + } + + currentDirectory = (u32)entry; + + return TRUE; +} + +BOOL DVDReadAsyncPrio(DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset, + DVDCallback callback, s32 prio) { + + ASSERTMSGLINE(0x2D5, fileInfo, "DVDReadAsync(): null pointer is specified to file info address "); + ASSERTMSGLINE(0x2D6, addr, "DVDReadAsync(): null pointer is specified to addr "); + ASSERTMSGLINE(0x2DA, !OFFSET(addr, 32), "DVDReadAsync(): address must be aligned with 32 byte boundaries "); + ASSERTMSGLINE(0x2DC, !(length & 0x1F), "DVDReadAsync(): length must be multiple of 32 byte "); + ASSERTMSGLINE(0x2DE, !(offset & 3), "DVDReadAsync(): offset must be multiple of 4 byte "); + + if (!((0 <= offset) && (offset <= fileInfo->length))) { + OSPanic(__FILE__, 0x2EE, "DVDReadAsync(): specified area is out of the file "); + } + + if (!((0 <= offset + length) && (offset + length < fileInfo->length + DVD_MIN_TRANSFER_SIZE))) { + OSPanic(__FILE__, 0x2F4, "DVDReadAsync(): specified area is out of the file "); + } + + fileInfo->callback = callback; + DVDReadAbsAsyncPrio(&(fileInfo->cb), addr, length, (s32)(fileInfo->startAddr + offset), + cbForReadAsync, prio); + + return TRUE; +} +#ifndef offsetof +#define offsetof(type, memb) ((u32) & ((type*)0)->memb) +#endif + +static void cbForReadAsync(s32 result, DVDCommandBlock* block) { + DVDFileInfo* fileInfo; + + fileInfo = (DVDFileInfo*)((char*)block - offsetof(DVDFileInfo, cb)); + ASSERTLINE(0x2FB, (void*) &fileInfo->cb == (void*) block); + if (fileInfo->callback) { + (fileInfo->callback)(result, fileInfo); + } +} + +long DVDReadPrio(struct DVDFileInfo * fileInfo, void * addr, long length, long offset, long prio) { + int result; + struct DVDCommandBlock * block; + long state; + int enabled; + long retVal; + + ASSERTMSGLINE(0x31B, fileInfo, "DVDRead(): null pointer is specified to file info address "); + ASSERTMSGLINE(0x31C, addr, "DVDRead(): null pointer is specified to addr "); + ASSERTMSGLINE(0x320, !OFFSET(addr, 32), "DVDRead(): address must be aligned with 32 byte boundaries "); + ASSERTMSGLINE(0x322, !(length & 0x1F), "DVDRead(): length must be multiple of 32 byte "); + ASSERTMSGLINE(0x324, !(offset & 3), "DVDRead(): offset must be multiple of 4 byte "); + + if (!((0 <= offset) && (offset <= fileInfo->length))) { + OSPanic(__FILE__, 0x334, "DVDRead(): specified area is out of the file "); + } + + if (!((0 <= offset + length) && (offset + length < fileInfo->length + DVD_MIN_TRANSFER_SIZE))) { + OSPanic(__FILE__, 0x33A, "DVDRead(): specified area is out of the file "); + } + + block = &fileInfo->cb; + result = DVDReadAbsAsyncPrio(block, addr, length, fileInfo->startAddr + offset, cbForReadSync, prio); + if (result == 0) { + return -1; + } + enabled = OSDisableInterrupts(); + + while(1) { + state = ((volatile DVDCommandBlock*)block)->state; + if (state == 0) { + retVal = (s32)block->transferredSize; + break; + } else if (state == -1) { + retVal = -1; + break; + } else if (state == 10) { + retVal = -3; + break; + } + OSSleepThread(&__DVDThreadQueue); + } + OSRestoreInterrupts(enabled); + return retVal; +} + +static void cbForReadSync() { + OSWakeupThread(&__DVDThreadQueue); +} + +int DVDSeekAsyncPrio(struct DVDFileInfo * fileInfo, long offset, void (* callback)(long, struct DVDFileInfo *), long prio) { + ASSERTMSGLINE(0x377, fileInfo, "DVDSeek(): null pointer is specified to file info address "); + ASSERTMSGLINE(0x37B, !(offset & 3), "DVDSeek(): offset must be multiple of 4 byte "); + + if (!((0 <= offset) && (offset <= fileInfo->length))) { + OSPanic(__FILE__, 0x38B, "DVDSeek(): offset is out of the file "); + } + + fileInfo->callback = callback; + DVDSeekAbsAsyncPrio(&fileInfo->cb, (u32)(char*)fileInfo->startAddr + offset, cbForSeekAsync, prio); + return 1; +} + +static void cbForSeekAsync(long result, struct DVDCommandBlock * block) { + struct DVDFileInfo * fileInfo; + + fileInfo = (struct DVDFileInfo *)&block->next; + ASSERTLINE(0x392, (void*) &fileInfo->cb == (void*) block); + if (fileInfo->callback) { + (fileInfo->callback)(result, fileInfo); + } +} + +long DVDSeekPrio(struct DVDFileInfo * fileInfo, long offset, long prio) { + int result; + struct DVDCommandBlock * block; + long state; + int enabled; + long retVal; + + ASSERTMSGLINE(0x3B0, fileInfo, "DVDSeek(): null pointer is specified to file info address "); + ASSERTMSGLINE(0x3B4, !(offset & 3), "DVDSeek(): offset must be multiple of 4 byte "); + ASSERTMSGLINE(0x3B8, (offset >= 0) && ((u32) offset < (u32) fileInfo->length), "DVDSeek(): offset is out of the file "); + + block = &fileInfo->cb; + result = DVDSeekAbsAsyncPrio(block, (u32)(char*)fileInfo->startAddr + offset, cbForSeekSync, prio); + if (!result) { + return -1; + } + enabled = OSDisableInterrupts(); + + while(1) { + state = ((volatile DVDCommandBlock*)block)->state; + if (state == 0) { + retVal = 0; + break; + } else if (state == -1) { + retVal = -1; + break; + } else if (state == 10) { + retVal = -3; + break; + } + OSSleepThread(&__DVDThreadQueue); + } + OSRestoreInterrupts(enabled); + return retVal; +} + +static void cbForSeekSync() { + OSWakeupThread(&__DVDThreadQueue); +} + +// long DVDGetFileInfoStatus(struct DVDFileInfo * fileInfo) { +// return DVDGetCommandBlockStatus(&fileInfo->cb); +// } + +BOOL DVDFastOpenDir(s32 entrynum, DVDDir * dir) { + ASSERTMSGLINE(0x40D, dir, "DVDFastOpenDir(): null pointer is specified to dir structure address "); + ASSERTMSG1LINE(0x410, entrynum >= 0 && entrynum < MaxEntryNum, "DVDFastOpenDir(): specified entry number \'%d\' is out of range ", entrynum); + ASSERTMSG1LINE(0x413, entryIsDir(entrynum), "DVDFastOpenDir(): entry number \'%d\' is assigned to a file ", entrynum); + + if (entrynum < 0 || entrynum >= MaxEntryNum || !entryIsDir(entrynum)) { + return FALSE; + } + + dir->entryNum = entrynum; + dir->location = entrynum + 1; + dir->next = FstStart[entrynum].nextEntryOrLength; + return TRUE; +} + +BOOL DVDOpenDir(char* dirName, DVDDir* dir) { + long entry; + char currentDir[128]; + + ASSERTMSGLINE(0x430, dirName, "DVDOpendir(): null pointer is specified to directory name "); + ASSERTMSGLINE(0x431, dir, "DVDOpenDir(): null pointer is specified to dir structure address "); + entry = DVDConvertPathToEntrynum(dirName); + if (entry < 0) { + DVDGetCurrentDir(currentDir, sizeof(currentDir)); + OSReport("Warning: DVDOpenDir(): file \'%s\' was not found under %s.\n", dirName, currentDir); + return FALSE; + } + + if (!entryIsDir(entry)) { + ASSERTMSG1LINE(0x43F, entryIsDir(entry), "DVDOpendir(): file \'%s\' is specified as a directory name ", dirName); + return FALSE; + } + + dir->entryNum = entry; + dir->location = entry + 1; + dir->next = nextDir(entry); + return TRUE; +} + +int DVDReadDir(DVDDir * dir, DVDDirEntry* dirent) { + unsigned long loc; + + loc = dir->location; + if ((loc <= (u32) dir->entryNum) || ((u32) dir->next <= loc)) { + return 0; + } + dirent->entryNum = loc; + dirent->isDir = entryIsDir(loc); + dirent->name = FstStringStart + stringOff(loc); + dir->location = entryIsDir(loc) ? nextDir(loc) : loc + 1; + return 1; +} + +int DVDCloseDir(DVDDir* dir) { + return 1; +} + +void * DVDGetFSTLocation() { + return BootInfo->FSTLocation; +} + +#define RoundUp32KB(x) (((u32)(x) + 32 * 1024 - 1) & ~(32 * 1024 - 1)) +#define Is32KBAligned(x) (((u32)(x) & (32 * 1024 - 1)) == 0) + +BOOL DVDPrepareStreamAsync(DVDFileInfo* fileInfo, u32 length, u32 offset, DVDCallback callback) { + u32 start; + + ASSERTMSGLINE(0x49C, fileInfo, "DVDPrepareStreamAsync(): NULL file info was specified"); + + start = fileInfo->startAddr + offset; + + if (!Is32KBAligned(start)) { + OSPanic(__FILE__, 0x4BB, + "DVDPrepareStreamAsync(): Specified start address (filestart(0x%x) + offset(0x%x)) is " + "not 32KB aligned", + fileInfo->startAddr, offset); + } + + if (length == 0) + length = fileInfo->length - offset; + + if (!Is32KBAligned(length)) { + OSPanic(__FILE__, 0x4C5, + "DVDPrepareStreamAsync(): Specified length (0x%x) is not a multiple of 32768(32*1024)", + length); + } + + if (!((offset <= fileInfo->length) && (offset + length <= fileInfo->length))) { + OSPanic(__FILE__, 0x4CD, + "DVDPrepareStreamAsync(): The area specified (offset(0x%x), length(0x%x)) is out of " + "the file", + offset, length); + } + + fileInfo->callback = callback; + return DVDPrepareStreamAbsAsync(&(fileInfo->cb), length, fileInfo->startAddr + offset, + cbForPrepareStreamAsync); +} + +static void cbForPrepareStreamAsync(s32 result, DVDCommandBlock* block) { + DVDFileInfo* fileInfo; + + fileInfo = (DVDFileInfo*)((char*)block - offsetof(DVDFileInfo, cb)); + + ASSERTLINE(0x4C7, (void*) &fileInfo->cb == (void*) block); + + if (fileInfo->callback) { + (fileInfo->callback)(result, fileInfo); + } +} + +/* This is based on the revolution SDK, these may not match in all cases */ +s32 DVDPrepareStream(DVDFileInfo* fileInfo, u32 length, u32 offset) { + BOOL result; + DVDCommandBlock* block; + s32 state; + BOOL enabled; + s32 retVal; + u32 start; + + ASSERTMSGLINE(0x4E9, fileInfo, "DVDPrepareStream(): NULL file info was specified"); + + start = fileInfo->startAddr + offset; + + if (!Is32KBAligned(start)) { + OSPanic(__FILE__, 0x508, + "DVDPrepareStream(): Specified start address (filestart(0x%x) + offset(0x%x)) is not " + "32KB aligned", + fileInfo->startAddr, offset); + } + + if (length == 0) + length = fileInfo->length - offset; + + if (!Is32KBAligned(length)) { + OSPanic(__FILE__, 0x512, + "DVDPrepareStream(): Specified length (0x%x) is not a multiple of 32768(32*1024)", + length); + } + + if (!((offset <= fileInfo->length) && (offset + length <= fileInfo->length))) { + OSPanic( + __FILE__, 0x51A, + "DVDPrepareStream(): The area specified (offset(0x%x), length(0x%x)) is out of the file", + offset, length); + } + + block = &(fileInfo->cb); + result = DVDPrepareStreamAbsAsync(block, length, start, cbForPrepareStreamSync); + + if (result == FALSE) { + return -1; + } + + enabled = OSDisableInterrupts(); + + while(1) { + state = ((volatile DVDCommandBlock*)block)->state; + + if (state == DVD_STATE_END) { + retVal = 0; + break; + } + if (state == DVD_STATE_FATAL_ERROR) { + retVal = DVD_RESULT_FATAL_ERROR; + break; + } + if (state == DVD_STATE_CANCELED) { + retVal = DVD_RESULT_CANCELED; + break; + } + + OSSleepThread(&__DVDThreadQueue); + } + + OSRestoreInterrupts(enabled); + return retVal; +} + +static void cbForPrepareStreamSync(s32 result, DVDCommandBlock* block) { + OSWakeupThread(&__DVDThreadQueue); +} + +s32 DVDGetTransferredSize(DVDFileInfo* fileinfo) { + s32 bytes; + DVDCommandBlock* cb; + + cb = &(fileinfo->cb); + + switch (cb->state) { + case DVD_STATE_COVER_CLOSED: + case DVD_STATE_NO_DISK: + case DVD_STATE_COVER_OPEN: + case DVD_STATE_WRONG_DISK: + case DVD_STATE_FATAL_ERROR: + case DVD_STATE_MOTOR_STOPPED: + case DVD_STATE_CANCELED: + case DVD_STATE_RETRY: + case DVD_STATE_END: + bytes = (s32)cb->transferredSize; + break; + case DVD_STATE_WAITING: + bytes = 0; + break; + case DVD_STATE_BUSY: + bytes = (s32)(cb->transferredSize + (cb->currTransferSize - __DIRegs[6])); + break; + default: + ASSERTMSG1LINE(0x556, FALSE, "DVDGetTransferredSize(): Illegal state (%d)", cb->state); + break; + } + return bytes; +} diff --git a/src/static/GAEJ01_01/dolphin/dvd/dvdidutils.c b/src/static/GAEJ01_01/dolphin/dvd/dvdidutils.c new file mode 100644 index 00000000..aeb42100 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/dvdidutils.c @@ -0,0 +1,53 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" + +static u32 strnlen(const char* str, u32 maxlen) { + u32 i; + + for (i = 0; i < maxlen; i++) { + if (*str++ == 0) { + return i; + } + } + + return maxlen; +} + +BOOL DVDCompareDiskID(DVDDiskID* id1, DVDDiskID* id2) { + if (id1->gameName[0] != 0 && id2->gameName[0] != 0 && strncmp(id1->gameName, id2->gameName, 4) != 0) { + return FALSE; + } + + if (id1->company[0] == 0 || id2->company[0] == 0 || strncmp(id1->company, id2->company, 2) != 0) { + return FALSE; + } + + if (id1->diskNumber != 0xFF && id2->diskNumber != 0xFF && id1->diskNumber != id2->diskNumber) { + return FALSE; + } + + if (id1->gameVersion != 0xFF && id2->gameVersion != 0xFF && id1->gameVersion != id2->gameVersion) { + return FALSE; + } + + return TRUE; +} + +DVDDiskID* DVDGenerateDiskID(DVDDiskID* id, const char* game, const char* company, u8 diskNum, u8 version) { + memset(id, 0, sizeof(DVDDiskID)); + + if (game != NULL) { + strncpy(id->gameName, game, 4); + } + + if (company != NULL) { + strncpy(id->company, company, 2); + } + + id->diskNumber = diskNum; + id->gameVersion = version; + return id; +} diff --git a/src/static/GAEJ01_01/dolphin/dvd/dvdlow.c b/src/static/GAEJ01_01/dolphin/dvd/dvdlow.c new file mode 100644 index 00000000..ab0ab2e0 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/dvdlow.c @@ -0,0 +1,559 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +static BOOL FirstRead = TRUE; +static volatile BOOL StopAtNextInt = FALSE; +static u32 LastLength = 0; +static DVDLowCallback Callback = NULL; +static DVDLowCallback ResetCoverCallback = NULL; +static volatile OSTime LastResetEnd = 0; +static volatile u32 ResetOccurred = FALSE; +static volatile BOOL WaitingCoverClose = FALSE; +static volatile BOOL Breaking = FALSE; +static volatile u32 WorkAroundType = 0; +static u32 WorkAroundSeekLocation = 0; +static volatile OSTime LastReadFinished = 0; +static OSTime LastReadIssued = 0; +static volatile BOOL LastCommandWasRead = FALSE; +static volatile u32 NextCommandNumber = 0; + +typedef struct { + void* addr; + u32 length; + u32 offset; +} DVDBuffer; + +typedef struct { + s32 cmd; + void* addr; + u32 length; + u32 offset; + DVDLowCallback callback; +} DVDCommand; + +static DVDCommand CommandList[3]; +static OSAlarm AlarmForWA; +static OSAlarm AlarmForTimeout; +static OSAlarm AlarmForBreak; +static DVDBuffer Prev; +static DVDBuffer Curr; + +void __DVDInitWA() +{ + NextCommandNumber = 0; + CommandList[0].cmd = -1; + __DVDLowSetWAType(0, 0); + OSInitAlarm(); +} + +static void Read(void* addr, u32 length, u32 offset, DVDLowCallback callback); + +static BOOL ProcessNextCommand() +{ + s32 n = NextCommandNumber; + + ASSERTLINE(0x127, n < 3); + if (CommandList[n].cmd == 1) { + ++NextCommandNumber; + Read(CommandList[n].addr, CommandList[n].length, CommandList[n].offset, CommandList[n].callback); + return TRUE; + } else if (CommandList[n].cmd == 2) { + ++NextCommandNumber; + DVDLowSeek(CommandList[n].offset, CommandList[n].callback); + return TRUE; + } + + return FALSE; +} + +void __DVDInterruptHandler(__OSInterrupt interrupt, OSContext* context) +{ + DVDLowCallback cb; + OSContext exceptionContext; + u32 cause = 0; + u32 reg; + u32 intr; + u32 mask; + + if (LastCommandWasRead) { + LastReadFinished = __OSGetSystemTime(); + FirstRead = FALSE; + Prev.addr = Curr.addr; + Prev.length = Curr.length; + Prev.offset = Curr.offset; + if (StopAtNextInt == TRUE) { + cause |= 8; + } + } + + LastCommandWasRead = FALSE; + StopAtNextInt = FALSE; + reg = __DIRegs[0]; + mask = reg & 0x2a; + intr = (reg & 0x54) & (mask << 1); + + if (intr & 0x40) { + cause |= 8; + } + + if (intr & 0x10) { + cause |= 1; + } + + if (intr & 4) { + cause |= 2; + } + + if (cause) { + ResetOccurred = FALSE; + OSCancelAlarm(&AlarmForTimeout); + } + + __DIRegs[0] = intr | mask; + + if (ResetOccurred && (__OSGetSystemTime() - LastResetEnd) < OSMillisecondsToTicks(200)) { + reg = __DIRegs[1]; + mask = reg & 0x2; + intr = (reg & 4) & (mask << 1); + if (intr & 4) { + if (ResetCoverCallback) { + ResetCoverCallback(4); + } + ResetCoverCallback = NULL; + } + + __DIRegs[1] = __DIRegs[1]; + } else if (WaitingCoverClose) { + reg = __DIRegs[1]; + mask = reg & 2; + intr = (reg & 4) & (mask << 1); + + if (intr & 4) { + cause |= 4; + } + + __DIRegs[1] = intr | mask; + WaitingCoverClose = FALSE; + } else { + __DIRegs[1] = 0; + } + + if ((cause & 8) && !Breaking) { + cause &= ~8; + } + + if ((cause & 1)) { + if (ProcessNextCommand()) { + return; + } + } else { + CommandList[0].cmd = -1; + NextCommandNumber = 0; + } + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + + if (cause) { + cb = Callback; + Callback = NULL; + if (cb) { + cb(cause); + } + + Breaking = FALSE; + } + + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +static void AlarmHandler(OSAlarm* alarm, OSContext* context) { + BOOL processed = ProcessNextCommand(); + + ASSERTLINE(0x28A, processed); +} + +static void AlarmHandlerForTimeout(OSAlarm* alarm, OSContext* context) +{ + OSContext tmpContext; + DVDLowCallback callback; + __OSMaskInterrupts(0x400); + OSClearContext(&tmpContext); + OSSetCurrentContext(&tmpContext); + callback = Callback; + Callback = NULL; + if (callback) { + callback(0x10); + } + OSClearContext(&tmpContext); + OSSetCurrentContext(context); +} + +static void SetTimeoutAlarm(OSTime timeout) +{ + OSCreateAlarm(&AlarmForTimeout); + OSSetAlarm(&AlarmForTimeout, timeout, AlarmHandlerForTimeout); +} + +static void Read(void* addr, u32 length, u32 offset, DVDLowCallback callback) +{ + Callback = callback; + StopAtNextInt = FALSE; + LastCommandWasRead = TRUE; + LastReadIssued = __OSGetSystemTime(); + + __DIRegs[2] = 0xa8000000; + __DIRegs[3] = offset / 4; + __DIRegs[4] = length; + __DIRegs[5] = (u32)addr; + __DIRegs[6] = length; + LastLength = length; + __DIRegs[7] = 3; + + if (length > 0xa00000) { + SetTimeoutAlarm(OSSecondsToTicks(20)); + } else { + SetTimeoutAlarm(OSSecondsToTicks(10)); + } +} + +static BOOL AudioBufferOn(void) +{ + DVDDiskID* id; + + id = DVDGetCurrentDiskID(); + if (id->streaming) { + return TRUE; + } + + return FALSE; +} + +static BOOL HitCache(DVDBuffer* cur, DVDBuffer* prev) +{ + u32 uVar1 = (prev->offset + prev->length - 1) >> 15; + u32 uVar2 = (cur->offset >> 15); + u32 iVar3 = AudioBufferOn() ? 5 : 15; + + if ((uVar2 > uVar1 - 2) || (uVar2 < uVar1 + iVar3 + 3)) { + return TRUE; + } + return FALSE; +} + +static void DoJustRead(void* addr, u32 length, u32 offset, DVDLowCallback callback) +{ + CommandList[0].cmd = -1; + NextCommandNumber = 0; + Read(addr, length, offset, callback); +} + +static void SeekTwiceBeforeRead(void* addr, u32 length, u32 offset, DVDLowCallback callback) +{ + u32 newOffset; + if ((offset & ~0x7FFF) == 0) { + newOffset = 0; + } else { + newOffset = (offset & ~0x7FFF) + WorkAroundSeekLocation; + } + CommandList[0].cmd = 2; + CommandList[0].offset = newOffset; + CommandList[0].callback = callback; + CommandList[1].cmd = 1; + CommandList[1].addr = addr; + CommandList[1].length = length; + CommandList[1].offset = offset; + CommandList[1].callback = callback; + CommandList[2].cmd = -1; + NextCommandNumber = 0; + DVDLowSeek(newOffset, callback); +} + +static void WaitBeforeRead(void* addr, u32 length, u32 offset, DVDLowCallback callback, OSTime timeout) +{ + CommandList[0].cmd = 1; + CommandList[0].addr = addr; + CommandList[0].length = length; + CommandList[0].offset = offset; + CommandList[0].callback = callback; + CommandList[1].cmd = -1; + NextCommandNumber = 0; + OSCreateAlarm(&AlarmForWA); + OSSetAlarm(&AlarmForWA, timeout, AlarmHandler); +} + +BOOL DVDLowRead(void* addr, u32 length, u32 offset, DVDLowCallback callback) +{ + u32 blockNumOfPrevEnd; + u32 blockNumOfCurrStart; + OSTime diff; + + ASSERTMSGLINE(0x341, (((u32)addr) & 31) == 0, "DVDLowRead(): address must be aligned with 32 byte boundary."); + ASSERTMSGLINE(0x342, (length & 31) == 0, "DVDLowRead(): length must be a multiple of 32."); + ASSERTMSGLINE(0x343, (offset & 3) == 0, "DVDLowRead(): offset must be a multiple of 4."); + ASSERTMSGLINE(0x345, length != 0, "DVD read: 0 was specified to length of the read\n"); + + __DIRegs[6] = length; + Curr.addr = addr; + Curr.length = length; + Curr.offset = offset; + + if (WorkAroundType == 0) { + DoJustRead(addr, length, offset, callback); + } else if (WorkAroundType == 1) { + if (FirstRead) { + SeekTwiceBeforeRead(addr, length, offset, callback); + } else { + if (!HitCache(&Curr, &Prev)) { + DoJustRead(addr, length, offset, callback); + } else { + blockNumOfPrevEnd = (u32)((Prev.offset + Prev.length - 1) >> 15) & 0x1FFFF; + blockNumOfCurrStart = (u32)((Curr.offset >> 15) & 0x1FFFF); + if (blockNumOfPrevEnd == blockNumOfCurrStart || blockNumOfPrevEnd + 1 == blockNumOfCurrStart) { + diff = __OSGetSystemTime() - LastReadFinished; + if (OSMillisecondsToTicks(5) < diff) { + DoJustRead(addr, length, offset, callback); + } else { + WaitBeforeRead(addr, length, offset, callback, OSMillisecondsToTicks(5) - diff + OSMicrosecondsToTicks(500)); + } + } else { + SeekTwiceBeforeRead(addr, length, offset, callback); + } + } + } + } else { + ASSERTLINE(0x380, FALSE); + } + + return TRUE; +} + +BOOL DVDLowSeek(u32 offset, DVDLowCallback callback) +{ + ASSERTMSGLINE(0x394, (offset & 3) == 0, "DVDLowSeek(): offset must be a multiple of 4."); + + Callback = callback; + StopAtNextInt = FALSE; + __DIRegs[2] = 0xab000000; + __DIRegs[3] = offset / 4; + __DIRegs[7] = 1; + SetTimeoutAlarm(OSSecondsToTicks(10)); + return TRUE; +} + +BOOL DVDLowWaitCoverClose(DVDLowCallback callback) +{ + Callback = callback; + WaitingCoverClose = TRUE; + StopAtNextInt = FALSE; + __DIRegs[1] = 2; + return TRUE; +} + +BOOL DVDLowReadDiskID(DVDDiskID* diskID, DVDLowCallback callback) +{ + ASSERTMSGLINE(0x3d2, (((u32)diskID) & 31) == 0, "DVDLowReadID(): id must be aligned with 32 byte boundary."); + + Callback = callback; + StopAtNextInt = FALSE; + __DIRegs[2] = 0xa8000040; + __DIRegs[3] = 0; + __DIRegs[4] = sizeof(DVDDiskID); + __DIRegs[5] = (u32)diskID; + __DIRegs[6] = sizeof(DVDDiskID); + __DIRegs[7] = 3; + SetTimeoutAlarm(OSSecondsToTicks(10)); + return TRUE; +} + +BOOL DVDLowStopMotor(DVDLowCallback callback) +{ + Callback = callback; + StopAtNextInt = FALSE; + __DIRegs[2] = 0xe3000000; + __DIRegs[7] = 1; + SetTimeoutAlarm(OSSecondsToTicks(10)); + return TRUE; +} + +BOOL DVDLowRequestError(DVDLowCallback callback) +{ + Callback = callback; + StopAtNextInt = FALSE; + __DIRegs[2] = 0xe0000000; + __DIRegs[7] = 1; + SetTimeoutAlarm(OSSecondsToTicks(10)); + return TRUE; +} + +BOOL DVDLowInquiry(DVDDriveInfo* info, DVDLowCallback callback) +{ + Callback = callback; + StopAtNextInt = FALSE; + __DIRegs[2] = 0x12000000; + __DIRegs[4] = sizeof(DVDDriveInfo); + __DIRegs[5] = (u32)info; + __DIRegs[6] = sizeof(DVDDriveInfo); + __DIRegs[7] = 3; + SetTimeoutAlarm(OSSecondsToTicks(10)); + return TRUE; +} + +BOOL DVDLowAudioStream(u32 subcmd, u32 length, u32 offset, DVDLowCallback callback) +{ + Callback = callback; + StopAtNextInt = FALSE; + __DIRegs[2] = subcmd | 0xe1000000; + __DIRegs[3] = offset >> 2; + __DIRegs[4] = length; + __DIRegs[7] = 1; + SetTimeoutAlarm(OSSecondsToTicks(10)); + return TRUE; +} + +BOOL DVDLowRequestAudioStatus(u32 subcmd, DVDLowCallback callback) +{ + Callback = callback; + StopAtNextInt = FALSE; + __DIRegs[2] = subcmd | 0xe2000000; + __DIRegs[7] = 1; + SetTimeoutAlarm(OSSecondsToTicks(10)); + return TRUE; +} + +BOOL DVDLowAudioBufferConfig(BOOL enable, u32 size, DVDLowCallback callback) +{ +#if DEBUG + u32 bufSize; + u32 trigger; +#endif + + Callback = callback; + StopAtNextInt = FALSE; + +#if DEBUG + bufSize = size & 0xF; + trigger = (size >> 4) & 0xF; + ASSERTLINE(0x4BD, bufSize < 16); + ASSERTLINE(0x4BE, trigger <= 2); +#endif + + __DIRegs[2] = 0xe4000000 | (enable != 0 ? 0x10000 : 0) | size; + __DIRegs[7] = 1; + SetTimeoutAlarm(OSSecondsToTicks(10)); + return TRUE; +} + +void DVDLowReset() +{ + u32 reg; + OSTime resetStart; + + __DIRegs[1] = 2; + reg = __PIRegs[9]; + __PIRegs[9] = (reg & ~4) | 1; + + resetStart = __OSGetSystemTime(); + while ((__OSGetSystemTime() - resetStart) < OSMicrosecondsToTicks(12)) + ; + + __PIRegs[9] = reg | 4 | 1; + ResetOccurred = TRUE; + LastResetEnd = __OSGetSystemTime(); +} + +DVDLowCallback DVDLowSetResetCoverCallback(DVDLowCallback callback) +{ + DVDLowCallback old; + BOOL enabled; + + enabled = OSDisableInterrupts(); + old = ResetCoverCallback; + ResetCoverCallback = callback; + OSRestoreInterrupts(enabled); + return old; +} + +static void DoBreak(void) +{ + u32 statusReg; + + statusReg = __DIRegs[0]; + statusReg |= 0x40 | 1; + __DIRegs[0] = statusReg; + Breaking = TRUE; +} + +static void SetBreakAlarm(OSTime timeout); + +static void AlarmHandlerForBreak(OSAlarm* alarm, OSContext* context) +{ + if (__DIRegs[6] < LastLength) { + DoBreak(); + } else { + SetBreakAlarm(OSMillisecondsToTicks(20)); + } +} + +static void SetBreakAlarm(OSTime timeout) +{ + OSCreateAlarm(&AlarmForBreak); + OSSetAlarm(&AlarmForBreak, timeout, AlarmHandlerForBreak); +} + +BOOL DVDLowBreak() +{ + StopAtNextInt = TRUE; + Breaking = TRUE; + return TRUE; +} + +DVDLowCallback DVDLowClearCallback() +{ + DVDLowCallback old; + __DIRegs[1] = 0; + old = Callback; + WaitingCoverClose = FALSE; + Callback = NULL; + return old; +} + +u32 DVDLowGetCoverStatus(void) +{ + if ((__OSGetSystemTime() - LastResetEnd) < OSMillisecondsToTicks(100)) { + return 0; + } + + if (__DIRegs[1] & 1) { + return 1; + } + + return 2; +} + + +void __DVDLowSetWAType(u32 type, u32 location) +{ + BOOL enabled; + + enabled = OSDisableInterrupts(); + ASSERTLINE(0x5B1, type < DVD_WATYPE_MAX); + WorkAroundType = type; + WorkAroundSeekLocation = location; + OSRestoreInterrupts(enabled); +} + +BOOL __DVDLowTestAlarm(OSAlarm* alarm) +{ + if (alarm == &AlarmForBreak) { + return TRUE; + } else if (alarm == &AlarmForTimeout) { + return TRUE; + } else { + return FALSE; + } +} diff --git a/src/static/GAEJ01_01/dolphin/dvd/dvdqueue.c b/src/static/GAEJ01_01/dolphin/dvd/dvdqueue.c new file mode 100644 index 00000000..f8f9ba2f --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/dvdqueue.c @@ -0,0 +1,166 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" + +static struct { + /* 0x00 */ struct DVDCommandBlock * next; + /* 0x04 */ struct DVDCommandBlock * prev; +} WaitingQueue[4]; + +static struct DVDCommandBlock * PopWaitingQueuePrio(long prio); + +void __DVDClearWaitingQueue(void) { + unsigned long i; + struct DVDCommandBlock * q; + + for(i = 0; i < 4; i++) { + q = (struct DVDCommandBlock *)&WaitingQueue[i].next; + q->next = q; + q->prev = q; + } +} + +int __DVDPushWaitingQueue(long prio, struct DVDCommandBlock * block) { + int enabled = OSDisableInterrupts(); + struct DVDCommandBlock * q = (struct DVDCommandBlock *)&WaitingQueue[prio]; + + q->prev->next = block; + block->prev = q->prev; + block->next = q; + q->prev = block; + OSRestoreInterrupts(enabled); + return 1; +} + +static struct DVDCommandBlock * PopWaitingQueuePrio(long prio) { + struct DVDCommandBlock * tmp; + int enabled; + struct DVDCommandBlock * q; + + enabled = OSDisableInterrupts(); + q = (struct DVDCommandBlock *)&WaitingQueue[prio]; + ASSERTLINE(0x57, q->next != q); + tmp = q->next; + q->next = tmp->next; + tmp->next->prev = q; + OSRestoreInterrupts(enabled); + tmp->next = 0; + tmp->prev = 0; + return tmp; +} + +struct DVDCommandBlock * __DVDPopWaitingQueue(void) { + unsigned long i; + int enabled; + struct DVDCommandBlock * q; + + enabled = OSDisableInterrupts(); + for(i = 0; i < 4; i++) { + q = (struct DVDCommandBlock *)&WaitingQueue[i]; + if (q->next != q) { + OSRestoreInterrupts(enabled); + return PopWaitingQueuePrio(i); + } + } + OSRestoreInterrupts(enabled); + return NULL; +} + +int __DVDCheckWaitingQueue(void) { + unsigned long i; + int enabled; + struct DVDCommandBlock * q; + + enabled = OSDisableInterrupts(); + for(i = 0; i < 4; i++) { + q = (struct DVDCommandBlock *)&WaitingQueue[i]; + if (q->next != q) { + OSRestoreInterrupts(enabled); + return 1; + } + } + OSRestoreInterrupts(enabled); + return 0; +} + +int __DVDDequeueWaitingQueue(struct DVDCommandBlock * block) { + int enabled; + struct DVDCommandBlock * prev; + struct DVDCommandBlock * next; + + enabled = OSDisableInterrupts(); + prev = block->prev; + next = block->next; + if (prev == NULL || next == NULL) { + OSRestoreInterrupts(enabled); + return 0; + } + prev->next = next; + next->prev = prev; + OSRestoreInterrupts(enabled); + return 1; +} + +int __DVDIsBlockInWaitingQueue(struct DVDCommandBlock * block) { + unsigned long i; + struct DVDCommandBlock * start; + struct DVDCommandBlock * q; + + for(i = 0; i < 4; i++) { + start = (struct DVDCommandBlock *)&WaitingQueue[i]; + if (start->next == start) { + continue; + } + for(q = start->next; q != start; q = q->next) { + if (q == block) { + return 1; + } + } + } + return 0; +} + +static char * CommandNames[16] = { + "", + "READ", + "SEEK", + "CHANGE_DISK", + "BSREAD", + "READID", + "INITSTREAM", + "CANCELSTREAM", + "STOP_STREAM_AT_END", + "REQUEST_AUDIO_ERROR", + "REQUEST_PLAY_ADDR", + "REQUEST_START_ADDR", + "REQUEST_LENGTH", + "AUDIO_BUFFER_CONFIG", + "INQUIRY", + "BS_CHANGE_DISK", +}; + +void DVDDumpWaitingQueue(void) { + unsigned long i; + struct DVDCommandBlock * start; + struct DVDCommandBlock * q; + + OSReport("==== DVD Waiting Queue Status ====\n"); + for(i = 0; i < 4; i++) { + OSReport("< Queue #%d > ", i); + start = (struct DVDCommandBlock *)&WaitingQueue[i]; + if (start->next == start) { + OSReport("None\n"); + } else { + OSReport("\n"); + for(q = start->next; q != start; q = q->next) { + OSReport("0x%08x: Command: %s ", q, CommandNames[q->command]); + if (q->command == 1) { + OSReport("Disk offset: %d, Length: %d, Addr: 0x%08x\n", q->offset, q->length, q->addr); + } else { + OSReport("\n"); + } + } + } + } +} diff --git a/src/static/GAEJ01_01/dolphin/dvd/fstload.c b/src/static/GAEJ01_01/dolphin/dvd/fstload.c new file mode 100644 index 00000000..7182a6fa --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/dvd/fstload.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" + +// .bss +static unsigned char bb2Buf[63]; // size: 0x3F, address: 0x0 + +// .sbss +static unsigned long status; // size: 0x4, address: 0x0 +static struct DVDBB2 * bb2; // size: 0x4, address: 0x4 +static struct DVDDiskID * idTmp; // size: 0x4, address: 0x8 + +// functions +static void cb(long result, struct DVDCommandBlock * block); +void __fstLoad(); + +static void cb(long result, struct DVDCommandBlock * block) { + if (result > 0) { + switch(status) { + case 0: + status = 1; + DVDReadAbsAsyncForBS(block, bb2, 0x20, 0x420, cb); + return; + case 1: + status = 2; + DVDReadAbsAsyncForBS(block, bb2->FSTAddress, (bb2->FSTLength + 0x1F) & 0xFFFFFFE0, bb2->FSTPosition, cb); + default: + return; + } + } + if (result == -1) { + return; + } else if (result == -4) { + status = 0; + DVDReset(); + DVDReadDiskID(block, idTmp, cb); + } +} + +void __fstLoad() { + struct OSBootInfo_s * bootInfo; + struct DVDDiskID * id; + unsigned char idTmpBuf[63]; + long state; + void * arenaHi; + static struct DVDCommandBlock block; + + arenaHi = OSGetArenaHi(); + bootInfo = (void*)OSPhysicalToCached(0); + idTmp = (void*)OSRoundUp32B(idTmpBuf); + bb2 = (void*)OSRoundUp32B(bb2Buf); + DVDReset(); + DVDReadDiskID(&block, idTmp, cb); + while (1) { + state = DVDGetDriveStatus(); + if (state == 0) { + break; + } + + // weird switch that seemingly wont do anything but break out of its own switch. What was this for? Early DVD development pre-hardware? + switch(state) { + case DVD_STATE_FATAL_ERROR: break; + case DVD_STATE_BUSY: break; + case DVD_STATE_WAITING: break; + case DVD_STATE_COVER_CLOSED: break; + case DVD_STATE_NO_DISK: break; + case DVD_STATE_COVER_OPEN: break; + case DVD_STATE_MOTOR_STOPPED: break; + } + } + bootInfo->FSTLocation = (void*)bb2->FSTAddress; + bootInfo->FSTMaxLength = bb2->FSTMaxLength; + id = &bootInfo->DVDDiskID; + memcpy(id, idTmp, 0x20); + OSReport("\n"); + OSReport(" Game Name ... %c%c%c%c\n", id->gameName[0], id->gameName[1], id->gameName[2], id->gameName[3]); + OSReport(" Company ..... %c%c\n", id->company[0], id->company[1]); + OSReport(" Disk # ...... %d\n", id->diskNumber); + OSReport(" Game ver .... %d\n", id->gameVersion); + OSReport(" Streaming ... %s\n", !(id->streaming) ? "OFF" : "ON"); + OSReport("\n"); + OSSetArenaHi(bb2->FSTAddress); +} diff --git a/src/static/GAEJ01_01/dolphin/exi/EXIAd16.c b/src/static/GAEJ01_01/dolphin/exi/EXIAd16.c new file mode 100644 index 00000000..6ef016f1 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/exi/EXIAd16.c @@ -0,0 +1,93 @@ +#include +#include + +static int Initialized; + +int AD16Init(void); +int AD16WriteReg(unsigned long word); +int AD16ReadReg(unsigned long *word); +int AD16Probe(void); + +int AD16Init(void) { + int err; + unsigned long cmd; + unsigned long id; + + if (Initialized != 0) { + return 1; + } + if (EXILock(2, 0, 0) == 0) { + return 0; + } + if (EXISelect(2, 0, 0) == 0) { + EXIUnlock(2); + return 0; + } + cmd = 0; + err = 0; + err |= !EXIImm(2, &cmd, 2, 1, 0); + err |= !EXISync(2); + err |= !EXIImm(2, &id, 4, 0, 0); + err |= !EXISync(2); + err |= !EXIDeselect(2); + EXIUnlock(2); + if (err != 0 || id != 0x4120000) { + return 0; + } + Initialized = 1; + return 1; +} + +int AD16WriteReg(unsigned long word) { + int err; + unsigned long cmd; + + if (Initialized == 0 || EXILock(2, 0, 0) == 0) { + return 0; + } + if (EXISelect(2, 0, 3) == 0) { + EXIUnlock(2); + return 0; + } + cmd = 0xA0000000; + err = 0; + err |= !EXIImm(2, &cmd, 1, 1, 0); + err |= !EXISync(2); + err |= !EXIImm(2, &word, 4, 1, 0); + err |= !EXISync(2); + err |= !EXIDeselect(2); + EXIUnlock(2); + if (err) { + return 0; + } + return 1; +} + +int AD16ReadReg(unsigned long * word) { + int err; + unsigned long cmd; + + if (Initialized == 0 || EXILock(2, 0, 0) == 0) { + return 0; + } + if (EXISelect(2, 0, 3) == 0) { + EXIUnlock(2); + return 0; + } + cmd = 0xA2000000; + err = 0; + err |= !EXIImm(2, &cmd, 1, 1, 0); + err |= !EXISync(2); + err |= !EXIImm(2, word, 4, 0, 0); + err |= !EXISync(2); + err |= !EXIDeselect(2); + EXIUnlock(2); + if (err) { + return 0; + } + return 1; +} + +int AD16Probe(void) { + return Initialized; +} diff --git a/src/static/GAEJ01_01/dolphin/exi/EXIBios.c b/src/static/GAEJ01_01/dolphin/exi/EXIBios.c new file mode 100644 index 00000000..bcb92628 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/exi/EXIBios.c @@ -0,0 +1,768 @@ +#include +#include +#include +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +typedef void (*EXICallback)(s32, OSContext*); + +typedef struct EXIControl { + EXICallback exiCallback; + EXICallback tcCallback; + EXICallback extCallback; + volatile u32 state; + int immLen; + u8* immBuf; + u32 dev; + u32 id; + s32 idTime; + int items; + struct { + u32 dev; + EXICallback callback; + } queue[3]; +} EXIControl; + +#define MAX_CHAN 3 + +#define STATE_BUSY 3 +#define STATE_SELECTED 4 + +#define MAX_IMM 4 +#define MAX_TYPE 3 +#define MAX_DEV 3 +#define MAX_FREQ 6 + +#define EXI_0LENGTH_EXILENGTH_MASK 0x03FFFFE0 + +#define EXI_READ 0 +#define EXI_WRITE 1 + +static struct EXIControl Ecb[3]; + +static void SetExiInterruptMask(long chan, struct EXIControl * exi); +static void CompleteTransfer(long chan); +static int __EXIProbe(long chan); +int EXIImm(long chan, void * buf, long len, unsigned long type, EXICallback callback); +int EXIImmEx(long chan, void * buf, long len, unsigned long mode); +int EXIDma(long chan, void * buf, long len, unsigned long type, EXICallback callback); +int EXISync(long chan); +unsigned long EXIClearInterrupts(long chan, int exi, int tc, int ext); +EXICallback EXISetExiCallback(long chan, EXICallback exiCallback); +void EXIProbeReset(); +int EXIProbe(long chan); +s32 EXIProbeEx(long chan); +int EXIAttach(long chan, EXICallback extCallback); +int EXIDetach(long chan); +int EXISelect(long chan, unsigned long dev, unsigned long freq); +int EXIDeselect(long chan); +static void EXIIntrruptHandler(signed short interrupt, struct OSContext * context); +static void TCIntrruptHandler(signed short interrupt, struct OSContext * context); +static void EXTIntrruptHandler(signed short interrupt, struct OSContext * context); +void EXIInit(); +int EXILock(long chan, unsigned long dev, void (* unlockedCallback)(long, struct OSContext *)); +int EXIUnlock(long chan); +unsigned long EXIGetState(long chan); +s32 EXIGetID(long chan, unsigned long dev, unsigned long * id); + +static void SetExiInterruptMask(long chan, struct EXIControl * exi) { + struct EXIControl * exi2 = &Ecb[2]; + + switch(chan) { + case 0: + if ((exi->exiCallback == 0 && exi2->exiCallback == 0) || exi->state & 0x10) { + __OSMaskInterrupts(0x410000U); + return; + } + __OSUnmaskInterrupts(0x410000U); + return; + case 1: + if (exi->exiCallback == 0 || exi->state & 0x10) { + __OSMaskInterrupts(0x80000U); + return; + } + __OSUnmaskInterrupts(0x80000U); + return; + case 2: + if ((__OSGetInterruptHandler(0x19) == 0U) || (exi->state & 0x10)) { + __OSMaskInterrupts(0x40U); + return; + } + __OSUnmaskInterrupts(0x40U); + return; + } +} + +static void CompleteTransfer(long chan) { + struct EXIControl * exi; + unsigned char * buf; + unsigned long data; + int i; + int len; + + exi = &Ecb[chan]; + ASSERTLINE(301, 0 <= chan && chan < MAX_CHAN); + + if (exi->state & 3) { + if (exi->state & 2) { + if ((len = exi->immLen) != 0) { + buf = exi->immBuf; + data = __EXIRegs[(chan * 5) + 4]; + for(i = 0; i < len; i++) { + *buf++ = data >> ((3 - i) * 8); + } + } + } + exi->state &= ~3; + } +} + +int EXIImm(long chan, void * buf, long len, unsigned long type, EXICallback callback) { + struct EXIControl * exi; + int enabled; + unsigned long data; + int i; + + exi = &Ecb[chan]; + ASSERTLINE(339, exi->state & STATE_SELECTED); + ASSERTLINE(340, 0 <= chan && chan < MAX_CHAN); + ASSERTLINE(341, 0 < len && len <= MAX_IMM); + ASSERTLINE(342, type < MAX_TYPE); + enabled = OSDisableInterrupts(); + if ((exi->state & 3) || !(exi->state & 4)) { + OSRestoreInterrupts(enabled); + return 0; + } + exi->tcCallback = callback; + if (exi->tcCallback) { + EXIClearInterrupts(chan, 0, 1, 0); + __OSUnmaskInterrupts(0x200000U >> (chan * 3)); + } + exi->state |= 2; + if (type != 0) { + data = 0; + for(i = 0; i < len; i++) { + data |= ((u8*)buf)[i] << ((3 - i) * 8); + } + __EXIRegs[(chan * 5) + 4] = data; + } + exi->immBuf = buf; + exi->immLen = (type != 1) ? len : 0; + __EXIRegs[(chan * 5) + 3] = (type << 2) | 1 | ((len - 1) << 4); + OSRestoreInterrupts(enabled); + return 1; +} + +int EXIImmEx(long chan, void * buf, long len, unsigned long mode) { + long xLen; + + while(len) { + xLen = (len < 4) ? len : 4; + if (EXIImm(chan, buf, xLen, mode, 0) == 0) { + return 0; + } + if (EXISync(chan) == 0) { + return 0; + } + ((u8*)buf) += xLen; + len -= xLen; + } + return 1; +} + +int EXIDma(long chan, void * buf, long len, unsigned long type, EXICallback callback) { + struct EXIControl * exi; + int enabled; + + exi = &Ecb[chan]; + + ASSERTLINE(444, exi->state & STATE_SELECTED); + ASSERTLINE(445, OFFSET(buf, 32) == 0); + ASSERTLINE(446, 0 < len && OFFSET(len, 32) == 0); + ASSERTLINE(448, ((u32) len & ~EXI_0LENGTH_EXILENGTH_MASK) == 0); + ASSERTLINE(450, type == EXI_READ || type == EXI_WRITE); + + enabled = OSDisableInterrupts(); + if ((exi->state & 3) || !(exi->state & 4)) { + OSRestoreInterrupts(enabled); + return 0; + } + exi->tcCallback = callback; + if ((u32)exi->tcCallback) { + EXIClearInterrupts(chan, 0, 1, 0); + __OSUnmaskInterrupts(0x200000U >> (chan * 3)); + } + exi->state |= 1; + __EXIRegs[(chan * 5) + 1] = (u32)buf & 0x03FFFFE0; + __EXIRegs[(chan * 5) + 2] = len; + __EXIRegs[(chan * 5) + 3] = (type * 4) | 3; + OSRestoreInterrupts(enabled); + return 1; +} + +int EXISync(long chan) { + struct EXIControl * exi; + int rc; + int enabled; + + exi = &Ecb[chan]; + rc = 0; + ASSERTLINE(498, 0 <= chan && chan < MAX_CHAN); + while ((exi->state & 4)) { + if (!(__EXIRegs[(chan * 5) + 3] & 1)) { + enabled = OSDisableInterrupts(); + if (exi->state & 4) { + CompleteTransfer(chan); + if (__OSGetDIConfig() != 0xFF || (exi->immLen != 4 || (__EXIRegs[chan * 5] & 0x70) || + (__EXIRegs[(chan * 5) + 4] != 0x01010000 && __EXIRegs[(chan * 5) + 4] != 0x05070000 && __EXIRegs[(chan * 5) + 4] != 0x04220001)) || + __OSDeviceCode == 0x8200) { + rc = 1; + } + } + OSRestoreInterrupts(enabled); + break; + } + } + ASSERTLINE(526, !(exi->state & STATE_BUSY)); + return rc; +} + +unsigned long EXIClearInterrupts(long chan, int exi, int tc, int ext) { + unsigned long cpr; + unsigned long prev; + + ASSERTLINE(547, 0 <= chan && chan < MAX_CHAN); + cpr = prev = __EXIRegs[(chan * 5)]; + prev &= 0x7F5; + if (exi != 0) { + prev |= 2; + } + if (tc != 0) { + prev |= 8; + } + if (ext != 0) { + prev |= 0x800; + } + __EXIRegs[(chan * 5)] = prev; + return cpr; +} + +EXICallback EXISetExiCallback(long chan, EXICallback exiCallback) { + struct EXIControl * exi; + EXICallback prev; + int enabled; + + exi = &Ecb[chan]; + ASSERTLINE(581, 0 <= chan && chan < MAX_CHAN); + enabled = OSDisableInterrupts(); + prev = exi->exiCallback; + exi->exiCallback = exiCallback; + if (chan != 2) { + SetExiInterruptMask(chan, exi); + } else { + SetExiInterruptMask(0, &Ecb[0]); + } + OSRestoreInterrupts(enabled); + return prev; +} + +void EXIProbeReset() { + __gUnknown800030C0[0] = __gUnknown800030C0[1] = 0; + Ecb[0].idTime = Ecb[1].idTime = 0; + __EXIProbe(0); + __EXIProbe(1); +} + +static int __EXIProbe(long chan) { + struct EXIControl * exi; + int enabled; + int rc; + unsigned long cpr; + long t; + + exi = &Ecb[chan]; + ASSERTLINE(636, 0 <= chan && chan < MAX_CHAN); + if (chan == 2) { + return 1; + } + rc = 1; + enabled = OSDisableInterrupts(); + cpr = __EXIRegs[(chan * 5)]; + if (!(exi->state & 8)) { + if (cpr & 0x800) { + EXIClearInterrupts(chan, 0, 0, 1); + __gUnknown800030C0[chan] = exi->idTime = 0; + } + if (cpr & 0x1000) { + t = ((long)(OSTicksToMilliseconds(OSGetTime()) / 100) + 1); + + if (__gUnknown800030C0[chan] == 0) { + __gUnknown800030C0[chan] = t; + } + if (t - (long)__gUnknown800030C0[chan] < 3) { + rc = 0; + } + } else { + __gUnknown800030C0[chan] = exi->idTime = 0; + rc = 0; + } + } else if(!(cpr & 0x1000) || (cpr & 0x800)) { + __gUnknown800030C0[chan] = exi->idTime = 0; + rc = 0; + } + OSRestoreInterrupts(enabled); + return rc; +} + +int EXIProbe(long chan) { + EXIControl* exi = &Ecb[chan]; + int rc; + u32 id; + + + rc = __EXIProbe(chan); + if (rc && !exi->idTime) { + rc = EXIGetID(chan, 0, &id) ? 1 : 0; + } + + return rc; +} + +s32 EXIProbeEx(long chan) { + if (EXIProbe(chan)) { + return 1; + } + if (__gUnknown800030C0[chan]) { + return 0; + } + return -1; +} + +static int __EXIAttach(long chan, EXICallback extCallback) { + struct EXIControl * exi; + int enabled; + + exi = &Ecb[chan]; + ASSERTLINE(741, 0 <= chan && chan < 2); + enabled = OSDisableInterrupts(); + if ((exi->state & 8) || !__EXIProbe(chan)) { + OSRestoreInterrupts(enabled); + return 0; + } + EXIClearInterrupts(chan, 1, 0, 0); + exi->extCallback = extCallback; + __OSUnmaskInterrupts(0x100000U >> (chan * 3)); + exi->state |= 8; + OSRestoreInterrupts(enabled); + return 1; +} + +int EXIAttach(long chan, EXICallback extCallback) { + struct EXIControl * exi; + int enabled; + int rc; + + exi = &Ecb[chan]; + ASSERTLINE(767, 0 <= chan && chan < 2); + EXIProbe(chan); + enabled = OSDisableInterrupts(); + if (exi->idTime == 0) { + OSRestoreInterrupts(enabled); + return 0; + } + + rc = __EXIAttach(chan, extCallback); + OSRestoreInterrupts(enabled); + return rc; +} + +int EXIDetach(long chan) { + struct EXIControl * exi; + int enabled; + + exi = &Ecb[chan]; + ASSERTLINE(801, 0 <= chan && chan < 2); + enabled = OSDisableInterrupts(); + if (!(exi->state & 8)) { + OSRestoreInterrupts(enabled); + return 1; + } + if ((exi->state & 0x10) && (exi->dev == 0)) { + OSRestoreInterrupts(enabled); + return 0; + } + exi->state &= ~8; + __OSMaskInterrupts(0x500000U >> (chan * 3)); + OSRestoreInterrupts(enabled); + return 1; +} + +int EXISelect(long chan, unsigned long dev, unsigned long freq) { + struct EXIControl * exi; + unsigned long cpr; + int enabled; + + exi = &Ecb[chan]; + + ASSERTLINE(841, 0 <= chan && chan < MAX_CHAN); + ASSERTLINE(842, chan == 0 && dev < MAX_DEV || dev == 0); + ASSERTLINE(843, freq < MAX_FREQ); + ASSERTLINE(844, !(exi->state & STATE_SELECTED)); + + enabled = OSDisableInterrupts(); + if ((exi->state & 4) || ((chan != 2) && (((dev == 0) && !(exi->state & 8) && (__EXIProbe(chan) == 0)) || !(exi->state & 0x10) || (exi->dev != dev)))) { + OSRestoreInterrupts(enabled); + return 0; + } + exi->state |= 4; + cpr = __EXIRegs[(chan * 5)]; + cpr &= 0x405; + cpr |= (((1 << dev) << 7) | (freq * 0x10)); + __EXIRegs[(chan * 5)] = cpr; + if (exi->state & 8) { + switch (chan) { + case 0: + __OSMaskInterrupts(0x100000U); + break; + case 1: + __OSMaskInterrupts(0x20000U); + break; + } + } + OSRestoreInterrupts(enabled); + return 1; +} + +int EXIDeselect(long chan) { + struct EXIControl * exi; + unsigned long cpr; + int enabled; + + exi = &Ecb[chan]; + ASSERTLINE(895, 0 <= chan && chan < MAX_CHAN); + enabled = OSDisableInterrupts(); + if (!(exi->state & 4)) { + OSRestoreInterrupts(enabled); + return 0; + } + exi->state &= ~4; + cpr = __EXIRegs[(chan * 5)]; + __EXIRegs[(chan * 5)] = cpr & 0x405; + if (exi->state & 8) { + switch (chan) { + case 0: + __OSUnmaskInterrupts(0x100000U); + break; + case 1: + __OSUnmaskInterrupts(0x20000U); + break; + } + } + OSRestoreInterrupts(enabled); + if ((chan != 2) && (cpr & 0x80)) { + if (__EXIProbe(chan) != 0) { + return 1; + } + return 0; + } + return 1; +} + +static void EXIIntrruptHandler(signed short interrupt, struct OSContext * context) { + long chan; + struct EXIControl * exi; + EXICallback callback; + + chan = (interrupt-9)/3; + + ASSERTLINE(946, 0 <= chan && chan < MAX_CHAN); + exi = &Ecb[chan]; + EXIClearInterrupts(chan, 1, 0, 0); + callback = exi->exiCallback; + if (callback) { + OSContext exceptionContext; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + callback(chan, context); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +static void TCIntrruptHandler(signed short interrupt, struct OSContext * context) { + long chan; + struct EXIControl * exi; + EXICallback callback; + + chan = (interrupt-10)/3; + + ASSERTLINE(982, 0 <= chan && chan < MAX_CHAN); + exi = &Ecb[chan]; + __OSMaskInterrupts(0x80000000U >> interrupt); + EXIClearInterrupts(chan, 0, 1, 0); + callback = exi->tcCallback; + if (callback) { + OSContext exceptionContext; + + exi->tcCallback = NULL; + CompleteTransfer(chan); + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + callback(chan, context); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +static void EXTIntrruptHandler(signed short interrupt, struct OSContext * context) { + long chan; + struct EXIControl * exi; + EXICallback callback; + + chan = (interrupt-11)/3; + + ASSERTLINE(1023, 0 <= chan && chan < 2); + __OSMaskInterrupts(0x500000U >> (chan * 3)); + // __EXIRegs[(chan * 5)] = 0; + exi = &Ecb[chan]; + callback = exi->extCallback; + exi->state &= 0xFFFFFFF7; + if (callback) { + OSContext exceptionContext; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + exi->extCallback = NULL; + callback(chan, context); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +void EXIInit() { + __OSMaskInterrupts(0x7F8000U); + __EXIRegs[0] = 0; + __EXIRegs[5] = 0; + __EXIRegs[10] = 0; + __EXIRegs[0] = 0x2000; + __OSSetInterruptHandler(9, EXIIntrruptHandler); + __OSSetInterruptHandler(10, TCIntrruptHandler); + __OSSetInterruptHandler(11, EXTIntrruptHandler); + __OSSetInterruptHandler(12, EXIIntrruptHandler); + __OSSetInterruptHandler(13, TCIntrruptHandler); + __OSSetInterruptHandler(14, EXTIntrruptHandler); + __OSSetInterruptHandler(15, EXIIntrruptHandler); + __OSSetInterruptHandler(16, TCIntrruptHandler); + if (OSGetConsoleType() & 0x10000000) { + EXIProbeReset(); + } +} + +int EXILock(long chan, unsigned long dev, void (* unlockedCallback)(long, struct OSContext *)) { + struct EXIControl * exi; + int enabled; + int i; + + exi = &Ecb[chan]; + ASSERTLINE(1112, 0 <= chan && chan < MAX_CHAN); + ASSERTLINE(1113, chan == 0 && dev < MAX_DEV || dev == 0); + enabled = OSDisableInterrupts(); + + if (exi->state & 0x10) { + if (unlockedCallback) { + ASSERTLINE(1119, chan == 0 && exi->items < (MAX_DEV - 1) || exi->items == 0); + for(i = 0; i < exi->items; i++) { + if (exi->queue[i].dev == dev) { + OSRestoreInterrupts(enabled); + return 0; + } + } + exi->queue[exi->items].callback = unlockedCallback; + exi->queue[exi->items].dev = dev; + exi->items++; + } + OSRestoreInterrupts(enabled); + return 0; + } + ASSERTLINE(1135, exi->items == 0); + exi->state |= 0x10; + exi->dev = dev; + SetExiInterruptMask(chan, exi); + OSRestoreInterrupts(enabled); + return 1; +} + +int EXIUnlock(long chan) { + struct EXIControl * exi; + int enabled; + EXICallback unlockedCallback; + + exi = &Ecb[chan]; + ASSERTLINE(1159, 0 <= chan && chan < MAX_CHAN); + enabled = OSDisableInterrupts(); + if (!(exi->state & 0x10)) { + OSRestoreInterrupts(enabled); + return 0; + } + exi->state &= 0xFFFFFFEF; + SetExiInterruptMask(chan, exi); + if (exi->items > 0) { + unlockedCallback = exi->queue[0].callback; + if (--exi->items > 0) { + memmove(&exi->queue[0], &exi->queue[1], exi->items * 8); + } + unlockedCallback(chan, 0); + } + OSRestoreInterrupts(enabled); + return 1; +} + +unsigned long EXIGetState(long chan) { + struct EXIControl * exi; + + exi = &Ecb[chan]; + ASSERTLINE(1196, 0 <= chan && chan < MAX_CHAN); + return exi->state; +} + +static void UnlockedHandler(s32 chan, OSContext* context) { + u32 id; + + EXIGetID(chan, 0, &id); +} + +s32 EXIGetID(s32 chan, u32 dev, u32* id) { + EXIControl* exi = &Ecb[chan]; + int err; + u32 cmd; + s32 startTime; + BOOL enabled; + + ASSERTLINE(1233, 0 <= chan && chan < MAX_CHAN); + if ((chan < 2) && (dev == 0)) { + if ((__EXIProbe(chan) == 0)) { + return 0; + } + + if (exi->idTime == __gUnknown800030C0[chan]) { + *id = exi->id; + return exi->idTime; + } + + if (!__EXIAttach(chan, NULL)) { + return 0; + } + + startTime = __gUnknown800030C0[chan]; + } + + err = !EXILock(chan, dev, (chan < 2 && dev == 0) ? &UnlockedHandler : NULL); + if (err == 0) { + err = !EXISelect(chan, dev, 0); + if (err == 0) { + cmd = 0; + err |= !EXIImm(chan, &cmd, 2, 1, 0); + err |= !EXISync(chan); + err |= !EXIImm(chan, id, 4, 0, 0); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + } + + EXIUnlock(chan); + } + + if ((chan < 2) && (dev == 0)) { + EXIDetach(chan); + enabled = OSDisableInterrupts(); + err |= __gUnknown800030C0[chan] != startTime; + + if (!err) { + exi->id = *id; + exi->idTime = startTime; + } + + OSRestoreInterrupts(enabled); + + if (err) { + return 0; + } + + return exi->idTime; + } + + if (err) { + return 0; + } + + return 1; +} + +s32 EXIGetType(s32 chan, u32 dev, u32* type) { + u32 _type; + s32 probe; + + probe = EXIGetID(chan, dev, &_type); + + if (!probe) { + return probe; + } + + switch (_type & ~0xFF) { + case 0x04020300: + case 0x04020200: + case 0x04020100: + case 0x04060000: + *type = (_type & ~0xFF); + return probe; + default: + if ((_type & ~0xFFFF) == 0x04220000) { + *type = 0x04220000; + return probe; + } else { + *type = _type; + return probe; + } + } +} + +char* EXIGetTypeString(u32 type) { + switch (type) { + case 0x00000004: + return "Memory Card 59"; + case 0x00000008: + return "Memory Card 123"; + case 0x00000010: + return "Memory Card 251"; + case 0x00000020: + return "Memory Card 507"; + case 0x01010000: + return "USB Adapter"; + case 0x01020000: + return "NPDP-GDEV"; + case 0x02020000: + return "Modem"; + case 0x03010000: + return "Marlin"; + case 0x04120000: + return "AD16"; + case 0x04040404: + return "RS232C"; + case 0x80000004: + case 0x80000008: + case 0x80000010: + case 0x80000020: + return "Net Card"; + case 0x04020100: + case 0x04020200: + case 0x04020300: + case 0x04220000: + return "Ether"; + case 0x04060000: + return "Mic"; + case 0x04130000: + return "Stream Hanger"; + default: + return "Unknown"; + } +} diff --git a/src/static/GAEJ01_01/dolphin/exi/EXIUart.c b/src/static/GAEJ01_01/dolphin/exi/EXIUart.c new file mode 100644 index 00000000..62bbd836 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/exi/EXIUart.c @@ -0,0 +1,196 @@ +#include +#include +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +static s32 Chan; +static u32 Dev; +static u32 Enabled; +static u32 BarnacleEnabled; + +int InitializeUART(); +int ReadUARTN(); +int WriteUARTN(void *buf, u32 len); + +static BOOL ProbeBarnacle(s32 chan, u32 dev, u32* revision) { + int err; + u32 cmd; + + if (chan != 2 && dev == 0 && !EXIAttach(chan, NULL)) { + return FALSE; + } + + err = !EXILock(chan, dev, NULL); + if (!err) { + err = !EXISelect(chan, dev, 0); + if (!err) { + cmd = 0x20011300; + err = FALSE; + err |= !EXIImm(chan, &cmd, sizeof(cmd), 1, NULL); + err |= !EXISync(chan); + err |= !EXIImm(chan, revision, sizeof(revision), 0, NULL); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + } + + EXIUnlock(chan); + } + + if (chan != 2 && dev == 0) { + EXIDetach(chan); + } + + if (err) { + return FALSE; + } + + if (*revision != 0xFFFFFFFF) { + return TRUE; + } + + return FALSE; +} + +void __OSEnableBarnacle(s32 chan, u32 dev) { + u32 id; + + if (!EXIGetID(chan, dev, &id)) { + return; + } + + switch (id) { + case 0x00000004: + case 0x00000008: + case 0x00000010: + case 0x00000020: + case 0x01010000: + case 0x01020000: + case 0x02020000: + case 0x03010000: + case 0x04020100: + case 0x04020200: + case 0x04020300: + case 0x04220000: + case 0x04040404: + case 0x04060000: + case 0x04120000: + case 0x04130000: + case 0x80000004: + case 0x80000008: + case 0x80000010: + case 0x80000020: + case 0xFFFFFFFF: + break; + default: + if (ProbeBarnacle(chan, dev, &id)) { + Chan = chan; + Dev = dev; + Enabled = BarnacleEnabled = 0xA5FF005A; + break; + } + } +} + +int InitializeUART() { + if (BarnacleEnabled == 0xA5FF005A) { + return 0; + } + + if ((OSGetConsoleType() & 0x10000000) == 0) { + Enabled = 0; + return 2; + } + + Chan = 0; + Dev = 1; + Enabled = 0xA5FF005A; + return 0; +} + +int ReadUARTN() { + return 4; +} + +static int QueueLength(void) { + unsigned long cmd; + + if (EXISelect(Chan, Dev, 3) == 0) { + return -1; + } + cmd = 0x20010000; + EXIImm(Chan, &cmd, sizeof(cmd), 1, 0); + EXISync(Chan); + EXIImm(Chan, &cmd, 1, 0, 0); + EXISync(Chan); + EXIDeselect(Chan); + return 0x10 - (cmd >> 0x18); +} + +int WriteUARTN(void *buf, u32 len) { + unsigned long cmd; + BOOL interrupt; + int qLen; + long xLen; + char* ptr; + int locked; + int error; + + if ((Enabled -0xA5FF0000) != 0x5A) { + return 2; + } + + interrupt = OSDisableInterrupts(); + + locked = EXILock(Chan, Dev, 0); + if (locked == 0) { + OSRestoreInterrupts(interrupt); + return 0; + } + else { + ptr = (char*)buf; + } + + while ((u32)ptr - (u32)buf < len) { + if (*(s8*)ptr == 0xA) { + *ptr = 0xD; + } + ptr++; + } + error = 0; + cmd = 0xA0010000; + + while (len != 0) { + qLen = QueueLength(); + if (qLen < 0) { + error = 3; + break; + } + + if ((qLen >= 0xC) || (qLen >= len)) { + if (EXISelect(Chan, Dev, 3) == 0) { + error = 3; + break; + } + + EXIImm(Chan, &cmd, sizeof(cmd), 1, 0); + EXISync(Chan); + + while((qLen != 0) && (len != 0)) { + if ((qLen < 4) && (qLen < len)) { + break; + } + + xLen = len < 4 ? (long)len : 4; + + EXIImm(Chan, buf, xLen, 1, 0); + (char*)buf += xLen; + len -= xLen; + qLen -= xLen; + EXISync(Chan); + } + EXIDeselect(Chan); + } + } + EXIUnlock(Chan); + OSRestoreInterrupts(interrupt); + return error; +} diff --git a/src/static/GAEJ01_01/dolphin/gba/GBA.c b/src/static/GAEJ01_01/dolphin/gba/GBA.c new file mode 100644 index 00000000..a9f64371 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gba/GBA.c @@ -0,0 +1,102 @@ +#include "GBA/GBAPriv.h" +#include + +// local declarations +static BOOL OnReset(BOOL final); + +//.data +static OSResetFunctionInfo ResetFunctionInfo = {OnReset, 127, NULL, NULL}; + +//.bss +static GBASecParam SecParams[4]; +GBAControl __GBA[4]; + +//.sbss +BOOL __GBAReset; + +static void ShortCommandProc(s32 chan) { + GBAControl* gba = &__GBA[chan]; // r31 + + if (gba->ret != 0) { + return; + } + + if (gba->input[0] != 0 || gba->input[1] != 4) { + gba->ret = 1; + return; + } + + *gba->status = gba->input[2] & GBA_JSTAT_MASK; +} + +void GBAInit(void) { + GBAControl* gba; // r31 + s32 chan; // r30 + + for (chan = 0; chan < 4; chan++) { + gba = &__GBA[chan]; + gba->delay = OSMicrosecondsToTicks(60); + OSInitThreadQueue(&gba->threadQueue); + gba->param = &SecParams[chan]; + ASSERTLINE(90, (u32) gba->param % 32 == 0); + } + + OSInitAlarm(); + DSPInit(); + + __GBAReset = FALSE; + OSRegisterResetFunction(&ResetFunctionInfo); +} + +s32 GBAGetStatusAsync(s32 chan, u8* status, GBACallback callback) { + GBAControl* gba = &__GBA[chan]; // r31 + + if (gba->callback != NULL) { + return GBA_BUSY; + } + + gba->output[0] = 0; + gba->status = status; + gba->callback = callback; + return __GBATransfer(chan, 1, 3, ShortCommandProc); +} + +s32 GBAGetStatus(s32 chan, u8* status) { + GBAControl* gba = &__GBA[chan]; // r1+0x10 + s32 ret; // r31 + + ret = GBAGetStatusAsync(chan, status, &__GBASyncCallback); + if (ret != GBA_READY) { + return ret; + } + return __GBASync(chan); +} + +s32 GBAResetAsync(s32 chan, u8* status, GBACallback callback) { + GBAControl *gba = &__GBA[chan]; // r31 + + if (gba->callback != NULL) { + return GBA_BUSY; + } + + gba->output[0] = 0xFF; + gba->status = status; + gba->callback = callback; + return __GBATransfer(chan, 1, 3, ShortCommandProc); +} + +s32 GBAReset(s32 chan, u8* status) { + GBAControl* gba = &__GBA[chan]; // r1+0x10 + s32 ret; // r31 + + ret = GBAResetAsync(chan, status, (GBACallback)&__GBASyncCallback); + if (ret != GBA_READY) { + return ret; + } + return __GBASync(chan); +} + +static BOOL OnReset(BOOL final) { + __GBAReset = TRUE; + return TRUE; +} diff --git a/src/static/GAEJ01_01/dolphin/gba/GBAGetProcessStatus.c b/src/static/GAEJ01_01/dolphin/gba/GBAGetProcessStatus.c new file mode 100644 index 00000000..65de6aa9 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gba/GBAGetProcessStatus.c @@ -0,0 +1,40 @@ +#include "GBA/GBAPriv.h" +#include "dolphin/os/OSInterrupt.h" +#include "dolphin/os/OSTime.h" + +s32 GBAGetProcessStatus(s32 chan, u8* percentp) { + BOOL enabled; // r26 + s32 ret; // r29 + GBAControl* gba = &__GBA[chan]; // r25 + GBABootInfo* bootInfo; // r31 + u8 percent; // r30 + OSTime t; // r27 + + bootInfo = &__GBA[chan].bootInfo; + enabled = OSDisableInterrupts(); + if (bootInfo->callback != NULL) { + ret = GBA_BUSY; + percent = (bootInfo->curOffset * 100) / bootInfo->realLength; + if (bootInfo->begin != 0) { + t = OSGetTime() - bootInfo->begin; + if (OSTicksToMilliseconds(t) < 5500) { + percent = (percent * t) / OSMillisecondsToTicks(5500ll); + } + + if (percent >= 100) { + percent = 100; + } + } + + if (percentp != NULL) { + *percentp = percent; + } + } else if (gba->callback != NULL) { + ret = GBA_BUSY; + } else { + ret = GBA_READY; + } + + OSRestoreInterrupts(enabled); + return ret; +} diff --git a/src/static/GAEJ01_01/dolphin/gba/GBAJoyBoot.c b/src/static/GAEJ01_01/dolphin/gba/GBAJoyBoot.c new file mode 100644 index 00000000..aba4af48 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gba/GBAJoyBoot.c @@ -0,0 +1,385 @@ +#include "GBA/GBAPriv.h" + +#include "jaudio_NES/dsp_GBAKey.h" + +static volatile u8 D54[] = { + 0x18, 0xFC, 0xC0, 0x80, 0x7f, 0x40, 0x3f, 0x01, 0x00, 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x64, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x4b, 0x61, 0x77, 0x61, 0x73, 0x65, 0x64, 0x6f, 0x00, + 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xAC, 0xC4, 0xF8, 0x08, 0x10, 0xBF, 0x18, +}; + +// local declarations +static void F23(s32 chan, s32 ret); +static void F25(s32 chan, s32 ret); +static void F27(s32 chan, s32 ret); +static void F29(s32 chan, s32 ret); +static void F31(s32 chan, s32 ret); +static void F33(s32 chan, s32 ret); +static void F35(s32 chan, s32 ret); +static void F37(s32 chan, s32 ret); +static void F39(s32 chan, s32 ret); + +static u32 F72(u32 crc, u32 src, volatile u8* keyp) { + int i; // r31 + int poly; // r30 + + poly = (keyp[19] << 8) + ((keyp[21] + (keyp[24] - (keyp[24] << 4))) - keyp[16]); + for (i = keyp[1]; i > keyp[11]; i--) { + if ((src ^ crc) & 1) { + crc >>= 1; + crc ^= poly; + } + else { + crc >>= 1; + } + src >>= 1; + } + return crc; +} + +static u32 F95(u32 src, volatile u8* keyp) { + src = (src * ((keyp[3] << keyp[22]) | ((keyp[1] | (keyp[4] << keyp[17])) | (keyp[4] << keyp[24])))) - (keyp[7] - keyp[6]); + return src; +} + +static void F104(s32 chan, s32 ret) { + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r31 + GBACallback callback; // r30 + + bootInfo->begin = 0; + if (bootInfo->callback != NULL) { + callback = bootInfo->callback; + bootInfo->callback = NULL; + callback(chan, ret); + } +} + +s32 GBAJoyBootAsync(s32 chan, s32 paletteColor, s32 paletteSpeed, u8* programp, s32 length, u8* status, GBACallback callback) { + s32 ret; // r30 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r31 + u8 percent; // r1+0x24 + + if (chan & ~3) { + return GBA_JOYBOOT_ERR_INVALID; + } + + if (length == 0 || GBA_JOYBOOT_PROGRAM_SIZE_MAX < length) { + return GBA_JOYBOOT_ERR_INVALID; + } + + if (paletteSpeed < -4 || paletteSpeed > 4) { + return GBA_JOYBOOT_ERR_INVALID; + } + + if (paletteColor < 0 || paletteColor > 6) { + return GBA_JOYBOOT_ERR_INVALID; + } + + if ( !(programp[0xAC] * programp[0xAD] * programp[0xAE] * programp[0xAF]) ) { + return GBA_JOYBOOT_ERR_INVALID; + } + + ret = GBAGetProcessStatus(chan, &percent); + if (ret != GBA_READY) { + return ret; + } + + bootInfo->paletteColor = paletteColor; + bootInfo->paletteSpeed = paletteSpeed; + bootInfo->programp = programp; + bootInfo->length = length; + bootInfo->status = status; + bootInfo->callback = callback; + bootInfo->curOffset = D54[8]; + ret = GBAGetStatusAsync(chan, bootInfo->status, F23); + if (ret != GBA_READY) { + bootInfo->callback = NULL; + } + + return ret; +} + +static void F23(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r29 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r28 + + if (ret != GBA_READY || (ret = GBAResetAsync(chan, bootInfo->status, F25)) != GBA_READY) { + F104(chan, ret); + } + gba->ret = ret; +} + +static void F25(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r28 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r29 + + if (ret == GBA_READY && *bootInfo->status != D54[37]) { + ret = GBA_JOYBOOT_UNKNOWN_STATE; + } + if (ret != GBA_READY || (ret = GBAGetStatusAsync(chan, bootInfo->status, F27)) != GBA_READY) { + F104(chan, ret); + } + gba->ret = ret; +} + +static void F27(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r28 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r29 + + if (ret == GBA_READY && *bootInfo->status != D54[0]) { + ret = GBA_JOYBOOT_UNKNOWN_STATE; + } + if (ret != GBA_READY || (ret = GBAReadAsync(chan, bootInfo->readbuf, bootInfo->status, F29)) != GBA_READY) { + F104(chan, ret); + } + gba->ret = ret; +} + +static void F29(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r29 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r28 + + if (ret == GBA_READY) { + __GBAX02(chan, bootInfo->readbuf); + } + else { + F104(chan, ret); + } + gba->ret = ret; +} + +void __GBAX01(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r28 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r31 + int val200; // r27 + + if (ret == GBA_READY) { + bootInfo->keyA = gba->param->keyA; + bootInfo->keyB = gba->param->keyB; + if (bootInfo->readbuf[3] == 0 || bootInfo->readbuf[2] == 0 || + (bootInfo->keyA & (D54[5] << 9)) == 0 || bootInfo->readbuf[1] == 0 || + (bootInfo->keyA >> 15) == 0 || bootInfo->readbuf[0] == 0) { + ret = GBA_JOYBOOT_UNKNOWN_STATE; + } + else { + bootInfo->i = ~D54[36] & (bootInfo->length + D54[36]); + val200 = D54[20] << D54[33]; + + if (bootInfo->i < val200) { + bootInfo->i = val200; + } + + bootInfo->realLength = bootInfo->i; + bootInfo->i -= val200; + bootInfo->i >>= D54[32]; + bootInfo->writebuf[0] = (u8)(bootInfo->keyB >> 0); + bootInfo->writebuf[1] = (u8)(bootInfo->keyB >> 8); + bootInfo->writebuf[3] = (u8)(bootInfo->keyB >> 24); + bootInfo->writebuf[2] = (u8)(bootInfo->keyB >> 16); + bootInfo->crc = (D54[38] + 1) << D54[34]; + bootInfo->curOffset = D54[8]; + bootInfo->begin = OSGetTime(); + bootInfo->firstXfer = TRUE; + ret = GBAWriteAsync(chan, bootInfo->writebuf, bootInfo->status, F31); + } + } + + if (ret != GBA_READY) { + F104(chan, ret); + } + gba->ret = ret; +} + +static void F31(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r26 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r31 + u32 writeWord; // r29 + + if (ret == GBA_READY) { + if (bootInfo->firstXfer != FALSE) { + bootInfo->firstXfer = FALSE; + } + else if ((*bootInfo->status & D54[20]) == 0 || + (*bootInfo->status & D54[42]) >> D54[33] != + (bootInfo->curOffset & D54[33]) >> D54[31]) { + ret = GBA_JOYBOOT_UNKNOWN_STATE; + goto exit; + } else { + bootInfo->curOffset -= D54[25] - D54[23]; + } + + if (bootInfo->curOffset <= bootInfo->realLength) { + if (bootInfo->curOffset < bootInfo->realLength) { + writeWord = D54[29]; + for (bootInfo->i = D54[29]; bootInfo->i < D54[33]; bootInfo->i++) { + if (bootInfo->length) { + writeWord |= *(bootInfo->programp++) << (bootInfo->i * D54[37]); + bootInfo->length--; + } + } + + if (bootInfo->curOffset == D54[38]) { + bootInfo->initialCode = writeWord; + } + else if (bootInfo->curOffset == D54[39]) { + writeWord = chan << D54[37]; + } + + if (bootInfo->curOffset >= D54[2]) { + bootInfo->crc = F72(bootInfo->crc, writeWord, &D54[19]); + } + + if (bootInfo->curOffset == D54[40] + 0x100) { + bootInfo->dummyWord[0] = writeWord; + } + else if (bootInfo->curOffset == D54[1] + 0x100) { + bootInfo->i = D54[7]; + bootInfo->dummyWord[bootInfo->i] = writeWord; + } + } + else { + writeWord = bootInfo->crc | (bootInfo->curOffset << 16); + } + + if (bootInfo->curOffset > D54[43]) { + bootInfo->keyA = F95(bootInfo->keyA, &D54[20]); + writeWord ^= bootInfo->keyA; + writeWord ^= -(bootInfo->curOffset + (D54[11] << 20)); + writeWord ^= D54[11] | (D54[11] << 24) | (D54[19] << 16) | (D54[18] << 8); + } + + bootInfo->writebuf[3] = writeWord >> D54[0]; + bootInfo->writebuf[0] = writeWord >> D54[30]; + bootInfo->writebuf[1] = writeWord >> D54[41]; + bootInfo->writebuf[2] = writeWord >> D54[42]; + + if (bootInfo->curOffset == D54[1] + D54[1]) { + bootInfo->dummyWord[2] = writeWord; + } + + if (bootInfo->i < D54[33]) { + bootInfo->dummyWord[3 - (1 - bootInfo->i)] = writeWord; + bootInfo->dummyWord[5 - bootInfo->i] = + bootInfo->dummyWord[2 - (1 - bootInfo->i)] * bootInfo->dummyWord[4 - bootInfo->i]; + bootInfo->dummyWord[5 - (1 - bootInfo->i)] = + bootInfo->dummyWord[1 - bootInfo->i] * bootInfo->dummyWord[bootInfo->i]; + bootInfo->dummyWord[7 - bootInfo->i] = + bootInfo->dummyWord[-(1 - bootInfo->i)] * bootInfo->dummyWord[4 - bootInfo->i]; + } + + ret = GBAWriteAsync(chan, bootInfo->writebuf, bootInfo->status, F31); + } + else { + bootInfo->start = OSGetTick(); + ret = GBAReadAsync(chan, bootInfo->readbuf, bootInfo->status, F33); + } + } + +exit: + if (ret != GBA_READY) { + F104(chan, ret); + } + gba->ret = ret; +} + +static void F33(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r27 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r31 + + if (ret == GBA_READY) { + for (bootInfo->i = 33; bootInfo->i < 36; bootInfo->i++) { + ret = (bootInfo->readbuf[3] ^ (bootInfo->dummyWord[D54[bootInfo->i]] >> 24) | + bootInfo->readbuf[2] ^ (bootInfo->dummyWord[D54[bootInfo->i]] >> 16) | + bootInfo->readbuf[1] ^ (bootInfo->dummyWord[D54[bootInfo->i]] >> 8) | + bootInfo->readbuf[0] ^ (bootInfo->dummyWord[D54[bootInfo->i]] >> 0)) << 24; + + if (ret == GBA_READY) { + break; + } + } + + if (ret != GBA_READY) { + ret = GBA_JOYBOOT_UNKNOWN_STATE; + } + else { + bootInfo->start = OSGetTick(); + ret = GBAGetStatusAsync(chan, bootInfo->status, F35); + } + } + + if (ret != GBA_READY) { + F104(chan, ret); + } + gba->ret = ret; +} + +static void F35(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r28 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r30 + + if (ret == GBA_READY) { + if (OSSecondsToTicks(10) <= OSGetTick() - bootInfo->start) { + ret = GBA_JOYBOOT_UNKNOWN_STATE; + } + else if ((*bootInfo->status & 0x32) != 0) { + ret = GBA_JOYBOOT_UNKNOWN_STATE; + } + else if (*bootInfo->status != 8) { + ret = GBAGetStatusAsync(chan, bootInfo->status, F35); + } + else { + __GBASetDelay(chan, OSMillisecondsToTicks(8)); + ret = GBAReadAsync(chan, bootInfo->readbuf, bootInfo->status, F37); + __GBASetDelay(chan, OSMicrosecondsToTicks(60)); + } + } + + if (ret != GBA_READY) { + F104(chan, ret); + } + gba->ret = ret; +} + +static void F37(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r28 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r31 + + if (ret == GBA_READY) { + if ((bootInfo->readbuf[3] ^ (bootInfo->initialCode >> 24) | + bootInfo->readbuf[2] ^ (bootInfo->initialCode >> 16) | + bootInfo->readbuf[1] ^ (bootInfo->initialCode >> 8) | + bootInfo->readbuf[0] ^ (bootInfo->initialCode >> 0)) << 24) { + ret = GBA_JOYBOOT_UNKNOWN_STATE; + } + else { + ret = GBAWriteAsync(chan, bootInfo->readbuf, bootInfo->status, F39); + } + } + + if (ret != GBA_READY) { + F104(chan, ret); + } + gba->ret = ret; +} + +static void F39(s32 chan, s32 ret) { + GBAControl* gba = &__GBA[chan]; // r29 + GBABootInfo* bootInfo = &__GBA[chan].bootInfo; // r28 + + if (ret == GBA_READY) { + *bootInfo->status = 0; + } + + F104(chan, ret); + gba->ret = ret; +} + +s32 GBAJoyBoot(s32 chan, s32 paletteColor, s32 paletteSpeed, u8* programp, s32 length, u8* status) { + s32 ret; // r31 + + ret = GBAJoyBootAsync(chan, paletteColor, paletteSpeed, programp, length, status, &__GBASyncCallback); + if (ret != GBA_READY) { + return ret; + } + return __GBASync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/gba/GBARead.c b/src/static/GAEJ01_01/dolphin/gba/GBARead.c new file mode 100644 index 00000000..1cfa182e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gba/GBARead.c @@ -0,0 +1,40 @@ +#include "GBA/GBAPriv.h" + +static void ReadProc(s32 chan) { + GBAControl* gba; + gba = &__GBA[chan]; + + if (gba->ret == 0) { + memcpy(gba->ptr, gba->input, 4); + gba->status[0] = gba->input[4] & GBA_JSTAT_MASK; + } +} + +s32 GBAReadAsync(s32 chan, u8* dst, u8* status, GBACallback callback) { + GBAControl* gba; + + gba = &__GBA[chan]; + + if (gba->callback != NULL) { + return 2; + } + + gba->output[0] = 0x14; + gba->ptr = dst; + gba->status = status; + gba->callback = callback; + + return __GBATransfer(chan, 1, 5, ReadProc); +} + +s32 GBARead(s32 chan, u8* dst, u8* status) { + s32 tmp; + GBAControl* gba = &__GBA[chan]; + s32 ret; + ret = GBAReadAsync(chan, dst, status, __GBASyncCallback); + if (ret != GBA_READY) { + return ret; + } + + return __GBASync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/gba/GBAWrite.c b/src/static/GAEJ01_01/dolphin/gba/GBAWrite.c new file mode 100644 index 00000000..32a4991b --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gba/GBAWrite.c @@ -0,0 +1,37 @@ +#include "GBA/GBAPriv.h" + +static void WriteProc(s32 chan) { + GBAControl* gba; + gba = &__GBA[chan]; + + if (gba->ret != 0) { + return; + } + + gba->status[0] = gba->input[0] & GBA_JSTAT_MASK; +} + +s32 GBAWriteAsync(s32 chan, u8* src, u8* status, GBACallback callback) { + GBAControl* gba = &__GBA[chan]; + + if (gba->callback != NULL) { + return GBA_BUSY; + } + gba->output[0] = 0x15; + memcpy(&gba->output[1], src, 4); + gba->ptr = src; + gba->status = status; + gba->callback = callback; + return __GBATransfer(chan, 5, 1, WriteProc); +} + +s32 GBAWrite(s32 chan, u8* src, u8* status) { + s32 tmp; + GBAControl* gba = &__GBA[chan]; + s32 ret; + ret = GBAWriteAsync(chan, src, status, __GBASyncCallback); + if (ret != GBA_READY) { + return ret; + } + return __GBASync(chan); +} diff --git a/src/static/GAEJ01_01/dolphin/gba/GBAXfer.c b/src/static/GAEJ01_01/dolphin/gba/GBAXfer.c new file mode 100644 index 00000000..039c3913 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gba/GBAXfer.c @@ -0,0 +1,123 @@ +#include "GBA/GBAPriv.h" +#include + +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; + } + + 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, u32 w1, u32 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; +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXAttr.c b/src/static/GAEJ01_01/dolphin/gx/GXAttr.c new file mode 100644 index 00000000..4c3c9f4f --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXAttr.c @@ -0,0 +1,482 @@ +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +static void __GXXfVtxSpecs(void) +{ + u32 normCount, colorCount, texCount; + + normCount = gx->hasBiNrms ? 2 : (gx->hasNrms ? 1 : 0); + + // Both fields in one access + colorCount = 33 - __cntlzw((gx->vcdLo & (0xf << 0xd)) >> 0xd); + colorCount /= 2; // equivalent to /=2 and >>= 1 + + // All 16 assigned bits in VCD_Hi + texCount = 33 - __cntlzw((gx->vcdHi & (0xffff << 0)) >> 0); + texCount /= 2; // equivalent to /=2 and >>= 1 + + GX_XF_LOAD_REG(GX_XF_REG_INVERTEXSPEC, (colorCount) | (normCount << 2) | (texCount << 4)); + gx->bpSentNot = GX_TRUE; + + return; +} + +void GXSetVtxDesc(GXAttr attr, GXAttrType type) +{ + switch (attr) { + case GX_VA_PNMTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_POSMTXIDX_ST, GX_CP_VCD_LO_POSMTXIDX_END); + break; + case GX_VA_TEX0MTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_TEX0MTXIDX_ST, GX_CP_VCD_LO_TEX0MTXIDX_END); + break; + case GX_VA_TEX1MTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_TEX1MTXIDX_ST, GX_CP_VCD_LO_TEX1MTXIDX_END); + break; + case GX_VA_TEX2MTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_TEX2MTXIDX_ST, GX_CP_VCD_LO_TEX2MTXIDX_END); + break; + case GX_VA_TEX3MTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_TEX3MTXIDX_ST, GX_CP_VCD_LO_TEX3MTXIDX_END); + break; + case GX_VA_TEX4MTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_TEX4MTXIDX_ST, GX_CP_VCD_LO_TEX4MTXIDX_END); + break; + case GX_VA_TEX5MTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_TEX5MTXIDX_ST, GX_CP_VCD_LO_TEX5MTXIDX_END); + break; + case GX_VA_TEX6MTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_TEX6MTXIDX_ST, GX_CP_VCD_LO_TEX6MTXIDX_END); + break; + case GX_VA_TEX7MTXIDX: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_TEX7MTXIDX_ST, GX_CP_VCD_LO_TEX7MTXIDX_END); + break; + case GX_VA_POS: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_POS_ST, GX_CP_VCD_LO_POS_END); + break; + case GX_VA_NRM: + if (type != GX_NONE) { + gx->hasNrms = TRUE; + gx->hasBiNrms = FALSE; + gx->nrmType = type; + } else { + gx->hasNrms = FALSE; + } + break; + case GX_VA_NBT: + if (type != GX_NONE) { + gx->hasBiNrms = TRUE; + gx->hasNrms = FALSE; + gx->nrmType = type; + } else { + gx->hasBiNrms = FALSE; + } + break; + case GX_VA_CLR0: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_CLRDIF_ST, GX_CP_VCD_LO_CLRDIF_END); + break; + case GX_VA_CLR1: + GX_SET_REG(gx->vcdLo, type, GX_CP_VCD_LO_CLRSPEC_ST, GX_CP_VCD_LO_CLRSPEC_END); + break; + case GX_VA_TEX0: + GX_SET_REG(gx->vcdHi, type, GX_CP_VCD_HI_TEX0COORD_ST, GX_CP_VCD_HI_TEX0COORD_END); + break; + case GX_VA_TEX1: + GX_SET_REG(gx->vcdHi, type, GX_CP_VCD_HI_TEX1COORD_ST, GX_CP_VCD_HI_TEX1COORD_END); + break; + case GX_VA_TEX2: + GX_SET_REG(gx->vcdHi, type, GX_CP_VCD_HI_TEX2COORD_ST, GX_CP_VCD_HI_TEX2COORD_END); + break; + case GX_VA_TEX3: + GX_SET_REG(gx->vcdHi, type, GX_CP_VCD_HI_TEX3COORD_ST, GX_CP_VCD_HI_TEX3COORD_END); + break; + case GX_VA_TEX4: + GX_SET_REG(gx->vcdHi, type, GX_CP_VCD_HI_TEX4COORD_ST, GX_CP_VCD_HI_TEX4COORD_END); + break; + case GX_VA_TEX5: + GX_SET_REG(gx->vcdHi, type, GX_CP_VCD_HI_TEX5COORD_ST, GX_CP_VCD_HI_TEX5COORD_END); + break; + case GX_VA_TEX6: + GX_SET_REG(gx->vcdHi, type, GX_CP_VCD_HI_TEX6COORD_ST, GX_CP_VCD_HI_TEX6COORD_END); + break; + case GX_VA_TEX7: + GX_SET_REG(gx->vcdHi, type, GX_CP_VCD_HI_TEX7COORD_ST, GX_CP_VCD_HI_TEX7COORD_END); + break; + } + + if (gx->hasNrms || gx->hasBiNrms) { + GX_SET_REG(gx->vcdLo, gx->nrmType, GX_CP_VCD_LO_NRM_ST, GX_CP_VCD_LO_NRM_END); + } else { + GX_SET_REG(gx->vcdLo, GX_NONE, GX_CP_VCD_LO_NRM_ST, GX_CP_VCD_LO_NRM_END); + } + + gx->dirtyState |= GX_DIRTY_VCD; +} + +void __GXSetVCD(void) +{ + + GX_CP_LOAD_REG(GX_CP_REG_VCD_LO, gx->vcdLo); + GX_CP_LOAD_REG(GX_CP_REG_VCD_HI, gx->vcdHi); + + __GXXfVtxSpecs(); +} + +void __GXCalculateVLim(void) +{ + static u8 tbl1[] = { 0, 4, 1, 2 }; + static u8 tbl2[] = { 0, 8, 1, 2 }; + static u8 tbl3[] = { 0, 12, 1, 2 }; + + u32 vlim; + u32 vcdLo; + u32 vcdHi; + s32 compCnt; + + if (gx->vNum == 0) { + return; + } + + vcdLo = gx->vcdLo; + vcdHi = gx->vcdHi; + + // GXCompCnt bit of normal parameters + compCnt = gx->vatA[GX_VTXFMT0]; + compCnt = (compCnt & 0x200) >> 9; + + vlim = GX_GET_REG(vcdLo, GX_CP_VCD_LO_POSMTXIDX_ST, GX_CP_VCD_LO_POSMTXIDX_END); + vlim += GX_GET_REG(vcdLo, GX_CP_VCD_LO_TEX0MTXIDX_ST, GX_CP_VCD_LO_TEX0MTXIDX_END); + vlim += GX_GET_REG(vcdLo, GX_CP_VCD_LO_TEX1MTXIDX_ST, GX_CP_VCD_LO_TEX1MTXIDX_END); + vlim += GX_GET_REG(vcdLo, GX_CP_VCD_LO_TEX2MTXIDX_ST, GX_CP_VCD_LO_TEX2MTXIDX_END); + vlim += GX_GET_REG(vcdLo, GX_CP_VCD_LO_TEX3MTXIDX_ST, GX_CP_VCD_LO_TEX3MTXIDX_END); + vlim += GX_GET_REG(vcdLo, GX_CP_VCD_LO_TEX4MTXIDX_ST, GX_CP_VCD_LO_TEX4MTXIDX_END); + vlim += GX_GET_REG(vcdLo, GX_CP_VCD_LO_TEX5MTXIDX_ST, GX_CP_VCD_LO_TEX5MTXIDX_END); + vlim += GX_GET_REG(vcdLo, GX_CP_VCD_LO_TEX6MTXIDX_ST, GX_CP_VCD_LO_TEX6MTXIDX_END); + vlim += GX_GET_REG(vcdLo, GX_CP_VCD_LO_TEX7MTXIDX_ST, GX_CP_VCD_LO_TEX7MTXIDX_END); + + vlim += tbl3[GX_GET_REG(vcdLo, GX_CP_VCD_LO_POS_ST, GX_CP_VCD_LO_POS_END)]; + vlim += tbl3[GX_GET_REG(vcdLo, GX_CP_VCD_LO_NRM_ST, GX_CP_VCD_LO_NRM_END)] * (compCnt == GX_NRM_NBT ? 3 : 1); + vlim += tbl1[GX_GET_REG(vcdLo, GX_CP_VCD_LO_CLRDIF_ST, GX_CP_VCD_LO_CLRDIF_END)]; + vlim += tbl1[GX_GET_REG(vcdLo, GX_CP_VCD_LO_CLRSPEC_ST, GX_CP_VCD_LO_CLRSPEC_END)]; + + vlim += tbl2[GX_GET_REG(vcdHi, GX_CP_VCD_HI_TEX0COORD_ST, GX_CP_VCD_HI_TEX0COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHi, GX_CP_VCD_HI_TEX1COORD_ST, GX_CP_VCD_HI_TEX1COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHi, GX_CP_VCD_HI_TEX2COORD_ST, GX_CP_VCD_HI_TEX2COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHi, GX_CP_VCD_HI_TEX3COORD_ST, GX_CP_VCD_HI_TEX3COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHi, GX_CP_VCD_HI_TEX4COORD_ST, GX_CP_VCD_HI_TEX4COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHi, GX_CP_VCD_HI_TEX5COORD_ST, GX_CP_VCD_HI_TEX5COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHi, GX_CP_VCD_HI_TEX6COORD_ST, GX_CP_VCD_HI_TEX6COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHi, GX_CP_VCD_HI_TEX7COORD_ST, GX_CP_VCD_HI_TEX7COORD_END)]; + + gx->vLim = vlim; +} + +void GXClearVtxDesc(void) +{ + gx->vcdLo = 0; + GX_SET_REG(gx->vcdLo, GX_DIRECT, GX_CP_VCD_LO_POS_ST, GX_CP_VCD_LO_POS_END); + gx->vcdHi = 0; + gx->hasNrms = FALSE; + gx->hasBiNrms = FALSE; + gx->dirtyState |= GX_DIRTY_VCD; +} + +static inline void SETVAT(u32* vatA, u32* vatB, u32* vatC, GXAttr attr, GXCompCnt compCnt, GXCompType compType, u8 shift) +{ + switch (attr) { + case GX_VA_POS: + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_POS_CNT_ST, GX_CP_VAT_GRP0_POS_CNT_END); + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_POS_TYPE_ST, GX_CP_VAT_GRP0_POS_TYPE_END); + GX_SET_REG(*vatA, shift, GX_CP_VAT_GRP0_POS_SHIFT_ST, GX_CP_VAT_GRP0_POS_SHIFT_END); + break; + case GX_VA_NRM: + case GX_VA_NBT: + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_NRM_TYPE_ST, GX_CP_VAT_GRP0_NRM_TYPE_END); + if (compCnt == GX_NRM_NBT3) { + // Probably because the compCnt can only be one bit? + GX_SET_REG(*vatA, GX_NRM_NBT, GX_CP_VAT_GRP0_NRM_CNT_ST, GX_CP_VAT_GRP0_NRM_CNT_END); + GX_SET_REG(*vatA, TRUE, GX_CP_VAT_GRP0_NRMIDX3_ST, GX_CP_VAT_GRP0_NRMIDX3_END); + } else { + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_NRM_CNT_ST, GX_CP_VAT_GRP0_NRM_CNT_END); + GX_SET_REG(*vatA, FALSE, GX_CP_VAT_GRP0_NRMIDX3_ST, GX_CP_VAT_GRP0_NRMIDX3_END); + } + break; + case GX_VA_CLR0: + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_CLRDIFF_CNT_ST, GX_CP_VAT_GRP0_CLRDIFF_CNT_END); + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_CLRDIFF_TYPE_ST, GX_CP_VAT_GRP0_CLRDIFF_TYPE_END); + break; + case GX_VA_CLR1: + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_CLRSPEC_CNT_ST, GX_CP_VAT_GRP0_CLRSPEC_CNT_END); + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_CLRSPEC_TYPE_ST, GX_CP_VAT_GRP0_CLRSPEC_TYPE_END); + break; + case GX_VA_TEX0: + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_TXC0_CNT_ST, GX_CP_VAT_GRP0_TXC0_CNT_END); + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_TXC0_TYPE_ST, GX_CP_VAT_GRP0_TXC0_TYPE_END); + GX_SET_REG(*vatA, shift, GX_CP_VAT_GRP0_TXC0_SHIFT_ST, GX_CP_VAT_GRP0_TXC0_SHIFT_END); + break; + case GX_VA_TEX1: + GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC1_CNT_ST, GX_CP_VAT_GRP1_TXC1_CNT_END); + GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC1_TYPE_ST, GX_CP_VAT_GRP1_TXC1_TYPE_END); + GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC1_SHIFT_ST, GX_CP_VAT_GRP1_TXC1_SHIFT_END); + break; + case GX_VA_TEX2: + GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC2_CNT_ST, GX_CP_VAT_GRP1_TXC2_CNT_END); + GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC2_TYPE_ST, GX_CP_VAT_GRP1_TXC2_TYPE_END); + GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC2_SHIFT_ST, GX_CP_VAT_GRP1_TXC2_SHIFT_END); + break; + case GX_VA_TEX3: + GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC3_CNT_ST, GX_CP_VAT_GRP1_TXC3_CNT_END); + GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC3_TYPE_ST, GX_CP_VAT_GRP1_TXC3_TYPE_END); + GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC3_SHIFT_ST, GX_CP_VAT_GRP1_TXC3_SHIFT_END); + break; + case GX_VA_TEX4: + GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC4_CNT_ST, GX_CP_VAT_GRP1_TXC4_CNT_END); + GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC4_TYPE_ST, GX_CP_VAT_GRP1_TXC4_TYPE_END); + GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC4_SHIFT_ST, GX_CP_VAT_GRP2_TXC4_SHIFT_END); + break; + case GX_VA_TEX5: + GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC5_CNT_ST, GX_CP_VAT_GRP2_TXC5_CNT_END); + GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC5_TYPE_ST, GX_CP_VAT_GRP2_TXC5_TYPE_END); + GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC5_SHIFT_ST, GX_CP_VAT_GRP2_TXC5_SHIFT_END); + break; + case GX_VA_TEX6: + GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC6_CNT_ST, GX_CP_VAT_GRP2_TXC6_CNT_END); + GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC6_TYPE_ST, GX_CP_VAT_GRP2_TXC6_TYPE_END); + GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC6_SHIFT_ST, GX_CP_VAT_GRP2_TXC6_SHIFT_END); + break; + case GX_VA_TEX7: + GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC7_CNT_ST, GX_CP_VAT_GRP2_TXC7_CNT_END); + GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC7_TYPE_ST, GX_CP_VAT_GRP2_TXC7_TYPE_END); + GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC7_SHIFT_ST, GX_CP_VAT_GRP2_TXC7_SHIFT_END); + break; + } +} + +void GXSetVtxAttrFmt(GXVtxFmt format, GXAttr attr, GXCompCnt count, GXCompType type, u8 frac) +{ + u32* vA = &gx->vatA[format]; + u32* vB = &gx->vatB[format]; + u32* vC = &gx->vatC[format]; + + SETVAT(vA, vB, vC, attr, count, type, frac); + + gx->dirtyState |= GX_DIRTY_VAT; + gx->dirtyVAT |= (u8)(1 << (u8)format); +} + +void GXSetVtxAttrFmtv(GXVtxFmt format, const GXVtxAttrFmtList* list) +{ + u32* vatA; + u32* vatB; + u32* vatC; + + vatA = &gx->vatA[format]; + vatB = &gx->vatB[format]; + vatC = &gx->vatC[format]; + + for (; list->attr != GX_VA_NULL; list++) { + SETVAT(vatA, vatB, vatC, list->attr, list->cnt, list->type, list->frac); + } + + gx->dirtyState |= GX_DIRTY_VAT; + gx->dirtyVAT |= (u8)(1 << (u8)format); +} + +void __GXSetVAT(void) +{ + u8 i; + for (i = 0; i < 8; i++) { + if (gx->dirtyVAT & (1 << (u8)i)) { + GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP0 | i, gx->vatA[i]); + GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP1 | i, gx->vatB[i]); + GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP2 | i, gx->vatC[i]); + } + } + + gx->dirtyVAT = 0; +} + +void GXSetArray(GXAttr attr, const void* basePtr, u8 stride) +{ + s32 idx; + s32 newAttr; + s32 attrReg; + + newAttr = attr; + if (newAttr == GX_VA_NBT) { + newAttr = GX_VA_NRM; + } + + attrReg = newAttr - GX_VA_POS; + + GX_CP_LOAD_REG(GX_BP_REG_SETMODE0_TEX4 | attrReg, + // Address -> offset? + (u32)basePtr & ~0xC0000000); + + idx = attrReg - 12; + if (idx >= 0 && idx < 4) { + gx->indexBase[idx] = (u32)basePtr & ~0xC0000000; + } + + GX_CP_LOAD_REG(GX_BP_REG_SETIMAGE2_TEX4 | attrReg, stride); + + idx = attrReg - 12; + if (idx >= 0 && idx < 4) { + gx->indexStride[idx] = stride; + } +} + +void GXInvalidateVtxCache(void) +{ + GX_WRITE_U8(GX_FIFO_CMD_INVAL_VTX); +} + +void GXSetTexCoordGen2(GXTexCoordID id, GXTexGenType type, GXTexGenSrc src, u32 texMtxIdx, GXBool normalize, u32 dualTexMtxIdx) +{ + u32 reg; + u32 inputRow; + GXXfTexReg inputForm; + + reg = 0; + inputForm = GX_XF_TEX_FORM_AB11; + inputRow = 5; + + switch (src) { + case GX_TG_POS: + inputRow = 0; + inputForm = GX_XF_TEX_FORM_ABC1; + break; + case GX_TG_NRM: + inputRow = 1; + inputForm = GX_XF_TEX_FORM_ABC1; + break; + case GX_TG_BINRM: + inputRow = 3; + inputForm = GX_XF_TEX_FORM_ABC1; + break; + case GX_TG_TANGENT: + inputRow = 4; + inputForm = GX_XF_TEX_FORM_ABC1; + break; + case GX_TG_COLOR0: + inputRow = 2; + break; + case GX_TG_COLOR1: + inputRow = 2; + break; + case GX_TG_TEX0: + inputRow = 5; + break; + case GX_TG_TEX1: + inputRow = 6; + break; + case GX_TG_TEX2: + inputRow = 7; + break; + case GX_TG_TEX3: + inputRow = 8; + break; + case GX_TG_TEX4: + inputRow = 9; + break; + case GX_TG_TEX5: + inputRow = 10; + break; + case GX_TG_TEX6: + inputRow = 11; + break; + case GX_TG_TEX7: + inputRow = 12; + break; + } + + switch (type) { + case GX_TG_NRM: + // reg = 0; + GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST, GX_XF_TEX_PROJTYPE_END); // 2x4 projection + GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END); + GX_SET_REG(reg, GX_TG_POS, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END); + break; + case GX_TG_POS: + // reg = 0; + GX_SET_REG(reg, GX_XF_TEX_PROJ_STQ, GX_XF_TEX_PROJTYPE_ST, GX_XF_TEX_PROJTYPE_END); // 3x4 projection + GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END); + GX_SET_REG(reg, GX_TG_POS, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END); + break; + case GX_TG_BUMP0: + case GX_TG_BUMP1: + case GX_TG_BUMP2: + case GX_TG_BUMP3: + case GX_TG_BUMP4: + case GX_TG_BUMP5: + case GX_TG_BUMP6: + case GX_TG_BUMP7: + // reg = 0; + GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST, GX_XF_TEX_PROJTYPE_END); // 2x4 projection + GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END); + GX_SET_REG(reg, GX_TG_NRM, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END); + GX_SET_REG(reg, src - GX_TG_TEXCOORD0, GX_XF_TEX_BUMPSRCTEX_ST, GX_XF_TEX_BUMPSRCTEX_END); + GX_SET_REG(reg, type - GX_TG_BUMP0, GX_XF_TEX_BUMPSRCLIGHT_ST, GX_XF_TEX_BUMPSRCLIGHT_END); + break; + case GX_TG_SRTG: + // reg = 0; + GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST, GX_XF_TEX_PROJTYPE_END); // 2x4 projection + GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END); + + if (src == GX_TG_COLOR0) { + GX_SET_REG(reg, GX_XF_TG_CLR0, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + } else { + GX_SET_REG(reg, GX_XF_TG_CLR1, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + } + GX_SET_REG(reg, 2, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END); + break; + default: + break; + } + + GX_XF_LOAD_REG(GX_XF_REG_TEX0 + id, reg); + + reg = 0; + GX_SET_REG(reg, dualTexMtxIdx - 0x40, GX_XF_MTXIDX0_GEOM_ST, GX_XF_MTXIDX0_GEOM_END); + GX_SET_REG(reg, normalize, GX_XF_DUALTEX_NORMALISE_ST, GX_XF_DUALTEX_NORMALISE_END); + + GX_XF_LOAD_REG(GX_XF_REG_DUALTEX0 + id, reg); + + switch (id) { + case GX_TEXCOORD0: + GX_SET_REG(gx->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX0_ST, GX_XF_MTXIDX0_TEX0_END); + break; + case GX_TEXCOORD1: + GX_SET_REG(gx->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX1_ST, GX_XF_MTXIDX0_TEX1_END); + break; + case GX_TEXCOORD2: + GX_SET_REG(gx->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX2_ST, GX_XF_MTXIDX0_TEX2_END); + break; + case GX_TEXCOORD3: + GX_SET_REG(gx->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX3_ST, GX_XF_MTXIDX0_TEX3_END); + break; + case GX_TEXCOORD4: + GX_SET_REG(gx->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX4_ST, GX_XF_MTXIDX1_TEX4_END); + break; + case GX_TEXCOORD5: + GX_SET_REG(gx->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX5_ST, GX_XF_MTXIDX1_TEX5_END); + break; + case GX_TEXCOORD6: + GX_SET_REG(gx->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX6_ST, GX_XF_MTXIDX1_TEX6_END); + break; + default: + GX_SET_REG(gx->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX7_ST, GX_XF_MTXIDX1_TEX7_END); + break; + } + __GXSetMatrixIndex(id + 1); +} + +void GXSetNumTexGens(u8 count) +{ + GX_SET_REG(gx->genMode, count, GX_BP_GENMODE_NUMTEX_ST, GX_BP_GENMODE_NUMTEX_END); + GX_XF_LOAD_REG(GX_XF_REG_NUMTEX, count); + gx->dirtyState |= GX_DIRTY_GEN_MODE; +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXBump.c b/src/static/GAEJ01_01/dolphin/gx/GXBump.c new file mode 100644 index 00000000..f8a9ef5e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXBump.c @@ -0,0 +1,202 @@ +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +// modified from Open_RVL +void GXSetTevIndirect(GXTevStageID tevStage, GXIndTexStageID texStage, GXIndTexFormat texFmt, GXIndTexBiasSel biasSel, GXIndTexMtxID mtxId, + GXIndTexWrap wrapS, GXIndTexWrap wrapT, u8 addPrev, u8 utcLod, GXIndTexAlphaSel alphaSel) +{ + u32 field = 0; + const u32 stage = tevStage + 0x10; + + GX_SET_REG(field, texStage, GX_BP_INDTEV_STAGE_ST, GX_BP_INDTEV_STAGE_END); + GX_SET_REG(field, texFmt, GX_BP_INDTEV_FMT_ST, GX_BP_INDTEV_FMT_END); + GX_SET_REG(field, biasSel, GX_BP_INDTEV_BIAS_ST, GX_BP_INDTEV_BIAS_END); + GX_SET_REG(field, alphaSel, GX_BP_INDTEV_ALPHA_ST, GX_BP_INDTEV_ALPHA_END); + GX_SET_REG(field, mtxId, GX_BP_INDTEV_MTX_ST, GX_BP_INDTEV_MTX_END); + GX_SET_REG(field, wrapS, GX_BP_INDTEV_WRAPS_ST, GX_BP_INDTEV_WRAPS_END); + GX_SET_REG(field, wrapT, GX_BP_INDTEV_WRAPT_ST, GX_BP_INDTEV_WRAPT_END); + GX_SET_REG(field, utcLod, GX_BP_INDTEV_UNMODTEXCOORD_ST, GX_BP_INDTEV_UNMODTEXCOORD_END); + GX_SET_REG(field, addPrev, GX_BP_INDTEV_ADDPREV_ST, GX_BP_INDTEV_ADDPREV_END); + GX_SET_REG(field, stage, 0, 7); + + GX_BP_LOAD_REG(field); + gx->bpSentNot = GX_FALSE; +} + +// modified from Open_RVL +void GXSetIndTexMtx(GXIndTexMtxID id, f32 mtx[2][3], s8 scale_exp) +{ + u32 val; + u32 field; + f32 mtx2[6]; + + // scale_exp range is -17..46 + // we need it in range 0..63 + scale_exp += 17; + + switch (id) { + case GX_ITM_0: + case GX_ITM_1: + case GX_ITM_2: + val = id - 1; + break; + case GX_ITM_S0: + case GX_ITM_S1: + case GX_ITM_S2: + val = id - 5; + break; + case GX_ITM_T0: + case GX_ITM_T1: + case GX_ITM_T2: + val = id - 9; + break; + default: + val = 0; + } + + field = 0; + GX_SET_REG(field, 1024.0f * mtx[0][0], GX_BP_INDMTX_M00_ST, GX_BP_INDMTX_M00_END); + GX_SET_REG(field, 1024.0f * mtx[1][0], GX_BP_INDMTX_M10_ST, GX_BP_INDMTX_M10_END); + GX_SET_REG(field, (scale_exp >> 0) & 3, GX_BP_INDMTX_EXP_ST, GX_BP_INDMTX_EXP_END); + GX_SET_REG(field, val * 3 + 6, 0, 7); + + GX_BP_LOAD_REG(field); + + field = 0; + GX_SET_REG(field, 1024.0f * mtx[0][1], GX_BP_INDMTX_M00_ST, GX_BP_INDMTX_M00_END); + GX_SET_REG(field, 1024.0f * mtx[1][1], GX_BP_INDMTX_M10_ST, GX_BP_INDMTX_M10_END); + GX_SET_REG(field, (scale_exp >> 2) & 3, GX_BP_INDMTX_EXP_ST, GX_BP_INDMTX_EXP_END); + GX_SET_REG(field, val * 3 + 7, 0, 7); + + GX_BP_LOAD_REG(field); + + field = 0; + GX_SET_REG(field, 1024.0f * mtx[0][2], GX_BP_INDMTX_M00_ST, GX_BP_INDMTX_M00_END); + GX_SET_REG(field, 1024.0f * mtx[1][2], GX_BP_INDMTX_M10_ST, GX_BP_INDMTX_M10_END); + GX_SET_REG(field, (scale_exp >> 4) & 3, GX_BP_INDMTX_EXP_ST, GX_BP_INDMTX_EXP_END); + GX_SET_REG(field, val * 3 + 8, 0, 7); + + GX_BP_LOAD_REG(field); + + gx->bpSentNot = GX_FALSE; +} + +// modified from Open_RVL +void GXSetIndTexCoordScale(GXIndTexStageID stage, GXIndTexScale scaleS, GXIndTexScale scaleT) +{ + GXData* data; + switch (stage) { + case GX_INDTEXSTAGE0: + GX_SET_REG(gx->IndTexScale0, scaleS, GX_BP_RAS1_SS0_S0_ST, GX_BP_RAS1_SS0_S0_END); + GX_SET_REG(gx->IndTexScale0, scaleT, GX_BP_RAS1_SS0_T0_ST, GX_BP_RAS1_SS0_T0_END); + GX_SET_REG(gx->IndTexScale0, 0x25, 0, 7); + + GX_BP_LOAD_REG(gx->IndTexScale0); + break; + + case GX_INDTEXSTAGE1: + GX_SET_REG(gx->IndTexScale0, scaleS, GX_BP_RAS1_SS0_S1_ST, GX_BP_RAS1_SS0_S1_END); + GX_SET_REG(gx->IndTexScale0, scaleT, GX_BP_RAS1_SS0_T1_ST, GX_BP_RAS1_SS0_T1_END); + GX_SET_REG(gx->IndTexScale0, 0x25, 0, 7); + + GX_BP_LOAD_REG(gx->IndTexScale0); + break; + + case GX_INDTEXSTAGE2: + GX_SET_REG(gx->IndTexScale1, scaleS, GX_BP_RAS1_SS1_S2_ST, GX_BP_RAS1_SS1_S2_END); + GX_SET_REG(gx->IndTexScale1, scaleT, GX_BP_RAS1_SS1_T2_ST, GX_BP_RAS1_SS1_T2_END); + GX_SET_REG(gx->IndTexScale1, 0x26, 0, 7); + + GX_BP_LOAD_REG(gx->IndTexScale1); + break; + + case GX_INDTEXSTAGE3: + GX_SET_REG(gx->IndTexScale1, scaleS, GX_BP_RAS1_SS1_S3_ST, GX_BP_RAS1_SS1_S3_END); + GX_SET_REG(gx->IndTexScale1, scaleT, GX_BP_RAS1_SS1_T3_ST, GX_BP_RAS1_SS1_T3_END); + GX_SET_REG(gx->IndTexScale1, 0x26, 0, 7); + + GX_BP_LOAD_REG(gx->IndTexScale1); + break; + } + + gx->bpSentNot = GX_FALSE; +} + +// modified from Open_RVL +void GXSetIndTexOrder(GXIndTexStageID stage, GXTexCoordID coord, GXTexMapID map) +{ + GXData* data; + if (map == GX_TEXMAP_NULL) { + map = GX_TEXMAP0; + } + + if (coord == GX_TEXCOORD_NULL) { + coord = GX_TEXCOORD0; + } + + switch (stage) { + case GX_INDTEXSTAGE0: + GX_SET_REG(gx->iref, map, GX_BP_RAS1_IREF_MAP0_ST, GX_BP_RAS1_IREF_MAP0_END); + GX_SET_REG(gx->iref, coord, GX_BP_RAS1_IREF_TXC0_ST, GX_BP_RAS1_IREF_TXC0_END); + break; + + case GX_INDTEXSTAGE1: + GX_SET_REG(gx->iref, map, GX_BP_RAS1_IREF_MAP1_ST, GX_BP_RAS1_IREF_MAP1_END); + GX_SET_REG(gx->iref, coord, GX_BP_RAS1_IREF_TXC1_ST, GX_BP_RAS1_IREF_TXC1_END); + break; + + case GX_INDTEXSTAGE2: + GX_SET_REG(gx->iref, map, GX_BP_RAS1_IREF_MAP2_ST, GX_BP_RAS1_IREF_MAP2_END); + GX_SET_REG(gx->iref, coord, GX_BP_RAS1_IREF_TXC2_ST, GX_BP_RAS1_IREF_TXC2_END); + break; + + case GX_INDTEXSTAGE3: + GX_SET_REG(gx->iref, map, GX_BP_RAS1_IREF_MAP3_ST, GX_BP_RAS1_IREF_MAP3_END); + GX_SET_REG(gx->iref, coord, GX_BP_RAS1_IREF_TXC3_ST, GX_BP_RAS1_IREF_TXC3_END); + break; + } + + GX_BP_LOAD_REG(gx->iref); + + gx->dirtyState |= (GX_DIRTY_SU_TEX | GX_DIRTY_BP_MASK); + gx->bpSentNot = GX_FALSE; +} + +// modified from Open_RVL +void GXSetNumIndStages(u8 num) +{ + GX_SET_REG(gx->genMode, num, GX_BP_GENMODE_NUMINDSTAGES_ST, GX_BP_GENMODE_NUMINDSTAGES_END); + gx->dirtyState |= (GX_DIRTY_BP_MASK | GX_DIRTY_GEN_MODE); +} + +// modified from Open_RVL +void GXSetTevDirect(GXTevStageID stage) +{ + GXSetTevIndirect(stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, FALSE, FALSE, GX_ITBA_OFF); +} + +void GXSetTevIndWarp(GXTevStageID stage, GXIndTexStageID indStage, GXBool doSignedBias, GXBool doWrap, GXIndTexMtxID mtxID) +{ + GXIndTexWrap wrapVal = ((doWrap) ? GX_ITW_0 : GX_ITW_OFF); + + GXSetTevIndirect(stage, indStage, GX_ITF_8, ((doSignedBias) ? GX_ITB_STU : GX_ITB_NONE), mtxID, wrapVal, wrapVal, FALSE, FALSE, + GX_ITBA_OFF); +} + +void __GXUpdateBPMask() +{ +} + +// modified from Open_RVL +void __GXSetIndirectMask(u32 mask) +{ + GX_SET_REG(gx->bpMask, mask, GX_BP_INDIMASK_ST, GX_BP_INDIMASK_END); + GX_BP_LOAD_REG(gx->bpMask); + gx->bpSentNot = GX_FALSE; +} + +void __GXFlushTextureState() +{ + GX_BP_LOAD_REG(gx->bpMask); + gx->bpSentNot = GX_FALSE; +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXDisplayList.c b/src/static/GAEJ01_01/dolphin/gx/GXDisplayList.c new file mode 100644 index 00000000..2e7654be --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXDisplayList.c @@ -0,0 +1,77 @@ +#include + +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" + +static __GXFifoObj DisplayListFifo; +static volatile __GXFifoObj* OldCPUFifo; +static GXData __savedGXdata; + +void GXBeginDisplayList(void* list, u32 size) +{ + __GXFifoObj* CPUFifo = (__GXFifoObj*)GXGetCPUFifo(); + + if (gx->dirtyState != 0) { + __GXSetDirtyState(); + } + + if (gx->dlSaveContext != 0) { + memcpy(&__savedGXdata, gx, sizeof(__savedGXdata)); + } + + DisplayListFifo.base = (u8*)list; + DisplayListFifo.top = (u8*)list + size - 4; + DisplayListFifo.size = size; + DisplayListFifo.count = 0; + DisplayListFifo.rdPtr = list; + DisplayListFifo.wrPtr = list; + gx->inDispList = 1; + GXSaveCPUFifo((GXFifoObj*)CPUFifo); + OldCPUFifo = CPUFifo; + GXSetCPUFifo((GXFifoObj*)&DisplayListFifo); + GXResetWriteGatherPipe(); +} + +u32 GXEndDisplayList(void) +{ + u32 ov; + BOOL enabled; + u32 cpenable; + + GXFlush(); + ov = (GX_GET_PI_REG(5) >> 26) & 1; + __GXSaveCPUFifoAux((GXFifoObj*)&DisplayListFifo); + GXSetCPUFifo((GXFifoObj*)OldCPUFifo); + + if (gx->dlSaveContext != 0) { + enabled = OSDisableInterrupts(); + cpenable = gx->cpEnable; + memcpy(gx, &__savedGXdata, sizeof(*gx)); + gx->cpEnable = cpenable; + OSRestoreInterrupts(enabled); + } + + gx->inDispList = 0; + if (!ov) { + return DisplayListFifo.count; + } + + return 0; +} + +void GXCallDisplayList(void* list, u32 nbytes) +{ + if (gx->dirtyState) { + __GXSetDirtyState(); + } + + if (GX_CHECK_FLUSH()) { + __GXSendFlushPrim(); + } + + GX_WRITE_U8(GX_FIFO_CMD_CALL_DL); + GX_WRITE_U32((u32)list); + GX_WRITE_U32(nbytes); +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXDraw.c b/src/static/GAEJ01_01/dolphin/gx/GXDraw.c new file mode 100644 index 00000000..94d7066a --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXDraw.c @@ -0,0 +1,558 @@ +#include + +#include +#include + +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +static GXVtxDescList vcd[27]; +static GXVtxAttrFmtList vat[27]; + +static void GetVertState(void) +{ + GXGetVtxDescv(vcd); + GXGetVtxAttrFmtv(GX_VTXFMT3, vat); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_NRM, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); +} + +static void RestoreVertState(void) +{ + GXSetVtxDescv(vcd); + GXSetVtxAttrFmtv(3, vat); +} + +static void vsub(f32 p1[3], f32 p2[3], f32 u[3]) +{ + u32 i; + + for (i = 0; i < 3; i++) { + u[i] = p2[i] - p1[i]; + } +} + +static void vcross(f32 u[3], f32 v[3], f32 n[3]) +{ + f32 n1[3]; + + n1[0] = (u[1] * v[2]) - (u[2] * v[1]); + n1[1] = (u[2] * v[0]) - (u[0] * v[2]); + n1[2] = (u[0] * v[1]) - (u[1] * v[0]); + n[0] = n1[0]; + n[1] = n1[1]; + n[2] = n1[2]; +} + +static void normalize(f32 v[3]) +{ + f32 d = sqrtf((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2])); + + ASSERTMSGLINE(0x89, d != 0.0f, "normalize: zero length vector"); + v[0] /= d; + v[1] /= d; + v[2] /= d; +} + +static void myvertex(f32 v[3], f32 n[3]) +{ + GXPosition3f32(v[0], v[1], v[2]); + GXNormal3f32(n[0], n[1], n[2]); +} + +static void DumpTriangle(f32 v0[3], f32 v1[3], f32 v2[3]) +{ + GXBegin(GX_TRIANGLES, GX_VTXFMT3, 3); + myvertex(v0, v0); + myvertex(v1, v1); + myvertex(v2, v2); + GXEnd(); +} + +static void Subdivide(u8 depth, f32 v0[3], f32 v1[3], f32 v2[3]) +{ + f32 v01[3]; + f32 v12[3]; + f32 v20[3]; + u32 i; + + if (depth == 0) { + DumpTriangle(v0, v1, v2); + return; + } + + for (i = 0; i < 3; i++) { + v01[i] = v0[i] + v1[i]; + v12[i] = v1[i] + v2[i]; + v20[i] = v2[i] + v0[i]; + } + normalize(v01); + normalize(v12); + normalize(v20); + Subdivide(depth - 1, v0, v01, v20); + Subdivide(depth - 1, v1, v12, v01); + Subdivide(depth - 1, v2, v20, v12); + Subdivide(depth - 1, v01, v12, v20); +} + +static void SubDivTriangle(u8 depth, u8 i, f32 (*data)[3], u8 (*ndx)[3]) +{ + f32 *x0 = data[ndx[i][0]]; + f32 *x1 = data[ndx[i][1]]; + f32 *x2 = data[ndx[i][2]]; + + Subdivide(depth, x0, x1, x2); +} + +void GXDrawCylinder(u8 numEdges) +{ + s32 i; + f32 top; + f32 bottom; + f32 x[100]; + f32 y[100]; + f32 angle; + + top = 1.0f; + bottom = -top; + ASSERTMSGLINE(0xD8, numEdges <= 99, "GXDrawCylinder: too many edges"); + + GetVertState(); + + for (i = 0; i <= numEdges; i++) { + angle = (3.1415927f * (2.0f * i)) / numEdges; + x[i] = cosf(angle); + y[i] = sinf(angle); + } + + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, (numEdges + 1) * 2); + for (i = 0; i <= numEdges; i++) { + GXPosition3f32(x[i], y[i], bottom); + GXNormal3f32(x[i], y[i], 0.0f); + GXPosition3f32(x[i], y[i], top); + GXNormal3f32(x[i], y[i], 0.0f); + + } + GXEnd(); + + GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, numEdges + 2); + GXPosition3f32(0.0f, 0.0f, top); + GXNormal3f32(0.0f, 0.0f, 1.0f); + for (i = 0; i <= numEdges; i++) { + GXPosition3f32(x[i], -y[i], top); + GXNormal3f32(0.0f, 0.0f, 1.0f); + + } + GXEnd(); + + GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, numEdges + 2); + GXPosition3f32(0.0f, 0.0f, bottom); + GXNormal3f32(0.0f, 0.0f, -1.0f); + for (i = 0; i <= numEdges; i++) { + GXPosition3f32(x[i], y[i], bottom); + GXNormal3f32(0.0f, 0.0f, -1.0f); + } + GXEnd(); + + RestoreVertState(); +} + +void GXDrawTorus(f32 rc, u8 numc, u8 numt) +{ + GXAttrType ttype; + s32 i, j, k; + f32 s, t; + f32 x, y, z; + f32 twopi = 6.2831855f; + f32 rt; + + ASSERTMSGLINE(0x13C, rc < 1.0f, "GXDrawTorus: doughnut too fat"); + + rt = 1.0f - rc; + GXGetVtxDesc(GX_VA_TEX0, &ttype); + GetVertState(); + if (ttype != GX_NONE) { + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + } + for (i = 0; i < numc; i++) { + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, (numt + 1) * 2); + for (j = 0; j <= numt; j++) { + for (k = 1; k >= 0; k--) { + s = (i + k) % numc; + t = j % numt; + x = (rt - rc * cosf(s * twopi / numc)) * cosf(t * twopi / numt); + y = (rt - rc * cosf(s * twopi / numc)) * sinf(t * twopi / numt); + z = rc * sinf(s * twopi / numc); + GXPosition3f32(x, y, z); + x = -cosf(t * twopi / numt) * cosf(s * twopi / numc); + y = -sinf(t * twopi / numt) * cosf(s * twopi / numc); + z = sinf(s * twopi / numc); + GXNormal3f32(x, y, z); + if (ttype != GX_NONE) { + GXTexCoord2f32((i + k) / (f32)numc, j / (f32)numt); + } + } + } + GXEnd(); + } + RestoreVertState(); +} + +void GXDrawSphere(u8 numMajor, u8 numMinor) +{ + GXAttrType ttype; + f32 radius = 1.0f; + f32 majorStep = 3.1415927f / numMajor; + f32 minorStep = 6.2831855f / numMinor; + s32 i, j; + f32 a, b; + f32 r0, r1; + f32 z0, z1; + f32 c; + f32 x, y; + + GXGetVtxDesc(GX_VA_TEX0, &ttype); + GetVertState(); + if (ttype != GX_NONE) { + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0U); + } + for (i = 0; i < numMajor; i++) { + a = i * majorStep; + b = a + majorStep; + r0 = radius * sinf(a); + r1 = radius * sinf(b); + z0 = radius * cosf(a); + z1 = radius * cosf(b); + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, (numMinor + 1) * 2); + for (j = 0; j <= numMinor; j++) { + c = j * minorStep; + x = cosf(c); + y = sinf(c); + GXPosition3f32(x * r1, y * r1, z1); + GXNormal3f32((x * r1) / radius, (y * r1) / radius, z1 / radius); + if (ttype != GX_NONE) { + GXTexCoord2f32((f32)j / (f32)numMinor, (f32)(i + 1) / (f32)numMajor); + } + GXPosition3f32(x * r0, y * r0, z0); + GXNormal3f32((x * r0) / radius, (y * r0) / radius, z0 / radius); + if (ttype != GX_NONE) { + GXTexCoord2f32((f32)j / (f32)numMinor, (f32)i / (f32)numMajor); + } + } + GXEnd(); + } + RestoreVertState(); +} + +static void GXDrawCubeFace(f32 nx, f32 ny, f32 nz, f32 tx, f32 ty, f32 tz, f32 bx, f32 by, f32 bz, GXAttrType binormal, GXAttrType texture) +{ + GXPosition3f32(0.57735026f * (nx + tx + bx), 0.57735026f * (ny + ty + by), 0.57735026f * (nz + tz + bz)); + GXNormal3f32(nx, ny, nz); + if (binormal != GX_NONE) { + GXNormal3f32(tx, ty, tz); + GXNormal3f32(bx, by, bz); + } + if (texture != GX_NONE) { + GXTexCoord2s8(1, 1); + } + GXPosition3f32(0.57735026f * (nx - tx + bx), 0.57735026f * (ny - ty + by), 0.57735026f * (nz - tz + bz)); + GXNormal3f32(nx, ny, nz); + if (binormal != GX_NONE) { + GXNormal3f32(tx, ty, tz); + GXNormal3f32(bx, by, bz); + } + if (texture != GX_NONE) { + GXTexCoord2s8(0, 1); + } + GXPosition3f32(0.57735026f * (nx - tx - bx), 0.57735026f * (ny - ty - by), 0.57735026f * (nz - tz - bz)); + GXNormal3f32(nx, ny, nz); + if (binormal != GX_NONE) { + GXNormal3f32(tx, ty, tz); + GXNormal3f32(bx, by, bz); + } + if (texture != GX_NONE) { + GXTexCoord2s8(0, 0); + } + GXPosition3f32(0.57735026f * (nx + tx - bx), 0.57735026f * (ny + ty - by), 0.57735026f * (nz + tz - bz)); + GXNormal3f32(nx, ny, nz); + if (binormal != GX_NONE) { + GXNormal3f32(tx, ty, tz); + GXNormal3f32(bx, by, bz); + } + if (texture != GX_NONE) { + GXTexCoord2s8(1, 0); + } +} + +void GXDrawCube(void) +{ + GXAttrType ntype; + GXAttrType ttype; + + GXGetVtxDesc(GX_VA_NBT, &ntype); + GXGetVtxDesc(GX_VA_TEX0, &ttype); + GetVertState(); + if (ntype != GX_NONE) { + GXSetVtxDesc(GX_VA_NBT, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_NBT, GX_TEX_ST, GX_RGBA6, 0); + } + if (ttype != GX_NONE) { + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_RGB8, 0); + } + + GXBegin(GX_QUADS, GX_VTXFMT3, 24); + GXDrawCubeFace(-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, ntype, ttype); + GXDrawCubeFace(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, ntype, ttype); + GXDrawCubeFace(0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, ntype, ttype); + GXDrawCubeFace(0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, ntype, ttype); + GXDrawCubeFace(0.0f, 0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, ntype, ttype); + GXDrawCubeFace(0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, ntype, ttype); + GXEnd(); + + RestoreVertState(); +} + +static u32 polygons[12][5] = { + { 0, 12, 10, 11, 16 }, + { 1, 17, 8, 9, 13 }, + { 2, 14, 9, 8, 18 }, + { 3, 19, 11, 10, 15 }, + { 4, 14, 2, 3, 15 }, + { 5, 12, 0, 1, 13 }, + { 6, 17, 1, 0, 16 }, + { 7, 19, 3, 2, 18 }, + { 8, 17, 6, 7, 18 }, + { 9, 14, 4, 5, 13 }, + { 10, 12, 5, 4, 15 }, + { 11, 19, 7, 6, 16 }, +}; + +static f32 verts[20][3] = { + { -0.809015f, 0.0f, 0.309015f }, + { -0.809015f, 0.0f, -0.309015f }, + { 0.809015f, 0.0f, -0.309015f }, + { 0.809015f, 0.0f, 0.309015f }, + { 0.309015f, -0.809015f, 0.0f }, + { -0.309015f, -0.809015f, 0.0f }, + { -0.309015f, 0.809015f, 0 }, + { 0.309015f, 0.809015f, 0 }, + { 0.0f, 0.309015f, -0.809015f }, + { 0.0f, -0.309015f, -0.809015f }, + { 0.0f, -0.309015f, 0.809015f }, + { 0.0f, 0.309015f, 0.809015f }, + { -0.5f, -0.5f, 0.5 }, + { -0.5f, -0.5f, -0.5 }, + { 0.5f, -0.5f, -0.5 }, + { 0.5f, -0.5f, 0.5 }, + { -0.5f, 0.5f, 0.5 }, + { -0.5f, 0.5f, -0.5 }, + { 0.5f, 0.5f, -0.5 }, + { 0.5f, 0.5f, 0.5 }, +}; + +void GXDrawDodeca(void) +{ + u32 i; + f32 *p0; + f32 *p1; + f32 *p2; + f32 u[3]; + f32 v[3]; + f32 n[3]; + + GetVertState(); + for (i = 0; i < 12; i++) { + p0 = verts[polygons[i][0]]; + p1 = verts[polygons[i][1]]; + p2 = verts[polygons[i][2]]; + vsub(p1, p2, u); + vsub(p1, p0, v); + vcross(u, v, n); + normalize(n); + GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, 5); + myvertex(verts[polygons[i][4]], n); + myvertex(verts[polygons[i][3]], n); + myvertex(p2, n); + myvertex(p1, n); + myvertex(p0, n); + GXEnd(); + } + RestoreVertState(); +} + +static f32 odata[6][3] = { + { 1.0f, 0.0f, 0.0f }, + { -1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { 0.0f, -1.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + { 0.0f, 0.0f, -1.0f }, +}; + +static u8 ondex[8][3] = { + { 0, 4, 2 }, + { 1, 2, 4 }, + { 0, 3, 4 }, + { 1, 4, 3 }, + { 0, 2, 5 }, + { 1, 5, 2 }, + { 0, 5, 3 }, + { 1, 3, 5 }, +}; + +void GXDrawOctahedron(void) +{ + s32 i; + + GetVertState(); + for (i = 7; i >= 0; i--) { + SubDivTriangle(0, i, odata, ondex); + } + RestoreVertState(); +} + +static f32 idata[12][3] = { + { -0.5257311f, 0.0f, 0.8506508f }, + { 0.5257311f, 0.0f, 0.8506508f }, + { -0.5257311f, 0.0f, -0.8506508f }, + { 0.5257311f, 0.0f, -0.8506508f }, + { 0.0f, 0.8506508f, 0.5257311f }, + { 0.0f, 0.8506508f, -0.5257311f }, + { 0.0f, -0.8506508f, 0.5257311f }, + { 0.0f, -0.8506508f, -0.5257311f }, + { 0.8506508f, 0.5257311f, 0.0f }, + { -0.8506508f, 0.5257311f, 0.0f }, + { 0.8506508f, -0.5257311f, 0.0f }, + { -0.8506508f, -0.5257311f, 0.0f }, +}; + +static u8 index[20][3] = { + { 0, 4, 1 }, + { 0, 9, 4 }, + { 9, 5, 4 }, + { 4, 5, 8 }, + { 4, 8, 1 }, + { 8, 10, 1 }, + { 8, 3, 10 }, + { 5, 3, 8 }, + { 5, 2, 3 }, + { 2, 7, 3 }, + { 7, 10, 3 }, + { 7, 6, 10 }, + { 7, 11, 6 }, + { 11, 0, 6 }, + { 0, 1, 6 }, + { 6, 1, 10 }, + { 9, 0, 11 }, + { 9, 11, 2 }, + { 9, 2, 5 }, + { 7, 2, 11 }, +}; + +void GXDrawIcosahedron(void) +{ + s32 i; + + GetVertState(); + for (i = 19; i >= 0; i--) { + SubDivTriangle(0, i, idata, index); + } + RestoreVertState(); +} + +void GXDrawSphere1(u8 depth) +{ + s32 i; + + GetVertState(); + for (i = 19; i >= 0; i--) { + SubDivTriangle(depth, i, idata, index); + } + RestoreVertState(); +} + +static u32 CmpNormal32(f32 n1[3], f32 n2[3]) +{ + u32 i; + + for (i = 0; i < 3; i++) { + if (n1[i] != n2[i]) + return FALSE; + } + return TRUE; +} + +static u32 nrm_cnt; +static f32 *nrm_tab; + +static void AddNormal(f32 n[3]) +{ + u32 indx; + u32 i; + + for (i = 0; i < nrm_cnt; i++) + { + if (CmpNormal32(n, &nrm_tab[i * 3])) + return; + } + indx = nrm_cnt * 3; + nrm_tab[indx + 0] = n[0]; + nrm_tab[indx + 1] = n[1]; + nrm_tab[indx + 2] = n[2]; + nrm_cnt++; +} + +static void SubdivideNrm(u8 depth, f32 v0[3], f32 v1[3], f32 v2[3]) +{ + f32 v01[3]; + f32 v12[3]; + f32 v20[3]; + u32 i; + + if (depth == 0) { + AddNormal(v0); + AddNormal(v1); + AddNormal(v2); + return; + } + + for (i = 0; i < 3; i++) { + v01[i] = v0[i] + v1[i]; + v12[i] = v1[i] + v2[i]; + v20[i] = v2[i] + v0[i]; + } + normalize(v01); + normalize(v12); + normalize(v20); + SubdivideNrm(depth - 1, v0, v01, v20); + SubdivideNrm(depth - 1, v1, v12, v01); + SubdivideNrm(depth - 1, v2, v20, v12); + SubdivideNrm(depth - 1, v01, v12, v20); +} + +static void SubDivNrm(u8 depth, u8 i, f32 (*data)[3], u8 (*ndx)[3]) +{ + f32 *x0 = data[ndx[i][0]]; + f32 *x1 = data[ndx[i][1]]; + f32 *x2 = data[ndx[i][2]]; + + SubdivideNrm(depth, x0, x1, x2); +} + +u32 GXGenNormalTable(u8 depth, f32 *table) +{ + s32 i; + + nrm_cnt = 0; + nrm_tab = table; + for (i = 7; i >= 0; i--) { + SubDivNrm(depth, i, odata, ondex); + } + return nrm_cnt; +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXFifo.c b/src/static/GAEJ01_01/dolphin/gx/GXFifo.c new file mode 100644 index 00000000..37bc371b --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXFifo.c @@ -0,0 +1,351 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +static GXFifoObj* CPUFifo; +static GXFifoObj* GPFifo; +static OSThread* __GXCurrentThread; +static u8 CPGPLinked; +static BOOL GXOverflowSuspendInProgress; +static GXBreakPtCallback BreakPointCB; +static u32 __GXOverflowCount; + +void GXOverflowHandler() +{ + __GXOverflowCount += 1; + __GXWriteFifoIntEnable(0, 1); + __GXWriteFifoIntReset(1, 0); + GXOverflowSuspendInProgress = TRUE; + OSSuspendThread(__GXCurrentThread); +} + +void GXUnderflowHandler() +{ + OSResumeThread(__GXCurrentThread); + GXOverflowSuspendInProgress = FALSE; + __GXWriteFifoIntReset(1, 1); + __GXWriteFifoIntEnable(1, 0); +} + +void GXBreakPointHandler(OSContext* context) +{ + OSContext bpContext; + GX_SET_REG(gx->cpEnable, 0, 26, 26); + GX_SET_CP_REG(1, gx->cpEnable); + + if (BreakPointCB) { + OSClearContext(&bpContext); + OSSetCurrentContext(&bpContext); + BreakPointCB(); + OSClearContext(&bpContext); + OSSetCurrentContext(context); + } +} + +void GXCPInterruptHandler(s16 p1, OSContext* context) +{ + + gx->cpStatus = GX_GET_CP_REG(0); + + if ((gx->cpEnable >> 3 & 1) && (gx->cpStatus >> 1 & 1)) { + GXUnderflowHandler(); + } + + if ((gx->cpEnable >> 2 & 1) && (gx->cpStatus >> 0 & 1)) { + GXOverflowHandler(); + } + + if ((gx->cpEnable >> 5 & 1) && (gx->cpStatus >> 4 & 1)) { + GXBreakPointHandler(context); + } +} + +void GXInitFifoBase(GXFifoObj* fifo, void* base, u32 size) +{ + GXFifoObjPriv* pFifo = (GXFifoObjPriv*)fifo; + pFifo->base = base; + pFifo->end = (void*)((u32)base + size - 4); + pFifo->size = size; + pFifo->rwDistance = 0; + GXInitFifoLimits(fifo, size - 0x4000, OSRoundDown32B(size / 2)); + GXInitFifoPtrs(fifo, base, base); +} + +void GXInitFifoPtrs(GXFifoObj* fifo, void* readPtr, void* writePtr) +{ + GXFifoObjPriv* pFifo = (GXFifoObjPriv*)fifo; + int interrupts = OSDisableInterrupts(); + pFifo->readPtr = readPtr; + pFifo->writePtr = writePtr; + pFifo->rwDistance = (u32)writePtr - (u32)readPtr; + if (pFifo->rwDistance < 0) { + pFifo->rwDistance += pFifo->size; + } + OSRestoreInterrupts(interrupts); +} + +void GXInitFifoLimits(GXFifoObj* fifo, u32 highWatermark, u32 lowWatermark) +{ + GXFifoObjPriv* pFifo = (GXFifoObjPriv*)fifo; + pFifo->highWatermark = highWatermark; + pFifo->lowWatermark = lowWatermark; +} + +void GXSetCPUFifo(GXFifoObj* fifo) +{ + BOOL interrupts; + interrupts = OSDisableInterrupts(); + + CPUFifo = fifo; + + if (fifo == GPFifo) { + u32 reg; + GX_SET_PI_REG(3, (u32)((GXFifoObjPriv*)fifo)->base & 0x3FFFFFFF); + GX_SET_PI_REG(4, (u32)((GXFifoObjPriv*)fifo)->end & 0x3FFFFFFF); + reg = 0; + GX_SET_REG(reg, (u32)((GXFifoObjPriv*)fifo)->writePtr >> 5, 6, 26); + GX_SET_REG(reg, 0, 5, 5); + GX_SET_PI_REG(5, reg); + + CPGPLinked = GX_TRUE; + + __GXWriteFifoIntReset(1, 1); + __GXWriteFifoIntEnable(1, 0); + __GXFifoLink(1); + } else { + u32 reg; + if (CPGPLinked) { + __GXFifoLink(0); + CPGPLinked = GX_FALSE; + } + __GXWriteFifoIntEnable(0, 0); + + GX_SET_PI_REG(3, (u32)((GXFifoObjPriv*)fifo)->base & 0x3FFFFFFF); + GX_SET_PI_REG(4, (u32)((GXFifoObjPriv*)fifo)->end & 0x3FFFFFFF); + reg = 0; + GX_SET_REG(reg, (u32)((GXFifoObjPriv*)fifo)->writePtr >> 5, 6, 26); + GX_SET_REG(reg, 0, 5, 5); + GX_SET_PI_REG(5, reg); + } + + PPCSync(); + + OSRestoreInterrupts(interrupts); +} + +void GXSetGPFifo(GXFifoObj* fifo) +{ + GXFifoObjPriv* pFifo = (GXFifoObjPriv*)fifo; + int interrupts = OSDisableInterrupts(); + __GXFifoReadDisable(); + __GXWriteFifoIntEnable(0, 0); + GPFifo = fifo; + GX_SET_CP_REG(16, (u16)pFifo->base); + GX_SET_CP_REG(18, (u16)pFifo->end); + GX_SET_CP_REG(24, (u16)pFifo->rwDistance); + GX_SET_CP_REG(26, (u16)pFifo->writePtr); + GX_SET_CP_REG(28, (u16)pFifo->readPtr); + GX_SET_CP_REG(20, (u16)pFifo->highWatermark); + GX_SET_CP_REG(22, (u16)pFifo->lowWatermark); + + GX_SET_CP_REG(17, ((u32)pFifo->base & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(19, ((u32)pFifo->end & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(25, (pFifo->rwDistance) >> 16); + GX_SET_CP_REG(27, ((u32)pFifo->writePtr & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(29, ((u32)pFifo->readPtr & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(21, (pFifo->highWatermark) >> 16); + GX_SET_CP_REG(23, (pFifo->lowWatermark) >> 16); + + PPCSync(); + + if (CPUFifo == GPFifo) { + CPGPLinked = 1; + __GXWriteFifoIntEnable(1, 0); + __GXFifoLink(1); + } else { + CPGPLinked = 0; + __GXWriteFifoIntEnable(0, 0); + __GXFifoLink(0); + } + __GXWriteFifoIntReset(1, 1); + __GXFifoReadEnable(); + OSRestoreInterrupts(interrupts); +} + +void GXSaveCPUFifo(GXFifoObj* fifo) +{ + GXFlush(); + __GXSaveCPUFifoAux(fifo); +} + +void __GXSaveCPUFifoAux(GXFifoObj* fifo) +{ + GXFifoObjPriv* pFifo = (GXFifoObjPriv*)fifo; + int interrupts = OSDisableInterrupts(); + pFifo->base = OSPhysicalToCached(GX_GET_PI_REG(3)); + pFifo->end = OSPhysicalToCached(GX_GET_PI_REG(4)); + pFifo->writePtr = OSPhysicalToCached(GX_GET_PI_REG(5) & ~0x4000000); + if (CPGPLinked != 0) { + u32 reg = GX_GET_CP_REG(29) << 16; + u32 reg2 = GX_GET_CP_REG(28) | reg; + pFifo->readPtr = (void*)(reg2 + -0x80000000); + reg = GX_GET_CP_REG(25) << 16; + pFifo->rwDistance = (((u32)GX_GET_CP_REG(24) | reg)); + + } else { + pFifo->rwDistance = (u32)pFifo->writePtr - (u32)pFifo->readPtr; + if (pFifo->rwDistance < 0) { + pFifo->rwDistance += pFifo->size; + } + } + OSRestoreInterrupts(interrupts); +} + +void GXGetGPStatus(GXBool* overhi, GXBool* underlow, GXBool* readIdle, GXBool* cmdIdle, GXBool* brkpt) +{ + gx->cpStatus = GX_GET_CP_REG(0); + *overhi = gx->cpStatus & 1; + *underlow = (gx->cpStatus >> 1) & 1; + *readIdle = (gx->cpStatus >> 2) & 1; + *cmdIdle = (gx->cpStatus >> 3) & 1; + *brkpt = (gx->cpStatus >> 4) & 1; +} + +GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb) +{ + GXBreakPtCallback oldCallback = BreakPointCB; + int interrupts = OSDisableInterrupts(); + BreakPointCB = cb; + OSRestoreInterrupts(interrupts); + return oldCallback; +} + +void __GXFifoInit(void) +{ + __OSSetInterruptHandler(0x11, GXCPInterruptHandler); + __OSUnmaskInterrupts(0x4000); + __GXCurrentThread = OSGetCurrentThread(); + GXOverflowSuspendInProgress = 0; + CPUFifo = NULL; + GPFifo = NULL; +} + +void __GXFifoReadEnable(void) +{ + GX_SET_REG(gx->cpEnable, GX_TRUE, 31, 31); + GX_SET_CP_REG(1, gx->cpEnable); +} + +void __GXFifoReadDisable(void) +{ + GX_SET_REG(gx->cpEnable, GX_FALSE, 31, 31); + GX_SET_CP_REG(1, gx->cpEnable); +} + +void __GXFifoLink(u8 link) +{ + u32 b; + if (link) { + b = 1; + } else { + b = 0; + } + GX_SET_REG(gx->cpEnable, b, 27, 27); + GX_SET_CP_REG(1, gx->cpEnable); +} + +void __GXWriteFifoIntEnable(u32 p1, u32 p2) +{ + GX_SET_REG(gx->cpEnable, p1, 29, 29); + GX_SET_REG(gx->cpEnable, (u8)p2, 28, 28); + GX_SET_CP_REG(1, gx->cpEnable); +} + +void __GXWriteFifoIntReset(u32 p1, u32 p2) +{ + GX_SET_REG(gx->cpClr, p1, 31, 31); + GX_SET_REG(gx->cpClr, (u8)p2, 30, 30); + GX_SET_CP_REG(2, gx->cpClr); +} + +void __GXCleanGPFifo(void) +{ + BOOL interrupts; + GXFifoObjPriv tempObj; + u32 i, j, k; + GXFifoObjPriv* gpFifo; + GXFifoObjPriv* cpuFifo; + void* tempPtr; + + gpFifo = (GXFifoObjPriv*)GXGetGPFifo(); + if (!gpFifo) { + return; + } + + cpuFifo = (GXFifoObjPriv*)GXGetCPUFifo(); + tempPtr = gpFifo->base; + + tempObj = *gpFifo; + + interrupts = OSDisableInterrupts(); + + tempObj.readPtr = tempPtr; + tempObj.writePtr = tempPtr; + tempObj.rwDistance = 0; + if (tempObj.rwDistance < 0) { + tempObj.rwDistance += tempObj.size; + } + + OSRestoreInterrupts(interrupts); + + GXSetGPFifo((GXFifoObj*)&tempObj); + + if (cpuFifo == gpFifo) { + GXSetCPUFifo((GXFifoObj*)&tempObj); + } + + interrupts = OSDisableInterrupts(); + + gpFifo->readPtr = tempPtr; + gpFifo->writePtr = tempPtr; + gpFifo->rwDistance = 0; + + if (gpFifo->rwDistance < 0) { + gpFifo->rwDistance += gpFifo->size; + } + OSRestoreInterrupts(interrupts); + + GXSetGPFifo((GXFifoObj*)gpFifo); + if (cpuFifo == gpFifo) { + GXSetCPUFifo((GXFifoObj*)cpuFifo); + } +} + +OSThread* GXSetCurrentGXThread(void) +{ + BOOL enabled; + OSThread* prev; + + enabled = OSDisableInterrupts(); + prev = __GXCurrentThread; + __GXCurrentThread = OSGetCurrentThread(); + OSRestoreInterrupts(enabled); + return prev; +} + +OSThread* GXGetCurrentGXThread(void) +{ + return __GXCurrentThread; +} + +GXFifoObj* GXGetCPUFifo(void) +{ + return CPUFifo; +} + +GXFifoObj* GXGetGPFifo(void) +{ + return GPFifo; +} + diff --git a/src/static/GAEJ01_01/dolphin/gx/GXFrameBuf.c b/src/static/GAEJ01_01/dolphin/gx/GXFrameBuf.c new file mode 100644 index 00000000..c5812166 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXFrameBuf.c @@ -0,0 +1,452 @@ +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +// clang-format off +GXRenderModeObj GXNtsc480IntDf = { + VI_TVMODE_NTSC_INT, 640, 480, 480, 40, 0, 640, 480, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 8, 8, 10, 12, 10, 8, 8, +}; + +GXRenderModeObj GXNtsc480Int = { + VI_TVMODE_NTSC_INT, 640, 480, 480, 40, 0, 640, 480, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 21, 22, 21, 0, 0, +}; + +GXRenderModeObj GXMpal480IntDf = { + VI_TVMODE_MPAL_INT, 640, 480, 480, 40, 0, 640, 480, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 8, 8, 10, 12, 10, 8, 8, +}; + +GXRenderModeObj GXPal528IntDf = { + VI_TVMODE_PAL_INT, 640, 528, 528, 40, 23, 640, 528, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 8, 8, 10, 12, 10, 8, 8, +}; + +GXRenderModeObj GXEurgb60Hz480IntDf = { + VI_TVMODE_EURGB60_INT, 640, 480, 480, 40, 0, 640, 480, VI_XFBMODE_DF, GX_FALSE, GX_FALSE, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 8, 8, 10, 12, 10, 8, 8, +}; +// clang-format on + +void GXSetDispCopySrc(u16 left, u16 top, u16 width, u16 height) +{ + gx->cpDispSrc = 0; + GX_SET_REG(gx->cpDispSrc, left, 22, 31); + GX_SET_REG(gx->cpDispSrc, top, 12, 21); + GX_SET_REG(gx->cpDispSrc, 0x49, 0, 7); + + gx->cpDispSize = 0; + GX_SET_REG(gx->cpDispSize, width - 1, 22, 31); + GX_SET_REG(gx->cpDispSize, height - 1, 12, 21); + GX_SET_REG(gx->cpDispSize, 0x4A, 0, 7); +} + +void GXSetTexCopySrc(u16 left, u16 top, u16 width, u16 height) +{ + gx->cpTexSrc = 0; + GX_SET_REG(gx->cpTexSrc, left, 22, 31); + GX_SET_REG(gx->cpTexSrc, top, 12, 21); + GX_SET_REG(gx->cpTexSrc, 0x49, 0, 7); + + gx->cpTexSize = 0; + GX_SET_REG(gx->cpTexSize, width - 1, 22, 31); + GX_SET_REG(gx->cpTexSize, height - 1, 12, 21); + GX_SET_REG(gx->cpTexSize, 0x4A, 0, 7); +} + +void GXSetDispCopyDst(u16 width, u16 height) +{ + u16 stride = width * 2; + gx->cpDispStride = 0; + GX_SET_REG(gx->cpDispStride, stride >> 5, 22, 31); + GX_SET_REG(gx->cpDispStride, 0x4D, 0, 7); +} + +void GXSetTexCopyDst(u16 width, u16 height, GXTexFmt format, GXBool useMIPmap) +{ + u32 sp20, sp1C, sp18; + u32 value; + u8 depthRelated; + + gx->cpTexZ = GX_NONE; + + depthRelated = format & 0xf; + if (format == GX_TF_Z16) { + depthRelated = 0xb; + } + + switch (format) { + case GX_TF_I4: + case GX_TF_I8: + case GX_TF_IA4: + case GX_TF_IA8: + case GX_CTF_YUVA8: + GX_SET_REG(gx->cpTex, 3, 15, 16); + break; + default: + GX_SET_REG(gx->cpTex, 2, 15, 16); + break; + } + + gx->cpTexZ = (format & 0x10) == 0x10; + + value = depthRelated >> 3; + + GX_SET_REG(gx->cpTex, value, 28, 28); + + depthRelated &= 7; + + __GetImageTileCount(format, width, height, &sp20, &sp1C, &sp18); + + gx->cpTexStride = GX_NONE; + GX_SET_REG(gx->cpTexStride, sp20 * sp18, 22, 31); + GX_SET_REG(gx->cpTexStride, 0x4D, 0, 7); + + GX_SET_REG(gx->cpTex, useMIPmap, 22, 22); + GX_SET_REG(gx->cpTex, depthRelated, 25, 27); +} + +void GXSetDispCopyFrame2Field(GXCopyMode mode) +{ + GX_SET_REG(gx->cpDisp, mode, 18, 19); + GX_SET_REG(gx->cpTex, 0, 18, 19); +} + +void GXSetCopyClamp(GXFBClamp clamp) +{ + GXBool clamp1 = ((clamp & 1) == 1); + GXBool clamp2 = ((clamp & 2) == 2); + GX_SET_REG(gx->cpDisp, clamp1, 31, 31); + GX_SET_REG(gx->cpDisp, clamp2, 30, 30); + GX_SET_REG(gx->cpTex, clamp1, 31, 31); + GX_SET_REG(gx->cpTex, clamp2, 30, 30); +} + +static u32 __GXGetNumXfbLines(u32 height, u32 scale) +{ + u32 numLines; + u32 actualHeight; + u32 newScale; + + numLines = (height - 1) * 0x100; + actualHeight = (numLines / scale) + 1; + + newScale = scale; + + if (newScale > 0x80 && newScale < 0x100) { + while (newScale % 2 == 0) { + newScale /= 2; + } + + if (height % newScale == 0) { + actualHeight++; + } + } + + if (actualHeight > 0x400) { + actualHeight = 0x400; + } + + return actualHeight; +} + +u16 GXGetNumXfbLines(const u16 efbHeight, f32 yScale) +{ + u32 scale = (u32)(256.0f / yScale) & 0x1FF; + + return __GXGetNumXfbLines(efbHeight, scale); +} + +f32 GXGetYScaleFactor(u16 efbHeight, u16 xfbHeight) +{ + u32 scale; + u32 height1; + u32 height2; + f32 scale2; + f32 scale1; + + height1 = xfbHeight; + scale1 = (f32)xfbHeight / (f32)efbHeight; + scale = (u32)(256.0f / scale1) & 0x1FF; + height2 = __GXGetNumXfbLines(efbHeight, scale); + + while (height2 > xfbHeight) { + height1--; + scale1 = (f32)height1 / (f32)efbHeight; + scale = (u32)(256.0f / scale1) & 0x1FF; + height2 = __GXGetNumXfbLines(efbHeight, scale); + } + + scale2 = scale1; + while (height2 < xfbHeight) { + scale2 = scale1; + height1++; + scale1 = (f32)height1 / (f32)efbHeight; + scale = (u32)(256.0f / scale1) & 0x1FF; + height2 = __GXGetNumXfbLines(efbHeight, scale); + } + + return scale2; +} + +u32 GXSetDispCopyYScale(f32 vertScale) +{ + u32 scale; + GXBool check; + u32 height; + u32 reg; + + scale = (u32)(256.0f / vertScale) & 0x1FF; + check = (scale != 0x100); + + reg = 0; + GX_SET_REG(reg, scale, 23, 31); + GX_SET_REG(reg, 0x4E, 0, 7); + GX_BP_LOAD_REG(reg); + gx->bpSentNot = GX_FALSE; + + GX_SET_REG(gx->cpDisp, check, 21, 21); + + height = (gx->cpDispSize >> 10 & 0x3FF) + 1; + + return __GXGetNumXfbLines(height, scale); +} + +void GXSetCopyClear(GXColor clearColor, u32 clearZ) +{ + u32 reg = 0; + GX_SET_REG(reg, clearColor.r, 24, 31); + GX_SET_REG(reg, clearColor.a, 16, 23); + GX_SET_REG(reg, 0x4F, 0, 7); + GX_BP_LOAD_REG(reg); + + reg = 0; + GX_SET_REG(reg, clearColor.b, 24, 31); + GX_SET_REG(reg, clearColor.g, 16, 23); + GX_SET_REG(reg, 0x50, 0, 7); + GX_BP_LOAD_REG(reg); + + reg = 0; + GX_SET_REG(reg, clearZ, 8, 31); + GX_SET_REG(reg, 0x51, 0, 7); + GX_BP_LOAD_REG(reg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetCopyFilter(GXBool useAA, const u8 samplePattern[12][2], GXBool doVertFilt, const u8 vFilt[7]) +{ + u32 vals[4]; + u32 unk1; + u32 unk2; + + if (useAA) { + vals[0] = 0; + GX_SET_REG(vals[0], samplePattern[0][0], 28, 31); + GX_SET_REG(vals[0], samplePattern[0][1], 24, 27); + GX_SET_REG(vals[0], samplePattern[1][0], 20, 23); + GX_SET_REG(vals[0], samplePattern[1][1], 16, 19); + GX_SET_REG(vals[0], samplePattern[2][0], 12, 15); + GX_SET_REG(vals[0], samplePattern[2][1], 8, 11); + GX_SET_REG(vals[0], 1, 0, 7); + + vals[1] = 0; + GX_SET_REG(vals[1], samplePattern[3][0], 28, 31); + GX_SET_REG(vals[1], samplePattern[3][1], 24, 27); + GX_SET_REG(vals[1], samplePattern[4][0], 20, 23); + GX_SET_REG(vals[1], samplePattern[4][1], 16, 19); + GX_SET_REG(vals[1], samplePattern[5][0], 12, 15); + GX_SET_REG(vals[1], samplePattern[5][1], 8, 11); + GX_SET_REG(vals[1], 2, 0, 7); + + vals[2] = 0; + GX_SET_REG(vals[2], samplePattern[6][0], 28, 31); + GX_SET_REG(vals[2], samplePattern[6][1], 24, 27); + GX_SET_REG(vals[2], samplePattern[7][0], 20, 23); + GX_SET_REG(vals[2], samplePattern[7][1], 16, 19); + GX_SET_REG(vals[2], samplePattern[8][0], 12, 15); + GX_SET_REG(vals[2], samplePattern[8][1], 8, 11); + GX_SET_REG(vals[2], 3, 0, 7); + + vals[3] = 0; + GX_SET_REG(vals[3], samplePattern[9][0], 28, 31); + GX_SET_REG(vals[3], samplePattern[9][1], 24, 27); + GX_SET_REG(vals[3], samplePattern[10][0], 20, 23); + GX_SET_REG(vals[3], samplePattern[10][1], 16, 19); + GX_SET_REG(vals[3], samplePattern[11][0], 12, 15); + GX_SET_REG(vals[3], samplePattern[11][1], 8, 11); + GX_SET_REG(vals[3], 4, 0, 7); + } else { + vals[0] = 0x01666666; + vals[1] = 0x02666666; + vals[2] = 0x03666666; + vals[3] = 0x04666666; + } + + GX_BP_LOAD_REG(vals[0]); + GX_BP_LOAD_REG(vals[1]); + GX_BP_LOAD_REG(vals[2]); + GX_BP_LOAD_REG(vals[3]); + + unk1 = 0; + GX_SET_REG(unk1, 0x53, 0, 7); + unk2 = 0; + GX_SET_REG(unk2, 0x54, 0, 7); + + if (doVertFilt) { + GX_SET_REG(unk1, vFilt[0], 26, 31); + GX_SET_REG(unk1, vFilt[1], 20, 25); + GX_SET_REG(unk1, vFilt[2], 14, 19); + GX_SET_REG(unk1, vFilt[3], 8, 13); + GX_SET_REG(unk2, vFilt[4], 26, 31); + GX_SET_REG(unk2, vFilt[5], 20, 25); + GX_SET_REG(unk2, vFilt[6], 14, 19); + + } else { + GX_SET_REG(unk1, 0, 26, 31); + GX_SET_REG(unk1, 0, 20, 25); + GX_SET_REG(unk1, 21, 14, 19); + GX_SET_REG(unk1, 22, 8, 13); + GX_SET_REG(unk2, 21, 26, 31); + GX_SET_REG(unk2, 0, 20, 25); + GX_SET_REG(unk2, 0, 14, 19); + } + + GX_BP_LOAD_REG(unk1); + GX_BP_LOAD_REG(unk2); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetDispCopyGamma(GXGamma gamma) +{ + GX_SET_REG(gx->cpDisp, gamma, 23, 24); +} + +void GXCopyDisp(void* dest, GXBool doClear) +{ + u32 reg; + u32 newDest; + GXBool check; + + if (doClear) { + reg = gx->zmode; + GX_SET_REG(reg, 1, 31, 31); + GX_SET_REG(reg, 7, 28, 30); + GX_BP_LOAD_REG(reg); + + reg = gx->cmode0; + GX_SET_REG(reg, 0, 31, 31); + GX_SET_REG(reg, 0, 30, 30); + GX_BP_LOAD_REG(reg); + } + + check = GX_FALSE; + if ((doClear || (gx->peCtrl & 0x7) == 3) && (gx->peCtrl >> 6 & 0x1) == 1) { + check = GX_TRUE; + reg = gx->peCtrl; + GX_SET_REG(reg, 0, 25, 25); + GX_BP_LOAD_REG(reg); + } + + GX_BP_LOAD_REG(gx->cpDispSrc); + GX_BP_LOAD_REG(gx->cpDispSize); + GX_BP_LOAD_REG(gx->cpDispStride); + + newDest = (u32)dest & 0x3FFFFFFF; + reg = 0; + GX_SET_REG(reg, newDest >> 5, 11, 31); + GX_SET_REG(reg, 0x4B, 0, 7); + GX_BP_LOAD_REG(reg); + + GX_SET_REG(gx->cpDisp, doClear, 20, 20); + GX_SET_REG(gx->cpDisp, 1, 17, 17); + GX_SET_REG(gx->cpDisp, 0x52, 0, 7); + GX_BP_LOAD_REG(gx->cpDisp); + + if (doClear) { + GX_BP_LOAD_REG(gx->zmode); + GX_BP_LOAD_REG(gx->cmode0); + } + + if (check) { + GX_BP_LOAD_REG(gx->peCtrl); + } + + gx->bpSentNot = GX_FALSE; +} + +void GXCopyTex(void* dest, GXBool doClear) +{ + u32 reg; + u32 reg2; + u32 newDest; + GXBool check; + + if (doClear) { + reg = gx->zmode; + GX_SET_REG(reg, 1, 31, 31); + GX_SET_REG(reg, 7, 28, 30); + GX_BP_LOAD_REG(reg); + + reg = gx->cmode0; + GX_SET_REG(reg, 0, 31, 31); + GX_SET_REG(reg, 0, 30, 30); + GX_BP_LOAD_REG(reg); + } + + check = GX_FALSE; + reg2 = gx->peCtrl; + if (gx->cpTexZ && (reg2 & 0x7) != 3) { + check = GX_TRUE; + GX_SET_REG(reg2, 3, 29, 31); + } + + if ((doClear || (reg2 & 0x7) == 3) && (reg2 >> 6 & 0x1) == 1) { + check = GX_TRUE; + GX_SET_REG(reg2, 0, 25, 25); + } + + if (check) { + GX_BP_LOAD_REG(reg2); + } + + GX_BP_LOAD_REG(gx->cpTexSrc); + GX_BP_LOAD_REG(gx->cpTexSize); + GX_BP_LOAD_REG(gx->cpTexStride); + + newDest = (u32)dest & 0x3FFFFFFF; + reg = 0; + GX_SET_REG(reg, newDest >> 5, 11, 31); + GX_SET_REG(reg, 0x4B, 0, 7); + GX_BP_LOAD_REG(reg); + + GX_SET_REG(gx->cpTex, doClear, 20, 20); + GX_SET_REG(gx->cpTex, 0, 17, 17); + GX_SET_REG(gx->cpTex, 0x52, 0, 7); + GX_BP_LOAD_REG(gx->cpTex); + + if (doClear) { + GX_BP_LOAD_REG(gx->zmode); + GX_BP_LOAD_REG(gx->cmode0); + } + + if (check) { + GX_BP_LOAD_REG(gx->peCtrl); + } + + gx->bpSentNot = GX_FALSE; +} + +void GXClearBoundingBox(void) +{ + GX_BP_LOAD_REG(0x550003FF); + GX_BP_LOAD_REG(0x560003FF); + gx->bpSentNot = GX_FALSE; +} + diff --git a/src/static/GAEJ01_01/dolphin/gx/GXGeometry.c b/src/static/GAEJ01_01/dolphin/gx/GXGeometry.c new file mode 100644 index 00000000..9d2c4677 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXGeometry.c @@ -0,0 +1,120 @@ +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +void __GXSetDirtyState(void) +{ + u32 dirtyFlags = gx->dirtyState; + + if (dirtyFlags & 1) { + __GXSetSUTexRegs(); + } + + if (dirtyFlags & 2) { + __GXUpdateBPMask(); + } + + if (dirtyFlags & 4) { + __GXSetGenMode(); + } + + if (dirtyFlags & 8) { + __GXSetVCD(); + } + + if (dirtyFlags & 0x10) { + __GXSetVAT(); + } + + if (dirtyFlags & 0x18) { + __GXCalculateVLim(); + } + + gx->dirtyState = 0; +} + +void GXBegin(GXPrimitive type, GXVtxFmt fmt, u16 vert_num) +{ + if (gx->dirtyState) { + __GXSetDirtyState(); + } + + if (GX_CHECK_FLUSH()) { + __GXSendFlushPrim(); + } + + GX_WRITE_U8(fmt | type); + GX_WRITE_U16(vert_num); +} + +void __GXSendFlushPrim(void) +{ + u32 i; + u32 sz = (gx->vNum * gx->vLim); + + GX_WRITE_U8(0x98); + GX_WRITE_U16(gx->vNum); + + for (i = 0; i < sz; i += 4) { + GX_WRITE_U32(0); + } + + gx->bpSentNot = GX_TRUE; +} + +void GXSetLineWidth(u8 width, GXTexOffset offsets) +{ + GX_SET_REG(gx->lpSize, width, 24, 31); + GX_SET_REG(gx->lpSize, offsets, 13, 15); + + GX_BP_LOAD_REG(gx->lpSize); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetPointSize(u8 size, GXTexOffset offsets) +{ + GX_SET_REG(gx->lpSize, size, 16, 23); + GX_SET_REG(gx->lpSize, offsets, 10, 12); + + GX_BP_LOAD_REG(gx->lpSize); + + gx->bpSentNot = GX_FALSE; +} + +void GXEnableTexOffsets(GXTexCoordID coord, GXBool line, GXBool point) +{ + GX_SET_REG(gx->suTs0[coord], line, 13, 13); + GX_SET_REG(gx->suTs0[coord], point, 12, 12); + + GX_BP_LOAD_REG(gx->suTs0[coord]); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetCullMode(GXCullMode mode) +{ + switch (mode) { + case GX_CULL_FRONT: + mode = GX_CULL_BACK; + break; + case GX_CULL_BACK: + mode = GX_CULL_FRONT; + break; + } + + GX_SET_REG(gx->genMode, mode, 16, 17); + gx->dirtyState |= 4; +} + +void GXSetCoPlanar(GXBool enable) +{ + GX_SET_REG(gx->genMode, enable, 12, 12); + GX_BP_LOAD_REG(0xFE080000); + GX_BP_LOAD_REG(gx->genMode); +} + +void __GXSetGenMode(void) +{ + GX_BP_LOAD_REG(gx->genMode); + gx->bpSentNot = GX_FALSE; +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXInit.c b/src/static/GAEJ01_01/dolphin/gx/GXInit.c new file mode 100644 index 00000000..5d5ee04a --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXInit.c @@ -0,0 +1,562 @@ +#include +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +static GXFifoObj FifoObj; +static GXData gxData; +GXData* const __GXData = &gxData; + +char* __GXVersion = "<< Dolphin SDK - GX\trelease build: Nov 26 2003 05:19:07 (0x2301) >>"; + +u32* __piReg = NULL; +u16* __cpReg = NULL; +u16* __peReg = NULL; +u16* __memReg = NULL; + +static u16 DefaultTexData[] ATTRIBUTE_ALIGN(32) = { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, +}; + +static GXVtxAttrFmtList GXDefaultVATList[] = { + { GX_VA_POS, GX_POS_XYZ, GX_F32, 0 }, + { GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0 }, + { GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 }, + { GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0 }, + { GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 }, + { GX_VA_TEX1, GX_TEX_ST, GX_F32, 0 }, + { GX_VA_TEX2, GX_TEX_ST, GX_F32, 0 }, + { GX_VA_TEX3, GX_TEX_ST, GX_F32, 0 }, + { GX_VA_TEX4, GX_TEX_ST, GX_F32, 0 }, + { GX_VA_TEX5, GX_TEX_ST, GX_F32, 0 }, + { GX_VA_TEX6, GX_TEX_ST, GX_F32, 0 }, + { GX_VA_TEX7, GX_TEX_ST, GX_F32, 0 }, + { GX_VA_NULL, 0, 0, 0 }, +}; + +static f32 GXDefaultProjData[] = { 1.0f, 0.0f, 1.0f, 0.0f, -1.0f, -2.0f, 0.0f }; + +static u32 GXTexRegionAddrTable[] = { + 0x00000, 0x10000, 0x20000, 0x30000, 0x40000, 0x50000, 0x60000, 0x70000, 0x08000, 0x18000, 0x28000, 0x38000, + 0x48000, 0x58000, 0x68000, 0x78000, 0x00000, 0x90000, 0x20000, 0xB0000, 0x40000, 0x98000, 0x60000, 0xB8000, + 0x80000, 0x10000, 0xA0000, 0x30000, 0x88000, 0x50000, 0xA8000, 0x70000, 0x00000, 0x90000, 0x20000, 0xB0000, + 0x40000, 0x90000, 0x60000, 0xB0000, 0x80000, 0x10000, 0xA0000, 0x30000, 0x80000, 0x50000, 0xA0000, 0x70000, +}; + +// forward declaring static reset function +static BOOL __GXShutdown(BOOL); + +static OSResetFunctionInfo GXResetFuncInfo = { __GXShutdown, 127 }; + +ASM BOOL IsWriteGatherBufferEmpty(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc; + sync; + + mfspr r3, WPAR; + andi. r3, r3, 1; + blr; +#endif // clang-format on +} + +static void EnableWriteGatherPipe() +{ + u32 hid2; // r31 + hid2 = PPCMfhid2(); + PPCMtwpar(OSUncachedToPhysical((void*)GXFIFO_ADDR)); + hid2 |= 0x40000000; + PPCMthid2(hid2); +} + +static void DisableWriteGatherPipe() +{ + u32 hid2; + hid2 = PPCMfhid2(); + hid2 &= ~0x40000000; + PPCMthid2(hid2); +} + +static GXTexRegion* __GXDefaultTexRegionCallback(const GXTexObj* obj, GXTexMapID id) +{ + GXTexFmt format; + GXBool isMipMap; + + format = GXGetTexObjFmt(obj); + isMipMap = GXGetTexObjMipMap(obj); + id = (GXTexMapID)(id % GX_MAX_TEXMAP); + + switch (format) { + case GX_TF_RGBA8: + if (isMipMap) { + return &gx->TexRegions2[id]; + } + return &gx->TexRegions1[id]; + + case GX_TF_C4: + case GX_TF_C8: + case GX_TF_C14X2: + return &gx->TexRegions0[id]; + + default: + if (isMipMap) { + return &gx->TexRegions1[id]; + } + return &gx->TexRegions0[id]; + } +} + +static GXTlutRegion* __GXDefaultTlutRegionCallback(u32 tlut) +{ + if (tlut >= GX_MAX_TLUT_ALL) { + return NULL; + } + + return &gx->TlutRegions[tlut]; +} + +BOOL __GXShutdown(BOOL final) +{ + static u32 peCount; + static OSTime time; + static u32 calledOnce = 0; + + u32 val; + u32 newPeCount; + OSTime newTime; + + if (!final) { + if (!calledOnce) { + peCount = GXReadMEMReg(0x28, 0x27); + time = OSGetTime(); + calledOnce = 1; + return FALSE; + } + + newTime = OSGetTime(); + newPeCount = GXReadMEMReg(0x28, 0x27); + + if (newTime - time < 10) { + return FALSE; + } + + if (newPeCount != peCount) { + peCount = newPeCount; + time = newTime; + return FALSE; + } + + } else { + GXSetBreakPtCallback(NULL); + GXSetDrawSyncCallback(NULL); + GXSetDrawDoneCallback(NULL); + + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + + PPCSync(); + + GX_SET_CP_REG(1, 0); + GX_SET_CP_REG(2, 3); + + gx->abtWaitPECopy = GX_TRUE; + + __GXAbort(); + } + + return TRUE; +} + +GXFifoObj* GXInit(void* base, u32 size) +{ + static u32 resetFuncRegistered = 0; + u32 i; + u32 pad; + u32 pad2; + + OSRegisterVersion(__GXVersion); + gx->inDispList = GX_FALSE; + gx->dlSaveContext = GX_TRUE; + gx->abtWaitPECopy = GX_TRUE; + + gx->tcsManEnab = 0; + gx->tevTcEnab = 0; + + GXSetMisc(GX_MT_XF_FLUSH, 0); + + __piReg = (u32*)OSPhysicalToUncached(GX_PI_ADDR); + __cpReg = (u16*)OSPhysicalToUncached(GX_CP_ADDR); + __peReg = (u16*)OSPhysicalToUncached(GX_PE_ADDR); + __memReg = (u16*)OSPhysicalToUncached(GX_MEM_ADDR); + + __GXFifoInit(); + + GXInitFifoBase(&FifoObj, base, size); + GXSetCPUFifo(&FifoObj); + GXSetGPFifo(&FifoObj); + + if (!resetFuncRegistered) { + OSRegisterResetFunction(&GXResetFuncInfo); + resetFuncRegistered = 1; + } + + __GXPEInit(); + EnableWriteGatherPipe(); + + gx->genMode = 0; + GX_SET_REG(gx->genMode, 0, 0, 7); + + gx->bpMask = 255; + GX_SET_REG(gx->bpMask, 0xF, 0, 7); + + gx->lpSize = 0; + GX_SET_REG(gx->lpSize, 34, 0, 7); + + for (i = 0; i < GX_MAX_TEVSTAGE; i++) { + gx->tevc[i] = 0; + gx->teva[i] = 0; + gx->tref[i / 2] = 0; + gx->texmapId[i] = GX_TEXMAP_NULL; + + GX_SET_REG(gx->tevc[i], 0xC0 + i * 2, 0, 7); + GX_SET_REG(gx->teva[i], 0xC1 + i * 2, 0, 7); + GX_SET_REG(gx->tevKsel[i / 2], 0xF6 + i / 2, 0, 7); + GX_SET_REG(gx->tref[i / 2], 0x28 + i / 2, 0, 7); + } + + gx->iref = 0; + GX_SET_REG(gx->iref, 0x27, 0, 7); + + for (i = 0; i < GX_MAX_TEXCOORD; i++) { + gx->suTs0[i] = 0; + gx->suTs1[i] = 0; + + GX_SET_REG(gx->suTs0[i], 0x30 + i * 2, 0, 7); + GX_SET_REG(gx->suTs1[i], 0x31 + i * 2, 0, 7); + } + + GX_SET_REG(gx->suScis0, 0x20, 0, 7); + GX_SET_REG(gx->suScis1, 0x21, 0, 7); + + GX_SET_REG(gx->cmode0, 0x41, 0, 7); + GX_SET_REG(gx->cmode1, 0x42, 0, 7); + + GX_SET_REG(gx->zmode, 0x40, 0, 7); + GX_SET_REG(gx->peCtrl, 0x43, 0, 7); + + GX_SET_REG(gx->cpTex, 0, 23, 24); + + gx->zScale = 1.6777216E7f; + gx->zOffset = 0.0f; + + gx->dirtyState = 0; + gx->dirtyVAT = 0; + + { + u32 val1; + u32 val2; + + val2 = OS_BUS_CLOCK / 500; + + __GXFlushTextureState(); + + val1 = (val2 / 2048) | 0x69000400; + + GX_BP_LOAD_REG(val1); + + __GXFlushTextureState(); + + val1 = (val2 / 4224) | 0x46000200; + + GX_BP_LOAD_REG(val1); + } + + for (i = 0; i < 8; i++) { + GX_SET_REG(gx->vatA[i], 1, 1, 1); + GX_SET_REG(gx->vatB[i], 1, 0, 0); + + GX_CP_LOAD_REG(i | 0x80, gx->vatB[i]); + } + + { + u32 reg1 = 0; + u32 reg2 = 0; + + GX_SET_REG(reg1, 1, 31, 31); + GX_SET_REG(reg1, 1, 30, 30); + GX_SET_REG(reg1, 1, 29, 29); + GX_SET_REG(reg1, 1, 28, 28); + GX_SET_REG(reg1, 1, 27, 27); + GX_SET_REG(reg1, 1, 26, 26); + + GX_XF_LOAD_REG(0x1000, reg1); + + GX_SET_REG(reg2, 1, 31, 31); + + GX_XF_LOAD_REG(0x1012, reg2); + } + + { + u32 reg = 0; + GX_SET_REG(reg, 1, 31, 31); + GX_SET_REG(reg, 1, 30, 30); + GX_SET_REG(reg, 1, 29, 29); + GX_SET_REG(reg, 1, 28, 28); + GX_SET_REG(reg, 0x58, 0, 7); + + GX_BP_LOAD_REG(reg); + } + + for (i = 0; i < GX_MAX_TEXMAP; i++) { + GXInitTexCacheRegion(&gx->TexRegions0[i], GX_FALSE, GXTexRegionAddrTable[i], GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 8], + GX_TEXCACHE_32K); + GXInitTexCacheRegion(&gx->TexRegions1[i], GX_FALSE, GXTexRegionAddrTable[i + 16], GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 24], + GX_TEXCACHE_32K); + GXInitTexCacheRegion(&gx->TexRegions2[i], GX_TRUE, GXTexRegionAddrTable[i + 32], GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 40], + GX_TEXCACHE_32K); + } + + for (i = 0; i < GX_MAX_TLUT; i++) { + GXInitTlutRegion(&gx->TlutRegions[i], 0xC0000 + 0x2000 * i, GX_TLUT_256); + } + + for (i = 0; i < GX_MAX_BIGTLUT; i++) { + GXInitTlutRegion(&gx->TlutRegions[i + 16], 0xE0000 + 0x8000 * i, GX_TLUT_1K); + } + + GX_SET_CP_REG(3, 0); + + GX_SET_REG(gx->perfSel, 0, 24, 27); + + GX_CP_LOAD_REG(0x20, gx->perfSel) + + GX_XF_LOAD_REG(0x1006, 0); + + GX_BP_LOAD_REG(0x23000000) + GX_BP_LOAD_REG(0x24000000) + GX_BP_LOAD_REG(0x67000000) + + __GXSetIndirectMask(0); + __GXSetTmemConfig(2); + __GXInitGX(); + + return &FifoObj; +} + +void __GXInitGX(void) +{ + GXRenderModeObj* renderObj; + GXTexObj texObj; + Mtx34 ident; + GXColor clearColor = { 64, 64, 64, 255 }; + GXColor ambColor = { 0, 0, 0, 0 }; + GXColor matColor = { 255, 255, 255, 255 }; + u32 i; + + switch (VIGetTvFormat()) { + case VI_NTSC: + renderObj = &GXNtsc480IntDf; + break; + + case VI_PAL: + renderObj = &GXPal528IntDf; + break; + + case VI_EURGB60: + renderObj = &GXEurgb60Hz480IntDf; + break; + + case VI_MPAL: + renderObj = &GXMpal480IntDf; + break; + + default: + renderObj = &GXNtsc480IntDf; + break; + } + + GXSetCopyClear(clearColor, 0xFFFFFF); + + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + + GXSetNumTexGens(1); + GXClearVtxDesc(); + GXInvalidateVtxCache(); + + for (i = GX_VA_POS; i <= GX_LIGHT_ARRAY; i++) { + GXSetArray((GXAttr)i, gx, 0); + } + + for (i = 0; i < GX_MAX_VTXFMT; i++) { + GXSetVtxAttrFmtv((GXVtxFmt)i, GXDefaultVATList); + } + + GXSetLineWidth(6, GX_TO_ZERO); + GXSetPointSize(6, GX_TO_ZERO); + GXEnableTexOffsets(GX_TEXCOORD0, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD1, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD2, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD3, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD4, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD5, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD6, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD7, GX_FALSE, GX_FALSE); + + ident[0][0] = 1.0f; + ident[0][1] = 0.0f; + ident[0][2] = 0.0f; + ident[0][3] = 0.0f; + + ident[1][0] = 0.0f; + ident[1][1] = 1.0f; + ident[1][2] = 0.0f; + ident[1][3] = 0.0f; + + ident[2][0] = 0.0f; + ident[2][1] = 0.0f; + ident[2][2] = 1.0f; + ident[2][3] = 0.0f; + + GXLoadPosMtxImm(ident, GX_PNMTX0); + GXLoadNrmMtxImm(ident, GX_PNMTX0); + GXSetCurrentMtx(GX_PNMTX0); + + GXLoadTexMtxImm(ident, GX_IDENTITY, GX_MTX3x4); + GXLoadTexMtxImm(ident, GX_PTIDENTITY, GX_MTX3x4); + + GXSetViewport(0.0f, 0.0f, renderObj->fbWidth, renderObj->xfbHeight, 0.0f, 1.0f); + + GXSetProjectionv(GXDefaultProjData); + + GXSetCoPlanar(GX_FALSE); + GXSetCullMode(GX_CULL_BACK); + GXSetClipMode(GX_CLIP_ENABLE); + + GXSetScissor(0, 0, renderObj->fbWidth, renderObj->efbHeight); + GXSetScissorBoxOffset(0, 0); + + GXSetNumChans(0); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR0A0, ambColor); + GXSetChanMatColor(GX_COLOR0A0, matColor); + + GXSetChanCtrl(GX_COLOR1A1, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR1A1, ambColor); + GXSetChanMatColor(GX_COLOR1A1, matColor); + + GXInvalidateTexAll(); + GXSetTexRegionCallback(__GXDefaultTexRegionCallback); + GXSetTlutRegionCallback(__GXDefaultTlutRegionCallback); + + GXInitTexObj(&texObj, DefaultTexData, 4, 4, GX_TF_IA8, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXLoadTexObj(&texObj, GX_TEXMAP0); + GXLoadTexObj(&texObj, GX_TEXMAP1); + GXLoadTexObj(&texObj, GX_TEXMAP2); + GXLoadTexObj(&texObj, GX_TEXMAP3); + GXLoadTexObj(&texObj, GX_TEXMAP4); + GXLoadTexObj(&texObj, GX_TEXMAP5); + GXLoadTexObj(&texObj, GX_TEXMAP6); + GXLoadTexObj(&texObj, GX_TEXMAP7); + + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0); + + GXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE10, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE11, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE12, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE13, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE14, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE15, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + + GXSetNumTevStages(1); + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + + GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0); + + for (i = 0; i < GX_MAX_TEVSTAGE; i++) { + GXSetTevKColorSel((GXTevStageID)i, GX_TEV_KCSEL_1_4); + GXSetTevKAlphaSel((GXTevStageID)i, GX_TEV_KASEL_1); + GXSetTevSwapMode((GXTevStageID)i, GX_TEV_SWAP0, GX_TEV_SWAP0); + } + + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA); + + for (i = 0; i < GX_MAX_TEVSTAGE; i++) { + GXSetTevDirect((GXTevStageID)i); + } + + GXSetNumIndStages(0); + GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE1, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE2, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE3, GX_ITS_1, GX_ITS_1); + + GXSetFog(GX_FOG_NONE, 0.0f, 1.0f, 0.1f, 1.0f, ambColor); + GXSetFogRangeAdj(GX_FALSE, 0, NULL); + + GXSetBlendMode(GX_BM_NONE, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + + GXSetColorUpdate(GX_TRUE); + GXSetAlphaUpdate(GX_TRUE); + + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GXSetZCompLoc(GX_TRUE); + + GXSetDither(GX_TRUE); + + GXSetDstAlpha(GX_FALSE, 0); + GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + GXSetFieldMask(GX_TRUE, GX_TRUE); + GXSetFieldMode((GXBool)renderObj->field_rendering, (GXBool)((renderObj->viHeight == 2 * renderObj->xfbHeight) ? GX_TRUE : GX_FALSE)); + + GXSetDispCopySrc(0, 0, renderObj->fbWidth, renderObj->efbHeight); + GXSetDispCopyDst(renderObj->fbWidth, renderObj->efbHeight); + GXSetDispCopyYScale((f32)renderObj->xfbHeight / (f32)renderObj->efbHeight); + GXSetCopyClamp((GXFBClamp)(GX_CLAMP_TOP | GX_CLAMP_BOTTOM)); + + GXSetCopyFilter(renderObj->aa, renderObj->sample_pattern, GX_TRUE, renderObj->vfilter); + GXSetDispCopyGamma(GX_GM_1_0); + GXSetDispCopyFrame2Field(GX_COPY_PROGRESSIVE); + GXClearBoundingBox(); + + GXPokeColorUpdate(GX_TRUE); + GXPokeAlphaUpdate(GX_TRUE); + GXPokeDither(GX_FALSE); + GXPokeBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ONE, GX_LO_SET); + GXPokeAlphaMode(GX_ALWAYS, 0); + GXPokeAlphaRead(GX_READ_FF); + GXPokeDstAlpha(GX_FALSE, 0); + GXPokeZMode(GX_TRUE, GX_ALWAYS, GX_TRUE); + GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE); + GXClearGPMetric(); +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXLight.c b/src/static/GAEJ01_01/dolphin/gx/GXLight.c new file mode 100644 index 00000000..ce44a70a --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXLight.c @@ -0,0 +1,336 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" + +void GXInitLightAttn(GXLightObj* obj, f32 a0, f32 a1, f32 a2, f32 k0, f32 k1, f32 k2) +{ + GXLightObjPriv* pObj = (GXLightObjPriv*)obj; + pObj->a[0] = a0; + pObj->a[1] = a1; + pObj->a[2] = a2; + + pObj->k[0] = k0; + pObj->k[1] = k1; + pObj->k[2] = k2; +} + +void GXInitLightSpot(GXLightObj* obj, f32 cutoff, GXSpotFn spotFunc) +{ + f32 a0, a1, a2, r, d, cr; + GXLightObjPriv* pObj = (GXLightObjPriv*)obj; + + if (cutoff <= 0.0f || cutoff > 90.0f) { + spotFunc = GX_SP_OFF; + } + + r = cutoff * 3.1415927f / 180.0f; + cr = cosf(r); + + switch (spotFunc) { + case GX_SP_FLAT: + a0 = -1000.0f * cr; + a1 = 1000.0f; + a2 = 0.0f; + break; + case GX_SP_COS: + a1 = 1.0f / (1.0f - cr); + a0 = -cr * a1; + a2 = 0.0f; + break; + case GX_SP_COS2: + a2 = 1.0f / (1.0f - cr); + a0 = 0.0f; + a1 = -cr * a2; + break; + case GX_SP_SHARP: + d = 1.0F / ((1.0F - cr) * (1.0F - cr)); + a0 = cr * (cr - 2.0F) * d; + a1 = 2.0F * d; + a2 = -d; + break; + case GX_SP_RING1: + d = 1.0f / ((1.0f - cr) * (1.0F - cr)); + a2 = -4.0f * d; + a0 = a2 * cr; + a1 = 4.0f * (1.0f + cr) * d; + break; + case GX_SP_RING2: + d = 1.0f / ((1.0f - cr) * (1.0F - cr)); + a0 = 1.0f - 2.0f * cr * cr * d; + a1 = 4.0f * cr * d; + a2 = -2.0f * d; + break; + case GX_SP_OFF: + default: + a0 = 1.0f; + a1 = 0.0f; + a2 = 0.0f; + break; + } + + pObj->a[0] = a0; + pObj->a[1] = a1; + pObj->a[2] = a2; +} + +void GXInitLightDistAttn(GXLightObj* obj, f32 refDist, f32 refBrightness, GXDistAttnFn distFunc) +{ + f32 k0, k1, k2; + GXLightObjPriv* pObj = (GXLightObjPriv*)obj; + + if (refDist < 0.0F) { + distFunc = GX_DA_OFF; + } + + if (refBrightness <= 0.0F || refBrightness >= 1.0F) { + distFunc = GX_DA_OFF; + } + + switch (distFunc) { + case GX_DA_GENTLE: + k0 = 1.0F; + k1 = (1.0F - refBrightness) / (refBrightness * refDist); + k2 = 0.0F; + break; + case GX_DA_MEDIUM: + k0 = 1.0f; + k1 = 0.5f * (1.0f - refBrightness) / (refBrightness * refDist); + k2 = 0.5f * (1.0f - refBrightness) / (refBrightness * refDist * refDist); + break; + case GX_DA_STEEP: + k0 = 1.0f; + k1 = 0.0f; + k2 = (1.0f - refBrightness) / (refBrightness * refDist * refDist); + break; + case GX_DA_OFF: + default: + k0 = 1.0f; + k1 = 0.0f; + k2 = 0.0f; + break; + } + + pObj->k[0] = k0; + pObj->k[1] = k1; + pObj->k[2] = k2; +} + +void GXInitLightPos(GXLightObj* obj, f32 x, f32 y, f32 z) +{ + GXLightObjPriv* pObj = (GXLightObjPriv*)obj; + pObj->lpos[0] = x; + pObj->lpos[1] = y; + pObj->lpos[2] = z; +} + +void GXInitLightDir(GXLightObj* obj, f32 nX, f32 nY, f32 nZ) +{ + GXLightObjPriv* pObj = (GXLightObjPriv*)obj; + pObj->ldir[0] = -nX; + pObj->ldir[1] = -nY; + pObj->ldir[2] = -nZ; +} + +void GXInitSpecularDir(GXLightObj* obj, f32 nX, f32 nY, f32 nZ) +{ + f32 mag; + f32 vx, vy, vz; + GXLightObjPriv* pObj = (GXLightObjPriv*)obj; + + vx = -nX; + vy = -nY; + vz = (-nZ + 1.0F); + mag = vx * vx + vy * vy + vz * vz; + + if (mag != 0.0f) { + mag = 1.0f / sqrtf(mag); + } + + pObj->ldir[0] = vx * mag; + pObj->ldir[1] = vy * mag; + pObj->ldir[2] = vz * mag; + + pObj->lpos[0] = nX * -GX_LARGE_NUMBER; + pObj->lpos[1] = nY * -GX_LARGE_NUMBER; + pObj->lpos[2] = nZ * -GX_LARGE_NUMBER; +} + +void GXInitLightColor(GXLightObj* obj, GXColor color) +{ + GXLightObjPriv* pObj = (GXLightObjPriv*)obj; + pObj->color = color; +} + +static inline void PushLight(const register GXLightObjPriv* lt_obj, register void* dest) +{ + register u32 zero, color; + register f32 a0_a1, a2_k0, k1_k2; + register f32 px_py, pz_dx, dy_dz; +#ifdef __MWERKS__ // clang-format off + asm { + lwz color, 12(lt_obj) + xor zero, zero, zero + psq_l a0_a1, 16(lt_obj), 0, 0 + psq_l a2_k0, 24(lt_obj), 0, 0 + psq_l k1_k2, 32(lt_obj), 0, 0 + psq_l px_py, 40(lt_obj), 0, 0 + psq_l pz_dx, 48(lt_obj), 0, 0 + psq_l dy_dz, 56(lt_obj), 0, 0 + + stw zero, 0(dest) + stw zero, 0(dest) + stw zero, 0(dest) + stw color, 0(dest) + psq_st a0_a1, 0(dest), 0, 0 + psq_st a2_k0, 0(dest), 0, 0 + psq_st k1_k2, 0(dest), 0, 0 + psq_st px_py, 0(dest), 0, 0 + psq_st pz_dx, 0(dest), 0, 0 + psq_st dy_dz, 0(dest), 0, 0 + } +#endif // clang-format on +} + +void GXLoadLightObjImm(GXLightObj* obj, GXLightID light) +{ + u32 addr; + u32 idx; + GXLightObjPriv* pObj = (GXLightObjPriv*)obj; + + idx = 31 - __cntlzw(light); + idx &= 7; + + addr = 0x600 + idx * 0x10; + + GX_XF_LOAD_REG_HDR(addr | (0x10 - 1) << 16); + + PushLight(pObj, (void*)GXFIFO_ADDR); + __GXData->bpSentNot = 1; +} + +void GXSetChanAmbColor(GXChannelID channel, GXColor color) +{ + u32 reg; + u32 rgb; + u32 colorID; + u8 alpha; + + switch (channel) { + case GX_COLOR0: + rgb = gx->ambColor[GX_COLOR0]; + reg = GX_SET_TRUNC(GXCOLOR_AS_U32(color) & ~0xff, rgb, 24, 31); + colorID = GX_COLOR0; + break; + case GX_COLOR1: + rgb = gx->ambColor[GX_COLOR1]; + reg = GX_SET_TRUNC(GXCOLOR_AS_U32(color) & ~0xff, rgb, 24, 31); + colorID = GX_COLOR1; + break; + case GX_ALPHA0: + reg = gx->ambColor[GX_COLOR0]; + reg = GX_SET_TRUNC(reg, color.a, 24, 31); + colorID = GX_COLOR0; + break; + case GX_ALPHA1: + reg = gx->ambColor[GX_COLOR1]; + reg = GX_SET_TRUNC(reg, color.a, 24, 31); + colorID = GX_COLOR1; + break; + case GX_COLOR0A0: + reg = GXCOLOR_AS_U32(color); + colorID = GX_COLOR0; + break; + case GX_COLOR1A1: + reg = GXCOLOR_AS_U32(color); + colorID = GX_COLOR1; + break; + default: + return; + } + + GX_XF_LOAD_REG(GX_XF_REG_AMBIENT0 + colorID, reg); + gx->bpSentNot = GX_TRUE; + gx->ambColor[colorID] = reg; +} + +void GXSetChanMatColor(GXChannelID channel, GXColor color) +{ + u32 reg = 0; + u32 rgb; + GXChannelID colorID; + + switch (channel) { + case GX_COLOR0: + rgb = gx->matColor[GX_COLOR0]; + reg = GX_SET_TRUNC(GXCOLOR_AS_U32(color) & ~0xff, rgb, 24, 31); + colorID = GX_COLOR0; + break; + case GX_COLOR1: + rgb = gx->matColor[GX_COLOR1]; + reg = GX_SET_TRUNC(GXCOLOR_AS_U32(color) & ~0xff, rgb, 24, 31); + colorID = GX_COLOR1; + break; + case GX_ALPHA0: + reg = gx->matColor[GX_COLOR0]; + reg = GX_SET_TRUNC(reg, color.a, 24, 31); + colorID = GX_COLOR0; + break; + case GX_ALPHA1: + reg = gx->matColor[GX_COLOR1]; + reg = GX_SET_TRUNC(reg, color.a, 24, 31); + colorID = GX_COLOR1; + break; + case GX_COLOR0A0: + reg = GXCOLOR_AS_U32(color); + colorID = GX_COLOR0; + break; + case GX_COLOR1A1: + reg = GXCOLOR_AS_U32(color); + colorID = GX_COLOR1; + break; + default: + return; + } + + GX_XF_LOAD_REG(GX_XF_REG_MATERIAL0 + colorID, reg); + gx->bpSentNot = GX_TRUE; + gx->matColor[colorID] = reg; +} + +void GXSetNumChans(u8 count) +{ + GX_SET_REG(gx->genMode, count, 25, 27); + GX_XF_LOAD_REG(GX_XF_REG_NUMCOLORS, count); + gx->dirtyState |= GX_DIRTY_GEN_MODE; +} + +void GXSetChanCtrl(GXChannelID channel, GXBool doEnable, GXColorSrc ambSrc, GXColorSrc matSrc, u32 mask, GXDiffuseFn diffFunc, + GXAttnFn attnFunc) +{ + const u32 colorID = (u32)channel & 0x3; + u32 reg = 0; + + GX_SET_REG(reg, doEnable, GX_XF_CLR0CTRL_LIGHT_ST, GX_XF_CLR0CTRL_LIGHT_END); + GX_SET_REG(reg, matSrc, GX_XF_CLR0CTRL_MTXSRC_ST, GX_XF_CLR0CTRL_MTXSRC_END); + GX_SET_REG(reg, ambSrc, GX_XF_CLR0CTRL_AMBSRC_ST, GX_XF_CLR0CTRL_AMBSRC_END); + GX_SET_REG(reg, (attnFunc == GX_AF_SPEC ? GX_DF_NONE : diffFunc), GX_XF_CLR0CTRL_DIFATTN_ST, GX_XF_CLR0CTRL_DIFATTN_END); + GX_SET_REG(reg, (attnFunc != GX_AF_NONE), GX_XF_CLR0CTRL_ATTNENABLE_ST, GX_XF_CLR0CTRL_ATTNENABLE_END); + GX_SET_REG(reg, (attnFunc != GX_AF_SPEC), GX_XF_CLR0CTRL_ATTNSEL_ST, GX_XF_CLR0CTRL_ATTNSEL_END); + + // why are we unmasking bits we're about to overwrite? + + reg = (reg & ~(0xf << 2)) | ((mask & 0xf) << 2); + + reg = (reg & ~(0xf << 11)) | (((mask >> 4) & 0xf) << 11); + + GX_XF_LOAD_REG(GX_XF_REG_COLOR0CNTRL + colorID, reg); + + if (channel == GX_COLOR0A0) { + GX_XF_LOAD_REG(GX_XF_REG_ALPHA0CNTRL, reg); + } else if (channel == GX_COLOR1A1) { + GX_XF_LOAD_REG(GX_XF_REG_ALPHA1CNTRL, reg); + } + + gx->bpSentNot = GX_TRUE; +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXMisc.c b/src/static/GAEJ01_01/dolphin/gx/GXMisc.c new file mode 100644 index 00000000..7efc082d --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXMisc.c @@ -0,0 +1,322 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +static GXDrawSyncCallback TokenCB; +static GXDrawDoneCallback DrawDoneCB; +static GXBool DrawDone; +static OSThreadQueue FinishQueue; + +void GXSetMisc(GXMiscToken token, u32 val) +{ + switch (token) { + case GX_MT_NULL: + break; + + case GX_MT_XF_FLUSH: + gx->vNum = val; + gx->vNumNot = !gx->vNum; + gx->bpSentNot = GX_TRUE; + + if (gx->vNum) { + gx->dirtyState |= GX_DIRTY_VCD; + } + break; + + case GX_MT_DL_SAVE_CONTEXT: + gx->dlSaveContext = (val != 0); + break; + + case GX_MT_ABORT_WAIT_COPYOUT: + gx->abtWaitPECopy = (val != 0); + break; + } +} + +void GXFlush(void) +{ + if (gx->dirtyState) { + __GXSetDirtyState(); + } + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + PPCSync(); +} + +void GXResetWriteGatherPipe(void) +{ + while (PPCMfwpar() & 1) { + } + PPCMtwpar(OSUncachedToPhysical((void*)GXFIFO_ADDR)); +} + +static void __GXAbortWait(u32 clocks) +{ + OSTime time0, time1; + time0 = OSGetTime(); + + do { + time1 = OSGetTime(); + } while (time1 - time0 <= clocks / 4); +} + +static void __GXAbortWaitPECopyDone(void) +{ + u32 peCnt0, peCnt1; + + peCnt0 = GXReadMEMReg(0x28, 0x27); + do { + peCnt1 = peCnt0; + __GXAbortWait(32); + + peCnt0 = GXReadMEMReg(0x28, 0x27); + } while (peCnt0 != peCnt1); +} + +void __GXAbort(void) +{ + if (gx->abtWaitPECopy && GXGetGPFifo()) { + __GXAbortWaitPECopyDone(); + } + + __PIRegs[0x18 / 4] = 1; + __GXAbortWait(200); + __PIRegs[0x18 / 4] = 0; + __GXAbortWait(20); +} + +void GXAbortFrame(void) +{ + __GXAbort(); + __GXCleanGPFifo(); +} + +void GXSetDrawSync(u16 token) +{ + u32 reg; + BOOL interrupts; + + interrupts = OSDisableInterrupts(); + reg = token | 0x48000000; + GX_BP_LOAD_REG(reg); + GX_SET_REG(reg, token, 16, 31); + GX_SET_REG(reg, 0x47, 0, 7); + GX_BP_LOAD_REG(reg); + + GXFlush(); + OSRestoreInterrupts(interrupts); + gx->bpSentNot = GX_FALSE; +} + +void GXSetDrawDone(void) +{ + u32 reg; + BOOL interrupts; + + interrupts = OSDisableInterrupts(); + reg = 0x45000002; + GX_BP_LOAD_REG(reg); + + GXFlush(); + DrawDone = GX_FALSE; + OSRestoreInterrupts(interrupts); +} + +void GXWaitDrawDone(void) +{ + BOOL interrupts; + interrupts = OSDisableInterrupts(); + while (!DrawDone) { + OSSleepThread(&FinishQueue); + } + + OSRestoreInterrupts(interrupts); +} + +void GXDrawDone(void) +{ + GXSetDrawDone(); + GXWaitDrawDone(); +} + +void GXPixModeSync(void) +{ + GX_BP_LOAD_REG(gx->peCtrl); + gx->bpSentNot = GX_FALSE; +} + +void GXPokeAlphaMode(GXCompare func, u8 threshold) +{ + GX_SET_PE_REG(3, func << 8 | threshold); +} + +void GXPokeAlphaRead(GXAlphaReadMode mode) +{ + u32 reg = 0; + GX_SET_REG(reg, mode, 30, 31); + GX_SET_REG(reg, 1, 29, 29); + GX_SET_PE_REG(4, reg); +} + +void GXPokeAlphaUpdate(GXBool doUpdate) +{ + u32 reg; + reg = GX_GET_PE_REG(1); + GX_SET_REG(reg, doUpdate, 27, 27); + GX_SET_PE_REG(1, reg); +} + +void GXPokeBlendMode(GXBlendMode mode, GXBlendFactor srcFactor, GXBlendFactor destFactor, GXLogicOp op) +{ + u32 reg; + + reg = GX_GET_PE_REG(1); + GX_SET_REG(reg, (mode == GX_BM_BLEND) || (mode == GX_BM_SUBTRACT), 31, 31); + GX_SET_REG(reg, (mode == GX_BM_SUBTRACT), 20, 20); + GX_SET_REG(reg, (mode == GX_BM_LOGIC), 30, 30); + GX_SET_REG(reg, op, 16, 19); + GX_SET_REG(reg, srcFactor, 21, 23); + GX_SET_REG(reg, destFactor, 24, 26); + GX_SET_REG(reg, 0x41, 0, 7); + GX_SET_PE_REG(1, reg); +} + +void GXPokeColorUpdate(GXBool doUpdate) +{ + u32 reg; + reg = GX_GET_PE_REG(1); + GX_SET_REG(reg, doUpdate, 28, 28); + GX_SET_PE_REG(1, reg); +} + +void GXPokeDstAlpha(GXBool doEnable, u8 alpha) +{ + u32 reg; + reg = 0; + GX_SET_REG(reg, alpha, 24, 31); + GX_SET_REG(reg, doEnable, 23, 23); + GX_SET_PE_REG(2, reg); +} + +void GXPokeDither(GXBool doDither) +{ + u32 reg; + reg = GX_GET_PE_REG(1); + GX_SET_REG(reg, doDither, 29, 29); + GX_SET_PE_REG(1, reg); +} + +void GXPokeZMode(GXBool doCompare, GXCompare func, GXBool doUpdate) +{ + u32 reg; + reg = 0; + GX_SET_REG(reg, doCompare, 31, 31); + GX_SET_REG(reg, func, 28, 30); + GX_SET_REG(reg, doUpdate, 27, 27); + GX_SET_PE_REG(0, reg); +} + +void GXPeekARGB(u16 x, u16 y, u32* color) +{ + u32 addr = (u32)OSPhysicalToUncached(0x08000000); + + GX_SET_REG(addr, x, 20, 29); + GX_SET_REG(addr, y, 10, 19); + GX_SET_REG(addr, 0, 8, 9); + *color = *(u32*)addr; +} + +GXDrawSyncCallback GXSetDrawSyncCallback(GXDrawSyncCallback callback) +{ + GXDrawSyncCallback prevCB; + BOOL interrupts; + + prevCB = TokenCB; + interrupts = OSDisableInterrupts(); + TokenCB = callback; + OSRestoreInterrupts(interrupts); + return prevCB; +} + +static void GXTokenInterruptHandler(__OSInterrupt interrupt, OSContext* context) +{ + u16 token; + OSContext exceptContext; + u32 reg; + + token = GX_GET_PE_REG(7); + + if (TokenCB) { + OSClearContext(&exceptContext); + OSSetCurrentContext(&exceptContext); + TokenCB(token); + OSClearContext(&exceptContext); + OSSetCurrentContext(context); + } + + reg = GX_GET_PE_REG(5); + GX_SET_REG(reg, 1, 29, 29); + GX_SET_PE_REG(5, reg); +} + +GXDrawDoneCallback GXSetDrawDoneCallback(GXDrawDoneCallback callback) +{ + GXDrawDoneCallback prevCB; + BOOL interrupts; + + prevCB = DrawDoneCB; + interrupts = OSDisableInterrupts(); + DrawDoneCB = callback; + OSRestoreInterrupts(interrupts); + return prevCB; +} + +static void GXFinishInterruptHandler(__OSInterrupt interrupt, OSContext* context) +{ + OSContext exceptContext; + u32 reg; + + reg = GX_GET_PE_REG(5); + GX_SET_REG(reg, 1, 28, 28); + GX_SET_PE_REG(5, reg); + + DrawDone = GX_TRUE; + + if (DrawDoneCB) { + OSClearContext(&exceptContext); + OSSetCurrentContext(&exceptContext); + DrawDoneCB(); + OSClearContext(&exceptContext); + OSSetCurrentContext(context); + } + + OSWakeupThread(&FinishQueue); +} + +void __GXPEInit(void) +{ + u32 reg; + + __OSSetInterruptHandler(__OS_INTERRUPT_PI_PE_TOKEN, GXTokenInterruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_PI_PE_FINISH, GXFinishInterruptHandler); + + OSInitThreadQueue(&FinishQueue); + + __OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_PE_TOKEN); + __OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_PE_FINISH); + + reg = GX_GET_PE_REG(5); + GX_SET_REG(reg, 1, 29, 29); + GX_SET_REG(reg, 1, 28, 28); + GX_SET_REG(reg, 1, 31, 31); + GX_SET_REG(reg, 1, 30, 30); + GX_SET_PE_REG(5, reg); +} + diff --git a/src/static/GAEJ01_01/dolphin/gx/GXPerf.c b/src/static/GAEJ01_01/dolphin/gx/GXPerf.c new file mode 100644 index 00000000..5593064c --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXPerf.c @@ -0,0 +1,307 @@ +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) +{ + switch (gx->perf0) { + case GX_PERF0_VERTICES: + case GX_PERF0_CLIP_VTX: + case GX_PERF0_CLIP_CLKS: + case GX_PERF0_XF_WAIT_IN: + case GX_PERF0_XF_WAIT_OUT: + case GX_PERF0_XF_XFRM_CLKS: + case GX_PERF0_XF_LIT_CLKS: + case GX_PERF0_XF_BOT_CLKS: + case GX_PERF0_XF_REGLD_CLKS: + case GX_PERF0_XF_REGRD_CLKS: + case GX_PERF0_CLIP_RATIO: + case GX_PERF0_CLOCKS: + GX_XF_LOAD_REG(0x1006, 0); + break; + + case GX_PERF0_TRIANGLES: + case GX_PERF0_TRIANGLES_CULLED: + case GX_PERF0_TRIANGLES_PASSED: + case GX_PERF0_TRIANGLES_SCISSORED: + case GX_PERF0_TRIANGLES_0TEX: + case GX_PERF0_TRIANGLES_1TEX: + case GX_PERF0_TRIANGLES_2TEX: + case GX_PERF0_TRIANGLES_3TEX: + case GX_PERF0_TRIANGLES_4TEX: + case GX_PERF0_TRIANGLES_5TEX: + case GX_PERF0_TRIANGLES_6TEX: + case GX_PERF0_TRIANGLES_7TEX: + case GX_PERF0_TRIANGLES_8TEX: + case GX_PERF0_TRIANGLES_0CLR: + case GX_PERF0_TRIANGLES_1CLR: + case GX_PERF0_TRIANGLES_2CLR: + GX_BP_LOAD_REG(0x23000000); + break; + + case GX_PERF0_QUAD_0CVG: + case GX_PERF0_QUAD_NON0CVG: + case GX_PERF0_QUAD_1CVG: + case GX_PERF0_QUAD_2CVG: + case GX_PERF0_QUAD_3CVG: + case GX_PERF0_QUAD_4CVG: + case GX_PERF0_AVG_QUAD_CNT: + GX_BP_LOAD_REG(0x24000000); + break; + + case GX_PERF0_NONE: + break; + } + + switch (gx->perf1) { + case GX_PERF1_TEXELS: + case GX_PERF1_TX_IDLE: + case GX_PERF1_TX_REGS: + case GX_PERF1_TX_MEMSTALL: + case GX_PERF1_TC_CHECK1_2: + case GX_PERF1_TC_CHECK3_4: + case GX_PERF1_TC_CHECK5_6: + case GX_PERF1_TC_CHECK7_8: + case GX_PERF1_TC_MISS: + case GX_PERF1_CLOCKS: + GX_BP_LOAD_REG(0x67000000); + break; + + case GX_PERF1_VC_ELEMQ_FULL: + case GX_PERF1_VC_MISSQ_FULL: + case GX_PERF1_VC_MEMREQ_FULL: + case GX_PERF1_VC_STATUS7: + case GX_PERF1_VC_MISSREP_FULL: + case GX_PERF1_VC_STREAMBUF_LOW: + case GX_PERF1_VC_ALL_STALLS: + case GX_PERF1_VERTICES: + GX_SET_REG(gx->perfSel, 0, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + + case GX_PERF1_FIFO_REQ: + case GX_PERF1_CALL_REQ: + case GX_PERF1_VC_MISS_REQ: + case GX_PERF1_CP_ALL_REQ: + GX_SET_CP_REG(3, 0); + break; + + case GX_PERF1_NONE: + break; + } + + gx->perf0 = perf0; + + switch (gx->perf0) { + case GX_PERF0_VERTICES: + GX_XF_LOAD_REG(0x1006, 0x273); + break; + case GX_PERF0_CLIP_VTX: + GX_XF_LOAD_REG(0x1006, 0x14A); + break; + case GX_PERF0_CLIP_CLKS: + GX_XF_LOAD_REG(0x1006, 0x16B); + break; + case GX_PERF0_XF_WAIT_IN: + GX_XF_LOAD_REG(0x1006, 0x84); + break; + case GX_PERF0_XF_WAIT_OUT: + GX_XF_LOAD_REG(0x1006, 0xC6); + break; + case GX_PERF0_XF_XFRM_CLKS: + GX_XF_LOAD_REG(0x1006, 0x210); + break; + case GX_PERF0_XF_LIT_CLKS: + GX_XF_LOAD_REG(0x1006, 0x252); + break; + case GX_PERF0_XF_BOT_CLKS: + GX_XF_LOAD_REG(0x1006, 0x231); + break; + case GX_PERF0_XF_REGLD_CLKS: + GX_XF_LOAD_REG(0x1006, 0x1AD); + break; + case GX_PERF0_XF_REGRD_CLKS: + GX_XF_LOAD_REG(0x1006, 0x1CE); + break; + case GX_PERF0_CLOCKS: + GX_XF_LOAD_REG(0x1006, 0x21); + break; + case GX_PERF0_CLIP_RATIO: + GX_XF_LOAD_REG(0x1006, 0x153); + break; + + case GX_PERF0_TRIANGLES: + GX_BP_LOAD_REG(0x2300AE7F); + break; + case GX_PERF0_TRIANGLES_CULLED: + GX_BP_LOAD_REG(0x23008E7F); + break; + case GX_PERF0_TRIANGLES_PASSED: + GX_BP_LOAD_REG(0x23009E7F); + break; + case GX_PERF0_TRIANGLES_SCISSORED: + GX_BP_LOAD_REG(0x23001E7F); + break; + case GX_PERF0_TRIANGLES_0TEX: + GX_BP_LOAD_REG(0x2300AC3F); + break; + case GX_PERF0_TRIANGLES_1TEX: + GX_BP_LOAD_REG(0x2300AC7F); + break; + case GX_PERF0_TRIANGLES_2TEX: + GX_BP_LOAD_REG(0x2300ACBF); + break; + case GX_PERF0_TRIANGLES_3TEX: + GX_BP_LOAD_REG(0x2300ACFF); + break; + case GX_PERF0_TRIANGLES_4TEX: + GX_BP_LOAD_REG(0x2300AD3F); + break; + case GX_PERF0_TRIANGLES_5TEX: + GX_BP_LOAD_REG(0x2300AD7F); + break; + case GX_PERF0_TRIANGLES_6TEX: + GX_BP_LOAD_REG(0x2300ADBF); + break; + case GX_PERF0_TRIANGLES_7TEX: + GX_BP_LOAD_REG(0x2300ADFF); + break; + case GX_PERF0_TRIANGLES_8TEX: + GX_BP_LOAD_REG(0x2300AE3F); + break; + case GX_PERF0_TRIANGLES_0CLR: + GX_BP_LOAD_REG(0x2300A27F); + break; + case GX_PERF0_TRIANGLES_1CLR: + GX_BP_LOAD_REG(0x2300A67F); + break; + case GX_PERF0_TRIANGLES_2CLR: + GX_BP_LOAD_REG(0x2300AA7F); + break; + + case GX_PERF0_QUAD_0CVG: + GX_BP_LOAD_REG(0x2402C0C6); + break; + case GX_PERF0_QUAD_NON0CVG: + GX_BP_LOAD_REG(0x2402C16B); + break; + case GX_PERF0_QUAD_1CVG: + GX_BP_LOAD_REG(0x2402C0E7); + break; + case GX_PERF0_QUAD_2CVG: + GX_BP_LOAD_REG(0x2402C108); + break; + case GX_PERF0_QUAD_3CVG: + GX_BP_LOAD_REG(0x2402C129); + break; + case GX_PERF0_QUAD_4CVG: + GX_BP_LOAD_REG(0x2402C14A); + break; + case GX_PERF0_AVG_QUAD_CNT: + GX_BP_LOAD_REG(0x2402C1AD); + break; + + case GX_PERF0_NONE: + break; + } + + gx->perf1 = perf1; + + switch (gx->perf1) { + case GX_PERF1_TEXELS: + GX_BP_LOAD_REG(0x67000042); + break; + case GX_PERF1_TX_IDLE: + GX_BP_LOAD_REG(0x67000084); + break; + case GX_PERF1_TX_REGS: + GX_BP_LOAD_REG(0x67000063); + break; + case GX_PERF1_TX_MEMSTALL: + GX_BP_LOAD_REG(0x67000129); + break; + case GX_PERF1_TC_MISS: + GX_BP_LOAD_REG(0x67000252); + break; + case GX_PERF1_CLOCKS: + GX_BP_LOAD_REG(0x67000021); + break; + case GX_PERF1_TC_CHECK1_2: + GX_BP_LOAD_REG(0x6700014B); + break; + case GX_PERF1_TC_CHECK3_4: + GX_BP_LOAD_REG(0x6700018D); + break; + case GX_PERF1_TC_CHECK5_6: + GX_BP_LOAD_REG(0x670001CF); + break; + case GX_PERF1_TC_CHECK7_8: + GX_BP_LOAD_REG(0x67000211); + break; + + case GX_PERF1_VC_ELEMQ_FULL: + GX_SET_REG(gx->perfSel, 2, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + case GX_PERF1_VC_MISSQ_FULL: + GX_SET_REG(gx->perfSel, 3, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + case GX_PERF1_VC_MEMREQ_FULL: + GX_SET_REG(gx->perfSel, 4, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + case GX_PERF1_VC_STATUS7: + GX_SET_REG(gx->perfSel, 5, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + case GX_PERF1_VC_MISSREP_FULL: + GX_SET_REG(gx->perfSel, 6, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + case GX_PERF1_VC_STREAMBUF_LOW: + GX_SET_REG(gx->perfSel, 7, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + case GX_PERF1_VC_ALL_STALLS: + GX_SET_REG(gx->perfSel, 9, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + case GX_PERF1_VERTICES: + GX_SET_REG(gx->perfSel, 8, 24, 27); + GX_CP_LOAD_REG(0x20, gx->perfSel); + break; + + case GX_PERF1_FIFO_REQ: + GX_SET_CP_REG(3, 2); + break; + case GX_PERF1_CALL_REQ: + GX_SET_CP_REG(3, 3); + break; + case GX_PERF1_VC_MISS_REQ: + GX_SET_CP_REG(3, 4); + break; + case GX_PERF1_CP_ALL_REQ: + GX_SET_CP_REG(3, 5); + break; + + case GX_PERF1_NONE: + break; + } + + gx->bpSentNot = GX_FALSE; +} + +void GXClearGPMetric(void) +{ + GX_SET_CP_REG(2, 4); +} + +#pragma scheduling off +void GXReadXfRasMetric(u32* xfWaitIn, u32* xfWaitOut, u32* rasBusy, u32* clocks) +{ + *rasBusy = GXReadCPReg(32, 33); + *clocks = GXReadCPReg(34, 35); + *xfWaitIn = GXReadCPReg(36, 37); + *xfWaitOut = GXReadCPReg(38, 39); +} +#pragma scheduling reset diff --git a/src/static/GAEJ01_01/dolphin/gx/GXPixel.c b/src/static/GAEJ01_01/dolphin/gx/GXPixel.c new file mode 100644 index 00000000..5835907d --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXPixel.c @@ -0,0 +1,262 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" + +void GXSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor color) +{ + f32 a, c; + u32 a_bits, c_bits; + + u32 fogColorReg = 0; + u32 fogParamReg0 = 0; + u32 fogParamReg1 = 0; + u32 fogParamReg2 = 0; + u32 fogParamReg3 = 0; + + u32 fsel = type & 7; + BOOL isOrtho = (type >> 3) & 1; + + if (isOrtho) { + if (farz == nearz || endz == startz) { + a = 0.0f; + c = 0.0f; + } else { + a = (1.0f / (endz - startz)) * (farz - nearz); + c = (1.0f / (endz - startz)) * (startz - nearz); + } + } else { + f32 tmpA, tmpB, tmpC; + u32 expB, magB, shiftB; + + if (farz == nearz || endz == startz) { + tmpA = 0.0f; + tmpB = 0.5f; + tmpC = 0.0f; + } else { + tmpA = (farz * nearz) / ((farz - nearz) * (endz - startz)); + tmpB = farz / (farz - nearz); + tmpC = startz / (endz - startz); + } + + expB = 0; + while (tmpB > 1.0) { + tmpB /= 2.0f; + expB++; + } + while (tmpB > 0.0f && tmpB < 0.5) { + tmpB *= 2.0f; + expB--; + } + + a = tmpA / (1 << expB + 1); + magB = 8388638.0f * tmpB; + shiftB = expB + 1; + c = tmpC; + + GX_SET_REG(fogParamReg1, magB, GX_BP_FOGPARAM1_B_MAG_ST, GX_BP_FOGPARAM1_B_MAG_END); + GX_SET_REG(fogParamReg2, shiftB, GX_BP_FOGPARAM2_B_SHIFT_ST, GX_BP_FOGPARAM2_B_SHIFT_END); + + GX_SET_REG(fogParamReg1, GX_BP_REG_FOGPARAM1, 0, 7); + GX_SET_REG(fogParamReg2, GX_BP_REG_FOGPARAM2, 0, 7); + } + + a_bits = *(u32*)&a; + c_bits = *(u32*)&c; + + GX_SET_REG(fogParamReg0, a_bits >> 12, GX_BP_FOGPARAM0_A_MANT_ST, GX_BP_FOGPARAM0_A_MANT_END); + GX_SET_REG(fogParamReg0, a_bits >> 23, GX_BP_FOGPARAM0_A_EXP_ST, GX_BP_FOGPARAM0_A_EXP_END); + GX_SET_REG(fogParamReg0, a_bits >> 31, GX_BP_FOGPARAM0_A_SIGN_ST, GX_BP_FOGPARAM0_A_SIGN_END); + + GX_SET_REG(fogParamReg0, GX_BP_REG_FOGPARAM0, 0, 7); + + GX_SET_REG(fogParamReg3, c_bits >> 12, GX_BP_FOGPARAM3_C_MANT_ST, GX_BP_FOGPARAM3_C_MANT_END); + GX_SET_REG(fogParamReg3, c_bits >> 23, GX_BP_FOGPARAM3_C_EXP_ST, GX_BP_FOGPARAM3_C_EXP_END); + GX_SET_REG(fogParamReg3, c_bits >> 31, GX_BP_FOGPARAM3_C_SIGN_ST, GX_BP_FOGPARAM3_C_SIGN_END); + + GX_SET_REG(fogParamReg3, isOrtho, GX_BP_FOGPARAM3_PROJ_ST, GX_BP_FOGPARAM3_PROJ_END); + GX_SET_REG(fogParamReg3, fsel, GX_BP_FOGPARAM3_FSEL_ST, GX_BP_FOGPARAM3_FSEL_END); + + GX_SET_REG(fogParamReg3, GX_BP_REG_FOGPARAM3, 0, 7); + + GX_SET_REG(fogColorReg, color.b, GX_BP_FOGCOLOR_RGB_ST + 16, GX_BP_FOGCOLOR_RGB_END); + GX_SET_REG(fogColorReg, color.g, (GX_BP_FOGCOLOR_RGB_ST + 8), (GX_BP_FOGCOLOR_RGB_END - 8)); + GX_SET_REG(fogColorReg, color.r, (GX_BP_FOGCOLOR_RGB_ST + 0), (GX_BP_FOGCOLOR_RGB_END - 16)); + GX_SET_REG(fogColorReg, GX_BP_REG_FOGCOLOR, 0, 7); + + GX_BP_LOAD_REG(fogParamReg0); + GX_BP_LOAD_REG(fogParamReg1); + GX_BP_LOAD_REG(fogParamReg2); + GX_BP_LOAD_REG(fogParamReg3); + GX_BP_LOAD_REG(fogColorReg); + + gx->bpSentNot = GX_FALSE; +} + +void GXInitFogAdjTable(GXFogAdjTable* table, u16 width, Mtx44 proj) +{ + f32 x, nearZ, scale, sideX, dist; + u32 i; + + if (proj[3][3] == 0.0) { + nearZ = proj[2][3] / (proj[2][2] - 1.0f); + sideX = nearZ / proj[0][0]; + } else { + sideX = 1.0f / proj[0][0]; + nearZ = 1.73205f * sideX; + } + + scale = 2.0f / width; + + for (i = 0; i < 10; i++) { + x = (i + 1) * 32; + x *= scale; + x *= sideX; + dist = sqrtf(1.0f + (x * x) / (nearZ * nearZ)); + table->r[i] = (u32)(dist * 256.0f) & 0xFFF; + } +} + +void GXSetFogRangeAdj(GXBool enable, u16 center, GXFogAdjTable* table) +{ + u32 fogRangeReg; + u32 fogRangeRegK; + u32 i; + + if (enable) { + for (i = 0; i < 10; i += 2) { + fogRangeRegK = 0; + GX_SET_REG(fogRangeRegK, table->r[i], GX_BP_FOGRANGEK_HI_ST, GX_BP_FOGRANGEK_HI_END); + GX_SET_REG(fogRangeRegK, table->r[i + 1], GX_BP_FOGRANGEK_LO_ST, GX_BP_FOGRANGEK_LO_END); + GX_SET_REG(fogRangeRegK, GX_BP_REG_FOGRANGEK0 + (i / 2), 0, 7); + GX_BP_LOAD_REG(fogRangeRegK); + } + } + + fogRangeReg = 0; + GX_SET_REG(fogRangeReg, center + 342, GX_BP_FOGRANGE_CENTER_ST, GX_BP_FOGRANGE_CENTER_END); + GX_SET_REG(fogRangeReg, enable, GX_BP_FOGRANGE_ENABLED_ST, GX_BP_FOGRANGE_ENABLED_END); + GX_SET_REG(fogRangeReg, GX_BP_REG_FOGRANGE, 0, 7); + GX_BP_LOAD_REG(fogRangeReg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op) +{ + u32 blendModeReg = gx->cmode0; + GX_SET_REG(blendModeReg, type == GX_BM_SUBTRACT, GX_BP_BLENDMODE_SUBTRACT_ST, GX_BP_BLENDMODE_SUBTRACT_END); + GX_SET_REG(blendModeReg, type, GX_BP_BLENDMODE_ENABLE_ST, GX_BP_BLENDMODE_ENABLE_END); + GX_SET_REG(blendModeReg, type == GX_BM_LOGIC, GX_BP_BLENDMODE_LOGIC_OP_ST, GX_BP_BLENDMODE_LOGIC_OP_END); + GX_SET_REG(blendModeReg, op, GX_BP_BLENDMODE_LOGICMODE_ST, GX_BP_BLENDMODE_LOGICMODE_END); + GX_SET_REG(blendModeReg, src_factor, GX_BP_BLENDMODE_SRCFACTOR_ST, GX_BP_BLENDMODE_SRCFACTOR_END); + GX_SET_REG(blendModeReg, dst_factor, GX_BP_BLENDMODE_DSTFACTOR_ST, GX_BP_BLENDMODE_DSTFACTOR_END); + + GX_BP_LOAD_REG(blendModeReg); + gx->cmode0 = blendModeReg; + + gx->bpSentNot = FALSE; +} + +void GXSetColorUpdate(GXBool updateEnable) +{ + u32 blendModeReg = gx->cmode0; + GX_SET_REG(blendModeReg, updateEnable, GX_BP_BLENDMODE_COLOR_UPDATE_ST, GX_BP_BLENDMODE_COLOR_UPDATE_END); + GX_BP_LOAD_REG(blendModeReg); + gx->cmode0 = blendModeReg; + gx->bpSentNot = GX_FALSE; +} + +void GXSetAlphaUpdate(GXBool updateEnable) +{ + u32 blendModeReg = gx->cmode0; + GX_SET_REG(blendModeReg, updateEnable, GX_BP_BLENDMODE_ALPHA_UPDATE_ST, GX_BP_BLENDMODE_ALPHA_UPDATE_END); + GX_BP_LOAD_REG(blendModeReg); + gx->cmode0 = blendModeReg; + gx->bpSentNot = GX_FALSE; +} + +void GXSetZMode(GXBool compareEnable, GXCompare func, GXBool updateEnable) +{ + u32 zModeReg = gx->zmode; + GX_SET_REG(zModeReg, compareEnable, GX_BP_ZMODE_TEST_ENABLE_ST, GX_BP_ZMODE_TEST_ENABLE_END); + GX_SET_REG(zModeReg, func, GX_BP_ZMODE_COMPARE_ST, GX_BP_ZMODE_COMPARE_END); + GX_SET_REG(zModeReg, updateEnable, GX_BP_ZMODE_UPDATE_ENABLE_ST, GX_BP_ZMODE_UPDATE_ENABLE_END); + GX_BP_LOAD_REG(zModeReg); + gx->zmode = zModeReg; + gx->bpSentNot = GX_FALSE; +} + +void GXSetZCompLoc(GXBool beforeTex) +{ + GX_SET_REG(gx->peCtrl, beforeTex, GX_BP_ZCONTROL_BEFORE_TEX_ST, GX_BP_ZCONTROL_BEFORE_TEX_END); + GX_BP_LOAD_REG(gx->peCtrl); + gx->bpSentNot = GX_FALSE; +} + +void GXSetPixelFmt(GXPixelFmt pixelFmt, GXZFmt16 zFmt) +{ + GXBool isZ16; + static u32 p2f[8] + = { GX_PF_RGB8_Z24, GX_PF_RGBA6_Z24, GX_PF_RGB565_Z16, GX_PF_Z24, GX_PF_Y8, GX_PF_Y8, GX_PF_Y8, GX_PF_U8 }; + + const u32 zControlRegOld = gx->peCtrl; + + GX_SET_REG(gx->peCtrl, p2f[pixelFmt], GX_BP_ZCONTROL_PIXEL_FMT_ST, GX_BP_ZCONTROL_PIXEL_FMT_END); + GX_SET_REG(gx->peCtrl, zFmt, GX_BP_ZCONTROL_Z_FMT_ST, GX_BP_ZCONTROL_Z_FMT_END); + + if (zControlRegOld != gx->peCtrl) { + GX_BP_LOAD_REG(gx->peCtrl); + isZ16 = (pixelFmt == GX_PF_RGB565_Z16) ? GX_TRUE : GX_FALSE; + GX_SET_REG(gx->genMode, isZ16, GX_BP_GENMODE_MULTISAMPLE_ST, GX_BP_GENMODE_MULTISAMPLE_END); + gx->dirtyState |= GX_DIRTY_GEN_MODE; + } + + if (p2f[pixelFmt] == GX_PF_Y8) { + GX_SET_REG(gx->cmode1, pixelFmt - GX_PF_Y8, GX_BP_DSTALPHA_YUV_FMT_ST, GX_BP_DSTALPHA_YUV_FMT_END); + GX_SET_REG(gx->cmode1, GX_BP_REG_DSTALPHA, 0, 7); + GX_BP_LOAD_REG(gx->cmode1); + } + + gx->bpSentNot = FALSE; +} + +void GXSetDither(GXBool dither) +{ + u32 blendModeReg = gx->cmode0; + GX_SET_REG(blendModeReg, dither, GX_BP_BLENDMODE_DITHER_ST, GX_BP_BLENDMODE_DITHER_END); + GX_BP_LOAD_REG(blendModeReg); + gx->cmode0 = blendModeReg; + gx->bpSentNot = GX_FALSE; +} + +void GXSetDstAlpha(GXBool enable, u8 alpha) +{ + u32 dstAlpha = gx->cmode1; + GX_SET_REG(dstAlpha, alpha, GX_BP_DSTALPHA_ALPHA_ST, GX_BP_DSTALPHA_ALPHA_END); + GX_SET_REG(dstAlpha, enable, GX_BP_DSTALPHA_ENABLE_ST, GX_BP_DSTALPHA_ENABLE_END); + GX_BP_LOAD_REG(dstAlpha); + gx->cmode1 = dstAlpha; + gx->bpSentNot = GX_FALSE; +} + +void GXSetFieldMask(GXBool enableEven, GXBool enableOdd) +{ + u32 fieldMaskReg = 0; + GX_SET_REG(fieldMaskReg, enableOdd, GX_BP_FIELDMASK_ODD_ST, GX_BP_FIELDMASK_ODD_END); + GX_SET_REG(fieldMaskReg, enableEven, GX_BP_FIELDMASK_EVEN_ST, GX_BP_FIELDMASK_EVEN_END); + GX_SET_REG(fieldMaskReg, GX_BP_REG_FIELDMASK, 0, 7); + + GX_BP_LOAD_REG(fieldMaskReg); + gx->bpSentNot = GX_FALSE; +} + +void GXSetFieldMode(GXBool texLOD, GXBool adjustAR) +{ + GX_SET_REG(gx->lpSize, adjustAR, GX_BP_LINEPTWIDTH_ADJUST_ST, GX_BP_LINEPTWIDTH_ADJUST_END); + GX_BP_LOAD_REG(gx->lpSize); + + __GXFlushTextureState(); + GX_BP_LOAD_REG(GX_BP_REG_FIELDMODE << 24 | texLOD); + __GXFlushTextureState(); +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXSave.c b/src/static/GAEJ01_01/dolphin/gx/GXSave.c new file mode 100644 index 00000000..92ce2f03 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXSave.c @@ -0,0 +1,522 @@ +#if DEBUG + +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +static u8 *dlist; +static u32 dlistSize; +static u32 bytesRead; + +void __GXShadowIndexState(u32 idx_reg, u32 reg_data); + +static u8 __ReadMem(void *ptr, u32 sz) +{ + u8 *src; + u8 *dst; + u32 i; + + if (sz > dlistSize - bytesRead) { + return FALSE; + } + + src = dlist; + dst = ptr; + for (i = 0; i < sz; i++) { + *dst++ = *src++; + } + bytesRead += sz; + dlist += sz; + return TRUE; +} + +inline void DPF(...) +{ + u8 unused[4]; +} + +static void __SaveCPRegs(u8 reg, u8 vatIdx, u32 data) +{ + s32 idx; + + DPF("\tCP Stream Reg[0x%x] = 0x%x\n", reg, data); + switch (reg) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + case 5: + gx->vcdLo = data; + break; + case 6: + gx->vcdHi = data; + break; + case 7: + gx->vatA[vatIdx & 0xFF] = data; + break; + case 8: + gx->vatB[vatIdx & 0xFF] = data; + break; + case 9: + gx->vatC[vatIdx & 0xFF] = data; + break; + case 10: + idx = vatIdx - 0x15; + if ((idx >= 0) && (idx < 4)) { + gx->indexBase[idx] = data; + } + break; + case 11: + idx = vatIdx - 0x15; + if ((idx >= 0) && (idx < 4)) { + gx->indexStride[idx] = data; + } + break; + default: + if (__gxVerif->verifyLevel >= __gxvWarnLev[113]) { + (*__gxVerif->cb)(__gxvWarnLev[113], 113, __gxvWarnings[113]); + } + OSReport("[Invalid CP Stream Register Address 0x%x\n]", reg); + break; + } +} + +static void __ReconstVtxStatus(u8 vatIdx) { + u32 vat; + + if ((gx->vcdLo & (3 << 11)) >> 11) { + vat = gx->vatA[vatIdx]; + + if ((vat >> 9) & 1) { + gx->hasNrms = GX_FALSE; + gx->hasBiNrms = GX_TRUE; + } else { + gx->hasNrms = GX_TRUE; + gx->hasBiNrms = GX_FALSE; + } + } + +} + +static u32 vtxCompSize[5] = { 1, 1, 2, 2, 4 }; +static int clrCompSize[6] = { 2, 3, 4, 2, 3, 4 }; + +static u32 GetAttrSize(u8 vatIdx, u32 attrIdx) +{ + u32 vcd; + u32 vat; + u32 nc; + + switch (attrIdx) { + case 0: + return GET_REG_FIELD(gx->vcdLo, 1, 0) ? 1 : 0; + case 1: + return GET_REG_FIELD(gx->vcdLo, 1, 1) ? 1 : 0; + case 2: + return GET_REG_FIELD(gx->vcdLo, 1, 2) ? 1 : 0; + case 3: + return GET_REG_FIELD(gx->vcdLo, 1, 3) ? 1 : 0; + case 4: + return GET_REG_FIELD(gx->vcdLo, 1, 4) ? 1 : 0; + case 5: + return GET_REG_FIELD(gx->vcdLo, 1, 5) ? 1 : 0; + case 6: + return GET_REG_FIELD(gx->vcdLo, 1, 6) ? 1 : 0; + case 7: + return GET_REG_FIELD(gx->vcdLo, 1, 7) ? 1 : 0; + case 8: + return GET_REG_FIELD(gx->vcdLo, 1, 8) ? 1 : 0; + case 9: + vcd = gx->vcdLo; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 9)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return ((vat & 1) + 2) * vtxCompSize[(vat >> 1) & 7]; + } + break; + case 10: + vcd = gx->vcdLo; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 11)) { + case 0: + return 0; + case 2: + if (((vat >> 9) & 1) && (vat >> 31)) { + nc = 3; + } else { + nc = 1; + } + return nc; + case 3: + if (((vat >> 9) & 1) && (vat >> 31)) { + nc = 6; + } else { + nc = 2; + } + return nc; + case 1: + if ((vat >> 9) & 1) { + nc = 9; + } else { + nc = 3; + } + + return nc * vtxCompSize[(vat >> 10) & 7]; + } + break; + case 11: + switch (GET_REG_FIELD(gx->vcdLo, 2, 13)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + vat = gx->vatA[vatIdx]; + return clrCompSize[(vat >> 14) & 7]; + } + break; + case 12: + switch (GET_REG_FIELD(gx->vcdLo, 2, 15)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + vat = gx->vatA[vatIdx]; + return clrCompSize[(vat >> 18) & 7]; + } + break; + case 13: + vcd = gx->vcdHi; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 0)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return (((vat >> 21) & 1) + 1) * vtxCompSize[(vat >> 22) & 7]; + } + break; + case 14: + vcd = gx->vcdHi; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 2)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return (((vat >> 0) & 1) + 1) * vtxCompSize[(vat >> 1) & 7]; + } + break; + case 15: + vcd = gx->vcdHi; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 4)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return (((vat >> 9) & 1) + 1) * vtxCompSize[(vat >> 10) & 7]; + } + break; + case 16: + vcd = gx->vcdHi; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 6)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return (((vat >> 18) & 1) + 1) * vtxCompSize[(vat >> 19) & 7]; + } + break; + case 17: + vcd = gx->vcdHi; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 8)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return (((vat >> 27) & 1) + 1) * vtxCompSize[(vat >> 28) & 7]; + } + break; + case 18: + vcd = gx->vcdHi; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 10)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return (((vat >> 5) & 1) + 1) * vtxCompSize[(vat >> 6) & 7]; + } + break; + case 19: + vcd = gx->vcdHi; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 12)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return (((vat >> 14) & 1) + 1) * vtxCompSize[(vat >> 15) & 7]; + } + break; + case 20: + vcd = gx->vcdHi; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 14)) { + case 0: + return 0; + case 2: + return 1; + case 3: + return 2; + case 1: + return (((vat >> 23) & 1) + 1) * vtxCompSize[(vat >> 24) & 7]; + } + break; + } + return 0; +} + +static void __ParseVertexData(u8 vatIdx) +{ + u16 vcnt; + GXAttr attrIdx; + u32 vsize; + + if (__ReadMem(&vcnt, 2)) { + vsize = 0; + for (attrIdx = 0; attrIdx < 26; attrIdx++) { + if (attrIdx != 25) { + vsize += GetAttrSize(vatIdx, attrIdx); + } + } + vsize *= vcnt; + dlist += vsize; + bytesRead += vsize; + } +} + +void __GXShadowDispList(void *list, u32 nbytes) +{ + u8 cmd; + u8 cmdOp; + u8 vatIdx; + u32 reg32; + u32 d32; + u8 reg8; + u8 cpAddr; + u32 i; + u32 addr; + u32 cnt; + + if (__gxVerif->verifyLevel == GX_WARN_NONE) { + return; + } + + dlist = list; + dlistSize = nbytes; + bytesRead = 0; + DPF("Displaylist IN\n"); + while (dlistSize > bytesRead) { + if (!__ReadMem(&cmd, 1)) { + break; + } + cmdOp = (u32)GET_REG_FIELD((u32)cmd, 5, 3); + vatIdx = cmd & 7; + switch (cmdOp) { + case 0: + case 9: + break; + case 16: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + __ReconstVtxStatus(vatIdx); + __GXVerifyState(vatIdx); + __ParseVertexData(vatIdx); + break; + case 1: + if (__ReadMem(®8, 1) && __ReadMem(&d32, 4)) { + vatIdx = reg8 & 0xF; + cpAddr = (reg8 & 0xF0) >> 4; + __SaveCPRegs(cpAddr, vatIdx, d32); + } + break; + case 2: + if (__ReadMem(®32, 4)) { + cnt = GET_REG_FIELD(reg32, 4, 16) + 1; + addr = (u16)reg32; + DPF("\tXFReg = 0x%x, Cnt = %d\n", addr, cnt); + for (i = 0; i < cnt; i++) { + if (__ReadMem(&d32, 4)) { + DPF("\tXFData = 0x%x\n", d32); + VERIF_MTXLIGHT(addr, d32); + addr++; + } + } + } + break; + case 4: + case 5: + case 6: + case 7: + if (__ReadMem(®32, 4)) { + DPF("\tXF_INDEX_LOAD: = 0x%x\n", reg32); + __GXShadowIndexState(cmdOp, reg32); + } + break; + case 8: + // OSReport("GX DisplayList: Nested Display Lists\n"); + if (__gxVerif->verifyLevel >= __gxvWarnLev[114]) { + (*__gxVerif->cb)(__gxvWarnLev[114], 114, __gxvWarnings[114]); + } + return; + case 12: + case 13: + if (__ReadMem(®32, 4)) { + DPF("\tSU Bypass = 0x%x\n", reg32); + __gxVerif->rasRegs[(reg32 >> 24) & 0xFF] = reg32; + } + break; + default: + if (__gxVerif->verifyLevel >= __gxvWarnLev[113]) { + (*__gxVerif->cb)(__gxvWarnLev[113], 113, __gxvWarnings[113]); + } + OSReport("[Bad Display List Command: %d\n]", cmdOp); + break; + } + } + + DPF("Displaylist OUT\n"); +} + +void __GXShadowIndexState(u32 idx_reg, u32 reg_data) +{ + u32 * basePtr; + u32 * memAddr; + u32 cnt; + u32 stride; + u32 addr; + u32 data; + u32 index; + u32 i; + + i = idx_reg - 4; + basePtr = OSPhysicalToCached(gx->indexBase[i]); + stride = gx->indexStride[i]; + addr = reg_data & 0xFFF; + cnt = (reg_data >> 12) & 0xF; + index = reg_data >> 16; + memAddr = (u32 *)((u8 *)basePtr + (index * stride)); + cnt++; + + while (cnt-- != 0) { + data = *memAddr; + VERIF_MTXLIGHT(addr, data); + memAddr = (u32 *)((u8 *)memAddr + stride); + addr++; + } + + &data; // needed to match +} + +void __GXPrintShadowState(void) +{ + u32 i; + u32 j; + + OSReport("CP State:\n"); + OSReport("\tvcdLo = 0x%x\n", gx->vcdLo); + OSReport("\tvcdHi = 0x%x\n", gx->vcdHi); + OSReport("\thasBiNrms = 0x%x\n", gx->hasBiNrms); + for (i = 0; i < 8; i++) { + OSReport("\tVertex Format %d:\n", i); + OSReport("\t\tvatA = 0x%x\n", gx->vatA[i]); + OSReport("\t\tvatB = 0x%x\n", gx->vatB[i]); + OSReport("\t\tvatC = 0x%x\n", gx->vatC[i]); + } + OSReport("\n-------------------------------------\n"); + OSReport("XF Pos/Tex Matrix State:\n"); + for (i = 0; i < 256; i += 4) { + if (__gxVerif->xfMtxDirty[i]) { + OSReport("\tXF_MATRIX[%d] = ", i); + OSReport("%f, %f, %f, %f\n", *(f32 *)&__gxVerif->xfMtx[i], *(f32 *)&__gxVerif->xfMtx[i + 1], *(f32 *)&__gxVerif->xfMtx[i + 2], *(f32 *)&__gxVerif->xfMtx[i + 3]); + } + } + OSReport("\n-------------------------------------\n"); + OSReport("XF Normal Matrix State:\n"); + for (i = 0; i < 96; i += 3) { + if (__gxVerif->xfNrmDirty[i]) { + OSReport("\tXF_NRM_MTX[%d] = ", i); + OSReport("%f, %f, %f\n", *(f32 *)&__gxVerif->xfMtx[i], *(f32 *)&__gxVerif->xfMtx[i + 1], *(f32 *)&__gxVerif->xfMtx[i + 2]); + } + } + OSReport("\n-------------------------------------\n"); + OSReport("XF Light State:\n"); + for (i = 0; i < 128; i += 16) { + if (__gxVerif->xfLightDirty[i]) { + OSReport("\tXF_LIGHT[%d]:\n", i >> 4); + for (j = 0; j < 4; j++) { + OSReport("\t\tparam[%d] = 0x%x\n", j, __gxVerif->xfLight[i + j]); + } + for (j = 4; j < 16; j++) { + OSReport("\t\tparam[%d] = %Lg\n", j, *(f32 *)&__gxVerif->xfLight[i + j]); + } + } + } + OSReport("\n-------------------------------------\n"); + OSReport("XF Register State:\n"); + for (i = 0; i < 80; i++) { + if (__gxVerif->xfRegsDirty[i]) { + OSReport("\tXF_REG[0x%x] = 0x%x (%f)\n", i, __gxVerif->xfRegs[i], *(f32 *)&__gxVerif->xfRegs[i]); + } + } + OSReport("\n-------------------------------------\n"); + OSReport("Raster Registers State:\n"); + for (i = 0; i < 256; i++) { + OSReport("\tRAS_REG[0x%x] = 0x%x\n", i, __gxVerif->rasRegs[i]); + } + OSReport("\n-------------------------------------\n"); +} + +#endif diff --git a/src/static/GAEJ01_01/dolphin/gx/GXStubs.c b/src/static/GAEJ01_01/dolphin/gx/GXStubs.c new file mode 100644 index 00000000..4bd49d09 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXStubs.c @@ -0,0 +1,6 @@ +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +void __GXSetRange(float nearz, float fgSideX) +{ +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXTev.c b/src/static/GAEJ01_01/dolphin/gx/GXTev.c new file mode 100644 index 00000000..a625c9da --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXTev.c @@ -0,0 +1,379 @@ +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" + +static u32 TEVCOpTableST0[] = { + 0xC008F8AF, // modulate + 0xC008A89F, // decal + 0xC008AC8F, // blend + 0xC008FFF8, // replace + 0xC008FFFA, // passclr +}; + +static u32 TEVCOpTableST1[] = { + 0xC008F80F, // modulate + 0xC008089F, // decal + 0xC0080C8F, // blend + 0xC008FFF8, // replace + 0xC008FFF0, // passclr +}; + +static u32 TEVAOpTableST0[] = { + 0xC108F2F0, // modulate + 0xC108FFD0, // decal + 0xC108F2F0, // blend + 0xC108FFC0, // replace + 0xC108FFD0, // passclr +}; + +static u32 TEVAOpTableST1[] = { + 0xC108F070, // modulate + 0xC108FF80, // decal + 0xC108F070, // blend + 0xC108FFC0, // replace + 0xC108FF80, // passclr +}; + +void GXSetTevOp(GXTevStageID stage, GXTevMode mode) +{ + u32* color; + u32* alpha; + u32 tevReg; + + if (stage == GX_TEVSTAGE0) { + color = &TEVCOpTableST0[mode]; + alpha = &TEVAOpTableST0[mode]; + } else { + color = &TEVCOpTableST1[mode]; + alpha = &TEVAOpTableST1[mode]; + } + + tevReg = gx->tevc[stage]; + tevReg = (*color & ~0xFF000000) | (tevReg & 0xFF000000); + + GX_BP_LOAD_REG(tevReg); + + gx->tevc[stage] = tevReg; + + tevReg = gx->teva[stage]; + tevReg = (*alpha & ~0xFF00000F) | (tevReg & 0xFF00000F); + + GX_BP_LOAD_REG(tevReg); + + gx->teva[stage] = tevReg; + + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevColorIn(GXTevStageID stage, GXTevColorArg a, GXTevColorArg b, GXTevColorArg c, GXTevColorArg d) +{ + u32 tevReg; + + tevReg = gx->tevc[stage]; + + GX_SET_REG(tevReg, a, 16, 19); + GX_SET_REG(tevReg, b, 20, 23); + GX_SET_REG(tevReg, c, 24, 27); + GX_SET_REG(tevReg, d, 28, 31); + + GX_BP_LOAD_REG(tevReg); + + gx->tevc[stage] = tevReg; + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevAlphaIn(GXTevStageID stage, GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, GXTevAlphaArg d) +{ + u32 tevReg; + + tevReg = gx->teva[stage]; + + GX_SET_REG(tevReg, a, 16, 18); + GX_SET_REG(tevReg, b, 19, 21); + GX_SET_REG(tevReg, c, 22, 24); + GX_SET_REG(tevReg, d, 25, 27); + + GX_BP_LOAD_REG(tevReg); + + gx->teva[stage] = tevReg; + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevColorOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool doClamp, GXTevRegID outReg) +{ + u32 tevReg; + + tevReg = gx->tevc[stage]; + GX_SET_REG(tevReg, op & 1, 13, 13); + + if (op <= 1) { + GX_SET_REG(tevReg, scale, 10, 11); + GX_SET_REG(tevReg, bias, 14, 15); + } else { + GX_SET_REG(tevReg, (op >> 1) & 3, 10, 11); + GX_SET_REG(tevReg, 3, 14, 15); + } + + GX_SET_REG(tevReg, doClamp, 12, 12); + GX_SET_REG(tevReg, outReg, 8, 9); + + GX_BP_LOAD_REG(tevReg); + + gx->tevc[stage] = tevReg; + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevAlphaOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool doClamp, GXTevRegID outReg) +{ + u32 tevReg; + + tevReg = gx->teva[stage]; + GX_SET_REG(tevReg, op & 1, 13, 13); + + if (op <= 1) { + GX_SET_REG(tevReg, scale, 10, 11); + GX_SET_REG(tevReg, bias, 14, 15); + } else { + GX_SET_REG(tevReg, (op >> 1) & 3, 10, 11); + GX_SET_REG(tevReg, 3, 14, 15); + } + + GX_SET_REG(tevReg, doClamp, 12, 12); + GX_SET_REG(tevReg, outReg, 8, 9); + + GX_BP_LOAD_REG(tevReg); + + gx->teva[stage] = tevReg; + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevColor(GXTevRegID reg, GXColor color) +{ + u32 ra = 0; + u32 bg = 0; + + GX_SET_REG(ra, color.r, 21, 31); + GX_SET_REG(ra, color.a, 9, 19); + GX_SET_REG(bg, color.b, 21, 31); + GX_SET_REG(bg, color.g, 9, 19); + + GX_SET_REG(ra, 0xE0 + reg * 2, 0, 7); + GX_SET_REG(bg, 0xE1 + reg * 2, 0, 7); + + GX_BP_LOAD_REG(ra); + GX_BP_LOAD_REG(bg); + GX_BP_LOAD_REG(bg); + GX_BP_LOAD_REG(bg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevColorS10(GXTevRegID reg, GXColorS10 color) +{ + u32 ra, bg; + + ra = 0; + GX_SET_REG(ra, color.r & 0x7ff, 21, 31); + GX_SET_REG(ra, color.a & 0x7ff, 9, 19); + GX_SET_REG(ra, GX_BP_REG_TEVREG0LO + reg * 2, 0, 7); + + bg = 0; + GX_SET_REG(bg, color.b & 0x7ff, 21, 31); + GX_SET_REG(bg, color.g & 0x7ff, 9, 19); + GX_SET_REG(bg, GX_BP_REG_TEVREG0HI + reg * 2, 0, 7); + + GX_BP_LOAD_REG(ra); + + GX_BP_LOAD_REG(bg); + GX_BP_LOAD_REG(bg); + GX_BP_LOAD_REG(bg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevKColor(GXTevKColorID id, GXColor color) +{ + u32 ra; + u32 bg; + + ra = 0; + GX_SET_REG(ra, color.r, 24, 31); + GX_SET_REG(ra, color.a, 12, 19); + GX_SET_REG(ra, 8, 8, 11); + GX_SET_REG(ra, 0xE0 + id * 2, 0, 7); + + bg = 0; + GX_SET_REG(bg, color.b, 24, 31); + GX_SET_REG(bg, color.g, 12, 19); + GX_SET_REG(bg, 8, 8, 11); + GX_SET_REG(bg, 0xE1 + id * 2, 0, 7); + + GX_BP_LOAD_REG(ra); + GX_BP_LOAD_REG(bg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevKColorSel(GXTevStageID stage, GXTevKColorSel sel) +{ + u32* reg; + + reg = &gx->tevKsel[stage >> 1]; + + if (stage & 1) { + GX_SET_REG(*reg, sel, 13, 17); + } else { + GX_SET_REG(*reg, sel, 23, 27); + } + + GX_BP_LOAD_REG(*reg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevKAlphaSel(GXTevStageID stage, GXTevKAlphaSel sel) +{ + u32* reg; + + reg = &gx->tevKsel[stage >> 1]; + + if (stage & 1) { + GX_SET_REG(*reg, sel, 8, 12); + } else { + GX_SET_REG(*reg, sel, 18, 22); + } + + GX_BP_LOAD_REG(*reg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevSwapMode(GXTevStageID stage, GXTevSwapSel rasSel, GXTevSwapSel texSel) +{ + u32* reg = &gx->teva[stage]; + GX_SET_REG(*reg, rasSel, 30, 31); + GX_SET_REG(*reg, texSel, 28, 29); + + GX_BP_LOAD_REG(*reg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevSwapModeTable(GXTevSwapSel table, GXTevColorChan red, GXTevColorChan green, GXTevColorChan blue, GXTevColorChan alpha) +{ + u32* reg; + + reg = &gx->tevKsel[table << 1]; + GX_SET_REG(*reg, red, 30, 31); + GX_SET_REG(*reg, green, 28, 29); + + GX_BP_LOAD_REG(*reg); + + reg = &gx->tevKsel[(table << 1) + 1]; + GX_SET_REG(*reg, blue, 30, 31); + GX_SET_REG(*reg, alpha, 28, 29); + + GX_BP_LOAD_REG(*reg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1) +{ + u32 reg = 0xF3000000; + + GX_SET_REG(reg, ref0, 24, 31); + GX_SET_REG(reg, ref1, 16, 23); + GX_SET_REG(reg, comp0, 13, 15); + GX_SET_REG(reg, comp1, 10, 12); + GX_SET_REG(reg, op, 8, 9); + + GX_BP_LOAD_REG(reg); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetZTexture(GXZTexOp op, GXTexFmt format, u32 bias) +{ + u32 val1; + u32 val2; + u32 val3; + + val1 = 0; + GX_SET_REG(val1, bias, 8, 31); + GX_SET_REG(val1, 0xF4, 0, 7); + + val2 = 0; + switch (format) { + case GX_TF_Z8: + val3 = 0; + break; + case GX_TF_Z16: + val3 = 1; + break; + case GX_TF_Z24X8: + val3 = 2; + break; + default: + val3 = 2; + break; + } + + GX_SET_REG(val2, val3, 30, 31); + GX_SET_REG(val2, op, 28, 29); + GX_SET_REG(val2, 0xF5, 0, 7); + + GX_BP_LOAD_REG(val1); + + GX_BP_LOAD_REG(val2); + + gx->bpSentNot = GX_FALSE; +} + +void GXSetTevOrder(GXTevStageID stage, GXTexCoordID coord, GXTexMapID map, GXChannelID color) +{ + static int c2r[] = { 0, 1, 0, 1, 0, 1, 7, 5, 6 }; + + u32* reg; + u32 tempMap; + u32 tempCoord; + + reg = &gx->tref[stage / 2]; + gx->texmapId[stage] = map; + + tempMap = map & ~0x100; + tempMap = (tempMap >= GX_MAX_TEXMAP) ? GX_TEXMAP0 : tempMap; + + if (coord >= GX_MAX_TEXCOORD) { + tempCoord = GX_TEXCOORD0; + gx->tevTcEnab = gx->tevTcEnab & ~(1 << stage); + } else { + tempCoord = coord; + gx->tevTcEnab = gx->tevTcEnab | (1 << stage); + } + + if (stage & 1) { + GX_SET_REG(*reg, tempMap, 17, 19); + GX_SET_REG(*reg, tempCoord, 14, 16); + GX_SET_REG(*reg, (color == GX_COLOR_NULL ? 7 : c2r[color]), 10, 12); + GX_SET_REG(*reg, ((map != GX_TEXMAP_NULL) && !(map & 0x100)), 13, 13); + + } else { + GX_SET_REG(*reg, tempMap, 29, 31); + GX_SET_REG(*reg, tempCoord, 26, 28); + GX_SET_REG(*reg, (color == GX_COLOR_NULL ? 7 : c2r[color]), 22, 24); + GX_SET_REG(*reg, ((map != GX_TEXMAP_NULL) && !(map & 0x100)), 25, 25); + } + + GX_BP_LOAD_REG(*reg); + + gx->bpSentNot = GX_FALSE; + gx->dirtyState |= 1; +} + +void GXSetNumTevStages(u8 count) +{ + GX_SET_REG(gx->genMode, count - 1, 18, 21); + + gx->dirtyState |= 0x4; +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXTexture.c b/src/static/GAEJ01_01/dolphin/gx/GXTexture.c new file mode 100644 index 00000000..a5147838 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXTexture.c @@ -0,0 +1,613 @@ +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +u8 GXTexMode0Ids[8] = { 0x80, 0x81, 0x82, 0x83, 0xA0, 0xA1, 0xA2, 0xA3 }; +u8 GXTexMode1Ids[8] = { 0x84, 0x85, 0x86, 0x87, 0xA4, 0xA5, 0xA6, 0xA7 }; +u8 GXTexImage0Ids[8] = { 0x88, 0x89, 0x8a, 0x8b, 0xA8, 0xA9, 0xAa, 0xAb }; +u8 GXTexImage1Ids[8] = { 0x8c, 0x8d, 0x8e, 0x8f, 0xAc, 0xAd, 0xAe, 0xAf }; +u8 GXTexImage2Ids[8] = { 0x90, 0x91, 0x92, 0x93, 0xB0, 0xB1, 0xB2, 0xB3 }; +u8 GXTexImage3Ids[8] = { 0x94, 0x95, 0x96, 0x97, 0xB4, 0xB5, 0xB6, 0xB7 }; +u8 GXTexTlutIds[8] = { 0x98, 0x99, 0x9a, 0x9b, 0xB8, 0xB9, 0xBa, 0xBb }; + +u8 GX2HWFiltConv[6] = { 0x00, 0x04, 0x01, 0x05, 0x02, 0x06 }; + +#define GET_TILE_COUNT(a, b) (((a) + (1 << (b)) - 1) >> (b)) + +inline void __GXGetTexTileShift(GXTexFmt format, u32* widthTiles, u32* heightTiles) +{ + switch (format) { + case GX_TF_I4: + case GX_TF_C4: + case GX_TF_CMPR: + case GX_CTF_R4: + case GX_CTF_Z4: + *widthTiles = 3; + *heightTiles = 3; + break; + + case GX_TF_I8: + case GX_TF_IA4: + case GX_TF_C8: + case GX_TF_Z8: + case GX_CTF_RA4: + case GX_CTF_A8: + case GX_CTF_R8: + case GX_CTF_G8: + case GX_CTF_B8: + case GX_CTF_Z8M: + case GX_CTF_Z8L: + *widthTiles = 3; + *heightTiles = 2; + break; + + case GX_TF_IA8: + case GX_TF_RGB565: + case GX_TF_RGB5A3: + case GX_TF_RGBA8: + case GX_TF_C14X2: + case GX_TF_Z16: + case GX_TF_Z24X8: + case GX_CTF_RA8: + case GX_CTF_RG8: + case GX_CTF_GB8: + case GX_CTF_Z16L: + *widthTiles = 2; + *heightTiles = 2; + break; + + default: + *heightTiles = 0; + *widthTiles = 0; + break; + } +} + +u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool mipmap, u8 max_lod) +{ + u32 widthTiles, heightTiles, tileSize, bufferSize, numX, numY, i; + + __GXGetTexTileShift(format, &widthTiles, &heightTiles); + + if (format == GX_TF_RGBA8 || format == GX_TF_Z24X8) { + tileSize = 0x40; + } else { + tileSize = 0x20; + } + + if (mipmap == GX_TRUE) { + + bufferSize = 0; + + for (i = 0; i < max_lod; i++) { + numX = GET_TILE_COUNT(width, widthTiles); + numY = GET_TILE_COUNT(height, heightTiles); + + bufferSize += numX * numY * tileSize; + if (width == 1 && height == 1) { + break; + } + + width = (width > 1) ? (width >> 1) : 1; + height = (height > 1) ? (height >> 1) : 1; + } + + } else { + numX = GET_TILE_COUNT(width, widthTiles); + numY = GET_TILE_COUNT(height, heightTiles); + bufferSize = numX * numY * tileSize; + } + + return bufferSize; +} + +void __GetImageTileCount(GXTexFmt format, u16 width, u16 height, u32* a, u32* b, u32* c) +{ + u32 widthTiles, heightTiles; + + __GXGetTexTileShift(format, &widthTiles, &heightTiles); + + if (width <= 0) { + width = 1; + } + + if (height <= 0) { + height = 1; + } + + *a = GET_TILE_COUNT(width, widthTiles); + *b = GET_TILE_COUNT(height, heightTiles); + *c = (format == GX_TF_RGBA8 || format == GX_TF_Z24X8) ? 2 : 1; +} + +void GXInitTexObj(GXTexObj* obj, void* imagePtr, u16 width, u16 height, GXTexFmt format, GXTexWrapMode sWrap, GXTexWrapMode tWrap, + GXBool useMIPmap) +{ + u32 imageBase; + u16 a, b; + u32 c, d; + + GXTexObjPriv* internal = (GXTexObjPriv*)obj; + memset(internal, 0, sizeof(*internal)); + + GX_SET_REG(internal->mode0, sWrap, 30, 31); + GX_SET_REG(internal->mode0, tWrap, 28, 29); + GX_SET_REG(internal->mode0, GX_TRUE, 27, 27); + + if (useMIPmap) { + u32 maxDimSize; + internal->flags |= 1; + if (format == 8 || format == 9 || format == 10) { + GX_SET_REG(internal->mode0, 5, 24, 26); + } else { + GX_SET_REG(internal->mode0, 6, 24, 26); + } + + maxDimSize = width > height ? 31 - __cntlzw(width) : 31 - __cntlzw(height); + + GX_SET_REG(internal->mode1, (maxDimSize) * 16.f, 16, 23); + } else { + GX_SET_REG(internal->mode0, 4, 24, 26); + } + + internal->format = format; + GX_SET_REG(internal->image0, width - 1, 22, 31); + GX_SET_REG(internal->image0, height - 1, 12, 21); + + GX_SET_REG(internal->image0, format & 0xf, 8, 11); + imageBase = (u32)imagePtr >> 5; + GX_SET_REG(internal->image3, imageBase, 11, 31); + + switch (format & 0xf) { + case 0: + case 8: + internal->loadFormat = 1; + a = 3; + b = 3; + break; + case 1: + case 2: + case 9: + internal->loadFormat = 2; + a = 3; + b = 2; + break; + case 3: + case 4: + case 5: + case 10: + internal->loadFormat = 2; + a = 2; + b = 2; + break; + case 6: + internal->loadFormat = 3; + a = 2; + b = 2; + break; + case 0xe: + internal->loadFormat = 0; + a = 3; + b = 3; + break; + default: + internal->loadFormat = 2; + a = 2; + b = 2; + break; + } + + internal->loadCount = (GET_TILE_COUNT(width, a) * GET_TILE_COUNT(height, b)) & 0x7fff; + + internal->flags |= 2; +} + +void GXInitTexObjCI(GXTexObj* obj, void* imagePtr, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode sWrap, GXTexWrapMode tWrap, + GXBool useMIPmap, u32 tlutName) +{ + GXTexObjPriv* internal = (GXTexObjPriv*)obj; + + GXInitTexObj(obj, imagePtr, width, height, format, sWrap, tWrap, useMIPmap); + + internal->flags &= ~2; + internal->tlutName = tlutName; +} + +void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilter, GXTexFilter maxFilter, f32 minLOD, f32 maxLOD, f32 lodBias, GXBool doBiasClamp, + GXBool doEdgeLOD, GXAnisotropy maxAniso) +{ + GXTexObjPriv* internal = (GXTexObjPriv*)obj; + u8 reg1, reg2; + if (lodBias < -4.0f) { + lodBias = -4.0f; + } else if (lodBias >= 4.0f) { + lodBias = 3.99f; + } + + GX_SET_REG(internal->mode0, lodBias * 32.0f, 15, 22); + GX_SET_REG(internal->mode0, maxFilter == 1 ? 1 : 0, 27, 27); + GX_SET_REG(internal->mode0, GX2HWFiltConv[minFilter], 24, 26); + GX_SET_REG(internal->mode0, doEdgeLOD ? 0 : 1, 23, 23); + GX_SET_REG(internal->mode0, 0, 14, 14); + GX_SET_REG(internal->mode0, 0, 13, 13); + GX_SET_REG(internal->mode0, maxAniso, 11, 12); + GX_SET_REG(internal->mode0, doBiasClamp, 10, 10); + + if (minLOD < 0.0f) { + minLOD = 0.0f; + } else if (minLOD > 10.0f) { + minLOD = 10.0f; + } + reg1 = minLOD * 16.0f; + + if (maxLOD < 0.0f) { + maxLOD = 0.0f; + } else if (maxLOD > 10.0f) { + maxLOD = 10.0f; + } + reg2 = maxLOD * 16.0f; + + GX_SET_REG(internal->mode1, reg1, 24, 31); + GX_SET_REG(internal->mode1, reg2, 16, 23); +} + +GXTexFmt GXGetTexObjFmt(const GXTexObj* obj) +{ + GXTexObjPriv* pObj = (GXTexObjPriv*)obj; + return pObj->format; +} + +GXBool GXGetTexObjMipMap(const GXTexObj* obj) +{ + GXTexObjPriv* internal = (GXTexObjPriv*)obj; + return (internal->flags & 1) == 1; +} + +void GXLoadTexObjPreLoaded(GXTexObj* obj, GXTexRegion* region, GXTexMapID map) +{ + u8 stackManipulation[0x18]; + + GXTexObjPriv* internalObj = (GXTexObjPriv*)obj; + GXTexRegionPriv* internalRegion = (GXTexRegionPriv*)region; + + GX_SET_REG(internalObj->mode0, GXTexMode0Ids[map], 0, 7); + GX_SET_REG(internalObj->mode1, GXTexMode1Ids[map], 0, 7); + GX_SET_REG(internalObj->image0, GXTexImage0Ids[map], 0, 7); + + GX_SET_REG(internalRegion->unk0, GXTexImage1Ids[map], 0, 7); + GX_SET_REG(internalRegion->unk4, GXTexImage2Ids[map], 0, 7); + + GX_SET_REG(internalObj->image3, GXTexImage3Ids[map], 0, 7); + + GX_BP_LOAD_REG(internalObj->mode0); + GX_BP_LOAD_REG(internalObj->mode1); + GX_BP_LOAD_REG(internalObj->image0); + GX_BP_LOAD_REG(internalRegion->unk0); + GX_BP_LOAD_REG(internalRegion->unk4); + GX_BP_LOAD_REG(internalObj->image3); + + if ((internalObj->flags & 2) == 0) { + GXTlutObjPriv* tlut = (GXTlutObjPriv*)gx->tlutRegionCallback(internalObj->tlutName); + GX_SET_REG(tlut->unk4, GXTexTlutIds[map], 0, 7); + + GX_BP_LOAD_REG(tlut->unk4); + } + + gx->tImage0[map] = internalObj->image0; + gx->tMode0[map] = internalObj->mode0; + + gx->dirtyState |= GX_DIRTY_SU_TEX; + gx->bpSentNot = GX_FALSE; +} + +void GXLoadTexObj(GXTexObj* obj, GXTexMapID map) +{ + GXTexRegion* ret = (GXTexRegion*)gx->texRegionCallback(obj, map); + + GXLoadTexObjPreLoaded(obj, ret, map); +} + +void GXInitTlutObj(GXTlutObj* obj, void* table, GXTlutFmt format, u16 numEntries) +{ + GXTlutObjPriv* internal = (GXTlutObjPriv*)obj; + + internal->unk0 = 0; + + GX_SET_REG(internal->unk0, format, 20, 21); + GX_SET_REG(internal->unk4, (u32)table >> 5, 11, 31); + GX_SET_REG(internal->unk4, 100, 0, 7); + + internal->numEntries = numEntries; +} + +void GXLoadTlut(GXTlutObj* obj, u32 tlutName) +{ + GXTlutObjPriv* internal = (GXTlutObjPriv*)obj; + GXTlutRegionPriv* ret = (GXTlutRegionPriv*)gx->tlutRegionCallback(tlutName); + u32 reg; + + __GXFlushTextureState(); + + GX_BP_LOAD_REG(internal->unk4); + GX_BP_LOAD_REG(ret->unk0); + + __GXFlushTextureState(); + + reg = ret->unk0; + GX_SET_REG(internal->unk0, reg, 22, 31); + + ret->tlutObj = *internal; +} + +void GXInitTexCacheRegion(GXTexRegion* region, GXBool is32bMIPmap, u32 memEven, GXTexCacheSize sizeEven, u32 memOdd, GXTexCacheSize sizeOdd) +{ + GXTexRegionPriv* internal = (GXTexRegionPriv*)region; + + u32 reg; + switch (sizeEven) { + case 0: + reg = 3; + break; + case 1: + reg = 4; + break; + case 2: + reg = 5; + break; + } + + internal->unk0 = 0; + + GX_SET_REG(internal->unk0, memEven >> 5, 17, 31); + GX_SET_REG(internal->unk0, reg, 14, 16); + GX_SET_REG(internal->unk0, reg, 11, 13); + GX_SET_REG(internal->unk0, 0, 10, 10); + + switch (sizeOdd) { + case 0: + reg = 3; + break; + case 1: + reg = 4; + break; + case 2: + reg = 5; + break; + case 3: + reg = 0; + break; + } + + internal->unk4 = 0; + GX_SET_REG(internal->unk4, memOdd >> 5, 17, 31); + GX_SET_REG(internal->unk4, reg, 14, 16); + GX_SET_REG(internal->unk4, reg, 11, 13); + + internal->unkC = is32bMIPmap; + internal->unkD = 1; +} + +void GXInitTlutRegion(GXTlutRegion* region, u32 memAddr, GXTlutSize tlutSize) +{ + GXTlutRegionPriv* internal = (GXTlutRegionPriv*)region; + + internal->unk0 = 0; + GX_SET_REG(internal->unk0, (memAddr - 0x80000) >> 9, 22, 31); + GX_SET_REG(internal->unk0, tlutSize, 11, 21); + GX_SET_REG(internal->unk0, 0x65, 0, 7); +} + +void GXInvalidateTexAll(void) +{ + __GXFlushTextureState(); + GX_BP_LOAD_REG(0x66001000); + GX_BP_LOAD_REG(0x66001100); + __GXFlushTextureState(); +} + +GXTexRegionCallback GXSetTexRegionCallback(GXTexRegionCallback func) +{ + GXTexRegionCallback oldFunc = gx->texRegionCallback; + + gx->texRegionCallback = func; + + return oldFunc; +} + +GXTlutRegionCallback GXSetTlutRegionCallback(GXTlutRegionCallback func) +{ + GXTlutRegionCallback oldFunc = gx->tlutRegionCallback; + + gx->tlutRegionCallback = func; + + return oldFunc; +} + +void GXSetTexCoordScaleManually(GXTexCoordID coord, GXBool enable, u16 ss, u16 ts) +{ + gx->tcsManEnab = (gx->tcsManEnab & ~(1 << coord)) | (enable << coord); + + if (enable) { + GX_SET_REG(gx->suTs0[coord], (u16)(ss - 1), 16, 31); + GX_SET_REG(gx->suTs1[coord], (u16)(ts - 1), 16, 31); + + GX_BP_LOAD_REG(gx->suTs0[coord]); + GX_BP_LOAD_REG(gx->suTs1[coord]); + gx->bpSentNot = GX_FALSE; + } +} + +void GXSetTexCoordBias(GXTexCoordID coord, GXBool s_enable, GXBool t_enable) +{ + GX_SET_REG(gx->suTs0[coord], s_enable, 15, 15); + GX_SET_REG(gx->suTs1[coord], t_enable, 15, 15); + + if (gx->tcsManEnab & (1 << coord)) { + GX_BP_LOAD_REG(gx->suTs0[coord]); + GX_BP_LOAD_REG(gx->suTs1[coord]); + gx->bpSentNot = GX_FALSE; + } +} + +void __SetSURegs(u32 texImgIndex, u32 setUpRegIndex) +{ + u16 a1, a2; + GXBool b, c; + + a1 = GX_GET_REG(gx->tImage0[texImgIndex], 22, 31); + // a2 = GX_GET_REG(gx->tImage0[texImgIndex], 12, 21); + a2 = (gx->tImage0[texImgIndex] & (0x3ff << 10)) >> 10; + + GX_SET_REG(gx->suTs0[setUpRegIndex], a1, 16, 31); + GX_SET_REG(gx->suTs1[setUpRegIndex], a2, 16, 31); + + b = GX_GET_REG(gx->tMode0[texImgIndex], 30, 31) == 1; + c = GX_GET_REG(gx->tMode0[texImgIndex], 28, 29) == 1; + + GX_SET_REG(gx->suTs0[setUpRegIndex], b, 15, 15); + GX_SET_REG(gx->suTs1[setUpRegIndex], c, 15, 15); + + GX_BP_LOAD_REG(gx->suTs0[setUpRegIndex]); + GX_BP_LOAD_REG(gx->suTs1[setUpRegIndex]); + + gx->bpSentNot = GX_FALSE; +} + +#pragma dont_inline on +void __GXSetSUTexRegs(void) +{ + u32 i; + u32 b; + u32 a; + u32 c; + u32 d; + u32 stackFiller; + if (gx->tcsManEnab != 0xff) { + a = GX_GET_REG(gx->genMode, 18, 21) + 1; + b = GX_GET_REG(gx->genMode, 13, 15); + for (i = 0; i < b; i++) { + switch (i) { + case 0: + c = GX_GET_REG(gx->iref, 29, 31); + d = GX_GET_REG(gx->iref, 26, 28); + break; + case 1: + c = GX_GET_REG(gx->iref, 23, 25); + d = GX_GET_REG(gx->iref, 20, 22); + break; + case 2: + c = GX_GET_REG(gx->iref, 17, 19); + d = GX_GET_REG(gx->iref, 14, 16); + break; + case 3: + c = GX_GET_REG(gx->iref, 11, 13); + d = GX_GET_REG(gx->iref, 8, 10); + break; + } + + if (!(gx->tcsManEnab & (1 << d))) { + __SetSURegs(c, d); + } + } + + for (i = 0; i < a; i++) { + u32* g = &gx->tref[i / 2]; + + c = gx->texmapId[i] & ~0x100; + + if (i & 1) { + d = GX_GET_REG(*g, 14, 16); + } else { + d = GX_GET_REG(*g, 26, 28); + } + + if (c != 0xff && !(gx->tcsManEnab & (1 << d)) && gx->tevTcEnab & (1 << i)) { + __SetSURegs(c, d); + } + } + } +} +#pragma dont_inline reset + +void __GXSetTmemConfig(u32 config) +{ + switch (config) { + case 2: + GX_BP_LOAD_REG(0x8c0d8000); + GX_BP_LOAD_REG(0x900dc000); + + GX_BP_LOAD_REG(0x8d0d8800); + GX_BP_LOAD_REG(0x910dc800); + + GX_BP_LOAD_REG(0x8e0d9000); + GX_BP_LOAD_REG(0x920dd000); + + GX_BP_LOAD_REG(0x8f0d9800); + GX_BP_LOAD_REG(0x930dd800); + + GX_BP_LOAD_REG(0xac0da000); + GX_BP_LOAD_REG(0xb00dc400); + + GX_BP_LOAD_REG(0xad0da800); + GX_BP_LOAD_REG(0xb10dcc00); + + GX_BP_LOAD_REG(0xae0db000); + GX_BP_LOAD_REG(0xb20dd400); + + GX_BP_LOAD_REG(0xaf0db800); + GX_BP_LOAD_REG(0xb30ddc00); + break; + case 1: + GX_BP_LOAD_REG(0x8c0d8000); + GX_BP_LOAD_REG(0x900dc000); + + GX_BP_LOAD_REG(0x8d0d8800); + GX_BP_LOAD_REG(0x910dc800); + + GX_BP_LOAD_REG(0x8e0d9000); + GX_BP_LOAD_REG(0x920dd000); + + GX_BP_LOAD_REG(0x8f0d9800); + GX_BP_LOAD_REG(0x930dd800); + + GX_BP_LOAD_REG(0xac0da000); + GX_BP_LOAD_REG(0xb00de000); + + GX_BP_LOAD_REG(0xad0da800); + GX_BP_LOAD_REG(0xb10de800); + + GX_BP_LOAD_REG(0xae0db000); + GX_BP_LOAD_REG(0xb20df000); + + GX_BP_LOAD_REG(0xaf0db800); + GX_BP_LOAD_REG(0xb30df800); + + break; + case 0: + default: + GX_BP_LOAD_REG(0x8c0d8000); + GX_BP_LOAD_REG(0x900dc000); + + GX_BP_LOAD_REG(0x8d0d8400); + GX_BP_LOAD_REG(0x910dc400); + + GX_BP_LOAD_REG(0x8e0d8800); + GX_BP_LOAD_REG(0x920dc800); + + GX_BP_LOAD_REG(0x8f0d8c00); + GX_BP_LOAD_REG(0x930dcc00); + + GX_BP_LOAD_REG(0xac0d9000); + GX_BP_LOAD_REG(0xb00dd000); + + GX_BP_LOAD_REG(0xad0d9400); + GX_BP_LOAD_REG(0xb10dd400); + + GX_BP_LOAD_REG(0xae0d9800); + GX_BP_LOAD_REG(0xb20dd800); + + GX_BP_LOAD_REG(0xaf0d9c00); + GX_BP_LOAD_REG(0xb30ddc00); + + break; + } +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXTransform.c b/src/static/GAEJ01_01/dolphin/gx/GXTransform.c new file mode 100644 index 00000000..e32c305e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXTransform.c @@ -0,0 +1,289 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" + +static void WriteProjPS(const register f32 src[6], register volatile void* dst) +{ + register f32 ps_0, ps_1, ps_2; + +#ifdef __MWERKS__ // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + psq_l ps_1, 8(src), 0, 0 + psq_l ps_2, 16(src), 0, 0 + psq_st ps_0, 0(dst), 0, 0 + psq_st ps_1, 0(dst), 0, 0 + psq_st ps_2, 0(dst), 0, 0 + } +#endif // clang-format on +} + +static void Copy6Floats(const register f32 src[6], register f32 dst[6]) +{ + register f32 ps_0, ps_1, ps_2; + +#ifdef __MWERKS__ // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + psq_l ps_1, 8(src), 0, 0 + psq_l ps_2, 16(src), 0, 0 + psq_st ps_0, 0(dst), 0, 0 + psq_st ps_1, 8(dst), 0, 0 + psq_st ps_2, 16(dst), 0, 0 + } +#endif // clang-format on +} + +void __GXSetProjection(void) +{ + GX_XF_LOAD_REGS(6, GX_XF_REG_PROJECTIONA); + WriteProjPS(gx->projMtx, (volatile void*)GXFIFO_ADDR); + GX_WRITE_U32(gx->projType); +} + +void GXSetProjection(Mtx44 proj, GXProjectionType type) +{ + gx->projType = type; + + gx->projMtx[0] = proj[0][0]; + gx->projMtx[2] = proj[1][1]; + gx->projMtx[4] = proj[2][2]; + gx->projMtx[5] = proj[2][3]; + + if (type == GX_ORTHOGRAPHIC) { + gx->projMtx[1] = proj[0][3]; + gx->projMtx[3] = proj[1][3]; + } else { + gx->projMtx[1] = proj[0][2]; + gx->projMtx[3] = proj[1][2]; + } + + __GXSetProjection(); + + gx->bpSentNot = GX_TRUE; +} + +void GXSetProjectionv(const f32* proj) +{ + gx->projType = proj[0] == 0.0f ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC; + Copy6Floats(&proj[1], gx->projMtx); + + __GXSetProjection(); + gx->bpSentNot = GX_TRUE; +} + +void WriteMTXPS4x3(register volatile void* dst, register const Mtx34 src) +{ + register f32 ps_0, ps_1, ps_2, ps_3, ps_4, ps_5; + +#ifdef __MWERKS__ // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + psq_l ps_1, 8(src), 0, 0 + psq_l ps_2, 16(src), 0, 0 + psq_l ps_3, 24(src), 0, 0 + psq_l ps_4, 32(src), 0, 0 + psq_l ps_5, 40(src), 0, 0 + + psq_st ps_0, 0(dst), 0, 0 + psq_st ps_1, 0(dst), 0, 0 + psq_st ps_2, 0(dst), 0, 0 + psq_st ps_3, 0(dst), 0, 0 + psq_st ps_4, 0(dst), 0, 0 + psq_st ps_5, 0(dst), 0, 0 + } +#endif // clang-format on +} + +void WriteMTXPS3x3(register volatile void* dst, register const Mtx34 src) +{ + register f32 ps_0, ps_1, ps_2, ps_3, ps_4, ps_5; + +#ifdef __MWERKS__ // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + lfs ps_1, 8(src) + psq_l ps_2, 16(src), 0, 0 + lfs ps_3, 24(src) + psq_l ps_4, 32(src), 0, 0 + lfs ps_5, 40(src) + + psq_st ps_0, 0(dst), 0, 0 + stfs ps_1, 0(dst) + psq_st ps_2, 0(dst), 0, 0 + stfs ps_3, 0(dst) + psq_st ps_4, 0(dst), 0, 0 + stfs ps_5, 0(dst) + } +#endif // clang-format on +} + +void WriteMTXPS4x2(register volatile void* dst, register const Mtx34 src) +{ + register f32 ps_0, ps_1, ps_2, ps_3; + +#ifdef __MWERKS__ // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + psq_l ps_1, 8(src), 0, 0 + psq_l ps_2, 16(src), 0, 0 + psq_l ps_3, 24(src), 0, 0 + + psq_st ps_0, 0(dst), 0, 0 + psq_st ps_1, 0(dst), 0, 0 + psq_st ps_2, 0(dst), 0, 0 + psq_st ps_3, 0(dst), 0, 0 + } +#endif // clang-format on +} + +void GXLoadPosMtxImm(Mtx34 mtx, u32 id) +{ + GX_XF_LOAD_REGS(4 * 3 - 1, id * 4 + GX_XF_MEM_POSMTX); + WriteMTXPS4x3(&GXWGFifo, mtx); +} + +void GXLoadNrmMtxImm(Mtx34 mtx, u32 id) +{ + GX_XF_LOAD_REGS(3 * 3 - 1, id * 3 + GX_XF_MEM_NRMMTX); + WriteMTXPS3x3(&GXWGFifo, mtx); +} + +void GXSetCurrentMtx(u32 id) +{ + GX_SET_REG(gx->matIdxA, id, GX_XF_MTXIDX0_GEOM_ST, GX_XF_MTXIDX0_GEOM_END); + __GXSetMatrixIndex(GX_VA_PNMTXIDX); +} + +void GXLoadTexMtxImm(Mtx34 mtx, u32 id, GXTexMtxType type) +{ + u32 addr; + u32 num; + u32 reg; + + // Matrix address in XF memory + addr = id >= GX_PTTEXMTX0 ? (id - GX_PTTEXMTX0) * 4 + GX_XF_MEM_DUALTEXMTX : id * 4 + (u64)GX_XF_MEM_POSMTX; + + // Number of elements in matrix + num = type == GX_MTX2x4 ? (u64)(2 * 4) : 3 * 4; + + reg = addr | (num - 1) << 16; + + GX_XF_LOAD_REG_HDR(reg); + + if (type == GX_MTX3x4) { + WriteMTXPS4x3(&GXWGFifo, mtx); + } else { + WriteMTXPS4x2(&GXWGFifo, mtx); + } +} + +void __GXSetViewport(void) +{ + f32 a, b, c, d, e, f; + f32 near, far; + + a = gx->vpWd / 2.0f; + b = -gx->vpHt / 2.0f; + d = gx->vpLeft + (gx->vpWd / 2.0f) + 342.0f; + e = gx->vpTop + (gx->vpHt / 2.0f) + 342.0f; + + near = gx->vpNearz * gx->zScale; + far = gx->vpFarz * gx->zScale; + + c = far - near; + f = far + gx->zOffset; + + GX_XF_LOAD_REGS(5, GX_XF_REG_SCALEX); + GX_WRITE_F32(a); + GX_WRITE_F32(b); + GX_WRITE_F32(c); + GX_WRITE_F32(d); + GX_WRITE_F32(e); + GX_WRITE_F32(f); +} + +void GXSetViewport(f32 left, f32 top, f32 width, f32 height, f32 nearZ, f32 farZ) +{ + gx->vpLeft = left; + gx->vpTop = top; + gx->vpWd = width; + gx->vpHt = height; + gx->vpNearz = nearZ; + gx->vpFarz = farZ; + __GXSetViewport(); + gx->bpSentNot = GX_TRUE; +} + +void GXSetScissor(u32 left, u32 top, u32 width, u32 height) +{ + u32 y1, x1, y2, x2; + u32 reg; + + y1 = top + 342; + x1 = left + 342; + + GX_SET_REG(gx->suScis0, y1, GX_BP_SCISSORTL_TOP_ST, GX_BP_SCISSORTL_TOP_END); + GX_SET_REG(gx->suScis0, x1, GX_BP_SCISSORTL_LEFT_ST, GX_BP_SCISSORTL_LEFT_END); + + y2 = y1 + height - 1; + x2 = x1 + width - 1; + + GX_SET_REG(gx->suScis1, y2, GX_BP_SCISSORBR_BOT_ST, GX_BP_SCISSORBR_BOT_END); + GX_SET_REG(gx->suScis1, x2, GX_BP_SCISSORBR_RIGHT_ST, GX_BP_SCISSORBR_RIGHT_END); + + GX_BP_LOAD_REG(gx->suScis0); + GX_BP_LOAD_REG(gx->suScis1); + gx->bpSentNot = FALSE; +} + +void GXGetScissor(u32* left, u32* top, u32* width, u32* height) +{ + u32 y1 = (gx->suScis0 & 0x0007FF) >> 0; + u32 x1 = (gx->suScis0 & 0x7FF000) >> 12; + u32 y2 = (gx->suScis1 & 0x0007FF) >> 0; + u32 x2 = (gx->suScis1 & 0x7FF000) >> 12; + + *left = x1 - 0x156; + *top = y1 - 0x156; + *width = (x2 - x1) + 1; + *height = (y2 - y1) + 1; +} + +void GXSetScissorBoxOffset(s32 x, s32 y) +{ + u32 cmd = 0; + u32 x1; + u32 y1; + + x1 = (u32)(x + 342) / 2; + y1 = (u32)(y + 342) / 2; + GX_SET_REG(cmd, x1, GX_BP_SCISSOROFS_OX_ST, GX_BP_SCISSOROFS_OX_END); + GX_SET_REG(cmd, y1, GX_BP_SCISSOROFS_OY_ST, GX_BP_SCISSOROFS_OY_END); + + GX_SET_REG(cmd, GX_BP_REG_SCISSOROFFSET, 0, 7); + + GX_BP_LOAD_REG(cmd); + gx->bpSentNot = GX_FALSE; +} + +void GXSetClipMode(GXClipMode mode) +{ + GX_XF_LOAD_REG(GX_XF_REG_CLIPDISABLE, mode); + gx->bpSentNot = GX_TRUE; +} + +void __GXSetMatrixIndex(GXAttr index) +{ + // Tex4 and after is stored in XF MatrixIndex1 + if (index < GX_VA_TEX4MTXIDX) { + GX_CP_LOAD_REG(GX_CP_REG_MTXIDXA, gx->matIdxA); + GX_XF_LOAD_REG(GX_XF_REG_MATRIXINDEX0, gx->matIdxA); + } else { + GX_CP_LOAD_REG(GX_CP_REG_MTXIDXB, gx->matIdxB); + GX_XF_LOAD_REG(GX_XF_REG_MATRIXINDEX1, gx->matIdxB); + } + + gx->bpSentNot = GX_TRUE; +} diff --git a/src/static/GAEJ01_01/dolphin/gx/GXVerifRAS.c b/src/static/GAEJ01_01/dolphin/gx/GXVerifRAS.c new file mode 100644 index 00000000..75d00dcb --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXVerifRAS.c @@ -0,0 +1,575 @@ +// TODO: match + +#if DEBUG + +#include + +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +void __GXVerifySU(void) +{ + if (__gxVerif->verifyLevel >= 1 && (u32)GET_REG_FIELD(__gxVerif->rasRegs[32], 11, 12) < 340.0f) { + sprintf(__gxvDummyStr, __gxvWarnings[2], (u32)GET_REG_FIELD(__gxVerif->rasRegs[32], 11, 12) - 340.0f); + __gxVerif->cb(1, 2U, __gxvDummyStr); + } + + if (__gxVerif->verifyLevel >= 1 && (u32)GET_REG_FIELD(__gxVerif->rasRegs[32], 11, 0) < 340.0f) { + sprintf(__gxvDummyStr, __gxvWarnings[3], (u32)GET_REG_FIELD(__gxVerif->rasRegs[32], 11, 12 /* bug? */) - 340.0f); + __gxVerif->cb(1, 3U, __gxvDummyStr); + } + + switch (__gxVerif->rasRegs[67] & 7) { + case 4: + case 5: + if (__gxVerif->verifyLevel >= 1) { + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[33], 11, 12) > 1059) { + sprintf(__gxvDummyStr, __gxvWarnings[4], 1059, "YUV"); + __gxVerif->cb(1, 4U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[33], 11, 0) > 915) { + sprintf(__gxvDummyStr, __gxvWarnings[5], 915, "YUV"); + __gxVerif->cb(1, 5U, __gxvDummyStr); + } + } + break; + case 0: + case 1: + case 3: + if (__gxVerif->verifyLevel >= 1) { + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[33], 11, 12) > 979) { + sprintf(__gxvDummyStr, __gxvWarnings[4], 979, "RGB"); + __gxVerif->cb(1, 4U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[33], 11, 0) > 867) { + sprintf(__gxvDummyStr, __gxvWarnings[5], 867, "RGB"); + __gxVerif->cb(1, 5U, __gxvDummyStr); + } + } + break; + case 2: + if (__gxVerif->verifyLevel >= 1) { + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[33], 11, 12) > 979) { + sprintf(__gxvDummyStr, __gxvWarnings[4], 979, "RGB multisample"); + __gxVerif->cb(1, 4U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[33], 11, 0) > 603) { + sprintf(__gxvDummyStr, __gxvWarnings[5], 603, "RGB multisample"); + __gxVerif->cb(1, 5U, __gxvDummyStr); + } + } + break; + } +} + +void __GXVerifyBUMP(void) +{ + u32 i; + u32 nBmp; + u32 nTev; + u32 nTex; + u32 matrix; + + nBmp = GET_REG_FIELD(__gxVerif->rasRegs[0], 3, 16); + nTex = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 0); + nTev = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 10) + 1; + + for (i = 0; i < nTev; i++) { + matrix = GET_REG_FIELD(__gxVerif->rasRegs[16 + i], 4, 9); + if (__gxVerif->verifyLevel >= 1) { + if ((u32)(__gxVerif->rasRegs[16 + i] & 0xFF000000) + 0x01000000 == 0U) { + sprintf(__gxvDummyStr, __gxvWarnings[7], i); + __gxVerif->cb(1, 7U, __gxvDummyStr); + } + if ((GET_REG_FIELD(__gxVerif->rasRegs[16 + i], 2, 7) != 0 || matrix != 0) + && GET_REG_FIELD(__gxVerif->rasRegs[16 + i], 2, 0) >= nBmp) { + sprintf(__gxvDummyStr, __gxvWarnings[8], i); + __gxVerif->cb(1, 8U, __gxvDummyStr); + } + if (matrix != 0) { + matrix = (matrix & 3) - 1; + if ((u32)(__gxVerif->rasRegs[(matrix * 3) + 6] & 0xFF000000) + 0x01000000 == 0 + || (u32)(__gxVerif->rasRegs[(matrix * 3) + 7] & 0xFF000000) + 0x01000000 == 0U + || (u32)(__gxVerif->rasRegs[(matrix * 3) + 8] & 0xFF000000) + 0x01000000 == 0U) { + sprintf(__gxvDummyStr, __gxvWarnings[9], matrix, i); + __gxVerif->cb(1, 9U, __gxvDummyStr); + } + } + } + } + if (__gxVerif->verifyLevel >= 1) { + if (nBmp != 0 && (u32)(__gxVerif->rasRegs[0x27] & 0xFF000000) + 0x01000000 == 0) { + __gxVerif->cb(1, 0xAU, __gxvWarnings[10]); + } + if (nBmp != 0 && (u32)(__gxVerif->rasRegs[0x25] & 0xFF000000) + 0x01000000 == 0) { + sprintf(__gxvDummyStr, __gxvWarnings[11], 0U, 1); + __gxVerif->cb(1, 0xBU, __gxvDummyStr); + } + if (nBmp > 2U && (u32)(__gxVerif->rasRegs[0x26] & 0xFF000000) + 0x01000000 == 0) { + sprintf(__gxvDummyStr, __gxvWarnings[11], 2U, 3); + __gxVerif->cb(1, 0xBU, __gxvDummyStr); + } + if (nBmp != 0 && GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 3) >= nTex) { + sprintf(__gxvDummyStr, __gxvWarnings[12], 0U); + __gxVerif->cb(1, 0xCU, __gxvDummyStr); + } + if (nBmp > 1U && GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 9) >= nTex) { + sprintf(__gxvDummyStr, __gxvWarnings[12], 1U); + __gxVerif->cb(1, 0xCU, __gxvDummyStr); + } + if (nBmp > 2U && GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 15) >= nTex) { + sprintf(__gxvDummyStr, __gxvWarnings[12], 2U); + __gxVerif->cb(1, 0xCU, __gxvDummyStr); + } + if (nBmp > 3U && GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 21) >= nTex) { + sprintf(__gxvDummyStr, __gxvWarnings[12], 3U); + __gxVerif->cb(1, 0xCU, __gxvDummyStr); + } + if (nBmp != 0 && GET_REG_FIELD(__gxVerif->rasRegs[0x10], 1, 20)) { + __gxVerif->cb(1, 0xDU, __gxvWarnings[13]); + } + if (nBmp != 0 && GET_REG_FIELD(__gxVerif->rasRegs[0x10], 2, 7) != 0) { + __gxVerif->cb(1, 0xEU, __gxvWarnings[14]); + } + if ((u32)(__gxVerif->rasRegs[0xF] & 0xFF000000) + 0x01000000 == 0 && (nTex != 0 || nBmp != 0)) { + __gxVerif->cb(1, 0xFU, __gxvWarnings[15]); + } + } +} + +#define SOMEINDEX(index) (index & 3) + ((index * 8) & ~0x1F) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +void __GXVerifyTEX(void) +{ + u32 i; + u32 nBmp; + u32 nTev; + u32 nTex; + u32 enabled; + u32 texId; + u32 direct[8]; + u32 indirect[8]; + u32 h2; + u32 w2; + u32 nlevels; + + nBmp = GET_REG_FIELD(__gxVerif->rasRegs[0], 3, 16); + nTex = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 0); + nTev = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 10) + 1; + + for (i = 0; i < 8; i++) { + direct[i] = 0; + indirect[i] = 0; + } + + for (i = 0; i < nTev + nBmp; i++) { + if (i < nTev) { + if (__gxVerif->verifyLevel >= 1) { + if ((__gxVerif->rasRegs[(i >> 1U) + 0x28] & 0xFF000000) + 0x01000000 == 0U) { + sprintf(__gxvDummyStr, __gxvWarnings[16], i); + __gxVerif->cb(1, 16, __gxvDummyStr); + } + if (i & 1) { + enabled = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 1, 18); + if (enabled && (GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 15) >= nTex)) { + sprintf(__gxvDummyStr, __gxvWarnings[17], i); + __gxVerif->cb(1, 17, __gxvDummyStr); + } + texId = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 12); + } else { + enabled = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 1, 6); + if (enabled && (GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 3) >= nTex)) { + sprintf(__gxvDummyStr, __gxvWarnings[17], i); + __gxVerif->cb(1, 17, __gxvDummyStr); + } + texId = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 0); + } + if (enabled && indirect[texId]) { + sprintf(__gxvDummyStr, __gxvWarnings[18], i); + __gxVerif->cb(1, 18, __gxvDummyStr); + } + if (enabled) { + direct[texId] = 1; + } + } + } else { + enabled = 1; + if ((i - nTev) == 0) { + texId = GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 0); + } else if ((i - nTev) == 1U) { + texId = GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 6); + } else if ((i - nTev) == 2U) { + texId = GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 12); + } else { + texId = GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 18); + } + if (__gxVerif->verifyLevel >= 1 && direct[texId]) { + sprintf(__gxvDummyStr, __gxvWarnings[18], i); + __gxVerif->cb(1, 18, __gxvDummyStr); + } + indirect[texId] = 1; + } + if (enabled) { + if (__gxVerif->verifyLevel >= 1) { + if ((u32)(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0 + || (u32)(__gxVerif->rasRegs[0x84 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0 + || (u32)(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0 + || (u32)(__gxVerif->rasRegs[0x8C + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0 + || (u32)(__gxVerif->rasRegs[0x90 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0) { + sprintf(__gxvDummyStr, __gxvWarnings[19], texId); + __gxVerif->cb(1, 19, __gxvDummyStr); + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x8C + SOMEINDEX(texId)], 1, 21) == 0 + && (u32)(__gxVerif->rasRegs[0x94 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0) { + sprintf(__gxvDummyStr, __gxvWarnings[20], texId); + __gxVerif->cb(1, 20, __gxvDummyStr); + } + if (((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 8 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 9 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 10) + && (__gxVerif->rasRegs[0x98 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0U) { + sprintf(__gxvDummyStr, __gxvWarnings[21], texId); + __gxVerif->cb(1, 21, __gxvDummyStr); + } + + if (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 0) + 1 == 0) { + w2 = 1; + } else { + w2 = 1; + while (!(w2 & (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 0) + 1))) { + w2 *= 2; + } + w2 = (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 0) + 1) == w2; + } + + if (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 10) + 1 == 0) { + h2 = 1; + } else { + h2 = 1; + while (!(h2 & (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 10) + 1))) { + h2 *= 2; + } + h2 = (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 10) + 1) == h2; + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFFFF, 2, 5) && !w2) { + sprintf(__gxvDummyStr, __gxvWarnings[22], "Width", texId); + __gxVerif->cb(1, 22, __gxvDummyStr); + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFFFF, 2, 5) && !h2) { + sprintf(__gxvDummyStr, __gxvWarnings[22], "Height", texId); + __gxVerif->cb(1, 22, __gxvDummyStr); + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 2, 0) && !w2) { + sprintf(__gxvDummyStr, __gxvWarnings[23], "S", texId); + __gxVerif->cb(1, 23, __gxvDummyStr); + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 2, 2) && !h2) { + sprintf(__gxvDummyStr, __gxvWarnings[23], "T", texId); + __gxVerif->cb(1, 23, __gxvDummyStr); + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFFFF, 2, 5) != 0 + && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 8 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 9 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 10) + && (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 3, 5) != 1 + && (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 3, 5) != 5) { + sprintf(__gxvDummyStr, __gxvWarnings[24], texId); + __gxVerif->cb(1, 24, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x84 + SOMEINDEX(texId)], 8, 0) > (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x84 + SOMEINDEX(texId)], 8, 8)) { + sprintf(__gxvDummyStr, __gxvWarnings[25], texId); + __gxVerif->cb(1, 25, __gxvDummyStr); + } + for ( + nlevels = 0; + ( + MAX((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 0) + 1, + (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 10) + 1) >> nlevels + ) != 0; + nlevels++) { + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x84 + SOMEINDEX(texId)], 8, 8) > (nlevels - 1) * 16) { + sprintf(__gxvDummyStr, __gxvWarnings[26], texId); + __gxVerif->cb(1, 26, __gxvDummyStr); + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 21) && GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 8)) { + sprintf(__gxvDummyStr, __gxvWarnings[27], texId); + __gxVerif->cb(1, 27, __gxvDummyStr); + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 2, 19) + && (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFFFF, 2, 5) == 0 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 3, 5) != 6 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 4) != 1 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 8 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 9 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 10 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 8) != 0 + || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 21))) { + sprintf(__gxvDummyStr, __gxvWarnings[28], texId); + __gxVerif->cb(1, 28, __gxvDummyStr); + } + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 18) != 0) { + if (__gxVerif->verifyLevel >= 1 + && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 3, 5) != 4 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 4) != 1)) { + sprintf(__gxvDummyStr, __gxvWarnings[29], texId); + __gxVerif->cb(1, 29, __gxvDummyStr); + } + if (__gxVerif->verifyLevel >= 3 + && (!GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 17) || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) != 1 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 2, 19) != 0)) { + sprintf(__gxvDummyStr, __gxvWarnings[30], texId); + __gxVerif->cb(1, 30, __gxvDummyStr); + } + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 17) != 0) { + if (__gxVerif->verifyLevel >= 1 + && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 9 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 10)) { + sprintf(__gxvDummyStr, __gxvWarnings[31], texId); + __gxVerif->cb(1, 31, __gxvDummyStr); + } + if (__gxVerif->verifyLevel >= 3 + && (!GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 18) || 0)) { + sprintf(__gxvDummyStr, __gxvWarnings[30], texId); + __gxVerif->cb(1, 30, __gxvDummyStr); + } + } + } + } +} + +#if DEBUG +// debug nonmatching: https://decomp.me/scratch/rXQyF +static char _383[] = "A"; +static char _384[] = "B"; +static char _385[] = "C"; +static char _386[] = "D"; +static char _387[] = "alpha"; +static char _388[] = "color"; +asm void __GXVerifyTEV(void) +{ + nofralloc +#include "../../nonmatchings/__GXVerifyTEV.s" +} +#pragma peephole on +#else +void __GXVerifyTEV(void) +{ + unsigned long i; // r31 + unsigned long nTev; // r29 + unsigned long nCol; // r28 + unsigned long enabled; // r30 + unsigned long color; // r27 + unsigned long Clh[4]; // r1+0x38 + unsigned long Alh[4]; // r1+0x28 + unsigned long Cwritten[4]; // r1+0x18 + unsigned long Awritten[4]; // r1+0x8 + + nTev = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 10) + 1; + nCol = GET_REG_FIELD(__gxVerif->rasRegs[0], 3, 4); +nCol; + for (i = 0; i < 4; i++) { + Clh[i] = 0; + Alh[i] = 0; + Cwritten[i] = 0; + Awritten[i] = 0; + } + + for (i = 0; i < nTev; i++) { + if (__gxVerif->verifyLevel >= 1 + && (((u32) ((__gxVerif->rasRegs[(i * 2) + 0xC0] & 0xFF000000) + 0x01000000) == 0U) || ((u32) ((__gxVerif->rasRegs[(i * 2) + 0xC1] & 0xFF000000) + 0x01000000) == 0U))) { + sprintf(__gxvDummyStr, __gxvWarnings[32], i); + __gxVerif->cb(1, 0x20U, __gxvDummyStr); + } + if (i & 1) { + color = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 19); + } else { + color = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 7); + } + if (__gxVerif->verifyLevel >= 2 && ((color == 0 && nCol < 1) || (color == 1 && nCol < 2))) { + sprintf(__gxvDummyStr, __gxvWarnings[33], i); + __gxVerif->cb(1, 0x21U, __gxvDummyStr); + } + if (i & 1) { + enabled = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 1, 18); + } else { + enabled = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 1, 6); + } + if (__gxVerif->verifyLevel >= 1) { + if (!enabled && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) == 9)) { + sprintf(__gxvDummyStr, __gxvWarnings[0x22], "A", i); + __gxVerif->cb(1, 0x22U, __gxvDummyStr); + } + if (!enabled && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) == 9)) { + sprintf(__gxvDummyStr, __gxvWarnings[0x22], "B", i); + __gxVerif->cb(1, 0x22U, __gxvDummyStr); + } + if (!enabled && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) == 9)) { + sprintf(__gxvDummyStr, __gxvWarnings[0x22], "C", i); + __gxVerif->cb(1, 0x22U, __gxvDummyStr); + } + if (!enabled && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 0) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 0) == 9)) { + sprintf(__gxvDummyStr, __gxvWarnings[0x22], "D", i); + __gxVerif->cb(1, 0x22U, __gxvDummyStr); + } + if (!enabled && (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13) == 4) { + sprintf(__gxvDummyStr, __gxvWarnings[0x23], "A", i); + __gxVerif->cb(1, 0x23U, __gxvDummyStr); + } + if (!enabled && (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10) == 4) { + sprintf(__gxvDummyStr, __gxvWarnings[0x23], "B", i); + __gxVerif->cb(1, 0x23U, __gxvDummyStr); + } + if (!enabled && (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7) == 4) { + sprintf(__gxvDummyStr, __gxvWarnings[0x23], "C", i); + __gxVerif->cb(1, 0x23U, __gxvDummyStr); + } + if (!enabled && (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 4) == 4) { + sprintf(__gxvDummyStr, __gxvWarnings[0x23], "D", i); + __gxVerif->cb(1, 0x23U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) <= 7 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) + 0xE1] & 0xFF000000) + 0x01000000) == 0U) { + if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 12) ? !Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)] : !Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)]) { + sprintf(__gxvDummyStr, __gxvWarnings[0x24], "A", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 0xCU) ? "alpha" : "color", (__gxVerif->rasRegs[(i * 2) + 0xC0] >> 0xDU) & 7); + __gxVerif->cb(1, 0x24U, __gxvDummyStr); + } + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) <= 7 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) + 0xE1] & 0xFF000000) + 0x01000000) == 0U) { + if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 8) ? !Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)] : !Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)]) { + sprintf(__gxvDummyStr, __gxvWarnings[0x24], "B", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 8U) ? "alpha" : "color", (__gxVerif->rasRegs[(i * 2) + 0xC0] >> 9U) & 7); + __gxVerif->cb(1, 0x24U, __gxvDummyStr); + } + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) <= 7 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) + 0xE1] & 0xFF000000) + 0x01000000) == 0U) { + if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 4) ? !Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)] : !Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)]) { + sprintf(__gxvDummyStr, __gxvWarnings[0x24], "C", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 4U) ? "alpha" : "color", (__gxVerif->rasRegs[(i * 2) + 0xC0] >> 5U) & 7); + __gxVerif->cb(1, 0x24U, __gxvDummyStr); + } + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 0) <= 7 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 0) + 0xE1] & 0xFF000000) + 0x01000000) == 0U) { + if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 0) ? !Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 1)] : !Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 1)]) { + sprintf(__gxvDummyStr, __gxvWarnings[0x24], "D", i, (__gxVerif->rasRegs[(i * 2) + 0xC0] & 1) ? "alpha" : "color", (__gxVerif->rasRegs[(i * 2) + 0xC0] >> 1U) & 7); + __gxVerif->cb(1, 0x24U, __gxvDummyStr); + } + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13) <= 3 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 4, 14) + 0xE0] & 0xFF000000) + 0x01000000) == 0U && Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13)] == 0U) { + sprintf(__gxvDummyStr, __gxvWarnings[0x25], "A", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13)); + __gxVerif->cb(1, 0x25U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10) <= 3 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 11) + 0xE0] & 0xFF000000) + 0x01000000) == 0U && Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10)] == 0U) { + sprintf(__gxvDummyStr, __gxvWarnings[0x25], "B", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10)); + __gxVerif->cb(1, 0x25U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7) <= 3 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 8) + 0xE0] & 0xFF000000) + 0x01000000) == 0U && Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7)] == 0U) { + sprintf(__gxvDummyStr, __gxvWarnings[0x25], "C", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7)); + __gxVerif->cb(1, 0x25U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 4) <= 3 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 3) + 0xE0] & 0xFF000000) + 0x01000000) == 0U && Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 4)] == 0U) { + sprintf(__gxvDummyStr, __gxvWarnings[0x25], "D", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 4)); + __gxVerif->cb(1, 0x25U, __gxvDummyStr); + } + } + if (__gxVerif->verifyLevel >= 3) { + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) <= 7) { + if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 12) ? Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)] : Clh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)]) { + sprintf(__gxvDummyStr, __gxvWarnings[0x26], "A", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 12) ? "alpha" : "color", GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)); + __gxVerif->cb(3, 0x26U, __gxvDummyStr); + } + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) <= 7) { + if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 8) ? Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)] : Clh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)]) { + sprintf(__gxvDummyStr, __gxvWarnings[0x26], "B", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 8) ? "alpha" : "color", GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)); + __gxVerif->cb(3, 0x26U, __gxvDummyStr); + } + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) <= 7) { + if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 4) ? Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)] : Clh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)]) { + sprintf(__gxvDummyStr, __gxvWarnings[0x26], "C", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 4) ? "alpha" : "color", GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)); + __gxVerif->cb(3, 0x26U, __gxvDummyStr); + } + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13) <= 3 && (u32)Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13)] != 0) { + sprintf(__gxvDummyStr, __gxvWarnings[0x27], "A", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 0xDU)); + __gxVerif->cb(3, 0x27U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10) <= 3 && (u32)Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10)] != 0) { + sprintf(__gxvDummyStr, __gxvWarnings[0x27], "B", i, ((__gxVerif->rasRegs[(i * 2) + 0xC1] >> 0xAU) & 7)); + __gxVerif->cb(3, 0x27U, __gxvDummyStr); + } + if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7) <= 3 && (u32)Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7)] != 0) { + sprintf(__gxvDummyStr, __gxvWarnings[0x27], "C", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7U)); + __gxVerif->cb(3, 0x27U, __gxvDummyStr); + } + } + Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 2, 22)] = 1; + Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 2, 22)] = 1; + Clh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 2, 22)] = (!GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 2, 0) && !GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 19)); + Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 2, 22)] = (!GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 2, 0) && !GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 1, 19)); + } + + for (i = 0; i < 4; i++) { + if (Cwritten[i] != 0U) { + __gxVerif->rasRegs[(i * 2) + 0xE1] = (__gxVerif->rasRegs[(i * 2) + 0xE1] & 0xFFFFFF) | 0xFF000000; + } + if (Awritten[i] != 0U) { + __gxVerif->rasRegs[(i * 2) + 0xE0] = (__gxVerif->rasRegs[(i * 2) + 0xE0] & 0xFFFFFF) | 0xFF000000; + } + } + if (GET_REG_FIELD(__gxVerif->rasRegs[0xF5], 2, 2) && __gxVerif->verifyLevel >= 1) { + if ((u32) ((__gxVerif->rasRegs[0xF4] & 0xFF000000) + 0x01000000) == 0U) { + __gxVerif->cb(1, 0x28U, __gxvWarnings[0x28]); + } + if (!enabled) { + __gxVerif->cb(1, 0x29U, __gxvWarnings[0x29]); + } + } + if (__gxVerif->verifyLevel >= 2) { + if (GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC0], 2, 22)) { + __gxVerif->cb(2, 0x2AU, __gxvWarnings[0x2A]); + } + if (GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC1], 2, 22)) { + __gxVerif->cb(2, 0x2BU, __gxvWarnings[0x2B]); + } + } + if (__gxVerif->verifyLevel >= 3) { + if (!GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC1], 2, 0) && !GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC0], 1, 19)) { + __gxVerif->cb(3, 0x2CU, __gxvWarnings[0x2C]); + } + if (!GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC1], 2, 0) && !GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC1], 1, 19)) { + __gxVerif->cb(3, 0x2DU, __gxvWarnings[0x2D]); + } + } + if (__gxVerif->verifyLevel >= 2 && GET_REG_FIELD(__gxVerif->rasRegs[0x43], 1, 6) && (GET_REG_FIELD(__gxVerif->rasRegs[0xF3], 2, 22) || ((u32) GET_REG_FIELD(__gxVerif->rasRegs[0xF3], 3, 16) != 7) || ((u32) GET_REG_FIELD(__gxVerif->rasRegs[0xF3], 3, 19) != 7))) { + __gxVerif->cb(2, 0x2EU, __gxvWarnings[0x2E]); + } +} +#endif + +void __GXVerifyPE(void) +{ + u32 i; + + if (__gxVerif->verifyLevel >= 1 && GET_REG_FIELD(__gxVerif->rasRegs[0x41], 1, 0) && GET_REG_FIELD(__gxVerif->rasRegs[0x41], 1, 1)) { + __gxVerif->cb(1, 0x2FU, __gxvWarnings[0x2F]); + } + if (__gxVerif->verifyLevel >= 2) { + if (GET_REG_FIELD(__gxVerif->rasRegs[0], 1, 9) && (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x43], 3, 0) != 2) { + __gxVerif->cb(2, 0x31U, __gxvWarnings[0x31]); + } + if (!GET_REG_FIELD(__gxVerif->rasRegs[0], 1, 9) && (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x43], 3, 0) == 2) { + __gxVerif->cb(2, 0x32U, __gxvWarnings[0x32]); + } + } + if (__gxVerif->verifyLevel >= 3) { + for (i = 0; i < 4; i++) { + if (((u32)GET_REG_FIELD(__gxVerif->rasRegs[i + 1], 4, 4) > GET_REG_FIELD(__gxVerif->rasRegs[i + 1], 4, 12) || (u32)GET_REG_FIELD(__gxVerif->rasRegs[i + 1], 4, 12) > (u32)GET_REG_FIELD(__gxVerif->rasRegs[i + 1], 4, 20)) + && (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x43], 3, 0) == 2) { + sprintf(__gxvDummyStr, __gxvWarnings[0x33], i); + __gxVerif->cb(3, 0x33U, __gxvDummyStr); + } + } + } +} + +#endif diff --git a/src/static/GAEJ01_01/dolphin/gx/GXVerifXF.c b/src/static/GAEJ01_01/dolphin/gx/GXVerifXF.c new file mode 100644 index 00000000..995b2c67 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXVerifXF.c @@ -0,0 +1,947 @@ +// TODO: match + +#if DEBUG + +#include + +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +static u8 internalDebug; +static u32 DumpCount; +static s8 XFBuf[128]; +static u32 numRegularTextures; +static u32 numBumpmapTextures; +static u32 numColor0Textures; +static u32 numColor1Textures; +static u32 numColorTextures; +static s32 XFChannel = -1; + +static GXAttr TextureEnums[8] = { + GX_VA_TEX0, + GX_VA_TEX1, + GX_VA_TEX2, + GX_VA_TEX3, + GX_VA_TEX4, + GX_VA_TEX5, + GX_VA_TEX6, + GX_VA_TEX7, +}; + +static u8 lightRegisterNames[13][256] = { + "Light Color RGBA", + "Cosine Attenuation A0", + "Cosine Attenuation A1", + "Cosine Attenuation A2", + "Distance Attenuation K0", + "Distance Attenuation K1", + "Distance Attenuation K2", + "X Light Position / Infinite Light X Direction", + "Y Light Position / Infinite Light Y Direction", + "Z Light Position / Infinite Light Z Direction", + "X Light Direction / Half Angle X Component", + "Y Light Direction / Half Angle Y Component", + "Z Light Direction / Half Angle Z Component", +}; + +#define LOWORD(var) (((u16 *)&(var))[0]) +#define HIWORD(var) (((u16 *)&(var))[1]) + +#define BYTE0(var) (((u8 *)&(var))[0]) +#define BYTE1(var) (((u8 *)&(var))[1]) +#define BYTE2(var) (((u8 *)&(var))[2]) +#define BYTE3(var) (((u8 *)&(var))[3]) + +static void CountTextureTypes(void) +{ + u32 i; + u32 texgen_type; + + numRegularTextures = 0; + numBumpmapTextures = 0; + numColor0Textures = 0; + numColor1Textures = 0; + for (i = 0; i < __gxVerif->xfRegs[0x3F]; i++) { + texgen_type = BYTE3(__gxVerif->xfRegs[i + 64]); + texgen_type = (texgen_type >> 4) & 7; + if (texgen_type == 0) { + numRegularTextures++; + } else if (texgen_type == 1) { + numBumpmapTextures++; + } else if (texgen_type == 2) { + numColor0Textures++; + } else if (texgen_type == 3) { + numColor1Textures++; + } else { + __GX_WARN3F_CHECK(GXWARN_INVALID_TG_TYPE, texgen_type, i); + } + } + numColorTextures = numColor0Textures + numColor1Textures; +} + +static void InitializeXFVerifyData(void) +{ + CountTextureTypes(); +} + +static void CheckDirty(u32 index, const char *name) +{ + if (!__gxVerif->xfRegsDirty[index - 0x1000]) { + __GX_WARN3F_CHECK(GXWARN_XF_CTRL_UNINIT, index, name); + } +} + +static void CheckClean(u32 index, const char *name) +{ + if (__gxVerif->xfRegsDirty[index - 0x1000]) { + __GX_WARN3F_CHECK(GXWARN_XF_CTRL_INIT, index, name); + } +} + +static void CheckCTGColors(void) +{ + if ((BYTE3(__gxVerif->xfRegs[9]) & 3) > 2u) { + __GX_WARN3F_CHECK(GXWARN_INV_NUM_COLORS, (u8)(BYTE3(__gxVerif->xfRegs[9]) & 3)); + } +} + +static GXBool __GXVertexPacketHas(GXAttr attr) +{ + switch (attr) { + case GX_VA_POS: return GET_REG_FIELD(gx->vcdLo, 2, 9) != 0; + case GX_VA_NRM: return gx->hasNrms ? GET_REG_FIELD(gx->vcdLo, 2, 11) != 0 : GX_FALSE; + case GX_VA_NBT: return gx->hasBiNrms ? GET_REG_FIELD(gx->vcdLo, 2, 11) != 0 : GX_FALSE; + case GX_VA_CLR0: return GET_REG_FIELD(gx->vcdLo, 2, 13) != 0; + case GX_VA_CLR1: return GET_REG_FIELD(gx->vcdLo, 2, 15) != 0; + case GX_VA_TEX0: return GET_REG_FIELD(gx->vcdHi, 2, 0) != 0; + case GX_VA_TEX1: return GET_REG_FIELD(gx->vcdHi, 2, 2) != 0; + case GX_VA_TEX2: return GET_REG_FIELD(gx->vcdHi, 2, 4) != 0; + case GX_VA_TEX3: return GET_REG_FIELD(gx->vcdHi, 2, 6) != 0; + case GX_VA_TEX4: return GET_REG_FIELD(gx->vcdHi, 2, 8) != 0; + case GX_VA_TEX5: return GET_REG_FIELD(gx->vcdHi, 2, 10) != 0; + case GX_VA_TEX6: return GET_REG_FIELD(gx->vcdHi, 2, 12) != 0; + case GX_VA_TEX7: return GET_REG_FIELD(gx->vcdHi, 2, 14) != 0; + case GX_VA_PNMTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 0) != 0; + case GX_VA_TEX0MTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 1) != 0; + case GX_VA_TEX1MTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 2) != 0; + case GX_VA_TEX2MTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 3) != 0; + case GX_VA_TEX3MTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 4) != 0; + case GX_VA_TEX4MTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 5) != 0; + case GX_VA_TEX5MTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 6) != 0; + case GX_VA_TEX6MTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 7) != 0; + case GX_VA_TEX7MTXIDX: return GET_REG_FIELD(gx->vcdLo, 1, 8) != 0; + default: + return GX_FALSE; + } +} + +static void CheckVertexPacket(void) +{ + u32 numHostTextures; + u32 i; + + if (!__GXVertexPacketHas(GX_VA_POS)) { + __GX_WARN3_CHECK(GXWARN_VTX_NO_GEOM); + } + if ((BYTE3(__gxVerif->xfRegs[8]) & 3) == 0) { + if (__GXVertexPacketHas(GX_VA_CLR0) || __GXVertexPacketHas(GX_VA_CLR1)) { + __GX_WARN3_CHECK(GXWARN_CLR_XF0_CP1); + } + } else if ((u32)(BYTE3(__gxVerif->xfRegs[8]) & 3) == 1) { + if (!__GXVertexPacketHas(GX_VA_CLR0)) { + __GX_WARN3_CHECK(GXWARN_CLR_XF1_CP0); + } + if (__GXVertexPacketHas(GX_VA_CLR1)) { + __GX_WARN3_CHECK(GXWARN_CLR_XF1_CP2); + } + } else if ((u32)(BYTE3(__gxVerif->xfRegs[8]) & 3) == 2) { + if (!__GXVertexPacketHas(GX_VA_CLR0)) { + __GX_WARN3_CHECK(GXWARN_CLR_XF2_CPN1); + } + if (!__GXVertexPacketHas(GX_VA_CLR1)) { + __GX_WARN3_CHECK(GXWARN_CLR_XF2_CPN2); + } + } else { + __GX_WARN3F_CHECK(GXWARN_INV_IVS_CLR, (u8)(BYTE3(__gxVerif->xfRegs[8]) & 3)); + } + if (((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3) == 0) { + if (__GXVertexPacketHas(GX_VA_NRM)) { + __GX_WARN3_CHECK(GXWARN_NRM_XF0_CP1); + } + if (__GXVertexPacketHas(GX_VA_NBT)) { + __GX_WARN3_CHECK(GXWARN_NRM_XF0_CP3); + } + } else if ((u32)((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3) == 1) { + if (!__GXVertexPacketHas(GX_VA_NRM)) { + __GX_WARN3_CHECK(GXWARN_NRM_XF1_CP0); + } + if (__GXVertexPacketHas(GX_VA_NBT)) { + __GX_WARN3_CHECK(GXWARN_NRM_XF1_CP3); + } + } else if ((u32)((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3) == 2) { + if (__GXVertexPacketHas(GX_VA_NRM)) { + __GX_WARN3_CHECK(GXWARN_NRM_XF3_CP1); + } + if (!__GXVertexPacketHas(GX_VA_NBT)) { + __GX_WARN3_CHECK(GXWARN_NRM_XF3_CP0); + } + } else { + __GX_WARN3F_CHECK(GXWARN_INV_IVS_NRM, (u8)((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3)); + } + numHostTextures = 0; + for (i = 0; i <= 7; i++) { + if (__GXVertexPacketHas(TextureEnums[i])) { + numHostTextures += 1; + } + } + if (numHostTextures != (u32)((BYTE3(__gxVerif->xfRegs[8]) >> 4) & 0xF)) { + __GX_WARN3F_CHECK(GXWARN_TEX_XFN_CPM, (u8)((BYTE3(__gxVerif->xfRegs[8]) >> 4) & 0xF), numHostTextures); + } +} + +static void CheckSourceRows(void) +{ + u32 i; + + for (i = 0; i < numRegularTextures; i++) { + switch ((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) { + case 0: + if (!__GXVertexPacketHas(GX_VA_POS)) { + __GX_WARN3F_CHECK(GXWARN_TEX_SRC_NPOS, i); + } + break; + case 1: + if (!__GXVertexPacketHas(GX_VA_NRM) && !__GXVertexPacketHas(GX_VA_NBT)) { + __GX_WARN3F_CHECK(GXWARN_TEX_SRC_NNRM, i); + } + break; + case 2: + if (!__GXVertexPacketHas(GX_VA_CLR0)) { + __GX_WARN3F_CHECK(GXWARN_TEX_SRC_NCLR0, i); + } + if (!__GXVertexPacketHas(GX_VA_CLR1)) { + __GX_WARN3F_CHECK(GXWARN_TEX_SRC_NCLR1, i); + } + break; + case 3: + case 4: + if (!__GXVertexPacketHas(GX_VA_NBT)) { + __GX_WARN3F_CHECK(GXWARN_TEX_SRC_NNBT, i); + } + break; + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + if (!__GXVertexPacketHas(TextureEnums[((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) - 5])) { + __GX_WARN3F_CHECK(GXWARN_TEX_SRC_NTEX, i, ((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) - 5); + } + break; + default: + __GX_WARN3F_CHECK(GXWARN_INV_TEX_SRC, i, (u8)((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F)); + break; + } + } +} + +static void CheckTextureOrder(void) +{ + u8 done = 0; + u32 count = 0; + + while (!done) { + if (count == __gxVerif->xfRegs[0x3F] || ((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7)) { + done = 1; + } else { + count += 1; + } + } + + done = 0; + while (done == 0) { + if (count == __gxVerif->xfRegs[0x3F]) { + done = 1; + } else if ((u32)((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7) != 1) { + if (!((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7)) { + __GX_WARN3_CHECK(GXWARN_INV_TG_ORDER); + } + done = 1; + } else { + count += 1; + } + } + + done = 0; + while (done == 0) { + if (count == __gxVerif->xfRegs[0x3F]) { + done = 1; + } else if (!((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7) || (u32)((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7) == 1) { + __GX_WARN3_CHECK(GXWARN_INV_TG_ORDER); + done = 1; + } else { + count += 1; + } + } +} + +static void CheckRAM(u8 Normal, u32 StartingAddress, u32 Count, GXWarnID WarnID, char *Str) +{ + u32 i; + u8 printedPreamble; + u8 dirtyBit; + + printedPreamble = FALSE; + for (i = StartingAddress; i < StartingAddress + Count; i++) { + dirtyBit = Normal != 0 ? __gxVerif->xfMtxDirty[i - 0x300] : __gxVerif->xfMtxDirty[i]; + if (dirtyBit == 0 && printedPreamble == FALSE) { + if (__gxVerif->verifyLevel >= __gxvWarnLev[WarnID]) { + __gxVerif->cb(__gxvWarnLev[WarnID], WarnID, Str); + } + printedPreamble = TRUE; + } + } +} + +static void CheckBumpmapTextures(void) +{ + u32 i; + u32 BumpMapSource; + u32 BumpMapLight; + u32 lightRAMOffset; + char Preamble[256]; + + if (!__GXVertexPacketHas(GX_VA_PNMTXIDX)) { + if ((u32)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F) > 30) { + __GX_WARN3F_CHECK(0x50, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + } + sprintf(Preamble, __gxvWarnings[0x6A], (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + CheckRAM(1, ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) * 3) + 0x400, 9U, 0x6A, Preamble); + } + + for (i = 0; i < numBumpmapTextures; i++) { + BumpMapSource = BYTE2(__gxVerif->xfRegs[numRegularTextures + i + 64]); + BumpMapSource = (BumpMapSource >> 4) & 7; + if ((BYTE3(__gxVerif->xfRegs[BumpMapSource + 64]) >> 4) & 7) { + __GX_WARN3F_CHECK(0x51, i + numRegularTextures, BumpMapSource); + } + BumpMapLight = __gxVerif->xfRegs[numRegularTextures + i + 0x40]; + BumpMapLight = (BumpMapLight >> 15) & 7; + lightRAMOffset = (BumpMapLight * 0x10) + 0x60A; + if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 0]) { + __GX_WARN3F_CHECK(0x52, i + numRegularTextures, BumpMapLight, "X"); + } + if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 1]) { + __GX_WARN3F_CHECK(0x52, i + numRegularTextures, BumpMapLight, "Y"); + } + if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 2]) { + __GX_WARN3F_CHECK(0x52, i + numRegularTextures, BumpMapLight, "Z"); + } + if (!__GXVertexPacketHas(GX_VA_NBT)) { + __GX_WARN3F_CHECK(0x53, i); + } + } + + lightRAMOffset;lightRAMOffset; // needed to match +} + +static void CheckTextureTransformMatrices(void) +{ + u32 i; + u32 StartingAddress; + u32 Size; + u8 MtxIndexInVertexPacket; + char Preamble[256]; + u32 Val; + + for (i = 0; i < numRegularTextures; i++) { + MtxIndexInVertexPacket = 0; + switch (i) { + case 0: + StartingAddress = (u8)((HIWORD(__gxVerif->xfRegs[0x18]) >> 4U) & 0xFC); + Val = HIWORD(__gxVerif->xfRegs[0x18]); + Val = (Val >> 6) & 0x3F; + MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX0MTXIDX); + break; + case 1: + StartingAddress = (u8)((__gxVerif->xfRegs[0x18] >> 10) & 0xFC); + Val = __gxVerif->xfRegs[0x18]; + Val = (Val >> 12) & 0x3F; + MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX1MTXIDX); + break; + case 2: + StartingAddress = (u8)(BYTE1(__gxVerif->xfRegs[0x18]) & 0xFC); + Val = BYTE1(__gxVerif->xfRegs[0x18]); + Val = (Val >> 2) & 0x3F; + MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX2MTXIDX); + break; + case 3: + StartingAddress = (BYTE0(__gxVerif->xfRegs[0x18]) * 4) & 0xFC; + Val = BYTE0(__gxVerif->xfRegs[0x18]); + Val = Val & 0x3F; + MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX3MTXIDX); + break; + case 4: + StartingAddress = (BYTE3(__gxVerif->xfRegs[0x19]) * 4) & 0xFC; + Val = BYTE3(__gxVerif->xfRegs[0x19]); + Val = Val & 0x3F; + MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX4MTXIDX); + break; + case 5: + StartingAddress = (u8)((HIWORD(__gxVerif->xfRegs[0x19]) >> 4) & 0xFC); + Val = HIWORD(__gxVerif->xfRegs[0x19]); + Val = (Val >> 6) & 0x3F; + MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX5MTXIDX); + break; + case 6: + StartingAddress = (u8)((__gxVerif->xfRegs[0x19] >> 10) & 0xFC); + Val = __gxVerif->xfRegs[0x19]; + Val = (Val >> 12) & 0x3F; + MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX6MTXIDX); + break; + case 7: + StartingAddress = (u8)(BYTE1(__gxVerif->xfRegs[0x19]) & 0xFC); + Val = BYTE1(__gxVerif->xfRegs[0x19]); + Val = (Val >> 2) & 0x3F; + MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX7MTXIDX); + break; + default: + __GX_WARN3F_CHECK(0x54, i); + break; + } + if (MtxIndexInVertexPacket == 0) { + sprintf(Preamble, __gxvWarnings[0x6B], i, i, Val); + if (!((BYTE3(__gxVerif->xfRegs[i + 64]) >> 1) & 1)) { + Size = 8; + } else { + Size = 0xC; + } + CheckRAM(0U, StartingAddress, Size, 0x6B, Preamble); + } + } + + // needed to match + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + StartingAddress; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; + MtxIndexInVertexPacket; +} + +static void CheckInputForms(void) +{ + u32 i; + + for (i = 0; i < numRegularTextures; i++) { + switch ((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) { + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + if ((BYTE3(__gxVerif->xfRegs[i + 64]) >> 2) & 1) { + __GX_WARN3F_CHECK(0x55, i, (u8)((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F)); + } + } + } +} + +static void CheckLight(u32 lightSource) +{ + u32 lightRAMOffset; + u8 printedPreamble; + u32 i; + + printedPreamble = 0; + lightRAMOffset = (lightSource * 0x10) + 0x603; + for (i = 0; i < 13; i++) { + if (!__gxVerif->xfLightDirty[lightRAMOffset + i - 0x600]) { + if (!printedPreamble) { + __GX_WARN3F_CHECK(0x6C, lightSource); + printedPreamble = 1; + } + } + } +} + +static void CheckColor0(void) +{ + char Preamble[256]; + u8 haveLight; + u32 i; + u8 lightUsed; + // regswaps here asm:0x1c64 + if ((BYTE3(__gxVerif->xfRegs[9]) & 3) || numColorTextures != 0) { + if (!__gxVerif->xfRegsDirty[14]) { + __GX_WARN3F_CHECK(0x56, 0x100E, "Color 0 control register"); + } + if (!__gxVerif->xfRegsDirty[16]) { + __GX_WARN3F_CHECK(0x56, 0x1010, "Alpha 0 control register"); + } + if (!(BYTE3(__gxVerif->xfRegs[14]) & 1) && !__gxVerif->xfRegsDirty[12]) { + __GX_WARN3F_CHECK(0x57, 0, 0, 0x100C); + } + if (!((BYTE3(__gxVerif->xfRegs[14]) >> 6) & 1) && !__gxVerif->xfRegsDirty[10]) { + __GX_WARN3F_CHECK(0x58, 0, 0, 0x100A); + } + if ((u32)((BYTE3(__gxVerif->xfRegs[14]) >> 1) & 1) == 1 || (u32)((BYTE3(__gxVerif->xfRegs[16]) >> 1) & 1) == 1) { + haveLight = 0; + for (i = 0; i < 8; i++) { + lightUsed = 0; + switch (i) { + case 0: + if ((u8)((BYTE3(__gxVerif->xfRegs[14]) >> 2) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[16]) >> 2) & 1)) { + lightUsed = 1; + } + break; + case 1: + if ((u8)((BYTE3(__gxVerif->xfRegs[14]) >> 3) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[16]) >> 3) & 1)) { + lightUsed = 1; + } + break; + case 2: + if ((u8)((BYTE3(__gxVerif->xfRegs[14]) >> 4) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[16]) >> 4) & 1)) { + lightUsed = 1; + } + break; + case 3: + if ((u8)((BYTE3(__gxVerif->xfRegs[14]) >> 5) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[16]) >> 5) & 1)) { + lightUsed = 1; + } + break; + case 4: + if ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 3) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[16]) >> 3) & 1)) { + lightUsed = 1; + } + break; + case 5: + if ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 4) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[16]) >> 4) & 1)) { + lightUsed = 1; + } + break; + case 6: + if ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 5) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[16]) >> 5) & 1)) { + lightUsed = 1; + } + break; + case 7: + if ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 6) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[16]) >> 6) & 1)) { + lightUsed = 1; + } + break; + } + if (lightUsed != 0) { + CheckLight(i); + haveLight = 1; + } + } + if (haveLight != 0) { + if (!((BYTE2(__gxVerif->xfRegs[14]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[14]) >> 7) & 3)) { + __GX_WARN3F_CHECK(0x59, "COLOR0", "COLOR0"); + } + if (!((BYTE2(__gxVerif->xfRegs[16]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[16]) >> 7) & 3)) { + __GX_WARN3F_CHECK(0x59, "ALPHA0", "ALPHA0"); + } + if (((HIWORD(__gxVerif->xfRegs[14]) >> 7) & 3) + || ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[14]) >> 2) & 1) == 1)) + || ((HIWORD(__gxVerif->xfRegs[16]) >> 7) & 3) + || ((u8)((BYTE2(__gxVerif->xfRegs[16]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[16]) >> 2) & 1) == 1))) { + if ((__GXVertexPacketHas(GX_VA_NRM) == 0) && (__GXVertexPacketHas(GX_VA_NBT) == 0)) { + __GX_WARN3F_CHECK(0x5A, 0); + } + if (__GXVertexPacketHas(GX_VA_PNMTXIDX) == 0) { + if ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) > 30u) { + __GX_WARN3F_CHECK(0x5B, 0, (BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + } + sprintf(Preamble, __gxvWarnings[0x6D], 0, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + CheckRAM(1, ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) * 3) + 0x400, 9, 0x6D, Preamble); + } + } + } + } + } +} + +static void CheckColor1(void) +{ + u8 usingColor1; + char Preamble[256]; + u8 haveLight; + u32 i; + u8 lightUsed; + + if (numColorTextures > 1 && ((u32)((BYTE3(__gxVerif->xfRegs[numRegularTextures + numBumpmapTextures + 1 + 64]) >> 4) & 7) == 3)) { + usingColor1 = 1; + } else { + usingColor1 = 0; + } + + if ((u32)(BYTE3(__gxVerif->xfRegs[9]) & 3) == 2 || usingColor1) { + if (!__gxVerif->xfRegsDirty[15]) { + __GX_WARN3F_CHECK(GXWARN_CLR_ADDR_UNINIT, 0x100F, "Color 1 control register"); + } + if (!__gxVerif->xfRegsDirty[17]) { + __GX_WARN3F_CHECK(GXWARN_CLR_ADDR_UNINIT, 0x1011, "Alpha 1 control register"); + } + if (!(BYTE3(__gxVerif->xfRegs[15]) & 1) && !__gxVerif->xfRegsDirty[13]) { + __GX_WARN3F_CHECK(GXWARN_CLR_MAT_UNINIT, 1, 1, 0x100D); + } + if (!((BYTE3(__gxVerif->xfRegs[15]) >> 6) & 1) && !__gxVerif->xfRegsDirty[11]) { + __GX_WARN3F_CHECK(GXWARN_CLR_AMB_UNINIT, 1, 1, 0x100B); + } + if ((u32)((BYTE3(__gxVerif->xfRegs[15]) >> 1) & 1) == 1 || (u32)((BYTE3(__gxVerif->xfRegs[17]) >> 1) & 1) == 1) { + haveLight = 0; + for (i = 0; i < 8; i++) { + lightUsed = 0; + switch (i) { + case 0: + if ((u8)((BYTE3(__gxVerif->xfRegs[15]) >> 2) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[17]) >> 2) & 1)) { + lightUsed = 1; + } + break; + case 1: + if ((u8)((BYTE3(__gxVerif->xfRegs[15]) >> 3) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[17]) >> 3) & 1)) { + lightUsed = 1; + } + break; + case 2: + if ((u8)((BYTE3(__gxVerif->xfRegs[15]) >> 4) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[17]) >> 4) & 1)) { + lightUsed = 1; + } + break; + case 3: + if ((u8)((BYTE3(__gxVerif->xfRegs[15]) >> 5) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[17]) >> 5) & 1)) { + lightUsed = 1; + } + break; + case 4: + if ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 3) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[17]) >> 3) & 1)) { + lightUsed = 1; + } + break; + case 5: + if ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 4) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[17]) >> 4) & 1)) { + lightUsed = 1; + } + break; + case 6: + if ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 5) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[17]) >> 5) & 1)) { + lightUsed = 1; + } + break; + case 7: + if ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 6) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[17]) >> 6) & 1)) { + lightUsed = 1; + } + break; + } + if (lightUsed != 0) { + CheckLight(i); + haveLight = 1; + } + } + if (haveLight != 0) { + if (!((BYTE2(__gxVerif->xfRegs[15]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[15]) >> 7) & 3)) { + __GX_WARN3F_CHECK(0x59, "COLOR1", "COLOR1"); + } + if (!((BYTE2(__gxVerif->xfRegs[17]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[17]) >> 7) & 3)) { + __GX_WARN3F_CHECK(0x59, "ALPHA1", "ALPHA1"); + } + if (((HIWORD(__gxVerif->xfRegs[15]) >> 7) & 3) + || ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[15]) >> 2) & 1) == 1)) + || ((HIWORD(__gxVerif->xfRegs[17]) >> 7) & 3) + || ((u8)((BYTE2(__gxVerif->xfRegs[17]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[17]) >> 2) & 1) == 1))) { + if ((__GXVertexPacketHas(GX_VA_NRM) == 0) && (__GXVertexPacketHas(GX_VA_NBT) == 0)) { + __GX_WARN3F_CHECK(0x5A, 1); + } + if (__GXVertexPacketHas(GX_VA_PNMTXIDX) == 0) { + if ((u32)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F) > 30) { + __GX_WARN3F_CHECK(0x5B, 1, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + } + sprintf(Preamble, __gxvWarnings[0x6D], 1, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + CheckRAM(1, ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) * 3) + 0x400, 9, 0x6D, Preamble); + } + } + } + } + } +} + +static void ComputeSignExponentMantissa(f32 floatVal, u32 *sign, u32 *exponent, u32 *mantissa) +{ + u32 intVal = *(u32 *)&floatVal; + + *sign = (intVal >> 31) & 1; + *exponent = (intVal >> 23) & 0xFF; + *mantissa = intVal & 0x7FFFFF; +} + +static void CheckFloatingPointValue(u8 dirtyBit, u32 value, char *label) +{ + u32 sign; + u32 exponent; + u32 mantissa; + f32 valuef; + + &valuef; + + if ((dirtyBit == 0)) { + return; + } + valuef = *(f32 *)&value; + ComputeSignExponentMantissa(valuef, &sign, &exponent, &mantissa); + + if (exponent == 0 && mantissa == 0) { + return; + } + + if (exponent == 0xFF) { + if (__gxVerif->verifyLevel >= 2) { + if (mantissa == 0) { + if (sign != 0) { + __GX_WARN3F_CHECK(0x5C, label, "-", *(u32 *)&valuef); + } else { + __GX_WARN3F_CHECK(0x5C, label, "+", *(u32 *)&valuef); + } + } else { + __GX_WARN3F_CHECK(0x5D, label, *(u32 *)&valuef); + } + } + } else if (__gxVerif->verifyLevel >= 3) { + if (exponent < 0x6BU) { + __GX_WARN3F_CHECK(0x5E, label, valuef, *(u32 *)&valuef); + } else if (exponent > 0x96U) { + __GX_WARN3F_CHECK(0x5F, label, valuef, *(u32 *)&valuef); + } + } +} + +static void CheckMatrixRAMRanges(void) +{ + u32 i; + char label[256]; + + for (i = 0; i <= 255; i++) { + sprintf(label, "Geometry/Texture Matrix ram address 0x%04x", i); + CheckFloatingPointValue(__gxVerif->xfMtxDirty[i], __gxVerif->xfMtx[i], label); + } +} + +static void CheckNormalRAMRanges(void) +{ + u32 i; + char label[256]; + + for (i = 1024; i <= 1119; i++) { + sprintf(label, "Normal Matrix ram address 0x%04x", i); + CheckFloatingPointValue(__gxVerif->xfNrmDirty[i - 1024], __gxVerif->xfNrm[i - 1024], label); + } +} + +static void CheckDMatrixRAMRanges(void) +{ + u32 i; + char label[256]; + + for (i = 1280; i <= 1535; i++) { + sprintf(label, "Dual Texture Matrix ram address 0x%04x", i); + CheckFloatingPointValue(__gxVerif->xfDMtxDirty[i - 1280], __gxVerif->xfDMtx[i - 1280], label); + } +} + +static void CheckLightRAMRanges(void) +{ + u32 lightSource; + u32 lightRAMOffset; + char label[256]; + u32 i; + + for (lightSource = 0; lightSource < 8; lightSource++) { + for (i = 1; i < 13; i++) { + lightRAMOffset = (lightSource << 4) + i; + lightRAMOffset += 0x603; + sprintf(label, "Light %d %s (address 0x%04x)", lightSource, lightRegisterNames[i], lightRAMOffset); + CheckFloatingPointValue(__gxVerif->xfLightDirty[lightRAMOffset - 0x600], __gxVerif->xfLight[(s32) (lightRAMOffset - 0x600)], label); + } + + } + + i; lightSource; // needed to match +} + +static void CheckControlRAMRanges(void) +{ + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1A], __gxVerif->xfRegs[0x1A], "Viewport Scale X"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1B], __gxVerif->xfRegs[0x1B], "Viewport Scale Y"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1C], __gxVerif->xfRegs[0x1C], "Viewport Scale Z"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1D], __gxVerif->xfRegs[0x1D], "Viewport Offset X"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1E], __gxVerif->xfRegs[0x1E], "Viewport Offset Y"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1F], __gxVerif->xfRegs[0x1F], "Viewport Offset Z"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x20], __gxVerif->xfRegs[0x20], "Projection Matrix A Value"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x21], __gxVerif->xfRegs[0x21], "Projection Matrix B Value"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x22], __gxVerif->xfRegs[0x22], "Projection Matrix C Value"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x23], __gxVerif->xfRegs[0x23], "Projection Matrix D Value"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x24], __gxVerif->xfRegs[0x24], "Projection Matrix E Value"); + CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x25], __gxVerif->xfRegs[0x25], "Projection Matrix F Value"); +} + +static void CheckFloatingPointRanges(void) +{ + CheckMatrixRAMRanges(); + CheckNormalRAMRanges(); + CheckDMatrixRAMRanges(); + CheckLightRAMRanges(); + CheckControlRAMRanges(); +} + +static void CheckMatrixIndices(void) +{ + if (!__GXVertexPacketHas(GX_VA_PNMTXIDX) + || !__GXVertexPacketHas(GX_VA_TEX0MTXIDX) + || !__GXVertexPacketHas(GX_VA_TEX1MTXIDX) + || !__GXVertexPacketHas(GX_VA_TEX2MTXIDX) + || !__GXVertexPacketHas(GX_VA_TEX3MTXIDX)) { + CheckDirty(0x1018U, "Geometry & Textures [0-3] transform matrix indices"); + } + if (__gxVerif->verifyLevel >= 1 && !__GXVertexPacketHas(GX_VA_PNMTXIDX)) { + CheckRAM(0U, (BYTE3(__gxVerif->xfRegs[24]) * 4) & 0xFC, 0xCU, 0x6E, __gxvWarnings[0x6E]); + } + if ((!__GXVertexPacketHas(GX_VA_TEX4MTXIDX) + || !__GXVertexPacketHas(GX_VA_TEX5MTXIDX) + || !__GXVertexPacketHas(GX_VA_TEX6MTXIDX) + || !__GXVertexPacketHas(GX_VA_TEX7MTXIDX)) + && numRegularTextures > 4 + && __gxVerif->verifyLevel >= 1 + && !__gxVerif->xfRegsDirty[0x19] + && __gxVerif->verifyLevel >= __gxvWarnLev[0x60]) { + __GX_WARN3F(0x60, numRegularTextures, 0x1019U); + } +} + +static void CheckErrors(void) +{ + u32 i; + char registerName[80]; + + CheckDirty(0x103FU, "Number of XF output textures"); + CheckDirty(0x1009U, "Number of XF output colors"); + CheckDirty(0x1008U, "InVertexSpec"); + CheckDirty(0x101AU, "Viewport ScaleX"); + CheckDirty(0x101BU, "Viewport ScaleY"); + CheckDirty(0x101CU, "Viewport ScaleZ"); + CheckDirty(0x101DU, "Viewport OffsetX"); + CheckDirty(0x101EU, "Viewport OffsetY"); + CheckDirty(0x101FU, "Viewport OffsetZ"); + CheckDirty(0x1020U, "Projection matrix 'A' value"); + CheckDirty(0x1021U, "Projection matrix 'B' value"); + CheckDirty(0x1022U, "Projection matrix 'C' value"); + CheckDirty(0x1023U, "Projection matrix 'D' value"); + CheckDirty(0x1024U, "Projection matrix 'E' value"); + CheckDirty(0x1025U, "Projection matrix 'F' value"); + CheckDirty(0x1026U, "Projection matrix orthographic/perspective select"); + CheckMatrixIndices(); + if (__gxVerif->verifyLevel >= 1) { + CheckCTGColors(); + if (__gxVerif->xfRegs[63] > 8) { + __GX_WARN3F_CHECK(0x64, __gxVerif->xfRegs[63], 8); + } + if (numRegularTextures > 8) { + __GX_WARN3F_CHECK(0x65, numRegularTextures, 8); + } + if (numBumpmapTextures > 3) { + __GX_WARN3F_CHECK(0x66, numBumpmapTextures, 3); + } + if (numColorTextures > 2) { + __GX_WARN3F_CHECK(0x67, numColorTextures, 2); + } + if (numColor0Textures > 1) { + __GX_WARN3F_CHECK(0x69, 0); + } + if (numColor1Textures > 1) { + __GX_WARN3F_CHECK(0x69, 1); + } + CheckVertexPacket(); + + for (i = 0; i < __gxVerif->xfRegs[0x3F]; i++) { + sprintf(registerName, "Texture %d settings", i); + CheckDirty(i + 0x1040, registerName); + } + CheckSourceRows(); + CheckTextureOrder(); + if (numBumpmapTextures != 0) { + CheckBumpmapTextures(); + } + CheckTextureTransformMatrices(); + if (numColorTextures != 0 && (u32)((BYTE3(__gxVerif->xfRegs[numRegularTextures + numBumpmapTextures + 64]) >> 4) & 7) != 2) {//((u32) (((u8) *(__gxVerif + (((numRegularTextures + (numBumpmapTextures + 0x40)) * 4) + 0xB)) >> 4U) & 7) != 2)) { + __GX_WARN3_CHECK(0x68); + } + CheckColor0(); + CheckColor1(); + } +} + +static void CheckWarnings(void) +{ + if (__gxVerif->verifyLevel >= 1) { + CheckInputForms(); + } + CheckClean(0x1000U, "Internal error register"); + CheckClean(0x1001U, "Internal diagnostic register"); + CheckClean(0x1002U, "Internal state register 0"); + CheckClean(0x1003U, "Internal state register 1"); + CheckClean(0x1004U, "Power savings register"); + if (__gxVerif->verifyLevel >= 2) { + CheckFloatingPointRanges(); + } +} + +static void DumpXFRegisters(void) +{ + static u8 firstTime = 1; +} + +void __GXVerifyXF(void) +{ + if (internalDebug) { + DumpXFRegisters(); + } + InitializeXFVerifyData(); + CheckErrors(); + CheckWarnings(); + DumpCount++; +} + +#endif diff --git a/src/static/GAEJ01_01/dolphin/gx/GXVerify.c b/src/static/GAEJ01_01/dolphin/gx/GXVerify.c new file mode 100644 index 00000000..cb348bb2 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXVerify.c @@ -0,0 +1,300 @@ +#if DEBUG + +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +static struct __GXVerifyData __gxVerifData; +struct __GXVerifyData * __gxVerif = &__gxVerifData; + +char *__gxvWarnings[115] = { + "Invalid Vertex Format. Normal count must be set to %s.", + "Texture size %ld not initialized.", + "Left edge of scissor rectangle is less than %d.", + "Top edge of scissor rectangle is less than %d.", + "Right edge of scissor rectangle is greater than %d in %s mode.", + "Bottom edge of scissor rectangle is greater than %d in %s mode.", + "%s value for subsample %d in pixel %ld is not 6 when single-sampling.", + "Indirect texture command for stage %ld is not set.", + "Invalid indirect texture request in TEV stage %ld.", + "Indirect matrix %ld requested in stage %d not set.", + "Requested indirect textures never initialized.", + "Indirect texture coordinate scales %d and %d not set.", + "Invalid texture coordinate specified for indirect stage %d.", + "Indirect texture feedback accumulation is on in TEV stage 0.", + "Indirect bump alpha is enabled in TEV stage 0.", + "Indirect vs. direct mask byte never set.", + "Texture reference never written for TEV stage %ld.", + "Invalid texture coordinate specified for TEV stage %ld.", + "Texture %ld is used as both indirect and direct.", + "Texture %ld not configured.", + "Base pointer for cached texture %ld is not specified.", + "TLUT for indexed texture %ld was never set up.", + "%s is not a power of 2 for mipmapped texture %ld.", + "%s is not GX_CLAMP for non-power-of-2 width in texture %ld.", + "Minification filter for texture %ld is not compatible with color index texture format.", + "Minimum LOD is greater than maximum LOD in texture %ld.", + "Maximum LOD is greater than image's maximum LOD for texture %ld.", + "LOD bias clamp shold be used with edge LOD for texture %ld.", + "Texture %ld does not meet requirements for anisotropic mipmapping.", + "Filters are not linear for field prediction in texture %ld.", + "Incomplete rounding mode configuration for texture %ld.", + "Rounding color indexed texture %ld.", + "Environment for TEV stage %ld not fully set up.", + "Invalid color channel selected in TEV stage %ld.", + "Argument %s selects null texture in TEV color stage %ld.", + "Argument %s selects null texture in TEV alpha stage %ld.", + "Color arg %s in TEV stage %ld accesses register %s, which may be dirty.", + "Alpha arg %s in TEV stage %ld accesses register %s, which may be dirty.", + "Color arg %s in TEV stage %ld accesses register %s, which was last unclamped. Possible wrap-around effect.", + "Alpha arg %s in TEV stage %ld accesses register %s, which was last unclamped. Possible wrap-around effect.", + "Z texturing enabled, but no Z offset specified.", + "Z texturing enabled, but no texture specified for final TEV stage.", + "Final TEV stage doesn't write color to register GX_TEVPREV.", + "Final TEV stage doesn't write alpha to register GX_TEVPREV.", + "Final TEV color stage has no clamping. Possible color wrap-around effect.", + "Final TEV alpha stage has no clamping. Possible alpha wrap-around effect.", + "Z buffering is before texture, but alpha compare operation is active.", + "PE blend and logicop are both on.", + "Selected pixel format does not support dithering.", + "Multisample enabled but pixel type is not RGB565.", + "Pixel type is RGB565 but multisample is not enabled.", + "Multisample locations for pixel %ld are not ordered correctly for antialias filter.", + "Invalid texgen_type %d for texture %d.", + "Register address 0x%04x uninitialized (%s).", + "Register address 0x%04x modified (%s), probably should not be.", + "Invalid combination of %d output color channels and %d color texgen textures.", + "Invalid number of output colors, %d.", + "Vertex packet does not contain position values.", + "XF is not expecting host colors but cp is sending some.", + "XF is expecting a host color but cp is not sending one.", + "XF is expecting a single host color but cp is sending two.", + "XF is expecting two host colors but cp is not sending first color.", + "XF is expecting two host colors but cp is not sending second color.", + "Invalid value (%d) for INVERTEXSPEC_REG.host_colors.", + "XF is not expecting host normals but cp is sending them.", + "XF is not expecting host normals, binormals and tangents but cp is sending them.", + "XF is expecting host normals but cp is not sending them.", + "XF is expecting host normals but cp is sending normals, binormals, and tangents.", + "XF is expecting host normals, binormals and tangents but cp is only sending normals.", + "XF is expecting host normals, binormals and tangents but cp is not sending them.", + "Invalid value (%d) for INVERTEXSPEC_REG.host_normal.", + "XF expecting %d host textures but CP is only sending %d.", + "GX_TEXCOORD%d specifies source row of position, but this is not getting sent.", + "GX_TEXCOORD%d specifies source row of normal, but this is not getting sent.", + "GX_TEXCOORD%d specifies source row of color0, but color0 is not getting sent.", + "GX_TEXCOORD%d specifies source row of color1, but color1 is not getting sent.", + "GX_TEXCOORD%d specifies source row of binormal or tangent, but this is not getting sent.", + "GX_TEXCOORD%d specifies source row of input texture coordinate %d, but this is not getting sent.", + "GX_TEXCOORD%d is specifying an invalid source row of %d.", + "TexCoordGen types are out of order. GX_TG_MTX2x4/3x4 should come first (if any), followed by GX_TG_BUMP (if any), then GX_TG_SRTG (if any).", + "Bumpmap texgen is defined, which requires that binormals and tangents be transformed by a normal matrix, but current matrix index is set to an invalid value (%d) for normal transform.", + "GX_TEXCOORD%d (texgen type bumpmap) is referencing texture %d as a source texture, which is not of texgen type regular.", + "GX_TEXCOORD%d (texgen type bumpmap) using light source %d, but light's %c position is not defined.", + "GX_TEXCOORD%d is defined as texgen type bumpmap, but binormals and tangents are not getting sent.", + "Invalid regular texture number (%d)", + "Regular texture %d specifying a source row of %d which only has 2 elements, but an input form of ABC1.", + "Output XF colors or color textures enabled, but register address 0x%04x uninitialized (%s).", + "Output XF colors or color textures enabled, COLOR%dCNTRL_REG.material_src == REGISTER, but Material %d register (0x%04x) is not initialized.", + "Output XF colors or color textures enabled, COLOR%dCNTRL_REG.ambient_src == REGISTER, but Ambient %d register (0x%04x) is not initialized.", + "Channel %s uses specular function (GX_AF_SPEC), but diffuse function is not GX_DF_NONE.", + "Channel %d performs lighting which requires a normal, but this is not getting sent.", + "Channel %d performs lighting which requires the normal to be transformed by a normal matrix, but current matrix index is (%d), which may be invalid.", + "%s has a value of %sinfinity (%08x), which is probably not intended.", + "%s has a value of NaN (%08x), which is probably not intended.", + "%s has a value of (%f 0x%08x), which might be unintentionally small.", + "%s has a value of (%f 0x%08x), which might be unintentionally large.", + "%d regular textures active, but MatrixIndex1 register (0x%04x) uninitialized.", + "gen_mode register not initialized.", + "Number of XF output textures does not match what downstream units are expecting.", + "Number of XF output colors does not match what downstream units are expecting.", + "Number of all texgens (%d) > max allowed %d.", + "Number of regular(2x4/3x4) type texgens (%d) > max allowed %d.", + "Number of bumpmap type texgens (%d) > max allowed %d.", + "Number of color texgens (%d) > max allowed %d.", + "First color texgen is not referencing COLOR0.", + "Color texgen from COLOR%d is used more than once.", + "Bumpmap texgen is defined, which requires the normal matrix values pointed by current matrix index (%d) to be loaded, however it may not be loaded yet.", + "GX_TEXCOORD%d requires the matrix values pointed by current texture matrix index %d (%d), however it may not be loaded yet.", + "GX_LIGHT%d is being referenced, however it may not be loaded yet.", + "Channel %d performs lighting which requires the normal matrix values pointed to by the current matrix index (%d), however these values may not be loaded yet.", + "Position matrix values pointed to by the current matrix index must be loaded, however they may not be loaded yet.", + "Address 0x%04x is uninitialized.", + "Register (0x%04x) (%s) is not initialized.", + "Display list contains invalid command.", + "Nested display list.", +}; + +#define GX_WARN_4 4 // not in GX_WARN_* + +GXWarningLevel __gxvWarnLev[115] = { + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_4, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_ALL, + GX_WARN_ALL, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_ALL, + GX_WARN_ALL, + GX_WARN_MEDIUM, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_ALL, + GX_WARN_4, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_ALL, + GX_WARN_ALL, + GX_WARN_SEVERE, + GX_WARN_4, + GX_WARN_4, + GX_WARN_4, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_SEVERE, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_MEDIUM, + GX_WARN_SEVERE, + GX_WARN_SEVERE, +}; + +char __gxvDummyStr[256]; + +static void __GXVerifyGlobal(void) +{ +} + +static void __GXVerifyCP(GXVtxFmt fmt) +{ + u32 nrmCnt = GET_REG_FIELD(gx->vatA[fmt], 1, 9); + + if (__gxVerif->verifyLevel >= GX_WARN_SEVERE) { + if (gx->hasNrms && nrmCnt != 0) { + if (__gxVerif->verifyLevel >= __gxvWarnLev[0]) { + sprintf(__gxvDummyStr, __gxvWarnings[0], "GX_NRM_XYZ"); + __gxVerif->cb(__gxvWarnLev[0], 0, __gxvDummyStr); + } + } + else if (gx->hasBiNrms && nrmCnt != 1) { + if (__gxVerif->verifyLevel >= __gxvWarnLev[0]) { + sprintf(__gxvDummyStr, __gxvWarnings[0], "GX_NRM_NBT or GX_NRM_NBT3"); + __gxVerif->cb(__gxvWarnLev[0], 0, __gxvDummyStr); + } + } + } +} + +void __GXVerifyState(GXVtxFmt vtxfmt) +{ + if (__gxVerif->verifyLevel != GX_WARN_NONE) { + __GXVerifyGlobal(); + __GXVerifyCP(vtxfmt); + __GXVerifyXF(); + __GXVerifySU(); + __GXVerifyBUMP(); + __GXVerifyTEX(); + __GXVerifyTEV(); + __GXVerifyPE(); + } +} + +void GXSetVerifyLevel(GXWarningLevel level) +{ + __gxVerif->verifyLevel = level; +} + +GXVerifyCallback GXSetVerifyCallback(GXVerifyCallback cb) +{ + GXVerifyCallback old_cb = __gxVerif->cb; + + __gxVerif->cb = cb; + return old_cb; +} + +#endif // DEBUG diff --git a/src/static/GAEJ01_01/dolphin/gx/GXVert.c b/src/static/GAEJ01_01/dolphin/gx/GXVert.c new file mode 100644 index 00000000..1d94071e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/GXVert.c @@ -0,0 +1,85 @@ +#if DEBUG +#include + +#include "../src/static/GAEJ01_01/dolphin/gx/__gx.h" +#define FUNC_1PARAM(name, T) \ +void name##1##T(T x) { GXWGFifo.T = x; } + +#define FUNC_2PARAM(name, T) \ +void name##2##T(T x, T y) { GXWGFifo.T = x; GXWGFifo.T = y; } + +#define FUNC_3PARAM(name, T) \ +void name##3##T(T x, T y, T z) { GXWGFifo.T = x; GXWGFifo.T = y; GXWGFifo.T = z; } + +#define FUNC_4PARAM(name, T) \ +void name##4##T(T x, T y, T z, T w) { GXWGFifo.T = x; GXWGFifo.T = y; GXWGFifo.T = z; GXWGFifo.T = w; } + +#define FUNC_INDEX8(name) \ +void name##1x8(u8 x) { GXWGFifo.u8 = x; } + +#define FUNC_INDEX16(name) \ +void name##1x16(u16 x) { GXWGFifo.u16 = x; } + +// GXCmd +FUNC_1PARAM(GXCmd, u8) +FUNC_1PARAM(GXCmd, u16) +FUNC_1PARAM(GXCmd, u32) + +// GXParam +FUNC_1PARAM(GXParam, u8) +FUNC_1PARAM(GXParam, u16) +FUNC_1PARAM(GXParam, u32) +FUNC_1PARAM(GXParam, s8) +FUNC_1PARAM(GXParam, s16) +FUNC_1PARAM(GXParam, s32) +FUNC_1PARAM(GXParam, f32) +FUNC_3PARAM(GXParam, f32) +FUNC_4PARAM(GXParam, f32) + +// GXPosition +FUNC_3PARAM(GXPosition, f32) +FUNC_3PARAM(GXPosition, u8) +FUNC_3PARAM(GXPosition, s8) +FUNC_3PARAM(GXPosition, u16) +FUNC_3PARAM(GXPosition, s16) +FUNC_2PARAM(GXPosition, f32) +FUNC_2PARAM(GXPosition, u8) +FUNC_2PARAM(GXPosition, s8) +FUNC_2PARAM(GXPosition, u16) +FUNC_2PARAM(GXPosition, s16) +FUNC_INDEX16(GXPosition) +FUNC_INDEX8(GXPosition) + +// GXNormal +FUNC_3PARAM(GXNormal, f32) +FUNC_3PARAM(GXNormal, s16) +FUNC_3PARAM(GXNormal, s8) +FUNC_INDEX16(GXNormal) +FUNC_INDEX8(GXNormal) + +// GXColor +FUNC_4PARAM(GXColor, u8) +FUNC_1PARAM(GXColor, u32) +FUNC_3PARAM(GXColor, u8) +FUNC_1PARAM(GXColor, u16) +FUNC_INDEX16(GXColor) +FUNC_INDEX8(GXColor) + +// GXTexCoord +FUNC_2PARAM(GXTexCoord, f32) +FUNC_2PARAM(GXTexCoord, s16) +FUNC_2PARAM(GXTexCoord, u16) +FUNC_2PARAM(GXTexCoord, s8) +FUNC_2PARAM(GXTexCoord, u8) +FUNC_1PARAM(GXTexCoord, f32) +FUNC_1PARAM(GXTexCoord, s16) +FUNC_1PARAM(GXTexCoord, u16) +FUNC_1PARAM(GXTexCoord, s8) +FUNC_1PARAM(GXTexCoord, u8) +FUNC_INDEX16(GXTexCoord) +FUNC_INDEX8(GXTexCoord) + +// GXMatrixIndex +FUNC_1PARAM(GXMatrixIndex, u8) + +#endif // DEBUG diff --git a/src/static/GAEJ01_01/dolphin/gx/__gx.h b/src/static/GAEJ01_01/dolphin/gx/__gx.h new file mode 100644 index 00000000..f26785b8 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/gx/__gx.h @@ -0,0 +1,1695 @@ +#ifndef _DOLPHIN_GX_INTERNAL_H_ +#define _DOLPHIN_GX_INTERNAL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Bitfield helpers */ + +#define GX_BITFIELD(field, pos, size, value) (__rlwimi((field), (value), 31 - (pos) - (size) + 1, (pos), (pos) + (size) - 1)) +#define GX_BITFIELD_SET(field, pos, size, value) ((field) = GX_BITFIELD(field, pos, size, value)) +#define GX_BITFIELD_TRUNC(field, pos, size, value) (__rlwimi((field), (value), 0, (pos), (pos) + (size) - 1)) +#define GX_BITGET(field, pos, size) ((field) >> (31 - (pos) - (size) + 1) & ((1 << (size)) - 1)) + +#define GX_REG_MASK(st, end) (((1 << ((end) - (st) + 1)) - 1) << 31 - (end)) +#define GX_GET_REG(reg, st, end) GX_BITGET((reg), (st), ((end) - (st) + 1)) +#define GX_SET_REG(reg, x, st, end) GX_BITFIELD_SET((reg), (st), ((end) - (st) + 1), (x)) +#define GX_SET_TRUNC(reg, x, st, end) GX_BITFIELD_TRUNC((reg), (st), ((end) - (st) + 1), (x)) + +#define GX_LARGE_NUMBER 1.0e+18f + +#define GX_MAX_TLUT 16 +#define GX_MAX_BIGTLUT 4 +#define GX_MAX_TLUT_ALL (GX_MAX_TLUT + GX_MAX_BIGTLUT) + +#define GXCOLOR_AS_U32(color) (*((u32*)&(color))) + +/* Write-gather FIFO */ + +#define GX_WRITE_U8(val) (GXWGFifo.u8 = val) +#define GX_WRITE_U16(val) (GXWGFifo.u16 = val) +#define GX_WRITE_U32(val) (GXWGFifo.u32 = (u32)val) +#define GX_WRITE_F32(val) (GXWGFifo.f32 = (f32)val) + +/* Internal object layouts */ + +typedef struct _GXFifoObjPriv { + void* base; // _00 + void* end; // _04 + u32 size; // _08 + u32 highWatermark; // _0C + u32 lowWatermark; // _10 + void* readPtr; // _14 + void* writePtr; // _18 + s32 rwDistance; // _1C + u8 _20[0x60]; // _20 +} GXFifoObjPriv; + +typedef struct __GXFifoObj { + u8* base; + u8* top; + u32 size; + u32 hiWatermark; + u32 loWatermark; + void* rdPtr; + void* wrPtr; + s32 count; + u8 bind_cpu; + u8 bind_gp; +} __GXFifoObj; + +typedef struct _GXTexObjPriv { + u32 mode0; // _00 + u32 mode1; // _04 + u32 image0; // _08 + u32 image3; // _0C + void* userData; // _10 + GXTexFmt format; // _14 + u32 tlutName; // _18 + u16 loadCount; // _1C + u8 loadFormat; // _1E + u8 flags; // _1F +} GXTexObjPriv; + +typedef struct _GXTexRegionPriv { + u32 unk0; // _00 + u32 unk4; // _04 + u32 unk8; // _08 + u8 unkC; // _0C + u8 unkD; // _0D + u8 padding[2]; // _0E +} GXTexRegionPriv; + +typedef struct _GXTlutObjPriv { + u32 unk0; // _00 + u32 unk4; // _04 + u16 numEntries; // _08 + u8 padding[0x2]; // _0A +} GXTlutObjPriv; + +typedef struct _GXTlutRegionPriv { + u32 unk0; // _00 + GXTlutObjPriv tlutObj; // _04 +} GXTlutRegionPriv; + +typedef struct __GXLightObjPriv { + u32 reserved[3]; // _00 + GXColor color; // _0C + f32 a[3]; // _10 + f32 k[3]; // _1C + f32 lpos[3]; // _28 + f32 ldir[3]; // _34 +} GXLightObjPriv; + +/* Hardware registers */ + +// Flags for setting GXData dirtyState. +typedef enum _GXDirtyFlag { + GX_DIRTY_SU_TEX = (1 << 0), // 0x1 + GX_DIRTY_BP_MASK = (1 << 1), // 0x2 + GX_DIRTY_GEN_MODE = (1 << 2), // 0x4 + GX_DIRTY_VCD = (1 << 3), // 0x8 + GX_DIRTY_VAT = (1 << 4), // 0x10 + // . . . + GX_DIRTY_AMB_COLOR0 = (1 << 8), // 0x100 + GX_DIRTY_AMB_COLOR1 = (1 << 9), // 0x200 + GX_DIRTY_MAT_COLOR0 = (1 << 10), // 0x400 + GX_DIRTY_MAT_COLOR1 = (1 << 11), // 0x800 + GX_DIRTY_CHAN_COLOR0 = (1 << 12), // 0x1000 + GX_DIRTY_CHAN_COLOR1 = (1 << 13), // 0x2000 + GX_DIRTY_CHAN_ALPHA0 = (1 << 14), // 0x4000 + GX_DIRTY_CHAN_ALPHA1 = (1 << 15), // 0x8000 + GX_DIRTY_TEX0 = (1 << 16), // 0x10000 + GX_DIRTY_TEX1 = (1 << 17), // 0x20000 + GX_DIRTY_TEX2 = (1 << 18), // 0x40000 + GX_DIRTY_TEX3 = (1 << 19), // 0x80000 + GX_DIRTY_TEX4 = (1 << 20), // 0x100000 + GX_DIRTY_TEX5 = (1 << 21), // 0x200000 + GX_DIRTY_TEX6 = (1 << 22), // 0x400000 + GX_DIRTY_TEX7 = (1 << 23), // 0x800000 + GX_DIRTY_NUM_COLORS = (1 << 24), // 0x1000000 + GX_DIRTY_NUM_TEX = (1 << 25), // 0x2000000 + GX_DIRTY_MTX_IDX = (1 << 26), // 0x4000000 + GX_DIRTY_PROJECTION = (1 << 27), // 0x8000000 + GX_DIRTY_VIEWPORT = (1 << 28), // 0x10000000 + + GX_AMB_MAT_MASK = GX_DIRTY_AMB_COLOR0 | GX_DIRTY_AMB_COLOR1 | GX_DIRTY_MAT_COLOR0 | GX_DIRTY_MAT_COLOR1, // 0xF00 + + GX_LIGHT_CHAN_MASK = GX_DIRTY_CHAN_COLOR0 | GX_DIRTY_CHAN_COLOR1 | GX_DIRTY_CHAN_ALPHA0 | GX_DIRTY_CHAN_ALPHA1 + | GX_DIRTY_NUM_COLORS, // 0x100F000 + + GX_TEX_GEN_MASK = 0x2FF0000, // all GX_DIRTY_TEXs | GX_DIRTY_NUM_TEX +} GXDirtyFlag; + +// Commands for interacting with the GXFifo pipe. +typedef enum _GXFifoCmd { + GX_FIFO_CMD_NOOP = 0x00, // no operation + + GX_FIFO_CMD_LOAD_BP_REG = 0x61, // load blitting processor reg + GX_FIFO_CMD_LOAD_CP_REG = 0x08, // load command processor reg + GX_FIFO_CMD_LOAD_XF_REG = 0x10, // load transform unit reg + + GX_FIFO_CMD_LOAD_INDX_A = 0x20, // load index A + GX_FIFO_CMD_LOAD_INDX_B = 0x28, // load index B + GX_FIFO_CMD_LOAD_INDX_C = 0x30, // load index C + GX_FIFO_CMD_LOAD_INDX_D = 0x38, // load index D + + GX_FIFO_CMD_CALL_DL = 0x40, // call displaylist + GX_FIFO_CMD_INVAL_VTX = 0x48, // invalid vertex + +} GXFifoCmd; + +// Texture register fields for XF (transform) unit. +typedef enum _GXXfTexReg { + GX_XF_TEX_PROJ_ST = 0, // (s,t) (2x4) + GX_XF_TEX_PROJ_STQ = 1, // (s,t,q) (3x4) + + GX_XF_TEX_FORM_AB11 = 0, // (A, B, 1.0f, 1.0f), used for regular tex src + GX_XF_TEX_FORM_ABC1 = 1, // (A, B, C, 1.0f), used for geometry/normal src +} GXXfTexReg; + +// General texture commands. +typedef enum _GXXfTexGen { + GX_XF_TG_REGULAR = 0, // Regular; transform incoming data. + GX_XF_TG_BUMP = 1, // Texgen bump mapping. + GX_XF_TG_CLR0 = 2, // Color texgen for color 0 (s,t) = (r, g:b) + GX_XF_TG_CLR1 = 3, // Color texgen for color 1 (s,t) = (r, g:b) +} GXXfTexGen; + +// Transform memory types. +typedef enum _GXXfMem { + GX_XF_MEM_POSMTX = 0x000, // position coord matrix + GX_XF_MEM_NRMMTX = 0x400, // normal coord matrix + GX_XF_MEM_DUALTEXMTX = 0x500, // dual texture matrix + GX_XF_MEM_LIGHTOBJ = 0x600, // light object +} GXXfMem; + +// Blitting processor registers. +typedef enum _GXBPRegs { + // gen mode + GX_BP_REG_GENMODE = 0x0, // gen mode + + // display copy filters + GX_BP_REG_DISPCOPYFILTER0 = 0x1, // display copy filter 0 + GX_BP_REG_DISPCOPYFILTER1 = 0x2, // display copy filter 1 + GX_BP_REG_DISPCOPYFILTER2 = 0x3, // display copy filter 2 + GX_BP_REG_DISPCOPYFILTER3 = 0x4, // display copy filter 3 + + // indirect matrices + GX_BP_REG_INDMTX0A = 0x6, // indirect matrix 0A + GX_BP_REG_INDMTX0B = 0x7, // indirect matrix 0B + GX_BP_REG_INDMTX0C = 0x8, // indirect matrix 0C + GX_BP_REG_INDMTX1A = 0x9, // indirect matrix 1A + GX_BP_REG_INDMTX1B = 0xA, // indirect matrix 1B + GX_BP_REG_INDMTX1C = 0xB, // indirect matrix 1C + GX_BP_REG_INDMTX2A = 0xC, // indirect matrix 2A + GX_BP_REG_INDMTX2B = 0xD, // indirect matrix 2B + GX_BP_REG_INDMTX2C = 0xE, // indirect matrix 2C + GX_BP_REG_INDIMASK = 0xF, // indirect mask + + // indirect TEV stages + GX_BP_REG_INDTEVSTAGE0 = 0x10, // indirect TEV stage 0 + GX_BP_REG_INDTEVSTAGE1 = 0x11, // indirect TEV stage 1 + GX_BP_REG_INDTEVSTAGE2 = 0x12, // indirect TEV stage 2 + GX_BP_REG_INDTEVSTAGE3 = 0x13, // indirect TEV stage 3 + GX_BP_REG_INDTEVSTAGE4 = 0x14, // indirect TEV stage 4 + GX_BP_REG_INDTEVSTAGE5 = 0x15, // indirect TEV stage 5 + GX_BP_REG_INDTEVSTAGE6 = 0x16, // indirect TEV stage 6 + GX_BP_REG_INDTEVSTAGE7 = 0x17, // indirect TEV stage 7 + GX_BP_REG_INDTEVSTAGE8 = 0x18, // indirect TEV stage 8 + GX_BP_REG_INDTEVSTAGE9 = 0x19, // indirect TEV stage 9 + GX_BP_REG_INDTEVSTAGE10 = 0x1A, // indirect TEV stage 10 + GX_BP_REG_INDTEVSTAGE11 = 0x1B, // indirect TEV stage 11 + GX_BP_REG_INDTEVSTAGE12 = 0x1C, // indirect TEV stage 12 + GX_BP_REG_INDTEVSTAGE13 = 0x1D, // indirect TEV stage 13 + GX_BP_REG_INDTEVSTAGE14 = 0x1E, // indirect TEV stage 14 + GX_BP_REG_INDTEVSTAGE15 = 0x1F, // indirect TEV stage 15 + + // performance manips + GX_BP_REG_SCISSORTL = 0x20, // scissor top left + GX_BP_REG_SCISSORBR = 0x21, // scissor bottom right + GX_BP_REG_LINEPTWIDTH = 0x22, // line point width + GX_BP_REG_PERF0TRI = 0x23, // performance 0 (triangle) + GX_BP_REG_PERF0QUAD = 0x24, // performance 0 (quad) + + // rasters + GX_BP_REG_RAS1_SS0 = 0x25, + GX_BP_REG_RAS1_SS1 = 0x26, + GX_BP_REG_RAS1_IREF = 0x27, + GX_BP_REG_RAS1_TREF0 = 0x28, + GX_BP_REG_RAS1_TREF1 = 0x29, + GX_BP_REG_RAS1_TREF2 = 0x2A, + GX_BP_REG_RAS1_TREF3 = 0x2B, + GX_BP_REG_RAS1_TREF4 = 0x2C, + GX_BP_REG_RAS1_TREF5 = 0x2D, + GX_BP_REG_RAS1_TREF6 = 0x2E, + GX_BP_REG_RAS1_TREF7 = 0x2F, + + // setup sizes + GX_BP_REG_SU_SSIZE0 = 0x30, + GX_BP_REG_SU_TSIZE0 = 0x31, + GX_BP_REG_SU_SSIZE1 = 0x32, + GX_BP_REG_SU_TSIZE1 = 0x33, + GX_BP_REG_SU_SSIZE2 = 0x34, + GX_BP_REG_SU_TSIZE2 = 0x35, + GX_BP_REG_SU_SSIZE3 = 0x36, + GX_BP_REG_SU_TSIZE3 = 0x37, + GX_BP_REG_SU_SSIZE4 = 0x38, + GX_BP_REG_SU_TSIZE4 = 0x39, + GX_BP_REG_SU_SSIZE5 = 0x3A, + GX_BP_REG_SU_TSIZE5 = 0x3B, + GX_BP_REG_SU_SSIZE6 = 0x3C, + GX_BP_REG_SU_TSIZE6 = 0x3D, + GX_BP_REG_SU_SSIZE7 = 0x3E, + GX_BP_REG_SU_TSIZE7 = 0x3F, + + // Z and blend controls + GX_BP_REG_ZMODE = 0x40, + GX_BP_REG_BLENDMODE = 0x41, + GX_BP_REG_DSTALPHA = 0x42, + GX_BP_REG_ZCONTROL = 0x43, + GX_BP_REG_FIELDMASK = 0x44, + GX_BP_REG_DRAWDONE = 0x45, + GX_BP_REG_PETOKEN = 0x47, + GX_BP_REG_PETOKENINT = 0x48, + + // copying + GX_BP_REG_TEXCOPYSRCXY = 0x49, + GX_BP_REG_TEXCOPYSRCWH = 0x4A, + GX_BP_REG_TEXCOPYDST = 0x4B, + GX_BP_REG_DISPCOPYSTRIDE = 0x4D, + GX_BP_REG_DISPCOPYSCALEY = 0x4E, + GX_BP_REG_COPYCLEARAR = 0x4F, + GX_BP_REG_COPYCLEARGB = 0x50, + GX_BP_REG_COPYCLEARZ = 0x51, + GX_BP_REG_COPYFILTER0 = 0x53, + GX_BP_REG_COPYFILTER1 = 0x54, + + // + GX_BP_REG_BOUNDINGBOX0 = 0x55, + GX_BP_REG_BOUNDINGBOX1 = 0x56, + + GX_BP_REG_SCISSOROFFSET = 0x59, + + // texture memory + GX_BP_REG_TMEMPRELOADADDR = 0x60, + GX_BP_REG_TMEMPRELOADEVEN = 0x61, + GX_BP_REG_TMEMPRELOADODD = 0x62, + GX_BP_REG_TMEMPRELOADMODE = 0x63, + GX_BP_REG_TMEMTLUTSRC = 0x64, + GX_BP_REG_TMEMTLUTDST = 0x65, + GX_BP_REG_TMEMTEXINVALIDATE = 0x66, + + // performance 1 + GX_BP_REG_PERF1 = 0x67, + GX_BP_REG_FIELDMODE = 0x68, + + // set modes + GX_BP_REG_SETMODE0_TEX0 = 0x80, + GX_BP_REG_SETMODE0_TEX1 = 0x81, + GX_BP_REG_SETMODE0_TEX2 = 0x82, + GX_BP_REG_SETMODE0_TEX3 = 0x83, + GX_BP_REG_SETMODE1_TEX0 = 0x84, + GX_BP_REG_SETMODE1_TEX1 = 0x85, + GX_BP_REG_SETMODE1_TEX2 = 0x86, + GX_BP_REG_SETMODE1_TEX3 = 0x87, + + // set images + GX_BP_REG_SETIMAGE0_TEX0 = 0x88, + GX_BP_REG_SETIMAGE0_TEX1 = 0x89, + GX_BP_REG_SETIMAGE0_TEX2 = 0x8A, + GX_BP_REG_SETIMAGE0_TEX3 = 0x8B, + GX_BP_REG_SETIMAGE1_TEX0 = 0x8C, + GX_BP_REG_SETIMAGE1_TEX1 = 0x8D, + GX_BP_REG_SETIMAGE1_TEX2 = 0x8E, + GX_BP_REG_SETIMAGE1_TEX3 = 0x8F, + GX_BP_REG_SETIMAGE2_TEX0 = 0x90, + GX_BP_REG_SETIMAGE2_TEX1 = 0x91, + GX_BP_REG_SETIMAGE2_TEX2 = 0x92, + GX_BP_REG_SETIMAGE2_TEX3 = 0x93, + GX_BP_REG_SETIMAGE3_TEX0 = 0x94, + GX_BP_REG_SETIMAGE3_TEX1 = 0x95, + GX_BP_REG_SETIMAGE3_TEX2 = 0x96, + GX_BP_REG_SETIMAGE3_TEX3 = 0x97, + + // set texture lookups + GX_BP_REG_SETTLUT_TEX0 = 0x98, + GX_BP_REG_SETTLUT_TEX1 = 0x99, + GX_BP_REG_SETTLUT_TEX2 = 0x9A, + GX_BP_REG_SETTLUT_TEX3 = 0x9B, + + // set modes continued + GX_BP_REG_SETMODE0_TEX4 = 0xA0, + GX_BP_REG_SETMODE0_TEX5 = 0xA1, + GX_BP_REG_SETMODE0_TEX6 = 0xA2, + GX_BP_REG_SETMODE0_TEX7 = 0xA3, + GX_BP_REG_SETMODE1_TEX4 = 0xA4, + GX_BP_REG_SETMODE1_TEX5 = 0xA5, + GX_BP_REG_SETMODE1_TEX6 = 0xA6, + GX_BP_REG_SETMODE1_TEX7 = 0xA7, + + // set images continued + GX_BP_REG_SETIMAGE0_TEX4 = 0xA8, + GX_BP_REG_SETIMAGE0_TEX5 = 0xA9, + GX_BP_REG_SETIMAGE0_TEX6 = 0xAA, + GX_BP_REG_SETIMAGE0_TEX7 = 0xAB, + GX_BP_REG_SETIMAGE1_TEX4 = 0xAC, + GX_BP_REG_SETIMAGE1_TEX5 = 0xAD, + GX_BP_REG_SETIMAGE1_TEX6 = 0xAE, + GX_BP_REG_SETIMAGE1_TEX7 = 0xAF, + GX_BP_REG_SETIMAGE2_TEX4 = 0xB0, + GX_BP_REG_SETIMAGE2_TEX5 = 0xB1, + GX_BP_REG_SETIMAGE2_TEX6 = 0xB2, + GX_BP_REG_SETIMAGE2_TEX7 = 0xB3, + GX_BP_REG_SETIMAGE3_TEX4 = 0xB4, + GX_BP_REG_SETIMAGE3_TEX5 = 0xB5, + GX_BP_REG_SETIMAGE3_TEX6 = 0xB6, + GX_BP_REG_SETIMAGE3_TEX7 = 0xB7, + + // set texture lookups continued + GX_BP_REG_SETTLUT_TEX4 = 0xB8, + GX_BP_REG_SETTLUT_TEX5 = 0xB9, + GX_BP_REG_SETTLUT_TEX6 = 0xBA, + GX_BP_REG_SETTLUT_TEX7 = 0xBB, + + // TEV color manips + GX_BP_REG_TEVCOLORCOMBINER0 = 0xC0, + GX_BP_REG_TEVALPHACOMBINER0 = 0xC1, + GX_BP_REG_TEVCOLORCOMBINER1 = 0xC2, + GX_BP_REG_TEVALPHACOMBINER1 = 0xC3, + GX_BP_REG_TEVCOLORCOMBINER2 = 0xC4, + GX_BP_REG_TEVALPHACOMBINER2 = 0xC5, + GX_BP_REG_TEVCOLORCOMBINER3 = 0xC6, + GX_BP_REG_TEVALPHACOMBINER3 = 0xC7, + GX_BP_REG_TEVCOLORCOMBINER4 = 0xC8, + GX_BP_REG_TEVALPHACOMBINER4 = 0xC9, + GX_BP_REG_TEVCOLORCOMBINER5 = 0xCA, + GX_BP_REG_TEVALPHACOMBINER5 = 0xCB, + GX_BP_REG_TEVCOLORCOMBINER6 = 0xCC, + GX_BP_REG_TEVALPHACOMBINER6 = 0xCD, + GX_BP_REG_TEVCOLORCOMBINER7 = 0xCE, + GX_BP_REG_TEVALPHACOMBINER7 = 0xCF, + GX_BP_REG_TEVCOLORCOMBINER8 = 0xD0, + GX_BP_REG_TEVALPHACOMBINER8 = 0xD1, + GX_BP_REG_TEVCOLORCOMBINER9 = 0xD2, + GX_BP_REG_TEVALPHACOMBINER9 = 0xD3, + GX_BP_REG_TEVCOLORCOMBINER10 = 0xD4, + GX_BP_REG_TEVALPHACOMBINER10 = 0xD5, + GX_BP_REG_TEVCOLORCOMBINER11 = 0xD6, + GX_BP_REG_TEVALPHACOMBINER11 = 0xD7, + GX_BP_REG_TEVCOLORCOMBINER12 = 0xD8, + GX_BP_REG_TEVALPHACOMBINER12 = 0xD9, + GX_BP_REG_TEVCOLORCOMBINER13 = 0xDA, + GX_BP_REG_TEVALPHACOMBINER13 = 0xDB, + GX_BP_REG_TEVCOLORCOMBINER14 = 0xDC, + GX_BP_REG_TEVALPHACOMBINER14 = 0xDD, + GX_BP_REG_TEVCOLORCOMBINER15 = 0xDE, + GX_BP_REG_TEVALPHACOMBINER15 = 0xDF, + + // TEV registers + GX_BP_REG_TEVREG0LO = 0xE0, + GX_BP_REG_TEVREG0HI = 0xE1, + GX_BP_REG_TEVREG1LO = 0xE2, + GX_BP_REG_TEVREG1HI = 0xE3, + GX_BP_REG_TEVREG2LO = 0xE4, + GX_BP_REG_TEVREG2HI = 0xE5, + GX_BP_REG_TEVREG3LO = 0xE6, + GX_BP_REG_TEVREG3HI = 0xE7, + + // fog registers + GX_BP_REG_FOGRANGE = 0xE8, + GX_BP_REG_FOGRANGEK0 = 0xE9, + GX_BP_REG_FOGRANGEK1 = 0xEA, + GX_BP_REG_FOGRANGEK2 = 0xEB, + GX_BP_REG_FOGRANGEK3 = 0xEC, + GX_BP_REG_FOGRANGEK4 = 0xED, + GX_BP_REG_FOGPARAM0 = 0xEE, + GX_BP_REG_FOGPARAM1 = 0xEF, + GX_BP_REG_FOGPARAM2 = 0xF0, + GX_BP_REG_FOGPARAM3 = 0xF1, + GX_BP_REG_FOGCOLOR = 0xF2, + + // performance manip registers + GX_BP_REG_ALPHACOMPARE = 0xF3, + GX_BP_REG_ZTEXTURE0 = 0xF4, + GX_BP_REG_ZTEXTURE1 = 0xF5, + + // TEV K selectors + GX_BP_REG_TEVKSEL0 = 0xF6, + GX_BP_REG_TEVKSEL1 = 0xF7, + GX_BP_REG_TEVKSEL2 = 0xF8, + GX_BP_REG_TEVKSEL3 = 0xF9, + GX_BP_REG_TEVKSEL4 = 0xFA, + GX_BP_REG_TEVKSEL5 = 0xFB, + GX_BP_REG_TEVKSEL6 = 0xFC, + GX_BP_REG_TEVKSEL7 = 0xFD, + + // SS mask + GX_BP_REG_SSMASK = 0xFE, +} GXBPRegs; + +// Command processor registers. +typedef enum _GXCPRegs { + GX_CP_REG_MTXIDXA = 0x30, // Matrix index A + GX_CP_REG_MTXIDXB = 0x40, // Matrix index B + GX_CP_REG_VCD_LO = 0x50, // Vertex descriptor (lo) + GX_CP_REG_VCD_HI = 0x60, // Vertex descriptor (hi) + GX_CP_REG_VAT_GRP0 = 0x70, // Vertex attribute table (group 0) + GX_CP_REG_VAT_GRP1 = 0x80, // Vertex attribute table (group 1) + GX_CP_REG_VAT_GRP2 = 0x90, // Vertex attribute table (group 2) + GX_CP_REG_ARRAYBASE = 0xA0, // Vertex array start/base + GX_CP_REG_ARRAYSTRIDE = 0xB0, // Vertex array stride +} GXCPRegs; + +// Transform unit registers. +typedef enum _GXXFRegs { + GX_XF_REG_ERROR = 0x1000, + GX_XF_REG_DIAGNOSTICS = 0x1001, + GX_XF_REG_STATE0 = 0x1002, + GX_XF_REG_STATE1 = 0x1003, + GX_XF_REG_CLOCK = 0x1004, + GX_XF_REG_CLIPDISABLE = 0x1005, + GX_XF_REG_PERF0 = 0x1006, + GX_XF_REG_PERF1 = 0x1007, + GX_XF_REG_INVERTEXSPEC = 0x1008, + GX_XF_REG_NUMCOLORS = 0x1009, + GX_XF_REG_AMBIENT0 = 0x100A, + GX_XF_REG_AMBIENT1 = 0x100B, + GX_XF_REG_MATERIAL0 = 0x100C, + GX_XF_REG_MATERIAL1 = 0x100D, + GX_XF_REG_COLOR0CNTRL = 0x100E, + GX_XF_REG_COLOR1CNTRL = 0x100F, + GX_XF_REG_ALPHA0CNTRL = 0x1010, + GX_XF_REG_ALPHA1CNTRL = 0x1011, + GX_XF_REG_DUALTEXTRAN = 0x1012, + GX_XF_REG_MATRIXINDEX0 = 0x1018, + GX_XF_REG_MATRIXINDEX1 = 0x1019, + GX_XF_REG_SCALEX = 0x101A, + GX_XF_REG_SCALEY = 0x101B, + GX_XF_REG_SCALEZ = 0x101C, + GX_XF_REG_OFFSETX = 0x101D, + GX_XF_REG_OFFSETY = 0x101E, + GX_XF_REG_OFFSETZ = 0x101F, + GX_XF_REG_PROJECTIONA = 0x1020, + GX_XF_REG_PROJECTIONB = 0x1021, + GX_XF_REG_PROJECTIONC = 0x1022, + GX_XF_REG_PROJECTIOND = 0x1023, + GX_XF_REG_PROJECTIONE = 0x1024, + GX_XF_REG_PROJECTIONF = 0x1025, + GX_XF_REG_PROJECTORTHO = 0x1026, + GX_XF_REG_NUMTEX = 0x103F, + GX_XF_REG_TEX0 = 0x1040, + GX_XF_REG_TEX1 = 0x1041, + GX_XF_REG_TEX2 = 0x1042, + GX_XF_REG_TEX3 = 0x1043, + GX_XF_REG_TEX4 = 0x1044, + GX_XF_REG_TEX5 = 0x1045, + GX_XF_REG_TEX6 = 0x1046, + GX_XF_REG_TEX7 = 0x1047, + GX_XF_REG_DUALTEX0 = 0x1050, + GX_XF_REG_DUALTEX1 = 0x1051, + GX_XF_REG_DUALTEX2 = 0x1052, + GX_XF_REG_DUALTEX3 = 0x1053, + GX_XF_REG_DUALTEX4 = 0x1054, + GX_XF_REG_DUALTEX5 = 0x1055, + GX_XF_REG_DUALTEX6 = 0x1056, + GX_XF_REG_DUALTEX7 = 0x1057, +} GXXFRegs; + +#define XF_REG_TEX(proj, form, tgType, row, embossRow, embossLit) \ + ((proj) << 1 | (form) << 2 | (tgType) << 4 | (row) << 7 | (embossRow) << 12 | (embossLit) << 15) + +// BP GenMode locators. +typedef enum _GXBPGenMode { + // Active texture counts [28-31] + GX_BP_GENMODE_NUMTEX_ST = 28, + GX_BP_GENMODE_NUMTEX_END = 31, + + // Color/channel counts [25-27] + GX_BP_GENMODE_NUMCOLORS_ST = 25, + GX_BP_GENMODE_NUMCOLORS_END = 27, + + // Multisample mode [22-22] + GX_BP_GENMODE_MULTISAMPLE_ST = 22, + GX_BP_GENMODE_MULTISAMPLE_END = 22, + + // Cull mode [16-17] + GX_BP_GENMODE_CULLMODE_ST = 16, + GX_BP_GENMODE_CULLMODE_END = 17, + + // Indirect stage counts [13-15] + GX_BP_GENMODE_NUMINDSTAGES_ST = 13, + GX_BP_GENMODE_NUMINDSTAGES_END = 15, + + // Toggle co-planar/Z-freeze [12-12] + GX_BP_GENMODE_COPLANAR_ST = 12, + GX_BP_GENMODE_COPLANAR_END = 12, +} GXBPGenMode; + +// BP locators for indirect texture matrices (same for A, B, and C). +typedef enum _GXBPIndMtx { + // Texture offset matrix [0][0] [21-31] + GX_BP_INDMTX_M00_ST = 21, + GX_BP_INDMTX_M00_END = 31, + + // Texture offset matrix [1][0] [10-20] + GX_BP_INDMTX_M10_ST = 10, + GX_BP_INDMTX_M10_END = 20, + + // Texture scaling exponent (2^x) [8-9] + GX_BP_INDMTX_EXP_ST = 8, + GX_BP_INDMTX_EXP_END = 9, +} GXBPIndMtx; + +// BP locators for indirect texture masks. +typedef enum _GXBPIndIMask { + // Indirect mask [24-31] + GX_BP_INDIMASK_ST = 24, + GX_BP_INDIMASK_END = 31, +} GXBPIndIMask; + +// BP locators for indirect texture environment details. +typedef enum _GXBPIndTevStage { + // Indirect texture stage ID [30-31] + GX_BP_INDTEV_STAGE_ST = 30, + GX_BP_INDTEV_STAGE_END = 31, + + // Indirect texture format [28-29] + GX_BP_INDTEV_FMT_ST = 28, + GX_BP_INDTEV_FMT_END = 29, + + // Indirect texture bias [25-27] + GX_BP_INDTEV_BIAS_ST = 25, + GX_BP_INDTEV_BIAS_END = 27, + + // Indirect texture alpha [23-24] + GX_BP_INDTEV_ALPHA_ST = 23, + GX_BP_INDTEV_ALPHA_END = 24, + + // Indirect texture matrices [19-22] + GX_BP_INDTEV_MTX_ST = 19, + GX_BP_INDTEV_MTX_END = 22, + + // Indirect texture S component wrap factor [16-18] + GX_BP_INDTEV_WRAPS_ST = 16, + GX_BP_INDTEV_WRAPS_END = 18, + + // Indirect texture T component wrap factor [13-15] + GX_BP_INDTEV_WRAPT_ST = 13, + GX_BP_INDTEV_WRAPT_END = 15, + + // Indirect texture unmodified texcoord setting (for mipmaps) [12-12] + GX_BP_INDTEV_UNMODTEXCOORD_ST = 12, + GX_BP_INDTEV_UNMODTEXCOORD_END = 12, + + // Indirect texture add previous results setting [11-11] + GX_BP_INDTEV_ADDPREV_ST = 11, + GX_BP_INDTEV_ADDPREV_END = 11, +} GXBPIndTevStage; + +// BP locators for top-left scissor. +typedef enum _GXBPScissorTL { + // Top component [21-31] + GX_BP_SCISSORTL_TOP_ST = 21, + GX_BP_SCISSORTL_TOP_END = 31, + + // Left component [9-19] + GX_BP_SCISSORTL_LEFT_ST = 9, + GX_BP_SCISSORTL_LEFT_END = 19, +} GXBPScissorTL; + +// BP locators for bottom-right scissor. +typedef enum _GXBPScissorBR { + // Bottom component [21-31] + GX_BP_SCISSORBR_BOT_ST = 21, + GX_BP_SCISSORBR_BOT_END = 31, + + // Right component [9-19] + GX_BP_SCISSORBR_RIGHT_ST = 9, + GX_BP_SCISSORBR_RIGHT_END = 19, +} GXBPScissorBR; + +// BP locators for line and point settings. +typedef enum _GXBPLinePtWidth { + // Line size/width [24-31] + GX_BP_LINEPTWIDTH_LINESZ_ST = 24, + GX_BP_LINEPTWIDTH_LINESZ_END = 31, + + // Point size [16-23] + GX_BP_LINEPTWIDTH_POINTSZ_ST = 16, + GX_BP_LINEPTWIDTH_POINTSZ_END = 23, + + // Line offset [13-15] + GX_BP_LINEPTWIDTH_LINEOFS_ST = 13, + GX_BP_LINEPTWIDTH_LINEOFS_END = 15, + + // Point offset [10-12] + GX_BP_LINEPTWIDTH_POINTOFS_ST = 10, + GX_BP_LINEPTWIDTH_POINTOFS_END = 12, + + // Interlacing adjustment for aspect ratio [9-9] + GX_BP_LINEPTWIDTH_ADJUST_ST = 9, + GX_BP_LINEPTWIDTH_ADJUST_END = 9, +} GXBPLinePtWidth; + +// BP locators for raster 1 SS0. +typedef enum _GXBPRas1SS0 { + // S-component scale (stage 0) [28-31] + GX_BP_RAS1_SS0_S0_ST = 28, + GX_BP_RAS1_SS0_S0_END = 31, + + // T-component scale (stage 0) [24-27] + GX_BP_RAS1_SS0_T0_ST = 24, + GX_BP_RAS1_SS0_T0_END = 27, + + // S-component scale (stage 1) [20-23] + GX_BP_RAS1_SS0_S1_ST = 20, + GX_BP_RAS1_SS0_S1_END = 23, + + // T-component scale (stage 1) [16-19] + GX_BP_RAS1_SS0_T1_ST = 16, + GX_BP_RAS1_SS0_T1_END = 19, +} GXBPRas1SS0; + +// BP locators for raster 1 SS1. +typedef enum _GXBPRas1SS1 { + // S-component scale (stage 2) [28-31] + GX_BP_RAS1_SS1_S2_ST = 28, + GX_BP_RAS1_SS1_S2_END = 31, + + // T-component scale (stage 2) [24-27] + GX_BP_RAS1_SS1_T2_ST = 24, + GX_BP_RAS1_SS1_T2_END = 27, + + // S-component scale (stage 3) [20-23] + GX_BP_RAS1_SS1_S3_ST = 20, + GX_BP_RAS1_SS1_S3_END = 23, + + // T-component scale (stage 3) [16-19] + GX_BP_RAS1_SS1_T3_ST = 16, + GX_BP_RAS1_SS1_T3_END = 19, +} GXBPRas1SS1; + +// BP locators for raster 1 ID-reference. +typedef enum _GXBPRasIRef { + // Texmap ID (stage 0) [29-31] + GX_BP_RAS1_IREF_MAP0_ST = 29, + GX_BP_RAS1_IREF_MAP0_END = 31, + + // Texcoord ID (stage 0) [26-28] + GX_BP_RAS1_IREF_TXC0_ST = 26, + GX_BP_RAS1_IREF_TXC0_END = 28, + + // Texmap ID (stage 1) [23-25] + GX_BP_RAS1_IREF_MAP1_ST = 23, + GX_BP_RAS1_IREF_MAP1_END = 25, + + // Texcoord ID (stage 1) [20-22] + GX_BP_RAS1_IREF_TXC1_ST = 20, + GX_BP_RAS1_IREF_TXC1_END = 22, + + // Texmap ID (stage 2) [17-19] + GX_BP_RAS1_IREF_MAP2_ST = 17, + GX_BP_RAS1_IREF_MAP2_END = 19, + + // Texcoord ID (stage 2) [14-16] + GX_BP_RAS1_IREF_TXC2_ST = 14, + GX_BP_RAS1_IREF_TXC2_END = 16, + + // Texmap ID (stage 3) [11-13] + GX_BP_RAS1_IREF_MAP3_ST = 11, + GX_BP_RAS1_IREF_MAP3_END = 13, + + // Texcoord ID (stage 3) [8-10] + GX_BP_RAS1_IREF_TXC3_ST = 8, + GX_BP_RAS1_IREF_TXC3_END = 10, +} GXBPRasIRef; + +// BP locators for setup size. +typedef enum _GXBPSUSSize { + // Use line offsets [13-13] + GX_BP_SU_SSIZE_USELINEOFS_ST = 13, + GX_BP_SU_SSIZE_USELINEOFS_END = 13, + + // Use point offsets [12-12] + GX_BP_SU_SSIZE_USEPTOFS_ST = 12, + GX_BP_SU_SSIZE_USEPTOFS_END = 12, +} GXBPSUSSize; + +// BP locators for Z mode. +typedef enum _GXBPZMode { + // Test enable [31-31] + GX_BP_ZMODE_TEST_ENABLE_ST = 31, + GX_BP_ZMODE_TEST_ENABLE_END = 31, + + // Compare [28-30] + GX_BP_ZMODE_COMPARE_ST = 28, + GX_BP_ZMODE_COMPARE_END = 30, + + // Update enable [27-27] + GX_BP_ZMODE_UPDATE_ENABLE_ST = 27, + GX_BP_ZMODE_UPDATE_ENABLE_END = 27, +} GXBPZMode; + +// BP locators for blend mode. +typedef enum _GXBPBlendMode { + // Blend enable [31-31] + GX_BP_BLENDMODE_ENABLE_ST = 31, + GX_BP_BLENDMODE_ENABLE_END = 31, + + // Logic operation enable [30-30] + GX_BP_BLENDMODE_LOGIC_OP_ST = 30, + GX_BP_BLENDMODE_LOGIC_OP_END = 30, + + // Dither [29-29] + GX_BP_BLENDMODE_DITHER_ST = 29, + GX_BP_BLENDMODE_DITHER_END = 29, + + // Color update [28-28] + GX_BP_BLENDMODE_COLOR_UPDATE_ST = 28, + GX_BP_BLENDMODE_COLOR_UPDATE_END = 28, + + // Alpha update [27-27] + GX_BP_BLENDMODE_ALPHA_UPDATE_ST = 27, + GX_BP_BLENDMODE_ALPHA_UPDATE_END = 27, + + // Destination factor [24-26] + GX_BP_BLENDMODE_DSTFACTOR_ST = 24, + GX_BP_BLENDMODE_DSTFACTOR_END = 26, + + // Source factor [21-23] + GX_BP_BLENDMODE_SRCFACTOR_ST = 21, + GX_BP_BLENDMODE_SRCFACTOR_END = 23, + + // Subtract [20-20] + GX_BP_BLENDMODE_SUBTRACT_ST = 20, + GX_BP_BLENDMODE_SUBTRACT_END = 20, + + // Logic mode [16-19] + GX_BP_BLENDMODE_LOGICMODE_ST = 16, + GX_BP_BLENDMODE_LOGICMODE_END = 19, +} GXBPBlendMode; + +// BP locators for destination alpha. +typedef enum _GXBPDstAlpha { + // Alpha [24-31] + GX_BP_DSTALPHA_ALPHA_ST = 24, + GX_BP_DSTALPHA_ALPHA_END = 31, + + // Enable [23-23] + GX_BP_DSTALPHA_ENABLE_ST = 23, + GX_BP_DSTALPHA_ENABLE_END = 23, + + // YUV format [21-22] + GX_BP_DSTALPHA_YUV_FMT_ST = 21, + GX_BP_DSTALPHA_YUV_FMT_END = 22, +} GXBPDstAlpha; + +// BP locators for Z control. +typedef enum _GXBPZControl { + // Pixel format [29-31] + GX_BP_ZCONTROL_PIXEL_FMT_ST = 29, + GX_BP_ZCONTROL_PIXEL_FMT_END = 31, + + // Z format [26-28] + GX_BP_ZCONTROL_Z_FMT_ST = 26, + GX_BP_ZCONTROL_Z_FMT_END = 28, + + // Whether to do Z-buffering before or after texturing [25-25] + GX_BP_ZCONTROL_BEFORE_TEX_ST = 25, + GX_BP_ZCONTROL_BEFORE_TEX_END = 25, +} GXBPZControl; + +// BP locators for field mask. +typedef enum _GXBPFieldMask { + // Whether to write odd fields to the EFB [31-31] + GX_BP_FIELDMASK_ODD_ST = 31, + GX_BP_FIELDMASK_ODD_END = 31, + + // Whether to write even fields to the EFB [30-30] + GX_BP_FIELDMASK_EVEN_ST = 30, + GX_BP_FIELDMASK_EVEN_END = 30, +} GXBPFieldMask; + +// BP locators for scissor offset. +typedef enum _GXBPScissorOffset { + // X offset [22-31] + GX_BP_SCISSOROFS_OX_ST = 22, + GX_BP_SCISSOROFS_OX_END = 31, + + // Y offset [12-21] + GX_BP_SCISSOROFS_OY_ST = 12, + GX_BP_SCISSOROFS_OY_END = 21, +} GXBPScissorOffset; + +// BP locators for field mode. +typedef enum _GXBPFieldMode { + // Adjust vertex tex LOD computation to account for interlacing + GX_BP_FIELDMODE_TEX_LOD_ST = 31, + GX_BP_FIELDMODE_TEX_LOD_END = 31, +} GXBPFieldMode; + +// BP locators for fog range. +typedef enum _GXBPFogRange { + // Center [22-31] + GX_BP_FOGRANGE_CENTER_ST = 22, + GX_BP_FOGRANGE_CENTER_END = 31, + + // Enabled [21-21] + GX_BP_FOGRANGE_ENABLED_ST = 21, + GX_BP_FOGRANGE_ENABLED_END = 21, +} GXBPFogRange; + +// BP locators for fog range K. +typedef enum _GXBPFogRangeK { + // Hi [20-31] + GX_BP_FOGRANGEK_HI_ST = 20, + GX_BP_FOGRANGEK_HI_END = 31, + + // Lo [8-19] + GX_BP_FOGRANGEK_LO_ST = 8, + GX_BP_FOGRANGEK_LO_END = 19, +} GXBPFogRangeK; + +// BP locators for fog parameter 0. +typedef enum _GXBPFogParam0 { + // A mantissa [21-31] + GX_BP_FOGPARAM0_A_MANT_ST = 21, + GX_BP_FOGPARAM0_A_MANT_END = 31, + + // A exponent [13-20] + GX_BP_FOGPARAM0_A_EXP_ST = 13, + GX_BP_FOGPARAM0_A_EXP_END = 20, + + // A sign [12-12] + GX_BP_FOGPARAM0_A_SIGN_ST = 12, + GX_BP_FOGPARAM0_A_SIGN_END = 12, +} GXBPFogParam0; + +// BP locators for fog parameter 1. +typedef enum _GXBPFogParam1 { + // B magnitude [8-31] + GX_BP_FOGPARAM1_B_MAG_ST = 8, + GX_BP_FOGPARAM1_B_MAG_END = 31, +} GXBPFogParam1; + +// BP locators for fog parameter 2. +typedef enum _GXBPFogParam2 { + // B shift [27-31] + GX_BP_FOGPARAM2_B_SHIFT_ST = 27, + GX_BP_FOGPARAM2_B_SHIFT_END = 31, +} GXBPFogParam2; + +// BP locators for fog parameter 3. +typedef enum _GXBPFogParam3 { + // C mantissa [21-31] + GX_BP_FOGPARAM3_C_MANT_ST = 21, + GX_BP_FOGPARAM3_C_MANT_END = 31, + + // C exponent [13-20] + GX_BP_FOGPARAM3_C_EXP_ST = 13, + GX_BP_FOGPARAM3_C_EXP_END = 20, + + // C sign [12-12] + GX_BP_FOGPARAM3_C_SIGN_ST = 12, + GX_BP_FOGPARAM3_C_SIGN_END = 12, + + // Projection [11] + GX_BP_FOGPARAM3_PROJ_ST = 11, + GX_BP_FOGPARAM3_PROJ_END = 11, + + // F select [8-10] + GX_BP_FOGPARAM3_FSEL_ST = 8, + GX_BP_FOGPARAM3_FSEL_END = 10, +} GXBPFogParam3; + +// BP locators for fog color. +typedef enum _GXBPFogColor { + // RGB components of color [8-31] + GX_BP_FOGCOLOR_RGB_ST = 8, + GX_BP_FOGCOLOR_RGB_END = 31, +} GXBPFogColor; + +// CP locator for matrix index A. +typedef enum _GXCPMtxIdxA { + // Geometry [26-31] + GX_CP_MTXIDXA_GEOM_ST = 26, + GX_CP_MTXIDXA_GEOM_END = 31, + + // Tex0 [20-25] + GX_CP_MTXIDXA_TEX0_ST = 20, + GX_CP_MTXIDXA_TEX0_END = 25, + + // Tex1 [14-19] + GX_CP_MTXIDXA_TEX1_ST = 14, + GX_CP_MTXIDXA_TEX1_END = 19, + + // Tex2 [8-13] + GX_CP_MTXIDXA_TEX2_ST = 8, + GX_CP_MTXIDXA_TEX2_END = 13, + + // Tex3 [2-7] + GX_CP_MTXIDXA_TEX3_ST = 2, + GX_CP_MTXIDXA_TEX3_END = 7, +} GXCPMtxIdxA; + +// CP locator for matrix index B. +typedef enum _GXCPMtxIdxB { + // Tex4 [26-31] + GX_CP_MTXIDXB_TEX4_ST = 26, + GX_CP_MTXIDXB_TEX4_END = 31, + + // Tex5 [20-25] + GX_CP_MTXIDXB_TEX5_ST = 20, + GX_CP_MTXIDXB_TEX5_END = 25, + + // Tex6 [14-19] + GX_CP_MTXIDXB_TEX6_ST = 14, + GX_CP_MTXIDXB_TEX6_END = 19, + + // Tex7 [8-13] + GX_CP_MTXIDXB_TEX7_ST = 8, + GX_CP_MTXIDXB_TEX7_END = 13, +} GXCPMtxIdxB; + +// CP locator for vertex descriptor (lo). +typedef enum _GXCPVCDLo { + // Position matrix idx [31] + GX_CP_VCD_LO_POSMTXIDX_ST = 31, + GX_CP_VCD_LO_POSMTXIDX_END = 31, + + // Tex 0 matrix idx [30] + GX_CP_VCD_LO_TEX0MTXIDX_ST = 30, + GX_CP_VCD_LO_TEX0MTXIDX_END = 30, + + // Tex 1 matrix idx [29] + GX_CP_VCD_LO_TEX1MTXIDX_ST = 29, + GX_CP_VCD_LO_TEX1MTXIDX_END = 29, + + // Tex 2 matrix idx [28] + GX_CP_VCD_LO_TEX2MTXIDX_ST = 28, + GX_CP_VCD_LO_TEX2MTXIDX_END = 28, + + // Tex 3 matrix idx [27] + GX_CP_VCD_LO_TEX3MTXIDX_ST = 27, + GX_CP_VCD_LO_TEX3MTXIDX_END = 27, + + // Tex 4 matrix idx [26] + GX_CP_VCD_LO_TEX4MTXIDX_ST = 26, + GX_CP_VCD_LO_TEX4MTXIDX_END = 26, + + // Tex 5 matrix idx [25] + GX_CP_VCD_LO_TEX5MTXIDX_ST = 25, + GX_CP_VCD_LO_TEX5MTXIDX_END = 25, + + // Tex 6 matrix idx [24] + GX_CP_VCD_LO_TEX6MTXIDX_ST = 24, + GX_CP_VCD_LO_TEX6MTXIDX_END = 24, + + // Tex 7 matrix idx [23] + GX_CP_VCD_LO_TEX7MTXIDX_ST = 23, + GX_CP_VCD_LO_TEX7MTXIDX_END = 23, + + // Position [21-22] + GX_CP_VCD_LO_POS_ST = 21, + GX_CP_VCD_LO_POS_END = 22, + + // Normal [19-20] + GX_CP_VCD_LO_NRM_ST = 19, + GX_CP_VCD_LO_NRM_END = 20, + + // Color diffused [17-18] + GX_CP_VCD_LO_CLRDIF_ST = 17, + GX_CP_VCD_LO_CLRDIF_END = 18, + + // Color specular [15-16] + GX_CP_VCD_LO_CLRSPEC_ST = 15, + GX_CP_VCD_LO_CLRSPEC_END = 16, +} GXCPVCDLo; + +// CP locators for vertex descriptor (hi). +typedef enum _GXCPVCDHi { + // Tex0 coordinates [30-31] + GX_CP_VCD_HI_TEX0COORD_ST = 30, + GX_CP_VCD_HI_TEX0COORD_END = 31, + + // Tex1 coordinates [28-29] + GX_CP_VCD_HI_TEX1COORD_ST = 28, + GX_CP_VCD_HI_TEX1COORD_END = 29, + + // Tex2 coordinates [26-27] + GX_CP_VCD_HI_TEX2COORD_ST = 26, + GX_CP_VCD_HI_TEX2COORD_END = 27, + + // Tex3 coordinates [24-25] + GX_CP_VCD_HI_TEX3COORD_ST = 24, + GX_CP_VCD_HI_TEX3COORD_END = 25, + + // Tex4 coordinates [22-23] + GX_CP_VCD_HI_TEX4COORD_ST = 22, + GX_CP_VCD_HI_TEX4COORD_END = 23, + + // Tex5 coordinates [20-21] + GX_CP_VCD_HI_TEX5COORD_ST = 20, + GX_CP_VCD_HI_TEX5COORD_END = 21, + + // Tex6 coordinates [18-19] + GX_CP_VCD_HI_TEX6COORD_ST = 18, + GX_CP_VCD_HI_TEX6COORD_END = 19, + + // Tex7 coordinates [16-17] + GX_CP_VCD_HI_TEX7COORD_ST = 16, + GX_CP_VCD_HI_TEX7COORD_END = 17, +} GXCPVCDHi; + +// CP locator for vertex attribute table (group 0). +typedef enum _GXCPVATGrp0 { + // Position count [31-31] + GX_CP_VAT_GRP0_POS_CNT_ST = 31, + GX_CP_VAT_GRP0_POS_CNT_END = 31, + + // Position type [28-30] + GX_CP_VAT_GRP0_POS_TYPE_ST = 28, + GX_CP_VAT_GRP0_POS_TYPE_END = 30, + + // Position shift [23-27] + GX_CP_VAT_GRP0_POS_SHIFT_ST = 23, + GX_CP_VAT_GRP0_POS_SHIFT_END = 27, + + // Normal count [22-22] + GX_CP_VAT_GRP0_NRM_CNT_ST = 22, + GX_CP_VAT_GRP0_NRM_CNT_END = 22, + + // Normal type [19-21] + GX_CP_VAT_GRP0_NRM_TYPE_ST = 19, + GX_CP_VAT_GRP0_NRM_TYPE_END = 21, + + // Color diffused count [18-18] + GX_CP_VAT_GRP0_CLRDIFF_CNT_ST = 18, + GX_CP_VAT_GRP0_CLRDIFF_CNT_END = 18, + + // Color diffused type [15-17] + GX_CP_VAT_GRP0_CLRDIFF_TYPE_ST = 15, + GX_CP_VAT_GRP0_CLRDIFF_TYPE_END = 17, + + // Color specular count [14-14] + GX_CP_VAT_GRP0_CLRSPEC_CNT_ST = 14, + GX_CP_VAT_GRP0_CLRSPEC_CNT_END = 14, + + // Color specular type [11-13] + GX_CP_VAT_GRP0_CLRSPEC_TYPE_ST = 11, + GX_CP_VAT_GRP0_CLRSPEC_TYPE_END = 13, + + // Tex0 coord count [10-10] + GX_CP_VAT_GRP0_TXC0_CNT_ST = 10, + GX_CP_VAT_GRP0_TXC0_CNT_END = 10, + + // Tex0 coord type [7-9] + GX_CP_VAT_GRP0_TXC0_TYPE_ST = 7, + GX_CP_VAT_GRP0_TXC0_TYPE_END = 9, + + // Tex0 coord shift [2-6] + GX_CP_VAT_GRP0_TXC0_SHIFT_ST = 2, + GX_CP_VAT_GRP0_TXC0_SHIFT_END = 6, + + // Byte dequantised [1-1] + GX_CP_VAT_GRP0_BYTEDEQ_ST = 1, + GX_CP_VAT_GRP0_BYTEDEQ_END = 1, + + // Normal index 3 [0-0] (Input will be treated as three staggered indices (one per triple biased by component size) into normal table)) + GX_CP_VAT_GRP0_NRMIDX3_ST = 0, + GX_CP_VAT_GRP0_NRMIDX3_END = 0, +} GXCPVATGrp0; + +// CP locators for vertex attribute table (group 1). +typedef enum _GXCPVATGrp1 { + // Tex1 coord count [31-31] + GX_CP_VAT_GRP1_TXC1_CNT_ST = 31, + GX_CP_VAT_GRP1_TXC1_CNT_END = 31, + + // Tex1 coord type [28-30] + GX_CP_VAT_GRP1_TXC1_TYPE_ST = 28, + GX_CP_VAT_GRP1_TXC1_TYPE_END = 30, + + // Tex1 coord shift [23-27] + GX_CP_VAT_GRP1_TXC1_SHIFT_ST = 23, + GX_CP_VAT_GRP1_TXC1_SHIFT_END = 27, + + // Tex2 coord count [22-22] + GX_CP_VAT_GRP1_TXC2_CNT_ST = 22, + GX_CP_VAT_GRP1_TXC2_CNT_END = 22, + + // Tex2 coord type [19-21] + GX_CP_VAT_GRP1_TXC2_TYPE_ST = 19, + GX_CP_VAT_GRP1_TXC2_TYPE_END = 21, + + // Tex2 coord shift [14-18] + GX_CP_VAT_GRP1_TXC2_SHIFT_ST = 14, + GX_CP_VAT_GRP1_TXC2_SHIFT_END = 18, + + // Tex3 coord count [13-13] + GX_CP_VAT_GRP1_TXC3_CNT_ST = 13, + GX_CP_VAT_GRP1_TXC3_CNT_END = 13, + + // Tex3 coord type [10-12] + GX_CP_VAT_GRP1_TXC3_TYPE_ST = 10, + GX_CP_VAT_GRP1_TXC3_TYPE_END = 12, + + // Tex3 coord shift [5-9] + GX_CP_VAT_GRP1_TXC3_SHIFT_ST = 5, + GX_CP_VAT_GRP1_TXC3_SHIFT_END = 9, + + // Tex4 coord count [4-4] + GX_CP_VAT_GRP1_TXC4_CNT_ST = 4, + GX_CP_VAT_GRP1_TXC4_CNT_END = 4, + + // Tex4 coord type [1-3] + GX_CP_VAT_GRP1_TXC4_TYPE_ST = 1, + GX_CP_VAT_GRP1_TXC4_TYPE_END = 3, + +} GXCPVATGrp1; + +// CP locators for vertex attribute table (group 2). +typedef enum _GXCPVATGrp2 { + // Tex4 coord shift [27-31] + GX_CP_VAT_GRP2_TXC4_SHIFT_ST = 27, + GX_CP_VAT_GRP2_TXC4_SHIFT_END = 31, + + // Tex5 coord count [26-26] + GX_CP_VAT_GRP2_TXC5_CNT_ST = 26, + GX_CP_VAT_GRP2_TXC5_CNT_END = 26, + + // Tex5 coord type [23-25] + GX_CP_VAT_GRP2_TXC5_TYPE_ST = 23, + GX_CP_VAT_GRP2_TXC5_TYPE_END = 25, + + // Tex5 coord shift [18-22] + GX_CP_VAT_GRP2_TXC5_SHIFT_ST = 18, + GX_CP_VAT_GRP2_TXC5_SHIFT_END = 22, + + // Tex6 coord count [17-17] + GX_CP_VAT_GRP2_TXC6_CNT_ST = 17, + GX_CP_VAT_GRP2_TXC6_CNT_END = 17, + + // Tex6 coord type [14-16] + GX_CP_VAT_GRP2_TXC6_TYPE_ST = 14, + GX_CP_VAT_GRP2_TXC6_TYPE_END = 16, + + // Tex6 coord shift [9-13] + GX_CP_VAT_GRP2_TXC6_SHIFT_ST = 9, + GX_CP_VAT_GRP2_TXC6_SHIFT_END = 13, + + // Tex7 coord count [8-8] + GX_CP_VAT_GRP2_TXC7_CNT_ST = 8, + GX_CP_VAT_GRP2_TXC7_CNT_END = 8, + + // Tex7 coord type [5-7] + GX_CP_VAT_GRP2_TXC7_TYPE_ST = 5, + GX_CP_VAT_GRP2_TXC7_TYPE_END = 7, + + // Tex7 coord shift [0-4] + GX_CP_VAT_GRP2_TXC7_SHIFT_ST = 0, + GX_CP_VAT_GRP2_TXC7_SHIFT_END = 4, +} GXCPVATGrp2; + +// CP locators for array base. +typedef enum _GXCPArrayBase { + // Base [6-31] + GX_CP_ARRAYBASE_BASE_ST = 6, + GX_CP_ARRAYBASE_BASE_END = 31, +} GXCPArrayBase; + +// CP locators for array stride. +typedef enum _GXCPArrayStride { + // Stride [24-31] + GX_CP_ARRAYSTRIDE_STRIDE_ST = 24, + GX_CP_ARRAYSTRIDE_STRIDE_END = 31, +} GXCPArrayStride; + +// XF locators for clip disabling. +typedef enum _GXXFClipDisable { + // Disable detection [31-31] + GX_XF_CLIPDISABLE_DETECT_ST = 31, + GX_XF_CLIPDISABLE_DETECT_END = 31, + + // Disable trivial rejection [30-30] + GX_XF_CLIPDISABLE_REJECT_ST = 30, + GX_XF_CLIPDISABLE_REJECT_END = 30, + + // Disable cpoly clipping acceleration [29-29] + GX_XF_CLIPDISABLE_ACCEL_ST = 29, + GX_XF_CLIPDISABLE_ACCEL_END = 29, +} GXXFClipDisable; + +// XF locators for InVertexSpec. +typedef enum _GXXFInVertexSpec { + // Color [30-31] + GX_XF_INVERTEXSPEC_CLR_ST = 30, + GX_XF_INVERTEXSPEC_CLR_END = 31, + + // Normal [28-29] + GX_XF_INVERTEXSPEC_NRM_ST = 28, + GX_XF_INVERTEXSPEC_NRM_END = 29, + + // Tex coords [24-27] + GX_XF_INVERTEXSPEC_TEX_ST = 24, + GX_XF_INVERTEXSPEC_TEX_END = 27, +} GXXFInVertexSpec; + +// XF locators for Color 0 control. +typedef enum _GXXFClr0Ctrl { + // Matrix source [31-31] + GX_XF_CLR0CTRL_MTXSRC_ST = 31, + GX_XF_CLR0CTRL_MTXSRC_END = 31, + + // Light [30-30] + GX_XF_CLR0CTRL_LIGHT_ST = 30, + GX_XF_CLR0CTRL_LIGHT_END = 30, + + // Light mask (hi) [26-29] + GX_XF_CLR0CTRL_LMASKHI_ST = 26, + GX_XF_CLR0CTRL_LMASKHI_END = 29, + + // Ambient source [25-25] + GX_XF_CLR0CTRL_AMBSRC_ST = 25, + GX_XF_CLR0CTRL_AMBSRC_END = 25, + + // Diffuse attenuation [23-24] + GX_XF_CLR0CTRL_DIFATTN_ST = 23, + GX_XF_CLR0CTRL_DIFATTN_END = 24, + + // Enable attenuation [22-22] + GX_XF_CLR0CTRL_ATTNENABLE_ST = 22, + GX_XF_CLR0CTRL_ATTNENABLE_END = 22, + + // Select attenuation [21-21] + GX_XF_CLR0CTRL_ATTNSEL_ST = 21, + GX_XF_CLR0CTRL_ATTNSEL_END = 21, + + // Light mask (lo) [17-20] + GX_XF_CLR0CTRL_LMASKLO_ST = 17, + GX_XF_CLR0CTRL_LMASKLO_END = 20, +} GXXFClr0Ctrl; + +// XF locators for matrix index 0. +typedef enum _GXXFMtxIdx0 { + // Geometry [26-31] + GX_XF_MTXIDX0_GEOM_ST = 26, + GX_XF_MTXIDX0_GEOM_END = 31, + + // Tex 0 [20-25] + GX_XF_MTXIDX0_TEX0_ST = 20, + GX_XF_MTXIDX0_TEX0_END = 25, + + // Tex 1 [14-19] + GX_XF_MTXIDX0_TEX1_ST = 14, + GX_XF_MTXIDX0_TEX1_END = 19, + + // Tex 2 [8-13] + GX_XF_MTXIDX0_TEX2_ST = 8, + GX_XF_MTXIDX0_TEX2_END = 13, + + // Tex 3 [2-7] + GX_XF_MTXIDX0_TEX3_ST = 2, + GX_XF_MTXIDX0_TEX3_END = 7, +} GXXFMtxIdx0; + +// XF locators for matrix index 1. +typedef enum _GXXFMtxIdx1 { + // Tex 4 [26-31] + GX_XF_MTXIDX1_TEX4_ST = 26, + GX_XF_MTXIDX1_TEX4_END = 31, + + // Tex 5 [20-25] + GX_XF_MTXIDX1_TEX5_ST = 20, + GX_XF_MTXIDX1_TEX5_END = 25, + + // Tex 6 [14-19] + GX_XF_MTXIDX1_TEX6_ST = 14, + GX_XF_MTXIDX1_TEX6_END = 19, + + // Tex 7 [8-13] + GX_XF_MTXIDX1_TEX7_ST = 8, + GX_XF_MTXIDX1_TEX7_END = 13, +} GXXFMtxIdx1; + +// XF locators for textures. +typedef enum _GXXFTex { + // Projection type [30-30] + GX_XF_TEX_PROJTYPE_ST = 30, + GX_XF_TEX_PROJTYPE_END = 30, + + // Input format [29-29] + GX_XF_TEX_INPUTFORM_ST = 29, + GX_XF_TEX_INPUTFORM_END = 29, + + // Texture gen type [25-27] + GX_XF_TEX_TEXGENTYPE_ST = 25, + GX_XF_TEX_TEXGENTYPE_END = 27, + + // Source row [20-24] + GX_XF_TEX_SRCROW_ST = 20, + GX_XF_TEX_SRCROW_END = 24, + + // Bump source texture [17-19] + GX_XF_TEX_BUMPSRCTEX_ST = 17, + GX_XF_TEX_BUMPSRCTEX_END = 19, + + // Bump source light [14-16] + GX_XF_TEX_BUMPSRCLIGHT_ST = 14, + GX_XF_TEX_BUMPSRCLIGHT_END = 16, +} GXXFTex; + +// XF locators for dual textures. +typedef enum _GXXFDualTex { + // Base row of the transform matrix [26-31] + GX_XF_DUALTEX_BASEROW_ST = 26, + GX_XF_DUALTEX_BASEROW_END = 31, + + // Normalise texcoord before sending transform [23-23] + GX_XF_DUALTEX_NORMALISE_ST = 23, + GX_XF_DUALTEX_NORMALISE_END = 23, +} GXXFDualTex; + + +/* Command FIFO register loads */ + +#define __GX_FIFO_SET_LOAD_INDX_DST(reg, x) ((reg) = GX_BITFIELD_SET(reg, 20, 12, x)) +#define __GX_FIFO_SET_LOAD_INDX_NELEM(reg, x) ((reg) = GX_BITFIELD_SET(reg, 16, 4, x)) +#define __GX_FIFO_SET_LOAD_INDX_INDEX(reg, x) ((reg) = GX_BITFIELD_SET(reg, 0, 16, x)) + +#define __GX_FIFO_LOAD_INDX(reg, dst, nelem, index) \ + { \ + u32 cmd = 0; \ + __GX_FIFO_SET_LOAD_INDX_DST(cmd, dst); \ + __GX_FIFO_SET_LOAD_INDX_NELEM(cmd, nelem); \ + __GX_FIFO_SET_LOAD_INDX_INDEX(cmd, index); \ + GXWGFifo.s8 = reg; \ + GXWGFifo.s32 = cmd; \ + } + +#define GX_FIFO_LOAD_INDX_A(dst, nelem, index) __GX_FIFO_LOAD_INDX(GX_FIFO_CMD_LOAD_INDX_A, dst, nelem, index) +#define GX_FIFO_LOAD_INDX_B(dst, nelem, index) __GX_FIFO_LOAD_INDX(GX_FIFO_CMD_LOAD_INDX_B, dst, nelem, index) +#define GX_FIFO_LOAD_INDX_C(dst, nelem, index) __GX_FIFO_LOAD_INDX(GX_FIFO_CMD_LOAD_INDX_C, dst, nelem, index) +#define GX_FIFO_LOAD_INDX_D(dst, nelem, index) __GX_FIFO_LOAD_INDX(GX_FIFO_CMD_LOAD_INDX_D, dst, nelem, index) + +#define GX_BP_LOAD_REG(data) \ + GXWGFifo.s8 = GX_FIFO_CMD_LOAD_BP_REG; \ + GXWGFifo.s32 = (data); + +#define GX_BP_SET_OPCODE(cmd, opcode) (cmd) = GX_BITFIELD_SET(cmd, 0, 8, (opcode)) + +#define GX_CP_LOAD_REG(addr, data) \ + GXWGFifo.s8 = GX_FIFO_CMD_LOAD_CP_REG; \ + GXWGFifo.s8 = (addr); \ + GXWGFifo.s32 = (data); + +#define GX_XF_LOAD_REG_HDR(addr) \ + GXWGFifo.s8 = GX_FIFO_CMD_LOAD_XF_REG; \ + GXWGFifo.s32 = (addr); + +#define GX_XF_LOAD_REG(addr, data) \ + GX_XF_LOAD_REG_HDR(addr); \ + GXWGFifo.s32 = (data); + +#define GX_XF_LOAD_REGS(size, addr) \ + { \ + u32 cmd = (size) << 16 | addr; \ + GX_XF_LOAD_REG_HDR(cmd); \ + } + +/* GX state */ + +typedef struct _GXData { + // Bypass and vertex info + u16 vNumNot; // _000 + u16 bpSentNot; // _002 + u16 vNum; // _004 + u16 vLim; // _006 + + // Command processor (CP) regs + u32 cpEnable; // _008 + u32 cpStatus; // _00C + u32 cpClr; // _010 + u32 vcdLo; // _014 + u32 vcdHi; // _018 + u32 vatA[8]; // _01C + u32 vatB[8]; // _03C + u32 vatC[8]; // _05C + u32 lpSize; // _07C + u32 matIdxA; // _080 + u32 matIdxB; // _084 + + // Index loading base/stride regs (pos, nrm, tex, light) + u32 indexBase[4]; // _088 + u32 indexStride[4]; // _098 + + // Transform and lighting regs + u32 ambColor[2]; // _0A8 + u32 matColor[2]; // _0B0 + + // Setup regs + u32 suTs0[8]; // _0B8 + u32 suTs1[8]; // _0D8 + u32 suScis0; // _0F8 + u32 suScis1; // _0FC + + // Raster regs + u32 tref[8]; // _100 + u32 iref; // _120 + + // Bump/Indirect texture regs + u32 bpMask; // _124 + u32 IndTexScale0; // _128 + u32 IndTexScale1; // _12C + + // Tev regs + u32 tevc[16]; // _130 + u32 teva[16]; // _170 + u32 tevKsel[8]; // _1B0 + + // Pixel engine regs + u32 cmode0; // _1D0 + u32 cmode1; // _1D4 + u32 zmode; // _1D8 + u32 peCtrl; // _1DC + + // Display copy regs + u32 cpDispSrc; // _1E0 + u32 cpDispSize; // _1E4 + u32 cpDispStride; // _1E8 + u32 cpDisp; // _1EC + + // Texture copy regs + u32 cpTexSrc; // _1F0 + u32 cpTexSize; // _1F4 + u32 cpTexStride; // _1F8 + u32 cpTex; // _1FC + GXBool cpTexZ; // _200 + + // General raster mode + u32 genMode; // _204 + + // Texture regions + GXTexRegion TexRegions0[GX_MAX_TEXMAP]; // _208 + GXTexRegion TexRegions1[GX_MAX_TEXMAP]; // _288 + GXTexRegion TexRegions2[GX_MAX_TEXMAP]; // _308 + + // Texture lookup table regions + GXTlutRegion TlutRegions[GX_MAX_TLUT_ALL]; // _388 + GXTexRegionCallback texRegionCallback; // _4C8 + GXTlutRegionCallback tlutRegionCallback; // _4CC + + // Command processor vars + GXAttrType nrmType; // _4D0 + GXBool hasNrms; // _4D4 + GXBool hasBiNrms; // _4D5 + u32 projType; // _4D8 + f32 projMtx[6]; // _4DC + + // Viewport parms + f32 vpLeft; // _4F4 + f32 vpTop; // _4F8 + f32 vpWd; // _4FC + f32 vpHt; // _500 + f32 vpNearz; // _504 + f32 vpFarz; // _508 + f32 zOffset; // _50C + f32 zScale; // _510 + + // Texture regs + u32 tImage0[8]; // _514 + u32 tMode0[8]; // _534 + u32 texmapId[16]; // _554 + u32 tcsManEnab; // _594 + u32 tevTcEnab; // _598 + + // Performance metrics + GXPerf0 perf0; // _59C + GXPerf1 perf1; // _5A0 + u32 perfSel; // _5A4 + + // Flags + GXBool inDispList; // _5A8 + GXBool dlSaveContext; // _5A9 + GXBool abtWaitPECopy; // _5AA + u8 dirtyVAT; // _5AB + u32 dirtyState; // _5AC +} GXData; // size 0x5B0 + +extern GXData* const __GXData; + +#define gx __GXData + +/* Memory-mapped register access */ + +#define GX_CP_ADDR (0x0C000000) +#define GX_PE_ADDR (0x0C001000) +#define GX_PI_ADDR (0x0C003000) +#define GX_MEM_ADDR (0x0C004000) + +#undef GX_GET_CP_REG +#undef GX_SET_CP_REG + +#define GX_GET_MEM_REG(offset) (*(volatile u16*)((volatile u16*)(__memReg) + (offset))) +#define GX_GET_CP_REG(offset) (*(volatile u16*)((volatile u16*)(__cpReg) + (offset))) +#define GX_GET_PE_REG(offset) (*(volatile u16*)((volatile u16*)(__peReg) + (offset))) +#define GX_GET_PI_REG(offset) (*(volatile u32*)((volatile u32*)(__piReg) + (offset))) + +#define GX_SET_MEM_REG(offset, val) (*(volatile u16*)((volatile u16*)(__memReg) + (offset)) = val) +#define GX_SET_CP_REG(offset, val) (*(volatile u16*)((volatile u16*)(__cpReg) + (offset)) = val) +#define GX_SET_PE_REG(offset, val) (*(volatile u16*)((volatile u16*)(__peReg) + (offset)) = val) +#define GX_SET_PI_REG(offset, val) (*(volatile u32*)((volatile u32*)(__piReg) + (offset)) = val) + +static inline u32 GXReadMEMReg(u32 addrLo, u32 addrHi) +{ + u32 hiStart, hiNew, lo; + hiStart = GX_GET_MEM_REG(addrHi); + do { + hiNew = hiStart; + lo = GX_GET_MEM_REG(addrLo); + hiStart = GX_GET_MEM_REG(addrHi); + } while (hiStart != hiNew); + + return ((hiStart << 16) | lo); +} + +static inline u32 GXReadCPReg(u32 addrLo, u32 addrHi) +{ + u32 hiStart, hiNew, lo; + hiStart = GX_GET_CP_REG(addrHi); + do { + hiNew = hiStart; + lo = GX_GET_CP_REG(addrLo); + hiStart = GX_GET_CP_REG(addrHi); + } while (hiStart != hiNew); + + return ((hiStart << 16) | lo); +} + +static inline u32 GXReadPEReg(u32 addrLo, u32 addrHi) +{ + u32 hiStart, hiNew, lo; + hiStart = GX_GET_PE_REG(addrHi); + do { + hiNew = hiStart; + lo = GX_GET_PE_REG(addrLo); + hiStart = GX_GET_PE_REG(addrHi); + } while (hiStart != hiNew); + + return ((hiStart << 16) | lo); +} + +static inline u32 GXReadPIReg(u32 addrLo, u32 addrHi) +{ + u32 hiStart, hiNew, lo; + hiStart = GX_GET_PI_REG(addrHi); + do { + hiNew = hiStart; + lo = GX_GET_PI_REG(addrLo); + hiStart = GX_GET_PI_REG(addrHi); + } while (hiStart != hiNew); + + return ((hiStart << 16) | lo); +} + +#define GX_CHECK_FLUSH() (!(*(u32*)(&gx->vNumNot))) + +/* Public functions missing from the shared headers */ + +void GXSetVtxAttrFmtv(GXVtxFmt vtxfmt, const GXVtxAttrFmtList* list); +void GXSetDispCopyFrame2Field(GXCopyMode mode); +void GXClearBoundingBox(void); +void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1); +void GXClearGPMetric(void); +void GXLoadTexObjPreLoaded(GXTexObj* obj, GXTexRegion* region, GXTexMapID id); +GXTlutRegionCallback GXSetTlutRegionCallback(GXTlutRegionCallback f); +void GXSetProjectionv(const f32* ptr); + +/* GXAttr.c */ + +void __GXSetVCD(void); +void __GXCalculateVLim(void); +void __GXSetVAT(void); + +/* GXBump.c */ + +void __GXUpdateBPMask(void); +void __GXFlushTextureState(void); +void __GXSetIndirectMask(u32 mask); + +/* GXFifo.c */ + +void __GXSaveCPUFifoAux(GXFifoObj* fifo); +void __GXFifoInit(void); +void __GXFifoReadEnable(void); +void __GXFifoReadDisable(void); +void __GXFifoLink(u8 link); +void __GXWriteFifoIntEnable(u32 p1, u32 p2); +void __GXWriteFifoIntReset(u32 p1, u32 p2); +void __GXCleanGPFifo(void); + +/* GXGeometry.c */ + +void __GXSetDirtyState(void); +void __GXSendFlushPrim(void); +void __GXSetGenMode(void); + +/* GXInit.c */ + +void __GXInitGX(void); + +/* GXMisc.c */ + +void __GXAbort(void); +void __GXPEInit(void); + +/* GXTexture.c */ + +void __GetImageTileCount(GXTexFmt fmt, u16 wd, u16 ht, u32* rowTiles, u32* colTiles, u32* cmpTiles); +void __SetSURegs(u32 texImgIndex, u32 setUpRegIndex); +void __GXSetSUTexRegs(void); +void __GXSetTmemConfig(u32 config); + +/* GXTransform.c */ + +void __GXSetMatrixIndex(GXAttr matIdxAttr); +void __GXSetProjection(void); +void __GXSetViewport(void); + +/* vi.c */ + +u32 VIGetTvFormat(void); + +/* GXStubs.c */ + +void __GXSetRange(f32 nearz, f32 fgSideX); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/static/GAEJ01_01/dolphin/mtx/mtx.c b/src/static/GAEJ01_01/dolphin/mtx/mtx.c new file mode 100644 index 00000000..29cbf28f --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/mtx/mtx.c @@ -0,0 +1,619 @@ +#include +#include +#include + +#define qr0 0 + +// unsorted externs +extern f32 sinf(f32); +extern f32 cosf(f32); +extern f32 tanf(f32); + +// .sbss +static float Unit01[2] = { 0.0f, 1.0f }; + +// MEME: if this function is not here, 0.0f and 1.0f have wrong order in .sdata2 +void C_MTXIdentity(GC_Mtx mtx) +{ + mtx[0][0] = 1.0f; + mtx[0][1] = 0.0f; + mtx[0][2] = 0.0f; + mtx[1][0] = 0.0f; + mtx[1][1] = 1.0f; + mtx[1][2] = 0.0f; + mtx[2][0] = 0.0f; + mtx[2][1] = 0.0f; + mtx[2][2] = 1.0f; +} + +void PSMTXIdentity(register GC_Mtx m) +{ + register f32 c_zero = 0.0f; + register f32 c_one = 1.0f; + register f32 c_01; + register f32 c_10; + +#ifdef __MWERKS__ // clang-format off + asm { + psq_st c_zero, 8(m), 0, qr0 + ps_merge01 c_01, c_zero, c_one + psq_st c_zero, 24(m), 0, qr0 + ps_merge10 c_10, c_one, c_zero + psq_st c_zero, 32(m), 0, qr0 + psq_st c_01, 16(m), 0, qr0 + psq_st c_10, 0(m), 0, qr0 + psq_st c_10, 40(m), 0, qr0 + } +#endif // clang-format on +} + +asm void PSMTXCopy(const register GC_Mtx src, register GC_Mtx dst) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f0, 0(src), 0, qr0 + psq_st f0, 0(dst), 0, qr0 + psq_l f1, 8(src), 0, qr0 + psq_st f1, 8(dst), 0, qr0 + psq_l f2, 16(src), 0, qr0 + psq_st f2, 16(dst), 0, qr0 + psq_l f3, 24(src), 0, qr0 + psq_st f3, 24(dst), 0, qr0 + psq_l f4, 32(src), 0, qr0 + psq_st f4, 32(dst), 0, qr0 + psq_l f5, 40(src), 0, qr0 + psq_st f5, 40(dst), 0, qr0 +#endif // clang-format on +} + +asm void PSMTXConcat(const register GC_Mtx mA, const register GC_Mtx mB, register GC_Mtx mAB) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + stwu r1, -64(r1) + psq_l f0, 0(mA), 0, qr0 + stfd f14, 8(r1) + psq_l f6, 0(mB), 0, qr0 + lis r6, Unit01@ha + psq_l f7, 8(mB), 0, qr0 + stfd f15, 16(r1) + addi r6, r6, Unit01@l + stfd f31, 40(r1) + psq_l f8, 16(mB), 0, qr0 + ps_muls0 f12, f6, f0 + psq_l f2, 16(mA), 0, qr0 + ps_muls0 f13, f7, f0 + psq_l f31, 0(r6), 0, qr0 + ps_muls0 f14, f6, f2 + psq_l f9, 24(mB), 0, qr0 + ps_muls0 f15, f7, f2 + psq_l f1, 8(mA), 0, qr0 + ps_madds1 f12, f8, f0, f12 + psq_l f3, 24(mA), 0, qr0 + ps_madds1 f14, f8, f2, f14 + psq_l f10, 32(mB), 0, qr0 + ps_madds1 f13, f9, f0, f13 + psq_l f11, 40(mB), 0, qr0 + ps_madds1 f15, f9, f2, f15 + psq_l f4, 32(mA), 0, qr0 + psq_l f5, 40(mA), 0, qr0 + ps_madds0 f12, f10, f1, f12 + ps_madds0 f13, f11, f1, f13 + ps_madds0 f14, f10, f3, f14 + ps_madds0 f15, f11, f3, f15 + psq_st f12, 0(mAB), 0, qr0 + ps_muls0 f2, f6, f4 + ps_madds1 f13, f31, f1, f13 + ps_muls0 f0, f7, f4 + psq_st f14, 16(mAB), 0, qr0 + ps_madds1 f15, f31, f3, f15 + psq_st f13, 8(mAB), 0, qr0 + ps_madds1 f2, f8, f4, f2 + ps_madds1 f0, f9, f4, f0 + ps_madds0 f2, f10, f5, f2 + lfd f14, 8(r1) + psq_st f15, 24(mAB), 0, qr0 + ps_madds0 f0, f11, f5, f0 + psq_st f2, 32(mAB), 0, qr0 + ps_madds1 f0, f31, f5, f0 + lfd f15, 16(r1) + psq_st f0, 40(mAB), 0, qr0 + lfd f31, 40(r1) + addi r1, r1, 64 + blr +#endif // clang-format on +} + +asm u32 PSMTXInverse(const register GC_Mtx src, register GC_Mtx inv) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f0, 0(src), 1, qr0 + psq_l f1, 4(src), 0, qr0 + psq_l f2, 16(src), 1, qr0 + ps_merge10 f6, f1, f0 + psq_l f3, 20(src), 0, qr0 + psq_l f4, 32(src), 1, qr0 + ps_merge10 f7, f3, f2 + psq_l f5, 36(src), 0, qr0 + ps_mul f11, f3, f6 + ps_mul f13, f5, f7 + ps_merge10 f8, f5, f4 + ps_msub f11, f1, f7, f11 + ps_mul f12, f1, f8 + ps_msub f13, f3, f8, f13 + ps_mul f10, f3, f4 + ps_msub f12, f5, f6, f12 + ps_mul f9, f0, f5 + ps_mul f8, f1, f2 + ps_sub f6, f6, f6 + ps_msub f10, f2, f5, f10 + ps_mul f7, f0, f13 + ps_msub f9, f1, f4, f9 + ps_madd f7, f2, f12, f7 + ps_msub f8, f0, f3, f8 + ps_madd f7, f4, f11, f7 + ps_cmpo0 cr0, f7, f6 + bne skip_return + li r3, 0 + blr +skip_return: + fres f0, f7 + ps_add f6, f0, f0 + ps_mul f5, f0, f0 + ps_nmsub f0, f7, f5, f6 + lfs f1, 12(src) + ps_muls0 f13, f13, f0 + lfs f2, 28(src) + ps_muls0 f12, f12, f0 + lfs f3, 44(src) + ps_muls0 f11, f11, f0 + ps_merge00 f5, f13, f12 + ps_muls0 f10, f10, f0 + ps_merge11 f4, f13, f12 + ps_muls0 f9, f9, f0 + psq_st f5, 0(inv), 0, qr0 + ps_mul f6, f13, f1 + psq_st f4, 16(inv), 0, qr0 + ps_muls0 f8, f8, f0 + ps_madd f6, f12, f2, f6 + psq_st f10, 32(inv), 1, qr0 + ps_nmadd f6, f11, f3, f6 + psq_st f9, 36(inv), 1, qr0 + ps_mul f7, f10, f1 + ps_merge00 f5, f11, f6 + psq_st f8, 40(inv), 1, qr0 + ps_merge11 f4, f11, f6 + psq_st f5, 8(inv), 0, qr0 + ps_madd f7, f9, f2, f7 + psq_st f4, 24(inv), 0, qr0 + ps_nmadd f7, f8, f3, f7 + li r3, 1 + psq_st f7, 44(inv), 1, qr0 +#endif // clang-format on +} + +asm u32 PSMTXInvXpose(const register GC_Mtx src, register GC_Mtx invX) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f0, 0(src), 1, qr0 + psq_l f1, 4(src), 0, qr0 + psq_l f2, 16(src), 1, qr0 + ps_merge10 f6, f1, f0 + psq_l f3, 20(src), 0, qr0 + psq_l f4, 32(src), 1, qr0 + ps_merge10 f7, f3, f2 + psq_l f5, 36(src), 0, qr0 + ps_mul f11, f3, f6 + ps_merge10 f8, f5, f4 + ps_mul f13, f5, f7 + ps_msub f11, f1, f7, f11 + ps_mul f12, f1, f8 + ps_msub f13, f3, f8, f13 + ps_msub f12, f5, f6, f12 + ps_mul f10, f3, f4 + ps_mul f9, f0, f5 + ps_mul f8, f1, f2 + ps_msub f10, f2, f5, f10 + ps_msub f9, f1, f4, f9 + ps_msub f8, f0, f3, f8 + ps_mul f7, f0, f13 + ps_sub f1, f1, f1 + ps_madd f7, f2, f12, f7 + ps_madd f7, f4, f11, f7 + ps_cmpo0 cr0, f7, f1 + bne skip_return + li r3, 0 + blr +skip_return: + fres f0, f7 + psq_st f1, 12(invX), 1, qr0 + ps_add f6, f0, f0 + ps_mul f5, f0, f0 + psq_st f1, 28(invX), 1, qr0 + ps_nmsub f0, f7, f5, f6 + psq_st f1, 44(invX), 1, qr0 + ps_muls0 f13, f13, f0 + ps_muls0 f12, f12, f0 + ps_muls0 f11, f11, f0 + psq_st f13, 0(invX), 0, qr0 + psq_st f12, 16(invX), 0, qr0 + ps_muls0 f10, f10, f0 + ps_muls0 f9, f9, f0 + psq_st f11, 32(invX), 0, qr0 + psq_st f10, 8(invX), 1, qr0 + ps_muls0 f8, f8, f0 + li r3, 1 + psq_st f9, 24(invX), 1, qr0 + psq_st f8, 40(invX), 1, qr0 +#endif // clang-format on +} + +void PSMTXRotRad(GC_Mtx m, char axis, f32 rad) +{ + f32 s = sinf(rad); + f32 c = cosf(rad); + + PSMTXRotTrig(m, axis, s, c); +} + +void PSMTXRotTrig(register GC_Mtx m, register char axis, register f32 sinA, + register f32 cosA) +{ + register f32 fc0; + register f32 fc1; + register f32 nsinA; + register f32 fw0, fw1, fw2, fw3; + + fc0 = 0.0f; + fc1 = 1.0f; + +#ifdef __MWERKS__ // clang-format off + asm { + ori axis, axis, 0x20 + ps_neg nsinA, sinA + cmplwi axis, 'x' + beq _case_x + cmplwi axis, 'y' + beq _case_y + cmplwi axis, 'z' + beq _case_z + b _end + +_case_x: + psq_st fc1, 0(m), 1, qr0 + psq_st fc0, 4(m), 0, qr0 + ps_merge00 fw0, sinA, cosA + psq_st fc0, 12(m), 0, qr0 + ps_merge00 fw1, cosA, nsinA + psq_st fc0, 28(m), 0, qr0 + psq_st fc0, 44(m), 1, qr0 + psq_st fw0, 36(m), 0, qr0 + psq_st fw1, 20(m), 0, qr0 + b _end; + +_case_y: + ps_merge00 fw0, cosA, fc0 + ps_merge00 fw1, fc0, fc1 + psq_st fc0, 24(m), 0, qr0 + psq_st fw0, 0(m), 0, qr0 + ps_merge00 fw2, nsinA, fc0 + ps_merge00 fw3, sinA, fc0 + psq_st fw0, 40(m), 0, qr0 + psq_st fw1, 16(m), 0, qr0 + psq_st fw3, 8(m), 0, qr0 + psq_st fw2, 32(m), 0, qr0 + b _end; + +_case_z: + psq_st fc0, 8(m), 0, qr0 + ps_merge00 fw0, sinA, cosA + ps_merge00 fw2, cosA, nsinA + psq_st fc0, 24(m), 0, qr0 + psq_st fc0, 32(m), 0, qr0 + ps_merge00 fw1, fc1, fc0 + psq_st fw0, 16(m), 0, qr0 + psq_st fw2, 0(m), 0, qr0 + psq_st fw1, 40(m), 0, qr0 + +_end: + } +#endif // clang-format on +} + +static inline void __PSMTXRotAxisRadInternal(register GC_Mtx m, + const register Vec* axis, + register f32 sT, register f32 cT) +{ +} + +void PSMTXRotAxisRad(register GC_Mtx m, const Vec* axis, register f32 rad) +{ + register f32 tmp0, tmp1, tmp2, tmp3, tmp4; + register f32 tmp5, tmp6, tmp7, tmp8, tmp9; + + register f32 sT; + register f32 cT; + register f32 oneMinusCosT; + register f32 zero; + Vec axisNormalized; + register Vec* axisNormalizedPtr; + + zero = 0.0f; + axisNormalizedPtr = &axisNormalized; + sT = sinf(rad); + cT = cosf(rad); + oneMinusCosT = 1.0f - cT; + + PSVECNormalize(axis, axisNormalizedPtr); + + // `rad` reused here -- absolutely disgusting. + // Also might've been an inline as in prime. +#ifdef __MWERKS__ // clang-format off + asm { + psq_l rad, 0x0(axisNormalizedPtr), 0, qr0 + lfs tmp1, 0x8(axisNormalizedPtr) + ps_merge00 tmp0, cT, cT + ps_muls0 tmp4, rad, oneMinusCosT + ps_muls0 tmp5, tmp1, oneMinusCosT + ps_muls1 tmp3, tmp4, rad + ps_muls0 tmp2, tmp4, rad + ps_muls0 rad, rad, sT + ps_muls0 tmp4, tmp4, tmp1 + fnmsubs tmp6, tmp1, sT, tmp3 + fmadds tmp7, tmp1, sT, tmp3 + ps_neg tmp9, rad + ps_sum0 tmp8, tmp4, zero, rad + ps_sum0 tmp2, tmp2, tmp6, tmp0 + ps_sum1 tmp3, tmp0, tmp7, tmp3 + ps_sum0 tmp6, tmp9, zero, tmp4 + ps_sum0 tmp9, tmp4, tmp4, tmp9 + psq_st tmp8, 0x8(m), 0, qr0 + ps_muls0 tmp5, tmp5, tmp1 + psq_st tmp2, 0x0(m), 0, qr0 + ps_sum1 tmp4, rad, tmp9, tmp4 + psq_st tmp3, 0x10(m), 0, qr0 + ps_sum0 tmp5, tmp5, zero, tmp0 + psq_st tmp6, 0x18(m), 0, qr0 + psq_st tmp4, 0x20(m), 0, qr0 + psq_st tmp5, 0x28(m), 0, qr0 + } +#endif // clang-format on +} + +void PSMTXTrans(register GC_Mtx m, register f32 xT, register f32 yT, + register f32 zT) +{ + register f32 c0 = 0.0F; + register f32 c1 = 1.0F; +#ifdef __MWERKS__ // clang-format off + asm { + stfs xT, 12(m) + stfs yT, 28(m) + psq_st c0, 4(m), 0, qr0 + psq_st c0, 32(m), 0, qr0 + stfs c0, 16(m) + stfs c1, 20(m) + stfs c0, 24(m) + stfs c1, 40(m) + stfs zT, 44(m) + stfs c1, 0(m) + } +#endif // clang-format on +} + +asm void PSMTXTransApply(const register GC_Mtx src, register GC_Mtx dst, register f32 xT, + register f32 yT, register f32 zT) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + psq_l fp4, 0(src), 0, qr0 + psq_l fp5, 8(src), 0, qr0 + psq_l fp7, 24(src), 0, qr0 + psq_l fp8, 40(src), 0, qr0 + ps_sum1 fp5, xT, fp5, fp5 + psq_l fp6, 16(src), 0, qr0 + ps_sum1 fp7, yT, fp7, fp7 + psq_l fp9, 32(src), 0, qr0 + ps_sum1 fp8, zT, fp8, fp8 + + psq_st fp4, 0(dst), 0, qr0 + psq_st fp5, 8(dst), 0, qr0 + psq_st fp6, 16(dst), 0, qr0 + psq_st fp7, 24(dst), 0, qr0 + psq_st fp9, 32(dst), 0, qr0 + psq_st fp8, 40(dst), 0, qr0 + blr +#endif // clang-format on +} + +void PSMTXScale(register GC_Mtx m, register f32 xS, register f32 yS, + register f32 zS) +{ + register f32 c0 = 0.0F; +#ifdef __MWERKS__ // clang-format off + asm { + stfs xS, 0(m) + psq_st c0, 4(m), 0, 0 + psq_st c0, 12(m), 0, 0 + stfs yS, 20(m) + psq_st c0, 24(m), 0, 0 + psq_st c0, 32(m), 0, 0 + stfs zS, 40(m) + stfs c0, 44(m) + } +#endif // clang-format on +} + +asm void PSMTXScaleApply(const register GC_Mtx src, register GC_Mtx dst, register f32 xS, + register f32 yS, register f32 zS) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + psq_l fp4, 0(src), 0, 0 + psq_l fp5, 8(src), 0, 0 + ps_muls0 fp4, fp4, xS + psq_l fp6, 16(src), 0, 0 + ps_muls0 fp5, fp5, xS + psq_l fp7, 24(src), 0, 0 + ps_muls0 fp6, fp6, yS + psq_l fp8, 32(src), 0, 0 + psq_st fp4, 0(dst), 0, 0 + ps_muls0 fp7, fp7, yS + psq_l fp2, 40(src), 0, 0 + psq_st fp5, 8(dst), 0, 0 + ps_muls0 fp8, fp8, zS + psq_st fp6, 16(dst), 0, 0 + ps_muls0 fp2, fp2, zS + psq_st fp7, 24(dst), 0, 0 + psq_st fp8, 32(dst), 0, 0 + psq_st fp2, 40(dst), 0, 0 + blr +#endif // clang-format on +} + +void PSMTXQuat(register GC_Mtx m, const register PSQuaternion* q) +{ + register f32 c_zero, c_one, c_two, scale; + register f32 tmp0, tmp1, tmp2, tmp3, tmp4; + register f32 tmp5, tmp6, tmp7, tmp8, tmp9; + + c_one = 1.0F; +#ifdef __MWERKS__ // clang-format off + asm { + psq_l tmp0, 0(q), 0, 0 + psq_l tmp1, 8(q), 0, 0 + fsubs c_zero, c_one, c_one + fadds c_two, c_one, c_one + ps_mul tmp2, tmp0, tmp0 + ps_merge10 tmp5, tmp0, tmp0 + ps_madd tmp4, tmp1, tmp1, tmp2 + ps_mul tmp3, tmp1, tmp1 + ps_sum0 scale, tmp4, tmp4, tmp4 + ps_muls1 tmp7, tmp5, tmp1 + fres tmp9, scale + ps_sum1 tmp4, tmp3, tmp4, tmp2 + ps_nmsub scale, scale, tmp9, c_two + ps_muls1 tmp6, tmp1, tmp1 + ps_mul scale, tmp9, scale + ps_sum0 tmp2, tmp2, tmp2, tmp2 + fmuls scale, scale, c_two + ps_madd tmp8, tmp0, tmp5, tmp6 + ps_msub tmp6, tmp0, tmp5, tmp6 + psq_st c_zero, 12(m), 1, 0 + ps_nmsub tmp2, tmp2, scale, c_one + ps_nmsub tmp4, tmp4, scale, c_one + psq_st c_zero, 44(m), 1, 0 + ps_mul tmp8, tmp8, scale + ps_mul tmp6, tmp6, scale + psq_st tmp2, 40(m), 1, 0 + ps_madds0 tmp5, tmp0, tmp1, tmp7 + ps_merge00 tmp1, tmp8, tmp4 + ps_nmsub tmp7, tmp7, c_two, tmp5 + ps_merge10 tmp0, tmp4, tmp6 + psq_st tmp1, 16(m), 0, 0 + ps_mul tmp5, tmp5, scale + ps_mul tmp7, tmp7, scale + psq_st tmp0, 0(m), 0, 0 + psq_st tmp5, 8(m), 1, 0 + ps_merge10 tmp3, tmp7, c_zero + ps_merge01 tmp9, tmp7, tmp5 + psq_st tmp3, 24(m), 0, 0 + psq_st tmp9, 32(m), 0, 0 + } +#endif // clang-format on +} + +void C_MTXLookAt(GC_Mtx m, const Vec* camPos, const Vec* camUp, const Vec* target) { + Vec vLook; + Vec vRight; + Vec vUp; + + ASSERTMSGLINE(2105, m, "MTXLookAt(): NULL MtxPtr 'm' "); + ASSERTMSGLINE(2106, camPos, "MTXLookAt(): NULL VecPtr 'camPos' "); + ASSERTMSGLINE(2107, camUp, "MTXLookAt(): NULL VecPtr 'camUp' "); + ASSERTMSGLINE(2108, target, "MTXLookAt(): NULL Point3dPtr 'target' "); + + vLook.x = camPos->x - target->x; + vLook.y = camPos->y - target->y; + vLook.z = camPos->z - target->z; + VECNormalize(&vLook, &vLook); + VECCrossProduct(camUp, &vLook, &vRight); + VECNormalize(&vRight, &vRight); + VECCrossProduct(&vLook, &vRight, &vUp); + m[0][0] = vRight.x; + m[0][1] = vRight.y; + m[0][2] = vRight.z; + m[0][3] = -((camPos->z * vRight.z) + ((camPos->x * vRight.x) + (camPos->y * vRight.y))); + m[1][0] = vUp.x; + m[1][1] = vUp.y; + m[1][2] = vUp.z; + m[1][3] = -((camPos->z * vUp.z) + ((camPos->x * vUp.x) + (camPos->y * vUp.y))); + m[2][0] = vLook.x; + m[2][1] = vLook.y; + m[2][2] = vLook.z; + m[2][3] = -((camPos->z * vLook.z) + ((camPos->x * vLook.x) + (camPos->y * vLook.y))); +} + +void C_MTXLightFrustum(GC_Mtx m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 scaleS, + f32 scaleT, f32 transS, f32 transT) +{ + f32 _tmp; + + _tmp = 1 / (r - l); + m[0][0] = (scaleS * (2 * n * _tmp)); + m[0][1] = 0; + m[0][2] = (scaleS * (_tmp * (r + l))) - transS; + m[0][3] = 0; + _tmp = 1 / (t - b); + m[1][0] = 0; + m[1][1] = (scaleT * (2 * n * _tmp)); + m[1][2] = (scaleT * (_tmp * (t + b))) - transT; + m[1][3] = 0; + m[2][0] = 0; + m[2][1] = 0; + m[2][2] = -1; + m[2][3] = 0; +} + +void C_MTXLightPerspective(GC_Mtx m, f32 fovY, f32 aspect, f32 scaleS, f32 scaleT, + f32 transS, f32 transT) +{ + f32 angle; + f32 cot; + + angle = (0.5f * fovY); + angle = angle * 0.017453293f; + cot = 1 / tanf(angle); + m[0][0] = (scaleS * (cot / aspect)); + m[0][1] = 0; + m[0][2] = -transS; + m[0][3] = 0; + m[1][0] = 0; + m[1][1] = (cot * scaleT); + m[1][2] = -transT; + m[1][3] = 0; + m[2][0] = 0; + m[2][1] = 0; + m[2][2] = -1; + m[2][3] = 0; +} + +void C_MTXLightOrtho(GC_Mtx m, f32 t, f32 b, f32 l, f32 r, f32 scaleS, f32 scaleT, + f32 transS, f32 transT) +{ + f32 _tmp; + + _tmp = 1 / (r - l); + m[0][0] = (2 * _tmp * scaleS); + m[0][1] = 0; + m[0][2] = 0; + m[0][3] = (transS + (scaleS * (_tmp * -(r + l)))); + _tmp = 1 / (t - b); + m[1][0] = 0; + m[1][1] = (2 * _tmp * scaleT); + m[1][2] = 0; + m[1][3] = (transT + (scaleT * (_tmp * -(t + b)))); + m[2][0] = 0; + m[2][1] = 0; + m[2][2] = 0; + m[2][3] = 1; +} diff --git a/src/static/GAEJ01_01/dolphin/mtx/mtx44.c b/src/static/GAEJ01_01/dolphin/mtx/mtx44.c new file mode 100644 index 00000000..910d6576 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/mtx/mtx44.c @@ -0,0 +1,88 @@ +#include +#include +#include + +extern f32 tanf(f32); + +// NOTE: this is not present in SMS but needed for .sdata2 to match +// stolen from prime +void C_MTXFrustum(Mtx44 m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 f) +{ + f32 tmp; + + tmp = 1.0f / (r - l); + m[0][0] = (2 * n) * tmp; + m[0][1] = 0.0f; + m[0][2] = (r + l) * tmp; + m[0][3] = 0.0f; + + tmp = 1.0f / (t - b); + m[1][0] = 0.0f; + m[1][1] = (2 * n) * tmp; + m[1][2] = (t + b) * tmp; + m[1][3] = 0.0f; + + m[2][0] = 0.0f; + m[2][1] = 0.0f; + + tmp = 1.0f / (f - n); + m[2][2] = -(n)*tmp; + m[2][3] = -(f * n) * tmp; + m[3][0] = 0.0f; + m[3][1] = 0.0f; + m[3][2] = -1.0f; + m[3][3] = 0.0f; +} + +void C_MTXPerspective(GC_Mtx m, f32 fovY, f32 aspect, f32 n, f32 f) +{ + f32 angle; + f32 cot; + f32 tmp; + + angle = (0.5f * fovY); + angle = angle * 0.017453293f; + cot = 1 / tanf(angle); + m[0][0] = (cot / aspect); + m[0][1] = 0; + m[0][2] = 0; + m[0][3] = 0; + m[1][0] = 0; + m[1][1] = (cot); + m[1][2] = 0; + m[1][3] = 0; + m[2][0] = 0; + m[2][1] = 0; + tmp = 1 / (f - n); + m[2][2] = (-n * tmp); + m[2][3] = (tmp * -(f * n)); + m[3][0] = 0; + m[3][1] = 0; + m[3][2] = -1; + m[3][3] = 0; +} + +void C_MTXOrtho(GC_Mtx m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 f) +{ + f32 tmp; + + tmp = 1 / (r - l); + m[0][0] = 2 * tmp; + m[0][1] = 0; + m[0][2] = 0; + m[0][3] = (tmp * -(r + l)); + tmp = 1 / (t - b); + m[1][0] = 0; + m[1][1] = 2 * tmp; + m[1][2] = 0; + m[1][3] = (tmp * -(t + b)); + m[2][0] = 0; + m[2][1] = 0; + tmp = 1 / (f - n); + m[2][2] = (-1 * tmp); + m[2][3] = (-f * tmp); + m[3][0] = 0; + m[3][1] = 0; + m[3][2] = 0; + m[3][3] = 1; +} diff --git a/src/static/GAEJ01_01/dolphin/mtx/mtxvec.c b/src/static/GAEJ01_01/dolphin/mtx/mtxvec.c new file mode 100644 index 00000000..325609da --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/mtx/mtxvec.c @@ -0,0 +1,103 @@ +#include +#include + +#define qr0 0 + +asm void PSMTXMultVec(const register Mtx44 m, const register Vec* src, register Vec* dst) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + psq_l f0, Vec.x(src), 0, qr0 + psq_l f2, 0(m), 0, qr0 + psq_l f1, Vec.z(src), 1, qr0 + ps_mul f4, f2, f0 + psq_l f3, 8(m), 0, qr0 + ps_madd f5, f3, f1, f4 + psq_l f8, 16(m), 0, qr0 + ps_sum0 f6, f5, f6, f5 + psq_l f9, 24(m), 0, qr0 + ps_mul f10, f8, f0 + psq_st f6, Vec.x(dst), 1, qr0 + ps_madd f11, f9, f1, f10 + psq_l f2, 32(m), 0, qr0 + ps_sum0 f12, f11, f12, f11 + psq_l f3, 40(m), 0, qr0 + ps_mul f4, f2, f0 + psq_st f12, Vec.y(dst), 1, qr0 + ps_madd f5, f3, f1, f4 + ps_sum0 f6, f5, f6, f5 + psq_st f6, Vec.z(dst), 1, qr0 + blr +#endif // clang-format on +} + +asm void PSMTXMultVecArray(const register GC_Mtx m, const register Vec* srcBase, + register Vec* dstBase, register u32 count) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f13, 0x0(m), 0, qr0 + psq_l f12, 0x10(m), 0, qr0 + subi count, count, 0x1 + psq_l f11, 0x8(m), 0, qr0 + ps_merge00 f0, f13, f12 + subi dstBase, dstBase, 0x4 + psq_l f10, 0x18(m), 0, qr0 + ps_merge11 f1, f13, f12 + + mtctr count + psq_l f4, 0x20(m), 0, qr0 + ps_merge00 f2, f11, f10 + psq_l f5, 0x28(m), 0, qr0 + ps_merge11 f3, f11, f10 + psq_l f6, Vec.x(srcBase), 0, qr0 + psq_lu f7, Vec.z(srcBase), 1, qr0 + ps_madds0 f8, f0, f6, f3 + ps_mul f9, f4, f6 + ps_madds1 f8, f1, f6, f8 + ps_madd f10, f5, f7, f9 + +loop: + psq_lu f6, Vec.y(srcBase), 0, qr0 + ps_madds0 f12, f2, f7, f8 + psq_lu f7, Vec.z(srcBase), 1, qr0 + ps_sum0 f13, f10, f9, f10 + ps_madds0 f8, f0, f6, f3 + ps_mul f9, f4, f6 + psq_stu f12, 0x4(dstBase), 0, qr0 + ps_madds1 f8, f1, f6, f8 + psq_stu f13, 0x8(dstBase), 1, qr0 + ps_madd f10, f5, f7, f9 + bdnz loop + + ps_madds0 f12, f2, f7, f8 + ps_sum0 f13, f10, f9, f10 + psq_stu f12, 0x4(dstBase), 0, qr0 + psq_stu f13, 0x8(dstBase), 1, qr0 +#endif // clang-format on +} + +asm void PSMTXMultVecSR(const register Mtx44 m, const register Vec* src, register Vec* dst) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f0, 0x0(m), 0, qr0 + psq_l f6, Vec.x(src), 0, qr0 + psq_l f2, 0x10(m), 0, qr0 + ps_mul f8, f0, f6 + psq_l f4, 0x20(m), 0, qr0 + ps_mul f10, f2, f6 + psq_l f7, Vec.z(src), 1, qr0 + ps_mul f12, f4, f6 + psq_l f3, 0x18(m), 0, qr0 + ps_sum0 f8, f8, f8, f8 + psq_l f5, 0x28(m), 0, qr0 + ps_sum0 f10, f10, f10, f10 + psq_l f1, 0x8(m), 0, qr0 + ps_sum0 f12, f12, f12, f12 + ps_madd f9, f1, f7, f8 + psq_st f9, Vec.x(dst), 1, qr0 + ps_madd f11, f3, f7, f10 + psq_st f11, Vec.y(dst), 1, qr0 + ps_madd f13, f5, f7, f12 + psq_st f13, Vec.z(dst), 1, qr0 +#endif // clang-format on +} diff --git a/src/static/GAEJ01_01/dolphin/mtx/vec.c b/src/static/GAEJ01_01/dolphin/mtx/vec.c new file mode 100644 index 00000000..995438aa --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/mtx/vec.c @@ -0,0 +1,171 @@ +#include +#include + +#define qr0 0 + +asm void PSVECAdd(register Vec* a, register Vec* b, register Vec* c) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f2, Vec.x(a), 0, qr0 + psq_l f4, Vec.x(b), 0, qr0 + ps_add f6, f2, f4 + psq_st f6, Vec.x(c), 0, qr0 + psq_l f3, Vec.z(a), 1, qr0 + psq_l f5, Vec.z(b), 1, qr0 + ps_add f7, f3, f5 + psq_st f7, Vec.z(c), 1, qr0 +#endif // clang-format on +} + +asm void PSVECSubtract(register Vec* a, register Vec* b, register Vec* c) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f2, Vec.x(a), 0, qr0 + psq_l f4, Vec.x(b), 0, qr0 + ps_sub f6, f2, f4 + psq_st f6, Vec.x(c), 0, qr0 + psq_l f3, Vec.z(a), 1, qr0 + psq_l f5, Vec.z(b), 1, qr0 + ps_sub f7, f3, f5 + psq_st f7, Vec.z(c), 1, qr0 +#endif // clang-format on +} + +asm void PSVECScale(register Vec* src, register Vec* dst, register f32 mult) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f0, Vec.x(src), 0, qr0 + psq_l f2, Vec.z(src), 1, qr0 + ps_muls0 f0, f0, f1 + psq_st f0, Vec.x(dst), 0, qr0 + ps_muls0 f0, f2, f1 + psq_st f0, Vec.z(dst), 1, qr0 +#endif // clang-format on +} + +void PSVECNormalize(const register Vec* vec1, register Vec* dst) +{ + register float c_half = 0.5f; + register float c_three = 3.0f; + register float v1_xy; + register float v1_z; + register float xx_zz; + register float xx_yy; + register float sqsum; + register float rsqrt; + register float nwork0; + register float nwork1; + +#ifdef __MWERKS__ // clang-format off + asm + { + psq_l v1_xy, Vec.x(vec1), 0, qr0 + ps_mul xx_yy, v1_xy, v1_xy + psq_l v1_z, Vec.z(vec1), 1, qr0 + ps_madd xx_zz, v1_z, v1_z, xx_yy + ps_sum0 sqsum, xx_zz, v1_z, xx_yy + frsqrte rsqrt, sqsum + fmuls nwork0, rsqrt, rsqrt + fmuls nwork1, rsqrt, c_half + fnmsubs nwork0, nwork0, sqsum, c_three + fmuls rsqrt, nwork0, nwork1 + ps_muls0 v1_xy, v1_xy, rsqrt + psq_st v1_xy, Vec.x(dst), 0, qr0 + ps_muls0 v1_z, v1_z, rsqrt + psq_st v1_z, Vec.z(dst), 1, qr0 + } +#endif // clang-format on +} + +asm float PSVECMag(register Vec* v) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f0, Vec.x(v), 0, qr0 + ps_mul f0, f0, f0 + lfs f1, Vec.z(v) + ps_madd f1, f1, f1, f0 + lfs f4, 0.5f + ps_sum0 f1, f1, f0, f0 + frsqrte f0, f1 + lfs f3, 3.0f + fmuls f2, f0, f0 + fmuls f0, f0, f4 + fnmsubs f2, f2, f1, f3 + fmuls f0, f2, f0 + fsel f0, f0, f0, f1 + fmuls f1, f1, f0 +#endif // clang-format on +} + +asm f32 PSVECDotProduct(register Vec* vec1, register Vec* vec2) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f2, Vec.y(vec1), 0, qr0 + psq_l f3, Vec.y(vec2), 0, qr0 + ps_mul f2, f2, f3 + psq_l f5, Vec.x(vec1), 0, qr0 + psq_l f4, Vec.x(vec2), 0, qr0 + ps_madd f3, f5, f4, f2 + ps_sum0 f1, f3, f2, f2 +#endif // clang-format on +} + +asm void PSVECCrossProduct(register Vec* vec1, register Vec* vec2, + register Vec* dst) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f1, Vec.x(vec2), 0, qr0 + lfs f2, Vec.z(vec1) + psq_l f0, Vec.x(vec1), 0, qr0 + ps_merge10 f6, f1, f1 + lfs f3, Vec.z(vec2) + ps_mul f4, f1, f2 + ps_muls0 f7, f1, f0 + ps_msub f5, f0, f3, f4 + ps_msub f8, f0, f6, f7 + ps_merge11 f9, f5, f5 + ps_merge01 f10, f5, f8 + psq_st f9, Vec.x(dst), 1, qr0 + ps_neg f10, f10 + psq_st f10, Vec.y(dst), 0, qr0 +#endif // clang-format on +} + +asm f32 PSVECSquareDistance(register Vec* vec1, register Vec* vec2) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f0, Vec.y(vec1), 0, qr0 + psq_l f1, Vec.y(vec2), 0, qr0 + ps_sub f2, f0, f1 + psq_l f0, Vec.x(vec1), 0, qr0 + psq_l f1, Vec.x(vec2), 0, qr0 + ps_mul f2, f2, f2 + ps_sub f0, f0, f1 + ps_madd f1, f0, f0, f2 + ps_sum0 f1, f1, f2, f2 +#endif // clang-format on +} + +asm f32 PSVECDistance(register Vec* vec1, register Vec* vec2) +{ +#ifdef __MWERKS__ // clang-format off + psq_l f0, Vec.y(vec1), 0, qr0 + psq_l f1, Vec.y(vec2), 0, qr0 + ps_sub f2, f0, f1 + psq_l f0, Vec.x(vec1), 0, qr0 + psq_l f1, Vec.x(vec2), 0, qr0 + ps_mul f2, f2, f2 + ps_sub f0, f0, f1 + lfs f3, 0.5f + ps_madd f0, f0, f0, f2 + ps_sum0 f0, f0, f2, f2 + lfs f4, 3.0f + frsqrte f1, f0 + fmuls f2, f1, f1 + fmuls f1, f1, f3 + fnmsubs f2, f2, f0, f4 + fmuls f1, f2, f1 + fsel f1, f1, f1, f0 + fmuls f1, f0, f1 +#endif // clang-format on +} diff --git a/src/static/GAEJ01_01/dolphin/odenotstub/odenotstub.c b/src/static/GAEJ01_01/dolphin/odenotstub/odenotstub.c new file mode 100644 index 00000000..05b11c60 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/odenotstub/odenotstub.c @@ -0,0 +1,5 @@ +#include "types.h" + +BOOL Hu_IsStub(void){ + return 0; +} \ No newline at end of file diff --git a/src/static/GAEJ01_01/dolphin/os/OS.c b/src/static/GAEJ01_01/dolphin/os/OS.c new file mode 100644 index 00000000..80c659eb --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OS.c @@ -0,0 +1,619 @@ +#include +#include +#include +#include +#include +#include +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +void EnableMetroTRKInterrupts(void); + +#define OS_CURRENTCONTEXT_PADDR 0x00C0 + +#define OS_EXCEPTIONTABLE_ADDR 0x3000 +#define OS_DBJUMPPOINT_ADDR 0x60 +// memory locations for important stuff +#define OS_BI2_DEBUG_ADDRESS 0x800000F4 +#define OS_BI2_DEBUGFLAG_OFFSET 0xC +#define PAD3_BUTTON_ADDR 0x800030E4 +#define OS_DVD_DEVICECODE 0x800030E6 +#define DEBUGFLAG_ADDR 0x800030E8 +#define OS_DEBUG_ADDRESS_2 0x800030E9 +#define DB_EXCEPTIONRET_OFFSET 0xC +#define DB_EXCEPTIONDEST_OFFSET 0x8 + +extern unsigned long __DVDLongFileNameFlag; +extern unsigned long __PADSpec; +extern unsigned char __ArenaLo[]; +extern char _stack_addr[]; +extern unsigned char __ArenaHi[]; + +void PPCMtmmcr0(u32); +void PPCMtmmcr1(u32); +void PPCMtpmc1(u32); +void PPCMtpmc2(u32); +void PPCMtpmc3(u32); +void PPCMtpmc4(u32); + +char* __OSVersion = "<< Dolphin SDK - OS\trelease build: Nov 26 2003 05:18:37 (0x2301) >>"; + +// dummy entry points to the OS Exception vector +void __OSEVStart(void); +void __OSEVEnd(void); +void __OSEVSetNumber(void); +void __OSExceptionVector(void); + +void __DBVECTOR(void); +void __OSDBINTSTART(void); +void __OSDBINTEND(void); +void __OSDBJUMPSTART(void); +void __OSDBJUMPEND(void); + +#define NOP 0x60000000 + +typedef void (*OSExceptionHandler)(u8, struct OSContext*); + +static DVDDriveInfo DriveInfo __attribute__((aligned(0x20))); +static DVDCommandBlock DriveBlock; + +static OSBootInfo* BootInfo; +static volatile u32* BI2DebugFlag; +static u32* BI2DebugFlagHolder; +__declspec(weak) BOOL __OSIsGcam = FALSE; +static f64 ZeroF; +static f32 ZeroPS[2]; +static BOOL AreWeInitialized = FALSE; +static OSExceptionHandler* OSExceptionTable; +OSTime __OSStartTime; +BOOL __OSInIPL; +void* __OSSavedRegionStart; +void* __OSSavedRegionEnd; + +// functions +static void OSExceptionInit(void); +static void OSDefaultExceptionHandler(u8 exception /* r3 */, + OSContext* context /* r4 */); + +asm void __OSFPRInit(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + + mfmsr r3 + ori r3, r3, 0x2000 + mtmsr r3 + + mfspr r3, 0x398 + rlwinm. r3, r3, 3, 0x1f, 0x1f + beq skip_ps_init + + lis r3, ZeroPS@ha + addi r3, r3, ZeroPS@l + psq_l f0, 0(r3), 0, 0 + ps_mr f1, f0 + ps_mr f2, f0 + ps_mr f3, f0 + ps_mr f4, f0 + ps_mr f5, f0 + ps_mr f6, f0 + ps_mr f7, f0 + ps_mr f8, f0 + ps_mr f9, f0 + ps_mr f10, f0 + ps_mr f11, f0 + ps_mr f12, f0 + ps_mr f13, f0 + ps_mr f14, f0 + ps_mr f15, f0 + ps_mr f16, f0 + ps_mr f17, f0 + ps_mr f18, f0 + ps_mr f19, f0 + ps_mr f20, f0 + ps_mr f21, f0 + ps_mr f22, f0 + ps_mr f23, f0 + ps_mr f24, f0 + ps_mr f25, f0 + ps_mr f26, f0 + ps_mr f27, f0 + ps_mr f28, f0 + ps_mr f29, f0 + ps_mr f30, f0 + ps_mr f31, f0 + +skip_ps_init: + lfd f0, ZeroF(r13) + fmr f1, f0 + fmr f2, f0 + fmr f3, f0 + fmr f4, f0 + fmr f5, f0 + fmr f6, f0 + fmr f7, f0 + fmr f8, f0 + fmr f9, f0 + fmr f10, f0 + fmr f11, f0 + fmr f12, f0 + fmr f13, f0 + fmr f14, f0 + fmr f15, f0 + fmr f16, f0 + fmr f17, f0 + fmr f18, f0 + fmr f19, f0 + fmr f20, f0 + fmr f21, f0 + fmr f22, f0 + fmr f23, f0 + fmr f24, f0 + fmr f25, f0 + fmr f26, f0 + fmr f27, f0 + fmr f28, f0 + fmr f29, f0 + fmr f30, f0 + fmr f31, f0 + + mtfsf 0xff, f0 + blr +#endif // clang-format on +} + +unsigned long OSGetConsoleType() +{ + if ((!BootInfo) || (BootInfo->consoleType == 0)) { + return OS_CONSOLE_ARTHUR; + } + return BootInfo->consoleType; +} + +volatile u16 __OSDeviceCode AT_ADDRESS(0x800030E6); + +static void ClearArena() +{ + if (OSGetResetCode() != -0x80000000) { + __OSSavedRegionStart = NULL; + __OSSavedRegionEnd = NULL; + memset(OSGetArenaLo(), 0, (u8*)OSGetArenaHi() - (u8*)OSGetArenaLo()); + return; + } + + __OSSavedRegionStart = BOOT_REGION_START; + __OSSavedRegionEnd = BOOT_REGION_END; + + if (BOOT_REGION_START == NULL) { + memset(OSGetArenaLo(), 0, (u8*)OSGetArenaHi() - (u8*)OSGetArenaLo()); + return; + } + + if ((u8*)OSGetArenaLo() < (u8*)__OSSavedRegionStart) { + if ((u8*)OSGetArenaHi() <= (u8*)__OSSavedRegionStart) { + memset(OSGetArenaLo(), 0, + (u8*)OSGetArenaHi() - (u8*)OSGetArenaLo()); + return; + } + + memset(OSGetArenaLo(), 0, + (u8*)__OSSavedRegionStart - (u8*)OSGetArenaLo()); + + if ((u8*)OSGetArenaHi() > (u8*)__OSSavedRegionEnd) { + memset(__OSSavedRegionEnd, 0, + (u8*)OSGetArenaHi() - (u8*)__OSSavedRegionEnd); + } + } +} + +static void InquiryCallback(s32 result, struct DVDCommandBlock* block) +{ + switch (block->state) { + case 0: + __OSDeviceCode = DriveInfo.deviceCode | 0x8000; + break; + default: + __OSDeviceCode = 1; + break; + } +} + +void OSInit() +{ + BI2Debug* DebugInfo; + void* debugArenaLo; + u32 inputConsoleType; + u32 tdev; + + if ((BOOL)AreWeInitialized == FALSE) { + AreWeInitialized = TRUE; + + __OSStartTime = __OSGetSystemTime(); + OSDisableInterrupts(); + + PPCMtmmcr0(0); + PPCMtmmcr1(0); + PPCMtpmc1(0); + PPCMtpmc2(0); + PPCMtpmc3(0); + PPCMtpmc4(0); + PPCDisableSpeculation(); + PPCSetFpNonIEEEMode(); + + BI2DebugFlag = 0; + BootInfo = (OSBootInfo*)OS_BASE_CACHED; + + __DVDLongFileNameFlag = (u32)0; + + DebugInfo = (BI2Debug*)*((u32*)OS_BI2_DEBUG_ADDRESS); + + if (DebugInfo != NULL) { + BI2DebugFlag = &DebugInfo->debugFlag; + __PADSpec = (u32)DebugInfo->padSpec; + *((u8*)DEBUGFLAG_ADDR) = (u8)*BI2DebugFlag; + *((u8*)OS_DEBUG_ADDRESS_2) = (u8)__PADSpec; + } else if (BootInfo->arenaHi) { + BI2DebugFlagHolder = (u32*)*((u8*)DEBUGFLAG_ADDR); + BI2DebugFlag = (u32*)&BI2DebugFlagHolder; + __PADSpec = (u32) * ((u8*)OS_DEBUG_ADDRESS_2); + } + + __DVDLongFileNameFlag = 1; + + OSSetArenaLo((BootInfo->arenaLo == NULL) ? __ArenaLo : BootInfo->arenaLo); + + if ((BootInfo->arenaLo == NULL) && (BI2DebugFlag != 0) && (*BI2DebugFlag < 2)) { + debugArenaLo = (char*)(((u32)_stack_addr + 0x1f) & ~0x1f); + OSSetArenaLo(debugArenaLo); + } + + OSSetArenaHi((BootInfo->arenaHi == NULL) ? __ArenaHi : BootInfo->arenaHi); + + OSExceptionInit(); + __OSInitSystemCall(); + OSInitAlarm(); + __OSModuleInit(); + __OSInterruptInit(); + __OSSetInterruptHandler(__OS_INTERRUPT_PI_RSW, __OSResetSWInterruptHandler); + __OSContextInit(); + __OSCacheInit(); + EXIInit(); + SIInit(); + __OSInitSram(); + __OSThreadInit(); + __OSInitAudioSystem(); + PPCMthid2(PPCMfhid2() & 0xBFFFFFFF); + if ((BOOL)__OSInIPL == FALSE) { + __OSInitMemoryProtection(); + } + + OSReport("\nDolphin OS\n"); + OSReport("Kernel built : %s %s\n", "Nov 26 2003", "05:18:37"); + OSReport("Console Type : "); + + if (BootInfo == NULL || (inputConsoleType = BootInfo->consoleType) == 0) { + inputConsoleType = OS_CONSOLE_ARTHUR; + } else { + inputConsoleType = BootInfo->consoleType; + } + + switch (inputConsoleType & 0xF0000000) { + case OS_CONSOLE_RETAIL: + OSReport("Retail %d\n", inputConsoleType); + break; + case OS_CONSOLE_DEVELOPMENT: + case OS_CONSOLE_TDEVKIT: + switch (inputConsoleType & 0x0FFFFFFF) { + case OS_CONSOLE_EMULATOR: + OSReport("Mac Emulator\n"); + break; + case OS_CONSOLE_PC_EMULATOR: + OSReport("PC Emulator\n"); + break; + case OS_CONSOLE_ARTHUR: + OSReport("EPPC Arthur\n"); + break; + case OS_CONSOLE_MINNOW: + OSReport("EPPC Minnow\n"); + break; + default: + tdev = (u32)inputConsoleType & 0x0FFFFFFF; + OSReport("Development HW%d (%08x)\n", tdev - 3, inputConsoleType); + break; + } + break; + default: + OSReport("%08x\n", inputConsoleType); + break; + } + + OSReport("Memory %d MB\n", (u32)BootInfo->memorySize >> 0x14U); + OSReport("Arena : 0x%x - 0x%x\n", OSGetArenaLo(), OSGetArenaHi()); + OSRegisterVersion(__OSVersion); + + if (BI2DebugFlag && ((*BI2DebugFlag) >= 2)) { + EnableMetroTRKInterrupts(); + } + + ClearArena(); + OSEnableInterrupts(); + + if ((BOOL)__OSInIPL == FALSE) { + DVDInit(); + if ((BOOL)__OSIsGcam) { + __OSDeviceCode = 0x9000; + return; + } + DCInvalidateRange(&DriveInfo, sizeof(DriveInfo)); + DVDInquiryAsync(&DriveBlock, &DriveInfo, InquiryCallback); + } + } +} + +static u32 __OSExceptionLocations[] = { + 0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500, + 0x00000600, 0x00000700, 0x00000800, 0x00000900, 0x00000C00, + 0x00000D00, 0x00000F00, 0x00001300, 0x00001400, 0x00001700, +}; + +static void OSExceptionInit(void) +{ + __OSException exception; + void* destAddr; + + // These two vars help us change the exception number embedded + // in the exception handler code. + u32* opCodeAddr; + u32 oldOpCode; + + // Address range of the actual code to be copied. + u8* handlerStart; + u32 handlerSize; + + // Install the first level exception vector. + opCodeAddr = (u32*)__OSEVSetNumber; + oldOpCode = *opCodeAddr; + handlerStart = (u8*)__OSEVStart; + handlerSize = (u32)((u8*)__OSEVEnd - (u8*)__OSEVStart); + + // Install the DB integrator, only if we are the first OSInit to be run + destAddr = (void*)OSPhysicalToCached(OS_DBJUMPPOINT_ADDR); + if (*(u32*)destAddr == 0) // Lomem should be zero cleared only once by BS2 + { + DBPrintf("Installing OSDBIntegrator\n"); + memcpy(destAddr, (void*)__OSDBINTSTART, + (u32)__OSDBJUMPSTART - (u32)__OSDBINTSTART); + DCFlushRangeNoSync(destAddr, + (u32)__OSDBJUMPSTART - (u32)__OSDBINTSTART); + __sync(); + ICInvalidateRange(destAddr, (u32)__OSDBJUMPSTART - (u32)__OSDBINTSTART); + } + + // Copy the right vector into the table + for (exception = 0; exception < __OS_EXCEPTION_MAX; exception++) { + if (BI2DebugFlag && (*BI2DebugFlag >= 2) + && __DBIsExceptionMarked(exception)) { + // this DBPrintf is suspicious. + DBPrintf(">>> OSINIT: exception %d commandeered by TRK\n", + exception); + continue; + } + + // Modify the copy of code in text before transferring + // to the exception table. + *opCodeAddr = oldOpCode | exception; + + // Modify opcodes at __DBVECTOR if necessary + if (__DBIsExceptionMarked(exception)) { + DBPrintf(">>> OSINIT: exception %d vectored to debugger\n", + exception); + memcpy((void*)__DBVECTOR, (void*)__OSDBJUMPSTART, + (u32)__OSDBJUMPEND - (u32)__OSDBJUMPSTART); + } else { + // make sure the opcodes are still nop + u32* ops = (u32*)__DBVECTOR; + int cb; + + for (cb = 0; cb < (u32)__OSDBJUMPEND - (u32)__OSDBJUMPSTART; + cb += sizeof(u32)) { + *ops++ = NOP; + } + } + + // Install the modified handler. + destAddr + = (void*)OSPhysicalToCached(__OSExceptionLocations[(u32)exception]); + memcpy(destAddr, handlerStart, handlerSize); + DCFlushRangeNoSync(destAddr, handlerSize); + __sync(); + ICInvalidateRange(destAddr, handlerSize); + } + // initialize pointer to exception table + OSExceptionTable = (void*)OSPhysicalToCached(OS_EXCEPTIONTABLE_ADDR); + + // install default exception handlers + for (exception = 0; exception < __OS_EXCEPTION_MAX; exception++) { + __OSSetExceptionHandler(exception, OSDefaultExceptionHandler); + } + + // restore the old opcode, so that we can re-start an application without + // downloading the text segments + *opCodeAddr = oldOpCode; + + DBPrintf("Exceptions initialized...\n"); +} + +static asm void __OSDBIntegrator(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc +entry __OSDBINTSTART + li r5, OS_DBINTERFACE_ADDR + mflr r3 + stw r3, DB_EXCEPTIONRET_OFFSET(r5) + lwz r3, DB_EXCEPTIONDEST_OFFSET(r5) + oris r3, r3, OS_CACHED_REGION_PREFIX + mtlr r3 + li r3, 0x30 // MSR_IR | MSR_DR // turn on memory addressing + mtmsr r3 + blr +entry __OSDBINTEND +#endif // clang-format on +} + +static asm void __OSDBJump(void) { +#ifdef __MWERKS__ // clang-format off + nofralloc +entry __OSDBJUMPSTART + bla OS_DBJUMPPOINT_ADDR +entry __OSDBJUMPEND +#endif // clang-format on +} + +__OSExceptionHandler __OSSetExceptionHandler(__OSException exception, + __OSExceptionHandler handler) +{ + __OSExceptionHandler oldHandler; + + oldHandler = OSExceptionTable[exception]; + OSExceptionTable[exception] = handler; + return oldHandler; +} + +__OSExceptionHandler __OSGetExceptionHandler(__OSException exception) +{ + return OSExceptionTable[exception]; +} + +static asm void OSExceptionVector(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + +entry __OSEVStart + // Save r4 into SPRG0 + mtsprg 0, r4 + + // Load current context physical address into r4 + lwz r4, OS_CURRENTCONTEXT_PADDR + + // Save r3 - r5 into the current context + stw r3, OS_CONTEXT_R3(r4) + mfsprg r3, 0 + stw r3, OS_CONTEXT_R4(r4) + stw r5, OS_CONTEXT_R5(r4) + + lhz r3, OS_CONTEXT_STATE(r4) + ori r3, r3, OS_CONTEXT_STATE_EXC + sth r3, OS_CONTEXT_STATE(r4) + + // Save misc registers + mfcr r3 + stw r3, OS_CONTEXT_CR(r4) + mflr r3 + stw r3, OS_CONTEXT_LR(r4) + mfctr r3 + stw r3, OS_CONTEXT_CTR(r4) + mfxer r3 + stw r3, OS_CONTEXT_XER(r4) + mfsrr0 r3 + stw r3, OS_CONTEXT_SRR0(r4) + mfsrr1 r3 + stw r3, OS_CONTEXT_SRR1(r4) + mr r5, r3 + +entry __DBVECTOR + nop + + // Set SRR1[IR|DR] to turn on address + // translation at the next RFI + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + // This lets us change the exception number based on the + // exception we're installing. +entry __OSEVSetNumber + addi r3, 0, 0x0000 + + // Load current context virtual address into r4 + lwz r4, 0xD4 + + // Check non-recoverable interrupt + rlwinm. r5, r5, 0, MSR_RI_BIT, MSR_RI_BIT + bne recoverable + addis r5, 0, OSDefaultExceptionHandler@ha + addi r5, r5, OSDefaultExceptionHandler@l + mtsrr0 r5 + rfi + // NOT REACHED HERE + +recoverable: + // Locate exception handler. + rlwinm r5, r3, 2, 22, 29 // r5 contains exception*4 + lwz r5, OS_EXCEPTIONTABLE_ADDR(r5) + mtsrr0 r5 + + // Final state + // r3 - exception number + // r4 - pointer to context + // r5 - garbage + // srr0 - exception handler + // srr1 - address translation enalbed, not yet recoverable + + rfi + // NOT REACHED HERE + // The handler will restore state + +entry __OSEVEnd + nop +#endif // clang-format on +} + +void __OSUnhandledException(__OSException exception, OSContext* context, + u32 dsisr, u32 dar); +asm void OSDefaultExceptionHandler(register __OSException exception, + register OSContext* context) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + OS_EXCEPTION_SAVE_GPRS(context) + mfdsisr r5 + mfdar r6 + stwu r1, -0x8(r1) + b __OSUnhandledException +#endif // clang-format on +} + +void __OSPSInit(void) +{ + PPCMthid2(PPCMfhid2() | 0xA0000000); + ICFlashInvalidate(); + __sync(); +#ifdef __MWERKS__ // clang-format off + asm + { + li r3, 0 + mtspr GQR0, r3 + mtspr GQR1, r3 + mtspr GQR2, r3 + mtspr GQR3, r3 + mtspr GQR4, r3 + mtspr GQR5, r3 + mtspr GQR6, r3 + mtspr GQR7, r3 + } +#endif // clang-format on +} + +#define DI_CONFIG_IDX 0x9 +#define DI_CONFIG_CONFIG_MASK 0xFF + +u32 __OSGetDIConfig(void) +{ + return (__DIRegs[DI_CONFIG_IDX] & DI_CONFIG_CONFIG_MASK); +} + +void OSRegisterVersion(const char* id) +{ + OSReport("%s\n", id); +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSAlarm.c b/src/static/GAEJ01_01/dolphin/os/OSAlarm.c new file mode 100644 index 00000000..1f313fc0 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSAlarm.c @@ -0,0 +1,235 @@ +#include "dolphin/os/OSAlarm.h" +#include "dolphin/os/OSTime.h" +#include "dolphin/os/OSContext.h" +#include "dolphin/os/OSInterrupt.h" +#include "dolphin/os/OSException.h" +#include "dolphin/os/OSReset.h" +#include "dolphin/os/OSInterrupt.h" + +#define OS_RESET_PRIO_ALARM 0xFFFFFFFF + +// OSAlarm with the tag field (stored in the padding after handler) +typedef struct OSAlarmTagged { + OSAlarmHandler handler; + u32 tag; +} OSAlarmTagged; + +BOOL __DVDTestAlarm(OSAlarm* alarm); + +struct OSAlarmQueue { + struct OSAlarm* head; + struct OSAlarm* tail; +}; + +static struct OSAlarmQueue AlarmQueue; + +static void DecrementerExceptionHandler(u8, OSContext*); +static BOOL OnReset(BOOL final); + +static OSResetFunctionInfo ResetFunctionInfo = { OnReset, OS_RESET_PRIO_ALARM }; + +static void SetTimer(struct OSAlarm* alarm) { + OSTime delta = alarm->fire - __OSGetSystemTime(); + + if (delta < 0) { + PPCMtdec(0); + } else if (delta < 0x80000000) { + PPCMtdec((u32)delta); + } else { + PPCMtdec(0x7fffffff); + } +} + +void OSInitAlarm(void) { + + if (__OSGetExceptionHandler(8) != DecrementerExceptionHandler) { + AlarmQueue.head = AlarmQueue.tail = NULL; + __OSSetExceptionHandler(8, DecrementerExceptionHandler); + OSRegisterResetFunction(&ResetFunctionInfo); + } +} +void OSCreateAlarm(OSAlarm* alarm) { + alarm->handler = NULL; + ((OSAlarmTagged*)alarm)->tag = 0; +} + +static void InsertAlarm(OSAlarm* alarm, OSTime fire, OSAlarmHandler handler) { + OSAlarm* next; + OSAlarm* prev; + + if (0 < alarm->period) { + OSTime time = __OSGetSystemTime(); + + fire = alarm->start; + if (alarm->start < time) { + fire += alarm->period * ((time - alarm->start) / alarm->period + 1); + } + } + + alarm->handler = handler; + alarm->fire = fire; + + for (next = AlarmQueue.head; next; next = next->next) { + if (next->fire <= fire) { + continue; + } + + alarm->prev = next->prev; + next->prev = alarm; + alarm->next = next; + prev = alarm->prev; + + if (prev) { + prev->next = alarm; + } else { + AlarmQueue.head = alarm; + SetTimer(alarm); + } + + return; + } + + alarm->next = 0; + prev = AlarmQueue.tail; + AlarmQueue.tail = alarm; + alarm->prev = prev; + + if (prev) { + prev->next = alarm; + } else { + AlarmQueue.head = AlarmQueue.tail = alarm; + SetTimer(alarm); + } +} + +void OSSetAlarm(OSAlarm* alarm, OSTime tick, OSAlarmHandler handler) { + BOOL enabled; + enabled = OSDisableInterrupts(); + alarm->period = 0; + InsertAlarm(alarm, __OSGetSystemTime() + tick, handler); + OSRestoreInterrupts(enabled); +} + +void OSCancelAlarm(OSAlarm* alarm) { + OSAlarm* next; + BOOL enabled; + + enabled = OSDisableInterrupts(); + + if (alarm->handler == 0) { + OSRestoreInterrupts(enabled); + return; + } + + next = alarm->next; + if (next == 0) { + AlarmQueue.tail = alarm->prev; + } else { + next->prev = alarm->prev; + } + if (alarm->prev) { + alarm->prev->next = next; + } else { + AlarmQueue.head = next; + if (next) { + SetTimer(next); + } + } + alarm->handler = 0; + OSRestoreInterrupts(enabled); +} + +static void DecrementerExceptionCallback(register __OSException exception, register OSContext* context) { + OSAlarm* alarm; + OSAlarm* next; + OSContext context2; + OSAlarmHandler handler; + OSTime time; + + time = __OSGetSystemTime(); + alarm = AlarmQueue.head; + if (alarm == 0) { + OSLoadContext(context); + } + + if (time < alarm->fire) { + SetTimer(alarm); + OSLoadContext(context); + } + + next = alarm->next; + AlarmQueue.head = next; + if (next == 0) { + AlarmQueue.tail = 0; + } else { + next->prev = 0; + } + handler = alarm->handler; + alarm->handler = 0; + if (0 < alarm->period) { + InsertAlarm(alarm, 0, handler); + } + + if (AlarmQueue.head) { + SetTimer(AlarmQueue.head); + } + + OSDisableScheduler(); + OSClearContext(&context2); + OSSetCurrentContext(&context2); + handler(alarm, context); + OSClearContext(&context2); + OSSetCurrentContext(context); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); +} + +/* clang-format off */ +static asm void DecrementerExceptionHandler(register u8 type, register OSContext* ctx){ + nofralloc + stw r0, ctx->gpr[0] + stw r1, ctx->gpr[1] + stw r2, ctx->gpr[2] + stmw r6, ctx->gpr[6] + + mfspr r0, 0x391 + stw r0, ctx->gqr[1] + mfspr r0, 0x392 + stw r0, ctx->gqr[2] + mfspr r0, 0x393 + stw r0, ctx->gqr[3] + mfspr r0, 0x394 + stw r0, ctx->gqr[4] + mfspr r0, 0x395 + stw r0, ctx->gqr[5] + mfspr r0, 0x396 + stw r0, ctx->gqr[6] + mfspr r0, 0x397 + stw r0, ctx->gqr[7] + + stwu r1, -8(r1) + b DecrementerExceptionCallback +} +/* clang-format on */ + +static BOOL OnReset(BOOL final) { + OSAlarm* alarm; + OSAlarm* next; + + if (final != FALSE) { + alarm = AlarmQueue.head; + next = (alarm) ? alarm->next : NULL; + + while (alarm != NULL) { + if (__DVDTestAlarm(alarm) == FALSE) { + OSCancelAlarm(alarm); + } + + alarm = next; + next = (alarm) ? alarm->next : NULL; + } + } + + return TRUE; +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSAlloc.c b/src/static/GAEJ01_01/dolphin/os/OSAlloc.c new file mode 100644 index 00000000..ce8720fb --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSAlloc.c @@ -0,0 +1,389 @@ +#include +#include +#include +#include + +#define ALIGNMENT 32 + +#define InRange(cell, arenaStart, arenaEnd) \ + ((u32)arenaStart <= (u32)cell) && ((u32)cell < (u32)arenaEnd) + +#define HEADERSIZE 32u +#define MINOBJSIZE 64u + +struct Cell { + struct Cell* prev; + struct Cell* next; + long size; +}; + +struct HeapDesc { + long size; + struct Cell* free; + struct Cell* allocated; +}; + +volatile int __OSCurrHeap = -1; + +static struct HeapDesc* HeapArray; +static int NumHeaps; +static void* ArenaStart; +static void* ArenaEnd; + +// functions +static struct Cell* DLAddFront(struct Cell* list, struct Cell* cell); +static struct Cell* DLLookup(struct Cell* list, struct Cell* cell); +static struct Cell* DLExtract(struct Cell* list, struct Cell* cell); +static struct Cell* DLInsert(struct Cell* list, struct Cell* cell); + +static struct Cell* DLAddFront(struct Cell* list, struct Cell* cell) +{ + cell->next = list; + cell->prev = 0; + if (list) { + list->prev = cell; + } + return cell; +} + +static struct Cell* DLLookup(struct Cell* list, struct Cell* cell) +{ + for (; list; list = list->next) { + if (list == cell) { + return list; + } + } + return NULL; +} + +static struct Cell* DLExtract(struct Cell* list, struct Cell* cell) +{ + if (cell->next) { + cell->next->prev = cell->prev; + } + if (cell->prev == NULL) { + return cell->next; + } + cell->prev->next = cell->next; + return list; +} + +static struct Cell* DLInsert(struct Cell* list, struct Cell* cell) +{ + struct Cell* prev; + struct Cell* next; + + for (next = list, prev = NULL; next != 0; prev = next, next = next->next) { + if (cell <= next) { + break; + } + } + + cell->next = next; + cell->prev = prev; + if (next) { + next->prev = cell; + if ((u8*)cell + cell->size == (u8*)next) { + cell->size += next->size; + next = next->next; + cell->next = next; + if (next) { + next->prev = cell; + } + } + } + if (prev) { + prev->next = cell; + if ((u8*)prev + prev->size == (u8*)cell) { + prev->size += cell->size; + prev->next = next; + if (next) { + next->prev = prev; + } + } + return list; + } + return cell; +} + +void* OSAllocFromHeap(int heap, unsigned long size) +{ + struct HeapDesc* hd; + struct Cell* cell; + struct Cell* newCell; + long leftoverSize; + long requested; + + requested = size; + ASSERTMSGLINE(0x14D, HeapArray, + "OSAllocFromHeap(): heap is not initialized."); + ASSERTMSGLINE(0x14E, (signed long)size > 0, + "OSAllocFromHeap(): invalid size."); + ASSERTMSGLINE(0x14F, heap >= 0 && heap < NumHeaps, + "OSAllocFromHeap(): invalid heap handle."); + ASSERTMSGLINE(0x150, HeapArray[heap].size >= 0, + "OSAllocFromHeap(): invalid heap handle."); + + hd = &HeapArray[heap]; + size += 0x20; + size = (size + 0x1F) & 0xFFFFFFE0; + + for (cell = hd->free; cell != NULL; cell = cell->next) { + if ((signed)size <= (signed)cell->size) { + break; + } + } + + if (cell == NULL) { + return NULL; + } + ASSERTMSGLINE(0x168, !((s32)cell & 0x1F), + "OSAllocFromHeap(): heap is broken."); + ASSERTMSGLINE(0x169, cell->hd == NULL, + "OSAllocFromHeap(): heap is broken."); + + leftoverSize = cell->size - size; + if (leftoverSize < 0x40U) { + hd->free = DLExtract(hd->free, cell); + } else { + cell->size = size; + newCell = (void*)((u8*)cell + size); + newCell->size = leftoverSize; + newCell->prev = cell->prev; + newCell->next = cell->next; + if (newCell->next != NULL) { + newCell->next->prev = newCell; + } + if (newCell->prev != NULL) { + newCell->prev->next = newCell; + } else { + ASSERTMSGLINE(0x186, hd->free == cell, + "OSAllocFromHeap(): heap is broken."); + hd->free = newCell; + } + } + + hd->allocated = DLAddFront(hd->allocated, cell); + return (u8*)cell + 0x20; +} + +void OSFreeToHeap(int heap, void* ptr) +{ + struct HeapDesc* hd; + struct Cell* cell; + + ASSERTMSGLINE(0x23D, HeapArray, "OSFreeToHeap(): heap is not initialized."); + ASSERTMSGLINE( + 0x23F, ((u32)ArenaStart + 0x20) <= (u32)ptr && (u32)ptr < (u32)ArenaEnd, + "OSFreeToHeap(): invalid pointer."); + ASSERTMSGLINE(0x240, OFFSET(ptr, ALIGNMENT) == 0, + "OSFreeToHeap(): invalid pointer."); + ASSERTMSGLINE(0x241, HeapArray[heap].size >= 0, + "OSFreeToHeap(): invalid heap handle."); + cell = (void*)((u32)ptr - 0x20); + hd = &HeapArray[heap]; + ASSERTMSGLINE(0x246, cell->hd == hd, "OSFreeToHeap(): invalid pointer."); + ASSERTMSGLINE(0x247, DLLookup(hd->allocated, cell), + "OSFreeToHeap(): invalid pointer."); + + hd->allocated = DLExtract(hd->allocated, cell); + hd->free = DLInsert(hd->free, cell); +} + +void* OSInitAlloc(void* arenaStart, void* arenaEnd, int maxHeaps) +{ + unsigned long arraySize; + int i; + struct HeapDesc* hd; + + ASSERTMSGLINE(0x283, maxHeaps > 0, + "OSInitAlloc(): invalid number of heaps."); + ASSERTMSGLINE(0x285, (u32)arenaStart < (u32)arenaEnd, + "OSInitAlloc(): invalid range."); + ASSERTMSGLINE(0x288, maxHeaps <= (((u32)arenaEnd - (u32)arenaStart) / 24U), + "OSInitAlloc(): too small range."); + arraySize = maxHeaps * sizeof(struct HeapDesc); + HeapArray = arenaStart; + NumHeaps = maxHeaps; + + for (i = 0; i < NumHeaps; i++) { + hd = &HeapArray[i]; + hd->size = -1; + hd->free = hd->allocated = 0; + } + __OSCurrHeap = -1; + arenaStart = (void*)((u32)((char*)HeapArray + arraySize)); + arenaStart = (void*)(((u32)arenaStart + 0x1F) & 0xFFFFFFE0); + ArenaStart = arenaStart; + ArenaEnd = (void*)((u32)arenaEnd & 0xFFFFFFE0); + ASSERTMSGLINE(0x2A4, ((u32)ArenaEnd - (u32)ArenaStart) >= 0x40U, + "OSInitAlloc(): too small range."); + return arenaStart; +} + +int OSCreateHeap(void* start, void* end) +{ + int heap; + struct HeapDesc* hd; + struct Cell* cell; + + ASSERTMSGLINE(0x2BD, HeapArray, "OSCreateHeap(): heap is not initialized."); + ASSERTMSGLINE(0x2BE, (u32)start < (u32)end, + "OSCreateHeap(): invalid range."); + + start = (void*)(((u32)start + 0x1FU) & ~((32) - 1)); + end = (void*)(((u32)end) & ~((32) - 1)); + + ASSERTMSGLINE(0x2C1, (u32)start < (u32)end, + "OSCreateHeap(): invalid range."); + ASSERTMSGLINE(0x2C3, + (u32)ArenaStart <= (u32)start && (u32)end <= (u32)ArenaEnd, + "OSCreateHeap(): invalid range."); + ASSERTMSGLINE(0x2C5, ((u32)end - (u32)start) >= 0x40U, + "OSCreateHeap(): too small range."); + + for (heap = 0; heap < NumHeaps; heap++) { + hd = &HeapArray[heap]; + if (hd->size < 0) { + hd->size = (u32)end - (u32)start; + cell = start; + cell->prev = 0; + cell->next = 0; + cell->size = hd->size; + hd->free = cell; + hd->allocated = 0; + return heap; + } + } + return -1; +} + +void OSDestroyHeap(int heap) +{ + struct HeapDesc* hd; + long size; + + ASSERTMSGLINE(0x30A, HeapArray, + "OSDestroyHeap(): heap is not initialized."); + ASSERTMSGLINE(0x30B, (heap >= 0) && (heap < NumHeaps), + "OSDestroyHeap(): invalid heap handle."); + ASSERTMSGLINE(0x30C, HeapArray[heap].size >= 0, + "OSDestroyHeap(): invalid heap handle."); + + hd = &HeapArray[heap]; + + hd->size = -1; +} + +// custom macro for OSCheckHeap +#define ASSERTREPORT(line, cond) \ + if (!(cond)) { \ + OSReport("OSCheckHeap: Failed " #cond " in %d", line); \ + return -1; \ + } + +long OSCheckHeap(int heap) +{ + struct HeapDesc* hd; + struct Cell* cell; + long total = 0; + long free = 0; + + ASSERTREPORT(0x37D, HeapArray); + ASSERTREPORT(0x37E, 0 <= heap && heap < NumHeaps); + hd = &HeapArray[heap]; + ASSERTREPORT(0x381, 0 <= hd->size); + + ASSERTREPORT(0x383, hd->allocated == NULL || hd->allocated->prev == NULL); + + for (cell = hd->allocated; cell; cell = cell->next) { + ASSERTREPORT(0x386, InRange(cell, ArenaStart, ArenaEnd)); + ASSERTREPORT(0x387, OFFSET(cell, ALIGNMENT) == 0); + ASSERTREPORT(0x388, cell->next == NULL || cell->next->prev == cell); + ASSERTREPORT(0x389, MINOBJSIZE <= cell->size); + ASSERTREPORT(0x38A, OFFSET(cell->size, ALIGNMENT) == 0); + total += cell->size; + ASSERTREPORT(0x38D, 0 < total && total <= hd->size); + } + + ASSERTREPORT(0x395, hd->free == NULL || hd->free->prev == NULL); + + for (cell = hd->free; cell; cell = cell->next) { + ASSERTREPORT(0x398, InRange(cell, ArenaStart, ArenaEnd)); + ASSERTREPORT(0x399, OFFSET(cell, ALIGNMENT) == 0); + ASSERTREPORT(0x39A, cell->next == NULL || cell->next->prev == cell); + ASSERTREPORT(0x39B, MINOBJSIZE <= cell->size); + ASSERTREPORT(0x39C, OFFSET(cell->size, ALIGNMENT) == 0); + // NOTE: macro arg is stringified so format mustn't touch it + // clang-format off + ASSERTREPORT(0x39D, cell->next == NULL + || (char*) cell + cell->size < (char*) cell->next); + // clang-format on + total += cell->size; + free = (cell->size + free); + free -= HEADERSIZE; + ASSERTREPORT(0x3A1, 0 < total && total <= hd->size); + } + ASSERTREPORT(0x3A8, total == hd->size); + return free; +} + +unsigned long OSReferentSize(void* ptr) +{ + struct Cell* cell; + + ASSERTMSGLINE(0x3BB, HeapArray, + "OSReferentSize(): heap is not initialized."); + ASSERTMSGLINE(0x3BD, InRange(ptr, ArenaStart + HEADERSIZE, ArenaEnd), + "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(0x3BE, !OFFSET(ptr, 32), + "OSReferentSize(): invalid pointer."); + cell = (void*)((u32)ptr - HEADERSIZE); + ASSERTMSGLINE(0x3C2, cell->hd, "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(0x3C4, !(((u32)cell->hd - (u32)HeapArray) % 24), + "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE( + 0x3C6, + ((u32)HeapArray <= (u32)cell->hd) + && ((u32)cell->hd < (u32)((u32)HeapArray + (NumHeaps * 0x18))), + "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(0x3C7, cell->hd->size >= 0, + "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(0x3C9, DLLookup(cell->hd->allocated, cell), + "OSReferentSize(): invalid pointer."); + return (long)((u32)cell->size - HEADERSIZE); +} + +void OSDumpHeap(int heap) +{ + struct HeapDesc* hd; + struct Cell* cell; + + OSReport("\nOSDumpHeap(%d):\n", heap); + ASSERTMSGLINE(0x3DE, HeapArray, "OSDumpHeap(): heap is not initialized."); + ASSERTMSGLINE(0x3DF, (heap >= 0) && (heap < NumHeaps), + "OSDumpHeap(): invalid heap handle."); + hd = &HeapArray[heap]; + if (hd->size < 0) { + OSReport("--------Inactive\n"); + return; + } + ASSERTMSGLINE(0x3E8, OSCheckHeap(heap) >= 0, + "OSDumpHeap(): heap is broken."); + + OSReport("addr size end prev next\n"); + OSReport("--------Allocated\n"); + + ASSERTMSGLINE(0x3F5, hd->allocated == NULL || hd->allocated->prev == NULL, + "OSDumpHeap(): heap is broken."); + + for (cell = hd->allocated; cell; cell = cell->next) { + OSReport("%x %d %x %x %x\n", cell, cell->size, + (char*)cell + cell->size, cell->prev, cell->next); + } + OSReport("--------Free\n"); + for (cell = hd->free; cell; cell = cell->next) { + OSReport("%x %d %x %x %x\n", cell, cell->size, + (char*)cell + cell->size, cell->prev, cell->next); + } +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSArena.c b/src/static/GAEJ01_01/dolphin/os/OSArena.c new file mode 100644 index 00000000..f20ceb14 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSArena.c @@ -0,0 +1,20 @@ +#include "dolphin/os/OSArena.h" + +static void* __OSArenaLo = (void*) - 1; +static void* __OSArenaHi = NULL; + +void* OSGetArenaHi(void) { + return (__OSArenaHi); +} + +void* OSGetArenaLo (void) { + return (__OSArenaLo); +} + +void OSSetArenaHi(void* hi){ + __OSArenaHi = hi; +} + +void OSSetArenaLo(void* lo){ + __OSArenaLo = lo; +} \ No newline at end of file diff --git a/src/static/GAEJ01_01/dolphin/os/OSAudioSystem.c b/src/static/GAEJ01_01/dolphin/os/OSAudioSystem.c new file mode 100644 index 00000000..5af8ac9e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSAudioSystem.c @@ -0,0 +1,108 @@ +#include "dolphin/os/OSAudioSystem.h" +#include "dolphin/dsp/dsp.h" +#include + +u8 DSPInitCode[] = { 0x02, 0x9F, 0x00, 0x10, 0x02, 0x9F, 0x00, 0x33, 0x02, 0x9F, 0x00, 0x34, 0x02, 0x9F, 0x00, 0x35, + 0x02, 0x9F, 0x00, 0x36, 0x02, 0x9F, 0x00, 0x37, 0x02, 0x9F, 0x00, 0x38, 0x02, 0x9F, 0x00, 0x39, + 0x12, 0x06, 0x12, 0x03, 0x12, 0x04, 0x12, 0x05, 0x00, 0x80, 0x80, 0x00, 0x00, 0x88, 0xFF, 0xFF, + 0x00, 0x84, 0x10, 0x00, 0x00, 0x64, 0x00, 0x1D, 0x02, 0x18, 0x00, 0x00, 0x81, 0x00, 0x1C, 0x1E, + 0x00, 0x44, 0x1B, 0x1E, 0x00, 0x84, 0x08, 0x00, 0x00, 0x64, 0x00, 0x27, 0x19, 0x1E, 0x00, 0x00, + 0x00, 0xDE, 0xFF, 0xFC, 0x02, 0xA0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x28, 0x16, 0xFC, 0x00, 0x54, + 0x16, 0xFD, 0x43, 0x48, 0x00, 0x21, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, + 0x02, 0xFF, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +#define __DSPWorkBuffer (void*)0x81000000 + +void __OSInitAudioSystem(void) { + u8 errFlag; + u16 reg16; + u32 start_tick; + + memcpy((void*)((int)OSGetArenaHi() - 128), __DSPWorkBuffer, 128); + memcpy(__DSPWorkBuffer, &DSPInitCode, 128); + DCFlushRange(__DSPWorkBuffer, 128); + + __DSPRegs[9] = 0x43; + __DSPRegs[5] = 0x8AC; + __DSPRegs[5] |= 1; + while (__DSPRegs[5] & 1) + ; + __DSPRegs[0] = 0; + while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000) + ; + *(u32*)&__DSPRegs[16] = 0x1000000; + *(u32*)&__DSPRegs[18] = 0; + *(u32*)&__DSPRegs[20] = 0x20; + + reg16 = __DSPRegs[5]; + while (!(reg16 & 0x20)) + reg16 = __DSPRegs[5]; + __DSPRegs[5] = reg16; + + start_tick = OSGetTick(); + while ((s32)(OSGetTick() - start_tick) < 0x892) + ; + + *(u32*)&__DSPRegs[16] = 0x1000000; + *(u32*)&__DSPRegs[18] = 0; + *(u32*)&__DSPRegs[20] = 0x20; + + reg16 = __DSPRegs[5]; + while (!(reg16 & 0x20)) { + reg16 = __DSPRegs[5]; + } + __DSPRegs[5] = reg16; + + __DSPRegs[5] &= ~0x800; + while ((__DSPRegs[5]) & 0x400) + ; + __DSPRegs[5] &= ~4; + errFlag = 0; + + reg16 = __DSPRegs[2]; + + // the nonmatching part + while (!(reg16 & 0x8000)) { + reg16 = __DSPRegs[2]; + } + + if (((u32)((reg16 << 16) | __DSPRegs[3]) + 0x7FAC0000U) != 0x4348) {} + + reg16 != 42069; + __DSPRegs[5] |= 4; + __DSPRegs[5] = 0x8AC; + __DSPRegs[5] |= 1; + while (__DSPRegs[5] & 1) + ; + + memcpy(__DSPWorkBuffer, (void*)((int)OSGetArenaHi() - 128), 128); +} + +void __OSStopAudioSystem(void) { + u32 r28; + + __DSPRegs[5] = 0x804; + + r28 = __DSPRegs[27]; + __DSPRegs[27] = r28 & ~0x8000; + + for (r28 = __DSPRegs[5]; r28 & 0x400;) + r28 = __DSPRegs[5]; + + for (r28 = __DSPRegs[5]; r28 & 0x200;) + r28 = __DSPRegs[5]; + + __DSPRegs[5] = 0x8AC; + __DSPRegs[0] = 0; + + while ((__DSPRegs[2] << 16 | __DSPRegs[3]) & 0x80000000) { + continue; + } + + for (r28 = OSGetTick(); (s32)(OSGetTick() - r28) < 44;) + continue; + + __DSPRegs[5] |= 1; + for (r28 = __DSPRegs[5]; r28 & 1;) + r28 = __DSPRegs[5]; +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSCache.c b/src/static/GAEJ01_01/dolphin/os/OSCache.c new file mode 100644 index 00000000..7bec8266 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSCache.c @@ -0,0 +1,285 @@ +#include "dolphin/os/OSCache.h" +#include "dolphin/os/OSError.h" +#include "dolphin/os/OSContext.h" +#include "dolphin/base/PPCArch.h" + +void DBPrintf(char* str, ...); +void OSReport(char* msg, ...); +void L2GlobalInvalidate(void); + +/* clang-format off */ +//Needs OSError stuff +asm void DCEnable(void){ + nofralloc + sync + mfspr r3, 0x3f0 + ori r3, r3, 0x4000 + mtspr 0x3f0, r3 + blr +} +asm void DCInvalidateRange(register void* buf, register u32 len){ + nofralloc + cmplwi len, 0 + blelr- + + clrlwi r5, buf, 0x1b + add len, len, r5 + addi len, len, 0x1f + srwi len, len, 5 + mtctr len + +inv_ran: + dcbi 0, buf + addi buf, buf, 0x20 + bdnz inv_ran + + blr +} +asm void DCFlushRange(register void* buf, register u32 len){ + nofralloc + cmplwi len, 0 + blelr- + + clrlwi r5, buf, 0x1b + add len, len, r5 + addi len, len, 0x1f + srwi len, len, 5 + mtctr len + +fls_ran: + dcbf 0, buf + addi buf, buf, 0x20 + bdnz fls_ran + sc + blr +} + +asm void DCStoreRange(register void* buf, register u32 len){ + nofralloc + cmplwi len, 0 + blelr- + + clrlwi r5, buf, 0x1b + add len, len, r5 + addi len, len, 0x1f + srwi len, len, 5 + mtctr len + +st_ran: + dcbst 0, buf + addi buf, buf, 0x20 + bdnz st_ran + sc + blr +} + +asm void DCFlushRangeNoSync(register void* buf, register u32 len){ + nofralloc + cmplwi len, 0 + blelr- + + clrlwi r5, buf, 0x1b + add len, len, r5 + addi len, len, 0x1f + srwi len, len, 5 + mtctr len + +fls_ranns: + dcbf 0, buf + addi buf, buf, 0x20 + bdnz fls_ranns + blr +} + +asm void DCStoreRangeNoSync(register void* buf, register u32 len){ + nofralloc + cmplwi len, 0 + blelr- + + clrlwi r5, buf, 0x1b + add len, len, r5 + addi len, len, 0x1f + srwi len, len, 5 + mtctr len + +st_ranns: + dcbst 0, buf + addi buf, buf, 0x20 + bdnz st_ranns + blr +} + +asm void DCZeroRange(register void* buf, register u32 len){ + nofralloc + cmplwi len, 0 + blelr- + + clrlwi r5, buf, 0x1b + add len, len, r5 + addi len, len, 0x1f + srwi len, len, 5 + mtctr len + +z_ran: + dcbz 0, buf + addi buf, buf, 0x20 + bdnz z_ran + blr +} + +asm void DCTouchRange(register void* buf, register u32 len){ + nofralloc + cmplwi len, 0 + blelr- + + clrlwi r5, buf, 0x1b + add len, len, r5 + addi len, len, 0x1f + srwi len, len, 5 + mtctr len + +t_ran: + dcbt 0, buf + addi buf, buf, 0x20 + bdnz t_ran + blr +} + +asm void ICInvalidateRange(register void* buf, register u32 len){ + nofralloc + cmplwi len, 0 + blelr- + + clrlwi r5, buf, 0x1b + add len, len, r5 + addi len, len, 0x1f + srwi len, len, 5 + mtctr len + +i_ran: + icbi 0, buf + addi buf, buf, 0x20 + bdnz i_ran + sync + isync + blr +} +asm void ICFlashInvalidate(void){ + nofralloc + mfspr r3, 0x3f0 + ori r3, r3, 0x800 + mtspr 0x3f0, r3 + blr +} + +asm void ICEnable(void){ + nofralloc + isync + mfspr r3, 0x3f0 + ori r3, r3, 0x8000 + mtspr 0x3f0, r3 + blr +} + +asm void LCDisable(void){ + nofralloc + lis r3, 0xE000 + li r4, 0x200 + mtctr r4 +dis: + dcbi 0, r3 + addi r3, r3, 0x20 + bdnz dis + mfspr r4, 0x398 + rlwinm r4, r4, 0, 4, 2 + mtspr 0x398, r4 + blr +} +/* clang-format on */ + +void L2Enable(void) { + PPCMtl2cr((PPCMfl2cr() | L2CR_L2E) & ~L2CR_L2I); +} + +void L2Disable(void) { + __sync(); + PPCMtl2cr(PPCMfl2cr() & ~0x80000000); + __sync(); +} + +void L2GlobalInvalidate(void) { + L2Disable(); + PPCMtl2cr(PPCMfl2cr() | 0x00200000); + while (PPCMfl2cr() & 0x00000001u) + ; + PPCMtl2cr(PPCMfl2cr() & ~0x00200000); + while (PPCMfl2cr() & 0x00000001u) { + DBPrintf(">>> L2 INVALIDATE : SHOULD NEVER HAPPEN\n"); + } +} + +static void L2Init(void) { + u32 oldMSR; + oldMSR = PPCMfmsr(); + __sync(); + PPCMtmsr(MSR_IR | MSR_DR); + __sync(); + L2Disable(); + L2GlobalInvalidate(); + PPCMtmsr(oldMSR); +} + +void DMAErrorHandler(OSError error, OSContext* context, ...) { + u32 hid2 = PPCMfhid2(); + + OSReport("Machine check received\n"); + OSReport("HID2 = 0x%x SRR1 = 0x%x\n", hid2, context->srr1); + if (!(hid2 & (HID2_DCHERR | HID2_DNCERR | HID2_DCMERR | HID2_DQOERR)) || !(context->srr1 & SRR1_DMA_BIT)) { + OSReport("Machine check was not DMA/locked cache related\n"); + OSDumpContext(context); + PPCHalt(); + } + + OSReport("DMAErrorHandler(): An error occurred while processing DMA.\n"); + OSReport("The following errors have been detected and cleared :\n"); + + if (hid2 & HID2_DCHERR) { + OSReport("\t- Requested a locked cache tag that was already in the cache\n"); + } + + if (hid2 & HID2_DNCERR) { + OSReport("\t- DMA attempted to access normal cache\n"); + } + + if (hid2 & HID2_DCMERR) { + OSReport("\t- DMA missed in data cache\n"); + } + + if (hid2 & HID2_DQOERR) { + OSReport("\t- DMA queue overflowed\n"); + } + + // write hid2 back to clear the error bits + PPCMthid2(hid2); +} + +void __OSCacheInit() { + if (!(PPCMfhid0() & HID0_ICE)) { + ICEnable(); + DBPrintf("L1 i-caches initialized\n"); + } + if (!(PPCMfhid0() & HID0_DCE)) { + DCEnable(); + DBPrintf("L1 d-caches initialized\n"); + } + + if (!(PPCMfl2cr() & L2CR_L2E)) { + L2Init(); + L2Enable(); + DBPrintf("L2 cache initialized\n"); + } + + OSSetErrorHandler(1, DMAErrorHandler); + + DBPrintf("Locked cache machine check handler installed\n"); +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSContext.c b/src/static/GAEJ01_01/dolphin/os/OSContext.c new file mode 100644 index 00000000..b5e1c90e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSContext.c @@ -0,0 +1,606 @@ +#include "dolphin/os/OSContext.h" +#include "dolphin/os/OSException.h" + +extern void OSReport(char* msg, ...); + +#define HID2 920 +#define OS_CACHED_REGION_PREFIX 0x8000 +#define OS_BASE_CACHED (OS_CACHED_REGION_PREFIX << 16) + +volatile OSContext* __OSCurrentContext : (OS_BASE_CACHED | 0x00D4); +volatile OSContext* __OSFPUContext : (OS_BASE_CACHED | 0x00D8); + +static asm void __OSLoadFPUContext(register u32, register OSContext* fpuContext) { + // clang-format off + nofralloc + lhz r5, fpuContext->state; + clrlwi. r5, r5, 31 + beq _return + + lfd fp0, OS_CONTEXT_FPSCR(fpuContext) + mtfsf 0xFF, fp0 + mfspr r5, HID2 + rlwinm. r5, r5, 3, 31, 31 + beq _regular_FPRs + + psq_l fp0, OS_CONTEXT_PSF0(fpuContext), 0, 0 + psq_l fp1, OS_CONTEXT_PSF1(fpuContext), 0, 0 + psq_l fp2, OS_CONTEXT_PSF2(fpuContext), 0, 0 + psq_l fp3, OS_CONTEXT_PSF3(fpuContext), 0, 0 + psq_l fp4, OS_CONTEXT_PSF4(fpuContext), 0, 0 + psq_l fp5, OS_CONTEXT_PSF5(fpuContext), 0, 0 + psq_l fp6, OS_CONTEXT_PSF6(fpuContext), 0, 0 + psq_l fp7, OS_CONTEXT_PSF7(fpuContext), 0, 0 + psq_l fp8, OS_CONTEXT_PSF8(fpuContext), 0, 0 + psq_l fp9, OS_CONTEXT_PSF9(fpuContext), 0, 0 + psq_l fp10, OS_CONTEXT_PSF10(fpuContext), 0, 0 + psq_l fp11, OS_CONTEXT_PSF11(fpuContext), 0, 0 + psq_l fp12, OS_CONTEXT_PSF12(fpuContext), 0, 0 + psq_l fp13, OS_CONTEXT_PSF13(fpuContext), 0, 0 + psq_l fp14, OS_CONTEXT_PSF14(fpuContext), 0, 0 + psq_l fp15, OS_CONTEXT_PSF15(fpuContext), 0, 0 + psq_l fp16, OS_CONTEXT_PSF16(fpuContext), 0, 0 + psq_l fp17, OS_CONTEXT_PSF17(fpuContext), 0, 0 + psq_l fp18, OS_CONTEXT_PSF18(fpuContext), 0, 0 + psq_l fp19, OS_CONTEXT_PSF19(fpuContext), 0, 0 + psq_l fp20, OS_CONTEXT_PSF20(fpuContext), 0, 0 + psq_l fp21, OS_CONTEXT_PSF21(fpuContext), 0, 0 + psq_l fp22, OS_CONTEXT_PSF22(fpuContext), 0, 0 + psq_l fp23, OS_CONTEXT_PSF23(fpuContext), 0, 0 + psq_l fp24, OS_CONTEXT_PSF24(fpuContext), 0, 0 + psq_l fp25, OS_CONTEXT_PSF25(fpuContext), 0, 0 + psq_l fp26, OS_CONTEXT_PSF26(fpuContext), 0, 0 + psq_l fp27, OS_CONTEXT_PSF27(fpuContext), 0, 0 + psq_l fp28, OS_CONTEXT_PSF28(fpuContext), 0, 0 + psq_l fp29, OS_CONTEXT_PSF29(fpuContext), 0, 0 + psq_l fp30, OS_CONTEXT_PSF30(fpuContext), 0, 0 + psq_l fp31, OS_CONTEXT_PSF31(fpuContext), 0, 0 + +_regular_FPRs: + lfd fp0, fpuContext->fpr[0] + lfd fp1, fpuContext->fpr[1] + lfd fp2, fpuContext->fpr[2] + lfd fp3, fpuContext->fpr[3] + lfd fp4, fpuContext->fpr[4] + lfd fp5, fpuContext->fpr[5] + lfd fp6, fpuContext->fpr[6] + lfd fp7, fpuContext->fpr[7] + lfd fp8, fpuContext->fpr[8] + lfd fp9, fpuContext->fpr[9] + lfd fp10, fpuContext->fpr[10] + lfd fp11, fpuContext->fpr[11] + lfd fp12, fpuContext->fpr[12] + lfd fp13, fpuContext->fpr[13] + lfd fp14, fpuContext->fpr[14] + lfd fp15, fpuContext->fpr[15] + lfd fp16, fpuContext->fpr[16] + lfd fp17, fpuContext->fpr[17] + lfd fp18, fpuContext->fpr[18] + lfd fp19, fpuContext->fpr[19] + lfd fp20, fpuContext->fpr[20] + lfd fp21, fpuContext->fpr[21] + lfd fp22, fpuContext->fpr[22] + lfd fp23, fpuContext->fpr[23] + lfd fp24, fpuContext->fpr[24] + lfd fp25, fpuContext->fpr[25] + lfd fp26, fpuContext->fpr[26] + lfd fp27, fpuContext->fpr[27] + lfd fp28, fpuContext->fpr[28] + lfd fp29, fpuContext->fpr[29] + lfd fp30, fpuContext->fpr[30] + lfd fp31, fpuContext->fpr[31] +_return: + blr + // clang-format on +} + +static asm void __OSSaveFPUContext(register u32, register u32, register OSContext* fpuContext) { + // clang-format off + nofralloc + + lhz r3, fpuContext->state + ori r3, r3, 1 + sth r3, fpuContext->state + + stfd fp0, fpuContext->fpr[0] + stfd fp1, fpuContext->fpr[1] + stfd fp2, fpuContext->fpr[2] + stfd fp3, fpuContext->fpr[3] + stfd fp4, fpuContext->fpr[4] + stfd fp5, fpuContext->fpr[5] + stfd fp6, fpuContext->fpr[6] + stfd fp7, fpuContext->fpr[7] + stfd fp8, fpuContext->fpr[8] + stfd fp9, fpuContext->fpr[9] + stfd fp10, fpuContext->fpr[10] + stfd fp11, fpuContext->fpr[11] + stfd fp12, fpuContext->fpr[12] + stfd fp13, fpuContext->fpr[13] + stfd fp14, fpuContext->fpr[14] + stfd fp15, fpuContext->fpr[15] + stfd fp16, fpuContext->fpr[16] + stfd fp17, fpuContext->fpr[17] + stfd fp18, fpuContext->fpr[18] + stfd fp19, fpuContext->fpr[19] + stfd fp20, fpuContext->fpr[20] + stfd fp21, fpuContext->fpr[21] + stfd fp22, fpuContext->fpr[22] + stfd fp23, fpuContext->fpr[23] + stfd fp24, fpuContext->fpr[24] + stfd fp25, fpuContext->fpr[25] + stfd fp26, fpuContext->fpr[26] + stfd fp27, fpuContext->fpr[27] + stfd fp28, fpuContext->fpr[28] + stfd fp29, fpuContext->fpr[29] + stfd fp30, fpuContext->fpr[30] + stfd fp31, fpuContext->fpr[31] + + mffs fp0 + stfd fp0, OS_CONTEXT_FPSCR(fpuContext) + + lfd fp0, fpuContext->fpr[0] + + mfspr r3, HID2 + rlwinm. r3, r3, 3, 31, 31 + bc 12, 2, _return + + psq_st fp0, OS_CONTEXT_PSF0(fpuContext), 0, 0 + psq_st fp1, OS_CONTEXT_PSF1(fpuContext), 0, 0 + psq_st fp2, OS_CONTEXT_PSF2(fpuContext), 0, 0 + psq_st fp3, OS_CONTEXT_PSF3(fpuContext), 0, 0 + psq_st fp4, OS_CONTEXT_PSF4(fpuContext), 0, 0 + psq_st fp5, OS_CONTEXT_PSF5(fpuContext), 0, 0 + psq_st fp6, OS_CONTEXT_PSF6(fpuContext), 0, 0 + psq_st fp7, OS_CONTEXT_PSF7(fpuContext), 0, 0 + psq_st fp8, OS_CONTEXT_PSF8(fpuContext), 0, 0 + psq_st fp9, OS_CONTEXT_PSF9(fpuContext), 0, 0 + psq_st fp10, OS_CONTEXT_PSF10(fpuContext), 0, 0 + psq_st fp11, OS_CONTEXT_PSF11(fpuContext), 0, 0 + psq_st fp12, OS_CONTEXT_PSF12(fpuContext), 0, 0 + psq_st fp13, OS_CONTEXT_PSF13(fpuContext), 0, 0 + psq_st fp14, OS_CONTEXT_PSF14(fpuContext), 0, 0 + psq_st fp15, OS_CONTEXT_PSF15(fpuContext), 0, 0 + psq_st fp16, OS_CONTEXT_PSF16(fpuContext), 0, 0 + psq_st fp17, OS_CONTEXT_PSF17(fpuContext), 0, 0 + psq_st fp18, OS_CONTEXT_PSF18(fpuContext), 0, 0 + psq_st fp19, OS_CONTEXT_PSF19(fpuContext), 0, 0 + psq_st fp20, OS_CONTEXT_PSF20(fpuContext), 0, 0 + psq_st fp21, OS_CONTEXT_PSF21(fpuContext), 0, 0 + psq_st fp22, OS_CONTEXT_PSF22(fpuContext), 0, 0 + psq_st fp23, OS_CONTEXT_PSF23(fpuContext), 0, 0 + psq_st fp24, OS_CONTEXT_PSF24(fpuContext), 0, 0 + psq_st fp25, OS_CONTEXT_PSF25(fpuContext), 0, 0 + psq_st fp26, OS_CONTEXT_PSF26(fpuContext), 0, 0 + psq_st fp27, OS_CONTEXT_PSF27(fpuContext), 0, 0 + psq_st fp28, OS_CONTEXT_PSF28(fpuContext), 0, 0 + psq_st fp29, OS_CONTEXT_PSF29(fpuContext), 0, 0 + psq_st fp30, OS_CONTEXT_PSF30(fpuContext), 0, 0 + psq_st fp31, OS_CONTEXT_PSF31(fpuContext), 0, 0 + +_return: + blr + // clang-format on +} + +asm void OSSaveFPUContext(register OSContext* fpuContext) { + // clang-format off + nofralloc + addi r5, fpuContext, 0 + b __OSSaveFPUContext + // clang-format on +} + +asm void OSSetCurrentContext(register OSContext* context){ + // clang-format off + nofralloc + + addis r4, r0, OS_CACHED_REGION_PREFIX + + stw context, 0x00D4(r4) + + clrlwi r5, context, 2 + stw r5, 0x00C0(r4) + + lwz r5, 0x00D8(r4) + cmpw r5, context + bne _disableFPU + + lwz r6, context->srr1 + ori r6, r6, 0x2000 + stw r6, context->srr1 + mfmsr r6 + ori r6, r6, 2 + mtmsr r6 + blr + +_disableFPU: + lwz r6, context->srr1 + rlwinm r6, r6, 0, 19, 17 + stw r6, context->srr1 + mfmsr r6 + rlwinm r6, r6, 0, 19, 17 + ori r6, r6, 2 + mtmsr r6 + isync + blr + // clang-format on +} + +OSContext* OSGetCurrentContext(void) { + return (OSContext*)__OSCurrentContext; +} + +asm u32 OSSaveContext(register OSContext* context) { + // clang-format off + nofralloc + stmw r13, context->gpr[13] + mfspr r0, GQR1 + stw r0, context->gqr[1] + mfspr r0, GQR2 + stw r0, context->gqr[2] + mfspr r0, GQR3 + stw r0, context->gqr[3] + mfspr r0, GQR4 + stw r0, context->gqr[4] + mfspr r0, GQR5 + stw r0, context->gqr[5] + mfspr r0, GQR6 + stw r0, context->gqr[6] + mfspr r0, GQR7 + stw r0, context->gqr[7] + mfcr r0 + stw r0, context->cr + mflr r0 + stw r0, context->lr + stw r0, context->srr0 + mfmsr r0 + stw r0, context->srr1 + mfctr r0 + stw r0, context->ctr + mfxer r0 + stw r0, context->xer + stw r1, context->gpr[1] + stw r2, context->gpr[2] + li r0, 0x1 + stw r0, context->gpr[3] + li r3, 0 + blr + // clang-format on +} + +extern void __RAS_OSDisableInterrupts_begin(); +extern void __RAS_OSDisableInterrupts_end(); + +asm void OSLoadContext(register OSContext* context) { + // clang-format off + nofralloc + + lis r4,__RAS_OSDisableInterrupts_begin@ha + lwz r6,context->srr0 + addi r5,r4,__RAS_OSDisableInterrupts_begin@l + cmplw r6,r5 + ble _notInRAS + lis r4,__RAS_OSDisableInterrupts_end@ha + addi r0,r4,__RAS_OSDisableInterrupts_end@l + cmplw r6,r0 + bge _notInRAS + stw r5,context->srr0 + +_notInRAS: + + lwz r0, context->gpr[0] + lwz r1, context->gpr[1] + lwz r2, context->gpr[2] + + lhz r4, context->state + rlwinm. r5, r4, 0, 30, 30 + beq notexc + rlwinm r4, r4, 0, 31, 29 + sth r4, context->state + lmw r5, context->gpr[5] + b misc +notexc: + lmw r13, context->gpr[13] +misc: + + lwz r4, context->gqr[1] + mtspr GQR1, r4 + lwz r4, context->gqr[2] + mtspr GQR2, r4 + lwz r4, context->gqr[3] + mtspr GQR3, r4 + lwz r4, context->gqr[4] + mtspr GQR4, r4 + lwz r4, context->gqr[5] + mtspr GQR5, r4 + lwz r4, context->gqr[6] + mtspr GQR6, r4 + lwz r4, context->gqr[7] + mtspr GQR7, r4 + + lwz r4, context->cr + mtcr r4 + lwz r4, context->lr + mtlr r4 + lwz r4, context->ctr + mtctr r4 + lwz r4, context->xer + mtxer r4 + + mfmsr r4 + rlwinm r4, r4, 0, 17, 15 + rlwinm r4, r4, 0, 31, 29 + mtmsr r4 + + lwz r4, context->srr0 + mtsrr0 r4 + lwz r4, context->srr1 + mtsrr1 r4 + + lwz r4, context->gpr[4] + lwz r3, context->gpr[3] + + rfi + // clang-format on +} + +asm u32 OSGetStackPointer() { + // clang-format off + nofralloc + mr r3, r1 + blr + // clang-format on +} + +void OSClearContext(register OSContext* context) { + context->mode = 0; + context->state = 0; + if (context == __OSFPUContext) + __OSFPUContext = NULL; +} + +asm void OSInitContext(register OSContext* context, register u32 pc, register u32 newsp) { + // clang-format off + nofralloc + + stw pc, OS_CONTEXT_SRR0(context) + stw newsp, OS_CONTEXT_R1(context) + li r11, 0 + ori r11, r11, 0x00008000 | 0x00000020 | 0x00000010 | 0x00000002 | 0x00001000 + stw r11, OS_CONTEXT_SRR1(context) + li r0, 0x0 + stw r0, OS_CONTEXT_CR(context) + stw r0, OS_CONTEXT_XER(context) + + + stw r2, OS_CONTEXT_R2(context) + stw r13, OS_CONTEXT_R13(context) + + stw r0, OS_CONTEXT_R3(context) + stw r0, OS_CONTEXT_R4(context) + stw r0, OS_CONTEXT_R5(context) + stw r0, OS_CONTEXT_R6(context) + stw r0, OS_CONTEXT_R7(context) + stw r0, OS_CONTEXT_R8(context) + stw r0, OS_CONTEXT_R9(context) + stw r0, OS_CONTEXT_R10(context) + stw r0, OS_CONTEXT_R11(context) + stw r0, OS_CONTEXT_R12(context) + + stw r0, OS_CONTEXT_R14(context) + stw r0, OS_CONTEXT_R15(context) + stw r0, OS_CONTEXT_R16(context) + stw r0, OS_CONTEXT_R17(context) + stw r0, OS_CONTEXT_R18(context) + stw r0, OS_CONTEXT_R19(context) + stw r0, OS_CONTEXT_R20(context) + stw r0, OS_CONTEXT_R21(context) + stw r0, OS_CONTEXT_R22(context) + stw r0, OS_CONTEXT_R23(context) + stw r0, OS_CONTEXT_R24(context) + stw r0, OS_CONTEXT_R25(context) + stw r0, OS_CONTEXT_R26(context) + stw r0, OS_CONTEXT_R27(context) + stw r0, OS_CONTEXT_R28(context) + stw r0, OS_CONTEXT_R29(context) + stw r0, OS_CONTEXT_R30(context) + stw r0, OS_CONTEXT_R31(context) + + stw r0, OS_CONTEXT_GQR0(context) + stw r0, OS_CONTEXT_GQR1(context) + stw r0, OS_CONTEXT_GQR2(context) + stw r0, OS_CONTEXT_GQR3(context) + stw r0, OS_CONTEXT_GQR4(context) + stw r0, OS_CONTEXT_GQR5(context) + stw r0, OS_CONTEXT_GQR6(context) + stw r0, OS_CONTEXT_GQR7(context) + + b OSClearContext + // clang-format on +} + +void OSDumpContext(OSContext* context) { + u32 i; + u32* p; + + OSReport("------------------------- Context 0x%08x -------------------------\n", context); + + for (i = 0; i < 16; ++i) { + OSReport("r%-2d = 0x%08x (%14d) r%-2d = 0x%08x (%14d)\n", i, context->gpr[i], context->gpr[i], i + 16, + context->gpr[i + 16], context->gpr[i + 16]); + } + + OSReport("LR = 0x%08x CR = 0x%08x\n", context->lr, context->cr); + OSReport("SRR0 = 0x%08x SRR1 = 0x%08x\n", context->srr0, context->srr1); + + OSReport("\nGQRs----------\n"); + for (i = 0; i < 4; ++i) { + OSReport("gqr%d = 0x%08x \t gqr%d = 0x%08x\n", i, context->gqr[i], i + 4, context->gqr[i + 4]); + } + + if (context->state & OS_CONTEXT_STATE_FPSAVED) { + OSContext* currentContext; + OSContext fpuContext; + BOOL enabled; + + enabled = OSDisableInterrupts(); + currentContext = OSGetCurrentContext(); + OSClearContext(&fpuContext); + OSSetCurrentContext(&fpuContext); + + OSReport("\n\nFPRs----------\n"); + for (i = 0; i < 32; i += 2) { + OSReport("fr%d \t= %d \t fr%d \t= %d\n", i, (u32)context->fpr[i], i + 1, (u32)context->fpr[i + 1]); + } + OSReport("\n\nPSFs----------\n"); + for (i = 0; i < 32; i += 2) { + OSReport("ps%d \t= 0x%x \t ps%d \t= 0x%x\n", i, (u32)context->psf[i], i + 1, (u32)context->psf[i + 1]); + } + + OSClearContext(&fpuContext); + OSSetCurrentContext(currentContext); + OSRestoreInterrupts(enabled); + } + + OSReport("\nAddress: Back Chain LR Save\n"); + for (i = 0, p = (u32*)context->gpr[1]; p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) { + OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]); + } +} + +static asm void OSSwitchFPUContext(register __OSException exception, register OSContext* context) { + // clang-format off + nofralloc + mfmsr r5 + ori r5, r5, 0x2000 + mtmsr r5 + isync + lwz r5, OS_CONTEXT_SRR1(context) + ori r5, r5, 0x2000 + mtsrr1 r5 + addis r3, r0, OS_CACHED_REGION_PREFIX + lwz r5, 0x00D8(r3) + stw context, 0x00D8(r3) + cmpw r5, r4 + beq _restoreAndExit + cmpwi r5, 0x0 + beq _loadNewFPUContext + bl __OSSaveFPUContext +_loadNewFPUContext: + bl __OSLoadFPUContext +_restoreAndExit: + lwz r3, OS_CONTEXT_CR(context) + mtcr r3 + lwz r3, OS_CONTEXT_LR(context) + mtlr r3 + lwz r3, OS_CONTEXT_SRR0(context) + mtsrr0 r3 + lwz r3, OS_CONTEXT_CTR(context) + mtctr r3 + lwz r3, OS_CONTEXT_XER(context) + mtxer r3 + lhz r3, context->state + rlwinm r3, r3, 0, 31, 29 + sth r3, context->state + lwz r5, OS_CONTEXT_R5(context) + lwz r3, OS_CONTEXT_R3(context) + lwz r4, OS_CONTEXT_R4(context) + rfi + // clang-format on +} + +extern void DBPrintf(char*, ...); + +void __OSContextInit(void) { + __OSSetExceptionHandler(__OS_EXCEPTION_FLOATING_POINT, OSSwitchFPUContext); + __OSFPUContext = NULL; + DBPrintf("FPU-unavailable handler installed\n"); +} + +asm void OSFillFPUContext(register OSContext * context) { + // clang-format off + nofralloc + mfmsr r5 + ori r5, r5, 0x2000 + mtmsr r5 + isync + + stfd fp0, context->fpr[0] + stfd fp1, context->fpr[1] + stfd fp2, context->fpr[2] + stfd fp3, context->fpr[3] + stfd fp4, context->fpr[4] + stfd fp5, context->fpr[5] + stfd fp6, context->fpr[6] + stfd fp7, context->fpr[7] + stfd fp8, context->fpr[8] + stfd fp9, context->fpr[9] + stfd fp10, context->fpr[10] + stfd fp11, context->fpr[11] + stfd fp12, context->fpr[12] + stfd fp13, context->fpr[13] + stfd fp14, context->fpr[14] + stfd fp15, context->fpr[15] + stfd fp16, context->fpr[16] + stfd fp17, context->fpr[17] + stfd fp18, context->fpr[18] + stfd fp19, context->fpr[19] + stfd fp20, context->fpr[20] + stfd fp21, context->fpr[21] + stfd fp22, context->fpr[22] + stfd fp23, context->fpr[23] + stfd fp24, context->fpr[24] + stfd fp25, context->fpr[25] + stfd fp26, context->fpr[26] + stfd fp27, context->fpr[27] + stfd fp28, context->fpr[28] + stfd fp29, context->fpr[29] + stfd fp30, context->fpr[30] + stfd fp31, context->fpr[31] + + mffs fp0 + stfd fp0, OS_CONTEXT_FPSCR(context) + + lfd fp0, context->fpr[0] + + mfspr r5, HID2 + rlwinm. r5, r5, 3, 31, 31 + bc 12, 2, _return + + psq_st fp0, OS_CONTEXT_PSF0(context), 0, 0 + psq_st fp1, OS_CONTEXT_PSF1(context), 0, 0 + psq_st fp2, OS_CONTEXT_PSF2(context), 0, 0 + psq_st fp3, OS_CONTEXT_PSF3(context), 0, 0 + psq_st fp4, OS_CONTEXT_PSF4(context), 0, 0 + psq_st fp5, OS_CONTEXT_PSF5(context), 0, 0 + psq_st fp6, OS_CONTEXT_PSF6(context), 0, 0 + psq_st fp7, OS_CONTEXT_PSF7(context), 0, 0 + psq_st fp8, OS_CONTEXT_PSF8(context), 0, 0 + psq_st fp9, OS_CONTEXT_PSF9(context), 0, 0 + psq_st fp10, OS_CONTEXT_PSF10(context), 0, 0 + psq_st fp11, OS_CONTEXT_PSF11(context), 0, 0 + psq_st fp12, OS_CONTEXT_PSF12(context), 0, 0 + psq_st fp13, OS_CONTEXT_PSF13(context), 0, 0 + psq_st fp14, OS_CONTEXT_PSF14(context), 0, 0 + psq_st fp15, OS_CONTEXT_PSF15(context), 0, 0 + psq_st fp16, OS_CONTEXT_PSF16(context), 0, 0 + psq_st fp17, OS_CONTEXT_PSF17(context), 0, 0 + psq_st fp18, OS_CONTEXT_PSF18(context), 0, 0 + psq_st fp19, OS_CONTEXT_PSF19(context), 0, 0 + psq_st fp20, OS_CONTEXT_PSF20(context), 0, 0 + psq_st fp21, OS_CONTEXT_PSF21(context), 0, 0 + psq_st fp22, OS_CONTEXT_PSF22(context), 0, 0 + psq_st fp23, OS_CONTEXT_PSF23(context), 0, 0 + psq_st fp24, OS_CONTEXT_PSF24(context), 0, 0 + psq_st fp25, OS_CONTEXT_PSF25(context), 0, 0 + psq_st fp26, OS_CONTEXT_PSF26(context), 0, 0 + psq_st fp27, OS_CONTEXT_PSF27(context), 0, 0 + psq_st fp28, OS_CONTEXT_PSF28(context), 0, 0 + psq_st fp29, OS_CONTEXT_PSF29(context), 0, 0 + psq_st fp30, OS_CONTEXT_PSF30(context), 0, 0 + psq_st fp31, OS_CONTEXT_PSF31(context), 0, 0 + +_return: + blr + // clang-format on +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSError.c b/src/static/GAEJ01_01/dolphin/os/OSError.c new file mode 100644 index 00000000..81ebd59b --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSError.c @@ -0,0 +1,218 @@ +// The shared headers still declare the pre-FPE (16 entry) error table. +#define __OSErrorTable __OSErrorTable16 +#include "dolphin/os.h" +#include "dolphin/os/OSError.h" +#include "dolphin/os/OSException.h" +#include "dolphin/os/OSInterrupt.h" +#include "dolphin/os/OSTime.h" +#include "dolphin/base/PPCArch.h" +#include "dolphin/hw_regs.h" + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#undef __OSErrorTable + +// All enable +#define FPSCR_ENABLE 0xF8 + +#define FPSCR_FX 0x80000000 // Exception summary +#define FPSCR_OX 0x10000000 // Overflow exception +#define FPSCR_UX 0x08000000 // Underflow exception +#define FPSCR_ZX 0x04000000 // Zero divide exception +#define FPSCR_XX 0x02000000 // Inexact exception +#define FPSCR_VXSNAN 0x01000000 // SNaN +#define FPSCR_VXISI 0x00800000 // Infinity - Infinity +#define FPSCR_VXIDI 0x00400000 // Infinity / Infinity +#define FPSCR_VXZDZ 0x00200000 // 0 / 0 +#define FPSCR_VXIMZ 0x00100000 // Infinity * 0 +#define FPSCR_VXVC 0x00080000 // Invalid compare +#define FPSCR_FI 0x00020000 // Fraction inexact +#define FPSCR_VXSOFT 0x00000400 // Software request +#define FPSCR_VXSQRT 0x00000200 // Invalid square root +#define FPSCR_VXCVI 0x00000100 // Invalid integer convert +#define FPSCR_NI 0x00000004 // Non-IEEE mode + +u32 PPCMffpscr(void); +void PPCMtfpscr(u32 newFPSCR); + +OSErrorHandler __OSErrorTable[OS_ERROR_FPE + 1]; +u32 __OSFpscrEnableBits = FPSCR_ENABLE; + +__declspec(weak) void OSReport(const char* msg, ...) { + va_list marker; + va_start(marker, msg); + vprintf(msg, marker); + va_end(marker); +} + +__declspec(weak) void OSPanic(const char* file, int line, const char* msg, ...) { + va_list marker; + u32 i; + u32* p; + + OSDisableInterrupts(); + va_start(marker, msg); + vprintf(msg, marker); + va_end(marker); + OSReport(" in \"%s\" on line %d.\n", file, line); + + OSReport("\nAddress: Back Chain LR Save\n"); + for (i = 0, p = (u32*)OSGetStackPointer(); p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) { + OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]); + } + + PPCHalt(); +} + +OSErrorHandler OSSetErrorHandler(OSError error, OSErrorHandler handler) { + OSErrorHandler oldHandler; + BOOL enabled; + + enabled = OSDisableInterrupts(); + oldHandler = __OSErrorTable[error]; + __OSErrorTable[error] = handler; + + if (error == OS_ERROR_FPE) { + u32 msr; + u32 fpscr; + OSThread* thread; + + msr = PPCMfmsr(); + PPCMtmsr(msr | MSR_FP); + fpscr = PPCMffpscr(); + if (handler) { + for (thread = __OSActiveThreadQueue.head; thread; thread = thread->linkActive.next) { + thread->context.srr1 |= MSR_FE0 | MSR_FE1; + if ((thread->context.state & OS_CONTEXT_STATE_FPSAVED) == 0) { + int i; + + thread->context.state |= OS_CONTEXT_STATE_FPSAVED; + for (i = 0; i < 32; ++i) { + *(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL; + *(u64*)&thread->context.psf[i] = (u64)0xffffffffffffffffLL; + } + thread->context.fpscr = FPSCR_NI; + } + thread->context.fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE; + thread->context.fpscr &= 0x6005F8FF; + } + fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE; + msr |= MSR_FE0 | MSR_FE1; + } else { + for (thread = __OSActiveThreadQueue.head; thread; thread = thread->linkActive.next) { + thread->context.srr1 &= ~(MSR_FE0 | MSR_FE1); + thread->context.fpscr &= ~FPSCR_ENABLE; + thread->context.fpscr &= 0x6005F8FF; + } + fpscr &= ~FPSCR_ENABLE; + msr &= ~(MSR_FE0 | MSR_FE1); + } + + fpscr &= 0x6005F8FF; + + PPCMtfpscr(fpscr); + PPCMtmsr(msr); + } + + OSRestoreInterrupts(enabled); + return oldHandler; +} + +void __OSUnhandledException(__OSException exception, OSContext* context, u32 dsisr, u32 dar) { + OSTime now; + + now = OSGetTime(); + + if (!(context->srr1 & MSR_RI)) { + OSReport("Non-recoverable Exception %d", exception); + } else { + if (exception == __OS_EXCEPTION_PROGRAM && (context->srr1 & (0x80000000 >> 11)) && __OSErrorTable[OS_ERROR_FPE] != NULL) { + u32 fpscr; + u32 msr; + + exception = OS_ERROR_FPE; + + msr = PPCMfmsr(); + PPCMtmsr(msr | MSR_FP); + + if (__OSFPUContext) { + OSSaveFPUContext((OSContext*)__OSFPUContext); + } + + fpscr = PPCMffpscr(); + fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT + | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI); + PPCMtfpscr(fpscr); + + PPCMtmsr(msr); + + if (__OSFPUContext == context) { + OSDisableScheduler(); + __OSErrorTable[exception](exception, context, dsisr, dar); + context->srr1 &= ~MSR_FP; + __OSFPUContext = NULL; + + context->fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN | FPSCR_VXSOFT + | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI); + OSEnableScheduler(); + __OSReschedule(); + } else { + context->srr1 &= ~MSR_FP; + __OSFPUContext = NULL; + } + + OSLoadContext(context); + } + + if (__OSErrorTable[exception]) { + OSDisableScheduler(); + __OSErrorTable[exception](exception, context, dsisr, dar); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); + } + + if (exception == __OS_EXCEPTION_DECREMENTER) { + OSLoadContext(context); + } + + OSReport("Unhandled Exception %d", exception); + } + + OSReport("\n"); + OSDumpContext(context); + OSReport("\nDSISR = 0x%08x DAR = 0x%08x\n", dsisr, dar); + OSReport("TB = 0x%016llx\n", now); + + switch (exception) { + case __OS_EXCEPTION_DSI: + OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access " + "invalid address 0x%x (read from DAR)\n", + context->srr0, dar); + break; + case __OS_EXCEPTION_ISI: + OSReport("\nAttempted to fetch instruction from invalid address 0x%x " + "(read from SRR0)\n", + context->srr0); + break; + case __OS_EXCEPTION_ALIGNMENT: + OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access " + "unaligned address 0x%x (read from DAR)\n", + context->srr0, dar); + break; + case __OS_EXCEPTION_PROGRAM: + OSReport("\nProgram exception : Possible illegal instruction/operation " + "at or around 0x%x (read from SRR0)\n", + context->srr0, dar); + break; + case OS_ERROR_PROTECTION: + OSReport("\n"); + OSReport("AI DMA Address = 0x%04x%04x\n", __DSPRegs[24], __DSPRegs[25]); + OSReport("ARAM DMA Address = 0x%04x%04x\n", __DSPRegs[16], __DSPRegs[17]); + OSReport("DI DMA Address = 0x%08x\n", __DIRegs[5]); + break; + } + + OSReport("\nLast interrupt (%d): SRR0 = 0x%08x TB = 0x%016llx\n", __OSLastInterrupt, __OSLastInterruptSrr0, + __OSLastInterruptTime); + PPCHalt(); +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSFont.c b/src/static/GAEJ01_01/dolphin/os/OSFont.c new file mode 100644 index 00000000..810096c3 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSFont.c @@ -0,0 +1,505 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +static OSFontHeader* FontData; // type unsure +static u8* SheetImage; // type unsure +static u8* WidthTable; // type unsure +static int CharsInSheet; // type unsure + +static u16 HankakuToCode[] = { + 0x20C, 0x20D, 0x20E, 0x20F, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215, 0x216, + 0x217, 0x218, 0x219, 0x21A, 0x21B, 0x21C, 0x21D, 0x21E, 0x21F, 0x220, 0x221, + 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22A, 0x22B, 0x22C, + 0x22D, 0x22E, 0x22F, 0x230, 0x231, 0x232, 0x233, 0x234, 0x235, 0x236, 0x237, + 0x238, 0x239, 0x23A, 0x23B, 0x23C, 0x23D, 0x23E, 0x23F, 0x240, 0x241, 0x242, + 0x243, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24A, 0x24B, 0x24C, 0x24D, + 0x24E, 0x24F, 0x250, 0x251, 0x252, 0x253, 0x254, 0x255, 0x256, 0x257, 0x258, + 0x259, 0x25A, 0x25B, 0x25C, 0x25D, 0x25E, 0x25F, 0x260, 0x261, 0x262, 0x263, + 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26A, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x26B, 0x26C, 0x26D, + 0x26E, 0x26F, 0x270, 0x271, 0x272, 0x273, 0x274, 0x275, 0x276, 0x277, 0x278, + 0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, 0x282, 0x283, + 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, + 0x28F, 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, + 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, 0x2A1, 0x2A2, 0x2A3, 0x2A4, + 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, +}; + +static u16 Zenkaku2Code[] = { + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00A, + 0x00B, 0x00C, 0x00D, 0x00E, 0x00F, 0x010, 0x011, 0x012, 0x013, 0x014, 0x015, + 0x016, 0x017, 0x018, 0x019, 0x01A, 0x01B, 0x01C, 0x01D, 0x01E, 0x01F, 0x020, + 0x021, 0x022, 0x023, 0x024, 0x025, 0x026, 0x027, 0x028, 0x029, 0x02A, 0x02B, + 0x02C, 0x02D, 0x02E, 0x02F, 0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, + 0x037, 0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x03F, 0x040, 0x041, + 0x042, 0x043, 0x044, 0x045, 0x046, 0x047, 0x048, 0x049, 0x04A, 0x04B, 0x04C, + 0x04D, 0x04E, 0x04F, 0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057, + 0x058, 0x059, 0x05A, 0x05B, 0x05C, 0x05D, 0x05E, 0x05F, 0x060, 0x061, 0x062, + 0x063, 0x064, 0x065, 0x066, 0x067, 0x068, 0x069, 0x06A, 0x06B, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x06C, 0x06D, + 0x06E, 0x06F, 0x070, 0x071, 0x072, 0x073, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07A, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x07B, + 0x07C, 0x07D, 0x07E, 0x07F, 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, + 0x087, 0x088, 0x089, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x08A, + 0x08B, 0x08C, 0x08D, 0x08E, 0x08F, 0x090, 0x091, 0x000, 0x000, 0x000, 0x000, + 0x092, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x093, 0x094, 0x095, 0x096, 0x097, 0x098, + 0x099, 0x09A, 0x09B, 0x09C, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x09D, 0x09E, 0x09F, 0x0A0, 0x0A1, 0x0A2, 0x0A3, 0x0A4, 0x0A5, 0x0A6, 0x0A7, + 0x0A8, 0x0A9, 0x0AA, 0x0AB, 0x0AC, 0x0AD, 0x0AE, 0x0AF, 0x0B0, 0x0B1, 0x0B2, + 0x0B3, 0x0B4, 0x0B5, 0x0B6, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x0B7, + 0x0B8, 0x0B9, 0x0BA, 0x0BB, 0x0BC, 0x0BD, 0x0BE, 0x0BF, 0x0C0, 0x0C1, 0x0C2, + 0x0C3, 0x0C4, 0x0C5, 0x0C6, 0x0C7, 0x0C8, 0x0C9, 0x0CA, 0x0CB, 0x0CC, 0x0CD, + 0x0CE, 0x0CF, 0x0D0, 0x000, 0x000, 0x000, 0x000, 0x0D1, 0x0D2, 0x0D3, 0x0D4, + 0x0D5, 0x0D6, 0x0D7, 0x0D8, 0x0D9, 0x0DA, 0x0DB, 0x0DC, 0x0DD, 0x0DE, 0x0DF, + 0x0E0, 0x0E1, 0x0E2, 0x0E3, 0x0E4, 0x0E5, 0x0E6, 0x0E7, 0x0E8, 0x0E9, 0x0EA, + 0x0EB, 0x0EC, 0x0ED, 0x0EE, 0x0EF, 0x0F0, 0x0F1, 0x0F2, 0x0F3, 0x0F4, 0x0F5, + 0x0F6, 0x0F7, 0x0F8, 0x0F9, 0x0FA, 0x0FB, 0x0FC, 0x0FD, 0x0FE, 0x0FF, 0x100, + 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, 0x10B, + 0x10C, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, + 0x117, 0x118, 0x119, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, + 0x122, 0x123, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x124, 0x125, 0x126, 0x127, 0x128, 0x129, 0x12A, 0x12B, 0x12C, + 0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x132, 0x133, 0x134, 0x135, 0x136, 0x137, + 0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141, 0x142, + 0x143, 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14A, 0x14B, 0x14C, 0x14D, + 0x14E, 0x14F, 0x150, 0x151, 0x152, 0x153, 0x154, 0x155, 0x156, 0x157, 0x158, + 0x159, 0x15A, 0x15B, 0x15C, 0x15D, 0x15E, 0x15F, 0x160, 0x161, 0x162, 0x163, + 0x164, 0x165, 0x166, 0x167, 0x168, 0x169, 0x16A, 0x16B, 0x16C, 0x16D, 0x16E, + 0x16F, 0x170, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0x177, 0x178, 0x179, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x17A, 0x17B, 0x17C, + 0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0x184, 0x185, 0x186, 0x187, + 0x188, 0x189, 0x18A, 0x18B, 0x18C, 0x18D, 0x18E, 0x18F, 0x190, 0x191, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x192, 0x193, 0x194, 0x195, + 0x196, 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19D, 0x19E, 0x19F, 0x1A0, + 0x1A1, 0x1A2, 0x1A3, 0x1A4, 0x1A5, 0x1A6, 0x1A7, 0x1A8, 0x1A9, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1AE, 0x1AF, 0x1B0, 0x1B1, + 0x1B2, 0x1B3, 0x1B4, 0x1B5, 0x1B6, 0x1B7, 0x1B8, 0x1B9, 0x1BA, 0x1BB, 0x1BC, + 0x1BD, 0x1BE, 0x1BF, 0x1C0, 0x1C1, 0x1C2, 0x1C3, 0x1C4, 0x1C5, 0x1C6, 0x1C7, + 0x1C8, 0x1C9, 0x1CA, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1CB, 0x1CC, 0x1CD, 0x1CE, + 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1D5, 0x1D6, 0x1D7, 0x1D8, 0x1D9, + 0x1DA, 0x1DB, 0x1DC, 0x1DD, 0x1DE, 0x1DF, 0x1E0, 0x1E1, 0x1E2, 0x1E3, 0x1E4, + 0x1E5, 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1EA, 0x1EB, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1EC, 0x1ED, + 0x1EE, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, 0x1F5, 0x1F6, 0x1F7, 0x1F8, + 0x1F9, 0x1FA, 0x1FB, 0x1FC, 0x1FD, 0x1FE, 0x1FF, 0x200, 0x201, 0x202, 0x203, + 0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20A, 0x20B, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x20C, 0x20D, 0x20E, 0x20F, 0x210, 0x211, 0x212, 0x213, + 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21A, 0x21B, 0x21C, 0x21D, 0x21E, + 0x21F, 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, + 0x22A, 0x22B, 0x22C, 0x22D, 0x22E, 0x22F, 0x230, 0x231, 0x232, 0x233, 0x234, + 0x235, 0x236, 0x237, 0x238, 0x239, 0x23A, 0x23B, 0x23C, 0x23D, 0x23E, 0x23F, + 0x240, 0x241, 0x242, 0x243, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24A, + 0x24B, 0x24C, 0x24D, 0x24E, 0x24F, 0x250, 0x251, 0x252, 0x253, 0x254, 0x255, + 0x256, 0x257, 0x258, 0x259, 0x25A, 0x25B, 0x25C, 0x25D, 0x25E, 0x25F, 0x260, + 0x261, 0x262, 0x263, 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26A, 0x26B, + 0x26C, 0x26D, 0x26E, 0x26F, 0x270, 0x271, 0x272, 0x273, 0x274, 0x275, 0x276, + 0x277, 0x278, 0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, + 0x282, 0x283, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, + 0x28D, 0x28E, 0x28F, 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, + 0x298, 0x299, 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, 0x2A1, 0x2A2, + 0x2A3, 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, 0x2AA, 0x2AB, 0x2AC, 0x2AD, + 0x2AE, 0x2AF, 0x2B0, 0x2B1, 0x2B2, 0x2B3, 0x2B4, 0x2B5, 0x2B6, 0x2B7, 0x2B8, + 0x2B9, 0x2BA, 0x2BB, 0x2BC, 0x2BD, 0x2BE, 0x2BF, 0x2C0, 0x2C1, 0x2C2, 0x2C3, + 0x2C4, 0x2C5, 0x2C6, 0x2C7, 0x2C8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x2C9, 0x2CA, 0x2CB, 0x2CC, 0x2CD, + 0x2CE, 0x2CF, 0x2D0, 0x2D1, 0x2D2, 0x2D3, 0x2D4, 0x2D5, 0x2D6, 0x2D7, 0x2D8, + 0x2D9, 0x2DA, 0x2DB, 0x2DC, 0x2DD, 0x2DE, 0x2DF, 0x2E0, 0x2E1, 0x2E2, 0x2E3, + 0x2E4, 0x2E5, 0x2E6, 0x000, 0x2E7, 0x2E8, 0x2E9, 0x2EA, 0x2EB, 0x2EC, 0x2ED, + 0x2EE, 0x2EF, 0x2F0, 0x2F1, 0x2F2, 0x2F3, 0x2F4, 0x2F5, 0x2F6, 0x2F7, 0x2F8, + 0x2F9, 0x2FA, 0x2FB, 0x2FC, 0x2FD, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x2FE, 0x2FF, 0x300, 0x301, 0x302, 0x303, 0x304, 0x305, 0x306, + 0x307, 0x308, 0x309, 0x30A, 0x30B, 0x30C, 0x30D, 0x30E, 0x30F, 0x310, 0x311, + 0x312, 0x313, 0x314, 0x315, 0x316, 0x317, 0x318, 0x319, 0x31A, 0x31B, 0x000 +}; + +static int GetFontCode(unsigned short code) +{ + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + if (code >= 0x20 && code <= 0xDF) { + return HankakuToCode[code - 0x20]; + } + + if (code > 0x889E) { + int i = ((code >> 8) - 0x88) * 188; + int j = (code & 0xFF) - 0x40; + + if (j >= 0x40) { + j--; + } + + return (i + j + 0x2BE); + } + + if (code < 0x879E) { + int i = ((code >> 8) - 0x81) * 188; + int j = (code & 0xFF) - 0x40; + + if (j >= 0x40) { + j--; + } + + return Zenkaku2Code[i + j]; + } + } else if (code > 0x20 && code <= 0xFF) { + return code - 0x20; + } else { + return 0; + } + return 0; +} + +static void Decode(unsigned char* s, unsigned char* d) +{ + int i; + int j; + int k; + int p; + int q; + int r7; // huh? DWARF info says these 2 variables might be register names + // and not actual names. + int r25; + int cnt; + int os; + unsigned int flag; + unsigned int code; + + os = *(int*)(s + 0x4); + r7 = *(int*)(s + 0x8); + r25 = *(int*)(s + 0xC); + + q = 0; + flag = 0; + p = 16; + + do { + // Get next mask + if (flag == 0) { + code = *(u32*)(s + p); + p += sizeof(u32); + flag = sizeof(u32) * 8; + } + + // Non-linked chunk + if (code & 0x80000000) { + d[q++] = s[r25++]; + } + // Linked chunk + else { + // Read offset from link table + j = s[r7] << 8 | s[r7 + 1]; + r7 += sizeof(u16); + + // Apply offset + k = q - (j & 0x0FFF); + cnt = j >> 12; + if (cnt == 0) { + cnt = s[r25++] + 0x12; + } else { + cnt += 2; + } + + // Copy chunk + for (i = 0; i < cnt; i++, q++, k++) { + d[q] = d[k - 1]; + } + } + + // Prepare next mask bit + code <<= 1; + flag--; + } while (q < os); +} + +static u32 GetFontSize(u8* buf) +{ + if (buf[0] == 'Y' && buf[1] == 'a' && buf[2] == 'y') { + return *(u32*)(buf + 0x4); + } + + return 0; +} + +unsigned short OSGetFontEncode(void) +{ + static u16 fontEncode = 0xFFFF; + if (fontEncode <= 1) { + return fontEncode; + } + switch (*(int*)OSPhysicalToCached(0xCC)) { + case VI_NTSC: + fontEncode = (__VIRegs[VI_DTV_STAT] & 2) ? OS_FONT_ENCODE_SJIS + : OS_FONT_ENCODE_ANSI; + break; + + case VI_PAL: + case VI_MPAL: + case VI_DEBUG: + case VI_DEBUG_PAL: + case VI_EURGB60: + default: + fontEncode = OS_FONT_ENCODE_ANSI; + } + + return fontEncode; +} + +static void ReadROM(void* buf, int length, int offset) +{ + int len; + while (length > 0) { + len = (length <= 0x100) ? length : 0x100; + length -= len; + + while (!__OSReadROM(buf, len, offset)) { + ; + } + + offset += len; + (u8*)buf += len; + } +} + +static u32 ReadFont(void* img) +{ + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + ReadROM(img, OS_FONT_ROM_SIZE_SJIS, 0x1AFF00); + } else { + ReadROM(img, OS_FONT_ROM_SIZE_ANSI, 0x1FCF00); + } + + return GetFontSize(img); +} + +u32 OSLoadFont(OSFontHeader* fontData, void* temp) +{ + u32 size; + + SheetImage = NULL; + size = ReadFont(temp); + if (size) { + Decode(temp, (void*)fontData); + FontData = fontData; + WidthTable = (u8*)FontData + FontData->widthTable; + CharsInSheet = FontData->sheetColumn * FontData->sheetRow; + } + + return size; +} + +char* OSGetFontTexel(char* string, void* image, long pos, long stride, + long* width) +{ + unsigned short code; + unsigned char* src; + unsigned char* dst; + int fontCode; + int sheet; + int numChars; + int row; + int column; + int x; + int y; + int offsetSrc; + int offsetDst; + unsigned char* colorIndex; + unsigned char* imageSrc; + + ASSERTLINE(0x1F6, FontData && !SheetImage); + + code = *string; + if (code == '\0') { + return string; + } + + string++; + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + if ((((code >= 0x80) && (code <= 0x9F)) + || ((code >= 0xE0) && (code <= 0xFF))) + && ((s8)*string != 0U)) { + code = (code << 8) | (*string++); // Shift-JIS encoded byte + } + } + colorIndex = &FontData->c0; + + ASSERTLINE(0x209, FontData->sheetFormat == GX_TF_I4); + + fontCode = GetFontCode(code); + + sheet = fontCode / CharsInSheet; + numChars = fontCode - (sheet * CharsInSheet); + row = numChars / FontData->sheetColumn; + column = (numChars - (row * FontData->sheetColumn)); + row *= FontData->cellHeight; + column *= FontData->cellWidth; + imageSrc = (u8*)FontData + FontData->sheetImage; + imageSrc += (sheet * FontData->sheetSize) / 2; + + for (y = 0; y < FontData->cellHeight; y++) { + for (x = 0; x < FontData->cellWidth; x++) { + src = imageSrc + + (((FontData->sheetWidth / 8) * 32) / 2) * ((row + y) / 8); + src += ((column + x) / 8) * 16; + src += ((row + y) % 8) * 2; + src += ((column + x) % 8) / 4; + + offsetSrc = (column + x) % 4; + + dst = (u8*)image + ((y / 8) * (((stride * 4) / 8) * 32)); + dst += (((pos + x) / 8) * 32); + dst += ((y % 8) * 4); + dst += ((pos + x) % 8) / 2; + + offsetDst = (pos + x) % 2; + + *dst |= colorIndex[*src >> (6 - (offsetSrc * 2)) & 3] + & ((offsetDst != 0) ? 0x0F : 0xF0); + } + } + *width = WidthTable[fontCode]; + + return string; +} + +static void ExpandFontSheet(u8* src, u8* dst) +{ + int i; + u8* colorIndex = &FontData->c0; + + if (FontData->sheetFormat == GX_TF_I4) { + for (i = (s32)(FontData->sheetFullSize) / 2 - 1; i >= 0; i--) { + dst[i * 2 + 0] = colorIndex[src[i] >> 6 & 3] & 0xF0 + | colorIndex[src[i] >> 4 & 3] & 0x0F; + dst[i * 2 + 1] = colorIndex[src[i] >> 2 & 3] & 0xF0 + | colorIndex[src[i] >> 0 & 3] & 0x0F; + } + } else if (FontData->sheetFormat == GX_TF_IA4) { + for (i = (s32)(FontData->sheetFullSize) / 4 - 1; i >= 0; i--) { + dst[i * 4 + 0] = colorIndex[src[i] >> 6 & 3]; + dst[i * 4 + 1] = colorIndex[src[i] >> 4 & 3]; + dst[i * 4 + 2] = colorIndex[src[i] >> 2 & 3]; + dst[i * 4 + 3] = colorIndex[src[i] >> 0 & 3]; + } + } + + DCStoreRange(dst, FontData->sheetFullSize); +} + +int OSInitFont(OSFontHeader* fontData) +{ + unsigned long size; + void* temp; + + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + temp = (void*)((u8*)fontData + 0xD3F00); + } else { + temp = (void*)((u8*)fontData + 0x1D120); + } + temp = ((void*)(((u32)(temp)) & ~((32) - 1))); + size = OSLoadFont(fontData, temp); + if (size == 0) { + return 0; + } + SheetImage = (u8*)FontData + FontData->sheetImage; + SheetImage = (void*)((s32)(SheetImage + 0x1F) & 0xFFFFFFE0); + ExpandFontSheet((u8*)FontData + FontData->sheetImage, SheetImage); + return 1; +} + +char* OSGetFontTexture(char* string, void** image, long* x, long* y, + long* width) +{ + unsigned short code; + int fontCode; + int sheet; + int numChars; + int row; + int column; + + ASSERTLINE(0x291, SheetImage); + ASSERTLINE(0x292, WidthTable); + + code = *string; + if (code == 0) { + *image = NULL; + return string; + } + + string++; + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + if ((((code >= 0x80) && (code <= 0x9F)) + || ((code >= 0xE0) && (code <= 0xFF))) + && ((s8)*string != 0U)) { + code = (code << 8) | (*string++); // Shift-JIS encoded byte + } + } + + fontCode = GetFontCode(code); + + sheet = fontCode / CharsInSheet; + ((u32*)image)[0] = (u32)SheetImage + (FontData->sheetSize * sheet); + numChars = fontCode - (sheet * CharsInSheet); + row = numChars / FontData->sheetColumn; + column = (numChars - (row * FontData->sheetColumn)); + *x = column * FontData->cellWidth; + *y = row * FontData->cellHeight; + + if (width) { + *width = WidthTable[fontCode]; + } + return string; +} + +char* OSGetFontWidth(char* string, s32* width) +{ + unsigned short code; + + ASSERTLINE(0x2C2, WidthTable); + + code = *string; + if (code == 0) { + return string; + } + + string++; + if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { + if ((((code >= 0x80) && (code <= 0x9F)) + || ((code >= 0xE0) && (code <= 0xFF))) + && ((s8)*string != 0U)) { + code = (code << 8) | (*string++); // Shift-JIS encoded byte + } + } + *width = WidthTable[GetFontCode(code)]; + return string; +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSInterrupt.c b/src/static/GAEJ01_01/dolphin/os/OSInterrupt.c new file mode 100644 index 00000000..c02baf6e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSInterrupt.c @@ -0,0 +1,424 @@ +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +static asm void ExternalInterruptHandler(register __OSException exception, + register OSContext* context); + +extern void __RAS_OSDisableInterrupts_begin(void); +extern void __RAS_OSDisableInterrupts_end(void); + +static __OSInterruptHandler* InterruptHandlerTable; + +volatile OSTime __OSLastInterruptTime; +volatile __OSInterrupt __OSLastInterrupt; +volatile u32 __OSLastInterruptSrr0; + +static OSInterruptMask InterruptPrioTable[] = { + OS_INTERRUPTMASK_PI_ERROR, + OS_INTERRUPTMASK_PI_DEBUG, + OS_INTERRUPTMASK_MEM, + OS_INTERRUPTMASK_PI_RSW, + OS_INTERRUPTMASK_PI_VI, + OS_INTERRUPTMASK_PI_PE, + OS_INTERRUPTMASK_PI_HSP, + OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP | OS_INTERRUPTMASK_AI + | OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI_SI + | OS_INTERRUPTMASK_PI_DI, + OS_INTERRUPTMASK_DSP_AI, + OS_INTERRUPTMASK_PI_CP, + 0xFFFFFFFF, +}; + +asm BOOL OSDisableInterrupts(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc +entry __RAS_OSDisableInterrupts_begin + mfmsr r3 + rlwinm r4, r3, 0, 17, 15 + mtmsr r4 +entry __RAS_OSDisableInterrupts_end + rlwinm r3, r3, 17, 31, 31 + blr +#endif // clang-format on +} + +asm BOOL OSEnableInterrupts(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + + mfmsr r3 + ori r4, r3, 0x8000 + mtmsr r4 + rlwinm r3, r3, 17, 31, 31 + blr +#endif // clang-format on +} + +asm BOOL OSRestoreInterrupts(register BOOL level) { +#ifdef __MWERKS__ // clang-format off + nofralloc + + cmpwi level, 0 + mfmsr r4 + beq _disable + ori r5, r4, 0x8000 + b _restore +_disable: + rlwinm r5, r4, 0, 17, 15 +_restore: + mtmsr r5 + rlwinm r3, r4, 17, 31, 31 + blr +#endif // clang-format on +} + +__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, + __OSInterruptHandler handler) +{ + __OSInterruptHandler oldHandler; + + oldHandler = InterruptHandlerTable[interrupt]; + InterruptHandlerTable[interrupt] = handler; + return oldHandler; +} + +__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt) +{ + return InterruptHandlerTable[interrupt]; +} + +void __OSInterruptInit(void) +{ + InterruptHandlerTable = (void*)OSPhysicalToCached(0x3040); + + memset(InterruptHandlerTable, 0, + __OS_INTERRUPT_MAX * sizeof(__OSInterruptHandler)); + + *(OSInterruptMask*)OSPhysicalToCached(0x00C4) = 0; + *(OSInterruptMask*)OSPhysicalToCached(0x00C8) = 0; + + __PIRegs[1] = 0xf0; + + __OSMaskInterrupts(OS_INTERRUPTMASK_MEM | OS_INTERRUPTMASK_DSP + | OS_INTERRUPTMASK_AI | OS_INTERRUPTMASK_EXI + | OS_INTERRUPTMASK_PI); + + __OSSetExceptionHandler(4, ExternalInterruptHandler); +} + +static u32 SetInterruptMask(OSInterruptMask mask, OSInterruptMask current) +{ + u32 reg; + + switch (__cntlzw(mask)) { + case __OS_INTERRUPT_MEM_0: + case __OS_INTERRUPT_MEM_1: + case __OS_INTERRUPT_MEM_2: + case __OS_INTERRUPT_MEM_3: + case __OS_INTERRUPT_MEM_ADDRESS: + reg = 0; + if (!(current & OS_INTERRUPTMASK_MEM_0)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_MEM_1)) + reg |= 0x2; + if (!(current & OS_INTERRUPTMASK_MEM_2)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_MEM_3)) + reg |= 0x8; + if (!(current & OS_INTERRUPTMASK_MEM_ADDRESS)) + reg |= 0x10; + __MEMRegs[0x0000000e] = (u16)reg; + mask &= ~OS_INTERRUPTMASK_MEM; + break; + case __OS_INTERRUPT_DSP_AI: + case __OS_INTERRUPT_DSP_ARAM: + case __OS_INTERRUPT_DSP_DSP: + reg = __DSPRegs[0x00000005]; + reg &= ~0x1F8; + if (!(current & OS_INTERRUPTMASK_DSP_AI)) + reg |= 0x10; + if (!(current & OS_INTERRUPTMASK_DSP_ARAM)) + reg |= 0x40; + if (!(current & OS_INTERRUPTMASK_DSP_DSP)) + reg |= 0x100; + __DSPRegs[0x00000005] = (u16)reg; + mask &= ~OS_INTERRUPTMASK_DSP; + break; + case __OS_INTERRUPT_AI_AI: + reg = __AIRegs[0]; + reg &= ~0x2C; + if (!(current & OS_INTERRUPTMASK_AI_AI)) + reg |= 0x4; + __AIRegs[0] = reg; + mask &= ~OS_INTERRUPTMASK_AI; + break; + case __OS_INTERRUPT_EXI_0_EXI: + case __OS_INTERRUPT_EXI_0_TC: + case __OS_INTERRUPT_EXI_0_EXT: + reg = __EXIRegs[0]; + reg &= ~0x2C0F; + if (!(current & OS_INTERRUPTMASK_EXI_0_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_0_TC)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_EXI_0_EXT)) + reg |= 0x400; + __EXIRegs[0] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_0; + break; + case __OS_INTERRUPT_EXI_1_EXI: + case __OS_INTERRUPT_EXI_1_TC: + case __OS_INTERRUPT_EXI_1_EXT: + reg = __EXIRegs[5]; + reg &= ~0xC0F; + + if (!(current & OS_INTERRUPTMASK_EXI_1_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_1_TC)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_EXI_1_EXT)) + reg |= 0x400; + __EXIRegs[5] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_1; + break; + case __OS_INTERRUPT_EXI_2_EXI: + case __OS_INTERRUPT_EXI_2_TC: + reg = __EXIRegs[10]; + reg &= ~0xF; + if (!(current & OS_INTERRUPTMASK_EXI_2_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_2_TC)) + reg |= 0x4; + + __EXIRegs[10] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_2; + break; + case __OS_INTERRUPT_PI_CP: + case __OS_INTERRUPT_PI_SI: + case __OS_INTERRUPT_PI_DI: + case __OS_INTERRUPT_PI_RSW: + case __OS_INTERRUPT_PI_ERROR: + case __OS_INTERRUPT_PI_VI: + case __OS_INTERRUPT_PI_DEBUG: + case __OS_INTERRUPT_PI_PE_TOKEN: + case __OS_INTERRUPT_PI_PE_FINISH: + case __OS_INTERRUPT_PI_HSP: + reg = 0xF0; + + if (!(current & OS_INTERRUPTMASK_PI_CP)) { + reg |= 0x800; + } + if (!(current & OS_INTERRUPTMASK_PI_SI)) { + reg |= 0x8; + } + if (!(current & OS_INTERRUPTMASK_PI_DI)) { + reg |= 0x4; + } + if (!(current & OS_INTERRUPTMASK_PI_RSW)) { + reg |= 0x2; + } + if (!(current & OS_INTERRUPTMASK_PI_ERROR)) { + reg |= 0x1; + } + if (!(current & OS_INTERRUPTMASK_PI_VI)) { + reg |= 0x100; + } + if (!(current & OS_INTERRUPTMASK_PI_DEBUG)) { + reg |= 0x1000; + } + if (!(current & OS_INTERRUPTMASK_PI_PE_TOKEN)) { + reg |= 0x200; + } + if (!(current & OS_INTERRUPTMASK_PI_PE_FINISH)) { + reg |= 0x400; + } + if (!(current & OS_INTERRUPTMASK_PI_HSP)) { + reg |= 0x2000; + } + __PIRegs[1] = reg; + mask &= ~OS_INTERRUPTMASK_PI; + break; + default: + break; + } + return mask; +} + +OSInterruptMask __OSMaskInterrupts(OSInterruptMask global) +{ + BOOL enabled; + OSInterruptMask prev; + OSInterruptMask local; + OSInterruptMask mask; + + enabled = OSDisableInterrupts(); + prev = *(OSInterruptMask*)OSPhysicalToCached(0x00C4); + local = *(OSInterruptMask*)OSPhysicalToCached(0x00C8); + mask = ~(prev | local) & global; + global |= prev; + *(OSInterruptMask*)OSPhysicalToCached(0x00C4) = global; + while (mask) { + mask = SetInterruptMask(mask, global | local); + } + OSRestoreInterrupts(enabled); + return prev; +} + +OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask global) +{ + BOOL enabled; + OSInterruptMask prev; + OSInterruptMask local; + OSInterruptMask mask; + + enabled = OSDisableInterrupts(); + prev = *(OSInterruptMask*)OSPhysicalToCached(0x00C4); + local = *(OSInterruptMask*)OSPhysicalToCached(0x00C8); + mask = (prev | local) & global; + global = prev & ~global; + *(OSInterruptMask*)OSPhysicalToCached(0x00C4) = global; + while (mask) { + mask = SetInterruptMask(mask, global | local); + } + OSRestoreInterrupts(enabled); + return prev; +} + +void __OSDispatchInterrupt(__OSException exception, OSContext* context) +{ + u32 intsr; + u32 reg; + OSInterruptMask cause; + OSInterruptMask unmasked; + OSInterruptMask* prio; + __OSInterrupt interrupt; + __OSInterruptHandler handler; + + intsr = __PIRegs[0]; + intsr &= ~0x00010000; + + if (intsr == 0 || (intsr & __PIRegs[1]) == 0) { + OSLoadContext(context); + } + + cause = 0; + + if (intsr & 0x00000080) { + reg = __MEMRegs[15]; + if (reg & 0x1) + cause |= OS_INTERRUPTMASK_MEM_0; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_MEM_1; + if (reg & 0x4) + cause |= OS_INTERRUPTMASK_MEM_2; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_MEM_3; + if (reg & 0x10) + cause |= OS_INTERRUPTMASK_MEM_ADDRESS; + } + + if (intsr & 0x00000040) { + reg = __DSPRegs[5]; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_DSP_AI; + if (reg & 0x20) + cause |= OS_INTERRUPTMASK_DSP_ARAM; + if (reg & 0x80) + cause |= OS_INTERRUPTMASK_DSP_DSP; + } + + if (intsr & 0x00000020) { + reg = __AIRegs[0]; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_AI_AI; + } + + if (intsr & 0x00000010) { + reg = __EXIRegs[0]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_0_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_0_TC; + if (reg & 0x800) + cause |= OS_INTERRUPTMASK_EXI_0_EXT; + reg = __EXIRegs[5]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_1_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_1_TC; + if (reg & 0x800) + cause |= OS_INTERRUPTMASK_EXI_1_EXT; + reg = __EXIRegs[10]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_2_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_2_TC; + } + + if (intsr & 0x00002000) + cause |= OS_INTERRUPTMASK_PI_HSP; + if (intsr & 0x00001000) + cause |= OS_INTERRUPTMASK_PI_DEBUG; + if (intsr & 0x00000400) + cause |= OS_INTERRUPTMASK_PI_PE_FINISH; + if (intsr & 0x00000200) + cause |= OS_INTERRUPTMASK_PI_PE_TOKEN; + if (intsr & 0x00000100) + cause |= OS_INTERRUPTMASK_PI_VI; + if (intsr & 0x00000008) + cause |= OS_INTERRUPTMASK_PI_SI; + if (intsr & 0x00000004) + cause |= OS_INTERRUPTMASK_PI_DI; + if (intsr & 0x00000002) + cause |= OS_INTERRUPTMASK_PI_RSW; + if (intsr & 0x00000800) + cause |= OS_INTERRUPTMASK_PI_CP; + if (intsr & 0x00000001) + cause |= OS_INTERRUPTMASK_PI_ERROR; + + unmasked = cause + & ~(*(OSInterruptMask*)OSPhysicalToCached(0x00C4) + | *(OSInterruptMask*)OSPhysicalToCached(0x00C8)); + if (unmasked) { + for (prio = InterruptPrioTable;; ++prio) { + if (unmasked & *prio) { + interrupt = (__OSInterrupt)__cntlzw(unmasked & *prio); + break; + } + } + + handler = __OSGetInterruptHandler(interrupt); + if (handler) { + if (interrupt > __OS_INTERRUPT_MEM_ADDRESS) { + __OSLastInterrupt = interrupt; + __OSLastInterruptTime = OSGetTime(); + __OSLastInterruptSrr0 = context->srr0; + } + OSDisableScheduler(); + handler(interrupt, context); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); + } + } + + OSLoadContext(context); +} + +static asm void ExternalInterruptHandler(register __OSException exception, + register OSContext* context) +{ +#pragma unused(exception) +#ifdef __MWERKS__ // clang-format off + nofralloc + OS_EXCEPTION_SAVE_GPRS(context) + stwu r1, -0x8(r1) + b __OSDispatchInterrupt +#endif // clang-format on +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSLink.c b/src/static/GAEJ01_01/dolphin/os/OSLink.c new file mode 100644 index 00000000..f714efda --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSLink.c @@ -0,0 +1,490 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t)) + +// Name Value Field Calculation +#define R_PPC_NONE 0 // none none +#define R_PPC_ADDR32 1 // word32 S + A +#define R_PPC_ADDR24 2 // low24* (S + A) >> 2 +#define R_PPC_ADDR16 3 // half16* S + A +#define R_PPC_ADDR16_LO 4 // half16 #lo(S + A) +#define R_PPC_ADDR16_HI 5 // half16 #hi(S + A) +#define R_PPC_ADDR16_HA 6 // half16 #ha(S + A) +#define R_PPC_ADDR14 7 // low14* (S + A) >> 2 +#define R_PPC_ADDR14_BRTAKEN 8 // low14* (S + A) >> 2 +#define R_PPC_ADDR14_BRNTAKEN 9 // low14* (S + A) >> 2 +#define R_PPC_REL24 10 // low24* (S + A - P) >> 2 +#define R_PPC_REL14 11 // low14* (S + A - P) >> 2 +#define R_PPC_REL14_BRTAKEN 12 // low14* (S + A - P) >> 2 +#define R_PPC_REL14_BRNTAKEN 13 // low14* (S + A - P) >> 2 + +#define R_PPC_GOT16 14 // half16* G + A +#define R_PPC_GOT16_LO 15 // half16 #lo(G + A) +#define R_PPC_GOT16_HI 16 // half16 #hi(G + A) +#define R_PPC_GOT16_HA 17 // half16 #ha(G + A) +#define R_PPC_PLTREL24 18 // low24* (L + A - P) >> 2 +#define R_PPC_COPY 19 // none none +#define R_PPC_GLOB_DAT 20 // word32 S + A +#define R_PPC_JMP_SLOT 21 // none +#define R_PPC_RELATIVE 22 // word32 B + A + +#define R_PPC_LOCAL24PC 23 // low24* + +#define R_PPC_UADDR32 24 // word32 S + A +#define R_PPC_UADDR16 25 // half16* S + A +#define R_PPC_REL32 26 // word32 S + A - P + +#define R_PPC_PLT32 27 // word32 L + A +#define R_PPC_PLTREL32 28 // word32 L + A - P +#define R_PPC_PLT16_LO 29 // half16 #lo(L + A) +#define R_PPL_PLT16_HI 30 // half16 #hi(L + A) +#define R_PPC_PLT16_HA 31 // half16 #ha(L + A) + +#define R_PPC_SDAREL16 32 // half16* S + A - _SDA_BASE_ +#define R_PPC_SECTOFF 33 // half16* R + A +#define R_PPC_SECTOFF_LO 34 // half16 #lo(R + A) +#define R_PPC_SECTOFF_HI 35 // half16 #hi(R + A) +#define R_PPC_SECTOFF_HA 36 // half16 #ha(R + A) +#define R_PPC_ADDR30 37 // word30 (S + A - P) >> 2 + +#define R_PPC_EMB_NADDR32 101 // uword32 N (A - S) +#define R_PPC_EMB_NADDR16 102 // uhalf16 Y (A - S) +#define R_PPC_EMB_NADDR16_LO 103 // uhalf16 N #lo(A - S) +#define R_PPC_EMB_NADDR16_HI 104 // uhalf16 N #hi(A - S) +#define R_PPC_EMB_NADDR16_HA 105 // uhalf16 N #ha(A - S) +#define R_PPC_EMB_SDAI16 106 // uhalf16 Y T +#define R_PPC_EMB_SDA2I16 107 // uhalf16 Y U +#define R_PPC_EMB_SDA2REL 108 // uhalf16 Y S + A - _SDA2_BASE_ +#define R_PPC_EMB_SDA21 109 // ulow21 N +#define R_PPC_EMB_MRKREF 110 // none N +#define R_PPC_EMB_RELSEC16 111 // uhalf16 Y V + A +#define R_PPC_EMB_RELST_LO 112 // uhalf16 N #lo(W + A) +#define R_PPC_EMB_RELST_HI 113 // uhalf16 N #hi(W + A) +#define R_PPC_EMB_RELST_HA 114 // uhalf16 N #ha(W + A) +#define R_PPC_EMB_BIT_FLD 115 // uword32 Y +#define R_PPC_EMB_RELSDA 116 // uhalf16 Y + +#undef OS_MODULE_VERSION +#define OS_MODULE_VERSION 3 + +typedef struct OSModuleHeaderEx { + OSModuleHeader header; + u32 fixSize; +} OSModuleHeaderEx; + +#define ENQUEUE_INFO(queue, info, link) \ + do { \ + OSModuleInfo* __prev; \ + \ + __prev = (queue)->tail; \ + if (__prev == NULL) \ + (queue)->head = (info); \ + else \ + __prev->link.next = (info); \ + (info)->link.prev = __prev; \ + (info)->link.next = NULL; \ + (queue)->tail = (info); \ + } while (0) + +#define DEQUEUE_INFO(info, queue, link) \ + do { \ + OSModuleInfo* __next; \ + OSModuleInfo* __prev; \ + \ + __next = (info)->link.next; \ + __prev = (info)->link.prev; \ + \ + if (__next == NULL) \ + (queue)->tail = __prev; \ + else \ + __next->link.prev = __prev; \ + \ + if (__prev == NULL) \ + (queue)->head = __next; \ + else \ + __prev->link.next = __next; \ + } while (0) + +#pragma dont_inline on +void OSNotifyLink(OSModuleInfo* module) {} + +void OSNotifyUnlink(OSModuleInfo* module) {} +#pragma dont_inline reset + +void OSSetStringTable(const void* stringTable) { + __OSStringTable = (void*)stringTable; +} + +static BOOL Relocate(OSModuleHeader* newModule, OSModuleHeader* module) { + OSModuleID idNew; + OSImportInfo* imp; + OSRel* rel; + OSSectionInfo* si; + OSSectionInfo* siFlush; + u32* p; + u32 offset; + u32 x; + + idNew = newModule ? newModule->info.id : 0; + for (imp = (OSImportInfo*)module->impOffset; + imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++) + { + if (imp->id == idNew) { + goto Found; + } + } + return FALSE; + +Found: + siFlush = 0; + for (rel = (OSRel*)imp->offset; rel->type != R_DOLPHIN_END; rel++) { + (u8*)p += rel->offset; + if (idNew) { + si = &OSGetSectionInfo(newModule)[rel->section]; + offset = OS_SECTIONINFO_OFFSET(si->offset); + } else { + offset = 0; + } + + switch (rel->type) { + case R_PPC_NONE: + break; + case R_PPC_ADDR32: + x = offset + rel->addend; + *p = x; + break; + case R_PPC_ADDR24: + x = offset + rel->addend; + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_ADDR16: + x = offset + rel->addend; + *(u16*)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_LO: + x = offset + rel->addend; + *(u16*)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_HI: + x = offset + rel->addend; + *(u16*)p = (u16)(((x >> 16) & 0xffff)); + break; + case R_PPC_ADDR16_HA: + x = offset + rel->addend; + *(u16*)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff); + break; + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + x = offset + rel->addend; + *p = (*p & ~0x0000fffc) | (x & 0x0000fffc); + break; + case R_PPC_REL24: + x = offset + rel->addend - (u32)p; + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + x = offset + rel->addend - (u32)p; + *p = (*p & ~0x0000fffc) | (x & 0x0000fffc); + break; + case R_DOLPHIN_NOP: + break; + case R_DOLPHIN_SECTION: + si = &OSGetSectionInfo(module)[rel->section]; + p = (u32*)OS_SECTIONINFO_OFFSET(si->offset); + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void*)offset, siFlush->size); + ICInvalidateRange((void*)offset, siFlush->size); + } + siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0; + break; + default: + OSReport("OSLink: unknown relocation type %3d\n", rel->type); + break; + } + } + + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void*)offset, siFlush->size); + ICInvalidateRange((void*)offset, siFlush->size); + } + + return TRUE; +} + +static BOOL Link(OSModuleInfo* newModule, void* bss, BOOL fixed) { + u32 i; + OSSectionInfo* si; + OSModuleHeader* moduleHeader; + OSModuleInfo* moduleInfo; + OSImportInfo* imp; + + + moduleHeader = (OSModuleHeader*)newModule; + moduleHeader->bssSection = 0; + + ASSERTLINE(293, newModule->version < 2 || moduleHeader->bssAlign == 0 || (u32) bss % moduleHeader->bssAlign == 0); + + if (OS_MODULE_VERSION < newModule->version || + 2 <= newModule->version && + (moduleHeader->align && (u32)newModule % moduleHeader->align != 0 || + moduleHeader->bssAlign && (u32)bss % moduleHeader->bssAlign != 0)) + { + return FALSE; + } + + ENQUEUE_INFO(&__OSModuleList, newModule, link); + newModule->sectionInfoOffset += (u32)moduleHeader; + moduleHeader->relOffset += (u32)moduleHeader; + moduleHeader->impOffset += (u32)moduleHeader; + if (3 <= newModule->version) { + ((OSModuleHeaderEx*)moduleHeader)->fixSize += (u32)moduleHeader; + } + + for (i = 1; i < newModule->numSections; i++) { + si = &OSGetSectionInfo(newModule)[i]; + if (si->offset != 0) { + si->offset += (u32)moduleHeader; + } else if (si->size != 0) { + moduleHeader->bssSection = (u8)i; + si->offset = (u32)bss; + } + } + + for (imp = (OSImportInfo*)moduleHeader->impOffset; + imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) + { + imp->offset += (u32)moduleHeader; + } + + if (moduleHeader->prologSection != SHN_UNDEF) { + moduleHeader->prolog += + OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->prologSection].offset); + } + + if (moduleHeader->epilogSection != SHN_UNDEF) { + moduleHeader->epilog += + OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->epilogSection].offset); + } + + if (moduleHeader->unresolvedSection != SHN_UNDEF) { + moduleHeader->unresolved += OS_SECTIONINFO_OFFSET( + OSGetSectionInfo(newModule)[moduleHeader->unresolvedSection].offset); + } + + if (__OSStringTable) { + newModule->nameOffset += (u32)__OSStringTable; + } + + Relocate(0, moduleHeader); + + for (moduleInfo = __OSModuleList.head; moduleInfo; moduleInfo = moduleInfo->link.next) { + Relocate(moduleHeader, (OSModuleHeader*)moduleInfo); + if (moduleInfo != newModule) { + Relocate((OSModuleHeader*)moduleInfo, moduleHeader); + } + } + + if (fixed) { + for (imp = (OSImportInfo*)moduleHeader->impOffset; + imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) + { + if (imp->id == 0 || imp->id == newModule->id) { + moduleHeader->impSize = (u32)((u8*)imp - (u8*)moduleHeader->impOffset); + break; + } + } + } + + memset(bss, 0, moduleHeader->bssSize); + + OSNotifyLink(newModule); + return TRUE; +} + +BOOL OSLink(OSModuleInfo* newModule, void* bss) { + return Link(newModule, bss, FALSE); +} + +BOOL OSLinkFixed(OSModuleInfo* newModule, void* bss) { + + if (OS_MODULE_VERSION < newModule->version || newModule->version < 3) { + return FALSE; + } + return Link(newModule, bss, TRUE); +} + +static BOOL Undo(OSModuleHeader* newModule, OSModuleHeader* module) { + OSModuleID idNew; + OSImportInfo* imp; + OSRel* rel; + OSSectionInfo* si; + OSSectionInfo* siFlush; + u32* p; + u32 offset; + u32 x; + + + idNew = newModule->info.id; + + for (imp = (OSImportInfo*)module->impOffset; + imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++) + { + if (imp->id == idNew) { + goto Found; + } + } + return FALSE; + +Found: + siFlush = 0; + for (rel = (OSRel*)imp->offset; rel->type != R_DOLPHIN_END; rel++) { + (u8*)p += rel->offset; + si = &OSGetSectionInfo(newModule)[rel->section]; + offset = OS_SECTIONINFO_OFFSET(si->offset); + x = 0; + switch (rel->type) { + case R_PPC_NONE: + break; + case R_PPC_ADDR32: + *p = x; + break; + case R_PPC_ADDR24: + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_ADDR16: + *(u16*)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_LO: + *(u16*)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_HI: + *(u16*)p = (u16)(((x >> 16) & 0xffff)); + break; + case R_PPC_ADDR16_HA: + *(u16*)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff); + break; + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + *p = (*p & ~0x0000fffc) | (x & 0x0000fffc); + break; + case R_PPC_REL24: + if (module->unresolvedSection != SHN_UNDEF) { + x = (u32)module->unresolved - (u32)p; + } + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + *p = (*p & ~0x0000fffc) | (x & 0x0000fffc); + break; + case R_DOLPHIN_NOP: + break; + case R_DOLPHIN_SECTION: + si = &OSGetSectionInfo(module)[rel->section]; + p = (u32*)OS_SECTIONINFO_OFFSET(si->offset); + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void*)offset, siFlush->size); + ICInvalidateRange((void*)offset, siFlush->size); + } + siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0; + break; + default: + OSReport("OSUnlink: unknown relocation type %3d\n", rel->type); + break; + } + } + + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void*)offset, siFlush->size); + ICInvalidateRange((void*)offset, siFlush->size); + } + + return TRUE; +} + +BOOL OSUnlink(OSModuleInfo* oldModule) { + OSModuleHeader* moduleHeader; + OSModuleInfo* moduleInfo; + u32 i; + OSSectionInfo* si; + OSImportInfo* imp; + + + moduleHeader = (OSModuleHeader*)oldModule; + + DEQUEUE_INFO(oldModule, &__OSModuleList, link); + + for (moduleInfo = __OSModuleList.head; moduleInfo; moduleInfo = moduleInfo->link.next) { + Undo(moduleHeader, (OSModuleHeader*)moduleInfo); + } + + OSNotifyUnlink(oldModule); + + if (__OSStringTable) { + oldModule->nameOffset -= (u32)__OSStringTable; + } + + if (moduleHeader->prologSection != SHN_UNDEF) { + moduleHeader->prolog -= + OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->prologSection].offset); + } + + if (moduleHeader->epilogSection != SHN_UNDEF) { + moduleHeader->epilog -= + OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->epilogSection].offset); + } + + if (moduleHeader->unresolvedSection != SHN_UNDEF) { + moduleHeader->unresolved -= OS_SECTIONINFO_OFFSET( + OSGetSectionInfo(oldModule)[moduleHeader->unresolvedSection].offset); + } + + for (imp = (OSImportInfo*)moduleHeader->impOffset; + imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) + { + imp->offset -= (u32)moduleHeader; + } + + for (i = 1; i < oldModule->numSections; i++) { + si = &OSGetSectionInfo(oldModule)[i]; + if (i == moduleHeader->bssSection) { + moduleHeader->bssSection = 0; + si->offset = 0; + } else if (si->offset != 0) { + si->offset -= (u32)moduleHeader; + } + } + moduleHeader->relOffset -= (u32)moduleHeader; + moduleHeader->impOffset -= (u32)moduleHeader; + oldModule->sectionInfoOffset -= (u32)moduleHeader; + + return TRUE; +} + +void __OSModuleInit(void) { + __OSModuleList.head = __OSModuleList.tail = 0; + __OSStringTable = 0; +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSMemory.c b/src/static/GAEJ01_01/dolphin/os/OSMemory.c new file mode 100644 index 00000000..588cc260 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSMemory.c @@ -0,0 +1,216 @@ +#include +#include "dolphin/os/OSMemory.h" +#include "dolphin/os/OSError.h" +#include "dolphin/os/OSInterrupt.h" +#include "dolphin/hw_regs.h" +#include "dolphin/os/OSReset.h" + +#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) +#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1)) + +u32 OSGetPhysicalMemSize(void){ + return *(u32*)(OSPhysicalToCached(0x28)); +} + +u32 OSGetConsoleSimulatedMemSize(void){ + return *(u32*)(OSPhysicalToCached(0xF0)); +} + +static BOOL OnReset(BOOL final){ + if (final) { + __MEMRegs[8] = 0xff; + __OSMaskInterrupts(0xF0000000); + } + return TRUE; +} + +static void MEMIntrruptHandler(__OSInterrupt interrupt, OSContext* ctx){ + u32 cause = __MEMRegs[0xf]; + u32 addr = (((u32) __MEMRegs[0x12] & 0x3ff) << 16) | __MEMRegs[0x11]; + __MEMRegs[0x10] = 0; + + if(__OSErrorTable[OS_ERROR_PROTECTION]) { + __OSErrorTable[OS_ERROR_PROTECTION](OS_ERROR_PROTECTION, ctx, cause, addr); + return; + } + + __OSUnhandledException(OS_ERROR_PROTECTION, ctx, cause, addr); +} + +#define OS_PROTECT_CONTROL_NONE 0x00 +#define OS_PROTECT_CONTROL_READ 0x01 +#define OS_PROTECT_CONTROL_WRITE 0x02 +#define OS_PROTECT_CONTROL_RDWR \ + (OS_PROTECT_CONTROL_READ | OS_PROTECT_CONTROL_WRITE) + +void OSProtectRange(u32 chan, void* addr, u32 nBytes, u32 control) +{ + BOOL enabled; + u32 start; + u32 end; + u16 reg; + if (4 <= chan) { + return; + } + + control &= OS_PROTECT_CONTROL_RDWR; + + end = (u32)addr + nBytes; + start = TRUNC(addr, 1u << 10); + end = ROUND(end, 1u << 10); + + DCFlushRange((void*)start, end - start); + + enabled = OSDisableInterrupts(); + + __OSMaskInterrupts(OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0 + chan)); + + __MEMRegs[0 + 2 * chan] = (u16)(start >> 10); + __MEMRegs[1 + 2 * chan] = (u16)(end >> 10); + + reg = __MEMRegs[8]; + reg &= ~(OS_PROTECT_CONTROL_RDWR << 2 * chan); + reg |= control << 2 * chan; + __MEMRegs[8] = reg; + + if (control != OS_PROTECT_CONTROL_RDWR) { + __OSUnmaskInterrupts(OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0 + chan)); + } + + OSRestoreInterrupts(enabled); +} + +static asm void Config24MB(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + + li r7, 0 + lis r4, 0x0000 + addi r4, r4, 0x0002 + lis r3, 0x8000 + addi r3, r3, 0x01FF + lis r6, 0x0100 + addi r6, r6, 0x0002 + lis r5, 0x8100 + addi r5, r5, 0x00FF + isync + mtdbatu 0, r7 + mtdbatl 0, r4 + mtdbatu 0, r3 + isync + mtibatu 0, r7 + mtibatl 0, r4 + mtibatu 0, r3 + isync + mtdbatu 2, r7 + mtdbatl 2, r6 + mtdbatu 2, r5 + isync + mtibatu 2, r7 + mtibatl 2, r6 + mtibatu 2, r5 + isync + mfmsr r3 + ori r3, r3, 0x30 + mtspr 0x1b, r3 + mflr r3 + mtspr 0x1a, r3 + rfi +#endif // clang-format on +} + +static asm void Config48MB(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + + li r7, 0 + lis r4, 0x0000 + addi r4, r4, 0x0002 + lis r3, 0x8000 + addi r3, r3, 0x03FF + lis r6, 0x0200 + addi r6, r6, 0x0002 + lis r5, 0x8200 + addi r5, r5, 0x01FF + isync + mtdbatu 0, r7 + mtdbatl 0, r4 + mtdbatu 0, r3 + isync + mtibatu 0, r7 + mtibatl 0, r4 + mtibatu 0, r3 + isync + mtdbatu 2, r7 + mtdbatl 2, r6 + mtdbatu 2, r5 + isync + mtibatu 2, r7 + mtibatl 2, r6 + mtibatu 2, r5 + isync + mfmsr r3 + ori r3, r3, 0x30 + mtspr 0x1b, r3 + mflr r3 + mtspr 0x1a, r3 + rfi +#endif // clang-format on +} + +static asm void RealMode(register u32 config) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + + clrlwi config, config, 2 + mtspr 0x1a, config + mfmsr config + rlwinm config, config, 0, 0x1c, 0x19 + mtspr 0x1b, config + rfi +#endif // clang-format on +} + +static OSResetFunctionInfo ResetFunctionInfo = { + OnReset, + 0x7F, +}; + +void __OSInitMemoryProtection() +{ + u32 padding[8]; + u32 simulatedSize; + BOOL enabled; + simulatedSize = OSGetConsoleSimulatedMemSize(); + enabled = OSDisableInterrupts(); + + __MEMRegs[16] = 0; + __MEMRegs[8] = 0xFF; + + __OSMaskInterrupts(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 + | OS_INTERRUPTMASK_MEM_2 | OS_INTERRUPTMASK_MEM_3); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_0, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_1, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_2, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_3, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_ADDRESS, MEMIntrruptHandler); + OSRegisterResetFunction(&ResetFunctionInfo); + + if (OSGetConsoleSimulatedMemSize() < OSGetPhysicalMemSize() + && OSGetConsoleSimulatedMemSize() == 0x1800000) { + DCInvalidateRange((void*)0x81800000, 0x1800000); + __MEMRegs[20] = 2; + } + + if (simulatedSize <= 0x1800000) { + RealMode((u32)&Config24MB); + } else if (simulatedSize <= 0x3000000) { + RealMode((u32)&Config48MB); + } + + __OSUnmaskInterrupts(OS_INTERRUPTMASK_MEM_ADDRESS); + OSRestoreInterrupts(enabled); +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSMessage.c b/src/static/GAEJ01_01/dolphin/os/OSMessage.c new file mode 100644 index 00000000..71bec9f6 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSMessage.c @@ -0,0 +1,74 @@ +#include +#include + +void OSInitMessageQueue(struct OSMessageQueue* mq, OSMessage* msgArray, + int msgCount) +{ + OSInitThreadQueue(&mq->queueSend); + OSInitThreadQueue(&mq->queueReceive); + mq->msgArray = msgArray; + mq->msgCount = msgCount; + mq->firstIndex = 0; + mq->usedCount = 0; +} + +int OSSendMessage(struct OSMessageQueue* mq, OSMessage msg, int flags) +{ + int enabled; + long lastIndex; + + enabled = OSDisableInterrupts(); + while (mq->msgCount <= mq->usedCount) { + if (!(flags & 1)) { + OSRestoreInterrupts(enabled); + return 0; + } + OSSleepThread(&mq->queueSend); + } + lastIndex = (mq->firstIndex + mq->usedCount) % mq->msgCount; + ((u32*)mq->msgArray)[lastIndex] = (u32)msg; + mq->usedCount++; + OSWakeupThread(&mq->queueReceive); + OSRestoreInterrupts(enabled); + return 1; +} + +int OSReceiveMessage(struct OSMessageQueue* mq, OSMessage* msg, int flags) +{ + int enabled = OSDisableInterrupts(); + + while (mq->usedCount == 0) { + if (!(flags & 1)) { + OSRestoreInterrupts(enabled); + return 0; + } + OSSleepThread(&mq->queueReceive); + } + if (msg != NULL) { + *(u32*)msg = ((u32*)mq->msgArray)[mq->firstIndex]; + } + + mq->firstIndex = (mq->firstIndex + 1) % mq->msgCount; + mq->usedCount--; + OSWakeupThread(&mq->queueSend); + OSRestoreInterrupts(enabled); + return 1; +} + +int OSJamMessage(struct OSMessageQueue * mq, OSMessage msg, int flags) { + int enabled = OSDisableInterrupts(); + + while(mq->msgCount <= mq->usedCount) { + if(!(flags & 1)) { + OSRestoreInterrupts(enabled); + return 0; + } + OSSleepThread(&mq->queueSend); + } + mq->firstIndex = (mq->firstIndex + mq->msgCount - 1) % mq->msgCount; + ((u32*)mq->msgArray)[mq->firstIndex] = (u32)msg; + mq->usedCount++; + OSWakeupThread(&mq->queueReceive); + OSRestoreInterrupts(enabled); + return 1; +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSMutex.c b/src/static/GAEJ01_01/dolphin/os/OSMutex.c new file mode 100644 index 00000000..e3e9f532 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSMutex.c @@ -0,0 +1,255 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +#define ENQUEUE_MUTEX(mutex, queue, link) \ + do { \ + struct OSMutex* __prev = (queue)->tail; \ + if (__prev == NULL) { \ + (queue)->head = (mutex); \ + } else { \ + __prev->link.next = (mutex); \ + } \ + (mutex)->link.prev = __prev; \ + (mutex)->link.next = 0; \ + (queue)->tail = (mutex); \ + } while (0); + +#define DEQUEUE_MUTEX(mutex, queue, link) \ + do { \ + struct OSMutex* __next = (mutex)->link.next; \ + struct OSMutex* __prev = (mutex)->link.prev; \ + if (__next == NULL) { \ + (queue)->tail = __prev; \ + } else { \ + __next->link.prev = __prev; \ + } \ + if (__prev == NULL) { \ + (queue)->head = __next; \ + } else { \ + __prev->link.next = __next; \ + } \ + } while (0); + +#define DEQUEUE_HEAD(mutex, queue, link) \ + do { \ + struct OSMutex* __next = mutex->link.next; \ + if (__next == NULL) { \ + (queue)->tail = 0; \ + } else { \ + __next->link.prev = 0; \ + } \ + (queue)->head = __next; \ + } while (0); + +void OSInitMutex(struct OSMutex* mutex) +{ + OSInitThreadQueue(&mutex->queue); + mutex->thread = 0; + mutex->count = 0; +} + +void OSLockMutex(struct OSMutex* mutex) +{ + int enabled = OSDisableInterrupts(); + struct OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(0x8C, currentThread, + "OSLockMutex(): current thread does not exist."); + ASSERTMSGLINE(0x8E, currentThread->state == 2, + "OSLockMutex(): current thread is not running."); + + while (1) { + struct OSThread* ownerThread = mutex->thread; + if (ownerThread == 0) { + mutex->thread = currentThread; + mutex->count++; + ENQUEUE_MUTEX(mutex, ¤tThread->queueMutex, link); + break; + } else if (ownerThread == currentThread) { + mutex->count++; + break; + } else { + currentThread->mutex = mutex; + __OSPromoteThread(mutex->thread, currentThread->priority); + OSSleepThread(&mutex->queue); + currentThread->mutex = NULL; + } + } + OSRestoreInterrupts(enabled); +} + +void OSUnlockMutex(struct OSMutex* mutex) +{ + int enabled = OSDisableInterrupts(); + struct OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(0xBD, currentThread, + "OSUnlockMutex(): current thread does not exist."); + ASSERTMSGLINE(0xBF, currentThread->state == 2, + "OSUnlockMutex(): current thread is not running."); + ASSERTMSG2LINE( + 0xC2, mutex->thread == currentThread, + "OSUnlockMutex(): current thread %p is not the owner of mutex %p.", + currentThread, mutex); + + if (mutex->thread == currentThread) { + if (!--mutex->count) { + DEQUEUE_MUTEX(mutex, ¤tThread->queueMutex, link); + mutex->thread = 0; + + if (currentThread->priority < currentThread->base) { + currentThread->priority + = __OSGetEffectivePriority(currentThread); + } + OSWakeupThread(&mutex->queue); + } + } + OSRestoreInterrupts(enabled); +} + +void __OSUnlockAllMutex(struct OSThread* thread) +{ + struct OSMutex* mutex; + + while (thread->queueMutex.head) { + mutex = thread->queueMutex.head; + DEQUEUE_HEAD(mutex, &thread->queueMutex, link); + ASSERTLINE(0xE5, mutex->thread == thread); + mutex->count = 0; + mutex->thread = 0; + OSWakeupThread(&mutex->queue); + } +} + +int OSTryLockMutex(struct OSMutex* mutex) +{ + int enabled = OSDisableInterrupts(); + struct OSThread* currentThread = OSGetCurrentThread(); + int locked; + + ASSERTMSGLINE(0xFF, currentThread, + "OSTryLockMutex(): current thread does not exist."); + ASSERTMSGLINE(0x101, currentThread->state == 2, + "OSTryLockMutex(): current thread is not running."); + + if (!mutex->thread) { + mutex->thread = currentThread; + mutex->count++; + ENQUEUE_MUTEX(mutex, ¤tThread->queueMutex, link); + locked = 1; + } else if (mutex->thread == currentThread) { + mutex->count++; + locked = 1; + } else { + locked = 0; + } + OSRestoreInterrupts(enabled); + return locked; +} + +void OSInitCond(struct OSCond* cond) { OSInitThreadQueue(&cond->queue); } + +void OSWaitCond(struct OSCond* cond, struct OSMutex* mutex) +{ + int enabled = OSDisableInterrupts(); + struct OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(0x139, currentThread, + "OSWaitCond(): current thread does not exist."); + ASSERTMSGLINE(0x13B, currentThread->state == 2, + "OSWaitCond(): current thread is not running."); + ASSERTMSG2LINE( + 0x13E, mutex->thread == currentThread, + "OSWaitCond(): current thread %p is not the owner of mutex %p.", + currentThread, mutex); + + if (mutex->thread == currentThread) { + long count = mutex->count; + mutex->count = 0; + DEQUEUE_MUTEX(mutex, ¤tThread->queueMutex, link); + mutex->thread = 0; + if (currentThread->priority < currentThread->base) { + currentThread->priority = __OSGetEffectivePriority(currentThread); + } + OSDisableScheduler(); + OSWakeupThread(&mutex->queue); + OSEnableScheduler(); + OSSleepThread(&cond->queue); + OSLockMutex(mutex); + mutex->count = count; + } + OSRestoreInterrupts(enabled); +} + +void OSSignalCond(struct OSCond* cond) { OSWakeupThread(&cond->queue); } + +int __OSCheckMutex(struct OSMutex * mutex) { + struct OSThread * thread; + struct OSThreadQueue * queue; + long priority; + + priority = 0; + queue = &mutex->queue; + + if (queue->head != NULL && queue->head->link.prev != NULL) { + return 0; + } + if (queue->tail != NULL && queue->tail->link.next != NULL) { + return 0; + } + thread = queue->head; + while(thread) { + if (thread->link.next != NULL && (thread != thread->link.next->link.prev)) { + return 0; + } + if (thread->link.prev != NULL && (thread != thread->link.prev->link.next)) { + return 0; + } + if (thread->state != 4) { + return 0; + } + if (thread->priority < priority) { + return 0; + } + priority = thread->priority; + thread = thread->link.next; + } + if (mutex->thread) { + if (mutex->count <= 0) { + return 0; + } + } else if (mutex->count != 0) { + return 0; + } + return 1; +} + +int __OSCheckDeadLock(struct OSThread * thread) { + struct OSMutex * mutex = thread->mutex; + + while(mutex && mutex->thread) { + if (mutex->thread == thread) { + return 1; + } + mutex = mutex->thread->mutex; + } + return 0; +} + +int __OSCheckMutexes(struct OSThread * thread) { + struct OSMutex * mutex = thread->queueMutex.head; + + while(mutex) { + if (mutex->thread != thread) { + return 0; + } + if (__OSCheckMutex(mutex) == 0) { + return 0; + } + mutex = mutex->link.next; + } + return 1; +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSReboot.c b/src/static/GAEJ01_01/dolphin/os/OSReboot.c new file mode 100644 index 00000000..d17611ba --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSReboot.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include "../src/static/GAEJ01_01/dolphin/dvd/__dvd.h" +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +static void* SaveStart = NULL; +static void* SaveEnd = NULL; +static BOOL Prepared; + +extern u32 OS_RESET_CODE AT_ADDRESS(0x800030F0); +// unknown function, set to true by __OSReboot +extern u8 OS_REBOOT_BOOL AT_ADDRESS(0x800030E2); +extern BOOL __OSIsGcam; + +#define OS_BOOTROM_ADDR ((void*)0x81300000) + +typedef struct _ApploaderHeader { + /* 0x00 */ char date[16]; + /* 0x10 */ u32 entry; + /* 0x14 */ u32 size; + /* 0x18 */ u32 rebootSize; + /* 0x1C */ u32 reserved2; +} ApploaderHeader; // Size: 0x20 + +static ApploaderHeader Header __attribute__((aligned(32))); + +static BOOL IsStreamEnabled(void) +{ + if (DVDGetCurrentDiskID()->streaming) { + return TRUE; + } + return FALSE; +} + +static asm void Run(register void* addr) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + + sync + isync + mtlr addr + blr +#endif // clang-format on +} + +static void ReadApploader(OSTime time1) +{ + if (!DVDCheckDisk() || OSGetTime() - time1 > OS_TIMER_CLOCK) { + __OSDoHotReset(0); + } +} + +static void Callback(s32 result, struct DVDCommandBlock* block) +{ + Prepared = TRUE; +} + +void __OSReboot(u32 resetCode, u32 bootDol) +{ + OSContext exceptionContext; + OSTime time1; + DVDCommandBlock dvdCmd; + DVDCommandBlock dvdCmd2; + DVDCommandBlock dvdCmd3; + u32 numBytes; + u32 offset; + + OSDisableInterrupts(); + OS_RESET_CODE = resetCode; + OS_REBOOT_BOOL = TRUE; + BOOT_REGION_START = SaveStart; + BOOT_REGION_END = SaveEnd; + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + DVDInit(); + DVDSetAutoInvalidation(TRUE); + DVDResume(); + + Prepared = FALSE; + __DVDPrepareResetAsync(Callback); + + __OSMaskInterrupts(0xffffffe0); + __OSUnmaskInterrupts(0x400); + OSEnableInterrupts(); + + time1 = OSGetTime(); + while (Prepared != TRUE) { + ReadApploader(time1); + } + + if (!__OSIsGcam) { + if (IsStreamEnabled()) { + AISetStreamVolLeft(0); + AISetStreamVolRight(0); + DVDCancelStreamAsync(&dvdCmd, NULL); + time1 = OSGetTime(); + while (DVDGetCommandBlockStatus(&dvdCmd)) { + ReadApploader(time1); + } + + AISetStreamPlayState(0); + } + } + + DVDReadAbsAsyncPrio(&dvdCmd2, Header.date, 32, 0x2440, NULL, 0); + + time1 = OSGetTime(); + while (DVDGetCommandBlockStatus(&dvdCmd2)) { + ReadApploader(time1); + } + + offset = Header.size + 0x20; + numBytes = OSRoundUp32B(Header.rebootSize); + DVDReadAbsAsyncPrio(&dvdCmd3, OS_BOOTROM_ADDR, numBytes, offset + 0x2440, NULL, 0); + + time1 = OSGetTime(); + while (DVDGetCommandBlockStatus(&dvdCmd3)) { + ReadApploader(time1); + } + + ICInvalidateRange(OS_BOOTROM_ADDR, numBytes); + OSDisableInterrupts(); + ICFlashInvalidate(); + Run(OS_BOOTROM_ADDR); +} + +void OSSetSaveRegion(void* start, void* end) +{ + SaveStart = start; + SaveEnd = end; +} + +void OSGetSaveRegion(void** start, void** end) +{ + *start = SaveStart; + *end = SaveEnd; +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSReset.c b/src/static/GAEJ01_01/dolphin/os/OSReset.c new file mode 100644 index 00000000..4873cb4e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSReset.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +// These macros are copied from OSThread.c. Or ARE they the same +// macros? They dont seem to be in the SDK headers. +#define ENQUEUE_INFO(info, queue) \ + do { \ + struct OSResetFunctionInfo* __prev = (queue)->tail; \ + if (__prev == 0) { \ + (queue)->head = (info); \ + } else { \ + __prev->next = (info); \ + } \ + (info)->prev = __prev; \ + (info)->next = 0; \ + (queue)->tail = (info); \ + } while (0); + +#define DEQUEUE_INFO(info, queue) \ + do { \ + struct OSResetFunctionInfo* __next = (info)->next; \ + struct OSResetFunctionInfo* __prev = (info)->prev; \ + if (__next == 0) { \ + (queue)->tail = __prev; \ + } else { \ + __next->prev = __prev; \ + } \ + if (__prev == 0) { \ + (queue)->head = __next; \ + } else { \ + __prev->next = __next; \ + } \ + } while (0); + +#define ENQUEUE_INFO_PRIO(info, queue) \ + do { \ + struct OSResetFunctionInfo* __prev; \ + struct OSResetFunctionInfo* __next; \ + for (__next = (queue)->head; \ + __next && (__next->priority <= (info)->priority); \ + __next = __next->next) \ + ; \ + \ + if (__next == 0) { \ + ENQUEUE_INFO(info, queue); \ + } else { \ + (info)->next = __next; \ + __prev = __next->prev; \ + __next->prev = (info); \ + (info)->prev = __prev; \ + if (__prev == 0) { \ + (queue)->head = (info); \ + } else { \ + __prev->next = (info); \ + } \ + } \ + } while (0); + +static struct OSResetFunctionQueue ResetFunctionQueue; +static u32 bootThisDol; + +static asm void Reset(unsigned long resetCode); + +void OSRegisterResetFunction(struct OSResetFunctionInfo* info) +{ + ENQUEUE_INFO_PRIO(info, &ResetFunctionQueue); +} + +void OSUnregisterResetFunction(struct OSResetFunctionInfo* info) +{ + DEQUEUE_INFO(info, &ResetFunctionQueue); +} + +static asm void Reset(unsigned long resetCode) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + b L_000001BC +L_000001A0: + mfspr r8, HID0 + ori r8, r8, 0x8 + mtspr HID0, r8 + isync + sync + nop + b L_000001C0 +L_000001BC: + b L_000001DC +L_000001C0: + mftb r5, 268 +L_000001C4: + mftb r6, 268 + subf r7, r5, r6 + cmplwi r7, 0x1124 + blt L_000001C4 + nop + b L_000001E0 +L_000001DC: + b L_000001FC +L_000001E0: + lis r8, 0xcc00 + ori r8, r8, 0x3000 + li r4, 0x3 + stw r4, 0x24(r8) + stw r3, 0x24(r8) + nop + b L_00000200 +L_000001FC: + b L_00000208 +L_00000200: + nop + b L_00000200 +L_00000208: + b L_000001A0 +#endif // clang-format on +} + +void __OSDoHotReset(s32 arg0) +{ + OSDisableInterrupts(); + __VIRegs[1] = 0; + ICFlashInvalidate(); + Reset(arg0 * 8); +} + +inline BOOL __OSCallResetFunctions(BOOL final) +{ + OSResetFunctionInfo* iter; + BOOL retCode = FALSE; + + for (iter = ResetFunctionQueue.head; (iter != NULL && retCode == FALSE); iter = iter->next) { + retCode |= !iter->func(final); + } + + retCode |= !__OSSyncSram(); + + if (retCode) { + return FALSE; + } + return TRUE; +} + +inline static void KillThreads(void) +{ + OSThread* thread; + OSThread* next; + + for (thread = __OSActiveThreadQueue.head; thread; thread = next) { + next = thread->linkActive.next; + switch (thread->state) { + case 1: + case 4: + OSCancelThread(thread); + break; + } + } +} + +void OSResetSystem(int reset, unsigned long resetCode, int forceMenu) +{ + BOOL rc; + BOOL disableRecalibration; + u32 unk[3]; + + OSDisableScheduler(); + __OSStopAudioSystem(); + + if (reset == OS_RESET_SHUTDOWN || (reset == OS_RESET_RESTART && bootThisDol != 0)) { + disableRecalibration = __PADDisableRecalibration(TRUE); + } + + while (!__OSCallResetFunctions(FALSE)) { + ; + } + + if (reset == OS_RESET_HOTRESET && forceMenu) { + OSSram* sram; + + sram = __OSLockSram(); + sram->flags |= 0x40; + __OSUnlockSram(TRUE); + + while (!__OSSyncSram()) { + ; + } + resetCode = 0; + } + + OSDisableInterrupts(); + __OSCallResetFunctions(TRUE); + LCDisable(); + if (reset == OS_RESET_HOTRESET) { + __OSDoHotReset(resetCode); + } else if (reset == OS_RESET_RESTART) { + if ((*(u32*)OSPhysicalToCached(0x30EC) = bootThisDol) != 0) { + __PADDisableRecalibration(disableRecalibration); + } + KillThreads(); + OSEnableScheduler(); + __OSReboot(resetCode, forceMenu); + } + + KillThreads(); + memset(OSPhysicalToCached(0x40), 0, 0xCC - 0x40); + memset(OSPhysicalToCached(0xD4), 0, 0xE8 - 0xD4); + memset(OSPhysicalToCached(0xF4), 0, 0xF8 - 0xF4); + memset(OSPhysicalToCached(0x3000), 0, 0xC0); + memset(OSPhysicalToCached(0x30C8), 0, 0xD4 - 0xC8); + memset(OSPhysicalToCached(0x30E2), 0, 1); + + __PADDisableRecalibration(disableRecalibration); +} + +u32 OSGetResetCode(void) +{ + if (*(u8*)OSPhysicalToCached(0x30E2) != 0) { + return *(u32*)OSPhysicalToCached(0x30F0) | 0x80000000; + } + + return ((__PIRegs[9] & ~7) >> 3); +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSResetSW.c b/src/static/GAEJ01_01/dolphin/os/OSResetSW.c new file mode 100644 index 00000000..1792c626 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSResetSW.c @@ -0,0 +1,92 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +u8 GameChoice AT_ADDRESS(OS_BASE_CACHED | 0x30E3); + +static OSResetCallback ResetCallback; + +static BOOL Down; + +static BOOL LastState; + +static OSTime HoldUp; +static OSTime HoldDown; + +void __OSResetSWInterruptHandler(__OSInterrupt exception, + struct OSContext* context) +{ + OSResetCallback callback; + + HoldDown = __OSGetSystemTime(); + while (__OSGetSystemTime() - HoldDown < OSMicrosecondsToTicks(100) + && !(__PIRegs[0] & 0x00010000)) { + ; + } + if (!(__PIRegs[0] & 0x00010000)) { + LastState = Down = TRUE; + __OSMaskInterrupts(OS_INTERRUPTMASK_PI_RSW); + if (ResetCallback) { + callback = ResetCallback; + ResetCallback = NULL; + callback(); + } + } + __PIRegs[0] = 2; +} + +BOOL OSGetResetButtonState(void) +{ + BOOL enabled = OSDisableInterrupts(); + BOOL state; + OSTime now = __OSGetSystemTime(); + u32 reg = __PIRegs[0]; + + if (!(reg & 0x00010000)) { + if (!Down) { + Down = TRUE; + state = HoldUp ? TRUE : FALSE; + HoldDown = now; + } else { + state = HoldUp || (OSMicrosecondsToTicks(100) < now - HoldDown) + ? TRUE + : FALSE; + } + } else if (Down) { + Down = FALSE; + state = LastState; + if (state) { + HoldUp = now; + } else { + HoldUp = 0; + } + } else if (HoldUp && (now - HoldUp < OSMillisecondsToTicks(40))) { + state = TRUE; + } else { + state = FALSE; + HoldUp = 0; + } + + LastState = state; + + if (GameChoice & 0x1F) { + OSTime fire = (GameChoice & 0x1F) * 60; + fire = __OSStartTime + OSSecondsToTicks(fire); + if (fire < now) { + now -= fire; + now = OSTicksToSeconds(now) / 2; + if ((now & 1) == 0) { + state = TRUE; + } else { + state = FALSE; + } + } + } + + OSRestoreInterrupts(enabled); + return state; +} + +BOOL OSGetResetSwitchState(void) { return OSGetResetButtonState(); } diff --git a/src/static/GAEJ01_01/dolphin/os/OSRtc.c b/src/static/GAEJ01_01/dolphin/os/OSRtc.c new file mode 100644 index 00000000..2bf63336 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSRtc.c @@ -0,0 +1,278 @@ +#include "dolphin/os/OSRtc.h" + +#include "dolphin/os/OSCache.h" +#include "dolphin/os.h" +#include "types.h" + +static SramControlBlock Scb ATTRIBUTE_ALIGN(32); + +u16 OSGetGbsMode(void); +void OSSetGbsMode(u16 mode); + +static inline BOOL ReadSram(void* buffer) { + u32 cmd; + BOOL err; + + DCInvalidateRange(buffer, RTC_SRAM_SIZE); + + if (!EXILock(RTC_CHAN, RTC_DEVICE, NULL)) { + return FALSE; + } + + if (!EXISelect(RTC_CHAN, RTC_DEVICE, RTC_FREQUENCY)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = RTC_CMD_READ | RTC_SRAM_ADDR; + err = !EXIImm(RTC_CHAN, &cmd, sizeof(u32), EXI_WRITE, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDma(RTC_CHAN, buffer, RTC_SRAM_SIZE, EXI_READ, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +void WriteSramCallback(s32 chan, OSContext* ctx) { + DOLPHIN_ASSERTLINE(!Scb.locked, 258); + Scb.sync = WriteSram(Scb.sram + Scb.offset, Scb.offset, RTC_SRAM_SIZE - Scb.offset); + DOLPHIN_ASSERTLINE(Scb.sync, 264); + + if (Scb.sync) { + Scb.offset = RTC_SRAM_SIZE; + } +} + +static BOOL WriteSram(void* buffer, u32 offset, u32 size) { + u32 cmd; + BOOL err; + + if (EXILock(RTC_CHAN, 1, WriteSramCallback) == FALSE) { + return FALSE; + } + + if (EXISelect(RTC_CHAN, RTC_DEVICE, RTC_FREQUENCY) == FALSE) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + offset *= RTC_SRAM_SIZE; + cmd = offset + RTC_SRAM_ADDR | RTC_CMD_WRITE; + err = !EXIImm(RTC_CHAN, &cmd, sizeof(u32), EXI_WRITE, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIImmEx(RTC_CHAN, buffer, size, EXI_WRITE); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + return !err; +} + +extern void __OSInitSram() { + Scb.enabled = FALSE; + Scb.locked = FALSE; + Scb.sync = ReadSram(Scb.sram); + DOLPHIN_ASSERTLINE(Scb.sync, 318); + Scb.offset = RTC_SRAM_SIZE; + OSSetGbsMode(OSGetGbsMode()); +} + +static inline void* LockSram(u32 offset) { + BOOL enabled = OSDisableInterrupts(); + + DOLPHIN_ASSERTLINE(Scb.locked, 341); + if (Scb.locked != FALSE) { + OSRestoreInterrupts(enabled); + return NULL; + } + + Scb.enabled = enabled; + Scb.locked = TRUE; + return Scb.sram + offset; +} + +extern OSSram* __OSLockSram() { + return (OSSram*)LockSram(0); + //return sram; +} + +extern OSSramEx* __OSLockSramEx() { + return (OSSramEx*)LockSram(sizeof(OSSram)); + //return sramEx; +} + +static BOOL UnlockSram(BOOL commit, u32 offset) { + u16* chksum_p; + + DOLPHIN_ASSERTLINE(Scb.locked, 375); + if (commit) { + if (offset == 0) { + OSSram* sram = (OSSram*)Scb.sram; + if ((sram->flags & 3u) > 2u) { + sram->flags &= (~3u); + } + + sram->checkSum = sram->checkSumInv = 0; + for (chksum_p = (u16*)&sram->counterBias; chksum_p < (u16*)(Scb.sram + sizeof(OSSram)); chksum_p++) { + sram->checkSum += *chksum_p; + sram->checkSumInv += ~*chksum_p; + } + } + + if (offset < Scb.offset) { + Scb.offset = offset; + } + + if (Scb.offset <= sizeof(OSSram)) { + OSSramEx* sramEx = (OSSramEx*)(Scb.sram + sizeof(OSSram)); + if ((u32)(sramEx->gbs & 0x7C00) == 0x5000 || (u32)(sramEx->gbs & 0xC0) == 0xC0) { + sramEx->gbs = 0; + } + } + + Scb.sync = WriteSram(Scb.sram + Scb.offset, Scb.offset, RTC_SRAM_SIZE - Scb.offset); + if (Scb.sync) { + Scb.offset = RTC_SRAM_SIZE; + } + } + + Scb.locked = FALSE; + OSRestoreInterrupts(Scb.enabled); + return Scb.sync; +} + +extern void __OSUnlockSram(BOOL commit) { + UnlockSram(commit, 0); +} + +extern void __OSUnlockSramEx(BOOL commit) { + UnlockSram(commit, sizeof(OSSram)); +} + +extern BOOL __OSSyncSram() { + return Scb.sync; +} + +extern u32 OSGetSoundMode() { + OSSram* sram = __OSLockSram(); + u32 mode = GET_SOUNDMODE(sram->flags) ? OS_SOUND_MODE_STEREO : OS_SOUND_MODE_MONO; + __OSUnlockSram(FALSE); + return mode; +} + +extern void OSSetSoundMode(u32 mode) { + u32 flag; + OSSram* sram; + u32 m; + + DOLPHIN_ASSERTLINE(mode == OS_SOUND_MODE_MONO || mode == OS_SOUND_MODE_STEREO, 617); + flag = SET_SOUNDMODE(mode); + sram = (OSSram*)__OSLockSram(); + if (flag == GET_SOUNDMODE(sram->flags)) { + __OSUnlockSram(FALSE); + } + else { + sram->flags = CLR_SOUNDMODE(sram->flags); + sram->flags |= flag; + __OSUnlockSram(TRUE); + } +} + +extern u32 OSGetProgressiveMode() { + OSSram* sram = __OSLockSram(); + u32 mode = GET_PROGMODE(sram->flags) >> 7; + __OSUnlockSram(FALSE); + return mode; +} + +extern void OSSetProgressiveMode(u32 on) { + u32 flag; + OSSram* sram; + u32 m; + + DOLPHIN_ASSERTLINE(on == OS_PROGRESSIVE_MODE_OFF || on == OS_PROGRESSIVE_MODE_ON, 670); + flag = SET_PROGMODE(on); + sram = __OSLockSram(); + + if (flag == GET_PROGMODE(sram->flags)) { + __OSUnlockSram(FALSE); + } + else { + sram->flags = CLR_PROGMODE(sram->flags); + sram->flags |= flag; + __OSUnlockSram(TRUE); + } +} + +u8 OSGetLanguage(void) { + OSSram* sram = __OSLockSram(); + u8 language = sram->language; + __OSUnlockSram(FALSE); + return language; +} + +extern void __OSSetBootMode(u8 mode) { + OSSram* sram; + u32 m; + + mode &= OS_BOOT_MODE_RETAIL; + sram = __OSLockSram(); + if (mode == (u32)GET_BOOTMODE(sram->ntd)) { + __OSUnlockSram(FALSE); + } + else { + sram->ntd = CLR_BOOTMODE(sram->ntd); + sram->ntd |= mode; + __OSUnlockSram(TRUE); + } +} + +u32 OSGetEuRgb60Mode(void) { + OSSram* sram = __OSLockSram(); + u32 mode = (sram->ntd & 0x40) >> 6; + __OSUnlockSram(FALSE); + return mode; +} + +extern u16 OSGetWirelessID(s32 chan) { + OSSramEx* sramEx = __OSLockSramEx(); + u16 id = sramEx->wirelessPadID[chan]; + __OSUnlockSramEx(FALSE); + return id; +} + +extern void OSSetWirelessID(s32 chan, u16 id) { + OSSramEx* sramEx = __OSLockSramEx(); + if (sramEx->wirelessPadID[chan] != id) { + sramEx->wirelessPadID[chan] = id; + __OSUnlockSramEx(TRUE); + } + else { + __OSUnlockSramEx(FALSE); + } +} + +u16 OSGetGbsMode(void) { + OSSramEx* sramEx = __OSLockSramEx(); + u16 mode = sramEx->gbs; + __OSUnlockSramEx(FALSE); + return mode; +} + +void OSSetGbsMode(u16 mode) { + u32 padding[1]; + OSSramEx* sramEx; + + if ((u32)(mode & 0x7C00) == 0x5000 || (u32)(mode & 0xC0) == 0xC0) { + mode = 0; + } + + sramEx = __OSLockSramEx(); + if (mode == sramEx->gbs) { + __OSUnlockSramEx(FALSE); + } + else { + sramEx->gbs = mode; + __OSUnlockSramEx(TRUE); + } +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSSemaphore.c b/src/static/GAEJ01_01/dolphin/os/OSSemaphore.c new file mode 100644 index 00000000..c58e20dd --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSSemaphore.c @@ -0,0 +1,56 @@ +#include +#include + +void OSInitSemaphore(OSSemaphore* sem, s32 count) { + BOOL enabled = OSDisableInterrupts(); + + OSInitThreadQueue(&sem->queue); + sem->count = count; + OSRestoreInterrupts(enabled); +} + +s32 OSWaitSemaphore(OSSemaphore* sem) { + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + + while((sem->count = (count = sem->count)) <= 0) { + OSSleepThread(&sem->queue); + } + + sem->count--; + OSRestoreInterrupts(enabled); + return count; +} + +s32 OSTryWaitSemaphore(OSSemaphore* sem) { + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + count = sem->count; + if (sem->count > 0) { + sem->count = sem->count - 1; + } + + OSRestoreInterrupts(enabled); + return count; +} + +s32 OSSignalSemaphore(OSSemaphore* sem) { + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + count = sem->count; + sem->count++; + + OSWakeupThread(&sem->queue); + OSRestoreInterrupts(enabled); + return count; +} + +s32 OSGetSemaphoreCount(OSSemaphore* sem) { + return sem->count; +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSStopwatch.c b/src/static/GAEJ01_01/dolphin/os/OSStopwatch.c new file mode 100644 index 00000000..39973077 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSStopwatch.c @@ -0,0 +1,48 @@ +#include +#include + +void OSInitStopwatch(struct OSStopwatch* sw, char* name) +{ + sw->name = name; + sw->total = 0; + sw->hits = 0; + sw->min = 0x00000000FFFFFFFF; + sw->max = 0; +} + +void OSStartStopwatch(struct OSStopwatch* sw) +{ + sw->running = 1; + sw->last = OSGetTime(); +} + +void OSStopStopwatch(struct OSStopwatch* sw) +{ + long long interval; + + if (sw->running != 0) { + interval = OSGetTime() - sw->last; + sw->total += interval; + sw->running = 0; + sw->hits++; + if (sw->max < interval) { + sw->max = interval; + } + if (interval < sw->min) { + sw->min = interval; + } + } +} + +long long OSCheckStopwatch(struct OSStopwatch* sw) +{ + long long currTotal; + + currTotal = sw->total; + if (sw->running != 0) { + currTotal += OSGetTime() - sw->last; + } + return currTotal; +} + +void OSResetStopwatch(struct OSStopwatch* sw) { OSInitStopwatch(sw, sw->name); } diff --git a/src/static/GAEJ01_01/dolphin/os/OSSync.c b/src/static/GAEJ01_01/dolphin/os/OSSync.c new file mode 100644 index 00000000..80ec3320 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSSync.c @@ -0,0 +1,35 @@ +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +void __OSSystemCallVectorStart(); +void __OSSystemCallVectorEnd(); + +static asm void SystemCallVector(void) +{ +#ifdef __MWERKS__ // clang-format off +entry __OSSystemCallVectorStart + nofralloc + mfspr r9, HID0 + ori r10, r9, 0x8 + mtspr HID0, r10 + isync + sync + mtspr HID0, r9 + rfi +entry __OSSystemCallVectorEnd + nop +#endif // clang-format on +} + +void __OSInitSystemCall(void) +{ + void* addr = (void*)OSPhysicalToCached(0xC00); + + memcpy(addr, __OSSystemCallVectorStart, + (u32)&__OSSystemCallVectorEnd - (u32)&__OSSystemCallVectorStart); + DCFlushRangeNoSync(addr, 0x100); + __sync(); + ICInvalidateRange(addr, 0x100); +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSThread.c b/src/static/GAEJ01_01/dolphin/os/OSThread.c new file mode 100644 index 00000000..d57ec39a --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSThread.c @@ -0,0 +1,843 @@ +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +#define IsSuspended(suspend) (suspend > 0) + +#define ENQUEUE_THREAD(thread, queue, link) \ + do { \ + OSThread* __prev = (queue)->tail; \ + if (__prev == NULL) { \ + (queue)->head = (thread); \ + } else { \ + __prev->link.next = (thread); \ + } \ + (thread)->link.prev = __prev; \ + (thread)->link.next = 0; \ + (queue)->tail = (thread); \ + } while (0); + +#define DEQUEUE_THREAD(thread, queue, link) \ + do { \ + OSThread* __next = (thread)->link.next; \ + OSThread* __prev = (thread)->link.prev; \ + if (__next == NULL) { \ + (queue)->tail = __prev; \ + } else { \ + __next->link.prev = __prev; \ + } \ + if (__prev == NULL) { \ + (queue)->head = __next; \ + } else { \ + __prev->link.next = __next; \ + } \ + } while (0); + +#define ENQUEUE_THREAD_PRIO(thread, queue, link) \ + do { \ + OSThread* __prev; \ + OSThread* __next; \ + for (__next = (queue)->head; \ + __next && (__next->priority <= (thread)->priority); \ + __next = __next->link.next) \ + ; \ + \ + if (__next == NULL) { \ + ENQUEUE_THREAD(thread, queue, link); \ + } else { \ + (thread)->link.next = __next; \ + __prev = __next->link.prev; \ + __next->link.prev = (thread); \ + (thread)->link.prev = __prev; \ + if (__prev == NULL) { \ + (queue)->head = (thread); \ + } else { \ + __prev->link.next = (thread); \ + } \ + } \ + } while (0); + +#define DEQUEUE_HEAD(thread, queue, link) \ + do { \ + OSThread* __next = thread->link.next; \ + if (__next == NULL) { \ + (queue)->tail = 0; \ + } else { \ + __next->link.prev = 0; \ + } \ + (queue)->head = __next; \ + } while (0); + +// which header should these go in? +extern unsigned char _stack_end[]; +extern char _stack_addr[]; + +// .bss +static OSThreadQueue RunQueue[32]; +static OSThread IdleThread; +static OSThread DefaultThread; +static struct OSContext IdleContext; +static volatile unsigned long RunQueueBits; +static volatile int RunQueueHint; +static long Reschedule; + +#define ALIGN4(val) (((val) + 0x3) & ~0x3) +#define ALIGN8(val) (((val) + 0x7) & ~0x7) + +// functions +static void OSInitMutexQueue(struct OSMutexQueue* queue); +static void __OSSwitchThread(OSThread* nextThread); +static int __OSIsThreadActive(OSThread* thread); +static void SetRun(OSThread* thread); +static void UnsetRun(OSThread* thread); +static OSThread* SetEffectivePriority(OSThread* thread, long priority); +static void UpdatePriority(OSThread* thread); +static OSThread* SelectThread(int yield); + +typedef void (*OSSwitchThreadCallback)(OSThread* from, OSThread* to); + +static void DefaultSwitchThreadCallback(OSThread* from, OSThread* to); +static OSSwitchThreadCallback SwitchThreadCallback = DefaultSwitchThreadCallback; + +void OSClearStack(u8 val); + +static inline void InitMutexQueue(struct OSMutexQueue* queue) +{ + queue->head = queue->tail = NULL; +} + +static inline void SetCurrentThread(OSThread* thread) +{ + SwitchThreadCallback(__gCurrentThread, thread); + __gCurrentThread = thread; +} + +static void DefaultSwitchThreadCallback(OSThread* from, OSThread* to) { } + +void __OSThreadInit() +{ + OSThread* thread = &DefaultThread; + int prio; + + thread->state = OS_THREAD_STATE_RUNNING; + thread->attr = OS_THREAD_ATTR_DETACH; + thread->priority = thread->base = 16; + thread->suspend = 0; + thread->val = (void*)-1; + thread->mutex = NULL; + OSInitThreadQueue(&thread->queueJoin); + InitMutexQueue(&thread->queueMutex); + + __gUnkThread1 = thread; + + OSClearContext(&thread->context); + OSSetCurrentContext(&thread->context); + thread->stackBase = (void*)_stack_addr; + thread->stackEnd = (void*)_stack_end; + *(thread->stackEnd) = OS_THREAD_STACK_MAGIC; + + SetCurrentThread(thread); + OSClearStack(0); + + RunQueueBits = 0; + RunQueueHint = FALSE; + for (prio = OS_PRIORITY_MIN; prio <= OS_PRIORITY_MAX; ++prio) { + OSInitThreadQueue(&RunQueue[prio]); + } + + OSInitThreadQueue(&__OSActiveThreadQueue); + ENQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + OSClearContext(&IdleContext); + Reschedule = 0; +} + +void OSInitThreadQueue(OSThreadQueue* queue) { queue->head = queue->tail = 0; } + +OSThread* OSGetCurrentThread() { return __gCurrentThread; } + +static void __OSSwitchThread(OSThread* nextThread) +{ + SwitchThreadCallback(__gCurrentThread, nextThread); + __gCurrentThread = nextThread; + OSSetCurrentContext(&nextThread->context); + OSLoadContext(&nextThread->context); +} + +int OSIsThreadTerminated(OSThread* thread) +{ + return (thread->state == 8 || thread->state == 0) ? 1 : 0; +} + +static int __OSIsThreadActive(OSThread* thread) +{ + OSThread* active; + + if (thread->state == 0) { + return 0; + } + + for (active = __OSActiveThreadQueue.head; active; + active = active->linkActive.next) { + if (thread == active) { + return 1; + } + } + return 0; +} + +s32 OSDisableScheduler(void) +{ + register int enabled; + long count; + + enabled = OSDisableInterrupts(); + count = Reschedule; + Reschedule = count + 1; + OSRestoreInterrupts(enabled); + return count; +} + +s32 OSEnableScheduler(void) +{ + register int enabled; + long count; + + enabled = OSDisableInterrupts(); + count = Reschedule; + Reschedule = count - 1; + OSRestoreInterrupts(enabled); + return count; +} + +static void SetRun(OSThread* thread) +{ + ASSERTLINE(469, !IsSuspended(thread->suspend)); + ASSERTLINE(470, thread->state == OS_THREAD_STATE_READY); + + ASSERTLINE(472, OS_PRIORITY_MIN <= thread->priority + && thread->priority <= OS_PRIORITY_MAX); + + thread->queue = &RunQueue[thread->priority]; + + ENQUEUE_THREAD(thread, thread->queue, link); + + RunQueueBits |= 1 << (0x1F - thread->priority); + RunQueueHint = 1; +} + +static void UnsetRun(OSThread* thread) +{ + OSThreadQueue* queue; + + ASSERTLINE(0x1ED, thread->state == OS_THREAD_STATE_READY); + + ASSERTLINE(0x1EF, OS_PRIORITY_MIN <= thread->priority + && thread->priority <= OS_PRIORITY_MAX); + ASSERTLINE(0x1F0, thread->queue == &RunQueue[thread->priority]); + + queue = thread->queue; + + DEQUEUE_THREAD(thread, queue, link); + + if (!queue->head) { + RunQueueBits &= ~(1 << (0x1F - thread->priority)); + } + thread->queue = NULL; +} + +long __OSGetEffectivePriority(OSThread* thread) +{ + long priority = thread->base; + struct OSMutex* mutex; + + for (mutex = thread->queueMutex.head; mutex; mutex = mutex->link.next) { + OSThread* blocked = mutex->queue.head; + if (blocked && blocked->priority < priority) { + priority = blocked->priority; + } + } + return priority; +} + +static OSThread* SetEffectivePriority(OSThread* thread, long priority) +{ + ASSERTLINE(547, !IsSuspended(thread->suspend)); + + switch (thread->state) { + case 1: + UnsetRun(thread); + thread->priority = priority; + SetRun(thread); + break; + case 4: + DEQUEUE_THREAD(thread, thread->queue, link); + thread->priority = priority; + + ENQUEUE_THREAD_PRIO(thread, thread->queue, link); + + if (thread->mutex) { + ASSERTLINE(0x232, thread->mutex->thread); + return thread->mutex->thread; + } + break; + case 2: + RunQueueHint = 1; + thread->priority = priority; + break; + } + return 0; +} + +static void UpdatePriority(OSThread* thread) +{ + long priority; + + while (1) { + if (thread->suspend > 0) { + break; + } + priority = __OSGetEffectivePriority(thread); + if (thread->priority == priority) { + break; + } + thread = SetEffectivePriority(thread, priority); + if (thread == 0) { + break; + } + } +} + +void __OSPromoteThread(OSThread* thread, long priority) +{ + while (1) { + if (thread->suspend > 0 || thread->priority <= priority) { + break; + } + thread = SetEffectivePriority(thread, priority); + if (thread == 0) { + break; + } + } +} + +static OSThread* SelectThread(int yield) +{ + struct OSContext* currentContext; + OSThread* currentThread; + OSThread* nextThread; + long priority; + OSThreadQueue* queue; + + if (Reschedule > 0) { + return NULL; + } + + currentContext = OSGetCurrentContext(); + currentThread = OSGetCurrentThread(); + + if (currentContext != ¤tThread->context) { + return NULL; + } + + if (currentThread) { + if (currentThread->state == 2) { + if (yield == 0) { + priority = __cntlzw(RunQueueBits); + if (currentThread->priority <= priority) + return NULL; + } + currentThread->state = 1; + SetRun(currentThread); + } + if (!(currentThread->context.state & 2) + && (OSSaveContext(¤tThread->context) != 0)) { + return NULL; + } + } + + if (RunQueueBits == 0) { + SwitchThreadCallback(__gCurrentThread, NULL); + __gCurrentThread = NULL; + OSSetCurrentContext(&IdleContext); + do { + OSEnableInterrupts(); + while (RunQueueBits == 0) + ; + OSDisableInterrupts(); + } while (RunQueueBits == 0); + OSClearContext(&IdleContext); + } + + RunQueueHint = 0; + priority = __cntlzw(RunQueueBits); + + ASSERTLINE(0x2C6, + OS_PRIORITY_MIN <= priority && priority <= OS_PRIORITY_MAX); + + queue = &RunQueue[priority]; + nextThread = queue->head; + + DEQUEUE_HEAD(nextThread, queue, link); + + ASSERTLINE(0x2C9, nextThread->priority == priority); + + if (!queue->head) { + RunQueueBits &= ~(1 << (0x1F - priority)); + } + nextThread->queue = 0; + nextThread->state = 2; + __OSSwitchThread(nextThread); + return nextThread; +} + +void __OSReschedule(void) +{ + if (RunQueueHint != 0) { + SelectThread(0); + } +} + +void OSYieldThread(void) +{ + int enabled = OSDisableInterrupts(); + + SelectThread(1); + OSRestoreInterrupts(enabled); +} + +int OSCreateThread(OSThread* thread, void* (*func)(void*), void* param, + void* stack, unsigned long stackSize, long priority, + unsigned short attr) +{ + BOOL enable; + u32 sp; + int i; + + if (priority < OS_PRIORITY_MIN || priority > OS_PRIORITY_MAX) { + return FALSE; + } + + sp = ((u32)stack & 0xFFFFFFF8); + thread->state = OS_THREAD_STATE_READY; + thread->attr = attr & OS_THREAD_ATTR_DETACH; + thread->base = priority; + thread->priority = priority; + thread->suspend = 1; + thread->val = (void*)-1; + thread->mutex = NULL; + OSInitThreadQueue(&thread->queueJoin); + InitMutexQueue(&thread->queueMutex); + *(u32*)(sp - 8) = 0; + *(u32*)(sp - 4) = 0; + + OSInitContext(&thread->context, (u32)func, (u32)(sp - 8)); + + thread->context.lr = (u32)&OSExitThread; + thread->context.gpr[3] = (u32)param; + thread->stackBase = stack; + thread->stackEnd = (u32*)((u32)stack - stackSize); + *(thread->stackEnd) = OS_THREAD_STACK_MAGIC; + thread->error = 0; + for (i = 0; i < 2; i++) { + thread->specific[i] = NULL; + } + + enable = OSDisableInterrupts(); + + if (__OSErrorTable[OS_ERROR_FPE] != NULL) { + thread->context.srr1 |= 0x900; + thread->context.state |= OS_CONTEXT_STATE_FPSAVED; + thread->context.fpscr = (__OSFpscrEnableBits & 0xF8) | 0x4; + + for (i = 0; i < 32; i++) { + *(u64*)&thread->context.fpr[i] = -1; + *(u64*)&thread->context.psf[i] = -1; + } + } + + ENQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + OSRestoreInterrupts(enable); + return TRUE; +} + +void OSExitThread(void* val) +{ + int enabled = OSDisableInterrupts(); + OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(0x354, currentThread, + "OSExitThread(): current thread does not exist."); + ASSERTMSGLINE(0x356, currentThread->state == 2, + "OSExitThread(): current thread is not running."); + ASSERTMSGLINE(0x358, __OSIsThreadActive(currentThread) != 0, + "OSExitThread(): current thread is not active."); + + OSClearContext(¤tThread->context); + if (currentThread->attr & 1) { + DEQUEUE_THREAD(currentThread, &__OSActiveThreadQueue, linkActive); + currentThread->state = 0; + } else { + currentThread->state = 8; + currentThread->val = val; + } + __OSUnlockAllMutex(currentThread); + OSWakeupThread(¤tThread->queueJoin); + RunQueueHint = 1; + + if (RunQueueHint != 0) { + SelectThread(0); + } + + OSRestoreInterrupts(enabled); +} + +void OSCancelThread(OSThread* thread) +{ + int enabled = OSDisableInterrupts(); + + ASSERTMSG1LINE(0x37E, __OSIsThreadActive(thread) != 0, + "OSExitThread(): thread %p is not active.", thread); + + switch (thread->state) { + case 1: + if (thread->suspend <= 0) { + UnsetRun(thread); + } + break; + case 2: + RunQueueHint = 1; + break; + case 4: + DEQUEUE_THREAD(thread, thread->queue, link); + thread->queue = 0; + if ((thread->suspend <= 0) && (thread->mutex)) { + ASSERTLINE(0x391, thread->mutex->thread); + UpdatePriority(thread->mutex->thread); + } + break; + default: + OSRestoreInterrupts(enabled); + return; + } + OSClearContext(&thread->context); + if (thread->attr & 1) { + DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + thread->state = 0; + } else { + thread->state = 8; + } + __OSUnlockAllMutex(thread); + OSWakeupThread(&thread->queueJoin); + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +int OSJoinThread(OSThread* thread, void** val) +{ + int enabled = OSDisableInterrupts(); + + ASSERTMSG1LINE(0x3CA, __OSIsThreadActive(thread) != 0, + "OSJoinThread(): thread %p is not active.", thread); + + if (!(thread->attr & 1) && (thread->state != 8) + && (thread->queueJoin.head == NULL)) { + OSSleepThread(&thread->queueJoin); + if (__OSIsThreadActive(thread) == 0) { + OSRestoreInterrupts(enabled); + return 0; + } + } + if (thread->state == 8) { + if (val) { + *val = thread->val; + } + DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + thread->state = 0; + OSRestoreInterrupts(enabled); + return 1; + } + OSRestoreInterrupts(enabled); + return 0; +} + +void OSDetachThread(OSThread* thread) +{ + int enabled = OSDisableInterrupts(); + + ASSERTMSG1LINE(0x3FC, __OSIsThreadActive(thread) != 0, + "OSDetachThread(): thread %p is not active.", thread); + + thread->attr |= 1; + if (thread->state == 8) { + DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + thread->state = 0; + } + OSWakeupThread(&thread->queueJoin); + OSRestoreInterrupts(enabled); +} + +long OSResumeThread(OSThread* thread) +{ + int enabled = OSDisableInterrupts(); + long suspendCount; + + ASSERTMSG1LINE(0x419, __OSIsThreadActive(thread) != 0, + "OSResumeThread(): thread %p is not active.", thread); + ASSERTMSG1LINE(0x41B, thread->state != 8, + "OSResumeThread(): thread %p is terminated.", thread); + + suspendCount = thread->suspend--; + if (thread->suspend < 0) { + thread->suspend = 0; + } else if (thread->suspend == 0) { + switch (thread->state) { + case 1: + thread->priority = __OSGetEffectivePriority(thread); + SetRun(thread); + break; + case 4: + ASSERTLINE(0x42A, thread->queue); + DEQUEUE_THREAD(thread, thread->queue, link); + thread->priority = __OSGetEffectivePriority(thread); + ENQUEUE_THREAD_PRIO(thread, thread->queue, link); + if (thread->mutex) { + UpdatePriority(thread->mutex->thread); + } + } + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return suspendCount; +} + +long OSSuspendThread(OSThread* thread) +{ + int enabled = OSDisableInterrupts(); + long suspendCount; + + ASSERTMSG1LINE(0x44C, __OSIsThreadActive(thread) != 0, + "OSSuspendThread(): thread %p is not active.", thread); + ASSERTMSG1LINE(0x44E, thread->state != 8, + "OSSuspendThread(): thread %p is terminated.", thread); + + suspendCount = thread->suspend++; + if (suspendCount == 0) { + switch (thread->state) { + case 2: + RunQueueHint = 1; + thread->state = 1; + break; + case 1: + UnsetRun(thread); + break; + case 4: + DEQUEUE_THREAD(thread, thread->queue, link); + thread->priority = 0x20; + ENQUEUE_THREAD(thread, thread->queue, link); + if (thread->mutex) { + ASSERTLINE(0x463, thread->mutex->thread); + UpdatePriority(thread->mutex->thread); + } + break; + } + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return suspendCount; +} + +void OSSleepThread(OSThreadQueue* queue) +{ + int enabled = OSDisableInterrupts(); + OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(0x484, currentThread, + "OSSleepThread(): current thread does not exist."); + ASSERTMSG1LINE(0x486, __OSIsThreadActive(currentThread) != 0, + "OSSleepThread(): current thread %p is not active.", + currentThread); + ASSERTMSG1LINE(0x488, currentThread->state == 2, + "OSSleepThread(): current thread %p is not running.", + currentThread); + ASSERTMSG1LINE(0x48A, currentThread->suspend <= 0, + "OSSleepThread(): current thread %p is suspended.", + currentThread); + + currentThread->state = 4; + currentThread->queue = queue; + ENQUEUE_THREAD_PRIO(currentThread, queue, link); + RunQueueHint = 1; + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +void OSWakeupThread(OSThreadQueue* queue) +{ + int enabled = OSDisableInterrupts(); + + while (queue->head) { + OSThread* thread = queue->head; + + DEQUEUE_HEAD(thread, queue, link); + + ASSERTLINE(0x4A7, __OSIsThreadActive(thread)); + ASSERTLINE(0x4A8, thread->state != OS_THREAD_STATE_MORIBUND); + ASSERTLINE(0x4A9, thread->queue == queue); + thread->state = 1; + if (thread->suspend <= 0) { + SetRun(thread); + } + } + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +int OSSetThreadPriority(struct OSThread * thread, long priority) { + int enabled; + + ASSERTMSGLINE(0x4C3, (priority >= 0) && (priority <= 0x1F), "OSSetThreadPriority(): priority out of range (0 <= priority <= 31)."); + + if ((priority < 0) || (priority > 0x1F)) { + return 0; + } + enabled = OSDisableInterrupts(); + + ASSERTMSG1LINE(0x4CA, __OSIsThreadActive(thread) != 0, "OSSetThreadPriority(): thread %p is not active.", thread); + ASSERTMSG1LINE(0x4CC, thread->state != 8, "OSSetThreadPriority(): thread %p is terminated.", thread); + + if (thread->base != priority) { + thread->base = priority; + UpdatePriority(thread); + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return 1; +} + +long OSGetThreadPriority(OSThread* thread) { return thread->base; } + + +static int CheckThreadQueue(struct OSThreadQueue * queue) { + struct OSThread * thread; + + if ((queue->head != NULL) && (queue->head->link.prev != NULL)) { + return 0; + } + if ((queue->tail != NULL) && (queue->tail->link.next != NULL)) { + return 0; + } + thread = queue->head; + while(thread) { + if ((thread->link.next != NULL) && (thread != thread->link.next->link.prev)) { + return 0; + } + if ((thread->link.prev != NULL) && (thread != thread->link.prev->link.next)) { + return 0; + } + thread = thread->link.next; + } + return 1; +} + +static int IsMember(struct OSThreadQueue * queue, struct OSThread * thread) { + struct OSThread * member = queue->head; + + while(member) { + if (thread == member) { + return 1; + } + member = member->link.next; + } + return 0; +} + +#define ASSERTREPORT(line, cond) \ + if (!(cond)) { \ + OSReport("OSCheckActiveThreads: Failed " #cond " in %d\n", line); \ + OSPanic(__FILE__, line, ""); \ + } + +long OSCheckActiveThreads() { + struct OSThread * thread; + long prio; + long cThread; + int enabled; + + cThread = 0; + enabled = OSDisableInterrupts(); + + for(prio = 0; prio <= 0x1F; prio++) { + if (RunQueueBits & (1 << (0x1F - prio))) { + ASSERTREPORT(0x5C1, RunQueue[prio].head != NULL && RunQueue[prio].tail != NULL); + } else { + ASSERTREPORT(0x5C6, RunQueue[prio].head == NULL && RunQueue[prio].tail == NULL); + } + ASSERTREPORT(0x5C8, CheckThreadQueue(&RunQueue[prio])); + } + + ASSERTREPORT(0x5CD, __OSActiveThreadQueue.head == NULL || __OSActiveThreadQueue.head->linkActive.prev == NULL); + ASSERTREPORT(0x5CF, __OSActiveThreadQueue.tail == NULL || __OSActiveThreadQueue.tail->linkActive.next == NULL); + + thread = __OSActiveThreadQueue.head; + while(thread) { + cThread++; + ASSERTREPORT(0x5D7, thread->linkActive.next == NULL || thread == thread->linkActive.next->linkActive.prev); + ASSERTREPORT(0x5D9, thread->linkActive.prev == NULL || thread == thread->linkActive.prev->linkActive.next); + ASSERTREPORT(0x5DC, *(thread->stackEnd) == OS_THREAD_STACK_MAGIC); + ASSERTREPORT(0x5DF, OS_PRIORITY_MIN <= thread->priority && thread->priority <= OS_PRIORITY_MAX+1); + ASSERTREPORT(0x5E0, 0 <= thread->suspend); + ASSERTREPORT(0x5E1, CheckThreadQueue(&thread->queueJoin)); + + switch(thread->state) { + case 1: + if (thread->suspend <= 0) { + ASSERTREPORT(0x5E7, thread->queue == &RunQueue[thread->priority]); + ASSERTREPORT(0x5E8, IsMember(&RunQueue[thread->priority], thread)); + ASSERTREPORT(0x5E9, thread->priority == __OSGetEffectivePriority(thread)); + } + break; + case 2: + ASSERTREPORT(0x5ED, !IsSuspended(thread->suspend)); + ASSERTREPORT(0x5EE, thread->queue == NULL); + ASSERTREPORT(0x5EF, thread->priority == __OSGetEffectivePriority(thread)); + break; + case 4: + ASSERTREPORT(0x5F2, thread->queue != NULL); + ASSERTREPORT(0x5F3, CheckThreadQueue(thread->queue)); + ASSERTREPORT(0x5F4, IsMember(thread->queue, thread)); + if (thread->suspend <= 0) { + ASSERTREPORT(0x5F7, thread->priority == __OSGetEffectivePriority(thread)); + } else { + ASSERTREPORT(0x5FB, thread->priority == 32); + } + ASSERTREPORT(0x5FD, !__OSCheckDeadLock(thread)); + break; + case 8: + ASSERTREPORT(0x601, thread->queueMutex.head == NULL && thread->queueMutex.tail == NULL); + break; + default: + OSReport("OSCheckActiveThreads: Failed. unkown thread state (%d) of thread %p\n", thread->state, thread); + OSPanic("OSThread.c", 0x607, ""); + } + ASSERTREPORT(0x60C, __OSCheckMutexes(thread)); + thread = thread->linkActive.next; + } + OSRestoreInterrupts(enabled); + return cThread; +} + +void OSClearStack(u8 val) +{ + register u32 sp; + register u32* p; + register u32 pattern; + + pattern = ((u32)val << 24) | ((u32)val << 16) | ((u32)val << 8) | (u32)val; + sp = OSGetStackPointer(); + for (p = __gCurrentThread->stackEnd + 1; p < (u32*)sp; ++p) { + *p = pattern; + } +} diff --git a/src/static/GAEJ01_01/dolphin/os/OSTime.c b/src/static/GAEJ01_01/dolphin/os/OSTime.c new file mode 100644 index 00000000..26f59148 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/OSTime.c @@ -0,0 +1,170 @@ +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +// End of each month in standard year +static int YearDays[MONTH_MAX] + = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; +// End of each month in leap year +static int LeapYearDays[MONTH_MAX] + = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; + +asm long long OSGetTime(void) +{ +#ifdef __MWERKS__ // clang-format off +jump: + nofralloc + + mftbu r3 + mftb r4 + + // Check for possible carry from TBL to TBU + mftbu r5 + cmpw r3, r5 + bne jump + + blr +#endif // clang-format on +} + +asm unsigned long OSGetTick(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + + mftb r3 + blr +#endif // clang-format on +} + +long long __OSGetSystemTime() +{ + int enabled; + long long* timeAdjustAddr; + long long result; + + timeAdjustAddr = (long long*)0x800030D8; + enabled = OSDisableInterrupts(); + + result = OSGetTime() + *timeAdjustAddr; + OSRestoreInterrupts(enabled); + return result; +} + +static int IsLeapYear(int year) +{ + return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); +} + +static int GetYearDays(int year, int mon) { + int* md = (IsLeapYear(year)) ? LeapYearDays : YearDays; + + return md[mon]; +} + +static int GetLeapDays(int year) +{ + ASSERTLINE(260, 0 <= year); + + if (year < 1) { + return 0; + } + return (year + 3) / 4 - (year - 1) / 100 + (year - 1) / 400; +} + +static void GetDates(int days, OSCalendarTime* td) +{ + int year; + int n; + int month; + int* md; + + ASSERTLINE(285, 0 <= days); + + td->wday = (days + 6) % WEEK_DAY_MAX; + + for (year = days / YEAR_DAY_MAX; + days < (n = year * YEAR_DAY_MAX + GetLeapDays(year)); year--) { + ; + } + + days -= n; + td->year = year; + td->yday = days; + + md = IsLeapYear(year) ? LeapYearDays : YearDays; + for (month = MONTH_MAX; days < md[--month];) { + ; + } + td->mon = month; + td->mday = days - md[month] + 1; +} + +void OSTicksToCalendarTime(long long ticks, OSCalendarTime* td) +{ + int days; + int secs; + long long d; + + d = ticks % OSSecondsToTicks(1); + if (d < 0) { + d += OSSecondsToTicks(1); + ASSERTLINE(330, 0 <= d); + } + + td->usec = OSTicksToMicroseconds(d) % USEC_MAX; + td->msec = OSTicksToMilliseconds(d) % MSEC_MAX; + + ASSERTLINE(334, 0 <= td->usec); + ASSERTLINE(335, 0 <= td->msec); + + ticks -= d; + + ASSERTLINE(338, ticks % OSSecondsToTicks(1) == 0); + ASSERTLINE(342, 0 <= OSTicksToSeconds(ticks) / 86400 + BIAS + && OSTicksToSeconds(ticks) / 86400 + BIAS <= INT_MAX); + + days = (OSTicksToSeconds(ticks) / SECS_IN_DAY) + BIAS; + secs = OSTicksToSeconds(ticks) % SECS_IN_DAY; + if (secs < 0) { + days -= 1; + secs += SECS_IN_DAY; + ASSERTLINE(349, 0 <= secs); + } + + GetDates(days, td); + td->hour = secs / 60 / 60; + td->min = secs / 60 % 60; + td->sec = secs % 60; +} + +OSTime OSCalendarTimeToTicks(OSCalendarTime* td) { + OSTime secs; + int ov_mon; + int mon; + int year; + + ov_mon = td->mon / MONTH_MAX; + mon = td->mon - (ov_mon * MONTH_MAX); + + if (mon < 0) { + mon += MONTH_MAX; + ov_mon--; + } + + ASSERTLINE(412, (ov_mon <= 0 && 0 <= td->year + ov_mon) || (0 < ov_mon && td->year <= INT_MAX - ov_mon)); + + year = td->year + ov_mon; + + secs = (OSTime)SECS_IN_YEAR * year + + (OSTime)SECS_IN_DAY * (GetLeapDays(year) + GetYearDays(year, mon) + td->mday - 1) + + (OSTime)SECS_IN_HOUR * td->hour + + (OSTime)SECS_IN_MIN * td->min + + td->sec - + (OSTime)0xEB1E1BF80ULL; + + return OSSecondsToTicks(secs) + OSMillisecondsToTicks((OSTime)td->msec) + + OSMicrosecondsToTicks((OSTime)td->usec); +} diff --git a/src/static/GAEJ01_01/dolphin/os/__os.h b/src/static/GAEJ01_01/dolphin/os/__os.h new file mode 100644 index 00000000..fa65b097 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/__os.h @@ -0,0 +1,131 @@ +#ifndef _DOLPHIN_OS_INTERNAL_H_ +#define _DOLPHIN_OS_INTERNAL_H_ + +#include + +#ifndef OS_ERROR_FPE +#define OS_ERROR_FPE 16 +#endif + +volatile OSContext* __OSFPUContext AT_ADDRESS(OS_BASE_CACHED | 0x00D8); + +// OS.c +void OSRegisterVersion(const char* id); + +extern char* __OSExceptionNames[15]; // D ONLY +extern OSTime __OSStartTime; + +unsigned long __OSIsDebuggerPresent(void); +void __OSPSInit(void); + +extern void* BOOT_REGION_START AT_ADDRESS(0x812FDFF0); +extern void* BOOT_REGION_END AT_ADDRESS(0x812FDFEC); + +// OSAlloc.c +extern volatile int __OSCurrHeap; + +// OSAudioSystem.c +void __OSInitAudioSystem(void); +void __OSStopAudioSystem(void); + +// OSCache.c +void __OSCacheInit(void); + +// OSContext.c +void __OSContextInit(void); + +// OSMemory.c +void __OSInitMemoryProtection(void); + +// OSError.c +void __OSUnhandledException(unsigned char exception, struct OSContext* context, + unsigned long dsisr, unsigned long dar); + +// OSInterrupt.c +extern void __RAS_OSDisableInterrupts_begin(void); +extern void __RAS_OSDisableInterrupts_end(void); + +extern unsigned long long __OSSpuriousInterrupts; // D ONLY +extern char* __OSInterruptNames[33]; // D ONLY +extern char* __OSPIErrors[8]; // D ONLY +extern OSErrorHandlerEx __OSErrorTable[16]; + +__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, + __OSInterruptHandler handler); +__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt); +void __OSInterruptInit(void); +OSInterruptMask __OSMaskInterrupts(OSInterruptMask global); +OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask global); +void __OSDispatchInterrupt(__OSException exception, OSContext* context); +void __OSModuleInit(void); + +// OSMutex.c +void __OSUnlockAllMutex(struct OSThread* thread); +int __OSCheckDeadLock(struct OSThread* thread); +int __OSCheckMutexes(struct OSThread* thread); + +// OSResetSW.c +void __OSResetSWInterruptHandler(__OSInterrupt exception, + struct OSContext* context); + +// OSReset.c +void __OSDoHotReset(s32); + +// OSReboot.c +void __OSReboot(u32, u32); + +// OSRtc.c +int __OSGetRTC(unsigned long* rtc); +int __OSSetRTC(unsigned long rtc); +void __OSInitSram(); +struct OSSram* __OSLockSram(void); +struct OSSramEx* __OSLockSramEx(void); +int __OSUnlockSram(int commit); +int __OSUnlockSramEx(int commit); +int __OSSyncSram(void); +int __OSCheckSram(void); +int __OSReadROM(void* buffer, long length, long offset); +int __OSReadROMAsync(void* buffer, long length, long offset, + void (*callback)()); +unsigned char __OSGetBootMode(void); +void __OSSetBootMode(unsigned char ntd); + +// OSSync.c +extern void __OSSystemCallVectorStart(); +extern void __OSSystemCallVectorEnd(); + +void __OSInitSystemCall(void); + +// OSThread.c +void __OSThreadInit(void); +long __OSGetEffectivePriority(struct OSThread* thread); +void __OSPromoteThread(struct OSThread* thread, long priority); +void __OSReschedule(void); + +// OSTime.c +void __OSSetTime(long long time); +long long __OSGetSystemTime(); +void __OSSetTick(register unsigned long newTicks); + +extern u32 __OSGetDIConfig(void); + +// ppc_eabi_init.c +__declspec(section ".init") asm void __init_hardware(void); +__declspec(section ".init") asm void __flush_cache(void* address, + unsigned int size); +void __init_user(void); +void __init_cpp(void); +void __fini_cpp(void); +void _ExitProcess(void); + +// start.c +void __start(void); + +__declspec(section ".init") extern void __start(void); + +// time.dolphin.c +long long __get_clock(void); +unsigned long __get_time(void); +int __to_gm_time(void); + +#endif // _DOLPHIN_OS_INTERNAL_H_ diff --git a/src/static/GAEJ01_01/dolphin/os/__ppc_eabi_init.cpp b/src/static/GAEJ01_01/dolphin/os/__ppc_eabi_init.cpp new file mode 100644 index 00000000..fe942b0d --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/__ppc_eabi_init.cpp @@ -0,0 +1,71 @@ +#include "dolphin/os/__ppc_eabi_init.h" + +#include "dolphin/base/PPCArch.h" +#include "dolphin/os.h" +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static void __init_cpp(void); +static void __fini_cpp(void); +void __OSFPRInit(void); + +/* clang-format off */ +__declspec(section ".init") asm void __init_hardware(void) { + nofralloc + mfmsr r0 + ori r0, r0, 0x2000 + mtmsr r0 + mflr r31 + bl __OSPSInit + bl __OSFPRInit + bl __OSCacheInit + mtlr r31 + blr +} + +__declspec(section ".init") asm void __flush_cache(void* address, u32 size) { + nofralloc + lis r5, 0xFFFFFFF1@h + ori r5, r5, 0xFFFFFFF1@l + and r5, r5, r3 + subf r3, r5, r3 + add r4, r4, r3 +loop: + dcbst 0, r5 + sync + icbi 0, r5 + addic r5, r5, 8 + addic. r4, r4, -8 + bge loop + isync + blr +} +/* clang-format on */ + +asm void __init_user(void) { + fralloc + bl __init_cpp +} + +static void __init_cpp(void) { + voidfunctionptr* constructor; + + for (constructor = _ctors; *constructor; constructor++) { + (*constructor)(); + } +} + +static void __fini_cpp(void) { + // UNUSED FUNCTION +} + +void _ExitProcess(void) { + PPCHalt(); +} + +#ifdef __cplusplus +} +#endif diff --git a/src/static/GAEJ01_01/dolphin/os/__start.c b/src/static/GAEJ01_01/dolphin/os/__start.c new file mode 100644 index 00000000..acb8eec8 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/os/__start.c @@ -0,0 +1,211 @@ +#include "dolphin/os.h" +#include "dolphin/db.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" +#include "dolphin/os/__ppc_eabi_init.h" +#include + +__declspec(section ".init") void __init_registers(void); +__declspec(section ".init") void __init_data(void); + +int main(int argc, char** argv); + +static u8 Debug_BBA = 0; + +__declspec(section ".init") void __check_pad3(void) { + if ((*(u16*)0x800030E4 & 0xEEF) == 0xEEF) { + OSResetSystem(0, 0, 0); + } +} + +__declspec(section ".init") void __set_debug_bba(void) { + Debug_BBA = 1; +} + +__declspec(section ".init") u8 __get_debug_bba(void) { + return Debug_BBA; +} + +/* clang-format off */ +__declspec(section ".init") asm void __start(void){ + nofralloc + + bl __init_registers + bl __init_hardware + li r0, -1 + stwu r1, -8(r1) + stw r0, 4(r1) + stw r0, 0(r1) + bl __init_data + li r0, 0x0 + lis r6, 0x8000 + addi r6, r6, 0x44 + stw r0, 0(r6) + lis r6, 0x8000 + addi r6, r6, 0xf4 + lwz r6, 0(r6) + cmplwi r6, 0 + beq- ar + lwz r7, 0xc(r6) + b h + +ar: + lis r5, 0x8000 + addi r5, r5, 0x34 + lwz r5, 0(r5) + cmplwi r5, 0 + beq- d + lis r7, 0x8000 + addi r7, r7, 0x30E8 + lwz r7, 0(r7) +h: + li r5, 0x0 + cmplwi r7, 2 + beq met + cmplwi r7, 3 + li r5, 0x1 + beq met + cmplwi r7, 4 + bne d + li r5, 0x2 + bl __set_debug_bba + b d +met: + lis r6, InitMetroTRK@ha + addi r6, r6, InitMetroTRK@l + mtlr r6 + blrl +d: + lis r6, 0x8000 + addi r6, r6, 0xF4 + lwz r5, 0(r6) + cmplwi r5, 0 + beq+ res + lwz r6, 8(r5) + cmplwi r6, 0 + beq+ res + add r6, r5, r6 + lwz r14, 0(r6) + cmplwi r14, 0 + beq- res + addi r15, r6, 0x4 + mtctr r14 + +loop: + addi r6, r6, 0x4 + lwz r7, 0(r6) + add r7, r7, r5 + stw r7, 0(r6) + bdnz loop + lis r5, 0x8000 + addi r5, r5, 0x34 + rlwinm r7, r15, 0, 0, 0x1A + stw r7, 0(r5) + b indeb +res: + li r14, 0x0 + li r15, 0x0 +indeb: + bl DBInit + bl OSInit + lis r4, 0x8000 + addi r4, r4, 0x30E6 + lhz r3, 0(r4) + andi. r5, r3, 0x8000 + beq- check + andi. r3, r3, 0x7FFF + cmplwi r3, 1 + bne- user + +check: + bl __check_pad3 +user: + bl __get_debug_bba + cmplwi r3, 1 + bne skip_bba + bl InitMetroTRK_BBA +skip_bba: + bl __init_user + mr r3, r14 + mr r4, r15 + bl main // can't find the dol main, because there's one main in dol and then one in rel + b exit +} + +__declspec(section ".init") asm void __init_registers(void){ + nofralloc + li r0, 0 + li r3, 0 + li r4, 0 + li r5, 0 + li r6, 0 + li r7, 0 + li r8, 0 + li r9, 0 + li r10, 0 + li r11, 0 + li r12, 0 + li r14, 0 + li r15, 0 + li r16, 0 + li r17, 0 + li r18, 0 + li r19, 0 + li r20, 0 + li r21, 0 + li r22, 0 + li r23, 0 + li r24, 0 + li r25, 0 + li r26, 0 + li r27, 0 + li r28, 0 + li r29, 0 + li r30, 0 + li r31, 0 + lis r1, _stack_addr@h + ori r1, r1, _stack_addr@l + lis r2, _SDA2_BASE_@h + ori r2, r2, _SDA2_BASE_@l + lis r13, _SDA_BASE_@h + ori r13, r13, _SDA_BASE_@l + blr +} +/* clang-format on */ + +inline void __copy_rom_section(void* dst, const void* src, size_t size) { + if (size && (dst != src)) { + memcpy(dst, src, size); + __flush_cache(dst, size); + } +} + +inline void __init_bss_section(void* dst, size_t size) { + if (size) { + memset(dst, 0, size); + } +} + +__declspec(section ".init") static void __init_data(void) { + RomSection* rs; + BssSection* bs; + + rs = _rom_copy_info; + while (1) { + if (rs->size == 0) { + break; + } + + __copy_rom_section(rs->virtualOfs, rs->romOfs, rs->size); + rs++; + } + + bs = _bss_init_info; + while (1) { + if (bs->size == 0) { + break; + } + + __init_bss_section(bs->virtualOfs, bs->size); + bs++; + } +} diff --git a/src/static/GAEJ01_01/dolphin/pad/Pad.c b/src/static/GAEJ01_01/dolphin/pad/Pad.c new file mode 100644 index 00000000..0c5c36f9 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/pad/Pad.c @@ -0,0 +1,809 @@ +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +#define PAD_ALL (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_DOWN | PAD_BUTTON_UP | PAD_TRIGGER_Z | PAD_TRIGGER_R | PAD_TRIGGER_L | PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_Y | PAD_BUTTON_MENU | 0x2000 | 0x0080) + +u16 __OSWirelessPadFixMode : 0x800030E0; + +const char* __PADVersion = "<< Dolphin SDK - PAD\trelease build: Aug 6 2003 04:30:02 (0x2301) >>"; + +// forward declarations of static functions. +static void SPEC0_MakeStatus(s32 chan, PADStatus* status, u32 data[2]); +static void SPEC1_MakeStatus(s32 chan, PADStatus* status, u32 data[2]); +static void SPEC2_MakeStatus(s32 chan, PADStatus* status, u32 data[2]); +static void PADTypeAndStatusCallback(s32 chan, u32 type); +static BOOL OnReset(BOOL final); + +// static symbols. +static u32 Type[SI_MAX_CHAN]; +static PADStatus Origin[SI_MAX_CHAN]; +static u32 CmdProbeDevice[SI_MAX_CHAN]; + +static s32 ResettingChan = 32; +static u32 XPatchBits = PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT; +static u32 AnalogMode = 0x00000300u; +static u32 Spec = 5; +static void (*MakeStatus)(s32, PADStatus*, u32[2]) = SPEC2_MakeStatus; + +static u32 CmdReadOrigin = 0x41 << 24; +static u32 CmdCalibrate = 0x42 << 24; + +static OSResetFunctionInfo ResetFunctionInfo = { OnReset, 127 }; + +static BOOL Initialized; + +static u32 EnabledBits; +static u32 ResettingBits; +static u32 RecalibrateBits; +static u32 WaitingBits; +static u32 CheckingBits; +static u32 PendingBits; +static u32 BarrelBits; + +static void (*SamplingCallback)(void); + +// global symbols +u32 __PADSpec; + + +static void PADEnable(s32 chan) +{ + u32 cmd; + u32 chanBit; + u32 data[2]; + + chanBit = PAD_CHAN0_BIT >> chan; + EnabledBits |= chanBit; + SIGetResponse(chan, data); + cmd = (0x40 << 16) | AnalogMode; + SISetCommand(chan, cmd); + SIEnablePolling(EnabledBits); +} + +static void PADDisable(s32 chan) +{ + BOOL enabled; + u32 chanBit; + + enabled = OSDisableInterrupts(); + + chanBit = PAD_CHAN0_BIT >> chan; + SIDisablePolling(chanBit); + EnabledBits &= ~chanBit; + WaitingBits &= ~chanBit; + CheckingBits &= ~chanBit; + PendingBits &= ~chanBit; + BarrelBits &= ~chanBit; + OSSetWirelessID(chan, 0); + + OSRestoreInterrupts(enabled); +} + +static void DoReset(void) +{ + u32 chanBit; + + ResettingChan = __cntlzw(ResettingBits); + if (ResettingChan == 32) { + return; + } + + ASSERT(0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); + + chanBit = PAD_CHAN0_BIT >> ResettingChan; + ResettingBits &= ~chanBit; + + memset(&Origin[ResettingChan], 0, sizeof(PADStatus)); + SIGetTypeAsync(ResettingChan, (SITypeAndStatusCallback)PADTypeAndStatusCallback); +} + +static void UpdateOrigin(s32 chan) +{ + PADStatus* origin; + u32 chanBit = PAD_CHAN0_BIT >> chan; + + origin = &Origin[chan]; + switch (AnalogMode & 0x00000700u) { + case 0x00000000u: + case 0x00000500u: + case 0x00000600u: + case 0x00000700u: + origin->triggerLeft &= ~15; + origin->triggerRight &= ~15; + origin->analogA &= ~15; + origin->analogB &= ~15; + break; + case 0x00000100u: + origin->substickX &= ~15; + origin->substickY &= ~15; + origin->analogA &= ~15; + origin->analogB &= ~15; + break; + case 0x00000200u: + origin->substickX &= ~15; + origin->substickY &= ~15; + origin->triggerLeft &= ~15; + origin->triggerRight &= ~15; + break; + case 0x00000300u: + break; + case 0x00000400u: + break; + } + + origin->stickX -= 128; + origin->stickY -= 128; + origin->substickX -= 128; + origin->substickY -= 128; + + if (XPatchBits & chanBit) { + if (64 < origin->stickX && (SIGetType(chan) & 0xffff0000) == SI_GC_CONTROLLER) { + origin->stickX = 0; + } + } +} + +static void PADOriginCallback(s32 chan, u32 error, OSContext* context) +{ + ASSERT(0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); + ASSERT(chan == ResettingChan); + if (!(error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) { + UpdateOrigin(ResettingChan); + PADEnable(ResettingChan); + } + DoReset(); +} + +static void PADOriginUpdateCallback(s32 chan, u32 error, OSContext* context) +{ + ASSERT(0 <= chan && chan < SI_MAX_CHAN); + + if (!(EnabledBits & (PAD_CHAN0_BIT >> chan))) { + return; + } + + if (!(error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) { + UpdateOrigin(chan); + } + + if (error & SI_ERROR_NO_RESPONSE) { + PADDisable(chan); + } +} + +static void PADProbeCallback(s32 chan, u32 error, OSContext* context) +{ + ASSERT(0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); + ASSERT(chan == ResettingChan); + ASSERT((Type[chan] & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT && !(Type[chan] & SI_WIRELESS_LITE)); + if (!(error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) { + PADEnable(ResettingChan); + WaitingBits |= PAD_CHAN0_BIT >> ResettingChan; + } + DoReset(); +} + +static void PADTypeAndStatusCallback(s32 chan, u32 type) +{ + u32 chanBit; + u32 recalibrate; + BOOL rc = TRUE; + u32 error; + + ASSERT(0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); + ASSERT(chan == ResettingChan); + + chanBit = PAD_CHAN0_BIT >> ResettingChan; + error = type & 0xFF; + recalibrate = RecalibrateBits & chanBit; + RecalibrateBits &= ~chanBit; + + if (error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)) { + DoReset(); + return; + } + + type &= ~0xFF; + + Type[ResettingChan] = type; + + if ((type & SI_TYPE_MASK) != SI_TYPE_GC || !(type & SI_GC_STANDARD)) { + DoReset(); + return; + } + + if (Spec < PAD_SPEC_2) { + PADEnable(ResettingChan); + DoReset(); + return; + } + + if (!(type & SI_GC_WIRELESS) || (type & SI_WIRELESS_IR)) { + if (recalibrate) { + rc = SITransfer(ResettingChan, &CmdCalibrate, 3, &Origin[ResettingChan], 10, (SICallback)PADOriginCallback, 0); + } else { + rc = SITransfer(ResettingChan, &CmdReadOrigin, 1, &Origin[ResettingChan], 10, (SICallback)PADOriginCallback, 0); + } + } else if ((type & SI_WIRELESS_FIX_ID) && (type & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT && !(type & SI_WIRELESS_LITE)) { + if (type & SI_WIRELESS_RECEIVED) { + rc = SITransfer(ResettingChan, &CmdReadOrigin, 1, &Origin[ResettingChan], 10, (SICallback)PADOriginCallback, 0); + } else { + rc = SITransfer(ResettingChan, &CmdProbeDevice[ResettingChan], 3, &Origin[ResettingChan], 8, (SICallback)PADProbeCallback, 0); + } + } + if (!rc) { + PendingBits |= chanBit; + DoReset(); + return; + } +} + +static void PADReceiveCheckCallback(s32 chan, u32 type) +{ + u32 error; + u32 chanBit; + + chanBit = PAD_CHAN0_BIT >> chan; + if (!(EnabledBits & chanBit)) { + return; + } + + error = type & 0xFF; + type &= ~0xFF; + + WaitingBits &= ~chanBit; + CheckingBits &= ~chanBit; + + if (!(error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)) && (type & SI_GC_WIRELESS) + && (type & SI_WIRELESS_FIX_ID) && (type & SI_WIRELESS_RECEIVED) && !(type & SI_WIRELESS_IR) + && (type & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT && !(type & SI_WIRELESS_LITE)) { + SITransfer(chan, &CmdReadOrigin, 1, &Origin[chan], 10, (SICallback)PADOriginUpdateCallback, 0); + } else { + PADDisable(chan); + } +} + +BOOL PADReset(u32 mask) +{ + BOOL enabled; + u32 disableBits; + + ASSERTMSGLINE(0x381, !(mask & 0x0FFFFFFF), "PADReset(): invalid mask"); + enabled = OSDisableInterrupts(); + + mask |= PendingBits; + PendingBits = 0; + mask &= ~(WaitingBits | CheckingBits); + ResettingBits |= mask; + disableBits = ResettingBits & EnabledBits; + EnabledBits &= ~mask; + BarrelBits &= ~mask; + + if (Spec == PAD_SPEC_4) { + RecalibrateBits |= mask; + } + + SIDisablePolling(disableBits); + + if (ResettingChan == 32) { + DoReset(); + } + OSRestoreInterrupts(enabled); + return TRUE; +} + +BOOL PADRecalibrate(u32 mask) +{ + BOOL enabled; + u32 disableBits; + + ASSERTMSGLINE(939, !(mask & 0x0FFFFFFF), "PADReset(): invalid mask"); + enabled = OSDisableInterrupts(); + + mask |= PendingBits; + PendingBits = 0; + mask &= ~(WaitingBits | CheckingBits); + ResettingBits |= mask; + disableBits = ResettingBits & EnabledBits; + EnabledBits &= ~mask; + BarrelBits &= ~mask; + + if (!(__gUnknown800030E3 & 0x40)) { + RecalibrateBits |= mask; + } + + SIDisablePolling(disableBits); + if (ResettingChan == 32) { + DoReset(); + } + OSRestoreInterrupts(enabled); + return TRUE; +} + +BOOL PADInit(void) +{ + s32 chan; + if (Initialized) { + return TRUE; + } + + OSRegisterVersion(__PADVersion); + + if (__PADSpec) { + PADSetSpec(__PADSpec); + } + + Initialized = TRUE; + + if (__PADFixBits != 0) { + OSTime time = OSGetTime(); + __OSWirelessPadFixMode + = (u16)((((time) & 0xffff) + ((time >> 16) & 0xffff) + ((time >> 32) & 0xffff) + ((time >> 48) & 0xffff)) & 0x3fffu); + RecalibrateBits = PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT; + } + + for (chan = 0; chan < SI_MAX_CHAN; ++chan) { + CmdProbeDevice[chan] = (0x4D << 24) | (chan << 22) | ((__OSWirelessPadFixMode & 0x3fffu) << 8); + } + + SIRefreshSamplingRate(); + OSRegisterResetFunction(&ResetFunctionInfo); + return PADReset(PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT); +} + +u32 PADRead(PADStatus* status) +{ + BOOL enabled; + s32 chan; + u32 data[2]; + u32 chanBit; + u32 sr; + s32 chanShift; + u32 motor; + + enabled = OSDisableInterrupts(); + + motor = 0; + for (chan = 0; chan < SI_MAX_CHAN; chan++, status++) { + chanBit = PAD_CHAN0_BIT >> chan; + chanShift = 8 * (SI_MAX_CHAN - 1 - chan); + + if (PendingBits & chanBit) { + PADReset(0); + status->err = PAD_ERR_NOT_READY; + memset(status, 0, offsetof(PADStatus, err)); + continue; + } + + if ((ResettingBits & chanBit) || ResettingChan == chan) { + status->err = PAD_ERR_NOT_READY; + memset(status, 0, offsetof(PADStatus, err)); + continue; + } + + if (!(EnabledBits & chanBit)) { + status->err = (s8)PAD_ERR_NO_CONTROLLER; + memset(status, 0, offsetof(PADStatus, err)); + continue; + } + + if (SIIsChanBusy(chan)) { + status->err = PAD_ERR_TRANSFER; + memset(status, 0, offsetof(PADStatus, err)); + continue; + } + + sr = SIGetStatus(chan); + if (sr & SI_ERROR_NO_RESPONSE) { + SIGetResponse(chan, data); + + if (WaitingBits & chanBit) { + status->err = (s8)PAD_ERR_NONE; + memset(status, 0, offsetof(PADStatus, err)); + + if (!(CheckingBits & chanBit)) { + CheckingBits |= chanBit; + SIGetTypeAsync(chan, (SITypeAndStatusCallback)PADReceiveCheckCallback); + } + continue; + } + + PADDisable(chan); + + status->err = (s8)PAD_ERR_NO_CONTROLLER; + memset(status, 0, offsetof(PADStatus, err)); + continue; + } + + if (!(SIGetType(chan) & SI_GC_NOMOTOR)) { + motor |= chanBit; + } + + if (!SIGetResponse(chan, data)) { + status->err = PAD_ERR_TRANSFER; + memset(status, 0, offsetof(PADStatus, err)); + continue; + } + + if (data[0] & 0x80000000) { + status->err = PAD_ERR_TRANSFER; + memset(status, 0, offsetof(PADStatus, err)); + continue; + } + + MakeStatus(chan, status, data); + + // Check and clear PAD_ORIGIN bit + if (status->button & 0x2000) { + status->err = PAD_ERR_TRANSFER; + memset(status, 0, offsetof(PADStatus, err)); + + // Get origin. It is okay if the following transfer fails + // since the PAD_ORIGIN bit remains until the read origin + // command complete. + SITransfer(chan, &CmdReadOrigin, 1, &Origin[chan], 10, (SICallback)PADOriginUpdateCallback, 0); + continue; + } + + status->err = PAD_ERR_NONE; + + // Clear PAD_INTERFERE bit + status->button &= ~0x0080; + } + + OSRestoreInterrupts(enabled); + return motor; +} + +void PADControlAllMotors(const u32* commandArray) +{ + BOOL enabled; + s32 chan; + u32 command; + BOOL commit; + u32 chanBit; + + enabled = OSDisableInterrupts(); + commit = FALSE; + for (chan = 0; chan < SI_MAX_CHAN; chan++, commandArray++) { + chanBit = PAD_CHAN0_BIT >> chan; + if ((EnabledBits & chanBit) && !(SIGetType(chan) & SI_GC_NOMOTOR)) { + command = *commandArray; + ASSERTMSGLINE(0x4B5, !(command & 0xFFFFFFFC), "PADControlAllMotors(): invalid command"); + if (Spec < PAD_SPEC_2 && command == PAD_MOTOR_STOP_HARD) { + command = PAD_MOTOR_STOP; + } + if (__gUnknown800030E3 & 0x20) { + command = PAD_MOTOR_STOP; + } + + SISetCommand(chan, (0x40 << 16) | AnalogMode | (command & (0x00000001 | 0x00000002))); + commit = TRUE; + } + } + if (commit) { + SITransferCommands(); + } + OSRestoreInterrupts(enabled); +} + +void PADControlMotor(s32 chan, u32 command) +{ + BOOL enabled; + u32 chanBit; + + enabled = OSDisableInterrupts(); + chanBit = PAD_CHAN0_BIT >> chan; + if ((EnabledBits & chanBit) && !(SIGetType(chan) & SI_GC_NOMOTOR)) { + if (Spec < PAD_SPEC_2 && command == PAD_MOTOR_STOP_HARD) { + command = PAD_MOTOR_STOP; + } + if (__gUnknown800030E3 & 0x20) { + command = PAD_MOTOR_STOP; + } + + SISetCommand(chan, (0x40 << 16) | AnalogMode | (command & (0x00000001 | 0x00000002))); + SITransferCommands(); + } + OSRestoreInterrupts(enabled); +} + +void PADSetSpec(u32 spec) +{ + __PADSpec = 0; + switch (spec) { + case PAD_SPEC_0: + MakeStatus = SPEC0_MakeStatus; + break; + case PAD_SPEC_1: + MakeStatus = SPEC1_MakeStatus; + break; + case PAD_SPEC_2: + case PAD_SPEC_3: + case PAD_SPEC_4: + case PAD_SPEC_5: + MakeStatus = SPEC2_MakeStatus; + break; + } + Spec = spec; +} + +u32 PADGetSpec(void) +{ + return Spec; +} + +static void SPEC0_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) +{ + status->button = 0; + status->button |= ((data[0] >> 16) & 0x0008) ? PAD_BUTTON_A : 0; + status->button |= ((data[0] >> 16) & 0x0020) ? PAD_BUTTON_B : 0; + status->button |= ((data[0] >> 16) & 0x0100) ? PAD_BUTTON_X : 0; + status->button |= ((data[0] >> 16) & 0x0001) ? PAD_BUTTON_Y : 0; + status->button |= ((data[0] >> 16) & 0x0010) ? PAD_BUTTON_START : 0; + status->stickX = (s8)(data[1] >> 16); + status->stickY = (s8)(data[1] >> 24); + status->substickX = (s8)(data[1]); + status->substickY = (s8)(data[1] >> 8); + status->triggerLeft = (u8)(data[0] >> 8); + status->triggerRight = (u8)data[0]; + status->analogA = 0; + status->analogB = 0; + if (170 <= status->triggerLeft) { + status->button |= PAD_TRIGGER_L; + } + if (170 <= status->triggerRight) { + status->button |= PAD_TRIGGER_R; + } + status->stickX -= 128; + status->stickY -= 128; + status->substickX -= 128; + status->substickY -= 128; +} + +static void SPEC1_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) +{ + status->button = 0; + status->button |= ((data[0] >> 16) & 0x0080) ? PAD_BUTTON_A : 0; + status->button |= ((data[0] >> 16) & 0x0100) ? PAD_BUTTON_B : 0; + status->button |= ((data[0] >> 16) & 0x0020) ? PAD_BUTTON_X : 0; + status->button |= ((data[0] >> 16) & 0x0010) ? PAD_BUTTON_Y : 0; + status->button |= ((data[0] >> 16) & 0x0200) ? PAD_BUTTON_START : 0; + + status->stickX = (s8)(data[1] >> 16); + status->stickY = (s8)(data[1] >> 24); + status->substickX = (s8)(data[1]); + status->substickY = (s8)(data[1] >> 8); + + status->triggerLeft = (u8)(data[0] >> 8); + status->triggerRight = (u8)data[0]; + + status->analogA = 0; + status->analogB = 0; + + if (170 <= status->triggerLeft) { + status->button |= PAD_TRIGGER_L; + } + if (170 <= status->triggerRight) { + status->button |= PAD_TRIGGER_R; + } + + status->stickX -= 128; + status->stickY -= 128; + status->substickX -= 128; + status->substickY -= 128; +} + +static s8 ClampS8(s8 var, s8 org) +{ + if (0 < org) { + s8 min = (s8)(-128 + org); + if (var < min) { + var = min; + } + } else if (org < 0) { + s8 max = (s8)(127 + org); + if (max < var) { + var = max; + } + } + return var -= org; +} + +static u8 ClampU8(u8 var, u8 org) +{ + if (var < org) { + var = org; + } + return var -= org; +} + +static void SPEC2_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) +{ + PADStatus* origin; + u32 type; + + status->button = (u16)((data[0] >> 16) & PAD_ALL); + status->stickX = (s8)(data[0] >> 8); + status->stickY = (s8)(data[0]); + + switch (AnalogMode & 0x00000700) { + case 0x00000000: + case 0x00000500: + case 0x00000600: + case 0x00000700: + status->substickX = (s8)(data[1] >> 24); + status->substickY = (s8)(data[1] >> 16); + status->triggerLeft = (u8)(((data[1] >> 12) & 0x0f) << 4); + status->triggerRight = (u8)(((data[1] >> 8) & 0x0f) << 4); + status->analogA = (u8)(((data[1] >> 4) & 0x0f) << 4); + status->analogB = (u8)(((data[1] >> 0) & 0x0f) << 4); + break; + case 0x00000100: + status->substickX = (s8)(((data[1] >> 28) & 0x0f) << 4); + status->substickY = (s8)(((data[1] >> 24) & 0x0f) << 4); + status->triggerLeft = (u8)(data[1] >> 16); + status->triggerRight = (u8)(data[1] >> 8); + status->analogA = (u8)(((data[1] >> 4) & 0x0f) << 4); + status->analogB = (u8)(((data[1] >> 0) & 0x0f) << 4); + break; + case 0x00000200: + status->substickX = (s8)(((data[1] >> 28) & 0x0f) << 4); + status->substickY = (s8)(((data[1] >> 24) & 0x0f) << 4); + status->triggerLeft = (u8)(((data[1] >> 20) & 0x0f) << 4); + status->triggerRight = (u8)(((data[1] >> 16) & 0x0f) << 4); + status->analogA = (u8)(data[1] >> 8); + status->analogB = (u8)(data[1] >> 0); + break; + case 0x00000300: + status->substickX = (s8)(data[1] >> 24); + status->substickY = (s8)(data[1] >> 16); + status->triggerLeft = (u8)(data[1] >> 8); + status->triggerRight = (u8)(data[1] >> 0); + status->analogA = 0; + status->analogB = 0; + break; + case 0x00000400: + status->substickX = (s8)(data[1] >> 24); + status->substickY = (s8)(data[1] >> 16); + status->triggerLeft = 0; + status->triggerRight = 0; + status->analogA = (u8)(data[1] >> 8); + status->analogB = (u8)(data[1] >> 0); + break; + } + + status->stickX -= 128; + status->stickY -= 128; + status->substickX -= 128; + status->substickY -= 128; + + type = Type[chan]; + + if (((Type[chan] & 0xffff0000) == SI_GC_CONTROLLER) && ((status->button & 0x80) ^ 0x80)) { + BarrelBits |= (PAD_CHAN0_BIT >> chan); + status->stickX = 0; + status->stickY = 0; + status->substickX = 0; + status->substickY = 0; + return; + } else { + BarrelBits &= ~(PAD_CHAN0_BIT >> chan); + } + + origin = &Origin[chan]; + status->stickX = ClampS8(status->stickX, origin->stickX); + status->stickY = ClampS8(status->stickY, origin->stickY); + status->substickX = ClampS8(status->substickX, origin->substickX); + status->substickY = ClampS8(status->substickY, origin->substickY); + status->triggerLeft = ClampU8(status->triggerLeft, origin->triggerLeft); + status->triggerRight = ClampU8(status->triggerRight, origin->triggerRight); +} + +BOOL PADGetType(s32 chan, u32* type) +{ + u32 chanBit; + + *type = SIGetType(chan); + chanBit = PAD_CHAN0_BIT >> chan; + if ((ResettingBits & chanBit) || ResettingChan == chan || !(EnabledBits & chanBit)) { + return FALSE; + } + return TRUE; +} + +BOOL PADSync(void) +{ + return ResettingBits == 0 && ResettingChan == 32 && !SIBusy(); +} + +void PADSetAnalogMode(u32 mode) +{ + BOOL enabled; + u32 mask; + + enabled = OSDisableInterrupts(); + AnalogMode = mode << 8; + mask = EnabledBits; + + EnabledBits &= ~mask; + WaitingBits &= ~mask; + CheckingBits &= ~mask; + + SIDisablePolling(mask); + OSRestoreInterrupts(enabled); +} + +static BOOL OnReset(BOOL f) +{ + static BOOL recalibrated = FALSE; + BOOL sync; + + if (SamplingCallback) { + PADSetSamplingCallback(NULL); + } + + if (!f) { + sync = PADSync(); + if (!recalibrated && sync) { + recalibrated = PADRecalibrate(PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT); + return FALSE; + } + return sync; + } else { + recalibrated = FALSE; + } + + return TRUE; +} + +void __PADDisableXPatch(void) +{ + XPatchBits = 0; +} + +static void SamplingHandler(__OSInterrupt interrupt, OSContext* context) +{ + OSContext exceptionContext; + + if (SamplingCallback) { + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + SamplingCallback(); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +PADSamplingCallback PADSetSamplingCallback(PADSamplingCallback callback) +{ + PADSamplingCallback prev; + + prev = SamplingCallback; + SamplingCallback = callback; + if (callback) { + SIRegisterPollingHandler(SamplingHandler); + } else { + SIUnregisterPollingHandler(SamplingHandler); + } + return prev; +} + +BOOL __PADDisableRecalibration(BOOL disable) +{ + BOOL enabled; + BOOL prev; + + enabled = OSDisableInterrupts(); + prev = (__gUnknown800030E3 & 0x40) ? TRUE : FALSE; + __gUnknown800030E3 &= ~0x40; + if (disable) { + __gUnknown800030E3 |= 0x40; + } + OSRestoreInterrupts(enabled); + return prev; +} diff --git a/src/static/GAEJ01_01/dolphin/pad/Padclamp.c b/src/static/GAEJ01_01/dolphin/pad/Padclamp.c new file mode 100644 index 00000000..40ac231e --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/pad/Padclamp.c @@ -0,0 +1,168 @@ +#include +#include +#include + +typedef struct PADClampRegion { + u8 minTrigger; + u8 maxTrigger; + s8 minStick; + s8 maxStick; + s8 xyStick; + s8 minSubstick; + s8 maxSubstick; + s8 xySubstick; + s8 radStick; + s8 radSubstick; +} PADClampRegion; + +static const PADClampRegion ClampRegion = { + // Triggers + 30, + 180, + + // Left stick + 15, + 72, + 40, + + // Right stick + 15, + 59, + 31, + + // Stick radii + 56, + 44, +}; + +void ClampStick(s8* px, s8* py, s8 max, s8 xy, s8 min) +{ + int x = *px; + int y = *py; + int signX; + int signY; + int d; + + if (0 <= x) { + signX = 1; + } else { + signX = -1; + x = -x; + } + + if (0 <= y) { + signY = 1; + } else { + signY = -1; + y = -y; + } + + if (x <= min) { + x = 0; + } else { + x -= min; + } + if (y <= min) { + y = 0; + } else { + y -= min; + } + + if (x == 0 && y == 0) { + *px = *py = 0; + return; + } + + if (xy * y <= xy * x) { + d = xy * x + (max - xy) * y; + if (xy * max < d) { + x = (s8)(xy * max * x / d); + y = (s8)(xy * max * y / d); + } + } else { + d = xy * y + (max - xy) * x; + if (xy * max < d) { + x = (s8)(xy * max * x / d); + y = (s8)(xy * max * y / d); + } + } + + *px = (s8)(signX * x); + *py = (s8)(signY * y); +} + +void ClampCircle(s8* px, s8* py, s8 radius, s8 min) +{ + int x = *px; + int y = *py; + int squared; + int length; + + if (-min < x && x < min) { + x = 0; + } else if (0 < x) { + x -= min; + } else { + x += min; + } + + if (-min < y && y < min) { + y = 0; + } else if (0 < y) { + y -= min; + } else { + y += min; + } + + squared = x * x + y * y; + if (radius * radius < squared) { + length = sqrtf(squared); + x = (x * radius) / length; + y = (y * radius) / length; + } + + *px = x; + *py = y; +} + +inline void ClampTrigger(u8* trigger, u8 min, u8 max) +{ + if (*trigger <= min) { + *trigger = 0; + } else { + if (max < *trigger) { + *trigger = max; + } + *trigger -= min; + } +} + +void PADClamp(PADStatus* status) +{ + int i; + for (i = 0; i < PAD_MAX_CONTROLLERS; i++, status++) { + if (status->err != PAD_ERR_NONE) { + continue; + } + + ClampStick(&status->stickX, &status->stickY, ClampRegion.maxStick, ClampRegion.xyStick, ClampRegion.minStick); + ClampStick(&status->substickX, &status->substickY, ClampRegion.maxSubstick, ClampRegion.xySubstick, ClampRegion.minSubstick); + ClampTrigger(&status->triggerLeft, ClampRegion.minTrigger, ClampRegion.maxTrigger); + ClampTrigger(&status->triggerRight, ClampRegion.minTrigger, ClampRegion.maxTrigger); + } +} + +void PADClampCircle(PADStatus* status) +{ + int i; + for (i = 0; i < 4; ++i, status++) { + if (status->err != PAD_ERR_NONE) { + continue; + } + + ClampCircle(&status->stickX, &status->stickY, ClampRegion.radStick, ClampRegion.minStick); + ClampCircle(&status->substickX, &status->substickY, ClampRegion.radSubstick, ClampRegion.minSubstick); + ClampTrigger(&status->triggerLeft, ClampRegion.minTrigger, ClampRegion.maxTrigger); + ClampTrigger(&status->triggerRight, ClampRegion.minTrigger, ClampRegion.maxTrigger); + } +} diff --git a/src/static/GAEJ01_01/dolphin/si/SIBios.c b/src/static/GAEJ01_01/dolphin/si/SIBios.c new file mode 100644 index 00000000..35fb7332 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/si/SIBios.c @@ -0,0 +1,784 @@ +#include +#include +#include +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +const char* __SIVersion = "<< Dolphin SDK - SI\trelease build: Apr 17 2003 12:33:19 (0x2301) >>"; + +static SIControl Si = { + /* chan */ -1, + /* poll */ 0, + /* inputBytes*/ 0, + /* input */ NULL, + /* callback */ NULL +}; + +static struct SIPacket Packet[4]; +static struct OSAlarm Alarm[4]; +static u32 Type[4] = { 0x08, 0x08, 0x08, 0x08 }; +static OSTime TypeTime[4]; +static OSTime XferTime[4]; +static SITypeCallback TypeCallback[4][4]; +static __OSInterruptHandler RDSTHandler[4]; +static BOOL InputBufferValid[4]; +static u32 InputBuffer[4][2]; +static volatile u32 InputBufferVcount[4]; + +u32 __PADFixBits; + +static u32 CompleteTransfer(); +static void SITransferNext(long chan); +static void SIInterruptHandler(s16 interrupt, OSContext* context); +static int __SITransfer(long chan, void* output, u32 outputBytes, void* input, u32 inputBytes, void (* callback)(long, u32, struct OSContext *)); +static void AlarmHandler(struct OSAlarm* alarm, struct OSContext* context); +static void GetTypeCallback(s32 chan, u32 error, OSContext* context); +static int SIGetResponseRaw(s32 chan); + +BOOL SIBusy() { + return (Si.chan != -1) ? TRUE : FALSE; +} + +BOOL SIIsChanBusy(s32 chan) { + return Packet[chan].chan != -1 || Si.chan == chan; +} + +static void SIClearTCInterrupt(void) { + u32 reg; + + reg = __SIRegs[SI_COMCSR_IDX]; + reg |= SI_COMCSR_TCINT_MASK; + reg &= ~SI_COMCSR_TSTART_MASK; + __SIRegs[SI_COMCSR_IDX] = reg; +} + +static u32 CompleteTransfer() { + u32 sr; + u32 i; + u32 rLen; + u8* input; + u32 temp; + + sr = __SIRegs[SI_STATUS_IDX]; + SIClearTCInterrupt(); + + if (Si.chan != -1) { + XferTime[Si.chan] = __OSGetSystemTime(); + input = Si.input; + rLen = Si.inputBytes / sizeof(u32); + for(i = 0; i < rLen; i++) { + *((u32*)input)++ = __SIRegs[i+0x20]; + } + + rLen = Si.inputBytes & 3; + if (rLen != 0) { + temp = __SIRegs[i + 32]; + for(i = 0; i < rLen; i++) { + *(input++) = temp >> ((3 - i)* 8); + } + } + + if (__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_COMERR_MASK) { + sr >>= (3 - Si.chan) * 8; + sr &= 0xF; + if ((sr & 8) != 0 && (Type[Si.chan] & 0x80) == 0) { + Type[Si.chan] = 8; + } + + if (sr == 0) { + sr = 4; + } + } else { + TypeTime[Si.chan] = __OSGetSystemTime(); + sr = 0; + } + + Si.chan = -1; + } + + return sr; +} + +static void SITransferNext(long chan) { + int i; + struct SIPacket* packet; + + for(i = 0; i < 4; i++) { + chan++; + chan %= 4; + packet = &Packet[chan]; + + if (packet->chan != -1) { + if (packet->fire <= __OSGetSystemTime()) { + if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback) != 0) { + OSCancelAlarm(&Alarm[chan]); + packet->chan = -1; + } + return; + } + } + } +} + +static void SIInterruptHandler(s16 interrupt, OSContext* context) { + u32 reg; + s32 chan; + u32 sr; + SICallback callback; + int i; + u32 vcount; + u32 x; + + reg = __SIRegs[SI_COMCSR_IDX]; + if ((reg & (SI_COMCSR_TCINT_MASK | SI_COMCSR_TCINTMSK_MASK)) == (SI_COMCSR_TCINT_MASK | SI_COMCSR_TCINTMSK_MASK)) { + ASSERTLINE(366, Si.chan != CHAN_NONE); + + chan = Si.chan; + sr = CompleteTransfer(); + callback = Si.callback; + Si.callback = NULL; + SITransferNext(chan); + + if (callback) { + callback(chan, sr, context); + } + + sr = __SIRegs[SI_STATUS_IDX]; + sr &= 0x0F000000 >> (chan << 3); + __SIRegs[SI_STATUS_IDX] = sr; + + if (Type[chan] == SI_ERROR_BUSY && !SIIsChanBusy(chan)) { + static u32 cmdTypeAndStatus; + + SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, &GetTypeCallback, OSMicrosecondsToTicks(65)); + } + } + + if ((reg & (SI_COMCSR_RDSTINT_MASK | SI_COMCSR_RDSTINTMSK_MASK)) == (SI_COMCSR_RDSTINT_MASK | SI_COMCSR_RDSTINTMSK_MASK)) { + vcount = 1 + VIGetCurrentLine(); + x = (Si.poll & (0x3FF << 16)) >> 16; + + for (i = 0; i < 4; i++) { + if (SIGetResponseRaw(i)) { + InputBufferVcount[i] = vcount; + } + } + + for (i = 0; i < 4; i++) { + if ((Si.poll & (0x80000000 >> (24 + i))) != 0) { + if (InputBufferVcount[i] == 0 || ((x >> 1) + InputBufferVcount[i]) < vcount) { + return; + } + } + } + + for (i = 0; i < 4; i++) { + InputBufferVcount[i] = 0; + } + + for (i = 0; i < 4; i++) { + if (RDSTHandler[i] != 0) { + (*RDSTHandler[i])(interrupt, context); + } + } + } +} + +static BOOL SIEnablePollingInterrupt(BOOL enable) { + BOOL enabled; + BOOL rc; + u32 reg; + int i; + + enabled = OSDisableInterrupts(); + reg = __SIRegs[SI_COMCSR_IDX]; + rc = ((reg & SI_COMCSR_RDSTINTMSK_MASK) != 0) ? TRUE : FALSE; + + if (enable) { + reg |= SI_COMCSR_RDSTINTMSK_MASK; + + for (i = 0; i < 4; i++) { + InputBufferVcount[i] = 0; + } + } else { + reg &= ~SI_COMCSR_RDSTINTMSK_MASK; + } + + reg &= ~(SI_COMCSR_TCINT_MASK | SI_COMCSR_TSTART_MASK); + __SIRegs[SI_COMCSR_IDX] = 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] != 0) { + break; + } + } + + if (i == 4) { + SIEnablePollingInterrupt(FALSE); + } + + OSRestoreInterrupts(enabled); + return TRUE; + } + } + + OSRestoreInterrupts(enabled); + return FALSE; +} + +void SIInit() { + OSRegisterVersion(__SIVersion); + + Packet[0].chan = Packet[1].chan = Packet[2].chan = Packet[3].chan = -1; + Si.poll = 0; + SISetSamplingRate(0); + do {} while(__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_TSTART_MASK); + __SIRegs[SI_COMCSR_IDX] = SI_COMCSR_TCINT_MASK; + __OSSetInterruptHandler(0x14, SIInterruptHandler); + __OSUnmaskInterrupts(0x800); + SIGetType(0); + SIGetType(1); + SIGetType(2); + SIGetType(3); +} + +static int __SITransfer(long chan, void* output, u32 outputBytes, void* input, u32 inputBytes, void (* callback)(long, u32, struct OSContext *)) { + int enabled; + u32 rLen; + u32 i; + u32 sr; + union { + u32 val; + struct { + u32 tcint : 1; + u32 tcintmsk : 1; + u32 comerr : 1; + u32 rdstint : 1; + u32 rdstintmsk : 1; + u32 pad2 : 4; + u32 outlngth : 7; + u32 pad1 : 1; + u32 inlngth : 7; + u32 pad0 : 5; + u32 channel : 2; + u32 tstart : 1; + } f; + } comcsr; + + ASSERTMSGLINE(615, (chan >= 0) && (chan < 4), "SITransfer(): invalid channel."); + ASSERTMSGLINE(617, (outputBytes != 0) && (outputBytes <= 128), "SITransfer(): output size is out of range (must be 1 to 128)."); + ASSERTMSGLINE(619, (inputBytes != 0) && (inputBytes <= 128), "SITransfer(): input size is out of range (must be 1 to 128)."); + + enabled = OSDisableInterrupts(); + if (Si.chan != -1) { + OSRestoreInterrupts(enabled); + return 0; + } + ASSERTLINE(629, (__SIRegs[SI_COMCSR_IDX] & (SI_COMCSR_TSTART_MASK | SI_COMCSR_TCINT_MASK)) == 0); + sr = __SIRegs[SI_STATUS_IDX]; + sr &= (0x0F000000 >> (chan* 8)); + __SIRegs[SI_STATUS_IDX] = 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[i+0x20] = ((u32*)output)[i]; + } + + comcsr.val = __SIRegs[SI_COMCSR_IDX]; + comcsr.f.tcint = 1; + comcsr.f.tcintmsk = callback ? 1 : 0; + comcsr.f.outlngth = outputBytes == 0x80 ? 0 : outputBytes; + comcsr.f.inlngth = inputBytes == 0x80 ? 0 : inputBytes; + comcsr.f.channel = chan; + comcsr.f.tstart = 1; + + __SIRegs[SI_COMCSR_IDX] = comcsr.val; + OSRestoreInterrupts(enabled); + return 1; +} + +u32 SISync() { + int enabled; // r31 + u32 sr; // r30 + + do {} while(__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_TSTART_MASK); + + enabled = OSDisableInterrupts(); + sr = CompleteTransfer(); + SITransferNext(4); + OSRestoreInterrupts(enabled); + return sr; +} + +u32 SIGetStatus(s32 chan) { + BOOL enabled; + u32 sr; + int chanShift; + + enabled = OSDisableInterrupts(); + sr = __SIRegs[SI_STATUS_IDX]; + chanShift = (3 - chan) * 8; + sr >>= chanShift; + + if ((sr & 8) != 0) { + if ((Type[chan] & SI_ERROR_BUSY) == 0) { + Type[chan] = 8; + } + } + + OSRestoreInterrupts(enabled); + return sr; +} + +void SISetCommand(long chan, u32 command) { + ASSERTMSGLINE(740, (chan >= 0) && (chan < 4), "SISetCommand(): invalid channel."); + __SIRegs[chan* 3] = command; +} + +u32 SIGetCommand(long chan) { + ASSERTMSGLINE(758, (chan >= 0) && (chan < 4), "SIGetCommand(): invalid channel."); + return __SIRegs[chan* 3]; +} + +void SITransferCommands() { + __SIRegs[SI_STATUS_IDX] = SI_COMCSR_TCINT_MASK; +} + +u32 SISetXY(u32 x, u32 y) { + u32 poll; + int enabled; + + ASSERTMSGLINE(791, x >= 8, "SISetXY(): x is out of range (8 <= x <= 1023)."); + ASSERTMSGLINE(792, x <= 1023, "SISetXY(): x is out of range (8 <= x <= 1023)."); + ASSERTMSGLINE(793, y <= 255, "SISetXY(): y is out of range (0 <= y <= 255)."); + + poll = x << 0x10; + poll |= y << 8; + enabled = OSDisableInterrupts(); + Si.poll &= 0xFC0000FF; + Si.poll |= poll; + poll = Si.poll; + __SIRegs[0x30/4] = poll; + OSRestoreInterrupts(enabled); + return poll; +} + +u32 SIEnablePolling(u32 poll) { + int enabled; + u32 en; + + ASSERTMSGLINE(822, (poll & 0x0FFFFFFF) == 0, "SIEnablePolling(): invalid chan bit(s)."); + if (poll == 0) { + return Si.poll; + } + + enabled = OSDisableInterrupts(); + poll = poll >> 24; + en = poll & 0xF0; + ASSERTLINE(853, en); + poll &= ((en >> 4) | 0x03FFFFF0); + poll &= 0xFC0000FF; + + Si.poll &= ~(en >> 4); + Si.poll |= poll; + poll = Si.poll; + SITransferCommands(); + __SIRegs[0x30/4] = poll; + OSRestoreInterrupts(enabled); + return poll; +} + +u32 SIDisablePolling(u32 poll) { + int enabled; + + ASSERTMSGLINE(896, (poll & 0x0FFFFFFF) == 0, "SIDisablePolling(): invalid chan bit(s)."); + if (poll == 0) { + return Si.poll; + } + enabled = OSDisableInterrupts(); + poll = poll >> 24; + poll &= 0xF0; + ASSERTLINE(909, poll); + poll = Si.poll & ~poll; + __SIRegs[0x30/4] = poll; + Si.poll = poll; + OSRestoreInterrupts(enabled); + return poll; +} + +static BOOL SIGetResponseRaw(s32 chan) { + u32 sr; + + sr = SIGetStatus(chan); + if (sr & 0x20) { + InputBuffer[chan][0] = __SIRegs[1 + chan * 3]; + InputBuffer[chan][1] = __SIRegs[2 + chan * 3]; + InputBufferValid[chan] = TRUE; + return TRUE; + } + + return FALSE; +} + +BOOL SIGetResponse(s32 chan, void* data) { + BOOL rc; + BOOL enabled; + + ASSERTMSGLINE(959, ((chan >= 0) && (chan < 4)), "SIGetResponse(): invalid channel."); + 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) { + s32 chan; + SIPacket* packet; + + chan = (s32)(alarm - Alarm); + ASSERTLINE(990, 0 <= chan && chan < SI_MAX_CHAN); + + packet = &Packet[chan]; + if (packet->chan != -1) { + ASSERTLINE(994, packet->fire <= __OSGetSystemTime()); + + 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; + OSTime now; + OSTime fire; + + packet = &Packet[chan]; + enabled = OSDisableInterrupts(); + + if (packet->chan != -1 || Si.chan == chan) { + OSRestoreInterrupts(enabled); + return FALSE; + } + + now = __OSGetSystemTime(); + if (delay == 0) { + fire = now; + } else { + fire = delay + XferTime[chan]; + } + + 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) { + SITypeCallback callback; + int i; + + for (i = 0; i < 4; i++) { + callback = TypeCallback[chan][i]; + + if (callback != 0) { + TypeCallback[chan][i] = 0; + (*callback)(chan, type); + } + } +} + +static void GetTypeCallback(s32 chan, u32 error, OSContext* context) { + u32 type; + u32 chanBit; + int fix; + u32 id; + + ASSERTLINE(1125, 0 <= chan && chan < SI_MAX_CHAN); + + ASSERTLINE(1127, (Type[chan] & 0xff) == SI_ERROR_BUSY); + Type[chan] &= ~SI_ERROR_BUSY; + Type[chan] |= error; + TypeTime[chan] = __OSGetSystemTime(); + + type = Type[chan]; + chanBit = 0x80000000 >> chan; + fix = __PADFixBits & chanBit; + __PADFixBits &= ~chanBit; + + if ((error & 0xF) != 0 || (type & 0x18000000) != 0x08000000 || (type & 0x80000000) == 0 || (type & 0x04000000) != 0) { + OSSetWirelessID(chan, 0); + CallTypeAndStatusCallback(chan, Type[chan]); + } else { + static u32 cmdFixDevice[4]; + + id = OSGetWirelessID(chan) << 8; + + if (fix != 0 && (id & 0x100000) != 0) { + cmdFixDevice[chan] = 0x4E000000 | (id & 0xCFFF00) | 0x100000; + Type[chan] = SI_ERROR_BUSY; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0); + return; + } + + if ((type & 0x00100000) != 0) { + if ((id & 0xCFFF00) != (type & 0xCFFF00)) { + if ((id & 0x100000) == 0) { + id = type & 0xCFFF00; + id |= 0x100000; + OSSetWirelessID(chan, id >> 8); + } + + cmdFixDevice[chan] = 0x4E000000 | id; + Type[chan] = SI_ERROR_BUSY; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0); + return; + } + } else { + if ((type & 0x40000000) != 0) { + id = type & 0xCFFF00; + id |= 0x100000; + OSSetWirelessID(chan, id >> 8); + + cmdFixDevice[chan] = 0x4E000000 | id; + Type[chan] = SI_ERROR_BUSY; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0); + return; + } + + OSSetWirelessID(chan, 0); + } + + CallTypeAndStatusCallback(chan, Type[chan]); + } +} + +u32 SIGetType(s32 chan) { + static u32 cmdTypeAndStatus; + BOOL enabled; + u32 type; + OSTime diff; + + enabled = OSDisableInterrupts(); + ASSERTLINE(1231, 0 <= chan && chan < SI_MAX_CHAN); + type = Type[chan]; + diff = __OSGetSystemTime() - TypeTime[chan]; + if ((Si.poll & (0x80 >> chan)) != 0) { + if (type != 8) { + TypeTime[chan] = __OSGetSystemTime(); + OSRestoreInterrupts(enabled); + return type; + } + + type = Type[chan] = SI_ERROR_BUSY; + } else { + if (diff <= OSMillisecondsToTicks(50) && type != 8) { + OSRestoreInterrupts(enabled); + return type; + } + + 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, SITypeCallback callback) { + BOOL enabled; + u32 type; + int i; + + enabled = OSDisableInterrupts(); + type = SIGetType(chan); + + if ((Type[chan] & SI_ERROR_BUSY) != 0) { + for (i = 0; i < SI_MAX_TYPE; i++) { + if (TypeCallback[chan][i] == callback) { + break; + } + + if (TypeCallback[chan][i] == 0) { + TypeCallback[chan][i] = callback; + break; + } + } + + ASSERTLINE(1312, i < SI_MAX_TYPE); + } else { + (*callback)(chan, type); + } + + OSRestoreInterrupts(enabled); + return type; +} + +static u32 SIDecodeType(u32 type) { + u32 error; + + error = type & 0xFF; + type &= ~0xFF; + + if (error & 8) { + return 8; + } + + if (error & 0x47) { + return 0x40; + } + + if (error != 0) { + ASSERTLINE(1359, error == SI_ERROR_BUSY); + return SI_ERROR_BUSY; + } + + if ((type & 0x18000000) == 0) { + switch (type & 0xFFFF0000) { + case 0x10000: + case 0x20000: + case 0x40000: + case 0x2000000: + case 0x5000000: + return type & 0xFFFF0000; + default: + return 0x40; + } + } + + if ((type & 0x18000000) != 0x08000000) { + return 0x40; + } + + switch (type & 0xFFFF0000) { + case 0x8000000: + case 0x9000000: + return type & 0xFFFF0000; + } + + if ((type & 0xFFE00000) == 0x8200000) { + return 0x8200000; + } + + if ((type & 0x80000000) != 0 && (type & 0x4000000) == 0) { + if ((type & 0x8B100000) == 0x8B100000) { + return 0x8B100000; + } + + if ((type & 0x2000000) == 0) { + return 0x88000000; + } + } + + if ((type & 0x9000000) == 0x9000000) { + return 0x9000000; + } + + return 0x40; +} + +u32 SIProbe(s32 chan) { + return SIDecodeType(SIGetType(chan)); +} + +char* SIGetTypeString(u32 type) { + switch (SIDecodeType(type)) { + case 0x00000008: + return "No response"; + case SI_ERROR_BUSY: + return "Busy"; + case 0x05000000: + return "N64 controller"; + case 0x00010000: + return "N64 microphone"; + case 0x00020000: + return "N64 keyboard"; + case 0x02000000: + return "N64 mouse"; + case 0x00040000: + return "GameBoy Advance"; + case 0x09000000: + return "Standard controller"; + case 0x88000000: + return "Wireless receiver"; + case 0x8B100000: + return "WaveBird controller"; + case 0x08200000: + return "Keyboard"; + case 0x08000000: + return "Steering"; + case 0x40: + default: + return "Unknown"; + } +} diff --git a/src/static/GAEJ01_01/dolphin/si/SISamplingRate.c b/src/static/GAEJ01_01/dolphin/si/SISamplingRate.c new file mode 100644 index 00000000..42a589c7 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/si/SISamplingRate.c @@ -0,0 +1,124 @@ +#include +#include +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" + +#define LATENCY 8 + +static u32 SamplingRate = 0; + +typedef struct XY { + u16 line; + u8 count; +} XY; + +static XY XYNTSC[12] = { + {0x00F6, 0x02}, + {0x000F, 0x12}, + {0x001E, 0x09}, + {0x002C, 0x06}, + {0x0034, 0x05}, + {0x0041, 0x04}, + {0x0057, 0x03}, + {0x0057, 0x03}, + {0x0057, 0x03}, + {0x0083, 0x02}, + {0x0083, 0x02}, + {0x0083, 0x02}, +}; + +static XY XYPAL[12] = { + {0x0128, 0x02}, + {0x000F, 0x15}, + {0x001D, 0x0B}, + {0x002D, 0x07}, + {0x0034, 0x06}, + {0x003F, 0x05}, + {0x004E, 0x04}, + {0x0068, 0x03}, + {0x0068, 0x03}, + {0x0068, 0x03}, + {0x0068, 0x03}, + {0x009C, 0x02}, +}; + +void SISetSamplingRate(u32 msec) { + XY* xy; + BOOL progressive; + BOOL enabled; + + ASSERTMSGLINE(374, 0 <= msec && msec <= 11, "SISetSamplingRate(): out of rage (0 <= msec <= 11)"); + 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; + } + + progressive = __VIRegs[VI_CLOCK_SEL] & 1; + SISetXY((progressive ? 2 : 1) * xy[msec].line, xy[msec].count); + OSRestoreInterrupts(enabled); +} + +void SIRefreshSamplingRate(void) { + SISetSamplingRate(SamplingRate); +} + +#if DEBUG +void __SITestSamplingRate(u32 tvmode) { + u32 msec; + u32 line; + u32 count; + XY* xy; + + switch (tvmode) { + case VI_NTSC: + case VI_MPAL: + xy = XYNTSC; + for (msec = 0; msec <= 11; msec++) { + line = xy[msec].line; + count = xy[msec].count; + OSReport("%2d[msec]: count %3d, line %3d, last %3d, diff0 %2d.%03d, diff1 %2d.%03d\n", + msec, count, line, line * (count - 1) + LATENCY, (line * 636) / 10000, (line * 636) % 10000, + ((263 - line * (count - 1)) * 636) / 10000, ((263 - line * (count - 1)) * 636) % 10000); + ASSERTLINE(443, line * (count - 1) + LATENCY < 263); + + if (msec != 0) { + ASSERTLINE(446, 636 * line < msec * 10000); + ASSERTLINE(447, 636 * (263 - line * (count - 1)) < msec * 10000); + } + } + break; + case VI_PAL: + xy = XYPAL; + for (msec = 0; msec <= 11; msec++) { + line = xy[msec].line; + count = xy[msec].count; + OSReport("%2d[msec]: count %3d, line %3d, last %3d, diff0 %2d.%03d, diff1 %2d.%03d\n", + msec, count, line, line * (count - 1) + LATENCY, (line * 640) / 10000, (line * 640) % 10000, + ((313 - line * (count - 1)) * 640) / 10000, ((313 - line * (count - 1)) * 640) % 10000); + ASSERTLINE(467, line * (count - 1) + LATENCY < 313); + + if (msec != 0) { + ASSERTLINE(470, 640 * line < msec * 10000); + ASSERTLINE(471, 640 * (313 - line * (count - 1)) < msec * 10000); + } + } + break; + } +} +#endif diff --git a/src/static/GAEJ01_01/dolphin/vi/__vi.h b/src/static/GAEJ01_01/dolphin/vi/__vi.h new file mode 100644 index 00000000..4dcf1c39 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/vi/__vi.h @@ -0,0 +1,100 @@ +#ifndef _DOLPHIN_VI_INTERNAL_H_ +#define _DOLPHIN_VI_INTERNAL_H_ + +#include + +#define VI_3D 3 +#define VI_GCA 6 + +#define VI_TVMODE_NTSC_3D VI_TVMODE(VI_NTSC, VI_3D) +#define VI_TVMODE_GCA_INT VI_TVMODE(VI_GCA, VI_INTERLACE) +#define VI_TVMODE_GCA_DS VI_TVMODE(VI_GCA, VI_NON_INTERLACE) +#define VI_TVMODE_GCA_PROG VI_TVMODE(VI_GCA, VI_PROGRESSIVE) + +typedef void (*VIPositionCallback)(s16 x, s16 y); + +typedef struct VITimingInfo { + u8 equ; // _00 + u16 acv; // _02 + u16 prbOdd; // _04 + u16 prbEven; // _06 + u16 psbOdd; // _08 + u16 psbEven; // _0A + u8 bs1; // _0C + u8 bs2; // _0D + u8 bs3; // _0E + u8 bs4; // _0F + u16 be1; // _10 + u16 be2; // _12 + u16 be3; // _14 + u16 be4; // _16 + u16 numHalfLines; // _18 + u16 hlw; // _1A + u8 hsy; // _1C + u8 hcs; // _1D + u8 hce; // _1E + u8 hbe640; // _1F + u16 hbs640; // _20 + u8 hbeCCIR656; // _24 + u16 hbsCCIR656; // _26 +} VITimingInfo; + +typedef struct VIPositionInfo { + u16 dispPosX; // _00 + u16 dispPosY; // _02 + u16 dispSizeX; // _04 + u16 dispSizeY; // _06 + u16 adjDispPosX; // _08 + u16 adjDispPosY; // _0A + u16 adjDispSizeY; // _0C + u16 adjPanPosY; // _0E + u16 adjPanSizeY; // _10 + u16 fbSizeX; // _12 + u16 fbSizeY; // _14 + u16 panPosX; // _16 + u16 panPosY; // _18 + u16 panSizeX; // _1A + u16 panSizeY; // _1C + VIXFBMode xfbMode; // _20 + u32 nonInter; // _24 + u32 tv; // _28 + u8 wordPerLine; // _2C + u8 std; // _2D + u8 wpl; // _2E + u32 bufAddr; // _30 + u32 tfbb; // _34 + u32 bfbb; // _38 + u8 xof; // _3C + BOOL isBlack; // _40 + BOOL is3D; // _44 + u32 rbufAddr; // _48 + u32 rtfbb; // _4C + u32 rbfbb; // _50 + VITimingInfo* timing; // _54 +} VIPositionInfo; + +/* gpioexi.c */ + +void __VIInitI2C(void); +void __VISetSCL(int value); +int __VIGetSCL(void); +void __VISetSDA(int value); +int __VIGetSDA(void); + +/* i2c.c */ + +int __VISendI2CData(u8 slaveAddr, u8* pData, int nBytes); + +/* initphilips.c */ + +void __VIInitPhilips(void); + +/* vi.c */ + +void __VIInit(VITVMode mode); +void __VISetAdjustingValues(s16 x, s16 y); +void __VIGetAdjustingValues(s16* x, s16* y); +void __VIGetCurrentPosition(s16* x, s16* y); +void __VIDisplayPositionToXY(u32 hcount, u32 vcount, s16* x, s16* y); + +#endif diff --git a/src/static/GAEJ01_01/dolphin/vi/vi.c b/src/static/GAEJ01_01/dolphin/vi/vi.c new file mode 100644 index 00000000..f197fae8 --- /dev/null +++ b/src/static/GAEJ01_01/dolphin/vi/vi.c @@ -0,0 +1,1063 @@ +#include +#include +#include +#include +#include + +#include "../src/static/GAEJ01_01/dolphin/os/__os.h" +#include "../src/static/GAEJ01_01/dolphin/vi/__vi.h" + +// Useful macros. +#define CLAMP(x, l, h) (((x) > (h)) ? (h) : (((x) < (l)) ? (l) : (x))) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define IS_LOWER_16MB(x) ((x) < 16 * 1024 * 1024) +#define ToPhysical(fb) (u32)(((u32)(fb)) & 0x3FFFFFFF) +#define ONES(x) ((1 << (x)) - 1) +#define VI_BITMASK(index) (1ull << (63 - (index))) + +const char* __VIVersion = "<< Dolphin SDK - VI\trelease build: Apr 17 2003 12:33:22 (0x2301) >>"; + +static BOOL IsInitialized; +static vu32 retraceCount; +static u32 flushFlag; +static OSThreadQueue retraceQueue; +static VIRetraceCallback PreCB; +static VIRetraceCallback PostCB; +static VIPositionCallback PositionCallback; +static u32 encoderType; + +static s16 displayOffsetH; +static s16 displayOffsetV; + +static vu32 changeMode; +static vu64 changed; + +static vu32 shdwChangeMode; +static vu64 shdwChanged; + +static VITimingInfo* CurrTiming; +static u32 CurrTvMode; + +static u32 NextBufAddr; +static u32 CurrBufAddr; + +static u32 FBSet; + +static vu16 regs[59]; +static vu16 shdwRegs[59]; + +static VIPositionInfo HorVer; +// clang-format off +static VITimingInfo timing[10] = { + { // NTSC INT + 6, 240, 24, 25, 3, 2, 12, 13, 12, 13, 520, 519, 520, 519, 525, 429, 64, 71, 105, 162, 373, 122, 412, + }, + { // NTSC DS + 6, 240, 24, 24, 4, 4, 12, 12, 12, 12, 520, 520, 520, 520, 526, 429, 64, 71, 105, 162, 373, 122, 412, + }, + { // PAL INT + 5, 287, 35, 36, 1, 0, 13, 12, 11, 10, 619, 618, 617, 620, 625, 432, 64, 75, 106, 172, 380, 133, 420, + }, + { // PAL DS + 5, 287, 33, 33, 2, 2, 13, 11, 13, 11, 619, 621, 619, 621, 624, 432, 64, 75, 106, 172, 380, 133, 420, + }, + { // MPAL INT + 6, 240, 24, 25, 3, 2, 16, 15, 14, 13, 518, 517, 516, 519, 525, 429, 64, 78, 112, 162, 373, 122, 412, + }, + { // MPAL DS + 6, 240, 24, 24, 4, 4, 16, 14, 16, 14, 518, 520, 518, 520, 526, 429, 64, 78, 112, 162, 373, 122, 412, + }, + { // NTSC PRO + 12, 480, 48, 48, 6, 6, 24, 24, 24, 24, 1038, 1038, 1038, 1038, 1050, 429, 64, 71, 105, 162, 373, 122, 412, + }, + { // NTSC 3D + 12, 480, 44, 44, 10, 10, 24, 24, 24, 24, 1038, 1038, 1038, 1038, 1050, 429, 64, 71, 105, 168, 379, 122, 412, + }, + { // GCA INT + 6, 241, 24, 25, 1, 0, 12, 13, 12, 13, 520, 519, 520, 519, 525, 429, 64, 71, 105, 159, 370, 122, 412, + }, + { // GCA DS + 12, 480, 48, 48, 6, 6, 24, 24, 24, 24, 1038, 1038, 1038, 1038, 1050, 429, 64, 71, 105, 180, 391, 122, 412, + }, +}; +// clang-format on + +static u16 taps[25] = { 496, 476, 430, 372, 297, 219, 142, 70, 12, 226, 203, 192, 196, 207, 222, 236, 252, 8, 15, 19, 19, 15, 12, 8, 1 }; + +// forward declaring statics +static u32 getCurrentFieldEvenOdd(); + + +static int cntlzd(u64 bit) +{ + u32 hi, lo; + int value; + + hi = (u32)(bit >> 32); + lo = (u32)(bit & 0xFFFFFFFF); + value = __cntlzw(hi); + + if (value < 32) { + return value; + } + + return (32 + __cntlzw(lo)); +} + +static BOOL VISetRegs(void) +{ + int regIndex; + + if (!((shdwChangeMode == 1) && (getCurrentFieldEvenOdd() == 0))) { + while (shdwChanged) { + regIndex = cntlzd(shdwChanged); + __VIRegs[regIndex] = shdwRegs[regIndex]; + shdwChanged &= ~(VI_BITMASK(regIndex)); + } + + shdwChangeMode = 0; + CurrTiming = HorVer.timing; + CurrTvMode = HorVer.tv; + CurrBufAddr = NextBufAddr; + + return TRUE; + } + return FALSE; +} + +static void __VIRetraceHandler(__OSInterrupt interrupt, OSContext* context) +{ + OSContext exceptionContext; + u16 viReg; + u32 inter = 0; + + viReg = __VIRegs[VI_DISP_INT_0]; + if (viReg & 0x8000) { + __VIRegs[VI_DISP_INT_0] = (u16)(viReg & ~0x8000); + inter |= 1; + } + + viReg = __VIRegs[VI_DISP_INT_1]; + if (viReg & 0x8000) { + __VIRegs[VI_DISP_INT_1] = (u16)(viReg & ~0x8000); + inter |= 2; + } + + viReg = __VIRegs[VI_DISP_INT_2]; + if (viReg & 0x8000) { + __VIRegs[VI_DISP_INT_2] = (u16)(viReg & ~0x8000); + inter |= 4; + } + + viReg = __VIRegs[VI_DISP_INT_3]; + if (viReg & 0x8000) { + __VIRegs[VI_DISP_INT_3] = (u16)(viReg & ~0x8000); + inter |= 8; + } + + if ((inter & 4) || (inter & 8)) { + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + if (PositionCallback) { + s16 x, y; + __VIGetCurrentPosition(&x, &y); + (*PositionCallback)(x, y); + } + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + return; + } + + retraceCount++; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + if (PreCB) { + (*PreCB)(retraceCount); + } + + if (flushFlag) { + if (VISetRegs()) { + flushFlag = 0; + SIRefreshSamplingRate(); + } + } + + if (PostCB) { + OSClearContext(&exceptionContext); + (*PostCB)(retraceCount); + } + + OSWakeupThread(&retraceQueue); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +VIRetraceCallback VISetPreRetraceCallback(VIRetraceCallback callback) +{ + int interrupt; + VIRetraceCallback oldCallback; + + oldCallback = PreCB; + + interrupt = OSDisableInterrupts(); + PreCB = callback; + OSRestoreInterrupts(interrupt); + + return oldCallback; +} + +VIRetraceCallback VISetPostRetraceCallback(VIRetraceCallback callback) +{ + int interrupt; + VIRetraceCallback oldCallback; + + oldCallback = PostCB; + + interrupt = OSDisableInterrupts(); + PostCB = callback; + OSRestoreInterrupts(interrupt); + + return oldCallback; +} + +static VITimingInfo* getTiming(VITVMode mode) +{ + switch (mode) { + case VI_TVMODE_NTSC_INT: + return &timing[0]; + case VI_TVMODE_NTSC_DS: + return &timing[1]; + + case VI_TVMODE_PAL_INT: + return &timing[2]; + case VI_TVMODE_PAL_DS: + return &timing[3]; + + case VI_TVMODE_EURGB60_INT: + return &timing[0]; + case VI_TVMODE_EURGB60_DS: + return &timing[1]; + + case VI_TVMODE_MPAL_INT: + return &timing[4]; + case VI_TVMODE_MPAL_DS: + return &timing[5]; + + case VI_TVMODE_NTSC_PROG: + return &timing[6]; + case VI_TVMODE_NTSC_3D: + return &timing[7]; + + case VI_TVMODE_DEBUG_PAL_INT: + return &timing[2]; + case VI_TVMODE_DEBUG_PAL_DS: + return &timing[3]; + + case VI_TVMODE_GCA_INT: + return &timing[8]; + case VI_TVMODE_GCA_PROG: + return &timing[9]; + } + + return NULL; +} + +void __VIInit(VITVMode mode) +{ + VITimingInfo* tm; + u32 nonInter; + vu32 a; + u32 tv, tvForReg; + + u16 hct, vct; + + nonInter = mode & 2; + tv = (u32)mode >> 2; + + *(u32*)OSPhysicalToCached(0xCC) = tv; + + tm = getTiming(mode); + + __VIRegs[VI_DISP_CONFIG] = 2; + for (a = 0; a < 1000; a++) { + ; + } + + __VIRegs[VI_DISP_CONFIG] = 0; + + __VIRegs[VI_HORIZ_TIMING_0U] = tm->hlw << 0; + __VIRegs[VI_HORIZ_TIMING_0L] = (tm->hce << 0) | (tm->hcs << 8); + + __VIRegs[VI_HORIZ_TIMING_1U] = (tm->hsy << 0) | ((tm->hbe640 & ((1 << 9) - 1)) << 7); + __VIRegs[VI_HORIZ_TIMING_1L] = ((tm->hbe640 >> 9) << 0) | (tm->hbs640 << 1); + + __VIRegs[VI_VERT_TIMING] = (tm->equ << 0) | (0 << 4); + + __VIRegs[VI_VERT_TIMING_ODD_U] = (tm->prbOdd + tm->acv * 2 - 2) << 0; + __VIRegs[VI_VERT_TIMING_ODD] = tm->psbOdd + 2 << 0; + + __VIRegs[VI_VERT_TIMING_EVEN_U] = (tm->prbEven + tm->acv * 2 - 2) << 0; + __VIRegs[VI_VERT_TIMING_EVEN] = tm->psbEven + 2 << 0; + + __VIRegs[VI_BBI_ODD_U] = (tm->bs1 << 0) | (tm->be1 << 5); + __VIRegs[VI_BBI_ODD] = (tm->bs3 << 0) | (tm->be3 << 5); + + __VIRegs[VI_BBI_EVEN_U] = (tm->bs2 << 0) | (tm->be2 << 5); + __VIRegs[VI_BBI_EVEN] = (tm->bs4 << 0) | (tm->be4 << 5); + + __VIRegs[VI_HSW] = (40 << 0) | (40 << 8); + + __VIRegs[VI_DISP_INT_1U] = 1; + __VIRegs[VI_DISP_INT_1] = (1 << 0) | (1 << 12) | (0 << 15); + + hct = (tm->hlw + 1); + vct = (tm->numHalfLines / 2 + 1) | (1 << 12) | (0 << 15); + __VIRegs[VI_DISP_INT_0U] = hct << 0; + __VIRegs[VI_DISP_INT_0] = vct; + + if (mode != VI_TVMODE_NTSC_PROG && mode != VI_TVMODE_NTSC_3D && mode != VI_TVMODE_GCA_PROG) { + __VIRegs[VI_DISP_CONFIG] = (1 << 0) | (0 << 1) | (nonInter << 2) | (0 << 3) | (0 << 4) | (0 << 6) | (tv << 8); + __VIRegs[VI_CLOCK_SEL] = 0; + + } else { + __VIRegs[VI_DISP_CONFIG] = (1 << 0) | (0 << 1) | (1 << 2) | (0 << 3) | (0 << 4) | (0 << 6) | (tv << 8); + __VIRegs[VI_CLOCK_SEL] = 1; + } +} + +static void AdjustPosition(u16 acv) +{ + s32 coeff, frac; + + HorVer.adjDispPosX = (u16)CLAMP((s16)HorVer.dispPosX + displayOffsetH, 0, 720 - HorVer.dispSizeX); + + coeff = (HorVer.xfbMode == VI_XFBMODE_SF) ? 2 : 1; + frac = HorVer.dispPosY & 1; + + HorVer.adjDispPosY = (u16)MAX((s16)HorVer.dispPosY + displayOffsetV, frac); + + HorVer.adjDispSizeY = (u16)(HorVer.dispSizeY + MIN((s16)HorVer.dispPosY + displayOffsetV - frac, 0) + - MAX((s16)HorVer.dispPosY + (s16)HorVer.dispSizeY + displayOffsetV - ((s16)acv * 2 - frac), 0)); + + HorVer.adjPanPosY = (u16)(HorVer.panPosY - MIN((s16)HorVer.dispPosY + displayOffsetV - frac, 0) / coeff); + + HorVer.adjPanSizeY = (u16)(HorVer.panSizeY + MIN((s16)HorVer.dispPosY + displayOffsetV - frac, 0) / coeff + - MAX((s16)HorVer.dispPosY + (s16)HorVer.dispSizeY + displayOffsetV - ((s16)acv * 2 - frac), 0) / coeff); +} + +static void ImportAdjustingValues(void) +{ + displayOffsetH = __OSLockSram()->displayOffsetH; + displayOffsetV = 0; + __OSUnlockSram(FALSE); +} + +void VIInit(void) +{ + u16 dspCfg; + u32 value, tv, tvInBootrom; + + if (IsInitialized) { + return; + } + + OSRegisterVersion(__VIVersion); + IsInitialized = TRUE; + encoderType = 1; + + if (!(__VIRegs[VI_DISP_CONFIG] & 1)) { + __VIInit(VI_TVMODE_NTSC_INT); + } + + retraceCount = 0; + changed = 0; + shdwChanged = 0; + changeMode = 0; + shdwChangeMode = 0; + flushFlag = 0; + + __VIRegs[VI_FCT_0U] = ((((taps[0])) << 0) | (((taps[1] & ((1 << (6)) - 1))) << 10)); + __VIRegs[VI_FCT_0] = ((((taps[1] >> 6)) << 0) | (((taps[2])) << 4)); + __VIRegs[VI_FCT_1U] = ((((taps[3])) << 0) | (((taps[4] & ((1 << (6)) - 1))) << 10)); + __VIRegs[VI_FCT_1] = ((((taps[4] >> 6)) << 0) | (((taps[5])) << 4)); + __VIRegs[VI_FCT_2U] = ((((taps[6])) << 0) | (((taps[7] & ((1 << (6)) - 1))) << 10)); + __VIRegs[VI_FCT_2] = ((((taps[7] >> 6)) << 0) | (((taps[8])) << 4)); + __VIRegs[VI_FCT_3U] = ((((taps[9])) << 0) | (((taps[10])) << 8)); + __VIRegs[VI_FCT_3] = ((((taps[11])) << 0) | (((taps[12])) << 8)); + __VIRegs[VI_FCT_4U] = ((((taps[13])) << 0) | (((taps[14])) << 8)); + __VIRegs[VI_FCT_4] = ((((taps[15])) << 0) | (((taps[16])) << 8)); + __VIRegs[VI_FCT_5U] = ((((taps[17])) << 0) | (((taps[18])) << 8)); + __VIRegs[VI_FCT_5] = ((((taps[19])) << 0) | (((taps[20])) << 8)); + __VIRegs[VI_FCT_6U] = ((((taps[21])) << 0) | (((taps[22])) << 8)); + __VIRegs[VI_FCT_6] = ((((taps[23])) << 0) | (((taps[24])) << 8)); + + __VIRegs[VI_WIDTH] = 640; + ImportAdjustingValues(); + tvInBootrom = *(u32*)OSPhysicalToCached(0xCC); + dspCfg = __VIRegs[VI_DISP_CONFIG]; + + HorVer.nonInter = ((((u32)(dspCfg)) >> 2 & 0x00000001)); + HorVer.tv = ((((u32)(dspCfg)) & 0x00000300) >> 8); + + if ((tvInBootrom == VI_PAL) && (HorVer.tv == VI_NTSC)) { + HorVer.tv = VI_EURGB60; + } + + tv = (HorVer.tv == VI_DEBUG) ? VI_NTSC : HorVer.tv; + HorVer.timing = getTiming((VITVMode)VI_TVMODE(tv, HorVer.nonInter)); + regs[VI_DISP_CONFIG] = dspCfg; + + CurrTiming = HorVer.timing; + CurrTvMode = HorVer.tv; + + HorVer.dispSizeX = 640; + HorVer.dispSizeY = (u16)(CurrTiming->acv * 2); + HorVer.dispPosX = (u16)((720 - HorVer.dispSizeX) / 2); + HorVer.dispPosY = 0; + + AdjustPosition(CurrTiming->acv); + + HorVer.fbSizeX = 640; + HorVer.fbSizeY = (u16)(CurrTiming->acv * 2); + HorVer.panPosX = 0; + HorVer.panPosY = 0; + HorVer.panSizeX = 640; + HorVer.panSizeY = (u16)(CurrTiming->acv * 2); + HorVer.xfbMode = VI_XFBMODE_SF; + HorVer.wordPerLine = 40; + HorVer.std = 40; + HorVer.wpl = 40; + HorVer.xof = 0; + HorVer.isBlack = TRUE; + HorVer.is3D = FALSE; + + OSInitThreadQueue(&retraceQueue); + + value = __VIRegs[VI_DISP_INT_0]; + value = (((u32)(value)) & ~0x00008000) | (((0)) << 15); + __VIRegs[VI_DISP_INT_0] = value; + + value = __VIRegs[VI_DISP_INT_1]; + value = (((u32)(value)) & ~0x00008000) | (((0)) << 15); + __VIRegs[VI_DISP_INT_1] = value; + + PreCB = NULL; + PostCB = NULL; + + __OSSetInterruptHandler(24, __VIRetraceHandler); + __OSUnmaskInterrupts((0x80000000u >> (24))); +} + +void VIWaitForRetrace(void) +{ + int interrupt; + u32 startCount; + + interrupt = OSDisableInterrupts(); + startCount = retraceCount; + do { + OSSleepThread(&retraceQueue); + } while (startCount == retraceCount); + OSRestoreInterrupts(interrupt); +} + +static void setInterruptRegs(VITimingInfo* tm) +{ + u16 vct, hct, borrow; + + vct = (u16)(tm->numHalfLines / 2); + borrow = (u16)(tm->numHalfLines % 2); + hct = (u16)((borrow) ? tm->hlw : (u16)0); + + vct++; + hct++; + + regs[VI_DISP_INT_0U] = (u16)hct; + changed |= VI_BITMASK(VI_DISP_INT_0U); + + regs[VI_DISP_INT_0] = (u16)((((u32)(vct))) | (((u32)(1)) << 12) | (((u32)(0)) << 15)); + changed |= VI_BITMASK(VI_DISP_INT_0); +} + +static void setPicConfig(u16 fbSizeX, VIXFBMode xfbMode, u16 panPosX, u16 panSizeX, u8* wordPerLine, u8* std, u8* wpl, u8* xof) +{ + *wordPerLine = (u8)((fbSizeX + 15) / 16); + *std = (u8)((xfbMode == VI_XFBMODE_SF) ? *wordPerLine : (u8)(2 * *wordPerLine)); + *xof = (u8)(panPosX % 16); + *wpl = (u8)((*xof + panSizeX + 15) / 16); + + regs[VI_HSW] = (u16)((((u32)(*std))) | (((u32)(*wpl)) << 8)); + changed |= VI_BITMASK(VI_HSW); +} + +static void setBBIntervalRegs(VITimingInfo* tm) +{ + u16 val; + + val = (u16)((((u32)(tm->bs1))) | (((u32)(tm->be1)) << 5)); + regs[VI_BBI_ODD_U] = val; + changed |= VI_BITMASK(VI_BBI_ODD_U); + + val = (u16)((((u32)(tm->bs3))) | (((u32)(tm->be3)) << 5)); + regs[VI_BBI_ODD] = val; + changed |= VI_BITMASK(VI_BBI_ODD); + + val = (u16)((((u32)(tm->bs2))) | (((u32)(tm->be2)) << 5)); + regs[VI_BBI_EVEN_U] = val; + changed |= VI_BITMASK(VI_BBI_EVEN_U); + + val = (u16)((((u32)(tm->bs4))) | (((u32)(tm->be4)) << 5)); + regs[VI_BBI_EVEN] = val; + changed |= VI_BITMASK(VI_BBI_EVEN); +} + +static void setScalingRegs(u16 panSizeX, u16 dispSizeX, BOOL is3D) +{ + u32 scale; + + panSizeX = (u16)(is3D ? panSizeX * 2 : panSizeX); + + if (panSizeX < dispSizeX) { + scale = (256 * (u32)panSizeX + (u32)dispSizeX - 1) / (u32)dispSizeX; + + regs[VI_HSR] = (u16)((((u32)(scale))) | (((u32)(1)) << 12)); + changed |= VI_BITMASK(VI_HSR); + + regs[VI_WIDTH] = (u16)((((u32)(panSizeX)))); + changed |= VI_BITMASK(VI_WIDTH); + } else { + regs[VI_HSR] = (u16)((((u32)(256))) | (((u32)(0)) << 12)); + changed |= VI_BITMASK(VI_HSR); + } +} + +static void calcFbbs(u32 bufAddr, u16 panPosX, u16 panPosY, u8 wordPerLine, VIXFBMode xfbMode, u16 dispPosY, u32* tfbb, u32* bfbb) +{ + u32 bytesPerLine, xoffInWords; + xoffInWords = (u32)panPosX / 16; + bytesPerLine = (u32)wordPerLine * 32; + + *tfbb = bufAddr + xoffInWords * 32 + bytesPerLine * panPosY; + *bfbb = (xfbMode == VI_XFBMODE_SF) ? *tfbb : (*tfbb + bytesPerLine); + + if (dispPosY % 2 == 1) { + u32 tmp = *tfbb; + *tfbb = *bfbb; + *bfbb = tmp; + } + + *tfbb = ToPhysical(*tfbb); + *bfbb = ToPhysical(*bfbb); +} + +static void setFbbRegs(VIPositionInfo* hv, u32* tfbb, u32* bfbb, u32* rtfbb, u32* rbfbb) +{ + u32 shifted; + calcFbbs(hv->bufAddr, hv->panPosX, hv->adjPanPosY, hv->wordPerLine, hv->xfbMode, hv->adjDispPosY, tfbb, bfbb); + + if (hv->is3D) { + calcFbbs(hv->rbufAddr, hv->panPosX, hv->adjPanPosY, hv->wordPerLine, hv->xfbMode, hv->adjDispPosY, rtfbb, rbfbb); + } + + if (IS_LOWER_16MB(*tfbb) && IS_LOWER_16MB(*bfbb) && IS_LOWER_16MB(*rtfbb) && IS_LOWER_16MB(*rbfbb)) { + shifted = 0; + } else { + shifted = 1; + } + + if (shifted) { + *tfbb >>= 5; + *bfbb >>= 5; + *rtfbb >>= 5; + *rbfbb >>= 5; + } + + regs[VI_TOP_FIELD_BASE_LEFT_U] = (u16)(*tfbb & 0xFFFF); + changed |= VI_BITMASK(VI_TOP_FIELD_BASE_LEFT_U); + + regs[VI_TOP_FIELD_BASE_LEFT] = (u16)((((*tfbb >> 16))) | hv->xof << 8 | shifted << 12); + changed |= VI_BITMASK(VI_TOP_FIELD_BASE_LEFT); + + regs[VI_BTTM_FIELD_BASE_LEFT_U] = (u16)(*bfbb & 0xFFFF); + changed |= VI_BITMASK(VI_BTTM_FIELD_BASE_LEFT_U); + + regs[VI_BTTM_FIELD_BASE_LEFT] = (u16)(*bfbb >> 16); + changed |= VI_BITMASK(VI_BTTM_FIELD_BASE_LEFT); + + if (hv->is3D) { + regs[VI_TOP_FIELD_BASE_RIGHT_U] = *rtfbb & 0xffff; + changed |= VI_BITMASK(VI_TOP_FIELD_BASE_RIGHT_U); + + regs[VI_TOP_FIELD_BASE_RIGHT] = *rtfbb >> 16; + changed |= VI_BITMASK(VI_TOP_FIELD_BASE_RIGHT); + + regs[VI_BTTM_FIELD_BASE_RIGHT_U] = *rbfbb & 0xFFFF; + changed |= VI_BITMASK(VI_BTTM_FIELD_BASE_RIGHT_U); + + regs[VI_BTTM_FIELD_BASE_RIGHT] = *rbfbb >> 16; + changed |= VI_BITMASK(VI_BTTM_FIELD_BASE_RIGHT); + } +} + +static void setHorizontalRegs(VITimingInfo* tm, u16 dispPosX, u16 dispSizeX) +{ + u32 hbe, hbs, hbeLo, hbeHi; + + regs[VI_HORIZ_TIMING_0U] = (u16)tm->hlw; + changed |= VI_BITMASK(VI_HORIZ_TIMING_0U); + + regs[VI_HORIZ_TIMING_0L] = (u16)(tm->hce | tm->hcs << 8); + changed |= VI_BITMASK(VI_HORIZ_TIMING_0L); + + hbe = (u32)(tm->hbe640 - 40 + dispPosX); + hbs = (u32)(tm->hbs640 + 40 + dispPosX - (720 - dispSizeX)); + + hbeLo = hbe & ONES(9); + hbeHi = hbe >> 9; + + regs[VI_HORIZ_TIMING_1U] = (u16)(tm->hsy | hbeLo << 7); + changed |= VI_BITMASK(VI_HORIZ_TIMING_1U); + + regs[VI_HORIZ_TIMING_1L] = (u16)(hbeHi | hbs << 1); + changed |= VI_BITMASK(VI_HORIZ_TIMING_1L); +} + +static void setVerticalRegs(u16 dispPosY, u16 dispSizeY, u8 equ, u16 acv, u16 prbOdd, u16 prbEven, u16 psbOdd, u16 psbEven, BOOL black) +{ + u16 actualPrbOdd, actualPrbEven, actualPsbOdd, actualPsbEven, actualAcv, c, d; + + if (regs[VI_CLOCK_SEL] & 1) { + c = 1; + d = 2; + } else { + c = 2; + d = 1; + } + + if (dispPosY % 2 == 0) { + actualPrbOdd = (u16)(prbOdd + d * dispPosY); + actualPsbOdd = (u16)(psbOdd + d * ((c * acv - dispSizeY) - dispPosY)); + actualPrbEven = (u16)(prbEven + d * dispPosY); + actualPsbEven = (u16)(psbEven + d * ((c * acv - dispSizeY) - dispPosY)); + } else { + actualPrbOdd = (u16)(prbEven + d * dispPosY); + actualPsbOdd = (u16)(psbEven + d * ((c * acv - dispSizeY) - dispPosY)); + actualPrbEven = (u16)(prbOdd + d * dispPosY); + actualPsbEven = (u16)(psbOdd + d * ((c * acv - dispSizeY) - dispPosY)); + } + + actualAcv = (u16)(dispSizeY / c); + + if (black) { + actualPrbOdd += 2 * actualAcv - 2; + actualPsbOdd += 2; + actualPrbEven += 2 * actualAcv - 2; + actualPsbEven += 2; + actualAcv = 0; + } + + regs[VI_VERT_TIMING] = (u16)(equ | actualAcv << 4); + changed |= VI_BITMASK(VI_VERT_TIMING); + + regs[VI_VERT_TIMING_ODD_U] = (u16)actualPrbOdd << 0; + changed |= VI_BITMASK(VI_VERT_TIMING_ODD_U); + + regs[VI_VERT_TIMING_ODD] = (u16)actualPsbOdd << 0; + changed |= VI_BITMASK(VI_VERT_TIMING_ODD); + + regs[VI_VERT_TIMING_EVEN_U] = (u16)actualPrbEven << 0; + changed |= VI_BITMASK(VI_VERT_TIMING_EVEN_U); + + regs[VI_VERT_TIMING_EVEN] = (u16)actualPsbEven << 0; + changed |= VI_BITMASK(VI_VERT_TIMING_EVEN); +} + +static void PrintDebugPalCaution(void) +{ + static u32 message = 0; + + if (message == 0) { + message = 1; + OSReport("***************************************\n"); + OSReport(" ! ! ! C A U T I O N ! ! ! \n"); + OSReport("This TV format \"DEBUG_PAL\" is only for \n"); + OSReport("temporary solution until PAL DAC board \n"); + OSReport("is available. Please do NOT use this \n"); + OSReport("mode in real games!!! \n"); + OSReport("***************************************\n"); + } +} + +void VIConfigure(const GXRenderModeObj* obj) +{ + VITimingInfo* tm; + u32 regDspCfg; + BOOL enabled; + u32 newNonInter, tvInBootrom, tvInGame; + + enabled = OSDisableInterrupts(); + newNonInter = (u32)obj->viTVmode & 3; + + if (HorVer.nonInter != newNonInter) { + changeMode = 1; + HorVer.nonInter = newNonInter; + } + + tvInGame = (u32)obj->viTVmode >> 2; + tvInBootrom = *(u32*)OSPhysicalToCached(0xCC); + + if (tvInGame == VI_DEBUG_PAL) { + PrintDebugPalCaution(); + } + + switch (tvInBootrom) { + case VI_MPAL: + case VI_NTSC: + case VI_GCA: + if (tvInGame == VI_NTSC || tvInGame == VI_MPAL || tvInGame == VI_GCA) { + break; + } + goto panic; + case VI_PAL: + case VI_EURGB60: + if (tvInGame == VI_PAL || tvInGame == VI_EURGB60) { + break; + } + default: + panic: + OSErrorLine(1908, "VIConfigure(): Tried to change mode from (%d) to (%d), which is forbidden\n", tvInBootrom, tvInGame); + } + + if ((tvInGame == VI_NTSC) || (tvInGame == VI_MPAL)) { + HorVer.tv = tvInBootrom; + } else { + HorVer.tv = tvInGame; + } + + HorVer.dispPosX = obj->viXOrigin; + HorVer.dispPosY = (u16)((HorVer.nonInter == VI_NON_INTERLACE) ? (u16)(obj->viYOrigin * 2) : obj->viYOrigin); + HorVer.dispSizeX = obj->viWidth; + HorVer.fbSizeX = obj->fbWidth; + HorVer.fbSizeY = obj->xfbHeight; + HorVer.xfbMode = obj->xFBmode; + HorVer.panSizeX = HorVer.fbSizeX; + HorVer.panSizeY = HorVer.fbSizeY; + HorVer.panPosX = 0; + HorVer.panPosY = 0; + + HorVer.dispSizeY = (u16)((HorVer.nonInter == VI_PROGRESSIVE) ? HorVer.panSizeY + : (HorVer.nonInter == VI_3D) ? HorVer.panSizeY + : (HorVer.xfbMode == VI_XFBMODE_SF) ? (u16)(2 * HorVer.panSizeY) + : HorVer.panSizeY); + + HorVer.is3D = (HorVer.nonInter == VI_3D) ? TRUE : FALSE; + + tm = getTiming((VITVMode)VI_TVMODE(HorVer.tv, HorVer.nonInter)); + HorVer.timing = tm; + + AdjustPosition(tm->acv); + if (encoderType == 0) { + HorVer.tv = VI_DEBUG; + } + setInterruptRegs(tm); + + regDspCfg = regs[VI_DISP_CONFIG]; + if ((HorVer.nonInter == VI_PROGRESSIVE) || (HorVer.nonInter == VI_3D)) { + regDspCfg = (((u32)(regDspCfg)) & ~0x00000004) | (((u32)(1)) << 2); + } else { + regDspCfg = (((u32)(regDspCfg)) & ~0x00000004) | (((u32)(HorVer.nonInter & 1)) << 2); + } + + regDspCfg = (((u32)(regDspCfg)) & ~0x00000008) | (((u32)(HorVer.is3D)) << 3); + + if ((HorVer.tv == VI_DEBUG_PAL) || (HorVer.tv == VI_EURGB60) || (HorVer.tv == VI_GCA)) { + regDspCfg = (((u32)(regDspCfg)) & ~0x00000300); + } else { + regDspCfg = (((u32)(regDspCfg)) & ~0x00000300) | (((u32)(HorVer.tv)) << 8); + } + + regs[VI_DISP_CONFIG] = (u16)regDspCfg; + changed |= VI_BITMASK(0x01); + + regDspCfg = regs[VI_CLOCK_SEL]; + if (obj->viTVmode == VI_TVMODE_NTSC_PROG || obj->viTVmode == VI_TVMODE_NTSC_3D || obj->viTVmode == VI_TVMODE_GCA_PROG) { + regDspCfg = (u32)(regDspCfg & ~0x1) | 1; + } else { + regDspCfg = (u32)(regDspCfg & ~0x1); + } + + regs[VI_CLOCK_SEL] = (u16)regDspCfg; + + changed |= 0x200; + + setScalingRegs(HorVer.panSizeX, HorVer.dispSizeX, HorVer.is3D); + setHorizontalRegs(tm, HorVer.adjDispPosX, HorVer.dispSizeX); + setBBIntervalRegs(tm); + setPicConfig(HorVer.fbSizeX, HorVer.xfbMode, HorVer.panPosX, HorVer.panSizeX, &HorVer.wordPerLine, &HorVer.std, &HorVer.wpl, + &HorVer.xof); + + if (FBSet) { + setFbbRegs(&HorVer, &HorVer.tfbb, &HorVer.bfbb, &HorVer.rtfbb, &HorVer.rbfbb); + } + + setVerticalRegs(HorVer.adjDispPosY, HorVer.adjDispSizeY, tm->equ, tm->acv, tm->prbOdd, tm->prbEven, tm->psbOdd, tm->psbEven, + HorVer.isBlack); + OSRestoreInterrupts(enabled); +} + +void VIConfigurePan(u16 panPosX, u16 panPosY, u16 panSizeX, u16 panSizeY) +{ + BOOL enabled; + VITimingInfo* tm; + + enabled = OSDisableInterrupts(); + HorVer.panPosX = panPosX; + HorVer.panPosY = panPosY; + HorVer.panSizeX = panSizeX; + HorVer.panSizeY = panSizeY; + + HorVer.dispSizeY = (u16)((HorVer.nonInter == VI_PROGRESSIVE) ? HorVer.panSizeY + : (HorVer.nonInter == VI_3D) ? HorVer.panSizeY + : (HorVer.xfbMode == VI_XFBMODE_SF) ? (u16)(2 * HorVer.panSizeY) + : HorVer.panSizeY); + + tm = HorVer.timing; + + AdjustPosition(tm->acv); + setScalingRegs(HorVer.panSizeX, HorVer.dispSizeX, HorVer.is3D); + setPicConfig(HorVer.fbSizeX, HorVer.xfbMode, HorVer.panPosX, HorVer.panSizeX, &HorVer.wordPerLine, &HorVer.std, &HorVer.wpl, + &HorVer.xof); + + if (FBSet) { + setFbbRegs(&HorVer, &HorVer.tfbb, &HorVer.bfbb, &HorVer.rtfbb, &HorVer.rbfbb); + } + + setVerticalRegs(HorVer.adjDispPosY, HorVer.dispSizeY, tm->equ, tm->acv, tm->prbOdd, tm->prbEven, tm->psbOdd, tm->psbEven, + HorVer.isBlack); + OSRestoreInterrupts(enabled); +} + +void VIFlush(void) +{ + BOOL enabled; + s32 regIndex; + u32 val; + + enabled = OSDisableInterrupts(); + shdwChangeMode |= changeMode; + changeMode = 0; + shdwChanged |= changed; + + while (changed) { + regIndex = cntlzd(changed); + shdwRegs[regIndex] = regs[regIndex]; + changed &= ~VI_BITMASK(regIndex); + } + + flushFlag = 1; + NextBufAddr = HorVer.bufAddr; + OSRestoreInterrupts(enabled); +} + +void VISetNextFrameBuffer(void* fb) +{ + BOOL enabled = OSDisableInterrupts(); + HorVer.bufAddr = (u32)fb; + FBSet = 1; + setFbbRegs(&HorVer, &HorVer.tfbb, &HorVer.bfbb, &HorVer.rtfbb, &HorVer.rbfbb); + OSRestoreInterrupts(enabled); +} + +void* VIGetNextFrameBuffer(void) +{ + return (void*)NextBufAddr; +} + +void* VIGetCurrentFrameBuffer(void) +{ + return (void*)CurrBufAddr; +} + + +void VISetBlack(BOOL isBlack) +{ + int interrupt; + VITimingInfo* tm; + + interrupt = OSDisableInterrupts(); + HorVer.isBlack = isBlack; + tm = HorVer.timing; + setVerticalRegs(HorVer.adjDispPosY, HorVer.dispSizeY, tm->equ, tm->acv, tm->prbOdd, tm->prbEven, tm->psbOdd, tm->psbEven, + HorVer.isBlack); + OSRestoreInterrupts(interrupt); +} + + +u32 VIGetRetraceCount(void) +{ + return retraceCount; +} + +static void GetCurrentDisplayPosition(u32* hct, u32* vct) +{ + u32 hcount, vcount0, vcount; + vcount = __VIRegs[VI_VERT_COUNT] & 0x7FF; + + do { + vcount0 = vcount; + hcount = __VIRegs[VI_HORIZ_COUNT] & 0x7FF; + vcount = __VIRegs[VI_VERT_COUNT] & 0x7FF; + } while (vcount0 != vcount); + + *hct = hcount; + *vct = vcount; +} + +static u32 getCurrentHalfLine(void) +{ + u32 hcount, vcount; + GetCurrentDisplayPosition(&hcount, &vcount); + + return ((vcount - 1) << 1) + ((hcount - 1) / CurrTiming->hlw); +} + +static u32 getCurrentFieldEvenOdd() +{ + return (getCurrentHalfLine() < CurrTiming->numHalfLines) ? 1 : 0; +} + +u32 VIGetNextField(void) +{ + u32 nextField; + int interrupt; + + interrupt = OSDisableInterrupts(); + nextField = getCurrentFieldEvenOdd() ^ 1; + OSRestoreInterrupts(interrupt); + return nextField ^ (HorVer.adjDispPosY & 1); +} + +u32 VIGetCurrentLine(void) +{ + u32 line; + VITimingInfo* tm; + int interrupt; + + tm = CurrTiming; + interrupt = OSDisableInterrupts(); + line = getCurrentHalfLine(); + OSRestoreInterrupts(interrupt); + + if (line >= tm->numHalfLines) { + line -= tm->numHalfLines; + } + + return (line >> 1); +} + +u32 VIGetTvFormat(void) +{ + u32 fmt; + int interrupt; + + interrupt = OSDisableInterrupts(); + + switch (CurrTvMode) { + case VI_NTSC: + case VI_DEBUG: + case VI_GCA: + fmt = VI_NTSC; + break; + case VI_PAL: + case VI_DEBUG_PAL: + fmt = VI_PAL; + break; + case VI_EURGB60: + case VI_MPAL: + fmt = CurrTvMode; + break; + } + + OSRestoreInterrupts(interrupt); + return fmt; +} + +u32 VIGetDTVStatus(void) +{ + u32 stat; + int interrupt; + + interrupt = OSDisableInterrupts(); + stat = (__VIRegs[VI_DTV_STAT] & 3); + OSRestoreInterrupts(interrupt); + return (stat & 1); +} + +void __VIDisplayPositionToXY(u32 hcount, u32 vcount, s16* x, s16* y) +{ + u32 halfLine = ((vcount - 1) << 1) + ((hcount - 1) / CurrTiming->hlw); + + if (HorVer.nonInter == VI_INTERLACE) { + if (halfLine < CurrTiming->numHalfLines) { + if (halfLine < CurrTiming->equ * 3 + CurrTiming->prbOdd) { + *y = -1; + } else if (halfLine >= CurrTiming->numHalfLines - CurrTiming->psbOdd) { + *y = -1; + } else { + *y = (s16)((halfLine - CurrTiming->equ * 3 - CurrTiming->prbOdd) & ~1); + } + } else { + halfLine -= CurrTiming->numHalfLines; + + if (halfLine < CurrTiming->equ * 3 + CurrTiming->prbEven) { + *y = -1; + } else if (halfLine >= CurrTiming->numHalfLines - CurrTiming->psbEven) { + *y = -1; + } else { + *y = (s16)(((halfLine - CurrTiming->equ * 3 - CurrTiming->prbEven) & ~1) + 1); + } + } + } else if (HorVer.nonInter == VI_NON_INTERLACE) { + if (halfLine >= CurrTiming->numHalfLines) { + halfLine -= CurrTiming->numHalfLines; + } + + if (halfLine < CurrTiming->equ * 3 + CurrTiming->prbOdd) { + *y = -1; + } else if (halfLine >= CurrTiming->numHalfLines - CurrTiming->psbOdd) { + *y = -1; + } else { + *y = (s16)((halfLine - CurrTiming->equ * 3 - CurrTiming->prbOdd) & ~1); + } + } else if (HorVer.nonInter == VI_PROGRESSIVE) { + if (halfLine < CurrTiming->numHalfLines) { + if (halfLine < CurrTiming->equ * 3 + CurrTiming->prbOdd) { + *y = -1; + } else if (halfLine >= CurrTiming->numHalfLines - CurrTiming->psbOdd) { + *y = -1; + } else { + *y = (s16)(halfLine - CurrTiming->equ * 3 - CurrTiming->prbOdd); + } + } else { + halfLine -= CurrTiming->numHalfLines; + + if (halfLine < CurrTiming->equ * 3 + CurrTiming->prbEven) { + *y = -1; + } else if (halfLine >= CurrTiming->numHalfLines - CurrTiming->psbEven) { + *y = -1; + } else + *y = (s16)((halfLine - CurrTiming->equ * 3 - CurrTiming->prbEven) & ~1); + } + } + + *x = (s16)(hcount - 1); +} + +void __VIGetCurrentPosition(s16* x, s16* y) +{ + u32 h, v; + GetCurrentDisplayPosition(&h, &v); + __VIDisplayPositionToXY(h, v, x, y); +} From 942ce3a9f69a63fd1e91415a33518e757362e488 Mon Sep 17 00:00:00 2001 From: h0504 Date: Tue, 27 Oct 2026 08:25:44 +0900 Subject: [PATCH 2/7] Add MSL_C and MetroTRK sources for Rev 1 Port the Metrowerks C library and MetroTRK v2.6 from the Pikmin 2 decompilation (same generation as e+ Rev 1) and adapt them to this tree. New self-contained headers live in include/PowerPC_EABI_Support/MSL_C/ MSL_Common and include/TRK; existing headers are not modified. Co-Authored-By: Claude Opus 5.5 --- .../MSL_C/MSL_Common/FILE_POS.h | 23 + .../MSL_C/MSL_Common/ansi_files.h | 89 ++ .../MSL_C/MSL_Common/ansi_fp.h | 37 + .../MSL_C/MSL_Common/arith.h | 35 + .../MSL_C/MSL_Common/critical_regions.h | 30 + .../MSL_C/MSL_Common/ctype_api.h | 70 + .../MSL_C/MSL_Common/direct_io.h | 8 + .../MSL_C/MSL_Common/errno.h | 20 + .../MSL_C/MSL_Common/file_io.h | 9 + .../MSL_C/MSL_Common/file_struc.h | 10 + .../MSL_C/MSL_Common/limits.h | 29 + .../MSL_C/MSL_Common/math_api.h | 87 ++ .../MSL_C/MSL_Common/mbstring.h | 21 + .../MSL_C/MSL_Common/mem.h | 21 + .../MSL_C/MSL_Common/mem_funcs.h | 16 + .../MSL_C/MSL_Common/misc_io.h | 8 + .../MSL_C/MSL_Common/msl_types.h | 43 + .../MSL_C/MSL_Common/printf.h | 15 + .../MSL_C/MSL_Common/rand.h | 17 + .../MSL_C/MSL_Common/scanf.h | 9 + .../MSL_C/MSL_Common/secure_error.h | 8 + .../MSL_C/MSL_Common/stdio_api.h | 35 + .../MSL_C/MSL_Common/string.h | 25 + .../MSL_C/MSL_Common/strtold.h | 16 + .../MSL_C/MSL_Common/strtoul.h | 22 + .../MSL_C/MSL_Common/wchar_io.h | 8 + include/TRK/AmcExi2Stubs.h | 33 + include/TRK/CircleBuffer.h | 23 + include/TRK/dstypes.h | 34 + include/TRK/memmap.h | 15 + include/TRK/ppc_reg.h | 242 ++++ include/TRK/trk.h | 201 +++ include/TRK/trkenum.h | 201 +++ include/TRK/trktypes.h | 147 ++ src/static/MSL_C.PPCEABI.bare.H/FILE_POS.C | 147 ++ src/static/MSL_C.PPCEABI.bare.H/abort_exit.c | 46 + src/static/MSL_C.PPCEABI.bare.H/ansi_files.c | 153 ++ src/static/MSL_C.PPCEABI.bare.H/ansi_fp.c | 775 ++++++++++ src/static/MSL_C.PPCEABI.bare.H/arith.c | 80 ++ src/static/MSL_C.PPCEABI.bare.H/buffer_io.c | 36 + .../critical_regions.gamecube.c | 21 + src/static/MSL_C.PPCEABI.bare.H/ctype.c | 57 + src/static/MSL_C.PPCEABI.bare.H/direct_io.c | 132 ++ src/static/MSL_C.PPCEABI.bare.H/e_acos.c | 107 ++ src/static/MSL_C.PPCEABI.bare.H/e_atan2.c | 143 ++ src/static/MSL_C.PPCEABI.bare.H/e_pow.c | 405 ++++++ src/static/MSL_C.PPCEABI.bare.H/e_rem_pio2.c | 180 +++ src/static/MSL_C.PPCEABI.bare.H/e_sqrt.c | 459 ++++++ src/static/MSL_C.PPCEABI.bare.H/errno.c | 3 + src/static/MSL_C.PPCEABI.bare.H/file_io.c | 70 + src/static/MSL_C.PPCEABI.bare.H/float.c | 10 + src/static/MSL_C.PPCEABI.bare.H/k_cos.c | 93 ++ src/static/MSL_C.PPCEABI.bare.H/k_rem_pio2.c | 353 +++++ src/static/MSL_C.PPCEABI.bare.H/k_sin.c | 80 ++ src/static/MSL_C.PPCEABI.bare.H/mbstring.c | 172 +++ src/static/MSL_C.PPCEABI.bare.H/mem.c | 98 ++ src/static/MSL_C.PPCEABI.bare.H/mem_funcs.c | 202 +++ src/static/MSL_C.PPCEABI.bare.H/misc_io.c | 7 + src/static/MSL_C.PPCEABI.bare.H/printf.c | 1242 +++++++++++++++++ src/static/MSL_C.PPCEABI.bare.H/rand.c | 14 + src/static/MSL_C.PPCEABI.bare.H/s_atan.c | 143 ++ src/static/MSL_C.PPCEABI.bare.H/s_ceil.c | 91 ++ src/static/MSL_C.PPCEABI.bare.H/s_copysign.c | 31 + src/static/MSL_C.PPCEABI.bare.H/s_cos.c | 83 ++ src/static/MSL_C.PPCEABI.bare.H/s_floor.c | 90 ++ src/static/MSL_C.PPCEABI.bare.H/s_frexp.c | 58 + src/static/MSL_C.PPCEABI.bare.H/s_ldexp.c | 62 + src/static/MSL_C.PPCEABI.bare.H/s_modf.c | 80 ++ src/static/MSL_C.PPCEABI.bare.H/s_sin.c | 83 ++ src/static/MSL_C.PPCEABI.bare.H/scanf.c | 649 +++++++++ src/static/MSL_C.PPCEABI.bare.H/string.c | 269 ++++ src/static/MSL_C.PPCEABI.bare.H/strtoul.c | 343 +++++ .../uart_console_io_gcn.c | 42 + src/static/MSL_C.PPCEABI.bare.H/w_acos.c | 38 + src/static/MSL_C.PPCEABI.bare.H/w_atan2.c | 38 + src/static/MSL_C.PPCEABI.bare.H/w_pow.c | 27 + src/static/MSL_C.PPCEABI.bare.H/wchar_io.c | 30 + src/static/TRK_MINNOW_DOLPHIN/CircleBuffer.c | 83 ++ .../MWCriticalSection_gc.cpp | 25 + src/static/TRK_MINNOW_DOLPHIN/MWTrace.c | 6 + src/static/TRK_MINNOW_DOLPHIN/UDP_Stubs.c | 47 + src/static/TRK_MINNOW_DOLPHIN/__exception.s | 476 +++++++ src/static/TRK_MINNOW_DOLPHIN/dispatch.c | 61 + src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c | 343 +++++ .../TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c | 204 +++ src/static/TRK_MINNOW_DOLPHIN/flush_cache.c | 23 + src/static/TRK_MINNOW_DOLPHIN/main.c | 148 ++ src/static/TRK_MINNOW_DOLPHIN/main_TRK.c | 18 + src/static/TRK_MINNOW_DOLPHIN/main_ddh.c | 142 ++ src/static/TRK_MINNOW_DOLPHIN/mainloop.c | 73 + src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c | 81 ++ src/static/TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c | 246 ++++ src/static/TRK_MINNOW_DOLPHIN/msg.c | 8 + src/static/TRK_MINNOW_DOLPHIN/msgbuf.c | 367 +++++ src/static/TRK_MINNOW_DOLPHIN/msghndlr.c | 548 ++++++++ src/static/TRK_MINNOW_DOLPHIN/mslsupp.c | 96 ++ src/static/TRK_MINNOW_DOLPHIN/mutex_TRK.c | 16 + src/static/TRK_MINNOW_DOLPHIN/notify.c | 34 + src/static/TRK_MINNOW_DOLPHIN/nubevent.c | 78 ++ src/static/TRK_MINNOW_DOLPHIN/nubinit.c | 74 + src/static/TRK_MINNOW_DOLPHIN/serpoll.c | 91 ++ src/static/TRK_MINNOW_DOLPHIN/support.c | 282 ++++ src/static/TRK_MINNOW_DOLPHIN/targcont.c | 10 + .../TRK_MINNOW_DOLPHIN/target_options.c | 14 + src/static/TRK_MINNOW_DOLPHIN/targimpl.c | 1184 ++++++++++++++++ src/static/TRK_MINNOW_DOLPHIN/targsupp.s | 32 + src/static/TRK_MINNOW_DOLPHIN/usr_put.c | 91 ++ 107 files changed, 13750 insertions(+) create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/FILE_POS.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_fp.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/arith.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/direct_io.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/file_io.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/file_struc.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/limits.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/math_api.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/mbstring.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/mem.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/mem_funcs.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/misc_io.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/printf.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/rand.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/scanf.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/secure_error.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/stdio_api.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/string.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/strtold.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/strtoul.h create mode 100644 include/PowerPC_EABI_Support/MSL_C/MSL_Common/wchar_io.h create mode 100644 include/TRK/AmcExi2Stubs.h create mode 100644 include/TRK/CircleBuffer.h create mode 100644 include/TRK/dstypes.h create mode 100644 include/TRK/memmap.h create mode 100644 include/TRK/ppc_reg.h create mode 100644 include/TRK/trk.h create mode 100644 include/TRK/trkenum.h create mode 100644 include/TRK/trktypes.h create mode 100644 src/static/MSL_C.PPCEABI.bare.H/FILE_POS.C create mode 100644 src/static/MSL_C.PPCEABI.bare.H/abort_exit.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/ansi_files.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/ansi_fp.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/arith.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/buffer_io.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/critical_regions.gamecube.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/ctype.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/direct_io.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/e_acos.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/e_atan2.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/e_pow.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/e_rem_pio2.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/e_sqrt.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/errno.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/file_io.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/float.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/k_cos.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/k_rem_pio2.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/k_sin.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/mbstring.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/mem.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/mem_funcs.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/misc_io.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/printf.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/rand.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_atan.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_ceil.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_copysign.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_cos.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_floor.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_frexp.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_ldexp.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_modf.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/s_sin.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/scanf.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/string.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/strtoul.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/uart_console_io_gcn.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/w_acos.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/w_atan2.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/w_pow.c create mode 100644 src/static/MSL_C.PPCEABI.bare.H/wchar_io.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/CircleBuffer.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/MWCriticalSection_gc.cpp create mode 100644 src/static/TRK_MINNOW_DOLPHIN/MWTrace.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/UDP_Stubs.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/__exception.s create mode 100644 src/static/TRK_MINNOW_DOLPHIN/dispatch.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/flush_cache.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/main.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/main_TRK.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/main_ddh.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/mainloop.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/msg.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/msgbuf.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/msghndlr.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/mslsupp.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/mutex_TRK.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/notify.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/nubevent.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/nubinit.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/serpoll.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/support.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/targcont.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/target_options.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/targimpl.c create mode 100644 src/static/TRK_MINNOW_DOLPHIN/targsupp.s create mode 100644 src/static/TRK_MINNOW_DOLPHIN/usr_put.c diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/FILE_POS.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/FILE_POS.h new file mode 100644 index 00000000..eb91b5ae --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/FILE_POS.h @@ -0,0 +1,23 @@ +#ifndef _MSL_COMMON_FILE_POS_H +#define _MSL_COMMON_FILE_POS_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +#define SEEK_SET (0) +#define SEEK_CUR (1) +#define SEEK_END (2) + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +int fseek(FILE* stream, u32 offset, int whence); +int _fseek(FILE* stream, u32 offset, int whence); +int ftell(FILE* stream); +int _ftell(FILE* stream); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h new file mode 100644 index 00000000..07e34003 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h @@ -0,0 +1,89 @@ +#ifndef _MSL_COMMON_ANSI_FILES_H +#define _MSL_COMMON_ANSI_FILES_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +typedef u32 __file_handle; +typedef u32 fpos_t; +typedef struct _IO_FILE _IO_FILE, *P_IO_FILE; + +#define __ungetc_buffer_size 2 + +enum __file_kinds { __closed_file, __disk_file, __console_file, __unavailable_file }; + +enum __file_orientation { __unoriented, __char_oriented, __wide_oriented }; + +typedef struct __file_modes { + u32 open_mode : 2; + u32 io_mode : 3; + u32 buffer_mode : 2; + u32 file_kind : 3; + +#ifdef _MSL_WIDE_CHAR + u32 file_orientation : 2; +#endif /* _MSL_WIDE_CHAR */ + + u32 binary_io : 1; +} file_modes; + +enum __io_states { __neutral, __writing, __reading, __rereading }; + +typedef struct __file_states { + u32 io_state : 3; + u32 free_buffer : 1; + + u8 eof; + u8 error; +} file_states; + +typedef void* __ref_con; +typedef void (*__idle_proc)(void); +typedef int (*__pos_proc)(__file_handle file, fpos_t* position, int mode, __ref_con ref_con); +typedef int (*__io_proc)(__file_handle file, char* buff, size_t* count, __ref_con ref_con); +typedef int (*__close_proc)(__file_handle file); + +struct _IO_FILE { + __file_handle mHandle; // _00 + file_modes mMode; // _04 + file_states mState; // _08 + u8 mIsDynamicallyAllocated; // _0C + u8 mCharBuffer; // _0D + u8 mCharBufferOverflow; // _0E + u8 mUngetcBuffer[__ungetc_buffer_size]; // _0F + wchar_t mUngetcWideBuffer[__ungetc_buffer_size]; // _12 + u32 mPosition; // _18 + char* mBuffer; // _1C + u32 mBufferSize; // _20 + char* mBufferPtr; // _24 + u32 mBufferLength; // _28 + u32 mBufferAlignment; // _2C + u32 mBufferLength2; // _30 + u32 mBufferPosition; // _34 + __pos_proc positionFunc; // _38 + __io_proc readFunc; // _3C + __io_proc writeFunc; // _40 + __close_proc closeFunc; // _44 + __ref_con ref_con; // _48 + _IO_FILE* mNextFile; // _4C +}; + +typedef struct _IO_FILE FILE; + +extern FILE __files[4]; + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +int fflush(FILE* __stream); +void free(void*); +int __flush_buffer(FILE* file, size_t* length); +void __prep_buffer(FILE* file); +u32 __flush_all(void); +void __close_all(void); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_fp.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_fp.h new file mode 100644 index 00000000..5432638b --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_fp.h @@ -0,0 +1,37 @@ +#ifndef _MSL_COMMON_ANSI_FP_H +#define _MSL_COMMON_ANSI_FP_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/math_api.h" + +#define SIGDIGLEN 36 + +typedef struct decimal { + char sign; + char unk1; + s16 exp; + struct { + u8 length; + u8 text[36]; + u8 unk41; + } sig; +} decimal; + +typedef struct decform { + char style; + char unk1; + s16 digits; +} decform; + +void __ull2dec(decimal*, u64); +void __timesdec(decimal*, const decimal*, const decimal*); +void __str2dec(decimal*, const char*, s16); +void __two_exp(decimal*, s32); +BOOL __equals_dec(const decimal*, const decimal*); +BOOL __less_dec(const decimal*, const decimal*); +void __minus_dec(decimal*, const decimal*, const decimal*); +void __num2dec_internal(decimal*, f64); +void __num2dec(const decform*, f64, decimal*); +f64 __dec2num(const decimal*); + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/arith.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/arith.h new file mode 100644 index 00000000..6934606d --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/arith.h @@ -0,0 +1,35 @@ +#ifndef _MSL_COMMON_ARITH_H +#define _MSL_COMMON_ARITH_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +typedef struct { + int quot; /* quotient */ + int rem; /* remainder */ +} div_t; + +typedef struct { + long quot; /* quotient */ + long rem; /* remainder */ +} ldiv_t; + +typedef struct { + long long quot; /* quotient */ + long long rem; /* remainder */ +} lldiv_t; + +int abs(int __x); +long labs(long __x); +div_t div(int __numer, int __denom); +ldiv_t ldiv(long __numer, long __denom); +lldiv_t lldiv(long long __numer, long long __denom); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h new file mode 100644 index 00000000..3876e4e7 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h @@ -0,0 +1,30 @@ +#ifndef _MSL_COMMON_CRITICAL_REGIONS_H +#define _MSL_COMMON_CRITICAL_REGIONS_H + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +enum critical_regions { + atexit_funcs_access, + malloc_pool_access, + stdin_access, + stdout_access, + stderr_access, + files_access, + console_status_access, + signal_funcs_access, + thread_access, + num_critical_regions +}; + +void __init_critical_regions(void); +void __kill_critical_regions(void); +void __begin_critical_region(int region); +void __end_critical_region(int region); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h new file mode 100644 index 00000000..3e099013 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h @@ -0,0 +1,70 @@ +#ifndef _MSL_COMMON_CTYPE_API_H +#define _MSL_COMMON_CTYPE_API_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +extern u8 __ctype_map[256]; +extern u8 __lower_map[256]; +extern u8 __upper_map[256]; + +#define __control_char 0x01 +#define __motion_char 0x02 +#define __space_char 0x04 +#define __punctuation 0x08 +#define __digit 0x10 +#define __hex_digit 0x20 +#define __lower_case 0x40 +#define __upper_case 0x80 + +#define __letter (__lower_case | __upper_case) +#define __alphanumeric (__letter | __digit) +#define __graphic (__alphanumeric | __punctuation) +#define __printable (__graphic | __space_char) +#define __whitespace (__motion_char | __space_char) +#define __control (__motion_char | __control_char) + +int tolower(int __c); + +inline int isalpha(int c) +{ + return (int)(__ctype_map[(u8)c] & __letter); +} +inline int isdigit(int c) +{ + return (int)(__ctype_map[(u8)c] & __digit); +} +inline int isspace(int c) +{ + return (int)(__ctype_map[(u8)c] & __whitespace); +} +inline int isupper(int c) +{ + return (int)(__ctype_map[(u8)c] & __upper_case); +} +inline int isxdigit(int c) +{ + return (int)(__ctype_map[(u8)c] & __hex_digit); +} +inline int isprintable(int c) +{ + return (int)(__ctype_map[(u8)c] & __printable); +} +// added underscore to avoid naming conflicts +inline int _tolower(int c) +{ + return (c == -1 ? -1 : (int)__lower_map[(u8)c]); +} +inline int toupper(int c) +{ + return (c == -1 ? -1 : (int)__upper_map[(u8)c]); +} + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/direct_io.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/direct_io.h new file mode 100644 index 00000000..924bca38 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/direct_io.h @@ -0,0 +1,8 @@ +#ifndef _MSL_COMMON_DIRECT_IO_H +#define _MSL_COMMON_DIRECT_IO_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +size_t fwrite(const void* pPtr, size_t memb_size, size_t num_memb, FILE* pFile); + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h new file mode 100644 index 00000000..e217e2ab --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h @@ -0,0 +1,20 @@ +#ifndef _MSL_COMMON_ERRNO_H +#define _MSL_COMMON_ERRNO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define ENOERR 0 +#define EDOM 33 +#define ERANGE 34 +#define EFPOS 40 +#define EILSEQ 88 + +extern int errno; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/file_io.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/file_io.h new file mode 100644 index 00000000..9344db16 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/file_io.h @@ -0,0 +1,9 @@ +#ifndef _MSL_COMMON_FILE_IO_H +#define _MSL_COMMON_FILE_IO_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +int fclose(FILE* file); +int fflush(FILE* file); + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/file_struc.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/file_struc.h new file mode 100644 index 00000000..9f0edaae --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/file_struc.h @@ -0,0 +1,10 @@ +#ifndef _MSL_COMMON_FILE_STRUC_H +#define _MSL_COMMON_FILE_STRUC_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +#define stdin &(__files[0]) +#define stdout &(__files[1]) +#define stderr &(__files[2]) + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/limits.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/limits.h new file mode 100644 index 00000000..9860ff0d --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/limits.h @@ -0,0 +1,29 @@ +#ifndef _MSL_COMMON_LIMITS_H +#define _MSL_COMMON_LIMITS_H + +#define CHAR_BIT 8 + +#define SCHAR_MIN (-0x7F - 1) +#define SCHAR_MAX 0x7F +#define UCHAR_MAX 0xFF + +#define CHAR_MIN 0 +#define CHAR_MAX SCHAR_MAX + +#define SHRT_MIN (-0x7FFF - 1) +#define SHRT_MAX 0x7FFF +#define USHRT_MAX 0xFFFF + +#define INT_MIN (-0x7FFFFFFF - 1) +#define INT_MAX 0x7FFFFFFF +#define UINT_MAX 0xFFFFFFFF + +#define LONG_MIN (-0x7FFFFFFFL - 1) +#define LONG_MAX 0x7FFFFFFFL +#define ULONG_MAX 0xFFFFFFFFUL + +#define LLONG_MIN (-0x7FFFFFFFFFFFFFFFLL - 1) +#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/math_api.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/math_api.h new file mode 100644 index 00000000..8ceef554 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/math_api.h @@ -0,0 +1,87 @@ +#ifndef _MSL_COMMON_MATH_API_H +#define _MSL_COMMON_MATH_API_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +inline int __fpclassifyf(f32 x) +{ + switch ((*(s32*)&x) & 0x7f800000) { + case 0x7f800000: { + if ((*(s32*)&x) & 0x007fffff) + return 1; + else + return 2; + break; + } + case 0: { + if ((*(s32*)&x) & 0x007fffff) + return 5; + else + return 3; + break; + } + } + return 4; +} + +inline int __fpclassifyd(f64 x) +{ + switch (__HI(x) & 0x7ff00000) { + case 0x7ff00000: { + if ((__HI(x) & 0x000fffff) || (__LO(x) & 0xffffffff)) + return 1; + else + return 2; + break; + } + case 0: { + if ((__HI(x) & 0x000fffff) || (__LO(x) & 0xffffffff)) + return 5; + else + return 3; + break; + } + } + return 4; +} + +#define fpclassify(x) ((sizeof(x) == sizeof(f32)) ? __fpclassifyf((f32)(x)) : __fpclassifyd((f64)(x))) + +#define SIGNBIT(x) ((int)(__HI(x) & 0x80000000)) + +#define isnan(x) ((fpclassify(x) == 1)) +#define isinf(x) ((fpclassify(x) == 2)) +#define isfinite(x) ((fpclassify(x) > 2)) + +extern int __double_max[]; +extern int __extended_min[]; +extern int __extended_max[]; + +#define DBL_MAX (*(f64*)__double_max) +#define LDBL_MAX (*(f128*)__extended_max) +#define LDBL_MIN (*(f128*)__extended_min) + +#define DBL_MANT_DIG 53 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN_10_EXP (-308) +#define DBL_MAX_EXP 1024 +#define DBL_MAX_10_EXP 308 + +#define LDBL_MANT_DIG 53 +#define LDBL_DIG 15 +#define LDBL_MIN_EXP (-1021) +#define LDBL_MIN_10_EXP (-308) +#define LDBL_MAX_EXP 1024 +#define LDBL_MAX_10_EXP 308 + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mbstring.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mbstring.h new file mode 100644 index 00000000..3d4e7edd --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mbstring.h @@ -0,0 +1,21 @@ +#ifndef _MSL_COMMON_MBSTRING_H +#define _MSL_COMMON_MBSTRING_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int __mbtowc_noconv(wchar_t*, const char*, size_t); +int __wctomb_noconv(char*, wchar_t); +size_t wcstombs(char* s, const wchar_t* pwcs, size_t n); +int mbstowcs(wchar_t* pwc, const char* s, size_t n); +int wctomb(char* s, wchar_t wchar); +int mbtowc(wchar_t* pwc, const char* s, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mem.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mem.h new file mode 100644 index 00000000..d6ae84d3 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mem.h @@ -0,0 +1,21 @@ +#ifndef _MSL_COMMON_MEM_H +#define _MSL_COMMON_MEM_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +int memcmp(const void*, const void*, size_t); +void* memchr(u8*, int, size_t); +u8* __memrchr(u8*, u8, size_t); +void* memmove(void*, const void*, size_t); +void* memcpy(void* dest, const void* src, size_t n); +void* memset(void* dest, int val, size_t count); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mem_funcs.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mem_funcs.h new file mode 100644 index 00000000..ef2f9c74 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/mem_funcs.h @@ -0,0 +1,16 @@ +#ifndef _MSL_COMMON_MEM_FUNCS_H +#define _MSL_COMMON_MEM_FUNCS_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +void __copy_longs_aligned(void* dst, const void* src, size_t len); +void __copy_longs_rev_aligned(void* dst, const void* src, size_t len); +void __copy_longs_unaligned(void* dst, const void* src, size_t len); +void __copy_longs_rev_unaligned(void* dst, const void* src, size_t len); + +#define srcCharPtr ((u8*)pSrc) +#define destCharPtr ((u8*)pDest) +#define srcLongPtr ((u32*)pSrc) +#define destLongPtr ((u32*)pDest) + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/misc_io.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/misc_io.h new file mode 100644 index 00000000..4e638b07 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/misc_io.h @@ -0,0 +1,8 @@ +#ifndef _MSL_COMMON_MISC_IO_H +#define _MSL_COMMON_MISC_IO_H + +extern void (*__stdio_exit)(void); + +void __stdio_atexit(void); + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h new file mode 100644 index 00000000..faf0e3d4 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h @@ -0,0 +1,43 @@ +#ifndef _MSL_TYPES_H +#define _MSL_TYPES_H + +typedef signed char s8; +typedef signed short s16; +typedef signed long s32; +typedef signed long long s64; +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +typedef unsigned long long u64; + +typedef float f32; +typedef double f64; +typedef long double f128; + +typedef unsigned int uint; + +#ifndef _SIZE_T_DEF +#define _SIZE_T_DEF +typedef unsigned long size_t; +#endif + +#ifndef __cplusplus +#ifndef _WCHAR_T_DEF +#define _WCHAR_T_DEF +typedef unsigned short wchar_t; +#endif +#endif + +typedef int BOOL; + +#define TRUE 1 +#define FALSE 0 + +#ifndef NULL +#define NULL ((void*)0) +#endif +#define nullptr 0 + +#define WEAKFUNC __declspec(weak) + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/printf.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/printf.h new file mode 100644 index 00000000..a5b7cae5 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/printf.h @@ -0,0 +1,15 @@ +#ifndef _MSL_COMMON_PRINTF_H +#define _MSL_COMMON_PRINTF_H + +#include "stdarg.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/file_struc.h" + +int printf(const char*, ...); +int fprintf(FILE*, const char* format, ...); +int vprintf(const char*, va_list); +int vsnprintf(char*, size_t, const char*, va_list); +int vsprintf(char*, const char*, va_list); +int snprintf(char*, size_t, const char*, ...); +int sprintf(char*, const char*, ...); + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/rand.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/rand.h new file mode 100644 index 00000000..cc1e4574 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/rand.h @@ -0,0 +1,17 @@ +#ifndef _MSL_COMMON_RAND_H +#define _MSL_COMMON_RAND_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +int rand(void); +void srand(u32 seed); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/scanf.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/scanf.h new file mode 100644 index 00000000..a37b4934 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/scanf.h @@ -0,0 +1,9 @@ +#ifndef _MSL_COMMON_SCANF_H +#define _MSL_COMMON_SCANF_H + +#include "stdarg.h" + +int vsscanf(const char*, const char*, va_list); +int sscanf(const char*, const char*, ...); + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/secure_error.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/secure_error.h new file mode 100644 index 00000000..d5b8deb5 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/secure_error.h @@ -0,0 +1,8 @@ +#ifndef _MSL_COMMON_SECURE_ERROR_H +#define _MSL_COMMON_SECURE_ERROR_H + +typedef void (*msl_constraint_handler)(int, int, int); + +void __msl_runtime_constraint_violation_s(int param1, int param2, int param3); + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/stdio_api.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/stdio_api.h new file mode 100644 index 00000000..009e35b9 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/stdio_api.h @@ -0,0 +1,35 @@ +#ifndef _MSL_COMMON_STDIO_API_H +#define _MSL_COMMON_STDIO_API_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +enum __ReadProcActions { __GetAChar, __UngetAChar, __TestForError }; + +enum __WReadProcActions { __GetAwChar, __UngetAwChar, __TestForwcsError }; + +typedef struct { + char* CharStr; + size_t MaxCharCount; + size_t CharsWritten; +} __OutStrCtrl; + +typedef struct { + char* NextChar; + int NullCharDetected; +} __InStrCtrl; + +typedef struct { + wchar_t* wCharStr; + size_t MaxCharCount; + size_t CharsWritten; +} __wOutStrCtrl; + +typedef struct { + wchar_t* wNextChar; + int wNullCharDetected; +} __wInStrCtrl; + +size_t __fwrite(const void* pPtr, size_t memb_size, size_t num_memb, FILE* pFile); +int __StringRead(void*, int, int); + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/string.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/string.h new file mode 100644 index 00000000..1af62429 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/string.h @@ -0,0 +1,25 @@ +#ifndef _MSL_COMMON_STRING_H +#define _MSL_COMMON_STRING_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/mem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +size_t strlen(const char*); +char* strcpy(char*, const char*); +char* strncpy(char*, const char*, size_t); +char* strcat(char*, const char*); +char* strncat(char*, const char*, size_t); +int strcmp(const char*, const char*); +int strncmp(const char*, const char*, size_t); +char* strchr(const char*, int); +char* strrchr(const char*, int); +char* strstr(const char*, const char*); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/strtold.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/strtold.h new file mode 100644 index 00000000..b47bf80a --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/strtold.h @@ -0,0 +1,16 @@ +#ifndef _MSL_COMMON_STRTOLD_H +#define _MSL_COMMON_STRTOLD_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +f128 __strtold(int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* overflow); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/strtoul.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/strtoul.h new file mode 100644 index 00000000..cc0b24df --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/strtoul.h @@ -0,0 +1,22 @@ +#ifndef _MSL_COMMON_STRTOUL_H +#define _MSL_COMMON_STRTOUL_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +u32 __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative, + int* overflow); +u64 __strtoull(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative, + int* overflow); +int atoi(const char* str); +u32 strtoul(const char* str, char** end, int base); +s32 strtol(const char* str, char** end, int base); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/PowerPC_EABI_Support/MSL_C/MSL_Common/wchar_io.h b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/wchar_io.h new file mode 100644 index 00000000..3f438675 --- /dev/null +++ b/include/PowerPC_EABI_Support/MSL_C/MSL_Common/wchar_io.h @@ -0,0 +1,8 @@ +#ifndef _MSL_COMMON_WCHAR_IO_H +#define _MSL_COMMON_WCHAR_IO_H + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +int fwide(FILE* stream, int mode); + +#endif diff --git a/include/TRK/AmcExi2Stubs.h b/include/TRK/AmcExi2Stubs.h new file mode 100644 index 00000000..58eaf9ef --- /dev/null +++ b/include/TRK/AmcExi2Stubs.h @@ -0,0 +1,33 @@ +#ifndef TRK_AMCEXI2STUBS_H +#define TRK_AMCEXI2STUBS_H + +#include "TRK/dstypes.h" +#include +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +// EXI callback function pointer type +typedef __OSInterruptHandler AmcEXICallback; + +// EXI error codes +typedef enum { + AMC_EXI_NO_ERROR = 0, + AMC_EXI_UNSELECTED + +} AmcExiError; + +void EXI2_Init(vu8**, AmcEXICallback); +void EXI2_EnableInterrupts(void); +int EXI2_Poll(void); +AmcExiError EXI2_ReadN(void*, u32); +AmcExiError EXI2_WriteN(const void*, u32); +void EXI2_Reserve(void); +void EXI2_Unreserve(void); +BOOL AMC_IsStub(void); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/TRK/CircleBuffer.h b/include/TRK/CircleBuffer.h new file mode 100644 index 00000000..b6e00d75 --- /dev/null +++ b/include/TRK/CircleBuffer.h @@ -0,0 +1,23 @@ +#ifndef TRK_CIRCLE_BUFFER_H +#define TRK_CIRCLE_BUFFER_H + +#include "TRK/dstypes.h" + +typedef struct CircleBuffer { + u8* mReadPtr; // _00 + u8* mWritePtr; // _04 + u8* mStartPtr; // _08 + u32 mSize; // _0C + u32 mBytesToRead; // _10 + u32 mBytesToWrite; // _14 + uint mSection; // _18 +} CircleBuffer; + +u32 CBGetBytesAvailableForRead(CircleBuffer* cb); +u32 CBGetBytesAvailableForWrite(CircleBuffer* cb); +void CircleBufferInitialize(CircleBuffer* cb, u8* buf, u32 size); +void CircleBufferTerminate(CircleBuffer* cb); +int CircleBufferWriteBytes(CircleBuffer* cb, u8* buf, u32 size); +int CircleBufferReadBytes(CircleBuffer* cb, u8* buf, u32 size); + +#endif diff --git a/include/TRK/dstypes.h b/include/TRK/dstypes.h new file mode 100644 index 00000000..a0425ddc --- /dev/null +++ b/include/TRK/dstypes.h @@ -0,0 +1,34 @@ +#ifndef TRK_DSTYPES_H +#define TRK_DSTYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +typedef unsigned int uint; + +typedef volatile u8 vu8; +typedef volatile u16 vu16; +typedef volatile u32 vu32; + +typedef unsigned char u128[16]; + +#define nullptr 0 + +#ifdef __MWERKS__ +#define WEAKFUNC __declspec(weak) +#define DECL_SECT(name) __declspec(section name) +#define ASM asm +#else +#define WEAKFUNC +#define DECL_SECT(name) +#define ASM +#endif + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/TRK/memmap.h b/include/TRK/memmap.h new file mode 100644 index 00000000..ec5becc1 --- /dev/null +++ b/include/TRK/memmap.h @@ -0,0 +1,15 @@ +#ifndef TRK_MEMMAP_H +#define TRK_MEMMAP_H +#include "TRK/dstypes.h" +#include "TRK/trk.h" + +typedef struct memRange { + u8* start; + u8* end; + BOOL readable; + BOOL writeable; +} memRange; + +const memRange gTRKMemMap[1] = { { (u8*)0, (u8*)-1, TRUE, TRUE } }; + +#endif diff --git a/include/TRK/ppc_reg.h b/include/TRK/ppc_reg.h new file mode 100644 index 00000000..22d3697b --- /dev/null +++ b/include/TRK/ppc_reg.h @@ -0,0 +1,242 @@ +#ifndef TRK_PPC_REG_H +#define TRK_PPC_REG_H + +#include "TRK/dstypes.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +typedef struct Default_PPC { + u32 GPR[32]; + u32 PC; + u32 LR; + u32 CR; + u32 CTR; + u32 XER; +} Default_PPC; + +typedef struct Float_PPC { + u64 FPR[32]; + u64 FPSCR; + u64 FPECR; +} Float_PPC; + +typedef struct Extended1_PPC_6xx_7xx { + // u8 pad[0x168]; + u32 SR[16]; + u32 TBL; + u32 TBU; + u32 HID0_; + u32 HID1; + u32 MSR; + u32 PVR; + u32 IBAT0U; + u32 IBAT0L; + u32 IBAT1U; + u32 IBAT1L; + u32 IBAT2U; + u32 IBAT2L; + u32 IBAT3U; + u32 IBAT3L; + u32 DBAT0U; + u32 DBAT0L; + u32 DBAT1U; + u32 DBAT1L; + u32 DBAT2U; + u32 DBAT2L; + u32 DBAT3U_; + u32 DBAT3L_; + u32 DMISS; + u32 DCMP; + u32 HASH1; + u32 HASH2; + u32 IMISS; + u32 ICMP; + u32 RPA; + u32 SDR1; + u32 DAR; + u32 DSISR; + u32 SPRG0; + u32 SPRG1; + u32 SPRG2; + u32 SPRG3; + u32 DEC; + u32 IABR; + u32 EAR; + u32 DABR; + u32 PMC1; + u32 PMC2; + u32 PMC3; + u32 PMC4; + u32 SIA; + u32 MMCR0; + u32 MMCR1; + u32 THRM1; + u32 THRM2; + u32 THRM3; + u32 ICTC; + u32 L2CR; + u32 UMMCR2; + u32 UBAMR; + u32 UMMCR0; + u32 UPMC1; + u32 UPMC2; + u32 USIA; + u32 UMMCR1; + u32 UPMC3; + u32 UPMC4; + u32 USDA; + u32 MMCR2; + u32 BAMR; + u32 SDA; + u32 MSSCR0; + u32 MSSCR1; + u32 PIR; + u32 exceptionID; + u32 GQR[8]; + u32 HID_G; + u32 WPAR; + u32 DMA_U_; + u32 DMA_L_; +} Extended1_PPC_6xx_7xx; + +typedef struct Extended2_PPC_6xx_7xx { + u32 PSR[32][2]; +} Extended2_PPC_6xx_7xx; + +typedef struct ProcessorState_PPC_6xx_7xx { + Default_PPC Default; + Float_PPC Float; + Extended1_PPC_6xx_7xx Extended1; + Extended2_PPC_6xx_7xx Extended2; + u32 transport_handler_saved_ra; +} ProcessorState_PPC_6xx_7xx; + +typedef ProcessorState_PPC_6xx_7xx ProcessorState_PPC; + +#define SPR_XER 1 +#define SPR_LR 8 +#define SPR_CTR 9 +#define SPR_DSISR 18 +#define SPR_DAR 19 +#define SPR_DEC 22 +#define SPR_SDR1 25 +#define SPR_SRR0 26 +#define SPR_SRR1 27 +#define SPR_SPRG0 272 +#define SPR_SPRG1 273 +#define SPR_SPRG2 274 +#define SPR_SPRG3 275 +#define SPR_EAR 282 +#define SPR_TBL 284 +#define SPR_TBU 285 +#define SPR_PVR 287 +#define SPR_IBAT0U 528 +#define SPR_IBAT0L 529 +#define SPR_IBAT1U 530 +#define SPR_IBAT1L 531 +#define SPR_IBAT2U 532 +#define SPR_IBAT2L 533 +#define SPR_IBAT3U 534 +#define SPR_IBAT3L 535 +#define SPR_IBAT4U 560 +#define SPR_IBAT4L 561 +#define SPR_IBAT5U 562 +#define SPR_IBAT5L 563 +#define SPR_IBAT6U 564 +#define SPR_IBAT6L 565 +#define SPR_IBAT7U 566 +#define SPR_IBAT7L 567 +#define SPR_DBAT0U 536 +#define SPR_DBAT0L 537 +#define SPR_DBAT1U 538 +#define SPR_DBAT1L 539 +#define SPR_DBAT2U 540 +#define SPR_DBAT2L 541 +#define SPR_DBAT3U 542 +#define SPR_DBAT3L 543 +#define SPR_DBAT4U 568 +#define SPR_DBAT4L 569 +#define SPR_DBAT5U 570 +#define SPR_DBAT5L 571 +#define SPR_DBAT6U 572 +#define SPR_DBAT6L 573 +#define SPR_DBAT7U 574 +#define SPR_DBAT7L 575 +#define SPR_GQR0 912 +#define SPR_GQR1 913 +#define SPR_GQR2 914 +#define SPR_GQR3 915 +#define SPR_GQR4 916 +#define SPR_GQR5 917 +#define SPR_GQR6 918 +#define SPR_GQR7 919 +#define SPR_HID2 920 +#define SPR_WPAR 921 +#define SPR_DMA_U 922 +#define SPR_DMA_L 923 +#define SPR_UMMCR0 936 +#define SPR_UPMC1 937 +#define SPR_UPMC2 938 +#define SPR_USIA 939 +#define SPR_UMMCR1 940 +#define SPR_UPMC3 941 +#define SPR_UPMC4 942 +#define SPR_USDA 943 +#define SPR_MMCR0 952 +#define SPR_PMC1 953 +#define SPR_PMC2 954 +#define SPR_SIA 955 +#define SPR_MMCR1 956 +#define SPR_PMC3 957 +#define SPR_PMC4 958 +#define SPR_SDA 959 +#define SPR_HID0 1008 +#define SPR_HID1 1009 +#define SPR_IABR 1010 +#define SPR_HID4 1011 +#define SPR_DABR 1013 +#define SPR_L2CR 1017 +#define SPR_ICTC 1019 +#define SPR_THRM1 1020 +#define SPR_THRM2 1021 +#define SPR_FPECR 1022 + +// PPC exceptions +// 0x000 is reserved +#define PPC_SystemReset 0x100 +#define PPC_MachineCheck 0x200 +#define PPC_DataStorage 0x300 +#define PPC_InstructionStorage 0x400 +#define PPC_ExternalInterrupt 0x500 +#define PPC_Alignment 0x600 +#define PPC_Program 0x700 +#define PPC_FloatingPointUnavailable 0x800 +#define PPC_Decrementer 0x900 +// 0xA00-0xB00 are reserved +#define PPC_SystemCall 0xC00 +#define PPC_Trace 0xD00 +#define PPC_FloatingPointAssist 0xE00 // unimplemented in 750CL +#define PPC_PerformanceMonitor 0xF00 // Dolphin/Broadway specific +// 0x1000-0x1200 are unimplemented in 750CL +#define PPC_InstructionAddressBreakpoint 0x1300 // Dolphin/Broadway specific +// 0x1400-0x2F00 are reserved, but TRK uses some +#define PPC_SystemManagementInterrupt 0x1400 +// 0x1500-0x1600 are unimplemented in 750CL +#define PPC_ThermalManagementInterrupt 0x1700 +#define PPC_1800Exception 0x1800 +#define PPC_1900Exception 0x1900 +#define PPC_1A00Exception 0x1A00 +#define PPC_1B00Exception 0x1B00 +#define PPC_1C00Exception 0x1C00 // Data breakpoint? +#define PPC_1D00Exception 0x1D00 // Instruction breakpoint? +#define PPC_1E00Exception 0x1E00 // Peripheral breakpoint? +#define PPC_1F00Exception 0x1F00 // Non maskable development port? +#define PPC_2000Exception 0x2000 + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/TRK/trk.h b/include/TRK/trk.h new file mode 100644 index 00000000..2075ea7f --- /dev/null +++ b/include/TRK/trk.h @@ -0,0 +1,201 @@ +#ifndef TRK_TRK_H +#define TRK_TRK_H + +#include "TRK/dstypes.h" +#include "TRK/trktypes.h" +#include "TRK/ppc_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +////// MSG HANDLING FUNCTIONS ////// +DSError TRKDoConnect(MessageBuffer*); +DSError TRKDoDisconnect(MessageBuffer*); +DSError TRKDoReset(MessageBuffer*); +DSError TRKDoVersions(MessageBuffer*); +DSError TRKDoSupportMask(MessageBuffer*); +DSError TRKDoOverride(MessageBuffer*); +DSError TRKDoReadMemory(MessageBuffer*); +DSError TRKDoWriteMemory(MessageBuffer*); +DSError TRKDoReadRegisters(MessageBuffer*); +DSError TRKDoWriteRegisters(MessageBuffer*); +DSError TRKDoSetOption(MessageBuffer*); +DSError TRKDoContinue(MessageBuffer*); +DSError TRKDoStep(MessageBuffer*); +DSError TRKDoStop(MessageBuffer*); + +void SetBufferPosition(MessageBuffer*, u32); +void SetTRKConnected(int); +int GetTRKConnected(void); + +DSError TRKGetFreeBuffer(int*, MessageBuffer**); +void OutputData(void* data, int length); +void TRKResetBuffer(MessageBuffer* msg, BOOL keepData); + +DSError TRKReadBuffer1_ui64(MessageBuffer* buffer, u64* data); +DSError TRKAppendBuffer1_ui64(MessageBuffer* buffer, const u64 data); +//////////////////////////////////// + +/////// DOLPHIN TRK FUNCTIONS ////// +void InitMetroTRK(void); +void InitMetroTRK_BBA(void); +void EnableMetroTRKInterrupts(void); + +void TRKLoadContext(OSContext* ctx, u32); +void TRKSaveExtended1Block(); +void TRKRestoreExtended1Block(); +int InitMetroTRKCommTable(int); +void TRK_board_display(char*); +//////////////////////////////////// + +////////// GDEV FUNCTIONS ////////// +int gdev_cc_initialize(void* flagOut, __OSInterruptHandler handler); +int gdev_cc_shutdown(); +int gdev_cc_open(); +int gdev_cc_close(); +int gdev_cc_read(u8* dest, int size); +int gdev_cc_write(const u8* src, int size); +int gdev_cc_pre_continue(); +int gdev_cc_post_stop(); +int gdev_cc_peek(); +int gdev_cc_initinterrupts(); +//////////////////////////////////// + +/////////// UDP FUNCTIONS ////////// +int udp_cc_initialize(void* flagOut, __OSInterruptHandler handler); +int udp_cc_shutdown(); +int udp_cc_open(); +int udp_cc_close(); +int udp_cc_read(u8* dest, int size); +int udp_cc_write(const u8* src, int size); +int udp_cc_pre_continue(); +int udp_cc_post_stop(); +int udp_cc_peek(); +int udp_cc_initinterrupts(); +//////////////////////////////////// + +/////////// DDH FUNCTIONS ////////// +#define DDH_ERR_NOT_INITIALIZED -0x2711 +#define DDH_ERR_ALREADY_INITIALIZED -0x2715 +#define DDH_ERR_READ_ERROR -0x2719 + +int ddh_cc_initialize(void* flagOut, __OSInterruptHandler handler); +int ddh_cc_shutdown(); +int ddh_cc_open(); +int ddh_cc_close(); +int ddh_cc_read(u8* dest, int size); +int ddh_cc_write(const u8* src, int size); +int ddh_cc_pre_continue(); +int ddh_cc_post_stop(); +int ddh_cc_peek(); +int ddh_cc_initinterrupts(); +//////////////////////////////////// + +////////// EVENT FUNCTIONS ///////// +void TRKConstructEvent(TRKEvent* event, int eventType); +void TRKDestructEvent(TRKEvent* event); +DSError TRKPostEvent(TRKEvent* event); +BOOL TRKGetNextEvent(TRKEvent* event); +DSError TRKDispatchMessage(MessageBuffer*); +void* TRKGetBuffer(int); +void TRKReleaseBuffer(int); +void TRKGetInput(); +//////////////////////////////////// + +///////// TARGET FUNCTIONS ///////// +DSError TRKTargetContinue(void); +DSError TRKTargetInterrupt(TRKEvent*); +BOOL TRKTargetStopped(); +void TRKTargetSetStopped(uint); +DSError TRKTargetSupportRequest(); +//////////////////////////////////// + +////// NUB AND MEM FUNCTIONS /////// +DSError TRKAppendBuffer_ui8(MessageBuffer*, const u8*, int); +DSError TRKSetBufferPosition(MessageBuffer*, u32); + +DSError TRKMessageSend(MessageBuffer*); +void TRKSwapAndGo(void); +DSError TRKInitializeNub(void); +DSError TRKTerminateNub(void); +void TRKNubWelcome(void); +void TRKNubMainLoop(void); + +DSError TRKInitializeMutex(void*); +DSError TRKAcquireMutex(void*); +DSError TRKReleaseMutex(void*); +void* TRK_memcpy(void* dst, const void* src, size_t n); +//////////////////////////////////// + +/////// INITIALIZE FUNCTIONS /////// +DSError TRKInitializeEventQueue(); +DSError TRKInitializeMessageBuffers(); +DSError TRKInitializeDispatcher(); +DSError InitializeProgramEndTrap(); +DSError TRKInitializeSerialHandler(); +DSError TRKTerminateSerialHandler(); +DSError TRKInitializeTarget(); +//////////////////////////////////// + +////////// EXI2 FUNCTIONS ////////// +/* EXI2 */ +void UnreserveEXI2Port(void); +void ReserveEXI2Port(void); +//////////////////////////////////// + +/////////// MW FUNCTIONS /////////// +void MWTRACE(u8, char*, ...); +//////////////////////////////////// + +//////// SUPPORT FUNCTIONS ///////// +DSError TRKRequestSend(); +u32 TRKAccessFile(u32, u32, u32*, u8*); +//////////////////////////////////// + +////////// OTHER FUNCTIONS ///////// +DSError TRK_main(void); +UARTError InitializeUART(UARTBaudRate baudRate); +DSError TRKInitializeIntDrivenUART(u32, u32, u32, void*); +int TRKPollUART(); +UARTError TRKReadUARTN(void*, u32); +UARTError TRKWriteUARTN(const void* bytes, u32 length); +void usr_put_initialize(); +void TRKTargetSetInputPendingPtr(void*); +void SetUseSerialIO(u8); +u8 GetUseSerialIO(void); + +DSError TRKTargetAddStopInfo(MessageBuffer*); +void TRKTargetAddExceptionInfo(MessageBuffer*); +void TRKInterruptHandler(); +BOOL usr_puts_serial(const char* msg); +//////////////////////////////////// + +//////// EXTERNAL DECLARES ///////// +extern BOOL gTRKBigEndian; +extern void* gTRKInputPendingPtr; +extern ProcessorState_PPC gTRKCPUState; +extern ProcessorRestoreFlags_PPC gTRKRestoreFlags; +extern u8 gTRKInterruptVectorTable[]; +extern TRKState gTRKState; +extern MessageBuffer gTRKMsgBufs[3]; +//////////////////////////////////// + +////////// USEFUL STATICS ////////// +static inline DSError TRKAppendBuffer1_ui8(MessageBuffer* buffer, const u8 data) +{ + if (buffer->position >= 0x880) { + return DS_MessageBufferOverflow; + } + + buffer->data[buffer->position++] = data; + buffer->length++; + return DS_NoError; +} +//////////////////////////////////// + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/TRK/trkenum.h b/include/TRK/trkenum.h new file mode 100644 index 00000000..4e67cc72 --- /dev/null +++ b/include/TRK/trkenum.h @@ -0,0 +1,201 @@ +#ifndef TRK_TRKENUM_H +#define TRK_TRKENUM_H + +#include "TRK/dstypes.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +//////////// TRK ENUMS ///////////// +// Hardware types. +typedef enum { + HARDWARE_AMC_DDH = 0, + HARDWARE_GDEV = 1, + HARDWARE_BBA = 2, +} HardwareType; + +// DS Error returns. +typedef enum { + DS_NoError = 0x0, + DS_StepError = 0x1, + DS_ParameterError = 0x2, + + DS_EventQueueFull = 0x100, + + DS_NoMessageBufferAvailable = 0x300, + DS_MessageBufferOverflow = 0x301, + DS_MessageBufferReadError = 0x302, + + DS_DispatchError = 0x500, + + DS_InvalidMemory = 0x700, + DS_InvalidRegister = 0x701, + DS_CWDSException = 0x702, + DS_UnsupportedError = 0x703, + DS_InvalidProcessID = 0x704, + DS_InvalidThreadID = 0x705, + DS_OSError = 0x706, + + DS_Error800 = 0x800, +} DSError; + +// Where to read/write. +typedef enum { + DS_Stdin = 0, + DS_Stdout = 1, + DS_Stderr = 2, +} DSFileHandle; + +// IO returns. +typedef enum { + DS_IONoError = 0, + DS_IOError = 1, + DS_IOEOF = 2, +} DSIOResult; + +// Message command IDs +typedef enum { + DSMSG_Ping = 0x0, + DSMSG_Connect = 0x1, + DSMSG_Disconnect = 0x2, + DSMSG_Reset = 0x3, + DSMSG_Versions = 0x4, + DSMSG_SupportMask = 0x5, + DSMSG_Override = 0x7, + + DSMSG_ReadMemory = 0x10, + DSMSG_WriteMemory = 0x11, + DSMSG_ReadRegisters = 0x12, + DSMSG_WriteRegisters = 0x13, + DSMSG_SetOption = 0x17, + DSMSG_Continue = 0x18, + DSMSG_Step = 0x19, + DSMSG_Stop = 0x1A, + + DSMSG_ReplyACK = 0x80, + + DSMSG_NotifyStopped = 0x90, + DSMSG_NotifyException = 0x91, + + DSMSG_WriteFile = 0xD0, + DSMSG_ReadFile = 0xD1, + DSMSG_OpenFile = 0xD2, + DSMSG_CloseFile = 0xD3, + DSMSG_PositionFile = 0xD4, + + DSMSG_ReplyNAK = 0xFF, +} MessageCommandID; + +// Register commands. +typedef enum { + DSREG_Default = 0, + DSREG_FP = 1, + DSREG_Extended1 = 2, + DSREG_Extended2 = 3, +} DSMessageRegisterOptions; + +// Step commands. +typedef enum { + DSSTEP_IntoCount = 0x0, + DSSTEP_IntoRange = 0x1, + DSSTEP_OverCount = 0x10, + DSSTEP_OverRange = 0x11, +} DSMessageStepOptions; + +typedef enum { + DSREPLY_NoError = 0x0, + DSREPLY_Error = 0x1, + DSREPLY_PacketSizeError = 0x2, + DSREPLY_CWDSError = 0x3, + DSREPLY_EscapeError = 0x4, + DSREPLY_BadFCS = 0x5, + DSREPLY_Overflow = 0x6, + DSREPLY_SequenceMissing = 0x7, + + DSREPLY_UnsupportedCommandError = 0x10, + DSREPLY_ParameterError = 0x11, + DSREPLY_UnsupportedOptionError = 0x12, + DSREPLY_InvalidMemoryRange = 0x13, + DSREPLY_InvalidRegisterRange = 0x14, + DSREPLY_CWDSException = 0x15, + DSREPLY_NotStopped = 0x16, + DSREPLY_BreakpointsFull = 0x17, + DSREPLY_BreakpointConflict = 0x18, + + DSREPLY_OSError = 0x20, + DSREPLY_InvalidProcessID = 0x21, + DSREPLY_InvalidThreadID = 0x22, + DSREPLY_DebugSecurityError = 0x23, +} DSReplyError; + +typedef enum { + DSRECV_Wait = 0, + DSRECV_Found = 1, + DSRECV_InFrame = 2, + DSRECV_FrameOverflow = 3, +} ReceiverState; + +typedef enum { + DSMSGMEMORY_Segmented = 0x01, /* non-flat addr space */ + DSMSGMEMORY_Extended = 0x02, /* > 32-bit data addr */ + DSMSGMEMORY_Protected = 0x04, /* non-user memory */ + DSMSGMEMORY_Userview = 0x08, /* breakpoints are invisible */ + DSMSGMEMORY_Space_program = 0x00, + DSMSGMEMORY_Space_data = 0x40, + DSMSGMEMORY_Space_io = 0x80 +}; + +typedef enum { + NUBEVENT_Null = 0, + NUBEVENT_Shutdown = 1, + NUBEVENT_Request = 2, + NUBEVENT_Breakpoint = 3, + NUBEVENT_Exception = 4, + NUBEVENT_Support = 5, +} NubEventType; + +typedef enum { + VALIDMEM_Readable = 0, + VALIDMEM_Writeable = 1, +} ValidMemoryOptions; + +typedef enum { + MEMACCESS_UserMemory = 0, + MEMACCESS_DebuggerMemory = 1, +} MemoryAccessOptions; + +typedef enum { + UART_NoError = 0, + UART_UnknownBaudRate = 1, + UART_ConfigurationError = 2, + UART_BufferOverflow = 3, // specified buffer was too small + UART_NoData = 4, // no data available from polling +} UARTErrorOptions; + +typedef enum { + kBaudHWSet = -1, // use HW settings such as DIP switches + kBaud300 = 300, // valid baud rates + kBaud600 = 600, + kBaud1200 = 1200, + kBaud1800 = 1800, + kBaud2000 = 2000, + kBaud2400 = 2400, + kBaud3600 = 3600, + kBaud4800 = 4800, + kBaud7200 = 7200, + kBaud9600 = 9600, + kBaud19200 = 19200, + kBaud38400 = 38400, + kBaud57600 = 57600, + kBaud115200 = 115200, + kBaud230400 = 230400 +} UARTBaudRate; + +//////////////////////////////////// + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/TRK/trktypes.h b/include/TRK/trktypes.h new file mode 100644 index 00000000..469163b0 --- /dev/null +++ b/include/TRK/trktypes.h @@ -0,0 +1,147 @@ +#ifndef TRK_TRKTYPES_H +#define TRK_TRKTYPES_H + +#include "TRK/dstypes.h" +#include +#include "TRK/trkenum.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +/////// TRK STRUCTS AND TYPES ////// +// Function types for DB communications. +typedef int (*DBCommFunc)(); +typedef int (*DBCommInitFunc)(void*, __OSInterruptHandler); +typedef int (*DBCommReadFunc)(u8*, int); +typedef int (*DBCommWriteFunc)(const u8*, int); + +// Message buffer ID type. +typedef int MessageBufferID; + +// Nub event ID type. +typedef u32 NubEventID; + +// UART Error type. +typedef int UARTError; + +// Size of message buffer. +#define TRKMSGBUF_SIZE (0x800 + 0x80) + +// Struct for sending and receiving messages (size 0x88C). +typedef struct MessageBuffer { + u32 _00; // _00, unknown + BOOL isInUse; // _04 + u32 length; // _08 + u32 position; // _0C + u8 data[TRKMSGBUF_SIZE]; // _10 +} MessageBuffer; + +// Struct for storing DB communication functions (size 0x28). +typedef struct DBCommTable { + DBCommInitFunc initialize_func; // _00 + DBCommFunc init_interrupts_func; // _04 + DBCommFunc shutdown_func; // _08 + DBCommFunc peek_func; // _0C + DBCommReadFunc read_func; // _10 + DBCommWriteFunc write_func; // _14 + DBCommFunc open_func; // _18 + DBCommFunc close_func; // _1C + DBCommFunc pre_continue_func; // _20 + DBCommFunc post_stop_func; // _24 +} DBCommTable; + +// Struct for information on DS versions (kernel and protocol) (size 0x4) +typedef struct DSVersions { + u8 kernelMajor; // _00 + u8 kernelMinor; // _01 + u8 protocolMajor; // _02 + u8 protocolMinor; // _03 +} DSVersions; + +// Struct for packet information (size 0x8). +typedef struct TRKPacketSeq { + u16 _00; // _00, unknown + u8 _02[6]; // _02, unknown +} TRKPacketSeq; + +// Struct for receiving packets from serial poll (size 0x14). +typedef struct TRKFramingState { + MessageBufferID msgBufID; // _00 + MessageBuffer* buffer; // _04 + ReceiverState receiveState; // _08 + BOOL isEscape; // _0C + u8 fcsType; // _10 +} TRKFramingState; + +// Command reply information (size 0x40). +typedef struct CommandReply { + u32 _00; // _00 + union { + u8 b; + MessageCommandID m; + } commandID; // _04, use MessageCommandID enum + union { + u8 b; + DSReplyError r; + } replyError; // _08, use DSReplyError enum - should be enum type? check size. + u32 _0C; // _0C + u8 _10[0x30]; // _10, unknown +} CommandReply; + +// Nub event information (size 0xC). +typedef struct TRKEvent { + NubEventType eventType; // _00 + NubEventID eventID; // _04 + MessageBufferID msgBufID; // _08 +} TRKEvent; + +// Event queue (size 0x28). +typedef struct TRKEventQueue { + u8 _00[4]; // _00, unknown + int count; // _04, number of events in queue + int next; // _08, next event in `events` to handle (0 or 1) + TRKEvent events[2]; // _0C + NubEventID eventID; // _24, ID to assign next event, min 0x100 +} TRKEventQueue; + +// Struct for state information (size 0xB0). +typedef struct TRKState { + u32 gpr[32]; // _00 + u32 lr; // _80 + u32 ctr; // _84 + u32 xer; // _88 + u32 msr; // _8C + u32 dar; // _90 + u32 dsisr; // _94 + BOOL isStopped; // _98 + BOOL inputActivated; // _9C + void* inputPendingPtr; // _A0 +} TRKState; + +typedef struct TRKState_PPC { + u32 GPR[32]; // 0x0 + u32 LR; // 0x80 + u32 CTR; // 0x84 + u32 XER; // 0x88 + u32 MSR; // 0x8c + u32 DAR; // 0x90 + u32 DSISR; // 0x94 + BOOL stopped; // 0x98 + BOOL inputActivated; // 0x9c + u8* inputPendingPtr; // 0xA0 +} TRKState_PPC; + +typedef struct ProcessorRestoreFlags_PPC { + u8 TBR; + u8 DEC; + u8 linker_padding[0x9 - 0x2]; +} ProcessorRestoreFlags_PPC; + +//////////////////////////////////// + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/src/static/MSL_C.PPCEABI.bare.H/FILE_POS.C b/src/static/MSL_C.PPCEABI.bare.H/FILE_POS.C new file mode 100644 index 00000000..e5363458 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/FILE_POS.C @@ -0,0 +1,147 @@ +#ifndef _MSL_WIDE_CHAR +#define _MSL_WIDE_CHAR +#endif + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/FILE_POS.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h" + +int ftell(FILE* stream) +{ + int retval; + + __begin_critical_region(stdin_access); + retval = (s32)_ftell(stream); + __end_critical_region(stdin_access); + return retval; +} + +int _ftell(FILE* file) +{ + int charsInUndoBuffer = 0; + int position; + + u8 tmp_kind = file->mMode.file_kind; + if (!(tmp_kind == __disk_file || tmp_kind == __console_file) || file->mState.error) { + errno = EFPOS; + return -1; + } + + if (file->mState.io_state == __neutral) + return (file->mPosition); + + position = file->mBufferPosition + (file->mBufferPtr - file->mBuffer); + + if (file->mState.io_state >= __rereading) { + charsInUndoBuffer = file->mState.io_state - __rereading + 1; + position -= charsInUndoBuffer; + } + + if (!file->mMode.binary_io) { + int n = file->mBufferPtr - file->mBuffer - charsInUndoBuffer; + u8* p = (u8*)file->mBuffer; + + while (n--) + if (*p++ == '\n') + position++; + } + + return (position); +} + +int _fseek(FILE* file, u32 offset, int whence) +{ + int bufferCode; + int pos; + int adjust; + u32 state; + int buffLen; + + char* ptr; + + if (file->mMode.file_kind != __disk_file || file->mState.error != 0) { + errno = EFPOS; + return -1; + } + + if (file->mState.io_state == __writing) { + if (__flush_buffer(file, nullptr) != 0) { + file->mState.error = 1; + file->mBufferLength = 0; + errno = EFPOS; + return -1; + } + } + + if (whence == SEEK_CUR) { + whence = SEEK_SET; + adjust = 0; + if ((file->mMode.file_kind != __disk_file && file->mMode.file_kind != __console_file) || file->mState.error != 0) { + errno = EFPOS; + pos = -1; + } else { + state = file->mState.io_state; + if (state == __neutral) { + pos = file->mPosition; + } else { + pos = file->mBufferPosition; + ptr = file->mBuffer; + buffLen = (file->mBufferPtr - ptr); + pos += buffLen; + if ((state >= __rereading)) { + adjust = (state - 2); + pos -= adjust; + } + + if (file->mMode.binary_io == 0) { + int i; + for (i = (buffLen - adjust); i != 0; i--) { + u8 c = *ptr; + ptr++; + if (c == 10) { + pos++; + } + } + } + } + } + offset += pos; + } + + if ((whence != SEEK_END) && (file->mMode.io_mode != 3) + && (file->mState.io_state == __reading || file->mState.io_state == __rereading)) { + if ((offset >= file->mPosition) || !(offset >= file->mBufferPosition)) { + file->mState.io_state = __neutral; + } else { + file->mBufferPtr = file->mBuffer + (offset - file->mBufferPosition); + file->mBufferLength = file->mPosition - offset; + file->mState.io_state = __reading; + } + } else { + file->mState.io_state = __neutral; + } + + if (file->mState.io_state == __neutral) { + if (file->positionFunc != nullptr && (int)file->positionFunc(file->mHandle, &offset, whence, file->ref_con)) { + file->mState.error = 1; + file->mBufferLength = 0; + errno = EFPOS; + return -1; + } else { + file->mState.eof = 0; + file->mPosition = offset; + file->mBufferLength = 0; + } + } + + return 0; +} + +int fseek(FILE* stream, u32 offset, int whence) +{ + int code; + __begin_critical_region(stdin_access); + code = _fseek(stream, offset, whence); // 0 if successful, -1 if error + __end_critical_region(stdin_access); + return code; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/abort_exit.c b/src/static/MSL_C.PPCEABI.bare.H/abort_exit.c new file mode 100644 index 00000000..4ae498f2 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/abort_exit.c @@ -0,0 +1,46 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +void __destroy_global_chain(void); +void _ExitProcess(void); + +extern void (*_dtors[])(void); + +static void (*__console_exit)(void); +void (*__stdio_exit)(void); +static int __atexit_curr_func; +int __aborting; + +static void (*__atexit_funcs[64])(void); + +void exit(int status) +{ + int i; + void (**dtor)(void); + + if (!__aborting) { + __begin_critical_region(atexit_funcs_access); + __end_critical_region(atexit_funcs_access); + __destroy_global_chain(); + dtor = _dtors; + while (*dtor != NULL) { + (*dtor)(); + dtor++; + } + if (__stdio_exit != NULL) { + __stdio_exit(); + __stdio_exit = NULL; + } + } + __begin_critical_region(atexit_funcs_access); + while (__atexit_curr_func > 0) + __atexit_funcs[--__atexit_curr_func](); + __end_critical_region(atexit_funcs_access); + __kill_critical_regions(); + if (__console_exit != NULL) { + + __console_exit(); + __console_exit = NULL; + } + _ExitProcess(); +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/ansi_files.c b/src/static/MSL_C.PPCEABI.bare.H/ansi_files.c new file mode 100644 index 00000000..a1cee15d --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/ansi_files.c @@ -0,0 +1,153 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/file_io.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h" + +static char stdin_buff[0x100]; +static char stdout_buff[0x100]; +static char stderr_buff[0x100]; + +int __read_console(__file_handle handle, char* buffer, size_t* count, __ref_con ref_con); +int __write_console(__file_handle handle, char* buffer, size_t* count, __ref_con ref_con); +int __close_console(__file_handle handle); + +// clang-format off +FILE __files[4] = +{ + { 0, // _00 + 0, // _04, open_mode + 1, // _04, io_mode + 1, // _04, buffer_mode + __console_file, // _04, file_kind + 0, // _04, binary_io + __neutral, // _08, io_state + 0, // _08, free_buffer + 0, // _08, eof + 0, // _08, error + 0, // _0C + 0, // _0D + 0, // _0E + 0, // _0F + 0, // _10 + 0, // _12 + 0, // _14 + 0, // _18 + stdin_buff, // _1C + sizeof(stdin_buff), // _20 + stdin_buff, // _24 + 0, // _28 + 0, // _2C + 0, // _30 + 0, // _34 + nullptr, // _38 + &__read_console, // _3C + &__write_console, // _40 + &__close_console, // _44 + 0, // _48 + &__files[1] // _4C + }, + { 1, // _00 + 0, // _04, open_mode + 2, // _04, io_mode + 1, // _04, buffer_mode + __console_file, // _04, file_kind + 0, // _04, binary_io + __neutral, // _08, io_state + 0, // _08, free_buffer + 0, // _08, eof + 0, // _08, error + 0, // _0C + 0, // _0D + 0, // _0E + 0, // _0F + 0, // _10 + 0, // _12 + 0, // _14 + 0, // _18 + stdout_buff, // _1C + sizeof(stdout_buff), // _20 + stdout_buff, // _24 + 0, // _28 + 0, // _2C + 0, // _30 + 0, // _34 + nullptr, // _38 + &__read_console, // _3C + &__write_console, // _40 + &__close_console, // _44 + 0, // _48 + &__files[2] // _4C + }, + { 2, // _00 + 0, // _04, open_mode + 2, // _04, io_mode + 0, // _04, buffer_mode + __console_file, // _04, file_kind + 0, // _04, binary_io + __neutral, // _08, io_state + 0, // _08, free_buffer + 0, // _08, eof + 0, // _08, error + 0, // _0C + 0, // _0D + 0, // _0E + 0, // _0F + 0, // _10 + 0, // _12 + 0, // _14 + 0, // _18 + stderr_buff, // _1C + sizeof(stderr_buff), // _20 + stderr_buff, // _24 + 0, // _28 + 0, // _2C + 0, // _30 + 0, // _34 + nullptr, // _38 + &__read_console, // _3C + &__write_console, // _40 + &__close_console, // _44 + 0, // _48 + &__files[3] // _4C + }, +}; +// clang-format on + +void __close_all(void) +{ + FILE* p = &__files[0]; + FILE* plast; + + __begin_critical_region(stdin_access); + + while (p) { + if (p->mMode.file_kind != __closed_file) { + fclose(p); + } + + plast = p; + p = p->mNextFile; + if (plast->mIsDynamicallyAllocated) + free(plast); + else { + plast->mMode.file_kind = __unavailable_file; + if ((p != NULL) && p->mIsDynamicallyAllocated) + plast->mNextFile = nullptr; + } + } + + __end_critical_region(stdin_access); +} + +u32 __flush_all(void) +{ + u32 retval = 0; + FILE* __stream; + __stream = &__files[0]; + while (__stream) { + if ((__stream->mMode.file_kind) && (fflush(__stream))) { + retval = -1; + } + __stream = __stream->mNextFile; + }; + return retval; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/ansi_fp.c b/src/static/MSL_C.PPCEABI.bare.H/ansi_fp.c new file mode 100644 index 00000000..3c19c830 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/ansi_fp.c @@ -0,0 +1,775 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_fp.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/limits.h" + +static int __count_trailing_zerol(u32 x) +{ + int result = 0; + int bits_not_checked = sizeof(u32) * CHAR_BIT; + int n = bits_not_checked / 2; + int mask_size = n; + u32 mask = (~0UL) >> (bits_not_checked - n); + + while (bits_not_checked) { + if (!(x & mask)) { + result += mask_size; + x >>= mask_size; + bits_not_checked -= mask_size; + } else if (mask == 1) { + break; + } + + if (n > 1) { + n /= 2; + } + + if (mask > 1) { + mask >>= n; + mask_size -= n; + } + } + return result; +} + +static int __count_trailing_zero(f64 x) +{ + u32* l = (u32*)&x; + + if (l[1] != 0) { + return __count_trailing_zerol(l[1]); + } + + return (int)(sizeof(u32) * CHAR_BIT + __count_trailing_zerol(l[0] | 0x00100000)); +} + +static int __must_round(const decimal* d, int digits) +{ + u8 const* i = d->sig.text + digits; + + if (*i > 5) { + return 1; + } + + if (*i < 5) { + return -1; + } + + { + u8 const* e = d->sig.text + d->sig.length; + + for (i++; i < e; i++) { + if (*i != 0) { + return 1; + } + } + } + + if (d->sig.text[digits - 1] & 1) { + return 1; + } + + return -1; +} + +static void __dorounddecup(decimal* d, int digits) +{ + u8* b = d->sig.text; + u8* i = b + digits - 1; + + while (1) { + if (*i < 9) { + *i += 1; + break; + } + if (i == b) { + *i = 1; + d->exp++; + break; + } + *i-- = 0; + } +} + +static void __rounddec(decimal* d, int digits) +{ + if (digits > 0 && digits < d->sig.length) { + int unkBool = __must_round(d, digits); + d->sig.length = digits; + + if (unkBool >= 0) { + __dorounddecup(d, digits); + } + } +} + +void __ull2dec(decimal* result, u64 val) +{ + result->sign = 0; + + if (val == 0) { + result->exp = 0; + result->sig.length = 1; + result->sig.text[0] = 0; + return; + } + + if (val < 0) { + val = -val; + result->sign = 1; + } + + result->sig.length = 0; + + for (; val != 0; val /= 10) { + result->sig.text[result->sig.length++] = (u8)(val % 10); + } + + { + u8* i = result->sig.text; + u8* j = result->sig.text + result->sig.length; + + for (; i < --j; ++i) { + u8 t = *i; + *i = *j; + *j = t; + } + } + + result->exp = result->sig.length - 1; +} + +void __timesdec(decimal* result, const decimal* x, const decimal* y) +{ + u32 accumulator = 0; + u8 mantissa[SIGDIGLEN * 2]; + int i = x->sig.length + y->sig.length - 1; + u8* pDigit; + u8* ip = mantissa + i + 1; + u8* ep = ip; + + result->sign = 0; + + for (; i > 0; i--) { + int k = y->sig.length - 1; + int j = i - k - 1; + int l; + int t; + const u8* jp; + const u8* kp; + + if (j < 0) { + j = 0; + k = i - 1; + } + + jp = x->sig.text + j; + kp = y->sig.text + k; + l = k + 1; + t = x->sig.length - j; + + if (l > t) + l = t; + + for (; l > 0; l--, jp++, kp--) { + accumulator += *jp * *kp; + } + + *--ip = (u8)(accumulator % 10); + accumulator /= 10; + } + + result->exp = (s16)(x->exp + y->exp); + + if (accumulator) { + *--ip = (u8)(accumulator); + result->exp++; + } + + for (i = 0; i < SIGDIGLEN && ip < ep; i++, ip++) { + result->sig.text[i] = *ip; + } + result->sig.length = (u8)(i); + + if (ip < ep && *ip >= 5) { + if (*ip == 5) { + u8* jp = ip + 1; + for (; jp < ep; jp++) { + if (*jp != 0) + goto round; + } + if ((ip[-1] & 1) == 0) + return; + } + round: + __dorounddecup(result, result->sig.length); + } +} + +void __str2dec(decimal* d, const char* s, s16 exp) +{ + int i; + + d->exp = exp; + d->sign = 0; + + for (i = 0; i < SIGDIGLEN && *s;) { + d->sig.text[i++] = *s++ - '0'; + } + d->sig.length = i; + + if (*s != 0) { + if (*s < 5) + return; + if (*s > 5) + goto round; + + { + const char* p = s + 1; + + for (; *p != 0; p++) { + if (*p != '0') + goto round; + } + + if ((d->sig.text[i - 1] & 1) == 0) + return; + } + round: + __dorounddecup(d, d->sig.length); + } +} + +void __two_exp(decimal* result, s32 exp) +{ + switch (exp) { + case -64: + __str2dec(result, "542101086242752217003726400434970855712890625", -20); + return; + case -53: + __str2dec(result, "11102230246251565404236316680908203125", -16); + return; + case -32: + __str2dec(result, "23283064365386962890625", -10); + return; + case -16: + __str2dec(result, "152587890625", -5); + return; + case -8: + __str2dec(result, "390625", -3); + return; + case -7: + __str2dec(result, "78125", -3); + return; + case -6: + __str2dec(result, "15625", -2); + return; + case -5: + __str2dec(result, "3125", -2); + return; + case -4: + __str2dec(result, "625", -2); + return; + case -3: + __str2dec(result, "125", -1); + return; + case -2: + __str2dec(result, "25", -1); + return; + case -1: + __str2dec(result, "5", -1); + return; + case 0: + __str2dec(result, "1", 0); + return; + case 1: + __str2dec(result, "2", 0); + return; + case 2: + __str2dec(result, "4", 0); + return; + case 3: + __str2dec(result, "8", 0); + return; + case 4: + __str2dec(result, "16", 1); + return; + case 5: + __str2dec(result, "32", 1); + return; + case 6: + __str2dec(result, "64", 1); + return; + case 7: + __str2dec(result, "128", 2); + return; + case 8: + __str2dec(result, "256", 2); + return; + } + + { + decimal x2, temp; + + __two_exp(&x2, exp / 2); + __timesdec(result, &x2, &x2); + + if (exp & 1) { + temp = *result; + if (exp > 0) { + __str2dec(&x2, "2", 0); + } else { + __str2dec(&x2, "5", -1); + } + __timesdec(result, &temp, &x2); + } + } +} + +BOOL __equals_dec(const decimal* x, const decimal* y) +{ + if (x->sig.text[0] == 0) { + if (y->sig.text[0] == 0) + return TRUE; + return FALSE; + } + if (y->sig.text[0] == 0) { + if (x->sig.text[0] == 0) + return TRUE; + return FALSE; + } + + if (x->exp == y->exp) { + int i; + int l = x->sig.length; + + if (l > y->sig.length) { + l = y->sig.length; + } + + for (i = 0; i < l; i++) { + if (x->sig.text[i] != y->sig.text[i]) { + return FALSE; + } + } + + if (l == x->sig.length) { + for (; i < y->sig.length; ++i) { + if (y->sig.text[i] != 0) { + return FALSE; + } + } + } else { + for (; i < x->sig.length; ++i) { + if (x->sig.text[i] != 0) { + return FALSE; + } + } + } + + return TRUE; + } + return FALSE; +} + +BOOL __less_dec(const decimal* x, const decimal* y) +{ + if (x->sig.text[0] == 0) { + if (y->sig.text[0] != 0) + return TRUE; + return FALSE; + } + + if (y->sig.text[0] == 0) { + return FALSE; + } + + if (x->exp == y->exp) { + int i; + int l = x->sig.length; + + if (l > y->sig.length) { + l = y->sig.length; + } + + for (i = 0; i < l; i++) { + if (x->sig.text[i] < y->sig.text[i]) { + return TRUE; + } else if (y->sig.text[i] < x->sig.text[i]) { + return FALSE; + } + } + + if (l == x->sig.length) { + for (; i < y->sig.length; i++) { + if (y->sig.text[i] != 0) { + return TRUE; + } + } + } + return FALSE; + } + + return x->exp < y->exp; +} + +void __minus_dec(decimal* z, const decimal* x, const decimal* y) +{ + int zlen, dexp; + u8 *ib, *i, *ie; + u8 const *jb, *j, *jn; + + *z = *x; + + if (y->sig.text[0] == 0) + return; + + zlen = z->sig.length; + if (zlen < y->sig.length) + zlen = y->sig.length; + + dexp = z->exp - y->exp; + zlen += dexp; + + if (zlen > SIGDIGLEN) + zlen = SIGDIGLEN; + + while (z->sig.length < zlen) { + z->sig.text[z->sig.length++] = 0; + } + + ib = z->sig.text; + i = ib + zlen; + + if (y->sig.length + dexp < zlen) { + i = ib + (y->sig.length + dexp); + } + + jb = y->sig.text; + j = jb + (i - ib - dexp); + jn = j; + + while (i > ib && j > jb) { + i--; + j--; + if (*i < *j) { + u8* k = i - 1; + while (*k == 0) + k--; + while (k != i) { + --*k; + *++k += 10; + } + } + *i -= *j; + } + + if (jn - jb < y->sig.length) { + BOOL round_down = FALSE; + if (*jn < 5) + round_down = TRUE; + else if (*jn == 5) { + u8 const* ibPtr = y->sig.text + y->sig.length; + + for (j = jn + 1; j < ibPtr; j++) { + if (*j != 0) + goto done; + } + i = ib + (jn - jb) + dexp - 1; + if (*i & 1) + round_down = 1; + } + if (round_down) { + if (*i < 1) { + u8* k = i - 1; + while (*k == 0) + k--; + while (k != i) { + --*k; + *++k += 10; + } + } + *i -= 1; + } + } +done: + for (i = ib; *i == 0; ++i) { } + + if (i > ib) { + u8 dl = (u8)(i - ib); + z->exp -= dl; + ie = ib + z->sig.length; + for (; i < ie; ++i, ++ib) + *ib = *i; + z->sig.length -= dl; + } + + ib = z->sig.text; + for (i = ib + z->sig.length; i > ib;) { + i--; + if (*i != 0) + break; + } + z->sig.length = (u8)(i - ib + 1); +} + +void __num2dec_internal(decimal* d, f64 x) +{ + s8 sign = (s8)(SIGNBIT(x) != 0); + + if (x == 0) { + d->sign = sign; + d->exp = 0; + d->sig.length = 1; + d->sig.text[0] = 0; + return; + } + + if (!isfinite(x)) { + d->sign = sign; + d->exp = 0; + d->sig.length = 1; + d->sig.text[0] = fpclassify(x) == 1 ? 'N' : 'I'; + return; + } + + if (sign != 0) { + x = -x; + } + + { + int exp; + f64 frac = frexp(x, &exp); + s32 num_bits_extract = DBL_MANT_DIG - __count_trailing_zero(frac); + f64 integer; + decimal int_d, pow2_d; + + __two_exp(&pow2_d, exp - num_bits_extract); + frac = modf(ldexp(frac, num_bits_extract), &integer); + __ull2dec(&int_d, (u64)integer); + __timesdec(d, &int_d, &pow2_d); + d->sign = sign; + } +} + +void __num2dec(const decform* form, f64 x, decimal* d) +{ + s16 digits = form->digits; + int i; + __num2dec_internal(d, x); + + if (d->sig.text[0] > 9) { + return; + } + + if (digits > SIGDIGLEN) { + digits = SIGDIGLEN; + } + + __rounddec(d, digits); + + while (d->sig.length < digits) { + d->sig.text[d->sig.length++] = 0; + } + + d->exp -= d->sig.length - 1; + + for (i = 0; i < d->sig.length; i++) { + d->sig.text[i] += '0'; + } +} + +f64 __dec2num(const decimal* d) +{ + if (d->sig.length <= 0) { + return copysign(0.0, d->sign == 0 ? 1.0 : -1.0); + } + + switch (d->sig.text[0]) { + case '0': + return copysign(0.0, d->sign == 0 ? 1.0 : -1.0); + case 'I': + return copysign((f64)INFINITY, d->sign == 0 ? 1.0 : -1.0); + case 'N': { + f64 result; + u64* ll = (u64*)&result; + + *ll = 0x7FF0000000000000; + if (d->sign) + *ll |= 0x8000000000000000; + + if (d->sig.length == 1) + *ll |= 0x8000000000000; + else { + u8* p = (u8*)&result + 1; + int placed_non_zero = 0; + int low = 1; + int i; + int e = d->sig.length; + if (e > 14) + e = 14; + + for (i = 1; i < e; ++i) { + u8 c = d->sig.text[i]; + + if (isdigit(c)) { + c -= '0'; + } else { + c = (u8)(_tolower(c) - 'a' + 10); + } + + if (c != 0) { + placed_non_zero = 1; + } + + if (low) { + *p++ |= c; + } else { + *p = (u8)(c << 4); + } + + low = !low; + } + + if (!placed_non_zero) { + *ll |= 0x0008000000000000; + } + } + + return result; + } + } + + { + static const f64 pow_10[8] = { 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8 }; + + decimal dec = *d; + u8* i = dec.sig.text; + u8* e = i + dec.sig.length; + f64 first_guess; + int exponent; + + for (; i < e; ++i) + *i -= '0'; + dec.exp += dec.sig.length - 1; + exponent = dec.exp; + + i = dec.sig.text; + first_guess = *i++; + + while (i < e) { + u32 ival = 0; + int j; + f64 temp1, temp2; + int ndig = (int)(e - i) % 8; + + if (ndig == 0) + ndig = 8; + + for (j = 0; j < ndig; ++j, ++i) { + ival = ival * 10 + *i; + } + + temp1 = first_guess * pow_10[ndig - 1]; + temp2 = temp1 + ival; + + if (ival != 0 && temp1 == temp2) + break; + + first_guess = temp2; + exponent -= ndig; + } + + if (exponent < 0) { + first_guess /= pow(5.0, -exponent); + } else { + first_guess *= pow(5.0, exponent); + } + + first_guess = ldexp(first_guess, exponent); + + if (isinf(first_guess)) { + decimal max; + __str2dec(&max, "179769313486231580793729011405303420", 308); + if (__less_dec(&max, &dec)) + goto done; + first_guess = DBL_MAX; + } + + { + decimal feedback1; + + __num2dec_internal(&feedback1, first_guess); + + if (__equals_dec(&feedback1, &dec)) { + goto done; + } + + if (__less_dec(&feedback1, &dec)) { + + decimal feedback2, difflow, diffhigh; + f64 next_guess = first_guess; + u64* ull = (u64*)&next_guess; + ++*ull; + + if (isinf(next_guess)) { + first_guess = next_guess; + goto done; + } + + __num2dec_internal(&feedback2, next_guess); + + while (__less_dec(&feedback2, &dec)) { + feedback1 = feedback2; + first_guess = next_guess; + ++*ull; + if (isinf(next_guess)) { + first_guess = next_guess; + goto done; + } + __num2dec_internal(&feedback2, next_guess); + } + + __minus_dec(&difflow, &dec, &feedback1); + __minus_dec(&diffhigh, &feedback2, &dec); + + if (__equals_dec(&difflow, &diffhigh)) { + if (*(u64*)&first_guess & 1) { + first_guess = next_guess; + } + } else if (!__less_dec(&difflow, &diffhigh)) { + first_guess = next_guess; + } + } else { + decimal feedback2, difflow, diffhigh; + f64 next_guess = first_guess; + u64* ull = (u64*)&next_guess; + --*ull; + + __num2dec_internal(&feedback2, next_guess); + + while (__less_dec(&dec, &feedback2)) { + feedback1 = feedback2; + first_guess = next_guess; + --*ull; + __num2dec_internal(&feedback2, next_guess); + } + + __minus_dec(&difflow, &dec, &feedback2); + __minus_dec(&diffhigh, &feedback1, &dec); + + if (__equals_dec(&difflow, &diffhigh)) { + if (*(u64*)&first_guess & 1) { + first_guess = next_guess; + } + } else if (__less_dec(&difflow, &diffhigh)) { + first_guess = next_guess; + } + } + } + done: + if (dec.sign) { + first_guess = -first_guess; + } + return first_guess; + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/arith.c b/src/static/MSL_C.PPCEABI.bare.H/arith.c new file mode 100644 index 00000000..072d5ce3 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/arith.c @@ -0,0 +1,80 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/arith.h" + +int abs(int x) +{ + return x > 0 ? x : -x; +} + +long labs(long x) +{ + return x > 0 ? x : -x; +} + +div_t div(int numer, int denom) +{ + int n_sign, d_sign; + div_t value; + + n_sign = 1; + d_sign = 1; + + if (numer < 0) { + numer = -numer; + n_sign = -1; + } + + if (denom < 0) { + denom = -denom; + d_sign = -1; + } + + value.quot = (numer / denom) * (n_sign * d_sign); + value.rem = (numer * n_sign) - (d_sign * (value.quot * denom)); + return value; +} + +ldiv_t ldiv(long numer, long denom) +{ + long n_sign, d_sign; + ldiv_t value; + + n_sign = 1; + d_sign = 1; + + if (numer < 0) { + numer = -numer; + n_sign = -1; + } + + if (denom < 0) { + denom = -denom; + d_sign = -1; + } + + value.quot = (numer / denom) * (n_sign * d_sign); + value.rem = (numer * n_sign) - (d_sign * (value.quot * denom)); + return value; +} + +lldiv_t lldiv(long long numer, long long denom) +{ + long long n_sign, d_sign; + lldiv_t value; + + n_sign = 1; + d_sign = 1; + + if (numer < 0) { + numer = -numer; + n_sign = -1; + } + + if (denom < 0) { + denom = -denom; + d_sign = -1; + } + + value.quot = (numer / denom) * (n_sign * d_sign); + value.rem = (numer * n_sign) - (d_sign * (value.quot * denom)); + return value; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/buffer_io.c b/src/static/MSL_C.PPCEABI.bare.H/buffer_io.c new file mode 100644 index 00000000..ccf43453 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/buffer_io.c @@ -0,0 +1,36 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +void __prep_buffer(FILE* file) + +{ + file->mBufferPtr = file->mBuffer; + file->mBufferLength = file->mBufferSize; + file->mBufferLength = file->mBufferLength - (file->mPosition & file->mBufferAlignment); + file->mBufferPosition = file->mPosition; + return; +} + +int __flush_buffer(FILE* file, size_t* length) +{ + size_t bufferLen; + int writeCode; + + bufferLen = file->mBufferPtr - file->mBuffer; + if (bufferLen) { + file->mBufferLength = bufferLen; + writeCode = file->writeFunc(file->mHandle, file->mBuffer, &file->mBufferLength, file->ref_con); + if (length) { + *length = file->mBufferLength; + } + if (writeCode) { + return writeCode; + } + file->mPosition += file->mBufferLength; + } + + file->mBufferPtr = file->mBuffer; + file->mBufferLength = file->mBufferSize; + file->mBufferLength = file->mBufferLength - (file->mPosition & file->mBufferAlignment); + file->mBufferPosition = file->mPosition; + return 0; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/critical_regions.gamecube.c b/src/static/MSL_C.PPCEABI.bare.H/critical_regions.gamecube.c new file mode 100644 index 00000000..e3907fb3 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/critical_regions.gamecube.c @@ -0,0 +1,21 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h" + +void __init_critical_regions(void) +{ + return; +} + +void __kill_critical_regions(void) +{ + return; +} + +void __begin_critical_region(int region) +{ + return; +} + +void __end_critical_region(int region) +{ + return; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/ctype.c b/src/static/MSL_C.PPCEABI.bare.H/ctype.c new file mode 100644 index 00000000..642aa52c --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/ctype.c @@ -0,0 +1,57 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h" + +#define octrl 0x01 +#define omotn 0x02 +#define ospac 0x04 +#define opunc 0x08 +#define odigi 0x10 +#define ohexd 0x20 +#define olowc 0x40 +#define ouppc 0x80 +#define odhex ohexd | odigi +#define ouhex ohexd | ouppc +#define olhex ohexd | olowc + +u8 __ctype_map[256] + = { octrl, octrl, octrl, octrl, octrl, octrl, octrl, octrl, octrl, omotn, omotn, omotn, omotn, omotn, octrl, octrl, octrl, octrl, octrl, + octrl, octrl, octrl, octrl, octrl, octrl, octrl, octrl, octrl, octrl, octrl, octrl, octrl, ospac, opunc, opunc, opunc, opunc, opunc, + opunc, opunc, opunc, opunc, opunc, opunc, opunc, opunc, opunc, opunc, odhex, odhex, odhex, odhex, odhex, odhex, odhex, odhex, odhex, + odhex, opunc, opunc, opunc, opunc, opunc, opunc, opunc, ouhex, ouhex, ouhex, ouhex, ouhex, ouhex, ouppc, ouppc, ouppc, ouppc, ouppc, + ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, ouppc, opunc, opunc, opunc, opunc, + opunc, opunc, olhex, olhex, olhex, olhex, olhex, olhex, olowc, olowc, olowc, olowc, olowc, olowc, olowc, olowc, olowc, olowc, olowc, + olowc, olowc, olowc, olowc, olowc, olowc, olowc, olowc, olowc, opunc, opunc, opunc, opunc, octrl }; + +u8 __lower_map[256] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, + 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, + 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, + 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +}; + +u8 __upper_map[256] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, + 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, + 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, + 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +}; + +int tolower(int __c) +{ + return _tolower(__c); +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/direct_io.c b/src/static/MSL_C.PPCEABI.bare.H/direct_io.c new file mode 100644 index 00000000..6f9d67d6 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/direct_io.c @@ -0,0 +1,132 @@ +#ifndef _MSL_WIDE_CHAR +#define _MSL_WIDE_CHAR +#endif + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/wchar_io.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/direct_io.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/FILE_POS.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/string.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/stdio_api.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/misc_io.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h" + +size_t fwrite(const void* pPtr, size_t memb_size, size_t num_memb, FILE* pFile) +{ + size_t retval; + + __begin_critical_region(stdin_access); + retval = __fwrite(pPtr, memb_size, num_memb, pFile); + __end_critical_region(stdin_access); + + return retval; +} + +size_t __fwrite(const void* pPtr, size_t memb_size, size_t num_memb, FILE* pFile) +{ + u8* cur_ptr; + size_t num_bytes, rem_bytes, bytes_written; + int res, buff; + + if (fwide(pFile, 0) == 0) { + fwide(pFile, -1); + } + + rem_bytes = memb_size * num_memb; + + if (rem_bytes == 0 || pFile->mState.error || pFile->mMode.file_kind == __closed_file) { + return 0; + } + + if (pFile->mMode.file_kind == __console_file) { + __stdio_atexit(); + } + + buff = (!pFile->mMode.binary_io || pFile->mMode.buffer_mode == 2 || pFile->mMode.buffer_mode == 1); + + if (pFile->mState.io_state == __neutral && pFile->mMode.io_mode & 2) { + if (pFile->mMode.io_mode & 4) { + if (fseek(pFile, 0, SEEK_END)) { + return 0; + } + } + + pFile->mState.io_state = __writing; + __prep_buffer(pFile); + } + + if (pFile->mState.io_state != __writing) { + pFile->mState.error = 1; + pFile->mBufferLength = 0; + return 0; + } + + cur_ptr = (u8*)pPtr; + bytes_written = 0; + + if (rem_bytes && (pFile->mBufferPtr != pFile->mBuffer || buff)) { + pFile->mBufferLength = pFile->mBufferSize - (pFile->mBufferPtr - pFile->mBuffer); + + do { + u8* nw = 0; + num_bytes = pFile->mBufferLength; + + if (num_bytes > rem_bytes) { + num_bytes = rem_bytes; + } + + if (pFile->mMode.buffer_mode == 1 && num_bytes) { + if ((nw = (u8*)__memrchr(cur_ptr, '\n', num_bytes)) != 0) { + num_bytes = nw + 1 - cur_ptr; + } + } + + if (num_bytes != 0) { + memcpy(pFile->mBufferPtr, cur_ptr, num_bytes); + cur_ptr += num_bytes; + bytes_written += num_bytes; + rem_bytes -= num_bytes; + pFile->mBufferPtr += num_bytes; + pFile->mBufferLength -= num_bytes; + } + + if (pFile->mBufferLength == 0 || nw != 0 || (!pFile->mMode.buffer_mode)) { + res = __flush_buffer(pFile, 0); + + if (res != 0) { + pFile->mState.error = 1; + pFile->mBufferLength = 0; + rem_bytes = 0; + break; + } + } + + } while (rem_bytes && buff); + } + + if (rem_bytes && buff == 0) { + u8* save_buf = (u8*)pFile->mBuffer; + size_t save_size = pFile->mBufferSize; + + pFile->mBuffer = (char*)cur_ptr; + pFile->mBufferSize = rem_bytes; + pFile->mBufferPtr = (char*)cur_ptr + rem_bytes; + + if (__flush_buffer(pFile, &num_bytes) != 0) { + pFile->mState.error = 1; + pFile->mBufferLength = 0; + } + + bytes_written += num_bytes; + + pFile->mBuffer = (char*)save_buf; + pFile->mBufferSize = save_size; + __prep_buffer(pFile); + pFile->mBufferLength = 0; + } + + if (pFile->mMode.buffer_mode != 2) { + pFile->mBufferLength = 0; + } + + return (bytes_written + memb_size - 1) / memb_size; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/e_acos.c b/src/static/MSL_C.PPCEABI.bare.H/e_acos.c new file mode 100644 index 00000000..383d46ab --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/e_acos.c @@ -0,0 +1,107 @@ +/* @(#)e_acos.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_acos(x) + * Method : + * acos(x) = pi/2 - asin(x) + * acos(-x) = pi/2 + asin(x) + * For |x|<=0.5 + * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) + * For x>0.5 + * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) + * = 2asin(sqrt((1-x)/2)) + * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) + * = 2f + (2c + 2s*z*R(z)) + * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term + * for f so that f+c ~ sqrt(z). + * For x<-0.5 + * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) + * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + * Function needed: sqrt + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif + one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ + pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ + pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ + pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ + pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ + pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ + pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ + pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ + pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ + pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ + qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ + qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ + qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ + qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +#ifdef __STDC__ +double __ieee754_acos(double x) +#else +double __ieee754_acos(x) +double x; +#endif +{ + double z, p, q, r, w, s, c, df; + int hx, ix; + hx = __HI(x); + ix = hx & 0x7fffffff; + if (ix >= 0x3ff00000) { /* |x| >= 1 */ + if (((ix - 0x3ff00000) | __LO(x)) == 0) { /* |x|==1 */ + if (hx > 0) + return 0.0; /* acos(1) = 0 */ + else + return pi + 2.0 * pio2_lo; /* acos(-1)= pi */ + } + return NAN; /* acos(|x|>1) is NaN */ + } + if (ix < 0x3fe00000) { /* |x| < 0.5 */ + if (ix <= 0x3c600000) + return pio2_hi + pio2_lo; /*if|x|<2**-57*/ + z = x * x; + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + r = p / q; + return pio2_hi - (x - (pio2_lo - x * r)); + } else if (hx < 0) { /* x < -0.5 */ + z = (one + x) * 0.5; + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + s = sqrt(z); + r = p / q; + w = r * s - pio2_lo; + return pi - 2.0 * (s + w); + } else { /* x > 0.5 */ + z = (one - x) * 0.5; + s = sqrt(z); + df = s; + __LO(df) = 0; + c = (z - df * df) / (s + df); + p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); + q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); + r = p / q; + w = r * s + c; + return 2.0 * (df + w); + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/e_atan2.c b/src/static/MSL_C.PPCEABI.bare.H/e_atan2.c new file mode 100644 index 00000000..dbf1abc3 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/e_atan2.c @@ -0,0 +1,143 @@ + +/* @(#)e_atan2.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* __ieee754_atan2(y,x) + * Method : + * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). + * 2. Reduce x to positive by (if x and y are unexceptional): + * ARG (x+iy) = arctan(y/x) ... if x > 0, + * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, + * + * Special cases: + * + * ATAN2((anything), NaN ) is NaN; + * ATAN2(NAN , (anything) ) is NaN; + * ATAN2(+-0, +(anything but NaN)) is +-0 ; + * ATAN2(+-0, -(anything but NaN)) is +-pi ; + * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; + * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; + * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; + * ATAN2(+-INF,+INF ) is +-pi/4 ; + * ATAN2(+-INF,-INF ) is +-3pi/4; + * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif + tiny = 1.0e-300, + zero = 0.0, pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ + pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ + pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ + pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ + +#ifdef __STDC__ +double __ieee754_atan2(double y, double x) +#else +double __ieee754_atan2(y, x) +double y, x; +#endif +{ + double z; + int k, m, hx, hy, ix, iy; + unsigned lx, ly; + + hx = __HI(x); + ix = hx & 0x7fffffff; + lx = __LO(x); + hy = __HI(y); + iy = hy & 0x7fffffff; + ly = __LO(y); + if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000) || ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) /* x or y is NaN */ + return x + y; + if ((hx - 0x3ff00000 | lx) == 0) + return atan(y); /* x=1.0 */ + m = ((hy >> 31) & 1) | ((hx >> 30) & 2); /* 2*sign(x)+sign(y) */ + + /* when y = 0 */ + if ((iy | ly) == 0) { + switch (m) { + case 0: + case 1: + return y; /* atan(+-0,+anything)=+-0 */ + case 2: + return pi + tiny; /* atan(+0,-anything) = pi */ + case 3: + return -pi - tiny; /* atan(-0,-anything) =-pi */ + } + } + /* when x = 0 */ + if ((ix | lx) == 0) + return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny; + + /* when x is INF */ + if (ix == 0x7ff00000) { + if (iy == 0x7ff00000) { + switch (m) { + case 0: + return pi_o_4 + tiny; /* atan(+INF,+INF) */ + case 1: + return -pi_o_4 - tiny; /* atan(-INF,+INF) */ + case 2: + return 3.0 * pi_o_4 + tiny; /*atan(+INF,-INF)*/ + case 3: + return -3.0 * pi_o_4 - tiny; /*atan(-INF,-INF)*/ + } + } else { + switch (m) { + case 0: + return zero; /* atan(+...,+INF) */ + case 1: + return -zero; /* atan(-...,+INF) */ + case 2: + return pi + tiny; /* atan(+...,-INF) */ + case 3: + return -pi - tiny; /* atan(-...,-INF) */ + } + } + } + /* when y is INF */ + if (iy == 0x7ff00000) + return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny; + + /* compute y/x */ + k = (iy - ix) >> 20; + if (k > 60) + z = pi_o_2 + 0.5 * pi_lo; /* |y/x| > 2**60 */ + else if (hx < 0 && k < -60) + z = 0.0; /* |y|/x < -2**60 */ + else + z = atan(__fabs(y / x)); /* safe to do y/x */ + switch (m) { + case 0: + return z; /* atan(+,+) */ + case 1: + __HI(z) ^= 0x80000000; + return z; /* atan(-,+) */ + case 2: + return pi - (z - pi_lo); /* atan(+,-) */ + default: /* case 3 */ + return (z - pi_lo) - pi; /* atan(-,-) */ + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/e_pow.c b/src/static/MSL_C.PPCEABI.bare.H/e_pow.c new file mode 100644 index 00000000..aec03e54 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/e_pow.c @@ -0,0 +1,405 @@ +//======================================================================== +// +// e_pow.c +// +// Part of the standard mathematical function library +// +//======================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +// #####DESCRIPTIONBEGIN#### +// +// Author(s): jlarmour +// Contributors: +// Date: 2001-07-20 +// Purpose: +// Description: +// Usage: +// +// ####DESCRIPTIONEND#### +// +//======================================================================== + +// CONFIGURATION + +/* @(#)e_pow.c 5.1 93/09/24 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_pow(x,y) return x**y + * + * n + * Method: Let x = 2 * (1+f) + * 1. Compute and return log2(x) in two pieces: + * log2(x) = w1 + w2, + * where w1 has 53-24 = 29 bit trailing zeros. + * 2. Perform y*log2(x) = n+y' by simulating muti-precision + * arithmetic, where |y'|<=0.5. + * 3. Return x**y = 2**n*exp(y'*log2) + * + * Special cases: + * 1. (anything) ** 0 is 1 + * 2. (anything) ** 1 is itself + * 3. (anything) ** NAN is NAN + * 4. NAN ** (anything except 0) is NAN + * 5. +-(|x| > 1) ** +INF is +INF + * 6. +-(|x| > 1) ** -INF is +0 + * 7. +-(|x| < 1) ** +INF is +0 + * 8. +-(|x| < 1) ** -INF is +INF + * 9. +-1 ** +-INF is NAN + * 10. +0 ** (+anything except 0, NAN) is +0 + * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 + * 12. +0 ** (-anything except 0, NAN) is +INF + * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF + * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) + * 15. +INF ** (+anything except 0,NAN) is +INF + * 16. +INF ** (-anything except 0,NAN) is +0 + * 17. -INF ** (anything) = -0 ** (-anything) + * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) + * 19. (-anything except 0 and inf) ** (non-integer) is NAN + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular + * pow(integer,integer) + * always returns the correct integer provided it is + * representable. + * + * Constants : + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h" +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +bp[] = {1.0, 1.5,}, +dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ +dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ +zero = 0.0, +one = 1.0, +two = 2.0, +two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ +huge = 1.0e300, +tiny = 1.0e-300, + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ +L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ +L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ +L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ +L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ +L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ +lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ +lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ +ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ +cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ +cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ +cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ +ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ +ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ +ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + +#ifdef __STDC__ +double __ieee754_pow(double x, double y) +#else +double __ieee754_pow(x, y) +double x, y; +#endif +{ + double z, ax, z_h, z_l, p_h, p_l; + double y1, t1, t2, r, s, t, u, v, w; + double qqq; // necessary temp + int i, j, k, yisint, n; + int hx, hy, ix, iy; + unsigned int lx, ly; + + hx = __HI(x); + lx = __LO(x); + hy = __HI(y); + ly = __LO(y); + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + + /* y==zero: x**0 = 1 */ + if ((iy | ly) == 0) + return one; + + /* +-NaN return x+y */ + if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) || iy > 0x7ff00000 || ((iy == 0x7ff00000) && (ly != 0))) + return x + y; + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if (hx < 0) { + if (iy >= 0x43400000) + yisint = 2; /* even integer y */ + else if (iy >= 0x3ff00000) { + k = (iy >> 20) - 0x3ff; /* exponent */ + if (k > 20) { + j = ly >> (52 - k); + if ((j << (52 - k)) == ly) + yisint = 2 - (j & 1); + } else if (ly == 0) { + j = iy >> (20 - k); + if ((j << (20 - k)) == iy) + yisint = 2 - (j & 1); + } + } + } + + /* special value of y */ + if (ly == 0) { + if (iy == 0x7ff00000) { /* y is +-inf */ + if (((ix - 0x3ff00000) | lx) == 0) + return y - y; /* inf**+-1 is NaN */ + else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ + return (hy >= 0) ? y : zero; + else /* (|x|<1)**-,+inf = inf,0 */ + return (hy < 0) ? -y : zero; + } + if (iy == 0x3ff00000) { /* y is +-1 */ + if (hy < 0) + return one / x; + else + return x; + } + if (hy == 0x40000000) + return x * x; /* y is 2 */ + if (hy == 0x3fe00000) { /* y is 0.5 */ + if (hx >= 0) /* x >= +0 */ + return sqrt(x); + } + } + + ax = __fabs(x); + qqq = ax; /*x is +-0,+-inf,+-1*/ + /* special value of x */ + if (lx == 0) { + if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { + z = qqq; /*x is +-0,+-inf,+-1*/ + if (hy < 0) + z = one / z; /* z = (1/|x|) */ + if (hx < 0) { + if (((ix - 0x3ff00000) | yisint) == 0) { + z = (z - z) / (z - z); /* (-1)**non-int is NaN */ + } else if (yisint == 1) + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + return z; + } + } + + /* (x<0)**(non-int) is NaN */ + /* CYGNUS LOCAL: This used to be + if((((hx>>31)+1)|yisint)==0) return (x-x)/(x-x); + but ANSI C says a right shift of a signed negative quantity is + implementation defined. */ + + if (((((int)hx >> 31) + 1) | yisint) == 0) { + errno = EDOM; + return (double)NAN; + }; + + /* |y| is huge */ + if (iy > 0x41e00000) { /* if |y| > 2**31 */ + if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ + if (ix <= 0x3fefffff) + return (hy < 0) ? huge * huge : tiny * tiny; + if (ix >= 0x3ff00000) + return (hy > 0) ? huge * huge : tiny * tiny; + } + /* over/underflow if x is not close to one */ + if (ix < 0x3fefffff) + return (hy < 0) ? huge * huge : tiny * tiny; + if (ix > 0x3ff00000) + return (hy > 0) ? huge * huge : tiny * tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = x - 1; /* t has 20 trailing zeros */ + w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25)); + u = ivln2_h * t; /* ivln2_h has 21 sig. bits */ + v = t * ivln2_l - w * ivln2; + t1 = u + v; + __LO(t1) = 0; + t2 = v - (t1 - u); + } else { + double s2, s_h, s_l, t_h, t_l; + n = 0; + /* take care subnormal number */ + if (ix < 0x00100000) { + ax *= two53; + n -= 53; + ix = __HI(ax); + } + n += ((ix) >> 20) - 0x3ff; + j = ix & 0x000fffff; + /* determine interval */ + ix = j | 0x3ff00000; /* normalize ix */ + if (j <= 0x3988E) + k = 0; /* |x|> 1) | 0x20000000) + 0x00080000 + (k << 18); + t_l = ax - (t_h - bp[k]); + s_l = v * ((u - s_h * t_h) - s_h * t_l); + /* compute log(ax) */ + s2 = s * s; + r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); + r += s_l * (s_h + s); + s2 = s_h * s_h; + t_h = 3.0 + s2 + r; + __LO(t_h) = 0; + t_l = r - ((t_h - 3.0) - s2); + /* u+v = s*(1+...) */ + u = s_h * t_h; + v = s_l * t_h + t_l * s; + /* 2/(3log2)*(s+...) */ + p_h = u + v; + __LO(p_h) = 0; + p_l = v - (p_h - u); + z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l * p_h + p_l * cp + dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double)n; + t1 = (((z_h + z_l) + dp_h[k]) + t); + __LO(t1) = 0; + t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if (((((int)hx >> 31) + 1) | (yisint - 1)) == 0) + s = -one; /* (-ve)**(odd int) */ + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + __LO(y1) = 0; + p_l = (y - y1) * t1 + y * t2; + p_h = y1 * t1; + z = p_l + p_h; + j = __HI(z); + i = __LO(z); + if (j >= 0x40900000) { /* z >= 1024 */ + if (((j - 0x40900000) | i) != 0) /* if z > 1024 */ + return s * huge * huge; /* overflow */ + else { + if (p_l + ovt > z - p_h) + return s * huge * huge; /* overflow */ + } + } else if ((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ + if (((j - 0xc090cc00) | i) != 0) /* z < -1075 */ + return s * tiny * tiny; /* underflow */ + else { + if (p_l <= z - p_h) + return s * tiny * tiny; /* underflow */ + } + } + /** + * compute 2**(p_h+p_l) + */ + i = j & 0x7fffffff; + k = (i >> 20) - 0x3ff; + n = 0; + if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j + (0x00100000 >> (k + 1)); + k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ + t = zero; + __HI(t) = (n & ~(0x000fffff >> k)); + n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); + if (j < 0) + n = -n; + p_h -= t; + } + t = p_l + p_h; + __LO(t) = 0; + u = t * lg2_h; + v = (p_l - (t - p_h)) * lg2 + t * lg2_l; + z = u + v; + w = v - (z - u); + t = z * z; + t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + r = (z * t1) / (t1 - two) - (w + z * w); + z = one - (r - z); + j = __HI(z); + j += (n << 20); + if ((j >> 20) <= 0) + z = ldexp(z, n); /* subnormal output */ + else + __HI(z) += (n << 20); + return s * z; +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ + +// EOF e_pow.c diff --git a/src/static/MSL_C.PPCEABI.bare.H/e_rem_pio2.c b/src/static/MSL_C.PPCEABI.bare.H/e_rem_pio2.c new file mode 100644 index 00000000..1f330b54 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/e_rem_pio2.c @@ -0,0 +1,180 @@ + +/* @(#)e_rem_pio2.c 1.4 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* __ieee754_rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __kernel_rem_pio2() + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +/** + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + */ +#ifdef __STDC__ +static const int two_over_pi[] = { +#else +static int two_over_pi[] = { +#endif + 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, + 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, + 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, + 0x8B5A0A, 0x6D1F6D, 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, + 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, + 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, +}; + +#ifdef __STDC__ +static const int npio2_hw[] = { +#else +static int npio2_hw[] = { +#endif + 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, + 0x4032D97C, 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, + 0x4042106C, 0x4042D97C, 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, 0x404858EB, 0x404921FB, +}; + +/** + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ + +#ifdef __STDC__ +static const double +#else +static double +#endif + zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ + two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ + invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ + pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ + pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ + pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ + pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ + pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ + pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +#ifdef __STDC__ +int __ieee754_rem_pio2(double x, double* y) +#else +int __ieee754_rem_pio2(x, y) +double x, y[]; +#endif +{ + double z, w, t, r, fn; + double tx[3]; + int e0, i, j, nx, n, ix, hx; + + hx = __HI(x); /* high word of x */ + ix = hx & 0x7fffffff; + if (ix <= 0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ + { + y[0] = x; + y[1] = 0; + return 0; + } + if (ix < 0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ + if (hx > 0) { + z = x - pio2_1; + if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z - pio2_1t; + y[1] = (z - y[0]) - pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z - y[0]) - pio2_2t; + } + return 1; + } else { /* negative x */ + z = x + pio2_1; + if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z + pio2_1t; + y[1] = (z - y[0]) + pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z - y[0]) + pio2_2t; + } + return -1; + } + } + if (ix <= 0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ + t = fabs(x); + n = (int)(t * invpio2 + half); + fn = (double)n; + r = t - fn * pio2_1; + w = fn * pio2_1t; /* 1st round good to 85 bit */ + if (n < 32 && ix != npio2_hw[n - 1]) { + y[0] = r - w; /* quick check no cancellation */ + } else { + j = ix >> 20; + y[0] = r - w; + i = j - (((__HI(y[0])) >> 20) & 0x7ff); + if (i > 16) { /* 2nd iteration needed, good to 118 */ + t = r; + r = t - fn * pio2_2; + w = fn * pio2_2t - ((t - r) - fn * pio2_2); + y[0] = r - w; + i = j - (((__HI(y[0])) >> 20) & 0x7ff); + if (i > 49) { /* 3rd iteration need, 151 bits acc */ + t = r; /* will cover all possible cases */ + w = fn * pio2_3; + r = t - w; + w = fn * pio2_3t - ((t - r) - w); + y[0] = r - w; + } + } + } + y[1] = (r - y[0]) - w; + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } else + return n; + } + /** + * all other (large) arguments + */ + if (ix >= 0x7ff00000) { /* x is inf or NaN */ + y[0] = y[1] = x - x; + return 0; + } + /* set z = scalbn(|x|,ilogb(x)-23) */ + __LO(z) = __LO(x); + e0 = (ix >> 20) - 1046; /* e0 = ilogb(z)-23; */ + __HI(z) = ix - (e0 << 20); + for (i = 0; i < 2; i++) { + tx[i] = (double)((int)(z)); + z = (z - tx[i]) * two24; + } + tx[2] = z; + nx = 3; + while (tx[nx - 1] == zero) + nx--; /* skip zero term */ + n = __kernel_rem_pio2(tx, y, e0, nx, 2, two_over_pi); + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } + return n; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/e_sqrt.c b/src/static/MSL_C.PPCEABI.bare.H/e_sqrt.c new file mode 100644 index 00000000..7d3fc5de --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/e_sqrt.c @@ -0,0 +1,459 @@ + +/* @(#)e_sqrt.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebraic manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + * + * Other methods : see the appended file at the end of the program below. + *--------------- + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h" + +#ifdef __STDC__ +static const double one = 1.0, tiny = 1.0e-300; +#else +static double one = 1.0, tiny = 1.0e-300; +#endif + +#ifdef __STDC__ +double __ieee754_sqrt(double x) +#else +double __ieee754_sqrt(x) +double x; +#endif +{ + double z; + int sign = (int)0x80000000; + unsigned r, t1, s1, ix1, q1; + int ix0, s0, q, m, t, i; + + ix0 = __HI(x); /* high word of x */ + ix1 = __LO(x); /* low word of x */ + + /* take care of Inf and NaN */ + if ((ix0 & 0x7ff00000) == 0x7ff00000) { + errno = EDOM; + return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + } + /* take care of zero */ + if (ix0 <= 0) { + if (((ix0 & (~sign)) | ix1) == 0) + return x; /* sqrt(+-0) = +-0 */ + else if (ix0 < 0) { + errno = EDOM; + return NAN; + } /* sqrt(-ve) = sNaN */ + } + /* normalize x */ + m = (ix0 >> 20); + if (m == 0) { /* subnormal x */ + while (ix0 == 0) { + m -= 21; + ix0 |= (ix1 >> 11); + ix1 <<= 21; + } + for (i = 0; (ix0 & 0x00100000) == 0; i++) + ix0 <<= 1; + m -= i - 1; + ix0 |= (ix1 >> (32 - i)); + ix1 <<= i; + } + m -= 1023; /* unbias exponent */ + ix0 = (ix0 & 0x000fffff) | 0x00100000; + if (m & 1) { /* odd m, double x to make it even */ + ix0 += ix0 + ((ix1 & sign) >> 31); + ix1 += ix1; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + ((ix1 & sign) >> 31); + ix1 += ix1; + q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ + r = 0x00200000; /* r = moving bit from right to left */ + + while (r != 0) { + t = s0 + r; + if (t <= ix0) { + s0 = t + r; + ix0 -= t; + q += r; + } + ix0 += ix0 + ((ix1 & sign) >> 31); + ix1 += ix1; + r >>= 1; + } + + r = sign; + while (r != 0) { + t1 = s1 + r; + t = s0; + if ((t < ix0) || ((t == ix0) && (t1 <= ix1))) { + s1 = t1 + r; + if (((t1 & sign) == sign) && (s1 & sign) == 0) + s0 += 1; + ix0 -= t; + if (ix1 < t1) + ix0 -= 1; + ix1 -= t1; + q1 += r; + } + ix0 += ix0 + ((ix1 & sign) >> 31); + ix1 += ix1; + r >>= 1; + } + + /* use floating add to find out rounding direction */ + if ((ix0 | ix1) != 0) { + z = one - tiny; /* trigger inexact flag */ + if (z >= one) { + z = one + tiny; + if (q1 == (unsigned)0xffffffff) { + q1 = 0; + q += 1; + } else if (z > one) { + if (q1 == (unsigned)0xfffffffe) + q += 1; + q1 += 2; + } else + q1 += (q1 & 1); + } + } + ix0 = (q >> 1) + 0x3fe00000; + ix1 = q1 >> 1; + if ((q & 1) == 1) + ix1 |= sign; + ix0 += (m << 20); + __HI(z) = ix0; + __LO(z) = ix1; + return z; +} + +/* +Other methods (use floating-point arithmetic) +------------- +(This is a copy of a drafted paper by Prof W. Kahan +and K.C. Ng, written in May, 1986) + + Two algorithms are given here to implement sqrt(x) + (IEEE double precision arithmetic) in software. + Both supply sqrt(x) correctly rounded. The first algorithm (in + Section A) uses newton iterations and involves four divisions. + The second one uses reciproot iterations to avoid division, but + requires more multiplications. Both algorithms need the ability + to chop results of arithmetic operations instead of round them, + and the INEXACT flag to indicate when an arithmetic operation + is executed exactly with no roundoff error, all part of the + standard (IEEE 754-1985). The ability to perform shift, add, + subtract and logical AND operations upon 32-bit words is needed + too, though not part of the standard. + +A. sqrt(x) by Newton Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + + 1 11 52 ...widths + ------------------------------------------------------ + x: |s| e | f | + ------------------------------------------------------ + msb lsb msb lsb ...order + + ------------------------ ------------------------ + x0: |s| e | f1 | x1: | f2 | + ------------------------ ------------------------ + + By performing shifts and subtracts on x0 and x1 (both regarded + as integers), we obtain an 8-bit approximation of sqrt(x) as + follows. + + k := (x0>>1) + 0x1ff80000; + y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits + Here k is a 32-bit integer and T1[] is an integer array containing + correction terms. Now magically the floating value of y (y's + leading 32-bit word is y0, the value of its trailing word is 0) + approximates sqrt(x) to almost 8-bit. + + Value of T1: + static int T1[32]= { + 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, + 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, + 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, + 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; + + (2) Iterative refinement + + Apply Heron's rule three times to y, we have y approximates + sqrt(x) to within 1 ulp (Unit in the Last Place): + + y := (y+x/y)/2 ... almost 17 sig. bits + y := (y+x/y)/2 ... almost 35 sig. bits + y := y-(y-x/y)/2 ... within 1 ulp + + Remark 1. + Another way to improve y to within 1 ulp is: + + y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) + y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) + + 2 + (x-y )*y + y := y + 2* ---------- ...within 1 ulp + 2 + 3y + x + + This formula has one division fewer than the one above; however, + it requires more multiplications and additions. Also x must be + scaled in advance to avoid spurious overflow in evaluating the + expression 3y*y+x. Hence it is not recommended uless division + is slow. If division is very slow, then one should use the + reciproot algorithm given in section B. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + I := FALSE; ... reset INEXACT flag I + R := RZ; ... set rounding mode to round-toward-zero + z := x/y; ... chopped quotient, possibly inexact + If(not I) then { ... if the quotient is exact + if(z=y) { + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + } else { + z := z - ulp; ... special rounding + } + } + i := TRUE; ... sqrt(x) is inexact + If (r=RN) then z=z+ulp ... rounded-to-nearest + If (r=RP) then { ... round-toward-+inf + y = y+ulp; z=z+ulp; + } + y := y+z; ... chopped sum + y0:=y0-0x00100000; ... y := y/2 is correctly rounded. + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + + (4) Special cases + + Square root of +inf, +-0, or NaN is itself; + Square root of a negative number is NaN with invalid signal. + +B. sqrt(x) by Reciproot Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + (see section A). By performing shifts and subtracts on x0 and y0, + we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. + + k := 0x5fe80000 - (x0>>1); + y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits + + Here k is a 32-bit integer and T2[] is an integer array + containing correction terms. Now magically the floating + value of y (y's leading 32-bit word is y0, the value of + its trailing word y1 is set to zero) approximates 1/sqrt(x) + to almost 7.8-bit. + + Value of T2: + static int T2[64]= { + 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, + 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, + 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, + 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, + 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, + 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, + 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, + 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; + + (2) Iterative refinement + + Apply Reciproot iteration three times to y and multiply the + result by x to get an approximation z that matches sqrt(x) + to about 1 ulp. To be exact, we will have + -1ulp < sqrt(x)-z<1.0625ulp. + + ... set rounding mode to Round-to-nearest + y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) + y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) + ... special arrangement for better accuracy + z := x*y ... 29 bits to sqrt(x), with z*y<1 + z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) + + Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that + (a) the term z*y in the final iteration is always less than 1; + (b) the error in the final result is biased upward so that + -1 ulp < sqrt(x) - z < 1.0625 ulp + instead of |sqrt(x)-z|<1.03125ulp. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + R := RZ; ... set rounding mode to round-toward-zero + switch(r) { + case RN: ... round-to-nearest + if(x<= z*(z-ulp)...chopped) z = z - ulp; else + if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; + break; + case RZ:case RM: ... round-to-zero or round-to--inf + R:=RP; ... reset rounding mod to round-to-+inf + if(x=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; + break; + case RP: ... round-to-+inf + if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else + if(x>z*z ...chopped) z = z+ulp; + break; + } + + Remark 3. The above comparisons can be done in fixed point. For + example, to compare x and w=z*z chopped, it suffices to compare + x1 and w1 (the trailing parts of x and w), regarding them as + two's complement integers. + + ...Is z an exact square root? + To determine whether z is an exact square root of x, let z1 be the + trailing part of z, and also let x0 and x1 be the leading and + trailing parts of x. + + If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 + I := 1; ... Raise Inexact flag: z is not exact + else { + j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 + k := z1 >> 26; ... get z's 25-th and 26-th + fraction bits + I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); + } + R:= r ... restore rounded mode + return sqrt(x):=z. + + If multiplication is cheaper then the foregoing red tape, the + Inexact flag can be evaluated by + + I := i; + I := (z*z!=x) or I. + + Note that z*z can overwrite I; this value must be sensed if it is + True. + + Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be + zero. + + -------------------- + z1: | f2 | + -------------------- + bit 31 bit 0 + + Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd + or even of logb(x) have the following relations: + + ------------------------------------------------- + bit 27,26 of z1 bit 1,0 of x1 logb(x) + ------------------------------------------------- + 00 00 odd and even + 01 01 even + 10 10 odd + 10 00 even + 11 01 even + ------------------------------------------------- + + (4) Special cases (see (4) of Section A). + + */ diff --git a/src/static/MSL_C.PPCEABI.bare.H/errno.c b/src/static/MSL_C.PPCEABI.bare.H/errno.c new file mode 100644 index 00000000..444398e6 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/errno.c @@ -0,0 +1,3 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h" + +int errno; diff --git a/src/static/MSL_C.PPCEABI.bare.H/file_io.c b/src/static/MSL_C.PPCEABI.bare.H/file_io.c new file mode 100644 index 00000000..7e7fcefe --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/file_io.c @@ -0,0 +1,70 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/file_io.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/FILE_POS.h" + +int fclose(FILE* file) +{ + int flush_result, close_result; + + if (file == nullptr) + return (-1); + if (file->mMode.file_kind == __closed_file) + return (0); + + flush_result = fflush(file); + + close_result = (*file->closeFunc)(file->mHandle); + + file->mMode.file_kind = __closed_file; + file->mHandle = 0; + + if (file->mState.free_buffer) + free(file->mBuffer); + return ((flush_result || close_result) ? -1 : 0); +} + +int fflush(FILE* file) +{ + int pos; + + if (file == nullptr) { + return __flush_all(); + } + + if (file->mState.error != 0 || file->mMode.file_kind == __closed_file) { + return -1; + } + + if (file->mMode.io_mode == 1) { + return 0; + } + + if (file->mState.io_state >= __rereading) { + file->mState.io_state = __reading; + } + + if (file->mState.io_state == __reading) { + file->mBufferLength = 0; + } + + if (file->mState.io_state != __writing) { + file->mState.io_state = __neutral; + return 0; + } + + if (file->mMode.file_kind != __disk_file) { + pos = 0; + } else { + pos = ftell(file); + } + + if (__flush_buffer(file, 0) != 0) { + file->mState.error = 1; + file->mBufferLength = 0; + return -1; + } + + file->mState.io_state = __neutral; + file->mPosition = pos; + file->mBufferLength = 0; + return 0; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/float.c b/src/static/MSL_C.PPCEABI.bare.H/float.c new file mode 100644 index 00000000..275b46f1 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/float.c @@ -0,0 +1,10 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/msl_types.h" + +s32 __float_nan[] = { 0x7FFFFFFF }; +s32 __float_huge[] = { 0x7F800000 }; +s32 __double_max[] = { 0x7FEFFFFF, 0xFFFFFFFF }; +s32 __double_huge[] = { 0x7FF00000, 0 }; +s32 __extended_min[] = { 0x00100000, 0 }; +s32 __extended_max[] = { 0x7FEFFFFF, 0xFFFFFFFF }; +s32 __float_max[] = { 0x7F7FFFFF }; +s32 __float_epsilon[] = { 0x34000000 }; diff --git a/src/static/MSL_C.PPCEABI.bare.H/k_cos.c b/src/static/MSL_C.PPCEABI.bare.H/k_cos.c new file mode 100644 index 00000000..17c4db00 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/k_cos.c @@ -0,0 +1,93 @@ + +/* @(#)k_cos.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/** + * __kernel_cos( x, y ) + * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * + * Algorithm + * 1. Since cos(-x) = cos(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. + * 3. cos(x) is approximated by a polynomial of degree 14 on + * [0,pi/4] + * 4 14 + * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x + * where the remez error is + * + * | 2 4 6 8 10 12 14 | -58 + * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 + * | | + * + * 4 6 8 10 12 14 + * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then + * cos(x) = 1 - x*x/2 + r + * since cos(x+y) ~ cos(x) - sin(x)*y + * ~ cos(x) - x*y, + * a correction term is necessary in cos(x) and hence + * cos(x+y) = 1 - (x*x/2 - (r - x*y)) + * For better accuracy when x > 0.3, let qx = |x|/4 with + * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. + * Then + * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)). + * Note that 1-qx and (x*x/2-qx) is EXACT here, and the + * magnitude of the latter is at least a quarter of x*x/2, + * thus, reducing the rounding error in the subtraction. + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif + one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ + C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ + C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ + C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ + C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ + C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ + C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +#ifdef __STDC__ +double __kernel_cos(double x, double y) +#else +double __kernel_cos(x, y) +double x, y; +#endif +{ + double a, hz, z, r, qx; + int ix; + ix = __HI(x) & 0x7fffffff; /* ix = |x|'s high word*/ + if (ix < 0x3e400000) { /* if x < 2**27 */ + if (((int)x) == 0) + return one; /* generate inexact */ + } + z = x * x; + r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6))))); + if (ix < 0x3FD33333) /* if |x| < 0.3 */ + return one - (0.5 * z - (z * r - x * y)); + else { + if (ix > 0x3fe90000) { /* x > 0.78125 */ + qx = 0.28125; + } else { + __HI(qx) = ix - 0x00200000; /* x/4 */ + __LO(qx) = 0; + } + hz = 0.5 * z - qx; + a = one - qx; + return a - (hz - (z * r - x * y)); + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/k_rem_pio2.c b/src/static/MSL_C.PPCEABI.bare.H/k_rem_pio2.c new file mode 100644 index 00000000..86eea426 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/k_rem_pio2.c @@ -0,0 +1,353 @@ + +#ifndef _No_Floating_Point +/* @(#)k_rem_pio2.c 1.2 95/01/04 */ +/* $Id: k_rem_pio2.c,v 1.2.14.1 2002/01/31 15:24:13 ceciliar Exp $ */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/** + * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) + * double x[],y[]; int e0,nx,prec; int ipio2[]; + * + * __kernel_rem_pio2 return the last three digits of N with + * y = x - N*pi/2 + * so that |y| < pi/2. + * + * The method is to compute the integer (mod 8) and fraction parts of + * (2/pi)*x without doing the full multiplication. In general we + * skip the part of the product that are known to be a huge integer ( + * more accurately, = 0 mod 8 ). Thus the number of operations are + * independent of the exponent of the input. + * + * (2/pi) is represented by an array of 24-bit integers in ipio2[]. + * + * Input parameters: + * x[] The input value (must be positive) is broken into nx + * pieces of 24-bit integers in double precision format. + * x[i] will be the i-th 24 bit of x. The scaled exponent + * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 + * match x's up to 24 bits. + * + * Example of breaking a double positive z into x[0]+x[1]+x[2]: + * e0 = ilogb(z)-23 + * z = ldexp(z,-e0) + * for i = 0,1,2 + * x[i] = floor(z) + * z = (z-x[i])*2**24 + * + * + * y[] ouput result in an array of double precision numbers. + * The dimension of y[] is: + * 24-bit precision 1 + * 53-bit precision 2 + * 64-bit precision 2 + * 113-bit precision 3 + * The actual value is the sum of them. Thus for 113-bit + * precision, one may have to do something like: + * + * f128 t,w,r_head, r_tail; + * t = (f128)y[2] + (f128)y[1]; + * w = (f128)y[0]; + * r_head = t+w; + * r_tail = w - (r_head - t); + * + * e0 The exponent of x[0] + * + * nx dimension of x[] + * + * prec an integer indicating the precision: + * 0 24 bits (single) + * 1 53 bits (double) + * 2 64 bits (extended) + * 3 113 bits (quad) + * + * ipio2[] + * integer array, contains the (24*i)-th to (24*i+23)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * ipio2[i] * 2^(-24(i+1)). + * + * External function: + * double ldexp(), floor(); + * + * + * Here is the description of some local variables: + * + * jk jk+1 is the initial number of terms of ipio2[] needed + * in the computation. The recommended value is 2,3,4, + * 6 for single, double, extended,and quad. + * + * jz local integer variable indicating the number of + * terms of ipio2[] used. + * + * jx nx - 1 + * + * jv index for pointing to the suitable ipio2[] for the + * computation. In general, we want + * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 + * is an integer. Thus + * e0-3-24*jv >= 0 or (e0-3)/24 >= jv + * Hence jv = max(0,(e0-3)/24). + * + * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. + * + * q[] double array with integral value, representing the + * 24-bits chunk of the product of x and 2/pi. + * + * q0 the corresponding exponent of q[0]. Note that the + * exponent for q[i] would be q0-24*i. + * + * PIo2[] double precision array, obtained by cutting pi/2 + * into 24 bits chunks. + * + * f[] ipio2[] in floating point + * + * iq[] integer array by breaking up q[] in 24-bits chunk. + * + * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] + * + * ih integer. If >0 it indicates q[] is >= 0.5, hence + * it also indicates the *sign* of the result. + * + */ + +/** + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const int init_jk[] = { 2, 3, 4, 6 }; +/* initial value for jk */ /*- cc 020130 -*/ +#else +static int init_jk[] = { 2, 3, 4, 6 }; /*- cc 020130 -*/ +#endif + +#ifdef __STDC__ +static const double PIo2[] = { +#else +static double PIo2[] = { +#endif + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +}; + +#ifdef __STDC__ +static const double +#else +static double +#endif + zero = 0.0, + one = 1.0, two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ + twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ + +#ifdef __STDC__ +int __kernel_rem_pio2(double* x, double* y, int e0, int nx, int prec, const int* ipio2) /*- cc 020130 -*/ +#else +int __kernel_rem_pio2(x, y, e0, nx, prec, ipio2) /*- cc 020130 -*/ +double x[], y[]; +int e0, nx, prec; +int ipio2[]; /*- cc 020130 -*/ +#endif +{ + int jz, jx, jv, jp, jk, carry, n, iq[20], i, j, k, m, q0, ih; /*- cc 020130 -*/ + double z, fw, f[20], fq[20], q[20]; + + /* initialize jk*/ + jk = init_jk[prec]; + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx - 1; + jv = (e0 - 3) / 24; + if (jv < 0) + jv = 0; + q0 = e0 - 24 * (jv + 1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv - jx; + m = jx + jk; + for (i = 0; i <= m; i++, j++) + f[i] = (j < 0) ? zero : (double)ipio2[j]; + + /* compute q[0],q[1],...q[jk] */ + for (i = 0; i <= jk; i++) { + for (j = 0, fw = 0.0; j <= jx; j++) + fw += x[j] * f[jx + i - j]; + q[i] = fw; + } + + jz = jk; +recompute: + /* distill q[] into iq[] reversingly */ + for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) { + fw = (double)((int)(twon24 * z)); /*- cc 020130 -*/ + iq[i] = (int)(z - two24 * fw); /*- cc 020130 -*/ + z = q[j - 1] + fw; + } + + /* compute n */ + z = ldexp(z, q0); /* actual value of z */ + z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */ + n = (int)z; /*- cc 020130 -*/ + z -= (double)n; + ih = 0; + if (q0 > 0) { /* need iq[jz-1] to determine n */ + i = (iq[jz - 1] >> (24 - q0)); + n += i; + iq[jz - 1] -= i << (24 - q0); + ih = iq[jz - 1] >> (23 - q0); + } else if (q0 == 0) + ih = iq[jz - 1] >> 23; + else if (z >= 0.5) + ih = 2; + + if (ih > 0) { /* q > 0.5 */ + n += 1; + carry = 0; + for (i = 0; i < jz; i++) { /* compute 1-q */ + j = iq[i]; + if (carry == 0) { + if (j != 0) { + carry = 1; + iq[i] = 0x1000000 - j; + } + } else + iq[i] = 0xffffff - j; + } + if (q0 > 0) { /* rare case: chance is 1 in 12 */ + switch (q0) { + case 1: + iq[jz - 1] &= 0x7fffff; + break; + case 2: + iq[jz - 1] &= 0x3fffff; + break; + } + } + if (ih == 2) { + z = one - z; + if (carry != 0) + z -= ldexp(one, q0); + } + } + + /* check if recomputation is needed */ + if (z == zero) { + j = 0; + for (i = jz - 1; i >= jk; i--) + j |= iq[i]; + if (j == 0) { /* need recomputation */ + for (k = 1; iq[jk - k] == 0; k++) + ; /* k = no. of terms needed */ + + for (i = jz + 1; i <= jz + k; i++) { /* add q[jz+1] to q[jz+k] */ + f[jx + i] = (double)ipio2[jv + i]; + for (j = 0, fw = 0.0; j <= jx; j++) + fw += x[j] * f[jx + i - j]; + q[i] = fw; + } + jz += k; + goto recompute; + } + } + + /* chop off zero terms */ + if (z == 0.0) { + jz -= 1; + q0 -= 24; + while (iq[jz] == 0) { + jz--; + q0 -= 24; + } + } else { /* break z into 24-bit if necessary */ + z = ldexp(z, -q0); + if (z >= two24) { + fw = (double)((int)(twon24 * z)); /*- cc 020130 -*/ + iq[jz] = (int)(z - two24 * fw); /*- cc 020130 -*/ + jz += 1; + q0 += 24; + iq[jz] = (int)fw; /*- cc 020130 -*/ + } else + iq[jz] = (int)z; /*- cc 020130 -*/ + } + + /* convert integer "bit" chunk to floating-point value */ + fw = ldexp(one, q0); + for (i = jz; i >= 0; i--) { + q[i] = fw * (double)iq[i]; + fw *= twon24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for (i = jz; i >= 0; i--) { + for (fw = 0.0, k = 0; k <= jp && k <= jz - i; k++) + fw += PIo2[k] * q[i + k]; + fq[jz - i] = fw; + } + + /* compress fq[] into y[] */ + switch (prec) { + case 0: + fw = 0.0; + for (i = jz; i >= 0; i--) + fw += fq[i]; + y[0] = (ih == 0) ? fw : -fw; + break; + case 1: + case 2: + fw = 0.0; + for (i = jz; i >= 0; i--) + fw += fq[i]; + y[0] = (ih == 0) ? fw : -fw; + fw = fq[0] - fw; + for (i = 1; i <= jz; i++) + fw += fq[i]; + y[1] = (ih == 0) ? fw : -fw; + break; + case 3: /* painful */ + for (i = jz; i > 0; i--) { + fw = fq[i - 1] + fq[i]; + fq[i] += fq[i - 1] - fw; + fq[i - 1] = fw; + } + for (i = jz; i > 1; i--) { + fw = fq[i - 1] + fq[i]; + fq[i] += fq[i - 1] - fw; + fq[i - 1] = fw; + } + for (fw = 0.0, i = jz; i >= 2; i--) + fw += fq[i]; + if (ih == 0) { + y[0] = fq[0]; + y[1] = fq[1]; + y[2] = fw; + } else { + y[0] = -fq[0]; + y[1] = -fq[1]; + y[2] = -fw; + } + } + return n & 7; +} +#endif /* _No_Floating_Point */ diff --git a/src/static/MSL_C.PPCEABI.bare.H/k_sin.c b/src/static/MSL_C.PPCEABI.bare.H/k_sin.c new file mode 100644 index 00000000..4fe79c7d --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/k_sin.c @@ -0,0 +1,80 @@ + +/* @(#)k_sin.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __kernel_sin( x, y, iy) + * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). + * + * Algorithm + * 1. Since sin(-x) = -sin(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0. + * 3. sin(x) is approximated by a polynomial of degree 13 on + * [0,pi/4] + * 3 13 + * sin(x) ~ x + S1*x + ... + S6*x + * where + * + * |sin(x) 2 4 6 8 10 12 | -58 + * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 + * | x | + * + * 4. sin(x+y) = sin(x) + sin'(x')*y + * ~ sin(x) + (1-x*x/2)*y + * For better accuracy, let + * 3 2 2 2 2 + * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) + * then 3 2 + * sin(x) = x + (S1*x + (x *(r-y/2)+y)) + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif + half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ + S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ + S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ + S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ + S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ + S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ + S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +#ifdef __STDC__ +double __kernel_sin(double x, double y, int iy) +#else +double __kernel_sin(x, y, iy) +double x, y; +int iy; /* iy=0 if y is zero */ +#endif +{ + double z, r, v; + int ix; + ix = __HI(x) & 0x7fffffff; /* high word of x */ + if (ix < 0x3e400000) /* |x| < 2**-27 */ + { + if ((int)x == 0) + return x; + } /* generate inexact */ + z = x * x; + v = z * x; + r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); + if (iy == 0) + return x + v * (S1 + z * r); + else + return x - ((z * (half * y - v * r) - y) - v * S1); +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/mbstring.c b/src/static/MSL_C.PPCEABI.bare.H/mbstring.c new file mode 100644 index 00000000..6de3ead5 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/mbstring.c @@ -0,0 +1,172 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/mbstring.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/string.h" + +static int is_utf8_complete(const char* s, size_t n) +{ + if (n == 0) { // must have more than zero characters + return -1; + } + + if (s[0] == 0x00) { // first char is 0 + return 0; + } + + if ((s[0] & 0x80) == 0x00) { + return (1); + } else if ((s[0] & 0xe0) == 0xc0) { + if (n >= 2) { + if ((*(s + 1) & 0x80) == 0x80) { + return 2; + } + return -1; + } + return -2; + } else if ((s[0] & 0xf0) == 0xe0) { + if (n >= 3) { + if ((s[1] & 0x80) == 0x80) { + if ((s[2] & 0x80) == 0x80) { + return 3; + } + } + return -1; + } else if ((n == 2 && ((s[1] & 0x80) == 0x80)) || n == 1) { + return -2; + } + return -1; + } else { + return (-1); + } +} + +int mbtowc(wchar_t* pwc, const char* s, size_t n) +{ + return mbstowcs(pwc, s, n); +} + +inline static int unicode_to_UTF8(char* s, wchar_t wchar) +{ + int number_of_bytes; + wchar_t wide_char; + char* target_ptr; + char first_byte_mark[4] = { 0x00, 0x00, 0xc0, 0xe0 }; + + if (!s) + return (0); + + wide_char = wchar; + if (wide_char < 0x0080) + number_of_bytes = 1; + else if (wide_char < 0x0800) + number_of_bytes = 2; + else + number_of_bytes = 3; + + target_ptr = s + number_of_bytes; + + switch (number_of_bytes) { + case 3: + *--target_ptr = (wide_char & 0x003f) | 0x80; + wide_char >>= 6; + case 2: + *--target_ptr = (wide_char & 0x003f) | 0x80; + wide_char >>= 6; + case 1: + *--target_ptr = wide_char | first_byte_mark[number_of_bytes]; + } + + return number_of_bytes; +} + +inline int wctomb(char* s, wchar_t wchar) +{ + return (unicode_to_UTF8(s, wchar)); +} + +inline int mbstowcs(wchar_t* pwc, const char* s, size_t n) +{ + u32 result_chr; + int number_of_bytes = 0; + int isUTF8; + char* source; + + if (!s) { + number_of_bytes = 0; + return (number_of_bytes); + } + + if (n <= 0) { + number_of_bytes = -1; + return (number_of_bytes); + } + + isUTF8 = is_utf8_complete(s, n); + if (isUTF8 < 0) { + number_of_bytes = -1; + return number_of_bytes; + } + + source = (char*)s; + switch (isUTF8) { + case 3: + result_chr = (*source & 0x1f); + source++; + number_of_bytes = (result_chr << 6) & 0x3C0; + case 2: + result_chr = number_of_bytes | (*source & 0x3f); + source++; + number_of_bytes = (result_chr << 6) & 0xFFC0; + case 1: + result_chr = number_of_bytes | (*source & 0x7f); + source++; + number_of_bytes = result_chr & 0xFFFF; + } + + result_chr = number_of_bytes & 0xFFFF; + + if (!(result_chr)) { + result_chr = 0; + } else if (result_chr < 0x00000080) { + result_chr = 1; + } else if (result_chr < 0x00000800) { + result_chr = 2; + } else { + result_chr = 3; + } + + if ((int)result_chr != isUTF8) { + number_of_bytes = -1; + return (number_of_bytes); + } + if (pwc) { + *pwc = number_of_bytes; + } + return isUTF8; +} + +size_t wcstombs(char* s, const wchar_t* pwcs, size_t n) +{ + int chars_written = 0; + int result; + char temp[3]; + wchar_t* source; + + if (!s || !pwcs) + return (0); + + source = (wchar_t*)pwcs; + while (chars_written <= n) { + if (!*source) { + *(s + chars_written) = '\0'; + break; + } else { + result = wctomb(temp, *source++); + if ((chars_written + result) <= n) { + strncpy(s + chars_written, temp, result); + chars_written += result; + } else + break; + } + } + + return chars_written; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/mem.c b/src/static/MSL_C.PPCEABI.bare.H/mem.c new file mode 100644 index 00000000..6235ef71 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/mem.c @@ -0,0 +1,98 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/string.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/mem_funcs.h" + +// thanks, kiwi! +void* memmove(void* dst, const void* src, size_t len) +{ + u8* csrc; + u8* cdst; + + int reverse = (u32)src < (u32)dst; + + if (len >= 32) { + if (((u32)dst ^ (u32)src) & 3) { + if (!reverse) { + __copy_longs_unaligned(dst, src, len); + } else { + __copy_longs_rev_unaligned(dst, src, len); + } + } else { + if (!reverse) { + __copy_longs_aligned(dst, src, len); + } else { + __copy_longs_rev_aligned(dst, src, len); + } + } + + return dst; + } else { + if (!reverse) { + csrc = ((u8*)src) - 1; + cdst = ((u8*)dst) - 1; + len++; + + while (--len > 0) { + *++cdst = *++csrc; + } + } else { + csrc = (u8*)src + len; + cdst = (u8*)dst + len; + len++; + + while (--len > 0) { + *--cdst = *--csrc; + } + } + } + + return dst; +} + +void* memchr(u8* s, int c, size_t n) +{ + int n_count; + size_t char_check; + + char_check = (u8)c; + s = &s[-1]; + n_count = n + 1; + while (--n_count) { + if (*++s == char_check) { + return s; + } + } + + return 0; +} + +u8* __memrchr(u8* s, u8 c, size_t n) +{ + int n_count; + size_t char_check; + + char_check = (u8)c; + s = &s[n]; + n_count = n + 1; + while (--n_count) { + if (*--s == char_check) { + return s; + } + } + + return 0; +} + +int memcmp(const void* __s1, const void* __s2, size_t __n) +{ + const u8* val1 = ((const u8*)__s1 - 1); + const u8* val2 = ((const u8*)__s2 - 1); + size_t size = __n + 1; + + while (--size > 0) { + if (*++val1 != *++val2) { + return (val1[0]) < (val2[0]) ? -1 : 1; + } + } + + return 0; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/mem_funcs.c b/src/static/MSL_C.PPCEABI.bare.H/mem_funcs.c new file mode 100644 index 00000000..093364e0 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/mem_funcs.c @@ -0,0 +1,202 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/mem_funcs.h" + +void __copy_longs_aligned(void* pDest, const void* pSrc, u32 len) +{ + u32 i = (-(u32)pDest) & 3; + srcCharPtr = ((u8*)pSrc) - 1; + destCharPtr = ((u8*)pDest) - 1; + + if (i != 0) { + len -= i; + + do { + *++(destCharPtr) = *++(srcCharPtr); + } while (--i); + } + + srcLongPtr = ((u32*)(srcCharPtr + 1)) - 1; + destLongPtr = ((u32*)(destCharPtr + 1)) - 1; + + i = len >> 5; + + if (i != 0) { + do { + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + *++(destLongPtr) = *++(srcLongPtr); + } while (--i); + } + + i = (len & 31) >> 2; + + if (i != 0) { + do { + *++(destLongPtr) = *++(srcLongPtr); + } while (--i); + } + + srcCharPtr = ((u8*)(srcLongPtr + 1)) - 1; + destCharPtr = ((u8*)(destLongPtr + 1)) - 1; + + len &= 3; + + if (len != 0) { + do + *++(destCharPtr) = *++(srcCharPtr); + while (--len); + } +} + +void __copy_longs_rev_aligned(void* pDest, const void* pSrc, u32 len) +{ + u32 i; + srcCharPtr = ((u8*)pSrc) + len; + destCharPtr = ((u8*)pDest) + len; + i = ((u32)destCharPtr) & 3; + + if (i != 0) { + len -= i; + + do { + *--destCharPtr = *--srcCharPtr; + } while (--i); + } + + i = len >> 5; + + if (i != 0) { + do { + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + *--destLongPtr = *--srcLongPtr; + } while (--i); + } + + i = (len & 31) >> 2; + + if (i != 0) { + do { + *--destLongPtr = *--srcLongPtr; + } while (--i); + } + + len &= 3; + + if (len != 0) { + do { + *--destCharPtr = *--srcCharPtr; + } while (--len); + } +} + +void __copy_longs_unaligned(void* pDest, const void* pSrc, u32 len) +{ + u32 i, v1, v2; + uint src, ls, rs; + + i = (-(u32)pDest) & 3; + srcCharPtr = ((u8*)pSrc) - 1; + destCharPtr = ((u8*)pDest) - 1; + + if (i != 0) { + len -= i; + + do { + *++destCharPtr = *++srcCharPtr; + } while (--i); + } + + src = ((uint)(srcCharPtr + 1)) & 3; + ls = src << 3; + rs = 32 - ls; + + srcCharPtr -= src; + + srcLongPtr = ((u32*)(srcCharPtr + 1)) - 1; + destLongPtr = ((u32*)(destCharPtr + 1)) - 1; + + i = len >> 3; + v1 = *++srcLongPtr; + + do { + v2 = *++srcLongPtr; + *++destLongPtr = (v1 << ls) | (v2 >> rs); + v1 = *++srcLongPtr; + *++destLongPtr = (v2 << ls) | (v1 >> rs); + } while (--i); + + if (len & 4) { + v2 = *++srcLongPtr; + *++destLongPtr = (v1 << ls) | (v2 >> rs); + } + + srcCharPtr = ((u8*)(srcLongPtr + 1)) - 1; + destCharPtr = ((u8*)(destLongPtr + 1)) - 1; + + len &= 3; + + if (len != 0) { + srcCharPtr -= 4 - src; + do { + *++destCharPtr = *++srcCharPtr; + } while (--len); + } +} + +void __copy_longs_rev_unaligned(void* pDest, const void* pSrc, u32 len) +{ + u32 i, v1, v2; + uint src, ls, rs; + + srcCharPtr = ((u8*)pSrc) + len; + destCharPtr = ((u8*)pDest) + len; + i = ((u32)pDest) & 3; + + if (i != 0) { + len -= i; + + do { + *--destCharPtr = *--srcCharPtr; + } while (--i); + } + + src = ((uint)(srcCharPtr)) & 3; + ls = src << 3; + rs = 32 - ls; + + srcCharPtr += 4 - src; + + i = len >> 3; + v1 = *--srcLongPtr; + + do { + v2 = *--srcLongPtr; + *--destLongPtr = (v2 << ls) | (v1 >> rs); + v1 = *--srcLongPtr; + *--destLongPtr = (v1 << ls) | (v2 >> rs); + } while (--i); + + if (len & 4) { + v2 = *--srcLongPtr; + *--destLongPtr = (v2 << ls) | (v1 >> rs); + } + + len &= 3; + + if (len != 0) { + srcCharPtr += src; + do { + *--destCharPtr = *--srcCharPtr; + } while (--len); + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/misc_io.c b/src/static/MSL_C.PPCEABI.bare.H/misc_io.c new file mode 100644 index 00000000..a297559b --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/misc_io.c @@ -0,0 +1,7 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/misc_io.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +void __stdio_atexit(void) +{ + __stdio_exit = __close_all; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/printf.c b/src/static/MSL_C.PPCEABI.bare.H/printf.c new file mode 100644 index 00000000..aacdb96a --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/printf.c @@ -0,0 +1,1242 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/stdio_api.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_fp.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/secure_error.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/critical_regions.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/mem.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/mbstring.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/printf.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/direct_io.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/wchar_io.h" +#include "stdarg.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/string.h" + +#define TARGET_FLOAT_BITS 64 +#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS / 8) +#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP +#define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG +#define TARGET_FLOAT_IMPLICIT_J_BIT 1 +#define TARGET_FLOAT_MANT_BITS (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT) +#define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1) + +typedef s64 intmax_t; + +#define PTRDIFF __typeof__((char*)0 - (char*)0) +typedef PTRDIFF ptrdiff_t; + +enum justification_options { left_justification, right_justification, zero_fill }; + +enum sign_options { only_minus, sign_always, space_holder }; + +enum argument_options { + normal_argument, + char_argument, + short_argument, + long_argument, + long_long_argument, + long_double_argument, + wchar_argument +}; + +typedef struct { + u8 justification_options; // _0 + u8 sign_options; // _1 + u8 precision_specified; // _2 + u8 alternate_form; // _3 + u8 argument_options; // _4 + u8 conversion_char; // _5 + int field_width; // _8 + int precision; // _C +} print_format; + +static const char* parse_format(const char* format_string, va_list* arg, print_format* format) +{ + print_format f; + const char* s = format_string; + int c; + int flag_found; + f.justification_options = right_justification; + f.sign_options = only_minus; + f.precision_specified = 0; + f.alternate_form = 0; + f.argument_options = normal_argument; + f.field_width = 0; + f.precision = 0; + + if ((c = *++s) == '%') { + f.conversion_char = c; + *format = f; + return ((const char*)s + 1); + } + + for (;;) { + flag_found = 1; + + switch (c) { + case '-': + f.justification_options = left_justification; + break; + case '+': + f.sign_options = sign_always; + break; + case ' ': + if (f.sign_options != sign_always) { + f.sign_options = space_holder; + } + break; + case '#': + f.alternate_form = 1; + break; + case '0': + if (f.justification_options != left_justification) { + f.justification_options = zero_fill; + } + break; + default: + flag_found = 0; + break; + } + + if (flag_found) { + c = *++s; + } else { + break; + } + } + + if (c == '*') { + if ((f.field_width = va_arg(*arg, int)) < 0) { + f.justification_options = left_justification; + f.field_width = -f.field_width; + } + + c = *++s; + } else { + while (isdigit(c)) { + f.field_width = (f.field_width * 10) + (c - '0'); + c = *++s; + } + } + + if (f.field_width > 509) { + f.conversion_char = 0xFF; + *format = f; + return ((const char*)s + 1); + } + + if (c == '.') { + f.precision_specified = 1; + + if ((c = *++s) == '*') { + if ((f.precision = va_arg(*arg, int)) < 0) { + f.precision_specified = 0; + } + + c = *++s; + } else { + while (isdigit(c)) { + f.precision = (f.precision * 10) + (c - '0'); + c = *++s; + } + } + } + + flag_found = 1; + + switch (c) { + case 'h': + f.argument_options = short_argument; + + if (s[1] == 'h') { + f.argument_options = char_argument; + c = *++s; + } + + break; + + case 'l': + f.argument_options = long_argument; + + if (s[1] == 'l') { + f.argument_options = long_long_argument; + c = *++s; + } + + break; + + case 'L': + f.argument_options = long_double_argument; + break; + default: + flag_found = 0; + break; + } + + if (flag_found) { + c = *++s; + } + + f.conversion_char = c; + + switch (c) { + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + if (f.argument_options == long_double_argument) { + f.conversion_char = 0xFF; + break; + } + + if (!f.precision_specified) { + f.precision = 1; + } else if (f.justification_options == zero_fill) { + f.justification_options = right_justification; + } + break; + + case 'f': + case 'F': + if (f.argument_options == short_argument || f.argument_options == long_long_argument) { + f.conversion_char = 0xFF; + break; + } + + if (!f.precision_specified) { + f.precision = 6; + } + break; + + case 'a': + case 'A': + if (!f.precision_specified) { + f.precision = 0xD; + } + + if (f.argument_options == short_argument || f.argument_options == long_long_argument || f.argument_options == char_argument) { + f.conversion_char = 0xFF; + } + + break; + + case 'g': + case 'G': + if (!f.precision) { + f.precision = 1; + } + + case 'e': + case 'E': + if (f.argument_options == short_argument || f.argument_options == long_long_argument || f.argument_options == char_argument) { + f.conversion_char = 0xFF; + break; + } + + if (!f.precision_specified) { + f.precision = 6; + } + break; + + case 'p': + f.conversion_char = 'x'; + f.alternate_form = 1; + f.argument_options = long_argument; + f.precision = 8; + break; + + case 'c': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } else { + if (f.precision_specified || f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + break; + + case 's': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + break; + + case 'n': + if (f.argument_options == long_double_argument) { + f.conversion_char = 0xFF; + } + + break; + + default: + f.conversion_char = 0xFF; + break; + } + + *format = f; + return ((const char*)s + 1); +} + +static char* long2str(s32 num, char* buff, print_format format) +{ + u32 unsigned_num, base; + char* p; + int n, digits; + int minus = 0; + unsigned_num = num; + minus = 0; + + p = buff; + *--p = 0; + digits = 0; + + if (!num && !format.precision && !(format.alternate_form && format.conversion_char == 'o')) { + return p; + } + + switch (format.conversion_char) { + case 'd': + case 'i': + base = 10; + + if (num < 0) { + unsigned_num = -unsigned_num; + minus = 1; + } + break; + + case 'o': + base = 8; + format.sign_options = only_minus; + break; + + case 'u': + base = 10; + format.sign_options = only_minus; + break; + + case 'x': + case 'X': + base = 16; + format.sign_options = only_minus; + break; + } + + do { + n = unsigned_num % base; + unsigned_num /= base; + + if (n < 10) { + n += '0'; + } else { + n -= 10; + + if (format.conversion_char == 'x') { + n += 'a'; + } else { + n += 'A'; + } + } + + *--p = n; + ++digits; + } while (unsigned_num != 0); + + if (base == 8 && format.alternate_form && *p != '0') { + *--p = '0'; + ++digits; + } + + if (format.justification_options == zero_fill) { + format.precision = format.field_width; + + if (minus || format.sign_options != only_minus) + --format.precision; + + if (base == 16 && format.alternate_form) + format.precision -= 2; + } + + if (buff - p + format.precision > 509) + return (0); + + while (digits < format.precision) { + *--p = '0'; + ++digits; + } + + if (base == 16 && format.alternate_form) { + *--p = format.conversion_char; + *--p = '0'; + } + + if (minus) { + *--p = '-'; + } else if (format.sign_options == sign_always) { + *--p = '+'; + } else if (format.sign_options == space_holder) { + *--p = ' '; + } + + return p; +} + +static char* longlong2str(s64 num, char* pBuf, print_format fmt) +{ + u64 unsigned_num, base; + char* p; + int n, digits; + int minus = 0; + unsigned_num = num; + minus = 0; + p = pBuf; + *--p = 0; + digits = 0; + + if (!num && !fmt.precision && !(fmt.alternate_form && fmt.conversion_char == 'o')) { + return p; + } + + switch (fmt.conversion_char) { + case 'd': + case 'i': + base = 10; + + if (num < 0) { + unsigned_num = -unsigned_num; + minus = 1; + } + break; + case 'o': + base = 8; + fmt.sign_options = only_minus; + break; + case 'u': + base = 10; + fmt.sign_options = only_minus; + break; + case 'x': + case 'X': + base = 16; + fmt.sign_options = only_minus; + break; + } + + do { + n = unsigned_num % base; + unsigned_num /= base; + + if (n < 10) { + n += '0'; + } else { + n -= 10; + if (fmt.conversion_char == 'x') { + n += 'a'; + } else { + n += 'A'; + } + } + + *--p = n; + ++digits; + } while (unsigned_num != 0); + + if (base == 8 && fmt.alternate_form && *p != '0') { + *--p = '0'; + ++digits; + } + + if (fmt.justification_options == zero_fill) { + fmt.precision = fmt.field_width; + + if (minus || fmt.sign_options != only_minus) { + --fmt.precision; + } + + if (base == 16 && fmt.alternate_form) { + fmt.precision -= 2; + } + } + + if (pBuf - p + fmt.precision > 509) { + return 0; + } + + while (digits < fmt.precision) { + *--p = '0'; + ++digits; + } + + if (base == 16 && fmt.alternate_form) { + *--p = fmt.conversion_char; + *--p = '0'; + } + + if (minus) { + *--p = '-'; + } else if (fmt.sign_options == sign_always) { + *--p = '+'; + } else if (fmt.sign_options == space_holder) { + *--p = ' '; + } + + return p; +} + +static char* double2hex(f128 num, char* buff, print_format format) +{ + int offset, what_nibble = 0; + char* wrk_byte_ptr; + char *p, *q; + char working_byte; + f128 ld; + s16* sptr; + s16 snum; + s32 exp; + print_format exp_format; + int hex_precision; + decform form; + decimal dec; + + p = buff; + ld = num; + sptr = (s16*)&ld; + + if (format.precision > 509) { + return 0; + } + + form.style = (char)0; + form.digits = 0x20; + __num2dec(&form, num, &dec); + + if (*dec.sig.text == 'I') { + if (*sptr & 0x8000) { + p = buff - 5; + if (format.conversion_char == 'A') + strcpy(p, "-INF"); + else + strcpy(p, "-inf"); + } else { + p = buff - 4; + if (format.conversion_char == 'A') + strcpy(p, "INF"); + else + strcpy(p, "inf"); + } + + return p; + } else if (*dec.sig.text == 'N') { + if (*(char*)&num & 0x80) { + p = buff - 5; + if (format.conversion_char == 'A') + strcpy(p, "-NAN"); + else + strcpy(p, "-nan"); + } else { + p = buff - 4; + if (format.conversion_char == 'A') + strcpy(p, "NAN"); + else + strcpy(p, "nan"); + } + + return p; + } + + exp_format.justification_options = right_justification; + exp_format.sign_options = sign_always; + exp_format.precision_specified = 0; + exp_format.alternate_form = 0; + exp_format.argument_options = normal_argument; + exp_format.field_width = 0; + exp_format.precision = 1; + exp_format.conversion_char = 'd'; + + snum = (*sptr & 0x7ff0) >> 4; + + exp = snum - 0x3FF; + + p = long2str(exp, buff, exp_format); + if (format.conversion_char == 'a') + *--p = 'p'; + else + *--p = 'P'; + + q = (char*)# + + for (hex_precision = format.precision; hex_precision >= 1; hex_precision--) { + working_byte = *(q + (hex_precision / 2) + 1); + if (hex_precision % 2) + working_byte = working_byte & 0x0f; + else + working_byte = (working_byte >> 4) & 0x0f; + + if (working_byte < 10) { + working_byte += '0'; + } else { + working_byte -= 10; + + if (format.conversion_char == 'a') { + working_byte += 'a'; + } else { + working_byte += 'A'; + } + } + + *--p = working_byte; + } + + if (format.precision || format.alternate_form) { + *--p = '.'; + } + + *--p = '1'; + + if (format.conversion_char == 'a') { + *--p = 'x'; + } else { + *--p = 'X'; + } + + *--p = '0'; + + if (*sptr & 0x8000) { + *--p = '-'; + } else if (format.sign_options == sign_always) { + *--p = '+'; + } else if (format.sign_options == space_holder) { + *--p = ' '; + } + + return p; +} + +static void round_decimal(decimal* dec, int new_length) +{ + char c; + char* p; + int carry; + + if (new_length < 0) { + return_zero: + dec->exp = 0; + dec->sig.length = 1; + *dec->sig.text = '0'; + return; + } + + if (new_length >= dec->sig.length) { + return; + } + + p = (char*)dec->sig.text + new_length + 1; + c = *--p - '0'; + + if (c == 5) { + char* q = &((char*)dec->sig.text)[dec->sig.length]; + + while (--q > p && *q == '0') + ; + carry = (q == p) ? p[-1] & 1 : 1; + } else { + carry = (c > 5); + } + + while (new_length != 0) { + c = *--p - '0' + carry; + + if ((carry = (c > 9)) != 0 || c == 0) { + --new_length; + } else { + *p = c + '0'; + break; + } + } + + if (carry != 0) { + dec->exp += 1; + dec->sig.length = 1; + *dec->sig.text = '1'; + return; + } else if (new_length == 0) { + goto return_zero; + } + + dec->sig.length = new_length; +} + +static char* float2str(f128 num, char* buff, print_format format) +{ + decimal dec; + decform form; + char* p; + char* q; + int n, digits, sign; + int int_digits, frac_digits; + int radix_marker; + + radix_marker = '.'; + + if (format.precision > 509) { + return 0; + } + + form.style = 0; + form.digits = 0x20; + __num2dec(&form, num, &dec); + p = (char*)dec.sig.text + dec.sig.length; + + while (dec.sig.length > 1 && *--p == '0') { + --dec.sig.length; + ++dec.exp; + } + + switch (*dec.sig.text) { + case '0': + dec.exp = 0; + break; + case 'I': + if (num < 0) { + p = buff - 5; + + if (isupper(format.conversion_char)) { + strcpy(p, "-INF"); + } else { + strcpy(p, "-inf"); + } + } else { + p = buff - 4; + if (isupper(format.conversion_char)) { + strcpy(p, "INF"); + } else { + strcpy(p, "inf"); + } + } + + return p; + + case 'N': + if (dec.sign) { + p = buff - 5; + + if (isupper(format.conversion_char)) { + strcpy(p, "-NAN"); + } else { + strcpy(p, "-nan"); + } + } else { + p = buff - 4; + if (isupper(format.conversion_char)) { + strcpy(p, "NAN"); + } else { + strcpy(p, "nan"); + } + } + + return p; + } + + dec.exp += dec.sig.length - 1; + p = buff; + *--p = 0; + + switch (format.conversion_char) { + case 'g': + case 'G': + + if (dec.sig.length > format.precision) { + round_decimal(&dec, format.precision); + } + + if (dec.exp < -4 || dec.exp >= format.precision) { + if (format.alternate_form) { + --format.precision; + } else { + format.precision = dec.sig.length - 1; + } + + if (format.conversion_char == 'g') { + format.conversion_char = 'e'; + } else { + format.conversion_char = 'E'; + } + + goto e_format; + } + + if (format.alternate_form) { + format.precision -= dec.exp + 1; + } else { + if ((format.precision = dec.sig.length - (dec.exp + 1)) < 0) { + format.precision = 0; + } + } + + goto f_format; + + case 'e': + case 'E': + e_format: + + if (dec.sig.length > format.precision + 1) { + round_decimal(&dec, format.precision + 1); + } + + n = dec.exp; + sign = '+'; + + if (n < 0) { + n = -n; + sign = '-'; + } + + for (digits = 0; n || digits < 2; ++digits) { + *--p = n % 10 + '0'; + n /= 10; + } + + *--p = sign; + *--p = format.conversion_char; + + if (buff - p + format.precision > 509) { + return 0; + } + + if (dec.sig.length < format.precision + 1) { + for (n = format.precision + 1 - dec.sig.length + 1; --n;) { + *--p = '0'; + } + } + + for (n = dec.sig.length, q = (char*)dec.sig.text + dec.sig.length; --n;) { + *--p = *--q; + } + + if (format.precision || format.alternate_form) { + *--p = radix_marker; + } + + *--p = *dec.sig.text; + + if (dec.sign) + *--p = '-'; + else if (format.sign_options == sign_always) + *--p = '+'; + else if (format.sign_options == space_holder) + *--p = ' '; + + break; + + case 'f': + case 'F': + f_format: + + if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0) + frac_digits = 0; + + if (frac_digits > format.precision) { + round_decimal(&dec, dec.sig.length - (frac_digits - format.precision)); + + if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0) + frac_digits = 0; + } + + if ((int_digits = dec.exp + 1) < 0) + int_digits = 0; + + if (int_digits + frac_digits > 509) + return 0; + + q = (char*)dec.sig.text + dec.sig.length; + + for (digits = 0; digits < (format.precision - frac_digits); ++digits) + *--p = '0'; + + for (digits = 0; digits < frac_digits && digits < dec.sig.length; ++digits) + *--p = *--q; + + for (; digits < frac_digits; ++digits) + *--p = '0'; + + if (format.precision || format.alternate_form) + *--p = radix_marker; + + if (int_digits) { + for (digits = 0; digits < int_digits - dec.sig.length; ++digits) { + *--p = '0'; + } + + for (; digits < int_digits; ++digits) { + *--p = *--q; + } + } else { + *--p = '0'; + } + + if (dec.sign) { + *--p = '-'; + } else if (format.sign_options == sign_always) { + *--p = '+'; + } else if (format.sign_options == space_holder) { + *--p = ' '; + } + + break; + } + + return p; +} + +static int __pformatter(void* (*WriteProc)(void*, const char*, size_t), void* WriteProcArg, const char* format_str, va_list arg) +{ + int num_chars, chars_written, field_width; + const char* format_ptr; + const char* curr_format; + print_format format; + s32 long_num; + s64 long_long_num; + f128 long_double_num; + char buff[512]; + char* buff_ptr; + char* string_end; + char fill_char = ' '; + + format_ptr = format_str; + chars_written = 0; + + while (*format_ptr) { + if (!(curr_format = strchr(format_ptr, '%'))) { + num_chars = strlen(format_ptr); + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { + return -1; + } + + break; + } + + num_chars = curr_format - format_ptr; + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, format_ptr, num_chars)) { + return -1; + } + + format_ptr = curr_format; + format_ptr = parse_format(format_ptr, (va_list*)arg, &format); + + switch (format.conversion_char) { + case 'd': + case 'i': + if (format.argument_options == long_argument) { + long_num = va_arg(arg, s32); + } else if (format.argument_options == long_long_argument) { + long_long_num = va_arg(arg, s64); + } else { + long_num = va_arg(arg, int); + } + + if (format.argument_options == short_argument) { + long_num = (s16)long_num; + } + + if (format.argument_options == char_argument) { + long_num = (s8)long_num; + } + + if ((format.argument_options == long_long_argument)) { + if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) { + goto conversion_error; + } + } else { + if (!(buff_ptr = long2str(long_num, buff + 512, format))) { + goto conversion_error; + } + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 'o': + case 'u': + case 'x': + case 'X': + if (format.argument_options == long_argument) { + long_num = va_arg(arg, u32); + } else if (format.argument_options == long_long_argument) { + long_long_num = va_arg(arg, s64); + } else { + long_num = va_arg(arg, uint); + } + + if (format.argument_options == short_argument) { + long_num = (u16)long_num; + } + + if (format.argument_options == char_argument) { + long_num = (u8)long_num; + } + + if ((format.argument_options == long_long_argument)) { + if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) { + goto conversion_error; + } + } else { + if (!(buff_ptr = long2str(long_num, buff + 512, format))) { + goto conversion_error; + } + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + if (format.argument_options == long_double_argument) { + long_double_num = va_arg(arg, f128); + } else { + long_double_num = va_arg(arg, f64); + } + + if (!(buff_ptr = float2str(long_double_num, buff + 512, format))) { + goto conversion_error; + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 'a': + case 'A': + if (format.argument_options == long_double_argument) { + long_double_num = va_arg(arg, f128); + } else { + long_double_num = va_arg(arg, f64); + } + + if (!(buff_ptr = double2hex(long_double_num, buff + 512, format))) { + goto conversion_error; + } + + num_chars = buff + 512 - 1 - buff_ptr; + break; + + case 's': + if (format.argument_options == wchar_argument) { + wchar_t* wcs_ptr = va_arg(arg, wchar_t*); + + if (wcs_ptr == NULL) { + wcs_ptr = L""; + } + + if ((num_chars = wcstombs(buff, wcs_ptr, sizeof(buff))) < 0) { + goto conversion_error; + } + + buff_ptr = &buff[0]; + } else { + buff_ptr = va_arg(arg, char*); + } + + if (buff_ptr == NULL) { + buff_ptr = ""; + } + + if (format.alternate_form) { + num_chars = (u8)*buff_ptr++; + + if (format.precision_specified && num_chars > format.precision) { + num_chars = format.precision; + } + } else if (format.precision_specified) { + num_chars = format.precision; + + if ((string_end = (char*)memchr((u8*)buff_ptr, 0, num_chars)) != 0) { + num_chars = string_end - buff_ptr; + } + } else { + num_chars = strlen(buff_ptr); + } + + break; + + case 'n': + buff_ptr = va_arg(arg, char*); + + switch (format.argument_options) { + case normal_argument: + *(int*)buff_ptr = chars_written; + break; + case short_argument: + *(s16*)buff_ptr = chars_written; + break; + case long_argument: + *(s32*)buff_ptr = chars_written; + break; + case long_long_argument: + *(s64*)buff_ptr = chars_written; + break; + } + + continue; + + case 'c': + buff_ptr = buff; + *buff_ptr = va_arg(arg, int); + num_chars = 1; + break; + + case '%': + buff_ptr = buff; + *buff_ptr = '%'; + num_chars = 1; + break; + + case 0xFF: + default: + conversion_error: + num_chars = strlen(curr_format); + chars_written += num_chars; + + if (num_chars && !(*WriteProc)(WriteProcArg, curr_format, num_chars)) { + return -1; + } + + return chars_written; + break; + } + + field_width = num_chars; + + if (format.justification_options != left_justification) { + fill_char = (format.justification_options == zero_fill) ? '0' : ' '; + + if (((*buff_ptr == '+') || (*buff_ptr == '-') || (*buff_ptr == ' ')) && (fill_char == '0')) { + if ((*WriteProc)(WriteProcArg, buff_ptr, 1) == 0) { + return -1; + } + + ++buff_ptr; + num_chars--; + } + + while (field_width < format.field_width) { + if ((*WriteProc)(WriteProcArg, &fill_char, 1) == 0) { + return -1; + } + + ++field_width; + } + } + + if (num_chars && !(*WriteProc)(WriteProcArg, buff_ptr, num_chars)) { + return -1; + } + + if (format.justification_options == left_justification) { + while (field_width < format.field_width) { + char blank = ' '; + + if ((*WriteProc)(WriteProcArg, &blank, 1) == 0) { + return -1; + } + + ++field_width; + } + } + + chars_written += field_width; + } + + return chars_written; +} + +static void* __FileWrite(void* pFile, const char* pBuffer, size_t char_num) +{ + return (fwrite(pBuffer, 1, char_num, (FILE*)pFile) == char_num ? pFile : 0); +} + +static void* __StringWrite(void* pCtrl, const char* pBuffer, size_t char_num) +{ + size_t chars; + __OutStrCtrl* ctrl = (__OutStrCtrl*)pCtrl; + void* res; + + chars = ((ctrl->CharsWritten + char_num) <= ctrl->MaxCharCount) ? char_num : ctrl->MaxCharCount - ctrl->CharsWritten; + res = memcpy(ctrl->CharStr + ctrl->CharsWritten, pBuffer, chars); + ctrl->CharsWritten += chars; + return (void*)1; +} + +int printf(const char* format, ...) +{ + int res; + + if (fwide(stdout, -1) >= 0) { + return -1; + } + + __begin_critical_region(stdin_access); + { + va_list args; + va_start(args, format); + res = __pformatter(&__FileWrite, (void*)stdout, format, args); + } + __end_critical_region(stdin_access); + return res; +} + +int vprintf(const char* pFormat, va_list arg) +{ + int ret; + + if (fwide(stdout, -1) >= 0) { + return -1; + } + + __begin_critical_region(stdin_access); + ret = __pformatter(&__FileWrite, (void*)stdout, pFormat, arg); + __end_critical_region(stdin_access); + return ret; +} + +int vsnprintf(char* s, size_t n, const char* format, va_list arg) +{ + int end; + __OutStrCtrl osc; + osc.CharStr = s; + osc.MaxCharCount = n; + osc.CharsWritten = 0; + + end = __pformatter(&__StringWrite, &osc, format, arg); + + if (s) { + s[(end < n) ? end : n - 1] = '\0'; + } + + return end; +} + +int vsprintf(char* s, const char* format, va_list arg) +{ + return vsnprintf(s, 0xFFFFFFFF, format, arg); +} + +int snprintf(char* s, size_t n, const char* format, ...) +{ + va_list args; + va_start(args, format); + return vsnprintf(s, n, format, args); +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/rand.c b/src/static/MSL_C.PPCEABI.bare.H/rand.c new file mode 100644 index 00000000..2bbd919f --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/rand.c @@ -0,0 +1,14 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/rand.h" + +static u32 next = 1; + +int rand(void) +{ + next = next * 1103515245 + 12345; + return ((next >> 16) & 0x7fff); +} + +void srand(u32 seed) +{ + next = seed; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_atan.c b/src/static/MSL_C.PPCEABI.bare.H/s_atan.c new file mode 100644 index 00000000..57b8a823 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_atan.c @@ -0,0 +1,143 @@ + +/* @(#)s_atan.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* atan(x) + * Method + * 1. Reduce x to positive by atan(x) = -atan(-x). + * 2. According to the integer k=4t+0.25 chopped, t=x, the argument + * is further reduced to one of the following intervals and the + * arctangent of t is evaluated by the corresponding formula: + * + * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) + * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) + * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) + * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) + * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double atanhi[] = { +#else +static double atanhi[] = { +#endif + 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ + 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ + 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ + 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ +}; + +#ifdef __STDC__ +static const double atanlo[] = { +#else +static double atanlo[] = { +#endif + 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ + 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ + 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ + 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ +}; + +#ifdef __STDC__ +static const double aT[] = { +#else +static double aT[] = { +#endif + 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ + -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ + 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ + -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ + 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ + -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ + 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ + -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ + 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ + -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ + 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ +}; + +#ifdef __STDC__ +static const double +#else +static double +#endif + one = 1.0, + huge = 1.0e300; + +#ifdef __STDC__ +double atan(double x) +#else +double atan(x) +double x; +#endif +{ + double w, s1, s2, z; + int ix, hx, id; + + hx = __HI(x); + ix = hx & 0x7fffffff; + if (ix >= 0x44100000) { /* if |x| >= 2^66 */ + if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (__LO(x) != 0))) + return x + x; /* NaN */ + if (hx > 0) + return atanhi[3] + atanlo[3]; + else + return -atanhi[3] - atanlo[3]; + } + if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ + if (ix < 0x3e200000) { /* |x| < 2^-29 */ + if (huge + x > one) + return x; /* raise inexact */ + } + id = -1; + } else { + x = __fabs(x); + if (ix < 0x3ff30000) { /* |x| < 1.1875 */ + if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ + id = 0; + x = (2.0 * x - one) / (2.0 + x); + } else { /* 11/16<=|x|< 19/16 */ + id = 1; + x = (x - one) / (x + one); + } + } else { + if (ix < 0x40038000) { /* |x| < 2.4375 */ + id = 2; + x = (x - 1.5) / (one + 1.5 * x); + } else { /* 2.4375 <= |x| < 2^66 */ + id = 3; + x = -1.0 / x; + } + } + } + /* end of argument reduction */ + z = x * x; + w = z * z; + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + s1 = z * (aT[0] + w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10]))))); + s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9])))); + if (id < 0) + return x - x * (s1 + s2); + else { + z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x); + return (hx < 0) ? -z : z; + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_ceil.c b/src/static/MSL_C.PPCEABI.bare.H/s_ceil.c new file mode 100644 index 00000000..341b3ad1 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_ceil.c @@ -0,0 +1,91 @@ + +/* @(#)s_ceil.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/** + * ceil(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to ceil(x). + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double huge = 1.0e300; +#else +static double huge = 1.0e300; +#endif + +#ifdef __STDC__ +double ceil(double x) +#else +double ceil(x) +double x; +#endif +{ + int i0, i1, j0; + unsigned i, j; + i0 = __HI(x); + i1 = __LO(x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + if (j0 < 20) { + if (j0 < 0) { /* raise inexact if x != 0 */ + if (huge + x > 0.0) { /* return 0*sign(x) if |x|<1 */ + if (i0 < 0) { + i0 = 0x80000000; + i1 = 0; + } else if ((i0 | i1) != 0) { + i0 = 0x3ff00000; + i1 = 0; + } + } + } else { + i = (0x000fffff) >> j0; + if (((i0 & i) | i1) == 0) + return x; /* x is integral */ + if (huge + x > 0.0) { /* raise inexact flag */ + if (i0 > 0) + i0 += (0x00100000) >> j0; + i0 &= (~i); + i1 = 0; + } + } + } else if (j0 > 51) { + if (j0 == 0x400) + return x + x; /* inf or NaN */ + else + return x; /* x is integral */ + } else { + i = ((unsigned)(0xffffffff)) >> (j0 - 20); + if ((i1 & i) == 0) + return x; /* x is integral */ + if (huge + x > 0.0) { /* raise inexact flag */ + if (i0 > 0) { + if (j0 == 20) + i0 += 1; + else { + j = i1 + (1 << (52 - j0)); + if (j < i1) + i0 += 1; /* got a carry */ + i1 = j; + } + } + i1 &= (~i); + } + } + __HI(x) = i0; + __LO(x) = i1; + return x; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_copysign.c b/src/static/MSL_C.PPCEABI.bare.H/s_copysign.c new file mode 100644 index 00000000..d2ff1885 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_copysign.c @@ -0,0 +1,31 @@ + +/* @(#)s_copysign.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/** + * copysign(double x, double y) + * copysign(x,y) returns a value with the magnitude of x and + * with the sign bit of y. + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +double copysign(double x, double y) +#else +double copysign(x, y) +double x, y; +#endif +{ + __HI(x) = (__HI(x) & 0x7fffffff) | (__HI(y) & 0x80000000); + return x; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_cos.c b/src/static/MSL_C.PPCEABI.bare.H/s_cos.c new file mode 100644 index 00000000..099afbc4 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_cos.c @@ -0,0 +1,83 @@ + +/* @(#)s_cos.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* cos(x) + * Return cosine function of x. + * + * kernel function: + * __kernel_sin ... sine function on [-pi/4,pi/4] + * __kernel_cos ... cosine function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +double cos(double x) +#else +double cos(x) +double x; +#endif +{ + double y[2], z = 0.0; + int n, ix; + + /* High word of x. */ + ix = __HI(x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if (ix <= 0x3fe921fb) + return __kernel_cos(x, z); + + /* cos(Inf or NaN) is NaN */ + else if (ix >= 0x7ff00000) + return x - x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x, y); + switch (n & 3) { + case 0: + return __kernel_cos(y[0], y[1]); + case 1: + return -__kernel_sin(y[0], y[1], 1); + case 2: + return -__kernel_cos(y[0], y[1]); + default: + return __kernel_sin(y[0], y[1], 1); + } + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_floor.c b/src/static/MSL_C.PPCEABI.bare.H/s_floor.c new file mode 100644 index 00000000..c22936f7 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_floor.c @@ -0,0 +1,90 @@ + +/* @(#)s_floor.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/** + * floor(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to floor(x). + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double huge = 1.0e300; +#else +static double huge = 1.0e300; +#endif + +#ifdef __STDC__ +double floor(double x) +#else +double floor(x) +double x; +#endif +{ + int i0, i1, j0; + unsigned i, j; + i0 = __HI(x); + i1 = __LO(x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + if (j0 < 20) { + if (j0 < 0) { /* raise inexact if x != 0 */ + if (huge + x > 0.0) { /* return 0*sign(x) if |x|<1 */ + if (i0 >= 0) { + i0 = i1 = 0; + } else if (((i0 & 0x7fffffff) | i1) != 0) { + i0 = 0xbff00000; + i1 = 0; + } + } + } else { + i = (0x000fffff) >> j0; + if (((i0 & i) | i1) == 0) + return x; /* x is integral */ + if (huge + x > 0.0) { /* raise inexact flag */ + if (i0 < 0) + i0 += (0x00100000) >> j0; + i0 &= (~i); + i1 = 0; + } + } + } else if (j0 > 51) { + if (j0 == 0x400) + return x + x; /* inf or NaN */ + else + return x; /* x is integral */ + } else { + i = ((unsigned)(0xffffffff)) >> (j0 - 20); + if ((i1 & i) == 0) + return x; /* x is integral */ + if (huge + x > 0.0) { /* raise inexact flag */ + if (i0 < 0) { + if (j0 == 20) + i0 += 1; + else { + j = i1 + (1 << (52 - j0)); + if (j < i1) + i0 += 1; /* got a carry */ + i1 = j; + } + } + i1 &= (~i); + } + } + __HI(x) = i0; + __LO(x) = i1; + return x; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_frexp.c b/src/static/MSL_C.PPCEABI.bare.H/s_frexp.c new file mode 100644 index 00000000..a36de734 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_frexp.c @@ -0,0 +1,58 @@ + +/* @(#)s_frexp.c 1.4 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/** + * for non-zero x + * x = frexp(arg,&exp); + * return a double fp quantity x such that 0.5 <= |x| <1.0 + * and the corresponding binary exponent "exp". That is + * arg = x*2^exp. + * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg + * with *exp=0. + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif + two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ + +#ifdef __STDC__ +double frexp(double x, int* eptr) +#else +double frexp(x, eptr) +double x; +int* eptr; +#endif +{ + int hx, ix, lx; + hx = __HI(x); + ix = 0x7fffffff & hx; + lx = __LO(x); + *eptr = 0; + if (ix >= 0x7ff00000 || ((ix | lx) == 0)) + return x; /* 0,inf,nan */ + if (ix < 0x00100000) { /* subnormal */ + x *= two54; + hx = __HI(x); + ix = hx & 0x7fffffff; + *eptr = -54; + } + *eptr += (ix >> 20) - 1022; + hx = (hx & 0x800fffff) | 0x3fe00000; + __HI(x) = hx; + return x; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_ldexp.c b/src/static/MSL_C.PPCEABI.bare.H/s_ldexp.c new file mode 100644 index 00000000..23f9a1fe --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_ldexp.c @@ -0,0 +1,62 @@ +#ifndef _No_Floating_Point +/* @(#)s_ldexp.c 1.2 95/01/04 */ +/* $Id: s_ldexp.c,v 1.3.14.1 2002/01/31 15:24:14 ceciliar Exp $ */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/math_api.h" /* for isfinite macro */ +static const double + + two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ + twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ + big = 1.0e+300, tiny = 1.0e-300; + +double ldexp(double x, int n) +{ + int k, hx, lx; /*- cc 020130 -*/ + if (!isfinite(x) || x == 0.0) + return x; + + hx = __HI(x); + lx = __LO(x); + k = (hx & 0x7ff00000) >> 20; /* extract exponent */ + if (k == 0) { /* 0 or subnormal x */ + if ((lx | (hx & 0x7fffffff)) == 0) + return x; /* +-0 */ + x *= two54; + hx = __HI(x); + k = ((hx & 0x7ff00000) >> 20) - 54; + if (n < -50000) + return tiny * x; /*underflow*/ + } + if (k == 0x7ff) + return x + x; /* NaN or Inf */ + k = k + n; + if (k > 0x7fe) + return big * copysign(big, x); /* overflow */ + if (k > 0) /* normal result */ + { + __HI(x) = (hx & 0x800fffff) | (k << 20); + return x; + } + if (k <= -54) + if (n > 50000) /* in case integer overflow in n+k */ + return big * copysign(big, x); /*overflow*/ + else + return tiny * copysign(tiny, x); /*underflow*/ + k += 54; /* subnormal result */ + __HI(x) = (hx & 0x800fffff) | (k << 20); + return x * twom54; +} + +/* changed __finite to __isfinite to match new naming convention 141097 bds */ +#endif /* _No_Floating_Point */ diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_modf.c b/src/static/MSL_C.PPCEABI.bare.H/s_modf.c new file mode 100644 index 00000000..ba888d1b --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_modf.c @@ -0,0 +1,80 @@ + +/* @(#)s_modf.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/** + * modf(double x, double *iptr) + * return fraction part of x, and return x's integral part in *iptr. + * Method: + * Bit twiddling. + * + * Exception: + * No exception. + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +static const double one = 1.0; +#else +static double one = 1.0; +#endif + +#ifdef __STDC__ +double modf(double x, double* iptr) +#else +double modf(x, iptr) +double x, *iptr; +#endif +{ + int i0, i1, j0; + unsigned i; + i0 = __HI(x); /* high x */ + i1 = __LO(x); /* low x */ + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; /* exponent of x */ + if (j0 < 20) { /* integer part in high x */ + if (j0 < 0) { /* |x|<1 */ + __HIp(iptr) = i0 & 0x80000000; + __LOp(iptr) = 0; /* *iptr = +-0 */ + return x; + } else { + i = (0x000fffff) >> j0; + if (((i0 & i) | i1) == 0) { /* x is integral */ + *iptr = x; + __HI(x) &= 0x80000000; + __LO(x) = 0; /* return +-0 */ + return x; + } else { + __HIp(iptr) = i0 & (~i); + __LOp(iptr) = 0; + return x - *iptr; + } + } + } else if (j0 > 51) { /* no fraction part */ + *iptr = x * one; + __HI(x) &= 0x80000000; + __LO(x) = 0; /* return +-0 */ + return x; + } else { /* fraction part in low x */ + i = ((unsigned)(0xffffffff)) >> (j0 - 20); + if ((i1 & i) == 0) { /* x is integral */ + *iptr = x; + __HI(x) &= 0x80000000; + __LO(x) = 0; /* return +-0 */ + return x; + } else { + __HIp(iptr) = i0; + __LOp(iptr) = i1 & (~i); + return x - *iptr; + } + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/s_sin.c b/src/static/MSL_C.PPCEABI.bare.H/s_sin.c new file mode 100644 index 00000000..66cb0746 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/s_sin.c @@ -0,0 +1,83 @@ + +/* @(#)s_sin.c 1.3 95/01/18 */ +/** + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* sin(x) + * Return sine function of x. + * + * kernel function: + * __kernel_sin ... sine function on [-pi/4,pi/4] + * __kernel_cos ... cose function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +double sin(double x) +#else +double sin(x) +double x; +#endif +{ + double y[2], z = 0.0; + int n, ix; + + /* High word of x. */ + ix = __HI(x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if (ix <= 0x3fe921fb) + return __kernel_sin(x, z, 0); + + /* sin(Inf or NaN) is NaN */ + else if (ix >= 0x7ff00000) + return x - x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x, y); + switch (n & 3) { + case 0: + return __kernel_sin(y[0], y[1], 1); + case 1: + return __kernel_cos(y[0], y[1]); + case 2: + return -__kernel_sin(y[0], y[1], 1); + default: + return -__kernel_cos(y[0], y[1]); + } + } +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/scanf.c b/src/static/MSL_C.PPCEABI.bare.H/scanf.c new file mode 100644 index 00000000..022cdd88 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/scanf.c @@ -0,0 +1,649 @@ +#include "stdarg.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/stdio_api.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/scanf.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/strtoul.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/strtold.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/mbstring.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/string.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_fp.h" + +typedef s64 intmax_t; + +#define PTRDIFF __typeof__((char*)0 - (char*)0) +typedef PTRDIFF ptrdiff_t; + +enum argument_options { + normal_argument, + char_argument, + short_argument, + long_argument, + long_long_argument, + double_argument, + long_double_argument, + wchar_argument +}; + +typedef u8 char_map[32]; + +typedef struct { + u8 suppress_assignment; + u8 field_width_specified; + u8 argument_options; + u8 conversion_char; + int field_width; + char_map char_set; +} scan_format; + +#define set_char_map(map, ch) map[(u8)ch >> 3] |= (1 << (ch & 7)) +#define tst_char_map(map, ch) (map[(u8)ch >> 3] & (1 << (ch & 7))) + +static const char* parse_format(const char* format_string, scan_format* format) +{ + const char* s = format_string; + int c; + int flag_found, invert; + scan_format f = { 0, 0, normal_argument, 0, 2147483647, { 0 } }; + + if (((c = *++s) == '%')) { + f.conversion_char = c; + *format = f; + return ((const char*)s + 1); + } + + if (c == '*') { + f.suppress_assignment = 1; + c = *++s; + } + + if (isdigit(c)) { + f.field_width = 0; + + do { + f.field_width = (f.field_width * 10) + (c - '0'); + c = *++s; + } while (isdigit(c)); + + if (f.field_width == 0) { + f.conversion_char = 0xFF; + *format = f; + return ((const char*)s + 1); + } + + f.field_width_specified = 1; + } + + flag_found = 1; + + switch (c) { + case 'h': + f.argument_options = short_argument; + + if (s[1] == 'h') { + f.argument_options = char_argument; + c = *++s; + } + + break; + case 'l': + f.argument_options = long_argument; + + if (s[1] == 'l') { + f.argument_options = long_long_argument; + c = *++s; + } + break; + case 'L': + f.argument_options = long_double_argument; + break; + default: + flag_found = 0; + } + + if (flag_found) { + c = *++s; + } + + f.conversion_char = c; + + switch (c) { + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + if (f.argument_options == long_double_argument) { + f.conversion_char = 0xFF; + break; + } + + break; + + case 'a': + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + if (f.argument_options == char_argument || f.argument_options == short_argument || f.argument_options == long_long_argument) { + f.conversion_char = 0xFF; + break; + } + + if (f.argument_options == long_argument) { + f.argument_options = double_argument; + } + + break; + + case 'p': + f.argument_options = long_argument; + f.conversion_char = 'x'; + break; + + case 'c': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + break; + + case 's': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + { + int i; + u8* p; + + for (i = sizeof(f.char_set), p = f.char_set; i; --i) { + *p++ = 0xFF; + } + + f.char_set[1] = 0xC1; + f.char_set[4] = 0xFE; + } + + break; + + case 'n': + break; + + case '[': + if (f.argument_options == long_argument) { + f.argument_options = wchar_argument; + } else { + if (f.argument_options != normal_argument) { + f.conversion_char = 0xFF; + } + } + + c = *++s; + invert = 0; + + if (c == '^') { + invert = 1; + c = *++s; + } + + if (c == ']') { + set_char_map(f.char_set, ']'); + c = *++s; + } + + while (c && c != ']') { + int d; + set_char_map(f.char_set, c); + + if (*(s + 1) == '-' && (d = *(s + 2)) != 0 && d != ']') { + while (++c <= d) { + set_char_map(f.char_set, c); + } + + c = *(s += 3); + } else { + c = *++s; + } + } + + if (!c) { + f.conversion_char = 0xFF; + break; + } + + if (invert) { + int i; + u8* p; + + for (i = sizeof(f.char_set), p = f.char_set; i; --i, ++p) { + *p = ~*p; + } + + break; + } + + break; + default: + f.conversion_char = 0xFF; + break; + } + + *format = f; + return ((const char*)s + 1); +} + +static int __sformatter(int (*ReadProc)(void*, int, int), void* ReadProcArg, const char* format_str, va_list arg) +{ + int num_chars, chars_read, items_assigned, conversions; + int base, negative, overflow; + const char* format_ptr; + char format_char; + char c; + scan_format format; + s32 long_num; + u32 u_long_num; + s64 long_long_num; + u64 u_long_long_num; + f128 long_double_num; + char* arg_ptr; + int terminate = 0; + + format_ptr = format_str; + chars_read = 0; + items_assigned = 0; + conversions = 0; + + while (!terminate && (format_char = *format_ptr) != 0) { + if (isspace(format_char)) { + do { + format_char = *++format_ptr; + } while (isspace(format_char)); + + while (isspace(c = (*ReadProc)(ReadProcArg, 0, __GetAChar))) + ++chars_read; + + (*ReadProc)(ReadProcArg, c, __UngetAChar); + + continue; + } + + if (format_char != '%') { + if ((c = (*ReadProc)(ReadProcArg, 0, __GetAChar)) != (u8)format_char) { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + goto exit; + } + + chars_read++; + format_ptr++; + + continue; + } + + format_ptr = parse_format(format_ptr, &format); + + if (!format.suppress_assignment && format.conversion_char != '%') { + arg_ptr = va_arg(arg, char*); + } else { + arg_ptr = 0; + } + + if ((format.conversion_char != 'n') && (*ReadProc)(ReadProcArg, 0, __TestForError)) { + terminate = 1; + goto exit; + } + + switch (format.conversion_char) { + case 'd': + base = 10; + goto signed_int; + case 'i': + base = 0; + signed_int: + if ((format.argument_options == long_long_argument)) + u_long_long_num = __strtoull(base, format.field_width, ReadProc, ReadProcArg, &num_chars, &negative, &overflow); + else + u_long_num = __strtoul(base, format.field_width, ReadProc, ReadProcArg, &num_chars, &negative, &overflow); + + if (!num_chars) { + goto exit; + } + + chars_read += num_chars; + + if ((format.argument_options == long_long_argument)) + long_long_num = (negative ? -u_long_long_num : u_long_long_num); + else + long_num = (negative ? -u_long_num : u_long_num); + + signed_int_assign: + + if (arg_ptr) { + switch (format.argument_options) { + case normal_argument: + *(int*)arg_ptr = long_num; + break; + case char_argument: + *(s8*)arg_ptr = long_num; + break; + case short_argument: + *(s16*)arg_ptr = long_num; + break; + case long_argument: + *(s32*)arg_ptr = long_num; + break; + case long_long_argument: + *(s64*)arg_ptr = long_long_num; + break; + } + + items_assigned++; + } + + conversions++; + break; + case 'o': + base = 8; + goto unsigned_int; + case 'u': + base = 10; + goto unsigned_int; + case 'x': + case 'X': + base = 16; + unsigned_int: + if ((format.argument_options == long_long_argument)) + u_long_long_num = __strtoull(base, format.field_width, ReadProc, ReadProcArg, &num_chars, &negative, &overflow); + else + u_long_num = __strtoul(base, format.field_width, ReadProc, ReadProcArg, &num_chars, &negative, &overflow); + + if (!num_chars) { + goto exit; + } + + chars_read += num_chars; + + if (negative) { + if (format.argument_options == long_long_argument) + u_long_long_num = -u_long_long_num; + else + u_long_num = -u_long_num; + } + + unsigned_int_assign: + + if (arg_ptr) { + switch (format.argument_options) { + case normal_argument: + *(uint*)arg_ptr = u_long_num; + break; + case char_argument: + *(u8*)arg_ptr = u_long_num; + break; + case short_argument: + *(u16*)arg_ptr = u_long_num; + break; + case long_argument: + *(u32*)arg_ptr = u_long_num; + break; + case long_long_argument: + *(u64*)arg_ptr = u_long_long_num; + break; + } + + items_assigned++; + } + + conversions++; + break; + case 'a': + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + flt: + long_double_num = __strtold(format.field_width, ReadProc, ReadProcArg, &num_chars, &overflow); + + if (!num_chars) { + goto exit; + } + + chars_read += num_chars; + + assign_float: + + if (arg_ptr) { + switch (format.argument_options) { + case normal_argument: + *(f32*)arg_ptr = long_double_num; + break; + case double_argument: + *(f64*)arg_ptr = long_double_num; + break; + case long_double_argument: + *(f128*)arg_ptr = long_double_num; + break; + } + + items_assigned++; + } + + conversions++; + break; + + case 'c': + + if (!format.field_width_specified) + format.field_width = 1; + + if (arg_ptr) { + int rval; + num_chars = 0; + + while (format.field_width-- && ((rval = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != -1)) { + c = rval; + + if (format.argument_options == wchar_argument) { + mbtowc(((wchar_t*)arg_ptr), (char*)(&c), 1); + (wchar_t*)arg_ptr++; + } else { + *arg_ptr++ = c; + } + num_chars++; + } + + if (!num_chars) { + goto exit; + } + + chars_read += num_chars; + + items_assigned++; + } else { + num_chars = 0; + + while (format.field_width-- && ((c = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != -1)) { + num_chars++; + } + if (!num_chars) + goto exit; + } + + conversions++; + break; + case '%': + while (isspace(c = (*ReadProc)(ReadProcArg, 0, __GetAChar))) + chars_read++; + + if (c != '%') { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + goto exit; + } + + chars_read++; + break; + case 's': + c = (*ReadProc)(ReadProcArg, 0, __GetAChar); + while (isspace(c)) { + chars_read++; + c = (*ReadProc)(ReadProcArg, 0, __GetAChar); + } + + (*ReadProc)(ReadProcArg, c, __UngetAChar); + case '[': + if (arg_ptr) { + num_chars = 0; + + while (format.field_width-- && ((c = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != -1) + && tst_char_map(format.char_set, c)) { + if (format.argument_options == wchar_argument) { + mbtowc(((wchar_t*)arg_ptr), (char*)&c, 1); + arg_ptr = (char*)((wchar_t*)arg_ptr + 1); + } else { + *arg_ptr++ = c; + } + num_chars++; + } + + if (!num_chars) { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + goto exit; + } + + chars_read += num_chars; + + if (format.argument_options == wchar_argument) + *(wchar_t*)arg_ptr = L'\0'; + else + *arg_ptr = 0; + + items_assigned++; + } else { + num_chars = 0; + + while (format.field_width-- && ((c = ((*ReadProc)(ReadProcArg, 0, __GetAChar))) != -1) + && tst_char_map(format.char_set, c)) { + + num_chars++; + } + + if (!num_chars) { + (*ReadProc)(ReadProcArg, c, __UngetAChar); + break; + } + chars_read += num_chars; + } + + if (format.field_width >= 0) + (*ReadProc)(ReadProcArg, c, __UngetAChar); + + conversions++; + break; + case 'n': + if (arg_ptr) + switch (format.argument_options) { + case normal_argument: + *(int*)arg_ptr = chars_read; + break; + case short_argument: + *(s16*)arg_ptr = chars_read; + break; + case long_argument: + *(s32*)arg_ptr = chars_read; + break; + case char_argument: + *(char*)arg_ptr = chars_read; + break; + case long_long_argument: + *(s64*)arg_ptr = chars_read; + break; + } + continue; + case 0xFF: + default: + goto exit; + } + } + +exit: + + if ((*ReadProc)(ReadProcArg, 0, __TestForError) && conversions == 0) + return -1; + + return items_assigned; +} + +int __StringRead(void* pPtr, int ch, int act) +{ + char ret; + __InStrCtrl* Iscp = (__InStrCtrl*)pPtr; + + switch (act) { + case __GetAChar: + ret = *(Iscp->NextChar); + + if (ret == '\0') { + Iscp->NullCharDetected = 1; + return -1; + } else { + Iscp->NextChar++; + return (u8)ret; + } + + case __UngetAChar: + if (Iscp->NullCharDetected == 0) { + Iscp->NextChar--; + } else { + Iscp->NullCharDetected = 0; + } + + return ch; + + case __TestForError: + return Iscp->NullCharDetected; + } + + return 0; +} + +inline int isspace_string(const char* s) +{ + int i = 0; + + while (s[i] != '\0') { + if (!isspace(s[i++])) + return 0; + } + + return 1; +} + +inline int vsscanf(const char* s, const char* format, va_list arg) +{ + __InStrCtrl isc; + isc.NextChar = (char*)s; + + if ((s == 0) || (*isc.NextChar == '\0')) { + return -1; + } + + isc.NullCharDetected = 0; + return __sformatter(&__StringRead, (void*)&isc, format, arg); +} + +int sscanf(const char* s, const char* pFormat, ...) +{ + va_list args; + va_start(args, pFormat); + return vsscanf(s, pFormat, args); +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/string.c b/src/static/MSL_C.PPCEABI.bare.H/string.c new file mode 100644 index 00000000..68a14dff --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/string.c @@ -0,0 +1,269 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/string.h" +#define K1 0x80808080 +#define K2 0xFEFEFEFF + +size_t(strlen)(const char* str) +{ + size_t len = -1; + u8* p = (u8*)str - 1; + + do + len++; + while (*++p); + return (len); +} + +char*(strcpy)(char* dst, const char* src) +{ + register u8 *destb, *fromb; + register u32 w, t, align; + + fromb = (u8*)src; + destb = (u8*)dst; + + if ((align = ((int)fromb & 3)) != ((int)destb & 3)) { + goto bytecopy; + } + + if (align) { + if ((*destb = *fromb) == 0) + return (dst); + for (align = 3 - align; align; align--) { + if ((*(++destb) = *(++fromb)) == 0) + return (dst); + } + ++destb; + ++fromb; + } + + w = *((int*)(fromb)); + + t = w + K2; + + t &= K1; + if (t) + goto bytecopy; + --((int*)(destb)); + + do { + *(++((int*)(destb))) = w; + w = *(++((int*)(fromb))); + + t = w + K2; + t &= K1; + if (t) + goto adjust; + } while (1); + +adjust: + ++((int*)(destb)); +bytecopy: + if ((*destb = *fromb) == 0) + return dst; + do { + if ((*(++destb) = *(++fromb)) == 0) + return dst; + } while (1); + + return dst; +} + +char* strncpy(char* dst, const char* src, size_t n) +{ + const u8* p = (const u8*)src - 1; + u8* q = (u8*)dst - 1; + u8 zero = 0; + + n++; + + while (--n) + if (!(*++q = *++p)) { + while (--n) + *++q = 0; + break; + } + return (dst); +} + +char* strcat(char* dst, const char* src) +{ + const u8* p = (u8*)src - 1; + u8* q = (u8*)dst - 1; + + while (*++q) + ; + + q--; + + while (*++q = *++p) + ; + + return (dst); +} + +char* strncat(char* dst, const char* src, size_t n) +{ + const u8* p = (u8*)src - 1; + u8* q = (u8*)dst - 1; + + while (*++q) + ; + + q--; + n++; + + while (--n) + if (!(*++q = *++p)) { + q--; + break; + } + + *++q = 0; + + return (dst); +} + +int strcmp(const char* str1, const char* str2) +{ + // bless metrowerks for this implementation + + register u8* left = (u8*)str1; + register u8* right = (u8*)str2; + u32 align, l1, r1, x; + + l1 = *left; + r1 = *right; + if (l1 - r1) { + return (l1 - r1); + } + + if ((align = ((int)left & 3)) != ((int)right & 3)) { + goto bytecopy; + } + if (align) { + if (l1 == 0) { + return 0; + } + for (align = 3 - align; align; align--) { + l1 = *(++left); + r1 = *(++right); + if (l1 - r1) { + return (l1 - r1); + } + if (l1 == 0) { + return 0; + } + } + left++; + right++; + } + + l1 = *(int*)left; + r1 = *(int*)right; + x = l1 + K2; + if (x & K1) { + goto adjust; + } + while (l1 == r1) { + l1 = *(++((int*)(left))); + r1 = *(++((int*)(right))); + x = l1 + K2; + if (x & K1) { + goto adjust; + } + } + if (l1 > r1) + return 1; + return -1; + +adjust: + l1 = *left; + r1 = *right; + if (l1 - r1) { + return (l1 - r1); + } +bytecopy: + if (l1 == 0) { + return 0; + } + do { + l1 = *(++left); + r1 = *(++right); + if (l1 - r1) { + return (l1 - r1); + } + if (l1 == 0) { + return 0; + } + } while (1); +} + +int strncmp(const char* str1, const char* str2, size_t n) +{ + const u8* p1 = (u8*)str1 - 1; + const u8* p2 = (u8*)str2 - 1; + u32 c1, c2; + + n++; + + while (--n) + if ((c1 = *++p1) != (c2 = *++p2)) + return (c1 - c2); + else if (!c1) + break; + return 0; +} + +char* strchr(const char* str, int chr) +{ + const u8* p = (u8*)str - 1; + u32 c = (chr & 0xFF); + u32 ch; + + while (ch = *++p) + if (ch == c) + return ((char*)p); + + return (c ? 0 : (char*)p); +} + +char* strrchr(const char* str, int chr) +{ + const u8* p = (u8*)str - 1; + const u8* q = 0; + u32 c = (chr & 0xFF); + u32 ch; + + while (ch = *++p) + if (ch == c) + q = p; + + if (q) + return ((char*)q); + + return (c ? 0 : (char*)p); +} + +char* strstr(const char* str, const char* pat) +{ + const u8* s1 = (const u8*)str - 1; + const u8* p1 = (const u8*)pat - 1; + u32 firstc, c1, c2; + + if ((pat == 0) || (!(firstc = *++p1))) + return ((char*)str); + + while (c1 = *++s1) + if (c1 == firstc) { + const u8* s2 = s1 - 1; + const u8* p2 = p1 - 1; + + while ((c1 = *++s2) == (c2 = *++p2) && c1) + ; + + if (!c2) + return ((char*)s1); + } + + return (0); +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/strtoul.c b/src/static/MSL_C.PPCEABI.bare.H/strtoul.c new file mode 100644 index 00000000..f6e26737 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/strtoul.c @@ -0,0 +1,343 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/strtoul.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/stdio_api.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ctype_api.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/errno.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/limits.h" + +enum scan_states { + start = 0x01, + check_for_zero = 0x02, + leading_zero = 0x04, + need_digit = 0x08, + digit_loop = 0x10, + finished = 0x20, + failure = 0x40 +}; + +#define final_state(scan_state) (scan_state & (finished | failure)) +#define success(scan_state) (scan_state & (leading_zero | digit_loop | finished)) +#define fetch() (count++, (*ReadProc)(ReadProcArg, 0, __GetAChar)) +#define unfetch(c) (*ReadProc)(ReadProcArg, c, __UngetAChar) + +u64 __strtoull(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative, + int* overflow) +{ + int scan_state = start; + int count = 0; + int spaces = 0; + u64 value = 0; + u64 value_max = 0; + u64 ullmax = ULLONG_MAX; + int c; + + *negative = *overflow = 0; + + if (base < 0 || base == 1 || base > 36 || max_width < 1) { + scan_state = failure; + } else { + c = fetch(); + } + + if (base != 0) { + value_max = ULLONG_MAX / base; + } + + while (count <= max_width && c != -1 && !final_state(scan_state)) { + switch (scan_state) { + case start: + if (isspace(c)) { + c = fetch(); + count--; + spaces++; + break; + } + + if (c == '+') { + c = fetch(); + } else if (c == '-') { + c = fetch(); + *negative = 1; + } + + scan_state = check_for_zero; + break; + + case check_for_zero: + if (base == 0 || base == 16) { + if (c == '0') { + scan_state = leading_zero; + c = fetch(); + break; + } + } + + scan_state = need_digit; + break; + + case leading_zero: + if (c == 'X' || c == 'x') { + base = 16; + scan_state = need_digit; + c = fetch(); + break; + } + + if (base == 0) { + base = 8; + } + + scan_state = digit_loop; + break; + + case need_digit: + case digit_loop: + if (base == 0) { + base = 10; + } + + if (!value_max) { + value_max = ullmax / base; + } + + if (isdigit(c)) { + if ((c -= '0') >= base) { + if (scan_state == digit_loop) { + scan_state = finished; + } else { + scan_state = failure; + } + + c += '0'; + break; + } + } else if (!isalpha(c) || (toupper(c) - 'A' + 10) >= base) { + if (scan_state == digit_loop) { + scan_state = finished; + } else { + scan_state = failure; + } + + break; + } else { + c = toupper(c) - 'A' + 10; + } + + if (value > value_max) { + *overflow = 1; + } + + value *= base; + + if (c > (ullmax - value)) { + *overflow = 1; + } + + value += c; + scan_state = digit_loop; + c = fetch(); + break; + } + } + + if (!success(scan_state)) { + count = 0; + value = *chars_scanned = 0; + } else { + count--; + *chars_scanned = count + spaces; + } + + unfetch(c); + return value; +} + +u32 __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, int* chars_scanned, int* negative, + int* overflow) +{ + int scan_state = start; + int count = 0; + int spaces = 0; + u32 value = 0; + u32 value_max = 0; + int c; + + *negative = *overflow = 0; + + if (base < 0 || base == 1 || base > 36 || max_width < 1) { + scan_state = failure; + } else { + c = fetch(); + } + + if (base != 0) { + value_max = ULONG_MAX / base; + } + + while (count <= max_width && c != -1 && !final_state(scan_state)) { + switch (scan_state) { + case start: + if (isspace(c)) { + c = fetch(); + count--; + spaces++; + break; + } + + if (c == '+') { + c = fetch(); + } else if (c == '-') { + c = fetch(); + *negative = 1; + } + + scan_state = check_for_zero; + break; + + case check_for_zero: + if (base == 0 || base == 16) { + if (c == '0') { + scan_state = leading_zero; + c = fetch(); + break; + } + } + + scan_state = need_digit; + break; + + case 4: + if (c == 'X' || c == 'x') { + base = 16; + scan_state = need_digit; + c = fetch(); + break; + } + + if (base == 0) { + base = 8; + } + + scan_state = digit_loop; + break; + + case need_digit: + case digit_loop: + if (base == 0) { + base = 10; + } + + if (!value_max) { + value_max = ULONG_MAX / base; + } + + if (isdigit(c)) { + if ((c -= '0') >= base) { + if (scan_state == digit_loop) { + scan_state = finished; + } else { + scan_state = failure; + } + + c += '0'; + break; + } + } else if (!isalpha(c) || (toupper(c) - 'A' + 10) >= base) { + if (scan_state == digit_loop) { + scan_state = finished; + } else { + scan_state = failure; + } + + break; + } else { + c = toupper(c) - 'A' + 10; + } + + if (value > value_max) { + *overflow = 1; + } + + value *= base; + + if (c > (ULONG_MAX - value)) { + *overflow = 1; + } + + value += c; + scan_state = digit_loop; + c = fetch(); + break; + } + } + + if (!success(scan_state)) { + count = 0; + value = 0; + *chars_scanned = 0; + } else { + count--; + *chars_scanned = count + spaces; + } + + unfetch(c); + return value; +} + +/** + * @brief STRing TO Unsigned Long. Converts any numbers (of base `base`) at start of input string `str` to u32 and returns. + * Any remaining string part goes in `end`. + */ +u32 strtoul(const char* str, char** end, int base) +{ + u32 value; + int count, negative, overflow; + + __InStrCtrl isc; + isc.NextChar = (char*)str; + isc.NullCharDetected = 0; + + value = __strtoul(base, 0x7FFFFFFF, &__StringRead, (void*)&isc, &count, &negative, &overflow); + + if (end) { + *end = (char*)str + count; + } + + if (overflow) { + value = ULONG_MAX; + errno = ERANGE; + } else if (negative) { + value = -value; + } + + return value; +} + +/** + * @brief STRing TO Long. Converts any numbers (of base `base`) at start of input string `str` to s32 and returns. + * Any remaining string part goes in `end`. + */ +s32 strtol(const char* str, char** end, int base) +{ + u32 uvalue; + s32 svalue; + int count, negative, overflow; + + __InStrCtrl isc; + isc.NextChar = (char*)str; + isc.NullCharDetected = 0; + + uvalue = __strtoul(base, 0x7FFFFFFF, &__StringRead, (void*)&isc, &count, &negative, &overflow); + + if (end) { + *end = (char*)str + count; + } + + if (overflow || (!negative && uvalue > LONG_MAX) || (negative && uvalue > -LONG_MIN)) { + svalue = (negative ? -LONG_MIN : LONG_MAX); + errno = ERANGE; + } else { + svalue = (negative ? (s32)-uvalue : (s32)uvalue); + } + + return svalue; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/uart_console_io_gcn.c b/src/static/MSL_C.PPCEABI.bare.H/uart_console_io_gcn.c new file mode 100644 index 00000000..ff65bfcd --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/uart_console_io_gcn.c @@ -0,0 +1,42 @@ +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/ansi_files.h" + +typedef int UARTError; + +UARTError InitializeUART(u32 baudRate); +UARTError WriteUARTN(const void* buf, u32 len); +u32 OSGetConsoleType(void); +int __TRK_write_console(__file_handle handle, char* buffer, size_t* count, __ref_con ref_con); + +int __write_console(__file_handle handle, char* buffer, size_t* count, __ref_con ref_con) +{ + static int initialized; + + if ((OSGetConsoleType() & 0x20000000) == 0) { + UARTError err = 0; + + if (initialized == 0) { + err = InitializeUART(0xE100); + + if (err == 0) { + initialized = 1; + } + } + + if (err != 0) { + return 1; + } + + if (WriteUARTN(buffer, *count) != 0) { + *count = 0; + return 1; + } + } + + __TRK_write_console(handle, buffer, count, ref_con); + return 0; +} + +int __close_console(__file_handle handle) +{ + return 0; +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/w_acos.c b/src/static/MSL_C.PPCEABI.bare.H/w_acos.c new file mode 100644 index 00000000..2c4a532e --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/w_acos.c @@ -0,0 +1,38 @@ +/* @(#)w_acos.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * wrap_acos(x) + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +double acos(double x) /* wrapper acos */ +#else +double acos(x) /* wrapper acos */ +double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_acos(x); +#else + double z; + z = __ieee754_acos(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (fabs(x) > 1.0) { + return __kernel_standard(x, x, 1); /* acos(|x|>1) */ + } else + return z; +#endif +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/w_atan2.c b/src/static/MSL_C.PPCEABI.bare.H/w_atan2.c new file mode 100644 index 00000000..4081f97c --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/w_atan2.c @@ -0,0 +1,38 @@ +/* @(#)w_atan2.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * wrapper atan2(y,x) + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +double atan2(double y, double x) /* wrapper atan2 */ +#else +double atan2(y, x) /* wrapper atan2 */ +double y, x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_atan2(y, x); +#else + double z; + z = __ieee754_atan2(y, x); + if (_LIB_VERSION == _IEEE_ || isnan(x) || isnan(y)) + return z; + if (x == 0.0 && y == 0.0) { + return __kernel_standard(y, x, 3); /* atan2(+-0,+-0) */ + } else + return z; +#endif +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/w_pow.c b/src/static/MSL_C.PPCEABI.bare.H/w_pow.c new file mode 100644 index 00000000..50334629 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/w_pow.c @@ -0,0 +1,27 @@ +/* @(#)w_pow.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * wrapper pow(x,y) return x**y + */ + +#include "MSL_C/MSL_Common_Embedded/Math/fdlibm.h" + +#ifdef __STDC__ +double pow(double x, double y) /* wrapper pow */ +#else +double pow(x, y) /* wrapper pow */ +double x, y; +#endif +{ + return __ieee754_pow(x, y); +} diff --git a/src/static/MSL_C.PPCEABI.bare.H/wchar_io.c b/src/static/MSL_C.PPCEABI.bare.H/wchar_io.c new file mode 100644 index 00000000..77e0f010 --- /dev/null +++ b/src/static/MSL_C.PPCEABI.bare.H/wchar_io.c @@ -0,0 +1,30 @@ +#ifndef _MSL_WIDE_CHAR +#define _MSL_WIDE_CHAR +#endif + +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/wchar_io.h" + +int fwide(FILE* stream, int mode) +{ + int orientation; + + if (stream == nullptr || stream->mMode.file_kind == __closed_file) + return 0; + + orientation = stream->mMode.file_orientation; + switch (orientation) { + case __unoriented: + if (mode > 0) + stream->mMode.file_orientation = __wide_oriented; + else if (mode < 0) + stream->mMode.file_orientation = __char_oriented; + + return mode; + + case __wide_oriented: + return 1; + + case __char_oriented: + return -1; + } +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/CircleBuffer.c b/src/static/TRK_MINNOW_DOLPHIN/CircleBuffer.c new file mode 100644 index 00000000..3f295d68 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/CircleBuffer.c @@ -0,0 +1,83 @@ +#include "TRK/CircleBuffer.h" + +u32 CBGetBytesAvailableForRead(CircleBuffer* cb) +{ + return cb->mBytesToRead; +} + +u32 CBGetBytesAvailableForWrite(CircleBuffer* cb) +{ + return cb->mBytesToWrite; +} + +void CircleBufferInitialize(CircleBuffer* cb, u8* buf, u32 size) +{ + cb->mStartPtr = buf; + cb->mSize = size; + cb->mReadPtr = cb->mStartPtr; + cb->mWritePtr = cb->mStartPtr; + cb->mBytesToRead = 0; + cb->mBytesToWrite = cb->mSize; + MWInitializeCriticalSection(&cb->mSection); +} + +void CircleBufferTerminate(CircleBuffer* cb) +{ + // UNUSED FUNCTION +} + +int CircleBufferWriteBytes(CircleBuffer* cb, u8* buf, u32 size) +{ + int availSize; + + if (size > cb->mBytesToWrite) { + return -1; + } + MWEnterCriticalSection(&cb->mSection); + availSize = cb->mSize - (cb->mWritePtr - cb->mStartPtr); + if (availSize >= size) { + memcpy(cb->mWritePtr, buf, size); + cb->mWritePtr += size; + } else { + memcpy(cb->mWritePtr, buf, availSize); + memcpy(cb->mStartPtr, buf + availSize, size - availSize); + cb->mWritePtr = cb->mStartPtr + size - availSize; + } + + if (cb->mSize == (cb->mWritePtr - cb->mStartPtr)) { + cb->mWritePtr = cb->mStartPtr; + } + + cb->mBytesToWrite -= size; + cb->mBytesToRead += size; + MWExitCriticalSection(&cb->mSection); + return 0; +} + +int CircleBufferReadBytes(CircleBuffer* cb, u8* buf, u32 size) +{ + int availSize; + + if (size > cb->mBytesToRead) { + return -1; + } + MWEnterCriticalSection(&cb->mSection); + availSize = cb->mSize - (cb->mReadPtr - cb->mStartPtr); + if (size < availSize) { + memcpy(buf, cb->mReadPtr, size); + cb->mReadPtr += size; + } else { + memcpy(buf, cb->mReadPtr, availSize); + memcpy(buf + availSize, cb->mStartPtr, size - availSize); + cb->mReadPtr = cb->mStartPtr + size - availSize; + } + + if (cb->mSize == (cb->mReadPtr - cb->mStartPtr)) { + cb->mReadPtr = cb->mStartPtr; + } + + cb->mBytesToWrite += size; + cb->mBytesToRead -= size; + MWExitCriticalSection(&cb->mSection); + return 0; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/MWCriticalSection_gc.cpp b/src/static/TRK_MINNOW_DOLPHIN/MWCriticalSection_gc.cpp new file mode 100644 index 00000000..d62eafcb --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/MWCriticalSection_gc.cpp @@ -0,0 +1,25 @@ +#include "TRK/dstypes.h" + +extern "C" { +bool OSRestoreInterrupts(uint); +uint OSDisableInterrupts(); + +void MWInitializeCriticalSection(uint* section) +{ +} + +void MWEnterCriticalSection(uint* section) +{ + *section = OSDisableInterrupts(); +} + +void MWExitCriticalSection(uint* section) +{ + OSRestoreInterrupts(*section); +} + +void MWTerminateCriticalSection() +{ + // UNUSED FUNCTION +} +}; diff --git a/src/static/TRK_MINNOW_DOLPHIN/MWTrace.c b/src/static/TRK_MINNOW_DOLPHIN/MWTrace.c new file mode 100644 index 00000000..5d94c0be --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/MWTrace.c @@ -0,0 +1,6 @@ +#include "TRK/trk.h" + + +void MWTRACE(u8, char*, ...) +{ +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/UDP_Stubs.c b/src/static/TRK_MINNOW_DOLPHIN/UDP_Stubs.c new file mode 100644 index 00000000..89691331 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/UDP_Stubs.c @@ -0,0 +1,47 @@ +#include "TRK/dstypes.h" +#include + +WEAKFUNC int udp_cc_initialize(void* flagOut, __OSInterruptHandler handler) +{ + return -1; +} + +WEAKFUNC int udp_cc_shutdown(void) +{ + return -1; +} + +WEAKFUNC int udp_cc_open(void) +{ + return -1; +} + +WEAKFUNC int udp_cc_close(void) +{ + return -1; +} + +WEAKFUNC int udp_cc_read(u8* dest, int size) +{ + return 0; +} + +WEAKFUNC int udp_cc_write(const u8* src, int size) +{ + return 0; +} + +WEAKFUNC int udp_cc_peek(void) +{ + return 0; +} + +WEAKFUNC int udp_cc_pre_continue(void) +{ + return -1; +} + +WEAKFUNC int udp_cc_post_stop(void) +{ + return -1; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/__exception.s b/src/static/TRK_MINNOW_DOLPHIN/__exception.s new file mode 100644 index 00000000..10b50153 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/__exception.s @@ -0,0 +1,476 @@ +.include "macros.inc" + +.section .init, "ax" # 0x80003100 - 0x80005600 + +.global gTRKInterruptVectorTable +gTRKInterruptVectorTable: +.asciz "Metrowerks Target Resident Kernel for PowerPC" +.balign 4 +.fill 0xD0 + +############################################# +# Interrupt vector slot 0x0000 is reserved. # +############################################# + +# Slot 0x0100: System Reset Exception + b __TRK_reset +.fill 0xFC + +# Slot 0x0200: Machine Check Exception +/* 80003354 00000354 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003358 00000358 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 8000335C 0000035C 7C 00 17 AC */ icbi 0, r2 +/* 80003360 00000360 7C 53 02 A6 */ mfdar r2 +/* 80003364 00000364 7C 00 13 AC */ dcbi 0, r2 +/* 80003368 00000368 7C 51 42 A6 */ mfspr r2, 0x111 +/* 8000336C 0000036C 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003370 00000370 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003374 00000374 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003378 00000378 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 8000337C 0000037C 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003380 00000380 7C 60 00 A6 */ mfmsr r3 +/* 80003384 00000384 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003388 00000388 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 8000338C 0000038C 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003390 00000390 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003394 00000394 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003398 00000398 38 60 02 00 */ li r3, 0x200 +/* 8000339C 0000039C 4C 00 00 64 */ rfi +.fill 0xB4 + +# Slot 0x0300: DSI Exception +/* 80003454 00000454 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003458 00000458 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000345C 0000045C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003460 00000460 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003464 00000464 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003468 00000468 7C 60 00 A6 */ mfmsr r3 +/* 8000346C 0000046C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003470 00000470 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003474 00000474 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003478 00000478 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000347C 0000047C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003480 00000480 38 60 03 00 */ li r3, 0x300 +/* 80003484 00000484 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0400: ISI Exception +/* 80003554 00000554 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003558 00000558 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000355C 0000055C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003560 00000560 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003564 00000564 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003568 00000568 7C 60 00 A6 */ mfmsr r3 +/* 8000356C 0000056C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003570 00000570 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003574 00000574 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003578 00000578 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000357C 0000057C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003580 00000580 38 60 04 00 */ li r3, 0x400 +/* 80003584 00000584 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0500: External Interrupt Exception +/* 80003654 00000654 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003658 00000658 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000365C 0000065C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003660 00000660 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003664 00000664 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003668 00000668 7C 60 00 A6 */ mfmsr r3 +/* 8000366C 0000066C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003670 00000670 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003674 00000674 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003678 00000678 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000367C 0000067C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003680 00000680 38 60 05 00 */ li r3, 0x500 +/* 80003684 00000684 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0600: Alignment Exception +/* 80003754 00000754 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003758 00000758 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000375C 0000075C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003760 00000760 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003764 00000764 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003768 00000768 7C 60 00 A6 */ mfmsr r3 +/* 8000376C 0000076C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003770 00000770 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003774 00000774 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003778 00000778 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000377C 0000077C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003780 00000780 38 60 06 00 */ li r3, 0x600 +/* 80003784 00000784 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0700: Program Exception +/* 80003854 00000854 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003858 00000858 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000385C 0000085C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003860 00000860 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003864 00000864 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003868 00000868 7C 60 00 A6 */ mfmsr r3 +/* 8000386C 0000086C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003870 00000870 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003874 00000874 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003878 00000878 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000387C 0000087C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003880 00000880 38 60 07 00 */ li r3, 0x700 +/* 80003884 00000884 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0800: Floating Point Unavailable Exception +/* 80003954 00000954 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003958 00000958 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000395C 0000095C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003960 00000960 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003964 00000964 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003968 00000968 7C 60 00 A6 */ mfmsr r3 +/* 8000396C 0000096C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003970 00000970 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003974 00000974 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003978 00000978 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000397C 0000097C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003980 00000980 38 60 08 00 */ li r3, 0x800 +/* 80003984 00000984 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0900: Decrementer Exception +/* 80003A54 00000A54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003A58 00000A58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003A5C 00000A5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003A60 00000A60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003A64 00000A64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003A68 00000A68 7C 60 00 A6 */ mfmsr r3 +/* 80003A6C 00000A6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003A70 00000A70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003A74 00000A74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003A78 00000A78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003A7C 00000A7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003A80 00000A80 38 60 09 00 */ li r3, 0x900 +/* 80003A84 00000A84 4C 00 00 64 */ rfi +.fill 0xCC + +###################################################### +# Interrupt vector slots 0x0A00 & 0x0B00 are reserved. +.fill 0x100 +.fill 0x100 +###################################################### + +# Slot 0x0C00: System Call Exception +/* 80003D54 00000D54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003D58 00000D58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003D5C 00000D5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003D60 00000D60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003D64 00000D64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003D68 00000D68 7C 60 00 A6 */ mfmsr r3 +/* 80003D6C 00000D6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003D70 00000D70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003D74 00000D74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003D78 00000D78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003D7C 00000D7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003D80 00000D80 38 60 0C 00 */ li r3, 0xc00 +/* 80003D84 00000D84 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0D00: Trace Exception +/* 80003E54 00000E54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003E58 00000E58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003E5C 00000E5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003E60 00000E60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003E64 00000E64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003E68 00000E68 7C 60 00 A6 */ mfmsr r3 +/* 80003E6C 00000E6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003E70 00000E70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003E74 00000E74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003E78 00000E78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003E7C 00000E7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003E80 00000E80 38 60 0D 00 */ li r3, 0xd00 +/* 80003E84 00000E84 4C 00 00 64 */ rfi +.fill 0xCC + +############################################################################ +# Slot 0x0E00 is usually for the Floating Point Assist Exception Handler, # +# however that exception is not implemented in the PPC 750CL architecture. # +############################################################################ + +# Slot 0x0F00: Performance Monitor Exception +/* 80003F54 00000F54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003F58 00000F58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003F5C 00000F5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003F60 00000F60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003F64 00000F64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003F68 00000F68 7C 60 00 A6 */ mfmsr r3 +/* 80003F6C 00000F6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003F70 00000F70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003F74 00000F74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003F78 00000F78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003F7C 00000F7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003F80 00000F80 38 60 0E 00 */ li r3, 0xe00 +/* 80003F84 00000F84 4C 00 00 64 */ rfi +.fill 0xCC + +################################################################################## +# Interrupt vector slots 0x1000 through 0x1200 are not implemented in the 750CL. # +################################################################################## + +# Slot 0x1300: Instruction Address Breakpoint Exception +/* 80004054 00001054 48 00 00 54 */ b .L_800040A8 +.fill 0x1C +/* 80004074 00001074 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004078 00001078 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000407C 0000107C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004080 00001080 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004084 00001084 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004088 00001088 7C 60 00 A6 */ mfmsr r3 +/* 8000408C 0000108C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004090 00001090 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004094 00001094 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004098 00001098 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000409C 0000109C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800040A0 000010A0 38 60 0F 20 */ li r3, 0xf20 +/* 800040A4 000010A4 4C 00 00 64 */ rfi +.L_800040A8: +/* 800040A8 000010A8 7C 51 43 A6 */ mtspr 0x111, r2 +/* 800040AC 000010AC 7C 72 43 A6 */ mtspr 0x112, r3 +/* 800040B0 000010B0 7C 93 43 A6 */ mtspr 0x113, r4 +/* 800040B4 000010B4 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 800040B8 000010B8 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 800040BC 000010BC 7C 60 00 A6 */ mfmsr r3 +/* 800040C0 000010C0 60 63 00 30 */ ori r3, r3, 0x30 +/* 800040C4 000010C4 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 800040C8 000010C8 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 800040CC 000010CC 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 800040D0 000010D0 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800040D4 000010D4 38 60 0F 00 */ li r3, 0xf00 +/* 800040D8 000010D8 4C 00 00 64 */ rfi +.fill 0x78 + +# Slot 0x1400: System Management Interrupt Exception +/* 80004154 00001154 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004158 00001158 7C 40 00 26 */ mfcr r2 +/* 8000415C 0000115C 7C 52 43 A6 */ mtspr 0x112, r2 +/* 80004160 00001160 7C 40 00 A6 */ mfmsr r2 +/* 80004164 00001164 74 42 00 02 */ andis. r2, r2, 2 +/* 80004168 00001168 41 82 00 1C */ beq .L_80004184 +/* 8000416C 0000116C 7C 40 00 A6 */ mfmsr r2 +/* 80004170 00001170 6C 42 00 02 */ xoris r2, r2, 2 +/* 80004174 00001174 7C 00 04 AC */ sync 0 +/* 80004178 00001178 7C 40 01 24 */ mtmsr r2 +/* 8000417C 0000117C 7C 00 04 AC */ sync 0 +/* 80004180 00001180 7C 51 43 A6 */ mtspr 0x111, r2 +.L_80004184: +/* 80004184 00001184 7C 52 42 A6 */ mfspr r2, 0x112 +/* 80004188 00001188 7C 4F F1 20 */ mtcrf 0xff, r2 +/* 8000418C 0000118C 7C 51 42 A6 */ mfspr r2, 0x111 +/* 80004190 00001190 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004194 00001194 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004198 00001198 7C 93 43 A6 */ mtspr 0x113, r4 +/* 8000419C 0000119C 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 800041A0 000011A0 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 800041A4 000011A4 7C 60 00 A6 */ mfmsr r3 +/* 800041A8 000011A8 60 63 00 30 */ ori r3, r3, 0x30 +/* 800041AC 000011AC 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 800041B0 000011B0 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 800041B4 000011B4 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 800041B8 000011B8 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800041BC 000011BC 38 60 10 00 */ li r3, 0x1000 +/* 800041C0 000011C0 4C 00 00 64 */ rfi +.fill 0x90 + + +############################################################################## +# Interrupt vector slots 0x1500 and 0x1600 are not implemented in the 750CL. # +############################################################################## + +# Slot 0x1700: Thermal-Management Interrupt Exception +/* 80004254 00001254 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004258 00001258 7C 40 00 26 */ mfcr r2 +/* 8000425C 0000125C 7C 52 43 A6 */ mtspr 0x112, r2 +/* 80004260 00001260 7C 40 00 A6 */ mfmsr r2 +/* 80004264 00001264 74 42 00 02 */ andis. r2, r2, 2 +/* 80004268 00001268 41 82 00 1C */ beq .L_80004284 +/* 8000426C 0000126C 7C 40 00 A6 */ mfmsr r2 +/* 80004270 00001270 6C 42 00 02 */ xoris r2, r2, 2 +/* 80004274 00001274 7C 00 04 AC */ sync 0 +/* 80004278 00001278 7C 40 01 24 */ mtmsr r2 +/* 8000427C 0000127C 7C 00 04 AC */ sync 0 +/* 80004280 00001280 7C 51 43 A6 */ mtspr 0x111, r2 +.L_80004284: +/* 80004284 00001284 7C 52 42 A6 */ mfspr r2, 0x112 +/* 80004288 00001288 7C 4F F1 20 */ mtcrf 0xff, r2 +/* 8000428C 0000128C 7C 51 42 A6 */ mfspr r2, 0x111 +/* 80004290 00001290 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004294 00001294 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004298 00001298 7C 93 43 A6 */ mtspr 0x113, r4 +/* 8000429C 0000129C 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 800042A0 000012A0 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 800042A4 000012A4 7C 60 00 A6 */ mfmsr r3 +/* 800042A8 000012A8 60 63 00 30 */ ori r3, r3, 0x30 +/* 800042AC 000012AC 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 800042B0 000012B0 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 800042B4 000012B4 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 800042B8 000012B8 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800042BC 000012BC 38 60 11 00 */ li r3, 0x1100 +/* 800042C0 000012C0 4C 00 00 64 */ rfi +.fill 0x90 + +# Slot 0x1800(?) +/* 80004354 00001354 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004358 00001358 7C 40 00 26 */ mfcr r2 +/* 8000435C 0000135C 7C 52 43 A6 */ mtspr 0x112, r2 +/* 80004360 00001360 7C 40 00 A6 */ mfmsr r2 +/* 80004364 00001364 74 42 00 02 */ andis. r2, r2, 2 +/* 80004368 00001368 41 82 00 1C */ beq .L_80004384 +/* 8000436C 0000136C 7C 40 00 A6 */ mfmsr r2 +/* 80004370 00001370 6C 42 00 02 */ xoris r2, r2, 2 +/* 80004374 00001374 7C 00 04 AC */ sync 0 +/* 80004378 00001378 7C 40 01 24 */ mtmsr r2 +/* 8000437C 0000137C 7C 00 04 AC */ sync 0 +/* 80004380 00001380 7C 51 43 A6 */ mtspr 0x111, r2 +.L_80004384: +/* 80004384 00001384 7C 52 42 A6 */ mfspr r2, 0x112 +/* 80004388 00001388 7C 4F F1 20 */ mtcrf 0xff, r2 +/* 8000438C 0000138C 7C 51 42 A6 */ mfspr r2, 0x111 +/* 80004390 00001390 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004394 00001394 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004398 00001398 7C 93 43 A6 */ mtspr 0x113, r4 +/* 8000439C 0000139C 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 800043A0 000013A0 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 800043A4 000013A4 7C 60 00 A6 */ mfmsr r3 +/* 800043A8 000013A8 60 63 00 30 */ ori r3, r3, 0x30 +/* 800043AC 000013AC 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 800043B0 000013B0 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 800043B4 000013B4 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 800043B8 000013B8 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800043BC 000013BC 38 60 12 00 */ li r3, 0x1200 +/* 800043C0 000013C0 4C 00 00 64 */ rfi +.fill 0x90 + +# Slot 0x1900(?) +/* 80004454 00001454 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004458 00001458 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000445C 0000145C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004460 00001460 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004464 00001464 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004468 00001468 7C 60 00 A6 */ mfmsr r3 +/* 8000446C 0000146C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004470 00001470 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004474 00001474 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004478 00001478 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000447C 0000147C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004480 00001480 38 60 13 00 */ li r3, 0x1300 +/* 80004484 00001484 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x1A00(?) +/* 80004554 00001554 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004558 00001558 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000455C 0000155C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004560 00001560 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004564 00001564 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004568 00001568 7C 60 00 A6 */ mfmsr r3 +/* 8000456C 0000156C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004570 00001570 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004574 00001574 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004578 00001578 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000457C 0000157C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004580 00001580 38 60 14 00 */ li r3, 0x1400 +/* 80004584 00001584 4C 00 00 64 */ rfi +.fill 0x1CC + +# Slot 0x1B00(?) +/* 80004754 00001754 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004758 00001758 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000475C 0000175C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004760 00001760 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004764 00001764 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004768 00001768 7C 60 00 A6 */ mfmsr r3 +/* 8000476C 0000176C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004770 00001770 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004774 00001774 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004778 00001778 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000477C 0000177C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004780 00001780 38 60 16 00 */ li r3, 0x1600 +/* 80004784 00001784 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x1C00(?) +/* 80004854 00001854 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004858 00001858 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000485C 0000185C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004860 00001860 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004864 00001864 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004868 00001868 7C 60 00 A6 */ mfmsr r3 +/* 8000486C 0000186C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004870 00001870 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004874 00001874 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004878 00001878 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000487C 0000187C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004880 00001880 38 60 17 00 */ li r3, 0x1700 +/* 80004884 00001884 4C 00 00 64 */ rfi +.fill 0x4CC + +# Slot 0x1D00(?) +/* 80004D54 00001D54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004D58 00001D58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004D5C 00001D5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004D60 00001D60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004D64 00001D64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004D68 00001D68 7C 60 00 A6 */ mfmsr r3 +/* 80004D6C 00001D6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004D70 00001D70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004D74 00001D74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004D78 00001D78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80004D7C 00001D7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004D80 00001D80 38 60 1C 00 */ li r3, 0x1c00 +/* 80004D84 00001D84 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x1E00(?) +/* 80004E54 00001E54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004E58 00001E58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004E5C 00001E5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004E60 00001E60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004E64 00001E64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004E68 00001E68 7C 60 00 A6 */ mfmsr r3 +/* 80004E6C 00001E6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004E70 00001E70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004E74 00001E74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004E78 00001E78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80004E7C 00001E7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004E80 00001E80 38 60 1D 00 */ li r3, 0x1d00 +/* 80004E84 00001E84 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x1F00(?) +/* 80004F54 00001F54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004F58 00001F58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004F5C 00001F5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004F60 00001F60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004F64 00001F64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004F68 00001F68 7C 60 00 A6 */ mfmsr r3 +/* 80004F6C 00001F6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004F70 00001F70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004F74 00001F74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004F78 00001F78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80004F7C 00001F7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004F80 00001F80 38 60 1E 00 */ li r3, 0x1e00 +/* 80004F84 00001F84 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x2000(?) +/* 80005054 00002054 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80005058 00002058 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000505C 0000205C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80005060 00002060 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80005064 00002064 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80005068 00002068 7C 60 00 A6 */ mfmsr r3 +/* 8000506C 0000206C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80005070 00002070 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80005074 00002074 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80005078 00002078 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000507C 0000207C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80005080 00002080 38 60 1F 00 */ li r3, 0x1f00 +/* 80005084 00002084 4C 00 00 64 */ rfi +.global gTRKInterruptVectorTableEnd +gTRKInterruptVectorTableEnd: diff --git a/src/static/TRK_MINNOW_DOLPHIN/dispatch.c b/src/static/TRK_MINNOW_DOLPHIN/dispatch.c new file mode 100644 index 00000000..bf721317 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/dispatch.c @@ -0,0 +1,61 @@ +#include "TRK/trk.h" + +DSError TRKInitializeDispatcher(void) +{ + return DS_NoError; +} + +DSError TRKDispatchMessage(MessageBuffer* msg) +{ + u32 err; + + err = DS_DispatchError; + TRKSetBufferPosition(msg, 0); + MWTRACE(1, "Dispatch command 0x%08x\n", msg->data[4]); + switch (msg->data[4]) { + case DSMSG_Connect: + err = TRKDoConnect(msg); + break; + case DSMSG_Disconnect: + err = TRKDoDisconnect(msg); + break; + case DSMSG_Reset: + err = TRKDoReset(msg); + break; + case DSMSG_Override: + err = TRKDoOverride(msg); + break; + case DSMSG_Versions: + err = TRKDoVersions(msg); + break; + case DSMSG_SupportMask: + err = TRKDoSupportMask(msg); + break; + case DSMSG_ReadMemory: + err = TRKDoReadMemory(msg); + break; + case DSMSG_WriteMemory: + err = TRKDoWriteMemory(msg); + break; + case DSMSG_ReadRegisters: + err = TRKDoReadRegisters(msg); + break; + case DSMSG_WriteRegisters: + err = TRKDoWriteRegisters(msg); + break; + case DSMSG_Continue: + err = TRKDoContinue(msg); + break; + case DSMSG_Step: + err = TRKDoStep(msg); + break; + case DSMSG_Stop: + err = TRKDoStop(msg); + break; + case DSMSG_SetOption: + err = TRKDoSetOption(msg); + break; + } + MWTRACE(1, "Dispatch complete err = %ld\n", err); + return err; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c b/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c new file mode 100644 index 00000000..196b7fa9 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c @@ -0,0 +1,343 @@ +#include "TRK/trk.h" + +extern u32 ARGetDMAStatus(void); +extern void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length); +extern u16 __ARGetInterruptStatus(void); +extern void __ARClearInterrupt(void); + +#define OSRoundUp32B(x) (((u32)(x) + 0x1F) & ~(0x1F)) + +extern u8 _db_stack_addr[]; +#define EXCEPTIONMASK_ADDR 0x80000044 + +extern void OSResetSystem(BOOL reset, u32 resetCode, BOOL forceMenu); + +static u32 lc_base; + +static u32 TRK_ISR_OFFSETS[15] = { PPC_SystemReset, + PPC_MachineCheck, + PPC_DataStorage, + PPC_InstructionStorage, + PPC_ExternalInterrupt, + PPC_Alignment, + PPC_Program, + PPC_FloatingPointUnavailable, + PPC_Decrementer, + PPC_SystemCall, + PPC_Trace, + PPC_PerformanceMonitor, + PPC_InstructionAddressBreakpoint, + PPC_SystemManagementInterrupt, + PPC_ThermalManagementInterrupt }; + +DECL_SECT(".init") void __TRK_reset() +{ + OSResetSystem(FALSE, 0, FALSE); +} + +void EnableMetroTRKInterrupts(void) +{ + EnableEXI2Interrupts(); +} + +u32 TRKTargetTranslate(u32 val) +{ + if (val >= lc_base && val < lc_base + 0x4000) { + if (((u32*)(&gTRKCPUState.Extended1))[36] & 3) + return val; + } + + if (val >= 0x7E000000 && val <= 0x80000000) { + return val; + } + + return (val & 0x3FFFFFFF) | 0x80000000; +} + +void TRK_copy_vector(u32 offset) +{ + void* destPtr = (void*)TRKTargetTranslate(offset); + TRK_memcpy(destPtr, (void*)(gTRKInterruptVectorTable + offset), 0x100); + TRK_flush_cache(destPtr, 0x100); +} + +void __TRK_copy_vectors(void) +{ + u32 r3 = lc_base; + u32* isrOffsetPtr; + int i; + u32 r29; + + if (r3 <= 0x44 && r3 + 0x4000 > 0x44 && gTRKCPUState.Extended1.DBAT3U_ & 3) { + r3 = 0x44; + } else { + r3 = EXCEPTIONMASK_ADDR; + } + + i = 0; + r29 = *(u32*)r3; + isrOffsetPtr = TRK_ISR_OFFSETS; + + do { + if ((r29 & (1 << i)) && i != 4) { + TRK_copy_vector(isrOffsetPtr[i]); + } + + i++; + } while (i <= 14); +} + +DSError TRKInitializeTarget() +{ + gTRKState.isStopped = TRUE; + gTRKState.msr = __TRK_get_MSR(); + lc_base = 0xE0000000; + return DS_NoError; +} + +#define __dcbi(a, b) asm { dcbi a, b } +#define __dcbfASM(a, b) asm { dcbf a, b } + +void TRK__read_aram(register int c, register u32 p2, void* p3) +{ + u32 err; + int i; + register int counter; + u16 r; + u32 g; + u32 x; + u32 size; + + if ((size_t)p2 < 0x4000 || p2 + *(u32*)p3 > 0x8000000) { + return; + } + + x = p2 & ~0x1F; + size = *(u32*)p3 + (p2 & 0x1F); + size = OSRoundUp32B(size); + counter = 0; + + for (i = 0; i < size; i += 0x20) { + __dcbi(counter, c); + counter += 0x20; + } + + do { + err = ARGetDMAStatus(); + } while (err); + + r = __ARGetInterruptStatus(); + g = 0x8000000; + __ARClearInterrupt(); + + ARStartDMA(1, c, x, size); + + while (!__ARGetInterruptStatus()) { } + + if (!r) { + __ARClearInterrupt(); + } +} + +void __read_aram_1block(void) +{ + // UNUSED FUNCTION +} + +void TRK__write_aram(register int c, register u32 p2, void* p3) +{ + u8 buff[32] ATTRIBUTE_ALIGN(32); + u32 err; + register int count = c; + register u32 bf; + u32 uVar1; + u32 size; + u16 r; + register u32 g; + register int counter; + u32 i; + + if ((size_t)p2 < 0x4000 || p2 + *(u32*)p3 > 0x8000000) { + return; + } + + uVar1 = p2 & ~0x1f; + counter = 0; + size = *(u32*)p3 + (p2 & 0x1f); + size = OSRoundUp32B(size); + + for (i = 0; i < size; i += 0x20) { + __dcbf((void*)counter, count); + counter += 0x20; + } + + do { + err = ARGetDMAStatus(); + } while (err); + + r = __ARGetInterruptStatus(); + g = 0x8000000; + + counter = p2 & 0x1f; + if (counter) { + g = uVar1; + bf = (u32)buff; + __dcbi(r0, bf); + __ARClearInterrupt(); + + ARStartDMA(1, bf, uVar1, 0x20); + + while (!__ARGetInterruptStatus()) { } + + TRK_memcpy((void*)c, buff, counter); + __dcbfASM(r0, c); + } + + p2 += *(u32*)p3; + counter = p2 & 0x1f; + if (counter) { + u32 val = p2 & ~0x1F; + if (val != g) { + bf = (u32)buff; + __dcbi(r0, bf); + __ARClearInterrupt(); + ARStartDMA(1, bf, val, 0x20); + + while (!__ARGetInterruptStatus()) { } + } + g = c + p2; + TRK_memcpy((void*)g, (void*)(buff + counter), 0x20 - counter); + + __dcbfASM(r0, g); + } + __sync(); + __ARClearInterrupt(); + ARStartDMA(0, c, uVar1, size); + if (!r) { + while (!__ARGetInterruptStatus()) { } + + __ARClearInterrupt(); + } +} + +ASM void InitMetroTRK(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + addi r1, r1, -4 + stw r3, 0(r1) + lis r3, gTRKCPUState@h + ori r3, r3, gTRKCPUState@l + stmw r0, ProcessorState_PPC.Default.GPR(r3) //Save the gprs + lwz r4, 0(r1) + addi r1, r1, 4 + stw r1, ProcessorState_PPC.Default.GPR[1](r3) + stw r4, ProcessorState_PPC.Default.GPR[3](r3) + mflr r4 + stw r4, ProcessorState_PPC.Default.LR(r3) + stw r4, ProcessorState_PPC.Default.PC(r3) + mfcr r4 + stw r4, ProcessorState_PPC.Default.CR(r3) + //??? + mfmsr r4 + ori r3, r4, (1 << (31 - 16)) + xori r3, r3, (1 << (31 - 16)) + mtmsr r3 + mtsrr1 r4 //Copy msr to srr1 + //Save misc registers to gTRKCPUState + bl TRKSaveExtended1Block + lis r3, gTRKCPUState@h + ori r3, r3, gTRKCPUState@l + lmw r0, ProcessorState_PPC.Default.GPR(r3) //Restore the gprs + //Reset IABR and DABR + li r0, 0 + mtspr 0x3f2, r0 + mtspr 0x3f5, r0 + //Restore stack pointer + lis r1, _db_stack_addr@h + ori r1, r1, _db_stack_addr@l + mr r3, r5 + bl InitMetroTRKCommTable //Initialize comm table + /* + If InitMetroTRKCommTable returned 1 (failure), an invalid hardware + id or the id for GDEV was somehow passed. Since only BBA or NDEV + are supported, we return early. Otherwise, we proceed with + starting up TRK. + */ + cmpwi r3, 1 + bne initCommTableSuccess + /* + BUG: The code probably originally reloaded gTRKCPUState here, but + as is it will read the returned value of InitMetroTRKCommTable + as a TRKCPUState struct pointer, causing the CPU to return to + a garbage code address. + */ + lwz r4, ProcessorState_PPC.Default.LR(r3) + mtlr r4 + lmw r0, ProcessorState_PPC.Default.GPR(r3) //Restore the gprs + blr +initCommTableSuccess: + b TRK_main //Jump to TRK_main + blr +#endif // clang-format on +} + +ASM void InitMetroTRK_BBA(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + addi r1, r1, -4 + stw r3, 0(r1) + lis r3, gTRKCPUState@h + ori r3, r3, gTRKCPUState@l + stmw r0, ProcessorState_PPC.Default.GPR(r3) //Save the gprs + lwz r4, 0(r1) + addi r1, r1, 4 + stw r1, ProcessorState_PPC.Default.GPR[1](r3) + stw r4, ProcessorState_PPC.Default.GPR[3](r3) + mflr r4 + stw r4, ProcessorState_PPC.Default.LR(r3) + stw r4, ProcessorState_PPC.Default.PC(r3) + mfcr r4 + stw r4, ProcessorState_PPC.Default.CR(r3) + //Turn on external interrupts + mfmsr r4 + ori r3, r4, (1 << (31 - 16)) + mtmsr r3 + mtsrr1 r4 //Copy original msr to srr1 + //Save misc registers to gTRKCPUState + bl TRKSaveExtended1Block + lis r3, gTRKCPUState@h + ori r3, r3, gTRKCPUState@l + lmw r0, ProcessorState_PPC.Default.GPR(r3) //Restore the gprs + //Reset IABR and DABR + li r0, 0 + mtspr 0x3f2, r0 + mtspr 0x3f5, r0 + //Restore the stack pointer + lis r1, _db_stack_addr@h + ori r1, r1, _db_stack_addr@l + li r3, 2 + bl InitMetroTRKCommTable //Initialize comm table as BBA hardware + /* + If InitMetroTRKCommTable returned 1 (failure), something went wrong + or whatever reason. If everything goes as expected, we proceed with + starting up TRK. + */ + cmpwi r3, 1 + bne initCommTableSuccess + /* + BUG: The code probably originally reloaded gTRKCPUState here, but + as is it will read the returned value of InitMetroTRKCommTable + as a TRKCPUState struct pointer, causing the CPU to return to + a garbage code address. + */ + lwz r4, ProcessorState_PPC.Default.LR(r3) + mtlr r4 + lmw r0, ProcessorState_PPC.Default.GPR(r3) + blr +initCommTableSuccess: + b TRK_main //Jump to TRK_main + blr +#endif // clang-format on +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c b/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c new file mode 100644 index 00000000..5915c515 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c @@ -0,0 +1,204 @@ +#include "TRK/trk.h" +#include "TRK/AmcExi2Stubs.h" + +extern void OSReport(const char* msg, ...); +extern s32 OSEnableScheduler(void); +extern void DCFlushRange(void* addr, u32 nBytes); +extern void ICInvalidateRange(void* addr, u32 nBytes); +extern void PPCHalt(void); + +BOOL _MetroTRK_Has_Framing; // UNUSED +// GPVE01 _MetroTRK_Has_Framing = .bss:0x804F4814; // type:object size:0x4 scope:global align:4 +// GPVE01_D17 _MetroTRK_Has_Framing = .bss:0x804F4754; // type:object size:0x4 scope:global align:4 +u8 TRK_Use_BBA; + +DBCommTable gDBCommTable = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + +void TRKEXICallBack(s16 r3, OSContext* ctx) +{ + OSEnableScheduler(); + TRKLoadContext(ctx, 0x500); +} + +int InitMetroTRKCommTable(int hwId) +{ + int result = 1; + OSReport("Devkit set to : %ld\n", hwId); + TRK_Use_BBA = 0; + + if (hwId == HARDWARE_BBA) { // BBA hardware + OSReport("MetroTRK : Set to BBA\n"); + // Initialize gDBCommTable + TRK_Use_BBA = 1; + gDBCommTable.initialize_func = udp_cc_initialize; + gDBCommTable.open_func = udp_cc_open; + gDBCommTable.close_func = udp_cc_close; + gDBCommTable.read_func = udp_cc_read; + gDBCommTable.write_func = udp_cc_write; + gDBCommTable.shutdown_func = udp_cc_shutdown; + gDBCommTable.peek_func = udp_cc_peek; + gDBCommTable.pre_continue_func = udp_cc_pre_continue; + gDBCommTable.post_stop_func = udp_cc_post_stop; + gDBCommTable.init_interrupts_func = nullptr; + return 0; + } + + if (hwId == HARDWARE_GDEV) { // NDEV hardware + OSReport("MetroTRK : Set to GDEV hardware\n"); + // Initialize gDBCommTable + result = Hu_IsStub(); + gDBCommTable.initialize_func = gdev_cc_initialize; + gDBCommTable.open_func = gdev_cc_open; + gDBCommTable.close_func = gdev_cc_close; + gDBCommTable.read_func = gdev_cc_read; + gDBCommTable.write_func = gdev_cc_write; + gDBCommTable.shutdown_func = gdev_cc_shutdown; + gDBCommTable.peek_func = gdev_cc_peek; + gDBCommTable.pre_continue_func = gdev_cc_pre_continue; + gDBCommTable.post_stop_func = gdev_cc_post_stop; + gDBCommTable.init_interrupts_func = gdev_cc_initinterrupts; + + } else if (hwId == HARDWARE_AMC_DDH) { + OSReport("MetroTRK : Set to AMC DDH hardware\n"); + result = AMC_IsStub(); + // Initialize gDBCommTable + gDBCommTable.initialize_func = ddh_cc_initialize; + gDBCommTable.open_func = ddh_cc_open; + gDBCommTable.close_func = ddh_cc_close; + gDBCommTable.read_func = ddh_cc_read; + gDBCommTable.write_func = ddh_cc_write; + gDBCommTable.shutdown_func = ddh_cc_shutdown; + gDBCommTable.peek_func = ddh_cc_peek; + gDBCommTable.pre_continue_func = ddh_cc_pre_continue; + gDBCommTable.post_stop_func = ddh_cc_post_stop; + gDBCommTable.init_interrupts_func = ddh_cc_initinterrupts; + + } else { // unknown hardware + OSReport("MetroTRK : Set to UNKNOWN hardware. (%ld)\n", hwId); + OSReport("MetroTRK : Invalid hardware ID passed from OS\n"); + OSReport("MetroTRK : Defaulting to GDEV Hardware\n"); + } + + return result; +} + +DSError TRKInitializeIntDrivenUART(u32, u32, u32, void* r5) +{ + gDBCommTable.initialize_func(r5, TRKEXICallBack); + gDBCommTable.open_func(); + return DS_NoError; +} + +void EnableEXI2Interrupts(void) +{ + if (!TRK_Use_BBA) { + if (gDBCommTable.init_interrupts_func != nullptr) { + gDBCommTable.init_interrupts_func(); + } + } +} + +int TRKPollUART(void) +{ + return gDBCommTable.peek_func(); +} + +UARTError TRKReadUARTN(void* bytes, u32 length) +{ + int readErr = gDBCommTable.read_func(bytes, length); + return ((-readErr | readErr) >> 31); +} + +UARTError TRKWriteUARTN(const void* bytes, u32 length) +{ + int writeErr = gDBCommTable.write_func(bytes, length); + return ((-writeErr | writeErr) >> 31); +} + +void WriteUARTFlush(void) +{ + // UNUSED FUNCTION +} + +void WriteUART1(void) +{ + // UNUSED FUNCTION +} + +void TRKReadUARTPoll(void) +{ + // UNUSED FUNCTION +} + +void ReserveEXI2Port(void) +{ + gDBCommTable.post_stop_func(); +} + +void UnreserveEXI2Port(void) +{ + gDBCommTable.pre_continue_func(); +} + +void TRK_board_display(char* str) +{ + OSReport("%s\n", str); +} + +DSError InitializeProgramEndTrap(void) +{ + static const u32 EndofProgramInstruction = 'END'; + + u8* endOfProgramInstructionBytes = (u8*)&EndofProgramInstruction; + u8* ppcHaltPtr = (u8*)PPCHalt; + TRK_memcpy(ppcHaltPtr + 4, endOfProgramInstructionBytes, 4); + ICInvalidateRange(ppcHaltPtr + 4, 4); + DCFlushRange(ppcHaltPtr + 4, 4); +} + +void TRKUARTInterruptHandler(void) +{ +} + +ASM void TRKLoadContext(OSContext* ctx, u32 r4) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + lwz r0, OSContext.gpr[0](r3) + lwz r1, OSContext.gpr[1](r3) + lwz r2, OSContext.gpr[2](r3) + lhz r5, OSContext.state(r3) + rlwinm. r6, r5, 0, 0x1e, 0x1e + beq L_802CC24C + rlwinm r5, r5, 0, 0x1f, 0x1d + sth r5, OSContext.state(r3) + lmw r5, OSContext.gpr[5](r3) + b L_802CC250 +L_802CC24C: + lmw r13, OSContext.gpr[13](r3) +L_802CC250: + mr r31, r3 + mr r3, r4 + lwz r4, OSContext.cr(r31) + mtcrf 0xff, r4 + lwz r4, OSContext.lr(r31) + mtlr r4 + lwz r4, OSContext.ctr(r31) + mtctr r4 + lwz r4, OSContext.xer(r31) + mtxer r4 + mfmsr r4 + rlwinm r4, r4, 0, 0x11, 0xf //Turn off external exceptions + rlwinm r4, r4, 0, 0x1f, 0x1d //Turn off recoverable exception flag + mtmsr r4 + mtsprg 1, r2 + lwz r4, OSContext.gpr[3](r31) + mtsprg 2, r4 + lwz r4, OSContext.gpr[4](r31) + mtsprg 3, r4 + lwz r2, OSContext.srr0(r31) + lwz r4, OSContext.srr1(r31) + lwz r31, OSContext.gpr[31](r31) + b TRKInterruptHandler +#endif // clang-format on +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/flush_cache.c b/src/static/TRK_MINNOW_DOLPHIN/flush_cache.c new file mode 100644 index 00000000..5499cceb --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/flush_cache.c @@ -0,0 +1,23 @@ +#include "TRK/dstypes.h" + +ASM void TRK_flush_cache(u32 param_1, int param_2) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + lis r5, 0xFFFFFFF1@h + ori r5, r5, 0xFFFFFFF1@l + and r5, r5, r3 + subf r3, r5, r3 + add r4, r4, r3 +loop: + dcbst 0, r5 + dcbf 0, r5 + sync + icbi 0, r5 + addic r5, r5, 8 + addic. r4, r4, -8 + bge loop + isync + blr +#endif // clang-format on +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/main.c b/src/static/TRK_MINNOW_DOLPHIN/main.c new file mode 100644 index 00000000..2172ec2f --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/main.c @@ -0,0 +1,148 @@ +#include "TRK/trk.h" +#include "TRK/AmcExi2Stubs.h" +#include "TRK/CircleBuffer.h" + +extern void DBInitComm(vu8** inputPendingPtrRef, AmcEXICallback monitorCallback); +extern void DBInitInterrupts(void); +extern u32 DBQueryData(void); +extern BOOL DBRead(void* data, u32 size); +extern BOOL DBWrite(const void* data, u32 size); +extern void DBOpen(void); +extern void DBClose(void); + +#define GDEV_BUF_SIZE (0x500) + +static CircleBuffer gRecvCB; +static u8 gRecvBuf[GDEV_BUF_SIZE]; +static BOOL gIsInitialized; + +int gdev_cc_initialize(void* inputPendingPtrRef, AmcEXICallback monitorCallback) +{ + MWTRACE(1, "CALLING EXI2_Init\n"); + DBInitComm(inputPendingPtrRef, monitorCallback); + MWTRACE(1, "DONE CALLING EXI2_Init\n"); + CircleBufferInitialize(&gRecvCB, gRecvBuf, GDEV_BUF_SIZE); + return 0; +} + +int gdev_cc_shutdown() +{ + return 0; +} + +int gdev_cc_open() +{ + if (gIsInitialized) { + return -0x2715; + } + + gIsInitialized = TRUE; + return 0; +} + +int gdev_cc_close() +{ + return 0; +} + +int gdev_cc_read(u8* data, int size) +{ + u8 buff[GDEV_BUF_SIZE]; + int p1; + u32 retval; + int p2; + int poll; + retval = 0; + if (!gIsInitialized) { + return -0x2711; + } + + MWTRACE(1, "Expected packet size : 0x%08x (%ld)\n", size, size); + + p1 = size; + p2 = size; + while ((u32)CBGetBytesAvailableForRead(&gRecvCB) < p2) { + retval = 0; + poll = DBQueryData(); + if (poll != 0) { + retval = DBRead(buff, p2); + if (retval == 0) { + CircleBufferWriteBytes(&gRecvCB, buff, poll); + } + } + } + + if (retval == 0) { + CircleBufferReadBytes(&gRecvCB, data, p1); + } else { + MWTRACE(8, "cc_read : error reading bytes from EXI2 %ld\n", retval); + } + + return retval; +} + +int gdev_cc_write(const u8* bytes, int length) +{ + int exi2Len; + int n_copy; + u32 hexCopy; + + hexCopy = (u32)bytes; + n_copy = length; + + if (gIsInitialized == FALSE) { + MWTRACE(8, "cc not initialized\n"); + return -0x2711; + } + + MWTRACE(8, "cc_write : Output data 0x%08x %ld bytes\n", bytes, length); + + while (n_copy > 0) { + MWTRACE(1, "cc_write sending %ld bytes\n", n_copy); + exi2Len = DBWrite((const void*)hexCopy, n_copy); + if (exi2Len == AMC_EXI_NO_ERROR) { + break; + } + hexCopy += exi2Len; + n_copy -= exi2Len; + } + + return 0; +} + +int gdev_cc_pre_continue() +{ + DBClose(); + return 0; +} + +int gdev_cc_post_stop() +{ + DBOpen(); + return 0; +} + +int gdev_cc_peek() +{ + int poll; + u8 buff[GDEV_BUF_SIZE]; + + poll = DBQueryData(); + if (poll <= 0) { + return 0; + } + + if (DBRead(buff, poll) == 0) { + CircleBufferWriteBytes(&gRecvCB, buff, poll); + } else { + return -0x2719; + } + + return poll; +} + +int gdev_cc_initinterrupts() +{ + DBInitInterrupts(); + return 0; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/main_TRK.c b/src/static/TRK_MINNOW_DOLPHIN/main_TRK.c new file mode 100644 index 00000000..66235d54 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/main_TRK.c @@ -0,0 +1,18 @@ +#include "TRK/trk.h" + +static DSError TRK_mainError; + +DSError TRK_main(void) +{ + MWTRACE(1, "TRK_Main \n"); + TRK_mainError = TRKInitializeNub(); + + if (TRK_mainError == DS_NoError) { + TRKNubWelcome(); + TRKNubMainLoop(); + } + + TRK_mainError = TRKTerminateNub(); + + return TRK_mainError; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/main_ddh.c b/src/static/TRK_MINNOW_DOLPHIN/main_ddh.c new file mode 100644 index 00000000..24ede259 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/main_ddh.c @@ -0,0 +1,142 @@ +#include "TRK/dstypes.h" +#include "TRK/trk.h" +#include "TRK/AmcExi2Stubs.h" +#include "TRK/CircleBuffer.h" + +#define DDH_BUF_SIZE (0x800) + +static CircleBuffer gRecvCB; +static u8 gRecvBuf[DDH_BUF_SIZE]; +static BOOL gIsInitialized; + +int ddh_cc_initialize(void* inputPendingPtrRef, AmcEXICallback monitorCallback) +{ + MWTRACE(1, "CALLING EXI2_Init\n"); + EXI2_Init(inputPendingPtrRef, monitorCallback); + MWTRACE(1, "DONE CALLING EXI2_Init\n"); + CircleBufferInitialize(&gRecvCB, gRecvBuf, DDH_BUF_SIZE); + return 0; +} + +int ddh_cc_shutdown() +{ + return 0; +} + +int ddh_cc_open() +{ + if (gIsInitialized) { + return DDH_ERR_ALREADY_INITIALIZED; + } + + gIsInitialized = TRUE; + return 0; +} + +int ddh_cc_close() +{ + return 0; +} + +int ddh_cc_read(u8* data, int size) +{ + u8 buff[DDH_BUF_SIZE]; + int originalDataSize; + u32 result; + int expectedDataSize; + int poll; + + result = 0; + if (!gIsInitialized) { + return DDH_ERR_NOT_INITIALIZED; + } + + MWTRACE(1, "Expected packet size : 0x%08x (%ld)\n", size, size); + + originalDataSize = expectedDataSize = size; + while ((u32)CBGetBytesAvailableForRead(&gRecvCB) < expectedDataSize) { + result = 0; + + poll = EXI2_Poll(); + if (poll != 0) { + result = EXI2_ReadN(buff, poll); + if (result == 0) { + CircleBufferWriteBytes(&gRecvCB, buff, poll); + } + } + } + + if (result == 0) { + CircleBufferReadBytes(&gRecvCB, data, originalDataSize); + } else { + MWTRACE(8, "cc_read : error reading bytes from EXI2 %ld\n", result); + } + + return result; +} + +int ddh_cc_write(const u8* bytes, int length) +{ + int exi2Len; + int n_copy; + u32 hexCopy; + + hexCopy = (u32)bytes; + n_copy = length; + + if (gIsInitialized == FALSE) { + MWTRACE(8, "cc not initialized\n"); + return DDH_ERR_NOT_INITIALIZED; + } + + MWTRACE(8, "cc_write : Output data 0x%08x %ld bytes\n", bytes, length); + + while (n_copy > 0) { + MWTRACE(1, "cc_write sending %ld bytes\n", n_copy); + exi2Len = EXI2_WriteN((const void*)hexCopy, n_copy); + if (exi2Len == AMC_EXI_NO_ERROR) { + break; + } + hexCopy += exi2Len; + n_copy -= exi2Len; + } + + return 0; +} + +int ddh_cc_pre_continue() +{ + EXI2_Unreserve(); + return 0; +} + +int ddh_cc_post_stop() +{ + EXI2_Reserve(); + return 0; +} + +int ddh_cc_peek() +{ + int poll; + u8 buff[DDH_BUF_SIZE]; + + poll = EXI2_Poll(); + if (poll <= 0) { + return 0; + } + + if (EXI2_ReadN(buff, poll) == 0) { + CircleBufferWriteBytes(&gRecvCB, buff, poll); + } else { + return DDH_ERR_READ_ERROR; + } + + return poll; +} + +int ddh_cc_initinterrupts() +{ + EXI2_EnableInterrupts(); + return 0; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/mainloop.c b/src/static/TRK_MINNOW_DOLPHIN/mainloop.c new file mode 100644 index 00000000..50e5a6f1 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/mainloop.c @@ -0,0 +1,73 @@ +#include "TRK/dstypes.h" +#include "TRK/trk.h" + +extern TRKEventQueue gTRKEventQueue; +extern TRKState gTRKState; + +void TRKHandleRequestEvent(void) +{ + // UNUSED FUNCTION +} + +void TRKHandleSupportEvent(void) +{ + // UNUSED FUNCTION +} + +void TRKIdle(void) +{ + // UNUSED FUNCTION +} + +void TRKNubMainLoop(void) +{ + void* msg; + TRKEvent event; + BOOL isShutdownRequested; + BOOL isNewInput; + + isShutdownRequested = FALSE; + isNewInput = FALSE; + while (isShutdownRequested == FALSE) { + if (TRKGetNextEvent(&event) != FALSE) { + isNewInput = FALSE; + + switch (event.eventType) { + case NUBEVENT_Null: + break; + + case NUBEVENT_Request: + msg = TRKGetBuffer(event.msgBufID); + TRKDispatchMessage(msg); + break; + + case NUBEVENT_Shutdown: + isShutdownRequested = TRUE; + break; + + case NUBEVENT_Breakpoint: + case NUBEVENT_Exception: + TRKTargetInterrupt(&event); + break; + + case NUBEVENT_Support: + TRKTargetSupportRequest(); + break; + } + + TRKDestructEvent(&event); + continue; + } + + if ((isNewInput == FALSE) || (*(u8*)gTRKInputPendingPtr != '\0')) { + isNewInput = TRUE; + TRKGetInput(); + continue; + } + + if (TRKTargetStopped() == FALSE) { + TRKTargetContinue(); + } + isNewInput = FALSE; + } +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c b/src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c new file mode 100644 index 00000000..c9fd5965 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c @@ -0,0 +1,81 @@ +#include "TRK/dstypes.h" + +#define WRITE(dst, add, n_dst, n_src) ((u##n_dst*)dst) = ((u##n_dst*)(((u##n_src*)dst) + add)) - 1 +#define WRITE_BYTE(dst, add) WRITE(dst, add, 8, 32) +#define WRITE_WORD(dst, add) WRITE(dst, add, 32, 8) + +DECL_SECT(".init") void* TRK_memcpy(void* dst, const void* src, size_t n); +DECL_SECT(".init") void* TRK_memset(void* dst, int val, size_t n); + +#pragma dont_inline on +void TRK_fill_mem(void* dst, int val, size_t n) +{ + u32 v = (u8)val; + u32 i, j; + + WRITE_BYTE(dst, 0); + + if (n >= 32) { + i = (~(u32)dst) & 3; + + if (i) { + n -= i; + + do { + *++(((u8*)dst)) = v; + } while (--i); + } + + if (v) + v |= v << 24 | v << 16 | v << 8; + + WRITE_WORD(dst, 4); + WRITE_WORD(dst, 1); + + i = n / 32; + + if (i) { + do { + for (j = 0; j < 8; j++) + *++((u32*)dst) = v; + } while (--i); + } + + i = (n / 4) % 8; + + if (i) { + do { + *++((u32*)dst) = v; + } while (--i); + } + + WRITE_BYTE(dst, 1); + + n %= 4; + } + + if (n) + do { + *++((u8*)dst) = v; + } while (--n); + + return; +} +#pragma dont_inline reset + +void* TRK_memcpy(void* dst, const void* src, size_t n) +{ + const u8* s = (const u8*)src - 1; + u8* d = (u8*)dst - 1; + + n++; + while (--n != 0) + *++d = *++s; + return dst; +} + +void* TRK_memset(void* dst, int val, size_t n) +{ + TRK_fill_mem(dst, val, n); + return dst; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c b/src/static/TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c new file mode 100644 index 00000000..096eefe1 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c @@ -0,0 +1,246 @@ +#include "TRK/trk.h" + +ASM void TRKSaveExtended1Block(void) +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + lis r2, gTRKCPUState@h + ori r2, r2, gTRKCPUState@l + mfsr r16, 0 + mfsr r17, 0x1 + mfsr r18, 0x2 + mfsr r19, 0x3 + mfsr r20, 0x4 + mfsr r21, 0x5 + mfsr r22, 0x6 + mfsr r23, 0x7 + mfsr r24, 0x8 + mfsr r25, 0x9 + mfsr r26, 0xA + mfsr r27, 0xB + mfsr r28, 0xC + mfsr r29, 0xD + mfsr r30, 0xE + mfsr r31, 0xF + stmw r16, 0x1A8(r2) + mftb r10, 0x10c + mftbu r11 + mfspr r12, 0x3F0 + mfspr r13, 0x3F1 + mfspr r14, 0x1b + mfspr r15, 0x11F + mfibatu r16, 0 + mfibatl r17, 0 + mfibatu r18, 0x1 + mfibatl r19, 0x1 + mfibatu r20, 0x2 + mfibatl r21, 0x2 + mfibatu r22, 0x3 + mfibatl r23, 0x3 + mfdbatu r24, 0 + mfdbatl r25, 0 + mfdbatu r26, 0x1 + mfdbatl r27, 0x1 + mfdbatu r28, 0x2 + mfdbatl r29, 0x2 + mfdbatu r30, 0x3 + mfdbatl r31, 0x3 + stmw r10, 0x1E8(r2) + mfsdr1 r22 + mfdar r23 + mfdsisr r24 + mfsprg r25, 0 + mfsprg r26, 0x1 + mfsprg r27, 0x2 + mfsprg r28, 0x3 + li r29, 0 + mfspr r30, 0x3F2 + mfear r31 + stmw r22, 0x25C(r2) + mfspr r20, 0x390 + mfspr r21, 0x391 + mfspr r22, 0x392 + mfspr r23, 0x393 + mfspr r24, 0x394 + mfspr r25, 0x395 + mfspr r26, 0x396 + mfspr r27, 0x397 + mfspr r28, 0x398 + mfspr r29, 0x399 + mfspr r30, 0x39A + mfspr r31, 0x39B + stmw r20, 0x2FC(r2) + b loc_0x150 + + mfspr r16, 0x3A0 + mfspr r17, 0x3A7 + mfspr r18, 0x3A8 + mfspr r19, 0x3A9 + mfspr r20, 0x3AA + mfspr r21, 0x3AB + mfspr r22, 0x3AC + mfspr r23, 0x3AD + mfspr r24, 0x3AE + mfspr r25, 0x3AF + mfspr r26, 0x3B0 + mfspr r27, 0x3B7 + mfspr r28, 0x3BF + mfspr r29, 0x3F6 + mfspr r30, 0x3F7 + mfspr r31, 0x3FF + stmw r16, 0x2B8(r2) + +loc_0x150: + mfspr r19, 0x3F5 + mfspr r20, 0x3B9 + mfspr r21, 0x3BA + mfspr r22, 0x3BD + mfspr r23, 0x3BE + mfspr r24, 0x3BB + mfspr r25, 0x3B8 + mfspr r26, 0x3BC + mfspr r27, 0x3FC + mfspr r28, 0x3FD + mfspr r29, 0x3FE + mfspr r30, 0x3FB + mfspr r31, 0x3F9 + stmw r19, 0x284(r2) + blr + mfspr r25, 0x3D0 + mfspr r26, 0x3D1 + mfspr r27, 0x3D2 + mfspr r28, 0x3D3 + mfspr r29, 0x3D4 + mfspr r30, 0x3D5 + mfspr r31, 0x3D6 + stmw r25, 0x240(r2) + mfdec r31 + stw r31, 0x278(r2) + blr +#endif // clang-format on +} + +ASM void TRKRestoreExtended1Block() +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + lis r2, gTRKCPUState@h + ori r2, r2, gTRKCPUState@l + lis r5, gTRKRestoreFlags@h + ori r5, r5, gTRKRestoreFlags@l + lbz r3, 0x0(r5) + lbz r6, 0x1(r5) + li r0, 0 + stb r0, 0x0(r5) + stb r0, 0x1(r5) + cmpwi r3, 0 + beq- loc_0x3C + lwz r24, 0x1E8(r2) + lwz r25, 0x1EC(r2) + mttbl r24 + mttbu r25 + +loc_0x3C: + lmw r20, 0x2FC(r2) + mtspr 912, r20 + mtspr 913, r21 + mtspr 914, r22 + mtspr 915, r23 + mtspr 916, r24 + mtspr 917, r25 + mtspr 918, r26 + mtspr 919, r27 + mtspr 920, r28 + mtspr 922, r30 + mtspr 923, r31 + b loc_0x88 + lmw r26, 0x2E0(r2) + mtspr 944, r26 + mtspr 951, r27 + mtspr 1014, r29 + mtspr 1015, r30 + mtspr 1023, r31 + +loc_0x88: + lmw r19, 0x284(r2) + mtspr 1013, r19 + mtspr 953, r20 + mtspr 954, r21 + mtspr 957, r22 + mtspr 958, r23 + mtspr 955, r24 + mtspr 952, r25 + mtspr 956, r26 + mtspr 1020, r27 + mtspr 1021, r28 + mtspr 1022, r29 + mtspr 1019, r30 + mtspr 1017, r31 + b loc_0xF4 + cmpwi r6, 0 + beq- loc_0xD4 + lwz r26, 0x278(r2) + mtdec r26 + +loc_0xD4: + lmw r25, 0x240(r2) + mtspr 976, r25 + mtspr 977, r26 + mtspr 978, r27 + mtspr 979, r28 + mtspr 980, r29 + mtspr 981, r30 + mtspr 982, r31 + +loc_0xF4: + lmw r16, 0x1A8(r2) + mtsr 0, r16 + mtsr 1, r17 + mtsr 2, r18 + mtsr 3, r19 + mtsr 4, r20 + mtsr 5, r21 + mtsr 6, r22 + mtsr 7, r23 + mtsr 8, r24 + mtsr 9, r25 + mtsr 10, r26 + mtsr 11, r27 + mtsr 12, r28 + mtsr 13, r29 + mtsr 14, r30 + mtsr 15, r31 + lmw r12, 0x1F0(r2) + mtspr 1008, r12 + mtspr 1009, r13 + mtsrr1 r14 + mtspr 287, r15 + mtibatu 0, r16 + mtibatl 0, r17 + mtibatu 1, r18 + mtibatl 1, r19 + mtibatu 2, r20 + mtibatl 2, r21 + mtibatu 3, r22 + mtibatl 3, r23 + mtdbatu 0, r24 + mtdbatl 0, r25 + mtdbatu 1, r26 + mtdbatl 1, r27 + mtdbatu 2, r28 + mtdbatl 2, r29 + mtdbatu 3, r30 + mtdbatl 3, r31 + lmw r22, 0x25C(r2) + mtsdr1 r22 + mtdar r23 + mtdsisr r24 + mtsprg 0, r25 + mtsprg 1, r26 + mtsprg 2, r27 + mtsprg 3, r28 + mtspr 1010, r30 + mtear r31 + blr +#endif // clang-format on +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/msg.c b/src/static/TRK_MINNOW_DOLPHIN/msg.c new file mode 100644 index 00000000..cdb0cb60 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/msg.c @@ -0,0 +1,8 @@ +#include "TRK/trk.h" + +DSError TRKMessageSend(MessageBuffer* msg) +{ + DSError writeErr = TRKWriteUARTN(&msg->data, msg->length); + MWTRACE(1, "MessageSend : cc_write returned %ld\n", writeErr); + return DS_NoError; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/msgbuf.c b/src/static/TRK_MINNOW_DOLPHIN/msgbuf.c new file mode 100644 index 00000000..8b8e90e2 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/msgbuf.c @@ -0,0 +1,367 @@ +#include "TRK/trk.h" + +MessageBuffer gTRKMsgBufs[3]; + +void TRKSetBufferUsed(MessageBuffer* msg, BOOL state) +{ + msg->isInUse = state; +} + +DSError TRKInitializeMessageBuffers(void) +{ + int i; + for (i = 0; i < 3; i++) { + TRKInitializeMutex(&gTRKMsgBufs[i]); + TRKAcquireMutex(&gTRKMsgBufs[i]); + TRKSetBufferUsed(&gTRKMsgBufs[i], FALSE); + TRKReleaseMutex(&gTRKMsgBufs[i]); + } + + return DS_NoError; +} + +DSError TRKGetFreeBuffer(int* msgID, MessageBuffer** outMsg) +{ + MessageBuffer* buf; + DSError error = DS_NoMessageBufferAvailable; + int i; + + *outMsg = nullptr; + + for (i = 0; i < 3; i++) { + buf = TRKGetBuffer(i); + + TRKAcquireMutex(buf); + if (!buf->isInUse) { + TRKResetBuffer(buf, TRUE); + TRKSetBufferUsed(buf, TRUE); + error = DS_NoError; + *outMsg = buf; + *msgID = i; + i = 3; // why not break? weird choice + } + TRKReleaseMutex(buf); + } + + if (error == DS_NoMessageBufferAvailable) { + usr_puts_serial("ERROR : No buffer available\n"); + } + + return error; +} + +void* TRKGetBuffer(int idx) +{ + MessageBuffer* buf = nullptr; + if (idx >= 0 && idx < 3) { + buf = &gTRKMsgBufs[idx]; + } + + return buf; +} + +void TRKReleaseBuffer(int idx) +{ + MessageBuffer* msg; + if (idx != -1 && idx >= 0 && idx < 3) { + msg = &gTRKMsgBufs[idx]; + TRKAcquireMutex(msg); + TRKSetBufferUsed(msg, FALSE); + TRKReleaseMutex(msg); + } +} + +void TRKResetBuffer(MessageBuffer* msg, BOOL keepData) +{ + msg->length = 0; + msg->position = 0; + + if (!keepData) { + TRK_memset(msg->data, 0, 0x880); + } +} + +DSError TRKSetBufferPosition(MessageBuffer* msg, u32 pos) +{ + DSError error = DS_NoError; + + if (pos > 0x880) { + error = DS_MessageBufferOverflow; + } else { + msg->position = pos; + // If the new position is past the current length, + // update the length + if (pos > msg->length) { + msg->length = pos; + } + } + + return error; +} + +DSError TRKAppendBuffer(MessageBuffer* msg, const void* data, size_t length) +{ + DSError error = DS_NoError; // r31 + u32 bytesLeft; + + // Return if no bytes to append + if (length == 0) { + return DS_NoError; + } + + bytesLeft = 0x880 - msg->position; + + // If there isn't enough space left in the buffer, change the number + // of bytes to append to the remaining number of bytes + if (bytesLeft < length) { + error = DS_MessageBufferOverflow; + length = bytesLeft; + } + + if (length == 1) { + // If the length of bytes to append is 1, just copy the byte over + msg->data[msg->position] = ((u8*)data)[0]; + } else { + // Otherwise, use memcpy + TRK_memcpy(msg->data + msg->position, data, length); + } + + // Update the position and length + msg->position += length; + msg->length = msg->position; + + return error; +} + +DSError TRKReadBuffer(MessageBuffer* msg, void* data, size_t length) +{ + DSError error = DS_NoError; + uint bytesLeft; // this has to be uint not u32 to match lmfao. + + // Return if no bytes to read + if (length == 0) { + return DS_NoError; + } + + bytesLeft = msg->length - msg->position; + + // If the number of bytes to read exceeds the buffer length, change + // the length to the remaining number of bytes + if (length > bytesLeft) { + error = DS_MessageBufferReadError; + length = bytesLeft; + } + + TRK_memcpy(data, msg->data + msg->position, length); + msg->position += length; + return error; +} + +void TRKAppendBuffer1_ui16(void) +{ + // UNUSED FUNCTION +} + +DSError TRKAppendBuffer1_ui32(MessageBuffer* buffer, const u32 data) +{ + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + + if (gTRKBigEndian) { + bigEndianData = (u8*)&data; + } else { + byteData = (u8*)&data; + bigEndianData = swapBuffer; + + bigEndianData[0] = byteData[3]; + bigEndianData[1] = byteData[2]; + bigEndianData[2] = byteData[1]; + bigEndianData[3] = byteData[0]; + } + + return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data)); +} + +DSError TRKAppendBuffer1_ui64(MessageBuffer* buffer, const u64 data) +{ + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + if (gTRKBigEndian) { + bigEndianData = (u8*)&data; + } else { + byteData = (u8*)&data; + bigEndianData = swapBuffer; + + bigEndianData[0] = byteData[7]; + bigEndianData[1] = byteData[6]; + bigEndianData[2] = byteData[5]; + bigEndianData[3] = byteData[4]; + bigEndianData[4] = byteData[3]; + bigEndianData[5] = byteData[2]; + bigEndianData[6] = byteData[1]; + bigEndianData[7] = byteData[0]; + } + + return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data)); +} + +void TRKAppendBuffer1_ui128(void) +{ + // UNUSED FUNCTION +} + +DSError TRKAppendBuffer_ui8(MessageBuffer* buffer, const u8* data, int count) +{ + DSError err; + int i; + + for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { + err = TRKAppendBuffer1_ui8(buffer, data[i]); + } + + return err; +} + +void TRKAppendBuffer_ui16(void) +{ + // UNUSED FUNCTION +} + +DSError TRKAppendBuffer_ui32(MessageBuffer* buffer, const u32* data, int count) +{ + DSError err; + int i; + + for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { + err = TRKAppendBuffer1_ui32(buffer, data[i]); + } + + return err; +} + +void TRKAppendBuffer_ui64(void) +{ + // UNUSED FUNCTION +} + +void TRKAppendBuffer_ui128(void) +{ + // UNUSED FUNCTION +} + +DSError TRKReadBuffer1_ui8(MessageBuffer* buffer, u8* data) +{ + return TRKReadBuffer(buffer, (void*)data, 1); +} + +void TRKReadBuffer1_ui16(void) +{ + // UNUSED FUNCTION +} + +DSError TRKReadBuffer1_ui32(MessageBuffer* buffer, u32* data) +{ + DSError err; + + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + + if (gTRKBigEndian) { + bigEndianData = (u8*)data; + } else { + bigEndianData = swapBuffer; + } + + err = TRKReadBuffer(buffer, (void*)bigEndianData, sizeof(*data)); + + if (!gTRKBigEndian && err == DS_NoError) { + byteData = (u8*)data; + + byteData[0] = bigEndianData[3]; + byteData[1] = bigEndianData[2]; + byteData[2] = bigEndianData[1]; + byteData[3] = bigEndianData[0]; + } + + return err; + // UNUSED FUNCTION +} + +DSError TRKReadBuffer1_ui64(MessageBuffer* buffer, u64* data) +{ + DSError err; + + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + + if (gTRKBigEndian) { + bigEndianData = (u8*)data; + } else { + bigEndianData = swapBuffer; + } + + err = TRKReadBuffer(buffer, (void*)bigEndianData, sizeof(*data)); + + if (!gTRKBigEndian && err == 0) { + byteData = (u8*)data; + + byteData[0] = bigEndianData[7]; + byteData[1] = bigEndianData[6]; + byteData[2] = bigEndianData[5]; + byteData[3] = bigEndianData[4]; + byteData[4] = bigEndianData[3]; + byteData[5] = bigEndianData[2]; + byteData[6] = bigEndianData[1]; + byteData[7] = bigEndianData[0]; + } + + return err; +} + +void TRKReadBuffer1_ui128(MessageBuffer* buffer, u8* p2, int p3) +{ + // UNUSED FUNCTION +} + +DSError TRKReadBuffer_ui8(MessageBuffer* buffer, u8* data, int count) +{ + DSError err; + int i; + + for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { + err = TRKReadBuffer1_ui8(buffer, &(data[i])); + } + + return err; +} + +void TRKReadBuffer_ui16(MessageBuffer* buffer, u8* p2, int p3) +{ + // UNUSED FUNCTION +} + +DSError TRKReadBuffer_ui32(MessageBuffer* buffer, u32* data, int count) +{ + DSError err; + s32 i; + + for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { + err = TRKReadBuffer1_ui32(buffer, &(data[i])); + } + + return err; +} + +void TRKReadBuffer_ui64(MessageBuffer* buffer, u8* p2, int p3) +{ + // UNUSED FUNCTION +} + +void TRKReadBuffer_ui128(MessageBuffer* buffer, u8* p2, int p3) +{ + // UNUSED FUNCTION +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/msghndlr.c b/src/static/TRK_MINNOW_DOLPHIN/msghndlr.c new file mode 100644 index 00000000..cacd8657 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/msghndlr.c @@ -0,0 +1,548 @@ +#include "TRK/trk.h" +static BOOL IsTRKConnected; +static u32 g_CurrentSequence; + +void OutputData(void* data, int length) +{ + // u8 byte; + int i; + u8* datapointer = data; + + for (i = 0; i < length; i++) { + MWTRACE(8, "%02x ", datapointer[i]); + if (i % 16 == 15) { + MWTRACE(8, "\n"); + } + } + + MWTRACE(8, "\n"); +} + +int GetTRKConnected(void) +{ + return IsTRKConnected; +} + +void SetTRKConnected(int isConnected) +{ + IsTRKConnected = isConnected; +} + +void TRKMessageIntoReply(void) +{ + // UNUSED FUNCTION +} + +DSError TRKSendACK(MessageBuffer* buffer) +{ + DSError err; + MWTRACE(1, "SendACK : Calling MessageSend\n"); + err = TRKMessageSend(buffer); + MWTRACE(1, "MessageSend err : %ld\n", err); + return err; +} + +DSError TRKStandardACK(MessageBuffer* buffer, MessageCommandID commandID, DSReplyError replyError) +{ + CommandReply reply; + + memset(&reply, 0, sizeof(CommandReply)); + reply.commandID.b = commandID; + reply._00 = 0x40; + reply.replyError.b = replyError; + TRKWriteUARTN(&reply, sizeof(CommandReply)); + return DS_NoError; +} + +void TRKDoError(void) +{ + // UNUSED FUNCTION +} + +void TRKDoUnsupported(void) +{ + // UNUSED FUNCTION +} + +DSError TRKDoConnect(MessageBuffer* buffer) +{ + IsTRKConnected = TRUE; + return TRKStandardACK(buffer, 0x80, DSREPLY_NoError); +} + +DSError TRKDoDisconnect(MessageBuffer* buffer) +{ + TRKEvent event; + + IsTRKConnected = FALSE; + TRKStandardACK(buffer, 0x80, DSREPLY_NoError); + TRKConstructEvent(&event, 1); + TRKPostEvent(&event); + return DS_NoError; +} + +DSError TRKDoReset(MessageBuffer* buffer) +{ + TRKStandardACK(buffer, 0x80, DSREPLY_NoError); + __TRK_reset(); + return DS_NoError; +} + +DSError TRKDoOverride(MessageBuffer* buffer) +{ + TRKStandardACK(buffer, 0x80, DSREPLY_NoError); + __TRK_copy_vectors(); + return DS_NoError; +} + +DSError TRKDoVersions(MessageBuffer*) +{ + return DS_NoError; +} + +DSError TRKDoSupportMask(MessageBuffer*) +{ + return DS_NoError; +} + +void TRKDoCPUType(void) +{ + // UNUSED FUNCTION +} + +DSError TRKDoReadMemory(MessageBuffer* buffer) +{ + u8 buf[0x820] __attribute__((aligned(32))); + size_t tempLength; + int result; + int replyErr; + int options; + size_t length; + u32 start; + + start = *(u32*)(buffer->data + 16); + length = *(u16*)(buffer->data + 12); + options = buffer->data[8]; + + MWTRACE(1, "ReadMemory (0x%02x) : 0x%08x 0x%08x 0x%08x\n", buffer->data[4], start, length, options); + + if (options & DSMSGMEMORY_Extended) { + return TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_UnsupportedOptionError); + } + + tempLength = length; + + if (options & DSMSGMEMORY_Space_data) { + result = TRKTargetAccessARAM(buf, start, &tempLength, TRUE); + } else { + result = TRKTargetAccessMemory(buf, start, &tempLength, options & DSMSGMEMORY_Userview ? 0 : 1, TRUE); + } + + TRKResetBuffer(buffer, 0); + + if (result == DS_NoError) { + CommandReply reply; + memset(&reply, 0, sizeof(CommandReply)); + reply.replyError.b = result; + reply._00 = tempLength + 0x40; + reply.commandID.b = DSMSG_ReplyACK; + TRKAppendBuffer(buffer, &reply, sizeof(CommandReply)); + + if (options & 0x40) { + result = TRKAppendBuffer(buffer, buf + (start & 0x1F), tempLength); + } else { + result = TRKAppendBuffer(buffer, buf, tempLength); + } + } + + if (result) { + switch (result) { + case DS_CWDSException: + replyErr = DSREPLY_CWDSException; + break; + case DS_InvalidMemory: + replyErr = DSREPLY_InvalidMemoryRange; + break; + case DS_InvalidProcessID: + replyErr = DSREPLY_InvalidProcessID; + break; + case DS_InvalidThreadID: + replyErr = DSREPLY_InvalidThreadID; + break; + case DS_OSError: + replyErr = DSREPLY_OSError; + break; + default: + replyErr = DSREPLY_CWDSError; + break; + } + return TRKStandardACK(buffer, DSMSG_ReplyACK, replyErr); + } + + return TRKSendACK(buffer); +} + +DSError TRKDoWriteMemory(MessageBuffer* b) +{ + u8 buf[0x820] __attribute__((aligned(32))); + size_t tempLength; + int options; + int result; + int replyErr; + size_t length; + u32 start; + + start = *(u32*)(&b->data[16]); + length = *(u16*)(&b->data[12]); + options = b->data[8]; + + MWTRACE(1, "WriteMemory (0x%02x) : 0x%08x 0x%08x 0x%08x\n", (uint)b->data[0x4], start, length, options); + + if (options & DSMSGMEMORY_Extended) { + return TRKStandardACK(b, DSMSG_ReplyACK, DSMSG_ReadRegisters); + } + + tempLength = length; + + TRKSetBufferPosition(b, DSMSGMEMORY_Space_data); + if (options & DSMSGMEMORY_Space_data) { + TRKReadBuffer(b, buf + (start & 0x1f), tempLength); + result = TRKTargetAccessARAM(buf, start, &tempLength, FALSE); + } else { + TRKReadBuffer(b, buf, tempLength); + result = TRKTargetAccessMemory(buf, start, &tempLength, options & DSMSGMEMORY_Userview ? 0 : 1, FALSE); + } + + TRKResetBuffer(b, 0); + + if (result == DS_NoError) { + CommandReply reply; + memset(&reply, 0, sizeof(CommandReply)); + reply._00 = 0x40; + reply.commandID.b = DSMSG_ReplyACK; + reply.replyError.b = result; + result = TRKAppendBuffer(b, &reply, sizeof(CommandReply)); + } + + if (result != DS_NoError) { + switch (result) { + case DS_CWDSException: + replyErr = DSREPLY_CWDSException; + break; + case DS_InvalidMemory: + replyErr = DSREPLY_InvalidMemoryRange; + break; + case DS_InvalidProcessID: + replyErr = DSREPLY_InvalidProcessID; + break; + case DS_InvalidThreadID: + replyErr = DSREPLY_InvalidThreadID; + break; + case DS_OSError: + replyErr = DSREPLY_OSError; + break; + default: + replyErr = DSREPLY_CWDSError; + break; + } + return TRKStandardACK(b, DSMSG_ReplyACK, replyErr); + } + + return TRKSendACK(b); +} + +DSError TRKDoReadRegisters(MessageBuffer* b) +{ + int error; + u8 options; + u16 firstRegister; + u16 lastRegister; + size_t registersLength; + CommandReply local_50; + + options = b->data[8]; + firstRegister = *(u16*)(b->data + 12); + lastRegister = *(u16*)(b->data + 16); + + if (firstRegister > lastRegister) { + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_InvalidRegisterRange); + } + + local_50.commandID.b = DSMSG_ReplyACK; + local_50._00 = 0x468; + + TRKResetBuffer(b, 0); + MWTRACE(4, "DoReadRegisters : Buffer length 0x%08x\n", b->length); + + TRKAppendBuffer_ui8(b, (u8*)&local_50, sizeof(CommandReply)); + MWTRACE(4, "DoReadRegisters : Buffer length 0x%08x\n", b->length); + + error = TRKTargetAccessDefault(0, 36, b, ®istersLength, TRUE); + MWTRACE(4, "DoReadRegisters : Error reading default regs 0x%08x\n", error); + MWTRACE(4, "DoReadRegisters : Buffer length 0x%08x\n", b->length); + + if (error == DS_NoError) { + error = TRKTargetAccessFP(0, 33, b, ®istersLength, TRUE); + } + MWTRACE(4, "DoReadRegisters : Error FP regs 0x%08x\n", error); + MWTRACE(4, "DoReadRegisters : Buffer length 0x%08x\n", b->length); + if (error == DS_NoError) { + error = TRKTargetAccessExtended1(0, 0x60, b, ®istersLength, TRUE); + } + MWTRACE(4, "DoReadRegisters : Error extended1 regs 0x%08x\n", error); + MWTRACE(4, "DoReadRegisters : Buffer length 0x%08x\n", b->length); + if (error == DS_NoError) { + error = TRKTargetAccessExtended2(0, 31, b, ®istersLength, TRUE); + } + MWTRACE(4, "DoReadRegisters : Error extended2 regs 0x%08x\n", error); + MWTRACE(4, "DoReadRegisters : Buffer length 0x%08x\n", b->length); + + // Check if there was an error, and respond accordingly + if (error != DS_NoError) { + int replyError; + switch (error) { + case DS_UnsupportedError: + replyError = DSREPLY_UnsupportedOptionError; + break; + case DS_InvalidRegister: + replyError = DSREPLY_InvalidRegisterRange; + break; + case DS_CWDSException: + replyError = DSREPLY_CWDSException; + break; + case DS_InvalidProcessID: + replyError = DSREPLY_InvalidProcessID; + break; + case DS_InvalidThreadID: + replyError = DSREPLY_InvalidThreadID; + break; + case DS_OSError: + replyError = DSREPLY_OSError; + break; + default: + replyError = DSREPLY_CWDSError; + } + + return TRKStandardACK(b, DSMSG_ReplyACK, replyError); + } else { + // No error, send ack + return TRKSendACK(b); + } +} + +DSError TRKDoWriteRegisters(MessageBuffer* b) +{ + int error; + int replyError; + u8 options; + u16 firstRegister; + u16 lastRegister; + size_t registersLength; + + options = b->data[8]; + firstRegister = *(u16*)(b->data + 12); + lastRegister = *(u16*)(b->data + 16); + + TRKSetBufferPosition(b, 0); + + if (firstRegister > lastRegister) { + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_InvalidRegisterRange); + } + + TRKSetBufferPosition(b, 0x40); + + switch (options) { + case DSREG_Default: + error = TRKTargetAccessDefault(firstRegister, lastRegister, b, ®istersLength, FALSE); + break; + case DSREG_FP: + error = TRKTargetAccessFP(firstRegister, lastRegister, b, ®istersLength, FALSE); + break; + case DSREG_Extended1: + error = TRKTargetAccessExtended1(firstRegister, lastRegister, b, ®istersLength, FALSE); + break; + case DSREG_Extended2: + error = TRKTargetAccessExtended2(firstRegister, lastRegister, b, ®istersLength, FALSE); + break; + default: + // invalid option + error = DS_UnsupportedError; + break; + } + + TRKResetBuffer(b, 0); + + if (error == DS_NoError) { + CommandReply local_50; + memset(&local_50, 0, sizeof(CommandReply)); + local_50._00 = 0x40; + local_50.commandID.b = DSMSG_ReplyACK; + local_50.replyError.b = error; + error = TRKAppendBuffer(b, (u8*)&local_50, sizeof(CommandReply)); + } + + // Check if there was an error, and respond accordingly + if (error != DS_NoError) { + switch (error) { + case DS_UnsupportedError: + replyError = DSREPLY_UnsupportedOptionError; + break; + case DS_InvalidRegister: + replyError = DSREPLY_InvalidRegisterRange; + break; + case DS_MessageBufferReadError: + replyError = DSREPLY_PacketSizeError; + break; + case DS_CWDSException: + replyError = DSREPLY_CWDSException; + break; + case DS_InvalidProcessID: + replyError = DSREPLY_InvalidProcessID; + break; + case DS_InvalidThreadID: + replyError = DSREPLY_InvalidThreadID; + break; + case DS_OSError: + replyError = DSREPLY_OSError; + break; + default: + replyError = DSREPLY_CWDSError; + } + + return TRKStandardACK(b, DSMSG_ReplyACK, replyError); + } else { + // No error, send ack + return TRKSendACK(b); + } +} + +void TRKDoFlushCache(void) +{ + MWTRACE(1, "DoFlushCache unimplemented!!!\n"); + // UNUSED FUNCTION +} + +DSError TRKDoContinue(MessageBuffer*) +{ + MWTRACE(1, "DoContinue\n"); + if (!TRKTargetStopped()) { + u8 arr[0x40]; + memset(arr, 0, 0x40); + + arr[4] = 0x80; + *(u32*)arr = 0x40; + arr[8] = 0x16; + + TRKWriteUARTN(arr, 0x40); + return DS_NoError; + } else { + u8 arr[0x40]; + memset(arr, 0, 0x40); + + arr[4] = 0x80; + *(u32*)arr = 0x40; + arr[8] = 0x00; + + TRKWriteUARTN(arr, 0x40); + return TRKTargetContinue(); + } +} + + +DSError TRKDoStep(MessageBuffer* b) +{ + DSError result; + u8 options; + u8 count; + u32 rangeStart; + u32 rangeEnd; + u32 pc; + TRKSetBufferPosition(b, 0); + + options = *(u8*)&b->data[8]; + rangeStart = *(u32*)&b->data[16]; + rangeEnd = *(u32*)&b->data[20]; + + switch (options) { + case DSSTEP_IntoCount: + case DSSTEP_OverCount: + count = b->data[12]; + if (count >= 1) { + break; + } + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_ParameterError); + case DSSTEP_IntoRange: + case DSSTEP_OverRange: + pc = TRKTargetGetPC(); + if (pc >= rangeStart && pc <= rangeEnd) { + break; + } + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_ParameterError); + default: + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_UnsupportedOptionError); + } + + if (!TRKTargetStopped()) { + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_NotStopped); + } else { + result = TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_NoError); + switch (options) { + case DSSTEP_IntoCount: + case DSSTEP_OverCount: + result = TRKTargetSingleStep(count, (options == DSSTEP_OverCount)); + break; + case DSSTEP_IntoRange: + case DSSTEP_OverRange: + result = TRKTargetStepOutOfRange(rangeStart, rangeEnd, (options == DSSTEP_OverRange)); + break; + } + + return result; + } +} + +DSError TRKDoStop(MessageBuffer* b) +{ + MessageCommandID c; + + switch (TRKTargetStop()) { + case DS_NoError: + c = DSMSG_Ping; + break; + case DS_InvalidProcessID: + c = '!'; + break; + case DS_InvalidThreadID: + c = '\"'; + break; + case DS_OSError: + c = ' '; + break; + default: + c = DSMSG_Connect; + break; + } + + TRKStandardACK(b, DSMSG_ReplyACK, c); + + return DS_NoError; +} + +DSError TRKDoSetOption(MessageBuffer* message) +{ + u8 enable = message->data[0xc]; + + if (message->data[0x8] == '\1') { + usr_puts_serial("\nMetroTRK Option : SerialIO - "); + if (enable) { + usr_puts_serial("Enable\n"); + } else { + usr_puts_serial("Disable\n"); + } + SetUseSerialIO(enable); + } + + TRKStandardACK(message, DSMSG_ReplyACK, DS_NoError); + + return 0; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/mslsupp.c b/src/static/TRK_MINNOW_DOLPHIN/mslsupp.c new file mode 100644 index 00000000..d378ff66 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/mslsupp.c @@ -0,0 +1,96 @@ +#include "TRK/trk.h" + +// forward declares +DSIOResult __read_file(u32 handle, u8* buffer, size_t* count, void* ref_con); +DSIOResult __write_file(u32 handle, u8* buffer, size_t* count, void* ref_con); +DSIOResult __close_file(u32 handle, u8* buffer, size_t* count, void* ref_con); +DSIOResult __access_file(u32 handle, u8* buffer, size_t* count, void* ref_con, MessageCommandID cmd); + +DSIOResult __read_console(u32 handle, u8* buffer, size_t* count, void* ref_con) +{ + if (GetUseSerialIO() == 0) { + return DS_IOError; + } + return __read_file(DS_Stdin, buffer, count, ref_con); +} + +DSIOResult __TRK_write_console(u32 handle, u8* buffer, size_t* count, void* ref_con) +{ + if (GetUseSerialIO() == 0) { + return DS_IOError; + } + return __write_file(DS_Stdout, buffer, count, ref_con); +} + +DSIOResult __read_file(u32 handle, u8* buffer, size_t* count, void* ref_con) +{ + return __access_file(handle, buffer, count, ref_con, DSMSG_ReadFile); +} + +DSIOResult __write_file(u32 handle, u8* buffer, size_t* count, void* ref_con) +{ + return __access_file(handle, buffer, count, ref_con, DSMSG_WriteFile); +} + +void __open_file(void) +{ + // UNUSED FUNCTION +} + +DSIOResult __close_file(u32 handle, u8* buffer, size_t* count, void* ref_con) +{ + u32 r0; + + if (GetTRKConnected() == DS_NoError) { + return DS_IOError; + } + + r0 = TRKCloseFile(DSMSG_CloseFile, handle); + + switch ((u8)r0) { + case DS_IONoError: + return DS_IONoError; + case DS_IOEOF: + return DS_IOEOF; + } + + return DS_IOError; +} + +void __position_file(void) +{ + // UNUSED FUNCTION +} + +void convertFileMode(void) +{ + // UNUSED FUNCTION +} + +DSIOResult __access_file(u32 handle, u8* buffer, size_t* count, void* ref_con, MessageCommandID cmd) +{ + size_t countTemp; + u32 r0; + + if (GetTRKConnected() == DS_NoError) { + return DS_IOError; + } + + countTemp = *count; + r0 = TRKAccessFile(cmd, handle, &countTemp, buffer); + *count = countTemp; + + switch ((u8)r0) { + case DS_IONoError: + return DS_IONoError; + case DS_IOEOF: + return DS_IOEOF; + } + + return DS_IOError; +} + +void __open_temp_file(void) +{ + // UNUSED FUNCTION +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/mutex_TRK.c b/src/static/TRK_MINNOW_DOLPHIN/mutex_TRK.c new file mode 100644 index 00000000..682a94ea --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/mutex_TRK.c @@ -0,0 +1,16 @@ +#include "TRK/trk.h" + +DSError TRKInitializeMutex(void* p1) +{ + return DS_NoError; +} + +DSError TRKAcquireMutex(void* p1) +{ + return DS_NoError; +} + +DSError TRKReleaseMutex(void* p1) +{ + return DS_NoError; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/notify.c b/src/static/TRK_MINNOW_DOLPHIN/notify.c new file mode 100644 index 00000000..855132e9 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/notify.c @@ -0,0 +1,34 @@ +#include "TRK/dstypes.h" +#include "TRK/trk.h" + +void TRKWaitForACK(void) +{ + // UNUSED FUNCTION +} + +DSError TRKDoNotifyStopped(MessageCommandID cmd) +{ + int reqIdx; + int bufIdx; + MessageBuffer* msg; + DSError err; + DSError bufError; + + bufError = TRKGetFreeBuffer(&bufIdx, &msg); + if ((err = bufError) == FALSE) { + if (err == DS_NoError) { + if (cmd == DSMSG_NotifyStopped) { + TRKTargetAddStopInfo(msg); + } else { + TRKTargetAddExceptionInfo(msg); + } + } + bufError = TRKRequestSend(msg, &reqIdx, 2, 3, 1); + err = bufError; + if (err == DS_NoError) { + TRKReleaseBuffer(reqIdx); + } + TRKReleaseBuffer(bufIdx); + } + return err; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/nubevent.c b/src/static/TRK_MINNOW_DOLPHIN/nubevent.c new file mode 100644 index 00000000..bcbf3cff --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/nubevent.c @@ -0,0 +1,78 @@ +#include "TRK/trk.h" + +TRKEventQueue gTRKEventQueue; + +DSError TRKInitializeEventQueue() +{ + TRKInitializeMutex(&gTRKEventQueue); + TRKAcquireMutex(&gTRKEventQueue); + gTRKEventQueue.count = 0; + gTRKEventQueue.next = 0; + gTRKEventQueue.eventID = 0x100; + TRKReleaseMutex(&gTRKEventQueue); + return DS_NoError; +} + +void TRKCopyEvent(void) +{ + // UNUSED FUNCTION +} + +BOOL TRKGetNextEvent(TRKEvent* ev) +{ + BOOL ret = FALSE; + + TRKAcquireMutex(&gTRKEventQueue); + + if (gTRKEventQueue.count > 0) { + TRK_memcpy(ev, &gTRKEventQueue.events[gTRKEventQueue.next], sizeof(TRKEvent)); + gTRKEventQueue.count--; + + if (++gTRKEventQueue.next == 2) { + gTRKEventQueue.next = 0; + } + + ret = TRUE; + } + + TRKReleaseMutex(&gTRKEventQueue); + return ret; +} + +DSError TRKPostEvent(TRKEvent* event) +{ + DSError ret = DS_NoError; + int nextEventID; + + TRKAcquireMutex(&gTRKEventQueue); + + if (gTRKEventQueue.count == 2) { + ret = DS_EventQueueFull; + + } else { + nextEventID = (gTRKEventQueue.next + gTRKEventQueue.count) % 2; + TRK_memcpy(&gTRKEventQueue.events[nextEventID], event, sizeof(TRKEvent)); + gTRKEventQueue.events[nextEventID].eventID = gTRKEventQueue.eventID; + + if (++gTRKEventQueue.eventID < 0x100) { + gTRKEventQueue.eventID = 0x100; + } + + gTRKEventQueue.count++; + } + + TRKReleaseMutex(&gTRKEventQueue); + return ret; +} + +void TRKConstructEvent(TRKEvent* event, int eventType) +{ + event->eventType = eventType; + event->eventID = 0; + event->msgBufID = -1; +} + +void TRKDestructEvent(TRKEvent* event) +{ + TRKReleaseBuffer(event->msgBufID); +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/nubinit.c b/src/static/TRK_MINNOW_DOLPHIN/nubinit.c new file mode 100644 index 00000000..9895a80a --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/nubinit.c @@ -0,0 +1,74 @@ +#include "TRK/trk.h" + +BOOL gTRKBigEndian; + +DSError TRKInitializeNub(void) +{ + DSError ret; + DSError uartErr; + + ret = TRKInitializeEndian(); + + MWTRACE(1, "Initialize NUB\n"); + if (ret == DS_NoError) { + usr_put_initialize(); + } + if (ret == DS_NoError) { + ret = TRKInitializeEventQueue(); + } + if (ret == DS_NoError) { + ret = TRKInitializeMessageBuffers(); + } + if (ret == DS_NoError) { + ret = TRKInitializeDispatcher(); + } + InitializeProgramEndTrap(); + if (ret == DS_NoError) { + ret = TRKInitializeSerialHandler(); + } + if (ret == DS_NoError) { + ret = TRKInitializeTarget(); + } + if (ret == DS_NoError) { + + uartErr = TRKInitializeIntDrivenUART(0x0000e100, 1, 0, &gTRKInputPendingPtr); + TRKTargetSetInputPendingPtr(gTRKInputPendingPtr); + if (uartErr != DS_NoError) { + ret = uartErr; + } + } + return ret; +} + +DSError TRKTerminateNub(void) +{ + TRKTerminateSerialHandler(); + return DS_NoError; +} + +void TRKNubWelcome(void) +{ + TRK_board_display("MetroTRK for GAMECUBE v2.6"); //"MetroTRK for GAMECUBE v2.6" + return; +} + +BOOL TRKInitializeEndian(void) +{ + u8 bendian[4]; + BOOL result = FALSE; + gTRKBigEndian = TRUE; + + bendian[0] = 0x12; + bendian[1] = 0x34; + bendian[2] = 0x56; + bendian[3] = 0x78; + + if (*(u32*)bendian == 0x12345678) { + gTRKBigEndian = TRUE; + } else if (*(u32*)bendian == 0x78563412) { + gTRKBigEndian = FALSE; + } else { + result = TRUE; + } + return result; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/serpoll.c b/src/static/TRK_MINNOW_DOLPHIN/serpoll.c new file mode 100644 index 00000000..adaa3217 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/serpoll.c @@ -0,0 +1,91 @@ +#include "TRK/trk.h" + +static TRKFramingState gTRKFramingState; +void* gTRKInputPendingPtr; + +MessageBufferID TRKTestForPacket() +{ + u8 payloadBuf[0x880]; + u8 packetBuf[0x40]; + int bufID; + MessageBuffer* msg; + MessageBufferID result; + + if (TRKPollUART() <= 0) { + return -1; + } + + result = TRKGetFreeBuffer(&bufID, &msg); + + MWTRACE(4, "TestForPacket : FreeBuffer is %ld\n", result); + + TRKSetBufferPosition(msg, 0); + if (TRKReadUARTN(packetBuf, 0x40) == UART_NoError) { + int readSize; + + TRKAppendBuffer_ui8(msg, packetBuf, 0x40); + readSize = ((u32*)packetBuf)[0] - 0x40; + result = bufID; + if (readSize > 0) { + MWTRACE(1, "Reading payload %ld bytes\n", readSize); + if (TRKReadUARTN(payloadBuf, ((u32*)packetBuf)[0] - 0x40) == UART_NoError) { + TRKAppendBuffer_ui8(msg, payloadBuf, ((u32*)packetBuf)[0]); + } else { + MWTRACE(8, "TestForPacket : Invalid size of packet hdr.size\n"); + TRKReleaseBuffer(result); + result = -1; + } + } + } else { + MWTRACE(8, "TestForPacket : Invalid size of packet\n"); + TRKReleaseBuffer(result); + result = -1; + } + + MWTRACE(1, "TestForPacket returning %ld\n", result); + return result; +} + +void TRKGetInput(void) +{ + MessageBufferID id = TRKTestForPacket(); + if (id != -1) { + TRKEvent event; + TRKGetBuffer(id); + TRKConstructEvent(&event, NUBEVENT_Request); + event.msgBufID = id; + gTRKFramingState.msgBufID = -1; + TRKPostEvent(&event); + } +} + +void TRKProcessInput(int bufferIdx) +{ + TRKEvent event; + + TRKConstructEvent(&event, NUBEVENT_Request); + event.msgBufID = bufferIdx; + gTRKFramingState.msgBufID = -1; + TRKPostEvent(&event); +} + +DSError TRKInitializeSerialHandler() +{ + gTRKFramingState.msgBufID = -1; + gTRKFramingState.receiveState = DSRECV_Wait; + gTRKFramingState.isEscape = FALSE; + + MWTRACE(1, "TRK_Packet_Header \t %ld bytes\n", 0x40); + MWTRACE(1, "TRK_CMD_ReadMemory %ld bytes\n", 0x40); + MWTRACE(1, "TRK_CMD_WriteMemory %ld bytes\n", 0x40); + MWTRACE(1, "TRK_CMD_Connect \t %ld bytes\n", 0x40); + MWTRACE(1, "TRK_CMD_ReplyAck\t %ld bytes\n", 0x40); + MWTRACE(1, "TRK_CMD_ReadRegisters\t%ld bytes\n", 0x40); + + return DS_NoError; +} + +DSError TRKTerminateSerialHandler(void) +{ + return DS_NoError; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/support.c b/src/static/TRK_MINNOW_DOLPHIN/support.c new file mode 100644 index 00000000..1d2fa375 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/support.c @@ -0,0 +1,282 @@ +#include "TRK/trk.h" +DSError TRKSuppAccessFile(u32 file_handle, u8* data, size_t* count, DSIOResult* io_result, BOOL need_reply, BOOL read) +{ + DSError error; + int replyBufferId; + MessageBuffer* replyBuffer; + u32 length; + int bufferId; + MessageBuffer* buffer; + u32 i; + u8 replyIOResult; + u32 replyLength; + BOOL exit; + CommandReply reply; + + if (data == nullptr || *count == 0) { + return DS_ParameterError; + } + + exit = FALSE; + *io_result = DS_IONoError; + i = 0; + error = DS_NoError; + while (!exit && i < *count && error == DS_NoError && *io_result == 0) { + memset(&reply, 0, sizeof(CommandReply)); + + if (*count - i <= 0x800) { + length = *count - i; + } else { + length = 0x800; + } + + reply.commandID.b = read ? DSMSG_ReadFile : DSMSG_WriteFile; + + if (read) { + reply._00 = 0x40; + } else { + reply._00 = length + 0x40; + } + + reply.replyError.r = file_handle; + *(u16*)&reply._0C = length; + + TRKGetFreeBuffer(&bufferId, &buffer); + error = TRKAppendBuffer_ui8(buffer, (u8*)&reply, 0x40); + + if (!read && error == DS_NoError) { + error = TRKAppendBuffer_ui8(buffer, data + i, length); + } + + if (error == DS_NoError) { + if (need_reply) { + BOOL b = read && file_handle == 0; + + error = TRKRequestSend(buffer, &replyBufferId, read ? 5 : 5, 3, !b); + if (error == DS_NoError) { + replyBuffer = (MessageBuffer*)TRKGetBuffer(replyBufferId); + } + replyIOResult = *(u32*)(replyBuffer->data + 0x10); + replyLength = *(u16*)(replyBuffer->data + 0x14); + if (read && error == DS_NoError && replyLength <= length) { + TRKSetBufferPosition(replyBuffer, 0x40); + error = TRKReadBuffer_ui8(replyBuffer, data + i, replyLength); + if (error == DS_MessageBufferReadError) { + error = DS_NoError; + } + } + + if (replyLength != length) { + length = replyLength; + exit = TRUE; + } + + *io_result = (DSIOResult)replyIOResult; + TRKReleaseBuffer(replyBufferId); + } else { + error = TRKMessageSend(buffer); + } + } + + TRKReleaseBuffer(bufferId); + i += length; + } + + *count = i; + return error; +} + +DSError TRKRequestSend(MessageBuffer* msgBuf, int* bufferId, u32 p1, u32 p2, int p3) +{ + int error = DS_NoError; + MessageBuffer* buffer; + u32 counter; + int count; + u8 msgCmd; + int msgReplyError; + BOOL badReply = TRUE; + + *bufferId = -1; + + for (count = p2 + 1; count != 0 && *bufferId == -1 && error == DS_NoError; count--) { + MWTRACE(1, "Calling MessageSend\n"); + error = TRKMessageSend(msgBuf); + if (error == DS_NoError) { + + if (p3) { + counter = 0; + } + + while (TRUE) { + do { + *bufferId = TRKTestForPacket(); + if (*bufferId != -1) + break; + } while (!p3 || ++counter < 79999980); + + if (*bufferId == -1) + break; + + badReply = 0; + + buffer = TRKGetBuffer(*bufferId); + TRKSetBufferPosition(buffer, 0); + OutputData(&buffer->data[0], buffer->length); + msgCmd = buffer->data[4]; + MWTRACE(1, "msg_command : 0x%02x hdr->cmdID 0x%02x\n", msgCmd, msgCmd); + + if (msgCmd >= DSMSG_ReplyACK) + break; + + TRKProcessInput(*bufferId); + *bufferId = -1; + } + + if (*bufferId != -1) { + if (buffer->length < 0x40) { + // OSReport("MetroTRK - bad reply size %ld\n", buffer->length); + badReply = TRUE; + } + if (error == DS_NoError && !badReply) { + msgReplyError = buffer->data[8]; + MWTRACE(1, "msg_error : 0x%02x\n", msgReplyError); + } + if (error == DS_NoError && !badReply) { + if ((int)msgCmd != DSMSG_ReplyACK || msgReplyError != DSREPLY_NoError) { + MWTRACE(8, "RequestSend : Bad ack or non ack received msg_command : 0x%02x msg_error 0x%02x\n", msgCmd, + msgReplyError); + badReply = TRUE; + } + } + if (error != DS_NoError || badReply) { + TRKReleaseBuffer(*bufferId); + *bufferId = -1; + } + } + } + } + + if (*bufferId == -1) { + error = DS_Error800; + } + + return error; +} + +DSError HandleOpenFileSupportRequest(const char* path, u8 replyError, u32* param_3, DSIOResult* ioResult) +{ + DSError error; + int bufferId2; + int bufferId1; + MessageBuffer* tempBuffer; + MessageBuffer* buffer; + CommandReply reply; + + memset(&reply, 0, sizeof(CommandReply)); + *param_3 = 0; + reply.commandID.b = DSMSG_OpenFile; + reply._00 = strlen(path) + 0x40 + 1; + reply.replyError.b = replyError; + *(u16*)&reply._0C = strlen(path) + 1; + TRKGetFreeBuffer(&bufferId1, &buffer); + error = TRKAppendBuffer_ui8(buffer, (u8*)&reply, 0x40); + + if (error == DS_NoError) { + error = TRKAppendBuffer_ui8(buffer, (u8*)path, strlen(path) + 1); + } + + if (error == DS_NoError) { + *ioResult = DS_IONoError; + error = TRKRequestSend(buffer, &bufferId2, 7, 3, 0); + + if (error == DS_NoError) { + tempBuffer = TRKGetBuffer(bufferId2); + } + + *ioResult = *(u32*)(tempBuffer->data + 0x10); + *param_3 = *(u32*)(tempBuffer->data + 0x8); + TRKReleaseBuffer(bufferId2); + } + TRKReleaseBuffer(bufferId1); + return error; +} + +DSError HandleCloseFileSupportRequest(int replyError, DSIOResult* ioResult) +{ + DSError error; + int replyBufferId; + int bufferId; + MessageBuffer* buffer1; + MessageBuffer* buffer2; + CommandReply reply; + + memset(&reply, 0, sizeof(CommandReply)); + reply.commandID.b = DSMSG_CloseFile; + reply._00 = 0x40; + reply.replyError.r = replyError; + error = TRKGetFreeBuffer(&bufferId, &buffer1); + + if (error == DS_NoError) { + error = TRKAppendBuffer_ui8(buffer1, (u8*)&reply, sizeof(CommandReply)); + } + + if (error == DS_NoError) { + *ioResult = DS_IONoError; + error = TRKRequestSend(buffer1, &replyBufferId, 3, 3, 0); + + if (error == DS_NoError) { + buffer2 = TRKGetBuffer(replyBufferId); + } + + if (error == DS_NoError) { + *ioResult = *(u32*)(buffer2->data + 0x10); + } + + TRKReleaseBuffer(replyBufferId); + } + + TRKReleaseBuffer(bufferId); + return error; +} + +DSError HandlePositionFileSupportRequest(DSReplyError replyErr, u32* param_2, u8 param_3, DSIOResult* ioResult) +{ + DSError error; + int bufferId2; + int bufferId1; + MessageBuffer* buffer1; + MessageBuffer* buffer2; + CommandReply reply; + + memset(&reply, 0, sizeof(CommandReply)); + reply.commandID.b = DSMSG_PositionFile; + reply._00 = 0x40; + reply.replyError.r = replyErr; + reply._0C = *param_2; + reply._10[0] = param_3; + error = TRKGetFreeBuffer(&bufferId1, &buffer1); + + if (error == DS_NoError) { + error = TRKAppendBuffer_ui8(buffer1, (u8*)&reply, sizeof(CommandReply)); + } + + if (error == DS_NoError) { + *ioResult = DS_IONoError; + *param_2 = -1; + error = TRKRequestSend(buffer1, &bufferId2, 3, 3, 0); + + if (error == DS_NoError) { + buffer2 = TRKGetBuffer(bufferId2); + + if (buffer2 != nullptr) { + *ioResult = *(u32*)(buffer2->data + 0x10); + *param_2 = *(u32*)(buffer2->data + 0x18); + } + } + + TRKReleaseBuffer(bufferId2); + } + + TRKReleaseBuffer(bufferId1); + return error; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/targcont.c b/src/static/TRK_MINNOW_DOLPHIN/targcont.c new file mode 100644 index 00000000..48b61fe5 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/targcont.c @@ -0,0 +1,10 @@ +#include "TRK/trk.h" + +DSError TRKTargetContinue(void) +{ + TRKTargetSetStopped(0); + UnreserveEXI2Port(); + TRKSwapAndGo(); + ReserveEXI2Port(); + return DS_NoError; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/target_options.c b/src/static/TRK_MINNOW_DOLPHIN/target_options.c new file mode 100644 index 00000000..5deb3912 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/target_options.c @@ -0,0 +1,14 @@ +#include "TRK/trk.h" + +static u8 bUseSerialIO; + +void SetUseSerialIO(u8 sio) +{ + bUseSerialIO = sio; + return; +} + +u8 GetUseSerialIO(void) +{ + return bUseSerialIO; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/targimpl.c b/src/static/TRK_MINNOW_DOLPHIN/targimpl.c new file mode 100644 index 00000000..56cd5584 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/targimpl.c @@ -0,0 +1,1184 @@ +#include "TRK/ppc_reg.h" +#include "TRK/trktypes.h" +#include "TRK/trkenum.h" +#include "TRK/dstypes.h" +#include "TRK/memmap.h" + +extern void TRKUARTInterruptHandler(void); // should probably go in a header + +typedef struct StopInfo_PPC { + u32 PC; + u32 PCInstruction; + u16 exceptionID; +} StopInfo_PPC; + +typedef struct TRKExceptionStatus { + StopInfo_PPC exceptionInfo; + u8 inTRK; + u8 exceptionDetected; +} TRKExceptionStatus; + +typedef struct TRKStepStatus { + BOOL active; // 0x0 + DSMessageStepOptions type; // 0x4 + u32 count; // 0x8 + u32 rangeStart; // 0xC + u32 rangeEnd; // 0x10 +} TRKStepStatus; + +ProcessorRestoreFlags_PPC gTRKRestoreFlags = { FALSE, FALSE }; + +static TRKExceptionStatus gTRKExceptionStatus = { { 0, 0, 0 }, TRUE, 0 }; + +static TRKStepStatus gTRKStepStatus = { FALSE, DSSTEP_IntoCount, 0, 0 }; + +typedef void (*RegAccessFunc)(void* srcDestPtr, u128 val); + +static void TRKExceptionHandler(u16); +void TRKInterruptHandlerEnableInterrupts(); +static void GetThreadInfo(int*, int*); +DSError TRKPPCAccessSPR(void* srcDestPtr, u32 spr, BOOL read); +DSError TRKPPCAccessPairedSingleRegister(void* srcDestPtr, u32 psr, BOOL read); +DSError TRKPPCAccessSpecialReg(void* srcDestPtr, u32* instructionData, BOOL read); +DSError TRKPPCAccessFPRegister(void* srcDestPtr, u32 fpr, BOOL read); +void WriteFPSCR(f64*); +void ReadFPSCR(f64*); + +static u16 TRK_saved_exceptionID = 0; +TRKState gTRKState; +Default_PPC gTRKSaveState; +ProcessorState_PPC gTRKCPUState; +u128 TRKvalue128_temp; + +// Instruction macros +#define INSTR_NOP 0x60000000 +#define INSTR_BLR 0x4E800020 +#define INSTR_PSQ_ST(psr, offset, rDest, w, gqr) (0xF0000000 | (psr << 21) | (rDest << 16) | (w << 15) | (gqr << 12) | offset) +#define INSTR_PSQ_L(psr, offset, rSrc, w, gqr) (0xE0000000 | (psr << 21) | (rSrc << 16) | (w << 15) | (gqr << 12) | offset) +#define INSTR_STW(rSrc, offset, rDest) (0x90000000 | (rSrc << 21) | (rDest << 16) | offset) +#define INSTR_LWZ(rDest, offset, rSrc) (0x80000000 | (rDest << 21) | (rSrc << 16) | offset) +#define INSTR_STFD(fprSrc, offset, rDest) (0xD8000000 | (fprSrc << 21) | (rDest << 16) | offset) +#define INSTR_LFD(fprDest, offset, rSrc) (0xC8000000 | (fprDest << 21) | (rSrc << 16) | offset) +#define INSTR_MFSPR(rDest, spr) (0x7C000000 | (rDest << 21) | ((spr & 0xFE0) << 6) | ((spr & 0x1F) << 16) | 0x2A6) +#define INSTR_MTSPR(spr, rSrc) (0x7C000000 | (rSrc << 21) | ((spr & 0xFE0) << 6) | ((spr & 0x1F) << 16) | 0x3A6) + +#define DSFetch_u32(_p_) (*((u32*)_p_)) +#define DSFetch_u64(_p_) (*((u64*)_p_)) + +void __TRK_set_MSR(register u32 msr); +u32 __TRK_get_MSR(); +void TRK_ppc_memcpy(register void* dest, register const void* src, register int n, register u32 param_4, register u32 param_5); + +DSError TRKValidMemory32(const void* addr, size_t length, ValidMemoryOptions readWriteable) +{ + DSError err = DS_InvalidMemory; /* assume range is invalid */ + + const u8* start; + const u8* end; + + s32 i; + + /* + ** Get start and end addresses for the memory range and + ** verify that they are reasonable. + */ + + start = (const u8*)addr; + end = ((const u8*)addr + (length - 1)); + + if (end < start) + return DS_InvalidMemory; + + /* + ** Iterate through the gTRKMemMap array to determine if the requested + ** range falls within the valid ranges in the map. + */ + + for (i = 0; (i < (s32)(sizeof(gTRKMemMap) / sizeof(memRange))); i++) { + /* + ** If the requested range is not completely above + ** the valid range AND it is not completely below + ** the valid range then it must overlap somewhere. + ** If the requested range overlaps with one of the + ** valid ranges, do some additional checking. + ** + */ + + if ((start <= (const u8*)gTRKMemMap[i].end) && (end >= (const u8*)gTRKMemMap[i].start)) { + /* + ** First, verify that the read/write attributes are + ** acceptable. If so, then recursively check any + ** part of the requested range that falls before or + ** after the valid range. + */ + + if (((readWriteable == VALIDMEM_Readable) && !gTRKMemMap[i].readable) + || ((readWriteable == VALIDMEM_Writeable) && !gTRKMemMap[i].writeable)) { + err = DS_InvalidMemory; + } else { + err = DS_NoError; + + /* + ** If a portion of the requested range falls before + ** the current valid range, then recursively + ** check it. + */ + + if (start < (const u8*)gTRKMemMap[i].start) + err = TRKValidMemory32(start, (u32)((const u8*)gTRKMemMap[i].start - start), readWriteable); + + /* + ** If a portion of the requested range falls after + ** the current valid range, then recursively + ** check it. + ** Note: Only do this step if the previous check + ** did not detect invalid access. + */ + + if ((err == DS_NoError) && (end > (const u8*)gTRKMemMap[i].end)) + err = TRKValidMemory32((const u8*)gTRKMemMap[i].end, (u32)(end - (const u8*)gTRKMemMap[i].end), readWriteable); + } + + break; + } + } + + return err; +} + +DSError TRKTargetAccessMemory(void* data, u32 start, size_t* length, MemoryAccessOptions accessOptions, BOOL read) +{ + DSError error; + u32 uVar5; + void* addr; + u32 param4; + TRKExceptionStatus tempExceptionStatus = gTRKExceptionStatus; + gTRKExceptionStatus.exceptionDetected = FALSE; + + addr = (void*)TRKTargetTranslate(start); + error = TRKValidMemory32(addr, *length, read == FALSE); + + if (error != DS_NoError) { + *length = 0; + } else { + uVar5 = __TRK_get_MSR(); + param4 = uVar5 | gTRKCPUState.Extended1.MSR & 0x10; + + if (read) { + TRK_ppc_memcpy(data, addr, *length, uVar5, param4); + } else { + TRK_ppc_memcpy(addr, data, *length, param4, uVar5); + TRK_flush_cache((u32)addr, *length); + if ((void*)start != addr) { + TRK_flush_cache(start, *length); + } + } + } + + if (gTRKExceptionStatus.exceptionDetected) { + *length = 0; + error = DS_CWDSException; + } + + gTRKExceptionStatus = tempExceptionStatus; + return error; +} + +DSError TRKTargetReadInstruction(void* data, u32 start) +{ + DSError error; + size_t registersLength = 4; + + error = TRKTargetAccessMemory(data, start, ®istersLength, MEMACCESS_UserMemory, TRUE); + + if (error == DS_NoError && registersLength != 4) { + error = DS_InvalidMemory; + } + + return error; +} + +DSError TRKTargetAccessDefault(u32 firstRegister, u32 lastRegister, MessageBuffer* b, size_t* registersLengthPtr, BOOL read) +{ + DSError error; + u32 count; + u32* data; + TRKExceptionStatus tempExceptionStatus; + + if (lastRegister > 0x24) { + return DS_InvalidRegister; + } + + tempExceptionStatus = gTRKExceptionStatus; + gTRKExceptionStatus.exceptionDetected = FALSE; + + data = gTRKCPUState.Default.GPR + firstRegister; + count = (lastRegister - firstRegister) + 1; + *registersLengthPtr = count * sizeof(u32); + + if (read) { + error = TRKAppendBuffer_ui32(b, data, count); + } else { + error = TRKReadBuffer_ui32(b, data, count); + } + + if (gTRKExceptionStatus.exceptionDetected) { + *registersLengthPtr = 0; + error = DS_CWDSException; + } + + gTRKExceptionStatus = tempExceptionStatus; + return error; +} + +DSError TRKTargetAccessFP(u32 firstRegister, u32 lastRegister, MessageBuffer* b, size_t* registersLengthPtr, BOOL read) +{ + u64 temp; + DSError error; + TRKExceptionStatus tempExceptionStatus; + u32 current; + + if (lastRegister > 0x21) { + return DS_InvalidRegister; + } + + tempExceptionStatus = gTRKExceptionStatus; + gTRKExceptionStatus.exceptionDetected = FALSE; + + __TRK_set_MSR(__TRK_get_MSR() | 0x2000); + + *registersLengthPtr = 0; + error = DS_NoError; + + for (current = firstRegister; (current <= lastRegister) && (error == DS_NoError); current++, *registersLengthPtr += sizeof(f64)) { + if (read) { + TRKPPCAccessFPRegister(&temp, current, read); + error = TRKAppendBuffer1_ui64(b, temp); + } else { + TRKReadBuffer1_ui64(b, &temp); + error = TRKPPCAccessFPRegister(&temp, current, read); + } + } + + if (gTRKExceptionStatus.exceptionDetected) { + *registersLengthPtr = 0; + error = DS_CWDSException; + } + + gTRKExceptionStatus = tempExceptionStatus; + return error; +} + +DSError TRKTargetAccessExtended1(u32 firstRegister, u32 lastRegister, MessageBuffer* b, size_t* registersLengthPtr, BOOL read) +{ + TRKExceptionStatus tempExceptionStatus; + int error; + u32* data; + int count; + + if (lastRegister > 0x60) { + return DS_InvalidRegister; + } + + tempExceptionStatus = gTRKExceptionStatus; + gTRKExceptionStatus.exceptionDetected = FALSE; + + *registersLengthPtr = 0; + + if (firstRegister <= lastRegister) { + data = (u32*)&gTRKCPUState.Extended1 + firstRegister; + count = lastRegister - firstRegister + 1; + *registersLengthPtr += count * sizeof(u32); + + if (read) { + error = TRKAppendBuffer_ui32(b, data, count); + } else { + + if (data <= &gTRKCPUState.Extended1.TBU && (data + count - 1) >= &gTRKCPUState.Extended1.TBL) { + gTRKRestoreFlags.TBR = 1; + } + + if (data <= &gTRKCPUState.Extended1.DEC && (data + count - 1) >= &gTRKCPUState.Extended1.DEC) { + gTRKRestoreFlags.DEC = 1; + } + error = TRKReadBuffer_ui32(b, data, count); + } + } + if (gTRKExceptionStatus.exceptionDetected) { + *registersLengthPtr = 0; + error = DS_CWDSException; + } + + gTRKExceptionStatus = tempExceptionStatus; + return error; +} + +DSError TRKTargetAccessExtended2(u32 firstRegister, u32 lastRegister, MessageBuffer* b, size_t* registerStorageSize, BOOL read) +{ + TRKExceptionStatus savedException; + u32 i; + u32 value_buf0[1]; + u32 value_buf[2]; + DSError err; + u32 access_func[10]; + + if (lastRegister > 0x1f) + return DS_InvalidRegister; + + /* + ** Save any existing exception status and clear the exception flag. + ** This allows detection of exceptions that occur ONLY within this + ** function. + */ + + savedException = gTRKExceptionStatus; + gTRKExceptionStatus.exceptionDetected = FALSE; + + TRKPPCAccessSPR(value_buf0, SPR_HID2, TRUE); + + value_buf0[0] |= 0xA0000000; + TRKPPCAccessSPR(value_buf0, SPR_HID2, FALSE); + + value_buf0[0] = 0; + TRKPPCAccessSPR(value_buf0, SPR_GQR0, FALSE); + + *registerStorageSize = 0; + err = DS_NoError; + + for (i = firstRegister; (i <= lastRegister) && (err == DS_NoError); i++) { + + if (read) { + err = TRKPPCAccessPairedSingleRegister((u64*)value_buf, i, read); + err = TRKAppendBuffer1_ui64(b, *(u64*)value_buf); + } else { + err = TRKReadBuffer1_ui64(b, (u64*)value_buf); + err = TRKPPCAccessPairedSingleRegister((u64*)value_buf, i, read); + } + + *registerStorageSize += sizeof(u64); + } + + if (gTRKExceptionStatus.exceptionDetected) { + *registerStorageSize = 0; + err = DS_CWDSException; + } + + gTRKExceptionStatus = savedException; + + return err; +} + +void TRKTargetVersions(void) +{ + // UNUSED FUNCTION +} + +void TRKTargetSupportMask(void) +{ + // UNUSED FUNCTION +} + +void TRKTargetCPUType(void) +{ + // UNUSED FUNCTION +} + +void TRKTargetCheckException(void) +{ + // UNUSED FUNCTION +} + +void TRKPostInterruptEvent(void) +{ + int eventType; + int local_14; + size_t registerSize; + TRKEvent event; + + if (gTRKState.inputActivated) { + gTRKState.inputActivated = FALSE; + } else { + switch (gTRKCPUState.Extended1.exceptionID & 0xFFFF) { + case 0xd00: + case 0x700: + registerSize = 4; + TRKTargetReadInstruction(&local_14, gTRKCPUState.Default.PC); + + if (local_14 == 0xfe00000) { + eventType = NUBEVENT_Support; + } else { + eventType = NUBEVENT_Breakpoint; + } + break; + default: + eventType = NUBEVENT_Exception; + break; + } + + TRKConstructEvent(&event, eventType); + TRKPostEvent(&event); + } +} + +DSError TRKTargetInterrupt(TRKEvent* event) +{ + DSError error = DS_NoError; + switch (event->eventType) { + case NUBEVENT_Breakpoint: + case NUBEVENT_Exception: + if (TRKTargetCheckStep() == FALSE) { + TRKTargetSetStopped(TRUE); + error = TRKDoNotifyStopped(DSMSG_NotifyStopped); + } + break; + default: + break; + } + + return error; +} + +u32* ConvertAddress(u32 addr) +{ + return (u32*)(addr | 0x80000000); +} +DSError TRKTargetAddStopInfo(MessageBuffer* b) +{ + DSError error; + CommandReply reply; + int t; + + memset(&reply, 0, 0x40); + reply._00 = 0x40; + reply.commandID.b = 0x90; + reply.replyError.r = gTRKCPUState.Default.PC; + TRKTargetReadInstruction(&t, gTRKCPUState.Default.PC); + + reply._0C = t; + *(u32*)reply._10 = gTRKCPUState.Extended1.exceptionID & 0xFFFF; + error = TRKAppendBuffer_ui8(b, (u8*)&reply, 0x40); + return error; +} + +void TRKTargetAddExceptionInfo(MessageBuffer* b) +{ + size_t local_58; + u32 local_54; + CommandReply reply; + + memset(&reply, 0, 0x40); + + reply._00 = 0x40; + reply.commandID.b = 0x91; + reply.replyError.r = gTRKExceptionStatus.exceptionInfo.PC; + + TRKTargetReadInstruction(&local_54, gTRKExceptionStatus.exceptionInfo.PC); + + reply._0C = local_54; + *(u32*)reply._10 = gTRKExceptionStatus.exceptionInfo.exceptionID; + + TRKAppendBuffer_ui8(b, (u8*)&reply, 0x40); +} + +inline DSError TRKTargetEnableTrace(BOOL val) +{ + if (val) { + gTRKCPUState.Extended1.MSR = (gTRKCPUState.Extended1.MSR | 0x400); + } else { + gTRKCPUState.Extended1.MSR = (gTRKCPUState.Extended1.MSR & ~0x400); + } + return DS_NoError; +} + +BOOL TRKTargetStepDone() +{ + BOOL result = TRUE; + + if (gTRKStepStatus.active && ((u16)gTRKCPUState.Extended1.exceptionID) == PPC_Trace) { + switch (gTRKStepStatus.type) { + case DSSTEP_IntoCount: + if (gTRKStepStatus.count > 0) { + result = FALSE; + } + break; + case DSSTEP_IntoRange: + if (gTRKCPUState.Default.PC >= gTRKStepStatus.rangeStart && gTRKCPUState.Default.PC <= gTRKStepStatus.rangeEnd) { + result = FALSE; + } + break; + default: + break; + } + } + + return result; +} + +inline DSError TRKTargetDoStep() +{ + gTRKStepStatus.active = TRUE; + MWTRACE(1, "TargetDoStep()\n"); + TRKTargetEnableTrace(TRUE); + + if (gTRKStepStatus.type == DSSTEP_IntoCount || gTRKStepStatus.type == DSSTEP_OverCount) { + gTRKStepStatus.count--; + } + + TRKTargetSetStopped(FALSE); + return DS_NoError; +} + +static BOOL TRKTargetCheckStep() +{ + if (gTRKStepStatus.active) { + TRKTargetEnableTrace(FALSE); + + if (TRKTargetStepDone()) { + gTRKStepStatus.active = FALSE; + } else { + TRKTargetDoStep(); + } + } + + return gTRKStepStatus.active; +} + +DSError TRKTargetSingleStep(u32 count, BOOL stepOver) +{ + DSError error = DS_NoError; + + if (stepOver) { + error = DS_UnsupportedError; + } else { + gTRKStepStatus.count = count; + gTRKStepStatus.type = DSSTEP_IntoCount; + error = TRKTargetDoStep(); + } + + return error; +} + +DSError TRKTargetStepOutOfRange(u32 rangeStart, u32 rangeEnd, BOOL stepOver) +{ + DSError error = DS_NoError; + + if (stepOver) { + // Stepping over isn't supported for PowerPC + error = DS_UnsupportedError; + } else { + gTRKStepStatus.type = DSSTEP_IntoRange; + // gTRKStepStatus.active = TRUE; + gTRKStepStatus.rangeStart = rangeStart; + gTRKStepStatus.rangeEnd = rangeEnd; + error = TRKTargetDoStep(); + } + + return error; +} + +u32 TRKTargetGetPC(void) +{ + return gTRKCPUState.Default.PC; +} + + +DSError TRKTargetSupportRequest() +{ + DSIOResult ioResult; + size_t* length; + MessageCommandID commandId; + DSError error; + u32 local_28; + TRKEvent event; + + commandId = gTRKCPUState.Default.GPR[3]; + if (commandId != DSMSG_ReadFile && commandId != DSMSG_WriteFile && commandId != DSMSG_OpenFile && commandId != DSMSG_CloseFile + && commandId != DSMSG_PositionFile) { + TRKConstructEvent(&event, 4); + TRKPostEvent(&event); + return DS_NoError; + } else if (commandId == DSMSG_OpenFile) { + error = HandleOpenFileSupportRequest(gTRKCPUState.Default.GPR[4], gTRKCPUState.Default.GPR[5] & 0xff, gTRKCPUState.Default.GPR[6], + &ioResult); + + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + + gTRKCPUState.Default.GPR[3] = ioResult; + } else if (commandId == DSMSG_CloseFile) { + error = HandleCloseFileSupportRequest(gTRKCPUState.Default.GPR[4], &ioResult); + + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + + gTRKCPUState.Default.GPR[3] = ioResult; + } else if (commandId == DSMSG_PositionFile) { + local_28 = *(u32*)gTRKCPUState.Default.GPR[5]; + error = HandlePositionFileSupportRequest(gTRKCPUState.Default.GPR[4], &local_28, (u8)gTRKCPUState.Default.GPR[6], &ioResult); + + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + + gTRKCPUState.Default.GPR[3] = ioResult; + *(u32*)gTRKCPUState.Default.GPR[5] = local_28; + } else { + length = (size_t*)gTRKCPUState.Default.GPR[5]; + error = TRKSuppAccessFile(gTRKCPUState.Default.GPR[4], (u8*)gTRKCPUState.Default.GPR[6], length, &ioResult, TRUE, + commandId == DSMSG_ReadFile); + + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + + gTRKCPUState.Default.GPR[3] = ioResult; + + if (commandId == DSMSG_ReadFile) { + TRK_flush_cache(gTRKCPUState.Default.GPR[6], *length); + } + } + + gTRKCPUState.Default.PC += 4; + return error; +} + +void TRKTargetFlushCache(void) +{ + // UNUSED FUNCTION +} + +BOOL TRKTargetStopped(void) +{ + return gTRKState.isStopped; +} + +void TRKTargetSetStopped(uint stopped) +{ + gTRKState.isStopped = stopped; +} + +BOOL TRKTargetStop() +{ + gTRKState.isStopped = 1; + return FALSE; +} + +DSError TRKPPCAccessSPR(void* value, u32 spr_register_num, BOOL read) +{ + /* Initialize instruction array with nop */ + + u32 access_func[10] = { INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP }; + /* + ** Construct a small assembly function to perform the + ** requested access and call it. The read/write function + ** is in the form: + ** + ** read: + ** mfspr r4, spr_register_num + ** stw r4, 0(r3) + ** blr + ** + ** write: + ** lwz r4, 0(r3) + ** mtspr spr_register_num, r4 + ** blr + ** + */ + + if (read) { + access_func[0] = INSTR_MFSPR(4, spr_register_num); + access_func[1] = (u32)INSTR_STW(4, 0, 3); + } else { + access_func[0] = (u32)INSTR_LWZ(4, 0, 3); + access_func[1] = INSTR_MTSPR(spr_register_num, 4); + } + + return TRKPPCAccessSpecialReg(value, access_func, read); +} + +DSError TRKPPCAccessPairedSingleRegister(void* srcDestPtr, u32 psr, BOOL read) +{ + // all nop by default + u32 instructionData[] + = { INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP }; + + if (read) { + instructionData[0] = INSTR_PSQ_ST(psr, 0, 3, 0, 0); // psq_st psr, 0(r3), 0, 0 + } else { + instructionData[0] = INSTR_PSQ_L(psr, 0, 3, 0, 0); // psq_l psr, 0(r3), 0, 0 + } + + return TRKPPCAccessSpecialReg(srcDestPtr, instructionData, read); +} + +DSError TRKPPCAccessFPRegister(void* srcDestPtr, u32 fpr, BOOL read) +{ + DSError error = DS_NoError; + // all nop by default + u32 instructionData1[] + = { INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP }; + + if (fpr < 0x20) { + if (read) { + instructionData1[0] = INSTR_STFD(fpr, 0, 3); // stfd fpr, 0(r3) + } else { + instructionData1[0] = INSTR_LFD(fpr, 0, 3); // lfd fpr, 0(r3) + } + + error = TRKPPCAccessSpecialReg(srcDestPtr, instructionData1, read); + } else if (fpr == 0x20) { + if (read) { + ReadFPSCR(srcDestPtr); + } else { + WriteFPSCR(srcDestPtr); + } + + *(u64*)srcDestPtr &= 0xFFFFFFFF; + } else if (fpr == 0x21) { + if (!read) { + *(u32*)srcDestPtr = *((u32*)(srcDestPtr) + 1); + } + + error = TRKPPCAccessSPR(srcDestPtr, SPR_FPECR, read); + if (read) { + DSFetch_u64(srcDestPtr) = DSFetch_u32(srcDestPtr) & 0xffffffffLL; + } + } + + return error; +} + +#define DEBUG_VECTORREG_ACCESS 0 + +DSError TRKPPCAccessSpecialReg(void* value, u32* access_func, BOOL read) +{ +#if defined(__MWERKS__) +#pragma unused(read) +#elif defined(__GNUC__) + UNUSED(read); +#endif + + typedef void (*asm_access_type)(void*, void*); + + asm_access_type asm_access; + + /* + ** Construct a small assembly function to perform the + ** requested access and call it. The read/write function + ** is in the form: + ** + ** + ** blr + */ + + /* + ** Put blr instruction at the end of access function (it should be + ** a 5-instruction array w/the last one empty). + */ + + access_func[9] = INSTR_BLR; + + /* + ** Now that the instruction array is built, get a function pointer to it. + */ + + asm_access = (asm_access_type)access_func; + +#if DEBUG_VECTORREG_ACCESS + + __puts("\r\nasm_access: "); + __puthex8((u32)asm_access); + __puts(" access_func: "); + __puthex8((u32)access_func); + + for (i = 0; i < 10; i++) { + __puts("\r\ninst["); + __puthex2(i); + __puts("]: "); + __puthex8(access_func[i]); + __puts(" ; "); + __puthex8(*((u32*)asm_access + i)); + } + + __puts("\r\n"); + +#endif + + // Flush cache + TRK_flush_cache((u32)access_func, (sizeof(access_func) * 10)); + (*asm_access)((u32*)value, (void*)&TRKvalue128_temp); + + return DS_NoError; +} + +void TRKTargetSetInputPendingPtr(void* ptr) +{ + gTRKState.inputPendingPtr = ptr; +} + +void SetInputState(void) +{ + // UNUSED FUNCTION +} + +void TRKGetInTRKFlag(void) +{ + // UNUSED FUNCTION +} + +DSError TRKTargetAccessARAM(u32 p1, u32 p2, u32* p3, BOOL read) +{ + DSError err; + TRKExceptionStatus status; + + err = DS_NoError; + status = gTRKExceptionStatus; + + gTRKExceptionStatus.exceptionDetected = 0; + + if (read) { + TRK__read_aram(p1, p2, p3); + } else { + TRK__write_aram(p1, p2, p3); + } + + if (gTRKExceptionStatus.exceptionDetected) { + *p3 = 0; + err = 0x702; + } + gTRKExceptionStatus = status; + return err; +} + +#ifdef __MWERKS__ // clang-format off +asm u32 __TRK_get_MSR(void) +{ + nofralloc + mfmsr r3 + blr +} +#endif // clang-format on + +#ifdef __MWERKS__ // clang-format off +asm void __TRK_set_MSR(register u32 v) +{ + mtmsr v + blr +} +#endif // clang-format on + +#ifdef __MWERKS__ // clang-format off +static asm void TRK_ppc_memcpy(register void* dest, register const void* src, register int n, register u32 param_4, register u32 param_5) +{ + #define msr r8 + #define byte r9 + #define count r10 + nofralloc + + mfmsr msr + li count, 0 + + top_loop: + cmpw count, n + beq out_loop + + mtmsr param_5 + sync + + lbzx byte, count, src + + mtmsr param_4 + sync + + stbx byte, count, dest + + addi count, count, 1 + + b top_loop + out_loop: + mtmsr msr + sync + + blr + #undef count + #undef byte + #undef msr +} +#endif // clang-format on + +#ifdef __MWERKS__ // clang-format off +asm void TRKInterruptHandler() +{ + nofralloc + mtsrr0 r2 + mtsrr1 r4 + mfsprg r4, 3 + mfcr r2 + mtsprg 3, r2 + lis r2, gTRKState@h + ori r2, r2, gTRKState@l + lwz r2, TRKState_PPC.MSR(r2) + ori r2, r2, 0x8002 + xori r2, r2, 0x8002 + sync + mtmsr r2 + sync + lis r2, TRK_saved_exceptionID@h + ori r2, r2, TRK_saved_exceptionID@l + sth r3, 0(r2) + cmpwi r3, 0x500 + bne L_802CF694 + lis r2, gTRKCPUState@h + ori r2, r2, gTRKCPUState@l + mflr r3 + stw r3, ProcessorState_PPC.transport_handler_saved_ra(r2) + bl TRKUARTInterruptHandler + lis r2, gTRKCPUState@h + ori r2, r2, gTRKCPUState@l + lwz r3, ProcessorState_PPC.transport_handler_saved_ra(r2) + mtlr r3 + lis r2, gTRKState@h + ori r2, r2, gTRKState@l + lwz r2, TRKState_PPC.inputPendingPtr(r2) + lbz r2, TRKState_PPC.GPR[0](r2) + cmpwi r2, 0 + beq L_802CF678 + lis r2, gTRKExceptionStatus@h + ori r2, r2, gTRKExceptionStatus@l + lbz r2, TRKExceptionStatus.inTRK(r2) + cmpwi r2, 1 + beq L_802CF678 + lis r2, gTRKState@h + ori r2, r2, gTRKState@l + li r3, 1 + stb r3, TRKState_PPC.inputActivated(r2) + b L_802CF694 +L_802CF678: + lis r2, gTRKSaveState@h + ori r2, r2, gTRKSaveState@l + lwz r3, Default_PPC.CR(r2) + mtcrf 0xff, r3 + lwz r3, Default_PPC.GPR[3](r2) + lwz r2, Default_PPC.GPR[2](r2) + rfi +L_802CF694: + lis r2, TRK_saved_exceptionID@h + ori r2, r2, TRK_saved_exceptionID@l + lhz r3, 0(r2) + lis r2, gTRKExceptionStatus@h + ori r2, r2, gTRKExceptionStatus@l + lbz r2, TRKExceptionStatus.inTRK(r2) + cmpwi r2, 0 + bne TRKExceptionHandler + lis r2, gTRKCPUState@h + ori r2, r2, gTRKCPUState@l + stw r0, ProcessorState_PPC.Default.GPR[0](r2) + stw r1, ProcessorState_PPC.Default.GPR[1](r2) + mfsprg r0, 1 + stw r0, ProcessorState_PPC.Default.GPR[2](r2) + sth r3, ProcessorState_PPC.Extended1.exceptionID(r2) + sth r3, (ProcessorState_PPC.Extended1.exceptionID + 2)(r2) + mfsprg r0, 2 + stw r0, ProcessorState_PPC.Default.GPR[3](r2) + stmw r4, ProcessorState_PPC.Default.GPR[4](r2) + mfsrr0 r27 + mflr r28 + mfsprg r29, 3 + mfctr r30 + mfxer r31 + stmw r27, ProcessorState_PPC.Default.PC(r2) + bl TRKSaveExtended1Block + lis r2, gTRKExceptionStatus@h + ori r2, r2, gTRKExceptionStatus@l + li r3, 1 + stb r3, TRKExceptionStatus.inTRK(r2) + lis r2, gTRKState@h + ori r2, r2, gTRKState@l + lwz r0, TRKState_PPC.MSR(r2) + sync + mtmsr r0 + sync + lwz r0, TRKState_PPC.LR(r2) + mtlr r0 + lwz r0, TRKState_PPC.CTR(r2) + mtctr r0 + lwz r0, TRKState_PPC.XER(r2) + mtxer r0 + lwz r0, TRKState_PPC.DSISR(r2) + mtdsisr r0 + lwz r0, TRKState_PPC.DAR(r2) + mtdar r0 + lmw r3, TRKState_PPC.GPR[3](r2) + lwz r0, TRKState_PPC.GPR[0](r2) + lwz r1, TRKState_PPC.GPR[1](r2) + lwz r2, TRKState_PPC.GPR[2](r2) + b TRKPostInterruptEvent +} +#endif // clang-format on + +#ifdef __MWERKS__ // clang-format off +static asm void TRKExceptionHandler(u16 r3) +{ + nofralloc + lis r2, gTRKExceptionStatus@h + ori r2, r2, gTRKExceptionStatus@l + sth r3, TRKExceptionStatus.exceptionInfo.exceptionID(r2) + mfsrr0 r3 + stw r3, TRKExceptionStatus.exceptionInfo.PC(r2) + lhz r3, TRKExceptionStatus.exceptionInfo.exceptionID(r2) + cmpwi r3, 0x200 + beq LAB_00010ba4 + cmpwi r3, 0x300 + beq LAB_00010ba4 + cmpwi r3, 0x400 + beq LAB_00010ba4 + cmpwi r3, 0x600 + beq LAB_00010ba4 + cmpwi r3, 0x700 + beq LAB_00010ba4 + cmpwi r3, 0x800 + beq LAB_00010ba4 + cmpwi r3, 0x1000 + beq LAB_00010ba4 + cmpwi r3, 0x1100 + beq LAB_00010ba4 + cmpwi r3, 0x1200 + beq LAB_00010ba4 + cmpwi r3, 0x1300 + beq LAB_00010ba4 + b LAB_00010bb0 +LAB_00010ba4: + mfsrr0 r3 + addi r3, r3, 0x4 + mtsrr0 r3 +LAB_00010bb0: + lis r2, gTRKExceptionStatus@h + ori r2, r2, gTRKExceptionStatus@l + li r3, 0x1 + stb r3, TRKExceptionStatus.exceptionDetected(r2) + mfsprg r3, 3 + mtcrf 0xff, r3 + mfsprg r2, 1 + mfsprg r3, 2 + rfi +} +#endif // clang-format on + +#ifdef __MWERKS__ // clang-format off +asm void TRKSwapAndGo() +{ + nofralloc + lis r3, gTRKState@h + ori r3, r3, gTRKState@l + stmw r0, TRKState_PPC.GPR[0](r3) + mfmsr r0 + stw r0, TRKState_PPC.MSR(r3) + mflr r0 + stw r0, TRKState_PPC.LR(r3) + mfctr r0 + stw r0, TRKState_PPC.CTR(r3) + mfxer r0 + stw r0, TRKState_PPC.XER(r3) + mfdsisr r0 + stw r0, TRKState_PPC.DSISR(r3) + mfdar r0 + stw r0, TRKState_PPC.DAR(r3) + li r1, -0x7ffe + nor r1, r1, r1 + mfmsr r3 + and r3, r3, r1 + mtmsr r3 + lis r2, gTRKState@h + ori r2, r2, gTRKState@l + lwz r2, TRKState_PPC.inputPendingPtr(r2) + lbz r2, TRKState_PPC.GPR[0](r2) + cmpwi r2, 0 + beq L_802CF930 + lis r2, gTRKState@h + ori r2, r2, gTRKState@l + li r3, 1 + stb r3, TRKState_PPC.inputActivated(r2) + b TRKInterruptHandlerEnableInterrupts +L_802CF930: + lis r2, gTRKExceptionStatus@h + ori r2, r2, gTRKExceptionStatus@l + li r3, 0 + stb r3, 0xc(r2) + bl TRKRestoreExtended1Block + lis r2, gTRKCPUState@h + ori r2, r2, gTRKCPUState@l + lmw r27, ProcessorState_PPC.Default.PC(r2) + mtsrr0 r27 + mtlr r28 + mtcrf 0xff, r29 + mtctr r30 + mtxer r31 + lmw r3, ProcessorState_PPC.Default.GPR[3](r2) + lwz r0, ProcessorState_PPC.Default.GPR[0](r2) + lwz r1, ProcessorState_PPC.Default.GPR[1](r2) + lwz r2, ProcessorState_PPC.Default.GPR[2](r2) + rfi +} +#endif // clang-format on + +#ifdef __MWERKS__ // clang-format off +asm void TRKInterruptHandlerEnableInterrupts(void) +{ + nofralloc; + lis r2, gTRKState@h + ori r2, r2, gTRKState@l + lwz r0, TRKState_PPC.MSR(r2) + sync + mtmsr r0 + sync + lwz r0, TRKState_PPC.LR(r2) + mtlr r0 + lwz r0, TRKState_PPC.CTR(r2) + mtctr r0 + lwz r0, TRKState_PPC.XER(r2) + mtxer r0 + lwz r0, TRKState_PPC.DSISR(r2) + mtdsisr r0 + lwz r0, TRKState_PPC.DAR(r2) + mtdar r0 + lmw r3, TRKState_PPC.GPR[3](r2) + lwz r0, TRKState_PPC.GPR[0](r2) + lwz r1, TRKState_PPC.GPR[1](r2) + lwz r2, TRKState_PPC.GPR[2](r2) + b TRKPostInterruptEvent +} +#endif // clang-format on + +#ifdef __MWERKS__ // clang-format off +asm void ReadFPSCR(register f64*) +{ + nofralloc + stwu r1, -0x40(r1) + stfd f31, 0x10(r1) + psq_st f31, 0x20(r1),0,0 + mffs f31 + stfd f31, 0x0(r3) + psq_l f31, 0x20(r1),0,0 + lfd f31, 0x10(r1) + addi r1, r1, 0x40 + blr +} +#endif // clang-format on + +#ifdef __MWERKS__ // clang-format off +asm void WriteFPSCR(register f64*) +{ + nofralloc + stwu r1, -0x40(r1) + stfd f31, 0x10(r1) + psq_st f31, 0x20(r1), 0, 0 + lfd f31, 0(r3) + mtfsf 0xff, f31 + psq_l f31, 0x20(r1), 0, 0 + lfd f31, 0x10(r1) + addi r1, r1, 0x40 + blr +} +#endif // clang-format on diff --git a/src/static/TRK_MINNOW_DOLPHIN/targsupp.s b/src/static/TRK_MINNOW_DOLPHIN/targsupp.s new file mode 100644 index 00000000..3bf48d2b --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/targsupp.s @@ -0,0 +1,32 @@ +.include "macros.inc" + +.text +.balign 32 + +.global TRKAccessFile +.type TRKAccessFile, @function +TRKAccessFile: + twi 31, r0, 0 + blr +.size TRKAccessFile, . - TRKAccessFile + +.global TRKOpenFile +.type TRKOpenFile, @function +TRKOpenFile: + twi 31, r0, 0 + blr +.size TRKOpenFile, . - TRKOpenFile + +.global TRKCloseFile +.type TRKCloseFile, @function +TRKCloseFile: + twi 31, r0, 0 + blr +.size TRKCloseFile, . - TRKCloseFile + +.global TRKPositionFile +.type TRKPositionFile, @function +TRKPositionFile: + twi 31, r0, 0 + blr +.size TRKPositionFile, . - TRKPositionFile diff --git a/src/static/TRK_MINNOW_DOLPHIN/usr_put.c b/src/static/TRK_MINNOW_DOLPHIN/usr_put.c new file mode 100644 index 00000000..98ac4436 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/usr_put.c @@ -0,0 +1,91 @@ +#include "TRK/dstypes.h" + +// can't include OS headers bc report needs to not generate crclr +extern void SetTRKConnected(u32); +extern u32 GetTRKConnected(void); +extern void OSReport(const char*); + +void usr_putchar_serial(void) +{ + // UNUSED FUNCTION +} + +BOOL usr_puts_serial(const char* msg) +{ + BOOL connect_ = FALSE; + char c; + char buf[2]; + + while (!connect_ && (c = *msg++) != '\0') { + BOOL connect = GetTRKConnected(); + + buf[0] = c; + buf[1] = '\0'; + + SetTRKConnected(FALSE); + OSReport(buf); + + SetTRKConnected(connect); + connect_ = FALSE; + } + return connect_; +} + +void usr_put_initialize_ram(void) +{ + // UNUSED FUNCTION +} + +void usr_putchar_ram(void) +{ + // UNUSED FUNCTION +} + +void usr_puts_ram(void) +{ + // UNUSED FUNCTION +} + +void usr_put_initialize(void) +{ +} + +void usr_putchar(void) +{ + // UNUSED FUNCTION +} + +void usr_puts(void) +{ + // UNUSED FUNCTION +} + +void __do_putchar(void) +{ + // UNUSED FUNCTION +} + +void __do_puts(void) +{ + // UNUSED FUNCTION +} + +void __do_puthex32(void) +{ + // UNUSED FUNCTION +} + +void __do_puthex8(void) +{ + // UNUSED FUNCTION +} + +void __do_puthex4(void) +{ + // UNUSED FUNCTION +} + +void __do_puthex2(void) +{ + // UNUSED FUNCTION +} From 61f624a572aa16d4a53614a7d50ef9f757944a8a Mon Sep 17 00:00:00 2001 From: h0504 Date: Tue, 27 Oct 2026 08:25:44 +0900 Subject: [PATCH 3/7] Update JSystem and its wrappers to the e+ Rev 1 revision - JKernel: JKRArchive grows to 0x64 (mExpandSizes), new u32* pSize overloads for the ARAM/DVD rippers, JKRThread::run out of line, JKRAramBlock/JKRAramArchive helpers in their own headers, placement new moved to include/libc/new.h. - JUtility: Rev 1 JUTGamePad (rumble hard stop, long press, stick clamp), coloured JUTDirectPrint, JUTException FPE info, JUTConsole tab width, newer exidrv/carddrv/fs_* code paths (fs_subd/fs_rddr Rev 1 changes are VERSION-guarded so Rev 0 is unchanged). - JFramework: JFWDisplay ported from the late-2003 JSystem. - JSUList: drop the empty user-declared JSULink/JSUTree destructors and use the implicit TColor::operator=, which reproduces the original weak function section order. - jsyswrap.cpp and libjsys rewritten for e+ (AGB, picture copy and SD card archives, new console/video wrappers). JC_JUTDirectPrint_setCharColor is a fabricated stand-in for a stripped wrapper, marked as such. Co-Authored-By: Claude Opus 5.5 --- include/JSystem/J2D/J2DGrafContext.h | 3 +- include/JSystem/JFramework/JFWDisplay.h | 61 +- include/JSystem/JGeometry.h | 3 +- include/JSystem/JKernel/JKRAram.h | 66 +- include/JSystem/JKernel/JKRAramArchive.h | 16 + include/JSystem/JKernel/JKRAramBlock.h | 45 + include/JSystem/JKernel/JKRArchive.h | 59 +- include/JSystem/JKernel/JKRDecomp.h | 7 +- include/JSystem/JKernel/JKRDvdAramRipper.h | 33 +- include/JSystem/JKernel/JKRDvdRipper.h | 26 + include/JSystem/JKernel/JKRFileLoader.h | 13 +- include/JSystem/JKernel/JKRHeap.h | 6 +- include/JSystem/JKernel/JKRThread.h | 7 +- include/JSystem/JSupport/JSUList.h | 5 - include/JSystem/JSystem.h | 8 - include/JSystem/JUtility/JUTConsole.h | 8 + include/JSystem/JUtility/JUTDbPrint.h | 3 + include/JSystem/JUtility/JUTDirectPrint.h | 14 + include/JSystem/JUtility/JUTException.h | 20 +- include/JSystem/JUtility/JUTGamePad.h | 94 +- include/JSystem/JUtility/JUTProcBar.h | 4 +- include/JSystem/JUtility/JUTVideo.h | 4 +- include/JSystem/JUtility/JUTXfb.h | 2 +- include/JSystem/JUtility/TColor.h | 5 - include/JSystem/JUtility/carddrv.h | 2 +- include/JSystem/JUtility/exidrv.h | 2 +- include/libc/new.h | 12 + include/libjsys/jsyswrapper.h | 4 +- src/static/JSystem/JFramework/JFWDisplay.cpp | 366 ++++-- src/static/JSystem/JKernel/JKRAram.cpp | 125 +- src/static/JSystem/JKernel/JKRAramArchive.cpp | 162 ++- src/static/JSystem/JKernel/JKRAramPiece.cpp | 2 +- src/static/JSystem/JKernel/JKRAramStream.cpp | 34 +- src/static/JSystem/JKernel/JKRArchivePri.cpp | 18 +- src/static/JSystem/JKernel/JKRArchivePub.cpp | 63 +- src/static/JSystem/JKernel/JKRCompArchive.cpp | 234 ++-- src/static/JSystem/JKernel/JKRDecomp.cpp | 6 +- .../JSystem/JKernel/JKRDvdAramRipper.cpp | 108 +- src/static/JSystem/JKernel/JKRDvdArchive.cpp | 209 +++- src/static/JSystem/JKernel/JKRDvdFile.cpp | 3 +- src/static/JSystem/JKernel/JKRDvdRipper.cpp | 358 +++--- src/static/JSystem/JKernel/JKRFileLoader.cpp | 17 + src/static/JSystem/JKernel/JKRHeap.cpp | 5 +- src/static/JSystem/JKernel/JKRMemArchive.cpp | 112 +- src/static/JSystem/JKernel/JKRThread.cpp | 77 +- src/static/JSystem/JUtility/JUTAssert.cpp | 10 +- src/static/JSystem/JUtility/JUTConsole.cpp | 13 +- src/static/JSystem/JUtility/JUTDbPrint.cpp | 27 +- .../JSystem/JUtility/JUTDirectPrint.cpp | 61 +- src/static/JSystem/JUtility/JUTException.cpp | 258 ++++- src/static/JSystem/JUtility/JUTGamePad.cpp | 523 +++++---- src/static/JSystem/JUtility/JUTVideo.cpp | 8 +- src/static/JSystem/JUtility/JUTXfb.cpp | 29 +- src/static/JSystem/JUtility/carddrv.c | 221 ++-- src/static/JSystem/JUtility/exidrv.c | 252 ++-- src/static/JSystem/JUtility/fs_form.c | 33 +- src/static/JSystem/JUtility/fs_rddr.c | 4 + src/static/JSystem/JUtility/fs_subd.c | 37 +- src/static/jsyswrap.cpp | 1018 +++++++++++++++++ src/static/jsyswrap_JKRAramStream.h | 10 + src/static/libjsys/jsyswrapper.cpp | 64 +- src/static/libjsys/jsyswrapper_ext.cpp | 41 - src/static/libjsys/jsyswrapper_main.cpp | 124 +- 63 files changed, 3662 insertions(+), 1502 deletions(-) create mode 100644 include/JSystem/JKernel/JKRAramArchive.h create mode 100644 include/JSystem/JKernel/JKRAramBlock.h create mode 100644 include/libc/new.h create mode 100644 src/static/jsyswrap.cpp create mode 100644 src/static/jsyswrap_JKRAramStream.h delete mode 100644 src/static/libjsys/jsyswrapper_ext.cpp diff --git a/include/JSystem/J2D/J2DGrafContext.h b/include/JSystem/J2D/J2DGrafContext.h index da97d160..2e6b7f7b 100644 --- a/include/JSystem/J2D/J2DGrafContext.h +++ b/include/JSystem/J2D/J2DGrafContext.h @@ -131,8 +131,7 @@ struct J2DOrthoGraph : public J2DGrafContext { } void setOrtho(f32 param_0, f32 param_1, f32 param_2, f32 param_3, f32 param_4, f32 param_5) { - JGeometry::TBox2 ortho(param_0, param_1, param_0 + param_2, param_1 + param_3); - setOrtho(ortho, param_4, param_5); + setOrtho(JGeometry::TBox2(param_0, param_1, param_0 + param_2, param_1 + param_3), param_4, param_5); } // _00 = VTBL diff --git a/include/JSystem/JFramework/JFWDisplay.h b/include/JSystem/JFramework/JFWDisplay.h index 67ab9467..15324a15 100644 --- a/include/JSystem/JFramework/JFWDisplay.h +++ b/include/JSystem/JFramework/JFWDisplay.h @@ -19,7 +19,7 @@ extern GC_Mtx e_mtx; class JFWAlarm : public OSAlarm { // everything here seems to be auto inlined or unused public: // Contructor and Destructor are both present in map but unused, not sure if it belongs here - JFWAlarm() { + JFWAlarm() : mLink(this) { } ~JFWAlarm() { } @@ -29,6 +29,12 @@ class JFWAlarm : public OSAlarm { // everything here seems to be auto inlined or void cancelAlarm() { OSCancelAlarm(this); } + void removeLink() { + sList.remove(&mLink); + } + void appendLink() { + sList.append(&mLink); + } OSThread* getThread() const { return mThread; @@ -41,6 +47,7 @@ class JFWAlarm : public OSAlarm { // everything here seems to be auto inlined or public: /* 0x28 */ OSThread* mThread; + /* 0x2C */ JSULink mLink; }; class JFWDisplay { @@ -51,6 +58,9 @@ class JFWDisplay { }; static JFWDisplay* createManager(const _GXRenderModeObj*, JKRHeap*, JUTXfb::EXfbNumber, bool); // 0x80015bfc + static JFWDisplay* createManager(JKRHeap* heap, JUTXfb::EXfbNumber xfbNum, bool enableAlpha) { + return createManager(nullptr, heap, xfbNum, enableAlpha); + } void waitBlanking(int); // 0x8001684c void threadSleep(s64); // 0x800169fc void clearEfb_init(); // 0x80016ab8 @@ -59,8 +69,8 @@ class JFWDisplay { void clearEfb(int, int, int, int, _GXColor); // 0x80016b9c void calcCombinationRatio(); // 0x80016f0c - void ctor_subroutine(const GXRenderModeObj*, bool); - JFWDisplay(const GXRenderModeObj*, JKRHeap*, JUTXfb::EXfbNumber, bool); + void ctor_subroutine(bool); + JFWDisplay(JKRHeap*, JUTXfb::EXfbNumber, bool); static void destroyManager(); void prepareCopyDisp(); @@ -99,15 +109,15 @@ class JFWDisplay { } const GXRenderModeObj* getRenderMode() const { - return mRMode; + return JUTVideo::getManager()->getRenderMode(); } int getEfbHeight() const { - return getRenderMode() ->efbHeight; + return (u16)JUTVideo::getManager()->getEfbHeight(); } int getEfbWidth() const { - return getRenderMode() ->fbWidth; + return JUTVideo::getManager()->getFbWidth(); } JUTFader* getFader() const { @@ -155,7 +165,7 @@ class JFWDisplay { return mEnableAlpha; } - void setGamma(u16 gamma) { + void setGamma(GXGamma gamma) { mGamma = gamma; } @@ -167,23 +177,26 @@ class JFWDisplay { static JFWDisplay* sManager; // 0x80415718 private: - JUTFader* mFader; // 04 - const GXRenderModeObj* mRMode; // 08 - JUtility::TColor mClearColor; // 0c - u32 mZClear; // 10 - JUTXfb* mXfb; // 14 - u16 mGamma; // 18 - EDrawDone mDrawDoneMethod; // 1c - u16 mFrameRate; // 20 - u32 mTickRate; // 24 - bool mEnableAlpha; // 28 - u16 mClamp; // 2a - f32 mCombinationRatio; // 2c - u32 mStartTick; // 30, tick of when the frame starts rendering - u32 mFrameTime; // 34, time it took to render a frame/amount of ticks beginRender took - u32 mVideoFrameTime; // 38, time between mStartTick and the last Video Tick - s16 mDrawingXfbNo; // 3c - bool mIsSingleXfb; // 3e + JUTFader* mFader; // 04 + JUtility::TColor mClearColor; // 08 + u32 mZClear; // 0c + JUTXfb* mXfb; // 10 + u16 mGamma; // 14 + EDrawDone mDrawDoneMethod; // 18 + u16 mFrameRate; // 1c + u32 mTickRate; // 20 + bool mEnableAlpha; // 24 + u16 mClamp; // 26 + f32 mCombinationRatio; // 28 + u32 mStartTick; // 2c, tick of when the frame starts rendering + u32 mFrameTime; // 30, time it took to render a frame/amount of ticks beginRender took + u32 mVideoFrameTime; // 34 + int mDrawInterval; // 38 + int mDrawCount; // 3c + bool mIsDrawFrame; // 40 + JFWDisplayUnkFunc mPreCopyDispFunc; // 44 + s16 mDrawingXfbNo; // 48 + bool mIsSingleXfb; // 4a }; #endif diff --git a/include/JSystem/JGeometry.h b/include/JSystem/JGeometry.h index ae0c7d44..d2ede8ad 100644 --- a/include/JSystem/JGeometry.h +++ b/include/JSystem/JGeometry.h @@ -25,7 +25,8 @@ template struct TVec2 { y = x = v; } - void set(T x, T y) { + template + void set(U x, U y) { this->x = x; this->y = y; } diff --git a/include/JSystem/JKernel/JKRAram.h b/include/JSystem/JKernel/JKRAram.h index 981bad61..e5838f46 100644 --- a/include/JSystem/JKernel/JKRAram.h +++ b/include/JSystem/JKernel/JKRAram.h @@ -25,40 +25,7 @@ class JKRAramHeap; class JKRDecompCommand; class JKRAMCommand; -class JKRAramBlock { - public: - JKRAramBlock(u32 address, u32 size, u32 freeSize, u8 groupID, bool tempMemory); - - virtual ~JKRAramBlock(); - - JKRAramBlock* allocHead(u32 size, u8 groupID, JKRAramHeap* heap); - JKRAramBlock* allocTail(u32 size, u8 groupID, JKRAramHeap* heap); - - u32 getAddress() const { - return this->mAddress; - } - u32 getSize() const { - return this->mSize; - } - u32 getFreeSize() const { - return this->mFreeSize; - } - bool isTempMemory() const { - return this->mIsTempMemory; - } - void newGroupID(u8 groupID) { - this->mGroupID = groupID; - } - - JSULink mLink; - u32 mAddress; - u32 mSize; - u32 mFreeSize; - u8 mGroupID; - bool mIsTempMemory; - - friend class JKRAramHeap; -}; +#include "JSystem/JKernel/JKRAramBlock.h" class JKRAramHeap : public JKRDisposer { public: @@ -116,6 +83,8 @@ class JKRAram : public JKRThread { static JKRAram* create(u32, u32, long, long, long); static JKRAramBlock* mainRamToAram(u8*, u32, u32, JKRExpandSwitch, u32, JKRHeap*, int); static JKRAramBlock* mainRamToAram(u8*, JKRAramBlock* block, u32, JKRExpandSwitch, u32, JKRHeap*, int); + static JKRAramBlock* mainRamToAram(u8*, u32, u32, JKRExpandSwitch, u32, JKRHeap*, int, u32*); + static JKRAramBlock* mainRamToAram(u8*, JKRAramBlock* block, u32, JKRExpandSwitch, u32, JKRHeap*, int, u32*); static u8* aramToMainRam(u32, u8*, u32, JKRExpandSwitch, u32, JKRHeap*, int, u32*); static u8* aramToMainRam(JKRAramBlock*, u8*, u32, u32, JKRExpandSwitch, u32, JKRHeap*, int, u32*); @@ -242,15 +211,16 @@ class JKRAramStreamCommand { u32 _0C; // _0C JSUFileInputStream* mStream; // _10 u32 mOffset; // _14 - u8* mTransferBuffer; // _18 - u32 mTransferBufferSize; // _1C - JKRHeap* mHeap; // _20 - bool mAllocatedTransferBuffer; // _24 - u32 _28; // _28 - OSMessageQueue mMessageQueue; // _2C - void* mMessage; // _4C - u32 _50; // _50 + u32* mReturnSize; // _18 + u8* mTransferBuffer; // _1C + u32 mTransferBufferSize; // _20 + JKRHeap* mHeap; // _24 + bool mAllocatedTransferBuffer; // _28 + u32 _2C; // _2C + OSMessageQueue mMessageQueue; // _30 + void* mMessage; // _50 u32 _54; // _54 + u32 _58; // _58 }; class JKRAramStream : public JKRThread { @@ -266,6 +236,8 @@ class JKRAramStream : public JKRThread { static s32 writeToAram(JKRAramStreamCommand*); static JKRAramStreamCommand* write_StreamToAram_Async(JSUFileInputStream*, JKRAramBlock*, u32, u32); static JKRAramStreamCommand* write_StreamToAram_Async(JSUFileInputStream*, u32, u32, u32); + static JKRAramStreamCommand* write_StreamToAram_Async(JSUFileInputStream*, JKRAramBlock*, u32, u32, u32*); + static JKRAramStreamCommand* write_StreamToAram_Async(JSUFileInputStream*, u32, u32, u32, u32*); static JKRAramStreamCommand* sync(JKRAramStreamCommand*, BOOL); static void setTransBuffer(u8*, u32, JKRHeap*); @@ -299,6 +271,16 @@ inline JKRAramBlock* JKRMainRamToAram(u8* buf, u32 bufSize, u32 alignedSize, JKR return JKRAram::mainRamToAram(buf, bufSize, alignedSize, expandSwitch, fileSize, heap, id); } +inline u8* JKRAramToMainRam(JKRAramBlock* block, u8* buf, u32 bufSize, u32 offset, JKRExpandSwitch expandSwitch, + u32 maxDest, JKRHeap* heap, int id, u32* pSize) { + return JKRAram::aramToMainRam(block, buf, bufSize, offset, expandSwitch, maxDest, heap, id, pSize); +} + +inline JKRAramBlock* JKRMainRamToAram(u8* buf, JKRAramBlock* block, u32 bufSize, JKRExpandSwitch expandSwitch, + u32 maxDest, JKRHeap* heap, int id, u32* pSize) { + return JKRAram::mainRamToAram(buf, block, bufSize, expandSwitch, maxDest, heap, id, pSize); +} + inline JKRAramStream* JKRCreateAramStreamManager(s32 priority) { return JKRAramStream::create(priority); } diff --git a/include/JSystem/JKernel/JKRAramArchive.h b/include/JSystem/JKernel/JKRAramArchive.h new file mode 100644 index 00000000..0f17ef14 --- /dev/null +++ b/include/JSystem/JKernel/JKRAramArchive.h @@ -0,0 +1,16 @@ +#ifndef JKRARAMARCHIVE_H +#define JKRARAMARCHIVE_H + +#include "JSystem/JKernel/JKRArchive.h" + +#ifdef __cplusplus +inline bool JKRMountFixedAramArchive(JKRAramArchive* archive, const char* path) { + return archive->mountFixed(path, JKRArchive::MOUNT_DIRECTION_HEAD); +} + +inline void JKRUnmountFixedAramArchive(JKRAramArchive* archive) { + archive->unmountFixed(); +} + +#endif +#endif diff --git a/include/JSystem/JKernel/JKRAramBlock.h b/include/JSystem/JKernel/JKRAramBlock.h new file mode 100644 index 00000000..505df436 --- /dev/null +++ b/include/JSystem/JKernel/JKRAramBlock.h @@ -0,0 +1,45 @@ +#ifndef JKRARAMBLOCK_H +#define JKRARAMBLOCK_H + +#include "types.h" +#include "JSystem/JSupport/JSUList.h" + +#ifdef __cplusplus +class JKRAramHeap; + +class JKRAramBlock { + public: + JKRAramBlock(u32 address, u32 size, u32 freeSize, u8 groupID, bool tempMemory); + + virtual ~JKRAramBlock(); + + JKRAramBlock* allocHead(u32 size, u8 groupID, JKRAramHeap* heap); + JKRAramBlock* allocTail(u32 size, u8 groupID, JKRAramHeap* heap); + + u32 getAddress() const { + return this->mAddress; + } + u32 getSize() const { + return this->mSize; + } + u32 getFreeSize() const { + return this->mFreeSize; + } + bool isTempMemory() const { + return this->mIsTempMemory; + } + void newGroupID(u8 groupID) { + this->mGroupID = groupID; + } + + JSULink mLink; + u32 mAddress; + u32 mSize; + u32 mFreeSize; + u8 mGroupID; + bool mIsTempMemory; + + friend class JKRAramHeap; +}; +#endif +#endif diff --git a/include/JSystem/JKernel/JKRArchive.h b/include/JSystem/JKernel/JKRArchive.h index fc080db2..8d58c532 100644 --- a/include/JSystem/JKernel/JKRArchive.h +++ b/include/JSystem/JKernel/JKRArchive.h @@ -167,9 +167,14 @@ class JKRArchive : public JKRFileLoader { virtual s32 getResSize(const void*) const; // _30 virtual u32 countFile(const char*) const; // _34 virtual JKRFileFinder* getFirstFile(const char*) const; // _38 - virtual void* fetchResource(SDIFileEntry* entry, u32* outSize) = 0; // _40 + virtual u32 getExpandedResSize(const void* resource) const { + return getResSize(resource); + } // _3C + virtual void* fetchResource(SDIFileEntry* entry, u32* outSize) = 0; // _40 virtual void* fetchResource(void* resourceBuffer, u32 bufferSize, SDIFileEntry* entry, u32* resSize, JKRExpandSwitch expandSwitch) = 0; // _44 + virtual void setExpandSize(SDIFileEntry* entry, u32 size); // _48 + virtual u32 getExpandSize(SDIFileEntry* entry) const; // _4C JKRArchive(s32, EMountMode); JKRArchive(); @@ -238,10 +243,11 @@ class JKRArchive : public JKRFileLoader { SArcDataInfo* mArcInfoBlock; // _44 SDIDirEntry* mDirectories; // _48 SDIFileEntry* mFileEntries; // _4C - const char* mStrTable; // _50 - int _54; // _54 - int mCompression; // _58 - EMountDirection mMountDirection; // _5C + u32* mExpandSizes; // _50 + const char* mStrTable; // _54 + int _58; // _58 + int mCompression; // _5C + EMountDirection mMountDirection; // _60 }; enum JKRMemBreakFlag { MBF_0 = 0, MBF_1 = 1 }; @@ -252,6 +258,7 @@ class JKRAramArchive : public JKRArchive { JKRAramArchive(s32, EMountDirection); virtual ~JKRAramArchive(); // _08 + virtual u32 getExpandedResSize(const void*) const; // _3C virtual void* fetchResource(SDIFileEntry*, u32*); // _40 virtual void* fetchResource(void*, u32, SDIFileEntry*, u32*, JKRExpandSwitch expandSwitch); // _44 @@ -278,6 +285,7 @@ struct JKRCompArchive : public JKRArchive { virtual ~JKRCompArchive(); // _08 virtual void removeResourceAll(); // _24 virtual bool removeResource(void*); // _28 + virtual u32 getExpandedResSize(const void*) const; // _3C virtual void* fetchResource(SDIFileEntry* entry, u32* outSize); // _40 virtual void* fetchResource(void* resourceBuffer, u32 bufferSize, SDIFileEntry* entry, u32* resSize, JKRExpandSwitch expandSwitch); // _44 @@ -291,24 +299,25 @@ struct JKRCompArchive : public JKRArchive { void unmountFixed(); // _00 = VTBL - // _00-_5C = JKRArchive - u32 _60; // _60 - JKRAramBlock* mAramPart; // _64 - u32 _68; // _68 - JKRFile* mDvdFile; // _6C - u32 mSizeOfMemPart; // _70 - u32 mSizeOfAramPart; // _74 - u32 _78; // _78 + // _00-_64 = JKRArchive + u32 _64; // _64 + JKRAramBlock* mAramPart; // _68 + u32 _6C; // _6C + JKRFile* mDvdFile; // _70 + u32 mSizeOfMemPart; // _74 + u32 mSizeOfAramPart; // _78 + u32 _7C; // _7C }; struct JKRDvdArchive : public JKRArchive { JKRDvdArchive(); JKRDvdArchive(s32, JKRArchive::EMountDirection); - virtual ~JKRDvdArchive(); // _00 - virtual void* fetchResource(SDIFileEntry* entry, u32* outSize); // _38 + virtual ~JKRDvdArchive(); // _08 + virtual u32 getExpandedResSize(const void*) const; // _3C + virtual void* fetchResource(SDIFileEntry* entry, u32* outSize); // _40 virtual void* fetchResource(void* resourceBuffer, u32 bufferSize, SDIFileEntry* entry, u32* resSize, - JKRExpandSwitch expandSwitch); // _3C + JKRExpandSwitch expandSwitch); // _44 bool open(s32); static u32 fetchResource_subroutine(s32, u32, u32, u8*, u32, int, int); @@ -321,9 +330,9 @@ struct JKRDvdArchive : public JKRArchive { unknown unmountFixed(); // _00 = VTBL - // _00-_5C = JKRArchive - int _60; // _60 - JKRFile* mDvdFile; // _64 + // _00-_64 = JKRArchive + int _64; // _64 + JKRFile* mDvdFile; // _68 }; struct JKRMemArchive : public JKRArchive { @@ -335,6 +344,7 @@ struct JKRMemArchive : public JKRArchive { virtual ~JKRMemArchive(); // _08 virtual void removeResourceAll(); // _24 virtual bool removeResource(void*); // _28 + virtual u32 getExpandedResSize(const void*) const; // _3C virtual void* fetchResource(SDIFileEntry* entry, u32* outSize); // _40 virtual void* fetchResource(void* resourceBuffer, u32 bufferSize, SDIFileEntry* entry, u32* resSize, JKRExpandSwitch expandSwitch); // _44 @@ -343,12 +353,13 @@ struct JKRMemArchive : public JKRArchive { bool open(void*, u32, JKRMemBreakFlag); static u32 fetchResource_subroutine(u8*, u32, u8*, u32, int); + bool mountFixed(void*, JKRMemBreakFlag); + void unmountFixed(); + // Unused/inlined: void fixedInit(s32); void mountFixed(s32, EMountDirection); void mountFixed(const char*, EMountDirection); - void mountFixed(void*, JKRMemBreakFlag); - void unmountFixed(); void open(const char*, EMountDirection); // _00 = VTBL @@ -371,5 +382,11 @@ inline JKRArchive* JKRMountArchive(void* inBuf, JKRHeap* heap, JKRArchive::EMoun return JKRArchive::mount(inBuf, heap, mountDirection); } +inline JKRArchive::SDIFileEntry* JKRGetResourceEntry(u32 type, const char* name, JKRArchive* archive) { + return archive->findTypeResource(type, name); +} + +#include "JSystem/JKernel/JKRAramArchive.h" + #endif #endif diff --git a/include/JSystem/JKernel/JKRDecomp.h b/include/JSystem/JKernel/JKRDecomp.h index 7ed5e688..57ebb5a1 100644 --- a/include/JSystem/JKernel/JKRDecomp.h +++ b/include/JSystem/JKernel/JKRDecomp.h @@ -9,7 +9,7 @@ #include "JSystem/JKernel/JKREnum.h" #ifdef __cplusplus -#define JKRDECOMP_MSG_BUF_COUNT 4 +#define JKRDECOMP_MSG_BUF_COUNT 8 #define JKRDECOMP_STACK_SIZE 0x4000 #define JKRDECOMP_THREAD_MSG_BUF_COUNT 16 @@ -47,7 +47,7 @@ class JKRDecompCommand { class JKRDecomp : public JKRThread { public: - enum CompressionMode { NONE = 0, SZP = 1, SZS = 2 }; + enum CompressionMode { NONE = 0, SZP = 1, SZS = 2, ASR = 3 }; JKRDecomp(s32 decompPriority); @@ -97,9 +97,12 @@ inline void JKRDecompress(u8* src, u8* dst, u32 srcLength, u32 skipCount) { } int JKRDecompressFromDVD(JKRDvdFile* srcFile, void* buf, u32 size, u32 maxDest, u32 fileOffset, u32 srcOffset); +int JKRDecompressFromDVD(JKRDvdFile* srcFile, void* buf, u32 size, u32 maxDest, u32 fileOffset, u32 srcOffset, u32* resSize); int JKRDecompressFromDVDToAram(JKRDvdFile* srcFile, u32 address, u32 fileSize, u32 maxDest, u32 fileOffset, u32 srcOffset); +int JKRDecompressFromDVDToAram(JKRDvdFile* srcFile, u32 address, u32 fileSize, u32 maxDest, u32 fileOffset, u32 srcOffset, u32* resSize); int JKRDecompressFromAramToMainRam(u32 srcAddress, void* dst, u32 fileSize, u32 maxDest, u32 fileOffset); +int JKRDecompressFromAramToMainRam(u32 srcAddress, void* dst, u32 fileSize, u32 maxDest, u32 fileOffset, u32* resSize); #endif #endif diff --git a/include/JSystem/JKernel/JKRDvdAramRipper.h b/include/JSystem/JKernel/JKRDvdAramRipper.h index 658dcc19..a29e0eb8 100644 --- a/include/JSystem/JKernel/JKRDvdAramRipper.h +++ b/include/JSystem/JKernel/JKRDvdAramRipper.h @@ -13,20 +13,19 @@ class JKRADCommand { JKRADCommand(); ~JKRADCommand(); - // Fields might need more swapping - JSULink mLink; + JSULink mLink; // _00 + u8 _10[0x18]; // _10 JKRDvdFile* mDvdFile; // _28 - u32 _14; // _14 - u32 _18; // _18, probably size - u32 _1C; // _1C - JKRAramBlock* mBlock; // _20 - JKRExpandSwitch mExpandSwitch; // _24 - u8 _28[0x10]; // _28 - unknown/padding - u32* _3C; // _3C - s32 _40; // _40 - LoadCallback mCallBack; // _40 - u8 _44; // _44 - JKRAramStreamCommand* mStreamCommand; // _48 + u32 _2C; // _2C, aram address + JKRAramBlock* mBlock; // _30 + JKRExpandSwitch mExpandSwitch; // _34 + LoadCallback mCallBack; // _38 + u32 _3C; // _3C, offset + u32 _40; // _40, size + u32* _44; // _44, resource size + s32 _48; // _48 + u8 _4C; // _4C + JKRAramStreamCommand* mStreamCommand; // _50 }; class JKRDvdAramRipper { @@ -35,6 +34,10 @@ class JKRDvdAramRipper { static JKRAramBlock* loadToAram(s32, u32, JKRExpandSwitch, u32, u32); static JKRAramBlock* loadToAram(JKRDvdFile*, u32, JKRExpandSwitch, u32, u32); static JKRADCommand* loadToAram_Async(JKRDvdFile*, u32, JKRExpandSwitch, JKRADCommand::LoadCallback, u32, u32); + static JKRAramBlock* loadToAram(s32, u32, JKRExpandSwitch, u32, u32, u32*); + static JKRAramBlock* loadToAram(JKRDvdFile*, u32, JKRExpandSwitch, u32, u32, u32*); + static JKRADCommand* loadToAram_Async(JKRDvdFile*, u32, JKRExpandSwitch, JKRADCommand::LoadCallback, u32, u32, + u32*); static JKRADCommand* callCommand_Async(JKRADCommand*); static bool syncAram(JKRADCommand*, int); @@ -61,5 +64,9 @@ inline JKRAramBlock* JKRDvdToAram(s32 entrynum, u32 p2, JKRExpandSwitch expSwitc return JKRDvdAramRipper::loadToAram(entrynum, p2, expSwitch, p4, p5); } +inline JKRAramBlock* JKRDvdToAram(s32 entrynum, u32 p2, JKRExpandSwitch expSwitch, u32 p4, u32 p5, u32* p6) { + return JKRDvdAramRipper::loadToAram(entrynum, p2, expSwitch, p4, p5, p6); +} + #endif #endif diff --git a/include/JSystem/JKernel/JKRDvdRipper.h b/include/JSystem/JKernel/JKRDvdRipper.h index cc8aca11..b4558fe3 100644 --- a/include/JSystem/JKernel/JKRDvdRipper.h +++ b/include/JSystem/JKernel/JKRDvdRipper.h @@ -37,6 +37,17 @@ class JKRDvdRipper { static void* loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, EAllocDirection allocDir, u32 offset, int* compressMode); + static void* loadToMainRAM(const char* file, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, + EAllocDirection allocDir, u32 offset, int* compressMode, u32* pSize); + static void* loadToMainRAM(s32 entrynum, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, + EAllocDirection allocDir, u32 offset, int* compressMode, u32* pSize); + static void* loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, + EAllocDirection allocDir, u32 offset, int* compressMode, u32* pSize); + + static int getSZSBufferSize() { + return sSZSBufferSize; + } + static inline bool isErrorRetry() { return JKRDvdRipper::errorRetry; } @@ -44,6 +55,7 @@ class JKRDvdRipper { static JSUList sDvdAsyncList; static bool errorRetry; + static int sSZSBufferSize; }; inline void* JKRDvdToMainRam(long entryNum, u8* dst, JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap, @@ -58,5 +70,19 @@ inline void* JKRDvdToMainRam(const char* path, u8* dst, JKRExpandSwitch expandSw pCompression); } +inline void* JKRDvdToMainRam(long entryNum, u8* dst, JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap, + JKRDvdRipper::EAllocDirection allocDirection, u32 startOffset, int* pCompression, + u32* pSize) { + return JKRDvdRipper::loadToMainRAM(entryNum, dst, expandSwitch, fileSize, heap, allocDirection, startOffset, + pCompression, pSize); +} + +inline void* JKRDvdToMainRam(const char* path, u8* dst, JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap, + JKRDvdRipper::EAllocDirection allocDirection, u32 startOffset, int* pCompression, + u32* pSize) { + return JKRDvdRipper::loadToMainRAM(path, dst, expandSwitch, fileSize, heap, allocDirection, startOffset, + pCompression, pSize); +} + #endif #endif diff --git a/include/JSystem/JKernel/JKRFileLoader.h b/include/JSystem/JKernel/JKRFileLoader.h index ffc89c20..00bb31eb 100644 --- a/include/JSystem/JKernel/JKRFileLoader.h +++ b/include/JSystem/JKernel/JKRFileLoader.h @@ -26,7 +26,7 @@ class JKRFileLoader : public JKRDisposer { virtual u32 countFile(const char*) const = 0; // _34 virtual JKRFileFinder* getFirstFile(const char*) const = 0; // _38 - bool isMounted() const { + bool isMounted() { return mIsMounted; } u32 getVolumeType() const { @@ -41,6 +41,7 @@ class JKRFileLoader : public JKRDisposer { static bool removeResource(void* resourceBuffer, JKRFileLoader* fileLoader); static bool detachResource(void* resourceBuffer, JKRFileLoader* fileLoader); + static u32 getResSize(void* resourceBuffer, JKRFileLoader* fileLoader); static JKRFileLoader* findVolume(const char**); static JKRFileFinder* findFirstFile(const char*); @@ -77,10 +78,18 @@ inline void* JKRGetResource(const char* path) { return JKRFileLoader::getGlbResource(path); } -inline void JKRRemoveResource(void* resource, JKRFileLoader* fileLoader) { +inline void JKRRemoveResource(void* resource, JKRFileLoader* fileLoader = nullptr) { JKRFileLoader::removeResource(resource, fileLoader); } +inline bool JKRDetachResource(void* resource, JKRFileLoader* fileLoader = nullptr) { + return JKRFileLoader::detachResource(resource, fileLoader); +} + +inline u32 JKRGetResourceSize(void* resource, JKRFileLoader* fileLoader = nullptr) { + return JKRFileLoader::getResSize(resource, fileLoader); +} + inline void JKRChangeDirectory(const char* dir) { JKRFileLoader::changeDirectory(dir); } diff --git a/include/JSystem/JKernel/JKRHeap.h b/include/JSystem/JKernel/JKRHeap.h index 9bc341b5..16487414 100644 --- a/include/JSystem/JKernel/JKRHeap.h +++ b/include/JSystem/JKernel/JKRHeap.h @@ -90,7 +90,7 @@ class JKRHeap : public JKRDisposer { /* vt[03] */ virtual void callAllDisposer(); /* vt[04] */ virtual u32 getHeapType() = 0; /* vt[05] */ virtual bool check() = 0; - /* vt[06] */ virtual bool dump_sort(); + /* vt[06] */ virtual bool dump_sort() { return true; } /* vt[07] */ virtual bool dump() = 0; /* vt[08] */ virtual void do_destroy() = 0; /* vt[09] */ virtual void* do_alloc(u32 size, int alignment) = 0; @@ -311,9 +311,7 @@ void JKRDefaultMemoryErrorRoutine(void*, u32, int); void* operator new(size_t); void* operator new(size_t, s32); void* operator new(size_t, JKRHeap*, int); -inline void* operator new(size_t, void* buf) { - return buf; -} // i believe this is actually part of MSL_C? +#include "libc/new.h" void* operator new[](size_t); void* operator new[](size_t, s32); diff --git a/include/JSystem/JKernel/JKRThread.h b/include/JSystem/JKernel/JKRThread.h index 440d710f..048cb932 100644 --- a/include/JSystem/JKernel/JKRThread.h +++ b/include/JSystem/JKernel/JKRThread.h @@ -101,9 +101,10 @@ class TLoad { JKRThread(OSThread* osThread, int msgCount); virtual ~JKRThread(); - virtual void* run() { - return nullptr; - } + virtual void* run(); + + void setCommon_mesgQueue(JKRHeap* heap, int msgCount); + BOOL setCommon_heapSpecified(JKRHeap* heap, u32 stackSize, int threadPrio); static void* start(void* param); static JSUList* getList() { diff --git a/include/JSystem/JSupport/JSUList.h b/include/JSystem/JSupport/JSUList.h index 603e9ab4..d86f90d1 100644 --- a/include/JSystem/JSupport/JSUList.h +++ b/include/JSystem/JSupport/JSUList.h @@ -180,9 +180,6 @@ template class JSULink : public JSUPtrLink { JSULink* getPrev() const { return (JSULink*)JSUPtrLink::getPrev(); } - - ~JSULink() { - } }; template // TODO: most of these inlines are probably wrong: rework @@ -190,8 +187,6 @@ class JSUTree : public JSUList, public JSULink { public: JSUTree(T* owner) : JSUList(), JSULink(owner) { } - ~JSUTree() { - } bool appendChild(JSUTree* child) { return this->append(child); diff --git a/include/JSystem/JSystem.h b/include/JSystem/JSystem.h index 34472f34..887f2759 100644 --- a/include/JSystem/JSystem.h +++ b/include/JSystem/JSystem.h @@ -12,14 +12,6 @@ // return JKRFileLoader::getGlbResource(resourceName); // } -inline void JKRRemoveResource(void* resource) { - JKRFileLoader::removeResource(resource, nullptr); -} - -inline BOOL JKRDetachResource(void* resource) { - return JKRFileLoader::detachResource(resource, nullptr); -} - inline void* JKRGetResourceEntry_byName(u32 root_name, const char* res_name, JKRArchive* archive) { return archive->findTypeResource(root_name, res_name); } diff --git a/include/JSystem/JUtility/JUTConsole.h b/include/JSystem/JUtility/JUTConsole.h index a943a1f5..92ad3edf 100644 --- a/include/JSystem/JUtility/JUTConsole.h +++ b/include/JSystem/JUtility/JUTConsole.h @@ -41,6 +41,7 @@ class JUTConsole : JKRDisposer { void doDraw(JUTConsole::EConsoleType) const; void print_f(char const*, ...); void print(char const*); + void print_f_va(const char*, va_list); void dumpToTerminal(uint); void scroll(int); int getUsedLine() const; @@ -173,6 +174,13 @@ class JUTConsoleManager { extern "C" { void JUTConsole_print_f_va_(JUTConsole*, const char*, va_list); +} + +inline void JUTConsole::print_f_va(const char* fmt, va_list args) { + JUTConsole_print_f_va_(this, fmt, args); +} + +extern "C" { JUTConsole* JUTGetReportConsole(); void JUTSetReportConsole(JUTConsole*); JUTConsole* JUTGetWarningConsole(); diff --git a/include/JSystem/JUtility/JUTDbPrint.h b/include/JSystem/JUtility/JUTDbPrint.h index 1a38f878..da0ab0af 100644 --- a/include/JSystem/JUtility/JUTDbPrint.h +++ b/include/JSystem/JUtility/JUTDbPrint.h @@ -35,6 +35,9 @@ struct JUTDbPrint { void setVisible(bool visible) { mVisible = visible; } + bool isVisible() const { + return mVisible; + } JUTFont* getFont() const { return mFont; } diff --git a/include/JSystem/JUtility/JUTDirectPrint.h b/include/JSystem/JUtility/JUTDirectPrint.h index 3638eaa9..afd6039d 100644 --- a/include/JSystem/JUtility/JUTDirectPrint.h +++ b/include/JSystem/JUtility/JUTDirectPrint.h @@ -3,6 +3,7 @@ #include "types.h" #include "libc/stdarg.h" +#include "JSystem/JUtility/TColor.h" #ifdef __cplusplus @@ -13,6 +14,8 @@ class JUTDirectPrint { public: static JUTDirectPrint* start(); void erase(int x, int y, int w, int h); + void setCharColor(JUtility::TColor color); + void setCharColor(u8 r, u8 g, u8 b); void drawChar(int, int, int); void drawString(u16 x, u16 y, char* text); void drawString_f(u16 x, u16 y, const char* text, ...); @@ -26,6 +29,9 @@ class JUTDirectPrint { void* getFrameBuffer() { return mFramebuffer; } + JUtility::TColor getCharColor() const { + return mCharColor; + } void changeFrameBuffer(void* fb) { changeFrameBuffer(fb, mFbWidth, mFbHeight); @@ -48,6 +54,14 @@ class JUTDirectPrint { size_t mFbSize; // _0C u8 _10[0x4]; // _10 - unknown u16* mFrameMemory; // _14 + JUtility::TColor mCharColor; // _18 + u16 mCharColorY; // _1C + u16 mCharColorCb; // _1E + u16 mCharColorCb2; // _20 + u16 mCharColorCb4; // _22 + u16 mCharColorCr; // _24 + u16 mCharColorCr2; // _26 + u16 mCharColorCr4; // _28 }; inline void JUTChangeFrameBuffer(void* buffer, u16 height, u16 width) { diff --git a/include/JSystem/JUtility/JUTException.h b/include/JSystem/JUtility/JUTException.h index d596c79a..651bc818 100644 --- a/include/JSystem/JUtility/JUTException.h +++ b/include/JSystem/JUtility/JUTException.h @@ -16,9 +16,10 @@ typedef void (*JUTErrorHandler)(OSError error, OSContext* context, u32 dsisr, u3 enum ExPrintFlags { EXPRINTFLAG_GPR = 0x1, EXPRINTFLAG_GPRMap = 0x2, - EXPRINTFLAG_Float = 0x4, - EXPRINTFLAG_Stack = 0x8, - EXPRINTFLAG_All = 0xFF, + EXPRINTFLAG_SRR0Map = 0x4, + EXPRINTFLAG_Float = 0x8, + EXPRINTFLAG_Stack = 0x10, + EXPRINTFLAG_All = 0x1F, }; /** @@ -30,7 +31,7 @@ struct JUTException : public JKRThread { INFOPAGE_Float = 2, INFOPAGE_Stack = 3, INFOPAGE_GPRMap = 4, - + INFOPAGE_SRR0Map = 5, }; // size: 0x14 @@ -106,13 +107,17 @@ struct JUTException : public JKRThread { mTraceSuppress = supress; } - void setGamePad(JUTGamePad* gamePad) { + void enterPad(JUTGamePad* gamePad) { mGamePad = gamePad; mPadPort = JUTGamePad::Port_Invalid; } void enterAllPad() { - setGamePad((JUTGamePad*)-1); + enterPad((JUTGamePad*)-1); + } + + static void setMapFile(const char* path) { + appendMapFile(path); } static JUTException* getManager() { @@ -132,7 +137,7 @@ struct JUTException : public JKRThread { static JUTErrorHandler sPostUserCallback; static u32 msr; static u32 fpscr; - static const char* sCpuExpName[16]; + static const char* sCpuExpName[17]; static JSUList sMapFileList; // _00 = VTBL @@ -146,6 +151,7 @@ struct JUTException : public JKRThread { u32 mTraceSuppress; // _94 u32 _98; // _98 u32 mPrintFlags; // _9C, see ExPrintFlags enum + u32 mStackPointer; // _A0 }; #endif diff --git a/include/JSystem/JUtility/JUTGamePad.h b/include/JSystem/JUtility/JUTGamePad.h index 6c510ead..51bb764a 100644 --- a/include/JSystem/JUtility/JUTGamePad.h +++ b/include/JSystem/JUtility/JUTGamePad.h @@ -25,6 +25,34 @@ class JUTGamePadRecordBase { } }; +struct JUTGamePadLongPress { + static JSUList sPatternList; + + void checkCallback(int port, u32 timer); + + u32 getMaskPattern() const { + return mMaskPattern; + } + u32 getPattern() const { + return mPattern; + } + bool isValid() const { + return mValid; + } + + u8 _00[0x10]; // _00 + bool mValid; // _10 + bool _11; // _11 + u32 mPattern; // _14 + u32 mMaskPattern; // _18 + u32 _1C; // _1C + bool _20[PAD_MAX_CONTROLLERS]; // _20 + OSTime mTimer[PAD_MAX_CONTROLLERS]; // _28 + bool _48[PAD_MAX_CONTROLLERS]; // _48 + void (*mCallback)(int, JUTGamePadLongPress*, int); // _4C + int _50; // _50 +}; + typedef void (*JUTResetBtnCb)(int, void*); class JUTGamePad : public JKRDisposer { public: @@ -68,7 +96,7 @@ class JUTGamePad : public JKRDisposer { void clearForReset(); static void init(); void initList(); - static void read(); + static u32 read(); static bool recalibrate(u32); void setButtonRepeat(u32, u32, u32); void update(); @@ -78,8 +106,9 @@ class JUTGamePad : public JKRDisposer { static bool mListInitialized; static u8 mPadAssign[PAD_MAX_CONTROLLERS]; - static u32 mSuppressPadReset; + static u32 sSuppressPadReset; static u32 sAnalogMode; + static u32 sRumbleSupported; static void setAnalogMode(u32 mode) { JUTGamePad::sAnalogMode = mode; @@ -107,10 +136,6 @@ class JUTGamePad : public JKRDisposer { return mPadStatus[port].err; } - static u32 getPadButton(EPadPort port) { - return mPadButton[port].mButton; - } - static u32 getPadTrigger(EPadPort port) { return mPadButton[port].mTrigger; } @@ -237,6 +262,10 @@ class JUTGamePad : public JKRDisposer { return this->mPadReplay; } + void stopMotorHard() { + CRumble::stopMotorHard(this->mPortNum); + } + class CButton { public: CButton() { @@ -271,13 +300,18 @@ class JUTGamePad : public JKRDisposer { } void clear(); - u32 update(s8 x, s8 y, JUTGamePad::EStickMode, JUTGamePad::EWhichStick); - u32 getButton(); + u32 update(s8 x, s8 y, JUTGamePad::EStickMode, JUTGamePad::EWhichStick, u32); + u32 getButton(u32); + + static f32 sPressPoint; + static f32 sReleasePoint; f32 mX; f32 mY; f32 mValue; s16 mAngle; + s8 mAnalogX; + s8 mAnalogY; }; class CRumble { @@ -292,13 +326,21 @@ class JUTGamePad : public JKRDisposer { static u32 mEnabled; static void startMotor(int port); - static void stopMotor(int port); - static void stopMotorHard(int port); + static void stopMotor(int port, bool hard); + static void stopMotorHard(int port) { + stopMotor(port, true); + } static bool isEnabled(u32 channel) { - return (JUTGamePad::CRumble::mEnabled & channel) != 0; + return (JUTGamePad::CRumble::mEnabled & channel) ? true : false; } + static bool isEnabledPort(int port) { + return isEnabled(sChannelMask[port]); + } + + static u32 sChannelMask[PAD_MAX_CONTROLLERS]; + void clear(); void clear(JUTGamePad* gamePad); void update(s16); @@ -308,6 +350,7 @@ class JUTGamePad : public JKRDisposer { u32 mLength; u8* mData; u32 mFrameCount; + u8* mHardStopData; }; class C3ButtonReset { @@ -329,8 +372,12 @@ class JUTGamePad : public JKRDisposer { bool mReset; }; - static PADStatus* getPadStatus(int idx) { - return &mPadStatus[idx]; + static PADStatus* getPadStatus(EPadPort port) { + return &mPadStatus[port]; + } + + static const CButton* getPadButton(EPadPort port) { + return &mPadButton[port]; } static JSUList mPadList; @@ -339,23 +386,20 @@ class JUTGamePad : public JKRDisposer { static CStick mPadSStick[PAD_MAX_CONTROLLERS]; static EStickMode sStickMode; static EClampMode sClampMode; - static f32 sPressPoint; - static f32 sReleasePoint; static PADStatus mPadStatus[PAD_MAX_CONTROLLERS]; CButton mButtons; // _18 CStick mMainStick; // _48 CStick mSubStick; // _58 - CRumble mRumble; // _68 - s16 mPortNum; // _78 - s8 mErrorStatus; // _7A - JSULink mLink; // _7C - JUTGamePadRecordBase* mPadRecord; - JUTGamePadRecordBase* mPadReplay; - u32 _94; - C3ButtonReset mButtonReset; // _98 - OSTime mResetTime; // _A0 - u8 _A8[8]; // _A8 + CRumble mRumble; // _68 + s16 mPortNum; // _7C + s8 mErrorStatus; // _7E + JSULink mLink; // _80 + JUTGamePadRecordBase* mPadRecord; // _90 + JUTGamePadRecordBase* mPadReplay; // _94 + C3ButtonReset mButtonReset; // _98 + OSTime mResetTime; // _A0 + u8 mResetEnabled; // _A8 }; } #endif diff --git a/include/JSystem/JUtility/JUTProcBar.h b/include/JSystem/JUtility/JUTProcBar.h index 93d7eca3..e28b37d9 100644 --- a/include/JSystem/JUtility/JUTProcBar.h +++ b/include/JSystem/JUtility/JUTProcBar.h @@ -172,10 +172,10 @@ class JUTProcBar { void setVisible(bool visible) { mVisible = visible; } - bool isVisible() { + bool isVisible() const { return mVisible; } - void setHeapBarVisible(bool visible) { + void setVisibleHeapBar(bool visible) { mHeapBarVisible = visible; } void userStart(int idx, u8 r, u8 g, u8 b) { diff --git a/include/JSystem/JUtility/JUTVideo.h b/include/JSystem/JUtility/JUTVideo.h index 4a998b16..7ff2971a 100644 --- a/include/JSystem/JUtility/JUTVideo.h +++ b/include/JSystem/JUtility/JUTVideo.h @@ -28,8 +28,8 @@ struct JUTVideo { int getXfbHeight() const { return mRenderModeObj->xfbHeight & 0xffff; } - u32 getFbWidth() const { - return (u16)mRenderModeObj->fbWidth; + u16 getFbWidth() const { + return mRenderModeObj->fbWidth; } void getBounds(u16& width, u16& height) const { width = getFbWidth(); diff --git a/include/JSystem/JUtility/JUTXfb.h b/include/JSystem/JUtility/JUTXfb.h index c4a92494..2959c16c 100644 --- a/include/JSystem/JUtility/JUTXfb.h +++ b/include/JSystem/JUtility/JUTXfb.h @@ -22,7 +22,7 @@ class JUTXfb { void clearIndex(); void common_init(int); - JUTXfb(JKRHeap*, JUTXfb::EXfbNumber); + JUTXfb(const GXRenderModeObj*, JKRHeap*, JUTXfb::EXfbNumber); ~JUTXfb(); void delXfb(int); static JUTXfb* createManager(JKRHeap*, JUTXfb::EXfbNumber); diff --git a/include/JSystem/JUtility/TColor.h b/include/JSystem/JUtility/TColor.h index ae7172e0..ce19605c 100644 --- a/include/JSystem/JUtility/TColor.h +++ b/include/JSystem/JUtility/TColor.h @@ -28,11 +28,6 @@ struct TColor : public GXColor { set(color); } - TColor& operator=(const TColor& other) { - ((GXColor*)this)->operator=(other); - return *this; - } - /** @fabricated */ TColor& operator=(const GXColorS10& other) { r = other.r; diff --git a/include/JSystem/JUtility/carddrv.h b/include/JSystem/JUtility/carddrv.h index aa620ea4..79a62790 100644 --- a/include/JSystem/JUtility/carddrv.h +++ b/include/JSystem/JUtility/carddrv.h @@ -74,7 +74,7 @@ extern int CARD_SectorSize[CARD_NUM_CHANS]; extern volatile u16 CARD_ErrStatus[CARD_NUM_CHANS]; extern int CARD_Status[CARD_NUM_CHANS]; extern int CARD_UnlockFlag[CARD_NUM_CHANS]; -extern int CARD_Size[CARD_NUM_CHANS]; +extern u32 CARD_Size[CARD_NUM_CHANS]; extern int func_CARD_In[CARD_NUM_CHANS]; extern int func_CARD_Out[CARD_NUM_CHANS]; diff --git a/include/JSystem/JUtility/exidrv.h b/include/JSystem/JUtility/exidrv.h index 10bae6ce..6766d6b3 100644 --- a/include/JSystem/JUtility/exidrv.h +++ b/include/JSystem/JUtility/exidrv.h @@ -15,7 +15,7 @@ extern void EXI_Unlock(s32 chan /*, OSContext* context*/); extern void EXI_AlarmFunc(OSAlarm* alarm, OSContext* context); extern u16 EXI_ResRead(u8* arg0, u16 arg1); extern u16 EXI_StopResRead(u8* arg0, u16 arg1); -extern u16 EXI_DataRes(u8* arg0); +extern u16 EXI_DataRes(u8* arg0, u16 arg1); extern u16 EXI_MultiWriteStop(void); extern u16 EXI_DataRead(u8* arg0, u16 arg1); extern u16 EXI_DataReadFinal(u8* arg0, u16 arg1); diff --git a/include/libc/new.h b/include/libc/new.h new file mode 100644 index 00000000..09f79288 --- /dev/null +++ b/include/libc/new.h @@ -0,0 +1,12 @@ +#ifndef _NEW_H +#define _NEW_H + +#include + +#ifdef __cplusplus +inline void* operator new(size_t, void* buf) { + return buf; +} +#endif + +#endif diff --git a/include/libjsys/jsyswrapper.h b/include/libjsys/jsyswrapper.h index edab1ac0..82c93235 100644 --- a/include/libjsys/jsyswrapper.h +++ b/include/libjsys/jsyswrapper.h @@ -35,6 +35,7 @@ extern CSDIFileEntry* JC__JKRGetResourceEntry_byName(u32 root_name, const char* extern void* JC__JKRDvdToMainRam_byName(const char* name, u8* buf, JKRExpandSwitch expandSwitch); extern void JC__JKRDetachResource(void* ptr); +extern u32 JC__JKRGetResourceSize(void* res); extern int JC_JUTConsole_isVisible(void* console); extern void JC_JUTConsole_setVisible(void* console, BOOL visible); @@ -53,6 +54,7 @@ extern u32 JC_JUTConsole_getHeight(void* console); extern u32 JC_JUTConsole_getUsedLine(void* console); extern void JC_JUTConsole_print_f_va(void* console, const char* fmt, va_list arg); extern void JC_JUTConsole_print_f(void* console, const char* fmt, ...); +extern void JC_JUTConsole_print(void* console, const char* str); extern void* JC_JUTConsoleManager_getManager(); extern void JC_JUTConsoleManager_drawDirect(void* manager, int direct); @@ -95,7 +97,7 @@ extern void* JC_JFWDisplay_changeToSingleXfb(void* manager, int index); extern void* JC_JFWDisplay_changeToDoubleXfb(void* manager); extern int JC_JFWDisplay_getEfbWidth(void* manager); extern int JC_JFWDisplay_getEfbHeight(void* manager); -extern void* JC_JFWDisplay_createManager_0(GXRenderModeObj* renderMode, void* heap, int exfbNumber, int enableAlpha); +extern void* JC_JFWDisplay_createManager_0(void* heap, int exfbNumber, int enableAlpha); extern void JC_JFWDisplay_setFader(void* manager, void* fader); extern void JC_JFWDisplay_setGamma(void* manager, int gamma); extern void JC_JFWDisplay_destroyManager(); diff --git a/src/static/JSystem/JFramework/JFWDisplay.cpp b/src/static/JSystem/JFramework/JFWDisplay.cpp index 601fb8ec..16315980 100644 --- a/src/static/JSystem/JFramework/JFWDisplay.cpp +++ b/src/static/JSystem/JFramework/JFWDisplay.cpp @@ -15,35 +15,19 @@ GC_Mtx e_mtx = { { 1.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f, 0.0f } }; +JSUList JFWAlarm::sList(false); JFWDisplay* JFWDisplay::sManager; -extern void JFWThreadAlarmHandler(OSAlarm*, OSContext*); -extern void JFWGXAbortAlarmHandler(OSAlarm*, OSContext*); -void waitForTick(u32, u16); -void diagnoseGpHang(); - -inline void JFWDrawDoneAlarm() { - OSAlarm alarm; - OSCreateAlarm(&alarm); - OSSetAlarm(&alarm, (OS_TIMER_CLOCK), JFWGXAbortAlarmHandler); - GXDrawDone(); - OSCancelAlarm(&alarm); -} - -void JFWDisplay::ctor_subroutine(const GXRenderModeObj* rmode, bool enableAlpha) { +void JFWDisplay::ctor_subroutine(bool enableAlpha) { mEnableAlpha = enableAlpha; mClamp = GX_CLAMP_TOP | GX_CLAMP_BOTTOM; mClearColor.set(0, 0, 0, 0); - mZClear = 0xFFFFFF; - mRMode = (rmode) ? rmode : JUTVideo::sManager->getRenderMode(); - mGamma = 0; mFader = nullptr; mFrameRate = 1; mTickRate = 0; mCombinationRatio = 0.0f; - mFrameTime = 0; mStartTick = OSGetTick(); mVideoFrameTime = 0; @@ -53,25 +37,37 @@ void JFWDisplay::ctor_subroutine(const GXRenderModeObj* rmode, bool enableAlpha) clearEfb_init(); JUTProcBar::create(); JUTProcBar::clear(); + mDrawInterval = 1; + mDrawCount = 0; + mIsDrawFrame = false; + mPreCopyDispFunc = nullptr; } -JFWDisplay::JFWDisplay(const _GXRenderModeObj* rmode, JKRHeap* heap, JUTXfb::EXfbNumber bufferCount, bool p3) { - ctor_subroutine(rmode, p3); +JFWDisplay::JFWDisplay(JKRHeap* heap, JUTXfb::EXfbNumber bufferCount, bool enableAlpha) { + ctor_subroutine(enableAlpha); mXfb = JUTXfb::createManager(heap, bufferCount); } JFWDisplay::~JFWDisplay() { - waitBlanking(2); + if (JUTVideo::getManager() != nullptr) { + waitBlanking(2); + } JUTProcBar::destroy(); JUTXfb::destroyManager(); + mXfb = nullptr; } JFWDisplay* JFWDisplay::createManager(const GXRenderModeObj* rmode, JKRHeap* heap, JUTXfb::EXfbNumber bufferCount, - bool p4) { + bool enableAlpha) { JUT_CONFIRM_MESSAGE(sManager == 0); - if (sManager == nullptr) - sManager = new JFWDisplay(rmode, heap, bufferCount, p4); + if (rmode != nullptr) { + JUTVideo::getManager()->setRenderMode(rmode); + } + + if (sManager == nullptr) { + sManager = new JFWDisplay(heap, bufferCount, enableAlpha); + } return sManager; } @@ -83,23 +79,26 @@ void JFWDisplay::destroyManager() { } void callDirectDraw() { - JUTChangeFrameBuffer(JUTXfb::getManager()->getDrawingXfb(), JUTVideo::getManager()->getEfbHeight(), - JUTVideo::getManager()->getFbWidth()); + JUTChangeFrameBuffer(JUTXfb::getManager()->getDrawingXfb(), (u16)JUTVideo::getManager()->getEfbHeight(), + (u16)JUTVideo::getManager()->getFbWidth()); JUTAssertion::flushMessage(); } void JFWDisplay::prepareCopyDisp() { - GXRenderModeObj* rmode = JUTVideo::getManager()->getRenderMode(); - u16 width = (u16)JUTVideo::getManager()->getFbWidth(); - u16 height = (u16)JUTVideo::getManager()->getEfbHeight(); - u16 xfbHeight = (u16)JUTVideo::getManager()->getXfbHeight(); + const GXRenderModeObj* rmode = JUTVideo::getManager()->getRenderMode(); + u16 height = rmode->efbHeight; + u16 width = rmode->fbWidth; + u16 xfbHeight = rmode->xfbHeight; + f32 yScale = GXGetYScaleFactor(height, xfbHeight); + u16 xfbLines = GXGetNumXfbLines(height, yScale); GXSetCopyClear(mClearColor, mZClear); GXSetDispCopySrc(0, 0, width, height); - GXSetDispCopyDst(width, xfbHeight); - GXSetDispCopyYScale(xfbHeight / (f32)height); + GXSetDispCopyDst(width, xfbLines); + GXSetDispCopyYScale(yScale); VIFlush(); - GXSetCopyFilter((GXBool)rmode->aa, rmode->sample_pattern, GX_ENABLE, rmode->vfilter); + GXSetCopyFilter((GXBool)JUTVideo::getManager()->isAntiAliasing(), JUTVideo::getManager()->getSamplePattern(), + GX_ENABLE, JUTVideo::getManager()->getVFilter()); GXSetCopyClamp((GXFBClamp)mClamp); GXSetDispCopyGamma((GXGamma)mGamma); GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE); @@ -108,13 +107,39 @@ void JFWDisplay::prepareCopyDisp() { } } +void JFWDrawDoneAlarm(); +void JFWThreadAlarmHandler(OSAlarm*, OSContext*); +void JFWGXAbortAlarmHandler(OSAlarm*, OSContext*); +void waitForTick(u32, u16); +void diagnoseGpHang(); + void JFWDisplay::drawendXfb_single() { - JUTXfb* manager = JUTXfb::getManager(); - if (manager->getDrawingXfbIndex() >= 0) { - prepareCopyDisp(); + JUTXfb* xfbMng = JUTXfb::getManager(); + + if (xfbMng->getDrawingXfbIndex() >= 0) { + const GXRenderModeObj* rmode = JUTVideo::getManager()->getRenderMode(); + u16 height = rmode->efbHeight; + u16 width = rmode->fbWidth; + u16 xfbHeight = rmode->xfbHeight; + f32 yScale = GXGetYScaleFactor(height, xfbHeight); + u16 xfbLines = GXGetNumXfbLines(height, yScale); + + GXSetCopyClear(mClearColor, mZClear); + GXSetDispCopySrc(0, 0, width, height); + GXSetDispCopyDst(width, xfbLines); + GXSetDispCopyYScale(yScale); + VIFlush(); + GXSetCopyFilter((GXBool)JUTVideo::getManager()->isAntiAliasing(), JUTVideo::getManager()->getSamplePattern(), + GX_ENABLE, JUTVideo::getManager()->getVFilter()); + GXSetCopyClamp((GXFBClamp)mClamp); + GXSetDispCopyGamma((GXGamma)mGamma); + GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE); + if (mEnableAlpha) { + GXSetAlphaUpdate(GX_ENABLE); + } JFWDrawDoneAlarm(); GXFlush(); - manager->setDrawnXfbIndex(manager->getDrawingXfbIndex()); + xfbMng->setDrawnXfbIndex(xfbMng->getDrawingXfbIndex()); } } @@ -123,9 +148,14 @@ void JFWDisplay::exchangeXfb_double() { if (xfbMng->getDrawnXfbIndex() == xfbMng->getDisplayingXfbIndex()) { if (xfbMng->getDrawingXfbIndex() >= 0) { + if (mPreCopyDispFunc != nullptr) { + mPreCopyDispFunc(); + } + prepareCopyDisp(); GXCopyDisp(xfbMng->getDrawingXfb(), GX_TRUE); if (mDrawDoneMethod == UNK_METHOD_0) { + xfbMng->setDrawnXfbIndex(xfbMng->getDrawingXfbIndex()); GXDrawDone(); JUTVideo::dummyNoDrawWait(); } else { @@ -140,7 +170,7 @@ void JFWDisplay::exchangeXfb_double() { xfbMng->setDrawnXfbIndex(cur_xfb_index); xfbMng->setDrawingXfbIndex(cur_xfb_index >= 0 ? cur_xfb_index ^ 1 : 0); } else { - clearEfb(JUtility::TColor(0, 0, 0, 0xff)); + clearEfb(mClearColor); if (xfbMng->getDrawingXfbIndex() < 0) { xfbMng->setDrawingXfbIndex(0); } @@ -169,7 +199,31 @@ void JFWDisplay::copyXfb_triple() { JUTXfb* xfbMng = JUTXfb::getManager(); if (xfbMng->getDrawingXfbIndex() >= 0) { - prepareCopyDisp(); + if (mPreCopyDispFunc != nullptr) { + mPreCopyDispFunc(); + } + + u16 xfbLines; + const GXRenderModeObj* rmode = JUTVideo::getManager()->getRenderMode(); + u16 height = rmode->efbHeight; + u16 width = rmode->fbWidth; + u16 xfbHeight = rmode->xfbHeight; + f32 yScale = GXGetYScaleFactor(height, xfbHeight); + xfbLines = GXGetNumXfbLines(height, yScale); + + GXSetCopyClear(mClearColor, mZClear); + GXSetDispCopySrc(0, 0, width, height); + GXSetDispCopyDst(width, xfbLines); + GXSetDispCopyYScale(yScale); + VIFlush(); + GXSetCopyFilter((GXBool)JUTVideo::getManager()->isAntiAliasing(), JUTVideo::getManager()->getSamplePattern(), + GX_ENABLE, JUTVideo::getManager()->getVFilter()); + GXSetCopyClamp((GXFBClamp)mClamp); + GXSetDispCopyGamma((GXGamma)mGamma); + GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE); + if (mEnableAlpha) { + GXSetAlphaUpdate(GX_ENABLE); + } GXCopyDisp(xfbMng->getDrawingXfb(), GX_TRUE); GXPixModeSync(); } @@ -179,7 +233,7 @@ void JFWDisplay::preGX() { GXInvalidateTexAll(); GXInvalidateVtxCache(); - if (mRMode->aa) { + if (JUTVideo::getManager()->isAntiAliasing()) { GXSetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); GXSetDither(GX_ENABLE); } else { @@ -194,8 +248,8 @@ void JFWDisplay::preGX() { } void JFWDisplay::endGX() { - u32 width = JUTVideo::getManager()->getFbWidth(); - u32 height = JUTVideo::getManager()->getEfbHeight(); + u16 width, height; + JUTVideo::getManager()->getBounds(width, height); J2DOrthoGraph ortho(0.0f, 0.0f, width, height, -1.0f, 1.0f); @@ -203,10 +257,11 @@ void JFWDisplay::endGX() { ortho.setPort(); mFader->control(); } - + ortho.setPort(); JUTDbPrint::getManager()->flush(); if (JUTConsoleManager::getManager() != nullptr) { + ortho.setPort(); JUTConsoleManager::getManager()->draw(); } @@ -220,9 +275,14 @@ void JFWDisplay::endGX() { } void JFWDisplay::beginRender() { - JUTProcBar::getManager()->wholeLoopEnd(); - JUTProcBar::getManager()->wholeLoopStart(); - JUTProcBar::getManager()->idleStart(); + if (mIsDrawFrame) { + JUTProcBar::getManager()->wholeLoopEnd(); + } + + if (mIsDrawFrame) { + JUTProcBar::getManager()->wholeLoopStart(); + JUTProcBar::getManager()->idleStart(); + } waitForTick(mTickRate, mFrameRate); JUTVideo::getManager()->waitRetraceIfNeed(); @@ -230,47 +290,64 @@ void JFWDisplay::beginRender() { u32 tick = OSGetTick(); mFrameTime = tick - mStartTick; mStartTick = tick; - mVideoFrameTime = mStartTick - JUTVideo::getVideoLastTick(); + mVideoFrameTime = mStartTick; - JUTProcBar::getManager()->idleEnd(); - JUTProcBar::getManager()->gpStart(); + if (mIsDrawFrame) { + JUTProcBar::getManager()->idleEnd(); + } - JUTXfb* xfbMgr = JUTXfb::getManager(); - switch (xfbMgr->getBufferNum()) { - case 1: - if (xfbMgr->getSDrawingFlag() != 2) { - xfbMgr->setSDrawingFlag(1); - clearEfb(JUtility::TColor(0, 0, 0, 0xff)); - } else { - xfbMgr->setSDrawingFlag(1); - } - xfbMgr->setDrawingXfbIndex(mDrawingXfbNo); - break; - case 2: - exchangeXfb_double(); - break; - case 3: - exchangeXfb_triple(); - break; - default: - break; - } - - preGX(); + if (mIsDrawFrame) { + JUTProcBar::getManager()->gpStart(); + + JUTXfb* xfbMng = JUTXfb::getManager(); + switch (xfbMng->getBufferNum()) { + case 1: + if (xfbMng->getSDrawingFlag() != 2) { + xfbMng->setSDrawingFlag(1); + clearEfb(mClearColor); + } else { + xfbMng->setSDrawingFlag(1); + } + xfbMng->setDrawingXfbIndex(mDrawingXfbNo); + break; + case 2: + exchangeXfb_double(); + break; + case 3: + exchangeXfb_triple(); + break; + default: + break; + } + } + + mDrawCount++; + bool isDrawFrame = mDrawCount >= mDrawInterval; + mIsDrawFrame = isDrawFrame; + if (isDrawFrame) { + mDrawCount = 0; + } + + if (mIsDrawFrame) { + clearEfb(); + preGX(); + } } void JFWDisplay::endRender() { endGX(); - switch (JUTXfb::getManager()->getBufferNum()) { - case 1: - drawendXfb_single(); - case 2: - break; - case 3: - copyXfb_triple(); - default: - break; + if (mIsDrawFrame) { + switch (JUTXfb::getManager()->getBufferNum()) { + case 1: + drawendXfb_single(); + case 2: + break; + case 3: + copyXfb_triple(); + default: + break; + } } JUTProcBar::getManager()->cpuStart(); @@ -279,34 +356,39 @@ void JFWDisplay::endRender() { void JFWDisplay::endFrame() { JUTProcBar::getManager()->cpuEnd(); - JUTProcBar::getManager()->gpWaitStart(); - - switch (JUTXfb::getManager()->getBufferNum()) { - case 1: - break; - case 2: - JFWDrawDoneAlarm(); - GXFlush(); - break; - case 3: - JFWDrawDoneAlarm(); - GXFlush(); - break; - default: - break; - } - - JUTProcBar::getManager()->gpWaitEnd(); - JUTProcBar::getManager()->gpEnd(); - - static u32 prevFrame = VIGetRetraceCount(); - u32 retrace_cnt = VIGetRetraceCount(); - JUTProcBar::getManager()->setCostFrame(retrace_cnt - prevFrame); - prevFrame = retrace_cnt; + + if (mIsDrawFrame) { + JUTProcBar::getManager()->gpWaitStart(); + + switch (JUTXfb::getManager()->getBufferNum()) { + case 1: + break; + case 2: + JFWDrawDoneAlarm(); + GXFlush(); + break; + case 3: + JFWDrawDoneAlarm(); + GXFlush(); + break; + default: + break; + } + + JUTProcBar::getManager()->gpWaitEnd(); + JUTProcBar::getManager()->gpEnd(); + } + + if (mIsDrawFrame) { + static u32 prevFrame = VIGetRetraceCount(); + u32 retrace_cnt = VIGetRetraceCount(); + JUTProcBar::getManager()->setCostFrame(retrace_cnt - prevFrame); + prevFrame = retrace_cnt; + } } -void JFWDisplay::waitBlanking(int p1) { - while (p1-- > 0) { +void JFWDisplay::waitBlanking(int count) { + while (count-- > 0) { waitForTick(mTickRate, mFrameRate); } } @@ -335,6 +417,7 @@ void waitForTick(u32 p1, u16 p2) { void JFWThreadAlarmHandler(OSAlarm* p_alarm, OSContext* p_ctx) { JFWAlarm* alarm = static_cast(p_alarm); + alarm->removeLink(); OSResumeThread(alarm->getThread()); } @@ -343,25 +426,25 @@ void JFWDisplay::threadSleep(s64 time) { alarm.createAlarm(); alarm.setThread(OSGetCurrentThread()); s32 status = OSDisableInterrupts(); + alarm.appendLink(); OSSetAlarm(&alarm, time, JFWThreadAlarmHandler); OSSuspendThread(alarm.getThread()); OSRestoreInterrupts(status); } -static GXTexObj clear_z_tobj; -static u8 clear_z_TX[] - __attribute__((aligned(32))) = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, - 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +GXTexObj clear_z_tobj; +u8 clear_z_TX[] __attribute__((aligned(32))) = { + 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; void* JFWDisplay::changeToSingleXfb(int index) { JUTXfb* xfb = JUTXfb::getManager(); s16 xfbNo = !index ? 1 : 0; - // Check if xfb is single buffered if (xfb->getBufferNum() != 2) { return nullptr; } @@ -393,7 +476,6 @@ void* JFWDisplay::changeToSingleXfb(int index) { void* JFWDisplay::changeToDoubleXfb() { JUTXfb* xfb = JUTXfb::getManager(); - // Check if xfb is not single buffered already if (!mIsSingleXfb) { return nullptr; } @@ -417,10 +499,22 @@ void JFWDisplay::clearEfb_init() { GXInitTexObjLOD(&clear_z_tobj, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); } +void JFWDisplay::clearEfb() { + clearEfb(mClearColor); +} + void JFWDisplay::clearEfb(GXColor color) { + int width = JUTVideo::getManager()->getFbWidth(); + int height = JUTVideo::getManager()->getEfbHeight(); + + clearEfb(0, 0, width, height, color); +} + +void JFWDisplay::clearEfb(int x, int y, int w, int h, GXColor color) { Mtx44 mtx; - u16 height = mRMode->efbHeight; - u16 width = mRMode->fbWidth; + const GXRenderModeObj* rmode = JUTVideo::getManager()->getRenderMode(); + u16 width = rmode->fbWidth; + u16 height = rmode->efbHeight; C_MTXOrtho(mtx, 0.0f, height, 0.0f, width, 0.0f, 1.0f); GXSetProjection(mtx, GX_ORTHOGRAPHIC); @@ -454,40 +548,40 @@ void JFWDisplay::clearEfb(GXColor color) { if (mEnableAlpha) { GXSetAlphaUpdate(GX_ENABLE); - GXSetDstAlpha(GX_ENABLE, 0); + GXSetDstAlpha(GX_ENABLE, color.a); } GXSetZMode(GX_ENABLE, GX_ALWAYS, GX_ENABLE); GXSetCullMode(GX_CULL_BACK); GXBegin(GX_QUADS, GX_VTXFMT0, 4); - GXPosition2u16(0, 0); + GXPosition2u16(x, y); GXTexCoord2u8(0, 0); - GXPosition2u16(0 + width, 0); + GXPosition2u16(x + w, y); GXTexCoord2u8(1, 0); - GXPosition2u16(0 + width, 0 + height); + GXPosition2u16(x + w, y + h); GXTexCoord2u8(1, 1); - GXPosition2u16(0, 0 + height); + GXPosition2u16(x, y + h); GXTexCoord2u8(0, 1); GXEnd(); GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z24X8, 0); GXSetZCompLoc(GX_ENABLE); if (mEnableAlpha) { - GXSetDstAlpha(GX_DISABLE, 0); + GXSetDstAlpha(GX_DISABLE, color.a); } } void JFWDisplay::calcCombinationRatio() { u32 vidInterval = JUTVideo::getVideoInterval(); - s32 unk30 = mFrameTime * 2; + s32 frameTime = mFrameTime * 2; s32 i = vidInterval; - for (; i < unk30; i += vidInterval) {} + for (; i < frameTime; i += vidInterval) {} - s32 tmp = (i - unk30) - mVideoFrameTime; + s32 tmp = (i - frameTime) - mVideoFrameTime; if (tmp < 0) { tmp += vidInterval; } @@ -497,7 +591,25 @@ void JFWDisplay::calcCombinationRatio() { } } -void JFWGXAbortAlarmHandler(OSAlarm* param_0, OSContext* param_1) { +void JFWDrawDoneAlarm() { + BOOL status; + JFWAlarm alarm; + + status = OSDisableInterrupts(); + alarm.createAlarm(); + alarm.appendLink(); + OSRestoreInterrupts(status); + + OSSetAlarm(&alarm, OS_TIMER_CLOCK * 0.5, JFWGXAbortAlarmHandler); + GXDrawDone(); + + status = OSDisableInterrupts(); + alarm.cancelAlarm(); + alarm.removeLink(); + OSRestoreInterrupts(status); +} + +void JFWGXAbortAlarmHandler(OSAlarm* alarm, OSContext* context) { diagnoseGpHang(); GXAbortFrame(); GXSetDrawDone(); diff --git a/src/static/JSystem/JKernel/JKRAram.cpp b/src/static/JSystem/JKernel/JKRAram.cpp index 5111c107..fce43d20 100644 --- a/src/static/JSystem/JKernel/JKRAram.cpp +++ b/src/static/JSystem/JKernel/JKRAram.cpp @@ -84,17 +84,15 @@ void* JKRAram::run() { } while (true); } -bool JKRAram::checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 blockSize) { +bool JKRAram::checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 param_4) { if (!IS_ALIGNED((u32)addr, 0x20) && !IS_ALIGNED(size, 0x20)) { - JPANIC(225, ":::address not 32Byte aligned."); + JPANIC(219, ":::address not 32Byte aligned."); return false; } - if (block) { - if (!IS_ALIGNED(block->getAddress() + blockSize, 0x20)) { - JPANIC(234, ":::address not 32Byte aligned."); - return false; - } + if (block != nullptr && !IS_ALIGNED(block->getAddress() + param_4, 0x20)) { + JPANIC(227, ":::address not 32Byte aligned."); + return false; } return true; } @@ -108,17 +106,17 @@ void JKRAram::changeGroupIdIfNeed(u8* data, int groupId) { } JKRAramBlock* JKRAram::mainRamToAram(u8* buf, u32 address, u32 alignedSize, JKRExpandSwitch expandSwitch, u32 fileSize, - JKRHeap* heap, int id) { + JKRHeap* heap, int id, u32* pSize) { JKRAramBlock* block = nullptr; checkOkAddress(buf, address, nullptr, 0); if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { expandSwitch = - (JKRCheckCompressed(buf) == JKRCOMPRESSION_NONE) ? EXPAND_SWITCH_DEFAULT : EXPAND_SWITCH_DECOMPRESS; + (JKRCheckCompressed_noASR(buf) == JKRCOMPRESSION_NONE) ? EXPAND_SWITCH_DEFAULT : EXPAND_SWITCH_DECOMPRESS; } if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { - u32 expandSize = JKRCheckCompressed(buf) != JKRCOMPRESSION_NONE ? JKRDecompExpandSize(buf) : 0; + u32 expandSize = JKRDecompExpandSize(buf); if (fileSize == 0 || fileSize > expandSize) { - fileSize = expandSize; + fileSize = ALIGN_NEXT(expandSize, 32); } if (address == 0) { block = JKRAllocFromAram(fileSize, JKRAramHeap::Head); @@ -129,24 +127,29 @@ JKRAramBlock* JKRAram::mainRamToAram(u8* buf, u32 address, u32 alignedSize, JKRE address = block->getAddress(); } if (alignedSize == 0 || alignedSize > expandSize) - alignedSize = expandSize; + alignedSize = ALIGN_NEXT(expandSize, 32); - if (fileSize > alignedSize) - fileSize = alignedSize; + if (alignedSize > fileSize) + alignedSize = fileSize; - void* allocatedMem = JKRAllocFromHeap(heap, fileSize, -32); + u8* allocatedMem = (u8*)JKRAllocFromHeap(heap, fileSize, -32); if (allocatedMem == nullptr) { if (block != nullptr) { delete block; } block = nullptr; } else { - JKRDecompress(buf, (u8*)allocatedMem, fileSize, 0); + JKRDecompress(buf, allocatedMem, fileSize, 0); JKRAramPcs(0, (u32)allocatedMem, address, alignedSize, block); JKRFreeToHeap(heap, allocatedMem); block = block == nullptr ? (JKRAramBlock*)-1 : block; + if (pSize != nullptr) { + *pSize = alignedSize; + } } } else { + if (fileSize != 0 && alignedSize > fileSize) + alignedSize = fileSize; if (address == 0) { block = JKRAllocFromAram(alignedSize, JKRAramHeap::Head); block->newGroupID(decideAramGroupId(id)); @@ -158,16 +161,18 @@ JKRAramBlock* JKRAram::mainRamToAram(u8* buf, u32 address, u32 alignedSize, JKRE JKRAramPcs(0, (u32)buf, address, alignedSize, block); block = block == nullptr ? (JKRAramBlock*)-1 : block; + if (pSize != nullptr) + *pSize = alignedSize; } return block; } JKRAramBlock* JKRAram::mainRamToAram(u8* buf, JKRAramBlock* block, u32 alignedSize, JKRExpandSwitch expandSwitch, - u32 fileSize, JKRHeap* heap, int id) { + u32 fileSize, JKRHeap* heap, int id, u32* pSize) { checkOkAddress(buf, 0, block, 0); if (block == nullptr) { - return mainRamToAram(buf, (u32)0, alignedSize, expandSwitch, fileSize, heap, id); + return mainRamToAram(buf, (u32)0, alignedSize, expandSwitch, fileSize, heap, id, pSize); } u32 blockSize = block->getSize(); @@ -178,14 +183,13 @@ JKRAramBlock* JKRAram::mainRamToAram(u8* buf, JKRAramBlock* block, u32 alignedSi alignedSize = alignedSize > blockSize ? blockSize : alignedSize; - return mainRamToAram(buf, block->getAddress(), alignedSize, expandSwitch, fileSize, heap, id); + return mainRamToAram(buf, block->getAddress(), alignedSize, expandSwitch, fileSize, heap, id, pSize); } -// TODO: figure out name of parameter 5 u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, JKRExpandSwitch expandSwitch, u32 p5, JKRHeap* heap, int id, u32* pSize) { int compression = JKRCOMPRESSION_NONE; - if (pSize) + if (pSize != nullptr) *pSize = 0; checkOkAddress(buf, address, nullptr, 0); @@ -194,14 +198,12 @@ u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, JKRExpandSwitch ex if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { u8 buffer[64]; u8* bufPtr = (u8*)ALIGN_NEXT((u32)buffer, 32); - JKRAramPcs(1, address, (u32)bufPtr, sizeof(buffer) / 2, - nullptr); // probably change sizeof(buffer) / 2 to 32 - compression = JKRCheckCompressed(bufPtr); + JKRAramPcs(1, address, (u32)bufPtr, sizeof(buffer) / 2, nullptr); + compression = JKRCheckCompressed_noASR(bufPtr); expandSize = JKRDecompExpandSize(bufPtr); } - if (compression == JKRCOMPRESSION_YAZ0) // SZS - { + if (compression == JKRCOMPRESSION_YAZ0) { if (p5 != 0 && p5 < expandSize) expandSize = p5; @@ -211,14 +213,10 @@ u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, JKRExpandSwitch ex return nullptr; else { changeGroupIdIfNeed(buf, id); - JKRDecompressFromAramToMainRam(address, buf, srcSize, expandSize, 0); - if (pSize) { - *pSize = expandSize; - } + JKRDecompressFromAramToMainRam(address, buf, srcSize, expandSize, 0, pSize); return buf; } - } else if (compression == JKRCOMPRESSION_YAY0) // SZP - { + } else if (compression == JKRCOMPRESSION_YAY0) { u8* szpSpace = (u8*)JKRAllocFromHeap(heap, srcSize, -32); if (szpSpace == nullptr) { return nullptr; @@ -227,23 +225,24 @@ u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, JKRExpandSwitch ex if (p5 != 0 && p5 < expandSize) expandSize = p5; - u8* szpBuffer = buf == nullptr ? (u8*)JKRAllocFromHeap(heap, expandSize, 32) : buf; + if (buf == nullptr) { + buf = (u8*)JKRAllocFromHeap(heap, expandSize, 32); + } - if (szpBuffer == nullptr) { + if (buf == nullptr) { JKRFree(szpSpace); return nullptr; } else { - changeGroupIdIfNeed(szpBuffer, id); - JKRDecompress(szpSpace, szpBuffer, expandSize, 0); + changeGroupIdIfNeed(buf, id); + JKRDecompress(szpSpace, buf, expandSize, 0); JKRFreeToHeap(heap, szpSpace); - if (pSize) { + if (pSize != nullptr) { *pSize = expandSize; } - return szpBuffer; + return buf; } } - } else // Not compressed or ASR - { + } else { if (buf == nullptr) buf = (u8*)JKRAllocFromHeap(heap, srcSize, 32); if (buf == nullptr) { @@ -259,28 +258,26 @@ u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, JKRExpandSwitch ex } } -// TODO: figure out what p6 does u8* JKRAram::aramToMainRam(JKRAramBlock* block, u8* buf, u32 bufSize, u32 alignedBlockSize, JKRExpandSwitch expandSwitch, u32 p6, JKRHeap* heap, int id, u32* pSize) { - int compression = JKRCOMPRESSION_NONE; - if (pSize) + if (pSize != nullptr) *pSize = 0; checkOkAddress(buf, 0, block, alignedBlockSize); if (block == nullptr) { - JPANIC(667, ":::Bad Aram Block specified.\n"); + return nullptr; } - u32 freeSize = block->getSize(); + u32 blockSize = block->getSize(); - if (alignedBlockSize >= freeSize) + if (alignedBlockSize >= blockSize) return nullptr; - bufSize = bufSize == 0 ? freeSize : bufSize; + bufSize = bufSize == 0 ? blockSize : bufSize; - if (alignedBlockSize + bufSize > freeSize) { - bufSize = freeSize - alignedBlockSize; + if (alignedBlockSize + bufSize > blockSize) { + bufSize = blockSize - alignedBlockSize; } return aramToMainRam(alignedBlockSize + block->getAddress(), buf, bufSize, expandSwitch, p6, heap, id, pSize); @@ -309,15 +306,22 @@ static u8* nextSrcData(u8* current); static int decompSZS_subroutine(u8* src, u8* dest); void JKRAram::aramSync(JKRAMCommand*, int) { - // JUT_REPORT_MSG("bad aramSync\n"); } -int JKRDecompressFromAramToMainRam(u32 src, void* dst, u32 srcLength, u32 dstLength, u32 offset) { - szpBuf = (u8*)JKRAllocFromSysHeap(SZP_BUFFERSIZE, 32); +int JKRDecompressFromAramToMainRam(u32 src, void* dst, u32 srcLength, u32 dstLength, u32 offset, u32* resourceSize) { + BOOL interrupts = OSDisableInterrupts(); + if (isInitMutex == false) { + OSInitMutex(&decompMutex); + isInitMutex = true; + } + OSRestoreInterrupts(interrupts); + OSLockMutex(&decompMutex); + u32 szsBufferSize = JKRAram::getSZSBufferSize(); + szpBuf = (u8*)JKRAllocFromSysHeap(szsBufferSize, 32); JUT_ASSERT(szpBuf != 0); - szpEnd = szpBuf + SZP_BUFFERSIZE; + szpEnd = szpBuf + szsBufferSize; if (offset != 0) { refBuf = (u8*)JKRAllocFromSysHeap(0x1120, 0); JUT_ASSERT(refBuf != 0); @@ -333,6 +337,8 @@ int JKRDecompressFromAramToMainRam(u32 src, void* dst, u32 srcLength, u32 dstLen fileOffset = offset; readCount = 0; maxDest = dstLength; + tsPtr = (resourceSize != 0) ? resourceSize : &tsArea; + *tsPtr = 0; decompSZS_subroutine(firstSrcData(), (u8*)dst); JKRFree(szpBuf); @@ -341,6 +347,9 @@ int JKRDecompressFromAramToMainRam(u32 src, void* dst, u32 srcLength, u32 dstLen JKRFree(refBuf); } + DCStoreRangeNoSync(dst, *tsPtr); + OSUnlockMutex(&decompMutex); + return 0; } @@ -348,6 +357,7 @@ int decompSZS_subroutine(u8* src, u8* dest) { u8* endPtr; s32 validBitCount = 0; s32 currCodeByte = 0; + u32 ts = 0; if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') { return -1; @@ -374,6 +384,7 @@ int decompSZS_subroutine(u8* src, u8* dest) { if (readCount >= fileOffset) { *dest = *src; dest++; + ts++; if (dest == endPtr) { break; } @@ -387,6 +398,7 @@ int decompSZS_subroutine(u8* src, u8* dest) { *dest = *src; dest++; src++; + ts++; if (dest == endPtr) { break; } @@ -416,6 +428,7 @@ int decompSZS_subroutine(u8* src, u8* dest) { if (readCount >= fileOffset) { *dest = *copySource; dest++; + ts++; if (dest == endPtr) { break; } @@ -435,6 +448,7 @@ int decompSZS_subroutine(u8* src, u8* dest) { do { *dest = *copySource; dest++; + ts++; if (dest == endPtr) { break; } @@ -447,6 +461,7 @@ int decompSZS_subroutine(u8* src, u8* dest) { currCodeByte <<= 1; validBitCount--; } while (dest < endPtr); + *tsPtr = ts; return 0; } @@ -461,6 +476,10 @@ static u8* firstSrcData() { srcOffset += transSize; transLeft -= transSize; + if (transLeft == 0) { + srcLimit = buf + transSize; + } + return buf; } diff --git a/src/static/JSystem/JKernel/JKRAramArchive.cpp b/src/static/JSystem/JKernel/JKRAramArchive.cpp index 835409d2..2438037a 100644 --- a/src/static/JSystem/JKernel/JKRAramArchive.cpp +++ b/src/static/JSystem/JKernel/JKRAramArchive.cpp @@ -1,5 +1,7 @@ #include #include +#include "_mem.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/arith.h" #include "JSystem/JKernel/JKRAram.h" #include "JSystem/JKernel/JKRArchive.h" @@ -38,6 +40,10 @@ JKRAramArchive::~JKRAramArchive() { mArcInfoBlock = nullptr; } + if (mExpandSizes) { + JKRFree(mExpandSizes); + mExpandSizes = nullptr; + } if (mDvdFile) { delete mDvdFile; } @@ -53,9 +59,9 @@ JKRAramArchive::~JKRAramArchive() { void JKRAramArchive::fixedInit(s32 entryNum, EMountDirection direction) { mIsMounted = false; mMountDirection = direction; - mMountMode = 2; + mMountMode = MOUNT_ARAM; mMountCount = 1; - _54 = 2; + _58 = 2; mHeap = JKRGetCurrentHeap(); mEntryNum = entryNum; @@ -69,7 +75,7 @@ bool JKRAramArchive::mountFixed(s32 entryNum, EMountDirection direction) { if (entryNum < 0) return false; - if (check_mount_already(entryNum)) + if (check_mount_already(entryNum, JKRGetCurrentHeap())) return false; fixedInit(entryNum, direction); @@ -115,10 +121,6 @@ void JKRAramArchive::unmountFixed() { mIsMounted = false; } -#if DEBUG -CW_FORCE_STRINGS(JKRAramArchive_cpp, __FILE__, "isMounted()", "mMountCount == 1") -#endif - bool JKRAramArchive::open(long entryNum) { mArcInfoBlock = nullptr; mDirectories = nullptr; @@ -132,14 +134,13 @@ bool JKRAramArchive::open(long entryNum) { return 0; } - // NOTE: a different struct is used here for sure, unfortunately i can't get - // any hits on this address, so gonna leave it like this for now SArcHeader* mem = (SArcHeader*)JKRAllocFromSysHeap(32, -32); if (mem == nullptr) { mMountMode = 0; } else { JKRDvdToMainRam(entryNum, (u8*)mem, EXPAND_SWITCH_DECOMPRESS, 32, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 0, - &mCompression); + &mCompression, nullptr); + DCInvalidateRange(mem, 32); int alignment = mMountDirection == MOUNT_DIRECTION_HEAD ? 32 : -32; u32 alignedSize = ALIGN_NEXT(mem->file_data_offset, 32); mArcInfoBlock = (SArcDataInfo*)JKRAllocFromHeap(mHeap, alignedSize, alignment); @@ -147,20 +148,49 @@ bool JKRAramArchive::open(long entryNum) { mMountMode = 0; } else { JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, EXPAND_SWITCH_DECOMPRESS, alignedSize, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, 32, nullptr); + JKRDvdRipper::ALLOC_DIR_TOP, 32, nullptr, nullptr); + DCInvalidateRange(mArcInfoBlock, alignedSize); mDirectories = (SDIDirEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->node_offset); mFileEntries = (SDIFileEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->file_entry_offset); mStrTable = (const char*)((u8*)mArcInfoBlock + mArcInfoBlock->string_table_offset); + mExpandSizes = nullptr; + + u8 compressedFiles = 0; + + SDIFileEntry* fileEntry = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { + u8 flag = fileEntry->mFlag >> 24; + if ((flag & 1)) { + compressedFiles |= (flag & JKRARCHIVE_ATTR_COMPRESSION); + } + fileEntry++; + } + + if (compressedFiles != 0) { + mExpandSizes = (u32*)JKRAllocFromHeap(mHeap, mArcInfoBlock->num_file_entries << 2, abs(alignment)); + if (mExpandSizes == nullptr) { + JKRFree(mArcInfoBlock); + mMountMode = 0; + goto cleanup; + } + memset(mExpandSizes, 0, mArcInfoBlock->num_file_entries << 2); + } u32 aramSize = ALIGN_NEXT(mem->file_data_length, 32); mBlock = JKRAllocFromAram(aramSize, mMountDirection == MOUNT_DIRECTION_HEAD ? JKRAramHeap::Head : JKRAramHeap::Tail); if (mBlock == nullptr) { + if (mArcInfoBlock) { + JKRFree(mArcInfoBlock); + } + if (mExpandSizes) { + JKRFree(mExpandSizes); + } mMountMode = 0; } else { JKRDvdToAram(entryNum, mBlock->getAddress(), EXPAND_SWITCH_DECOMPRESS, - mem->header_length + mem->file_data_offset, 0); + mem->header_length + mem->file_data_offset, 0, nullptr); } } } @@ -169,10 +199,12 @@ bool JKRAramArchive::open(long entryNum) { JKRFreeToSysHeap(mem); } if (mMountMode == 0) { - JREPORTF(":::[%s: %d] Cannot alloc memory\n", __FILE__, - 415); // TODO: macro + if (mDvdFile != nullptr) { + delete mDvdFile; + } + return false; } - return mMountMode != 0; + return true; } void* JKRAramArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { @@ -181,17 +213,26 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { u32 sizeRef; u8* data; - if (fileEntry->mData) { - if (pSize) - *pSize = fileEntry->mSize; + if (pSize == nullptr) { + pSize = &sizeRef; + } + + int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + if (fileEntry->mData == nullptr) { + u32 size = fetchResource_subroutine(fileEntry->mDataOffset + mBlock->getAddress(), fileEntry->mSize, mHeap, + compression, &data); + *pSize = size; + if (size == 0) { + return nullptr; + } + fileEntry->mData = data; + if (compression == JKRCOMPRESSION_YAZ0) { + setExpandSize(fileEntry, *pSize); + } + } else if (compression == JKRCOMPRESSION_YAZ0) { + *pSize = getExpandSize(fileEntry); } else { - u32 addres = mBlock->getAddress(); - int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); - u32 size = - fetchResource_subroutine(fileEntry->mDataOffset + addres, fileEntry->mSize, mHeap, compression, &data); - if (pSize) - *pSize = size; - fileEntry->mData = (void*)data; + *pSize = fileEntry->mSize; } return fileEntry->mData; @@ -204,15 +245,28 @@ void* JKRAramArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry if (fileSize > compressedSize) { fileSize = compressedSize; } - if (fileEntry->mData) { - JKRHeap::copyMemory(data, fileEntry->mData, fileSize); - } else { - int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + + int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + if (fileEntry->mData == nullptr) { if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) - compression = 0; + compression = JKRCOMPRESSION_NONE; + compressedSize = (s32)ALIGN_PREV(compressedSize, 32); fileSize = fetchResource_subroutine(fileEntry->mDataOffset + mBlock->getAddress(), fileSize, (u8*)data, compressedSize, compression); + } else { + if (compression == JKRCOMPRESSION_YAZ0) { + u32 expandSize = getExpandSize(fileEntry); + if (expandSize != 0) { + fileSize = expandSize; + } + } + + if (fileSize > compressedSize) { + fileSize = compressedSize; + } + + JKRHeap::copyMemory(data, fileEntry->mData, fileSize); } if (pSize != nullptr) { @@ -255,7 +309,7 @@ u32 JKRAramArchive::fetchResource_subroutine(u32 srcAram, u32 size, u8* data, u3 &sizeRef); return sizeRef; default: - JPANIC(550, ":::??? bad sequence\n"); + JPANIC(655, "??? bad sequence\n"); return 0; } } @@ -272,23 +326,53 @@ u32 JKRAramArchive::fetchResource_subroutine(u32 srcAram, u32 size, JKRHeap* hea JKRAramToMainRam(srcAram, buffer, alignedSize, EXPAND_SWITCH_DEFAULT, alignedSize, nullptr, -1, nullptr); *pBuf = buffer; - return size; case JKRCOMPRESSION_YAY0: case JKRCOMPRESSION_YAZ0: - u8* header = (u8*)JKRAllocFromHeap(heap, 0x20, 0x20); - JKRAramToMainRam(srcAram, header, 0x20, EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); - u32 expandSize = JKRDecompExpandSize(header); - JKRFreeToHeap(heap, header); - expandSize = ALIGN_NEXT(expandSize, 32); - buffer = (u8*)JKRAllocFromHeap(heap, expandSize, 0x20); + u8 decompBuf[64]; + u8* bufptr = (u8*)ALIGN_NEXT((u32)decompBuf, 32); + JKRAramToMainRam(srcAram, bufptr, sizeof(decompBuf) / 2, EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); + + u32 expandSize = ALIGN_NEXT(JKRDecompExpandSize(bufptr), 32); + buffer = (u8*)JKRAllocFromHeap(heap, expandSize, 32); JUT_ASSERT(buffer); JKRAramToMainRam(srcAram, buffer, alignedSize, EXPAND_SWITCH_DECOMPRESS, expandSize, heap, -1, &resSize); *pBuf = buffer; return resSize; default: - JPANIC(605, ":::??? bad sequence\n"); + JPANIC(713, "??? bad sequence\n"); return 0; } } + +u32 JKRAramArchive::getExpandedResSize(const void* resource) const { + if (mExpandSizes == nullptr) { + return getResSize(resource); + } + + SDIFileEntry* fileEntry = findPtrResource(resource); + if (fileEntry == nullptr) { + return 0xffffffff; + } + + u8 flags = (fileEntry->mFlag >> 0x18); + if ((flags & 4) == 0) { + return getResSize(resource); + } + + u32 expandSize = getExpandSize(fileEntry); + if (expandSize != 0) { + return expandSize; + } + + u8 buf[64]; + u8* bufPtr = (u8*)ALIGN_NEXT((u32)buf, 32); + + JKRAramToMainRam(fileEntry->mDataOffset + mBlock->getAddress(), bufPtr, sizeof(buf) / 2, EXPAND_SWITCH_DEFAULT, 0, + nullptr, -1, nullptr); + + u32 decompExpandSize = JKRDecompExpandSize(bufPtr); + const_cast(this)->setExpandSize(fileEntry, decompExpandSize); + return decompExpandSize; +} diff --git a/src/static/JSystem/JKernel/JKRAramPiece.cpp b/src/static/JSystem/JKernel/JKRAramPiece.cpp index 30f64675..9ba6277f 100644 --- a/src/static/JSystem/JKernel/JKRAramPiece.cpp +++ b/src/static/JSystem/JKernel/JKRAramPiece.cpp @@ -38,7 +38,7 @@ JKRAMCommand* JKRAramPiece::orderAsync(int direction, u32 source, u32 destinatio JLOGF("source = %x\n", source); JLOGF("destination = %x\n", destination); JLOGF("length = %x\n", length); - JPANICLINE(102); + JPANIC(108, "illegal address. abort."); } JKRAramCommand* aramCmd = new (JKRGetSystemHeap(), -4) JKRAramCommand(); diff --git a/src/static/JSystem/JKernel/JKRAramStream.cpp b/src/static/JSystem/JKernel/JKRAramStream.cpp index b5356e53..a78d4d67 100644 --- a/src/static/JSystem/JKernel/JKRAramStream.cpp +++ b/src/static/JSystem/JKernel/JKRAramStream.cpp @@ -72,7 +72,7 @@ s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) { buffer = (u8*)JKRAllocFromHeap(heap, bufferSize, -0x20); command->mTransferBuffer = buffer; } else { - buffer = (u8*)JKRAllocFromHeap(nullptr, bufferSize, -0x20); + buffer = (u8*)JKRAllocFromSysHeap(bufferSize, -0x20); command->mTransferBuffer = buffer; } @@ -86,7 +86,7 @@ s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) { } else { heap->dump(); } - JPANIC(169, "abort\n"); + JPANIC(172, ":::Cannot alloc memory\n"); } if (buffer) { @@ -95,11 +95,19 @@ s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) { u32 length = (dstSize > bufferSize) ? bufferSize : dstSize; s32 readLength = command->mStream->read(buffer, length); + if (readLength == 0) { + writtenLength = 0; + break; + } JKRAramPcs(0, (u32)buffer, destination, length, nullptr); dstSize -= length; writtenLength += length; destination += length; + + if (command->mReturnSize) { + *command->mReturnSize += length; + } } if (command->mAllocatedTransferBuffer) { @@ -112,24 +120,22 @@ s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) { return writtenLength; }; -/* - * Unused function, made-up contents. Do not take this seriously! - * While the function exists in the map, this is almost certainly incorrect. - * Should exist to generate JSURandomInputStream::getAvailable() const - * afterwards. - */ JKRAramStreamCommand* JKRAramStream::write_StreamToAram_Async(JSUFileInputStream* stream, JKRAramBlock* addr, u32 size, - u32 offset) { + u32 offset, u32* returnSize) { JKRAramStreamCommand* command = new (JKRGetSystemHeap(), -4) JKRAramStreamCommand(); command->type = JKRAramStreamCommand::ECT_WRITE; command->mAddress = (u32)addr; command->mSize = size; command->mStream = stream; - command->_28 = stream->getAvailable(); + command->_2C = stream->getAvailable(); command->mOffset = offset; command->mTransferBuffer = transBuffer; command->mHeap = transHeap; command->mTransferBufferSize = transSize; + command->mReturnSize = returnSize; + if (returnSize) { + *returnSize = 0; + } OSInitMessageQueue(&command->mMessageQueue, &command->mMessage, 1); OSSendMessage(&sMessageQueue, command, OS_MESSAGE_BLOCK); @@ -137,17 +143,21 @@ JKRAramStreamCommand* JKRAramStream::write_StreamToAram_Async(JSUFileInputStream } JKRAramStreamCommand* JKRAramStream::write_StreamToAram_Async(JSUFileInputStream* stream, u32 addr, u32 size, - u32 offset) { + u32 offset, u32* returnSize) { JKRAramStreamCommand* command = new (JKRGetSystemHeap(), -4) JKRAramStreamCommand(); command->type = JKRAramStreamCommand::ECT_WRITE; command->mAddress = addr; command->mSize = size; command->mStream = stream; - command->_28 = 0; + command->_2C = 0; command->mOffset = offset; command->mTransferBuffer = transBuffer; command->mHeap = transHeap; command->mTransferBufferSize = transSize; + command->mReturnSize = returnSize; + if (returnSize) { + *returnSize = 0; + } OSInitMessageQueue(&command->mMessageQueue, &command->mMessage, 1); OSSendMessage(&sMessageQueue, command, OS_MESSAGE_BLOCK); diff --git a/src/static/JSystem/JKernel/JKRArchivePri.cpp b/src/static/JSystem/JKernel/JKRArchivePri.cpp index 591f1883..2adb084c 100644 --- a/src/static/JSystem/JKernel/JKRArchivePri.cpp +++ b/src/static/JSystem/JKernel/JKRArchivePri.cpp @@ -16,7 +16,7 @@ JKRArchive::JKRArchive(s32 entryNum, JKRArchive::EMountMode mountMode) : JKRFile mIsMounted = false; mMountMode = mountMode; mMountCount = 1; - _54 = 1; + _58 = 1; mHeap = JKRHeap::findFromRoot(this); if (!mHeap) { mHeap = JKRHeap::sCurrentHeap; @@ -187,3 +187,19 @@ const char* JKRArchive::CArcName::store(const char* name, char endChar) { return nullptr; return name + 1; } + +void JKRArchive::setExpandSize(SDIFileEntry* entry, u32 size) { + u32 index = entry - mFileEntries; + if (mExpandSizes == nullptr || index >= mArcInfoBlock->num_file_entries) { + return; + } + mExpandSizes[index] = size; +} + +u32 JKRArchive::getExpandSize(SDIFileEntry* entry) const { + u32 index = entry - mFileEntries; + if (mExpandSizes == nullptr || index >= mArcInfoBlock->num_file_entries) { + return 0; + } + return mExpandSizes[index]; +} diff --git a/src/static/JSystem/JKernel/JKRArchivePub.cpp b/src/static/JSystem/JKernel/JKRArchivePub.cpp index d49287a2..af9d2e42 100644 --- a/src/static/JSystem/JKernel/JKRArchivePub.cpp +++ b/src/static/JSystem/JKernel/JKRArchivePub.cpp @@ -11,18 +11,12 @@ // TODO: this file should emit a vtable but it doesn't, luckily JKRArchivePri // does that and it doesn't cause any issues -JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* pHeap) { - // UNUSED FUNCTION - JKRHeap* heap = pHeap; - if (heap == nullptr) { - heap = JKRGetCurrentHeap(); - } - - JSUListIterator iterator; - for (iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) { +JKRArchive* JKRArchive::check_mount_already(s32 entryNum) { + for (JSUListIterator iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); + ++iterator) { if (iterator->getVolumeType() == 'RARC') { JKRArchive* archive = (JKRArchive*)iterator.getObject(); // in TP debug it calls operator-> ? - if (archive->mEntryNum == entryNum && archive->mHeap == heap) { + if (archive->mEntryNum == entryNum) { archive->mMountCount++; return archive; } @@ -31,12 +25,17 @@ JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* pHeap) { return nullptr; } -JKRArchive* JKRArchive::check_mount_already(s32 entryNum) { - for (JSUListIterator iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); - ++iterator) { +JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* pHeap) { + JKRHeap* heap = pHeap; + if (heap == nullptr) { + heap = JKRGetCurrentHeap(); + } + + JSUListIterator iterator; + for (iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) { if (iterator->getVolumeType() == 'RARC') { JKRArchive* archive = (JKRArchive*)iterator.getObject(); // in TP debug it calls operator-> ? - if (archive->mEntryNum == entryNum) { + if (archive->mEntryNum == entryNum && archive->mHeap == heap) { archive->mMountCount++; return archive; } @@ -47,38 +46,7 @@ JKRArchive* JKRArchive::check_mount_already(s32 entryNum) { JKRArchive* JKRArchive::mount(const char* path, EMountMode mode, JKRHeap* heap, EMountDirection direction) { int entryNum = DVDConvertPathToEntrynum((char*)path); - if (entryNum < 0) - return nullptr; - - JKRArchive* mountedArchive = check_mount_already(entryNum); - if (mountedArchive != nullptr) { - return mountedArchive; - } - - int alignment = (direction == MOUNT_DIRECTION_HEAD) ? 4 : -4; - JKRArchive* archive; - switch (mode) { - case MOUNT_MEM: - if (entryNum == -1) - archive = nullptr; - else - archive = new (heap, alignment) JKRMemArchive(entryNum, direction); - break; - case MOUNT_ARAM: - archive = new (heap, alignment) JKRAramArchive(entryNum, direction); - break; - case MOUNT_DVD: - archive = new (heap, alignment) JKRDvdArchive(entryNum, direction); - break; - case MOUNT_COMP: - archive = new (heap, alignment) JKRCompArchive(entryNum, direction); - break; - } - if (archive != nullptr && archive->getMountMode() == UNKNOWN_MOUNT_MODE) { - delete archive; - archive = nullptr; - } - return archive; + return (entryNum < 0) ? nullptr : mount(entryNum, mode, heap, direction); } JKRArchive* JKRArchive::mount(void* p1, JKRHeap* heap, EMountDirection mountDirection) { @@ -242,9 +210,10 @@ void JKRArchive::removeResourceAll() { SDIFileEntry* entry = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { if (entry->mData) { - entry->mData = nullptr; JKRFreeToHeap(mHeap, entry->mData); + entry->mData = nullptr; } + entry++; } } } diff --git a/src/static/JSystem/JKernel/JKRCompArchive.cpp b/src/static/JSystem/JKernel/JKRCompArchive.cpp index 09a800f4..27700f51 100644 --- a/src/static/JSystem/JKernel/JKRCompArchive.cpp +++ b/src/static/JSystem/JKernel/JKRCompArchive.cpp @@ -1,5 +1,7 @@ #include #include +#include "_mem.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/arith.h" #include "JSystem/JKernel/JKRArchive.h" #include "JSystem/JKernel/JKRDecomp.h" @@ -32,7 +34,7 @@ JKRCompArchive::~JKRCompArchive() { SDIFileEntry* fileEntries = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { u32 flag = (fileEntries->mFlag >> 24); - if ((flag & 16) == 0 && fileEntries->mData) { + if ((flag & 16) == 0 && fileEntries->mData != nullptr) { JKRFreeToHeap(mHeap, fileEntries->mData); } fileEntries++; @@ -43,6 +45,10 @@ JKRCompArchive::~JKRCompArchive() { if (mAramPart) { delete mAramPart; } + if (mExpandSizes) { + JKRFree(mExpandSizes); + mExpandSizes = nullptr; + } if (mDvdFile) { delete mDvdFile; } @@ -53,12 +59,12 @@ JKRCompArchive::~JKRCompArchive() { bool JKRCompArchive::open(long entryNum) { mArcInfoBlock = nullptr; - _60 = 0; + _64 = 0; mAramPart = nullptr; - _68 = 0; + _6C = 0; mSizeOfMemPart = 0; mSizeOfAramPart = 0; - _78 = 0; + _7C = 0; mDirectories = nullptr; mFileEntries = nullptr; mStrTable = nullptr; @@ -68,15 +74,15 @@ bool JKRCompArchive::open(long entryNum) { mMountMode = 0; return 0; } - SArcHeader* arcHeader = - (SArcHeader*)JKRAllocFromSysHeap(sizeof(SArcHeader), -32); // NOTE: unconfirmed if this struct is used + SArcHeader* arcHeader = (SArcHeader*)JKRAllocFromSysHeap(sizeof(SArcHeader), -32); if (arcHeader == nullptr) { mMountMode = 0; } else { int alignment; - JKRDvdToMainRam(entryNum, (u8*)arcHeader, EXPAND_SWITCH_DECOMPRESS, 32, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 0, - &mCompression); + JKRDvdToMainRam(entryNum, (u8*)arcHeader, EXPAND_SWITCH_DECOMPRESS, 32, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, + 0, &mCompression, nullptr); + DCInvalidateRange(arcHeader, 32); mSizeOfMemPart = arcHeader->_14; mSizeOfAramPart = arcHeader->_18; @@ -94,8 +100,9 @@ bool JKRCompArchive::open(long entryNum) { } else { JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, EXPAND_SWITCH_DECOMPRESS, (u32)arcHeader->file_data_offset + mSizeOfMemPart, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, 0x20, nullptr); - _60 = (u32)mArcInfoBlock + arcHeader->file_data_offset; + JKRDvdRipper::ALLOC_DIR_TOP, 0x20, nullptr, nullptr); + DCInvalidateRange(mArcInfoBlock, (u32)arcHeader->file_data_offset + mSizeOfMemPart); + _64 = (u32)mArcInfoBlock + arcHeader->file_data_offset; if (mSizeOfAramPart != 0) { mAramPart = JKRAllocFromAram(mSizeOfAramPart, JKRAramHeap::Head); @@ -105,13 +112,14 @@ bool JKRCompArchive::open(long entryNum) { } JKRDvdToAram(entryNum, mAramPart->getAddress(), EXPAND_SWITCH_DECOMPRESS, - arcHeader->header_length + arcHeader->file_data_offset + mSizeOfMemPart, 0); + arcHeader->header_length + arcHeader->file_data_offset + mSizeOfMemPart, 0, + nullptr); } mDirectories = (SDIDirEntry*)((u32)mArcInfoBlock + mArcInfoBlock->node_offset); mFileEntries = (SDIFileEntry*)((u32)mArcInfoBlock + mArcInfoBlock->file_entry_offset); mStrTable = (const char*)((u32)mArcInfoBlock + mArcInfoBlock->string_table_offset); - _68 = arcHeader->header_length + arcHeader->file_data_offset; + _6C = arcHeader->header_length + arcHeader->file_data_offset; } break; @@ -124,7 +132,8 @@ bool JKRCompArchive::open(long entryNum) { mMountMode = 0; } else { JKRDvdToMainRam(entryNum, buf, EXPAND_SWITCH_NONE, alignedSize, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, 0, nullptr); + JKRDvdRipper::ALLOC_DIR_TOP, 0, nullptr, nullptr); + DCInvalidateRange(buf, alignedSize); u32 expandSize = ALIGN_NEXT(JKRDecompExpandSize(buf), 32); u8* mem = (u8*)JKRAllocFromHeap(mHeap, expandSize, -alignment); @@ -140,20 +149,18 @@ bool JKRCompArchive::open(long entryNum) { if (mArcInfoBlock == nullptr) { mMountMode = 0; } else { - // arcHeader + 1 should lead to 0x20, which is the data after the - // header JKRHeap::copyMemory((u8*)mArcInfoBlock, arcHeader + 1, (arcHeader->file_data_offset + mSizeOfMemPart)); - _60 = (u32)mArcInfoBlock + arcHeader->file_data_offset; + _64 = (u32)mArcInfoBlock + arcHeader->file_data_offset; if (mSizeOfAramPart != 0) { mAramPart = JKRAllocFromAram(mSizeOfAramPart, JKRAramHeap::Head); if (mAramPart == nullptr) { mMountMode = 0; } else { - JKRMainRamToAram((u8*)mem + arcHeader->header_length + arcHeader->file_data_offset + - mSizeOfMemPart, - mAramPart->getAddress(), mSizeOfAramPart, EXPAND_SWITCH_DEFAULT, 0, - nullptr, -1, nullptr); + JKRAram::mainRamToAram((u8*)mem + arcHeader->header_length + + arcHeader->file_data_offset + mSizeOfMemPart, + mAramPart->getAddress(), mSizeOfAramPart, + EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); } } } @@ -162,130 +169,144 @@ bool JKRCompArchive::open(long entryNum) { mDirectories = (SDIDirEntry*)((u32)mArcInfoBlock + mArcInfoBlock->node_offset); mFileEntries = (SDIFileEntry*)((u32)mArcInfoBlock + mArcInfoBlock->file_entry_offset); mStrTable = (const char*)((u32)mArcInfoBlock + mArcInfoBlock->string_table_offset); - _68 = arcHeader->header_length + arcHeader->file_data_offset; + _6C = arcHeader->header_length + arcHeader->file_data_offset; break; } + mExpandSizes = nullptr; + u8 compressedFiles = 0; + SDIFileEntry* fileEntry = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { + u8 flag = fileEntry->mFlag >> 0x18; + if (((flag & 0x1) != 0) && (((flag)&0x10) == 0)) { + compressedFiles = compressedFiles | (flag & 4); + } + fileEntry++; + } + + if (compressedFiles != 0) { + mExpandSizes = (u32*)JKRAllocFromHeap(mHeap, mArcInfoBlock->num_file_entries * 4, abs(alignment)); + if (mExpandSizes == nullptr) { + JKRFreeToSysHeap(mArcInfoBlock); + mMountMode = 0; + } else { + memset(mExpandSizes, 0, mArcInfoBlock->num_file_entries * 4); + } + } } - if (arcHeader) { - JKRFreeToHeap(mHeap, arcHeader); + if (arcHeader != nullptr) { + JKRFreeToSysHeap(arcHeader); } if (mMountMode == 0) { - JREPORTF(0, ":::[%s: %d] Cannot alloc memory in mounting CompArchive\n", __FILE__, 567); // Macro? - if (mDvdFile) { + if (mDvdFile != nullptr) { delete mDvdFile; - mDvdFile = nullptr; } + return false; } - return mMountMode != 0; + return true; } void* JKRCompArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { JUT_ASSERT(isMounted()); u32 ptrSize; + u32 size = fileEntry->mSize; + int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + + if (pSize == nullptr) { + pSize = &ptrSize; + } if (fileEntry->mData == nullptr) { u32 flag = fileEntry->mFlag >> 0x18; if (flag & 0x10) { - fileEntry->mData = (void*)(_60 + fileEntry->mDataOffset); - if (pSize) - *pSize = fileEntry->mSize; + fileEntry->mData = (void*)(_64 + fileEntry->mDataOffset); + *pSize = size; } else if (flag & 0x20) { - u32 address = mAramPart->getAddress(); - int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); - u8* data; - u32 size = JKRAramArchive::fetchResource_subroutine(fileEntry->mDataOffset + address - mSizeOfMemPart, - fileEntry->mSize, mHeap, compression, &data); - - if (pSize) - *pSize = size; - + *pSize = JKRAramArchive::fetchResource_subroutine( + fileEntry->mDataOffset + mAramPart->getAddress() - mSizeOfMemPart, size, mHeap, compression, &data); fileEntry->mData = data; - + if (compression == JKRCOMPRESSION_YAZ0) { + setExpandSize(fileEntry, *pSize); + } } else if (flag & 0x40) { - int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); - u8* data; - u32 size = JKRDvdArchive::fetchResource_subroutine( - mEntryNum, _68 + fileEntry->mDataOffset, fileEntry->mSize, mHeap, compression, mCompression, &data); - - if (pSize) - *pSize = size; - + u32 resSize = JKRDvdArchive::fetchResource_subroutine(mEntryNum, _6C + fileEntry->mDataOffset, + fileEntry->mSize, mHeap, compression, + mCompression, &data); + if (pSize != nullptr) { + *pSize = resSize; + } fileEntry->mData = data; + if (compression == JKRCOMPRESSION_YAZ0) { + setExpandSize(fileEntry, *pSize); + } + } + } else { + if (pSize != nullptr) { + *pSize = fileEntry->mSize; } - } else if (pSize) { - *pSize = fileEntry->mSize; } return fileEntry->mData; } void* JKRCompArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry* fileEntry, u32* pSize, JKRExpandSwitch expandSwitch) { - // u32 size = 0; + u32 size = 0; JUT_ASSERT(isMounted()); - u32 size = ALIGN_NEXT(fileEntry->mSize, 32); - u32 expandSize = 0; + u32 fileSize = fileEntry->mSize; + u32 alignedSize = ALIGN_NEXT(fileSize, 32); + u32 fileFlag = fileEntry->mFlag >> 0x18; + int compression = JKRConvertAttrToCompressionType(fileFlag); - if (size == 0) - JPANIC(651, ":::bad resource size. size = 0\n"); + if (fileEntry->mData != nullptr) { + if (compression == JKRCOMPRESSION_YAZ0) { + u32 expandSize = getExpandSize(fileEntry); + if (expandSize != 0) { + fileSize = expandSize; + } + } - if (fileEntry->mData) { - if (size > (compressedSize & ~31)) { - size = (compressedSize & ~31); + if (fileSize > compressedSize) { + fileSize = compressedSize; } - JKRHeap::copyMemory(data, fileEntry->mData, size); - expandSize = size; + JKRHeap::copyMemory(data, fileEntry->mData, fileSize); + size = fileSize; } else { - u32 fileFlag = fileEntry->mFlag >> 0x18; - int compression = JKRConvertAttrToCompressionType(fileFlag); if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) - compression = 0; + compression = JKRCOMPRESSION_NONE; if (fileFlag & 0x10) { - if (size > (compressedSize & ~31)) { - size = (compressedSize & ~31); - } - - if (FLAG_ON(fileFlag, 4)) { - JKRHeap::copyMemory(data, (void*)(_60 + fileEntry->mDataOffset), size); - } else { - u8* header = (u8*)(_60 + fileEntry->mDataOffset); - expandSize = JKRDecompExpandSize(header); - expandSize = (expandSize > compressedSize) ? compressedSize : expandSize; - JKRDecompress(header, (u8*)data, expandSize, 0); - } - - expandSize = JKRMemArchive::fetchResource_subroutine((u8*)(_60 + fileEntry->mDataOffset), size, (u8*)data, - compressedSize, compression); + size = JKRMemArchive::fetchResource_subroutine((u8*)(_64 + fileEntry->mDataOffset), alignedSize, + (u8*)data, compressedSize & ~31, compression); } else if (fileFlag & 0x20) { - expandSize = JKRAramArchive::fetchResource_subroutine(fileEntry->mDataOffset + mAramPart->getAddress() - - mSizeOfMemPart, - size, (u8*)data, compressedSize, compression); + size = JKRAramArchive::fetchResource_subroutine( + fileEntry->mDataOffset + mAramPart->getAddress() - mSizeOfMemPart, alignedSize, (u8*)data, + compressedSize & ~31, compression); } else if (fileFlag & 0x40) { - expandSize = JKRDvdArchive::fetchResource_subroutine(mEntryNum, _68 + fileEntry->mDataOffset, size, - (u8*)data, compressedSize, compression, mCompression); + size = JKRDvdArchive::fetchResource_subroutine(mEntryNum, _6C + fileEntry->mDataOffset, alignedSize, + (u8*)data, compressedSize & ~31, compression, + mCompression); } else { - JPANIC(731, ":::CompArchive: bad mode."); + JPANIC(776, "illegal archive."); } } - if (pSize) { - *pSize = expandSize; + if (pSize != nullptr) { + *pSize = size; } return data; } void JKRCompArchive::removeResourceAll() { - if (mArcInfoBlock && mMountMode != MOUNT_MEM) { + if (mArcInfoBlock != nullptr && mMountMode != MOUNT_MEM) { SDIFileEntry* fileEntry = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { u32 flag = fileEntry->mFlag >> 0x18; - if (fileEntry->mData) { + if (fileEntry->mData != nullptr) { if ((flag & 0x10) == 0) { JKRFreeToHeap(mHeap, fileEntry->mData); } @@ -308,3 +329,40 @@ bool JKRCompArchive::removeResource(void* resource) { fileEntry->mData = nullptr; return true; } + +u32 JKRCompArchive::getExpandedResSize(const void* resource) const { + if (mExpandSizes == nullptr) { + return getResSize(resource); + } + + SDIFileEntry* fileEntry = findPtrResource(resource); + if (!fileEntry) { + return 0xffffffff; + } + + u8 flags = (fileEntry->mFlag >> 0x18); + if ((flags & 4) == 0) { + return getResSize(resource); + } + + if ((flags & 0x10) != 0) { + return JKRDecompExpandSize((u8*)resource); + } + + u8 buf[64]; + u8* bufPtr = (u8*)ALIGN_NEXT((u32)buf, 32); + if ((flags & 0x20) != 0) { + JKRAramToMainRam(fileEntry->mDataOffset + mAramPart->mAddress, bufPtr, sizeof(buf) / 2, + EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); + DCInvalidateRange(bufPtr, sizeof(buf) / 2); + } else if ((flags & 0x40) != 0) { + JKRDvdToMainRam(mEntryNum, bufPtr, EXPAND_SWITCH_NONE, sizeof(buf) / 2, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, + _6C + fileEntry->mDataOffset, nullptr, nullptr); + DCInvalidateRange(bufPtr, sizeof(buf) / 2); + } else { + JPANIC(943, "illegal resource."); + } + u32 expandSize = JKRDecompExpandSize(bufPtr); + const_cast(this)->setExpandSize(fileEntry, expandSize); + return expandSize; +} diff --git a/src/static/JSystem/JKernel/JKRDecomp.cpp b/src/static/JSystem/JKernel/JKRDecomp.cpp index ae17d9b3..eed0ba3b 100644 --- a/src/static/JSystem/JKernel/JKRDecomp.cpp +++ b/src/static/JSystem/JKernel/JKRDecomp.cpp @@ -75,7 +75,7 @@ JKRDecompCommand* JKRDecomp::prepareCommand(u8* srcBuffer, u8* dstBuffer, u32 sr } BOOL JKRDecomp::sendCommand(JKRDecompCommand* cmd) { - BOOL res = OSSendMessage(&JKRDecomp::sMessageQueue, (OSMessage)cmd, OS_MESSAGE_BLOCK); + BOOL res = OSSendMessage(&JKRDecomp::sMessageQueue, (OSMessage)cmd, OS_MESSAGE_NOBLOCK); #ifdef JSYSTEM_DEBUG if (res == FALSE) { @@ -261,6 +261,10 @@ JKRDecomp::CompressionMode JKRDecomp::checkCompressed(u8* buf) { } } + if (buf[0] == 'A' && buf[1] == 'S' && buf[2] == 'R') { + return ASR; + } + return NONE; } diff --git a/src/static/JSystem/JKernel/JKRDvdAramRipper.cpp b/src/static/JSystem/JKernel/JKRDvdAramRipper.cpp index 999e4cb9..ee2050c1 100644 --- a/src/static/JSystem/JKernel/JKRDvdAramRipper.cpp +++ b/src/static/JSystem/JKernel/JKRDvdAramRipper.cpp @@ -14,19 +14,26 @@ JSUList JKRDvdAramRipper::sDvdAramAsyncList; bool JKRDvdAramRipper::errorRetry = true; int JKRDvdAramRipper::sSZSBufferSize = 0x400; -JKRAramBlock* JKRDvdAramRipper::loadToAram(s32 entrynum, u32 p2, JKRExpandSwitch expSwitch, u32 p6, u32 p7) { +JKRAramBlock* JKRDvdAramRipper::loadToAram(s32 entrynum, u32 address, JKRExpandSwitch expSwitch, u32 offset, u32 size, + u32* pSize) { JKRDvdFile dvdFile; if (!dvdFile.open(entrynum)) return nullptr; else - return loadToAram(&dvdFile, p2, expSwitch, p6, p7); + return loadToAram(&dvdFile, address, expSwitch, offset, size, pSize); } -JKRAramBlock* JKRDvdAramRipper::loadToAram(JKRDvdFile* dvdFile, u32 p1, JKRExpandSwitch p2, u32 p3, u32 p4) { - JKRADCommand* command = loadToAram_Async(dvdFile, p1, p2, nullptr, p3, p4); +JKRAramBlock* JKRDvdAramRipper::loadToAram(JKRDvdFile* dvdFile, u32 address, JKRExpandSwitch expSwitch, u32 offset, + u32 size, u32* pSize) { + JKRADCommand* command = loadToAram_Async(dvdFile, address, expSwitch, nullptr, offset, size, pSize); syncAram(command, 0); - if (p1) { + if (command->_48 < 0) { + delete command; + return nullptr; + } + + if (address) { delete command; return (JKRAramBlock*)-1; } @@ -36,17 +43,17 @@ JKRAramBlock* JKRDvdAramRipper::loadToAram(JKRDvdFile* dvdFile, u32 p1, JKRExpan return result; } -JKRADCommand* JKRDvdAramRipper::loadToAram_Async(JKRDvdFile* dvdFile, u32 p1, JKRExpandSwitch expSwitch, - JKRADCommand::LoadCallback cb, u32 p4, u32 p5) { +JKRADCommand* JKRDvdAramRipper::loadToAram_Async(JKRDvdFile* dvdFile, u32 address, JKRExpandSwitch expSwitch, + JKRADCommand::LoadCallback cb, u32 offset, u32 size, u32* pSize) { JKRADCommand* command = new (JKRGetSystemHeap(), -4) JKRADCommand(); command->mDvdFile = dvdFile; - command->_1C = p1; + command->_2C = address; command->mBlock = nullptr; command->mExpandSwitch = expSwitch; command->mCallBack = cb; - - command->_14 = p4; - command->_18 = p5; + command->_3C = offset; + command->_40 = size; + command->_44 = pSize; if (!callCommand_Async(command)) { delete command; @@ -63,6 +70,9 @@ JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) { OSLockMutex(&dvdFile->mAramMutex); s32 uncompressedSize; + if (command->_44) { + *command->_44 = 0; + } if (dvdFile->mAramThread) { isCmdTrdNull = false; @@ -71,8 +81,8 @@ JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) { JSUFileInputStream* stream = new (JKRGetSystemHeap(), -4) JSUFileInputStream(dvdFile); dvdFile->mInputStream = stream; u32 fileSize = dvdFile->getFileSize(); - if (command->_18 && fileSize > command->_18) { - fileSize = command->_18; + if (command->_40 && fileSize > command->_40) { + fileSize = command->_40; } fileSize = ALIGN_NEXT(fileSize, 0x20); if (command->mExpandSwitch == EXPAND_SWITCH_DECOMPRESS) { @@ -90,13 +100,13 @@ JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) { VIWaitForRetrace(); } - - compression = JKRCheckCompressed(bufPtr); + DCInvalidateRange(bufPtr, 0x20); + compression = JKRCheckCompressed_noASR(bufPtr); u32 expSize = JKRDecompExpandSize(bufPtr); uncompressedSize = expSize; - if ((command->_18 != 0) && expSize > command->_18) { - uncompressedSize = command->_18; + if ((command->_40 != 0) && expSize > command->_40) { + uncompressedSize = command->_40; } } @@ -105,46 +115,49 @@ JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) { } if (command->mExpandSwitch == EXPAND_SWITCH_DECOMPRESS) { - if (command->_1C == 0 && command->mBlock == nullptr) { + if (command->_2C == 0 && command->mBlock == nullptr) { command->mBlock = JKRAram::getAramHeap()->alloc(uncompressedSize, JKRAramHeap::Head); if (command->mBlock) { - command->_1C = command->mBlock->mAddress; + command->_2C = command->mBlock->mAddress; } dvdFile->mAramBlock = command->mBlock; } if (command->mBlock) { - command->_1C = command->mBlock->mAddress; + command->_2C = command->mBlock->mAddress; } - if (command->_1C == 0) { + if (command->_2C == 0) { dvdFile->mAramThread = nullptr; return nullptr; } } else { - if (command->_1C == 0 && !command->mBlock) { + if (command->_2C == 0 && !command->mBlock) { command->mBlock = JKRAram::getAramHeap()->alloc(fileSize, JKRAramHeap::Head); } if (command->mBlock) { - command->_1C = command->mBlock->mAddress; + command->_2C = command->mBlock->mAddress; } - if (command->_1C == 0) { + if (command->_2C == 0) { dvdFile->mAramThread = nullptr; return nullptr; } } - if (compression == 0) { - command->mStreamCommand = - JKRAramStream::write_StreamToAram_Async(stream, command->_1C, fileSize - command->_14, command->_14); + if (compression == JKRCOMPRESSION_NONE) { + command->mStreamCommand = JKRAramStream::write_StreamToAram_Async(stream, command->_2C, + fileSize - command->_3C, command->_3C, + command->_44); } else if (compression == JKRCOMPRESSION_YAY0) { - command->mStreamCommand = - JKRAramStream::write_StreamToAram_Async(stream, command->_1C, fileSize - command->_14, command->_14); + command->mStreamCommand = JKRAramStream::write_StreamToAram_Async(stream, command->_2C, + fileSize - command->_3C, command->_3C, + command->_44); } else if (compression == JKRCOMPRESSION_YAZ0) { command->mStreamCommand = nullptr; - JKRDecompressFromDVDToAram(command->mDvdFile, command->_1C, fileSize, uncompressedSize, command->_14, 0); + JKRDecompressFromDVDToAram(command->mDvdFile, command->_2C, fileSize, uncompressedSize, command->_3C, 0, + command->_44); } if (!command->mCallBack) { @@ -164,6 +177,7 @@ bool JKRDvdAramRipper::syncAram(JKRADCommand* command, int p1) { if (command->mStreamCommand) { JKRAramStreamCommand* var1 = JKRAramStream::sync(command->mStreamCommand, p1); + command->_48 = var1 != nullptr ? 0 : -1; if (p1 != 0 && var1 == nullptr) { OSUnlockMutex(&dvdFile->mAramMutex); @@ -183,11 +197,12 @@ bool JKRDvdAramRipper::syncAram(JKRADCommand* command, int p1) { } JKRADCommand::JKRADCommand() : mLink(this) { - _44 = 0; + _48 = 0; + _4C = 0; } JKRADCommand::~JKRADCommand() { - if (_44 == 1) + if (_4C == 1) delete mDvdFile; } @@ -217,11 +232,19 @@ static u8* nextSrcData(u8*); static u32 dmaBufferFlush(u32); int JKRDecompressFromDVDToAram(JKRDvdFile* dvdFile, u32 address, u32 fileSize, u32 _maxDest, u32 _fileOffset, - u32 _srcOffset) { - int result = 0; - szpBuf = (u8*)JKRAllocFromSysHeap(SZP_BUFFERSIZE, 32); + u32 _srcOffset, u32* pSize) { + BOOL interrupt = OSDisableInterrupts(); + if (!isInitMutex) { + OSInitMutex(&decompMutex); + isInitMutex = true; + } + OSRestoreInterrupts(interrupt); + OSLockMutex(&decompMutex); + + u32 bufferSize = JKRDvdAramRipper::getSZSBufferSize(); + szpBuf = (u8*)JKRAllocFromSysHeap(bufferSize, 32); JUT_ASSERT(szpBuf != 0); - szpEnd = szpBuf + SZP_BUFFERSIZE; + szpEnd = szpBuf + bufferSize; refBuf = (u8*)JKRAllocFromSysHeap(REF_BUFFERSIZE, 0); JUT_ASSERT(refBuf != 0); @@ -239,15 +262,16 @@ int JKRDecompressFromDVDToAram(JKRDvdFile* dvdFile, u32 address, u32 fileSize, u fileOffset = _fileOffset; readCount = 0; maxDest = _maxDest; + pSize = pSize ? pSize : &tsArea; + tsPtr = pSize; + *pSize = 0; u8* first = firstSrcData(); - if (first) - result = decompSZS_subroutine(first, address); - + int result = first ? decompSZS_subroutine(first, address) : -1; JKRFree(szpBuf); JKRFree(refBuf); JKRFree(dmaBuf); - + OSUnlockMutex(&decompMutex); return result; } @@ -258,6 +282,7 @@ int decompSZS_subroutine(u8* src, u32 dmaAddr) { s32 currCodeByte = 0; s32 numBytes; + u32 ts = 0; u32 dmaStart = dmaAddr; if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') @@ -282,6 +307,7 @@ int decompSZS_subroutine(u8* src, u32 dmaAddr) { if (readCount >= fileOffset) { dmaAddr++; *dmaCurrent++ = *src; + ts++; if (dmaCurrent == dmaEnd) dmaStart += dmaBufferFlush(dmaStart); @@ -313,6 +339,7 @@ int decompSZS_subroutine(u8* src, u32 dmaAddr) { if (readCount >= fileOffset) { dmaAddr++; *(dmaCurrent++) = *copySource; + ts++; if (dmaCurrent == dmaEnd) dmaStart += dmaBufferFlush(dmaStart); @@ -337,6 +364,7 @@ int decompSZS_subroutine(u8* src, u32 dmaAddr) { } while (dmaAddr < endPtr); dmaBufferFlush(dmaStart); + *tsPtr = ts; return 0; } diff --git a/src/static/JSystem/JKernel/JKRDvdArchive.cpp b/src/static/JSystem/JKernel/JKRDvdArchive.cpp index b825b394..db6810e0 100644 --- a/src/static/JSystem/JKernel/JKRDvdArchive.cpp +++ b/src/static/JSystem/JKernel/JKRDvdArchive.cpp @@ -1,5 +1,7 @@ #include #include +#include "_mem.h" +#include "PowerPC_EABI_Support/MSL_C/MSL_Common/arith.h" #include "JSystem/JKernel/JKRArchive.h" #include "JSystem/JKernel/JKRDecomp.h" @@ -34,8 +36,13 @@ JKRDvdArchive::~JKRDvdArchive() { fileEntries++; } JKRFreeToHeap(mHeap, mArcInfoBlock); + mArcInfoBlock = nullptr; } + if (mExpandSizes) { + JKRFree(mExpandSizes); + mExpandSizes = nullptr; + } if (mDvdFile) { delete mDvdFile; } @@ -45,13 +52,9 @@ JKRDvdArchive::~JKRDvdArchive() { } } -#if DEBUG -CW_FORCE_STRINGS(JKRDvdArchive_cpp, __FILE__, "isMounted()", "mMountCount == 1") -#endif - -bool JKRDvdArchive::open(long entryNum) { +bool JKRDvdArchive::open(s32 entryNum) { mArcInfoBlock = nullptr; - _60 = 0; + _64 = 0; mDirectories = nullptr; mFileEntries = nullptr; mStrTable = nullptr; @@ -61,12 +64,14 @@ bool JKRDvdArchive::open(long entryNum) { mMountMode = 0; return 0; } - SDIFileEntry* mem = (SDIFileEntry*)JKRAllocFromSysHeap(32, 32); // NOTE: unconfirmed if this struct was used here + + SDIFileEntry* mem = (SDIFileEntry*)JKRAllocFromSysHeap(32, 32); if (mem == nullptr) { mMountMode = 0; } else { JKRDvdToMainRam(entryNum, (u8*)mem, EXPAND_SWITCH_DECOMPRESS, 32, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 0, - &mCompression); + &mCompression, nullptr); + DCInvalidateRange(mem, 32); int alignment = mMountDirection == MOUNT_DIRECTION_HEAD ? 32 : -32; mArcInfoBlock = (SArcDataInfo*)JKRAllocFromHeap(mHeap, mem->mSize, alignment); @@ -74,12 +79,35 @@ bool JKRDvdArchive::open(long entryNum) { mMountMode = 0; } else { JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, EXPAND_SWITCH_DECOMPRESS, mem->mSize, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, 32, nullptr); + JKRDvdRipper::ALLOC_DIR_TOP, 32, nullptr, nullptr); + DCInvalidateRange(mArcInfoBlock, mem->mSize); mDirectories = (SDIDirEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->node_offset); mFileEntries = (SDIFileEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->file_entry_offset); mStrTable = (const char*)((u8*)mArcInfoBlock + mArcInfoBlock->string_table_offset); - _60 = mem->mDataOffset + mem->mSize; // End of data offset? + mExpandSizes = nullptr; + + u8 compressedFiles = 0; + + SDIFileEntry* fileEntry = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { + u8 flag = fileEntry->mFlag >> 24; + if ((flag & 1)) { + compressedFiles |= (flag & JKRARCHIVE_ATTR_COMPRESSION); + } + fileEntry++; + } + + if (compressedFiles != 0) { + mExpandSizes = (u32*)JKRAllocFromHeap(mHeap, mArcInfoBlock->num_file_entries << 2, abs(alignment)); + if (mExpandSizes == nullptr) { + JKRFreeToSysHeap(mArcInfoBlock); + mMountMode = 0; + goto cleanup; + } + memset(mExpandSizes, 0, mArcInfoBlock->num_file_entries << 2); + } + _64 = mem->mDataOffset + mem->mSize; } } cleanup: @@ -87,30 +115,40 @@ bool JKRDvdArchive::open(long entryNum) { JKRFreeToSysHeap(mem); } if (mMountMode == 0) { - JREPORTF(":::Cannot alloc memory [%s][%d]\n", __FILE__, 397); // Macro? if (mDvdFile != nullptr) { delete mDvdFile; } + return false; } - return mMountMode != 0; + return true; } void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { JUT_ASSERT(isMounted()); - - u32 sizeRef; + u32 sizeptr; + u32 size; u8* data; - if (fileEntry->mData == nullptr) { - int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); - u32 size = fetchResource_subroutine(mEntryNum, _60 + fileEntry->mDataOffset, fileEntry->mSize, mHeap, - (int)compression, mCompression, &data); + if (pSize == nullptr) { + pSize = &sizeptr; + } - if (pSize) - *pSize = size; + int compression = JKRConvertAttrToCompressionType((u8)(fileEntry->mFlag >> 24)); + if (fileEntry->mData == nullptr) { + size = fetchResource_subroutine(mEntryNum, _64 + fileEntry->mDataOffset, fileEntry->mSize, mHeap, + (int)compression, mCompression, &data); + *pSize = size; + if (size == 0) { + return nullptr; + } fileEntry->mData = data; - } else if (pSize) { + if (compression == JKRCOMPRESSION_YAZ0) { + setExpandSize(fileEntry, *pSize); + } + } else if (compression == JKRCOMPRESSION_YAZ0) { + *pSize = getExpandSize(fileEntry); + } else { *pSize = fileEntry->mSize; } @@ -121,30 +159,39 @@ void* JKRDvdArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry* JKRExpandSwitch expandSwitch) { JUT_ASSERT(isMounted()); - u32 fileSize = compressedSize & -32; - u32 alignedSize = ALIGN_NEXT(fileEntry->mSize, 32); - - if (alignedSize > fileSize) { - alignedSize = fileSize; - } + u32 fileSize = fileEntry->mSize; + u32 fileFlag = fileEntry->mFlag >> 0x18; + int compression = JKRConvertAttrToCompressionType(fileFlag); if (fileEntry->mData == nullptr) { - int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) - compression = 0; - alignedSize = fetchResource_subroutine(mEntryNum, _60 + fileEntry->mDataOffset, fileEntry->mSize, (u8*)data, - fileSize, compression, mCompression); + compression = JKRCOMPRESSION_NONE; + + compressedSize = (s32)ALIGN_PREV(compressedSize, 32); + fileSize = fetchResource_subroutine(mEntryNum, _64 + fileEntry->mDataOffset, fileEntry->mSize, (u8*)data, + compressedSize, compression, mCompression); } else { - JKRHeap::copyMemory(data, fileEntry->mData, alignedSize); + if (compression == JKRCOMPRESSION_YAZ0) { + u32 expandSize = getExpandSize(fileEntry); + if (expandSize != 0) { + fileSize = expandSize; + } + } + + if (fileSize > compressedSize) { + fileSize = compressedSize; + } + + JKRHeap::copyMemory(data, fileEntry->mData, fileSize); } - if (pSize) { - *pSize = alignedSize; + if (pSize != nullptr) { + *pSize = fileSize; } return data; } -u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, u8* data, u32 expandSize, +u32 JKRDvdArchive::fetchResource_subroutine(s32 entryNum, u32 offset, u32 size, u8* data, u32 expandSize, int fileCompression, int archiveCompression) { u32 prevAlignedSize, alignedSize; @@ -154,27 +201,29 @@ u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, case JKRCOMPRESSION_NONE: { switch (fileCompression) { case JKRCOMPRESSION_NONE: - if (alignedSize > prevAlignedSize) { alignedSize = prevAlignedSize; } - JKRDvdRipper::loadToMainRAM(entryNum, data, EXPAND_SWITCH_DEFAULT, alignedSize, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + JKRDvdToMainRam(entryNum, data, EXPAND_SWITCH_DEFAULT, alignedSize, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr, nullptr); + DCInvalidateRange(data, alignedSize); return alignedSize; case JKRCOMPRESSION_YAY0: case JKRCOMPRESSION_YAZ0: - u8* header = (u8*)JKRAllocFromSysHeap(0x20, 0x20); - JKRDvdRipper::loadToMainRAM(entryNum, header, EXPAND_SWITCH_NONE, 0x20, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); - u32 expandFileSize = JKRDecompExpandSize(header); - JKRFreeToSysHeap(header); + u8 buf[64]; + u8* bufPtr = (u8*)ALIGN_NEXT((u32)buf, 32); + JKRDvdToMainRam(entryNum, bufPtr, EXPAND_SWITCH_NONE, sizeof(buf) / 2, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr, nullptr); + DCInvalidateRange(bufPtr, sizeof(buf) / 2); + u32 expandFileSize = JKRDecompExpandSize(bufPtr); alignedSize = ALIGN_NEXT(expandFileSize, 32); if (alignedSize > prevAlignedSize) { alignedSize = prevAlignedSize; } - JKRDvdRipper::loadToMainRAM(entryNum, data, EXPAND_SWITCH_DECOMPRESS, alignedSize, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + JKRDvdToMainRam(entryNum, data, EXPAND_SWITCH_DECOMPRESS, alignedSize, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr, nullptr); + DCInvalidateRange(data, alignedSize); return expandFileSize; } } @@ -183,23 +232,23 @@ u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, size = prevAlignedSize; } JKRDvdRipper::loadToMainRAM(entryNum, data, EXPAND_SWITCH_DECOMPRESS, size, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr, nullptr); + DCInvalidateRange(data, size); return size; } case JKRCOMPRESSION_YAY0: { - JPANIC(537, "Sorry, not prepared for SZP archive.\n"); - return 0; + JPANIC(649, "Sorry, not applied for SZP archive.\n"); } default: { - JPANIC(546, ":::??? bad sequence\n"); + JPANIC(653, "??? bad sequence\n"); } } return 0; } -u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, JKRHeap* heap, int fileCompression, +u32 JKRDvdArchive::fetchResource_subroutine(s32 entryNum, u32 offset, u32 size, JKRHeap* heap, int fileCompression, int archiveCompression, u8** pBuf) { u32 alignedSize = ALIGN_NEXT(size, 32); @@ -212,23 +261,27 @@ u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, JUT_ASSERT(buffer != 0); JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_DEFAULT, alignedSize, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr, nullptr); + DCInvalidateRange(buffer, alignedSize); *pBuf = buffer; return alignedSize; case JKRCOMPRESSION_YAY0: case JKRCOMPRESSION_YAZ0: - u8* header = (u8*)JKRAllocFromHeap(heap, 0x20, 0x20); - JKRDvdToMainRam(entryNum, header, EXPAND_SWITCH_NONE, 0x20, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, - offset, nullptr); + u8 decompBuf[64]; + u8* bufptr = (u8*)ALIGN_NEXT((u32)decompBuf, 32); + JKRDvdToMainRam(entryNum, bufptr, EXPAND_SWITCH_NONE, sizeof(decompBuf) / 2, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr, nullptr); + DCInvalidateRange(bufptr, 0x20); + + alignedSize = JKRDecompExpandSize(bufptr); - alignedSize = JKRDecompExpandSize(header); - JKRFreeToHeap(heap, header); - buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, 0x20); + buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, 32); JUT_ASSERT(buffer); JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_DECOMPRESS, alignedSize, nullptr, - JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr, nullptr); + DCInvalidateRange(buffer, alignedSize); *pBuf = buffer; return alignedSize; } @@ -237,19 +290,51 @@ u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, 32); JUT_ASSERT(buffer); JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_DECOMPRESS, size, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, - offset, nullptr); + offset, nullptr, nullptr); + DCInvalidateRange(buffer, size); *pBuf = buffer; return alignedSize; } case JKRCOMPRESSION_YAY0: { - JPANIC(612, "Sorry, not prepared for SZP archive.\n"); - return 0; + JPANIC(754, "Sorry, not applied SZP archive.\n"); } default: { - JPANIC(617, ":::??? bad sequence\n"); + JPANIC(758, "??? bad sequence\n"); } } return 0; } + +u32 JKRDvdArchive::getExpandedResSize(const void* resource) const { + if (mExpandSizes == nullptr) { + return getResSize(resource); + } + + SDIFileEntry* fileEntry = findPtrResource(resource); + if (fileEntry == nullptr) { + return 0xffffffff; + } + + u8 flags = (fileEntry->mFlag >> 0x18); + if ((flags & 4) == 0) { + return getResSize(resource); + } + + u32 expandSize = getExpandSize(fileEntry); + if (expandSize != 0) { + return expandSize; + } + + u8 buf[64]; + u8* bufPtr = (u8*)ALIGN_NEXT((u32)buf, 32); + + JKRDvdToMainRam(mEntryNum, bufPtr, EXPAND_SWITCH_NONE, sizeof(buf) / 2, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, + _64 + fileEntry->mDataOffset, nullptr, nullptr); + DCInvalidateRange(bufPtr, sizeof(buf) / 2); + + u32 decompExpandSize = JKRDecompExpandSize(bufPtr); + const_cast(this)->setExpandSize(fileEntry, decompExpandSize); + return decompExpandSize; +} diff --git a/src/static/JSystem/JKernel/JKRDvdFile.cpp b/src/static/JSystem/JKernel/JKRDvdFile.cpp index 1803fb24..c67a5afd 100644 --- a/src/static/JSystem/JKernel/JKRDvdFile.cpp +++ b/src/static/JSystem/JKernel/JKRDvdFile.cpp @@ -1,4 +1,5 @@ #include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JMacro.h" JSUList JKRDvdFile::sDvdList; @@ -73,7 +74,7 @@ bool JKRDvdFile::close() { this->mFileOpen = false; return sDvdList.remove(&this->mLink); } else { - OSErrorLine(212, "cannot close DVD file\n"); /* JKRDvdFile.cpp line 212 */ + JPANIC(213, "cannot close DVD file\n"); } } } diff --git a/src/static/JSystem/JKernel/JKRDvdRipper.cpp b/src/static/JSystem/JKernel/JKRDvdRipper.cpp index 27de91b2..fac8099b 100644 --- a/src/static/JSystem/JKernel/JKRDvdRipper.cpp +++ b/src/static/JSystem/JKernel/JKRDvdRipper.cpp @@ -8,243 +8,268 @@ #include "JSystem/JKernel/JKRDvdRipper.h" +static u8* firstSrcData(); +static u8* nextSrcData(u8* src); +static int decompSZS_subroutine(u8* src, u8* dest); + JSUList JKRDvdRipper::sDvdAsyncList; +static OSMutex decompMutex; bool JKRDvdRipper::errorRetry = true; +int JKRDvdRipper::sSZSBufferSize = 0x400; -static int decompSZS_subroutine(u8* src, u8* dest); -static u8* firstSrcData(); -static u8* nextSrcData(u8* nowData); +static u8* szpBuf; +static u8* szpEnd; +static u8* refBuf; +static u8* refEnd; +static u8* refCurrent; +static u32 srcOffset; +static u32 transLeft; +static u8* srcLimit; +static JKRDvdFile* srcFile; +static u32 fileOffset; +static u32 readCount; +static u32 maxDest; +static bool isInitMutex; +static u32* tsPtr; +static u32 tsArea; -void* JKRDvdRipper::loadToMainRAM(const char* file, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, - EAllocDirection allocDir, u32 offset, int* compressMode) { +void* JKRDvdRipper::loadToMainRAM(const char* fileName, u8* buf, JKRExpandSwitch expandSwitch, u32 maxSize, + JKRHeap* heap, EAllocDirection allocDir, u32 offset, int* pCompression, + u32* pSize) { JKRDvdFile dvdFile; - - if (!dvdFile.open(file)) { + if (!dvdFile.open(fileName)) { return nullptr; } else { - return JKRDvdRipper::loadToMainRAM(&dvdFile, buf, expandSwitch, maxDest, heap, allocDir, offset, compressMode); + return loadToMainRAM(&dvdFile, buf, expandSwitch, maxSize, heap, allocDir, offset, pCompression, pSize); } } -void* JKRDvdRipper::loadToMainRAM(s32 entrynum, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, - EAllocDirection allocDir, u32 offset, int* compressMode) { +void* JKRDvdRipper::loadToMainRAM(s32 entryNum, u8* buf, JKRExpandSwitch expandSwitch, u32 maxSize, JKRHeap* heap, + EAllocDirection allocDir, u32 offset, int* pCompression, u32* pSize) { JKRDvdFile dvdFile; - - if (!dvdFile.open(entrynum)) { + if (!dvdFile.open(entryNum)) { return nullptr; } else { - return JKRDvdRipper::loadToMainRAM(&dvdFile, buf, expandSwitch, maxDest, heap, allocDir, offset, compressMode); + return loadToMainRAM(&dvdFile, buf, expandSwitch, maxSize, heap, allocDir, offset, pCompression, pSize); } } -void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, - EAllocDirection allocDir, u32 offset, int* compressMode) { - u32 finalSize; - - bool allocated = false; - JKRDecomp::CompressionMode fileCompressMode = JKRDecomp::NONE; +void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* dvdFile, u8* buf, JKRExpandSwitch expandSwitch, u32 maxSize, + JKRHeap* heap, EAllocDirection allocDir, u32 offset, int* pCompression, + u32* pSize) { + s32 fileSizeAligned; + bool hasAllocated = false; + int compression = JKRCOMPRESSION_NONE; + u32 expandSize; u8* mem = nullptr; - u32 fileSize = ALIGN_NEXT(file->getFileSize(), 32); + fileSizeAligned = ALIGN_NEXT(dvdFile->getFileSize(), 32); if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { - u8 buffer[64]; - u8* aligned_buf = (u8*)ALIGN_NEXT((u32)buffer, 32); + u8 buffer[0x40]; + u8* bufPtr = (u8*)ALIGN_NEXT((u32)buffer, 32); while (true) { - if (DVDReadPrio(file->getFileInfo(), aligned_buf, 32, 0, 2) >= 0) { + int readBytes = DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 0x20, 0, 2); + if (readBytes >= 0) { break; } - if (JKRDvdRipper::errorRetry == false) { + + if (readBytes == -3 || errorRetry == false) { return nullptr; } VIWaitForRetrace(); } + DCInvalidateRange(bufPtr, 0x20); - fileCompressMode = JKRCheckCompressed(aligned_buf); - finalSize = JKRDecompExpandSize(aligned_buf); + compression = JKRCheckCompressed_noASR(bufPtr); + expandSize = JKRDecompExpandSize(bufPtr); } - if (compressMode != nullptr) { - *compressMode = fileCompressMode; + if (pCompression) { + *pCompression = compression; } - if (expandSwitch == EXPAND_SWITCH_DECOMPRESS && fileCompressMode != JKRDecomp::NONE) { - if (maxDest != 0 && finalSize > maxDest) { - finalSize = maxDest; + if (expandSwitch == EXPAND_SWITCH_DECOMPRESS && compression != JKRCOMPRESSION_NONE) { + if (maxSize != 0 && expandSize > maxSize) { + expandSize = maxSize; } - if (buf == nullptr) { - buf = (u8*)JKRAllocFromHeap(heap, finalSize, allocDir == ALLOC_DIR_TOP ? 32 : -32); - allocated = true; + buf = (u8*)JKRAllocFromHeap(heap, expandSize, allocDir == ALLOC_DIR_TOP ? 32 : -32); + hasAllocated = true; } - if (buf == nullptr) { return nullptr; } - - if (fileCompressMode == JKRDecomp::SZP) { - mem = (u8*)JKRAllocFromHeap(heap, fileSize, 32); - if (mem == nullptr && allocated == true) { - JKRFree(buf); - return nullptr; + if (compression == JKRCOMPRESSION_YAY0) { + mem = (u8*)JKRAllocFromHeap(heap, fileSizeAligned, 32); + if (mem == nullptr) { + if (hasAllocated == true) { + JKRFree(buf); + return nullptr; + } } } } else { if (buf == nullptr) { - buf = (u8*)JKRAllocFromHeap(heap, fileSize - offset, allocDir == ALLOC_DIR_TOP ? 32 : -32); - allocated = true; - } + u32 size = fileSizeAligned - offset; + if (maxSize != 0 && size > maxSize) { + size = maxSize; + } + buf = (u8*)JKRAllocFromHeap(heap, size, allocDir == ALLOC_DIR_TOP ? 32 : -32); + hasAllocated = true; + } if (buf == nullptr) { return nullptr; } } - if (fileCompressMode == JKRDecomp::NONE) { - JKRDecomp::CompressionMode subCompressMode = JKRDecomp::NONE; + if (compression == JKRCOMPRESSION_NONE) { + int compression2 = JKRCOMPRESSION_NONE; if (offset != 0) { - u8 buffer[64]; - u8* aligned_buf = (u8*)ALIGN_NEXT((u32)buffer, 32); + u8 buffer[0x40]; + u8* bufPtr = (u8*)ALIGN_NEXT((u32)buffer, 32); while (true) { - if (DVDReadPrio(file->getFileInfo(), aligned_buf, 32, offset, 2) >= 0) { + int readBytes = DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 32, (s32)offset, 2); + if (readBytes >= 0) { break; } - if (JKRDvdRipper::errorRetry == false) { + if (readBytes == -3 || !errorRetry) { + if (hasAllocated == true) { + JKRFree(buf); + } return nullptr; } - VIWaitForRetrace(); } + DCInvalidateRange(bufPtr, 32); - subCompressMode = JKRCheckCompressed(aligned_buf); + compression2 = JKRCheckCompressed_noASR(bufPtr); } - if (subCompressMode == JKRDecomp::NONE || expandSwitch == EXPAND_SWITCH_NONE || + if ((compression2 == JKRCOMPRESSION_NONE || expandSwitch == EXPAND_SWITCH_NONE) || expandSwitch == EXPAND_SWITCH_DEFAULT) { - s32 readSize = fileSize - offset; - if (maxDest != 0 && maxDest < readSize) { - readSize = maxDest; + s32 size = fileSizeAligned - offset; + if (maxSize != 0 && maxSize < size) { + size = maxSize; } while (true) { - if (DVDReadPrio(file->getFileInfo(), buf, readSize, offset, 2) >= 0) { + int readBytes = DVDReadPrio(dvdFile->getFileInfo(), buf, size, (s32)offset, 2); + if (readBytes >= 0) { break; } - if (JKRDvdRipper::errorRetry == false) { + if (readBytes == -3 || !errorRetry) { + if (hasAllocated == true) { + JKRFree(buf); + } return nullptr; } - VIWaitForRetrace(); } - return buf; - } - if (subCompressMode == JKRDecomp::SZS) { - JKRDecompressFromDVD(file, buf, fileSize, maxDest, 0, offset); + if (pSize) { + *pSize = size; + } + return buf; + } else if (compression2 == JKRCOMPRESSION_YAZ0) { + JKRDecompressFromDVD(dvdFile, buf, fileSizeAligned, maxSize, 0, offset, pSize); } else { - JPANIC(297, "Sorry, not prepared for SZP resource\n"); + JPANIC(323, "Sorry, not applied for SZP archive."); } - } - - if (fileCompressMode == JKRDecomp::SZP) { + return buf; + } else if (compression == JKRCOMPRESSION_YAY0) { if (offset != 0) { - JPANIC(306, ":::Not support SZP with offset read"); + JPANIC(333, "Not support SZP with offset read"); } - /* Looks like a bug here */ -#ifndef FIXES - if (DVDReadPrio(file->getFileInfo(), mem, fileSize, 0, 2) < 0) { - if (JKRDvdRipper::errorRetry == false) { - VIWaitForRetrace(); + while (true) { + int readBytes = DVDReadPrio(dvdFile->getFileInfo(), mem, fileSizeAligned, 0, 2); + if (readBytes >= 0) { + break; } - JKRFree(mem); - return nullptr; - } else { - JKRDecompress(mem, buf, finalSize, offset); - JKRFree(mem); - return buf; - } -#else - while (DVDReadPrio(file->getFileInfo(), mem, fileSize, 0, 2) < 0) { - if (JKRDvdRipper::errorRetry == false) { - if (allocated) { + if (readBytes == -3 || !errorRetry) { + if (hasAllocated == true) { JKRFree(buf); } JKRFree(mem); return nullptr; } - VIWaitForRetrace(); } - - JKRDecompress(mem, buf, finalSize, 0); + DCInvalidateRange(mem, fileSizeAligned); + JKRDecompress(mem, buf, expandSize, offset); JKRFree(mem); -#endif - } else if (fileCompressMode == JKRDecomp::SZS) { - JKRDecompressFromDVD(file, buf, fileSize, finalSize, offset, 0); + if (pSize) { + *pSize = expandSize; + } return buf; - } else { - if (allocated) { - JKRFree(buf); + } else if (compression == JKRCOMPRESSION_YAZ0) { + if (JKRDecompressFromDVD(dvdFile, buf, fileSizeAligned, expandSize, offset, 0, pSize) != 0u) { + if (hasAllocated) { + JKRFree(buf); + } + buf = nullptr; } - return nullptr; + return buf; + } else if (hasAllocated) { + JKRFree(buf); + buf = nullptr; } - - return buf; + return nullptr; } -static u8* szpBuf; -static u8* szpEnd; -static u8* refBuf; -static u8* refEnd; -static u8* refCurrent; - -static u32 srcOffset; -static u32 transLeft; -static u8* srcLimit; -static JKRDvdFile* srcFile; -static u32 fileOffset; -static u32 readCount; -static u32 maxDest; - -int JKRDecompressFromDVD(JKRDvdFile* _srcFile, void* buf, u32 size, u32 _maxDest, u32 _fileOffset, u32 _srcOffset) { - int res = 0; +int JKRDecompressFromDVD(JKRDvdFile* file, void* dst, u32 size, u32 inMaxDest, u32 inFileOffset, u32 inSrcOffset, + u32* inTsPtr) { + BOOL interrupts = OSDisableInterrupts(); + if (isInitMutex == false) { + OSInitMutex(&decompMutex); + isInitMutex = true; + } + OSRestoreInterrupts(interrupts); + OSLockMutex(&decompMutex); - szpBuf = (u8*)JKRAllocFromSysHeap(SZP_BUFFERSIZE, -32); - szpEnd = szpBuf + SZP_BUFFERSIZE; + int bufSize = JKRDvdRipper::getSZSBufferSize(); + szpBuf = (u8*)JKRAllocFromSysHeap(bufSize, -0x20); + JUT_ASSERT(szpBuf != 0); + szpEnd = szpBuf + bufSize; - if (_fileOffset != 0) { + if (inFileOffset != 0) { refBuf = (u8*)JKRAllocFromSysHeap(REF_BUFFERSIZE, -4); + JUT_ASSERT(refBuf != 0); refEnd = refBuf + REF_BUFFERSIZE; refCurrent = refBuf; } else { refBuf = nullptr; } - srcFile = _srcFile; - srcOffset = _srcOffset; - transLeft = size - _srcOffset; - fileOffset = _fileOffset; + srcFile = file; + srcOffset = inSrcOffset; + transLeft = size - inSrcOffset; + fileOffset = inFileOffset; readCount = 0; - maxDest = _maxDest; - - u8* src = firstSrcData(); - if (src != nullptr) { - res = decompSZS_subroutine(src, (u8*)buf); + maxDest = inMaxDest; + if (!inTsPtr) { + tsPtr = &tsArea; + } else { + tsPtr = inTsPtr; } + *tsPtr = 0; + u8* data = firstSrcData(); + u32 result = (data != nullptr) ? decompSZS_subroutine(data, (u8*)dst) : -1; JKRFree(szpBuf); - - if (refBuf != nullptr) { + if (refBuf) { JKRFree(refBuf); } - - return res; + DCStoreRangeNoSync(dst, *tsPtr); + OSUnlockMutex(&decompMutex); + return result; } static int decompSZS_subroutine(u8* src, u8* dest) { @@ -253,12 +278,12 @@ static int decompSZS_subroutine(u8* src, u8* dest) { s32 currCodeByte = 0; u32 ts = 0; - if ((s32)src[0] != 'Y' || (s32)src[1] != 'a' || (s32)src[2] != 'z' || (s32)src[3] != '0') { + if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') { return -1; } - SZPHeader* header = (SZPHeader*)src; - endPtr = dest + (header->decompSize - fileOffset); + SYaz0Header* header = (SYaz0Header*)src; + endPtr = dest + (header->length - fileOffset); if (endPtr > dest + maxDest) { endPtr = dest + maxDest; } @@ -358,70 +383,65 @@ static int decompSZS_subroutine(u8* src, u8* dest) { currCodeByte <<= 1; validBitCount--; } while (dest < endPtr); - + *tsPtr = ts; return 0; } static u8* firstSrcData() { srcLimit = szpEnd - 0x19; u8* buf = szpBuf; - u32 size = (szpEnd - szpBuf); - u32 transSize = MIN(transLeft, size); + u32 max = (szpEnd - szpBuf); + u32 transSize = MIN(transLeft, max); while (true) { - if (DVDReadPrio(srcFile->getFileInfo(), buf, transSize, srcOffset, 2) < 0) { - if (JKRDvdRipper::errorRetry == false) { - return nullptr; - } - VIWaitForRetrace(); - } else { - srcOffset += transSize; - transLeft -= transSize; - return buf; + int result = DVDReadPrio(srcFile->getFileInfo(), buf, transSize, srcOffset, 2); + if (0 <= result) { + break; + } + if (result == -3 || !JKRDvdRipper::isErrorRetry()) { + return nullptr; } + VIWaitForRetrace(); } + DCInvalidateRange(buf, transSize); + srcOffset += transSize; + transLeft -= transSize; + return buf; } -static u8* nextSrcData(u8* nowData) { - u32 size = (szpEnd - nowData); - u8* dst; - if (JKR_ISNOTALIGNED32(size)) { - dst = szpBuf + 32 - (size & 31); +static u8* nextSrcData(u8* src) { + u32 limit = szpEnd - src; + u8* buf; + if (IS_NOT_ALIGNED(limit, 0x20)) { + buf = szpBuf + 0x20 - (limit & (0x20 - 1)); } else { - dst = szpBuf; + buf = szpBuf; } - memcpy(dst, nowData, size); - - u32 n_size = (szpEnd - (dst + size)); - if (n_size > transLeft) { - n_size = transLeft; + memcpy(buf, src, limit); + u32 transSize = (u32)(szpEnd - (buf + limit)); + if (transSize > transLeft) { + transSize = transLeft; } + JUT_ASSERT(transSize > 0); while (true) { - if (DVDReadPrio(srcFile->getFileInfo(), (dst + size), n_size, srcOffset, 2) >= 0) { + s32 result = DVDReadPrio(srcFile->getFileInfo(), (buf + limit), transSize, srcOffset, 2); + if (result >= 0) { break; } - // Oopsies, forgot to call the function -#ifndef FIXES - if (JKRDvdRipper::isErrorRetry == false) { - return nullptr; - } -#else - if (JKRDvdRipper::isErrorRetry() == false) { + if (result == -3 || !JKRDvdRipper::isErrorRetry) { return nullptr; } -#endif VIWaitForRetrace(); } - - srcOffset += n_size; - transLeft -= n_size; - + DCInvalidateRange((buf + limit), transSize); + srcOffset += transSize; + transLeft -= transSize; if (transLeft == 0) { - srcLimit = (dst + size) + n_size; + srcLimit = transSize + (buf + limit); } - return dst; + return buf; } diff --git a/src/static/JSystem/JKernel/JKRFileLoader.cpp b/src/static/JSystem/JKernel/JKRFileLoader.cpp index d6400e0d..834dda5e 100644 --- a/src/static/JSystem/JKernel/JKRFileLoader.cpp +++ b/src/static/JSystem/JKernel/JKRFileLoader.cpp @@ -88,6 +88,23 @@ bool JKRFileLoader::detachResource(void* resourceBuffer, JKRFileLoader* fileLoad return false; } +u32 JKRFileLoader::getResSize(void* resourceBuffer, JKRFileLoader* fileLoader) { + long resSize = -1; + if (fileLoader) { + return fileLoader->getResSize(resourceBuffer); + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + resSize = iterator->getResSize(resourceBuffer); + if (resSize >= 0) + break; + } + + return resSize; +} + JKRFileLoader* JKRFileLoader::findVolume(const char** volumeName) { if (*volumeName[0] != '/') { return sCurrentVolume; diff --git a/src/static/JSystem/JKernel/JKRHeap.cpp b/src/static/JSystem/JKernel/JKRHeap.cpp index 8c134883..0d967786 100644 --- a/src/static/JSystem/JKernel/JKRHeap.cpp +++ b/src/static/JSystem/JKernel/JKRHeap.cpp @@ -1,4 +1,5 @@ #include "JSystem/JUtility/JUTAssertion.h" +#include "JSystem/JMacro.h" #include "JSystem/JKernel/JKRHeap.h" #include "dolphin/os.h" #include "dolphin/os/OSArena.h" @@ -11,6 +12,7 @@ JKRHeap* JKRHeap::sSystemHeap; JKRHeap* JKRHeap::sCurrentHeap; JKRHeap* JKRHeap::sRootHeap; JKRHeapErrorHandler* JKRHeap::mErrorHandler; +bool JKRHeap::sDefaultFillCheckFlag = false; void* JKRHeap::mCodeStart; void* JKRHeap::mCodeEnd; void* JKRHeap::mUserRamStart; @@ -18,7 +20,6 @@ void* JKRHeap::mUserRamEnd; u32 JKRHeap::mMemorySize; bool JKRHeap::sDefaultFillFlag = true; -bool JKRHeap::sDefaultFillCheckFlag = false; JKRHeap::JKRHeap(void* data, u32 size, JKRHeap* heap, bool errorFlag) : JKRDisposer(), mChildTree(this), mDisposerList() { @@ -279,7 +280,7 @@ void JKRHeap::copyMemory(void* dst, void* src, u32 size) { void JKRDefaultMemoryErrorRoutine(void* heap, u32 size, int alignment) { // OSReport("Error: Cannot allocate memory %d(0x%x)byte in %d byte alignment from %08x\n", size, size, alignment, // heap); - OSErrorLine(830, "abort\n"); + JPANIC(831, "abort\n"); } JKRHeapErrorHandler* JKRHeap::setErrorHandler(JKRHeapErrorHandler* newHandler) { diff --git a/src/static/JSystem/JKernel/JKRMemArchive.cpp b/src/static/JSystem/JKernel/JKRMemArchive.cpp index 74519a48..42a951b1 100644 --- a/src/static/JSystem/JKernel/JKRMemArchive.cpp +++ b/src/static/JSystem/JKernel/JKRMemArchive.cpp @@ -1,4 +1,5 @@ #include +#include "_mem.h" #include #include "JSystem/JSystem.h" @@ -45,14 +46,49 @@ JKRMemArchive::~JKRMemArchive() { } } -#if DEBUG // function is needed to generate certain strings first, however this is not what the original function looks - // like -void JKRMemArchive::fixedInit(s32) { - JUT_ASSERT(isMounted()); - JUT_PANIC("mMountCount == 1"); // some member is called mMountCount, if there's a game with this assert, fix - JUT_ASSERT(mArcHeader->signature == 'RARC'); +void JKRMemArchive::fixedInit(s32 entryNum) { + mIsMounted = false; + mMountMode = MOUNT_MEM; + mMountCount = 1; + _58 = 2; + mHeap = JKRHeap::getCurrentHeap(); + mEntryNum = entryNum; + if (sCurrentVolume == nullptr) { + sCurrentVolume = this; + sCurrentDirID = 0; + } +} + +bool JKRMemArchive::mountFixed(void* buffer, JKRMemBreakFlag flag) { + if (check_mount_already((s32)buffer)) { + return false; + } + + fixedInit((s32)buffer); + if (!open(buffer, 0xFFFF, flag)) { + return false; + } + + mVolumeType = 'RARC'; + mVolumeName = &mStrTable[mDirectories->mOffset]; + sVolumeList.prepend(&mFileLoaderLink); + mIsOpen = (flag == MBF_1) ? true : false; + mIsMounted = true; + return true; +} + +void JKRMemArchive::unmountFixed() { + if (sCurrentVolume == this) { + sCurrentVolume = nullptr; + } + + if (mIsOpen && mArcHeader) { + JKRFreeToHeap(mHeap, mArcHeader); + } + + sVolumeList.remove(&mFileLoaderLink); + mIsMounted = false; } -#endif bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirection) { mArcHeader = nullptr; @@ -67,12 +103,19 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio if (mMountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) { u32 loadedSize; mArcHeader = (SArcHeader*)JKRDvdRipper::loadToMainRAM(entryNum, nullptr, EXPAND_SWITCH_DECOMPRESS, 0, mHeap, - JKRDvdRipper::ALLOC_DIR_TOP, 0, (int*)&mCompression); - + JKRDvdRipper::ALLOC_DIR_TOP, 0, (int*)&mCompression, + &loadedSize); + if (mArcHeader) { + DCInvalidateRange(mArcHeader, loadedSize); + } } else { u32 loadedSize; mArcHeader = (SArcHeader*)JKRDvdRipper::loadToMainRAM(entryNum, nullptr, EXPAND_SWITCH_DECOMPRESS, 0, mHeap, - JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, (int*)&mCompression); + JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, (int*)&mCompression, + &loadedSize); + if (mArcHeader) { + DCInvalidateRange(mArcHeader, loadedSize); + } } if (!mArcHeader) { @@ -87,12 +130,6 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio mArchiveData = (u8*)((u32)mArcHeader + mArcHeader->header_length + mArcHeader->file_data_offset); mIsOpen = true; } -#if DEBUG - // OS Assert? - if (mMountMode == UNKNOWN_MOUNT_MODE) { - OSReport(":::Cannot alloc memory [%s][%d]\n", __FILE__, 460); - } -#endif return (mMountMode == UNKNOWN_MOUNT_MODE) ? false : true; } @@ -104,7 +141,7 @@ bool JKRMemArchive::open(void* buffer, u32 bufferSize, JKRMemBreakFlag flag) { mFileEntries = (SDIFileEntry*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset); mStrTable = (char*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset); mArchiveData = (u8*)(((u32)mArcHeader + mArcHeader->header_length) + mArcHeader->file_data_offset); - mIsOpen = (flag == MBF_1) ? true : false; // mIsOpen might be u8 + mIsOpen = (flag == MBF_1) ? true : false; mHeap = JKRHeap::findFromRoot(buffer); mCompression = JKRCOMPRESSION_NONE; return true; @@ -126,14 +163,13 @@ void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* f JKRExpandSwitch expandSwitch) { JUT_ASSERT(isMounted()) - bufferSize = (bufferSize & -32); - u32 srcLength = ALIGN_NEXT(fileEntry->mSize, 32); + u32 srcLength = fileEntry->mSize; if (srcLength > bufferSize) { srcLength = bufferSize; } if (fileEntry->mData != nullptr) { - JKRHeap::copyMemory(buffer, fileEntry->mData, srcLength); + memcpy(buffer, fileEntry->mData, srcLength); } else { int compression = JKRConvertAttrToCompressionType(fileEntry->getAttr()); if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) @@ -180,32 +216,40 @@ bool JKRMemArchive::removeResource(void* resource) { } u32 JKRMemArchive::fetchResource_subroutine(u8* src, u32 srcLength, u8* dst, u32 dstLength, int compression) { - u32 alignedDst = dstLength & -32; - u32 alignedSrc = ALIGN_NEXT(srcLength, 32); switch (compression) { case JKRCOMPRESSION_NONE: - if (alignedSrc > alignedDst) - alignedSrc = alignedDst; + if (srcLength > dstLength) + srcLength = dstLength; - JKRHeap::copyMemory(dst, src, alignedSrc); - return alignedSrc; + memcpy(dst, src, srcLength); + return srcLength; case JKRCOMPRESSION_YAY0: case JKRCOMPRESSION_YAZ0: u32 expandSize = JKRDecompExpandSize(src); + srcLength = expandSize; + if (expandSize > dstLength) + srcLength = dstLength; - if (expandSize > alignedDst) { - expandSize = alignedDst; - } - - JKRDecompress(src, dst, expandSize, 0); - return expandSize; + JKRDecompress(src, dst, srcLength, 0); + return srcLength; default: { - JPANIC(709, ":::??? bad sequence\n"); + JPANIC(723, "??? bad sequence\n"); return 0; } } - return alignedSrc; + return srcLength; +} + +u32 JKRMemArchive::getExpandedResSize(const void* resource) const { + SDIFileEntry* fileEntry = findPtrResource(resource); + if (fileEntry == nullptr) + return -1; + + if (((u8)(fileEntry->mFlag >> 24) & 4) == 0) + return getResSize(resource); + else + return JKRDecompExpandSize((u8*)resource); } diff --git a/src/static/JSystem/JKernel/JKRThread.cpp b/src/static/JSystem/JKernel/JKRThread.cpp index 27d3310a..e0d39d0d 100644 --- a/src/static/JSystem/JKernel/JKRThread.cpp +++ b/src/static/JSystem/JKernel/JKRThread.cpp @@ -1,59 +1,73 @@ - #include "JSystem/JKernel/JKRMacro.h" #include "JSystem/JKernel/JKRThread.h" #include "JSystem/JKernel/JKRHeap.h" -JSUList JKRThread::sThreadList; +JSUList JKRThread::sThreadList(false); +JSUList JKRTask::sTaskList; +u8 JKRTask::sEndMesgQueue[32]; JKRThread::JKRThread(u32 stackSize, int msgCount, int threadPrio) : mLink(this) { - this->mHeap = JKRHeap::findFromRoot(this); - if (this->mHeap == nullptr) { - this->mHeap = JKRHeap::sSystemHeap; + JKRHeap* heap = JKRHeap::findFromRoot(this); + if (heap == nullptr) { + heap = JKRHeap::getSystemHeap(); } - this->mStackSize = JKR_ALIGN32(stackSize); - this->mStackMemory = JKRHeap::alloc(this->mStackSize, 32, this->mHeap); - this->mThreadRecord = (OSThread*)JKRHeap::alloc(sizeof(OSThread), 32, this->mHeap); - OSCreateThread(this->mThreadRecord, &JKRThread::start, this, (void*)((u32)this->mStackMemory + this->mStackSize), - this->mStackSize, threadPrio, OS_THREAD_ATTR_DETACH); - this->mMesgCount = msgCount; - this->mMesgBuffer = (OSMessage*)JKRHeap::alloc(mMesgCount * sizeof(OSMessage), 0, this->mHeap); - OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, this->mMesgCount); - JKRThread::sThreadList.append(&this->mLink); + setCommon_heapSpecified(heap, stackSize, threadPrio); + setCommon_mesgQueue(mHeap, msgCount); } JKRThread::JKRThread(OSThread* threadRecord, int msgCount) : mLink(this) { - this->mHeap = nullptr; - this->mThreadRecord = threadRecord; - this->mStackSize = (u32)threadRecord->stackEnd - (u32)threadRecord->stackBase; - this->mStackMemory = threadRecord->stackBase; - this->mMesgCount = msgCount; - this->mMesgBuffer = (OSMessage*)JKRHeap::sSystemHeap->alloc(mMesgCount * sizeof(OSMessage), 4); - OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, this->mMesgCount); - JKRThread::sThreadList.append(&this->mLink); + mHeap = nullptr; + mThreadRecord = threadRecord; + mStackSize = (u32)threadRecord->stackEnd - (u32)threadRecord->stackBase; + mStackMemory = threadRecord->stackBase; + + setCommon_mesgQueue(JKRHeap::getSystemHeap(), msgCount); } JKRThread::~JKRThread() { - JKRThread::sThreadList.remove(&this->mLink); + sThreadList.remove(&mLink); - if (this->mHeap != nullptr) { - if (!OSIsThreadTerminated(this->mThreadRecord)) { - OSDetachThread(this->mThreadRecord); - OSCancelThread(this->mThreadRecord); + if (mHeap != nullptr) { + if (!OSIsThreadTerminated(mThreadRecord)) { + OSDetachThread(mThreadRecord); + OSCancelThread(mThreadRecord); } - JKRHeap::free(this->mStackMemory, this->mHeap); - JKRHeap::free(this->mThreadRecord, this->mHeap); + JKRFreeToHeap(mHeap, mStackMemory); + JKRFreeToHeap(mHeap, mThreadRecord); } - JKRHeap::free(this->mMesgBuffer, nullptr); + JKRFree(mMesgBuffer); +} + +void JKRThread::setCommon_mesgQueue(JKRHeap* heap, int msgCount) { + mMesgCount = msgCount; + mMesgBuffer = (OSMessage*)JKRHeap::alloc(mMesgCount * sizeof(OSMessage), 0, heap); + + OSInitMessageQueue(&mMesgQueue, mMesgBuffer, mMesgCount); + sThreadList.append(&mLink); + mCurrentHeap = nullptr; + mCurrentHeapError = 0; +} + +BOOL JKRThread::setCommon_heapSpecified(JKRHeap* heap, u32 stackSize, int threadPrio) { + mHeap = heap; + mStackSize = JKR_ALIGN32(stackSize); + mStackMemory = JKRHeap::alloc(mStackSize, 32, mHeap); + mThreadRecord = (OSThread*)JKRHeap::alloc(sizeof(OSThread), 32, mHeap); + return OSCreateThread(mThreadRecord, &JKRThread::start, this, (void*)((u32)mStackMemory + mStackSize), mStackSize, + threadPrio, OS_THREAD_ATTR_DETACH); } void* JKRThread::start(void* thread) { return static_cast(thread)->run(); } -// UNUSED FUNCTIONS, REQUIRED FOR RTTI +void* JKRThread::run() { + return nullptr; +} + JKRTask::JKRTask() : JKRThread(0x4000, 4, 31) { } @@ -70,7 +84,6 @@ void JKRTask::destroy() { void* JKRTask::run() { Request* req; - // OSInitFastCast(); while (true) { req = (Request*)waitMessageBlock(); if (req->mCb) { diff --git a/src/static/JSystem/JUtility/JUTAssert.cpp b/src/static/JSystem/JUtility/JUTAssert.cpp index 7cebc2e9..4be7a012 100644 --- a/src/static/JSystem/JUtility/JUTAssert.cpp +++ b/src/static/JSystem/JUtility/JUTAssert.cpp @@ -11,7 +11,7 @@ static u32 sMessageLife; static u32 sMessageOwner; static bool mSynchro; static char sMessageFileLine[64]; -static char sMessageString[96]; +static char sMessageString[256]; static u32 sDisplayTime = -1; static u32 sDevice = 3; @@ -36,8 +36,12 @@ u32 flush_subroutine() { void flushMessage() { if (flush_subroutine() && sVisible == true) { - JUTDirectPrint::getManager()->drawString(16, 16, sMessageFileLine); - JUTDirectPrint::getManager()->drawString(16, 24, sMessageString); + JUTDirectPrint* manager = JUTDirectPrint::getManager(); + JUtility::TColor color = manager->getCharColor(); + manager->setCharColor(JUtility::TColor(255, 200, 200, 255)); + manager->drawString(16, 16, sMessageFileLine); + manager->drawString(16, 24, sMessageString); + manager->setCharColor(color); } } diff --git a/src/static/JSystem/JUtility/JUTConsole.cpp b/src/static/JSystem/JUtility/JUTConsole.cpp index 9a022e4f..90cee6d3 100644 --- a/src/static/JSystem/JUtility/JUTConsole.cpp +++ b/src/static/JSystem/JUtility/JUTConsole.cpp @@ -66,10 +66,12 @@ JUTConsole::JUTConsole(uint p1, uint maxLines, bool p3) { mIsVisible = true; _69 = false; _6A = false; + _6B = false; mOutput = 1; _5C = JUtility::TColor(0, 0, 0, 100); _60 = JUtility::TColor(0, 0, 0, 230); + _64 = 8; } JUTConsole::~JUTConsole() { @@ -116,9 +118,8 @@ void JUTConsole::doDraw(JUTConsole::EConsoleType consoleType) const { J2DOrthoGraph ortho(0.0f, 0.0f, 640.0f, 480.0f, -1.0f, 1.0f); ortho.setPort(); } else { - f32 w = JUTVideo::getManager()->getFbWidth(); - f32 h = JUTVideo::getManager()->getEfbHeight(); - J2DOrthoGraph ortho(0.0f, 0.0f, w, h, -1.0f, 1.0f); + J2DOrthoGraph ortho(0.0f, 0.0f, (u16)JUTVideo::getManager()->getFbWidth(), + (u16)JUTVideo::getManager()->getEfbHeight(), -1.0f, 1.0f); ortho.setPort(); } @@ -148,6 +149,7 @@ void JUTConsole::doDraw(JUTConsole::EConsoleType consoleType) const { } else { JUTDirectPrint::getManager()->erase(mPositionX - 3, mPositionY - 2, (_20 * 6) + 6, (int)(font_yOffset * mHeight) + 4); + JUTDirectPrint::getManager()->setCharColor(JUtility::TColor(255, 255, 255, 255)); } char* linePtr; @@ -204,7 +206,7 @@ void JUTConsole::print(char const* param_0) { while (_3C < _20) { *(r28++) = ' '; _3C++; - if (_3C % 8 == 0) { + if (_3C % _64 == 0) { break; } } @@ -241,6 +243,9 @@ void JUTConsole::print(char const* param_0) { if (_38 == _30) { _30 = nextIndex(_30); } + if (_6B) { + break; + } } *r28 = 0; } diff --git a/src/static/JSystem/JUtility/JUTDbPrint.cpp b/src/static/JSystem/JUtility/JUTDbPrint.cpp index f0f264a6..0ef541d1 100644 --- a/src/static/JSystem/JUtility/JUTDbPrint.cpp +++ b/src/static/JSystem/JUtility/JUTDbPrint.cpp @@ -53,13 +53,17 @@ void JUTDbPrint::enter(int x, int y, int duration, const char* txt, int len) { } void JUTDbPrint::flush() { + flush(0, 0, JUTVideo::getManager()->getRenderMode()->fbWidth, JUTVideo::getManager()->getEfbHeight()); +} + +void JUTDbPrint::flush(int left, int top, int right, int bottom) { // eyebrow raise emoji JUTDbPrintList* pList = (JUTDbPrintList*)&mList; JUTDbPrintList* currList = mList; if (mFont) { if (currList) { - J2DOrthoGraph orthograph(0.0f, 0.0f, 640.0f, 480.0f, -1.0f, 1.0f); + J2DOrthoGraph orthograph(left, top, right, bottom, -1.0f, 1.0f); orthograph.setPort(); mFont->setGX(); mFont->setCharColor(mColor); @@ -81,21 +85,21 @@ void JUTDbPrint::flush() { } } -void JUTDbPrint::flush(int left, int top, int right, int bottom) { -} - void JUTDbPrint::drawString(int x, int y, int len, const unsigned char* str) { mFont->drawString_size(x, y, reinterpret_cast(str), len, true); } +inline void enter_(int x, int y, int duration, const char* txt, int n) { + if (n >= 0) { + JUTDbPrint::getManager()->enter(x, y, duration, txt, n < 256 ? n : 255); + } +} + void JUTReport(int x, int y, const char* fmt, ...) { va_list vl; va_start(vl, fmt); - char buf[128]; - s32 n = vsnprintf(buf, sizeof(buf), fmt, vl); - if (n >= 0) { - JUTDbPrint::getManager()->enter(x, y, 1, buf, n < 256 ? n : 255); - } + char buf[256]; + enter_(x, y, 1, buf, vsnprintf(buf, sizeof(buf), fmt, vl)); va_end(); } @@ -103,9 +107,6 @@ void JUTReport(int x, int y, int duration, const char* fmt, ...) { va_list vl; va_start(vl, fmt); char buf[256]; - s32 n = vsnprintf(buf, sizeof(buf), fmt, vl); - if (n >= 0) { - JUTDbPrint::getManager()->enter(x, y, duration, buf, n < 256 ? n : 255); - } + enter_(x, y, duration, buf, vsnprintf(buf, sizeof(buf), fmt, vl)); va_end(vl); } diff --git a/src/static/JSystem/JUtility/JUTDirectPrint.cpp b/src/static/JSystem/JUtility/JUTDirectPrint.cpp index 5ad86db3..5f4752ff 100644 --- a/src/static/JSystem/JUtility/JUTDirectPrint.cpp +++ b/src/static/JSystem/JUtility/JUTDirectPrint.cpp @@ -7,6 +7,7 @@ JUTDirectPrint* JUTDirectPrint::sDirectPrint; JUTDirectPrint::JUTDirectPrint() { changeFrameBuffer(nullptr, 0, 0); + setCharColor(0xFF, 0xFF, 0xFF); } JUTDirectPrint* JUTDirectPrint::start() { @@ -77,6 +78,8 @@ u32 JUTDirectPrint::sFontData2[77] = { }; void JUTDirectPrint::drawChar(int position_x, int position_y, int ch) { + static u32 twiceBit[4] = { 0x00000000, 0x00000003, 0x0000000C, 0x0000000F }; + int codepoint = (100 <= ch) ? ch - 100 : ch; int col_index = (codepoint % 5) * 6; int row_index = (codepoint / 5) * 7; @@ -91,19 +94,36 @@ void JUTDirectPrint::drawChar(int position_x, int position_y, int ch) { u32 data = *font_data << col_index; font_data += 1; - for (int x = 0; x < 6; x++) { - u16 value = (data & 0x80000000) ? 0xeb80 : 0x80; + if (scale_x == 1) { + data = (data & 0xFC000000) >> 1; + } else { + u32 a = twiceBit[(data >> 26) & 3]; + u32 b = twiceBit[(data >> 28) & 3] << 4; + u32 c = twiceBit[(data >> 30) & 3] << 8; + data = (a | b | c) << 19; + } - for (int y2 = 0; y2 < scale_y; y2++) { - int tmp = mStride * y2; - for (int x2 = 0; x2 < scale_x; x2++) { - u16* row = &pixel[tmp]; - row[x2] = value; - } + for (int x = 0; x < scale_x * 6; x += 2) { + u16 value; + + value = (((data & 0x40000000) ? mCharColorY : 0) | ((data & 0x80000000) ? mCharColorCb4 : 32) + + ((data & 0x40000000) ? mCharColorCb2 : 64) + + ((data & 0x20000000) ? mCharColorCb4 : 32)); + pixel[0] = value; + if (scale_y > 1) { + pixel[mStride] = value; + } + + value = (((data & 0x20000000) ? mCharColorY : 0) | ((data & 0x40000000) ? mCharColorCr4 : 32) + + ((data & 0x20000000) ? mCharColorCr2 : 64) + + ((data & 0x10000000) ? mCharColorCr4 : 32)); + pixel[1] = value; + if (scale_y > 1) { + pixel[1 + mStride] = value; } - data <<= 1; - pixel += scale_x; + pixel += 2; + data <<= 2; } pixel += mStride * scale_y - 6 * scale_x; @@ -151,7 +171,7 @@ void JUTDirectPrint::printSub(u16 position_x, u16 position_y, const char* format } } - DCFlushRange(mFrameMemory, mFbSize); + DCStoreRange(mFrameMemory, mFbSize); } void JUTDirectPrint::print(u16 position_x, u16 position_y, char const* format, ...) { @@ -175,3 +195,22 @@ void JUTDirectPrint::drawString_f(u16 position_x, u16 position_y, char const* fo va_end(args); } } + +void JUTDirectPrint::setCharColor(JUtility::TColor color) { + setCharColor(color.r, color.g, color.b); +} + +void JUTDirectPrint::setCharColor(u8 r, u8 g, u8 b) { + mCharColor = JUtility::TColor(r, g, b, 0xFF); + u16 Y = 0.257 * (int)r + 0.504 * (int)g + 0.098 * (int)b + 16; + u16 Cb = -0.148 * (int)r - 0.291 * (int)g + 0.439 * (int)b + 128; + u16 Cr = 0.439 * (int)r - 0.368 * (int)g - 0.071 * (int)b + 128; + + mCharColorY = Y << 8; + mCharColorCb = Cb; + mCharColorCb2 = Cb / 2; + mCharColorCb4 = Cb / 4; + mCharColorCr = Cr; + mCharColorCr2 = Cr / 2; + mCharColorCr4 = Cr / 4; +} diff --git a/src/static/JSystem/JUtility/JUTException.cpp b/src/static/JSystem/JUtility/JUTException.cpp index 0ea860f7..0e1945e9 100644 --- a/src/static/JSystem/JUtility/JUTException.cpp +++ b/src/static/JSystem/JUtility/JUTException.cpp @@ -5,12 +5,37 @@ #include #include "MSL_C/printf.h" +#include "_mem.h" #include "libc/string.h" #include "JSystem/JUtility/JUTException.h" #include "JSystem/JUtility/JUTDirectPrint.h" #include "JSystem/JUtility/JUTDirectFile.h" +#ifndef OS_ERROR_FPE +#define OS_ERROR_FPE 16 +#endif + +inline int __fpclassifyf(f32 x) { + switch ((*(s32*)&x) & 0x7F800000) { + case 0x7F800000: { + if ((*(s32*)&x) & 0x007FFFFF) + return FP_QNAN; + else + return FP_INFINITE; + break; + } + case 0: { + if ((*(s32*)&x) & 0x007FFFFF) + return FP_SUBNORMAL; + else + return FP_ZERO; + break; + } + } + return FP_NORMAL; +} + struct CallbackObject { JUTErrorHandler callback; u16 error; @@ -39,7 +64,8 @@ const char* JUTException::sCpuExpName[] = { "SYSTEM RESET", "BREAK POINT", "SYSTEM INTERRUPT", "THERMAL INTERRUPT", - "PROTECTION" }; + "PROTECTION", + "FLOATING POINT" }; JUTException* JUTException::sErrorManager; JUTErrorHandler JUTException::sPreUserCallback; @@ -53,6 +79,27 @@ u32 JUTException::fpscr; JSUList JUTException::sMapFileList(false); +JUTException::JUTException(JUTDirectPrint* directPrint) : JKRThread(0x4000, 0x10, 0) { + mDirectPrint = directPrint; + + OSSetErrorHandler(OS_ERROR_DSI, (OSErrorHandler)errorHandler); + OSSetErrorHandler(OS_ERROR_ISI, (OSErrorHandler)errorHandler); + OSSetErrorHandler(OS_ERROR_PROGRAM, (OSErrorHandler)errorHandler); + OSSetErrorHandler(OS_ERROR_ALIGNMENT, (OSErrorHandler)errorHandler); + OSSetErrorHandler(OS_ERROR_PROTECTION, (OSErrorHandler)errorHandler); + setFPException(0); + + sPreUserCallback = nullptr; + sPostUserCallback = nullptr; + mGamePad = nullptr; + mPadPort = JUTGamePad::Port_Invalid; + mPrintWaitTime0 = 10; + mPrintWaitTime1 = 10; + mTraceSuppress = 0xffffffff; + _98 = 0; + mPrintFlags = EXPRINTFLAG_All; +} + JUTException* JUTException::create(JUTDirectPrint* directPrint) { if (sErrorManager == nullptr) { sErrorManager = new (JKRGetSystemHeap(), 0) JUTException(directPrint); @@ -67,6 +114,8 @@ void* JUTException::run() { OSMessage message; while (true) { OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK); + VISetPreRetraceCallback(nullptr); + VISetPostRetraceCallback(nullptr); CallbackObject* cb = (CallbackObject*)message; JUTErrorHandler callback = cb->callback; u16 error = cb->error; @@ -74,42 +123,28 @@ void* JUTException::run() { u32 dsisr = cb->dsisr; u32 dar = cb->dar; - mFrameMemory = (JUTExternalFB*)sErrorManager->mDirectPrint->getFrameBuffer(); - if (!sErrorManager->mDirectPrint->getFrameBuffer()) + if (error < OS_ERROR_FPE + 1) + mStackPointer = context->gpr[1]; + + mFrameMemory = (JUTExternalFB*)VIGetCurrentFrameBuffer(); + if (mFrameMemory == nullptr) sErrorManager->createFB(); + sErrorManager->mDirectPrint->changeFrameBuffer(mFrameMemory); if (callback) callback(error, context, dsisr, dar); OSDisableInterrupts(); + mFrameMemory = (JUTExternalFB*)VIGetCurrentFrameBuffer(); + sErrorManager->mDirectPrint->changeFrameBuffer(mFrameMemory); sErrorManager->printContext(error, context, dsisr, dar); } } -JUTException::JUTException(JUTDirectPrint* directPrint) : JKRThread(0x4000, 0x10, 0) { - mDirectPrint = directPrint; - - OSSetErrorHandler(OS_ERROR_DSI, (OSErrorHandler)errorHandler); - OSSetErrorHandler(OS_ERROR_ISI, (OSErrorHandler)errorHandler); - OSSetErrorHandler(OS_ERROR_PROGRAM, (OSErrorHandler)errorHandler); - OSSetErrorHandler(OS_ERROR_ALIGNMENT, (OSErrorHandler)errorHandler); - OSSetErrorHandler(OS_ERROR_PROTECTION, (OSErrorHandler)errorHandler); - - sPreUserCallback = nullptr; - sPostUserCallback = nullptr; - mGamePad = nullptr; - mPadPort = JUTGamePad::Port_Invalid; - mPrintWaitTime0 = 10; - mPrintWaitTime1 = 10; - mTraceSuppress = 0xffffffff; - _98 = 0; - mPrintFlags = EXPRINTFLAG_All; -} - void JUTException::errorHandler(OSError error, OSContext* context, u32 dsisr, u32 dar) { msr = PPCMfmsr(); - fpscr = getFpscr(); + fpscr = context->fpscr; OSFillFPUContext(context); OSSetErrorHandler(error, nullptr); if (error == OS_ERROR_PROTECTION) { @@ -130,6 +165,51 @@ void JUTException::errorHandler(OSError error, OSContext* context, u32 dsisr, u3 OSYieldThread(); } +void JUTException::panic_f_va(const char* file, int line, const char* fmt, va_list vl) { + char buf[256]; + vsnprintf(buf, sizeof(buf) - 1, fmt, vl); + if (sErrorManager == nullptr) { + OSPanic(file, line, buf); + } + + static OSContext context; + memcpy(&context, OSGetCurrentContext(), sizeof(OSContext)); + sErrorManager->mStackPointer = OSGetStackPointer(); + + exCallbackObject.callback = sPreUserCallback; + exCallbackObject.error = 0xFF; + exCallbackObject.context = &context; + exCallbackObject.dsisr = 0; + exCallbackObject.dar = 0; + + if (sConsole == nullptr || (sConsole && !(sConsole->getOutput() & JUTConsole::OUTPUT_CONSOLE))) { + OSReport("%s in \"%s\" on line %d\n", buf, file, line); + } + + if (sConsole) { + sConsole->print_f("%s in \"%s\" on line %d\n", buf, file, line); + } + + OSSendMessage(&sMessageQueue, &exCallbackObject, OS_MESSAGE_BLOCK); + OSSuspendThread(OSGetCurrentThread()); +} + +void JUTException::panic_f(const char* file, int line, const char* fmt, ...) { + va_list vl; + va_start(vl, fmt); + panic_f_va(file, line, fmt, vl); + va_end(vl); +} + +void JUTException::setFPException(u32 fpscr_enable_bits) { + __OSFpscrEnableBits = fpscr_enable_bits; + if (fpscr_enable_bits) { + OSSetErrorHandler(OS_ERROR_FPE, (OSErrorHandler)errorHandler); + } else { + OSSetErrorHandler(OS_ERROR_FPE, nullptr); + } +} + void JUTException::showFloatSub(int index, f32 value) { if (isnan(value)) { sConsole->print_f("F%02d: Nan ", index); @@ -224,12 +304,11 @@ void JUTException::showStack(OSContext* context) { } u32 i; - u32* stackPointer; sConsole->print("-------------------------------- TRACE\n"); + u32* stackPointer = (u32*)mStackPointer; sConsole->print_f("Address: BackChain LR save\n"); - for (i = 0, stackPointer = (u32*)context->gpr[1]; - (stackPointer != nullptr) && (stackPointer != (u32*)0xFFFFFFFF) && (i++ < 0x10);) { + for (i = 0; (stackPointer != nullptr) && (stackPointer != (u32*)0xFFFFFFFF) && (i++ < 0x10);) { if (i > mTraceSuppress) { sConsole->print("Suppress trace.\n"); return; @@ -249,7 +328,57 @@ void JUTException::showMainInfo(u16 error, OSContext* context, u32 dsisr, u32 da return; } - sConsole->print_f("CONTEXT:%08XH (%s EXCEPTION)\n", context, sCpuExpName[error]); + if (error < OS_ERROR_FPE + 1) { + sConsole->print_f("CONTEXT:%08XH (%s EXCEPTION)\n", context, sCpuExpName[error]); + } else { + sConsole->print_f("CONTEXT:%08XH\n", context); + } + + if (error == OS_ERROR_FPE) { + u32 flags = fpscr & (((fpscr & 0xF8) << 22) | 0x1F80700); + if ((flags & 0x20000000) != 0) { + sConsole->print_f(" FPE: Invalid operation\n"); + if ((fpscr & 0x1000000) != 0) { + sConsole->print_f(" SNaN\n"); + } + if ((fpscr & 0x800000) != 0) { + sConsole->print_f(" Infinity - Infinity\n"); + } + if ((fpscr & 0x400000) != 0) { + sConsole->print_f(" Infinity / Infinity\n"); + } + if ((fpscr & 0x200000) != 0) { + sConsole->print_f(" 0 / 0\n"); + } + if ((fpscr & 0x100000) != 0) { + sConsole->print_f(" Infinity * 0\n"); + } + if ((fpscr & 0x80000) != 0) { + sConsole->print_f(" Invalid compare\n"); + } + if ((fpscr & 0x400) != 0) { + sConsole->print_f(" Software request\n"); + } + if ((fpscr & 0x200) != 0) { + sConsole->print_f(" Invalid square root\n"); + } + if ((fpscr & 0x100) != 0) { + sConsole->print_f(" Invalid integer convert\n"); + } + } + if ((flags & 0x10000000) != 0) { + sConsole->print_f(" FPE: Overflow\n"); + } + if ((flags & 0x8000000) != 0) { + sConsole->print_f(" FPE: Underflow\n"); + } + if ((flags & 0x4000000) != 0) { + sConsole->print_f(" FPE: Zero division\n"); + } + if ((flags & 0x2000000) != 0) { + sConsole->print_f(" FPE: Inexact result\n"); + } + } sConsole->print_f("SRR0: %08XH SRR1:%08XH\n", context->srr0, context->srr1); sConsole->print_f("DSISR: %08XH DAR: %08XH\n", dsisr, dar); } @@ -268,17 +397,18 @@ void JUTException::showGPR(OSContext* context) { } bool JUTException::showMapInfo_subroutine(u32 address, bool begin_with_newline) { - if ((address < 0x80000000) || (0x82ffffff < address)) { - return false; - } - + const char* new_line; u32 name_offset; u32 module_id; u32 section_id; u32 section_offset; u8 name_part[36]; - const char* new_line = "\n"; + if ((address < 0x80000000) || (0x82ffffff < address)) { + return false; + } + + new_line = "\n"; if (begin_with_newline == false) { new_line = ""; } @@ -296,16 +426,17 @@ bool JUTException::showMapInfo_subroutine(u32 address, bool begin_with_newline) u32 out_addr; u32 out_size; char out_line[256]; + bool map_result; if (result == true) { - result = queryMapAddress((char*)name_part, section_offset, section_id, &out_addr, &out_size, out_line, - sizeof(out_line), true, begin_with_newline); + map_result = queryMapAddress((char*)name_part, section_offset, section_id, &out_addr, &out_size, + out_line, sizeof(out_line), true, begin_with_newline); } else { - result = queryMapAddress(nullptr, address, -1, &out_addr, &out_size, out_line, sizeof(out_line), true, - begin_with_newline); + map_result = queryMapAddress(nullptr, address, -1, &out_addr, &out_size, out_line, sizeof(out_line), + true, begin_with_newline); } - if (result == true) { + if (map_result == true) { return true; } } @@ -314,6 +445,8 @@ bool JUTException::showMapInfo_subroutine(u32 address, bool begin_with_newline) } void JUTException::showGPRMap(OSContext* context) { + u32 address; + if (!sConsole) { return; } @@ -322,7 +455,7 @@ void JUTException::showGPRMap(OSContext* context) { sConsole->print("-------------------------------- GPRMAP\n"); for (int i = 0; i < 31; i++) { - u32 address = context->gpr[i]; + address = context->gpr[i]; if (address >= 0x80000000 && 0x83000000 - 1 >= address) { found_address_register = true; @@ -341,6 +474,22 @@ void JUTException::showGPRMap(OSContext* context) { } } +void JUTException::showSRR0Map(OSContext* context) { + if (!sConsole) { + return; + } + + sConsole->print("-------------------------------- SRR0MAP\n"); + u32 address = context->srr0; + if (address >= 0x80000000 && 0x83000000 - 1 >= address) { + sConsole->print_f("SRR0: %08XH", address); + if (showMapInfo_subroutine(address, true) == false) { + sConsole->print(" no information\n"); + } + JUTConsoleManager::getManager()->drawDirect(true); + } +} + void JUTException::printDebugInfo(JUTException::EInfoPage page, OSError error, OSContext* context, u32 param_3, u32 param_4) { switch (page) { @@ -356,6 +505,8 @@ void JUTException::printDebugInfo(JUTException::EInfoPage page, OSError error, O return showStack(context); case INFOPAGE_GPRMap: return showGPRMap(context); + case INFOPAGE_SRR0Map: + return showSRR0Map(context); } } @@ -450,12 +601,20 @@ void JUTException::printContext(OSError error, OSContext* context, u32 dsisr, u3 if (!sErrorManager->mDirectPrint->isActive()) { return; } + VISetPreRetraceCallback(nullptr); + VISetPostRetraceCallback(nullptr); + VISetBlack(FALSE); + VIFlush(); if (!sConsole) { return; } - sConsole->print_f("******** EXCEPTION OCCURRED! ********\nFrameMemory:%XH\n", getFrameMemory()); + if (error < OS_ERROR_FPE + 1) { + sConsole->print_f("******** EXCEPTION OCCURRED! ********\nFrameMemory:%XH\n", getFrameMemory()); + } else { + sConsole->print_f("******** USER HALT ********\nFrameMemory:%XH\n", getFrameMemory()); + } int post_callback_executed = false; while (true) { @@ -469,6 +628,11 @@ void JUTException::printContext(OSError error, OSContext* context, u32 dsisr, u3 JUTConsoleManager::sManager->drawDirect(true); waitTime(mPrintWaitTime0); } + if ((mPrintFlags & EXPRINTFLAG_SRR0Map) != 0) { + printDebugInfo(INFOPAGE_SRR0Map, error, context, dsisr, dar); + JUTConsoleManager::sManager->drawDirect(true); + waitTime(mPrintWaitTime0); + } if ((mPrintFlags & EXPRINTFLAG_GPRMap) != 0) { printDebugInfo(INFOPAGE_GPRMap, error, context, dsisr, dar); JUTConsoleManager::sManager->drawDirect(true); @@ -612,13 +776,20 @@ void JUTException::createFB() { void* begin = (void*)ALIGN_PREV((u32)end - size, 32); void* object = (void*)ALIGN_PREV((s32)begin - sizeof(JUTExternalFB), 32); - JUTExternalFB* fb = new (object) JUTExternalFB(renderMode, GX_GM_1_7, begin, size); + new (object) JUTExternalFB(renderMode, GX_GM_1_7, begin, size); - mDirectPrint->changeFrameBuffer(object); + mDirectPrint->changeFrameBuffer(begin, renderMode->fbWidth, renderMode->efbHeight); VIConfigure(renderMode); VISetNextFrameBuffer(begin); VISetBlack(FALSE); VIFlush(); + VIFlush(); + + for (int i = 0; i < 3; i++) { + u32 retraceCount = VIGetRetraceCount(); + do { + } while (retraceCount == VIGetRetraceCount()); + } mFrameMemory = (JUTExternalFB*)object; } @@ -748,8 +919,7 @@ bool JUTException::queryMapAddress_single(char* mapPath, u32 address, s32 sectio break; if ((length < 28)) continue; - // if (buffer[28] == '4') { - if (buffer[37] == '4') { + if (buffer[28] == '4') { u32 addr = ((buffer[18] - '0') << 28) | strtol(buffer + 19, nullptr, 16); int size = strtol(buffer + 11, nullptr, 16); if ((addr <= address && address < addr + size)) { diff --git a/src/static/JSystem/JUtility/JUTGamePad.cpp b/src/static/JSystem/JUtility/JUTGamePad.cpp index dff2f418..fbb81a82 100644 --- a/src/static/JSystem/JUtility/JUTGamePad.cpp +++ b/src/static/JSystem/JUtility/JUTGamePad.cpp @@ -4,12 +4,68 @@ #include "MSL_C/w_math.h" #include "MSL_C/math.h" -static u32 channel_mask[PAD_MAX_CONTROLLERS] = { 0x80000000 >> 0, 0x80000000 >> 1, 0x80000000 >> 2, 0x80000000 >> 3 }; +extern "C" void PADClampCircle(PADStatus* status); + +inline int __fpclassifyf(f32 x) { + switch ((*(s32*)&x) & 0x7F800000) { + case 0x7F800000: { + if ((*(s32*)&x) & 0x007FFFFF) + return FP_QNAN; + else + return FP_INFINITE; + break; + } + case 0: { + if ((*(s32*)&x) & 0x007FFFFF) + return FP_SUBNORMAL; + else + return FP_ZERO; + break; + } + } + return FP_NORMAL; +} + +namespace std { +inline float sqrtf(float x) { + const double _half = .5; + const double _three = 3.0; + + if (x > 0.0f) { + double guess = __frsqrte((double)x); + guess = _half * guess * (_three - guess * guess * x); + guess = _half * guess * (_three - guess * guess * x); + guess = _half * guess * (_three - guess * guess * x); + return (float)(x * guess); + } else if (x < 0.0) { + return NAN; + } else if (isnan(x)) { + return NAN; + } + + return x; +} +} // namespace std + +u32 JUTGamePad::CRumble::sChannelMask[PAD_MAX_CONTROLLERS] = { + 0x80000000 >> 0, + 0x80000000 >> 1, + 0x80000000 >> 2, + 0x80000000 >> 3, +}; + +static u32 channel_mask[PAD_MAX_CONTROLLERS] = { + 0x80000000 >> 0, + 0x80000000 >> 1, + 0x80000000 >> 2, + 0x80000000 >> 3, +}; JUTGamePad::EStickMode JUTGamePad::sStickMode = Clamped; +JUTGamePad::EClampMode JUTGamePad::sClampMode = Clamp; +f32 JUTGamePad::CStick::sPressPoint = 0.5f; +f32 JUTGamePad::CStick::sReleasePoint = 0.25f; u32 JUTGamePad::C3ButtonReset::sResetPattern = START | X | B; -f32 JUTGamePad::sPressPoint = 0.5f; -f32 JUTGamePad::sReleasePoint = 0.25f; u32 JUTGamePad::C3ButtonReset::sResetMaskPattern = 0xFFFF; JSUList JUTGamePad::mPadList(false); @@ -20,8 +76,9 @@ JUTGamePad::CStick JUTGamePad::mPadSStick[PAD_MAX_CONTROLLERS]; bool JUTGamePad::mListInitialized = false; u8 JUTGamePad::mPadAssign[PAD_MAX_CONTROLLERS]; -u32 JUTGamePad::mSuppressPadReset = 0; +u32 JUTGamePad::sSuppressPadReset = 0; u32 JUTGamePad::sAnalogMode = 0; +u32 JUTGamePad::sRumbleSupported = 0; u8 JUTGamePad::CRumble::mStatus[PAD_MAX_CONTROLLERS]; u32 JUTGamePad::CRumble::mEnabled = 0; JUTResetBtnCb JUTGamePad::C3ButtonReset::sCallback = nullptr; @@ -33,31 +90,34 @@ s32 JUTGamePad::C3ButtonReset::sResetOccurredPort = 0; JUTGamePad::JUTGamePad(EPadPort port) : mButtons(), mMainStick(), mSubStick(), mRumble(this), mLink(this), mButtonReset() { - this->mPortNum = port; - mPadAssign[port]++; - this->initList(); - JUTGamePad::mPadList.append(&this->mLink); - this->update(); - this->mPadRecord = nullptr; - this->mPadReplay = nullptr; + mPortNum = port; + if (mPortNum >= 0) { + mPadAssign[port]++; + } + initList(); + JUTGamePad::mPadList.append(&mLink); + update(); + mPadRecord = nullptr; + mPadReplay = nullptr; + clear(); } JUTGamePad::JUTGamePad() : mButtons(), mMainStick(), mSubStick(), mRumble(this), mLink(this), mButtonReset() { - this->mPortNum = -1; - this->initList(); - JUTGamePad::mPadList.append(&this->mLink); - this->mPadRecord = nullptr; - this->mPadReplay = nullptr; - this->clear(); + mPortNum = -1; + initList(); + JUTGamePad::mPadList.append(&mLink); + mPadRecord = nullptr; + mPadReplay = nullptr; + clear(); } JUTGamePad::~JUTGamePad() { - if (this->mPortNum != -1) { - mPadAssign[this->mPortNum]--; - this->mPortNum = -1; + if (mPortNum >= 0) { + mPadAssign[mPortNum]--; + mPortNum = -1; } - JUTGamePad::mPadList.remove(&this->mLink); + JUTGamePad::mPadList.remove(&mLink); } void JUTGamePad::initList() { @@ -75,57 +135,67 @@ void JUTGamePad::init() { } void JUTGamePad::clear() { - this->mButtonReset.mReset = false; + mButtonReset.mReset = false; + mResetEnabled = true; } -void JUTGamePad::read() { - PADRead(JUTGamePad::mPadStatus); - PADClamp(JUTGamePad::mPadStatus); +u32 JUTGamePad::read() { + sRumbleSupported = PADRead(mPadStatus); + + switch (sClampMode) { + case Clamp: + PADClamp(mPadStatus); + break; + case ClampCircle: + PADClampCircle(mPadStatus); + break; + } u32 mask; u32 resetControllerMask = 0; - for (s32 i = 0; i < PAD_MAX_CONTROLLERS; i++) { + for (int i = 0; i < PAD_MAX_CONTROLLERS; i++) { mask = 0x80000000 >> i; - if (JUTGamePad::mPadStatus[i].err == 0) { - PADStatus* status = &JUTGamePad::mPadStatus[i]; + if (mPadStatus[i].err == PAD_ERR_NONE) { + PADStatus* status = &mPadStatus[i]; u32 buttons; - buttons = (JUTGamePad::mPadMStick[i].update(status->stickX, status->stickY, JUTGamePad::sStickMode, - WhichStick_MainStick) - << 24); - buttons |= (JUTGamePad::mPadSStick[i].update(status->substickX, status->substickY, JUTGamePad::sStickMode, - WhichStick_SubStick) - << 16); - JUTGamePad::mPadButton[i].update(status, buttons); - } else if (JUTGamePad::mPadStatus[i].err == -1) { - JUTGamePad::mPadMStick[i].update(0, 0, JUTGamePad::sStickMode, WhichStick_MainStick); - JUTGamePad::mPadSStick[i].update(0, 0, JUTGamePad::sStickMode, WhichStick_SubStick); - JUTGamePad::mPadButton[i].update(nullptr, 0); - - if ((JUTGamePad::mSuppressPadReset & mask) == 0) { + buttons = mPadMStick[i].update(status->stickX, status->stickY, sStickMode, WhichStick_MainStick, + mPadButton[i].mButton) + << 24; + buttons |= mPadSStick[i].update(status->substickX, status->substickY, sStickMode, WhichStick_SubStick, + mPadButton[i].mButton) + << 16; + mPadButton[i].update(status, buttons); + } else if (mPadStatus[i].err == PAD_ERR_NO_CONTROLLER) { + mPadMStick[i].update(0, 0, sStickMode, WhichStick_MainStick, 0); + mPadSStick[i].update(0, 0, sStickMode, WhichStick_SubStick, 0); + mPadButton[i].update(nullptr, 0); + + if ((sSuppressPadReset & mask) == 0) { resetControllerMask |= mask; } } else { - JUTGamePad::mPadButton[i].mTrigger = 0; - JUTGamePad::mPadButton[i].mRelease = 0; - JUTGamePad::mPadButton[i].mRepeat = 0; + mPadButton[i].mTrigger = 0; + mPadButton[i].mRelease = 0; + mPadButton[i].mRepeat = 0; } } JSUListIterator it; - for (it = JUTGamePad::mPadList.getFirst(); it != JUTGamePad::mPadList.getEnd(); it++) { - if (it->getPadReplay() != nullptr) { + for (it = mPadList.getFirst(); it != mPadList.getEnd(); ++it) { + if (it->getPadReplay() != nullptr && it->getPadReplay()->isActive()) { PADStatus status; u32 buttons; it->getPadReplay()->read(&status); - buttons = it->mMainStick.update(status.stickX, status.stickY, JUTGamePad::sStickMode, WhichStick_MainStick) + buttons = it->mMainStick.update(status.stickX, status.stickY, sStickMode, WhichStick_MainStick, + it->mButtons.mButton) << 24; - buttons |= - it->mSubStick.update(status.substickX, status.substickY, JUTGamePad::sStickMode, WhichStick_SubStick) - << 16; + buttons |= it->mSubStick.update(status.substickX, status.substickY, sStickMode, WhichStick_SubStick, + it->mButtons.mButton) + << 16; it->mButtons.update(&status, buttons); } else { if (it->mPortNum == -1) { @@ -135,11 +205,12 @@ void JUTGamePad::read() { it->update(); } - if (it->getPadRecord() != nullptr && it->mPortNum != -1) { - int port = it->mPortNum; - - if (JUTGamePad::mPadStatus[port].err == 0) { - it->getPadRecord()->write(&JUTGamePad::mPadStatus[port]); + if (it->getPadRecord() != nullptr && it->getPadRecord()->isActive()) { + if (it->mPortNum >= 0) { + int port = it->mPortNum; + if (mPadStatus[port].err == PAD_ERR_NONE) { + it->getPadRecord()->write(&mPadStatus[port]); + } } } } @@ -148,55 +219,78 @@ void JUTGamePad::read() { PADReset(resetControllerMask); } - JUTGamePad::checkResetSwitch(); + checkResetSwitch(); + return sRumbleSupported; } void JUTGamePad::assign() { for (s32 i = 0; i < PAD_MAX_CONTROLLERS; i++) { - if (JUTGamePad::mPadStatus[i].err == 0 && JUTGamePad::mPadAssign[i] == 0) { - this->mPortNum = i; + if (JUTGamePad::mPadStatus[i].err == PAD_ERR_NONE && JUTGamePad::mPadAssign[i] == 0) { + mPortNum = i; JUTGamePad::mPadAssign[i] = 1; - JUTGamePad::mPadButton[i].setRepeat(this->mButtons.mRepeatMask, this->mButtons.mRepeatDelay, - this->mButtons.mRepeatFrequency); - this->mRumble.clear(this); + JUTGamePad::mPadButton[i].setRepeat(mButtons.mRepeatMask, mButtons.mRepeatDelay, mButtons.mRepeatFrequency); + mRumble.clear(this); break; } } } void JUTGamePad::checkResetCallback(OSTime time) { - if (this->mPortNum != -1 && time >= JUTGamePad::C3ButtonReset::sThreshold) { + if (time >= JUTGamePad::C3ButtonReset::sThreshold) { JUTGamePad::C3ButtonReset::sResetOccurred = true; - JUTGamePad::C3ButtonReset::sResetOccurredPort = this->mPortNum; + JUTGamePad::C3ButtonReset::sResetOccurredPort = mPortNum; - if (JUTGamePad::C3ButtonReset::sCallback != NULL) { - (*JUTGamePad::C3ButtonReset::sCallback)(this->mPortNum, JUTGamePad::C3ButtonReset::sCallbackArg); + if (JUTGamePad::C3ButtonReset::sCallback != nullptr) { + (*JUTGamePad::C3ButtonReset::sCallback)(mPortNum, JUTGamePad::C3ButtonReset::sCallbackArg); } } } void JUTGamePad::update() { - if (this->mPortNum != -1) { - this->mButtons = JUTGamePad::mPadButton[this->mPortNum]; - this->mMainStick = JUTGamePad::mPadMStick[this->mPortNum]; - this->mSubStick = JUTGamePad::mPadSStick[this->mPortNum]; - this->mErrorStatus = JUTGamePad::mPadStatus[this->mPortNum].err; - - if (JUTGamePad::C3ButtonReset::sResetOccurred == false) { - if (JUTGamePad::C3ButtonReset::sResetPattern == - (JUTGamePad::C3ButtonReset::sResetPattern & this->mButtons.mButton)) { - if (this->mButtonReset.mReset == true) { - this->checkResetCallback(OSGetTime() - this->mResetTime); - } else { - this->mButtonReset.mReset = true; - this->mResetTime = OSGetTime(); - } + if (mPortNum != -1) { + if (mPortNum >= 0 && mPortNum < PAD_MAX_CONTROLLERS) { + mButtons = JUTGamePad::mPadButton[mPortNum]; + mMainStick = JUTGamePad::mPadMStick[mPortNum]; + mSubStick = JUTGamePad::mPadSStick[mPortNum]; + mErrorStatus = JUTGamePad::mPadStatus[mPortNum].err; + } + + if (!mResetEnabled || JUTGamePad::C3ButtonReset::sResetPattern != + (mButtons.mButton & JUTGamePad::C3ButtonReset::sResetMaskPattern)) { + mButtonReset.mReset = false; + } else if (JUTGamePad::C3ButtonReset::sResetOccurred == false) { + if (mButtonReset.mReset == true) { + checkResetCallback(OSGetTime() - mResetTime); } else { - this->mButtonReset.mReset = false; + mButtonReset.mReset = true; + mResetTime = OSGetTime(); } } - this->mRumble.update(this->mPortNum); + JSUListIterator pad = JUTGamePadLongPress::sPatternList.getFirst(); + for (; pad != JUTGamePadLongPress::sPatternList.getEnd(); ++pad) { + if (pad->isValid()) { + if (mPortNum >= 0 && mPortNum < PAD_MAX_CONTROLLERS) { + if ((mButtons.mButton & pad->getMaskPattern()) == pad->getPattern()) { + if (pad->_20[mPortNum] == true) { + s64 diff = OSGetTime() - pad->mTimer[mPortNum]; + pad->checkCallback(mPortNum, diff); + continue; + } + + pad->_20[mPortNum] = true; + pad->mTimer[mPortNum] = OSGetTime(); + continue; + } + + pad->_20[mPortNum] = false; + } + } + } + + if (mPortNum >= 0 && mPortNum < PAD_MAX_CONTROLLERS) { + mRumble.update(mPortNum); + } } } @@ -220,19 +314,19 @@ void JUTGamePad::checkResetSwitch() { } void JUTGamePad::CButton::clear() { - this->mButton = 0; - this->mTrigger = 0; - this->mRelease = 0; - this->mRepeat = 0; - this->mAnalogA = 0; - this->mAnalogB = 0; - this->mAnalogL = 0; - this->mAnalogR = 0; - this->mRepeatTimer = 0; - this->mRepeatLastButton = 0; - this->mRepeatMask = 0; - this->mRepeatDelay = 0; - this->mRepeatFrequency = 0; + mButton = 0; + mTrigger = 0; + mRelease = 0; + mRepeat = 0; + mAnalogA = 0; + mAnalogB = 0; + mAnalogL = 0; + mAnalogR = 0; + mRepeatTimer = 0; + mRepeatLastButton = 0; + mRepeatMask = 0; + mRepeatDelay = 0; + mRepeatFrequency = 0; } void JUTGamePad::CButton::update(const PADStatus* padStatus, u32 stick_buttons) { @@ -246,107 +340,123 @@ void JUTGamePad::CButton::update(const PADStatus* padStatus, u32 stick_buttons) } buttons = stick_buttons | tempButtons; - this->mRepeat = 0; + mRepeat = 0; - if (this->mRepeatDelay != 0) { - if (this->mRepeatMask != 0) { - u32 repeatButtons = buttons & this->mRepeatMask; - this->mRepeat = 0; + if (mRepeatDelay != 0) { + if (mRepeatMask != 0) { + u32 repeatButtons = buttons & mRepeatMask; + mRepeat = 0; if (repeatButtons == 0) { - this->mRepeatLastButton = 0; - this->mRepeatTimer = 0; - } else if (this->mRepeatLastButton == repeatButtons) { - this->mRepeatTimer++; - if (this->mRepeatTimer == this->mRepeatDelay || - (this->mRepeatTimer > this->mRepeatDelay && - ((this->mRepeatTimer - this->mRepeatDelay) % this->mRepeatFrequency) == 0)) { - this->mRepeat = repeatButtons; + mRepeatLastButton = 0; + mRepeatTimer = 0; + } else if (mRepeatLastButton == repeatButtons) { + mRepeatTimer++; + if (mRepeatTimer == mRepeatDelay || + (mRepeatTimer > mRepeatDelay && ((mRepeatTimer - mRepeatDelay) % mRepeatFrequency) == 0)) { + mRepeat = repeatButtons; } } else { - this->mRepeat = repeatButtons & (this->mRepeatLastButton ^ 0xFFFFFFFF); - this->mRepeatLastButton = repeatButtons; - this->mRepeatTimer = 0; + mRepeat = repeatButtons & (mRepeatLastButton ^ 0xFFFFFFFF); + mRepeatLastButton = repeatButtons; + mRepeatTimer = 0; } } } - this->mTrigger = buttons & (buttons ^ this->mButton); - this->mRelease = this->mButton & (buttons ^ this->mButton); - this->mButton = buttons; - this->mRepeat |= (this->mRepeatMask ^ 0xFFFFFFFF) & this->mTrigger; + mTrigger = buttons & (buttons ^ mButton); + mRelease = mButton & (buttons ^ mButton); + mButton = buttons; + mRepeat |= (mRepeatMask ^ 0xFFFFFFFF) & mTrigger; if (padStatus != nullptr) { - this->mAnalogA = padStatus->analogA; - this->mAnalogB = padStatus->analogB; - this->mAnalogL = padStatus->triggerLeft; - this->mAnalogR = padStatus->triggerRight; + mAnalogA = padStatus->analogA; + mAnalogB = padStatus->analogB; + mAnalogL = padStatus->triggerLeft; + mAnalogR = padStatus->triggerRight; } else { - this->mAnalogA = 0; - this->mAnalogB = 0; - this->mAnalogL = 0; - this->mAnalogR = 0; + mAnalogA = 0; + mAnalogB = 0; + mAnalogL = 0; + mAnalogR = 0; } - this->mAnalogLf = (f32)(int)this->mAnalogL / 150.0f; - this->mAnalogRf = (f32)(int)this->mAnalogR / 150.0f; + mAnalogLf = (f32)(int)mAnalogL / 150.0f; + mAnalogRf = (f32)(int)mAnalogR / 150.0f; } void JUTGamePad::CStick::clear() { - this->mX = 0.0f; - this->mY = 0.0f; - this->mValue = 0.0f; - this->mAngle = 0; + mX = 0.0f; + mY = 0.0f; + mValue = 0.0f; + mAngle = 0; } -u32 JUTGamePad::CStick::update(s8 x, s8 y, EStickMode stickMode, EWhichStick whichStick) { - int stickMax = whichStick == WhichStick_MainStick ? 54 : 42; +u32 JUTGamePad::CStick::update(s8 x, s8 y, EStickMode stickMode, EWhichStick whichStick, u32 mask) { + s32 clamp; + switch (getClampMode()) { + case Clamp: + clamp = whichStick == WhichStick_MainStick ? 54 : 42; + break; + case ClampCircle: + clamp = whichStick == WhichStick_MainStick ? 38 : 29; + break; + default: + clamp = whichStick == WhichStick_MainStick ? 69 : 57; + break; + } - this->mX = (f32)x / (f32)stickMax; - this->mY = (f32)y / (f32)stickMax; - this->mValue = sqrtf(this->mX * this->mX + this->mY * this->mY); + mAnalogX = x; + mAnalogY = y; + mX = (f32)x / clamp; + mY = (f32)y / clamp; + mValue = std::sqrtf(mX * mX + mY * mY); - if (this->mValue > 1.0f) { + if (mValue > 1.0f) { if (stickMode == Clamped) { - this->mX /= this->mValue; - this->mY /= this->mValue; + mX /= mValue; + mY /= mValue; } - this->mValue = 1.0f; + mValue = 1.0f; } - if (this->mValue > 0.0f) { - if (this->mY == 0.0f) { - if (this->mX > 0.0f) { - this->mAngle = 0x4000; + if (mValue > 0.0f) { + if (mY == 0.0f) { + if (mX > 0.0f) { + mAngle = 0x4000; } else { - this->mAngle = -0x4000; + mAngle = -0x4000; } } else { - f32 angle = atan2(this->mX, -this->mY); - this->mAngle = angle * 10430.379f; //((f32)0x8000 / F_PI); + f32 angle = atan2(mX, -mY); + mAngle = angle * 10430.379f; //((f32)0x8000 / F_PI); } } - return this->getButton(); + return getButton(mask >> (whichStick == WhichStick_MainStick ? 24 : 16)); } -u32 JUTGamePad::CStick::getButton() { - u32 button = 0; +u32 JUTGamePad::CStick::getButton(u32 mask) { + u32 button = mask & 0xF; - if (-0.25f < this->mX && this->mX < 0.25f) { + if (-sReleasePoint < mX && mX < sReleasePoint) { button &= ~(DPAD_LEFT | DPAD_RIGHT); - } else if (this->mX <= -0.5f) { + } else if (mX <= -sPressPoint) { + button &= ~DPAD_RIGHT; button |= DPAD_LEFT; - } else if (this->mX >= 0.5f) { + } else if (mX >= sPressPoint) { + button &= ~DPAD_LEFT; button |= DPAD_RIGHT; } - if (-0.25f < this->mY && this->mY < 0.25f) { + if (-sReleasePoint < mY && mY < sReleasePoint) { button &= ~(DPAD_DOWN | DPAD_UP); - } else if (this->mY <= -0.5f) { + } else if (mY <= -sPressPoint) { + button &= ~DPAD_UP; button |= DPAD_DOWN; - } else if (this->mY >= 0.5f) { + } else if (mY >= sPressPoint) { + button &= ~DPAD_DOWN; button |= DPAD_UP; } @@ -354,61 +464,57 @@ u32 JUTGamePad::CStick::getButton() { } void JUTGamePad::CRumble::clear() { - this->mFrame = 0; - this->mLength = 0; - this->mData = nullptr; - this->mFrameCount = 0; + mFrame = 0; + mLength = 0; + mData = nullptr; + mFrameCount = 0; + mHardStopData = nullptr; JUTGamePad::CRumble::mEnabled = 0xF0000000; } void JUTGamePad::CRumble::clear(JUTGamePad* gamePad) { if (0 <= gamePad->getPortNum() && gamePad->getPortNum() < PAD_MAX_CONTROLLERS) { JUTGamePad::CRumble::mStatus[gamePad->getPortNum()] = 0; - this->stopMotorHard(gamePad->getPortNum()); + gamePad->stopMotorHard(); } - this->clear(); + clear(); } void JUTGamePad::CRumble::startMotor(int port) { - if (JUTGamePad::CRumble::isEnabled(channel_mask[port])) { + if (JUTGamePad::CRumble::isEnabledPort(port)) { PADControlMotor(port, PAD_MOTOR_RUMBLE); JUTGamePad::CRumble::mStatus[port] = 1; } } -void JUTGamePad::CRumble::stopMotor(int port) { - if (JUTGamePad::CRumble::isEnabled(channel_mask[port])) { - PADControlMotor(port, PAD_MOTOR_STOP); +void JUTGamePad::CRumble::stopMotor(int port, bool hard) { + if (JUTGamePad::CRumble::isEnabledPort(port)) { + PADControlMotor(port, (u8)(hard ? PAD_MOTOR_STOP_HARD : PAD_MOTOR_STOP)); JUTGamePad::CRumble::mStatus[port] = 0; } } -void JUTGamePad::CRumble::stopMotorHard(int port) { - if (JUTGamePad::CRumble::isEnabled(channel_mask[port])) { - PADControlMotor(port, PAD_MOTOR_STOP_HARD); - JUTGamePad::CRumble::mStatus[port] = 0; - } -} - -static inline u8 getNumBit(const u8* data, int bit) { - return (((0x80 >> (bit & 7)) & data[(u32)bit >> 3]) & 0xFF); +static bool getNumBit(u8* data, int bit) { + u8 numBit = (0x80 >> (bit & 7)) & data[bit >> 3]; + return numBit != 0; } void JUTGamePad::CRumble::update(s16 port) { - if (!JUTGamePad::CRumble::isEnabled(channel_mask[port])) { - this->mFrame = 0; - this->mLength = 0; - this->mData = nullptr; - this->mFrameCount = 0; + if (!JUTGamePad::CRumble::isEnabledPort(port)) { + mFrame = 0; + mLength = 0; + mData = nullptr; + mFrameCount = 0; + mHardStopData = nullptr; } - if (this->mLength != 0) { - if (this->mFrame >= this->mLength) { + if (mLength != 0) { + if (mFrame >= mLength) { JUTGamePad::CRumble::stopMotorHard(port); - this->mLength = 0; + mLength = 0; } else { - if (this->mFrameCount == 0) { + if (mFrameCount == 0) { if (JUTGamePad::CRumble::mStatus[port] == 0) { JUTGamePad::CRumble::startMotor(port); } @@ -416,34 +522,57 @@ void JUTGamePad::CRumble::update(s16 port) { return; } - u8 bit = getNumBit(this->mData, this->mFrame % this->mFrameCount); - if (bit != 0 && JUTGamePad::CRumble::mStatus[port] == 0) { + bool enable = getNumBit(mData, mFrame % mFrameCount); + bool status = JUTGamePad::CRumble::mStatus[port]; + if (enable && !status) { JUTGamePad::CRumble::startMotor(port); - } else if (bit == 0 && JUTGamePad::CRumble::mStatus[port] != 0) { - JUTGamePad::CRumble::stopMotorHard(port); + } else if (!enable) { + bool hardStop = false; + if (mHardStopData != nullptr) { + hardStop = getNumBit(mHardStopData, mFrame % mFrameCount); + } + + if (status) { + JUTGamePad::CRumble::stopMotor(port, hardStop); + } else if (hardStop) { + JUTGamePad::CRumble::stopMotorHard(port); + } } } - this->mFrame++; + mFrame++; } } void JUTGamePad::CButton::setRepeat(u32 repeatMask, u32 repeatDelay, u32 repeatFreq) { - this->mRepeatLastButton = 0; - this->mRepeatTimer = 0; - this->mRepeatMask = repeatMask; - this->mRepeatDelay = repeatDelay; - this->mRepeatFrequency = repeatFreq; + mRepeatLastButton = 0; + mRepeatTimer = 0; + mRepeatMask = repeatMask; + mRepeatDelay = repeatDelay; + mRepeatFrequency = repeatFreq; } bool JUTGamePad::recalibrate(u32 channels) { - u32 channelMasks[PAD_MAX_CONTROLLERS] = { 0x80000000 >> 0, 0x80000000 >> 1, 0x80000000 >> 2, 0x80000000 >> 3 }; - for (int i = 0; i < PAD_MAX_CONTROLLERS; i++) { - if ((JUTGamePad::mSuppressPadReset & channelMasks[i]) != 0) { - channels &= channelMasks[i] ^ 0xFFFFFFFF; + if ((JUTGamePad::sSuppressPadReset & channel_mask[i]) != 0) { + channels &= channel_mask[i] ^ 0xFFFFFFFF; } } - return PADRecalibrate(channels); + BOOL res = PADRecalibrate(channels); + return res; +} + +JSUList JUTGamePadLongPress::sPatternList(false); + +void JUTGamePadLongPress::checkCallback(int port, u32 timer) { + if (port >= 0) { + if (timer >= _1C) { + _11 = true; + _48[port] = true; + if (mCallback != nullptr) { + mCallback(port, this, _50); + } + } + } } diff --git a/src/static/JSystem/JUtility/JUTVideo.cpp b/src/static/JSystem/JUtility/JUTVideo.cpp index 448b1b09..a7a186b5 100644 --- a/src/static/JSystem/JUtility/JUTVideo.cpp +++ b/src/static/JSystem/JUtility/JUTVideo.cpp @@ -26,9 +26,9 @@ void JUTVideo::destroyManager() { JUTVideo::JUTVideo(const GXRenderModeObj* renderModeObj) { mRenderModeObj = nullptr; VIInit(); - setRenderMode(renderModeObj); mIsSetBlack = true; mSetBlackFrameCount = 2; + setRenderMode(renderModeObj); VISetBlack(TRUE); VIFlush(); _08 = 0; @@ -102,9 +102,9 @@ void JUTVideo::preRetraceProc(u32 retrace_count) { VISetBlack(TRUE); VIFlush(); } else { - VISetBlack(FALSE); VISetNextFrameBuffer(xfb->getDisplayingXfb()); VIFlush(); + VISetBlack(FALSE); frameBuffer = xfb->getDisplayingXfb(); } } @@ -117,7 +117,9 @@ void JUTVideo::preRetraceProc(u32 retrace_count) { GXFlush(); xfb->setSDrawingFlag(2); frameBuffer = xfb->getDisplayingXfb(); - VISetBlack(FALSE); + if (VIGetNextFrameBuffer()) { + VISetBlack(FALSE); + } } else { VISetBlack(TRUE); diff --git a/src/static/JSystem/JUtility/JUTXfb.cpp b/src/static/JSystem/JUtility/JUTXfb.cpp index cb8f69ef..d4a46411 100644 --- a/src/static/JSystem/JUtility/JUTXfb.cpp +++ b/src/static/JSystem/JUtility/JUTXfb.cpp @@ -19,14 +19,20 @@ void JUTXfb::common_init(int xfbNum) { mSDrawingFlag = 99; } -JUTXfb::JUTXfb(JKRHeap* heap, JUTXfb::EXfbNumber number) { +JUTXfb::JUTXfb(const GXRenderModeObj* rmode, JKRHeap* heap, JUTXfb::EXfbNumber number) { common_init(number); - u16 efbWidth = JUTVideo::getManager()->getRenderMode()->fbWidth; - u16 xfbHeight = JUTVideo::getManager()->getRenderMode()->xfbHeight; - u16 efbHeight = JUTVideo::getManager()->getRenderMode()->efbHeight; + if (rmode) { + initiate(rmode->fbWidth, rmode->xfbHeight, heap, number); + } else { + u16 efbWidth = JUTVideo::getManager()->getRenderMode()->fbWidth; + u16 xfbHeight = JUTVideo::getManager()->getRenderMode()->xfbHeight; + u16 efbHeight = JUTVideo::getManager()->getRenderMode()->efbHeight; - initiate(efbWidth, xfbHeight, heap, number); + f32 yScale = GXGetYScaleFactor(efbHeight, xfbHeight); + u16 numLines = GXGetNumXfbLines(efbHeight, yScale); + initiate(efbWidth, numLines, heap, number); + } } JUTXfb::~JUTXfb() { @@ -45,7 +51,7 @@ void JUTXfb::delXfb(int xfbIdx) { JUTXfb* JUTXfb::createManager(JKRHeap* heap, JUTXfb::EXfbNumber number) { JUT_CONFIRM_MESSAGE(sManager == 0); if (sManager == nullptr) { - sManager = new JUTXfb(heap, number); + sManager = new JUTXfb(nullptr, heap, number); } return sManager; } @@ -83,8 +89,11 @@ void JUTXfb::initiate(u16 w, u16 h, JKRHeap* heap, JUTXfb::EXfbNumber number) { } u32 JUTXfb::accumeXfbSize() { - JUTVideo* video = JUTVideo::getManager(); - u16 height = video->getXfbHeight(); - u16 width = video->getFbWidth(); - return (u16)ALIGN_NEXT(width, 16) * height * 2; + const GXRenderModeObj* rmode = JUTVideo::getManager()->getRenderMode(); + u16 efbHeight = rmode->efbHeight; + u16 xfbHeight = rmode->xfbHeight; + u16 efbWidth = rmode->fbWidth; + f32 yScale = GXGetYScaleFactor(efbHeight, xfbHeight); + u16 numLines = GXGetNumXfbLines(efbHeight, yScale); + return (u16)ALIGN_NEXT((u16)efbWidth, 16) * numLines * 2; } diff --git a/src/static/JSystem/JUtility/carddrv.c b/src/static/JSystem/JUtility/carddrv.c index 5ef4a41e..c71e0667 100644 --- a/src/static/JSystem/JUtility/carddrv.c +++ b/src/static/JSystem/JUtility/carddrv.c @@ -14,11 +14,11 @@ CSD SD_CSD[CARD_NUM_CHANS]; OSAlarm CARD_Alarm[CARD_NUM_CHANS]; OSSemaphore CARD_Sem[CARD_NUM_CHANS]; -const u8 CARD_TBL_CLOCK_DIV[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0x05, 0xFF, 0x00, 0x03, 0x05, 0xFF, 0x00, 0x03, 0x05, - 0xFF, 0x00, 0x03, 0x05, 0xFF, 0x01, 0x04, 0x05, 0xFF, 0x01, 0x04, 0x05, 0xFF, 0x01, 0x04, 0x05, - 0xFF, 0x01, 0x05, 0x05, 0xFF, 0x02, 0x05, 0x05, 0xFF, 0x02, 0x05, 0x05, 0xFF, 0x02, 0x05, 0x05, - 0xFF, 0x02, 0x05, 0x05, 0xFF, 0x02, 0x05, 0x05, 0xFF, 0x02, 0x05, 0x05, 0xFF, 0x03, 0x05, 0x05, +const u8 CARD_TBL_CLOCK_DIV[16][4] = { + { 0xFF, 0xFF, 0xFF, 0xFF }, { 0xFF, 0x00, 0x03, 0x05 }, { 0xFF, 0x00, 0x03, 0x05 }, { 0xFF, 0x00, 0x03, 0x05 }, + { 0xFF, 0x00, 0x03, 0x05 }, { 0xFF, 0x01, 0x04, 0x05 }, { 0xFF, 0x01, 0x04, 0x05 }, { 0xFF, 0x01, 0x04, 0x05 }, + { 0xFF, 0x01, 0x05, 0x05 }, { 0xFF, 0x02, 0x05, 0x05 }, { 0xFF, 0x02, 0x05, 0x05 }, { 0xFF, 0x02, 0x05, 0x05 }, + { 0xFF, 0x02, 0x05, 0x05 }, { 0xFF, 0x02, 0x05, 0x05 }, { 0xFF, 0x02, 0x05, 0x05 }, { 0xFF, 0x03, 0x05, 0x05 }, }; int CARD_WP_Flag[CARD_NUM_CHANS]; // write protection flag @@ -29,7 +29,7 @@ int CARD_SectorSize[CARD_NUM_CHANS]; volatile u16 CARD_ErrStatus[CARD_NUM_CHANS]; int CARD_Status[CARD_NUM_CHANS]; int CARD_UnlockFlag[CARD_NUM_CHANS]; -int CARD_Size[CARD_NUM_CHANS]; +u32 CARD_Size[CARD_NUM_CHANS]; int func_CARD_In[CARD_NUM_CHANS]; int func_CARD_Out[CARD_NUM_CHANS]; @@ -83,13 +83,17 @@ u16 CARD_Select(u16 nDrive) { } u16 CARD_Reset() { - u32 sp8; - u32 temp_r0; - u8 temp_r28; - u8 temp_r29; - u8 temp_r29_2; + volatile u32 sp8; + u8 tran; + u8 value; + u16 div; + u8 unit; - CARD_ExiFreq[CARD_ExiChannel] = 4; + (void)tran; + (void)tran; + (void)tran; + + CARD_ExiFreq[CARD_ExiChannel] = 0; if (EXIAttach(CARD_ExiChannel, (EXICallback)EXI_Null) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_0090; @@ -133,45 +137,51 @@ u16 CARD_Reset() { return CARD_ErrStatus[CARD_ExiChannel]; } - temp_r29 = SD_CSD[CARD_ExiChannel].data[3]; - temp_r29_2 = temp_r29 & 7; + unit = SD_CSD[CARD_ExiChannel].data[3]; + value = (unit >> 3) & 0xF; + unit &= 7; - if (temp_r29_2 > 3) { + if (unit > 3) { CARD_ExiFreq[CARD_ExiChannel] = 0; } else { - temp_r28 = CARD_TBL_CLOCK_DIV[((((temp_r29 >> 3U) & 0xF) * 4) & 0x3FC) + temp_r29_2]; + div = CARD_TBL_CLOCK_DIV[value][unit]; - if (temp_r28 == 0xFF) { + if (div == 0xFF) { CARD_ExiFreq[CARD_ExiChannel] = 0; } else { - CARD_ExiFreq[CARD_ExiChannel] = temp_r28; + CARD_ExiFreq[CARD_ExiChannel] = div; } } + CARD_ErrStatus[CARD_ExiChannel]; CARD_SD_Status(); if (CARD_ErrStatus[CARD_ExiChannel] != 0) { return CARD_ErrStatus[CARD_ExiChannel]; } - CARD_Size[CARD_ExiChannel] = SD_SDSTATUS[CARD_ExiChannel].data[6] * 0x100 + SD_SDSTATUS[CARD_ExiChannel].data[7]; - CARD_Size[CARD_ExiChannel] = SD_SDSTATUS[CARD_ExiChannel].data[4] * 0x100 + SD_SDSTATUS[CARD_ExiChannel].data[5]; + ((u16*)&CARD_Size[CARD_ExiChannel])[1] = + ((u16)SD_SDSTATUS[CARD_ExiChannel].data[6] << 8) + SD_SDSTATUS[CARD_ExiChannel].data[7]; + ((u16*)&CARD_Size[CARD_ExiChannel])[0] = + ((u16)SD_SDSTATUS[CARD_ExiChannel].data[4] << 8) + SD_SDSTATUS[CARD_ExiChannel].data[5]; - CARD_Size[CARD_ExiChannel] *= - (4 << ((SD_CSD[CARD_ExiChannel].data[9] & 3) << 1 | (SD_CSD[CARD_ExiChannel].data[10] >> 7))); + CARD_Size[CARD_ExiChannel] *= 4 << (((SD_CSD[CARD_ExiChannel].data[9] & 3) << 1) | + ((SD_CSD[CARD_ExiChannel].data[10] & 0x80) >> 7)); - if ((SD_CSD[CARD_ExiChannel].data[5] & 0xf) != 0) { - CARD_Size[CARD_ExiChannel] <<= - ((SD_CSD[CARD_ExiChannel].data[12] & 3) << 2 | (SD_CSD[CARD_ExiChannel].data[0xd] >> 6)); + if ((SD_CSD[CARD_ExiChannel].data[5] & 0xF) != 0) { + CARD_Size[CARD_ExiChannel] = CARD_Size[CARD_ExiChannel] << (((SD_CSD[CARD_ExiChannel].data[12] & 3) << 2) | + ((SD_CSD[CARD_ExiChannel].data[13] & 0xC0) >> 6)); } CARD_Size[CARD_ExiChannel] /= CARD_SectorSize[CARD_ExiChannel]; - CARD_Size[CARD_ExiChannel] += - (((SD_CSD[CARD_ExiChannel].data[8] >> 6) + SD_CSD[CARD_ExiChannel].data[7] * 4 + - (SD_CSD[CARD_ExiChannel].data[6] & 3) * 0x400 + 1) * - (4 << ((SD_CSD[CARD_ExiChannel].data[9] & 3) << 1 | (SD_CSD[CARD_ExiChannel].data[10] >> 7))) - << ((SD_CSD[CARD_ExiChannel].data[12] & 3) << 2 | (SD_CSD[CARD_ExiChannel].data[13] >> 6))) / - CARD_SectorSize[CARD_ExiChannel]; + sp8 = ((SD_CSD[CARD_ExiChannel].data[8] & 0xC0) >> 6) + (SD_CSD[CARD_ExiChannel].data[7] << 2) + + ((SD_CSD[CARD_ExiChannel].data[6] & 3) << 10) + 1; + sp8 *= 4 << (((SD_CSD[CARD_ExiChannel].data[9] & 3) << 1) | ((SD_CSD[CARD_ExiChannel].data[10] & 0x80) >> 7)); + sp8 <<= ((SD_CSD[CARD_ExiChannel].data[12] & 3) << 2) | ((SD_CSD[CARD_ExiChannel].data[13] & 0xC0) >> 6); + sp8 /= CARD_SectorSize[CARD_ExiChannel]; + !tran; + CARD_Size[CARD_ExiChannel] += sp8; + !tran; return CARD_ErrStatus[CARD_ExiChannel]; } @@ -248,7 +258,7 @@ u16 CARD_WriteD(u8* param1, u32 param2, int param3, int param4, UnknownStruct1* if (!CARD_Command(WRITE_MULTIPLE_BLOCK, param3 * CARD_SectorSize[CARD_ExiChannel]) && !CARD_Response1()) { for (i = 0; i < param2; i++) { - if (EXI_MultiDataWrite(pData, CARD_SectorSize[CARD_ExiChannel]) || CARD_DataResponse()) { + if (EXI_MultiDataWrite(pData, CARD_SectorSize[CARD_ExiChannel])) { break; } @@ -387,52 +397,39 @@ u16 CARD_StopResponse() { return CARD_ErrStatus[CARD_ExiChannel]; } -u16 CARD_DataResponse() { - EXI_DataRes(SD_RES[CARD_ExiChannel].data); - - if (((CARD_GetResponse0() >> 1) & 7) == 5) { - CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_0002; - } - - if (((CARD_GetResponse0() >> 1) & 7) == 6) { - CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_0200; - } - - return CARD_ErrStatus[CARD_ExiChannel]; -} - u16 CARD_SoftReset() { u16 ret; - int tmp; + UnkARG iVar0; + UnkARG iVar1; UnkARG iVar2; - UnkARG iVar2_2; - int pad1; - int pad2; + UnkARG iVar3; CARD_ErrStatus[CARD_ExiChannel] = CARD_ERROR_0000; SD_ARG[CARD_ExiChannel].data_u32 = 0; - iVar2.arg = SD_ARG[CARD_ExiChannel]; - iVar2._00 = GO_IDLE_STATE; - SD_CMD[CARD_ExiChannel].data[0] = iVar2._00; - SD_CMD[CARD_ExiChannel].data[1] = iVar2.arg.data[0]; - SD_CMD[CARD_ExiChannel].data[2] = iVar2.arg.data[1]; - SD_CMD[CARD_ExiChannel].data[3] = iVar2.arg.data[2]; - SD_CMD[CARD_ExiChannel].data[4] = iVar2.arg.data[3]; + iVar1.arg = SD_ARG[CARD_ExiChannel]; + iVar1._00 = GO_IDLE_STATE; + SD_CMD[CARD_ExiChannel].data[0] = iVar1._00; + SD_CMD[CARD_ExiChannel].data[1] = iVar1.arg.data[0]; + SD_CMD[CARD_ExiChannel].data[2] = iVar1.arg.data[1]; + SD_CMD[CARD_ExiChannel].data[3] = iVar1.arg.data[2]; + SD_CMD[CARD_ExiChannel].data[4] = iVar1.arg.data[3]; EXI_CmdWrite0(SD_CMD[CARD_ExiChannel].data, 5); CARD_ErrStatus[CARD_ExiChannel]; + !ret; + !ret; CARD_ErrStatus[CARD_ExiChannel]; CARD_Response1(); CARD_ErrStatus[CARD_ExiChannel]; - iVar2_2.arg = iVar2.arg; - iVar2_2._00 = STOP_TRANSMISSION; - SD_CMD[CARD_ExiChannel].data[0] = iVar2_2._00; - SD_CMD[CARD_ExiChannel].data[1] = iVar2_2.arg.data[0]; - SD_CMD[CARD_ExiChannel].data[2] = iVar2_2.arg.data[1]; - SD_CMD[CARD_ExiChannel].data[3] = iVar2_2.arg.data[2]; - SD_CMD[CARD_ExiChannel].data[4] = iVar2_2.arg.data[3]; + iVar2.arg.data_u32 = 0; + iVar2._00 = STOP_TRANSMISSION; + SD_CMD[CARD_ExiChannel].data[0] = iVar2._00; + SD_CMD[CARD_ExiChannel].data[1] = iVar2.arg.data[0]; + SD_CMD[CARD_ExiChannel].data[2] = iVar2.arg.data[1]; + SD_CMD[CARD_ExiChannel].data[3] = iVar2.arg.data[2]; + SD_CMD[CARD_ExiChannel].data[4] = iVar2.arg.data[3]; EXI_CmdWrite(SD_CMD[CARD_ExiChannel].data, 5); @@ -443,27 +440,25 @@ u16 CARD_SoftReset() { CARD_ErrStatus[CARD_ExiChannel] = CARD_ERROR_0000; SD_ARG[CARD_ExiChannel].data_u32 = 0; - iVar2.arg = SD_ARG[CARD_ExiChannel]; - iVar2._00 = GO_IDLE_STATE; - SD_CMD[CARD_ExiChannel].data[0] = iVar2._00; - SD_CMD[CARD_ExiChannel].data[1] = iVar2.arg.data[0]; - SD_CMD[CARD_ExiChannel].data[2] = iVar2.arg.data[1]; - SD_CMD[CARD_ExiChannel].data[3] = iVar2.arg.data[2]; - SD_CMD[CARD_ExiChannel].data[4] = iVar2.arg.data[3]; + iVar3.arg = SD_ARG[CARD_ExiChannel]; + iVar3._00 = GO_IDLE_STATE; + SD_CMD[CARD_ExiChannel].data[0] = iVar3._00; + SD_CMD[CARD_ExiChannel].data[1] = iVar3.arg.data[0]; + SD_CMD[CARD_ExiChannel].data[2] = iVar3.arg.data[1]; + SD_CMD[CARD_ExiChannel].data[3] = iVar3.arg.data[2]; + SD_CMD[CARD_ExiChannel].data[4] = iVar3.arg.data[3]; EXI_CmdWrite(SD_CMD[CARD_ExiChannel].data, 5); if (CARD_ErrStatus[CARD_ExiChannel] != 0) { - // ? - CARD_ErrStatus[CARD_ExiChannel]; - } else { - // ? - CARD_ErrStatus[CARD_ExiChannel]; - CARD_Response1(); + return CARD_ErrStatus[CARD_ExiChannel]; } - // ? CARD_ErrStatus[CARD_ExiChannel]; + !ret; + CARD_Response1(); + !ret; + CARD_ErrStatus[CARD_ExiChannel]; ret = CARD_ErrStatus[CARD_ExiChannel]; return ret; } @@ -482,62 +477,71 @@ u16 CARD_AppCommand() { } CARD_Response1(); - ret = CARD_ErrStatus[CARD_ExiChannel]; return ret; } -inline u16 CARD_SendOpCond_UnknownInline1() { - u16 ret; +static inline u16 CARD_AppCommandI() { + UnkARG iVar2; - if (CARD_ErrStatus[CARD_ExiChannel] != 0) { - ret = CARD_ErrStatus[CARD_ExiChannel]; - } else { - // CARD_Response1(); - ret = CARD_ErrStatus[CARD_ExiChannel]; + SD_ARG[CARD_ExiChannel].data_u32 = 0; + iVar2.arg = SD_ARG[CARD_ExiChannel]; + iVar2._00 = APP_CMD; + + if (CARD_Command2(&iVar2)) { + return CARD_ErrStatus[CARD_ExiChannel]; } - return ret; + CARD_Response1(); + return CARD_ErrStatus[CARD_ExiChannel]; } u16 CARD_SendOpCond() { - UnkARG iVar2; u16 ret; + UnkARG iVar1; + UnkARG iVar2; OSTick tick; tick = OSGetTick(); do { - CARD_AppCommand(); - CARD_SendOpCond_UnknownInline1(); + CARD_AppCommandI(); + if (CARD_ErrStatus[CARD_ExiChannel] != 0) { + return CARD_ErrStatus[CARD_ExiChannel]; + } + CARD_ErrStatus[CARD_ExiChannel]; SD_ARG[CARD_ExiChannel].data_u32 = 0; - iVar2.arg = SD_ARG[CARD_ExiChannel]; - iVar2._00 = CMD_69; - if (CARD_Command2(&iVar2)) { - ret = CARD_ErrStatus[CARD_ExiChannel]; - return ret; + iVar1.arg = SD_ARG[CARD_ExiChannel]; + iVar1._00 = CMD_69; + if (CARD_Command2(&iVar1)) { + return CARD_ErrStatus[CARD_ExiChannel]; } CARD_Response1(); + ret = SD_RES[CARD_ExiChannel].data[0]; + !tick; if (CARD_ErrStatus[CARD_ExiChannel] != 0 || !(SD_RES[CARD_ExiChannel].data[0] & 1)) { goto end; } } while (EXI_CheckTimeOut(tick, 1500) == 0); - CARD_AppCommand(); - CARD_SendOpCond_UnknownInline1(); + CARD_AppCommandI(); + if (CARD_ErrStatus[CARD_ExiChannel] != 0) { + return CARD_ErrStatus[CARD_ExiChannel]; + } + CARD_ErrStatus[CARD_ExiChannel]; SD_ARG[CARD_ExiChannel].data_u32 = 0; iVar2.arg = SD_ARG[CARD_ExiChannel]; - iVar2._00 = SEND_CSD; + iVar2._00 = CMD_69; if (CARD_Command2(&iVar2)) { - ret = CARD_ErrStatus[CARD_ExiChannel]; - return ret; + return CARD_ErrStatus[CARD_ExiChannel]; } CARD_Response1(); + ret = SD_RES[CARD_ExiChannel].data[0]; if (CARD_ErrStatus[CARD_ExiChannel] == 0 && (SD_RES[CARD_ExiChannel].data[0] & 1)) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_8000; @@ -615,6 +619,23 @@ u16 CARD_SetBlockLength(int param_1) { return ret; } +u16 CARD_SecureGetinfo(SDInfos* param1) { + u8* ptr; + int i; + + CARD_SD_Status(); + + if (CARD_ErrStatus[CARD_ExiChannel] == 0) { + ptr = param1->data; + + for (i = 0; i < ARRAY_COUNT(SD_SDSTATUS[CARD_ExiChannel].data); i++) { + *ptr++ = SD_SDSTATUS[CARD_ExiChannel].data[i]; + } + } + + return CARD_ErrStatus[CARD_ExiChannel]; +} + u16 CARD_Term() { u16 uVar2; diff --git a/src/static/JSystem/JUtility/exidrv.c b/src/static/JSystem/JUtility/exidrv.c index 5698fe18..fbbbad1d 100644 --- a/src/static/JSystem/JUtility/exidrv.c +++ b/src/static/JSystem/JUtility/exidrv.c @@ -49,27 +49,38 @@ u8 EXI_ClrData[CARD_NUM_CHANS]; } static inline u16 EXI_LockAndSelect(u32 nFreq) { - (void)nFreq; - EXI_Lock(); EXI_Select(nFreq); return 0; } -static inline u16 EXI_DeselectAndUnlock() { - if (EXIDeselect(CARD_ExiChannel) == 0) { - CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00E0; - } - - if (EXIUnlock(CARD_ExiChannel) == 0) { - CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00D0; - CARD_ErrStatus[CARD_ExiChannel]; +#define EXI_Deselect_Unlock() \ + { \ + if (EXIDeselect(CARD_ExiChannel) == 0) { \ + CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00E0; \ + } \ + \ + if (EXIUnlock(CARD_ExiChannel) == 0) { \ + CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00D0; \ + CARD_ErrStatus[CARD_ExiChannel]; \ + } \ } +static inline u16 EXI_DeselectAndUnlock() { + EXI_Deselect_Unlock(); return CARD_ErrStatus[CARD_ExiChannel]; } +#define EXI_DataResReturn(locked) \ + { \ + if ((locked) == 0) { \ + EXI_Deselect_Unlock(); \ + } \ + \ + return CARD_ErrStatus[CARD_ExiChannel]; \ + } + static inline void EXI_UnknownInline3(u8* pRES, OSTick tick, int time) { while (((pRES[0] & 0x80) != 0)) { pRES[0] = EXI_ClrData[CARD_ExiChannel]; @@ -152,7 +163,7 @@ void EXI_AlarmFunc(OSAlarm* alarm, OSContext* context) { u16 EXI_ResRead(u8* arg0, u16 arg1) { u8* sp8; u16 spE; - u16 bruh = arg1; + u16 bruh = 0; OSTick tick; if (EXI_LockAndSelect(CARD_ExiFreq[CARD_ExiChannel])) { @@ -161,7 +172,6 @@ u16 EXI_ResRead(u8* arg0, u16 arg1) { spE = 0; sp8 = arg0; - (void)sp8; (void)bruh; (void)bruh; (void)bruh; @@ -174,7 +184,6 @@ u16 EXI_ResRead(u8* arg0, u16 arg1) { } tick = OSGetTick(); - (void)tick; EXI_UnknownInline3(sp8, tick, 500); if (arg1 > sizeof(u8)) { @@ -191,7 +200,7 @@ u16 EXI_ResRead(u8* arg0, u16 arg1) { u16 EXI_StopResRead(u8* arg0, u16 arg1) { u8* sp8; s16 spE; - u16 bruh = arg1; + u16 bruh = 0; OSTick tick; if (EXI_LockAndSelect(CARD_ExiFreq[CARD_ExiChannel])) { @@ -200,7 +209,6 @@ u16 EXI_StopResRead(u8* arg0, u16 arg1) { spE = 0; sp8 = arg0; - (void)sp8; (void)bruh; (void)bruh; (void)bruh; @@ -234,18 +242,19 @@ u16 EXI_StopResRead(u8* arg0, u16 arg1) { return EXI_DeselectAndUnlock(); } -u16 EXI_DataRes(u8* arg0) { +u16 EXI_DataRes(u8* arg0, u16 arg1) { u8* sp8; - OSTick tick; int pad2; + OSTick tick; s16 spE; - if (EXI_LockAndSelect(CARD_ExiFreq[CARD_ExiChannel])) { - return CARD_ErrStatus[CARD_ExiChannel]; + if (arg1 == 0) { + if (EXI_LockAndSelect(CARD_ExiFreq[CARD_ExiChannel])) { + return CARD_ErrStatus[CARD_ExiChannel]; + } } spE = 0; - pad2 = 0; (void)pad2; (void)pad2; (void)pad2; @@ -253,25 +262,22 @@ u16 EXI_DataRes(u8* arg0) { (void)pad2; (void)pad2; (void)pad2; - (void)pad2; - (void)sp8; sp8 = arg0; sp8[0] = EXI_ClrData[CARD_ExiChannel]; if (EXIImmEx(CARD_ExiChannel, sp8, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; - return EXI_DeselectAndUnlock(); + EXI_DataResReturn(arg1); } tick = OSGetTick(); - (void)tick; - (void)tick; + pad2 = EXI_ClrData[CARD_ExiChannel]; while (sp8[0] & 0x10) { sp8[0] = EXI_ClrData[CARD_ExiChannel]; if (EXIImmEx(CARD_ExiChannel, sp8, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; - return EXI_DeselectAndUnlock(); + EXI_DataResReturn(arg1); } if (sp8[0] & 0x10) { @@ -283,7 +289,7 @@ u16 EXI_DataRes(u8* arg0) { if (EXIImmEx(CARD_ExiChannel, sp8, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; - return EXI_DeselectAndUnlock(); + EXI_DataResReturn(arg1); } if (sp8[0] & 0x10) { @@ -297,19 +303,17 @@ u16 EXI_DataRes(u8* arg0) { *++sp8 = EXI_ClrData[CARD_ExiChannel]; if (EXIImmEx(CARD_ExiChannel, sp8, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; - return EXI_DeselectAndUnlock(); + EXI_DataResReturn(arg1); } tick = OSGetTick(); - (void)tick; - (void)tick; while (sp8[0] == 0) { sp8[0] = EXI_ClrData[CARD_ExiChannel]; if (EXIImmEx(CARD_ExiChannel, sp8, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; - return EXI_DeselectAndUnlock(); + EXI_DataResReturn(arg1); } if (sp8[0] == 0) { @@ -321,7 +325,7 @@ u16 EXI_DataRes(u8* arg0) { if (EXIImmEx(CARD_ExiChannel, sp8, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; - return EXI_DeselectAndUnlock(); + EXI_DataResReturn(arg1); } if (sp8[0] == 0) { @@ -332,7 +336,7 @@ u16 EXI_DataRes(u8* arg0) { break; } - return EXI_DeselectAndUnlock(); + EXI_DataResReturn(arg1); } u16 EXI_MultiWriteStop(void) { @@ -387,7 +391,6 @@ u16 EXI_MultiWriteStop(void) { (void)tick2; (void)tick2; (void)tick2; - (void)tick2; tick = OSGetTick(); !tick; @@ -426,9 +429,14 @@ u16 EXI_DataRead(u8* arg0, u16 arg1) { OSTick temp_r25; int var_r28; u8* var_r31; - u16 sp12[CARD_NUM_CHANS]; + volatile u16 crc2; + volatile u16 crc; u8 sp10[CARD_NUM_CHANS]; + int pad; + (void)pad; + (void)pad; + (void)pad; if (EXI_LockAndSelect(CARD_ExiFreq[CARD_ExiChannel])) { return CARD_ErrStatus[CARD_ExiChannel]; } @@ -438,35 +446,37 @@ u16 EXI_DataRead(u8* arg0, u16 arg1) { *var_r31++ = EXI_ClrData[CARD_ExiChannel]; } - sp12[0] = sp12[1] = 0; + crc2 = crc = 0; - if (EXIImmEx(CARD_ExiChannel, arg0, sizeof(u8), 2) == 0) { + var_r31 = arg0; + if (EXIImmEx(CARD_ExiChannel, var_r31, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } temp_r25 = OSGetTick(); - while (arg0[0] != 0xFE) { - arg0[0] = EXI_ClrData[CARD_ExiChannel]; + pad = EXI_ClrData[CARD_ExiChannel]; + while (var_r31[0] != 0xFE) { + var_r31[0] = EXI_ClrData[CARD_ExiChannel]; - if (EXIImmEx(CARD_ExiChannel, arg0, sizeof(u8), 2) == 0) { + if (EXIImmEx(CARD_ExiChannel, var_r31, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } - if (arg0[0] != 0xFE) { + if (var_r31[0] != 0xFE) { if (EXI_CheckTimeOut(temp_r25, 1500) == 0) { continue; } - arg0[0] = EXI_ClrData[CARD_ExiChannel]; + var_r31[0] = EXI_ClrData[CARD_ExiChannel]; - if (EXIImmEx(CARD_ExiChannel, arg0, sizeof(u8), 2) == 0) { + if (EXIImmEx(CARD_ExiChannel, var_r31, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } - if (arg0[0] != 0xFE) { + if (var_r31[0] != 0xFE) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_4000; } } @@ -474,8 +484,8 @@ u16 EXI_DataRead(u8* arg0, u16 arg1) { break; } - arg0[0] = EXI_ClrData[CARD_ExiChannel]; - if (EXIImmEx(CARD_ExiChannel, arg0, arg1, 2) == 0) { + var_r31[0] = EXI_ClrData[CARD_ExiChannel]; + if (EXIImmEx(CARD_ExiChannel, var_r31, arg1, 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } @@ -491,8 +501,8 @@ u16 EXI_DataRead(u8* arg0, u16 arg1) { return EXI_DeselectAndUnlock(); } - sp12[0] = (sp10[0] << 8) & 0xFF00; - sp12[0] += sp10[1]; + crc = (u16)sp10[0] << 8; + crc += sp10[1]; if (EXIDeselect(CARD_ExiChannel) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00E0; @@ -503,7 +513,7 @@ u16 EXI_DataRead(u8* arg0, u16 arg1) { CARD_ErrStatus[CARD_ExiChannel]; } - if (sp12[0] != EXI_MakeCRC16(arg0, arg1)) { + if (crc != EXI_MakeCRC16(arg0, arg1)) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_0002; } @@ -511,56 +521,68 @@ u16 EXI_DataRead(u8* arg0, u16 arg1) { } u16 EXI_DataReadFinal(u8* arg0, u16 arg1) { - int var_r28; - u8* sp8; + int i; u8* var_r31; OSTick tick; - u16 sp12[CARD_NUM_CHANS]; + int pad1; + volatile u16 crc2; + volatile u16 crc; u8 sp10[CARD_NUM_CHANS]; - u8 crc[6]; - int i; + int pad2; + int pad3; + u8 cmd[6]; + u8 crc7; + int pad; + + (void)pad; + (void)pad; + (void)pad; + (void)pad; + (void)pad; + (void)pad; + (void)pad; + (void)pad; if (EXI_LockAndSelect(CARD_ExiFreq[CARD_ExiChannel])) { return CARD_ErrStatus[CARD_ExiChannel]; } var_r31 = arg0; - for (var_r28 = 0; var_r28 < arg1; var_r28++) { + for (i = 0; i < arg1; i++) { *var_r31++ = EXI_ClrData[CARD_ExiChannel]; } - sp12[0] = sp12[1] = 0; + crc2 = crc = 0; - arg0 = (u8*)var_r31; - if (EXIImmEx(CARD_ExiChannel, arg0, sizeof(u8), 2) == 0) { + var_r31 = arg0; + if (EXIImmEx(CARD_ExiChannel, var_r31, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } tick = OSGetTick(); - (void)tick; - (void)tick; - while (arg0[0] != 0xFE) { - arg0[0] = EXI_ClrData[CARD_ExiChannel]; + pad = EXI_ClrData[CARD_ExiChannel]; + while (var_r31[0] != 0xFE) { + var_r31[0] = EXI_ClrData[CARD_ExiChannel]; - if (EXIImmEx(CARD_ExiChannel, arg0, sizeof(u8), 2) == 0) { + if (EXIImmEx(CARD_ExiChannel, var_r31, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } - if (arg0[0] != 0xFE) { + if (var_r31[0] != 0xFE) { if (EXI_CheckTimeOut(tick, 1500) == 0) { continue; } - arg0[0] = EXI_ClrData[CARD_ExiChannel]; + var_r31[0] = EXI_ClrData[CARD_ExiChannel]; - if (EXIImmEx(CARD_ExiChannel, arg0, sizeof(u8), 2) == 0) { + if (EXIImmEx(CARD_ExiChannel, var_r31, sizeof(u8), 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } - if (arg0[0] != 0xFE) { + if (var_r31[0] != 0xFE) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_4000; } } @@ -568,43 +590,45 @@ u16 EXI_DataReadFinal(u8* arg0, u16 arg1) { break; } - arg0[0] = EXI_ClrData[CARD_ExiChannel]; - if (EXIImmEx(CARD_ExiChannel, arg0, arg1 - 4, 2) == 0) { + var_r31[0] = EXI_ClrData[CARD_ExiChannel]; + if (EXIImmEx(CARD_ExiChannel, var_r31, arg1 - 4, 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } - crc[0] = 0x0C; - crc[1] = 0x00; - crc[2] = 0x00; - crc[3] = 0x00; - crc[4] = 0x00; - crc[0] |= 0x40; - crc[5] = EXI_MakeCRC7(crc, 5) | 1; + cmd[0] = 0x0C; + cmd[1] = 0x00; + cmd[2] = 0x00; + cmd[3] = 0x00; + cmd[4] = 0x00; + cmd[0] |= 0x40; + crc7 = EXI_MakeCRC7(cmd, 5); + crc7 |= 1; + cmd[5] = crc7; if (CARD_WP_Flag[CARD_ExiChannel] != 0) { for (i = 0; i < 6; i++) { - crc[i] = ~crc[i]; + cmd[i] = ~cmd[i]; } } - if (EXIImmEx(CARD_ExiChannel, &sp10, 6, 2) == 0) { + if (EXIImmEx(CARD_ExiChannel, cmd, 6, 2) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } - arg0[arg1 - 4] = crc[0]; - arg0[arg1 - 3] = crc[1]; - arg0[arg1 - 2] = crc[2]; - arg0[arg1 - 1] = crc[3]; - sp10[0] = crc[4]; - sp10[1] = crc[5]; + var_r31[arg1 - 4] = cmd[0]; + var_r31[arg1 - 3] = cmd[1]; + var_r31[arg1 - 2] = cmd[2]; + var_r31[arg1 - 1] = cmd[3]; + sp10[0] = cmd[4]; + sp10[1] = cmd[5]; OSSetAlarm(&CARD_Alarm[CARD_ExiChannel], OSMicrosecondsToTicks(1), EXI_AlarmFunc); OSWaitSemaphore(&CARD_Sem[CARD_ExiChannel]); - sp12[0] = (sp10[0] << 8) & 0xFF00; - sp12[0] += sp10[1]; + crc = (u16)sp10[0] << 8; + crc += sp10[1]; if (EXIDeselect(CARD_ExiChannel) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00E0; @@ -615,7 +639,7 @@ u16 EXI_DataReadFinal(u8* arg0, u16 arg1) { CARD_ErrStatus[CARD_ExiChannel]; } - if (sp12[0] != EXI_MakeCRC16(arg0, arg1)) { + if (crc != EXI_MakeCRC16(arg0, arg1)) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_0002; } @@ -643,7 +667,6 @@ u16 EXI_CmdWrite0(u8* arg0, u16 arg1) { (void)pad0; (void)pad0; (void)arg1; - (void)arg1; EXI_ClrData[CARD_ExiChannel] = 0xFF; var_r29 = arg0; @@ -666,7 +689,6 @@ u16 EXI_CmdWrite0(u8* arg0, u16 arg1) { var_r29 = arg0; for (var_r30 = 0; var_r30 < (s32)sizeof(SD_DUMMY); var_r30++) { - !var_r29; SD_DUMMY[var_r30] = EXI_ClrData[CARD_ExiChannel]; } @@ -710,10 +732,7 @@ u16 EXI_CmdWrite(u8* arg0, u16 arg1) { u8 sp18; u8 sp10[0x20]; - pad0 = 0; - (void)pad0; - (void)pad0; - (void)pad0; + pad0 = CARD_ExiChannel + 1; (void)pad0; (void)pad0; (void)pad0; @@ -722,14 +741,10 @@ u16 EXI_CmdWrite(u8* arg0, u16 arg1) { (void)pad0; (void)pad0; - // (void)arg0; - // (void)arg1; - // (void)arg1; - var_r29 = arg0; var_r29[0] |= 0x40; - sp18 = EXI_MakeCRC7(var_r29, arg1); + sp18 = EXI_MakeCRC7(arg0, arg1); if (CARD_WP_Flag[CARD_ExiChannel] != 0) { for (var_r30 = 0; var_r30 < arg1; var_r30++) { *var_r29++ = ~(*var_r29); @@ -748,7 +763,7 @@ u16 EXI_CmdWrite(u8* arg0, u16 arg1) { return CARD_ErrStatus[CARD_ExiChannel]; } - !var_r29; + pad0 = EXI_ClrData[CARD_ExiChannel]; for (var_r30 = 0; var_r30 < 0x20; var_r30++) { sp10[var_r30] = EXI_ClrData[CARD_ExiChannel]; @@ -759,10 +774,7 @@ u16 EXI_CmdWrite(u8* arg0, u16 arg1) { return EXI_DeselectAndUnlock(); } - (void)arg0; - (void)arg0; - - if (EXIImmEx(CARD_ExiChannel, arg0, arg1, 1) == 0) { + if (EXIImmEx(CARD_ExiChannel, var_r29, arg1, 1) == 0) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; return EXI_DeselectAndUnlock(); } @@ -781,14 +793,11 @@ u16 EXI_CmdWrite(u8* arg0, u16 arg1) { u16 EXI_MultiDataWrite(u8* arg0, u16 arg1) { int pad0; - int pad1; int i; u8* volatile sp30; u8 sp8[32]; u16 crc; - (void)pad0; - (void)pad0; (void)pad0; (void)pad0; @@ -796,12 +805,27 @@ u16 EXI_MultiDataWrite(u8* arg0, u16 arg1) { sp8[i] = EXI_ClrData[CARD_ExiChannel]; } + (void)pad0; + (void)pad0; crc = EXI_MakeCRC16(arg0, arg1); if (EXI_LockAndSelect(CARD_ExiFreq[CARD_ExiChannel])) { return CARD_ErrStatus[CARD_ExiChannel]; } + if (EXIImmEx(CARD_ExiChannel, sp8, 8, 1) == 0) { + CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; + return EXI_DeselectAndUnlock(); + } + + (void)pad0; + (void)pad0; + for (i = 0; i < 0x20; i++) { + sp8[i] = EXI_ClrData[CARD_ExiChannel]; + } + + (void)pad0; + (void)pad0; sp30 = arg0; sp8[0] = 0xFC; if (EXIImmEx(CARD_ExiChannel, sp8, sizeof(u8), 1) == 0) { @@ -814,9 +838,6 @@ u16 EXI_MultiDataWrite(u8* arg0, u16 arg1) { return EXI_DeselectAndUnlock(); } - OSSetAlarm(&CARD_Alarm[CARD_ExiChannel], OSMicrosecondsToTicks(1), EXI_AlarmFunc); - OSWaitSemaphore(&CARD_Sem[CARD_ExiChannel]); - sp8[0] = crc >> 8; sp8[1] = crc; @@ -824,6 +845,19 @@ u16 EXI_MultiDataWrite(u8* arg0, u16 arg1) { CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_00F0; } + EXI_DataRes(SD_RES[CARD_ExiChannel].data, 1); + + if (((SD_RES[CARD_ExiChannel].data[0] & 0x0E) >> 1) == 5) { + CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_0002; + } + + if (((SD_RES[CARD_ExiChannel].data[0] & 0x0E) >> 1) == 6) { + CARD_ErrStatus[CARD_ExiChannel] |= CARD_ERROR_0200; + } + + OSSetAlarm(&CARD_Alarm[CARD_ExiChannel], OSMicrosecondsToTicks(1), EXI_AlarmFunc); + OSWaitSemaphore(&CARD_Sem[CARD_ExiChannel]); + return EXI_DeselectAndUnlock(); } diff --git a/src/static/JSystem/JUtility/fs_form.c b/src/static/JSystem/JUtility/fs_form.c index cbdee64c..972ecac7 100644 --- a/src/static/JSystem/JUtility/fs_form.c +++ b/src/static/JSystem/JUtility/fs_form.c @@ -421,29 +421,6 @@ u16 FS_calc_parameter(u32* param1, u16 param2) { return 0xA01E; } -inline void test(DrvCtl* temp_r31, u32 arg1, u16 index) { - -} - -u32 GET_FS_LCS() { return FS_LCS; }; -u16 GET_FS_TRACK_PER_SECTOR() { return FS_TRACK_PER_SECTOR; }; -u16 GET_FS_HEAD_NUM() { return FS_HEAD_NUM; }; -u32 GET_FS_gl_partition_size() { return FS_gl_partition_size; }; -u16 GET_FS_gl_card_size() { return FS_gl_card_size; }; -u16 GET_FS_format_fat_mode() { return FS_format_fat_mode; }; -u16 GET_FS_gl_bu() { return FS_gl_bu; }; -u8 GET_FS_FAT_MODE() { return FS_FAT_MODE; }; -u16 GET_FS_FAT_SC() { return FS_FAT_SC; }; -u32 GET_FS_FAT_MAX() { return FS_FAT_MAX; }; -u16 GET_FS_FAT_SF() { return FS_FAT_SF; }; -u16 GET_FS_FAT_SSA() { return FS_FAT_SSA; }; -u16 GET_FS_FAT_RSC() { return FS_FAT_RSC; }; -u16 GET_FS_FAT_MBR() { return FS_FAT_MBR; }; -u16 GET_FS_BUF_POS_FDC() { return FS_BUF_POS_FDC; }; -u16 GET_FS_BUF_POS_FAT1() { return FS_BUF_POS_FAT1; }; -u16 GET_FS_BUF_POS_FAT2() { return FS_BUF_POS_FAT2; }; -u16 GET_FS_BUF_POS_RDE() { return FS_BUF_POS_RDE; }; - u16 FS_init_pbs(char* arg0, u32 arg1, s32* arg2, u16 arg3, u16 arg4, u16 arg5) { DrvCtl* temp_r31; u16 index; @@ -476,7 +453,7 @@ u16 FS_init_pbs(char* arg0, u32 arg1, s32* arg2, u16 arg3, u16 arg4, u16 arg5) { temp_r31->unk_20BA4[OFFSET_BPB_BYTES_PER_SEC_INDEX_0 + index] = 0; temp_r31->unk_20BA4[OFFSET_BPB_BYTES_PER_SEC_INDEX_1 + index] = 2; - temp_r31->unk_20BA4[OFFSET_BPB_SEC_PER_CLUS + index] = FS_LCS / sizeof(FSPartitionBootSector); + temp_r31->unk_20BA4[OFFSET_BPB_SEC_PER_CLUS + index] = (FS_LCS >> 9) & 0xFF; temp_r31->unk_20BA4[OFFSET_BPB_RSVD_SEC_CNT_INDEX_0 + index] = FS_FAT_RSC; temp_r31->unk_20BA4[OFFSET_BPB_RSVD_SEC_CNT_INDEX_1 + index] = (FS_FAT_RSC >> 8); @@ -529,13 +506,21 @@ u16 FS_init_pbs(char* arg0, u32 arg1, s32* arg2, u16 arg3, u16 arg4, u16 arg5) { status = FS_rand(0xFF, arg5) * 256; // tmp = FS_rand(0xFF, arg5); +#if VERSION == VER_GAEJ01_00 status *= (temp_r29 = FS_rand(0xFF, arg5)); +#else + status += (temp_r29 = FS_rand(0xFF, arg5)); +#endif temp_r31->unk_20BA4[OFFSET_BS_VOL_ID_INDEX_0 + index] = status; temp_r31->unk_20BA4[OFFSET_BS_VOL_ID_INDEX_1 + index] = EXTRACT_BITS(status, 8, 8); status = FS_rand(0xFF, arg5) * 256; // tmp = FS_rand(0xFF, arg5); +#if VERSION == VER_GAEJ01_00 status *= (temp_r29 = FS_rand(0xFF, arg5)); +#else + status += (temp_r29 = FS_rand(0xFF, arg5)); +#endif temp_r31->unk_20BA4[OFFSET_BS_VOL_ID_INDEX_2 + index] = status; // temp_r31->unk_20BA4[OFFSET_BS_VOL_ID_INDEX_3 + index] = EXTRACT_BITS(status, 8, 8); temp_r31->unk_20BA4[OFFSET_BS_VOL_ID_INDEX_3 + index] = (status >> 8) & 0xFF; diff --git a/src/static/JSystem/JUtility/fs_rddr.c b/src/static/JSystem/JUtility/fs_rddr.c index a7bb8f12..92fcb480 100644 --- a/src/static/JSystem/JUtility/fs_rddr.c +++ b/src/static/JSystem/JUtility/fs_rddr.c @@ -151,7 +151,11 @@ u16 FS_Readdir_sub(SDDirInfo* pDirInfo, UnknownStruct3* param2) { temp_r30 = LOAD_LE_u16(var_r31->DIR_WrtTime.data_u16); param2->unk_4C = ((temp_r30 >> 11) & 0x1F); param2->unk_4E = ((temp_r30 >> 5) & 0x3F); +#if VERSION == VER_GAEJ01_01 + param2->unk_50 = ((temp_r30 & 0x1F) << 1); +#else param2->unk_50 = ((temp_r30 << 1) & 0x3E); +#endif sp28 += 0x20; sp30++; diff --git a/src/static/JSystem/JUtility/fs_subd.c b/src/static/JSystem/JUtility/fs_subd.c index 38c3dc92..146067de 100644 --- a/src/static/JSystem/JUtility/fs_subd.c +++ b/src/static/JSystem/JUtility/fs_subd.c @@ -1961,7 +1961,11 @@ u16 FS_write_sub(u8* param1, u32 param2, u32 param3, UnknownStruct1* param4, u16 } u16 FS_csd_to_size(u32 *outSectorsPerCluster, s32 *outCsdBlockMultiplier, u16 modeFlags, u16 arg3, u16 chan) { +#if VERSION == VER_GAEJ01_00 s32 blockMultiplier; +#else + u32 max; +#endif u32 i; DrvCtl* pDrvCtl; SDInfos rawCsdInfo; @@ -1971,18 +1975,28 @@ u16 FS_csd_to_size(u32 *outSectorsPerCluster, s32 *outCsdBlockMultiplier, u16 mo u32 read_bl_len; u32 c_size; u32 c_size_mult; +#if VERSION == VER_GAEJ01_00 u32 max; +#else + s32 blockMultiplier; +#endif u32 size; s32 t0; pDrvCtl = &FS_drv_ctl[chan]; sp16 = arg3; +#if VERSION == VER_GAEJ01_01 + status = 0; + (void)status; +#endif +#if VERSION == VER_GAEJ01_00 // these are probably used somewhere in assert calls or something (void)read_bl_len; (void)c_size; (void)c_size_mult; (void)t0; +#endif if (modeFlags & FS_SD_CARD_MODE_RAW) { *outSectorsPerCluster = 0xF28 * 0x20; // 0x1E500 @@ -1992,7 +2006,11 @@ u16 FS_csd_to_size(u32 *outSectorsPerCluster, s32 *outCsdBlockMultiplier, u16 mo *outCsdBlockMultiplier = 0x20; } +#if VERSION == VER_GAEJ01_00 status = FS_DrvSel_Getinfo(&rawCsdInfo, pDrvCtl->unk_00[1]); +#else + FS_DrvSel_Getinfo(&rawCsdInfo, pDrvCtl->unk_00[1]); +#endif // byte swap CSD register data I guess? i = 0; @@ -2002,10 +2020,19 @@ u16 FS_csd_to_size(u32 *outSectorsPerCluster, s32 *outCsdBlockMultiplier, u16 mo } read_bl_len = ((u16)(csdInfo.data[12] & 3) << 2) | ((u16)(csdInfo.data[13] & (3 << 6)) >> 6); +#if VERSION == VER_GAEJ01_00 c_size = ((u16)(csdInfo.data[6] & (3 << 0)) << 10) | ((u16)(csdInfo.data[7] << 2)) | ((u16)(csdInfo.data[8] & (3 << 6)) >> 6); +#else + c_size = ((csdInfo.data[6] & 3) << 10) | ((u16)(csdInfo.data[7] << 2)) | ((u16)(csdInfo.data[8] & (3 << 6)) >> 6); + status = 0; + (void)status; +#endif c_size_mult = ((u16)(csdInfo.data[9] & (3 << 0)) << 1) | ((u16)(csdInfo.data[10] & (1 << 7)) >> 7); // r23 size = 1 + (c_size & 0xFFFF); // these are actually the 'total blocks' until the later multiplication step - + +#if VERSION == VER_GAEJ01_01 + (void)size; +#endif max = c_size_mult & 0xFFFF; blockMultiplier = 2; i = 0; @@ -2055,16 +2082,14 @@ u16 FS_csd_to_size(u32 *outSectorsPerCluster, s32 *outCsdBlockMultiplier, u16 mo *outSectorsPerCluster = 0xA0 * 0x100; // 2GB card } #else - u16 status; - - status = FS_DrvSel_SecureGetInfo(&csdInfo, pDrvCtl->unk_00[1]); - if (status != 0) { + if ((u16)FS_DrvSel_SecureGetInfo(&rawCsdInfo, pDrvCtl->unk_00[1]) != 0) { *outSectorsPerCluster = 0; *outCsdBlockMultiplier = 0; return 0xA00E; } - *outSectorsPerCluster = blockMultiplier * (((csdInfo.pad_unk_20[32] & 0xFF) << 24) | ((csdInfo.pad_unk_20[33] & 0xFF) << 16) | ((csdInfo.pad_unk_20[34] & 0xFF) << 8) | (csdInfo.pad_unk_20[35] & 0xFF)); + *outSectorsPerCluster = blockMultiplier * (((rawCsdInfo.data[4] & 0xFF) << 24) | ((rawCsdInfo.data[5] & 0xFF) << 16) | + ((rawCsdInfo.data[6] & 0xFF) << 8) | (rawCsdInfo.data[7] & 0xFF)); #endif *outCsdBlockMultiplier = blockMultiplier; diff --git a/src/static/jsyswrap.cpp b/src/static/jsyswrap.cpp new file mode 100644 index 00000000..3364f1a2 --- /dev/null +++ b/src/static/jsyswrap.cpp @@ -0,0 +1,1018 @@ +#include "jsyswrap_cpp.h" + +#include "JSystem/JSystem.h" +#include "JSystem/JUtility/JUTGamePad.h" +#include "JSystem/JUtility/TColor.h" +#include "JSystem/JFramework/JFWSystem.h" +#include "libforest/emu64.h" +#include "_mem.h" +#include "m_lib.h" +#include "dolphin/os/OSArena.h" +#include "dolphin/private/__os.h" +#include "libc64/malloc.h" +#include "../src/static/jsyswrap_JKRAramStream.h" + +extern "C" { +u32 OSGetPhysicalMemSize(void); +u8 OSGetLanguage(void); +u32 OSGetEuRgb60Mode(void); + +u8* Get_free_buff_p_for_moduleI_or_moduleO(void); + +u8* JW_Get_AgbTargetClient_InAgbArchiveFile1234_data_p(void); +u8* JW_Get_AgbTargetChild_InAgbArchiveFile1234_data_p(void); +size_t JW_Get_AgbTargetClient_InAgbArchiveFile1234_size(void); +size_t JW_Get_AgbTargetChild_InAgbArchiveFile1234_size(void); +int JW_Get_request_type_AgbProg(void); +int JW_Get_loaded_type_AgbProg(void); +void JW_Load_AGB_archive_outdoor(u8* buf, u32 size); +void JW_Release_AGB_archive_outdoor(void); +u8* JW_Get_AgbTarget_Special_archive_p(void); +void JW_Load_AGB_archive_special(void); +void JW_Unload_AGB_archive_special(void); +void JW_Load_picture_copy_archive(void); +void JW_Unload_picture_copy_archive(void); +void* JW_Get_picture_copy_data_p(void); +u8* JW_Get_picture_copy_archive_p(void); +u8* JW_Get_SDCardBuffer_p(void); +} + +class JUTGamePadX : public JUTGamePad { + public: + static CStick* getPadSubStick(EPadPort port); +}; + +/* These bytes are probably generated by an unused function that got stripped... thanks mwcc */ +#ifdef MUST_MATCH +#pragma force_active on +u8 _jsyswrap_autogen_match[0x40]; +#pragma force_active reset +#endif + +JUTGamePad gamePad[4]; +void* jc_fader = nullptr; +void* forest_arc_aram_p = nullptr; +void* forest_arc_aram2_p = nullptr; +void* forest_arc_aram_msg_p = nullptr; +void* forest_arc_aram_script_p = nullptr; +void* gameheap_base; +void* jc_gport = nullptr; +void* jc_sysConsole = nullptr; +u8 video_progressive = 0; +u8 video_lowreso = 0; +u8 video_famicom = 0; +u8 video_logo = 0; +u8 video_pan_enable = 0; +u16 video_pan_xorg = 0; +u16 video_pan_yorg = 0; +u16 video_pan_width = 0; +u16 video_pan_height = 0; + +u32 SystemHeapSize = 0x16C7000; +u32 gameheap_len = 0x380000; + +void ReportDiskID() { + DVDDiskID* disk_id = DVDGetCurrentDiskID(); + + JC_JUTConsole_print_f(jc_sysConsole, "DiskID %.4s %.2s %d 0x%02x(%d)\n", disk_id->gameName, disk_id->company, + disk_id->diskNumber, disk_id->gameVersion, disk_id->gameVersion); +} + +GXRenderModeObj customized_GXNtsc240Ds = { VI_TVMODE_NTSC_DS, + 640, + 240, + 240, + 30, + 0, + 660, + 480, + VI_XFBMODE_SF, + FALSE, + FALSE, + { { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 } }, + { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj customized_GXNtsc240Prog = { VI_TVMODE_NTSC_PROG, + 640, + 240, + 480, + 30, + 0, + 660, + 480, + VI_XFBMODE_SF, + FALSE, + FALSE, + { { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 } }, + { 0, 0, 21, 22, 21, 0, 0 } }; +GXRenderModeObj customized_GXNtsc240IntDf = { VI_TVMODE_NTSC_INT, + 640, + 240, + 480, + 30, + 0, + 660, + 480, + VI_XFBMODE_DF, + FALSE, + FALSE, + { { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 } }, + { 8, 8, 10, 12, 10, 8, 8 } }; +GXRenderModeObj customized_GXNtsc480IntDf = { VI_TVMODE_NTSC_INT, + 640, + 480, + 480, + 30, + 0, + 660, + 480, + VI_XFBMODE_DF, + FALSE, + FALSE, + { { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 } }, + { 8, 8, 10, 12, 10, 8, 8 } }; +GXRenderModeObj customized_GXNtsc480Prog = { VI_TVMODE_NTSC_PROG, + 640, + 480, + 480, + 30, + 0, + 660, + 480, + VI_XFBMODE_SF, + FALSE, + FALSE, + { { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 }, + { 6, 6 } }, + { 0, 0, 21, 22, 21, 0, 0 } }; + +extern void JW_UpdateVideoMode() { + GXRenderModeObj* renderMode; + + if (video_famicom) { + video_pan_xorg = 32; + video_pan_yorg = 8; + video_pan_width = 256; + video_pan_height = 232; + + if (video_lowreso != FALSE && video_progressive == FALSE) { + renderMode = &customized_GXNtsc240Ds; + } else { + video_pan_yorg *= 2; + video_pan_height *= 2; + + if (video_progressive != FALSE) { + renderMode = &customized_GXNtsc240Prog; + } else { + renderMode = &customized_GXNtsc240IntDf; + } + } + } else { + video_pan_xorg = 20; + video_pan_yorg = 6; + video_pan_width = 598; + video_pan_height = 464; + + if (video_progressive) { + renderMode = &customized_GXNtsc480Prog; + } else { + renderMode = &customized_GXNtsc480IntDf; + } + } + + if (renderMode != NULL) { + VIWaitForRetrace(); + JC_JUTVideo_setRenderMode(JC_JUTVideo_getManager(), renderMode); + } + + if (video_pan_enable) { + VIConfigurePan(video_pan_xorg, video_pan_yorg, video_pan_width, video_pan_height); + } +} + +extern void JW_SetProgressiveMode(int enabled) { + if (video_progressive != enabled) { + video_progressive = enabled; + JW_UpdateVideoMode(); + } +} + +extern void JW_SetLowResoMode(int enabled) { + if (video_lowreso != enabled) { + video_lowreso = enabled; + JW_UpdateVideoMode(); + } +} + +extern void JW_SetFamicomMode(int enabled) { + if (video_famicom != enabled) { + video_famicom = enabled; + JW_UpdateVideoMode(); + } +} + +extern void JW_SetVideoPan(u16 origin_x, u16 origin_y, u16 width, u16 height) { + if (video_pan_xorg != origin_x || video_pan_yorg != origin_y || video_pan_width != width || + video_pan_height != height) { + video_pan_enable = TRUE; + video_pan_xorg = origin_x; + video_pan_yorg = origin_y; + video_pan_width = width; + video_pan_height = height; + } +} + +extern void JW_SetLogoMode(int enabled) { + if (video_logo != enabled) { + video_logo = enabled; + JW_UpdateVideoMode(); + } +} + +extern void JW_JUTGamePad_read() { + static OSTime last_pad_read; + OSTime now = OSGetTime(); + + if (now > last_pad_read + OSMillisecondsToTicks(16) || now < last_pad_read) { + last_pad_read = now; + JC_JUTGamePad_read(); + } +} + +extern void JW_getPadStatus(PADStatus* padStatus) { + memcpy(&padStatus[0], JUTGamePad::getPadStatus(JUTGamePad::Port1), sizeof(PADStatus)); + memcpy(&padStatus[1], JUTGamePad::getPadStatus(JUTGamePad::Port2), sizeof(PADStatus)); + memcpy(&padStatus[2], JUTGamePad::getPadStatus(JUTGamePad::Port3), sizeof(PADStatus)); + memcpy(&padStatus[3], JUTGamePad::getPadStatus(JUTGamePad::Port4), sizeof(PADStatus)); +} + +extern int JW_JUTGamepad_getErrorStatus() { + return JUTGamePad::getPortStatus(JUTGamePad::Port1); +} + +extern u32 JW_JUTGamepad_getButton() { + return JUTGamePad::getPadButton(JUTGamePad::Port1)->mButton; +} + +extern u32 JW_JUTGamepad_getTrigger() { + return JUTGamePad::getPadButton(JUTGamePad::Port1)->mTrigger; +} + +JUTGamePad::CStick* JUTGamePadX::getPadSubStick(EPadPort port) { + return &mPadSStick[port]; +} + +extern f32 JW_JUTGamepad_getSubStickValue() { + return JUTGamePadX::getPadSubStick(JUTGamePad::Port1)->mValue; +} + +extern s16 JW_JUTGamepad_getSubStickAngle() { + return JUTGamePadX::getPadSubStick(JUTGamePad::Port1)->mAngle; +} + +bool FrameDrawing = false; + +extern void JW_BeginFrame() { + while (FrameCansel) { + VIWaitForRetrace(); + } + + FrameDrawing = true; + void* displayManager = JC_JFWDisplay_getManager(); + JC_JFWDisplay_endFrame(displayManager); + JC_JFWDisplay_beginRender(displayManager); + JC_J2DOrthoGraph_setOrtho(jc_gport, 0, 0, JC_JFWDisplay_getEfbWidth(displayManager), + JC_JFWDisplay_getEfbHeight(displayManager)); + JC_J2DOrthoGraph_setPort(jc_gport); +} + +extern void JW_EndFrame() { + JC_JFWDisplay_endRender(JC_JFWDisplay_getManager()); + FrameDrawing = false; +} + +extern int JW_setClearColor(u8 r, u8 g, u8 b) { + static GXColor clear_color; + + if (clear_color.r != r || clear_color.g != g || clear_color.b != b) { + void* manager = JC_JFWDisplay_getManager(); + + clear_color.r = r; + clear_color.g = g; + clear_color.b = b; + + JC_JFWDisplay_setClearColor(manager, clear_color); + return TRUE; + } + + return FALSE; +} + +const char* aram_resName[] = { "fgdata.bin", + "pallet_boy.bin", + "tex_boy.bin", + "face_boy.bin", + "fgnpcdata.bin", + "my_original.bin", + "needlework.bin", + "player_room_floor.bin", + "player_room_wall.bin", + "npc_name_str_table.bin", + "d_obj_npc_stock_sch.bin", + "d_obj_npc_stock_scl.bin", + "title.bti", + "mura_spring.bti", + "mura_spring.bti", + "mura_spring.bti", + "mura_spring.bti", + "b_letter1.bti", + "b_design1.bti", + "odekake.bti", + "omake.bti", + "boy1.bti", + "boy2.bti", + "boy3.bti", + "boy4.bti", + "boy5.bti", + "boy6.bti", + "boy7.bti", + "boy8.bti", + "girl1.bti", + "girl2.bti", + "girl3.bti", + "girl4.bti", + "girl5.bti", + "girl6.bti", + "girl7.bti", + "girl8.bti", + "eki1.bti", + "eki1_2.bti", + "eki1_3.bti", + "eki1_4.bti", + "eki1_5.bti", + "eki2.bti", + "eki2_2.bti", + "eki2_3.bti", + "eki2_4.bti", + "eki2_5.bti", + "eki3.bti", + "eki3_2.bti", + "eki3_3.bti", + "eki3_4.bti", + "eki3_5.bti", + "present1.bti", + "present2.bti", + "nes.bti", + "letter1.bti", + "letter2.bti", + "letter3.bti", + "letter4.bti", + "letter5.bti", + "design1.bti", + "design2.bti", + "design3.bti", + "design4.bti", + "design5.bti", + "d_bg_island_sch.bin", + "eappli.bin", + "animal_param.bin", + "msg.bin", + "msg_color.bmc", + "mail.bin", + "maila.bin", + "mailb.bin", + "mailc.bin", + "ps.bin", + "psz.bin", + "select.bin", + "string.bin", + "superz.bin", + "super.bin" }; + +extern u32 JW_GetAramAddress(int res_no) { + u32 address = 0; + + if (res_no >= RESOURCE_FGDATA && res_no < RESOURCE_FGNPCDATA) { + address = JC_JKRAramArchive_getAramAddress_byName(forest_arc_aram_p, (u32)'DATA', aram_resName[res_no]); + } else if (res_no < RESOURCE_MESSAGE) { + address = JC_JKRAramArchive_getAramAddress_byName(forest_arc_aram2_p, (u32)'DATA', aram_resName[res_no]); + } else if (res_no < RESOURCE_MAIL) { + address = JC_JKRAramArchive_getAramAddress_byName(forest_arc_aram_msg_p, (u32)'DATA', aram_resName[res_no]); + } else if (res_no < RESOURCE_NUM) { + address = JC_JKRAramArchive_getAramAddress_byName(forest_arc_aram_script_p, (u32)'DATA', aram_resName[res_no]); + } + + return address; +} + +extern u8* _JW_GetResourceAram(u32 aram_addr, u8* dst, u32 size) { + return JKRAramToMainRam(aram_addr, dst, size, EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); +} + +extern u32 JW_GetResSizeFileNo(int res_no) { + u32 res_size = 0; + + if (res_no >= RESOURCE_FGDATA && res_no < RESOURCE_FGNPCDATA) { + CSDIFileEntry* entry = JC__JKRGetResourceEntry_byName((u32)'DATA', aram_resName[res_no], forest_arc_aram_p); + + if (entry != nullptr) { + res_size = entry->mSize; + } + } else if (res_no < RESOURCE_MESSAGE) { + CSDIFileEntry* entry = JC__JKRGetResourceEntry_byName((u32)'DATA', aram_resName[res_no], forest_arc_aram2_p); + + if (entry != nullptr) { + res_size = entry->mSize; + } + } else if (res_no < RESOURCE_MAIL) { + CSDIFileEntry* entry = + JC__JKRGetResourceEntry_byName((u32)'DATA', aram_resName[res_no], forest_arc_aram_msg_p); + + if (entry != nullptr) { + res_size = entry->mSize; + } + } else if (res_no < RESOURCE_NUM) { + CSDIFileEntry* entry = + JC__JKRGetResourceEntry_byName((u32)'DATA', aram_resName[res_no], forest_arc_aram_script_p); + + if (entry != nullptr) { + res_size = entry->mSize; + } + } + + return res_size; +} + +#define FIX_ARENA_LO 0x8029C000 +#define FIX_ARENA_HI 0x817FFBC0 + +u32 JW_soundAramSize = 0x820000; + +extern void JW_Init() { + void* arenaLo = OSGetArenaLo(); + void* arenaHi = OSGetArenaHi(); + + if ((u32)arenaLo <= FIX_ARENA_LO) { + OSSetArenaLo((void*)FIX_ARENA_LO); + } else { + OSReport("\x1b[43;30mWARNING: ArenaLo(%x) > %x\x1b[m\n", arenaLo, FIX_ARENA_LO); + } + + if ((u32)arenaHi != FIX_ARENA_HI && (u32)arenaHi < 0x81800000) { + OSReport("\x1b[43;30mWARNING: ArenaHi(%x) != %x\x1b[m\n", arenaHi, OSGetArenaHi); + } + + SystemHeapSize = (u32)OSGetArenaHi() - (u32)OSGetArenaLo() - 0xD0; + JC_JFWSystem_setMaxStdHeap(1); + JC_JFWSystem_setSysHeapSize(SystemHeapSize); + JC_JFWSystem_setFifoBufSize(0x10001); + + u32 soundAramSize = JW_soundAramSize; + u32 graphAramSize = 0x709960; + OSReport("soundAramSize=%08x graphAramSize=%08x totalAramSize=%08x\n", soundAramSize, graphAramSize, + soundAramSize + graphAramSize); + JC_JFWSystem_setAramAudioBufSize(soundAramSize); + JC_JFWSystem_setAramGraphBufSize(graphAramSize); + JFWSystem::setRenderMode(&customized_GXNtsc480IntDf); + JC_JFWSystem_init(); + JKRSetAramTransferBuffer((u8*)JKRAllocFromSysHeap(0x1000, 0), 0x1000, nullptr); + JC_JKRExpHeap_changeGroupID(JC_JFWSystem_getSystemHeap(), 1); + jc_sysConsole = JC_JFWSystem_getSystemConsole(); + JC_JUTConsole_setOutput(jc_sysConsole, 3); + JC_JUTConsole_setPosition(jc_sysConsole, 32, 42); + JC_JUTConsole_print(jc_sysConsole, "JC_JUTConsole START\n"); + JC_JUTConsole_print_f(jc_sysConsole, "Initial Arena = %x-%x\n", arenaLo, arenaHi); + JC_JUTConsole_print_f(jc_sysConsole, " Fix Arena = %x-%x\n", FIX_ARENA_LO, FIX_ARENA_HI); + JC_JUTConsole_print_f(jc_sysConsole, + "FontEnc %x Lang %x SoundMode %x\nProgMode %x ConsType %x\nSimMem %x PhyMem %x ResetCode %x\n", + OSGetFontEncode(), OSGetLanguage(), OSGetSoundMode(), OSGetProgressiveMode(), + OSGetConsoleType(), OSGetConsoleSimulatedMemSize(), OSGetPhysicalMemSize(), + OSGetResetCode()); + JC_JUTConsole_print_f(jc_sysConsole, "DTVStatus %x ProgressiveMode %x EuRGB60Mode %x\n", VIGetDTVStatus(), + OSGetProgressiveMode(), OSGetEuRgb60Mode()); + + OSTime time = OSGetTime() - __OSStartTime; + OSCalendarTime cal; + OSTicksToCalendarTime(time, &cal); + JC_JUTConsole_print_f(jc_sysConsole, "%04d-%02d-%02d %02d:%02d:%02d'%03d''%03d(%016llx)\n", cal.year, cal.mon, + cal.mday, cal.hour, cal.min, cal.sec, cal.msec, cal.usec, time); + + void* display_manager = JC_JFWDisplay_createManager_0(JC_JFWSystem_getSystemHeap(), 2, 1); + JC_JUTProcBar_setVisible(JC_JUTProcBar_getManager(), FALSE); + JC_JUTProcBar_setVisibleHeapBar(JC_JUTProcBar_getManager(), FALSE); + jc_gport = JC_J2DOrthoGraph_new(); + GXColor color = TCOLOR_BLACK; + jc_fader = JC_JUTFader_new(0, 0, (u16)JC_JUTVideo_getFbWidth(JC_JUTVideo_getManager()), + (u16)JC_JUTVideo_getEfbHeight(JC_JUTVideo_getManager()), (u32*)&color); + JC_JFWDisplay_setFader(display_manager, jc_fader); + JC_JFWDisplay_setClearColor(display_manager, TCOLOR_BLACK); + JC_JFWDisplay_setGamma(display_manager, 0); + JW_SetVideoPan(20, 6, 598, 464); + VIConfigurePan(20, 6, 598, 464); + JC_JKRExpHeap_changeGroupID(JC_JFWSystem_getSystemHeap(), 2); +} + +extern void JW_Init2() { + JC_JKRExpHeap_changeGroupID(JC_JFWSystem_getSystemHeap(), 3); + ReportDiskID(); + + if (forest_arc_aram_p == nullptr) { + forest_arc_aram_p = JC_JKRAramArchive_new(); + + if (forest_arc_aram_p == nullptr || + JC__JKRMountFixedAramArchive(forest_arc_aram_p, "forest_1st.arc") == FALSE) { + OSDVDFatalError(); + } + } + + if (forest_arc_aram_script_p == nullptr) { + forest_arc_aram_script_p = JC_JKRAramArchive_new(); + + if (forest_arc_aram_script_p == nullptr || + JC__JKRMountFixedAramArchive(forest_arc_aram_script_p, "forest_1st_script.arc") == FALSE) { + OSDVDFatalError(); + } + } + + gameheap_len = JC_JKRHeap_getFreeSize(JC_JFWSystem_getSystemHeap()) - 0x8000; + gameheap_base = JC_JKRHeap_alloc(JC_JFWSystem_getSystemHeap(), gameheap_len, 32); + MallocInit(gameheap_base, gameheap_len); + JC_JKRExpHeap_changeGroupID(JC_JFWSystem_getSystemHeap(), 4); +} + +extern void JW_Init3() { + if (forest_arc_aram2_p == nullptr) { + forest_arc_aram2_p = JC_JKRAramArchive_new(); + + if (forest_arc_aram2_p == nullptr || + JC__JKRMountFixedAramArchive(forest_arc_aram2_p, "forest_2nd.arc") == FALSE) { + OSDVDFatalError(); + } + } +} + +extern void JW_Init4() { + if (forest_arc_aram_msg_p == nullptr) { + forest_arc_aram_msg_p = JC_JKRAramArchive_new(); + + if (forest_arc_aram_msg_p == nullptr || + JC__JKRMountFixedAramArchive(forest_arc_aram_msg_p, "forest_msg.arc") == FALSE) { + OSDVDFatalError(); + } + } +} + +extern void JW_Cleanup() { + MallocCleanup(); + JC_JKRHeap_free(JC_JFWSystem_getSystemHeap(), gameheap_base); + gameheap_base = nullptr; + + if (forest_arc_aram_p != nullptr) { + JC__JKRUnmountFixedAramArchive(forest_arc_aram_p); + JC_JKRAramArchive_delete(forest_arc_aram_p); + forest_arc_aram_p = nullptr; + } + + if (forest_arc_aram2_p != nullptr) { + JC__JKRUnmountFixedAramArchive(forest_arc_aram2_p); + JC_JKRAramArchive_delete(forest_arc_aram2_p); + forest_arc_aram2_p = nullptr; + } + + if (forest_arc_aram_msg_p != nullptr) { + JC__JKRUnmountFixedAramArchive(forest_arc_aram_msg_p); + JC_JKRAramArchive_delete(forest_arc_aram_msg_p); + forest_arc_aram_msg_p = nullptr; + } + + if (forest_arc_aram_script_p != nullptr) { + JC__JKRUnmountFixedAramArchive(forest_arc_aram_script_p); + JC_JKRAramArchive_delete(forest_arc_aram_script_p); + forest_arc_aram_script_p = nullptr; + } + + JC_JFWDisplay_destroyManager(); + + if (jc_fader != nullptr) { + JC_JUTFader_delete(jc_fader); + jc_fader = nullptr; + } + + if (jc_gport != nullptr) { + JC_J2DOrthoGraph_delete(jc_gport); + jc_gport = nullptr; + } +} + +void* JW_AgbTargetNpcHead_InAgbArchiveFile0_data_p; +long JW_AgbTargetNpcHead_InAgbArchiveFile0_size; +void* JW_AgbTargetNpcBody_InAgbArchiveFile0_data_p; +long JW_AgbTargetNpcBody_InAgbArchiveFile0_size; +void* JW_AgbTargetNpcPal_InAgbArchiveFile0_data_p; +long JW_AgbTargetNpcPal_InAgbArchiveFile0_size; +void* JW_AgbTargetPlayerHead_InAgbArchiveFile0_data_p; +long JW_AgbTargetPlayerHead_InAgbArchiveFile0_size; +void* JW_AgbTargetPlayerBody_InAgbArchiveFile0_data_p; +long JW_AgbTargetPlayerBody_InAgbArchiveFile0_size; +void* JW_AgbTargetPlayerPal_InAgbArchiveFile0_data_p; +long JW_AgbTargetPlayerPal_InAgbArchiveFile0_size; +void* JW_AgbTargetMiniClient_InAgbArchiveFile1234_data_p; +long JW_AgbTargetMiniClient_InAgbArchiveFile1234_size; +void* JW_AgbTargetMiniChild_InAgbArchiveFile1234_data_p; +long JW_AgbTargetMiniChild_InAgbArchiveFile1234_size; + +extern u32 JW_Get_AgbTargetNpcHead_InAgbArchiveFile0_data_p() { + return (u32)JW_AgbTargetNpcHead_InAgbArchiveFile0_data_p; +} + +extern u32 JW_Get_AgbTargetNpcBody_InAgbArchiveFile0_data_p() { + return (u32)JW_AgbTargetNpcBody_InAgbArchiveFile0_data_p; +} + +extern u32 JW_Get_AgbTargetNpcPal_InAgbArchiveFile0_data_p() { + return (u32)JW_AgbTargetNpcPal_InAgbArchiveFile0_data_p; +} + +extern u32 JW_Get_AgbTargetPlayerHead_InAgbArchiveFile0_data_p() { + return (u32)JW_AgbTargetPlayerHead_InAgbArchiveFile0_data_p; +} + +extern u32 JW_Get_AgbTargetPlayerBody_InAgbArchiveFile0_data_p() { + return (u32)JW_AgbTargetPlayerBody_InAgbArchiveFile0_data_p; +} + +extern u32 JW_Get_AgbTargetPlayerPal_InAgbArchiveFile0_data_p() { + return (u32)JW_AgbTargetPlayerPal_InAgbArchiveFile0_data_p; +} + +extern u8* JW_Get_AgbTargetClient_InAgbArchiveFile1234_data_p() { + return (u8*)JW_AgbTargetMiniClient_InAgbArchiveFile1234_data_p; +} + +extern u8* JW_Get_AgbTargetChild_InAgbArchiveFile1234_data_p() { + return (u8*)JW_AgbTargetMiniChild_InAgbArchiveFile1234_data_p; +} + +extern size_t JW_Get_AgbTargetClient_InAgbArchiveFile1234_size() { + return JW_AgbTargetMiniClient_InAgbArchiveFile1234_size; +} + +extern size_t JW_Get_AgbTargetChild_InAgbArchiveFile1234_size() { + return JW_AgbTargetMiniChild_InAgbArchiveFile1234_size; +} + +int JW_request_type_AgbProg; + +extern int JW_Get_request_type_AgbProg() { + return JW_request_type_AgbProg; +} + +extern void JW_Set_request_type_AgbProg(int type) { + if (type >= 0 && type < 3) { + JW_request_type_AgbProg = type; + } +} + +int JW_loaded_type_AgbProg = -1; + +extern int JW_Get_loaded_type_AgbProg() { + return JW_loaded_type_AgbProg; +} + +void JW_Set_loaded_type_AgbProg(int type) { + JW_loaded_type_AgbProg = type; +} + +u32 JW_ArchiveExpandSize(u8* data) { + return (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; +} + +u8* JW_FileLoad_DvdToMainRam_byName(char* name, u8** buf_p, u32 buf_end) { + u8* data = (u8*)JC__JKRDvdToMainRam_byName(name, *buf_p, EXPAND_SWITCH_DECOMPRESS); + + if (data == nullptr) { + OSReport("\x1b[41;37m外専用AGBファイルの読み込みに失敗しました:%s\n\x1b[m", name); + return nullptr; + } + + *buf_p += JW_ArchiveExpandSize(data); + *buf_p = (u8*)ALIGN_NEXT((u32)*buf_p, 32); + + if ((u32)*buf_p >= buf_end) { + OSReport("\x1b[41;37m外専用AGBファイルが大きすぎます:%s\n\x1b[m", name); + return nullptr; + } + + return data; +} + +JKRMemArchive* JW_Create_JKRMemArchive(u8** buf_p, u32 buf_end) { + u8* buf = *buf_p; + u32 next = ALIGN_NEXT((u32)buf + sizeof(JKRMemArchive), 32); + + if (next >= buf_end) { + OSReport("\x1b[41;37m外専用AGBアーカイブのインスタンスが確保できませんでした:%s %d\n\x1b[m", + "jsyswrap.cpp", 2179); + return nullptr; + } + + JKRMemArchive* archive = new (buf) JKRMemArchive(); + if (archive == nullptr) { + OSReport("\x1b[41;37m外専用AGBアーカイブのインスタンス作成に失敗しました:%s %d\n\x1b[m", "jsyswrap.cpp", + 2191); + return nullptr; + } + + *buf_p = (u8*)next; + return archive; +} + +int JW_LoadedFileToArchve(JKRMemArchive* archive, u8* data) { + archive->mountFixed(data, MBF_0); + + if (!archive->isMounted()) { + OSReport("\x1b[41;37mAGBデータのマウントに失敗しました:%s %d\n\x1b[m", "jsyswrap.cpp", 2211); + return FALSE; + } + + return TRUE; +} + +void JW_Get_ArchveInfo(char* name, void** data_p, long* size_p) { + *data_p = JC__JKRGetResource(name); + + if (*data_p != nullptr) { + *size_p = JC__JKRGetResourceSize(*data_p); + } else { + OSReport("\x1b[41;37mAGBデータに指定したファイルがありませんでした:%s\n\x1b[m", name); + } +} + +extern void JW_Load_AGB_archive_outdoor(u8* buf, u32 size) { + static char* archive_file_name[] = { "agb_game0.arc.szs", "agb_game1.arc.szs", "agb_game2.arc.szs" }; + static char* target_file0_name[] = { "/agb_game0/mini_client0.bin", "/agb_game1/mini_client1.bin", + "/agb_game2/mini_client2.bin" }; + static char* target_file1_name[] = { "/agb_game0/mini_child0.bin", "/agb_game1/mini_child1.bin", + "/agb_game2/mini_child2.bin" }; + u8* buf_p = buf; + u32 buf_end = (u32)buf + size; + u8* save_p; + + if (buf == nullptr || size == 0) { + OSReport("\x1b[41;37m外専用AGBアーカイブ領域がありません\n\x1b[m"); + return; + } + + u8* data = JW_FileLoad_DvdToMainRam_byName("agb_data.arc.szs", &buf_p, buf_end); + if (data == nullptr) { + return; + } + + save_p = buf_p; + JKRMemArchive* archive = JW_Create_JKRMemArchive(&buf_p, buf_end); + if (archive == nullptr) { + JC__JKRDetachResource(data); + return; + } + + if (!JW_LoadedFileToArchve(archive, data)) { + delete archive; + JC__JKRDetachResource(data); + return; + } + + JW_Get_ArchveInfo("/agb_data/npc_head.bin", &JW_AgbTargetNpcHead_InAgbArchiveFile0_data_p, + &JW_AgbTargetNpcHead_InAgbArchiveFile0_size); + JW_Get_ArchveInfo("/agb_data/npc_body.bin", &JW_AgbTargetNpcBody_InAgbArchiveFile0_data_p, + &JW_AgbTargetNpcBody_InAgbArchiveFile0_size); + JW_Get_ArchveInfo("/agb_data/npc_pal.bin", &JW_AgbTargetNpcPal_InAgbArchiveFile0_data_p, + &JW_AgbTargetNpcPal_InAgbArchiveFile0_size); + JW_Get_ArchveInfo("/agb_data/player_head.bin", &JW_AgbTargetPlayerHead_InAgbArchiveFile0_data_p, + &JW_AgbTargetPlayerHead_InAgbArchiveFile0_size); + JW_Get_ArchveInfo("/agb_data/player_body.bin", &JW_AgbTargetPlayerBody_InAgbArchiveFile0_data_p, + &JW_AgbTargetPlayerBody_InAgbArchiveFile0_size); + JW_Get_ArchveInfo("/agb_data/player_pal.bin", &JW_AgbTargetPlayerPal_InAgbArchiveFile0_data_p, + &JW_AgbTargetPlayerPal_InAgbArchiveFile0_size); + archive->unmountFixed(); + delete archive; + buf_p = save_p; + JC__JKRDetachResource(data); + + int type = JW_Get_request_type_AgbProg(); + if (type < 0 || type >= 3) { + type = 0; + } + + u8* prog_data = JW_FileLoad_DvdToMainRam_byName(archive_file_name[type], &buf_p, buf_end); + if (prog_data == nullptr) { + JW_Set_loaded_type_AgbProg(-1); + return; + } + + save_p = buf_p; + JKRMemArchive* prog_archive = JW_Create_JKRMemArchive(&buf_p, buf_end); + if (prog_archive == nullptr) { + JC__JKRDetachResource(prog_data); + JW_Set_loaded_type_AgbProg(-1); + return; + } + + if (!JW_LoadedFileToArchve(prog_archive, prog_data)) { + delete prog_archive; + JC__JKRDetachResource(prog_data); + JW_Set_loaded_type_AgbProg(-1); + return; + } + + JW_Get_ArchveInfo(target_file0_name[type], &JW_AgbTargetMiniClient_InAgbArchiveFile1234_data_p, + &JW_AgbTargetMiniClient_InAgbArchiveFile1234_size); + JW_Get_ArchveInfo(target_file1_name[type], &JW_AgbTargetMiniChild_InAgbArchiveFile1234_data_p, + &JW_AgbTargetMiniChild_InAgbArchiveFile1234_size); + prog_archive->unmountFixed(); + delete prog_archive; + buf_p = save_p; + JC__JKRDetachResource(prog_data); + JW_Set_loaded_type_AgbProg(type); +} + +extern void JW_Release_AGB_archive_outdoor() { + JW_AgbTargetNpcHead_InAgbArchiveFile0_data_p = nullptr; + JW_AgbTargetNpcHead_InAgbArchiveFile0_size = 0; + JW_AgbTargetNpcBody_InAgbArchiveFile0_data_p = nullptr; + JW_AgbTargetNpcBody_InAgbArchiveFile0_size = 0; + JW_AgbTargetNpcPal_InAgbArchiveFile0_data_p = nullptr; + JW_AgbTargetNpcPal_InAgbArchiveFile0_size = 0; + JW_AgbTargetPlayerHead_InAgbArchiveFile0_data_p = nullptr; + JW_AgbTargetPlayerHead_InAgbArchiveFile0_size = 0; + JW_AgbTargetPlayerBody_InAgbArchiveFile0_data_p = nullptr; + JW_AgbTargetPlayerBody_InAgbArchiveFile0_size = 0; + JW_AgbTargetPlayerPal_InAgbArchiveFile0_data_p = nullptr; + JW_AgbTargetPlayerPal_InAgbArchiveFile0_size = 0; + JW_AgbTargetMiniClient_InAgbArchiveFile1234_data_p = nullptr; + JW_AgbTargetMiniClient_InAgbArchiveFile1234_size = 0; + JW_AgbTargetMiniChild_InAgbArchiveFile1234_data_p = nullptr; + JW_AgbTargetMiniChild_InAgbArchiveFile1234_size = 0; + JW_Set_loaded_type_AgbProg(-1); +} + +u8* JW_AgbTarget_Special_archive_p; +void* JW_AgbTarget_EditorLoader_data_p; +long JW_AgbTarget_EditorLoader_size; +void* JW_AgbTarget_EditorProg_data_p; +long JW_AgbTarget_EditorProg_size; + +extern u8* JW_Get_AgbTarget_EditorLoader_data_p() { + return (u8*)JW_AgbTarget_EditorLoader_data_p; +} + +extern u8* JW_Get_AgbTarget_EditorProg_data_p() { + return (u8*)JW_AgbTarget_EditorProg_data_p; +} + +extern u8* JW_Get_AgbTarget_Special_archive_p() { + return JW_AgbTarget_Special_archive_p; +} + +extern size_t JW_Get_AgbTarget_EditorLoader_size() { + return JW_AgbTarget_EditorLoader_size; +} + +extern size_t JW_Get_AgbTarget_EditorProg_size() { + return JW_AgbTarget_EditorProg_size; +} + +extern void JW_Load_AGB_archive_special() { + char* name = "agb_special.arc.szs"; + + JW_AgbTarget_Special_archive_p = (u8*)JC__JKRDvdToMainRam_byName(name, nullptr, EXPAND_SWITCH_DECOMPRESS); + if (JW_AgbTarget_Special_archive_p == nullptr) { + OSReport("\x1b[41;37m常駐AGBファイルの読み込みに失敗しました:%s\n\x1b[m", name); + JW_Unload_AGB_archive_special(); + return; + } + + JC__JKRDetachResource(JW_AgbTarget_Special_archive_p); + + JKRMemArchive archive; + if (!JW_LoadedFileToArchve(&archive, JW_AgbTarget_Special_archive_p)) { + JW_Free(JW_AgbTarget_Special_archive_p); + JW_AgbTarget_Special_archive_p = nullptr; + JW_Unload_AGB_archive_special(); + return; + } + + JW_Get_ArchveInfo("/agb_special/editor_ldr_JPN.bin", &JW_AgbTarget_EditorLoader_data_p, + &JW_AgbTarget_EditorLoader_size); + JW_Get_ArchveInfo("/agb_special/editor_prg_JPN.bin", &JW_AgbTarget_EditorProg_data_p, + &JW_AgbTarget_EditorProg_size); + archive.unmountFixed(); +} + +extern void JW_Unload_AGB_archive_special() { + if (JW_AgbTarget_Special_archive_p != nullptr) { + JW_Free(JW_AgbTarget_Special_archive_p); + JW_AgbTarget_Special_archive_p = nullptr; + } + + JW_AgbTarget_EditorLoader_data_p = nullptr; + JW_AgbTarget_EditorLoader_size = 0; + JW_AgbTarget_EditorProg_data_p = nullptr; + JW_AgbTarget_EditorProg_size = 0; +} + +u8* JW_picture_copy_archive_p; +void* JW_picture_copy_data_p; + +extern void JW_Load_picture_copy_archive() { + char* name = "picture_copy.arc.szs"; + + JW_picture_copy_archive_p = (u8*)JC__JKRDvdToMainRam_byName(name, nullptr, EXPAND_SWITCH_DECOMPRESS); + if (JW_picture_copy_archive_p == nullptr) { + OSReport("\x1b[41;37mTIFFの著作権表示用アーカイブファイルの読み込みに失敗しました:%s\n\x1b[m", name); + JW_Unload_picture_copy_archive(); + return; + } + + JC__JKRDetachResource(JW_picture_copy_archive_p); + + JKRMemArchive archive; + if (!JW_LoadedFileToArchve(&archive, JW_picture_copy_archive_p)) { + JW_Free(JW_picture_copy_archive_p); + JW_Unload_picture_copy_archive(); + return; + } + + long size; + JW_Get_ArchveInfo("picture_copy.bti", &JW_picture_copy_data_p, &size); + archive.unmountFixed(); +} + +extern void JW_Unload_picture_copy_archive() { + JW_picture_copy_archive_p = nullptr; + JW_picture_copy_data_p = nullptr; +} + +extern void* JW_Get_picture_copy_data_p() { + return JW_picture_copy_data_p; +} + +extern u8* JW_Get_picture_copy_archive_p() { + return JW_picture_copy_archive_p; +} + +extern u8* JW_Get_SDCardBuffer_p() { + return Get_free_buff_p_for_moduleI_or_moduleO(); +} diff --git a/src/static/jsyswrap_JKRAramStream.h b/src/static/jsyswrap_JKRAramStream.h new file mode 100644 index 00000000..2e7403ca --- /dev/null +++ b/src/static/jsyswrap_JKRAramStream.h @@ -0,0 +1,10 @@ +#ifndef JSYSWRAP_JKRARAMSTREAM_H +#define JSYSWRAP_JKRARAMSTREAM_H + +#include "JSystem/JKernel/JKRAram.h" + +inline void JKRSetAramTransferBuffer(u8* buf, u32 size, JKRHeap* heap) { + JKRAramStream::setTransBuffer(buf, size, heap); +} + +#endif diff --git a/src/static/libjsys/jsyswrapper.cpp b/src/static/libjsys/jsyswrapper.cpp index 307f6fe5..b27c7004 100644 --- a/src/static/libjsys/jsyswrapper.cpp +++ b/src/static/libjsys/jsyswrapper.cpp @@ -1,5 +1,3 @@ -#include "libjsys/jsyswrapper.h" - #include "JSystem/JSystem.h" #include "JSystem/JKernel/JKRExpHeap.h" #include "JSystem/JUtility/JUTDbPrint.h" @@ -14,7 +12,63 @@ #include "MSL_C/printf.h" -// TODO: there are a ton of unused functions we may want to add to this, check DnM+'s static.map file - -#include "../src/static/libjsys/jsyswrapper_ext.cpp" +extern "C" { #include "../src/static/libjsys/jsyswrapper_main.cpp" +} + +extern "C" void JC_JUTConsole_print_f_va(void* console, const char* fmt, va_list arg) { + reinterpret_cast(console)->print_f_va(fmt, arg); +} + +extern "C" void JC_JUTConsole_print_f(void* console, const char* fmt, ...) { + va_list arg; + + va_start(arg, fmt); + JC_JUTConsole_print_f_va(console, fmt, arg); + va_end(arg); +} + +void enter_(int x, int y, int show_count, const char* fmt, va_list arg); + +extern "C" void JW_JUTReport(int x, int y, int show_count, const char* fmt, ...) { + va_list arg; + + va_start(arg, fmt); + enter_(x, y, show_count, fmt, arg); + va_end(arg); +} + +void enter_(int x, int y, int show_count, const char* fmt, va_list arg) { + JUTDbPrint* dbprint = JUTDbPrint::getManager(); + + if (dbprint == nullptr || !dbprint->isVisible()) { + return; + } + + char buf[256]; + int len = vsnprintf(buf, sizeof(buf), fmt, arg); + + if (len >= 0) { + dbprint->enter(x, y, show_count, buf, len >= (int)sizeof(buf) ? sizeof(buf) - 1 : len); + } +} + +extern "C" void* JW_Alloc(size_t size, int align) { + return JC_JKRHeap_alloc(JC_JFWSystem_getSystemHeap(), size, align); +} + +extern "C" s32 JW_Resize(void* ptr, size_t new_size) { + return JC_JKRHeap_resize(JC_JFWSystem_getSystemHeap(), ptr, new_size); +} + +extern "C" void JW_Free(void* ptr) { + JC_JKRHeap_free(JC_JFWSystem_getSystemHeap(), ptr); +} + +extern "C" size_t JW_GetMemBlockSize(void* ptr) { + return JC_JKRHeap_getSize(JC_JFWSystem_getSystemHeap(), ptr); +} + +extern "C" void JW_JUTXfb_clearIndex(void) { + JC_JUTXfb_clearIndex(JC_JUTXfb_getManager()); +} diff --git a/src/static/libjsys/jsyswrapper_ext.cpp b/src/static/libjsys/jsyswrapper_ext.cpp deleted file mode 100644 index 47af9dc7..00000000 --- a/src/static/libjsys/jsyswrapper_ext.cpp +++ /dev/null @@ -1,41 +0,0 @@ -extern void JC_JUTConsole_print_f_va(void* console, const char* fmt, va_list arg) { - char buf[256]; - - vsnprintf(buf, sizeof(buf), fmt, arg); - reinterpret_cast(console)->print(buf); -} - -extern void JW_JUTReport(int x, int y, int show_count, const char* fmt, ...) { - char buf[256]; - va_list arg; - int len; - int shown_len; - - va_start(arg, fmt); - len = (int)vsnprintf(buf, sizeof(buf), fmt, arg); - va_end(arg); - - if (len >= 0) { - JUTDbPrint::sDebugPrint->enter(x, y, show_count, buf, len >= (int)sizeof(buf) ? sizeof(buf) - 1 : len); - } -} - -extern void* JW_Alloc(size_t size, int align) { - return JC_JKRHeap_alloc(JC_JFWSystem_getSystemHeap(), size, align); -} - -extern s32 JW_Resize(void* ptr, size_t new_size) { - return JC_JKRHeap_resize(JC_JFWSystem_getSystemHeap(), ptr, new_size); -} - -extern void JW_Free(void* ptr) { - JC_JKRHeap_free(JC_JFWSystem_getSystemHeap(), ptr); -} - -extern size_t JW_GetMemBlockSize(void* ptr) { - return JC_JKRHeap_getSize(JC_JFWSystem_getSystemHeap(), ptr); -} - -extern void JW_JUTXfb_clearIndex(void) { - JC_JUTXfb_clearIndex(JC_JUTXfb_getManager()); -} diff --git a/src/static/libjsys/jsyswrapper_main.cpp b/src/static/libjsys/jsyswrapper_main.cpp index 4c73df16..b89b75e8 100644 --- a/src/static/libjsys/jsyswrapper_main.cpp +++ b/src/static/libjsys/jsyswrapper_main.cpp @@ -6,34 +6,6 @@ extern void* JC_JUTFader_new(int ul_x, int ul_y, int br_x, int br_y, u32* color) return new JUTFader(ul_x, ul_y, br_x, br_y, JUtility::TColor(*(GXColor*)color)); } -// @unused (necessary for virtual function emmission) -extern int JC_JKRHeap_dump_sort(void* heap) { - return reinterpret_cast(heap)->dump_sort(); -} - -// @unused -extern int JC_JKRHeap_check(void* heap) { - return reinterpret_cast(heap)->check(); -} - -// @fabricated - necessary for virtuals -extern void JC_JUTResFont_fabricated(void* font) { - reinterpret_cast(font)->getLeading(); - reinterpret_cast(font)->getFontType(); - reinterpret_cast(font)->getResFont(); -} -// @unused -extern int JC_JUTFont_getWidth(void* font) { - return reinterpret_cast(font)->getWidth(); -} - -// @unused -- extra hacked for the right weak func emission order -extern int JC_JUTFont_getHeight(void* font) { - return reinterpret_cast(font)->getHeight(); - return reinterpret_cast(font)->getDescent(); - return reinterpret_cast(font)->getAscent(); -} - extern void* JC_JUTDbPrint_getManager() { return JUTDbPrint::getManager(); } @@ -55,7 +27,7 @@ extern void JC_J2DOrthoGraph_setPort(void* orthograph) { } extern void JC_J2DOrthoGraph_setOrtho(void* orthograph, int ul_x, int ul_y, int br_x, int br_y) { - reinterpret_cast(orthograph)->setOrtho(JGeometry::TBox2f((f32)ul_x, (f32)ul_y, (f32)ul_x + (f32)br_x, (f32)ul_y + (f32)br_y), -1.0f, 1.0f); + reinterpret_cast(orthograph)->setOrtho((f32)ul_x, (f32)ul_y, (f32)br_x, (f32)br_y, -1.0f, 1.0f); } extern void* JC_JUTVideo_getManager() { @@ -65,12 +37,16 @@ extern void JC_JUTVideo_setRenderMode(void* manager, GXRenderModeObj* renderMode reinterpret_cast(manager)->setRenderMode(renderMode); } +extern const GXRenderModeObj* JC_JUTVideo_getRenderMode(void* manager) { + return reinterpret_cast(manager)->getRenderMode(); +} + extern u32 JC_JUTVideo_getFbWidth(void* manager) { return reinterpret_cast(manager)->getFbWidth(); } extern u32 JC_JUTVideo_getEfbHeight(void* manager) { - return reinterpret_cast(manager)->getEfbHeight(); + return (u16)reinterpret_cast(manager)->getEfbHeight(); } extern void* JC_JKRHeap_alloc(void* heap, u32 size, int align) { @@ -89,6 +65,16 @@ extern int JC_JKRHeap_dump(void* heap) { return reinterpret_cast(heap)->dump(); } +// @unused +extern int JC_JKRHeap_dump_sort(void* heap) { + return reinterpret_cast(heap)->dump_sort(); +} + +// @unused +extern int JC_JKRHeap_check(void* heap) { + return reinterpret_cast(heap)->check(); +} + extern u32 JC_JKRHeap_getFreeSize(void* heap) { return reinterpret_cast(heap)->getFreeSize(); } @@ -102,7 +88,7 @@ extern size_t JC_JKRHeap_getSize(void* heap, void* mem) { } extern void* JC__JKRGetSystemHeap() { - return JKRHeap::getSystemHeap(); + return JKRGetSystemHeap(); } extern u32 JC__JKRGetMemBlockSize(void* heap, void* ptr) { @@ -113,12 +99,44 @@ extern u8 JC_JKRExpHeap_changeGroupID(void* expheap, u8 groupId) { return reinterpret_cast(expheap)->changeGroupID((u8)groupId); } +// @unused +extern void JC_JUTResFont_fabricated(void* font) { + reinterpret_cast(font)->getLeading(); + reinterpret_cast(font)->getFontType(); + reinterpret_cast(font)->getResFont(); +} + +// @unused +extern int JC_JUTFont_getWidth(void* font) { + return reinterpret_cast(font)->getWidth(); +} + +// @unused +extern int JC_JUTFont_getHeight(void* font) { + return reinterpret_cast(font)->getHeight(); + return reinterpret_cast(font)->getDescent(); + return reinterpret_cast(font)->getAscent(); +} + +// @unused +extern void JC__JKRRemoveResource(void* res) { + JKRRemoveResource(res); +} + +// @unused, @fabricated +extern void JC_JUTDirectPrint_setCharColor(u32* color) { + JUtility::TColor charColor; + + charColor = *(JUtility::TColor*)color; + JUTDirectPrint::getManager()->setCharColor(charColor); +} + extern void JC_JUTGamePad_read() { JUTGamePad::read(); } extern PADStatus JC_JUTGamePad_getPadStatus(u32 port) { - return *JUTGamePad::getPadStatus(port); + return *JUTGamePad::getPadStatus((JUTGamePad::EPadPort)port); } extern u8 JC_JUTGamePad_recalibrate(u32 port) { @@ -141,6 +159,10 @@ extern int JC_JUTConsole_isVisible(void* console) { return reinterpret_cast(console)->isVisible(); } +extern void JC_JUTConsole_print(void* console, const char* str) { + reinterpret_cast(console)->print(str); +} + extern u32 JC_JUTConsole_getHeight(void* console) { return reinterpret_cast(console)->getHeight(); } @@ -206,7 +228,7 @@ extern void JC_JUTException_setPostUserCallback(void* callback) { } extern void JC_JUTException_setMapFile(const char* path) { - JUTException::appendMapFile(path); + JUTException::setMapFile(path); } extern void* JC_JUTException_getConsole() { @@ -225,8 +247,8 @@ extern void JC_JUTException_waitTime(u32 time) { JUTException::waitTime(time); } -extern void* JC_JFWDisplay_createManager_0(GXRenderModeObj* renderMode, void* heap, int exfbNumber, int enableAlpha) { - return JFWDisplay::createManager(renderMode, reinterpret_cast(heap), (JUTXfb::EXfbNumber)exfbNumber, (bool)enableAlpha); +extern void* JC_JFWDisplay_createManager_0(void* heap, int exfbNumber, int enableAlpha) { + return JFWDisplay::createManager(reinterpret_cast(heap), (JUTXfb::EXfbNumber)exfbNumber, (bool)enableAlpha); } extern void JC_JFWDisplay_destroyManager() { @@ -238,10 +260,10 @@ extern void* JC_JFWDisplay_getManager() { } extern void JC_JFWDisplay_setGamma(void* manager, int gamma) { - reinterpret_cast(manager)->setGamma(gamma); + reinterpret_cast(manager)->setGamma((GXGamma)gamma); } -extern void JC_JFWDisplay_setFrameRate(void* manager, u16 framerate) { +extern void JC_JFWDisplay_setFrameRate(void* manager, int framerate) { reinterpret_cast(manager)->setFrameRate(framerate); } @@ -293,10 +315,6 @@ extern void JC_JFWDisplay_clearEfb(void* manager, GXColor color) { reinterpret_cast(manager)->clearEfb(color); } -extern const GXRenderModeObj* JC_JFWDisplay_getRenderMode(void* manager) { - return reinterpret_cast(manager)->getRenderMode(); -} - extern void JC_JFWSystem_setMaxStdHeap(int max) { JFWSystem::setMaxStdHeap(max); } @@ -342,7 +360,7 @@ extern void JC_JUTProcBar_setVisible(void* procbar, BOOL visible) { } extern void JC_JUTProcBar_setVisibleHeapBar(void* procbar, BOOL visible) { - reinterpret_cast(procbar)->setHeapBarVisible(visible); + reinterpret_cast(procbar)->setVisibleHeapBar(visible); } extern int JC_JKRDecomp_checkCompressed(u8* bufp) { @@ -357,20 +375,24 @@ extern void* JC__JKRGetResource(const char* resourceName) { return JKRGetResource(resourceName); } -extern void JC__JKRRemoveResource(void* res) { - JKRRemoveResource(res); +extern int JC__JKRReadResource(void* dst, size_t dst_size, const char* src, int expandSwitch) { + return JKRReadResource(dst, dst_size, src, (JKRExpandSwitch)expandSwitch); } extern void JC__JKRDetachResource(void* ptr) { JKRDetachResource(ptr); } +extern u32 JC__JKRGetResourceSize(void* res) { + return JKRGetResourceSize(res); +} + extern void* JC__JKRMountArchive(const char* path, int mount_mode, void* heap, int mount_direction) { return JKRMountArchive(path, (JKRArchive::EMountMode)mount_mode, reinterpret_cast(heap), (JKRArchive::EMountDirection)mount_direction); } -extern CSDIFileEntry* JC__JKRGetResourceEntry_byName(u32 root_name, const char* res_name, void* archive) { - JKRGetResourceEntry_byName(root_name, res_name, reinterpret_cast(archive)); +extern void* JC__JKRGetResourceEntry_byName(u32 root_name, const char* res_name, void* archive) { + return JKRGetResourceEntry(root_name, res_name, reinterpret_cast(archive)); } extern void JC_JKRAramHeap_dump(void* heap) { @@ -390,11 +412,11 @@ extern void* JC_JKRAramArchive_new() { } extern BOOL JC__JKRMountFixedAramArchive(void* aram_archive, const char* file) { - return reinterpret_cast(aram_archive)->mountFixed(file, JKRArchive::MOUNT_DIRECTION_HEAD); + return JKRMountFixedAramArchive(reinterpret_cast(aram_archive), file); } extern void JC__JKRUnmountFixedAramArchive(void* aram_archive) { - reinterpret_cast(aram_archive)->unmountFixed(); + JKRUnmountFixedAramArchive(reinterpret_cast(aram_archive)); } extern u32 JC_JKRAramArchive_getAramAddress_byName(void* archive, u32 root_name, const char* res_name) { @@ -412,15 +434,15 @@ extern u32 JC_JKRAramBlock_getAddress(void* aramBlock) { #pragma force_active reset extern u8* JC__JKRAramToMainRam_block(void* aramBlock, u8* ramDst, size_t size) { - return JKRAram::aramToMainRam(reinterpret_cast(aramBlock), ramDst, size, 0, EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); + return JKRAramToMainRam(reinterpret_cast(aramBlock), ramDst, size, 0, EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); } extern void* JC__JKRMainRamToAram_block(u8* ramAddr, void* aramBlock, size_t size) { - return JKRAram::mainRamToAram(ramAddr, reinterpret_cast(aramBlock), size, EXPAND_SWITCH_DEFAULT, 0, nullptr, -1); + return JKRMainRamToAram(ramAddr, reinterpret_cast(aramBlock), size, EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); } extern void* JC__JKRDvdToMainRam_byName(const char* name, u8* buf, JKRExpandSwitch expandSwitch) { - return JKRDvdRipper::loadToMainRAM(name, buf, expandSwitch, 0, NULL, JKRDvdRipper::ALLOC_DIR_TOP, 0, NULL); + return JKRDvdToMainRam(name, buf, expandSwitch, 0, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 0, nullptr, nullptr); } extern void JC_JUTAssertion_changeDevice(int device) { From 030dec7b18aeaa3dfd5232c8fd1b9c0411855c0d Mon Sep 17 00:00:00 2001 From: h0504 Date: Tue, 27 Oct 2026 08:25:58 +0900 Subject: [PATCH 4/7] Match remaining jaudio_PP and Famicom code for Rev 1 - Split oneshot, driver, jammain_2 and emusound into #included .c_inc files so the -sym on build reproduces the original .text sections. emusound's Sound_GetPCM is a fabricated stand-in for a stripped function whose 32-aligned section produced the trailing padding. - dspboot: DspBoot comes first; playercall: Jac_CheckPlayerCallback is global; system/sub_sys: non-volatile AUDIO_SYSTEM_READY for Rev 1; smaller fixes in memory, rspsim, dummyrom, audiothread. - Famicom: Rev 1 nogbaInput and card result mapping, inline std::strstr in famicom_cstring.h, ks_nes_draw register allocation fixes. Co-Authored-By: Claude Opus 5.5 --- include/Famicom/famicom_cstring.h | 14 + include/jaudio_NES/system.h | 5 + src/static/Famicom/famicom.cpp | 59 +- src/static/Famicom/ks_nes_draw.cpp | 219 +- src/static/jaudio_PP/game/emusound.c | 1595 +------- src/static/jaudio_PP/game/emusound_a.c_inc | 202 + src/static/jaudio_PP/game/emusound_b.c_inc | 200 + src/static/jaudio_PP/game/emusound_c.c_inc | 124 + src/static/jaudio_PP/game/emusound_d.c_inc | 140 + src/static/jaudio_PP/game/emusound_disk.c_inc | 107 + src/static/jaudio_PP/game/emusound_e.c_inc | 115 + .../jaudio_PP/game/emusound_event.c_inc | 84 + src/static/jaudio_PP/game/emusound_hvc.c_inc | 355 ++ src/static/jaudio_PP/game/emusound_pcm.c_inc | 11 + src/static/jaudio_PP/game/emusound_vrc.c_inc | 239 ++ src/static/jaudio_PP/internal/audiothread.c | 7 +- src/static/jaudio_PP/internal/driver.c | 1426 +------ .../jaudio_PP/internal/driver_acmd.c_inc | 56 + .../jaudio_PP/internal/driver_auxbuf1.c_inc | 21 + .../jaudio_PP/internal/driver_auxch.c_inc | 69 + .../jaudio_PP/internal/driver_cpufx.c_inc | 104 + .../jaudio_PP/internal/driver_sendline.c_inc | 30 + .../jaudio_PP/internal/driver_synth.c_inc | 1144 ++++++ src/static/jaudio_PP/internal/dspboot.c | 41 +- src/static/jaudio_PP/internal/dummyrom.c | 2 +- src/static/jaudio_PP/internal/jammain_2.c | 3262 ++--------------- .../jaudio_PP/internal/jammain_2_cmd.c_inc | 863 +++++ .../internal/jammain_2_cmdproc.c_inc | 218 ++ .../jaudio_PP/internal/jammain_2_port.c_inc | 555 +++ .../jaudio_PP/internal/jammain_2_reg.c_inc | 435 +++ .../jaudio_PP/internal/jammain_2_update.c_inc | 498 +++ src/static/jaudio_PP/internal/memory.c | 32 +- src/static/jaudio_PP/internal/oneshot.c | 455 +-- .../jaudio_PP/internal/oneshot_effecter.c_inc | 185 + .../internal/oneshot_getchannel.c_inc | 53 + .../jaudio_PP/internal/oneshot_instread.c_inc | 41 + .../jaudio_PP/internal/oneshot_monopoly.c_inc | 126 + .../internal/oneshot_playstart.c_inc | 41 + src/static/jaudio_PP/internal/playercall.c | 2 +- src/static/jaudio_PP/internal/rspsim.c | 152 +- src/static/jaudio_PP/internal/system.c | 6 +- 41 files changed, 6711 insertions(+), 6582 deletions(-) create mode 100644 include/Famicom/famicom_cstring.h create mode 100644 src/static/jaudio_PP/game/emusound_a.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_b.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_c.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_d.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_disk.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_e.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_event.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_hvc.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_pcm.c_inc create mode 100644 src/static/jaudio_PP/game/emusound_vrc.c_inc create mode 100644 src/static/jaudio_PP/internal/driver_acmd.c_inc create mode 100644 src/static/jaudio_PP/internal/driver_auxbuf1.c_inc create mode 100644 src/static/jaudio_PP/internal/driver_auxch.c_inc create mode 100644 src/static/jaudio_PP/internal/driver_cpufx.c_inc create mode 100644 src/static/jaudio_PP/internal/driver_sendline.c_inc create mode 100644 src/static/jaudio_PP/internal/driver_synth.c_inc create mode 100644 src/static/jaudio_PP/internal/jammain_2_cmd.c_inc create mode 100644 src/static/jaudio_PP/internal/jammain_2_cmdproc.c_inc create mode 100644 src/static/jaudio_PP/internal/jammain_2_port.c_inc create mode 100644 src/static/jaudio_PP/internal/jammain_2_reg.c_inc create mode 100644 src/static/jaudio_PP/internal/jammain_2_update.c_inc create mode 100644 src/static/jaudio_PP/internal/oneshot_effecter.c_inc create mode 100644 src/static/jaudio_PP/internal/oneshot_getchannel.c_inc create mode 100644 src/static/jaudio_PP/internal/oneshot_instread.c_inc create mode 100644 src/static/jaudio_PP/internal/oneshot_monopoly.c_inc create mode 100644 src/static/jaudio_PP/internal/oneshot_playstart.c_inc diff --git a/include/Famicom/famicom_cstring.h b/include/Famicom/famicom_cstring.h new file mode 100644 index 00000000..ae3de6f6 --- /dev/null +++ b/include/Famicom/famicom_cstring.h @@ -0,0 +1,14 @@ +#ifndef FAMICOM_CSTRING_H +#define FAMICOM_CSTRING_H + +#include "libc/string.h" + +#ifdef __cplusplus +namespace std { +inline char* strstr(char* str, const char* pat) { + return ::strstr(str, pat); +} +} // namespace std +#endif + +#endif diff --git a/include/jaudio_NES/system.h b/include/jaudio_NES/system.h index a34f1cb1..d9903781 100644 --- a/include/jaudio_NES/system.h +++ b/include/jaudio_NES/system.h @@ -3,6 +3,7 @@ #include "types.h" #include "libultra/libultra.h" +#include "ver.h" #define REFRESH_RATE_DEVIATION_NTSC 1.00278f #define REFRESH_RATE_NTSC 60 @@ -62,7 +63,11 @@ extern void MK_Init(void); extern void Nas_WaveDmaNew(s32 n_channels); extern Na_SyncProc NA_SYNC_PROC; +#if VERSION == VER_GAEJ01_01 +extern BOOL AUDIO_SYSTEM_READY; +#else extern volatile BOOL AUDIO_SYSTEM_READY; +#endif extern Na_DmaProc NA_DMA_PROC; extern OSMesgQueue MK_QUEUE; extern OSMesg MK_QBUF[]; diff --git a/src/static/Famicom/famicom.cpp b/src/static/Famicom/famicom.cpp index f0aa3f1d..8c05bd91 100644 --- a/src/static/Famicom/famicom.cpp +++ b/src/static/Famicom/famicom.cpp @@ -20,14 +20,22 @@ #include "libjsys/jsyswrapper.h" #include "jsyswrap_cpp.h" #include "MSL_C/printf.h" +#include "ver.h" #include "jaudio_NES/emusound.h" #include "JSystem/JUtility/JUTProcBar.h" #include "JSystem/JUtility/JUTGamePad.h" #include "nintendo_hi_0.h" #include "m_nmibuf.h" -#include "MSL_C/string.h" +#include "Famicom/famicom_cstring.h" // #include "JSystem/J2D/J2DGrafContext.h" // needed for ~J2DOrthoGraph +/* OSPanic line numbers differ between revisions */ +#if VERSION == VER_GAEJ01_01 +#define REV_LINE(rev0, rev1) (rev1) +#else +#define REV_LINE(rev0, rev1) (rev0) +#endif + /* For some reason, there are a bunch of unused implicit one-byte 4-byte-aligned bss variables */ #ifdef MUST_MATCH static u8 __unused_implicit[0x40] ATTRIBUTE_ALIGN(32); @@ -1556,7 +1564,7 @@ static void select_game() { if (nesrom_idx >= nesrom_count) { if (nesrom_idx_loaded < 0) { - OSPanic(__FILE__, 4231, "no nesfile specified"); + OSPanic(__FILE__, REV_LINE(4231, 4242), "no nesfile specified"); continue; } @@ -1681,14 +1689,14 @@ extern int famicom_init(int rom_idx, Famicom_MallocInfo* malloc_info, int player JKRChangeDirectory("/FAMICOM/"); size_t unused_totalfreesize = my_gettotalfreesize(); - MALLOC_MALLOC(u8, CHR_TO_I8_BUF_SIZE, famicomCommon.chr_to_i8_bufp, 4492); - MALLOC_MALLOC(u8, KS_NES_NESFILE_HEADER_SIZE + KS_NES_PRGROM_SIZE + KS_NES_CHRROM_SIZE, famicomCommon.nesromp, 4494); - MALLOC_MALLOC(ksNesCommonWorkObj, sizeof(ksNesCommonWorkObj), famicomCommon.wp, 4496); - MALLOC_MALLOC(ksNesStateObj, sizeof(ksNesStateObj), famicomCommon.sp, 4497); - MALLOC_MALLOC(u8, KS_NES_CHRRAM_SIZE, famicomCommon.chrramp, 4500); - MALLOC_MALLOC(u8, KS_NES_BBRAM_SIZE, famicomCommon.bbramp, 4505); - MALLOC_MALLOC(u8, KS_NES_NOISE_DATA_SIZE, famicomCommon.noise_bufp, 4510); - MALLOC_MALLOC(u8, KS_NES_DRAW_RESULT_BUF_SIZE, famicomCommon.result_bufp, 4512); + MALLOC_MALLOC(u8, CHR_TO_I8_BUF_SIZE, famicomCommon.chr_to_i8_bufp, REV_LINE(4492, 4503)); + MALLOC_MALLOC(u8, KS_NES_NESFILE_HEADER_SIZE + KS_NES_PRGROM_SIZE + KS_NES_CHRROM_SIZE, famicomCommon.nesromp, REV_LINE(4494, 4505)); + MALLOC_MALLOC(ksNesCommonWorkObj, sizeof(ksNesCommonWorkObj), famicomCommon.wp, REV_LINE(4496, 4507)); + MALLOC_MALLOC(ksNesStateObj, sizeof(ksNesStateObj), famicomCommon.sp, REV_LINE(4497, 4508)); + MALLOC_MALLOC(u8, KS_NES_CHRRAM_SIZE, famicomCommon.chrramp, REV_LINE(4500, 4511)); + MALLOC_MALLOC(u8, KS_NES_BBRAM_SIZE, famicomCommon.bbramp, REV_LINE(4505, 4516)); + MALLOC_MALLOC(u8, KS_NES_NOISE_DATA_SIZE, famicomCommon.noise_bufp, REV_LINE(4510, 4521)); + MALLOC_MALLOC(u8, KS_NES_DRAW_RESULT_BUF_SIZE, famicomCommon.result_bufp, REV_LINE(4512, 4523)); famicomCommon.memcard_save_comment = commentImageBuffer; @@ -1732,8 +1740,8 @@ extern int famicom_init(int rom_idx, Famicom_MallocInfo* malloc_info, int player goto exit; } - MALLOC_MALLOC(u8 *, nesrom_count * sizeof(u8*), nesrom_filename_ptrs, 4671); - MALLOC_MALLOC(char, length, nesrom_filename_strbuf, 4672); + MALLOC_MALLOC(u8 *, nesrom_count * sizeof(u8*), nesrom_filename_ptrs, REV_LINE(4671, 4682)); + MALLOC_MALLOC(char, length, nesrom_filename_strbuf, REV_LINE(4672, 4683)); } } } @@ -2292,10 +2300,12 @@ static int ksnes_thread_exec(u32 flags) { if (ksnes_emu_stack != nullptr) { OSTime timeout = OSMillisecondsToTicks(2000); // 2 second timeout +#if VERSION == VER_GAEJ01_00 if (famicomCommon.sp->motor_timer != 0) { // Disk motor is on. OSReport("ディスクモーターオン\n"); } +#endif OSTime frame_start_time = OSGetTime(); s32 prio = OSGetThreadPriority(OSGetCurrentThread()); @@ -2336,6 +2346,21 @@ static void nogbaInput() { switch ((int)JUTGamePad::getPortStatus((JUTGamePad::EPadPort)port)) { case PAD_ERR_NONE: { +#if VERSION == VER_GAEJ01_01 + const JUTGamePad::CButton* button; + + InputValid[port] = true; + button = JUTGamePad::getPadButton((JUTGamePad::EPadPort)port); + InputData[port] = button->mButton; + + if (button->mAnalogL != 0) { + InputData[port] |= JUTGamePad::L; + } + + if (button->mAnalogR != 0) { + InputData[port] |= JUTGamePad::R; + } +#else InputValid[port] = true; InputData[port] = ((JUTGamePad*)gamePad)[port].getButton(); @@ -2346,6 +2371,7 @@ static void nogbaInput() { if (((JUTGamePad*)gamePad)[port].getAnalogR() != 0) { InputData[port] |= JUTGamePad::R; } +#endif break; } @@ -2592,7 +2618,7 @@ extern int famicom_rom_load_check() { nesrom_idx++; if (nesrom_idx >= nesrom_count) { if (nesrom_idx_loaded < 0) { - OSPanic(__FILE__, 6063, "no nesfile specified"); + OSPanic(__FILE__, REV_LINE(6063, 6174), "no nesfile specified"); continue; } @@ -2621,10 +2647,17 @@ static int famicom_cardResultToMiyake(s32 cardResult) { return FAMICOM_RESULT_NOSPACE; case CARD_RESULT_NOENT: return FAMICOM_RESULT_NOENTRY; +#if VERSION == VER_GAEJ01_01 + case CARD_RESULT_IOERROR: +#else case CARD_RESULT_BROKEN: +#endif return FAMICOM_RESULT_BROKEN; case CARD_RESULT_WRONGDEVICE: return FAMICOM_RESULT_WRONGDEVICE; +#if VERSION == VER_GAEJ01_01 + case CARD_RESULT_BROKEN: +#endif case CARD_RESULT_ENCODING: return FAMICOM_RESULT_WRONGENCODING; case CARD_RESULT_NOCARD: diff --git a/src/static/Famicom/ks_nes_draw.cpp b/src/static/Famicom/ks_nes_draw.cpp index ca06d404..0b108e66 100644 --- a/src/static/Famicom/ks_nes_draw.cpp +++ b/src/static/Famicom/ks_nes_draw.cpp @@ -7,6 +7,7 @@ #include "dolphin/PPCArch.h" #include "_mem.h" #include "dolphin/os.h" +#include "ver.h" u8 ksNesPaletteNormal[] = { 0xc2, 0x10, 0x80, 0x17, 0x98, 0x17, 0xc0, 0x14, 0xdc, 0x0d, 0xd8, 0x03, 0xd8, 0x00, 0xc8, 0x80, 0xbc, 0xa0, 0x80, @@ -131,11 +132,11 @@ void ksNesDrawMakeBGIndTex(ksNesCommonWorkObj* wp, u32 mmc3) { tile_byte = nametable_p[((scanline_ctrl0 & 0xF8) << 2) + ((scanline_ctrl1 & 0xF8) >> 3)]; } - palette_bits = patternPtrBase[((u8)tile_byte >> 6) | ((wp->draw_ctx.ppu_scanline_regs[row].ppu_ctrl & KS_NES_PPU_CTRL_BG_PATTERN) >> 2)]; + palette_bits = patternPtrBase[((wp->draw_ctx.ppu_scanline_regs[row].ppu_ctrl >> 2) & 4) | ((u8)tile_byte >> 6)]; // issue is here - wp->draw_ctx.bg_tile_index_texture[(((col & 0x3C) * 8) + ((col & 3) * 2) + ((row >> 2) * 288) + ((row & 3) * 8)) + 0] = (((palette_bits & 1) << 6) | (tile_byte & 0x3F)) - (col & 1); - wp->draw_ctx.bg_tile_index_texture[(((col & 0x3C) * 8) + ((col & 3) * 2) + ((row >> 2) * 288) + ((row & 3) * 8)) + 1] = (palette_bits >> 1) ^ mask; + wp->draw_ctx.bg_tile_index_texture[(((col & 3) * 2) + ((col & 0x3C) * 8) + ((row >> 2) * 288) + ((row & 3) * 8)) + 0] = (((palette_bits & 1) << 6) | (tile_byte & 0x3F)) - (col & 1); + wp->draw_ctx.bg_tile_index_texture[(((col & 3) * 2) + ((col & 0x3C) * 8) + ((row >> 2) * 288) + ((row & 3) * 8)) + 1] = (palette_bits >> 1) ^ mask; if ((col & 1) != 0) { wp->draw_ctx.bg_palette_attr_texture[((col >> 1) & 3) + (col & 0x38) * 4 + ((row & 7) * 4 + (row >> 3) * 160)] = nibble_acc; @@ -150,18 +151,18 @@ void ksNesDrawMakeBGIndTex(ksNesCommonWorkObj* wp, u32 mmc3) { } void ksNesDrawMakeBGIndTexMMC5(ksNesCommonWorkObj* wp, ksNesStateObj* sp) { - u32 banks_mask = sp->chr_banks & 0x1FC; u32 row; u32 col; + u32 scanline_ctrl1; + u32 tile_byte; + u32 banks_mask = sp->chr_banks & 0x1FC; for (row = 8; row < 236; row++) { - u32 tile_byte; u32 scanline_ctrl0 = wp->draw_ctx.ppu_scanline_regs[row].vram_addr_y; - u32 scanline_ctrl1 = wp->draw_ctx.ppu_scanline_regs[row].vram_addr_coarse_x; + scanline_ctrl1 = wp->draw_ctx.ppu_scanline_regs[row].vram_addr_coarse_x; u32 nibble_acc; // @bug - uninitialized u8* patternPtrBase = (u8*)&wp->draw_ctx.ppu_scanline_regs[row].chr_bank_bg; u32 palette_bits; - u32 tmp; u8* nametable_p; for (col = 0; col < 34; col++) { @@ -177,11 +178,10 @@ void ksNesDrawMakeBGIndTexMMC5(ksNesCommonWorkObj* wp, ksNesStateObj* sp) { // issue in this area too probably if (wp->draw_ctx.ppu_scanline_regs[row].mmc5_ext_mode & 0x20) { // MMC5 extension ram - nibble_acc = (nibble_acc & 0xF0) | (sp->mmc5_extension_ram[((scanline_ctrl1 >> 3) & 0x1F) + ((scanline_ctrl0 & 0xF8) << 2)] >> 6) & 0x0F; + nibble_acc = ((sp->mmc5_extension_ram[((scanline_ctrl1 >> 3) & 0x1F) + ((scanline_ctrl0 & 0xF8) << 2)] >> 6) & 0x0F) | (nibble_acc & 0xF0); palette_bits = ((sp->mmc5_extension_ram[((scanline_ctrl1 >> 3) & 0x1F) + ((scanline_ctrl0 & 0xF8) << 2)] << 2) & banks_mask) | ((u8)tile_byte >> 6); } else { - tmp = ((wp->draw_ctx.ppu_scanline_regs[row].ppu_ctrl & 0x10) >> 2) | ((tile_byte >> 6) & 0x3); - palette_bits = ((wp->draw_ctx.ppu_scanline_regs[row].chr_bank_ext_upper_bg << (tmp + 1)) & 0x100) | (patternPtrBase[tmp]); + palette_bits = patternPtrBase[((wp->draw_ctx.ppu_scanline_regs[row].ppu_ctrl >> 2) & 4) | ((u8)tile_byte >> 6)] | ((wp->draw_ctx.ppu_scanline_regs[row].chr_bank_ext_upper_bg << ((((wp->draw_ctx.ppu_scanline_regs[row].ppu_ctrl >> 2) & 4) | ((u8)tile_byte >> 6)) + 1)) & 0x100); } // issue is here @@ -205,19 +205,28 @@ void ksNesDrawMakeBGIndTexMMC5(ksNesCommonWorkObj* wp, ksNesStateObj* sp) { void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj* wp, u32 default_bank) { u32 CHR_flag_xor = wp->chr_to_i8_buf_size <= CHR_TO_I8_BUF_SIZE ? (wp->chr_to_i8_buf_size >> 13) : 0x80; - u32 mmc2_bank = 0x02; // 0x02 = unset + ksNesCommonWorkObj* row_wp2; + u32 idx; + ksNesCommonWorkObj* row_wp; + u32 scanline_ctrl1; u32 row; u32 col; u32 i; int j; + u32 tile_byte; + u32 mask; + u32 nibble_acc; // @bug - uninitialized + u8* patternPtrBase; + u32 mmc2_bank = 0x02; // 0x02 = unset i = 239; do { - u32 scanline_ctrl1 = wp->draw_ctx.ppu_scanline_regs[i].vram_addr_coarse_x; - u32 idx = (wp->draw_ctx.ppu_scanline_regs[i].vram_addr_y & 0xF8) * 4; + row_wp = (ksNesCommonWorkObj*)((u8*)wp + i * sizeof(ksNesPPUScanlineState)); + idx = (row_wp->draw_ctx.ppu_scanline_regs[0].vram_addr_y & 0xF8) * 4; + u32 latch_ctrl = row_wp->draw_ctx.ppu_scanline_regs[0].vram_addr_coarse_x; for (j = 0; j < 34; j++) { - u32 val = (wp->draw_ctx.ppu_scanline_regs[i].nametable_ptrs[(scanline_ctrl1 >> 8) & 1] + ((scanline_ctrl1 >> 3) & 0x1F))[idx]; + u32 val = (row_wp->draw_ctx.ppu_scanline_regs[0].nametable_ptrs[(latch_ctrl >> 8) & 1] + ((latch_ctrl >> 3) & 0x1F))[idx]; if (val == ksNes_MMC2_LATCH_HI) { mmc2_bank = 0x00; @@ -225,7 +234,7 @@ void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj* wp, u32 default_bank) { mmc2_bank = 0x01; } - scanline_ctrl1 += 8; + latch_ctrl += 8; } } while (i-- != 0 && mmc2_bank == 0x02); @@ -234,12 +243,13 @@ void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj* wp, u32 default_bank) { mmc2_bank = default_bank; } - for (i = 0; i < 8; i++) { - u32 scanline_ctrl1 = wp->draw_ctx.ppu_scanline_regs[i].vram_addr_coarse_x; - u32 idx = (wp->draw_ctx.ppu_scanline_regs[i].vram_addr_y & 0xF8) * 4; + for (row = 0; row < 8; row++) { + row_wp2 = (ksNesCommonWorkObj*)((u8*)wp + row * sizeof(ksNesPPUScanlineState)); + idx = (row_wp2->draw_ctx.ppu_scanline_regs[0].vram_addr_y & 0xF8) * 4; + u32 latch_ctrl = row_wp2->draw_ctx.ppu_scanline_regs[0].vram_addr_coarse_x; for (j = 0; j < 34; j++) { - u32 val = (wp->draw_ctx.ppu_scanline_regs[i].nametable_ptrs[(scanline_ctrl1 >> 8) & 1] + ((scanline_ctrl1 >> 3) & 0x1F))[idx]; + u32 val = (row_wp2->draw_ctx.ppu_scanline_regs[0].nametable_ptrs[(latch_ctrl >> 8) & 1] + ((latch_ctrl >> 3) & 0x1F))[idx]; if (val == ksNes_MMC2_LATCH_HI) { mmc2_bank = 0x00; @@ -247,17 +257,14 @@ void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj* wp, u32 default_bank) { mmc2_bank = 0x01; } - scanline_ctrl1 += 8; + latch_ctrl += 8; } } - for (row = 8; row < 236; row++) { - u32 scanline_ctrl0 = wp->draw_ctx.ppu_scanline_regs[row].vram_addr_y; - u32 scanline_ctrl1 = wp->draw_ctx.ppu_scanline_regs[row].vram_addr_coarse_x; - u32 mask; - u32 nibble_acc; // @bug - uninitialized - u8* patternPtrBase = wp->draw_ctx.ppu_scanline_regs[row].chr_bank_sprite; - u32 tile_byte; + for (i = 8; i < 236; i++) { + u32 scanline_ctrl0 = wp->draw_ctx.ppu_scanline_regs[i].vram_addr_y; + scanline_ctrl1 = wp->draw_ctx.ppu_scanline_regs[i].vram_addr_coarse_x; + patternPtrBase = wp->draw_ctx.ppu_scanline_regs[i].chr_bank_sprite; u32 palette_bits; u32 dst_idx; u8* nametable_p; @@ -265,7 +272,7 @@ void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj* wp, u32 default_bank) { mask = mask = (scanline_ctrl0 & 0x04) ? CHR_flag_xor : 0; // bruh for (col = 0; col < 34; col++) { - nametable_p = wp->draw_ctx.ppu_scanline_regs[row].nametable_ptrs[((scanline_ctrl1 >> 8) & 1)]; + nametable_p = wp->draw_ctx.ppu_scanline_regs[i].nametable_ptrs[((scanline_ctrl1 >> 8) & 1)]; if (((s32)nametable_p) >= 0) { nibble_acc = (((u32)nametable_p) & 3) | (nibble_acc << 4); tile_byte = (((u32)nametable_p) >> 8) & 0xFF; @@ -274,7 +281,7 @@ void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj* wp, u32 default_bank) { tile_byte = nametable_p[((scanline_ctrl0 & 0xF8) << 2) + ((scanline_ctrl1 & 0xF8) >> 3)]; if (tile_byte == ksNes_MMC2_LATCH_HI) { - palette_bits = patternPtrBase[(mmc2_bank) | ((wp->draw_ctx.ppu_scanline_regs[row].ppu_ctrl & 0x10) >> 2)] | 0x03; + palette_bits = patternPtrBase[((wp->draw_ctx.ppu_scanline_regs[i].ppu_ctrl >> 2) & 4) | mmc2_bank] | 0x03; mmc2_bank = 0x00; goto set; } else if (tile_byte == ksNes_MMC2_LATCH_LO) { @@ -282,15 +289,15 @@ void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj* wp, u32 default_bank) { } } - palette_bits = ((u8)tile_byte >> 6) | patternPtrBase[((mmc2_bank) | ((wp->draw_ctx.ppu_scanline_regs[row].ppu_ctrl & 0x10) >> 2))]; + palette_bits = patternPtrBase[((wp->draw_ctx.ppu_scanline_regs[i].ppu_ctrl >> 2) & 4) | mmc2_bank] | ((u8)tile_byte >> 6); set: // issue is here - wp->draw_ctx.bg_tile_index_texture[(((col & 0x3C) * 8) + ((col & 3) * 2) + ((row >> 2) * 288) + ((row & 3) * 8)) + 0] = (((palette_bits & 1) << 6) | (tile_byte & 0x3F)) - (col & 1); - wp->draw_ctx.bg_tile_index_texture[(((col & 0x3C) * 8) + ((col & 3) * 2) + ((row >> 2) * 288) + ((row & 3) * 8)) + 1] = (palette_bits >> 1) ^ mask; + wp->draw_ctx.bg_tile_index_texture[(((col & 3) * 2) + ((col & 0x3C) * 8) + ((i >> 2) * 288) + ((i & 3) * 8)) + 0] = (((palette_bits & 1) << 6) | (tile_byte & 0x3F)) - (col & 1); + wp->draw_ctx.bg_tile_index_texture[(((col & 3) * 2) + ((col & 0x3C) * 8) + ((i >> 2) * 288) + ((i & 3) * 8)) + 1] = (palette_bits >> 1) ^ mask; if ((col & 1) != 0) { - wp->draw_ctx.bg_palette_attr_texture[((col >> 1) & 3) + (col & 0x38) * 4 + ((row & 7) * 4 + (row >> 3) * 160)] = nibble_acc; + wp->draw_ctx.bg_palette_attr_texture[((col >> 1) & 3) + (col & 0x38) * 4 + ((i & 7) * 4 + (i >> 3) * 160)] = nibble_acc; } scanline_ctrl1 += 8; @@ -301,35 +308,36 @@ void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj* wp, u32 default_bank) { DCFlushRangeNoSync(wp->draw_ctx.bg_palette_attr_texture, sizeof(wp->draw_ctx.bg_palette_attr_texture)); } +#define ksNesGetOAMEntry(wp, i) (((ksNesCommonWorkObj*)((u8*)(wp) + (i)))->draw_ctx.OAMTable[0]) + void ksNesDrawOBJSetupMMC2(ksNesCommonWorkObj* wp) { u32 i; u32 j; - u32 k; + u32 maxv; + u32 bank; - memset(wp->draw_ctx.mmc2_scanline_latch_tiles, 0, sizeof(wp->draw_ctx.mmc2_scanline_latch_tiles)); - for (i = 0; i < ARRAY_COUNT(wp->draw_ctx.OAMTable); i++) { + memset(wp->draw_ctx.mmc2_scanline_latch_tiles, 0, KS_NES_SCANLINE_COUNT * sizeof(u8)); + for (i = 0; i < ARRAY_COUNT(wp->draw_ctx.OAMTable) * sizeof(ksNesOAMEntry); i += sizeof(ksNesOAMEntry)) { // ppu_scanline_regs is the scanline state, OAMTable is list of scanline triggers? - if (wp->draw_ctx.OAMTable[i].y_pos >= 236 || (wp->draw_ctx.OAMTable[i].tile_index != ksNes_MMC2_LATCH_HI && wp->draw_ctx.OAMTable[i].tile_index != ksNes_MMC2_LATCH_LO)) { - continue; + if (ksNesGetOAMEntry(wp, i).y_pos < 236 && (ksNesGetOAMEntry(wp, i).tile_index == ksNes_MMC2_LATCH_HI || ksNesGetOAMEntry(wp, i).tile_index == ksNes_MMC2_LATCH_LO)) { + u32 j = ksNesGetOAMEntry(wp, i).y_pos; + u32 maxv = j + 8 + ((wp->draw_ctx.ppu_scanline_regs[j].ppu_ctrl & KS_NES_PPU_CTRL_SPRITE_SIZE) >> 5) * 8; + do { + wp->draw_ctx.mmc2_scanline_latch_tiles[j] = ksNesGetOAMEntry(wp, i).tile_index; + j++; + } while(j < maxv); } - - j = wp->draw_ctx.OAMTable[i].y_pos; - k = (((wp->draw_ctx.ppu_scanline_regs[j].ppu_ctrl >> 2) & 0x08) + 8) + j; - do { - wp->draw_ctx.mmc2_scanline_latch_tiles[j] = wp->draw_ctx.OAMTable[i].tile_index; - j++; - } while(j < k); } // _0200 is the scanline marker entries - for (i = 0, k = 0; i < ARRAY_COUNT(wp->draw_ctx.mmc2_scanline_latch_tiles); i++) { + for (i = 0, bank = 0; i < KS_NES_SCANLINE_COUNT; i++) { if (wp->draw_ctx.mmc2_scanline_latch_tiles[i] == ksNes_MMC2_LATCH_HI) { - k = 0; + bank = 0; } else if (wp->draw_ctx.mmc2_scanline_latch_tiles[i] == ksNes_MMC2_LATCH_LO) { - k = 1; + bank = 1; } - if (k) { + if (bank) { wp->draw_ctx.ppu_scanline_regs[i].chr_bank_sprite[0] = wp->draw_ctx.ppu_scanline_regs[i].chr_bank_sprite[1] - 1; wp->draw_ctx.ppu_scanline_regs[i].chr_bank_sprite[2] = wp->draw_ctx.ppu_scanline_regs[i].chr_bank_sprite[1] + 1; wp->draw_ctx.ppu_scanline_regs[i].chr_bank_sprite[3] = wp->draw_ctx.ppu_scanline_regs[i].chr_bank_sprite[1] + 2; @@ -353,10 +361,10 @@ void ksNesDrawBG(ksNesCommonWorkObj* wp, ksNesStateObj* sp) { GXTexObj obj2; u32 curline; u32 cnt; - u32 color; + u32 line; u32 x0; u32 x1; - s16 y; + u32 color; u32 i; u32 j; @@ -493,16 +501,14 @@ void ksNesDrawBG(ksNesCommonWorkObj* wp, ksNesStateObj* sp) { GXBegin(GX_LINES, GX_VTXFMT0, cnt); - for (i = 8; i < 236; i++) { - - if ((wp->draw_ctx.ppu_scanline_regs[i].ppumask_flags & KS_NES_PPU_MASK_SHOW_BG) == 0) { - s16 y = -0x81 - i; - u32 color = (wp->draw_ctx.ppu_scanline_regs[i].ppu_ctrl & 0xC0) << 24; + for (line = 8; line < 236; line++) { + if ((wp->draw_ctx.ppu_scanline_regs[line].ppumask_flags & KS_NES_PPU_MASK_SHOW_BG) == 0) { + color = (wp->draw_ctx.ppu_scanline_regs[line].ppu_ctrl & 0xC0) << 24; - GXPosition2s16(0x80, y); + GXPosition2s16(0x80, -0x81 - line); GXColor1u32(color); - GXPosition2s16(0x180, y); + GXPosition2s16(0x180, -0x81 - line); GXColor1u32(color); } } @@ -576,6 +582,9 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior // check the pass is for foreground sprites if (sprite_priority_pass == 0) { + u32 i; + u32 j; + for (i = 0; i < KS_NES_SCANLINE_SPRITE_OVERDRAW_COUNT; i++) { wp->draw_ctx.sprite_scanline_limit[i] = i < KS_NES_SCANLINE_COUNT ? ((state->frame_flags & KS_NES_FLAG_NINES_OVER_MODE) ? 255 : KS_NES_SPRITES_PER_SCANLINE) : 0; @@ -631,8 +640,8 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior for (j = 0; j < _j; j++) { u32 ypos = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + i))->y_pos; ypos += j; - if (wp->draw_ctx.sprite_scanline_limit[((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + i))->y_pos + j] != 0) { - wp->draw_ctx.sprite_scanline_limit[((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + i))->y_pos + j]--; + if ((*(&wp->draw_ctx.sprite_scanline_limit[((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + i))->y_pos] + j)) != 0) { + (*(&wp->draw_ctx.sprite_scanline_limit[((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + i))->y_pos] + j))--; if ((a & 2) == 0) { quad_p->y_and_v_pairs[a] = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + i))->y_pos + j; quad_p->y_and_v_pairs[a + 1] = b; @@ -667,8 +676,8 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior GXSetVtxDesc(GX_VA_TEX1, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_S, GX_U16, 10); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_TEX_S, GX_U16, 10); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U16, 10); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_TEX_ST, GX_U16, 10); GXInitTexObj(&GStack_7c, wp->chr_to_u8_bufp, 0x400, (u16)(size >> 10), GX_TF_I8, GX_MIRROR, GX_CLAMP, 0); GXInitTexObjLOD(&GStack_7c, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); GXLoadTexObj(&GStack_7c, GX_TEXMAP0); @@ -724,26 +733,38 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior GXSetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_ALWAYS, 0); - u32 n_verts = 0; - u32 idx2 = 0; - for (i = 0; i < ARRAY_COUNT(wp->draw_ctx.OAMTable); i++) { + u8* quad_pairs; + u32 s0, t1, t1_2; + u32 idx; + u32 y0, t0; + int color; + u32 x0, x1; + u32 s1; + u32 oam_attrs; + u32 tile_index, flags2; + union { u32 value; u16 half[2]; } temp; + u32 y1; + union { u32 value; u16 half[2]; } oam_offset; + u32 s1_2; + u32 idx2; + i = 0; + oam_offset.value = i; + for (; oam_offset.value < sizeof(wp->draw_ctx.OAMTable); oam_offset.value += sizeof(ksNesOAMEntry)) { // draw sprites - if (sprite_priority_pass == 0 || (((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx2))->attributes & KS_NES_OAM_ATTR_PRIORITY) != 0) { - n_verts += wp->draw_ctx.sprite_vertex_count[idx2 >> 2]; + if (sprite_priority_pass == 0 || (((u8*)wp)[oam_offset.value + offsetof(ksNesCommonWorkObj, draw_ctx.OAMTable) + offsetof(ksNesOAMEntry, attributes)] & KS_NES_OAM_ATTR_PRIORITY) != 0) { + i += wp->draw_ctx.sprite_vertex_count[oam_offset.value >> 2]; } - - idx2 += 4; } - u32 idx = 0x100-4; + idx = sizeof(wp->draw_ctx.OAMTable) - sizeof(ksNesOAMEntry); idx2 = ARRAY_COUNT(wp->draw_ctx.OAMTable) - 1; - GXBegin(GX_QUADS, GX_VTXFMT0, n_verts); + GXBegin(GX_QUADS, GX_VTXFMT0, i); while (TRUE) { // ksNesSpriteQuadData* quad_p = &wp->draw_ctx.sprite_quad_data[idx2]; // u32 scanline_idx = wp->draw_ctx.OAMTable[idx]; - u8* quad_pairs = ((ksNesSpriteQuadData*)((u8*)wp->draw_ctx.sprite_quad_data + (idx << 3)))->y_and_v_pairs; - u32 tile_index = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->tile_index; - u32 flags2; + quad_pairs = wp->draw_ctx.sprite_quad_data[idx2].y_and_v_pairs; + tile_index = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->tile_index; + if (wp->draw_ctx.ppu_scanline_regs[((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->y_pos].ppu_ctrl & KS_NES_PPU_CTRL_SPRITE_SIZE) { // 8x16 sprite @@ -755,10 +776,10 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior } // u32 flags3 = wp->draw_ctx.OAMTable[idx + 2]; - u32 oam_attrs = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->attributes; - u32 x0 = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->x_pos + 128; - u32 x1 = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->x_pos + 136; - u32 color = ((((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->x_pos & 3) * 16 + 4) * 0x01000000; + oam_attrs = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->attributes; + x0 = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->x_pos + 128; + x1 = ((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->x_pos + 136; + color = (((oam_attrs & KS_NES_OAM_ATTR_PALETTE_MASK) * 16 + 4) * 0x01000000); if (sprite_priority_pass != 0) { // We're in the BG pass so skip if the sprite is supposed to be drawn in front of the BG @@ -772,34 +793,26 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior } } - u32 s0; - u32 t0; - u32 s1; - u32 s1_2; - u32 t1; - u32 t1_2; - u32 temp; // u32 j; s0 = 0; t0 = (flags2 & 0xFE) * 2; // select chr bank offset - temp = ((tile_index & 0x3F) * 0x20) | ((flags2 & 0x01) * 0x800); // flags2 bit0 determines the pattern table + temp.value = ((tile_index & 0x3F) * 0x20) | ((flags2 & 0x01) * 0x800); // flags2 bit0 determines the pattern table if (((ksNesOAMEntry*)((u8*)wp->draw_ctx.OAMTable + idx))->attributes & KS_NES_OAM_ATTR_FLIP_HORIZONTAL) { - s1 = temp + 32; - s1_2 = temp; + s1 = temp.value + 32; + s1_2 = temp.value; } else { - s1 = temp; - s1_2 = temp + 32; + s1 = temp.value; + s1_2 = temp.value + 32; } for (j = 0; j < wp->draw_ctx.sprite_vertex_count[idx >> 2]; j += 4) { - u32 y0 = -129 - quad_pairs[0]; + y0 = -129 - quad_pairs[0]; t1 = quad_pairs[1]; - u32 y1 = -129 - quad_pairs[2]; + y1 = -129 - quad_pairs[2]; t1_2 = quad_pairs[3]; - quad_pairs += 4; GXPosition2s16(x0, y0); GXColor1u32(color); GXTexCoord2u16(s0, t0); @@ -819,6 +832,8 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior GXColor1u32(color); GXTexCoord2u16(s0, t0); GXTexCoord2u16(s1, t1_2); + + quad_pairs += 4; } @@ -828,7 +843,7 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior } idx -= 4; - // idx2--; + idx2--; } GXEnd(); @@ -855,7 +870,7 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior GXBegin(GX_QUADS, GX_VTXFMT0, n * 2); for (u32 i = 0; i < n; i += 2) { - s16 x1 = (wp->draw_ctx.ppu_scanline_regs[wp->draw_ctx.scanline_y_coords[i]].ppumask_flags & KS_NES_PPU_MASK_SPRITES_COMBINED) == KS_NES_PPU_MASK_SHOW_SPRITES ? 136 : 384; + int x1 = (wp->draw_ctx.ppu_scanline_regs[wp->draw_ctx.scanline_y_coords[i]].ppumask_flags & KS_NES_PPU_MASK_SPRITES_COMBINED) == KS_NES_PPU_MASK_SHOW_SPRITES ? 136 : 384; GXPosition2s16(128, -128 - wp->draw_ctx.scanline_y_coords[i]); GXColor1u32(0x00000000); @@ -871,7 +886,6 @@ void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 sprite_prior } } -#define ksNesGetOAMEntry(wp, i) (((ksNesCommonWorkObj*)((u8*)(wp) + (i)))->draw_ctx.OAMTable[0]) void ksNesDrawOBJMMC5(ksNesCommonWorkObj* wp, ksNesStateObj* sp, u32 sprite_priority_pass) { GXTexObj obj3; @@ -1196,6 +1210,7 @@ void ksNesDrawOBJI8ToEFB(ksNesCommonWorkObj* wp, u8* buf) { GXEnd(); } +#pragma opt_dead_assignments off void ksNesDrawEmuResult(ksNesCommonWorkObj* wp) { static f32 indtexmtx[2][3] = { { 0.5f, 0.0f, 0.0f }, @@ -1211,8 +1226,8 @@ void ksNesDrawEmuResult(ksNesCommonWorkObj* wp) { u32 color_effects_state; u8 y; u32 val; - u32 clr; ksNesScanlineYCoords* scanline_y_coords; + u32 clr; GXTexObj obj; GXTexObj obj2; @@ -1242,7 +1257,7 @@ void ksNesDrawEmuResult(ksNesCommonWorkObj* wp) { GXInitTexObjLOD(&obj, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); GXLoadTexObj(&obj, GX_TEXMAP0); - GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 60, GX_FALSE, 125); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 60); GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_TRUE, 256, 256); GXSetTexCoordBias(GX_TEXCOORD0, 0, 0); @@ -1298,6 +1313,8 @@ void ksNesDrawEmuResult(ksNesCommonWorkObj* wp) { GXTexCoord2u16(0, scanline_y_coords->top); } } while (i != 0); + + GXEnd(); } // Count grayscale scanlines @@ -1404,6 +1421,8 @@ void ksNesDrawEmuResult(ksNesCommonWorkObj* wp) { GXTexCoord2u16(0, scanline_y_coords->top); } } while (i != 0); + + GXEnd(); } GXSetTexCopySrc(KS_NES_CENTER_X, KS_NES_CENTER_Y, KS_NES_WIDTH, KS_NES_HEIGHT); @@ -1412,6 +1431,7 @@ void ksNesDrawEmuResult(ksNesCommonWorkObj* wp) { GXCopyTex(wp->result_bufp, GX_FALSE); GXPixModeSync(); } +#pragma opt_dead_assignments reset void ksNesDraw(ksNesCommonWorkObj* wp, ksNesStateObj* state) { ksNesDrawInit(wp); @@ -1436,6 +1456,9 @@ void ksNesDraw(ksNesCommonWorkObj* wp, ksNesStateObj* state) { } else { ksNesDrawOBJ(wp, state, 1); } +#if VERSION == VER_GAEJ01_01 + GXPixModeSync(); +#endif ksNesDrawBG(wp, state); ksNesDrawOBJI8ToEFB(wp, wp->result_bufp); diff --git a/src/static/jaudio_PP/game/emusound.c b/src/static/jaudio_PP/game/emusound.c index 7b5d28ab..5b3697e5 100644 --- a/src/static/jaudio_PP/game/emusound.c +++ b/src/static/jaudio_PP/game/emusound.c @@ -418,1588 +418,13 @@ u8 VOLTABLE_VRCPULSE[] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f }; -s32 __GetWave_Pulse(s32 a, s32 b) { - switch (a) { - - case 0: { - if (b >= 4 && b <= 7) { - return 1; - } else { - return 0; - } - } - case 1: { - return b <= 7; - } - case 2: { - return b <= 15; - } - case 3: { - return b > 7; - } - case 0xb: { - return b & 0xff; - } - case 0xc: { - return b <= 0 ? 127 : 0; - } - case 0xd: { - return b <= 1 ? 127 : 0; - } - case 0xe: { - return b <= 2 ? 127 : 0; - } - case 0xf: { - return b <= 3 ? 127 : 0; - } - case 0x10: { - return b <= 4 ? 127 : 0; - } - case 0x11: { - return b <= 5 ? 0 : 127; - } - case 0x12: { - return b <= 6 ? 0 : 127; - } - case 0x13: { - return b <= 7 ? 0 : 127; - } - } - return a; -} - -u32 __PitchTo32_VRC_C(u16 pitch) { - f32 scalefactor = 2.f; - return (u32)((NES_CLOCK_SPEED - 0.25f) / scalefactor / (pitch + 1) / 1000.875f * 32768.f); -} - -u32 __PitchTo32_VRC_PULSE(u16 pitch) { - f32 scalefactor = 16.f; - return (u32)((NES_CLOCK_SPEED - 0.25f) / scalefactor / (pitch + 1) / 1000.875f * 32768.f); -} - -u32 __PitchTo32_HVC(u16 pitch) { - f32 scalefactor = 8.f; - return (u32)((NES_CLOCK_SPEED - 0.25f) / scalefactor / (pitch + 1) / 1000.875f * 32768.f); -} - -void __Sound_Write_VRC(u16 a, u8 b) { - NESSoundStruct* pSound; - Unknown_VRC* pBuffer; - int v; - int xyzIndex; - - u16 index = a - 0xc0; - if (index <= 3) { - pSound = &SoundX; - xyzIndex = 0; - pBuffer = &sbuffer.apu._C0; - } else if (index <= 7) { - pSound = &SoundY; - xyzIndex = 1; - pBuffer = &sbuffer.apu._C4; - } else { - pSound = &SoundZ; - xyzIndex = 2; - pBuffer = &sbuffer.apu._C8; - } - - if (index == 21) { - if (!(b & 1)) { - SoundX._00 = 0; - } - if (!(b & 2)) { - SoundY._00 = 0; - } - if (!(b & 4)) { - SoundZ._00 = 0; - } - return; - } - - switch (index & 3) { - case 0: { - pSound->_3C = pBuffer->_0_6; - pSound->_28 = pBuffer->_0_7; - pSound->_1C = VOLTABLE_VRCPULSE[pBuffer->_0_3]; - pSound->_1D = pBuffer->_0_3; - pSound->_2A = pSound->_1D; - if (xyzIndex == 2) { - pSound->_24 = ((pSound->_3C & 3) << 4) | pSound->_2A; - pSound->_1C = (pSound->_24 * 7) / 3; - if (pSound->_1C >= 0x7f) { - pSound->_1C = 0x7f; - } - } - } break; - case 2: { - pSound->_0C = (pBuffer->_3_3 << 8) | pBuffer->_2; - if (xyzIndex == 2) { - pSound->_08 = __PitchTo32_VRC_C(pSound->_0C); - } else { - pSound->_08 = __PitchTo32_VRC_PULSE(pSound->_0C); - } - } break; - case 3: { - pSound->_0C = (pBuffer->_3_3 << 8) | pBuffer->_2; - if (xyzIndex == 2) { - pSound->_08 = __PitchTo32_VRC_C(pSound->_0C); - } else { - pSound->_08 = __PitchTo32_VRC_PULSE(pSound->_0C); - } - - if (!pSound->_00 && !pSound->_3E) { - pSound->_04 = 0; - } - - if (xyzIndex == 0) { - v = sbuffer.apu._D5_0; - } - if (xyzIndex == 1) { - v = sbuffer.apu._D5_1; - } - if (xyzIndex == 2) { - v = sbuffer.apu._D5_2; - } - - if ((u8)v == 1 && pBuffer->_3_7) { - pSound->_00 = 1; - } else { - pSound->_00 = 0; - } - - pSound->_2A = pSound->_1D; - pSound->_20 = 0; - } break; - } -} - -void __Sound_Write_MMC5(u16 a, u8 b) { - NESSoundStruct* pSound; - PulseChannel* pBuffer; - u32 v; - int xyzIndex; - - u16 index = a - 0xc0; - pBuffer = 0; - if (index <= 3) { - pSound = &SoundX; - xyzIndex = 0; - pBuffer = (PulseChannel*)&sbuffer.apu._C0; - } else if (index <= 7) { - pSound = &SoundY; - xyzIndex = 1; - pBuffer = (PulseChannel*)&sbuffer.apu._C4; - } - - if (index == 17) { - SoundZ._3E = (b & 0xff) << 6; - } else if (index == 21) { - if (!(b & 1)) { - SoundX._00 = 0; - } - if (!(b & 2)) { - SoundY._00 = 0; - } - } else if (pBuffer) { - switch (index & 3) { - case 0: { - pSound->_3C = pBuffer->Duty; - v = pSound->_28; - pSound->_28 = pBuffer->ConstantVolume ^ 1; - pSound->_14 = pBuffer->EnvelopeLoopCounter; - pSound->_1D = VOLTABLE_HVCPULSE[pBuffer->EnvelopePeriod_Volume]; - if (pSound->_28 == 0 && pSound->_00 == 1) { - pSound->_1C = VOLTABLE_HVCPULSE[pBuffer->EnvelopePeriod_Volume]; - } else { - pSound->_24 = PHASE_SAMPLE * (pBuffer->EnvelopePeriod_Volume + 1); - if (v == 0) { - pSound->_2A = 0xf; - pSound->_20 = 0; - } - } - } break; - case 2: { - pSound->_0C = pBuffer->TimerHigh << 8 | pBuffer->TimerLow; - pSound->_08 = __PitchTo32_HVC(pSound->_0C); - } break; - case 3: { - pSound->_0C = pBuffer->TimerHigh << 8 | pBuffer->TimerLow; - pSound->_08 = __PitchTo32_HVC(pSound->_0C); - pSound->_18 = LEN_TABLE_HVC[pBuffer->LengthCounterLow]; - pSound->_10 = FRAME_SAMPLE * pSound->_18; - if (!pSound->_00 && !pSound->_3E) { - pSound->_04 = 0; - } - - if (xyzIndex == 0) { - v = sbuffer.apu._D5_0; - } - if (xyzIndex == 1) { - v = sbuffer.apu._D5_1; - } - - if ((v & 0xff) != 0) { - pSound->_00 = 1; - } - - if (pBuffer->ConstantVolume == 0) { - pSound->_1C = VOLTABLE_HVCPULSE[15]; - } else { - pSound->_1C = pSound->_1D; - } - - pSound->_2A = 0xf; - pSound->_20 = 0; - pSound->_30 = 0; - pSound->_3A = 0; - } break; - } - } -} - -void __Sound_Write_A(u16 a, u8 b) { - switch (a) { - case 0: { - SoundA._3C = sbuffer.apu.Pulse1.Duty; - u32 v = SoundA._28; - SoundA._28 = sbuffer.apu.Pulse1.ConstantVolume ^ 1; - SoundA._14 = sbuffer.apu.Pulse1.EnvelopeLoopCounter; - if (!SoundA._28) { - SoundA._2C = sbuffer.apu.Pulse1.EnvelopePeriod_Volume << 8; - } else { - SoundA._24 = sbuffer.apu.Pulse1.EnvelopePeriod_Volume + 1; - if (!v && SoundA._00) { - SoundA._2C = 0xf00; - SoundA._20 = 0; - } - } - } break; - case 1: { - SoundA._34 = (sbuffer.apu.Pulse1.SweepUnitPeriod + 1) << 1; - SoundA._39 = sbuffer.apu.Pulse1.SweepUnitNegative; - SoundA._38 = sbuffer.apu.Pulse1.SweepUnitShiftCount; - SoundA._30 = 0; - SoundA._3B = 0; - SoundA._3A = sbuffer.apu.Pulse1.SweepUnitEnabled; - } break; - case 2: { - SoundA._0C = SoundA._0C & 0xf00 | sbuffer.apu.Pulse1.TimerLow; - SoundA._08 = __PitchTo32_HVC(SoundA._0C); - } break; - case 3: { - SoundA._0C = (sbuffer.apu.Pulse1.TimerHigh << 8) | sbuffer.apu.Pulse1.TimerLow; - SoundA._08 = __PitchTo32_HVC(SoundA._0C); - SoundA._18 = LEN_TABLE_HVC[sbuffer.apu.Pulse1.LengthCounterLow]; - SoundA._10 = SoundA._18 << 2; - SoundA._04 = 0; - SoundA._48 = 0; - SoundA._3E = 0; - SoundA._2A = 0; - if (sbuffer.apu.Pulse1Status) { - SoundA._00 = 1; - } - if (!sbuffer.apu.Pulse1.ConstantVolume) { - SoundA._2C = 0xf00; - } else { - SoundA._2C = sbuffer.apu.Pulse1.EnvelopePeriod_Volume << 8; - } - SoundA._20 = 0; - SoundA._30 = 0; - SoundA._3B = 0; - SoundA._3A = sbuffer.apu.Pulse1.SweepUnitEnabled; - } break; - } -} - -int __ProcessSoundA() { - if (SoundA._3A) { - if (PHASE_SYNC_FLAG) { - SoundA._30++; - if (SoundA._30 % SoundA._34 == 0) { - SoundA._3B |= 1; - } - } - - if (SoundA._3B == 3) { - SoundA._3B = 0; - u32 c = SoundA._0C; - u16 j = SoundA._0C >> SoundA._38; - if (!SoundA._38) { - j = 0; - } - switch (SoundA._39) { - case 0: { - SoundA._0C = SoundA._0C + j; - } break; - case 1: { - if (!SoundA._38) { - j = 0; - } - j = SoundA._0C - j; - SoundA._0C = j; - if (j && SoundA._38) { - SoundA._0C--; - } - } break; - } - if (SoundA._0C >= 0x800) { - SoundA._0C = 0x800; - } else { - SoundA._08 = __PitchTo32_HVC(SoundA._0C); - } - } - } - - if (!SoundA._00 && !SoundA._3E) { - return 0; - } - - if (SoundA._28 && PHASE_SYNC_FLAG) { - SoundA._20++; - if ((SoundA._20 % SoundA._24) == 0) { - switch (SoundA._14) { - case 0: { - if (SoundA._2C) { - SoundA._2C -= 0x100; - } else { - SoundA._00 = 0; - } - } break; - case 1: { - if (SoundA._2C) { - SoundA._2C -= 0x100; - } else { - SoundA._2C = 0xf00; - } - } break; - } - } - } - - if (SoundA._14 == 0) { - if (PHASE_SYNC_FLAG && SoundA._10) { - SoundA._10--; - } - if (SoundA._10 == 0) { - SoundA._00 = 0; - } - } - - if (SoundA._0C <= 7) { - SoundA._44 = 1; - } else if (SoundA._0C >= 0x800) { - SoundA._44 = 1; - } else { - SoundA._44 = 0; - } - - s8 c = __GetWave_Pulse(SoundA._3C, SoundA._04p._04_hi); - - if (SoundA._44) { - SoundA._04 += SoundA._40; - } else { - SoundA._04 += SoundA._08; - SoundA._40 = SoundA._08; - } - - if (SoundA._04 & 0xffe00000) { - SoundA._3B |= 2; - } - - SoundA._04 &= 0x1fffff; - if (SoundA._44 == 1 || !SoundA._00) { - if (SoundA._3E) { - SoundA._3E--; - } - } else { - if (SoundA._3E < 0x20) { - SoundA._3E++; - } - if (SoundA._3E < 0x20) { - SoundA._3E++; - } - } - - u32 _2a_6 = SoundA._2A >> 8 & 0xff; - f32 f_2a = (SoundA._2A & 0xff) / 256.f; - f32 param0 = VOLTABLE_HVCPULSE[_2a_6]; - f32 param1 = VOLTABLE_HVCPULSE[_2a_6 + 1]; - f32 f_sum = param0 * (1.f - f_2a) + param1 * f_2a; - - if (SoundA._2A != SoundA._2C) { - if (SoundA._2A > SoundA._2C) { - u16 diff = (SoundA._2A - SoundA._2C) >> 4; - if (!diff) { - SoundA._2A = SoundA._2C; - } else { - SoundA._2A -= diff; - } - } else if (SoundA._2A < SoundA._2C) { - u16 diff = (SoundA._2C - SoundA._2A) >> 4; - if (!diff) { - SoundA._2A = SoundA._2C; - } else { - SoundA._2A += diff; - } - } - } - - switch (c) { - case 0: { - // almost 1. / 15.6 - f_sum = -0.064103; - } break; - case 1: { - f_sum = -0.064103 + f_sum; - } break; - } - - s16 t = f_sum * 4096.f; - - t = (t * SoundA._3E) >> 5; - return t; -} - -void __Sound_Write_B(u16 a, u8 b) { - a -= 4; - switch (a) { - case 0: { - SoundB._3C = sbuffer.apu.Pulse2.Duty; - u32 v = SoundB._28; - SoundB._28 = sbuffer.apu.Pulse2.ConstantVolume ^ 1; - SoundB._14 = sbuffer.apu.Pulse2.EnvelopeLoopCounter; - if (!SoundB._28) { - SoundB._2C = sbuffer.apu.Pulse2.EnvelopePeriod_Volume << 8; - } else { - SoundB._24 = sbuffer.apu.Pulse2.EnvelopePeriod_Volume + 1; - if (!v && SoundB._00) { - SoundB._2C = 0xf00; - SoundB._20 = 0; - } - } - } break; - case 1: { - SoundB._34 = (sbuffer.apu.Pulse2.SweepUnitPeriod + 1) << 1; - SoundB._39 = sbuffer.apu.Pulse2.SweepUnitNegative; - SoundB._38 = sbuffer.apu.Pulse2.SweepUnitShiftCount; - SoundB._30 = 0; - SoundB._3B = 0; - SoundB._3A = sbuffer.apu.Pulse2.SweepUnitEnabled; - } break; - case 2: { - SoundB._0C = SoundB._0C & 0xf00 | sbuffer.apu.Pulse2.TimerLow; - SoundB._08 = __PitchTo32_HVC(SoundB._0C); - } break; - case 3: { - SoundB._0C = (sbuffer.apu.Pulse2.TimerHigh << 8) | sbuffer.apu.Pulse2.TimerLow; - SoundB._08 = __PitchTo32_HVC(SoundB._0C); - SoundB._18 = LEN_TABLE_HVC[sbuffer.apu.Pulse2.LengthCounterLow]; - SoundB._10 = SoundB._18 << 2; - SoundB._04 = 0; - SoundB._48 = 0; - SoundB._3E = 0; - SoundB._2A = 0; - if (sbuffer.apu.Pulse2Status) { - SoundB._00 = 1; - } - if (!sbuffer.apu.Pulse2.ConstantVolume) { - SoundB._2C = 0xf00; - } else { - SoundB._2C = sbuffer.apu.Pulse2.EnvelopePeriod_Volume << 8; - } - SoundB._20 = 0; - SoundB._30 = 0; - SoundB._3B = 0; - SoundB._3A = sbuffer.apu.Pulse2.SweepUnitEnabled; - } break; - } -} - -int __ProcessSoundB() { - if (SoundB._3A) { - if (PHASE_SYNC_FLAG) { - SoundB._30++; - if (SoundB._30 % SoundB._34 == 0) { - SoundB._3B |= 1; - } - } - - if (SoundB._3B == 3) { - SoundB._3B = 0; - u32 c = SoundB._0C; - u16 j = SoundB._0C >> SoundB._38; - if (!SoundB._38) { - j = 0; - } - switch (SoundB._39) { - case 0: { - SoundB._0C = SoundB._0C + j; - } break; - case 1: { - if (!SoundB._38) { - j = 0; - } - - SoundB._0C = SoundB._0C - j; - } break; - } - if (SoundB._0C >= 0x800) { - SoundB._0C = 0x800; - } else { - SoundB._08 = __PitchTo32_HVC(SoundB._0C); - } - } - } - - if (!SoundB._00 && !SoundB._3E) { - return 0; - } - - if (SoundB._28 && PHASE_SYNC_FLAG) { - SoundB._20++; - if ((SoundB._20 % SoundB._24) == 0) { - switch (SoundB._14) { - case 0: { - if (SoundB._2C) { - SoundB._2C -= 0x100; - } else { - SoundB._00 = 0; - } - } break; - case 1: { - if (SoundB._2C) { - SoundB._2C -= 0x100; - } else { - SoundB._2C = 0xf00; - } - } break; - } - } - } - - if (SoundB._14 == 0) { - if (PHASE_SYNC_FLAG && SoundB._10) { - SoundB._10--; - } - if (SoundB._10 == 0) { - SoundB._00 = 0; - } - } - - if (SoundB._0C <= 7) { - SoundB._44 = 1; - } else if (SoundB._0C >= 0x800) { - SoundB._44 = 1; - } else { - SoundB._44 = 0; - } - - s8 c = __GetWave_Pulse(SoundB._3C, SoundB._04p._04_hi); - - if (SoundB._44) { - SoundB._04 += SoundB._40; - } else { - SoundB._04 += SoundB._08; - SoundB._40 = SoundB._08; - } - - if (SoundB._04 & 0xffe00000) { - SoundB._3B |= 2; - } - - SoundB._04 &= 0x1fffff; - if (SoundB._44 == 1 || !SoundB._00) { - if (SoundB._3E) { - SoundB._3E--; - } - } else { - if (SoundB._3E < 0x20) { - SoundB._3E++; - } - if (SoundB._3E < 0x20) { - SoundB._3E++; - } - } - - u32 _2a_6 = SoundB._2A >> 8 & 0xff; - f32 f_2a = (SoundB._2A & 0xff) / 256.f; - f32 param0 = VOLTABLE_HVCPULSE[_2a_6]; - f32 param1 = VOLTABLE_HVCPULSE[_2a_6 + 1]; - f32 f_sum = param0 * (1.f - f_2a) + param1 * f_2a; - - if (SoundB._2A != SoundB._2C) { - if (SoundB._2A > SoundB._2C) { - u16 diff = (SoundB._2A - SoundB._2C) >> 4; - if (!diff) { - SoundB._2A = SoundB._2C; - } else { - SoundB._2A -= diff; - } - } else if (SoundB._2A < SoundB._2C) { - u16 diff = (SoundB._2C - SoundB._2A) >> 4; - if (!diff) { - SoundB._2A = SoundB._2C; - } else { - SoundB._2A += diff; - } - } - } - - switch (c) { - case 0: { - // almost 1. / 15.6 - f_sum = -0.064103; - } break; - case 1: { - f_sum = -0.064103 + f_sum; - } break; - } - - s16 t = f_sum * 4096.f; - - t = (t * SoundB._3E) >> 5; - return t; -} - -int __PitchTo32_HVC_D(u16 a) { - return NOISE_TABLE[a]; -} - -void __Sound_Write_D(u16 a, u8 b) { - switch (a) { - case 0xc: { - u32 v = SoundD._28; - SoundD._28 = sbuffer.apu.Noise.ConstantVolume ^ 1; - SoundD._14 = sbuffer.apu.Noise.LoopEnvelope; - SoundD._1D = (u8)(16.f * VOLTABLE_HVCPULSE[sbuffer.apu.Noise.EnvelopePeriod_Volume]); - if (!SoundD._28) { - SoundD._1C = SoundD._1D; - } else { - SoundD._24 = sbuffer.apu.Noise.EnvelopePeriod_Volume + 1; - if (!v) { - SoundD._2A = 0xf; - SoundD._20 = 0; - } - } - } break; - case 0xe: { - SoundD._0C = sbuffer.apu.Noise.Period; - if (sbuffer.apu.Noise.LoopNoise == 1u) { - SoundD._0C += 0x10; - NOISE_SHIFT = 0x40; - NOISE_MASTER = 1; - } else { - - NOISE_SHIFT = 0x4000; - } - NOISE_PULSE = NOISE_PULSE_TABLE[SoundD._0C & 0xf]; - SoundD._08 = __PitchTo32_HVC_D(SoundD._0C & 0xf); - } break; - case 0xf: { - SoundD._0C = sbuffer.apu.Noise.Period; - if (sbuffer.apu.Noise.LoopNoise == 1u) { - SoundD._0C += 0x10; - NOISE_SHIFT = 0x40; - NOISE_MASTER = 1; - } else { - NOISE_SHIFT = 0x4000; - } - NOISE_PULSE = NOISE_PULSE_TABLE[SoundD._0C % 16u]; - SoundD._08 = __PitchTo32_HVC_D(SoundD._0C % 16u); - SoundD._18 = LEN_TABLE_HVC[sbuffer.apu.Noise.LengthCounterLoad]; - SoundD._10 = SoundD._18 * 4; - if (sbuffer.apu.NoiseStatus != 0) { - SoundD._00 = '\x01'; - } - if (sbuffer.apu.Noise.ConstantVolume == 0) { - SoundD._1C = (u8)(16.f * VOLTABLE_HVCPULSE[15]); - } else { - SoundD._1C = SoundD._1D; - } - SoundD._2A = 0xf; - SoundD._20 = 0; - } break; - } -} - -s8 __GetNoise(u32 a) { - static u8 data = 0; - - for (int i = 0; i < a >> 16; i++) { - data = NOISE_MASTER & 3; - switch (data) { - case 0: - case 3: { - NOISE_MASTER = (NOISE_MASTER >> 1) | NOISE_SHIFT; - } break; - case 1: - case 2: { - NOISE_MASTER >>= 1; - } break; - } - } - - if (NOISE_MASTER & 1) { - return (s32)NOISE_PULSE; - } else { - return -(s32)NOISE_PULSE; - } -} - -volatile u32 delta_counter; -volatile s8 delta_sign; -volatile s32 bias_move; -volatile s32 bias; -volatile f32 voltage; -volatile f32 voltage_out; - -int __ProcessSoundD() { - s16 ret; - if (!SoundD._00) { - if (!SoundD._3E) { - return 0; - } - SoundD._3E--; - SoundD._1C = SoundD._3E; - } - SoundD._04 += SoundD._08; - ret = __GetNoise(SoundD._04); - ret *= SoundD._1C; - SoundD._04p._04_hi = 0; - SoundD._3E = SoundD._1C; - - if (SoundD._28 && PHASE_SYNC_FLAG) { - SoundD._20++; - if (SoundD._20 % SoundD._24 == 0) { - switch (SoundD._14) { - case 0: { - if (SoundD._2A) { - SoundD._2A--; - } else { - SoundD._00 = 0; - } - } break; - case 1: { - if (SoundD._2A) { - SoundD._2A--; - } else { - SoundD._2A = 0xf; - } - } break; - } - SoundD._1C = (u8)(16.f * VOLTABLE_HVCPULSE[SoundD._2A]); - } - } - - if (!SoundD._14) { - if (PHASE_SYNC_FLAG && SoundD._10) { - SoundD._10--; - } - if (!SoundD._10) { - SoundD._00 = 0; - } - } - return ret; -} - -void MoveDeltaCounter(u8 a) { - if (a) { - delta_counter++; - delta_sign++; - } else { - delta_counter--; - delta_sign--; - } -} - -void MoveBias() { - s32 b_move; - s32 diff; - s32 sign = delta_sign; - s32 oldBias = bias; - bias = oldBias + sign * 2; - if (bias > 0x7f) { - bias = 0x7f; - } - if (bias < 0) { - bias = 0; - } - - diff = bias - oldBias; - b_move = bias_move; - bias_move = b_move + diff; - delta_sign = 0; -} - -void WriteBias(u16 a) { - bias_move = (s16)a - (s16)bias; - bias = a; -} - -int MoveVoltage() { - voltage = 0.9994586f * voltage; - voltage += bias_move; - bias_move = 0; - if (voltage > 127.f) { - voltage = 127.f; - } - if (voltage < -127.f) { - voltage = -127.f; - } - voltage_out += (voltage - voltage_out) / 4.f; - - return (int)(216.f * voltage_out); -} - -u32 __PitchTo32_HVC_E(u16 a) { - return DMOD_TABLE[a]; -} - -void __Sound_Write_E(u16 a, u8 b) { - switch (a) { - case 0x10: { - SoundE._08 = __PitchTo32_HVC_E(sbuffer.apu.DMC.FrequencyIndex); - } break; - case 0x11: { - SoundE._1E = sbuffer.apu.DMC.DirectLoad; - WriteBias(SoundE._1E); - } break; - case 0x12: { - SoundE._18 = sbuffer.apu.DMC.SampleAddress << 6; - } break; - case 0x13: { - SoundE._10 = sbuffer.apu.DMC.SampleLength << 4; - } break; - } -} - -void StartE() { - SoundE._00 = 1; - SoundE._14 = (SoundE._10 + 1) * 8; - SoundE._04 = 0; - SoundE._1A = 0; - SoundE._20 = 0; - delta_counter = 0; - bias_move = 0; -} - -int __ProcessSoundE() { - if (SoundE._00) { - for (int i = 0; i < 2u; i++) { - SoundE._04 += SoundE._08; - if (SoundE._04p._04_hi != SoundE._1A) { - u32 vv = SoundE._1A & 7; - u32 offset = (SoundE._1A >> 3 & 0x1fff); - if (!vv) { - if (SoundE._18 + offset < 0x2000) { - SoundE._1C = ROM_TOP_C000[SoundE._18 + offset]; - } else { - SoundE._1C = ROM_TOP_E000[SoundE._18 + offset - 0x2000]; - } - } - MoveDeltaCounter((SoundE._1C << vv) & 0x80); - SoundE._1A = SoundE._04p._04_hi; - if (SoundE._14) { - SoundE._14--; - } - if (!SoundE._14) { - switch (sbuffer.apu.DMC.LoopSample) { - case 0: { - SoundE._00 = 0; - if (sbuffer.apu.DMC.IRQEnable == 1) { - SoundE._20 = 1; - } - } break; - case 1: { - SoundE._14 = (SoundE._10 + 1) * 8; - SoundE._04p._04_hi = 0; - SoundE._1A = 0; - } break; - } - } - } - } - } - MoveBias(); - return MoveVoltage(); -} - -s8 __GetWave_Triangle(s32 a) { - return TRIANGLE_TABLE[a]; -} - -u32 __PitchTo32_HVC_C(u16 a) { - u32 pitch; - if (a == 0) { - return 0; - } else { - f32 scalefactor = 16.f; - return (u32)((NES_CLOCK_SPEED - 0.25f) / scalefactor / (a + 1) / 1000.875f * 32768.f); - } -} -u32 sample_timer = 0; -u32 abs_timer = 0; - -void __Sound_Write_C(u16 a, u8 b) { - switch (a) { - case 0x8: { - u8 v = SoundC._14; - if (sbuffer.apu.Triangle.LinearCounterReloadVaue) { - SoundC._24 = sbuffer.apu.Triangle.LinearCounterReloadVaue + 1; - } else { - SoundC._24 = 0; - } - - if (SoundC._00 && SoundC._4A) { - SoundC._14 = sbuffer.apu.Triangle.LengthCounter; - SoundC._20 = SoundC._24; - } else if (SoundC._00) { - if (v && !sbuffer.apu.Triangle.LengthCounter) { - SoundC._14 = sbuffer.apu.Triangle.LengthCounter; - SoundC._20 = SoundC._24; - SoundC._4A = 0x80; - } else if (v) { - SoundC._20 = SoundC._24; - } - } else if (SoundC._4A) { - SoundC._14 = sbuffer.apu.Triangle.LengthCounter; - SoundC._20 = SoundC._24; - if (sbuffer.apu.TriangleStatus) { - SoundC._00 = 1; - } - } - - if (!sbuffer.apu.Triangle.LinearCounterReloadVaue && !SoundC._14) { - SoundC._00 = 0; - } - } break; - case 0xa: { - SoundC._0C = (sbuffer.apu.Triangle.TimerHigh << 8) | sbuffer.apu.Triangle.TimerLow; - SoundC._08 = __PitchTo32_HVC_C(SoundC._0C); - } break; - case 0xb: { - sample_timer = 0; - SoundC._0C = (sbuffer.apu.Triangle.TimerHigh << 8) | sbuffer.apu.Triangle.TimerLow; - SoundC._18 = LEN_TABLE_HVC[sbuffer.apu.Triangle.LengthCounterLoad]; - SoundC._10 = SoundC._18 * 4; - if (!SoundC._00 || !SoundC._20) { - SoundC._04 = 0; - SoundC._1C = (127 - bias >> 3) + 16; - SoundC._48 = 0; - SoundC._08 = __PitchTo32_HVC_C(SoundC._0C); - } else { - SoundC._08 = __PitchTo32_HVC_C(SoundC._0C); - } - SoundC._4A = 60; - SoundC._14 = sbuffer.apu.Triangle.LengthCounter; - SoundC._20 = SoundC._24; - if (sbuffer.apu.TriangleStatus && sbuffer.apu.Triangle.LinearCounterReloadVaue) { - if (!SoundC._00) { - SoundC._00 = 1; - } - } else { - SoundC._00 = 0; - } - } break; - } -} - -int __ProcessSoundC() { - static s16 timer = 0; - sample_timer++; - abs_timer++; - - u16 v = SoundC._08; - if (!SoundC._00 || !SoundC._20) { - if (SoundC._3E) { - SoundC._3E--; - } - } else if (SoundC._3E < 0x20) { - SoundC._3E++; - } - - s16 b = (int)__GetWave_Triangle(SoundC._04p._04_hi); - SoundC._1C = (127 - bias >> 3) + 0x10; - b *= SoundC._1C; - SoundC._04 = SoundC._04 + SoundC._08; - SoundC._04 &= 0x1fffff; - SoundC._40 = v; - - if (!SoundC._14) { - if (PHASE_SYNC_FLAG && SoundC._10) { - SoundC._10--; - } - if (!SoundC._10 && !SoundC._14) { - SoundC._00 = 0; - } - if (SoundC._20 && PHASE_SYNC_FLAG) { - SoundC._20--; - } - } - - if (!SoundC._20 && !SoundC._14) { - SoundC._00 = 0; - } - - if (SoundC._4A) { - SoundC._4A--; - } - - s16 ret = (b * SoundC._3E) >> 5; - return ret; -} - -u8 DISKSUB_TABLE[32]; -s16 disksubwave[32][2]; - -void __CreateDiskSubWave() { - for (int i = 0; i < 32; i++) { - disksubwave[i][0] = DISK_SUB_GAIN[DISKSUB_TABLE[i]]; - disksubwave[i][1] = DISK_SUB_GAIN[DISKSUB_TABLE[i]]; - } -} - -u32 __PitchTo32_DISKFM(u16 v) { - return (0.85343015f * (int)v) / 500.4375f * 32768.f; -} - -void __Sound_Write_Disk(u16 a, u8 b) { - static int shiftr = 0; - sbuffer.buff[a] = b; - if (a == 0x23) { - if (!(b & 2)) { - SoundF._2D = 0; - SoundF._2C = 0; - } - } else if (a >= 0x40 && a <= 0x7f) { - DISKFM_TABLE[a - 0x40] = ((WaveTableEntry*)&sbuffer.buff[a])->Sample; - } else { - switch (a) { - case 0x80: { - u32 old_2c = SoundF._2C; - SoundF._2C = sbuffer.apu.VolumeEnvelopeEnabled; - SoundF._2E = sbuffer.apu.VolumeEnvelopeIncreasing; - if (SoundF._2C == 1) { - SoundF._2D = sbuffer.apu.VolumeEnvelopeGainAndSpeed; - } else { - SoundF._28 = (DISK_FRAME_SAMPLE * (sbuffer.apu.VolumeEnvelopeGainAndSpeed + 1)) >> 4; - } - if (SoundF._2C != old_2c) { - SoundF._24 = 0; - } - } break; - case 0x82: { - SoundF._14 = sbuffer.apu.FrequencyHigh << 8 | sbuffer.apu.FrequencyLow; - SoundF._10 = __PitchTo32_DISKFM(SoundF._14); - } break; - case 0x83: { - SoundF._14 = sbuffer.apu.FrequencyHigh << 8 | sbuffer.apu.FrequencyLow; - SoundF._10 = __PitchTo32_DISKFM(SoundF._14); - if (sbuffer.apu.HighSpeedFrequency) { - SoundF._04 = 0; - } - } break; - case 0x84: { - u32 c = SoundF._38; - SoundF._38 = sbuffer.apu.ModEnvelopeEnabled; - SoundF._3A = sbuffer.apu.ModEnvelopeIncreasing; - if (SoundF._38 == 1) { - SoundF._39 = sbuffer.apu.ModEnvelopeGainAndSpeed; - } else { - SoundF._34 = (DISK_FRAME_SAMPLE * (sbuffer.apu.ModEnvelopeGainAndSpeed + 1)) >> 4; - } - if (SoundF._38 != c) { - SoundF._30 = 0; - } - } break; - case 0x85: { - SoundF._44 = sbuffer.apu.ModCounter; - if (SoundF._44 & 0x40) { - SoundF._44 |= 0x80; - } - } break; - case 0x86: { - SoundF._1C = sbuffer.apu.ModFrequencyHigh << 8 | sbuffer.apu.ModFrequencyLow; - SoundF._18 = __PitchTo32_DISKFM(SoundF._1C); - } break; - case 0x87: { - u32 c = sbuffer.apu.HaltModTableCounter; - SoundF._1C = sbuffer.apu.ModFrequencyHigh << 8 | sbuffer.apu.ModFrequencyLow; - SoundF._18 = __PitchTo32_DISKFM(SoundF._1C); - SoundF._46 = sbuffer.apu.HaltModTableCounter; - if (!SoundF._46 && c == 1) { - __CreateDiskSubWave(); - } - if (SoundF._46) { - shiftr = 0; - } - SoundF._0C = -1; - SoundF._08 = 0; - SoundF._47 = 0; - - } break; - case 0x88: { - if (shiftr < 0x20) { - DISKSUB_TABLE[shiftr & 0x1f] = b & 7; - if (++shiftr == 0x20) { - __CreateDiskSubWave(); - } - } - } break; - case 0x89: { - SoundF._43 = DISKFM_GAINTABLE[sbuffer.apu.WaveTableMasterVolume]; - SoundF._45 = sbuffer.apu.WaveTableWriteEnable; - } break; - case 0x8a: { - SoundF._48 = sbuffer.apu.EnvelopeSpeed; - } break; - } - } -} -OSMessageQueue SoundQ; -OSMessage SoundQbuf[0x1000]; - -void HS_Event_Reset() { - OSInitMessageQueue(&SoundQ, SoundQbuf, ARRAY_COUNT(SoundQbuf)); -} - -void HS_Event_Update() { - //! TODO: this has to be wrong - typedef struct { - u8 a, b; - } tempBuf; - tempBuf message; - - while (1) { - // this should take a void** for message, and it fills out the OSMessage(which is a void*) - if (!OSReceiveMessage(&SoundQ, (OSMessage*)&message, 0)) { - break; - } - __Sound_Write_HVC(message.a, message.b); - } -} - -void HS_Event_Write(u16 a, u8 b) { - if (a >= 0x5000 && a <= 0x5015) { - a = (a - 0xf40); - } - - OSSendMessage(&SoundQ, (OSMessage)((a - 0x4000) << 0x18 | b << 0x10), 0); - switch (a & 0xff) { - case 3: { - DUMMY_ACTIVE[0] = 2; - } break; - case 7: { - DUMMY_ACTIVE[1] = 2; - } break; - case 0xb: { - DUMMY_ACTIVE[2] = 2; - } break; - case 0xf: { - DUMMY_ACTIVE[3] = 2; - } break; - case 0x15: { - if (!(b & 1)) { - DUMMY_ACTIVE[0] = 1; - } - if (!(b & 2)) { - DUMMY_ACTIVE[1] = 1; - } - if (!(b & 4)) { - DUMMY_ACTIVE[2] = 1; - } - if (!(b & 8)) { - DUMMY_ACTIVE[3] = 1; - } - if (!(b & 0x10)) { - DUMMY_ACTIVE[4] = 1; - } - if (b & 0x10) { - DUMMY_ACTIVE[4] = 2; - } - } break; - case 0xc3: { - DUMMY_ACTIVE[6] = 2; - } break; - case 0xc7: { - DUMMY_ACTIVE[7] = 2; - } break; - case 0xcb: { - DUMMY_ACTIVE[8] = 2; - } break; - case 0xd5: { - if (!(b & 1)) { - DUMMY_ACTIVE[6] = 1; - } - if (!(b & 2)) { - DUMMY_ACTIVE[7] = 1; - } - if (!(b & 4)) { - DUMMY_ACTIVE[8] = 1; - } - } break; - } -} - -void ProcessPhaseCounter() { - if (PHASE_SYNC_COUNTER != 0) { - PHASE_SYNC_COUNTER--; - } - if (PHASE_SYNC_COUNTER == 0) { - PHASE_SYNC_FLAG = 1; - PHASE_SYNC_COUNTER = PHASE_SAMPLE; - } - - if (PHASE_SYNC_FLAG) { - if (FRAME_SYNC_COUNTER != 0) { - FRAME_SYNC_COUNTER--; - } - if (FRAME_SYNC_COUNTER == 0) { - FRAME_SYNC_FLAG = 1; - FRAME_SYNC_COUNTER = 4; - } - } -} - -void ForceProcessPhaseCounter() { - PHASE_SYNC_COUNTER = 0; - ProcessPhaseCounter(); -} - -int Sound_Make_HVC(s32 count, s16* v) { - static int lastsample; - HS_Event_Update(); - for (int i = 0; i < count; i++) { - ProcessPhaseCounter(); - int a = __ProcessSoundA(); - int b = __ProcessSoundB(); - int c = __ProcessSoundC(); - int d = __ProcessSoundD(); - int e = __ProcessSoundE(); - int j = (s16)a + (s16)b - (s16)c - (s16)d + (s16)e; - if (j >= 0x7fff) { - j = 0x7fff; - } else if (j <= -0x7fff) { - j = -0x7fff; - } - lastsample += (j - lastsample) / 2; - v[i] = lastsample; - PHASE_SYNC_FLAG = 0; - FRAME_SYNC_FLAG = 0; - } - DUMMY_ACTIVE[0] = 0; - DUMMY_ACTIVE[1] = 0; - DUMMY_ACTIVE[2] = 0; - DUMMY_ACTIVE[3] = 0; - DUMMY_ACTIVE[4] = 0; - DUMMY_ACTIVE[5] = 0; - DUMMY_ACTIVE[6] = 0; - DUMMY_ACTIVE[7] = 0; - DUMMY_ACTIVE[8] = 0; -} - -s16 sound_loop_buffer[0x2000]; - -int read_pointer; - -void Buffer_Reset() { - for (int i = 0; i < ARRAY_COUNT(sound_loop_buffer); i++) { - sound_loop_buffer[i] = 0; - } - read_pointer = 0; - write_pointer = 0x690; - buffer_remain = 0x690; -} - -void Sample_Copy(u16 count, s16* v) { - u32 i; - for (i = 0; i < count; i++, buffer_remain--) { - if (buffer_remain == 0) { - Buffer_Reset(); - break; - } - v[i] = sound_loop_buffer[read_pointer]; - sound_loop_buffer[read_pointer] = 0; - if (++read_pointer == 0x2000) { - read_pointer = 0; - } - } - - for (i; i < count; i++) { - v[i] = 0; - } -} - -void Sound_Write(u16 event, u8 value, u16 maybe_frames) { - if (event == 0) { - static f32 create_counter = 0; - static f32 create_speed; - int interrupts = OSDisableInterrupts(); - if (buffer_remain < 0x460) { - create_speed = 2.038168f * ((5.f * (0x460 - buffer_remain) + 1680.f) / 1680.f); - if (create_speed > 2.5) { - create_speed = 2.5f; - } - } else if (buffer_remain > 1680) { - create_speed = 2.038168f * (1680.f / ((-0x690 + buffer_remain) * 5 + 0x690)); - } else { - create_speed = 2.038168f; - } - create_counter += create_speed; - int c = (int)create_counter; - create_counter -= c; - static s16 buf[0x10]; - Sound_Make_HVC(c, buf); - if (c != 0) { - for (u32 i = 0; i < c; i++) { - if (buffer_remain == 0x2000) { - break; - } - sound_loop_buffer[write_pointer] = buf[i]; - if (++write_pointer == 0x2000) { - write_pointer = 0; - } - buffer_remain++; - } - } - OSRestoreInterrupts(interrupts); - } else { - HS_Event_Write(event, value); - } -} - -void Sound_Reset() { - HS_Event_Reset(); - Jac_bzero(&SoundA, sizeof(SoundA)); - Jac_bzero(&SoundB, sizeof(SoundB)); - Jac_bzero(&SoundC, sizeof(SoundC)); - Jac_bzero(&SoundD, sizeof(SoundD)); - Jac_bzero(&SoundX, sizeof(SoundX)); - Jac_bzero(&SoundY, sizeof(SoundY)); - Jac_bzero(&SoundZ, sizeof(SoundZ)); - Jac_bzero(&SoundM, sizeof(SoundM)); - Jac_bzero(&SoundN, sizeof(SoundN)); - Jac_bzero(&SoundE, sizeof(SoundE)); - Jac_bzero(&SoundF, sizeof(SoundF)); - Jac_bzero(&SoundP, sizeof(SoundP)); - SoundA._3E = 0; - SoundB._3E = 0; - SoundC._3E = 0; - SoundD._3E = 0; - SoundF._3C = 0; - SoundP._0E = 0; - - SoundX._3E = 0; - SoundY._3E = 0; - SoundZ._3E = 0; - - SoundA._04 = 0; - SoundB._04 = 0; - SoundC._04 = 0; - SoundD._04 = 0; - SoundE._04 = 0; - SoundF._04 = 0; - SoundP._04 = 0; - - SoundA._48 = 0; - SoundB._48 = 0; - SoundC._48 = 0; - SoundX._04 = 0; - SoundY._04 = 0; - SoundZ._04 = 0; - SoundP._0D = 0; - WriteBias(0); - Buffer_Reset(); -} - -u32 exitflag; -MixCallback old_mixcall; -u8 old_mixmode; - -s16* __FrameCallback(s32 a) { - static s16 buf[0x320]; - if (move_to_50) { - move_to_50--; - if (move_to_50 == 0) { - FRAME_SAMPLE = 0x280; - PHASE_SAMPLE = 0xa0; - } - } - Sample_Copy(a, buf); - if (exitflag) { - f32 f2 = 1.f; - f32 f = 1.f / a; - Jac_RegisterMixcallback(old_mixcall, old_mixmode); - exitflag = FALSE; - for (int i = 0; i < a; i++) { - buf[i] = f2 * buf[i]; - f2 -= f; - } - } - return buf; -} - -void EmuSound_Start(u8* noise_data) { - NOISE_DTABLE = noise_data; - Sound_Reset(); - exitflag = 0; - old_mixcall = Jac_GetMixcallback(&old_mixmode); - Jac_RegisterMixcallback(__FrameCallback, 0); -} - -void EmuSound_Exit() { - exitflag = TRUE; -} - -u8 Sound_Read(u16 reg_addr) { - if (reg_addr == 0x5015) { - u8 x, y, z; - if (!DUMMY_ACTIVE[6]) { - x = SoundX._00; - } - if (!DUMMY_ACTIVE[7]) { - y = SoundY._00; - } - if (!DUMMY_ACTIVE[8]) { - z = SoundZ._00; - } - return z << 2 | y << 1 | (x); - } else if (reg_addr == 0x4015) { - u8 a, b, c, d, e; - if (DUMMY_ACTIVE[0]) { - a = DUMMY_ACTIVE[0] - 1; - } else { - a = SoundA._00; - } - - if (DUMMY_ACTIVE[1]) { - b = DUMMY_ACTIVE[1] - 1; - } else { - b = SoundB._00; - } - - if (DUMMY_ACTIVE[2]) { - c = DUMMY_ACTIVE[2] - 1; - } else { - c = SoundC._00; - } - - if (DUMMY_ACTIVE[3]) { - d = DUMMY_ACTIVE[3] - 1; - } else { - d = SoundD._00; - } - - if (DUMMY_ACTIVE[4]) { - e = DUMMY_ACTIVE[4] - 1; - } else { - e = SoundE._00; - } - return SoundE._20 << 7 | e << 4 | d << 3 | c << 2 | b << 1 | a; - } else { - switch (reg_addr & 0xff) { - case 0x90: - return SoundF._2D; - case 0x92: - return SoundF._39; - default: - return 0; - } - } -} - -void Sound_SetC000(u8* romTop) { - ROM_TOP_C000 = romTop; -} -void Sound_SetE000(u8* romTop) { - ROM_TOP_E000 = romTop; -} - -void Sound_SetMMC(u8 mmcMode) { - FRAME_SAMPLE = 0x280; - PHASE_SAMPLE = 0xa0; - beforemode = 0; - MMC_MODE = mmcMode; - Sound_Reset(); -} - -#pragma force_active on -void Sound_PlayMENUPCM(u8 v) { - SoundP._0D = v; -} -#pragma force_active reset - -void __Sound_Write_HVC(u16 index, u8 v) { - sbuffer.buff[index] = v; - if (index >= 0xc0) { - switch (MMC_MODE) { - case 1: { - __Sound_Write_VRC(index, v); - } break; - case 0: { - __Sound_Write_MMC5(index, v); - } break; - } - } else if (index > 0x17) { - __Sound_Write_Disk(index, v); - } else { - switch (index >> 2) { - case 0: { - __Sound_Write_A(index, v); - } break; - case 1: { - __Sound_Write_B(index, v); - } break; - case 2: { - __Sound_Write_C(index, v); - } break; - case 3: { - __Sound_Write_D(index, v); - } break; - case 4: { - __Sound_Write_E(index, v); - } break; - - case 5: { - if (index == 0x17) { - if (v & 0x80) { - FRAME_SAMPLE = 0x280; - PHASE_SAMPLE = 0xa0; - beforemode = 0; - } else { - FRAME_SAMPLE = 0x215; - PHASE_SAMPLE = 0x85; - beforemode = 1; - } - ForceProcessPhaseCounter(); - } else { - if (!(v & 1)) { - SoundA._00 = 0; - } - if (!(v & 2)) { - SoundB._00 = 0; - } - if (!(v & 4)) { - SoundC._00 = 0; - } - if (!(v & 8)) { - SoundD._00 = 0; - } - if (!(v & 0x10)) { - SoundE._00 = 0; - } - if ((v & 0x10) && !SoundE._00) { - StartE(); - } - } - } break; - } - } -} - -// UNUSED -void* PCM[9] = { (void*)&_STOP, (void*)&_STOP, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - -// UNUSED -u32 PCMSIZE[9] = { sizeof(_STOP), sizeof(_STOP), 0, 0, 0, 0, 0, 0, 0 }; +#include "../src/static/jaudio_PP/game/emusound_vrc.c_inc" +#include "../src/static/jaudio_PP/game/emusound_a.c_inc" +#include "../src/static/jaudio_PP/game/emusound_b.c_inc" +#include "../src/static/jaudio_PP/game/emusound_d.c_inc" +#include "../src/static/jaudio_PP/game/emusound_e.c_inc" +#include "../src/static/jaudio_PP/game/emusound_c.c_inc" +#include "../src/static/jaudio_PP/game/emusound_disk.c_inc" +#include "../src/static/jaudio_PP/game/emusound_event.c_inc" +#include "../src/static/jaudio_PP/game/emusound_hvc.c_inc" +#include "../src/static/jaudio_PP/game/emusound_pcm.c_inc" diff --git a/src/static/jaudio_PP/game/emusound_a.c_inc b/src/static/jaudio_PP/game/emusound_a.c_inc new file mode 100644 index 00000000..9bd371c9 --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_a.c_inc @@ -0,0 +1,202 @@ +void __Sound_Write_A(u16 a, u8 b) { + switch (a) { + case 0: { + SoundA._3C = sbuffer.apu.Pulse1.Duty; + u32 v = SoundA._28; + SoundA._28 = sbuffer.apu.Pulse1.ConstantVolume ^ 1; + SoundA._14 = sbuffer.apu.Pulse1.EnvelopeLoopCounter; + if (!SoundA._28) { + SoundA._2C = sbuffer.apu.Pulse1.EnvelopePeriod_Volume << 8; + } else { + SoundA._24 = sbuffer.apu.Pulse1.EnvelopePeriod_Volume + 1; + if (!v && SoundA._00) { + SoundA._2C = 0xf00; + SoundA._20 = 0; + } + } + } break; + case 1: { + SoundA._34 = (sbuffer.apu.Pulse1.SweepUnitPeriod + 1) << 1; + SoundA._39 = sbuffer.apu.Pulse1.SweepUnitNegative; + SoundA._38 = sbuffer.apu.Pulse1.SweepUnitShiftCount; + SoundA._30 = 0; + SoundA._3B = 0; + SoundA._3A = sbuffer.apu.Pulse1.SweepUnitEnabled; + } break; + case 2: { + SoundA._0C = SoundA._0C & 0xf00 | sbuffer.apu.Pulse1.TimerLow; + SoundA._08 = __PitchTo32_HVC(SoundA._0C); + } break; + case 3: { + SoundA._0C = (sbuffer.apu.Pulse1.TimerHigh << 8) | sbuffer.apu.Pulse1.TimerLow; + SoundA._08 = __PitchTo32_HVC(SoundA._0C); + SoundA._18 = LEN_TABLE_HVC[sbuffer.apu.Pulse1.LengthCounterLow]; + SoundA._10 = SoundA._18 << 2; + SoundA._04 = 0; + SoundA._48 = 0; + SoundA._3E = 0; + SoundA._2A = 0; + if (sbuffer.apu.Pulse1Status) { + SoundA._00 = 1; + } + if (!sbuffer.apu.Pulse1.ConstantVolume) { + SoundA._2C = 0xf00; + } else { + SoundA._2C = sbuffer.apu.Pulse1.EnvelopePeriod_Volume << 8; + } + SoundA._20 = 0; + SoundA._30 = 0; + SoundA._3B = 0; + SoundA._3A = sbuffer.apu.Pulse1.SweepUnitEnabled; + } break; + } +} + +int __ProcessSoundA() { + if (SoundA._3A) { + if (PHASE_SYNC_FLAG) { + SoundA._30++; + if (SoundA._30 % SoundA._34 == 0) { + SoundA._3B |= 1; + } + } + + if (SoundA._3B == 3) { + SoundA._3B = 0; + u32 c = SoundA._0C; + u16 j = SoundA._0C >> SoundA._38; + if (!SoundA._38) { + j = 0; + } + switch (SoundA._39) { + case 0: { + SoundA._0C = SoundA._0C + j; + } break; + case 1: { + if (!SoundA._38) { + j = 0; + } + j = SoundA._0C - j; + SoundA._0C = j; + if (j && SoundA._38) { + SoundA._0C--; + } + } break; + } + if (SoundA._0C >= 0x800) { + SoundA._0C = 0x800; + } else { + SoundA._08 = __PitchTo32_HVC(SoundA._0C); + } + } + } + + if (!SoundA._00 && !SoundA._3E) { + return 0; + } + + if (SoundA._28 && PHASE_SYNC_FLAG) { + SoundA._20++; + if ((SoundA._20 % SoundA._24) == 0) { + switch (SoundA._14) { + case 0: { + if (SoundA._2C) { + SoundA._2C -= 0x100; + } else { + SoundA._00 = 0; + } + } break; + case 1: { + if (SoundA._2C) { + SoundA._2C -= 0x100; + } else { + SoundA._2C = 0xf00; + } + } break; + } + } + } + + if (SoundA._14 == 0) { + if (PHASE_SYNC_FLAG && SoundA._10) { + SoundA._10--; + } + if (SoundA._10 == 0) { + SoundA._00 = 0; + } + } + + if (SoundA._0C <= 7) { + SoundA._44 = 1; + } else if (SoundA._0C >= 0x800) { + SoundA._44 = 1; + } else { + SoundA._44 = 0; + } + + s8 c = __GetWave_Pulse(SoundA._3C, SoundA._04p._04_hi); + + if (SoundA._44) { + SoundA._04 += SoundA._40; + } else { + SoundA._04 += SoundA._08; + SoundA._40 = SoundA._08; + } + + if (SoundA._04 & 0xffe00000) { + SoundA._3B |= 2; + } + + SoundA._04 &= 0x1fffff; + if (SoundA._44 == 1 || !SoundA._00) { + if (SoundA._3E) { + SoundA._3E--; + } + } else { + if (SoundA._3E < 0x20) { + SoundA._3E++; + } + if (SoundA._3E < 0x20) { + SoundA._3E++; + } + } + + u32 _2a_6 = SoundA._2A >> 8 & 0xff; + f32 f_2a = (SoundA._2A & 0xff) / 256.f; + f32 param0 = VOLTABLE_HVCPULSE[_2a_6]; + f32 param1 = VOLTABLE_HVCPULSE[_2a_6 + 1]; + f32 f_sum = param0 * (1.f - f_2a) + param1 * f_2a; + + if (SoundA._2A != SoundA._2C) { + if (SoundA._2A > SoundA._2C) { + u16 diff = (SoundA._2A - SoundA._2C) >> 4; + if (!diff) { + SoundA._2A = SoundA._2C; + } else { + SoundA._2A -= diff; + } + } else if (SoundA._2A < SoundA._2C) { + u16 diff = (SoundA._2C - SoundA._2A) >> 4; + if (!diff) { + SoundA._2A = SoundA._2C; + } else { + SoundA._2A += diff; + } + } + } + + switch (c) { + case 0: { + // almost 1. / 15.6 + f_sum = -0.064103; + } break; + case 1: { + f_sum = -0.064103 + f_sum; + } break; + } + + s16 t = f_sum * 4096.f; + + t = (t * SoundA._3E) >> 5; + return t; +} diff --git a/src/static/jaudio_PP/game/emusound_b.c_inc b/src/static/jaudio_PP/game/emusound_b.c_inc new file mode 100644 index 00000000..82356f6b --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_b.c_inc @@ -0,0 +1,200 @@ +void __Sound_Write_B(u16 a, u8 b) { + a -= 4; + switch (a) { + case 0: { + SoundB._3C = sbuffer.apu.Pulse2.Duty; + u32 v = SoundB._28; + SoundB._28 = sbuffer.apu.Pulse2.ConstantVolume ^ 1; + SoundB._14 = sbuffer.apu.Pulse2.EnvelopeLoopCounter; + if (!SoundB._28) { + SoundB._2C = sbuffer.apu.Pulse2.EnvelopePeriod_Volume << 8; + } else { + SoundB._24 = sbuffer.apu.Pulse2.EnvelopePeriod_Volume + 1; + if (!v && SoundB._00) { + SoundB._2C = 0xf00; + SoundB._20 = 0; + } + } + } break; + case 1: { + SoundB._34 = (sbuffer.apu.Pulse2.SweepUnitPeriod + 1) << 1; + SoundB._39 = sbuffer.apu.Pulse2.SweepUnitNegative; + SoundB._38 = sbuffer.apu.Pulse2.SweepUnitShiftCount; + SoundB._30 = 0; + SoundB._3B = 0; + SoundB._3A = sbuffer.apu.Pulse2.SweepUnitEnabled; + } break; + case 2: { + SoundB._0C = SoundB._0C & 0xf00 | sbuffer.apu.Pulse2.TimerLow; + SoundB._08 = __PitchTo32_HVC(SoundB._0C); + } break; + case 3: { + SoundB._0C = (sbuffer.apu.Pulse2.TimerHigh << 8) | sbuffer.apu.Pulse2.TimerLow; + SoundB._08 = __PitchTo32_HVC(SoundB._0C); + SoundB._18 = LEN_TABLE_HVC[sbuffer.apu.Pulse2.LengthCounterLow]; + SoundB._10 = SoundB._18 << 2; + SoundB._04 = 0; + SoundB._48 = 0; + SoundB._3E = 0; + SoundB._2A = 0; + if (sbuffer.apu.Pulse2Status) { + SoundB._00 = 1; + } + if (!sbuffer.apu.Pulse2.ConstantVolume) { + SoundB._2C = 0xf00; + } else { + SoundB._2C = sbuffer.apu.Pulse2.EnvelopePeriod_Volume << 8; + } + SoundB._20 = 0; + SoundB._30 = 0; + SoundB._3B = 0; + SoundB._3A = sbuffer.apu.Pulse2.SweepUnitEnabled; + } break; + } +} + +int __ProcessSoundB() { + if (SoundB._3A) { + if (PHASE_SYNC_FLAG) { + SoundB._30++; + if (SoundB._30 % SoundB._34 == 0) { + SoundB._3B |= 1; + } + } + + if (SoundB._3B == 3) { + SoundB._3B = 0; + u32 c = SoundB._0C; + u16 j = SoundB._0C >> SoundB._38; + if (!SoundB._38) { + j = 0; + } + switch (SoundB._39) { + case 0: { + SoundB._0C = SoundB._0C + j; + } break; + case 1: { + if (!SoundB._38) { + j = 0; + } + + SoundB._0C = SoundB._0C - j; + } break; + } + if (SoundB._0C >= 0x800) { + SoundB._0C = 0x800; + } else { + SoundB._08 = __PitchTo32_HVC(SoundB._0C); + } + } + } + + if (!SoundB._00 && !SoundB._3E) { + return 0; + } + + if (SoundB._28 && PHASE_SYNC_FLAG) { + SoundB._20++; + if ((SoundB._20 % SoundB._24) == 0) { + switch (SoundB._14) { + case 0: { + if (SoundB._2C) { + SoundB._2C -= 0x100; + } else { + SoundB._00 = 0; + } + } break; + case 1: { + if (SoundB._2C) { + SoundB._2C -= 0x100; + } else { + SoundB._2C = 0xf00; + } + } break; + } + } + } + + if (SoundB._14 == 0) { + if (PHASE_SYNC_FLAG && SoundB._10) { + SoundB._10--; + } + if (SoundB._10 == 0) { + SoundB._00 = 0; + } + } + + if (SoundB._0C <= 7) { + SoundB._44 = 1; + } else if (SoundB._0C >= 0x800) { + SoundB._44 = 1; + } else { + SoundB._44 = 0; + } + + s8 c = __GetWave_Pulse(SoundB._3C, SoundB._04p._04_hi); + + if (SoundB._44) { + SoundB._04 += SoundB._40; + } else { + SoundB._04 += SoundB._08; + SoundB._40 = SoundB._08; + } + + if (SoundB._04 & 0xffe00000) { + SoundB._3B |= 2; + } + + SoundB._04 &= 0x1fffff; + if (SoundB._44 == 1 || !SoundB._00) { + if (SoundB._3E) { + SoundB._3E--; + } + } else { + if (SoundB._3E < 0x20) { + SoundB._3E++; + } + if (SoundB._3E < 0x20) { + SoundB._3E++; + } + } + + u32 _2a_6 = SoundB._2A >> 8 & 0xff; + f32 f_2a = (SoundB._2A & 0xff) / 256.f; + f32 param0 = VOLTABLE_HVCPULSE[_2a_6]; + f32 param1 = VOLTABLE_HVCPULSE[_2a_6 + 1]; + f32 f_sum = param0 * (1.f - f_2a) + param1 * f_2a; + + if (SoundB._2A != SoundB._2C) { + if (SoundB._2A > SoundB._2C) { + u16 diff = (SoundB._2A - SoundB._2C) >> 4; + if (!diff) { + SoundB._2A = SoundB._2C; + } else { + SoundB._2A -= diff; + } + } else if (SoundB._2A < SoundB._2C) { + u16 diff = (SoundB._2C - SoundB._2A) >> 4; + if (!diff) { + SoundB._2A = SoundB._2C; + } else { + SoundB._2A += diff; + } + } + } + + switch (c) { + case 0: { + // almost 1. / 15.6 + f_sum = -0.064103; + } break; + case 1: { + f_sum = -0.064103 + f_sum; + } break; + } + + s16 t = f_sum * 4096.f; + + t = (t * SoundB._3E) >> 5; + return t; +} diff --git a/src/static/jaudio_PP/game/emusound_c.c_inc b/src/static/jaudio_PP/game/emusound_c.c_inc new file mode 100644 index 00000000..ab9584dd --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_c.c_inc @@ -0,0 +1,124 @@ +s8 __GetWave_Triangle(s32 a) { + return TRIANGLE_TABLE[a]; +} + +u32 __PitchTo32_HVC_C(u16 a) { + u32 pitch; + if (a == 0) { + return 0; + } else { + f32 scalefactor = 16.f; + return (u32)((NES_CLOCK_SPEED - 0.25f) / scalefactor / (a + 1) / 1000.875f * 32768.f); + } +} +u32 sample_timer = 0; +u32 abs_timer = 0; + +void __Sound_Write_C(u16 a, u8 b) { + switch (a) { + case 0x8: { + u8 v = SoundC._14; + if (sbuffer.apu.Triangle.LinearCounterReloadVaue) { + SoundC._24 = sbuffer.apu.Triangle.LinearCounterReloadVaue + 1; + } else { + SoundC._24 = 0; + } + + if (SoundC._00 && SoundC._4A) { + SoundC._14 = sbuffer.apu.Triangle.LengthCounter; + SoundC._20 = SoundC._24; + } else if (SoundC._00) { + if (v && !sbuffer.apu.Triangle.LengthCounter) { + SoundC._14 = sbuffer.apu.Triangle.LengthCounter; + SoundC._20 = SoundC._24; + SoundC._4A = 0x80; + } else if (v) { + SoundC._20 = SoundC._24; + } + } else if (SoundC._4A) { + SoundC._14 = sbuffer.apu.Triangle.LengthCounter; + SoundC._20 = SoundC._24; + if (sbuffer.apu.TriangleStatus) { + SoundC._00 = 1; + } + } + + if (!sbuffer.apu.Triangle.LinearCounterReloadVaue && !SoundC._14) { + SoundC._00 = 0; + } + } break; + case 0xa: { + SoundC._0C = (sbuffer.apu.Triangle.TimerHigh << 8) | sbuffer.apu.Triangle.TimerLow; + SoundC._08 = __PitchTo32_HVC_C(SoundC._0C); + } break; + case 0xb: { + sample_timer = 0; + SoundC._0C = (sbuffer.apu.Triangle.TimerHigh << 8) | sbuffer.apu.Triangle.TimerLow; + SoundC._18 = LEN_TABLE_HVC[sbuffer.apu.Triangle.LengthCounterLoad]; + SoundC._10 = SoundC._18 * 4; + if (!SoundC._00 || !SoundC._20) { + SoundC._04 = 0; + SoundC._1C = (127 - bias >> 3) + 16; + SoundC._48 = 0; + SoundC._08 = __PitchTo32_HVC_C(SoundC._0C); + } else { + SoundC._08 = __PitchTo32_HVC_C(SoundC._0C); + } + SoundC._4A = 60; + SoundC._14 = sbuffer.apu.Triangle.LengthCounter; + SoundC._20 = SoundC._24; + if (sbuffer.apu.TriangleStatus && sbuffer.apu.Triangle.LinearCounterReloadVaue) { + if (!SoundC._00) { + SoundC._00 = 1; + } + } else { + SoundC._00 = 0; + } + } break; + } +} + +int __ProcessSoundC() { + static s16 timer = 0; + sample_timer++; + abs_timer++; + + u16 v = SoundC._08; + if (!SoundC._00 || !SoundC._20) { + if (SoundC._3E) { + SoundC._3E--; + } + } else if (SoundC._3E < 0x20) { + SoundC._3E++; + } + + s16 b = (int)__GetWave_Triangle(SoundC._04p._04_hi); + SoundC._1C = (127 - bias >> 3) + 0x10; + b *= SoundC._1C; + SoundC._04 = SoundC._04 + SoundC._08; + SoundC._04 &= 0x1fffff; + SoundC._40 = v; + + if (!SoundC._14) { + if (PHASE_SYNC_FLAG && SoundC._10) { + SoundC._10--; + } + if (!SoundC._10 && !SoundC._14) { + SoundC._00 = 0; + } + if (SoundC._20 && PHASE_SYNC_FLAG) { + SoundC._20--; + } + } + + if (!SoundC._20 && !SoundC._14) { + SoundC._00 = 0; + } + + if (SoundC._4A) { + SoundC._4A--; + } + + s16 ret = (b * SoundC._3E) >> 5; + return ret; +} diff --git a/src/static/jaudio_PP/game/emusound_d.c_inc b/src/static/jaudio_PP/game/emusound_d.c_inc new file mode 100644 index 00000000..fd816542 --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_d.c_inc @@ -0,0 +1,140 @@ +int __PitchTo32_HVC_D(u16 a) { + return NOISE_TABLE[a]; +} + +void __Sound_Write_D(u16 a, u8 b) { + switch (a) { + case 0xc: { + u32 v = SoundD._28; + SoundD._28 = sbuffer.apu.Noise.ConstantVolume ^ 1; + SoundD._14 = sbuffer.apu.Noise.LoopEnvelope; + SoundD._1D = (u8)(16.f * VOLTABLE_HVCPULSE[sbuffer.apu.Noise.EnvelopePeriod_Volume]); + if (!SoundD._28) { + SoundD._1C = SoundD._1D; + } else { + SoundD._24 = sbuffer.apu.Noise.EnvelopePeriod_Volume + 1; + if (!v) { + SoundD._2A = 0xf; + SoundD._20 = 0; + } + } + } break; + case 0xe: { + SoundD._0C = sbuffer.apu.Noise.Period; + if (sbuffer.apu.Noise.LoopNoise == 1u) { + SoundD._0C += 0x10; + NOISE_SHIFT = 0x40; + NOISE_MASTER = 1; + } else { + + NOISE_SHIFT = 0x4000; + } + NOISE_PULSE = NOISE_PULSE_TABLE[SoundD._0C & 0xf]; + SoundD._08 = __PitchTo32_HVC_D(SoundD._0C & 0xf); + } break; + case 0xf: { + SoundD._0C = sbuffer.apu.Noise.Period; + if (sbuffer.apu.Noise.LoopNoise == 1u) { + SoundD._0C += 0x10; + NOISE_SHIFT = 0x40; + NOISE_MASTER = 1; + } else { + NOISE_SHIFT = 0x4000; + } + NOISE_PULSE = NOISE_PULSE_TABLE[SoundD._0C % 16u]; + SoundD._08 = __PitchTo32_HVC_D(SoundD._0C % 16u); + SoundD._18 = LEN_TABLE_HVC[sbuffer.apu.Noise.LengthCounterLoad]; + SoundD._10 = SoundD._18 * 4; + if (sbuffer.apu.NoiseStatus != 0) { + SoundD._00 = '\x01'; + } + if (sbuffer.apu.Noise.ConstantVolume == 0) { + SoundD._1C = (u8)(16.f * VOLTABLE_HVCPULSE[15]); + } else { + SoundD._1C = SoundD._1D; + } + SoundD._2A = 0xf; + SoundD._20 = 0; + } break; + } +} + +s8 __GetNoise(u32 a) { + static u8 data = 0; + + for (int i = 0; i < a >> 16; i++) { + data = NOISE_MASTER & 3; + switch (data) { + case 0: + case 3: { + NOISE_MASTER = (NOISE_MASTER >> 1) | NOISE_SHIFT; + } break; + case 1: + case 2: { + NOISE_MASTER >>= 1; + } break; + } + } + + if (NOISE_MASTER & 1) { + return (s32)NOISE_PULSE; + } else { + return -(s32)NOISE_PULSE; + } +} + +u32 delta_counter; +s8 delta_sign; +s32 bias_move; +s32 bias; +f32 voltage; +f32 voltage_out; + +int __ProcessSoundD() { + s16 ret; + if (!SoundD._00) { + if (!SoundD._3E) { + return 0; + } + SoundD._3E--; + SoundD._1C = SoundD._3E; + } + SoundD._04 += SoundD._08; + ret = __GetNoise(SoundD._04); + ret *= SoundD._1C; + SoundD._04p._04_hi = 0; + SoundD._3E = SoundD._1C; + + if (SoundD._28 && PHASE_SYNC_FLAG) { + SoundD._20++; + if (SoundD._20 % SoundD._24 == 0) { + switch (SoundD._14) { + case 0: { + if (SoundD._2A) { + SoundD._2A--; + } else { + SoundD._00 = 0; + } + } break; + case 1: { + if (SoundD._2A) { + SoundD._2A--; + } else { + SoundD._2A = 0xf; + } + } break; + } + SoundD._1C = (u8)(16.f * VOLTABLE_HVCPULSE[SoundD._2A]); + } + } + + if (!SoundD._14) { + if (PHASE_SYNC_FLAG && SoundD._10) { + SoundD._10--; + } + if (!SoundD._10) { + SoundD._00 = 0; + } + } + return ret; +} diff --git a/src/static/jaudio_PP/game/emusound_disk.c_inc b/src/static/jaudio_PP/game/emusound_disk.c_inc new file mode 100644 index 00000000..54bb9b2c --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_disk.c_inc @@ -0,0 +1,107 @@ +u8 DISKSUB_TABLE[32]; +s16 disksubwave[32][2]; + +void __CreateDiskSubWave() { + for (int i = 0; i < 32; i++) { + disksubwave[i][0] = DISK_SUB_GAIN[DISKSUB_TABLE[i]]; + disksubwave[i][1] = DISK_SUB_GAIN[DISKSUB_TABLE[i]]; + } +} + +u32 __PitchTo32_DISKFM(u16 v) { + return (0.85343015f * (int)v) / 500.4375f * 32768.f; +} + +void __Sound_Write_Disk(u16 a, u8 b) { + static int shiftr = 0; + sbuffer.buff[a] = b; + if (a == 0x23) { + if (!(b & 2)) { + SoundF._2D = 0; + SoundF._2C = 0; + } + } else if (a >= 0x40 && a <= 0x7f) { + DISKFM_TABLE[a - 0x40] = ((WaveTableEntry*)&sbuffer.buff[a])->Sample; + } else { + switch (a) { + case 0x80: { + u32 old_2c = SoundF._2C; + SoundF._2C = sbuffer.apu.VolumeEnvelopeEnabled; + SoundF._2E = sbuffer.apu.VolumeEnvelopeIncreasing; + if (SoundF._2C == 1) { + SoundF._2D = sbuffer.apu.VolumeEnvelopeGainAndSpeed; + } else { + SoundF._28 = (DISK_FRAME_SAMPLE * (sbuffer.apu.VolumeEnvelopeGainAndSpeed + 1)) >> 4; + } + if (SoundF._2C != old_2c) { + SoundF._24 = 0; + } + } break; + case 0x82: { + SoundF._14 = sbuffer.apu.FrequencyHigh << 8 | sbuffer.apu.FrequencyLow; + SoundF._10 = __PitchTo32_DISKFM(SoundF._14); + } break; + case 0x83: { + SoundF._14 = sbuffer.apu.FrequencyHigh << 8 | sbuffer.apu.FrequencyLow; + SoundF._10 = __PitchTo32_DISKFM(SoundF._14); + if (sbuffer.apu.HighSpeedFrequency) { + SoundF._04 = 0; + } + } break; + case 0x84: { + u32 c = SoundF._38; + SoundF._38 = sbuffer.apu.ModEnvelopeEnabled; + SoundF._3A = sbuffer.apu.ModEnvelopeIncreasing; + if (SoundF._38 == 1) { + SoundF._39 = sbuffer.apu.ModEnvelopeGainAndSpeed; + } else { + SoundF._34 = (DISK_FRAME_SAMPLE * (sbuffer.apu.ModEnvelopeGainAndSpeed + 1)) >> 4; + } + if (SoundF._38 != c) { + SoundF._30 = 0; + } + } break; + case 0x85: { + SoundF._44 = sbuffer.apu.ModCounter; + if (SoundF._44 & 0x40) { + SoundF._44 |= 0x80; + } + } break; + case 0x86: { + SoundF._1C = sbuffer.apu.ModFrequencyHigh << 8 | sbuffer.apu.ModFrequencyLow; + SoundF._18 = __PitchTo32_DISKFM(SoundF._1C); + } break; + case 0x87: { + u32 c = sbuffer.apu.HaltModTableCounter; + SoundF._1C = sbuffer.apu.ModFrequencyHigh << 8 | sbuffer.apu.ModFrequencyLow; + SoundF._18 = __PitchTo32_DISKFM(SoundF._1C); + SoundF._46 = sbuffer.apu.HaltModTableCounter; + if (!SoundF._46 && c == 1) { + __CreateDiskSubWave(); + } + if (SoundF._46) { + shiftr = 0; + } + SoundF._0C = -1; + SoundF._08 = 0; + SoundF._47 = 0; + + } break; + case 0x88: { + if (shiftr < 0x20) { + DISKSUB_TABLE[shiftr & 0x1f] = b & 7; + if (++shiftr == 0x20) { + __CreateDiskSubWave(); + } + } + } break; + case 0x89: { + SoundF._43 = DISKFM_GAINTABLE[sbuffer.apu.WaveTableMasterVolume]; + SoundF._45 = sbuffer.apu.WaveTableWriteEnable; + } break; + case 0x8a: { + SoundF._48 = sbuffer.apu.EnvelopeSpeed; + } break; + } + } +} diff --git a/src/static/jaudio_PP/game/emusound_e.c_inc b/src/static/jaudio_PP/game/emusound_e.c_inc new file mode 100644 index 00000000..609e054d --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_e.c_inc @@ -0,0 +1,115 @@ +void MoveDeltaCounter(u8 a) { + if (a) { + delta_counter++; + delta_sign++; + } else { + delta_counter--; + delta_sign--; + } +} + +void MoveBias() { + s32 oldBias = bias; + bias += delta_sign * 2; + if (bias > 0x7f) { + bias = 0x7f; + } + if (bias < 0) { + bias = 0; + } + bias_move += bias - oldBias; + delta_sign = 0; +} + +void WriteBias(u16 a) { + bias_move = (s16)a - (s16)bias; + bias = (a & 0xffff); +} + +int MoveVoltage() { + voltage = 0.9994586f * voltage; + voltage += bias_move; + bias_move = 0; + if (voltage > 127.f) { + voltage = 127.f; + } + if (voltage < -127.f) { + voltage = -127.f; + } + voltage_out += (voltage - voltage_out) / 4.f; + + return (int)(216.f * voltage_out); +} + +u32 __PitchTo32_HVC_E(u16 a) { + return DMOD_TABLE[a]; +} + +void __Sound_Write_E(u16 a, u8 b) { + switch (a) { + case 0x10: { + SoundE._08 = __PitchTo32_HVC_E(sbuffer.apu.DMC.FrequencyIndex); + } break; + case 0x11: { + SoundE._1E = sbuffer.apu.DMC.DirectLoad; + WriteBias(SoundE._1E); + } break; + case 0x12: { + SoundE._18 = sbuffer.apu.DMC.SampleAddress << 6; + } break; + case 0x13: { + SoundE._10 = sbuffer.apu.DMC.SampleLength << 4; + } break; + } +} + +void StartE() { + SoundE._00 = 1; + SoundE._14 = (SoundE._10 + 1) * 8; + SoundE._04 = 0; + SoundE._1A = 0; + SoundE._20 = 0; + delta_counter = 0; + bias_move = 0; +} + +int __ProcessSoundE() { + if (SoundE._00) { + for (int i = 0; i < 2u; i++) { + SoundE._04 += SoundE._08; + if (SoundE._04p._04_hi != SoundE._1A) { + u32 vv = SoundE._1A & 7; + u32 offset = (SoundE._1A >> 3 & 0x1fff); + if (!vv) { + if (SoundE._18 + offset < 0x2000) { + SoundE._1C = ROM_TOP_C000[SoundE._18 + offset]; + } else { + SoundE._1C = ROM_TOP_E000[SoundE._18 + offset - 0x2000]; + } + } + MoveDeltaCounter((SoundE._1C << vv) & 0x80); + SoundE._1A = SoundE._04p._04_hi; + if (SoundE._14) { + SoundE._14--; + } + if (!SoundE._14) { + switch (sbuffer.apu.DMC.LoopSample) { + case 0: { + SoundE._00 = 0; + if (sbuffer.apu.DMC.IRQEnable == 1) { + SoundE._20 = 1; + } + } break; + case 1: { + SoundE._14 = (SoundE._10 + 1) * 8; + SoundE._04p._04_hi = 0; + SoundE._1A = 0; + } break; + } + } + } + } + } + MoveBias(); + return MoveVoltage(); +} diff --git a/src/static/jaudio_PP/game/emusound_event.c_inc b/src/static/jaudio_PP/game/emusound_event.c_inc new file mode 100644 index 00000000..5baaef5a --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_event.c_inc @@ -0,0 +1,84 @@ +OSMessageQueue SoundQ; +OSMessage SoundQbuf[0x1000]; + +void HS_Event_Reset() { + OSInitMessageQueue(&SoundQ, SoundQbuf, ARRAY_COUNT(SoundQbuf)); +} + +void HS_Event_Update() { + //! TODO: this has to be wrong + typedef struct { + u8 a, b; + } tempBuf; + tempBuf message; + + while (1) { + // this should take a void** for message, and it fills out the OSMessage(which is a void*) + if (!OSReceiveMessage(&SoundQ, (OSMessage*)&message, 0)) { + break; + } + __Sound_Write_HVC(message.a, message.b); + } +} + +void HS_Event_Write(u16 a, u8 b) { + if (a >= 0x5000 && a <= 0x5015) { + a = (a - 0xf40); + } + + OSSendMessage(&SoundQ, (OSMessage)((a - 0x4000) << 0x18 | b << 0x10), 0); + switch (a & 0xff) { + case 3: { + DUMMY_ACTIVE[0] = 2; + } break; + case 7: { + DUMMY_ACTIVE[1] = 2; + } break; + case 0xb: { + DUMMY_ACTIVE[2] = 2; + } break; + case 0xf: { + DUMMY_ACTIVE[3] = 2; + } break; + case 0x15: { + if (!(b & 1)) { + DUMMY_ACTIVE[0] = 1; + } + if (!(b & 2)) { + DUMMY_ACTIVE[1] = 1; + } + if (!(b & 4)) { + DUMMY_ACTIVE[2] = 1; + } + if (!(b & 8)) { + DUMMY_ACTIVE[3] = 1; + } + if (!(b & 0x10)) { + DUMMY_ACTIVE[4] = 1; + } + if (b & 0x10) { + DUMMY_ACTIVE[4] = 2; + } + } break; + case 0xc3: { + DUMMY_ACTIVE[6] = 2; + } break; + case 0xc7: { + DUMMY_ACTIVE[7] = 2; + } break; + case 0xcb: { + DUMMY_ACTIVE[8] = 2; + } break; + case 0xd5: { + if (!(b & 1)) { + DUMMY_ACTIVE[6] = 1; + } + if (!(b & 2)) { + DUMMY_ACTIVE[7] = 1; + } + if (!(b & 4)) { + DUMMY_ACTIVE[8] = 1; + } + } break; + } +} diff --git a/src/static/jaudio_PP/game/emusound_hvc.c_inc b/src/static/jaudio_PP/game/emusound_hvc.c_inc new file mode 100644 index 00000000..059f7dc6 --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_hvc.c_inc @@ -0,0 +1,355 @@ +void ProcessPhaseCounter() { + if (PHASE_SYNC_COUNTER != 0) { + PHASE_SYNC_COUNTER--; + } + if (PHASE_SYNC_COUNTER == 0) { + PHASE_SYNC_FLAG = 1; + PHASE_SYNC_COUNTER = PHASE_SAMPLE; + } + + if (PHASE_SYNC_FLAG) { + if (FRAME_SYNC_COUNTER != 0) { + FRAME_SYNC_COUNTER--; + } + if (FRAME_SYNC_COUNTER == 0) { + FRAME_SYNC_FLAG = 1; + FRAME_SYNC_COUNTER = 4; + } + } +} + +void ForceProcessPhaseCounter() { + PHASE_SYNC_COUNTER = 0; + ProcessPhaseCounter(); +} + +int Sound_Make_HVC(s32 count, s16* v) { + static int lastsample; + HS_Event_Update(); + for (int i = 0; i < count; i++) { + ProcessPhaseCounter(); + int a = __ProcessSoundA(); + int b = __ProcessSoundB(); + int c = __ProcessSoundC(); + int d = __ProcessSoundD(); + int e = __ProcessSoundE(); + int j = (s16)a + (s16)b - (s16)c - (s16)d + (s16)e; + if (j >= 0x7fff) { + j = 0x7fff; + } else if (j <= -0x7fff) { + j = -0x7fff; + } + lastsample += (j - lastsample) / 2; + v[i] = lastsample; + PHASE_SYNC_FLAG = 0; + FRAME_SYNC_FLAG = 0; + } + DUMMY_ACTIVE[0] = 0; + DUMMY_ACTIVE[1] = 0; + DUMMY_ACTIVE[2] = 0; + DUMMY_ACTIVE[3] = 0; + DUMMY_ACTIVE[4] = 0; + DUMMY_ACTIVE[5] = 0; + DUMMY_ACTIVE[6] = 0; + DUMMY_ACTIVE[7] = 0; + DUMMY_ACTIVE[8] = 0; +} + +s16 sound_loop_buffer[0x2000]; + +int read_pointer; + +void Buffer_Reset() { + for (int i = 0; i < ARRAY_COUNT(sound_loop_buffer); i++) { + sound_loop_buffer[i] = 0; + } + read_pointer = 0; + write_pointer = 0x690; + buffer_remain = 0x690; +} + +void Sample_Copy(u16 count, s16* v) { + u32 i; + for (i = 0; i < count; i++, buffer_remain--) { + if (buffer_remain == 0) { + Buffer_Reset(); + break; + } + v[i] = sound_loop_buffer[read_pointer]; + sound_loop_buffer[read_pointer] = 0; + if (++read_pointer == 0x2000) { + read_pointer = 0; + } + } + + for (i; i < count; i++) { + v[i] = 0; + } +} + +void Sound_Write(u16 event, u8 value, u16 maybe_frames) { + if (event == 0) { + static f32 create_counter = 0; + static f32 create_speed; + int interrupts = OSDisableInterrupts(); + if (buffer_remain < 0x460) { + create_speed = 2.038168f * ((5.f * (0x460 - buffer_remain) + 1680.f) / 1680.f); + if (create_speed > 2.5) { + create_speed = 2.5f; + } + } else if (buffer_remain > 1680) { + create_speed = 2.038168f * (1680.f / ((-0x690 + buffer_remain) * 5 + 0x690)); + } else { + create_speed = 2.038168f; + } + create_counter += create_speed; + int c = (int)create_counter; + create_counter -= c; + static s16 buf[0x10]; + Sound_Make_HVC(c, buf); + if (c != 0) { + for (u32 i = 0; i < c; i++) { + if (buffer_remain == 0x2000) { + break; + } + sound_loop_buffer[write_pointer] = buf[i]; + if (++write_pointer == 0x2000) { + write_pointer = 0; + } + buffer_remain++; + } + } + OSRestoreInterrupts(interrupts); + } else { + HS_Event_Write(event, value); + } +} + +void Sound_Reset() { + HS_Event_Reset(); + Jac_bzero(&SoundA, sizeof(SoundA)); + Jac_bzero(&SoundB, sizeof(SoundB)); + Jac_bzero(&SoundC, sizeof(SoundC)); + Jac_bzero(&SoundD, sizeof(SoundD)); + Jac_bzero(&SoundX, sizeof(SoundX)); + Jac_bzero(&SoundY, sizeof(SoundY)); + Jac_bzero(&SoundZ, sizeof(SoundZ)); + Jac_bzero(&SoundM, sizeof(SoundM)); + Jac_bzero(&SoundN, sizeof(SoundN)); + Jac_bzero(&SoundE, sizeof(SoundE)); + Jac_bzero(&SoundF, sizeof(SoundF)); + Jac_bzero(&SoundP, sizeof(SoundP)); + SoundA._3E = 0; + SoundB._3E = 0; + SoundC._3E = 0; + SoundD._3E = 0; + SoundF._3C = 0; + SoundP._0E = 0; + + SoundX._3E = 0; + SoundY._3E = 0; + SoundZ._3E = 0; + + SoundA._04 = 0; + SoundB._04 = 0; + SoundC._04 = 0; + SoundD._04 = 0; + SoundE._04 = 0; + SoundF._04 = 0; + SoundP._04 = 0; + + SoundA._48 = 0; + SoundB._48 = 0; + SoundC._48 = 0; + SoundX._04 = 0; + SoundY._04 = 0; + SoundZ._04 = 0; + SoundP._0D = 0; + WriteBias(0); + Buffer_Reset(); +} + +u32 exitflag; +MixCallback old_mixcall; +u8 old_mixmode; + +s16* __FrameCallback(s32 a) { + static s16 buf[0x320]; + if (move_to_50) { + move_to_50--; + if (move_to_50 == 0) { + FRAME_SAMPLE = 0x280; + PHASE_SAMPLE = 0xa0; + } + } + Sample_Copy(a, buf); + if (exitflag) { + f32 f2 = 1.f; + f32 f = 1.f / a; + Jac_RegisterMixcallback(old_mixcall, old_mixmode); + exitflag = FALSE; + for (int i = 0; i < a; i++) { + buf[i] = f2 * buf[i]; + f2 -= f; + } + } + return buf; +} + +void EmuSound_Start(u8* noise_data) { + NOISE_DTABLE = noise_data; + Sound_Reset(); + exitflag = 0; + old_mixcall = Jac_GetMixcallback(&old_mixmode); + Jac_RegisterMixcallback(__FrameCallback, 0); +} + +void EmuSound_Exit() { + exitflag = TRUE; +} + +u8 Sound_Read(u16 reg_addr) { + if (reg_addr == 0x5015) { + u8 x, y, z; + if (!DUMMY_ACTIVE[6]) { + x = SoundX._00; + } + if (!DUMMY_ACTIVE[7]) { + y = SoundY._00; + } + if (!DUMMY_ACTIVE[8]) { + z = SoundZ._00; + } + return z << 2 | y << 1 | (x); + } else if (reg_addr == 0x4015) { + u8 a, b, c, d, e; + if (DUMMY_ACTIVE[0]) { + a = DUMMY_ACTIVE[0] - 1; + } else { + a = SoundA._00; + } + + if (DUMMY_ACTIVE[1]) { + b = DUMMY_ACTIVE[1] - 1; + } else { + b = SoundB._00; + } + + if (DUMMY_ACTIVE[2]) { + c = DUMMY_ACTIVE[2] - 1; + } else { + c = SoundC._00; + } + + if (DUMMY_ACTIVE[3]) { + d = DUMMY_ACTIVE[3] - 1; + } else { + d = SoundD._00; + } + + if (DUMMY_ACTIVE[4]) { + e = DUMMY_ACTIVE[4] - 1; + } else { + e = SoundE._00; + } + return SoundE._20 << 7 | e << 4 | d << 3 | c << 2 | b << 1 | a; + } else { + switch (reg_addr & 0xff) { + case 0x90: + return SoundF._2D; + case 0x92: + return SoundF._39; + default: + return 0; + } + } +} + +void Sound_SetC000(u8* romTop) { + ROM_TOP_C000 = romTop; +} +void Sound_SetE000(u8* romTop) { + ROM_TOP_E000 = romTop; +} + +void Sound_SetMMC(u8 mmcMode) { + FRAME_SAMPLE = 0x280; + PHASE_SAMPLE = 0xa0; + beforemode = 0; + MMC_MODE = mmcMode; + Sound_Reset(); +} + +#pragma force_active on +void Sound_PlayMENUPCM(u8 v) { + SoundP._0D = v; +} +#pragma force_active reset + +void __Sound_Write_HVC(u16 index, u8 v) { + sbuffer.buff[index] = v; + if (index >= 0xc0) { + switch (MMC_MODE) { + case 1: { + __Sound_Write_VRC(index, v); + } break; + case 0: { + __Sound_Write_MMC5(index, v); + } break; + } + } else if (index > 0x17) { + __Sound_Write_Disk(index, v); + } else { + switch (index >> 2) { + case 0: { + __Sound_Write_A(index, v); + } break; + case 1: { + __Sound_Write_B(index, v); + } break; + case 2: { + __Sound_Write_C(index, v); + } break; + case 3: { + __Sound_Write_D(index, v); + } break; + case 4: { + __Sound_Write_E(index, v); + } break; + + case 5: { + if (index == 0x17) { + if (v & 0x80) { + FRAME_SAMPLE = 0x280; + PHASE_SAMPLE = 0xa0; + beforemode = 0; + } else { + FRAME_SAMPLE = 0x215; + PHASE_SAMPLE = 0x85; + beforemode = 1; + } + ForceProcessPhaseCounter(); + } else { + if (!(v & 1)) { + SoundA._00 = 0; + } + if (!(v & 2)) { + SoundB._00 = 0; + } + if (!(v & 4)) { + SoundC._00 = 0; + } + if (!(v & 8)) { + SoundD._00 = 0; + } + if (!(v & 0x10)) { + SoundE._00 = 0; + } + if ((v & 0x10) && !SoundE._00) { + StartE(); + } + } + } break; + } + } +} diff --git a/src/static/jaudio_PP/game/emusound_pcm.c_inc b/src/static/jaudio_PP/game/emusound_pcm.c_inc new file mode 100644 index 00000000..09486fa7 --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_pcm.c_inc @@ -0,0 +1,11 @@ +// UNUSED +void* PCM[9] = { (void*)&_STOP, (void*)&_STOP, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +// UNUSED +u32 PCMSIZE[9] = { sizeof(_STOP), sizeof(_STOP), 0, 0, 0, 0, 0, 0, 0 }; + +// @unused, @fabricated +void* Sound_GetPCM(u8 no, u32* size) { + *size = PCMSIZE[no]; + return PCM[no]; +} diff --git a/src/static/jaudio_PP/game/emusound_vrc.c_inc b/src/static/jaudio_PP/game/emusound_vrc.c_inc new file mode 100644 index 00000000..530779ba --- /dev/null +++ b/src/static/jaudio_PP/game/emusound_vrc.c_inc @@ -0,0 +1,239 @@ +s32 __GetWave_Pulse(s32 a, s32 b) { + switch (a) { + + case 0: { + if (b >= 4 && b <= 7) { + return 1; + } else { + return 0; + } + } + case 1: { + return b <= 7; + } + case 2: { + return b <= 15; + } + case 3: { + return b > 7; + } + case 0xb: { + return b & 0xff; + } + case 0xc: { + return b <= 0 ? 127 : 0; + } + case 0xd: { + return b <= 1 ? 127 : 0; + } + case 0xe: { + return b <= 2 ? 127 : 0; + } + case 0xf: { + return b <= 3 ? 127 : 0; + } + case 0x10: { + return b <= 4 ? 127 : 0; + } + case 0x11: { + return b <= 5 ? 0 : 127; + } + case 0x12: { + return b <= 6 ? 0 : 127; + } + case 0x13: { + return b <= 7 ? 0 : 127; + } + } + return a; +} + +u32 __PitchTo32_VRC_C(u16 pitch) { + f32 scalefactor = 2.f; + return (u32)((NES_CLOCK_SPEED - 0.25f) / scalefactor / (pitch + 1) / 1000.875f * 32768.f); +} + +u32 __PitchTo32_VRC_PULSE(u16 pitch) { + f32 scalefactor = 16.f; + return (u32)((NES_CLOCK_SPEED - 0.25f) / scalefactor / (pitch + 1) / 1000.875f * 32768.f); +} + +u32 __PitchTo32_HVC(u16 pitch) { + f32 scalefactor = 8.f; + return (u32)((NES_CLOCK_SPEED - 0.25f) / scalefactor / (pitch + 1) / 1000.875f * 32768.f); +} + +void __Sound_Write_VRC(u16 a, u8 b) { + NESSoundStruct* pSound; + Unknown_VRC* pBuffer; + int v; + int xyzIndex; + + u16 index = a - 0xc0; + if (index <= 3) { + pSound = &SoundX; + xyzIndex = 0; + pBuffer = &sbuffer.apu._C0; + } else if (index <= 7) { + pSound = &SoundY; + xyzIndex = 1; + pBuffer = &sbuffer.apu._C4; + } else { + pSound = &SoundZ; + xyzIndex = 2; + pBuffer = &sbuffer.apu._C8; + } + + if (index == 21) { + if (!(b & 1)) { + SoundX._00 = 0; + } + if (!(b & 2)) { + SoundY._00 = 0; + } + if (!(b & 4)) { + SoundZ._00 = 0; + } + return; + } + + switch (index & 3) { + case 0: { + pSound->_3C = pBuffer->_0_6; + pSound->_28 = pBuffer->_0_7; + pSound->_1C = VOLTABLE_VRCPULSE[pBuffer->_0_3]; + pSound->_1D = pBuffer->_0_3; + pSound->_2A = pSound->_1D; + if (xyzIndex == 2) { + pSound->_24 = ((pSound->_3C & 3) << 4) | pSound->_2A; + pSound->_1C = (pSound->_24 * 7) / 3; + if (pSound->_1C >= 0x7f) { + pSound->_1C = 0x7f; + } + } + } break; + case 2: { + pSound->_0C = (pBuffer->_3_3 << 8) | pBuffer->_2; + if (xyzIndex == 2) { + pSound->_08 = __PitchTo32_VRC_C(pSound->_0C); + } else { + pSound->_08 = __PitchTo32_VRC_PULSE(pSound->_0C); + } + } break; + case 3: { + pSound->_0C = (pBuffer->_3_3 << 8) | pBuffer->_2; + if (xyzIndex == 2) { + pSound->_08 = __PitchTo32_VRC_C(pSound->_0C); + } else { + pSound->_08 = __PitchTo32_VRC_PULSE(pSound->_0C); + } + + if (!pSound->_00 && !pSound->_3E) { + pSound->_04 = 0; + } + + if (xyzIndex == 0) { + v = sbuffer.apu._D5_0; + } + if (xyzIndex == 1) { + v = sbuffer.apu._D5_1; + } + if (xyzIndex == 2) { + v = sbuffer.apu._D5_2; + } + + if ((u8)v == 1 && pBuffer->_3_7) { + pSound->_00 = 1; + } else { + pSound->_00 = 0; + } + + pSound->_2A = pSound->_1D; + pSound->_20 = 0; + } break; + } +} + +void __Sound_Write_MMC5(u16 a, u8 b) { + NESSoundStruct* pSound; + PulseChannel* pBuffer; + u32 v; + int xyzIndex; + + u16 index = a - 0xc0; + pBuffer = 0; + if (index <= 3) { + pSound = &SoundX; + xyzIndex = 0; + pBuffer = (PulseChannel*)&sbuffer.apu._C0; + } else if (index <= 7) { + pSound = &SoundY; + xyzIndex = 1; + pBuffer = (PulseChannel*)&sbuffer.apu._C4; + } + + if (index == 17) { + SoundZ._3E = (b & 0xff) << 6; + } else if (index == 21) { + if (!(b & 1)) { + SoundX._00 = 0; + } + if (!(b & 2)) { + SoundY._00 = 0; + } + } else if (pBuffer) { + switch (index & 3) { + case 0: { + pSound->_3C = pBuffer->Duty; + v = pSound->_28; + pSound->_28 = pBuffer->ConstantVolume ^ 1; + pSound->_14 = pBuffer->EnvelopeLoopCounter; + pSound->_1D = VOLTABLE_HVCPULSE[pBuffer->EnvelopePeriod_Volume]; + if (pSound->_28 == 0 && pSound->_00 == 1) { + pSound->_1C = VOLTABLE_HVCPULSE[pBuffer->EnvelopePeriod_Volume]; + } else { + pSound->_24 = PHASE_SAMPLE * (pBuffer->EnvelopePeriod_Volume + 1); + if (v == 0) { + pSound->_2A = 0xf; + pSound->_20 = 0; + } + } + } break; + case 2: { + pSound->_0C = pBuffer->TimerHigh << 8 | pBuffer->TimerLow; + pSound->_08 = __PitchTo32_HVC(pSound->_0C); + } break; + case 3: { + pSound->_0C = pBuffer->TimerHigh << 8 | pBuffer->TimerLow; + pSound->_08 = __PitchTo32_HVC(pSound->_0C); + pSound->_18 = LEN_TABLE_HVC[pBuffer->LengthCounterLow]; + pSound->_10 = FRAME_SAMPLE * pSound->_18; + if (!pSound->_00 && !pSound->_3E) { + pSound->_04 = 0; + } + + if (xyzIndex == 0) { + v = sbuffer.apu._D5_0; + } + if (xyzIndex == 1) { + v = sbuffer.apu._D5_1; + } + + if ((v & 0xff) != 0) { + pSound->_00 = 1; + } + + if (pBuffer->ConstantVolume == 0) { + pSound->_1C = VOLTABLE_HVCPULSE[15]; + } else { + pSound->_1C = pSound->_1D; + } + + pSound->_2A = 0xf; + pSound->_20 = 0; + pSound->_30 = 0; + pSound->_3A = 0; + } break; + } + } +} diff --git a/src/static/jaudio_PP/internal/audiothread.c b/src/static/jaudio_PP/internal/audiothread.c index 2461d12d..d8000fe1 100644 --- a/src/static/jaudio_PP/internal/audiothread.c +++ b/src/static/jaudio_PP/internal/audiothread.c @@ -18,7 +18,7 @@ #include "jaudio_NES/playercall.h" #include "jaudio_NES/dspbuf.h" -#define AUDIO_STACK_SIZE 0x1000 +#define AUDIO_STACK_SIZE 0x2000 #define AUDIOPROC_MQ_BUF_COUNT 16 #define AUDIOPROC_MESSAGE_UPDATE_DAC ((OSMessage)0) @@ -76,10 +76,7 @@ extern void NeosSync(void) { static void __DspSync(__OSInterrupt interrupt, OSContext* context) { u16 reg = __DSPRegs[DSP_CONTROL_STATUS]; - reg &= ~(1 << 3); /* clear AI interrupt */ - reg &= ~(1 << 5); /* clear AR interrupt */ - reg |= (1 << 7); /* set DSP interrupt */ - __DSPRegs[DSP_CONTROL_STATUS] = reg; + __DSPRegs[DSP_CONTROL_STATUS] = (reg & ~((1 << 3) | (1 << 5))) | (1 << 7); /* clear AI/AR interrupts, set DSP interrupt */ OSContext tmp_context; OSClearContext(&tmp_context); diff --git a/src/static/jaudio_PP/internal/driver.c b/src/static/jaudio_PP/internal/driver.c index cda340e6..c144cbd6 100644 --- a/src/static/jaudio_PP/internal/driver.c +++ b/src/static/jaudio_PP/internal/driver.c @@ -41,1427 +41,5 @@ static Acmd* __LoadAuxBuf(Acmd* cmd, u16 ofs, u16 startPos, s32 size, delay* del static Acmd* __SaveAuxBuf(Acmd* cmd, u16 ofs, u16 startPos, s32 size, delay* del_p); static Acmd* Nas_SaveBufferAuto(Acmd* cmd, u16 ofs, u16 size, s32 startAddr); -static void Nas_CpuFX(s32 chunkLen, s32 updateIdx, s32 reverbIdx) { - delayparam* param_p; - s32 count; - delay* del_p; - s32 t; - s32 i; - s32 sample2; - s32 next_buf_pos; - s32 t2; - s32 idx; - s32 t3; - s32 sample; - s32 n; - s32 s; - - del_p = &AG.synth_delay[reverbIdx]; - param_p = &del_p->params[del_p->cur_frame][updateIdx]; - count = chunkLen / AG.synth_delay[reverbIdx].downsample_rate; - if (AG.synth_delay[reverbIdx].resample_effect_on && AG.synth_delay[reverbIdx].downsample_rate == 1 && del_p->right_save_resample_buf != NULL) { - count += del_p->resample_effect_extra_samples; - param_p->save_resample_num_samples = count; - param_p->load_resample_pitch = (param_p->save_resample_num_samples << 15) / chunkLen; - param_p->save_resample_pitch = (chunkLen << 15) / param_p->save_resample_num_samples; - - n = 10; - s = 10; - for (i = 0; i < 10; i++) { - n--; - sample = del_p->resample_effect_load_unk + param_p->load_resample_pitch * chunkLen * SAMPLE_SIZE; - sample2 = (sample >> 16); - if (sample2 != count && n == 0) { - param_p->load_resample_pitch = (count * 0x10000 - del_p->resample_effect_load_unk) / (chunkLen * SAMPLE_SIZE); - } else if (sample2 > count) { - param_p->load_resample_pitch--; - } else if (sample2 < count) { - param_p->load_resample_pitch++; - } else { - break; - } - } - - del_p->resample_effect_load_unk = sample; - - for (i = 0; i < 10; i++) { - s--; - sample = del_p->resample_effect_save_unk + param_p->save_resample_pitch * count * SAMPLE_SIZE; - sample2 = (sample >> 16); - if (sample2 != chunkLen && s == 0) { - param_p->save_resample_pitch = (chunkLen * 0x10000 - del_p->resample_effect_save_unk) / (count * SAMPLE_SIZE); - } else if (sample2 > chunkLen) { - param_p->save_resample_pitch--; - } else if (sample2 < chunkLen) { - param_p->save_resample_pitch++; - } else { - break; - } - } - - del_p->resample_effect_save_unk = sample; - } - - next_buf_pos = del_p->next_reverb_buf_pos; - t = del_p->next_reverb_buf_pos + count - del_p->delay_num_samples; - - if (t < 0) { - param_p->size = count * SAMPLE_SIZE; - param_p->wrapped_size = 0; - param_p->start_pos = del_p->next_reverb_buf_pos; - del_p->next_reverb_buf_pos += count; - } else { - param_p->size = (count - t) * SAMPLE_SIZE; - param_p->wrapped_size = t * SAMPLE_SIZE; - param_p->start_pos = del_p->next_reverb_buf_pos; - del_p->next_reverb_buf_pos = t; - } - - param_p->n_samples_after_downsampling = count; - param_p->n_samples = chunkLen; - - if (del_p->sub_delay != 0) { - t = del_p->delay_num_samples; - idx = next_buf_pos + del_p->sub_delay; - while (idx >= t) { - idx -= t; - } - - param_p = del_p->sub_params[del_p->cur_frame] + updateIdx; - t2 = chunkLen / del_p->downsample_rate; - t3 = idx + t2 - t; - - if (t3 < 0) { - param_p->size = t2 * SAMPLE_SIZE; - param_p->wrapped_size = 0; - param_p->start_pos = idx; - } else { - param_p->size = (t2 - t3) * SAMPLE_SIZE; - param_p->wrapped_size = t3 * SAMPLE_SIZE; - param_p->start_pos = idx; - } - - param_p->n_samples_after_downsampling = t2; - param_p->n_samples = chunkLen; - } -} - -static void __Nas_PushDrvReg(s32 updateIdx) { - s32 i; - commonch* common0; - commonch* common1; - s32 baseIdx = updateIdx * AG.num_channels; - - for (i = 0; i < AG.num_channels; i++) { - common0 = &AG.channels[i].common_ch; - common1 = &AG.common_channel[baseIdx + i]; - - if (common0->enabled) { - CopyStc(common1, common0); - common0->needs_init = FALSE; - } else { - common1->enabled = FALSE; - } - - common0->harmonic_idx_cur_and_prev = 0; - } -} - -extern Acmd* Nas_smzAudioFrame(Acmd* cmdStart, s32* cmdCount, s16* aiStart, s32 aiBufLen) { - Acmd* cmdP; - s16* aiBufP; - s32 chunkLen; - s32 i; - s32 j; - - cmdP = cmdStart; - for (i = AG.audio_params.updates_per_frame; i > 0; i--) { - Nas_MySeqMain(i - 1); - __Nas_PushDrvReg(AG.audio_params.updates_per_frame - i); - } - - aiBufP = aiStart; - AG.adpcm_code_book = NULL; - - for (i = AG.audio_params.updates_per_frame; i > 0; i--) { - chunkLen = AG.audio_params.num_samples_per_update; - - for (j = 0; j < AG.num_synth_reverbs; j++) { - if (AG.synth_delay[j].use_reverb) { - Nas_CpuFX(chunkLen, AG.audio_params.updates_per_frame - i, j); - } - } - - cmdP = Nas_DriveRsp(aiBufP, chunkLen, cmdP, AG.audio_params.updates_per_frame - i); - aiBufLen -= chunkLen; - aiBufP += (JAC_FRAMESAMPLES >> 1) & ~1; - } - - for (j = 0; j < AG.num_synth_reverbs; j++) { - if (AG.synth_delay[j].frames_to_ignore != 0) { - AG.synth_delay[j].frames_to_ignore--; - } - AG.synth_delay[j].cur_frame ^= 1; - } - - *cmdCount = cmdP - cmdStart; - return cmdP; -} - -static void __Nas_WaveTerminateProcess(s32 updateIdx, s32 chanIdx) { - commonch* common; - s32 i; - - for (i = updateIdx + 1; i < AG.audio_params.updates_per_frame; i++) { - common = &AG.common_channel[i * AG.num_channels + chanIdx]; - if (!common->needs_init) { - common->enabled = FALSE; - } else { - break; - } - } -} - -static Acmd* Nas_LoadAux2nd(Acmd* cmd, const delay* del_p, s16 updateIdx) { - const delayparam* param = &del_p->params[del_p->cur_frame][updateIdx]; - - cmd = __LoadAuxBuf(cmd, 0x3A0, param->start_pos, param->size, (delay*)del_p); - if (param->wrapped_size != 0) { - cmd = __LoadAuxBuf(cmd, 0x3A0 + param->size, 0, param->wrapped_size, (delay*)del_p); - } - - return cmd; -} - -static Acmd* Nas_SaveAux2nd(Acmd* cmd, const delay* del_p, s16 updateIdx) { - const delayparam* param = &del_p->params[del_p->cur_frame][updateIdx]; - - cmd = __SaveAuxBuf(cmd, 0x3A0, param->start_pos, param->size, (delay*)del_p); - if (param->wrapped_size != 0) { - cmd = __SaveAuxBuf(cmd, 0x3A0 + param->size, 0, param->wrapped_size, (delay*)del_p); - } - - return cmd; -} - -static void Nas_ClearBuffer(Acmd* cmd, s32 dmem, s32 size) { - aClearBuffer(cmd, dmem, size); -} - -static void Nas_Mix(Acmd* cmd, s32 flags, s32 gain, s32 dmem_in, s32 dmem_out) { - aMix(cmd, flags, gain, dmem_in, dmem_out); -} - -static void Nas_SetBuffer(Acmd* cmd, s32 flags, s32 dmem_in, s32 dmem_out, s32 count) { - aSetBuffer(cmd, flags, dmem_in, dmem_out, count); -} - -static void Nas_DMEMMove(Acmd* cmd, s32 dmem_in, s32 dmem_out, s32 count) { - aDMEMMove(cmd, dmem_in, dmem_out, count); -} - -static void Nas_HalfCut(Acmd* cmd, s32 src, s32 dst, s32 len) { - aHalfCut(cmd, src, dst, len); -} - -static void Nas_SetEnvParam(Acmd* cmd, s32 reverbVol, s32 rampReverb, s32 rampL, s32 rampR) { - aSetEnvParam(cmd, reverbVol, rampReverb, rampL, rampR); -} - -static void Nas_LoadBuffer2(Acmd* cmd, s32 dst, s32 len, s32 src) { - aLoadBuffer2(cmd, src, dst, len); -} - -static void Nas_SaveBuffer2(Acmd* cmd, s32 src, s32 len, s32 dst) { - aSaveBuffer2(cmd, dst, src, len); -} - -static void Nas_SetEnvParam2(Acmd* cmd, s32 volL, s32 volR) { - aSetEnvParam2(cmd, volL, volR); -} - -static void Nas_PCM8dec(Acmd* cmd, s32 flags, s32 state) { - aPCM8dec(cmd, flags, state); -} - -static void Nas_DistFilter(Acmd* cmd, s32 gain, s32 dmem_in, s32 dmem_out, s32 len) { - aDistFilter(cmd, gain, dmem_in, dmem_out, len); -} - -// TODO: check params -static void Nas_NoiseFilter(Acmd* cmd, s32 buf, s32 flags, s32 addr, s32 len) { - aNoiseFilter(cmd, buf, flags, addr, len); -} - -static void Nas_FirFilter(Acmd* cmd, s32 flags, s32 buf, s16* filter) { - aFirFilter(cmd, flags, buf, filter); -} - -static void Nas_FirLoadTable(Acmd* cmd, s32 size, s16* filter) { - aFirLoadTable(cmd, size, filter); -} - -static Acmd* Nas_CrossMix(Acmd* cmd, delay* del_p) { - aDMEMMove(cmd++, 0xC40, 0x6E0, 0x1A0); - aMix(cmd++, 0x1A, del_p->leak_rtl, 0xDE0, 0xC40); - aMix(cmd++, 0x1A, del_p->leak_ltl, 0x6E0, 0xDe0); - return cmd; -} - -static Acmd* Nas_LoadAuxBufferC(Acmd* cmd, s32 samples_per_update, delay* del_p, s16 update_idx) { - delayparam* param = &del_p->params[del_p->cur_frame][update_idx]; - s16 ofs_size = (param->start_pos & 7) * SAMPLE_SIZE; - - cmd = __LoadAuxBuf(cmd, 0x3A0, param->start_pos - (ofs_size / SAMPLE_SIZE), 0x1A0, del_p); - if (param->wrapped_size != 0) { - s16 wrapped_ofs_size = ALIGN_NEXT(ofs_size + param->size, 16); - - cmd = __LoadAuxBuf(cmd, 0x3A0 + wrapped_ofs_size, 0, 0x1A0 - wrapped_ofs_size, del_p); - } - - aSetBuffer(cmd++, 0, 0x3A0 + ofs_size, 0xC40, samples_per_update * SAMPLE_SIZE); - aResample(cmd++, del_p->resample_flags, del_p->downsample_pitch, del_p->left_load_resample_buf); - aSetBuffer(cmd++, 0, 0x3A0 + 0x1A0 + ofs_size, 0xDE0, samples_per_update * SAMPLE_SIZE); - aResample(cmd++, del_p->resample_flags, del_p->downsample_pitch, del_p->right_load_resample_buf); - return cmd; -} - -static Acmd* Nas_SaveAuxBufferCH(Acmd* cmd, delay* del_p, s16 update_idx) { - delayparam* param = &del_p->params[del_p->cur_frame][update_idx]; - s16 samples = param->n_samples; - u32 size = samples * SAMPLE_SIZE; - - aDMEMMove(cmd++, 0xC40, 0x3A0, size); - aSetBuffer(cmd++, 0, 0x3A0, 0x6E0, param->save_resample_num_samples * SAMPLE_SIZE); - aResample(cmd++, del_p->resample_flags, param->save_resample_pitch, del_p->left_save_resample_buf); - cmd = Nas_SaveBufferAuto(cmd, 0x6E0, param->size, (s32)&del_p->left_reverb_buf[param->start_pos]); - if (param->wrapped_size != 0) { - cmd = Nas_SaveBufferAuto(cmd, 0x6E0 + param->size, param->wrapped_size, (s32)&del_p->left_reverb_buf[0]); - } - - aDMEMMove(cmd++, 0xDE0, 0x3A0, size); - aSetBuffer(cmd++, 0, 0x3A0, 0x6E0, param->save_resample_num_samples * SAMPLE_SIZE); - aResample(cmd++, del_p->resample_flags, param->save_resample_pitch, del_p->right_save_resample_buf); - cmd = Nas_SaveBufferAuto(cmd, 0x6E0, param->size, (s32)&del_p->right_reverb_buf[param->start_pos]); - if (param->wrapped_size != 0) { - cmd = Nas_SaveBufferAuto(cmd, 0x6E0 + param->size, param->wrapped_size, (s32)&del_p->right_reverb_buf[0]); - } - - return cmd; -} - -static Acmd* Nas_LoadAuxBufferCH(Acmd* cmd, s32 samples_per_update, delay* del_p, s16 update_idx) { - delayparam* param = &del_p->params[del_p->cur_frame][update_idx]; - s16 ofs_size = (param->start_pos & 7) * SAMPLE_SIZE; - - cmd = __LoadAuxBuf(cmd, 0x3A0, param->start_pos - (ofs_size / SAMPLE_SIZE), 0x1A0, del_p); - if (param->wrapped_size != 0) { - s16 wrapped_ofs_size = ALIGN_NEXT(ofs_size + param->size, 16); - s32 load_size = 0x1A0 - wrapped_ofs_size; - - if (load_size > 0) { - cmd = __LoadAuxBuf(cmd, 0x3A0 + wrapped_ofs_size, 0, load_size, del_p); - } - } - - aSetBuffer(cmd++, 0, 0x3A0 + ofs_size, 0xC40, samples_per_update * SAMPLE_SIZE); - aResample(cmd++, del_p->resample_flags, param->load_resample_pitch, del_p->left_load_resample_buf); - aSetBuffer(cmd++, 0, 0x3A0 + 0x1A0 + ofs_size, 0xDE0, samples_per_update * SAMPLE_SIZE); - aResample(cmd++, del_p->resample_flags, param->load_resample_pitch, del_p->right_load_resample_buf); - return cmd; -} - -static Acmd* Nas_DelayFilter(Acmd* cmd, s32 size, delay* del_p) { - if (del_p->filter_left != NULL) { - aFirLoadTable(cmd++, size, del_p->filter_left); - aFirFilter(cmd++, del_p->resample_flags, 0xC40, del_p->filter_left_state); - } - - if (del_p->filter_right != NULL) { - aFirLoadTable(cmd++, size, del_p->filter_right); - aFirFilter(cmd++, del_p->resample_flags, 0xDE0, del_p->filter_right_state); - } - - return cmd; -} - -static Acmd* Nas_SendLine(Acmd* cmd, delay* del_p, s32 update_idx) { - delay* mix_delay; - - if (del_p->mix_reverb_idx >= AG.num_synth_reverbs) { - return cmd; - } - - mix_delay = &AG.synth_delay[del_p->mix_reverb_idx]; - if (mix_delay->downsample_rate == 1) { - cmd = Nas_LoadAux2nd(cmd, mix_delay, update_idx); - aMix(cmd++, 0x34, del_p->mix_reverb_strength, 0xC40, 0x3A0); - cmd = Nas_LoadAux2nd(cmd, mix_delay, update_idx); - } - - return cmd; -} - -static Acmd* Nas_LoadAuxBuffer1(Acmd* cmd, s32 samples_per_update, delay* del_p, s16 update_idx) { - delayparam* param_p = &del_p->params[del_p->cur_frame][update_idx]; - - cmd = __LoadAuxBuf(cmd, 0xC40, param_p->start_pos, param_p->size, del_p); - if (param_p->wrapped_size != 0) { - cmd = __LoadAuxBuf(cmd, 0xC40 + param_p->size, 0, param_p->wrapped_size, del_p); - } - - return cmd; -} - -static Acmd* Nas_LoadAuxBuffer1_B(Acmd* cmd, s32 samples_per_update, delay* del_p, s16 update_idx) { - delayparam* param_p = &del_p->sub_params[del_p->cur_frame][update_idx]; - - cmd = __LoadAuxBuf(cmd, 0xC40, param_p->start_pos, param_p->size, del_p); - if (param_p->wrapped_size != 0) { - cmd = __LoadAuxBuf(cmd, 0xC40 + param_p->size, 0, param_p->wrapped_size, del_p); - } - - return cmd; -} - -static Acmd* Nas_SaveBufferAuto(Acmd* cmd, u16 dmem, u16 size, s32 startAddr) { - s32 startUnaligned = startAddr & 15; - s32 endAddr = startAddr + size; - s32 endUnaligned = endAddr & 15; - - if (endUnaligned != 0) { - aLoadBuffer2(cmd++, (endAddr - endUnaligned), 0x380, 16); - aDMEMMove(cmd++, dmem, 0x390, size); - aDMEMMove(cmd++, 0x380 + endUnaligned, 0x390 + size, 16 - endUnaligned); - size += 16 - endUnaligned; - dmem = 0x390; - } - - if (startUnaligned != 0) { - aLoadBuffer2(cmd++, (startAddr - startUnaligned), 0x380, 16); - aDMEMMove(cmd++, dmem, 0x380 + startUnaligned, size); - - size += startUnaligned; - dmem = 0x380; - } - - aSaveBuffer2(cmd++, startAddr - startUnaligned, dmem, size); - return cmd; -} - -static Acmd* __LoadAuxBuf(Acmd* cmd, u16 dmem, u16 startPos, s32 size, delay* del_p) { - aLoadBuffer2(cmd++, &del_p->left_reverb_buf[startPos], dmem, size); - aLoadBuffer2(cmd++, &del_p->right_reverb_buf[startPos], dmem + 0x1A0, size); - return cmd; -} - -static Acmd* __SaveAuxBuf(Acmd* cmd, u16 dmem, u16 startPos, s32 size, delay* del_p) { - aSaveBuffer2(cmd++, &del_p->left_reverb_buf[startPos], dmem, size); - aSaveBuffer2(cmd++, &del_p->right_reverb_buf[startPos], dmem + 0x1A0, size); - return cmd; -} - -static Acmd* Nas_LoadAuxBuffer_B(Acmd* cmd, s32 numSamplesPerUpdate, delay* del_p, s16 updateIdx) { - if (del_p->downsample_rate == 1) { - cmd = Nas_LoadAuxBuffer1_B(cmd, numSamplesPerUpdate, del_p, updateIdx); - } - - return cmd; -} - -static Acmd* Nas_LoadAuxBuffer(Acmd* cmd, s32 numSamplesPerUpdate, delay* del_p, s16 updateIdx) { - if (del_p->downsample_rate == 1) { - if (del_p->resample_effect_on) { - cmd = Nas_LoadAuxBufferCH(cmd, numSamplesPerUpdate, del_p, updateIdx); - } else { - cmd = Nas_LoadAuxBuffer1(cmd, numSamplesPerUpdate, del_p, updateIdx); - } - } else { - cmd = Nas_LoadAuxBufferC(cmd, numSamplesPerUpdate, del_p, updateIdx); - } - - return cmd; -} - -static Acmd* Nas_SaveAuxBuffer(Acmd* cmd, delay* del_p, s16 update_idx) { - delayparam* param = &del_p->params[del_p->cur_frame][update_idx]; - s32 downsample_rate; - s32 n_samples; - - switch (del_p->downsample_rate) { - case 1: - if (del_p->resample_effect_on) { - cmd = Nas_SaveAuxBufferCH(cmd, del_p, update_idx); - } else { - cmd = __SaveAuxBuf(cmd, 0xC40, param->start_pos, param->size, del_p); - if (param->wrapped_size != 0) { - cmd = __SaveAuxBuf(cmd, 0xC40 + param->size, 0, param->wrapped_size, del_p); - } - } - break; - default: - downsample_rate = del_p->downsample_rate; - n_samples = 13 * 16; // 16 = SAMPLES_PER_FRAME - - while (downsample_rate > 1) { - aHalfCut(cmd++, 0xC40, 0xC40, n_samples); - aHalfCut(cmd++, 0xDE0, 0xDE0, n_samples); - n_samples >>= 1; - downsample_rate >>= 1; - } - - if (param->size != 0) { - cmd = Nas_SaveBufferAuto(cmd, 0xC40, (u16)param->size, (s32)&del_p->left_reverb_buf[param->start_pos]); - cmd = Nas_SaveBufferAuto(cmd, 0xDE0, (u16)param->size, (s32)&del_p->right_reverb_buf[param->start_pos]); - } - - if (param->wrapped_size != 0) { - cmd = Nas_SaveBufferAuto(cmd, 0xC40 + param->size, (u16)param->wrapped_size, (s32)&del_p->left_reverb_buf[0]); - cmd = Nas_SaveBufferAuto(cmd, 0xDE0 + param->size, (u16)param->wrapped_size, (s32)&del_p->right_reverb_buf[0]); - } - break; - } - - del_p->resample_flags = 0; - return cmd; -} - -static Acmd* Nas_SaveAuxBuffer_B(Acmd* cmd, delay* del_p, s16 update_idx) { - delayparam* param = &del_p->sub_params[del_p->cur_frame][update_idx]; - - cmd = __SaveAuxBuf(cmd, 0xC40, param->start_pos, param->size, del_p); - if (param->wrapped_size != 0) { - cmd = __SaveAuxBuf(cmd, 0xC40 + param->size, 0, param->wrapped_size, del_p); - } - - return cmd; -} - -extern Acmd* Nas_DriveRsp(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updateIndex) { - s32 size = aiBufLen * SAMPLE_SIZE; - u8 noteIndices[64]; - s32 noteCount = 0; - s32 reverbIndex; - delay* reverb; - s32 useReverb; - s32 sampleStateOffset = updateIndex * AG.num_channels; - s32 i; - commonch* sampleState; - - if (AG.num_synth_reverbs == 0) { - int idx = sampleStateOffset; - for (i = 0; i < AG.num_channels; i++) { - if (AG.common_channel[idx++].enabled) { - noteIndices[noteCount++] = i; - } - } - } else { - for (reverbIndex = 0; reverbIndex < AG.num_synth_reverbs; reverbIndex++) { - for (i = 0; i < AG.num_channels; i++) { - sampleState = &AG.common_channel[sampleStateOffset + i]; - if (sampleState->enabled && (sampleState->reverb_idx == reverbIndex)) { - noteIndices[noteCount++] = i; - } - } - } - - for (i = 0; i < AG.num_channels; i++) { - sampleState = &AG.common_channel[sampleStateOffset + i]; - if (sampleState->enabled && (sampleState->reverb_idx >= AG.num_synth_reverbs)) { - noteIndices[noteCount++] = i; - } - } - } - - aClearBuffer(cmd++, DMEM_LEFT_CH, DMEM_2CH_SIZE); - - i = 0; - for (reverbIndex = 0; reverbIndex < AG.num_synth_reverbs; reverbIndex++) { - s32 subDelay; - // commonch* sampleState; - - reverb = &AG.synth_delay[reverbIndex]; - useReverb = reverb->use_reverb; - if (useReverb) { - // Loads reverb samples from DRAM (ringBuffer) into DMEM (DMEM_WET_LEFT_CH) - cmd = Nas_LoadAuxBuffer(cmd, aiBufLen, reverb, updateIndex); - - // Mixes reverb sample into the main dry channel - // reverb->volume is always set to 0x7FFF (audio spec), and DMEM_LEFT_CH is cleared before reverbs. - // So this is essentially a DMEMmove from DMEM_WET_LEFT_CH to DMEM_LEFT_CH - aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->volume, DMEM_WET_LEFT_CH, DMEM_LEFT_CH); - - subDelay = reverb->sub_delay; - if (subDelay != 0) { - aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, DMEM_2CH_SIZE); - } - - // Decays reverb over time. The (+ 0x8000) here is -100% - aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->decay_ratio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH); - - if (((reverb->leak_rtl != 0) || (reverb->leak_ltl != 0)) && (AG.sound_mode != SOUND_OUTPUT_MONO)) { - cmd = Nas_CrossMix(cmd, reverb); - } - - if (subDelay != 0) { - if (reverb->mix_reverb_idx != -1) { - cmd = Nas_SendLine(cmd, reverb, updateIndex); - } - - cmd = Nas_SaveAuxBuffer(cmd, reverb, updateIndex); - cmd = Nas_LoadAuxBuffer_B(cmd, aiBufLen, reverb, updateIndex); - aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->sub_volume, DMEM_WET_TEMP, DMEM_WET_LEFT_CH); - } - } - - while (i < noteCount) { - sampleState = &AG.common_channel[sampleStateOffset + noteIndices[i]]; - if (sampleState->reverb_idx != reverbIndex) { - break; - } - cmd = Nas_SynthMain(noteIndices[i], sampleState, &AG.channels[noteIndices[i]].driver_ch, - aiBuf, aiBufLen, cmd, updateIndex); - i++; - } - - if (useReverb) { - if ((reverb->filter_left != NULL) || (reverb->filter_right != NULL)) { - cmd = Nas_DelayFilter(cmd, size, reverb); - } - - // Saves the wet channel sample from DMEM (DMEM_WET_LEFT_CH) into (ringBuffer) DRAM for future use - if (subDelay != 0) { - cmd = Nas_SaveAuxBuffer_B(cmd, reverb, updateIndex); - } else { - if (reverb->mix_reverb_idx != -1) { - cmd = Nas_SendLine(cmd, reverb, updateIndex); - } - cmd = Nas_SaveAuxBuffer(cmd, reverb, updateIndex); - } - } - } - - while (i < noteCount) { - cmd = Nas_SynthMain(noteIndices[i], &AG.common_channel[sampleStateOffset + noteIndices[i]], - &AG.channels[noteIndices[i]].driver_ch, aiBuf, aiBufLen, cmd, - updateIndex); - i++; - } - - // size = aiBufLen * SAMPLE_SIZE; - aInterleave2(cmd++, DMEM_TEMP, DMEM_LEFT_CH, DMEM_RIGHT_CH, size); - - if (NA_DACOUT_CALLBACK != NULL) { - cmd = (Acmd*)((u32)NA_DACOUT_CALLBACK(cmd, 2 * size, updateIndex) & 0xFF); // ?? what is this? this has to be a bug - } - - aSaveBuffer2(cmd++, aiBuf, DMEM_TEMP, JAC_FRAMESAMPLES); - - return cmd; -} - -extern Acmd* Nas_SynthMain(s32 chan_id, commonch* common, driverch* driver, s16* samples, s32 samples_per_update, Acmd* cmd, s32 update_idx) { - s32 pad1[1]; - s32 size; - void* reverbAddrSrc; - smzwavetable* sample; - adpcmloop* loopInfo; - s32 numSamplesUntilEnd; - s32 flags; - s32 skipBytes; - s32 dmemUncompressedAddrOffset1; - s32 numSamplesToLoadAdj; - s32 numSamplesProcessed; - s32 numFirstFrameSamplesToIgnore; - s32 numSamplesToDecode; - s32 numSamplesInThisIteration; - s32 sampleFinished; - s32 loopToPoint; - u16 frequencyFixedPoint; - s32 gain; - s32 frameIndex; - u32 numSamplesToLoadFixedPoint; - s32 numSamplesToLoad; - u8* sampleAddr; - s32 sampleEndPos; - s32 numSamplesToProcess; - s32 dmemUncompressedAddrOffset2; - s32 pad2[3]; - s32 numSamplesInFirstFrame; - s32 numTrailingSamplesToIgnore; - s32 pad3[3]; - s16 sampleDataDmemAddr; - s32 frameSize; - s32 numFramesToDecode; - u8* samplesToLoadAddr; - s32 numParts; - s32 curPart; - s32 sampleDataChunkAlignPad; - s32 haasEffectDelaySide; - s32 sampleDataChunkSize; - s32 skipInitialSamples; - s32 zeroOffset; - s32 sampleAddrOffset; - s32 combFilterDmem; - channel* chan; - u32 combFilterSize; - u32 combFilterGain; - void* combFilterState; - s16* filter; - s32 numSamplesToLoadFirstPart; - u16 sampleDmemBeforeResampling; - u16 something_unused_from_sm64; - u32 stack_chan_id; - u32 stack_update_idx; - u8* tmpSamplesToLoadAddr; - s32 bookOffset = common->book_ofs; - s32 finished = common->finished; - - something_unused_from_sm64 = 0; - chan = &AG.channels[chan_id]; - DCTouchRange(chan, sizeof(channel)); - size = SAMPLE_SIZE * samples_per_update; - - // Deviation from MM: Ensure that the wavetable isn't null - if (common->tuned_sample != NULL) { - flags = A_CONTINUE; - - // Initialize the synthesis state - if (common->needs_init == true) { - flags = A_INIT; - driver->at_loop_point = false; - driver->stop_loop = false; - driver->sample_pos_integer_part = chan->playback_ch.start_sample_pos; - driver->sample_pos_fractional_part = 0; - - // deviation from MM - if (chan->playback_ch.adsr_envp.state.flags.unused == TRUE) { - // previously unused ADSR state bit seems to be used for preserving volume - driver->current_volume_left = common->target_volume_left << 4; - driver->current_volume_right = common->target_volume_right << 4; - } else { - driver->current_volume_left = 0; - driver->current_volume_right = 0; - } - - driver->prev_haas_effect_left_delay_size = 0; - driver->prev_haas_effect_right_delay_size = 0; - driver->cur_reverb_vol = common->target_reverb_volume; - driver->num_parts = 0; - driver->comb_filter_needs_init = true; - chan->common_ch.finished = false; - driver->vel_conv_table_idx = chan->playback_ch.vel_conv_table_idx; - finished = false; - } - - // Process the sample in either one or two parts - numParts = common->has_two_parts + 1; - - // Determine number of samples to load based on samples_per_update and relative frequency - frequencyFixedPoint = common->frequency_fixed_point; - numSamplesToLoadFixedPoint = (frequencyFixedPoint * samples_per_update * SAMPLE_SIZE) + driver->sample_pos_fractional_part; - numSamplesToLoad = (u16)(numSamplesToLoadFixedPoint >> 16); - - if (numSamplesToLoad == 0) { - skipBytes = false; - } - - driver->sample_pos_fractional_part = numSamplesToLoadFixedPoint & 0xFFFF; - - // Partially-optimized out no-op ifs required for matching. SM64 decomp - // makes it clear that this is how it should look. - if (((driver->num_parts == 1) && (numParts == 2))) { - } else if (((driver->num_parts == 2) && (numParts == 1))) { - } else { - something_unused_from_sm64 = 0; - } - - driver->num_parts = numParts; - - // deviation from MM here, no synth wave check - - sample = common->tuned_sample->wavetable; - loopInfo = sample->loop; - - if (chan->playback_ch.status != 0) { - driver->stop_loop = true; - } - - if ((loopInfo->count == 2) && driver->stop_loop) { - sampleEndPos = loopInfo->sample_end; - } else { - sampleEndPos = loopInfo->loop_end; - } - - stack_chan_id = chan_id; - stack_update_idx = update_idx; - sampleAddr = sample->sample; - numSamplesToLoadFirstPart = 0; - - // If the frequency requested is more than double that of the raw sample, - // then the sample processing is split into two parts. - for (curPart = 0; curPart < numParts; curPart++) { - numSamplesProcessed = 0; - dmemUncompressedAddrOffset1 = 0; - - // Adjust the number of samples to load only if there are two parts and an odd number of samples - if (numParts == 1) { - numSamplesToLoadAdj = numSamplesToLoad; - } else if ((s32)numSamplesToLoad & 1) { - // round down for the first part - // round up for the second part - numSamplesToLoadAdj = (numSamplesToLoad & ~1) + (curPart * 2); - } else { - numSamplesToLoadAdj = numSamplesToLoad; - } - - // Load the ADPCM codeBook - if ((sample->codec == CODEC_ADPCM) || (sample->codec == CODEC_SMALL_ADPCM)) { - if (AG.adpcm_code_book != sample->book->codebook) { - u32 numEntries; - - switch (bookOffset) { - case 1: - // AG.adpcm_code_book = &gInvalidAdpcmCodeBook[1]; - // break; - - case 2: - case 3: - default: - AG.adpcm_code_book = sample->book->codebook; - break; - } - - numEntries = SAMPLE_SIZE * sample->book->order * sample->book->n_predictors; - numEntries *= 8; // deviation from MM: multiply numEntries by 8 - if (numEntries != 0) { - aLoadADPCM(cmd++, numEntries, AG.adpcm_code_book); - } - } - } - - // Continue processing samples until the number of samples needed to load is reached - while (numSamplesProcessed != numSamplesToLoadAdj) { - sampleFinished = false; - loopToPoint = false; - dmemUncompressedAddrOffset2 = 0; - - numFirstFrameSamplesToIgnore = driver->sample_pos_integer_part & 0xF; - numSamplesUntilEnd = sampleEndPos - driver->sample_pos_integer_part; - - // Calculate number of samples to process this loop - numSamplesToProcess = numSamplesToLoadAdj - numSamplesProcessed; - - if ((numFirstFrameSamplesToIgnore == 0) && !driver->at_loop_point) { - numFirstFrameSamplesToIgnore = SAMPLES_PER_FRAME; - } - numSamplesInFirstFrame = SAMPLES_PER_FRAME - numFirstFrameSamplesToIgnore; - - // Determine the number of samples to decode based on whether the end will be reached or not. - if (numSamplesUntilEnd > numSamplesToProcess) { - // The end will not be reached. - numFramesToDecode = - (s32)(numSamplesToProcess + SAMPLES_PER_FRAME - 1 - numSamplesInFirstFrame) / SAMPLES_PER_FRAME; - numSamplesToDecode = numFramesToDecode * SAMPLES_PER_FRAME; - numTrailingSamplesToIgnore = numSamplesInFirstFrame + numSamplesToDecode - numSamplesToProcess; - } else { - // The end will be reached. - numSamplesToDecode = numSamplesUntilEnd - numSamplesInFirstFrame; - if (numSamplesToDecode <= 0) { - numSamplesToDecode = 0; - numSamplesInFirstFrame = numSamplesUntilEnd; - } - numTrailingSamplesToIgnore = 0; - numFramesToDecode = (numSamplesToDecode + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME; - if (loopInfo->count != 0) { - if ((loopInfo->count == 2) && driver->stop_loop) { - sampleFinished = true; - } else { - // Loop around and restart - loopToPoint = true; - } - } else { - sampleFinished = true; - } - } - - // Set parameters based on compression type - switch (sample->codec) { - case CODEC_ADPCM: - // 16 2-byte samples (32 bytes) compressed into 4-bit samples (8 bytes) + 1 header byte - frameSize = 9; - skipInitialSamples = SAMPLES_PER_FRAME; - zeroOffset = 0; - break; - - case CODEC_SMALL_ADPCM: - // 16 2-byte samples (32 bytes) compressed into 2-bit samples (4 bytes) + 1 header byte - frameSize = 5; - skipInitialSamples = SAMPLES_PER_FRAME; - zeroOffset = 0; - break; - - case CODEC_UNK7: - // 2 2-byte samples (4 bytes) processed without decompression - frameSize = 4; - skipInitialSamples = SAMPLES_PER_FRAME; - zeroOffset = 0; - break; - - case CODEC_S8: - // 16 2-byte samples (32 bytes) compressed into 8-bit samples (16 bytes) - frameSize = 16; - skipInitialSamples = SAMPLES_PER_FRAME; - zeroOffset = 0; - break; - - case CODEC_REVERB: - reverbAddrSrc = (void*)0xFFFFFFFF; - if (NA_SOUND_CALLBACK != NULL) { - // ??? - reverbAddrSrc = (void*)((u32)NA_SOUND_CALLBACK(sample, numSamplesToLoadAdj, flags, chan_id) & 0xFF); - } - - if ((s32)reverbAddrSrc == 0xFFFFFFFF) { - sampleFinished = true; - } else if ((s32)reverbAddrSrc == 0) { - return cmd; - } else { - Nas_LoadBuffer2(cmd++, DMEM_UNCOMPRESSED_NOTE, - numSamplesToLoadAdj * SAMPLE_SIZE + SAMPLES_PER_FRAME * SAMPLE_SIZE, - (s32)reverbAddrSrc); - // deviation from MM: - goto codec_continue_and_skip; - // flags = A_CONTINUE; - // skipBytes = 0; - // numSamplesProcessed = numSamplesToLoadAdj; - // dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; - } - goto skip; - - case CODEC_S16_INMEMORY: - case CODEC_UNK6: - Nas_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, - numSamplesToLoadAdj * SAMPLE_SIZE + SAMPLES_PER_FRAME * SAMPLE_SIZE); -codec_continue_and_skip: - skipBytes = 0; - flags = A_CONTINUE; - numSamplesProcessed = numSamplesToLoadAdj; - dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; - goto skip; - - case CODEC_S16: - Nas_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, - numSamplesToLoadAdj * SAMPLE_SIZE + SAMPLES_PER_FRAME * SAMPLE_SIZE); - skipBytes = 0; - flags = A_CONTINUE; - numSamplesProcessed = numSamplesToLoadAdj; - dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; - goto skip; - - default: - break; - } - - sampleDataChunkSize = ALIGN_PREV((numFramesToDecode * frameSize) + 31, 16); - sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize; - - // Move the compressed raw sample data from ram into the rsp (DMEM) - if (numFramesToDecode != 0) { - // Get the offset from the start of the sample to where the sample is currently playing from - frameIndex = (skipInitialSamples + driver->sample_pos_integer_part - numFirstFrameSamplesToIgnore) / - SAMPLES_PER_FRAME; - sampleAddrOffset = frameIndex * frameSize; - tmpSamplesToLoadAddr = sampleAddr + sampleAddrOffset; - tmpSamplesToLoadAddr += zeroOffset; - - // Get the ram address of the requested sample chunk - if (sample->medium == MEDIUM_RAM) { - // Sample is already loaded into ram - if (sample->bit31 == TRUE) { - samplesToLoadAddr = (u8*)(*NA_SYNC_PROC)(tmpSamplesToLoadAddr, numFramesToDecode * frameSize); - } else { - samplesToLoadAddr = tmpSamplesToLoadAddr; - } - } else if (AG._2A14) { // always false - return cmd; - } else if (sample->medium == MEDIUM_DISK) { - // This medium is unsupported so terminate processing this chan - return cmd; - } else { - // This medium is not in ram, so dma the requested sample into ram - samplesToLoadAddr = (u8*)Nas_WaveDmaCallBack((u32)(tmpSamplesToLoadAddr), - sampleDataChunkSize, flags, - &driver->sample_dma_idx, sample->medium); - } - - if (samplesToLoadAddr == NULL) { - // The ram address was unsuccessfully allocated - return cmd; - } - - // Move the raw sample chunk from ram to the rsp - // DMEM at the addresses before DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkAlignPad = (u32)samplesToLoadAddr & 0xF; - aLoadCache(cmd++, samplesToLoadAddr - sampleDataChunkAlignPad, sampleDataDmemAddr, - sampleDataChunkSize); - } else { - numSamplesToDecode = 0; - sampleDataChunkAlignPad = 0; - } - - if (driver->at_loop_point) { - aSetLoop(cmd++, sample->loop->predictor_state); - flags = A_LOOP; - driver->at_loop_point = false; - } - - numSamplesInThisIteration = numSamplesToDecode + numSamplesInFirstFrame - numTrailingSamplesToIgnore; - - if (numSamplesProcessed == 0) { - //! FAKE: - if (1) {} - skipBytes = numFirstFrameSamplesToIgnore * SAMPLE_SIZE; - } else { - dmemUncompressedAddrOffset2 = ALIGN_NEXT(dmemUncompressedAddrOffset1 + 8 * SAMPLE_SIZE, 16); - } - - // Decompress the raw sample chunks in the rsp - // Goes from adpcm (compressed) sample data to pcm (uncompressed) sample data - switch (sample->codec) { - case CODEC_ADPCM: - aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, - DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, - numSamplesToDecode * SAMPLE_SIZE); - aADPCMdec(cmd++, flags, driver->synth_params->adpcm_state); - break; - - case CODEC_SMALL_ADPCM: - aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, - DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, - numSamplesToDecode * SAMPLE_SIZE); - aADPCMdec(cmd++, flags | A_ADPCM_SHORT, driver->synth_params->adpcm_state); - break; - - case CODEC_S8: - Nas_SetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, - DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, - numSamplesToDecode * SAMPLE_SIZE); - Nas_PCM8dec(cmd++, flags, (s32)driver->synth_params->adpcm_state); - break; - - case CODEC_UNK7: - default: - // No decompression - break; - } - - if (numSamplesProcessed != 0) { - aDMEMMove(cmd++, - DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2 + - (numFirstFrameSamplesToIgnore * SAMPLE_SIZE), - DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1, - numSamplesInThisIteration * SAMPLE_SIZE); - } - - numSamplesProcessed += numSamplesInThisIteration; - - switch (flags) { - case A_INIT: - skipBytes = SAMPLES_PER_FRAME * SAMPLE_SIZE; - dmemUncompressedAddrOffset1 = numSamplesToDecode * SAMPLE_SIZE + SAMPLES_PER_FRAME * SAMPLE_SIZE; - break; - - case A_LOOP: - dmemUncompressedAddrOffset1 = - numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1; - break; - - default: - if (dmemUncompressedAddrOffset1 != 0) { - dmemUncompressedAddrOffset1 = - numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1; - } else { - dmemUncompressedAddrOffset1 = - (numFirstFrameSamplesToIgnore + numSamplesInThisIteration) * SAMPLE_SIZE; - } - break; - } - - flags = A_CONTINUE; - - skip: - - // Update what to do with the samples next - if (sampleFinished) { - s32 dmemClearCount = numSamplesToLoadAdj - numSamplesProcessed; - if (dmemClearCount != 0) { - Nas_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1, - dmemClearCount * SAMPLE_SIZE); - } - finished = true; - chan->common_ch.finished = true; - __Nas_WaveTerminateProcess(stack_update_idx, stack_chan_id); - break; // break out of the for-loop - } else if (loopToPoint) { - driver->at_loop_point = true; - driver->sample_pos_integer_part = loopInfo->loop_start; - } else { - driver->sample_pos_integer_part += numSamplesToProcess; - } - } - - switch (numParts) { - case 1: - sampleDmemBeforeResampling = DMEM_UNCOMPRESSED_NOTE + skipBytes; - break; - - case 2: - switch (curPart) { - case 0: - Nas_HalfCut(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes, - DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE), - ALIGN_NEXT(numSamplesToLoadAdj / 2, 8)); - numSamplesToLoadFirstPart = numSamplesToLoadAdj; - sampleDmemBeforeResampling = DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE); - if (finished) { - Nas_ClearBuffer(cmd++, sampleDmemBeforeResampling + numSamplesToLoadFirstPart, - numSamplesToLoadAdj + SAMPLES_PER_FRAME); - } - break; - - case 1: - Nas_HalfCut(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes, - DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE) + numSamplesToLoadFirstPart, - ALIGN_NEXT(numSamplesToLoadAdj / 2, 8)); - break; - - default: - break; - } - break; - - default: - break; - } - if (finished) { - break; - } - } - - // Update the flags for the signal processing below - flags = A_CONTINUE; - if (common->needs_init == true) { - flags = A_INIT; - common->needs_init = false; - } - - // Resample the decompressed mono-signal to the correct pitch - cmd = Nas_Synth_Resample(cmd, driver, size, frequencyFixedPoint, - sampleDmemBeforeResampling, flags | something_unused_from_sm64); - - // Not present in MM - if (bookOffset != 0) { - Nas_NoiseFilter(cmd++, DMEM_TEMP, samples_per_update, NOISE_TABLE[(bookOffset >> 4) & 0xF], NOISE_TABLE[bookOffset & 0xF]); - } - - // Apply the gain to the mono-signal to adjust the volume - gain = common->gain; - if (gain != 0) { - // A gain of 0x10 (a UQ4.4 number) is equivalent to 1.0 and represents no volume change - if (gain < 0x10) { - gain = 0x10; - } - Nas_DistFilter(cmd++, gain, DMEM_TEMP, 0, size + SAMPLES_PER_FRAME * SAMPLE_SIZE); - } - - // Not in MM - if (!STOP_VELOCONV) { - // Load the velocity convolution table into DMEM_0x800 - s32 vel_conv_idx = driver->vel_conv_table_idx; - aLoadBuffer2(cmd++, (u32)VELOCONV_TABLE[vel_conv_idx], 0x800, sizeof(VELOCONV_TABLE[vel_conv_idx])); - aUnkCmd3(cmd++, DMEM_TEMP, 0x800, samples_per_update); - } - - // Apply the filter to the mono-signal - filter = common->filter; - if (filter != 0) { - Nas_FirLoadTable(cmd++, size, filter); - Nas_FirFilter(cmd++, flags, DMEM_TEMP, driver->synth_params->filter_state); - } - - // Apply the comb filter to the mono-signal by taking the signal with a small temporal offset, - // and adding it back to itself - combFilterSize = common->comb_filter_size; - combFilterGain = common->comb_filter_gain; - combFilterState = driver->synth_params->comb_filter_state; - if ((common->comb_filter_size != 0) && (common->comb_filter_gain != 0)) { - Nas_DMEMMove(cmd++, DMEM_TEMP, DMEM_COMB_TEMP, size); - // combFilterDmem = DMEM_COMB_TEMP - combFilterSize; - if (driver->comb_filter_needs_init) { - Nas_ClearBuffer(cmd++, DMEM_COMB_TEMP - combFilterSize, combFilterSize); - driver->comb_filter_needs_init = false; - } else { - Nas_LoadBuffer2(cmd++, DMEM_COMB_TEMP - combFilterSize, combFilterSize, (s32)combFilterState); - } - Nas_SaveBuffer2(cmd++, DMEM_TEMP - combFilterSize + size, combFilterSize, (s32)combFilterState); - Nas_Mix(cmd++, size >> 4, combFilterGain, DMEM_COMB_TEMP, DMEM_COMB_TEMP - combFilterSize); - Nas_DMEMMove(cmd++, DMEM_COMB_TEMP - combFilterSize, DMEM_TEMP, size); - } else { - driver->comb_filter_needs_init = true; - } - - // Determine the behavior of the audio processing that leads to the haas effect - if ((common->haas_effect_left_delay_size != 0) || (driver->prev_haas_effect_left_delay_size != 0)) { - haasEffectDelaySide = HAAS_EFFECT_DELAY_LEFT; - } else if ((common->haas_effect_right_delay_size != 0) || (driver->prev_haas_effect_right_delay_size != 0)) { - haasEffectDelaySide = HAAS_EFFECT_DELAY_RIGHT; - } else { - haasEffectDelaySide = HAAS_EFFECT_DELAY_NONE; - } - - // Apply an unknown effect based on the surround sound-mode - if (AG.sound_mode == SOUND_OUTPUT_DOLBY_SURROUND) { - // common->target_volume_left = common->target_volume_left >> 1; - // common->target_volume_right = common->target_volume_right >> 1; - if (common->surround_effect_idx != 0xFF) { - cmd = Nas_DolbySurround(cmd, common, driver, samples_per_update, DMEM_TEMP, flags); - } - } - - // Split the mono-signal into left and right channels: - // Both for dry signal (to go to the speakers now) - // and for wet signal (to go to a reverb buffer to be stored, and brought back later to produce an echo) - cmd = Nas_Synth_Envelope(cmd, common, driver, samples_per_update, DMEM_TEMP, haasEffectDelaySide, flags); - - // Apply the haas effect by delaying either the left or the right channel by a small amount - if (common->use_haas_effect) { - if (!(flags & A_INIT)) { - flags = A_CONTINUE; - } - cmd = Nas_Synth_Delay(cmd, common, driver, size, flags, haasEffectDelaySide); - } - } - - return cmd; -} - -Acmd* Nas_DolbySurround(Acmd* cmd, commonch* common, driverch* driver, s32 num_samples_per_update, s32 haas_dmem, s32 flags) { - s32 size; - u16 wetGain; - u16 dryGain; - s64 dmem = DMEM_SURROUND_TEMP; - f32 decayGain; - - size = num_samples_per_update * SAMPLE_SIZE; - Nas_DMEMMove(cmd++, haas_dmem, DMEM_HAAS_TEMP, size); - dryGain = driver->surround_effect_gain; - - if (flags == A_INIT) { - aClearBuffer(cmd++, dmem, sizeof(driver->synth_params->surround_effect_state)); - driver->surround_effect_gain = 0; - } else { - wetGain = (driver->surround_effect_gain * driver->cur_reverb_vol) >> 7; - - aLoadBuffer2(cmd++, driver->synth_params->surround_effect_state, dmem, sizeof(driver->synth_params->surround_effect_state)); - - aMix(cmd++, size >> 4, dryGain, dmem, DMEM_LEFT_CH); - aMix(cmd++, size >> 4, (u16)(dryGain ^ 0xFFFF), dmem, DMEM_RIGHT_CH); - - aMix(cmd++, size >> 4, wetGain, dmem, DMEM_WET_LEFT_CH); - aMix(cmd++, size >> 4, (wetGain ^ 0xFFFF), dmem, DMEM_WET_RIGHT_CH); - } - - aSaveBuffer2(cmd++, driver->synth_params->surround_effect_state, DMEM_SURROUND_TEMP + size, sizeof(driver->synth_params->surround_effect_state)); - - decayGain = (common->target_volume_left + common->target_volume_right) / 8192.0f; - if (decayGain > 1.0f) { - decayGain = 1.0f; - } - - decayGain = decayGain * StereoLeft[127 - common->surround_effect_idx]; - driver->surround_effect_gain = ((decayGain * 0x7FFF) + driver->surround_effect_gain) / 2; - - Nas_DMEMMove(cmd++, DMEM_HAAS_TEMP, haas_dmem, size); - - return cmd; -} - -extern Acmd* Nas_Synth_Resample(Acmd* cmd, const driverch* driver, s32 size, u16 pitch, u16 sampleDmemBeforeResampling, s32 flags) { - if (pitch == 0) { - Nas_ClearBuffer(cmd++, DMEM_TEMP, size); - } else { - aSetBuffer(cmd++, 0, sampleDmemBeforeResampling, DMEM_TEMP, size); - aResample(cmd++, flags, pitch, driver->synth_params->final_resample_state); - } - - return cmd; -} - -// @non-matching - issues with aSetEnvParam2 macro -extern Acmd* Nas_Synth_Envelope(Acmd* cmd, commonch* common, driverch* driver, s32 samples_per_update, u16 dmem, s32 haasEffectDelaySide, s32 flags) { - s32 targetReverbVol; - u16 curVolLeft; - u16 curVolRight; - u16 targetVolLeft; - u16 targetVolRight; - u32 dmemDests; - s32 curReverbVolAndFlags; - u16 curReverbVol; - s16 rampLeft; - s16 rampRight; - s16 rampReverb; - f32 defaultPanVolume; - - - targetReverbVol = common->target_reverb_volume; - curVolLeft = driver->current_volume_left & 0xFFFF; - curVolRight = driver->current_volume_right & 0xFFFF; - - targetVolLeft = common->target_volume_left << 4; - targetVolRight = common->target_volume_right << 4; - - if (AG.sound_mode == SOUND_OUTPUT_DOLBY_SURROUND) { - u8 idx = common->surround_effect_idx; - - if (idx != 0xFF) { - defaultPanVolume = StereoLeft[idx]; - targetVolLeft *= defaultPanVolume; - targetVolRight *= defaultPanVolume; - } - } - - if (targetVolLeft != (u32)curVolLeft) { - rampLeft = (targetVolLeft - (s32)curVolLeft) / (samples_per_update >> 3); - } else { - rampLeft = 0; - } - - if (targetVolRight != (u32)curVolRight) { - rampRight = (targetVolRight - (s32)curVolRight) / (samples_per_update >> 3); - } else { - rampRight = 0; - } - - curReverbVolAndFlags = (s16)driver->cur_reverb_vol; - if (targetReverbVol != curReverbVolAndFlags) { - curReverbVol = curReverbVolAndFlags & 0x7F; - rampReverb = (((targetReverbVol & 0x7F) - (curReverbVol)) << 9) / (samples_per_update >> 3); - driver->cur_reverb_vol = targetReverbVol; - } else { - rampReverb = 0; - } - - driver->current_volume_left = curVolLeft + (rampLeft * (samples_per_update >> 3)); - driver->current_volume_right = curVolRight + (rampRight * (samples_per_update >> 3)); - - if (common->use_haas_effect) { - // curReverbVol = curReverbVolAndFlags & 0x7F; - Nas_ClearBuffer(cmd++, DMEM_HAAS_TEMP, DMEM_1CH_SIZE); - Nas_SetEnvParam(cmd++, (curReverbVolAndFlags & 0x7F) * 2, rampReverb, rampLeft, rampRight); - Nas_SetEnvParam2(cmd++, curVolLeft, curVolRight); - - switch (haasEffectDelaySide) { - case HAAS_EFFECT_DELAY_LEFT: - // Store the left dry channel in a temp space to be delayed to produce the haas effect - dmemDests = Env_Data_L1; - break; - - case HAAS_EFFECT_DELAY_RIGHT: - // Store the right dry channel in a temp space to be delayed to produce the haas effect - dmemDests = Env_Data_L2; - break; - - default: // HAAS_EFFECT_DELAY_NONE - dmemDests = Env_Data_L3; - break; - } - } else { - curReverbVol = (curReverbVolAndFlags << 1) & 0xFE; - aSetEnvParam(cmd++, (curReverbVol), rampReverb, rampLeft, rampRight); - - { - cmd->words.w0 = _SHIFTL(A_CMD_SETENVPARAM2, 24, 8); - cmd->words.w1 = _SHIFTL(curVolLeft, 16, 16) | _SHIFTL(curVolRight, 0, 16); - // cmd->words.w1 = ((curVolLeft & 0xFFFF) << 16) | (curVolRight & 0xFFFF); - cmd++; - } - // aSetEnvParam2(cmd++, curVolLeft & 0xFFFF, curVolRight & 0xFFFF); - dmemDests = Env_Data_L3; - } - - aEnvMixer2(cmd++, dmem, samples_per_update, (curReverbVolAndFlags & 0x80) >> 7, - common->strong_reverb_right, common->strong_reverb_left, - common->strong_right, common->strong_left, dmemDests, Env_DataH); - - return cmd; -} - -extern Acmd* Nas_Synth_Delay(Acmd* cmd, commonch* common, driverch* driver, s32 size, s32 flags, s32 haasEffectDelaySide) { - u16 haasEffectDelaySize; - u16 prevHaasEffectDelaySize; - u16 dmemDest; - u16 pitch; - - switch (haasEffectDelaySide) { - case HAAS_EFFECT_DELAY_LEFT: - // Delay the sample on the left channel - // This allows the right channel to be heard first - dmemDest = DMEM_LEFT_CH; - haasEffectDelaySize = common->haas_effect_left_delay_size; - prevHaasEffectDelaySize = driver->prev_haas_effect_left_delay_size; - driver->prev_haas_effect_left_delay_size = haasEffectDelaySize; - driver->prev_haas_effect_right_delay_size = 0; - break; - - case HAAS_EFFECT_DELAY_RIGHT: - // Delay the sample on the right channel - // This allows the left channel to be heard first - dmemDest = DMEM_RIGHT_CH; - haasEffectDelaySize = common->haas_effect_right_delay_size; - prevHaasEffectDelaySize = driver->prev_haas_effect_right_delay_size; - driver->prev_haas_effect_right_delay_size = haasEffectDelaySize; - driver->prev_haas_effect_left_delay_size = 0; - break; - - default: // HAAS_EFFECT_DELAY_NONE - return cmd; - } - - if (flags != A_INIT) { - // Slightly adjust the sample rate in order to fit a change in sample delay - if (haasEffectDelaySize != prevHaasEffectDelaySize) { - pitch = pitch = (((size << 0xF) / 2) - 1) / ((size + haasEffectDelaySize - prevHaasEffectDelaySize - 2) / 2); - aSetBuffer(cmd++, 0, DMEM_HAAS_TEMP, DMEM_TEMP, size + haasEffectDelaySize - prevHaasEffectDelaySize); - aResampleZoh(cmd++, pitch, 0); - } else { - aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size); - } - - if (prevHaasEffectDelaySize != 0) { - aLoadBuffer2(cmd++, driver->synth_params->haas_effect_delay_state, DMEM_HAAS_TEMP, - ALIGN_NEXT(prevHaasEffectDelaySize, 16)); - aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + prevHaasEffectDelaySize, - size + haasEffectDelaySize - prevHaasEffectDelaySize); - } else { - aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP, size + haasEffectDelaySize); - } - } else { - // Just apply a delay directly - aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size); - if (haasEffectDelaySize) { // != 0 - aClearBuffer(cmd++, DMEM_HAAS_TEMP, haasEffectDelaySize); - } - aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + haasEffectDelaySize, size); - } - - if (haasEffectDelaySize) { // != 0 - // Save excessive samples for next iteration - aSaveBuffer2(cmd++, driver->synth_params->haas_effect_delay_state, DMEM_HAAS_TEMP + size, - ALIGN_NEXT(haasEffectDelaySize, 16)); - } - - aAddMixer(cmd++, ALIGN_NEXT(size, 64), DMEM_HAAS_TEMP, dmemDest, 0x7FFF); - - return cmd; -} +#include "../src/static/jaudio_PP/internal/driver_cpufx.c_inc" +#include "../src/static/jaudio_PP/internal/driver_synth.c_inc" diff --git a/src/static/jaudio_PP/internal/driver_acmd.c_inc b/src/static/jaudio_PP/internal/driver_acmd.c_inc new file mode 100644 index 00000000..bc3f97f8 --- /dev/null +++ b/src/static/jaudio_PP/internal/driver_acmd.c_inc @@ -0,0 +1,56 @@ +static void Nas_ClearBuffer(Acmd* cmd, s32 dmem, s32 size) { + aClearBuffer(cmd, dmem, size); +} + +static void Nas_Mix(Acmd* cmd, s32 flags, s32 gain, s32 dmem_in, s32 dmem_out) { + aMix(cmd, flags, gain, dmem_in, dmem_out); +} + +static void Nas_SetBuffer(Acmd* cmd, s32 flags, s32 dmem_in, s32 dmem_out, s32 count) { + aSetBuffer(cmd, flags, dmem_in, dmem_out, count); +} + +static void Nas_DMEMMove(Acmd* cmd, s32 dmem_in, s32 dmem_out, s32 count) { + aDMEMMove(cmd, dmem_in, dmem_out, count); +} + +static void Nas_HalfCut(Acmd* cmd, s32 src, s32 dst, s32 len) { + aHalfCut(cmd, src, dst, len); +} + +static void Nas_SetEnvParam(Acmd* cmd, s32 reverbVol, s32 rampReverb, s32 rampL, s32 rampR) { + aSetEnvParam(cmd, reverbVol, rampReverb, rampL, rampR); +} + +static void Nas_LoadBuffer2(Acmd* cmd, s32 dst, s32 len, s32 src) { + aLoadBuffer2(cmd, src, dst, len); +} + +static void Nas_SaveBuffer2(Acmd* cmd, s32 src, s32 len, s32 dst) { + aSaveBuffer2(cmd, dst, src, len); +} + +static void Nas_SetEnvParam2(Acmd* cmd, s32 volL, s32 volR) { + aSetEnvParam2(cmd, volL, volR); +} + +static void Nas_PCM8dec(Acmd* cmd, s32 flags, s32 state) { + aPCM8dec(cmd, flags, state); +} + +static void Nas_DistFilter(Acmd* cmd, s32 gain, s32 dmem_in, s32 dmem_out, s32 len) { + aDistFilter(cmd, gain, dmem_in, dmem_out, len); +} + +// TODO: check params +static void Nas_NoiseFilter(Acmd* cmd, s32 buf, s32 flags, s32 addr, s32 len) { + aNoiseFilter(cmd, buf, flags, addr, len); +} + +static void Nas_FirFilter(Acmd* cmd, s32 flags, s32 buf, s16* filter) { + aFirFilter(cmd, flags, buf, filter); +} + +static void Nas_FirLoadTable(Acmd* cmd, s32 size, s16* filter) { + aFirLoadTable(cmd, size, filter); +} diff --git a/src/static/jaudio_PP/internal/driver_auxbuf1.c_inc b/src/static/jaudio_PP/internal/driver_auxbuf1.c_inc new file mode 100644 index 00000000..1865b9ae --- /dev/null +++ b/src/static/jaudio_PP/internal/driver_auxbuf1.c_inc @@ -0,0 +1,21 @@ +static Acmd* Nas_LoadAuxBuffer1(Acmd* cmd, s32 samples_per_update, delay* del_p, s16 update_idx) { + delayparam* param_p = &del_p->params[del_p->cur_frame][update_idx]; + + cmd = __LoadAuxBuf(cmd, 0xC40, param_p->start_pos, param_p->size, del_p); + if (param_p->wrapped_size != 0) { + cmd = __LoadAuxBuf(cmd, 0xC40 + param_p->size, 0, param_p->wrapped_size, del_p); + } + + return cmd; +} + +static Acmd* Nas_LoadAuxBuffer1_B(Acmd* cmd, s32 samples_per_update, delay* del_p, s16 update_idx) { + delayparam* param_p = &del_p->sub_params[del_p->cur_frame][update_idx]; + + cmd = __LoadAuxBuf(cmd, 0xC40, param_p->start_pos, param_p->size, del_p); + if (param_p->wrapped_size != 0) { + cmd = __LoadAuxBuf(cmd, 0xC40 + param_p->size, 0, param_p->wrapped_size, del_p); + } + + return cmd; +} diff --git a/src/static/jaudio_PP/internal/driver_auxch.c_inc b/src/static/jaudio_PP/internal/driver_auxch.c_inc new file mode 100644 index 00000000..23a9e2f9 --- /dev/null +++ b/src/static/jaudio_PP/internal/driver_auxch.c_inc @@ -0,0 +1,69 @@ +static Acmd* Nas_CrossMix(Acmd* cmd, delay* del_p) { + aDMEMMove(cmd++, 0xC40, 0x6E0, 0x1A0); + aMix(cmd++, 0x1A, del_p->leak_rtl, 0xDE0, 0xC40); + aMix(cmd++, 0x1A, del_p->leak_ltl, 0x6E0, 0xDe0); + return cmd; +} + +static Acmd* Nas_LoadAuxBufferC(Acmd* cmd, s32 samples_per_update, delay* del_p, s16 update_idx) { + delayparam* param = &del_p->params[del_p->cur_frame][update_idx]; + s16 ofs_size = (param->start_pos & 7) * SAMPLE_SIZE; + + cmd = __LoadAuxBuf(cmd, 0x3A0, param->start_pos - (ofs_size / SAMPLE_SIZE), 0x1A0, del_p); + if (param->wrapped_size != 0) { + s16 wrapped_ofs_size = ALIGN_NEXT(ofs_size + param->size, 16); + + cmd = __LoadAuxBuf(cmd, 0x3A0 + wrapped_ofs_size, 0, 0x1A0 - wrapped_ofs_size, del_p); + } + + aSetBuffer(cmd++, 0, 0x3A0 + ofs_size, 0xC40, samples_per_update * SAMPLE_SIZE); + aResample(cmd++, del_p->resample_flags, del_p->downsample_pitch, del_p->left_load_resample_buf); + aSetBuffer(cmd++, 0, 0x3A0 + 0x1A0 + ofs_size, 0xDE0, samples_per_update * SAMPLE_SIZE); + aResample(cmd++, del_p->resample_flags, del_p->downsample_pitch, del_p->right_load_resample_buf); + return cmd; +} + +static Acmd* Nas_SaveAuxBufferCH(Acmd* cmd, delay* del_p, s16 update_idx) { + delayparam* param = &del_p->params[del_p->cur_frame][update_idx]; + s16 samples = param->n_samples; + u32 size = samples * SAMPLE_SIZE; + + aDMEMMove(cmd++, 0xC40, 0x3A0, size); + aSetBuffer(cmd++, 0, 0x3A0, 0x6E0, param->save_resample_num_samples * SAMPLE_SIZE); + aResample(cmd++, del_p->resample_flags, param->save_resample_pitch, del_p->left_save_resample_buf); + cmd = Nas_SaveBufferAuto(cmd, 0x6E0, param->size, (s32)&del_p->left_reverb_buf[param->start_pos]); + if (param->wrapped_size != 0) { + cmd = Nas_SaveBufferAuto(cmd, 0x6E0 + param->size, param->wrapped_size, (s32)&del_p->left_reverb_buf[0]); + } + + aDMEMMove(cmd++, 0xDE0, 0x3A0, size); + aSetBuffer(cmd++, 0, 0x3A0, 0x6E0, param->save_resample_num_samples * SAMPLE_SIZE); + aResample(cmd++, del_p->resample_flags, param->save_resample_pitch, del_p->right_save_resample_buf); + cmd = Nas_SaveBufferAuto(cmd, 0x6E0, param->size, (s32)&del_p->right_reverb_buf[param->start_pos]); + if (param->wrapped_size != 0) { + cmd = Nas_SaveBufferAuto(cmd, 0x6E0 + param->size, param->wrapped_size, (s32)&del_p->right_reverb_buf[0]); + } + + return cmd; +} + +static Acmd* Nas_LoadAuxBufferCH(Acmd* cmd, s32 samples_per_update, delay* del_p, s16 update_idx) { + delayparam* param = &del_p->params[del_p->cur_frame][update_idx]; + s16 ofs_size = (param->start_pos & 7) * SAMPLE_SIZE; + + cmd = __LoadAuxBuf(cmd, 0x3A0, param->start_pos - (ofs_size / SAMPLE_SIZE), 0x1A0, del_p); + if (param->wrapped_size != 0) { + s16 wrapped_ofs_size = ALIGN_NEXT(ofs_size + param->size, 16); + s32 load_size = 0x1A0 - wrapped_ofs_size; + + if (load_size > 0) { + cmd = __LoadAuxBuf(cmd, 0x3A0 + wrapped_ofs_size, 0, load_size, del_p); + } + } + + aSetBuffer(cmd++, 0, 0x3A0 + ofs_size, 0xC40, samples_per_update * SAMPLE_SIZE); + aResample(cmd++, del_p->resample_flags, param->load_resample_pitch, del_p->left_load_resample_buf); + aSetBuffer(cmd++, 0, 0x3A0 + 0x1A0 + ofs_size, 0xDE0, samples_per_update * SAMPLE_SIZE); + aResample(cmd++, del_p->resample_flags, param->load_resample_pitch, del_p->right_load_resample_buf); + return cmd; +} diff --git a/src/static/jaudio_PP/internal/driver_cpufx.c_inc b/src/static/jaudio_PP/internal/driver_cpufx.c_inc new file mode 100644 index 00000000..72f29b81 --- /dev/null +++ b/src/static/jaudio_PP/internal/driver_cpufx.c_inc @@ -0,0 +1,104 @@ +static void Nas_CpuFX(s32 chunkLen, s32 updateIdx, s32 reverbIdx) { + delayparam* param_p; + s32 count; + delay* del_p; + s32 t; + s32 i; + s32 sample2; + s32 next_buf_pos; + s32 t2; + s32 idx; + s32 t3; + s32 sample; + s32 n; + s32 s; + + del_p = &AG.synth_delay[reverbIdx]; + param_p = &del_p->params[del_p->cur_frame][updateIdx]; + count = chunkLen / AG.synth_delay[reverbIdx].downsample_rate; + if (AG.synth_delay[reverbIdx].resample_effect_on && AG.synth_delay[reverbIdx].downsample_rate == 1 && del_p->right_save_resample_buf != NULL) { + count += del_p->resample_effect_extra_samples; + param_p->save_resample_num_samples = count; + param_p->load_resample_pitch = (param_p->save_resample_num_samples << 15) / chunkLen; + param_p->save_resample_pitch = (chunkLen << 15) / param_p->save_resample_num_samples; + + n = 10; + s = 10; + for (i = 0; i < 10; i++) { + n--; + sample = del_p->resample_effect_load_unk + param_p->load_resample_pitch * chunkLen * SAMPLE_SIZE; + sample2 = (sample >> 16); + if (sample2 != count && n == 0) { + param_p->load_resample_pitch = (count * 0x10000 - del_p->resample_effect_load_unk) / (chunkLen * SAMPLE_SIZE); + } else if (sample2 > count) { + param_p->load_resample_pitch--; + } else if (sample2 < count) { + param_p->load_resample_pitch++; + } else { + break; + } + } + + del_p->resample_effect_load_unk = sample; + + for (i = 0; i < 10; i++) { + s--; + sample = del_p->resample_effect_save_unk + param_p->save_resample_pitch * count * SAMPLE_SIZE; + sample2 = (sample >> 16); + if (sample2 != chunkLen && s == 0) { + param_p->save_resample_pitch = (chunkLen * 0x10000 - del_p->resample_effect_save_unk) / (count * SAMPLE_SIZE); + } else if (sample2 > chunkLen) { + param_p->save_resample_pitch--; + } else if (sample2 < chunkLen) { + param_p->save_resample_pitch++; + } else { + break; + } + } + + del_p->resample_effect_save_unk = sample; + } + + next_buf_pos = del_p->next_reverb_buf_pos; + t = del_p->next_reverb_buf_pos + count - del_p->delay_num_samples; + + if (t < 0) { + param_p->size = count * SAMPLE_SIZE; + param_p->wrapped_size = 0; + param_p->start_pos = del_p->next_reverb_buf_pos; + del_p->next_reverb_buf_pos += count; + } else { + param_p->size = (count - t) * SAMPLE_SIZE; + param_p->wrapped_size = t * SAMPLE_SIZE; + param_p->start_pos = del_p->next_reverb_buf_pos; + del_p->next_reverb_buf_pos = t; + } + + param_p->n_samples_after_downsampling = count; + param_p->n_samples = chunkLen; + + if (del_p->sub_delay != 0) { + t = del_p->delay_num_samples; + idx = next_buf_pos + del_p->sub_delay; + while (idx >= t) { + idx -= t; + } + + param_p = del_p->sub_params[del_p->cur_frame] + updateIdx; + t2 = chunkLen / del_p->downsample_rate; + t3 = idx + t2 - t; + + if (t3 < 0) { + param_p->size = t2 * SAMPLE_SIZE; + param_p->wrapped_size = 0; + param_p->start_pos = idx; + } else { + param_p->size = (t2 - t3) * SAMPLE_SIZE; + param_p->wrapped_size = t3 * SAMPLE_SIZE; + param_p->start_pos = idx; + } + + param_p->n_samples_after_downsampling = t2; + param_p->n_samples = chunkLen; + } +} diff --git a/src/static/jaudio_PP/internal/driver_sendline.c_inc b/src/static/jaudio_PP/internal/driver_sendline.c_inc new file mode 100644 index 00000000..349c0e73 --- /dev/null +++ b/src/static/jaudio_PP/internal/driver_sendline.c_inc @@ -0,0 +1,30 @@ +static Acmd* Nas_DelayFilter(Acmd* cmd, s32 size, delay* del_p) { + if (del_p->filter_left != NULL) { + aFirLoadTable(cmd++, size, del_p->filter_left); + aFirFilter(cmd++, del_p->resample_flags, 0xC40, del_p->filter_left_state); + } + + if (del_p->filter_right != NULL) { + aFirLoadTable(cmd++, size, del_p->filter_right); + aFirFilter(cmd++, del_p->resample_flags, 0xDE0, del_p->filter_right_state); + } + + return cmd; +} + +static Acmd* Nas_SendLine(Acmd* cmd, delay* del_p, s32 update_idx) { + delay* mix_delay; + + if (del_p->mix_reverb_idx >= AG.num_synth_reverbs) { + return cmd; + } + + mix_delay = &AG.synth_delay[del_p->mix_reverb_idx]; + if (mix_delay->downsample_rate == 1) { + cmd = Nas_LoadAux2nd(cmd, mix_delay, update_idx); + aMix(cmd++, 0x34, del_p->mix_reverb_strength, 0xC40, 0x3A0); + cmd = Nas_SaveAux2nd(cmd, mix_delay, update_idx); + } + + return cmd; +} diff --git a/src/static/jaudio_PP/internal/driver_synth.c_inc b/src/static/jaudio_PP/internal/driver_synth.c_inc new file mode 100644 index 00000000..a9286f1c --- /dev/null +++ b/src/static/jaudio_PP/internal/driver_synth.c_inc @@ -0,0 +1,1144 @@ +static void __Nas_PushDrvReg(s32 updateIdx) { + s32 i; + commonch* common0; + commonch* common1; + s32 baseIdx = updateIdx * AG.num_channels; + + for (i = 0; i < AG.num_channels; i++) { + common0 = &AG.channels[i].common_ch; + common1 = &AG.common_channel[baseIdx + i]; + + if (common0->enabled) { + CopyStc(common1, common0); + common0->needs_init = FALSE; + } else { + common1->enabled = FALSE; + } + + common0->harmonic_idx_cur_and_prev = 0; + } +} + +extern Acmd* Nas_smzAudioFrame(Acmd* cmdStart, s32* cmdCount, s16* aiStart, s32 aiBufLen) { + Acmd* cmdP; + s16* aiBufP; + s32 chunkLen; + s32 i; + s32 j; + + cmdP = cmdStart; + for (i = AG.audio_params.updates_per_frame; i > 0; i--) { + Nas_MySeqMain(i - 1); + __Nas_PushDrvReg(AG.audio_params.updates_per_frame - i); + } + + aiBufP = aiStart; + AG.adpcm_code_book = NULL; + + for (i = AG.audio_params.updates_per_frame; i > 0; i--) { + chunkLen = AG.audio_params.num_samples_per_update; + + for (j = 0; j < AG.num_synth_reverbs; j++) { + if (AG.synth_delay[j].use_reverb) { + Nas_CpuFX(chunkLen, AG.audio_params.updates_per_frame - i, j); + } + } + + cmdP = Nas_DriveRsp(aiBufP, chunkLen, cmdP, AG.audio_params.updates_per_frame - i); + aiBufLen -= chunkLen; + aiBufP += (JAC_FRAMESAMPLES >> 1) & ~1; + } + + for (j = 0; j < AG.num_synth_reverbs; j++) { + if (AG.synth_delay[j].frames_to_ignore != 0) { + AG.synth_delay[j].frames_to_ignore--; + } + AG.synth_delay[j].cur_frame ^= 1; + } + + *cmdCount = cmdP - cmdStart; + return cmdP; +} + +static void __Nas_WaveTerminateProcess(s32 updateIdx, s32 chanIdx) { + commonch* common; + s32 i; + + for (i = updateIdx + 1; i < AG.audio_params.updates_per_frame; i++) { + common = &AG.common_channel[i * AG.num_channels + chanIdx]; + if (!common->needs_init) { + common->enabled = FALSE; + } else { + break; + } + } +} + +static Acmd* Nas_LoadAux2nd(Acmd* cmd, const delay* del_p, s16 updateIdx) { + const delayparam* param = &del_p->params[del_p->cur_frame][updateIdx]; + + cmd = __LoadAuxBuf(cmd, 0x3A0, param->start_pos, param->size, (delay*)del_p); + if (param->wrapped_size != 0) { + cmd = __LoadAuxBuf(cmd, 0x3A0 + param->size, 0, param->wrapped_size, (delay*)del_p); + } + + return cmd; +} + +static Acmd* Nas_SaveAux2nd(Acmd* cmd, const delay* del_p, s16 updateIdx) { + const delayparam* param = &del_p->params[del_p->cur_frame][updateIdx]; + + cmd = __SaveAuxBuf(cmd, 0x3A0, param->start_pos, param->size, (delay*)del_p); + if (param->wrapped_size != 0) { + cmd = __SaveAuxBuf(cmd, 0x3A0 + param->size, 0, param->wrapped_size, (delay*)del_p); + } + + return cmd; +} + +#include "../src/static/jaudio_PP/internal/driver_acmd.c_inc" +#include "../src/static/jaudio_PP/internal/driver_auxch.c_inc" +#include "../src/static/jaudio_PP/internal/driver_sendline.c_inc" +#include "../src/static/jaudio_PP/internal/driver_auxbuf1.c_inc" + +static Acmd* Nas_SaveBufferAuto(Acmd* cmd, u16 dmem, u16 size, s32 startAddr) { + s32 startUnaligned = startAddr & 15; + s32 endAddr = startAddr + size; + s32 endUnaligned = endAddr & 15; + + if (endUnaligned != 0) { + aLoadBuffer2(cmd++, (endAddr - endUnaligned), 0x380, 16); + aDMEMMove(cmd++, dmem, 0x390, size); + aDMEMMove(cmd++, 0x380 + endUnaligned, 0x390 + size, 16 - endUnaligned); + size += 16 - endUnaligned; + dmem = 0x390; + } + + if (startUnaligned != 0) { + aLoadBuffer2(cmd++, (startAddr - startUnaligned), 0x380, 16); + aDMEMMove(cmd++, dmem, 0x380 + startUnaligned, size); + + size += startUnaligned; + dmem = 0x380; + } + + aSaveBuffer2(cmd++, startAddr - startUnaligned, dmem, size); + return cmd; +} + +static Acmd* __LoadAuxBuf(Acmd* cmd, u16 dmem, u16 startPos, s32 size, delay* del_p) { + aLoadBuffer2(cmd++, &del_p->left_reverb_buf[startPos], dmem, size); + aLoadBuffer2(cmd++, &del_p->right_reverb_buf[startPos], dmem + 0x1A0, size); + return cmd; +} + +static Acmd* __SaveAuxBuf(Acmd* cmd, u16 dmem, u16 startPos, s32 size, delay* del_p) { + aSaveBuffer2(cmd++, &del_p->left_reverb_buf[startPos], dmem, size); + aSaveBuffer2(cmd++, &del_p->right_reverb_buf[startPos], dmem + 0x1A0, size); + return cmd; +} + +static Acmd* Nas_LoadAuxBuffer_B(Acmd* cmd, s32 numSamplesPerUpdate, delay* del_p, s16 updateIdx) { + if (del_p->downsample_rate == 1) { + cmd = Nas_LoadAuxBuffer1_B(cmd, numSamplesPerUpdate, del_p, updateIdx); + } + + return cmd; +} + +static Acmd* Nas_LoadAuxBuffer(Acmd* cmd, s32 numSamplesPerUpdate, delay* del_p, s16 updateIdx) { + if (del_p->downsample_rate == 1) { + if (del_p->resample_effect_on) { + cmd = Nas_LoadAuxBufferCH(cmd, numSamplesPerUpdate, del_p, updateIdx); + } else { + cmd = Nas_LoadAuxBuffer1(cmd, numSamplesPerUpdate, del_p, updateIdx); + } + } else { + cmd = Nas_LoadAuxBufferC(cmd, numSamplesPerUpdate, del_p, updateIdx); + } + + return cmd; +} + +static Acmd* Nas_SaveAuxBuffer(Acmd* cmd, delay* del_p, s16 update_idx) { + delayparam* param = &del_p->params[del_p->cur_frame][update_idx]; + s32 downsample_rate; + s32 n_samples; + + switch (del_p->downsample_rate) { + case 1: + if (del_p->resample_effect_on) { + cmd = Nas_SaveAuxBufferCH(cmd, del_p, update_idx); + } else { + cmd = __SaveAuxBuf(cmd, 0xC40, param->start_pos, param->size, del_p); + if (param->wrapped_size != 0) { + cmd = __SaveAuxBuf(cmd, 0xC40 + param->size, 0, param->wrapped_size, del_p); + } + } + break; + default: + downsample_rate = del_p->downsample_rate; + n_samples = 13 * 16; // 16 = SAMPLES_PER_FRAME + + while (downsample_rate > 1) { + aHalfCut(cmd++, 0xC40, 0xC40, n_samples); + aHalfCut(cmd++, 0xDE0, 0xDE0, n_samples); + n_samples >>= 1; + downsample_rate >>= 1; + } + + if (param->size != 0) { + cmd = Nas_SaveBufferAuto(cmd, 0xC40, (u16)param->size, (s32)&del_p->left_reverb_buf[param->start_pos]); + cmd = Nas_SaveBufferAuto(cmd, 0xDE0, (u16)param->size, (s32)&del_p->right_reverb_buf[param->start_pos]); + } + + if (param->wrapped_size != 0) { + cmd = Nas_SaveBufferAuto(cmd, 0xC40 + param->size, (u16)param->wrapped_size, (s32)&del_p->left_reverb_buf[0]); + cmd = Nas_SaveBufferAuto(cmd, 0xDE0 + param->size, (u16)param->wrapped_size, (s32)&del_p->right_reverb_buf[0]); + } + break; + } + + del_p->resample_flags = 0; + return cmd; +} + +static Acmd* Nas_SaveAuxBuffer_B(Acmd* cmd, delay* del_p, s16 update_idx) { + delayparam* param = &del_p->sub_params[del_p->cur_frame][update_idx]; + + cmd = __SaveAuxBuf(cmd, 0xC40, param->start_pos, param->size, del_p); + if (param->wrapped_size != 0) { + cmd = __SaveAuxBuf(cmd, 0xC40 + param->size, 0, param->wrapped_size, del_p); + } + + return cmd; +} + +extern Acmd* Nas_DriveRsp(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updateIndex) { + s32 size = aiBufLen * SAMPLE_SIZE; + u8 noteIndices[64]; + s32 noteCount = 0; + s32 reverbIndex; + delay* reverb; + s32 useReverb; + s32 sampleStateOffset = updateIndex * AG.num_channels; + s32 i; + commonch* sampleState; + + if (AG.num_synth_reverbs == 0) { + int idx = sampleStateOffset; + for (i = 0; i < AG.num_channels; i++) { + if (AG.common_channel[idx++].enabled) { + noteIndices[noteCount++] = i; + } + } + } else { + for (reverbIndex = 0; reverbIndex < AG.num_synth_reverbs; reverbIndex++) { + for (i = 0; i < AG.num_channels; i++) { + sampleState = &AG.common_channel[sampleStateOffset + i]; + if (sampleState->enabled && (sampleState->reverb_idx == reverbIndex)) { + noteIndices[noteCount++] = i; + } + } + } + + for (i = 0; i < AG.num_channels; i++) { + sampleState = &AG.common_channel[sampleStateOffset + i]; + if (sampleState->enabled && (sampleState->reverb_idx >= AG.num_synth_reverbs)) { + noteIndices[noteCount++] = i; + } + } + } + + aClearBuffer(cmd++, DMEM_LEFT_CH, DMEM_2CH_SIZE); + + i = 0; + for (reverbIndex = 0; reverbIndex < AG.num_synth_reverbs; reverbIndex++) { + s32 subDelay; + // commonch* sampleState; + + reverb = &AG.synth_delay[reverbIndex]; + useReverb = reverb->use_reverb; + if (useReverb) { + // Loads reverb samples from DRAM (ringBuffer) into DMEM (DMEM_WET_LEFT_CH) + cmd = Nas_LoadAuxBuffer(cmd, aiBufLen, reverb, updateIndex); + + // Mixes reverb sample into the main dry channel + // reverb->volume is always set to 0x7FFF (audio spec), and DMEM_LEFT_CH is cleared before reverbs. + // So this is essentially a DMEMmove from DMEM_WET_LEFT_CH to DMEM_LEFT_CH + aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->volume, DMEM_WET_LEFT_CH, DMEM_LEFT_CH); + + subDelay = reverb->sub_delay; + if (subDelay != 0) { + aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, DMEM_2CH_SIZE); + } + + // Decays reverb over time. The (+ 0x8000) here is -100% + aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->decay_ratio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH); + + if (((reverb->leak_rtl != 0) || (reverb->leak_ltl != 0)) && (AG.sound_mode != SOUND_OUTPUT_MONO)) { + cmd = Nas_CrossMix(cmd, reverb); + } + + if (subDelay != 0) { + if (reverb->mix_reverb_idx != -1) { + cmd = Nas_SendLine(cmd, reverb, updateIndex); + } + + cmd = Nas_SaveAuxBuffer(cmd, reverb, updateIndex); + cmd = Nas_LoadAuxBuffer_B(cmd, aiBufLen, reverb, updateIndex); + aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->sub_volume, DMEM_WET_TEMP, DMEM_WET_LEFT_CH); + } + } + + while (i < noteCount) { + sampleState = &AG.common_channel[sampleStateOffset + noteIndices[i]]; + if (sampleState->reverb_idx != reverbIndex) { + break; + } + cmd = Nas_SynthMain(noteIndices[i], sampleState, &AG.channels[noteIndices[i]].driver_ch, + aiBuf, aiBufLen, cmd, updateIndex); + i++; + } + + if (useReverb) { + if ((reverb->filter_left != NULL) || (reverb->filter_right != NULL)) { + cmd = Nas_DelayFilter(cmd, size, reverb); + } + + // Saves the wet channel sample from DMEM (DMEM_WET_LEFT_CH) into (ringBuffer) DRAM for future use + if (subDelay != 0) { + cmd = Nas_SaveAuxBuffer_B(cmd, reverb, updateIndex); + } else { + if (reverb->mix_reverb_idx != -1) { + cmd = Nas_SendLine(cmd, reverb, updateIndex); + } + cmd = Nas_SaveAuxBuffer(cmd, reverb, updateIndex); + } + } + } + + while (i < noteCount) { + cmd = Nas_SynthMain(noteIndices[i], &AG.common_channel[sampleStateOffset + noteIndices[i]], + &AG.channels[noteIndices[i]].driver_ch, aiBuf, aiBufLen, cmd, + updateIndex); + i++; + } + + // size = aiBufLen * SAMPLE_SIZE; + aInterleave2(cmd++, DMEM_TEMP, DMEM_LEFT_CH, DMEM_RIGHT_CH, size); + + if (NA_DACOUT_CALLBACK != NULL) { + cmd = (Acmd*)((u32)NA_DACOUT_CALLBACK(cmd, 2 * size, updateIndex) & 0xFF); // ?? what is this? this has to be a bug + } + + aSaveBuffer2(cmd++, aiBuf, DMEM_TEMP, JAC_FRAMESAMPLES); + + return cmd; +} + +extern Acmd* Nas_SynthMain(s32 chan_id, commonch* common, driverch* driver, s16* samples, s32 samples_per_update, Acmd* cmd, s32 update_idx) { + s32 pad1[1]; + s32 size; + void* reverbAddrSrc; + smzwavetable* sample; + adpcmloop* loopInfo; + s32 numSamplesUntilEnd; + s32 flags; + s32 skipBytes; + s32 dmemUncompressedAddrOffset1; + s32 numSamplesToLoadAdj; + s32 numSamplesProcessed; + s32 numFirstFrameSamplesToIgnore; + s32 numSamplesToDecode; + s32 numSamplesInThisIteration; + s32 sampleFinished; + s32 loopToPoint; + u16 frequencyFixedPoint; + s32 gain; + s32 frameIndex; + u32 numSamplesToLoadFixedPoint; + s32 numSamplesToLoad; + u8* sampleAddr; + s32 sampleEndPos; + s32 numSamplesToProcess; + s32 dmemUncompressedAddrOffset2; + s32 pad2[3]; + s32 numSamplesInFirstFrame; + s32 numTrailingSamplesToIgnore; + s32 pad3[3]; + s16 sampleDataDmemAddr; + s32 frameSize; + s32 numFramesToDecode; + u8* samplesToLoadAddr; + s32 numParts; + s32 curPart; + s32 sampleDataChunkAlignPad; + s32 haasEffectDelaySide; + s32 sampleDataChunkSize; + s32 skipInitialSamples; + s32 zeroOffset; + s32 sampleAddrOffset; + s32 combFilterDmem; + channel* chan; + u32 combFilterSize; + u32 combFilterGain; + void* combFilterState; + s16* filter; + s32 numSamplesToLoadFirstPart; + u16 sampleDmemBeforeResampling; + u16 something_unused_from_sm64; + u32 stack_chan_id; + u32 stack_update_idx; + u8* tmpSamplesToLoadAddr; + s32 bookOffset = common->book_ofs; + s32 finished = common->finished; + + something_unused_from_sm64 = 0; + chan = &AG.channels[chan_id]; + DCTouchRange(chan, sizeof(channel)); + size = SAMPLE_SIZE * samples_per_update; + + // Deviation from MM: Ensure that the wavetable isn't null + if (common->tuned_sample != NULL) { + flags = A_CONTINUE; + + // Initialize the synthesis state + if (common->needs_init == true) { + flags = A_INIT; + driver->at_loop_point = false; + driver->stop_loop = false; + driver->sample_pos_integer_part = chan->playback_ch.start_sample_pos; + driver->sample_pos_fractional_part = 0; + + // deviation from MM + if (chan->playback_ch.adsr_envp.state.flags.unused == TRUE) { + // previously unused ADSR state bit seems to be used for preserving volume + driver->current_volume_left = common->target_volume_left << 4; + driver->current_volume_right = common->target_volume_right << 4; + } else { + driver->current_volume_left = 0; + driver->current_volume_right = 0; + } + + driver->prev_haas_effect_left_delay_size = 0; + driver->prev_haas_effect_right_delay_size = 0; + driver->cur_reverb_vol = common->target_reverb_volume; + driver->num_parts = 0; + driver->comb_filter_needs_init = true; + chan->common_ch.finished = false; + driver->vel_conv_table_idx = chan->playback_ch.vel_conv_table_idx; + finished = false; + } + + // Process the sample in either one or two parts + numParts = common->has_two_parts + 1; + + // Determine number of samples to load based on samples_per_update and relative frequency + frequencyFixedPoint = common->frequency_fixed_point; + numSamplesToLoadFixedPoint = (frequencyFixedPoint * samples_per_update * SAMPLE_SIZE) + driver->sample_pos_fractional_part; + numSamplesToLoad = (u16)(numSamplesToLoadFixedPoint >> 16); + + if (numSamplesToLoad == 0) { + skipBytes = false; + } + + driver->sample_pos_fractional_part = numSamplesToLoadFixedPoint & 0xFFFF; + + // Partially-optimized out no-op ifs required for matching. SM64 decomp + // makes it clear that this is how it should look. + if (((driver->num_parts == 1) && (numParts == 2))) { + } else if (((driver->num_parts == 2) && (numParts == 1))) { + } else { + something_unused_from_sm64 = 0; + } + + driver->num_parts = numParts; + + // deviation from MM here, no synth wave check + + sample = common->tuned_sample->wavetable; + loopInfo = sample->loop; + + if (chan->playback_ch.status != 0) { + driver->stop_loop = true; + } + + if ((loopInfo->count == 2) && driver->stop_loop) { + sampleEndPos = loopInfo->sample_end; + } else { + sampleEndPos = loopInfo->loop_end; + } + + stack_chan_id = chan_id; + stack_update_idx = update_idx; + sampleAddr = sample->sample; + numSamplesToLoadFirstPart = 0; + + // If the frequency requested is more than double that of the raw sample, + // then the sample processing is split into two parts. + for (curPart = 0; curPart < numParts; curPart++) { + numSamplesProcessed = 0; + dmemUncompressedAddrOffset1 = 0; + + // Adjust the number of samples to load only if there are two parts and an odd number of samples + if (numParts == 1) { + numSamplesToLoadAdj = numSamplesToLoad; + } else if ((s32)numSamplesToLoad & 1) { + // round down for the first part + // round up for the second part + numSamplesToLoadAdj = (numSamplesToLoad & ~1) + (curPart * 2); + } else { + numSamplesToLoadAdj = numSamplesToLoad; + } + + // Load the ADPCM codeBook + if ((sample->codec == CODEC_ADPCM) || (sample->codec == CODEC_SMALL_ADPCM)) { + if (AG.adpcm_code_book != sample->book->codebook) { + u32 numEntries; + + switch (bookOffset) { + case 1: + // AG.adpcm_code_book = &gInvalidAdpcmCodeBook[1]; + // break; + + case 2: + case 3: + default: + AG.adpcm_code_book = sample->book->codebook; + break; + } + + numEntries = SAMPLE_SIZE * sample->book->order * sample->book->n_predictors; + numEntries *= 8; // deviation from MM: multiply numEntries by 8 + if (numEntries != 0) { + aLoadADPCM(cmd++, numEntries, AG.adpcm_code_book); + } + } + } + + // Continue processing samples until the number of samples needed to load is reached + while (numSamplesProcessed != numSamplesToLoadAdj) { + sampleFinished = false; + loopToPoint = false; + dmemUncompressedAddrOffset2 = 0; + + numFirstFrameSamplesToIgnore = driver->sample_pos_integer_part & 0xF; + numSamplesUntilEnd = sampleEndPos - driver->sample_pos_integer_part; + + // Calculate number of samples to process this loop + numSamplesToProcess = numSamplesToLoadAdj - numSamplesProcessed; + + if ((numFirstFrameSamplesToIgnore == 0) && !driver->at_loop_point) { + numFirstFrameSamplesToIgnore = SAMPLES_PER_FRAME; + } + numSamplesInFirstFrame = SAMPLES_PER_FRAME - numFirstFrameSamplesToIgnore; + + // Determine the number of samples to decode based on whether the end will be reached or not. + if (numSamplesUntilEnd > numSamplesToProcess) { + // The end will not be reached. + numFramesToDecode = + (s32)(numSamplesToProcess + SAMPLES_PER_FRAME - 1 - numSamplesInFirstFrame) / SAMPLES_PER_FRAME; + numSamplesToDecode = numFramesToDecode * SAMPLES_PER_FRAME; + numTrailingSamplesToIgnore = numSamplesInFirstFrame + numSamplesToDecode - numSamplesToProcess; + } else { + // The end will be reached. + numSamplesToDecode = numSamplesUntilEnd - numSamplesInFirstFrame; + if (numSamplesToDecode <= 0) { + numSamplesToDecode = 0; + numSamplesInFirstFrame = numSamplesUntilEnd; + } + numTrailingSamplesToIgnore = 0; + numFramesToDecode = (numSamplesToDecode + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME; + if (loopInfo->count != 0) { + if ((loopInfo->count == 2) && driver->stop_loop) { + sampleFinished = true; + } else { + // Loop around and restart + loopToPoint = true; + } + } else { + sampleFinished = true; + } + } + + // Set parameters based on compression type + switch (sample->codec) { + case CODEC_ADPCM: + // 16 2-byte samples (32 bytes) compressed into 4-bit samples (8 bytes) + 1 header byte + frameSize = 9; + skipInitialSamples = SAMPLES_PER_FRAME; + zeroOffset = 0; + break; + + case CODEC_SMALL_ADPCM: + // 16 2-byte samples (32 bytes) compressed into 2-bit samples (4 bytes) + 1 header byte + frameSize = 5; + skipInitialSamples = SAMPLES_PER_FRAME; + zeroOffset = 0; + break; + + case CODEC_UNK7: + // 2 2-byte samples (4 bytes) processed without decompression + frameSize = 4; + skipInitialSamples = SAMPLES_PER_FRAME; + zeroOffset = 0; + break; + + case CODEC_S8: + // 16 2-byte samples (32 bytes) compressed into 8-bit samples (16 bytes) + frameSize = 16; + skipInitialSamples = SAMPLES_PER_FRAME; + zeroOffset = 0; + break; + + case CODEC_REVERB: + reverbAddrSrc = (void*)0xFFFFFFFF; + if (NA_SOUND_CALLBACK != NULL) { + // ??? + reverbAddrSrc = (void*)((u32)NA_SOUND_CALLBACK(sample, numSamplesToLoadAdj, flags, chan_id) & 0xFF); + } + + if ((s32)reverbAddrSrc == 0xFFFFFFFF) { + sampleFinished = true; + } else if ((s32)reverbAddrSrc == 0) { + return cmd; + } else { + Nas_LoadBuffer2(cmd++, DMEM_UNCOMPRESSED_NOTE, + numSamplesToLoadAdj * SAMPLE_SIZE + SAMPLES_PER_FRAME * SAMPLE_SIZE, + (s32)reverbAddrSrc); + // deviation from MM: + goto codec_continue_and_skip; + // flags = A_CONTINUE; + // skipBytes = 0; + // numSamplesProcessed = numSamplesToLoadAdj; + // dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; + } + goto skip; + + case CODEC_S16_INMEMORY: + case CODEC_UNK6: + Nas_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, + numSamplesToLoadAdj * SAMPLE_SIZE + SAMPLES_PER_FRAME * SAMPLE_SIZE); +codec_continue_and_skip: + skipBytes = 0; + flags = A_CONTINUE; + numSamplesProcessed = numSamplesToLoadAdj; + dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; + goto skip; + + case CODEC_S16: + Nas_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, + numSamplesToLoadAdj * SAMPLE_SIZE + SAMPLES_PER_FRAME * SAMPLE_SIZE); + skipBytes = 0; + flags = A_CONTINUE; + numSamplesProcessed = numSamplesToLoadAdj; + dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; + goto skip; + + default: + break; + } + + sampleDataChunkSize = ALIGN_PREV((numFramesToDecode * frameSize) + 31, 16); + sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize; + + // Move the compressed raw sample data from ram into the rsp (DMEM) + if (numFramesToDecode != 0) { + // Get the offset from the start of the sample to where the sample is currently playing from + frameIndex = (skipInitialSamples + driver->sample_pos_integer_part - numFirstFrameSamplesToIgnore) / + SAMPLES_PER_FRAME; + sampleAddrOffset = frameIndex * frameSize; + tmpSamplesToLoadAddr = sampleAddr + sampleAddrOffset; + tmpSamplesToLoadAddr += zeroOffset; + + // Get the ram address of the requested sample chunk + if (sample->medium == MEDIUM_RAM) { + // Sample is already loaded into ram + if (sample->bit31 == TRUE) { + samplesToLoadAddr = (u8*)(*NA_SYNC_PROC)(tmpSamplesToLoadAddr, numFramesToDecode * frameSize); + } else { + samplesToLoadAddr = tmpSamplesToLoadAddr; + } + } else if (AG._2A14) { // always false + return cmd; + } else if (sample->medium == MEDIUM_DISK) { + // This medium is unsupported so terminate processing this chan + return cmd; + } else { + // This medium is not in ram, so dma the requested sample into ram + samplesToLoadAddr = (u8*)Nas_WaveDmaCallBack((u32)(tmpSamplesToLoadAddr), + sampleDataChunkSize, flags, + &driver->sample_dma_idx, sample->medium); + } + + if (samplesToLoadAddr == NULL) { + // The ram address was unsuccessfully allocated + return cmd; + } + + // Move the raw sample chunk from ram to the rsp + // DMEM at the addresses before DMEM_COMPRESSED_ADPCM_DATA + sampleDataChunkAlignPad = (u32)samplesToLoadAddr & 0xF; + aLoadCache(cmd++, samplesToLoadAddr - sampleDataChunkAlignPad, sampleDataDmemAddr, + sampleDataChunkSize); + } else { + numSamplesToDecode = 0; + sampleDataChunkAlignPad = 0; + } + + if (driver->at_loop_point) { + aSetLoop(cmd++, sample->loop->predictor_state); + flags = A_LOOP; + driver->at_loop_point = false; + } + + numSamplesInThisIteration = numSamplesToDecode + numSamplesInFirstFrame - numTrailingSamplesToIgnore; + + if (numSamplesProcessed == 0) { + //! FAKE: + if (1) {} + skipBytes = numFirstFrameSamplesToIgnore * SAMPLE_SIZE; + } else { + dmemUncompressedAddrOffset2 = ALIGN_NEXT(dmemUncompressedAddrOffset1 + 8 * SAMPLE_SIZE, 16); + } + + // Decompress the raw sample chunks in the rsp + // Goes from adpcm (compressed) sample data to pcm (uncompressed) sample data + switch (sample->codec) { + case CODEC_ADPCM: + aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, + numSamplesToDecode * SAMPLE_SIZE); + aADPCMdec(cmd++, flags, driver->synth_params->adpcm_state); + break; + + case CODEC_SMALL_ADPCM: + aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, + numSamplesToDecode * SAMPLE_SIZE); + aADPCMdec(cmd++, flags | A_ADPCM_SHORT, driver->synth_params->adpcm_state); + break; + + case CODEC_S8: + Nas_SetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, + numSamplesToDecode * SAMPLE_SIZE); + Nas_PCM8dec(cmd++, flags, (s32)driver->synth_params->adpcm_state); + break; + + case CODEC_UNK7: + default: + // No decompression + break; + } + + if (numSamplesProcessed != 0) { + aDMEMMove(cmd++, + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2 + + (numFirstFrameSamplesToIgnore * SAMPLE_SIZE), + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1, + numSamplesInThisIteration * SAMPLE_SIZE); + } + + numSamplesProcessed += numSamplesInThisIteration; + + switch (flags) { + case A_INIT: + skipBytes = SAMPLES_PER_FRAME * SAMPLE_SIZE; + dmemUncompressedAddrOffset1 = numSamplesToDecode * SAMPLE_SIZE + SAMPLES_PER_FRAME * SAMPLE_SIZE; + break; + + case A_LOOP: + dmemUncompressedAddrOffset1 = + numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1; + break; + + default: + if (dmemUncompressedAddrOffset1 != 0) { + dmemUncompressedAddrOffset1 = + numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1; + } else { + dmemUncompressedAddrOffset1 = + (numFirstFrameSamplesToIgnore + numSamplesInThisIteration) * SAMPLE_SIZE; + } + break; + } + + flags = A_CONTINUE; + + skip: + + // Update what to do with the samples next + if (sampleFinished) { + s32 dmemClearCount = numSamplesToLoadAdj - numSamplesProcessed; + if (dmemClearCount != 0) { + Nas_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1, + dmemClearCount * SAMPLE_SIZE); + } + finished = true; + chan->common_ch.finished = true; + __Nas_WaveTerminateProcess(stack_update_idx, stack_chan_id); + break; // break out of the for-loop + } else if (loopToPoint) { + driver->at_loop_point = true; + driver->sample_pos_integer_part = loopInfo->loop_start; + } else { + driver->sample_pos_integer_part += numSamplesToProcess; + } + } + + switch (numParts) { + case 1: + sampleDmemBeforeResampling = DMEM_UNCOMPRESSED_NOTE + skipBytes; + break; + + case 2: + switch (curPart) { + case 0: + Nas_HalfCut(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes, + DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE), + ALIGN_NEXT(numSamplesToLoadAdj / 2, 8)); + numSamplesToLoadFirstPart = numSamplesToLoadAdj; + sampleDmemBeforeResampling = DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE); + if (finished) { + Nas_ClearBuffer(cmd++, sampleDmemBeforeResampling + numSamplesToLoadFirstPart, + numSamplesToLoadAdj + SAMPLES_PER_FRAME); + } + break; + + case 1: + Nas_HalfCut(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes, + DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE) + numSamplesToLoadFirstPart, + ALIGN_NEXT(numSamplesToLoadAdj / 2, 8)); + break; + + default: + break; + } + break; + + default: + break; + } + if (finished) { + break; + } + } + + // Update the flags for the signal processing below + flags = A_CONTINUE; + if (common->needs_init == true) { + flags = A_INIT; + common->needs_init = false; + } + + // Resample the decompressed mono-signal to the correct pitch + cmd = Nas_Synth_Resample(cmd, driver, size, frequencyFixedPoint, + sampleDmemBeforeResampling, flags | something_unused_from_sm64); + + // Not present in MM + if (bookOffset != 0) { + Nas_NoiseFilter(cmd++, DMEM_TEMP, samples_per_update, NOISE_TABLE[(bookOffset >> 4) & 0xF], NOISE_TABLE[bookOffset & 0xF]); + } + + // Apply the gain to the mono-signal to adjust the volume + gain = common->gain; + if (gain != 0) { + // A gain of 0x10 (a UQ4.4 number) is equivalent to 1.0 and represents no volume change + if (gain < 0x10) { + gain = 0x10; + } + Nas_DistFilter(cmd++, gain, DMEM_TEMP, 0, size + SAMPLES_PER_FRAME * SAMPLE_SIZE); + } + + // Not in MM + if (!STOP_VELOCONV) { + // Load the velocity convolution table into DMEM_0x800 + s32 vel_conv_idx = driver->vel_conv_table_idx; + aLoadBuffer2(cmd++, (u32)VELOCONV_TABLE[vel_conv_idx], 0x800, sizeof(VELOCONV_TABLE[vel_conv_idx])); + aUnkCmd3(cmd++, DMEM_TEMP, 0x800, samples_per_update); + } + + // Apply the filter to the mono-signal + filter = common->filter; + if (filter != 0) { + Nas_FirLoadTable(cmd++, size, filter); + Nas_FirFilter(cmd++, flags, DMEM_TEMP, driver->synth_params->filter_state); + } + + // Apply the comb filter to the mono-signal by taking the signal with a small temporal offset, + // and adding it back to itself + combFilterSize = common->comb_filter_size; + combFilterGain = common->comb_filter_gain; + combFilterState = driver->synth_params->comb_filter_state; + if ((common->comb_filter_size != 0) && (common->comb_filter_gain != 0)) { + Nas_DMEMMove(cmd++, DMEM_TEMP, DMEM_COMB_TEMP, size); + // combFilterDmem = DMEM_COMB_TEMP - combFilterSize; + if (driver->comb_filter_needs_init) { + Nas_ClearBuffer(cmd++, DMEM_COMB_TEMP - combFilterSize, combFilterSize); + driver->comb_filter_needs_init = false; + } else { + Nas_LoadBuffer2(cmd++, DMEM_COMB_TEMP - combFilterSize, combFilterSize, (s32)combFilterState); + } + Nas_SaveBuffer2(cmd++, DMEM_TEMP - combFilterSize + size, combFilterSize, (s32)combFilterState); + Nas_Mix(cmd++, size >> 4, combFilterGain, DMEM_COMB_TEMP, DMEM_COMB_TEMP - combFilterSize); + Nas_DMEMMove(cmd++, DMEM_COMB_TEMP - combFilterSize, DMEM_TEMP, size); + } else { + driver->comb_filter_needs_init = true; + } + + // Determine the behavior of the audio processing that leads to the haas effect + if ((common->haas_effect_left_delay_size != 0) || (driver->prev_haas_effect_left_delay_size != 0)) { + haasEffectDelaySide = HAAS_EFFECT_DELAY_LEFT; + } else if ((common->haas_effect_right_delay_size != 0) || (driver->prev_haas_effect_right_delay_size != 0)) { + haasEffectDelaySide = HAAS_EFFECT_DELAY_RIGHT; + } else { + haasEffectDelaySide = HAAS_EFFECT_DELAY_NONE; + } + + // Apply an unknown effect based on the surround sound-mode + if (AG.sound_mode == SOUND_OUTPUT_DOLBY_SURROUND) { + // common->target_volume_left = common->target_volume_left >> 1; + // common->target_volume_right = common->target_volume_right >> 1; + if (common->surround_effect_idx != 0xFF) { + cmd = Nas_DolbySurround(cmd, common, driver, samples_per_update, DMEM_TEMP, flags); + } + } + + // Split the mono-signal into left and right channels: + // Both for dry signal (to go to the speakers now) + // and for wet signal (to go to a reverb buffer to be stored, and brought back later to produce an echo) + cmd = Nas_Synth_Envelope(cmd, common, driver, samples_per_update, DMEM_TEMP, haasEffectDelaySide, flags); + + // Apply the haas effect by delaying either the left or the right channel by a small amount + if (common->use_haas_effect) { + if (!(flags & A_INIT)) { + flags = A_CONTINUE; + } + cmd = Nas_Synth_Delay(cmd, common, driver, size, flags, haasEffectDelaySide); + } + } + + return cmd; +} + +Acmd* Nas_DolbySurround(Acmd* cmd, commonch* common, driverch* driver, s32 num_samples_per_update, s32 haas_dmem, s32 flags) { + s32 size; + u16 wetGain; + u16 dryGain; + s64 dmem = DMEM_SURROUND_TEMP; + f32 decayGain; + + size = num_samples_per_update * SAMPLE_SIZE; + Nas_DMEMMove(cmd++, haas_dmem, DMEM_HAAS_TEMP, size); + dryGain = driver->surround_effect_gain; + + if (flags == A_INIT) { + aClearBuffer(cmd++, dmem, sizeof(driver->synth_params->surround_effect_state)); + driver->surround_effect_gain = 0; + } else { + wetGain = (driver->surround_effect_gain * driver->cur_reverb_vol) >> 7; + + aLoadBuffer2(cmd++, driver->synth_params->surround_effect_state, dmem, sizeof(driver->synth_params->surround_effect_state)); + + aMix(cmd++, size >> 4, dryGain, dmem, DMEM_LEFT_CH); + aMix(cmd++, size >> 4, (u16)(dryGain ^ 0xFFFF), dmem, DMEM_RIGHT_CH); + + aMix(cmd++, size >> 4, wetGain, dmem, DMEM_WET_LEFT_CH); + aMix(cmd++, size >> 4, (wetGain ^ 0xFFFF), dmem, DMEM_WET_RIGHT_CH); + } + + aSaveBuffer2(cmd++, driver->synth_params->surround_effect_state, DMEM_SURROUND_TEMP + size, sizeof(driver->synth_params->surround_effect_state)); + + decayGain = (common->target_volume_left + common->target_volume_right) / 8192.0f; + if (decayGain > 1.0f) { + decayGain = 1.0f; + } + + decayGain = decayGain * StereoLeft[127 - common->surround_effect_idx]; + driver->surround_effect_gain = ((decayGain * 0x7FFF) + driver->surround_effect_gain) / 2; + + Nas_DMEMMove(cmd++, DMEM_HAAS_TEMP, haas_dmem, size); + + return cmd; +} + +extern Acmd* Nas_Synth_Resample(Acmd* cmd, const driverch* driver, s32 size, u16 pitch, u16 sampleDmemBeforeResampling, s32 flags) { + if (pitch == 0) { + Nas_ClearBuffer(cmd++, DMEM_TEMP, size); + } else { + aSetBuffer(cmd++, 0, sampleDmemBeforeResampling, DMEM_TEMP, size); + aResample(cmd++, flags, pitch, driver->synth_params->final_resample_state); + } + + return cmd; +} + +extern Acmd* Nas_Synth_Envelope(Acmd* cmd, commonch* common, driverch* driver, s32 samples_per_update, u16 dmem, s32 haasEffectDelaySide, s32 flags) { + s32 targetReverbVol = common->target_reverb_volume; + s16* currentVolume = &driver->current_volume_left; + s16 curVolLeftTemp = *currentVolume++; + u16 curVolRight = *currentVolume & 0xFFFF; + u16 curVolLeft = curVolLeftTemp & 0xFFFF; + u16 targetVolLeft = common->target_volume_left << 4; + u16 targetVolRight = common->target_volume_right << 4; + u32 dmemDests; + s32 curReverbVolAndFlags; + u16 curReverbVol; + s16 rampLeft; + s16 rampRight; + s16 rampReverb; + f32 defaultPanVolume; + + + // targetReverbVol = common->target_reverb_volume; + // curVolLeft = driver->current_volume_left; + // curVolRight = driver->current_volume_right; + + // targetVolLeft = common->target_volume_left << 4; + // targetVolRight = common->target_volume_right << 4; + + if (AG.sound_mode == SOUND_OUTPUT_DOLBY_SURROUND) { + u8 idx = common->surround_effect_idx; + + if (idx != 0xFF) { + defaultPanVolume = StereoLeft[idx]; + targetVolLeft *= defaultPanVolume; + targetVolRight *= defaultPanVolume; + } + } + + if (targetVolLeft != (u32)curVolLeft) { + rampLeft = (targetVolLeft - (s32)curVolLeft) / (samples_per_update >> 3); + } else { + rampLeft = 0; + } + + if (targetVolRight != (u32)curVolRight) { + rampRight = (targetVolRight - (s32)curVolRight) / (samples_per_update >> 3); + } else { + rampRight = 0; + } + + curReverbVolAndFlags = (s16)driver->cur_reverb_vol; + if (targetReverbVol != curReverbVolAndFlags) { + curReverbVol = curReverbVolAndFlags & 0x7F; + rampReverb = (((targetReverbVol & 0x7F) - (curReverbVol)) << 9) / (samples_per_update >> 3); + driver->cur_reverb_vol = targetReverbVol; + } else { + rampReverb = 0; + } + + driver->current_volume_left = curVolLeft + (rampLeft * (samples_per_update >> 3)); + driver->current_volume_right = curVolRight + (rampRight * (samples_per_update >> 3)); + + if (common->use_haas_effect) { + // curReverbVol = curReverbVolAndFlags & 0x7F; + Nas_ClearBuffer(cmd++, DMEM_HAAS_TEMP, DMEM_1CH_SIZE); + Nas_SetEnvParam(cmd++, (curReverbVolAndFlags & 0x7F) * 2, rampReverb, rampLeft, rampRight); + Nas_SetEnvParam2(cmd++, curVolLeft, curVolRight); + + switch (haasEffectDelaySide) { + case HAAS_EFFECT_DELAY_LEFT: + // Store the left dry channel in a temp space to be delayed to produce the haas effect + dmemDests = Env_Data_L1; + break; + + case HAAS_EFFECT_DELAY_RIGHT: + // Store the right dry channel in a temp space to be delayed to produce the haas effect + dmemDests = Env_Data_L2; + break; + + default: // HAAS_EFFECT_DELAY_NONE + dmemDests = Env_Data_L3; + break; + } + } else { + curReverbVol = (curReverbVolAndFlags << 1) & 0xFE; + aSetEnvParam(cmd++, (curReverbVol), rampReverb, rampLeft, rampRight); + + { + cmd->words.w0 = _SHIFTL(A_CMD_SETENVPARAM2, 24, 8); + cmd->words.w1 = _SHIFTL(curVolLeft, 16, 16) | _SHIFTL(curVolRight, 0, 16); + cmd++; + } + // aSetEnvParam2(cmd++, curVolLeft & 0xFFFF, curVolRight & 0xFFFF); + dmemDests = Env_Data_L3; + } + + aEnvMixer2(cmd++, dmem, samples_per_update, (curReverbVolAndFlags & 0x80) >> 7, + common->strong_reverb_right, common->strong_reverb_left, + common->strong_right, common->strong_left, dmemDests, Env_DataH); + + return cmd; +} + +extern Acmd* Nas_Synth_Delay(Acmd* cmd, commonch* common, driverch* driver, s32 size, s32 flags, s32 haasEffectDelaySide) { + u16 haasEffectDelaySize; + u16 prevHaasEffectDelaySize; + u16 dmemDest; + u16 pitch; + + switch (haasEffectDelaySide) { + case HAAS_EFFECT_DELAY_LEFT: + // Delay the sample on the left channel + // This allows the right channel to be heard first + dmemDest = DMEM_LEFT_CH; + haasEffectDelaySize = common->haas_effect_left_delay_size; + prevHaasEffectDelaySize = driver->prev_haas_effect_left_delay_size; + driver->prev_haas_effect_left_delay_size = haasEffectDelaySize; + driver->prev_haas_effect_right_delay_size = 0; + break; + + case HAAS_EFFECT_DELAY_RIGHT: + // Delay the sample on the right channel + // This allows the left channel to be heard first + dmemDest = DMEM_RIGHT_CH; + haasEffectDelaySize = common->haas_effect_right_delay_size; + prevHaasEffectDelaySize = driver->prev_haas_effect_right_delay_size; + driver->prev_haas_effect_right_delay_size = haasEffectDelaySize; + driver->prev_haas_effect_left_delay_size = 0; + break; + + default: // HAAS_EFFECT_DELAY_NONE + return cmd; + } + + if (flags != A_INIT) { + // Slightly adjust the sample rate in order to fit a change in sample delay + if (haasEffectDelaySize != prevHaasEffectDelaySize) { + pitch = pitch = (((size << 0xF) / 2) - 1) / ((size + haasEffectDelaySize - prevHaasEffectDelaySize - 2) / 2); + aSetBuffer(cmd++, 0, DMEM_HAAS_TEMP, DMEM_TEMP, size + haasEffectDelaySize - prevHaasEffectDelaySize); + aResampleZoh(cmd++, pitch, 0); + } else { + aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size); + } + + if (prevHaasEffectDelaySize != 0) { + aLoadBuffer2(cmd++, driver->synth_params->haas_effect_delay_state, DMEM_HAAS_TEMP, + ALIGN_NEXT(prevHaasEffectDelaySize, 16)); + aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + prevHaasEffectDelaySize, + size + haasEffectDelaySize - prevHaasEffectDelaySize); + } else { + aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP, size + haasEffectDelaySize); + } + } else { + // Just apply a delay directly + aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size); + if (haasEffectDelaySize) { // != 0 + aClearBuffer(cmd++, DMEM_HAAS_TEMP, haasEffectDelaySize); + } + aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + haasEffectDelaySize, size); + } + + if (haasEffectDelaySize) { // != 0 + // Save excessive samples for next iteration + aSaveBuffer2(cmd++, driver->synth_params->haas_effect_delay_state, DMEM_HAAS_TEMP + size, + ALIGN_NEXT(haasEffectDelaySize, 16)); + } + + aAddMixer(cmd++, ALIGN_NEXT(size, 64), DMEM_HAAS_TEMP, dmemDest, 0x7FFF); + + return cmd; +} diff --git a/src/static/jaudio_PP/internal/dspboot.c b/src/static/jaudio_PP/internal/dspboot.c index 94b94940..1594ba51 100644 --- a/src/static/jaudio_PP/internal/dspboot.c +++ b/src/static/jaudio_PP/internal/dspboot.c @@ -245,6 +245,27 @@ u16 jdsp[] ATTRIBUTE_ALIGN(32) = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, }; +extern void DSPInit2(DSPTaskInfo2* task); + +void DspBoot(){ + DSPTaskInfo2 task; + + task.iram_mmem_addr = jdsp; + task.iram_length = sizeof(jdsp); + task.iram_addr = 0; + task.dram_mmem_addr = jdsp; + task.dram_length = 0x100; + task.dram_addr = 0; + + task.dsp_init_vector = 0; + DSPInit2(&task); + + while(DSPCheckMailFromDSP() == 0); + DSPReadMailFromDSP(); + DSPCheckMailFromDSP(); + DwaitFrame(); +} + extern s32 __DSPCheckMXICBoot2(DSPTaskInfo2* task) { u32 mail; @@ -358,23 +379,3 @@ extern void DSPInit2 (DSPTaskInfo2* task){ OSPanic("mxic.c", 357,"DSPInit(): MXIC Boot failed."); } } - - -void DspBoot(){ - DSPTaskInfo2 task; - - task.iram_mmem_addr = jdsp; - task.iram_length = sizeof(jdsp); - task.iram_addr = 0; - task.dram_mmem_addr = jdsp; - task.dram_length = 0x100; - task.dram_addr = 0; - - task.dsp_init_vector = 0; - DSPInit2(&task); - - while(DSPCheckMailFromDSP() == 0); - DSPReadMailFromDSP(); - DSPCheckMailFromDSP(); - DwaitFrame(); -} diff --git a/src/static/jaudio_PP/internal/dummyrom.c b/src/static/jaudio_PP/internal/dummyrom.c index 9a16c9d9..ade1b45d 100644 --- a/src/static/jaudio_PP/internal/dummyrom.c +++ b/src/static/jaudio_PP/internal/dummyrom.c @@ -65,7 +65,7 @@ extern void* ARAllocFull(u32* outSize) { } extern void Jac_InitARAM(u32 loadAudiorom) { - u32 aram_size = AUDIO_ARAM_SIZE; + u32 aram_size = 0x810000; volatile u32 audiorom_size; if (SELECTED_ARAM_SIZE != 0) { diff --git a/src/static/jaudio_PP/internal/jammain_2.c b/src/static/jaudio_PP/internal/jammain_2.c index a8ab8801..039b556f 100644 --- a/src/static/jaudio_PP/internal/jammain_2.c +++ b/src/static/jaudio_PP/internal/jammain_2.c @@ -53,9 +53,6 @@ static seqp_* SEQ_P; static u8 SEQ_CMD; static u32 SEQ_ARG[8]; -// predeclare this so Jam_UpdateTrackAll can use this stupid function. -extern "C" static void OSf32tos8(f32* in, s8* out); - /* * --INFO-- * Address: 8000F400 @@ -257,2944 +254,375 @@ int Jam_SEQtimeToDSPtime(seqp_* track, s32 param_2, u8 param_3) return dspTime; } -/* - * --INFO-- - * Address: 8000F8C0 - * Size: 000020 - */ -u16 Extend8to16(u8 value) -{ - if (value & 0x80) { - return value + 0xFF00; - } - return value; -} - -/* - * --INFO-- - * Address: 8000F8E0 - * Size: 0001A8 - */ -void Jam_WriteTimeParam(seqp_* track, u8 controlByte) -{ - - s32 duration; - u8 paramIndex; - s16 targetValue; - MoveParam_* param; - - duration = 0; - paramIndex = __ByteRead(track); - - // Extract target value based on controlByte[3:2] - switch (controlByte & 0x0C) { - case 0x00: // Use register value - targetValue = track->regParam.reg[__ByteRead(track)]; - break; - case 0x04: // 8-bit immediate value - targetValue = __ByteRead(track); - break; - case 0x08: // 8-bit value shifted to high byte - targetValue = __ByteRead(track) << 8; - break; - case 0x0C: // 16-bit immediate value - targetValue = __WordRead(track); - break; - } - - // Determine time over which to interpolate the parameter - switch (controlByte & 0x03) { - case 0: // Immediate (no interpolation) - duration = -1; - break; - case 1: // Time from register - duration = track->regParam.reg[__ByteRead(track)]; - break; - case 2: // 8-bit immediate duration - duration = __ByteRead(track); - break; - case 3: // 16-bit immediate duration - duration = __WordRead(track); - break; - } - - param = &track->timedParam.move[paramIndex]; - param->targetValue = targetValue / 32768.0f; - - if (duration >= 0) { - param->duration = duration; - } - - if (param->duration <= 0.0f) { - param->currentValue = param->targetValue; - param->stepSize = 0.0f; - param->duration = 1.0f; - } else { - param->stepSize = (param->targetValue - param->currentValue) / param->duration; - } -} - -/* - * --INFO-- - * Address: 8000FAA0 - * Size: 0000AC - */ -void Jam_WriteRegDirect(seqp_* track, u8 index, u16 value) -{ - - u16 uVar1; - - switch (index) { - case 0: - case 1: - case 2: - value = value & 0xff; - uVar1 = Extend8to16(value); - break; - case 32: - case 33: - return; - case 34: - Jam_WriteRegDirect(track, 0, value >> 8); - uVar1 = value; - value = value & 0xff; - index = 1; - break; - default: - uVar1 = value; - break; - } - - track->regParam.reg[index] = value; - track->regParam.param.value = uVar1; -} - -/* - * --INFO-- - * Address: 8000FB60 - * Size: 000098 - */ -static u32 LoadTbl(seqp_* track, u32 ofs, u32 idx, u32 param_4) -{ - u32 result; +#include "../src/static/jaudio_PP/internal/jammain_2_reg.c_inc" +#include "../src/static/jaudio_PP/internal/jammain_2_port.c_inc" +#include "../src/static/jaudio_PP/internal/jammain_2_update.c_inc" +#include "../src/static/jaudio_PP/internal/jammain_2_cmd.c_inc" +#include "../src/static/jaudio_PP/internal/jammain_2_cmdproc.c_inc" - switch (param_4) { - case 4: - result = __ByteReadOfs(track, ofs + idx); - break; - case 5: - idx = idx * 2; - result = __WordReadOfs(track, ofs + idx); - break; - case 6: - idx = idx * 2 + idx; // Roundabout way to multiply by 3. - result = __24ReadOfs(track, ofs + idx); - break; - case 7: - idx = idx * 4; - case 8: - result = __LongReadOfs(track, ofs + idx); - break; - } - return result; -} +// TODO: These five values appear all over this file. They mean something. +static u8 osc_table[] = { 0x01, 0x02, 0x08, 0x04, 0x10 }; /* * --INFO-- - * Address: 8000FC00 - * Size: 000484 + * Address: 80012EC0 + * Size: 0008C0 + * Note: (Roughly) Equivalent to `JASTrack::mainProc` in later JAudio. */ -void Jam_WriteRegParam(seqp_* track, u8 param_2) -{ - - s16 r30_newRegValue; // r30 - u8 r29_regIdx; // r29 - u16 r28; // r28 - u32 unaff_r27; // r27 - u32 r26; // r26 - u32 r25; // r25 - u32 unaff_r24; // r24 - s16 r23_oldRegValue; // r23 - - r26 = param_2 & 0xc; - r25 = param_2 & 3; - if ((param_2 & 0x0F) == 0x0B) { - r26 = 0; - r25 = 0xb; - } - if ((param_2 & 0x0F) == 0x0A) { - param_2 = __ByteRead(track); - r26 = param_2 & 0x0C; - r25 = 0xa; - unaff_r24 = (u8)(param_2 >> 4) + 4; - } - if ((param_2 & 0x0F) == 0x09) { - param_2 = __ByteRead(track); - r26 = param_2 & 0x0c; - r25 = param_2 & 0xf0; - if (r26 == 8) { - r26 = 0x10; - } - } - r29_regIdx = __ByteRead(track); - if (r25 == 0x0A) { - unaff_r27 = Jam_ReadReg32(track, __ByteRead(track)); - } - switch (r26) { - case 0: - r30_newRegValue = Jam_ReadRegDirect(track, __ByteRead(track)); - break; - case 4: - r30_newRegValue = __ByteRead(track); - break; - case 8: - r30_newRegValue = __ByteRead(track) << 8; - break; - case 12: - r30_newRegValue = __WordRead(track); - break; - case 16: - r30_newRegValue = -1; - } - - r23_oldRegValue = Jam_ReadRegDirect(track, r29_regIdx); - switch (r25) { - case 0x00: - break; - case 0x01: - if (r26 == 4) { - r30_newRegValue = Extend8to16(r30_newRegValue); - } - r30_newRegValue = r23_oldRegValue + r30_newRegValue; - break; - case 0x02: - unaff_r27 = r23_oldRegValue * r30_newRegValue; - Jam_WriteRegXY(track, unaff_r27); - return; - case 0x03: - track->regParam.param.value = r23_oldRegValue - r30_newRegValue; - return; - case 0x0B: - r30_newRegValue = r23_oldRegValue - r30_newRegValue; - break; - case 0x10: - if (r26 == 4) { - r30_newRegValue = Extend8to16(r30_newRegValue); - } - if (r30_newRegValue < 0) { - r30_newRegValue = (u16)r23_oldRegValue >> -r30_newRegValue; - } else { - r30_newRegValue = (u16)r23_oldRegValue << r30_newRegValue; - } - break; - case 0x20: - if (r26 == 4) { - r30_newRegValue = Extend8to16(r30_newRegValue); - } - if (r30_newRegValue < 0) { - r30_newRegValue = r23_oldRegValue >> -r30_newRegValue; - } else { - r30_newRegValue = r23_oldRegValue << r30_newRegValue; - } - break; - case 0x30: - r30_newRegValue = r23_oldRegValue & r30_newRegValue; - break; - case 0x40: - r30_newRegValue = r23_oldRegValue | r30_newRegValue; - break; - case 0x50: - r30_newRegValue = r23_oldRegValue ^ r30_newRegValue; - break; - case 0x60: - r30_newRegValue = -r23_oldRegValue; - break; - case 0x90: - unaff_r27 = GetRandom_s32(); - r30_newRegValue = unaff_r27 % (u16)r30_newRegValue; - break; - case 0xA: - unaff_r27 = LoadTbl(track, unaff_r27, r30_newRegValue, unaff_r24); - r30_newRegValue = (u16)unaff_r27; - break; - } - - switch (r29_regIdx) { - case 0: - case 1: - case 2: - r30_newRegValue = r30_newRegValue & 0xff; - r28 = Extend8to16(r30_newRegValue); - break; - case 0x21: - r29_regIdx = 6; - r30_newRegValue = track->regParam.param.bankNumber & 0xff00 | r30_newRegValue & 0x00ff; - break; - case 0x20: - r29_regIdx = 6; - r30_newRegValue = track->regParam.param.bankNumber & 0x00ff | r30_newRegValue << 8; - break; - case 0x2E: - r29_regIdx = 0xd; - r30_newRegValue = track->regParam.param.basePriority & 0xff00 | r30_newRegValue & 0x00ff; - break; - case 0x2F: - r29_regIdx = 0xd; - r30_newRegValue = track->regParam.param.basePriority & 0x00ff | r30_newRegValue << 8; - break; - case 0x22: - Jam_WriteRegDirect(track, 0, r30_newRegValue >> 8); - r30_newRegValue = r30_newRegValue & 0xff; - r28 = r30_newRegValue; - r29_regIdx = 1; - break; - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - track->regParam.param._20[r29_regIdx - 0x28] = unaff_r27; - return; - default: - r28 = r30_newRegValue; - break; - } +#pragma opt_dead_assignments off +s32 Jam_SeqmainNote(seqp_* track, u8 isMuted) { + u32 pitch; + u32 uVar2; + BOOL var_r26; + u8 bVar9; + u8 velocity; + u32 noteMode; + int iVar11; + s32 uVar5; + u8 bVar10_2; + f32 tempoProportion; + u8 opcode; + u8 uVar6; + u32 keyTarget; + u8 bVar10; + int local_64; + int iVar11_2; + int iVar12; + u32 seqRes; + int duration; + int iVar11_3; + u8 voice; + + seqRes = 0; + if (track->parent && track->doChangeTempo == TRUE) { + tempoProportion = (float)track->tempo / (float)track->parent->tempo; + if (tempoProportion > 1.0f) { + tempoProportion = 1.0f; + } + track->tempoAccumulator += tempoProportion; + if (track->tempoAccumulator < 1.0f) { + return 0; + } + track->tempoAccumulator -= 1.0f; + } + + { // This whole part is not present(?) in later JAudio. + if (track->parent) { + track->isMuted = isMuted; + } + if (track->parent && track->parentController.chanCount != 0) { + jc_* pjVar3 = List_GetChannel(&track->parentController.freeChannels); + if (pjVar3) { + List_AddChannel(&track->parent->parentController.freeChannels, pjVar3); + pjVar3->mMgr = &track->parent->parentController; + track->parentController.chanCount--; + track->parent->parentController.chanCount++; + } + } + // This resembles `JASTrack::getTranspose` of later JAudio. + if (track->parent) { + track->finalTranspose = track->transpose + track->parent->finalTranspose; + } else { + track->finalTranspose = track->transpose; + } + } + + Jam_SetInterrupt(track, 7); + { // This resembles `JASIntrMgr::timerProcess` of later JAudio. + if (track->timer != 0) { + if (--track->timer == 0) { + Jam_SetInterrupt(track, 6); + if (track->timerCount != 0) { + if (--track->timerCount != 0) { + track->timer = track->maxTime; + } + } else { + track->timer = track->maxTime; + } + } + } + } - track->regParam.reg[r29_regIdx] = r30_newRegValue; - track->regParam.param.value = r28; +try_interrupt: + Jam_TryInterrupt(track); + if (track->isPaused && (track->pauseStatus & 2)) { + goto LAB_800136e0; + } + track->tickCounter++; + if (track->waitTimer == -1) { + if ((u8)CheckNoteStop(track, 0)) { // TODO: CheckNoteStop should return u8 or C++ bool + track->waitTimer = 0; + } else { + goto timed; + } + } + + if (track->waitTimer > 0) { + --track->waitTimer; + if (track->waitTimer != 0) { + goto timed; + } + if (track->_D0 != -1 && track->_D4 == 0) { + for (int index = 0; index < (int)track->_90; index++) { + track->_94[index] = 0xff; + track->channels[index] = NULL; + } + } + } + + while (TRUE) { + opcode = __ByteRead(track); + if (!(opcode & 0x80)) { + // MIDI pitch (0-127) + pitch = (u8)(opcode + track->finalTranspose); + + if ((bVar10 = __ByteRead(track)) & 0x80) { + u8 exchangedPitch = __ExchangeRegisterValue(track, pitch); + pitch = (u8)(exchangedPitch + track->finalTranspose); + } - if (r29_regIdx == 6) { - Osc_Clear_Overwrite(track); - } - if (r29_regIdx == 7) { - track->updateFlags |= OuterParamFlag_Pitch; - } - if (r29_regIdx == 0xd) { - track->parentController.channelPriority = track->regParam.param.basePriority | 0x10000; - track->parentController.releaseTime = 0; - } -} + if ((u8)pitch >= 128) { + OSReport("♪Jam/Seq :: Error Note %d\n", (u8)pitch); + } -/* - * --INFO-- - * Address: 800100A0 - * Size: 00016C - */ -u16 Jam_ReadRegDirect(seqp_* track, u8 regIdx) -{ - s16 result; - u16 regDirectLo; - u16 regDirectHi; - int i; + noteMode = bVar10; + noteMode &= 0x60; + noteMode >>= 5; + if (noteMode & 2) { + keyTarget = (u8)pitch; + pitch = *(s8*)((u8*)track + 0xD5) & 0xff; + } - switch (regIdx) { - case 0x20: - case 0x21: - result = track->regParam.param.bankNumber; - break; - case 0x22: - regDirectLo = Jam_ReadRegDirect(track, 1); - regDirectHi = Jam_ReadRegDirect(track, 0); - result = regDirectHi << 8 | regDirectLo; - break; - case 0x2C: - result = 0; - for (i = 15; i >= 0; --i) { - result = result << 1; // For some reason, `<<=` prevents `srawi`. - if (track->children[i] && track->children[i]->trackState) { - result |= 1; - } - } - break; - case 0x2D: - result = 0; - for (i = 7; i >= 0; --i) { - result = result << 1; // For some reason, `<<=` prevents `srawi`. - result |= (u8)CheckNoteStop(track, i); - } - break; - case 0x30: - if (track->callStackDepth == 0) { - result = 0; - } else { - result = track->loopCounters[track->callStackDepth - 1]; - } - break; - default: - result = track->regParam.reg[regIdx]; - break; - } - switch (regIdx) { - case 0x00: - case 0x01: - case 0x02: - case 0x21: - result = result & 0xff; - break; - case 0x20: - result = result >> 8; - break; - } - return result; -} + velocity = __ByteRead(track); + if (velocity >= 0x80) { + velocity = __ExchangeRegisterValue(track, velocity - 0x80); + } -/* - * --INFO-- - * Address: 80010220 - * Size: 000048 - */ -u32 Jam_ReadRegXY(seqp_* track) -{ - return (Jam_ReadRegDirect(track, 4) << 16) | Jam_ReadRegDirect(track, 5); -} + u32 lowBits = bVar10; + lowBits &= 7; + if (lowBits == 0) { + voice = 0; + bVar9 = __ByteRead(track); + if (bVar9 >= 0x80) { + bVar9 = __ExchangeRegisterValue(track, bVar9 - 0x80); + } + uVar2 = 0; + for (iVar11 = 0; iVar11 < (bVar10 >> 3 & 3); iVar11++) { + uVar2 = uVar2 << 8 | __ByteRead(track); + } + if ((u32)(bVar10 >> 3 & 3) == 1 && uVar2 >= 0x80) { + uVar2 = __ExchangeRegisterValue(track, uVar2 - 0x80); + } + } else { + voice = lowBits; + // fake volatile for matching + if (*(u8*)&bVar10 >> 3 & 3) { + voice = __ExchangeRegisterValue(track, voice - 1); + if (voice >= 8) { + break; + } + } + uVar2 = -1; + bVar9 = 100; + } -/* - * --INFO-- - * Address: 80010280 - * Size: 00005C - */ -u32 Jam_ReadReg32(seqp_* track, u8 index) -{ - switch (index) { - case 40: - case 41: - case 42: - case 43: - return track->regParam.param._20[index - 40]; - case 35: - return Jam_ReadRegXY(track); - } - return Jam_ReadRegDirect(track, index); -} + track->_D4 = noteMode; -/* - * --INFO-- - * Address: 800102E0 - * Size: 000048 - */ -void Jam_WriteRegXY(seqp_* track, u32 param_2) -{ - u16 v = param_2 >> 16; - Jam_WriteRegDirect(track, 4, (u16)v); - u16 v2 = param_2; - Jam_WriteRegDirect(track, 5, (u16)v2); -} + BOOL cond = track->_D6 ? TRUE : FALSE; + int voiceArg = voice; + var_r26 = FALSE; -/* - * --INFO-- - * Address: 80010340 - * Size: 00003C - * Note: Equivalent to `JASTrack::exchangeRegisterValue` in later JAudio. - */ -u32 __ExchangeRegisterValue(seqp_* track, u8 param_2) -{ - if (param_2 < 64) { - return Jam_ReadReg32(track, param_2); - } - return track->trackPort[param_2 - 64].value; -} + for (int j = 0; j < 1; j++) { + // u8* track_p = track->_94; + int unused = j * 2; + + if (cond) { + duration = uVar2; + if (track->_D4 & 1) { + duration = -1; + } + if (duration != -1) { + duration = Jam_SEQtimeToDSPtime(track, duration, bVar9); + } + if (track->isPaused && (track->pauseStatus & 0x10)) { + iVar11_2 = -1; + } else { + u32 gatePitch = pitch; + gatePitch &= 0xff; + iVar11_2 = GateON(track, voiceArg, gatePitch, velocity, duration); + } + } else { + if ((duration = uVar2) != -1) { + duration = Jam_SEQtimeToDSPtime(track, duration, bVar9); + } + if (track->_D4 & 1) { + duration = -1; + } + if (track->isPaused && (track->pauseStatus & 0x10)) { + iVar11_2 = -1; + } else { + u32 notePitch = pitch; + notePitch = (notePitch << 24) >> 24; + iVar11_2 = NoteON(track, voiceArg, notePitch, velocity, duration); + } + } + + if (iVar11_2 != -1) { + track->_94[voice + j] = pitch; + var_r26 = TRUE; + } + } -/* - * --INFO-- - * Address: ........ - * Size: 00004C - */ -void Jam_WritePortApp(void) -{ - // UNUSED FUNCTION -} + track->_90 = var_r26; + track->_CC = bVar9; + track->_CD = velocity; + track->_D0 = uVar2; -/* - * --INFO-- - * Address: ........ - * Size: 00004C - */ -void Jam_ReadPortApp(void) -{ - // UNUSED FUNCTION -} + if (track->_D4 & 1) { + track->_D6 = TRUE; + } else { + track->_D6 = FALSE; + } -/* - * --INFO-- - * Address: ........ - * Size: 000048 - */ -void Jam_CheckExportApp(void) -{ - // UNUSED FUNCTION -} + if (track->_D4 & 2) { + s32 steps = duration; + if (duration == -1) { + steps = Jam_SEQtimeToDSPtime(track, uVar2, track->_CC); + } + SetKeyTarget_1Shot(track->channels[0], (u8)keyTarget + track->finalTranspose, steps); + pitch = (u8)keyTarget; + } -/* - * --INFO-- - * Address: ........ - * Size: 000048 - */ -void Jam_CheckImportApp(void) -{ - // UNUSED FUNCTION -} + track->_D5 = pitch; -/* - * --INFO-- - * Address: ........ - * Size: 0000A0 - */ -void Jam_WritePortIndirect(void) -{ - // UNUSED FUNCTION -} + if (uVar2 != -1) { + track->waitTimer = uVar2; + if (uVar2 == 0) { + track->waitTimer = -1; + } + break; + } + } else if ((opcode & 0xf0) == 0x80 || opcode == 0xf9) { + iVar11_3 = 1; + uVar5 = 0; + if (opcode == 0xf9) { + bVar10_2 = __ByteRead(track); + uVar6 = __ExchangeRegisterValue(track, bVar10_2 & 7); + if (uVar6 > 7 || uVar6 == 0) { + OSReport("♪Jam/main :: r-noteoff error\n"); + if ((bVar10_2 & 0x80) != 0) { + __ByteRead(track); + } + continue; + } + opcode = uVar6 + 0x80; + if (bVar10_2 & 0x80) { + opcode += 8; + } + } + uVar6 = opcode & 0x0f; + if (uVar6 == 8) { + iVar11_3 = 2; + uVar6 -= 8; + } + if (uVar6 > 8) { + uVar6 -= 8; + uVar5 = __ByteRead(track); + if (uVar5 > 100) { + uVar5 = (uVar5 - 98) * 20; + } + } + if (uVar6 == 0) { + // This for loop init feels fake... but idk. Check this again later. + for (track->waitTimer = iVar12 = 0; iVar12 < iVar11_3; iVar12++) { + track->waitTimer = track->waitTimer << 8 | __ByteRead(track); + } + if (track->waitTimer == 0) { + continue; + } + break; + } + if (uVar5 == 0) { + NoteOFF(track, uVar6); + } else { + NoteOFF_R(track, uVar6, uVar5); + } + } else { + // This portion is equivalent to `JASSeqParser::parseSeq` in later JAudio. + u32 cmdResult = 0; + if ((opcode & 0xf0) == 0x90) { + Jam_WriteTimeParam(track, opcode & 0x0f); + } else if ((opcode & 0xf0) == 0xa0) { + Jam_WriteRegParam(track, opcode & 0x0f); + } else if ((opcode & 0xf0) == 0xb0) { + u32 param_3 = opcode & 7; + cmdResult = RegCmd_Process(track, (opcode & 8) ? TRUE : FALSE, param_3); + } else { + cmdResult = Cmd_Process(track, opcode, 0); + } -/* - * --INFO-- - * Address: ........ - * Size: 000058 - */ -void Jam_ReadPortIndirect(void) -{ - // UNUSED FUNCTION -} + if (cmdResult == 0) { + continue; + } else if (cmdResult == 1) { + break; + } else if (cmdResult == 2) { + goto try_interrupt; + } else if (cmdResult == 3) { + return -1; + } else if (cmdResult == 0x80) { + OSReport("\x1b[4%dm", 1); + OSReport("♪Jam/seq :: Sequence Error occerd... I try to continue\n"); + OSReport("\x1b[m"); + } + } + } -/* - * --INFO-- - * Address: ........ - * Size: 0000A4 - */ -void Jam_CheckPortIndirect(void) -{ - // UNUSED FUNCTION -} +timed: + // This portion is equivalent to `JASTrack::updateTimedParam` in later JAudio. + for (int i = 0; i < 18; i++) { + MoveParam_* move = &track->timedParam.move[i]; + if (move->duration > 0.0f) { + move->currentValue += move->stepSize; + move->duration -= 1.0f; + if (i <= 5 || i >= 11) { + seqRes |= (1 << i); + } else { + Osc_Update_Param(track, i, move->currentValue); + } + } + } -/* - * --INFO-- - * Address: 80010380 - * Size: 000078 - */ -BOOL Jam_WritePortAppDirect(seqp_* track, u32 param_2, u16 param_3) -{ - if (!track) { - return FALSE; - } - track->trackPort[param_2].value = param_3; - track->trackPort[param_2].importFlag = 1; - if (param_2 == 0) { - Jam_SetInterrupt(track, 3); - } - if (param_2 == 1) { - Jam_SetInterrupt(track, 4); - } - return TRUE; -} + if (track->oscillatorRouting[0] == 0x0E) { + seqRes |= osc_table[track->oscillators[0].mode]; + } + if (track->oscillatorRouting[1] == 0x0E) { + seqRes |= osc_table[track->oscillators[1].mode]; + } -/* - * --INFO-- - * Address: 80010400 - * Size: 000030 - */ -BOOL Jam_ReadPortAppDirect(seqp_* track, u32 param_2, u16* param_3) -{ - if (!track) { - return FALSE; - } - *param_3 = track->trackPort[param_2].value; - track->trackPort[param_2].exportFlag = 0; - return TRUE; -} +LAB_800136e0: + track->updateFlags |= seqRes; + + int childOffset; + int i; + i = 0; + childOffset = 0; + for (; i < 16; i++, childOffset += 4) { + if ((*(seqp_**)((u8*)track + 0x44 + childOffset)) && + (*(seqp_**)((u8*)track + 0x44 + childOffset))->trackState != 0) { + if (track != (*(seqp_**)((u8*)track + 0x44 + childOffset))->parent) { + OSReport("##########Error:: Track %d の共有違反です\n", i); + } + BOOL childIsMuted = track->isMuted | ((track->childMuteMask & (1 << i)) >> i); + if (Jam_SeqmainNote((*(seqp_**)((u8*)track + 0x44 + childOffset)), childIsMuted) == -1) { + Jaq_CloseTrack((*(seqp_**)((u8*)track + 0x44 + childOffset))); + (*(seqp_**)((u8*)track + 0x44 + childOffset)) = NULL; + } + } + } -/* - * --INFO-- - * Address: 80010440 - * Size: 00006C - */ -BOOL Jam_CheckPortAppDirect(seqp_* track, u32 param_2, u16 param_3) -{ - // Again with the cast to u8... what is it? - switch ((u8)param_3) { - case FALSE: - if (track->trackPort[param_2].exportFlag == FALSE) { - return FALSE; - } - return TRUE; - case TRUE: - if (track->trackPort[param_2].importFlag == TRUE) { - return FALSE; - } - return TRUE; - } - return FALSE; -} - -/* - * --INFO-- - * Address: ........ - * Size: 000018 - */ -void Jam_WritePort(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: ........ - * Size: 000018 - */ -void Jam_ReadPort(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: ........ - * Size: 000034 - */ -void Jam_WritePortChild(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: ........ - * Size: 000038 - */ -void Jam_WritePortBros(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: 800104C0 - * Size: 000030 - */ -void Jam_InitRegistTrack(void) -{ - int i; - - T_LISTS = 0; - for (i = 0; i < TRACK_LIST_SIZE; ++i) { - TRACK_LIST[i].track = NULL; - } -} - -/* - * --INFO-- - * Address: 80010500 - * Size: 0000A8 - */ -void Jam_RegistTrack(seqp_* track, u32 param_2) -{ - u32* REF_param_2; - size_t i; - - for (i = 0; i < T_LISTS; ++i) { - if (param_2 == TRACK_LIST[i].id) { - return; - } - } - if (T_LISTS == TRACK_LIST_SIZE) { - for (i = 0; i < TRACK_LIST_SIZE; ++i) { - if (!TRACK_LIST[i].track) { - break; - } - } - if (i == TRACK_LIST_SIZE) { - return; - } - } else { - i = T_LISTS; - ++T_LISTS; - } - REF_param_2 = ¶m_2; - TRACK_LIST[i].id = param_2; - TRACK_LIST[i].track = track; - track->isRegistered = 1; -} - -/* - * --INFO-- - * Address: 800105C0 - * Size: 00008C - */ -void Jam_UnRegistTrack(seqp_* track) -{ - size_t i; - - if (!track->isRegistered) { - return; - } - for (i = 0; i < T_LISTS; ++i) { - if (track == TRACK_LIST[i].track) { - TRACK_LIST[i].track = NULL; - } - } - track->isRegistered = FALSE; - for (; T_LISTS != 0; --T_LISTS) { - if (TRACK_LIST[T_LISTS - 1].track) { - break; - } - } -} - -/* - * --INFO-- - * Address: 80010660 - * Size: 000050 - */ -seqp_* Jam_GetTrackHandle(u32 param_1) -{ - size_t i; - - for (i = 0; i < T_LISTS; ++i) { - if (param_1 == TRACK_LIST[i].id && TRACK_LIST[i].track) { - return TRACK_LIST[i].track; - } - } - return NULL; -} - -/* - * --INFO-- - * Address: 800106C0 - * Size: 000018 - */ -void Jam_InitExtBuffer(OuterParam_* ext) -{ - ext->flags = 0; - ext->updateFlags = 0; - ext->isAssigned = FALSE; - ext->refCount = 0; -} - -/* - * --INFO-- - * Address: 800106E0 - * Size: 000038 - */ -BOOL Jam_AssignExtBuffer(seqp_* track, OuterParam_* ext) -{ - if (!track) { - return FALSE; - } - if (!ext) { - return FALSE; - } - track->outerParams = ext; - ++ext->refCount; - return TRUE; -} - -/* - * --INFO-- - * Address: 80010720 - * Size: 000060 - */ -BOOL Jam_AssignExtBufferP(seqp_* track, u8 index, OuterParam_* ext) -{ - if (!track) { - return FALSE; - } - if (!ext) { - return FALSE; - } - track->childOuterParams[index] = ext; - ext->isAssigned = TRUE; - Jam_AssignExtBuffer(track->children[index], ext); - return TRUE; -} - -/* - * --INFO-- - * Address: 80010780 - * Size: 000044 - */ -void Jam_SetExtFirFilterD(OuterParam_* ext, s16* param_2) -{ - int i; - - if (!ext) { - return; - } - ext->updateFlags |= OuterParamFlag_FIR8Filter; - ext->flags |= OuterParamFlag_FIR8Filter; - for (i = 0; i < 8; ++i) { - ext->firCoefficients[i] = param_2[i]; - } -} - -/* - * --INFO-- - * Address: 800107E0 - * Size: 0000A4 - */ -void Jam_SetExtParamD(f32 value, OuterParam_* ext, u8 updateFlags) -{ - f32* member; - - if (!ext) { - return; - } - - switch (updateFlags) { - case OuterParamFlag_Volume: - member = &ext->volume; - break; - case OuterParamFlag_Pitch: - member = &ext->pitch; - break; - case OuterParamFlag_Fxmix: - member = &ext->fxMix; - break; - case OuterParamFlag_Dolby: - member = &ext->dolby; - break; - case OuterParamFlag_Pan: - member = &ext->pan; - break; - case OuterParamFlag_Tempo: - member = &ext->tempo; - break; - default: - return; - } - - *member = value; - ext->updateFlags |= updateFlags; -} - -/* - * --INFO-- - * Address: 800108A0 - * Size: 000024 - */ -void Jam_OnExtSwitchD(OuterParam_* ext, u16 param_2) -{ - if (!ext) { - return; - } - ext->flags |= param_2; - ext->updateFlags |= param_2; -} - -/* - * --INFO-- - * Address: 800108E0 - * Size: 000028 - */ -void Jam_OffExtSwitchD(OuterParam_* ext, u16 param_2) -{ - if (!ext) { - return; - } - ext->flags ^= ext->flags & param_2; - ext->updateFlags |= param_2; -} - -/* - * --INFO-- - * Address: ........ - * Size: 00001C - */ -void Jam_SetExtSwitchDirectD(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: ........ - * Size: 00002C - */ -void Jam_SetExtFirFilter(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: 80010920 - * Size: 00002C - */ -void Jam_SetExtParam(f32 param_1, seqp_* track, u8 param_3) -{ - if (!track) { - return; - } - Jam_SetExtParamD(param_1, track->outerParams, param_3); -} - -/* - * --INFO-- - * Address: 80010960 - * Size: 00002C - */ -void Jam_OnExtSwitch(seqp_* track, u16 param_2) -{ - if (!track) { - return; - } - Jam_OnExtSwitchD(track->outerParams, param_2); -} - -/* - * --INFO-- - * Address: 800109A0 - * Size: 00002C - */ -void Jam_OffExtSwitch(seqp_* track, u16 param_2) -{ - if (!track) { - return; - } - Jam_OffExtSwitchD(track->outerParams, param_2); -} - -/* - * --INFO-- - * Address: ........ - * Size: 00002C - */ -void Jam_SetExtSwitchDirect(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: ........ - * Size: 00003C - */ -void Jam_SetExtFirFilterP(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: 800109E0 - * Size: 000038 - */ -void Jam_SetExtParamP(f32 param_1, seqp_* track, u8 index, u8 param_4) -{ - if (!track) { - return; - } - Jam_SetExtParamD(param_1, track->childOuterParams[index], param_4); -} - -/* - * --INFO-- - * Address: 80010A20 - * Size: 00003C - */ -void Jam_OnExtSwitchP(seqp_* track, u8 index, u16 param_3) -{ - if (!track) { - return; - } - Jam_OnExtSwitchD(track->childOuterParams[index], param_3); -} - -/* - * --INFO-- - * Address: ........ - * Size: 00003C - */ -void Jam_OffExtSwitchP(seqp_* track, u8 index, u16 param_3) -{ - if (!track) { - return; - } - Jam_OffExtSwitchD(track->childOuterParams[index], param_3); -} - -/* - * --INFO-- - * Address: ........ - * Size: 00003C - */ -void Jam_SetExtSwitchDirectP(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: ........ - * Size: 00002C - */ -void Jam_CheckRunningCounter(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: 80010A60 - * Size: 00000C - */ -BOOL Jam_RegisterTrackCallback(TrackCallback callback) -{ - JAM_CALLBACK_FUNC = callback; - return TRUE; -} - -/* - * --INFO-- - * Address: ........ - * Size: 000038 - */ -void Jam_SetTrackExtPanPower(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: 80010A80 - * Size: 00004C - */ -static f32 __PanCalc(f32 param_1, f32 param_2, f32 param_3, u8 param_4) -{ - f32 result; - - switch (param_4) { - case 0: - return param_1; - case 1: - return param_2; - case 2: - result = param_1 * (1.0f - param_3) + (param_2 * param_3); - } - return result; -} - -/* - * --INFO-- - * Address: 80010AE0 - * Size: 000320 - */ -void Jam_UpdateTrackAll(seqp_* track) -{ - f32 volumeValue; - f32 pitchCents; - f32 panValue; - f32 fxMixValue; - f32 dolbyValue; - f32 distance; - f32 parentDistance; - - f32 panScaled; - s8 pan8bit; - s8 panDelayLeft; - - size_t i; - - distance = track->regParam.param.arguments[3] / 32767.0f; - if (track->flags != 4) { - track->parentController.channelPriority = track->regParam.param.basePriority | 0x10000; - track->parentController.releaseTime = 0; - - panDelayLeft = 0; - panScaled = track->timedParam.inner._110.currentValue * 128.0f; - - OSf32tos8(&panScaled, &pan8bit); - if (pan8bit < 0) { - panDelayLeft = -pan8bit; - pan8bit = 0; - } - - track->parentController.maxDelay = 0x10; - track->parentController.masterLevels[0] = panDelayLeft; - track->parentController.masterLevels[1] = pan8bit; - - // Read base volume; if muted, force to zero - volumeValue = track->timedParam.inner.volume.currentValue; - if (track->isMuted > 0) { - volumeValue = 0.0f; - } - - // Convert pitch to cents, read pan/fxmix/dolby from timed parameters - pitchCents = Jam_PitchToCent(track->timedParam.inner.pitch.currentValue, track->regParam.param.pitchScale); - panValue = track->timedParam.inner.pan.currentValue; - fxMixValue = track->timedParam.inner.fxmix.currentValue; - dolbyValue = track->timedParam.inner.dolby.currentValue; - - if (track->outerParams) { - if (track->outerParams->flags & OuterParamFlag_Volume) { - volumeValue = volumeValue * track->outerParams->volume; - } - - if (track->outerParams->flags & OuterParamFlag_Pitch) { - pitchCents = pitchCents * track->outerParams->pitch; - } - - if (track->outerParams->flags & OuterParamFlag_Fxmix) { - fxMixValue = __PanCalc(fxMixValue, track->outerParams->fxMix, distance, track->panCalcTypes[1]); - } - - if (track->outerParams->flags & OuterParamFlag_Dolby) { - dolbyValue = __PanCalc(dolbyValue, track->outerParams->dolby, distance, track->panCalcTypes[2]); - } - - if (track->outerParams->flags & OuterParamFlag_Pan) { - panValue = __PanCalc(panValue, track->outerParams->pan, distance, track->panCalcTypes[0]); - } - } - - // If there is no parent or this track overrides its parent (trackFlags & 1), - // write the final values directly into the channel state - if (!track->parent || (track->flags & 1)) { - track->parentController.volume = volumeValue; - track->parentController.pitch = pitchCents; - track->parentController.pan = panValue; - track->parentController.fxmix = fxMixValue; - track->parentController.dolby = dolbyValue; - } else { - // Otherwise, combine with parent’s values using a second attenuation factor - parentDistance = track->regParam.param.arguments[4] / 32767.0f; - - track->parentController.volume = track->parent->parentController.volume * volumeValue; - track->parentController.pitch = track->parent->parentController.pitch * pitchCents; - track->parentController.pan - = __PanCalc(panValue, track->parent->parentController.pan, parentDistance, track->parentPanCalcTypes[0]); - track->parentController.fxmix - = __PanCalc(fxMixValue, track->parent->parentController.fxmix, parentDistance, track->parentPanCalcTypes[1]); - track->parentController.dolby - = __PanCalc(dolbyValue, track->parent->parentController.dolby, parentDistance, track->parentPanCalcTypes[2]); - - // If outerParams specify a custom FIR filter, copy those coefficients - if (track->outerParams && (track->outerParams->flags & OuterParamFlag_FIR8Filter)) { - for (i = 0; i < 8; ++i) { - track->parentController.firCoefficients[i] = track->outerParams->firCoefficients[i]; - } - - track->parentController.filterMode = 8; - } - - // Read inner IIR coefficients (normalized floats) and convert to 16-bit - for (i = 0; i < 4; ++i) { - track->parentController.iirCoefficients[i] = track->timedParam.inner.IIRs[i].currentValue * 32767.0f; - } - - track->parentController.filterMode |= 0x20; - track->parentController.distFilter = track->timedParam.inner.distFilter.currentValue * 32767.0f; - } - } -} - -#define OS_FASTCAST_S8 (4) - -/* - * --INFO-- - * Address: 80010E00 - * Size: 00000C - */ -static void OSf32tos8(register f32* in, volatile register s8* out) -{ - *out = __OSf32tos8(*in); -} - -/* - * --INFO-- - * Address: 80010E20 - * Size: 0004A8 - */ -void Jam_UpdateTrack(seqp_* track, u32 updateFlags) -{ - // A bizarre way the devs attempted to re-use some repeated AND operations in this function, - // which the compiler can already see and optimize in its own way, causes regalloc inflation. - u32 updateVolumeFlag; - u32 updatePitchFlag; - u32 updatePanFlag; - u32 updateFxMixFlag; - u32 updateDolbyFlag; - - f32 computedVolume; // f31 - f32 unaff_f30; // f30 - f32 unaff_f29; // f29 - f32 unaff_f28; // f28 - f32 unaff_f27; // f27 - f32 regionAttenuation; - f32 offset; - f32 dVar15_3; - - size_t i; - - // Used for `OSf32tos8` - f32 masterLevelF32; - s8 masterRight; - s8 masterLeft; - - regionAttenuation = track->regParam.param.arguments[3] / 32767.0f; - - if (track->flags != 0x04) { - - // Update master pan delay levels if requested - if (updateFlags & SEQTRACK_FLAG_MASTER_LEVEL) { - masterLeft = 0; - masterLevelF32 = track->timedParam.inner._110.currentValue * 128.0f; - OSf32tos8(&masterLevelF32, &masterRight); - if (masterRight < 0) { - masterLeft = -masterRight; - masterRight = 0; - } - track->parentController.masterLevels[0] = masterLeft; - track->parentController.masterLevels[1] = masterRight; - } - - // Tempo update (only if top-level track) - if (updateFlags & OuterParamFlag_Tempo && !track->parent) { - Jam_UpdateTempo(track); - } - - updateVolumeFlag = updateFlags & OuterParamFlag_Volume; - if (updateVolumeFlag) { - computedVolume = track->timedParam.inner.volume.currentValue; - if (track->isMuted != 0) { - computedVolume = 0.0f; - } - - if (track->outerParams && (track->outerParams->flags & OuterParamFlag_Volume)) { - computedVolume *= track->outerParams->volume; - } - - if (track->isPaused && (track->pauseStatus & 1)) { - computedVolume *= track->timedParam.inner._100.currentValue; - } - } - - updatePitchFlag = updateFlags & OuterParamFlag_Pitch; - if (updatePitchFlag) { - unaff_f30 = Jam_PitchToCent((track->timedParam).inner.pitch.currentValue, track->regParam.param.pitchScale); - if (track->outerParams && ((track->outerParams->flags & OuterParamFlag_Pitch) != 0)) { - unaff_f30 = (unaff_f30 * track->outerParams->pitch); - } - } - - updatePanFlag = updateFlags & OuterParamFlag_Pan; - if (updatePanFlag) { - unaff_f29 = (track->timedParam).inner.pan.currentValue; - if (track->outerParams && ((track->outerParams->flags & OuterParamFlag_Pan) != 0)) { - unaff_f29 = __PanCalc(unaff_f29, track->outerParams->pan, regionAttenuation, track->panCalcTypes[0]); - } - } - - updateFxMixFlag = updateFlags & OuterParamFlag_Fxmix; - if (updateFxMixFlag) { - unaff_f28 = (track->timedParam).inner.fxmix.currentValue; - if (track->outerParams && ((track->outerParams->flags & OuterParamFlag_Fxmix) != 0)) { - unaff_f28 = __PanCalc(unaff_f28, track->outerParams->fxMix, regionAttenuation, track->panCalcTypes[1]); - } - } - - updateDolbyFlag = updateFlags & OuterParamFlag_Dolby; - if (updateDolbyFlag) { - unaff_f27 = (track->timedParam).inner.dolby.currentValue; - if (track->outerParams && ((track->outerParams->flags & OuterParamFlag_Dolby) != 0)) { - unaff_f27 = __PanCalc(unaff_f27, track->outerParams->dolby, regionAttenuation, track->panCalcTypes[2]); - } - } - - // IIR flag is set - if (updateFlags & OuterParamFlag_IIRFilter) { - for (i = 0; i < 4; ++i) { - track->parentController.iirCoefficients[i] = track->timedParam.inner.IIRs[i].currentValue * 32767.0f; - } - - track->parentController.filterMode |= 0x20; - } - - if (track->outerParams) { - if (updateFlags & OuterParamFlag_FIR8Filter && (track->outerParams->flags & OuterParamFlag_FIR8Filter)) { - for (i = 0; i < 8; ++i) { - track->parentController.firCoefficients[i] = track->outerParams->firCoefficients[i]; - } - - track->parentController.filterMode = (track->parentController.filterMode & 0x20) + 8; - } - } - - if (updateFlags & OuterParamFlag_DistFilt) { - track->parentController.distFilter = track->timedParam.inner.distFilter.currentValue * 32767.0f; - } - - for (i = 0; i < 2; ++i) { - if (track->oscillatorRouting[i] == 0x0E) { - offset = Bank_OscToOfs(&track->oscillators[i], &track->oscillatorParams[i]); - switch (track->oscillators[i].mode) { - case 1: - unaff_f30 = unaff_f30 * offset; - break; - case 0: - computedVolume = computedVolume * offset; - break; - case 2: - unaff_f29 = unaff_f29 * offset; - break; - case 3: - unaff_f28 = unaff_f28 * offset; - break; - case 4: - unaff_f27 = unaff_f27 * offset; - break; - } - } - } - if (!track->parent || ((track->flags & 1) != 0)) { - if (updateVolumeFlag) { - track->parentController.volume = computedVolume; - } - if (updatePitchFlag) { - track->parentController.pitch = unaff_f30; - } - if (updatePanFlag) { - track->parentController.pan = unaff_f29; - } - if (updateFxMixFlag) { - track->parentController.fxmix = unaff_f28; - } - if (updateDolbyFlag != 0) { - track->parentController.dolby = unaff_f27; - } - } else { - dVar15_3 = track->regParam.param.arguments[4] / 32767.0f; - if (updateVolumeFlag) { - track->parentController.volume = track->parent->parentController.volume * computedVolume; - } - if (updatePitchFlag) { - track->parentController.pitch = track->parent->parentController.pitch * unaff_f30; - } - if (updatePanFlag) { - track->parentController.pan - = __PanCalc(unaff_f29, track->parent->parentController.pan, dVar15_3, track->parentPanCalcTypes[0]); - } - if (updateFxMixFlag) { - track->parentController.fxmix - = __PanCalc(unaff_f28, track->parent->parentController.fxmix, dVar15_3, track->parentPanCalcTypes[1]); - } - if (updateDolbyFlag) { - track->parentController.dolby - = __PanCalc(unaff_f27, track->parent->parentController.dolby, dVar15_3, track->parentPanCalcTypes[2]); - } - } - } -} - -/* - * --INFO-- - * Address: 800112E0 - * Size: 000104 - */ -void Jam_UpdateTempo(seqp_* track) -{ - size_t i; - - size_t* REF_i; - - if (!track->parent) { - track->tempoFactor = (float)track->timeBase * (float)track->tempo / (JAC_DAC_RATE * 60.0f / 80.0f); - if ((track->outerParams->flags & OuterParamFlag_Tempo) != 0) { - track->tempoFactor = track->tempoFactor * track->outerParams->tempo; - } - } else { - track->tempoFactor = track->parent->tempoFactor; - track->timeBase = track->parent->timeBase; - } - for (i = 0; i < 16; ++i) { - REF_i = &i; - if (track->children[i] && track->children[i]->trackState) { - Jam_UpdateTempo(track->children[i]); - } - } -} - -/* - * --INFO-- - * Address: 80011400 - * Size: 0000CC - */ -void Jam_MuteTrack(seqp_* track, u8 param_2) -{ - u32 i; - u16 mask; - - if (track->parent) { - track->isMuted = track->parent->isMuted | param_2; - mask = 1 << (track->trackId & 0xf); - if (!param_2) { - track->parent->childMuteMask &= ~mask; - } else { - track->parent->childMuteMask |= mask; - } - } else { - track->isMuted = param_2; - } - track->updateFlags |= OuterParamFlag_Volume; - if (track->isMuted && (track->pauseStatus & 0x20)) { - for (i = 0; i < 8; ++i) { - NoteOFF_R(track, (u8)i, 10); - }; - } -} - -/* - * --INFO-- - * Address: ........ - * Size: 0000B4 - */ -void Jam_MuteChildTracks(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: 800114E0 - * Size: 00013C - */ -void Jam_PauseTrack(seqp_* track, u8 param_2) -{ - size_t i; - jc_* pjVar1; - - size_t* REF_i; - - track->isPaused = TRUE; - if (track->pauseStatus & 0x01) { - track->updateFlags |= OuterParamFlag_Volume; - } - if (track->pauseStatus & 0x04) { - for (i = 0; i < 8; ++i) { - REF_i = &i; - NoteOFF_R(track, i, 10); - } - } - if (track->pauseStatus & 0x08) { - for (i = 0; i < 8; ++i) { - pjVar1 = track->channels[i]; - if (pjVar1 && track->activeSoundIds[i] == pjVar1->channelId) { - UpdatePause_1Shot(pjVar1, 1); - } - } - } - Jam_SetInterrupt(track, 0); - if (param_2 == TRUE) { - for (i = 0; i < 16; ++i) { - if (track->children[i] && track->children[i]->trackState) { - Jam_PauseTrack(track->children[i], 1); - } - } - } -} - -/* - * --INFO-- - * Address: 80011620 - * Size: 0000EC - */ -void Jam_UnPauseTrack(seqp_* track, u8 param_2) -{ - size_t i; - jc_* pjVar1; - - size_t* REF_i; - - track->isPaused = FALSE; - track->updateFlags |= OuterParamFlag_Volume; - for (i = 0; i < 8; ++i) { - REF_i = &i; - pjVar1 = track->channels[i]; - if (pjVar1 && track->activeSoundIds[i] == pjVar1->channelId) { - UpdatePause_1Shot(pjVar1, 0); - } - } - Jam_SetInterrupt(track, 1); - if (param_2 == TRUE) { - for (i = 0; i < 16; ++i) { - if (track->children[i] && track->children[i]->trackState) { - Jam_UnPauseTrack(track->children[i], 1); - } - } - } -} - -/* - * --INFO-- - * Address: 80011720 - * Size: 000028 - * Note: Equivalent to `JASIntrMgr::request` in later JAudio. - */ -void Jam_SetInterrupt(seqp_* track, u16 interrupt) -{ - if (track->interruptEnable & (1 << interrupt)) { - track->interruptPending |= (1 << interrupt); - } -} - -/* - * --INFO-- - * Address: 80011760 - * Size: 000090 - */ -BOOL Jam_TryInterrupt(seqp_* track) -{ - u32 mask; - int i; - - if (track->interruptActive) { - return FALSE; - } - for (i = 0; i < 8; ++i) { - mask = 1 << i; - if ((track->interruptEnable & mask) && (track->interruptPending & mask)) { - track->savedProgramCounter = track->programCounter; - track->programCounter = track->interruptAddresses[i]; - track->interruptActive = mask; - track->_3CC = track->waitTimer; - track->waitTimer = 0; - track->interruptPending ^= mask; - return TRUE; - } - } - return FALSE; -} - -/* - * --INFO-- - * Address: 80011800 - * Size: 000038 - */ -static u32 Cmd_OpenTrack() -{ - Jaq_OpenTrack(SEQ_P, SEQ_ARG[0], SEQ_ARG[1]); - return 0; -} - -/* - * --INFO-- - * Address: 80011840 - * Size: 000050 - */ -static u32 Cmd_OpenTrackBros() -{ - if (SEQ_P->parent) { - Jaq_OpenTrack(SEQ_P->parent, SEQ_ARG[0], SEQ_ARG[1]); - } else { - return 0x40; - } - return 0; -} - -/* - * --INFO-- - * Address: 800118A0 - * Size: 00003C - */ -static u32 Cmd_Call() -{ - SEQ_P->callStack[SEQ_P->callStackDepth++] = SEQ_P->programCounter; - SEQ_P->programCounter = SEQ_ARG[0]; - return 0; -} - -/* - * --INFO-- - * Address: 800118E0 - * Size: 000100 - */ -static u32 Cmd_CallF() -{ - u8 bVar1; - u32 uVar2; - u32 uVar3; - u8 uVar4; - - bVar1 = __ByteRead(SEQ_P); - if (bVar1 & 0x80) { - uVar4 = __ByteRead(SEQ_P); - uVar2 = Jam_ReadRegDirect(SEQ_P, uVar4); - if (bVar1 & 0x40) { - if (bVar1 & 0x20) { - uVar4 = __ByteRead(SEQ_P); - uVar3 = Jam_ReadRegDirect(SEQ_P, uVar4); - } else { - uVar3 = __24Read(SEQ_P); - } - uVar2 = __24ReadOfs(SEQ_P, uVar3 + uVar2 * 3); - } - } else { - uVar2 = __24Read(SEQ_P); - } - if ((u8)__ConditionCheck(SEQ_P, bVar1 & 0x0f) == TRUE) { - if (SEQ_CMD == (0xC0 + CMD_CALL_F)) { - SEQ_P->callStack[SEQ_P->callStackDepth++] = SEQ_P->programCounter; - } - SEQ_P->programCounter = uVar2; - } - return 0; -} - -/* - * --INFO-- - * Address: 800119E0 - * Size: 000028 - */ -static u32 Cmd_Ret() -{ - SEQ_P->programCounter = SEQ_P->callStack[--SEQ_P->callStackDepth]; - return 0; -} - -/* - * --INFO-- - * Address: 80011A20 - * Size: 000060 - */ -static u32 Cmd_RetF() -{ - // But why cast it...? And why check if it explicitly equals TRUE...? - if ((u8)__ConditionCheck(SEQ_P, SEQ_ARG[0] & 0x0f) == TRUE) { - SEQ_P->programCounter = SEQ_P->callStack[--SEQ_P->callStackDepth]; - } - return 0; -} - -/* - * --INFO-- - * Address: 80011A80 - * Size: 00001C - */ -static u32 Cmd_Jmp() -{ - SEQ_P->programCounter = SEQ_ARG[1]; - return 0; -} - -/* - * --INFO-- - * Address: 80011AA0 - * Size: 000020 - */ -static u32 Cmd_JmpF() -{ - Cmd_CallF(); -} - -/* - * --INFO-- - * Address: 80011AC0 - * Size: 000048 - */ -static u32 Cmd_LoopS() -{ - SEQ_P->callStack[SEQ_P->callStackDepth] = SEQ_P->programCounter; - SEQ_P->loopCounters[SEQ_P->callStackDepth++] = SEQ_ARG[0]; - return 0; -} - -/* - * --INFO-- - * Address: 80011B20 - * Size: 000078 - */ -static u32 Cmd_LoopE() -{ - u16 uVar1; - - if (SEQ_P->callStackDepth == 0) { - return 0x80; - } - - uVar1 = SEQ_P->loopCounters[SEQ_P->callStackDepth - 1]; - if (uVar1 != 0) { - uVar1 = (u16)(uVar1 - 1); - } - - if (uVar1 == 0) { - SEQ_P->callStackDepth -= 1; - return 0; - } - - SEQ_P->loopCounters[SEQ_P->callStackDepth - 1] = uVar1; - SEQ_P->programCounter = SEQ_P->callStack[SEQ_P->callStackDepth - 1]; - return 0; -} - -/* - * --INFO-- - * Address: 80011BA0 - * Size: 000054 - */ -static u32 Cmd_ReadPort() -{ - u16 temp; - - temp = SEQ_P->trackPort[SEQ_ARG[0]].value; - SEQ_P->trackPort[SEQ_ARG[0]].importFlag = 0; - Jam_WriteRegDirect(SEQ_P, SEQ_ARG[1], temp); - return 0; -} - -/* - * --INFO-- - * Address: 80011C00 - * Size: 000040 - */ -static u32 Cmd_WritePort() -{ - SEQ_P->trackPort[SEQ_ARG[0]].value = SEQ_ARG[1]; - SEQ_P->trackPort[SEQ_ARG[0]].exportFlag = 1; - return 0; -} - -/* - * --INFO-- - * Address: 80011C40 - * Size: 000044 - */ -static u32 Cmd_CheckPortImport() -{ - Jam_WriteRegDirect(SEQ_P, 3, SEQ_P->trackPort[SEQ_ARG[0]].importFlag); - return 0; -} - -/* - * --INFO-- - * Address: 80011CA0 - * Size: 000044 - */ -static u32 Cmd_CheckPortExport() -{ - Jam_WriteRegDirect(SEQ_P, 3, SEQ_P->trackPort[SEQ_ARG[0]].exportFlag); - return 0; -} - -/* - * --INFO-- - * Address: 80011D00 - * Size: 00002C - */ -static u32 Cmd_WaitReg() -{ - SEQ_P->waitTimer = SEQ_ARG[0]; - return SEQ_ARG[0] ? 1 : 0; -} - -/* - * --INFO-- - * Address: 80011D40 - * Size: 000028 - */ -static u32 Cmd_ConnectName() -{ - SEQ_P->connectionId = SEQ_ARG[0] << 16 | SEQ_ARG[1]; - return 0; -} - -/* - * --INFO-- - * Address: 80011D80 - * Size: 000040 - */ -static u32 Cmd_ParentWritePort() -{ - Jam_WritePortAppDirect(SEQ_P->parent, SEQ_ARG[0] & 0x0f, SEQ_ARG[1]); - return 0; -} - -/* - * --INFO-- - * Address: 80011DC0 - * Size: 000048 - */ -static u32 Cmd_ChildWritePort() -{ - Jam_WritePortAppDirect(SEQ_P->children[(SEQ_ARG[0] >> 4)], SEQ_ARG[0] & 0x0f, SEQ_ARG[1]); - return 0; -} - -/* - * --INFO-- - * Address: 80011E20 - * Size: 000030 - */ -static u32 Cmd_SetLastNote() -{ - SEQ_P->_D5 = SEQ_ARG[0]; - SEQ_P->_D5 += SEQ_P->finalTranspose; - return 0; -} - -/* - * --INFO-- - * Address: 80011E60 - * Size: 00001C - */ -static u32 Cmd_TimeRelate() -{ - SEQ_P->timeRelationMode = SEQ_ARG[0]; - return 0; -} - -/* - * --INFO-- - * Address: 80011E80 - * Size: 000034 - */ -static u32 Cmd_SimpleOsc() -{ - Osc_Setup_Simple(SEQ_P, SEQ_ARG[0]); - return 0; -} - -/* - * --INFO-- - * Address: 80011EC0 - * Size: 000038 - */ -static u32 Cmd_SimpleEnv() -{ - Osc_Setup_SimpleEnv(SEQ_P, SEQ_ARG[0], SEQ_ARG[1]); - return 0; -} - -/* - * --INFO-- - * Address: 80011F00 - * Size: 000064 - */ -static u32 Cmd_SimpleADSR() -{ - int i; - s16 local_10[5]; - - for (i = 0; i < 5; ++i) { - local_10[i] = SEQ_ARG[i]; - } - Osc_Setup_ADSR(SEQ_P, local_10); - return 0; -} - -/* - * --INFO-- - * Address: 80011F80 - * Size: 000048 - */ -static u32 Cmd_Transpose() -{ - SEQ_P->transpose = SEQ_ARG[0]; - if (SEQ_P->parent) { - SEQ_P->finalTranspose = SEQ_P->parent->transpose + SEQ_P->transpose; - } else { - SEQ_P->finalTranspose = SEQ_P->transpose; - } - return 0; -} - -/* - * --INFO-- - * Address: 80011FE0 - * Size: 000068 - */ -static u32 Cmd_CloseTrack() -{ - u8 index = SEQ_ARG[0]; - if (index >= (u32)ARRAY_COUNT(SEQ_P->children)) { - return 0x80; - } - Jaq_CloseTrack(SEQ_P->children[index]); - SEQ_P->children[index] = NULL; - return 0; -} - -/* - * --INFO-- - * Address: 80012060 - * Size: 000038 - */ -static u32 Cmd_OutSwitch() -{ - if (SEQ_P->outerParams) { - SEQ_P->outerParams->flags = SEQ_ARG[0]; - SEQ_P->outerParams->updateFlags = -1; - } - - return 0; -} - -/* - * --INFO-- - * Address: 800120A0 - * Size: 000034 - */ -static u32 Cmd_UpdateSync() -{ - Jam_UpdateTrack(SEQ_P, SEQ_ARG[0]); - return 0; -} - -/* - * --INFO-- - * Address: 800120E0 - * Size: 00002C - */ -static u32 Cmd_BusConnect() -{ - if (SEQ_ARG[0] < 6) { - SEQ_P->parentController.busConnect[SEQ_ARG[0]] = SEQ_ARG[1]; - } - return 0; -} - -/* - * --INFO-- - * Address: 80012120 - * Size: 00001C - */ -static u32 Cmd_PauseStatus() -{ - SEQ_P->pauseStatus = SEQ_ARG[0]; - return 0; -} - -/* - * --INFO-- - * Address: 80012140 - * Size: 000044 - */ -static u32 Cmd_SetInterrupt() -{ - SEQ_P->interruptEnable |= (1 << SEQ_ARG[0]); - SEQ_P->interruptAddresses[SEQ_ARG[0]] = SEQ_ARG[1]; - return 0; -} - -/* - * --INFO-- - * Address: 800121A0 - * Size: 000030 - */ -static u32 Cmd_DisInterrupt() -{ - u8 arg; - arg = SEQ_ARG[0]; - arg = 1 << arg; - arg = ~arg; - SEQ_P->interruptEnable &= arg; - return 0; -} - -/* - * --INFO-- - * Address: 800121E0 - * Size: 000014 - */ -static u32 Cmd_ClrI() -{ - SEQ_P->interruptActive = 0; - return 0; -} - -/* - * --INFO-- - * Address: 80012200 - * Size: 000014 - */ -static u32 Cmd_SetI() -{ - SEQ_P->interruptActive = 1; - return 0; -} - -/* - * --INFO-- - * Address: 80012220 - * Size: 00002C - */ -static u32 Cmd_RetI() -{ - SEQ_P->waitTimer = SEQ_P->_3CC; - SEQ_P->interruptActive = 0; - SEQ_P->programCounter = SEQ_P->savedProgramCounter; - return 2; -} - -/* - * --INFO-- - * Address: 80012260 - * Size: 000034 - */ -static u32 Cmd_IntTimer() -{ - SEQ_P->timerCount = SEQ_ARG[0]; - SEQ_P->timer = SEQ_ARG[1]; - SEQ_P->maxTime = SEQ_ARG[1]; - return 0; -} - -/* - * --INFO-- - * Address: 800122A0 - * Size: 00002C - */ -static u32 Cmd_ConnectOpen() -{ - Jam_RegistTrack(SEQ_P, SEQ_P->connectionId); - return 0; -} - -/* - * --INFO-- - * Address: 800122E0 - * Size: 000028 - */ -static u32 Cmd_ConnectClose() -{ - Jam_UnRegistTrack(SEQ_P); - return 0; -} - -/* - * --INFO-- - * Address: 80012320 - * Size: 000060 - */ -static u32 Cmd_SyncCPU() -{ - u16 seq_arg; - u16 param_3; - - seq_arg = SEQ_ARG[0]; - if (JAM_CALLBACK_FUNC) { - param_3 = JAM_CALLBACK_FUNC(SEQ_P, seq_arg); - } else { - param_3 = 0xffff; - } - Jam_WriteRegDirect(SEQ_P, 3, param_3); - return 0; -} - -/* - * --INFO-- - * Address: 80012380 - * Size: 000038 - */ -static u32 Cmd_FlushAll() -{ - AllStop_1Shot(&SEQ_P->parentController); - FlushRelease_1Shot(&SEQ_P->parentController); - return 0; -} - -/* - * --INFO-- - * Address: 800123C0 - * Size: 00002C - */ -static u32 Cmd_FlushRelease() -{ - FlushRelease_1Shot(&SEQ_P->parentController); - return 0; -} - -/* - * --INFO-- - * Address: 80012400 - * Size: 00002C - */ -static u32 Cmd_Wait3() -{ - SEQ_P->waitTimer = SEQ_ARG[0]; - return SEQ_ARG[0] ? 1 : 0; -} - -/* - * --INFO-- - * Address: 80012440 - * Size: 000044 - */ -static u32 Cmd_TimeBase() -{ - SEQ_P->timeBase = SEQ_ARG[0]; - if (!SEQ_P->parent) { - Jam_UpdateTempo(SEQ_P); - } - return 0; -} - -/* - * --INFO-- - * Address: 800124A0 - * Size: 000050 - */ -static u32 Cmd_Tempo() -{ - SEQ_P->tempo = SEQ_ARG[0]; - if (!SEQ_P->parent) { - Jam_UpdateTempo(SEQ_P); - } else { - SEQ_P->doChangeTempo = TRUE; - } - return 0; -} - -/* - * --INFO-- - * Address: 80012500 - * Size: 0000CC - */ -static u32 Cmd_Finish() -{ - size_t i; - u32 updateFlags; - MoveParam_* temp; - - updateFlags = 0; - for (i = 0; i < 18; ++i) { - temp = &SEQ_P->timedParam.move[i]; - if (temp->duration > 0.0f) { - temp->currentValue += temp->stepSize; - temp->duration -= 1.0f; - if (i <= 5 || i >= 11) { - updateFlags |= 1 << i; - } else { - Osc_Update_Param(SEQ_P, i, temp->currentValue); - } - } - } - SeqUpdate(SEQ_P, updateFlags); - - return 3; -} - -/* - * --INFO-- - * Address: 800125E0 - * Size: 000008 - */ -static u32 Cmd_Nop() -{ - return 0; -} - -/* - * --INFO-- - * Address: 80012600 - * Size: 0000AC - */ -static u32 Cmd_PanPowSet() -{ - size_t i; - - for (i = 0; i < 3; ++i) { - SEQ_P->regParam.param.arguments[i] = SEQ_ARG[i]; - } - for (i = 3; i < 5; ++i) { - SEQ_P->regParam.param.arguments[i] = SEQ_ARG[i] * 327.67f; - } - - return 0; -} - -/* - * --INFO-- - * Address: 800126C0 - * Size: 000094 - */ -static u32 Cmd_IIRSet() -{ - - size_t i; - MoveParam_* iir; - - for (i = 0; i < 4; ++i) { - iir = &SEQ_P->timedParam.move[i + 12]; // IIRs 0 - 4 are at 12-15 - iir->targetValue = (s16)SEQ_ARG[i] / 32768.0f; - iir->currentValue = iir->targetValue; - iir->stepSize = 0.0f; - iir->duration = 1.0f; - } - - return 0; -} - -/* - * --INFO-- - * Address: 80012760 - * Size: 000044 - */ -static u32 Cmd_FIRSet() -{ - Jam_SetExtFirFilterD(SEQ_P->outerParams, (s16*)Jam_OfsToAddr(SEQ_P, SEQ_ARG[0])); - return 0; -} - -/* - * --INFO-- - * Address: 800127C0 - * Size: 000050 - */ -static u32 Cmd_EXTSet() -{ - OuterParam_* ext; - - ext = (OuterParam_*)Jam_OfsToAddr(SEQ_P, SEQ_ARG[0]); - Jam_InitExtBuffer(ext); - Jam_AssignExtBuffer(SEQ_P, ext); - return 0; -} - -/* - * --INFO-- - * Address: 80012820 - * Size: 0000C4 - */ -static u32 Cmd_PanSwSet() -{ - size_t i; - - // Ah yes, let's just construct this on the stack real quick. - u8 calcTypes[] = { 0, 0, 0, 1, 1, 2, 2 }; - u8 parentCalcTypes[] = { 0, 1, 2, 0, 2, 0, 2 }; - - for (i = 0; i < 3; ++i) { - SEQ_P->panCalcTypes[i] = calcTypes[SEQ_ARG[i] >> 5]; - SEQ_P->parentPanCalcTypes[i] = parentCalcTypes[SEQ_ARG[i] >> 5]; - SEQ_P->parentController.panCalcTypes[i] = SEQ_ARG[i] & 0x1f; - SEQ_P->updateFlags |= OuterParamFlag_Pan; - } - - return 0; -} - -/* - * --INFO-- - * Address: 80012900 - * Size: 000040 - */ -static u32 Cmd_OscRoute() -{ - u8 uVar2; - u8 oscRoute; - - uVar2 = SEQ_ARG[0] >> 4 & 0xf; - oscRoute = SEQ_ARG[0] & 0xf; - - SEQ_P->oscillatorRouting[uVar2] = oscRoute; - if (oscRoute == 14) { - SEQ_P->oscillatorParams[uVar2].state = 1; - } - - return 0; -} - -/* - * --INFO-- - * Address: 80012940 - * Size: 0000A0 - */ -static u32 Cmd_IIRCutOff() -{ - u8 index; - size_t i; - MoveParam_* iir; - - index = SEQ_ARG[0]; - for (i = 0; i < 4; ++i) { - iir = &SEQ_P->timedParam.move[i + 12]; // IIRs 0 - 4 are at 12-15 - iir->targetValue = CUTOFF_TO_IIR_TABLE[index][i] / 32767.0f; - iir->currentValue = iir->targetValue; - iir->stepSize = 0.0f; - iir->duration = 1.0f; - } - - return 0; -} - -/* - * --INFO-- - * Address: 800129E0 - * Size: 000040 - */ -static u32 Cmd_OscFull() -{ - Osc_Setup_Full(SEQ_P, SEQ_ARG[0], SEQ_ARG[1], SEQ_ARG[2]); - return 0; -} - -/* - * --INFO-- - * Address: 80012A20 - * Size: 000068 - */ -static u32 Cmd_CheckWave() -{ - SOUNDID_ soundID; - u32 uVar2; - - soundID.value = SEQ_ARG[0] | (Jam_ReadRegDirect(SEQ_P, 6) << 16); - uVar2 = One_CheckInstWave(soundID); - Jam_WriteRegDirect(SEQ_P, 3, (u8)uVar2); - return 0; -} - -/* - * --INFO-- - * Address: 80012AA0 - * Size: 000204 - */ -static u32 Cmd_Printf() -{ - char fmtStr[0x80]; - u8 fmtFlags[4]; - u32 fmtParms[4]; - size_t fmtCount; - size_t i; - - fmtCount = 0; - for (i = 0; i < (u32)ARRAY_COUNT(fmtStr); ++i) { - fmtStr[i] = __ByteRead(SEQ_P); - if (fmtStr[i] == '\0') { - // Handle end of string - break; - } - if (fmtStr[i] == '\\') { - // Handle escape sequences (just the one) - fmtStr[i] = __ByteRead(SEQ_P); - - if (fmtStr[i] == '\0') { - // Unexpected end of string! - break; - } - switch (fmtStr[i]) { - case 'n': - // Convert newlines to... carriage returns? - fmtStr[i] = '\r'; - break; - } - continue; - } - if (fmtStr[i] == '%') { - // Handle conversion specifiers (plus a few custom ones!) - ++i; - fmtStr[i] = __ByteRead(SEQ_P); - - if (fmtStr[i] == '\0') { - // Unexpected end of string! - break; - } - switch (fmtStr[i]) { - case 'd': // Decimal - fmtFlags[fmtCount] = 0; - break; - case 'x': // Hexadecimal - fmtFlags[fmtCount] = 1; - break; - case 's': // String - fmtFlags[fmtCount] = 2; - break; - case 'r': // ? - fmtFlags[fmtCount] = 3; - fmtStr[i] = 'd'; - break; - case 'R': - fmtFlags[fmtCount] = 4; - fmtStr[i] = 'x'; - break; - } - ++fmtCount; - continue; - } - } - for (i = 0; i < fmtCount; ++i) { - fmtParms[i] = __ByteRead(SEQ_P); - if (fmtFlags[i] == 2) { - fmtParms[i] = (u32)Jam_OfsToAddr(SEQ_P, fmtParms[i]); - // } else if (fmtFlags[i] == 5) { - // fmtParms[i] = SEQ_P->trackId; - } - - if (fmtFlags[i] >= 3) { - fmtParms[i] = __ExchangeRegisterValue(SEQ_P, fmtParms[i]); - } - } - // A restoration of this command's functionality can be enabled below: - OSReport(fmtStr, fmtParms[0], fmtParms[1], fmtParms[2], fmtParms[3]); - return 0; -} - -static Arghead_ Arglist[CMD_COUNT] = { - { 0, 0x0000 }, // - { 2, 0x0008 }, // OpenTrack - { 2, 0x0008 }, // OpenTrackBros - { 1, 0x0002 }, // Call - { 0, 0x0000 }, // CallF - { 0, 0x0000 }, // Ret - { 1, 0x0000 }, // RetF - { 1, 0x0002 }, // Jmp - { 0, 0x0000 }, // JmpF - { 1, 0x0001 }, // LoopS - { 0, 0x0000 }, // LoopE - { 2, 0x0000 }, // ReadPort - { 2, 0x000c }, // WritePort - { 1, 0x0000 }, // CheckPortImport - { 1, 0x0000 }, // CheckPortExport - { 1, 0x0003 }, // WaitReg - { 2, 0x0005 }, // ConnectName - { 2, 0x000c }, // ParentWritePort - { 2, 0x000c }, // ChildWritePort - { 2, 0x000f }, // - { 1, 0x0000 }, // SetLastNote - { 1, 0x0000 }, // TimeRelate - { 1, 0x0000 }, // SimpleOsc - { 2, 0x0008 }, // SimpleEnv - { 5, 0x0155 }, // SimpleADSR - { 1, 0x0000 }, // Transpose - { 1, 0x0000 }, // CloseTrack - { 1, 0x0000 }, // OutSwitch - { 1, 0x0001 }, // UpdateSync - { 2, 0x0004 }, // BusConnect - { 1, 0x0000 }, // PauseStatus - { 2, 0x0008 }, // SetInterrupt - { 1, 0x0000 }, // DisInterrupt - { 0, 0x0000 }, // ClrI - { 0, 0x0000 }, // SetI - { 0, 0x0000 }, // RetI - { 2, 0x0004 }, // IntTimer - { 0, 0x0000 }, // ConnectOpen - { 0, 0x0000 }, // ConnectClose - { 1, 0x0001 }, // SyncCPU - { 0, 0x0000 }, // FlushAll - { 0, 0x0000 }, // FlushRelease - { 1, 0x0002 }, // Wait3 - { 5, 0x0000 }, // PanPowSet - { 4, 0x0055 }, // IIRSet - { 1, 0x0002 }, // FIRSet - { 1, 0x0002 }, // EXTSet - { 3, 0x0000 }, // PanSwSet - { 1, 0x0000 }, // OscRoute - { 1, 0x0000 }, // IIRCutOff - { 3, 0x0028 }, // OscFull - { 0, 0x0000 }, // - { 0, 0x0000 }, // - { 0, 0x0000 }, // - { 0, 0x0000 }, // - { 0, 0x0000 }, // - { 0, 0x0000 }, // - { 0, 0x0000 }, // - { 1, 0x0001 }, // CheckWave - { 0, 0x0000 }, // Printf - { 0, 0x0000 }, // Nop - { 1, 0x0001 }, // Tempo - { 1, 0x0001 }, // TimeBase - { 0, 0x0000 }, // Finish - -}; - -static CmdFunction CMDP_LIST[CMD_COUNT] = { - NULL, - Cmd_OpenTrack, - Cmd_OpenTrackBros, - Cmd_Call, - Cmd_CallF, - Cmd_Ret, - Cmd_RetF, - Cmd_Jmp, - Cmd_JmpF, - Cmd_LoopS, - Cmd_LoopE, - Cmd_ReadPort, - Cmd_WritePort, - Cmd_CheckPortImport, - Cmd_CheckPortExport, - Cmd_WaitReg, - Cmd_ConnectName, - Cmd_ParentWritePort, - Cmd_ChildWritePort, - NULL, - Cmd_SetLastNote, - Cmd_TimeRelate, - Cmd_SimpleOsc, - Cmd_SimpleEnv, - Cmd_SimpleADSR, - Cmd_Transpose, - Cmd_CloseTrack, - Cmd_OutSwitch, - Cmd_UpdateSync, - Cmd_BusConnect, - Cmd_PauseStatus, - Cmd_SetInterrupt, - Cmd_DisInterrupt, - Cmd_ClrI, - Cmd_SetI, - Cmd_RetI, - Cmd_IntTimer, - Cmd_ConnectOpen, - Cmd_ConnectClose, - Cmd_SyncCPU, - Cmd_FlushAll, - Cmd_FlushRelease, - Cmd_Wait3, - Cmd_PanPowSet, - Cmd_IIRSet, - Cmd_FIRSet, - Cmd_EXTSet, - Cmd_PanSwSet, - Cmd_OscRoute, - Cmd_IIRCutOff, - Cmd_OscFull, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - Cmd_CheckWave, - Cmd_Printf, - Cmd_Nop, - Cmd_Tempo, - Cmd_TimeBase, - Cmd_Finish, -}; - -/* - * --INFO-- - * Address: 80012CC0 - * Size: 000130 - */ -u32 Cmd_Process(seqp_* track, u8 cmd, u16 param_3) -{ - Arghead_ argpair; - u16 argTypes; - size_t i; - u32 arg; - CmdFunction function; - seqp_** REF_track; - u8* REF_cmd; - - REF_track = &track; - REF_cmd = &cmd; - - argpair = Arglist[cmd - 0xC0]; - argTypes = argpair.argTypes | param_3; - for (i = 0; i < argpair.argCount; ++i) { - switch (argTypes & 0x03) { - case 0: // 8-bit immediate value - arg = __ByteRead(track); - break; - case 1: // 16-bit immediate value - arg = __WordRead(track); - break; - case 2: // 24-bit immediate value - arg = __24Read(track); - break; - case 3: // Register value - arg = __ExchangeRegisterValue(track, __ByteRead(track)); - break; - } - - argTypes = argTypes >> 2; - SEQ_ARG[i] = arg; - } - - // Me when I have to introduce global state because I'm bored. - SEQ_CMD = cmd; - SEQ_P = track; - - function = CMDP_LIST[cmd - 0xC0]; - if (!function) { - OSReport("Error: NULL Command Pointer (cmd. %x ) \n", cmd); - OSReport("SEQP %x Access Offset %d\n", track, track->programCounter); - return 0; - } - return function(); -} - -/* - * --INFO-- - * Address: 80012E00 - * Size: 0000A8 - */ -u32 RegCmd_Process(seqp_* track, BOOL param_2, u32 param_3) -{ - size_t i; - u8 uVar4; - u8 uVar3; - u16 uVar5; - u16 uVar6; // Uninitialized! Naughty! - - uVar4 = __ByteRead(track); - if (param_2 == TRUE) { - uVar4 = __ExchangeRegisterValue(track, uVar4); - } - if (param_2 != TRUE || param_3 != 0) { - uVar3 = __ByteRead(track); - uVar5 = 0b11; - for (i = 0; i < param_3 + 1; ++i) { - if (uVar3 & 0b10000000) { - uVar6 |= uVar5; - } - uVar3 = uVar3 << 1; - uVar5 = uVar5 << 2; - } - } - return Cmd_Process(track, uVar4, uVar6); -} - -// TODO: These five values appear all over this file. They mean something. -static u8 osc_table[] = { 0x01, 0x02, 0x08, 0x04, 0x10 }; - -/* - * --INFO-- - * Address: 80012EC0 - * Size: 0008C0 - * Note: (Roughly) Equivalent to `JASTrack::mainProc` in later JAudio. - */ -s32 Jam_SeqmainNote(seqp_* track, u8 isMuted) -{ - BOOL var_r26; - u8 bVar9; - u8 velocity; - u32 uVar2; - s32 uVar5; - u8 bVar10_2; - f32 tempoProportion; - u8 opcode; - u8 uVar6; - u8 keyTarget; - u8 pitch; - u8 bVar10; - int local_64; - int iVar11; - int iVar11_2; - int iVar12; - u32 seqRes; - int duration; - jc_* pjVar3; - int iVar11_3; - u8 voice; - - seqRes = 0; - if (track->parent && track->doChangeTempo == TRUE) { - tempoProportion = (float)track->tempo / (float)track->parent->tempo; - if (tempoProportion > 1.0f) { - tempoProportion = 1.0f; - } - track->tempoAccumulator += tempoProportion; - if (track->tempoAccumulator < 1.0f) { - return 0; - } - track->tempoAccumulator -= 1.0f; - } - - { // This whole part is not present(?) in later JAudio. - if (track->parent) { - track->isMuted = isMuted; - } - if (track->parent && track->parentController.chanCount != 0) { - pjVar3 = List_GetChannel(&track->parentController.freeChannels); - if (pjVar3) { - List_AddChannel(&track->parent->parentController.freeChannels, pjVar3); - pjVar3->mMgr = &track->parent->parentController; - track->parentController.chanCount--; - track->parent->parentController.chanCount++; - } - } - // This resembles `JASTrack::getTranspose` of later JAudio. - if (track->parent) { - track->finalTranspose = track->transpose + track->parent->finalTranspose; - } else { - track->finalTranspose = track->transpose; - } - } - - Jam_SetInterrupt(track, 7); - { // This resembles `JASIntrMgr::timerProcess` of later JAudio. - if (track->timer != 0) { - if (--track->timer == 0) { - Jam_SetInterrupt(track, 6); - if (track->timerCount != 0) { - if (--track->timerCount != 0) { - track->timer = track->maxTime; - } - } else { - track->timer = track->maxTime; - } - } - } - } - -try_interrupt: - Jam_TryInterrupt(track); - if (track->isPaused && (track->pauseStatus & 2)) { - goto LAB_800136e0; - } - track->tickCounter++; - if (track->waitTimer == -1) { - if ((u8)CheckNoteStop(track, 0)) { // TODO: CheckNoteStop should return u8 or C++ bool - track->waitTimer = 0; - } else { - goto timed; - } - } - - if (track->waitTimer > 0) { - --track->waitTimer; - if (track->waitTimer != 0) { - goto timed; - } - if (track->_D0 != -1 && track->_D4 == 0) { - for (local_64 = 0; local_64 < (int)track->_90; local_64++) { - track->_94[local_64] = -1; - track->channels[local_64] = NULL; - } - } - } - - while (TRUE) { - opcode = __ByteRead(track); - if (!(opcode & 0x80)) { - // MIDI pitch (0-127) - pitch = opcode; - pitch += track->finalTranspose; - - if ((bVar10 = __ByteRead(track)) & 0x80) { - pitch = __ExchangeRegisterValue(track, pitch); - pitch += track->finalTranspose; - } - - if (pitch >= 128) { - OSReport("♪Jam/Seq :: Error Note %d\n", pitch); - } - - if (bVar10 >> 5 & 2) { - keyTarget = pitch; - pitch = track->_D5; - } - - velocity = __ByteRead(track); - if (velocity >= 0x80) { - velocity = __ExchangeRegisterValue(track, velocity - 0x80); - } - - u32 lowBits = bVar10; - lowBits &= 7; - if (lowBits == 0) { - voice = 0; - bVar9 = __ByteRead(track); - if (bVar9 >= 0x80) { - bVar9 = __ExchangeRegisterValue(track, bVar9 - 0x80); - } - uVar2 = 0; - for (iVar11 = 0; iVar11 < (bVar10 >> 3 & 3); iVar11++) { - uVar2 = uVar2 << 8 | __ByteRead(track); - } - if ((u32)(bVar10 >> 3 & 3) == 1 && uVar2 >= 0x80) { - uVar2 = __ExchangeRegisterValue(track, uVar2 - 0x80); - } - } else { - voice = lowBits; - // fake volatile for matching - if (*(volatile u8*)&bVar10 >> 3 & 3) { - voice = __ExchangeRegisterValue(track, voice - 1); - if (voice >= 8) { - break; - } - } - uVar2 = -1; - bVar9 = 100; - } - - track->_D4 = bVar10 >> 5 & 3; - - BOOL cond = track->_D6 ? TRUE : FALSE; - var_r26 = FALSE; - - for (int j = 0; j < 1; j++) { - // u8* track_p = track->_94; - int unused = j * 2; - - if (cond) { - duration = uVar2; - if (track->_D4 & 1) { - duration = -1; - } - if (duration != -1) { - duration = Jam_SEQtimeToDSPtime(track, duration, bVar9); - } - if (track->isPaused && (track->pauseStatus & 0x10)) { - iVar11_2 = -1; - } else { - iVar11_2 = GateON(track, voice, pitch, velocity, duration); - } - } else { - if ((duration = uVar2) != -1) { - duration = Jam_SEQtimeToDSPtime(track, duration, bVar9); - } - if (track->_D4 & 1) { - duration = -1; - } - if (track->isPaused && (track->pauseStatus & 0x10)) { - iVar11_2 = -1; - } else { - iVar11_2 = NoteON(track, voice, (u8)pitch, velocity, duration); - } - } - - if (iVar11_2 != -1) { - track->_94[voice] = pitch; - var_r26 = TRUE; - } - !unused; - } - - track->_90 = var_r26; - track->_CC = bVar9; - track->_CD = velocity; - track->_D0 = uVar2; - - if (track->_D4 & 1) { - track->_D6 = TRUE; - } else { - track->_D6 = FALSE; - } - - if (track->_D4 & 2) { - s32 steps = duration; - if (duration == -1) { - steps = Jam_SEQtimeToDSPtime(track, uVar2, track->_CC); - } - SetKeyTarget_1Shot(track->channels[0], keyTarget + track->finalTranspose, steps); - pitch = (u8)keyTarget; - } - - track->_D5 = pitch; - - if (uVar2 != -1) { - track->waitTimer = uVar2; - if (uVar2 == 0) { - track->waitTimer = -1; - } - break; - } - } else if ((opcode & 0xf0) == 0x80 || opcode == 0xf9) { - iVar11_3 = 1; - uVar5 = 0; - if (opcode == 0xf9) { - bVar10_2 = __ByteRead(track); - uVar6 = __ExchangeRegisterValue(track, bVar10_2 & 7); - if (uVar6 > 7 || uVar6 == 0) { - OSReport("♪Jam/main :: r-noteoff error\n"); - if ((bVar10_2 & 0x80) != 0) { - __ByteRead(track); - } - continue; - } - opcode = uVar6 + 0x80; - if (bVar10_2 & 0x80) { - opcode += 8; - } - } - uVar6 = opcode & 0x0f; - if (uVar6 == 8) { - iVar11_3 = 2; - uVar6 -= 8; - } - if (uVar6 > 8) { - uVar6 -= 8; - uVar5 = __ByteRead(track); - if (uVar5 > 100) { - uVar5 = (uVar5 - 98) * 20; - } - } - if (uVar6 == 0) { - // This for loop init feels fake... but idk. Check this again later. - for (track->waitTimer = iVar12 = 0; iVar12 < iVar11_3; iVar12++) { - track->waitTimer = track->waitTimer << 8 | __ByteRead(track); - } - if (track->waitTimer == 0) { - continue; - } - break; - } - if (uVar5 == 0) { - NoteOFF(track, uVar6); - } else { - NoteOFF_R(track, uVar6, uVar5); - } - } else { - // This portion is equivalent to `JASSeqParser::parseSeq` in later JAudio. - u32 cmdResult = 0; - if ((opcode & 0xf0) == 0x90) { - Jam_WriteTimeParam(track, opcode & 0x0f); - } else if ((opcode & 0xf0) == 0xa0) { - Jam_WriteRegParam(track, opcode & 0x0f); - } else if ((opcode & 0xf0) == 0xb0) { - u32 param_3 = opcode & 7; - cmdResult = RegCmd_Process(track, (opcode & 8) ? TRUE : FALSE, param_3); - } else { - cmdResult = Cmd_Process(track, opcode, 0); - } - - if (cmdResult == 0) { - continue; - } else if (cmdResult == 1) { - break; - } else if (cmdResult == 2) { - goto try_interrupt; - } else if (cmdResult == 3) { - return -1; - } else if (cmdResult == 0x80) { - OSReport("\x1b[4%dm", cmdResult); - OSReport("♪Jam/seq :: Sequence Error occerd... I try to continue\n"); - OSReport("\x1b[m"); - } - } - } - -timed: - // This portion is equivalent to `JASTrack::updateTimedParam` in later JAudio. - for (int i = 0; i < 18; i++) { - MoveParam_* move = &track->timedParam.move[i]; - if (move->duration > 0.0f) { - move->currentValue += move->stepSize; - move->duration -= 1.0f; - if (i <= 5 || i >= 11) { - seqRes |= (1 << i); - } else { - Osc_Update_Param(track, i, move->currentValue); - } - } - } - - if (track->oscillatorRouting[0] == 0x0E) { - seqRes |= osc_table[track->oscillators[0].mode]; - } - if (track->oscillatorRouting[1] == 0x0E) { - seqRes |= osc_table[track->oscillators[1].mode]; - } - -LAB_800136e0: - track->updateFlags |= seqRes; - - for (int i = 0; i < 16; i++) { - if (track->children[i] && track->children[i]->trackState != 0) { - if (track != track->children[i]->parent) { - OSReport("##########Error:: Track %d の共有違反です\n", i); - } - // Return of the worst bit extract extraction method known to man. - BOOL childIsMuted = track->isMuted | ((track->childMuteMask & (1 << i)) >> i); - if (Jam_SeqmainNote(track->children[i], childIsMuted) == -1) { - Jaq_CloseTrack(track->children[i]); - track->children[i] = NULL; - } - } - } - - return 0; + return 0; } +#pragma opt_dead_assignments reset /* * --INFO-- diff --git a/src/static/jaudio_PP/internal/jammain_2_cmd.c_inc b/src/static/jaudio_PP/internal/jammain_2_cmd.c_inc new file mode 100644 index 00000000..ce364800 --- /dev/null +++ b/src/static/jaudio_PP/internal/jammain_2_cmd.c_inc @@ -0,0 +1,863 @@ +/* + * --INFO-- + * Address: 80011800 + * Size: 000038 + */ +static u32 Cmd_OpenTrack() +{ + Jaq_OpenTrack(SEQ_P, SEQ_ARG[0], SEQ_ARG[1]); + return 0; +} + +/* + * --INFO-- + * Address: 80011840 + * Size: 000050 + */ +static u32 Cmd_OpenTrackBros() +{ + if (SEQ_P->parent) { + Jaq_OpenTrack(SEQ_P->parent, SEQ_ARG[0], SEQ_ARG[1]); + } else { + return 0x40; + } + return 0; +} + +/* + * --INFO-- + * Address: 800118A0 + * Size: 00003C + */ +static u32 Cmd_Call() +{ + SEQ_P->callStack[SEQ_P->callStackDepth++] = SEQ_P->programCounter; + SEQ_P->programCounter = SEQ_ARG[0]; + return 0; +} + +/* + * --INFO-- + * Address: 800118E0 + * Size: 000100 + */ +static u32 Cmd_CallF() +{ + u8 bVar1; + u32 uVar2; + u32 uVar3; + u8 uVar4; + + bVar1 = __ByteRead(SEQ_P); + if (bVar1 & 0x80) { + uVar4 = __ByteRead(SEQ_P); + uVar2 = Jam_ReadRegDirect(SEQ_P, uVar4); + if (bVar1 & 0x40) { + if (bVar1 & 0x20) { + uVar4 = __ByteRead(SEQ_P); + uVar3 = Jam_ReadRegDirect(SEQ_P, uVar4); + } else { + uVar3 = __24Read(SEQ_P); + } + uVar2 = __24ReadOfs(SEQ_P, uVar3 + uVar2 * 3); + } + } else { + uVar2 = __24Read(SEQ_P); + } + if ((u8)__ConditionCheck(SEQ_P, bVar1 & 0x0f) == TRUE) { + if (SEQ_CMD == (0xC0 + CMD_CALL_F)) { + SEQ_P->callStack[SEQ_P->callStackDepth++] = SEQ_P->programCounter; + } + SEQ_P->programCounter = uVar2; + } + return 0; +} + +/* + * --INFO-- + * Address: 800119E0 + * Size: 000028 + */ +static u32 Cmd_Ret() +{ + SEQ_P->programCounter = SEQ_P->callStack[--SEQ_P->callStackDepth]; + return 0; +} + +/* + * --INFO-- + * Address: 80011A20 + * Size: 000060 + */ +static u32 Cmd_RetF() +{ + // But why cast it...? And why check if it explicitly equals TRUE...? + if ((u8)__ConditionCheck(SEQ_P, SEQ_ARG[0] & 0x0f) == TRUE) { + SEQ_P->programCounter = SEQ_P->callStack[--SEQ_P->callStackDepth]; + } + return 0; +} + +/* + * --INFO-- + * Address: 80011A80 + * Size: 00001C + */ +static u32 Cmd_Jmp() +{ + SEQ_P->programCounter = SEQ_ARG[1]; + return 0; +} + +/* + * --INFO-- + * Address: 80011AA0 + * Size: 000020 + */ +static u32 Cmd_JmpF() +{ + Cmd_CallF(); +} + +/* + * --INFO-- + * Address: 80011AC0 + * Size: 000048 + */ +static u32 Cmd_LoopS() +{ + SEQ_P->callStack[SEQ_P->callStackDepth] = SEQ_P->programCounter; + SEQ_P->loopCounters[SEQ_P->callStackDepth++] = SEQ_ARG[0]; + return 0; +} + +/* + * --INFO-- + * Address: 80011B20 + * Size: 000078 + */ +static u32 Cmd_LoopE() +{ + u16 uVar1; + + if (SEQ_P->callStackDepth == 0) { + return 0x80; + } + + uVar1 = SEQ_P->loopCounters[SEQ_P->callStackDepth - 1]; + if (uVar1 != 0) { + uVar1 = (u16)(uVar1 - 1); + } + + if (uVar1 == 0) { + SEQ_P->callStackDepth -= 1; + return 0; + } + + SEQ_P->loopCounters[SEQ_P->callStackDepth - 1] = uVar1; + SEQ_P->programCounter = SEQ_P->callStack[SEQ_P->callStackDepth - 1]; + return 0; +} + +/* + * --INFO-- + * Address: 80011BA0 + * Size: 000054 + */ +static u32 Cmd_ReadPort() +{ + u16 temp; + + temp = SEQ_P->trackPort[SEQ_ARG[0]].value; + SEQ_P->trackPort[SEQ_ARG[0]].importFlag = 0; + Jam_WriteRegDirect(SEQ_P, SEQ_ARG[1], temp); + return 0; +} + +/* + * --INFO-- + * Address: 80011C00 + * Size: 000040 + */ +static u32 Cmd_WritePort() +{ + SEQ_P->trackPort[SEQ_ARG[0]].value = SEQ_ARG[1]; + SEQ_P->trackPort[SEQ_ARG[0]].exportFlag = 1; + return 0; +} + +/* + * --INFO-- + * Address: 80011C40 + * Size: 000044 + */ +static u32 Cmd_CheckPortImport() +{ + Jam_WriteRegDirect(SEQ_P, 3, SEQ_P->trackPort[SEQ_ARG[0]].importFlag); + return 0; +} + +/* + * --INFO-- + * Address: 80011CA0 + * Size: 000044 + */ +static u32 Cmd_CheckPortExport() +{ + Jam_WriteRegDirect(SEQ_P, 3, SEQ_P->trackPort[SEQ_ARG[0]].exportFlag); + return 0; +} + +/* + * --INFO-- + * Address: 80011D00 + * Size: 00002C + */ +static u32 Cmd_WaitReg() +{ + SEQ_P->waitTimer = SEQ_ARG[0]; + return SEQ_ARG[0] ? 1 : 0; +} + +/* + * --INFO-- + * Address: 80011D40 + * Size: 000028 + */ +static u32 Cmd_ConnectName() +{ + SEQ_P->connectionId = SEQ_ARG[0] << 16 | SEQ_ARG[1]; + return 0; +} + +/* + * --INFO-- + * Address: 80011D80 + * Size: 000040 + */ +static u32 Cmd_ParentWritePort() +{ + Jam_WritePortAppDirect(SEQ_P->parent, SEQ_ARG[0] & 0x0f, SEQ_ARG[1]); + return 0; +} + +/* + * --INFO-- + * Address: 80011DC0 + * Size: 000048 + */ +static u32 Cmd_ChildWritePort() +{ + Jam_WritePortAppDirect(SEQ_P->children[(SEQ_ARG[0] >> 4)], SEQ_ARG[0] & 0x0f, SEQ_ARG[1]); + return 0; +} + +/* + * --INFO-- + * Address: 80011E20 + * Size: 000030 + */ +static u32 Cmd_SetLastNote() +{ + SEQ_P->_D5 = SEQ_ARG[0]; + SEQ_P->_D5 += SEQ_P->finalTranspose; + return 0; +} + +/* + * --INFO-- + * Address: 80011E60 + * Size: 00001C + */ +static u32 Cmd_TimeRelate() +{ + SEQ_P->timeRelationMode = SEQ_ARG[0]; + return 0; +} + +/* + * --INFO-- + * Address: 80011E80 + * Size: 000034 + */ +static u32 Cmd_SimpleOsc() +{ + Osc_Setup_Simple(SEQ_P, SEQ_ARG[0]); + return 0; +} + +/* + * --INFO-- + * Address: 80011EC0 + * Size: 000038 + */ +static u32 Cmd_SimpleEnv() +{ + Osc_Setup_SimpleEnv(SEQ_P, SEQ_ARG[0], SEQ_ARG[1]); + return 0; +} + +/* + * --INFO-- + * Address: 80011F00 + * Size: 000064 + */ +static u32 Cmd_SimpleADSR() +{ + int i; + s16 local_10[5]; + + for (i = 0; i < 5; ++i) { + local_10[i] = SEQ_ARG[i]; + } + Osc_Setup_ADSR(SEQ_P, local_10); + return 0; +} + +/* + * --INFO-- + * Address: 80011F80 + * Size: 000048 + */ +static u32 Cmd_Transpose() +{ + SEQ_P->transpose = SEQ_ARG[0]; + if (SEQ_P->parent) { + SEQ_P->finalTranspose = SEQ_P->parent->transpose + SEQ_P->transpose; + } else { + SEQ_P->finalTranspose = SEQ_P->transpose; + } + return 0; +} + +/* + * --INFO-- + * Address: 80011FE0 + * Size: 000068 + */ +static u32 Cmd_CloseTrack() +{ + u8 index = SEQ_ARG[0]; + if (index >= (u32)ARRAY_COUNT(SEQ_P->children)) { + return 0x80; + } + Jaq_CloseTrack(SEQ_P->children[index]); + SEQ_P->children[index] = NULL; + return 0; +} + +/* + * --INFO-- + * Address: 80012060 + * Size: 000038 + */ +static u32 Cmd_OutSwitch() +{ + if (SEQ_P->outerParams) { + SEQ_P->outerParams->flags = SEQ_ARG[0]; + SEQ_P->outerParams->updateFlags = -1; + } + + return 0; +} + +/* + * --INFO-- + * Address: 800120A0 + * Size: 000034 + */ +static u32 Cmd_UpdateSync() +{ + Jam_UpdateTrack(SEQ_P, SEQ_ARG[0]); + return 0; +} + +/* + * --INFO-- + * Address: 800120E0 + * Size: 00002C + */ +static u32 Cmd_BusConnect() +{ + if (SEQ_ARG[0] < 6) { + SEQ_P->parentController.busConnect[SEQ_ARG[0]] = SEQ_ARG[1]; + } + return 0; +} + +/* + * --INFO-- + * Address: 80012120 + * Size: 00001C + */ +static u32 Cmd_PauseStatus() +{ + SEQ_P->pauseStatus = SEQ_ARG[0]; + return 0; +} + +/* + * --INFO-- + * Address: 80012140 + * Size: 000044 + */ +static u32 Cmd_SetInterrupt() +{ + SEQ_P->interruptEnable |= (1 << SEQ_ARG[0]); + SEQ_P->interruptAddresses[SEQ_ARG[0]] = SEQ_ARG[1]; + return 0; +} + +/* + * --INFO-- + * Address: 800121A0 + * Size: 000030 + */ +static u32 Cmd_DisInterrupt() +{ + u8 arg; + arg = SEQ_ARG[0]; + arg = 1 << arg; + arg = ~arg; + SEQ_P->interruptEnable &= arg; + return 0; +} + +/* + * --INFO-- + * Address: 800121E0 + * Size: 000014 + */ +static u32 Cmd_ClrI() +{ + SEQ_P->interruptActive = 0; + return 0; +} + +/* + * --INFO-- + * Address: 80012200 + * Size: 000014 + */ +static u32 Cmd_SetI() +{ + SEQ_P->interruptActive = 1; + return 0; +} + +/* + * --INFO-- + * Address: 80012220 + * Size: 00002C + */ +static u32 Cmd_RetI() +{ + SEQ_P->waitTimer = SEQ_P->_3CC; + SEQ_P->interruptActive = 0; + SEQ_P->programCounter = SEQ_P->savedProgramCounter; + return 2; +} + +/* + * --INFO-- + * Address: 80012260 + * Size: 000034 + */ +static u32 Cmd_IntTimer() +{ + SEQ_P->timerCount = SEQ_ARG[0]; + SEQ_P->timer = SEQ_ARG[1]; + SEQ_P->maxTime = SEQ_ARG[1]; + return 0; +} + +/* + * --INFO-- + * Address: 800122A0 + * Size: 00002C + */ +static u32 Cmd_ConnectOpen() +{ + Jam_RegistTrack(SEQ_P, SEQ_P->connectionId); + return 0; +} + +/* + * --INFO-- + * Address: 800122E0 + * Size: 000028 + */ +static u32 Cmd_ConnectClose() +{ + Jam_UnRegistTrack(SEQ_P); + return 0; +} + +/* + * --INFO-- + * Address: 80012320 + * Size: 000060 + */ +static u32 Cmd_SyncCPU() +{ + u16 seq_arg; + u16 param_3; + + seq_arg = SEQ_ARG[0]; + if (JAM_CALLBACK_FUNC) { + param_3 = JAM_CALLBACK_FUNC(SEQ_P, seq_arg); + } else { + param_3 = 0xffff; + } + Jam_WriteRegDirect(SEQ_P, 3, param_3); + return 0; +} + +/* + * --INFO-- + * Address: 80012380 + * Size: 000038 + */ +static u32 Cmd_FlushAll() +{ + AllStop_1Shot(&SEQ_P->parentController); + FlushRelease_1Shot(&SEQ_P->parentController); + return 0; +} + +/* + * --INFO-- + * Address: 800123C0 + * Size: 00002C + */ +static u32 Cmd_FlushRelease() +{ + FlushRelease_1Shot(&SEQ_P->parentController); + return 0; +} + +/* + * --INFO-- + * Address: 80012400 + * Size: 00002C + */ +static u32 Cmd_Wait3() +{ + SEQ_P->waitTimer = SEQ_ARG[0]; + return SEQ_ARG[0] ? 1 : 0; +} + +/* + * --INFO-- + * Address: 80012440 + * Size: 000044 + */ +static u32 Cmd_TimeBase() +{ + SEQ_P->timeBase = SEQ_ARG[0]; + if (!SEQ_P->parent) { + Jam_UpdateTempo(SEQ_P); + } + return 0; +} + +/* + * --INFO-- + * Address: 800124A0 + * Size: 000050 + */ +static u32 Cmd_Tempo() +{ + SEQ_P->tempo = SEQ_ARG[0]; + if (!SEQ_P->parent) { + Jam_UpdateTempo(SEQ_P); + } else { + SEQ_P->doChangeTempo = TRUE; + } + return 0; +} + +/* + * --INFO-- + * Address: 80012500 + * Size: 0000CC + */ +static u32 Cmd_Finish() +{ + size_t i; + u32 updateFlags; + MoveParam_* temp; + + updateFlags = 0; + for (i = 0; i < 18; ++i) { + temp = &SEQ_P->timedParam.move[i]; + if (temp->duration > 0.0f) { + temp->currentValue += temp->stepSize; + temp->duration -= 1.0f; + if (i <= 5 || i >= 11) { + updateFlags |= 1 << i; + } else { + Osc_Update_Param(SEQ_P, i, temp->currentValue); + } + } + } + SeqUpdate(SEQ_P, updateFlags); + + return 3; +} + +/* + * --INFO-- + * Address: 800125E0 + * Size: 000008 + */ +static u32 Cmd_Nop() +{ + return 0; +} + +/* + * --INFO-- + * Address: 80012600 + * Size: 0000AC + */ +static u32 Cmd_PanPowSet() +{ + size_t i; + + for (i = 0; i < 3; ++i) { + SEQ_P->regParam.param.arguments[i] = SEQ_ARG[i]; + } + for (i = 3; i < 5; ++i) { + SEQ_P->regParam.param.arguments[i] = SEQ_ARG[i] * 327.67f; + } + + return 0; +} + +/* + * --INFO-- + * Address: 800126C0 + * Size: 000094 + */ +static u32 Cmd_IIRSet() +{ + + size_t i; + MoveParam_* iir; + + for (i = 0; i < 4; ++i) { + iir = &SEQ_P->timedParam.move[i + 12]; // IIRs 0 - 4 are at 12-15 + iir->targetValue = (s16)SEQ_ARG[i] / 32768.0f; + iir->currentValue = iir->targetValue; + iir->stepSize = 0.0f; + iir->duration = 1.0f; + } + + return 0; +} + +/* + * --INFO-- + * Address: 80012760 + * Size: 000044 + */ +static u32 Cmd_FIRSet() +{ + Jam_SetExtFirFilterD(SEQ_P->outerParams, (s16*)Jam_OfsToAddr(SEQ_P, SEQ_ARG[0])); + return 0; +} + +/* + * --INFO-- + * Address: 800127C0 + * Size: 000050 + */ +static u32 Cmd_EXTSet() +{ + OuterParam_* ext; + + ext = (OuterParam_*)Jam_OfsToAddr(SEQ_P, SEQ_ARG[0]); + Jam_InitExtBuffer(ext); + Jam_AssignExtBuffer(SEQ_P, ext); + return 0; +} + +/* + * --INFO-- + * Address: 80012820 + * Size: 0000C4 + */ +static u32 Cmd_PanSwSet() +{ + size_t i; + + // Ah yes, let's just construct this on the stack real quick. + u8 calcTypes[] = { 0, 0, 0, 1, 1, 2, 2 }; + u8 parentCalcTypes[] = { 0, 1, 2, 0, 2, 0, 2 }; + + for (i = 0; i < 3; ++i) { + SEQ_P->panCalcTypes[i] = calcTypes[SEQ_ARG[i] >> 5]; + SEQ_P->parentPanCalcTypes[i] = parentCalcTypes[SEQ_ARG[i] >> 5]; + SEQ_P->parentController.panCalcTypes[i] = SEQ_ARG[i] & 0x1f; + SEQ_P->updateFlags |= OuterParamFlag_Pan; + } + + return 0; +} + +/* + * --INFO-- + * Address: 80012900 + * Size: 000040 + */ +static u32 Cmd_OscRoute() +{ + u8 uVar2; + u8 oscRoute; + + uVar2 = SEQ_ARG[0] >> 4 & 0xf; + oscRoute = SEQ_ARG[0] & 0xf; + + SEQ_P->oscillatorRouting[uVar2] = oscRoute; + if (oscRoute == 14) { + SEQ_P->oscillatorParams[uVar2].state = 1; + } + + return 0; +} + +/* + * --INFO-- + * Address: 80012940 + * Size: 0000A0 + */ +static u32 Cmd_IIRCutOff() +{ + u8 index; + size_t i; + MoveParam_* iir; + + index = SEQ_ARG[0]; + for (i = 0; i < 4; ++i) { + iir = &SEQ_P->timedParam.move[i + 12]; // IIRs 0 - 4 are at 12-15 + iir->targetValue = CUTOFF_TO_IIR_TABLE[index][i] / 32767.0f; + iir->currentValue = iir->targetValue; + iir->stepSize = 0.0f; + iir->duration = 1.0f; + } + + return 0; +} + +/* + * --INFO-- + * Address: 800129E0 + * Size: 000040 + */ +static u32 Cmd_OscFull() +{ + Osc_Setup_Full(SEQ_P, SEQ_ARG[0], SEQ_ARG[1], SEQ_ARG[2]); + return 0; +} + +/* + * --INFO-- + * Address: 80012A20 + * Size: 000068 + */ +static u32 Cmd_CheckWave() +{ + SOUNDID_ soundID; + u32 uVar2; + + soundID.value = SEQ_ARG[0] | (Jam_ReadRegDirect(SEQ_P, 6) << 16); + uVar2 = One_CheckInstWave(soundID); + Jam_WriteRegDirect(SEQ_P, 3, (u8)uVar2); + return 0; +} + +/* + * --INFO-- + * Address: 80012AA0 + * Size: 000204 + */ +static u32 Cmd_Printf() +{ + char fmtStr[0x80]; + u8 fmtFlags[4]; + u32 fmtParms[4]; + size_t fmtCount; + size_t i; + + fmtCount = 0; + for (i = 0; i < (u32)ARRAY_COUNT(fmtStr); ++i) { + fmtStr[i] = __ByteRead(SEQ_P); + if (fmtStr[i] == '\0') { + // Handle end of string + break; + } + if (fmtStr[i] == '\\') { + // Handle escape sequences (just the one) + fmtStr[i] = __ByteRead(SEQ_P); + + if (fmtStr[i] == '\0') { + // Unexpected end of string! + break; + } + switch (fmtStr[i]) { + case 'n': + // Convert newlines to... carriage returns? + fmtStr[i] = '\r'; + break; + } + continue; + } + if (fmtStr[i] == '%') { + // Handle conversion specifiers (plus a few custom ones!) + ++i; + fmtStr[i] = __ByteRead(SEQ_P); + + if (fmtStr[i] == '\0') { + // Unexpected end of string! + break; + } + switch (fmtStr[i]) { + case 'd': // Decimal + fmtFlags[fmtCount] = 0; + break; + case 'x': // Hexadecimal + fmtFlags[fmtCount] = 1; + break; + case 's': // String + fmtFlags[fmtCount] = 2; + break; + case 'r': // ? + fmtFlags[fmtCount] = 3; + fmtStr[i] = 'd'; + break; + case 'R': + fmtFlags[fmtCount] = 4; + fmtStr[i] = 'x'; + break; + } + ++fmtCount; + continue; + } + } + for (i = 0; i < fmtCount; ++i) { + fmtParms[i] = __ByteRead(SEQ_P); + if (fmtFlags[i] == 2) { + fmtParms[i] = (u32)Jam_OfsToAddr(SEQ_P, fmtParms[i]); + // } else if (fmtFlags[i] == 5) { + // fmtParms[i] = SEQ_P->trackId; + } + + if (fmtFlags[i] >= 3) { + fmtParms[i] = __ExchangeRegisterValue(SEQ_P, fmtParms[i]); + } + } + // A restoration of this command's functionality can be enabled below: + OSReport(fmtStr, fmtParms[0], fmtParms[1], fmtParms[2], fmtParms[3]); + return 0; +} diff --git a/src/static/jaudio_PP/internal/jammain_2_cmdproc.c_inc b/src/static/jaudio_PP/internal/jammain_2_cmdproc.c_inc new file mode 100644 index 00000000..23800373 --- /dev/null +++ b/src/static/jaudio_PP/internal/jammain_2_cmdproc.c_inc @@ -0,0 +1,218 @@ +static Arghead_ Arglist[CMD_COUNT] = { + { 0, 0x0000 }, // + { 2, 0x0008 }, // OpenTrack + { 2, 0x0008 }, // OpenTrackBros + { 1, 0x0002 }, // Call + { 0, 0x0000 }, // CallF + { 0, 0x0000 }, // Ret + { 1, 0x0000 }, // RetF + { 1, 0x0002 }, // Jmp + { 0, 0x0000 }, // JmpF + { 1, 0x0001 }, // LoopS + { 0, 0x0000 }, // LoopE + { 2, 0x0000 }, // ReadPort + { 2, 0x000c }, // WritePort + { 1, 0x0000 }, // CheckPortImport + { 1, 0x0000 }, // CheckPortExport + { 1, 0x0003 }, // WaitReg + { 2, 0x0005 }, // ConnectName + { 2, 0x000c }, // ParentWritePort + { 2, 0x000c }, // ChildWritePort + { 2, 0x000f }, // + { 1, 0x0000 }, // SetLastNote + { 1, 0x0000 }, // TimeRelate + { 1, 0x0000 }, // SimpleOsc + { 2, 0x0008 }, // SimpleEnv + { 5, 0x0155 }, // SimpleADSR + { 1, 0x0000 }, // Transpose + { 1, 0x0000 }, // CloseTrack + { 1, 0x0000 }, // OutSwitch + { 1, 0x0001 }, // UpdateSync + { 2, 0x0004 }, // BusConnect + { 1, 0x0000 }, // PauseStatus + { 2, 0x0008 }, // SetInterrupt + { 1, 0x0000 }, // DisInterrupt + { 0, 0x0000 }, // ClrI + { 0, 0x0000 }, // SetI + { 0, 0x0000 }, // RetI + { 2, 0x0004 }, // IntTimer + { 0, 0x0000 }, // ConnectOpen + { 0, 0x0000 }, // ConnectClose + { 1, 0x0001 }, // SyncCPU + { 0, 0x0000 }, // FlushAll + { 0, 0x0000 }, // FlushRelease + { 1, 0x0002 }, // Wait3 + { 5, 0x0000 }, // PanPowSet + { 4, 0x0055 }, // IIRSet + { 1, 0x0002 }, // FIRSet + { 1, 0x0002 }, // EXTSet + { 3, 0x0000 }, // PanSwSet + { 1, 0x0000 }, // OscRoute + { 1, 0x0000 }, // IIRCutOff + { 3, 0x0028 }, // OscFull + { 0, 0x0000 }, // + { 0, 0x0000 }, // + { 0, 0x0000 }, // + { 0, 0x0000 }, // + { 0, 0x0000 }, // + { 0, 0x0000 }, // + { 0, 0x0000 }, // + { 1, 0x0001 }, // CheckWave + { 0, 0x0000 }, // Printf + { 0, 0x0000 }, // Nop + { 1, 0x0001 }, // Tempo + { 1, 0x0001 }, // TimeBase + { 0, 0x0000 }, // Finish + +}; + +static CmdFunction CMDP_LIST[CMD_COUNT] = { + NULL, + Cmd_OpenTrack, + Cmd_OpenTrackBros, + Cmd_Call, + Cmd_CallF, + Cmd_Ret, + Cmd_RetF, + Cmd_Jmp, + Cmd_JmpF, + Cmd_LoopS, + Cmd_LoopE, + Cmd_ReadPort, + Cmd_WritePort, + Cmd_CheckPortImport, + Cmd_CheckPortExport, + Cmd_WaitReg, + Cmd_ConnectName, + Cmd_ParentWritePort, + Cmd_ChildWritePort, + NULL, + Cmd_SetLastNote, + Cmd_TimeRelate, + Cmd_SimpleOsc, + Cmd_SimpleEnv, + Cmd_SimpleADSR, + Cmd_Transpose, + Cmd_CloseTrack, + Cmd_OutSwitch, + Cmd_UpdateSync, + Cmd_BusConnect, + Cmd_PauseStatus, + Cmd_SetInterrupt, + Cmd_DisInterrupt, + Cmd_ClrI, + Cmd_SetI, + Cmd_RetI, + Cmd_IntTimer, + Cmd_ConnectOpen, + Cmd_ConnectClose, + Cmd_SyncCPU, + Cmd_FlushAll, + Cmd_FlushRelease, + Cmd_Wait3, + Cmd_PanPowSet, + Cmd_IIRSet, + Cmd_FIRSet, + Cmd_EXTSet, + Cmd_PanSwSet, + Cmd_OscRoute, + Cmd_IIRCutOff, + Cmd_OscFull, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Cmd_CheckWave, + Cmd_Printf, + Cmd_Nop, + Cmd_Tempo, + Cmd_TimeBase, + Cmd_Finish, +}; + +/* + * --INFO-- + * Address: 80012CC0 + * Size: 000130 + */ +u32 Cmd_Process(seqp_* track, u8 cmd, u16 param_3) +{ + Arghead_ argpair; + u16 argTypes; + size_t i; + u32 arg; + CmdFunction function; + seqp_** REF_track; + u8* REF_cmd; + + REF_track = &track; + REF_cmd = &cmd; + + argpair = Arglist[cmd - 0xC0]; + argTypes = argpair.argTypes | param_3; + for (i = 0; i < argpair.argCount; ++i) { + switch (argTypes & 0x03) { + case 0: // 8-bit immediate value + arg = __ByteRead(track); + break; + case 1: // 16-bit immediate value + arg = __WordRead(track); + break; + case 2: // 24-bit immediate value + arg = __24Read(track); + break; + case 3: // Register value + arg = __ExchangeRegisterValue(track, __ByteRead(track)); + break; + } + + argTypes = argTypes >> 2; + SEQ_ARG[i] = arg; + } + + // Me when I have to introduce global state because I'm bored. + SEQ_CMD = cmd; + SEQ_P = track; + + function = CMDP_LIST[cmd - 0xC0]; + if (!function) { + OSReport("Error: NULL Command Pointer (cmd. %x ) \n", cmd); + OSReport("SEQP %x Access Offset %d\n", track, track->programCounter); + return 0; + } + return function(); +} + +/* + * --INFO-- + * Address: 80012E00 + * Size: 0000A8 + */ +u32 RegCmd_Process(seqp_* track, BOOL param_2, u32 param_3) +{ + size_t i; + u8 uVar4; + u8 uVar3; + u16 uVar5; + u16 uVar6; // Uninitialized! Naughty! + + uVar4 = __ByteRead(track); + if (param_2 == TRUE) { + uVar4 = __ExchangeRegisterValue(track, uVar4); + } + if (param_2 != TRUE || param_3 != 0) { + uVar3 = __ByteRead(track); + uVar5 = 0b11; + for (i = 0; i < param_3 + 1; ++i) { + if (uVar3 & 0b10000000) { + uVar6 |= uVar5; + } + uVar3 = uVar3 << 1; + uVar5 = uVar5 << 2; + } + } + return Cmd_Process(track, uVar4, uVar6); +} diff --git a/src/static/jaudio_PP/internal/jammain_2_port.c_inc b/src/static/jaudio_PP/internal/jammain_2_port.c_inc new file mode 100644 index 00000000..6a9ec377 --- /dev/null +++ b/src/static/jaudio_PP/internal/jammain_2_port.c_inc @@ -0,0 +1,555 @@ +/* + * --INFO-- + * Address: ........ + * Size: 00004C + */ +void Jam_WritePortApp(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 00004C + */ +void Jam_ReadPortApp(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 000048 + */ +void Jam_CheckExportApp(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 000048 + */ +void Jam_CheckImportApp(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 0000A0 + */ +void Jam_WritePortIndirect(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 000058 + */ +void Jam_ReadPortIndirect(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 0000A4 + */ +void Jam_CheckPortIndirect(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: 80010380 + * Size: 000078 + */ +BOOL Jam_WritePortAppDirect(seqp_* track, u32 param_2, u16 param_3) +{ + if (!track) { + return FALSE; + } + track->trackPort[param_2].value = param_3; + track->trackPort[param_2].importFlag = 1; + if (param_2 == 0) { + Jam_SetInterrupt(track, 3); + } + if (param_2 == 1) { + Jam_SetInterrupt(track, 4); + } + return TRUE; +} + +/* + * --INFO-- + * Address: 80010400 + * Size: 000030 + */ +BOOL Jam_ReadPortAppDirect(seqp_* track, u32 param_2, u16* param_3) +{ + if (!track) { + return FALSE; + } + *param_3 = track->trackPort[param_2].value; + track->trackPort[param_2].exportFlag = 0; + return TRUE; +} + +/* + * --INFO-- + * Address: 80010440 + * Size: 00006C + */ +BOOL Jam_CheckPortAppDirect(seqp_* track, u32 param_2, u16 param_3) +{ + // Again with the cast to u8... what is it? + switch ((u8)param_3) { + case FALSE: + if (track->trackPort[param_2].exportFlag == FALSE) { + return FALSE; + } + return TRUE; + case TRUE: + if (track->trackPort[param_2].importFlag == TRUE) { + return FALSE; + } + return TRUE; + } + return FALSE; +} + +/* + * --INFO-- + * Address: ........ + * Size: 000018 + */ +void Jam_WritePort(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 000018 + */ +void Jam_ReadPort(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 000034 + */ +void Jam_WritePortChild(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 000038 + */ +void Jam_WritePortBros(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: 800104C0 + * Size: 000030 + */ +void Jam_InitRegistTrack(void) +{ + int i; + + T_LISTS = 0; + for (i = 0; i < TRACK_LIST_SIZE; ++i) { + TRACK_LIST[i].track = NULL; + } +} + +/* + * --INFO-- + * Address: 80010500 + * Size: 0000A8 + */ +void Jam_RegistTrack(seqp_* track, u32 param_2) +{ + u32* REF_param_2; + size_t i; + + for (i = 0; i < T_LISTS; ++i) { + if (param_2 == TRACK_LIST[i].id) { + return; + } + } + if (T_LISTS == TRACK_LIST_SIZE) { + for (i = 0; i < TRACK_LIST_SIZE; ++i) { + if (!TRACK_LIST[i].track) { + break; + } + } + if (i == TRACK_LIST_SIZE) { + return; + } + } else { + i = T_LISTS; + ++T_LISTS; + } + REF_param_2 = ¶m_2; + TRACK_LIST[i].id = param_2; + TRACK_LIST[i].track = track; + track->isRegistered = 1; +} + +/* + * --INFO-- + * Address: 800105C0 + * Size: 00008C + */ +void Jam_UnRegistTrack(seqp_* track) +{ + size_t i; + + if (!track->isRegistered) { + return; + } + for (i = 0; i < T_LISTS; ++i) { + if (track == TRACK_LIST[i].track) { + TRACK_LIST[i].track = NULL; + } + } + track->isRegistered = FALSE; + for (; T_LISTS != 0; --T_LISTS) { + if (TRACK_LIST[T_LISTS - 1].track) { + break; + } + } +} + +/* + * --INFO-- + * Address: 80010660 + * Size: 000050 + */ +seqp_* Jam_GetTrackHandle(u32 param_1) +{ + size_t i; + + for (i = 0; i < T_LISTS; ++i) { + if (param_1 == TRACK_LIST[i].id && TRACK_LIST[i].track) { + return TRACK_LIST[i].track; + } + } + return NULL; +} + +/* + * --INFO-- + * Address: 800106C0 + * Size: 000018 + */ +void Jam_InitExtBuffer(OuterParam_* ext) +{ + ext->flags = 0; + ext->updateFlags = 0; + ext->isAssigned = FALSE; + ext->refCount = 0; +} + +/* + * --INFO-- + * Address: 800106E0 + * Size: 000038 + */ +BOOL Jam_AssignExtBuffer(seqp_* track, OuterParam_* ext) +{ + if (!track) { + return FALSE; + } + if (!ext) { + return FALSE; + } + track->outerParams = ext; + ++ext->refCount; + return TRUE; +} + +/* + * --INFO-- + * Address: 80010720 + * Size: 000060 + */ +BOOL Jam_AssignExtBufferP(seqp_* track, u8 index, OuterParam_* ext) +{ + if (!track) { + return FALSE; + } + if (!ext) { + return FALSE; + } + track->childOuterParams[index] = ext; + ext->isAssigned = TRUE; + Jam_AssignExtBuffer(track->children[index], ext); + return TRUE; +} + +/* + * --INFO-- + * Address: 80010780 + * Size: 000044 + */ +void Jam_SetExtFirFilterD(OuterParam_* ext, s16* param_2) +{ + int i; + + if (!ext) { + return; + } + ext->updateFlags |= OuterParamFlag_FIR8Filter; + ext->flags |= OuterParamFlag_FIR8Filter; + for (i = 0; i < 8; ++i) { + ext->firCoefficients[i] = param_2[i]; + } +} + +/* + * --INFO-- + * Address: 800107E0 + * Size: 0000A4 + */ +void Jam_SetExtParamD(f32 value, OuterParam_* ext, u8 updateFlags) +{ + f32* member; + + if (!ext) { + return; + } + + switch (updateFlags) { + case OuterParamFlag_Volume: + member = &ext->volume; + break; + case OuterParamFlag_Pitch: + member = &ext->pitch; + break; + case OuterParamFlag_Fxmix: + member = &ext->fxMix; + break; + case OuterParamFlag_Dolby: + member = &ext->dolby; + break; + case OuterParamFlag_Pan: + member = &ext->pan; + break; + case OuterParamFlag_Tempo: + member = &ext->tempo; + break; + default: + return; + } + + *member = value; + ext->updateFlags |= updateFlags; +} + +/* + * --INFO-- + * Address: 800108A0 + * Size: 000024 + */ +void Jam_OnExtSwitchD(OuterParam_* ext, u16 param_2) +{ + if (!ext) { + return; + } + ext->flags |= param_2; + ext->updateFlags |= param_2; +} + +/* + * --INFO-- + * Address: 800108E0 + * Size: 000028 + */ +void Jam_OffExtSwitchD(OuterParam_* ext, u16 param_2) +{ + if (!ext) { + return; + } + ext->flags ^= ext->flags & param_2; + ext->updateFlags |= param_2; +} + +/* + * --INFO-- + * Address: ........ + * Size: 00001C + */ +void Jam_SetExtSwitchDirectD(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 00002C + */ +void Jam_SetExtFirFilter(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: 80010920 + * Size: 00002C + */ +void Jam_SetExtParam(f32 param_1, seqp_* track, u8 param_3) +{ + if (!track) { + return; + } + Jam_SetExtParamD(param_1, track->outerParams, param_3); +} + +/* + * --INFO-- + * Address: 80010960 + * Size: 00002C + */ +void Jam_OnExtSwitch(seqp_* track, u16 param_2) +{ + if (!track) { + return; + } + Jam_OnExtSwitchD(track->outerParams, param_2); +} + +/* + * --INFO-- + * Address: 800109A0 + * Size: 00002C + */ +void Jam_OffExtSwitch(seqp_* track, u16 param_2) +{ + if (!track) { + return; + } + Jam_OffExtSwitchD(track->outerParams, param_2); +} + +/* + * --INFO-- + * Address: ........ + * Size: 00002C + */ +void Jam_SetExtSwitchDirect(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 00003C + */ +void Jam_SetExtFirFilterP(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: 800109E0 + * Size: 000038 + */ +void Jam_SetExtParamP(f32 param_1, seqp_* track, u8 index, u8 param_4) +{ + if (!track) { + return; + } + Jam_SetExtParamD(param_1, track->childOuterParams[index], param_4); +} + +/* + * --INFO-- + * Address: 80010A20 + * Size: 00003C + */ +void Jam_OnExtSwitchP(seqp_* track, u8 index, u16 param_3) +{ + if (!track) { + return; + } + Jam_OnExtSwitchD(track->childOuterParams[index], param_3); +} + +/* + * --INFO-- + * Address: ........ + * Size: 00003C + */ +void Jam_OffExtSwitchP(seqp_* track, u8 index, u16 param_3) +{ + if (!track) { + return; + } + Jam_OffExtSwitchD(track->childOuterParams[index], param_3); +} + +/* + * --INFO-- + * Address: ........ + * Size: 00003C + */ +void Jam_SetExtSwitchDirectP(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: ........ + * Size: 00002C + */ +void Jam_CheckRunningCounter(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: 80010A60 + * Size: 00000C + */ +BOOL Jam_RegisterTrackCallback(TrackCallback callback) +{ + JAM_CALLBACK_FUNC = callback; + return TRUE; +} + +/* + * --INFO-- + * Address: ........ + * Size: 000038 + */ +void Jam_SetTrackExtPanPower(void) +{ + // UNUSED FUNCTION +} diff --git a/src/static/jaudio_PP/internal/jammain_2_reg.c_inc b/src/static/jaudio_PP/internal/jammain_2_reg.c_inc new file mode 100644 index 00000000..c8845c31 --- /dev/null +++ b/src/static/jaudio_PP/internal/jammain_2_reg.c_inc @@ -0,0 +1,435 @@ +/* + * --INFO-- + * Address: 8000F8C0 + * Size: 000020 + */ +u16 Extend8to16(u8 value) +{ + if (value & 0x80) { + return value + 0xFF00; + } + return value; +} + +/* + * --INFO-- + * Address: 8000F8E0 + * Size: 0001A8 + */ +void Jam_WriteTimeParam(seqp_* track, u8 controlByte) +{ + + s32 duration; + u8 paramIndex; + s16 targetValue; + MoveParam_* param; + + duration = 0; + paramIndex = __ByteRead(track); + + // Extract target value based on controlByte[3:2] + switch (controlByte & 0x0C) { + case 0x00: // Use register value + targetValue = track->regParam.reg[__ByteRead(track)]; + break; + case 0x04: // 8-bit immediate value + targetValue = __ByteRead(track); + break; + case 0x08: // 8-bit value shifted to high byte + targetValue = __ByteRead(track) << 8; + break; + case 0x0C: // 16-bit immediate value + targetValue = __WordRead(track); + break; + } + + // Determine time over which to interpolate the parameter + switch (controlByte & 0x03) { + case 0: // Immediate (no interpolation) + duration = -1; + break; + case 1: // Time from register + duration = track->regParam.reg[__ByteRead(track)]; + break; + case 2: // 8-bit immediate duration + duration = __ByteRead(track); + break; + case 3: // 16-bit immediate duration + duration = __WordRead(track); + break; + } + + param = &track->timedParam.move[paramIndex]; + param->targetValue = targetValue / 32768.0f; + + if (duration >= 0) { + param->duration = duration; + } + + if (param->duration <= 0.0f) { + param->currentValue = param->targetValue; + param->stepSize = 0.0f; + param->duration = 1.0f; + } else { + param->stepSize = (param->targetValue - param->currentValue) / param->duration; + } +} + +/* + * --INFO-- + * Address: 8000FAA0 + * Size: 0000AC + */ +void Jam_WriteRegDirect(seqp_* track, u8 index, u16 value) +{ + + u16 uVar1; + + switch (index) { + case 0: + case 1: + case 2: + value = value & 0xff; + uVar1 = Extend8to16(value); + break; + case 32: + case 33: + return; + case 34: + Jam_WriteRegDirect(track, 0, value >> 8); + uVar1 = value; + value = value & 0xff; + index = 1; + break; + default: + uVar1 = value; + break; + } + + track->regParam.reg[index] = value; + track->regParam.param.value = uVar1; +} + +/* + * --INFO-- + * Address: 8000FB60 + * Size: 000098 + */ +static u32 LoadTbl(seqp_* track, u32 ofs, u32 idx, u32 param_4) +{ + u32 result; + + switch (param_4) { + case 4: + result = __ByteReadOfs(track, ofs + idx); + break; + case 5: + idx = idx * 2; + result = __WordReadOfs(track, ofs + idx); + break; + case 6: + idx = idx * 2 + idx; // Roundabout way to multiply by 3. + result = __24ReadOfs(track, ofs + idx); + break; + case 7: + idx = idx * 4; + case 8: + result = __LongReadOfs(track, ofs + idx); + break; + } + return result; +} + +/* + * --INFO-- + * Address: 8000FC00 + * Size: 000484 + */ +void Jam_WriteRegParam(seqp_* track, u8 param_2) +{ + + s16 r30_newRegValue; // r30 + u8 r29_regIdx; // r29 + u16 r28; // r28 + u32 unaff_r27; // r27 + u32 r26; // r26 + u32 r25; // r25 + u32 unaff_r24; // r24 + s16 r23_oldRegValue; // r23 + + r26 = param_2 & 0xc; + r25 = param_2 & 3; + if ((param_2 & 0x0F) == 0x0B) { + r26 = 0; + r25 = 0xb; + } + if ((param_2 & 0x0F) == 0x0A) { + param_2 = __ByteRead(track); + r26 = param_2 & 0x0C; + r25 = 0xa; + unaff_r24 = (u8)(param_2 >> 4) + 4; + } + if ((param_2 & 0x0F) == 0x09) { + param_2 = __ByteRead(track); + r26 = param_2 & 0x0c; + r25 = param_2 & 0xf0; + if (r26 == 8) { + r26 = 0x10; + } + } + r29_regIdx = __ByteRead(track); + if (r25 == 0x0A) { + unaff_r27 = Jam_ReadReg32(track, __ByteRead(track)); + } + switch (r26) { + case 0: + r30_newRegValue = Jam_ReadRegDirect(track, __ByteRead(track)); + break; + case 4: + r30_newRegValue = __ByteRead(track); + break; + case 8: + r30_newRegValue = __ByteRead(track) << 8; + break; + case 12: + r30_newRegValue = __WordRead(track); + break; + case 16: + r30_newRegValue = -1; + } + + r23_oldRegValue = Jam_ReadRegDirect(track, r29_regIdx); + switch (r25) { + case 0x00: + break; + case 0x01: + if (r26 == 4) { + r30_newRegValue = Extend8to16(r30_newRegValue); + } + r30_newRegValue = r23_oldRegValue + r30_newRegValue; + break; + case 0x02: + unaff_r27 = r23_oldRegValue * r30_newRegValue; + Jam_WriteRegXY(track, unaff_r27); + return; + case 0x03: + track->regParam.param.value = r23_oldRegValue - r30_newRegValue; + return; + case 0x0B: + r30_newRegValue = r23_oldRegValue - r30_newRegValue; + break; + case 0x10: + if (r26 == 4) { + r30_newRegValue = Extend8to16(r30_newRegValue); + } + if (r30_newRegValue < 0) { + r30_newRegValue = (u16)r23_oldRegValue >> -r30_newRegValue; + } else { + r30_newRegValue = (u16)r23_oldRegValue << r30_newRegValue; + } + break; + case 0x20: + if (r26 == 4) { + r30_newRegValue = Extend8to16(r30_newRegValue); + } + if (r30_newRegValue < 0) { + r30_newRegValue = r23_oldRegValue >> -r30_newRegValue; + } else { + r30_newRegValue = r23_oldRegValue << r30_newRegValue; + } + break; + case 0x30: + r30_newRegValue = r23_oldRegValue & r30_newRegValue; + break; + case 0x40: + r30_newRegValue = r23_oldRegValue | r30_newRegValue; + break; + case 0x50: + r30_newRegValue = r23_oldRegValue ^ r30_newRegValue; + break; + case 0x60: + r30_newRegValue = -r23_oldRegValue; + break; + case 0x90: + unaff_r27 = GetRandom_s32(); + r30_newRegValue = unaff_r27 % (u16)r30_newRegValue; + break; + case 0xA: + unaff_r27 = LoadTbl(track, unaff_r27, r30_newRegValue, unaff_r24); + r30_newRegValue = (u16)unaff_r27; + break; + } + + switch (r29_regIdx) { + case 0: + case 1: + case 2: + r30_newRegValue = r30_newRegValue & 0xff; + r28 = Extend8to16(r30_newRegValue); + break; + case 0x21: + r29_regIdx = 6; + r30_newRegValue = track->regParam.param.bankNumber & 0xff00 | r30_newRegValue & 0x00ff; + break; + case 0x20: + r29_regIdx = 6; + r30_newRegValue = track->regParam.param.bankNumber & 0x00ff | r30_newRegValue << 8; + break; + case 0x2E: + r29_regIdx = 0xd; + r30_newRegValue = track->regParam.param.basePriority & 0xff00 | r30_newRegValue & 0x00ff; + break; + case 0x2F: + r29_regIdx = 0xd; + r30_newRegValue = track->regParam.param.basePriority & 0x00ff | r30_newRegValue << 8; + break; + case 0x22: + Jam_WriteRegDirect(track, 0, r30_newRegValue >> 8); + r30_newRegValue = r30_newRegValue & 0xff; + r28 = r30_newRegValue; + r29_regIdx = 1; + break; + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + track->regParam.param._20[r29_regIdx - 0x28] = unaff_r27; + return; + default: + r28 = r30_newRegValue; + break; + } + + track->regParam.reg[r29_regIdx] = r30_newRegValue; + track->regParam.param.value = r28; + + if (r29_regIdx == 6) { + Osc_Clear_Overwrite(track); + } + if (r29_regIdx == 7) { + track->updateFlags |= OuterParamFlag_Pitch; + } + if (r29_regIdx == 0xd) { + track->parentController.channelPriority = track->regParam.param.basePriority | 0x10000; + track->parentController.releaseTime = 0; + } +} + +/* + * --INFO-- + * Address: 800100A0 + * Size: 00016C + */ +u16 Jam_ReadRegDirect(seqp_* track, u8 regIdx) +{ + s16 result; + u16 regDirectLo; + u16 regDirectHi; + int i; + + switch (regIdx) { + case 0x20: + case 0x21: + result = track->regParam.param.bankNumber; + break; + case 0x22: + regDirectLo = Jam_ReadRegDirect(track, 1); + regDirectHi = Jam_ReadRegDirect(track, 0); + result = regDirectHi << 8 | regDirectLo; + break; + case 0x2C: + result = 0; + for (i = 15; i >= 0; --i) { + result = result << 1; // For some reason, `<<=` prevents `srawi`. + if (track->children[i] && track->children[i]->trackState) { + result |= 1; + } + } + break; + case 0x2D: + result = 0; + for (i = 7; i >= 0; --i) { + result = result << 1; // For some reason, `<<=` prevents `srawi`. + result |= (u8)CheckNoteStop(track, i); + } + break; + case 0x30: + if (track->callStackDepth == 0) { + result = 0; + } else { + result = track->loopCounters[track->callStackDepth - 1]; + } + break; + default: + result = track->regParam.reg[regIdx]; + break; + } + switch (regIdx) { + case 0x00: + case 0x01: + case 0x02: + case 0x21: + result = result & 0xff; + break; + case 0x20: + result = result >> 8; + break; + } + return result; +} + +/* + * --INFO-- + * Address: 80010220 + * Size: 000048 + */ +u32 Jam_ReadRegXY(seqp_* track) +{ + return (Jam_ReadRegDirect(track, 4) << 16) | Jam_ReadRegDirect(track, 5); +} + +/* + * --INFO-- + * Address: 80010280 + * Size: 00005C + */ +u32 Jam_ReadReg32(seqp_* track, u8 index) +{ + switch (index) { + case 40: + case 41: + case 42: + case 43: + return track->regParam.param._20[index - 40]; + case 35: + return Jam_ReadRegXY(track); + } + return Jam_ReadRegDirect(track, index); +} + +/* + * --INFO-- + * Address: 800102E0 + * Size: 000048 + */ +void Jam_WriteRegXY(seqp_* track, u32 param_2) +{ + u16 v = param_2 >> 16; + Jam_WriteRegDirect(track, 4, (u16)v); + u16 v2 = param_2; + Jam_WriteRegDirect(track, 5, (u16)v2); +} + +/* + * --INFO-- + * Address: 80010340 + * Size: 00003C + * Note: Equivalent to `JASTrack::exchangeRegisterValue` in later JAudio. + */ +u32 __ExchangeRegisterValue(seqp_* track, u8 param_2) +{ + if (param_2 < 64) { + return Jam_ReadReg32(track, param_2); + } + return track->trackPort[param_2 - 64].value; +} diff --git a/src/static/jaudio_PP/internal/jammain_2_update.c_inc b/src/static/jaudio_PP/internal/jammain_2_update.c_inc new file mode 100644 index 00000000..ccb6ee3a --- /dev/null +++ b/src/static/jaudio_PP/internal/jammain_2_update.c_inc @@ -0,0 +1,498 @@ +/* + * --INFO-- + * Address: 80010A80 + * Size: 00004C + */ +static f32 __PanCalc(f32 param_1, f32 param_2, f32 param_3, u8 param_4) +{ + f32 result; + + switch (param_4) { + case 0: + return param_1; + case 1: + return param_2; + case 2: + result = param_1 * (1.0f - param_3) + (param_2 * param_3); + } + return result; +} + +/* + * --INFO-- + * Address: 80010AE0 + * Size: 000320 + */ +void Jam_UpdateTrackAll(seqp_* track) +{ + f32 volumeValue; + f32 pitchCents; + f32 panValue; + f32 fxMixValue; + f32 dolbyValue; + f32 distance; + f32 parentDistance; + + f32 panScaled; + s8 pan8bit; + s8 panDelayLeft; + + size_t i; + + distance = track->regParam.param.arguments[3] / 32767.0f; + if (track->flags != 4) { + track->parentController.channelPriority = track->regParam.param.basePriority | 0x10000; + track->parentController.releaseTime = 0; + + panDelayLeft = 0; + panScaled = track->timedParam.inner._110.currentValue * 128.0f; + + OSf32tos8(&panScaled, &pan8bit); + if (pan8bit < 0) { + panDelayLeft = -pan8bit; + pan8bit = 0; + } + + track->parentController.maxDelay = 0x10; + track->parentController.masterLevels[0] = panDelayLeft; + track->parentController.masterLevels[1] = pan8bit; + + // Read base volume; if muted, force to zero + volumeValue = track->timedParam.inner.volume.currentValue; + if (track->isMuted > 0) { + volumeValue = 0.0f; + } + + // Convert pitch to cents, read pan/fxmix/dolby from timed parameters + pitchCents = Jam_PitchToCent(track->timedParam.inner.pitch.currentValue, track->regParam.param.pitchScale); + panValue = track->timedParam.inner.pan.currentValue; + fxMixValue = track->timedParam.inner.fxmix.currentValue; + dolbyValue = track->timedParam.inner.dolby.currentValue; + + if (track->outerParams) { + if (track->outerParams->flags & OuterParamFlag_Volume) { + volumeValue = volumeValue * track->outerParams->volume; + } + + if (track->outerParams->flags & OuterParamFlag_Pitch) { + pitchCents = pitchCents * track->outerParams->pitch; + } + + if (track->outerParams->flags & OuterParamFlag_Fxmix) { + fxMixValue = __PanCalc(fxMixValue, track->outerParams->fxMix, distance, track->panCalcTypes[1]); + } + + if (track->outerParams->flags & OuterParamFlag_Dolby) { + dolbyValue = __PanCalc(dolbyValue, track->outerParams->dolby, distance, track->panCalcTypes[2]); + } + + if (track->outerParams->flags & OuterParamFlag_Pan) { + panValue = __PanCalc(panValue, track->outerParams->pan, distance, track->panCalcTypes[0]); + } + } + + // If there is no parent or this track overrides its parent (trackFlags & 1), + // write the final values directly into the channel state + if (!track->parent || (track->flags & 1)) { + track->parentController.volume = volumeValue; + track->parentController.pitch = pitchCents; + track->parentController.pan = panValue; + track->parentController.fxmix = fxMixValue; + track->parentController.dolby = dolbyValue; + } else { + // Otherwise, combine with parent’s values using a second attenuation factor + parentDistance = track->regParam.param.arguments[4] / 32767.0f; + + track->parentController.volume = track->parent->parentController.volume * volumeValue; + track->parentController.pitch = track->parent->parentController.pitch * pitchCents; + track->parentController.pan + = __PanCalc(panValue, track->parent->parentController.pan, parentDistance, track->parentPanCalcTypes[0]); + track->parentController.fxmix + = __PanCalc(fxMixValue, track->parent->parentController.fxmix, parentDistance, track->parentPanCalcTypes[1]); + track->parentController.dolby + = __PanCalc(dolbyValue, track->parent->parentController.dolby, parentDistance, track->parentPanCalcTypes[2]); + + // If outerParams specify a custom FIR filter, copy those coefficients + if (track->outerParams && (track->outerParams->flags & OuterParamFlag_FIR8Filter)) { + for (i = 0; i < 8; ++i) { + track->parentController.firCoefficients[i] = track->outerParams->firCoefficients[i]; + } + + track->parentController.filterMode = 8; + } + + // Read inner IIR coefficients (normalized floats) and convert to 16-bit + for (i = 0; i < 4; ++i) { + track->parentController.iirCoefficients[i] = track->timedParam.inner.IIRs[i].currentValue * 32767.0f; + } + + track->parentController.filterMode |= 0x20; + track->parentController.distFilter = track->timedParam.inner.distFilter.currentValue * 32767.0f; + } + } +} + +/* + * --INFO-- + * Address: 80010E20 + * Size: 0004A8 + */ +void Jam_UpdateTrack(seqp_* track, u32 updateFlags) +{ + // A bizarre way the devs attempted to re-use some repeated AND operations in this function, + // which the compiler can already see and optimize in its own way, causes regalloc inflation. + u32 updateVolumeFlag; + u32 updatePitchFlag; + u32 updatePanFlag; + u32 updateFxMixFlag; + u32 updateDolbyFlag; + + f32 computedVolume; // f31 + f32 unaff_f30; // f30 + f32 unaff_f29; // f29 + f32 unaff_f28; // f28 + f32 unaff_f27; // f27 + f32 regionAttenuation; + f32 offset; + f32 dVar15_3; + + size_t i; + + // Used for `OSf32tos8` + f32 masterLevelF32; + s8 masterRight; + s8 masterLeft; + + regionAttenuation = track->regParam.param.arguments[3] / 32767.0f; + + if (track->flags != 0x04) { + + // Update master pan delay levels if requested + if (updateFlags & SEQTRACK_FLAG_MASTER_LEVEL) { + masterLeft = 0; + masterLevelF32 = track->timedParam.inner._110.currentValue * 128.0f; + OSf32tos8(&masterLevelF32, &masterRight); + if (masterRight < 0) { + masterLeft = -masterRight; + masterRight = 0; + } + track->parentController.masterLevels[0] = masterLeft; + track->parentController.masterLevels[1] = masterRight; + } + + // Tempo update (only if top-level track) + if (updateFlags & OuterParamFlag_Tempo && !track->parent) { + Jam_UpdateTempo(track); + } + + updateVolumeFlag = updateFlags & OuterParamFlag_Volume; + if (updateVolumeFlag) { + computedVolume = track->timedParam.inner.volume.currentValue; + if (track->isMuted != 0) { + computedVolume = 0.0f; + } + + if (track->outerParams && (track->outerParams->flags & OuterParamFlag_Volume)) { + computedVolume *= track->outerParams->volume; + } + + if (track->isPaused && (track->pauseStatus & 1)) { + computedVolume *= track->timedParam.inner._100.currentValue; + } + } + + updatePitchFlag = updateFlags & OuterParamFlag_Pitch; + if (updatePitchFlag) { + unaff_f30 = Jam_PitchToCent((track->timedParam).inner.pitch.currentValue, track->regParam.param.pitchScale); + if (track->outerParams && ((track->outerParams->flags & OuterParamFlag_Pitch) != 0)) { + unaff_f30 = (unaff_f30 * track->outerParams->pitch); + } + } + + updatePanFlag = updateFlags & OuterParamFlag_Pan; + if (updatePanFlag) { + unaff_f29 = (track->timedParam).inner.pan.currentValue; + if (track->outerParams && ((track->outerParams->flags & OuterParamFlag_Pan) != 0)) { + unaff_f29 = __PanCalc(unaff_f29, track->outerParams->pan, regionAttenuation, track->panCalcTypes[0]); + } + } + + updateFxMixFlag = updateFlags & OuterParamFlag_Fxmix; + if (updateFxMixFlag) { + unaff_f28 = (track->timedParam).inner.fxmix.currentValue; + if (track->outerParams && ((track->outerParams->flags & OuterParamFlag_Fxmix) != 0)) { + unaff_f28 = __PanCalc(unaff_f28, track->outerParams->fxMix, regionAttenuation, track->panCalcTypes[1]); + } + } + + updateDolbyFlag = updateFlags & OuterParamFlag_Dolby; + if (updateDolbyFlag) { + unaff_f27 = (track->timedParam).inner.dolby.currentValue; + if (track->outerParams && ((track->outerParams->flags & OuterParamFlag_Dolby) != 0)) { + unaff_f27 = __PanCalc(unaff_f27, track->outerParams->dolby, regionAttenuation, track->panCalcTypes[2]); + } + } + + // IIR flag is set + if (updateFlags & OuterParamFlag_IIRFilter) { + for (i = 0; i < 4; ++i) { + track->parentController.iirCoefficients[i] = track->timedParam.inner.IIRs[i].currentValue * 32767.0f; + } + + track->parentController.filterMode |= 0x20; + } + + if (track->outerParams) { + if (updateFlags & OuterParamFlag_FIR8Filter && (track->outerParams->flags & OuterParamFlag_FIR8Filter)) { + for (i = 0; i < 8; ++i) { + track->parentController.firCoefficients[i] = track->outerParams->firCoefficients[i]; + } + + track->parentController.filterMode = (track->parentController.filterMode & 0x20) + 8; + } + } + + if (updateFlags & OuterParamFlag_DistFilt) { + track->parentController.distFilter = track->timedParam.inner.distFilter.currentValue * 32767.0f; + } + + for (i = 0; i < 2; ++i) { + if (track->oscillatorRouting[i] == 0x0E) { + offset = Bank_OscToOfs(&track->oscillators[i], &track->oscillatorParams[i]); + switch (track->oscillators[i].mode) { + case 1: + unaff_f30 = unaff_f30 * offset; + break; + case 0: + computedVolume = computedVolume * offset; + break; + case 2: + unaff_f29 = unaff_f29 * offset; + break; + case 3: + unaff_f28 = unaff_f28 * offset; + break; + case 4: + unaff_f27 = unaff_f27 * offset; + break; + } + } + } + if (!track->parent || ((track->flags & 1) != 0)) { + if (updateVolumeFlag) { + track->parentController.volume = computedVolume; + } + if (updatePitchFlag) { + track->parentController.pitch = unaff_f30; + } + if (updatePanFlag) { + track->parentController.pan = unaff_f29; + } + if (updateFxMixFlag) { + track->parentController.fxmix = unaff_f28; + } + if (updateDolbyFlag != 0) { + track->parentController.dolby = unaff_f27; + } + } else { + dVar15_3 = track->regParam.param.arguments[4] / 32767.0f; + if (updateVolumeFlag) { + track->parentController.volume = track->parent->parentController.volume * computedVolume; + } + if (updatePitchFlag) { + track->parentController.pitch = track->parent->parentController.pitch * unaff_f30; + } + if (updatePanFlag) { + track->parentController.pan + = __PanCalc(unaff_f29, track->parent->parentController.pan, dVar15_3, track->parentPanCalcTypes[0]); + } + if (updateFxMixFlag) { + track->parentController.fxmix + = __PanCalc(unaff_f28, track->parent->parentController.fxmix, dVar15_3, track->parentPanCalcTypes[1]); + } + if (updateDolbyFlag) { + track->parentController.dolby + = __PanCalc(unaff_f27, track->parent->parentController.dolby, dVar15_3, track->parentPanCalcTypes[2]); + } + } + } +} + +/* + * --INFO-- + * Address: 800112E0 + * Size: 000104 + */ +void Jam_UpdateTempo(seqp_* track) +{ + size_t i; + + size_t* REF_i; + + if (!track->parent) { + track->tempoFactor = (float)track->timeBase * (float)track->tempo / (JAC_DAC_RATE * 60.0f / 80.0f); + if ((track->outerParams->flags & OuterParamFlag_Tempo) != 0) { + track->tempoFactor = track->tempoFactor * track->outerParams->tempo; + } + } else { + track->tempoFactor = track->parent->tempoFactor; + track->timeBase = track->parent->timeBase; + } + for (i = 0; i < 16; ++i) { + REF_i = &i; + if (track->children[i] && track->children[i]->trackState) { + Jam_UpdateTempo(track->children[i]); + } + } +} + +/* + * --INFO-- + * Address: 80011400 + * Size: 0000CC + */ +void Jam_MuteTrack(seqp_* track, u8 param_2) +{ + u32 i; + u16 mask; + + if (track->parent) { + track->isMuted = track->parent->isMuted | param_2; + mask = 1 << (track->trackId & 0xf); + if (!param_2) { + track->parent->childMuteMask &= ~mask; + } else { + track->parent->childMuteMask |= mask; + } + } else { + track->isMuted = param_2; + } + track->updateFlags |= OuterParamFlag_Volume; + if (track->isMuted && (track->pauseStatus & 0x20)) { + for (i = 0; i < 8; ++i) { + NoteOFF_R(track, (u8)i, 10); + }; + } +} + +/* + * --INFO-- + * Address: ........ + * Size: 0000B4 + */ +void Jam_MuteChildTracks(void) +{ + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: 800114E0 + * Size: 00013C + */ +void Jam_PauseTrack(seqp_* track, u8 param_2) +{ + size_t i; + jc_* pjVar1; + + size_t* REF_i; + + track->isPaused = TRUE; + if (track->pauseStatus & 0x01) { + track->updateFlags |= OuterParamFlag_Volume; + } + if (track->pauseStatus & 0x04) { + for (i = 0; i < 8; ++i) { + REF_i = &i; + NoteOFF_R(track, i, 10); + } + } + if (track->pauseStatus & 0x08) { + for (i = 0; i < 8; ++i) { + pjVar1 = track->channels[i]; + if (pjVar1 && track->activeSoundIds[i] == pjVar1->channelId) { + UpdatePause_1Shot(pjVar1, 1); + } + } + } + Jam_SetInterrupt(track, 0); + if (param_2 == TRUE) { + for (i = 0; i < 16; ++i) { + if (track->children[i] && track->children[i]->trackState) { + Jam_PauseTrack(track->children[i], 1); + } + } + } +} + +/* + * --INFO-- + * Address: 80011620 + * Size: 0000EC + */ +void Jam_UnPauseTrack(seqp_* track, u8 param_2) +{ + size_t i; + jc_* pjVar1; + + size_t* REF_i; + + track->isPaused = FALSE; + track->updateFlags |= OuterParamFlag_Volume; + for (i = 0; i < 8; ++i) { + REF_i = &i; + pjVar1 = track->channels[i]; + if (pjVar1 && track->activeSoundIds[i] == pjVar1->channelId) { + UpdatePause_1Shot(pjVar1, 0); + } + } + Jam_SetInterrupt(track, 1); + if (param_2 == TRUE) { + for (i = 0; i < 16; ++i) { + if (track->children[i] && track->children[i]->trackState) { + Jam_UnPauseTrack(track->children[i], 1); + } + } + } +} + +/* + * --INFO-- + * Address: 80011720 + * Size: 000028 + * Note: Equivalent to `JASIntrMgr::request` in later JAudio. + */ +void Jam_SetInterrupt(seqp_* track, u16 interrupt) +{ + if (track->interruptEnable & (1 << interrupt)) { + track->interruptPending |= (1 << interrupt); + } +} + +/* + * --INFO-- + * Address: 80011760 + * Size: 000090 + */ +BOOL Jam_TryInterrupt(seqp_* track) +{ + u32 mask; + int i; + + if (track->interruptActive) { + return FALSE; + } + for (i = 0; i < 8; ++i) { + mask = 1 << i; + if ((track->interruptEnable & mask) && (track->interruptPending & mask)) { + track->savedProgramCounter = track->programCounter; + track->programCounter = track->interruptAddresses[i]; + track->interruptActive = mask; + track->_3CC = track->waitTimer; + track->waitTimer = 0; + track->interruptPending ^= mask; + return TRUE; + } + } + return FALSE; +} diff --git a/src/static/jaudio_PP/internal/memory.c b/src/static/jaudio_PP/internal/memory.c index fa122383..4152ff4b 100644 --- a/src/static/jaudio_PP/internal/memory.c +++ b/src/static/jaudio_PP/internal/memory.c @@ -811,7 +811,7 @@ void Nas_SetBPFilter(s16* a, s32 b, s32 c) { Nas_SetLPFilter(a, b); return; } else if (b == 0) { - Nas_SetLPFilter(a, c); + Nas_SetHPFilter(a, c); return; } k = 0; @@ -1005,24 +1005,28 @@ void __Nas_MemoryReconfig() { } /*0x2A18*/ AG.num_abi_cmds_max = 8; - /*0x0002*/ AG._0002 = spec->_14; + /*0x0002*/ AG._0002 = (s16)spec->_14; - s32 tmp = AG.audio_params.updates_per_frame; - /*0x28BC*/ AG.max_tempo = ((((60.0f * 1000.0f * AUDIO_TATUMS_PER_BEAT) * tmp) / AGC.timeBase) / AG._29D8) / 1.04613; + /*0x28BC*/ AG.max_tempo = (int)(((((60.0f * 1000.0f * AUDIO_TATUMS_PER_BEAT) * (s16)AG.audio_params.updates_per_frame) / AGC.timeBase) / AG._29D8) / 1.04613); - /*0x2894*/ AG._2894 = (f32)AG.refresh_rate * (f32)tmp / AG.audio_params.ai_sampling_frequency / AG.max_tempo; + /*0x2894*/ AG._2894 = (f32)AG.refresh_rate * (f32)AG.audio_params.updates_per_frame / AG.audio_params.ai_sampling_frequency / (s16)AG.max_tempo; - /*0x286C*/ AG.audio_params.spec = spec->_04; /*0x2894*/ AG._2894 = AG.refresh_rate; - /*0x2894*/ AG._2894 *= tmp; + /*0x2894*/ AG._2894 *= AG.audio_params.updates_per_frame; /*0x2894*/ AG._2894 /= AG.audio_params.ai_sampling_frequency; - /*0x2894*/ AG._2894 /= AG.max_tempo; - /*0x2876*/ AG.audio_params.num_samples_per_frame_min *= AG.audio_params.spec; - /*0x2878*/ AG.audio_params.updates_per_frame *= AG.audio_params.spec; - /*0x2872*/ AG.audio_params.num_samples_per_frame_target *= AG.audio_params.spec; - /*0x2874*/ AG.audio_params.num_samples_per_frame_max *= AG.audio_params.spec; - - if (AG.audio_params.spec > 1) { + /*0x2894*/ AG._2894 /= (s16)AG.max_tempo; + + (void)(f32)AG.refresh_rate; + (void)(f32)AG.audio_params.updates_per_frame; + (void)(f32)AG.audio_params.ai_sampling_frequency; + + /*0x286C*/ AG.audio_params.spec = (s16)spec->_04; + /*0x2872*/ AG.audio_params.num_samples_per_frame_target *= (s16)AG.audio_params.spec; + /*0x2874*/ AG.audio_params.num_samples_per_frame_max *= (s16)AG.audio_params.spec; + /*0x2876*/ AG.audio_params.num_samples_per_frame_min *= (s16)AG.audio_params.spec; + /*0x2878*/ AG.audio_params.updates_per_frame *= (s16)AG.audio_params.spec; + + if ((s16)AG.audio_params.spec > 1) { /*0x2874*/ AG.audio_params.num_samples_per_frame_max -= 0x10; } // int c = (a + b); diff --git a/src/static/jaudio_PP/internal/oneshot.c b/src/static/jaudio_PP/internal/oneshot.c index 3b81041c..ac9cb21e 100644 --- a/src/static/jaudio_PP/internal/oneshot.c +++ b/src/static/jaudio_PP/internal/oneshot.c @@ -18,456 +18,11 @@ Osc_ PERC_ENV = { 0, 1.0f, 0, 0, 1.0f, 0 }; Osc_ OSC_ENV = { 0, 1.0f, 0, OSC_REL, 1.0f, 0 }; u8 polys_table[] = { 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32 }; -/* - * --INFO-- - * Address: 80015140 - * Size: 000034 - */ -static u8 __GetTrigger(jc_* jc, u8 n) -{ - switch (n) { - case 1: - return jc->velocity; - case 2: - return jc->note; - } - - return 0; -} - -/* - * --INFO-- - * Address: 80015180 - * Size: 000028 - */ -static f32 __Clamp01(f32 val) -{ - if (val < 0.0f) { - return 0.0f; - } - if (val > 1.0f) { - return 1.0f; - } - return val; -} - -/* - * --INFO-- - * Address: 800151C0 - * Size: 000054 - */ -static void __Clamp01InitPan(jc_* jc) -{ - for (u32 i = 1; i < 3; i++) { - jc->panMatrices[i].values[0] = __Clamp01(jc->panMatrices[i].values[0]); - } -} - -/* - * --INFO-- - * Address: 80015220 - * Size: 000068 - */ -static void __DoEffect(jc_* jc, u8 id, f32 val) -{ - switch (id) { - case 1: - jc->currentPitch *= val; - break; - case 0: - jc->currentVolume *= val; - break; - case 2: - jc->panMatrices[1].values[1] = val; - break; - case 3: - jc->panMatrices[2].values[1] = val; - break; - case 4: - jc->panMatrices[3].values[1] = val; - break; - } -} - -/* - * --INFO-- - * Address: 800152A0 - * Size: 000138 - */ -static void EffecterInit(jc_* jc, Inst_* inst) -{ - jc->pitchModifier = 1.0f; - jc->volumeModifier = 1.0f; - jc->panMatrices[1].values[1] = 0.5f; - jc->panMatrices[2].values[1] = 0.0f; - jc->panMatrices[3].values[1] = 0.0f; - for (u32 i = 0; i < 2; i++) { - if (inst->mSensors[i]) { - u8 trigger = __GetTrigger(jc, inst->mSensors[i]->type); - f32 sense = Bank_SenseToOfs(inst->mSensors[i], trigger); - f32* REF_sense = &sense; - __DoEffect(jc, inst->mSensors[i]->id, sense); - } - - if (inst->mEffects[i]) { - f32 r = Bank_RandToOfs(inst->mEffects[i]); - __DoEffect(jc, inst->mEffects[i]->id, r); - } - - if (inst->mOscillators[i]) { - jc->mOscBuffers[i].state = 1; - jc->mOscillators[i] = inst->mOscillators[i]; - f32 ofs = Bank_OscToOfs(jc->mOscillators[i], &jc->mOscBuffers[i]); - DoEffectOsc(jc, jc->mOscillators[i]->mode, ofs); - } else { - jc->mOscillators[i] = NULL; - } - } - __Clamp01InitPan(jc); -} - -/* - * --INFO-- - * Address: 800153E0 - * Size: 0000D0 - */ -static void EffecterInit_Perc(jc_* jc, Pmap_* pmap, u16 id) -{ - jc->pitchModifier = 1.0f; - jc->volumeModifier = 1.0f; - jc->panMatrices[1].values[1] = 0.5f; - jc->panMatrices[2].values[1] = 0.0f; - jc->panMatrices[3].values[1] = 0.0f; - - // PERC instruments only have rand and not osc - Pmap_* map; - for (u32 i = 0; i < 2; i++) { - map = (Pmap_*)((int*)pmap + i + 2); - if (map->_00) { - f32 r = Bank_RandToOfs(map->_00); - f32* REF_r = &r; - __DoEffect(jc, map->_00->id, r); - } - - jc->mOscillators[i] = NULL; - } - jc->mOscillators[0] = &PERC_ENV; - jc->mOscBuffers[0].state = TRUE; - Bank_OscToOfs(jc->mOscillators[0], &jc->mOscBuffers[0]); - jc->mOscBuffers[0].releaseParam = id; - __Clamp01InitPan(jc); -} - -/* - * --INFO-- - * Address: 800154C0 - * Size: 00007C - */ -static void EffecterInit_Osc(jc_* jc) -{ - jc->pitchModifier = 1.0f; - jc->volumeModifier = 1.0f; - jc->panMatrices[1].values[1] = 0.5f; - jc->panMatrices[2].values[1] = 0.0f; - jc->panMatrices[3].values[1] = 0.0f; - - for (u32 i = 0; i < 2; i++) { - jc->mOscillators[i] = NULL; - } - - jc->mOscillators[0] = &OSC_ENV; - jc->mOscBuffers[0].state = TRUE; - Bank_OscToOfs(jc->mOscillators[0], &jc->mOscBuffers[0]); -} - -/* - * --INFO-- - * Address: 80015540 - * Size: 00006C - */ -void Effecter_Overwrite_1ShotD(jc_* jc, Osc_* osc, u32 id) -{ - if (id < 4) { - jc->mOscBuffers[id].state = TRUE; - jc->mOscillators[id] = osc; - DoEffectOsc(jc, jc->mOscillators[id]->mode, Bank_OscToOfs(jc->mOscillators[id], &jc->mOscBuffers[id])); - } -} - -/* - * --INFO-- - * Address: ........ - * Size: 000060 - */ -void Effecter_Overwrite_1Shot(jc_* jc, Osc_* osc1, Osc_* osc2) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: 800155C0 - * Size: 00010C - */ -static jc_* __Oneshot_Play_Start(jcs_* jcs, jc_* jc, u32 id) -{ - BOOL play; - - if (id == 0) { - id = -1; - } - jc->playId = id; - jc->savedPlayId = jc->playId; - jc->updateCallback = Jesus1Shot_Update; - jc->dspChannel = AllocDSPchannel(0, (u32)jc); - - if (jc->dspChannel == NULL) { - play = CheckLogicalChannel(jc); - } else { - play = PlayLogicalChannel(jc); - } - - if (jc->dspChannel == NULL && play == TRUE) { - if (Add_WaitDSPChannel(jc) == TRUE) { - List_AddChannelTail(&jcs->waitingChannels, jc); - return jc; - } else { - List_AddChannelTail(&jcs->freeChannels, jc); - return NULL; - } - } else if (play == FALSE) { - DeAllocDSPchannel(jc->dspChannel, (u32)jc); - jc->dspChannel = NULL; - List_AddChannelTail(&jcs->freeChannels, jc); - return NULL; - } else { - List_AddChannelTail(&jcs->activeChannels, jc); - } - return jc; -} - -/* - * --INFO-- - * Address: 800156E0 - * Size: 000154 - */ -static jc_* __Oneshot_GetLogicalChannel(jcs_* jcs, CtrlWave_* wave) -{ - if (wave && wave->_0C == NULL) { - return FALSE; - } - - jc_* chan = List_GetChannel(&jcs->freeChannels); - jc_* chan2; - jc_** REF_chan2 = &chan2; - if (chan == NULL) { - - if (FixAllocChannel(jcs, 1) == FALSE) { - return 0; - } - jcs->chanAllocCount++; - chan = List_GetChannel(&jcs->freeChannels); - if (chan == NULL) { - return 0; - } - - if (jcs->voiceStealingMode == 1) { - chan2 = List_GetChannel(&jcs->releasingChannels); - if (chan2 == NULL) { - chan2 = List_GetChannel(&jcs->activeChannels); - if (chan2) { - List_CountChannel(&jcs->waitingChannels); - } - } - - if (chan2) { - chan2->mOscBuffers[0].state = 6; - List_AddChannel(&jcs->waitingChannels, chan2); - if (chan2->dspChannel) { - ForceStopDSPchannel(chan2->dspChannel); - } - } - } - } - Channel_Init(chan); - if (wave) { - chan->waveData = (Wave_*)wave->_34; - chan->_14 = wave->_0C; - chan->logicalChanType = 0; - } - chan->_18 = 0; - UpdatePanPower_1Shot(chan, 1.0f, 1.0f, 1.0f, 1.0f); - return chan; -} - -/* - * --INFO-- - * Address: 80015840 - * Size: 000044 - */ -Perc_* PercRead(u32 a1, u32 a2) -{ - Bank_* bank = Bank_Get(a1); - if (bank == NULL) { - return NULL; - } - - return Bank_PercChange(bank, a2); -} - -/* - * --INFO-- - * Address: 800158A0 - * Size: 000044 - */ -Inst_* InstRead(u32 a1, u32 a2) -{ - - Bank_* bank = Bank_Get(a1); - if (bank == NULL) { - return NULL; - } - - return Bank_InstChange(bank, a2); -} - -/* - * --INFO-- - * Address: 80015900 - * Size: 00002C - */ -Vmap_* VmapRead(Inst_* inst, u8 a1, u8 a2) -{ - Vmap_* map = (Vmap_*)Bank_GetInstVmap(inst, a1, a2); - return !map ? NULL : map; -} - -/* - * --INFO-- - * Address: 80015940 - * Size: 000010 - */ -static void __Oneshot_WavePause(jc_* jc, u8 a) -{ - jc->pauseFlag = a; - jc->toFlush = 1; -} - -/* - * --INFO-- - * Address: 80015960 - * Size: 00014C - */ -static BOOL __Oneshot_StartMonoPolyCheck(jc_* jc, u32 id) -{ - jcs_* mgr = jc->mMgr; - jc_* chan = mgr->activeChannels; - u32 index = 0; - u8 flag = id >> 0x18; - u8 poly = polys_table[flag & 0xf]; - - - if (poly == 0) { - return TRUE; - } - - while (TRUE) { - if (chan == NULL) { - break; - } - - if (chan->soundId == id) { - if (flag & 0x20) { - index++; - } else { - chan->polyphonyCounter++; - if (chan->polyphonyCounter == poly) { - if (flag & 0x10) { - ForceStopLogicalChannel(chan); - } else { - __Oneshot_WavePause(chan, 1); - } - } - } - } - chan = (jc_*)chan->mNext; - } - - chan = mgr->releasingChannels; - while (TRUE) { - if (chan == NULL) { - break; - } - - if (chan->soundId == id) { - if (flag & 0x20) { - index++; - } else { - chan->polyphonyCounter++; - if (chan->polyphonyCounter == poly) { - ForceStopLogicalChannel(chan); - } - } - } - - chan = (jc_*)chan->mNext; - } - - if (flag & 0x20) { - jc->polyphonyCounter = index; - if (index < poly) { - return TRUE; - } - return FALSE; - } - - jc->polyphonyCounter = 0; - return TRUE; -} - -/* - * --INFO-- - * Address: 80015AC0 - * Size: 0000E8 - */ -static void __Oneshot_StopMonoPolyCheck(jc_* jc, u32 id) -{ - jc_* chan; - u8 poly; - - chan = jc->mMgr->activeChannels; - poly = polys_table[id >> 0x18 & 0xf]; - - if (id && poly) { - - while (TRUE) { - if (chan == NULL) { - break; - } - - int flag = id >> 0x18 & 0x20; - if (chan->soundId == id) { - if (flag) { - if (chan->polyphonyCounter > jc->polyphonyCounter) { - chan->polyphonyCounter--; - if (chan->polyphonyCounter == poly - 1) { - __Oneshot_WavePause(chan, 0); - } - } - } else { - if (chan->polyphonyCounter > jc->polyphonyCounter) { - chan->polyphonyCounter--; - if (chan->polyphonyCounter < poly) { - __Oneshot_WavePause(chan, 0); - } - } - } - } - - chan = (jc_*)chan->mNext; - } - } -} +#include "../src/static/jaudio_PP/internal/oneshot_effecter.c_inc" +#include "../src/static/jaudio_PP/internal/oneshot_playstart.c_inc" +#include "../src/static/jaudio_PP/internal/oneshot_getchannel.c_inc" +#include "../src/static/jaudio_PP/internal/oneshot_instread.c_inc" +#include "../src/static/jaudio_PP/internal/oneshot_monopoly.c_inc" /* * --INFO-- diff --git a/src/static/jaudio_PP/internal/oneshot_effecter.c_inc b/src/static/jaudio_PP/internal/oneshot_effecter.c_inc new file mode 100644 index 00000000..78f4634a --- /dev/null +++ b/src/static/jaudio_PP/internal/oneshot_effecter.c_inc @@ -0,0 +1,185 @@ +/* + * --INFO-- + * Address: 80015140 + * Size: 000034 + */ +static u8 __GetTrigger(jc_* jc, u8 n) +{ + switch (n) { + case 1: + return jc->velocity; + case 2: + return jc->note; + } + + return 0; +} + +/* + * --INFO-- + * Address: 80015180 + * Size: 000028 + */ +static f32 __Clamp01(f32 val) +{ + if (val < 0.0f) { + return 0.0f; + } + if (val > 1.0f) { + return 1.0f; + } + return val; +} + +/* + * --INFO-- + * Address: 800151C0 + * Size: 000054 + */ +static void __Clamp01InitPan(jc_* jc) +{ + for (u32 i = 1; i < 3; i++) { + jc->panMatrices[i].values[0] = __Clamp01(jc->panMatrices[i].values[0]); + } +} + +/* + * --INFO-- + * Address: 80015220 + * Size: 000068 + */ +static void __DoEffect(jc_* jc, u8 id, f32 val) +{ + switch (id) { + case 1: + jc->currentPitch *= val; + break; + case 0: + jc->currentVolume *= val; + break; + case 2: + jc->panMatrices[1].values[1] = val; + break; + case 3: + jc->panMatrices[2].values[1] = val; + break; + case 4: + jc->panMatrices[3].values[1] = val; + break; + } +} + +/* + * --INFO-- + * Address: 800152A0 + * Size: 000138 + */ +static void EffecterInit(jc_* jc, Inst_* inst) +{ + jc->pitchModifier = 1.0f; + jc->volumeModifier = 1.0f; + jc->panMatrices[1].values[1] = 0.5f; + jc->panMatrices[2].values[1] = 0.0f; + jc->panMatrices[3].values[1] = 0.0f; + for (u32 i = 0; i < 2; i++) { + if (inst->mSensors[i]) { + u8 trigger = __GetTrigger(jc, inst->mSensors[i]->type); + f32 sense = Bank_SenseToOfs(inst->mSensors[i], trigger); + f32* REF_sense = &sense; + __DoEffect(jc, inst->mSensors[i]->id, sense); + } + + if (inst->mEffects[i]) { + f32 r = Bank_RandToOfs(inst->mEffects[i]); + __DoEffect(jc, inst->mEffects[i]->id, r); + } + + if (inst->mOscillators[i]) { + jc->mOscBuffers[i].state = 1; + jc->mOscillators[i] = inst->mOscillators[i]; + f32 ofs = Bank_OscToOfs(jc->mOscillators[i], &jc->mOscBuffers[i]); + DoEffectOsc(jc, jc->mOscillators[i]->mode, ofs); + } else { + jc->mOscillators[i] = NULL; + } + } + __Clamp01InitPan(jc); +} + +/* + * --INFO-- + * Address: 800153E0 + * Size: 0000D0 + */ +static void EffecterInit_Perc(jc_* jc, Pmap_* pmap, u16 id) +{ + jc->pitchModifier = 1.0f; + jc->volumeModifier = 1.0f; + jc->panMatrices[1].values[1] = 0.5f; + jc->panMatrices[2].values[1] = 0.0f; + jc->panMatrices[3].values[1] = 0.0f; + + // PERC instruments only have rand and not osc + Pmap_* map; + for (u32 i = 0; i < 2; i++) { + map = (Pmap_*)((int*)pmap + i + 2); + if (map->_00) { + f32 r = Bank_RandToOfs(map->_00); + f32* REF_r = &r; + __DoEffect(jc, map->_00->id, r); + } + + jc->mOscillators[i] = NULL; + } + jc->mOscillators[0] = &PERC_ENV; + jc->mOscBuffers[0].state = TRUE; + Bank_OscToOfs(jc->mOscillators[0], &jc->mOscBuffers[0]); + jc->mOscBuffers[0].releaseParam = id; + __Clamp01InitPan(jc); +} + +/* + * --INFO-- + * Address: 800154C0 + * Size: 00007C + */ +static void EffecterInit_Osc(jc_* jc) +{ + jc->pitchModifier = 1.0f; + jc->volumeModifier = 1.0f; + jc->panMatrices[1].values[1] = 0.5f; + jc->panMatrices[2].values[1] = 0.0f; + jc->panMatrices[3].values[1] = 0.0f; + + for (u32 i = 0; i < 2; i++) { + jc->mOscillators[i] = NULL; + } + + jc->mOscillators[0] = &OSC_ENV; + jc->mOscBuffers[0].state = TRUE; + Bank_OscToOfs(jc->mOscillators[0], &jc->mOscBuffers[0]); +} + +/* + * --INFO-- + * Address: 80015540 + * Size: 00006C + */ +void Effecter_Overwrite_1ShotD(jc_* jc, Osc_* osc, u32 id) +{ + if (id < 4) { + jc->mOscBuffers[id].state = TRUE; + jc->mOscillators[id] = osc; + DoEffectOsc(jc, jc->mOscillators[id]->mode, Bank_OscToOfs(jc->mOscillators[id], &jc->mOscBuffers[id])); + } +} + +/* + * --INFO-- + * Address: ........ + * Size: 000060 + */ +void Effecter_Overwrite_1Shot(jc_* jc, Osc_* osc1, Osc_* osc2) +{ + // UNUSED FUNCTION +} diff --git a/src/static/jaudio_PP/internal/oneshot_getchannel.c_inc b/src/static/jaudio_PP/internal/oneshot_getchannel.c_inc new file mode 100644 index 00000000..299460f1 --- /dev/null +++ b/src/static/jaudio_PP/internal/oneshot_getchannel.c_inc @@ -0,0 +1,53 @@ +/* + * --INFO-- + * Address: 800156E0 + * Size: 000154 + */ +static jc_* __Oneshot_GetLogicalChannel(jcs_* jcs, CtrlWave_* wave) +{ + if (wave && wave->_0C == NULL) { + return FALSE; + } + + jc_* chan = List_GetChannel(&jcs->freeChannels); + jc_* chan2; + jc_** REF_chan2 = &chan2; + if (chan == NULL) { + + if (FixAllocChannel(jcs, 1) == FALSE) { + return 0; + } + jcs->chanAllocCount++; + chan = List_GetChannel(&jcs->freeChannels); + if (chan == NULL) { + return 0; + } + + if (jcs->voiceStealingMode == 1) { + chan2 = List_GetChannel(&jcs->releasingChannels); + if (chan2 == NULL) { + chan2 = List_GetChannel(&jcs->activeChannels); + if (chan2) { + List_CountChannel(&jcs->waitingChannels); + } + } + + if (chan2) { + chan2->mOscBuffers[0].state = 6; + List_AddChannel(&jcs->waitingChannels, chan2); + if (chan2->dspChannel) { + ForceStopDSPchannel(chan2->dspChannel); + } + } + } + } + Channel_Init(chan); + if (wave) { + chan->waveData = (Wave_*)wave->_34; + chan->_14 = wave->_0C; + chan->logicalChanType = 0; + } + chan->_18 = 0; + UpdatePanPower_1Shot(chan, 1.0f, 1.0f, 1.0f, 1.0f); + return chan; +} diff --git a/src/static/jaudio_PP/internal/oneshot_instread.c_inc b/src/static/jaudio_PP/internal/oneshot_instread.c_inc new file mode 100644 index 00000000..f68b04b9 --- /dev/null +++ b/src/static/jaudio_PP/internal/oneshot_instread.c_inc @@ -0,0 +1,41 @@ +/* + * --INFO-- + * Address: 80015840 + * Size: 000044 + */ +Perc_* PercRead(u32 a1, u32 a2) +{ + Bank_* bank = Bank_Get(a1); + if (bank == NULL) { + return NULL; + } + + return Bank_PercChange(bank, a2); +} + +/* + * --INFO-- + * Address: 800158A0 + * Size: 000044 + */ +Inst_* InstRead(u32 a1, u32 a2) +{ + + Bank_* bank = Bank_Get(a1); + if (bank == NULL) { + return NULL; + } + + return Bank_InstChange(bank, a2); +} + +/* + * --INFO-- + * Address: 80015900 + * Size: 00002C + */ +Vmap_* VmapRead(Inst_* inst, u8 a1, u8 a2) +{ + Vmap_* map = (Vmap_*)Bank_GetInstVmap(inst, a1, a2); + return !map ? NULL : map; +} diff --git a/src/static/jaudio_PP/internal/oneshot_monopoly.c_inc b/src/static/jaudio_PP/internal/oneshot_monopoly.c_inc new file mode 100644 index 00000000..d0cb04f9 --- /dev/null +++ b/src/static/jaudio_PP/internal/oneshot_monopoly.c_inc @@ -0,0 +1,126 @@ +/* + * --INFO-- + * Address: 80015940 + * Size: 000010 + */ +static void __Oneshot_WavePause(jc_* jc, u8 a) +{ + jc->pauseFlag = a; + jc->toFlush = 1; +} + +/* + * --INFO-- + * Address: 80015960 + * Size: 00014C + */ +static BOOL __Oneshot_StartMonoPolyCheck(jc_* jc, u32 id) +{ + jcs_* mgr = jc->mMgr; + jc_* chan = mgr->activeChannels; + u32 index = 0; + u8 flag = id >> 0x18; + u8 poly = polys_table[flag & 0xf]; + + + if (poly == 0) { + return TRUE; + } + + while (TRUE) { + if (chan == NULL) { + break; + } + + if (chan->soundId == id) { + if (flag & 0x20) { + index++; + } else { + chan->polyphonyCounter++; + if (chan->polyphonyCounter == poly) { + if (flag & 0x10) { + ForceStopLogicalChannel(chan); + } else { + __Oneshot_WavePause(chan, 1); + } + } + } + } + chan = (jc_*)chan->mNext; + } + + chan = mgr->releasingChannels; + while (TRUE) { + if (chan == NULL) { + break; + } + + if (chan->soundId == id) { + if (flag & 0x20) { + index++; + } else { + chan->polyphonyCounter++; + if (chan->polyphonyCounter == poly) { + ForceStopLogicalChannel(chan); + } + } + } + + chan = (jc_*)chan->mNext; + } + + if (flag & 0x20) { + jc->polyphonyCounter = index; + if (index < poly) { + return TRUE; + } + return FALSE; + } + + jc->polyphonyCounter = 0; + return TRUE; +} + +/* + * --INFO-- + * Address: 80015AC0 + * Size: 0000E8 + */ +static void __Oneshot_StopMonoPolyCheck(jc_* jc, u32 id) +{ + jc_* chan; + u8 poly; + + chan = jc->mMgr->activeChannels; + poly = polys_table[id >> 0x18 & 0xf]; + + if (id && poly) { + + while (TRUE) { + if (chan == NULL) { + break; + } + + int flag = id >> 0x18 & 0x20; + if (chan->soundId == id) { + if (flag) { + if (chan->polyphonyCounter > jc->polyphonyCounter) { + chan->polyphonyCounter--; + if (chan->polyphonyCounter == poly - 1) { + __Oneshot_WavePause(chan, 0); + } + } + } else { + if (chan->polyphonyCounter > jc->polyphonyCounter) { + chan->polyphonyCounter--; + if (chan->polyphonyCounter < poly) { + __Oneshot_WavePause(chan, 0); + } + } + } + } + + chan = (jc_*)chan->mNext; + } + } +} diff --git a/src/static/jaudio_PP/internal/oneshot_playstart.c_inc b/src/static/jaudio_PP/internal/oneshot_playstart.c_inc new file mode 100644 index 00000000..b88436a2 --- /dev/null +++ b/src/static/jaudio_PP/internal/oneshot_playstart.c_inc @@ -0,0 +1,41 @@ +/* + * --INFO-- + * Address: 800155C0 + * Size: 00010C + */ +static jc_* __Oneshot_Play_Start(jcs_* jcs, jc_* jc, u32 id) +{ + BOOL play; + + if (id == 0) { + id = -1; + } + jc->playId = id; + jc->savedPlayId = jc->playId; + jc->updateCallback = Jesus1Shot_Update; + jc->dspChannel = AllocDSPchannel(0, (u32)jc); + + if (jc->dspChannel == NULL) { + play = CheckLogicalChannel(jc); + } else { + play = PlayLogicalChannel(jc); + } + + if (jc->dspChannel == NULL && play == TRUE) { + if (Add_WaitDSPChannel(jc) == TRUE) { + List_AddChannelTail(&jcs->waitingChannels, jc); + return jc; + } else { + List_AddChannelTail(&jcs->freeChannels, jc); + return NULL; + } + } else if (play == FALSE) { + DeAllocDSPchannel(jc->dspChannel, (u32)jc); + jc->dspChannel = NULL; + List_AddChannelTail(&jcs->freeChannels, jc); + return NULL; + } else { + List_AddChannelTail(&jcs->activeChannels, jc); + } + return jc; +} diff --git a/src/static/jaudio_PP/internal/playercall.c b/src/static/jaudio_PP/internal/playercall.c index 58a13730..28b72902 100644 --- a/src/static/jaudio_PP/internal/playercall.c +++ b/src/static/jaudio_PP/internal/playercall.c @@ -11,7 +11,7 @@ extern void ResetPlayerCallback() { } } -static s32 Jac_CheckPlayerCallback(PlayerCallBack callback, void* arg) { +s32 Jac_CheckPlayerCallback(PlayerCallBack callback, void* arg) { int i; for (i = 0; i < 16; i++) { diff --git a/src/static/jaudio_PP/internal/rspsim.c b/src/static/jaudio_PP/internal/rspsim.c index 9b4cf36c..3ae239d3 100644 --- a/src/static/jaudio_PP/internal/rspsim.c +++ b/src/static/jaudio_PP/internal/rspsim.c @@ -7,7 +7,7 @@ static u8 DMEM[0x1000] ATTRIBUTE_ALIGN(32); static u32 ADPCM_BOOKBUF_SIZE = 0; -static s16 ADPCM_BOOKBUF[8][16] ATTRIBUTE_ALIGN(32); +static s16 ADPCM_BOOKBUF[8 * 16] ATTRIBUTE_ALIGN(32); static s16 FINALR_STATE_BUF[16] ATTRIBUTE_ALIGN(32); static s16 RES_FILTER[64][4] ATTRIBUTE_ALIGN(32) = { @@ -61,6 +61,7 @@ extern void RspStart2(u32* task, s32 tasks, s32 mode) { #define DMEM_OFS(ofs) ((s16*)&((u8*)DMEM)[(ofs)]) +#pragma scheduling 7400 extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { static BOOL init = TRUE; s32 i; // r30 @@ -70,8 +71,8 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { u16 DMEMIn; // r27 u16 DMEMOut; // r26 s32 temp0; - u32 temp1; - u32 temp2; + u8 temp2; + u8 temp1; void* loop_point; // r1+0x134 s16 envParam1_1; s16 envParam1_2; @@ -117,19 +118,27 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { Jac_bcopy((void*)cmdLo, &DMEM[DMEMOut], 16 * sizeof(s16)); } - s16* var_r17 = (s16*)&DMEM[(u16)(DMEMOut + 32)]; + s32 j; + s16 temp_r4; + s32 temp_r19; + u16 idx = DMEMOut + 32; + u8* var_r18; + s16* var_r17 = (s16*)&DMEM[idx]; + s16* temp_r16; s16 var_r5 = var_r17[-1]; s16 var_r0 = var_r17[-2]; - u8* var_r18 = sp128 + DMEMIn - sp12C; + var_r18 = sp128 + DMEMIn - sp12C; u16 sp13C = (DMEMCount + 31) / 32; s32 var_r12; - s32 j; s32 k; - s32 l; + s16* src; for (j = 0; j < sp13C; j++) { - s16 temp_r4 = *var_r18++; - s32 temp_r19 = temp_r4 >> 4; - s16* temp_r16 = ADPCM_BOOKBUF[temp_r4 & 0xF]; + temp_r16 = ADPCM_BOOKBUF; + temp_r4 = (s16)*var_r18++; + temp_r19 = (temp_r4 >> 4); + + temp_r4 &= 0xF; + temp_r16 += temp_r4 * 16; if (flags & 4) { for (k = 0; k < 4; k++) { s16 temp_r14_2 = *var_r18++; @@ -147,7 +156,8 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { } for (k = 0; k < 8; k++) { sp7C[k] = sp9C[k] << temp_r19; - var_r12 = sp7C[k] + (var_r5 * temp_r16[k + 8] / 0x800) + (var_r0 * temp_r16[k] / 0x800); + s32 var_r12 = (var_r5 * temp_r16[k + 8] / 0x800) + (var_r0 * temp_r16[k] / 0x800) + sp7C[k]; + s32 l; for (l = 0; l < k; l++) { var_r12 += sp7C[l] * temp_r16[k - l + 7] / 0x800; } @@ -163,7 +173,8 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { var_r0 = sp9C[6]; for (k = 0; k < 8; k++) { sp5C[k] = sp9C[k + 8] << temp_r19; - var_r12 = (var_r5 * temp_r16[k + 8] / 0x800) + (var_r0 * temp_r16[k] / 0x800) + sp5C[k]; + s32 var_r12 = (var_r5 * temp_r16[k + 8] / 0x800) + (var_r0 * temp_r16[k] / 0x800) + sp5C[k]; + s32 l; for (l = 0; l < k; l++) { var_r12 += sp5C[l] * temp_r16[k - l + 7] / 0x800; } @@ -177,11 +188,12 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { } var_r5 = sp9C[15]; var_r0 = sp9C[14]; - for (k = 0; k < 16; k++) { + for (s32 k = 0; k < 16; k++) { *var_r17++ = sp9C[k]; } } - Jac_bcopy(var_r17 - 16, (void*)cmdLo, 16 * sizeof(s16)); + src = var_r17 - 16; + Jac_bcopy(src, (void*)cmdLo, 16 * sizeof(s16)); break; } @@ -194,15 +206,15 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { case A_CMD_RESAMPLE: { // A_RESAMPLE s16 spC[8]; s16* var_r4; + s32 j; s16* var_r6; u32 var_r7; s32 var_r8; + s16* temp_r9_2; s32 var_r9; s32 var_r14; s32 var_r15; u16 count; - s16* temp_r9_2; - s32 j; count = DMEMCount >> 1; var_r14 = cmdHi & 0xFFFF; @@ -271,10 +283,10 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { break; case A_CMD_DUPLICATE: { // A_DUPLICATE + s32 j; u16 src = cmdHi & 0xFFFF; u16 dst = cmdLo >> 16; s32 count = (cmdHi >> 16) & 0xFF; - s32 j; for (j = 0; j < count; j++) { Jac_bcopy(&DMEM[src], &DMEM[dst], 0x80); @@ -283,7 +295,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { } break; } - + // case 3: // A_UNK3 // // not emulated // break; @@ -303,7 +315,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { Jac_bcopy((void*)cmdLo, ADPCM_BOOKBUF, cmdHi & 0xFFFF); ADPCM_BOOKBUF_SIZE = cmdHi & 0xFFFF; break; - + case A_CMD_ADDMIXER: // A_ADDMIXER case A_CMD_MIXER: { // A_MIXER s16* src = DMEM_OFS(cmdLo >> 16); @@ -314,7 +326,8 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { for (j = 0; j < count * 8; j++) { s16 v0 = *src++; - s32 mixed = *dst + ((v0 * m) >> 15); + s32 mixed = *dst; + mixed += (v0 * m) >> 15; if (mixed > 0x7FFF) { mixed = 0x7FFF; } @@ -347,7 +360,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { pInL = DMEM_OFS(inL); pInR = DMEM_OFS(inR); pOut = DMEM_OFS(out); - Jac_Resample16(pInL, pInR, pOut, count, JAC_FRAMESAMPLES >> 2, finalr_state, &finalr_phase, flag); + Jac_Resample16(pInR, pInL, pOut, count, JAC_FRAMESAMPLES >> 2, finalr_state, &finalr_phase, flag); flag = FALSE; break; } @@ -360,11 +373,15 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { break; case A_CMD_UNK16: { // ??? - u8 count = (cmdHi >> 16) & 0xFF; - u32 dst = cmdHi & 0xFFFF; - u32 src = cmdLo >> 16; - s32 stride = cmdLo & 0xFFFF; + s32 stride; + u32 dst; + u32 src; s32 j; + s32 count; + dst = cmdHi & 0xFFFF; + src = cmdLo >> 16; + stride = cmdLo & 0xFFFF; + count = (cmdHi >> 16) & 0xFF; for (j = 0; j < count; j++) { Jac_bcopy(&DMEM[(u16)dst], &DMEM[(u16)src], stride); dst += stride; @@ -374,9 +391,9 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { } case A_CMD_HALFCUT: { // A_INTERL - s32 count = cmdHi & 0xFFFF; s16* src = (s16*)&DMEM[cmdLo >> 16]; s16* dst = (s16*)&DMEM[cmdLo & 0xFFFF]; + s32 count = cmdHi & 0xFFFF; s32 j; for (j = 0; j < count; j++) { @@ -420,12 +437,22 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { s16* var_r19; s16* var_r20; s16* var_r21; - u16 count; s32 j; + s32 left_wet_mid_narrow; + s32 right_wet_2; + s32 right_wet_mid_narrow; + s32 var_r14_2; + s32 var_r4_7; + s32 left_wet_low; + s32 var_r16_3; + s32 left_wet_2; + s32 var_r12_2; + u16 count; + s32 right_wet_low; temp1 = cmdHi & 2; // this should not be stored to stack temp2 = cmdHi & 1; - temp0 = (cmdHi >> 8) & 0xFF; + temp0 = (u8)(cmdHi >> 8); var_r16 = temp0 << 1; var_r17 = (s16*)&DMEM[((cmdHi >> 16) & 0xFF) * 16]; @@ -433,19 +460,21 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { var_r19 = (s16*)&DMEM[((cmdLo >> 16) & 0xFF) * 16]; DCTouchRange(var_r18, var_r16); DCTouchRange(var_r19, var_r16); - var_r20 = (s16*)&DMEM[((cmdLo >> 8) & 0xFF) * 16]; - var_r21 = (s16*)&DMEM[(cmdLo & 0xFF) * 16]; + var_r20 = (s16*)&DMEM[(cmdLo >> 4) & 0xFF0]; + var_r21 = (s16*)&DMEM[(cmdLo << 4) & 0xFF0]; DCTouchRange(var_r20, var_r16); DCTouchRange(var_r21, var_r16); count = temp0 >> 1; for (j = 0; j < count; j++) { s16 temp_r0_6 = *var_r17++; - s16 temp_r5_2 = *var_r17++; - s32 var_r4_7 = (temp_r0_6 * envParam2_0) >> 16; - s32 var_r12_2 = (temp_r0_6 * envParam2_1) >> 16; - s32 var_r14_2 = (temp_r5_2 * envParam2_0) >> 16; - s32 var_r16_3 = (temp_r5_2 * envParam2_1) >> 16; + s32 temp_r5_2 = *var_r17++; + + + var_r4_7 = (temp_r0_6 * envParam2_0) >> 16; + var_r12_2 = (temp_r0_6 * envParam2_1) >> 16; + var_r14_2 = (temp_r5_2 * envParam2_0) >> 16; + var_r16_3 = (temp_r5_2 * envParam2_1) >> 16; if (temp1) { // temp1 should not be stored to stack, needs r15 var_r4_7 = -var_r4_7; var_r14_2 = -var_r14_2; @@ -455,14 +484,29 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { var_r16_3 = -var_r16_3; } // TODO: weird math - s32 var_r0_3 = var_r18[0] + var_r4_7; - s32 var_r3_2 = var_r18[1] + var_r14_2; - s32 var_r4_8 = var_r19[0] + var_r12_2; - s32 var_r5_6 = var_r19[1] + var_r16_3; - f32 var_f2 = ((var_r4_7 * envParam1_0) >> 16) + ((var_r4_7 * envParam1_0) >> 18) + ((var_r4_7 * (u16)envParam1_0) >> 19); - f32 var_f5 = ((var_r12_2 * envParam1_0) >> 16) + ((var_r12_2 * envParam1_0) >> 18) + ((var_r12_2 * (u16)envParam1_0) >> 19); - f32 var_f4 = ((var_r14_2 * envParam1_0) >> 16) + ((var_r14_2 * envParam1_0) >> 18) + ((var_r14_2 * (u16)envParam1_0) >> 19); - f32 var_f6 = ((var_r16_3 * envParam1_0) >> 16) + ((var_r16_3 * envParam1_0) >> 18) + ((var_r16_3 * (u16)envParam1_0) >> 19); + f32 var_f2; + f32 var_f4; + f32 var_f5; + f32 var_f6; + s32 var_r0_3 = var_r18[0]; + s32 var_r3_2 = var_r18[1]; + s32 var_r4_8 = var_r19[0]; + s32 var_r5_6 = var_r19[1]; + right_wet_2 = var_r12_2 * envParam1_0; + var_r0_3 += var_r4_7; + var_r3_2 += var_r14_2; + var_r4_8 += var_r12_2; + var_r5_6 += var_r16_3; + left_wet_mid_narrow = right_wet_2 >> 18; + left_wet_low = right_wet_2 >> 19; + left_wet_2 = right_wet_2 >> 16; + var_f2 = ((var_r4_7 * envParam1_0) >> 16) + ((var_r4_7 * envParam1_0) >> 18) + ((var_r4_7 * envParam1_0) >> 19); + var_f4 = left_wet_2 + left_wet_mid_narrow + left_wet_low; + right_wet_mid_narrow = (var_r16_3 * envParam1_0) >> 18; + right_wet_low = (var_r16_3 * envParam1_0) >> 19; + right_wet_2 = ((var_r16_3 * envParam1_0) >> 16); + var_f5 = ((var_r14_2 * envParam1_0) >> 16) + ((var_r14_2 * envParam1_0) >> 18) + ((var_r14_2 * envParam1_0) >> 19); + var_f6 = right_wet_2 + right_wet_mid_narrow + right_wet_low; if (var_r0_3 > 0x7FFF) { var_r0_3 = 0x7FFF; } @@ -492,10 +536,14 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { *var_r19++ = var_r4_8; *var_r19++ = var_r5_6; - s32 var_r3_3 = var_r20[0] + var_f2; - s32 var_r4_9 = var_r20[1] + var_f4; - s32 var_r5_7 = var_r21[0] + var_f5; - s32 var_r7_4 = var_r21[1] + var_f6; + s32 var_r3_3 = var_r20[0]; + s32 var_r4_9 = var_r20[1]; + s32 var_r5_7 = var_r21[0]; + s32 var_r7_4 = var_r21[1]; + var_r3_3 += var_f2; + var_r4_9 += var_f5; + var_r5_7 += var_f4; + var_r7_4 += var_f6; if (var_r3_3 > 0x7FFF) { var_r3_3 = 0x7FFF; } @@ -547,18 +595,16 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { Jac_bcopy((void*)cmdLo, DMEM_OFS(DMEMOut), 16 * sizeof(s16)); } - u16 temp1 = DMEMOut + 32; - s16* dst = (s16*)&DMEM[temp1]; + s16* dst = (s16*)&DMEM[(u16)(DMEMOut + 32)]; u8* src = sp128 + DMEMIn - sp12C; + u16 count = DMEMCount >> 1; s32 j; - for (j = 0; j < DMEMCount >> 1; j++) { + for (j = 0; j < count; j++) { *dst++ = (*src++) << 8; } - u16 temp2 = DMEMOut; - temp2 += 32; - Jac_bcopy(&DMEM[temp2 - 32], (void*)cmdLo, 32); + Jac_bcopy(&DMEM[(u16)(DMEMOut + 32) - 32], (void*)cmdLo, 32); break; } diff --git a/src/static/jaudio_PP/internal/system.c b/src/static/jaudio_PP/internal/system.c index afcad6ae..b905026a 100644 --- a/src/static/jaudio_PP/internal/system.c +++ b/src/static/jaudio_PP/internal/system.c @@ -19,7 +19,11 @@ static s32 Nas_GetSyncDummy(u8* param0, s32 param1); +#if VERSION == VER_GAEJ01_01 +BOOL AUDIO_SYSTEM_READY = FALSE; +#else volatile BOOL AUDIO_SYSTEM_READY = FALSE; +#endif static void* FASTDMA_BUFFER = NULL; Na_DmaProc NA_DMA_PROC = Z_osEPiStartDma; Na_SyncProc NA_SYNC_PROC = Nas_GetSyncDummy; @@ -535,7 +539,7 @@ s32 Nas_StartSeq_Skip(s32 group_idx, s32 seq_id, s32 skip_ticks) { return __Nas_StartSeq(group_idx, seq_id); } -static s32 __Nas_StartSeq(s32 group_idx, s32 seq_id, s32 param) { +static s32 __Nas_StartSeq(s32 group_idx, s32 seq_id) { group* group = AG.groups_p[group_idx]; u8* seq_p; s32 bank_id; From de8edf6196beb9917676624d10ff84c42c8ee41a Mon Sep 17 00:00:00 2001 From: h0504 Date: Tue, 27 Oct 2026 08:25:58 +0900 Subject: [PATCH 5/7] Add e+ Rev 1 boot code, boot data and libforest units Port boot.c, initial_menu.c, dvderr.c, version.c, gba2/JoyBoot.cpp and libforest (osreport, fault, ReconfigBATs) from Animal Crossing and update them for e+ (REL reload for the indoor/outdoor modules, version check, fault callback, JUTGba-based GBA boot). The boot screen data (bootdata gam_win1-3, logo_nin) and nintendo_hi_0 are rebuilt from extracted assets with display lists decoded back into gbi macros. Co-Authored-By: Claude Opus 5.5 --- include/bootdata.h | 1 + include/dolphin/os/OSLink.h | 2 + include/libforest/fault.h | 2 +- src/static/boot.c | 853 +++++++++++++++++++ src/static/bootdata/gam_win1.c | 192 +++++ src/static/bootdata/gam_win2.c | 163 ++++ src/static/bootdata/gam_win3.c | 22 + src/static/bootdata/logo_nin.c | 33 + src/static/dvderr.c | 982 ++++++++++++++++++++++ src/static/gba2/JoyBoot.cpp | 1181 +++++++++++++++++++++++++++ src/static/initial_menu.c | 442 ++++++++++ src/static/libforest/ReconfigBATs.c | 72 ++ src/static/libforest/fault.c | 147 ++++ src/static/libforest/osreport.c | 85 ++ src/static/nintendo_hi_0.c | 5 + src/static/version.c | 11 + 16 files changed, 4192 insertions(+), 1 deletion(-) create mode 100644 src/static/boot.c create mode 100644 src/static/bootdata/gam_win1.c create mode 100644 src/static/bootdata/gam_win2.c create mode 100644 src/static/bootdata/gam_win3.c create mode 100644 src/static/bootdata/logo_nin.c create mode 100644 src/static/dvderr.c create mode 100644 src/static/gba2/JoyBoot.cpp create mode 100644 src/static/initial_menu.c create mode 100644 src/static/libforest/ReconfigBATs.c create mode 100644 src/static/libforest/fault.c create mode 100644 src/static/libforest/osreport.c create mode 100644 src/static/nintendo_hi_0.c create mode 100644 src/static/version.c diff --git a/include/bootdata.h b/include/bootdata.h index b6dc7793..3f9e738c 100644 --- a/include/bootdata.h +++ b/include/bootdata.h @@ -22,6 +22,7 @@ extern Gfx gam_win1_moji2_model[]; extern Gfx gam_win1_moji3_model[]; extern Gfx gam_win2_moji_model[]; +extern Gfx gam_win2_moji2_model[]; extern Gfx gam_win3_moji_model[]; extern u8 nintendo_376x104[]; diff --git a/include/dolphin/os/OSLink.h b/include/dolphin/os/OSLink.h index 1e6a031c..e8d75c2e 100644 --- a/include/dolphin/os/OSLink.h +++ b/include/dolphin/os/OSLink.h @@ -7,7 +7,9 @@ extern "C" { #endif +#ifndef OS_MODULE_VERSION #define OS_MODULE_VERSION 2 +#endif typedef struct OSModuleHeader OSModuleHeader; diff --git a/include/libforest/fault.h b/include/libforest/fault.h index e3c64d02..26681817 100644 --- a/include/libforest/fault.h +++ b/include/libforest/fault.h @@ -45,7 +45,7 @@ typedef struct { extern void fault_AddClientEx(fault_client* client, FaultCallback callback, const char* msg, u32 param, u8 priority, u8 flags); extern void fault_AddClient(fault_client* client, FaultCallback callback, const char* msg, u32 param); extern void fault_Printf(const char* msg, ...); -static void fault_DrawUpdate(); +extern void fault_DrawUpdate(); extern void fault_WaitTime(u32 waitTime); extern int fault_ReadPad(u32* outTriggers, u32* outButtons); static void fault_CallBackFunc(int stage); diff --git a/src/static/boot.c b/src/static/boot.c new file mode 100644 index 00000000..aefb8e50 --- /dev/null +++ b/src/static/boot.c @@ -0,0 +1,853 @@ +#define FIX_SQRT_LINKAGE +#define OS_MODULE_VERSION 3 +#include "boot.h" + +#include "dolphin/dvd.h" +#include "dolphin/os.h" +#include "dolphin/os/OSArena.h" +#include "dolphin/os/OSContext.h" +#include "dolphin/os/OSModule.h" +#include "dolphin/os/OSReset.h" +#include "dolphin/pad.h" +#include "dolphin/ai.h" +#include "libforest/fault.h" +#include "jaudio_NES/game64.h" +#include "libc64/malloc.h" +#include "libc64/sleep.h" +#include "libforest/osreport.h" +#include "libforest/emu64/emu64_wrapper.h" +#include "jsyswrap.h" +#include "libultra/initialize.h" +#include "libultra/contreaddata.h" +#include "libultra/libultra.h" +#include "libultra/shutdown.h" +#include "m_nmibuf.h" +#include "nintendo_hi_0.h" +#include "sys_math.h" +#include "terminal.h" +#include "dolphin/vi.h" +#include "_mem.h" +#include "initial_menu.h" +#include "libforest/batconfig.h" +#include "dolphin/os/OSAlarm.h" +#include "dvderr.h" +#include "libforest/osreport.h" +#include "MSL_C/string.h" + +s32 zurumode_flag = 0; +u8* buff_p_for_moduleI_or_moduleO = nullptr; +size_t buff_size_for_moduleI_or_moduleO = 0; +static void* StringTable; +OSModuleHeader* moduleI; +OSModuleHeader* moduleO; +u8* AfterLoadModuleO_RestMemUse_p; +size_t AfterLoadModuleO_RestMemSize; +static BOOL fakemain_check; +OSTime InitialStartTime; /* TODO: this appears to be N64's type of OSTime (u64), and not Dolphin's (s64) */ +void* boot_copyDate; +OSModuleHeader* moduleD; +static OSModuleHeader* moduleA; +void* HotStartEntry; +u8 boot_sound_initializing; +u8 SoftResetEnable; +void (*zurumode_onFaultCallback)(void* param); + +extern u32 JW_soundAramSize; +extern int JW_Get_request_type_AgbProg(void); +extern int JW_Get_loaded_type_AgbProg(void); +extern void JW_Load_AGB_archive_outdoor(u8* buf, size_t size); +extern void JW_Release_AGB_archive_outdoor(void); +extern void* JW_Get_AgbTarget_Special_archive_p(void); +extern void JW_Load_AGB_archive_special(void); +extern void JW_Unload_AGB_archive_special(void); +extern void JW_Load_picture_copy_archive(void); +extern void JW_Unload_picture_copy_archive(void); +extern void* JW_Get_picture_copy_archive_p(void); + +#define BOOT_SDK_VERSION "08May2003Patch3" + +/** + * @brief Tries to find an absolute address within any loaded modules. + * + * @param addr The address to search for + * @param module_id Out module id + * @param section_idx Out module section index + * @param section_addr Out module section offset + * @param module_name_ofs Out module name offset + * @return s32 success + */ +s32 search_partial_address(u32 addr, u32* module_id, u32* section_idx, u32* section_addr, u32* module_name_ofs) { + u32 section_size; + OSModuleHeader* module_p; + u32 section; + u32 section_ofs; + OSSectionInfo* section_info; + + if (addr == 0) { + return -1; /* failed */ + } + + module_p = BaseModule; + while (module_p != nullptr) { + section_info = OSGetSectionInfo(module_p); + for (section = 0; section < module_p->info.numSections; + section_info++, section++) { + section_size = section_info->size; + if (section_size != 0) { + section_ofs = OS_SECTIONINFO_OFFSET(section_info->offset); + if ((section_ofs <= addr) && (addr < section_ofs + section_size)) { + if (module_id != nullptr) { + *module_id = module_p->info.id; + } + if (section_idx != nullptr) { + *section_idx = section; + } + if (section_addr != nullptr) { + *section_addr = addr - section_ofs; + } + if (module_name_ofs != nullptr) { + *module_name_ofs = module_p->info.nameOffset; + } + + return 0; /* success */ + } + } + } + + module_p = (OSModuleHeader*)module_p->info.link.next; + } + + return -1; /* failed */ +} + +/** + * @brief Attempts to convert an absolute address to a module_id-section_idx-section_offset pair. + * + * @param addr Address to attempt conversion on + * @return u32 convertedAddress + */ +extern u32 convert_partial_address(u32 addr) { + u32 module_id, section_idx, section_ofs; + + if (search_partial_address(addr, &module_id, §ion_idx, §ion_ofs, nullptr) == 0) { + return MAKE_PARTIAL_ADDRESS(section_idx, section_ofs); + } + + return addr; +} + +/** + * @brief Loads a debug string table for debugging. + * + * @param table Path to the string table. + */ +void LoadStringTable(const char* table) { + StringTable = JC__JKRDvdToMainRam_byName(table, nullptr, EXPAND_SWITCH_DECOMPRESS); + + if (StringTable == nullptr) { + OSDVDFatalError(); + } + + OSSetStringTable(StringTable); +} + +/** + * @brief Utility function to "un-link" a relocatable module (rel). + * + * @param module Handle to the module header to unload. + * @param keep_memory Don't free the module's memory when TRUE. + * @param unlink Run the epilog & unlink the module when TRUE. + */ +extern void UnLink(OSModuleHeader* module, BOOL keep_memory, BOOL unlink) { + if (unlink && module != nullptr) { + if (module->epilog != 0) { + OSReport("エピローグ開始\n"); /* epilog start */ + ((void (*)())module->epilog)(); + OSReport("エピローグ完了\n"); /* epilog complete */ + } + + OSReport("アンリンク中\n"); /* unlinking */ + OSUnlink(&module->info); + OSReport("アンリンク完了\n"); /* unlinking complete */ + } + + if (!keep_memory) { + JW_Free(module); + } +} + +/** + * @brief Relocatable module (reL) loading utility function. Loads a module by its file name. + * May return nullptr if unable to load the module for whatever reason. + * + * @param module_name The file name of the module. + * @param buf Buffer to load the module into, or nullptr to allocate one. + * @param buf_size Minimum size of the allocated buffer. + * @param link Link the module & run its prolog when TRUE. + * @param cache_whole_buf Register the whole buffer as texture cache data when TRUE. + * @param rest_p Out pointer to the memory after the module & its bss. + * @param end_p Out pointer to the end of the allocated buffer. + * @return OSModuleHeader* loadedModule + */ +OSModuleHeader* LoadLink(const char* module_name, u8* buf, size_t buf_size, BOOL link, BOOL cache_whole_buf, u8** rest_p, u8** end_p) { + int result; + size_t length; + void* bss; + OSModuleHeader* module; + int alignLength; + int size; + size_t used_size; + size_t alignBufSize; + + bss = nullptr; + OSReport("モジュール(%s)の読み込み中\n", module_name); /* Loading module (%s) */ + module = (OSModuleHeader*)JC__JKRDvdToMainRam_byName(module_name, buf, EXPAND_SWITCH_DECOMPRESS); + if (module == nullptr) { + OSReport("モジュール(%s)の読み込みに失敗しました\n", module_name); /* Failed to load module (%s) */ + OSDVDFatalError(); + return module; + } + + OSReport("モジュール(%s)の読み込み完了\n", module_name); /* Module (%s) load complete */ + OSReport("module=%08x\n", module); + result = !!module; + OSReport("result=%08x\n", result); + length = JW_GetMemBlockSize(module); + OSReport("length=%08x\n", length); + JC__JKRDetachResource(module); + if (result) { + alignLength = ALIGN_NEXT(length, 32); + bss = (u8*)module + alignLength; + + if (buf == nullptr) { + used_size = alignLength + module->bssSize; + alignBufSize = ALIGN_NEXT(buf_size, 32); + size = used_size < alignBufSize ? alignBufSize : used_size; + + if (rest_p != nullptr) { + *rest_p = (u8*)module + used_size; + } + + if (end_p != nullptr) { + *end_p = (u8*)module + size; + } + + if (JW_Resize(module, size) >= 0) { + if (link) { + if (!cache_whole_buf) { + emu64_texture_cache_data_entry_set((u8*)module, bss); + } + else { + emu64_texture_cache_data_entry_set((u8*)module, module + size); + } + } + } + else { + OSReport("bss領域をmoduleに連続した領域に確保できませんでした\n"); /* Could not allocate the bss area contiguous to the module */ + goto failed; + } + } + + if (link) { + OSLink(&module->info, bss); + ((void (*)())module->prolog)(); + } + + return module; + } + +failed: + JW_Free(bss); + JW_Free(module); + return nullptr; +} + +OSModuleHeader* LoadLink_compare(const char* module_name, const char* compare_module_name, u8** rest_p, u8** end_p) { + size_t size = 0; + OSModuleHeader* module = LoadLink(compare_module_name, nullptr, 0, FALSE, FALSE, nullptr, nullptr); + size_t compare_size; + + if ((compare_size = JW_GetMemBlockSize(module)) > size) { + size = compare_size; + } + + UnLink(module, FALSE, FALSE); + return LoadLink(module_name, nullptr, size, TRUE, TRUE, rest_p, end_p); +} + +u8* Get_free_buff_p_for_moduleI_or_moduleO() { + if (moduleI == nullptr || moduleO == nullptr) { + return buff_p_for_moduleI_or_moduleO; + } + + return nullptr; +} + +void set_info_ReloadLink_module_IorO(u8* rest_p, u8* end_p) { + u8* use_p = nullptr; + size_t size = 0; + + if (rest_p != nullptr && end_p != nullptr) { + if ((u64)ALIGN_NEXT((u32)rest_p, 32) < (u64)ALIGN_PREV((u32)end_p, 32)) { + use_p = (u8*)ALIGN_NEXT((u32)rest_p, 32); + size = (u64)ALIGN_PREV((u32)end_p, 32) - (u64)ALIGN_NEXT((u32)rest_p, 32); + } + } + + AfterLoadModuleO_RestMemUse_p = use_p; + AfterLoadModuleO_RestMemSize = size; +} + +void reset_info_ReloadLink_module_IorO() { + AfterLoadModuleO_RestMemUse_p = nullptr; + AfterLoadModuleO_RestMemSize = 0; +} + +void ReloadLink_module_IorO(int outSideType) { + OSModuleHeader* module; + + if (moduleI != nullptr && moduleO != nullptr) { + OSReport("室内外データを同時にロードしてしまっている"); /* Indoor and outdoor data are loaded at the same time */ + return; + } + + if (buff_p_for_moduleI_or_moduleO == nullptr) { + OSReport("室内外データロード領域が確保されていない"); /* Indoor/outdoor data load area is not allocated */ + return; + } + + if (moduleI != nullptr) { + if (outSideType != BOOT_IorO_TYPE_INSIDE) { + module = moduleI; + moduleI = nullptr; + UnLink(module, TRUE, TRUE); + ReloadLink_module_IorO(outSideType); + } + } + else if (moduleO != nullptr) { + module = moduleO; + if (outSideType == BOOT_IorO_TYPE_OUTSIDE) { + if (JW_Get_request_type_AgbProg() != JW_Get_loaded_type_AgbProg()) { + JW_Release_AGB_archive_outdoor(); + JW_Load_AGB_archive_outdoor(AfterLoadModuleO_RestMemUse_p, AfterLoadModuleO_RestMemSize); + } + } + else if (outSideType == BOOT_IorO_TYPE_DEFAULT) { + JW_Release_AGB_archive_outdoor(); + } + else { + JW_Release_AGB_archive_outdoor(); + moduleO = nullptr; + UnLink(module, TRUE, TRUE); + ReloadLink_module_IorO(outSideType); + } + } + else if (outSideType != BOOT_IorO_TYPE_PLAYERSELECT) { + if (outSideType == BOOT_IorO_TYPE_INSIDE) { + moduleI = LoadLink("/foresti.rel.szs", buff_p_for_moduleI_or_moduleO, buff_size_for_moduleI_or_moduleO, TRUE, FALSE, nullptr, nullptr); + } + else { + moduleO = LoadLink("/foresto.rel.szs", buff_p_for_moduleI_or_moduleO, buff_size_for_moduleI_or_moduleO, TRUE, FALSE, nullptr, nullptr); + if (outSideType == BOOT_IorO_TYPE_OUTSIDE) { + JW_Load_AGB_archive_outdoor(AfterLoadModuleO_RestMemUse_p, AfterLoadModuleO_RestMemSize); + } + } + } +} + +/** + * @brief Callback if an error occurs during audio initialization. + * + */ +void audioFatalCallback() { + OSReport("audioFatalCallback" VT_RST "\n"); + OSDVDFatalError(); +} + +/** + * @brief First half of audio initialization. Prepares boot sound. + * + */ +void sound_initial() { + Na_InitAudio(audioFatalCallback, nintendo_hi_0, 0x66a0, JW_soundAramSize); + msleep(2500); +} + +/** + * @brief Second half of audio initialization. Waits for 'Neos' to finish initialization. + * + */ +void sound_initial2() { + while (!Na_CheckNeosBoot()) { + VIWaitForRetrace(); + Na_GameFrame(); + } + + bzero(&nintendo_hi_0, sizeof(nintendo_hi_0)); +} + +/** + * @brief Performs a hot reset to the IPL menu + * + */ +void HotResetIplMenu() { + if (APPNMI_ZURUMODE3_GET()) { + OSChangeBootMode(RETAIL_MODE); /* Switch back to retail mode before rebooting */ + } + + /* Utilize osAppNMIBuffer[15] as the boot code to recover it & signal hotreset*/ + OSResetSystem(OS_RESET_HOTRESET, osAppNMIBuffer[15], TRUE); +} + +/** + * @brief faultmgr callback which checks for correct debug key input. + * + * @param msg The message displayed for the key combo. + * @param param The key combination separated into two u16s. + */ +void fault_callback_keyCheck(const char* msg, u32 param) { + u32 trigger; + u32 button; + + if (APPNMI_ZURUMODE_GET()) { + fault_Printf("PUSH %s\n", msg); + } + do { + do { + fault_DrawUpdate(); + fault_ReadPad(&trigger, &button); + } while ((u16)trigger != (u16)param); + } while ((u16)button != (u16)((param >> 16) | trigger)); +} + +/** + * @brief faultmgr callback which acknowledges correct debug key input. + * + */ +void fault_callback_OK() { + fault_Printf("\nOK! YOU SUCCESS!\n"); + fault_DrawUpdate(); + fault_WaitTime(2000); +} + +/** + * @brief faultmgr callback which prints control text to the console. + * + */ +void fault_callback_Setumei() { + fault_Printf("\n+ KEY to SCROLL UP/DOWN\nB BUTTON : TOP OF CONSOLE\nA BUTTON : BOTTOM OF CONSOLE\n"); +} + +/** + * @brief faultmgr callback which stops audio & waits for a restart unless zurumode is active. + * + */ +void fault_callback_first() { + u32 triggers, buttons; + + fault_WaitTime(1000); + APPNMI_RESETEXEMPT2_SET(); + + if (AICheckInit()) { + AIStopDMA(); + AIReset(); + AIInit(nullptr); + } + + if (!APPNMI_TESTMODE_GET() && !APPNMI_ZURUMODE_GET()) { + OSReport("ずるモードになればコードがでます\n"); /* The code will be shown in zurumode */ + OSReport("B+X+STARTでリスタートします\n"); /* B+X+START to restart */ + + do { + if (OSGetResetSwitchState()) { + __osResetSwitchPressed = TRUE; + } else { + if (__osResetSwitchPressed) { + osShutdownStart(OS_RESET_SHUTDOWN); + } + } + + fault_ReadPad(&triggers, &buttons); + if (buttons == (PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_START)) { + osShutdownStart(OS_RESET_SHUTDOWN); + } + + if (buttons == (PAD_BUTTON_Y | PAD_BUTTON_A | PAD_TRIGGER_Z | PAD_BUTTON_UP) && triggers == PAD_BUTTON_A) { + break; + } + } while (!APPNMI_ZURUMODE_GET()); + } +} + +/** + * @brief faultmgr callback which resets the video mode. + * + */ +void fault_callback_vimode() { + JW_SetFamicomMode(FALSE); + JW_SetLowResoMode(FALSE); +} + +#define OVERLINE(con) (((JC_JUTConsole_getUsedLine(con) - JC_JUTConsole_getHeight(con)) + 1) <= JC_JUTConsole_getLineOffset(con)) + +/** + * @brief faultmgr callback to scroll console + * + */ +void fault_callback_scroll() { + u32 button; + u32 trigger; + void* manager; + void* console; + s32 up_speed; + s32 down_speed; + s32 update_console; + u32 retrace_cnt; + int pad_disabled; + + manager = JC_JUTException_getManager(); + console = JC_JUTException_getConsole(); + pad_disabled = !JC_JUTException_isEnablePad(manager); + if (!pad_disabled) { + OSEnableInterrupts(); + up_speed = 0; + down_speed = 0; + do { + JC_JUTException_readPad(manager, &trigger, &button); + update_console = FALSE; + if (trigger == PAD_BUTTON_A) { + JC_JUTConsole_scrollToLastLine(console); + update_console = TRUE; + } + if (trigger == PAD_BUTTON_B) { + JC_JUTConsole_scrollToFirstLine(console); + update_console = TRUE; + } + if (button == PAD_BUTTON_UP) { + JC_JUTConsole_scroll( + console, (up_speed < 3) + ? -1 + : ((up_speed < 5) ? -2 : ((up_speed < 7) ? -4 : -8))); + update_console = TRUE; + down_speed = 0; + up_speed++; + } else if (button == PAD_BUTTON_DOWN) { + JC_JUTConsole_scroll( + console, (down_speed < 3) + ? 1 + : ((down_speed < 5) ? 2 : ((down_speed < 7) ? 4 : 8))); + update_console = TRUE; + up_speed = 0; + down_speed++; + } else { + up_speed = 0; + down_speed = 0; + } + if (update_console == TRUE) { + retrace_cnt = VIGetRetraceCount(); + do { + } while (retrace_cnt == VIGetRetraceCount()); + JC_JUTConsoleManager_drawDirect(JC_JUTConsoleManager_getManager(), 1); + } + JC_JUTException_waitTime(30); + if (OSGetResetSwitchState()) { + osShutdownStart(OS_RESET_RESTART); + } + } while (TRUE); + } + + do { + JC_JUTConsole_scrollToFirstLine(console); + JC_JUTConsoleManager_drawDirect(JC_JUTConsoleManager_getManager(), 1); + JC_JUTException_waitTime(2000); + + do { + u32 height; + for (height = JC_JUTConsole_getHeight(console); height != 0; height--) { + JC_JUTConsole_scroll(console, 1); + JC_JUTConsoleManager_drawDirect(JC_JUTConsoleManager_getManager(), 1); + + if (OVERLINE(console)) { + break; + } + + JC_JUTException_waitTime(20); + } + + JC_JUTException_waitTime(3000); + if (OVERLINE(console)) { + break; + } + } while (TRUE); + } while (TRUE); +} + +/** + * @brief Adjusts the memory arena depending on installed RAM size. + * osAppNMIBuffers's 'extended memory' bitflag must be enabled for extended memory settings. + */ +void adjustOSArena() { + void* arenalo = OSGetArenaLo(); + void* arenahi = OSGetArenaHi(); + + OSReport("ARENA %08x-%08x" VT_RST "\n", arenalo, arenahi); + + if (arenahi > (void*)0x81800000) { + if (!APPNMI_EXTENDEDMEMORY_GET()) { + OSReport("搭載メモリが 24MB を超えていますが、24MB に限定します。" VT_RST "\n"); /* The installed memory exceeds 24MB, but will be limited to 24MB. */ + arenahi = (void*)0x817ffa80; + } else if (arenahi > (void*)0x82000000) { + OSReport("搭載メモリが 32MB を超えていますが、32MB に限定します。" VT_RST "\n"); /* The installed memory exceeds 32MB, but will be limited to 32MB. */ + arenahi = (void*)0x81e00000; + } else { + OSReport("搭載メモリが 32MB を超えています。" VT_RST "\n"); /* The installed memory exceeds 32MB. */ + } + } else { + OSReport("搭載メモリが 24MB 以下なので動かない事がありえます。" VT_RST "\n"); /* Since the installed memory is 24MB or less, there may be issues. */ + } + + OSSetArenaHi(arenahi); + OSReport("ARENA %08x-%08x" VT_RST "\n", arenalo, arenahi); + + bzero(arenalo, ((u32)arenahi - (u32)arenalo)); +} + +/** + * @brief Halts if the game was not built against the expected SDK version. + * + */ +void version_check() { + if (strcmp(BOOT_SDK_VERSION, BOOT_SDK_VERSION) != 0) { + while (TRUE) {} + } +} + +/** + * @brief Loads the outdoor module into a buffer large enough to also hold the indoor module. + * + */ +static inline void LoadLink_moduleIorO() { + u8* end_p; + u8* rest_p; + + rest_p = nullptr; + end_p = nullptr; + reset_info_ReloadLink_module_IorO(); + buff_p_for_moduleI_or_moduleO = (u8*)(moduleO = LoadLink_compare("/foresto.rel.szs", "/foresti.rel.szs", &rest_p, &end_p)); + buff_size_for_moduleI_or_moduleO = JW_GetMemBlockSize(buff_p_for_moduleI_or_moduleO); + set_info_ReloadLink_module_IorO(rest_p, end_p); +} + +/** + * @brief Standard C main function/entry point + * + * @param argc unused + * @param argv unused + * @return int exitCode + */ +int main(int argc, const char** argv) { + static const boot_tbl_t tbl = { + "L+R+X+Y+Down, START BUTTON", + PAD_TRIGGER_L | PAD_TRIGGER_R | PAD_BUTTON_X | PAD_BUTTON_Y | PAD_BUTTON_DOWN, + PAD_BUTTON_START + }; + + static fault_client + my_fault_client1, + my_fault_client2, + my_fault_client3, + my_fault_client4, + my_fault_client5, + my_fault_client6, + my_fault_client7; + + void* start; + void* end; + DVDDiskID* diskId; + DVDFileInfo fileInfo; + size_t audiorom_size; + + version_check(); + ReconfigBATs(); + if (fakemain_check) { + return -1; + } + + fakemain_check = 1; + InitialStartTime = osGetTime(); + OSInit(); + OSInitAlarm(); + + /* Reset N64 NMI buffer*/ + bzero(osAppNMIBuffer, 16 * sizeof(s32)); + + /* Adjust process based on how the console started */ + switch (OSGetResetCode()) { + case 0: + OSReport("システムパワーオン\n"); /* system power on */ + break; + case OS_RESETCODE_RESTART: + OSReport("リスタート\n"); /* restart */ + OSGetSaveRegion(&start, &end); + OSReport("OSGetSaveRegion %08x %08x\n", start, end); + bcopy(NMISaveArea, osAppNMIBuffer, 16 * sizeof(s32)); + break; + default: + OSReport("ホットリセット\n"); /* hot reset */ + OSReport("OSGetResetCode=0x%08x\n", OSGetResetCode()); + OSReport("リリース版ではリセットコードを無視します\n"); /* In the release version, the reset code is ignored. */ + break; + } + + __osInitialize_common(); + + /* Setup development environment for dev hardware */ + if ((OSGetConsoleType() & OS_CONSOLE_DEVELOPMENT) != 0) { + APPNMI_ZURUMODE3_SET(); + } else if (APPNMI_ZURUMODE3_GET()) { + OSReport("デベロップメントモードに戻します。そしてリセット" VT_RST "\n"); /* Return to development mode, then reset. */ + OSChangeBootMode(0); + OSResetSystem(1, osAppNMIBuffer[15], 0); + } + + /* Initialize zurumode levels */ + diskId = DVDGetCurrentDiskID(); + if (diskId->gameVersion == 0x99) { + APPNMI_DEBUGMODE_SET(); + } + if (diskId->gameVersion >= 0x90) { + APPNMI_TESTMODE_SET(); + } + + if (diskId->gameVersion >= 0x90) { + OSReport("ZURUMODE2 ENABLE\n"); + APPNMI_ZURUMODE2_SET(); + } + + OSReport("osAppNMIBuffer[15]=0x%08x\n", osAppNMIBuffer[15]); + if (APPNMI_RESETEXEMPT2_GET()) { + APPNMI_RESETEXEMPT2_CLR(); + APPNMI_RESETEXEMPT_SET(); + OSReport( + "異常状態でのリセット検出ゆえリセットさん免除フラグをセットしました" VT_RST "\n"); /* Decetected abnormal reset state, so set reset exemption flag. */ + } else { + APPNMI_RESETEXEMPT_CLR(); + } + + APPNMI_RESETEXEMPT2_SET(); + OSReport("どうぶつの森ブートローダ起動\n"); /* Animal Crossing bootloader startup */ + adjustOSArena(); + + DVDOpen("audiorom.img", &fileInfo); + audiorom_size = ALIGN_NEXT(fileInfo.length, 32); + DVDClose(&fileInfo); + JW_soundAramSize = Na_GetAudioARAMSize(audiorom_size, 0x66a0); + JW_Init(); + + /* Check enable debug process bars */ + if (APPNMI_DEBUGMODE_GET()) { + JC_JUTProcBar_setVisible(JC_JUTProcBar_getManager(), APPNMI_TESTMODE_GET() != 0); + JC_JUTProcBar_setVisibleHeapBar(JC_JUTProcBar_getManager(), APPNMI_TESTMODE_GET() != 0); + } + + /* Load static.dol symbol map file */ + JC_JUTException_setMapFile("/static.map"); + JC_JUTException_enterAllPad(JC_JUTException_getManager()); + + /* Initialize fault 'class' & clients */ + fault_Init(); + fault_AddClientEx(&my_fault_client7, (FaultCallback)fault_callback_first, nullptr, 0, 10, 14); + fault_AddClientEx(&my_fault_client5, (FaultCallback)fault_callback_vimode, nullptr, 0, 10, 14); + fault_AddClientEx(&my_fault_client1, (FaultCallback)fault_callback_keyCheck, tbl.msg, (tbl.param_upper << 16) | tbl.param_lower, 10, 14); + fault_AddClientEx(&my_fault_client2, (FaultCallback)fault_callback_OK, nullptr, 0, 10, 14); + fault_AddClientEx(&my_fault_client3, (FaultCallback)fault_callback_Setumei, nullptr, 0, 10, 9); + fault_AddClientEx(&my_fault_client6, (FaultCallback)fault_callback_scroll, nullptr, 0, 1, 9); + fault_AddClient(&my_fault_client4, (FaultCallback)DisplayArena, nullptr, 0); + + /* Toggle JUtility debug console visibility */ + if (APPNMI_TESTMODE_GET()) { + JC_JUTAssertion_changeDevice(3); + JC_JUTDbPrint_setVisible(JC_JUTDbPrint_getManager(), TRUE); + } else { + JC_JUTAssertion_changeDevice(2); + JC_JUTDbPrint_setVisible(JC_JUTDbPrint_getManager(), FALSE); + } + JC_JUTAssertion_changeDisplayTime(600); + + OSReport("InitialStartTime=%u us\n", (u32)OSTicksToMicroseconds((u64)InitialStartTime)); + sound_initial(); + initial_menu_init(); + dvderr_init(); + sound_initial2(); + + if ((OSGetConsoleType() & OS_CONSOLE_DEVELOPMENT) == 0) { + OSReport("以降OSReportを無効\n"); /* OSReport disabled from now on. */ + OSReportDisable(); + } + + OSReport("Loging COPYDATE\n"); + boot_copyDate = JC__JKRDvdToMainRam_byName("/COPYDATE", nullptr, EXPAND_SWITCH_DECOMPRESS); + if (boot_copyDate == nullptr) { + OSDVDFatalError(); + } + + LoadStringTable("/static.str"); + + LoadLink_moduleIorO(); + moduleD = LoadLink("/forestd.rel.szs", nullptr, 0, TRUE, FALSE, nullptr, nullptr); + moduleA = LoadLink("/foresta.rel.szs", nullptr, 0, TRUE, FALSE, nullptr, nullptr); + JW_Load_AGB_archive_special(); + JW_Load_picture_copy_archive(); + JW_Init2(); + initial_menu_cleanup(); + + if (buff_p_for_moduleI_or_moduleO == nullptr) { + LoadLink_moduleIorO(); + } + + if (moduleD == nullptr) { + moduleD = LoadLink("/forestd.rel.szs", nullptr, 0, TRUE, FALSE, nullptr, nullptr); + } + + if (moduleA == nullptr) { + moduleA = LoadLink("/foresta.rel.szs", nullptr, 0, TRUE, FALSE, nullptr, nullptr); + } + + if (JW_Get_AgbTarget_Special_archive_p() == nullptr) { + JW_Load_AGB_archive_special(); + } + + if (JW_Get_picture_copy_archive_p() == nullptr) { + JW_Load_picture_copy_archive(); + } + + JC_JKRExpHeap_changeGroupID(JC_JFWSystem_getSystemHeap(), 5); + + while (HotStartEntry != nullptr) { + OSReport("ホットスタート(%08x)\n", HotStartEntry); + HotStartEntry = (*(void* (*)())HotStartEntry)(); + } + + JW_Unload_picture_copy_archive(); + JW_Unload_AGB_archive_special(); + UnLink(moduleA, FALSE, TRUE); + moduleA = nullptr; + UnLink(moduleD, FALSE, TRUE); + moduleD = nullptr; + UnLink(moduleI, FALSE, TRUE); + moduleI = nullptr; + UnLink(moduleO, FALSE, TRUE); + moduleO = nullptr; + buff_p_for_moduleI_or_moduleO = nullptr; + buff_size_for_moduleI_or_moduleO = 0; + reset_info_ReloadLink_module_IorO(); + + if (StringTable != nullptr) { + JW_Free(StringTable); + StringTable = nullptr; + } + + OSReport("どうぶつの森ブートローダ終了\n"); /* Animal Crossing bootloader end */ + JW_Cleanup(); + return 0; +} diff --git a/src/static/bootdata/gam_win1.c b/src/static/bootdata/gam_win1.c new file mode 100644 index 00000000..42fbec3b --- /dev/null +++ b/src/static/bootdata/gam_win1.c @@ -0,0 +1,192 @@ +#include "bootdata.h" +#include "libforest/gbi_extensions.h" + +static u8 gam_win_moji1_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/gam_win_moji1_tex.inc" +}; + +u8 gam_win_moji2_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/gam_win_moji2_tex.inc" +}; + +u8 gam_win_moji3_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/gam_win_moji3_tex.inc" +}; + +u8 gam_win_moji4_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/gam_win_moji4_tex.inc" +}; + +u8 gam_win_moji5_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/gam_win_moji5_tex.inc" +}; + +static u8 att_win_waku1_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/att_win_waku1_tex.inc" +}; + +static u8 att_win_waku2_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/att_win_waku2_tex.inc" +}; + +static u8 att_win_waku3_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/att_win_waku3_tex.inc" +}; + +static u8 att_win_waku4_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/att_win_waku4_tex.inc" +}; + +static u8 att_win_waku5_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/att_win_waku5_tex.inc" +}; + +static u8 att_win_waku6_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win1/att_win_waku6_tex.inc" +}; + +Vtx gam_win1_v[] = { +#include "assets/bootdata/win1/gam_win1_v.inc" +}; + +Gfx gam_win1_cursor_model[] = { + gsDPSetPrimColor(0, 255, 145, 40, 40, 255), + gsSPVertex(&gam_win1_v[0], 3, 0), + gsSPNTrianglesInit_5b( + 1, // tri count + 0, 1, 2, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; + +Gfx gam_win1_moji_model[] = { + gsDPSetPrimColor(0, 255, 50, 50, 60, 255), + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji3_tex, G_IM_FMT_I, 112, 16, 15, GX_CLAMP, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win1_v[3], 12, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji2_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji1_tex, G_IM_FMT_I, 128, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 8, 9, 10, // tri0 + 9, 11, 10, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; + +Gfx gam_win1_moji2_model[] = { + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji4_tex, G_IM_FMT_I, 32, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win1_v[15], 4, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; + +Gfx gam_win1_moji3_model[] = { + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji5_tex, G_IM_FMT_I, 48, 16, 15, GX_CLAMP, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win1_v[19], 4, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; + +Gfx gam_win1_winT_model[] = { + gsDPSetPrimColor(0, 255, 225, 255, 255, 255), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku6_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win1_v[23], 28, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku5_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 8, 9, 10 // tri2 + ), + gsSPNTriangles_5b( + 11, 8, 10, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku4_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 12, 13, 14, // tri0 + 15, 12, 14, // tri1 + 16, 17, 18 // tri2 + ), + gsSPNTriangles_5b( + 17, 19, 18, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku3_tex, G_IM_FMT_I, 32, 64, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 20, 21, 22, // tri0 + 21, 23, 22, // tri1 + 24, 25, 26 // tri2 + ), + gsSPNTriangles_5b( + 25, 27, 26, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku2_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win1_v[51], 16, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 7, 4, 6, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku1_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 8, 9, 10, // tri0 + 11, 8, 10, // tri1 + 12, 13, 14 // tri2 + ), + gsSPNTriangles_5b( + 13, 15, 14, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; diff --git a/src/static/bootdata/gam_win2.c b/src/static/bootdata/gam_win2.c new file mode 100644 index 00000000..f1b3c94c --- /dev/null +++ b/src/static/bootdata/gam_win2.c @@ -0,0 +1,163 @@ +#include "bootdata.h" +#include "libforest/gbi_extensions.h" + +u8 gam_win_moji6_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/gam_win_moji6_tex.inc" +}; + +u8 gam_win_moji7_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/gam_win_moji7_tex.inc" +}; + +u8 gam_win_moji8_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/gam_win_moji8_tex.inc" +}; + +static u8 gam_win_moji1_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/gam_win_moji1_tex.inc" +}; + +static u8 att_win_waku1_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/att_win_waku1_tex.inc" +}; + +static u8 att_win_waku2_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/att_win_waku2_tex.inc" +}; + +static u8 att_win_waku3_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/att_win_waku3_tex.inc" +}; + +static u8 att_win_waku4_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/att_win_waku4_tex.inc" +}; + +static u8 att_win_waku5_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/att_win_waku5_tex.inc" +}; + +static u8 att_win_waku6_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win2/att_win_waku6_tex.inc" +}; + +Vtx gam_win2_v[] = { +#include "assets/bootdata/win2/gam_win2_v.inc" +}; + +Gfx gam_win2_moji_model[] = { + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji8_tex, G_IM_FMT_I, 96, 16, 15, GX_CLAMP, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win2_v[0], 12, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji7_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji6_tex, G_IM_FMT_I, 96, 16, 15, GX_CLAMP, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 8, 9, 10, // tri0 + 9, 11, 10, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; + +Gfx gam_win2_moji2_model[] = { + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji1_tex, G_IM_FMT_I, 128, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win2_v[12], 4, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; + +Gfx gam_win2_winT_model[] = { + gsDPSetPrimColor(0, 255, 225, 255, 255, 255), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku6_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win2_v[16], 28, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku5_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 8, 9, 10 // tri2 + ), + gsSPNTriangles_5b( + 11, 8, 10, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku4_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 12, 13, 14, // tri0 + 15, 12, 14, // tri1 + 16, 17, 18 // tri2 + ), + gsSPNTriangles_5b( + 17, 19, 18, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku3_tex, G_IM_FMT_I, 32, 64, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 20, 21, 22, // tri0 + 21, 23, 22, // tri1 + 24, 25, 26 // tri2 + ), + gsSPNTriangles_5b( + 25, 27, 26, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku2_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win2_v[44], 16, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 7, 4, 6, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(att_win_waku1_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 8, 9, 10, // tri0 + 11, 8, 10, // tri1 + 12, 13, 14 // tri2 + ), + gsSPNTriangles_5b( + 13, 15, 14, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; diff --git a/src/static/bootdata/gam_win3.c b/src/static/bootdata/gam_win3.c new file mode 100644 index 00000000..a8387dca --- /dev/null +++ b/src/static/bootdata/gam_win3.c @@ -0,0 +1,22 @@ +#include "bootdata.h" +#include "libforest/gbi_extensions.h" + +u8 gam_win_moji9_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/win3/gam_win_moji9_tex.inc" +}; + +Vtx gam_win3_v[] = { +#include "assets/bootdata/win3/gam_win3_v.inc" +}; + +Gfx gam_win3_moji_model[] = { + gsDPLoadTextureBlock_4b_Dolphin(gam_win_moji9_tex, G_IM_FMT_I, 128, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&gam_win3_v[0], 4, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; diff --git a/src/static/bootdata/logo_nin.c b/src/static/bootdata/logo_nin.c new file mode 100644 index 00000000..5847d384 --- /dev/null +++ b/src/static/bootdata/logo_nin.c @@ -0,0 +1,33 @@ +#include "bootdata.h" +#include "libforest/gbi_extensions.h" + +u8 logo_nin2_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/logo_nin2_tex.inc" +}; + +u8 logo_nin1_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/bootdata/logo_nin1_tex.inc" +}; + +Vtx logo_nin_v[] = { +#include "assets/bootdata/logo_nin_v.inc" +}; + +Gfx logo_ninT_model[] = { + gsDPLoadTextureBlock_4b_Dolphin(logo_nin1_tex, G_IM_FMT_I, 256, 32, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPVertex(&logo_nin_v[0], 8, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 0, 2, 3, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(logo_nin2_tex, G_IM_FMT_I, 256, 32, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 4, 5, 6, // tri0 + 4, 6, 7, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; diff --git a/src/static/dvderr.c b/src/static/dvderr.c new file mode 100644 index 00000000..ea967d1b --- /dev/null +++ b/src/static/dvderr.c @@ -0,0 +1,982 @@ +#define FIX_SQRT_LINKAGE +#include "dvderr.h" + +#include "libultra/libultra.h" +#include "dolphin/dvd.h" +#include "libforest/gbi_extensions.h" +#include "libforest/emu64/emu64_wrapper.h" +#include "jsyswrap.h" +#include "dolphin/vi.h" +#include "dolphin/gx.h" + +static u8 dvd_keikoku_moji1_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji1_tex.inc" +}; + +static u8 dvd_keikoku_moji2_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji2_tex.inc" +}; + +static u8 dvd_keikoku_pp_moji1_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_pp_moji1_tex.inc" +}; + +static u8 ctl_att_w1_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/ctl_att_w1_tex.inc" +}; + +static u8 ctl_att_w2_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/ctl_att_w2_tex.inc" +}; + +static u8 ctl_att_w3_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/ctl_att_w3_tex.inc" +}; + +static u8 ctl_att_w4_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/ctl_att_w4_tex.inc" +}; + +static u8 ctl_att_w5_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/ctl_att_w5_tex.inc" +}; + +static u8 ctl_att_w6_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/ctl_att_w6_tex.inc" +}; + +static u8 dvd_keikoku_moji3_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji3_tex.inc" +}; + +static u8 dvd_keikoku_moji4_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji4_tex.inc" +}; + +static u8 dvd_keikoku_e_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_e_tex.inc" +}; + +static u8 dvd_keikoku_moji5_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji5_tex.inc" +}; + +static u8 dvd_keikoku_moji6_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji6_tex.inc" +}; + +static u8 dvd_keikoku_moji7_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji7_tex.inc" +}; + +static u8 dvd_keikoku_moji8_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji8_tex.inc" +}; + +static u8 dvd_keikoku_moji9_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji9_tex.inc" +}; + +static u8 dvd_keikoku_moji10_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji10_tex.inc" +}; + +static u8 dvd_keikoku_maru_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_maru_tex.inc" +}; + +static u8 dvd_keikoku_moji11_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji11_tex.inc" +}; + +static u8 dvd_keikoku_moji13_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji13_tex.inc" +}; + +static u8 dvd_keikoku_moji14_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji14_tex.inc" +}; + +static u8 dvd_keikoku_moji15_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji15_tex.inc" +}; + +static u8 dvd_keikoku_moji16_tex[] ATTRIBUTE_ALIGN(32) = { +#include "assets/dvd_keikoku_moji16_tex.inc" +}; + +static Vtx dvd_keikoku1_v[] = { +#include "assets/dvd_keikoku1_v.inc" +}; + +static Gfx keikoku1_dvd_att_moji_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 235, 235, 255, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_XLU_INTER2), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_pp_moji1_tex, G_IM_FMT_I, 128, 32, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku1_v[0], 24, 0), + gsSPNTrianglesInit_5b( + 8, // tri count + 0, 1, 2, // tri0 + 0, 3, 1, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 4, 7, 5, // tri0 + 8, 9, 10, // tri1 + 8, 11, 9, // tri2 + 12, 13, 14 // tri3 + ), + gsSPNTriangles_5b( + 12, 15, 13, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji2_tex, G_IM_FMT_I, 96, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 16, 17, 18, // tri0 + 16, 19, 17, // tri1 + 20, 21, 22 // tri2 + ), + gsSPNTriangles_5b( + 21, 23, 22, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji1_tex, G_IM_FMT_I, 96, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPVertex(&dvd_keikoku1_v[24], 8, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 4, 7, 5, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; + +static Gfx keikoku1_dvd_att_winT_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 100, 0, 170, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_ZB_XLU_SURF2), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w6_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku1_v[32], 28, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w5_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 8, 9, 10 // tri2 + ), + gsSPNTriangles_5b( + 11, 8, 10, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w4_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 12, 13, 14, // tri0 + 15, 12, 14, // tri1 + 16, 17, 18 // tri2 + ), + gsSPNTriangles_5b( + 17, 19, 18, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w3_tex, G_IM_FMT_I, 32, 64, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 20, 21, 22, // tri0 + 23, 20, 22, // tri1 + 24, 25, 26 // tri2 + ), + gsSPNTriangles_5b( + 25, 27, 26, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w2_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&dvd_keikoku1_v[60], 16, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 7, 4, 6, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w1_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 8, 9, 10, // tri0 + 11, 8, 10, // tri1 + 12, 13, 14 // tri2 + ), + gsSPNTriangles_5b( + 13, 15, 14, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; + +static Vtx dvd_keikoku2_v[] = { +#include "assets/dvd_keikoku2_v.inc" +}; + +static Gfx keikoku2_dvd_att_moji_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 235, 235, 255, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_XLU_INTER2), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_e_tex, G_IM_FMT_I, 16, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku2_v[0], 16, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 0, 3, 1, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji4_tex, G_IM_FMT_I, 112, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji3_tex, G_IM_FMT_I, 192, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 8, 9, 10, // tri0 + 8, 11, 9, // tri1 + 12, 13, 14 // tri2 + ), + gsSPNTriangles_5b( + 12, 15, 13, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; + +static Gfx keikoku2_dvd_att_winT_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 100, 0, 170, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_ZB_XLU_SURF2), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w6_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku2_v[16], 28, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w5_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 8, 9, 10 // tri2 + ), + gsSPNTriangles_5b( + 11, 8, 10, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w4_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 12, 13, 14, // tri0 + 15, 12, 14, // tri1 + 16, 17, 18 // tri2 + ), + gsSPNTriangles_5b( + 17, 19, 18, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w3_tex, G_IM_FMT_I, 32, 64, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 20, 21, 22, // tri0 + 23, 20, 22, // tri1 + 24, 25, 26 // tri2 + ), + gsSPNTriangles_5b( + 25, 27, 26, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w2_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&dvd_keikoku2_v[44], 16, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 7, 4, 6, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w1_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 8, 9, 10, // tri0 + 11, 8, 10, // tri1 + 12, 13, 14 // tri2 + ), + gsSPNTriangles_5b( + 13, 15, 14, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; + +static Vtx dvd_keikoku3_v[] = { +#include "assets/dvd_keikoku3_v.inc" +}; + +static Gfx keikoku3_dvd_att_moji_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 235, 235, 255, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_XLU_INTER2), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_e_tex, G_IM_FMT_I, 16, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku3_v[0], 24, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 0, 3, 1, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 4, 6, 7, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji4_tex, G_IM_FMT_I, 112, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 8, 9, 10, // tri0 + 9, 11, 10, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji3_tex, G_IM_FMT_I, 192, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 12, 13, 14, // tri0 + 12, 15, 13, // tri1 + 16, 17, 18 // tri2 + ), + gsSPNTriangles_5b( + 16, 19, 17, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji6_tex, G_IM_FMT_I, 144, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 20, 21, 22, // tri0 + 21, 23, 22, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji5_tex, G_IM_FMT_I, 208, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPVertex(&dvd_keikoku3_v[24], 8, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 0, 3, 1, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 4, 7, 5, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; + +static Gfx keikoku3_dvd_att_winT_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 100, 0, 170, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_ZB_XLU_SURF2), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w6_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku3_v[32], 28, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w5_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 8, 9, 10 // tri2 + ), + gsSPNTriangles_5b( + 11, 8, 10, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w4_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 12, 13, 14, // tri0 + 15, 12, 14, // tri1 + 16, 17, 18 // tri2 + ), + gsSPNTriangles_5b( + 17, 19, 18, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w3_tex, G_IM_FMT_I, 32, 64, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 20, 21, 22, // tri0 + 23, 20, 22, // tri1 + 24, 25, 26 // tri2 + ), + gsSPNTriangles_5b( + 25, 27, 26, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w2_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&dvd_keikoku3_v[60], 16, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 7, 4, 6, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w1_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 8, 9, 10, // tri0 + 11, 8, 10, // tri1 + 12, 13, 14 // tri2 + ), + gsSPNTriangles_5b( + 13, 15, 14, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; + +static Vtx dvd_keikoku4_v[] = { +#include "assets/dvd_keikoku4_v.inc" +}; + +static Gfx keikoku4_dvd_att_moji_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 235, 235, 255, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_XLU_INTER2), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_maru_tex, G_IM_FMT_I, 16, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku4_v[0], 20, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji10_tex, G_IM_FMT_I, 96, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji9_tex, G_IM_FMT_I, 176, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 8, 9, 10, // tri0 + 9, 11, 10, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji8_tex, G_IM_FMT_I, 144, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 12, 13, 14, // tri0 + 13, 15, 14, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji7_tex, G_IM_FMT_I, 160, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 16, 17, 18, // tri0 + 17, 19, 18, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; + +static Gfx keikoku4_dvd_att_winT_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 100, 0, 170, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_ZB_XLU_SURF2), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w6_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku4_v[20], 28, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w5_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 8, 9, 10 // tri2 + ), + gsSPNTriangles_5b( + 11, 8, 10, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w4_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 12, 13, 14, // tri0 + 15, 12, 14, // tri1 + 16, 17, 18 // tri2 + ), + gsSPNTriangles_5b( + 17, 19, 18, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w3_tex, G_IM_FMT_I, 32, 64, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 20, 21, 22, // tri0 + 23, 20, 22, // tri1 + 24, 25, 26 // tri2 + ), + gsSPNTriangles_5b( + 25, 27, 26, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w2_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&dvd_keikoku4_v[48], 16, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 7, 4, 6, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w1_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 8, 9, 10, // tri0 + 11, 8, 10, // tri1 + 12, 13, 14 // tri2 + ), + gsSPNTriangles_5b( + 13, 15, 14, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; + +static Vtx dvd_keikoku5_v[] = { +#include "assets/dvd_keikoku5_v.inc" +}; + +static Gfx keikoku5_dvd_att_moji_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 235, 235, 255, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_XLU_INTER2), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_maru_tex, G_IM_FMT_I, 16, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku5_v[0], 28, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 7, 4, 6, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji16_tex, G_IM_FMT_I, 64, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 8, 9, 10, // tri0 + 9, 11, 10, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji15_tex, G_IM_FMT_I, 144, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 12, 13, 14, // tri0 + 13, 15, 14, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji14_tex, G_IM_FMT_I, 176, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 16, 17, 18, // tri0 + 17, 19, 18, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji13_tex, G_IM_FMT_I, 192, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 20, 21, 22, // tri0 + 23, 20, 22, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(dvd_keikoku_moji11_tex, G_IM_FMT_I, 144, 16, 15, GX_CLAMP, GX_CLAMP, 0, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 24, 25, 26, // tri0 + 25, 27, 26, // tri1 + 0, 0, 0 // tri2 + ), + gsSPEndDisplayList(), +}; + +static Gfx keikoku5_dvd_att_winT_model[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_PASS2), + gsDPSetPrimColor(0, 255, 100, 0, 170, 255), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_ZB_XLU_SURF2), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w6_tex, G_IM_FMT_I, 16, 16, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_SHADING_SMOOTH), + gsSPVertex(&dvd_keikoku5_v[28], 28, 0), + gsSPNTrianglesInit_5b( + 2, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 0, 0, 0 // tri2 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w5_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 4, 5, 6, // tri0 + 5, 7, 6, // tri1 + 8, 9, 10 // tri2 + ), + gsSPNTriangles_5b( + 11, 8, 10, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w4_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 12, 13, 14, // tri0 + 15, 12, 14, // tri1 + 16, 17, 18 // tri2 + ), + gsSPNTriangles_5b( + 17, 19, 18, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w3_tex, G_IM_FMT_I, 32, 64, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 20, 21, 22, // tri0 + 23, 20, 22, // tri1 + 24, 25, 26 // tri2 + ), + gsSPNTriangles_5b( + 25, 27, 26, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w2_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPVertex(&dvd_keikoku5_v[56], 16, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 0, 1, 2, // tri0 + 1, 3, 2, // tri1 + 4, 5, 6 // tri2 + ), + gsSPNTriangles_5b( + 7, 4, 6, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsDPLoadTextureBlock_4b_Dolphin(ctl_att_w1_tex, G_IM_FMT_I, 64, 32, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPNTrianglesInit_5b( + 4, // tri count + 8, 9, 10, // tri0 + 11, 8, 10, // tri1 + 12, 13, 14 // tri2 + ), + gsSPNTriangles_5b( + 13, 15, 14, // tri0 + 0, 0, 0, // tri1 + 0, 0, 0, // tri2 + 0, 0, 0 // tri3 + ), + gsSPEndDisplayList(), +}; + +static dvderr_work Dvderr_work; +static dvderr_work* const this = &Dvderr_work; + +static Vp Dvderr_viewport = {{ + { 1280, 960, 511, 0 }, + { 1280, 960, 511, 0 } +}}; + +static Gfx Dvderr_initial_dl[] = { + gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_FILL | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2), + gsDPSetFillColor(GPACK_RGBA5551(0, 0, 0, 1) << 16 | GPACK_RGBA5551(0, 0, 0, 1)), /* fill color to black */ + gsDPFillRectangle(0, 0, 639, 479), /* fill in rectangle which is the size of the screen */ + gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, 640, 480), /* set scissor to screen size, TODO: should probably be defintions */ + gsSPClipRatio(FRUSTRATIO_2), /* 2:1 clipping ratio */ + gsSPViewport(&Dvderr_viewport), + gsSPMatrix(&Dvderr_work.ortho, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION), + gsSPMatrix(&Dvderr_work.projection, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION), + gsDPSetOtherMode(G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2), + gsSPMatrix(&Dvderr_work.modelview, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW), + gsSPEndDisplayList(), +}; + + +static void dvderr_exec_dl(Gfx* dl) { + emu64_init(); + emu64_taskstart(dl); + emu64_cleanup(); +} + +static int dvderr_check_drive() { + int err = DVDERR_NONE; + + if (osShutdown == FALSE) { + switch (DVDGetDriveStatus()) { + case DVD_STATE_FATAL_ERROR: + err = DVDERR_FATAL; + break; + + case DVD_STATE_BUSY: + err = this->next_error; + break; + + case DVD_STATE_NO_DISK: + err = DVDERR_NO_DISK; + break; + + case DVD_STATE_COVER_OPEN: + err = DVDERR_COVER_OPEN; + break; + + case DVD_STATE_WRONG_DISK: + err = DVDERR_WRONG_DISK; + break; + + case DVD_STATE_RETRY: + err = DVDERR_RETRY; + break; + } + } + + return err; +} + +static void dvderr_draw_CoverOpen() { + gSPDisplayList(this->gfx_p++, keikoku1_dvd_att_winT_model); + gSPDisplayList(this->gfx_p++, keikoku1_dvd_att_moji_model); +} + +static void dvderr_draw_NoDisk() { + gSPDisplayList(this->gfx_p++, keikoku2_dvd_att_winT_model); + gSPDisplayList(this->gfx_p++, keikoku2_dvd_att_moji_model); +} + +static void dvderr_draw_WrongDisk() { + gSPDisplayList(this->gfx_p++, keikoku3_dvd_att_winT_model); + gSPDisplayList(this->gfx_p++, keikoku3_dvd_att_moji_model); +} + +static void dvderr_draw_Retry() { + gSPDisplayList(this->gfx_p++, keikoku4_dvd_att_winT_model); + gSPDisplayList(this->gfx_p++, keikoku4_dvd_att_moji_model); +} + +static void dvderr_draw_Fatal() { + gSPDisplayList(this->gfx_p++, keikoku5_dvd_att_winT_model); + gSPDisplayList(this->gfx_p++, keikoku5_dvd_att_moji_model); +} + +static void dvderr_mtx_set() { + guScale(&this->modelview, this->scale, this->scale, 1.0f); +} + +#define DVDERR_MOVE_SPEED (1.0f/18.0f) + +static void dvderr_move_up(); +static void dvderr_move_down(); +static void dvderr_move_wait(); + +static void dvderr_move_up() { + this->scale += DVDERR_MOVE_SPEED; + if (this->scale >= 1.0f) { + this->scale = 1.0f; + } + + if (this->next_error != this->now_error) { + this->draw_proc = &dvderr_move_down; + } +} + +static void dvderr_move_down() { + if (this->scale <= 0.0f) { + this->scale = 0.0f; + this->now_error = this->next_error; + this->draw_proc = &dvderr_move_wait; + } + else { + this->scale -= DVDERR_MOVE_SPEED; + if (this->scale <= 0.0f) { + this->scale = 0.0f; + } + } +} + +static void dvderr_move_wait() { + if (this->next_error == DVDERR_NONE) { + return; + } + + this->now_error = this->next_error; + this->draw_proc = &dvderr_move_up; +} + +static void dvderr_move() { + (*this->draw_proc)(); +} + +extern int dvderr_draw() { + static const DVDERR_DRAW_PROC draw_proc[DVDERR_NUM] = { + &dvderr_draw_CoverOpen, + &dvderr_draw_NoDisk, + &dvderr_draw_WrongDisk, + &dvderr_draw_Retry, + &dvderr_draw_Fatal + }; + + this->next_error = dvderr_check_drive(); + dvderr_move(); + + if (this->now_error >= DVDERR_COVER_OPEN) { + dvderr_mtx_set(); + JW_BeginFrame(); + this->gfx_p = this->gfx; + gSPDisplayList(this->gfx_p++, Dvderr_initial_dl); + + if (draw_proc[this->now_error] != NULL) { + (*draw_proc[this->now_error])(); + } + + gDPFullSync(this->gfx_p++); + gSPEndDisplayList(this->gfx_p++); + + dvderr_exec_dl(this->gfx); + JW_EndFrame(); + VISetBlack(FALSE); + return TRUE; + } + else { + return FALSE; + } +} + +extern void dvderr_init() { + bzero(this, sizeof(dvderr_work)); + this->draw_proc = &dvderr_move_wait; + this->now_error = DVDERR_NONE; + this->next_error = DVDERR_NONE; + + guOrtho(&this->ortho, -160.0f, 160.0f, -120.0f, 120.0f, -800.0f, 800.0f, 1.0f); /* TODO: N64 screen size macros (float) */ + guLookAt(&this->projection, 0.0f, 0.0f, 400.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); +} diff --git a/src/static/gba2/JoyBoot.cpp b/src/static/gba2/JoyBoot.cpp new file mode 100644 index 00000000..84cc81c5 --- /dev/null +++ b/src/static/gba2/JoyBoot.cpp @@ -0,0 +1,1181 @@ +#include "GBA2/gba2.h" + +#include "JSystem/JUtility/JUTGba.h" +#include "dolphin/si.h" +#include "boot.h" +#include "_mem.h" + +typedef struct mGcgba_work_s { + /* 0x00 */ JUTGba* gba; + /* 0x04 */ u8* buf_p; + /* 0x08 */ int size; + /* 0x0C */ int timer; + /* 0x10 */ u32 cmd; + /* 0x14 */ u32 cmd2; + /* 0x18 */ u32 checksum; + /* 0x1C */ u32 block_checksum; + /* 0x20 */ u32 send_data; + /* 0x24 */ u32 recv_data; + /* 0x28 */ u8 state; + /* 0x29 */ u8 step; + /* 0x2A */ u8 busy; + /* 0x2B */ s8 result; + /* 0x2C */ u8 block_count; +} mGcgba_work_c; + +#define JUTGBA_RESULT_BUSY -2 + +mGcgba_work_c g_Joy_wrk; +int g_port; + +static u32 mJOYSIO_ConvData(u8* data) { + u8 conv_buf[sizeof(u32)]; + + conv_buf[0] = data[3]; + conv_buf[1] = data[2]; + conv_buf[2] = data[1]; + conv_buf[3] = data[0]; + + return *(u32*)conv_buf; +} + +extern "C" void mGcgba_Init() { } + +extern "C" void mGcgba_Finish() { + g_port = -1; + g_Joy_wrk.busy = FALSE; +} + +extern "C" void mGcgba_InitVar() { + static JUTGba mGcgba_work_for_JUTGba; + + memset(&g_Joy_wrk, 0, sizeof(g_Joy_wrk)); + g_Joy_wrk.gba = JUTGba::getManager(); + if (g_Joy_wrk.gba == NULL) { + memset(&mGcgba_work_for_JUTGba, 0, sizeof(mGcgba_work_for_JUTGba)); + SoftResetEnable = FALSE; + g_Joy_wrk.gba = JUTGba::create(&mGcgba_work_for_JUTGba); + SoftResetEnable = TRUE; + } +} + +extern "C" void mGcgba_EndComm() { + g_port = -1; +} + +extern "C" int mGcgba_ConnectEnabled() { + int ret = GBA2_GBA_STATE_TRANSMITTING; + int i; + + if (g_Joy_wrk.state == 0) { + for (i = 0; i < GBA_MAX_CHAN; i++) { + g_Joy_wrk.gba->doInitProbe(i, NULL, NULL); + } + + g_port = -1; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + } + else { + BOOL done = TRUE; + + g_port = -1; + for (i = 0; i < GBA_MAX_CHAN; i++) { + u32 type; + s32 res = g_Joy_wrk.gba->resultInitProbe(i, &type); + + if (res == GBA_READY && type == SI_GBA && g_port == -1) { + g_port = i; + } + + if (res == JUTGBA_RESULT_BUSY) { + done = FALSE; + } + } + + if (done && g_port != -1) { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_SUCCESS; + } + + if (ret == GBA2_GBA_STATE_TRANSMITTING && ++g_Joy_wrk.timer > GBA2_DEFAULT_TRIES) { + ret = GBA2_GBA_STATE_ERROR; + g_port = -1; + g_Joy_wrk.state = 0; + } + } + + return ret; +} + +extern "C" int mGcgba_Boot(u8* data_buf, size_t buf_size) { + int ret = GBA2_GBA_STATE_TRANSMITTING; + + if (g_Joy_wrk.state == 0) { + if (g_port > 0 && g_port < GBA_MAX_CHAN) { + g_Joy_wrk.gba->doJoyBoot(g_port, 3, -1, data_buf, buf_size, NULL, NULL); + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + } + else { + ret = GBA2_GBA_STATE_ERROR; + } + } + else { + u8 status; + s32 res = g_Joy_wrk.gba->resultJoyBoot(g_port, &status); + + if (res == GBA_READY) { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_SUCCESS; + } + else if (res != JUTGBA_RESULT_BUSY) { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_ERROR; + } + + if (ret == GBA2_GBA_STATE_TRANSMITTING && ++g_Joy_wrk.timer > 1000) { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_ERROR; + } + } + + return ret; +} + +static void CallBack_Connection(JUTGbaParam* param, void* arg) { + u8 status; + + if (g_Joy_wrk.busy == TRUE) { + switch (g_Joy_wrk.step) { + case 0: + if (g_Joy_wrk.gba->resultReset(g_port, &status) == GBA_READY) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_Connection, arg); + return; + } + break; + case 1: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (g_Joy_wrk.recv_data == *(u32*)"gaej") { + g_Joy_wrk.step++; + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)"GAEJ"); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Connection, arg); + } + else { + g_Joy_wrk.step--; + g_Joy_wrk.gba->doReset(g_port, &CallBack_Connection, arg); + } + return; + } + break; + case 2: + if (g_Joy_wrk.gba->resultWrite(g_port, &status) == GBA_READY) { + g_Joy_wrk.result = 1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; + return; + } + break; + } + } + + g_Joy_wrk.result = -1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; +} + +static void CallBack_TypeCheck(JUTGbaParam* param, void* arg) { + u8 status; + u32 data; + + if (g_Joy_wrk.busy == TRUE) { + switch (g_Joy_wrk.step) { + case 0: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_RECV) == 0) { + g_Joy_wrk.step++; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 5); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_TypeCheck, arg); + } + else { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_TypeCheck, arg); + } + return; + } + break; + case 1: + if (g_Joy_wrk.gba->resultWrite(g_port, &status) == GBA_READY) { + g_Joy_wrk.step++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_TypeCheck, arg); + return; + } + break; + case 2: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_SEND) != 0) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_TypeCheck, arg); + } + else { + g_Joy_wrk.step--; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 5); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_TypeCheck, arg); + } + return; + } + break; + case 3: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data); + if (data == g_Joy_wrk.cmd) { + g_Joy_wrk.result = 1; + } + else if (data == g_Joy_wrk.cmd2) { + g_Joy_wrk.result = 0; + } + else { + break; + } + + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; + return; + } + break; + } + } + + g_Joy_wrk.result = -1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; +} + +extern "C" int mGcgba_IsEditor() { + int ret = GBA2_GBA_STATE_TRANSMITTING; + + switch (g_Joy_wrk.state) { + case 0: + if (g_port > 0 && g_port < GBA_MAX_CHAN) { + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doReset(g_port, &CallBack_Connection, NULL); + } + else { + ret = GBA2_GBA_STATE_ERROR; + } + break; + case 1: + if (g_Joy_wrk.busy == FALSE) { + if (g_Joy_wrk.result == 1) { + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 6); + g_Joy_wrk.cmd2 = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 11); + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_TypeCheck, NULL); + } + else { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_ERROR; + } + } + break; + case 2: + if (g_Joy_wrk.busy == FALSE) { + ret = g_Joy_wrk.result; + g_Joy_wrk.state = 0; + } + break; + } + + if (ret == GBA2_GBA_STATE_TRANSMITTING && ++g_Joy_wrk.timer > 30) { + ret = GBA2_GBA_STATE_ERROR; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.state = 0; + } + + return ret; +} + +extern "C" int mGcgba_IsGame() { + int ret = GBA2_GBA_STATE_TRANSMITTING; + + switch (g_Joy_wrk.state) { + case 0: + if (g_port > 0 && g_port < GBA_MAX_CHAN) { + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doReset(g_port, &CallBack_Connection, NULL); + } + else { + ret = GBA2_GBA_STATE_ERROR; + } + break; + case 1: + if (g_Joy_wrk.busy == FALSE) { + if (g_Joy_wrk.result == 1) { + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 11); + g_Joy_wrk.cmd2 = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 6); + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_TypeCheck, NULL); + } + else { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_ERROR; + } + } + break; + case 2: + if (g_Joy_wrk.busy == FALSE) { + ret = g_Joy_wrk.result; + g_Joy_wrk.state = 0; + } + break; + } + + if (ret == GBA2_GBA_STATE_TRANSMITTING && ++g_Joy_wrk.timer > 30) { + ret = GBA2_GBA_STATE_ERROR; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.state = 0; + } + + return ret; +} + +static void CallBack_Recv(JUTGbaParam* param, void* arg); + +static void CallBack_CardScan(JUTGbaParam* param, void* arg) { + u8 status; + + if (g_Joy_wrk.busy == TRUE) { + switch (g_Joy_wrk.step) { + case 0: + case 3: + if (g_Joy_wrk.gba->resultWrite(g_port, &status) == GBA_READY) { + g_Joy_wrk.step++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_CardScan, arg); + return; + } + break; + case 1: + case 4: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_SEND) != 0) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_CardScan, arg); + } + else { + g_Joy_wrk.step--; + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.cmd); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_CardScan, arg); + } + return; + } + break; + case 2: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + u32 data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data); + + if (data == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 8)) { + g_Joy_wrk.step++; + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 9); + } + else if (data == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 10)) { + g_Joy_wrk.step = 0; + } + else { + break; + } + + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.cmd); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_CardScan, arg); + return; + } + break; + case 5: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + u32 data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data); + + if (data == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 8)) { + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 10); + g_Joy_wrk.step = 0; + g_Joy_wrk.timer = -GBA2_READ_TRIES; + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.cmd); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Recv, NULL); + return; + } + else if (data == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 10)) { + g_Joy_wrk.step = 3; + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.cmd); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_CardScan, arg); + return; + } + } + break; + } + } + + g_Joy_wrk.result = -1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; +} + +static void CallBack_Recv(JUTGbaParam* param, void* arg) { + u8 status; + u32 data; + + if (g_Joy_wrk.busy == TRUE) { + switch (g_Joy_wrk.step) { + case 0: + case 3: + case 6: + if (g_Joy_wrk.gba->resultWrite(g_port, &status) == GBA_READY) { + g_Joy_wrk.step++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Recv, arg); + return; + } + break; + case 1: + case 4: + case 7: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_SEND) != 0) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_Recv, arg); + } + else { + g_Joy_wrk.step--; + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.cmd); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Recv, arg); + } + return; + } + break; + case 2: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data) == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 4)) { + g_Joy_wrk.step++; + g_Joy_wrk.checksum = 0; + g_Joy_wrk.block_checksum = 0; + g_Joy_wrk.block_count = 0; + } + else { + g_Joy_wrk.step = 0; + } + + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.cmd); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Recv, arg); + return; + } + break; + case 5: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (g_Joy_wrk.size <= 0) { + g_Joy_wrk.step++; + data = g_Joy_wrk.checksum + mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data) == 0xFFFFFFFF + ? GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 6) + : GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 7); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Recv, arg); + return; + } + + if (g_Joy_wrk.block_count == 0xFF) { + if (g_Joy_wrk.block_checksum + mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data) != 0xFFFFFFFF) { + break; + } + + g_Joy_wrk.block_checksum = 0; + } + else { + *(u32*)g_Joy_wrk.buf_p = g_Joy_wrk.recv_data; + g_Joy_wrk.buf_p += sizeof(u32); + g_Joy_wrk.size -= sizeof(u32); + g_Joy_wrk.checksum += mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data); + g_Joy_wrk.block_checksum += mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data); + } + + g_Joy_wrk.block_count++; + g_Joy_wrk.step--; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Recv, arg); + return; + } + break; + case 8: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data) == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 8)) { + g_Joy_wrk.result = 1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; + return; + } + + if (mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data) != GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 9)) { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Recv, arg); + return; + } + } + break; + } + } + + g_Joy_wrk.result = -1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; +} + +extern "C" int mGcgba_Recv(u8* recv_bufp, size_t recv_buf_size) { + int ret = GBA2_GBA_STATE_TRANSMITTING; + + switch (g_Joy_wrk.state) { + case 0: + if (g_port > 0 && g_port < GBA_MAX_CHAN) { + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doReset(g_port, &CallBack_Connection, NULL); + } + else { + ret = GBA2_GBA_STATE_ERROR; + } + break; + case 1: + if (g_Joy_wrk.busy == FALSE) { + if (g_Joy_wrk.result == 1) { + g_Joy_wrk.buf_p = recv_bufp; + g_Joy_wrk.size = recv_buf_size; + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 2); + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.cmd); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Recv, NULL); + } + else { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_ERROR; + } + } + break; + case 2: + if (g_Joy_wrk.busy == FALSE) { + ret = g_Joy_wrk.result; + g_Joy_wrk.state = 0; + } + break; + } + + if (ret == GBA2_GBA_STATE_TRANSMITTING && ++g_Joy_wrk.timer > GBA2_DEFAULT_TRIES) { + ret = GBA2_GBA_STATE_ERROR; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.state = 0; + } + + return ret; +} + +extern "C" int mGcgba_Read(u8* read_buf, size_t read_buf_size, u8 prog_type) { + int ret = GBA2_GBA_STATE_TRANSMITTING; + + switch (g_Joy_wrk.state) { + case 0: + if (g_port > 0 && g_port < GBA_MAX_CHAN) { + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doReset(g_port, &CallBack_Connection, NULL); + } + else { + ret = GBA2_GBA_STATE_ERROR; + } + break; + case 1: + if (g_Joy_wrk.busy == FALSE) { + if (g_Joy_wrk.result == 1) { + g_Joy_wrk.buf_p = read_buf; + g_Joy_wrk.size = read_buf_size; + + switch (prog_type) { + case GBA2_EAPPLI_TYPE_NEEDLEWORK: + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 8); + break; + case GBA2_EAPPLI_TYPE_MUSICSCORE: + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 11); + break; + case GBA2_EAPPLI_TYPE_PTERMINAL: + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 12); + break; + default: + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 13); + break; + } + + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = -GBA2_READ_TRIES; + g_Joy_wrk.state++; + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.cmd); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_CardScan, NULL); + } + else { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_ERROR; + } + } + break; + case 2: + if (g_Joy_wrk.busy == FALSE) { + ret = g_Joy_wrk.result; + g_Joy_wrk.state = 0; + } + break; + } + + if (ret == GBA2_GBA_STATE_TRANSMITTING && ++g_Joy_wrk.timer > GBA2_DEFAULT_TRIES) { + ret = GBA2_GBA_STATE_ERROR; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.state = 0; + } + + return ret; +} + +static void CallBack_Send(JUTGbaParam* param, void* arg) { + u8 status; + u32 data; + + if (g_Joy_wrk.busy == TRUE) { + switch (g_Joy_wrk.step) { + case 0: + case 10: + if (g_Joy_wrk.gba->resultWrite(g_port, &status) == GBA_READY) { + g_Joy_wrk.step++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Send, arg); + return; + } + break; + case 1: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_SEND) != 0) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_Send, arg); + } + else { + g_Joy_wrk.step--; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 2); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, arg); + } + return; + } + break; + case 2: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data) == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 4)) { + g_Joy_wrk.step += 2; + g_Joy_wrk.checksum = 0; + g_Joy_wrk.block_checksum = 0; + g_Joy_wrk.block_count = 0; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Send, arg); + } + else { + g_Joy_wrk.step = 0; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 2); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, arg); + } + return; + } + break; + case 3: + case 5: + case 7: + case 13: + case 15: + case 17: + case 19: + if (g_Joy_wrk.gba->resultWrite(g_port, &status) == GBA_READY) { + g_Joy_wrk.step++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Send, arg); + return; + } + break; + case 4: + case 16: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_RECV) == 0) { + if (g_Joy_wrk.size <= 0) { + g_Joy_wrk.step++; + g_Joy_wrk.send_data = ~g_Joy_wrk.checksum; + } + else if (g_Joy_wrk.block_count == 0xFF) { + g_Joy_wrk.step--; + g_Joy_wrk.send_data = ~g_Joy_wrk.block_checksum; + g_Joy_wrk.block_checksum = 0; + g_Joy_wrk.block_count++; + } + else { + g_Joy_wrk.step--; + g_Joy_wrk.send_data = *(u32*)g_Joy_wrk.buf_p; + g_Joy_wrk.buf_p += sizeof(u32); + g_Joy_wrk.size -= sizeof(u32); + g_Joy_wrk.checksum += g_Joy_wrk.send_data; + g_Joy_wrk.block_checksum += g_Joy_wrk.send_data; + g_Joy_wrk.block_count++; + } + + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, arg); + } + else { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Send, arg); + } + return; + } + break; + case 6: + case 18: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_RECV) == 0) { + g_Joy_wrk.step++; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 2); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, arg); + } + return; + } + break; + case 8: + case 20: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_SEND) != 0) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_Send, arg); + } + else { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Send, arg); + } + return; + } + break; + case 9: + case 21: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data) == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 8)) { + g_Joy_wrk.result = 1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; + return; + } + } + break; + case 11: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_SEND) != 0) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_Send, arg); + } + else { + g_Joy_wrk.step--; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 12); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, arg); + } + return; + } + break; + case 12: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data) == GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GC, 4)) { + g_Joy_wrk.step += 2; + g_Joy_wrk.checksum = 0; + g_Joy_wrk.block_checksum = 0; + g_Joy_wrk.block_count = 0; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Send, arg); + } + else { + g_Joy_wrk.step = 10; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 12); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, arg); + } + return; + } + break; + case 14: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_RECV) == 0) { + g_Joy_wrk.step++; + g_Joy_wrk.send_data = g_Joy_wrk.cmd; + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, arg); + } + else { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_Send, arg); + } + return; + } + break; + } + } + + g_Joy_wrk.result = -1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; +} + +extern "C" int mGcgba_Send(u8* send_bufp, size_t send_buf_size) { + int ret = GBA2_GBA_STATE_TRANSMITTING; + u32 data; + + switch (g_Joy_wrk.state) { + case 0: + if (g_port > 0 && g_port < GBA_MAX_CHAN) { + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doReset(g_port, &CallBack_Connection, NULL); + } + else { + ret = GBA2_GBA_STATE_ERROR; + } + break; + case 1: + if (g_Joy_wrk.busy == FALSE) { + if (g_Joy_wrk.result == 1) { + g_Joy_wrk.buf_p = send_bufp; + g_Joy_wrk.size = send_buf_size; + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = -GBA2_READ_TRIES; + g_Joy_wrk.state++; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 2); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, NULL); + } + else { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_ERROR; + } + } + break; + case 2: + if (g_Joy_wrk.busy == FALSE) { + ret = g_Joy_wrk.result; + g_Joy_wrk.state = 0; + } + break; + } + + if (ret == GBA2_GBA_STATE_TRANSMITTING && ++g_Joy_wrk.timer > GBA2_DEFAULT_TRIES) { + ret = GBA2_GBA_STATE_ERROR; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.state = 0; + } + + return ret; +} + +extern "C" int mGcgba_SendGame(u8* send_bufp, size_t send_buf_size, u8 game_type) { + int ret = GBA2_GBA_STATE_TRANSMITTING; + static int test = 0; + u32 data; + + if (++test < 20) { + return GBA2_GBA_STATE_TRANSMITTING; + } + + switch (g_Joy_wrk.state) { + case 0: + if (g_port > 0 && g_port < GBA_MAX_CHAN) { + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doReset(g_port, &CallBack_Connection, NULL); + } + else { + ret = GBA2_GBA_STATE_ERROR; + } + break; + case 1: + if (g_Joy_wrk.busy == FALSE) { + if (g_Joy_wrk.result == 1) { + g_Joy_wrk.buf_p = send_bufp; + g_Joy_wrk.size = send_buf_size; + g_Joy_wrk.cmd = game_type; + g_Joy_wrk.step = 10; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = -GBA2_READ_TRIES; + g_Joy_wrk.state++; + data = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 12); + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&data); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_Send, NULL); + } + else { + g_Joy_wrk.state = 0; + ret = GBA2_GBA_STATE_ERROR; + } + } + break; + case 2: + if (g_Joy_wrk.busy == FALSE) { + ret = g_Joy_wrk.result; + g_Joy_wrk.state = 0; + } + break; + } + + if (ret == GBA2_GBA_STATE_TRANSMITTING) { + if (++g_Joy_wrk.timer > GBA2_READ_TRIES) { + ret = GBA2_GBA_STATE_ERROR; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.state = 0; + } + } + else { + test = 0; + } + + return ret; +} + +static void CallBack_SendEAppri(JUTGbaParam* param, void* arg) { + u8 status; + + if (g_Joy_wrk.busy == TRUE) { + switch (g_Joy_wrk.step) { + case 0: + if (g_Joy_wrk.gba->resultReset(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_SEND) != 0 && (status & GBA_JSTAT_PSF1) != 0) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_SendEAppri, arg); + } + else { + g_Joy_wrk.gba->doReset(g_port, &CallBack_SendEAppri, arg); + } + return; + } + break; + case 1: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (g_Joy_wrk.recv_data == *(u32*)"PSAJ") { + g_Joy_wrk.step++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_SendEAppri, arg); + } + else { + g_Joy_wrk.step--; + g_Joy_wrk.gba->doReset(g_port, &CallBack_SendEAppri, arg); + } + return; + } + break; + case 2: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if (status == GBA_JSTAT_PSF1) { + g_Joy_wrk.step++; + g_Joy_wrk.send_data = *(u32*)"PSAJ"; + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_SendEAppri, arg); + } + else { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_SendEAppri, arg); + } + return; + } + break; + case 3: + case 5: + if (g_Joy_wrk.gba->resultWrite(g_port, &status) == GBA_READY) { + g_Joy_wrk.step++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_SendEAppri, arg); + return; + } + break; + case 4: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if (status == (GBA_JSTAT_PSF1 | GBA_JSTAT_PSF0)) { + g_Joy_wrk.step++; + g_Joy_wrk.send_data = mJOYSIO_ConvData((u8*)&g_Joy_wrk.size); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_SendEAppri, arg); + } + else { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_SendEAppri, arg); + } + return; + } + break; + case 6: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_SEND) != 0) { + g_Joy_wrk.step++; + g_Joy_wrk.recv_data = 0; + g_Joy_wrk.gba->doRead(g_port, (u8*)&g_Joy_wrk.recv_data, &CallBack_SendEAppri, arg); + } + else { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_SendEAppri, arg); + } + return; + } + break; + case 7: + if (g_Joy_wrk.gba->resultRead(g_port, &status) == GBA_READY) { + if (g_Joy_wrk.size == mJOYSIO_ConvData((u8*)&g_Joy_wrk.recv_data)) { + g_Joy_wrk.step++; + } + else { + g_Joy_wrk.step--; + } + + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_SendEAppri, arg); + return; + } + break; + case 8: + if (g_Joy_wrk.gba->resultGetStatus(g_port, &status) == GBA_READY) { + if ((status & GBA_JSTAT_PSF0) != 0 && (status & GBA_JSTAT_PSF1) != 0) { + if ((status & GBA_JSTAT_RECV) == 0) { + g_Joy_wrk.timer = 0; + g_Joy_wrk.step++; + g_Joy_wrk.send_data = *(u32*)g_Joy_wrk.buf_p; + g_Joy_wrk.buf_p += sizeof(u32); + g_Joy_wrk.size -= sizeof(u32); + g_Joy_wrk.gba->doWrite(g_port, (u8*)&g_Joy_wrk.send_data, &CallBack_SendEAppri, arg); + } + else { + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_SendEAppri, arg); + } + return; + } + } + break; + case 9: + if (g_Joy_wrk.gba->resultWrite(g_port, &status) == GBA_READY) { + if (g_Joy_wrk.size <= 0) { + g_Joy_wrk.result = 1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; + } + else { + g_Joy_wrk.step--; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_SendEAppri, arg); + } + return; + } + break; + } + } + + g_Joy_wrk.result = -1; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.step = 0; +} + +extern "C" int mGcgba_send_eAppri(u8* eappli_p, size_t eappli_size) { + int ret = GBA2_EAPPLI_TRANSMITTING; + + switch (g_Joy_wrk.state) { + case 0: + if (g_port > 0 && g_port < GBA_MAX_CHAN) { + g_Joy_wrk.buf_p = eappli_p; + g_Joy_wrk.size = eappli_size; + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = GBA2_GBA_STATE_TRANSMITTING; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doReset(g_port, &CallBack_SendEAppri, NULL); + } + else { + ret = GBA2_EAPPLI_FAILURE_NO_GBA; + } + break; + case 1: + if (g_Joy_wrk.busy == FALSE) { + if (g_Joy_wrk.result == 1) { + g_Joy_wrk.state++; + } + else { + g_Joy_wrk.state = 0; + ret = GBA2_EAPPLI_FAILURE_NO_GBA; + } + } + break; + case 2: + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = -1; + g_Joy_wrk.timer = -GBA2_READ_TRIES; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doReset(g_port, &CallBack_Connection, NULL); + break; + case 3: + if (g_Joy_wrk.busy == FALSE) { + if (g_Joy_wrk.result == 1) { + g_Joy_wrk.cmd = GBA2_MAKE_ACKNOWLEDGE_CODE(GBA2_DEVICE_GBA, 10); + g_Joy_wrk.step = 0; + g_Joy_wrk.busy = TRUE; + g_Joy_wrk.result = -1; + g_Joy_wrk.timer = 0; + g_Joy_wrk.state++; + g_Joy_wrk.gba->doGetStatus(g_port, &CallBack_TypeCheck, NULL); + } + else { + g_Joy_wrk.state = 0; + ret = GBA2_EAPPLI_FAILURE_NO_GBA; + } + } + break; + case 4: + if (g_Joy_wrk.busy == FALSE) { + g_Joy_wrk.state = 0; + if (g_Joy_wrk.result == 1) { + ret = GBA2_EAPPLI_SUCCESS; + } + else { + ret = GBA2_EAPPLI_FAILURE_NO_GBA; + } + } + break; + } + + if (ret == GBA2_EAPPLI_TRANSMITTING && ++g_Joy_wrk.timer > GBA2_DEFAULT_TRIES) { + ret = GBA2_EAPPLI_FAILURE_NO_GBA; + g_Joy_wrk.busy = FALSE; + g_Joy_wrk.state = 0; + } + + return ret; +} diff --git a/src/static/initial_menu.c b/src/static/initial_menu.c new file mode 100644 index 00000000..5b270eb6 --- /dev/null +++ b/src/static/initial_menu.c @@ -0,0 +1,442 @@ +#define FIX_SQRT_LINKAGE +#include "initial_menu.h" +#include "PR/mbi.h" +#include "libforest/gbi_extensions.h" +#include "m_nmibuf.h" +#include "dolphin/dvd.h" +#include "jsyswrap.h" +#include "boot.h" +#include "dolphin/os/OSFont.h" +#include "bootdata.h" +#include "libultra/libultra.h" +#include "libforest/emu64/emu64_wrapper.h" +#include "dolphin/vi.h" +// #include "dolphin/os/OSRtc.h" +#include "dolphin/os/OSMessage.h" +#include "dolphin/os/OSResetSW.h" +#include "dolphin/os/OSReset.h" +#include "dolphin/os.h" +#include "m_controller.h" +#include "dvderr.h" + +#define G_CC_LOGO 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0 + +static Mtx model_cursor; +static u8 progressive_mode; + +static Gfx gam_win1_cursor_setup[] = { + gsSPTexture(0, 0, 0, 0, G_OFF), + gsDPSetCombineMode(G_CC_PRIMITIVE, G_CC_PRIMITIVE), + gsDPSetRenderMode(G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2), + gsSPLoadGeometryMode(G_SHADE | G_SHADING_SMOOTH), + gsSPEndDisplayList(), +}; + +static Gfx gam_win1_moji_setup[] = { + gsSPTexture(0, 0, 0, 0, G_ON), + gsDPSetCombineMode(G_CC_BLENDPRIMDECALA, G_CC_BLENDPRIMDECALA), + gsDPSetRenderMode(G_RM_XLU_SURF, G_RM_XLU_SURF2), + gsSPLoadGeometryMode(G_SHADE | G_SHADING_SMOOTH), + gsSPEndDisplayList(), +}; + +static Vp viewport = { + 1280, 960, 511, 0, + 1280, 960, 511, 0 +}; + +static Mtx projection = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xFFFF0000, 0x00000000, 0xFFFF0001, + 0x00CC0000, 0x00000000, 0x00000111, 0x00000000, + 0x00000000, 0xFFFF0000, 0x00000000, 0x00000000 +}; + +static Mtx lookat = { + 0x10000, 0x00000, 0x00001, 0x00000, + 0x00000, 0x10000, 0x00000, 0x00001, + 0x00000, 0x00000, 0x00000, 0x00000, + 0x00000, 0x00000, 0x00000, 0x00000 +}; + +static Mtx default_model_scale = { + 0x20000, 0x00000, 0x00002, 0x00000, + 0x00000, 0x10000, 0x00000, 0x00001, + 0x00000, 0x00000, 0x00000, 0x00000, + 0x00000, 0x00000, 0x00000, 0x00000 +}; + +static Mtx logo_model_scale = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00010000, 0x00000000, 0x00000001, + 0x028F0000, 0x00000000, 0x0000028F, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +static Gfx initial_dl[] = { + gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, 640, 480), + gsSPClipRatio(FRUSTRATIO_2), + gsSPViewport(&viewport), + gsSPMatrix(&projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION), + gsSPMatrix(&lookat, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION), + gsSPMatrix(&default_model_scale, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW), + gsDPSetOtherMode(G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2), + gsSPEndDisplayList(), +}; + +static Gfx logo_draw_dl[] = { + gsSPDisplayList(initial_dl), + gsSPDisplayList(gam_win1_moji_setup), + gsDPSetPrimColor(0, 255, 0, 70, 255, 255), + gsSPMatrix(&logo_model_scale, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW), + gsSPDisplayList(logo_ninT_model), + gsSPPopMatrix(G_MTX_MODELVIEW), + gsSPEndDisplayList(), +}; + +static Gfx step1_draw_dl[] = { + gsSPDisplayList(initial_dl), + gsSPDisplayList(gam_win1_moji_setup), + gsSPDisplayList(gam_win1_winT_model), + gsSPDisplayList(gam_win1_moji_model), + gsDPSetPrimColor(0, 255, 90, 90, 155, 255), + gsSPDisplayList(0x08000000), + gsDPSetPrimColor(0, 255, 50, 30, 150, 255), + gsSPDisplayList(0x09000000), + gsSPDisplayList(gam_win1_cursor_setup), + gsSPMatrix(&model_cursor, G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW), + gsSPDisplayList(gam_win1_cursor_model), + gsSPPopMatrix(G_MTX_MODELVIEW), + gsSPEndDisplayList(), +}; + +static Gfx step2_draw_dl[] = { + gsSPDisplayList(initial_dl), /* call initial dl */ + gsSPDisplayList(gam_win1_moji_setup), /* call gam_win1_moji_setup */ + gsDPSetPrimColor(0, 255, 225, 255, 255, 255), /* set primitive color to off-white */ + gsSPDisplayList(gam_win2_winT_model), /* call gam_win2_winT_model */ + gsDPSetPrimColor(0, 255, 50, 50, 60, 255), /* set primitive color to dark blue-gray */ + gsSPDisplayList(gam_win2_moji_model), + gsSPDisplayList(0x08000000), /* call progressive mode model set in step2_make_dl */ + gsSPEndDisplayList(), +}; + +static int pad_good_frame_count = -1; + +static void step0_make_dl(Gfx** gpp) { + Gfx* g = *gpp; + + if (APPNMI_TESTMODE_GET()) { + DVDDiskID* diskId = DVDGetCurrentDiskID(); + if (boot_copyDate != NULL) { + JW_JUTReport(150, 400, 1, "COPYDATE: %.17s", boot_copyDate); + } + + if (diskId != NULL) { + JW_JUTReport(150, 330, 1, ""); + JW_JUTReport(150, 342, 1, "GAMENAME: %.4s", diskId->gameName); + JW_JUTReport(150, 354, 1, " COMPANY: %.2s", diskId->company); + JW_JUTReport(150, 366, 1, " VERSION: 0x%02X(%d)", diskId->gameVersion, diskId->gameVersion); + } + + JW_JUTReport(150, 330, 1, ""); /* I belive the above is a 'bug', because this is the exact same print */ + JW_JUTReport(150, 50, 1, "SDK VERSION: 08May2003 Patch3"); + + if (OSGetFontEncode() != OS_FONT_ENCODE_SJIS) { + JW_JUTReport(150, 100, 1, " ****** WARNING ******"); + JW_JUTReport(150, 112, 1, "The DISP SW isn't JAPAN MODE now"); + JW_JUTReport(150, 124, 1, "but this GAME is JAPAN version"); + } + } + + if (APPNMI_SHOPPROMOVERSION_GET()) { + JW_JUTReport(150, 410, 1, "SHOP PROMOTE VERSION"); + } + + gSPDisplayList(g++, logo_draw_dl); + *gpp = g; +} + +extern void make_dl_nintendo_logo(Gfx** gpp, u32 alpha) { + Gfx* g = *gpp; + + gSPSegment(g++, G_MWO_SEGMENT_8, initial_dl); /* segment 8 = initial_dl */ + gSPSegment(g++, G_MWO_SEGMENT_9, gam_win1_moji_setup); /* segment 9 = gam_win1_moji_setup */ + gSPDisplayList(g++, SEGMENT_ADDR(8, 0)); /* call to segment 8 (initial_dl) */ + gSPDisplayList(g++, SEGMENT_ADDR(9, 0)); /* call to segment 9 (gam_win1_moji_setup) */ + gSPMatrix(g++, &logo_model_scale, G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW); /* set logo model scale */ + gDPSetCombineMode(g++, G_CC_LOGO, G_CC_LOGO); /* set color combiner for logo */ + gDPSetPrimColor(g++, 0, 255, 0, 70, 255, alpha); /* set logo color */ + gSPDisplayList(g++, logo_ninT_model); /* call logo display list (logo_ninT_model) */ + gSPPopMatrix(g++, G_MTX_MODELVIEW); /* remove logo model scale */ + + *gpp = g; +} + +static void step1_make_dl(Gfx** gpp) { + static Gfx* yes_no_model[2] = { + gam_win1_moji2_model, + gam_win1_moji3_model + }; + + Gfx* g = *gpp; + + guTranslate(&model_cursor, progressive_mode != 0 ? -42 : 0, -86.0f, 0.0f); + + gSPSegment(g++, G_MWO_SEGMENT_8, yes_no_model[progressive_mode]); /* segment 8 is yes/no */ + gSPSegment(g++, G_MWO_SEGMENT_9, yes_no_model[progressive_mode ^ 1]); /* segment 9 is inverse yes/no */ + gSPDisplayList(g++, step1_draw_dl); /* call step1 display list */ + + *gpp = g; +} + +static void step2_make_dl(Gfx** gpp) { + Gfx* g = *gpp; + + gSPSegment(g++, G_MWO_SEGMENT_8, progressive_mode != 0 ? gam_win2_moji2_model : gam_win3_moji_model); + gSPDisplayList(g++, step2_draw_dl); + + *gpp = g; +} + +static u8 menu_step; + +static void make_dl(Gfx* gfx, int size) { + Gfx* g = gfx; + + step0_make_dl(&g); + if (menu_step == 1 || menu_step == 11) { + step1_make_dl(&g); + } + else if (menu_step == 2) { + step2_make_dl(&g); + } + + gDPFullSync(g++); + gSPEndDisplayList(g++); +} + +extern void exec_dl(Gfx* gfx) { + emu64_init(); + emu64_taskstart(gfx); + emu64_cleanup(); +} + +static Z_OSTime start_time; +static u32 button; +static u32 trigger; +static int frame_count; +static Z_OSTime limit_time; +static int select_done; +static u8 menu_sub_frame; + +extern void keycheck() { + Z_OSTime now = osGetTime(); + Z_OSTime delta = now - start_time; + u32 t; + u32 error; + + JC_JUTGamePad_read(); + button = JW_JUTGamepad_getButton(); + t = JW_JUTGamepad_getTrigger(); + trigger = t; + trigger |= (((t >> 16) | (t >> 24)) & 0xF); + error = JW_JUTGamepad_getErrorStatus(); + + if (pad_good_frame_count < 0 && error == 0) { + pad_good_frame_count = frame_count; + } + + if (menu_step == 0) { + u32 dtv_status = VIGetDTVStatus(); + + if (OSGetProgressiveMode() && !dtv_status) { + progressive_mode = FALSE; + OSSetProgressiveMode(progressive_mode); + } + else if ((button == B || OSGetProgressiveMode()) && dtv_status) { + progressive_mode = TRUE; + menu_step = 1; + start_time = now; + limit_time = button == B ? INITIAL_MENU_LIMIT_TIME : INITIAL_MENU_LIMIT_TIME; // 10 second limit + } + else { + if (limit_time < delta) { + menu_step = 3; + select_done = TRUE; + start_time = now; + } + } + } + else if (menu_step == 1) { + if ((trigger & A) != 0 || limit_time < delta) { + OSSetProgressiveMode(progressive_mode); + start_time = now; + menu_step = 11; + menu_sub_frame = 0; + } + else { + if ((trigger & DPAD_LEFT)) { + progressive_mode = TRUE; + start_time = now; + limit_time = INITIAL_MENU_LIMIT_TIME; + } + else { + if ((trigger & DPAD_RIGHT)) { + progressive_mode = FALSE; + start_time = now; + limit_time = INITIAL_MENU_LIMIT_TIME; + } + } + } + } + else if (menu_step == 11) { + switch (menu_sub_frame) { + case 0: + { + JC_JFWDisplay_startFadeOut(JC_JFWDisplay_getManager(), 10); + break; + } + + case 5: + { + JW_SetProgressiveMode(progressive_mode); + break; + } + + case 105: + { + JC_JFWDisplay_startFadeIn(JC_JFWDisplay_getManager(), 15); + start_time = now; + menu_step = 2; + break; + } + } + + menu_sub_frame++; + } + else { + if (menu_step == 2 && INITIAL_MENU_SELECT_WAIT_TIME < delta) { + menu_step = 3; + select_done = TRUE; + start_time = now; + } + } +} + +static OSMessageQueue commandQ; +static int fadeout_step; +static int load_game_done; +static Gfx gfxbuf[16]; +static OSMessageQueue statusQ; +static OSThread* Thread_p; +static void* initialMenuStack; +static OSMessage commandMsgBuf[2]; +static OSMessage statusMsgBuf[1]; + +extern void proc(void* arg) { + u32 msg; + int proc_done; + OSTimer timer; + + osRecvMesg(&commandQ, (OSMessage*)&msg, OS_MESSAGE_BLOCK); + progressive_mode = FALSE; + fadeout_step = 0; + menu_step = 0; + select_done = FALSE; + load_game_done = FALSE; + start_time = osGetTime(); + limit_time = OSMicrosecondsToTicks(5000000ull); + pad_good_frame_count = -1; + frame_count = 0; + + do { + if (OSGetResetSwitchState()) { + __osResetSwitchPressed = TRUE; + } + else { + if (__osResetSwitchPressed) { + osShutdownStart(OS_RESET_RESTART); + } + } + + if (!osRecvMesg(&commandQ, (OSMessage*)&msg, OS_MESSAGE_NOBLOCK)) { + if (msg == INITIAL_MENU_OSMESG_FADEOUT_STEP) { + fadeout_step = 2; + } + + if (msg == INITIAL_MENU_OSMESG_LOAD_GAME_DONE) { + load_game_done = TRUE; + } + } + + if (fadeout_step == 0 && select_done && load_game_done) { + fadeout_step = 1; + osSetTimer(&timer, OSMicrosecondsToTicks(533312ull), 0, &commandQ, (OSMessage)INITIAL_MENU_OSMESG_FADEOUT_STEP); + JC_JFWDisplay_startFadeOut(JC_JFWDisplay_getManager(), 32); + } + + if ((menu_step != 0 && menu_step != 3) || dvderr_draw() == FALSE) { + JW_BeginFrame(); + keycheck(); + make_dl(gfxbuf, 16); + exec_dl(gfxbuf); + JW_EndFrame(); + frame_count++; + } + + proc_done = FALSE; + if (fadeout_step == 2 && select_done && load_game_done) { + proc_done = TRUE; + } + } while (!proc_done); + + osSendMesg(&statusQ, (OSMessage)msg, OS_MESSAGE_NOBLOCK); // signal done +} + +static void* my_alloc(size_t size) { + return JW_Alloc(size, 32); +} + +static void my_free(void* ptr) { + JW_Free(ptr); +} + +extern void initial_menu_init() { + Thread_p = (OSThread*)my_alloc(sizeof(OSThread)); + initialMenuStack = my_alloc(INITIAL_MENU_STACK_SIZE); + if (Thread_p == NULL || initialMenuStack == NULL) { + OSReport("initial_menu_init: Memory insufficiency.\n"); + my_free(Thread_p); + Thread_p = NULL; + my_free(initialMenuStack); + initialMenuStack = NULL; + } + else { + osCreateMesgQueue(&commandQ, commandMsgBuf, 2); + osCreateMesgQueue(&statusQ, statusMsgBuf, 1); + osCreateThread2(Thread_p, 1, &proc, NULL, (void*)((int)initialMenuStack + INITIAL_MENU_STACK_SIZE), INITIAL_MENU_STACK_SIZE, 1); + osStartThread(Thread_p); + JC_JFWDisplay_startFadeIn(JC_JFWDisplay_getManager(), 32); + osSendMesg(&commandQ, (OSMessage)INITIAL_MENU_OSMESG_INIT_DONE, OS_MESSAGE_NOBLOCK); + } +} + +extern void initial_menu_cleanup() { + int msg; + + if (Thread_p != NULL) { + if (!osRecvMesg(&commandQ, (OSMessage*)&msg, OS_MESSAGE_NOBLOCK)) { + osSendMesg(&commandQ, (OSMessage)INITIAL_MENU_OSMESG_LOAD_GAME_DONE, OS_MESSAGE_NOBLOCK); + osRecvMesg(&statusQ, (OSMessage*)&msg, OS_MESSAGE_BLOCK); + } + + osDestroyThread(Thread_p); + } + + JC_JFWDisplay_startFadeIn(JC_JFWDisplay_getManager(), 32); + my_free(Thread_p); + Thread_p = NULL; + my_free(initialMenuStack); + initialMenuStack = NULL; +} diff --git a/src/static/libforest/ReconfigBATs.c b/src/static/libforest/ReconfigBATs.c new file mode 100644 index 00000000..b6cfe57c --- /dev/null +++ b/src/static/libforest/ReconfigBATs.c @@ -0,0 +1,72 @@ +#include "libforest/batconfig.h" + +asm void Config24MB(){ +nofralloc +/* 8005ADAC 7C6000A6 */ mfmsr r3 +/* 8005ADB0 54630734 */ rlwinm r3, r3, 0, 0x1c, 0x1a +/* 8005ADB4 7C600124 */ mtmsr r3 +/* 8005ADB8 4C00012C */ isync +/* 8005ADBC 38E00000 */ li r7, 0x0 +/* 8005ADC0 3C800000 */ lis r4, 0 +/* 8005ADC4 38840002 */ addi r4, r4, 0x2 +/* 8005ADC8 3C608000 */ lis r3, 0x8000 +/* 8005ADCC 386301FF */ addi r3, r3, 0x1ff +/* 8005ADD0 3CC00100 */ lis r6, 0x100 +/* 8005ADD4 38C60002 */ addi r6, r6, 0x2 +/* 8005ADD8 3CA08100 */ lis r5, 0x8100 +/* 8005ADDC 38A500FF */ addi r5, r5, 0xff +/* 8005ADE0 4C00012C */ isync +/* 8005ADE4 7CF883A6 */ mtdbatu 0, r7 +/* 8005ADE8 7C9983A6 */ mtdbatl 0, r4 +/* 8005ADEC 7C7883A6 */ mtdbatu 0, r3 +/* 8005ADF0 4C00012C */ isync +/* 8005ADF4 7CFC83A6 */ mtdbatu 2, r7 +/* 8005ADF8 7CDD83A6 */ mtdbatl 2, r6 +/* 8005ADFC 7CBC83A6 */ mtdbatu 2, r5 +/* 8005AE00 4C00012C */ isync +/* 8005AE04 7C6000A6 */ mfmsr r3 +/* 8005AE08 60630010 */ ori r3, r3, 0x10 +/* 8005AE0C 7C600124 */ mtmsr r3 +/* 8005AE10 4C00012C */ isync +/* 8005AE14 4E800020 */ blr +} +asm void Config48MB(){ +nofralloc +/* 8005AE18 7C6000A6 */ mfmsr r3 +/* 8005AE1C 54630734 */ rlwinm r3, r3, 0, 0x1c, 0x1a +/* 8005AE20 7C600124 */ mtmsr r3 +/* 8005AE24 4C00012C */ isync +/* 8005AE28 38E00000 */ li r7, 0x0 +/* 8005AE2C 3C800000 */ lis r4, 0 +/* 8005AE30 38840002 */ addi r4, r4, 0x2 +/* 8005AE34 3C608000 */ lis r3, 0x8000 +/* 8005AE38 386303FF */ addi r3, r3, 0x3ff +/* 8005AE3C 3CC00200 */ lis r6, 0x200 +/* 8005AE40 38C60002 */ addi r6, r6, 0x2 +/* 8005AE44 3CA08200 */ lis r5, 0x8200 +/* 8005AE48 38A501FF */ addi r5, r5, 0x1ff +/* 8005AE4C 4C00012C */ isync +/* 8005AE50 7CF883A6 */ mtdbatu 0, r7 +/* 8005AE54 7C9983A6 */ mtdbatl 0, r4 +/* 8005AE58 7C7883A6 */ mtdbatu 0, r3 +/* 8005AE5C 4C00012C */ isync +/* 8005AE60 7CFC83A6 */ mtdbatu 2, r7 +/* 8005AE64 7CDD83A6 */ mtdbatl 2, r6 +/* 8005AE68 7CBC83A6 */ mtdbatu 2, r5 +/* 8005AE6C 4C00012C */ isync +/* 8005AE70 7C6000A6 */ mfmsr r3 +/* 8005AE74 60630010 */ ori r3, r3, 0x10 +/* 8005AE78 7C600124 */ mtmsr r3 +/* 8005AE7C 4C00012C */ isync +/* 8005AE80 4E800020 */ blr +} +void ReconfigBATs(){ + BOOL rest = OSDisableInterrupts(); + if (OSGetConsoleSimulatedMemSize() <= 0x1800000){ + Config24MB(); + } + else { + Config48MB(); + } + OSRestoreInterrupts(rest); +} \ No newline at end of file diff --git a/src/static/libforest/fault.c b/src/static/libforest/fault.c new file mode 100644 index 00000000..7011737e --- /dev/null +++ b/src/static/libforest/fault.c @@ -0,0 +1,147 @@ +#include "libforest/fault.h" +#include "terminal.h" +// #include "va_args.h" +#include "jsyswrap.h" +#include "dolphin/os.h" + +static fault* this = NULL; +static fault fault_class; + +extern void fault_AddClientEx(fault_client* client, FaultCallback callback, const char* msg, u32 param, u8 priority, u8 flags) { + BOOL enable; + BOOL client_exists; + fault_client* f0; + fault_client* f1; + + client_exists = FALSE; + if (client == NULL || callback == NULL) { + return; + } + + enable = OSDisableInterrupts(); + f0 = NULL; + for (f1 = this->first_client; f1 != NULL; f1 = f1->next) { + if (f1 == client) { + client_exists = TRUE; + goto exit; + } + + if (f1->priority >= priority ) { + f0 = f1; + } + } + + client->callback = callback; + client->msg = msg; + client->param = param; + client->priority = priority; + client->flags = flags; + if (f0 != NULL) { + client->next = f0->next; + f0->next = client; + } + else { + client->next = this->first_client; + this->first_client = client; + } + + this->num_clients++; + +exit: + OSRestoreInterrupts(enable); + if (client_exists != FALSE) { + OSReport(VT_COL(RED, WHITE) "fault_AddClient: %08x は既にリスト中にある\n" VT_RST, client); + } +} + +extern void fault_AddClient(fault_client* client, FaultCallback callback, const char* msg, u32 param) { + fault_AddClientEx(client, callback, msg, param, FAULT_MIN_PRIORITY, FAULT_FLAG_POSTEXCEPTION); +} + +extern void fault_Printf(const char* fmt, ...) { + void* console; + + console = JC_JUTException_getConsole(); + if (console != NULL) { + va_list arg; + va_start(arg, fmt); + JC_JUTConsole_print_f_va(console, fmt, arg); + va_end(arg); + } +} + +extern void fault_DrawUpdate() { + void* manager = JC_JUTConsoleManager_getManager(); + if (manager != NULL) { + JC_JUTConsoleManager_drawDirect(manager, TRUE); + } +} + +extern void fault_WaitTime(u32 waitTime) { + JC_JUTException_waitTime(waitTime); +} + +extern int fault_ReadPad(u32* outTrigger, u32* outButton) { + void* manager; + + manager = JC_JUTException_getManager(); + if (manager == NULL) { + return FAULT_PAD_READ_FAILED; + } + else { + JC_JUTException_readPad(manager, outTrigger, outButton); + return FAULT_PAD_READ_SUCCESS; + } +} + +static void fault_CallBackFunc(int stage) { + fault_client* client; + int index; + + index = 0; + for (client = this->first_client; client != NULL; client = client->next) { + if (client->callback != NULL) { + if ((client->flags & (1 << stage)) != 0) { + if ((client->flags & FAULT_FLAG_SKIP_DRAW_SEPARATOR) == 0) { + fault_Printf("---------------------------------------------\n"); + fault_DrawUpdate(); + } + + if ((client->flags & FAULT_FLAG_SKIP_DRAW_CALLBACK_INFO) == 0) { + fault_Printf("CallBack (%d/%d) %08x %08x %08x\n", index++, this->num_clients, client, client->msg, client->param); + fault_DrawUpdate(); + } + + (*client->callback)(client->msg, client->param); + fault_DrawUpdate(); + } + } + } + + fault_DrawUpdate(); +} + +static void my_PreExceptionCallback() { + if (JC_JUTException_getConsole() != NULL && JC_JUTConsoleManager_getManager() != NULL && JC_JUTException_getManager() != NULL) { + fault_CallBackFunc(FAULT_STAGE_PRE); + } +} + +static void my_PostExceptionCallback() { + if (JC_JUTException_getConsole() != NULL && JC_JUTConsoleManager_getManager() != NULL && JC_JUTException_getManager() != NULL) { + fault_CallBackFunc(FAULT_STAGE_POST); + } +} + +extern void fault_Init() { + this = &fault_class; + bzero(&fault_class, sizeof(fault_class)); + this->_0 = 0; + this->_1 = 0; + this->_2 = 0; + this->first_client = NULL; + this->_3 = 0; + fault_class._2 = 1; + JC_JUTException_setPreUserCallback(&my_PreExceptionCallback); + JC_JUTException_setPostUserCallback(&my_PostExceptionCallback); +} diff --git a/src/static/libforest/osreport.c b/src/static/libforest/osreport.c new file mode 100644 index 00000000..37760f0d --- /dev/null +++ b/src/static/libforest/osreport.c @@ -0,0 +1,85 @@ +#include "libforest/osreport.h" +#include "dolphin/os/OSInterrupt.h" +#include "dolphin/os/OSRtc.h" + +#include "MSL_C/printf.h" + +static BOOL __OSReport_disable; +static OSThread* __OSReport_MonopolyThread; +static u8 print_mutex_initialized; +static OSMutex print_mutex; + +extern void OSReportDisable() { + __OSReport_disable = TRUE; +} + +extern void OSReportEnable() { + __OSReport_disable = FALSE; +} + +void OSVReport(const char* fmt, va_list list) { + OSThread* cur_thread; + u32 enable; + + if (__OSReport_disable == FALSE) { + cur_thread = OSGetCurrentThread(); + if ((cur_thread != NULL) && (cur_thread->state != (u32)OS_THREAD_STATE_RUNNING)) { + cur_thread = NULL; + } + if ((__OSReport_MonopolyThread == NULL) || (__OSReport_MonopolyThread == cur_thread)) { + if (print_mutex_initialized == FALSE) { + enable = OSDisableInterrupts(); + if (print_mutex_initialized == FALSE) { + OSInitMutex(&print_mutex); + print_mutex_initialized = TRUE; + printf("*** OSVReport - OSInitMutex ***"); + } + OSRestoreInterrupts(enable); + } + if (cur_thread != NULL) { + OSLockMutex(&print_mutex); + } + vprintf(fmt, list); + if (cur_thread != NULL) { + OSUnlockMutex(&print_mutex); + } + } + } +} + +void OSReport(const char* fmt, ...) { + va_list arg; + va_start(arg, fmt); + OSVReport(fmt, arg); + va_end(arg); +} + +void OSPanic(const char* file, int line, const char* fmt, ...) { + va_list list; + u32 enable; + OSThread* thread; + enable = OSDisableInterrupts(); + + + va_start(list, fmt); + vprintf(fmt, list); + va_end(list); + printf(" in \"%s\" on line %d.\n", file, line); + + thread = OSGetCurrentThread(); + + OSSetThreadPriority(thread, OS_PRIORITY_IDLE); + OSRestoreInterrupts(enable); + OSThrow(); /* Stop processor execution forcefully */ +} + +extern void OSChangeBootMode(u32 mode) { + __OSSetBootMode(mode ? OS_BOOT_MODE_RETAIL : OS_BOOT_MODE_DEBUG); + + while(__OSSyncSram() == FALSE) { } +} + +extern void OSDVDFatalError(void) { + OSReport("OSDVDFatalError called.\nExitThread.\n"); + OSExitThread(NULL); +} diff --git a/src/static/nintendo_hi_0.c b/src/static/nintendo_hi_0.c new file mode 100644 index 00000000..3444afb5 --- /dev/null +++ b/src/static/nintendo_hi_0.c @@ -0,0 +1,5 @@ +#include "nintendo_hi_0.h" + +u8 nintendo_hi_0[NINTENDO_HI_0_SIZE] ATTRIBUTE_ALIGN(32) = { +#include "assets/nintendo_hi_0.inc" +}; diff --git a/src/static/version.c b/src/static/version.c new file mode 100644 index 00000000..8360da8d --- /dev/null +++ b/src/static/version.c @@ -0,0 +1,11 @@ +#include "version.h" + +char __Creator__[] = { +#include "assets/__Creator__.inc" +}; + +char __DateTime__[] = { +#include "assets/__DateTime__.inc" +}; + + From 4dc6f0e119d204d6e85a93a1cccfa837284c1c38 Mon Sep 17 00:00:00 2001 From: h0504 Date: Tue, 27 Oct 2026 08:25:58 +0900 Subject: [PATCH 6/7] Add REL module fakemain and align glider data forestd, foresti and foresto share an executor.o/fakemain.o prolog. Add fakemain.c; glider_v needs 32-byte alignment so its .data starts at 0x20 after fakemain's string, as in forestd.map. Co-Authored-By: Claude Opus 5.5 --- src/data/always/glider.c | 2 +- src/fakemain.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 src/fakemain.c diff --git a/src/data/always/glider.c b/src/data/always/glider.c index 5f60f122..e560eb3a 100644 --- a/src/data/always/glider.c +++ b/src/data/always/glider.c @@ -2,7 +2,7 @@ #include "libforest/gbi_extensions.h" #include "PR/mbi.h" -Vtx glider_v[] ATTRIBUTE_ALIGN(8) = { +Vtx glider_v[] ATTRIBUTE_ALIGN(32) = { #include "assets/forestd/glider/glider_v.inc" }; diff --git a/src/fakemain.c b/src/fakemain.c new file mode 100644 index 00000000..9141cc0e --- /dev/null +++ b/src/fakemain.c @@ -0,0 +1,6 @@ +#include "main.h" +#include "dolphin/os.h" + +void main() { + OSReport("fake main() called.\n"); +} From 9620cef2e69194d4c006ca78be023ac195187aa3 Mon Sep 17 00:00:00 2001 From: h0504 Date: Tue, 27 Oct 2026 08:26:08 +0900 Subject: [PATCH 7/7] Configure and link matched units for Rev 1 - splits: name Rev 1 SDK units GAEJ01_01/dolphin/..., jsyswrap.cpp, jaudio_PP/internal/oneshot.c, bootdata/gam_win1-3.c + logo_nin.c, and module/executor.c + fakemain.c in forestd/foresti/foresto. - configure.py: register Rev 1 SDK, MSL_C, MetroTRK, boot, libforest and bootdata objects; mark everything that links byte-identically as Matching for GAEJ01_01 (per-object flags where Rev 1 needs them, e.g. JoyBoot/jsyswrap -inline off -sym on, JUTSDFile GC/1.3.2, mtx 1.2.5n). - config.yml: block false-positive relocations found in data (nintendo_hi_0, JUTDirectPrint font, jaudio tables, Famicom palette, dvderr textures) and add boot/dvderr asset extraction. - symbols.txt: TRKAccessFile/OpenFile/CloseFile/PositionFile are size-8 functions. GAEJ01_01 now builds to the original static.dol and all four RELs. Remaining Rev 1 code: carddrv CARD_SendOpCond/CARD_SoftReset, fs_form FS_init_pbs, JUTException showGPRMap, JFWDisplay beginRender (register allocation only). Co-Authored-By: Claude Opus 5.5 --- config/GAEJ01_01/config.yml | 330 ++++++++++++++++++++++++ config/GAEJ01_01/forestd/splits.txt | 4 +- config/GAEJ01_01/foresti/splits.txt | 4 +- config/GAEJ01_01/foresto/splits.txt | 4 +- config/GAEJ01_01/splits.txt | 192 +++++++------- config/GAEJ01_01/symbols.txt | 12 +- configure.py | 378 +++++++++++++++++++++------- 7 files changed, 725 insertions(+), 199 deletions(-) diff --git a/config/GAEJ01_01/config.yml b/config/GAEJ01_01/config.yml index 5c5e788b..5891cfe4 100644 --- a/config/GAEJ01_01/config.yml +++ b/config/GAEJ01_01/config.yml @@ -15,10 +15,31 @@ fill_gaps: true ldscript_template: config/GAEJ01_01/ldscript.tpl block_relocations: +# jaudio dspinterface DSPRES_FILTER / jamosc TRE_TABLE (numeric tables, false positive pointers) +- source: 0x800FB620 +- source: 0x800FC19C +# Famicom ksNesPaletteNormal (palette data, false positive pointers) +- source: 0x800FE3CC +- source: 0x800FE3EC +- source: 0x800FE40C +- source: 0x800FE42C +# Famicom float constant pool (false positive pointer) +- source: 0x800FE590 +# JUTDirectPrint::sFontData2 (font bitmap, false positive pointer into __savedGXdata) +- source: 0x801053F8 +# nintendo_hi_0 (compressed data, false positive pointers) +- source: 0x800ECD80 +- source: 0x800EE898 # dspboot - source: 0x800FAE38 # emu64 - source: 0x800FF0F4 +# dvderr textures (false positive pointers) +- source: 0x800D9AFC +- source: 0x800DC7DC +- source: 0x800DC848 +- source: 0x800DCDFC +- source: 0x800DD27C add_relocations: # emu64 @@ -39,6 +60,315 @@ extract: - symbol: JUTResFONT_Ascfont_fix12 binary: assets/JSystem/JUtility/FontData/Ascfont_fix12.bfn +- symbol: __Creator__ + binary: assets/__Creator__.bin + header: assets/__Creator__.inc + header_type: raw + +- symbol: __DateTime__ + binary: assets/__DateTime__.bin + header: assets/__DateTime__.inc + header_type: raw + +- symbol: dvd_keikoku_moji1_tex + binary: assets/dvd_keikoku_moji1_tex.bin + header: assets/dvd_keikoku_moji1_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji2_tex + binary: assets/dvd_keikoku_moji2_tex.bin + header: assets/dvd_keikoku_moji2_tex.inc + header_type: raw + +- symbol: dvd_keikoku_pp_moji1_tex + binary: assets/dvd_keikoku_pp_moji1_tex.bin + header: assets/dvd_keikoku_pp_moji1_tex.inc + header_type: raw + +- symbol: ctl_att_w1_tex + binary: assets/ctl_att_w1_tex.bin + header: assets/ctl_att_w1_tex.inc + header_type: raw + +- symbol: ctl_att_w2_tex + binary: assets/ctl_att_w2_tex.bin + header: assets/ctl_att_w2_tex.inc + header_type: raw + +- symbol: ctl_att_w3_tex + binary: assets/ctl_att_w3_tex.bin + header: assets/ctl_att_w3_tex.inc + header_type: raw + +- symbol: ctl_att_w4_tex + binary: assets/ctl_att_w4_tex.bin + header: assets/ctl_att_w4_tex.inc + header_type: raw + +- symbol: ctl_att_w5_tex + binary: assets/ctl_att_w5_tex.bin + header: assets/ctl_att_w5_tex.inc + header_type: raw + +- symbol: ctl_att_w6_tex + binary: assets/ctl_att_w6_tex.bin + header: assets/ctl_att_w6_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji3_tex + binary: assets/dvd_keikoku_moji3_tex.bin + header: assets/dvd_keikoku_moji3_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji4_tex + binary: assets/dvd_keikoku_moji4_tex.bin + header: assets/dvd_keikoku_moji4_tex.inc + header_type: raw + +- symbol: dvd_keikoku_e_tex + binary: assets/dvd_keikoku_e_tex.bin + header: assets/dvd_keikoku_e_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji5_tex + binary: assets/dvd_keikoku_moji5_tex.bin + header: assets/dvd_keikoku_moji5_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji6_tex + binary: assets/dvd_keikoku_moji6_tex.bin + header: assets/dvd_keikoku_moji6_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji7_tex + binary: assets/dvd_keikoku_moji7_tex.bin + header: assets/dvd_keikoku_moji7_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji8_tex + binary: assets/dvd_keikoku_moji8_tex.bin + header: assets/dvd_keikoku_moji8_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji9_tex + binary: assets/dvd_keikoku_moji9_tex.bin + header: assets/dvd_keikoku_moji9_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji10_tex + binary: assets/dvd_keikoku_moji10_tex.bin + header: assets/dvd_keikoku_moji10_tex.inc + header_type: raw + +- symbol: dvd_keikoku_maru_tex + binary: assets/dvd_keikoku_maru_tex.bin + header: assets/dvd_keikoku_maru_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji11_tex + binary: assets/dvd_keikoku_moji11_tex.bin + header: assets/dvd_keikoku_moji11_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji13_tex + binary: assets/dvd_keikoku_moji13_tex.bin + header: assets/dvd_keikoku_moji13_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji14_tex + binary: assets/dvd_keikoku_moji14_tex.bin + header: assets/dvd_keikoku_moji14_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji15_tex + binary: assets/dvd_keikoku_moji15_tex.bin + header: assets/dvd_keikoku_moji15_tex.inc + header_type: raw + +- symbol: dvd_keikoku_moji16_tex + binary: assets/dvd_keikoku_moji16_tex.bin + header: assets/dvd_keikoku_moji16_tex.inc + header_type: raw + +- symbol: dvd_keikoku1_v + binary: assets/dvd_keikoku1_v.bin + header: assets/dvd_keikoku1_v.inc + header_type: none + custom_type: vtx + +- symbol: dvd_keikoku2_v + binary: assets/dvd_keikoku2_v.bin + header: assets/dvd_keikoku2_v.inc + header_type: none + custom_type: vtx + +- symbol: dvd_keikoku3_v + binary: assets/dvd_keikoku3_v.bin + header: assets/dvd_keikoku3_v.inc + header_type: none + custom_type: vtx + +- symbol: dvd_keikoku4_v + binary: assets/dvd_keikoku4_v.bin + header: assets/dvd_keikoku4_v.inc + header_type: none + custom_type: vtx + +- symbol: dvd_keikoku5_v + binary: assets/dvd_keikoku5_v.bin + header: assets/dvd_keikoku5_v.inc + header_type: none + custom_type: vtx + +- symbol: gam_win_moji1_tex!.data:0x800E1BA0 + binary: assets/bootdata/win1/gam_win_moji1_tex.bin + header: assets/bootdata/win1/gam_win_moji1_tex.inc + header_type: raw + +- symbol: gam_win_moji2_tex + binary: assets/bootdata/win1/gam_win_moji2_tex.bin + header: assets/bootdata/win1/gam_win_moji2_tex.inc + header_type: raw + +- symbol: gam_win_moji3_tex + binary: assets/bootdata/win1/gam_win_moji3_tex.bin + header: assets/bootdata/win1/gam_win_moji3_tex.inc + header_type: raw + +- symbol: gam_win_moji4_tex + binary: assets/bootdata/win1/gam_win_moji4_tex.bin + header: assets/bootdata/win1/gam_win_moji4_tex.inc + header_type: raw + +- symbol: gam_win_moji5_tex + binary: assets/bootdata/win1/gam_win_moji5_tex.bin + header: assets/bootdata/win1/gam_win_moji5_tex.inc + header_type: raw + +- symbol: att_win_waku1_tex!.data:0x800E2620 + binary: assets/bootdata/win1/att_win_waku1_tex.bin + header: assets/bootdata/win1/att_win_waku1_tex.inc + header_type: raw + +- symbol: att_win_waku2_tex!.data:0x800E2A20 + binary: assets/bootdata/win1/att_win_waku2_tex.bin + header: assets/bootdata/win1/att_win_waku2_tex.inc + header_type: raw + +- symbol: att_win_waku3_tex!.data:0x800E2E20 + binary: assets/bootdata/win1/att_win_waku3_tex.bin + header: assets/bootdata/win1/att_win_waku3_tex.inc + header_type: raw + +- symbol: att_win_waku4_tex!.data:0x800E3220 + binary: assets/bootdata/win1/att_win_waku4_tex.bin + header: assets/bootdata/win1/att_win_waku4_tex.inc + header_type: raw + +- symbol: att_win_waku5_tex!.data:0x800E3620 + binary: assets/bootdata/win1/att_win_waku5_tex.bin + header: assets/bootdata/win1/att_win_waku5_tex.inc + header_type: raw + +- symbol: att_win_waku6_tex!.data:0x800E3A20 + binary: assets/bootdata/win1/att_win_waku6_tex.bin + header: assets/bootdata/win1/att_win_waku6_tex.inc + header_type: raw + +- symbol: gam_win1_v + binary: assets/bootdata/win1/gam_win1_v.bin + header: assets/bootdata/win1/gam_win1_v.inc + header_type: none + custom_type: vtx + +- symbol: gam_win_moji6_tex + binary: assets/bootdata/win2/gam_win_moji6_tex.bin + header: assets/bootdata/win2/gam_win_moji6_tex.inc + header_type: raw + +- symbol: gam_win_moji7_tex + binary: assets/bootdata/win2/gam_win_moji7_tex.bin + header: assets/bootdata/win2/gam_win_moji7_tex.inc + header_type: raw + +- symbol: gam_win_moji8_tex + binary: assets/bootdata/win2/gam_win_moji8_tex.bin + header: assets/bootdata/win2/gam_win_moji8_tex.inc + header_type: raw + +- symbol: gam_win_moji1_tex!.data:0x800E4700 + binary: assets/bootdata/win2/gam_win_moji1_tex.bin + header: assets/bootdata/win2/gam_win_moji1_tex.inc + header_type: raw + +- symbol: att_win_waku1_tex!.data:0x800E4B00 + binary: assets/bootdata/win2/att_win_waku1_tex.bin + header: assets/bootdata/win2/att_win_waku1_tex.inc + header_type: raw + +- symbol: att_win_waku2_tex!.data:0x800E4F00 + binary: assets/bootdata/win2/att_win_waku2_tex.bin + header: assets/bootdata/win2/att_win_waku2_tex.inc + header_type: raw + +- symbol: att_win_waku3_tex!.data:0x800E5300 + binary: assets/bootdata/win2/att_win_waku3_tex.bin + header: assets/bootdata/win2/att_win_waku3_tex.inc + header_type: raw + +- symbol: att_win_waku4_tex!.data:0x800E5700 + binary: assets/bootdata/win2/att_win_waku4_tex.bin + header: assets/bootdata/win2/att_win_waku4_tex.inc + header_type: raw + +- symbol: att_win_waku5_tex!.data:0x800E5B00 + binary: assets/bootdata/win2/att_win_waku5_tex.bin + header: assets/bootdata/win2/att_win_waku5_tex.inc + header_type: raw + +- symbol: att_win_waku6_tex!.data:0x800E5F00 + binary: assets/bootdata/win2/att_win_waku6_tex.bin + header: assets/bootdata/win2/att_win_waku6_tex.inc + header_type: raw + +- symbol: gam_win2_v + binary: assets/bootdata/win2/gam_win2_v.bin + header: assets/bootdata/win2/gam_win2_v.inc + header_type: none + custom_type: vtx + +- symbol: gam_win_moji9_tex + binary: assets/bootdata/win3/gam_win_moji9_tex.bin + header: assets/bootdata/win3/gam_win_moji9_tex.inc + header_type: raw + +- symbol: gam_win3_v + binary: assets/bootdata/win3/gam_win3_v.bin + header: assets/bootdata/win3/gam_win3_v.inc + header_type: none + custom_type: vtx + +- symbol: logo_nin2_tex + binary: assets/bootdata/logo_nin2_tex.bin + header: assets/bootdata/logo_nin2_tex.inc + header_type: raw + +- symbol: logo_nin1_tex + binary: assets/bootdata/logo_nin1_tex.bin + header: assets/bootdata/logo_nin1_tex.inc + header_type: raw + +- symbol: logo_nin_v + binary: assets/bootdata/logo_nin_v.bin + header: assets/bootdata/logo_nin_v.inc + header_type: none + custom_type: vtx + +- symbol: nintendo_hi_0 + binary: assets/nintendo_hi_0.bin + header: assets/nintendo_hi_0.inc + header_type: raw + modules: - object: files/foresta.rel hash: a3b987c9a0cc9764494ac1e6ec64dc6c5c16ead2 diff --git a/config/GAEJ01_01/forestd/splits.txt b/config/GAEJ01_01/forestd/splits.txt index 296f2534..55b9ded5 100644 --- a/config/GAEJ01_01/forestd/splits.txt +++ b/config/GAEJ01_01/forestd/splits.txt @@ -5,11 +5,11 @@ Sections: .data type:data align:32 .bss type:bss align:8 -executor.o: +module/executor.c: .text start:0x00000000 end:0x00000060 .bss start:0x00000000 end:0x00000004 -fakemain.o: +fakemain.c: .text start:0x00000060 end:0x0000008C .data start:0x00000000 end:0x00000020 diff --git a/config/GAEJ01_01/foresti/splits.txt b/config/GAEJ01_01/foresti/splits.txt index 8c926351..a8a8d168 100644 --- a/config/GAEJ01_01/foresti/splits.txt +++ b/config/GAEJ01_01/foresti/splits.txt @@ -5,11 +5,11 @@ Sections: .data type:data align:32 .bss type:bss align:8 -executor.o: +module/executor.c: .text start:0x00000000 end:0x00000060 .bss start:0x00000000 end:0x00000004 -fakemain.o: +fakemain.c: .text start:0x00000060 end:0x0000008C .data start:0x00000000 end:0x00000020 diff --git a/config/GAEJ01_01/foresto/splits.txt b/config/GAEJ01_01/foresto/splits.txt index db37a10e..68f37c8d 100644 --- a/config/GAEJ01_01/foresto/splits.txt +++ b/config/GAEJ01_01/foresto/splits.txt @@ -5,11 +5,11 @@ Sections: .data type:data align:32 .bss type:bss align:8 -executor.o: +module/executor.c: .text start:0x00000000 end:0x00000060 .bss start:0x00000000 end:0x00000004 -fakemain.o: +fakemain.c: .text start:0x00000060 end:0x0000008C .data start:0x00000000 end:0x00000020 diff --git a/config/GAEJ01_01/splits.txt b/config/GAEJ01_01/splits.txt index 8cecc2ea..3d6087a6 100644 --- a/config/GAEJ01_01/splits.txt +++ b/config/GAEJ01_01/splits.txt @@ -19,7 +19,7 @@ boot.c: .data start:0x800D83A0 end:0x800D8950 .bss start:0x801088C0 end:0x80108998 -jsyswrap.c: +jsyswrap.cpp: .text start:0x80006B04 end:0x8000830C .text start:0x8000830C end:0x8000834C .text start:0x8000834C end:0x8000836C @@ -60,14 +60,20 @@ m_sdcard.cpp: .data start:0x800E1990 end:0x800E1BA0 .bss start:0x80109290 end:0x80109818 -bootdata.obj: - .text start:0x8000CB50 end:0x8000CB50 - .text start:0x8000CB50 end:0x8000CB50 - .text start:0x8000CB50 end:0x8000CB50 +bootdata/gam_win1.c: .text start:0x8000CB50 end:0x8000CB50 .data start:0x800E1BA0 end:0x800E4080 + +bootdata/gam_win2.c: + .text start:0x8000CB50 end:0x8000CB50 .data start:0x800E4080 end:0x800E64A0 + +bootdata/gam_win3.c: + .text start:0x8000CB50 end:0x8000CB50 .data start:0x800E64A0 end:0x800E6920 + +bootdata/logo_nin.c: + .text start:0x8000CB50 end:0x8000CB50 .data start:0x800E6920 end:0x800E89E0 nintendo_hi_0.c: @@ -473,7 +479,7 @@ jaudio_PP/internal/jamosc.c: .data start:0x800FC168 end:0x800FC250 .sdata2 start:0x80292EB8 end:0x80292EC0 -jaudio_PP/oneshot.c: +jaudio_PP/internal/oneshot.c: .text start:0x8003C2A0 end:0x8003CF80 .text start:0x8003CF80 end:0x8003D400 .text start:0x8003D400 end:0x8003D520 @@ -520,26 +526,26 @@ Famicom/famicom_nesinfo.cpp: .data start:0x800FF690 end:0x801006B8 .bss start:0x80220880 end:0x80220940 -gba/GBA.c: +GAEJ01_01/dolphin/gba/GBA.c: .text start:0x8004C1F0 end:0x8004C4E0 .data start:0x801006B8 end:0x801006C8 .bss start:0x80220940 end:0x80220E40 .sbss start:0x802922C0 end:0x802922C8 -gba/GBAGetProcessStatus.c: +GAEJ01_01/dolphin/gba/GBAGetProcessStatus.c: .text start:0x8004C4E0 end:0x8004C654 -gba/GBAJoyBoot.c: +GAEJ01_01/dolphin/gba/GBAJoyBoot.c: .text start:0x8004C654 end:0x8004D560 .data start:0x801006C8 end:0x801006F8 -gba/GBARead.c: +GAEJ01_01/dolphin/gba/GBARead.c: .text start:0x8004D560 end:0x8004D6C0 -gba/GBAWrite.c: +GAEJ01_01/dolphin/gba/GBAWrite.c: .text start:0x8004D6C0 end:0x8004D848 -gba/GBAXfer.c: +GAEJ01_01/dolphin/gba/GBAXfer.c: .text start:0x8004D848 end:0x8004DB80 gba2/JoyBoot.cpp: @@ -1224,287 +1230,287 @@ JSystem/J2DGraph/J2DOrthoGraph.cpp: .sdata start:0x80291E08 end:0x80291E18 .sdata2 start:0x802932E0 end:0x802932E8 -base/PPCArch.c: +GAEJ01_01/dolphin/base/PPCArch.c: .text start:0x8009E140 end:0x8009E260 -os/OS.c: +GAEJ01_01/dolphin/os/OS.c: .text start:0x8009E260 end:0x8009ED4C .data start:0x801057B0 end:0x801059A8 .bss start:0x802822A0 end:0x802822F0 .sdata start:0x80291E18 end:0x80291E28 .sbss start:0x802926A8 end:0x802926E8 -os/OSAlarm.c: +GAEJ01_01/dolphin/os/OSAlarm.c: .text start:0x8009ED4C end:0x8009F4A8 .data start:0x801059A8 end:0x801059B8 .sbss start:0x802926E8 end:0x802926F0 -os/OSAlloc.c: +GAEJ01_01/dolphin/os/OSAlloc.c: .text start:0x8009F4A8 end:0x8009F614 .sdata start:0x80291E28 end:0x80291E30 .sbss start:0x802926F0 end:0x80292700 -os/OSArena.c: +GAEJ01_01/dolphin/os/OSArena.c: .text start:0x8009F614 end:0x8009F634 .sdata start:0x80291E30 end:0x80291E38 .sbss start:0x80292700 end:0x80292708 -os/OSAudioSystem.c: +GAEJ01_01/dolphin/os/OSAudioSystem.c: .text start:0x8009F634 end:0x8009F8C8 .data start:0x801059B8 end:0x80105A38 -os/OSCache.c: +GAEJ01_01/dolphin/os/OSCache.c: .text start:0x8009F8C8 end:0x8009FD84 .data start:0x80105A38 end:0x80105C68 -os/OSContext.c: +GAEJ01_01/dolphin/os/OSContext.c: .text start:0x8009FD84 end:0x800A0720 .data start:0x80105C68 end:0x80105E40 -os/OSError.c: +GAEJ01_01/dolphin/os/OSError.c: .text start:0x800A0720 end:0x800A0C20 .data start:0x80105E40 end:0x80106160 .bss start:0x802822F0 end:0x80282340 .sdata start:0x80291E38 end:0x80291E40 -os/OSFont.c: +GAEJ01_01/dolphin/os/OSFont.c: .text start:0x800A0C20 end:0x800A0C78 .sdata start:0x80291E40 end:0x80291E48 -os/OSInterrupt.c: +GAEJ01_01/dolphin/os/OSInterrupt.c: .text start:0x800A0C78 end:0x800A14E4 .data start:0x80106160 end:0x80106190 .sbss start:0x80292708 end:0x80292720 -os/OSLink.c: +GAEJ01_01/dolphin/os/OSLink.c: .text start:0x800A14E4 end:0x800A1EDC .data start:0x80106190 end:0x801061E0 -os/OSMessage.c: +GAEJ01_01/dolphin/os/OSMessage.c: .text start:0x800A1EDC end:0x800A21B4 -os/OSMemory.c: +GAEJ01_01/dolphin/os/OSMemory.c: .text start:0x800A21B4 end:0x800A2568 .data start:0x801061E0 end:0x801061F0 -os/OSMutex.c: +GAEJ01_01/dolphin/os/OSMutex.c: .text start:0x800A2568 end:0x800A2960 -os/OSReboot.c: +GAEJ01_01/dolphin/os/OSReboot.c: .text start:0x800A2960 end:0x800A2CC0 .bss start:0x80282340 end:0x80282360 .sbss start:0x80292720 end:0x80292730 -os/OSReset.c: +GAEJ01_01/dolphin/os/OSReset.c: .text start:0x800A2CC0 end:0x800A30EC .sbss start:0x80292730 end:0x80292740 -os/OSResetSW.c: +GAEJ01_01/dolphin/os/OSResetSW.c: .text start:0x800A30EC end:0x800A3498 .sbss start:0x80292740 end:0x80292760 -os/OSRtc.c: +GAEJ01_01/dolphin/os/OSRtc.c: .text start:0x800A3498 end:0x800A41A8 .bss start:0x80282360 end:0x802823B8 -os/OSSemaphore.c: +GAEJ01_01/dolphin/os/OSSemaphore.c: .text start:0x800A41A8 end:0x800A42D0 -os/OSSync.c: +GAEJ01_01/dolphin/os/OSSync.c: .text start:0x800A42D0 end:0x800A4354 -os/OSThread.c: +GAEJ01_01/dolphin/os/OSThread.c: .text start:0x800A4354 end:0x800A6078 .data start:0x801061F0 end:0x80106A00 .bss start:0x802823B8 end:0x80282DB0 .sdata start:0x80291E48 end:0x80291E50 .sbss start:0x80292760 end:0x80292770 -os/OSTime.c: +GAEJ01_01/dolphin/os/OSTime.c: .text start:0x800A6078 end:0x800A677C .data start:0x80106A00 end:0x80106A60 -os/__start.c: +GAEJ01_01/dolphin/os/__start.c: .init start:0x80003100 end:0x80003400 .sbss start:0x80292770 end:0x80292778 -os/__ppc_eabi_init.cpp: +GAEJ01_01/dolphin/os/__ppc_eabi_init.cpp: .init start:0x80003400 end:0x80003458 .text start:0x800A677C end:0x800A6810 -exi/EXIUart.c: +GAEJ01_01/dolphin/exi/EXIUart.c: .text start:0x800A6810 end:0x800A6A9C .sbss start:0x80292778 end:0x80292788 -si/SIBios.c: +GAEJ01_01/dolphin/si/SIBios.c: .text start:0x800A6A9C end:0x800A82FC .data start:0x80106A60 end:0x80106B78 .bss start:0x80282DB0 end:0x80282FB0 .sdata start:0x80291E50 end:0x80291E58 .sbss start:0x80292788 end:0x80292798 -si/SISamplingRate.c: +GAEJ01_01/dolphin/si/SISamplingRate.c: .text start:0x800A82FC end:0x800A8404 .data start:0x80106B78 end:0x80106C10 .sbss start:0x80292798 end:0x802927A0 -db/db.c: +GAEJ01_01/dolphin/db/db.c: .text start:0x800A8404 end:0x800A84F0 .data start:0x80106C10 end:0x80106C28 .sbss start:0x802927A0 end:0x802927A8 -mtx/mtx.c: +GAEJ01_01/dolphin/mtx/mtx.c: .text start:0x800A84F0 end:0x800A8A4C .sdata start:0x80291E58 end:0x80291E60 .sdata2 start:0x802932E8 end:0x802932F8 -mtx/mtxvec.c: +GAEJ01_01/dolphin/mtx/mtxvec.c: .text start:0x800A8A4C end:0x800A8AA0 -mtx/mtx44.c: +GAEJ01_01/dolphin/mtx/mtx44.c: .text start:0x800A8AA0 end:0x800A8B38 .sdata2 start:0x802932F8 end:0x80293308 -mtx/vec.c: +GAEJ01_01/dolphin/mtx/vec.c: .text start:0x800A8B38 end:0x800A8BB8 .sdata2 start:0x80293308 end:0x80293310 -dvd/dvdlow.c: +GAEJ01_01/dolphin/dvd/dvdlow.c: .text start:0x800A8BB8 end:0x800A9A34 .bss start:0x80282FB0 end:0x80283080 .sdata start:0x80291E60 end:0x80291E68 .sbss start:0x802927A8 end:0x802927F0 -dvd/dvdfs.c: +GAEJ01_01/dolphin/dvd/dvdfs.c: .text start:0x800A9A34 end:0x800AA42C .data start:0x80106C28 end:0x80107018 .sdata start:0x80291E68 end:0x80291E70 .sbss start:0x802927F0 end:0x80292810 -dvd/dvd.c: +GAEJ01_01/dolphin/dvd/dvd.c: .text start:0x800AA42C end:0x800ACDA8 .data start:0x80107018 end:0x80107198 .bss start:0x80283080 end:0x80283118 .sdata start:0x80291E70 end:0x80291E88 .sbss start:0x80292810 end:0x80292858 -dvd/dvdqueue.c: +GAEJ01_01/dolphin/dvd/dvdqueue.c: .text start:0x800ACDA8 end:0x800ACFA0 .bss start:0x80283118 end:0x80283138 -dvd/dvderror.c: +GAEJ01_01/dolphin/dvd/dvderror.c: .text start:0x800ACFA0 end:0x800AD138 .data start:0x80107198 end:0x801071E0 -dvd/dvdidutils.c: +GAEJ01_01/dolphin/dvd/dvdidutils.c: .text start:0x800AD138 end:0x800AD230 -dvd/dvdFatal.c: +GAEJ01_01/dolphin/dvd/dvdFatal.c: .text start:0x800AD230 end:0x800AD260 .sbss start:0x80292858 end:0x80292860 -dvd/fstload.c: +GAEJ01_01/dolphin/dvd/fstload.c: .text start:0x800AD260 end:0x800AD4A0 .data start:0x801071E0 end:0x80107250 .bss start:0x80283138 end:0x802831A8 .sdata start:0x80291E88 end:0x80291E98 .sbss start:0x80292860 end:0x80292870 -vi/vi.c: +GAEJ01_01/dolphin/vi/vi.c: .text start:0x800AD4A0 end:0x800AF5C0 .data start:0x80107250 end:0x80107620 .bss start:0x802831A8 end:0x802832F0 .sdata start:0x80291E98 end:0x80291EA8 .sbss start:0x80292870 end:0x802928D0 -pad/Padclamp.c: +GAEJ01_01/dolphin/pad/Padclamp.c: .text start:0x800AF5C0 end:0x800AFAB8 .rodata start:0x800D7778 end:0x800D7788 .sdata2 start:0x80293310 end:0x80293330 -pad/Pad.c: +GAEJ01_01/dolphin/pad/Pad.c: .text start:0x800AFAB8 end:0x800B1540 .data start:0x80107620 end:0x80107678 .bss start:0x802832F0 end:0x80283340 .sdata start:0x80291EA8 end:0x80291EC8 .sbss start:0x802928D0 end:0x80292900 -ai/ai.c: +GAEJ01_01/dolphin/ai/ai.c: .text start:0x800B1540 end:0x800B1E98 .data start:0x80107678 end:0x801076C0 .sdata start:0x80291EC8 end:0x80291ED0 .sbss start:0x80292900 end:0x80292940 -ar/ar.c: +GAEJ01_01/dolphin/ar/ar.c: .text start:0x800B1E98 end:0x800B39E0 .data start:0x801076C0 end:0x80107708 .sdata start:0x80291ED0 end:0x80291ED8 .sbss start:0x80292940 end:0x80292960 -ar/arq.c: +GAEJ01_01/dolphin/ar/arq.c: .text start:0x800B39E0 end:0x800B3D7C .data start:0x80107708 end:0x80107750 .sdata start:0x80291ED8 end:0x80291EE0 .sbss start:0x80292960 end:0x80292988 -dsp/dsp.c: +GAEJ01_01/dolphin/dsp/dsp.c: .text start:0x800B3D7C end:0x800B3DC8 -card/CARDBios.c: +GAEJ01_01/dolphin/card/CARDBios.c: .text start:0x800B3DC8 end:0x800B5130 .data start:0x80107750 end:0x801077A8 .bss start:0x80283340 end:0x80283580 .sdata start:0x80291EE0 end:0x80291EE8 .sbss start:0x80292988 end:0x80292990 -card/CARDRdwr.c: +GAEJ01_01/dolphin/card/CARDRdwr.c: .text start:0x800B5130 end:0x800B53B0 -card/CARDBlock.c: +GAEJ01_01/dolphin/card/CARDBlock.c: .text start:0x800B53B0 end:0x800B57B4 -card/CARDDir.c: +GAEJ01_01/dolphin/card/CARDDir.c: .text start:0x800B57B4 end:0x800B5A18 -card/CARDCheck.c: +GAEJ01_01/dolphin/card/CARDCheck.c: .text start:0x800B5A18 end:0x800B69A8 -card/CARDMount.c: +GAEJ01_01/dolphin/card/CARDMount.c: .text start:0x800B69A8 end:0x800B7468 .data start:0x801077A8 end:0x80107800 -card/CARDFormat.c: +GAEJ01_01/dolphin/card/CARDFormat.c: .text start:0x800B7468 end:0x800B7CA0 -card/CARDOpen.c: +GAEJ01_01/dolphin/card/CARDOpen.c: .text start:0x800B7CA0 end:0x800B8390 -card/CARDCreate.c: +GAEJ01_01/dolphin/card/CARDCreate.c: .text start:0x800B8390 end:0x800B8728 -card/CARDRead.c: +GAEJ01_01/dolphin/card/CARDRead.c: .text start:0x800B8728 end:0x800B8B9C -card/CARDWrite.c: +GAEJ01_01/dolphin/card/CARDWrite.c: .text start:0x800B8B9C end:0x800B8F18 -card/CARDDelete.c: +GAEJ01_01/dolphin/card/CARDDelete.c: .text start:0x800B8F18 end:0x800B9114 -card/CARDStat.c: +GAEJ01_01/dolphin/card/CARDStat.c: .text start:0x800B9114 end:0x800B95DC -card/CARDRename.c: +GAEJ01_01/dolphin/card/CARDRename.c: .text start:0x800B95DC end:0x800B9820 -card/CARDStatEx.c: +GAEJ01_01/dolphin/card/CARDStatEx.c: .text start:0x800B9820 end:0x800B9BA8 -card/CARDNet.c: +GAEJ01_01/dolphin/card/CARDNet.c: .text start:0x800B9BA8 end:0x800B9D14 .sdata start:0x80291EE8 end:0x80291EF0 -gx/GXInit.c: +GAEJ01_01/dolphin/gx/GXInit.c: .text start:0x800B9D14 end:0x800BB094 .data start:0x80107800 end:0x80107A40 .bss start:0x80283580 end:0x80283BB0 @@ -1512,59 +1518,59 @@ gx/GXInit.c: .sbss start:0x80292990 end:0x802929B8 .sdata2 start:0x80293330 end:0x80293358 -gx/GXFifo.c: +GAEJ01_01/dolphin/gx/GXFifo.c: .text start:0x800BB094 end:0x800BB96C .sbss start:0x802929B8 end:0x802929D8 -gx/GXAttr.c: +GAEJ01_01/dolphin/gx/GXAttr.c: .text start:0x800BB96C end:0x800BC6C0 .data start:0x80107A40 end:0x80107BA0 .sdata start:0x80291EF8 end:0x80291F08 -gx/GXMisc.c: +GAEJ01_01/dolphin/gx/GXMisc.c: .text start:0x800BC6C0 end:0x800BCF48 .sbss start:0x802929D8 end:0x802929F0 -gx/GXGeometry.c: +GAEJ01_01/dolphin/gx/GXGeometry.c: .text start:0x800BCF48 end:0x800BD284 -gx/GXFrameBuf.c: +GAEJ01_01/dolphin/gx/GXFrameBuf.c: .text start:0x800BD284 end:0x800BDEB0 .data start:0x80107BA0 end:0x80107CD0 .sdata2 start:0x80293358 end:0x80293368 -gx/GXLight.c: +GAEJ01_01/dolphin/gx/GXLight.c: .text start:0x800BDEB0 end:0x800BE254 -gx/GXTexture.c: +GAEJ01_01/dolphin/gx/GXTexture.c: .text start:0x800BE254 end:0x800BF1C0 .data start:0x80107CD0 end:0x80107E00 .sdata start:0x80291F08 end:0x80291F48 .sdata2 start:0x80293368 end:0x80293390 -gx/GXBump.c: +GAEJ01_01/dolphin/gx/GXBump.c: .text start:0x800BF1C0 end:0x800BF698 .sdata2 start:0x80293390 end:0x80293398 -gx/GXTev.c: +GAEJ01_01/dolphin/gx/GXTev.c: .text start:0x800BF698 end:0x800BFD0C .data start:0x80107E00 end:0x80107E78 -gx/GXPixel.c: +GAEJ01_01/dolphin/gx/GXPixel.c: .text start:0x800BFD0C end:0x800C0354 .data start:0x80107E78 end:0x80107E98 .sdata2 start:0x80293398 end:0x802933D0 -gx/GXDisplayList.c: +GAEJ01_01/dolphin/gx/GXDisplayList.c: .text start:0x800C0354 end:0x800C0554 .bss start:0x80283BB0 end:0x80284188 .sbss start:0x802929F0 end:0x802929F8 -gx/GXTransform.c: +GAEJ01_01/dolphin/gx/GXTransform.c: .text start:0x800C0554 end:0x800C0A48 .sdata2 start:0x802933D0 end:0x802933E0 -gx/GXPerf.c: +GAEJ01_01/dolphin/gx/GXPerf.c: .text start:0x800C0A48 end:0x800C1364 .data start:0x80107E98 end:0x80107F88 @@ -1898,13 +1904,13 @@ TRK_MINNOW_DOLPHIN/MWTrace.c: TRK_MINNOW_DOLPHIN/MWCriticalSection_gc.cpp: .text start:0x800D0D54 end:0x800D0DAC -amcstubs/AmcExi2Stubs.c: +GAEJ01_01/dolphin/amcstubs/AmcExi2Stubs.c: .text start:0x800D0DAC end:0x800D0DDC -OdemuExi2/DebuggerDriver.c: +GAEJ01_01/dolphin/OdemuExi2/DebuggerDriver.c: .text start:0x800D0DDC end:0x800D185C .sdata start:0x80291F68 end:0x80291F69 .sbss start:0x80292A38 end:0x80292A4D -odenotstub/odenotstub.c: +GAEJ01_01/dolphin/odenotstub/odenotstub.c: .text start:0x800D185C end:0x800D1864 diff --git a/config/GAEJ01_01/symbols.txt b/config/GAEJ01_01/symbols.txt index 55252593..bae077c6 100644 --- a/config/GAEJ01_01/symbols.txt +++ b/config/GAEJ01_01/symbols.txt @@ -3774,14 +3774,10 @@ TRKTargetAccessDefault = .text:0x800CED50; // type:function size:0xF4 scope:glob TRKTargetReadInstruction = .text:0x800CEE44; // type:function size:0x4C scope:global align:4 TRKTargetAccessMemory = .text:0x800CEE90; // type:function size:0x14C scope:global align:4 TRKValidMemory32 = .text:0x800CEFDC; // type:function size:0x2A4 scope:global align:4 -TRKAccessFile = .text:0x800CF280; // type:label scope:global -fn_800CF280 = .text:0x800CF280; // type:function size:0x8 -TRKOpenFile = .text:0x800CF288; // type:label scope:global -fn_800CF288 = .text:0x800CF288; // type:function size:0x8 -TRKCloseFile = .text:0x800CF290; // type:label scope:global -fn_800CF290 = .text:0x800CF290; // type:function size:0x8 -TRKPositionFile = .text:0x800CF298; // type:label scope:global -fn_800CF298 = .text:0x800CF298; // type:function size:0x8 +TRKAccessFile = .text:0x800CF280; // type:function size:0x8 scope:global +TRKOpenFile = .text:0x800CF288; // type:function size:0x8 scope:global +TRKCloseFile = .text:0x800CF290; // type:function size:0x8 scope:global +TRKPositionFile = .text:0x800CF298; // type:function size:0x8 scope:global TRKSaveExtended1Block = .text:0x800CF2A0; // type:function size:0x1B8 scope:global align:4 TRKRestoreExtended1Block = .text:0x800CF458; // type:function size:0x1B8 scope:global align:4 InitMetroTRK = .text:0x800CF610; // type:function size:0x98 scope:global align:4 diff --git a/configure.py b/configure.py index c8696773..17e77d00 100755 --- a/configure.py +++ b/configure.py @@ -352,176 +352,265 @@ def MatchingFor(*versions): "ai", [ Object(MatchingFor(), "GAEJ01_00/dolphin/ai/ai.c"), + Object(Matching, "GAEJ01_01/dolphin/ai/ai.c"), ], ), DolphinLib( "ar", [ Object(MatchingFor(), "GAEJ01_00/dolphin/ar/ar.c"), + Object(Matching, "GAEJ01_01/dolphin/ar/ar.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/ar/arq.c"), + Object(Matching, "GAEJ01_01/dolphin/ar/arq.c"), ], ), DolphinLib( "amcstubs", [ Object(MatchingFor(), "GAEJ01_00/dolphin/amcstubs/AmcExi2Stubs.c"), + Object(Matching, "GAEJ01_01/dolphin/amcstubs/AmcExi2Stubs.c"), ], ), DolphinLib( "base", [ Object(MatchingFor(), "GAEJ01_00/dolphin/base/PPCArch.c"), + Object(Matching, "GAEJ01_01/dolphin/base/PPCArch.c"), ], ), DolphinLib( "card", [ Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDBios.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDBios.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDBlock.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDBlock.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDCheck.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDCheck.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDCreate.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDCreate.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDDelete.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDDelete.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDDir.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDDir.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDFormat.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDFormat.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDMount.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDMount.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDNet.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDNet.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDOpen.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDOpen.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDRdwr.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDRdwr.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDRead.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDRead.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDRename.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDRename.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDStat.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDStat.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDStatEx.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDStatEx.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/card/CARDWrite.c"), + Object(Matching, "GAEJ01_01/dolphin/card/CARDWrite.c"), ], ), DolphinLib( "db", [ Object(MatchingFor(), "GAEJ01_00/dolphin/db/db.c"), + Object(Matching, "GAEJ01_01/dolphin/db/db.c"), ], ), DolphinLib( "dsp", [ Object(MatchingFor(), "GAEJ01_00/dolphin/dsp/dsp.c"), + Object(Matching, "GAEJ01_01/dolphin/dsp/dsp.c"), ], ), DolphinLib( "dvd", [ Object(MatchingFor(), "GAEJ01_00/dolphin/dvd/dvd.c"), + Object(Matching, "GAEJ01_01/dolphin/dvd/dvd.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/dvd/dvderror.c"), + Object(Matching, "GAEJ01_01/dolphin/dvd/dvderror.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/dvd/dvdfs.c"), + Object(Matching, "GAEJ01_01/dolphin/dvd/dvdfs.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/dvd/dvdlow.c"), + Object(Matching, "GAEJ01_01/dolphin/dvd/dvdlow.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/dvd/dvdqueue.c"), + Object(Matching, "GAEJ01_01/dolphin/dvd/dvdqueue.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/dvd/fstload.c"), + Object(Matching, "GAEJ01_01/dolphin/dvd/dvdidutils.c"), + Object(Matching, "GAEJ01_01/dolphin/dvd/dvdFatal.c"), + Object(Matching, "GAEJ01_01/dolphin/dvd/fstload.c"), ], ), DolphinLib( "exi", [ Object(MatchingFor(), "GAEJ01_00/dolphin/exi/EXIBios.c"), + Object(NonMatching, "GAEJ01_01/dolphin/exi/EXIBios.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/exi/EXIUart.c"), + Object(Matching, "GAEJ01_01/dolphin/exi/EXIUart.c"), ], ), DolphinLib( "gba", [ Object(MatchingFor("GAEJ01_00"), "GAEJ01_00/dolphin/gba/GBA.c"), + Object(Matching, "GAEJ01_01/dolphin/gba/GBA.c"), Object(MatchingFor("GAEJ01_00"), "GAEJ01_00/dolphin/gba/GBAGetProcessStatus.c"), + Object(Matching, "GAEJ01_01/dolphin/gba/GBAGetProcessStatus.c"), Object(MatchingFor("GAEJ01_00"), "GAEJ01_00/dolphin/gba/GBAJoyBoot.c"), + Object(Matching, "GAEJ01_01/dolphin/gba/GBAJoyBoot.c"), Object(MatchingFor("GAEJ01_00"), "GAEJ01_00/dolphin/gba/GBARead.c"), + Object(Matching, "GAEJ01_01/dolphin/gba/GBARead.c"), Object(MatchingFor("GAEJ01_00"), "GAEJ01_00/dolphin/gba/GBAWrite.c"), + Object(Matching, "GAEJ01_01/dolphin/gba/GBAWrite.c"), Object(MatchingFor("GAEJ01_00"), "GAEJ01_00/dolphin/gba/GBAXfer.c"), + Object(Matching, "GAEJ01_01/dolphin/gba/GBAXfer.c"), ], ), DolphinLib( "gx", [ Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXAttr.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXAttr.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXBump.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXBump.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXDisplayList.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXDisplayList.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXFifo.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXFifo.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXFrameBuf.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXFrameBuf.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXGeometry.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXGeometry.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXInit.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXInit.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXLight.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXLight.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXMisc.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXMisc.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXPerf.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXPerf.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXPixel.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXPixel.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXStubs.c"), + Object(NonMatching, "GAEJ01_01/dolphin/gx/GXStubs.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXTev.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXTev.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXTexture.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXTexture.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/gx/GXTransform.c"), + Object(Matching, "GAEJ01_01/dolphin/gx/GXTransform.c"), ], ), DolphinLibMtx( "mtx", [ Object(MatchingFor(), "GAEJ01_00/dolphin/mtx/mtx.c"), + Object(Matching, "GAEJ01_01/dolphin/mtx/mtx.c", mw_version="GC/1.2.5n"), Object(MatchingFor(), "GAEJ01_00/dolphin/mtx/mtx44.c"), + Object(Matching, "GAEJ01_01/dolphin/mtx/mtx44.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/mtx/mtxvec.c"), + Object(Matching, "GAEJ01_01/dolphin/mtx/mtxvec.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/mtx/vec.c"), + Object(Matching, "GAEJ01_01/dolphin/mtx/vec.c"), ], ), DolphinLib( "OdemuExi2", [ Object(MatchingFor(), "GAEJ01_00/dolphin/OdemuExi2/DebuggerDriver.c", extra_cflags=["-inline deferred"]), + Object(Matching, "GAEJ01_01/dolphin/OdemuExi2/DebuggerDriver.c", extra_cflags=["-inline deferred"]), ], ), DolphinLib( "odenotstub", [ Object(MatchingFor(), "GAEJ01_00/dolphin/odenotstub/odenotstub.c"), + Object(Matching, "GAEJ01_01/dolphin/odenotstub/odenotstub.c"), ], ), DolphinLib( "os", [ Object(MatchingFor(), "GAEJ01_00/dolphin/os/__ppc_eabi_init.cpp"), + Object(Matching, "GAEJ01_01/dolphin/os/__ppc_eabi_init.cpp"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/__start.c"), + Object(Matching, "GAEJ01_01/dolphin/os/__start.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OS.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OS.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSAlarm.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSAlarm.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSAlloc.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSAlloc.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSArena.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSArena.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSAudioSystem.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSAudioSystem.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSCache.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSCache.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSContext.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSContext.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSError.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSError.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSFont.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSFont.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSInterrupt.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSInterrupt.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSLink.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSLink.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSMemory.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSMemory.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSMessage.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSMessage.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSMutex.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSMutex.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSReboot.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSReboot.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSReset.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSReset.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSResetSW.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSResetSW.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSRtc.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSRtc.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSSync.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSSemaphore.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSSync.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSThread.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSThread.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/os/OSTime.c"), + Object(Matching, "GAEJ01_01/dolphin/os/OSTime.c"), ], ), DolphinLib( "pad", [ Object(MatchingFor(), "GAEJ01_00/dolphin/pad/Pad.c"), + Object(Matching, "GAEJ01_01/dolphin/pad/Pad.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/pad/Padclamp.c"), + Object(Matching, "GAEJ01_01/dolphin/pad/Padclamp.c"), ], ), DolphinLib( "si", [ Object(MatchingFor(), "GAEJ01_00/dolphin/si/SIBios.c"), + Object(Matching, "GAEJ01_01/dolphin/si/SIBios.c"), Object(MatchingFor(), "GAEJ01_00/dolphin/si/SISamplingRate.c"), + Object(Matching, "GAEJ01_01/dolphin/si/SISamplingRate.c"), ], ), DolphinLib( "vi", [ Object(MatchingFor(), "GAEJ01_00/dolphin/vi/vi.c"), + Object(Matching, "GAEJ01_01/dolphin/vi/vi.c"), ], ), JSystemLib( @@ -547,27 +636,27 @@ def MatchingFor(*versions): JSystemLib( "JKernel", [ - Object(NonMatching, "JSystem/JKernel/JKRAram.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramArchive.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramBlock.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramHeap.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramPiece.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramStream.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRArchivePri.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRArchivePub.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRCompArchive.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRDecomp.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRAram.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRAramArchive.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRAramBlock.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRAramHeap.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRAramPiece.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRAramStream.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRArchivePri.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRArchivePub.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRCompArchive.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRDecomp.cpp"), Object(Matching, "JSystem/JKernel/JKRDisposer.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRDvdAramRipper.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRDvdArchive.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRDvdFile.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRDvdRipper.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRDvdAramRipper.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRDvdArchive.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRDvdFile.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRDvdRipper.cpp"), Object(Matching, "JSystem/JKernel/JKRExpHeap.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRFileFinder.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRFileLoader.cpp"), - Object(Equivalent, "JSystem/JKernel/JKRHeap.cpp"), # Maybe need PCH for this? - Object(NonMatching, "JSystem/JKernel/JKRMemArchive.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRThread.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRFileFinder.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRFileLoader.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRHeap.cpp"), # Maybe need PCH for this? + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRMemArchive.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JKernel/JKRThread.cpp"), ], ), JSystemLib( @@ -582,27 +671,27 @@ def MatchingFor(*versions): JSystemLib( "JUtility", [ - Object(NonMatching, "JSystem/JUtility/JUTAssert.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTConsole.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTDbPrint.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTDirectFile.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTDirectPrint.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTAssert.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTConsole.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTDbPrint.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTDirectFile.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTDirectPrint.cpp"), Object(NonMatching, "JSystem/JUtility/JUTException.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTFader.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTFont.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTFader.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTFont.cpp"), Object(Matching, "JSystem/JUtility/JUTFontData_Ascfont_fix12.s"), - Object(NonMatching, "JSystem/JUtility/JUTGamePad.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTGraphFifo.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTGamePad.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTGraphFifo.cpp"), Object(Matching, "JSystem/JUtility/JUTProcBar.cpp"), Object(Matching, "JSystem/JUtility/JUTResFont.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTVideo.cpp"), - Object(NonMatching, "JSystem/JUtility/JUTXfb.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTVideo.cpp"), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/JUTXfb.cpp"), Object(Matching, "JSystem/JUtility/JUTGba.cpp"), Object(Matching, "JSystem/JUtility/JUTSDDrive.cpp", extra_cflags=["-O4,p", "-RTTI on", "-inline auto", "-enum int"]), Object(Matching, "JSystem/JUtility/fs_vara.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), - Object(MatchingFor("GAEJ01_00"), "JSystem/JUtility/JUTSDFile.cpp", extra_cflags=["-O4,p", "-RTTI on", "-inline auto", "-enum int"]), + Object(MatchingFor("GAEJ01_00", "GAEJ01_01"), "JSystem/JUtility/JUTSDFile.cpp", mw_version="GC/1.3.2", extra_cflags=["-O4,p", "-RTTI on", "-inline auto", "-enum int"]), Object(NonMatching, "JSystem/JUtility/fs_form.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), - Object(MatchingFor("GAEJ01_00"), "JSystem/JUtility/fs_subd.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), + Object(MatchingFor("GAEJ01_00", "GAEJ01_01"), "JSystem/JUtility/fs_subd.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_drv.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/time.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_init.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), @@ -615,7 +704,7 @@ def MatchingFor(*versions): Object(Matching, "JSystem/JUtility/fs_seek.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_dele.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_opdr.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), - Object(MatchingFor("GAEJ01_00"), "JSystem/JUtility/fs_rddr.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), + Object(MatchingFor("GAEJ01_00", "GAEJ01_01"), "JSystem/JUtility/fs_rddr.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_cldr.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_mkdr.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_renm.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), @@ -624,7 +713,7 @@ def MatchingFor(*versions): Object(Matching, "JSystem/JUtility/fs_getps.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_cardrst.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/fs_drvsel.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), - Object(NonMatching, "JSystem/JUtility/exidrv.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), + Object(MatchingFor("GAEJ01_01"), "JSystem/JUtility/exidrv.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(NonMatching, "JSystem/JUtility/carddrv.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-inline all"]), Object(Matching, "JSystem/JUtility/EXIBios.c", mw_version="GC/1.2.5n", cflags=[*cflags_base, "-O3,p", "-inline all"]), @@ -640,7 +729,7 @@ def MatchingFor(*versions): "objects": [ Object(Matching, "jaudio_PP/game/audioheaders.c"), Object(Matching, "jaudio_PP/game/dummyprobe.c"), - Object(NonMatching, "jaudio_PP/game/emusound.c", extra_cflags=["-O4,s", "-fp_contract on", "-func_align 32", "-vector on"]), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/game/emusound.c", extra_cflags=["-O4,s", "-fp_contract on", "-func_align 32", "-vector on"]), Object(Matching, "jaudio_PP/game/game64.c"), Object(Matching, "jaudio_PP/game/kappa.c"), Object(Matching, "jaudio_PP/game/melody.c"), @@ -669,57 +758,57 @@ def MatchingFor(*versions): "progress_category": "library", "src_dir": "src/static", "objects": [ - Object(NonMatching, "jaudio_PP/internal/aictrl.c"), - Object(NonMatching, "jaudio_PP/internal/astest.c"), - Object(NonMatching, "jaudio_PP/internal/audiothread.c", extra_cflags=["-sym off"]), # The entire lib probably has sym off - Object(NonMatching, "jaudio_PP/internal/cpubuf.c"), - Object(NonMatching, "jaudio_PP/internal/dspboot.c"), - Object(NonMatching, "jaudio_PP/internal/dspbuf.c"), - Object(NonMatching, "jaudio_PP/internal/dspproc.c"), - Object(NonMatching, "jaudio_PP/internal/dummyrom.c"), - Object(NonMatching, "jaudio_PP/internal/dvdthread.c"), - Object(NonMatching, "jaudio_PP/internal/neosthread.c"), - Object(NonMatching, "jaudio_PP/internal/os.c"), - Object(NonMatching, "jaudio_PP/internal/playercall.c"), - Object(NonMatching, "jaudio_PP/internal/random.c"), - Object(NonMatching, "jaudio_PP/internal/sample.c"), - Object(NonMatching, "jaudio_PP/internal/streamctrl.c"), - Object(NonMatching, "jaudio_PP/internal/sub_sys.c"), - Object(NonMatching, "jaudio_PP/internal/track.c"), - Object(NonMatching, "jaudio_PP/internal/aramcall.c"), - Object(NonMatching, "jaudio_PP/internal/audioconst.c"), - Object(NonMatching, "jaudio_PP/internal/audiotable.c"), - Object(NonMatching, "jaudio_PP/internal/audiowork.c"), - Object(NonMatching, "jaudio_PP/internal/bankdrv.c", extra_cflags=["-pragma \"scheduling 7400\""]), - Object(NonMatching, "jaudio_PP/internal/bankread.c"), - Object(NonMatching, "jaudio_PP/internal/centcalc.c"), - Object(NonMatching, "jaudio_PP/internal/channel.c"), - Object(NonMatching, "jaudio_PP/internal/cmdstack.c"), - Object(NonMatching, "jaudio_PP/internal/connect.c"), - Object(NonMatching, "jaudio_PP/internal/driver.c", extra_cflags=["-vector on"]), - Object(NonMatching, "jaudio_PP/internal/driverinterface.c"), - Object(NonMatching, "jaudio_PP/internal/dsp_cardunlock.c"), - Object(NonMatching, "jaudio_PP/internal/dsp_GBAKey.c"), - Object(NonMatching, "jaudio_PP/internal/dspdriver.c", extra_cflags=["-vector on"]), - Object(NonMatching, "jaudio_PP/internal/dspinterface.c"), - Object(NonMatching, "jaudio_PP/internal/effect.c", extra_cflags=["-pragma \"scheduling 7400\""]), - Object(NonMatching, "jaudio_PP/internal/fat.c"), - Object(NonMatching, "jaudio_PP/internal/fxinterface.c"), - Object(NonMatching, "jaudio_PP/internal/heapctrl.c"), - Object(NonMatching, "jaudio_PP/internal/ipldec.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/aictrl.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/astest.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/audiothread.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/cpubuf.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dspboot.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dspbuf.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dspproc.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dummyrom.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dvdthread.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/neosthread.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/os.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/playercall.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/random.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/sample.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/streamctrl.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/sub_sys.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/track.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/aramcall.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/audioconst.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/audiotable.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/audiowork.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/bankdrv.c", extra_cflags=["-pragma \"scheduling 7400\""]), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/bankread.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/centcalc.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/channel.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/cmdstack.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/connect.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/driver.c", extra_cflags=["-vector on"]), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/driverinterface.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dsp_cardunlock.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dsp_GBAKey.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dspdriver.c", extra_cflags=["-vector on"]), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/dspinterface.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/effect.c", extra_cflags=["-pragma \"scheduling 7400\""]), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/fat.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/fxinterface.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/heapctrl.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/ipldec.c"), Object(Matching, "jaudio_PP/internal/ja_calc.c", extra_cflags=["-sym off"]), - Object(NonMatching, "jaudio_PP/internal/jammain_2.c", extra_cflags=["-sym on"]), - Object(NonMatching, "jaudio_PP/internal/jamosc.c"), - Object(NonMatching, "jaudio_PP/internal/memory.c", extra_cflags=["-pragma \"scheduling 7400\""]), - Object(NonMatching, "jaudio_PP/internal/midplay.c"), - Object(NonMatching, "jaudio_PP/internal/noteon.c"), - Object(NonMatching, "jaudio_PP/internal/oneshot.c"), - Object(NonMatching, "jaudio_PP/internal/rate.c"), - Object(NonMatching, "jaudio_PP/internal/rspsim.c"), - Object(NonMatching, "jaudio_PP/internal/seqsetup.c"), - Object(NonMatching, "jaudio_PP/internal/system.c", extra_cflags=["-vector on"]), - Object(NonMatching, "jaudio_PP/internal/tables.c"), - Object(NonMatching, "jaudio_PP/internal/waveread.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/jammain_2.c", extra_cflags=["-sym on"]), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/jamosc.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/memory.c", extra_cflags=["-pragma \"scheduling 7400\""]), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/midplay.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/noteon.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/oneshot.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/rate.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/rspsim.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/seqsetup.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/system.c", extra_cflags=["-vector on"]), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/tables.c"), + Object(MatchingFor("GAEJ01_01"), "jaudio_PP/internal/waveread.c"), ], }, { @@ -747,10 +836,112 @@ def MatchingFor(*versions): "progress_category": "sdk", "src_dir": "src/static", "objects": [ + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/abort_exit.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/errno.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/ansi_files.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/ansi_fp.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/arith.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/buffer_io.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/critical_regions.gamecube.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/ctype.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/direct_io.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/file_io.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/FILE_POS.C"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/mbstring.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/mem.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/mem_funcs.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/misc_io.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/printf.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/rand.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/float.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/scanf.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/string.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/strtoul.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/wchar_io.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/uart_console_io_gcn.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/e_acos.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/e_atan2.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/e_pow.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/e_rem_pio2.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/k_cos.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/k_rem_pio2.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/k_sin.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_atan.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_ceil.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_copysign.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_cos.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_floor.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_frexp.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_ldexp.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_modf.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/s_sin.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/w_acos.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/w_atan2.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/w_pow.c"), + Object(MatchingFor("GAEJ01_01"), "MSL_C.PPCEABI.bare.H/e_sqrt.c"), Object(Matching, "MSL_C.PPCEABI.bare.H/math_ppc.c"), Object(Matching, "MSL_C.PPCEABI.bare.H/w_sqrt.c"), ], }, + { + "lib": "TRK_MINNOW_DOLPHIN", + "mw_version": config.linker_version, + "cflags": [*cflags_runtime, "-inline deferred", "-sdata 0", "-sdata2 0", "-use_lmw_stmw on", "-str reuse,readonly", "-char signed"], + "progress_category": "sdk", + "src_dir": "src/static", + "objects": [ + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/mainloop.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/nubevent.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/nubinit.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/msg.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/msgbuf.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/serpoll.c", extra_cflags=["-sdata 8"]), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/usr_put.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/dispatch.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/msghndlr.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/support.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/mutex_TRK.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/notify.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/flush_cache.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/mem_TRK.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/targimpl.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/targsupp.s"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/__exception.s"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/dolphin_trk.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/main_TRK.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/targcont.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/target_options.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/mslsupp.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/UDP_Stubs.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/main_ddh.c", extra_cflags=["-sdata 8"]), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/CircleBuffer.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/main.c", extra_cflags=["-sdata 8"]), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/MWTrace.c"), + Object(MatchingFor("GAEJ01_01"), "TRK_MINNOW_DOLPHIN/MWCriticalSection_gc.cpp"), + ], + }, + { + "lib": "boot", + "mw_version": config.linker_version, + "cflags": [*cflags_static, "-sdata 0", "-sdata2 0", "-inline on"], + "progress_category": "game", + "src_dir": "src/static", + "objects": [ + Object(MatchingFor("GAEJ01_01"), "boot.c"), + Object(MatchingFor("GAEJ01_01"), "jsyswrap.cpp", extra_cflags=["-inline off", "-sym on"]), + Object(MatchingFor("GAEJ01_01"), "version.c"), + Object(MatchingFor("GAEJ01_01"), "initial_menu.c"), + Object(MatchingFor("GAEJ01_01"), "dvderr.c", extra_cflags=["-pool off"]), + Object(MatchingFor("GAEJ01_01"), "bootdata/gam_win1.c"), + Object(MatchingFor("GAEJ01_01"), "bootdata/gam_win2.c"), + Object(MatchingFor("GAEJ01_01"), "bootdata/gam_win3.c"), + Object(MatchingFor("GAEJ01_01"), "bootdata/logo_nin.c"), + Object(MatchingFor("GAEJ01_01"), "nintendo_hi_0.c"), + Object(MatchingFor("GAEJ01_01"), "gba2/JoyBoot.cpp", extra_cflags=["-inline off", "-sym on"]), + ], + }, { "lib": "Famicom", "mw_version": config.linker_version, @@ -765,8 +956,8 @@ def MatchingFor(*versions): "src_dir": "src/static", "objects": [ Object(Matching, "Famicom/ks_nes_core.cpp"), - Object(NonMatching, "Famicom/ks_nes_draw.cpp"), - Object(Equivalent, "Famicom/famicom.cpp"), # std::strstr appears too early in splits + Object(MatchingFor("GAEJ01_01"), "Famicom/ks_nes_draw.cpp"), + Object(MatchingFor("GAEJ01_01"), "Famicom/famicom.cpp"), # std::strstr appears too early in splits Object(Matching, "Famicom/famicom_nesinfo.cpp"), ], }, @@ -778,9 +969,9 @@ def MatchingFor(*versions): "src_dir": "src/static", "objects": [ Object(Matching, "libforest/emu64/emu64.c", extra_cflags=["-lang=c++", "-O4,p", "-inline off", "-sym on"]), - # Object(Matching, "libforest/osreport.c"), - # Object(Matching, "libforest/fault.c"), - # Object(Matching, "libforest/ReconfigBATs.c"), + Object(MatchingFor("GAEJ01_01"), "libforest/osreport.c"), + Object(MatchingFor("GAEJ01_01"), "libforest/fault.c"), + Object(MatchingFor("GAEJ01_01"), "libforest/ReconfigBATs.c"), ], }, { @@ -869,11 +1060,11 @@ def MatchingFor(*versions): { "lib": "libjsys", "mw_version": config.linker_version, - "cflags": cflags_static, + "cflags": [*cflags_static, "-inline off", "-sym on"], "progress_category": "library", "src_dir": "src/static", "objects": [ - Object(NonMatching, "libjsys/jsyswrapper.cpp"), + Object(MatchingFor("GAEJ01_01"), "libjsys/jsyswrapper.cpp"), ], }, Rel( @@ -1526,6 +1717,9 @@ def MatchingFor(*versions): Rel( "forestd", [ + # Shared by forestd, foresti and foresto + Object(MatchingFor("GAEJ01_01"), "module/executor.c", source="executor.c"), + Object(MatchingFor("GAEJ01_01"), "fakemain.c"), Object(Matching, "data/always/glider.c"), Object(Matching, "data/always/bev.c"), Object(Matching, "data/always/bev_1.c"),