Import gx, PadClamp, rest of mtx, TRK 2.6 and MSL (#525)

* Match mtx and Padclamp.c

* Match the rest of GX

* Import TRK 2.6

* Import MSL headers and files

* Merge some MSL headers into ours
This commit is contained in:
dbalatoni13 2025-01-12 15:11:23 +01:00 committed by GitHub
parent a79294aac0
commit cdb1d1fc37
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
113 changed files with 11219 additions and 394 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,43 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/dispatch.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h"
u32 gTRKDispatchTableSize;
struct DispatchEntry {
int (*fn)(TRKBuffer*);
};
struct DispatchEntry gTRKDispatchTable[33] = {
{ &TRKDoUnsupported }, { &TRKDoConnect }, { &TRKDoDisconnect },
{ &TRKDoReset }, { &TRKDoVersions }, { &TRKDoSupportMask },
{ &TRKDoCPUType }, { &TRKDoUnsupported }, { &TRKDoUnsupported },
{ &TRKDoUnsupported }, { &TRKDoUnsupported }, { &TRKDoUnsupported },
{ &TRKDoUnsupported }, { &TRKDoUnsupported }, { &TRKDoUnsupported },
{ &TRKDoUnsupported }, { &TRKDoReadMemory }, { &TRKDoWriteMemory },
{ &TRKDoReadRegisters }, { &TRKDoWriteRegisters }, { &TRKDoUnsupported },
{ &TRKDoUnsupported }, { &TRKDoFlushCache }, { &TRKDoUnsupported },
{ &TRKDoContinue }, { &TRKDoStep }, { &TRKDoStop },
{ &TRKDoUnsupported }, { &TRKDoUnsupported }, { &TRKDoUnsupported },
{ &TRKDoUnsupported }, { &TRKDoUnsupported },
};
DSError TRKInitializeDispatcher()
{
gTRKDispatchTableSize = 32;
return DS_NoError;
}
DSError TRKDispatchMessage(TRKBuffer* buffer)
{
DSError error;
u8 command;
error = DS_DispatchError;
TRKSetBufferPosition(buffer, 0);
TRKReadBuffer1_ui8(buffer, &command);
if (command < gTRKDispatchTableSize) {
error = gTRKDispatchTable[command].fn(buffer);
}
return error;
}

View file

@ -0,0 +1,137 @@
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/main_TRK.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_TRK.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.h"
#include "dolphin/ar.h"
#include "stddef.h"
#define EXCEPTIONMASK_ADDR 0x80000044
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_FloatingPointUnavaiable,
PPC_Decrementer,
PPC_SystemCall,
PPC_Trace,
PPC_PerformanceMonitor,
PPC_InstructionAddressBreakpoint,
PPC_SystemManagementInterrupt,
PPC_ThermalManagementInterrupt };
__declspec(section ".init") void __TRK_reset(void) { __TRK_copy_vectors(); }
asm void InitMetroTRK()
{
#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, 0x80426008@h
ori r1, r1, 0x80426008@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 orginally 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
#endif // clang-format on
}
void EnableMetroTRKInterrupts(void) { EnableEXI2Interrupts(); }
u32 TRKTargetTranslate(u32 param_0)
{
if (param_0 >= lc_base) {
if ((param_0 < lc_base + 0x4000)
&& ((gTRKCPUState.Extended1.DBAT3U & 3) != 0)) {
return param_0;
}
}
return param_0 & 0x3FFFFFFF | 0x80000000;
}
extern u8 gTRKInterruptVectorTable[];
void TRK_copy_vector(u32 offset)
{
void* destPtr = (void*)TRKTargetTranslate(offset);
TRK_memcpy(destPtr, gTRKInterruptVectorTable + offset, 0x100);
TRK_flush_cache(destPtr, 0x100);
}
void __TRK_copy_vectors(void)
{
int i;
u32 mask;
mask = *(u32*)TRKTargetTranslate(0x44);
for (i = 0; i <= 14; ++i) {
if (mask & (1 << i)) {
TRK_copy_vector(TRK_ISR_OFFSETS[i]);
}
}
}
DSError TRKInitializeTarget()
{
gTRKState.isStopped = TRUE;
gTRKState.msr = __TRK_get_MSR();
lc_base = 0xE0000000;
return DS_NoError;
}

View file

