summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2025-08-20 20:55:56 +0200
committerrobojumper <robojumper@gmail.com>2025-08-20 20:55:56 +0200
commit50c32beaa74ad74efbb4ed8200f81eba63e91557 (patch)
treec62fd1fdcd8c9e39ed8185d2e1cd2600dc4fb196 /src
parent897de53b2dd1c5a315a995db768b083b0267ff5d (diff)
Various exception/assert files
Diffstat (limited to 'src')
-rw-r--r--src/d/d_heap.cpp10
-rw-r--r--src/nw4r/db/db_exception.cpp12
-rw-r--r--src/s/s_Assert.cpp22
-rw-r--r--src/s/s_Crc.cpp2
-rw-r--r--src/s/s_Print.cpp42
-rw-r--r--src/toBeSorted/d_exception.cpp172
-rw-r--r--src/toBeSorted/file_manager.cpp2
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();