/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2014 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include #include #include #include #include #include #include #include #include namespace xdb { namespace ui { IMPLEMENT_APP(XdbApp); bool XdbApp::OnInit() { return true; } int XdbApp::OnExit() { // Top level windows are deleted by wx automatically. return 0; } void XdbApp::OpenEmpty() { while (true) { OpenPostmortemTraceDialog dialog; if (dialog.ShowModal() == wxID_CANCEL) { Exit(); return; } if (OpenTraceFile(dialog.trace_file_path(), dialog.content_file_path())) { break; } } } bool XdbApp::OpenTraceFile(const std::string& trace_file_path, const std::string& content_file_path) { std::wstring_convert> converter; return OpenTraceFile(converter.from_bytes(trace_file_path), converter.from_bytes(content_file_path)); } bool XdbApp::OpenTraceFile(const std::wstring& trace_file_path, const std::wstring& content_file_path) { std::unique_ptr target(new PostmortemDebugTarget()); if (!target->LoadTrace(trace_file_path)) { HandleOpenError("Unable to load trace file."); return false; } if (!target->LoadContent(content_file_path)) { HandleOpenError("Unable to load source game content module."); return false; } wxProgressDialog progress_dialog( "Preparing trace...", "This may take some time.", 100, nullptr, wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_SMOOTH | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | wxPD_ELAPSED_TIME); progress_dialog.Show(); enum class PrepareStatus { PROCESSING, SUCCEEDED, FAILED, }; std::atomic status(PrepareStatus::PROCESSING); std::atomic cancelled; std::thread preparation_thread([&target, &cancelled, &status]() { status = target->Prepare(cancelled) ? PrepareStatus::SUCCEEDED : PrepareStatus::FAILED; }); do { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } while (status == PrepareStatus::PROCESSING && progress_dialog.Pulse()); cancelled = progress_dialog.WasCancelled(); preparation_thread.join(); progress_dialog.Hide(); if (cancelled) { return false; } if (status == PrepareStatus::FAILED) { HandleOpenError("Invalid trace file; unable to process."); return false; } return OpenDebugTarget(std::move(target)); } bool XdbApp::OpenDebugTarget(std::unique_ptr debug_target) { auto main_frame = new MainFrame(std::move(debug_target)); main_frames_.push_back(main_frame); main_frame->Connect(wxEVT_DESTROY, wxEventHandler(XdbApp::OnMainFrameDestroy), nullptr, this); main_frame->Show(); main_frame->SetFocus(); return true; } void XdbApp::HandleOpenError(const std::string& message) { wxMessageDialog dialog(nullptr, message, "Error", wxOK | wxOK_DEFAULT | wxICON_ERROR); dialog.ShowModal(); } void XdbApp::OnMainFrameDestroy(wxEvent& event) { for (auto it = main_frames_.begin(); it != main_frames_.end(); ++it) { if (*it == event.GetEventObject()) { main_frames_.erase(it); return; } } assert_always(); } } // namespace ui } // namespace xdb