@ -0,0 +1,116 @@
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h"
#include "OdemuExi2/odemuexi/DebuggerDriver.h"
#include "amcstubs/AmcExi2Stubs.h"
#include "PowerPC_EABI_Support/MetroTRK/trk.h"
DBCommTable gDBCommTable = {};
asm void TRKLoadContext(OSContext* ctx, u32)
{
#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 lbl_80371C1C
rlwinm r5, r5, 0, 0x1f, 0x1d
sth r5, OSContext.state(r3)
lmw r5, OSContext.gpr[5](r3)
b lbl_80371C20
lbl_80371C1C:
lmw r13, OSContext.gpr[13](r3)
lbl_80371C20:
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
}
void TRKEXICallBack(__OSInterrupt param_0, OSContext* ctx)
{
OSEnableScheduler();
TRKLoadContext(ctx, 0x500);
}
int InitMetroTRKCommTable(int hwId)
{
int result;
if (hwId == HARDWARE_GDEV) {
result = Hu_IsStub();
gDBCommTable.initialize_func = DBInitComm;
gDBCommTable.init_interrupts_func = DBInitInterrupts;
gDBCommTable.peek_func = DBQueryData;
gDBCommTable.read_func = DBRead;
gDBCommTable.write_func = DBWrite;
gDBCommTable.open_func = DBOpen;
gDBCommTable.close_func = DBClose;
} else {
result = AMC_IsStub();
gDBCommTable.initialize_func = EXI2_Init;
gDBCommTable.init_interrupts_func = EXI2_EnableInterrupts;
gDBCommTable.peek_func = EXI2_Poll;
gDBCommTable.read_func = EXI2_ReadN;
gDBCommTable.write_func = EXI2_WriteN;
gDBCommTable.open_func = EXI2_Reserve;
gDBCommTable.close_func = EXI2_Unreserve;
}
return result;
}
void TRKUARTInterruptHandler() { }
DSError TRKInitializeIntDrivenUART(u32 param_0, u32 param_1, u32 param_2,
volatile u8** param_3)
{
gDBCommTable.initialize_func(param_3, TRKEXICallBack);
return DS_NoError;
}
void EnableEXI2Interrupts(void) { 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 == 0 ? 0 : -1;
}
UARTError TRKWriteUARTN(const void* bytes, u32 length)
{
int writeErr = gDBCommTable.write_func(bytes, length);
return writeErr == 0 ? 0 : -1;
}
void ReserveEXI2Port(void) { gDBCommTable.open_func(); }
void UnreserveEXI2Port(void) { gDBCommTable.close_func(); }
void TRK_board_display(char* str) { OSReport(str); }

View file

@ -0,0 +1,26 @@
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.h"
asm void TRK_flush_cache(register void* param_1, register int param_2)
{
#ifdef __MWERKS__ // clang-format off
nofralloc
lis r5, 0xFFFF
ori r5, r5, 0xFFF1
and r5, r5, param_1
subf r3, r5, param_1
add r4, param_2, 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
}

View file

@ -0,0 +1,17 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/main_TRK.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubinit.h"
static DSError TRK_mainError;
DSError TRK_main(void)
{
TRK_mainError = TRKInitializeNub();
if (TRK_mainError == DS_NoError) {
TRKNubWelcome();
TRKNubMainLoop();
}
TRK_mainError = TRKTerminateNub();
return TRK_mainError;
}

View file

@ -0,0 +1,70 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/dispatch.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h"
void TRKHandleRequestEvent(TRKEvent* event)
{
TRKBuffer* buffer = TRKGetBuffer(event->msgBufID);
TRKDispatchMessage(buffer);
}
void TRKHandleSupportEvent(TRKEvent* event) { TRKTargetSupportRequest(); }
void TRKIdle()
{
if (TRKTargetStopped() == FALSE) {
TRKTargetContinue();
}
}
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:
TRKHandleRequestEvent(&event);
break;
case NUBEVENT_Shutdown:
isShutdownRequested = TRUE;
break;
case NUBEVENT_Breakpoint:
case NUBEVENT_Exception:
TRKTargetInterrupt(&event);
break;
case NUBEVENT_Support:
TRKHandleSupportEvent(&event);
break;
}
TRKDestructEvent(&event);
continue;
}
if ((isNewInput == FALSE) || (*(u8*)gTRKInputPendingPtr != '\0')) {
isNewInput = TRUE;
TRKGetInput();
continue;
}
TRKIdle();
isNewInput = FALSE;
}
}

View file

@ -0,0 +1,83 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_TRK.h"
#include "dolphin/types.h"
void TRK_fill_mem(void *dest, int value, unsigned long length)
{
#define cDest ((unsigned char *)dest)
#define lDest ((unsigned long *)dest)
unsigned long val = (unsigned char)value;
unsigned long i;
lDest = (unsigned long *)dest;
cDest = (unsigned char *)dest;
cDest--;
if (length >= 32) {
i = ~(unsigned long)dest & 3;
if (i) {
length -= i;
do {
*++cDest = val;
} while (--i);
}
if (val) {
val |= val << 24 | val << 16 | val << 8;
}
lDest = (unsigned long *)(cDest + 1) - 1;
i = length >> 5;
if (i) {
do {
*++lDest = val;
*++lDest = val;
*++lDest = val;
*++lDest = val;
*++lDest = val;
*++lDest = val;
*++lDest = val;
*++lDest = val;
} while (--i);
}
i = (length & 31) >> 2;
if (i) {
do {
*++lDest = val;
} while (--i);
}
cDest = (unsigned char *)(lDest + 1) - 1;
length &= 3;
}
if (length) {
do {
*++cDest = val;
} while (--length);
}
#undef cDest
#undef lDest
}
__declspec(section ".init") void *TRK_memcpy(void *dst, const void *src, size_t n)
{
const char *p;
char *q;
for (p = (const char *)src - 1, q = (char *)dst - 1, n++; --n;)
*++q = *++p;
return dst;
}
__declspec(section ".init") void *TRK_memset(void *dst, int val, size_t n)
{
TRK_fill_mem(dst, val, n);
return dst;
}

View file

