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());
Emu.Pause();
}
catch (EmulationStopped)
{
LOG_NOTICE(GENERAL, "Thread aborted");
}
on_exit();
});

View file

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

View file

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

View file

@ -44,6 +44,7 @@
#endif
#include <cfenv>
#include "Utilities/GSL.h"
extern u64 get_system_time();
@ -90,6 +91,7 @@ std::string ppu_thread::dump() const
{
std::string ret = cpu_thread::dump();
ret += fmt::format("Priority: %d\n", prio);
ret += fmt::format("Last function: %s\n", last_function ? last_function : "");
ret += "\nRegisters:\n=========\n";
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 (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
@ -223,11 +230,11 @@ void ppu_thread::exec_task()
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;
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)
{
const auto old_pc = cia;
const auto old_stack = gpr[1];
const auto old_cia = cia;
const auto old_rtoc = gpr[2];
const auto old_lr = lr;
const auto old_func = last_function;
@ -357,46 +363,46 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
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
{
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)
{
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;
cia = old_pc;
gpr[1] = old_stack;
gpr[2] = old_rtoc;
lr = old_lr;
last_function = old_func;
g_tls_log_prefix = old_fmt;
if (_s != cpu_flag::ret)
{
throw;
}
}
}
u32 ppu_thread::stack_push(u32 size, u32 align_v)

View file

@ -4,6 +4,7 @@
#include "Emu/IdManager.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
#include "sys_lwmutex.h"
#include "sys_lwcond.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 "ARMv7Interpreter.h"
#include "Utilities/GSL.h"
namespace vm { using namespace psv; }
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 result = cpu_thread::dump();
result += "Last function: ";
result += last_function ? last_function : "";
result += "\n\n";
result += "Registers:\n=========\n";
for(int i=0; i<15; ++i)
{
@ -40,7 +45,7 @@ extern thread_local std::string(*g_tls_log_prefix)();
void ARMv7Thread::cpu_task()
{
return custom_task ? custom_task(*this) : fast_call(PC);
return fast_call(PC);
}
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)
{
const auto old_PC = PC;
const auto old_SP = SP;
const auto old_LR = LR;
const auto old_task = std::move(custom_task);
const auto old_func = last_function;
PC = addr;
LR = Emu.GetCPUThreadStop();
custom_task = 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
{
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)
{
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;
PC = old_PC;
SP = old_SP;
LR = old_LR;
custom_task = std::move(old_task);
last_function = old_func;
if (_s != cpu_flag::ret)
{
throw;
}
}
}
u32 ARMv7Thread::stack_push(u32 size, u32 align_v)

View file

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

View file

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

View file

@ -1,7 +1,6 @@
#pragma once
#include "VFS.h"
#include "DbgCommand.h"
enum class system_type
{
@ -20,7 +19,6 @@ struct EmuCallbacks
std::function<void(std::function<void()>)> call_after;
std::function<void()> process_events;
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 MouseHandlerBase>()> get_mouse_handler;
std::function<std::shared_ptr<class PadHandlerBase>()> get_pad_handler;
@ -39,9 +37,6 @@ enum Status : u32
Ready,
};
// Emulation Stopped exception event
class EmulationStopped {};
class Emulator final
{
atomic_t<u32> m_status;
@ -71,11 +66,6 @@ public:
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
void CallAfter(std::function<void()>&& func) const
{
@ -135,6 +125,7 @@ public:
bool IsPaused() const { return m_status == Paused; }
bool IsStopped() const { return m_status == Stopped; }
bool IsReady() const { return m_status == Ready; }
auto GetStatus() const { return m_status.load(); }
};
extern Emulator Emu;

View file

@ -107,17 +107,11 @@ enum
id_timer,
};
BEGIN_EVENT_TABLE(LogFrame, wxPanel)
EVT_CLOSE(LogFrame::OnQuit)
EVT_TIMER(id_timer, LogFrame::OnTimer)
END_EVENT_TABLE()
LogFrame::LogFrame(wxWindow* parent)
: 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_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_timer(this, id_timer)
, m_cfg_level(g_gui_cfg["Log Level"])
, 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_tty);
Bind(wxEVT_CLOSE_WINDOW, [](wxCloseEvent& event) { event.Skip(); });
Show();
// Update listener info
s_gui_listener.enabled = get_cfg_level();
// Check for updates every ~10 ms
m_timer.Start(10);
}
LogFrame::~LogFrame()
@ -160,11 +153,6 @@ bool LogFrame::Close(bool force)
return wxWindowBase::Close(force);
}
void LogFrame::OnQuit(wxCloseEvent& event)
{
event.Skip();
}
// Deals with the RightClick on Log Console, shows up the Context Menu.
void LogFrame::OnRightClick(wxMouseEvent& event)
{
@ -237,7 +225,7 @@ void LogFrame::OnContextMenu(wxCommandEvent& event)
event.Skip();
}
void LogFrame::OnTimer(wxTimerEvent& event)
void LogFrame::UpdateUI()
{
std::vector<char> buf(4096);

View file

@ -11,8 +11,6 @@ class LogFrame : public wxPanel
//Copy Action in Context Menu
wxTextDataObject* m_tdo;
wxTimer m_timer;
YAML::Node m_cfg_level;
YAML::Node m_cfg_tty;
@ -32,14 +30,9 @@ public:
~LogFrame();
bool Close(bool force = false);
void UpdateUI();
private:
virtual void Task(){};
void OnQuit(wxCloseEvent& event);
void OnRightClick(wxMouseEvent& event); // Show context menu
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_restart;
wxButton* m_btn_capture_frame;
u32 m_last_status = Ready;
public:
DbgEmuPanel(wxWindow* parent) : wxPanel(parent)
@ -43,30 +44,37 @@ public:
Layout();
UpdateUI();
wxGetApp().Bind(wxEVT_DBG_COMMAND, &DbgEmuPanel::HandleCommand, this);
}
void UpdateUI()
{
m_btn_run->Enable(!Emu.IsStopped());
m_btn_stop->Enable(!Emu.IsStopped());
m_btn_restart->Enable(!Emu.GetPath().empty());
const auto status = Emu.GetStatus();
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)
{
if(Emu.IsRunning())
if (Emu.IsReady())
{
Emu.Run();
}
else if (Emu.IsRunning())
{
Emu.Pause();
}
else if(Emu.IsPaused())
else if (Emu.IsPaused())
{
Emu.Resume();
}
else
{
Emu.Run();
}
}
void OnStop(wxCommandEvent& event)
@ -84,37 +92,16 @@ public:
{
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)
{
m_aui_mgr.SetManagedWindow(this);
m_aui_mgr.AddPane(new DbgEmuPanel(this), wxAuiPaneInfo().Top());
m_aui_mgr.AddPane(new InterpreterDisAsmFrame(this), wxAuiPaneInfo().Center().CaptionVisible(false).CloseButton().MaximizeButton());
m_dbg_panel = new DbgEmuPanel(this);
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();
}
@ -125,4 +112,6 @@ DebuggerPanel::~DebuggerPanel()
void DebuggerPanel::UpdateUI()
{
m_dbg_panel->UpdateUI();
m_disasm_frame->UpdateUI();
}

