diff options
| author | robojumper <robojumper@gmail.com> | 2025-08-20 20:55:56 +0200 |
|---|---|---|
| committer | robojumper <robojumper@gmail.com> | 2025-08-20 20:55:56 +0200 |
| commit | 50c32beaa74ad74efbb4ed8200f81eba63e91557 (patch) | |
| tree | c62fd1fdcd8c9e39ed8185d2e1cd2600dc4fb196 /src | |
| parent | 897de53b2dd1c5a315a995db768b083b0267ff5d (diff) | |
Various exception/assert files
Diffstat (limited to 'src')
| -rw-r--r-- | src/d/d_heap.cpp | 10 | ||||
| -rw-r--r-- | src/nw4r/db/db_exception.cpp | 12 | ||||
| -rw-r--r-- | src/s/s_Assert.cpp | 22 | ||||
| -rw-r--r-- | src/s/s_Crc.cpp | 2 | ||||
| -rw-r--r-- | src/s/s_Print.cpp | 42 | ||||
| -rw-r--r-- | src/toBeSorted/d_exception.cpp | 172 | ||||
| -rw-r--r-- | src/toBeSorted/file_manager.cpp | 2 |
7 files changed, 249 insertions, 13 deletions
diff --git a/src/d/d_heap.cpp b/src/d/d_heap.cpp index e5b926a3..b3441f0d 100644 --- a/src/d/d_heap.cpp +++ b/src/d/d_heap.cpp @@ -1,7 +1,7 @@ #include "d/d_heap.h" #include "d/d_heap_alloc.h" - +#include "s/s_Assert.h" dHeap dHeap::work1Heap; dHeap dHeap::work2Heap; @@ -14,8 +14,7 @@ dHeap dHeap::fontHeap; dHeap dHeap::HBMHeap; dHeapAllocator dHeapAllocator::sAllocator; -extern u8 lbl_80571C58; -extern "C" void fn_802DE710(); +static bool sAssertOnAllocFailure = true; // TODO TU splits? @@ -23,10 +22,10 @@ void dHeapAllocator::onAlloc(EGG::HeapAllocArg *arg) { if (arg->ptr != nullptr) { return; } - if (lbl_80571C58 == 0) { + if (!sAssertOnAllocFailure) { return; } - fn_802DE710(); + sAssert::assert(); } EGG::ExpHeap *dHeap::init(const char *name, size_t size, EGG::Heap *parent) { @@ -75,7 +74,6 @@ void dHeap::createHBMHeap(size_t size, EGG::Heap *parent) { HBMHeap.init(name, size, parent); } -// TODO this doesn't match (many more stack stores) void dHeapAllocator::initCallbacks() { sAllocator.doInitCallbacks(); } diff --git a/src/nw4r/db/db_exception.cpp b/src/nw4r/db/db_exception.cpp index dccba52e..69f1d567 100644 --- a/src/nw4r/db/db_exception.cpp +++ b/src/nw4r/db/db_exception.cpp @@ -4,6 +4,7 @@ #include "nw4r/db/db_mapFile.h" #include "rvl/GX.h" // IWYU pragma: export #include "rvl/VI.h" // IWYU pragma: export +#include "rvl/OS/OSError.h" #include "string.h" @@ -63,12 +64,13 @@ void Exception_Init() { OSCreateThread(&sException.thread, RunThread_, nullptr, sThreadBuffer + 0x4000, 0x4000, 0, 1); OSInitMessageQueue(&sException.queue, sMessageBuffer, 1); OSResumeThread(&sException.thread); - OSSetErrorHandler(2, ErrorHandler_); - OSSetErrorHandler(3, ErrorHandler_); - OSSetErrorHandler(5, ErrorHandler_); - OSSetErrorHandler(15, ErrorHandler_); + // UB: casting non-variadic function to variadic (and letting OS invoke it) + OSSetErrorHandler(OS_ERR_DSI, (OSErrorHandler)ErrorHandler_); + OSSetErrorHandler(OS_ERR_ISI, (OSErrorHandler)ErrorHandler_); + OSSetErrorHandler(OS_ERR_ALIGNMENT, (OSErrorHandler)ErrorHandler_); + OSSetErrorHandler(OS_ERR_PROTECTION, (OSErrorHandler)ErrorHandler_); __OSFpscrEnableBits = 0; - OSSetErrorHandler(16, nullptr); + OSSetErrorHandler(OS_ERR_FP_EXCEPTION, nullptr); } extern "C" u32 PPCMfmsr(); extern "C" void PPCMtmsr(u32); diff --git a/src/s/s_Assert.cpp b/src/s/s_Assert.cpp new file mode 100644 index 00000000..d39925f7 --- /dev/null +++ b/src/s/s_Assert.cpp @@ -0,0 +1,22 @@ +#include "s/s_Assert.h" + +#include "common.h" + +namespace sAssert { + +typedef void (*AssertCallback)(void *); + +AssertCallback sAssertCallback; + +void setAssertCallback(AssertCallback cb) { + sAssertCallback = cb; +} + +void assert() { + if (sAssertCallback != nullptr) { + (sAssertCallback)(nullptr); + } + while (true) {} +} + +} // namespace sAssert diff --git a/src/s/s_Crc.cpp b/src/s/s_Crc.cpp index 7ba034fb..67e0e226 100644 --- a/src/s/s_Crc.cpp +++ b/src/s/s_Crc.cpp @@ -4,7 +4,7 @@ namespace sCrc { -u32 calcCRC(const void *ptr, u32 size) { +u32 calcCRC32(const void *ptr, u32 size) { return OSCalcCRC32(ptr, size); } diff --git a/src/s/s_Print.cpp b/src/s/s_Print.cpp new file mode 100644 index 00000000..3a94b0cc --- /dev/null +++ b/src/s/s_Print.cpp @@ -0,0 +1,42 @@ +#include "s/s_Print.h" + +#include "rvl/OS/OSError.h" + +#include <cstdarg> +#include <cstdio> +#include <stdio.h> + +namespace sLib { + +typedef int (*vprintf_sig)(const char *format, va_list args); + +static vprintf_sig sPrintfFunc = &std::vprintf; + +static vprintf_sig getVprintfFunc() { + return sPrintfFunc; +} + +static void my_vprintf(const char *format, va_list args) { + (getVprintfFunc())(format, args); +} + +void printf(const char *msg, ...) { + va_list l; + va_start(l, msg); + vprintf(msg, l); + va_end(l); +} + +} // namespace sLib + +// Overriding the weakly linked OS functions... +void OSReport(const char *msg, ...) { + va_list l; + va_start(l, msg); + OSVReport(msg, l); + va_end(l); +} + +void OSVReport(const char *msg, va_list args) { + sLib::my_vprintf(msg, args); +} diff --git a/src/toBeSorted/d_exception.cpp b/src/toBeSorted/d_exception.cpp new file mode 100644 index 00000000..f6a4384b --- /dev/null +++ b/src/toBeSorted/d_exception.cpp @@ -0,0 +1,172 @@ +#include "toBeSorted/d_exception.h" + +#include "DynamicLink.h" +#include "common.h" +#include "egg/core/eggController.h" +#include "egg/core/eggHeap.h" +#include "egg/prim/eggAssert.h" +#include "egg/util/eggException.h" +#include "m/m_pad.h" +#include "nw4r/db/db_assert.h" +#include "nw4r/db/db_console.h" +#include "nw4r/db/db_exception.h" +#include "rvl/AI/AI.h" +#include "rvl/KPAD/KPAD.h" +#include "rvl/OS/OSError.h" +#include "rvl/OS/OSInterrupt.h" +#include "rvl/WPAD/WPAD.h" +#include "s/s_Assert.h" +#include "toBeSorted/revision_info.h" + +#include <cstdarg> + +#define D_INFO_BUILD_TYPE "PRD" + +#define D_INFO_COUNTRY "US" +#define D_INFO_GAME_CODE "SOUE" + +#define D_ASSERT_NUM_ERROR_HANDLERS 5 + +static const u8 sErrorCodes[D_ASSERT_NUM_ERROR_HANDLERS] = { + OS_ERR_DSI, OS_ERR_ISI, OS_ERR_ALIGNMENT, OS_ERR_PROTECTION, OS_ERR_FP_EXCEPTION +}; + +static OSErrorHandler sSavedErrorHandlers[D_ASSERT_NUM_ERROR_HANDLERS] = {}; + +static void printGameInfo() { + nw4r::db::ConsoleHandle c = nw4r::db::Exception_GetConsole(); + nw4r::db::Console_Printf(c, " COUNTRY: %s\n", D_INFO_COUNTRY); + nw4r::db::Console_Printf(c, "BUILD_TYPE: %s\n", D_INFO_BUILD_TYPE); + nw4r::db::Console_Printf(c, " GAME_CODE: %s\n", D_INFO_GAME_CODE); + + nw4r::db::Console_Printf(c, "URL_INFO:%s\n", getUrlInfo()); + nw4r::db::Console_Printf(c, "REV_INFO:%s\n", getRevisionInfo()); + nw4r::db::Console_Printf(c, "COPYDATE:%s\n", getCopydate()); +} + +// Copied from EGG::Exception::ExceptionCallback_ +static void waitForButtonSequence(void *data) { + KPADStatus status; + 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); + EGG::Exception::ExceptionWaitTime(50); + if (status.trig) { + // Reset the sequence on wrong button press, advance on right button press + u4 = status.trig & (((u16 *)data)[u4]) ? u4 + 1 : 0; + } + } + } +} + +static void preExceptionCallback() { + WPADControlMotor(0, WPAD_MOTOR_STOP); + AIStopDMA(); + WPADSetAcceptConnection(true); + printGameInfo(); +} + +static void exceptionCallback(EGG::CoreStatus *status) { + if ((status->hold & (mPad::BUTTON_MINUS | mPad::BUTTON_PLUS)) == (mPad::BUTTON_MINUS | mPad::BUTTON_PLUS)) { + // When holding Minus and Plus at the same time, go back to the EGG exception handler + EGG::Exception::SetCallbackMode(true); + EGG::Exception::SetUserCallback(nullptr); + } +} + +static void *sButtonSequencePtr = nullptr; + +static void assertCallback() { + WPADControlMotor(0, WPAD_MOTOR_STOP); + AIStopDMA(); + WPADSetAcceptConnection(true); + waitForButtonSequence(sButtonSequencePtr); + printGameInfo(); +} + +static bool sAsserted = false; +static void sAssertCallback(void *) { + OSDisableInterrupts(); + if (sAsserted) { + OSReport("Recursive assertioned.\n"); + while (true) {} + } + sAsserted = true; + EGG::Assert::assert("PANIC", 0, "PANIC"); +} + +static void mainErrorHandler(u16 error, OSContext *ctx, u32 dsisr, u32 dar) { + for (int i = 0; i < D_ASSERT_NUM_ERROR_HANDLERS; i++) { + if (error == sErrorCodes[i] && sSavedErrorHandlers[i] != nullptr) { + (sSavedErrorHandlers[i])(error, ctx, dsisr, dar); + } + } +} + +static void initErrorHandlers() { + for (int i = 0; i < D_ASSERT_NUM_ERROR_HANDLERS; i++) { + // UB: casting non-variadic function to variadic (and letting OS invoke it) + OSErrorHandler oldHandler = OSSetErrorHandler(sErrorCodes[i], (OSErrorHandler)mainErrorHandler); + if (oldHandler != nullptr) { + sSavedErrorHandlers[i] = oldHandler; + } else { + OSSetErrorHandler(sErrorCodes[i], nullptr); + } + } +} + +// HOME, -, +, -, +, 1, 2, 1, 2, A, same as NSMBW +static const u16 sButtonSequence[] = { + mPad::BUTTON_HOME, + mPad::BUTTON_MINUS, + mPad::BUTTON_PLUS, + mPad::BUTTON_MINUS, + mPad::BUTTON_PLUS, + mPad::BUTTON_1, + mPad::BUTTON_2, + mPad::BUTTON_1, + mPad::BUTTON_2, + mPad::BUTTON_A, + 0, +}; + +void exceptionCreate(EGG::Heap *heap) { + EGG::Exception::create(64, 100, 1, heap, 0); + initErrorHandlers(); + + static DbMapFile mapFile; + mapFile.RegisterOnDvd("maps/RVZELDANP.map", nullptr); + nw4r::db::Exception_SetDisplayInfo(0x20 | 0x10 | 0x8 | 0x4 | 0x2 | 0x1); + nw4r::db::Assertion_SetConsole(EGG::Exception::GetConsoleHandle()); + EGG::Exception::SetCallbackArgs((void *)sButtonSequence); + sButtonSequencePtr = (void *)sButtonSequence; + EGG::Exception::SetPreExceptionCallback(preExceptionCallback); + EGG::Exception::SetUserCallback(exceptionCallback); + EGG::Assert::setAssertCallback(assertCallback); + sAssert::setAssertCallback(sAssertCallback); +} + +// Overriding weakly linked OS function +static bool sPanicked = false; +void OSPanic(const char *file, int line, const char *msg, ...) { + OSDisableInterrupts(); + if (sPanicked) { + OSReport("Recursive assertioned.\n"); + while (true) {} + } + sPanicked = true; + + va_list l; + va_start(l, msg); + EGG::Assert::system_halt(file, line, msg, l); + va_end(l); +} + +// Pooled data +void d_exception_unused() { + OSReport("d_Exception.cpp"); + OSReport("Recursive assertioned."); +} diff --git a/src/toBeSorted/file_manager.cpp b/src/toBeSorted/file_manager.cpp index 3f8fdb5e..19a3a055 100644 --- a/src/toBeSorted/file_manager.cpp +++ b/src/toBeSorted/file_manager.cpp @@ -433,7 +433,7 @@ extern "C" void fn_800C01F0(); // todo flag managers return &mFileB; } /* 80011280 */ u32 FileManager::calcFileCRC(const void *data, u32 length) { - return sCrc::calcCRC(data, length); + return sCrc::calcCRC32(data, length); } /* 80011290 */ void FileManager::updateEmptyFiles() { updateEmptyFileFlags(); |
