diff --git a/src/Cemu/Logging/CemuLogging.cpp b/src/Cemu/Logging/CemuLogging.cpp index ccf594bc..95614a98 100644 --- a/src/Cemu/Logging/CemuLogging.cpp +++ b/src/Cemu/Logging/CemuLogging.cpp @@ -92,13 +92,18 @@ void cemuLog_thread() } } +fs::path cemuLog_GetLogFilePath() +{ + return ActiveSettings::GetUserDataPath("log.txt"); +} + void cemuLog_createLogFile(bool triggeredByCrash) { std::unique_lock lock(LogContext.log_mutex); if (LogContext.file_stream.is_open()) return; - const auto path = ActiveSettings::GetUserDataPath("log.txt"); + const auto path = cemuLog_GetLogFilePath(); LogContext.file_stream.open(path, std::ios::out); if (LogContext.file_stream.fail()) { diff --git a/src/Cemu/Logging/CemuLogging.h b/src/Cemu/Logging/CemuLogging.h index c9718f07..09a08ec7 100644 --- a/src/Cemu/Logging/CemuLogging.h +++ b/src/Cemu/Logging/CemuLogging.h @@ -112,6 +112,7 @@ uint64 cemuLog_getFlag(LogType type); void cafeLog_setLoggingFlagEnable(sint32 loggingType, bool isEnable); bool cafeLog_isLoggingFlagEnabled(sint32 loggingType); +fs::path cemuLog_GetLogFilePath(); void cemuLog_createLogFile(bool triggeredByCrash); [[nodiscard]] std::unique_lock cafeLog_acquire(); diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt index ea132087..7ed3d67a 100644 --- a/src/Common/CMakeLists.txt +++ b/src/Common/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(CemuCommon cpu_features.cpp cpu_features.h enumFlags.h + ExceptionHandler/ExceptionHandler.cpp ExceptionHandler/ExceptionHandler.h FileStream.h GLInclude/glext.h diff --git a/src/Common/ExceptionHandler/ExceptionHandler.cpp b/src/Common/ExceptionHandler/ExceptionHandler.cpp new file mode 100644 index 00000000..5308ea8e --- /dev/null +++ b/src/Common/ExceptionHandler/ExceptionHandler.cpp @@ -0,0 +1,161 @@ +#include "config/ActiveSettings.h" +#include "config/CemuConfig.h" +#include "Cafe/CafeSystem.h" +#include "Cafe/OS/libs/coreinit/coreinit_Thread.h" +#include "Cafe/HW/Espresso/PPCState.h" +#include "Cafe/HW/Espresso/Debugger/GDBStub.h" +#include "ExceptionHandler.h" + +void DebugLogStackTrace(OSThread_t* thread, MPTR sp); + +bool crashLogCreated = false; + +bool CrashLog_Create() +{ + if (crashLogCreated) + return false; // only create one crashlog + crashLogCreated = true; + cemuLog_createLogFile(true); + CrashLog_SetOutputChannels(true, true); + return true; +} + +static bool s_writeToStdErr{true}; +static bool s_writeToLogTxt{true}; + +void CrashLog_SetOutputChannels(bool writeToStdErr, bool writeToLogTxt) +{ + s_writeToStdErr = writeToStdErr; + s_writeToLogTxt = writeToLogTxt; +} + +// outputs to both stderr and log.txt +void CrashLog_WriteLine(std::string_view text, bool newLine) +{ + if(s_writeToLogTxt) + cemuLog_writeLineToLog(text, false, newLine); + if(s_writeToStdErr) + { + fwrite(text.data(), sizeof(char), text.size(), stderr); + if(newLine) + fwrite("\n", sizeof(char), 1, stderr); + } +} + +void CrashLog_WriteHeader(const char* header) +{ + CrashLog_WriteLine("-----------------------------------------"); + CrashLog_WriteLine(" ", false); + CrashLog_WriteLine(header); + CrashLog_WriteLine("-----------------------------------------"); +} + +void ExceptionHandler_LogGeneralInfo() +{ + char dumpLine[1024]; + // info about game + CrashLog_WriteLine(""); + CrashLog_WriteHeader("Game info"); + if (CafeSystem::IsTitleRunning()) + { + CrashLog_WriteLine("Game: ", false); + CrashLog_WriteLine(CafeSystem::GetForegroundTitleName()); + // title id + CrashLog_WriteLine(fmt::format("TitleId: {:016x}", CafeSystem::GetForegroundTitleId())); + // rpx hash + sprintf(dumpLine, "RPXHash: %08x (Update: %08x)", CafeSystem::GetRPXHashBase(), CafeSystem::GetRPXHashUpdated()); + CrashLog_WriteLine(dumpLine); + } + else + { + CrashLog_WriteLine("Not running"); + } + // info about active PPC instance: + CrashLog_WriteLine(""); + CrashLog_WriteHeader("Active PPC instance"); + if (ppcInterpreterCurrentInstance) + { + OSThread_t* currentThread = coreinit::OSGetCurrentThread(); + uint32 threadPtr = memory_getVirtualOffsetFromPointer(coreinit::OSGetCurrentThread()); + sprintf(dumpLine, "IP 0x%08x LR 0x%08x Thread 0x%08x", ppcInterpreterCurrentInstance->instructionPointer, ppcInterpreterCurrentInstance->spr.LR, threadPtr); + CrashLog_WriteLine(dumpLine); + + // GPR info + CrashLog_WriteLine(""); + auto gprs = ppcInterpreterCurrentInstance->gpr; + sprintf(dumpLine, "r0 =%08x r1 =%08x r2 =%08x r3 =%08x r4 =%08x r5 =%08x r6 =%08x r7 =%08x", gprs[0], gprs[1], gprs[2], gprs[3], gprs[4], gprs[5], gprs[6], gprs[7]); + CrashLog_WriteLine(dumpLine); + sprintf(dumpLine, "r8 =%08x r9 =%08x r10=%08x r11=%08x r12=%08x r13=%08x r14=%08x r15=%08x", gprs[8], gprs[9], gprs[10], gprs[11], gprs[12], gprs[13], gprs[14], gprs[15]); + CrashLog_WriteLine(dumpLine); + sprintf(dumpLine, "r16=%08x r17=%08x r18=%08x r19=%08x r20=%08x r21=%08x r22=%08x r23=%08x", gprs[16], gprs[17], gprs[18], gprs[19], gprs[20], gprs[21], gprs[22], gprs[23]); + CrashLog_WriteLine(dumpLine); + sprintf(dumpLine, "r24=%08x r25=%08x r26=%08x r27=%08x r28=%08x r29=%08x r30=%08x r31=%08x", gprs[24], gprs[25], gprs[26], gprs[27], gprs[28], gprs[29], gprs[30], gprs[31]); + CrashLog_WriteLine(dumpLine); + + // stack trace + MPTR currentStackVAddr = ppcInterpreterCurrentInstance->gpr[1]; + CrashLog_WriteLine(""); + CrashLog_WriteHeader("PPC stack trace"); + DebugLogStackTrace(currentThread, currentStackVAddr); + + // stack dump + CrashLog_WriteLine(""); + CrashLog_WriteHeader("PPC stack dump"); + for (uint32 i = 0; i < 16; i++) + { + MPTR lineAddr = currentStackVAddr + i * 8 * 4; + if (memory_isAddressRangeAccessible(lineAddr, 8 * 4)) + { + sprintf(dumpLine, "[0x%08x] %08x %08x %08x %08x - %08x %08x %08x %08x", lineAddr, memory_readU32(lineAddr + 0), memory_readU32(lineAddr + 4), memory_readU32(lineAddr + 8), memory_readU32(lineAddr + 12), memory_readU32(lineAddr + 16), memory_readU32(lineAddr + 20), memory_readU32(lineAddr + 24), memory_readU32(lineAddr + 28)); + CrashLog_WriteLine(dumpLine); + } + else + { + sprintf(dumpLine, "[0x%08x] ?", lineAddr); + CrashLog_WriteLine(dumpLine); + } + } + } + else + { + CrashLog_WriteLine("Not active"); + } + + // PPC thread log + CrashLog_WriteLine(""); + CrashLog_WriteHeader("PPC threads"); + if (activeThreadCount == 0) + { + CrashLog_WriteLine("None active"); + } + for (sint32 i = 0; i < activeThreadCount; i++) + { + MPTR threadItrMPTR = activeThread[i]; + OSThread_t* threadItrBE = (OSThread_t*)memory_getPointerFromVirtualOffset(threadItrMPTR); + + // get thread state + OSThread_t::THREAD_STATE threadState = threadItrBE->state; + const char* threadStateStr = "UNDEFINED"; + if (threadItrBE->suspendCounter != 0) + threadStateStr = "SUSPENDED"; + else if (threadState == OSThread_t::THREAD_STATE::STATE_NONE) + threadStateStr = "NONE"; + else if (threadState == OSThread_t::THREAD_STATE::STATE_READY) + threadStateStr = "READY"; + else if (threadState == OSThread_t::THREAD_STATE::STATE_RUNNING) + threadStateStr = "RUNNING"; + else if (threadState == OSThread_t::THREAD_STATE::STATE_WAITING) + threadStateStr = "WAITING"; + else if (threadState == OSThread_t::THREAD_STATE::STATE_MORIBUND) + threadStateStr = "MORIBUND"; + // generate log line + uint8 affinity = threadItrBE->attr; + sint32 effectivePriority = threadItrBE->effectivePriority; + const char* threadName = "NULL"; + if (!threadItrBE->threadName.IsNull()) + threadName = threadItrBE->threadName.GetPtr(); + sprintf(dumpLine, "%08x Ent %08x IP %08x LR %08x %-9s Aff %d%d%d Pri %2d Name %s", threadItrMPTR, _swapEndianU32(threadItrBE->entrypoint), threadItrBE->context.srr0, _swapEndianU32(threadItrBE->context.lr), threadStateStr, (affinity >> 0) & 1, (affinity >> 1) & 1, (affinity >> 2) & 1, effectivePriority, threadName); + // write line to log + CrashLog_WriteLine(dumpLine); + } +} diff --git a/src/Common/ExceptionHandler/ExceptionHandler.h b/src/Common/ExceptionHandler/ExceptionHandler.h index bb139ca2..845e5f7f 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler.h +++ b/src/Common/ExceptionHandler/ExceptionHandler.h @@ -1,3 +1,10 @@ #pragma once -void ExceptionHandler_init(); \ No newline at end of file +void ExceptionHandler_Init(); + +bool CrashLog_Create(); +void CrashLog_SetOutputChannels(bool writeToStdErr, bool writeToLogTxt); +void CrashLog_WriteLine(std::string_view text, bool newLine = true); +void CrashLog_WriteHeader(const char* header); + +void ExceptionHandler_LogGeneralInfo(); diff --git a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp index 3a5620c2..34430e37 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp +++ b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp @@ -4,13 +4,14 @@ #include #include "config/CemuConfig.h" #include "util/helpers/StringHelpers.h" +#include "ExceptionHandler.h" #if BOOST_OS_LINUX #include "ELFSymbolTable.h" #endif #if BOOST_OS_LINUX -void demangleAndPrintBacktrace(char** backtrace, size_t size) +void DemangleAndPrintBacktrace(char** backtrace, size_t size) { ELFSymbolTable symTable; for (char** i = backtrace; i < backtrace + size; i++) @@ -25,7 +26,7 @@ void demangleAndPrintBacktrace(char** backtrace, size_t size) offsetPlus < parenthesesOpen || offsetPlus > parenthesesClose) { // fall back to default string - std::cerr << traceLine << std::endl; + CrashLog_WriteLine(traceLine); continue; } @@ -38,29 +39,32 @@ void demangleAndPrintBacktrace(char** backtrace, size_t size) symbolName = symTable.OffsetToSymbol(symbolOffset, newOffset); } - std::cerr << traceLine.substr(0, parenthesesOpen+1); + CrashLog_WriteLine(traceLine.substr(0, parenthesesOpen+1), false); - std::cerr << boost::core::demangle(symbolName.empty() ? "" : symbolName.data()); + CrashLog_WriteLine(boost::core::demangle(symbolName.empty() ? "" : symbolName.data()), false); // print relative or existing symbol offset. - std::cerr << '+'; + CrashLog_WriteLine("+", false); if (newOffset != -1) { - std::cerr << std::hex << newOffset; - std::cerr << traceLine.substr(parenthesesClose) << std::endl; + CrashLog_WriteLine(fmt::format("0x{:x}", newOffset), false); + CrashLog_WriteLine(traceLine.substr(parenthesesClose)); } else { - std::cerr << traceLine.substr(offsetPlus+1) << std::endl; + CrashLog_WriteLine(traceLine.substr(offsetPlus+1)); } } } #endif // handle signals that would dump core, print stacktrace and then dump depending on config -void handlerDumpingSignal(int sig) +void handlerDumpingSignal(int sig, siginfo_t *info, void *context) { - char* sigName = strsignal(sig); + if(!CrashLog_Create()) + return; // give up if crashlog was already created + + char* sigName = strsignal(sig); if (sigName) { printf("%s!\n", sigName); @@ -71,31 +75,42 @@ void handlerDumpingSignal(int sig) printf("Unknown core dumping signal!\n"); } - void *array[128]; + void* backtraceArray[128]; size_t size; // get void*'s for all entries on the stack - size = backtrace(array, 128); + size = backtrace(backtraceArray, 128); + // replace the deepest entry with the actual crash address +#if defined(ARCH_X86_64) && BOOST_OS_LINUX > 0 + ucontext_t *uc = (ucontext_t *)context; + backtraceArray[0] = (void *)uc->uc_mcontext.gregs[REG_RIP]; +#endif - // print out all the frames to stderr - fprintf(stderr, "Error: signal %d:\n", sig); + CrashLog_WriteLine(fmt::format("Error: signal {}:", sig)); #if BOOST_OS_LINUX - char** symbol_trace = backtrace_symbols(array, size); + char** symbol_trace = backtrace_symbols(backtraceArray, size); if (symbol_trace) { - demangleAndPrintBacktrace(symbol_trace, size); + DemangleAndPrintBacktrace(symbol_trace, size); free(symbol_trace); } else { - std::cerr << "Failed to read backtrace" << std::endl; + CrashLog_WriteLine("Failed to read backtrace"); } #else - backtrace_symbols_fd(array, size, STDERR_FILENO); + backtrace_symbols_fd(backtraceArray, size, STDERR_FILENO); #endif + std::cerr << fmt::format("\nStacktrace and additional info written to:") << std::endl; + std::cerr << cemuLog_GetLogFilePath().generic_string() << std::endl; + + CrashLog_SetOutputChannels(false, true); + ExceptionHandler_LogGeneralInfo(); + CrashLog_SetOutputChannels(true, true); + if (GetConfig().crash_dump == CrashDump::Enabled) { // reset signal handler to default and re-raise signal to dump core @@ -119,7 +134,7 @@ void handler_SIGINT(int sig) _Exit(0); } -void ExceptionHandler_init() +void ExceptionHandler_Init() { struct sigaction action; action.sa_flags = 0; @@ -128,7 +143,9 @@ void ExceptionHandler_init() action.sa_handler = handler_SIGINT; sigaction(SIGINT, &action, nullptr); - action.sa_handler = handlerDumpingSignal; + action.sa_flags = SA_SIGINFO; + action.sa_handler = nullptr; + action.sa_sigaction = handlerDumpingSignal; sigaction(SIGABRT, &action, nullptr); sigaction(SIGBUS, &action, nullptr); sigaction(SIGFPE, &action, nullptr); diff --git a/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp b/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp index c793e434..6b205d26 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp +++ b/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp @@ -1,36 +1,22 @@ #include "Common/precompiled.h" #include "Cafe/CafeSystem.h" +#include "ExceptionHandler.h" #include #include #include -#include "Config/ActiveSettings.h" -#include "Config/CemuConfig.h" +#include "config/ActiveSettings.h" +#include "config/CemuConfig.h" #include "Cafe/OS/libs/coreinit/coreinit_Thread.h" #include "Cafe/HW/Espresso/PPCState.h" #include "Cafe/HW/Espresso/Debugger/GDBStub.h" -extern uint32 currentBaseApplicationHash; -extern uint32 currentUpdatedApplicationHash; - LONG handleException_SINGLE_STEP(PEXCEPTION_POINTERS pExceptionInfo) { return EXCEPTION_CONTINUE_SEARCH; } -void crashlog_writeHeader(const char* header) -{ - cemuLog_writePlainToLog("-----------------------------------------\n"); - - cemuLog_writePlainToLog(" "); - cemuLog_writePlainToLog(header); - cemuLog_writePlainToLog("\n"); - - cemuLog_writePlainToLog("-----------------------------------------\n"); -} - -bool crashLogCreated = false; #include BOOL CALLBACK MyMiniDumpCallback(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput) { @@ -108,8 +94,6 @@ bool CreateMiniDump(CrashDump dump, EXCEPTION_POINTERS* pep) return result != FALSE; } -void DebugLogStackTrace(OSThread_t* thread, MPTR sp); - void DumpThreadStackTrace() { HANDLE process = GetCurrentProcess(); @@ -123,7 +107,7 @@ void DumpThreadStackTrace() symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - crashlog_writeHeader("Stack trace"); + CrashLog_WriteHeader("Stack trace"); for (unsigned int i = 0; i < frames; i++) { DWORD64 stackTraceOffset = (DWORD64)stack[i]; @@ -171,11 +155,8 @@ void DumpThreadStackTrace() void createCrashlog(EXCEPTION_POINTERS* e, PCONTEXT context) { - if (crashLogCreated) - return; // only create one crashlog - crashLogCreated = true; - - cemuLog_createLogFile(true); + if(!CrashLog_Create()) + return; // give up if crashlog was already created const auto crash_dump = GetConfig().crash_dump.GetValue(); const auto dump_written = CreateMiniDump(crash_dump, e); @@ -236,117 +217,10 @@ void createCrashlog(EXCEPTION_POINTERS* e, PCONTEXT context) cemuLog_writePlainToLog(dumpLine); sprintf(dumpLine, "R12=%016I64x R13=%016I64x R14=%016I64x R15=%016I64x\n", context->R12, context->R13, context->R14, context->R15); cemuLog_writePlainToLog(dumpLine); - // info about game - cemuLog_writePlainToLog("\n"); - crashlog_writeHeader("Game info"); - if (CafeSystem::IsTitleRunning()) - { - cemuLog_writePlainToLog("Game: "); - cemuLog_writePlainToLog(CafeSystem::GetForegroundTitleName().c_str()); - cemuLog_writePlainToLog("\n"); - // title id - sprintf(dumpLine, "TitleId: %I64x\n", CafeSystem::GetForegroundTitleId()); - cemuLog_writePlainToLog(dumpLine); - // rpx hash - sprintf(dumpLine, "RPXHash: %x\n", currentBaseApplicationHash); - cemuLog_writePlainToLog(dumpLine); - } - else - { - cemuLog_writePlainToLog("Not running\n"); - } - // info about active PPC instance: - cemuLog_writePlainToLog("\n"); - crashlog_writeHeader("Active PPC instance"); - if (ppcInterpreterCurrentInstance) - { - OSThread_t* currentThread = coreinit::OSGetCurrentThread(); - uint32 threadPtr = memory_getVirtualOffsetFromPointer(coreinit::OSGetCurrentThread()); - sprintf(dumpLine, "IP 0x%08x LR 0x%08x Thread 0x%08x\n", ppcInterpreterCurrentInstance->instructionPointer, ppcInterpreterCurrentInstance->spr.LR, threadPtr); - cemuLog_writePlainToLog(dumpLine); - // GPR info - sprintf(dumpLine, "\n"); - cemuLog_writePlainToLog(dumpLine); - auto gprs = ppcInterpreterCurrentInstance->gpr; - sprintf(dumpLine, "r0 =%08x r1 =%08x r2 =%08x r3 =%08x r4 =%08x r5 =%08x r6 =%08x r7 =%08x\n", gprs[0], gprs[1], gprs[2], gprs[3], gprs[4], gprs[5], gprs[6], gprs[7]); - cemuLog_writePlainToLog(dumpLine); - sprintf(dumpLine, "r8 =%08x r9 =%08x r10=%08x r11=%08x r12=%08x r13=%08x r14=%08x r15=%08x\n", gprs[8], gprs[9], gprs[10], gprs[11], gprs[12], gprs[13], gprs[14], gprs[15]); - cemuLog_writePlainToLog(dumpLine); - sprintf(dumpLine, "r16=%08x r17=%08x r18=%08x r19=%08x r20=%08x r21=%08x r22=%08x r23=%08x\n", gprs[16], gprs[17], gprs[18], gprs[19], gprs[20], gprs[21], gprs[22], gprs[23]); - cemuLog_writePlainToLog(dumpLine); - sprintf(dumpLine, "r24=%08x r25=%08x r26=%08x r27=%08x r28=%08x r29=%08x r30=%08x r31=%08x\n", gprs[24], gprs[25], gprs[26], gprs[27], gprs[28], gprs[29], gprs[30], gprs[31]); - cemuLog_writePlainToLog(dumpLine); - - // write line to log - cemuLog_writePlainToLog(dumpLine); - - // stack trace - MPTR currentStackVAddr = ppcInterpreterCurrentInstance->gpr[1]; - cemuLog_writePlainToLog("\n"); - crashlog_writeHeader("PPC stack trace"); - DebugLogStackTrace(currentThread, currentStackVAddr); - - // stack dump - cemuLog_writePlainToLog("\n"); - crashlog_writeHeader("PPC stack dump"); - for (uint32 i = 0; i < 16; i++) - { - MPTR lineAddr = currentStackVAddr + i * 8 * 4; - if (memory_isAddressRangeAccessible(lineAddr, 8 * 4)) - { - sprintf(dumpLine, "[0x%08x] %08x %08x %08x %08x - %08x %08x %08x %08x\n", lineAddr, memory_readU32(lineAddr + 0), memory_readU32(lineAddr + 4), memory_readU32(lineAddr + 8), memory_readU32(lineAddr + 12), memory_readU32(lineAddr + 16), memory_readU32(lineAddr + 20), memory_readU32(lineAddr + 24), memory_readU32(lineAddr + 28)); - cemuLog_writePlainToLog(dumpLine); - } - else - { - sprintf(dumpLine, "[0x%08x] ?\n", lineAddr); - cemuLog_writePlainToLog(dumpLine); - } - } - } - else - { - cemuLog_writePlainToLog("Not active\n"); - } - - // PPC thread log - cemuLog_writePlainToLog("\n"); - crashlog_writeHeader("PPC threads"); - if (activeThreadCount == 0) - { - cemuLog_writePlainToLog("None active\n"); - } - for (sint32 i = 0; i < activeThreadCount; i++) - { - MPTR threadItrMPTR = activeThread[i]; - OSThread_t* threadItrBE = (OSThread_t*)memory_getPointerFromVirtualOffset(threadItrMPTR); - - // get thread state - OSThread_t::THREAD_STATE threadState = threadItrBE->state; - const char* threadStateStr = "UNDEFINED"; - if (threadItrBE->suspendCounter != 0) - threadStateStr = "SUSPENDED"; - else if (threadState == OSThread_t::THREAD_STATE::STATE_NONE) - threadStateStr = "NONE"; - else if (threadState == OSThread_t::THREAD_STATE::STATE_READY) - threadStateStr = "READY"; - else if (threadState == OSThread_t::THREAD_STATE::STATE_RUNNING) - threadStateStr = "RUNNING"; - else if (threadState == OSThread_t::THREAD_STATE::STATE_WAITING) - threadStateStr = "WAITING"; - else if (threadState == OSThread_t::THREAD_STATE::STATE_MORIBUND) - threadStateStr = "MORIBUND"; - // generate log line - uint8 affinity = threadItrBE->attr; - sint32 effectivePriority = threadItrBE->effectivePriority; - const char* threadName = "NULL"; - if (!threadItrBE->threadName.IsNull()) - threadName = threadItrBE->threadName.GetPtr(); - sprintf(dumpLine, "%08x Ent %08x IP %08x LR %08x %-9s Aff %d%d%d Pri %2d Name %s\n", threadItrMPTR, _swapEndianU32(threadItrBE->entrypoint), threadItrBE->context.srr0, _swapEndianU32(threadItrBE->context.lr), threadStateStr, (affinity >> 0) & 1, (affinity >> 1) & 1, (affinity >> 2) & 1, effectivePriority, threadName); - // write line to log - cemuLog_writePlainToLog(dumpLine); - } + CrashLog_SetOutputChannels(false, true); + ExceptionHandler_LogGeneralInfo(); + CrashLog_SetOutputChannels(true, true); cemuLog_waitForFlush(); @@ -405,7 +279,7 @@ LONG WINAPI cemu_unhandledExceptionFilter(EXCEPTION_POINTERS* pExceptionInfo) return EXCEPTION_NONCONTINUABLE_EXCEPTION; } -void ExceptionHandler_init() +void ExceptionHandler_Init() { SetUnhandledExceptionFilter(cemu_unhandledExceptionFilter); AddVectoredExceptionHandler(1, VectoredExceptionHandler); diff --git a/src/main.cpp b/src/main.cpp index 33b1b0a3..eac11953 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -179,7 +179,7 @@ void mainEmulatorCommonInit() // set high priority SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); #endif - ExceptionHandler_init(); + ExceptionHandler_Init(); // read config g_config.Load(); if (NetworkConfig::XMLExists())