diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc index 309dee985..fdfa33cf4 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc @@ -9,10 +9,15 @@ #include "xenia/base/debugging.h" #include "xenia/base/logging.h" +#include "xenia/emulator.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_private.h" #include "xenia/kernel/xthread.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/window.h" +#include "xenia/ui/windowed_app_context.h" namespace xe { namespace kernel { @@ -147,13 +152,39 @@ DECLARE_XBOXKRNL_EXPORT2(RtlRaiseException, kDebug, kStub, kImportant); void KeBugCheckEx_entry(dword_t code, dword_t param1, dword_t param2, dword_t param3, dword_t param4) { - XELOGD("*** STOP: 0x{:08X} (0x{:08X}, 0x{:08X}, 0x{:08X}, 0x{:08X})", - static_cast(code), static_cast(param1), - static_cast(param2), static_cast(param3), - static_cast(param4)); + auto msg = + fmt::format("*** STOP: 0x{:08X} (0x{:08X}, 0x{:08X}, 0x{:08X}, 0x{:08X})", + static_cast(code), static_cast(param1), + static_cast(param2), static_cast(param3), + static_cast(param4)); + XELOGE("{}", msg); fflush(stdout); - xe::debugging::Break(); - assert_always(); + + if (xe::debugging::IsDebuggerAttached()) { + xe::debugging::Break(); + } + + // Show crash dialog and suspend the guest thread instead of killing the + // host process. + auto current_thread = kernel::XThread::GetCurrentThread(); + const auto* emulator = kernel_state()->emulator(); + auto* display_window = emulator->display_window(); + auto* imgui_drawer = emulator->imgui_drawer(); + if (display_window && imgui_drawer) { + auto dlg_msg = fmt::format( + "The guest kernel has crashed (KeBugCheck).\n\n{}\n\n" + "The faulting thread has been suspended.", + msg); + display_window->app_context().CallInUIThreadSynchronous( + [imgui_drawer, &dlg_msg]() { + xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer, + "Guest Kernel Crash", dlg_msg); + }); + } + + if (current_thread) { + current_thread->Suspend(nullptr); + } } DECLARE_XBOXKRNL_EXPORT2(KeBugCheckEx, kDebug, kStub, kImportant);