Debugger fix

Crash fixes
GUI fixes
Debug enhancements
This commit is contained in:
Nekotekina 2017-02-10 01:51:29 +03:00
parent ff07595519
commit 257b9a2015
26 changed files with 282 additions and 455 deletions

View file

@ -2380,10 +2380,6 @@ void named_thread::start_thread(const std::shared_ptr<void>& _this)
LOG_FATAL(GENERAL, "%s thrown: %s", typeid(e).name(), e.what()); LOG_FATAL(GENERAL, "%s thrown: %s", typeid(e).name(), e.what());
Emu.Pause(); Emu.Pause();
} }
catch (EmulationStopped)
{
LOG_NOTICE(GENERAL, "Thread aborted");
}
on_exit(); on_exit();
}); });

View file

@ -2,7 +2,8 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "CPUThread.h" #include "CPUThread.h"
#include <mutex> DECLARE(cpu_thread::g_threads_created){0};
DECLARE(cpu_thread::g_threads_deleted){0};
template<> template<>
void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg) void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
@ -11,15 +12,15 @@ void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
{ {
switch (f) switch (f)
{ {
STR_CASE(cpu_flag::stop); case cpu_flag::stop: return "STOP";
STR_CASE(cpu_flag::exit); case cpu_flag::exit: return "EXIT";
STR_CASE(cpu_flag::suspend); case cpu_flag::suspend: return "s";
STR_CASE(cpu_flag::ret); case cpu_flag::ret: return "ret";
STR_CASE(cpu_flag::signal); case cpu_flag::signal: return "sig";
STR_CASE(cpu_flag::dbg_global_pause); case cpu_flag::dbg_global_pause: return "G.PAUSE";
STR_CASE(cpu_flag::dbg_global_stop); case cpu_flag::dbg_global_stop: return "G.EXIT";
STR_CASE(cpu_flag::dbg_pause); case cpu_flag::dbg_pause: return "PAUSE";
STR_CASE(cpu_flag::dbg_step); case cpu_flag::dbg_step: return "STEP";
case cpu_flag::__bitset_enum_max: break; case cpu_flag::__bitset_enum_max: break;
} }
@ -41,10 +42,8 @@ void cpu_thread::on_task()
g_tls_current_cpu_thread = this; g_tls_current_cpu_thread = this;
Emu.SendDbgCommand(DID_CREATE_THREAD, this);
// Check thread status // Check thread status
while (!test(state & cpu_flag::exit)) while (!test(state, cpu_flag::exit + cpu_flag::dbg_global_stop))
{ {
// Check stop status // Check stop status
if (!test(state & cpu_flag::stop)) if (!test(state & cpu_flag::stop))
@ -79,11 +78,13 @@ void cpu_thread::on_stop()
cpu_thread::~cpu_thread() cpu_thread::~cpu_thread()
{ {
g_threads_deleted++;
} }
cpu_thread::cpu_thread(u32 id) cpu_thread::cpu_thread(u32 id)
: id(id) : id(id)
{ {
g_threads_created++;
} }
bool cpu_thread::check_state() bool cpu_thread::check_state()

View file

@ -56,6 +56,9 @@ public:
return id >> 24; return id >> 24;
} }
// Thread stats for external observation
static atomic_t<u64> g_threads_created, g_threads_deleted;
// Print CPU state // Print CPU state
virtual std::string dump() const; virtual std::string dump() const;

View file

@ -44,6 +44,7 @@
#endif #endif
#include <cfenv> #include <cfenv>
#include "Utilities/GSL.h"
extern u64 get_system_time(); extern u64 get_system_time();
@ -90,6 +91,7 @@ std::string ppu_thread::dump() const
{ {
std::string ret = cpu_thread::dump(); std::string ret = cpu_thread::dump();
ret += fmt::format("Priority: %d\n", prio); ret += fmt::format("Priority: %d\n", prio);
ret += fmt::format("Last function: %s\n", last_function ? last_function : "");
ret += "\nRegisters:\n=========\n"; ret += "\nRegisters:\n=========\n";
for (uint i = 0; i < 32; ++i) ret += fmt::format("GPR[%d] = 0x%llx\n", i, gpr[i]); for (uint i = 0; i < 32; ++i) ret += fmt::format("GPR[%d] = 0x%llx\n", i, gpr[i]);
@ -210,6 +212,11 @@ void ppu_thread::exec_task()
if (UNLIKELY(test(state))) if (UNLIKELY(test(state)))
{ {
if (check_state()) return; if (check_state()) return;
// Decode single instruction (may be step)
const u32 op = *reinterpret_cast<const be_t<u32>*>(base + cia);
if (table[ppu_decode(op)](*this, {op})) { cia += 4; }
continue;
} }
// Reinitialize // Reinitialize
@ -223,11 +230,11 @@ void ppu_thread::exec_task()
func3 = table[_i._u32[3]]; func3 = table[_i._u32[3]];
} }
while (LIKELY(func0(*this, { _op._u32[0] }))) while (LIKELY(func0(*this, {_op._u32[0]})))
{ {
if (cia += 4, LIKELY(func1(*this, { _op._u32[1] }))) if (cia += 4, LIKELY(func1(*this, {_op._u32[1]})))
{ {
if (cia += 4, LIKELY(func2(*this, { _op._u32[2] }))) if (cia += 4, LIKELY(func2(*this, {_op._u32[2]})))
{ {
cia += 4; cia += 4;
func0 = func3; func0 = func3;
@ -343,8 +350,7 @@ be_t<u64>* ppu_thread::get_stack_arg(s32 i, u64 align)
void ppu_thread::fast_call(u32 addr, u32 rtoc) void ppu_thread::fast_call(u32 addr, u32 rtoc)
{ {
const auto old_pc = cia; const auto old_cia = cia;
const auto old_stack = gpr[1];
const auto old_rtoc = gpr[2]; const auto old_rtoc = gpr[2];
const auto old_lr = lr; const auto old_lr = lr;
const auto old_func = last_function; const auto old_func = last_function;
@ -357,46 +363,46 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
g_tls_log_prefix = [] g_tls_log_prefix = []
{ {
const auto ppu = static_cast<ppu_thread*>(get_current_cpu_thread()); const auto _this = static_cast<ppu_thread*>(get_current_cpu_thread());
return fmt::format("%s [0x%08x]", ppu->get_name(), ppu->cia); return fmt::format("%s [0x%08x]", _this->get_name(), _this->cia);
}; };
auto at_ret = gsl::finally([&]()
{
if (std::uncaught_exception())
{
if (last_function)
{
LOG_WARNING(PPU, "'%s' aborted (%fs)", last_function, (get_system_time() - gpr[10]) / 1000000.);
}
last_function = old_func;
}
else
{
state -= cpu_flag::ret;
cia = old_cia;
gpr[2] = old_rtoc;
lr = old_lr;
last_function = old_func;
g_tls_log_prefix = old_fmt;
}
});
try try
{ {
exec_task(); exec_task();
if (gpr[1] != old_stack && !test(state, cpu_flag::ret + cpu_flag::exit)) // gpr[1] shouldn't change
{
fmt::throw_exception("Stack inconsistency (addr=0x%x, rtoc=0x%x, SP=0x%llx, old=0x%llx)", addr, rtoc, gpr[1], old_stack);
}
} }
catch (cpu_flag _s) catch (cpu_flag _s)
{ {
state += _s; state += _s;
if (_s != cpu_flag::ret) throw;
}
catch (EmulationStopped)
{
if (last_function) LOG_WARNING(PPU, "'%s' aborted (%fs)", last_function, (get_system_time() - gpr[10]) / 1000000.);
last_function = old_func;
throw;
}
catch (...)
{
if (last_function) LOG_ERROR(PPU, "'%s' aborted", last_function);
last_function = old_func;
throw;
}
state -= cpu_flag::ret; if (_s != cpu_flag::ret)
{
cia = old_pc; throw;
gpr[1] = old_stack; }
gpr[2] = old_rtoc; }
lr = old_lr;
last_function = old_func;
g_tls_log_prefix = old_fmt;
} }
u32 ppu_thread::stack_push(u32 size, u32 align_v) u32 ppu_thread::stack_push(u32 size, u32 align_v)

View file

@ -4,6 +4,7 @@
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
#include "sys_lwmutex.h" #include "sys_lwmutex.h"
#include "sys_lwcond.h" #include "sys_lwcond.h"
#include "sys_mutex.h" #include "sys_mutex.h"

View file

@ -1,35 +0,0 @@
#pragma once
enum DbgCommand
{
DID_FIRST_COMMAND = 0x500,
DID_START_EMU,
DID_STARTED_EMU,
DID_STOP_EMU,
DID_STOPPED_EMU,
DID_PAUSE_EMU,
DID_PAUSED_EMU,
DID_RESUME_EMU,
DID_RESUMED_EMU,
DID_READY_EMU,
DID_CREATE_THREAD,
DID_CREATED_THREAD,
DID_REMOVE_THREAD,
DID_REMOVED_THREAD,
DID_RENAME_THREAD,
DID_RENAMED_THREAD,
DID_START_THREAD,
DID_STARTED_THREAD,
DID_STOP_THREAD,
DID_STOPED_THREAD,
DID_PAUSE_THREAD,
DID_PAUSED_THREAD,
DID_RESUME_THREAD,
DID_RESUMED_THREAD,
DID_EXEC_THREAD,
DID_REGISTRED_CALLBACK,
DID_UNREGISTRED_CALLBACK,
DID_LAST_COMMAND,
};

View file

@ -7,6 +7,8 @@
#include "ARMv7Opcodes.h" #include "ARMv7Opcodes.h"
#include "ARMv7Interpreter.h" #include "ARMv7Interpreter.h"
#include "Utilities/GSL.h"
namespace vm { using namespace psv; } namespace vm { using namespace psv; }
const arm_decoder<arm_interpreter> s_arm_interpreter; const arm_decoder<arm_interpreter> s_arm_interpreter;
@ -19,6 +21,9 @@ std::string ARMv7Thread::get_name() const
std::string ARMv7Thread::dump() const std::string ARMv7Thread::dump() const
{ {
std::string result = cpu_thread::dump(); std::string result = cpu_thread::dump();
result += "Last function: ";
result += last_function ? last_function : "";
result += "\n\n";
result += "Registers:\n=========\n"; result += "Registers:\n=========\n";
for(int i=0; i<15; ++i) for(int i=0; i<15; ++i)
{ {
@ -40,7 +45,7 @@ extern thread_local std::string(*g_tls_log_prefix)();
void ARMv7Thread::cpu_task() void ARMv7Thread::cpu_task()
{ {
return custom_task ? custom_task(*this) : fast_call(PC); return fast_call(PC);
} }
void ARMv7Thread::cpu_task_main() void ARMv7Thread::cpu_task_main()
@ -113,50 +118,46 @@ ARMv7Thread::ARMv7Thread(const std::string& name, u32 prio, u32 stack)
void ARMv7Thread::fast_call(u32 addr) void ARMv7Thread::fast_call(u32 addr)
{ {
const auto old_PC = PC; const auto old_PC = PC;
const auto old_SP = SP;
const auto old_LR = LR; const auto old_LR = LR;
const auto old_task = std::move(custom_task);
const auto old_func = last_function; const auto old_func = last_function;
PC = addr; PC = addr;
LR = Emu.GetCPUThreadStop(); LR = Emu.GetCPUThreadStop();
custom_task = nullptr;
last_function = nullptr; last_function = nullptr;
auto at_ret = gsl::finally([&]()
{
if (std::uncaught_exception())
{
if (last_function)
{
LOG_ERROR(ARMv7, "'%s' aborted", last_function);
}
last_function = old_func;
}
else
{
state -= cpu_flag::ret;
PC = old_PC;
LR = old_LR;
last_function = old_func;
}
});
try try
{ {
cpu_task_main(); cpu_task_main();
if (SP != old_SP && !test(state, cpu_flag::ret + cpu_flag::exit)) // SP shouldn't change
{
fmt::throw_exception("Stack inconsistency (addr=0x%x, SP=0x%x, old=0x%x)", addr, SP, old_SP);
}
} }
catch (cpu_flag _s) catch (cpu_flag _s)
{ {
state += _s; state += _s;
if (_s != cpu_flag::ret) throw;
}
catch (EmulationStopped)
{
if (last_function) LOG_WARNING(ARMv7, "'%s' aborted", last_function);
last_function = old_func;
throw;
}
catch (...)
{
if (last_function) LOG_ERROR(ARMv7, "'%s' aborted", last_function);
last_function = old_func;
throw;
}
state -= cpu_flag::ret; if (_s != cpu_flag::ret)
{
PC = old_PC; throw;
SP = old_SP; }
LR = old_LR; }
custom_task = std::move(old_task);
last_function = old_func;
} }
u32 ARMv7Thread::stack_push(u32 size, u32 align_v) u32 ARMv7Thread::stack_push(u32 size, u32 align_v)

View file

@ -139,8 +139,6 @@ public:
const std::string m_name; const std::string m_name;
std::function<void(ARMv7Thread&)> custom_task;
const char* last_function = nullptr; const char* last_function = nullptr;
void write_pc(u32 value, u32 size) void write_pc(u32 value, u32 size)

View file

@ -312,7 +312,6 @@ void Emulator::Load()
} }
debug::autopause::reload(); debug::autopause::reload();
SendDbgCommand(DID_READY_EMU);
if (g_cfg_autostart) Run(); if (g_cfg_autostart) Run();
} }
catch (const std::exception& e) catch (const std::exception& e)
@ -340,8 +339,6 @@ void Emulator::Run()
rpcs3::on_run()(); rpcs3::on_run()();
SendDbgCommand(DID_START_EMU);
m_pause_start_time = 0; m_pause_start_time = 0;
m_pause_amend_time = 0; m_pause_amend_time = 0;
m_status = Running; m_status = Running;
@ -355,8 +352,6 @@ void Emulator::Run()
idm::select<ARMv7Thread>(on_select); idm::select<ARMv7Thread>(on_select);
idm::select<RawSPUThread>(on_select); idm::select<RawSPUThread>(on_select);
idm::select<SPUThread>(on_select); idm::select<SPUThread>(on_select);
SendDbgCommand(DID_STARTED_EMU);
} }
bool Emulator::Pause() bool Emulator::Pause()
@ -377,8 +372,6 @@ bool Emulator::Pause()
LOG_ERROR(GENERAL, "Emulator::Pause() error: concurrent access"); LOG_ERROR(GENERAL, "Emulator::Pause() error: concurrent access");
} }
SendDbgCommand(DID_PAUSE_EMU);
auto on_select = [](u32, cpu_thread& cpu) auto on_select = [](u32, cpu_thread& cpu)
{ {
cpu.state += cpu_flag::dbg_global_pause; cpu.state += cpu_flag::dbg_global_pause;
@ -388,9 +381,6 @@ bool Emulator::Pause()
idm::select<ARMv7Thread>(on_select); idm::select<ARMv7Thread>(on_select);
idm::select<RawSPUThread>(on_select); idm::select<RawSPUThread>(on_select);
idm::select<SPUThread>(on_select); idm::select<SPUThread>(on_select);
SendDbgCommand(DID_PAUSED_EMU);
return true; return true;
} }
@ -416,8 +406,6 @@ void Emulator::Resume()
LOG_ERROR(GENERAL, "Emulator::Resume() error: concurrent access"); LOG_ERROR(GENERAL, "Emulator::Resume() error: concurrent access");
} }
SendDbgCommand(DID_RESUME_EMU);
auto on_select = [](u32, cpu_thread& cpu) auto on_select = [](u32, cpu_thread& cpu)
{ {
cpu.state -= cpu_flag::dbg_global_pause; cpu.state -= cpu_flag::dbg_global_pause;
@ -430,8 +418,6 @@ void Emulator::Resume()
idm::select<SPUThread>(on_select); idm::select<SPUThread>(on_select);
rpcs3::on_resume()(); rpcs3::on_resume()();
SendDbgCommand(DID_RESUMED_EMU);
} }
void Emulator::Stop() void Emulator::Stop()
@ -444,12 +430,11 @@ void Emulator::Stop()
LOG_NOTICE(GENERAL, "Stopping emulator..."); LOG_NOTICE(GENERAL, "Stopping emulator...");
rpcs3::on_stop()(); rpcs3::on_stop()();
SendDbgCommand(DID_STOP_EMU);
auto on_select = [](u32, cpu_thread& cpu) auto on_select = [](u32, cpu_thread& cpu)
{ {
cpu.state += cpu_flag::dbg_global_stop; cpu.state += cpu_flag::dbg_global_stop;
cpu.get()->set_exception(std::make_exception_ptr(EmulationStopped())); cpu.get()->set_exception(std::make_exception_ptr(cpu_flag::dbg_global_stop));
}; };
idm::select<ppu_thread>(on_select); idm::select<ppu_thread>(on_select);
@ -476,8 +461,6 @@ void Emulator::Stop()
RSXIOMem.Clear(); RSXIOMem.Clear();
vm::close(); vm::close();
SendDbgCommand(DID_STOPPED_EMU);
if (g_cfg_autoexit) if (g_cfg_autoexit)
{ {
GetCallbacks().exit(); GetCallbacks().exit();

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "VFS.h" #include "VFS.h"
#include "DbgCommand.h"
enum class system_type enum class system_type
{ {
@ -20,7 +19,6 @@ struct EmuCallbacks
std::function<void(std::function<void()>)> call_after; std::function<void(std::function<void()>)> call_after;
std::function<void()> process_events; std::function<void()> process_events;
std::function<void()> exit; std::function<void()> exit;
std::function<void(DbgCommand, class cpu_thread*)> send_dbg_command;
std::function<std::shared_ptr<class KeyboardHandlerBase>()> get_kb_handler; std::function<std::shared_ptr<class KeyboardHandlerBase>()> get_kb_handler;
std::function<std::shared_ptr<class MouseHandlerBase>()> get_mouse_handler; std::function<std::shared_ptr<class MouseHandlerBase>()> get_mouse_handler;
std::function<std::shared_ptr<class PadHandlerBase>()> get_pad_handler; std::function<std::shared_ptr<class PadHandlerBase>()> get_pad_handler;
@ -39,9 +37,6 @@ enum Status : u32
Ready, Ready,
}; };
// Emulation Stopped exception event
class EmulationStopped {};
class Emulator final class Emulator final
{ {
atomic_t<u32> m_status; atomic_t<u32> m_status;
@ -71,11 +66,6 @@ public:
return m_cb; return m_cb;
} }
void SendDbgCommand(DbgCommand cmd, class cpu_thread* thread = nullptr)
{
if (m_cb.send_dbg_command) m_cb.send_dbg_command(cmd, thread);
}
// Call from the GUI thread // Call from the GUI thread
void CallAfter(std::function<void()>&& func) const void CallAfter(std::function<void()>&& func) const
{ {
@ -135,6 +125,7 @@ public:
bool IsPaused() const { return m_status == Paused; } bool IsPaused() const { return m_status == Paused; }
bool IsStopped() const { return m_status == Stopped; } bool IsStopped() const { return m_status == Stopped; }
bool IsReady() const { return m_status == Ready; } bool IsReady() const { return m_status == Ready; }
auto GetStatus() const { return m_status.load(); }
}; };
extern Emulator Emu; extern Emulator Emu;

View file

@ -107,17 +107,11 @@ enum
id_timer, id_timer,
}; };
BEGIN_EVENT_TABLE(LogFrame, wxPanel)
EVT_CLOSE(LogFrame::OnQuit)
EVT_TIMER(id_timer, LogFrame::OnTimer)
END_EVENT_TABLE()
LogFrame::LogFrame(wxWindow* parent) LogFrame::LogFrame(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(600, 500)) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(600, 500))
, m_tabs(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS) , m_tabs(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS)
, m_log(new wxTextCtrl(&m_tabs, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2)) , m_log(new wxTextCtrl(&m_tabs, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2))
, m_tty(new wxTextCtrl(&m_tabs, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2)) , m_tty(new wxTextCtrl(&m_tabs, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2))
, m_timer(this, id_timer)
, m_cfg_level(g_gui_cfg["Log Level"]) , m_cfg_level(g_gui_cfg["Log Level"])
, m_cfg_tty(g_gui_cfg["Log TTY"]) , m_cfg_tty(g_gui_cfg["Log TTY"])
{ {
@ -142,13 +136,12 @@ LogFrame::LogFrame(wxWindow* parent)
Bind(wxEVT_MENU, &LogFrame::OnContextMenu, this, id_log_level, id_log_level + 7); Bind(wxEVT_MENU, &LogFrame::OnContextMenu, this, id_log_level, id_log_level + 7);
Bind(wxEVT_MENU, &LogFrame::OnContextMenu, this, id_log_tty); Bind(wxEVT_MENU, &LogFrame::OnContextMenu, this, id_log_tty);
Bind(wxEVT_CLOSE_WINDOW, [](wxCloseEvent& event) { event.Skip(); });
Show(); Show();
// Update listener info // Update listener info
s_gui_listener.enabled = get_cfg_level(); s_gui_listener.enabled = get_cfg_level();
// Check for updates every ~10 ms
m_timer.Start(10);
} }
LogFrame::~LogFrame() LogFrame::~LogFrame()
@ -160,11 +153,6 @@ bool LogFrame::Close(bool force)
return wxWindowBase::Close(force); return wxWindowBase::Close(force);
} }
void LogFrame::OnQuit(wxCloseEvent& event)
{
event.Skip();
}
// Deals with the RightClick on Log Console, shows up the Context Menu. // Deals with the RightClick on Log Console, shows up the Context Menu.
void LogFrame::OnRightClick(wxMouseEvent& event) void LogFrame::OnRightClick(wxMouseEvent& event)
{ {
@ -237,7 +225,7 @@ void LogFrame::OnContextMenu(wxCommandEvent& event)
event.Skip(); event.Skip();
} }
void LogFrame::OnTimer(wxTimerEvent& event) void LogFrame::UpdateUI()
{ {
std::vector<char> buf(4096); std::vector<char> buf(4096);

View file

@ -11,8 +11,6 @@ class LogFrame : public wxPanel
//Copy Action in Context Menu //Copy Action in Context Menu
wxTextDataObject* m_tdo; wxTextDataObject* m_tdo;
wxTimer m_timer;
YAML::Node m_cfg_level; YAML::Node m_cfg_level;
YAML::Node m_cfg_tty; YAML::Node m_cfg_tty;
@ -32,14 +30,9 @@ public:
~LogFrame(); ~LogFrame();
bool Close(bool force = false); bool Close(bool force = false);
void UpdateUI();
private: private:
virtual void Task(){};
void OnQuit(wxCloseEvent& event);
void OnRightClick(wxMouseEvent& event); // Show context menu void OnRightClick(wxMouseEvent& event); // Show context menu
void OnContextMenu(wxCommandEvent& event); // After select void OnContextMenu(wxCommandEvent& event); // After select
void OnTimer(wxTimerEvent& event);
DECLARE_EVENT_TABLE();
}; };