@ -0,0 +1,248 @@
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h"
extern u8 gTRKRestoreFlags[9 + 3 /* padding */];
asm void TRKSaveExtended1Block()
{
#ifdef __MWERKS__ // clang-format off
nofralloc
lis r2, gTRKCPUState@h /* 0x8044F338@h */
ori r2, r2, gTRKCPUState@l /* 0x8044F338@l */
mfsr r16, 0
mfsr r17, 1
mfsr r18, 2
mfsr r19, 3
mfsr r20, 4
mfsr r21, 5
mfsr r22, 6
mfsr r23, 7
mfsr r24, 8
mfsr r25, 9
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
mfpvr r15
mfibatu r16, 0
mfibatl r17, 0
mfibatu r18, 1
mfibatl r19, 1
mfibatu r20, 2
mfibatl r21, 2
mfibatu r22, 3
mfibatl r23, 3
mfdbatu r24, 0
mfdbatl r25, 0
mfdbatu r26, 1
mfdbatl r27, 1
mfdbatu r28, 2
mfdbatl r29, 2
mfdbatu r30, 3
mfdbatl r31, 3
stmw r10, 0x1e8(r2)
mfspr r22, 0x19
mfdar r23
mfdsisr r24
mfspr r25, 0x110
mfspr r26, 0x111
mfspr r27, 0x112
mfspr r28, 0x113
li r29, 0
mfspr r30, 0x3f2
mfspr r31, 0x11a
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 lbl_80371340
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)
lbl_80371340:
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)
b end
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)
mfspr r31, 0x16
stw r31, 0x278(r2)
end:
blr
#endif // clang-format on
}
asm void TRKRestoreExtended1Block()
{
#ifdef __MWERKS__ // clang-format off
nofralloc
lis r2, gTRKCPUState@h /* 0x8044F338@h */
ori r2, r2, gTRKCPUState@l /* 0x8044F338@l */
lis r5, gTRKRestoreFlags@h /* 0x803D3238@h */
ori r5, r5, gTRKRestoreFlags@l /* 0x803D3238@l */
lbz r3, 0(r5)
lbz r6, 1(r5)
li r0, 0
stb r0, 0(r5)
stb r0, 1(r5)
cmpwi r3, 0
beq lbl_803713E4
lwz r24, 0x1e8(r2)
lwz r25, 0x1ec(r2)
mttbl r24
mttbu r25
lbl_803713E4:
lmw r20, 0x2fc(r2)
mtspr 0x390, r20
mtspr 0x391, r21
mtspr 0x392, r22
mtspr 0x393, r23
mtspr 0x394, r24
mtspr 0x395, r25
mtspr 0x396, r26
mtspr 0x397, r27
mtspr 0x398, r28
mtspr 0x39a, r30
mtspr 0x39b, r31
b lbl_80371430
lmw r26, 0x2e0(r2)
mtspr 0x3b0, r26
mtspr 0x3b7, r27
mtspr 0x3f6, r29
mtspr 0x3f7, r30
mtspr 0x3ff, r31
lbl_80371430:
lmw r19, 0x284(r2)
mtspr 0x3f5, r19
mtspr 0x3b9, r20
mtspr 0x3ba, r21
mtspr 0x3bd, r22
mtspr 0x3be, r23
mtspr 0x3bb, r24
mtspr 0x3b8, r25
mtspr 0x3bc, r26
mtspr 0x3fc, r27
mtspr 0x3fd, r28
mtspr 0x3fe, r29
mtspr 0x3FB, r30
mtspr 0x3f9, r31
b lbl_8037149C
cmpwi r6, 0
beq lbl_8037147C
lwz r26, 0x278(r2)
mtspr 0x16, r26
lbl_8037147C:
lmw r25, 0x240(r2)
mtspr 0x3d0, r25
mtspr 0x3d1, r26
mtspr 0x3d2, r27
mtspr 0x3d3, r28
mtspr 0x3D4, r29
mtspr 0x3D5, r30
mtspr 0x3d6, r31
lbl_8037149C:
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 0xa, r26
mtsr 0xb, r27
mtsr 0xc, r28
mtsr 0xd, r29
mtsr 0xe, r30
mtsr 0xf, r31
lmw r12, 0x1f0(r2)
mtspr 0x3f0, r12
mtspr 0x3f1, r13
mtspr 0x1b, r14
mtspr 0x11f, 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)
mtspr 0x19, r22
mtdar r23
mtdsisr r24
mtspr 0x110, r25
mtspr 0x111, r26
mtspr 0x112, r27
mtspr 0x113, r28
mtspr 0x3f2, r30
mtspr 0x11a, r31
blr
#endif // clang-format on
}
u32 TRKTargetCPUMinorType(void) { return 0x54; }

View file

@ -0,0 +1,9 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msg.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h"
#include "PowerPC_EABI_Support/MetroTRK/trk.h"
DSError TRKMessageSend(TRK_Msg* msg)
{
DSError write_err = TRKWriteUARTN(&msg->m_msg, msg->m_msgLength);
return DS_NoError;
}

View file

