A new debugger.

Lots of bugs/rough edges/etc - issues will be filed.
Old-style debugging still works (just use --emit_source_annotations to get
the helpful movs back and --break_on_instruction will still fire).
This commit is contained in:
Ben Vanik
2015-09-20 21:31:05 -07:00
parent 8046c19898
commit 5d033f9cb3
90 changed files with 4183 additions and 4651 deletions

View File

@@ -1,88 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/application.h"
#include "xenia/base/assert.h"
#include "xenia/base/logging.h"
#include "xenia/base/platform.h"
#include "xenia/base/threading.h"
#include "xenia/debug/ui/main_window.h"
#include "xenia/profiling.h"
namespace xe {
namespace debug {
namespace ui {
Application* current_application_ = nullptr;
Application* Application::current() {
assert_not_null(current_application_);
return current_application_;
}
Application::Application() {
current_application_ = this;
loop_ = xe::ui::Loop::Create();
}
Application::~Application() {
assert_true(current_application_ == this);
current_application_ = nullptr;
}
std::unique_ptr<Application> Application::Create() {
std::unique_ptr<Application> app(new Application());
xe::threading::Fence fence;
app->loop()->Post([&app, &fence]() {
xe::threading::set_name("Win32 Loop");
xe::Profiler::ThreadEnter("Win32 Loop");
if (!app->Initialize()) {
xe::FatalError("Failed to initialize application");
return;
}
fence.Signal();
});
fence.Wait();
return app;
}
bool Application::Initialize() {
// Bind the object model to the client so it'll maintain state.
system_ = std::make_unique<model::System>(loop(), &client_);
// TODO(benvanik): flags and such.
if (!client_.Connect("localhost", 9002)) {
return false;
}
main_window_ = std::make_unique<MainWindow>(this);
if (!main_window_->Initialize()) {
XELOGE("Unable to initialize main window");
return false;
}
return true;
}
void Application::Quit() {
loop_->Quit();
// TODO(benvanik): proper exit.
XELOGI("User-initiated death!");
exit(1);
}
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,55 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_APPLICATION_H_
#define XENIA_DEBUG_UI_APPLICATION_H_
#include <memory>
#include "xenia/debug/debug_client.h"
#include "xenia/debug/ui/model/system.h"
#include "xenia/ui/loop.h"
namespace xe {
namespace debug {
namespace ui {
class MainWindow;
class Application {
public:
~Application();
static std::unique_ptr<Application> Create();
static Application* current();
xe::ui::Loop* loop() { return loop_.get(); }
MainWindow* main_window() const { return main_window_.get(); }
DebugClient* client() { return &client_; }
model::System* system() const { return system_.get(); }
void Quit();
private:
Application();
bool Initialize();
std::unique_ptr<xe::ui::Loop> loop_;
std::unique_ptr<MainWindow> main_window_;
DebugClient client_;
std::unique_ptr<model::System> system_;
};
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_APPLICATION_H_

View File

@@ -1,49 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_CONTROL_H_
#define XENIA_DEBUG_UI_CONTROL_H_
#include <memory>
#include <string>
#include "el/elements.h"
#include "el/event_handler.h"
#include "xenia/debug/ui/application.h"
namespace xe {
namespace debug {
namespace ui {
class Control {
public:
virtual ~Control() = default;
el::LayoutBox* root_element() { return &root_element_; }
xe::ui::Loop* loop() const { return Application::current()->loop(); }
DebugClient* client() const { return client_; }
model::System* system() const { return Application::current()->system(); }
virtual el::Element* BuildUI() = 0;
virtual void Setup(xe::debug::DebugClient* client) = 0;
protected:
Control() = default;
el::LayoutBox root_element_;
std::unique_ptr<el::EventHandler> handler_;
xe::debug::DebugClient* client_ = nullptr;
};
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_CONTROL_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_DEBUG_WINDOW_H_
#define XENIA_DEBUG_UI_DEBUG_WINDOW_H_
#include <memory>
#include <vector>
#include "xenia/base/x64_context.h"
#include "xenia/debug/debugger.h"
#include "xenia/emulator.h"
#include "xenia/ui/loop.h"
#include "xenia/ui/menu_item.h"
#include "xenia/ui/window.h"
#include "xenia/xbox.h"
namespace xe {
namespace debug {
namespace ui {
class ImGuiRenderer;
class DebugWindow : public DebugListener {
public:
~DebugWindow();
static std::unique_ptr<DebugWindow> Create(Emulator* emulator,
xe::ui::Loop* loop);
Emulator* emulator() const { return emulator_; }
xe::ui::Loop* loop() const { return loop_; }
xe::ui::Window* window() const { return window_.get(); }
void OnFocus() override;
void OnDetached() override;
void OnExecutionPaused() override;
void OnExecutionContinued() override;
void OnExecutionEnded() override;
void OnStepCompleted(xe::kernel::XThread* thread) override;
void OnBreakpointHit(Breakpoint* breakpoint,
xe::kernel::XThread* thread) override;
private:
explicit DebugWindow(Emulator* emulator, xe::ui::Loop* loop);
bool Initialize();
void DrawFrame();
void DrawToolbar();
void DrawFunctionsPane();
void DrawSourcePane();
void DrawGuestFunctionSource();
void DrawMachineCodeSource(const uint8_t* ptr, size_t length);
void DrawBreakpointGutterButton(bool has_breakpoint,
CodeBreakpoint::AddressType address_type,
uint64_t address);
void ScrollToSourceIfPcChanged();
void DrawRegistersPane();
bool DrawRegisterTextBox(int id, uint32_t* value);
bool DrawRegisterTextBox(int id, uint64_t* value);
bool DrawRegisterTextBox(int id, double* value);
bool DrawRegisterTextBoxes(int id, float* value);
void DrawThreadsPane();
void DrawMemoryPane();
void DrawBreakpointsPane();
void DrawLogPane();
void SelectThreadStackFrame(kernel::XThread* thread, size_t stack_frame_index,
bool always_navigate);
void NavigateToFunction(cpu::Function* function, uint32_t guest_pc = 0,
uint64_t host_pc = 0);
// void NavigateToMemory(uint64_t address, uint64_t length = 0);
// void ToggleLogThreadFocus(thread | nullptr);
void UpdateCache();
void CreateCodeBreakpoint(CodeBreakpoint::AddressType address_type,
uint64_t address);
void DeleteCodeBreakpoint(CodeBreakpoint* breakpoint);
void DeleteBreakpoint(Breakpoint* breakpoint);
CodeBreakpoint* LookupBreakpointAtAddress(
CodeBreakpoint::AddressType address_type, uint64_t address);
Emulator* emulator_ = nullptr;
Debugger* debugger_ = nullptr;
xe::ui::Loop* loop_ = nullptr;
std::unique_ptr<xe::ui::Window> window_;
std::unique_ptr<ImGuiRenderer> imgui_renderer_;
uint64_t last_draw_tick_count_ = 0;
uintptr_t capstone_handle_ = 0;
// Cached debugger data, updated on every break before a frame is drawn.
// Prefer putting stuff here that will be queried either each frame or
// multiple times per frame to avoid expensive redundant work.
struct ImDataCache {
bool is_running = false;
std::vector<kernel::object_ref<kernel::XModule>> modules;
std::vector<ThreadExecutionInfo*> thread_execution_infos;
} cache_;
enum class RegisterGroup {
kGuestGeneral,
kGuestFloat,
kGuestVector,
kHostGeneral,
kHostVector,
};
// The current state of the UI. Use this to synchronize multiple parts of the
// UI.
struct ImState {
static const int kRightPaneThreads = 0;
static const int kRightPaneMemory = 1;
int right_pane_tab = kRightPaneThreads;
xe::kernel::XThread* thread = nullptr;
ThreadExecutionInfo* thread_info = nullptr;
size_t thread_stack_frame_index = 0;
bool has_changed_thread = false;
xe::cpu::Function* function = nullptr;
uint64_t last_host_pc = 0;
bool has_changed_pc = false;
int source_display_mode = 3;
RegisterGroup register_group = RegisterGroup::kGuestGeneral;
bool register_input_hex = true;
struct {
char kernel_call_filter[64] = {0};
std::vector<std::unique_ptr<Breakpoint>> all_breakpoints;
std::unordered_map<uint32_t, CodeBreakpoint*>
code_breakpoints_by_guest_address;
std::unordered_map<uintptr_t, CodeBreakpoint*>
code_breakpoints_by_host_address;
} breakpoints;
xe::kernel::XThread* isolated_log_thread = nullptr;
} state_;
};
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_DEBUG_WINDOW_H_

View File

@@ -1,32 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <gflags/gflags.h>
#include <cstring>
#include "xenia/base/main.h"
#include "xenia/debug/ui/application.h"
namespace xe {
namespace debug {
namespace ui {
int main(const std::vector<std::wstring>& args) {
auto app = Application::Create();
app->loop()->AwaitQuit();
return 0;
}
} // namespace ui
} // namespace debug
} // namespace xe
DEFINE_ENTRY_POINT(L"xenia-debug-ui", L"xenia-debug-ui ??",
xe::debug::ui::main);

View File

@@ -1,6 +0,0 @@
//{{NO_DEPENDENCIES}}
#include "third_party\\elemental-forms\\resources.rc"
//IDR_xe_debug_ui_resources_skin_bg_tile_png RCDATA ".\\resources\\skin\\bg_tile.png"
IDR_xe_debug_ui_resources_smaller_skin_skin_tb_txt RCDATA ".\\resources\\smaller_skin\\skin.tb.txt"

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,55 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_IMGUI_RENDERER_H_
#define XENIA_DEBUG_UI_IMGUI_RENDERER_H_
#include <memory>
#include "third_party/imgui/imgui.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/ui/gl/circular_buffer.h"
#include "xenia/ui/gl/gl_context.h"
#include "xenia/ui/window.h"
namespace xe {
namespace debug {
namespace ui {
class ImGuiRenderer {
public:
ImGuiRenderer(xe::ui::Window* window, xe::ui::GraphicsContext* context);
~ImGuiRenderer();
private:
static ImGuiRenderer* global_renderer_;
void Initialize();
void InitializeShaders();
void InitializeFontTextures();
void Shutdown();
void RenderDrawLists(ImDrawData* data);
xe::ui::Window* window_ = nullptr;
xe::ui::GraphicsContext* context_ = nullptr;
GLuint program_ = 0;
GLuint vao_ = 0;
xe::ui::gl::CircularBuffer vertex_buffer_;
xe::ui::gl::CircularBuffer index_buffer_;
};
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_IMGUI_RENDERER_H_

View File

@@ -1,197 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/main_window.h"
#include "el/animation_manager.h"
#include "el/io/file_manager.h"
#include "el/util/debug.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
#include "xenia/base/platform.h"
#include "xenia/base/threading.h"
#include "xenia/ui/gl/gl_context.h"
#if XE_PLATFORM_WIN32
#include "el/io/win32_res_file_system_win.h"
#endif // XE_PLATFORM_WIN32
namespace xe {
namespace debug {
namespace ui {
using xe::ui::MenuItem;
const std::wstring kBaseTitle = L"xenia debugger";
MainWindow::MainWindow(Application* app) : app_(app) {}
MainWindow::~MainWindow() = default;
bool MainWindow::Initialize() {
client_ = app_->client();
window_ = xe::ui::Window::Create(app()->loop(), kBaseTitle);
if (!window_) {
return false;
}
window_->Initialize();
window_->set_context(xe::ui::gl::GLContext::Create(window_.get()));
#if XE_PLATFORM_WIN32
el::io::FileManager::RegisterFileSystem(
std::make_unique<el::io::Win32ResFileSystem>(
"IDR_xe_debug_ui_resources_"));
#endif // XE_PLATFORM_WIN32
window_->LoadSkin("smaller_skin/skin.tb.txt");
window_->on_closed.AddListener(std::bind(&MainWindow::OnClose, this));
window_->on_key_down.AddListener([this](xe::ui::KeyEvent* e) {
bool handled = true;
switch (e->key_code()) {
case 0x1B: { // VK_ESCAPE
// Allow users to escape fullscreen (but not enter it).
if (window_->is_fullscreen()) {
window_->ToggleFullscreen(false);
}
} break;
case 0x70: { // VK_F1
LaunchBrowser("http://xenia.jp");
} break;
default: { handled = false; } break;
}
e->set_handled(handled);
});
// Main menu.
auto main_menu = MenuItem::Create(MenuItem::Type::kNormal);
auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File");
{
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, L"E&xit",
L"Alt+F4",
[this]() { window_->Close(); }));
}
main_menu->AddChild(std::move(file_menu));
// Help menu.
auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&Help");
{
help_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, L"&Website...", L"F1",
[]() { LaunchBrowser("http://xenia.jp"); }));
help_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, L"&About...",
[]() { LaunchBrowser("http://xenia.jp/about/"); }));
}
main_menu->AddChild(std::move(help_menu));
window_->set_main_menu(std::move(main_menu));
window_->Resize(1440, 1200);
BuildUI();
return true;
}
void MainWindow::BuildUI() {
using namespace el::dsl; // NOLINT(build/namespaces)
el::AnimationBlocker animation_blocker;
auto root_element = window_->root_element();
form_ = std::make_unique<el::Form>();
form_->set_settings(el::FormSettings::kFullScreen);
root_element->AddChild(form_.get());
auto root_node =
LayoutBoxNode()
.gravity(Gravity::kAll)
.distribution(LayoutDistribution::kAvailable)
.axis(Axis::kY)
.child(
LayoutBoxNode()
.id("toolbar_box")
.gravity(Gravity::kTop | Gravity::kLeftRight)
.distribution(LayoutDistribution::kGravity)
.distribution_position(LayoutDistributionPosition::kLeftTop)
.child(ButtonNode("Pause").id("pause_button"))
.child(ButtonNode("Continue").id("resume_button")))
.child(
SplitContainerNode()
.id("split_container")
.gravity(Gravity::kAll)
.axis(Axis::kX)
.fixed_pane(FixedPane::kSecond)
.min(128)
.value(250)
.pane(TabContainerNode()
.id("tab_container")
.gravity(Gravity::kAll)
.align(Align::kTop))
.pane(LayoutBoxNode().id("log_box").gravity(Gravity::kAll)));
form_->LoadNodeTree(root_node);
form_->GetElementsById({
{TBIDC("split_container"), &ui_.split_container},
{TBIDC("toolbar_box"), &ui_.toolbar_box},
{TBIDC("tab_container"), &ui_.tab_container},
});
handler_ = std::make_unique<el::EventHandler>(form_.get());
handler_->Listen(el::EventType::kClick, TBIDC("pause_button"),
[this](const el::Event& ev) {
client_->Interrupt();
return true;
});
handler_->Listen(el::EventType::kClick, TBIDC("resume_button"),
[this](const el::Event& ev) {
client_->Continue();
return true;
});
system()->on_execution_state_changed.AddListener(
[this]() { UpdateElementState(); });
ui_.tab_container->tab_bar()->LoadNodeTree(ButtonNode(cpu_view_.name()));
ui_.tab_container->content_root()->AddChild(cpu_view_.BuildUI());
cpu_view_.Setup(Application::current()->client());
ui_.tab_container->tab_bar()->LoadNodeTree(ButtonNode(gpu_view_.name()));
ui_.tab_container->content_root()->AddChild(gpu_view_.BuildUI());
gpu_view_.Setup(Application::current()->client());
UpdateElementState();
el::util::ShowDebugInfoSettingsForm(root_element);
}
void MainWindow::UpdateElementState() {
bool is_running = client_->execution_state() == ExecutionState::kRunning;
el::TabContainer* tab_container;
el::Button* pause_button;
el::Button* resume_button;
form_->GetElementsById({
{TBIDC("tab_container"), &tab_container},
{TBIDC("pause_button"), &pause_button},
{TBIDC("resume_button"), &resume_button},
});
tab_container->set_enabled(!is_running);
pause_button->set_enabled(is_running);
resume_button->set_enabled(!is_running);
}
void MainWindow::OnClose() { app_->Quit(); }
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,63 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_MAIN_WINDOW_H_
#define XENIA_DEBUG_UI_MAIN_WINDOW_H_
#include <memory>
#include "el/elements.h"
#include "xenia/debug/ui/application.h"
#include "xenia/debug/ui/views/cpu/cpu_view.h"
#include "xenia/debug/ui/views/gpu/gpu_view.h"
#include "xenia/ui/window.h"
namespace xe {
namespace debug {
namespace ui {
class MainWindow {
public:
explicit MainWindow(Application* app);
~MainWindow();
Application* app() const { return app_; }
xe::ui::Loop* loop() const { return app_->loop(); }
model::System* system() const { return app_->system(); }
bool Initialize();
// void NavigateToCpuView(uint32_t address);
private:
void BuildUI();
void UpdateElementState();
void OnClose();
Application* app_ = nullptr;
xe::debug::DebugClient* client_ = nullptr;
std::unique_ptr<xe::ui::Window> window_;
std::unique_ptr<el::Form> form_;
struct {
el::SplitContainer* split_container;
el::LayoutBox* toolbar_box;
el::TabContainer* tab_container;
} ui_ = {0};
std::unique_ptr<el::EventHandler> handler_;
views::cpu::CpuView cpu_view_;
views::gpu::GpuView gpu_view_;
};
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_MAIN_WINDOW_H_

View File

@@ -1,22 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/model/function.h"
namespace xe {
namespace debug {
namespace ui {
namespace model {
//
} // namespace model
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,29 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_MODEL_FUNCTION_H_
#define XENIA_DEBUG_UI_MODEL_FUNCTION_H_
#include <cstdint>
namespace xe {
namespace debug {
namespace ui {
namespace model {
class Function {
public:
};
} // namespace model
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_MODEL_FUNCTION_H_

View File

@@ -1,26 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/model/module.h"
#include "xenia/debug/ui/model/system.h"
namespace xe {
namespace debug {
namespace ui {
namespace model {
void Module::Update(const proto::ModuleListEntry* entry) {
std::memcpy(&entry_, entry, sizeof(entry_));
}
} // namespace model
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,50 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_MODEL_MODULE_H_
#define XENIA_DEBUG_UI_MODEL_MODULE_H_
#include <cstdint>
#include <string>
#include "xenia/debug/proto/xdp_protocol.h"
namespace xe {
namespace debug {
namespace ui {
namespace model {
class System;
class Module {
public:
explicit Module(System* system) : system_(system) {}
bool is_dead() const { return is_dead_; }
void set_dead(bool is_dead) { is_dead_ = is_dead; }
uint32_t module_handle() const { return entry_.module_handle; }
bool is_kernel_module() const { return entry_.is_kernel_module; }
std::string name() const { return entry_.name; }
const proto::ModuleListEntry* entry() const { return &entry_; }
void Update(const proto::ModuleListEntry* entry);
private:
System* system_ = nullptr;
bool is_dead_ = false;
proto::ModuleListEntry entry_ = {0};
};
} // namespace model
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_MODEL_MODULE_H_

View File

@@ -1,128 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/model/system.h"
#include <unordered_set>
namespace xe {
namespace debug {
namespace ui {
namespace model {
using namespace xe::debug::proto; // NOLINT(build/namespaces)
System::System(xe::ui::Loop* loop, DebugClient* client)
: loop_(loop), client_(client) {
client_->set_listener(this);
client_->set_loop(loop);
}
System::~System() { client_->set_listener(nullptr); }
ExecutionState System::execution_state() { return client_->execution_state(); }
std::vector<Module*> System::modules() {
std::vector<Module*> result;
for (auto& module : modules_) {
result.push_back(module.get());
}
return result;
}
std::vector<Thread*> System::threads() {
std::vector<Thread*> result;
for (auto& thread : threads_) {
result.push_back(thread.get());
}
return result;
}
Module* System::GetModuleByHandle(uint32_t module_handle) {
auto it = modules_by_handle_.find(module_handle);
return it != modules_by_handle_.end() ? it->second : nullptr;
}
Thread* System::GetThreadByHandle(uint32_t thread_handle) {
auto it = threads_by_handle_.find(thread_handle);
return it != threads_by_handle_.end() ? it->second : nullptr;
}
void System::OnExecutionStateChanged(ExecutionState execution_state) {
on_execution_state_changed();
}
void System::OnModulesUpdated(std::vector<const ModuleListEntry*> entries) {
std::unordered_set<uint32_t> extra_modules;
for (size_t i = 0; i < modules_.size(); ++i) {
extra_modules.emplace(modules_[i]->module_handle());
}
for (auto entry : entries) {
auto existing_module = modules_by_handle_.find(entry->module_handle);
if (existing_module == modules_by_handle_.end()) {
auto module = std::make_unique<Module>(this);
module->Update(entry);
modules_by_handle_.emplace(entry->module_handle, module.get());
modules_.emplace_back(std::move(module));
} else {
existing_module->second->Update(entry);
extra_modules.erase(existing_module->first);
}
}
for (auto module_handle : extra_modules) {
auto module = modules_by_handle_.find(module_handle);
if (module != modules_by_handle_.end()) {
module->second->set_dead(true);
}
}
on_modules_updated();
}
void System::OnThreadsUpdated(std::vector<const ThreadListEntry*> entries) {
std::unordered_set<uint32_t> extra_threads;
for (size_t i = 0; i < threads_.size(); ++i) {
extra_threads.emplace(threads_[i]->thread_handle());
}
for (auto entry : entries) {
auto existing_thread = threads_by_handle_.find(entry->thread_handle);
if (existing_thread == threads_by_handle_.end()) {
auto thread = std::make_unique<Thread>(this);
thread->Update(entry);
threads_by_handle_.emplace(entry->thread_handle, thread.get());
threads_.emplace_back(std::move(thread));
} else {
existing_thread->second->Update(entry);
extra_threads.erase(existing_thread->first);
}
}
for (auto thread_handle : extra_threads) {
auto thread = threads_by_handle_.find(thread_handle);
if (thread != threads_by_handle_.end()) {
thread->second->set_dead(true);
}
}
on_threads_updated();
}
void System::OnThreadStateUpdated(
uint32_t thread_handle, const ThreadStateEntry* entry,
std::vector<const ThreadCallStackFrame*> frames) {
auto thread = threads_by_handle_[thread_handle];
if (thread != nullptr) {
thread->UpdateState(entry, std::move(frames));
on_thread_state_updated(thread);
}
}
} // namespace model
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,75 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_MODEL_SYSTEM_H_
#define XENIA_DEBUG_UI_MODEL_SYSTEM_H_
#include <cstdint>
#include <memory>
#include <unordered_map>
#include <vector>
#include "xenia/base/delegate.h"
#include "xenia/debug/debug_client.h"
#include "xenia/debug/ui/model/function.h"
#include "xenia/debug/ui/model/module.h"
#include "xenia/debug/ui/model/thread.h"
#include "xenia/ui/loop.h"
namespace xe {
namespace debug {
namespace ui {
namespace model {
class System : public DebugClientListener {
public:
System(xe::ui::Loop* loop, DebugClient* client);
~System() override;
xe::ui::Loop* loop() const { return loop_; }
DebugClient* client() const { return client_; }
ExecutionState execution_state();
std::vector<Module*> modules();
std::vector<Thread*> threads();
Module* GetModuleByHandle(uint32_t module_handle);
Thread* GetThreadByHandle(uint32_t thread_handle);
Delegate<void> on_execution_state_changed;
Delegate<void> on_modules_updated;
Delegate<void> on_threads_updated;
Delegate<Thread*> on_thread_state_updated;
private:
void OnExecutionStateChanged(ExecutionState execution_state) override;
void OnModulesUpdated(
std::vector<const proto::ModuleListEntry*> entries) override;
void OnThreadsUpdated(
std::vector<const proto::ThreadListEntry*> entries) override;
void OnThreadStateUpdated(
uint32_t thread_handle, const ThreadStateEntry* entry,
std::vector<const ThreadCallStackFrame*> frames) override;
xe::ui::Loop* loop_ = nullptr;
DebugClient* client_ = nullptr;
std::vector<std::unique_ptr<Module>> modules_;
std::unordered_map<uint32_t, Module*> modules_by_handle_;
std::vector<std::unique_ptr<Thread>> threads_;
std::unordered_map<uint32_t, Thread*> threads_by_handle_;
};
} // namespace model
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_MODEL_SYSTEM_H_

View File

@@ -1,50 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/model/thread.h"
#include "xenia/debug/ui/model/system.h"
namespace xe {
namespace debug {
namespace ui {
namespace model {
Thread::Thread(System* system) : system_(system) {
state_ = memory::AlignedAlloc<proto::ThreadStateEntry>(64);
}
Thread::~Thread() { memory::AlignedFree(state_); }
std::string Thread::to_string() {
std::string value = entry_.name;
if (is_host_thread()) {
value += " (host)";
}
return value;
}
void Thread::Update(const proto::ThreadListEntry* entry) {
std::memcpy(&entry_, entry, sizeof(entry_));
}
void Thread::UpdateState(
const proto::ThreadStateEntry* entry,
std::vector<const proto::ThreadCallStackFrame*> frames) {
std::memcpy(state_, entry, sizeof(*state_));
call_stack_.resize(frames.size());
for (size_t i = 0; i < frames.size(); ++i) {
std::memcpy(call_stack_.data() + i, frames[i], sizeof(Frame));
}
}
} // namespace model
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,69 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_MODEL_THREAD_H_
#define XENIA_DEBUG_UI_MODEL_THREAD_H_
#include <cstdint>
#include <string>
#include <vector>
#include "xenia/debug/proto/xdp_protocol.h"
namespace xe {
namespace debug {
namespace ui {
namespace model {
class System;
class Thread {
public:
using Frame = proto::ThreadCallStackFrame;
explicit Thread(System* system);
~Thread();
bool is_dead() const { return is_dead_; }
void set_dead(bool is_dead) { is_dead_ = is_dead; }
const proto::ThreadListEntry* entry() const { return &entry_; }
const proto::ThreadStateEntry* state() const { return state_; }
uint32_t thread_handle() const { return entry_.thread_handle; }
uint32_t thread_id() const { return entry_.thread_id; }
bool is_host_thread() const { return entry_.is_host_thread; }
std::string name() const { return entry_.name; }
const cpu::frontend::PPCContext* guest_context() const {
return &state_->guest_context;
}
const cpu::X64Context* host_context() const { return &state_->host_context; }
const std::vector<Frame>& call_stack() const { return call_stack_; }
std::string to_string();
void Update(const proto::ThreadListEntry* entry);
void UpdateState(const proto::ThreadStateEntry* entry,
std::vector<const proto::ThreadCallStackFrame*> frames);
private:
System* system_ = nullptr;
bool is_dead_ = false;
proto::ThreadListEntry entry_ = {0};
proto::ThreadStateEntry* state_ = nullptr;
std::vector<Frame> call_stack_;
};
} // namespace model
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_MODEL_THREAD_H_

View File

@@ -3,56 +3,25 @@ include(project_root.."/build_tools")
group("src")
project("xenia-debug-ui")
uuid("ed128630-8b4e-4dd7-afc9-ef00052fe3a7")
kind("WindowedApp")
uuid("9193a274-f4c2-4746-bd85-93fcfc5c3e38")
kind("StaticLib")
language("C++")
links({
"elemental-forms",
"gflags",
"xenia-apu",
"xenia-apu-nop",
"xenia-apu-xaudio2",
"glew",
"imgui",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-cpu-backend-x64",
"xenia-debug",
"xenia-gpu",
"xenia-gpu-gl4",
"xenia-hid-nop",
"xenia-hid-winkey",
"xenia-hid-xinput",
"xenia-kernel",
"xenia-ui",
"xenia-ui-gl",
"xenia-vfs",
})
flags({
"WinMain", -- Use WinMain instead of main.
})
defines({
"GLEW_STATIC=1",
"GLEW_MX=1",
})
includedirs({
project_root.."/third_party/elemental-forms/src",
project_root.."/build_tools/third_party/gflags/src",
project_root.."/third_party/elemental-forms/src",
})
recursive_platform_files()
files({
"debugger_main.cc",
"../../base/main_"..platform_suffix..".cc",
})
files({
"debugger_resources.rc",
})
resincludedirs({
project_root,
project_root.."/third_party/elemental-forms",
})
filter("platforms:Windows")
debugdir(project_root)
debugargs({
"--flagfile=scratch/flags.txt",
"2>&1",
"1>scratch/stdout-debugger.txt",
})
local_platform_files()

View File

@@ -1,11 +0,0 @@
elements
Button
padding 3 4
Button.flat
padding 3 4
ButtonInGroup
padding 3 4
Box
padding 5
ListItem
padding 1 4

View File

@@ -1,51 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_VIEW_H_
#define XENIA_DEBUG_UI_VIEW_H_
#include <memory>
#include <string>
#include "el/elements.h"
#include "el/event_handler.h"
#include "xenia/debug/ui/application.h"
namespace xe {
namespace debug {
namespace ui {
class View {
public:
virtual ~View() = default;
std::string name() const { return name_; }
el::LayoutBox* root_element() { return &root_element_; }
xe::ui::Loop* loop() const { return Application::current()->loop(); }
DebugClient* client() const { return client_; }
model::System* system() const { return Application::current()->system(); }
virtual el::Element* BuildUI() = 0;
virtual void Setup(xe::debug::DebugClient* client) = 0;
protected:
explicit View(std::string name) : name_(name) {}
std::string name_;
el::LayoutBox root_element_;
std::unique_ptr<el::EventHandler> handler_;
xe::debug::DebugClient* client_ = nullptr;
};
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_VIEW_H_

View File

@@ -1,152 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/views/cpu/call_stack_control.h"
#include "el/animation_manager.h"
#include "xenia/base/string_buffer.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace cpu {
class CallStackItem : public el::GenericStringItem {
public:
CallStackItem(size_t ordinal, const ThreadCallStackFrame* frame)
: GenericStringItem(""), ordinal_(ordinal), frame_(frame) {
StringBuffer sb;
if (frame_->guest_pc) {
sb.AppendFormat(" %.2lld %.16llX %.8X %s", ordinal_, frame_->host_pc,
frame_->guest_pc, frame_->name);
} else {
sb.AppendFormat(" %.2lld %.16llX %s", ordinal_, frame_->host_pc,
frame_->name);
}
str = sb.to_string();
}
private:
size_t ordinal_ = 0;
const ThreadCallStackFrame* frame_ = nullptr;
};
class CallStackItemElement : public el::LayoutBox {
public:
CallStackItemElement(CallStackItem* item, CallStackItemSource* source,
el::ListItemObserver* source_viewer, size_t index)
: item_(item),
source_(source),
source_viewer_(source_viewer),
index_(index) {
set_background_skin(TBIDC("ListItem"));
set_axis(el::Axis::kY);
set_gravity(el::Gravity::kAll);
set_layout_position(el::LayoutPosition::kLeftTop);
set_layout_distribution(el::LayoutDistribution::kAvailable);
set_layout_distribution_position(el::LayoutDistributionPosition::kLeftTop);
set_layout_size(el::LayoutSize::kAvailable);
set_paint_overflow_fadeout(false);
using namespace el::dsl; // NOLINT(build/namespaces)
el::AnimationBlocker animation_blocker;
auto node = LabelNode(item_->str.c_str())
.gravity(Gravity::kLeft)
.ignore_input(true)
.text_align(el::TextAlign::kLeft);
content_root()->LoadNodeTree(node);
}
bool OnEvent(const el::Event& ev) override {
return el::LayoutBox::OnEvent(ev);
}
private:
CallStackItem* item_ = nullptr;
CallStackItemSource* source_ = nullptr;
el::ListItemObserver* source_viewer_ = nullptr;
size_t index_ = 0;
};
class CallStackItemSource : public el::ListItemSourceList<CallStackItem> {
public:
el::Element* CreateItemElement(size_t index,
el::ListItemObserver* viewer) override {
return new CallStackItemElement(at(index), this, viewer, index);
}
};
CallStackControl::CallStackControl()
: item_source_(new CallStackItemSource()) {}
CallStackControl::~CallStackControl() = default;
el::Element* CallStackControl::BuildUI() {
using namespace el::dsl; // NOLINT(build/namespaces)
el::AnimationBlocker animation_blocker;
auto node =
LayoutBoxNode()
.gravity(Gravity::kAll)
.distribution(LayoutDistribution::kAvailable)
.child(ListBoxNode().id("stack_listbox").gravity(Gravity::kAll));
root_element_.set_gravity(Gravity::kAll);
root_element_.set_layout_distribution(LayoutDistribution::kAvailable);
root_element_.LoadNodeTree(node);
auto stack_listbox =
root_element_.GetElementById<el::ListBox>(TBIDC("stack_listbox"));
stack_listbox->set_source(item_source_.get());
stack_listbox->scroll_container()->set_scroll_mode(
el::ScrollMode::kAutoXAutoY);
handler_ = std::make_unique<el::EventHandler>(&root_element_);
return &root_element_;
}
void CallStackControl::Setup(DebugClient* client) {
client_ = client;
system()->on_thread_state_updated.AddListener([this](model::Thread* thread) {
if (thread == thread_) {
InvalidateCallStack();
}
});
}
void CallStackControl::set_thread(model::Thread* thread) {
thread_ = thread;
InvalidateCallStack();
}
void CallStackControl::InvalidateCallStack() {
item_source_->clear();
if (!thread_) {
return;
}
auto& call_stack = thread_->call_stack();
for (size_t i = 0; i < call_stack.size(); ++i) {
auto& frame = call_stack[i];
size_t ordinal = call_stack.size() - i - 1;
auto item = std::make_unique<CallStackItem>(ordinal, &frame);
item->tag.set_integer(static_cast<int>(i));
item_source_->push_back(std::move(item));
}
item_source_->InvokeAllItemsRemoved();
}
} // namespace cpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,51 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_VIEWS_CPU_CALL_STACK_CONTROL_H_
#define XENIA_DEBUG_UI_VIEWS_CPU_CALL_STACK_CONTROL_H_
#include <memory>
#include <string>
#include "xenia/debug/ui/control.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace cpu {
class CallStackItemSource;
class CallStackControl : public Control {
public:
CallStackControl();
~CallStackControl() override;
el::Element* BuildUI() override;
void Setup(xe::debug::DebugClient* client) override;
model::Thread* thread() const { return thread_; }
void set_thread(model::Thread* thread);
private:
void InvalidateCallStack();
model::Thread* thread_ = nullptr;
std::unique_ptr<CallStackItemSource> item_source_;
};
} // namespace cpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_VIEWS_CPU_CALL_STACK_CONTROL_H_

View File

@@ -1,278 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/views/cpu/cpu_view.h"
#include "el/animation_manager.h"
#include "xenia/base/string_buffer.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace cpu {
CpuView::CpuView()
: View("CPU"),
gr_registers_control_(RegisterSet::kGeneral),
fr_registers_control_(RegisterSet::kFloat),
vr_registers_control_(RegisterSet::kVector),
host_registers_control_(RegisterSet::kHost) {}
CpuView::~CpuView() = default;
el::Element* CpuView::BuildUI() {
using namespace el::dsl; // NOLINT(build/namespaces)
el::AnimationBlocker animation_blocker;
auto functions_node =
LayoutBoxNode()
.gravity(Gravity::kAll)
.distribution(LayoutDistribution::kAvailable)
.axis(Axis::kY)
.child(LayoutBoxNode()
.gravity(Gravity::kTop | Gravity::kLeftRight)
.distribution(LayoutDistribution::kAvailable)
.axis(Axis::kX)
.skin("button_group")
.child(DropDownButtonNode().id("module_dropdown")))
.child(ListBoxNode().id("function_listbox").gravity(Gravity::kAll))
.child(LayoutBoxNode()
.gravity(Gravity::kBottom | Gravity::kLeftRight)
.distribution(LayoutDistribution::kAvailable)
.axis(Axis::kX)
.child(TextBoxNode()
.type(EditType::kSearch)
.placeholder("Filter")));
auto register_list_node = ListBoxNode()
.gravity(Gravity::kAll)
.item("A")
.item("A")
.item("A")
.item("A");
auto source_registers_node =
TabContainerNode()
.gravity(Gravity::kAll)
.tab(ButtonNode("GR"), LabelNode("<register list control>")
.id("gr_registers_placeholder"))
.tab(ButtonNode("FR"), LabelNode("<register list control>")
.id("fr_registers_placeholder"))
.tab(ButtonNode("VR"), LabelNode("<register list control>")
.id("vr_registers_placeholder"))
.tab(ButtonNode("X64"), LabelNode("<register list control>")
.id("host_registers_placeholder"));
auto source_tools_node =
TabContainerNode()
.gravity(Gravity::kAll)
.align(Align::kLeft)
.tab(ButtonNode("Stack"),
LabelNode("<callstack control>").id("call_stack_placeholder"))
.tab(ButtonNode("BPs"), LabelNode("BREAKPOINTS"));
auto source_pane_node =
LayoutBoxNode()
.gravity(Gravity::kAll)
.distribution(LayoutDistribution::kAvailable)
.axis(Axis::kY)
.child(
LayoutBoxNode()
.id("source_toolbar")
.gravity(Gravity::kTop | Gravity::kLeftRight)
.distribution(LayoutDistribution::kGravity)
.distribution_position(LayoutDistributionPosition::kLeftTop)
.axis(Axis::kX)
.child(DropDownButtonNode().id("thread_dropdown")))
.child(LayoutBoxNode()
.id("source_content")
.gravity(Gravity::kAll)
.distribution(LayoutDistribution::kAvailable)
.child(SplitContainerNode()
.gravity(Gravity::kAll)
.axis(Axis::kX)
.fixed_pane(FixedPane::kSecond)
.value(250)
.pane(SplitContainerNode()
.gravity(Gravity::kAll)
.axis(Axis::kY)
.fixed_pane(FixedPane::kSecond)
.value(240)
.pane(LabelNode("<source control>")
.id("source_placeholder"))
.pane(source_registers_node))
.pane(source_tools_node)));
auto memory_pane_node = LabelNode("MEMORY");
auto node = SplitContainerNode()
.gravity(Gravity::kAll)
.axis(Axis::kY)
.min(128)
.max(512)
.value(128)
.pane(functions_node)
.pane(SplitContainerNode()
.gravity(Gravity::kAll)
.axis(Axis::kY)
.value(800)
.pane(source_pane_node)
.pane(memory_pane_node));
root_element_.set_gravity(Gravity::kAll);
root_element_.set_layout_distribution(LayoutDistribution::kAvailable);
root_element_.LoadNodeTree(node);
el::Label* source_placeholder;
el::Label* gr_registers_placeholder;
el::Label* fr_registers_placeholder;
el::Label* vr_registers_placeholder;
el::Label* host_registers_placeholder;
el::Label* call_stack_placeholder;
root_element_.GetElementsById({
{TBIDC("source_placeholder"), &source_placeholder},
{TBIDC("gr_registers_placeholder"), &gr_registers_placeholder},
{TBIDC("fr_registers_placeholder"), &fr_registers_placeholder},
{TBIDC("vr_registers_placeholder"), &vr_registers_placeholder},
{TBIDC("host_registers_placeholder"), &host_registers_placeholder},
{TBIDC("call_stack_placeholder"), &call_stack_placeholder},
});
source_placeholder->parent()->ReplaceChild(source_placeholder,
source_control_.BuildUI());
source_control_.Setup(client_);
gr_registers_placeholder->parent()->ReplaceChild(
gr_registers_placeholder, gr_registers_control_.BuildUI());
gr_registers_control_.Setup(client_);
fr_registers_placeholder->parent()->ReplaceChild(
fr_registers_placeholder, fr_registers_control_.BuildUI());
fr_registers_control_.Setup(client_);
vr_registers_placeholder->parent()->ReplaceChild(
vr_registers_placeholder, vr_registers_control_.BuildUI());
vr_registers_control_.Setup(client_);
host_registers_placeholder->parent()->ReplaceChild(
host_registers_placeholder, host_registers_control_.BuildUI());
host_registers_control_.Setup(client_);
call_stack_placeholder->parent()->ReplaceChild(call_stack_placeholder,
call_stack_control_.BuildUI());
call_stack_control_.Setup(client_);
handler_ = std::make_unique<el::EventHandler>(&root_element_);
handler_->Listen(el::EventType::kChanged, TBIDC("module_dropdown"),
[this](const el::Event& ev) {
UpdateFunctionList();
return true;
});
handler_->Listen(
el::EventType::kChanged, TBIDC("thread_dropdown"),
[this](const el::Event& ev) {
auto thread_dropdown = root_element_.GetElementById<el::DropDownButton>(
TBIDC("thread_dropdown"));
auto thread_handle = uint32_t(thread_dropdown->selected_item_id());
if (thread_handle) {
current_thread_ = system()->GetThreadByHandle(thread_handle);
} else {
current_thread_ = nullptr;
}
SwitchCurrentThread(current_thread_);
return true;
});
return &root_element_;
}
void CpuView::Setup(DebugClient* client) {
client_ = client;
system()->on_execution_state_changed.AddListener(
[this]() { UpdateElementState(); });
system()->on_modules_updated.AddListener([this]() { UpdateModuleList(); });
system()->on_threads_updated.AddListener([this]() { UpdateThreadList(); });
}
void CpuView::UpdateElementState() {
root_element_.GetElementsById({
//
});
}
void CpuView::UpdateModuleList() {
el::DropDownButton* module_dropdown;
root_element_.GetElementsById({
{TBIDC("module_dropdown"), &module_dropdown},
});
auto module_items = module_dropdown->default_source();
auto modules = system()->modules();
bool is_first = module_items->size() == 0;
for (size_t i = module_items->size(); i < modules.size(); ++i) {
auto module = modules[i];
auto item = std::make_unique<el::GenericStringItem>(module->name());
item->id = module->module_handle();
module_items->push_back(std::move(item));
}
if (is_first) {
module_dropdown->set_value(static_cast<int>(module_items->size() - 1));
}
}
void CpuView::UpdateFunctionList() {
el::DropDownButton* module_dropdown;
el::ListBox* function_listbox;
root_element_.GetElementsById({
{TBIDC("module_dropdown"), &module_dropdown},
{TBIDC("function_listbox"), &function_listbox},
});
auto module_handle = module_dropdown->selected_item_id();
auto module = system()->GetModuleByHandle(module_handle);
if (!module) {
function_listbox->default_source()->clear();
return;
}
// TODO(benvanik): fetch list.
}
void CpuView::UpdateThreadList() {
el::DropDownButton* thread_dropdown;
root_element_.GetElementsById({
{TBIDC("thread_dropdown"), &thread_dropdown},
});
auto thread_items = thread_dropdown->default_source();
auto threads = system()->threads();
bool is_first = thread_items->size() == 0;
for (size_t i = 0; i < thread_items->size(); ++i) {
auto thread = threads[i];
auto item = thread_items->at(i);
item->str = thread->to_string();
}
for (size_t i = thread_items->size(); i < threads.size(); ++i) {
auto thread = threads[i];
auto item = std::make_unique<el::GenericStringItem>(thread->to_string());
item->id = thread->thread_handle();
thread_items->push_back(std::move(item));
}
if (is_first) {
thread_dropdown->set_value(static_cast<int>(thread_items->size() - 1));
}
}
void CpuView::SwitchCurrentThread(model::Thread* thread) {
current_thread_ = thread;
source_control_.set_thread(thread);
gr_registers_control_.set_thread(thread);
fr_registers_control_.set_thread(thread);
vr_registers_control_.set_thread(thread);
host_registers_control_.set_thread(thread);
call_stack_control_.set_thread(thread);
}
} // namespace cpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,61 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_VIEWS_CPU_CPU_VIEW_H_
#define XENIA_DEBUG_UI_VIEWS_CPU_CPU_VIEW_H_
#include <memory>
#include <string>
#include "xenia/debug/ui/view.h"
#include "xenia/debug/ui/views/cpu/call_stack_control.h"
#include "xenia/debug/ui/views/cpu/register_list_control.h"
#include "xenia/debug/ui/views/cpu/source_control.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace cpu {
class CpuView : public View {
public:
CpuView();
~CpuView() override;
el::Element* BuildUI() override;
void Setup(xe::debug::DebugClient* client) override;
protected:
void UpdateElementState();
void UpdateModuleList();
void UpdateFunctionList();
void UpdateThreadList();
void SwitchCurrentThread(model::Thread* thread);
// TODO(benvanik): better state machine.
model::Thread* current_thread_ = nullptr;
SourceControl source_control_;
RegisterListControl gr_registers_control_;
RegisterListControl fr_registers_control_;
RegisterListControl vr_registers_control_;
RegisterListControl host_registers_control_;
CallStackControl call_stack_control_;
};
} // namespace cpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_VIEWS_CPU_CPU_VIEW_H_

View File

@@ -1,325 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/views/cpu/register_list_control.h"
#include <cinttypes>
#include <cstdlib>
#include "el/animation_manager.h"
#include "xenia/base/string_buffer.h"
#include "xenia/base/string_util.h"
#include "xenia/cpu/x64_context.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace cpu {
using xe::cpu::frontend::PPCRegister;
using xe::cpu::X64Register;
enum class RegisterType {
kControl,
kInteger,
kFloat,
kVector,
};
class RegisterItem : public el::GenericStringItem {
public:
const char* name() { return name_.c_str(); }
virtual void set_thread(model::Thread* thread) { thread_ = thread; }
protected:
RegisterItem(RegisterSet set, RegisterType type, int ordinal)
: GenericStringItem(""), set_(set), type_(type), ordinal_(ordinal) {
tag.set_integer(ordinal);
}
RegisterSet set_;
RegisterType type_;
int ordinal_;
model::Thread* thread_ = nullptr;
std::string name_;
};
class GuestRegisterItem : public RegisterItem {
public:
GuestRegisterItem(RegisterSet set, RegisterType type, PPCRegister reg)
: RegisterItem(set, type, static_cast<int>(reg)), reg_(reg) {
name_ = xe::cpu::frontend::PPCContext::GetRegisterName(reg_);
}
void set_thread(model::Thread* thread) override {
RegisterItem::set_thread(thread);
if (thread_) {
str = thread_->guest_context()->GetStringFromValue(reg_);
} else {
str = "unknown";
}
}
private:
PPCRegister reg_;
};
class HostRegisterItem : public RegisterItem {
public:
HostRegisterItem(RegisterSet set, RegisterType type, X64Register reg)
: RegisterItem(set, type, static_cast<int>(reg)), reg_(reg) {
name_ = xe::cpu::X64Context::GetRegisterName(reg_);
}
void set_thread(model::Thread* thread) override {
RegisterItem::set_thread(thread);
if (thread_) {
str = thread_->host_context()->GetStringFromValue(reg_);
} else {
str = "unknown";
}
}
private:
X64Register reg_;
};
class RegisterItemElement : public el::LayoutBox {
public:
RegisterItemElement(RegisterItem* item, RegisterItemSource* source,
el::ListItemObserver* source_viewer, size_t index)
: item_(item),
source_(source),
source_viewer_(source_viewer),
index_(index) {
set_background_skin(TBIDC("ListItem"));
set_axis(el::Axis::kY);
set_gravity(el::Gravity::kAll);
set_layout_position(el::LayoutPosition::kLeftTop);
set_layout_distribution(el::LayoutDistribution::kAvailable);
set_layout_distribution_position(el::LayoutDistributionPosition::kLeftTop);
set_layout_size(el::LayoutSize::kAvailable);
set_paint_overflow_fadeout(false);
using namespace el::dsl; // NOLINT(build/namespaces)
el::AnimationBlocker animation_blocker;
auto node = LayoutBoxNode()
.axis(Axis::kX)
.gravity(Gravity::kLeft)
.distribution(LayoutDistribution::kAvailable)
.child(LabelNode(item_->name())
.ignore_input(true)
.width(45_px)
.gravity(Gravity::kLeft))
.child(TextBoxNode(item_->str.c_str())
.gravity(Gravity::kLeftRight));
content_root()->LoadNodeTree(node);
}
bool OnEvent(const el::Event& ev) override {
return el::LayoutBox::OnEvent(ev);
}
private:
RegisterItem* item_ = nullptr;
RegisterItemSource* source_ = nullptr;
el::ListItemObserver* source_viewer_ = nullptr;
size_t index_ = 0;
};
class RegisterItemSource : public el::ListItemSourceList<RegisterItem> {
public:
el::Element* CreateItemElement(size_t index,
el::ListItemObserver* viewer) override {
return new RegisterItemElement(at(index), this, viewer, index);
}
};
void DefineRegisterItem(RegisterItemSource* item_source, RegisterSet set,
RegisterType type, PPCRegister reg) {
auto item = std::make_unique<GuestRegisterItem>(set, type, reg);
item->tag.set_integer(static_cast<int>(reg));
item_source->push_back(std::move(item));
}
void DefineRegisterItem(RegisterItemSource* item_source, RegisterSet set,
RegisterType type, X64Register reg) {
auto item = std::make_unique<HostRegisterItem>(set, type, reg);
item->tag.set_integer(static_cast<int>(reg));
item_source->push_back(std::move(item));
}
RegisterListControl::RegisterListControl(RegisterSet set)
: set_(set), item_source_(new RegisterItemSource()) {
switch (set_) {
case RegisterSet::kGeneral: {
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
PPCRegister::kLR);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
PPCRegister::kCTR);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kControl,
PPCRegister::kXER);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kControl,
PPCRegister::kCR);
for (size_t i = 0; i < 32; ++i) {
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
static_cast<PPCRegister>(
static_cast<size_t>(PPCRegister::kR0) + i));
}
} break;
case RegisterSet::kFloat: {
DefineRegisterItem(item_source_.get(), set_, RegisterType::kControl,
PPCRegister::kFPSCR);
for (size_t i = 0; i < 32; ++i) {
DefineRegisterItem(item_source_.get(), set_, RegisterType::kFloat,
static_cast<PPCRegister>(
static_cast<size_t>(PPCRegister::kFR0) + i));
}
} break;
case RegisterSet::kVector: {
DefineRegisterItem(item_source_.get(), set_, RegisterType::kControl,
PPCRegister::kVSCR);
for (size_t i = 0; i < 128; ++i) {
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
static_cast<PPCRegister>(
static_cast<size_t>(PPCRegister::kVR0) + i));
}
} break;
case RegisterSet::kHost: {
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRip);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kControl,
X64Register::kEflags);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRax);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRcx);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRdx);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRbx);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRsp);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRbp);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRsi);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kRdi);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kR8);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kR9);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kR10);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kR11);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kR12);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kR13);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kR14);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kInteger,
X64Register::kR15);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm0);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm1);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm2);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm3);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm4);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm5);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm6);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm7);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm8);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm9);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm10);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm11);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm12);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm13);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm14);
DefineRegisterItem(item_source_.get(), set_, RegisterType::kVector,
X64Register::kXmm15);
} break;
}
}
RegisterListControl::~RegisterListControl() = default;
el::Element* RegisterListControl::BuildUI() {
using namespace el::dsl; // NOLINT(build/namespaces)
el::AnimationBlocker animation_blocker;
auto node =
LayoutBoxNode()
.gravity(Gravity::kAll)
.distribution(LayoutDistribution::kAvailable)
.child(ListBoxNode().id("register_listbox").gravity(Gravity::kAll));
root_element_.set_gravity(Gravity::kAll);
root_element_.set_layout_distribution(LayoutDistribution::kAvailable);
root_element_.LoadNodeTree(node);
auto register_listbox =
root_element_.GetElementById<el::ListBox>(TBIDC("register_listbox"));
register_listbox->set_source(item_source_.get());
register_listbox->scroll_container()->set_scroll_mode(
el::ScrollMode::kAutoXAutoY);
handler_ = std::make_unique<el::EventHandler>(&root_element_);
return &root_element_;
}
void RegisterListControl::Setup(DebugClient* client) {
client_ = client;
system()->on_thread_state_updated.AddListener([this](model::Thread* thread) {
if (thread == thread_) {
InvalidateRegisters();
}
});
}
void RegisterListControl::set_thread(model::Thread* thread) {
thread_ = thread;
InvalidateRegisters();
}
void RegisterListControl::InvalidateRegisters() {
for (size_t i = 0; i < item_source_->size(); ++i) {
item_source_->at(i)->set_thread(thread_);
}
auto register_listbox =
root_element_.GetElementById<el::ListBox>(TBIDC("register_listbox"));
register_listbox->InvalidateList();
}
} // namespace cpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,59 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_VIEWS_CPU_REGISTER_LIST_CONTROL_H_
#define XENIA_DEBUG_UI_VIEWS_CPU_REGISTER_LIST_CONTROL_H_
#include <memory>
#include <string>
#include "xenia/debug/ui/control.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace cpu {
class RegisterItemSource;
enum class RegisterSet {
kGeneral,
kFloat,
kVector,
kHost,
};
class RegisterListControl : public Control {
public:
explicit RegisterListControl(RegisterSet set);
~RegisterListControl() override;
el::Element* BuildUI() override;
void Setup(xe::debug::DebugClient* client) override;
model::Thread* thread() const { return thread_; }
void set_thread(model::Thread* thread);
private:
void InvalidateRegisters();
RegisterSet set_;
model::Thread* thread_ = nullptr;
std::unique_ptr<RegisterItemSource> item_source_;
};
} // namespace cpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_VIEWS_CPU_REGISTER_LIST_CONTROL_H_