View file

@ -16,6 +16,7 @@ class DbgEmuPanel : public wxPanel
wxButton* m_btn_stop; wxButton* m_btn_stop;
wxButton* m_btn_restart; wxButton* m_btn_restart;
wxButton* m_btn_capture_frame; wxButton* m_btn_capture_frame;
u32 m_last_status = Ready;
public: public:
DbgEmuPanel(wxWindow* parent) : wxPanel(parent) DbgEmuPanel(wxWindow* parent) : wxPanel(parent)
@ -43,30 +44,37 @@ public:
Layout(); Layout();
UpdateUI(); UpdateUI();
wxGetApp().Bind(wxEVT_DBG_COMMAND, &DbgEmuPanel::HandleCommand, this);
} }
void UpdateUI() void UpdateUI()
{ {
m_btn_run->Enable(!Emu.IsStopped()); const auto status = Emu.GetStatus();
m_btn_stop->Enable(!Emu.IsStopped());
m_btn_restart->Enable(!Emu.GetPath().empty()); if (m_last_status != status)
{
m_last_status = status;
m_btn_run->Enable(status != Stopped);
m_btn_stop->Enable(status != Stopped);
m_btn_restart->Enable(!Emu.GetPath().empty());
m_btn_run->SetLabel(status == Paused ? "Resume" : status == Running ? "Pause" : "Run");
}
} }
void OnRun(wxCommandEvent& event) void OnRun(wxCommandEvent& event)
{ {
if(Emu.IsRunning()) if (Emu.IsReady())
{
Emu.Run();
}
else if (Emu.IsRunning())
{ {
Emu.Pause(); Emu.Pause();
} }
else if(Emu.IsPaused()) else if (Emu.IsPaused())
{ {
Emu.Resume(); Emu.Resume();
} }
else
{
Emu.Run();
}
} }
void OnStop(wxCommandEvent& event) void OnStop(wxCommandEvent& event)
@ -84,37 +92,16 @@ public:
{ {
user_asked_for_frame_capture = true; user_asked_for_frame_capture = true;
} }
void HandleCommand(wxCommandEvent& event)
{
event.Skip();
switch(event.GetId())
{
case DID_STOP_EMU:
m_btn_run->SetLabel("Run");
break;
case DID_PAUSE_EMU:
m_btn_run->SetLabel("Resume");
break;
case DID_START_EMU:
case DID_RESUME_EMU:
m_btn_run->SetLabel("Pause");
break;
}
UpdateUI();
}
}; };
DebuggerPanel::DebuggerPanel(wxWindow* parent) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(400, 600), wxTAB_TRAVERSAL) DebuggerPanel::DebuggerPanel(wxWindow* parent) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(400, 600), wxTAB_TRAVERSAL)
{ {
m_aui_mgr.SetManagedWindow(this); m_aui_mgr.SetManagedWindow(this);
m_aui_mgr.AddPane(new DbgEmuPanel(this), wxAuiPaneInfo().Top()); m_dbg_panel = new DbgEmuPanel(this);
m_aui_mgr.AddPane(new InterpreterDisAsmFrame(this), wxAuiPaneInfo().Center().CaptionVisible(false).CloseButton().MaximizeButton()); m_disasm_frame = new InterpreterDisAsmFrame(this);
m_aui_mgr.AddPane(m_dbg_panel, wxAuiPaneInfo().Top());
m_aui_mgr.AddPane(m_disasm_frame, wxAuiPaneInfo().Center().CaptionVisible(false).CloseButton().MaximizeButton());
m_aui_mgr.Update(); m_aui_mgr.Update();
} }
@ -125,4 +112,6 @@ DebuggerPanel::~DebuggerPanel()
void DebuggerPanel::UpdateUI() void DebuggerPanel::UpdateUI()
{ {
m_dbg_panel->UpdateUI();
m_disasm_frame->UpdateUI();
} }