@ -0,0 +1,359 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubinit.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mutex_TRK.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_TRK.h"
#include "stddef.h"
TRKBuffer gTRKMsgBufs[3];
void TRKSetBufferUsed(TRKBuffer* 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, TRKBuffer** outMsg)
{
TRKBuffer* buf;
DSError error = DS_NoMessageBufferAvailable;
int i;
*outMsg = NULL;
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);
}
return error;
}
void* TRKGetBuffer(int idx)
{
TRKBuffer* buf = NULL;
if (idx >= 0 && idx < 3) {
buf = &gTRKMsgBufs[idx];
}
return buf;
}
void TRKReleaseBuffer(int idx)
{
TRKBuffer* msg;
if (idx != -1 && idx >= 0 && idx < 3) {
msg = &gTRKMsgBufs[idx];
TRKAcquireMutex(msg);
TRKSetBufferUsed(msg, FALSE);
TRKReleaseMutex(msg);
}
}
void TRKResetBuffer(TRKBuffer* msg, BOOL keepData)
{
msg->length = 0;
msg->position = 0;
if (!keepData) {
TRK_memset(msg->data, 0, TRKMSGBUF_SIZE);
}
}
DSError TRKSetBufferPosition(TRKBuffer* 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(TRKBuffer* 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 remaning 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(TRKBuffer* msg, void* data, size_t length)
{
DSError error = DS_NoError;
unsigned int
bytesLeft; // this has to be unsigned int 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;
}
DSError TRKAppendBuffer1_ui16(TRKBuffer* buffer, const u16 data)
{
u8* bigEndianData;
u8* byteData;
u8 swapBuffer[sizeof(data)];
if (gTRKBigEndian) {
bigEndianData = (u8*)&data;
} else {
byteData = (u8*)&data;
bigEndianData = swapBuffer;
bigEndianData[0] = byteData[1];
bigEndianData[1] = byteData[0];
}
return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data));
}
DSError TRKAppendBuffer1_ui32(TRKBuffer* 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(TRKBuffer* 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));
}
DSError TRKAppendBuffer_ui8(TRKBuffer* 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;
}
DSError TRKAppendBuffer_ui32(TRKBuffer* 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;
}
DSError TRKReadBuffer1_ui8(TRKBuffer* buffer, u8* data)
{
return TRKReadBuffer(buffer, (void*)data, 1);
}
DSError TRKReadBuffer1_ui16(TRKBuffer* buffer, u16* 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[1];
byteData[1] = bigEndianData[0];
}
return err;
}
DSError TRKReadBuffer1_ui32(TRKBuffer* 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;
}
DSError TRKReadBuffer1_ui64(TRKBuffer* 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;
}
DSError TRKReadBuffer_ui8(TRKBuffer* 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;
}
DSError TRKReadBuffer_ui32(TRKBuffer* 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;
}

View file

