diff options
| author | Jcw87 <Jcw87@users.noreply.github.com> | 2023-09-20 21:07:19 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-20 21:07:19 -0700 |
| commit | 12ddfa5d0023df3a72c640370aa626ddf1ceafe6 (patch) | |
| tree | ec936bc26a7da9119c74262ec3ca39de19cadb5e /src/JSystem/JUtility/JUTException.cpp | |
| parent | b2fc1d2683958a772da702d74bbbfd8e4a1d514c (diff) | |
JUTAssert, JUTConsole, JUTException (#63)
* JUTAssert
* JUTConsole
* JUTException
Diffstat (limited to 'src/JSystem/JUtility/JUTException.cpp')
| -rw-r--r-- | src/JSystem/JUtility/JUTException.cpp | 979 |
1 files changed, 916 insertions, 63 deletions
diff --git a/src/JSystem/JUtility/JUTException.cpp b/src/JSystem/JUtility/JUTException.cpp index 7e113e68..b32a961b 100644 --- a/src/JSystem/JUtility/JUTException.cpp +++ b/src/JSystem/JUtility/JUTException.cpp @@ -4,154 +4,1007 @@ // #include "JSystem/JUtility/JUTException.h" -#include "dolphin/types.h" +#include "JSystem/JUtility/JUTConsole.h" +#include "JSystem/JUtility/JUTDirectFile.h" +#include "JSystem/JUtility/JUTDirectPrint.h" +#include "MSL_C/math.h" +#include "MSL_C/stdio.h" +#include "MSL_C/stdlib.h" +#include "dolphin/base/PPCArch.h" +#include "dolphin/gx/GX.h" +#include "dolphin/os/OS.h" +#include "dolphin/vi/vi.h" + +struct CallbackObject { + /* 0x00 */ OSErrorHandler callback; + /* 0x04 */ u16 error; + /* 0x06 */ u16 pad_0x06; + /* 0x08 */ OSContext* context; + /* 0x0C */ int param_3; + /* 0x10 */ int param_4; +}; + +void search_name_part(u8*, u8*, int); + +OSMessageQueue JUTException::sMessageQueue = {}; +static OSTime c3bcnt[4] = {0, 0, 0, 0}; +const char* JUTException::sCpuExpName[] = { + "SYSTEM RESET", + "MACHINE CHECK", + "DSI", + "ISI", + "EXTERNAL INTERRUPT", + "ALIGNMENT", + "PROGRAM", + "FLOATING POINT", + "DECREMENTER", + "SYSTEM CALL", + "TRACE", + "PERFORMACE MONITOR", + "BREAK POINT", + "SYSTEM INTERRUPT", + "THERMAL INTERRUPT", + "PROTECTION", + "FLOATING POINT", +}; +JUTException* JUTException::sErrorManager; +OSErrorHandler JUTException::sPreUserCallback; +OSErrorHandler JUTException::sPostUserCallback; /* 802C4AC8-802C4BAC .text __ct__12JUTExceptionFP14JUTDirectPrint */ -JUTException::JUTException(JUTDirectPrint*) { - /* Nonmatching */ +JUTException::JUTException(JUTDirectPrint* directPrint) : JKRThread(0x4000, 0x10, 0) { + mDirectPrint = directPrint; + OSSetErrorHandler(EXCEPTION_DSI, errorHandler); + OSSetErrorHandler(EXCEPTION_ISI, errorHandler); + OSSetErrorHandler(EXCEPTION_PROGRAM, errorHandler); + OSSetErrorHandler(EXCEPTION_ALIGNMENT, errorHandler); + OSSetErrorHandler(EXCEPTION_MEMORY_PROTECTION, errorHandler); + setFPException(0); + + sPreUserCallback = NULL; + sPostUserCallback = NULL; + + setGamePad(NULL); + + this->mPrintWaitTime0 = 10; + this->mPrintWaitTime1 = 10; + this->mTraceSuppress = -1; + this->field_0x98 = 0; + this->mPrintFlags = + JUT_PRINT_GPR | JUT_PRINT_GPR_MAP | JUT_PRINT_SRR0_MAP | JUT_PRINT_FLOAT | JUT_PRINT_STACK; } /* 802C4BAC-802C4C14 .text create__12JUTExceptionFP14JUTDirectPrint */ -void JUTException::create(JUTDirectPrint*) { - /* Nonmatching */ +JUTException* JUTException::create(JUTDirectPrint* directPrint) { + if (!sErrorManager) { + JKRHeap* systemHeap = JKRGetSystemHeap(); + sErrorManager = new (systemHeap, 0) JUTException(directPrint); + sErrorManager->resume(); + } + + return sErrorManager; } +OSMessage JUTException::sMessageBuffer[1] = {0}; + /* 802C4C14-802C4CEC .text run__12JUTExceptionFv */ -void JUTException::run() { - /* Nonmatching */ +void* JUTException::run() { + PPCMtmsr(PPCMfmsr() & ~0x0900); + OSInitMessageQueue(&sMessageQueue, sMessageBuffer, 1); + OSMessage message; + while (true) { + OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK); + CallbackObject* cb = (CallbackObject*)message; + OSErrorHandler callback = cb->callback; + u16 error = cb->error; + OSContext* context = cb->context; + int r24 = cb->param_3; + int r23 = cb->param_4; + mFrameMemory = (JUTExternalFB*)sErrorManager->mDirectPrint->getFrameBuffer(); + if (!sErrorManager->mDirectPrint->getFrameBuffer()) { + sErrorManager->createFB(); + } + if (callback) { + callback(error, context, r24, r23); + } + OSDisableInterrupts(); + sErrorManager->printContext(error, context, r24, r23); + } } +static CallbackObject exCallbackObject; +void* JUTException::sConsoleBuffer; +u32 JUTException::sConsoleBufferSize; +JUTConsole* JUTException::sConsole; +u32 JUTException::msr; +u32 JUTException::fpscr; + /* 802C4CEC-802C5084 .text errorHandler__12JUTExceptionFUsP9OSContextUlUl */ -void JUTException::errorHandler(unsigned short, OSContext*, unsigned long, unsigned long) { +void JUTException::errorHandler(OSError error, OSContext* context, u32 param_3, u32 param_4) { /* Nonmatching */ + if (error == 0x10) { + OSReport("\x1b[41;37m"); + OSReport(" FPE: 浮動小数点例外が発生しました。アドレスは %08x fpscr=%08x\n", context->srr0, context->fpscr); + u8 stack_38[0x20]; + u32 stack_3c; + u32 stack_40; + u32 stack_44; + u32 stack_48; + if (searchPartialModule(context->srr0, &stack_40, &stack_44, &stack_48, &stack_3c) == 1) { + search_name_part((u8*)stack_3c, stack_38, 0x20); + OSReport("%s:%x section:%d\n", stack_38, stack_48, stack_44); + } + u32 r31 = context->fpscr; + r31 &= ((context->fpscr & 0xf8) << 22) | 0x01f80700; + if (r31 & 0x20000000) { + context->fpscr &= ~0x80; + OSReport(" FPE: Invalid operation(無効な演算)\n"); + if (fpscr & 0x01000000) { + OSReport(" SNaN\n"); + } + if (fpscr & 0x00800000) { + OSReport(" Infinity - Infinity\n"); + } + if (fpscr & 0x00400000) { + OSReport(" Infinity / Infinity\n"); + } + if (fpscr & 0x00200000) { + OSReport(" 0 / 0\n"); + } + if (fpscr & 0x00100000) { + OSReport(" Infinity * 0\n"); + } + if (fpscr & 0x00080000) { + OSReport(" Invalid compare\n"); + } + if (fpscr & 0x0400) { + OSReport(" Software request\n"); + } + if (fpscr & 0x0200) { + OSReport(" Invalid square root\n"); + } + if (fpscr & 0x0100) { + OSReport(" Invalid integer convert\n"); + } + } + if (r31 & 0x10000000) { + context->fpscr &= ~0x40; + OSReport(" FPE: Overflow(オーバーフロー)\n"); + } + if (r31 & 0x08000000) { + context->fpscr &= ~0x20; + OSReport(" FPE: Underflow(アンダーフロー)\n"); + } + if (r31 & 0x04000000) { + context->fpscr &= ~0x10; + OSReport(" FPE: Zero division(0による割り算)\n"); + } + if (r31 & 0x02000000) { + context->fpscr &= ~0x08; + OSReport(" FPE: Inexact result(不正確な結果)\n"); + } + OSReport("\x1b[m"); + return; + } + + msr = PPCMfmsr(); + fpscr = context->fpscr; + OSFillFPUContext(context); + OSSetErrorHandler(error, NULL); + if (error == OS_ERROR_MEMORY_PROTECTION) { + OSProtectRange(0, NULL, 0, 3); + OSProtectRange(1, NULL, 0, 3); + OSProtectRange(2, NULL, 0, 3); + OSProtectRange(3, NULL, 0, 3); + } + + exCallbackObject.callback = sPreUserCallback; + exCallbackObject.error = error; + exCallbackObject.context = context; + exCallbackObject.param_3 = param_3; + exCallbackObject.param_4 = param_4; + + OSSendMessage(&sMessageQueue, &exCallbackObject, OS_MESSAGE_BLOCK); + OSEnableScheduler(); + OSYieldThread(); } /* 802C5084-802C50CC .text setFPException__12JUTExceptionFUl */ -void JUTException::setFPException(unsigned long) { - /* Nonmatching */ +void JUTException::setFPException(u32 fpscr_enable_bits) { + __OSFpscrEnableBits = fpscr_enable_bits; + if (fpscr_enable_bits) { + OSSetErrorHandler(EXCEPTION_FLOATING_POINT_EXCEPTION, errorHandler); + } else { + OSSetErrorHandler(EXCEPTION_FLOATING_POINT_EXCEPTION, NULL); + } } /* 802C50CC-802C525C .text showFloatSub__12JUTExceptionFif */ -void JUTException::showFloatSub(int, float) { - /* Nonmatching */ +void JUTException::showFloatSub(int index, f32 value) { + if (fpclassify(value) == FP_NAN) { + sConsole->print_f("F%02d: Nan ", index); + } else if (fpclassify(value) == FP_INFINITE) { + if (signbit(value)) { + sConsole->print_f("F%02d:+Inf ", index); + } else { + sConsole->print_f("F%02d:-Inf ", index); + } + } else if (value == 0.0f) { + sConsole->print_f("F%02d: 0.0 ", index); + } else { + sConsole->print_f("F%02d:%+.3E", index, value); + } } /* 802C525C-802C5380 .text showFloat__12JUTExceptionFP9OSContext */ -void JUTException::showFloat(OSContext*) { - /* Nonmatching */ +void JUTException::showFloat(OSContext* context) { + if (!sConsole) { + return; + } + + sConsole->print("-------------------------------- FPR\n"); + for (int i = 0; i < 10; i++) { + showFloatSub(i, context->fpr[i]); + sConsole->print(" "); + showFloatSub(i + 11, context->fpr[i + 11]); + sConsole->print(" "); + showFloatSub(i + 22, context->fpr[i + 22]); + sConsole->print("\n"); + } + showFloatSub(10, context->fpr[10]); + sConsole->print(" "); + showFloatSub(21, context->fpr[21]); + sConsole->print("\n"); } /* 802C5380-802C5440 .text searchPartialModule__12JUTExceptionFUlPUlPUlPUlPUl */ -void JUTException::searchPartialModule(unsigned long, unsigned long*, unsigned long*, unsigned long*, unsigned long*) { - /* Nonmatching */ +bool JUTException::searchPartialModule(u32 address, u32* module_id, u32* section_id, u32* section_offset, u32* name_offset) { + if (!address) { + return false; + } + + OSModuleInfo* module = *(OSModuleInfo**)0x800030C8; + while (module) { + OSSectionInfo* section = (OSSectionInfo*)module->info.sectionInfoOffset; + for (u32 i = 0; i < module->mNumSections; section = section + 1, i++) { + if (section->mSize) { + u32 addr = ALIGN_PREV(section->mOffset, 2); + if ((addr <= address) && (address < addr + section->mSize)) { + if (module_id) + *module_id = module->mId; + if (section_id) + *section_id = i; + if (section_offset) + *section_offset = address - addr; + if (name_offset) + *name_offset = module->mModuleNameOffset; + return true; + } + } + } + + module = (OSModuleInfo*)module->mNext; + } + + return false; } /* 802C5440-802C54B8 .text search_name_part__FPUcPUci */ -void search_name_part(unsigned char*, unsigned char*, int) { - /* Nonmatching */ +void search_name_part(u8* src, u8* dst, int dst_length) { + for (u8* p = src; *p; p++) { + if (*p == '\\') { + src = p; + } + } + + if (*src == '\\') { + src++; + } + + for (int i = 0; (*src != 0) && (i < dst_length);) { + if (*src == '.') + break; + *dst++ = *src++; + i++; + } + + *dst = '\0'; } /* 802C54B8-802C55BC .text showStack__12JUTExceptionFP9OSContext */ -void JUTException::showStack(OSContext*) { - /* Nonmatching */ +void JUTException::showStack(OSContext* context) { + if (!sConsole) { + return; + } + + u32 i; + u32* stackPointer; + sConsole->print("-------------------------------- TRACE\n"); + sConsole->print_f("Address: BackChain LR save\n"); + + for (i = 0, stackPointer = (u32*)context->gpr[1]; (stackPointer != NULL) && (stackPointer != (u32*)0xFFFFFFFF) && (i++ < 0x10);) { + if (i > mTraceSuppress) { + sConsole->print("Suppress trace.\n"); + return; + } + + sConsole->print_f("%08X: %08X %08X\n", stackPointer, stackPointer[0], stackPointer[1]); + showMapInfo_subroutine(stackPointer[1], false); + JUTConsoleManager* manager = JUTConsoleManager::sManager; + manager->drawDirect(true); + waitTime(mPrintWaitTime1); + stackPointer = (u32*)stackPointer[0]; + } } /* 802C55BC-802C586C .text showMainInfo__12JUTExceptionFUsP9OSContextUlUl */ -void JUTException::showMainInfo(unsigned short, OSContext*, unsigned long, unsigned long) { - /* Nonmatching */ +void JUTException::showMainInfo(u16 error, OSContext* context, u32 dsisr, u32 dar) { + if (!sConsole) { + return; + } + + sConsole->print_f("CONTEXT:%08XH (%s EXCEPTION)\n", context, sCpuExpName[error]); + + if (error == OS_ERROR_FLOATING_POINT_EXCEPTION) { + u32 flags = fpscr & (((fpscr & 0xf8) << 0x16) | 0x1f80700); + if ((flags & 0x20000000) != 0) { + sConsole->print_f(" FPE: Invalid operation\n"); + if ((fpscr & 0x1000000) != 0) { + sConsole->print_f(" SNaN\n"); + } + if ((fpscr & 0x800000) != 0) { + sConsole->print_f(" Infinity - Infinity\n"); + } + if ((fpscr & 0x400000) != 0) { + sConsole->print_f(" Infinity / Infinity\n"); + } + if ((fpscr & 0x200000) != 0) { + sConsole->print_f(" 0 / 0\n"); + } + if ((fpscr & 0x100000) != 0) { + sConsole->print_f(" Infinity * 0\n"); + } + if ((fpscr & 0x80000) != 0) { + sConsole->print_f(" Invalid compare\n"); + } + if ((fpscr & 0x400) != 0) { + sConsole->print_f(" Software request\n"); + } + if ((fpscr & 0x200) != 0) { + sConsole->print_f(" Invalid square root\n"); + } + if ((fpscr & 0x100) != 0) { + sConsole->print_f(" Invalid integer convert\n"); + } + } + if ((flags & 0x10000000) != 0) { + sConsole->print_f(" FPE: Overflow\n"); + } + if ((flags & 0x8000000) != 0) { + sConsole->print_f(" FPE: Underflow\n"); + } + if ((flags & 0x4000000) != 0) { + sConsole->print_f(" FPE: Zero division\n"); + } + if ((flags & 0x2000000) != 0) { + sConsole->print_f(" FPE: Inexact result\n"); + } + } + sConsole->print_f("SRR0: %08XH SRR1:%08XH\n", context->srr0, context->srr1); + sConsole->print_f("DSISR: %08XH DAR: %08XH\n", dsisr, dar); } /* 802C586C-802C592C .text showGPR__12JUTExceptionFP9OSContext */ -void JUTException::showGPR(OSContext*) { - /* Nonmatching */ +void JUTException::showGPR(OSContext* context) { + if (!sConsole) { + return; + } + + sConsole->print("-------------------------------- GPR\n"); + for (int i = 0; i < 10; i++) { + sConsole->print_f("R%02d:%08XH R%02d:%08XH R%02d:%08XH\n", i, context->gpr[i], i + 11, + context->gpr[i + 11], i + 22, context->gpr[i + 22]); + } + sConsole->print_f("R%02d:%08XH R%02d:%08XH\n", 10, context->gpr[10], 21, context->gpr[21]); } +JSUList<JUTException::JUTExMapFile> JUTException::sMapFileList(false); + /* 802C592C-802C5A88 .text showMapInfo_subroutine__12JUTExceptionFUlb */ -void JUTException::showMapInfo_subroutine(unsigned long, bool) { - /* Nonmatching */ +bool JUTException::showMapInfo_subroutine(u32 address, bool begin_with_newline) { + if ((address < 0x80000000) || (0x82ffffff < address)) { + return false; + } + + u32 name_offset; + u32 module_id; + u32 section_id; + u32 section_offset; + u8 name_part[36]; + + const char* new_line = "\n"; + if (begin_with_newline == false) { + new_line = ""; + } + + bool result = + searchPartialModule(address, &module_id, §ion_id, §ion_offset, &name_offset); + if (result == true) { + search_name_part((u8*)name_offset, name_part, 32); + sConsole->print_f("%s %s:%x section:%d\n", new_line, name_part, section_offset, section_id); + begin_with_newline = false; + } + + JSUListIterator<JUTException::JUTExMapFile> last = sMapFileList.getEnd(); + JSUListIterator<JUTException::JUTExMapFile> first = sMapFileList.getFirst(); + if (first != last) { + u32 out_addr; + u32 out_size; + char out_line[256]; + + if (result == true) { + result = + queryMapAddress((char*)name_part, section_offset, section_id, &out_addr, &out_size, + out_line, ARRAY_SIZE(out_line), true, begin_with_newline); + } else { + result = queryMapAddress(NULL, address, -1, &out_addr, &out_size, out_line, + ARRAY_SIZE(out_line), true, begin_with_newline); + } + + if (result == true) { + return true; + } + } + + return false; } /* 802C5A88-802C5B94 .text showGPRMap__12JUTExceptionFP9OSContext */ -void JUTException::showGPRMap(OSContext*) { - /* Nonmatching */ +void JUTException::showGPRMap(OSContext* context) { + if (!sConsole) { + return; + } + + bool found_address_register = false; + sConsole->print("-------------------------------- GPRMAP\n"); + + for (int i = 0; i < 31; i++) { + u32 address = context->gpr[i]; + + if (address >= 0x80000000 && 0x83000000 - 1 >= address) { + found_address_register = true; + + sConsole->print_f("R%02d: %08XH", i, address); + if (!showMapInfo_subroutine(address, true)) { + sConsole->print(" no information\n"); + } + JUTConsoleManager::sManager->drawDirect(true); + waitTime(mPrintWaitTime1); + } + } + + if (!found_address_register) { + sConsole->print(" no register which seem to address.\n"); + } } /* 802C5B94-802C5C58 .text showSRR0Map__12JUTExceptionFP9OSContext */ -void JUTException::showSRR0Map(OSContext*) { - /* Nonmatching */ +void JUTException::showSRR0Map(OSContext* context) { + if (!sConsole) { + return; + } + + sConsole->print("-------------------------------- SRR0MAP\n"); + u32 address = context->srr0; + if (address >= 0x80000000 && 0x83000000 - 1 >= address) { + sConsole->print_f("SRR0: %08XH", address); + if (showMapInfo_subroutine(address, true) == false) { + sConsole->print(" no information\n"); + } + JUTConsoleManager::getManager()->drawDirect(true); + } } /* 802C5C58-802C5D00 .text printDebugInfo__12JUTExceptionFQ212JUTException9EInfoPageUsP9OSContextUlUl */ -void JUTException::printDebugInfo(JUTException::EInfoPage, unsigned short, OSContext*, unsigned long, unsigned long) { - /* Nonmatching */ +void JUTException::printDebugInfo(JUTException::EInfoPage page, OSError error, OSContext* context, u32 param_3, u32 param_4) { + switch (page) { + case EINFO_PAGE_GPR: + return showGPR(context); + case EINFO_PAGE_FLOAT: + showFloat(context); + if (sConsole) { + sConsole->print_f(" MSR:%08XH\t FPSCR:%08XH\n", msr, fpscr); + } + break; + case EINFO_PAGE_STACK: + return showStack(context); + case EINFO_PAGE_GPR_MAP: + return showGPRMap(context); + case EINFO_PAGE_SSR0_MAP: + return showSRR0Map(context); + } } /* 802C5D00-802C5D3C .text isEnablePad__12JUTExceptionCFv */ -void JUTException::isEnablePad() const { - /* Nonmatching */ +bool JUTException::isEnablePad() const { + if (mGamePad == (JUTGamePad*)0xFFFFFFFF) + return true; + + if (mGamePadPort >= 0) + return true; + + return mGamePad; } /* 802C5D3C-802C62A8 .text readPad__12JUTExceptionFPUlPUl */ -void JUTException::readPad(unsigned long*, unsigned long*) { - /* Nonmatching */ +bool JUTException::readPad(u32* out_trigger, u32* out_button) { + bool result = false; + OSTime start_time = OSGetTime(); + OSTime ms; + do { + OSTime end_time = OSGetTime(); + OSTime ticks = end_time - start_time; + ms = ticks / (OS_TIMER_CLOCK / 1000); + } while (ms < 0x32); + + if (mGamePad == (JUTGamePad*)0xffffffff) { + JUTGamePad gamePad0(JUTGamePad::Port_1); + JUTGamePad gamePad1(JUTGamePad::Port_2); + JUTGamePad gamePad2(JUTGamePad::Port_3); + JUTGamePad gamePad3(JUTGamePad::Port_4); + JUTGamePad::read(); + + c3bcnt[0] = + (gamePad0.isPushing3ButtonReset() ? (c3bcnt[0] != 0 ? c3bcnt[0] : OSGetTime()) : 0); + c3bcnt[1] = + (gamePad1.isPushing3ButtonReset() ? (c3bcnt[1] != 0 ? c3bcnt[1] : OSGetTime()) : 0); + c3bcnt[2] = + (gamePad2.isPushing3ButtonReset() ? (c3bcnt[2] != 0 ? c3bcnt[2] : OSGetTime()) : 0); + c3bcnt[3] = + (gamePad3.isPushing3ButtonReset() ? (c3bcnt[3] != 0 ? c3bcnt[3] : OSGetTime()) : 0); + + OSTime resetTime0 = (c3bcnt[0] != 0) ? (OSGetTime() - c3bcnt[0]) : 0; + OSTime resetTime1 = (c3bcnt[1] != 0) ? (OSGetTime() - c3bcnt[1]) : 0; + OSTime resetTime2 = (c3bcnt[2] != 0) ? (OSGetTime() - c3bcnt[2]) : 0; + OSTime resetTime3 = (c3bcnt[3] != 0) ? (OSGetTime() - c3bcnt[3]) : 0; + + gamePad0.checkResetCallback(resetTime0); + gamePad1.checkResetCallback(resetTime1); + gamePad2.checkResetCallback(resetTime2); + gamePad3.checkResetCallback(resetTime3); + + if (out_trigger) { + *out_trigger = gamePad0.getTrigger() | gamePad1.getTrigger() | gamePad2.getTrigger() | + gamePad3.getTrigger(); + } + if (out_button) { + *out_button = gamePad0.getButton() | gamePad1.getButton() | gamePad2.getButton() | + gamePad3.getButton(); + } + + result = true; + } else if (mGamePadPort >= 0) { + JUTGamePad gamePad(mGamePadPort); + OSTime& gamePadTime = c3bcnt[0]; + gamePadTime = + (gamePad.isPushing3ButtonReset() ? (gamePadTime != 0 ? gamePadTime : OSGetTime()) : 0); + + OSTime resetTime = (gamePadTime != 0) ? (OSGetTime() - gamePadTime) : 0; + gamePad.checkResetCallback(resetTime); + + JUTGamePad::read(); + if (out_trigger) { + *out_trigger = gamePad.getTrigger(); + } + if (out_button) { + *out_button = gamePad.getButton(); + } + + result = true; + } else if (mGamePad) { + JUTGamePad::read(); + if (out_trigger) { + *out_trigger = mGamePad->getTrigger(); + } + if (out_button) { + *out_button = mGamePad->getButton(); + } + + result = true; + } + + return result; } /* 802C62A8-802C6724 .text printContext__12JUTExceptionFUsP9OSContextUlUl */ -void JUTException::printContext(unsigned short, OSContext*, unsigned long, unsigned long) { - /* Nonmatching */ +void JUTException::printContext(OSError error, OSContext* context, u32 dsisr, u32 dar) { + bool is_pad_enabled = isEnablePad() == 0; + if (!sErrorManager->mDirectPrint->isActive()) { + return; + } + + if (!sConsole) { + return; + } + + sConsole->print_f("******** EXCEPTION OCCURRED! ********\nFrameMemory:%XH\n", getFrameMemory()); + + int post_callback_executed = false; + while (true) { + showMainInfo(error, context, dsisr, dar); + + JUTConsoleManager::sManager->drawDirect(true); + waitTime(mPrintWaitTime0); + + if ((mPrintFlags & JUT_PRINT_GPR) != 0) { + printDebugInfo(EINFO_PAGE_GPR, error, context, dsisr, dar); + JUTConsoleManager::sManager->drawDirect(true); + waitTime(mPrintWaitTime0); + } + if ((mPrintFlags & JUT_PRINT_SRR0_MAP) != 0) { + printDebugInfo(EINFO_PAGE_SSR0_MAP, error, context, dsisr, dar); + JUTConsoleManager::sManager->drawDirect(true); + waitTime(mPrintWaitTime0); + } + if ((mPrintFlags & JUT_PRINT_GPR_MAP) != 0) { + printDebugInfo(EINFO_PAGE_GPR_MAP, error, context, dsisr, dar); + JUTConsoleManager::sManager->drawDirect(true); + waitTime(mPrintWaitTime0); + } + if ((mPrintFlags & JUT_PRINT_FLOAT) != 0) { + printDebugInfo(EINFO_PAGE_FLOAT, error, context, dsisr, dar); + JUTConsoleManager::sManager->drawDirect(true); + waitTime(mPrintWaitTime0); + } + if ((mPrintFlags & JUT_PRINT_STACK) != 0) { + printDebugInfo(EINFO_PAGE_STACK, error, context, dsisr, dar); + JUTConsoleManager::sManager->drawDirect(true); + waitTime(mPrintWaitTime1); + } + + sConsole->print("--------------------------------\n"); + JUTConsoleManager::sManager->drawDirect(true); + + if (post_callback_executed == 0 && sPostUserCallback) { + BOOL enable = OSEnableInterrupts(); + post_callback_executed = true; + (*sPostUserCallback)(error, context, dsisr, dar); + OSRestoreInterrupts(enable); + } + + if (this->field_0x98 == 0 || !is_pad_enabled) { + break; + } + + sConsole->setOutput(sConsole->getOutput() & 1); + } + + if (!is_pad_enabled) { + OSEnableInterrupts(); + + u32 button; + u32 trigger; + + int down = 0; + int up = 0; + do { + readPad(&trigger, &button); + + bool draw = false; + if (trigger == 0x100) { + sConsole->scrollToLastLine(); + draw = true; + } + + if (trigger == 0x200) { + sConsole->scrollToFirstLine(); + draw = true; + } + + if (button == 8) { + JUTConsole* console = sConsole; + up = (down < 3) ? -1 : ((down < 5) ? -2 : ((down < 7) ? -4 : -8)); + + console->scroll(up); + draw = true; + up = 0; + down++; + } else if (button == 4) { + JUTConsole* console = sConsole; + down = (up < 3) ? 1 : ((up < 5) ? 2 : ((up < 7) ? 4 : 8)); + + console->scroll(down); + draw = true; + down = 0; + up++; + } else { + down = 0; + up = 0; + } + + if (draw == true) { + u32 start = VIGetRetraceCount(); + while (start == VIGetRetraceCount()) + ; + JUTConsoleManager::sManager->drawDirect(true); + } + + waitTime(30); + } while (true); + } + + while (true) { + sConsole->scrollToFirstLine(); + JUTConsoleManager::sManager->drawDirect(true); + waitTime(2000); + + int line_offset; + int used_line; + u32 height; + next: + for (u32 i = sConsole->getHeight(); i > 0; i--) { + sConsole->scroll(1); + JUTConsoleManager::sManager->drawDirect(true); + + height = sConsole->getHeight(); + JUTConsole* console = sConsole; + line_offset = console->getLineOffset(); + used_line = console->getUsedLine(); + if ((used_line - height) + 1U <= line_offset) + break; + waitTime(20); + } + + waitTime(3000); + height = sConsole->getHeight(); + JUTConsole* console = sConsole; + line_offset = console->getLineOffset(); + used_line = console->getUsedLine(); + if ((used_line - height) + 1U <= line_offset) { + continue; + } + goto next; + } } /* 802C6724-802C67AC .text waitTime__12JUTExceptionFl */ -void JUTException::waitTime(long) { - /* Nonmatching */ +void JUTException::waitTime(s32 timeout_ms) { + if (timeout_ms) { + OSTime start_time = OSGetTime(); + OSTime ms; + do { + OSTime end_time = OSGetTime(); + OSTime ticks = end_time - start_time; + ms = ticks / (OS_TIMER_CLOCK / 1000); + } while (ms < timeout_ms); + } } /* 802C67AC-802C6868 .text createFB__12JUTExceptionFv */ void JUTException::createFB() { - /* Nonmatching */ + GXRenderModeObj* renderMode = &GXNtsc480Int; + void* end = (void*)OSGetArenaHi(); + u16 width = ALIGN_NEXT(renderMode->fb_width, 16); + u16 height = renderMode->xfb_height; + u32 pixel_count = width * height; + u32 size = pixel_count * 2; + + void* begin = (void*)ALIGN_PREV((u32)end - size, 32); + void* object = (void*)ALIGN_PREV((s32)begin - sizeof(JUTExternalFB), 32); + new (object) JUTExternalFB(renderMode, GX_GM_1_7, begin, size); + + mDirectPrint->changeFrameBuffer(object); + VIConfigure(renderMode); + VISetNextFrameBuffer(begin); + VISetBlack(FALSE); + VIFlush(); + + mFrameMemory = (JUTExternalFB*)object; } /* 802C6868-802C6878 .text setPreUserCallback__12JUTExceptionFPFUsP9OSContextUlUl_v */ -void JUTException::setPreUserCallback(void (*)(unsigned short, OSContext*, unsigned long, unsigned long)) { - /* Nonmatching */ +OSErrorHandler JUTException::setPreUserCallback(OSErrorHandler callback) { + OSErrorHandler previous = sPreUserCallback; + sPreUserCallback = callback; + return previous; } /* 802C6878-802C6888 .text setPostUserCallback__12JUTExceptionFPFUsP9OSContextUlUl_v */ -void JUTException::setPostUserCallback(void (*)(unsigned short, OSContext*, unsigned long, unsigned long)) { - /* Nonmatching */ +OSErrorHandler JUTException::setPostUserCallback(OSErrorHandler callback) { + OSErrorHandler previous = sPostUserCallback; + sPostUserCallback = callback; + return previous; } /* 802C6888-802C691C .text appendMapFile__12JUTExceptionFPCc */ -void JUTException::appendMapFile(const char*) { - /* Nonmatching */ +void JUTException::appendMapFile(const char* path) { + if (!path) { + return; + } + + JSUListIterator<JUTExMapFile> iterator; + for (iterator = sMapFileList.getFirst(); iterator != sMapFileList.getEnd(); ++iterator) { + if (strcmp(path, iterator->mPath) == 0) { + return; + } + } + + JUTExMapFile* mapFile = new JUTExMapFile((char*)path); + sMapFileList.append(&mapFile->mLink); } /* 802C691C-802C6A0C .text queryMapAddress__12JUTExceptionFPcUllPUlPUlPcUlbb */ -void JUTException::queryMapAddress(char*, unsigned long, long, unsigned long*, unsigned long*, char*, unsigned long, bool, bool) { - /* Nonmatching */ +bool JUTException::queryMapAddress(char* mapPath, u32 address, s32 section_id, u32* out_addr, u32* out_size, char* out_line, u32 line_length, bool print, bool begin_with_newline) { + if (mapPath) { + char buffer[80]; + snprintf(buffer, sizeof(buffer), "/maps/%s.map", mapPath); + if (queryMapAddress_single(buffer, address, section_id, out_addr, out_size, out_line, + line_length, print, begin_with_newline) == true) + { + return true; + } + } else if (sMapFileList.getFirst() != sMapFileList.getEnd()) { + if (queryMapAddress_single(sMapFileList.getFirst()->getObject()->mPath, address, -1, + out_addr, out_size, out_line, line_length, print, + begin_with_newline) == true) + { + return true; + } + } + + return false; } /* 802C6A0C-802C6D60 .text queryMapAddress_single__12JUTExceptionFPcUllPUlPUlPcUlbb */ -void JUTException::queryMapAddress_single(char*, unsigned long, long, unsigned long*, unsigned long*, char*, unsigned long, bool, bool) { +bool JUTException::queryMapAddress_single(char* mapPath, u32 address, s32 section_id, u32* out_addr, u32* out_size, char* out_line, u32 line_length, bool print, bool begin_with_newline) { /* Nonmatching */ + if (!mapPath) { + return false; + } + + char section_name[16]; + char buffer[0x200]; + JUTDirectFile file; + int i = 0; + if (!file.fopen(mapPath)) { + return false; + } + + int result = 0; + do { + char* src = buffer; + int found_section = 0; + do { + i++; + while (true) { + while (true) { + int length = file.fgets(buffer, ARRAY_SIZE(buffer)); + if (length < 0) + goto next_section; + if (buffer[0] == '.') + break; + } + + char* dst = section_name; + int i = 0; + char* src = buffer + 1; + for (; *src != '\0'; i++, dst++, src++) { + *dst = *src; + if (*src == ' ' || i == 0xf) + break; + } + + section_name[i] = 0; + if (*src == 0) + break; + + if (src[1] == 's' && src[2] == 'e' && src[3] == 'c' && src[4] == 't') { + found_section = true; + break; + } + } + if ((found_section & 0xFF) == 0) + goto end; + } while (section_id >= 0 && section_id != i); + next_section:; + + u32 addr; + int size; + do { + int length; + do { + length = file.fgets(buffer, ARRAY_SIZE(buffer)); + if (length <= 4) + goto next_symbol; + } while ((length < 28) || (buffer[28] != '4')); + + addr = strtol(buffer + 19, NULL, 16); + addr = ((buffer[18] - '0') << 28) | addr; + size = strtol(buffer + 11, NULL, 16); + } while (addr > address || address >= addr + size); + + if (out_addr) + *out_addr = addr; + + if (out_size) + *out_size = size; + + if (out_line) { + src = buffer + 0x1e; + char* dst = out_line; + u32 length = 0; + for (; length < line_length - 1; src++) { + u32 ch = *(u8*)src; + if (ch < ' ' && ch != '\t') + break; + if (((int)ch == ' ' || ch == '\t') && (length != 0)) { + if (dst[-1] != ' ') { + *dst = ' '; + dst++; + length++; + } + } else { + *dst = ch; + dst++; + length++; + } + } + if (length != 0 && dst[-1] == ' ') { + dst--; + } + *dst = 0; + if (print) { + if (begin_with_newline) { + sConsole->print("\n"); + } + sConsole->print_f(" [%08X]: .%s [%08X: %XH]\n %s\n", address, section_name, addr, size, out_line); + begin_with_newline = false; + } + } + + result = true; + + next_symbol:; + } while (section_id >= 0 && section_id != i); + + if (print && begin_with_newline) { + sConsole->print("\n"); + } + +end: + file.fclose(); + bool bresult = (result & 0xff) != 0; + return bresult; } /* 802C6D60-802C6E40 .text createConsole__12JUTExceptionFPvUl */ -void JUTException::createConsole(void*, unsigned long) { - /* Nonmatching */ -} +void JUTException::createConsole(void* console_buffer, u32 console_buffer_size) { + if (!console_buffer || !console_buffer_size) { + return; + } -/* 802C6E40-802C6E60 .text __ct__13JUTExternalFBFP16_GXRenderModeObj8_GXGammaPvUl */ -JUTExternalFB::JUTExternalFB(_GXRenderModeObj*, _GXGamma, void*, unsigned long) { - /* Nonmatching */ -} + u32 lines = JUTConsole::getLineFromObjectSize(console_buffer_size, 0x32); + if (lines != 0) { + sConsoleBuffer = console_buffer; + sConsoleBufferSize = console_buffer_size; + sConsole = JUTConsole::create(0x32, console_buffer, console_buffer_size); -/* 802C6E60-802C6EC0 .text __dt__12JUTExceptionFv */ -JUTException::~JUTException() { - /* Nonmatching */ + JUTConsoleManager* manager = JUTConsoleManager::sManager; + manager->setDirectConsole(sConsole); + + sConsole->setFontSize(10.0, 6.0); + sConsole->setPosition(12, 40); + sConsole->setHeight(23); + sConsole->setVisible(true); + sConsole->setOutput(JUTConsole::OUTPUT_OSREPORT | JUTConsole::OUTPUT_CONSOLE); + } } -/* 802C6F08-802C6F5C .text __dt__39JSUList<Q212JUTException12JUTExMapFile>Fv */ -JSUList<JUTException::JUTExMapFile>::~JSUList() { - /* Nonmatching */ +/* 802C6E40-802C6E60 .text __ct__13JUTExternalFBFP16_GXRenderModeObj8_GXGammaPvUl */ +JUTExternalFB::JUTExternalFB(GXRenderModeObj* renderMode, GXGamma gamma, void* buffer, u32 size) { + mRenderMode = renderMode; + mSize = size; + field_0x0C = 1; + mGamma = gamma; + field_0x10 = false; } |
