commit
0136dda405
5 changed files with 382 additions and 6 deletions
10
configure.py
10
configure.py
|
|
@ -242,7 +242,7 @@ cflags_trk = [
|
||||||
|
|
||||||
cflags_odemuexi = [
|
cflags_odemuexi = [
|
||||||
*cflags_base,
|
*cflags_base,
|
||||||
"-inline auto,deferred",
|
# TODO figure out flags
|
||||||
]
|
]
|
||||||
|
|
||||||
cflags_amcstub = [
|
cflags_amcstub = [
|
||||||
|
|
@ -460,7 +460,7 @@ config.libs = [
|
||||||
[
|
[
|
||||||
Object(Matching, "dolphin/os/OS.c"),
|
Object(Matching, "dolphin/os/OS.c"),
|
||||||
Object(Matching, "dolphin/os/OSAlarm.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/OSArena.c"),
|
||||||
Object(Matching, "dolphin/os/OSAudioSystem.c"),
|
Object(Matching, "dolphin/os/OSAudioSystem.c"),
|
||||||
Object(Matching, "dolphin/os/OSCache.c"),
|
Object(Matching, "dolphin/os/OSCache.c"),
|
||||||
|
|
@ -760,7 +760,7 @@ config.libs = [
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
"lib": "OdemuExi2",
|
"lib": "OdemuExi2",
|
||||||
"mw_version": config.linker_version,
|
"mw_version": "GC/1.2.5",
|
||||||
"cflags": cflags_odemuexi,
|
"cflags": cflags_odemuexi,
|
||||||
"host": False,
|
"host": False,
|
||||||
"objects": [
|
"objects": [
|
||||||
|
|
@ -773,7 +773,7 @@ config.libs = [
|
||||||
"cflags": cflags_amcstub,
|
"cflags": cflags_amcstub,
|
||||||
"host": False,
|
"host": False,
|
||||||
"objects": [
|
"objects": [
|
||||||
Object(NonMatching, "amcstubs/AmcExi2Stubs.c"),
|
Object(Matching, "amcstubs/AmcExi2Stubs.c"),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -782,7 +782,7 @@ config.libs = [
|
||||||
"cflags": cflags_odenotstub,
|
"cflags": cflags_odenotstub,
|
||||||
"host": False,
|
"host": False,
|
||||||
"objects": [
|
"objects": [
|
||||||
Object(NonMatching, "odenotstub/odenotstub.c"),
|
Object(Matching, "odenotstub/odenotstub.c"),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
327
src/OdemuExi2/DebuggerDriver.c
Normal file
327
src/OdemuExi2/DebuggerDriver.c
Normal file
|
|
@ -0,0 +1,327 @@
|
||||||
|
#include <dolphin/exi.h>
|
||||||
|
#include <dolphin/hw_regs.h>
|
||||||
|
#include <dolphin/os.h>
|
||||||
|
|
||||||
|
|
||||||
|
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) { }
|
||||||
40
src/amcstubs/AmcExi2Stubs.c
Normal file
40
src/amcstubs/AmcExi2Stubs.c
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <dolphin.h>
|
||||||
|
|
||||||
|
// 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() { }
|
||||||
|
|
@ -461,7 +461,9 @@ long OSCheckHeap(int heap)
|
||||||
ASSERTREPORT(0x39A, cell->next == NULL || cell->next->prev == cell);
|
ASSERTREPORT(0x39A, cell->next == NULL || cell->next->prev == cell);
|
||||||
ASSERTREPORT(0x39B, MINOBJSIZE <= cell->size);
|
ASSERTREPORT(0x39B, MINOBJSIZE <= cell->size);
|
||||||
ASSERTREPORT(0x39C, OFFSET(cell->size, ALIGNMENT) == 0);
|
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;
|
total += cell->size;
|
||||||
free = (cell->size + free);
|
free = (cell->size + free);
|
||||||
free -= HEADERSIZE;
|
free -= HEADERSIZE;
|
||||||
|
|
|
||||||
7
src/odenotstub/odenotstub.c
Normal file
7
src/odenotstub/odenotstub.c
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include <dolphin.h>
|
||||||
|
|
||||||
|
int Hu_IsStub();
|
||||||
|
|
||||||
|
int Hu_IsStub() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue