diff --git a/config/D44J01/splits.txt b/config/D44J01/splits.txt index ac83aaa33..26eb99474 100644 --- a/config/D44J01/splits.txt +++ b/config/D44J01/splits.txt @@ -3993,7 +3993,7 @@ TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.c: TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s: comment:0 .text start:0x80335DB0 end:0x80335DD0 align:16 -TRK_MINNOW_DOLPHIN/ppc/Generic/__exception.c: comment:0 +TRK_MINNOW_DOLPHIN/ppc/Generic/exception.s: comment:0 .init start:0x80003534 end:0x80005468 TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.c: diff --git a/config/GZLE01/splits.txt b/config/GZLE01/splits.txt index 84da23a2f..0d615b095 100644 --- a/config/GZLE01/splits.txt +++ b/config/GZLE01/splits.txt @@ -4021,7 +4021,7 @@ TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.c: TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s: comment:0 .text start:0x80337020 end:0x80337040 align:16 -TRK_MINNOW_DOLPHIN/ppc/Generic/__exception.c: comment:0 +TRK_MINNOW_DOLPHIN/ppc/Generic/exception.s: comment:0 .init start:0x80003534 end:0x80005468 TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.c: diff --git a/config/GZLJ01/splits.txt b/config/GZLJ01/splits.txt index aab43c2a6..a18b84ef7 100644 --- a/config/GZLJ01/splits.txt +++ b/config/GZLJ01/splits.txt @@ -4017,7 +4017,7 @@ TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.c: TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s: comment:0 .text start:0x80334A20 end:0x80334A40 align:16 -TRK_MINNOW_DOLPHIN/ppc/Generic/__exception.c: comment:0 +TRK_MINNOW_DOLPHIN/ppc/Generic/exception.s: comment:0 .init start:0x80003534 end:0x80005468 TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.c: diff --git a/config/GZLP01/splits.txt b/config/GZLP01/splits.txt index 8153c1ee0..cab83871b 100644 --- a/config/GZLP01/splits.txt +++ b/config/GZLP01/splits.txt @@ -4021,7 +4021,7 @@ TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.c: TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s: comment:0 .text start:0x8033C570 end:0x8033C590 align:16 -TRK_MINNOW_DOLPHIN/ppc/Generic/__exception.c: comment:0 +TRK_MINNOW_DOLPHIN/ppc/Generic/exception.s: comment:0 .init start:0x80003534 end:0x80005468 TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.c: diff --git a/configure.py b/configure.py index a6a6ac34d..bbf0689fd 100755 --- a/configure.py +++ b/configure.py @@ -216,7 +216,7 @@ cflags_base = [ "-fp hardware", "-Cpp_exceptions off", # "-W all", - "-O4,p", + # "-O4,p", "-inline auto", '-pragma "cats off"', '-pragma "warn_notinlined off"', @@ -235,6 +235,7 @@ cflags_base = [ "-i src/PowerPC_EABI_Support/MSL/MSL_C/PPC_EABI/Include", "-i src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include", "-i src/PowerPC_EABI_Support/Runtime/Inc", + "-i src/PowerPC_EABI_Support/MetroTRK", f"-DVERSION={version_num}", ] @@ -258,17 +259,31 @@ elif args.warn == "error": # Metrowerks library flags cflags_runtime = [ *cflags_base, + "-O4,p", "-use_lmw_stmw on", "-str reuse,pool,readonly", - "-gccinc", "-common off", "-inline deferred,auto", "-char signed", ] +cflags_trk = [ + *cflags_base, + "-O4,p", + "-use_lmw_stmw on", + "-rostr", + "-str reuse", + "-common off", + "-inline deferred,auto", + "-char signed", + "-sdata 0", + "-sdata2 0", +] + # Dolphin library flags cflags_dolphin = [ *cflags_base, + "-O4,p", "-fp_contract off", ] @@ -923,16 +938,20 @@ config.libs = [ Object(Matching, "JAZelAudio/JAIZelSound.cpp"), ], }, - DolphinLib( - "gf", - [ + { + "lib": "gf", + "mw_version": "GC/1.3.2", + "cflags": [*cflags_base, "-O3"], + "progress_category": "sdk", + "host": False, + "objects": [ Object(NonMatching, "dolphin/gf/GFGeometry.cpp"), Object(NonMatching, "dolphin/gf/GFLight.cpp"), - Object(NonMatching, "dolphin/gf/GFPixel.cpp"), + Object(MatchingFor("GZLJ01", "GZLE01", "GZLP01"), "dolphin/gf/GFPixel.cpp"), Object(NonMatching, "dolphin/gf/GFTev.cpp"), Object(NonMatching, "dolphin/gf/GFTransform.cpp"), ], - ), + }, JSystemLib( "JKernel", [ @@ -1078,7 +1097,7 @@ config.libs = [ DolphinLib( "base", [ - Object(NonMatching, "dolphin/base/PPCArch.c"), + Object(Matching, "dolphin/base/PPCArch.c"), ], ), DolphinLib( @@ -1109,24 +1128,28 @@ config.libs = [ Object(Matching, "dolphin/os/__ppc_eabi_init.cpp"), ], ), - DolphinLib( - "exi", - [ - Object(NonMatching, "dolphin/exi/EXIBios.c"), - Object(NonMatching, "dolphin/exi/EXIUart.c"), + { + "lib": "exi", + "mw_version": "GC/1.2.5n", + "cflags": [*cflags_base], + "progress_category": "sdk", + "host": False, + "objects": [ + Object(Matching, "dolphin/exi/EXIBios.c", extra_cflags=["-O3,p"]), + Object(Matching, "dolphin/exi/EXIUart.c", extra_cflags=["-O4,p"]), ], - ), + }, DolphinLib( "si", [ - Object(NonMatching, "dolphin/si/SIBios.c"), - Object(NonMatching, "dolphin/si/SISamplingRate.c"), + Object(Matching, "dolphin/si/SIBios.c"), + Object(Matching, "dolphin/si/SISamplingRate.c"), ], ), DolphinLib( "db", [ - Object(NonMatching, "dolphin/db/db.c"), + Object(Matching, "dolphin/db/db.c"), ], ), DolphinLib( @@ -1155,54 +1178,54 @@ config.libs = [ DolphinLib( "vi", [ - Object(NonMatching, "dolphin/vi/vi.c"), + Object(MatchingFor("GZLJ01", "GZLE01"), "dolphin/vi/vi.c"), ], ), DolphinLib( "pad", [ - Object(NonMatching, "dolphin/pad/Padclamp.c"), - Object(NonMatching, "dolphin/pad/Pad.c"), + Object(Matching, "dolphin/pad/Padclamp.c"), + Object(Matching, "dolphin/pad/Pad.c"), ], ), DolphinLib( "ai", [ - Object(NonMatching, "dolphin/ai/ai.c"), - Object(NonMatching, "dolphin/ar/ar.c"), + Object(Matching, "dolphin/ai/ai.c"), + Object(Matching, "dolphin/ar/ar.c"), ], ), DolphinLib( "ar", [ - Object(NonMatching, "dolphin/ar/arq.c"), + Object(Matching, "dolphin/ar/arq.c"), ], ), DolphinLib( "dsp", [ - Object(NonMatching, "dolphin/dsp/dsp.c"), - Object(NonMatching, "dolphin/dsp/dsp_debug.c"), - Object(NonMatching, "dolphin/dsp/dsp_task.c"), + Object(Matching, "dolphin/dsp/dsp.c"), + Object(Matching, "dolphin/dsp/dsp_debug.c"), + Object(Matching, "dolphin/dsp/dsp_task.c"), ], ), DolphinLib( "card", [ - Object(NonMatching, "dolphin/card/CARDBios.c"), - Object(NonMatching, "dolphin/card/CARDUnlock.c"), - Object(NonMatching, "dolphin/card/CARDRdwr.c"), - Object(NonMatching, "dolphin/card/CARDBlock.c"), - Object(NonMatching, "dolphin/card/CARDDir.c"), - Object(NonMatching, "dolphin/card/CARDCheck.c"), - Object(NonMatching, "dolphin/card/CARDMount.c"), - Object(NonMatching, "dolphin/card/CARDFormat.c"), - Object(NonMatching, "dolphin/card/CARDOpen.c"), - Object(NonMatching, "dolphin/card/CARDCreate.c"), - Object(NonMatching, "dolphin/card/CARDRead.c"), - Object(NonMatching, "dolphin/card/CARDWrite.c"), - Object(NonMatching, "dolphin/card/CARDStat.c"), - Object(NonMatching, "dolphin/card/CARDNet.c"), + Object(Matching, "dolphin/card/CARDBios.c"), + Object(Matching, "dolphin/card/CARDUnlock.c"), + Object(Matching, "dolphin/card/CARDRdwr.c"), + Object(Matching, "dolphin/card/CARDBlock.c"), + Object(Matching, "dolphin/card/CARDDir.c"), + Object(Matching, "dolphin/card/CARDCheck.c"), + Object(Matching, "dolphin/card/CARDMount.c"), + Object(Matching, "dolphin/card/CARDFormat.c"), + Object(Matching, "dolphin/card/CARDOpen.c"), + Object(Matching, "dolphin/card/CARDCreate.c"), + Object(Matching, "dolphin/card/CARDRead.c"), + Object(Matching, "dolphin/card/CARDWrite.c"), + Object(Matching, "dolphin/card/CARDStat.c"), + Object(Matching, "dolphin/card/CARDNet.c"), ], ), DolphinLib( @@ -1219,7 +1242,7 @@ config.libs = [ Object(NonMatching, "dolphin/gx/GXBump.c"), Object(NonMatching, "dolphin/gx/GXTev.c"), Object(NonMatching, "dolphin/gx/GXPixel.c"), - Object(NonMatching, "dolphin/gx/GXStubs.c"), + Object(Matching, "dolphin/gx/GXStubs.c"), Object(Matching, "dolphin/gx/GXDisplayList.c"), Object(NonMatching, "dolphin/gx/GXTransform.c", extra_cflags=["-fp_contract off"]), Object(Matching, "dolphin/gx/GXPerf.c"), @@ -1228,8 +1251,8 @@ config.libs = [ DolphinLib( "gd", [ - Object(NonMatching, "dolphin/gd/GDBase.c"), - Object(NonMatching, "dolphin/gd/GDGeometry.c"), + Object(Matching, "dolphin/gd/GDBase.c"), + Object(Matching, "dolphin/gd/GDGeometry.c"), ], ), { @@ -1243,7 +1266,7 @@ config.libs = [ Object(Matching, "PowerPC_EABI_Support/Runtime/Src/__va_arg.c"), Object(Matching, "PowerPC_EABI_Support/Runtime/Src/global_destructor_chain.c"), Object(Matching, "PowerPC_EABI_Support/Runtime/Src/CPlusLibPPC.cp"), - Object(NonMatching, "PowerPC_EABI_Support/Runtime/Src/NMWException.cp"), + Object(Matching, "PowerPC_EABI_Support/Runtime/Src/NMWException.cp", extra_cflags=["-Cpp_exceptions on"]), Object(Matching, "PowerPC_EABI_Support/Runtime/Src/ptmf.c"), Object(Matching, "PowerPC_EABI_Support/Runtime/Src/runtime.c"), Object(Matching, "PowerPC_EABI_Support/Runtime/Src/__init_cpp_exceptions.cpp"), @@ -1313,64 +1336,64 @@ config.libs = [ { "lib": "TRK_MINNOW_DOLPHIN", "mw_version": "GC/1.3.2", - "cflags": cflags_runtime, + "cflags": cflags_trk, "progress_category": "sdk", "host": False, "objects": [ - Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/mainloop.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/nubevent.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/Portable/mainloop.c", extra_cflags=["-enum min"]), + Object(Matching, "TRK_MINNOW_DOLPHIN/Portable/nubevent.c", extra_cflags=["-enum min"]), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/nubinit.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/msg.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/msgbuf.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/serpoll.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/usr_put.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/Portable/usr_put.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/dispatch.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/msghndlr.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/support.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/mutex_TRK.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/Portable/mutex_TRK.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/notify.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/mem_TRK.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/ppc/Generic/__exception.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s"), + Object(NonMatching, "TRK_MINNOW_DOLPHIN/ppc/Generic/exception.s"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/Portable/main_TRK.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/Portable/main_TRK.c"), Object(NonMatching, "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.c"), - Object(NonMatching, "TRK_MINNOW_DOLPHIN/MetroTRK/Export/mslsupp.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.c"), + Object(Matching, "TRK_MINNOW_DOLPHIN/MetroTRK/Export/mslsupp.c"), ], }, { "lib": "amcstubs", "mw_version": "GC/1.3.2", - "cflags": cflags_runtime, + "cflags": cflags_dolphin, "progress_category": "sdk", "host": False, "objects": [ - Object(NonMatching, "amcstubs/AmcExi2Stubs.c"), + Object(Matching, "amcstubs/AmcExi2Stubs.c"), ], }, { "lib": "OdemuExi2", - "mw_version": "GC/1.3.2", + "mw_version": "GC/1.2.5n", "cflags": cflags_runtime, "progress_category": "sdk", "host": False, "objects": [ - Object(NonMatching, "OdemuExi2/DebuggerDriver.c"), + Object(Matching, "OdemuExi2/DebuggerDriver.c"), ], }, { "lib": "odenotstub", "mw_version": "GC/1.3.2", - "cflags": cflags_runtime, + "cflags": cflags_dolphin, "progress_category": "sdk", "host": False, "objects": [ - Object(NonMatching, "odenotstub/odenotstub.c"), + Object(Matching, "odenotstub/odenotstub.c"), ], }, diff --git a/include/JSystem/JUtility/JUTGamePad.h b/include/JSystem/JUtility/JUTGamePad.h index a25a55a00..21c5d7428 100644 --- a/include/JSystem/JUtility/JUTGamePad.h +++ b/include/JSystem/JUtility/JUTGamePad.h @@ -190,7 +190,7 @@ public: CRumble(JUTGamePad* pad) { clear(pad); } static u8 mStatus[4]; - static PADMask mEnabled; + static u32 mEnabled; enum ERumble { LOOP_ONCE = 0, diff --git a/include/TRK_MINNOW_DOLPHIN/GCN/EXI2_DDH_GCN/main.h b/include/TRK_MINNOW_DOLPHIN/GCN/EXI2_DDH_GCN/main.h new file mode 100644 index 000000000..5b05d2ffa --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/GCN/EXI2_DDH_GCN/main.h @@ -0,0 +1,5 @@ +#ifndef GCN_EXI2_DDH_GCN_MAIN_H +#define GCN_EXI2_DDH_GCN_MAIN_H + + +#endif /* GCN_EXI2_DDH_GCN_MAIN_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/GCN/EXI2_GDEV_GCN/main.h b/include/TRK_MINNOW_DOLPHIN/GCN/EXI2_GDEV_GCN/main.h new file mode 100644 index 000000000..90bc6b07a --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/GCN/EXI2_GDEV_GCN/main.h @@ -0,0 +1,5 @@ +#ifndef GCN_EXI2_GDEV_GCN_MAIN_H +#define GCN_EXI2_GDEV_GCN_MAIN_H + + +#endif /* GCN_EXI2_GDEV_GCN_MAIN_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Export/mslsupp.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Export/mslsupp.h new file mode 100644 index 000000000..1354eaa8f --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Export/mslsupp.h @@ -0,0 +1,5 @@ +#ifndef METROTRK_EXPORT_MSLSUPP_H +#define METROTRK_EXPORT_MSLSUPP_H + + +#endif /* METROTRK_EXPORT_MSLSUPP_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/dispatch.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/dispatch.h new file mode 100644 index 000000000..19a35ab67 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/dispatch.h @@ -0,0 +1,33 @@ +#ifndef METROTRK_PORTABLE_DISPATCH_H +#define METROTRK_PORTABLE_DISPATCH_H + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRK_DISPATCH_CMD_CONNECT 1 /* Connect to the console */ +#define TRK_DISPATCH_CMD_DISCONNECT 2 /* Disconnect from the console */ +#define TRK_DISPATCH_CMD_RESET 3 /* Reset the debugger */ +#define TRK_DISPATCH_CMD_GETVERSION 4 /* Get debugger version */ +#define TRK_DISPATCH_CMD_GETSUPPORTMASK 5 /* Get Support Mask */ +#define TRK_DISPATCH_CMD_OVERRIDE 7 /* Override? */ +#define TRK_DISPATCH_CMD_READMEM 16 /* Reading from memory */ +#define TRK_DISPATCH_CMD_WRITEMEM 17 /* Writing to memory */ +#define TRK_DISPATCH_CMD_READREGS 18 /* Read a register value */ +#define TRK_DISPATCH_CMD_WRITEREGS 19 /* Set a register */ +#define TRK_DISPATCH_CMD_SETOPTION 23 /* Set an option? */ +#define TRK_DISPATCH_CMD_CONTINUE 24 /* Continue debugging */ +#define TRK_DISPATCH_CMD_STEP 25 /* Step through an instruction */ +#define TRK_DISPATCH_CMD_STOP 26 /* Stop the debugger */ + +typedef struct TRKBuffer TRKBuffer; + +BOOL TRKDispatchMessage(TRKBuffer* buffer); + +#ifdef __cplusplus +} +#endif + +#endif /* METROTRK_PORTABLE_DISPATCH_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/main_TRK.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/main_TRK.h new file mode 100644 index 000000000..88463dc2a --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/main_TRK.h @@ -0,0 +1,16 @@ +#ifndef METROTRK_PORTABLE_MAIN_TRK_H +#define METROTRK_PORTABLE_MAIN_TRK_H + +#include "trk.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DSError TRK_main(void); + +#ifdef __cplusplus +} +#endif + +#endif /* METROTRK_PORTABLE_MAIN_TRK_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mainloop.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mainloop.h new file mode 100644 index 000000000..69d96c353 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mainloop.h @@ -0,0 +1,7 @@ +#ifndef METROTRK_PORTABLE_MAINLOOP_H +#define METROTRK_PORTABLE_MAINLOOP_H + + +void TRKNubMainLoop(void); + +#endif /* METROTRK_PORTABLE_MAINLOOP_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_TRK.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_TRK.h new file mode 100644 index 000000000..135e1275b --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_TRK.h @@ -0,0 +1,10 @@ +#ifndef METROTRK_PORTABLE_MEM_TRK_H +#define METROTRK_PORTABLE_MEM_TRK_H + +#include "dolphin/types.h" + +void* TRK_memset(void* dest, int val, size_t count); +void* TRK_memcpy(void* dest, const void* src, size_t count); +void TRK_fill_mem(void* dest, int val, size_t count); + +#endif /* METROTRK_PORTABLE_MEM_TRK_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msg.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msg.h new file mode 100644 index 000000000..c2a697ce4 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msg.h @@ -0,0 +1,13 @@ +#ifndef METROTRK_PORTABLE_MSG_H +#define METROTRK_PORTABLE_MSG_H + +#include "dolphin/types.h" + +typedef struct _TRK_Msg { + u8 _00[8]; + u32 m_msgLength; + u32 _0C; + u32 m_msg; +} TRK_Msg; + +#endif /* METROTRK_PORTABLE_MSG_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h new file mode 100644 index 000000000..ff14b4326 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h @@ -0,0 +1,37 @@ +#ifndef METROTRK_PORTABLE_MSGBUF_H +#define METROTRK_PORTABLE_MSGBUF_H + +#include "trk.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DSError TRKSetBufferPosition(TRKBuffer* msg, u32 pos); +void* TRKGetBuffer(int); +void TRKResetBuffer(TRKBuffer* msg, BOOL keepData); + +DSError TRKAppendBuffer1_ui16(TRKBuffer* buffer, const u16 data); +DSError TRKAppendBuffer1_ui32(TRKBuffer* buffer, const u32 data); +DSError TRKAppendBuffer1_ui64(TRKBuffer* buffer, const u64 data); + +DSError TRKAppendBuffer_ui8(TRKBuffer* buffer, const u8* data, int count); +DSError TRKAppendBuffer_ui16(TRKBuffer* buffer, const u16* data, int count); +DSError TRKAppendBuffer_ui32(TRKBuffer* buffer, const u32* data, int count); +DSError TRKAppendBuffer_ui64(TRKBuffer* buffer, const u64* 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 TRKReadBuffer_ui8(TRKBuffer* buffer, u8* data, int count); +DSError TRKReadBuffer_ui16(TRKBuffer* buffer, u16* data, int count); +DSError TRKReadBuffer_ui32(TRKBuffer* buffer, u32* data, int count); +DSError TRKReadBuffer_ui64(TRKBuffer* buffer, u64* data, int count); + +#ifdef __cplusplus +} +#endif + +#endif /* METROTRK_PORTABLE_MSGBUF_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h new file mode 100644 index 000000000..56f8695e4 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h @@ -0,0 +1,23 @@ +#ifndef METROTRK_PORTABLE_MSGHNDLR_H +#define METROTRK_PORTABLE_MSGHNDLR_H + +#include "trk.h" + +void SetTRKConnected(BOOL); +BOOL GetTRKConnected(void); +DSError TRKDoSetOption(TRKBuffer*); +DSError TRKDoStop(TRKBuffer*); +DSError TRKDoStep(TRKBuffer*); +DSError TRKDoContinue(TRKBuffer*); +DSError TRKDoWriteRegisters(TRKBuffer*); +DSError TRKDoReadRegisters(TRKBuffer*); +DSError TRKDoWriteMemory(TRKBuffer*); +DSError TRKDoReadMemory(TRKBuffer*); +DSError TRKDoSupportMask(TRKBuffer*); +DSError TRKDoVersions(TRKBuffer*); +DSError TRKDoOverride(TRKBuffer*); +DSError TRKDoReset(TRKBuffer*); +DSError TRKDoDisconnect(TRKBuffer*); +DSError TRKDoConnect(TRKBuffer*); + +#endif /* METROTRK_PORTABLE_MSGHNDLR_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mutex_TRK.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mutex_TRK.h new file mode 100644 index 000000000..9139673dc --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mutex_TRK.h @@ -0,0 +1,10 @@ +#ifndef METROTRK_PORTABLE_MUTEX_TRK_H +#define METROTRK_PORTABLE_MUTEX_TRK_H + +#include "dolphin/types.h" + +u8 TRKReleaseMutex(); +u8 TRKAcquireMutex(); +u8 TRKInitializeMutex(); + +#endif /* METROTRK_PORTABLE_MUTEX_TRK_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/notify.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/notify.h new file mode 100644 index 000000000..aeb9480ed --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/notify.h @@ -0,0 +1,5 @@ +#ifndef METROTRK_PORTABLE_NOTIFY_H +#define METROTRK_PORTABLE_NOTIFY_H + + +#endif /* METROTRK_PORTABLE_NOTIFY_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h new file mode 100644 index 000000000..7fa53a07b --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h @@ -0,0 +1,37 @@ +#ifndef METROTRK_PORTABLE_NUBEVENT_H +#define METROTRK_PORTABLE_NUBEVENT_H + +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef u32 NubEventID; + +typedef struct TRKEvent { + NubEventType eventType; + NubEventID eventID; + MessageBufferID msgBufID; +} TRKEvent; + +typedef struct TRKEventQueue { + int _00; + int count; + int next; + TRKEvent events[2]; + NubEventID eventID; +} TRKEventQueue; +extern TRKEventQueue gTRKEventQueue; + +BOOL TRKGetNextEvent(TRKEvent* event); +void TRKDestructEvent(TRKEvent*); +void TRKConstructEvent(TRKEvent*, NubEventType); +DSError TRKPostEvent(TRKEvent*); +DSError TRKInitializeEventQueue(); + +#ifdef __cplusplus +} +#endif + +#endif /* METROTRK_PORTABLE_NUBEVENT_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubinit.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubinit.h new file mode 100644 index 000000000..729756b52 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubinit.h @@ -0,0 +1,21 @@ +#ifndef METROTRK_PORTABLE_NUBINIT_H +#define METROTRK_PORTABLE_NUBINIT_H + +#include "trk.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void TRKNubWelcome(void); +void TRKNubMainLoop(void); +DSError TRKTerminateNub(void); +DSError TRKInitializeNub(void); + +extern BOOL gTRKBigEndian; + +#ifdef __cplusplus +} +#endif + +#endif /* METROTRK_PORTABLE_NUBINIT_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h new file mode 100644 index 000000000..180cfb83f --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h @@ -0,0 +1,17 @@ +#ifndef METROTRK_PORTABLE_SERPOLL_H +#define METROTRK_PORTABLE_SERPOLL_H + + +#ifdef __cplusplus +extern "C" { +#endif + +void TRKGetInput(void); + +extern void* gTRKInputPendingPtr; + +#ifdef __cplusplus +} +#endif + +#endif /* METROTRK_PORTABLE_SERPOLL_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/string_TRK.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/string_TRK.h new file mode 100644 index 000000000..63714ad7d --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/string_TRK.h @@ -0,0 +1,6 @@ +#ifndef METROTRK_PORTABLE_STRING_TRK_H +#define METROTRK_PORTABLE_STRING_TRK_H + +int TRK_strlen(const char* str); + +#endif /* METROTRK_PORTABLE_STRING_TRK_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/support.h b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/support.h new file mode 100644 index 000000000..dca001381 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/MetroTRK/Portable/support.h @@ -0,0 +1,18 @@ +#ifndef METROTRK_PORTABLE_SUPPORT_H +#define METROTRK_PORTABLE_SUPPORT_H + +#include "trk.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct TRKBuffer TRKBuffer; + +DSError TRKRequestSend(TRKBuffer* msgBuf, int* bufferId, u32 p1, u32 p2, int p3); + +#ifdef __cplusplus +} +#endif + +#endif /* METROTRK_PORTABLE_SUPPORT_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/Os/dolphin/DDH_Stubs.h b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/DDH_Stubs.h new file mode 100644 index 000000000..a346ccb2b --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/DDH_Stubs.h @@ -0,0 +1,25 @@ +#ifndef OS_DOLPHIN_DDH_STUBS_H +#define OS_DOLPHIN_DDH_STUBS_H + +#include "dolphin/exi/EXIBios.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int ddh_cc_initialize(void* inputPendingPtrRef, EXICallback monitorCallback); +int ddh_cc_shutdown(); +int ddh_cc_open(); +int ddh_cc_close(); +int ddh_cc_read(u8* data, int size); +int ddh_cc_write(const u8* bytes, int length); +int ddh_cc_pre_continue(); +int ddh_cc_post_stop(); +int ddh_cc_peek(); +int ddh_cc_initinterrupts(); + +#ifdef __cplusplus +} +#endif + +#endif /* OS_DOLPHIN_DDH_STUBS_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/Os/dolphin/GDEV_Stubs.h b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/GDEV_Stubs.h new file mode 100644 index 000000000..f768efdf2 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/GDEV_Stubs.h @@ -0,0 +1,25 @@ +#ifndef OS_DOLPHIN_GDEV_STUBS_H +#define OS_DOLPHIN_GDEV_STUBS_H + +#include "dolphin/exi/EXIBios.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int gdev_cc_initialize(void* inputPendingPtrRef, EXICallback monitorCallback); +int gdev_cc_shutdown(); +int gdev_cc_open(); +int gdev_cc_close(); +int gdev_cc_read(u8* data, int size); +int gdev_cc_write(const u8* bytes, int length); +int gdev_cc_pre_continue(); +int gdev_cc_post_stop(); +int gdev_cc_peek(); +int gdev_cc_initinterrupts(); + +#ifdef __cplusplus +} +#endif + +#endif /* OS_DOLPHIN_GDEV_STUBS_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/Os/dolphin/UDP_Stubs.h b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/UDP_Stubs.h new file mode 100644 index 000000000..89e2689aa --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/UDP_Stubs.h @@ -0,0 +1,24 @@ +#ifndef OS_DOLPHIN_UDP_STUBS_H +#define OS_DOLPHIN_UDP_STUBS_H + +#include "dolphin/os/OS.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int udp_cc_initialize(void* flagOut, __OSInterruptHandler handler); +int udp_cc_shutdown(void); +int udp_cc_open(void); +int udp_cc_close(void); +int udp_cc_read(u8* dest, int size); +int udp_cc_write(const u8* src, int size); +int udp_cc_peek(void); +int udp_cc_pre_continue(void); +int udp_cc_post_stop(void); + +#ifdef __cplusplus +} +#endif + +#endif /* OS_DOLPHIN_UDP_STUBS_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.h b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.h new file mode 100644 index 000000000..1a65cedc9 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.h @@ -0,0 +1,6 @@ +#ifndef OS_DOLPHIN_DOLPHIN_TRK_H +#define OS_DOLPHIN_DOLPHIN_TRK_H + +void EnableMetroTRKInterrupts(); + +#endif /* OS_DOLPHIN_DOLPHIN_TRK_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h new file mode 100644 index 000000000..a33ffde4f --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h @@ -0,0 +1,40 @@ +#ifndef OS_DOLPHIN_DOLPHIN_TRK_GLUE_H +#define OS_DOLPHIN_DOLPHIN_TRK_GLUE_H + +#include "trk.h" +#include "dolphin/os/OS.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*DBCommFunc)(); +typedef int (*DBCommInitFunc)(void*, __OSInterruptHandler); +typedef int (*DBCommReadFunc)(u8*, int); +typedef int (*DBCommWriteFunc)(const u8*, int); + +typedef struct DBCommTable { + DBCommInitFunc initialize_func; + DBCommFunc init_interrupts_func; + DBCommFunc shutdown_func; + DBCommFunc peek_func; + DBCommReadFunc read_func; + DBCommWriteFunc write_func; + DBCommFunc open_func; + DBCommFunc close_func; + DBCommFunc pre_continue_func; + DBCommFunc post_stop_func; +} DBCommTable; + +void UnreserveEXI2Port(); +void ReserveEXI2Port(); +UARTError TRKWriteUARTN(const void*, u32); +void TRKLoadContext(OSContext* ctx, u32 r4); +int InitMetroTRKCommTable(int hwId); + +#ifdef __cplusplus +} +#endif + + +#endif /* OS_DOLPHIN_DOLPHIN_TRK_GLUE_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.h b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.h new file mode 100644 index 000000000..aa10acf87 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.h @@ -0,0 +1,16 @@ +#ifndef OS_DOLPHIN_TARGCONT_H +#define OS_DOLPHIN_TARGCONT_H + +#include "trk.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DSError TRKTargetContinue(void); + +#ifdef __cplusplus +} +#endif + +#endif /* OS_DOLPHIN_TARGCONT_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.h b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.h new file mode 100644 index 000000000..c77c54b2b --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.h @@ -0,0 +1,17 @@ +#ifndef OS_DOLPHIN_TARGET_OPTIONS_H +#define OS_DOLPHIN_TARGET_OPTIONS_H + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +u8 GetUseSerialIO(void); +void SetUseSerialIO(u8); + +#ifdef __cplusplus +} +#endif + +#endif /* OS_DOLPHIN_TARGET_OPTIONS_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/Os/dolphin/usr_put.h b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/usr_put.h new file mode 100644 index 000000000..87091d4b2 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/Os/dolphin/usr_put.h @@ -0,0 +1,6 @@ +#ifndef OS_DOLPHIN_USR_PUT_H +#define OS_DOLPHIN_USR_PUT_H + +#include "dolphin/types.h" + +#endif /* OS_DOLPHIN_USR_PUT_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.h b/include/TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.h new file mode 100644 index 000000000..bf0e9b928 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.h @@ -0,0 +1,19 @@ +#ifndef PPC_EXPORT_TARGSUPP_H +#define PPC_EXPORT_TARGSUPP_H + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +u32 TRKAccessFile(u32, u32, u32*, u8*); +u32 TRKOpenFile(u32, u32, u32*, u8*); +u32 TRKCloseFile(u32, u32); +u32 TRKPositionFile(u32, u32, u32*, u8*); + +#ifdef __cplusplus +} +#endif + +#endif /* PPC_EXPORT_TARGSUPP_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.h b/include/TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.h new file mode 100644 index 000000000..768b032d5 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.h @@ -0,0 +1,5 @@ +#ifndef PPC_GENERIC_FLUSH_CACHE_H +#define PPC_GENERIC_FLUSH_CACHE_H + + +#endif /* PPC_GENERIC_FLUSH_CACHE_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.h b/include/TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.h new file mode 100644 index 000000000..4753780b9 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.h @@ -0,0 +1,5 @@ +#ifndef PPC_GENERIC_MPC_7XX_603E_H +#define PPC_GENERIC_MPC_7XX_603E_H + + +#endif /* PPC_GENERIC_MPC_7XX_603E_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h b/include/TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h new file mode 100644 index 000000000..51571963d --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h @@ -0,0 +1,143 @@ +#ifndef PPC_GENERIC_TARGIMPL_H +#define PPC_GENERIC_TARGIMPL_H + +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void TRKSwapAndGo(); +void TRKTargetSetStopped(unsigned int); +DSError TRKTargetInterrupt(TRKEvent*); +DSError TRKTargetSupportRequest(); +void TRKDestructEvent(TRKEvent*); +BOOL TRKTargetStopped(void); + +typedef struct Default_PPC { + u32 GPR[32]; + u32 PC; + u32 LR; + u32 CR; + u32 CTR; + u32 XER; +} Default_PPC; + +typedef struct Float_PPC { + u64 FPR[32]; + u64 FPSCR; + u64 FPECR; +} Float_PPC; + +typedef struct Extended1_PPC_6xx_7xx { + u32 SR[16]; + u32 TBL; + u32 TBU; + u32 HID0; + u32 HID1; + u32 MSR; + u32 PVR; + u32 IBAT0U; + u32 IBAT0L; + u32 IBAT1U; + u32 IBAT1L; + u32 IBAT2U; + u32 IBAT2L; + u32 IBAT3U; + u32 IBAT3L; + u32 DBAT0U; + u32 DBAT0L; + u32 DBAT1U; + u32 DBAT1L; + u32 DBAT2U; + u32 DBAT2L; + u32 DBAT3U; + u32 DBAT3L; + u32 DMISS; + u32 DCMP; + u32 HASH1; + u32 HASH2; + u32 IMISS; + u32 ICMP; + u32 RPA; + u32 SDR1; + u32 DAR; + u32 DSISR; + u32 SPRG0; + u32 SPRG1; + u32 SPRG2; + u32 SPRG3; + u32 DEC; + u32 IABR; + u32 EAR; + u32 DABR; + u32 PMC1; + u32 PMC2; + u32 PMC3; + u32 PMC4; + u32 SIA; + u32 MMCR0; + u32 MMCR1; + u32 THRM1; + u32 THRM2; + u32 THRM3; + u32 ICTC; + u32 L2CR; + u32 UMMCR2; + u32 UBAMR; + u32 UMMCR0; + u32 UPMC1; + u32 UPMC2; + u32 USIA; + u32 UMMCR1; + u32 UPMC3; + u32 UPMC4; + u32 USDA; + u32 MMCR2; + u32 BAMR; + u32 SDA; + u32 MSSCR0; + u32 MSSCR1; + u32 PIR; + u32 exceptionID; + u32 GQR[8]; + u32 HID_G; + u32 WPAR; + u32 DMA_U; + u32 DMA_L; +} Extended1_PPC_6xx_7xx; + +typedef struct Extended2_PPC_6xx_7xx { + u32 PSR[32][2]; +} Extended2_PPC_6xx_7xx; + +typedef struct ProcessorState_PPC_6xx_7xx { + Default_PPC Default; + Float_PPC Float; + Extended1_PPC_6xx_7xx Extended1; + Extended2_PPC_6xx_7xx Extended2; + u32 transport_handler_saved_ra; +} ProcessorState_PPC_6xx_7xx; + +typedef ProcessorState_PPC_6xx_7xx ProcessorState_PPC; +extern ProcessorState_PPC gTRKCPUState; + +typedef struct TRKState { + u32 gpr[32]; // _00 + u32 lr; // _80 + u32 ctr; // _84 + u32 xer; // _88 + u32 msr; // _8C + u32 dar; // _90 + u32 dsisr; // _94 + BOOL isStopped; // _98 + BOOL inputActivated; // _9C + void* inputPendingPtr; // _A0 +} TRKState; +extern TRKState gTRKState; + +#ifdef __cplusplus +} +#endif + +#endif /* PPC_GENERIC_TARGIMPL_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/utils/common/CircleBuffer.h b/include/TRK_MINNOW_DOLPHIN/utils/common/CircleBuffer.h new file mode 100644 index 000000000..4bea02109 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/utils/common/CircleBuffer.h @@ -0,0 +1,29 @@ +#ifndef UTILS_COMMON_CIRCLEBUFFER_H +#define UTILS_COMMON_CIRCLEBUFFER_H + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CircleBuffer { + u8* read_ptr; + u8* write_ptr; + u8* start_ptr; + u32 size; + s32 mBytesToRead; + u32 mBytesToWrite; + u32 mCriticalSection; +} CircleBuffer; + +int CircleBufferReadBytes(CircleBuffer*, u8*, u32); +int CircleBufferWriteBytes(CircleBuffer*, u8*, u32); +void CircleBufferInitialize(CircleBuffer*, u8*, s32); +u32 CBGetBytesAvailableForRead(CircleBuffer*); + +#ifdef __cplusplus +} +#endif + +#endif /* UTILS_COMMON_CIRCLEBUFFER_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h b/include/TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h new file mode 100644 index 000000000..35f9bb2fd --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h @@ -0,0 +1,8 @@ +#ifndef UTILS_COMMON_MWTRACE_H +#define UTILS_COMMON_MWTRACE_H + +#include "dolphin/types.h" + +void MWTRACE(u8, char*, ...); + +#endif /* UTILS_COMMON_MWTRACE_H */ diff --git a/include/TRK_MINNOW_DOLPHIN/utils/gc/MWCriticalSection_gc.h b/include/TRK_MINNOW_DOLPHIN/utils/gc/MWCriticalSection_gc.h new file mode 100644 index 000000000..f5fcf67f0 --- /dev/null +++ b/include/TRK_MINNOW_DOLPHIN/utils/gc/MWCriticalSection_gc.h @@ -0,0 +1,18 @@ +#ifndef UTILS_GC_MWCRITICALSECTION_GC_H +#define UTILS_GC_MWCRITICALSECTION_GC_H + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void MWExitCriticalSection(unsigned int* section); +void MWEnterCriticalSection(unsigned int* section); +void MWInitializeCriticalSection(unsigned int*); + +#ifdef __cplusplus +} +#endif + +#endif /* UTILS_GC_MWCRITICALSECTION_GC_H */ diff --git a/include/dolphin/card.h b/include/dolphin/card.h index 80493236d..403186cb4 100644 --- a/include/dolphin/card.h +++ b/include/dolphin/card.h @@ -1,12 +1,19 @@ #ifndef CARD_H #define CARD_H -#include "dolphin/types.h" +#include "dolphin/dsp.h" +#include "dolphin/os/OS.h" #ifdef __cplusplus extern "C" { #endif +#define CARD_FILENAME_MAX 32 +#define CARD_MAX_FILE 127 +#define CARD_ICON_MAX 8 + +typedef void (*CARDCallback)(s32 chan, s32 result); + typedef struct CARDFileInfo { /* 0x00 */ s32 chan; /* 0x04 */ s32 fileNo; @@ -17,35 +24,139 @@ typedef struct CARDFileInfo { } CARDFileInfo; typedef struct CARDStat { - u8 fileName[32]; - u32 dataLength; - u32 lastModified; - u8 gameCode[4]; - u8 company[2]; - - u8 bannerFmt; - u32 iconAddr; - u16 iconFormat; - u16 iconSpeed; - u32 commentAddr; - - u32 offsetBanner; - u32 offsetBannerTlut; - u32 offsetIcon[8]; - u32 offsetIconTlut; - u32 offsetData; + /* 0x00 */ char fileName[CARD_FILENAME_MAX]; + /* 0x20 */ u32 length; + /* 0x24 */ u32 time; + /* 0x28 */ u8 gameName[4]; + /* 0x2C */ u8 company[2]; + /* 0x2E */ u8 bannerFormat; + /* 0x30 */ u32 iconAddr; + /* 0x34 */ u16 iconFormat; + /* 0x36 */ u16 iconSpeed; + /* 0x38 */ u32 commentAddr; + /* 0x3C */ u32 offsetBanner; + /* 0x40 */ u32 offsetBannerTlut; + /* 0x44 */ u32 offsetIcon[CARD_ICON_MAX]; + /* 0x64 */ u32 offsetIconTlut; + /* 0x68 */ u32 offsetData; } CARDStat; -#define CARDGetBannerFormat(stat) ((stat)->bannerFmt & 0x03) -#define CARDGetIconAnim(stat) ((stat)->bannerFmt & 0x04) +typedef struct CARDDir { + u8 gameName[4]; + u8 company[2]; + u8 _padding0; + u8 bannerFormat; + u8 fileName[CARD_FILENAME_MAX]; + u32 time; // seconds since 01/01/2000 midnight + u32 iconAddr; // 0xffffffff if not used + u16 iconFormat; + u16 iconSpeed; + u8 permission; + u8 copyTimes; + u16 startBlock; + u16 length; + u8 _padding1[2]; + u32 commentAddr; // 0xffffffff if not used +} CARDDir; + +typedef struct CARDID { + /* 0x000 */ u8 serial[32]; + /* 0x020 */ u16 deviceID; + /* 0x022 */ u16 size; + /* 0x024 */ u16 encode; + /* 0x026 */ u8 padding[470]; + /* 0x1FC */ u16 checkSum; + /* 0x1FE */ u16 checkSumInv; +} CARDID; + +typedef struct CARDDecParam { + /* 0x00 */ u8* inputAddr; + /* 0x04 */ u32 inputLength; + /* 0x08 */ u32 aramAddr; + /* 0x0C */ u8* outputAddr; +} CARDDecParam; + +typedef struct CARDControl { + /* 0x000 */ BOOL attached; + /* 0x004 */ s32 result; + /* 0x008 */ u16 size; + /* 0x00A */ u16 pageSize; + /* 0x00C */ s32 sectorSize; + /* 0x010 */ u16 cBlock; + /* 0x012 */ u16 vendorID; + /* 0x014 */ s32 latency; + /* 0x018 */ u8 id[12]; + /* 0x024 */ int mountStep; + /* 0x028 */ int formatStep; + /* 0x028 */ u32 scramble; + /* 0x02C */ DSPTaskInfo task; + /* 0x080 */ void* workArea; + /* 0x084 */ CARDDir* currentDir; + /* 0x088 */ u16* currentFat; + /* 0x08C */ OSThreadQueue threadQueue; + /* 0x094 */ u8 cmd[9]; + /* 0x0A0 */ s32 cmdlen; + /* 0x0A4 */ volatile u32 mode; + /* 0x0A8 */ int retry; + /* 0x0AC */ int repeat; + /* 0x0B0 */ u32 addr; + /* 0x0B4 */ void* buffer; + /* 0x0B8 */ s32 xferred; + /* 0x0BC */ u16 freeNo; + /* 0x0BE */ u16 startBlock; + /* 0x0C0 */ CARDFileInfo* fileInfo; + /* 0x0C4 */ CARDCallback extCallback; + /* 0x0C8 */ CARDCallback txCallback; + /* 0x0CC */ CARDCallback exiCallback; + /* 0x0D0 */ CARDCallback apiCallback; + /* 0x0D4 */ CARDCallback xferCallback; + /* 0x0D8 */ CARDCallback eraseCallback; + /* 0x0DC */ CARDCallback unlockCallback; + /* 0x0E0 */ OSAlarm alarm; + /* 0x108 */ u32 cid; + /* 0x10C */ const DVDDiskID* diskID; +} CARDControl; + +typedef struct CARDDirCheck { + /* 0x00 */ u8 padding0[56]; + /* 0x38 */ u16 padding1; + /* 0x3A */ s16 checkCode; + /* 0x3C */ u16 checkSum; + /* 0x3E */ u16 checkSumInv; +} CARDDirCheck; + +#define CARDGetBannerFormat(stat) ((stat)->bannerFormat & 0x03) +#define CARDGetIconAnim(stat) ((stat)->bannerFormat & 0x04) #define CARDGetIconFormat(stat, n) ((stat)->iconFormat >> (2 * (n)) & 0x03) #define CARDGetIconSpeed(stat, n) ((stat)->iconSpeed >> (2 * (n)) & 0x03) -#define CARDSetBannerFormat(stat, v) ((stat)->bannerFmt = (u8)(((stat)->bannerFmt & ~0x03) | (v))) -#define CARDSetIconAnim(stat, v) ((stat)->bannerFmt = (u8)(((stat)->bannerFmt & ~0x04) | (v))) +#define CARDSetBannerFormat(stat, v) ((stat)->bannerFormat = (u8)(((stat)->bannerFormat & ~0x03) | (v))) +#define CARDSetIconAnim(stat, v) ((stat)->bannerFormat = (u8)(((stat)->bannerFormat & ~0x04) | (v))) #define CARDSetIconFormat(stat, n, v) ((stat)->iconFormat = (u16)(((stat)->iconFormat & ~(0x03 << (2 * (n)))) | ((v) << (2 * (n))))) #define CARDSetIconSpeed(stat, n, v) ((stat)->iconSpeed = (u16)(((stat)->iconSpeed & ~(0x03 << (2 * (n)))) | ((v) << (2 * (n))))) +#define CARD_ENCODE_ANSI 0 +#define CARD_ENCODE_SJIS 1 + +#define CARD_READ_SIZE 512 +#define CARD_COMMENT_SIZE 64 + +#define CARD_ICON_WIDTH 32 +#define CARD_ICON_HEIGHT 32 + +#define CARD_BANNER_WIDTH 96 +#define CARD_BANNER_HEIGHT 32 + +#define CARD_STAT_ICON_NONE 0 +#define CARD_STAT_ICON_C8 1 +#define CARD_STAT_ICON_RGB5A3 2 +#define CARD_STAT_ICON_MASK 3 + +#define CARD_STAT_BANNER_NONE 0 +#define CARD_STAT_BANNER_C8 1 +#define CARD_STAT_BANNER_RGB5A3 2 +#define CARD_STAT_BANNER_MASK 3 + enum { CARD_ERROR_UNLOCKED = 1, CARD_ERROR_READY = 0, @@ -66,23 +177,81 @@ enum { CARD_ERROR_FATAL_ERROR = -128, }; +#define CARD_ATTR_PUBLIC 0x04u +#define CARD_ATTR_NO_COPY 0x08u +#define CARD_ATTR_NO_MOVE 0x10u +#define CARD_ATTR_GLOBAL 0x20u +#define CARD_ATTR_COMPANY 0x40u + +#define CARD_FAT_AVAIL 0x0000u +#define CARD_FAT_CHECKSUM 0x0000u +#define CARD_FAT_CHECKSUMINV 0x0001u +#define CARD_FAT_CHECKCODE 0x0002u +#define CARD_FAT_FREEBLOCKS 0x0003u +#define CARD_FAT_LASTSLOT 0x0004u + +#define CARD_WORKAREA_SIZE (5 * 8 * 1024) + +#define CARD_SEG_SIZE 0x200u +#define CARD_PAGE_SIZE 0x80u +#define CARD_MAX_SIZE 0x01000000U + +#define CARD_NUM_SYSTEM_BLOCK 5 +#define CARD_SYSTEM_BLOCK_SIZE (8 * 1024u) + +#define CARD_MAX_MOUNT_STEP (CARD_NUM_SYSTEM_BLOCK + 2) + +#define CARD_STAT_SPEED_END 0 +#define CARD_STAT_SPEED_FAST 1 +#define CARD_STAT_SPEED_MIDDLE 2 +#define CARD_STAT_SPEED_SLOW 3 +#define CARD_STAT_SPEED_MASK 3 + +#define CARD_STAT_ANIM_LOOP 0 +#define CARD_STAT_ANIM_BOUNCE 4 +#define CARD_STAT_ANIM_MASK 0x4 + +#define CARD_RESULT_UNLOCKED 1 +#define CARD_RESULT_READY 0 +#define CARD_RESULT_BUSY -1 +#define CARD_RESULT_WRONGDEVICE -2 +#define CARD_RESULT_NOCARD -3 +#define CARD_RESULT_NOFILE -4 +#define CARD_RESULT_IOERROR -5 +#define CARD_RESULT_BROKEN -6 +#define CARD_RESULT_EXIST -7 +#define CARD_RESULT_NOENT -8 +#define CARD_RESULT_INSSPACE -9 +#define CARD_RESULT_NOPERM -10 +#define CARD_RESULT_LIMIT -11 +#define CARD_RESULT_NAMETOOLONG -12 +#define CARD_RESULT_ENCODING -13 +#define CARD_RESULT_CANCELED -14 +#define CARD_RESULT_FATAL_ERROR -128 + +#define CARDIsValidBlockNo(card, blockNo) ((blockNo) >= CARD_NUM_SYSTEM_BLOCK && (blockNo) < (card)->cBlock) +#define CARDGetDirCheck(dir) ((CARDDirCheck*)&(dir)[CARD_MAX_FILE]) + void CARDInit(); BOOL CARDProbe(s32); s32 CARDGetStatus(s32, s32, CARDStat*); s32 CARDSetStatus(s32, s32, CARDStat*); s32 CARDOpen(s32, const char*, CARDFileInfo*); s32 CARDClose(CARDFileInfo*); -s32 CARDCreate(s32, const char*, s32, CARDFileInfo*); +s32 CARDCreate(s32, const char*, u32, CARDFileInfo*); s32 CARDFormat(s32); s32 CARDProbeEx(s32, s32*, s32*); s32 CARDUnmount(s32); -s32 CARDMount(s32, void*, void*); +s32 CARDMount(s32 chan, void* workArea, CARDCallback detachCallback); s32 CARDCheck(s32); s32 CARDFreeBlocks(s32, s32*, s32*); s32 CARDRead(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset); -s32 CARDWrite(CARDFileInfo* fileInfo, const void* buf, s32 length, s32 offset); +s32 CARDWrite(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset); s32 CARDGetSerialNo(s32, u64*); +extern CARDControl __CARDBlock[2]; +extern DVDDiskID __CARDDiskNone; + #ifdef __cplusplus } #endif diff --git a/include/dolphin/gd/GDBase.h b/include/dolphin/gd/GDBase.h index eeccefe3f..313a2dc48 100644 --- a/include/dolphin/gd/GDBase.h +++ b/include/dolphin/gd/GDBase.h @@ -8,18 +8,26 @@ extern "C" { #endif +#define GX_LOAD_CP_REG 0x08 +#define GX_LOAD_XF_REG 0x10 +#define GX_LOAD_INDX_A 0x20 +#define GX_LOAD_INDX_B 0x28 +#define GX_LOAD_INDX_C 0x30 +#define GX_LOAD_INDX_D 0x38 +#define GX_LOAD_BP_REG 0x61 + typedef struct _GDLObj { /* 0x0 */ u8* start; /* 0x4 */ u32 length; /* 0x8 */ u8* ptr; - /* 0xC */ u8* end; + /* 0xC */ u8* top; } GDLObj; // Size: 0x10 extern GDLObj* __GDCurrentDL; typedef void (*GDOverflowCallback)(void); -void GDInitGDLObj(GDLObj*, u8*, u32); +void GDInitGDLObj(GDLObj*, void*, u32); void GDFlushCurrToMem(void); void GDPadCurr32(void); void GDOverflowed(void); @@ -59,7 +67,7 @@ inline GDLObj* GDGetCurrent() { } */ inline void GDOverflowCheck(u32 len) { - if (__GDCurrentDL->ptr + len > __GDCurrentDL->end) { + if (__GDCurrentDL->ptr + len > __GDCurrentDL->top) { GDOverflowed(); } } @@ -83,6 +91,54 @@ inline void GDWrite_u8(u8 v) { __GDWrite(v); } +inline static void GDWriteXFCmdHdr(u16 addr, u8 len) { + GDWrite_u8(GX_LOAD_XF_REG); + GDWrite_u16(len - 1); + GDWrite_u16(addr); +} + +inline static void GDWriteXFCmd(u16 addr, u32 val) { + GDWrite_u8(GX_LOAD_XF_REG); + GDWrite_u16(0); + GDWrite_u16(addr); + GDWrite_u32(val); +} + +inline static void GDWriteXFIndxDCmd(u16 addr, u8 len, u16 index) { + GDWrite_u8(GX_LOAD_INDX_D); + GDWrite_u16(index); + GDWrite_u16((len - 1) << 12 | addr); +} + +inline static void GDWriteXFIndxACmd(u16 addr, u8 len, u16 index) { + GDWrite_u8(GX_LOAD_INDX_A); + GDWrite_u16(index); + GDWrite_u16(((len - 1) << 12) | addr); +} + +inline static void GDWriteXFIndxBCmd(u16 addr, u8 len, u16 index) { + GDWrite_u8(GX_LOAD_INDX_B); + GDWrite_u16(index); + GDWrite_u16(((len - 1) << 12) | addr); +} + +inline static void GDWriteXFIndxCCmd(u16 addr, u8 len, u16 index) { + GDWrite_u8(GX_LOAD_INDX_C); + GDWrite_u16(index); + GDWrite_u16(((len - 1) << 12) | addr); +} + +inline static void GDWriteCPCmd(u8 addr, u32 val) { + GDWrite_u8(GX_LOAD_CP_REG); + GDWrite_u8(addr); + GDWrite_u32(val); +} + +inline static void GDWriteBPCmd(u32 regval) { + GDWrite_u8(GX_LOAD_BP_REG); + GDWrite_u32(regval); +} + #ifdef __cplusplus }; #endif diff --git a/include/dolphin/gd/GDGeometry.h b/include/dolphin/gd/GDGeometry.h index 4df5072e2..f1ad8a634 100644 --- a/include/dolphin/gd/GDGeometry.h +++ b/include/dolphin/gd/GDGeometry.h @@ -7,10 +7,508 @@ extern "C" { #endif +// Command processor register IDs +#define CP_REG_MTXIDXA_ID 0x30 // Matrix index A +#define CP_REG_MTXIDXB_ID 0x40 // Matrix index B +#define CP_REG_VCD_LO_ID 0x50 // Vertex descriptor (lo) +#define CP_REG_VCD_HI_ID 0x60 // Vertex descriptor (hi) +#define CP_REG_VAT_GRP0_ID 0x70 // Vertex attribute table (group 0) +#define CP_REG_VAT_GRP1_ID 0x80 // Vertex attribute table (group 1) +#define CP_REG_VAT_GRP2_ID 0x90 // Vertex attribute table (group 2) +#define CP_REG_ARRAYBASE_ID 0xA0 // Vertex array start/base +#define CP_REG_ARRAYSTRIDE_ID 0xB0 // Vertex array stride + +// XF locators for textures +// Projection type [30-30] +#define GX_XF_TEX_PROJTYPE_ST 30 +#define GX_XF_TEX_PROJTYPE_END 30 + +// Input format [29-29] +#define GX_XF_TEX_INPUTFORM_ST 29 +#define GX_XF_TEX_INPUTFORM_END 29 + +// Texture gen type [25-27] +#define GX_XF_TEX_TEXGENTYPE_ST 25 +#define GX_XF_TEX_TEXGENTYPE_END 27 + +// Source row [20-24] +#define GX_XF_TEX_SRCROW_ST 20 +#define GX_XF_TEX_SRCROW_END 24 + +// Bump source texture [17-19] +#define GX_XF_TEX_BUMPSRCTEX_ST 17 +#define GX_XF_TEX_BUMPSRCTEX_END 19 + +// Bump source light [14-16] +#define GX_XF_TEX_BUMPSRCLIGHT_ST 14 +#define GX_XF_TEX_BUMPSRCLIGHT_END 16 + +// Blitting processor registers. +#define GX_BP_REG_GENMODE 0x0 // gen mode + +// display copy filters +#define GX_BP_REG_DISPCOPYFILTER0 0x1 // display copy filter 0 +#define GX_BP_REG_DISPCOPYFILTER1 0x2 // display copy filter 1 +#define GX_BP_REG_DISPCOPYFILTER2 0x3 // display copy filter 2 +#define GX_BP_REG_DISPCOPYFILTER3 0x4 // display copy filter 3 + +// indirect matrices +#define GX_BP_REG_INDMTX0A 0x6 // indirect matrix 0A +#define GX_BP_REG_INDMTX0B 0x7 // indirect matrix 0B +#define GX_BP_REG_INDMTX0C 0x8 // indirect matrix 0C +#define GX_BP_REG_INDMTX1A 0x9 // indirect matrix 1A +#define GX_BP_REG_INDMTX1B 0xA // indirect matrix 1B +#define GX_BP_REG_INDMTX1C 0xB // indirect matrix 1C +#define GX_BP_REG_INDMTX2A 0xC // indirect matrix 2A +#define GX_BP_REG_INDMTX2B 0xD // indirect matrix 2B +#define GX_BP_REG_INDMTX2C 0xE // indirect matrix 2C +#define GX_BP_REG_INDIMASK 0xF // indirect mask + +// indirect TEV stages +#define GX_BP_REG_INDTEVSTAGE0 0x10 // indirect TEV stage 0 +#define GX_BP_REG_INDTEVSTAGE1 0x11 // indirect TEV stage 1 +#define GX_BP_REG_INDTEVSTAGE2 0x12 // indirect TEV stage 2 +#define GX_BP_REG_INDTEVSTAGE3 0x13 // indirect TEV stage 3 +#define GX_BP_REG_INDTEVSTAGE4 0x14 // indirect TEV stage 4 +#define GX_BP_REG_INDTEVSTAGE5 0x15 // indirect TEV stage 5 +#define GX_BP_REG_INDTEVSTAGE6 0x16 // indirect TEV stage 6 +#define GX_BP_REG_INDTEVSTAGE7 0x17 // indirect TEV stage 7 +#define GX_BP_REG_INDTEVSTAGE8 0x18 // indirect TEV stage 8 +#define GX_BP_REG_INDTEVSTAGE9 0x19 // indirect TEV stage 9 +#define GX_BP_REG_INDTEVSTAGE10 0x1A // indirect TEV stage 10 +#define GX_BP_REG_INDTEVSTAGE11 0x1B // indirect TEV stage 11 +#define GX_BP_REG_INDTEVSTAGE12 0x1C // indirect TEV stage 12 +#define GX_BP_REG_INDTEVSTAGE13 0x1D // indirect TEV stage 13 +#define GX_BP_REG_INDTEVSTAGE14 0x1E // indirect TEV stage 14 +#define GX_BP_REG_INDTEVSTAGE15 0x1F // indirect TEV stage 15 + +// performance manips +#define GX_BP_REG_SCISSORTL 0x20 // scissor top left +#define GX_BP_REG_SCISSORBR 0x21 // scissor bottom right +#define GX_BP_REG_LINEPTWIDTH 0x22 // line point width +#define GX_BP_REG_PERF0TRI 0x23 // performance 0 (triangle) +#define GX_BP_REG_PERF0QUAD 0x24 // performance 0 (quad) + +// rasters +#define GX_BP_REG_RAS1_SS0 0x25 +#define GX_BP_REG_RAS1_SS1 0x26 +#define GX_BP_REG_RAS1_IREF 0x27 +#define GX_BP_REG_RAS1_TREF0 0x28 +#define GX_BP_REG_RAS1_TREF1 0x29 +#define GX_BP_REG_RAS1_TREF2 0x2A +#define GX_BP_REG_RAS1_TREF3 0x2B +#define GX_BP_REG_RAS1_TREF4 0x2C +#define GX_BP_REG_RAS1_TREF5 0x2D +#define GX_BP_REG_RAS1_TREF6 0x2E +#define GX_BP_REG_RAS1_TREF7 0x2F + +// setup sizes +#define GX_BP_REG_SU_SSIZE0 0x30 +#define GX_BP_REG_SU_TSIZE0 0x31 +#define GX_BP_REG_SU_SSIZE1 0x32 +#define GX_BP_REG_SU_TSIZE1 0x33 +#define GX_BP_REG_SU_SSIZE2 0x34 +#define GX_BP_REG_SU_TSIZE2 0x35 +#define GX_BP_REG_SU_SSIZE3 0x36 +#define GX_BP_REG_SU_TSIZE3 0x37 +#define GX_BP_REG_SU_SSIZE4 0x38 +#define GX_BP_REG_SU_TSIZE4 0x39 +#define GX_BP_REG_SU_SSIZE5 0x3A +#define GX_BP_REG_SU_TSIZE5 0x3B +#define GX_BP_REG_SU_SSIZE6 0x3C +#define GX_BP_REG_SU_TSIZE6 0x3D +#define GX_BP_REG_SU_SSIZE7 0x3E +#define GX_BP_REG_SU_TSIZE7 0x3F + +// Z and blend controls +#define GX_BP_REG_ZMODE 0x40 +#define GX_BP_REG_BLENDMODE 0x41 +#define GX_BP_REG_DSTALPHA 0x42 +#define GX_BP_REG_ZCONTROL 0x43 +#define GX_BP_REG_FIELDMASK 0x44 +#define GX_BP_REG_DRAWDONE 0x45 +#define GX_BP_REG_PETOKEN 0x47 +#define GX_BP_REG_PETOKENINT 0x48 + +// copying +#define GX_BP_REG_TEXCOPYSRCXY 0x49 +#define GX_BP_REG_TEXCOPYSRCWH 0x4A +#define GX_BP_REG_TEXCOPYDST 0x4B +#define GX_BP_REG_DISPCOPYSTRIDE 0x4D +#define GX_BP_REG_DISPCOPYSCALEY 0x4E +#define GX_BP_REG_COPYCLEARAR 0x4F +#define GX_BP_REG_COPYCLEARGB 0x50 +#define GX_BP_REG_COPYCLEARZ 0x51 +#define GX_BP_REG_COPYFILTER0 0x53 +#define GX_BP_REG_COPYFILTER1 0x54 + +// +#define GX_BP_REG_BOUNDINGBOX0 0x55 +#define GX_BP_REG_BOUNDINGBOX1 0x56 + +#define GX_BP_REG_SCISSOROFFSET 0x59 + +// texture memory +#define GX_BP_REG_TMEMPRELOADADDR 0x60 +#define GX_BP_REG_TMEMPRELOADEVEN 0x61 +#define GX_BP_REG_TMEMPRELOADODD 0x62 +#define GX_BP_REG_TMEMPRELOADMODE 0x63 +#define GX_BP_REG_TMEMTLUTSRC 0x64 +#define GX_BP_REG_TMEMTLUTDST 0x65 +#define GX_BP_REG_TMEMTEXINVALIDATE 0x66 + +// performance 1 +#define GX_BP_REG_PERF1 0x67 +#define GX_BP_REG_FIELDMODE 0x68 + +// set modes +#define GX_BP_REG_SETMODE0_TEX0 0x80 +#define GX_BP_REG_SETMODE0_TEX1 0x81 +#define GX_BP_REG_SETMODE0_TEX2 0x82 +#define GX_BP_REG_SETMODE0_TEX3 0x83 +#define GX_BP_REG_SETMODE1_TEX0 0x84 +#define GX_BP_REG_SETMODE1_TEX1 0x85 +#define GX_BP_REG_SETMODE1_TEX2 0x86 +#define GX_BP_REG_SETMODE1_TEX3 0x87 + +// set images +#define GX_BP_REG_SETIMAGE0_TEX0 0x88 +#define GX_BP_REG_SETIMAGE0_TEX1 0x89 +#define GX_BP_REG_SETIMAGE0_TEX2 0x8A +#define GX_BP_REG_SETIMAGE0_TEX3 0x8B +#define GX_BP_REG_SETIMAGE1_TEX0 0x8C +#define GX_BP_REG_SETIMAGE1_TEX1 0x8D +#define GX_BP_REG_SETIMAGE1_TEX2 0x8E +#define GX_BP_REG_SETIMAGE1_TEX3 0x8F +#define GX_BP_REG_SETIMAGE2_TEX0 0x90 +#define GX_BP_REG_SETIMAGE2_TEX1 0x91 +#define GX_BP_REG_SETIMAGE2_TEX2 0x92 +#define GX_BP_REG_SETIMAGE2_TEX3 0x93 +#define GX_BP_REG_SETIMAGE3_TEX0 0x94 +#define GX_BP_REG_SETIMAGE3_TEX1 0x95 +#define GX_BP_REG_SETIMAGE3_TEX2 0x96 +#define GX_BP_REG_SETIMAGE3_TEX3 0x97 + +// set texture lookups +#define GX_BP_REG_SETTLUT_TEX0 0x98 +#define GX_BP_REG_SETTLUT_TEX1 0x99 +#define GX_BP_REG_SETTLUT_TEX2 0x9A +#define GX_BP_REG_SETTLUT_TEX3 0x9B + +// set modes continued +#define GX_BP_REG_SETMODE0_TEX4 0xA0 +#define GX_BP_REG_SETMODE0_TEX5 0xA1 +#define GX_BP_REG_SETMODE0_TEX6 0xA2 +#define GX_BP_REG_SETMODE0_TEX7 0xA3 +#define GX_BP_REG_SETMODE1_TEX4 0xA4 +#define GX_BP_REG_SETMODE1_TEX5 0xA5 +#define GX_BP_REG_SETMODE1_TEX6 0xA6 +#define GX_BP_REG_SETMODE1_TEX7 0xA7 + +// set images continued +#define GX_BP_REG_SETIMAGE0_TEX4 0xA8 +#define GX_BP_REG_SETIMAGE0_TEX5 0xA9 +#define GX_BP_REG_SETIMAGE0_TEX6 0xAA +#define GX_BP_REG_SETIMAGE0_TEX7 0xAB +#define GX_BP_REG_SETIMAGE1_TEX4 0xAC +#define GX_BP_REG_SETIMAGE1_TEX5 0xAD +#define GX_BP_REG_SETIMAGE1_TEX6 0xAE +#define GX_BP_REG_SETIMAGE1_TEX7 0xAF +#define GX_BP_REG_SETIMAGE2_TEX4 0xB0 +#define GX_BP_REG_SETIMAGE2_TEX5 0xB1 +#define GX_BP_REG_SETIMAGE2_TEX6 0xB2 +#define GX_BP_REG_SETIMAGE2_TEX7 0xB3 +#define GX_BP_REG_SETIMAGE3_TEX4 0xB4 +#define GX_BP_REG_SETIMAGE3_TEX5 0xB5 +#define GX_BP_REG_SETIMAGE3_TEX6 0xB6 +#define GX_BP_REG_SETIMAGE3_TEX7 0xB7 + +// set texture lookups continued +#define GX_BP_REG_SETTLUT_TEX4 0xB8 +#define GX_BP_REG_SETTLUT_TEX5 0xB9 +#define GX_BP_REG_SETTLUT_TEX6 0xBA +#define GX_BP_REG_SETTLUT_TEX7 0xBB + +// TEV color manips +#define GX_BP_REG_TEVCOLORCOMBINER0 0xC0 +#define GX_BP_REG_TEVALPHACOMBINER0 0xC1 +#define GX_BP_REG_TEVCOLORCOMBINER1 0xC2 +#define GX_BP_REG_TEVALPHACOMBINER1 0xC3 +#define GX_BP_REG_TEVCOLORCOMBINER2 0xC4 +#define GX_BP_REG_TEVALPHACOMBINER2 0xC5 +#define GX_BP_REG_TEVCOLORCOMBINER3 0xC6 +#define GX_BP_REG_TEVALPHACOMBINER3 0xC7 +#define GX_BP_REG_TEVCOLORCOMBINER4 0xC8 +#define GX_BP_REG_TEVALPHACOMBINER4 0xC9 +#define GX_BP_REG_TEVCOLORCOMBINER5 0xCA +#define GX_BP_REG_TEVALPHACOMBINER5 0xCB +#define GX_BP_REG_TEVCOLORCOMBINER6 0xCC +#define GX_BP_REG_TEVALPHACOMBINER6 0xCD +#define GX_BP_REG_TEVCOLORCOMBINER7 0xCE +#define GX_BP_REG_TEVALPHACOMBINER7 0xCF +#define GX_BP_REG_TEVCOLORCOMBINER8 0xD0 +#define GX_BP_REG_TEVALPHACOMBINER8 0xD1 +#define GX_BP_REG_TEVCOLORCOMBINER9 0xD2 +#define GX_BP_REG_TEVALPHACOMBINER9 0xD3 +#define GX_BP_REG_TEVCOLORCOMBINER10 0xD4 +#define GX_BP_REG_TEVALPHACOMBINER10 0xD5 +#define GX_BP_REG_TEVCOLORCOMBINER11 0xD6 +#define GX_BP_REG_TEVALPHACOMBINER11 0xD7 +#define GX_BP_REG_TEVCOLORCOMBINER12 0xD8 +#define GX_BP_REG_TEVALPHACOMBINER12 0xD9 +#define GX_BP_REG_TEVCOLORCOMBINER13 0xDA +#define GX_BP_REG_TEVALPHACOMBINER13 0xDB +#define GX_BP_REG_TEVCOLORCOMBINER14 0xDC +#define GX_BP_REG_TEVALPHACOMBINER14 0xDD +#define GX_BP_REG_TEVCOLORCOMBINER15 0xDE +#define GX_BP_REG_TEVALPHACOMBINER15 0xDF + +// TEV registers +#define GX_BP_REG_TEVREG0LO 0xE0 +#define GX_BP_REG_TEVREG0HI 0xE1 +#define GX_BP_REG_TEVREG1LO 0xE2 +#define GX_BP_REG_TEVREG1HI 0xE3 +#define GX_BP_REG_TEVREG2LO 0xE4 +#define GX_BP_REG_TEVREG2HI 0xE5 +#define GX_BP_REG_TEVREG3LO 0xE6 +#define GX_BP_REG_TEVREG3HI 0xE7 + +// fog registers +#define GX_BP_REG_FOGRANGE 0xE8 +#define GX_BP_REG_FOGRANGEK0 0xE9 +#define GX_BP_REG_FOGRANGEK1 0xEA +#define GX_BP_REG_FOGRANGEK2 0xEB +#define GX_BP_REG_FOGRANGEK3 0xEC +#define GX_BP_REG_FOGRANGEK4 0xED +#define GX_BP_REG_FOGPARAM0 0xEE +#define GX_BP_REG_FOGPARAM1 0xEF +#define GX_BP_REG_FOGPARAM2 0xF0 +#define GX_BP_REG_FOGPARAM3 0xF1 +#define GX_BP_REG_FOGCOLOR 0xF2 + +// performance manip registers +#define GX_BP_REG_ALPHACOMPARE 0xF3 +#define GX_BP_REG_ZTEXTURE0 0xF4 +#define GX_BP_REG_ZTEXTURE1 0xF5 + +// TEV K selectors +#define GX_BP_REG_TEVKSEL0 0xF6 +#define GX_BP_REG_TEVKSEL1 0xF7 +#define GX_BP_REG_TEVKSEL2 0xF8 +#define GX_BP_REG_TEVKSEL3 0xF9 +#define GX_BP_REG_TEVKSEL4 0xFA +#define GX_BP_REG_TEVKSEL5 0xFB +#define GX_BP_REG_TEVKSEL6 0xFC +#define GX_BP_REG_TEVKSEL7 0xFD + +// SS mask +#define GX_BP_REG_SSMASK 0xFE + +// Transform Unit Registers +#define GX_XF_REG_ERROR 0x1000 +#define GX_XF_REG_DIAGNOSTICS 0x1001 +#define GX_XF_REG_STATE0 0x1002 +#define GX_XF_REG_STATE1 0x1003 +#define GX_XF_REG_CLOCK 0x1004 +#define GX_XF_REG_CLIPDISABLE 0x1005 +#define GX_XF_REG_PERF0 0x1006 +#define GX_XF_REG_PERF1 0x1007 +#define GX_XF_REG_INVERTEXSPEC 0x1008 +#define GX_XF_REG_NUMCOLORS 0x1009 +#define GX_XF_REG_AMBIENT0 0x100A +#define GX_XF_REG_AMBIENT1 0x100B +#define GX_XF_REG_MATERIAL0 0x100C +#define GX_XF_REG_MATERIAL1 0x100D +#define GX_XF_REG_COLOR0CNTRL 0x100E +#define GX_XF_REG_COLOR1CNTRL 0x100F +#define GX_XF_REG_ALPHA0CNTRL 0x1010 +#define GX_XF_REG_ALPHA1CNTRL 0x1011 +#define GX_XF_REG_DUALTEXTRAN 0x1012 +#define GX_XF_REG_MATRIXINDEX0 0x1018 +#define GX_XF_REG_MATRIXINDEX1 0x1019 +#define GX_XF_REG_SCALEX 0x101A +#define GX_XF_REG_SCALEY 0x101B +#define GX_XF_REG_SCALEZ 0x101C +#define GX_XF_REG_OFFSETX 0x101D +#define GX_XF_REG_OFFSETY 0x101E +#define GX_XF_REG_OFFSETZ 0x101F +#define GX_XF_REG_PROJECTIONA 0x1020 +#define GX_XF_REG_PROJECTIONB 0x1021 +#define GX_XF_REG_PROJECTIONC 0x1022 +#define GX_XF_REG_PROJECTIOND 0x1023 +#define GX_XF_REG_PROJECTIONE 0x1024 +#define GX_XF_REG_PROJECTIONF 0x1025 +#define GX_XF_REG_PROJECTORTHO 0x1026 +#define GX_XF_REG_NUMTEX 0x103F +#define GX_XF_REG_TEX0 0x1040 +#define GX_XF_REG_TEX1 0x1041 +#define GX_XF_REG_TEX2 0x1042 +#define GX_XF_REG_TEX3 0x1043 +#define GX_XF_REG_TEX4 0x1044 +#define GX_XF_REG_TEX5 0x1045 +#define GX_XF_REG_TEX6 0x1046 +#define GX_XF_REG_TEX7 0x1047 +#define GX_XF_REG_DUALTEX0 0x1050 +#define GX_XF_REG_DUALTEX1 0x1051 +#define GX_XF_REG_DUALTEX2 0x1052 +#define GX_XF_REG_DUALTEX3 0x1053 +#define GX_XF_REG_DUALTEX4 0x1054 +#define GX_XF_REG_DUALTEX5 0x1055 +#define GX_XF_REG_DUALTEX6 0x1056 +#define GX_XF_REG_DUALTEX7 0x1057 + +#define CP_REG_VCD_LO(pnMtxIdx, txMtxIdxMask, posn, norm, col0, col1) \ + ( \ + (pnMtxIdx) << 0 | \ + (txMtxIdxMask) << 1 | \ + (posn) << 9 | \ + (norm) << 11 | \ + (col0) << 13 | \ + (col1) << 15 \ + ) + +#define CP_REG_VCD_HI(tex0, tex1, tex2, tex3, tex4, tex5, tex6, tex7) \ + ( \ + (tex0) << 0 | \ + (tex1) << 2 | \ + (tex2) << 4 | \ + (tex3) << 6 | \ + (tex4) << 8 | \ + (tex5) << 10 | \ + (tex6) << 12 | \ + (tex7) << 14 \ + ) + +#define CP_REG_VAT_GRP0(posCnt, posType, posFrac, nrmCnt, nrmType, c0Cnt, c0Type, c1Cnt, c1Type, tx0Cnt, tx0Type, tx0Frac, p12, nrmIdx3) \ + ( \ + (posCnt) << 0 | \ + (posType) << 1 | \ + (posFrac) << 4 | \ + (nrmCnt) << 9 | \ + (nrmType) << 10 | \ + (c0Cnt) << 13 | \ + (c0Type) << 14 | \ + (c1Cnt) << 17 | \ + (c1Type) << 18 | \ + (tx0Cnt) << 21 | \ + (tx0Type) << 22 | \ + (tx0Frac) << 25 | \ + (p12) << 30 | \ + (nrmIdx3) << 31 \ + ) + +#define CP_REG_VAT_GRP1(tx1Cnt, tx1Type, tx1Frac, tx2Cnt, tx2Type, tx2Frac, tx3Cnt, tx3Type, tx3Frac, tx4Cnt, tx4Type, p11) \ + ( \ + (tx1Cnt) << 0 | \ + (tx1Type) << 1 | \ + (tx1Frac) << 4 | \ + (tx2Cnt) << 9 | \ + (tx2Type) << 10 | \ + (tx2Frac) << 13 | \ + (tx3Cnt) << 18 | \ + (tx3Type) << 19 | \ + (tx3Frac) << 22 | \ + (tx4Cnt) << 27 | \ + (tx4Type) << 28 | \ + p11 << 31 \ + ) + +#define CP_REG_VAT_GRP2(tx4Frac, tx5Cnt, tx5Type, tx5Frac, tx6Cnt, tx6Type, tx6Frac, tx7Cnt, tx7Type, tx7Frac) \ + ( \ + (tx4Frac) << 0 | \ + (tx5Cnt) << 5 | \ + (tx5Type) << 6 | \ + (tx5Frac) << 9 | \ + (tx6Cnt) << 14 | \ + (tx6Type) << 15 | \ + (tx6Frac) << 18 | \ + (tx7Cnt) << 23 | \ + (tx7Type) << 24 | \ + (tx7Frac) << 27 \ + ) + +// Transform unit register IDs +#define XF_REG_ERROR_ID 0x1000 +#define XF_REG_DIAGNOSTICS_ID 0x1001 +#define XF_REG_STATE0_ID 0x1002 +#define XF_REG_STATE1_ID 0x1003 +#define XF_REG_CLOCK_ID 0x1004 +#define XF_REG_CLIPDISABLE_ID 0x1005 +#define XF_REG_PERF0_ID 0x1006 +#define XF_REG_PERF1_ID 0x1007 +#define XF_REG_INVERTEXSPEC_ID 0x1008 +#define XF_REG_NUMCOLORS_ID 0x1009 +#define XF_REG_DUALTEXTRAN_ID 0x1012 +#define XF_REG_SCALEX_ID 0x101A +#define XF_REG_SCALEY_ID 0x101B +#define XF_REG_SCALEZ_ID 0x101C +#define XF_REG_OFFSETX_ID 0x101D +#define XF_REG_OFFSETY_ID 0x101E +#define XF_REG_OFFSETZ_ID 0x101F +#define XF_REG_NUMTEX_ID 0x103F +#define XF_REG_TEX0_ID 0x1040 +#define XF_REG_TEX1_ID 0x1041 +#define XF_REG_TEX2_ID 0x1042 +#define XF_REG_TEX3_ID 0x1043 +#define XF_REG_TEX4_ID 0x1044 +#define XF_REG_TEX5_ID 0x1045 +#define XF_REG_TEX6_ID 0x1046 +#define XF_REG_TEX7_ID 0x1047 +#define XF_REG_DUALTEX0_ID 0x1050 +#define XF_REG_DUALTEX1_ID 0x1051 +#define XF_REG_DUALTEX2_ID 0x1052 +#define XF_REG_DUALTEX3_ID 0x1053 +#define XF_REG_DUALTEX4_ID 0x1054 +#define XF_REG_DUALTEX5_ID 0x1055 +#define XF_REG_DUALTEX6_ID 0x1056 +#define XF_REG_DUALTEX7_ID 0x1057 + +#define XF_REG_INVTXSPEC(ncols, nnorms, ntexs) \ + ( \ + (ncols) << 0 | \ + (nnorms) << 2 | \ + (ntexs) << 4 \ + ) + +#define XF_REG_TEX(proj, form, tgType, row, embossRow, embossLit) \ + ( \ + (proj) << 1 | \ + (form) << 2 | \ + (tgType) << 4 | \ + (row) << 7 | \ + (embossRow) << 12 | \ + (embossLit) << 15 \ + ) + +#define XF_REG_DUALTEX(mtx, normalize) \ + ( \ + (mtx) << 0 | \ + (normalize) << 8 \ + ) + +#define BP_GEN_MODE(nTexGens, nChans, nTevs, p4, nInds) \ + ( \ + (u32)(nTexGens) << 0 | \ + (u32)(nChans) << 4 | \ + (u32)(nTevs) << 10 | \ + (u32)(p4) << 14 | \ + (u32)(nInds) << 16 \ + ) + +#define BP_LP_SIZE(lineWidth, pointSize, lineOffset, pointOffset, lineHalfAspect, p5) \ + ( \ + (u32)(lineWidth) << 0 | \ + (u32)(pointSize) << 8 | \ + (u32)(lineOffset) << 16 | \ + (u32)(pointOffset) << 19 | \ + (u32)(lineHalfAspect) << 22 | \ + (u32)(p5) << 24 \ + ) + typedef struct _GXVtxDescList GXVtxDescList; void GDSetVtxDescv(GXVtxDescList*); -void GDSetArray(GXAttr attr, const void* data, u8 stride); +void GDSetArray(GXAttr attr, void* data, u8 stride); void GDSetArrayRaw(GXAttr attr, u32 data, u8 stride); #ifdef __cplusplus diff --git a/include/dolphin/gf/GFPixel.h b/include/dolphin/gf/GFPixel.h index 95e309b3b..311a688a3 100644 --- a/include/dolphin/gf/GFPixel.h +++ b/include/dolphin/gf/GFPixel.h @@ -4,6 +4,75 @@ #include "dolphin/gx/GXEnum.h" #include "dolphin/gx/GXStruct.h" +#define BP_FOG_UNK0(a, id) \ + ( \ + (u32)(a) << 0 | \ + (u32)(id) << 24 \ + ) + +#define BP_FOG_UNK1(b_m, id) \ + ( \ + (u32)(b_m) << 0 | \ + (u32)(id) << 24 \ + ) + +#define BP_FOG_UNK2(b_expn, id) \ + ( \ + (u32)(b_expn) << 0 | \ + (u32)(id) << 24 \ + ) + +#define BP_FOG_UNK3(c, proj, fsel, id) \ + ( \ + (u32)(c) << 0 | \ + (u32)(proj) << 20 | \ + (u32)(fsel) << 21 | \ + (u32)(id) << 24 \ + ) + +#define BP_FOG_COLOR(r, g, b, id) \ + ( \ + (u32)(b) << 0 | \ + (u32)(g) << 8 | \ + (u32)(r) << 16 | \ + (u32)(id) << 24 \ + ) + +#define BP_BLEND_MODE(enable, enable_logic, enable_dither, enable_color_update, enable_alpha_update, dst_factor, src_factor, blend_sub, logic_op, id) \ + ( \ + (u32)(enable) << 0 | \ + (u32)(enable_logic) << 1 | \ + (u32)(enable_dither) << 2 | \ + (u32)(enable_color_update) << 3 | \ + (u32)(enable_alpha_update) << 4 | \ + (u32)(dst_factor) << 5 | \ + (u32)(src_factor) << 8 | \ + (u32)(blend_sub) << 11 | \ + (u32)(logic_op) << 12 | \ + (u32)(id) << 24 \ + ) + +#define BP_Z_MODE(enable_compare, compare_fn, enable_update, id) \ + ( \ + (u32)(enable_compare) << 0 | \ + (u32)(compare_fn) << 1 | \ + (u32)(enable_update) << 4 | \ + (u32)(id) << 24 \ + ) + +#define BP_DST_ALPHA(alpha, enable, id) \ + ( \ + (u32)(alpha) << 0 | \ + (u32)(enable) << 8 | \ + (u32)(id) << 24 \ + ) + +#define BP_TOKEN(token, id) \ + ( \ + (u32)(token) << 0 | \ + (u32)(id) << 24 \ + ) + void GFSetFog(GXFogType type, f32 startZ, f32 endZ, f32 nearZ, f32 farZ, GXColor color); void GFSetBlendModeEtc(GXBlendMode, GXBlendFactor, GXBlendFactor, GXLogicOp, u8, u8, u8); void GFSetDstAlpha(u8, u8); diff --git a/include/dolphin/gf/GFTev.h b/include/dolphin/gf/GFTev.h index e16ad9b81..0022792d1 100644 --- a/include/dolphin/gf/GFTev.h +++ b/include/dolphin/gf/GFTev.h @@ -4,6 +4,99 @@ #include "dolphin/gx/GXEnum.h" #include "dolphin/gx/GXStruct.h" +#define BP_TEV_COLOR(d, c, b, a, bias, op, clamp, scale, out, id) \ + ( \ + (u32)(d) << 0 | \ + (u32)(c) << 4 | \ + (u32)(b) << 8 | \ + (u32)(a) << 12 | \ + (u32)(bias) << 16 | \ + (u32)(op) << 18 | \ + (u32)(clamp) << 19 | \ + (u32)(scale) << 20 | \ + (u32)(out) << 22 | \ + (u32)(id) << 24 \ + ) + +#define BP_TEV_ALPHA(ras_sel, tex_sel, d, c, b, a, bias, op, clamp, scale, out, id) \ + ( \ + (u32)(ras_sel) << 0 | \ + (u32)(tex_sel) << 2 | \ + (u32)(d) << 4 | \ + (u32)(c) << 7 | \ + (u32)(b) << 10 | \ + (u32)(a) << 13 | \ + (u32)(bias) << 16 | \ + (u32)(op) << 18 | \ + (u32)(clamp) << 19 | \ + (u32)(scale) << 20 | \ + (u32)(out) << 22 | \ + (u32)(id) << 24 \ + ) + +#define BP_TEV_COLOR_REG_RA(r, a, reg, id) \ + ( \ + (u32)(r) << 0 | \ + (u32)(a) << 12 | \ + (u32)(reg) << 23 | \ + (u32)(id) << 24 \ + ) + +#define BP_TEV_COLOR_REG_BG(b, g, reg, id) \ + ( \ + (u32)(b) << 0 | \ + (u32)(g) << 12 | \ + (u32)(reg) << 23 | \ + (u32)(id) << 24 \ + ) + +#define BP_TEV_KSEL(rb, ga, kcsel0, kasel0, kcsel1, kasel1, id) \ + ( \ + (u32)(rb) << 0 | \ + (u32)(ga) << 2 | \ + (u32)(kcsel0) << 4 | \ + (u32)(kasel0) << 9 | \ + (u32)(kcsel1) << 14 | \ + (u32)(kasel1) << 19 | \ + (u32)(id) << 24 \ + ) + +#define BP_ALPHA_COMPARE(ref0, ref1, comp0, comp1, op, id) \ + ( \ + (u32)(ref0) << 0 | \ + (u32)(ref1) << 8 | \ + (u32)(comp0) << 16 | \ + (u32)(comp1) << 19 | \ + (u32)(op) << 22 | \ + (u32)(id) << 24 \ + ) + +#define BP_ZTEX_PARAMS_0(bias, id) \ + ( \ + (u32)(bias) << 0 | \ + (u32)(id) << 24 \ + ) + +#define BP_ZTEX_PARAMS_1(zfmt, op, id) \ + ( \ + (u32)(zfmt) << 0 | \ + (u32)(op) << 2 | \ + (u32)(id) << 24 \ + ) + +#define BP_TEV_ORDER(map0, coord0, enable0, color0, map1, coord1, enable1, color1, id) \ + ( \ + (u32)(map0) << 0 | \ + (u32)(coord0) << 3 | \ + (u32)(enable0) << 6 | \ + (u32)(color0) << 7 | \ + (u32)(map1) << 12 | \ + (u32)(coord1) << 15 | \ + (u32)(enable1) << 18 | \ + (u32)(color1) << 19 | \ + (u32)(id) << 24 \ + ) + void GFSetTevColor(GXTevRegID, GXColor); void GFSetTevColorS10(GXTevRegID, GXColorS10); void GFSetAlphaCompare(GXCompare, u8, GXAlphaOp, GXCompare, u8); diff --git a/include/dolphin/gx/GX.h b/include/dolphin/gx/GX.h index 43aa0a9a7..3371092e0 100644 --- a/include/dolphin/gx/GX.h +++ b/include/dolphin/gx/GX.h @@ -234,6 +234,9 @@ inline void GXEnd() {} #define GX_WRITE_F32(f) \ GXFIFO.f32 = (f32)(f); +#define VERIF_RAS_REG(v) +#define VERIF_XF_REG(r, v) + #define GX_WRITE_XF_REG(addr, value) \ do { \ GX_WRITE_U8(0x10); \ diff --git a/include/dolphin/gx/GXAttr.h b/include/dolphin/gx/GXAttr.h index dfc954fcf..9c4940990 100644 --- a/include/dolphin/gx/GXAttr.h +++ b/include/dolphin/gx/GXAttr.h @@ -13,10 +13,10 @@ typedef struct _GXVtxDescList { } GXVtxDescList; // Size: 0x08 typedef struct _GXVtxAttrFmtList { - /* 0x00 */ GXAttr mAttrib; - /* 0x04 */ GXCompCnt mCompCnt; - /* 0x08 */ GXCompType mCompType; - /* 0x0C */ u8 mCompShift; + GXAttr attr; + GXCompCnt cnt; + GXCompType type; + u8 frac; } GXVtxAttrFmtList; // Size: 0x10 void GXSetVtxDesc(GXAttr attr, GXAttrType type); diff --git a/include/dolphin/os/OS.h b/include/dolphin/os/OS.h index 00dfe288a..7715166bc 100644 --- a/include/dolphin/os/OS.h +++ b/include/dolphin/os/OS.h @@ -93,6 +93,7 @@ extern BOOL __OSIsGcam; extern u32 BOOT_REGION_START AT_ADDRESS(0x812FDFF0); extern u32 BOOT_REGION_END AT_ADDRESS(0x812FDFEC); +extern u8 __gUnknown800030E3 AT_ADDRESS(OS_BASE_CACHED | 0x30E3); u8* OSGetStackPointer(void); void __OSFPRInit(void); diff --git a/include/dolphin/pad/Pad.h b/include/dolphin/pad/Pad.h index 169222cc2..33a172e04 100644 --- a/include/dolphin/pad/Pad.h +++ b/include/dolphin/pad/Pad.h @@ -9,12 +9,10 @@ extern "C" { typedef struct OSContext OSContext; -typedef enum PADMask { - PAD_CHAN3_BIT = (1 << 28), - PAD_CHAN2_BIT = (1 << 29), - PAD_CHAN1_BIT = (1 << 30), - PAD_CHAN0_BIT = (1 << 31), -} PADMask; +#define PAD_CHAN0_BIT 0x80000000 +#define PAD_CHAN1_BIT 0x40000000 +#define PAD_CHAN2_BIT 0x20000000 +#define PAD_CHAN3_BIT 0x10000000 #define PAD_SPEC_0 0 #define PAD_SPEC_1 1 @@ -47,18 +45,31 @@ typedef enum PADMask { #define PAD_BUTTON_START 0x1000 typedef struct PADStatus { - /* 0x0 */ u16 button; - /* 0x2 */ s8 stick_x; - /* 0x3 */ s8 stick_y; - /* 0x4 */ s8 substick_x; - /* 0x5 */ s8 substick_y; - /* 0x6 */ u8 trigger_left; - /* 0x7 */ u8 trigger_right; - /* 0x8 */ u8 analog_a; - /* 0x9 */ u8 analog_b; - /* 0xA */ s8 error; + /* 0x00 */ u16 button; + /* 0x02 */ s8 stickX; + /* 0x03 */ s8 stickY; + /* 0x04 */ s8 substickX; + /* 0x05 */ s8 substickY; + /* 0x06 */ u8 triggerLeft; + /* 0x07 */ u8 triggerRight; + /* 0x08 */ u8 analogA; + /* 0x09 */ u8 analogB; + /* 0x0A */ s8 err; } PADStatus; +typedef struct PADClampRegion { + u8 minTrigger; + u8 maxTrigger; + s8 minStick; + s8 maxStick; + s8 xyStick; + s8 minSubstick; + s8 maxSubstick; + s8 xySubstick; + s8 radStick; + s8 radSubstick; +} PADClampRegion; + typedef void (*PADSamplingCallback)(void); BOOL PADInit(void); @@ -70,6 +81,7 @@ void PADClamp(PADStatus* status); u32 PADRead(PADStatus* status); void PADControlMotor(s32 channel, u32 command); BOOL PADRecalibrate(u32 mask); +PADSamplingCallback PADSetSamplingCallback(PADSamplingCallback callback); static void PADOriginCallback(s32 chan, u32 error, OSContext* context); static void PADOriginUpdateCallback(s32 chan, u32 error, OSContext* context); static void PADProbeCallback(s32 chan, u32 error, OSContext* context); @@ -77,6 +89,7 @@ static void PADTypeAndStatusCallback(s32 chan, u32 type); static void PADReceiveCheckCallback(s32 chan, u32 type); extern u32 __PADSpec; +extern u32 __PADFixBits; #ifdef __cplusplus }; diff --git a/include/dolphin/si/SIBios.h b/include/dolphin/si/SIBios.h index 2e8d19de4..edc4bf355 100644 --- a/include/dolphin/si/SIBios.h +++ b/include/dolphin/si/SIBios.h @@ -9,6 +9,41 @@ extern "C" { #endif +#define SI_MAX_TYPE 4 + +#define SI_COMCSR_IDX 13 +#define SI_STATUS_IDX 14 + +#define SI_COMCSR_TCINT_MASK (1 << 31) +#define SI_COMCSR_TCINTMSK_MASK (1 << 30) +#define SI_COMCSR_COMERR_MASK (1 << 29) +#define SI_COMCSR_RDSTINT_MASK (1 << 28) +#define SI_COMCSR_RDSTINTMSK_MASK (1 << 27) + +// 4 bits of padding +#define SI_COMCSR_OUTLNGTH_MASK (1 << 22) \ + | (1 << 21) \ + | (1 << 20) \ + | (1 << 19) \ + | (1 << 18) \ + | (1 << 17) \ + | (1 << 16) + +// 1 bit of padding +#define SI_COMCSR_INLNGTH_MASK (1 << 14) \ + | (1 << 13) \ + | (1 << 12) \ + | (1 << 11) \ + | (1 << 10) \ + | (1 << 9) \ + | (1 << 8) + +// 5 bits of padding +#define SI_COMCSR_CHANNEL_MASK (1 << 2) \ + | (1 << 1) + +#define SI_COMCSR_TSTART_MASK (1 << 0) + #define SI_MAX_CHAN 4 #define SI_MAX_COMCSR_INLNGTH 128 #define SI_MAX_COMCSR_OUTLNGTH 128 @@ -61,7 +96,7 @@ extern "C" { #define SI_GC_STEERING (SI_TYPE_GC | 0x00000000) typedef void (*SICallback)(s32 chan, u32 sr, OSContext* context); -typedef void (*SITypeAndStatusCallback)(s32 chan, u32 type); +typedef void (*SITypeCallback)(s32 chan, u32 type); typedef struct SIPacket { s32 chan; @@ -119,7 +154,7 @@ BOOL SIGetResponse(s32 chan, void* data); BOOL SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes, SICallback callback, OSTime delay); u32 SIGetType(s32 chan); -u32 SIGetTypeAsync(s32 chan, SITypeAndStatusCallback callback); +u32 SIGetTypeAsync(s32 chan, SITypeCallback callback); u32 SIProbe(s32 chan); vu32 __SIRegs[64] AT_ADDRESS(0xCC006400); diff --git a/include/dolphin/types.h b/include/dolphin/types.h index f548f7d3f..bac4bfc44 100644 --- a/include/dolphin/types.h +++ b/include/dolphin/types.h @@ -35,6 +35,55 @@ typedef unsigned int uint; (((u32)ptr[offset] << 24) | ((u32)ptr[offset + 1] << 16) | ((u32)ptr[offset + 2] << 8) | \ (u32)ptr[offset + 3]); +#if defined(__MWERKS__) +#define AT_ADDRESS(addr) : (addr) +#elif defined(__GNUC__) +//#define AT_ADDRESS(addr) __attribute__((address((addr)))) +#define AT_ADDRESS(addr) // was removed in GCC. define in linker script instead. +#else +#define AT_ADDRESS(addr) +#endif + +#ifndef ATTRIBUTE_ALIGN +#if defined(__MWERKS__) || defined(__GNUC__) +#define ATTRIBUTE_ALIGN(num) __attribute__((aligned(num))) +#elif defined(_MSC_VER) +#define ATTRIBUTE_ALIGN(num) +#else +#error unknown compiler +#endif +#endif + +#ifndef DECL_WEAK +#if defined(__MWERKS__) +#define DECL_WEAK __declspec(weak) +#elif defined(__GNUC__) +#define DECL_WEAK __attribute__((weak)) +#elif defined(_MSC_VER) +#define DECL_WEAK +#else +#error unknown compiler +#endif +#endif + +#ifndef NULL +#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#else +#define NULL 0 +#endif +#else +#define NULL ((void*)0) +#endif +#endif + +#ifdef __MWERKS__ +#define __REGISTER register +#else +#define __REGISTER +#endif + #include "stddef.h" // IWYU pragma: export #define INT32_MAX (0x7fffffff) diff --git a/include/odemuexi2/DebuggerDriver.h b/include/odemuexi2/DebuggerDriver.h new file mode 100644 index 000000000..f417d9fa0 --- /dev/null +++ b/include/odemuexi2/DebuggerDriver.h @@ -0,0 +1,22 @@ +#ifndef ODEMUEXI_DEBUGGERDRIVER_H +#define ODEMUEXI_DEBUGGERDRIVER_H + +#include "dolphin/types.h" + +typedef void (*MTRCallbackType)(int); + +void DBInitComm(u8** a, MTRCallbackType b); + +void DBInitInterrupts(void); + +u32 DBQueryData(void); + +BOOL DBRead(u32* buffer, s32 count); + +BOOL DBWrite(void* src, u32 size); + +void DBOpen(void); + +void DBClose(void); + +#endif /* ODEMUEXI_DEBUGGERDRIVER_H */ diff --git a/src/JSystem/J3DGraphAnimator/J3DModelData.cpp b/src/JSystem/J3DGraphAnimator/J3DModelData.cpp index e52bb0604..e838f5697 100644 --- a/src/JSystem/J3DGraphAnimator/J3DModelData.cpp +++ b/src/JSystem/J3DGraphAnimator/J3DModelData.cpp @@ -150,10 +150,10 @@ void J3DModelData::indexToPtr() { bool J3DModelData::isDeformablePositionFormat() const { GXVtxAttrFmtList *vtxAttr = getVtxAttrFmtList(); - for (; vtxAttr->mAttrib != GX_VA_NULL; vtxAttr++) { - switch (vtxAttr->mAttrib) { + for (; vtxAttr->attr != GX_VA_NULL; vtxAttr++) { + switch (vtxAttr->attr) { case GX_VA_POS: - if (vtxAttr->mCompType == GX_F32 && vtxAttr->mCompCnt == GX_POS_XYZ) + if (vtxAttr->type == GX_F32 && vtxAttr->cnt == GX_POS_XYZ) return true; break; default: diff --git a/src/JSystem/J3DGraphBase/J3DGD.cpp b/src/JSystem/J3DGraphBase/J3DGD.cpp index a76bcf02b..f8ccac237 100644 --- a/src/JSystem/J3DGraphBase/J3DGD.cpp +++ b/src/JSystem/J3DGraphBase/J3DGD.cpp @@ -179,73 +179,73 @@ void J3DGDSetVtxAttrFmtv(GXVtxFmt fmt, GXVtxAttrFmtList* vtxAttr, bool forceNBT) GXCompType tex7CompType = GX_F32; u32 tex7CompShift = 0; - for (; vtxAttr->mAttrib != GX_VA_NULL; vtxAttr++) { - switch (vtxAttr->mAttrib) { + for (; vtxAttr->attr != GX_VA_NULL; vtxAttr++) { + switch (vtxAttr->attr) { case GX_VA_POS: - posCompCnt = vtxAttr->mCompCnt; - posCompType = vtxAttr->mCompType; - posCompShift = vtxAttr->mCompShift; + posCompCnt = vtxAttr->cnt; + posCompType = vtxAttr->type; + posCompShift = vtxAttr->frac; break; case GX_VA_NRM: case GX_VA_NBT: - nrmCompType = vtxAttr->mCompType; - if (vtxAttr->mCompCnt == GX_NRM_NBT3) { + nrmCompType = vtxAttr->type; + if (vtxAttr->cnt == GX_NRM_NBT3) { nrmCompCnt = GX_NRM_NBT; nbt3 = true; } else { - // possible fakematch? need to cast vtxAttr->mCompCnt to int to put value in r0 temporarily - // nrmCompCnt = forceNBT ? GX_NRM_NBT : vtxAttr->mCompCnt; - nrmCompCnt = (GXCompCnt)(forceNBT ? GX_NRM_NBT : (int)(vtxAttr->mCompCnt)); + // possible fakematch? need to cast vtxAttr->cnt to int to put value in r0 temporarily + // nrmCompCnt = forceNBT ? GX_NRM_NBT : vtxAttr->cnt; + nrmCompCnt = (GXCompCnt)(forceNBT ? GX_NRM_NBT : (int)(vtxAttr->cnt)); nbt3 = false; } break; case GX_VA_CLR0: - clr0CompCnt = vtxAttr->mCompCnt; - clr0CompType = vtxAttr->mCompType; + clr0CompCnt = vtxAttr->cnt; + clr0CompType = vtxAttr->type; break; case GX_VA_CLR1: - clr1CompCnt = vtxAttr->mCompCnt; - clr1CompType = vtxAttr->mCompType; + clr1CompCnt = vtxAttr->cnt; + clr1CompType = vtxAttr->type; break; case GX_VA_TEX0: - tex0CompCnt = vtxAttr->mCompCnt; - tex0CompType = vtxAttr->mCompType; - tex0CompShift = vtxAttr->mCompShift; + tex0CompCnt = vtxAttr->cnt; + tex0CompType = vtxAttr->type; + tex0CompShift = vtxAttr->frac; break; case GX_VA_TEX1: - tex1CompCnt = vtxAttr->mCompCnt; - tex1CompType = vtxAttr->mCompType; - tex1CompShift = vtxAttr->mCompShift; + tex1CompCnt = vtxAttr->cnt; + tex1CompType = vtxAttr->type; + tex1CompShift = vtxAttr->frac; break; case GX_VA_TEX2: - tex2CompCnt = vtxAttr->mCompCnt; - tex2CompType = vtxAttr->mCompType; - tex2CompShift = vtxAttr->mCompShift; + tex2CompCnt = vtxAttr->cnt; + tex2CompType = vtxAttr->type; + tex2CompShift = vtxAttr->frac; break; case GX_VA_TEX3: - tex3CompCnt = vtxAttr->mCompCnt; - tex3CompType = vtxAttr->mCompType; - tex3CompShift = vtxAttr->mCompShift; + tex3CompCnt = vtxAttr->cnt; + tex3CompType = vtxAttr->type; + tex3CompShift = vtxAttr->frac; break; case GX_VA_TEX4: - tex4CompCnt = vtxAttr->mCompCnt; - tex4CompType = vtxAttr->mCompType; - tex4CompShift = vtxAttr->mCompShift; + tex4CompCnt = vtxAttr->cnt; + tex4CompType = vtxAttr->type; + tex4CompShift = vtxAttr->frac; break; case GX_VA_TEX5: - tex5CompCnt = vtxAttr->mCompCnt; - tex5CompType = vtxAttr->mCompType; - tex5CompShift = vtxAttr->mCompShift; + tex5CompCnt = vtxAttr->cnt; + tex5CompType = vtxAttr->type; + tex5CompShift = vtxAttr->frac; break; case GX_VA_TEX6: - tex6CompCnt = vtxAttr->mCompCnt; - tex6CompType = vtxAttr->mCompType; - tex6CompShift = vtxAttr->mCompShift; + tex6CompCnt = vtxAttr->cnt; + tex6CompType = vtxAttr->type; + tex6CompShift = vtxAttr->frac; break; case GX_VA_TEX7: - tex7CompCnt = vtxAttr->mCompCnt; - tex7CompType = vtxAttr->mCompType; - tex7CompShift = vtxAttr->mCompShift; + tex7CompCnt = vtxAttr->cnt; + tex7CompType = vtxAttr->type; + tex7CompShift = vtxAttr->frac; break; default: break; diff --git a/src/JSystem/J3DGraphBase/J3DShape.cpp b/src/JSystem/J3DGraphBase/J3DShape.cpp index 3f369181b..6feeb125f 100644 --- a/src/JSystem/J3DGraphBase/J3DShape.cpp +++ b/src/JSystem/J3DGraphBase/J3DShape.cpp @@ -97,31 +97,31 @@ void J3DShape::makeVtxArrayCmd() { array[i] = 0; } - for (; vtxAttr->mAttrib != GX_VA_NULL; vtxAttr++) { - switch (vtxAttr->mAttrib) { + for (; vtxAttr->attr != GX_VA_NULL; vtxAttr++) { + switch (vtxAttr->attr) { case GX_VA_POS: { - if (vtxAttr->mCompType == GX_F32) - stride[vtxAttr->mAttrib - GX_VA_POS] = 0x0C; + if (vtxAttr->type == GX_F32) + stride[vtxAttr->attr - GX_VA_POS] = 0x0C; else - stride[vtxAttr->mAttrib - GX_VA_POS] = 0x06; - array[vtxAttr->mAttrib - GX_VA_POS] = mVertexData->getVtxPosArray(); - mVertexData->setVtxPosFrac(vtxAttr->mCompShift); - mVertexData->setVtxPosType((GXCompType)vtxAttr->mCompType); + stride[vtxAttr->attr - GX_VA_POS] = 0x06; + array[vtxAttr->attr - GX_VA_POS] = mVertexData->getVtxPosArray(); + mVertexData->setVtxPosFrac(vtxAttr->frac); + mVertexData->setVtxPosType((GXCompType)vtxAttr->type); } break; case GX_VA_NRM: { - if (vtxAttr->mCompType == GX_F32) - stride[vtxAttr->mAttrib - GX_VA_POS] = 0x0C; + if (vtxAttr->type == GX_F32) + stride[vtxAttr->attr - GX_VA_POS] = 0x0C; else - stride[vtxAttr->mAttrib - GX_VA_POS] = 0x06; - array[vtxAttr->mAttrib - GX_VA_POS] = mVertexData->getVtxNrmArray(); - mVertexData->setVtxNrmFrac(vtxAttr->mCompShift); - mVertexData->setVtxNrmType((GXCompType)vtxAttr->mCompType); + stride[vtxAttr->attr - GX_VA_POS] = 0x06; + array[vtxAttr->attr - GX_VA_POS] = mVertexData->getVtxNrmArray(); + mVertexData->setVtxNrmFrac(vtxAttr->frac); + mVertexData->setVtxNrmType((GXCompType)vtxAttr->type); } break; case GX_VA_CLR0: case GX_VA_CLR1: { - stride[vtxAttr->mAttrib - GX_VA_POS] = 0x04; - array[vtxAttr->mAttrib - GX_VA_POS] = - mVertexData->getVtxColorArray(vtxAttr->mAttrib - GX_VA_CLR0); + stride[vtxAttr->attr - GX_VA_POS] = 0x04; + array[vtxAttr->attr - GX_VA_POS] = + mVertexData->getVtxColorArray(vtxAttr->attr - GX_VA_CLR0); } break; case GX_VA_TEX0: case GX_VA_TEX1: @@ -131,11 +131,11 @@ void J3DShape::makeVtxArrayCmd() { case GX_VA_TEX5: case GX_VA_TEX6: case GX_VA_TEX7: { - if (vtxAttr->mCompType == GX_F32) - stride[vtxAttr->mAttrib - GX_VA_POS] = 0x08; + if (vtxAttr->type == GX_F32) + stride[vtxAttr->attr - GX_VA_POS] = 0x08; else - stride[vtxAttr->mAttrib - GX_VA_POS] = 0x04; - array[vtxAttr->mAttrib - GX_VA_POS] = mVertexData->getVtxTexCoordArray(vtxAttr->mAttrib - GX_VA_TEX0); + stride[vtxAttr->attr - GX_VA_POS] = 0x04; + array[vtxAttr->attr - GX_VA_POS] = mVertexData->getVtxTexCoordArray(vtxAttr->attr - GX_VA_TEX0); } break; default: break; diff --git a/src/JSystem/J3DGraphLoader/J3DModelLoader.cpp b/src/JSystem/J3DGraphLoader/J3DModelLoader.cpp index 27b141c15..f79c93b77 100644 --- a/src/JSystem/J3DGraphLoader/J3DModelLoader.cpp +++ b/src/JSystem/J3DGraphLoader/J3DModelLoader.cpp @@ -270,9 +270,9 @@ void J3DModelLoader::readInformation(const J3DModelInfoBlock* i_block, u32 i_fla /* 802FC3E4-802FC410 .text getFmtType__FP17_GXVtxAttrFmtList7_GXAttr */ static GXCompType getFmtType(GXVtxAttrFmtList* i_fmtList, GXAttr i_attr) { - for (; i_fmtList->mAttrib != GX_VA_NULL; i_fmtList++) { - if (i_fmtList->mAttrib == i_attr) { - return i_fmtList->mCompType; + for (; i_fmtList->attr != GX_VA_NULL; i_fmtList++) { + if (i_fmtList->attr == i_attr) { + return i_fmtList->type; } } return GX_F32; diff --git a/src/JSystem/JUtility/JUTGamePad.cpp b/src/JSystem/JUtility/JUTGamePad.cpp index 7219ff4c4..7840dd697 100644 --- a/src/JSystem/JUtility/JUTGamePad.cpp +++ b/src/JSystem/JUtility/JUTGamePad.cpp @@ -71,11 +71,11 @@ u32 JUTGamePad::read() { u32 mask = 0; for (int i = 0; i < 4; i++) { u32 mask_tmp = 0x80000000 >> i; - if (mPadStatus[i].error == 0) { - u32 local_2c = mPadMStick[i].update(mPadStatus[i].stick_x, mPadStatus[i].stick_y, sStickMode, WS_MAIN_STICK) << 0x18; - local_2c |= (mPadSStick[i].update(mPadStatus[i].substick_x, mPadStatus[i].substick_y, sStickMode, WS_SUB_STICK) << 0x10); + if (mPadStatus[i].err == 0) { + u32 local_2c = mPadMStick[i].update(mPadStatus[i].stickX, mPadStatus[i].stickY, sStickMode, WS_MAIN_STICK) << 0x18; + local_2c |= (mPadSStick[i].update(mPadStatus[i].substickX, mPadStatus[i].substickY, sStickMode, WS_SUB_STICK) << 0x10); mPadButton[i].update(&mPadStatus[i], local_2c); - } else if (mPadStatus[i].error == -1) { + } else if (mPadStatus[i].err == -1) { mPadMStick[i].update(0, 0, sStickMode, WS_MAIN_STICK); mPadSStick[i].update(0, 0, sStickMode, WS_SUB_STICK); mPadButton[i].update(NULL, 0); @@ -84,8 +84,8 @@ u32 JUTGamePad::read() { mask |= mask_tmp; } } else { - if (mPadStatus[i].error != -3) { - OSReport("game pad read error (%d)\n", mPadStatus[i].error); + if (mPadStatus[i].err != -3) { + OSReport("game pad read error (%d)\n", mPadStatus[i].err); } mPadButton[i].mTrigger = 0; mPadButton[i].mRelease = 0; @@ -97,10 +97,10 @@ u32 JUTGamePad::read() { if (pad->getPadReplay()) { PADStatus status; pad->getPadReplay()->unk1(&status); - u32 m_stick = pad->mMainStick.update(status.stick_x, status.stick_y, sStickMode, + u32 m_stick = pad->mMainStick.update(status.stickX, status.stickY, sStickMode, WS_MAIN_STICK) << 0x18; - u32 s_stick = pad->mSubStick.update(status.substick_x, status.substick_y, sStickMode, + u32 s_stick = pad->mSubStick.update(status.substickX, status.substickY, sStickMode, WS_SUB_STICK) << 0x10; m_stick |= s_stick; @@ -114,7 +114,7 @@ u32 JUTGamePad::read() { if (pad->getPadRecord() && pad->mPortNum != -1) { s32 port = pad->mPortNum; - if (mPadStatus[port].error == 0) { + if (mPadStatus[port].err == 0) { pad->getPadRecord()->write(&mPadStatus[port]); } } @@ -131,7 +131,7 @@ u32 JUTGamePad::read() { /* 802C3C14-802C3CC4 .text assign__10JUTGamePadFv */ void JUTGamePad::assign() { for (int i = 0; i < 4; i++) { - if (mPadStatus[i].error == 0 && mPadAssign[i] == 0) { + if (mPadStatus[i].err == 0 && mPadAssign[i] == 0) { mPortNum = i; mPadAssign[i] = 1; mPadButton[i].setRepeat(mButton.field_0x24, mButton.field_0x28, mButton.field_0x2c); @@ -142,7 +142,7 @@ void JUTGamePad::assign() { } u8 JUTGamePad::CRumble::mStatus[4]; -PADMask JUTGamePad::CRumble::mEnabled; +u32 JUTGamePad::CRumble::mEnabled; callbackFn JUTGamePad::C3ButtonReset::sCallback; void* JUTGamePad::C3ButtonReset::sCallbackArg; OSTime JUTGamePad::C3ButtonReset::sThreshold = (OSTime)((OS_BUS_CLOCK / 4) / 60) * 30; @@ -176,7 +176,7 @@ void JUTGamePad::update() { mButton = mPadButton[mPortNum]; mMainStick = mPadMStick[mPortNum]; mSubStick = mPadSStick[mPortNum]; - mErrorStatus = mPadStatus[mPortNum].error; + mErrorStatus = mPadStatus[mPortNum].err; if ((mButton.mButton & C3ButtonReset::sResetMaskPattern) != C3ButtonReset::sResetPattern) { @@ -276,10 +276,10 @@ void JUTGamePad::CButton::update(const PADStatus* padStatus, u32 stickStatus) { mRepeat |= (field_0x24 ^ 0xFFFFFFFF) & mTrigger; if (padStatus != NULL) { - mAnalogA = padStatus->analog_a; - mAnalogB = padStatus->analog_b; - mAnalogL = padStatus->trigger_left; - mAnalogR = padStatus->trigger_right; + mAnalogA = padStatus->analogA; + mAnalogB = padStatus->analogB; + mAnalogL = padStatus->triggerLeft; + mAnalogR = padStatus->triggerRight; } else { mAnalogA = 0; mAnalogB = 0; @@ -362,7 +362,7 @@ void JUTGamePad::CRumble::clear() { mLength = 0; mData = 0; mFrameCount = 0; - mEnabled = (PADMask)(PAD_CHAN3_BIT | PAD_CHAN2_BIT | PAD_CHAN1_BIT | PAD_CHAN0_BIT); + mEnabled = (PAD_CHAN3_BIT | PAD_CHAN2_BIT | PAD_CHAN1_BIT | PAD_CHAN0_BIT); } /* 802C4444-802C449C .text clear__Q210JUTGamePad7CRumbleFP10JUTGamePad */ @@ -495,7 +495,7 @@ void JUTGamePad::CRumble::setEnabled(u32 mask) { } } } - mEnabled = (PADMask)(mask & (PAD_CHAN3_BIT | PAD_CHAN2_BIT | PAD_CHAN1_BIT | PAD_CHAN0_BIT)); + mEnabled = (mask & (PAD_CHAN3_BIT | PAD_CHAN2_BIT | PAD_CHAN1_BIT | PAD_CHAN0_BIT)); } /* 802C489C-802C48B8 .text setRepeat__Q210JUTGamePad7CButtonFUlUlUl */ @@ -517,7 +517,7 @@ bool JUTGamePad::recalibrate(u32 mask) { } } - return PADRecalibrate((PADMask)mask); + return PADRecalibrate(mask); } static void dummy() { diff --git a/src/PowerPC_EABI_Support/MetroTRK/trk.h b/src/PowerPC_EABI_Support/MetroTRK/trk.h new file mode 100644 index 000000000..e67b0e8f2 --- /dev/null +++ b/src/PowerPC_EABI_Support/MetroTRK/trk.h @@ -0,0 +1,378 @@ +#ifndef __METROTRK_TRK_H__ +#define __METROTRK_TRK_H__ + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//////////// TRK ENUMS ///////////// +// Hardware types. +typedef enum { + HARDWARE_AMC_DDH = 0, + HARDWARE_GDEV = 1, + HARDWARE_BBA = 2, +} HardwareType; + +// DS Error returns. +typedef enum { + DS_NoError = 0x0, + DS_StepError = 0x1, + DS_ParameterError = 0x2, + + DS_EventQueueFull = 0x100, + + DS_NoMessageBufferAvailable = 0x300, + DS_MessageBufferOverflow = 0x301, + DS_MessageBufferReadError = 0x302, + + DS_DispatchError = 0x500, + + DS_InvalidMemory = 0x700, + DS_InvalidRegister = 0x701, + DS_CWDSException = 0x702, + DS_UnsupportedError = 0x703, + DS_InvalidProcessID = 0x704, + DS_InvalidThreadID = 0x705, + DS_OSError = 0x706, + + DS_Error800 = 0x800, +} DSError; + +// Where to read/write. +typedef enum { + DS_Stdin = 0, + DS_Stdout = 1, + DS_Stderr = 2, +} DSFileHandle; + +// IO returns. +typedef enum { + DS_IONoError = 0, + DS_IOError = 1, + DS_IOEOF = 2, +} DSIOResult; + +// Message command IDs +typedef enum { + DSMSG_Ping = 0x0, + DSMSG_Connect = 0x1, + DSMSG_Disconnect = 0x2, + DSMSG_Reset = 0x3, + DSMSG_Versions = 0x4, + DSMSG_SupportMask = 0x5, + DSMSG_Override = 0x7, + + DSMSG_ReadMemory = 0x10, + DSMSG_WriteMemory = 0x11, + DSMSG_ReadRegisters = 0x12, + DSMSG_WriteRegisters = 0x13, + DSMSG_SetOption = 0x17, + DSMSG_Continue = 0x18, + DSMSG_Step = 0x19, + DSMSG_Stop = 0x1A, + + DSMSG_ReplyACK = 0x80, + + DSMSG_NotifyStopped = 0x90, + DSMSG_NotifyException = 0x91, + + DSMSG_WriteFile = 0xD0, + DSMSG_ReadFile = 0xD1, + DSMSG_OpenFile = 0xD2, + DSMSG_CloseFile = 0xD3, + DSMSG_PositionFile = 0xD4, + + DSMSG_ReplyNAK = 0xFF, +} MessageCommandID; + +// Register commands. +typedef enum { + DSREG_Default = 0, + DSREG_FP = 1, + DSREG_Extended1 = 2, + DSREG_Extended2 = 3, +} DSMessageRegisterOptions; + +// Step commands. +typedef enum { + DSSTEP_IntoCount = 0x0, + DSSTEP_IntoRange = 0x1, + DSSTEP_OverCount = 0x10, + DSSTEP_OverRange = 0x11, +} DSMessageStepOptions; + +typedef enum { + DSREPLY_NoError = 0x0, + DSREPLY_Error = 0x1, + DSREPLY_PacketSizeError = 0x2, + DSREPLY_CWDSError = 0x3, + DSREPLY_EscapeError = 0x4, + DSREPLY_BadFCS = 0x5, + DSREPLY_Overflow = 0x6, + DSREPLY_SequenceMissing = 0x7, + + DSREPLY_UnsupportedCommandError = 0x10, + DSREPLY_ParameterError = 0x11, + DSREPLY_UnsupportedOptionError = 0x12, + DSREPLY_InvalidMemoryRange = 0x13, + DSREPLY_InvalidRegisterRange = 0x14, + DSREPLY_CWDSException = 0x15, + DSREPLY_NotStopped = 0x16, + DSREPLY_BreakpointsFull = 0x17, + DSREPLY_BreakpointConflict = 0x18, + + DSREPLY_OSError = 0x20, + DSREPLY_InvalidProcessID = 0x21, + DSREPLY_InvalidThreadID = 0x22, + DSREPLY_DebugSecurityError = 0x23, +} DSReplyError; + +typedef enum { + DSRECV_Wait = 0, + DSRECV_Found = 1, + DSRECV_InFrame = 2, + DSRECV_FrameOverflow = 3, +} ReceiverState; + +typedef enum { + DSMSGMEMORY_Segmented = 0x01, /* non-flat addr space */ + DSMSGMEMORY_Extended = 0x02, /* > 32-bit data addr */ + DSMSGMEMORY_Protected = 0x04, /* non-user memory */ + DSMSGMEMORY_Userview = 0x08, /* breakpoints are invisible */ + DSMSGMEMORY_Space_program = 0x00, + DSMSGMEMORY_Space_data = 0x40, + DSMSGMEMORY_Space_io = 0x80 +}; + +typedef enum { + NUBEVENT_Null = 0, + NUBEVENT_Shutdown = 1, + NUBEVENT_Request = 2, + NUBEVENT_Breakpoint = 3, + NUBEVENT_Exception = 4, + NUBEVENT_Support = 5, +} NubEventType; + +typedef enum { + VALIDMEM_Readable = 0, + VALIDMEM_Writeable = 1, +} ValidMemoryOptions; + +typedef enum { + MEMACCESS_UserMemory = 0, + MEMACCESS_DebuggerMemory = 1, +} MemoryAccessOptions; + +typedef int UARTError; + +typedef enum { + UART_NoError = 0, + UART_UnknownBaudRate = 1, + UART_ConfigurationError = 2, + UART_BufferOverflow = 3, // specified buffer was too small + UART_NoData = 4, // no data available from polling +} UARTErrorOptions; + +typedef enum { + kBaudHWSet = -1, // use HW settings such as DIP switches + kBaud300 = 300, // valid baud rates + kBaud600 = 600, + kBaud1200 = 1200, + kBaud1800 = 1800, + kBaud2000 = 2000, + kBaud2400 = 2400, + kBaud3600 = 3600, + kBaud4800 = 4800, + kBaud7200 = 7200, + kBaud9600 = 9600, + kBaud19200 = 19200, + kBaud38400 = 38400, + kBaud57600 = 57600, + kBaud115200 = 115200, + kBaud230400 = 230400 +} UARTBaudRate; + +//////////////////////////////////// + +typedef int MessageBufferID; + +#define TRKMSGBUF_SIZE (0x800 + 0x80) + +typedef struct TRKBuffer { + /* 0x00 */ u32 _00; + /* 0x04 */ BOOL isInUse; + /* 0x08 */ u32 length; + /* 0x0C */ u32 position; + /* 0x10 */ u8 data[TRKMSGBUF_SIZE]; +} TRKBuffer; + +typedef struct TRKFramingState { + MessageBufferID msgBufID; // _00 + TRKBuffer* buffer; // _04 + ReceiverState receiveState; // _08 + BOOL isEscape; // _0C + u8 fcsType; // _10 +} TRKFramingState; + +typedef struct TRKState_PPC { + u32 GPR[32]; // 0x0 + u32 LR; // 0x80 + u32 CTR; // 0x84 + u32 XER; // 0x88 + u32 MSR; // 0x8c + u32 DAR; // 0x90 + u32 DSISR; // 0x94 + BOOL stopped; // 0x98 + BOOL inputActivated; // 0x9c + u8* inputPendingPtr; // 0xA0 +} TRKState_PPC; + +typedef struct CommandReply { + u32 _00; // _00 + union { + u8 b; + MessageCommandID m; + } commandID; // _04, use MessageCommandID enum + union { + u8 b; + DSReplyError r; + } replyError; // _08, use DSReplyError enum - should be enum type? check size. + u32 _0C; // _0C + u8 _10[0x30]; // _10, unknown +} CommandReply; + +typedef struct ProcessorRestoreFlags_PPC { + u8 TBR; + u8 DEC; + u8 linker_padding[0x9 - 0x2]; +} ProcessorRestoreFlags_PPC; + +void TRKSaveExtended1Block(); + +#define SPR_XER 1 +#define SPR_LR 8 +#define SPR_CTR 9 +#define SPR_DSISR 18 +#define SPR_DAR 19 +#define SPR_DEC 22 +#define SPR_SDR1 25 +#define SPR_SRR0 26 +#define SPR_SRR1 27 +#define SPR_SPRG0 272 +#define SPR_SPRG1 273 +#define SPR_SPRG2 274 +#define SPR_SPRG3 275 +#define SPR_EAR 282 +#define SPR_TBL 284 +#define SPR_TBU 285 +#define SPR_PVR 287 +#define SPR_IBAT0U 528 +#define SPR_IBAT0L 529 +#define SPR_IBAT1U 530 +#define SPR_IBAT1L 531 +#define SPR_IBAT2U 532 +#define SPR_IBAT2L 533 +#define SPR_IBAT3U 534 +#define SPR_IBAT3L 535 +#define SPR_IBAT4U 560 +#define SPR_IBAT4L 561 +#define SPR_IBAT5U 562 +#define SPR_IBAT5L 563 +#define SPR_IBAT6U 564 +#define SPR_IBAT6L 565 +#define SPR_IBAT7U 566 +#define SPR_IBAT7L 567 +#define SPR_DBAT0U 536 +#define SPR_DBAT0L 537 +#define SPR_DBAT1U 538 +#define SPR_DBAT1L 539 +#define SPR_DBAT2U 540 +#define SPR_DBAT2L 541 +#define SPR_DBAT3U 542 +#define SPR_DBAT3L 543 +#define SPR_DBAT4U 568 +#define SPR_DBAT4L 569 +#define SPR_DBAT5U 570 +#define SPR_DBAT5L 571 +#define SPR_DBAT6U 572 +#define SPR_DBAT6L 573 +#define SPR_DBAT7U 574 +#define SPR_DBAT7L 575 +#define SPR_GQR0 912 +#define SPR_GQR1 913 +#define SPR_GQR2 914 +#define SPR_GQR3 915 +#define SPR_GQR4 916 +#define SPR_GQR5 917 +#define SPR_GQR6 918 +#define SPR_GQR7 919 +#define SPR_HID2 920 +#define SPR_WPAR 921 +#define SPR_DMA_U 922 +#define SPR_DMA_L 923 +#define SPR_UMMCR0 936 +#define SPR_UPMC1 937 +#define SPR_UPMC2 938 +#define SPR_USIA 939 +#define SPR_UMMCR1 940 +#define SPR_UPMC3 941 +#define SPR_UPMC4 942 +#define SPR_USDA 943 +#define SPR_MMCR0 952 +#define SPR_PMC1 953 +#define SPR_PMC2 954 +#define SPR_SIA 955 +#define SPR_MMCR1 956 +#define SPR_PMC3 957 +#define SPR_PMC4 958 +#define SPR_SDA 959 +#define SPR_HID0 1008 +#define SPR_HID1 1009 +#define SPR_IABR 1010 +#define SPR_HID4 1011 +#define SPR_DABR 1013 +#define SPR_L2CR 1017 +#define SPR_ICTC 1019 +#define SPR_THRM1 1020 +#define SPR_THRM2 1021 +#define SPR_FPECR 1022 + +// PPC exceptions +// 0x000 is reserved +#define PPC_SystemReset 0x100 +#define PPC_MachineCheck 0x200 +#define PPC_DataStorage 0x300 +#define PPC_InstructionStorage 0x400 +#define PPC_ExternalInterrupt 0x500 +#define PPC_Alignment 0x600 +#define PPC_Program 0x700 +#define PPC_FloatingPointUnavaiable 0x800 +#define PPC_Decrementer 0x900 +// 0xA00-0xB00 are reserved +#define PPC_SystemCall 0xC00 +#define PPC_Trace 0xD00 +#define PPC_FloatingPointAssist 0xE00 // unimplemented in 750CL +#define PPC_PerformanceMonitor 0xF00 // Dolphin/Broadway specific +// 0x1000-0x1200 are unimplemented in 750CL +#define PPC_InstructionAddressBreakpoint 0x1300 // Dolphin/Broadway specific +// 0x1400-0x2F00 are reserved, but TRK uses some +#define PPC_SystemManagementInterrupt 0x1400 +// 0x1500-0x1600 are unimplemented in 750CL +#define PPC_ThermalManagementInterrupt 0x1700 +#define PPC_1800Exception 0x1800 +#define PPC_1900Exception 0x1900 +#define PPC_1A00Exception 0x1A00 +#define PPC_1B00Exception 0x1B00 +#define PPC_1C00Exception 0x1C00 // Data breakpoint? +#define PPC_1D00Exception 0x1D00 // Instruction breakpoint? +#define PPC_1E00Exception 0x1E00 // Peripheral breakpoint? +#define PPC_1F00Exception 0x1F00 // Non maskable development port? +#define PPC_2000Exception 0x2000 + +#ifdef __cplusplus +} +#endif + +#endif /* __METROTRK_TRK_H__ */ diff --git a/src/PowerPC_EABI_Support/Runtime/Inc/MWCPlusLib.h b/src/PowerPC_EABI_Support/Runtime/Inc/MWCPlusLib.h new file mode 100644 index 000000000..820db4c42 --- /dev/null +++ b/src/PowerPC_EABI_Support/Runtime/Inc/MWCPlusLib.h @@ -0,0 +1,33 @@ +#ifndef MWCPLUSLIB_H +#define MWCPLUSLIB_H + +#include "stddef.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CTORARG_TYPE int +#define CTORARG_PARTIAL (0) +#define CTORARG_COMPLETE (1) + +#define CTORCALL_COMPLETE(ctor, objptr) (((void (*)(void*, CTORARG_TYPE))ctor)(objptr, CTORARG_COMPLETE)) + +#define DTORARG_TYPE int + +#define DTORCALL_COMPLETE(dtor, objptr) (((void (*)(void*, DTORARG_TYPE))dtor)(objptr, -1)) + +typedef void* ConstructorDestructor; + +extern void __construct_array(void* ptr, ConstructorDestructor ctor, ConstructorDestructor dtor, size_t size, size_t n); +extern void __destroy_arr(void* block, ConstructorDestructor* dtor, size_t size, size_t n); +extern void* __construct_new_array(void* block, ConstructorDestructor ctor, ConstructorDestructor dtor_arg, size_t size, size_t n); +extern void __destroy_new_array(void* block, ConstructorDestructor dtor); +extern void __destroy_new_array2(); +extern void __destroy_new_array3(); + +#ifdef __cplusplus +} +#endif + +#endif /* MWCPLUSLIB_H */ diff --git a/src/PowerPC_EABI_Support/Runtime/Src/NMWException.cp b/src/PowerPC_EABI_Support/Runtime/Src/NMWException.cp index 97885901e..3285b3ebd 100644 --- a/src/PowerPC_EABI_Support/Runtime/Src/NMWException.cp +++ b/src/PowerPC_EABI_Support/Runtime/Src/NMWException.cp @@ -1 +1,218 @@ #include "NMWException.h" +#include "MWCPlusLib.h" + +typedef void (*unexpected_handler)(); +unexpected_handler set_unexpected(unexpected_handler handler); +void unexpected(); + +typedef void (*terminate_handler)(); +terminate_handler set_terminate(terminate_handler handler); +void terminate(); + +#define ARRAY_HEADER_SIZE 16 + +extern "C" { +extern void abort(); +} + +namespace std { +static void dthandler() { abort(); } + +static terminate_handler thandler = dthandler; + +static void duhandler() { terminate(); } + +static unexpected_handler uhandler = duhandler; + +extern terminate_handler set_terminate(terminate_handler handler) { + terminate_handler old = thandler; + thandler = handler; + return old; +} + +extern void terminate() { thandler(); } + +extern unexpected_handler set_unexpected(unexpected_handler handler) { + unexpected_handler old = uhandler; + uhandler = handler; + return old; +} + +extern void unexpected() { uhandler(); } +} // namespace std + +extern char __throw_catch_compare(const char* throwtype, const char* catchtype, long* offset_result) { + const char *cptr1, *cptr2; + + *offset_result = 0; + + if ((cptr2 = catchtype) == 0) { + return true; + } + + cptr1 = throwtype; + + if (*cptr2 == 'P') { + cptr2++; + if (*cptr2 == 'C') + cptr2++; + if (*cptr2 == 'V') + cptr2++; + if (*cptr2 == 'v') { + if (*cptr1 == 'P' || *cptr1 == '*') { + return true; + } + } + cptr2 = catchtype; + } + + switch (*cptr1) { + case '*': + case '!': + if (*cptr1++ != *cptr2++) + return false; + for (;;) { + if (*cptr1 == *cptr2++) { + if (*cptr1++ == '!') { + long offset; + + for (offset = 0; *cptr1 != '!';) { + offset = offset * 10 + *cptr1++ - '0'; + } + *offset_result = offset; + return true; + } + } else { + while (*cptr1++ != '!') { } + while (*cptr1++ != '!') { } + if (*cptr1 == 0) + return false; + + cptr2 = catchtype + 1; + } + } + return false; + } + + while ((*cptr1 == 'P' || *cptr1 == 'R') && *cptr1 == *cptr2) { + cptr1++; + cptr2++; + + if (*cptr2 == 'C') { + if (*cptr1 == 'C') + cptr1++; + cptr2++; + } + if (*cptr1 == 'C') + return false; + + if (*cptr2 == 'V') { + if (*cptr1 == 'V') + cptr1++; + cptr2++; + } + if (*cptr1 == 'V') + return false; + } + + for (; *cptr1 == *cptr2; cptr1++, cptr2++) { + if (*cptr1 == 0) + return true; + } + + return false; +} + +class __partial_array_destructor { +private: + void* p; + size_t size; + size_t n; + ConstructorDestructor dtor; + +public: + size_t i; + + __partial_array_destructor(void* array, size_t elementsize, size_t nelements, ConstructorDestructor destructor) { + p = array; + size = elementsize; + n = nelements; + dtor = destructor; + i = n; + } + + ~__partial_array_destructor() { + char* ptr; + + if (i < n && dtor) { + for (ptr = (char*)p + size * i; i > 0; i--) { + ptr -= size; + DTORCALL_COMPLETE(dtor, ptr); + } + } + } +}; + +extern void* __construct_new_array(void* block, ConstructorDestructor ctor, ConstructorDestructor dtor, size_t size, size_t n) { + char* ptr; + + if ((ptr = (char*)block) != 0L) { + size_t* p = (size_t*)ptr; + + p[0] = size; + p[1] = n; + ptr += ARRAY_HEADER_SIZE; + + if (ctor) { + __partial_array_destructor pad(ptr, size, n, dtor); + char* p; + + for (pad.i = 0, p = (char*)ptr; pad.i < n; pad.i++, p += size) { + CTORCALL_COMPLETE(ctor, p); + } + } + } + return ptr; +} + +extern void __construct_array(void* ptr, ConstructorDestructor ctor, ConstructorDestructor dtor, size_t size, size_t n) { + __partial_array_destructor pad(ptr, size, n, dtor); + char* p; + + for (pad.i = 0, p = (char*)ptr; pad.i < n; pad.i++, p += size) { + CTORCALL_COMPLETE(ctor, p); + } +} + +extern void __destroy_arr(void* block, ConstructorDestructor* dtor, size_t size, size_t n) { + char* p; + + for (p = (char*)block + size * n; n > 0; n--) { + p -= size; + DTORCALL_COMPLETE(dtor, p); + } +} + +extern void __destroy_new_array(void* block, ConstructorDestructor dtor) { + if (block) { + if (dtor) { + size_t i, objects, objectsize; + char* p; + + objectsize = *(size_t*)((char*)block - ARRAY_HEADER_SIZE); + objects = ((size_t*)((char*)block - ARRAY_HEADER_SIZE))[1]; + p = (char*)block + (objectsize * objects); + + for (i = 0; i < objects; i++) { + p -= objectsize; + DTORCALL_COMPLETE(dtor, p); + } + } + + ::operator delete[]((char*)block - ARRAY_HEADER_SIZE); + } +} + +void __destroy_new_array2(void) {} + +void __destroy_new_array3(void) {} diff --git a/src/TRK_MINNOW_DOLPHIN/MetroTRK/Export/mslsupp.c b/src/TRK_MINNOW_DOLPHIN/MetroTRK/Export/mslsupp.c new file mode 100644 index 000000000..0ae2c53b7 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/MetroTRK/Export/mslsupp.c @@ -0,0 +1,54 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h" +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.h" +#include "TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.h" + +DSIOResult __read_file(u32 handle, u8* buffer, size_t* count, void* ref_con); +DSIOResult __write_file(u32 handle, u8* buffer, size_t* count, void* ref_con); +DSIOResult __close_file(u32 handle, u8* buffer, size_t* count, void* ref_con); +DSIOResult __access_file(u32 handle, u8* buffer, size_t* count, void* ref_con, + MessageCommandID cmd); + +DSIOResult __read_console(u32 handle, u8* buffer, size_t* count, void* ref_con) { + if (GetUseSerialIO() == 0) { + return DS_IOError; + } + return __read_file(DS_Stdin, buffer, count, ref_con); +} + +DSIOResult __TRK_write_console(u32 handle, u8* buffer, size_t* count, void* ref_con) { + if (GetUseSerialIO() == 0) { + return DS_IOError; + } + return __write_file(DS_Stdout, buffer, count, ref_con); +} + +static DSIOResult __read_file(u32 handle, u8* buffer, size_t* count, void* ref_con) { + return __access_file(handle, buffer, count, ref_con, DSMSG_ReadFile); +} + +static DSIOResult __write_file(u32 handle, u8* buffer, size_t* count, void* ref_con) { + return __access_file(handle, buffer, count, ref_con, DSMSG_WriteFile); +} + +static 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; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.c b/src/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.c new file mode 100644 index 000000000..7f9d57231 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.c @@ -0,0 +1,148 @@ +#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h" +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/main_TRK.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_TRK.h" +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h" + +#include "global.h" + +#undef DBAT3U +#undef LR + +extern u32 _db_stack_addr; + +#define EXCEPTIONMASK_ADDR 0x80000044 + +static u32 lc_base; + +static u32 TRK_ISR_OFFSETS[15] = {PPC_SystemReset, + PPC_MachineCheck, + PPC_DataStorage, + PPC_InstructionStorage, + PPC_ExternalInterrupt, + PPC_Alignment, + PPC_Program, + PPC_FloatingPointUnavaiable, + PPC_Decrementer, + PPC_SystemCall, + PPC_Trace, + PPC_PerformanceMonitor, + PPC_InstructionAddressBreakpoint, + PPC_SystemManagementInterrupt, + PPC_ThermalManagementInterrupt}; + +void __TRK_copy_vectors(void); +__declspec(section ".init") void __TRK_reset(void) { OSResetSystem(FALSE, 0, FALSE); } + +void EnableMetroTRKInterrupts(void) { + EnableEXI2Interrupts(); +} + +u32 TRKTargetTranslate(u32 param_0) { + if (param_0 >= lc_base) { + if ((param_0 < lc_base + 0x4000) && ((gTRKCPUState.Extended1.DBAT3U & 3) != 0)) { + return param_0; + } + } + return param_0 & 0x3FFFFFFF | 0x80000000; +} + +extern u8 gTRKInterruptVectorTable[]; + +__declspec(section ".init") void TRK_copy_vector(u32 offset) { + void* destPtr = (void*)TRKTargetTranslate(offset); + TRK_memcpy(destPtr, (void*)(gTRKInterruptVectorTable + offset), 0x100); + TRK_flush_cache(destPtr, 0x100); +} + +void __TRK_copy_vectors(void) { + u32 r3 = lc_base; + u32* isrOffsetPtr; + int i; + u32 r29; + + if (r3 <= 0x44 && r3 + 0x4000 > 0x44 && gTRKCPUState.Extended1.DBAT3U & 3) { + r3 = 0x44; + } else { + r3 = EXCEPTIONMASK_ADDR; + } + + i = 0; + r29 = *(u32*)r3; + isrOffsetPtr = TRK_ISR_OFFSETS; + + do { + if ((r29 & (1 << i)) && i != 4) { + TRK_copy_vector(isrOffsetPtr[i]); + } + + i++; + } while (i <= 14); +} + +DSError TRKInitializeTarget() { + gTRKState.isStopped = TRUE; + gTRKState.msr = __TRK_get_MSR(); + lc_base = 0xE0000000; + return DS_NoError; +} + +asm void InitMetroTRK() { + // 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 + // clang-format on +} diff --git a/src/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.c b/src/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.c new file mode 100644 index 000000000..e22f2c565 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.c @@ -0,0 +1,174 @@ +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h" +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/DDH_Stubs.h" +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/GDEV_Stubs.h" +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/UDP_Stubs.h" +#include "dolphin/base/PPCArch.h" +#include "trk.h" + +void TRKInterruptHandler(); + +BOOL _MetroTRK_Has_Framing; + +u8 TRK_Use_BBA; + +DBCommTable gDBCommTable = {}; + +void TRKEXICallBack(s16 param_0, OSContext* ctx) { + OSEnableScheduler(); + TRKLoadContext(ctx, 0x500); +} + +int InitMetroTRKCommTable(int hwId) { + int result = 1; + OSReport("Devkit set to : %ld\n", hwId); + TRK_Use_BBA = 0; + + if (hwId == HARDWARE_BBA) { // BBA hardware + OSReport("MetroTRK : Set to BBA\n"); + // Initialize gDBCommTable + TRK_Use_BBA = 1; + gDBCommTable.initialize_func = udp_cc_initialize; + gDBCommTable.open_func = udp_cc_open; + gDBCommTable.close_func = udp_cc_close; + gDBCommTable.read_func = udp_cc_read; + gDBCommTable.write_func = udp_cc_write; + gDBCommTable.shutdown_func = udp_cc_shutdown; + gDBCommTable.peek_func = udp_cc_peek; + gDBCommTable.pre_continue_func = udp_cc_pre_continue; + gDBCommTable.post_stop_func = udp_cc_post_stop; + gDBCommTable.init_interrupts_func = NULL; + return 0; + } + + if (hwId == HARDWARE_GDEV) { // NDEV hardware + OSReport("MetroTRK : Set to GDEV hardware\n"); + // Initialize gDBCommTable + result = Hu_IsStub(); + gDBCommTable.initialize_func = (DBCommInitFunc)gdev_cc_initialize; + gDBCommTable.open_func = gdev_cc_open; + gDBCommTable.close_func = gdev_cc_close; + gDBCommTable.read_func = gdev_cc_read; + gDBCommTable.write_func = gdev_cc_write; + gDBCommTable.shutdown_func = gdev_cc_shutdown; + gDBCommTable.peek_func = gdev_cc_peek; + gDBCommTable.pre_continue_func = gdev_cc_pre_continue; + gDBCommTable.post_stop_func = gdev_cc_post_stop; + gDBCommTable.init_interrupts_func = gdev_cc_initinterrupts; + + } else if (hwId == HARDWARE_AMC_DDH) { + OSReport("MetroTRK : Set to AMC DDH hardware\n"); + result = AMC_IsStub(); + // Initialize gDBCommTable + gDBCommTable.initialize_func = (DBCommInitFunc)ddh_cc_initialize; + gDBCommTable.open_func = ddh_cc_open; + gDBCommTable.close_func = ddh_cc_close; + gDBCommTable.read_func = ddh_cc_read; + gDBCommTable.write_func = ddh_cc_write; + gDBCommTable.shutdown_func = ddh_cc_shutdown; + gDBCommTable.peek_func = ddh_cc_peek; + gDBCommTable.pre_continue_func = ddh_cc_pre_continue; + gDBCommTable.post_stop_func = ddh_cc_post_stop; + gDBCommTable.init_interrupts_func = ddh_cc_initinterrupts; + + } else { // unknown hardware + OSReport("MetroTRK : Set to UNKNOWN hardware. (%ld)\n", hwId); + OSReport("MetroTRK : Invalid hardware ID passed from OS\n"); + OSReport("MetroTRK : Defaulting to GDEV Hardware\n"); + } + + return result; +} + +DSError TRKInitializeIntDrivenUART(u32 param_0, u32 param_1, u32 param_2, void* param_3) { + gDBCommTable.initialize_func(param_3, TRKEXICallBack); + gDBCommTable.open_func(); + return DS_NoError; +} + +void EnableEXI2Interrupts(void) { + if (!TRK_Use_BBA) { + if (gDBCommTable.init_interrupts_func != NULL) { + gDBCommTable.init_interrupts_func(); + } + } +} + +int TRKPollUART(void) { + return gDBCommTable.peek_func(); +} + +UARTError TRKReadUARTN(void* bytes, u32 length) { + int readErr = gDBCommTable.read_func(bytes, length); + return ((-readErr | readErr) >> 31); +} + +UARTError TRKWriteUARTN(const void* bytes, u32 length) { + int writeErr = gDBCommTable.write_func(bytes, length); + return ((-writeErr | writeErr) >> 31); +} + +void ReserveEXI2Port(void) { + gDBCommTable.post_stop_func(); +} + +void UnreserveEXI2Port(void) { + gDBCommTable.pre_continue_func(); +} + +void TRK_board_display(char* str) { + OSReport("%s\n", str); +} + +DSError InitializeProgramEndTrap(void) { + static const u32 EndofProgramInstruction = 'END'; + + u8* endOfProgramInstructionBytes = (u8*)&EndofProgramInstruction; + u8* ppcHaltPtr = (u8*)PPCHalt; + TRK_memcpy(ppcHaltPtr + 4, endOfProgramInstructionBytes, 4); + ICInvalidateRange(ppcHaltPtr + 4, 4); + DCFlushRange(ppcHaltPtr + 4, 4); +} + +void TRKUARTInterruptHandler() {} + +asm void TRKLoadContext(OSContext* ctx, u32) { + // 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 + // clang-format on +} diff --git a/src/TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.c b/src/TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.c new file mode 100644 index 000000000..4ea2c7eee --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.c @@ -0,0 +1,14 @@ +/** + * targcont.c + * Description: + */ + +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/targcont.h" + +DSError TRKTargetContinue(void) { + TRKTargetSetStopped(0); + UnreserveEXI2Port(); + TRKSwapAndGo(); + ReserveEXI2Port(); + return 0; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.c b/src/TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.c new file mode 100644 index 000000000..d574dbba6 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.c @@ -0,0 +1,16 @@ +/** + * target_options.c + * Description: + */ + +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/target_options.h" + +static u8 bUseSerialIO; + +void SetUseSerialIO(u8 serialIO) { + bUseSerialIO = serialIO; +} + +u8 GetUseSerialIO(void) { + return bUseSerialIO; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/dispatch.c b/src/TRK_MINNOW_DOLPHIN/Portable/dispatch.c new file mode 100644 index 000000000..5b2dcf167 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/dispatch.c @@ -0,0 +1,62 @@ +/** + * dispatch.c + * Description: + */ + +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/dispatch.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h" +#include "TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h" + +u32 gTRKDispatchTableSize; + +struct DispatchEntry { + int (*fn)(TRKBuffer*); +}; + +extern int TRKDoUnsupported(TRKBuffer*); +extern int TRKDoConnect(TRKBuffer*); +extern int TRKDoDisconnect(TRKBuffer*); +extern int TRKDoReset(TRKBuffer*); +extern int TRKDoVersions(TRKBuffer*); +extern int TRKDoSupportMask(TRKBuffer*); +extern int TRKDoCPUType(TRKBuffer*); +extern int TRKDoReadMemory(TRKBuffer*); +extern int TRKDoWriteMemory(TRKBuffer*); +extern int TRKDoReadRegisters(TRKBuffer*); +extern int TRKDoWriteRegisters(TRKBuffer*); +extern int TRKDoFlushCache(TRKBuffer*); +extern int TRKDoContinue(TRKBuffer*); +extern int TRKDoStep(TRKBuffer*); +extern int TRKDoStop(TRKBuffer*); + +struct DispatchEntry gTRKDispatchTable[33] = { + { &TRKDoUnsupported }, { &TRKDoConnect }, { &TRKDoDisconnect }, + { &TRKDoReset }, { &TRKDoVersions }, { &TRKDoSupportMask }, + { &TRKDoCPUType }, { &TRKDoUnsupported }, { &TRKDoUnsupported }, + { &TRKDoUnsupported }, { &TRKDoUnsupported }, { &TRKDoUnsupported }, + { &TRKDoUnsupported }, { &TRKDoUnsupported }, { &TRKDoUnsupported }, + { &TRKDoUnsupported }, { &TRKDoReadMemory }, { &TRKDoWriteMemory }, + { &TRKDoReadRegisters }, { &TRKDoWriteRegisters }, { &TRKDoUnsupported }, + { &TRKDoUnsupported }, { &TRKDoFlushCache }, { &TRKDoUnsupported }, + { &TRKDoContinue }, { &TRKDoStep }, { &TRKDoStop }, + { &TRKDoUnsupported }, { &TRKDoUnsupported }, { &TRKDoUnsupported }, + { &TRKDoUnsupported }, { &TRKDoUnsupported }, +}; + +DSError TRKInitializeDispatcher() { + gTRKDispatchTableSize = 32; + return DS_NoError; +} + +BOOL TRKDispatchMessage(TRKBuffer* buffer) { + DSError error; + u8 command; + + error = DS_DispatchError; + TRKSetBufferPosition(buffer, 0); + TRKReadBuffer1_ui8(buffer, &command); + if (command < gTRKDispatchTableSize) { + error = gTRKDispatchTable[command].fn(buffer); + } + return error; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/main_TRK.c b/src/TRK_MINNOW_DOLPHIN/Portable/main_TRK.c new file mode 100644 index 000000000..ab94a0422 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/main_TRK.c @@ -0,0 +1,21 @@ +/** + * main_TRK.c + * Description: + */ + +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/main_TRK.h" +#include "TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h" + +static DSError TRK_mainError; + +DSError TRK_main(void) { + TRK_mainError = TRKInitializeNub(); + + if (TRK_mainError == DS_NoError) { + TRKNubWelcome(); + TRKNubMainLoop(); + } + + TRK_mainError = TRKTerminateNub(); + return TRK_mainError; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/mainloop.c b/src/TRK_MINNOW_DOLPHIN/Portable/mainloop.c new file mode 100644 index 000000000..eb04b7fcd --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/mainloop.c @@ -0,0 +1,55 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h" +#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h" +#include "trk.h" + +void TRKNubMainLoop(void) { + void* msg; + TRKEvent event; + BOOL isShutdownRequested; + BOOL isNewInput; + + isShutdownRequested = FALSE; + isNewInput = FALSE; + while (isShutdownRequested == FALSE) { + if (TRKGetNextEvent(&event) != FALSE) { + isNewInput = FALSE; + + switch (event.eventType) { + case NUBEVENT_Null: + break; + + case NUBEVENT_Request: + msg = TRKGetBuffer(event.msgBufID); + TRKDispatchMessage(msg); + break; + + case NUBEVENT_Shutdown: + isShutdownRequested = TRUE; + break; + + case NUBEVENT_Breakpoint: + case NUBEVENT_Exception: + TRKTargetInterrupt(&event); + break; + + case NUBEVENT_Support: + TRKTargetSupportRequest(); + break; + } + + TRKDestructEvent(&event); + continue; + } + + if ((isNewInput == FALSE) || (*(u8*)gTRKInputPendingPtr != '\0')) { + isNewInput = TRUE; + TRKGetInput(); + continue; + } + + if (TRKTargetStopped() == FALSE) { + TRKTargetContinue(); + } + isNewInput = FALSE; + } +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/mem_TRK.c b/src/TRK_MINNOW_DOLPHIN/Portable/mem_TRK.c new file mode 100644 index 000000000..a30ab8c7a --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/mem_TRK.c @@ -0,0 +1,76 @@ +/** + * mem_TRK.c + * Description: + */ + +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mem_TRK.h" +#include + +#pragma dont_inline on +void TRK_fill_mem(void* dst, int val, u32 n) { + u32 v, i, j; + v = (u8)val; + + ((u8*)dst) = ((u8*)dst) - 1; + + if (n >= 32) { + i = (~(uintptr_t)dst) & 3; + + if (i) { + n -= i; + + do { + *++(((u8*)dst)) = v; + } while (--i); + } + + if (v) + v |= v << 24 | v << 16 | v << 8; + + ((u32*)dst) = ((u32*)(((u8*)dst) + 4)) - 1; + ((u32*)dst) = ((u32*)(((u8*)dst) + 1)) - 1; + + i = n / 32; + + if (i) { + do { + for (j = 0; j < 8; j++) + *++((u32*)dst) = v; + } while (--i); + } + + i = (n / 4) % 8; + + if (i) { + do { + *++((u32*)dst) = v; + } while (--i); + } + + ((u8*)dst) = ((u8*)(((u32*)dst) + 1)) - 1; + + n %= 4; + } + + if (n) + do { + *++((u8*)dst) = v; + } while (--n); +} +#pragma dont_inline reset + +__declspec(section ".init") void* TRK_memcpy(void* dst, const void* src, size_t n) { + const unsigned char* s = (const unsigned char*)src - 1; + unsigned char* d = (unsigned char*)dst - 1; + + n++; + while (--n != 0) + *++d = *++s; + return dst; +} + +__declspec(section ".init") void* TRK_memset(void* dst, int val, size_t n) { + TRK_fill_mem(dst, val, n); + + return dst; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/msg.c b/src/TRK_MINNOW_DOLPHIN/Portable/msg.c new file mode 100644 index 000000000..f66972d56 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/msg.c @@ -0,0 +1,12 @@ +/** + * msg.c + * Description: + */ + +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msg.h" +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/dolphin_trk_glue.h" +#include "trk.h" + +DSError TRKMessageSend(TRK_Msg* msg) { + return TRKWriteUARTN(&msg->m_msg, msg->m_msgLength); +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/msgbuf.c b/src/TRK_MINNOW_DOLPHIN/Portable/msgbuf.c new file mode 100644 index 000000000..459b0608b --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/msgbuf.c @@ -0,0 +1,329 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubinit.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/mutex_TRK.h" + +TRKBuffer gTRKMsgBufs[3]; + +void TRKSetBufferUsed(TRKBuffer* msg, BOOL state) { + msg->isInUse = state; +} + +DSError TRKInitializeMessageBuffers(void) { + int i; + for (i = 0; i < 3; i++) { + TRKInitializeMutex(&gTRKMsgBufs[i]); + TRKAcquireMutex(&gTRKMsgBufs[i]); + TRKSetBufferUsed(&gTRKMsgBufs[i], FALSE); + TRKReleaseMutex(&gTRKMsgBufs[i]); + } + + return DS_NoError; +} + +DSError TRKGetFreeBuffer(int* msgID, TRKBuffer** outMsg) { + TRKBuffer* buf; + DSError error = DS_NoMessageBufferAvailable; + int i; + + *outMsg = NULL; + + for (i = 0; i < 3; i++) { + buf = TRKGetBuffer(i); + + TRKAcquireMutex(buf); + if (!buf->isInUse) { + TRKResetBuffer(buf, TRUE); + TRKSetBufferUsed(buf, TRUE); + error = DS_NoError; + *outMsg = buf; + *msgID = i; + i = 3; // why not break? weird choice + } + TRKReleaseMutex(buf); + } + + if (error == DS_NoMessageBufferAvailable) { + usr_puts_serial("ERROR : No buffer available\n"); + } + + return error; +} + +void* TRKGetBuffer(int idx) { + TRKBuffer* buf = NULL; + if (idx >= 0 && idx < 3) { + buf = &gTRKMsgBufs[idx]; + } + + return buf; +} + +void TRKReleaseBuffer(int idx) { + TRKBuffer* msg; + if (idx != -1 && idx >= 0 && idx < 3) { + msg = &gTRKMsgBufs[idx]; + TRKAcquireMutex(msg); + TRKSetBufferUsed(msg, FALSE); + TRKReleaseMutex(msg); + } +} + +void TRKResetBuffer(TRKBuffer* msg, BOOL keepData) { + msg->length = 0; + msg->position = 0; + + if (!(u8)keepData) { + TRK_memset(msg->data, 0, 0x880); + } +} + +DSError TRKSetBufferPosition(TRKBuffer* msg, u32 pos) { + DSError error = DS_NoError; + + if (pos > 0x880) { + error = DS_MessageBufferOverflow; + } else { + msg->position = pos; + // If the new position is past the current length, + // update the length + if (pos > msg->length) { + msg->length = pos; + } + } + + return error; +} + +DSError TRKAppendBuffer(TRKBuffer* msg, const void* data, size_t length) { + DSError error = DS_NoError; // r31 + u32 bytesLeft; + + // Return if no bytes to append + if (length == 0) { + return DS_NoError; + } + + bytesLeft = 0x880 - msg->position; + + // If there isn't enough space left in the buffer, change the number + // of bytes to append to the remaning number of bytes + if (bytesLeft < length) { + error = DS_MessageBufferOverflow; + length = bytesLeft; + } + + if (length == 1) { + // If the length of bytes to append is 1, just copy the byte over + msg->data[msg->position] = ((u8*)data)[0]; + } else { + // Otherwise, use memcpy + TRK_memcpy(msg->data + msg->position, data, length); + } + + // Update the position and length + msg->position += length; + msg->length = msg->position; + + return error; +} + +DSError TRKReadBuffer(TRKBuffer* msg, void* data, size_t length) { + DSError error = DS_NoError; + unsigned int bytesLeft; // this has to be unsigned int not u32 to match lmfao. + + // Return if no bytes to read + if (length == 0) { + return DS_NoError; + } + + bytesLeft = msg->length - msg->position; + + // If the number of bytes to read exceeds the buffer length, change + // the length to the remaining number of bytes + if (length > bytesLeft) { + error = DS_MessageBufferReadError; + length = bytesLeft; + } + + TRK_memcpy(data, msg->data + msg->position, length); + msg->position += length; + return error; +} + +DSError TRKAppendBuffer1_ui16(TRKBuffer* buffer, const u16 data) { + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + + if (gTRKBigEndian) { + bigEndianData = (u8*)&data; + } else { + byteData = (u8*)&data; + bigEndianData = swapBuffer; + + bigEndianData[0] = byteData[1]; + bigEndianData[1] = byteData[0]; + } + + return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data)); +} + +DSError TRKAppendBuffer1_ui8(TRKBuffer* buffer, const u8 data) { + if (buffer->position >= 0x880) { + return DS_MessageBufferOverflow; + } + + buffer->data[buffer->position++] = data; + buffer->length++; + return DS_NoError; +} + +DSError TRKAppendBuffer1_ui32(TRKBuffer* buffer, const u32 data) { + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + + if (gTRKBigEndian) { + bigEndianData = (u8*)&data; + } else { + byteData = (u8*)&data; + bigEndianData = swapBuffer; + + bigEndianData[0] = byteData[3]; + bigEndianData[1] = byteData[2]; + bigEndianData[2] = byteData[1]; + bigEndianData[3] = byteData[0]; + } + + return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data)); +} + +DSError TRKAppendBuffer1_ui64(TRKBuffer* buffer, const u64 data) { + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + if (gTRKBigEndian) { + bigEndianData = (u8*)&data; + } else { + byteData = (u8*)&data; + bigEndianData = swapBuffer; + + bigEndianData[0] = byteData[7]; + bigEndianData[1] = byteData[6]; + bigEndianData[2] = byteData[5]; + bigEndianData[3] = byteData[4]; + bigEndianData[4] = byteData[3]; + bigEndianData[5] = byteData[2]; + bigEndianData[6] = byteData[1]; + bigEndianData[7] = byteData[0]; + } + + return TRKAppendBuffer(buffer, (const void*)bigEndianData, sizeof(data)); +} + +DSError TRKAppendBuffer_ui8(TRKBuffer* buffer, const u8* data, int count) { + DSError err; + int i; + + for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { + err = TRKAppendBuffer1_ui8(buffer, data[i]); + } + + return err; +} + +DSError TRKAppendBuffer_ui32(TRKBuffer* buffer, const u32* data, int count) { + DSError err; + int i; + + for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { + err = TRKAppendBuffer1_ui32(buffer, data[i]); + } + + return err; +} + +DSError TRKReadBuffer1_ui8(TRKBuffer* buffer, u8* data) { + return TRKReadBuffer(buffer, (void*)data, 1); +} + +DSError TRKReadBuffer1_ui32(TRKBuffer* buffer, u32* data) { + DSError err; + + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + + if (gTRKBigEndian) { + bigEndianData = (u8*)data; + } else { + bigEndianData = swapBuffer; + } + + err = TRKReadBuffer(buffer, (void*)bigEndianData, sizeof(*data)); + + if (!gTRKBigEndian && err == DS_NoError) { + byteData = (u8*)data; + + byteData[0] = bigEndianData[3]; + byteData[1] = bigEndianData[2]; + byteData[2] = bigEndianData[1]; + byteData[3] = bigEndianData[0]; + } + + return err; + // UNUSED FUNCTION +} + +DSError TRKReadBuffer1_ui64(TRKBuffer* buffer, u64* data) { + DSError err; + + u8* bigEndianData; + u8* byteData; + u8 swapBuffer[sizeof(data)]; + + if (gTRKBigEndian) { + bigEndianData = (u8*)data; + } else { + bigEndianData = swapBuffer; + } + + err = TRKReadBuffer(buffer, (void*)bigEndianData, sizeof(*data)); + + if (!gTRKBigEndian && err == 0) { + byteData = (u8*)data; + + byteData[0] = bigEndianData[7]; + byteData[1] = bigEndianData[6]; + byteData[2] = bigEndianData[5]; + byteData[3] = bigEndianData[4]; + byteData[4] = bigEndianData[3]; + byteData[5] = bigEndianData[2]; + byteData[6] = bigEndianData[1]; + byteData[7] = bigEndianData[0]; + } + + return err; +} + +DSError TRKReadBuffer_ui8(TRKBuffer* buffer, u8* data, int count) { + DSError err; + int i; + + for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { + err = TRKReadBuffer1_ui8(buffer, &(data[i])); + } + + return err; +} + +DSError TRKReadBuffer_ui32(TRKBuffer* buffer, u32* data, int count) { + DSError err; + s32 i; + + for (i = 0, err = DS_NoError; err == DS_NoError && i < count; i++) { + err = TRKReadBuffer1_ui32(buffer, &(data[i])); + } + + return err; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/msghndlr.c b/src/TRK_MINNOW_DOLPHIN/Portable/msghndlr.c new file mode 100644 index 000000000..a9ea18a6d --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/msghndlr.c @@ -0,0 +1,469 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msghndlr.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h" +#include "TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h" +#include "trk.h" +#include "string.h" + +static BOOL IsTRKConnected; + +BOOL GetTRKConnected(void) { + return IsTRKConnected; +} + +void SetTRKConnected(BOOL isTRKConnected) { + IsTRKConnected = isTRKConnected; +} + +DSError TRKSendACK(TRKBuffer* buffer) { + DSError err; + err = TRKMessageSend(buffer); + return err; +} + +DSError TRKStandardACK(TRKBuffer* buffer, MessageCommandID commandID, + DSReplyError replyError) { + CommandReply reply; + + memset(&reply, 0, sizeof(CommandReply)); + reply.commandID.b = commandID; + reply._00 = 0x40; + reply.replyError.b = replyError; + TRKWriteUARTN(&reply, sizeof(CommandReply)); + return DS_NoError; +} + +DSError TRKDoConnect(TRKBuffer* buffer) { + IsTRKConnected = TRUE; + return TRKStandardACK(buffer, 0x80, DSREPLY_NoError); +} + +DSError TRKDoDisconnect(TRKBuffer* buffer) { + TRKEvent event; + + IsTRKConnected = FALSE; + TRKStandardACK(buffer, 0x80, DSREPLY_NoError); + TRKConstructEvent(&event, 1); + TRKPostEvent(&event); + return DS_NoError; +} + +DSError TRKDoReset(TRKBuffer* buffer) { + TRKStandardACK(buffer, 0x80, DSREPLY_NoError); + __TRK_reset(); + return DS_NoError; +} + +DSError TRKDoOverride(TRKBuffer* buffer) { + TRKStandardACK(buffer, 0x80, DSREPLY_NoError); + __TRK_copy_vectors(); + return DS_NoError; +} + +DSError TRKDoVersions(TRKBuffer*) { + return DS_NoError; +} + +DSError TRKDoSupportMask(TRKBuffer*) { + return DS_NoError; +} + +DSError TRKDoReadMemory(TRKBuffer* buffer) { + u8 buf[0x820] ATTRIBUTE_ALIGN(32); + size_t tempLength; + int result; + int replyErr; + int options; + size_t length; + u32 start; + + start = *(u32*)(buffer->data + 16); + length = *(u16*)(buffer->data + 12); + options = buffer->data[8]; + + if (options & DSMSGMEMORY_Extended) { + return TRKStandardACK(buffer, DSMSG_ReplyACK, DSREPLY_UnsupportedOptionError); + } + + tempLength = length; + + if (options & DSMSGMEMORY_Space_data) { + result = TRKTargetAccessARAM(buf, start, &tempLength, TRUE); + } else { + result = TRKTargetAccessMemory(buf, start, &tempLength, + options & DSMSGMEMORY_Userview ? 0 : 1, TRUE); + } + + TRKResetBuffer(buffer, 0); + + if (result == DS_NoError) { + CommandReply reply; + memset(&reply, 0, sizeof(CommandReply)); + reply.replyError.b = result; + reply._00 = tempLength + 0x40; + reply.commandID.b = DSMSG_ReplyACK; + TRKAppendBuffer(buffer, &reply, sizeof(CommandReply)); + + if (options & 0x40) { + result = TRKAppendBuffer(buffer, buf + (start & 0x1F), tempLength); + } else { + result = TRKAppendBuffer(buffer, buf, tempLength); + } + } + + if (result) { + switch (result) { + case DS_CWDSException: + replyErr = DSREPLY_CWDSException; + break; + case DS_InvalidMemory: + replyErr = DSREPLY_InvalidMemoryRange; + break; + case DS_InvalidProcessID: + replyErr = DSREPLY_InvalidProcessID; + break; + case DS_InvalidThreadID: + replyErr = DSREPLY_InvalidThreadID; + break; + case DS_OSError: + replyErr = DSREPLY_OSError; + break; + default: + replyErr = DSREPLY_CWDSError; + break; + } + return TRKStandardACK(buffer, DSMSG_ReplyACK, replyErr); + } + + return TRKSendACK(buffer); +} + +DSError TRKDoWriteMemory(TRKBuffer* b) { + u8 buf[0x820] ATTRIBUTE_ALIGN(32); + size_t tempLength; + int options; + int result; + int replyErr; + size_t length; + u32 start; + + start = *(u32*)(&b->data[16]); + length = *(u16*)(&b->data[12]); + options = b->data[8]; + + if (options & DSMSGMEMORY_Extended) { + return TRKStandardACK(b, DSMSG_ReplyACK, DSMSG_ReadRegisters); + } + + tempLength = length; + + TRKSetBufferPosition(b, DSMSGMEMORY_Space_data); + if (options & DSMSGMEMORY_Space_data) { + TRKReadBuffer(b, buf + (start & 0x1f), tempLength); + result = TRKTargetAccessARAM(buf, start, &tempLength, FALSE); + } else { + TRKReadBuffer(b, buf, tempLength); + result = TRKTargetAccessMemory(buf, start, &tempLength, + options & DSMSGMEMORY_Userview ? 0 : 1, FALSE); + } + + TRKResetBuffer(b, 0); + + if (result == DS_NoError) { + CommandReply reply; + memset(&reply, 0, sizeof(CommandReply)); + reply._00 = 0x40; + reply.commandID.b = DSMSG_ReplyACK; + reply.replyError.b = result; + result = TRKAppendBuffer(b, &reply, sizeof(CommandReply)); + } + + if (result != DS_NoError) { + switch (result) { + case DS_CWDSException: + replyErr = DSREPLY_CWDSException; + break; + case DS_InvalidMemory: + replyErr = DSREPLY_InvalidMemoryRange; + break; + case DS_InvalidProcessID: + replyErr = DSREPLY_InvalidProcessID; + break; + case DS_InvalidThreadID: + replyErr = DSREPLY_InvalidThreadID; + break; + case DS_OSError: + replyErr = DSREPLY_OSError; + break; + default: + replyErr = DSREPLY_CWDSError; + break; + } + return TRKStandardACK(b, DSMSG_ReplyACK, replyErr); + } + + return TRKSendACK(b); +} + +DSError TRKDoReadRegisters(TRKBuffer* b) { + int error; + u8 options; + u16 firstRegister; + u16 lastRegister; + size_t registersLength; + CommandReply local_50; + + options = b->data[8]; + firstRegister = *(u16*)(b->data + 12); + lastRegister = *(u16*)(b->data + 16); + + if (firstRegister > lastRegister) { + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_InvalidRegisterRange); + } + + local_50.commandID.b = DSMSG_ReplyACK; + local_50._00 = 0x468; + + TRKResetBuffer(b, 0); + + TRKAppendBuffer_ui8(b, (u8*)&local_50, sizeof(CommandReply)); + + error = TRKTargetAccessDefault(0, 36, b, ®istersLength, TRUE); + + if (error == DS_NoError) { + error = TRKTargetAccessFP(0, 33, b, ®istersLength, TRUE); + } + if (error == DS_NoError) { + error = TRKTargetAccessExtended1(0, 0x60, b, ®istersLength, TRUE); + } + if (error == DS_NoError) { + error = TRKTargetAccessExtended2(0, 31, b, ®istersLength, TRUE); + } + + // Check if there was an error, and respond accordingly + if (error != DS_NoError) { + int replyError; + switch (error) { + case DS_UnsupportedError: + replyError = DSREPLY_UnsupportedOptionError; + break; + case DS_InvalidRegister: + replyError = DSREPLY_InvalidRegisterRange; + break; + case DS_CWDSException: + replyError = DSREPLY_CWDSException; + break; + case DS_InvalidProcessID: + replyError = DSREPLY_InvalidProcessID; + break; + case DS_InvalidThreadID: + replyError = DSREPLY_InvalidThreadID; + break; + case DS_OSError: + replyError = DSREPLY_OSError; + break; + default: + replyError = DSREPLY_CWDSError; + } + + return TRKStandardACK(b, DSMSG_ReplyACK, replyError); + } else { + // No error, send ack + return TRKSendACK(b); + } +} + +DSError TRKDoWriteRegisters(TRKBuffer* b) { + int error; + int replyError; + u8 options; + u16 firstRegister; + u16 lastRegister; + size_t registersLength; + + options = b->data[8]; + firstRegister = *(u16*)(b->data + 12); + lastRegister = *(u16*)(b->data + 16); + + TRKSetBufferPosition(b, 0); + + if (firstRegister > lastRegister) { + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_InvalidRegisterRange); + } + + TRKSetBufferPosition(b, 0x40); + + switch (options) { + case DSREG_Default: + error = TRKTargetAccessDefault(firstRegister, lastRegister, b, ®istersLength, FALSE); + break; + case DSREG_FP: + error = TRKTargetAccessFP(firstRegister, lastRegister, b, ®istersLength, FALSE); + break; + case DSREG_Extended1: + error = TRKTargetAccessExtended1(firstRegister, lastRegister, b, ®istersLength, FALSE); + break; + case DSREG_Extended2: + error = TRKTargetAccessExtended2(firstRegister, lastRegister, b, ®istersLength, FALSE); + break; + default: + // invalid option + error = DS_UnsupportedError; + break; + } + + TRKResetBuffer(b, 0); + + if (error == DS_NoError) { + CommandReply local_50; + memset(&local_50, 0, sizeof(CommandReply)); + local_50._00 = 0x40; + local_50.commandID.b = DSMSG_ReplyACK; + local_50.replyError.b = error; + error = TRKAppendBuffer(b, (u8*)&local_50, sizeof(CommandReply)); + } + + // Check if there was an error, and respond accordingly + if (error != DS_NoError) { + switch (error) { + case DS_UnsupportedError: + replyError = DSREPLY_UnsupportedOptionError; + break; + case DS_InvalidRegister: + replyError = DSREPLY_InvalidRegisterRange; + break; + case DS_MessageBufferReadError: + replyError = DSREPLY_PacketSizeError; + break; + case DS_CWDSException: + replyError = DSREPLY_CWDSException; + break; + case DS_InvalidProcessID: + replyError = DSREPLY_InvalidProcessID; + break; + case DS_InvalidThreadID: + replyError = DSREPLY_InvalidThreadID; + break; + case DS_OSError: + replyError = DSREPLY_OSError; + break; + default: + replyError = DSREPLY_CWDSError; + } + + return TRKStandardACK(b, DSMSG_ReplyACK, replyError); + } else { + // No error, send ack + return TRKSendACK(b); + } +} + +void TRKDoFlushCache(void) { + // UNUSED FUNCTION +} + +DSError TRKDoContinue(TRKBuffer*) { + if (!TRKTargetStopped()) { + u8 arr[0x40]; + memset(arr, 0, 0x40); + + arr[4] = 0x80; + *(u32*)arr = 0x40; + arr[8] = 0x16; + + TRKWriteUARTN(arr, 0x40); + return DS_NoError; + } else { + u8 arr[0x40]; + memset(arr, 0, 0x40); + + arr[4] = 0x80; + *(u32*)arr = 0x40; + arr[8] = 0x00; + + TRKWriteUARTN(arr, 0x40); + return TRKTargetContinue(); + } +} + +DSError TRKDoStep(TRKBuffer* b) { + DSError result; + u8 options; + u8 count; + u32 rangeStart; + u32 rangeEnd; + u32 pc; + TRKSetBufferPosition(b, 0); + + options = *(u8*)&b->data[8]; + rangeStart = *(u32*)&b->data[16]; + rangeEnd = *(u32*)&b->data[20]; + + switch (options) { + case DSSTEP_IntoCount: + case DSSTEP_OverCount: + count = b->data[12]; + if (count >= 1) { + break; + } + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_ParameterError); + case DSSTEP_IntoRange: + case DSSTEP_OverRange: + pc = TRKTargetGetPC(); + if (pc >= rangeStart && pc <= rangeEnd) { + break; + } + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_ParameterError); + default: + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_UnsupportedOptionError); + } + + if (!TRKTargetStopped()) { + return TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_NotStopped); + } else { + result = TRKStandardACK(b, DSMSG_ReplyACK, DSREPLY_NoError); + switch (options) { + case DSSTEP_IntoCount: + case DSSTEP_OverCount: + result = TRKTargetSingleStep(count, (options == DSSTEP_OverCount)); + break; + case DSSTEP_IntoRange: + case DSSTEP_OverRange: + result = TRKTargetStepOutOfRange(rangeStart, rangeEnd, (options == DSSTEP_OverRange)); + break; + } + + return result; + } +} + +DSError TRKDoStop(TRKBuffer* b) { + MessageCommandID c; + + switch (TRKTargetStop()) { + case DS_NoError: + c = DSMSG_Ping; + break; + case DS_InvalidProcessID: + c = '!'; + break; + case DS_InvalidThreadID: + c = '\"'; + break; + case DS_OSError: + c = ' '; + break; + default: + c = DSMSG_Connect; + break; + } + + TRKStandardACK(b, DSMSG_ReplyACK, c); + + return DS_NoError; +} + +DSError TRKDoSetOption(TRKBuffer* message) { + u8 enable = message->data[0xc]; + TRKStandardACK(message, DSMSG_ReplyACK, DS_NoError); + return 0; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/mutex_TRK.c b/src/TRK_MINNOW_DOLPHIN/Portable/mutex_TRK.c new file mode 100644 index 000000000..91fbed5a1 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/mutex_TRK.c @@ -0,0 +1,18 @@ +/** + * mutex_TRK.c + * Description: + */ + +#include "trk.h" + +DSError TRKInitializeMutex(void*) { + return DS_NoError; +} + +DSError TRKAcquireMutex(void*) { + return DS_NoError; +} + +DSError TRKReleaseMutex(void*) { + return DS_NoError; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/notify.c b/src/TRK_MINNOW_DOLPHIN/Portable/notify.c new file mode 100644 index 000000000..b27c77776 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/notify.c @@ -0,0 +1,28 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/notify.h" +#include "trk.h" + +DSError TRKDoNotifyStopped(MessageCommandID cmd) { + int reqIdx; + int bufIdx; + TRKBuffer* msg; + DSError err; + DSError bufError; + + bufError = TRKGetFreeBuffer(&bufIdx, &msg); + if ((err = bufError) == FALSE) { + if (err == DS_NoError) { + if (cmd == DSMSG_NotifyStopped) { + TRKTargetAddStopInfo(msg); + } else { + TRKTargetAddExceptionInfo(msg); + } + } + bufError = TRKRequestSend(msg, &reqIdx, 2, 3, 1); + err = bufError; + if (err == DS_NoError) { + TRKReleaseBuffer(reqIdx); + } + TRKReleaseBuffer(bufIdx); + } + return err; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/nubevent.c b/src/TRK_MINNOW_DOLPHIN/Portable/nubevent.c new file mode 100644 index 000000000..dde0b4bf6 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/nubevent.c @@ -0,0 +1,63 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h" + +TRKEventQueue gTRKEventQueue; + +DSError TRKInitializeEventQueue() { + TRKInitializeMutex(&gTRKEventQueue); + TRKAcquireMutex(&gTRKEventQueue); + gTRKEventQueue.count = 0; + gTRKEventQueue.next = 0; + gTRKEventQueue.eventID = 0x100; + TRKReleaseMutex(&gTRKEventQueue); + return DS_NoError; +} + +BOOL TRKGetNextEvent(TRKEvent* event) { + BOOL status = 0; + TRKAcquireMutex(&gTRKEventQueue); + if (0 < gTRKEventQueue.count) { + TRK_memcpy(event, &gTRKEventQueue.events[gTRKEventQueue.next], sizeof(TRKEvent)); + gTRKEventQueue.count--; + if (++gTRKEventQueue.next == 2) { + gTRKEventQueue.next = 0; + } + status = 1; + } + TRKReleaseMutex(&gTRKEventQueue); + return status; +} + +DSError TRKPostEvent(TRKEvent* event) { + DSError ret = DS_NoError; + int nextEventID; + + TRKAcquireMutex(&gTRKEventQueue); + + if (gTRKEventQueue.count == 2) { + ret = DS_EventQueueFull; + + } else { + nextEventID = (gTRKEventQueue.next + gTRKEventQueue.count) % 2; + TRK_memcpy(&gTRKEventQueue.events[nextEventID], event, sizeof(TRKEvent)); + gTRKEventQueue.events[nextEventID].eventID = gTRKEventQueue.eventID; + + if (++gTRKEventQueue.eventID < 0x100) { + gTRKEventQueue.eventID = 0x100; + } + + gTRKEventQueue.count++; + } + + TRKReleaseMutex(&gTRKEventQueue); + return ret; +} + +void TRKConstructEvent(TRKEvent* event, NubEventType eventType) { + event->eventType = eventType; + event->eventID = 0; + event->msgBufID = -1; +} + +void TRKDestructEvent(TRKEvent* event) { + TRKReleaseBuffer(event->msgBufID); +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/nubinit.c b/src/TRK_MINNOW_DOLPHIN/Portable/nubinit.c new file mode 100644 index 000000000..b3099f90d --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/nubinit.c @@ -0,0 +1,69 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubinit.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h" +#include "TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h" + +BOOL gTRKBigEndian; + +DSError TRKInitializeNub(void) { + DSError ret; + DSError uartErr; + + ret = TRKInitializeEndian(); + + if (ret == DS_NoError) { + usr_put_initialize(); + } + if (ret == DS_NoError) { + ret = TRKInitializeEventQueue(); + } + if (ret == DS_NoError) { + ret = TRKInitializeMessageBuffers(); + } + if (ret == DS_NoError) { + ret = TRKInitializeDispatcher(); + } + if (ret == DS_NoError) { + uartErr = TRKInitializeIntDrivenUART(0x0000e100, 1, 0, &gTRKInputPendingPtr); + TRKTargetSetInputPendingPtr(gTRKInputPendingPtr); + if (uartErr != DS_NoError) { + ret = uartErr; + } + } + if (ret == DS_NoError) { + ret = TRKInitializeSerialHandler(); + } + if (ret == DS_NoError) { + ret = TRKInitializeTarget(); + } + return ret; +} + +DSError TRKTerminateNub(void) { + TRKTerminateSerialHandler(); + return DS_NoError; +} + +void TRKNubWelcome(void) { + TRK_board_display("MetroTRK for GAMECUBE v0.10"); + return; +} + +BOOL TRKInitializeEndian(void) { + u8 bendian[4]; + BOOL result = FALSE; + gTRKBigEndian = TRUE; + + bendian[0] = 0x12; + bendian[1] = 0x34; + bendian[2] = 0x56; + bendian[3] = 0x78; + + if (*(u32*)bendian == 0x12345678) { + gTRKBigEndian = TRUE; + } else if (*(u32*)bendian == 0x78563412) { + gTRKBigEndian = FALSE; + } else { + result = TRUE; + } + return result; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/serpoll.c b/src/TRK_MINNOW_DOLPHIN/Portable/serpoll.c new file mode 100644 index 000000000..76043fef0 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/serpoll.c @@ -0,0 +1,79 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/serpoll.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/nubevent.h" +#include "trk.h" + +static TRKFramingState gTRKFramingState; + +void* gTRKInputPendingPtr; + +extern int TRKPollUART(void); + +MessageBufferID TRKTestForPacket() { + u8 payloadBuf[0x880]; + u8 packetBuf[0x40]; + int bufID; + TRKBuffer* msg; + MessageBufferID result; + + if (TRKPollUART() <= 0) { + return -1; + } + + result = TRKGetFreeBuffer(&bufID, &msg); + + TRKSetBufferPosition(msg, 0); + if (TRKReadUARTN(packetBuf, 0x40) == UART_NoError) { + int readSize; + + TRKAppendBuffer_ui8(msg, packetBuf, 0x40); + readSize = ((u32*)packetBuf)[0] - 0x40; + result = bufID; + if (readSize > 0) { + if (TRKReadUARTN(payloadBuf, ((u32*)packetBuf)[0] - 0x40) == UART_NoError) { + TRKAppendBuffer_ui8(msg, payloadBuf, ((u32*)packetBuf)[0]); + } else { + TRKReleaseBuffer(result); + result = -1; + } + } + } else { + TRKReleaseBuffer(result); + result = -1; + } + + return result; +} + +void TRKGetInput(void) { + MessageBufferID id = TRKTestForPacket(); + if (id != -1) { + TRKEvent event; + TRKGetBuffer(id); + TRKConstructEvent(&event, NUBEVENT_Request); + event.msgBufID = id; + gTRKFramingState.msgBufID = -1; + TRKPostEvent(&event); + } +} + +void TRKProcessInput(int bufferIdx) { + TRKEvent event; + + TRKConstructEvent(&event, NUBEVENT_Request); + event.msgBufID = bufferIdx; + gTRKFramingState.msgBufID = -1; + TRKPostEvent(&event); +} + +DSError TRKInitializeSerialHandler() { + gTRKFramingState.msgBufID = -1; + gTRKFramingState.receiveState = DSRECV_Wait; + gTRKFramingState.isEscape = FALSE; + + + return DS_NoError; +} + +DSError TRKTerminateSerialHandler(void) { + return DS_NoError; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/support.c b/src/TRK_MINNOW_DOLPHIN/Portable/support.c new file mode 100644 index 000000000..906623149 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/support.c @@ -0,0 +1,278 @@ +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/support.h" +#include "TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h" +#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h" +#include "string.h" + +DSError TRKSuppAccessFile(u32 file_handle, u8* data, size_t* count, DSIOResult* io_result, + BOOL need_reply, BOOL read) { + DSError error; + int replyBufferId; + TRKBuffer* replyBuffer; + u32 length; + int bufferId; + TRKBuffer* buffer; + u32 i; + u8 replyIOResult; + u32 replyLength; + BOOL exit; + CommandReply reply; + + if (data == NULL || *count == 0) { + return DS_ParameterError; + } + + exit = FALSE; + *io_result = DS_IONoError; + i = 0; + error = DS_NoError; + while (!exit && i < *count && error == DS_NoError && *io_result == 0) { + memset(&reply, 0, sizeof(CommandReply)); + + if (*count - i <= 0x800) { + length = *count - i; + } else { + length = 0x800; + } + + reply.commandID.b = read ? DSMSG_ReadFile : DSMSG_WriteFile; + + if (read) { + reply._00 = 0x40; + } else { + reply._00 = length + 0x40; + } + + reply.replyError.r = file_handle; + *(u16*)&reply._0C = length; + + TRKGetFreeBuffer(&bufferId, &buffer); + error = TRKAppendBuffer_ui8(buffer, (u8*)&reply, 0x40); + + if (!read && error == DS_NoError) { + error = TRKAppendBuffer_ui8(buffer, data + i, length); + } + + if (error == DS_NoError) { + if (need_reply) { + BOOL b = read && file_handle == 0; + + error = TRKRequestSend(buffer, &replyBufferId, read ? 5 : 5, 3, !b); + if (error == DS_NoError) { + replyBuffer = (TRKBuffer*)TRKGetBuffer(replyBufferId); + } + replyIOResult = *(u32*)(replyBuffer->data + 0x10); + replyLength = *(u16*)(replyBuffer->data + 0x14); + if (read && error == DS_NoError && replyLength <= length) { + TRKSetBufferPosition(replyBuffer, 0x40); + error = TRKReadBuffer_ui8(replyBuffer, data + i, replyLength); + if (error == DS_MessageBufferReadError) { + error = DS_NoError; + } + } + + if (replyLength != length) { + length = replyLength; + exit = TRUE; + } + + *io_result = (DSIOResult)replyIOResult; + TRKReleaseBuffer(replyBufferId); + } else { + error = TRKMessageSend(buffer); + } + } + + TRKReleaseBuffer(bufferId); + i += length; + } + + *count = i; + return error; +} + +DSError TRKRequestSend(TRKBuffer* msgBuf, int* bufferId, u32 p1, u32 p2, int p3) { + int error = DS_NoError; + TRKBuffer* buffer; + u32 counter; + int count; + u8 msgCmd; + int msgReplyError; + BOOL badReply = TRUE; + + *bufferId = -1; + + for (count = p2 + 1; count != 0 && *bufferId == -1 && error == DS_NoError; count--) { + error = TRKMessageSend(msgBuf); + if (error == DS_NoError) { + if (p3) { + counter = 0; + } + + while (TRUE) { + do { + *bufferId = TRKTestForPacket(); + if (*bufferId != -1) + break; + } while (!p3 || ++counter < 79999980); + + if (*bufferId == -1) + break; + + badReply = 0; + + buffer = TRKGetBuffer(*bufferId); + TRKSetBufferPosition(buffer, 0); + OutputData(&buffer->data[0], buffer->length); + msgCmd = buffer->data[4]; + + if (msgCmd >= DSMSG_ReplyACK) + break; + + TRKProcessInput(*bufferId); + *bufferId = -1; + } + + if (*bufferId != -1) { + if (buffer->length < 0x40) { + // OSReport("MetroTRK - bad reply size %ld\n", buffer->length); + badReply = TRUE; + } + if (error == DS_NoError && !badReply) { + msgReplyError = buffer->data[8]; + } + if (error == DS_NoError && !badReply) { + if ((int)msgCmd != DSMSG_ReplyACK || msgReplyError != 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, + DSIOResult* ioResult) { + DSError error; + int bufferId2; + int bufferId1; + TRKBuffer* tempBuffer; + TRKBuffer* buffer; + CommandReply reply; + + memset(&reply, 0, sizeof(CommandReply)); + *param_3 = 0; + reply.commandID.b = DSMSG_OpenFile; + reply._00 = strlen(path) + 0x40 + 1; + reply.replyError.b = replyError; + *(u16*)&reply._0C = strlen(path) + 1; + TRKGetFreeBuffer(&bufferId1, &buffer); + error = TRKAppendBuffer_ui8(buffer, (u8*)&reply, 0x40); + + if (error == DS_NoError) { + error = TRKAppendBuffer_ui8(buffer, (u8*)path, strlen(path) + 1); + } + + if (error == DS_NoError) { + *ioResult = DS_IONoError; + error = TRKRequestSend(buffer, &bufferId2, 7, 3, 0); + + if (error == DS_NoError) { + tempBuffer = TRKGetBuffer(bufferId2); + } + + *ioResult = *(u32*)(tempBuffer->data + 0x10); + *param_3 = *(u32*)(tempBuffer->data + 0x8); + TRKReleaseBuffer(bufferId2); + } + TRKReleaseBuffer(bufferId1); + return error; +} + +DSError HandleCloseFileSupportRequest(int replyError, DSIOResult* ioResult) { + DSError error; + int replyBufferId; + int bufferId; + TRKBuffer* buffer1; + TRKBuffer* buffer2; + CommandReply reply; + + memset(&reply, 0, sizeof(CommandReply)); + reply.commandID.b = DSMSG_CloseFile; + reply._00 = 0x40; + reply.replyError.r = replyError; + error = TRKGetFreeBuffer(&bufferId, &buffer1); + + if (error == DS_NoError) { + error = TRKAppendBuffer_ui8(buffer1, (u8*)&reply, sizeof(CommandReply)); + } + + if (error == DS_NoError) { + *ioResult = DS_IONoError; + error = TRKRequestSend(buffer1, &replyBufferId, 3, 3, 0); + + if (error == DS_NoError) { + buffer2 = TRKGetBuffer(replyBufferId); + } + + if (error == DS_NoError) { + *ioResult = *(u32*)(buffer2->data + 0x10); + } + + TRKReleaseBuffer(replyBufferId); + } + + TRKReleaseBuffer(bufferId); + return error; +} + +DSError HandlePositionFileSupportRequest(DSReplyError replyErr, u32* param_2, u8 param_3, + DSIOResult* ioResult) { + DSError error; + int bufferId2; + int bufferId1; + TRKBuffer* buffer1; + TRKBuffer* buffer2; + CommandReply reply; + + memset(&reply, 0, sizeof(CommandReply)); + reply.commandID.b = DSMSG_PositionFile; + reply._00 = 0x40; + reply.replyError.r = replyErr; + reply._0C = *param_2; + reply._10[0] = param_3; + error = TRKGetFreeBuffer(&bufferId1, &buffer1); + + if (error == DS_NoError) { + error = TRKAppendBuffer_ui8(buffer1, (u8*)&reply, sizeof(CommandReply)); + } + + if (error == DS_NoError) { + *ioResult = DS_IONoError; + *param_2 = -1; + error = TRKRequestSend(buffer1, &bufferId2, 3, 3, 0); + + if (error == DS_NoError) { + buffer2 = TRKGetBuffer(bufferId2); + + if (buffer2 != NULL) { + *ioResult = *(u32*)(buffer2->data + 0x10); + *param_2 = *(u32*)(buffer2->data + 0x18); + } + } + + TRKReleaseBuffer(bufferId2); + } + + TRKReleaseBuffer(bufferId1); + return error; +} diff --git a/src/TRK_MINNOW_DOLPHIN/Portable/usr_put.c b/src/TRK_MINNOW_DOLPHIN/Portable/usr_put.c new file mode 100644 index 000000000..f70141de3 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/Portable/usr_put.c @@ -0,0 +1,34 @@ +/** + * usr_put.c + * Description: + */ + +#include "TRK_MINNOW_DOLPHIN/Os/dolphin/usr_put.h" +// #include + +// void OSReport(char* fmt, ...) causes extra crclr instruction. +// look into issue later +extern void OSReport(char* fmt); + +BOOL usr_puts_serial(const char* msg) { + BOOL connect_ = FALSE; + char c; + char buf[2]; + + while (!connect_ && (c = *msg++) != '\0') { + BOOL connect = GetTRKConnected(); + + buf[0] = c; + buf[1] = '\0'; + + SetTRKConnected(FALSE); + OSReport(buf); + + SetTRKConnected(connect); + connect_ = FALSE; + } + + return connect_; +} + +void usr_put_initialize(void) {} diff --git a/src/TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s b/src/TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s new file mode 100644 index 000000000..0d3813d08 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/ppc/Export/targsupp.s @@ -0,0 +1,25 @@ +.include "macros.inc" +# .file "targsupp.s" + +.text +.balign 16 + +.fn TRKAccessFile, global + twui r0, 0x0 + blr +.endfn TRKAccessFile + +.fn TRKOpenFile, global + twui r0, 0x0 + blr +.endfn TRKOpenFile + +.fn TRKCloseFile, global + twui r0, 0x0 + blr +.endfn TRKCloseFile + +.fn TRKPositionFile, global + twui r0, 0x0 + blr +.endfn TRKPositionFile diff --git a/src/TRK_MINNOW_DOLPHIN/ppc/Generic/exception.s b/src/TRK_MINNOW_DOLPHIN/ppc/Generic/exception.s new file mode 100644 index 000000000..10b501532 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/ppc/Generic/exception.s @@ -0,0 +1,476 @@ +.include "macros.inc" + +.section .init, "ax" # 0x80003100 - 0x80005600 + +.global gTRKInterruptVectorTable +gTRKInterruptVectorTable: +.asciz "Metrowerks Target Resident Kernel for PowerPC" +.balign 4 +.fill 0xD0 + +############################################# +# Interrupt vector slot 0x0000 is reserved. # +############################################# + +# Slot 0x0100: System Reset Exception + b __TRK_reset +.fill 0xFC + +# Slot 0x0200: Machine Check Exception +/* 80003354 00000354 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003358 00000358 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 8000335C 0000035C 7C 00 17 AC */ icbi 0, r2 +/* 80003360 00000360 7C 53 02 A6 */ mfdar r2 +/* 80003364 00000364 7C 00 13 AC */ dcbi 0, r2 +/* 80003368 00000368 7C 51 42 A6 */ mfspr r2, 0x111 +/* 8000336C 0000036C 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003370 00000370 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003374 00000374 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003378 00000378 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 8000337C 0000037C 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003380 00000380 7C 60 00 A6 */ mfmsr r3 +/* 80003384 00000384 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003388 00000388 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 8000338C 0000038C 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003390 00000390 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003394 00000394 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003398 00000398 38 60 02 00 */ li r3, 0x200 +/* 8000339C 0000039C 4C 00 00 64 */ rfi +.fill 0xB4 + +# Slot 0x0300: DSI Exception +/* 80003454 00000454 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003458 00000458 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000345C 0000045C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003460 00000460 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003464 00000464 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003468 00000468 7C 60 00 A6 */ mfmsr r3 +/* 8000346C 0000046C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003470 00000470 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003474 00000474 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003478 00000478 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000347C 0000047C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003480 00000480 38 60 03 00 */ li r3, 0x300 +/* 80003484 00000484 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0400: ISI Exception +/* 80003554 00000554 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003558 00000558 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000355C 0000055C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003560 00000560 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003564 00000564 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003568 00000568 7C 60 00 A6 */ mfmsr r3 +/* 8000356C 0000056C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003570 00000570 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003574 00000574 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003578 00000578 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000357C 0000057C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003580 00000580 38 60 04 00 */ li r3, 0x400 +/* 80003584 00000584 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0500: External Interrupt Exception +/* 80003654 00000654 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003658 00000658 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000365C 0000065C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003660 00000660 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003664 00000664 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003668 00000668 7C 60 00 A6 */ mfmsr r3 +/* 8000366C 0000066C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003670 00000670 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003674 00000674 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003678 00000678 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000367C 0000067C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003680 00000680 38 60 05 00 */ li r3, 0x500 +/* 80003684 00000684 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0600: Alignment Exception +/* 80003754 00000754 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003758 00000758 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000375C 0000075C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003760 00000760 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003764 00000764 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003768 00000768 7C 60 00 A6 */ mfmsr r3 +/* 8000376C 0000076C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003770 00000770 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003774 00000774 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003778 00000778 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000377C 0000077C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003780 00000780 38 60 06 00 */ li r3, 0x600 +/* 80003784 00000784 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0700: Program Exception +/* 80003854 00000854 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003858 00000858 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000385C 0000085C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003860 00000860 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003864 00000864 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003868 00000868 7C 60 00 A6 */ mfmsr r3 +/* 8000386C 0000086C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003870 00000870 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003874 00000874 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003878 00000878 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000387C 0000087C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003880 00000880 38 60 07 00 */ li r3, 0x700 +/* 80003884 00000884 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0800: Floating Point Unavailable Exception +/* 80003954 00000954 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003958 00000958 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000395C 0000095C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003960 00000960 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003964 00000964 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003968 00000968 7C 60 00 A6 */ mfmsr r3 +/* 8000396C 0000096C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003970 00000970 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003974 00000974 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003978 00000978 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000397C 0000097C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003980 00000980 38 60 08 00 */ li r3, 0x800 +/* 80003984 00000984 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0900: Decrementer Exception +/* 80003A54 00000A54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003A58 00000A58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003A5C 00000A5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003A60 00000A60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003A64 00000A64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003A68 00000A68 7C 60 00 A6 */ mfmsr r3 +/* 80003A6C 00000A6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003A70 00000A70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003A74 00000A74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003A78 00000A78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003A7C 00000A7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003A80 00000A80 38 60 09 00 */ li r3, 0x900 +/* 80003A84 00000A84 4C 00 00 64 */ rfi +.fill 0xCC + +###################################################### +# Interrupt vector slots 0x0A00 & 0x0B00 are reserved. +.fill 0x100 +.fill 0x100 +###################################################### + +# Slot 0x0C00: System Call Exception +/* 80003D54 00000D54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003D58 00000D58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003D5C 00000D5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003D60 00000D60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003D64 00000D64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003D68 00000D68 7C 60 00 A6 */ mfmsr r3 +/* 80003D6C 00000D6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003D70 00000D70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003D74 00000D74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003D78 00000D78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003D7C 00000D7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003D80 00000D80 38 60 0C 00 */ li r3, 0xc00 +/* 80003D84 00000D84 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x0D00: Trace Exception +/* 80003E54 00000E54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003E58 00000E58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003E5C 00000E5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003E60 00000E60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003E64 00000E64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003E68 00000E68 7C 60 00 A6 */ mfmsr r3 +/* 80003E6C 00000E6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003E70 00000E70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003E74 00000E74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003E78 00000E78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003E7C 00000E7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003E80 00000E80 38 60 0D 00 */ li r3, 0xd00 +/* 80003E84 00000E84 4C 00 00 64 */ rfi +.fill 0xCC + +############################################################################ +# Slot 0x0E00 is usually for the Floating Point Assist Exception Handler, # +# however that exception is not implemented in the PPC 750CL architecture. # +############################################################################ + +# Slot 0x0F00: Performance Monitor Exception +/* 80003F54 00000F54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80003F58 00000F58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80003F5C 00000F5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80003F60 00000F60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80003F64 00000F64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80003F68 00000F68 7C 60 00 A6 */ mfmsr r3 +/* 80003F6C 00000F6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80003F70 00000F70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80003F74 00000F74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80003F78 00000F78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80003F7C 00000F7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80003F80 00000F80 38 60 0E 00 */ li r3, 0xe00 +/* 80003F84 00000F84 4C 00 00 64 */ rfi +.fill 0xCC + +################################################################################## +# Interrupt vector slots 0x1000 through 0x1200 are not implemented in the 750CL. # +################################################################################## + +# Slot 0x1300: Instruction Address Breakpoint Exception +/* 80004054 00001054 48 00 00 54 */ b .L_800040A8 +.fill 0x1C +/* 80004074 00001074 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004078 00001078 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000407C 0000107C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004080 00001080 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004084 00001084 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004088 00001088 7C 60 00 A6 */ mfmsr r3 +/* 8000408C 0000108C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004090 00001090 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004094 00001094 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004098 00001098 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000409C 0000109C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800040A0 000010A0 38 60 0F 20 */ li r3, 0xf20 +/* 800040A4 000010A4 4C 00 00 64 */ rfi +.L_800040A8: +/* 800040A8 000010A8 7C 51 43 A6 */ mtspr 0x111, r2 +/* 800040AC 000010AC 7C 72 43 A6 */ mtspr 0x112, r3 +/* 800040B0 000010B0 7C 93 43 A6 */ mtspr 0x113, r4 +/* 800040B4 000010B4 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 800040B8 000010B8 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 800040BC 000010BC 7C 60 00 A6 */ mfmsr r3 +/* 800040C0 000010C0 60 63 00 30 */ ori r3, r3, 0x30 +/* 800040C4 000010C4 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 800040C8 000010C8 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 800040CC 000010CC 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 800040D0 000010D0 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800040D4 000010D4 38 60 0F 00 */ li r3, 0xf00 +/* 800040D8 000010D8 4C 00 00 64 */ rfi +.fill 0x78 + +# Slot 0x1400: System Management Interrupt Exception +/* 80004154 00001154 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004158 00001158 7C 40 00 26 */ mfcr r2 +/* 8000415C 0000115C 7C 52 43 A6 */ mtspr 0x112, r2 +/* 80004160 00001160 7C 40 00 A6 */ mfmsr r2 +/* 80004164 00001164 74 42 00 02 */ andis. r2, r2, 2 +/* 80004168 00001168 41 82 00 1C */ beq .L_80004184 +/* 8000416C 0000116C 7C 40 00 A6 */ mfmsr r2 +/* 80004170 00001170 6C 42 00 02 */ xoris r2, r2, 2 +/* 80004174 00001174 7C 00 04 AC */ sync 0 +/* 80004178 00001178 7C 40 01 24 */ mtmsr r2 +/* 8000417C 0000117C 7C 00 04 AC */ sync 0 +/* 80004180 00001180 7C 51 43 A6 */ mtspr 0x111, r2 +.L_80004184: +/* 80004184 00001184 7C 52 42 A6 */ mfspr r2, 0x112 +/* 80004188 00001188 7C 4F F1 20 */ mtcrf 0xff, r2 +/* 8000418C 0000118C 7C 51 42 A6 */ mfspr r2, 0x111 +/* 80004190 00001190 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004194 00001194 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004198 00001198 7C 93 43 A6 */ mtspr 0x113, r4 +/* 8000419C 0000119C 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 800041A0 000011A0 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 800041A4 000011A4 7C 60 00 A6 */ mfmsr r3 +/* 800041A8 000011A8 60 63 00 30 */ ori r3, r3, 0x30 +/* 800041AC 000011AC 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 800041B0 000011B0 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 800041B4 000011B4 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 800041B8 000011B8 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800041BC 000011BC 38 60 10 00 */ li r3, 0x1000 +/* 800041C0 000011C0 4C 00 00 64 */ rfi +.fill 0x90 + + +############################################################################## +# Interrupt vector slots 0x1500 and 0x1600 are not implemented in the 750CL. # +############################################################################## + +# Slot 0x1700: Thermal-Management Interrupt Exception +/* 80004254 00001254 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004258 00001258 7C 40 00 26 */ mfcr r2 +/* 8000425C 0000125C 7C 52 43 A6 */ mtspr 0x112, r2 +/* 80004260 00001260 7C 40 00 A6 */ mfmsr r2 +/* 80004264 00001264 74 42 00 02 */ andis. r2, r2, 2 +/* 80004268 00001268 41 82 00 1C */ beq .L_80004284 +/* 8000426C 0000126C 7C 40 00 A6 */ mfmsr r2 +/* 80004270 00001270 6C 42 00 02 */ xoris r2, r2, 2 +/* 80004274 00001274 7C 00 04 AC */ sync 0 +/* 80004278 00001278 7C 40 01 24 */ mtmsr r2 +/* 8000427C 0000127C 7C 00 04 AC */ sync 0 +/* 80004280 00001280 7C 51 43 A6 */ mtspr 0x111, r2 +.L_80004284: +/* 80004284 00001284 7C 52 42 A6 */ mfspr r2, 0x112 +/* 80004288 00001288 7C 4F F1 20 */ mtcrf 0xff, r2 +/* 8000428C 0000128C 7C 51 42 A6 */ mfspr r2, 0x111 +/* 80004290 00001290 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004294 00001294 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004298 00001298 7C 93 43 A6 */ mtspr 0x113, r4 +/* 8000429C 0000129C 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 800042A0 000012A0 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 800042A4 000012A4 7C 60 00 A6 */ mfmsr r3 +/* 800042A8 000012A8 60 63 00 30 */ ori r3, r3, 0x30 +/* 800042AC 000012AC 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 800042B0 000012B0 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 800042B4 000012B4 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 800042B8 000012B8 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800042BC 000012BC 38 60 11 00 */ li r3, 0x1100 +/* 800042C0 000012C0 4C 00 00 64 */ rfi +.fill 0x90 + +# Slot 0x1800(?) +/* 80004354 00001354 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004358 00001358 7C 40 00 26 */ mfcr r2 +/* 8000435C 0000135C 7C 52 43 A6 */ mtspr 0x112, r2 +/* 80004360 00001360 7C 40 00 A6 */ mfmsr r2 +/* 80004364 00001364 74 42 00 02 */ andis. r2, r2, 2 +/* 80004368 00001368 41 82 00 1C */ beq .L_80004384 +/* 8000436C 0000136C 7C 40 00 A6 */ mfmsr r2 +/* 80004370 00001370 6C 42 00 02 */ xoris r2, r2, 2 +/* 80004374 00001374 7C 00 04 AC */ sync 0 +/* 80004378 00001378 7C 40 01 24 */ mtmsr r2 +/* 8000437C 0000137C 7C 00 04 AC */ sync 0 +/* 80004380 00001380 7C 51 43 A6 */ mtspr 0x111, r2 +.L_80004384: +/* 80004384 00001384 7C 52 42 A6 */ mfspr r2, 0x112 +/* 80004388 00001388 7C 4F F1 20 */ mtcrf 0xff, r2 +/* 8000438C 0000138C 7C 51 42 A6 */ mfspr r2, 0x111 +/* 80004390 00001390 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004394 00001394 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004398 00001398 7C 93 43 A6 */ mtspr 0x113, r4 +/* 8000439C 0000139C 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 800043A0 000013A0 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 800043A4 000013A4 7C 60 00 A6 */ mfmsr r3 +/* 800043A8 000013A8 60 63 00 30 */ ori r3, r3, 0x30 +/* 800043AC 000013AC 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 800043B0 000013B0 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 800043B4 000013B4 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 800043B8 000013B8 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 800043BC 000013BC 38 60 12 00 */ li r3, 0x1200 +/* 800043C0 000013C0 4C 00 00 64 */ rfi +.fill 0x90 + +# Slot 0x1900(?) +/* 80004454 00001454 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004458 00001458 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000445C 0000145C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004460 00001460 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004464 00001464 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004468 00001468 7C 60 00 A6 */ mfmsr r3 +/* 8000446C 0000146C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004470 00001470 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004474 00001474 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004478 00001478 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000447C 0000147C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004480 00001480 38 60 13 00 */ li r3, 0x1300 +/* 80004484 00001484 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x1A00(?) +/* 80004554 00001554 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004558 00001558 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000455C 0000155C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004560 00001560 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004564 00001564 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004568 00001568 7C 60 00 A6 */ mfmsr r3 +/* 8000456C 0000156C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004570 00001570 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004574 00001574 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004578 00001578 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000457C 0000157C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004580 00001580 38 60 14 00 */ li r3, 0x1400 +/* 80004584 00001584 4C 00 00 64 */ rfi +.fill 0x1CC + +# Slot 0x1B00(?) +/* 80004754 00001754 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004758 00001758 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000475C 0000175C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004760 00001760 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004764 00001764 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004768 00001768 7C 60 00 A6 */ mfmsr r3 +/* 8000476C 0000176C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004770 00001770 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004774 00001774 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004778 00001778 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000477C 0000177C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004780 00001780 38 60 16 00 */ li r3, 0x1600 +/* 80004784 00001784 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x1C00(?) +/* 80004854 00001854 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004858 00001858 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000485C 0000185C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004860 00001860 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004864 00001864 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004868 00001868 7C 60 00 A6 */ mfmsr r3 +/* 8000486C 0000186C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004870 00001870 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004874 00001874 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004878 00001878 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000487C 0000187C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004880 00001880 38 60 17 00 */ li r3, 0x1700 +/* 80004884 00001884 4C 00 00 64 */ rfi +.fill 0x4CC + +# Slot 0x1D00(?) +/* 80004D54 00001D54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004D58 00001D58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004D5C 00001D5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004D60 00001D60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004D64 00001D64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004D68 00001D68 7C 60 00 A6 */ mfmsr r3 +/* 80004D6C 00001D6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004D70 00001D70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004D74 00001D74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004D78 00001D78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80004D7C 00001D7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004D80 00001D80 38 60 1C 00 */ li r3, 0x1c00 +/* 80004D84 00001D84 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x1E00(?) +/* 80004E54 00001E54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004E58 00001E58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004E5C 00001E5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004E60 00001E60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004E64 00001E64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004E68 00001E68 7C 60 00 A6 */ mfmsr r3 +/* 80004E6C 00001E6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004E70 00001E70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004E74 00001E74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004E78 00001E78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80004E7C 00001E7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004E80 00001E80 38 60 1D 00 */ li r3, 0x1d00 +/* 80004E84 00001E84 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x1F00(?) +/* 80004F54 00001F54 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80004F58 00001F58 7C 72 43 A6 */ mtspr 0x112, r3 +/* 80004F5C 00001F5C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80004F60 00001F60 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80004F64 00001F64 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80004F68 00001F68 7C 60 00 A6 */ mfmsr r3 +/* 80004F6C 00001F6C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80004F70 00001F70 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80004F74 00001F74 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80004F78 00001F78 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 80004F7C 00001F7C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80004F80 00001F80 38 60 1E 00 */ li r3, 0x1e00 +/* 80004F84 00001F84 4C 00 00 64 */ rfi +.fill 0xCC + +# Slot 0x2000(?) +/* 80005054 00002054 7C 51 43 A6 */ mtspr 0x111, r2 +/* 80005058 00002058 7C 72 43 A6 */ mtspr 0x112, r3 +/* 8000505C 0000205C 7C 93 43 A6 */ mtspr 0x113, r4 +/* 80005060 00002060 7C 5A 02 A6 */ mfspr r2, 0x1a +/* 80005064 00002064 7C 9B 02 A6 */ mfspr r4, 0x1b +/* 80005068 00002068 7C 60 00 A6 */ mfmsr r3 +/* 8000506C 0000206C 60 63 00 30 */ ori r3, r3, 0x30 +/* 80005070 00002070 7C 7B 03 A6 */ mtspr 0x1b, r3 +/* 80005074 00002074 3C 60 80 0B */ lis r3, TRKInterruptHandler@h +/* 80005078 00002078 60 63 DE F4 */ ori r3, r3, TRKInterruptHandler@l +/* 8000507C 0000207C 7C 7A 03 A6 */ mtspr 0x1a, r3 +/* 80005080 00002080 38 60 1F 00 */ li r3, 0x1f00 +/* 80005084 00002084 4C 00 00 64 */ rfi +.global gTRKInterruptVectorTableEnd +gTRKInterruptVectorTableEnd: diff --git a/src/TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.c b/src/TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.c new file mode 100644 index 000000000..fcfbd12a3 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/ppc/Generic/flush_cache.c @@ -0,0 +1,30 @@ +/** + * flush_cache.c + * Description: + */ + +#include "dolphin/types.h" + +asm void TRK_flush_cache(u32, int) { + // clang-format off + nofralloc + + lis r5, 0xFFFF + ori r5, r5, 0xFFF1 + and r5, r5, r3 + subf r3, r5, r3 + add r4, r4, r3 + +loop: + dcbst 0, r5 + dcbf 0, r5 + sync + icbi 0, r5 + addic r5, r5, 8 + addic. r4, r4, -8 + bge loop + + isync + blr + // clang-format on +} diff --git a/src/TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.c b/src/TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.c new file mode 100644 index 000000000..98f676555 --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.c @@ -0,0 +1,244 @@ +#include "TRK_MINNOW_DOLPHIN/ppc/Generic/mpc_7xx_603e.h" +#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h" + +extern u8 gTRKRestoreFlags[9 + 3 /* padding */]; + +asm void TRKSaveExtended1Block() { + // 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) + blr + mfspr r25, 0x3d0 + mfspr r26, 0x3d1 + mfspr r27, 0x3d2 + mfspr r28, 0x3d3 + mfspr r29, 0x3D4 + mfspr r30, 0x3D5 + mfspr r31, 0x3d6 + stmw r25, 0x240(r2) + mfspr r31, 0x16 + stw r31, 0x278(r2) + blr + // clang-format on +} + +asm void TRKRestoreExtended1Block() { + // 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 + // clang-format on +} + +u8 TRKTargetCPUMinorType(void) { return 0x54; } diff --git a/src/TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.c b/src/TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.c new file mode 100644 index 000000000..5cb06ed9c --- /dev/null +++ b/src/TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.c @@ -0,0 +1,1144 @@ +#include "TRK_MINNOW_DOLPHIN/ppc/Generic/targimpl.h" +#include "TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h" +#include +#include "string.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 + 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; +TRKState gTRKState; +Default_PPC gTRKSaveState; +ProcessorState_PPC gTRKCPUState; + +typedef unsigned char u128[16]; +u128 TRKvalue128_temp; + +// Instruction macros +#define INSTR_NOP 0x60000000 +#define INSTR_BLR 0x4E800020 +#define INSTR_PSQ_ST(psr, offset, rDest, w, gqr) \ + (0xF0000000 | (psr << 21) | (rDest << 16) | (w << 15) | (gqr << 12) | offset) +#define INSTR_PSQ_L(psr, offset, rSrc, w, gqr) \ + (0xE0000000 | (psr << 21) | (rSrc << 16) | (w << 15) | (gqr << 12) | offset) +#define INSTR_STW(rSrc, offset, rDest) (0x90000000 | (rSrc << 21) | (rDest << 16) | offset) +#define INSTR_LWZ(rDest, offset, rSrc) (0x80000000 | (rDest << 21) | (rSrc << 16) | offset) +#define INSTR_STFD(fprSrc, offset, rDest) (0xD8000000 | (fprSrc << 21) | (rDest << 16) | offset) +#define INSTR_LFD(fprDest, offset, rSrc) (0xC8000000 | (fprDest << 21) | (rSrc << 16) | offset) +#define INSTR_MFSPR(rDest, spr) \ + (0x7C000000 | (rDest << 21) | ((spr & 0xFE0) << 6) | ((spr & 0x1F) << 16) | 0x2A6) +#define INSTR_MTSPR(spr, rSrc) \ + (0x7C000000 | (rSrc << 21) | ((spr & 0xFE0) << 6) | ((spr & 0x1F) << 16) | 0x3A6) + +#define DSFetch_u32(_p_) (*((u32*)_p_)) +#define DSFetch_u64(_p_) (*((u64*)_p_)) + +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(__REGISTER u32 msr); +u32 __TRK_get_MSR(); +void TRK_ppc_memcpy(__REGISTER void* dest, __REGISTER const void* src, __REGISTER int n, + __REGISTER u32 param_4, __REGISTER u32 param_5); + +void TRKRestoreExtended1Block(); +void TRKUARTInterruptHandler(); + +DSError TRKValidMemory32(const void* addr, size_t length, ValidMemoryOptions readWriteable) { + DSError err = DS_InvalidMemory; /* assume range is invalid */ + + const u8* start; + const u8* end; + + s32 i; + + /* + ** Get start and end addresses for the memory range and + ** verify that they are reasonable. + */ + + start = (const u8*)addr; + end = ((const u8*)addr + (length - 1)); + + if (end < start) + return DS_InvalidMemory; + + /* + ** Iterate through the gTRKMemMap array to determine if the requested + ** range falls within the valid ranges in the map. + */ + + for (i = 0; (i < (s32)(sizeof(gTRKMemMap) / sizeof(memRange))); i++) { + /* + ** If the requested range is not completely above + ** the valid range AND it is not completely below + ** the valid range then it must overlap somewhere. + ** If the requested range overlaps with one of the + ** valid ranges, do some additional checking. + ** + */ + + if ((start <= (const u8*)gTRKMemMap[i].end) && (end >= (const u8*)gTRKMemMap[i].start)) { + /* + ** First, verify that the read/write attributes are + ** acceptable. If so, then recursively check any + ** part of the requested range that falls before or + ** after the valid range. + */ + + if (((readWriteable == VALIDMEM_Readable) && !gTRKMemMap[i].readable) || + ((readWriteable == VALIDMEM_Writeable) && !gTRKMemMap[i].writeable)) + { + err = DS_InvalidMemory; + } else { + err = DS_NoError; + + /* + ** If a portion of the requested range falls before + ** the current valid range, then recursively + ** check it. + */ + + if (start < (const u8*)gTRKMemMap[i].start) + err = TRKValidMemory32(start, (uintptr_t)((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, + (uintptr_t)(end - (const u8*)gTRKMemMap[i].end), readWriteable); + } + + break; + } + } + + return err; +} + +DSError TRKTargetAccessMemory(void* data, u32 start, size_t* length, + MemoryAccessOptions accessOptions, BOOL read) { + DSError error; + u32 uVar5; + void* addr; + u32 param4; + TRKExceptionStatus tempExceptionStatus = gTRKExceptionStatus; + gTRKExceptionStatus.exceptionDetected = FALSE; + + addr = (void*)TRKTargetTranslate(start); + error = TRKValidMemory32(addr, *length, read == FALSE); + + if (error != DS_NoError) { + *length = 0; + } else { + uVar5 = __TRK_get_MSR(); + param4 = uVar5 | gTRKCPUState.Extended1.MSR & 0x10; + + if (read) { + TRK_ppc_memcpy(data, addr, *length, uVar5, param4); + } else { + TRK_ppc_memcpy(addr, data, *length, param4, uVar5); + TRK_flush_cache((uintptr_t)addr, *length); + if ((void*)start != addr) { + TRK_flush_cache(start, *length); + } + } + } + + if (gTRKExceptionStatus.exceptionDetected) { + *length = 0; + error = DS_CWDSException; + } + + gTRKExceptionStatus = tempExceptionStatus; + return error; +} + +DSError TRKTargetReadInstruction(void* data, u32 start) { + DSError error; + size_t registersLength = 4; + + error = TRKTargetAccessMemory(data, start, ®istersLength, MEMACCESS_UserMemory, TRUE); + + if (error == DS_NoError && registersLength != 4) { + error = DS_InvalidMemory; + } + + return error; +} + +DSError TRKTargetAccessDefault(u32 firstRegister, u32 lastRegister, 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; +} + +void TRKPostInterruptEvent(void) { + int eventType; + int local_14; + size_t registerSize; + TRKEvent event; + + if (gTRKState.inputActivated) { + gTRKState.inputActivated = FALSE; + } else { + switch (gTRKCPUState.Extended1.exceptionID & 0xFFFF) { + case 0xd00: + case 0x700: + registerSize = 4; + TRKTargetReadInstruction(&local_14, gTRKCPUState.Default.PC); + + if (local_14 == 0xfe00000) { + eventType = NUBEVENT_Support; + } else { + eventType = NUBEVENT_Breakpoint; + } + break; + default: + eventType = NUBEVENT_Exception; + break; + } + + TRKConstructEvent(&event, eventType); + TRKPostEvent(&event); + } +} + +DSError TRKTargetInterrupt(TRKEvent* event) { + DSError error = DS_NoError; + switch (event->eventType) { + case NUBEVENT_Breakpoint: + case NUBEVENT_Exception: + if (TRKTargetCheckStep() == FALSE) { + TRKTargetSetStopped(TRUE); + error = TRKDoNotifyStopped(DSMSG_NotifyStopped); + } + break; + default: + break; + } + + return error; +} + +u32* ConvertAddress(u32 addr) { + return (u32*)(addr | 0x80000000); +} +DSError TRKTargetAddStopInfo(TRKBuffer* b) { + DSError error; + CommandReply reply; + int t; + + memset(&reply, 0, 0x40); + reply._00 = 0x40; + reply.commandID.b = 0x90; + reply.replyError.r = gTRKCPUState.Default.PC; + TRKTargetReadInstruction(&t, gTRKCPUState.Default.PC); + + reply._0C = t; + *(u32*)reply._10 = gTRKCPUState.Extended1.exceptionID & 0xFFFF; + error = TRKAppendBuffer_ui8(b, (u8*)&reply, 0x40); + return error; +} + +void TRKTargetAddExceptionInfo(TRKBuffer* b) { + size_t local_58; + u32 local_54; + CommandReply reply; + + memset(&reply, 0, 0x40); + + reply._00 = 0x40; + reply.commandID.b = 0x91; + reply.replyError.r = gTRKExceptionStatus.exceptionInfo.PC; + + TRKTargetReadInstruction(&local_54, gTRKExceptionStatus.exceptionInfo.PC); + + reply._0C = local_54; + *(u32*)reply._10 = gTRKExceptionStatus.exceptionInfo.exceptionID; + + TRKAppendBuffer_ui8(b, (u8*)&reply, 0x40); +} + +inline DSError TRKTargetEnableTrace(BOOL val) { + if (val) { + gTRKCPUState.Extended1.MSR = (gTRKCPUState.Extended1.MSR | 0x400); + } else { + gTRKCPUState.Extended1.MSR = (gTRKCPUState.Extended1.MSR & ~0x400); + } + return DS_NoError; +} + +BOOL TRKTargetStepDone() { + BOOL result = TRUE; + + if (gTRKStepStatus.active && ((u16)gTRKCPUState.Extended1.exceptionID) == PPC_Trace) { + switch (gTRKStepStatus.type) { + case DSSTEP_IntoCount: + if (gTRKStepStatus.count > 0) { + result = FALSE; + } + break; + case DSSTEP_IntoRange: + if (gTRKCPUState.Default.PC >= gTRKStepStatus.rangeStart && + gTRKCPUState.Default.PC <= gTRKStepStatus.rangeEnd) + { + result = FALSE; + } + break; + default: + break; + } + } + + return result; +} + +inline DSError TRKTargetDoStep() { + gTRKStepStatus.active = TRUE; + MWTRACE(1, "TargetDoStep()\n"); + TRKTargetEnableTrace(TRUE); + + if (gTRKStepStatus.type == DSSTEP_IntoCount || gTRKStepStatus.type == DSSTEP_OverCount) { + gTRKStepStatus.count--; + } + + TRKTargetSetStopped(FALSE); + return DS_NoError; +} + +static BOOL TRKTargetCheckStep() { + if (gTRKStepStatus.active) { + TRKTargetEnableTrace(FALSE); + + if (TRKTargetStepDone()) { + gTRKStepStatus.active = FALSE; + } else { + TRKTargetDoStep(); + } + } + + return gTRKStepStatus.active; +} + +DSError TRKTargetSingleStep(u32 count, BOOL stepOver) { + DSError error = DS_NoError; + + if (stepOver) { + error = DS_UnsupportedError; + } else { + gTRKStepStatus.count = count; + gTRKStepStatus.type = DSSTEP_IntoCount; + error = TRKTargetDoStep(); + } + + return error; +} + +DSError TRKTargetStepOutOfRange(u32 rangeStart, u32 rangeEnd, BOOL stepOver) { + DSError error = DS_NoError; + + if (stepOver) { + // Stepping over isn't supported for PowerPC + error = DS_UnsupportedError; + } else { + gTRKStepStatus.type = DSSTEP_IntoRange; + // gTRKStepStatus.active = TRUE; + gTRKStepStatus.rangeStart = rangeStart; + gTRKStepStatus.rangeEnd = rangeEnd; + error = TRKTargetDoStep(); + } + + return error; +} + +u32 TRKTargetGetPC() { + return gTRKCPUState.Default.PC; +} + +DSError TRKTargetSupportRequest() { + DSIOResult ioResult; + size_t* length; + MessageCommandID commandId; + DSError error; + u32 local_28; + TRKEvent event; + + commandId = gTRKCPUState.Default.GPR[3]; + if (commandId != DSMSG_ReadFile && commandId != DSMSG_WriteFile && + commandId != DSMSG_OpenFile && commandId != DSMSG_CloseFile && + commandId != DSMSG_PositionFile) + { + TRKConstructEvent(&event, 4); + TRKPostEvent(&event); + return DS_NoError; + } else if (commandId == DSMSG_OpenFile) { + error = HandleOpenFileSupportRequest(gTRKCPUState.Default.GPR[4], + gTRKCPUState.Default.GPR[5] & 0xff, + gTRKCPUState.Default.GPR[6], &ioResult); + + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + + gTRKCPUState.Default.GPR[3] = ioResult; + } else if (commandId == DSMSG_CloseFile) { + error = HandleCloseFileSupportRequest(gTRKCPUState.Default.GPR[4], &ioResult); + + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + + gTRKCPUState.Default.GPR[3] = ioResult; + } else if (commandId == DSMSG_PositionFile) { + local_28 = *(u32*)gTRKCPUState.Default.GPR[5]; + error = HandlePositionFileSupportRequest(gTRKCPUState.Default.GPR[4], &local_28, + (u8)gTRKCPUState.Default.GPR[6], &ioResult); + + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + + gTRKCPUState.Default.GPR[3] = ioResult; + *(u32*)gTRKCPUState.Default.GPR[5] = local_28; + } else { + length = (size_t*)gTRKCPUState.Default.GPR[5]; + error = TRKSuppAccessFile(gTRKCPUState.Default.GPR[4], (u8*)gTRKCPUState.Default.GPR[6], + length, &ioResult, TRUE, commandId == DSMSG_ReadFile); + + if (ioResult == DS_IONoError && error != DS_NoError) { + ioResult = DS_IOError; + } + + gTRKCPUState.Default.GPR[3] = ioResult; + + if (commandId == DSMSG_ReadFile) { + TRK_flush_cache(gTRKCPUState.Default.GPR[6], *length); + } + } + + gTRKCPUState.Default.PC += 4; + return error; +} + +BOOL TRKTargetStopped() { + return gTRKState.isStopped; +} + +void TRKTargetSetStopped(unsigned int stopped) { + gTRKState.isStopped = stopped; +} + +u32 TRKTargetStop() { + gTRKState.isStopped = TRUE; + 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); +} + +DSError TRKPPCAccessFPRegister(void* srcDestPtr, u32 fpr, BOOL read) { + DSError error = DS_NoError; + // all nop by default + u32 instructionData1[] = {INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, + INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP, INSTR_NOP}; + + if (fpr < 0x20) { + if (read) { + instructionData1[0] = INSTR_STFD(fpr, 0, 3); // stfd fpr, 0(r3) + } else { + instructionData1[0] = INSTR_LFD(fpr, 0, 3); // lfd fpr, 0(r3) + } + + error = TRKPPCAccessSpecialReg(srcDestPtr, instructionData1, read); + } else if (fpr == 0x20) { + if (read) { + ReadFPSCR(srcDestPtr); + } else { + WriteFPSCR(srcDestPtr); + } + + *(u64*)srcDestPtr &= 0xFFFFFFFF; + } else if (fpr == 0x21) { + if (!read) { + *(u32*)srcDestPtr = *((u32*)(srcDestPtr) + 1); + } + + error = TRKPPCAccessSPR(srcDestPtr, SPR_FPECR, read); + if (read) { + DSFetch_u64(srcDestPtr) = DSFetch_u32(srcDestPtr) & 0xffffffffLL; + } + } + + return error; +} + +#define DEBUG_VECTORREG_ACCESS 0 + +DSError TRKPPCAccessSpecialReg(void* value, u32* access_func, BOOL read) { +#if defined(__MWERKS__) +#pragma unused(read) +#elif defined(__GNUC__) + UNUSED(read); +#endif + + typedef void (*asm_access_type)(void*, void*); + + asm_access_type asm_access; + + /* + ** Construct a small assembly function to perform the + ** requested access and call it. The read/write function + ** is in the form: + ** + ** + ** blr + */ + + /* + ** Put blr instruction at the end of access function (it should be + ** a 5-instruction array w/the last one empty). + */ + + access_func[9] = INSTR_BLR; + + /* + ** Now that the instruction array is built, get a function pointer to it. + */ + + asm_access = (asm_access_type)access_func; + +#if DEBUG_VECTORREG_ACCESS + + __puts("\r\nasm_access: "); + __puthex8((u32)asm_access); + __puts(" access_func: "); + __puthex8((u32)access_func); + + for (i = 0; i < 10; i++) { + __puts("\r\ninst["); + __puthex2(i); + __puts("]: "); + __puthex8(access_func[i]); + __puts(" ; "); + __puthex8(*((u32*)asm_access + i)); + } + + __puts("\r\n"); + +#endif + + // Flush cache + TRK_flush_cache((u32)access_func, (sizeof(access_func) * 10)); + (*asm_access)((u32*)value, (void*)&TRKvalue128_temp); + + return DS_NoError; +} + +void TRKTargetSetInputPendingPtr(void* ptr) { + gTRKState.inputPendingPtr = ptr; +} + +DSError TRKTargetAccessARAM(u32 p1, u32 p2, u32* p3, BOOL read) { + DSError err; + TRKExceptionStatus status; + + err = DS_NoError; + status = gTRKExceptionStatus; + + gTRKExceptionStatus.exceptionDetected = 0; + + if (read) { + TRK__read_aram(p1, p2, p3); + } else { + TRK__write_aram(p1, p2, p3); + } + + if (gTRKExceptionStatus.exceptionDetected) { + *p3 = 0; + err = 0x702; + } + gTRKExceptionStatus = status; + return err; +} + +asm u32 __TRK_get_MSR() { + // clang-format off + nofralloc + mfmsr r3 + blr + // clang-format on +} + +asm void __TRK_set_MSR(__REGISTER u32) { + // clang-format off + nofralloc + mtmsr r3 + blr + // clang-format on +} + +static asm void TRK_ppc_memcpy(__REGISTER void* dest, __REGISTER const void* src, __REGISTER int n, + __REGISTER u32 param_4, __REGISTER u32 param_5) { + // 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 + // clang-format on +} + +asm void TRKInterruptHandler() { + // 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 + // clang-format on +} + +static asm void TRKExceptionHandler(u16) { + // 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 + // clang-format on +} + +asm void TRKSwapAndGo() { + // 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 + // clang-format on +} + +asm void TRKInterruptHandlerEnableInterrupts(void) { + // 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 + // clang-format on +} + +asm void ReadFPSCR(__REGISTER f64*) { + // clang-format off + nofralloc + stwu r1, -0x40(r1) + stfd f31, 0x10(r1) + psq_st f31, 0x20(r1),0,0 + mffs f31 + stfd f31, 0x0(r3) + psq_l f31, 0x20(r1),0,0 + lfd f31, 0x10(r1) + addi r1, r1, 0x40 + blr + // clang-format on +} + +asm void WriteFPSCR(__REGISTER f64*) { + // clang-format off + nofralloc + stwu r1, -0x40(r1) + stfd f31, 0x10(r1) + psq_st f31, 0x20(r1), 0, 0 + lfd f31, 0(r3) + mtfsf 0xff, f31 + psq_l f31, 0x20(r1), 0, 0 + lfd f31, 0x10(r1) + addi r1, r1, 0x40 + blr + // clang-format on +} diff --git a/src/amcstubs/AmcExi2Stubs.c b/src/amcstubs/AmcExi2Stubs.c new file mode 100644 index 000000000..9091fda47 --- /dev/null +++ b/src/amcstubs/AmcExi2Stubs.c @@ -0,0 +1,28 @@ +#include "dolphin/amcstubs/AmcExi2Stubs.h" + +// prototypes +int AMC_IsStub(void); + +void EXI2_Init(volatile unsigned char **inputPendingPtrRef, AmcEXICallback monitorCallback) {} + +void EXI2_EnableInterrupts(void) {} + +int EXI2_Poll(void) { + return 0; +} + +AmcExiError EXI2_ReadN(void *bytes, unsigned long length) { + return AMC_EXI_NO_ERROR; +} + +AmcExiError EXI2_WriteN(const void *bytes, unsigned long length) { + return AMC_EXI_NO_ERROR; +} + +void EXI2_Reserve(void) {} + +void EXI2_Unreserve(void) {} + +int AMC_IsStub(void) { + return 1; +} diff --git a/src/dolphin/ai/ai.c b/src/dolphin/ai/ai.c new file mode 100644 index 000000000..deecab78d --- /dev/null +++ b/src/dolphin/ai/ai.c @@ -0,0 +1,334 @@ +#include "dolphin/os/OS.h" +#include "dolphin/gx/GX.h" +#include "dolphin/ai/ai.h" +#include "dolphin/dsp.h" + +const char* __AIVersion = "<< Dolphin SDK - AI\trelease build: Sep 5 2002 05:34:25 (0x2301) >>"; + +static AISCallback __AIS_Callback; +static AIDCallback __AID_Callback; +static u8* __CallbackStack; +static u8* __OldStack; +static BOOL __AI_init_flag; +static BOOL __AID_Active; +static OSTime bound_32KHz; +static OSTime bound_48KHz; +static OSTime min_wait; +static OSTime max_wait; +static OSTime buffer; + +// prototypes +void __AI_DEBUG_set_stream_sample_rate(u32 rate); + +static void __AI_set_stream_sample_rate(u32 rate); +static void __AIDHandler(__OSInterrupt interrupt, OSContext* context); +static void __AISHandler(__OSInterrupt interrupt, OSContext* context); +static void __AICallbackStackSwitch(void* cb); +static void __AI_SRC_INIT(void); + +AIDCallback AIRegisterDMACallback(AIDCallback callback) { + AIDCallback old_callback; + BOOL old; + + old_callback = __AID_Callback; + old = OSDisableInterrupts(); + __AID_Callback = callback; + OSRestoreInterrupts(old); + return old_callback; +} + +void AIInitDMA(u32 start_addr, u32 length) { + BOOL old; + + old = OSDisableInterrupts(); + __DSPRegs[24] = (__DSPRegs[24] & 0xFFFFFC00) | (start_addr >> 16); + __DSPRegs[25] = (__DSPRegs[25] & 0xFFFF001F) | (start_addr & 0xFFFF); + ASSERTMSGLINE(316, (length & 0x1F) == 0, "AIStartDMA: length must be multiple of 32 bytes"); + __DSPRegs[27] = (__DSPRegs[27] & 0xFFFF8000) | ((length >> 5) & 0xFFFF); + OSRestoreInterrupts(old); +} + +void AIStartDMA(void) { + __DSPRegs[27] = __DSPRegs[27] | 0x8000; +} + +void AIResetStreamSampleCount(void) { + __AIRegs[0] = (__AIRegs[0] & ~0x20) | 0x20; +} + +void AISetStreamTrigger(u32 trigger) { + __AIRegs[3] = trigger; +} + +void AISetStreamPlayState(u32 state) { + BOOL old; + u8 vol_left; + u8 vol_right; + + if (state != AIGetStreamPlayState()) { + if (AIGetStreamSampleRate() == 0 && state == 1) { + vol_left = AIGetStreamVolRight(); + vol_right = AIGetStreamVolLeft(); + AISetStreamVolRight(0); + AISetStreamVolLeft(0); + old = OSDisableInterrupts(); + __AI_SRC_INIT(); + SET_REG_FIELD(__AIRegs[0], 1, 5, 1); + SET_REG_FIELD(__AIRegs[0], 1, 0, 1); + OSRestoreInterrupts(old); + AISetStreamVolLeft(vol_left); + AISetStreamVolRight(vol_right); + return; + } + SET_REG_FIELD(__AIRegs[0], 1, 0, state); + } +} + +u32 AIGetStreamPlayState(void) { + return __AIRegs[0] & 1; +} + +void AISetDSPSampleRate(u32 rate) { + BOOL old; + u32 play_state; + u32 afr_state; + u8 vol_left; + u8 vol_right; + + if (rate != AIGetDSPSampleRate()) { + __AIRegs[0] = (__AIRegs[0] & 0xFFFFFFBF); + if (rate == 0) { + vol_left = AIGetStreamVolLeft(); + vol_right = AIGetStreamVolRight(); + play_state = AIGetStreamPlayState(); + afr_state = AIGetStreamSampleRate(); + AISetStreamVolLeft(0U); + AISetStreamVolRight(0U); + old = OSDisableInterrupts(); + __AI_SRC_INIT(); + SET_REG_FIELD(__AIRegs[0], 1, 5, 1); + SET_REG_FIELD(__AIRegs[0], 1, 1, afr_state); + SET_REG_FIELD(__AIRegs[0], 1, 0, play_state); + __AIRegs[0] |= 0x40; + OSRestoreInterrupts(old); + AISetStreamVolLeft(vol_left); + AISetStreamVolRight(vol_right); + } + } +} + +u32 AIGetDSPSampleRate(void) { + return ((__AIRegs[0] >> 6) & 1) ^ 1; +} + +void AISetStreamSampleRate(u32 rate) { + if (rate == 1) { + __AI_set_stream_sample_rate(rate); + return; + } +#if DEBUG + OSReport("AISetStreamSampleRate(): OBSOLETED. Only 48KHz streaming from disk is supported!\n"); +#endif +} + +static void __AI_set_stream_sample_rate(u32 rate) { + BOOL old; + u32 play_state; + u8 vol_left; + u8 vol_right; + u32 dsp_src_state; + + if (rate != AIGetStreamSampleRate()) { + play_state = AIGetStreamPlayState(); + vol_left = AIGetStreamVolLeft(); + vol_right = AIGetStreamVolRight(); + AISetStreamVolRight(0); + AISetStreamVolLeft(0); + dsp_src_state = __AIRegs[0] & 0x40; + SET_REG_FIELD(__AIRegs[0], 1, 6, 0); + old = OSDisableInterrupts(); + __AI_SRC_INIT(); + __AIRegs[0] |= dsp_src_state; + SET_REG_FIELD(__AIRegs[0], 1, 5, 1); + SET_REG_FIELD(__AIRegs[0], 1, 1, rate); + OSRestoreInterrupts(old); + AISetStreamPlayState(play_state); + AISetStreamVolLeft(vol_left); + AISetStreamVolRight(vol_right); + } +} + +u32 AIGetStreamSampleRate(void) { + return (__AIRegs[0] >> 1) & 1; +} + +void AISetStreamVolLeft(u8 vol) { + SET_REG_FIELD(__AIRegs[1], 8, 0, vol); +} + +u8 AIGetStreamVolLeft(void) { + return __AIRegs[1]; +} + +void AISetStreamVolRight(u8 vol) { + SET_REG_FIELD(__AIRegs[1], 8, 8, vol); +} + +u8 AIGetStreamVolRight(void) { + return (__AIRegs[1] & (0xFF << 8)) >> 8; +} + +void AIInit(u8* stack) { + if (__AI_init_flag != TRUE) { + OSRegisterVersion(__AIVersion); + + bound_32KHz = OSNanosecondsToTicks(31524); + bound_48KHz = OSNanosecondsToTicks(42024); + min_wait = OSNanosecondsToTicks(42000); + max_wait = OSNanosecondsToTicks(63000); + buffer = OSNanosecondsToTicks(3000); + AISetStreamVolRight(0); + AISetStreamVolLeft(0); + AISetStreamTrigger(0); + AIResetStreamSampleCount(); + __AI_set_stream_sample_rate(1); + AISetDSPSampleRate(0); +#if DEBUG + OSReport("AIInit(): DSP is 32KHz\n"); +#endif + __AIS_Callback = NULL; + __AID_Callback = NULL; + __CallbackStack = stack; + if (stack) { + ASSERTMSGLINE(1107, ((u32)stack & 7) == 0, "AIInit: stack must be 8-byte aligned"); + } + __OSSetInterruptHandler(5, __AIDHandler); + __OSUnmaskInterrupts(0x04000000); + __OSSetInterruptHandler(8, __AISHandler); + __OSUnmaskInterrupts(0x800000); + __AI_init_flag = TRUE; + } +} + +static void __AISHandler(__OSInterrupt interrupt, OSContext* context) { + OSContext exceptionContext; + + __AIRegs[0] |= 8; + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + if (__AIS_Callback) { + __AIS_Callback(__AIRegs[2]); + } + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +static void __AIDHandler(__OSInterrupt interrupt, OSContext* context) { + OSContext exceptionContext; + u16 tmp; + + tmp = __DSPRegs[5]; + tmp = (tmp & ~0xA0) | 8; + __DSPRegs[5] = tmp; + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + if (__AID_Callback && !__AID_Active) { + __AID_Active = TRUE; + if (__CallbackStack) { + __AICallbackStackSwitch(__AID_Callback); + } else { + __AID_Callback(); + } + __AID_Active = FALSE; + } + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +// clang-format off +static asm void __AICallbackStackSwitch(__REGISTER void* cb) { + nofralloc + mflr r0 + stw r0, 0x4(r1) + stwu r1, -0x18(r1) + stw r31, 0x14(r1) + mr r31, r3 + lis r5, __OldStack@ha + addi r5, r5, __OldStack@l + stw r1, 0x0(r5) + lis r5, __CallbackStack@ha + addi r5, r5, __CallbackStack@l + lwz r1, 0x0(r5) + subi r1, r1, 0x8 + mtlr r31 + blrl + lis r5, __OldStack@ha + addi r5, r5, __OldStack@l + lwz r1, 0x0(r5) + lwz r0, 0x1c(r1) + lwz r31, 0x14(r1) + addi r1, r1, 0x18 + mtlr r0 + blr +} +// clang-format on + +void __AI_SRC_INIT(void) { + OSTime rise32 = 0; + OSTime rise48 = 0; + OSTime diff = 0; + OSTime unused1 = 0; + OSTime temp = 0; + u32 temp0 = 0; + u32 temp1 = 0; + u32 done = 0; + u32 walking = 0; + u32 unused2 = 0; + u32 initCnt = 0; + + walking = 0; + initCnt = 0; + temp = 0; + + while (!done) { + __AIRegs[0] = (__AIRegs[0] & ~0x20) | 0x20; + __AIRegs[0] &= ~2; + __AIRegs[0] = (__AIRegs[0] & ~1) | 1; + + temp0 = __AIRegs[2]; + + while (temp0 == __AIRegs[2]) + ; + rise32 = OSGetTime(); + + __AIRegs[0] = (__AIRegs[0] & ~2) | 2; + __AIRegs[0] = (__AIRegs[0] & ~1) | 1; + + temp1 = __AIRegs[2]; + while (temp1 == __AIRegs[2]) + ; + + rise48 = OSGetTime(); + + diff = rise48 - rise32; + __AIRegs[0] &= ~2; + __AIRegs[0] &= ~1; + + if (diff < (bound_32KHz - buffer)) { + temp = min_wait; + done = 1; + ++initCnt; + } else if (diff >= (bound_32KHz + buffer) && diff < (bound_48KHz - buffer)) { + temp = max_wait; + done = 1; + ++initCnt; + } else { + done = 0; + walking = 1; + ++initCnt; + } + } + + while ((rise48 + temp) > OSGetTime()) + ; +} diff --git a/src/dolphin/ar/ar.c b/src/dolphin/ar/ar.c new file mode 100644 index 000000000..6173eb7f7 --- /dev/null +++ b/src/dolphin/ar/ar.c @@ -0,0 +1,342 @@ +#include "dolphin/os/OS.h" +#include "dolphin/ar/ar.h" +#include "dolphin/ar/arq.h" +#include "dolphin/dsp.h" + +const char* __ARVersion = "<< Dolphin SDK - AR\trelease build: Sep 5 2002 05:34:27 (0x2301) >>"; + +static void (*__AR_Callback)(); +static u32 __AR_Size; +static u32 __AR_InternalSize; +static u32 __AR_ExpansionSize; +static u32 __AR_StackPointer; +static u32 __AR_FreeBlocks; +static u32* __AR_BlockLength; +static BOOL __AR_init_flag; + +// prototypes +static void __ARHandler(__OSInterrupt exception, OSContext* context); +static void __ARWaitForDMA(void); +static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length); +static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length); +static void __ARChecksize(void); +static void __ARClearArea(u32 start_addr, u32 length); + +ARCallback ARRegisterDMACallback(ARCallback callback) { + ARCallback old_callback; + BOOL old; + + old_callback = __AR_Callback; + old = OSDisableInterrupts(); + __AR_Callback = callback; + OSRestoreInterrupts(old); + return old_callback; +} + +void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length) { + BOOL old; + + old = OSDisableInterrupts(); + ASSERTMSGLINE(376, !(__DSPRegs[5] & 0x200), "ARAM DMA already in progress\n"); + ASSERTMSGLINE(377, !(mainmem_addr & 0x1F), "AR: Main memory address is not a multiple of 32 bytes!\n"); + ASSERTMSGLINE(378, !(length & 0x1F), "AR: DMA transfer length is not a multiple of 32 bytes!\n"); + __DSPRegs[16] = (__DSPRegs[16] & 0xFFFFFC00 | (mainmem_addr >> 0x10)); + __DSPRegs[17] = (__DSPRegs[17] & 0xFFFF001F | ((u16)mainmem_addr)); + __DSPRegs[18] = (__DSPRegs[18] & 0xFFFFFC00 | (aram_addr >> 0x10)); + __DSPRegs[19] = (__DSPRegs[19] & 0xFFFF001F | ((u16)aram_addr)); + __DSPRegs[20] = __DSPRegs[20] & ~0x8000 | ((type << 0xF) & ~0x7FFF); + __DSPRegs[20] = (__DSPRegs[20] & 0xFFFFFC00) | (length >> 0x10); + __DSPRegs[21] = (__DSPRegs[21] & 0xFFFF001F) | (length & 0x0000FFFF); + OSRestoreInterrupts(old); +} + +u32 ARAlloc(u32 length) { + u32 tmp; + BOOL old; + + old = OSDisableInterrupts(); + ASSERTMSGLINE(430, !(length & 0x1F), "ARAlloc(): length is not multiple of 32bytes!"); + ASSERTMSGLINE(434, length <= (__AR_Size - __AR_StackPointer), "ARAlloc(): Out of ARAM!"); + ASSERTMSGLINE(435, __AR_FreeBlocks, "ARAlloc(): No more free blocks!"); + + tmp = __AR_StackPointer; + __AR_StackPointer += length; + *__AR_BlockLength = length; + __AR_BlockLength += 1; + __AR_FreeBlocks -= 1; + OSRestoreInterrupts(old); + return tmp; +} + +u32 ARInit(u32* stack_index_addr, u32 num_entries) { + BOOL old; + u16 refresh; + + if (__AR_init_flag == TRUE) { + return 0x4000; + } + + OSRegisterVersion(__ARVersion); + + old = OSDisableInterrupts(); + __AR_Callback = NULL; + __OSSetInterruptHandler(6, __ARHandler); + __OSUnmaskInterrupts(0x02000000); + __AR_StackPointer = 0x4000; + __AR_FreeBlocks = num_entries; + __AR_BlockLength = stack_index_addr; + refresh = __DSPRegs[13] & 0xFF; + + ASSERTMSGLINE(590, (refresh <= 196.0f), "ARInit(): ILLEGAL SDRAM REFRESH VALUE\n"); + __DSPRegs[13] = (u16)((__DSPRegs[13] & ~0xFF) | (refresh & 0xFF)); + + __ARChecksize(); + __AR_init_flag = TRUE; + OSRestoreInterrupts(old); + return __AR_StackPointer; +} + +u32 ARGetBaseAddress(void) { + return 0x4000; +} + +u32 ARGetSize(void) { + return __AR_Size; +} + +static void __ARHandler(__OSInterrupt exception, OSContext* context) { + OSContext exceptionContext; + u16 tmp; + + tmp = __DSPRegs[5]; + tmp = (tmp & ~0x88) | 0x20; + __DSPRegs[5] = (tmp); + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + if (__AR_Callback) { + __AR_Callback(); + } + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +void __ARClearInterrupt(void) { + u16 tmp; + + tmp = __DSPRegs[5]; + tmp = (tmp & ~0x88) | 0x20; + __DSPRegs[5] = (tmp); +} + +static void __ARWaitForDMA(void) { + while (__DSPRegs[5] & 0x200); +} + +static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length) { + // Main mem address + __DSPRegs[DSP_ARAM_DMA_MM_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_MM_HI] & ~0x03ff) | (u16)(mmem_addr >> 16)); + __DSPRegs[DSP_ARAM_DMA_MM_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_MM_LO] & ~0xffe0) | (u16)(mmem_addr & 0xffff)); + + // ARAM address + __DSPRegs[DSP_ARAM_DMA_ARAM_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_ARAM_HI] & ~0x03ff) | (u16)(aram_addr >> 16)); + __DSPRegs[DSP_ARAM_DMA_ARAM_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_ARAM_LO] & ~0xffe0) | (u16)(aram_addr & 0xffff)); + + // DMA buffer size + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)(__DSPRegs[DSP_ARAM_DMA_SIZE_HI] & ~0x8000); + + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_HI] & ~0x03ff) | (u16)(length >> 16)); + __DSPRegs[DSP_ARAM_DMA_SIZE_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_LO] & ~0xffe0) | (u16)(length & 0xffff)); + + __ARWaitForDMA(); + __ARClearInterrupt(); +} + +static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length) { + // Main mem address + __DSPRegs[DSP_ARAM_DMA_MM_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_MM_HI] & ~0x03ff) | (u16)(mmem_addr >> 16)); + __DSPRegs[DSP_ARAM_DMA_MM_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_MM_LO] & ~0xffe0) | (u16)(mmem_addr & 0xffff)); + + // ARAM address + __DSPRegs[DSP_ARAM_DMA_ARAM_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_ARAM_HI] & ~0x03ff) | (u16)(aram_addr >> 16)); + __DSPRegs[DSP_ARAM_DMA_ARAM_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_ARAM_LO] & ~0xffe0) | (u16)(aram_addr & 0xffff)); + + // DMA buffer size + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)(__DSPRegs[DSP_ARAM_DMA_SIZE_HI] | 0x8000); + + __DSPRegs[DSP_ARAM_DMA_SIZE_HI] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_HI] & ~0x03ff) | (u16)(length >> 16)); + __DSPRegs[DSP_ARAM_DMA_SIZE_LO] = (u16)((__DSPRegs[DSP_ARAM_DMA_SIZE_LO] & ~0xffe0) | (u16)(length & 0xffff)); + + __ARWaitForDMA(); + __ARClearInterrupt(); +} + +static void __ARChecksize(void) { + u8 test_data_pad[63]; + u8 dummy_data_pad[63]; + u8 buffer_pad[63]; + u8 save_pad_1[63]; + u8 save_pad_2[63]; + u8 save_pad_3[63]; + u8 save_pad_4[63]; + u8 save_pad_5[63]; + u32* test_data; + u32* dummy_data; + u32* buffer; + u32* save1; + u32* save2; + u32* save3; + u32* save4; + u32* save5; + u16 ARAM_mode = 0; + u32 ARAM_size = 0; + u32 i; + + do {} while(!(__DSPRegs[11] & 1)); + + ARAM_mode = 3; + ARAM_size = __AR_InternalSize = 0x1000000; + __DSPRegs[9] = ((__DSPRegs[9] & 0xFFFFFFC0) | 3) | 0x20; + + test_data = (u32*)(OSRoundUp32B((u32)(test_data_pad))); + dummy_data = (u32*)(OSRoundUp32B((u32)(dummy_data_pad))); + buffer = (u32*)(OSRoundUp32B((u32)(buffer_pad))); + + save1 = (u32*)(OSRoundUp32B((u32)(save_pad_1))); + save2 = (u32*)(OSRoundUp32B((u32)(save_pad_2))); + save3 = (u32*)(OSRoundUp32B((u32)(save_pad_3))); + save4 = (u32*)(OSRoundUp32B((u32)(save_pad_4))); + save5 = (u32*)(OSRoundUp32B((u32)(save_pad_5))); + + for (i = 0; i < 8; i++) { + *(test_data + i) = 0xDEADBEEF; + *(dummy_data + i) = 0xBAD0BAD0; + } + + DCFlushRange((void*)test_data, 0x20); + DCFlushRange((void*)dummy_data, 0x20); + + __AR_ExpansionSize = 0; + + DCInvalidateRange((void*)save1, 0x20); + __ARReadDMA((u32)save1, ARAM_size + 0, 0x20); + PPCSync(); + + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0000000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + DCInvalidateRange((void*)save2, 0x20); + __ARReadDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + PPCSync(); + + DCInvalidateRange((void*)save3, 0x20); + __ARReadDMA((u32)save3, ARAM_size + 0x1000000, 0x20); + PPCSync(); + + DCInvalidateRange((void*)save4, 0x20); + __ARReadDMA((u32)save4, ARAM_size + 0x0000200, 0x20); + PPCSync(); + + DCInvalidateRange((void*)save5, 0x20); + __ARReadDMA((u32)save5, ARAM_size + 0x0400000, 0x20); + PPCSync(); + + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x0200000, 0x20); + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0200000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + + ARAM_mode |= 0 << 1; + ARAM_size += 0x0200000; + __AR_ExpansionSize = 0x0200000; + } else { + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x1000000, 0x20); + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x1000000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + __ARWriteDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + + ARAM_mode |= 4 << 1; + ARAM_size += 0x0400000; + __AR_ExpansionSize = 0x0400000; + } else { + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x0000200, 0x20); + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0000200, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + __ARWriteDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + __ARWriteDMA((u32)save3, ARAM_size + 0x1000000, 0x20); + + ARAM_mode |= 8 << 1; + ARAM_size += 0x0800000; + __AR_ExpansionSize = 0x0800000; + } else { + __ARWriteDMA((u32)dummy_data, ARAM_size + 0x0400000, 0x20); + + __ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20); + + memset((void*)buffer, 0, 0x20); + DCFlushRange((void*)buffer, 0x20); + + __ARReadDMA((u32)buffer, ARAM_size + 0x0400000, 0x20); + PPCSync(); + + if (buffer[0] == test_data[0]) { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + __ARWriteDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + __ARWriteDMA((u32)save3, ARAM_size + 0x1000000, 0x20); + __ARWriteDMA((u32)save4, ARAM_size + 0x0000200, 0x20); + + ARAM_mode |= 12 << 1; + ARAM_size += 0x1000000; + __AR_ExpansionSize = 0x1000000; + } else { + __ARWriteDMA((u32)save1, ARAM_size + 0x0000000, 0x20); + __ARWriteDMA((u32)save2, ARAM_size + 0x0200000, 0x20); + __ARWriteDMA((u32)save3, ARAM_size + 0x1000000, 0x20); + __ARWriteDMA((u32)save4, ARAM_size + 0x0000200, 0x20); + __ARWriteDMA((u32)save5, ARAM_size + 0x0400000, 0x20); + + ARAM_mode |= 16 << 1; + ARAM_size += 0x2000000; + __AR_ExpansionSize = 0x2000000; + } + } + } + } + +#if DEBUG + OSReport("__ARChecksize(): ARAM Expansion present.\n"); +#endif + __DSPRegs[9] = (u16)((__DSPRegs[9] & ~(0x07 | 0x38)) | ARAM_mode); + } + + *(u32*)OSPhysicalToUncached(0x00D0) = ARAM_size; + __AR_Size = ARAM_size; +} diff --git a/src/dolphin/ar/arq.c b/src/dolphin/ar/arq.c new file mode 100644 index 000000000..d1848ff6b --- /dev/null +++ b/src/dolphin/ar/arq.c @@ -0,0 +1,140 @@ +#include "dolphin/os/OS.h" +#include "dolphin/ar/ar.h" +#include "dolphin/ar/arq.h" + +const char* __ARQVersion = "<< Dolphin SDK - ARQ\trelease build: Sep 5 2002 05:34:29 (0x2301) >>"; + +static ARQRequest* __ARQRequestQueueHi; +static ARQRequest* __ARQRequestTailHi; +static ARQRequest* __ARQRequestQueueLo; +static ARQRequest* __ARQRequestTailLo; +static ARQRequest* __ARQRequestPendingHi; +static ARQRequest* __ARQRequestPendingLo; +static ARQCallback __ARQCallbackHi; +static ARQCallback __ARQCallbackLo; +static u32 __ARQChunkSize; +static BOOL __ARQ_init_flag; + +void __ARQPopTaskQueueHi(void) { + if (__ARQRequestQueueHi) { + if (__ARQRequestQueueHi->type == 0) { + ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->source, __ARQRequestQueueHi->destination, __ARQRequestQueueHi->length); + } else { + ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->destination, __ARQRequestQueueHi->source, __ARQRequestQueueHi->length); + } + __ARQCallbackHi = __ARQRequestQueueHi->callback; + __ARQRequestPendingHi = __ARQRequestQueueHi; + __ARQRequestQueueHi = __ARQRequestQueueHi->next; + } +} + +void __ARQServiceQueueLo(void) { + if (__ARQRequestPendingLo == 0 && __ARQRequestQueueLo) { + __ARQRequestPendingLo = __ARQRequestQueueLo; + __ARQRequestQueueLo = __ARQRequestQueueLo->next; + } + + if (__ARQRequestPendingLo) { + if (__ARQRequestPendingLo->length <= __ARQChunkSize) { + if (__ARQRequestPendingLo->type == 0) { + ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->source, __ARQRequestPendingLo->destination, __ARQRequestPendingLo->length); + } else { + ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->destination, __ARQRequestPendingLo->source, __ARQRequestPendingLo->length); + } + __ARQCallbackLo = __ARQRequestPendingLo->callback; + } else if (__ARQRequestPendingLo->type == 0) { + ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->source, __ARQRequestPendingLo->destination, __ARQChunkSize); + } else { + ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->destination, __ARQRequestPendingLo->source, __ARQChunkSize); + } + + __ARQRequestPendingLo->length -= __ARQChunkSize; + __ARQRequestPendingLo->source += __ARQChunkSize; + __ARQRequestPendingLo->destination += __ARQChunkSize; + } +} + +void __ARQCallbackHack(u32 unused) {} + +void __ARQInterruptServiceRoutine() { + if (__ARQCallbackHi) { + __ARQCallbackHi((u32)__ARQRequestPendingHi); + __ARQRequestPendingHi = NULL; + __ARQCallbackHi = NULL; + } else if (__ARQCallbackLo) { + __ARQCallbackLo((u32)__ARQRequestPendingLo); + __ARQRequestPendingLo = NULL; + __ARQCallbackLo = NULL; + } + + __ARQPopTaskQueueHi(); + + if (__ARQRequestPendingHi == 0) { + __ARQServiceQueueLo(); + } +} + +void ARQInit(void) { + if (__ARQ_init_flag != TRUE) { + OSRegisterVersion(__ARQVersion); + + __ARQRequestQueueHi = __ARQRequestQueueLo = NULL; + __ARQChunkSize = 0x1000; + ARRegisterDMACallback(__ARQInterruptServiceRoutine); + __ARQRequestPendingHi = NULL; + __ARQRequestPendingLo = NULL; + __ARQCallbackHi = NULL; + __ARQCallbackLo = NULL; + __ARQ_init_flag = TRUE; + } +} + +void ARQPostRequest(ARQRequest* request, u32 owner, u32 type, u32 priority, u32 source, u32 dest, u32 length, ARQCallback callback) { + BOOL level; + + ASSERTLINE(437, request); + ASSERTLINE(438, (type == ARQ_TYPE_MRAM_TO_ARAM) || (type == ARQ_TYPE_ARAM_TO_MRAM)); + ASSERTLINE(439, (priority == ARQ_PRIORITY_LOW) || (priority == ARQ_PRIORITY_HIGH)); + ASSERTLINE(442, (length % ARQ_DMA_ALIGNMENT) == 0); + + request->next = NULL; + request->owner = owner; + request->type = type; + request->source = source; + request->destination = dest; + request->length = length; + if (callback) { + request->callback = callback; + } else { + request->callback = __ARQCallbackHack; + } + + level = OSDisableInterrupts(); + switch(priority) { + case ARQ_PRIORITY_LOW: + if (__ARQRequestQueueLo) { + __ARQRequestTailLo->next = request; + } else { + __ARQRequestQueueLo = request; + } + __ARQRequestTailLo = request; + break; + case ARQ_PRIORITY_HIGH: + if (__ARQRequestQueueHi) { + __ARQRequestTailHi->next = request; + } else { + __ARQRequestQueueHi = request; + } + __ARQRequestTailHi = request; + break; + } + + if ((__ARQRequestPendingHi == 0) && ( __ARQRequestPendingLo == 0)) { + __ARQPopTaskQueueHi(); + if ( __ARQRequestPendingHi == 0) { + __ARQServiceQueueLo(); + } + } + + OSRestoreInterrupts(level); +} diff --git a/src/dolphin/base/PPCArch.c b/src/dolphin/base/PPCArch.c new file mode 100644 index 000000000..a1bd8e98e --- /dev/null +++ b/src/dolphin/base/PPCArch.c @@ -0,0 +1,110 @@ +#include "dolphin/base/PPCArch.h" + +asm u32 PPCMfmsr() { + nofralloc + mfmsr r3 + blr +} + +asm void PPCMtmsr(__REGISTER u32 newMSR) { + nofralloc + mtmsr newMSR + blr +} + +asm u32 PPCMfhid0() { + nofralloc + mfspr r3, HID0 + blr +} + +asm void PPCMthid0(__REGISTER u32 newHID0) { + nofralloc + mtspr HID0, newHID0 + blr +} + +asm u32 PPCMfl2cr() { + nofralloc + mfspr r3, L2CR + blr +} + +asm void PPCMtl2cr(__REGISTER u32 newL2cr) { + nofralloc + mtspr L2CR, newL2cr + blr +} + +asm void PPCMtdec(__REGISTER u32 newDec) { + nofralloc + mtdec newDec + blr +} + +asm void PPCSync() { + nofralloc + sc + blr +} + +asm void PPCHalt() { + nofralloc + sync +loop: + nop + li r3, 0 + nop + b loop +} + +u32 PPCMffpscr() { + union FpscrUnion m; + + asm { + mffs fp31 + stfd fp31, m.f; + } + + return m.u.fpscr; +} + +void PPCMtfpscr(__REGISTER u32 newFPSCR) { + union FpscrUnion m; + + asm { + li r4, 0 + stw r4, m.u.fpscr_pad; + stw newFPSCR, m.u.fpscr + lfd fp31, m.f + mtfsf 0xff, fp31 + } +} + +asm u32 PPCMfhid2() { + nofralloc + mfspr r3, HID2 + blr +} + +asm void PPCMthid2(__REGISTER u32 newhid2) { + nofralloc + mtspr HID2, newhid2 + blr +} + +asm void PPCMtwpar(__REGISTER u32 newwpar) { + nofralloc + mtspr WPAR, newwpar + blr +} + +void PPCDisableSpeculation(void) { + PPCMthid0(PPCMfhid0() | HID0_SPD); +} + +asm void PPCSetFpNonIEEEMode() { + nofralloc + mtfsb1 29 + blr +} diff --git a/src/dolphin/card/CARDBios.c b/src/dolphin/card/CARDBios.c new file mode 100644 index 000000000..2dfccf305 --- /dev/null +++ b/src/dolphin/card/CARDBios.c @@ -0,0 +1,634 @@ +#include "dolphin/card.h" + +const char* __CARDVersion = "<< Dolphin SDK - CARD\trelease build: Sep 5 2002 05:35:20 (0x2301) >>"; + +CARDControl __CARDBlock[2]; + +static u16 __CARDEncode; + +DVDDiskID __CARDDiskNone; + +// prototypes +static void TimeoutHandler(OSAlarm* alarm, OSContext* context); +static void SetupTimeoutAlarm(CARDControl* card); +static s32 Retry(s32 chan); +static void UnlockedCallback(s32 chan, s32 result); +static BOOL OnReset(BOOL f); +s32 __CARDReadStatus(s32 chan, u8* status); +s32 __CARDClearStatus(s32 chan); +void __CARDSetDiskID(const DVDDiskID* id); + +void* __CARDGetFatBlock(CARDControl* card); +CARDDir* __CARDGetDirBlock(CARDControl* card); + +static OSResetFunctionInfo ResetFunctionInfo = {OnReset, 127}; + +void __CARDDefaultApiCallback(s32 chan, s32 result) {} + +void __CARDSyncCallback(s32 chan, s32 result) { + CARDControl* card; + card = &__CARDBlock[chan]; + OSWakeupThread(&card->threadQueue); +} + +void __CARDExtHandler(s32 chan, OSContext* context) { + CARDControl* card; + CARDCallback callback; + + ASSERTLINE(232, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (card->attached) { + ASSERTLINE(239, card->txCallback == 0); + card->attached = FALSE; + EXISetExiCallback(chan, 0); + OSCancelAlarm(&card->alarm); + callback = card->exiCallback; + + if (callback) { + card->exiCallback = 0; + callback(chan, CARD_RESULT_NOCARD); + } + + if (card->result != CARD_RESULT_BUSY) { + card->result = CARD_RESULT_NOCARD; + } + + callback = card->extCallback; + if (callback && CARD_MAX_MOUNT_STEP <= card->mountStep) { + card->extCallback = 0; + callback(chan, CARD_RESULT_NOCARD); + } + } +} + +void __CARDExiHandler(s32 chan, OSContext* context) { + CARDControl* card; + CARDCallback callback; + u8 status; + s32 result; + + ASSERTLINE(283, 0 <= chan && chan < 2); + card = &__CARDBlock[chan]; + + OSCancelAlarm(&card->alarm); + + if (!card->attached) { + return; + } + + if (!EXILock(chan, 0, 0)) { + result = CARD_RESULT_FATAL_ERROR; + goto fatal; + } + + if ((result = __CARDReadStatus(chan, &status)) < 0 || (result = __CARDClearStatus(chan)) < 0) { + goto error; + } + + if ((result = (status & 0x18) ? CARD_RESULT_IOERROR : CARD_RESULT_READY) == CARD_RESULT_IOERROR && + --card->retry > 0) + { + result = Retry(chan); + if (result >= 0) + { + return; + } + goto fatal; + } + +error: + EXIUnlock(chan); + +fatal: + callback = card->exiCallback; + if (callback) { + card->exiCallback = 0; + callback(chan, result); + } +} + +void __CARDTxHandler(s32 chan, OSContext* context) { + CARDControl* card; + CARDCallback callback; + int err; + + ASSERTLINE(365, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + err = !EXIDeselect(chan); + EXIUnlock(chan); + callback = card->txCallback; + if (callback) { + card->txCallback = NULL; + callback(chan, (!err && EXIProbe(chan)) ? CARD_RESULT_READY : CARD_RESULT_NOCARD); + } +} + +void __CARDUnlockedHandler(s32 chan, OSContext* context) { + CARDControl* card; + CARDCallback callback; + + ASSERTLINE(412, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + callback = card->unlockCallback; + if (callback) { + card->unlockCallback = 0; + callback(chan, EXIProbe(chan) ? CARD_RESULT_UNLOCKED : CARD_RESULT_NOCARD); + } +} + +s32 __CARDEnableInterrupt(s32 chan, BOOL enable) { + BOOL err; + u32 cmd; + + ASSERTLINE(431, 0 <= chan && chan < 2); + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = enable ? 0x81010000 : 0x81000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 2, EXI_WRITE, NULL); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +s32 __CARDReadStatus(s32 chan, u8* status) { + BOOL err; + u32 cmd; + + ASSERTLINE(450, 0 <= chan && chan < 2); + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = 0x83000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 2, EXI_WRITE, NULL); + err |= !EXISync(chan); + err |= !EXIImm(chan, status, 1, EXI_READ, NULL); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +s32 __CARDClearStatus(s32 chan) { + BOOL err; + u32 cmd; + + ASSERTLINE(492, 0 <= chan && chan < 2); + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = 0x89000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 1, EXI_WRITE, 0); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +static void TimeoutHandler(OSAlarm* alarm, OSContext* context) { + s32 chan; + CARDControl* card; + CARDCallback callback; + for (chan = 0; chan < 2; ++chan) { + card = &__CARDBlock[chan]; + if (alarm == &card->alarm) { + break; + } + } + + ASSERTLINE(578, 0 <= chan && chan < 2); + + if (!card->attached) { + return; + } + + EXISetExiCallback(chan, NULL); + callback = card->exiCallback; + if (callback) { + card->exiCallback = 0; + callback(chan, CARD_RESULT_IOERROR); + } +} + +static void SetupTimeoutAlarm(CARDControl* card) { + OSCancelAlarm(&card->alarm); + switch (card->cmd[0]) { + case 0xF2: + OSSetAlarm(&card->alarm, OSMillisecondsToTicks(100), + TimeoutHandler); + break; + case 0xF3: + break; + case 0xF4: + case 0xF1: + OSSetAlarm(&card->alarm, OSSecondsToTicks((OSTime)2) * (card->sectorSize / 0x2000), + TimeoutHandler); + break; + } +} + +static s32 Retry(s32 chan) { + CARDControl* card; + + ASSERTLINE(654, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!EXISelect(chan, 0, 4)) { + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + SetupTimeoutAlarm(card); + + if (!EXIImmEx(chan, card->cmd, card->cmdlen, EXI_WRITE)) { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + if (card->cmd[0] == 0x52 && + !EXIImmEx(chan, (u8* )card->workArea + sizeof(CARDID), card->latency, EXI_WRITE)) + { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + if (card->mode == 0xffffffff) { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_READY; + } + + if (!EXIDma(chan, card->buffer, (s32)((card->cmd[0] == 0x52) ? 512 : 128), card->mode, + __CARDTxHandler)) + { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + return CARD_RESULT_READY; +} + +static void UnlockedCallback(s32 chan, s32 result) { + CARDCallback callback; + CARDControl* card; + + ASSERTLINE(718, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (result >= 0) { + card->unlockCallback = UnlockedCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) { + result = CARD_RESULT_READY; + } else { + card->unlockCallback = 0; + result = Retry(chan); + } + } + + if (result < 0) { + switch (card->cmd[0]) { + case 0x52: + callback = card->txCallback; + if (callback) { + card->txCallback = NULL; + callback(chan, result); + } + break; + case 0xF2: + case 0xF4: + case 0xF1: + callback = card->exiCallback; + if (callback) { + card->exiCallback = 0; + callback(chan, result); + } + break; + } + } +} + +static s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallback) { + BOOL enabled; + CARDControl* card; + s32 result; + + enabled = OSDisableInterrupts(); + + ASSERTLINE(784, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!card->attached) { + result = CARD_RESULT_NOCARD; + } else { + if (txCallback) { + card->txCallback = txCallback; + } + + if (exiCallback) { + card->exiCallback = exiCallback; + } + + card->unlockCallback = UnlockedCallback; + + if (!EXILock(chan, 0, __CARDUnlockedHandler)) { + result = CARD_RESULT_BUSY; + } else { + card->unlockCallback = 0; + + if (!EXISelect(chan, 0, 4)) { + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } else { + SetupTimeoutAlarm(card); + result = CARD_RESULT_READY; + } + } + } + + OSRestoreInterrupts(enabled); + return result; +} + +#define AD1(x) ((u8)(((x) >> 17) & 0x7f)) +#define AD1EX(x) ((u8)(AD1(x) | 0x80)); +#define AD2(x) ((u8)(((x) >> 9) & 0xff)) +#define AD3(x) ((u8)(((x) >> 7) & 0x03)) +#define BA(x) ((u8)((x)&0x7f)) + +s32 __CARDReadSegment(s32 chan, CARDCallback callback) { + CARDControl* card; + s32 result; + + ASSERTLINE(846, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + ASSERTLINE(848, card->addr % CARD_SEG_SIZE == 0); + ASSERTLINE(849, card->addr < (u32) card->size * 1024 * 1024 / 8); + + card->cmd[0] = 0x52; + card->cmd[1] = AD1(card->addr); + card->cmd[2] = AD2(card->addr); + card->cmd[3] = AD3(card->addr); + card->cmd[4] = BA(card->addr); + card->cmdlen = 5; + card->mode = 0; + card->retry = 0; + + result = __CARDStart(chan, callback, 0); + if (result == CARD_RESULT_BUSY) { + result = CARD_RESULT_READY; + } else if (result >= 0) { + if (!EXIImmEx(chan, card->cmd, card->cmdlen, EXI_WRITE) || + !EXIImmEx(chan, (u8* )card->workArea + sizeof(CARDID), card->latency, + EXI_WRITE) || // XXX use DMA if possible + !EXIDma(chan, card->buffer, 512, card->mode, __CARDTxHandler)) + { + card->txCallback = NULL; + EXIDeselect(chan); + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } else { + result = CARD_RESULT_READY; + } + } + + return result; +} + +s32 __CARDWritePage(s32 chan, CARDCallback callback) { + CARDControl* card; + s32 result; + + ASSERTLINE(903, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + ASSERTLINE(905, card->addr % card->pageSize == 0); + ASSERTLINE(906, card->addr < (u32) card->size * 1024 * 1024 / 8); + card->cmd[0] = 0xF2; + card->cmd[1] = AD1(card->addr); + card->cmd[2] = AD2(card->addr); + card->cmd[3] = AD3(card->addr); + card->cmd[4] = BA(card->addr); + card->cmdlen = 5; + card->mode = 1; + card->retry = 3; + + result = __CARDStart(chan, 0, callback); + if (result == CARD_RESULT_BUSY) { + result = CARD_RESULT_READY; + } else if (result >= 0) { + if (!EXIImmEx(chan, card->cmd, card->cmdlen, EXI_WRITE) || + !EXIDma(chan, card->buffer, 128, card->mode, __CARDTxHandler)) + { + card->exiCallback = 0; + EXIDeselect(chan); + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } else { + result = CARD_RESULT_READY; + } + } + + return result; +} + +s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback) { + CARDControl* card; + s32 result; + + ASSERTLINE(1010, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + ASSERTLINE(1012, addr % card->sectorSize == 0); + ASSERTLINE(1013, addr < (u32) card->size * 1024 * 1024 / 8); + + card->cmd[0] = 0xF1; + card->cmd[1] = AD1(addr); + card->cmd[2] = AD2(addr); + card->cmdlen = 3; + card->mode = -1; + card->retry = 3; + + result = __CARDStart(chan, 0, callback); + + if (result == CARD_RESULT_BUSY) { + result = CARD_RESULT_READY; + } else if (result >= 0) { + if (!EXIImmEx(chan, card->cmd, card->cmdlen, EXI_WRITE)) { + result = CARD_RESULT_NOCARD; + card->exiCallback = NULL; + } else { + result = CARD_RESULT_READY; + } + + EXIDeselect(chan); + EXIUnlock(chan); + } + return result; +} + +void CARDInit(void) { + int chan; + + if (__CARDBlock[0].diskID && __CARDBlock[1].diskID) { + return; + } + + __CARDEncode = OSGetFontEncode(); + + OSRegisterVersion(__CARDVersion); + + DSPInit(); + OSInitAlarm(); + + for (chan = 0; chan < 2; ++chan) { + CARDControl* card = &__CARDBlock[chan]; + + card->result = CARD_RESULT_NOCARD; + OSInitThreadQueue(&card->threadQueue); + OSCreateAlarm(&card->alarm); + } + __CARDSetDiskID((void*)OSPhysicalToCached(0)); + + OSRegisterResetFunction(&ResetFunctionInfo); +} + +u16 __CARDGetFontEncode(void) { + return __CARDEncode; +} + +void __CARDSetDiskID(const DVDDiskID* id) { + __CARDBlock[0].diskID = id ? id : &__CARDDiskNone; + __CARDBlock[1].diskID = id ? id : &__CARDDiskNone; +} + +s32 __CARDGetControlBlock(s32 chan, CARDControl** pcard) { + BOOL enabled; + s32 result; + CARDControl* card; + + card = &__CARDBlock[chan]; + + if (chan < 0 || chan >= 2 || card->diskID == 0) { + return CARD_RESULT_FATAL_ERROR; + } + + enabled = OSDisableInterrupts(); + + if (!card->attached) { + result = CARD_RESULT_NOCARD; + } else if (card->result == CARD_RESULT_BUSY) { + result = CARD_RESULT_BUSY; + } else { + card->result = CARD_RESULT_BUSY; + result = CARD_RESULT_READY; + card->apiCallback = NULL; + *pcard = card; + } + + OSRestoreInterrupts(enabled); + return result; +} + +s32 __CARDPutControlBlock(CARDControl* card, s32 result) { + BOOL enabled; + + ASSERTLINE(1259, result != CARD_RESULT_BUSY); + + enabled = OSDisableInterrupts(); + if (card->attached) { + card->result = result; + } else if (card->result == CARD_RESULT_BUSY) { + card->result = result; + } + + OSRestoreInterrupts(enabled); + return result; +} + +s32 CARDGetResultCode(s32 chan) { + CARDControl* card; + + ASSERTLINE(1292, 0 <= chan && chan < 2); + + if (chan < 0 || chan >= 2) { + return CARD_RESULT_FATAL_ERROR; + } + card = &__CARDBlock[chan]; + return card->result; +} + +s32 CARDFreeBlocks(s32 chan, s32* byteNotUsed, s32* filesNotUsed) { + CARDControl* card; + s32 result; + u16* fat; + CARDDir* dir; + CARDDir* ent; + u16 fileNo; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + + fat = __CARDGetFatBlock(card); + dir = __CARDGetDirBlock(card); + if (fat == 0 || dir == 0) { + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + if (byteNotUsed) { + *byteNotUsed = (s32)(card->sectorSize * fat[CARD_FAT_FREEBLOCKS]); + } + + if (filesNotUsed) { + *filesNotUsed = 0; + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) { + ent = &dir[fileNo]; + if (ent->fileName[0] == 0xff) { + ++*filesNotUsed; + } + } + } + + return __CARDPutControlBlock(card, CARD_RESULT_READY); +} + +s32 __CARDSync(s32 chan) { + CARDControl* block; + s32 result; + s32 enabled; + + block = &__CARDBlock[chan]; + enabled = OSDisableInterrupts(); + while ((result = CARDGetResultCode(chan)) == CARD_RESULT_BUSY) { + OSSleepThread(&block->threadQueue); + } + + OSRestoreInterrupts(enabled); + return result; +} + +static BOOL OnReset(BOOL final) { + if (!final) { + if (CARDUnmount(0) == CARD_RESULT_BUSY || CARDUnmount(1) == CARD_RESULT_BUSY) { + return FALSE; + } + } + + return TRUE; +} diff --git a/src/dolphin/card/CARDBlock.c b/src/dolphin/card/CARDBlock.c new file mode 100644 index 000000000..1f2649308 --- /dev/null +++ b/src/dolphin/card/CARDBlock.c @@ -0,0 +1,134 @@ +#include "dolphin/card.h" + +// prototypes +static void WriteCallback(s32 chan, s32 result); +static void EraseCallback(s32 chan, s32 result); +s32 __CARDUpdateFatBlock(s32 chan, u16* fat, CARDCallback callback); + +void* __CARDGetFatBlock(CARDControl* card) { + ASSERTLINE(57, card->currentFat); + return card->currentFat; +} + +static void WriteCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + u16* fat0; + u16* fat1; + + card = &__CARDBlock[chan]; + + if (result >= 0) { + fat0 = (u16*)((u8*)card->workArea + 0x6000); + fat1 = (u16*)((u8*)card->workArea + 0x8000); + + ASSERTLINE(82, card->currentFat); + if (card->currentFat == fat0) { + card->currentFat = fat1; + memcpy(fat1, fat0, 0x2000); + } else { + ASSERTLINE(90, card->currentFat == fat1); + card->currentFat = fat0; + memcpy(fat0, fat1, 0x2000); + } + } + + if (!card->apiCallback) + __CARDPutControlBlock(card, result); + + callback = card->eraseCallback; + if (callback) { + card->eraseCallback = NULL; + callback(chan, result); + } +} + +static void EraseCallback(s32 chan, s32 result) { + CARDControl* card = &__CARDBlock[chan]; + CARDCallback callback; + u16* fat; + u32 addr; + + if (result < 0) + goto error; + + fat = __CARDGetFatBlock(card); + addr = ((u32)fat - (u32)card->workArea) / CARD_SYSTEM_BLOCK_SIZE * card->sectorSize; + result = __CARDWrite(chan, addr, CARD_SYSTEM_BLOCK_SIZE, fat, WriteCallback); + if (result < 0) + goto error; + + return; + +error: + if (!card->apiCallback) + __CARDPutControlBlock(card, result); + + callback = card->eraseCallback; + if (callback) { + card->eraseCallback = NULL; + callback(chan, result); + } +} + +s32 __CARDAllocBlock(s32 chan, u32 cBlock, CARDCallback callback) { + CARDControl* card; + u16* fat; + u16 iBlock; + u16 startBlock; + u16 prevBlock; + u16 count; + + ASSERTLINE(182, 0 < cBlock); + ASSERTLINE(183, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!card->attached) + return CARD_RESULT_NOCARD; + + fat = __CARDGetFatBlock(card); + if (fat[3] < cBlock) + return CARD_RESULT_INSSPACE; + + fat[3] -= cBlock; + startBlock = 0xFFFF; + iBlock = fat[4]; + count = 0; + while (0 < cBlock) { + if (card->cBlock - 5 < ++count) + return CARD_RESULT_BROKEN; + + iBlock++; + if (!CARDIsValidBlockNo(card, iBlock)) + iBlock = 5; + + if (fat[iBlock] == 0x0000u) { + if (startBlock == 0xFFFF) + startBlock = iBlock; + else + fat[prevBlock] = iBlock; + prevBlock = iBlock; + fat[iBlock] = 0xFFFF; + --cBlock; + } + } + + fat[4] = iBlock; + card->startBlock = startBlock; + return __CARDUpdateFatBlock(chan, fat, callback); +} + +s32 __CARDUpdateFatBlock(s32 chan, u16* fat, CARDCallback callback) { + CARDControl* card; + u32 addr; + + ASSERTLINE(295, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + ++fat[2]; + __CARDCheckSum(fat + 2, 0x1FFC, fat, fat + 1); + DCStoreRange(fat, 0x2000); + card->eraseCallback = callback; + addr = (((char*)fat - (char*)card->workArea) / 8192u) * card->sectorSize; + return __CARDEraseSector(chan, addr, EraseCallback); +} diff --git a/src/dolphin/card/CARDCheck.c b/src/dolphin/card/CARDCheck.c new file mode 100644 index 000000000..1a172e71e --- /dev/null +++ b/src/dolphin/card/CARDCheck.c @@ -0,0 +1,343 @@ +#include "dolphin/card.h" + +// prototypes +static s32 VerifyID(CARDControl* card); +static s32 VerifyDir(CARDControl* card, int* pcurrent); +static s32 VerifyFAT(CARDControl* card, int* pcurrent); + +extern void __CARDSyncCallback(s32 chan, s32 result); +extern u16 __CARDGetFontEncode(void); + +void __CARDCheckSum(void* ptr, int length, u16* checksum, u16* checksumInv) { + u16* p; + int i; + + ASSERTLINE(82, length % sizeof(u16) == 0); + + length /= sizeof(u16); + *checksum = *checksumInv = 0; + for (i = 0, p = ptr; i < length; i++, p++) { + *checksum += *p; + *checksumInv += ~*p; + } + + if (*checksum == 0xFFFF) + *checksum = 0; + + if (*checksumInv == 0xFFFF) + *checksumInv = 0; +} + +static s32 VerifyID(CARDControl* card) { + CARDID* id; + u16 checksum; + u16 checksumInv; + OSSramEx* sramEx; + OSTime rand; + int i; + + id = card->workArea; + + if (id->deviceID != 0 || id->size != card->size) + return CARD_RESULT_BROKEN; + + __CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &checksum, &checksumInv); + if (id->checkSum != checksum || id->checkSumInv != checksumInv) + return CARD_RESULT_BROKEN; + + rand = *(OSTime*)&id->serial[12]; + sramEx = __OSLockSramEx(); + for (i = 0; i < 12; i++) { + rand = (rand * 1103515245 + 12345) >> 16; + if (id->serial[i] != (u8)(sramEx->flashID[card - __CARDBlock][i] + rand)) { + __OSUnlockSramEx(FALSE); + return CARD_RESULT_BROKEN; + } + rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF; + } + + __OSUnlockSramEx(FALSE); + + if (id->encode != __CARDGetFontEncode()) + return CARD_RESULT_ENCODING; + + return CARD_RESULT_READY; +} + +static s32 VerifyDir(CARDControl* card, int* pcurrent) { + CARDDir* dir[2]; + CARDDirCheck* check[2]; + u16 checkSum; + u16 checkSumInv; + int i; + int errors; + int current; + + current = errors = 0; + for (i = 0; i < 2; i++) { + dir[i] = (CARDDir*)((u8*)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE); + check[i] = CARDGetDirCheck(dir[i]); + __CARDCheckSum(dir[i], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv); + if (check[i]->checkSum != checkSum || check[i]->checkSumInv != checkSumInv) { + ++errors; + current = i; + card->currentDir = 0; + } + } + + if (0 == errors) { + if (card->currentDir == 0) { + if ((check[0]->checkCode - check[1]->checkCode) < 0) + current = 0; + else + current = 1; + card->currentDir = dir[current]; + memcpy(dir[current], dir[current ^ 1], CARD_SYSTEM_BLOCK_SIZE); + } else { + current = (card->currentDir == dir[0]) ? 0 : 1; + } + } + + if (pcurrent) + *pcurrent = current; + + return errors; +} + +static s32 VerifyFAT(CARDControl* card, int* pcurrent) { + u16* fat[2]; + u16* fatp; + u16 nBlock; + u16 cFree; + int i; + u16 checkSum; + u16 checkSumInv; + int errors; + int current; + + current = errors = 0; + for (i = 0; i < 2; i++) { + fatp = fat[i] = (u16*)((u8*)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE); + + __CARDCheckSum(&fatp[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv); + if (fatp[CARD_FAT_CHECKSUM] != checkSum || fatp[CARD_FAT_CHECKSUMINV] != checkSumInv) { + ++errors; + current = i; + card->currentFat = 0; + continue; + } + + cFree = 0; + for (nBlock = CARD_NUM_SYSTEM_BLOCK; nBlock < card->cBlock; nBlock++) { + if (fatp[nBlock] == CARD_FAT_AVAIL) + cFree++; + } + + if (cFree != fatp[CARD_FAT_FREEBLOCKS]) { + ++errors; + current = i; + card->currentFat = 0; + continue; + } + } + + if (0 == errors) { + if (card->currentFat == 0) { + if (((s16)fat[0][CARD_FAT_CHECKCODE] - (s16)fat[1][CARD_FAT_CHECKCODE]) < 0) + current = 0; + else + current = 1; + card->currentFat = fat[current]; + memcpy(fat[current], fat[current ^ 1], CARD_SYSTEM_BLOCK_SIZE); + } else + current = (card->currentFat == fat[0]) ? 0 : 1; + } + + if (pcurrent) + *pcurrent = current; + + return errors; +} + +s32 __CARDVerify(CARDControl* card) { + s32 result; + int errors; + + result = VerifyID(card); + if (result < 0) + return result; + + errors = VerifyDir(card, NULL); + errors += VerifyFAT(card, NULL); + switch (errors) { + case 0: + ASSERTLINE(301, card->currentDir); + ASSERTLINE(302, card->currentFat); + return CARD_RESULT_READY; + case 1: + return CARD_RESULT_BROKEN; + default: + return CARD_RESULT_BROKEN; + } +} + +s32 CARDCheckExAsync(s32 chan, s32* xferBytes, CARDCallback callback) { + CARDControl* card; + CARDDir* dir[2]; + u16* fat[2]; + u16* map; + s32 result; + int errors; + int currentFat; + int currentDir; + s32 fileNo; + u16 iBlock; + u16 cBlock; + u16 cFree; + BOOL updateFat = FALSE; + BOOL updateDir = FALSE; + BOOL updateOrphan = FALSE; + + ASSERTLINE(346, 0 <= chan && chan < 2); + + if (xferBytes) { + *xferBytes = 0; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + + result = VerifyID(card); + if (result < 0) { + return __CARDPutControlBlock(card, result); + } + + errors = VerifyDir(card, ¤tDir); + errors += VerifyFAT(card, ¤tFat); + if (1 < errors) { + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + dir[0] = (CARDDir*)((u8*)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE); + dir[1] = (CARDDir*)((u8*)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE); + fat[0] = (u16*)((u8*)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE); + fat[1] = (u16*)((u8*)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE); + + ASSERTLINE(377, errors == 0 || errors == 1); + + switch (errors) { + case 0: + ASSERTLINE(381, card->currentDir); + ASSERTLINE(382, card->currentFat); + break; + case 1: + if (!card->currentDir) { + ASSERTLINE(387, card->currentFat); + card->currentDir = dir[currentDir]; + memcpy(dir[currentDir], dir[currentDir ^ 1], CARD_SYSTEM_BLOCK_SIZE); + updateDir = TRUE; + } else { + ASSERTLINE(394, !card->currentFat); + card->currentFat = fat[currentFat]; + memcpy(fat[currentFat], fat[currentFat ^ 1], CARD_SYSTEM_BLOCK_SIZE); + updateFat = TRUE; + } + break; + } + + map = fat[currentFat ^ 1]; + memset(map, 0, CARD_SYSTEM_BLOCK_SIZE); + + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) { + CARDDir* ent; + + ent = &card->currentDir[fileNo]; + if (ent->gameName[0] == 0xff) { + continue; + } + + for (iBlock = ent->startBlock, cBlock = 0; iBlock != 0xFFFF && cBlock < ent->length; + iBlock = card->currentFat[iBlock], ++cBlock) + { + if (!CARDIsValidBlockNo(card, iBlock) || 1 < ++map[iBlock]) { + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + } + + if (cBlock != ent->length || iBlock != 0xFFFF) { + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + } + + cFree = 0; + for (iBlock = CARD_NUM_SYSTEM_BLOCK; iBlock < card->cBlock; iBlock++) { + u16 nextBlock; + + nextBlock = card->currentFat[iBlock]; + if (map[iBlock] == 0) { + if (nextBlock != CARD_FAT_AVAIL) { + card->currentFat[iBlock] = CARD_FAT_AVAIL; + updateOrphan = TRUE; + } + cFree++; + } else if (!CARDIsValidBlockNo(card, nextBlock) && nextBlock != 0xFFFF) { + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + } + + if (cFree != card->currentFat[CARD_FAT_FREEBLOCKS]) { + card->currentFat[CARD_FAT_FREEBLOCKS] = cFree; + updateOrphan = TRUE; + } + + if (updateOrphan) { + __CARDCheckSum(&card->currentFat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), + &card->currentFat[CARD_FAT_CHECKSUM], + &card->currentFat[CARD_FAT_CHECKSUMINV]); + } + + memcpy(fat[currentFat ^ 1], fat[currentFat], CARD_SYSTEM_BLOCK_SIZE); + + if (updateDir) { + if (xferBytes) { + *xferBytes = CARD_SYSTEM_BLOCK_SIZE; + } + return __CARDUpdateDir(chan, callback); + } + + if (updateFat | updateOrphan) { + if (xferBytes) { + *xferBytes = CARD_SYSTEM_BLOCK_SIZE; + } + return __CARDUpdateFatBlock(chan, card->currentFat, callback); + } + + __CARDPutControlBlock(card, CARD_RESULT_READY); + if (callback) { + BOOL enabled = OSDisableInterrupts(); + callback(chan, CARD_RESULT_READY); + OSRestoreInterrupts(enabled); + } + return CARD_RESULT_READY; +} + +s32 CARDCheckAsync(s32 chan, CARDCallback callback) { + s32 xferBytes; + return CARDCheckExAsync(chan, &xferBytes, callback); +} + +s32 CARDCheckEx(s32 chan, s32* xferBytes) { + s32 result = CARDCheckExAsync(chan, xferBytes, __CARDSyncCallback); + if (result < 0 || xferBytes == 0) { + return result; + } + + return __CARDSync(chan); +} + +s32 CARDCheck(s32 chan) { + s32 xferBytes; + return CARDCheckEx(chan, &xferBytes); +} diff --git a/src/dolphin/card/CARDCreate.c b/src/dolphin/card/CARDCreate.c new file mode 100644 index 000000000..2b96633ef --- /dev/null +++ b/src/dolphin/card/CARDCreate.c @@ -0,0 +1,129 @@ +#include "dolphin/card.h" + +extern CARDDir* __CARDGetDirBlock(CARDControl* card); +extern void* __CARDGetFatBlock(CARDControl* card); +extern void __CARDDefaultApiCallback(s32 chan, s32 result); +extern void __CARDSyncCallback(s32 chan, s32 result); + +// prototypes +static void CreateCallbackFat(s32 chan, s32 result); + +static void CreateCallbackFat(s32 chan, s32 result) { + CARDControl* card; + CARDDir* dir; + CARDDir* ent; + CARDCallback callback; + + card = &__CARDBlock[chan]; + callback = card->apiCallback; + card->apiCallback = NULL; + + if (result >= 0) { + dir = __CARDGetDirBlock(card); + ent = &dir[card->freeNo]; + memcpy(ent->gameName, card->diskID->game_name, sizeof(ent->gameName)); + memcpy(ent->company, card->diskID->company, sizeof(ent->company)); + ent->permission = 4; + ent->copyTimes = 0; + + ASSERTLINE(111, CARDIsValidBlockNo(card, card->startBlock)); + ent->startBlock = (u16)card->startBlock; + ent->bannerFormat = 0; + ent->iconAddr = -1; + ent->iconFormat = 0; + ent->iconSpeed = 0; + ent->commentAddr = -1; + + CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST); + card->fileInfo->offset = 0; + card->fileInfo->iBlock = ent->startBlock; + ent->time = OSTicksToSeconds(OSGetTime()); + result = __CARDUpdateDir(chan, callback); + if (result < 0) { + goto after; + } + } else { +after:; + __CARDPutControlBlock(card, result); + if (callback) { + callback(chan, result); + } + } +} + +s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo, CARDCallback callback) { + CARDControl* card; + CARDDir* dir; + CARDDir* ent; + u16 fileNo; + u16 freeNo; + u16* fat; + s32 result; + + ASSERTLINE(175, 0 <= chan && chan < 2); + ASSERTLINE(176, strlen(fileName) <= CARD_FILENAME_MAX); + + if (strlen(fileName) > (u32)CARD_FILENAME_MAX) { + return CARD_RESULT_NAMETOOLONG; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + + ASSERTLINE(188, 0 < size && (size % card->sectorSize) == 0); + + if (size <= 0 || (size % card->sectorSize) != 0) { + return CARD_RESULT_FATAL_ERROR; + } + + freeNo = (u16)-1; + dir = __CARDGetDirBlock(card); + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) { + ent = &dir[fileNo]; + if (ent->gameName[0] == 0xff) { + if (freeNo == (u16)-1) { + freeNo = fileNo; + } + } else if (memcmp(ent->gameName, card->diskID->game_name, sizeof(ent->gameName)) == 0 && + memcmp(ent->company, card->diskID->company, sizeof(ent->company)) == 0 && + __CARDCompareFileName(ent, fileName)) { + return __CARDPutControlBlock(card, CARD_RESULT_EXIST); + } + } + + if (freeNo == (u16)-1) { + return __CARDPutControlBlock(card, CARD_RESULT_NOENT); + } + + fat = __CARDGetFatBlock(card); + if (card->sectorSize * fat[CARD_FAT_FREEBLOCKS] < size) { + return __CARDPutControlBlock(card, CARD_RESULT_INSSPACE); + } + + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + card->freeNo = freeNo; + ent = &dir[freeNo]; + ent->length = (u16)(size / card->sectorSize); + strncpy((char*)ent->fileName, fileName, CARD_FILENAME_MAX); + + card->fileInfo = fileInfo; + fileInfo->chan = chan; + fileInfo->fileNo = freeNo; + + result = __CARDAllocBlock(chan, size / card->sectorSize, CreateCallbackFat); + if (result < 0) { + return __CARDPutControlBlock(card, result); + } + return result; +} + +s32 CARDCreate(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo) { + s32 result = CARDCreateAsync(chan, fileName, size, fileInfo, __CARDSyncCallback); + if (result < 0) { + return result; + } + + return __CARDSync(chan); +} diff --git a/src/dolphin/card/CARDDir.c b/src/dolphin/card/CARDDir.c new file mode 100644 index 000000000..b57e555f8 --- /dev/null +++ b/src/dolphin/card/CARDDir.c @@ -0,0 +1,87 @@ +#include "dolphin/card.h" + +// prototypes +static void WriteCallback(s32 chan, s32 result); +static void EraseCallback(s32 chan, s32 result); + +CARDDir* __CARDGetDirBlock(CARDControl* card) { + ASSERTLINE(54, card->currentDir); + return card->currentDir; +} + +static void WriteCallback(s32 chan, s32 result) { + CARDControl* card = &__CARDBlock[chan]; + CARDCallback callback; + + if (result >= 0) { + CARDDir* dir0 = (CARDDir*)((u8*)card->workArea + 0x2000); + CARDDir* dir1 = (CARDDir*)((u8*)card->workArea + 0x4000); + + ASSERTLINE(79, card->currentDir); + + if (card->currentDir == dir0) { + card->currentDir = dir1; + memcpy(dir1, dir0, 0x2000); + } else { + ASSERTLINE(87, card->currentDir == dir1); + card->currentDir = dir0; + memcpy(dir0, dir1, 0x2000); + } + } + + if (!card->apiCallback) + __CARDPutControlBlock(card, result); + + callback = card->eraseCallback; + if (callback) { + card->eraseCallback = NULL; + callback(chan, result); + } +} + +static void EraseCallback(s32 chan, s32 result) { + CARDControl* card = &__CARDBlock[chan]; + CARDCallback callback; + CARDDir* dir; + u32 addr; + + if (result >= 0) { + dir = __CARDGetDirBlock(card); + addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize; + result = __CARDWrite(chan, addr, 0x2000, dir, WriteCallback); + if (result >= 0) + return; + } + + if (!card->apiCallback) + __CARDPutControlBlock(card, result); + + callback = card->eraseCallback; + if (callback) { + card->eraseCallback = NULL; + callback(chan, result); + } +} + +s32 __CARDUpdateDir(s32 chan, CARDCallback callback) { + CARDControl* card; + CARDDirCheck* check; + u32 addr; + CARDDir* dir; + + ASSERTLINE(173, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!card->attached) + return CARD_RESULT_NOCARD; + + dir = __CARDGetDirBlock(card); + check = CARDGetDirCheck(dir); + ++check->checkCode; + __CARDCheckSum(dir, 0x2000 - sizeof(u32), &check->checkSum, &check->checkSumInv); + DCStoreRange(dir, 0x2000); + + card->eraseCallback = callback; + addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize; + return __CARDEraseSector(chan, addr, EraseCallback); +} diff --git a/src/dolphin/card/CARDFormat.c b/src/dolphin/card/CARDFormat.c new file mode 100644 index 000000000..c3371e3a8 --- /dev/null +++ b/src/dolphin/card/CARDFormat.c @@ -0,0 +1,126 @@ +#include "dolphin/card.h" +#include "dolphin/vi/vi.h" + +extern void __CARDDefaultApiCallback(s32 chan, s32 result); +extern void __CARDSyncCallback(s32 chan, s32 result); +extern u16 __CARDGetFontEncode(void); + +static void FormatCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + + card = &__CARDBlock[chan]; + if (result < 0) + goto error; + + ++card->formatStep; + if (card->formatStep < CARD_NUM_SYSTEM_BLOCK) { + result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback); + if (result >= 0) + return; + } else if (card->formatStep < 2 * CARD_NUM_SYSTEM_BLOCK) { + int step = card->formatStep - CARD_NUM_SYSTEM_BLOCK; + result = __CARDWrite(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE, + (u8* )card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), FormatCallback); + if (result >= 0) + return; + } else { + card->currentDir = (CARDDir*)((u8*)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE); + memcpy(card->currentDir, (u8*)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE); + card->currentFat = (u16*)((u8*)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE); + memcpy(card->currentFat, (u8*)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE); + } + +error: + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(133, callback); + callback(chan, result); +} + +s32 __CARDFormatRegionAsync(s32 chan, u16 encode, CARDCallback callback) { + CARDControl* card; + CARDID* id; + CARDDir* dir; + u16* fat; + s16 i; + s32 result; + OSSram* sram; + OSSramEx* sramEx; + u16 dvdstatus; + OSTime time; + OSTime rand; + + ASSERTLINE(167, encode == CARD_ENCODE_ANSI || encode == CARD_ENCODE_SJIS); + ASSERTLINE(168, 0 <= chan && chan < 2); + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + id = (CARDID*)card->workArea; + memset(id, 0xff, CARD_SYSTEM_BLOCK_SIZE); + dvdstatus = __VIRegs[55]; + + id->encode = encode; + sram = __OSLockSram(); + *(u32*)&id->serial[20] = sram->counterBias; + *(u32*)&id->serial[24] = sram->language; + __OSUnlockSram(FALSE); + + rand = time = OSGetTime(); + + sramEx = __OSLockSramEx(); + for (i = 0; i < 12; i++) { + rand = (rand * 1103515245 + 12345) >> 16; + id->serial[i] = (u8)(sramEx->flashID[chan][i] + rand); + rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF; + } + __OSUnlockSramEx(FALSE); + + *(u32*)&id->serial[28] = dvdstatus; + *(OSTime*)&id->serial[12] = time; + + id->deviceID = 0; + id->size = card->size; + __CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &id->checkSum, &id->checkSumInv); + + for (i = 0; i < 2; i++) { + CARDDirCheck* check; + + dir = (CARDDir*)((u8*)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE); + memset(dir, 0xff, CARD_SYSTEM_BLOCK_SIZE); + check = CARDGetDirCheck(dir); + check->checkCode = i; + __CARDCheckSum(dir, CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &check->checkSum, &check->checkSumInv); + } + + for (i = 0; i < 2; i++) { + fat = (u16*)((u8*)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE); + memset(fat, 0x00, CARD_SYSTEM_BLOCK_SIZE); + fat[CARD_FAT_CHECKCODE] = (u16)i; + fat[CARD_FAT_FREEBLOCKS] = (u16)(card->cBlock - CARD_NUM_SYSTEM_BLOCK); + fat[CARD_FAT_LASTSLOT] = CARD_NUM_SYSTEM_BLOCK - 1; + __CARDCheckSum(&fat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &fat[CARD_FAT_CHECKSUM], + &fat[CARD_FAT_CHECKSUMINV]); + } + + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + DCStoreRange(card->workArea, CARD_WORKAREA_SIZE); + + card->formatStep = 0; + result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +s32 CARDFormat(s32 chan) { + s32 result = __CARDFormatRegionAsync(chan, __CARDGetFontEncode(), &__CARDSyncCallback); + if (result < 0) { + return result; + } + + return __CARDSync(chan); +} diff --git a/src/dolphin/card/CARDMount.c b/src/dolphin/card/CARDMount.c new file mode 100644 index 000000000..dae5c03f4 --- /dev/null +++ b/src/dolphin/card/CARDMount.c @@ -0,0 +1,378 @@ +#include "dolphin/card.h" + +extern u16 __CARDVendorID; + +static u32 SectorSizeTable[8] = { + 8 * 1024, 16 * 1024, 32 * 1024, 64 * 1024, 128 * 1024, 256 * 1024, 0, 0, +}; + +static u32 LatencyTable[8] = { + 4, 8, 16, 32, 64, 128, 256, 512, +}; + +// prototypes +static s32 DoMount(s32 chan); +static void DoUnmount(s32 chan, s32 result); +void __CARDMountCallback(s32 chan, s32 result); + +extern void __CARDExiHandler(s32 chan, OSContext* context); +extern void __CARDUnlockedHandler(s32 chan, OSContext* context); +extern void __CARDDefaultApiCallback(s32 chan, s32 result); +extern void __CARDExtHandler(s32 chan, OSContext* context); +extern void __CARDSyncCallback(s32 chan, s32 result); + +static BOOL IsCard(u32 id) { + u32 size; + s32 sectorSize; + if (id & (0xFFFF0000) && (id != 0x80000004 || __CARDVendorID == 0xFFFF)) { + return FALSE; + } + + if ((id & 3) != 0) { + return FALSE; + } + + size = id & 0xfc; + switch (size) { + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + break; + default: + return FALSE; + break; + } + + sectorSize = SectorSizeTable[(id & 0x00003800) >> 11]; + if (sectorSize == 0) { + return FALSE; + } + + if ((size * 1024 * 1024 / 8) / sectorSize < 8) { + return FALSE; + } + + return TRUE; +} + +int CARDProbe(s32 chan) { + if (__gUnknown800030E3 & 0x80) { + return 0; + } else { + return EXIProbe(chan); + } +} + +s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize) { + u32 id; + CARDControl* card; + BOOL enabled; + s32 result; + int probe; + + if (chan < 0 || 2 <= chan) + return CARD_RESULT_FATAL_ERROR; + + if (__gUnknown800030E3 & 0x80) { + return CARD_RESULT_NOCARD; + } + + card = &__CARDBlock[chan]; + enabled = OSDisableInterrupts(); + + probe = EXIProbeEx(chan); + if (probe == -1) + result = CARD_RESULT_NOCARD; + else if (probe == 0) + result = CARD_RESULT_BUSY; + else if (card->attached) { + if (card->mountStep < 1) + result = CARD_RESULT_BUSY; + else { + if (memSize) + *memSize = card->size; + + if (sectorSize) + *sectorSize = card->sectorSize; + + result = CARD_RESULT_READY; + } + } + else if ((EXIGetState(chan) & 8)) + result = CARD_RESULT_WRONGDEVICE; + else if (!EXIGetID(chan, 0, &id)) + result = CARD_RESULT_BUSY; + else if (IsCard(id)) { + if (memSize) + *memSize = (s32)(id & 0xfc); + + if (sectorSize) + *sectorSize = SectorSizeTable[(id & 0x00003800) >> 11]; + result = CARD_RESULT_READY; + } else { + result = CARD_RESULT_WRONGDEVICE; + } + + OSRestoreInterrupts(enabled); + return result; +} + +static s32 DoMount(s32 chan) { + CARDControl* card; + u32 id; + u8 status; + s32 result; + OSSramEx* sram; + int i; + u8 checkSum; + int step; + + ASSERTLINE(399, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (card->mountStep == 0) { + if (EXIGetID(chan, 0, &id) == 0) { + result = CARD_RESULT_NOCARD; + } else if (IsCard(id)) { + result = CARD_RESULT_READY; + } else { + result = CARD_RESULT_WRONGDEVICE; + } + + if (result < 0) + goto error; + + card->cid = id; + card->size = (u16)(id & 0xFC); + ASSERTLINE(424, card->size); + + card->sectorSize = SectorSizeTable[(id & 0x00003800) >> 11]; + ASSERTLINE(426, card->sectorSize); + + card->cBlock = (u16)((card->size * 1024 * 1024 / 8) / card->sectorSize); + ASSERTLINE(428, 8 <= card->cBlock); + + card->latency = LatencyTable[(id & 0x00000700) >> 8]; + + result = __CARDClearStatus(chan); + if (result < 0) + goto error; + + result = __CARDReadStatus(chan, &status); + if (result < 0) + goto error; + + if (!EXIProbe(chan)) { + result = CARD_RESULT_NOCARD; + goto error; + } + + if (!(status & 0x40)) { + result = __CARDUnlock(chan, card->id); + if (result < 0) + goto error; + + checkSum = 0; + sram = __OSLockSramEx(); + for (i = 0; i < 12; i++) { + sram->flashID[chan][i] = card->id[i]; + checkSum += card->id[i]; + } + sram->flashIDCheckSum[chan] = (u8)~checkSum; + __OSUnlockSramEx(TRUE); + + return result; + } else { + card->mountStep = 1; + + checkSum = 0; + sram = __OSLockSramEx(); + for (i = 0; i < 12; i++) + checkSum += sram->flashID[chan][i]; + + __OSUnlockSramEx(FALSE); + if (sram->flashIDCheckSum[chan] != (u8)~checkSum) { + result = CARD_RESULT_IOERROR; + goto error; + } + } + } + + if (card->mountStep == 1) { + if (card->cid == 0x80000004) { + u16 vendorID; + + sram = __OSLockSramEx(); + vendorID = *(u16*)sram->flashID[chan]; + __OSUnlockSramEx(FALSE); + + if (__CARDVendorID == 0xFFFF || vendorID != __CARDVendorID) { + result = CARD_RESULT_WRONGDEVICE; + goto error; + } + } + + card->mountStep = 2; + + result = __CARDEnableInterrupt(chan, TRUE); + if (result < 0) + goto error; + + EXISetExiCallback(chan, __CARDExiHandler); + EXIUnlock(chan); + DCInvalidateRange(card->workArea, CARD_WORKAREA_SIZE); + } + + step = card->mountStep - 2; + result = __CARDRead(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE, + (u8 *)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), __CARDMountCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; + +error: + EXIUnlock(chan); + DoUnmount(chan, result); + return result; +} + +void __CARDMountCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + + ASSERTLINE(570, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + switch (result) { + case CARD_RESULT_READY: + if (++card->mountStep < CARD_MAX_MOUNT_STEP) { + result = DoMount(chan); + if (0 <= result) + return; + } else + result = __CARDVerify(card); + break; + case CARD_RESULT_UNLOCKED: + card->unlockCallback = __CARDMountCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) { + return; + } + card->unlockCallback = 0; + + result = DoMount(chan); + if (result >= 0) + return; + break; + case CARD_RESULT_IOERROR: + case CARD_RESULT_NOCARD: + DoUnmount(chan, result); + break; + } + + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(620, callback); + callback(chan, result); +} + +s32 CARDMountAsync(s32 chan, void* workArea, CARDCallback detachCallback, CARDCallback attachCallback) { + CARDControl* card; + BOOL enabled; + + ASSERTLINE(652, workArea && ((u32) workArea % 32 == 0)); + ASSERTLINE(653, 0 <= chan && chan < 2); + + if (chan < 0 || 2 <= chan) + return CARD_RESULT_FATAL_ERROR; + + if (__gUnknown800030E3 & 0x80) { + return CARD_RESULT_NOCARD; + } + + card = &__CARDBlock[chan]; + + enabled = OSDisableInterrupts(); + if (card->result == CARD_RESULT_BUSY) { + OSRestoreInterrupts(enabled); + return CARD_RESULT_BUSY; + } + + if (!card->attached && (EXIGetState(chan) & 0x08)) { + OSRestoreInterrupts(enabled); + return CARD_RESULT_WRONGDEVICE; + } + + card->result = CARD_RESULT_BUSY; + card->workArea = workArea; + card->extCallback = detachCallback; + card->apiCallback = attachCallback ? attachCallback : __CARDDefaultApiCallback; + card->exiCallback = 0; + + if (!card->attached && !EXIAttach(chan, __CARDExtHandler)) { + card->result = CARD_RESULT_NOCARD; + OSRestoreInterrupts(enabled); + return CARD_RESULT_NOCARD; + } + + card->mountStep = 0; + card->attached = TRUE; + EXISetExiCallback(chan, 0); + OSCancelAlarm(&card->alarm); + + card->currentDir = 0; + card->currentFat = 0; + + OSRestoreInterrupts(enabled); + + card->unlockCallback = __CARDMountCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) + return CARD_RESULT_READY; + + card->unlockCallback = 0; + return DoMount(chan); +} + +s32 CARDMount(s32 chan, void* workArea, CARDCallback detachCallback) { + s32 result = CARDMountAsync(chan, workArea, detachCallback, __CARDSyncCallback); + + if (result < 0) + return result; + return __CARDSync(chan); +} + +static void DoUnmount(s32 chan, s32 result) { + CARDControl* card; + BOOL enabled; + + ASSERTLINE(758, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + enabled = OSDisableInterrupts(); + if (card->attached) { + EXISetExiCallback(chan, 0); + EXIDetach(chan); + OSCancelAlarm(&card->alarm); + card->attached = FALSE; + card->result = result; + card->mountStep = 0; + } + OSRestoreInterrupts(enabled); +} + +s32 CARDUnmount(s32 chan) { + CARDControl* card; + s32 result; + + ASSERTLINE(793, 0 <= chan && chan < 2); + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + DoUnmount(chan, CARD_RESULT_NOCARD); + return CARD_RESULT_READY; +} diff --git a/src/dolphin/card/CARDNet.c b/src/dolphin/card/CARDNet.c new file mode 100644 index 000000000..609556da8 --- /dev/null +++ b/src/dolphin/card/CARDNet.c @@ -0,0 +1,32 @@ +#include "dolphin/card.h" + +extern void __CARDSyncCallback(s32 chan, s32 result); + +u16 __CARDVendorID = 0xFFFF; + +s32 CARDGetSerialNo(s32 chan, u64* serialNo) { + CARDControl* card; + s32 result; + CARDID* id; + u64 code; + int i; + + ASSERTLINE(105, 0 <= chan && chan < 2); + + if (!(0 <= chan && chan < 2)) { + return CARD_RESULT_FATAL_ERROR; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + + id = (CARDID*)card->workArea; + for (code = 0, i = 0; i < sizeof(id->serial) / sizeof(u64); ++i) { + code ^= *(u64*)&id->serial[sizeof(u64) * i]; + } + *serialNo = code; + + return __CARDPutControlBlock(card, CARD_RESULT_READY); +} diff --git a/src/dolphin/card/CARDOpen.c b/src/dolphin/card/CARDOpen.c new file mode 100644 index 000000000..c3f276bae --- /dev/null +++ b/src/dolphin/card/CARDOpen.c @@ -0,0 +1,116 @@ +#include "dolphin/card.h" + +extern u8 __CARDPermMask; + +extern CARDDir* __CARDGetDirBlock(CARDControl* card); + +BOOL __CARDCompareFileName(CARDDir* ent, const char* fileName) { + char* entName = (char*)ent->fileName; + char c1; + char c2; + int n = CARD_FILENAME_MAX; + + while (--n >= 0) { + if ((c1 = *entName++) != (c2 = *fileName++)) + return FALSE; + else if (c2 == '\0') + return TRUE; + } + + if (*fileName == '\0') + return TRUE; + return FALSE; +} + +s32 __CARDAccess(CARDControl* card, CARDDir* ent) { + if (ent->gameName[0] == 0xFF) + return CARD_RESULT_NOFILE; + + if (card->diskID == &__CARDDiskNone + || (memcmp(ent->gameName, card->diskID->game_name, sizeof(ent->gameName)) == 0 + && memcmp(ent->company, card->diskID->company, sizeof(ent->company)) == 0)) + return CARD_RESULT_READY; + + return CARD_RESULT_NOPERM; +} + +s32 __CARDIsPublic(CARDDir* ent) { + if (ent->gameName[0] == 0xFF) + return CARD_RESULT_NOFILE; + + if (ent->permission & 4) + return CARD_RESULT_READY; + + return CARD_RESULT_NOPERM; +} + +s32 __CARDGetFileNo(CARDControl* card, const char* fileName, s32* pfileNo) { + CARDDir* dir; + CARDDir* ent; + s32 fileNo; + s32 result; + + if (!card->attached) + return CARD_RESULT_NOCARD; + + dir = __CARDGetDirBlock(card); + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) { + ent = &dir[fileNo]; + result = __CARDAccess(card, ent); + + if (result < 0) + continue; + if (__CARDCompareFileName(ent, fileName)) { + *pfileNo = fileNo; + return CARD_RESULT_READY; + } + } + + return CARD_RESULT_NOFILE; +} + +s32 CARDOpen(s32 chan, const char* fileName, CARDFileInfo* fileInfo) { + CARDControl* card; + s32 fileNo; + s32 result; + CARDDir* dir; + CARDDir* ent; + + ASSERTLINE(336, 0 <= chan && chan < 2); + + fileInfo->chan = -1; + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + result = __CARDGetFileNo(card, fileName, &fileNo); + if (result >= 0) { + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + if (!CARDIsValidBlockNo(card, ent->startBlock)) + result = CARD_RESULT_BROKEN; + else { + fileInfo->chan = chan; + fileInfo->fileNo = fileNo; + fileInfo->offset = 0; + fileInfo->iBlock = ent->startBlock; + } + } + + return __CARDPutControlBlock(card, result); +} + +s32 CARDClose(CARDFileInfo* fileInfo) { + CARDControl* card; + s32 result; + + ASSERTLINE(380, 0 <= fileInfo->chan && fileInfo->chan < 2); + ASSERTLINE(381, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); + + result = __CARDGetControlBlock(fileInfo->chan, &card); + if (result < 0) + return result; + + fileInfo->chan = -1; + return __CARDPutControlBlock(card, CARD_RESULT_READY); +} diff --git a/src/dolphin/card/CARDRdwr.c b/src/dolphin/card/CARDRdwr.c new file mode 100644 index 000000000..606f89f23 --- /dev/null +++ b/src/dolphin/card/CARDRdwr.c @@ -0,0 +1,98 @@ +#include "dolphin/card.h" + +// prototypes +static void BlockReadCallback(s32 chan, s32 result); +static void BlockWriteCallback(s32 chan, s32 result); + +static void BlockReadCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + + card = &__CARDBlock[chan]; + + if ((result >= 0)) { + card->xferred += 0x200; + card->addr += 0x200; + ((u8*)card->buffer) += 0x200; + + if (--card->repeat > 0) { + result = __CARDReadSegment(chan, BlockReadCallback); + if (result >= 0) { + return; + } + } + } + + if (!card->apiCallback) { + __CARDPutControlBlock(card, result); + } + + callback = card->xferCallback; + if (callback) { + card->xferCallback = NULL; + callback(chan, result); + } +} + +s32 __CARDRead(s32 chan, u32 addr, s32 length, void* dst, CARDCallback callback) { + CARDControl* card; + + ASSERTLINE(91, 0 < length && length % CARD_SEG_SIZE == 0); + ASSERTLINE(92, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (card->attached == 0) { + return CARD_RESULT_NOCARD; + } + card->xferCallback = callback; + card->repeat = (length / 512u); + card->addr = addr; + card->buffer = dst; + return __CARDReadSegment(chan, BlockReadCallback); +} + +static void BlockWriteCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + + card = &__CARDBlock[chan]; + if (result >= 0) { + card->xferred += 0x80; + card->addr += 0x80; + ((u8*)card->buffer) += 0x80; + + if (--card->repeat > 0) { + result = __CARDWritePage(chan, BlockWriteCallback); + if (result >= 0) { + return; + } + } + } + + if (!card->apiCallback) { + __CARDPutControlBlock(card, result); + } + + callback = card->xferCallback; + if (callback) { + card->xferCallback = NULL; + callback(chan, result); + } +} + +s32 __CARDWrite(s32 chan, u32 addr, s32 length, void* dst, CARDCallback callback) { + CARDControl* card; + card = &__CARDBlock[chan]; + + ASSERTLINE(153, 0 < length && length % card->pageSize == 0); + ASSERTLINE(154, 0 <= chan && chan < 2); + + if (card->attached == 0) { + return CARD_RESULT_NOCARD; + } + card->xferCallback = callback; + card->repeat = (int)(length / 128u); + card->addr = addr; + card->buffer = dst; + return __CARDWritePage(chan, BlockWriteCallback); +} diff --git a/src/dolphin/card/CARDRead.c b/src/dolphin/card/CARDRead.c new file mode 100644 index 000000000..d2836bed5 --- /dev/null +++ b/src/dolphin/card/CARDRead.c @@ -0,0 +1,159 @@ +#include "dolphin/card.h" + +#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) +#define OFFSET(addr, align) (((u32)(addr) & ((align)-1))) + +extern CARDDir* __CARDGetDirBlock(CARDControl* card); +extern void* __CARDGetFatBlock(CARDControl* card); +extern void __CARDDefaultApiCallback(s32 chan, s32 result); +extern void __CARDSyncCallback(s32 chan, s32 result); + +// prototypes +static void ReadCallback(s32 chan, s32 result); + +s32 __CARDSeek(CARDFileInfo* fileInfo, s32 length, s32 offset, CARDControl** pcard) { + CARDControl* card; + CARDDir* dir; + CARDDir* ent; + s32 result; + u16* fat; + + ASSERTLINE(98, 0 <= fileInfo->chan && fileInfo->chan < 2); + ASSERTLINE(99, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); + + result = __CARDGetControlBlock(fileInfo->chan, &card); + if (result < 0) + return result; + + ASSERTLINE(106, CARDIsValidBlockNo(card, fileInfo->iBlock)); + ASSERTLINE(107, fileInfo->offset < card->cBlock * card->sectorSize); + + if (!CARDIsValidBlockNo(card, fileInfo->iBlock) || card->cBlock * card->sectorSize <= fileInfo->offset) + return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR); + + dir = __CARDGetDirBlock(card); + ent = &dir[fileInfo->fileNo]; + + ASSERTLINE(117, ent->gameName[0] != 0xff); + + if (ent->length * card->sectorSize <= offset || ent->length * card->sectorSize < offset + length) + return __CARDPutControlBlock(card, CARD_RESULT_LIMIT); + + card->fileInfo = fileInfo; + fileInfo->length = length; + if (offset < fileInfo->offset) { + fileInfo->offset = 0; + fileInfo->iBlock = ent->startBlock; + if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + fat = __CARDGetFatBlock(card); + while (fileInfo->offset < TRUNC(offset, card->sectorSize)) { + fileInfo->offset += card->sectorSize; + fileInfo->iBlock = fat[fileInfo->iBlock]; + if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + fileInfo->offset = offset; + + *pcard = card; + return CARD_RESULT_READY; +} + +static void ReadCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + u16* fat; + CARDFileInfo* fileInfo; + s32 length; + + card = &__CARDBlock[chan]; + if (result < 0) + goto error; + + fileInfo = card->fileInfo; + if (fileInfo->length < 0) { + result = CARD_RESULT_CANCELED; + goto error; + } + + length = TRUNC(fileInfo->offset + card->sectorSize, card->sectorSize) - fileInfo->offset; + fileInfo->length -= length; + if (fileInfo->length <= 0) + goto error; + + fat = __CARDGetFatBlock(card); + fileInfo->offset += length; + fileInfo->iBlock = fat[fileInfo->iBlock]; + if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) { + result = CARD_RESULT_BROKEN; + goto error; + } + + ASSERTLINE(199, OFFSET(fileInfo->length, CARD_SEG_SIZE) == 0); + ASSERTLINE(200, OFFSET(fileInfo->offset, card->sectorSize) == 0); + + result = __CARDRead(chan, card->sectorSize * (u32)fileInfo->iBlock, + (fileInfo->length < card->sectorSize) ? fileInfo->length : card->sectorSize, card->buffer, + ReadCallback); + if (result < 0) + goto error; + + return; + +error: + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(217, callback); + callback(chan, result); +} + +s32 CARDReadAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback) { + CARDControl* card; + s32 result; + CARDDir* dir; + CARDDir* ent; + + ASSERTLINE(250, buf && OFFSET(buf, 32) == 0); + ASSERTLINE(251, OFFSET(offset, CARD_SEG_SIZE) == 0); + ASSERTLINE(252, 0 < length && OFFSET(length, CARD_SEG_SIZE) == 0); + + if (OFFSET(offset, CARD_SEG_SIZE) != 0 || OFFSET(length, CARD_SEG_SIZE) != 0) + return CARD_RESULT_FATAL_ERROR; + + result = __CARDSeek(fileInfo, length, offset, &card); + if (result < 0) + return result; + + dir = __CARDGetDirBlock(card); + ent = &dir[fileInfo->fileNo]; + result = __CARDAccess(card, ent); + if (result == CARD_RESULT_NOPERM) { + result = __CARDIsPublic(ent); + } + + if (result < 0) + return __CARDPutControlBlock(card, result); + + DCInvalidateRange(buf, (u32)length); + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + + offset = (s32)OFFSET(fileInfo->offset, card->sectorSize); + length = (length < card->sectorSize - offset) ? length : card->sectorSize - offset; + result = __CARDRead(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock + offset, length, buf, ReadCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +s32 CARDRead(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset) { + s32 result = CARDReadAsync(fileInfo, buf, length, offset, __CARDSyncCallback); + if (result < 0) { + return result; + } + + return __CARDSync(fileInfo->chan); +} diff --git a/src/dolphin/card/CARDStat.c b/src/dolphin/card/CARDStat.c new file mode 100644 index 000000000..c7b19b794 --- /dev/null +++ b/src/dolphin/card/CARDStat.c @@ -0,0 +1,160 @@ +#include "dolphin/card.h" + +extern CARDDir* __CARDGetDirBlock(CARDControl* card); +extern void __CARDSyncCallback(s32 chan, s32 result); + +static void UpdateIconOffsets(CARDDir* ent, CARDStat* stat) { + u32 offset; + BOOL iconTlut; + int i; + + offset = ent->iconAddr; + if (offset == 0xffffffff) { + stat->bannerFormat = 0; + stat->iconFormat = 0; + stat->iconSpeed = 0; + offset = 0; + } + + iconTlut = FALSE; + switch (CARDGetBannerFormat(ent)) { + case CARD_STAT_BANNER_C8: + stat->offsetBanner = offset; + offset += CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT; + stat->offsetBannerTlut = offset; + offset += 2 * 256; + break; + case CARD_STAT_BANNER_RGB5A3: + stat->offsetBanner = offset; + offset += 2 * CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT; + stat->offsetBannerTlut = 0xffffffff; + break; + default: + stat->offsetBanner = 0xffffffff; + stat->offsetBannerTlut = 0xffffffff; + break; + } + + for (i = 0; i < CARD_ICON_MAX; ++i) { + switch (CARDGetIconFormat(ent, i)) { + case CARD_STAT_ICON_C8: + stat->offsetIcon[i] = offset; + offset += CARD_ICON_WIDTH * CARD_ICON_HEIGHT; + iconTlut = TRUE; + break; + case CARD_STAT_ICON_RGB5A3: + stat->offsetIcon[i] = offset; + offset += 2 * CARD_ICON_WIDTH * CARD_ICON_HEIGHT; + break; + default: + stat->offsetIcon[i] = 0xffffffff; + break; + } + } + + if (iconTlut) { + stat->offsetIconTlut = offset; + offset += 2 * 256; + } else { + stat->offsetIconTlut = 0xffffffff; + } + stat->offsetData = offset; +} + +s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat* stat) { + CARDControl* card; + CARDDir* dir; + CARDDir* ent; + s32 result; + + ASSERTLINE(172, 0 <= chan && chan < 2); + ASSERTLINE(173, 0 <= fileNo && fileNo < CARD_MAX_FILE); + + if (fileNo < 0 || CARD_MAX_FILE <= fileNo) + return CARD_RESULT_FATAL_ERROR; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + result = __CARDAccess(card, ent); + if (result == CARD_RESULT_NOPERM) { + result = __CARDIsPublic(ent); + } + + if (result >= 0) { + memcpy(stat->gameName, ent->gameName, sizeof(stat->gameName)); + memcpy(stat->company, ent->company, sizeof(stat->company)); + stat->length = (u32)ent->length * card->sectorSize; + memcpy(stat->fileName, ent->fileName, CARD_FILENAME_MAX); + stat->time = ent->time; + + stat->bannerFormat = ent->bannerFormat; + stat->iconAddr = ent->iconAddr; + stat->iconFormat = ent->iconFormat; + stat->iconSpeed = ent->iconSpeed; + stat->commentAddr = ent->commentAddr; + + UpdateIconOffsets(ent, stat); + } + + return __CARDPutControlBlock(card, result); +} + +s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat* stat, CARDCallback callback) { + CARDControl* card; + CARDDir* dir; + CARDDir* ent; + s32 result; + + ASSERTLINE(231, 0 <= fileNo && fileNo < CARD_MAX_FILE); + ASSERTLINE(232, 0 <= chan && chan < 2); + ASSERTMSGLINE(240, stat->iconAddr == 0xffffffff || stat->iconAddr < CARD_READ_SIZE, "CARDSetStatus[Async](): stat->iconAddr must be 0xffffffff or less than CARD_READ_SIZE."); + ASSERTMSGLINE(243, stat->commentAddr == 0xffffffff || (stat->commentAddr & 0x1FFF) <= 8128, "CARDSetStatus[Async](): comment strings (set by stat->commentAddr) must not cross 8KB byte boundary."); + + if (fileNo < 0 || CARD_MAX_FILE <= fileNo || + (stat->iconAddr != 0xffffffff && CARD_READ_SIZE <= stat->iconAddr) || + (stat->commentAddr != 0xffffffff && + CARD_SYSTEM_BLOCK_SIZE - CARD_COMMENT_SIZE < stat->commentAddr % CARD_SYSTEM_BLOCK_SIZE)) + { + return CARD_RESULT_FATAL_ERROR; + } + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + dir = __CARDGetDirBlock(card); + ent = &dir[fileNo]; + result = __CARDAccess(card, ent); + if (result < 0) + return __CARDPutControlBlock(card, result); + + ent->bannerFormat = stat->bannerFormat; + ent->iconAddr = stat->iconAddr; + ent->iconFormat = stat->iconFormat; + ent->iconSpeed = stat->iconSpeed; + ent->commentAddr = stat->commentAddr; + UpdateIconOffsets(ent, stat); + + if (ent->iconAddr == 0xffffffff) { + CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST); + } + + ent->time = (u32)OSTicksToSeconds(OSGetTime()); + result = __CARDUpdateDir(chan, callback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +s32 CARDSetStatus(s32 chan, s32 fileNo, CARDStat* stat) { + s32 result = CARDSetStatusAsync(chan, fileNo, stat, __CARDSyncCallback); + if (result < 0) { + return result; + } + + return __CARDSync(chan); +} diff --git a/src/dolphin/card/CARDUnlock.c b/src/dolphin/card/CARDUnlock.c new file mode 100644 index 000000000..5e2852c9f --- /dev/null +++ b/src/dolphin/card/CARDUnlock.c @@ -0,0 +1,401 @@ +#include "dolphin/card.h" + +static u8 CardData[352] ATTRIBUTE_ALIGN(32) = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0xFF, 0x00, 0x21, 0x13, 0x06, 0x12, 0x03, 0x12, 0x04, + 0x13, 0x05, 0x00, 0x92, 0x00, 0xFF, 0x00, 0x88, 0xFF, 0xFF, 0x00, 0x89, 0xFF, 0xFF, 0x00, 0x8A, 0xFF, 0xFF, 0x00, + 0x8B, 0xFF, 0xFF, 0x8F, 0x00, 0x02, 0xBF, 0x00, 0x88, 0x16, 0xFC, 0xDC, 0xD1, 0x16, 0xFD, 0x00, 0x00, 0x16, 0xFB, + 0x00, 0x01, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x03, 0x80, 0xFF, 0x00, 0x02, 0x94, 0x00, 0x27, 0x02, 0xBF, 0x00, + 0x8E, 0x1F, 0xDF, 0x24, 0xFF, 0x02, 0x40, 0x0F, 0xFF, 0x00, 0x98, 0x04, 0x00, 0x00, 0x9A, 0x00, 0x10, 0x00, 0x99, + 0x00, 0x00, 0x8E, 0x00, 0x02, 0xBF, 0x00, 0x94, 0x02, 0xBF, 0x86, 0x44, 0x02, 0xBF, 0x00, 0x88, 0x16, 0xFC, 0xDC, + 0xD1, 0x16, 0xFD, 0x00, 0x03, 0x16, 0xFB, 0x00, 0x01, 0x8F, 0x00, 0x02, 0xBF, 0x00, 0x8E, 0x03, 0x80, 0xCD, 0xD1, + 0x02, 0x94, 0x00, 0x48, 0x27, 0xFF, 0x03, 0x80, 0x00, 0x01, 0x02, 0x95, 0x00, 0x5A, 0x03, 0x80, 0x00, 0x02, 0x02, + 0x95, 0x80, 0x00, 0x02, 0x9F, 0x00, 0x48, 0x00, 0x21, 0x8E, 0x00, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, + 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC5, 0xFF, 0xFF, 0x03, + 0x40, 0x0F, 0xFF, 0x1C, 0x9F, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC7, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC6, + 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC0, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x20, 0xFF, 0x03, 0x40, 0x0F, + 0xFF, 0x1F, 0x5F, 0x02, 0xBF, 0x00, 0x8E, 0x21, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x23, 0xFF, 0x12, 0x05, 0x12, 0x06, + 0x02, 0x9F, 0x80, 0xB5, 0x00, 0x21, 0x27, 0xFC, 0x03, 0xC0, 0x80, 0x00, 0x02, 0x9D, 0x00, 0x88, 0x02, 0xDF, 0x27, + 0xFE, 0x03, 0xC0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x8E, 0x02, 0xDF, 0x2E, 0xCE, 0x2C, 0xCF, 0x00, 0xF8, 0xFF, 0xCD, + 0x00, 0xF9, 0xFF, 0xC9, 0x00, 0xFA, 0xFF, 0xCB, 0x26, 0xC9, 0x02, 0xC0, 0x00, 0x04, 0x02, 0x9D, 0x00, 0x9C, 0x02, + 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static u32 next = 1; + +// prototypes +static u32 exnor_1st(u32 data, u32 rshift); +static u32 exnor(u32 data, u32 lshift); +static u32 bitrev(u32 data); +static s32 ReadArrayUnlock(s32 chan, u32 data, void* rbuf, s32 rlen, int mode); +static u32 GetInitVal(void); +static s32 DummyLen(void); +static void InitCallback(void* _task); +static void DoneCallback(void* _task); + +static int CARDRand(void) { + next = (next * 0x41C64E6D) + 0x3039; + return (next / 0x10000) & 0x7FFF; +} + +static void CARDSrand(unsigned int seed) { + next = seed; +} + +static u32 exnor_1st(u32 data, u32 rshift) { + u32 wk; + u32 work; + u32 i; + + work = data; + for (i = 0; i < rshift; i++) { + wk = ~(work ^ (work >> 7) ^ (work >> 15) ^ (work >> 23)); + work = (work >> 1) | ((wk << 30) & 0x40000000); + } + + return work; +} + +static u32 exnor(u32 data, u32 lshift) { + u32 wk; + u32 work; + u32 i; + + work = data; + for (i = 0; i < lshift; i++) { + // 1bit Left Shift + wk = ~(work ^ (work << 7) ^ (work << 15) ^ (work << 23)); + work = (work << 1) | ((wk >> 30) & 0x00000002); + } + + return work; +} + +static u32 bitrev(u32 data) { + u32 wk; + u32 i; + u32 k = 0; + u32 j = 1; + + wk = 0; + for (i = 0; i < 32; i++) { + if (i > 15) { + if (i == 31) + wk |= (((data & (0x01 << 31)) >> 31) & 0x01); + else { + wk |= ((data & (0x01 << i)) >> j); + j += 2; + } + } else { + wk |= ((data & (0x01 << i)) << (31 - i - k)); + k++; + } + } + + return wk; +} + +#define SEC_AD1(x) ((u8)(((x) >> 29) & 0x03)) +#define SEC_AD2(x) ((u8)(((x) >> 21) & 0xff)) +#define SEC_AD3(x) ((u8)(((x) >> 19) & 0x03)) +#define SEC_BA(x) ((u8)(((x) >> 12) & 0x7f)) + +static s32 ReadArrayUnlock(s32 chan, u32 data, void* rbuf, s32 rlen, int mode) { + CARDControl* card; + BOOL err; + u8 cmd[5]; + + ASSERTLINE(240, 0 <= chan && chan < 2); + + card = &__CARDBlock[chan]; + if (!EXISelect(chan, 0, 4)) + return CARD_RESULT_NOCARD; + + data &= 0xfffff000; + memset(cmd, 0, 5); + cmd[0] = 0x52; + if (mode == 0) { + cmd[1] = SEC_AD1(data); + cmd[2] = SEC_AD2(data); + cmd[3] = SEC_AD3(data); + cmd[4] = SEC_BA(data); + } else { + cmd[1] = (u8)((data & 0xff000000) >> 24); + cmd[2] = (u8)((data & 0x00ff0000) >> 16); + } + + err = FALSE; + err |= !EXIImmEx(chan, cmd, 5, 1); + err |= !EXIImmEx(chan, (u8* )card->workArea + (u32)sizeof(CARDID), card->latency, 1); + err |= !EXIImmEx(chan, rbuf, rlen, 0); + err |= !EXIDeselect(chan); + + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +static u32 GetInitVal(void) { + u32 tmp; + u32 tick; + + tick = OSGetTick(); + CARDSrand(tick); + tmp = 0x7fec8000; + tmp |= CARDRand(); + tmp &= 0xfffff000; + return tmp; +} + +static s32 DummyLen(void) { + u32 tick; + u32 wk; + s32 tmp; + u32 max; + + wk = 1; + max = 0; + tick = OSGetTick(); + CARDSrand(tick); + + tmp = CARDRand(); + tmp &= 0x0000001f; + tmp += 1; + while ((tmp < 4) && (max < 10)) { + tick = OSGetTick(); + tmp = (s32)(tick << wk); + wk++; + if (wk > 16) + wk = 1; + CARDSrand((u32)tmp); + tmp = CARDRand(); + tmp &= 0x0000001f; + tmp += 1; + max++; + } + + if (tmp < 4) + tmp = 4; + + return tmp; +} + +s32 __CARDUnlock(s32 chan, u8 flashID[12]) { + u32 init_val; + u32 data; + + s32 dummy; + s32 rlen; + u32 rshift; + + u8 fsts; + u32 wk, wk1; + u32 Ans1 = 0; + u32 Ans2 = 0; + u32* dp; + u8 rbuf[64]; + u32 para1A = 0; + u32 para1B = 0; + u32 para2A = 0; + u32 para2B = 0; + + CARDControl* card; + DSPTaskInfo* task; + CARDDecParam* param; + u8* input; + u8* output; + + card = &__CARDBlock[chan]; + task = &card->task; + param = (CARDDecParam*)card->workArea; + input = (u8*)((u8* )param + sizeof(CARDDecParam)); + input = (u8*)OSRoundUp32B(input); + output = input + 32; + + fsts = 0; + init_val = GetInitVal(); + + dummy = DummyLen(); + rlen = dummy; + if (ReadArrayUnlock(chan, init_val, rbuf, rlen, 0) < 0) + return CARD_RESULT_NOCARD; + + rshift = (u32)(dummy * 8 + 1); + wk = exnor_1st(init_val, rshift); + wk1 = ~(wk ^ (wk >> 7) ^ (wk >> 15) ^ (wk >> 23)); + card->scramble = (wk | ((wk1 << 31) & 0x80000000)); + card->scramble = bitrev(card->scramble); + dummy = DummyLen(); + rlen = 20 + dummy; + data = 0; + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) + return CARD_RESULT_NOCARD; + + dp = (u32* )rbuf; + para1A = *dp++; + para1B = *dp++; + Ans1 = *dp++; + para2A = *dp++; + para2B = *dp++; + para1A = (para1A ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + para1B = (para1B ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + Ans1 ^= card->scramble; + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + para2A = (para2A ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + para2B = (para2B ^ card->scramble); + rshift = (u32)(dummy * 8); + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + rshift = 32 + 1; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + *(u32*)&input[0] = para2A; + *(u32*)&input[4] = para2B; + + param->inputAddr = input; + param->inputLength = 8; + param->outputAddr = output; + param->aramAddr = 0; + + DCFlushRange(input, 8); + DCInvalidateRange(output, 4); + DCFlushRange(param, sizeof(CARDDecParam)); + + task->priority = 255; + task->iram_mmem_addr = (u16*)OSCachedToPhysical(CardData); + task->iram_length = 0x160; + task->iram_addr = 0; + task->dsp_init_vector = 0x10; + task->init_cb = InitCallback; + task->res_cb = NULL; + task->done_cb = DoneCallback; + task->req_cb = NULL; + DSPAddTask(task); + + dp = (u32*)flashID; + *dp++ = para1A; + *dp++ = para1B; + *dp = Ans1; + + return CARD_RESULT_READY; +} + +static void InitCallback(void* _task) { + s32 chan; + CARDControl* card; + DSPTaskInfo* task; + CARDDecParam* param; + + task = _task; + for (chan = 0; chan < 2; ++chan) { + card = &__CARDBlock[chan]; + if ((DSPTaskInfo*)&card->task == task) + break; + } + + ASSERTLINE(514, 0 <= chan && chan < 2); + + param = (CARDDecParam*)card->workArea; + + DSPSendMailToDSP(0xff000000); + while (DSPCheckMailToDSP()) + ; + + DSPSendMailToDSP((u32)param); + while (DSPCheckMailToDSP()) + ; +} + +static void DoneCallback(void* _task) { + u8 rbuf[64]; + u32 data; + s32 dummy; + s32 rlen; + u32 rshift; + + u8 unk; + u32 wk, wk1; + u32 Ans2; + + s32 chan; + CARDControl* card; + s32 result; + DSPTaskInfo* task; + CARDDecParam* param; + + u8* input; + u8* output; + task = _task; + for (chan = 0; chan < 2; ++chan) { + card = &__CARDBlock[chan]; + if ((DSPTaskInfo* )&card->task == task) + break; + } + + ASSERTLINE(563, 0 <= chan && chan < 2); + + param = (CARDDecParam*)card->workArea; + input = (u8*)((u8*)param + sizeof(CARDDecParam)); + input = (u8*)OSRoundUp32B(input); + output = input + 32; + + Ans2 = *(u32*)output; + dummy = DummyLen(); + rlen = dummy; + data = ((Ans2 ^ card->scramble) & 0xffff0000); + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + + rshift = (u32)((dummy + 4 + card->latency) * 8 + 1); + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + dummy = DummyLen(); + rlen = dummy; + data = (((Ans2 << 16) ^ card->scramble) & 0xffff0000); + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + + result = __CARDReadStatus(chan, &unk); + if (!EXIProbe(chan)) { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + + if (result == CARD_RESULT_READY && !(unk & 0x40)) { + EXIUnlock(chan); + result = CARD_RESULT_IOERROR; + } + + __CARDMountCallback(chan, result); +} diff --git a/src/dolphin/card/CARDWrite.c b/src/dolphin/card/CARDWrite.c new file mode 100644 index 000000000..af9981137 --- /dev/null +++ b/src/dolphin/card/CARDWrite.c @@ -0,0 +1,128 @@ +#include "dolphin/card.h" + +#define OFFSET(addr, align) (((u32)(addr) & ((align)-1))) + +extern CARDDir* __CARDGetDirBlock(CARDControl* card); +extern void* __CARDGetFatBlock(CARDControl* card); +extern void __CARDDefaultApiCallback(s32 chan, s32 result); +extern void __CARDSyncCallback(s32 chan, s32 result); + +// prototypes +static void WriteCallback(s32 chan, s32 result); +static void EraseCallback(s32 chan, s32 result); + +static void WriteCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + u16* fat; + CARDDir* dir; + CARDDir* ent; + CARDFileInfo* fileInfo; + + card = &__CARDBlock[chan]; + if (result >= 0) { + fileInfo = card->fileInfo; + if (fileInfo->length < 0) { + result = CARD_RESULT_CANCELED; + goto after; + } + fileInfo->length -= card->sectorSize; + if (fileInfo->length <= 0) { + dir = __CARDGetDirBlock(card); + ent = dir + fileInfo->fileNo; + ent->time = OSGetTime()/(__OSBusClock/4); + callback = card->apiCallback; + card->apiCallback = NULL; + result = __CARDUpdateDir(chan, callback); + goto check; + } else { + fat = __CARDGetFatBlock(card); + fileInfo->offset += card->sectorSize; + fileInfo->iBlock = fat[fileInfo->iBlock]; + if ((fileInfo->iBlock < 5) || (fileInfo->iBlock >= card->cBlock)) { + result = CARD_RESULT_BROKEN; + goto after; + } + result = __CARDEraseSector(chan, card->sectorSize * fileInfo->iBlock, EraseCallback); +check:; + if (result < 0) { + goto after; + } + } + } else { +after:; + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(0x86, callback); + callback(chan, result); + } +} + +static void EraseCallback(s32 chan, s32 result) { + CARDControl* card; + CARDCallback callback; + CARDFileInfo* fileInfo; + + card = &__CARDBlock[chan]; + if (result >= 0) { + fileInfo = card->fileInfo; + ASSERTLINE(161, OFFSET(fileInfo->offset, card->sectorSize) == 0); + result = __CARDWrite(chan, card->sectorSize * fileInfo->iBlock, card->sectorSize, card->buffer, WriteCallback); + if (result < 0) { + goto after; + } + } else { +after:; + callback = card->apiCallback; + card->apiCallback = NULL; + __CARDPutControlBlock(card, result); + ASSERTLINE(175, callback); + callback(chan, result); + } +} + +s32 CARDWriteAsync(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset, CARDCallback callback) { + CARDControl* card; + s32 result; + CARDDir* dir; + CARDDir* ent; + + ASSERTLINE(210, buf && ((u32) buf % 32) == 0); + ASSERTLINE(211, 0 < length); + + result = __CARDSeek(fileInfo, length, offset, &card); + if (result < 0) { + return result; + } + + ASSERTLINE(217, OFFSET(offset, card->sectorSize) == 0); + ASSERTLINE(218, OFFSET(length, card->sectorSize) == 0); + + if (OFFSET(offset, card->sectorSize) != 0 || OFFSET(length, card->sectorSize) != 0) + return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR); + + dir = __CARDGetDirBlock(card); + ent = &dir[fileInfo->fileNo]; + result = __CARDAccess(card, ent); + if (result < 0) + return __CARDPutControlBlock(card, result); + + DCStoreRange((void*)buf, (u32)length); + card->apiCallback = callback ? callback : __CARDDefaultApiCallback; + card->buffer = (void*)buf; + + result = __CARDEraseSector(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock, EraseCallback); + if (result < 0) + __CARDPutControlBlock(card, result); + return result; +} + +s32 CARDWrite(CARDFileInfo* fileInfo, void* buf, s32 length, s32 offset) { + s32 result = CARDWriteAsync(fileInfo, buf, length, offset, __CARDSyncCallback); + if (result < 0) { + return result; + } + + return __CARDSync(fileInfo->chan); +} diff --git a/src/dolphin/db/db.c b/src/dolphin/db/db.c new file mode 100644 index 000000000..378aeb646 --- /dev/null +++ b/src/dolphin/db/db.c @@ -0,0 +1,38 @@ +#include "dolphin/base/PPCArch.h" +#include "dolphin/db/db.h" +#include "dolphin/os/OS.h" + +BOOL DBVerbose; +DBInterface* __DBInterface; + +void DBInit(void) { + __DBInterface = OSPhysicalToCached(0x40); + __DBInterface->ExceptionDestination = (void *)OSCachedToPhysical(__DBExceptionDestination); + DBVerbose = TRUE; +} + +void __DBExceptionDestinationAux(void) { + u32* contextAddr; + OSContext* context; + + contextAddr = (void*)0xC0; + context = OSPhysicalToCached(*contextAddr); + OSReport("DBExceptionDestination\n"); + OSDumpContext(context); + PPCHalt(); +} + +asm void __DBExceptionDestination(void) { + nofralloc + mfmsr r3 + ori r3, r3, 0x30 + mtmsr r3 + b __DBExceptionDestinationAux +} + +BOOL __DBIsExceptionMarked(__OSException exception) { + u32 mask = (1 << exception); + return __DBInterface->exceptionMask & mask; +} + +void DBPrintf(char* str, ...) {} diff --git a/src/dolphin/dsp/dsp.c b/src/dolphin/dsp/dsp.c new file mode 100644 index 000000000..3b6d04ccf --- /dev/null +++ b/src/dolphin/dsp/dsp.c @@ -0,0 +1,66 @@ +#include "dolphin/dsp.h" + +const char* __DSPVersion = "<< Dolphin SDK - DSP\trelease build: Sep 5 2002 05:35:13 (0x2301) >>"; + +extern DSPTaskInfo* __DSP_rude_task; +extern int __DSP_rude_task_pending; + +static BOOL __DSP_init_flag; + +extern void __DSPHandler(__OSInterrupt, OSContext*); + +u32 DSPCheckMailToDSP(void) { + return (__DSPRegs[0] & (1 << 15)) >> 15; +} + +u32 DSPCheckMailFromDSP(void) { + return (__DSPRegs[2] & (1 << 15)) >> 15; +} + +u32 DSPReadMailFromDSP(void) { + return (__DSPRegs[2] << 16) | __DSPRegs[3]; +} + +void DSPSendMailToDSP(u32 mail) { + __DSPRegs[0] = mail >> 16; + __DSPRegs[1] = mail & 0xFFFF; +} + +void DSPAssertInt(void) { + BOOL old; + u16 tmp; + + old = OSDisableInterrupts(); + tmp = __DSPRegs[5]; + tmp = (tmp & ~0xA8) | 2; + __DSPRegs[5] = tmp; + OSRestoreInterrupts(old); +} + +void DSPInit(void) { + BOOL old; + u16 tmp; + + __DSP_debug_printf("DSPInit(): Build Date: %s %s\n", "Sep 5 2002", "05:35:13"); + + if (__DSP_init_flag == 1) + return; + + OSRegisterVersion(__DSPVersion); + + old = OSDisableInterrupts(); + __OSSetInterruptHandler(7, __DSPHandler); + __OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_DSP); + + tmp = __DSPRegs[5]; + tmp = (tmp & ~0xA8) | 0x800; + __DSPRegs[5] = tmp; + + tmp = __DSPRegs[5]; + __DSPRegs[5] = tmp = tmp & ~0xAC; + + __DSP_first_task = __DSP_last_task = __DSP_curr_task = __DSP_tmp_task = NULL; + __DSP_init_flag = 1; + + OSRestoreInterrupts(old); +} diff --git a/src/dolphin/dsp/dsp_debug.c b/src/dolphin/dsp/dsp_debug.c new file mode 100644 index 000000000..bf6daffc1 --- /dev/null +++ b/src/dolphin/dsp/dsp_debug.c @@ -0,0 +1,3 @@ +#include "dolphin/dsp.h" + +void __DSP_debug_printf(const char* fmt, ...) {} diff --git a/src/dolphin/dsp/dsp_task.c b/src/dolphin/dsp/dsp_task.c new file mode 100644 index 000000000..74edde2ee --- /dev/null +++ b/src/dolphin/dsp/dsp_task.c @@ -0,0 +1,212 @@ +#include "dolphin/dsp.h" + +DSPTaskInfo* __DSP_curr_task; +DSPTaskInfo* __DSP_first_task; +DSPTaskInfo* __DSP_last_task; +DSPTaskInfo* __DSP_tmp_task; + +void __DSP_exec_task(DSPTaskInfo* curr, DSPTaskInfo* next) { + ASSERTMSGLINE(552, next != NULL, "__DSP_exec_task(): NULL task. It is to weep.\n"); + + if (curr != NULL) { + DSPSendMailToDSP((u32)curr->dram_mmem_addr); + while (DSPCheckMailToDSP() != 0) + ; + DSPSendMailToDSP(curr->dram_length); + while (DSPCheckMailToDSP() != 0) + ; + DSPSendMailToDSP(curr->dram_addr); + while (DSPCheckMailToDSP() != 0) + ; + } else { + DSPSendMailToDSP(0); + while (DSPCheckMailToDSP() != 0) + ; + DSPSendMailToDSP(0); + while (DSPCheckMailToDSP() != 0) + ; + DSPSendMailToDSP(0); + while (DSPCheckMailToDSP() != 0) + ; + } + + DSPSendMailToDSP((u32)next->iram_mmem_addr); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(next->iram_length); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(next->iram_addr); + while (DSPCheckMailToDSP() != 0) + ; + + if (next->state == 0) { + DSPSendMailToDSP(next->dsp_init_vector); + while (DSPCheckMailToDSP() != 0) + ; + DSPSendMailToDSP(0); + while (DSPCheckMailToDSP() != 0) + ; + DSPSendMailToDSP(0); + while (DSPCheckMailToDSP() != 0) + ; + DSPSendMailToDSP(0); + while (DSPCheckMailToDSP() != 0) + ; + } else { + DSPSendMailToDSP(next->dsp_resume_vector); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP((u32)next->dram_mmem_addr); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(next->dram_length); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(next->dram_addr); + while (DSPCheckMailToDSP() != 0) + ; + } +} + +void __DSP_boot_task(DSPTaskInfo* task) { + volatile u32 mail; + + ASSERTMSGLINE(634, task != NULL, "__DSP_boot_task(): NULL task!\n"); + while (DSPCheckMailFromDSP() == 0) + ; + + mail = DSPReadMailFromDSP(); + ASSERTMSGLINEV(640, mail == 0x8071FEED, "__DSP_boot_task(): Failed to sync DSP on boot! (0x%08X)\n", mail); + + DSPSendMailToDSP(0x80F3A001); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP((u32)task->iram_mmem_addr); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(0x80F3C002); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(task->iram_addr & 0xFFFF); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(0x80F3A002); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(task->iram_length); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(0x80F3B002); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(0); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(0x80F3D001); + while (DSPCheckMailToDSP() != 0) + ; + + DSPSendMailToDSP(task->dsp_init_vector); + while (DSPCheckMailToDSP() != 0) + ; + + __DSP_debug_printf("DSP is booting task: 0x%08X\n", (u32)task); + __DSP_debug_printf("__DSP_boot_task() : IRAM MMEM ADDR: 0x%08X\n", (u32)task->iram_mmem_addr); + __DSP_debug_printf("__DSP_boot_task() : IRAM DSP ADDR : 0x%08X\n", task->iram_addr); + __DSP_debug_printf("__DSP_boot_task() : IRAM LENGTH : 0x%08X\n", task->iram_length); + __DSP_debug_printf("__DSP_boot_task() : DRAM MMEM ADDR: 0x%08X\n", task->dram_length); + __DSP_debug_printf("__DSP_boot_task() : Start Vector : 0x%08X\n", task->dsp_init_vector); +} + +void __DSP_insert_task(DSPTaskInfo* task) { + DSPTaskInfo* temp; + + if (__DSP_first_task == NULL) { + __DSP_curr_task = task; + __DSP_first_task = __DSP_last_task = task; + task->next = task->prev = NULL; + return; + } + + temp = __DSP_first_task; + while (temp != NULL) { + if (task->priority < temp->priority) { + task->prev = temp->prev; + temp->prev = task; + task->next = temp; + if (task->prev == NULL) + __DSP_first_task = task; + else + task->prev->next = task; + break; + } + temp = temp->next; + } + + if (temp == NULL) { + __DSP_last_task->next = task; + task->next = NULL; + task->prev = __DSP_last_task; + __DSP_last_task = task; + } +} + +void __DSP_add_task(DSPTaskInfo* task) { + ASSERTMSGLINE(771, task != NULL, "__DSP_add_task(): Why are you adding a NULL task?\n"); + + if (__DSP_last_task == NULL) { + __DSP_curr_task = task; + __DSP_last_task = task; + __DSP_first_task = task; + task->next = task->prev = NULL; + } else { + __DSP_last_task->next = task; + task->next = NULL; + task->prev = __DSP_last_task; + __DSP_last_task = task; + } + + task->state = 0; + __DSP_debug_printf("__DSP_add_task() : Added task : 0x%08X\n", (u32)task); +} + +void __DSP_remove_task(DSPTaskInfo* task) { + ASSERTMSGLINE(813, task != NULL, "__DSP_remove_task(): NULL task! Why? WHY?!?!\n"); + task->flags = 0; + task->state = 3; + + if (__DSP_first_task == task) { + if (task->next != NULL) { + __DSP_first_task = task->next; + task->next->prev = NULL; + } + else + __DSP_first_task = __DSP_last_task = __DSP_curr_task = NULL; + return; + } + + if (__DSP_last_task == task) { + __DSP_last_task = task->prev; + task->prev->next = NULL; + __DSP_curr_task = __DSP_first_task; + return; + } + + __DSP_curr_task = task->next; + task->prev->next = task->next; + task->next->prev = task->prev; +} diff --git a/src/dolphin/exi/EXIBios.c b/src/dolphin/exi/EXIBios.c new file mode 100644 index 000000000..b20eb31c2 --- /dev/null +++ b/src/dolphin/exi/EXIBios.c @@ -0,0 +1,828 @@ +#include "dolphin/exi/EXIBios.h" +#include "dolphin/os/OS.h" + +extern int __gUnknown800030C0[2] AT_ADDRESS(OS_BASE_CACHED | 0x30C0); + +#define REG_MAX 5 +#define REG(chan, idx) (__EXIRegs[((chan) * REG_MAX) + (idx)]) + +#define STATE_IDLE 0 +#define STATE_DMA 1 +#define STATE_IMM 2 +#define STATE_BUSY 3 +#define STATE_SELECTED 4 +#define STATE_ATTACHED 8 +#define STATE_LOCKED 16 + +#define MAX_CHAN 3 + +#define MAX_IMM 4 +#define MAX_TYPE 3 +#define MAX_DEV 3 +#define MAX_FREQ 6 + +#define EXI_0LENGTH_EXILENGTH_MASK 0x03FFFFE0 + +const char* __EXIVersion = "<< Dolphin SDK - EXI\trelease build: Sep 5 2002 05:33:04 (0x2301) >>"; + +static EXIControl Ecb[3]; + +// external functions +extern void __OSEnableBarnacle(s32 chan, u32 dev); + +// prototypes +u32 EXIClearInterrupts(s32 chan, int exi, int tc, int ext); +static int __EXIProbe(s32 chan); + +static void SetExiInterruptMask(s32 chan, EXIControl* exi) { + EXIControl* exi2; + exi2 = &Ecb[2]; + + switch (chan) { + case 0: + if ((exi->exiCallback == 0 && exi2->exiCallback == 0) || (exi->state & STATE_LOCKED)) { + __OSMaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_2_EXI); + } else { + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_2_EXI); + } + break; + case 1: + if (exi->exiCallback == 0 || (exi->state & STATE_LOCKED)) { + __OSMaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXI); + } else { + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXI); + } + break; + case 2: + if (__OSGetInterruptHandler(0x19) == 0 || (exi->state & STATE_LOCKED)) { + __OSMaskInterrupts(OS_INTERRUPTMASK_PI_DEBUG); + } else { + __OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_DEBUG); + } + break; + } +} + +static void CompleteTransfer(s32 chan) { + EXIControl* exi; + u8* buf; + u32 data; + int i; + int len; + + exi = &Ecb[chan]; + ASSERTLINE(366, 0 <= chan && chan < MAX_CHAN); + + if (exi->state & STATE_BUSY) { + if (exi->state & STATE_IMM) { + if ((len = exi->immLen) != 0) { + buf = exi->immBuf; + data = __EXIRegs[(chan * 5) + 4]; + for(i = 0; i < len; i++) { + *buf++ = data >> ((3 - i) * 8); + } + } + } + exi->state &= ~STATE_BUSY; + } +} + +s32 EXIImm(s32 chan, void* buf, s32 len, u32 type, EXICallback callback) { + EXIControl* exi; + BOOL enabled; + u32 data; + int i; + + exi = &Ecb[chan]; + ASSERTLINE(404, exi->state & STATE_SELECTED); + ASSERTLINE(405, 0 <= chan && chan < MAX_CHAN); + ASSERTLINE(406, 0 < len && len <= MAX_IMM); + ASSERTLINE(407, type < MAX_TYPE); + enabled = OSDisableInterrupts(); + + if ((exi->state & STATE_BUSY) || !(exi->state & STATE_SELECTED)) { + OSRestoreInterrupts(enabled); + return 0; + } + + exi->tcCallback = callback; + if (exi->tcCallback) { + EXIClearInterrupts(chan, 0, 1, 0); + __OSUnmaskInterrupts(0x200000U >> (chan * 3)); + } + + exi->state |= STATE_IMM; + if (type != 0) { + data = 0; + for(i = 0; i < len; i++) { + data |= ((u8*)buf)[i] << ((3 - i) * 8); + } + __EXIRegs[(chan * 5) + 4] = data; + } + + exi->immBuf = buf; + exi->immLen = (type != 1) ? len : 0; + __EXIRegs[(chan * 5) + 3] = (type << 2) | 1 | ((len - 1) << 4); + OSRestoreInterrupts(enabled); + return 1; +} + +s32 EXIImmEx(s32 chan, void* buf, s32 len, u32 mode) { + s32 xLen; + + while (len) { + xLen = (len < 4) ? len : 4; + if (EXIImm(chan, buf, xLen, mode, 0) == 0) { + return 0; + } + if (EXISync(chan) == 0) { + return 0; + } + ((u8*)buf) += xLen; + len -= xLen; + } + + return 1; +} + +int EXIDma(s32 chan, void* buf, s32 len, u32 type, EXICallback callback) { + EXIControl* exi; + BOOL enabled; + + exi = &Ecb[chan]; + + ASSERTLINE(509, exi->state & STATE_SELECTED); + ASSERTLINE(510, OFFSET(buf, 32) == 0); + ASSERTLINE(511, 0 < len && OFFSET(len, 32) == 0); + ASSERTLINE(513, ((u32) len & ~EXI_0LENGTH_EXILENGTH_MASK) == 0); + ASSERTLINE(515, type == EXI_READ || type == EXI_WRITE); + + enabled = OSDisableInterrupts(); + if ((exi->state & STATE_BUSY) || !(exi->state & STATE_SELECTED)) { + OSRestoreInterrupts(enabled); + return 0; + } + + exi->tcCallback = callback; + if ((u32)exi->tcCallback) { + EXIClearInterrupts(chan, 0, 1, 0); + __OSUnmaskInterrupts(0x200000U >> (chan * 3)); + } + + exi->state |= STATE_DMA; + __EXIRegs[(chan * 5) + 1] = (u32)buf & EXI_0LENGTH_EXILENGTH_MASK; + __EXIRegs[(chan * 5) + 2] = len; + __EXIRegs[(chan * 5) + 3] = (type * 4) | 3; + + OSRestoreInterrupts(enabled); + return 1; +} + +int EXISync(s32 chan) { + EXIControl* exi; + int rc; + BOOL enabled; + + exi = &Ecb[chan]; + rc = 0; + ASSERTLINE(565, 0 <= chan && chan < MAX_CHAN); + + while ((exi->state & STATE_SELECTED)) { + if (!(__EXIRegs[(chan * 5) + 3] & 1)) { + enabled = OSDisableInterrupts(); + if (exi->state & STATE_SELECTED) { + CompleteTransfer(chan); + if (__OSGetDIConfig() != 0xFF || exi->immLen != 4 || (__EXIRegs[chan * 5] & 0x70) || (__EXIRegs[(chan * 5) + 4] != 0x01010000 && __EXIRegs[(chan * 5) + 4] != 0x05070000 && __EXIRegs[(chan * 5) + 4] != 0x04220001) || __OSDeviceCode == 0x8200) { + rc = 1; + } + } + OSRestoreInterrupts(enabled); + break; + } + } + + ASSERTLINE(593, !(exi->state & STATE_BUSY)); + return rc; +} + +u32 EXIClearInterrupts(s32 chan, int exi, int tc, int ext) { + u32 cpr; + u32 prev; + + ASSERTLINE(614, 0 <= chan && chan < MAX_CHAN); + + cpr = prev = __EXIRegs[(chan * 5)]; + prev &= 0x7F5; + + if (exi != 0) { + prev |= 2; + } + + if (tc != 0) { + prev |= 8; + } + + if (ext != 0) { + prev |= 0x800; + } + + __EXIRegs[(chan * 5)] = prev; + return cpr; +} + +EXICallback EXISetExiCallback(s32 chan, EXICallback exiCallback) { + EXIControl* exi; + EXICallback prev; + BOOL enabled; + + exi = &Ecb[chan]; + ASSERTLINE(648, 0 <= chan && chan < MAX_CHAN); + enabled = OSDisableInterrupts(); + + prev = exi->exiCallback; + exi->exiCallback = exiCallback; + if (chan != 2) { + SetExiInterruptMask(chan, exi); + } else { + SetExiInterruptMask(0, &Ecb[0]); + } + + OSRestoreInterrupts(enabled); + return prev; +} + +void EXIProbeReset() { + __gUnknown800030C0[0] = __gUnknown800030C0[1] = 0; + Ecb[0].idTime = Ecb[1].idTime = 0; + __EXIProbe(0); + __EXIProbe(1); +} + +static int __EXIProbe(s32 chan) { + EXIControl* exi; + BOOL enabled; + int rc; + u32 cpr; + s32 t; + + exi = &Ecb[chan]; + ASSERTLINE(703, 0 <= chan && chan < MAX_CHAN); + if (chan == 2) { + return 1; + } + + rc = 1; + enabled = OSDisableInterrupts(); + cpr = __EXIRegs[(chan * 5)]; + + if (!(exi->state & STATE_ATTACHED)) { + if (cpr & 0x800) { + EXIClearInterrupts(chan, 0, 0, 1); + __gUnknown800030C0[chan] = exi->idTime = 0; + } + + if (cpr & 0x1000) { + t = ((s32)(OSTicksToMilliseconds(OSGetTime()) / 100) + 1); + + if (__gUnknown800030C0[chan] == 0) { + __gUnknown800030C0[chan] = t; + } + + if (t - (s32)__gUnknown800030C0[chan] < 3) { + rc = 0; + } + } else { + __gUnknown800030C0[chan] = exi->idTime = 0; + rc = 0; + } + } else if(!(cpr & 0x1000) || (cpr & 0x800)) { + __gUnknown800030C0[chan] = exi->idTime = 0; + rc = 0; + } + + OSRestoreInterrupts(enabled); + return rc; +} + +int EXIProbe(s32 chan) { + EXIControl* exi = &Ecb[chan]; + int rc; + u32 id; + + rc = __EXIProbe(chan); + if (rc && !exi->idTime) { + rc = EXIGetID(chan, 0, &id) ? 1 : 0; + } + + return rc; +} + +s32 EXIProbeEx(s32 chan) { + if (EXIProbe(chan)) { + return 1; + } + + if (__gUnknown800030C0[chan]) { + return 0; + } + + return -1; +} + +static int __EXIAttach(s32 chan, EXICallback extCallback) { + EXIControl* exi; + BOOL enabled; + + exi = &Ecb[chan]; + ASSERTLINE(808, 0 <= chan && chan < 2); + enabled = OSDisableInterrupts(); + + if ((exi->state & STATE_ATTACHED) || !__EXIProbe(chan)) { + OSRestoreInterrupts(enabled); + return 0; + } + + EXIClearInterrupts(chan, 1, 0, 0); + exi->extCallback = extCallback; + __OSUnmaskInterrupts(0x100000U >> (chan * 3)); + exi->state |= STATE_ATTACHED; + + OSRestoreInterrupts(enabled); + return 1; +} + +int EXIAttach(s32 chan, EXICallback extCallback) { + EXIControl* exi; + BOOL enabled; + int rc; + + exi = &Ecb[chan]; + ASSERTLINE(834, 0 <= chan && chan < 2); + + EXIProbe(chan); + enabled = OSDisableInterrupts(); + if (exi->idTime == 0) { + OSRestoreInterrupts(enabled); + return 0; + } + + rc = __EXIAttach(chan, extCallback); + OSRestoreInterrupts(enabled); + return rc; +} + +int EXIDetach(s32 chan) { + EXIControl* exi; + BOOL enabled; + + exi = &Ecb[chan]; + ASSERTLINE(868, 0 <= chan && chan < 2); + enabled = OSDisableInterrupts(); + + if (!(exi->state & STATE_ATTACHED)) { + OSRestoreInterrupts(enabled); + return 1; + } + + if ((exi->state & STATE_LOCKED) && (exi->dev == 0)) { + OSRestoreInterrupts(enabled); + return 0; + } + + exi->state &= ~STATE_ATTACHED; + __OSMaskInterrupts(0x500000U >> (chan * 3)); + + OSRestoreInterrupts(enabled); + return 1; +} + +int EXISelectSD(s32 chan, u32 dev, u32 freq) { + EXIControl* exi; + u32 cpr; + BOOL enabled; + + exi = &Ecb[chan]; + + ASSERTLINE(908, 0 <= chan && chan < MAX_CHAN); + ASSERTLINE(909, chan == 0 && dev < MAX_DEV || dev == 0); + ASSERTLINE(910, freq < MAX_FREQ); + ASSERTLINE(911, !(exi->state & STATE_SELECTED)); + + enabled = OSDisableInterrupts(); + if ((exi->state & STATE_SELECTED) || ((chan != 2) && (((dev == 0) && !(exi->state & STATE_ATTACHED) && (EXIProbe(chan) == 0)) || !(exi->state & STATE_LOCKED) || (exi->dev != dev)))) { + OSRestoreInterrupts(enabled); + return 0; + } + + exi->state |= STATE_SELECTED; + cpr = __EXIRegs[(chan * 5)]; + cpr &= 0x405; + cpr |= freq * 0x10; + __EXIRegs[(chan * 5)] = cpr; + + if (exi->state & STATE_ATTACHED) { + switch (chan) { + case 0: + __OSMaskInterrupts(0x100000U); + break; + case 1: + __OSMaskInterrupts(0x20000U); + break; + } + } + + OSRestoreInterrupts(enabled); + return 1; +} + +int EXISelect(s32 chan, u32 dev, u32 freq) { + EXIControl* exi; + u32 cpr; + BOOL enabled; + + exi = &Ecb[chan]; + + ASSERTLINE(966, 0 <= chan && chan < MAX_CHAN); + ASSERTLINE(967, chan == 0 && dev < MAX_DEV || dev == 0); + ASSERTLINE(968, freq < MAX_FREQ); + ASSERTLINE(969, !(exi->state & STATE_SELECTED)); + + enabled = OSDisableInterrupts(); + if ((exi->state & STATE_SELECTED) || ((chan != 2) && (((dev == 0) && !(exi->state & STATE_ATTACHED) && (__EXIProbe(chan) == 0)) || !(exi->state & STATE_LOCKED) || (exi->dev != dev)))) { + OSRestoreInterrupts(enabled); + return 0; + } + + exi->state |= STATE_SELECTED; + cpr = __EXIRegs[(chan * 5)]; + cpr &= 0x405; + cpr |= (((1 << dev) << 7) | (freq * 0x10)); + __EXIRegs[(chan * 5)] = cpr; + + if (exi->state & STATE_ATTACHED) { + switch (chan) { + case 0: + __OSMaskInterrupts(0x100000U); + break; + case 1: + __OSMaskInterrupts(0x20000U); + break; + } + } + + OSRestoreInterrupts(enabled); + return 1; +} + +int EXIDeselect(s32 chan) { + EXIControl* exi; + u32 cpr; + BOOL enabled; + + exi = &Ecb[chan]; + ASSERTLINE(1020, 0 <= chan && chan < MAX_CHAN); + enabled = OSDisableInterrupts(); + + if (!(exi->state & STATE_SELECTED)) { + OSRestoreInterrupts(enabled); + return 0; + } + + exi->state &= ~STATE_SELECTED; + cpr = __EXIRegs[(chan * 5)]; + __EXIRegs[(chan * 5)] = cpr & 0x405; + + if (exi->state & STATE_ATTACHED) { + switch (chan) { + case 0: + __OSUnmaskInterrupts(0x100000U); + break; + case 1: + __OSUnmaskInterrupts(0x20000U); + break; + } + } + + OSRestoreInterrupts(enabled); + + if ((chan != 2) && (cpr & 0x80)) { + if (__EXIProbe(chan) != 0) { + return 1; + } + return 0; + } + + return 1; +} + +static void EXIIntrruptHandler(__OSInterrupt interrupt, OSContext* context) { + s32 chan; + EXIControl* exi; + EXICallback callback; + + chan = (interrupt - 9) / 3; + + ASSERTLINE(1071, 0 <= chan && chan < MAX_CHAN); + exi = &Ecb[chan]; + EXIClearInterrupts(chan, 1, 0, 0); + + callback = exi->exiCallback; + if (callback) { + OSContext exceptionContext; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + callback(chan, context); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +static void TCIntrruptHandler(__OSInterrupt interrupt, OSContext* context) { + s32 chan; + EXIControl* exi; + EXICallback callback; + + chan = (interrupt - 10) / 3; + + ASSERTLINE(1107, 0 <= chan && chan < MAX_CHAN); + exi = &Ecb[chan]; + __OSMaskInterrupts(0x80000000U >> interrupt); + EXIClearInterrupts(chan, 0, 1, 0); + + callback = exi->tcCallback; + if (callback) { + OSContext exceptionContext; + + exi->tcCallback = NULL; + CompleteTransfer(chan); + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + callback(chan, context); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +static void EXTIntrruptHandler(__OSInterrupt interrupt, OSContext* context) { + s32 chan; + EXIControl* exi; + EXICallback callback; + + chan = (interrupt - 11) / 3; + + ASSERTLINE(1147, 0 <= chan && chan < 2); + __OSMaskInterrupts(0x500000U >> (chan * 3)); + exi = &Ecb[chan]; + callback = exi->extCallback; + exi->state &= ~STATE_ATTACHED; + + if (callback) { + OSContext exceptionContext; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + exi->extCallback = NULL; + callback(chan, context); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +void EXIInit() { + OSRegisterVersion(__EXIVersion); + __OSMaskInterrupts(0x7F8000U); + __EXIRegs[0] = 0; + __EXIRegs[5] = 0; + __EXIRegs[10] = 0; + __EXIRegs[0] = 0x2000; + __OSSetInterruptHandler(9, EXIIntrruptHandler); + __OSSetInterruptHandler(10, TCIntrruptHandler); + __OSSetInterruptHandler(11, EXTIntrruptHandler); + __OSSetInterruptHandler(12, EXIIntrruptHandler); + __OSSetInterruptHandler(13, TCIntrruptHandler); + __OSSetInterruptHandler(14, EXTIntrruptHandler); + __OSSetInterruptHandler(15, EXIIntrruptHandler); + __OSSetInterruptHandler(16, TCIntrruptHandler); + + if (OSGetConsoleType() & 0x10000000) { + EXIProbeReset(); + } +} + +int EXILock(s32 chan, u32 dev, EXICallback unlockedCallback) { + EXIControl* exi; + BOOL enabled; + int i; + + exi = &Ecb[chan]; + ASSERTLINE(1259, 0 <= chan && chan < MAX_CHAN); + ASSERTLINE(1260, chan == 0 && dev < MAX_DEV || dev == 0); + enabled = OSDisableInterrupts(); + + if (exi->state & STATE_LOCKED) { + if (unlockedCallback) { + ASSERTLINE(1266, chan == 0 && exi->items < (MAX_DEV - 1) || exi->items == 0); + for(i = 0; i < exi->items; i++) { + if (exi->queue[i].dev == dev) { + OSRestoreInterrupts(enabled); + return 0; + } + } + exi->queue[exi->items].callback = unlockedCallback; + exi->queue[exi->items].dev = dev; + exi->items++; + } + OSRestoreInterrupts(enabled); + return 0; + } + + ASSERTLINE(1282, exi->items == 0); + exi->state |= STATE_LOCKED; + exi->dev = dev; + SetExiInterruptMask(chan, exi); + OSRestoreInterrupts(enabled); + return 1; +} + +int EXIUnlock(s32 chan) { + EXIControl* exi; + BOOL enabled; + EXICallback unlockedCallback; + + exi = &Ecb[chan]; + ASSERTLINE(1306, 0 <= chan && chan < MAX_CHAN); + enabled = OSDisableInterrupts(); + + if (!(exi->state & STATE_LOCKED)) { + OSRestoreInterrupts(enabled); + return 0; + } + + exi->state &= ~STATE_LOCKED; + SetExiInterruptMask(chan, exi); + if (exi->items > 0) { + unlockedCallback = exi->queue[0].callback; + if (--exi->items > 0) { + memmove(&exi->queue[0], &exi->queue[1], exi->items * 8); + } + unlockedCallback(chan, 0); + } + + OSRestoreInterrupts(enabled); + return 1; +} + +u32 EXIGetState(s32 chan) { + EXIControl* exi; + + exi = &Ecb[chan]; + ASSERTLINE(1343, 0 <= chan && chan < MAX_CHAN); + return exi->state; +} + +static void UnlockedHandler(s32 chan, OSContext* context) { + u32 id; + EXIGetID(chan, 0, &id); +} + +s32 EXIGetID(s32 chan, u32 dev, u32* id) { + EXIControl* exi = &Ecb[chan]; + int err; + u32 cmd; + s32 startTime; + BOOL enabled; + + ASSERTLINE(1380, 0 <= chan && chan < MAX_CHAN); + if ((chan < 2) && (dev == 0)) { + if ((__EXIProbe(chan) == 0)) { + return 0; + } + + if (exi->idTime == __gUnknown800030C0[chan]) { + *id = exi->id; + return exi->idTime; + } + + if (!__EXIAttach(chan, NULL)) { + return 0; + } + + startTime = __gUnknown800030C0[chan]; + } + + err = !EXILock(chan, dev, (chan < 2 && dev == 0) ? &UnlockedHandler : NULL); + if (err == 0) { + err = !EXISelect(chan, dev, 0); + if (err == 0) { + cmd = 0; + err |= !EXIImm(chan, &cmd, 2, 1, 0); + err |= !EXISync(chan); + err |= !EXIImm(chan, id, 4, 0, 0); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + } + + EXIUnlock(chan); + } + + if ((chan < 2) && (dev == 0)) { + EXIDetach(chan); + enabled = OSDisableInterrupts(); + err |= __gUnknown800030C0[chan] != startTime; + + if (!err) { + exi->id = *id; + exi->idTime = startTime; + } + + OSRestoreInterrupts(enabled); + + if (err) { + return 0; + } + + return exi->idTime; + } + + if (err) { + return 0; + } + + return 1; +} + +s32 EXIGetType(s32 chan, u32 dev, u32* type) { + u32 _type; + s32 probe; + + probe = EXIGetID(chan, dev, &_type); + + if (!probe) { + return probe; + } + + switch (_type & ~0xFF) { + case 0x04020300: + case EXI_ETHER: + case 0x04020100: + case 0x04060000: + *type = (_type & ~0xFF); + return probe; + default: + switch (_type & ~0xFFFF) { + case 0x00000000: + if (!(_type & 0x3803)) { + switch (_type & 0xFC) { + case EXI_MEMORY_CARD_59: + case EXI_MEMORY_CARD_123: + case EXI_MEMORY_CARD_251: + case EXI_MEMORY_CARD_507: + case EXI_MEMORY_CARD_1019: + case EXI_MEMORY_CARD_2043: + *type = _type & 0xFC; + return probe; + } + } + break; + case EXI_IS_VIEWER: + *type = EXI_IS_VIEWER; + return probe; + } + + *type = _type; + return probe; + } +} + +char* EXIGetTypeString(u32 type) { + switch (type) { + case EXI_MEMORY_CARD_59: + return "Memory Card 59"; + case EXI_MEMORY_CARD_123: + return "Memory Card 123"; + case EXI_MEMORY_CARD_251: + return "Memory Card 251"; + case EXI_MEMORY_CARD_507: + return "Memory Card 507"; + case EXI_USB_ADAPTER: + return "USB Adapter"; + case 0x80000020: + case 0x80000080: + case 0x80000040: + case 0x80000008: + case 0x80000010: + case 0x80000004: + return "Net Card"; + case EXI_ETHER_VIEWER: + return "Artist Ether"; + case 0x4020100: + case 0x4020300: + case EXI_ETHER: + case EXI_STREAM_HANGER: + return "Stream Hanger"; + case EXI_IS_VIEWER: + return "IS Viewer"; + } +} diff --git a/src/dolphin/exi/EXIUart.c b/src/dolphin/exi/EXIUart.c new file mode 100644 index 000000000..b4981051f --- /dev/null +++ b/src/dolphin/exi/EXIUart.c @@ -0,0 +1,113 @@ +#include "dolphin/exi/EXIUart.h" +#include "dolphin/os/OS.h" + +static s32 Chan; +static u32 Dev; +static u32 Enabled; +static u32 BarnacleEnabled; + +// prototypes +int InitializeUART(void); +int ReadUARTN(void); +int WriteUARTN(void *buf, u32 len); + +int InitializeUART(void) { + if (BarnacleEnabled == 0xA5FF005A) { + return 0; + } + + if ((OSGetConsoleType() & 0x10000000) == 0) { + Enabled = 0; + return 2; + } + + Chan = 0; + Dev = 1; + Enabled = 0xA5FF005A; + return 0; +} + +int ReadUARTN(void) { + return 4; +} + +static int QueueLength(void) { + u32 cmd; + + if (EXISelect(Chan, Dev, 3) == 0) { + return -1; + } + + cmd = 0x20010000; + EXIImm(Chan, &cmd, sizeof(cmd), EXI_WRITE, 0); + EXISync(Chan); + EXIImm(Chan, &cmd, 1, EXI_READ, 0); + EXISync(Chan); + EXIDeselect(Chan); + return 0x10 - (cmd >> 0x18); +} + +int WriteUARTN(void *buf, u32 len) { + u32 cmd; + s32 xLen; + int qLen; + char* ptr; + int locked; + int error; + + if ((Enabled - 0xA5FF0000) != 0x5A) { + return 2; + } + + locked = EXILock(Chan, Dev, 0); + if (locked == 0) { + return 0; + } else { + ptr = (char*)buf; + } + + while ((u32)ptr - (u32)buf < len) { + if (*(s8*)ptr == 0xA) { + *ptr = 0xD; + } + ptr++; + } + error = 0; + cmd = 0xA0010000; + + while (len != 0) { + qLen = QueueLength(); + if (qLen < 0) { + error = 3; + break; + } + + if ((qLen >= 0xC) || (qLen >= len)) { + if (EXISelect(Chan, Dev, EXI_FREQ_8M) == 0) { + error = 3; + break; + } + + EXIImm(Chan, &cmd, sizeof(cmd), EXI_WRITE, 0); + EXISync(Chan); + + while((qLen != 0) && (len != 0)) { + if ((qLen < 4) && (qLen < len)) { + break; + } + + xLen = len < 4 ? (long)len : 4; + + EXIImm(Chan, buf, xLen, EXI_WRITE, 0); + (char*)buf += xLen; + len -= xLen; + qLen -= xLen; + EXISync(Chan); + } + EXIDeselect(Chan); + } + } + + EXIUnlock(Chan); + return error; +} diff --git a/src/dolphin/gd/GDBase.c b/src/dolphin/gd/GDBase.c new file mode 100644 index 000000000..8b64442e5 --- /dev/null +++ b/src/dolphin/gd/GDBase.c @@ -0,0 +1,37 @@ +#include "dolphin/gd/GDBase.h" +#include "dolphin/os/OS.h" + +GDLObj* __GDCurrentDL = NULL; +static GDOverflowCallback overflowcb = NULL; + +void GDInitGDLObj(GDLObj* dl, void* start, u32 length) { + ASSERTMSGLINE(40, !((u32)start & 0x1F), "start must be aligned to 32 bytes"); + ASSERTMSGLINE(41, !((u32)length & 0x1F), "length must be aligned to 32 bytes"); + dl->start = start; + dl->ptr = start; + dl->top = (u8*)start + length; + dl->length = length; +} + +void GDFlushCurrToMem(void) { + DCFlushRange(__GDCurrentDL->start, __GDCurrentDL->length); +} + +void GDPadCurr32(void) { + u32 n; + + n = (u32)__GDCurrentDL->ptr & 0x1F; + if (n != 0) { + for (; n < 32; n = n + 1) { + __GDWrite(0); + } + } +} + +void GDOverflowed(void) { + if (overflowcb) { + (*overflowcb)(); + } else { + ASSERTMSGLINE(77, 0, "GDWrite: display list overflowed"); + } +} diff --git a/src/dolphin/gd/GDGeometry.c b/src/dolphin/gd/GDGeometry.c new file mode 100644 index 000000000..525d597c9 --- /dev/null +++ b/src/dolphin/gd/GDGeometry.c @@ -0,0 +1,144 @@ +#include "dolphin/gx/GX.h" +#include "dolphin/gd/GDGeometry.h" +#include "dolphin/gd/GDBase.h" +#include "dolphin/os/OS.h" + +void GDSetVtxDescv(GXVtxDescList* attrPtr) { + u32 nnorms = 0; + u32 ncols = 0; + u32 ntexs = 0; + u32 pnMtxIdx = GX_NONE; + u32 txMtxIdxMask = 0; + u32 posn = GX_DIRECT; + u32 norm = GX_NONE; + u32 col0 = GX_NONE; + u32 col1 = GX_NONE; + u32 tex0 = GX_NONE; + u32 tex1 = GX_NONE; + u32 tex2 = GX_NONE; + u32 tex3 = GX_NONE; + u32 tex4 = GX_NONE; + u32 tex5 = GX_NONE; + u32 tex6 = GX_NONE; + u32 tex7 = GX_NONE; + + for (; attrPtr->attr != GX_VA_NULL; ++attrPtr) { + ASSERTMSGLINE(91, attrPtr->attr >= GX_VA_PNMTXIDX && attrPtr->attr <= GX_VA_MAX_ATTR, "GDSetVtxDescv: invalid attribute"); + ASSERTMSGLINE(95, attrPtr->type >= GX_NONE && attrPtr->type <= GX_INDEX16, "GDSetVtxDescv: invalid type"); + + ASSERTMSGLINE(101, attrPtr->attr >= GX_VA_PNMTXIDX && attrPtr->attr <= GX_VA_TEX7MTXIDX ? (attrPtr->type == 0 || attrPtr->type == 1) : TRUE, "GDSetVtxDescv: invalid type for given attribute"); + + switch (attrPtr->attr) { + case GX_VA_PNMTXIDX: + pnMtxIdx = attrPtr->type; + break; + case GX_VA_TEX0MTXIDX: + txMtxIdxMask = (txMtxIdxMask & ~0x1) | (attrPtr->type << 0); + break; + case GX_VA_TEX1MTXIDX: + txMtxIdxMask = (txMtxIdxMask & ~0x2) | (attrPtr->type << 1); + break; + case GX_VA_TEX2MTXIDX: + txMtxIdxMask = (txMtxIdxMask & ~0x4) | (attrPtr->type << 2); + break; + case GX_VA_TEX3MTXIDX: + txMtxIdxMask = (txMtxIdxMask & ~0x8) | (attrPtr->type << 3); + break; + case GX_VA_TEX4MTXIDX: + txMtxIdxMask = (txMtxIdxMask & ~0x10) | (attrPtr->type << 4); + break; + case GX_VA_TEX5MTXIDX: + txMtxIdxMask = (txMtxIdxMask & ~0x20) | (attrPtr->type << 5); + break; + case GX_VA_TEX6MTXIDX: + txMtxIdxMask = (txMtxIdxMask & ~0x40) | (attrPtr->type << 6); + break; + case GX_VA_TEX7MTXIDX: + txMtxIdxMask = (txMtxIdxMask & ~0x80) | (attrPtr->type << 7); + break; + case GX_VA_POS: + posn = attrPtr->type; + break; + case GX_VA_NRM: + if (attrPtr->type != GX_NONE) { + norm = attrPtr->type; + nnorms = 1; + } + break; + case GX_VA_NBT: + if (attrPtr->type != GX_NONE) { + norm = attrPtr->type; + nnorms = 2; + } + break; + case GX_VA_CLR0: + col0 = attrPtr->type; + ncols += (col0 != GX_NONE); + break; + case GX_VA_CLR1: + col1 = attrPtr->type; + ncols += (col1 != GX_NONE); + break; + case GX_VA_TEX0: + tex0 = attrPtr->type; + ntexs += (tex0 != GX_NONE); + break; + case GX_VA_TEX1: + tex1 = attrPtr->type; + ntexs += (tex1 != GX_NONE); + break; + case GX_VA_TEX2: + tex2 = attrPtr->type; + ntexs += (tex2 != GX_NONE); + break; + case GX_VA_TEX3: + tex3 = attrPtr->type; + ntexs += (tex3 != GX_NONE); + break; + case GX_VA_TEX4: + tex4 = attrPtr->type; + ntexs += (tex4 != GX_NONE); + break; + case GX_VA_TEX5: + tex5 = attrPtr->type; + ntexs += (tex5 != GX_NONE); + break; + case GX_VA_TEX6: + tex6 = attrPtr->type; + ntexs += (tex6 != GX_NONE); + break; + case GX_VA_TEX7: + tex7 = attrPtr->type; + ntexs += (tex7 != GX_NONE); + break; + } + } + + GDWriteCPCmd(CP_REG_VCD_LO_ID, CP_REG_VCD_LO(pnMtxIdx, txMtxIdxMask, posn, norm, col0, col1)); + GDWriteCPCmd(CP_REG_VCD_HI_ID, CP_REG_VCD_HI(tex0, tex1, tex2, tex3, tex4, tex5, tex6, tex7)); + GDWriteXFCmd(XF_REG_INVERTEXSPEC_ID, XF_REG_INVTXSPEC(ncols, nnorms, ntexs)); +} + +void GDSetArray(GXAttr attr, void* base_ptr, u8 stride) { + s32 cpAttr; + if (attr == GX_VA_NBT) { + cpAttr = GX_VA_TEX0MTXIDX; + } else { + cpAttr = attr - GX_VA_POS; + } + + GDWriteCPCmd(cpAttr + CP_REG_ARRAYBASE_ID, OSCachedToPhysical(base_ptr)); + GDWriteCPCmd(cpAttr + CP_REG_ARRAYSTRIDE_ID, stride); +} + +void GDSetArrayRaw(GXAttr attr, u32 base_ptr_raw, u8 stride) { + s32 cpAttr; + if (attr == GX_VA_NBT) { + cpAttr = GX_VA_TEX0MTXIDX; + } else { + cpAttr = attr - GX_VA_POS; + } + + GDWriteCPCmd(cpAttr + CP_REG_ARRAYBASE_ID, base_ptr_raw); + GDWriteCPCmd(cpAttr + CP_REG_ARRAYSTRIDE_ID, stride); +} diff --git a/src/dolphin/gf/GFGeometry.cpp b/src/dolphin/gf/GFGeometry.cpp new file mode 100644 index 000000000..95ccaff25 --- /dev/null +++ b/src/dolphin/gf/GFGeometry.cpp @@ -0,0 +1,20 @@ +#include "dolphin/gd/GDBase.h" +#include "dolphin/gd/GDGeometry.h" +#include "dolphin/gf/GF.h" +#include "dolphin/os/OS.h" + +void GFSetVtxDescv(GXVtxDescList*) { + // NONMATCHING +} + +void GFSetVtxAttrFmtv(GXVtxFmt, GXVtxAttrFmtList*) { + // NONMATCHING +} + +void GFSetArray(GXAttr, void*, u8) { + // NONMATCHING +} + +void GFSetCullMode(GXCullMode) { + // NONMATCHING +} diff --git a/src/dolphin/gf/GFLight.cpp b/src/dolphin/gf/GFLight.cpp new file mode 100644 index 000000000..0cef82ad6 --- /dev/null +++ b/src/dolphin/gf/GFLight.cpp @@ -0,0 +1,8 @@ +#include "dolphin/gd/GDBase.h" +#include "dolphin/gd/GDGeometry.h" +#include "dolphin/gf/GF.h" +#include "dolphin/os/OS.h" + +void GFSetChanMatColor(GXChannelID, GXColor) { + // NONMATCHING +} diff --git a/src/dolphin/gf/GFPixel.cpp b/src/dolphin/gf/GFPixel.cpp new file mode 100644 index 000000000..c4ce966da --- /dev/null +++ b/src/dolphin/gf/GFPixel.cpp @@ -0,0 +1,72 @@ +#include "dolphin/gd/GDBase.h" +#include "dolphin/gd/GDGeometry.h" +#include "dolphin/gf/GF.h" +#include "dolphin/os/OS.h" + +void GFSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor color) { + f32 A; + f32 B; + f32 B_mant; + f32 C; + f32 A_f; + u32 b_expn; + u32 b_m; + u32 a_hex; + u32 c_hex; + + ASSERTMSGLINE(62, farz >= 0.0f, "GFSetFog: The farz should be positive value"); + ASSERTMSGLINE(63, farz >= nearz, "GFSetFog: The farz should be larger than nearz"); + + if (farz == nearz || endz == startz) { + A = 0.0f; + B = 0.5f; + C = 0.0f; + } else { + A = (farz * nearz) / ((farz - nearz) * (endz - startz)); + B = farz / (farz - nearz); + C = startz / (endz - startz); + } + + B_mant = B; + b_expn = 1; + + while (B_mant > 1.0) { + B_mant *= 0.5f; + b_expn++; + } + + while (B_mant > 0.0f && B_mant < 0.5) { + B_mant *= 2.0f; + b_expn--; + } + + A_f = A / (1 << b_expn); + b_m = (u32) (8388638.0f * B_mant); + + a_hex = *(u32*)&A_f; + c_hex = *(u32*)&C; + + GFWriteBPCmd(BP_FOG_UNK0(a_hex >> 12, 0xEE)); + GFWriteBPCmd(BP_FOG_UNK1(b_m, 0xEF)); + GFWriteBPCmd(BP_FOG_UNK2(b_expn, 0xF0)); + GFWriteBPCmd(BP_FOG_UNK3(c_hex >> 12, 0, type, 0xF1)); + GFWriteBPCmd(BP_FOG_COLOR(color.r, color.g, color.b, 0xF2)); +} + +void GFSetBlendModeEtc(GXBlendMode type, GXBlendFactor src_factor, + GXBlendFactor dst_factor, GXLogicOp logic_op, + u8 color_update_enable, u8 alpha_update_enable, + u8 dither_enable) { + GFWriteBPCmd(BP_BLEND_MODE( + type == GX_BM_BLEND || type == GX_BM_SUBTRACT, + type == GX_BM_LOGIC, + dither_enable, + color_update_enable, + alpha_update_enable, + dst_factor, + src_factor, + type == GX_BM_SUBTRACT, + logic_op, + 0x41 + )); +} diff --git a/src/dolphin/gf/GFTev.cpp b/src/dolphin/gf/GFTev.cpp new file mode 100644 index 000000000..0c08e1818 --- /dev/null +++ b/src/dolphin/gf/GFTev.cpp @@ -0,0 +1,24 @@ +#include "dolphin/gd/GDBase.h" +#include "dolphin/gd/GDGeometry.h" +#include "dolphin/gf/GF.h" + +void GFSetTevColor(GXTevRegID, GXColor) { + // NONMATCHING +} + +void GFSetTevColorS10(GXTevRegID reg, GXColorS10 color) { + u32 regRA; + u32 regBG; + + regRA = BP_TEV_COLOR_REG_RA(color.r & 0x7FF, color.a & 0x7FF, 0, 0xE0 + reg * 2); + regBG = BP_TEV_COLOR_REG_BG(color.b & 0x7FF, color.g & 0x7FF, 0, 0xE1 + reg * 2); + + GFWriteBPCmd(regRA); + GFWriteBPCmd(regBG); + GFWriteBPCmd(regBG); + GFWriteBPCmd(regBG); +} + +void GFSetAlphaCompare(GXCompare, u8, GXAlphaOp, GXCompare, u8) { + // NONMATCHING +} diff --git a/src/dolphin/gf/GFTransform.cpp b/src/dolphin/gf/GFTransform.cpp new file mode 100644 index 000000000..ca77b333f --- /dev/null +++ b/src/dolphin/gf/GFTransform.cpp @@ -0,0 +1,15 @@ +#include "dolphin/gd/GDBase.h" +#include "dolphin/gd/GDGeometry.h" +#include "dolphin/gf/GF.h" + +void GFLoadPosMtxImm(MtxP, u32) { + // NONMATCHING +} + +void GFLoadNrmMtxImm(MtxP, u32) { + // NONMATCHING +} + +void GFSetCurrentMtx(u32, u32, u32, u32, u32, u32, u32, u32, u32) { + // NONMATCHING +} diff --git a/src/dolphin/gx/GXAttr.c b/src/dolphin/gx/GXAttr.c index dcf317172..d9981b613 100644 --- a/src/dolphin/gx/GXAttr.c +++ b/src/dolphin/gx/GXAttr.c @@ -400,8 +400,8 @@ void GXSetVtxAttrFmtv(GXVtxFmt format, GXVtxAttrFmtList* list) { vatB = (u32*)&gx->vatB[format]; vatC = &gx->vatC[format]; - for (; list->mAttrib != GX_VA_NULL; list++) { - SETVAT(vatA, vatB, vatC, list->mAttrib, list->mCompCnt, list->mCompType, list->mCompShift); + for (; list->attr != GX_VA_NULL; list++) { + SETVAT(vatA, vatB, vatC, list->attr, list->cnt, list->type, list->frac); } gx->dirtyState |= GX_DIRTY_VAT; @@ -471,12 +471,12 @@ void GXGetVtxAttrFmtv(GXVtxFmt param_0, GXVtxAttrFmtList* param_1) { #endif for (i = 9; i <= 0x14; i++) { - param_1->mAttrib = i; - GXGetVtxAttrFmt(param_0, i, ¶m_1->mCompCnt, ¶m_1->mCompType, ¶m_1->mCompShift); + param_1->attr = i; + GXGetVtxAttrFmt(param_0, i, ¶m_1->cnt, ¶m_1->type, ¶m_1->frac); param_1++; } - param_1->mAttrib = 0xFF; + param_1->attr = 0xFF; } void GXGetVtxAttrFmt(GXVtxFmt param_0, int param_1, GXCompCnt* param_2, GXCompType* param_3, diff --git a/src/dolphin/gx/GXStubs.c b/src/dolphin/gx/GXStubs.c new file mode 100644 index 000000000..fc4113666 --- /dev/null +++ b/src/dolphin/gx/GXStubs.c @@ -0,0 +1,3 @@ +#include "dolphin/gx/GX.h" + +void __GXSetRange(f32 nearz, f32 fgSideX) {} diff --git a/src/dolphin/pad/Pad.c b/src/dolphin/pad/Pad.c new file mode 100644 index 000000000..fa8beda4c --- /dev/null +++ b/src/dolphin/pad/Pad.c @@ -0,0 +1,740 @@ +#include "dolphin/os/OS.h" +#include "dolphin/si/SIBios.h" +#include "dolphin/pad/Pad.h" + +extern u16 __OSWirelessPadFixMode AT_ADDRESS(OS_BASE_CACHED | 0x30E0); + +const char* __PADVersion = "<< Dolphin SDK - PAD\trelease build: Sep 5 2002 05:34:02 (0x2301) >>"; + +#define PAD_ALL \ + ( \ + PAD_BUTTON_LEFT | \ + PAD_BUTTON_RIGHT | \ + PAD_BUTTON_DOWN | \ + PAD_BUTTON_UP | \ + PAD_TRIGGER_Z | \ + PAD_TRIGGER_R | \ + PAD_TRIGGER_L | \ + PAD_BUTTON_A | \ + PAD_BUTTON_B | \ + PAD_BUTTON_X | \ + PAD_BUTTON_Y | \ + PAD_BUTTON_MENU | \ + 0x2000 | \ + 0x0080 \ + ) + +static s32 ResettingChan = 0x20; +static u32 XPatchBits = PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT; +static u32 AnalogMode = 0x300; +static u32 Spec = PAD_SPEC_5; + +static BOOL Initialized; +static u32 EnabledBits; +static u32 ResettingBits; +static u32 RecalibrateBits; +static u32 WaitingBits; +static u32 CheckingBits; +static u32 PendingBits; + +static u32 Type[4]; +static PADStatus Origin[4]; + +u32 __PADSpec; + +// prototypes +static void PADTypeAndStatusCallback(s32 chan, u32 type); +static u16 GetWirelessID(s32 chan); +static void SetWirelessID(s32 chan, u16 id); +static void DoReset(); +static void PADEnable(s32 chan); +static void ProbeWireless(s32 chan); +static void PADProbeCallback(s32 chan, u32 error, OSContext *context); +static void PADDisable(s32 chan); +static void UpdateOrigin(s32 chan); +static void PADOriginCallback(s32 chan, u32 error, OSContext *context); +static void PADFixCallback(s32 unused, u32 error, struct OSContext *context); +static void PADResetCallback(s32 unused, u32 error, struct OSContext *context); +static void PADReceiveCheckCallback(s32 chan, u32 error); +static void SPEC0_MakeStatus(s32 chan, PADStatus *status, u32 data[2]); +static void SPEC1_MakeStatus(s32 chan, PADStatus *status, u32 data[2]); +static s8 ClampS8(s8 var, s8 org); +static u8 ClampU8(u8 var, u8 org); +static void SPEC2_MakeStatus(s32 chan, PADStatus *status, u32 data[2]); +static BOOL OnReset(BOOL f); +void __PADDisableXPatch(void); +BOOL __PADDisableRumble(BOOL disable); + +typedef void (*SPECCallback)(s32, PADStatus*, u32*); +static SPECCallback MakeStatus = SPEC2_MakeStatus; + +static u32 CmdReadOrigin = 0x41000000; +static u32 CmdCalibrate = 0x42000000; +static u32 CmdProbeDevice[4]; + +static OSResetFunctionInfo ResetFunctionInfo = { + OnReset, + 127, + NULL, + NULL, +}; + +static void PADEnable(s32 chan) { + u32 cmd; + u32 chanBit; + u32 data[2]; + + chanBit = PAD_CHAN0_BIT >> chan; + EnabledBits |= chanBit; + SIGetResponse(chan, &data); + cmd = (AnalogMode | 0x400000); + SISetCommand(chan, cmd); + SIEnablePolling(EnabledBits); +} + +static void PADDisable(s32 chan) { + BOOL enabled; + u32 chanBit; + + enabled = OSDisableInterrupts(); + chanBit = PAD_CHAN0_BIT >> chan; + SIDisablePolling(chanBit); + EnabledBits &= ~chanBit; + WaitingBits &= ~chanBit; + CheckingBits &= ~chanBit; + PendingBits &= ~chanBit; + OSSetWirelessID(chan, 0); + OSRestoreInterrupts(enabled); +} + +static void DoReset() { + u32 chanBit; + + ResettingChan = __cntlzw(ResettingBits); + if (ResettingChan != 32) { + ASSERTLINE(559, 0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); + chanBit = (PAD_CHAN0_BIT >> ResettingChan); + ResettingBits &= ~chanBit; + + memset(&Origin[ResettingChan], 0, sizeof(PADStatus)); + SIGetTypeAsync(ResettingChan, PADTypeAndStatusCallback); + } +} + +static void UpdateOrigin(s32 chan) { + PADStatus* origin; + u32 chanBit = 0x80000000 >> chan; + + origin = &Origin[chan]; + switch (AnalogMode & 0x00000700u) { + case 0x00000000u: + case 0x00000500u: + case 0x00000600u: + case 0x00000700u: + origin->triggerLeft &= ~15; + origin->triggerRight &= ~15; + origin->analogA &= ~15; + origin->analogB &= ~15; + break; + case 0x00000100u: + origin->substickX &= ~15; + origin->substickY &= ~15; + origin->analogA &= ~15; + origin->analogB &= ~15; + break; + case 0x00000200u: + origin->substickX &= ~15; + origin->substickY &= ~15; + origin->triggerLeft &= ~15; + origin->triggerRight &= ~15; + break; + case 0x00000300u: break; + case 0x00000400u: break; + } + + origin->stickX -= 128; + origin->stickY -= 128; + origin->substickX -= 128; + origin->substickY -= 128; + + if (XPatchBits & chanBit) { + if (64 < origin->stickX && (SIGetType(chan) & 0xFFFF0000) == SI_GC_CONTROLLER) { + origin->stickX = 0; + } + } +} + +static void PADOriginCallback(s32 chan, u32 error, OSContext* context) { + ASSERTLINE(641, 0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); + ASSERTLINE(642, chan == ResettingChan); + + if (!(error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) + { + UpdateOrigin(ResettingChan); + PADEnable(ResettingChan); + } + + DoReset(); +} + +static void PADOriginUpdateCallback(s32 chan, u32 error, OSContext* context) { + ASSERTLINE(671, 0 <= chan && chan < SI_MAX_CHAN); + if (!(EnabledBits & (PAD_CHAN0_BIT >> chan))) + return; + if (!(error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) + UpdateOrigin(chan); + if (error & SI_ERROR_NO_RESPONSE) { + PADDisable(chan); + } +} + +static void PADProbeCallback(s32 chan, u32 error, OSContext* context) { + u32 type; + ASSERTLINE(710, 0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); + ASSERTLINE(711, chan == ResettingChan); + ASSERTLINE(713, (Type[chan] & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT && !(Type[chan] & SI_WIRELESS_LITE)); + + if (!(error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION))) + { + PADEnable(ResettingChan); + WaitingBits |= PAD_CHAN0_BIT >> ResettingChan; + } + + DoReset(); +} + +static void PADTypeAndStatusCallback(s32 chan, u32 type) { + u32 chanBit; + u32 recalibrate; + BOOL rc = TRUE; + u32 error; + + ASSERTLINE(746, 0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); + ASSERTLINE(747, chan == ResettingChan); + + chanBit = PAD_CHAN0_BIT >> ResettingChan; + error = type & 0xFF; + ASSERTLINE(756, !(error & SI_ERROR_BUSY)); + + recalibrate = RecalibrateBits & chanBit; + RecalibrateBits &= ~chanBit; + + if (error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)) + { + DoReset(); + return; + } + + type &= ~0xFF; + Type[ResettingChan] = type; + + if ((type & SI_TYPE_MASK) != SI_TYPE_GC || !(type & SI_GC_STANDARD)) { + DoReset(); + return; + } + + if (Spec < PAD_SPEC_2) { + PADEnable(ResettingChan); + DoReset(); + return; + } + + if (!(type & SI_GC_WIRELESS) || (type & SI_WIRELESS_IR)) { + if (recalibrate) { + rc = SITransfer(ResettingChan, &CmdCalibrate, 3, &Origin[ResettingChan], 10, + PADOriginCallback, 0); + } else { + rc = SITransfer(ResettingChan, &CmdReadOrigin, 1, &Origin[ResettingChan], 10, + PADOriginCallback, 0); + } + } else if ((type & SI_WIRELESS_FIX_ID) && (type & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT && + !(type & SI_WIRELESS_LITE)) + { + if (type & SI_WIRELESS_RECEIVED) { + rc = SITransfer(ResettingChan, &CmdReadOrigin, 1, &Origin[ResettingChan], 10, + PADOriginCallback, 0); + } else { + rc = SITransfer(ResettingChan, &CmdProbeDevice[ResettingChan], 3, + &Origin[ResettingChan], 8, PADProbeCallback, 0); + } + } + + if (!rc) { + PendingBits |= chanBit; + DoReset(); + return; + } +} + +static void PADReceiveCheckCallback(s32 chan, u32 type) { + u32 error; + u32 chanBit; + + chanBit = PAD_CHAN0_BIT >> chan; + + if (EnabledBits & chanBit) { + error = type & 0xFF; + type &= ~0xFF; + + WaitingBits &= ~chanBit; + CheckingBits &= ~chanBit; + + if (!(error & + (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)) && + (type & SI_GC_WIRELESS) && (type & SI_WIRELESS_FIX_ID) && (type & SI_WIRELESS_RECEIVED) && + !(type & SI_WIRELESS_IR) && (type & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT && + !(type & SI_WIRELESS_LITE)) + { + SITransfer(chan, &CmdReadOrigin, 1, &Origin[chan], 10, PADOriginUpdateCallback, 0); + } else { + PADDisable(chan); + } + } +} + +int PADReset(u32 mask) { + BOOL enabled; + u32 disableBits; + + ASSERTMSGLINE(0x381, !(mask & 0x0FFFFFFF), "PADReset(): invalid mask"); + + enabled = OSDisableInterrupts(); + mask |= PendingBits; + PendingBits = 0; + mask &= ~(WaitingBits | CheckingBits); + ResettingBits |= mask; + disableBits = ResettingBits & EnabledBits; + EnabledBits &= ~mask; + + if (Spec == 4) { + RecalibrateBits |= mask; + } + + SIDisablePolling(disableBits); + + if (ResettingChan == 0x20) { + DoReset(); + } + + OSRestoreInterrupts(enabled); + return 1; +} + +BOOL PADRecalibrate(u32 mask) { + BOOL enabled; + u32 disableBits; + + ASSERTMSGLINE(939, !(mask & 0x0FFFFFFF), "PADReset(): invalid mask"); + enabled = OSDisableInterrupts(); + + mask |= PendingBits; + PendingBits = 0; + mask &= ~(WaitingBits | CheckingBits); + ResettingBits |= mask; + disableBits = ResettingBits & EnabledBits; + EnabledBits &= ~mask; + + if (!(__gUnknown800030E3 & 0x40)) { + RecalibrateBits |= mask; + } + + SIDisablePolling(disableBits); + if (ResettingChan == 32) + DoReset(); + + OSRestoreInterrupts(enabled); + return 1; +} + +BOOL PADInit() { + s32 chan; + if (Initialized) { + return 1; + } + + OSRegisterVersion(__PADVersion); + + if (__PADSpec) + PADSetSpec(__PADSpec); + + Initialized = TRUE; + + if (__PADFixBits != 0) { + OSTime time = OSGetTime(); + __OSWirelessPadFixMode = (u16)((((time)&0xffff) + ((time >> 16) & 0xffff) + + ((time >> 32) & 0xffff) + ((time >> 48) & 0xffff)) & + 0x3fffu); + RecalibrateBits = PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT; + } + + for (chan = 0; chan < SI_MAX_CHAN; ++chan) { + CmdProbeDevice[chan] = (0x4D << 24) | (chan << 22) | ((__OSWirelessPadFixMode & 0x3fffu) << 8); + } + + SIRefreshSamplingRate(); + OSRegisterResetFunction(&ResetFunctionInfo); + + return PADReset(PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT); +} + +u32 PADRead(PADStatus* status) { + BOOL enabled; + s32 chan; + u32 data[2]; + u32 chanBit; + u32 sr; + int chanShift; + u32 motor; + + enabled = OSDisableInterrupts(); + motor = 0; + + for (chan = 0; chan < 4; chan++, status++) { + chanBit = PAD_CHAN0_BIT >> chan; + chanShift = 8 * (SI_MAX_CHAN - 1 - chan); + + if (PendingBits & chanBit) { + PADReset(0); + status->err = PAD_ERR_NOT_READY; + memset(status, 0, offsetof(PADStatus, err)); + } else if ((ResettingBits & chanBit) || ResettingChan == chan) { + status->err = PAD_ERR_NOT_READY; + memset(status, 0, offsetof(PADStatus, err)); + } else if (!(EnabledBits & chanBit)) { + status->err = PAD_ERR_NO_CONTROLLER; + memset(status, 0, offsetof(PADStatus, err)); + } else if (SIIsChanBusy(chan)) { + status->err = PAD_ERR_TRANSFER; + memset(status, 0, offsetof(PADStatus, err)); + } else { + sr = SIGetStatus(chan); + if (sr & SI_ERROR_NO_RESPONSE) { + SIGetResponse(chan, data); + + if (WaitingBits & chanBit) { + status->err = PAD_ERR_NONE; + memset(status, 0, offsetof(PADStatus, err)); + + if (!(CheckingBits & chanBit)) { + CheckingBits |= chanBit; + SIGetTypeAsync(chan, PADReceiveCheckCallback); + } + } else { + PADDisable(chan); + status->err = PAD_ERR_NO_CONTROLLER; + memset(status, 0, offsetof(PADStatus, err)); + } + } else { + if (!(SIGetType(chan) & SI_GC_NOMOTOR)) { + motor |= chanBit; + } + + if (!SIGetResponse(chan, &data)) { + status->err = PAD_ERR_TRANSFER; + memset(status, 0, offsetof(PADStatus, err)); + } else if (data[0] & 0x80000000) { + status->err = PAD_ERR_TRANSFER; + memset(status, 0, offsetof(PADStatus, err)); + } else { + MakeStatus(chan, status, data); + + // Check and clear PAD_ORIGIN bit + if (status->button & 0x2000) { + status->err = PAD_ERR_TRANSFER; + memset(status, 0, offsetof(PADStatus, err)); + + // Get origin. It is okay if the following transfer fails + // since the PAD_ORIGIN bit remains until the read origin + // command complete. + SITransfer(chan, &CmdReadOrigin, 1, &Origin[chan], 10, PADOriginUpdateCallback, 0); + } else { + status->err = PAD_ERR_NONE; + + // Clear PAD_INTERFERE bit + status->button &= ~0x0080; + } + } + } + } + } + + OSRestoreInterrupts(enabled); + return motor; +} + +typedef struct XY { + u8 line; + u8 count; +} XY; + +#if DEBUG +void __PADTestSamplingRate(u32 tvmode) { + __SITestSamplingRate(tvmode); +} +#endif + +void PADControlMotor(s32 chan, u32 command) { + BOOL enabled; + u32 chanBit; + + ASSERTMSGLINE(1244, !(command & 0xFFFFFFFC), "PADControlMotor(): invalid command"); + + enabled = OSDisableInterrupts(); + chanBit = PAD_CHAN0_BIT >> chan; + if ((EnabledBits & chanBit) && !(SIGetType(chan) & SI_GC_NOMOTOR)) { + if (Spec < PAD_SPEC_2 && command == PAD_MOTOR_STOP_HARD) + command = PAD_MOTOR_STOP; + + SISetCommand(chan, (0x40 << 16) | AnalogMode | (command & (0x00000001 | 0x00000002))); + SITransferCommands(); + } + + OSRestoreInterrupts(enabled); +} + +void PADSetSpec(u32 spec) { + ASSERTLINE(1282, !Initialized); + __PADSpec = 0; + + switch (spec) { + case PAD_SPEC_0: + MakeStatus = SPEC0_MakeStatus; + break; + case PAD_SPEC_1: + MakeStatus = SPEC1_MakeStatus; + break; + case PAD_SPEC_2: + case PAD_SPEC_3: + case PAD_SPEC_4: + case PAD_SPEC_5: + MakeStatus = SPEC2_MakeStatus; + break; + } + Spec = spec; +} + +static void SPEC0_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) { + status->button = 0; + status->button |= ((data[0] >> 16) & 0x0008) ? PAD_BUTTON_A : 0; + status->button |= ((data[0] >> 16) & 0x0020) ? PAD_BUTTON_B : 0; + status->button |= ((data[0] >> 16) & 0x0100) ? PAD_BUTTON_X : 0; + status->button |= ((data[0] >> 16) & 0x0001) ? PAD_BUTTON_Y : 0; + status->button |= ((data[0] >> 16) & 0x0010) ? PAD_BUTTON_START : 0; + status->stickX = (s8)(data[1] >> 16); + status->stickY = (s8)(data[1] >> 24); + status->substickX = (s8)(data[1]); + status->substickY = (s8)(data[1] >> 8); + status->triggerLeft = (u8)(data[0] >> 8); + status->triggerRight = (u8)data[0]; + status->analogA = 0; + status->analogB = 0; + if (170 <= status->triggerLeft) + status->button |= PAD_TRIGGER_L; + if (170 <= status->triggerRight) + status->button |= PAD_TRIGGER_R; + status->stickX -= 128; + status->stickY -= 128; + status->substickX -= 128; + status->substickY -= 128; +} + +static void SPEC1_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) { + status->button = 0; + status->button |= ((data[0] >> 16) & 0x0080) ? PAD_BUTTON_A : 0; + status->button |= ((data[0] >> 16) & 0x0100) ? PAD_BUTTON_B : 0; + status->button |= ((data[0] >> 16) & 0x0020) ? PAD_BUTTON_X : 0; + status->button |= ((data[0] >> 16) & 0x0010) ? PAD_BUTTON_Y : 0; + status->button |= ((data[0] >> 16) & 0x0200) ? PAD_BUTTON_START : 0; + + status->stickX = (s8)(data[1] >> 16); + status->stickY = (s8)(data[1] >> 24); + status->substickX = (s8)(data[1]); + status->substickY = (s8)(data[1] >> 8); + + status->triggerLeft = (u8)(data[0] >> 8); + status->triggerRight = (u8)data[0]; + + status->analogA = 0; + status->analogB = 0; + + if (170 <= status->triggerLeft) + status->button |= PAD_TRIGGER_L; + if (170 <= status->triggerRight) + status->button |= PAD_TRIGGER_R; + + status->stickX -= 128; + status->stickY -= 128; + status->substickX -= 128; + status->substickY -= 128; +} + +static s8 ClampS8(s8 var, s8 org) { + if (0 < org) { + s8 min = (s8)(-128 + org); + if (var < min) + var = min; + } else if (org < 0) { + s8 max = (s8)(127 + org); + if (max < var) + var = max; + } + return var -= org; +} + +static u8 ClampU8(u8 var, u8 org) { + if (var < org) + var = org; + return var -= org; +} + +static void SPEC2_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) { + PADStatus* origin; + + status->button = (u16)((data[0] >> 16) & PAD_ALL); + status->stickX = (s8)(data[0] >> 8); + status->stickY = (s8)(data[0]); + + switch (AnalogMode & 0x00000700) { + case 0x00000000: + case 0x00000500: + case 0x00000600: + case 0x00000700: + status->substickX = (s8)(data[1] >> 24); + status->substickY = (s8)(data[1] >> 16); + status->triggerLeft = (u8)(((data[1] >> 12) & 0x0f) << 4); + status->triggerRight = (u8)(((data[1] >> 8) & 0x0f) << 4); + status->analogA = (u8)(((data[1] >> 4) & 0x0f) << 4); + status->analogB = (u8)(((data[1] >> 0) & 0x0f) << 4); + break; + case 0x00000100: + status->substickX = (s8)(((data[1] >> 28) & 0x0f) << 4); + status->substickY = (s8)(((data[1] >> 24) & 0x0f) << 4); + status->triggerLeft = (u8)(data[1] >> 16); + status->triggerRight = (u8)(data[1] >> 8); + status->analogA = (u8)(((data[1] >> 4) & 0x0f) << 4); + status->analogB = (u8)(((data[1] >> 0) & 0x0f) << 4); + break; + case 0x00000200: + status->substickX = (s8)(((data[1] >> 28) & 0x0f) << 4); + status->substickY = (s8)(((data[1] >> 24) & 0x0f) << 4); + status->triggerLeft = (u8)(((data[1] >> 20) & 0x0f) << 4); + status->triggerRight = (u8)(((data[1] >> 16) & 0x0f) << 4); + status->analogA = (u8)(data[1] >> 8); + status->analogB = (u8)(data[1] >> 0); + break; + case 0x00000300: + status->substickX = (s8)(data[1] >> 24); + status->substickY = (s8)(data[1] >> 16); + status->triggerLeft = (u8)(data[1] >> 8); + status->triggerRight = (u8)(data[1] >> 0); + status->analogA = 0; + status->analogB = 0; + break; + case 0x00000400: + status->substickX = (s8)(data[1] >> 24); + status->substickY = (s8)(data[1] >> 16); + status->triggerLeft = 0; + status->triggerRight = 0; + status->analogA = (u8)(data[1] >> 8); + status->analogB = (u8)(data[1] >> 0); + break; + } + + status->stickX -= 128; + status->stickY -= 128; + status->substickX -= 128; + status->substickY -= 128; + + origin = &Origin[chan]; + status->stickX = ClampS8(status->stickX, origin->stickX); + status->stickY = ClampS8(status->stickY, origin->stickY); + status->substickX = ClampS8(status->substickX, origin->substickX); + status->substickY = ClampS8(status->substickY, origin->substickY); + status->triggerLeft = ClampU8(status->triggerLeft, origin->triggerLeft); + status->triggerRight = ClampU8(status->triggerRight, origin->triggerRight); +} + +BOOL PADSync(void) { + return ResettingBits == 0 && (s32)ResettingChan == 32 && !SIBusy(); +} + +void PADSetAnalogMode(u32 mode) { + BOOL enabled; + u32 mask; + + ASSERTMSGLINE(1615, (mode < 8), "PADSetAnalogMode(): invalid mode"); + + enabled = OSDisableInterrupts(); + AnalogMode = mode << 8; + mask = EnabledBits; + + EnabledBits &= ~mask; + WaitingBits &= ~mask; + CheckingBits &= ~mask; + + SIDisablePolling(mask); + OSRestoreInterrupts(enabled); +} + +static void (*SamplingCallback)(); + +static BOOL OnReset(BOOL final) { + BOOL sync; + static BOOL recalibrated = FALSE; + + if (SamplingCallback) + PADSetSamplingCallback(NULL); + + if (!final) { + sync = PADSync(); + if (!recalibrated && sync) { + recalibrated = PADRecalibrate(PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT); + return FALSE; + } + return sync; + } else + recalibrated = FALSE; + + return TRUE; +} + +static void SamplingHandler(__OSInterrupt interrupt, OSContext* context) { + OSContext exceptionContext; + + if (SamplingCallback) { + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + SamplingCallback(); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +PADSamplingCallback PADSetSamplingCallback(PADSamplingCallback callback) { + PADSamplingCallback prev; + + prev = SamplingCallback; + SamplingCallback = callback; + if (callback) { + SIRegisterPollingHandler(SamplingHandler); + } else { + SIUnregisterPollingHandler(SamplingHandler); + } + + return prev; +} + +BOOL __PADDisableRecalibration(BOOL disable) { + BOOL enabled; + BOOL prev; + + enabled = OSDisableInterrupts(); + prev = (__gUnknown800030E3 & 0x40) ? TRUE : FALSE; + __gUnknown800030E3 &= (u8)~0x40; + if (disable) { + __gUnknown800030E3 |= 0x40; + } + + OSRestoreInterrupts(enabled); + return prev; +} diff --git a/src/dolphin/pad/Padclamp.c b/src/dolphin/pad/Padclamp.c new file mode 100644 index 000000000..2f5686627 --- /dev/null +++ b/src/dolphin/pad/Padclamp.c @@ -0,0 +1,105 @@ +#include "dolphin/pad/Pad.h" + +static const PADClampRegion ClampRegion = { + // Triggers + 30, + 180, + + // Left stick + 15, + 72, + 40, + + // Right stick + 15, + 59, + 31, + + // Stick radii + 56, + 44, +}; + +// prototypes +static void ClampStick(s8* px, s8* py, s8 max, s8 xy, s8 min); +static void ClampCircle(s8* px, s8* py, s8 radius, s8 min); +static void ClampTrigger(u8* trigger, u8 min, u8 max); + +static void ClampStick(s8* px, s8* py, s8 max, s8 xy, s8 min) { + int x = *px; + int y = *py; + int signX; + int signY; + int d; + + if (0 <= x) { + signX = 1; + } else { + signX = -1; + x = -x; + } + + if (0 <= y) { + signY = 1; + } else { + signY = -1; + y = -y; + } + + if (x <= min) { + x = 0; + } else { + x -= min; + } + if (y <= min) { + y = 0; + } else { + y -= min; + } + + if (x == 0 && y == 0) { + *px = *py = 0; + return; + } + + if (xy * y <= xy * x) { + d = xy * x + (max - xy) * y; + if (xy * max < d) { + x = (s8)(xy * max * x / d); + y = (s8)(xy * max * y / d); + } + } else { + d = xy * y + (max - xy) * x; + if (xy * max < d) { + x = (s8)(xy * max * x / d); + y = (s8)(xy * max * y / d); + } + } + + *px = (s8)(signX * x); + *py = (s8)(signY * y); +} + +static void ClampTrigger(u8* trigger, u8 min, u8 max) { + if (*trigger <= min) { + *trigger = 0; + } else { + if (max < *trigger) { + *trigger = max; + } + *trigger -= min; + } +} + +void PADClamp(PADStatus * status) { + int i; + + for (i = 0; i < 4; i++, status++) { + if (status->err == PAD_ERR_NONE) { + ClampStick(&status->stickX, &status->stickY, ClampRegion.maxStick, ClampRegion.xyStick, ClampRegion.minStick); + ClampStick(&status->substickX, &status->substickY, ClampRegion.maxSubstick, ClampRegion.xySubstick, ClampRegion.minSubstick); + ClampTrigger(&status->triggerLeft, ClampRegion.minTrigger, ClampRegion.maxTrigger); + ClampTrigger(&status->triggerRight, ClampRegion.minTrigger, ClampRegion.maxTrigger); + } + } +} diff --git a/src/dolphin/si/SIBios.c b/src/dolphin/si/SIBios.c new file mode 100644 index 000000000..f93d31105 --- /dev/null +++ b/src/dolphin/si/SIBios.c @@ -0,0 +1,769 @@ +#include "dolphin/si/SIBios.h" +#include "dolphin/os/OS.h" + +#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1)) + +const char* __SIVersion = "<< Dolphin SDK - SI\trelease build: Sep 5 2002 05:33:08 (0x2301) >>"; + +static SIControl Si = { + /* chan */ -1, + /* poll */ 0, + /* inputBytes */ 0, + /* input */ NULL, + /* callback */ NULL +}; + +static SIPacket Packet[4]; +static OSAlarm Alarm[4]; +static u32 Type[4] = { SI_ERROR_NO_RESPONSE, SI_ERROR_NO_RESPONSE, SI_ERROR_NO_RESPONSE, SI_ERROR_NO_RESPONSE }; +static OSTime TypeTime[4]; +static OSTime XferTime[4]; +static SITypeCallback TypeCallback[4][4]; +static __OSInterruptHandler RDSTHandler[4]; +static BOOL InputBufferValid[4]; +static u32 InputBuffer[4][2]; +static volatile u32 InputBufferVcount[4]; + +u32 __PADFixBits; + +// prototypes +static u32 CompleteTransfer(); +static void SITransferNext(s32 chan); +static void SIInterruptHandler(__OSInterrupt interrupt, OSContext* context); +static int __SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes, SICallback callback); +static void AlarmHandler(OSAlarm* alarm, OSContext* context); +static void GetTypeCallback(s32 chan, u32 error, OSContext* context); +static int SIGetResponseRaw(s32 chan); + +BOOL SIBusy(void) { + return (Si.chan != -1) ? TRUE : FALSE; +} + +BOOL SIIsChanBusy(s32 chan) { + return Packet[chan].chan != -1 || Si.chan == chan; +} + +static void SIClearTCInterrupt(void) { + u32 reg; + + reg = __SIRegs[SI_COMCSR_IDX]; + reg |= SI_COMCSR_TCINT_MASK; + reg &= ~SI_COMCSR_TSTART_MASK; + __SIRegs[SI_COMCSR_IDX] = reg; +} + +static u32 CompleteTransfer(void) { + u32 sr; + u32 i; + u32 rLen; + u8* input; + u32 temp; + + sr = __SIRegs[SI_STATUS_IDX]; + SIClearTCInterrupt(); + + if (Si.chan != -1) { + XferTime[Si.chan] = __OSGetSystemTime(); + input = Si.input; + rLen = Si.inputBytes / sizeof(u32); + for (i = 0; i < rLen; i++) { + *((u32*)input)++ = __SIRegs[i+0x20]; + } + + rLen = Si.inputBytes & 3; + if (rLen != 0) { + temp = __SIRegs[i + 32]; + for (i = 0; i < rLen; i++) { + *(input++) = temp >> ((3 - i) * 8); + } + } + + if (__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_COMERR_MASK) { + sr >>= (3 - Si.chan) * 8; + sr &= 0xF; + if ((sr & 8) != 0 && (Type[Si.chan] & 0x80) == 0) { + Type[Si.chan] = 8; + } + + if (sr == 0) { + sr = 4; + } + } else { + TypeTime[Si.chan] = __OSGetSystemTime(); + sr = 0; + } + + Si.chan = -1; + } + + return sr; +} + +static void SITransferNext(s32 chan) { + int i; + SIPacket* packet; + + for (i = 0; i < 4; i++) { + chan++; + chan %= 4; + packet = &Packet[chan]; + + if (packet->chan != -1) { + if (packet->fire <= __OSGetSystemTime()) { + if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback) != 0) { + OSCancelAlarm(&Alarm[chan]); + packet->chan = -1; + } + return; + } + } + } +} + +#define CHAN_NONE -1 + +static void SIInterruptHandler(__OSInterrupt interrupt, OSContext* context) { + u32 reg; + s32 chan; + u32 sr; + SICallback callback; + int i; + u32 vcount; + u32 x; + + reg = __SIRegs[SI_COMCSR_IDX]; + if ((reg & (SI_COMCSR_TCINT_MASK | SI_COMCSR_TCINTMSK_MASK)) == (SI_COMCSR_TCINT_MASK | SI_COMCSR_TCINTMSK_MASK)) { + ASSERTLINE(376, Si.chan != CHAN_NONE); + + chan = Si.chan; + sr = CompleteTransfer(); + callback = Si.callback; + Si.callback = NULL; + SITransferNext(chan); + + if (callback) { + callback(chan, sr, context); + } + + sr = __SIRegs[SI_STATUS_IDX]; + sr &= 0x0F000000 >> (chan << 3); + __SIRegs[SI_STATUS_IDX] = sr; + + if (Type[chan] == SI_ERROR_BUSY && !SIIsChanBusy(chan)) { + static u32 cmdTypeAndStatus; + + SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, &GetTypeCallback, OSMicrosecondsToTicks(65)); + } + } + + if ((reg & (SI_COMCSR_RDSTINT_MASK | SI_COMCSR_RDSTINTMSK_MASK)) == (SI_COMCSR_RDSTINT_MASK | SI_COMCSR_RDSTINTMSK_MASK)) { + vcount = 1 + VIGetCurrentLine(); + x = (Si.poll & (0x3FF << 16)) >> 16; + + for (i = 0; i < 4; i++) { + if (SIGetResponseRaw(i)) { + InputBufferVcount[i] = vcount; + } + } + + for (i = 0; i < 4; i++) { + if ((Si.poll & (0x80000000 >> (24 + i))) != 0) { + if (InputBufferVcount[i] == 0 || ((x >> 1) + InputBufferVcount[i]) < vcount) { + return; + } + } + } + + for (i = 0; i < 4; i++) { + InputBufferVcount[i] = 0; + } + + for (i = 0; i < 4; i++) { + if (RDSTHandler[i] != 0) { + (*RDSTHandler[i])(interrupt, context); + } + } + } +} + +static BOOL SIEnablePollingInterrupt(BOOL enable) { + BOOL enabled; + BOOL rc; + u32 reg; + int i; + + enabled = OSDisableInterrupts(); + reg = __SIRegs[SI_COMCSR_IDX]; + rc = ((reg & SI_COMCSR_RDSTINTMSK_MASK) != 0) ? TRUE : FALSE; + + if (enable) { + reg |= SI_COMCSR_RDSTINTMSK_MASK; + + for (i = 0; i < 4; i++) { + InputBufferVcount[i] = 0; + } + } else { + reg &= ~SI_COMCSR_RDSTINTMSK_MASK; + } + + reg &= ~(SI_COMCSR_TCINT_MASK | SI_COMCSR_TSTART_MASK); + __SIRegs[SI_COMCSR_IDX] = reg; + + OSRestoreInterrupts(enabled); + return rc; +} + +BOOL SIRegisterPollingHandler(__OSInterruptHandler handler) { + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + for (i = 0; i < 4; i++) { + if (RDSTHandler[i] == handler) { + OSRestoreInterrupts(enabled); + return TRUE; + } + } + + for (i = 0; i < 4; i++) { + if (RDSTHandler[i] == 0) { + RDSTHandler[i] = handler; + SIEnablePollingInterrupt(TRUE); + OSRestoreInterrupts(enabled); + return TRUE; + } + } + + OSRestoreInterrupts(enabled); + return FALSE; +} + +BOOL SIUnregisterPollingHandler(__OSInterruptHandler handler) { + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + for (i = 0; i < 4; i++) { + if (RDSTHandler[i] == handler) { + RDSTHandler[i] = 0; + + for (i = 0; i < 4; i++) { + if (RDSTHandler[i] != 0) { + break; + } + } + + if (i == 4) { + SIEnablePollingInterrupt(FALSE); + } + + OSRestoreInterrupts(enabled); + return TRUE; + } + } + + OSRestoreInterrupts(enabled); + return FALSE; +} + +void SIInit(void) { + OSRegisterVersion(__SIVersion); + + Packet[0].chan = Packet[1].chan = Packet[2].chan = Packet[3].chan = -1; + Si.poll = 0; + SISetSamplingRate(0); + + do {} while(__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_TSTART_MASK); + + __SIRegs[SI_COMCSR_IDX] = SI_COMCSR_TCINT_MASK; + __OSSetInterruptHandler(0x14, SIInterruptHandler); + __OSUnmaskInterrupts(0x800); + + SIGetType(0); + SIGetType(1); + SIGetType(2); + SIGetType(3); +} + +static int __SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes, SICallback callback) { + BOOL enabled; + u32 rLen; + u32 i; + u32 sr; + union { + u32 val; + struct { + u32 tcint : 1; + u32 tcintmsk : 1; + u32 comerr : 1; + u32 rdstint : 1; + u32 rdstintmsk : 1; + u32 pad2 : 4; + u32 outlngth : 7; + u32 pad1 : 1; + u32 inlngth : 7; + u32 pad0 : 5; + u32 channel : 2; + u32 tstart : 1; + } f; + } comcsr; + + ASSERTMSGLINE(627, (chan >= 0) && (chan < 4), "SITransfer(): invalid channel."); + ASSERTMSGLINE(629, (outputBytes != 0) && (outputBytes <= 128), "SITransfer(): output size is out of range (must be 1 to 128)."); + ASSERTMSGLINE(631, (inputBytes != 0) && (inputBytes <= 128), "SITransfer(): input size is out of range (must be 1 to 128)."); + + enabled = OSDisableInterrupts(); + if (Si.chan != -1) { + OSRestoreInterrupts(enabled); + return 0; + } + + ASSERTLINE(641, (__SIRegs[SI_COMCSR_IDX] & (SI_COMCSR_TSTART_MASK | SI_COMCSR_TCINT_MASK)) == 0); + sr = __SIRegs[SI_STATUS_IDX]; + sr &= (0x0F000000 >> (chan* 8)); + __SIRegs[SI_STATUS_IDX] = sr; + + Si.chan = chan; + Si.callback = callback; + Si.inputBytes = inputBytes; + Si.input = input; + + rLen = ROUND(outputBytes, 4) / 4; + for (i = 0; i < rLen; i++) { + __SIRegs[i + 0x20] = ((u32*)output)[i]; + } + + comcsr.val = __SIRegs[SI_COMCSR_IDX]; + comcsr.f.tcint = 1; + comcsr.f.tcintmsk = callback ? 1 : 0; + comcsr.f.outlngth = outputBytes == 0x80 ? 0 : outputBytes; + comcsr.f.inlngth = inputBytes == 0x80 ? 0 : inputBytes; + comcsr.f.channel = chan; + comcsr.f.tstart = 1; + + __SIRegs[SI_COMCSR_IDX] = comcsr.val; + OSRestoreInterrupts(enabled); + return 1; +} + +u32 SIGetStatus(s32 chan) { + BOOL enabled; + u32 sr; + int chanShift; + + enabled = OSDisableInterrupts(); + sr = __SIRegs[SI_STATUS_IDX]; + chanShift = (3 - chan) * 8; + sr >>= chanShift; + + if ((sr & 8) != 0) { + if ((Type[chan] & SI_ERROR_BUSY) == 0) { + Type[chan] = 8; + } + } + + OSRestoreInterrupts(enabled); + return sr; +} + +void SISetCommand(s32 chan, u32 command) { + ASSERTMSGLINE(752, (chan >= 0) && (chan < 4), "SISetCommand(): invalid channel."); + __SIRegs[chan* 3] = command; +} + +void SITransferCommands(void) { + __SIRegs[SI_STATUS_IDX] = SI_COMCSR_TCINT_MASK; +} + +u32 SISetXY(u32 x, u32 y) { + u32 poll; + BOOL enabled; + + ASSERTMSGLINE(803, x >= 8, "SISetXY(): x is out of range (8 <= x <= 1023)."); + ASSERTMSGLINE(804, x <= 1023, "SISetXY(): x is out of range (8 <= x <= 1023)."); + ASSERTMSGLINE(805, y <= 255, "SISetXY(): y is out of range (0 <= y <= 255)."); + + poll = x << 0x10; + poll |= y << 8; + enabled = OSDisableInterrupts(); + Si.poll &= 0xFC0000FF; + Si.poll |= poll; + poll = Si.poll; + __SIRegs[0x30 / 4] = poll; + OSRestoreInterrupts(enabled); + return poll; +} + +u32 SIEnablePolling(u32 poll) { + BOOL enabled; + u32 en; + + ASSERTMSGLINE(834, (poll & 0x0FFFFFFF) == 0, "SIEnablePolling(): invalid chan bit(s)."); + if (poll == 0) { + return Si.poll; + } + + enabled = OSDisableInterrupts(); + poll = poll >> 24; + en = poll & 0xF0; + ASSERTLINE(865, en); + poll &= ((en >> 4) | 0x03FFFFF0); + poll &= 0xFC0000FF; + + Si.poll &= ~(en >> 4); + Si.poll |= poll; + poll = Si.poll; + SITransferCommands(); + __SIRegs[0x30 / 4] = poll; + OSRestoreInterrupts(enabled); + return poll; +} + +u32 SIDisablePolling(u32 poll) { + BOOL enabled; + + ASSERTMSGLINE(908, (poll & 0x0FFFFFFF) == 0, "SIDisablePolling(): invalid chan bit(s)."); + if (poll == 0) { + return Si.poll; + } + + enabled = OSDisableInterrupts(); + poll = poll >> 24; + poll &= 0xF0; + ASSERTLINE(921, poll); + poll = Si.poll & ~poll; + __SIRegs[0x30 / 4] = poll; + Si.poll = poll; + OSRestoreInterrupts(enabled); + return poll; +} + +static BOOL SIGetResponseRaw(s32 chan) { + u32 sr; + + sr = SIGetStatus(chan); + if (sr & 0x20) { + InputBuffer[chan][0] = __SIRegs[1 + chan * 3]; + InputBuffer[chan][1] = __SIRegs[2 + chan * 3]; + InputBufferValid[chan] = TRUE; + return TRUE; + } + + return FALSE; +} + +BOOL SIGetResponse(s32 chan, void* data) { + BOOL rc; + BOOL enabled; + + ASSERTMSGLINE(971, ((chan >= 0) && (chan < 4)), "SIGetResponse(): invalid channel."); + enabled = OSDisableInterrupts(); + SIGetResponseRaw(chan); + rc = InputBufferValid[chan]; + InputBufferValid[chan] = FALSE; + + if (rc) { + ((u32*)data)[0] = InputBuffer[chan][0]; + ((u32*)data)[1] = InputBuffer[chan][1]; + } + + OSRestoreInterrupts(enabled); + return rc; +} + +static void AlarmHandler(OSAlarm* alarm, OSContext* context) { + s32 chan; + SIPacket* packet; + + chan = (s32)(alarm - Alarm); + ASSERTLINE(1002, 0 <= chan && chan < SI_MAX_CHAN); + + packet = &Packet[chan]; + if (packet->chan != -1) { + ASSERTLINE(1006, packet->fire <= __OSGetSystemTime()); + + if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback)) { + packet->chan = -1; + } + } +} + +BOOL SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes, + SICallback callback, OSTime delay) { + BOOL enabled; + SIPacket* packet; + OSTime now; + OSTime fire; + + packet = &Packet[chan]; + enabled = OSDisableInterrupts(); + + if (packet->chan != -1 || Si.chan == chan) { + OSRestoreInterrupts(enabled); + return FALSE; + } + + now = __OSGetSystemTime(); + if (delay == 0) { + fire = now; + } else { + fire = delay + XferTime[chan]; + } + + if (now < fire) { + delay = fire - now; + OSSetAlarm(&Alarm[chan], delay, AlarmHandler); + } else if (__SITransfer(chan, output, outputBytes, input, inputBytes, callback)) { + OSRestoreInterrupts(enabled); + return TRUE; + } + + packet->chan = chan; + packet->output = output; + packet->outputBytes = outputBytes; + packet->input = input; + packet->inputBytes = inputBytes; + packet->callback = callback; + packet->fire = fire; + OSRestoreInterrupts(enabled); + return TRUE; +} + +static void CallTypeAndStatusCallback(s32 chan, u32 type) { + SITypeCallback callback; + int i; + + for (i = 0; i < 4; i++) { + callback = TypeCallback[chan][i]; + + if (callback != 0) { + TypeCallback[chan][i] = 0; + (*callback)(chan, type); + } + } +} + +static void GetTypeCallback(s32 chan, u32 error, OSContext* context) { + u32 type; + u32 chanBit; + int fix; + u32 id; + + ASSERTLINE(1137, 0 <= chan && chan < SI_MAX_CHAN); + + ASSERTLINE(1139, (Type[chan] & 0xff) == SI_ERROR_BUSY); + Type[chan] &= ~SI_ERROR_BUSY; + Type[chan] |= error; + TypeTime[chan] = __OSGetSystemTime(); + + type = Type[chan]; + chanBit = 0x80000000 >> chan; + fix = __PADFixBits & chanBit; + __PADFixBits &= ~chanBit; + + if ((error & 0xF) != 0 || (type & 0x18000000) != 0x08000000 || (type & 0x80000000) == 0 || (type & 0x04000000) != 0) { + OSSetWirelessID(chan, 0); + CallTypeAndStatusCallback(chan, Type[chan]); + } else { + static u32 cmdFixDevice[4]; + + id = OSGetWirelessID(chan) << 8; + + if (fix != 0 && (id & 0x100000) != 0) { + cmdFixDevice[chan] = 0x4E000000 | (id & 0xCFFF00) | 0x100000; + Type[chan] = SI_ERROR_BUSY; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0); + return; + } + + if ((type & 0x00100000) != 0) { + if ((id & 0xCFFF00) != (type & 0xCFFF00)) { + if ((id & 0x100000) == 0) { + id = type & 0xCFFF00; + id |= 0x100000; + OSSetWirelessID(chan, id >> 8); + } + + cmdFixDevice[chan] = 0x4E000000 | id; + Type[chan] = SI_ERROR_BUSY; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0); + return; + } + } else { + if ((type & 0x40000000) != 0) { + id = type & 0xCFFF00; + id |= 0x100000; + OSSetWirelessID(chan, id >> 8); + + cmdFixDevice[chan] = 0x4E000000 | id; + Type[chan] = SI_ERROR_BUSY; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0); + return; + } + + OSSetWirelessID(chan, 0); + } + + CallTypeAndStatusCallback(chan, Type[chan]); + } +} + +u32 SIGetType(s32 chan) { + static u32 cmdTypeAndStatus; + BOOL enabled; + u32 type; + OSTime diff; + + enabled = OSDisableInterrupts(); + ASSERTLINE(1243, 0 <= chan && chan < SI_MAX_CHAN); + type = Type[chan]; + diff = __OSGetSystemTime() - TypeTime[chan]; + if ((Si.poll & (0x80 >> chan)) != 0) { + if (type != 8) { + TypeTime[chan] = __OSGetSystemTime(); + OSRestoreInterrupts(enabled); + return type; + } + + type = Type[chan] = SI_ERROR_BUSY; + } else { + if (diff <= OSMillisecondsToTicks(50) && type != 8) { + OSRestoreInterrupts(enabled); + return type; + } + + if (diff <= OSMillisecondsToTicks(75)) { + Type[chan] = SI_ERROR_BUSY; + } else { + type = Type[chan] = SI_ERROR_BUSY; + } + } + + TypeTime[chan] = __OSGetSystemTime(); + SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, &GetTypeCallback, OSMicrosecondsToTicks(65)); + OSRestoreInterrupts(enabled); + return type; +} + +u32 SIGetTypeAsync(s32 chan, SITypeCallback callback) { + BOOL enabled; + u32 type; + int i; + + enabled = OSDisableInterrupts(); + type = SIGetType(chan); + + if ((Type[chan] & SI_ERROR_BUSY) != 0) { + for (i = 0; i < SI_MAX_TYPE; i++) { + if (TypeCallback[chan][i] == callback) { + break; + } + + if (TypeCallback[chan][i] == 0) { + TypeCallback[chan][i] = callback; + break; + } + } + + ASSERTLINE(1324, i < SI_MAX_TYPE); + } else { + (*callback)(chan, type); + } + + OSRestoreInterrupts(enabled); + return type; +} + +u32 SIDecodeType(u32 type) { + u32 error; + + error = type & 0xFF; + type &= ~0xFF; + + if (error & SI_ERROR_NO_RESPONSE) { + return SI_ERROR_NO_RESPONSE; + } + + if (error & (SI_ERROR_UNKNOWN | SI_ERROR_COLLISION | SI_ERROR_OVER_RUN | SI_ERROR_UNDER_RUN)) { + return SI_ERROR_UNKNOWN; + } + + if (error != 0) { + ASSERTLINE(1371, error == SI_ERROR_BUSY); + return SI_ERROR_BUSY; + } + + if ((type & SI_TYPE_MASK) == SI_TYPE_N64) { + switch (type & 0xFFFF0000) { + case SI_N64_MIC: + case SI_N64_KEYBOARD: + case SI_GBA: + case SI_N64_MOUSE: + case SI_N64_CONTROLLER: + return type & 0xFFFF0000; + default: + return SI_ERROR_UNKNOWN; + } + } + + if ((type & SI_TYPE_MASK) != SI_TYPE_DOLPHIN) { + return SI_ERROR_UNKNOWN; + } + + switch (type & 0xFFFF0000) { + case SI_GC_STEERING: + case SI_GC_CONTROLLER: + return type & 0xFFFF0000; + } + + if ((type & 0xFFE00000) == SI_GC_KEYBOARD) { + return SI_GC_KEYBOARD; + } + + if ((type & SI_GC_WIRELESS) != 0 && (type & SI_WIRELESS_IR) == 0) { + if ((type & SI_GC_WAVEBIRD) == SI_GC_WAVEBIRD) { + return SI_GC_WAVEBIRD; + } + + if ((type & SI_WIRELESS_STATE) == 0) { + return SI_GC_RECEIVER; + } + } + + if ((type & SI_GC_CONTROLLER) == SI_GC_CONTROLLER) { + return SI_GC_CONTROLLER; + } + + return SI_ERROR_UNKNOWN; +} + +u32 SIProbe(s32 chan) { + return SIDecodeType(SIGetType(chan)); +} + +char* SIGetTypeString(u32 type) { + switch (SIDecodeType(type)) { + case SI_ERROR_NO_RESPONSE: + return "No response"; + case SI_N64_CONTROLLER: + return "N64 controller"; + case SI_N64_MIC: + return "N64 microphone"; + case SI_N64_KEYBOARD: + return "N64 keyboard"; + case SI_N64_MOUSE: + return "N64 mouse"; + case SI_GBA: + return "GameBoy Advance"; + case SI_GC_CONTROLLER: + return "Standard controller"; + case SI_GC_RECEIVER: + return "Wireless receiver"; + case SI_GC_WAVEBIRD: + return "WaveBird controller"; + case SI_GC_KEYBOARD: + return "Keyboard"; + case SI_GC_STEERING: + return "Steering"; + } +} diff --git a/src/dolphin/si/SISamplingRate.c b/src/dolphin/si/SISamplingRate.c new file mode 100644 index 000000000..3ca2e3919 --- /dev/null +++ b/src/dolphin/si/SISamplingRate.c @@ -0,0 +1,79 @@ +#include "dolphin/si/SIBios.h" +#include "dolphin/os/OS.h" +#include "dolphin/vi/vi.h" + +#define LATENCY 8 + +static u32 SamplingRate = 0; + +typedef struct XY { + u16 line; + u8 count; +} XY; + +static XY XYNTSC[12] = { + {0x00F6, 0x02}, + {0x000F, 0x12}, + {0x001E, 0x09}, + {0x002C, 0x06}, + {0x0034, 0x05}, + {0x0041, 0x04}, + {0x0057, 0x03}, + {0x0057, 0x03}, + {0x0057, 0x03}, + {0x0083, 0x02}, + {0x0083, 0x02}, + {0x0083, 0x02}, +}; + +static XY XYPAL[12] = { + {0x0128, 0x02}, + {0x000F, 0x15}, + {0x001D, 0x0B}, + {0x002D, 0x07}, + {0x0034, 0x06}, + {0x003F, 0x05}, + {0x004E, 0x04}, + {0x0068, 0x03}, + {0x0068, 0x03}, + {0x0068, 0x03}, + {0x0068, 0x03}, + {0x009C, 0x02}, +}; + +void SISetSamplingRate(u32 msec) { + XY* xy; + BOOL progressive; + BOOL enabled; + + ASSERTMSGLINE(377, 0 <= msec && msec <= 11, "SISetSamplingRate(): out of rage (0 <= msec <= 11)"); + if (msec > 11) { + msec = 11; + } + enabled = OSDisableInterrupts(); + SamplingRate = msec; + + switch (VIGetTvFormat()) { + case VI_NTSC: + case VI_MPAL: + case VI_EURGB60: + xy = XYNTSC; + break; + case VI_PAL: + xy = XYPAL; + break; + default: + OSReport("SISetSamplingRate: unknown TV format. Use default."); + msec = 0; + xy = XYNTSC; + break; + } + + progressive = __VIRegs[54] & 1; + SISetXY((progressive ? 2 : 1) * xy[msec].line, xy[msec].count); + OSRestoreInterrupts(enabled); +} + +void SIRefreshSamplingRate(void) { + SISetSamplingRate(SamplingRate); +} diff --git a/src/dolphin/vi/vi.c b/src/dolphin/vi/vi.c new file mode 100644 index 000000000..e74b61670 --- /dev/null +++ b/src/dolphin/vi/vi.c @@ -0,0 +1,1010 @@ +#include "dolphin/os/OS.h" +#include "dolphin/vi/vi.h" +#include "dolphin/gx/GX.h" + +const char* __VIVersion = "<< Dolphin SDK - VI\trelease build: Sep 5 2002 05:33:13 (0x2301) >>"; + +typedef struct { + u8 equ; + u16 acv; + u16 prbOdd; + u16 prbEven; + u16 psbOdd; + u16 psbEven; + u8 bs1; + u8 bs2; + u8 bs3; + u8 bs4; + u16 be1; + u16 be2; + u16 be3; + u16 be4; + u16 nhlines; + u16 hlw; + u8 hsy; + u8 hcs; + u8 hce; + u8 hbe640; + u16 hbs640; + u8 hbeCCIR656; + u16 hbsCCIR656; +} VITiming; + +typedef struct { + u16 DispPosX; + u16 DispPosY; + u16 DispSizeX; + u16 DispSizeY; + u16 AdjustedDispPosX; + u16 AdjustedDispPosY; + u16 AdjustedDispSizeY; + u16 AdjustedPanPosY; + u16 AdjustedPanSizeY; + u16 FBSizeX; + u16 FBSizeY; + u16 PanPosX; + u16 PanPosY; + u16 PanSizeX; + u16 PanSizeY; + VIXFBMode FBMode; + u32 nonInter; + u32 tv; + u8 wordPerLine; + u8 std; + u8 wpl; + u32 bufAddr; + u32 tfbb; + u32 bfbb; + u8 xof; + BOOL black; + BOOL threeD; + u32 rbufAddr; + u32 rtfbb; + u32 rbfbb; + VITiming* timing; +} SomeVIStruct; + +static BOOL IsInitialized; +static volatile u32 retraceCount; + +static volatile u32 flushFlag; +static OSThreadQueue retraceQueue; +static void (*PreCB)(u32); +static void (*PostCB)(u32); +static u32 encoderType; +static s16 displayOffsetH; +static s16 displayOffsetV; +static volatile u32 changeMode; +static volatile u64 changed; +static volatile u32 shdwChangeMode; +static volatile u16 regs[59]; +static volatile u64 shdwChanged; +static VITiming* CurrTiming; +static u32 CurrTvMode; +static u32 NextBufAddr; +static u32 CurrBufAddr; +static volatile u16 shdwRegs[59]; + +#define MARK_CHANGED(index) (changed |= 1LL << (63 - (index))) + +static VITiming timing[10] = { + { 6, 240, 24, 25, 3, 2, 12, 13, 12, 13, 520, 519, 520, 519, 525, 429, 64, 71, 105, 162, 373, 122, 412 }, + { 6, 240, 24, 24, 4, 4, 12, 12, 12, 12, 520, 520, 520, 520, 526, 429, 64, 71, 105, 162, 373, 122, 412 }, + { 5, 287, 35, 36, 1, 0, 13, 12, 11, 10, 619, 618, 617, 620, 625, 432, 64, 75, 106, 172, 380, 133, 420 }, + { 5, 287, 33, 33, 2, 2, 13, 11, 13, 11, 619, 621, 619, 621, 624, 432, 64, 75, 106, 172, 380, 133, 420 }, + { 6, 240, 24, 25, 3, 2, 16, 15, 14, 13, 518, 517, 516, 519, 525, 429, 64, 78, 112, 162, 373, 122, 412 }, + { 6, 240, 24, 24, 4, 4, 16, 14, 16, 14, 518, 520, 518, 520, 526, 429, 64, 78, 112, 162, 373, 122, 412 }, + { 12, 480, 48, 48, 6, 6, 24, 24, 24, 24, 1038, 1038, 1038, 1038, 1050, 429, 64, 71, 105, 162, 373, 122, 412 }, + { 12, 480, 44, 44, 10, 10, 24, 24, 24, 24, 1038, 1038, 1038, 1038, 1050, 429, 64, 71, 105, 168, 379, 122, 412 }, + { 6, 241, 24, 25, 1, 0, 12, 13, 12, 13, 520, 519, 520, 519, 525, 429, 64, 71, 105, 159, 370, 122, 412 }, + { 12, 480, 48, 48, 6, 6, 24, 24, 24, 24, 1038, 1038, 1038, 1038, 1050, 429, 64, 71, 105, 180, 391, 122, 412 } +}; + +static u16 taps[25] = { + 0x01F0, 0x01DC, + 0x01AE, 0x0174, + 0x0129, 0x00DB, + 0x008E, 0x0046, + 0x000C, 0x00E2, + 0x00CB, 0x00C0, + 0x00C4, 0x00CF, + 0x00DE, 0x00EC, + 0x00FC, 0x0008, + 0x000F, 0x0013, + 0x0013, 0x000F, + 0x000C, 0x0008, + 0x0001 +}; + +static SomeVIStruct HorVer; +static u32 FBSet; + +// prototypes +static u32 getCurrentFieldEvenOdd(void); +VITiming* __VISetExtraTiming(VITiming* t); +void __VIEnableRawPositionInterrupt(s16 x, s16 y, void (*callback)(s16, s16)); +void (*__VIDisableRawPositionInterrupt())(s16, s16); +void __VIDisplayPositionToXY(u32 hct, u32 vct, s16* x, s16* y); +void __VISetLatchMode(u32 mode); +int __VIGetLatch0Position(s16* px, s16* py); +int __VIGetLatch1Position(s16* px, s16* py); +int __VIGetLatchPosition(u32 port, s16* px, s16* py); +void __VIGetCurrentPosition(s16* x, s16* y); + + +static u32 getEncoderType(void) { + return 1; +} + +static s32 cntlzd(u64 bit) { + u32 hi; + u32 lo; + s32 value; + + hi = bit >> 32; + lo = bit & 0xFFFFFFFF; + value = __cntlzw(hi); + if (value < 32) { + return value; + } + return __cntlzw(lo) + 32; +} + +static int VISetRegs(void) { + s32 regIndex; + + if (shdwChangeMode != 1 || getCurrentFieldEvenOdd() != 0) { + while (shdwChanged != 0) { + regIndex = cntlzd(shdwChanged); + __VIRegs[regIndex] = shdwRegs[regIndex]; + shdwChanged &= ~((u64)1 << (63 - regIndex)); + } + + shdwChangeMode = 0; + CurrTiming = HorVer.timing; + CurrTvMode = HorVer.tv; + CurrBufAddr = NextBufAddr; + return 1; + } + + return 0; +} + +static void __VIRetraceHandler(__OSInterrupt unused, OSContext* context) { + OSContext exceptionContext; + u16 reg; + u32 inter; +#if DEBUG + static u32 dbgCount; +#endif + + inter = 0; + reg = __VIRegs[0x18]; + if (reg & 0x8000) { + __VIRegs[0x18] = reg & ~0x8000; + inter |= 1; + } + reg = __VIRegs[0x1A]; + if (reg & 0x8000) { + __VIRegs[0x1A] = reg & ~0x8000; + inter |= 2; + } + reg = __VIRegs[0x1C]; + if (reg & 0x8000) { + __VIRegs[0x1C] = reg & ~0x8000; + inter |= 4; + } + reg = __VIRegs[0x1E]; + if (reg & 0x8000) { + __VIRegs[0x1E] = reg & ~0x8000; + inter |= 8; + } + reg = __VIRegs[0x1E]; + + if ((inter & 4) || (inter & 8)) { + OSSetCurrentContext(context); + return; + } + + if (inter == 0) { + ASSERTLINE(955, FALSE); + } + + retraceCount += 1; + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + + if (PreCB) { + PreCB(retraceCount); + } + + if (flushFlag != 0) { +#if DEBUG + dbgCount = 0; +#endif + if (VISetRegs() != 0) { + flushFlag = 0; + SIRefreshSamplingRate(); + } + } +#if DEBUG + else if (changed != 0) { + dbgCount++; + if (dbgCount > 60) { + OSReport("Warning: VIFlush() was not called for 60 frames although VI settings were changed\n"); + dbgCount = 0; + } + } +#endif + + if (PostCB) { + OSClearContext(&exceptionContext); + PostCB(retraceCount); + } + + OSWakeupThread(&retraceQueue); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +VIRetraceCallback VISetPreRetraceCallback(VIRetraceCallback cb) { + BOOL enabled; + VIRetraceCallback oldcb; + + oldcb = PreCB; + enabled = OSDisableInterrupts(); + PreCB = cb; + OSRestoreInterrupts(enabled); + return oldcb; +} + +VIRetraceCallback VISetPostRetraceCallback(VIRetraceCallback cb) { + BOOL enabled; + VIRetraceCallback oldcb; + + oldcb = PostCB; + enabled = OSDisableInterrupts(); + PostCB = cb; + OSRestoreInterrupts(enabled); + return oldcb; +} + +#pragma dont_inline on +static VITiming* getTiming(VITVMode mode) { + switch (mode) { + case VI_TVMODE_NTSC_INT: return &timing[0]; + case VI_TVMODE_NTSC_DS: return &timing[1]; + case VI_TVMODE_PAL_INT: return &timing[2]; + case VI_TVMODE_PAL_DS: return &timing[3]; + case VI_TVMODE_EURGB60_INT: return &timing[0]; + case VI_TVMODE_EURGB60_DS: return &timing[1]; + case VI_TVMODE_MPAL_INT: return &timing[4]; + case VI_TVMODE_MPAL_DS: return &timing[5]; + case VI_TVMODE_NTSC_PROG: return &timing[6]; + case 3: return &timing[7]; + case VI_TVMODE_DEBUG_PAL_INT: return &timing[2]; + case VI_TVMODE_DEBUG_PAL_DS: return &timing[3]; + case 24: return &timing[8]; + case 26: return &timing[9]; + default: + return NULL; + } +} +#pragma dont_inline reset + +void __VIInit(VITVMode mode) { + VITiming* tm; + u32 nonInter; + u32 tv; + volatile u32 a; + u16 hct; + u16 vct; + u32 encoderType; + + encoderType = getEncoderType(); + if (encoderType == 0) { + __VIInitPhilips(); + } + + nonInter = mode & 2; + tv = (u32)mode >> 2; + *(u32*)OSPhysicalToCached(0xCC) = tv; + if (encoderType == 0) { + tv = 3; + } + tm = getTiming(mode); + __VIRegs[1] = 2; + + // why? + for (a = 0; a < 1000; a++) {} + + __VIRegs[1] = 0; + __VIRegs[3] = (u32)tm->hlw; + __VIRegs[2] = tm->hce | (tm->hcs << 8); + __VIRegs[5] = tm->hsy | ((tm->hbe640 & 0x1FF) << 7); + __VIRegs[4] = (tm->hbe640 >> 9) | ((tm->hbs640 & 0xFFFF) << 1); + if (encoderType == 0) { + __VIRegs[0x39] = tm->hbeCCIR656 | 0x8000; + __VIRegs[0x3A] = (u32)tm->hbsCCIR656; + } + __VIRegs[0] = (u32)tm->equ; + __VIRegs[7] = (u32)(tm->prbOdd + (tm->acv * 2) - 2); + __VIRegs[6] = (u32)(tm->psbOdd + 2); + __VIRegs[9] = (u32)(tm->prbEven + (tm->acv * 2) - 2); + __VIRegs[8] = (u32)(tm->psbEven + 2); + __VIRegs[11] = tm->bs1 | (tm->be1 << 5); + __VIRegs[10] = tm->bs3 | (tm->be3 << 5); + __VIRegs[13] = tm->bs2 | (tm->be2 << 5); + __VIRegs[12] = tm->bs4 | (tm->be4 << 5); + __VIRegs[36] = 0x2828; + __VIRegs[27] = 1; + __VIRegs[26] = 0x1001; + hct = tm->hlw + 1; + vct = (tm->nhlines / 2) + 1; + __VIRegs[25] = (u16)(u32)hct; + __VIRegs[24] = vct | 0x1000; + + if (mode != VI_TVMODE_NTSC_PROG && mode != VI_TVMODE_NTSC_3D && mode != VI_TVMODE_GCA_PROG) { + __VIRegs[1] = (nonInter << 2) | 1 | (tv << 8); + __VIRegs[54] = 0; + return; + } + __VIRegs[1] = (tv << 8) | 5; + __VIRegs[54] = 1; +} + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define CLAMP(val, min, max) ((val) > (max) ? (max) : (val) < (min) ? (min) : (val)) + +static void AdjustPosition(u16 acv) { + s32 coeff; + s32 frac; + + HorVer.AdjustedDispPosX = CLAMP((s16)HorVer.DispPosX + displayOffsetH, 0, 0x2D0 - HorVer.DispSizeX); + coeff = (HorVer.FBMode == VI_XFBMODE_SF) ? 2 : 1; + frac = HorVer.DispPosY & 1; + HorVer.AdjustedDispPosY = MAX((s16)HorVer.DispPosY + displayOffsetV, frac); + HorVer.AdjustedDispSizeY = HorVer.DispSizeY + + MIN((s16)HorVer.DispPosY + displayOffsetV - frac, 0) + - MAX((s16)HorVer.DispPosY + (s16)HorVer.DispSizeY + displayOffsetV - (((s16)acv * 2) - frac), 0); + HorVer.AdjustedPanPosY = HorVer.PanPosY + - (MIN((s16)HorVer.DispPosY + displayOffsetV - frac, 0) / coeff); + HorVer.AdjustedPanSizeY = HorVer.PanSizeY + + (MIN((s16)HorVer.DispPosY + displayOffsetV - frac, 0) / coeff) + - (MAX((s16)HorVer.DispPosY + (s16)HorVer.DispSizeY + displayOffsetV - (((s16)acv * 2) - frac), 0) / coeff); +} + +static void ImportAdjustingValues(void) { + OSSram* sram = __OSLockSram(); + + ASSERTLINE(1322, sram); + displayOffsetH = sram->displayOffsetH; + displayOffsetV = 0; + __OSUnlockSram(0); +} + +void VIInit(void) { + u16 dspCfg; + u32 value; + u32 tv; + u32 tvInBootrom; + + if (IsInitialized) { + return; + } + + OSRegisterVersion(__VIVersion); + IsInitialized = TRUE; + + encoderType = getEncoderType(); + if (!(__VIRegs[1] & 1)) { + __VIInit(VI_TVMODE_NTSC_INT); + } + + retraceCount = 0; + changed = 0; + shdwChanged = 0; + changeMode = 0; + shdwChangeMode = 0; + flushFlag = 0; + + __VIRegs[39] = taps[0] | ((taps[1] & 0x3F) << 10); + __VIRegs[38] = (taps[1] >> 6) | (taps[2] << 4); + __VIRegs[41] = taps[3] | ((taps[4] & 0x3F) << 10); + __VIRegs[40] = (taps[4] >> 6) | (taps[5] << 4); + __VIRegs[43] = taps[6] | ((taps[7] & 0x3F) << 10); + __VIRegs[42] = (taps[7] >> 6) | (taps[8] << 4); + __VIRegs[45] = taps[9] | (taps[10] << 8); + __VIRegs[44] = taps[11] | (taps[12] << 8); + __VIRegs[47] = taps[13] | (taps[14] << 8); + __VIRegs[46] = taps[15] | (taps[16] << 8); + __VIRegs[49] = taps[17] | (taps[18] << 8); + __VIRegs[48] = taps[19] | (taps[20] << 8); + __VIRegs[51] = taps[21] | (taps[22] << 8); + __VIRegs[50] = taps[23] | (taps[24] << 8); + __VIRegs[56] = 0x280; + ImportAdjustingValues(); + + tvInBootrom = *(u32*)OSPhysicalToCached(0xCC); + dspCfg = __VIRegs[1]; + HorVer.nonInter = (s32) ((dspCfg >> 2U) & 1); + HorVer.tv = ((u32)(dspCfg) & 0x300) >> 8; + + if (tvInBootrom == VI_PAL && HorVer.tv == VI_NTSC) { + HorVer.tv = VI_EURGB60; + } + + tv = (HorVer.tv == 3) ? 0 : HorVer.tv; + HorVer.timing = getTiming((tv << 2) + HorVer.nonInter); + regs[1] = dspCfg; + + CurrTiming = HorVer.timing; + CurrTvMode = HorVer.tv; + + HorVer.DispSizeX = 640; + HorVer.DispSizeY = CurrTiming->acv * 2; + HorVer.DispPosX = (720 - HorVer.DispSizeX) / 2; + HorVer.DispPosY = 0; + AdjustPosition(CurrTiming->acv); + HorVer.FBSizeX = 640; + HorVer.FBSizeY = CurrTiming->acv * 2; + HorVer.PanPosX = 0; + HorVer.PanPosY = 0; + HorVer.PanSizeX = 640; + HorVer.PanSizeY = CurrTiming->acv * 2; + HorVer.FBMode = 0; + + HorVer.wordPerLine = 40; + HorVer.std = 40; + HorVer.wpl = 40; + HorVer.xof = 0; + HorVer.black = 1; + HorVer.threeD = 0; + OSInitThreadQueue(&retraceQueue); + value = __VIRegs[24]; + value &= ~0x8000; +#if !DEBUG + value = (u16)value; +#endif + __VIRegs[24] = value; + value = __VIRegs[26]; + value = value & ~0x8000; +#if !DEBUG + value = (u16)value; +#endif + __VIRegs[26] = value; + PreCB = NULL; + PostCB = NULL; + __OSSetInterruptHandler(0x18, __VIRetraceHandler); + __OSUnmaskInterrupts(0x80); +} + +void VIWaitForRetrace(void) { + BOOL enabled; + u32 count; + + enabled = OSDisableInterrupts(); + count = retraceCount; + do { + OSSleepThread(&retraceQueue); + } while (count == retraceCount); + OSRestoreInterrupts(enabled); +} + +static void setInterruptRegs(VITiming* tm) { +#if DEBUG + u16 vct, hct; +#else + u16 hct, vct; +#endif + u16 borrow; + + vct = tm->nhlines / 2; + borrow = tm->nhlines % 2; + if (borrow != 0) { + hct = tm->hlw; + } else { + hct = 0; + } + vct++; + hct++; + regs[25] = (u16)(u32)hct; + MARK_CHANGED(25); + regs[24] = vct | 0x1000; + MARK_CHANGED(24); + + vct; // fixes regalloc +} + +static void setPicConfig(u16 fbSizeX, VIXFBMode xfbMode, u16 panPosX, u16 panSizeX, u8* wordPerLine, u8* std, u8* wpl, u8* xof) { + *wordPerLine = (fbSizeX + 15) / 16; + *std = (xfbMode == VI_XFBMODE_SF) ? *wordPerLine : (u8)(*wordPerLine * 2); + *xof = panPosX % 16; + *wpl = (*xof + panSizeX + 15) / 16; + regs[0x24] = *std | (*wpl << 8); + changed |= 0x8000000; +} + +static void setBBIntervalRegs(VITiming* tm) { + u16 val; + + val = tm->bs1 | (tm->be1 << 5); + regs[11] = val; + changed |= 0x10000000000000; + + val = tm->bs3 | (tm->be3 << 5); + regs[10] = val; + changed |= 0x20000000000000; + + val = tm->bs2 | (tm->be2 << 5); + regs[13] = val; + changed |= 0x4000000000000; + + val = tm->bs4 | (tm->be4 << 5); + regs[12] = val; + changed |= (1LL << (63-12)); +} + +static void setScalingRegs(u16 panSizeX, u16 dispSizeX, BOOL threeD) { + u32 scale; + + panSizeX = threeD ? (panSizeX << 1) : panSizeX; + if (panSizeX < dispSizeX) { + scale = (u32)(dispSizeX + (panSizeX << 8) - 1) / dispSizeX; + regs[37] = scale | 0x1000; + changed |= 0x04000000; + regs[56] = (u32)panSizeX; + changed |= 0x80; + } else { + regs[37] = 0x100; + changed |= 0x04000000; + } +} + +static void calcFbbs(u32 bufAddr, u16 panPosX, u16 panPosY, u8 wordPerLine, VIXFBMode xfbMode, u16 dispPosY, u32* tfbb, u32* bfbb) { + u32 bytesPerLine; + u32 xoffInWords; + u32 tmp; + + xoffInWords = (panPosX & ~0xF) >> 4; + bytesPerLine = (wordPerLine & 0xFF) << 5; + *tfbb = bufAddr + (xoffInWords << 5) + (bytesPerLine * panPosY); + *bfbb = (xfbMode == VI_XFBMODE_SF) ? *tfbb : *tfbb + bytesPerLine; + if (dispPosY % 2 == 1) { + tmp = *tfbb; + *tfbb = *bfbb; + *bfbb = tmp; + } + *tfbb &= 0x3FFFFFFF; + *bfbb &= 0x3FFFFFFF; +} + +static void setFbbRegs(SomeVIStruct* HorVer, u32* tfbb, u32* bfbb, u32* rtfbb, u32* rbfbb) { + u32 shifted; + + calcFbbs(HorVer->bufAddr, HorVer->PanPosX, HorVer->AdjustedPanPosY, HorVer->wordPerLine, HorVer->FBMode, HorVer->AdjustedDispPosY, tfbb, bfbb); + if (HorVer->threeD) { + calcFbbs(HorVer->rbufAddr, HorVer->PanPosX, HorVer->AdjustedPanPosY, HorVer->wordPerLine, HorVer->FBMode, HorVer->AdjustedDispPosY, rtfbb, rbfbb); + } + + if (*tfbb < 0x01000000U && *bfbb < 0x01000000U && *rtfbb < 0x01000000U && *rbfbb < 0x01000000U) { + shifted = 0; + } else { + shifted = 1; + } + + if (shifted) { + *tfbb >>= 5; + *bfbb >>= 5; + *rtfbb >>= 5; + *rbfbb >>= 5; + } + + regs[15] = (u16)*tfbb & 0xFFFF; + MARK_CHANGED(15); + regs[14] = (shifted << 12) | ((*tfbb >> 16) | (HorVer->xof << 8)); + MARK_CHANGED(14); + regs[19] = (u16)*bfbb & 0xFFFF; + MARK_CHANGED(19); + regs[18] = (*bfbb >> 16); + MARK_CHANGED(18); + + if (HorVer->threeD) { + regs[17] = (u16)*rtfbb & 0xFFFF; + MARK_CHANGED(17); + regs[16] = *rtfbb >> 16; + MARK_CHANGED(16); + regs[21] = (u16)*rbfbb & 0xFFFF; + MARK_CHANGED(21); + regs[20] = *rbfbb >> 16; + MARK_CHANGED(20); + } +} + +static void setHorizontalRegs(VITiming* tm, u16 dispPosX, u16 dispSizeX) { + u32 hbe; + u32 hbs; + u32 hbeLo; + u32 hbeHi; + + regs[3] = (u16)(u32)tm->hlw; + MARK_CHANGED(3); + regs[2] = tm->hce | (tm->hcs << 8); + MARK_CHANGED(2); + hbe = tm->hbe640 - 40 + dispPosX; + hbs = tm->hbs640 + 40 + dispPosX - (720 - dispSizeX); + hbeLo = hbe & 0x1FF; + hbeHi = hbe >> 9; + regs[5] = tm->hsy | (hbeLo << 7); + MARK_CHANGED(5); + regs[4] = hbeHi | (hbs * 2); + MARK_CHANGED(4); +} + +static void setVerticalRegs(u16 dispPosY, u16 dispSizeY, u8 equ, u16 acv, u16 prbOdd, u16 prbEven, u16 psbOdd, u16 psbEven, BOOL black) { + u16 actualPrbOdd; + u16 actualPrbEven; + u16 actualPsbOdd; + u16 actualPsbEven; + u16 actualAcv; + u16 c; + u16 d; + + if (regs[54] & 1) { + c = 1; + d = 2; + } else { + c = 2; + d = 1; + } + + if ((dispPosY % 2) == 0) { + actualPrbOdd = prbOdd + (d * dispPosY); + actualPsbOdd = psbOdd + (d * (((c * acv) - dispSizeY) - dispPosY)); + actualPrbEven = prbEven + (d * dispPosY); + actualPsbEven = psbEven + (d * (((c * acv) - dispSizeY) - dispPosY)); + } else { + actualPrbOdd = prbEven + (d * dispPosY); + actualPsbOdd = psbEven + (d * (((c * acv) - dispSizeY) - dispPosY)); + actualPrbEven = prbOdd + (d * dispPosY); + actualPsbEven = psbOdd + (d * (((c * acv) - dispSizeY) - dispPosY)); + } + + actualAcv = dispSizeY / c; + + if (black) { + actualPrbOdd += 2 * actualAcv - 2; + actualPsbOdd += 2; + actualPrbEven += 2 * actualAcv - 2; + actualPsbEven += 2; + actualAcv = 0; + } + + regs[0] = equ | (actualAcv << 4); + MARK_CHANGED(0); + regs[7] = (u16)(u32)actualPrbOdd; + MARK_CHANGED(7); + regs[6] = (u16)(u32)actualPsbOdd; + MARK_CHANGED(6); + regs[9] = (u16)(u32)actualPrbEven; + MARK_CHANGED(9); + regs[8] = (u16)(u32)actualPsbEven; + MARK_CHANGED(8); +} + +static void PrintDebugPalCaution(void) { + static u32 message; + + if (message == 0) { + message = 1; + OSReport("***************************************\n"); + OSReport(" ! ! ! C A U T I O N ! ! ! \n"); + OSReport("This TV format \"DEBUG_PAL\" is only for \n"); + OSReport("temporary solution until PAL DAC board \n"); + OSReport("is available. Please do NOT use this \n"); + OSReport("mode in real games!!! \n"); + OSReport("***************************************\n"); + } +} + +void VIConfigure(GXRenderModeObj* rm) { + VITiming* tm; + u32 regDspCfg; + BOOL enabled; + u32 newNonInter; + u32 tvInBootrom; + u32 tvInGame; + + enabled = OSDisableInterrupts(); + newNonInter = rm->viTVmode & 3; + + if (HorVer.nonInter != newNonInter) { + changeMode = 1; + HorVer.nonInter = newNonInter; + } + + ASSERTMSGLINEV(1926, (rm->viHeight & 1) == 0, + "VIConfigure(): Odd number(%d) is specified to viHeight\n", + rm->viHeight); + +#if DEBUG + if (rm->xFBmode == VI_XFBMODE_DF || newNonInter == VI_TVMODE_NTSC_PROG || newNonInter == 3) { + ASSERTMSGLINEV(1933, rm->xfbHeight == rm->viHeight, + "VIConfigure(): xfbHeight(%d) is not equal to viHeight(%d) when DF XFB mode or progressive mode is specified\n", + rm->xfbHeight, rm->viHeight); + } + + if (rm->xFBmode == VI_XFBMODE_SF && newNonInter != VI_TVMODE_NTSC_PROG && newNonInter != 3) { + ASSERTMSGLINEV(1941, rm->viHeight == rm->xfbHeight * 2, + "VIConfigure(): xfbHeight(%d) is not as twice as viHeight(%d) when SF XFB mode is specified\n", + rm->xfbHeight, rm->viHeight); + } +#endif + + tvInGame = (u32)rm->viTVmode >> 2; + tvInBootrom = *(u32*)OSPhysicalToCached(0xCC); + + if (tvInGame == VI_DEBUG_PAL) { + PrintDebugPalCaution(); + } + + switch (tvInBootrom) { + case VI_MPAL: + case VI_NTSC: + case VI_GCA: + if (tvInGame == VI_NTSC || tvInGame == VI_MPAL || tvInGame == VI_GCA) { + break; + } + goto panic; + case VI_PAL: + case VI_EURGB60: + if (tvInGame == VI_PAL || tvInGame == VI_EURGB60) { + break; + } + default: + panic: + OSPanic(__FILE__, 1884, + "VIConfigure(): Tried to change mode from (%d) to (%d), which is forbidden\n", + tvInBootrom, tvInGame); + } + + if ((tvInGame == VI_NTSC) || (tvInGame == VI_MPAL)) { + HorVer.tv = tvInBootrom; + } else { + HorVer.tv = tvInGame; + } + + HorVer.DispPosX = rm->viXOrigin; + HorVer.DispPosY = (HorVer.nonInter == 1) ? (u16)(rm->viYOrigin * 2) : rm->viYOrigin; + HorVer.DispSizeX = rm->viWidth; + HorVer.FBSizeX = rm->fbWidth; + HorVer.FBSizeY = rm->xfbHeight; + HorVer.FBMode = rm->xFBmode; + HorVer.PanSizeX = HorVer.FBSizeX; + HorVer.PanSizeY = HorVer.FBSizeY; + HorVer.PanPosX = 0; + HorVer.PanPosY = 0; + HorVer.DispSizeY = (HorVer.nonInter == 2) ? HorVer.PanSizeY : + (HorVer.nonInter == 3) ? HorVer.PanSizeY : + (HorVer.FBMode == VI_XFBMODE_SF) ? (u16)(HorVer.PanSizeY * 2) : + HorVer.PanSizeY; + HorVer.threeD = (HorVer.nonInter == 3) ? TRUE : FALSE; + + tm = getTiming((HorVer.tv << 2) + HorVer.nonInter); + HorVer.timing = tm; + + AdjustPosition(tm->acv); + ASSERTMSGLINEV(2022, rm->viXOrigin <= tm->hlw + 40 - tm->hbe640, + "VIConfigure(): viXOrigin(%d) cannot be greater than %d in this TV mode\n", + rm->viXOrigin, tm->hlw + 40 - tm->hbe640); + ASSERTMSGLINEV(2027, rm->viXOrigin + rm->viWidth >= 680 - tm->hbs640, + "VIConfigure(): viXOrigin + viWidth (%d) cannot be less than %d in this TV mode\n", + rm->viXOrigin + rm->viWidth, 680 - tm->hbs640); + + if (encoderType == 0) { + HorVer.tv = 3; + } + setInterruptRegs(tm); + + regDspCfg = regs[1]; + + if ((HorVer.nonInter == VI_PROGRESSIVE) || (HorVer.nonInter == VI_3D)) { + regDspCfg = (((u32)(regDspCfg)) & ~0x00000004) | (((u32)(1)) << 2); + } else { + regDspCfg = (((u32)(regDspCfg)) & ~0x00000004) | (((u32)(HorVer.nonInter & 1)) << 2); + } + + regDspCfg = (((u32)(regDspCfg)) & ~0x00000008) | (((u32)(HorVer.threeD)) << 3); + + if ((HorVer.tv == VI_DEBUG_PAL) || (HorVer.tv == VI_EURGB60) || (HorVer.tv == VI_GCA)) { + regDspCfg = (((u32)(regDspCfg)) & ~0x00000300) | (((u32)(0)) << 8); + } else { + regDspCfg = (((u32)(regDspCfg)) & ~0x00000300) | (((u32)(HorVer.tv)) << 8); + } + + regs[1] = regDspCfg; + MARK_CHANGED(1); + + regDspCfg = regs[54]; + if (rm->viTVmode == VI_TVMODE_NTSC_PROG || rm->viTVmode == VI_TVMODE_NTSC_3D || rm->viTVmode == VI_TVMODE_GCA_PROG) { + regDspCfg = (u32)(regDspCfg & ~0x1) | 1; + } else { + regDspCfg = (u32)(regDspCfg & ~0x1); + } + + regs[54] = (u16)regDspCfg; + MARK_CHANGED(54); + + setScalingRegs(HorVer.PanSizeX, HorVer.DispSizeX, HorVer.threeD); + setHorizontalRegs(tm, HorVer.AdjustedDispPosX, HorVer.DispSizeX); + setBBIntervalRegs(tm); + setPicConfig(HorVer.FBSizeX, HorVer.FBMode, HorVer.PanPosX, HorVer.PanSizeX, &HorVer.wordPerLine, &HorVer.std, &HorVer.wpl, &HorVer.xof); + if (FBSet != 0) { + setFbbRegs(&HorVer, &HorVer.tfbb, &HorVer.bfbb, &HorVer.rtfbb, &HorVer.rbfbb); + } + setVerticalRegs(HorVer.AdjustedDispPosY, HorVer.AdjustedDispSizeY, tm->equ, tm->acv, tm->prbOdd, tm->prbEven, tm->psbOdd, tm->psbEven, HorVer.black); + OSRestoreInterrupts(enabled); +} + +void VIConfigurePan(u16 xOrg, u16 yOrg, u16 width, u16 height) { + BOOL enabled; + VITiming* tm; + +#if DEBUG + ASSERTMSGLINEV(2118, (xOrg & 1) == 0, + "VIConfigurePan(): Odd number(%d) is specified to xOrg\n", + xOrg); + if (HorVer.FBMode == VI_XFBMODE_DF) { + ASSERTMSGLINEV(2123, (height & 1) == 0, + "VIConfigurePan(): Odd number(%d) is specified to height when DF XFB mode\n", + height); + } +#endif + enabled = OSDisableInterrupts(); + HorVer.PanPosX = xOrg; + HorVer.PanPosY = yOrg; + HorVer.PanSizeX = width; + HorVer.PanSizeY = height; + HorVer.DispSizeY = (HorVer.nonInter == 2) ? HorVer.PanSizeY : + (HorVer.nonInter == 3) ? HorVer.PanSizeY : + (HorVer.FBMode == VI_XFBMODE_SF) ? (u16)(HorVer.PanSizeY * 2) : + HorVer.PanSizeY; + tm = HorVer.timing; + AdjustPosition(tm->acv); + setScalingRegs(HorVer.PanSizeX, HorVer.DispSizeX, HorVer.threeD); + setPicConfig(HorVer.FBSizeX, HorVer.FBMode, HorVer.PanPosX, HorVer.PanSizeX, &HorVer.wordPerLine, &HorVer.std, &HorVer.wpl, &HorVer.xof); + if (FBSet != 0) { + setFbbRegs(&HorVer, &HorVer.tfbb, &HorVer.bfbb, &HorVer.rtfbb, &HorVer.rbfbb); + } + setVerticalRegs(HorVer.AdjustedDispPosY, HorVer.DispSizeY, tm->equ, tm->acv, tm->prbOdd, tm->prbEven, tm->psbOdd, tm->psbEven, HorVer.black); + OSRestoreInterrupts(enabled); +} + +void VIFlush(void) { + BOOL enabled; + s32 regIndex; + + enabled = OSDisableInterrupts(); + shdwChangeMode |= changeMode; + changeMode = 0; + shdwChanged |= changed; + + while (changed != 0) { + regIndex = cntlzd(changed); + shdwRegs[regIndex] = regs[regIndex]; + changed &= ~((u64)1 << (63 - regIndex)); + } + + flushFlag = 1; + NextBufAddr = HorVer.bufAddr; + OSRestoreInterrupts(enabled); +} + +void VISetNextFrameBuffer(void* fb) { + BOOL enabled; + + ASSERTMSGLINEV(2216, ((u32)fb & 0x1F) == 0, + "VISetNextFrameBuffer(): Frame buffer address(0x%08x) is not 32byte aligned\n", + fb); + enabled = OSDisableInterrupts(); + HorVer.bufAddr = (u32)fb; + FBSet = 1; + setFbbRegs(&HorVer, &HorVer.tfbb, &HorVer.bfbb, &HorVer.rtfbb, &HorVer.rbfbb); + OSRestoreInterrupts(enabled); +} + +void VISetBlack(BOOL black) { + BOOL enabled; + VITiming* tm; + + enabled = OSDisableInterrupts(); + HorVer.black = black; + tm = HorVer.timing; + setVerticalRegs(HorVer.AdjustedDispPosY, HorVer.DispSizeY, tm->equ, tm->acv, tm->prbOdd, tm->prbEven, tm->psbOdd, tm->psbEven, HorVer.black); + OSRestoreInterrupts(enabled); +} + +u32 VIGetRetraceCount(void) { + return retraceCount; +} + +static u32 getCurrentHalfLine(void) { + u32 hcount; + u32 vcount0; + u32 vcount; + + vcount = __VIRegs[22] & 0x7FF; + do { + vcount0 = vcount; + hcount = __VIRegs[23] & 0x7FF; + vcount = __VIRegs[22] & 0x7FF; + } while (vcount0 != vcount); + return ((vcount - 1) * 2) + ((hcount - 1) / CurrTiming->hlw); +} + +static u32 getCurrentFieldEvenOdd(void) { + return (getCurrentHalfLine() < CurrTiming->nhlines) ? 1 : 0; +} + +u32 VIGetNextField(void) { + s32 nextField; + BOOL enabled; + + enabled = OSDisableInterrupts(); + nextField = getCurrentFieldEvenOdd() ^ 1; + OSRestoreInterrupts(enabled); + return nextField ^ (HorVer.AdjustedDispPosY & 1); +} + +u32 VIGetCurrentLine(void) { + u32 halfLine; + VITiming* tm; + BOOL enabled; + + tm = CurrTiming; + enabled = OSDisableInterrupts(); + halfLine = getCurrentHalfLine(); + OSRestoreInterrupts(enabled); + if (halfLine >= tm->nhlines) { + halfLine -= tm->nhlines; + } + return halfLine >> 1U; +} + +u32 VIGetTvFormat(void) { + u32 format; + BOOL enabled; + + enabled = OSDisableInterrupts(); + + switch (CurrTvMode) { + case VI_NTSC: + case VI_DEBUG: + case 6: + format = VI_NTSC; + break; + case VI_PAL: + case VI_DEBUG_PAL: + format = VI_PAL; + break; + case VI_EURGB60: + case VI_MPAL: + format = CurrTvMode; + break; + default: + ASSERTLINE(2527, FALSE); + } + + OSRestoreInterrupts(enabled); + return format; +} + +u32 VIGetDTVStatus(void) { + u32 dtvStatus; + BOOL enabled = OSDisableInterrupts(); + + dtvStatus = __VIRegs[55] & 3; + OSRestoreInterrupts(enabled); + return dtvStatus & 1; +} diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index 13813e74d..ac59eef0a 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -281,7 +281,7 @@ bool mDoGph_AfterOfDraw() { BOOL printVisible = false; #else BOOL consoleVisible = JFWSystem::getSystemConsole()->isVisible(); - BOOL pad3Connected = JUTGamePad::getPortStatus(JUTGamePad::Port_3).error == 0; + BOOL pad3Connected = JUTGamePad::getPortStatus(JUTGamePad::Port_3).err == 0; BOOL procVisible = pad3Connected && fapGmHIO_getMeter() && !consoleVisible; BOOL printVisible = pad3Connected && fapGmHIO_isPrint(); if (mDoMain::developmentMode == 0) { diff --git a/src/odemuexi2/DebuggerDriver.c b/src/odemuexi2/DebuggerDriver.c new file mode 100644 index 000000000..847014a9f --- /dev/null +++ b/src/odemuexi2/DebuggerDriver.c @@ -0,0 +1,301 @@ +#include "odemuexi2/DebuggerDriver.h" +#include "dolphin/os/OS.h" + +static MTRCallbackType MTRCallback; + +static void (*DBGCallback)(u32, OSContext*); + +static u32 SendMailData; + +static s32 RecvDataLeng; + +static u8* pEXIInputFlag; + +static u8 EXIInputFlag; + +static u8 SendCount = 0x80; + +#define IS_TRUE(x) ((x) != FALSE) +#define IS_FALSE(x) !IS_TRUE(x) +#define ROUND_UP(x, align) (((x) + (align)-1) & (-(align))) + +void DBGEXIInit() { + __OSMaskInterrupts(0x18000); + __EXIRegs[10] = 0; +} + +static u32 DBGEXISelect(u32 v) { + u32 regs = __EXIRegs[10]; + regs &= 0x405; + regs |= 0x80 | (v << 4); + __EXIRegs[10] = regs; + return TRUE; +} + +BOOL DBGEXIDeselect(void) { + __EXIRegs[10] &= 0x405; + return TRUE; +} + +static BOOL DBGEXISync() { + while (__EXIRegs[13] & 1) + ; + + return TRUE; +} + +static BOOL DBGEXIImm(void* buffer, s32 bytecounter, u32 write) { + u8* tempPointer; + u32 writeOutValue; + int i; + + if (write) { + tempPointer = buffer; + writeOutValue = 0; + for (i = 0; i < bytecounter; i++) { + u8* temp = ((u8*)buffer) + i; + writeOutValue |= *temp << ((3 - i) << 3); + } + __EXIRegs[14] = writeOutValue; + } + + __EXIRegs[13] = 1 | write << 2 | (bytecounter - 1) << 4; + DBGEXISync(); + + if (!write) { + writeOutValue = __EXIRegs[14]; + tempPointer = buffer; + for (i = 0; i < bytecounter; i++) { + *tempPointer++ = writeOutValue >> ((3 - i) << 3); + } + } + + return TRUE; +} + +static BOOL DBGWriteMailbox(u32 p1) { + u32 cmd = 0xc0000000; + u32 v; + u32 base = p1; + BOOL total = FALSE; + + DBGEXISelect(4); + v = (base & 0x1fffffff) | (cmd); + total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 1)); + total |= IS_FALSE(DBGEXISync()); + total |= IS_FALSE(DBGEXIDeselect()); + + return IS_FALSE(total); +} + +#pragma dont_inline on +static BOOL DBGReadMailbox(u32* p1) { + BOOL total = FALSE; + u32 v; + + DBGEXISelect(4); + + v = 0x60000000; + total |= IS_FALSE(DBGEXIImm(&v, 2, 1)); + total |= IS_FALSE(DBGEXISync()); + + total |= IS_FALSE(DBGEXIImm(p1, 4, 0)); + total |= IS_FALSE(DBGEXISync()); + + total |= IS_FALSE(DBGEXIDeselect()); + + return IS_FALSE(total); +} +#pragma dont_inline reset + +static BOOL DBGRead(u32 count, u32* buffer, s32 param3) { + BOOL total = FALSE; + u32* buf_p = (u32*)buffer; + u32 v1; + u32 v; + + DBGEXISelect(4); + + v1 = (count & 0x1fffc) << 8 | 0x20000000; + total |= IS_FALSE(DBGEXIImm(&v1, sizeof(v1), 1)); + total |= IS_FALSE(DBGEXISync()); + + while (param3) { + total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 0)); + total |= IS_FALSE(DBGEXISync()); + + *buf_p++ = v; + + param3 -= 4; + if (param3 < 0) { + param3 = 0; + } + } + + total |= IS_FALSE(DBGEXIDeselect()); + return IS_FALSE(total); +} + +static BOOL DBGWrite(u32 count, void* buffer, s32 param3) { + BOOL total = FALSE; + u32* buf_p = (u32*)buffer; + u32 v1; + u32 v; + + DBGEXISelect(4); + + v1 = (count & 0x1fffc) << 8 | 0xa0000000; + total |= IS_FALSE(DBGEXIImm(&v1, sizeof(v1), 1)); + total |= IS_FALSE(DBGEXISync()); + + while (param3 != 0) { + v = *buf_p++; + + total |= IS_FALSE(DBGEXIImm(&v, sizeof(v), 1)); + total |= IS_FALSE(DBGEXISync()); + + param3 -= 4; + if (param3 < 0) { + param3 = 0; + } + } + + total |= IS_FALSE(DBGEXIDeselect()); + return IS_FALSE(total); +} + +inline static BOOL _DBGReadStatus(u32* p1) { + BOOL total = FALSE; + u32 v; + + DBGEXISelect(4); + + v = 1 << 30; + total |= IS_FALSE(DBGEXIImm(&v, 2, 1)); + total |= IS_FALSE(DBGEXISync()); + + total |= IS_FALSE(DBGEXIImm(p1, 4, 0)); + total |= IS_FALSE(DBGEXISync()); + + total |= IS_FALSE(DBGEXIDeselect()); + + return IS_FALSE(total); +} +#pragma dont_inline on +static BOOL DBGReadStatus(u32* p1) { + return _DBGReadStatus(p1); +} +#pragma dont_inline reset + +static void MWCallback(u32 a, OSContext* b) { + EXIInputFlag = TRUE; + if (MTRCallback) { + MTRCallback(0); + } +} + +static void DBGHandler(s16 a, OSContext* b) { + *__PIRegs = 0x1000; + if (DBGCallback) { + DBGCallback(a, b); + } +} + +void DBInitComm(u8** a, MTRCallbackType b) { + BOOL interrupts = OSDisableInterrupts(); + { + pEXIInputFlag = (u8*)EXIInputFlag; + pEXIInputFlag = &EXIInputFlag; + + *a = pEXIInputFlag; + + MTRCallback = b; + + DBGEXIInit(); + } + OSRestoreInterrupts(interrupts); +} + +void DBInitInterrupts(void) { + __OSMaskInterrupts(0x18000); + __OSMaskInterrupts(0x40); + DBGCallback = &MWCallback; + __OSSetInterruptHandler(0x19, DBGHandler); + __OSUnmaskInterrupts(0x40); +} + +static void CheckMailBox(void) { + u32 v; + DBGReadStatus(&v); + if (v & 1) { + DBGReadMailbox(&v); + v &= 0x1fffffff; + + if ((v & 0x1f000000) == 0x1f000000) { + SendMailData = v; + RecvDataLeng = v & 0x7fff; + EXIInputFlag = 1; + } + } +} + +u32 DBQueryData(void) { + EXIInputFlag = 0; + if (!RecvDataLeng) { + BOOL interrupts = OSDisableInterrupts(); + CheckMailBox(); + OSRestoreInterrupts(interrupts); + } + return RecvDataLeng; +} + +BOOL DBRead(u32* buffer, s32 count) { + u32 interrupts = OSDisableInterrupts(); + u32 v = SendMailData & 0x10000 ? 0x1000 : 0; + + DBGRead(v + 0x1e000, buffer, ROUND_UP(count, 4)); + + RecvDataLeng = 0; + EXIInputFlag = 0; + + OSRestoreInterrupts(interrupts); + + return 0; +} + +BOOL DBWrite(void* src, u32 size) { + u32 v; + u32 busyFlag; + BOOL interrupts = OSDisableInterrupts(); + + do { + _DBGReadStatus(&busyFlag); + } while (busyFlag & 2); + + SendCount++; + v = ((SendCount & 1) ? 0x1000 : 0); + + while (!DBGWrite(v | 0x1c000, src, ROUND_UP(size, 4))) + ; + + do { + _DBGReadStatus(&busyFlag); + } while (busyFlag & 2); + + v = SendCount; + while (!DBGWriteMailbox((0x1f000000) | v << 0x10 | size)) + ; + + do { + while (!_DBGReadStatus(&busyFlag)) + ; + } while (busyFlag & 2); + + OSRestoreInterrupts(interrupts); + + return 0; +} + +void DBOpen(void) {} + +void DBClose(void) {} diff --git a/src/odenotstub/odenotstub.c b/src/odenotstub/odenotstub.c new file mode 100644 index 000000000..cc633aa50 --- /dev/null +++ b/src/odenotstub/odenotstub.c @@ -0,0 +1,8 @@ +#include "dolphin/types.h" + +// prototypes +DECL_WEAK int Hu_IsStub(); + +DECL_WEAK int Hu_IsStub() { + return 0; +}