diff --git a/config/GAFE01_00/config.yml b/config/GAFE01_00/config.yml index 439db84e..065ec811 100644 --- a/config/GAFE01_00/config.yml +++ b/config/GAFE01_00/config.yml @@ -8,6 +8,7 @@ common_start: 0x8020D78C mw_comment_version: 10 symbols_known: true fill_gaps: false +ldscript_template: config/GAFE01_00/ldscript.tpl block_relocations: # emu64 diff --git a/config/GAFE01_00/ldscript.tpl b/config/GAFE01_00/ldscript.tpl new file mode 100644 index 00000000..7817acd4 --- /dev/null +++ b/config/GAFE01_00/ldscript.tpl @@ -0,0 +1,25 @@ +MEMORY +{ + text : origin = $ORIGIN +} + +SECTIONS +{ + GROUP: + { + $SECTIONS + .stack ALIGN(0x20):{} + } > text + + _stack_end = ($LAST_SECTION_SYMBOL + SIZEOF($LAST_SECTION_NAME)+ 0x7) & ~0x7; + _stack_addr = (_stack_end + 0x2000 + 0x7) & ~0x7; + _db_stack_addr = (_stack_addr + 0x1000); + _db_stack_end = _stack_addr; + __ArenaLo = _db_stack_addr; + __ArenaHi = 0x81700000; +} + +FORCEACTIVE +{ + $FORCEACTIVE +} diff --git a/config/GAFE01_00/splits.txt b/config/GAFE01_00/splits.txt index 128131bb..8188a728 100644 --- a/config/GAFE01_00/splits.txt +++ b/config/GAFE01_00/splits.txt @@ -12,9 +12,6 @@ Sections: .sbss type:bss align:16 .sdata2 type:rodata align:4 -dolphin/os/__start.c: - .init start:0x80003100 end:0x80003354 - boot.c: .text start:0x800056C0 end:0x8000663C .rodata start:0x800A97E0 end:0x800A97E8 @@ -1040,6 +1037,9 @@ dolphin/os/OSTime.c: .text start:0x8007F6F8 end:0x8007FDFC .data start:0x800E09C8 end:0x800E0A28 +dolphin/os/__start.c: + .init start:0x80003100 end:0x80003354 + dolphin/os/__ppc_eabi_init.cpp: .init start:0x80003354 end:0x800033A8 .text start:0x8007FDFC end:0x8007FE90 diff --git a/configure.py b/configure.py index 4368ce2f..2e6337bf 100644 --- a/configure.py +++ b/configure.py @@ -155,7 +155,7 @@ if not config.non_matching: # Tool versions config.binutils_tag = "2.42-1" config.compilers_tag = "20240706" -config.dtk_tag = "v1.2.0" +config.dtk_tag = "v1.5.1" config.objdiff_tag = "v2.3.4" config.sjiswrap_tag = "v1.2.0" config.wibo_tag = "0.6.11" @@ -884,27 +884,27 @@ config.libs = [ "objects": [ Object(Matching, "TRK_MINNOW_DOLPHIN/__exception.s"), Object(Matching, "TRK_MINNOW_DOLPHIN/dispatch.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/dolphin_trk.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/flush_cache.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/main_TRK.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/dolphin_trk.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/flush_cache.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/main_TRK.c"), Object(Matching, "TRK_MINNOW_DOLPHIN/mainloop.c"), Object(Matching, "TRK_MINNOW_DOLPHIN/mem_TRK.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/msg.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/msg.c"), Object(Matching, "TRK_MINNOW_DOLPHIN/msgbuf.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/msghndlr.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/mslsupp.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/mutex_TRK.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/notify.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/msghndlr.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/mslsupp.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/mutex_TRK.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/notify.c"), Object(Matching, "TRK_MINNOW_DOLPHIN/nubevent.c"), Object(Matching, "TRK_MINNOW_DOLPHIN/nubinit.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/serpoll.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/support.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/targcont.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/target_options.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/targimpl.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/targsupp.s"), + Object(Matching, "TRK_MINNOW_DOLPHIN/serpoll.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/support.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/targcont.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/target_options.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/targimpl.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/targsupp.s"), Object(Matching, "TRK_MINNOW_DOLPHIN/usr_put.c"), ], }, diff --git a/include/OdemuExi2/odemuexi/DebuggerDriver.h b/include/OdemuExi2/odemuexi/DebuggerDriver.h new file mode 100644 index 00000000..71a27ed3 --- /dev/null +++ b/include/OdemuExi2/odemuexi/DebuggerDriver.h @@ -0,0 +1,24 @@ +#ifndef ODEMUEXI_DEBUGGER_DRIVER_H +#define ODEMUEXI_DEBUGGER_DRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int Hu_IsStub(); + +void DBInitComm(volatile u8** param_1, __OSInterruptHandler param_2); +void DBInitInterrupts(void); +u32 DBQueryData(void); +int DBRead(void* data, u32 size); +int DBWrite(const void* data, u32 size); +void DBOpen(void); +void DBClose(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/TRK/custconn/CircleBuffer.h b/include/PowerPC_EABI_Support/MetroTRK/custconn/CircleBuffer.h similarity index 100% rename from include/TRK/custconn/CircleBuffer.h rename to include/PowerPC_EABI_Support/MetroTRK/custconn/CircleBuffer.h diff --git a/include/TRK/custconn/cc_gdev.h b/include/PowerPC_EABI_Support/MetroTRK/custconn/cc_gdev.h similarity index 78% rename from include/TRK/custconn/cc_gdev.h rename to include/PowerPC_EABI_Support/MetroTRK/custconn/cc_gdev.h index 97850dac..218cbe27 100644 --- a/include/TRK/custconn/cc_gdev.h +++ b/include/PowerPC_EABI_Support/MetroTRK/custconn/cc_gdev.h @@ -2,15 +2,14 @@ #define TRK_CC_GDEV_H #include "types.h" -#include -// #include "NdevExi2A/DebuggerDriver.h" +#include "NdevExi2A/DebuggerDriver.h" // TODO: figure out what these values represent typedef enum { GDEV_RESULT_10009 = -10009, GDEV_RESULT_10005 = -10005, GDEV_RESULT_10001 = -10001 } UnkGdevEnum; void OutputData(); BOOL IsInitialized(); -int gdev_cc_initialize(u8** flagOut, __OSInterruptHandler handler); +int gdev_cc_initialize(u8** flagOut, OSInterruptHandler handler); int gdev_cc_shutdown(); int gdev_cc_open(); int gdev_cc_close(); diff --git a/include/TRK/dstypes.h b/include/PowerPC_EABI_Support/MetroTRK/dstypes.h similarity index 100% rename from include/TRK/dstypes.h rename to include/PowerPC_EABI_Support/MetroTRK/dstypes.h diff --git a/include/TRK/memmap.h b/include/PowerPC_EABI_Support/MetroTRK/memmap.h similarity index 69% rename from include/TRK/memmap.h rename to include/PowerPC_EABI_Support/MetroTRK/memmap.h index 3ff85621..20524664 100644 --- a/include/TRK/memmap.h +++ b/include/PowerPC_EABI_Support/MetroTRK/memmap.h @@ -1,7 +1,7 @@ #ifndef METROTRK_MEM_TRK_H #define METROTRK_MEM_TRK_H -#include "TRK/dstypes.h" -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/dstypes.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" typedef struct memRange { u8* start; diff --git a/include/TRK/ppc_reg.h b/include/PowerPC_EABI_Support/MetroTRK/ppc_reg.h similarity index 100% rename from include/TRK/ppc_reg.h rename to include/PowerPC_EABI_Support/MetroTRK/ppc_reg.h diff --git a/include/TRK/trk.h b/include/PowerPC_EABI_Support/MetroTRK/trk.h similarity index 66% rename from include/TRK/trk.h rename to include/PowerPC_EABI_Support/MetroTRK/trk.h index 580e9ae2..b5fcf344 100644 --- a/include/TRK/trk.h +++ b/include/PowerPC_EABI_Support/MetroTRK/trk.h @@ -1,43 +1,56 @@ #ifndef _DOLPHIN_TRK_H #define _DOLPHIN_TRK_H -#include -#include "TRK/trktypes.h" -#include "TRK/ppc_reg.h" +#include "types.h" +#include "PowerPC_EABI_Support/MetroTRK/trktypes.h" +#include "PowerPC_EABI_Support/MetroTRK/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*); -DSError TRKDoUnsupported(MessageBuffer*); -DSError TRKDoCPUType(MessageBuffer*); -DSError TRKDoFlushCache(MessageBuffer*); +DSError TRKDoConnect(TRKBuffer*); +DSError TRKDoDisconnect(TRKBuffer*); +DSError TRKDoReset(TRKBuffer*); +DSError TRKDoVersions(TRKBuffer*); +DSError TRKDoSupportMask(TRKBuffer*); +DSError TRKDoOverride(TRKBuffer*); +DSError TRKDoReadMemory(TRKBuffer*); +DSError TRKDoWriteMemory(TRKBuffer*); +DSError TRKDoReadRegisters(TRKBuffer*); +DSError TRKDoWriteRegisters(TRKBuffer*); +DSError TRKDoSetOption(TRKBuffer*); +DSError TRKDoContinue(TRKBuffer*); +DSError TRKDoStep(TRKBuffer*); +DSError TRKDoStop(TRKBuffer*); +DSError TRKDoUnsupported(TRKBuffer*); +DSError TRKDoCPUType(TRKBuffer*); +DSError TRKDoFlushCache(TRKBuffer*); -void SetBufferPosition(MessageBuffer*, u32); +void __TRK_copy_vectors(); + +void SetBufferPosition(TRKBuffer*, u32); void SetTRKConnected(int); int GetTRKConnected(void); -DSError TRKGetFreeBuffer(int*, MessageBuffer**); +DSError TRKGetFreeBuffer(int*, TRKBuffer**); void OutputData(void* data, int length); -void TRKResetBuffer(MessageBuffer* msg, u8 keepData); +void TRKResetBuffer(TRKBuffer* msg, u8 keepData); -DSError TRKReadBuffer1_ui64(MessageBuffer* buffer, u64* data); -DSError TRKAppendBuffer1_ui64(MessageBuffer* buffer, const u64 data); +DSError TRKReadBuffer_ui8(TRKBuffer* buffer, u8* data, int count); +DSError TRKReadBuffer_ui32(TRKBuffer* buffer, u32* data, int count); + +DSError TRKReadBuffer1_ui8(TRKBuffer* buffer, u8* data); +DSError TRKReadBuffer1_ui16(TRKBuffer* buffer, u16* data); +DSError TRKReadBuffer1_ui32(TRKBuffer* buffer, u32* data); +DSError TRKReadBuffer1_ui64(TRKBuffer* buffer, u64* data); + +DSError TRKAppendBuffer_ui8(TRKBuffer* buffer, const u8* data, int count); +DSError TRKAppendBuffer_ui32(TRKBuffer* buffer, const u32* data, int count); +DSError TRKAppendBuffer1_ui16(TRKBuffer* buffer, const u16 data); +DSError TRKAppendBuffer1_ui32(TRKBuffer* buffer, const u32 data); +DSError TRKAppendBuffer1_ui64(TRKBuffer* buffer, const u64 data); //////////////////////////////////// /////// DOLPHIN TRK FUNCTIONS ////// @@ -100,7 +113,7 @@ void TRKConstructEvent(TRKEvent* event, int eventType); void TRKDestructEvent(TRKEvent* event); DSError TRKPostEvent(TRKEvent* event); BOOL TRKGetNextEvent(TRKEvent* event); -DSError TRKDispatchMessage(MessageBuffer*); +DSError TRKDispatchMessage(TRKBuffer*); void* TRKGetBuffer(int); void TRKReleaseBuffer(int); void TRKGetInput(); @@ -115,10 +128,10 @@ DSError TRKTargetSupportRequest(); //////////////////////////////////// ////// NUB AND MEM FUNCTIONS /////// -DSError TRKAppendBuffer_ui8(MessageBuffer*, const u8*, int); -DSError TRKSetBufferPosition(MessageBuffer*, u32); +DSError TRKAppendBuffer_ui8(TRKBuffer*, const u8*, int); +DSError TRKSetBufferPosition(TRKBuffer*, u32); -DSError TRKMessageSend(MessageBuffer*); +DSError TRKMessageSend(TRKBuffer*); void TRKSwapAndGo(void); DSError TRKInitializeNub(void); DSError TRKTerminateNub(void); @@ -156,10 +169,16 @@ DSError TRKRequestSend(); u32 TRKAccessFile(u32, u32, u32*, u8*); //////////////////////////////////// +///// SERIAL POLLING FUNCTIONS ///// +TRKBufferID TRKTestForPacker(); +void TRKGetInput(); +void TRKProcessInput(TRKBufferID bufID); +//////////////////////////////////// + ////////// OTHER FUNCTIONS ///////// DSError TRK_main(void); UARTError InitializeUART(UARTBaudRate baudRate); -DSError TRKInitializeIntDrivenUART(u32, u32, u32, void*); +DSError TRKInitializeIntDrivenUART(u32, u32, u32, volatile u8**); int TRKPollUART(); UARTError TRKReadUARTN(void*, u32); UARTError TRKWriteUARTN(const void* bytes, u32 length); @@ -167,10 +186,12 @@ void usr_put_initialize(); void TRKTargetSetInputPendingPtr(void*); void SetUseSerialIO(u8); u8 GetUseSerialIO(void); +u8 TRKTargetCPUMinorType(); -DSError TRKTargetAddStopInfo(MessageBuffer*); -void TRKTargetAddExceptionInfo(MessageBuffer*); +DSError TRKTargetAddStopInfo(TRKBuffer*); +DSError TRKTargetAddExceptionInfo(TRKBuffer*); void TRKInterruptHandler(); +void TRKPostInterruptEvent(); BOOL usr_puts_serial(const char* msg); //////////////////////////////////// @@ -181,11 +202,11 @@ extern ProcessorState_PPC gTRKCPUState; extern ProcessorRestoreFlags_PPC gTRKRestoreFlags; extern u8 gTRKInterruptVectorTable[]; extern TRKState gTRKState; -extern MessageBuffer gTRKMsgBufs[3]; +extern TRKBuffer gTRKMsgBufs[3]; //////////////////////////////////// ////////// USEFUL STATICS ////////// -static inline DSError TRKAppendBuffer1_ui8(MessageBuffer* buffer, const u8 data) +static inline DSError TRKAppendBuffer1_ui8(TRKBuffer* buffer, const u8 data) { if (buffer->position >= 0x880) { return DS_MessageBufferOverflow; diff --git a/include/TRK/trkenum.h b/include/PowerPC_EABI_Support/MetroTRK/trkenum.h similarity index 95% rename from include/TRK/trkenum.h rename to include/PowerPC_EABI_Support/MetroTRK/trkenum.h index f337fd91..6755a48b 100644 --- a/include/TRK/trkenum.h +++ b/include/PowerPC_EABI_Support/MetroTRK/trkenum.h @@ -40,6 +40,17 @@ typedef enum { DS_Error800 = 0x800, } DSError; +typedef struct DSCPUType { + u8 cpuMajor; + u8 cpuMinor; + u8 bigEndian; + u8 defaultTypeSize; + u8 fpTypeSize; + u8 extended1TypeSize; + u8 extended2TypeSize; +} DSCPUType; +DSError TRKTargetCPUType(DSCPUType* cpuType); + // Where to read/write. typedef enum { DS_Stdin = 0, diff --git a/include/TRK/trktypes.h b/include/PowerPC_EABI_Support/MetroTRK/trktypes.h similarity index 74% rename from include/TRK/trktypes.h rename to include/PowerPC_EABI_Support/MetroTRK/trktypes.h index aa714cb3..d7f07106 100644 --- a/include/TRK/trktypes.h +++ b/include/PowerPC_EABI_Support/MetroTRK/trktypes.h @@ -2,8 +2,8 @@ #define _METROTRK_TRKTYPES_H #include "types.h" -#include -#include "TRK/trkenum.h" +#include "Dolphin/OS/OSInterrupt.h" +#include "PowerPC_EABI_Support/MetroTRK/trkenum.h" #ifdef __cplusplus extern "C" { @@ -12,12 +12,12 @@ extern "C" { /////// 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); +typedef void (*DBCommInitFunc)(volatile u8**, __OSInterruptHandler); +typedef int (*DBCommReadFunc)(void*, u32); +typedef int (*DBCommWriteFunc)(const void*, u32); // Message buffer ID type. -typedef int MessageBufferID; +typedef int TRKBufferID; // Nub event ID type. typedef u32 NubEventID; @@ -29,26 +29,23 @@ typedef int UARTError; #define TRKMSGBUF_SIZE (0x800 + 0x80) // Struct for sending and receiving messages (size 0x88C). -typedef struct MessageBuffer { - u32 _00; // _00, unknown +typedef struct TRKBuffer { + u32 mutex; // _00 BOOL isInUse; // _04 u32 length; // _08 u32 position; // _0C u8 data[TRKMSGBUF_SIZE]; // _10 -} MessageBuffer; +} TRKBuffer; -// Struct for storing DB communication functions (size 0x28). +// Struct for storing DB communication functions (size 0x1C). 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 + DBCommFunc peek_func; // _08 + DBCommReadFunc read_func; // _0C + DBCommWriteFunc write_func; // _10 + DBCommFunc open_func; // _14 + DBCommFunc close_func; // _18 } DBCommTable; // Struct for information on DS versions (kernel and protocol) (size 0x4) @@ -67,11 +64,11 @@ typedef struct 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 + TRKBufferID msgBufID; // _00 + TRKBuffer* buffer; // _04 + u8 receiveState; // _08 + BOOL isEscape; // _0C + u8 fcsType; // _10 } TRKFramingState; // Command reply information (size 0x40). @@ -91,9 +88,9 @@ typedef struct CommandReply { // Nub event information (size 0xC). typedef struct TRKEvent { - u8 eventType; // _00 - NubEventID eventID; // _04 - MessageBufferID msgBufID; // _08 + u8 eventType; // _00 + NubEventID eventID; // _04 + TRKBufferID msgBufID; // _08 } TRKEvent; // Event queue (size 0x28). diff --git a/include/amcstubs/AmcExi2Stubs.h b/include/amcstubs/AmcExi2Stubs.h new file mode 100644 index 00000000..48298c34 --- /dev/null +++ b/include/amcstubs/AmcExi2Stubs.h @@ -0,0 +1,27 @@ +#ifndef AMCEXI2STUBS_H +#define AMCEXI2STUBS_H + +#include "dolphin/os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef __OSInterruptHandler AmcEXICallback; + +typedef enum { AMC_EXI_NO_ERROR = 0, AMC_EXI_UNSELECTED } AmcExiError; + +void EXI2_Init(volatile u8**, AmcEXICallback); +void EXI2_EnableInterrupts(void); +u32 EXI2_Poll(void); +int EXI2_ReadN(void*, u32); +int EXI2_WriteN(const void*, u32); +void EXI2_Reserve(void); +void EXI2_Unreserve(void); +BOOL AMC_IsStub(void); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/include/dolphin/db.h b/include/dolphin/db.h index b5a10929..7fe822e0 100644 --- a/include/dolphin/db.h +++ b/include/dolphin/db.h @@ -1,13 +1,30 @@ #ifndef DB_H #define DB_H +#include "types.h" + #ifdef __cplusplus extern "C"{ #endif +#define OS_DBINTERFACE_ADDR 0x00000040 + +typedef struct DBInterface +{ + u32 bPresent; + u32 exceptionMask; + void (*ExceptionDestination) ( void ); + void *exceptionReturn; +} DBInterface; + +extern DBInterface* __DBInterface; + void DBInit(void); +void DBInitComm(int* inputFlagPtr, int* mtrCallback); +static void __DBExceptionDestination(void); +void DBPrintf(char* format, ...); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/include/dolphin/trk.h b/include/dolphin/trk.h new file mode 100644 index 00000000..86823a38 --- /dev/null +++ b/include/dolphin/trk.h @@ -0,0 +1,21 @@ +#ifndef _DOLPHIN_TRK_H +#define _DOLPHIN_TRK_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +unsigned int TRKTargetContinue(void); +void TRKTargetSetStopped(unsigned int); +void TRKSwapAndGo(); + +void UnreserveEXI2Port(); +void ReserveEXI2Port(); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/src/static/TRK_MINNOW_DOLPHIN/dispatch.c b/src/static/TRK_MINNOW_DOLPHIN/dispatch.c index 5f555040..caef1245 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/dispatch.c +++ b/src/static/TRK_MINNOW_DOLPHIN/dispatch.c @@ -1,37 +1,64 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" u32 gTRKDispatchTableSize; -DSError (*gTRKDispatchTable[])(MessageBuffer*) = { - &TRKDoUnsupported, &TRKDoConnect, &TRKDoDisconnect, - &TRKDoReset, &TRKDoVersions, &TRKDoSupportMask, - &TRKDoCPUType, &TRKDoUnsupported, &TRKDoUnsupported, - &TRKDoUnsupported, &TRKDoUnsupported, &TRKDoUnsupported, - &TRKDoUnsupported, &TRKDoUnsupported, &TRKDoUnsupported, - &TRKDoUnsupported, &TRKDoReadMemory, &TRKDoWriteMemory, - &TRKDoReadRegisters, &TRKDoWriteRegisters, &TRKDoUnsupported, - &TRKDoUnsupported, &TRKDoFlushCache, &TRKDoSetOption, - &TRKDoContinue, &TRKDoStep, &TRKDoStop, - &TRKDoUnsupported, &TRKDoUnsupported, &TRKDoUnsupported, - &TRKDoUnsupported, &TRKDoUnsupported, NULL, +struct DispatchEntry { + DSError (*fn)(TRKBuffer*); }; -DSError TRKInitializeDispatcher() { - gTRKDispatchTableSize = 32; - return DS_NoError; +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 }, { &TRKDoSetOption }, + { &TRKDoContinue }, { &TRKDoStep }, { &TRKDoStop }, + { &TRKDoUnsupported }, { &TRKDoUnsupported }, { &TRKDoUnsupported }, + { &TRKDoUnsupported }, { &TRKDoUnsupported }, +}; + +/* + * --INFO-- + * Address: 8021CEE0 + * Size: 000014 + */ +DSError TRKInitializeDispatcher() +{ + gTRKDispatchTableSize = 32; + return DS_NoError; } -DSError TRKDispatchMessage(MessageBuffer* mbuf) { +/* + * --INFO-- + * Address: ........ + * Size: 0000A0 + */ +DSError TRKOverrideDispatch(TRKBuffer* buffer) +{ + return DS_NoError; - u8 buf; - s16 val; - DSError res = DS_DispatchError; - - TRKSetBufferPosition(mbuf, 0); - TRKReadBuffer1_ui8(mbuf, &buf); - val = buf; - if ((val & 0xFF) < gTRKDispatchTableSize) { - res = gTRKDispatchTable[buf](mbuf); - } - return res; + // UNUSED FUNCTION +} + +/* + * --INFO-- + * Address: 8021CEF4 + * Size: 000084 + */ +DSError TRKDispatchMessage(TRKBuffer* buffer) +{ + DSError error; + u8 command; + + error = DS_DispatchError; + TRKSetBufferPosition(buffer, 0); + TRKReadBuffer1_ui8(buffer, &command); + command &= 0xFF; + if (command < gTRKDispatchTableSize) { + error = gTRKDispatchTable[command].fn(buffer); + } + return error; } diff --git a/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c b/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c index 1570e337..e5a263df 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c +++ b/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk.c @@ -1,5 +1,159 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" -__declspec(section ".init") asm void __TRK_reset(void){ - +#define EXCEPTIONMASK_ADDR 0x80000044 + +static u32 lc_base; +extern u32 _db_stack_addr; + +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() +{ + __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, _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 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 +} + +/* + * --INFO-- + * Address: 8021FEF4 + * Size: 000020 + */ +void EnableMetroTRKInterrupts(void) +{ + EnableEXI2Interrupts(); +} + +/* + * --INFO-- + * Address: 8021FF14 + * Size: 000048 + */ +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; +} + +/* + * --INFO-- + * Address: 8021FF5C + * Size: 000060 + */ +void TRK_copy_vector(u32 offset) +{ + void* destPtr = (void*)TRKTargetTranslate(offset); + TRK_memcpy(destPtr, gTRKInterruptVectorTable + offset, 0x100); + TRK_flush_cache(destPtr, 0x100); +} + +/* + * --INFO-- + * Address: 8021FFBC + * Size: 000094 + */ +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]); + } + } +} + +/* + * --INFO-- + * Address: 80220050 + * Size: 000050 + */ +DSError TRKInitializeTarget() +{ + gTRKState.isStopped = TRUE; + gTRKState.msr = __TRK_get_MSR(); + lc_base = 0xE0000000; + return DS_NoError; } 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..003d4d21 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/dolphin_trk_glue.c @@ -0,0 +1,260 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" +#include "OdemuExi2/odemuexi/DebuggerDriver.h" +#include "amcstubs/AmcExi2Stubs.h" + +#define BUFF_LEN 4362 + +u8 gWriteBuf[BUFF_LEN]; +u8 gReadBuf[BUFF_LEN]; +s32 _MetroTRK_Has_Framing; +s32 gReadCount; +s32 gReadPos; +s32 gWritePos; + +DBCommTable gDBCommTable = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + +/* + * --INFO-- + * Address: 80220460 + * Size: 000088 + */ +asm void TRKLoadContext(OSContext* ctx, u32 a) +{ +#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 +} +/* + * --INFO-- + * Address: 802204E8 + * Size: 000038 + */ +void TRKEXICallBack(__OSInterrupt param_0, OSContext* ctx) +{ + OSEnableScheduler(); + TRKLoadContext(ctx, 0x500); +} + +/* + * --INFO-- + * Address: 80220520 + * Size: 0000E8 + */ +int InitMetroTRKCommTable(int hwId) +{ + int result; + + if (hwId == HARDWARE_GDEV) { + OSReport("MetroTRK : Set to GDEV hardware\n"); + result = Hu_IsStub(); + + gDBCommTable.initialize_func = (DBCommInitFunc)DBInitComm; + gDBCommTable.init_interrupts_func = (DBCommFunc)DBInitInterrupts; + gDBCommTable.peek_func = (DBCommFunc)DBQueryData; + gDBCommTable.read_func = (DBCommReadFunc)DBRead; + gDBCommTable.write_func = (DBCommWriteFunc)DBWrite; + gDBCommTable.open_func = (DBCommFunc)DBOpen; + gDBCommTable.close_func = (DBCommFunc)DBClose; + } else { + OSReport("MetroTRK : Set to AMC DDH hardware\n"); + result = AMC_IsStub(); + + gDBCommTable.initialize_func = (DBCommInitFunc)EXI2_Init; + gDBCommTable.init_interrupts_func = (DBCommFunc)EXI2_EnableInterrupts; + gDBCommTable.peek_func = (DBCommFunc)EXI2_Poll; + gDBCommTable.read_func = (DBCommReadFunc)EXI2_ReadN; + gDBCommTable.write_func = (DBCommWriteFunc)EXI2_WriteN; + gDBCommTable.open_func = (DBCommFunc)EXI2_Reserve; + gDBCommTable.close_func = (DBCommFunc)EXI2_Unreserve; + } + + return result; +} + +/* + * --INFO-- + * Address: 8022060C + * Size: 000040 + */ +DSError TRKInitializeIntDrivenUART(u32 param_0, u32 param_1, u32 param_2, volatile u8** param_3) +{ + gDBCommTable.initialize_func(param_3, TRKEXICallBack); + return DS_NoError; +} + +/* + * --INFO-- + * Address: 8022064C + * Size: 000030 + */ +void EnableEXI2Interrupts(void) +{ + gDBCommTable.init_interrupts_func(); +} + +/* + * --INFO-- + * Address: 8022067C + * Size: 000030 + */ +int TRKPollUART(void) +{ + return gDBCommTable.peek_func(); +} + +/* + * --INFO-- + * Address: 802206AC + * Size: 000044 + */ +UARTError TRKReadUARTN(void* bytes, u32 length) +{ + int readErr = gDBCommTable.read_func(bytes, length); + return readErr == 0 ? 0 : -1; +} + +/* + * --INFO-- + * Address: 802206F0 + * Size: 000044 + */ +UARTError TRKWriteUARTN(const void* bytes, u32 length) +{ + int writeErr = gDBCommTable.write_func(bytes, length); + return writeErr == 0 ? 0 : -1; +} + +/* + * --INFO-- + * Address: ........ + * Size: 000050 + */ +UARTError WriteUARTFlush(void) +{ + UARTError readErr = 0; + + while (gWritePos < 0x800) { + gWriteBuf[gWritePos] = 0; + gWritePos++; + } + if (gWritePos != 0) { + readErr = TRKWriteUARTN(gWriteBuf, gWritePos); + gWritePos = 0; + } + return readErr; +} +/* + * --INFO-- + * Address: ........ + * Size: 00002C + */ +UARTError WriteUART1(u8 arg0) +{ + gWriteBuf[gWritePos++] = arg0; + return 0; +} + +/* + * --INFO-- + * Address: ........ + * Size: 0000F8 + */ +UARTError TRKReadUARTPoll(u8* arg0) +{ + UARTError readErr = 4; + s32 cnt; + + if (gReadPos >= gReadCount) { + gReadPos = 0; + cnt = gReadCount = TRKPollUART(); + if (cnt > 0) { + if (cnt > BUFF_LEN) { + gReadCount = BUFF_LEN; + } + readErr = TRKReadUARTN(gReadBuf, gReadCount); + if (readErr != 0) { + gReadCount = 0; + } + } + } + if (gReadPos < gReadCount) { + *arg0 = gReadBuf[gReadPos++]; + readErr = 0; + } + return readErr; +} + +/* + * --INFO-- + * Address: 80220734 + * Size: 000030 + */ +void ReserveEXI2Port(void) +{ + gDBCommTable.open_func(); +} + +/* + * --INFO-- + * Address: 80220764 + * Size: 000030 + */ +void UnreserveEXI2Port(void) +{ + gDBCommTable.close_func(); +} + +/* + * --INFO-- + * Address: 80220794 + * Size: 000024 + */ +void TRK_board_display(char* str) +{ + OSReport(str); +} + +/* + * --INFO-- + * Address: 80220608 + * Size: 000004 + */ +void TRKUARTInterruptHandler(void) +{ +} 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..252d0c27 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/flush_cache.c @@ -0,0 +1,26 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.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 +} 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..59da5619 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/main_TRK.c @@ -0,0 +1,20 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" + +static DSError TRK_mainError; + +/* + * --INFO-- + * Address: 80220418 + * Size: 000048 + */ +DSError TRK_main(void) +{ + TRK_mainError = TRKInitializeNub(); + + if (TRK_mainError == DS_NoError) { + TRKNubWelcome(); + TRKNubMainLoop(); + } + + return TRK_mainError = TRKTerminateNub(); +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/mainloop.c b/src/static/TRK_MINNOW_DOLPHIN/mainloop.c index 72616c94..e6991795 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/mainloop.c +++ b/src/static/TRK_MINNOW_DOLPHIN/mainloop.c @@ -1,44 +1,91 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" -void TRKNubMainLoop(void){ - - MessageBuffer* msg; - TRKEvent event; - BOOL loop = FALSE; - BOOL statInput = FALSE; - - while(loop == FALSE){ - if(TRKGetNextEvent(&event) != FALSE){ - statInput = FALSE; - switch(event.eventType){ - case 0: - break; - case 2: - msg = TRKGetBuffer(event.msgBufID); - TRKDispatchMessage(msg); - break; - case 1: - loop = TRUE; - break; - case 3: - case 4: - TRKTargetInterrupt(&event); - break; - case 5: - TRKTargetSupportRequest(); - break; - } - TRKDestructEvent(&event); - } - else if((statInput == FALSE) || (*(u8*)gTRKInputPendingPtr != 0)){ - statInput = TRUE; - TRKGetInput(); - } - else{ - if(TRKTargetStopped() == FALSE){ - TRKTargetContinue(); - } - statInput = FALSE; - } - } +extern TRKEventQueue gTRKEventQueue; +extern TRKState gTRKState; + +/* + * --INFO-- + * Address: 8021BF4C + * Size: 000028 + */ +void TRKHandleRequestEvent(TRKEvent* event) +{ + TRKBuffer* buffer = TRKGetBuffer(event->msgBufID); + TRKDispatchMessage(buffer); +} + +/* + * --INFO-- + * Address: 8021BF74 + * Size: 000020 + */ +void TRKHandleSupportEvent(TRKEvent* event) +{ + TRKTargetSupportRequest(); +} + +/* + * --INFO-- + * Address: 8021BF94 + * Size: 00002C + */ +void TRKIdle() +{ + if (TRKTargetStopped() == FALSE) { + TRKTargetContinue(); + } +} + +/* + * --INFO-- + * Address: 8021BFC0 + * Size: 0000F4 + */ +void TRKNubMainLoop(void) +{ + 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; + } } diff --git a/src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c b/src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c index 886c8f8e..40bbdd97 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c +++ b/src/static/TRK_MINNOW_DOLPHIN/mem_TRK.c @@ -1,89 +1,90 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" -void TRK_fill_mem(void *dst, int val, u32 length); +static void TRK_fill_mem(void* dest, int val, size_t count); -__declspec(section ".init") void *TRK_memcpy(void *dst, const void *src, size_t n) +__declspec(section ".init") void* TRK_memcpy(void* dest, const void* src, size_t count) { - const unsigned char *s = (const unsigned char *)src - 1; - unsigned char *d = (unsigned char *)dst - 1; + u8* s = (u8*)src - 1; + u8* d = (u8*)dest - 1; - n++; - while (--n != 0) - *++d = *++s; - return dst; + count++; + + while (--count) { + *++d = *++s; + } } -__declspec(section ".init") void* TRK_memset(void* dst, int val, size_t size){ - TRK_fill_mem(dst, val, size); - - return dst; +__declspec(section ".init") void* TRK_memset(void* dest, int val, size_t count) +{ + TRK_fill_mem(dest, val, count); + return dest; } -void TRK_fill_mem(void *dst, int val, u32 length) { - u32 v = (u8)val; - u32 i; +/* + * --INFO-- + * Address: 8021E7C0 + * Size: 0000C4 + */ +static void TRK_fill_mem(void* dest, int value, size_t length) +{ +#define cDest ((u8*)dest) +#define lDest ((u32*)dest) + u32 val = (u8)value; + u32 i; + lDest = (u32*)dest; + cDest = (u8*)dest; - union - { - u8 *cpd; - u32 *lpd; - } dstu; + cDest--; - dstu.cpd = (((u8 *)dst) - 1); + if (length >= 32) { + i = ~(u32)dest & 3; - if (length >= 32) - { - i = ((~ (u32)dstu.cpd) & 3); + if (i) { + length -= i; + do { + *++cDest = val; + } while (--i); + } - if (i) - { - length -= i; + if (val) { + val |= val << 24 | val << 16 | val << 8; + } - do - *++(dstu.cpd) = (u8)v; - while (--i); - } + lDest = (u32*)(cDest + 1) - 1; - if (v) - v |= ((v << 24) | (v << 16) | (v << 8)); + i = length >> 5; + if (i) { + do { + *++lDest = val; + *++lDest = val; + *++lDest = val; + *++lDest = val; + *++lDest = val; + *++lDest = val; + *++lDest = val; + *++lDest = val; + } while (--i); + } - dstu.lpd = (((u32 *)(dstu.cpd + 1)) - 1); + i = (length & 31) >> 2; - i = (length >> 5); + if (i) { + do { + *++lDest = val; + } while (--i); + } - if (i) - { - do - { - *++(dstu.lpd) = v; - *++(dstu.lpd) = v; - *++(dstu.lpd) = v; - *++(dstu.lpd) = v; - *++(dstu.lpd) = v; - *++(dstu.lpd) = v; - *++(dstu.lpd) = v; - *++(dstu.lpd) = v; - } while (--i); - } + cDest = (u8*)(lDest + 1) - 1; - i = ((length & 31) >> 2); + length &= 3; + } - if (i) - { - do - *++(dstu.lpd) = v; - while (--i); - } + if (length) { + do { + *++cDest = val; + } while (--length); + } - dstu.cpd = (((u8 *)(dstu.lpd + 1)) - 1); - - length &= 3; - } - - if (length) - { - do - *++(dstu.cpd) = (u8)v; - while (--length); - } +#undef cDest +#undef lDest } 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..cf32b38b --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/mpc_7xx_603e.c @@ -0,0 +1,263 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" + +/* + * --INFO-- + * Address: 802200A0 + * Size: 0001B8 + */ +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 +} + +/* + * --INFO-- + * Address: 80220258 + * Size: 0001B8 + */ +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 +} + +/* + * --INFO-- + * Address: 80220410 + * Size: 000008 + */ +u8 TRKTargetCPUMinorType(void) +{ + return 0x54; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/msg.c b/src/static/TRK_MINNOW_DOLPHIN/msg.c index 6124a8be..ed31bd50 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/msg.c +++ b/src/static/TRK_MINNOW_DOLPHIN/msg.c @@ -1,7 +1,59 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" -DSError TRKMessageSend(MessageBuffer* msg) +// Incorrect signature? Should be u8. +UARTError WriteUART1(s8 arg0); + +DSError TRKMessageSend(TRKBuffer* msg) { - DSError writeErr = TRKWriteUARTN(&msg->data, msg->length); - return DS_NoError; + u8 var_r30; + u8 var_r28; + u8 var_r28_2; + s32 var_r3; + s32 i; + + var_r30 = 0; + for (i = 0; i < msg->length; i++) { + var_r30 = var_r30 + msg->data[i]; + } + var_r30 = var_r30 ^ 0xFF; + var_r3 = WriteUART1(0x7E); + if (var_r3 == 0) { + for (i = 0; i < msg->length; i++) { + var_r28 = msg->data[i]; + if (var_r28 == 0x7E || var_r28 == 0x7D) { + var_r3 = WriteUART1(0x7D); + var_r28 ^= 0x20; + if (var_r3 != 0) { + break; + } + } + var_r3 = WriteUART1(var_r28); + if (var_r3 != 0) { + break; + } + } + } + if (var_r3 == 0) { + var_r28_2 = var_r30; + for (i = 0; i < 1; i++) { + if (var_r28_2 == 0x7E || var_r28_2 == 0x7D) { + var_r3 = WriteUART1(0x7D); + var_r28_2 ^= 0x20; + if (var_r3 != 0) { + break; + } + } + var_r3 = WriteUART1(var_r28_2); + if (var_r3 != 0) { + break; + } + } + } + if (var_r3 == 0) { + var_r3 = WriteUART1(0x7E); + } + if (var_r3 == 0) { + var_r3 = WriteUARTFlush(); + } + return var_r3; } diff --git a/src/static/TRK_MINNOW_DOLPHIN/msgbuf.c b/src/static/TRK_MINNOW_DOLPHIN/msgbuf.c index f31fe5fa..f8ddd66c 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/msgbuf.c +++ b/src/static/TRK_MINNOW_DOLPHIN/msgbuf.c @@ -1,9 +1,22 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" -MessageBuffer gTRKMsgBufs[3]; +TRKBuffer gTRKMsgBufs[3]; -void TRKSetBufferUsed(MessageBuffer* msg, BOOL state) { msg->isInUse = state; } +/* + * --INFO-- + * Address: 8021C4CC + * Size: 000008 + */ +static void TRKSetBufferUsed(TRKBuffer* msg, BOOL state) +{ + msg->isInUse = state; +} +/* + * --INFO-- + * Address: 8021C4D4 + * Size: 000078 + */ DSError TRKInitializeMessageBuffers(void) { int i; @@ -17,20 +30,23 @@ DSError TRKInitializeMessageBuffers(void) return DS_NoError; } -DSError TRKGetFreeBuffer(int* msgID, MessageBuffer** outMsg) +/* + * --INFO-- + * Address: 8021C54C + * Size: 00009C + */ +DSError TRKGetFreeBuffer(int* msgID, TRKBuffer** outMsg) { - MessageBuffer* buf; DSError error = DS_NoMessageBufferAvailable; int i; - - *outMsg = nullptr; + *outMsg = NULL; for (i = 0; i < 3; i++) { - buf = TRKGetBuffer(i); + TRKBuffer* buf = TRKGetBuffer(i); TRKAcquireMutex(buf); if (!buf->isInUse) { - TRKResetBuffer(buf, TRUE); + TRKResetBuffer(buf, 1); TRKSetBufferUsed(buf, TRUE); error = DS_NoError; *outMsg = buf; @@ -40,16 +56,21 @@ DSError TRKGetFreeBuffer(int* msgID, MessageBuffer** outMsg) TRKReleaseMutex(buf); } - if (error == DS_NoMessageBufferAvailable) { - usr_puts_serial("ERROR : No buffer available\n"); - } + if (error == DS_NoMessageBufferAvailable) { + usr_puts_serial("ERROR : No buffer available\n"); + } return error; } +/* + * --INFO-- + * Address: 8021C5E8 + * Size: 00002C + */ void* TRKGetBuffer(int idx) { - MessageBuffer* buf = nullptr; + TRKBuffer* buf = NULL; if (idx >= 0 && idx < 3) { buf = &gTRKMsgBufs[idx]; } @@ -57,9 +78,14 @@ void* TRKGetBuffer(int idx) return buf; } +/* + * --INFO-- + * Address: 8021C614 + * Size: 000068 + */ void TRKReleaseBuffer(int idx) { - MessageBuffer* msg; + TRKBuffer* msg; if (idx != -1 && idx >= 0 && idx < 3) { msg = &gTRKMsgBufs[idx]; TRKAcquireMutex(msg); @@ -68,17 +94,27 @@ void TRKReleaseBuffer(int idx) } } -void TRKResetBuffer(MessageBuffer* msg, u8 keepData) +/* + * --INFO-- + * Address: 8021C67C + * Size: 000040 + */ +void TRKResetBuffer(TRKBuffer* msg, u8 keepData) { msg->length = 0; msg->position = 0; if (!keepData) { - TRK_memset(msg->data, 0, 0x880); + TRK_memset(msg->data, 0, TRKMSGBUF_SIZE); } } -DSError TRKSetBufferPosition(MessageBuffer* msg, u32 pos) +/* + * --INFO-- + * Address: 8021C6BC + * Size: 000030 + */ +DSError TRKSetBufferPosition(TRKBuffer* msg, u32 pos) { DSError error = DS_NoError; @@ -96,8 +132,13 @@ DSError TRKSetBufferPosition(MessageBuffer* msg, u32 pos) return error; } +/* + * --INFO-- + * Address: 8021C6EC + * Size: 0000A4 + */ #pragma dont_inline on -DSError TRKAppendBuffer(MessageBuffer* msg, const void* data, size_t length) +DSError TRKAppendBuffer(TRKBuffer* msg, const void* data, size_t length) { DSError error = DS_NoError; // r31 u32 bytesLeft; @@ -132,10 +173,15 @@ DSError TRKAppendBuffer(MessageBuffer* msg, const void* data, size_t length) } #pragma dont_inline reset -DSError TRKReadBuffer(MessageBuffer* msg, void* data, size_t length) +/* + * --INFO-- + * Address: 8021C790 + * Size: 00008C + */ +DSError TRKReadBuffer(TRKBuffer* msg, void* data, size_t length) { DSError error = DS_NoError; - uint bytesLeft; // this has to be uint not u32 to match lmfao. + unsigned int bytesLeft; // this has to be unsigned int not u32 to match lmfao. // Return if no bytes to read if (length == 0) { @@ -156,7 +202,12 @@ DSError TRKReadBuffer(MessageBuffer* msg, void* data, size_t length) return error; } -DSError TRKAppendBuffer1_ui16(MessageBuffer* buffer, const u16 data) +/* + * --INFO-- + * Address: 8021C81C + * Size: 000054 + */ +DSError TRKAppendBuffer1_ui16(TRKBuffer* buffer, const u16 data) { u8* bigEndianData; u8* byteData; @@ -175,7 +226,12 @@ DSError TRKAppendBuffer1_ui16(MessageBuffer* buffer, const u16 data) return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data)); } -DSError TRKAppendBuffer1_ui32(MessageBuffer* buffer, const u32 data) +/* + * --INFO-- + * Address: 8021C870 + * Size: 000064 + */ +DSError TRKAppendBuffer1_ui32(TRKBuffer* buffer, const u32 data) { u8* bigEndianData; u8* byteData; @@ -195,8 +251,12 @@ DSError TRKAppendBuffer1_ui32(MessageBuffer* buffer, const u32 data) return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data)); } - -DSError TRKAppendBuffer1_ui64(MessageBuffer* buffer, const u64 data) +/* + * --INFO-- + * Address: 8021C8D4 + * Size: 000088 + */ +DSError TRKAppendBuffer1_ui64(TRKBuffer* buffer, const u64 data) { u8* bigEndianData; u8* byteData; @@ -220,12 +280,22 @@ DSError TRKAppendBuffer1_ui64(MessageBuffer* buffer, const u64 data) return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data)); } +/* + * --INFO-- + * Address: ........ + * Size: 0000C4 + */ void TRKAppendBuffer1_ui128(void) { // UNUSED FUNCTION } -DSError TRKAppendBuffer_ui8(MessageBuffer* buffer, const u8* data, int count) +/* + * --INFO-- + * Address: 8021C95C + * Size: 000068 + */ +DSError TRKAppendBuffer_ui8(TRKBuffer* buffer, const u8* data, int count) { DSError err; int i; @@ -237,19 +307,22 @@ DSError TRKAppendBuffer_ui8(MessageBuffer* buffer, const u8* data, int count) return err; } -DSError TRKAppendBuffer_ui16(MessageBuffer* buffer, const u16* data, int count) +/* + * --INFO-- + * Address: ........ + * Size: 00007C + */ +void TRKAppendBuffer_ui16(void) { - DSError err; - int i; - - for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { - err = TRKAppendBuffer1_ui16(buffer, data[i]); - } - - return err; + // UNUSED FUNCTION } -DSError TRKAppendBuffer_ui32(MessageBuffer* buffer, const u32* data, int count) +/* + * --INFO-- + * Address: 8021C9C4 + * Size: 00007C + */ +DSError TRKAppendBuffer_ui32(TRKBuffer* buffer, const u32* data, int count) { DSError err; int i; @@ -261,19 +334,42 @@ DSError TRKAppendBuffer_ui32(MessageBuffer* buffer, const u32* data, int count) return err; } +/* + * --INFO-- + * Address: ........ + * Size: 000080 + */ void TRKAppendBuffer_ui64(void) { // UNUSED FUNCTION } +/* + * --INFO-- + * Address: ........ + * Size: 00007C + */ void TRKAppendBuffer_ui128(void) { // UNUSED FUNCTION } -DSError TRKReadBuffer1_ui8(MessageBuffer* buffer, u8* data) { return TRKReadBuffer(buffer, (void*)data, 1); } +/* + * --INFO-- + * Address: 8021CA40 + * Size: 000024 + */ +DSError TRKReadBuffer1_ui8(TRKBuffer* buffer, u8* data) +{ + return TRKReadBuffer(buffer, (void*)data, 1); +} -DSError TRKReadBuffer1_ui16(MessageBuffer* buffer, u16* data) +/* + * --INFO-- + * Address: 8021CA64 + * Size: 000080 + */ +DSError TRKReadBuffer1_ui16(TRKBuffer* buffer, u16* data) { DSError err; @@ -297,10 +393,14 @@ DSError TRKReadBuffer1_ui16(MessageBuffer* buffer, u16* data) } return err; - // UNUSED FUNCTION } -DSError TRKReadBuffer1_ui32(MessageBuffer* buffer, u32* data) +/* + * --INFO-- + * Address: 8021CAE4 + * Size: 000090 + */ +DSError TRKReadBuffer1_ui32(TRKBuffer* buffer, u32* data) { DSError err; @@ -326,10 +426,14 @@ DSError TRKReadBuffer1_ui32(MessageBuffer* buffer, u32* data) } return err; - // UNUSED FUNCTION } -DSError TRKReadBuffer1_ui64(MessageBuffer* buffer, u64* data) +/* + * --INFO-- + * Address: 8021CB74 + * Size: 0000B0 + */ +DSError TRKReadBuffer1_ui64(TRKBuffer* buffer, u64* data) { DSError err; @@ -361,12 +465,22 @@ DSError TRKReadBuffer1_ui64(MessageBuffer* buffer, u64* data) return err; } -void TRKReadBuffer1_ui128(MessageBuffer* buffer, u8* p2, int p3) +/* + * --INFO-- + * Address: ........ + * Size: 0000F0 + */ +void TRKReadBuffer1_ui128(void) { // UNUSED FUNCTION } -DSError TRKReadBuffer_ui8(MessageBuffer* buffer, u8* data, int count) +/* + * --INFO-- + * Address: 8021CC24 + * Size: 000074 + */ +DSError TRKReadBuffer_ui8(TRKBuffer* buffer, u8* data, int count) { DSError err; int i; @@ -378,12 +492,22 @@ DSError TRKReadBuffer_ui8(MessageBuffer* buffer, u8* data, int count) return err; } -void TRKReadBuffer_ui16(MessageBuffer* buffer, u8* p2, int p3) +/* + * --INFO-- + * Address: ........ + * Size: 00007C + */ +void TRKReadBuffer_ui16(void) { // UNUSED FUNCTION } -DSError TRKReadBuffer_ui32(MessageBuffer* buffer, u32* data, int count) +/* + * --INFO-- + * Address: 8021CC98 + * Size: 00007C + */ +DSError TRKReadBuffer_ui32(TRKBuffer* buffer, u32* data, int count) { DSError err; s32 i; @@ -395,12 +519,22 @@ DSError TRKReadBuffer_ui32(MessageBuffer* buffer, u32* data, int count) return err; } -void TRKReadBuffer_ui64(MessageBuffer* buffer, u8* p2, int p3) +/* + * --INFO-- + * Address: ........ + * Size: 00007C + */ +void TRKReadBuffer_ui64(void) { // UNUSED FUNCTION } -void TRKReadBuffer_ui128(MessageBuffer* buffer, u8* p2, int p3) +/* + * --INFO-- + * Address: ........ + * Size: 00007C + */ +void TRKReadBuffer_ui128(void) { // 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..0f6f6497 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/msghndlr.c @@ -0,0 +1,718 @@ +#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(buffer); + --ackTries; + } while (err != DS_NoError && ackTries > 0); + + return err; +} + +DSError TRKStandardACK(TRKBuffer* buffer, MessageCommandID commandID, + DSReplyError replyError) +{ + TRKMessageIntoReply(buffer, commandID, replyError); + return TRKSendACK(buffer); +} + +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); + + error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NoError); + if (error == 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); + } +} + +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; + } + + 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); +} + +DSError TRKDoReadMemory(TRKBuffer* buffer) +{ + DSError error; + DSReplyError replyError; + u8 tempBuf[0x800]; + u32 msg_start; + u32 length; + u16 msg_length; + u8 msg_command; + u8 msg_options; + + 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 msg_start; + u32 length; + u16 msg_length; + u8 msg_command; + u8 msg_options; + + 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_firstRegister; + u16 msg_lastRegister; + u8 msg_command; + u8 msg_options; + + if (buffer->length != 6) { + error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError); + return; + } + 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; + } + + if (error == DS_NoError) + TRKMessageIntoReply(buffer, DSMSG_ReplyACK, DSREPLY_NoError); + + options = (DSMessageRegisterOptions)(msg_options & 7); + switch (options) { + case DSREG_Default: + error = TRKTargetAccessDefault(msg_firstRegister, msg_lastRegister, + buffer, ®isterDataLength, TRUE); + break; + case DSREG_FP: + error = TRKTargetAccessFP(msg_firstRegister, msg_lastRegister, buffer, + ®isterDataLength, TRUE); + break; + case DSREG_Extended1: + error = TRKTargetAccessExtended1(msg_firstRegister, msg_lastRegister, + buffer, ®isterDataLength, TRUE); + break; + case DSREG_Extended2: + error = TRKTargetAccessExtended2(msg_firstRegister, msg_lastRegister, + buffer, ®isterDataLength, 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); + } +} + +DSError TRKDoWriteRegisters(TRKBuffer* buffer) +{ + DSError error; + DSReplyError replyError; + DSMessageRegisterOptions options; + u32 registerDataLength; + u16 msg_firstRegister; + u16 msg_lastRegister; + u8 msg_command; + u8 msg_options; + + if (buffer->length <= 6) { + error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError); + return; + } + 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; + } + + options = (DSMessageRegisterOptions)msg_options; + switch (options) { + case DSREG_Default: + error = TRKTargetAccessDefault(msg_firstRegister, msg_lastRegister, + buffer, ®isterDataLength, FALSE); + break; + case DSREG_FP: + error = TRKTargetAccessFP(msg_firstRegister, msg_lastRegister, buffer, + ®isterDataLength, FALSE); + break; + case DSREG_Extended1: + error = TRKTargetAccessExtended1(msg_firstRegister, msg_lastRegister, + buffer, ®isterDataLength, FALSE); + break; + case DSREG_Extended2: + error = TRKTargetAccessExtended2(msg_firstRegister, msg_lastRegister, + buffer, ®isterDataLength, 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); + } +} + +DSError TRKDoFlushCache(TRKBuffer* buffer) +{ + DSError error; + DSReplyError replyErr; + u32 msg_start; + u32 msg_end; + u8 msg_command; + u8 msg_options; + + if (buffer->length != 10) { + error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError); + return; + } + + 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; + } + + 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); + } +} + +DSError TRKDoContinue(TRKBuffer* buffer) +{ + DSError error; + + error = TRKTargetStopped(); + if (error == DS_NoError) { + error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NotStopped); + return; + } + + error = TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NoError); + if (error == DS_NoError) + error = TRKTargetContinue(); +} + +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) { + TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError); + return; + } + + 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; + } + TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_ParameterError); + return; + case DSSTEP_IntoRange: + case DSSTEP_OverRange: + if (buffer->length != 10) { + TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_PacketSizeError); + return; + } + + 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; + } + TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_ParameterError); + return; + default: + TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_UnsupportedOptionError); + return; + } + + if (!TRKTargetStopped()) { + TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_NotStopped); + return; + } + + 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; + } +} + +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); +} + +DSError TRKDoSetOption(TRKBuffer* buffer) { + DSError error; + u8 spA; + u8 sp9; + u8 sp8; + + spA = 0; + sp9 = 0; + sp8 = 0; + TRKSetBufferPosition(buffer, DSREPLY_NoError); + error = TRKReadBuffer1_ui8(buffer, &spA); + if (error == DS_NoError) { + error = TRKReadBuffer1_ui8(buffer, &sp9); + } + if (error == DS_NoError) { + error = TRKReadBuffer1_ui8(buffer, &sp8); + } + if (error != DS_NoError) { + TRKResetBuffer(buffer, 1); + if (buffer->position < 0x880) { + buffer->data[buffer->position++] = 0x80; + buffer->length++; + } + if (buffer->position < 0x880) { + buffer->data[buffer->position++] = 1; + buffer->length++; + } + TRKSendACK(buffer); + } else if (sp9 == 1) { + SetUseSerialIO(sp8); + } + TRKResetBuffer(buffer, 1); + if (buffer->position < 0x880) { + buffer->data[buffer->position++] = 0x80; + buffer->length++; + } + if (buffer->position < 0x880) { + buffer->data[buffer->position++] = 0; + buffer->length++; + } + return TRKSendACK(buffer); +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/mslsupp.c b/src/static/TRK_MINNOW_DOLPHIN/mslsupp.c new file mode 100644 index 00000000..cbcfc85f --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/mslsupp.c @@ -0,0 +1,112 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" +#include + +// 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 __access_file(u32 handle, u8* buffer, size_t* count, void* ref_con, MessageCommandID cmd); + +/** + * @note Address: 0x800C0B4C + * @note Size: 0xBC + */ +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); +} + +/** + * @note Address: 0x800C0A90 + * @note Size: 0xBC + */ +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); +} + +/** + * @note Address: N/A + * @note Size: 0xB4 + */ +DSIOResult __read_file(u32 handle, u8* buffer, size_t* count, void* ref_con) +{ + return __access_file(handle, buffer, count, ref_con, DSMSG_ReadFile); +} + +/** + * @note Address: N/A + * @note Size: 0xB4 + */ +DSIOResult __write_file(u32 handle, u8* buffer, size_t* count, void* ref_con) +{ + return __access_file(handle, buffer, count, ref_con, DSMSG_WriteFile); +} + +/** + * @note Address: N/A + * @note Size: 0x17C + */ +void __open_file(void) +{ + // UNUSED FUNCTION +} + +/** + * @note Address: N/A + * @note Size: 0xDC + */ +void __position_file(void) +{ + // UNUSED FUNCTION +} + +/** + * @note Address: N/A + * @note Size: 0xE0 + */ +void convertFileMode(void) +{ + // UNUSED FUNCTION +} + +/** + * @note Address: N/A + * @note Size: 0xC0 + */ +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; +} + +/** + * @note Address: N/A + * @note Size: 0x1D0 + */ +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..fe841dac --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/mutex_TRK.c @@ -0,0 +1,31 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" + +/* + * --INFO-- + * Address: 8021E698 + * Size: 000008 + */ +DSError TRKInitializeMutex(void*) +{ + return DS_NoError; +} + +/* + * --INFO-- + * Address: 8021E6A0 + * Size: 000008 + */ +DSError TRKAcquireMutex(void*) +{ + return DS_NoError; +} + +/* + * --INFO-- + * Address: 8021E6A8 + * Size: 000008 + */ +DSError TRKReleaseMutex(void*) +{ + 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..b2ac40a7 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/notify.c @@ -0,0 +1,44 @@ + +#include "PowerPC_EABI_Support/MetroTRK/trk.h" + +inline DSError TRKDoNotifyStopped_Inline(TRKBuffer* msg, MessageCommandID cmd) { + DSError err; + + if (msg->position >= 0x880) { + err = DS_MessageBufferOverflow; + } else { + msg->data[msg->position++] = cmd; + msg->length+=1; + err = 0; + } + return err; +} + +DSError TRKDoNotifyStopped(MessageCommandID cmd) +{ + DSError err; + int reqIdx; + int bufIdx; + TRKBuffer* msg; + + err = TRKGetFreeBuffer(&bufIdx, &msg); + if (err == DS_NoError) { + err = TRKDoNotifyStopped_Inline(msg, cmd); + + if (err == DS_NoError) { + if ((u8)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; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/nubevent.c b/src/static/TRK_MINNOW_DOLPHIN/nubevent.c index 1db082b2..beacc903 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/nubevent.c +++ b/src/static/TRK_MINNOW_DOLPHIN/nubevent.c @@ -1,63 +1,102 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" TRKEventQueue gTRKEventQueue; -DSError TRKInitializeEventQueue(){ - TRKInitializeMutex(&gTRKEventQueue); - TRKAcquireMutex(&gTRKEventQueue); - gTRKEventQueue.count = 0; - gTRKEventQueue.next = 0; +/* + * --INFO-- + * Address: 8021C0B4 + * Size: 00005C + */ +DSError TRKInitializeEventQueue() +{ + TRKInitializeMutex(&gTRKEventQueue); + TRKAcquireMutex(&gTRKEventQueue); + gTRKEventQueue.count = 0; + gTRKEventQueue.next = 0; gTRKEventQueue.eventID = 0x100; - TRKReleaseMutex(&gTRKEventQueue); - return DS_NoError; + TRKReleaseMutex(&gTRKEventQueue); + return DS_NoError; } -BOOL TRKGetNextEvent(TRKEvent* event){ - - BOOL res = FALSE; - TRKAcquireMutex(&gTRKEventQueue); - - if(gTRKEventQueue.count > 0){ - TRK_memcpy(event, &gTRKEventQueue.events[gTRKEventQueue.next], sizeof(TRKEvent)); - gTRKEventQueue.count--; - if(++gTRKEventQueue.next == 2){ - gTRKEventQueue.next = 0; - } - res = TRUE; - } - TRKReleaseMutex(&gTRKEventQueue); - return res; +/* + * --INFO-- + * Address: 8021C110 + * Size: 000024 + */ +void TRKCopyEvent(TRKEvent* dstEvent, const TRKEvent* srcEvent) +{ + TRK_memcpy(dstEvent, srcEvent, sizeof(TRKEvent)); } -DSError TRKPostEvent(TRKEvent* event){ +/* + * --INFO-- + * Address: 8021C134 + * Size: 0000C0 + */ +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; - DSError res = 0; - int evId; - - TRKAcquireMutex(&gTRKEventQueue); - - if(gTRKEventQueue.count == 2){ - res = 0x100; - } - else{ - evId = (gTRKEventQueue.next + gTRKEventQueue.count) % 2; - TRK_memcpy(&gTRKEventQueue.events[evId], event, sizeof(TRKEvent)); - gTRKEventQueue.events[evId].eventID = gTRKEventQueue.eventID; - gTRKEventQueue.eventID++; - if(gTRKEventQueue.eventID < 256){ - gTRKEventQueue.eventID = 256; - } - gTRKEventQueue.count++; - } - TRKReleaseMutex(&gTRKEventQueue); - return res; + status = 1; + } + TRKReleaseMutex(&gTRKEventQueue); + return status; } -void TRKConstructEvent(TRKEvent* event, int type){ - event->eventType = type; - event->eventID = 0; - event->msgBufID = -1; +/* + * --INFO-- + * Address: 8021C1F4 + * Size: 0000E0 + */ +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 TRKDestructEvent(TRKEvent* event){ - TRKReleaseBuffer(event->msgBufID); + +/* + * --INFO-- + * Address: 8021C2D4 + * Size: 000018 + */ +void TRKConstructEvent(TRKEvent* event, int eventType) +{ + event->eventType = eventType; + event->eventID = 0; + event->msgBufID = -1; +} + +/* + * --INFO-- + * Address: 8021C2EC + * Size: 000024 + */ +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 index b447bce6..6908cc55 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/nubinit.c +++ b/src/static/TRK_MINNOW_DOLPHIN/nubinit.c @@ -1,4 +1,4 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" BOOL gTRKBigEndian; @@ -46,7 +46,7 @@ DSError TRKInitializeNub (void){ } if(res == DS_NoError){ - DSError ures = TRKInitializeIntDrivenUART(0xE100, 1, 0, &gTRKInputPendingPtr); + DSError ures = TRKInitializeIntDrivenUART(0xE100, 1, 0, (volatile u8**)&gTRKInputPendingPtr); TRKTargetSetInputPendingPtr(gTRKInputPendingPtr); if(ures != DS_NoError){ res = ures; diff --git a/src/static/TRK_MINNOW_DOLPHIN/serpoll.c b/src/static/TRK_MINNOW_DOLPHIN/serpoll.c new file mode 100644 index 00000000..354007b7 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/serpoll.c @@ -0,0 +1,136 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" + +static TRKFramingState gTRKFramingState; + +void* gTRKInputPendingPtr; + +static inline BOOL serpoll_inline_00(TRKBuffer* buffer) { + if (buffer->length < 2) { + TRKStandardACK(buffer, DSMSG_ReplyNAK, DSREPLY_PacketSizeError); + if (gTRKFramingState.msgBufID != -1) { + TRKReleaseBuffer(gTRKFramingState.msgBufID); + gTRKFramingState.msgBufID = -1; + } + gTRKFramingState.buffer = NULL; + gTRKFramingState.receiveState = DSRECV_Wait; + return FALSE; + } + buffer->position = 0; + buffer->length--; + return TRUE; +} + +int TRKTestForPacket(void) { + s32 var_r29; + s32 var_r3; + s8 sp8; + s32 temp_r3; + + var_r29 = 0; + var_r3 = TRKReadUARTPoll(&sp8); + while (var_r3 == 0 && var_r29 == 0) { + if (gTRKFramingState.receiveState != DSRECV_InFrame) { + gTRKFramingState.isEscape = FALSE; + } + switch (gTRKFramingState.receiveState) { + case DSRECV_Wait: + if (sp8 == 0x7E) { + var_r29 = TRKGetFreeBuffer(&gTRKFramingState.msgBufID, &gTRKFramingState.buffer); + gTRKFramingState.fcsType = 0; + gTRKFramingState.receiveState = DSRECV_Found; + } + break; + case DSRECV_Found: + if (sp8 == 0x7E) { + break; + } + gTRKFramingState.receiveState = DSRECV_InFrame; + /* fallthrough */ + case DSRECV_InFrame: + if (sp8 == 0x7E) { + if (gTRKFramingState.isEscape) { + TRKStandardACK(gTRKFramingState.buffer, DSMSG_ReplyNAK, DSREPLY_EscapeError); + if (gTRKFramingState.msgBufID != -1) { + TRKReleaseBuffer(gTRKFramingState.msgBufID); + gTRKFramingState.msgBufID = -1; + } + gTRKFramingState.buffer = NULL; + gTRKFramingState.receiveState = DSRECV_Wait; + break; + } + if (serpoll_inline_00(gTRKFramingState.buffer)) { + temp_r3 = gTRKFramingState.msgBufID; + gTRKFramingState.msgBufID = -1; + gTRKFramingState.buffer = NULL; + gTRKFramingState.receiveState = DSRECV_Wait; + return temp_r3; + } + gTRKFramingState.receiveState = DSRECV_Wait; + } else { + if (gTRKFramingState.isEscape) { + sp8 ^= 0x20; + gTRKFramingState.isEscape = FALSE; + } else if (sp8 == 0x7D) { + gTRKFramingState.isEscape = TRUE; + break; + } + var_r29 = TRKAppendBuffer1_ui8(gTRKFramingState.buffer, sp8); + gTRKFramingState.fcsType += sp8; + } + break; + case DSRECV_FrameOverflow: + if (sp8 == 0x7E) { + if (gTRKFramingState.msgBufID != -1) { + TRKReleaseBuffer(gTRKFramingState.msgBufID); + gTRKFramingState.msgBufID = -1; + } + gTRKFramingState.buffer = NULL; + gTRKFramingState.receiveState = DSRECV_Wait; + } + break; + } + var_r3 = TRKReadUARTPoll(&sp8); + } + return -1; +} + +void TRKGetInput(void) +{ + TRKBuffer* msgBuffer; + int id; + 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; } diff --git a/src/static/TRK_MINNOW_DOLPHIN/support.c b/src/static/TRK_MINNOW_DOLPHIN/support.c new file mode 100644 index 00000000..7cdd1d51 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/support.c @@ -0,0 +1,282 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" + +DSError TRKSuppAccessFile(u32 file_handle, u8* data, size_t* count, + u8* 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 == DS_IONoError) { + 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(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(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; +} + +DSError HandleOpenFileSupportRequest(const char* path, u8 replyError, u32* param_3, u8* ioResult) { + int sp10; + int spC; + TRKBuffer* sp8; + TRKBuffer* var_r31; + DSError var_r26; + + *param_3 = 0; + var_r26 = TRKGetFreeBuffer(&spC, &sp8); + if (var_r26 == DS_NoError) { + var_r26 = TRKAppendBuffer1_ui8(sp8, 0xD2); + } + if (var_r26 == DS_NoError) { + var_r26 = TRKAppendBuffer1_ui8(sp8, replyError); + } + if (var_r26 == DS_NoError) { + var_r26 = TRKAppendBuffer1_ui16(sp8, strlen(path) + 1); + } + if (var_r26 == DS_NoError) { + var_r26 = TRKAppendBuffer_ui8(sp8, (u8*) path, strlen(path) + 1); + } + if (var_r26 == DS_NoError) { + *ioResult = 0; + var_r26 = TRKRequestSend(sp8, &sp10, 7, 3, 0); + if (var_r26 == DS_NoError) { + var_r31 = TRKGetBuffer(sp10); + TRKSetBufferPosition(var_r31, 2); + } + if (var_r26 == DS_NoError) { + var_r26 = TRKReadBuffer1_ui8(var_r31, ioResult); + } + if (var_r26 == DS_NoError) { + var_r26 = TRKReadBuffer1_ui32(var_r31, param_3); + } + TRKReleaseBuffer(sp10); + } + TRKReleaseBuffer(spC); + return var_r26; +} + +DSError HandleCloseFileSupportRequest(int replyError, u8* ioResult) { + int sp10; + int spC; + DSError var_r31; + TRKBuffer* sp8; + TRKBuffer* var_r30; + + var_r31 = TRKGetFreeBuffer(&spC, &sp8); + if (var_r31 == DS_NoError) { + var_r31 = TRKAppendBuffer1_ui8(sp8, 0xD3); + } + if (var_r31 == DS_NoError) { + var_r31 = TRKAppendBuffer1_ui32(sp8, replyError); + } + if (var_r31 == DS_NoError) { + *ioResult = DS_IONoError; + var_r31 = TRKRequestSend(sp8, &sp10, 3, 3, 0); + if (var_r31 == DS_NoError) { + var_r30 = TRKGetBuffer(sp10); + TRKSetBufferPosition(var_r30, 2); + } + if (var_r31 == DS_NoError) { + var_r31 = TRKReadBuffer1_ui8(var_r30, ioResult); + } + TRKReleaseBuffer(sp10); + } + TRKReleaseBuffer(spC); + return var_r31; +} + +DSError HandlePositionFileSupportRequest(u32 replyErr, u32* param_2, u8 param_3, u8* ioResult) { + int sp10; + int spC; + TRKBuffer* sp8; + TRKBuffer* var_r31; + DSError var_r27; + + var_r27 = TRKGetFreeBuffer(&spC, &sp8); + if (var_r27 == DS_NoError) { + var_r27 = TRKAppendBuffer1_ui8(sp8, 0xD4); + } + if (var_r27 == DS_NoError) { + var_r27 = TRKAppendBuffer1_ui32(sp8, replyErr); + } + if (var_r27 == DS_NoError) { + var_r27 = TRKAppendBuffer1_ui32(sp8, *param_2); + } + if (var_r27 == DS_NoError) { + var_r27 = TRKAppendBuffer1_ui8(sp8, param_3); + } + if (var_r27 == DS_NoError) { + *ioResult = DS_IONoError; + var_r27 = TRKRequestSend(sp8, &sp10, 3, 3, 0); + if (var_r27 == DS_NoError) { + var_r31 = TRKGetBuffer(sp10); + TRKSetBufferPosition(var_r31, 2); + } + if (var_r27 == DS_NoError) { + var_r27 = TRKReadBuffer1_ui8(var_r31, ioResult); + } + if (var_r27 == DS_NoError) { + var_r27 = TRKReadBuffer1_ui32(var_r31, param_2); + } else { + *param_2 = -1; + } + TRKReleaseBuffer(sp10); + } + TRKReleaseBuffer(spC); + return var_r27; +} diff --git a/src/static/TRK_MINNOW_DOLPHIN/targcont.c b/src/static/TRK_MINNOW_DOLPHIN/targcont.c new file mode 100644 index 00000000..a3c9c28c --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/targcont.c @@ -0,0 +1,16 @@ +#include "dolphin/trk.h" + +/* + * --INFO-- + * Address: 802207B8 + * Size: 000034 + */ + +unsigned int TRKTargetContinue(void) +{ + TRKTargetSetStopped(0); + UnreserveEXI2Port(); + TRKSwapAndGo(); + ReserveEXI2Port(); + return 0; +} 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..22cc3e98 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/target_options.c @@ -0,0 +1,11 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" + +static u8 bUseSerialIO; + +void SetUseSerialIO(u8 sio) { + bUseSerialIO = sio; +} + +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..d580ab56 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/targimpl.c @@ -0,0 +1,1195 @@ +#include "PowerPC_EABI_Support/MetroTRK/trk.h" + +typedef struct memRange { + u8* start; + u8* end; + BOOL readable; + BOOL writeable; +} memRange; + +const memRange gTRKMemMap[1] = { { (u8*)0, (u8*)-1, TRUE, TRUE } }; + +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 + u8 type; // 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 }; + +static u16 TRK_saved_exceptionID = 0; +ProcessorState_PPC gTRKCPUState; +TRKState gTRKState; + +typedef unsigned char u128[16]; +u128 TRKvalue128_temp; + +Default_PPC gTRKSaveState; + +// 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_)) + +DSError TRKPPCAccessSPR(void* value, u32 spr_register_num, BOOL read); +DSError TRKPPCAccessPairedSingleRegister(void* srcDestPtr, u32 psr, BOOL read); +DSError TRKPPCAccessFPRegister(void* srcDestPtr, u32 fpr, BOOL read); +DSError TRKPPCAccessSpecialReg(void* value, u32* access_func, BOOL read); +static void TRKExceptionHandler(u16); +void TRKInterruptHandlerEnableInterrupts(void); +void WriteFPSCR(register f64*); +void ReadFPSCR(register f64*); +void __TRK_set_MSR(u32 msr); +u32 __TRK_get_MSR(); +static void TRK_ppc_memcpy(register void* dest, register const void* src, + register int n, register u32 param_4, + register u32 param_5); + +void TRKRestoreExtended1Block(); +void TRKUARTInterruptHandler(); +DSError TRKTargetReadInstruction(void* data, u32 start); +DSError HandleOpenFileSupportRequest(const char* path, u8 replyError, u32* param_3, u8* ioResult); + +static BOOL TRKTargetCheckStep(); + +asm u32 __TRK_get_MSR() +{ +#ifdef __MWERKS__ // clang-format off + nofralloc + mfmsr r3 + blr +#endif // clang-format on +} + +asm void __TRK_set_MSR(register u32 msr) { +#ifdef __MWERKS__ // clang-format off + nofralloc + mtmsr msr + blr +#endif // clang-format on +} + +#pragma dont_inline on +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 ((((u8)readWriteable == VALIDMEM_Readable) + && !gTRKMemMap[i].readable) + || (((u8)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; +} +#pragma dont_inline reset + +static asm void TRK_ppc_memcpy(register void* dest, register const void* src, + register int n, register u32 param_4, + register u32 param_5) { +#ifdef __MWERKS__ // clang-format off +#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 +} + +#pragma dont_inline on +DSError TRKTargetAccessMemory(void* data, u32 start, size_t* length, + MemoryAccessOptions accessOptions, BOOL read) +{ + DSError error; + u32 target_msr; + void* addr; + u32 trk_msr; + TRKExceptionStatus tempExceptionStatus = gTRKExceptionStatus; + gTRKExceptionStatus.exceptionDetected = FALSE; + + addr = (void*)TRKTargetTranslate(start); + error = TRKValidMemory32(addr, *length, + read ? VALIDMEM_Readable : VALIDMEM_Writeable); + + if (error != DS_NoError) { + *length = 0; + } else { + target_msr = __TRK_get_MSR(); + trk_msr = target_msr | gTRKCPUState.Extended1.MSR & 0x10; + + if (read) { + TRK_ppc_memcpy(data, addr, *length, target_msr, trk_msr); + } else { + TRK_ppc_memcpy(addr, data, *length, trk_msr, target_msr); + TRK_flush_cache(addr, *length); + if ((void*)start != addr) { + TRK_flush_cache((void*)start, *length); + } + } + } + + if (gTRKExceptionStatus.exceptionDetected) { + *length = 0; + error = DS_CWDSException; + } + + gTRKExceptionStatus = tempExceptionStatus; + return error; +} +#pragma dont_inline reset + +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, + TRKBuffer* 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, TRKBuffer* 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, + TRKBuffer* 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, + TRKBuffer* 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; +} + +DSError TRKTargetVersions(DSVersions* versions) +{ + versions->kernelMajor = 0; + versions->kernelMinor = 10; + versions->protocolMajor = 1; + versions->protocolMinor = 10; + return DS_NoError; +} + +DSError TRKTargetSupportMask(u8 mask[32]) +{ + mask[0] = 0x7a; + mask[1] = 0; + mask[2] = 0x4f; + mask[3] = 7; + mask[4] = 0; + mask[5] = 0; + mask[6] = 0; + mask[7] = 0; + mask[8] = 0; + mask[9] = 0; + mask[10] = 0; + mask[0xb] = 0; + mask[0xc] = 0; + mask[0xd] = 0; + mask[0xe] = 0; + mask[0xf] = 0; + mask[0x10] = 1; + mask[0x11] = 0; + mask[0x12] = 3; + mask[0x13] = 0; + mask[0x14] = 0; + mask[0x15] = 0; + mask[0x16] = 0; + mask[0x17] = 0; + mask[0x18] = 0; + mask[0x19] = 0; + mask[0x1a] = 3; + mask[0x1b] = 0; + mask[0x1c] = 0; + mask[0x1d] = 0; + mask[0x1e] = 0; + mask[0x1f] = 0x80; + return DS_NoError; +} + +extern BOOL gTRKBigEndian; + +DSError TRKTargetCPUType(DSCPUType* cpuType) +{ + cpuType->cpuMajor = 0; + cpuType->cpuMinor = TRKTargetCPUMinorType(); + cpuType->bigEndian = gTRKBigEndian; + cpuType->defaultTypeSize = 4; + cpuType->fpTypeSize = 8; + cpuType->extended1TypeSize = 4; + cpuType->extended2TypeSize = 8; + return DS_NoError; +} + +asm void TRKInterruptHandler() +{ +#ifdef __MWERKS__ // clang-format off + 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 +} + +static asm void TRKExceptionHandler(u16) +{ +#ifdef __MWERKS__ // clang-format off + 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 +} + +void TRKPostInterruptEvent(void) +{ + NubEventType eventType; + u32 inst; + TRKEvent event; + + if (gTRKState.inputActivated) { + gTRKState.inputActivated = FALSE; + } else { + switch (gTRKCPUState.Extended1.exceptionID & 0xFFFF) { + case 0xd00: + case 0x700: + TRKTargetReadInstruction(&inst, gTRKCPUState.Default.PC); + + if (inst == 0xfe00000) { + eventType = NUBEVENT_Support; + } else { + eventType = NUBEVENT_Breakpoint; + } + break; + default: + eventType = NUBEVENT_Exception; + break; + } + + TRKConstructEvent(&event, eventType); + TRKPostEvent(&event); + } +} + +asm void TRKSwapAndGo() +{ +#ifdef __MWERKS__ // clang-format off + 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 +} + +asm void TRKInterruptHandlerEnableInterrupts(void) +{ +#ifdef __MWERKS__ // clang-format off + 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 +} + +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; +} + +DSError TRKTargetAddStopInfo(TRKBuffer* buffer) +{ + DSError error; + u32 instruction; + s32 i; + + error = TRKAppendBuffer1_ui32(buffer, gTRKCPUState.Default.PC); + if (error == DS_NoError) { + error = TRKTargetReadInstruction(&instruction, gTRKCPUState.Default.PC); + } + if (error == DS_NoError) + error = TRKAppendBuffer1_ui32(buffer, instruction); + if (error == DS_NoError) + error = TRKAppendBuffer1_ui16(buffer, gTRKCPUState.Extended1.exceptionID); + + if (error == DS_NoError) { + for (i = 0; i < 32; i++) { + error = TRKAppendBuffer1_ui32(buffer, (u16) gTRKCPUState.Default.GPR[i]); + } + for (i = 0; i < 32; i++) { + error = TRKAppendBuffer1_ui64(buffer, (u16) gTRKCPUState.Float.FPR[i]); + } + } + + return error; +} + +DSError TRKTargetAddExceptionInfo(TRKBuffer* buffer) +{ + DSError error; + u32 local_10; + + error = TRKAppendBuffer1_ui32(buffer, gTRKExceptionStatus.exceptionInfo.PC); + if (error == 0) { + error = TRKTargetReadInstruction(&local_10, + gTRKExceptionStatus.exceptionInfo.PC); + } + if (error == 0) { + error = TRKAppendBuffer1_ui32(buffer, local_10); + } + if (error == 0) { + error = TRKAppendBuffer1_ui16( + buffer, gTRKExceptionStatus.exceptionInfo.exceptionID); + } + + return error; +} + +static DSError TRKTargetEnableTrace(BOOL val) +{ + if (val) { + gTRKCPUState.Extended1.MSR = (gTRKCPUState.Extended1.MSR | 0x400); + } else { + gTRKCPUState.Extended1.MSR = (gTRKCPUState.Extended1.MSR & ~0x400); + } + return DS_NoError; +} + +static 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; +} + +static DSError TRKTargetDoStep() +{ + gTRKStepStatus.active = TRUE; + 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.type = DSSTEP_IntoCount; + gTRKStepStatus.count = count; + 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() { return gTRKCPUState.Default.PC; } + +DSError TRKTargetSupportRequest(void) { + DSError error; + u32 spC; + size_t* length; + MessageCommandID commandId; + TRKEvent event; + u8 ioResult; + + commandId = (u8) gTRKCPUState.Default.GPR[3]; + if ((u32)commandId != DSMSG_ReadFile && (u32)commandId != DSMSG_WriteFile && (u32)commandId != DSMSG_OpenFile && (u32)commandId != DSMSG_CloseFile && (u32)commandId != DSMSG_PositionFile) { + TRKConstructEvent(&event, NUBEVENT_Exception); + TRKPostEvent(&event); + return DS_NoError; + } + if ((u32)commandId == DSMSG_OpenFile) { + error = HandleOpenFileSupportRequest((char*) gTRKCPUState.Default.GPR[4], (u8)gTRKCPUState.Default.GPR[5], (u32*) gTRKCPUState.Default.GPR[6], &ioResult); + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + gTRKCPUState.Default.GPR[3] = ioResult; + } else if ((u32)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 ((u32)commandId == DSMSG_PositionFile) { + spC = *((u32*) gTRKCPUState.Default.GPR[5]); + error = HandlePositionFileSupportRequest(gTRKCPUState.Default.GPR[4], &spC, (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]) = spC; + } else { + length = (size_t*) gTRKCPUState.Default.GPR[5]; + error = TRKSuppAccessFile((u8) gTRKCPUState.Default.GPR[4], (u8*) gTRKCPUState.Default.GPR[6], length, (DSIOResult*) &ioResult, TRUE, commandId == DSMSG_ReadFile); + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + gTRKCPUState.Default.GPR[3] = ioResult; + if ((u32)commandId == DSMSG_ReadFile) { + TRK_flush_cache((void*) gTRKCPUState.Default.GPR[6], *length); + } + } + gTRKCPUState.Default.PC += 4; + return error; +} + +DSError TRKTargetFlushCache(u8, void* start, void* end) +{ + if (start < end) { + TRK_flush_cache(start, (u8*)end - (u8*)start); + return DS_NoError; + } + + return DS_InvalidMemory; +} + +BOOL TRKTargetStopped() { return gTRKState.isStopped; } + +void TRKTargetSetStopped(unsigned int stopped) +{ + gTRKState.isStopped = stopped; +} + +u32 TRKTargetStop() +{ + TRKTargetSetStopped(1); + return 0; +} + +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); +} + +#pragma dont_inline on +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) { + *(u64*)srcDestPtr &= 0xFFFFFFFF; + } else if (fpr == 0x21) { + if (!read) { + *(u32*)srcDestPtr = *((u32*)(srcDestPtr) + 1); + } + error = TRKPPCAccessSPR(srcDestPtr, 1022, read); + if (read) { + DSFetch_u64(srcDestPtr) = DSFetch_u32(srcDestPtr) & 0xffffffffLL; + } + } + + return error; +} +#pragma dont_inline reset + +#define DEBUG_VECTORREG_ACCESS 0 + +DSError TRKPPCAccessSpecialReg(void* value, u32* access_func, BOOL read) +{ + 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((void*)(u32)access_func, (sizeof(access_func) * 10)); + (*asm_access)((u32*)value, (void*)&TRKvalue128_temp); + + return DS_NoError; +} + +void TRKTargetSetInputPendingPtr(void* ptr) { gTRKState.inputPendingPtr = ptr; } diff --git a/src/static/TRK_MINNOW_DOLPHIN/targsupp.s b/src/static/TRK_MINNOW_DOLPHIN/targsupp.s new file mode 100644 index 00000000..037ce585 --- /dev/null +++ b/src/static/TRK_MINNOW_DOLPHIN/targsupp.s @@ -0,0 +1,33 @@ +.include "macros.inc" +.file "targsupp.s" + +.text +.balign 16 + +.global TRKAccessFile +.type TRKAccessFile, @function +TRKAccessFile: + twui r0, 0x0 + blr +.size TRKAccessFile, . - TRKAccessFile + +.global TRKOpenFile +.type TRKOpenFile, @function +TRKOpenFile: + twui r0, 0x0 + blr +.size TRKOpenFile, . - TRKOpenFile + +.global TRKCloseFile +.type TRKCloseFile, @function +TRKCloseFile: + twui r0, 0x0 + blr +.size TRKCloseFile, . - TRKCloseFile + +.global TRKPositionFile +.type TRKPositionFile, @function +TRKPositionFile: + twui r0, 0x0 + blr +.size TRKPositionFile, . - TRKPositionFile diff --git a/src/static/TRK_MINNOW_DOLPHIN/usr_put.c b/src/static/TRK_MINNOW_DOLPHIN/usr_put.c index e18c2a2a..4550947f 100644 --- a/src/static/TRK_MINNOW_DOLPHIN/usr_put.c +++ b/src/static/TRK_MINNOW_DOLPHIN/usr_put.c @@ -1,23 +1,24 @@ -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" -extern void OSReport(const char*); +BOOL usr_puts_serial(const char* msg) +{ + BOOL connect_ = FALSE; + char c; + char buf[2]; -BOOL usr_puts_serial(const char* putString) { - BOOL res = FALSE; - char tstring; - char buff[2]; - int con; - while ((res == FALSE) && (tstring = *putString++) != 0) { - con = GetTRKConnected(); - buff[0] = tstring; - buff[1] = '\0'; - SetTRKConnected(0); - OSReport(buff); - SetTRKConnected(con); - res = FALSE; - } - return res; + 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() { -} +void usr_put_initialize(void) { } diff --git a/src/static/dolphin/os/__start.c b/src/static/dolphin/os/__start.c index f12babea..23db45b7 100644 --- a/src/static/dolphin/os/__start.c +++ b/src/static/dolphin/os/__start.c @@ -1,6 +1,6 @@ #include "dolphin/os.h" #include "dolphin/db.h" -#include "TRK/trk.h" +#include "PowerPC_EABI_Support/MetroTRK/trk.h" #include "dolphin/os/__ppc_eabi_init.h" #include