mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
Debugger/SPU: Implement SPU Disassembler
This commit is contained in:
parent
7c898c3e4e
commit
d6acdc77e0
@ -65,7 +65,7 @@ extern std::shared_ptr<CPUDisAsm> make_disasm(const cpu_thread* cpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
debugger_frame::debugger_frame(std::shared_ptr<gui_settings> gui_settings, QWidget *parent)
|
debugger_frame::debugger_frame(std::shared_ptr<gui_settings> gui_settings, QWidget *parent)
|
||||||
: custom_dock_widget(tr("Debugger [Press F1 for help]"), parent)
|
: custom_dock_widget(tr("Debugger [Press F1 for Help]"), parent)
|
||||||
, m_gui_settings(std::move(gui_settings))
|
, m_gui_settings(std::move(gui_settings))
|
||||||
{
|
{
|
||||||
setContentsMargins(0, 0, 0, 0);
|
setContentsMargins(0, 0, 0, 0);
|
||||||
@ -177,7 +177,7 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> gui_settings, QWidg
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(m_choice_units, QOverload<int>::of(&QComboBox::activated), this, &debugger_frame::UpdateUI);
|
connect(m_choice_units, QOverload<int>::of(&QComboBox::activated), this, &debugger_frame::UpdateUI);
|
||||||
connect(m_choice_units, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &debugger_frame::OnSelectUnit);
|
connect(m_choice_units, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](){ m_is_spu_disasm_mode = false; OnSelectUnit(); });
|
||||||
connect(this, &QDockWidget::visibilityChanged, this, &debugger_frame::EnableUpdateTimer);
|
connect(this, &QDockWidget::visibilityChanged, this, &debugger_frame::EnableUpdateTimer);
|
||||||
|
|
||||||
connect(m_debugger_list, &debugger_list::BreakpointRequested, m_breakpoint_list, &breakpoint_list::HandleBreakpointRequest);
|
connect(m_debugger_list, &debugger_list::BreakpointRequested, m_breakpoint_list, &breakpoint_list::HandleBreakpointRequest);
|
||||||
@ -317,6 +317,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
"\nKeys Alt+S: Capture SPU images of selected SPU or generalized form when used from PPU."
|
"\nKeys Alt+S: Capture SPU images of selected SPU or generalized form when used from PPU."
|
||||||
"\nKeys Alt+S: Launch a memory viewer pointed to the current RSX semaphores location when used from RSX."
|
"\nKeys Alt+S: Launch a memory viewer pointed to the current RSX semaphores location when used from RSX."
|
||||||
"\nKeys Alt+R: Load last saved SPU state capture."
|
"\nKeys Alt+R: Load last saved SPU state capture."
|
||||||
|
"\nKeys Alt+F5: Show the SPU disassmebler dialog."
|
||||||
"\nKey D: SPU MFC commands logger, MFC debug setting must be enabled."
|
"\nKey D: SPU MFC commands logger, MFC debug setting must be enabled."
|
||||||
"\nKey D: Also PPU calling history logger, interpreter and non-zero call history size must be used."
|
"\nKey D: Also PPU calling history logger, interpreter and non-zero call history size must be used."
|
||||||
"\nKey E: Instruction Editor: click on the instruction you want to modify, then press E."
|
"\nKey E: Instruction Editor: click on the instruction you want to modify, then press E."
|
||||||
@ -484,7 +485,6 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (cpu->get_class() == thread_class::spu && g_cfg.core.mfc_debug)
|
if (cpu->get_class() == thread_class::spu && g_cfg.core.mfc_debug)
|
||||||
{
|
{
|
||||||
const u32 max = get_max_allowed(tr("Max MFC cmds logged"), tr("Decimal only, max allowed is %0."), spu_thread::max_mfc_dump_idx);
|
const u32 max = get_max_allowed(tr("Max MFC cmds logged"), tr("Decimal only, max allowed is %0."), spu_thread::max_mfc_dump_idx);
|
||||||
@ -771,6 +771,16 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
|||||||
DoStep(false);
|
DoStep(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case Qt::Key_F5:
|
||||||
|
{
|
||||||
|
if (modifiers & Qt::AltModifier)
|
||||||
|
{
|
||||||
|
OnSelectSPUDisassembler();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1030,6 +1040,11 @@ void debugger_frame::UpdateUnitList()
|
|||||||
|
|
||||||
void debugger_frame::OnSelectUnit()
|
void debugger_frame::OnSelectUnit()
|
||||||
{
|
{
|
||||||
|
if (m_is_spu_disasm_mode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_thread* selected = nullptr;
|
cpu_thread* selected = nullptr;
|
||||||
|
|
||||||
if (m_emu_state != system_state::stopped)
|
if (m_emu_state != system_state::stopped)
|
||||||
@ -1059,6 +1074,7 @@ void debugger_frame::OnSelectUnit()
|
|||||||
m_disasm.reset();
|
m_disasm.reset();
|
||||||
m_cpu.reset();
|
m_cpu.reset();
|
||||||
m_rsx = nullptr;
|
m_rsx = nullptr;
|
||||||
|
m_spu_disasm_memory.reset();
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
{
|
{
|
||||||
@ -1122,6 +1138,150 @@ void debugger_frame::OnSelectUnit()
|
|||||||
UpdateUI();
|
UpdateUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void debugger_frame::OnSelectSPUDisassembler()
|
||||||
|
{
|
||||||
|
if (m_spu_disasm_dialog)
|
||||||
|
{
|
||||||
|
m_spu_disasm_dialog->move(QCursor::pos());
|
||||||
|
m_spu_disasm_dialog->show();
|
||||||
|
m_spu_disasm_dialog->setFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_spu_disasm_dialog = new QDialog(this);
|
||||||
|
m_spu_disasm_dialog->setWindowTitle(tr("SPU Disassmebler Properties"));
|
||||||
|
|
||||||
|
// Panels
|
||||||
|
QVBoxLayout* vbox_panel(new QVBoxLayout());
|
||||||
|
QHBoxLayout* hbox_expression_input_panel = new QHBoxLayout();
|
||||||
|
QHBoxLayout* hbox_button_panel(new QHBoxLayout());
|
||||||
|
|
||||||
|
// Address expression input
|
||||||
|
QLineEdit* source_eal(new QLineEdit(m_spu_disasm_dialog));
|
||||||
|
QLineEdit* start_pc(new QLineEdit(m_spu_disasm_dialog));
|
||||||
|
source_eal->setFont(m_mono);
|
||||||
|
source_eal->setMaxLength(12);
|
||||||
|
source_eal->setValidator(new QRegularExpressionValidator(QRegularExpression("^(0[xX])?0*[a-fA-F0-9]{0,8}$"), this));
|
||||||
|
start_pc->setFont(m_mono);
|
||||||
|
start_pc->setMaxLength(7);
|
||||||
|
start_pc->setValidator(new QRegularExpressionValidator(QRegularExpression("^(0[xX])?0*[a-fA-F0-9]{0,5}$"), this));
|
||||||
|
|
||||||
|
// Ok/Cancel
|
||||||
|
QPushButton* button_ok = new QPushButton(tr("OK"));
|
||||||
|
QPushButton* button_cancel = new QPushButton(tr("Cancel"));
|
||||||
|
|
||||||
|
hbox_expression_input_panel->addWidget(new QLabel(tr("Source Address: ")));
|
||||||
|
hbox_expression_input_panel->addWidget(source_eal);
|
||||||
|
hbox_expression_input_panel->addSpacing(10);
|
||||||
|
hbox_expression_input_panel->addWidget(new QLabel(tr("Load PC: ")));
|
||||||
|
hbox_expression_input_panel->addWidget(start_pc);
|
||||||
|
|
||||||
|
hbox_button_panel->addWidget(button_ok);
|
||||||
|
hbox_button_panel->addWidget(button_cancel);
|
||||||
|
|
||||||
|
vbox_panel->addLayout(hbox_expression_input_panel);
|
||||||
|
vbox_panel->addSpacing(8);
|
||||||
|
vbox_panel->addLayout(hbox_button_panel);
|
||||||
|
|
||||||
|
m_spu_disasm_dialog->setLayout(vbox_panel);
|
||||||
|
|
||||||
|
const QFont font = source_eal->font();
|
||||||
|
|
||||||
|
source_eal->setPlaceholderText(QString::fromStdString(fmt::format("0x%08x", 0)));
|
||||||
|
start_pc->setPlaceholderText(QString::fromStdString(fmt::format("0x%05x", 0)));
|
||||||
|
|
||||||
|
source_eal->setFixedWidth(gui::utils::get_label_width(source_eal->placeholderText(), &font) + 5);
|
||||||
|
start_pc->setFixedWidth(gui::utils::get_label_width(start_pc->placeholderText(), &font) + 5);
|
||||||
|
|
||||||
|
if (m_spu_disasm_origin_eal)
|
||||||
|
{
|
||||||
|
source_eal->setText(QString::fromStdString(fmt::format("0x%08x", m_spu_disasm_origin_eal)));
|
||||||
|
start_pc->setText(QString::fromStdString(fmt::format("0x%05x", m_spu_disasm_pc)));
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(button_ok, &QAbstractButton::clicked, m_spu_disasm_dialog, &QDialog::accept);
|
||||||
|
connect(button_cancel, &QAbstractButton::clicked, m_spu_disasm_dialog, &QDialog::reject);
|
||||||
|
|
||||||
|
m_spu_disasm_dialog->move(QCursor::pos());
|
||||||
|
m_spu_disasm_dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
connect(m_spu_disasm_dialog, &QDialog::finished, this, [this, source_eal, start_pc](int result)
|
||||||
|
{
|
||||||
|
m_spu_disasm_dialog = nullptr;
|
||||||
|
|
||||||
|
if (result != QDialog::Accepted)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const u64 spu_base = EvaluateExpression(start_pc->text());
|
||||||
|
|
||||||
|
if (spu_base > SPU_LS_SIZE - 4 || spu_base % 4)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u64 spu_addr = EvaluateExpression(source_eal->text());
|
||||||
|
|
||||||
|
if (spu_addr == umax || !spu_addr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to load as much memory as possible until SPU local memory ends
|
||||||
|
// Because I don't think there is a need for a size argument
|
||||||
|
// The user probably does not know the exact size of the SPU code either
|
||||||
|
u32 spu_size = SPU_LS_SIZE - spu_base;
|
||||||
|
|
||||||
|
for (u32 passed = spu_base; passed < SPU_LS_SIZE; passed += 4096)
|
||||||
|
{
|
||||||
|
if (!vm::check_addr(spu_addr + passed))
|
||||||
|
{
|
||||||
|
if (passed == spu_base)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spu_size = passed - spu_base - (spu_addr + passed) % 4096;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (4096 > ~(spu_addr + passed))
|
||||||
|
{
|
||||||
|
// For overflow
|
||||||
|
spu_size = std::min<u32>(SPU_LS_SIZE, 0 - spu_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_disasm.reset();
|
||||||
|
m_cpu.reset();
|
||||||
|
m_rsx = nullptr;
|
||||||
|
|
||||||
|
m_spu_disasm_memory = std::make_shared<utils::shm>(SPU_LS_SIZE);
|
||||||
|
m_spu_disasm_memory->map_self();
|
||||||
|
m_is_spu_disasm_mode = true;
|
||||||
|
|
||||||
|
std::memset(m_spu_disasm_memory->get(), 0, spu_base);
|
||||||
|
std::memcpy(m_spu_disasm_memory->get() + spu_base, vm::get_super_ptr(spu_addr), spu_size);
|
||||||
|
std::memset(m_spu_disasm_memory->get() + spu_base + spu_size, 0, SPU_LS_SIZE - (spu_base + spu_size));
|
||||||
|
|
||||||
|
m_spu_disasm_pc = spu_base;
|
||||||
|
m_spu_disasm_origin_eal = spu_addr;
|
||||||
|
|
||||||
|
m_disasm = std::make_shared<SPUDisAsm>(cpu_disasm_mode::interpreter, m_spu_disasm_memory->get());
|
||||||
|
|
||||||
|
EnableButtons(true);
|
||||||
|
|
||||||
|
m_debugger_list->UpdateCPUData(nullptr, m_disasm.get());
|
||||||
|
m_breakpoint_list->UpdateCPUData(nullptr, m_disasm.get());
|
||||||
|
ShowPC(true);
|
||||||
|
DoUpdate();
|
||||||
|
UpdateUI();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_spu_disasm_dialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
void debugger_frame::DoUpdate()
|
void debugger_frame::DoUpdate()
|
||||||
{
|
{
|
||||||
// Check if we need to disable a step over bp
|
// Check if we need to disable a step over bp
|
||||||
@ -1219,7 +1379,7 @@ void debugger_frame::ShowGotoAddressDialog()
|
|||||||
// -1 from get_pc() turns into 0
|
// -1 from get_pc() turns into 0
|
||||||
const u32 pc = cpu ? utils::align<u32>(cpu->get_pc(), 4) : 0;
|
const u32 pc = cpu ? utils::align<u32>(cpu->get_pc(), 4) : 0;
|
||||||
expression_input->setPlaceholderText(QString("0x%1").arg(pc, 16, 16, QChar('0')));
|
expression_input->setPlaceholderText(QString("0x%1").arg(pc, 16, 16, QChar('0')));
|
||||||
expression_input->setFixedWidth(gui::utils::get_label_width(expression_input->placeholderText(), &font));
|
expression_input->setFixedWidth(gui::utils::get_label_width(expression_input->placeholderText(), &font) + 5);
|
||||||
|
|
||||||
connect(button_ok, &QAbstractButton::clicked, m_goto_dialog, &QDialog::accept);
|
connect(button_ok, &QAbstractButton::clicked, m_goto_dialog, &QDialog::accept);
|
||||||
connect(button_cancel, &QAbstractButton::clicked, m_goto_dialog, &QDialog::reject);
|
connect(button_cancel, &QAbstractButton::clicked, m_goto_dialog, &QDialog::reject);
|
||||||
@ -1329,7 +1489,7 @@ void debugger_frame::ShowPC(bool user_requested)
|
|||||||
{
|
{
|
||||||
const auto cpu0 = get_cpu();
|
const auto cpu0 = get_cpu();
|
||||||
|
|
||||||
const u32 pc = (cpu0 ? cpu0->get_pc() : 0);
|
const u32 pc = (cpu0 ? cpu0->get_pc() : (m_is_spu_disasm_mode ? m_spu_disasm_pc : 0));
|
||||||
|
|
||||||
if (user_requested)
|
if (user_requested)
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,11 @@ namespace rsx
|
|||||||
class thread;
|
class thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
class shm;
|
||||||
|
}
|
||||||
|
|
||||||
enum class system_state : u32;
|
enum class system_state : u32;
|
||||||
|
|
||||||
class instruction_editor_dialog;
|
class instruction_editor_dialog;
|
||||||
@ -67,6 +72,10 @@ class debugger_frame : public custom_dock_widget
|
|||||||
std::shared_ptr<CPUDisAsm> m_disasm; // Only shared to allow base/derived functionality
|
std::shared_ptr<CPUDisAsm> m_disasm; // Only shared to allow base/derived functionality
|
||||||
std::shared_ptr<cpu_thread> m_cpu;
|
std::shared_ptr<cpu_thread> m_cpu;
|
||||||
rsx::thread* m_rsx = nullptr;
|
rsx::thread* m_rsx = nullptr;
|
||||||
|
std::shared_ptr<utils::shm> m_spu_disasm_memory;
|
||||||
|
u32 m_spu_disasm_origin_eal = 0;
|
||||||
|
u32 m_spu_disasm_pc = 0;
|
||||||
|
bool m_is_spu_disasm_mode = false;
|
||||||
|
|
||||||
breakpoint_list* m_breakpoint_list;
|
breakpoint_list* m_breakpoint_list;
|
||||||
breakpoint_handler* m_ppu_breakpoint_handler;
|
breakpoint_handler* m_ppu_breakpoint_handler;
|
||||||
@ -74,6 +83,7 @@ class debugger_frame : public custom_dock_widget
|
|||||||
instruction_editor_dialog* m_inst_editor = nullptr;
|
instruction_editor_dialog* m_inst_editor = nullptr;
|
||||||
register_editor_dialog* m_reg_editor = nullptr;
|
register_editor_dialog* m_reg_editor = nullptr;
|
||||||
QDialog* m_goto_dialog = nullptr;
|
QDialog* m_goto_dialog = nullptr;
|
||||||
|
QDialog* m_spu_disasm_dialog = nullptr;
|
||||||
|
|
||||||
std::shared_ptr<gui_settings> m_gui_settings;
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
|
|
||||||
@ -119,6 +129,7 @@ public Q_SLOTS:
|
|||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void OnSelectUnit();
|
void OnSelectUnit();
|
||||||
|
void OnSelectSPUDisassembler();
|
||||||
void ShowPC(bool user_requested = false);
|
void ShowPC(bool user_requested = false);
|
||||||
void EnableUpdateTimer(bool enable) const;
|
void EnableUpdateTimer(bool enable) const;
|
||||||
void RunBtnPress();
|
void RunBtnPress();
|
||||||
|
@ -73,7 +73,7 @@ u32 debugger_list::GetStartAddress(u32 address)
|
|||||||
const u32 steps = m_item_count / 3;
|
const u32 steps = m_item_count / 3;
|
||||||
const u32 inst_count_jump_on_step = std::min<u32>(steps, 4);
|
const u32 inst_count_jump_on_step = std::min<u32>(steps, 4);
|
||||||
|
|
||||||
const bool is_spu = m_cpu && m_cpu->get_class() == thread_class::spu;
|
const bool is_spu = IsSpu();
|
||||||
const u32 address_mask = (is_spu ? 0x3fffc : ~3);
|
const u32 address_mask = (is_spu ? 0x3fffc : ~3);
|
||||||
|
|
||||||
u32 result = address & address_mask;
|
u32 result = address & address_mask;
|
||||||
@ -129,6 +129,11 @@ u32 debugger_list::GetStartAddress(u32 address)
|
|||||||
return m_start_addr;
|
return m_start_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool debugger_list::IsSpu() const
|
||||||
|
{
|
||||||
|
return (m_cpu && m_cpu->get_class() == thread_class::spu) || (m_disasm && !m_cpu);
|
||||||
|
}
|
||||||
|
|
||||||
void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct)
|
void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct)
|
||||||
{
|
{
|
||||||
const decltype(spu_thread::local_breakpoints)* spu_bps_list{};
|
const decltype(spu_thread::local_breakpoints)* spu_bps_list{};
|
||||||
@ -190,7 +195,7 @@ void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_cpu || !m_disasm || +m_cpu->state + cpu_flag::exit + cpu_flag::wait == +m_cpu->state)
|
if (!m_disasm || (m_cpu && m_cpu->state.all_of(cpu_flag::exit + cpu_flag::wait)))
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < m_item_count; ++i)
|
for (uint i = 0; i < m_item_count; ++i)
|
||||||
{
|
{
|
||||||
@ -202,9 +207,9 @@ void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const bool is_spu = m_cpu->get_class() == thread_class::spu;
|
const bool is_spu = IsSpu();
|
||||||
const u32 address_limits = (is_spu ? 0x3fffc : ~3);
|
const u32 address_limits = (is_spu ? 0x3fffc : ~3);
|
||||||
const u32 current_pc = m_cpu->get_pc();
|
const u32 current_pc = (m_cpu ? m_cpu->get_pc() : 0);
|
||||||
m_start_addr &= address_limits;
|
m_start_addr &= address_limits;
|
||||||
pc = m_start_addr;
|
pc = m_start_addr;
|
||||||
|
|
||||||
@ -238,14 +243,14 @@ void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct)
|
|||||||
list_item->setBackground(default_background);
|
list_item->setBackground(default_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cpu->get_class() == thread_class::ppu && !vm::check_addr(pc, 0))
|
if (m_cpu && m_cpu->get_class() == thread_class::ppu && !vm::check_addr(pc, 0))
|
||||||
{
|
{
|
||||||
list_item->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] ?? ?? ?? ??:", pc)));
|
list_item->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] ?? ?? ?? ??:", pc)));
|
||||||
count = 4;
|
count = 4;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cpu->get_class() == thread_class::ppu && !vm::check_addr(pc, vm::page_executable))
|
if (m_cpu && m_cpu->get_class() == thread_class::ppu && !vm::check_addr(pc, vm::page_executable))
|
||||||
{
|
{
|
||||||
const u32 data = *vm::get_super_ptr<atomic_be_t<u32>>(pc);
|
const u32 data = *vm::get_super_ptr<atomic_be_t<u32>>(pc);
|
||||||
list_item->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] %02x %02x %02x %02x:", pc,
|
list_item->setText((IsBreakpoint(pc) ? ">> " : " ") + qstr(fmt::format("[%08x] %02x %02x %02x %02x:", pc,
|
||||||
|
@ -52,6 +52,7 @@ private:
|
|||||||
* It really upsetted me I had to copy this code to make debugger_list/frame not circularly dependent.
|
* It really upsetted me I had to copy this code to make debugger_list/frame not circularly dependent.
|
||||||
*/
|
*/
|
||||||
u32 GetStartAddress(u32 address);
|
u32 GetStartAddress(u32 address);
|
||||||
|
bool IsSpu() const;
|
||||||
|
|
||||||
std::shared_ptr<gui_settings> m_gui_settings;
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
|
|
||||||
|
@ -942,7 +942,7 @@ namespace utils
|
|||||||
{
|
{
|
||||||
void* ptr = m_ptr;
|
void* ptr = m_ptr;
|
||||||
|
|
||||||
if (!ptr)
|
while (!ptr)
|
||||||
{
|
{
|
||||||
const auto mapped = this->map(nullptr, prot);
|
const auto mapped = this->map(nullptr, prot);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user