diff --git a/configure.py b/configure.py index 52215c30..f8a43598 100644 --- a/configure.py +++ b/configure.py @@ -242,7 +242,7 @@ cflags_trk = [ cflags_odemuexi = [ *cflags_base, - "-inline auto,deferred", + # TODO figure out flags ] cflags_amcstub = [ @@ -460,7 +460,7 @@ config.libs = [ [ Object(Matching, "dolphin/os/OS.c"), Object(Matching, "dolphin/os/OSAlarm.c"), - Object(NonMatching, "dolphin/os/OSAlloc.c"), + Object(Matching, "dolphin/os/OSAlloc.c"), Object(Matching, "dolphin/os/OSArena.c"), Object(Matching, "dolphin/os/OSAudioSystem.c"), Object(Matching, "dolphin/os/OSCache.c"), @@ -760,7 +760,7 @@ config.libs = [ ), { "lib": "OdemuExi2", - "mw_version": config.linker_version, + "mw_version": "GC/1.2.5", "cflags": cflags_odemuexi, "host": False, "objects": [ @@ -773,7 +773,7 @@ config.libs = [ "cflags": cflags_amcstub, "host": False, "objects": [ - Object(NonMatching, "amcstubs/AmcExi2Stubs.c"), + Object(Matching, "amcstubs/AmcExi2Stubs.c"), ], }, { @@ -782,7 +782,7 @@ config.libs = [ "cflags": cflags_odenotstub, "host": False, "objects": [ - Object(NonMatching, "odenotstub/odenotstub.c"), + Object(Matching, "odenotstub/odenotstub.c"), ], }, { diff --git a/src/OdemuExi2/DebuggerDriver.c b/src/OdemuExi2/DebuggerDriver.c new file mode 100644 index 00000000..e9be8b4e --- /dev/null +++ b/src/OdemuExi2/DebuggerDriver.c @@ -0,0 +1,327 @@ +#include +#include +#include + + +typedef void (*MTRCallbackType)(int); + +static MTRCallbackType MTRCallback; + +static void (*DBGCallback)(u32, OSContext *); + +static u32 SendMailData; + +static s32 RecvDataLeng; + +static u8 *pEXIInputFlag; + +static u8 EXIInputFlag; + +static u8 SendCount = 0x80; + +#define IS_TRUE(x) ((x) != FALSE) +#define IS_FALSE(x) !IS_TRUE(x) +#define ROUND_UP(x, align) (((x) + (align)-1) & (-(align))) + +// TODO + +void DBGEXIInit() +{ + __OSMaskInterrupts(0x18000); + __EXIRegs[10] = 0; +} + +static u32 DBGEXISelect(u32 v) +{ + u32 regs = __EXIRegs[10]; + regs &= 0x405; + regs |= 0x80 | (v << 4); + __EXIRegs[10] = regs; + return TRUE; +} + +BOOL DBGEXIDeselect(void) +{ + __EXIRegs[10] &= 0x405; + return TRUE; +} + +static BOOL DBGEXISync() +{ + while (__EXIRegs[13] & 1) + ; + + return TRUE; +} + +static BOOL DBGEXIImm(void *buffer, s32 bytecounter, u32 write) +{ + u8 *tempPointer; + u32 writeOutValue; + int i; + + if (write) { + tempPointer = buffer; + writeOutValue = 0; + for (i = 0; i < bytecounter; i++) { + u8 *temp = ((u8 *)buffer) + i; + writeOutValue |= *temp << ((3 - i) << 3); + } + __EXIRegs[14] = writeOutValue; + } + + __EXIRegs[13] = 1 | write << 2 | (bytecounter - 1) << 4; + DBGEXISync(); + + if (!write) { + writeOutValue = __EXIRegs[14]; + tempPointer = buffer; + for (i = 0; i < bytecounter; i++) { + *tempPointer++ = writeOutValue >> ((3 - i) << 3); + } + } + + return TRUE; +} + +static BOOL DBGWriteMailbox(u32 p1) +{ + u32 cmd = 0xc0000000; + u32 v; + u32 base = p1; + BOOL total = FALSE; + + DBGEXISelect(4); + v = (base & 0x1fffffff) | (cmd); + total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 1)); + total |= IS_FALSE(DBGEXISync()); + total |= IS_FALSE(DBGEXIDeselect()); + + return IS_FALSE(total); +} + +#pragma dont_inline on + +static BOOL DBGReadMailbox(u32 *p1) +{ + BOOL total = FALSE; + u32 v; + + DBGEXISelect(4); + + v = 0x60000000; + total |= IS_FALSE(DBGEXIImm(&v, 2, 1)); + total |= IS_FALSE(DBGEXISync()); + + total |= IS_FALSE(DBGEXIImm(p1, 4, 0)); + total |= IS_FALSE(DBGEXISync()); + + total |= IS_FALSE(DBGEXIDeselect()); + + return IS_FALSE(total); +} +#pragma dont_inline off + +static BOOL DBGRead(u32 count, u32 *buffer, s32 param3) +{ + BOOL total = FALSE; + u32 *buf_p = (u32 *)buffer; + u32 v1; + u32 v; + + DBGEXISelect(4); + + v1 = (count & 0x1fffc) << 8 | 0x20000000; + total |= IS_FALSE(DBGEXIImm(&v1, sizeof(v1), 1)); + total |= IS_FALSE(DBGEXISync()); + + while (param3) { + total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 0)); + total |= IS_FALSE(DBGEXISync()); + + *buf_p++ = v; + + param3 -= 4; + if (param3 < 0) { + param3 = 0; + } + } + + total |= IS_FALSE(DBGEXIDeselect()); + return IS_FALSE(total); +} + +static BOOL DBGWrite(u32 count, void *buffer, s32 param3) +{ + BOOL total = FALSE; + u32 *buf_p = (u32 *)buffer; + u32 v1; + u32 v; + + DBGEXISelect(4); + + v1 = (count & 0x1fffc) << 8 | 0xa0000000; + total |= IS_FALSE(DBGEXIImm(&v1, sizeof(v1), 1)); + total |= IS_FALSE(DBGEXISync()); + + while (param3 != 0) { + v = *buf_p++; + + total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 1)); + total |= IS_FALSE(DBGEXISync()); + + param3 -= 4; + if (param3 < 0) { + param3 = 0; + } + } + + total |= IS_FALSE(DBGEXIDeselect()); + return IS_FALSE(total); +} + +static BOOL _DBGReadStatus(u32 *p1) +{ + BOOL total = FALSE; + u32 v; + + DBGEXISelect(4); + + v = 1 << 30; + total |= IS_FALSE(DBGEXIImm(&v, 2, 1)); + total |= IS_FALSE(DBGEXISync()); + + total |= IS_FALSE(DBGEXIImm(p1, 4, 0)); + total |= IS_FALSE(DBGEXISync()); + + total |= IS_FALSE(DBGEXIDeselect()); + + return IS_FALSE(total); +} + +static BOOL DBGReadStatus(u32 *p1) +{ + return _DBGReadStatus(p1); +} + +static void MWCallback(u32 a, OSContext *b) +{ + EXIInputFlag = TRUE; + if (MTRCallback) { + MTRCallback(0); + } +} + +static void DBGHandler(s16 a, OSContext *b) +{ + *__PIRegs = 0x1000; + if (DBGCallback) { + DBGCallback(a, b); + } +} + +void DBInitComm(u8 **a, MTRCallbackType b) +{ + BOOL interrupts = OSDisableInterrupts(); + { + pEXIInputFlag = (u8 *)EXIInputFlag; + pEXIInputFlag = &EXIInputFlag; + + *a = pEXIInputFlag; + + MTRCallback = b; + + DBGEXIInit(); + } + OSRestoreInterrupts(interrupts); +} + +void DBInitInterrupts(void) +{ + __OSMaskInterrupts(0x18000); + __OSMaskInterrupts(0x40); + DBGCallback = &MWCallback; + __OSSetInterruptHandler(0x19, DBGHandler); + __OSUnmaskInterrupts(0x40); +} + +static void CheckMailBox(void) +{ + u32 v; + DBGReadStatus(&v); + if (v & 1) { + DBGReadMailbox(&v); + v &= 0x1fffffff; + + if ((v & 0x1f000000) == 0x1f000000) { + SendMailData = v; + RecvDataLeng = v & 0x7fff; + EXIInputFlag = 1; + } + } +} + +u32 DBQueryData(void) +{ + BOOL interrupts; + EXIInputFlag = 0; + if (!RecvDataLeng) { + interrupts = OSDisableInterrupts(); + CheckMailBox(); + } + OSRestoreInterrupts(interrupts); + return RecvDataLeng; +} + +BOOL DBRead(u32 *buffer, s32 count) +{ + u32 interrupts = OSDisableInterrupts(); + u32 v = SendMailData & 0x10000 ? 0x1000 : 0; + + DBGRead(v + 0x1e000, buffer, ROUND_UP(count, 4)); + + RecvDataLeng = 0; + EXIInputFlag = 0; + + OSRestoreInterrupts(interrupts); + + return 0; +} + +BOOL DBWrite(void *src, u32 size) +{ + u32 v; + u32 busyFlag; + BOOL interrupts = OSDisableInterrupts(); + + do { + _DBGReadStatus(&busyFlag); + } while (busyFlag & 2); + + SendCount++; + v = ((SendCount & 1) ? 0x1000 : 0); + + while (!DBGWrite(v | 0x1c000, src, ROUND_UP(size, 4))) + ; + + do { + _DBGReadStatus(&busyFlag); + } while (busyFlag & 2); + + v = SendCount; + while (!DBGWriteMailbox((0x1f000000) | v << 0x10 | size)) + ; + + do { + while (!_DBGReadStatus(&busyFlag)) + ; + } while (busyFlag & 2); + + OSRestoreInterrupts(interrupts); + + return 0; +} + +void DBOpen(void) { } + +void DBClose(void) { } diff --git a/src/amcstubs/AmcExi2Stubs.c b/src/amcstubs/AmcExi2Stubs.c new file mode 100644 index 00000000..f3aa9d3f --- /dev/null +++ b/src/amcstubs/AmcExi2Stubs.c @@ -0,0 +1,40 @@ +#include + +// EXI error codes +typedef enum { AMC_EXI_NO_ERROR = 0, AMC_EXI_UNSELECTED } AmcExiError; + +int AMC_IsStub(); +void EXI2_Unreserve(); +void EXI2_Reserve(); +AmcExiError EXI2_WriteN(); +AmcExiError EXI2_ReadN(); +int EXI2_Poll(); +void EXI2_EnableInterrupts(); +void EXI2_Init(); + +int AMC_IsStub() +{ + return 1; +} + +void EXI2_Unreserve() { } + +void EXI2_Reserve() { } + +AmcExiError EXI2_WriteN() +{ + return AMC_EXI_NO_ERROR; +} + +AmcExiError EXI2_ReadN() +{ + return AMC_EXI_NO_ERROR; +} + +int EXI2_Poll() +{ + return 0; +} + +void EXI2_EnableInterrupts() { } +void EXI2_Init() { } diff --git a/src/dolphin/os/OSAlloc.c b/src/dolphin/os/OSAlloc.c index fe0c34ae..32515afd 100644 --- a/src/dolphin/os/OSAlloc.c +++ b/src/dolphin/os/OSAlloc.c @@ -461,7 +461,9 @@ long OSCheckHeap(int heap) ASSERTREPORT(0x39A, cell->next == NULL || cell->next->prev == cell); ASSERTREPORT(0x39B, MINOBJSIZE <= cell->size); ASSERTREPORT(0x39C, OFFSET(cell->size, ALIGNMENT) == 0); - ASSERTREPORT(0x39D, cell->next == NULL || (char *)cell + cell->size < (char *)cell->next); + /* 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; diff --git a/src/odenotstub/odenotstub.c b/src/odenotstub/odenotstub.c new file mode 100644 index 00000000..2aeb1140 --- /dev/null +++ b/src/odenotstub/odenotstub.c @@ -0,0 +1,7 @@ +#include + +int Hu_IsStub(); + +int Hu_IsStub() { + return 0; +}