diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index c259bf46..57f88846 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -1481,6 +1481,8 @@ egg/audio/eggAudioSystem.cpp: egg/util/eggException.cpp: .text start:0x804B7550 end:0x804B7B48 + .data start:0x8056F420 end:0x8056F438 + .sbss start:0x80576900 end:0x80576920 Runtime.PPCEABI.H/global_destructor_chain.c: .text start:0x804C65C0 end:0x804C6620 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 40ff5c6b..bd24a3e4 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -26863,14 +26863,14 @@ fn_804B7370 = .text:0x804B7370; // type:function size:0x60 fn_804B73D0 = .text:0x804B73D0; // type:function size:0x78 fn_804B7450 = .text:0x804B7450; // type:function size:0xF4 ExceptionWaitTime__Q23EGG9ExceptionFUl = .text:0x804B7550; // type:function size:0x78 -EGG__Exception__ExceptionCallback = .text:0x804B75D0; // type:function size:0x58 +ExceptionCallback__Q23EGG9ExceptionFPQ44nw4r2db6detail11ConsoleHeadPv = .text:0x804B75D0; // type:function size:0x58 ExceptionCallback___Q23EGG9ExceptionFPQ44nw4r2db6detail11ConsoleHeadPv = .text:0x804B7630; // type:function size:0x214 create__Q23EGG9ExceptionFUsUsUsPQ23EGG4Heapi = .text:0x804B7850; // type:function size:0x98 -EGG__Exception__setCallbackArgs = .text:0x804B78F0; // type:function size:0x54 -EGG__Exception__setPreExceptionCallback = .text:0x804B7950; // type:function size:0x8 -EGG__Exception__SetUserCallback = .text:0x804B7960; // type:function size:0x8 -EGG__Exception__setDisplayInfo = .text:0x804B7970; // type:function size:0x8 -EGG__Exception__getConsoleHandle = .text:0x804B7980; // type:function size:0x8 +SetCallbackArgs__Q23EGG9ExceptionFPv = .text:0x804B78F0; // type:function size:0x54 +SetPreExceptionCallback__Q23EGG9ExceptionFPFv_v = .text:0x804B7950; // type:function size:0x8 +SetUserCallback__Q23EGG9ExceptionFPFPQ23EGG10CoreStatus_v = .text:0x804B7960; // type:function size:0x8 +SetCallbackMode__Q23EGG9ExceptionFb = .text:0x804B7970; // type:function size:0x8 +GetConsoleHandle__Q23EGG9ExceptionFv = .text:0x804B7980; // type:function size:0x8 __dt__Q23EGG9ExceptionFv = .text:0x804B7990; // type:function size:0xA4 __ct__Q23EGG9ExceptionFUsUsUsPQ23EGG4Heapi = .text:0x804B7A40; // type:function size:0x108 fn_804B7B50 = .text:0x804B7B50; // type:function size:0x64 @@ -37220,8 +37220,8 @@ lbl_8056F320 = .data:0x8056F320; // type:object size:0xA8 lbl_8056F3C8 = .data:0x8056F3C8; // type:object size:0x10 lbl_8056F3D8 = .data:0x8056F3D8; // type:object size:0x30 lbl_8056F408 = .data:0x8056F408; // type:object size:0x18 -lbl_8056F420 = .data:0x8056F420; // type:object size:0xC data:string -EGG__Exception__vtable = .data:0x8056F42C; // type:object size:0xC +lbl_8056F420 = .data:0x8056F420; // type:object size:0xC scope:local data:string +__vt__Q23EGG9Exception = .data:0x8056F42C; // type:object size:0xC lbl_8056F438 = .data:0x8056F438; // type:object size:0x14 lbl_8056F44C = .data:0x8056F44C; // type:object size:0x14 lbl_8056F460 = .data:0x8056F460; // type:object size:0x10 @@ -41031,15 +41031,15 @@ AudioHeap_ptr = .sbss:0x805768EC; // type:object size:0x4 data:4byte lbl_805768F0 = .sbss:0x805768F0; // type:object size:0x4 data:4byte lbl_805768F4 = .sbss:0x805768F4; // type:object size:0x4 data:4byte lbl_805768F8 = .sbss:0x805768F8; // type:object size:0x8 data:4byte -EGG__Exception__sException = .sbss:0x80576900; // type:object size:0x4 data:4byte -EGG__Exception__sConsoleHandle = .sbss:0x80576904; // type:object size:0x4 data:4byte -EGG__Exception__sMapFileWorks = .sbss:0x80576908; // type:object size:0x4 data:4byte -EGG__Exception__sMapFileNumMax = .sbss:0x8057690C; // type:object size:0x4 data:4byte -EGG__Exception__sCurrentMapFileNum = .sbss:0x80576910; // type:object size:0x4 data:4byte -EGG__Exception__sPreException = .sbss:0x80576914; // type:object size:0x4 data:4byte -EGG__Exception__sUserCallbackFunc = .sbss:0x80576918; // type:object size:0x4 data:4byte -EGG__Exception__sEnableUserCallback = .sbss:0x8057691C; // type:object size:0x1 data:byte -EGG__Exception__sDisplayInfo = .sbss:0x8057691E; // type:object size:0x2 data:2byte +sException__Q23EGG9Exception = .sbss:0x80576900; // type:object size:0x4 data:4byte +sConsoleHandle__Q23EGG9Exception = .sbss:0x80576904; // type:object size:0x4 data:4byte +sMapFileWorks__Q23EGG9Exception = .sbss:0x80576908; // type:object size:0x4 data:4byte +sMapFileNumMax__Q23EGG9Exception = .sbss:0x8057690C; // type:object size:0x4 data:4byte +sCurrentMapFileNum__Q23EGG9Exception = .sbss:0x80576910; // type:object size:0x4 data:4byte +sPreException__Q23EGG9Exception = .sbss:0x80576914; // type:object size:0x4 data:4byte +sUserCallbackFunc__Q23EGG9Exception = .sbss:0x80576918; // type:object size:0x4 data:4byte +sUserCallbackMode__Q23EGG9Exception = .sbss:0x8057691C; // type:object size:0x1 data:byte +sExceptionDisplayInfo__Q23EGG9Exception = .sbss:0x8057691E; // type:object size:0x2 data:2byte lbl_80576920 = .sbss:0x80576920; // type:object size:0x8 data:float lbl_80576928 = .sbss:0x80576928; // type:object size:0x8 data:4byte __global_destructor_chain = .sbss:0x80576930; // type:object size:0x4 scope:global data:4byte diff --git a/include/egg/core/eggVideo.h b/include/egg/core/eggVideo.h index 00ebf89c..37633ee9 100644 --- a/include/egg/core/eggVideo.h +++ b/include/egg/core/eggVideo.h @@ -7,6 +7,8 @@ #include +extern "C" GXRenderModeObj lbl_8055FC64; + namespace EGG { class Video { @@ -28,6 +30,13 @@ class Video { static u32 getTickPerVRetrace(); static const GXRenderModeObj *getStandardRenderModeObj(const RenderModeObjSet *); + GXRenderModeObj* getCurrentOrFallbackRenderModeObj() const { + if (pRenderMode == nullptr) { + return &lbl_8055FC64; + } + return pRenderMode; + } + public: void setBlack(bool b) { VISetBlack(!mFlag.onBit(0)); diff --git a/include/egg/util/eggException.h b/include/egg/util/eggException.h index c2e21809..3252f35c 100644 --- a/include/egg/util/eggException.h +++ b/include/egg/util/eggException.h @@ -1,6 +1,45 @@ #ifndef EGG_EXCEPTION_H #define EGG_EXCEPTION_H -namespace EGG {} // namespace EGG +#include +#include + +namespace EGG { + +class Heap; +class CoreStatus; + +class Exception { +public: + Exception(u16, u16, u16, EGG::Heap *, int); + virtual ~Exception(); + + static void ExceptionWaitTime(u32 time); + static bool ExceptionCallback(nw4r::db::ConsoleHandle handle, void *); + static bool ExceptionCallback_(nw4r::db::ConsoleHandle handle, void *); + static Exception *create(u16, u16, u16, Heap *, int); + + static Exception *sException; + + volatile static nw4r::db::ConsoleHandle sConsoleHandle; + static void *sMapFileWorks; + static u32 sMapFileNumMax; + static u32 sCurrentMapFileNum; + static volatile bool sUserCallbackMode; + + // inofficial + + static void (*sPreException)(); + static void (*sUserCallbackFunc)(CoreStatus *status); + static s16 sExceptionDisplayInfo; + + static void SetUserCallback(void (*cb)(CoreStatus *status)); + static void SetPreExceptionCallback(void (*cb)()); + static void SetCallbackMode(bool); + static void SetCallbackArgs(void *); + nw4r::db::ConsoleHandle GetConsoleHandle(); +}; + +} // namespace EGG #endif diff --git a/include/nw4r/db/db_console.h b/include/nw4r/db/db_console.h index 01921110..b2d724c6 100644 --- a/include/nw4r/db/db_console.h +++ b/include/nw4r/db/db_console.h @@ -17,7 +17,7 @@ typedef struct ConsoleHead { u16 printTop; u16 printXPos; u16 ringTop; - u32 ringTopLineCnt; + s32 ringTopLineCnt; s32 viewTopLine; s16 viewPosX; s16 viewPosY; @@ -38,15 +38,47 @@ enum ConsoleOutputType { CONSOLE_OUTPUT_ALL = CONSOLE_OUTPUT_DISPLAY | CONSOLE_OUTPUT_TERMINAL, }; +inline s16 Console_GetPositionX(ConsoleHandle console) { + return console->viewPosX; +} + +inline s16 Console_GetPositionY(ConsoleHandle console) { + return console->viewPosY; +} + +inline bool Console_SetVisible(ConsoleHandle handle, bool bVisible) { + bool old = handle->isVisible; + handle->isVisible = bVisible; + return old; +} + +inline void Console_SetPosition(ConsoleHandle handle, s32 x, s32 y) { + handle->viewPosX = x; + handle->viewPosY = y; +} + +inline s32 Console_GetViewBaseLine(ConsoleHandle console) { + return console->viewTopLine; +} + +inline s32 Console_SetViewBaseLine(ConsoleHandle console, s32 line) { + s32 old = console->viewTopLine; + console->viewTopLine = line; + return old; +} + +inline s32 Console_GetBufferHeadLine(ConsoleHandle console) { + return console->ringTopLineCnt; +} + ConsoleHandle Console_Create(void *arg, u16, u16, u16, u16, u16); ConsoleHandle Console_Destroy(ConsoleHandle console); void Console_DrawDirect(ConsoleHandle console); -void Console_VFPrintf(ConsoleOutputType type, ConsoleHandle console, const char* format, va_list vlist); -void Console_Printf(ConsoleHandle console, const char* format, ...); +void Console_VFPrintf(ConsoleOutputType type, ConsoleHandle console, const char *format, va_list vlist); +void Console_Printf(ConsoleHandle console, const char *format, ...); s32 Console_GetTotalLines(ConsoleHandle console); } // namespace db } // namespace nw4r - #endif diff --git a/include/nw4r/db/db_exception.h b/include/nw4r/db/db_exception.h index 34bc646d..9e14e803 100644 --- a/include/nw4r/db/db_exception.h +++ b/include/nw4r/db/db_exception.h @@ -19,6 +19,7 @@ void Exception_Init(); ConsoleHandle Exception_SetConsole(ConsoleHandle, const _GXRenderModeObj *); ConsoleHandle Exception_GetConsole(); void Exception_SetUserCallback(bool (*)(ConsoleHandle, void *), void *); +u16 Exception_SetDisplayInfo(u16 newInfo); } // namespace db } // namespace nw4r diff --git a/include/rvl/KPAD/KPAD.h b/include/rvl/KPAD/KPAD.h index 6eac5f21..87f47832 100644 --- a/include/rvl/KPAD/KPAD.h +++ b/include/rvl/KPAD/KPAD.h @@ -13,6 +13,7 @@ typedef void (*KPADConnectCallback)(s32, s32); // TODO: Create Proper Headers void KPADInitEx(void * /* UNKTYPE */, u32); +s32 KPADRead(s32 chan, UNKTYPE *status, s32); s32 KPADReadEx(s32 chan, UNKTYPE *status, s32, s32 *); void KPADSetConnectCallback(u32, KPADConnectCallback); diff --git a/src/egg/util/eggException.cpp b/src/egg/util/eggException.cpp index 65bab2ae..2b4ea036 100644 --- a/src/egg/util/eggException.cpp +++ b/src/egg/util/eggException.cpp @@ -1 +1,194 @@ +#include +#include +#include +#include #include +#include +#include +#include +#include +#include + +namespace EGG { + +Exception *Exception::sException; +volatile nw4r::db::ConsoleHandle Exception::sConsoleHandle; +void *Exception::sMapFileWorks; +u32 Exception::sMapFileNumMax; +u32 Exception::sCurrentMapFileNum; +void (*Exception::sPreException)(); +void (*Exception::sUserCallbackFunc)(CoreStatus *status); +volatile bool Exception::sUserCallbackMode; +s16 Exception::sExceptionDisplayInfo; + +void Exception::ExceptionWaitTime(u32 time) { + u32 tick = OSGetTick(); + u32 tick2; + do { + tick2 = OSGetTick(); + } while ((tick2 - tick) / (OS_BUS_CLOCK_SPEED / 4 / 1000) < time); +} + +bool Exception::ExceptionCallback(nw4r::db::ConsoleHandle handle, void *data) { + if (sPreException != nullptr) { + (*sPreException)(); + } + nw4r::db::Exception_SetDisplayInfo(sExceptionDisplayInfo); + nw4r::db::Exception_SetUserCallback(ExceptionCallback_, data); + return true; +} + +bool Exception::ExceptionCallback_(nw4r::db::ConsoleHandle console, void *data) { + EGG::CoreStatus status; + if (console == nullptr) { + OSReport("No Console\n"); + return 0; + } + OSEnableInterrupts(); + if (data != nullptr) { + // Require a specific button sequence to show the exception handler + int u4 = 0; + while (((u16 *)data)[u4] != 0) { + KPADRead(0, &status, 1); + ExceptionWaitTime(50); + if (status.mTrig) { + // Reset the sequence on wrong button press, advance on right button press + u4 = status.mTrig & (((u16 *)data)[u4]) ? u4 + 1 : 0; + } + } + } + int line, start, end; + start = nw4r::db::Console_GetBufferHeadLine(console); + line = start; + nw4r::db::Console_SetVisible(console, true); + end = nw4r::db::Console_GetTotalLines(console); + for (; line < end; line++) { + nw4r::db::Console_SetViewBaseLine(console, line); + nw4r::db::Console_DrawDirect(console); + ExceptionWaitTime(250); + } + + int prevY, newY; + int newX, prevX; + + newY = start; + + nw4r::db::Console_SetViewBaseLine(console, start); + nw4r::db::Console_DrawDirect(console); + while (true) { + KPADRead(0, &status, 1); + ExceptionWaitTime(100); + if (status.mTrig & (/* HOME */ 0x8000)) { + sUserCallbackMode = !sUserCallbackMode; + } + if (sUserCallbackMode && sUserCallbackFunc != nullptr) { + (*sUserCallbackFunc)(&status); + continue; + } + + prevX = newX = nw4r::db::Console_GetPositionX(console); + ; + prevY = newY; + + if (status.mHold & (/* DPAD_DOWN */ 0x4)) { + newY += 1; + if (newY > end) { + newY = end; + } + } else if (status.mHold & (/* DPAD_UP */ 0x8)) { + newY -= 1; + if (newY < start) { + newY = start; + } + } else if (status.mHold & (/* DPAD_RIGHT */ 0x2)) { + newX -= 5; + if (newX < -150) { + newX = -150; + } + } else if (status.mHold & (/* DPAD_LEFT */ 0x1)) { + newX += 5; + if (newX > 10) { + newX = 10; + } + } + + if (newY != prevY || newX != prevX) { + nw4r::db::Console_SetPosition(console, newX, nw4r::db::Console_GetPositionY(console)); + nw4r::db::Console_SetViewBaseLine(console, newY); + nw4r::db::Console_DrawDirect(console); + } + } +} + +Exception *Exception::create(u16 width, u16 height, u16 attr, EGG::Heap *heap, int mapFileNum) { + if (sException == nullptr) { + nw4r::db::Exception_Init(); + nw4r::db::DirectPrint_Init(); + if (heap == nullptr) { + heap = Heap::sCurrentHeap; + } + sException = new (heap) Exception(width, height, attr, heap, mapFileNum); + } + + return sException; +} +void Exception::SetCallbackArgs(void *data) { + nw4r::db::Exception_SetUserCallback(ExceptionCallback_, data); + nw4r::db::Exception_SetUserCallback(ExceptionCallback, data); + sExceptionDisplayInfo = nw4r::db::Exception_SetDisplayInfo(0); +} + +void Exception::SetPreExceptionCallback(void (*cb)()) { + sPreException = cb; +} + +void Exception::SetUserCallback(void (*cb)(CoreStatus *status)) { + sUserCallbackFunc = cb; +} + +void Exception::SetCallbackMode(bool arg) { + sUserCallbackMode = arg; +} + +nw4r::db::ConsoleHandle Exception::GetConsoleHandle() { + return sConsoleHandle; +} + +Exception::~Exception() { + nw4r::db::ConsoleHandle h = sConsoleHandle; + if (h != nullptr) { + nw4r::db::ConsoleHandle handle = nw4r::db::Console_Destroy(h); + Heap::free(handle, nullptr); + sConsoleHandle = nullptr; + } + nw4r::db::MapFile_UnregistAll(); + if (sMapFileWorks != nullptr) { + Heap::free(sMapFileWorks, nullptr); + sMapFileWorks = nullptr; + sMapFileNumMax = 0; + sCurrentMapFileNum = 0; + } +} + +Exception::Exception(u16 width, u16 height, u16 attr, EGG::Heap *heap, int mapFileNum) { + void *data = Heap::alloc((width + 1) * height + 0x2C, 4, heap); + nw4r::db::ConsoleHandle handle = nw4r::db::Console_Create(data, width, height, 18, 0, attr); + sConsoleHandle = handle; + if (handle == nullptr) { + return; + } + + GXRenderModeObj *o = EGG::BaseSystem::getVideo()->getCurrentOrFallbackRenderModeObj(); + nw4r::db::Exception_SetConsole(sConsoleHandle, o); + + nw4r::db::Console_SetPosition(sConsoleHandle, 0, 30); + nw4r::db::Console_SetVisible(sConsoleHandle, false); + + sMapFileNumMax = mapFileNum; + size_t size = mapFileNum * 0x14; + sCurrentMapFileNum = 0; + sMapFileWorks = Heap::alloc(size, 4, heap); + SetCallbackArgs(nullptr); +} + +} // namespace EGG diff --git a/src/nw4r/db/db_exception.cpp b/src/nw4r/db/db_exception.cpp index 6485f0a3..c26370e1 100644 --- a/src/nw4r/db/db_exception.cpp +++ b/src/nw4r/db/db_exception.cpp @@ -125,9 +125,6 @@ void *RunThread_(void *) { static void PrintContext_(u16, const OSContext *, u32, u32); static void WaitTime_(s32 time); -static void Console_SetVisible(ConsoleHandle, bool); -static void Console_SetViewBaseLine(ConsoleHandle, s32); -static u32 Console_GetBufferHeadLine(ConsoleHandle); static void DrawConsoleEndless_(ConsoleHandle console) { s32 lineCnt = Console_GetBufferHeadLine(console); @@ -476,17 +473,6 @@ void DrawConsoleEndless_(detail::ConsoleHead *) { // TODO } */ -static void Console_SetVisible(detail::ConsoleHead *, bool) { - // TODO -} - -static void Console_SetViewBaseLine(detail::ConsoleHead *console, s32 line) { - console->viewTopLine = line; -} - -static u32 Console_GetBufferHeadLine(detail::ConsoleHead *console) { - return console->ringTopLineCnt; -} } // namespace db } // namespace nw4r