@ -0,0 +1,689 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msg.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h"
#include "PowerPC_EABI_Support/MetroTRK/trk.h"
BOOL IsTRKConnected;
BOOL GetTRKConnected()
{
return IsTRKConnected;
}
void SetTRKConnected(BOOL connected)
{
IsTRKConnected = connected;
}
static void TRKMessageIntoReply(TRKBuffer* buffer, u8 ackCmd,
DSReplyError errSentInAck)
{
TRKResetBuffer(buffer, 1);
TRKAppendBuffer1_ui8(buffer, ackCmd);
TRKAppendBuffer1_ui8(buffer, errSentInAck);
}
DSError TRKSendACK(TRKBuffer* buffer)
{
DSError err;
int ackTries;
ackTries = 3;
do {
err = TRKMessageSend((TRK_Msg*)buffer);
--ackTries;
} while (err != DS_NoError && ackTries > 0);
return err;
}
DSError TRKStandardACK(TRKBuffer* buffer, MessageCommandID commandID,
DSReplyError replyError)
{
TRKMessageIntoReply(buffer, commandID, replyError);
TRKSendACK(buffer);
return;
}
DSError TRKDoUnsupported(TRKBuffer* buffer)
{
return TRKStandardACK(buffer, DSMSG_ReplyACK,
DSREPLY_UnsupportedCommandError);
}
DSError TRKDoConnect(TRKBuffer* buffer)
{
SetTRKConnected(TRUE);
return TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
}
DSError TRKDoDisconnect(TRKBuffer* buffer)
{
DSError error = DS_NoError;
TRKEvent event;
SetTRKConnected(FALSE);
if ((error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NoError))
== DS_NoError) {
TRKConstructEvent(&event, 1);
TRKPostEvent(&event);
}
return error;
}
DSError TRKDoReset(TRKBuffer* buffer)
{
TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
__TRK_reset();
return DS_NoError;
}
DSError TRKDoVersions(TRKBuffer* buffer)
{
DSError error;
DSVersions versions;
if (buffer->length != 1) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
} else {
TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
error = TRKTargetVersions(&versions);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, versions.kernelMajor);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, versions.kernelMinor);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, versions.protocolMajor);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, versions.protocolMinor);
if (error != DS_NoError)
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_CWDSError);
else
error = TRKSendACK(buffer);
}
return error;
}
DSError TRKDoSupportMask(TRKBuffer* buffer)
{
DSError error;
u8 mask[32];
if (buffer->length != 1) {
TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
} else {
TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
error = TRKTargetSupportMask(mask);
if (error == DS_NoError)
error = TRKAppendBuffer(buffer, mask, 32);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, 2);
if (error != DS_NoError)
TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_CWDSError);
else
TRKSendACK(buffer);
}
}
DSError TRKDoCPUType(TRKBuffer* buffer)
{
DSError error;
DSCPUType cputype;
if (buffer->length != 1) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
return error;
}
TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
error = TRKTargetCPUType(&cputype);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, cputype.cpuMajor);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, cputype.cpuMinor);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, cputype.bigEndian);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, cputype.defaultTypeSize);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, cputype.fpTypeSize);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, cputype.extended1TypeSize);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, cputype.extended2TypeSize);
if (error != DS_NoError)
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_CWDSError);
else
error = TRKSendACK(buffer);
return error;
}
DSError TRKDoReadMemory(TRKBuffer* buffer)
{
DSError error;
DSReplyError replyError;
u8 tempBuf[0x800];
u32 length;
u32 msg_start;
u16 msg_length;
u8 msg_options;
u8 msg_command;
if (buffer->length != 8) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
return error;
}
TRKSetBufferPosition(buffer, DSREPLY_NoError);
error = TRKReadBuffer1_ui8(buffer, &msg_command);
if (error == DS_NoError)
error = TRKReadBuffer1_ui8(buffer, &msg_options);
if (error == DS_NoError)
error = TRKReadBuffer1_ui16(buffer, &msg_length);
if (error == DS_NoError)
error = TRKReadBuffer1_ui32(buffer, &msg_start);
if (msg_options & 2) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK,
DSREPLY_UnsupportedOptionError);
return error;
}
if (msg_length > 0x800) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_ParameterError);
return error;
}
TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
if (error == DS_NoError) {
length = (u32)msg_length;
error = TRKTargetAccessMemory(
tempBuf, msg_start, &length,
(msg_options & 8) ? MEMACCESS_UserMemory : MEMACCESS_DebuggerMemory,
1);
msg_length = (u16)length;
if (error == DS_NoError)
error = TRKAppendBuffer1_ui16(buffer, msg_length);
if (error == DS_NoError)
error = TRKAppendBuffer(buffer, tempBuf, length);
}
if (error != DS_NoError) {
switch (error) {
case DS_CWDSException:
replyError = DSREPLY_CWDSException;
break;
case DS_InvalidMemory:
replyError = DSREPLY_InvalidMemoryRange;
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;
break;
}
error = TRKStandardACK(buffer, DSMSG_ReplyACK, replyError);
} else {
error = TRKSendACK(buffer);
}
return error;
}
DSError TRKDoWriteMemory(TRKBuffer* buffer)
{
DSError error;
DSReplyError replyError;
u8 tmpBuffer[0x800];
u32 length;
u32 msg_start;
u16 msg_length;
u8 msg_options;
u8 msg_command;
if (buffer->length <= 8) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
return error;
}
TRKSetBufferPosition(buffer, DSREPLY_NoError);
error = TRKReadBuffer1_ui8(buffer, &msg_command);
if (error == DS_NoError)
error = TRKReadBuffer1_ui8(buffer, &msg_options);
if (error == DS_NoError)
error = TRKReadBuffer1_ui16(buffer, &msg_length);
if (error == DS_NoError)
error = TRKReadBuffer1_ui32(buffer, &msg_start);
if (msg_options & 2) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK,
DSREPLY_UnsupportedOptionError);
return error;
}
if ((buffer->length != msg_length + 8) || (msg_length > 0x800)) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_ParameterError);
} else {
if (error == DS_NoError) {
length = (u32)msg_length;
error = TRKReadBuffer(buffer, tmpBuffer, length);
if (error == DS_NoError) {
error = TRKTargetAccessMemory(tmpBuffer, msg_start, &length,
(msg_options & 8)
? MEMACCESS_UserMemory
: MEMACCESS_DebuggerMemory,
FALSE);
}
msg_length = (u16)length;
}
if (error == DS_NoError)
TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui16(buffer, msg_length);
if (error != DS_NoError) {
switch (error) {
case DS_CWDSException:
replyError = DSREPLY_CWDSException;
break;
case DS_InvalidMemory:
replyError = DSREPLY_InvalidMemoryRange;
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;
break;
}
error = TRKStandardACK(buffer, DSMSG_ReplyACK, replyError);
} else {
error = TRKSendACK(buffer);
}
}
return error;
}
DSError TRKDoReadRegisters(TRKBuffer* buffer)
{
DSError error;
DSReplyError replyError;
DSMessageRegisterOptions options;
u32 registerDataLength;
u16 msg_lastRegister;
u16 msg_firstRegister;
u8 msg_options;
u8 msg_command;
if (buffer->length != 6) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
return error;
}
TRKSetBufferPosition(buffer, DSREPLY_NoError);
error = TRKReadBuffer1_ui8(buffer, &msg_command);
if (error == DS_NoError)
error = TRKReadBuffer1_ui8(buffer, &msg_options);
if (error == DS_NoError)
error = TRKReadBuffer1_ui16(buffer, &msg_firstRegister);
if (error == DS_NoError)
error = TRKReadBuffer1_ui16(buffer, &msg_lastRegister);
if (msg_firstRegister > msg_lastRegister) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK,
DSREPLY_InvalidRegisterRange);
return error;
}
if (error == DS_NoError)
TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
options = (DSMessageRegisterOptions)msg_options;
switch (options) {
case DSREG_Default:
error = TRKTargetAccessDefault(msg_firstRegister, msg_lastRegister,
buffer, &registerDataLength, TRUE);
break;
case DSREG_FP:
error = TRKTargetAccessFP(msg_firstRegister, msg_lastRegister, buffer,
&registerDataLength, TRUE);
break;
case DSREG_Extended1:
error = TRKTargetAccessExtended1(msg_firstRegister, msg_lastRegister,
buffer, &registerDataLength, TRUE);
break;
case DSREG_Extended2:
error = TRKTargetAccessExtended2(msg_firstRegister, msg_lastRegister,
buffer, &registerDataLength, TRUE);
break;
default:
error = DS_UnsupportedError;
break;
}
if (error != DS_NoError) {
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;
}
error = TRKStandardACK(buffer, DSMSG_ReplyACK, replyError);
} else {
error = TRKSendACK(buffer);
}
return error;
}
DSError TRKDoWriteRegisters(TRKBuffer* buffer)
{
DSError error;
DSReplyError replyError;
DSMessageRegisterOptions options;
u32 registerDataLength;
u16 msg_lastRegister;
u16 msg_firstRegister;
u8 msg_options;
u8 msg_command;
if (buffer->length <= 6) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
return error;
}
TRKSetBufferPosition(buffer, DSREPLY_NoError);
error = TRKReadBuffer1_ui8(buffer, &msg_command);
if (error == DS_NoError)
error = TRKReadBuffer1_ui8(buffer, &msg_options);
if (error == DS_NoError)
error = TRKReadBuffer1_ui16(buffer, &msg_firstRegister);
if (error == DS_NoError)
error = TRKReadBuffer1_ui16(buffer, &msg_lastRegister);
if (msg_firstRegister > msg_lastRegister) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK,
DSREPLY_InvalidRegisterRange);
return error;
}
options = (DSMessageRegisterOptions)msg_options;
switch (options) {
case DSREG_Default:
error = TRKTargetAccessDefault(msg_firstRegister, msg_lastRegister,
buffer, &registerDataLength, FALSE);
break;
case DSREG_FP:
error = TRKTargetAccessFP(msg_firstRegister, msg_lastRegister, buffer,
&registerDataLength, FALSE);
break;
case DSREG_Extended1:
error = TRKTargetAccessExtended1(msg_firstRegister, msg_lastRegister,
buffer, &registerDataLength, FALSE);
break;
case DSREG_Extended2:
error = TRKTargetAccessExtended2(msg_firstRegister, msg_lastRegister,
buffer, &registerDataLength, FALSE);
break;
default:
error = DS_UnsupportedError;
break;
}
if (error == DS_NoError)
TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
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;
}
error = TRKStandardACK(buffer, DSMSG_ReplyACK, replyError);
} else {
error = TRKSendACK(buffer);
}
return error;
}
DSError TRKDoFlushCache(TRKBuffer* buffer)
{
DSError error;
DSReplyError replyErr;
u32 msg_end;
u32 msg_start;
u8 msg_options;
u8 msg_command;
if (buffer->length != 10) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
return error;
}
TRKSetBufferPosition(buffer, DSREPLY_NoError);
error = TRKReadBuffer1_ui8(buffer, &msg_command);
if (error == DS_NoError)
error = TRKReadBuffer1_ui8(buffer, &msg_options);
if (error == DS_NoError)
error = TRKReadBuffer1_ui32(buffer, &msg_start);
if (error == DS_NoError)
error = TRKReadBuffer1_ui32(buffer, &msg_end);
if (msg_start > msg_end) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK,
DSREPLY_InvalidMemoryRange);
return error;
}
if (error == DS_NoError)
error = TRKTargetFlushCache(msg_options, (void*)msg_start,
(void*)msg_end);
if (error == DS_NoError)
TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
if (error != DS_NoError) {
switch (error) {
case DS_UnsupportedError:
replyErr = DSREPLY_UnsupportedOptionError;
break;
default:
replyErr = DSREPLY_CWDSError;
break;
}
error = TRKStandardACK(buffer, DSMSG_ReplyACK, replyErr);
} else {
error = TRKSendACK(buffer);
}
return error;
}
DSError TRKDoContinue(TRKBuffer* buffer)
{
DSError error;
error = TRKTargetStopped();
if (error == DS_NoError) {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NotStopped);
return error;
}
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
if (error == DS_NoError)
error = TRKTargetContinue();
return error;
}
DSError TRKDoStep(TRKBuffer* buffer)
{
DSError error;
u8 msg_command;
u8 msg_options;
u8 msg_count;
u32 msg_rangeStart;
u32 msg_rangeEnd;
u32 pc;
if (buffer->length < 3)
return TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError);
TRKSetBufferPosition(buffer, DSREPLY_NoError);
error = TRKReadBuffer1_ui8(buffer, &msg_command);
if (error == DS_NoError)
error = TRKReadBuffer1_ui8(buffer, &msg_options);
switch (msg_options) {
case DSSTEP_IntoCount:
case DSSTEP_OverCount:
if (error == DS_NoError)
TRKReadBuffer1_ui8(buffer, &msg_count);
if (msg_count >= 1) {
break;
}
return TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_ParameterError);
case DSSTEP_IntoRange:
case DSSTEP_OverRange:
if (buffer->length != 10)
return TRKStandardACK(buffer, DSMSG_ReplyACK,
DSREPLY_PacketSizeError);
if (error == DS_NoError)
error = TRKReadBuffer1_ui32(buffer, &msg_rangeStart);
if (error == DS_NoError)
error = TRKReadBuffer1_ui32(buffer, &msg_rangeEnd);
pc = TRKTargetGetPC();
if (pc >= msg_rangeStart && pc <= msg_rangeEnd) {
break;
}
return TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_ParameterError);
default:
return TRKStandardACK(buffer, DSMSG_ReplyACK,
DSREPLY_UnsupportedOptionError);
}
if (!TRKTargetStopped()) {
return TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NotStopped);
} else {
error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NoError);
if (error == DS_NoError)
switch (msg_options) {
case DSSTEP_IntoCount:
case DSSTEP_OverCount:
error = TRKTargetSingleStep(msg_count,
(msg_options == DSSTEP_OverCount));
break;
case DSSTEP_IntoRange:
case DSSTEP_OverRange:
error = TRKTargetStepOutOfRange(
msg_rangeStart, msg_rangeEnd,
(msg_options == DSSTEP_OverRange));
break;
}
return error;
}
}
DSError TRKDoStop(TRKBuffer* b)
{
DSReplyError replyError;
switch (TRKTargetStop()) {
case DS_NoError:
replyError = DSREPLY_NoError;
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_Error;
break;
}
return TRKStandardACK(b, DSMSG_ReplyACK, replyError);
}