View file

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

View file

@ -8,7 +8,7 @@
#include "Emu/Cell/SPUThread.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)
, pc(_pc)
, 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->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;
this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview));

View file

@ -8,10 +8,10 @@ class InstructionEditorDialog : public wxDialog
wxStaticText* t3_preview;
public:
cpu_thread* cpu;
std::weak_ptr<cpu_thread> cpu;
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);
};

View file

@ -23,10 +23,17 @@ std::map<u32, bool> g_breakpoints;
u32 InterpreterDisAsmFrame::GetPc() const
{
const auto cpu = this->cpu.lock();
if (!cpu)
{
return 0;
}
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::psv: return static_cast<ARMv7Thread*>(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.get())->PC;
}
return 0xabadcafe;
@ -40,7 +47,6 @@ u32 InterpreterDisAsmFrame::CentrePc(u32 pc) const
InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(500, 700), wxTAB_TRAVERSAL)
, m_pc(0)
, cpu(nullptr)
, m_item_count(30)
{
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);
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_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);
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_calls, 1, wxEXPAND | wxRIGHT | wxDOWN, 5);
s_p_main->Add(s_b_main, 0, wxEXPAND | wxLEFT | wxRIGHT, 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_KEY_DOWN, &InterpreterDisAsmFrame::OnKeyDown, this);
wxGetApp().Bind(wxEVT_DBG_COMMAND, &InterpreterDisAsmFrame::HandleCommand, this);
ShowAddr(CentrePc(m_pc));
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()
{
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->Clear();
@ -133,36 +191,41 @@ void InterpreterDisAsmFrame::UpdateUnitList()
idm::select<SPUThread>(on_select);
m_choice_units->Thaw();
m_choice_units->Update();
}
void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
{
m_disasm.reset();
if (cpu = (cpu_thread*)event.GetClientData())
const auto on_select = [&](u32, cpu_thread& cpu)
{
switch (g_system)
{
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);
}
return event.GetClientData() == &cpu;
};
break;
}
case system_type::psv:
{
m_disasm = std::make_unique<ARMv7DisAsm>(CPUDisAsm_InterpreterMode);
break;
}
}
if (event.GetClientData() == nullptr)
{
// Nothing selected
}
else if (auto ppu = idm::select<ppu_thread>(on_select))
{
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();
@ -238,7 +301,6 @@ void InterpreterDisAsmFrame::DoUpdate()
wxCommandEvent ce;
Show_PC(ce);
WriteRegs();
WriteCallStack();
}
void InterpreterDisAsmFrame::ShowAddr(u32 addr)
@ -246,6 +308,8 @@ void InterpreterDisAsmFrame::ShowAddr(u32 addr)
m_pc = addr;
m_list->Freeze();
const auto cpu = this->cpu.lock();
if (!cpu)
{
for (uint i = 0; i<m_item_count; ++i, m_pc += 4)
@ -291,6 +355,8 @@ void InterpreterDisAsmFrame::ShowAddr(u32 addr)
void InterpreterDisAsmFrame::WriteRegs()
{
const auto cpu = this->cpu.lock();
if (!cpu)
{
m_regs->Clear();
@ -303,105 +369,6 @@ void InterpreterDisAsmFrame::WriteRegs()
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)
{
//WriteRegs();
@ -425,6 +392,8 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event))
diag->SetSizerAndFit(s_panel);
const auto cpu = this->cpu.lock();
if (cpu) p_pc->SetValue(wxString::Format("%x", GetPc()));
if (diag->ShowModal() == wxID_OK)
@ -437,21 +406,25 @@ void InterpreterDisAsmFrame::Show_Val(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))
{
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;
cpu->notify();
if (!test(cpu->state, cpu_state_pause))
{
cpu->notify();
}
}
}
void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event))
{
if (cpu)
if (const auto cpu = this->cpu.lock())
{
cpu->state += cpu_flag::dbg_pause;
}
@ -459,7 +432,7 @@ void InterpreterDisAsmFrame::DoPause(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)
{
@ -474,6 +447,8 @@ void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event))
void InterpreterDisAsmFrame::InstrKey(wxListEvent& event)
{
const auto cpu = this->cpu.lock();
long i = m_list->GetFirstSelected();
if (i < 0 || !cpu)
{

View file

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

View file

@ -29,10 +29,6 @@
#include "frame_icon.xpm"
#endif
BEGIN_EVENT_TABLE(MainFrame, FrameBase)
EVT_CLOSE(MainFrame::OnQuit)
END_EVENT_TABLE()
enum IDs
{
id_boot_elf = 0x555,
@ -68,6 +64,7 @@ wxString GetPaneName()
MainFrame::MainFrame()
: FrameBase(nullptr, wxID_ANY, "", "MainFrame", wxSize(900, 600))
, m_timer(this, id_update_dbg)
, m_aui_mgr(this)
, m_sys_menu_opened(false)
{
@ -160,9 +157,17 @@ MainFrame::MainFrame()
Bind(wxEVT_MENU, &MainFrame::AboutDialogHandler, this, id_help_about);
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_DBG_COMMAND, &MainFrame::UpdateUI, this);
// Check for updates every ~10 ms
m_timer.Start(10);
}
MainFrame::~MainFrame()
@ -494,67 +499,11 @@ void MainFrame::AboutDialogHandler(wxCommandEvent& WXUNUSED(event))
AboutDialog(this).ShowModal();
}
void MainFrame::UpdateUI(wxCommandEvent& event)
void MainFrame::UpdateUI(wxEvent& event)
{
event.Skip();
bool is_running, is_stopped, is_ready;
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();
}
const bool is_running = Emu.IsRunning();
const bool is_stopped = Emu.IsStopped();
const bool is_ready = Emu.IsReady();
// Update menu items based on the state of the emulator
wxMenuBar& menubar( *GetMenuBar() );
@ -583,12 +532,12 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
memory_viewer.Enable(!is_stopped);
rsx_debugger.Enable(!is_stopped);
string_search.Enable(!is_stopped);
}
void MainFrame::OnQuit(wxCloseEvent& event)
{
DoSettings(false);
TheApp->Exit();
// Debugger
m_debugger_frame->UpdateUI();
// Logs
m_log_frame->UpdateUI();
}
void MainFrame::OnKeyDown(wxKeyEvent& event)

