Files
ss/src/egg/prim/eggAssert.cpp
T
2025-09-16 22:32:07 -04:00

195 lines
5.1 KiB
C++

#include "egg/prim/eggAssert.h"
#include "__va_arg.h"
#include "egg/core/eggSystem.h"
#include "egg/core/eggXfbManager.h"
#include "nw4r/db/db_directPrint.h"
#include "nw4r/db/db_mapFile.h"
#include "string.h"
#include "rvl/OS.h" // IWYU pragma: export
#include "rvl/VI.h" // IWYU pragma: export
namespace EGG {
namespace Assert {
AssertCallback sAssertCallback;
AssertCallback sAssertCallback2;
u32 sPtrOverride;
bool sInstantHalt;
bool sAssertOccurred;
void wait(u32 time) {
u32 tick = OSGetTick();
u32 tick2;
do {
tick2 = OSGetTick();
} while ((tick2 - tick) / (OS_BUS_CLOCK_SPEED / 4 / 1000) < time);
}
void system_vreport(const char *str, va_list list) {
OSVReport(str, list);
}
void system_report(const char *str, ...) {
va_list l;
va_start(l, str);
system_vreport(str, l);
va_end(l);
}
s32 getPeriodPos(const char *str) {
char *b = strchr(str, '.');
s32 len;
if (b == nullptr) {
len = strlen(str);
} else {
len = b - str;
}
if (len > 0xff) {
return 0xff;
}
return len;
}
char buf[260];
const char *getMapSymbol(void *arg) {
bool success = nw4r::db::MapFile_QuerySymbol((u32)arg, (u8 *)buf, sizeof(buf));
return success ? buf : nullptr;
}
bool isOutsideMEM1(u32 addr) {
if (!(0x80000000 <= addr) || !(addr <= 0x83000000 - 1)) {
return true;
}
return false;
}
AssertCallback setAssertCallback(AssertCallback cb) {
AssertCallback old = sAssertCallback;
sAssertCallback = cb;
return old;
}
void system_halt(const char *file, u32 line, const char *msg, va_list list) {
if (sAssertOccurred) {
#line 152
OSError("Recursive assertioned");
}
sAssertOccurred = true;
if (sAssertCallback != nullptr) {
sAssertCallback();
}
VISetPreRetraceCallback(nullptr);
VISetPostRetraceCallback(nullptr);
system_report("\n---------- HALT -------------\n");
s32 pos = getPeriodPos(file);
system_report("%.*s(%d):", pos, file, line);
va_list args;
va_copy(args, list);
system_vreport(msg, args);
system_report("\n");
u32 *stackp = (u32 *)OSGetStackPointer();
if (sPtrOverride != 0) {
stackp = (u32 *)((u32 *)sPtrOverride)[1];
}
u32 *stack = stackp;
s32 num = 0;
for (s32 num = 0; num < 0x1e; num++) {
if (isOutsideMEM1((u32)stack)) {
break;
}
const char *sym = getMapSymbol((void *)stack[1]);
if (sym != nullptr) {
system_report("%d: %s\n", num, sym);
} else {
system_report("%d: %p\n", num, stack[1]);
}
stack = (u32 *)stack[0];
if (isOutsideMEM1((u32)stack)) {
break;
}
}
if (sInstantHalt == 0) {
VISetBlack(false);
VIFlush();
nw4r::db::DirectPrint_Init();
nw4r::db::detail::DirectPrint_SetupFB(0);
Xfb *fb = BaseSystem::mConfigData->getXfbMgr()->mToShowXfb;
if (fb == nullptr) {
fb = BaseSystem::mConfigData->getXfbMgr()->mNextXfb;
}
if (fb == nullptr) {
#line 239
OSError("Program Halt");
}
// Random float conversion here for no reason
f32 wid = fb->mWidth;
nw4r::db::DirectPrint_EraseXfb(0, 0, fb->mWidth, fb->mHeight);
nw4r::db::DirectPrint_StoreCache();
OSDisableInterrupts();
OSDisableScheduler();
OSEnableInterrupts();
while (true) {
nw4r::db::DirectPrint_EraseXfb(0, 0, fb->mWidth, fb->mHeight);
nw4r::db::DirectPrint_StoreCache();
nw4r::db::DirectPrint_Printf(2, 2, "%.*s:%d", pos, file, line);
va_list args;
va_copy(args, list);
nw4r::db::DirectPrint_printfsub(2, 0xe, msg, args);
nw4r::db::DirectPrint_StoreCache();
s32 line;
u32 *stack = stackp;
s32 counter;
for (counter = 0, line = 0x1a; counter < 0x10; counter++) {
if (isOutsideMEM1((u32)stack)) {
break;
}
const char *sym = getMapSymbol((void *)stack[1]);
if (sym != nullptr) {
nw4r::db::DirectPrint_Printf(2, line, "%d:%s\n", counter, sym);
} else {
nw4r::db::DirectPrint_Printf(2, line, "LR Save[%d]:%p\n", counter, (void *)stack[1]);
}
nw4r::db::DirectPrint_StoreCache();
stack = (u32 *)*stack;
if (isOutsideMEM1((u32)stack)) {
break;
}
line += 0xc;
}
nw4r::db::DirectPrint_StoreCache();
wait(4000);
if (sAssertCallback2 == nullptr) {
goto end;
}
nw4r::db::DirectPrint_EraseXfb(0, 0, fb->mWidth, fb->mHeight);
(sAssertCallback2)();
nw4r::db::DirectPrint_StoreCache();
wait(4000);
}
}
end:
#line 315
OSError("Program Halt");
return;
}
void assert(const char *file, u32 line, const char *msg, ...) {
va_list l;
va_start(l, msg);
system_halt(file, line, msg, l);
va_end(l);
}
} // namespace Assert
} // namespace EGG