View File

@@ -1,75 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/debug/ui/views/cpu/source_control.h"
#include "el/animation_manager.h"
#include "xenia/base/string_buffer.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace cpu {
SourceControl::SourceControl() = default;
SourceControl::~SourceControl() = default;
el::Element* SourceControl::BuildUI() {
using namespace el::dsl; // NOLINT(build/namespaces)
el::AnimationBlocker animation_blocker;
auto node = LayoutBoxNode()
.gravity(Gravity::kAll)
.distribution(LayoutDistribution::kAvailable)
.axis(Axis::kY)
.child(LayoutBoxNode()
.gravity(Gravity::kTop | Gravity::kLeftRight)
.distribution(LayoutDistribution::kGravity)
.distribution_position(
LayoutDistributionPosition::kLeftTop)
.axis(Axis::kX)
.child(ButtonNode("A")))
.child(TextBoxNode("source!")
.id("source_textbox")
.gravity(Gravity::kAll)
.is_multiline(true)
.is_read_only(true));
root_element_.set_gravity(Gravity::kAll);
root_element_.set_layout_distribution(LayoutDistribution::kAvailable);
root_element_.LoadNodeTree(node);
handler_ = std::make_unique<el::EventHandler>(&root_element_);
return &root_element_;
}
void SourceControl::Setup(DebugClient* client) {
client_ = client;
// system()->on_thread_state_updated.AddListener([this](model::Thread* thread)
// {
// if (thread == thread_) {
// InvalidateCallStack();
// }
//});
}
void SourceControl::set_thread(model::Thread* thread) {
thread_ = thread;
// InvalidateCallStack();
}
} // namespace cpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,46 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_VIEWS_CPU_SOURCE_CONTROL_H_
#define XENIA_DEBUG_UI_VIEWS_CPU_SOURCE_CONTROL_H_
#include <memory>
#include <string>
#include "xenia/debug/ui/control.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace cpu {
class SourceControl : public Control {
public:
SourceControl();
~SourceControl() override;
el::Element* BuildUI() override;
void Setup(xe::debug::DebugClient* client) override;
model::Thread* thread() const { return thread_; }
void set_thread(model::Thread* thread);
private:
model::Thread* thread_ = nullptr;
};
} // namespace cpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_VIEWS_CPU_SOURCE_CONTROL_H_