View file

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

View file

@ -7,7 +7,7 @@
#include "Emu/Cell/SPUThread.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")
, pc(_pc)
, cpu(_cpu)
@ -86,6 +86,8 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
if (ShowModal() == wxID_OK)
{
const auto cpu = _cpu.get();
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
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)
{
const auto cpu = this->cpu.lock();
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
std::string str;
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('[');
if (first_brk != -1)
@ -187,7 +191,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
}
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('[');
if (first_brk != std::string::npos)

View file

@ -9,10 +9,10 @@ class RegisterEditorDialog : public wxDialog
wxStaticText* t3_preview;
public:
cpu_thread* cpu;
std::weak_ptr<cpu_thread> cpu;
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);
};

View file

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

View file

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

View file

@ -65,8 +65,6 @@ void save_gui_cfg()
s_gui_cfg.write(out.c_str(), out.size());
}
wxDEFINE_EVENT(wxEVT_DBG_COMMAND, wxCommandEvent);
IMPLEMENT_APP(Rpcs3App)
Rpcs3App* TheApp;
@ -156,11 +154,6 @@ bool Rpcs3App::OnInit()
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_mouse_handler = []{ return g_cfg_mouse_handler.get()(); };
@ -245,13 +238,6 @@ void Rpcs3App::Exit()
wxApp::Exit();
}
void Rpcs3App::SendDbgCommand(DbgCommand id, cpu_thread* thr)
{
wxCommandEvent event(wxEVT_DBG_COMMAND, id);
event.SetClientData(thr);
AddPendingEvent(event);
}
Rpcs3App::Rpcs3App()
{
#ifdef _WIN32

View file

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