diff --git a/src/alloy/backend/ivm/ivm_intcode.cc b/src/alloy/backend/ivm/ivm_intcode.cc index b9122604d..6d38409ac 100644 --- a/src/alloy/backend/ivm/ivm_intcode.cc +++ b/src/alloy/backend/ivm/ivm_intcode.cc @@ -249,7 +249,6 @@ int Translate_SOURCE_OFFSET(TranslationContext& ctx, Instr* i) { // TODO(benvanik): dispatch of register forms. uint32_t IntCode_TRACE_SOURCE(IntCodeState& ics, const IntCode* i) { - // TODO(benvanik): append to active trace writer. uint64_t trace_base = ics.thread_state->memory()->trace_base(); if (trace_base) { auto ev = xdb::protocol::InstrEvent::Append(trace_base); @@ -323,7 +322,7 @@ uint32_t IntCode_TRAP(IntCodeState& ics, const IntCode* i) { switch (i->flags) { case 20: // 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length - break; + return IA_NEXT; case 22: // Always trap? break; diff --git a/src/alloy/delegate.h b/src/alloy/delegate.h index 53d4eae72..1c6ca5f42 100644 --- a/src/alloy/delegate.h +++ b/src/alloy/delegate.h @@ -20,6 +20,9 @@ namespace alloy { // TODO(benvanik): go lockfree, and don't hold the lock while emitting. +template +class Delegate; + template class Delegate { public: @@ -30,16 +33,6 @@ class Delegate { listeners_.push_back(listener); } - void RemoveListener(Listener const& listener) { - std::lock_guard guard(lock_); - for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { - if (it == listener) { - listeners_.erase(it); - break; - } - } - } - void RemoveAllListeners() { std::lock_guard guard(lock_); listeners_.clear(); @@ -57,6 +50,33 @@ class Delegate { std::vector listeners_; }; +template <> +class Delegate { + public: + typedef std::function Listener; + + void AddListener(Listener const& listener) { + std::lock_guard guard(lock_); + listeners_.push_back(listener); + } + + void RemoveAllListeners() { + std::lock_guard guard(lock_); + listeners_.clear(); + } + + void operator()() { + std::lock_guard guard(lock_); + for (auto& listener : listeners_) { + listener(); + } + } + + private: + std::mutex lock_; + std::vector listeners_; +}; + } // namespace alloy #endif // ALLOY_DELEGATE_H_ diff --git a/src/xdb/cursor.cc b/src/xdb/cursor.cc new file mode 100644 index 000000000..13d9a2174 --- /dev/null +++ b/src/xdb/cursor.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/cursor.h b/src/xdb/cursor.h new file mode 100644 index 000000000..8c9fa2481 --- /dev/null +++ b/src/xdb/cursor.h @@ -0,0 +1,57 @@ +/** + ****************************************************************************** + * 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_CURSOR_H_ +#define XDB_CURSOR_H_ + +#include + +#include +#include +#include +#include + +namespace xdb { + +class Cursor { + public: + virtual ~Cursor() = default; + + virtual bool can_step() const = 0; + + // TODO(benvanik): breakpoints/events + + alloy::Delegate end_of_stream; + + std::vector modules(); + std::vector threads(); + + alloy::Delegate module_loaded; + alloy::Delegate module_unloaded; + alloy::Delegate thread_created; + alloy::Delegate thread_exited; + + // TODO(benvanik): memory access + + virtual void Continue(Thread* thread = nullptr) = 0; + virtual void ContinueTo(uint32_t address, Thread* thread = nullptr) = 0; + virtual void ContinueToNextCall(Thread* thread = nullptr) = 0; + virtual void ContinueToReturn(Thread* thread = nullptr) = 0; + virtual void ContinueUntil( + const std::function predicate, + Thread* thread = nullptr) = 0; + virtual void Break() = 0; + + protected: + Cursor() = default; +}; + +} // namespace xdb + +#endif // XDB_CURSOR_H_ diff --git a/src/xdb/debug_target.cc b/src/xdb/debug_target.cc index 65b1ea810..7baa9b5b1 100644 --- a/src/xdb/debug_target.cc +++ b/src/xdb/debug_target.cc @@ -27,4 +27,16 @@ bool DebugTarget::InitializeFileSystem(const std::wstring& path) { return true; } +Module* DebugTarget::GetModule(uint16_t module_id) { + std::lock_guard lock(object_lock_); + auto it = module_map_.find(module_id); + return it != module_map_.end() ? it->second : nullptr; +} + +Thread* DebugTarget::GetThread(uint16_t thread_id) { + std::lock_guard lock(object_lock_); + auto it = thread_map_.find(thread_id); + return it != thread_map_.end() ? it->second : nullptr; +} + } // namespace xdb diff --git a/src/xdb/debug_target.h b/src/xdb/debug_target.h index 7724daefd..41ec61d69 100644 --- a/src/xdb/debug_target.h +++ b/src/xdb/debug_target.h @@ -10,6 +10,12 @@ #ifndef XDB_DEBUG_TARGET_H_ #define XDB_DEBUG_TARGET_H_ +#include +#include +#include +#include + +#include #include namespace xdb { @@ -20,12 +26,23 @@ class DebugTarget { xe::kernel::fs::FileSystem* file_system() const { return file_system_.get(); } + virtual std::unique_ptr CreateCursor() = 0; + + Module* GetModule(uint16_t module_id); + Thread* GetThread(uint16_t thread_id); + protected: DebugTarget() = default; bool InitializeFileSystem(const std::wstring& path); std::unique_ptr file_system_; + + std::mutex object_lock_; + std::vector> modules_; + std::vector> threads_; + std::unordered_map module_map_; + std::unordered_map thread_map_; }; } // namespace xdb diff --git a/src/xdb/module.cc b/src/xdb/module.cc new file mode 100644 index 000000000..897ebb39a --- /dev/null +++ b/src/xdb/module.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/module.h b/src/xdb/module.h new file mode 100644 index 000000000..8be42b0be --- /dev/null +++ b/src/xdb/module.h @@ -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. * + ****************************************************************************** + */ + +#ifndef XDB_MODULE_H_ +#define XDB_MODULE_H_ + +#include + +namespace xdb { + +class Module { + public: + uint16_t module_id; + // info +}; + +} // namespace xdb + +#endif // XDB_MODULE_H_ diff --git a/src/xdb/postmortem_cursor.cc b/src/xdb/postmortem_cursor.cc new file mode 100644 index 000000000..c1e6e3e00 --- /dev/null +++ b/src/xdb/postmortem_cursor.cc @@ -0,0 +1,181 @@ +/** + ****************************************************************************** + * 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 + +namespace xdb { + +using xdb::protocol::EventType; + +struct Command { + enum class Type { + EXIT, + CONTINUE, + }; + Type type; + + protected: + Command(Type type) : type(type) {} +}; + +struct ExitCommand : public Command { + ExitCommand() : Command(Type::EXIT) {} +}; + +struct ContinueCommand : public Command { + ContinueCommand() : Command(Type::CONTINUE), thread(nullptr) {} + Thread* thread; +}; + +class PostmortemCursor::Executor { + public: + Executor(PostmortemCursor* cursor) : cursor_(cursor), running_(true) { + trace_ptr_ = cursor->target_->trace_base(); + + // Must be last, as it'll spin up here. + thread_ = std::thread(std::bind(&Executor::ExecutionThread, this)); + } + ~Executor() { + running_ = false; + IssueCommand(std::make_unique()); + thread_.join(); + } + + bool eof() const { return eof_; } + + void IssueCommand(std::unique_ptr command) { + { + std::unique_lock lock(queue_lock_); + queue_.push(std::move(command)); + pending_commands_ = true; + } + queue_cond_.notify_one(); + } + + private: + void ExecutionThread() { + while (running_) { + auto command = AwaitCommand(); + if (!running_ || !command || command->type == Command::Type::EXIT) { + break; + } + + switch (command->type) { + case Command::Type::CONTINUE: { + auto cmd = static_cast(command.get()); + cmd->thread; + break; + } + } + + // + Process(pending_commands_); + } + } + + void Process(std::atomic& exit_signal) { + if (eof_) { + return; + } + while (!exit_signal) { + auto event_type = poly::load(trace_ptr_); + switch (event_type) { + case EventType::END_OF_STREAM: { + eof_= true; + cursor_->end_of_stream(); + return; + } + case EventType::MODULE_LOAD: { + auto ev = protocol::ModuleLoadEvent::Get(trace_ptr_); + break; + } + case EventType::MODULE_UNLOAD: { + auto ev = protocol::ModuleLoadEvent::Get(trace_ptr_); + break; + } + case EventType::THREAD_CREATE: { + auto ev = protocol::ThreadCreateEvent::Get(trace_ptr_); + break; + } + case EventType::THREAD_INFO: { + auto ev = protocol::ThreadInfoEvent::Get(trace_ptr_); + break; + } + case EventType::THREAD_EXIT: { + auto ev = protocol::ThreadExitEvent::Get(trace_ptr_); + break; + } + } + trace_ptr_ += protocol::kEventSizes[static_cast(event_type)]; + } + } + + std::unique_ptr AwaitCommand() { + std::unique_lock lock(queue_lock_); + while (queue_.empty()) { + queue_cond_.wait(lock); + } + auto command = std::move(queue_.front()); + queue_.pop(); + pending_commands_ = !queue_.empty(); + return command; + } + + PostmortemCursor* cursor_; + std::atomic running_; + const uint8_t* trace_ptr_; + std::atomic eof_; + std::thread thread_; + + std::queue> queue_; + std::mutex queue_lock_; + std::condition_variable queue_cond_; + std::atomic pending_commands_; +}; + +PostmortemCursor::PostmortemCursor(PostmortemDebugTarget* target) + : target_(target) { + executor_.reset(new Executor(this)); +} + +PostmortemCursor::~PostmortemCursor() { executor_.reset(); } + +bool PostmortemCursor::can_step() const { + // TODO(benvanik): check trace flags. + return true; +} + +void PostmortemCursor::Continue(Thread* thread) { + auto cmd = std::make_unique(); + cmd->thread = thread; + executor_->IssueCommand(std::move(cmd)); +} + +void PostmortemCursor::ContinueTo(uint32_t address, Thread* thread) {} + +void PostmortemCursor::ContinueToNextCall(Thread* thread) {} + +void PostmortemCursor::ContinueToReturn(Thread* thread) {} + +void PostmortemCursor::ContinueUntil( + const std::function predicate, + Thread* thread) {} + +void PostmortemCursor::Break() {} + +} // namespace xdb diff --git a/src/xdb/postmortem_cursor.h b/src/xdb/postmortem_cursor.h new file mode 100644 index 000000000..e8d3595cc --- /dev/null +++ b/src/xdb/postmortem_cursor.h @@ -0,0 +1,46 @@ +/** + ****************************************************************************** + * 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_CURSOR_H_ +#define XDB_POSTMORTEM_CURSOR_H_ + +#include + +#include + +namespace xdb { + +class PostmortemDebugTarget; + +class PostmortemCursor : public Cursor { + public: + PostmortemCursor(PostmortemDebugTarget* target); + ~PostmortemCursor() override; + + bool can_step() const override; + + void Continue(Thread* thread = nullptr) override; + void ContinueTo(uint32_t address, Thread* thread = nullptr) override; + void ContinueToNextCall(Thread* thread = nullptr) override; + void ContinueToReturn(Thread* thread = nullptr) override; + void ContinueUntil( + const std::function predicate, + Thread* thread = nullptr) override; + void Break() override; + + private: + class Executor; + + PostmortemDebugTarget* target_; + std::unique_ptr executor_; +}; + +} // namespace xdb + +#endif // XDB_POSTMORTEM_CURSOR_H_ diff --git a/src/xdb/postmortem_debug_target.cc b/src/xdb/postmortem_debug_target.cc index 6a3009385..ffad63348 100644 --- a/src/xdb/postmortem_debug_target.cc +++ b/src/xdb/postmortem_debug_target.cc @@ -10,37 +10,13 @@ #include #include +#include #include namespace xdb { using xdb::protocol::EventType; -// Matches the EventType ordering to allow for quick event size checks. -const size_t event_sizes[] = { - 0, - sizeof(protocol::ProcessStartEvent), - sizeof(protocol::ProcessExitEvent), - sizeof(protocol::ModuleLoadEvent), - sizeof(protocol::ModuleUnloadEvent), - sizeof(protocol::ThreadCreateEvent), - sizeof(protocol::ThreadInfoEvent), - sizeof(protocol::ThreadExitEvent), - sizeof(protocol::FunctionCompiledEvent), - sizeof(protocol::OutputStringEvent), - sizeof(protocol::KernelCallEvent), - sizeof(protocol::KernelCallReturnEvent), - sizeof(protocol::UserCallEvent), - sizeof(protocol::UserCallReturnEvent), - sizeof(protocol::InstrEvent), - sizeof(protocol::InstrEventR8), - sizeof(protocol::InstrEventR8R8), - sizeof(protocol::InstrEventR8R16), - sizeof(protocol::InstrEventR16), - sizeof(protocol::InstrEventR16R8), - sizeof(protocol::InstrEventR16R16), -}; - PostmortemDebugTarget::PostmortemDebugTarget() : file_(nullptr), file_mapping_(nullptr), @@ -66,8 +42,8 @@ bool PostmortemDebugTarget::LoadTrace(const std::wstring& path, return false; } - file_mapping_ = CreateFileMapping(file_, nullptr, PAGE_READONLY, 0, 0, - L"Local\\xenia_xdb_trace"); + file_mapping_ = + CreateFileMapping(file_, nullptr, PAGE_READONLY, 0, 0, nullptr); if (!file_mapping_) { XELOGE("Could not create trace file mapping"); return false; @@ -95,7 +71,7 @@ bool PostmortemDebugTarget::LoadTrace(const std::wstring& path, if (process_start_event_) { break; } - ptr += event_sizes[static_cast(event_type)]; + ptr += protocol::kEventSizes[static_cast(event_type)]; } bool initialized_filesystem = false; @@ -129,7 +105,8 @@ bool PostmortemDebugTarget::Prepare(std::atomic& cancelled) { EventType::END_OF_STREAM) { switch (event_type) { case EventType::PROCESS_START: { - process_start_event_ = protocol::ProcessStartEvent::Get(ptr); + assert_true(process_start_event_ == + protocol::ProcessStartEvent::Get(ptr)); break; } case EventType::PROCESS_EXIT: { @@ -209,10 +186,17 @@ bool PostmortemDebugTarget::Prepare(std::atomic& cancelled) { break; } } - ptr += event_sizes[static_cast(event_type)]; + ptr += protocol::kEventSizes[static_cast(event_type)]; }; + trace_length_ = ptr - trace_base_; + return true; } +std::unique_ptr PostmortemDebugTarget::CreateCursor() { + auto cursor = std::make_unique(this); + return std::unique_ptr(cursor.release()); +} + } // namespace xdb diff --git a/src/xdb/postmortem_debug_target.h b/src/xdb/postmortem_debug_target.h index 6f4575337..715b64456 100644 --- a/src/xdb/postmortem_debug_target.h +++ b/src/xdb/postmortem_debug_target.h @@ -25,16 +25,22 @@ class PostmortemDebugTarget : public DebugTarget { PostmortemDebugTarget(); ~PostmortemDebugTarget() override; + const uint8_t* trace_base() const { return trace_base_ + 8; } + size_t trace_length() const { return trace_length_; } + bool LoadTrace(const std::wstring& path, const std::wstring& content_path = L""); bool Prepare(); bool Prepare(std::atomic& cancelled); + std::unique_ptr CreateCursor() override; + private: HANDLE file_; HANDLE file_mapping_; const uint8_t* trace_base_; + size_t trace_length_; const protocol::ProcessStartEvent* process_start_event_; const protocol::ProcessExitEvent* process_exit_event_; diff --git a/src/xdb/protocol.h b/src/xdb/protocol.h index b1b4be039..85536ab9f 100644 --- a/src/xdb/protocol.h +++ b/src/xdb/protocol.h @@ -77,14 +77,9 @@ struct ProcessExitEvent : public Event { EventType type; }; -struct ModuleInfo { - uint32_t module_id; -}; - struct ModuleLoadEvent : public Event { EventType type; uint32_t module_id; - ModuleInfo module_info; }; struct ModuleUnloadEvent : public Event { @@ -227,6 +222,31 @@ struct InstrEventR16R16 : public Event { #pragma pack(pop) +// Matches the EventType ordering to allow for quick event size checks. +const size_t kEventSizes[] = { + 0, + sizeof(protocol::ProcessStartEvent), + sizeof(protocol::ProcessExitEvent), + sizeof(protocol::ModuleLoadEvent), + sizeof(protocol::ModuleUnloadEvent), + sizeof(protocol::ThreadCreateEvent), + sizeof(protocol::ThreadInfoEvent), + sizeof(protocol::ThreadExitEvent), + sizeof(protocol::FunctionCompiledEvent), + sizeof(protocol::OutputStringEvent), + sizeof(protocol::KernelCallEvent), + sizeof(protocol::KernelCallReturnEvent), + sizeof(protocol::UserCallEvent), + sizeof(protocol::UserCallReturnEvent), + sizeof(protocol::InstrEvent), + sizeof(protocol::InstrEventR8), + sizeof(protocol::InstrEventR8R8), + sizeof(protocol::InstrEventR8R16), + sizeof(protocol::InstrEventR16), + sizeof(protocol::InstrEventR16R8), + sizeof(protocol::InstrEventR16R16), +}; + } // namespace protocol } // namespace xdb diff --git a/src/xdb/sources.gypi b/src/xdb/sources.gypi index eec8b4a15..8f052078f 100644 --- a/src/xdb/sources.gypi +++ b/src/xdb/sources.gypi @@ -1,11 +1,19 @@ # Copyright 2014 Ben Vanik. All Rights Reserved. { 'sources': [ + 'cursor.cc', + 'cursor.h', 'debug_target.cc', 'debug_target.h', + 'module.cc', + 'module.h', + 'postmortem_cursor.cc', + 'postmortem_cursor.h', 'postmortem_debug_target.cc', 'postmortem_debug_target.h', 'protocol.h', + 'thread.cc', + 'thread.h', 'xdb.cc', 'xdb.h', ], diff --git a/src/xdb/thread.cc b/src/xdb/thread.cc new file mode 100644 index 000000000..163c979ce --- /dev/null +++ b/src/xdb/thread.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/thread.h b/src/xdb/thread.h new file mode 100644 index 000000000..425b45c44 --- /dev/null +++ b/src/xdb/thread.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_THREAD_H_ +#define XDB_THREAD_H_ + +#include + +namespace xdb { + +class Thread { + public: + uint16_t thread_id; + // name + // etc +}; + +} // namespace xdb + +#endif // XDB_THREAD_H_ diff --git a/src/xdb/ui/main_frame.cc b/src/xdb/ui/main_frame.cc index 1542435d6..08453647f 100644 --- a/src/xdb/ui/main_frame.cc +++ b/src/xdb/ui/main_frame.cc @@ -13,7 +13,32 @@ namespace xdb { namespace ui { MainFrame::MainFrame(std::unique_ptr debug_target) - : MainFrameBase(nullptr), debug_target_(std::move(debug_target)) {} + : MainFrameBase(nullptr), debug_target_(std::move(debug_target)) { + cursor_ = std::move(debug_target_->CreateCursor()); + cursor_->end_of_stream.AddListener([]() { + XELOGI("eos"); + }); + cursor_->module_loaded.AddListener([](Module* module) { + // + XELOGI("mod load"); + }); + cursor_->module_unloaded.AddListener([](Module* module) { + // + XELOGI("mod unload"); + }); + cursor_->thread_created.AddListener([](Thread* thread) { + // + XELOGI("thread create"); + }); + cursor_->thread_exited.AddListener([](Thread* thread) { + // + XELOGI("thread exit"); + }); + cursor_->Continue(); +} + +void MainFrame::OnIdle(wxIdleEvent& event) { +} } // namespace ui } // namespace xdb diff --git a/src/xdb/ui/main_frame.h b/src/xdb/ui/main_frame.h index 2c7228dcc..eae87642d 100644 --- a/src/xdb/ui/main_frame.h +++ b/src/xdb/ui/main_frame.h @@ -23,10 +23,11 @@ class MainFrame : public MainFrameBase { MainFrame(std::unique_ptr debug_target); protected: - // + void OnIdle(wxIdleEvent& event) override; private: - std::unique_ptr debug_target_; + std::unique_ptr debug_target_; + std::unique_ptr cursor_; }; } // namespace ui diff --git a/src/xdb/ui/xdb-ui.fbp b/src/xdb/ui/xdb-ui.fbp index 7166732f5..0c3a7aca3 100644 --- a/src/xdb/ui/xdb-ui.fbp +++ b/src/xdb/ui/xdb-ui.fbp @@ -67,7 +67,7 @@ - + OnIdle @@ -536,7 +536,7 @@ - + 0 @@ -598,16 +598,16 @@ - + root_panel_outer wxVERTICAL none - + 10 wxEXPAND | wxALL 1 - + 1 1 1 @@ -681,7 +681,7 @@ - + 1 wxVERTICAL 0 @@ -693,11 +693,11 @@ none 0 0 - + 5 wxALL 0 - + 1 1 1 @@ -776,11 +776,11 @@ - + 5 wxEXPAND 0 - + 2 wxBOTH 1 @@ -1138,11 +1138,11 @@ - + 0 wxEXPAND 1 - + 0 1 0 diff --git a/src/xdb/ui/xdb_ui.cpp b/src/xdb/ui/xdb_ui.cpp index 0ec24af81..28e247680 100644 --- a/src/xdb/ui/xdb_ui.cpp +++ b/src/xdb/ui/xdb_ui.cpp @@ -40,10 +40,16 @@ MainFrameBase::MainFrameBase( wxWindow* parent, wxWindowID id, const wxString& t m_mgr.Update(); this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_IDLE, wxIdleEventHandler( MainFrameBase::OnIdle ) ); } MainFrameBase::~MainFrameBase() { + // Disconnect Events + this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( MainFrameBase::OnIdle ) ); + m_mgr.UnInit(); } diff --git a/src/xdb/ui/xdb_ui.h b/src/xdb/ui/xdb_ui.h index 31e418046..778cfeddc 100644 --- a/src/xdb/ui/xdb_ui.h +++ b/src/xdb/ui/xdb_ui.h @@ -53,6 +53,10 @@ namespace xdb wxAuiNotebook* notebook_; wxPanel* m_panel3; wxPanel* m_panel4; + + // Virtual event handlers, overide them in your derived class + virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); } + public: diff --git a/tools/tools.gypi b/tools/tools.gypi index ab8e44c99..3e6a56ffd 100644 --- a/tools/tools.gypi +++ b/tools/tools.gypi @@ -2,6 +2,7 @@ { 'includes': [ 'alloy-sandbox/alloy-sandbox.gypi', + 'xenia-compare/xenia-compare.gypi', 'xenia-debug/xenia-debug.gypi', 'xenia-run/xenia-run.gypi', #'xenia-test/xenia-test.gypi', diff --git a/tools/xenia-compare/xenia-compare.cc b/tools/xenia-compare/xenia-compare.cc new file mode 100644 index 000000000..7fb6c9488 --- /dev/null +++ b/tools/xenia-compare/xenia-compare.cc @@ -0,0 +1,51 @@ +/** + ****************************************************************************** + * 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 + +DEFINE_string(trace_file_left, "", "Trace file to compare (original)."); +DEFINE_string(trace_file_right, "", "Trace file to compare (new)."); + +namespace xc { + +using xdb::PostmortemDebugTarget; + +int main(int argc, xechar_t** argv) { + // Create platform abstraction layer. + xe_pal_options_t pal_options; + xe_zero_struct(&pal_options, sizeof(pal_options)); + if (xe_pal_init(pal_options)) { + XEFATAL("Failed to initialize PAL"); + return 1; + } + + auto left_target = std::make_unique(); + if (!left_target->LoadTrace(poly::to_wstring(FLAGS_trace_file_left))) { + XEFATAL("Unable to load left trace file: %s", + FLAGS_trace_file_left.c_str()); + } + auto right_target = std::make_unique(); + if (!right_target->LoadTrace(poly::to_wstring(FLAGS_trace_file_right))) { + XEFATAL("Unable to load right trace file: %s", + FLAGS_trace_file_right.c_str()); + } + + return 0; +} + +} // namespace xc + +// TODO(benvanik): move main thunk into poly +// ehhh +XE_MAIN_WINDOW_THUNK(xc::main, L"xenia-compare", "xenia-compare"); diff --git a/tools/xenia-compare/xenia-compare.gypi b/tools/xenia-compare/xenia-compare.gypi new file mode 100644 index 000000000..2b43a2883 --- /dev/null +++ b/tools/xenia-compare/xenia-compare.gypi @@ -0,0 +1,28 @@ +# Copyright 2014 Ben Vanik. All Rights Reserved. +{ + 'targets': [ + { + 'target_name': 'xenia-compare', + 'type': 'executable', + + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2' + } + }, + + 'dependencies': [ + 'xdb', + 'xenia', + ], + + 'include_dirs': [ + '.', + ], + + 'sources': [ + 'xenia-compare.cc', + ], + }, + ], +}