View file

@ -0,0 +1,7 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mutex_TRK.h"
DSError TRKInitializeMutex(void*) { return DS_NoError; }
DSError TRKAcquireMutex(void*) { return DS_NoError; }
DSError TRKReleaseMutex(void*) { return DS_NoError; }

View file

@ -0,0 +1,40 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/notify.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/support.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h"
#include "PowerPC_EABI_Support/MetroTRK/trk.h"
DSError TRKDoNotifyStopped(MessageCommandID cmd)
{
DSError err;
int reqIdx;
int bufIdx;
TRKBuffer* msg;
err = TRKGetFreeBuffer(&bufIdx, &msg);
if (err == DS_NoError) {
if (msg->position >= 0x880) {
err = DS_MessageBufferOverflow;
} else {
msg->data[msg->position++] = cmd;
++msg->length;
err = 0;
}
if (err == DS_NoError) {
if (cmd == DSMSG_NotifyStopped) {
TRKTargetAddStopInfo(msg);
} else {
TRKTargetAddExceptionInfo(msg);
}
}
err = TRKRequestSend(msg, &reqIdx, 2, 3, 1);
if (err == DS_NoError) {
TRKReleaseBuffer(reqIdx);
}
TRKReleaseBuffer(bufIdx);
}
return err;
}