View File

@@ -1,47 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "el/animation_manager.h"
#include "xenia/debug/ui/views/gpu/gpu_view.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace gpu {
GpuView::GpuView() : View("GPU") {}
GpuView::~GpuView() = default;
el::Element* GpuView::BuildUI() {
using namespace el::dsl; // NOLINT(build/namespaces)
el::AnimationBlocker animation_blocker;
auto node = LabelNode("TODO");
root_element_.set_gravity(Gravity::kAll);
root_element_.set_layout_distribution(LayoutDistribution::kAvailable);
root_element_.LoadNodeTree(node);
root_element_.GetElementsById({
//
});
handler_ = std::make_unique<el::EventHandler>(&root_element_);
return &root_element_;
}
void GpuView::Setup(xe::debug::DebugClient* client) {
//
}
} // namespace gpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -1,42 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_DEBUG_UI_VIEWS_GPU_GPU_VIEW_H_
#define XENIA_DEBUG_UI_VIEWS_GPU_GPU_VIEW_H_
#include <memory>
#include <string>
#include "xenia/debug/ui/view.h"
namespace xe {
namespace debug {
namespace ui {
namespace views {
namespace gpu {
class GpuView : public View {
public:
GpuView();
~GpuView() override;
el::Element* BuildUI() override;
void Setup(xe::debug::DebugClient* client) override;
protected:
};
} // namespace gpu
} // namespace views
} // namespace ui
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_UI_VIEWS_GPU_GPU_VIEW_H_

View File

@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C5BA52F0-C86B-4817-921C-CCA257FC04BE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>xedebugui</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\build\Xenia.Cpp.$(Platform).Common.props" />
<Import Project="..\..\..\..\build\Xenia.Cpp.$(Platform).$(Configuration).props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\build\Xenia.Cpp.$(Platform).Common.props" />
<Import Project="..\..\..\..\build\Xenia.Cpp.$(Platform).$(Configuration).props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libgflags.lib;libglew.lib;libxenia.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libgflags.lib;libglew.lib;libxenia.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\base\main.h" />
<ClInclude Include="application.h" />
<ClInclude Include="main_window.h" />
<ClInclude Include="view.h" />
<ClInclude Include="views\cpu\cpu_view.h" />
<ClInclude Include="views\gpu\gpu_view.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\base\main_win.cc" />
<ClCompile Include="application.cc" />
<ClCompile Include="main_window.cc" />
<ClCompile Include="views\cpu\cpu_view.cc" />
<ClCompile Include="views\gpu\gpu_view.cc" />
<ClCompile Include="xe-debug-ui.cc" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="resources.rc">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)third_party/elemental-forms;$(SolutionDir);.</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)third_party/elemental-forms;$(SolutionDir);.</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{52d1c314-7464-4640-bee4-59b30d2b2df4}</UniqueIdentifier>
</Filter>
<Filter Include="src\xenia">
<UniqueIdentifier>{f8d1867c-424d-4942-ba97-a7b29fa8c87c}</UniqueIdentifier>
</Filter>
<Filter Include="src\xenia\debug">
<UniqueIdentifier>{1b70e26e-0024-410f-b27f-ceaba190d5a9}</UniqueIdentifier>
</Filter>
<Filter Include="src\xenia\debug\ui">
<UniqueIdentifier>{9b5a4bce-210a-4488-863a-9175f0543d00}</UniqueIdentifier>
</Filter>
<Filter Include="src\xenia\base">
<UniqueIdentifier>{9a5724c2-5473-4d53-93b4-26531201f38d}</UniqueIdentifier>
</Filter>
<Filter Include="src\xenia\debug\ui\elements">
<UniqueIdentifier>{f0ac4999-4700-4b41-b73d-c6dc8b23c5e6}</UniqueIdentifier>
</Filter>
<Filter Include="src\xenia\debug\ui\views">
<UniqueIdentifier>{5601b0a2-a720-4d89-9fca-df1637fce0b1}</UniqueIdentifier>
</Filter>
<Filter Include="src\xenia\debug\ui\views\cpu">
<UniqueIdentifier>{5b186e9a-1fef-42f5-b06b-2ac0b10a8a5b}</UniqueIdentifier>
</Filter>
<Filter Include="src\xenia\debug\ui\views\gpu">
<UniqueIdentifier>{c66e9a6b-0947-4610-9b2b-29db99c08e91}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\base\main.h">
<Filter>src\xenia\base</Filter>
</ClInclude>
<ClInclude Include="main_window.h">
<Filter>src\xenia\debug\ui</Filter>
</ClInclude>
<ClInclude Include="application.h">
<Filter>src\xenia\debug\ui</Filter>
</ClInclude>
<ClInclude Include="view.h">
<Filter>src\xenia\debug\ui</Filter>
</ClInclude>
<ClInclude Include="views\gpu\gpu_view.h">
<Filter>src\xenia\debug\ui\views\gpu</Filter>
</ClInclude>
<ClInclude Include="views\cpu\cpu_view.h">
<Filter>src\xenia\debug\ui\views\cpu</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\base\main_win.cc">
<Filter>src\xenia\base</Filter>
</ClCompile>
<ClCompile Include="xe-debug-ui.cc">
<Filter>src\xenia\debug\ui</Filter>
</ClCompile>
<ClCompile Include="main_window.cc">
<Filter>src\xenia\debug\ui</Filter>
</ClCompile>
<ClCompile Include="application.cc">
<Filter>src\xenia\debug\ui</Filter>
</ClCompile>
<ClCompile Include="views\gpu\gpu_view.cc">
<Filter>src\xenia\debug\ui\views\gpu</Filter>
</ClCompile>
<ClCompile Include="views\cpu\cpu_view.cc">
<Filter>src\xenia\debug\ui\views\cpu</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="resources.rc">
<Filter>src\xenia\debug\ui</Filter>
</ResourceCompile>
</ItemGroup>
</Project>