diff --git a/src/xdb/debug_target.cc b/src/xdb/debug_target.cc new file mode 100644 index 000000000..197ab2be6 --- /dev/null +++ b/src/xdb/debug_target.cc @@ -0,0 +1,16 @@ +/** + ****************************************************************************** + * 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 + +namespace xdb { + +// + +} // namespace xdb diff --git a/src/xdb/debug_target.h b/src/xdb/debug_target.h new file mode 100644 index 000000000..2ff238f5d --- /dev/null +++ b/src/xdb/debug_target.h @@ -0,0 +1,23 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#ifndef XDB_DEBUG_TARGET_H_ +#define XDB_DEBUG_TARGET_H_ + +namespace xdb { + +class DebugTarget { + public: + protected: + DebugTarget() = default; +}; + +} // namespace xdb + +#endif // XDB_DEBUG_TARGET_H_ diff --git a/src/xdb/postmortem_debug_target.cc b/src/xdb/postmortem_debug_target.cc new file mode 100644 index 000000000..fa541a72d --- /dev/null +++ b/src/xdb/postmortem_debug_target.cc @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * 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 + +namespace xdb { + +bool PostmortemDebugTarget::LoadTrace(const std::wstring& path) { + // TODO(benvanik): memory map trace. + return true; +} + +bool PostmortemDebugTarget::LoadContent(const std::wstring& path) { + // If no path is provided attempt to infer from the trace. + if (path.empty()) { + // TODO(benvanik): find process info block and read source path. + } + // TODO(benvanik): initialize filesystem and load iso/stfs/etc to get at xex. + return true; +} + +bool PostmortemDebugTarget::Prepare() { + std::atomic cancelled(false); + return Prepare(cancelled); +} + +bool PostmortemDebugTarget::Prepare(std::atomic& cancelled) { + // TODO(benvanik): scan file, build indicies, etc. + return true; +} + +} // namespace xdb diff --git a/src/xdb/postmortem_debug_target.h b/src/xdb/postmortem_debug_target.h new file mode 100644 index 000000000..4071ea19e --- /dev/null +++ b/src/xdb/postmortem_debug_target.h @@ -0,0 +1,33 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#ifndef XDB_POSTMORTEM_DEBUG_TARGET_H_ +#define XDB_POSTMORTEM_DEBUG_TARGET_H_ + +#include +#include + +#include + +namespace xdb { + +class PostmortemDebugTarget : public DebugTarget { + public: + PostmortemDebugTarget() = default; + + bool LoadTrace(const std::wstring& path); + bool LoadContent(const std::wstring& path = L""); + + bool Prepare(); + bool Prepare(std::atomic& cancelled); +}; + +} // namespace xdb + +#endif // XDB_POSTMORTEM_DEBUG_TARGET_H_ diff --git a/src/xdb/sources.gypi b/src/xdb/sources.gypi index 7e08a9fc7..621a218e1 100644 --- a/src/xdb/sources.gypi +++ b/src/xdb/sources.gypi @@ -1,6 +1,10 @@ # Copyright 2014 Ben Vanik. All Rights Reserved. { 'sources': [ + 'debug_target.cc', + 'debug_target.h', + 'postmortem_debug_target.cc', + 'postmortem_debug_target.h', 'protocol.h', 'xdb.cc', 'xdb.h', @@ -9,6 +13,7 @@ ], 'includes': [ + 'sym/sources.gypi', 'ui/sources.gypi', ], } diff --git a/src/xdb/sym/map_symbol_database.cc b/src/xdb/sym/map_symbol_database.cc new file mode 100644 index 000000000..f8fba81d8 --- /dev/null +++ b/src/xdb/sym/map_symbol_database.cc @@ -0,0 +1,20 @@ +/** + ****************************************************************************** + * 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 + +namespace xdb { +namespace sym { + +Symbol* MapSymbolDatabase::Lookup(uint32_t address) { + return nullptr; +} + +} // namespace sym +} // namespace xdb diff --git a/src/xdb/sym/map_symbol_database.h b/src/xdb/sym/map_symbol_database.h new file mode 100644 index 000000000..25d9ef19c --- /dev/null +++ b/src/xdb/sym/map_symbol_database.h @@ -0,0 +1,26 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#ifndef XDB_SYM_MAP_SYMBOL_DATABASE_H_ +#define XDB_SYM_MAP_SYMBOL_DATABASE_H_ + +#include + +namespace xdb { +namespace sym { + +class MapSymbolDatabase : public SymbolDatabase { + public: + Symbol* Lookup(uint32_t address) override; +}; + +} // namespace sym +} // namespace xdb + +#endif // XDB_SYM_MAP_SYMBOL_DATABASE_H_ diff --git a/src/xdb/sym/sources.gypi b/src/xdb/sym/sources.gypi new file mode 100644 index 000000000..ecff8910f --- /dev/null +++ b/src/xdb/sym/sources.gypi @@ -0,0 +1,14 @@ +# Copyright 2014 Ben Vanik. All Rights Reserved. +{ + 'sources': [ + 'map_symbol_database.cc', + 'map_symbol_database.h', + 'symbol_database.cc', + 'symbol_database.h', + 'symbol_provider.cc', + 'symbol_provider.h', + ], + + 'includes': [ + ], +} diff --git a/src/xdb/sym/symbol_database.cc b/src/xdb/sym/symbol_database.cc new file mode 100644 index 000000000..e2bc02f2d --- /dev/null +++ b/src/xdb/sym/symbol_database.cc @@ -0,0 +1,18 @@ +/** + ****************************************************************************** + * 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 + +namespace xdb { +namespace sym { + +// + +} // namespace sym +} // namespace xdb diff --git a/src/xdb/sym/symbol_database.h b/src/xdb/sym/symbol_database.h new file mode 100644 index 000000000..bf43a38e2 --- /dev/null +++ b/src/xdb/sym/symbol_database.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#ifndef XDB_SYM_SYMBOL_DATABASE_H_ +#define XDB_SYM_SYMBOL_DATABASE_H_ + +#include +#include + +namespace xdb { +namespace sym { + +class ObjectFile { + public: + std::string library; + std::string name; +}; + +enum class SymbolType { + FUNCTION, + VARIABLE, +}; + +class Symbol { + public: + uint32_t address; + ObjectFile* object_file; + std::string name; + SymbolType type; + bool is_inlined; +}; + +class SymbolDatabase { + public: + virtual Symbol* Lookup(uint32_t address) = 0; + + protected: + SymbolDatabase() = default; +}; + +} // namespace sym +} // namespace xdb + +#endif // XDB_SYM_SYMBOL_DATABASE_H_ diff --git a/src/xdb/sym/symbol_provider.cc b/src/xdb/sym/symbol_provider.cc new file mode 100644 index 000000000..3b5748290 --- /dev/null +++ b/src/xdb/sym/symbol_provider.cc @@ -0,0 +1,25 @@ +/** + ****************************************************************************** + * 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 + +namespace xdb { +namespace sym { + +void SymbolProvider::AddSearchPath(const std::string& path) { + // +} + +std::unique_ptr SymbolProvider::LoadDatabase( + const std::string& module_path) { + return nullptr; +} + +} // namespace sym +} // namespace xdb diff --git a/src/xdb/sym/symbol_provider.h b/src/xdb/sym/symbol_provider.h new file mode 100644 index 000000000..89c1291aa --- /dev/null +++ b/src/xdb/sym/symbol_provider.h @@ -0,0 +1,33 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#ifndef XDB_SYM_SYMBOL_PROVIDER_H_ +#define XDB_SYM_SYMBOL_PROVIDER_H_ + +#include +#include + +#include + +namespace xdb { +namespace sym { + +class SymbolProvider { + public: + SymbolProvider() = default; + + void AddSearchPath(const std::string& path); + + std::unique_ptr LoadDatabase(const std::string& module_path); +}; + +} // namespace sym +} // namespace xdb + +#endif // XDB_SYM_SYMBOL_PROVIDER_H_ diff --git a/src/xdb/ui/main_frame.cc b/src/xdb/ui/main_frame.cc index 606da3f44..1542435d6 100644 --- a/src/xdb/ui/main_frame.cc +++ b/src/xdb/ui/main_frame.cc @@ -12,7 +12,8 @@ namespace xdb { namespace ui { -MainFrame::MainFrame() : MainFrameBase(nullptr) {} +MainFrame::MainFrame(std::unique_ptr debug_target) + : MainFrameBase(nullptr), debug_target_(std::move(debug_target)) {} } // namespace ui } // namespace xdb diff --git a/src/xdb/ui/main_frame.h b/src/xdb/ui/main_frame.h index 9f6ba8ffd..2c7228dcc 100644 --- a/src/xdb/ui/main_frame.h +++ b/src/xdb/ui/main_frame.h @@ -10,8 +10,9 @@ #ifndef XDB_UI_MAIN_FRAME_H_ #define XDB_UI_MAIN_FRAME_H_ -#include +#include +#include #include namespace xdb { @@ -19,9 +20,13 @@ namespace ui { class MainFrame : public MainFrameBase { public: - MainFrame(); + MainFrame(std::unique_ptr debug_target); + protected: // + + private: + std::unique_ptr debug_target_; }; } // namespace ui diff --git a/src/xdb/ui/open_postmortem_trace_dialog.h b/src/xdb/ui/open_postmortem_trace_dialog.h new file mode 100644 index 000000000..64944029f --- /dev/null +++ b/src/xdb/ui/open_postmortem_trace_dialog.h @@ -0,0 +1,33 @@ +/** + ****************************************************************************** + * 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. * + ****************************************************************************** + */ + +#ifndef XDB_UI_OPEN_POSTMORTEM_TRACE_DIALOG_H_ +#define XDB_UI_OPEN_POSTMORTEM_TRACE_DIALOG_H_ + +#include + +namespace xdb { +namespace ui { + +class OpenPostmortemTraceDialog : public OpenPostmortemTraceDialogBase { + public: + OpenPostmortemTraceDialog() : OpenPostmortemTraceDialogBase(nullptr) {} + + const std::wstring trace_file_path() const { + return trace_file_picker_->GetFileName().GetFullPath().ToStdWstring(); + } + const std::wstring content_file_path() const { + return content_file_picker_->GetFileName().GetFullPath().ToStdWstring(); + } +}; + +} // namespace ui +} // namespace xdb + +#endif // XDB_UI_OPEN_POSTMORTEM_TRACE_DIALOG_H_ diff --git a/src/xdb/ui/sources.gypi b/src/xdb/ui/sources.gypi index 3673fcf7a..bc406dd7d 100644 --- a/src/xdb/ui/sources.gypi +++ b/src/xdb/ui/sources.gypi @@ -3,6 +3,7 @@ 'sources': [ 'main_frame.cc', 'main_frame.h', + 'open_postmortem_trace_dialog.h', 'xdb_ui.cpp', 'xdb_ui.h', ], diff --git a/src/xdb/ui/xdb-ui.fbp b/src/xdb/ui/xdb-ui.fbp index 4a40d2e42..7166732f5 100644 --- a/src/xdb/ui/xdb-ui.fbp +++ b/src/xdb/ui/xdb-ui.fbp @@ -11,7 +11,7 @@ res UTF-8 connect - + xdb_ui 1000 none 0 @@ -46,7 +46,7 @@ 1024,768 wxDEFAULT_FRAME_STYLE - + ; xenia debugger @@ -135,7 +135,7 @@ File - file + file_menu_ protected @@ -536,5 +536,638 @@ + + 0 + + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + OpenPostmortemTraceDialogBase + + -1,-1 + wxDEFAULT_DIALOG_STYLE + + Open Postmortem Trace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + root_panel_outer + wxVERTICAL + none + + 10 + wxEXPAND | wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + root_panel + 1 + + + none + 1 + + Resizable + 1 + + + 0 + + + + wxTAB_TRAVERSAL + + + + + + + + + + + + + + + + + + + + + + + + + 1 + wxVERTICAL + 0 + + 0 + + root_sizer + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Use --trace_file= to specify the output file path when running xenia-run. + + 0 + + + 0 + + 1 + info_label + 1 + + + none + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + 2 + wxBOTH + 1 + + 0 + + content_sizer + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Trace File: + + 0 + + + 0 + + 1 + trace_file_label + 1 + + + none + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER|wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + Select a .trace file + + 0 + + 1 + trace_file_picker_ + 1 + + + protected + 1 + + Resizable + 1 + + wxFLP_DEFAULT_STYLE|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + *.trace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Content Path: + + 0 + + + 0 + + 1 + content_file_label + 1 + + + none + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER|wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + Select the source content path + + 0 + + 1 + content_file_picker_ + 1 + + + protected + 1 + + Resizable + 1 + + wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + *.xex;*.iso;*.* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + wxEXPAND + 1 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + dialog_buttons_ + protected + + OnCancelButtonClick + + + + OnOKButtonClick + + + + + + + + + diff --git a/src/xdb/ui/xdb_ui.cpp b/src/xdb/ui/xdb_ui.cpp index c537f8f6a..0ec24af81 100644 --- a/src/xdb/ui/xdb_ui.cpp +++ b/src/xdb/ui/xdb_ui.cpp @@ -17,8 +17,8 @@ MainFrameBase::MainFrameBase( wxWindow* parent, wxWindowID id, const wxString& t m_mgr.SetFlags(wxAUI_MGR_DEFAULT|wxAUI_MGR_LIVE_RESIZE); menu_bar_ = new wxMenuBar( 0 ); - file = new wxMenu(); - menu_bar_->Append( file, wxT("File") ); + file_menu_ = new wxMenu(); + menu_bar_->Append( file_menu_, wxT("File") ); this->SetMenuBar( menu_bar_ ); @@ -47,3 +47,83 @@ MainFrameBase::~MainFrameBase() m_mgr.UnInit(); } + +OpenPostmortemTraceDialogBase::OpenPostmortemTraceDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* root_panel_outer; + root_panel_outer = new wxBoxSizer( wxVERTICAL ); + + wxPanel* root_panel; + root_panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxFlexGridSizer* root_sizer; + root_sizer = new wxFlexGridSizer( 0, 1, 0, 0 ); + root_sizer->AddGrowableCol( 0 ); + root_sizer->SetFlexibleDirection( wxVERTICAL ); + root_sizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + wxStaticText* info_label; + info_label = new wxStaticText( root_panel, wxID_ANY, wxT("Use --trace_file= to specify the output file path when running xenia-run."), wxDefaultPosition, wxDefaultSize, 0 ); + info_label->Wrap( -1 ); + root_sizer->Add( info_label, 0, wxALL, 5 ); + + wxFlexGridSizer* content_sizer; + content_sizer = new wxFlexGridSizer( 0, 2, 0, 0 ); + content_sizer->AddGrowableCol( 1 ); + content_sizer->SetFlexibleDirection( wxBOTH ); + content_sizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + wxStaticText* trace_file_label; + trace_file_label = new wxStaticText( root_panel, wxID_ANY, wxT("Trace File:"), wxDefaultPosition, wxDefaultSize, 0 ); + trace_file_label->Wrap( -1 ); + content_sizer->Add( trace_file_label, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 ); + + trace_file_picker_ = new wxFilePickerCtrl( root_panel, wxID_ANY, wxEmptyString, wxT("Select a .trace file"), wxT("*.trace"), wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL ); + content_sizer->Add( trace_file_picker_, 1, wxALIGN_CENTER|wxALL|wxEXPAND, 5 ); + + wxStaticText* content_file_label; + content_file_label = new wxStaticText( root_panel, wxID_ANY, wxT("Content Path:"), wxDefaultPosition, wxDefaultSize, 0 ); + content_file_label->Wrap( -1 ); + content_sizer->Add( content_file_label, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 ); + + content_file_picker_ = new wxFilePickerCtrl( root_panel, wxID_ANY, wxEmptyString, wxT("Select the source content path"), wxT("*.xex;*.iso;*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL ); + content_sizer->Add( content_file_picker_, 1, wxALIGN_CENTER|wxALL|wxEXPAND, 5 ); + + + root_sizer->Add( content_sizer, 0, wxEXPAND, 5 ); + + dialog_buttons_ = new wxStdDialogButtonSizer(); + dialog_buttons_OK = new wxButton( root_panel, wxID_OK ); + dialog_buttons_->AddButton( dialog_buttons_OK ); + dialog_buttons_Cancel = new wxButton( root_panel, wxID_CANCEL ); + dialog_buttons_->AddButton( dialog_buttons_Cancel ); + dialog_buttons_->Realize(); + + root_sizer->Add( dialog_buttons_, 1, wxEXPAND, 0 ); + + + root_panel->SetSizer( root_sizer ); + root_panel->Layout(); + root_sizer->Fit( root_panel ); + root_panel_outer->Add( root_panel, 1, wxEXPAND | wxALL, 10 ); + + + this->SetSizer( root_panel_outer ); + this->Layout(); + root_panel_outer->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + dialog_buttons_Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OpenPostmortemTraceDialogBase::OnCancelButtonClick ), NULL, this ); + dialog_buttons_OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OpenPostmortemTraceDialogBase::OnOKButtonClick ), NULL, this ); +} + +OpenPostmortemTraceDialogBase::~OpenPostmortemTraceDialogBase() +{ + // Disconnect Events + dialog_buttons_Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OpenPostmortemTraceDialogBase::OnCancelButtonClick ), NULL, this ); + dialog_buttons_OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( OpenPostmortemTraceDialogBase::OnOKButtonClick ), NULL, this ); + +} diff --git a/src/xdb/ui/xdb_ui.h b/src/xdb/ui/xdb_ui.h index 421f89942..31e418046 100644 --- a/src/xdb/ui/xdb_ui.h +++ b/src/xdb/ui/xdb_ui.h @@ -25,6 +25,11 @@ #include #include #include +#include +#include +#include +#include +#include /////////////////////////////////////////////////////////////////////////// @@ -41,7 +46,7 @@ namespace xdb protected: wxMenuBar* menu_bar_; - wxMenu* file; + wxMenu* file_menu_; wxAuiToolBar* tool_bar_; wxAuiToolBarItem* tool_test_; wxStatusBar* status_bar_; @@ -58,6 +63,32 @@ namespace xdb }; + /////////////////////////////////////////////////////////////////////////////// + /// Class OpenPostmortemTraceDialogBase + /////////////////////////////////////////////////////////////////////////////// + class OpenPostmortemTraceDialogBase : public wxDialog + { + private: + + protected: + wxFilePickerCtrl* trace_file_picker_; + wxFilePickerCtrl* content_file_picker_; + wxStdDialogButtonSizer* dialog_buttons_; + wxButton* dialog_buttons_OK; + wxButton* dialog_buttons_Cancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnCancelButtonClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOKButtonClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + OpenPostmortemTraceDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Open Postmortem Trace"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~OpenPostmortemTraceDialogBase(); + + }; + } // namespace ui } // namespace xdb diff --git a/src/xdb/xdb_app.cc b/src/xdb/xdb_app.cc index b91672189..2da4cf668 100644 --- a/src/xdb/xdb_app.cc +++ b/src/xdb/xdb_app.cc @@ -9,21 +9,123 @@ #include +#include +#include +#include + +#include +#include +#include +#include +#include + namespace xdb { IMPLEMENT_APP(XdbApp); -bool XdbApp::OnInit() { - main_frame_.reset(new ui::MainFrame()); - - main_frame_->Show(); - return true; -} +bool XdbApp::OnInit() { return true; } int XdbApp::OnExit() { // Top level windows are deleted by wx automatically. - main_frame_.release(); return 0; } +void XdbApp::OpenEmpty() { + while (true) { + ui::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 ui::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 xdb diff --git a/src/xdb/xdb_app.h b/src/xdb/xdb_app.h index b373ab7fe..1aa607042 100644 --- a/src/xdb/xdb_app.h +++ b/src/xdb/xdb_app.h @@ -11,10 +11,18 @@ #define XDB_XDB_APP_H_ #include +#include +#include -#include +#include #include +namespace xdb { +namespace ui { +class MainFrame; +} // namespace ui +} // namespace xdb + namespace xdb { class XdbApp : public wxApp { @@ -22,8 +30,19 @@ class XdbApp : public wxApp { bool OnInit() override; int OnExit() override; + void OpenEmpty(); + bool OpenTraceFile(const std::string& trace_file_path, + const std::string& content_file_path = ""); + bool OpenTraceFile(const std::wstring& trace_file_path, + const std::wstring& content_file_path = L""); + bool OpenDebugTarget(std::unique_ptr debug_target); + private: - std::unique_ptr main_frame_; + void HandleOpenError(const std::string& message); + + void OnMainFrameDestroy(wxEvent& event); + + std::vector main_frames_; }; } // namespace xdb diff --git a/tools/xenia-debug/xenia-debug.cc b/tools/xenia-debug/xenia-debug.cc index 6fc239eb6..090975438 100644 --- a/tools/xenia-debug/xenia-debug.cc +++ b/tools/xenia-debug/xenia-debug.cc @@ -16,6 +16,10 @@ #include #include +DEFINE_string(trace_file, "", "Trace file to load on startup."); +DEFINE_string(content_file, "", + "ISO/STFS/XEX file the specified trace_file should reference."); + namespace xdb { int main(int argc, xechar_t** argv) { @@ -44,6 +48,14 @@ int main(int argc, xechar_t** argv) { XEFATAL("Failed to init app"); return 1; } + + if (!FLAGS_trace_file.empty()) { + // Trace file specified on command line. + app->OpenTraceFile(FLAGS_trace_file, FLAGS_content_file); + } else { + app->OpenEmpty(); + } + app->OnRun(); int result_code = app->OnExit(); wxEntryCleanup();