View file

@ -2,10 +2,16 @@
#include <wx/listctrl.h> #include <wx/listctrl.h>
#include <wx/aui/aui.h> #include <wx/aui/aui.h>
class DbgEmuPanel;
class InterpreterDisAsmFrame;
class DebuggerPanel : public wxPanel class DebuggerPanel : public wxPanel
{ {
wxAuiManager m_aui_mgr; wxAuiManager m_aui_mgr;
DbgEmuPanel* m_dbg_panel;
InterpreterDisAsmFrame* m_disasm_frame;
public: public:
DebuggerPanel(wxWindow* parent); DebuggerPanel(wxWindow* parent);
~DebuggerPanel(); ~DebuggerPanel();

View file

@ -8,7 +8,7 @@
#include "Emu/Cell/SPUThread.h" #include "Emu/Cell/SPUThread.h"
#include "InstructionEditor.h" #include "InstructionEditor.h"
InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u32 _pc, cpu_thread* _cpu, CPUDisAsm* _disasm) InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u32 _pc, const std::shared_ptr<cpu_thread>& _cpu, CPUDisAsm* _disasm)
: wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition) : wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition)
, pc(_pc) , pc(_pc)
, cpu(_cpu) , cpu(_cpu)
@ -61,6 +61,8 @@ InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u32 _pc, cpu_t
s_panel_margin_x->Add(s_panel_margin_y); s_panel_margin_x->Add(s_panel_margin_y);
s_panel_margin_x->AddSpacer(12); s_panel_margin_x->AddSpacer(12);
const auto cpu = _cpu.get();
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0; const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview)); this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview));

