Experimenting with xdb API, starting on compare tool.

This commit is contained in:
Ben Vanik 2014-08-15 13:53:02 -07:00
parent 3de39aaf10
commit 1a39f5bd06
24 changed files with 627 additions and 62 deletions

View File

@ -249,7 +249,6 @@ int Translate_SOURCE_OFFSET(TranslationContext& ctx, Instr* i) {
// TODO(benvanik): dispatch of register forms. // TODO(benvanik): dispatch of register forms.
uint32_t IntCode_TRACE_SOURCE(IntCodeState& ics, const IntCode* i) { 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(); uint64_t trace_base = ics.thread_state->memory()->trace_base();
if (trace_base) { if (trace_base) {
auto ev = xdb::protocol::InstrEvent::Append(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) { switch (i->flags) {
case 20: case 20:
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length // 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
break; return IA_NEXT;
case 22: case 22:
// Always trap? // Always trap?
break; break;

View File

@ -20,6 +20,9 @@ namespace alloy {
// TODO(benvanik): go lockfree, and don't hold the lock while emitting. // TODO(benvanik): go lockfree, and don't hold the lock while emitting.
template <typename T>
class Delegate;
template <typename T> template <typename T>
class Delegate { class Delegate {
public: public:
@ -30,16 +33,6 @@ class Delegate {
listeners_.push_back(listener); listeners_.push_back(listener);
} }
void RemoveListener(Listener const& listener) {
std::lock_guard<std::mutex> guard(lock_);
for (auto it = listeners_.begin(); it != listeners_.end(); ++it) {
if (it == listener) {
listeners_.erase(it);
break;
}
}
}
void RemoveAllListeners() { void RemoveAllListeners() {
std::lock_guard<std::mutex> guard(lock_); std::lock_guard<std::mutex> guard(lock_);
listeners_.clear(); listeners_.clear();
@ -57,6 +50,33 @@ class Delegate {
std::vector<Listener> listeners_; std::vector<Listener> listeners_;
}; };
template <>
class Delegate<void> {
public:
typedef std::function<void()> Listener;
void AddListener(Listener const& listener) {
std::lock_guard<std::mutex> guard(lock_);
listeners_.push_back(listener);
}
void RemoveAllListeners() {
std::lock_guard<std::mutex> guard(lock_);
listeners_.clear();
}
void operator()() {
std::lock_guard<std::mutex> guard(lock_);
for (auto& listener : listeners_) {
listener();
}
}
private:
std::mutex lock_;
std::vector<Listener> listeners_;
};
} // namespace alloy } // namespace alloy
#endif // ALLOY_DELEGATE_H_ #endif // ALLOY_DELEGATE_H_

16
src/xdb/cursor.cc Normal file
View File

@ -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 <xdb/cursor.h>
namespace xdb {
//
} // namespace xdb

57
src/xdb/cursor.h Normal file
View File

@ -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 <functional>
#include <alloy/delegate.h>
#include <xdb/module.h>
#include <xdb/protocol.h>
#include <xdb/thread.h>
namespace xdb {
class Cursor {
public:
virtual ~Cursor() = default;
virtual bool can_step() const = 0;
// TODO(benvanik): breakpoints/events
alloy::Delegate<void> end_of_stream;
std::vector<Module*> modules();
std::vector<Thread*> threads();
alloy::Delegate<Module*> module_loaded;
alloy::Delegate<Module*> module_unloaded;
alloy::Delegate<Thread*> thread_created;
alloy::Delegate<Thread*> 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<bool(protocol::EventType, uint8_t*)> predicate,
Thread* thread = nullptr) = 0;
virtual void Break() = 0;
protected:
Cursor() = default;
};
} // namespace xdb
#endif // XDB_CURSOR_H_

View File

@ -27,4 +27,16 @@ bool DebugTarget::InitializeFileSystem(const std::wstring& path) {
return true; return true;
} }
Module* DebugTarget::GetModule(uint16_t module_id) {
std::lock_guard<std::mutex> 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<std::mutex> lock(object_lock_);
auto it = thread_map_.find(thread_id);
return it != thread_map_.end() ? it->second : nullptr;
}
} // namespace xdb } // namespace xdb

View File

@ -10,6 +10,12 @@
#ifndef XDB_DEBUG_TARGET_H_ #ifndef XDB_DEBUG_TARGET_H_
#define XDB_DEBUG_TARGET_H_ #define XDB_DEBUG_TARGET_H_
#include <memory>
#include <mutex>
#include <unordered_map>
#include <vector>
#include <xdb/cursor.h>
#include <xenia/kernel/fs/filesystem.h> #include <xenia/kernel/fs/filesystem.h>
namespace xdb { namespace xdb {
@ -20,12 +26,23 @@ class DebugTarget {
xe::kernel::fs::FileSystem* file_system() const { return file_system_.get(); } xe::kernel::fs::FileSystem* file_system() const { return file_system_.get(); }
virtual std::unique_ptr<Cursor> CreateCursor() = 0;
Module* GetModule(uint16_t module_id);
Thread* GetThread(uint16_t thread_id);
protected: protected:
DebugTarget() = default; DebugTarget() = default;
bool InitializeFileSystem(const std::wstring& path); bool InitializeFileSystem(const std::wstring& path);
std::unique_ptr<xe::kernel::fs::FileSystem> file_system_; std::unique_ptr<xe::kernel::fs::FileSystem> file_system_;
std::mutex object_lock_;
std::vector<std::unique_ptr<Module>> modules_;
std::vector<std::unique_ptr<Thread>> threads_;
std::unordered_map<uint16_t, Module*> module_map_;
std::unordered_map<uint16_t, Thread*> thread_map_;
}; };
} // namespace xdb } // namespace xdb

16
src/xdb/module.cc Normal file
View File

@ -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 <xdb/module.h>
namespace xdb {
//
} // namespace xdb

25
src/xdb/module.h Normal file
View File

@ -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 <cstdint>
namespace xdb {
class Module {
public:
uint16_t module_id;
// info
};
} // namespace xdb
#endif // XDB_MODULE_H_

View File

@ -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 <xdb/postmortem_cursor.h>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <thread>
#include <xdb/postmortem_debug_target.h>
#include <xdb/protocol.h>
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<ExitCommand>());
thread_.join();
}
bool eof() const { return eof_; }
void IssueCommand(std::unique_ptr<Command> command) {
{
std::unique_lock<std::mutex> 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<ContinueCommand*>(command.get());
cmd->thread;
break;
}
}
//
Process(pending_commands_);
}
}
void Process(std::atomic<bool>& exit_signal) {
if (eof_) {
return;
}
while (!exit_signal) {
auto event_type = poly::load<EventType>(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<uint8_t>(event_type)];
}
}
std::unique_ptr<Command> AwaitCommand() {
std::unique_lock<std::mutex> 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<bool> running_;
const uint8_t* trace_ptr_;
std::atomic<bool> eof_;
std::thread thread_;
std::queue<std::unique_ptr<Command>> queue_;
std::mutex queue_lock_;
std::condition_variable queue_cond_;
std::atomic<bool> 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<ContinueCommand>();
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<bool(protocol::EventType, uint8_t*)> predicate,
Thread* thread) {}
void PostmortemCursor::Break() {}
} // namespace xdb