View file

@ -0,0 +1,72 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mutex_TRK.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_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(TRKEvent* dstEvent, const TRKEvent* srcEvent)
{
TRK_memcpy(dstEvent, srcEvent, sizeof(TRKEvent));
}
BOOL TRKGetNextEvent(TRKEvent* event)
{
BOOL status = 0;
TRKAcquireMutex(&gTRKEventQueue);
if (0 < gTRKEventQueue.count) {
TRKCopyEvent(event, &gTRKEventQueue.events[gTRKEventQueue.next]);
gTRKEventQueue.count--;
gTRKEventQueue.next++;
if (gTRKEventQueue.next == 2)
gTRKEventQueue.next = 0;
status = 1;
}
TRKReleaseMutex(&gTRKEventQueue);
return status;
}
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;
TRKCopyEvent(&gTRKEventQueue.events[nextEventID], event);
gTRKEventQueue.events[nextEventID].eventID = gTRKEventQueue.eventID;
gTRKEventQueue.eventID++;
if (gTRKEventQueue.eventID < 0x100)
gTRKEventQueue.eventID = 0x100;
gTRKEventQueue.count++;
}
TRKReleaseMutex(&gTRKEventQueue);
return ret;
}
void TRKConstructEvent(TRKEvent* event, NubEventType eventType)
{
event->eventType = eventType;
event->eventID = 0;
event->msgBufID = -1;
}
void TRKDestructEvent(TRKEvent* event) { TRKReleaseBuffer(event->msgBufID); }

View file

@ -0,0 +1,80 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubinit.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/dispatch.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/usr_put.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h"
BOOL gTRKBigEndian;
BOOL TRKInitializeEndian(void);
DSError TRKInitializeNub(void)
{
DSError ret;
DSError uartErr;
ret = TRKInitializeEndian();
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();
if (ret == DS_NoError) {
uartErr = TRKInitializeIntDrivenUART(0x0000e100, 1, 0,
(volatile u8**)&gTRKInputPendingPtr);
TRKTargetSetInputPendingPtr(gTRKInputPendingPtr);
if (uartErr != DS_NoError) {
ret = uartErr;
}
}
if (ret == DS_NoError)
ret = TRKInitializeSerialHandler();
if (ret == DS_NoError)
ret = TRKInitializeTarget();
return ret;
}
DSError TRKTerminateNub(void)
{
TRKTerminateSerialHandler();
return DS_NoError;
}
void TRKNubWelcome(void)
{
TRK_board_display("MetroTRK for GAMECUBE v0.10");
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;
}

View file

@ -0,0 +1,82 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h"
#include "PowerPC_EABI_Support/MetroTRK/trk.h"
static TRKFramingState gTRKFramingState;
void* gTRKInputPendingPtr;
MessageBufferID TRKTestForPacket()
{
int bytes;
int batch;
int err;
TRKBuffer* b;
int id;
bytes = TRKPollUART();
if (bytes > 0) {
TRKGetFreeBuffer(&id, &b);
if (bytes > TRKMSGBUF_SIZE) {
for (; bytes > 0; bytes -= batch) {
batch = bytes > TRKMSGBUF_SIZE ? TRKMSGBUF_SIZE : bytes;
TRKReadUARTN(b->data, batch);
}
TRKStandardACK(b, 0xff, 6);
} else {
err = TRKReadUARTN(b->data, bytes);
if (err == 0) {
b->length = bytes;
return id;
}
}
}
if (id != -1) {
TRKReleaseBuffer(id);
}
return -1;
}
void TRKGetInput(void)
{
MessageBufferID id;
TRKBuffer* msgBuffer;
u8 command;
id = TRKTestForPacket();
if (id == -1)
return;
msgBuffer = TRKGetBuffer(id);
TRKSetBufferPosition(msgBuffer, 0);
TRKReadBuffer1_ui8(msgBuffer, &command);
if (command < DSMSG_ReplyACK) {
TRKProcessInput(id);
} else {
TRKReleaseBuffer(id);
}
}
void TRKProcessInput(int bufferIdx)
{
TRKEvent event;
TRKConstructEvent(&event, NUBEVENT_Request);
gTRKFramingState.msgBufID = -1;
event.msgBufID = bufferIdx;
TRKPostEvent(&event);
}
DSError TRKInitializeSerialHandler(void)
{
gTRKFramingState.msgBufID = -1;
gTRKFramingState.receiveState = DSRECV_Wait;
gTRKFramingState.isEscape = FALSE;
return DS_NoError;
}
DSError TRKTerminateSerialHandler(void) { return DS_NoError; }