View file

@ -8,10 +8,10 @@ class InstructionEditorDialog : public wxDialog
wxStaticText* t3_preview; wxStaticText* t3_preview;
public: public:
cpu_thread* cpu; std::weak_ptr<cpu_thread> cpu;
public: public:
InstructionEditorDialog(wxPanel *parent, u32 _pc, cpu_thread* _cpu, CPUDisAsm* _disasm); InstructionEditorDialog(wxPanel *parent, u32 _pc, const std::shared_ptr<cpu_thread>& _cpu, CPUDisAsm* _disasm);
void updatePreview(wxCommandEvent& event); void updatePreview(wxCommandEvent& event);
}; };

View file

@ -23,10 +23,17 @@ std::map<u32, bool> g_breakpoints;
u32 InterpreterDisAsmFrame::GetPc() const u32 InterpreterDisAsmFrame::GetPc() const
{ {
const auto cpu = this->cpu.lock();
if (!cpu)
{
return 0;
}
switch (g_system) switch (g_system)
{ {
case system_type::ps3: return cpu->id_type() == 1 ? static_cast<ppu_thread*>(cpu)->cia : static_cast<SPUThread*>(cpu)->pc; case system_type::ps3: return cpu->id_type() == 1 ? static_cast<ppu_thread*>(cpu.get())->cia : static_cast<SPUThread*>(cpu.get())->pc;
case system_type::psv: return static_cast<ARMv7Thread*>(cpu)->PC; case system_type::psv: return static_cast<ARMv7Thread*>(cpu.get())->PC;
} }
return 0xabadcafe; return 0xabadcafe;
@ -40,7 +47,6 @@ u32 InterpreterDisAsmFrame::CentrePc(u32 pc) const
InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent) InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(500, 700), wxTAB_TRAVERSAL) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(500, 700), wxTAB_TRAVERSAL)
, m_pc(0) , m_pc(0)
, cpu(nullptr)
, m_item_count(30) , m_item_count(30)
{ {
wxBoxSizer* s_p_main = new wxBoxSizer(wxVERTICAL); wxBoxSizer* s_p_main = new wxBoxSizer(wxVERTICAL);
@ -68,19 +74,12 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent)
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_DONTWRAP | wxNO_BORDER | wxTE_RICH2); wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_DONTWRAP | wxNO_BORDER | wxTE_RICH2);
m_regs->SetEditable(false); m_regs->SetEditable(false);
//Call Stack
m_calls = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_DONTWRAP | wxNO_BORDER | wxTE_RICH2);
m_calls->SetEditable(false);
m_list->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); m_list->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
m_regs->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); m_regs->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
m_calls->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
wxBoxSizer* s_w_list = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* s_w_list = new wxBoxSizer(wxHORIZONTAL);
s_w_list->Add(m_list, 2, wxEXPAND | wxLEFT | wxDOWN, 5); s_w_list->Add(m_list, 2, wxEXPAND | wxLEFT | wxDOWN, 5);
s_w_list->Add(m_regs, 1, wxEXPAND | wxRIGHT | wxDOWN, 5); s_w_list->Add(m_regs, 1, wxEXPAND | wxRIGHT | wxDOWN, 5);
s_w_list->Add(m_calls, 1, wxEXPAND | wxRIGHT | wxDOWN, 5);
s_p_main->Add(s_b_main, 0, wxEXPAND | wxLEFT | wxRIGHT, 5); s_p_main->Add(s_b_main, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
s_p_main->Add(s_w_list, 1, wxEXPAND | wxDOWN, 5); s_p_main->Add(s_w_list, 1, wxEXPAND | wxDOWN, 5);
@ -107,7 +106,6 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent)
Bind(wxEVT_SIZE, &InterpreterDisAsmFrame::OnResize, this); Bind(wxEVT_SIZE, &InterpreterDisAsmFrame::OnResize, this);
Bind(wxEVT_KEY_DOWN, &InterpreterDisAsmFrame::OnKeyDown, this); Bind(wxEVT_KEY_DOWN, &InterpreterDisAsmFrame::OnKeyDown, this);
wxGetApp().Bind(wxEVT_DBG_COMMAND, &InterpreterDisAsmFrame::HandleCommand, this);
ShowAddr(CentrePc(m_pc)); ShowAddr(CentrePc(m_pc));
UpdateUnitList(); UpdateUnitList();
@ -117,8 +115,68 @@ InterpreterDisAsmFrame::~InterpreterDisAsmFrame()
{ {
} }
void InterpreterDisAsmFrame::UpdateUI()
{
UpdateUnitList();
const auto cpu = this->cpu.lock();
if (!cpu)
{
if (m_last_pc != -1 || m_last_stat)
{
m_last_pc = -1;
m_last_stat = 0;
DoUpdate();
m_btn_run->Disable();
m_btn_step->Disable();
m_btn_pause->Disable();
}
}
else
{
const auto cia = GetPc();
const auto state = cpu->state.load();
if (m_last_pc != cia || m_last_stat != static_cast<u32>(state))
{
m_last_pc = cia;
m_last_stat = static_cast<u32>(state);
DoUpdate();
if (test(state & cpu_flag::dbg_pause))
{
m_btn_run->Enable();
m_btn_step->Enable();
m_btn_pause->Disable();
}
else
{
m_btn_run->Disable();
m_btn_step->Disable();
m_btn_pause->Enable();
}
}
}
}
void InterpreterDisAsmFrame::UpdateUnitList() void InterpreterDisAsmFrame::UpdateUnitList()
{ {
const u64 threads_created = cpu_thread::g_threads_created;
const u64 threads_deleted = cpu_thread::g_threads_deleted;
if (threads_created != m_threads_created || threads_deleted != m_threads_deleted)
{
m_threads_created = threads_created;
m_threads_deleted = threads_deleted;
}
else
{
// Nothing to do
return;
}
m_choice_units->Freeze(); m_choice_units->Freeze();
m_choice_units->Clear(); m_choice_units->Clear();
@ -133,36 +191,41 @@ void InterpreterDisAsmFrame::UpdateUnitList()
idm::select<SPUThread>(on_select); idm::select<SPUThread>(on_select);
m_choice_units->Thaw(); m_choice_units->Thaw();
m_choice_units->Update();
} }
void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event) void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
{ {
m_disasm.reset(); m_disasm.reset();
if (cpu = (cpu_thread*)event.GetClientData()) const auto on_select = [&](u32, cpu_thread& cpu)
{ {
switch (g_system) return event.GetClientData() == &cpu;
{ };
case system_type::ps3:
{
if (cpu->id_type() == 1)
{
m_disasm = std::make_unique<PPUDisAsm>(CPUDisAsm_InterpreterMode);
}
else
{
m_disasm = std::make_unique<SPUDisAsm>(CPUDisAsm_InterpreterMode);
}
break; if (event.GetClientData() == nullptr)
} {
// Nothing selected
case system_type::psv: }
{ else if (auto ppu = idm::select<ppu_thread>(on_select))
m_disasm = std::make_unique<ARMv7DisAsm>(CPUDisAsm_InterpreterMode); {
break; m_disasm = std::make_unique<PPUDisAsm>(CPUDisAsm_InterpreterMode);
} cpu = ppu.ptr;
} }
else if (auto spu1 = idm::select<SPUThread>(on_select))
{
m_disasm = std::make_unique<SPUDisAsm>(CPUDisAsm_InterpreterMode);
cpu = spu1.ptr;
}
else if (auto rspu = idm::select<RawSPUThread>(on_select))
{
m_disasm = std::make_unique<SPUDisAsm>(CPUDisAsm_InterpreterMode);
cpu = rspu.ptr;
}
else if (auto arm = idm::select<ARMv7Thread>(on_select))
{
m_disasm = std::make_unique<ARMv7DisAsm>(CPUDisAsm_InterpreterMode);
cpu = arm.ptr;
} }
DoUpdate(); DoUpdate();
@ -238,7 +301,6 @@ void InterpreterDisAsmFrame::DoUpdate()
wxCommandEvent ce; wxCommandEvent ce;
Show_PC(ce); Show_PC(ce);
WriteRegs(); WriteRegs();
WriteCallStack();
} }
void InterpreterDisAsmFrame::ShowAddr(u32 addr) void InterpreterDisAsmFrame::ShowAddr(u32 addr)
@ -246,6 +308,8 @@ void InterpreterDisAsmFrame::ShowAddr(u32 addr)
m_pc = addr; m_pc = addr;
m_list->Freeze(); m_list->Freeze();
const auto cpu = this->cpu.lock();
if (!cpu) if (!cpu)
{ {
for (uint i = 0; i<m_item_count; ++i, m_pc += 4) for (uint i = 0; i<m_item_count; ++i, m_pc += 4)
@ -291,6 +355,8 @@ void InterpreterDisAsmFrame::ShowAddr(u32 addr)
void InterpreterDisAsmFrame::WriteRegs() void InterpreterDisAsmFrame::WriteRegs()
{ {
const auto cpu = this->cpu.lock();
if (!cpu) if (!cpu)
{ {
m_regs->Clear(); m_regs->Clear();
@ -303,105 +369,6 @@ void InterpreterDisAsmFrame::WriteRegs()
m_regs->Thaw(); m_regs->Thaw();
} }
void InterpreterDisAsmFrame::WriteCallStack()
{
if (!cpu)
{
m_calls->Clear();
return;
}
m_calls->Freeze();
m_calls->Clear();
//m_calls->WriteText(fmt::FromUTF8(data));
m_calls->Thaw();
}
void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event)
{
cpu_thread* thr = (cpu_thread*)event.GetClientData();
event.Skip();
if (!thr)
{
switch (event.GetId())
{
case DID_STOPPED_EMU:
UpdateUnitList();
break;
case DID_PAUSED_EMU:
//DoUpdate();
break;
}
}
else if (cpu && thr == cpu)
{
switch (event.GetId())
{
case DID_PAUSE_THREAD:
m_btn_run->Disable();
m_btn_step->Disable();
m_btn_pause->Disable();
break;
case DID_PAUSED_THREAD:
m_btn_run->Enable();
m_btn_step->Enable();
m_btn_pause->Disable();
DoUpdate();
break;
case DID_START_THREAD:
case DID_EXEC_THREAD:
case DID_RESUME_THREAD:
m_btn_run->Disable();
m_btn_step->Disable();
m_btn_pause->Enable();
break;
case DID_REMOVE_THREAD:
case DID_STOP_THREAD:
m_btn_run->Disable();
m_btn_step->Disable();
m_btn_pause->Disable();
if (event.GetId() == DID_REMOVE_THREAD)
{
//m_choice_units->SetSelection(-1);
//wxCommandEvent event;
//event.SetInt(-1);
//event.SetClientData(nullptr);
//OnSelectUnit(event);
UpdateUnitList();
//DoUpdate();
}
break;
}
}
else
{
switch (event.GetId())
{
case DID_CREATE_THREAD:
UpdateUnitList();
if (m_choice_units->GetSelection() == -1)
{
//m_choice_units->SetSelection(0);
//wxCommandEvent event;
//event.SetInt(0);
//event.SetClientData(&Emu.GetCPU().GetThreads()[0]);
//OnSelectUnit(event);
}
break;
case DID_REMOVED_THREAD:
UpdateUnitList();
break;
}
}
}
void InterpreterDisAsmFrame::OnUpdate(wxCommandEvent& event) void InterpreterDisAsmFrame::OnUpdate(wxCommandEvent& event)
{ {
//WriteRegs(); //WriteRegs();
@ -425,6 +392,8 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event))
diag->SetSizerAndFit(s_panel); diag->SetSizerAndFit(s_panel);
const auto cpu = this->cpu.lock();
if (cpu) p_pc->SetValue(wxString::Format("%x", GetPc())); if (cpu) p_pc->SetValue(wxString::Format("%x", GetPc()));
if (diag->ShowModal() == wxID_OK) if (diag->ShowModal() == wxID_OK)
@ -437,21 +406,25 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event))
void InterpreterDisAsmFrame::Show_PC(wxCommandEvent& WXUNUSED(event)) void InterpreterDisAsmFrame::Show_PC(wxCommandEvent& WXUNUSED(event))
{ {
if (cpu) ShowAddr(CentrePc(GetPc())); if (const auto cpu = this->cpu.lock()) ShowAddr(CentrePc(GetPc()));
} }
void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event)) void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event))
{ {
if (cpu && test(cpu->state & cpu_state_pause)) const auto cpu = this->cpu.lock();
if (cpu && cpu->state.test_and_reset(cpu_flag::dbg_pause))
{ {
cpu->state -= cpu_flag::dbg_pause; if (!test(cpu->state, cpu_state_pause))
cpu->notify(); {
cpu->notify();
}
} }
} }
void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event)) void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event))
{ {
if (cpu) if (const auto cpu = this->cpu.lock())
{ {
cpu->state += cpu_flag::dbg_pause; cpu->state += cpu_flag::dbg_pause;
} }
@ -459,7 +432,7 @@ void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event))
void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event)) void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event))
{ {
if (cpu) if (const auto cpu = this->cpu.lock())
{ {
if (test(cpu_flag::dbg_pause, cpu->state.fetch_op([](bs_t<cpu_flag>& state) if (test(cpu_flag::dbg_pause, cpu->state.fetch_op([](bs_t<cpu_flag>& state)
{ {
@ -474,6 +447,8 @@ void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event))
void InterpreterDisAsmFrame::InstrKey(wxListEvent& event) void InterpreterDisAsmFrame::InstrKey(wxListEvent& event)
{ {
const auto cpu = this->cpu.lock();
long i = m_list->GetFirstSelected(); long i = m_list->GetFirstSelected();
if (i < 0 || !cpu) if (i < 0 || !cpu)
{ {

View file

@ -9,20 +9,25 @@ class InterpreterDisAsmFrame : public wxPanel
std::unique_ptr<CPUDisAsm> m_disasm; std::unique_ptr<CPUDisAsm> m_disasm;
u32 m_pc; u32 m_pc;
wxTextCtrl* m_regs; wxTextCtrl* m_regs;
wxTextCtrl* m_calls;
wxButton* m_btn_step; wxButton* m_btn_step;
wxButton* m_btn_run; wxButton* m_btn_run;
wxButton* m_btn_pause; wxButton* m_btn_pause;
u32 m_item_count; u32 m_item_count;
wxChoice* m_choice_units; wxChoice* m_choice_units;
u64 m_threads_created = 0;
u64 m_threads_deleted = 0;
u32 m_last_pc = -1;
u32 m_last_stat = 0;
public: public:
cpu_thread* cpu; std::weak_ptr<cpu_thread> cpu;
public: public:
InterpreterDisAsmFrame(wxWindow* parent); InterpreterDisAsmFrame(wxWindow* parent);
~InterpreterDisAsmFrame(); ~InterpreterDisAsmFrame();
void UpdateUI();
void UpdateUnitList(); void UpdateUnitList();
u32 GetPc() const; u32 GetPc() const;
@ -33,9 +38,7 @@ public:
void DoUpdate(); void DoUpdate();
void ShowAddr(u32 addr); void ShowAddr(u32 addr);
void WriteRegs(); void WriteRegs();
void WriteCallStack();
void HandleCommand(wxCommandEvent& event);
void OnUpdate(wxCommandEvent& event); void OnUpdate(wxCommandEvent& event);
void Show_Val(wxCommandEvent& event); void Show_Val(wxCommandEvent& event);
void Show_PC(wxCommandEvent& event); void Show_PC(wxCommandEvent& event);

View file

@ -29,10 +29,6 @@
#include "frame_icon.xpm" #include "frame_icon.xpm"
#endif #endif
BEGIN_EVENT_TABLE(MainFrame, FrameBase)
EVT_CLOSE(MainFrame::OnQuit)
END_EVENT_TABLE()
enum IDs enum IDs
{ {
id_boot_elf = 0x555, id_boot_elf = 0x555,
@ -68,6 +64,7 @@ wxString GetPaneName()
MainFrame::MainFrame() MainFrame::MainFrame()
: FrameBase(nullptr, wxID_ANY, "", "MainFrame", wxSize(900, 600)) : FrameBase(nullptr, wxID_ANY, "", "MainFrame", wxSize(900, 600))
, m_timer(this, id_update_dbg)
, m_aui_mgr(this) , m_aui_mgr(this)
, m_sys_menu_opened(false) , m_sys_menu_opened(false)
{ {
@ -160,9 +157,17 @@ MainFrame::MainFrame()
Bind(wxEVT_MENU, &MainFrame::AboutDialogHandler, this, id_help_about); Bind(wxEVT_MENU, &MainFrame::AboutDialogHandler, this, id_help_about);
Bind(wxEVT_MENU, &MainFrame::UpdateUI, this, id_update_dbg); Bind(wxEVT_MENU, &MainFrame::UpdateUI, this, id_update_dbg);
Bind(wxEVT_TIMER, &MainFrame::UpdateUI, this, id_update_dbg);
Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent&)
{
DoSettings(false);
TheApp->Exit();
});
wxGetApp().Bind(wxEVT_KEY_DOWN, &MainFrame::OnKeyDown, this); wxGetApp().Bind(wxEVT_KEY_DOWN, &MainFrame::OnKeyDown, this);
wxGetApp().Bind(wxEVT_DBG_COMMAND, &MainFrame::UpdateUI, this);
// Check for updates every ~10 ms
m_timer.Start(10);
} }
MainFrame::~MainFrame() MainFrame::~MainFrame()
@ -494,67 +499,11 @@ void MainFrame::AboutDialogHandler(wxCommandEvent& WXUNUSED(event))
AboutDialog(this).ShowModal(); AboutDialog(this).ShowModal();
} }
void MainFrame::UpdateUI(wxCommandEvent& event) void MainFrame::UpdateUI(wxEvent& event)
{ {
event.Skip(); const bool is_running = Emu.IsRunning();
const bool is_stopped = Emu.IsStopped();
bool is_running, is_stopped, is_ready; const bool is_ready = Emu.IsReady();
if(event.GetEventType() == wxEVT_DBG_COMMAND)
{
switch(event.GetId())
{
case DID_START_EMU:
case DID_STARTED_EMU:
is_running = true;
is_stopped = false;
is_ready = false;
break;
case DID_STOP_EMU:
case DID_STOPPED_EMU:
is_running = false;
is_stopped = true;
is_ready = false;
m_sys_menu_opened = false;
break;
case DID_PAUSE_EMU:
case DID_PAUSED_EMU:
is_running = false;
is_stopped = false;
is_ready = false;
break;
case DID_RESUME_EMU:
case DID_RESUMED_EMU:
is_running = true;
is_stopped = false;
is_ready = false;
break;
case DID_READY_EMU:
is_running = false;
is_stopped = false;
is_ready = true;
break;
case DID_REGISTRED_CALLBACK:
is_running = Emu.IsRunning();
is_stopped = Emu.IsStopped();
is_ready = Emu.IsReady();
break;
default:
return;
}
}
else
{
is_running = Emu.IsRunning();
is_stopped = Emu.IsStopped();
is_ready = Emu.IsReady();
}
// Update menu items based on the state of the emulator // Update menu items based on the state of the emulator
wxMenuBar& menubar( *GetMenuBar() ); wxMenuBar& menubar( *GetMenuBar() );
@ -583,12 +532,12 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
memory_viewer.Enable(!is_stopped); memory_viewer.Enable(!is_stopped);
rsx_debugger.Enable(!is_stopped); rsx_debugger.Enable(!is_stopped);
string_search.Enable(!is_stopped); string_search.Enable(!is_stopped);
}
void MainFrame::OnQuit(wxCloseEvent& event) // Debugger
{ m_debugger_frame->UpdateUI();
DoSettings(false);
TheApp->Exit(); // Logs
m_log_frame->UpdateUI();
} }
void MainFrame::OnKeyDown(wxKeyEvent& event) void MainFrame::OnKeyDown(wxKeyEvent& event)

View file

@ -8,9 +8,10 @@ class GameViewer;
class MainFrame : public FrameBase class MainFrame : public FrameBase
{ {
wxTimer m_timer;
DebuggerPanel* m_debugger_frame; DebuggerPanel* m_debugger_frame;
GameViewer* m_game_viewer; GameViewer* m_game_viewer;
LogFrame * m_log_frame; LogFrame* m_log_frame;
wxAuiManager m_aui_mgr; wxAuiManager m_aui_mgr;
bool m_sys_menu_opened; bool m_sys_menu_opened;
@ -22,8 +23,6 @@ public:
void DoSettings(bool load); void DoSettings(bool load);
private: private:
void OnQuit(wxCloseEvent& event);
void BootGame(wxCommandEvent& event); void BootGame(wxCommandEvent& event);
void BootGameAndRun(wxCommandEvent& event); void BootGameAndRun(wxCommandEvent& event);
void InstallPkg(wxCommandEvent& event); void InstallPkg(wxCommandEvent& event);
@ -46,9 +45,6 @@ private:
void OpenCgDisasm(wxCommandEvent& evt); void OpenCgDisasm(wxCommandEvent& evt);
void DecryptSPRXLibraries(wxCommandEvent& event); void DecryptSPRXLibraries(wxCommandEvent& event);
void AboutDialogHandler(wxCommandEvent& event); void AboutDialogHandler(wxCommandEvent& event);
void UpdateUI(wxCommandEvent& event); void UpdateUI(wxEvent& event);
void OnKeyDown(wxKeyEvent& event); void OnKeyDown(wxKeyEvent& event);
private:
DECLARE_EVENT_TABLE()
}; };

View file

@ -7,7 +7,7 @@
#include "Emu/Cell/SPUThread.h" #include "Emu/Cell/SPUThread.h"
#include "RegisterEditor.h" #include "RegisterEditor.h"
RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread* _cpu, CPUDisAsm* _disasm) RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, const std::shared_ptr<cpu_thread>& _cpu, CPUDisAsm* _disasm)
: wxDialog(parent, wxID_ANY, "Edit registers") : wxDialog(parent, wxID_ANY, "Edit registers")
, pc(_pc) , pc(_pc)
, cpu(_cpu) , cpu(_cpu)
@ -86,6 +86,8 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
if (ShowModal() == wxID_OK) if (ShowModal() == wxID_OK)
{ {
const auto cpu = _cpu.get();
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection()); std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
std::string value = fmt::ToUTF8(t2_value->GetValue()); std::string value = fmt::ToUTF8(t2_value->GetValue());
@ -166,12 +168,14 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
void RegisterEditorDialog::updateRegister(wxCommandEvent& event) void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
{ {
const auto cpu = this->cpu.lock();
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection()); std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
std::string str; std::string str;
if (g_system == system_type::ps3 && cpu->id_type() == 1) if (g_system == system_type::ps3 && cpu->id_type() == 1)
{ {
auto& ppu = *static_cast<ppu_thread*>(cpu); auto& ppu = *static_cast<ppu_thread*>(cpu.get());
std::size_t first_brk = reg.find('['); std::size_t first_brk = reg.find('[');
if (first_brk != -1) if (first_brk != -1)
@ -187,7 +191,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
} }
else if (g_system == system_type::ps3 && cpu->id_type() != 1) else if (g_system == system_type::ps3 && cpu->id_type() != 1)
{ {
auto& spu = *static_cast<SPUThread*>(cpu); auto& spu = *static_cast<SPUThread*>(cpu.get());
std::string::size_type first_brk = reg.find('['); std::string::size_type first_brk = reg.find('[');
if (first_brk != std::string::npos) if (first_brk != std::string::npos)

View file

@ -9,10 +9,10 @@ class RegisterEditorDialog : public wxDialog
wxStaticText* t3_preview; wxStaticText* t3_preview;
public: public:
cpu_thread* cpu; std::weak_ptr<cpu_thread> cpu;
public: public:
RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread* _cpu, CPUDisAsm* _disasm); RegisterEditorDialog(wxPanel *parent, u32 _pc, const std::shared_ptr<cpu_thread>& _cpu, CPUDisAsm* _disasm);
void updateRegister(wxCommandEvent& event); void updateRegister(wxCommandEvent& event);
}; };

View file

@ -606,7 +606,6 @@
<ClInclude Include="Emu\Cell\SPUThread.h" /> <ClInclude Include="Emu\Cell\SPUThread.h" />
<ClInclude Include="Emu\CPU\CPUDisAsm.h" /> <ClInclude Include="Emu\CPU\CPUDisAsm.h" />
<ClInclude Include="Emu\CPU\CPUThread.h" /> <ClInclude Include="Emu\CPU\CPUThread.h" />
<ClInclude Include="Emu\DbgCommand.h" />
<ClInclude Include="Emu\Memory\wait_engine.h" /> <ClInclude Include="Emu\Memory\wait_engine.h" />
<ClInclude Include="Emu\RSX\Common\TextGlyphs.h" /> <ClInclude Include="Emu\RSX\Common\TextGlyphs.h" />
<ClInclude Include="Emu\RSX\gcm_enums.h" /> <ClInclude Include="Emu\RSX\gcm_enums.h" />

View file

@ -1000,9 +1000,6 @@
<ClInclude Include="..\Utilities\Timer.h"> <ClInclude Include="..\Utilities\Timer.h">
<Filter>Utilities</Filter> <Filter>Utilities</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\DbgCommand.h">
<Filter>Emu</Filter>
</ClInclude>
<ClInclude Include="..\Utilities\Log.h"> <ClInclude Include="..\Utilities\Log.h">
<Filter>Utilities</Filter> <Filter>Utilities</Filter>
</ClInclude> </ClInclude>

View file

@ -65,8 +65,6 @@ void save_gui_cfg()
s_gui_cfg.write(out.c_str(), out.size()); s_gui_cfg.write(out.c_str(), out.size());
} }
wxDEFINE_EVENT(wxEVT_DBG_COMMAND, wxCommandEvent);
IMPLEMENT_APP(Rpcs3App) IMPLEMENT_APP(Rpcs3App)
Rpcs3App* TheApp; Rpcs3App* TheApp;
@ -156,11 +154,6 @@ bool Rpcs3App::OnInit()
wxGetApp().Exit(); wxGetApp().Exit();
}; };
callbacks.send_dbg_command = [](DbgCommand id, cpu_thread* t)
{
wxGetApp().SendDbgCommand(id, t);
};
callbacks.get_kb_handler = []{ return g_cfg_kb_handler.get()(); }; callbacks.get_kb_handler = []{ return g_cfg_kb_handler.get()(); };
callbacks.get_mouse_handler = []{ return g_cfg_mouse_handler.get()(); }; callbacks.get_mouse_handler = []{ return g_cfg_mouse_handler.get()(); };
@ -245,13 +238,6 @@ void Rpcs3App::Exit()
wxApp::Exit(); wxApp::Exit();
} }
void Rpcs3App::SendDbgCommand(DbgCommand id, cpu_thread* thr)
{
wxCommandEvent event(wxEVT_DBG_COMMAND, id);
event.SetClientData(thr);
AddPendingEvent(event);
}
Rpcs3App::Rpcs3App() Rpcs3App::Rpcs3App()
{ {
#ifdef _WIN32 #ifdef _WIN32

View file

@ -1,12 +1,9 @@
#pragma once #pragma once
#include "Gui/MainFrame.h" #include "Gui/MainFrame.h"
#include "Emu/DbgCommand.h"
#include <wx/app.h> #include <wx/app.h>
#include <wx/cmdline.h> #include <wx/cmdline.h>
wxDECLARE_EVENT(wxEVT_DBG_COMMAND, wxCommandEvent);
class Rpcs3App : public wxApp class Rpcs3App : public wxApp
{ {
private: private:
@ -20,8 +17,6 @@ public:
virtual void Exit(); virtual void Exit();
Rpcs3App(); Rpcs3App();
void SendDbgCommand(DbgCommand id, class cpu_thread* thr = nullptr);
}; };
DECLARE_APP(Rpcs3App) DECLARE_APP(Rpcs3App)