View File

@ -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 <memory>
#include <xdb/cursor.h>
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<bool(protocol::EventType, uint8_t*)> predicate,
Thread* thread = nullptr) override;
void Break() override;
private:
class Executor;
PostmortemDebugTarget* target_;
std::unique_ptr<Executor> executor_;
};
} // namespace xdb
#endif // XDB_POSTMORTEM_CURSOR_H_

View File

@ -10,37 +10,13 @@
#include <xdb/postmortem_debug_target.h> #include <xdb/postmortem_debug_target.h>
#include <poly/poly.h> #include <poly/poly.h>
#include <xdb/postmortem_cursor.h>
#include <xenia/logging.h> #include <xenia/logging.h>
namespace xdb { namespace xdb {
using xdb::protocol::EventType; 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() PostmortemDebugTarget::PostmortemDebugTarget()
: file_(nullptr), : file_(nullptr),
file_mapping_(nullptr), file_mapping_(nullptr),
@ -66,8 +42,8 @@ bool PostmortemDebugTarget::LoadTrace(const std::wstring& path,
return false; return false;
} }
file_mapping_ = CreateFileMapping(file_, nullptr, PAGE_READONLY, 0, 0, file_mapping_ =
L"Local\\xenia_xdb_trace"); CreateFileMapping(file_, nullptr, PAGE_READONLY, 0, 0, nullptr);
if (!file_mapping_) { if (!file_mapping_) {
XELOGE("Could not create trace file mapping"); XELOGE("Could not create trace file mapping");
return false; return false;
@ -95,7 +71,7 @@ bool PostmortemDebugTarget::LoadTrace(const std::wstring& path,
if (process_start_event_) { if (process_start_event_) {
break; break;
} }
ptr += event_sizes[static_cast<uint8_t>(event_type)]; ptr += protocol::kEventSizes[static_cast<uint8_t>(event_type)];
} }
bool initialized_filesystem = false; bool initialized_filesystem = false;
@ -129,7 +105,8 @@ bool PostmortemDebugTarget::Prepare(std::atomic<bool>& cancelled) {
EventType::END_OF_STREAM) { EventType::END_OF_STREAM) {
switch (event_type) { switch (event_type) {
case EventType::PROCESS_START: { case EventType::PROCESS_START: {
process_start_event_ = protocol::ProcessStartEvent::Get(ptr); assert_true(process_start_event_ ==
protocol::ProcessStartEvent::Get(ptr));
break; break;
} }
case EventType::PROCESS_EXIT: { case EventType::PROCESS_EXIT: {
@ -209,10 +186,17 @@ bool PostmortemDebugTarget::Prepare(std::atomic<bool>& cancelled) {
break; break;
} }
} }
ptr += event_sizes[static_cast<uint8_t>(event_type)]; ptr += protocol::kEventSizes[static_cast<uint8_t>(event_type)];
}; };
trace_length_ = ptr - trace_base_;
return true; return true;
} }
std::unique_ptr<Cursor> PostmortemDebugTarget::CreateCursor() {
auto cursor = std::make_unique<PostmortemCursor>(this);
return std::unique_ptr<Cursor>(cursor.release());
}
} // namespace xdb } // namespace xdb