View file

@ -0,0 +1,177 @@
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/support.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msg.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h"
#include "stddef.h"
#include "string.h"
DSError TRKSuppAccessFile(u32 file_handle, u8* data, size_t* count,
DSIOResult* io_result, BOOL need_reply, BOOL read)
{
DSError error;
int replyBufferId;
TRKBuffer* replyBuffer;
int bufferId;
TRKBuffer* buffer;
u32 length;
u32 done;
u8 replyIOResult;
u16 replyLength;
BOOL exit;
if (data == NULL || *count == 0) {
return DS_ParameterError;
}
exit = FALSE;
*io_result = DS_IONoError;
done = 0;
error = DS_NoError;
while (!exit && done < *count && error == DS_NoError && *io_result == 0) {
if (*count - done > 0x800) {
length = 0x800;
} else {
length = *count - done;
}
error = TRKGetFreeBuffer(&bufferId, &buffer);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui8(buffer, read ? DSMSG_ReadFile
: DSMSG_WriteFile);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui32(buffer, file_handle);
if (error == DS_NoError)
error = TRKAppendBuffer1_ui16(buffer, length);
if (!read && error == DS_NoError)
error = TRKAppendBuffer_ui8(buffer, data + done, length);
if (error == DS_NoError) {
if (need_reply) {
replyLength = 0;
replyIOResult = 0;
error = TRKRequestSend(buffer, &replyBufferId, read ? 5 : 5, 3,
!(read && file_handle == 0));
if (error == DS_NoError) {
replyBuffer = (TRKBuffer*)TRKGetBuffer(replyBufferId);
TRKSetBufferPosition(replyBuffer, 2);
}
if (error == DS_NoError)
error = TRKReadBuffer1_ui8(replyBuffer, &replyIOResult);
if (error == DS_NoError)
error = TRKReadBuffer1_ui16(replyBuffer, &replyLength);
if (read && error == DS_NoError) {
if (replyBuffer->length != replyLength + 5) {
replyLength = replyBuffer->length - 5;
if (replyIOResult == 0)
replyIOResult = 1;
}
if (replyLength <= length)
error = TRKReadBuffer_ui8(replyBuffer, data + done,
replyLength);
}
if (replyLength != length) {
if ((!read || replyLength >= length) && replyIOResult == 0)
replyIOResult = 1;
length = replyLength;
exit = TRUE;
}
*io_result = (DSIOResult)replyIOResult;
TRKReleaseBuffer(replyBufferId);
} else {
error = TRKMessageSend((TRK_Msg*)buffer);
}
}
TRKReleaseBuffer(bufferId);
done += length;
}
*count = done;
return error;
}
DSError TRKRequestSend(TRKBuffer* msgBuf, int* bufferId, u32 p1, u32 p2, int p3)
{
int error = DS_NoError;
TRKBuffer* buffer;
u32 timer;
int tries;
u8 msg_command;
u8 msg_error;
BOOL badReply = TRUE;
*bufferId = -1;
for (tries = p2 + 1; tries != 0 && *bufferId == -1 && error == DS_NoError;
tries--) {
error = TRKMessageSend((TRK_Msg*)msgBuf);
if (error == DS_NoError) {
if (p3) {
timer = 0;
}
while (TRUE) {
do {
*bufferId = TRKTestForPacket();
if (*bufferId != -1)
break;
} while (!p3 || ++timer < 79999980);
if (*bufferId == -1)
break;
badReply = FALSE;
buffer = TRKGetBuffer(*bufferId);
TRKSetBufferPosition(buffer, 0);
if ((error = TRKReadBuffer1_ui8(buffer, &msg_command))
!= DS_NoError)
break;
if (msg_command >= DSMSG_ReplyACK)
break;
TRKProcessInput(*bufferId);
*bufferId = -1;
}
if (*bufferId != -1) {
if (buffer->length < p1) {
badReply = TRUE;
}
if (error == DS_NoError && !badReply) {
error = TRKReadBuffer1_ui8(buffer, &msg_error);
}
if (error == DS_NoError && !badReply) {
if (msg_command != DSMSG_ReplyACK
|| msg_error != DSREPLY_NoError) {
badReply = TRUE;
}
}
if (error != DS_NoError || badReply) {
TRKReleaseBuffer(*bufferId);
*bufferId = -1;
}
}
}
}
if (*bufferId == -1) {
error = DS_Error800;
}
return error;
}

View file

@ -0,0 +1,12 @@
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.h"
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h"
#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h"
DSError TRKTargetContinue(void)
{
TRKTargetSetStopped(0);
UnreserveEXI2Port();
TRKSwapAndGo();
ReserveEXI2Port();
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
#include "TRK_MINNOW_DOLPHIN/Os/dolphin/usr_put.h"
#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h"
#include "PowerPC_EABI_Support/MetroTRK/trk.h"
void usr_put_initialize(void) { }