View File

@ -25,16 +25,22 @@ class PostmortemDebugTarget : public DebugTarget {
PostmortemDebugTarget(); PostmortemDebugTarget();
~PostmortemDebugTarget() override; ~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, bool LoadTrace(const std::wstring& path,
const std::wstring& content_path = L""); const std::wstring& content_path = L"");
bool Prepare(); bool Prepare();
bool Prepare(std::atomic<bool>& cancelled); bool Prepare(std::atomic<bool>& cancelled);
std::unique_ptr<Cursor> CreateCursor() override;
private: private:
HANDLE file_; HANDLE file_;
HANDLE file_mapping_; HANDLE file_mapping_;
const uint8_t* trace_base_; const uint8_t* trace_base_;
size_t trace_length_;
const protocol::ProcessStartEvent* process_start_event_; const protocol::ProcessStartEvent* process_start_event_;
const protocol::ProcessExitEvent* process_exit_event_; const protocol::ProcessExitEvent* process_exit_event_;

View File

@ -77,14 +77,9 @@ struct ProcessExitEvent : public Event<ProcessExitEvent> {
EventType type; EventType type;
}; };
struct ModuleInfo {
uint32_t module_id;
};
struct ModuleLoadEvent : public Event<ModuleLoadEvent> { struct ModuleLoadEvent : public Event<ModuleLoadEvent> {
EventType type; EventType type;
uint32_t module_id; uint32_t module_id;
ModuleInfo module_info;
}; };
struct ModuleUnloadEvent : public Event<ModuleUnloadEvent> { struct ModuleUnloadEvent : public Event<ModuleUnloadEvent> {
@ -227,6 +222,31 @@ struct InstrEventR16R16 : public Event<InstrEventR16R16> {
#pragma pack(pop) #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 protocol
} // namespace xdb } // namespace xdb

View File

@ -1,11 +1,19 @@
# Copyright 2014 Ben Vanik. All Rights Reserved. # Copyright 2014 Ben Vanik. All Rights Reserved.
{ {
'sources': [ 'sources': [
'cursor.cc',
'cursor.h',
'debug_target.cc', 'debug_target.cc',
'debug_target.h', 'debug_target.h',
'module.cc',
'module.h',
'postmortem_cursor.cc',
'postmortem_cursor.h',
'postmortem_debug_target.cc', 'postmortem_debug_target.cc',
'postmortem_debug_target.h', 'postmortem_debug_target.h',
'protocol.h', 'protocol.h',
'thread.cc',
'thread.h',
'xdb.cc', 'xdb.cc',
'xdb.h', 'xdb.h',
], ],

16
src/xdb/thread.cc Normal file
View File

@ -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 <xdb/thread.h>
namespace xdb {
//
} // namespace xdb

26
src/xdb/thread.h Normal file
View File

@ -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 <cstdint>
namespace xdb {
class Thread {
public:
uint16_t thread_id;
// name
// etc
};
} // namespace xdb
#endif // XDB_THREAD_H_

View File

@ -13,7 +13,32 @@ namespace xdb {
namespace ui { namespace ui {
MainFrame::MainFrame(std::unique_ptr<DebugTarget> debug_target) MainFrame::MainFrame(std::unique_ptr<DebugTarget> 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 ui
} // namespace xdb } // namespace xdb

View File

@ -23,10 +23,11 @@ class MainFrame : public MainFrameBase {
MainFrame(std::unique_ptr<DebugTarget> debug_target); MainFrame(std::unique_ptr<DebugTarget> debug_target);
protected: protected:
// void OnIdle(wxIdleEvent& event) override;
private: private:
std::unique_ptr<DebugTarget> debug_target_; std::unique_ptr<DebugTarget> debug_target_;
std::unique_ptr<Cursor> cursor_;
}; };
} // namespace ui } // namespace ui

View File

@ -67,7 +67,7 @@
<event name="OnEraseBackground"></event> <event name="OnEraseBackground"></event>
<event name="OnHibernate"></event> <event name="OnHibernate"></event>
<event name="OnIconize"></event> <event name="OnIconize"></event>
<event name="OnIdle"></event> <event name="OnIdle">OnIdle</event>
<event name="OnKeyDown"></event> <event name="OnKeyDown"></event>
<event name="OnKeyUp"></event> <event name="OnKeyUp"></event>
<event name="OnKillFocus"></event> <event name="OnKillFocus"></event>
@ -536,7 +536,7 @@
</object> </object>
</object> </object>
</object> </object>
<object class="Dialog" expanded="1"> <object class="Dialog" expanded="0">
<property name="aui_managed">0</property> <property name="aui_managed">0</property>
<property name="aui_manager_style"></property> <property name="aui_manager_style"></property>
<property name="bg"></property> <property name="bg"></property>
@ -598,16 +598,16 @@
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
<object class="wxBoxSizer" expanded="1"> <object class="wxBoxSizer" expanded="0">
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">root_panel_outer</property> <property name="name">root_panel_outer</property>
<property name="orient">wxVERTICAL</property> <property name="orient">wxVERTICAL</property>
<property name="permission">none</property> <property name="permission">none</property>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">10</property> <property name="border">10</property>
<property name="flag">wxEXPAND | wxALL</property> <property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="wxPanel" expanded="1"> <object class="wxPanel" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
@ -681,7 +681,7 @@
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
<object class="wxFlexGridSizer" expanded="1"> <object class="wxFlexGridSizer" expanded="0">
<property name="cols">1</property> <property name="cols">1</property>
<property name="flexible_direction">wxVERTICAL</property> <property name="flexible_direction">wxVERTICAL</property>
<property name="growablecols">0</property> <property name="growablecols">0</property>
@ -693,11 +693,11 @@
<property name="permission">none</property> <property name="permission">none</property>
<property name="rows">0</property> <property name="rows">0</property>
<property name="vgap">0</property> <property name="vgap">0</property>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALL</property> <property name="flag">wxALL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
@ -776,11 +776,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND</property> <property name="flag">wxEXPAND</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxFlexGridSizer" expanded="1"> <object class="wxFlexGridSizer" expanded="0">
<property name="cols">2</property> <property name="cols">2</property>
<property name="flexible_direction">wxBOTH</property> <property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1</property> <property name="growablecols">1</property>
@ -1138,11 +1138,11 @@
</object> </object>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">0</property> <property name="border">0</property>
<property name="flag">wxEXPAND</property> <property name="flag">wxEXPAND</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="wxStdDialogButtonSizer" expanded="1"> <object class="wxStdDialogButtonSizer" expanded="0">
<property name="Apply">0</property> <property name="Apply">0</property>
<property name="Cancel">1</property> <property name="Cancel">1</property>
<property name="ContextHelp">0</property> <property name="ContextHelp">0</property>

View File

@ -40,10 +40,16 @@ MainFrameBase::MainFrameBase( wxWindow* parent, wxWindowID id, const wxString& t
m_mgr.Update(); m_mgr.Update();
this->Centre( wxBOTH ); this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_IDLE, wxIdleEventHandler( MainFrameBase::OnIdle ) );
} }
MainFrameBase::~MainFrameBase() MainFrameBase::~MainFrameBase()
{ {
// Disconnect Events
this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( MainFrameBase::OnIdle ) );
m_mgr.UnInit(); m_mgr.UnInit();
} }

View File

@ -53,6 +53,10 @@ namespace xdb
wxAuiNotebook* notebook_; wxAuiNotebook* notebook_;
wxPanel* m_panel3; wxPanel* m_panel3;
wxPanel* m_panel4; wxPanel* m_panel4;
// Virtual event handlers, overide them in your derived class
virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); }
public: public:

View File

@ -2,6 +2,7 @@
{ {
'includes': [ 'includes': [
'alloy-sandbox/alloy-sandbox.gypi', 'alloy-sandbox/alloy-sandbox.gypi',
'xenia-compare/xenia-compare.gypi',
'xenia-debug/xenia-debug.gypi', 'xenia-debug/xenia-debug.gypi',
'xenia-run/xenia-run.gypi', 'xenia-run/xenia-run.gypi',
#'xenia-test/xenia-test.gypi', #'xenia-test/xenia-test.gypi',

View File

@ -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 <memory>
#include <gflags/gflags.h>
#include <poly/poly.h>
#include <xdb/postmortem_debug_target.h>
#include <xdb/xdb.h>
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<PostmortemDebugTarget>();
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<PostmortemDebugTarget>();
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");

View File

@ -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',
],
},
],
}