mirror of https://github.com/RPCS3/rpcs3.git
Qt/Utilities: Merge memory viewer with searcher
This commit is contained in:
parent
9ab4802d07
commit
f5b9d86e42
|
@ -284,9 +284,6 @@
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_main_window.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_main_window.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_memory_string_searcher.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_memory_viewer_panel.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_memory_viewer_panel.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -524,9 +521,6 @@
|
||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_main_window.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_main_window.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_memory_string_searcher.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_memory_viewer_panel.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_memory_viewer_panel.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -881,16 +875,6 @@
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
<CustomBuild Include="rpcs3qt\memory_string_searcher.h">
|
|
||||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing memory_string_searcher.h...</Message>
|
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
|
||||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing memory_string_searcher.h...</Message>
|
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="rpcs3qt\gui_settings.h">
|
<CustomBuild Include="rpcs3qt\gui_settings.h">
|
||||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing gui_settings.h...</Message>
|
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing gui_settings.h...</Message>
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
|
|
|
@ -1222,9 +1222,6 @@
|
||||||
<CustomBuild Include="rpcs3qt\game_list_grid.h">
|
<CustomBuild Include="rpcs3qt\game_list_grid.h">
|
||||||
<Filter>Gui\game list</Filter>
|
<Filter>Gui\game list</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
<CustomBuild Include="rpcs3qt\memory_string_searcher.h">
|
|
||||||
<Filter>Gui\dev tools</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="rpcs3qt\settings_dialog.h">
|
<CustomBuild Include="rpcs3qt\settings_dialog.h">
|
||||||
<Filter>Gui\settings</Filter>
|
<Filter>Gui\settings</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include "register_editor_dialog.h"
|
#include "register_editor_dialog.h"
|
||||||
#include "instruction_editor_dialog.h"
|
#include "instruction_editor_dialog.h"
|
||||||
#include "memory_viewer_panel.h"
|
#include "memory_viewer_panel.h"
|
||||||
#include "memory_string_searcher.h"
|
|
||||||
#include "gui_settings.h"
|
#include "gui_settings.h"
|
||||||
#include "debugger_list.h"
|
#include "debugger_list.h"
|
||||||
#include "breakpoint_list.h"
|
#include "breakpoint_list.h"
|
||||||
|
@ -290,7 +289,6 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
||||||
QLabel* l = new QLabel(tr(
|
QLabel* l = new QLabel(tr(
|
||||||
"Keys Ctrl+G: Go to typed address."
|
"Keys Ctrl+G: Go to typed address."
|
||||||
"\nKeys Ctrl+B: Open breakpoints settings."
|
"\nKeys Ctrl+B: Open breakpoints settings."
|
||||||
"\nKeys Ctrl+S: Search memory string utility."
|
|
||||||
"\nKeys Alt+S: Capture SPU images of selected SPU."
|
"\nKeys Alt+S: Capture SPU images of selected SPU."
|
||||||
"\nKeys Alt+R: Load last saved SPU state capture."
|
"\nKeys Alt+R: Load last saved SPU state capture."
|
||||||
"\nKey D: SPU MFC commands logger, MFC debug setting must be enabled."
|
"\nKey D: SPU MFC commands logger, MFC debug setting must be enabled."
|
||||||
|
@ -351,20 +349,6 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
||||||
open_breakpoints_settings();
|
open_breakpoints_settings();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Qt::Key_S:
|
|
||||||
{
|
|
||||||
if (m_disasm && (cpu->id_type() == 2 || cpu->id_type() == 1))
|
|
||||||
{
|
|
||||||
if (cpu->id_type() == 2)
|
|
||||||
{
|
|
||||||
// Save shared pointer to shared memory handle, ensure the destructor will not be called until the SPUDisAsm is destroyed
|
|
||||||
static_cast<SPUDisAsm*>(m_disasm.get())->set_shm(static_cast<const spu_thread*>(cpu)->shm);
|
|
||||||
}
|
|
||||||
|
|
||||||
idm::make<memory_searcher_handle>(this, m_disasm, cpu->id_type() == 2 ? cpu->get_name() : "");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -638,8 +622,14 @@ void debugger_frame::keyPressEvent(QKeyEvent* event)
|
||||||
if (event->isAutoRepeat())
|
if (event->isAutoRepeat())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m_disasm && cpu->id_type() == 2)
|
||||||
|
{
|
||||||
|
// Save shared pointer to shared memory handle, ensure the destructor will not be called until the SPUDisAsm is destroyed
|
||||||
|
static_cast<SPUDisAsm*>(m_disasm.get())->set_shm(static_cast<const spu_thread*>(cpu)->shm);
|
||||||
|
}
|
||||||
|
|
||||||
// Memory viewer
|
// Memory viewer
|
||||||
idm::make<memory_viewer_handle>(this, pc, make_check_cpu(cpu));
|
idm::make<memory_viewer_handle>(this, m_disasm, pc, make_check_cpu(cpu));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Qt::Key_F10:
|
case Qt::Key_F10:
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "auto_pause_settings_dialog.h"
|
#include "auto_pause_settings_dialog.h"
|
||||||
#include "cg_disasm_window.h"
|
#include "cg_disasm_window.h"
|
||||||
#include "log_viewer.h"
|
#include "log_viewer.h"
|
||||||
#include "memory_string_searcher.h"
|
|
||||||
#include "memory_viewer_panel.h"
|
#include "memory_viewer_panel.h"
|
||||||
#include "rsx_debugger.h"
|
#include "rsx_debugger.h"
|
||||||
#include "about_dialog.h"
|
#include "about_dialog.h"
|
||||||
|
@ -1904,7 +1903,6 @@ void main_window::EnableMenus(bool enabled) const
|
||||||
ui->toolskernel_explorerAct->setEnabled(enabled);
|
ui->toolskernel_explorerAct->setEnabled(enabled);
|
||||||
ui->toolsmemory_viewerAct->setEnabled(enabled);
|
ui->toolsmemory_viewerAct->setEnabled(enabled);
|
||||||
ui->toolsRsxDebuggerAct->setEnabled(enabled);
|
ui->toolsRsxDebuggerAct->setEnabled(enabled);
|
||||||
ui->toolsStringSearchAct->setEnabled(enabled);
|
|
||||||
ui->toolsSystemCommandsAct->setEnabled(enabled);
|
ui->toolsSystemCommandsAct->setEnabled(enabled);
|
||||||
ui->actionCreate_RSX_Capture->setEnabled(enabled);
|
ui->actionCreate_RSX_Capture->setEnabled(enabled);
|
||||||
ui->actionCreate_Savestate->setEnabled(enabled);
|
ui->actionCreate_Savestate->setEnabled(enabled);
|
||||||
|
@ -2519,7 +2517,7 @@ void main_window::CreateConnects()
|
||||||
connect(ui->toolsmemory_viewerAct, &QAction::triggered, this, [this]
|
connect(ui->toolsmemory_viewerAct, &QAction::triggered, this, [this]
|
||||||
{
|
{
|
||||||
if (!Emu.IsStopped())
|
if (!Emu.IsStopped())
|
||||||
idm::make<memory_viewer_handle>(this);
|
idm::make<memory_viewer_handle>(this, make_basic_ppu_disasm());
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->toolsRsxDebuggerAct, &QAction::triggered, this, [this]
|
connect(ui->toolsRsxDebuggerAct, &QAction::triggered, this, [this]
|
||||||
|
@ -2528,12 +2526,6 @@ void main_window::CreateConnects()
|
||||||
rsx->show();
|
rsx->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->toolsStringSearchAct, &QAction::triggered, this, [this]
|
|
||||||
{
|
|
||||||
if (!Emu.IsStopped())
|
|
||||||
idm::make<memory_searcher_handle>(this, make_basic_ppu_disasm());
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(ui->toolsSystemCommandsAct, &QAction::triggered, this, [this]
|
connect(ui->toolsSystemCommandsAct, &QAction::triggered, this, [this]
|
||||||
{
|
{
|
||||||
if (Emu.IsStopped()) return;
|
if (Emu.IsStopped()) return;
|
||||||
|
|
|
@ -274,7 +274,6 @@
|
||||||
<addaction name="toolskernel_explorerAct"/>
|
<addaction name="toolskernel_explorerAct"/>
|
||||||
<addaction name="toolsmemory_viewerAct"/>
|
<addaction name="toolsmemory_viewerAct"/>
|
||||||
<addaction name="toolsRsxDebuggerAct"/>
|
<addaction name="toolsRsxDebuggerAct"/>
|
||||||
<addaction name="toolsStringSearchAct"/>
|
|
||||||
<addaction name="toolsSystemCommandsAct"/>
|
<addaction name="toolsSystemCommandsAct"/>
|
||||||
<addaction name="patchCreatorAct"/>
|
<addaction name="patchCreatorAct"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
@ -646,14 +645,6 @@
|
||||||
<string>RSX Debugger</string>
|
<string>RSX Debugger</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="toolsStringSearchAct">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Memory Searcher</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="toolsDecryptSprxLibsAct">
|
<action name="toolsDecryptSprxLibsAct">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Decrypt PS3 Binaries</string>
|
<string>Decrypt PS3 Binaries</string>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "memory_string_searcher.h"
|
#include "memory_viewer_panel.h"
|
||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
#include "Emu/Memory/vm_reservation.h"
|
#include "Emu/Memory/vm_reservation.h"
|
||||||
#include "Emu/CPU/CPUDisAsm.h"
|
#include "Emu/CPU/CPUDisAsm.h"
|
||||||
|
@ -26,17 +26,6 @@ LOG_CHANNEL(gui_log, "GUI");
|
||||||
|
|
||||||
constexpr auto qstr = QString::fromStdString;
|
constexpr auto qstr = QString::fromStdString;
|
||||||
|
|
||||||
enum search_mode : int
|
|
||||||
{
|
|
||||||
no_mode = 1,
|
|
||||||
as_string = 2,
|
|
||||||
as_hex = 4,
|
|
||||||
as_f64 = 8,
|
|
||||||
as_f32 = 16,
|
|
||||||
as_inst = 32,
|
|
||||||
as_fake_spu_inst = 64,
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void fmt_class_string<search_mode>::format(std::string& out, u64 arg)
|
void fmt_class_string<search_mode>::format(std::string& out, u64 arg)
|
||||||
{
|
{
|
||||||
|
@ -45,9 +34,9 @@ void fmt_class_string<search_mode>::format(std::string& out, u64 arg)
|
||||||
out += "No search modes have been selected";
|
out += "No search modes have been selected";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int modes = static_cast<int>(arg); modes; modes &= modes - 1)
|
for (u32 modes = static_cast<u32>(arg); modes; modes &= modes - 1)
|
||||||
{
|
{
|
||||||
const int mode = modes & ~(modes - 1);
|
const u32 mode = modes & ~(modes - 1);
|
||||||
|
|
||||||
auto mode_s = [&]() -> std::string_view
|
auto mode_s = [&]() -> std::string_view
|
||||||
{
|
{
|
||||||
|
@ -68,7 +57,7 @@ void fmt_class_string<search_mode>::format(std::string& out, u64 arg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modes != static_cast<int>(arg))
|
if (modes != static_cast<u32>(arg))
|
||||||
{
|
{
|
||||||
out += ", ";
|
out += ", ";
|
||||||
}
|
}
|
||||||
|
@ -77,125 +66,13 @@ void fmt_class_string<search_mode>::format(std::string& out, u64 arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_string_searcher::memory_string_searcher(QWidget* parent, std::shared_ptr<CPUDisAsm> disasm, std::string_view title)
|
u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode)
|
||||||
: QDialog(parent)
|
|
||||||
, m_disasm(std::move(disasm))
|
|
||||||
{
|
{
|
||||||
if (title.empty())
|
if (m_rsx)
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Memory Searcher"));
|
return 0;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setWindowTitle(tr("Memory Searcher Of %1").arg(title.data()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setObjectName("memory_string_searcher");
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
|
|
||||||
// Extract memory view from the disassembler
|
|
||||||
std::tie(m_ptr, m_size) = m_disasm->get_memory_span();
|
|
||||||
|
|
||||||
m_addr_line = new QLineEdit(this);
|
|
||||||
m_addr_line->setFixedWidth(QLabel("This is the very length of the lineedit due to hidpi reasons.").sizeHint().width());
|
|
||||||
m_addr_line->setPlaceholderText(tr("Search..."));
|
|
||||||
m_addr_line->setMaxLength(4096);
|
|
||||||
|
|
||||||
QPushButton* button_search = new QPushButton(tr("&Search"), this);
|
|
||||||
|
|
||||||
m_chkbox_case_insensitive = new QCheckBox(tr("Case Insensitive"), this);
|
|
||||||
m_chkbox_case_insensitive->setCheckable(true);
|
|
||||||
m_chkbox_case_insensitive->setToolTip(tr("When using string mode, the characters' case will not matter both in string and in memory."
|
|
||||||
"\nWarning: this may reduce performance of the search."));
|
|
||||||
|
|
||||||
m_cbox_input_mode = new QComboBox(this);
|
|
||||||
m_cbox_input_mode->addItem(tr("Select search mode(s).."), QVariant::fromValue(+no_mode));
|
|
||||||
m_cbox_input_mode->addItem(tr("String"), QVariant::fromValue(+as_string));
|
|
||||||
m_cbox_input_mode->addItem(tr("HEX bytes/integer"), QVariant::fromValue(+as_hex));
|
|
||||||
m_cbox_input_mode->addItem(tr("Double"), QVariant::fromValue(+as_f64));
|
|
||||||
m_cbox_input_mode->addItem(tr("Float"), QVariant::fromValue(+as_f32));
|
|
||||||
m_cbox_input_mode->addItem(tr("Instruction"), QVariant::fromValue(+as_inst));
|
|
||||||
|
|
||||||
QString tooltip = tr("String: search the memory for the specified string."
|
|
||||||
"\nHEX bytes/integer: search the memory for hexadecimal values. Spaces, commas, \"0x\", \"0X\", \"\\x\", \"h\", \"H\" ensure separation of bytes but they are not mandatory."
|
|
||||||
"\nDouble: reinterpret the string as 64-bit precision floating point value. Values are searched for exact representation, meaning -0 != 0."
|
|
||||||
"\nFloat: reinterpret the string as 32-bit precision floating point value. Values are searched for exact representation, meaning -0 != 0."
|
|
||||||
"\nInstruction: search an instruction contains the text of the string.");
|
|
||||||
|
|
||||||
if (m_size != 0x40000/*SPU_LS_SIZE*/)
|
|
||||||
{
|
|
||||||
m_cbox_input_mode->addItem("SPU Instruction", QVariant::fromValue(+as_fake_spu_inst));
|
|
||||||
tooltip.append(tr("\nSPU Instruction: Search an SPU instruction contains the text of the string. For searching instructions within embedded SPU images.\nTip: SPU floats are commented along forming instructions."));
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(m_cbox_input_mode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
|
|
||||||
{
|
|
||||||
if (index < 0) return;
|
|
||||||
|
|
||||||
if ((1 << index) == no_mode)
|
|
||||||
{
|
|
||||||
m_modes = {};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_modes = search_mode{m_modes | (1 << index)};
|
|
||||||
}
|
|
||||||
|
|
||||||
m_modes_label->setText(qstr(fmt::format("%s.", m_modes)));
|
|
||||||
});
|
|
||||||
|
|
||||||
m_cbox_input_mode->setToolTip(tooltip);
|
|
||||||
|
|
||||||
m_modes_label = new QLabel(qstr(fmt::format("%s.", m_modes)));
|
|
||||||
|
|
||||||
QHBoxLayout* hbox_panel = new QHBoxLayout();
|
|
||||||
hbox_panel->addWidget(m_addr_line);
|
|
||||||
hbox_panel->addWidget(m_cbox_input_mode);
|
|
||||||
hbox_panel->addWidget(m_chkbox_case_insensitive);
|
|
||||||
hbox_panel->addWidget(button_search);
|
|
||||||
|
|
||||||
QVBoxLayout* vbox_panel = new QVBoxLayout();
|
|
||||||
vbox_panel->addLayout(hbox_panel);
|
|
||||||
vbox_panel->addWidget(m_modes_label);
|
|
||||||
|
|
||||||
setLayout(vbox_panel);
|
|
||||||
|
|
||||||
connect(button_search, &QAbstractButton::clicked, this, [this]()
|
|
||||||
{
|
|
||||||
std::string wstr = m_addr_line->text().toStdString();
|
|
||||||
|
|
||||||
if (wstr.empty() || wstr.size() >= 4096u)
|
|
||||||
{
|
|
||||||
gui_log.error("String is empty or too long (size=%u)", wstr.size());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gui_log.notice("Searching for %s (mode: %s)", wstr, m_modes);
|
|
||||||
|
|
||||||
u64 found = 0;
|
|
||||||
|
|
||||||
for (int modes = m_modes; modes; modes &= modes - 1)
|
|
||||||
{
|
|
||||||
found += OnSearch(wstr, modes & ~(modes - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
gui_log.success("Search completed (found %u matches)", +found);
|
|
||||||
});
|
|
||||||
|
|
||||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
|
||||||
|
|
||||||
// Show by default
|
|
||||||
show();
|
|
||||||
|
|
||||||
// Expected to be created by IDM, emulation stop will close it
|
|
||||||
connect(this, &memory_string_searcher::finished, [id = idm::last_id()](int)
|
|
||||||
{
|
|
||||||
idm::remove<memory_searcher_handle>(id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 memory_string_searcher::OnSearch(std::string wstr, int mode)
|
|
||||||
{
|
|
||||||
bool case_insensitive = false;
|
bool case_insensitive = false;
|
||||||
|
|
||||||
// First characters for case insensitive search
|
// First characters for case insensitive search
|
||||||
|
@ -250,7 +127,7 @@ u64 memory_string_searcher::OnSearch(std::string wstr, int mode)
|
||||||
if (const usz pos = wstr.find_first_not_of(hex_chars); pos != umax)
|
if (const usz pos = wstr.find_first_not_of(hex_chars); pos != umax)
|
||||||
{
|
{
|
||||||
gui_log.error("String '%s' cannot be interpreted as hexadecimal byte string due to unknown character '%c'.",
|
gui_log.error("String '%s' cannot be interpreted as hexadecimal byte string due to unknown character '%c'.",
|
||||||
m_addr_line->text().toStdString(), wstr[pos]);
|
m_search_line->text().toStdString(), wstr[pos]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "util/types.hpp"
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
class QLineEdit;
|
|
||||||
class QCheckBox;
|
|
||||||
class QComboBox;
|
|
||||||
class QLabel;
|
|
||||||
|
|
||||||
class CPUDisAsm;
|
|
||||||
|
|
||||||
enum search_mode : int;
|
|
||||||
|
|
||||||
class memory_string_searcher : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
QLineEdit* m_addr_line = nullptr;
|
|
||||||
QCheckBox* m_chkbox_case_insensitive = nullptr;
|
|
||||||
QComboBox* m_cbox_input_mode = nullptr;
|
|
||||||
QLabel* m_modes_label = nullptr;
|
|
||||||
|
|
||||||
std::shared_ptr<CPUDisAsm> m_disasm;
|
|
||||||
|
|
||||||
const void* m_ptr;
|
|
||||||
usz m_size;
|
|
||||||
|
|
||||||
search_mode m_modes{};
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit memory_string_searcher(QWidget* parent, std::shared_ptr<CPUDisAsm> disasm, std::string_view title = {});
|
|
||||||
|
|
||||||
private:
|
|
||||||
u64 OnSearch(std::string wstr, int mode);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lifetime management with IDM
|
|
||||||
struct memory_searcher_handle
|
|
||||||
{
|
|
||||||
static constexpr u32 id_base = 1;
|
|
||||||
static constexpr u32 id_step = 1;
|
|
||||||
static constexpr u32 id_count = 2048;
|
|
||||||
SAVESTATE_INIT_POS(32); // Of course not really used
|
|
||||||
|
|
||||||
template <typename... Args> requires (std::is_constructible_v<memory_string_searcher, Args&&...>)
|
|
||||||
memory_searcher_handle(Args&&... args)
|
|
||||||
: m_mss(new memory_string_searcher(std::forward<Args>(args)...))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~memory_searcher_handle() { m_mss->close(); m_mss->deleteLater(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::add_pointer_t<memory_string_searcher> m_mss;
|
|
||||||
};
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "memory_viewer_panel.h"
|
#include "memory_viewer_panel.h"
|
||||||
|
|
||||||
#include "Emu/Cell/SPUThread.h"
|
#include "Emu/Cell/SPUThread.h"
|
||||||
|
#include "Emu/CPU/CPUDisAsm.h"
|
||||||
|
#include "Emu/Cell/SPUDisAsm.h"
|
||||||
#include "Emu/RSX/RSXThread.h"
|
#include "Emu/RSX/RSXThread.h"
|
||||||
#include "Emu/RSX/rsx_utils.h"
|
#include "Emu/RSX/rsx_utils.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
@ -14,14 +16,20 @@
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QCheckBox>
|
||||||
#include <QWheelEvent>
|
#include <QWheelEvent>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "util/logs.hpp"
|
||||||
#include "util/asm.hpp"
|
#include "util/asm.hpp"
|
||||||
#include "util/vm.hpp"
|
#include "util/vm.hpp"
|
||||||
|
|
||||||
|
LOG_CHANNEL(gui_log, "GUI");
|
||||||
|
|
||||||
constexpr auto qstr = QString::fromStdString;
|
constexpr auto qstr = QString::fromStdString;
|
||||||
|
|
||||||
memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::function<cpu_thread*()> func)
|
memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDisAsm> disasm, u32 addr, std::function<cpu_thread*()> func)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
, m_addr(addr)
|
, m_addr(addr)
|
||||||
, m_get_cpu(std::move(func))
|
, m_get_cpu(std::move(func))
|
||||||
|
@ -43,6 +51,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
return cpu && m_type == thread_type::spu ? static_cast<spu_thread*>(cpu)->shm : nullptr;
|
return cpu && m_type == thread_type::spu ? static_cast<spu_thread*>(cpu)->shm : nullptr;
|
||||||
}())
|
}())
|
||||||
, m_addr_mask(m_type == thread_type::spu ? SPU_LS_SIZE - 1 : ~0)
|
, m_addr_mask(m_type == thread_type::spu ? SPU_LS_SIZE - 1 : ~0)
|
||||||
|
, m_disasm(std::move(disasm))
|
||||||
{
|
{
|
||||||
const auto cpu = m_get_cpu();
|
const auto cpu = m_get_cpu();
|
||||||
|
|
||||||
|
@ -53,7 +62,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
|
|
||||||
setObjectName("memory_viewer");
|
setObjectName("memory_viewer");
|
||||||
m_colcount = 4;
|
m_colcount = 4;
|
||||||
m_rowcount = 16;
|
m_rowcount = 1;
|
||||||
const int pSize = 10;
|
const int pSize = 10;
|
||||||
|
|
||||||
// Font
|
// Font
|
||||||
|
@ -62,18 +71,18 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
m_fontMetrics = new QFontMetrics(mono);
|
m_fontMetrics = new QFontMetrics(mono);
|
||||||
|
|
||||||
// Layout:
|
// Layout:
|
||||||
QVBoxLayout* vbox_panel = new QVBoxLayout();
|
QVBoxLayout* vbox_panel = new QVBoxLayout(this);
|
||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
QHBoxLayout* hbox_tools = new QHBoxLayout();
|
QHBoxLayout* hbox_tools = new QHBoxLayout(this);
|
||||||
|
|
||||||
// Tools: Memory Viewer Options
|
// Tools: Memory Viewer Options
|
||||||
QGroupBox* tools_mem = new QGroupBox(tr("Memory Viewer Options"));
|
QGroupBox* tools_mem = new QGroupBox(tr("Memory Viewer Options"), this);
|
||||||
QHBoxLayout* hbox_tools_mem = new QHBoxLayout();
|
QHBoxLayout* hbox_tools_mem = new QHBoxLayout(this);
|
||||||
|
|
||||||
// Tools: Memory Viewer Options: Address
|
// Tools: Memory Viewer Options: Address
|
||||||
QGroupBox* tools_mem_addr = new QGroupBox(tr("Address"));
|
QGroupBox* tools_mem_addr = new QGroupBox(tr("Address"), this);
|
||||||
QHBoxLayout* hbox_tools_mem_addr = new QHBoxLayout();
|
QHBoxLayout* hbox_tools_mem_addr = new QHBoxLayout(this);
|
||||||
m_addr_line = new QLineEdit(this);
|
m_addr_line = new QLineEdit(this);
|
||||||
m_addr_line->setPlaceholderText("00000000");
|
m_addr_line->setPlaceholderText("00000000");
|
||||||
m_addr_line->setFont(mono);
|
m_addr_line->setFont(mono);
|
||||||
|
@ -85,7 +94,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
tools_mem_addr->setLayout(hbox_tools_mem_addr);
|
tools_mem_addr->setLayout(hbox_tools_mem_addr);
|
||||||
|
|
||||||
// Tools: Memory Viewer Options: Words
|
// Tools: Memory Viewer Options: Words
|
||||||
QGroupBox* tools_mem_words = new QGroupBox(tr("Words"));
|
QGroupBox* tools_mem_words = new QGroupBox(tr("Words"), this);
|
||||||
QHBoxLayout* hbox_tools_mem_words = new QHBoxLayout();
|
QHBoxLayout* hbox_tools_mem_words = new QHBoxLayout();
|
||||||
|
|
||||||
class words_spin_box : public QSpinBox
|
class words_spin_box : public QSpinBox
|
||||||
|
@ -114,7 +123,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
|
|
||||||
// Tools: Memory Viewer Options: Control
|
// Tools: Memory Viewer Options: Control
|
||||||
QGroupBox* tools_mem_buttons = new QGroupBox(tr("Control"));
|
QGroupBox* tools_mem_buttons = new QGroupBox(tr("Control"));
|
||||||
QHBoxLayout* hbox_tools_mem_buttons = new QHBoxLayout();
|
QHBoxLayout* hbox_tools_mem_buttons = new QHBoxLayout(this);
|
||||||
QPushButton* b_fprev = new QPushButton("<<", this);
|
QPushButton* b_fprev = new QPushButton("<<", this);
|
||||||
QPushButton* b_prev = new QPushButton("<", this);
|
QPushButton* b_prev = new QPushButton("<", this);
|
||||||
QPushButton* b_next = new QPushButton(">", this);
|
QPushButton* b_next = new QPushButton(">", this);
|
||||||
|
@ -140,12 +149,12 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
tools_mem->setLayout(hbox_tools_mem);
|
tools_mem->setLayout(hbox_tools_mem);
|
||||||
|
|
||||||
// Tools: Raw Image Preview Options
|
// Tools: Raw Image Preview Options
|
||||||
QGroupBox* tools_img = new QGroupBox(tr("Raw Image Preview Options"));
|
QGroupBox* tools_img = new QGroupBox(tr("Raw Image Preview Options"), this);
|
||||||
QHBoxLayout* hbox_tools_img = new QHBoxLayout();
|
QHBoxLayout* hbox_tools_img = new QHBoxLayout(this);
|
||||||
|
|
||||||
// Tools: Raw Image Preview Options : Size
|
// Tools: Raw Image Preview Options : Size
|
||||||
QGroupBox* tools_img_size = new QGroupBox(tr("Size"));
|
QGroupBox* tools_img_size = new QGroupBox(tr("Size"), this);
|
||||||
QHBoxLayout* hbox_tools_img_size = new QHBoxLayout();
|
QHBoxLayout* hbox_tools_img_size = new QHBoxLayout(this);
|
||||||
QLabel* l_x = new QLabel(" x ");
|
QLabel* l_x = new QLabel(" x ");
|
||||||
QSpinBox* sb_img_size_x = new QSpinBox(this);
|
QSpinBox* sb_img_size_x = new QSpinBox(this);
|
||||||
QSpinBox* sb_img_size_y = new QSpinBox(this);
|
QSpinBox* sb_img_size_y = new QSpinBox(this);
|
||||||
|
@ -159,8 +168,8 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
tools_img_size->setLayout(hbox_tools_img_size);
|
tools_img_size->setLayout(hbox_tools_img_size);
|
||||||
|
|
||||||
// Tools: Raw Image Preview Options: Mode
|
// Tools: Raw Image Preview Options: Mode
|
||||||
QGroupBox* tools_img_mode = new QGroupBox(tr("Mode"));
|
QGroupBox* tools_img_mode = new QGroupBox(tr("Mode"), this);
|
||||||
QHBoxLayout* hbox_tools_img_mode = new QHBoxLayout();
|
QHBoxLayout* hbox_tools_img_mode = new QHBoxLayout(this);
|
||||||
QComboBox* cbox_img_mode = new QComboBox(this);
|
QComboBox* cbox_img_mode = new QComboBox(this);
|
||||||
cbox_img_mode->addItem("RGB", QVariant::fromValue(color_format::RGB));
|
cbox_img_mode->addItem("RGB", QVariant::fromValue(color_format::RGB));
|
||||||
cbox_img_mode->addItem("ARGB", QVariant::fromValue(color_format::ARGB));
|
cbox_img_mode->addItem("ARGB", QVariant::fromValue(color_format::ARGB));
|
||||||
|
@ -176,7 +185,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
tools_img->setLayout(hbox_tools_img);
|
tools_img->setLayout(hbox_tools_img);
|
||||||
|
|
||||||
// Tools: Tool Buttons
|
// Tools: Tool Buttons
|
||||||
QGroupBox* tools_buttons = new QGroupBox(tr("Tools"));
|
QGroupBox* tools_buttons = new QGroupBox(tr("Tools"), this);
|
||||||
QVBoxLayout* hbox_tools_buttons = new QVBoxLayout(this);
|
QVBoxLayout* hbox_tools_buttons = new QVBoxLayout(this);
|
||||||
QPushButton* b_img = new QPushButton(tr("View\nimage"), this);
|
QPushButton* b_img = new QPushButton(tr("View\nimage"), this);
|
||||||
b_img->setAutoDefault(false);
|
b_img->setAutoDefault(false);
|
||||||
|
@ -184,17 +193,22 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
tools_buttons->setLayout(hbox_tools_buttons);
|
tools_buttons->setLayout(hbox_tools_buttons);
|
||||||
|
|
||||||
// Merge Tools = Memory Viewer Options + Raw Image Preview Options + Tool Buttons
|
// Merge Tools = Memory Viewer Options + Raw Image Preview Options + Tool Buttons
|
||||||
hbox_tools->addSpacing(10);
|
hbox_tools->addSpacing(20);
|
||||||
hbox_tools->addWidget(tools_mem);
|
hbox_tools->addWidget(tools_mem);
|
||||||
hbox_tools->addWidget(tools_img);
|
hbox_tools->addWidget(tools_img);
|
||||||
hbox_tools->addWidget(tools_buttons);
|
hbox_tools->addWidget(tools_buttons);
|
||||||
hbox_tools->addSpacing(10);
|
hbox_tools->addSpacing(20);
|
||||||
|
|
||||||
// Memory Panel:
|
// Memory Panel:
|
||||||
QHBoxLayout* hbox_mem_panel = new QHBoxLayout();
|
m_hbox_mem_panel = new QHBoxLayout(this);
|
||||||
|
|
||||||
// Memory Panel: Address Panel
|
// Memory Panel: Address Panel
|
||||||
m_mem_addr = new QLabel("");
|
m_mem_addr = new QLabel("");
|
||||||
|
|
||||||
|
QSizePolicy sp_retain = m_mem_addr->sizePolicy();
|
||||||
|
sp_retain.setRetainSizeWhenHidden(false);
|
||||||
|
|
||||||
|
m_mem_addr->setSizePolicy(sp_retain);
|
||||||
m_mem_addr->setObjectName("memory_viewer_address_panel");
|
m_mem_addr->setObjectName("memory_viewer_address_panel");
|
||||||
m_mem_addr->setFont(mono);
|
m_mem_addr->setFont(mono);
|
||||||
m_mem_addr->setAutoFillBackground(true);
|
m_mem_addr->setAutoFillBackground(true);
|
||||||
|
@ -203,6 +217,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
|
|
||||||
// Memory Panel: Hex Panel
|
// Memory Panel: Hex Panel
|
||||||
m_mem_hex = new QLabel("");
|
m_mem_hex = new QLabel("");
|
||||||
|
m_mem_hex->setSizePolicy(sp_retain);
|
||||||
m_mem_hex->setObjectName("memory_viewer_hex_panel");
|
m_mem_hex->setObjectName("memory_viewer_hex_panel");
|
||||||
m_mem_hex->setFont(mono);
|
m_mem_hex->setFont(mono);
|
||||||
m_mem_hex->setAutoFillBackground(true);
|
m_mem_hex->setAutoFillBackground(true);
|
||||||
|
@ -211,6 +226,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
|
|
||||||
// Memory Panel: ASCII Panel
|
// Memory Panel: ASCII Panel
|
||||||
m_mem_ascii = new QLabel("");
|
m_mem_ascii = new QLabel("");
|
||||||
|
m_mem_ascii->setSizePolicy(sp_retain);
|
||||||
m_mem_ascii->setObjectName("memory_viewer_ascii_panel");
|
m_mem_ascii->setObjectName("memory_viewer_ascii_panel");
|
||||||
m_mem_ascii->setFont(mono);
|
m_mem_ascii->setFont(mono);
|
||||||
m_mem_ascii->setAutoFillBackground(true);
|
m_mem_ascii->setAutoFillBackground(true);
|
||||||
|
@ -218,40 +234,170 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
m_mem_ascii->ensurePolished();
|
m_mem_ascii->ensurePolished();
|
||||||
|
|
||||||
// Merge Memory Panel:
|
// Merge Memory Panel:
|
||||||
hbox_mem_panel->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
|
m_hbox_mem_panel->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
|
||||||
hbox_mem_panel->addSpacing(20);
|
m_hbox_mem_panel->addSpacing(20);
|
||||||
hbox_mem_panel->addWidget(m_mem_addr);
|
m_hbox_mem_panel->addWidget(m_mem_addr);
|
||||||
hbox_mem_panel->addSpacing(10);
|
m_hbox_mem_panel->addSpacing(10);
|
||||||
hbox_mem_panel->addWidget(m_mem_hex);
|
m_hbox_mem_panel->addWidget(m_mem_hex);
|
||||||
hbox_mem_panel->addSpacing(10);
|
m_hbox_mem_panel->addSpacing(10);
|
||||||
hbox_mem_panel->addWidget(m_mem_ascii);
|
m_hbox_mem_panel->addWidget(m_mem_ascii);
|
||||||
hbox_mem_panel->addSpacing(10);
|
m_hbox_mem_panel->addSpacing(20);
|
||||||
|
|
||||||
|
QHBoxLayout* hbox_memory_search = new QHBoxLayout(this);
|
||||||
|
|
||||||
// Set Margins to adjust WindowSize
|
// Set Margins to adjust WindowSize
|
||||||
vbox_panel->setContentsMargins(0, 0, 0, 0);
|
vbox_panel->setContentsMargins(0, 0, 0, 0);
|
||||||
hbox_tools->setContentsMargins(0, 0, 0, 0);
|
hbox_tools->setContentsMargins(0, 0, 0, 0);
|
||||||
tools_mem_addr->setContentsMargins(0, 10, 0, 0);
|
tools_mem_addr->setContentsMargins(0, 5, 0, 0);
|
||||||
tools_mem_words->setContentsMargins(0, 10, 0, 0);
|
tools_mem_words->setContentsMargins(0, 5, 0, 0);
|
||||||
tools_mem_buttons->setContentsMargins(0, 10, 0, 0);
|
tools_mem_buttons->setContentsMargins(0, 5, 0, 0);
|
||||||
tools_img_mode->setContentsMargins(0, 10, 0, 0);
|
tools_img_mode->setContentsMargins(0, 5, 0, 0);
|
||||||
tools_img_size->setContentsMargins(0, 10, 0, 0);
|
tools_img_size->setContentsMargins(0, 5, 0, 0);
|
||||||
tools_mem->setContentsMargins(0, 10, 0, 0);
|
tools_mem->setContentsMargins(0, 5, 0, 0);
|
||||||
tools_img->setContentsMargins(0, 10, 0, 0);
|
tools_img->setContentsMargins(0, 5, 0, 0);
|
||||||
tools_buttons->setContentsMargins(0, 10, 0, 0);
|
tools_buttons->setContentsMargins(0, 5, 0, 0);
|
||||||
hbox_mem_panel->setContentsMargins(0, 0, 0, 0);
|
m_hbox_mem_panel->setContentsMargins(0, 0, 0, 0);
|
||||||
|
hbox_memory_search->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
if (m_disasm)
|
||||||
|
{
|
||||||
|
// Extract memory view from the disassembler
|
||||||
|
std::tie(m_ptr, m_size) = m_disasm->get_memory_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox* group_search = new QGroupBox(tr("Memory Search"), this);
|
||||||
|
QPushButton* button_collapse_viewer = new QPushButton(reinterpret_cast<const char*>(u8"Ʌ"), group_search);
|
||||||
|
button_collapse_viewer->setFixedWidth(QLabel(button_collapse_viewer->text()).sizeHint().width() * 3);
|
||||||
|
|
||||||
|
m_search_line = new QLineEdit(group_search);
|
||||||
|
m_search_line->setFixedWidth(QLabel(QString("This is the very length of the lineedit due to hidpi reasons.").chopped(4)).sizeHint().width());
|
||||||
|
m_search_line->setPlaceholderText(tr("Search..."));
|
||||||
|
m_search_line->setMaxLength(4096);
|
||||||
|
|
||||||
|
QPushButton* button_search = new QPushButton(tr("Search"), group_search);
|
||||||
|
button_search->setEnabled(false);
|
||||||
|
|
||||||
|
m_chkbox_case_insensitive = new QCheckBox(tr("Case Insensitive"), group_search);
|
||||||
|
m_chkbox_case_insensitive->setCheckable(true);
|
||||||
|
m_chkbox_case_insensitive->setToolTip(tr("When using string mode, the characters' case will not matter both in string and in memory."
|
||||||
|
"\nWarning: this may reduce performance of the search."));
|
||||||
|
|
||||||
|
m_cbox_input_mode = new QComboBox(group_search);
|
||||||
|
m_cbox_input_mode->addItem(tr("Select search mode(s).."), QVariant::fromValue(+no_mode));
|
||||||
|
m_cbox_input_mode->addItem(tr("Deselect All Modes"), QVariant::fromValue(+clear_modes));
|
||||||
|
m_cbox_input_mode->addItem(tr("String"), QVariant::fromValue(+as_string));
|
||||||
|
m_cbox_input_mode->addItem(tr("HEX bytes/integer"), QVariant::fromValue(+as_hex));
|
||||||
|
m_cbox_input_mode->addItem(tr("Double"), QVariant::fromValue(+as_f64));
|
||||||
|
m_cbox_input_mode->addItem(tr("Float"), QVariant::fromValue(+as_f32));
|
||||||
|
m_cbox_input_mode->addItem(tr("Instruction"), QVariant::fromValue(+as_inst));
|
||||||
|
|
||||||
|
QString tooltip = tr("String: search the memory for the specified string."
|
||||||
|
"\nHEX bytes/integer: search the memory for hexadecimal values. Spaces, commas, \"0x\", \"0X\", \"\\x\", \"h\", \"H\" ensure separation of bytes but they are not mandatory."
|
||||||
|
"\nDouble: reinterpret the string as 64-bit precision floating point value. Values are searched for exact representation, meaning -0 != 0."
|
||||||
|
"\nFloat: reinterpret the string as 32-bit precision floating point value. Values are searched for exact representation, meaning -0 != 0."
|
||||||
|
"\nInstruction: search an instruction contains the text of the string.");
|
||||||
|
|
||||||
|
if (m_size != 0x40000/*SPU_LS_SIZE*/)
|
||||||
|
{
|
||||||
|
m_cbox_input_mode->addItem("SPU Instruction", QVariant::fromValue(+as_fake_spu_inst));
|
||||||
|
tooltip.append(tr("\nSPU Instruction: Search an SPU instruction contains the text of the string. For searching instructions within embedded SPU images.\nTip: SPU floats are commented along forming instructions."));
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(m_cbox_input_mode, QOverload<int>::of(&QComboBox::currentIndexChanged), group_search, [this, button_search](int index)
|
||||||
|
{
|
||||||
|
if (index < 1 || m_rsx)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((1u << index) == clear_modes)
|
||||||
|
{
|
||||||
|
m_modes = {};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_modes = search_mode{m_modes | (1 << index)};
|
||||||
|
}
|
||||||
|
|
||||||
|
const s32 count = std::popcount(+m_modes);
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
button_search->setEnabled(false);
|
||||||
|
m_cbox_input_mode->setItemText(0, tr("Select search mode(s).."));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
button_search->setEnabled(true);
|
||||||
|
m_cbox_input_mode->setItemText(0, tr("%0 mode(s) selected").arg(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = search_mode_last / 2; i > clear_modes; i /= 2)
|
||||||
|
{
|
||||||
|
if (i & m_modes && count > 1)
|
||||||
|
{
|
||||||
|
m_cbox_input_mode->setItemText(std::countr_zero<u32>(i), qstr(fmt::format("* %s", search_mode{i})));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cbox_input_mode->setItemText(std::countr_zero<u32>(i), qstr(fmt::format("%s", search_mode{i})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count != 1)
|
||||||
|
{
|
||||||
|
m_cbox_input_mode->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
m_cbox_input_mode->setToolTip(tooltip);
|
||||||
|
|
||||||
|
QVBoxLayout* vbox_search_layout = new QVBoxLayout(group_search);
|
||||||
|
|
||||||
|
QHBoxLayout* hbox_search_panel = new QHBoxLayout(group_search);
|
||||||
|
QHBoxLayout* hbox_search_modes = new QHBoxLayout(group_search);
|
||||||
|
|
||||||
|
hbox_search_panel->addWidget(button_collapse_viewer);
|
||||||
|
hbox_search_panel->addWidget(m_search_line);
|
||||||
|
hbox_search_panel->addWidget(m_cbox_input_mode);
|
||||||
|
hbox_search_panel->addWidget(m_chkbox_case_insensitive);
|
||||||
|
hbox_search_panel->addWidget(button_search);
|
||||||
|
|
||||||
|
vbox_search_layout->addLayout(hbox_search_panel);
|
||||||
|
vbox_search_layout->addLayout(hbox_search_modes);
|
||||||
|
group_search->setLayout(vbox_search_layout);
|
||||||
|
|
||||||
|
hbox_memory_search->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||||
|
hbox_memory_search->addSpacing(20);
|
||||||
|
hbox_memory_search->addWidget(group_search);
|
||||||
|
hbox_memory_search->addSpacing(20);
|
||||||
|
|
||||||
// Merge and display everything
|
// Merge and display everything
|
||||||
vbox_panel->addSpacing(10);
|
vbox_panel->addSpacing(10);
|
||||||
vbox_panel->addLayout(hbox_tools, 0);
|
|
||||||
vbox_panel->addSpacing(10);
|
auto get_row = [row = 0]() mutable
|
||||||
vbox_panel->addLayout(hbox_mem_panel, 1);
|
{
|
||||||
vbox_panel->addSpacing(10);
|
return row++;
|
||||||
|
};
|
||||||
|
|
||||||
|
vbox_panel->addLayout(hbox_tools, get_row());
|
||||||
|
vbox_panel->addSpacing(5);
|
||||||
|
vbox_panel->addLayout(m_hbox_mem_panel, get_row());
|
||||||
|
|
||||||
|
// TODO: RSX memory searcher
|
||||||
|
if (!m_rsx)
|
||||||
|
{
|
||||||
|
vbox_panel->addLayout(hbox_memory_search, get_row());
|
||||||
|
vbox_panel->addSpacing(15);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
group_search->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
vbox_panel->setSizeConstraint(QLayout::SetNoConstraint);
|
vbox_panel->setSizeConstraint(QLayout::SetNoConstraint);
|
||||||
setLayout(vbox_panel);
|
setLayout(vbox_panel);
|
||||||
|
|
||||||
// Fill the QTextEdits
|
|
||||||
scroll(0);
|
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
connect(m_addr_line, &QLineEdit::returnPressed, [this]()
|
connect(m_addr_line, &QLineEdit::returnPressed, [this]()
|
||||||
{
|
{
|
||||||
|
@ -280,15 +426,117 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::functio
|
||||||
ShowImage(this, m_addr, format, sizex, sizey, false);
|
ShowImage(this, m_addr, format, sizex, sizey, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!m_rsx)
|
||||||
|
{
|
||||||
|
connect(button_search, &QAbstractButton::clicked, this, [this]()
|
||||||
|
{
|
||||||
|
if (m_search_thread && m_search_thread->isRunning())
|
||||||
|
{
|
||||||
|
// Prevent spamming (search is costly on performance)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_search_thread)
|
||||||
|
{
|
||||||
|
m_search_thread->deleteLater();
|
||||||
|
m_search_thread = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string wstr = m_search_line->text().toStdString();
|
||||||
|
|
||||||
|
if (wstr.empty() || wstr.size() >= 4096u)
|
||||||
|
{
|
||||||
|
gui_log.error("String is empty or too long (size=%u)", wstr.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_search_thread = QThread::create([this, wstr, m_modes = m_modes]()
|
||||||
|
{
|
||||||
|
gui_log.notice("Searching for %s (mode: %s)", wstr, m_modes);
|
||||||
|
|
||||||
|
u64 found = 0;
|
||||||
|
|
||||||
|
for (int modes = m_modes; modes; modes &= modes - 1)
|
||||||
|
{
|
||||||
|
found += OnSearch(wstr, modes & ~(modes - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_log.success("Search completed (found %u matches)", +found);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_search_thread->start();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(button_collapse_viewer, &QAbstractButton::clicked, this, [this, button_collapse_viewer, m_previous_row_count = -1]() mutable
|
||||||
|
{
|
||||||
|
const bool is_collapsing = button_collapse_viewer->text() == reinterpret_cast<const char*>(u8"Ʌ");
|
||||||
|
button_collapse_viewer->setText(is_collapsing ? "V" : reinterpret_cast<const char*>(u8"Ʌ"));
|
||||||
|
|
||||||
|
if (is_collapsing)
|
||||||
|
{
|
||||||
|
m_previous_row_count = std::exchange(m_rowcount, 0);
|
||||||
|
setMinimumHeight(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_rowcount = std::exchange(m_previous_row_count, 0);
|
||||||
|
setMaximumHeight(16777215); // Default Qt value
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowMemory();
|
||||||
|
|
||||||
|
QTimer::singleShot(0, this, [this, button_collapse_viewer]()
|
||||||
|
{
|
||||||
|
const bool is_collapsing = button_collapse_viewer->text() != reinterpret_cast<const char*>(u8"Ʌ");
|
||||||
|
|
||||||
|
// singleShot to evaluate properly after the event
|
||||||
|
const int height_hint = sizeHint().height();
|
||||||
|
resize(size().width(), height_hint);
|
||||||
|
|
||||||
|
if (is_collapsing)
|
||||||
|
{
|
||||||
|
setMinimumHeight(height_hint);
|
||||||
|
setMaximumHeight(height_hint + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setMinimumHeight(m_min_height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the minimum height of one row
|
||||||
|
m_rowcount = 1;
|
||||||
|
ShowMemory();
|
||||||
|
m_min_height = sizeHint().height();
|
||||||
|
setMinimumHeight(m_min_height);
|
||||||
|
|
||||||
|
m_rowcount = 16;
|
||||||
|
ShowMemory();
|
||||||
|
|
||||||
setFixedWidth(sizeHint().width());
|
setFixedWidth(sizeHint().width());
|
||||||
|
|
||||||
|
// Fill the QTextEdits
|
||||||
|
scroll(0);
|
||||||
|
|
||||||
// Show by default
|
// Show by default
|
||||||
show();
|
show();
|
||||||
|
|
||||||
// Expected to be created by IDM, emulation stop will close it
|
// Expected to be created by IDM, emulation stop will close it
|
||||||
connect(this, &memory_viewer_panel::finished, [id = idm::last_id()](int)
|
const u32 id = idm::last_id();
|
||||||
|
auto handle_ptr = idm::get_unlocked<memory_viewer_handle>(id);
|
||||||
|
|
||||||
|
connect(this, &memory_viewer_panel::finished, [handle_ptr = std::move(handle_ptr), id, this](int)
|
||||||
{
|
{
|
||||||
idm::remove<memory_viewer_handle>(id);
|
if (m_search_thread)
|
||||||
|
{
|
||||||
|
m_search_thread->wait();
|
||||||
|
m_search_thread->deleteLater();
|
||||||
|
m_search_thread = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
idm::remove_verify<memory_viewer_handle>(id, handle_ptr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,6 +563,7 @@ void memory_viewer_panel::scroll(s32 steps)
|
||||||
m_addr -= m_addr % (m_colcount * 4); // Align by amount of bytes in a row
|
m_addr -= m_addr % (m_colcount * 4); // Align by amount of bytes in a row
|
||||||
|
|
||||||
m_addr_line->setText(qstr(fmt::format("%08x", m_addr)));
|
m_addr_line->setText(qstr(fmt::format("%08x", m_addr)));
|
||||||
|
|
||||||
ShowMemory();
|
ShowMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,21 +575,26 @@ void memory_viewer_panel::resizeEvent(QResizeEvent *event)
|
||||||
const QMargins margins = layout()->contentsMargins();
|
const QMargins margins = layout()->contentsMargins();
|
||||||
|
|
||||||
int free_height = event->size().height()
|
int free_height = event->size().height()
|
||||||
- (layout()->count() * (margins.top() + margins.bottom()));
|
- (layout()->count() * (margins.top() + margins.bottom())) - c_pad_memory_labels;
|
||||||
|
|
||||||
for (int i = 0; i < layout()->count(); i++)
|
for (int i = 0; i < layout()->count(); i++)
|
||||||
{
|
{
|
||||||
if (i != 3) // Index of our memory layout
|
const auto it = layout()->itemAt(i);
|
||||||
free_height -= layout()->itemAt(i)->sizeHint().height();
|
if (it != m_hbox_mem_panel) // Do not take our memory layout into account
|
||||||
|
free_height -= it->sizeHint().height();
|
||||||
}
|
}
|
||||||
|
|
||||||
setMinimumHeight(event->size().height() - free_height + font_height);
|
|
||||||
const u32 new_row_count = std::max(0, free_height) / font_height;
|
const u32 new_row_count = std::max(0, free_height) / font_height;
|
||||||
|
|
||||||
if (m_rowcount != new_row_count)
|
if (m_rowcount != new_row_count)
|
||||||
{
|
{
|
||||||
m_rowcount = new_row_count;
|
m_rowcount = new_row_count;
|
||||||
ShowMemory();
|
|
||||||
|
QTimer::singleShot(0, [this]()
|
||||||
|
{
|
||||||
|
// Prevent recursion of events
|
||||||
|
ShowMemory();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +793,7 @@ void memory_viewer_panel::ShowMemory()
|
||||||
|
|
||||||
if (const auto ptr = this->to_ptr(addr))
|
if (const auto ptr = this->to_ptr(addr))
|
||||||
{
|
{
|
||||||
const be_t<u32> rmem = *static_cast<be_t<u32>*>(ptr);
|
const be_t<u32> rmem = read_from_ptr<be_t<u32>>(static_cast<const u8*>(ptr));
|
||||||
t_mem_hex_str += qstr(fmt::format("%02x %02x %02x %02x",
|
t_mem_hex_str += qstr(fmt::format("%02x %02x %02x %02x",
|
||||||
static_cast<u8>(rmem >> 24),
|
static_cast<u8>(rmem >> 24),
|
||||||
static_cast<u8>(rmem >> 16),
|
static_cast<u8>(rmem >> 16),
|
||||||
|
@ -563,19 +817,28 @@ void memory_viewer_panel::ShowMemory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_mem_addr->setVisible(m_rowcount != 0);
|
||||||
|
m_mem_hex->setVisible(m_rowcount != 0);
|
||||||
|
m_mem_ascii->setVisible(m_rowcount != 0);
|
||||||
|
|
||||||
m_mem_addr->setText(t_mem_addr_str);
|
m_mem_addr->setText(t_mem_addr_str);
|
||||||
m_mem_hex->setText(t_mem_hex_str);
|
m_mem_hex->setText(t_mem_hex_str);
|
||||||
m_mem_ascii->setText(t_mem_ascii_str);
|
m_mem_ascii->setText(t_mem_ascii_str);
|
||||||
|
|
||||||
|
auto mask_height = [&](int height)
|
||||||
|
{
|
||||||
|
return m_rowcount != 0 ? height + c_pad_memory_labels : 0;
|
||||||
|
};
|
||||||
|
|
||||||
// Adjust Text Boxes (also helps with window resize)
|
// Adjust Text Boxes (also helps with window resize)
|
||||||
QSize textSize = m_fontMetrics->size(0, m_mem_addr->text());
|
QSize textSize = m_fontMetrics->size(0, m_mem_addr->text());
|
||||||
m_mem_addr->setFixedSize(textSize.width() + 10, textSize.height());
|
m_mem_addr->setFixedSize(textSize.width() + 10, mask_height(textSize.height()));
|
||||||
|
|
||||||
textSize = m_fontMetrics->size(0, m_mem_hex->text());
|
textSize = m_fontMetrics->size(0, m_mem_hex->text());
|
||||||
m_mem_hex->setFixedSize(textSize.width() + 10, textSize.height());
|
m_mem_hex->setFixedSize(textSize.width() + 10, mask_height(textSize.height()));
|
||||||
|
|
||||||
textSize = m_fontMetrics->size(0, m_mem_ascii->text());
|
textSize = m_fontMetrics->size(0, m_mem_ascii->text());
|
||||||
m_mem_ascii->setFixedSize(textSize.width() + 10, textSize.height());
|
m_mem_ascii->setFixedSize(textSize.width() + 10, mask_height(textSize.height()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_viewer_panel::SetPC(const uint pc)
|
void memory_viewer_panel::SetPC(const uint pc)
|
||||||
|
|
|
@ -10,7 +10,15 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class QCheckBox;
|
||||||
|
class QComboBox;
|
||||||
|
class QLabel;
|
||||||
|
class QThread;
|
||||||
|
class QHBoxLayout;
|
||||||
|
|
||||||
class cpu_thread;
|
class cpu_thread;
|
||||||
|
class CPUDisAsm;
|
||||||
|
|
||||||
namespace utils
|
namespace utils
|
||||||
{
|
{
|
||||||
|
@ -22,12 +30,25 @@ namespace rsx
|
||||||
class thread;
|
class thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum search_mode : unsigned
|
||||||
|
{
|
||||||
|
no_mode = 1,
|
||||||
|
clear_modes = 2,
|
||||||
|
as_string = 4,
|
||||||
|
as_hex = 8,
|
||||||
|
as_f64 = 16,
|
||||||
|
as_f32 = 32,
|
||||||
|
as_inst = 64,
|
||||||
|
as_fake_spu_inst = 128,
|
||||||
|
search_mode_last = 256,
|
||||||
|
};
|
||||||
|
|
||||||
class memory_viewer_panel : public QDialog
|
class memory_viewer_panel : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
memory_viewer_panel(QWidget* parent, u32 addr = 0, std::function<cpu_thread*()> func = []() -> cpu_thread* { return {}; });
|
memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDisAsm> disasm, u32 addr = 0, std::function<cpu_thread*()> func = []() -> cpu_thread* { return {}; });
|
||||||
~memory_viewer_panel();
|
~memory_viewer_panel();
|
||||||
|
|
||||||
enum class color_format : int
|
enum class color_format : int
|
||||||
|
@ -44,17 +65,26 @@ protected:
|
||||||
void resizeEvent(QResizeEvent* event) override;
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 m_addr;
|
u32 m_addr = 0;
|
||||||
u32 m_colcount;
|
u32 m_colcount = 0;
|
||||||
u32 m_rowcount;
|
u32 m_rowcount = 0;
|
||||||
|
u32 m_min_height = 0;
|
||||||
|
|
||||||
QLineEdit* m_addr_line;
|
QLineEdit* m_addr_line = nullptr;
|
||||||
|
|
||||||
QLabel* m_mem_addr;
|
QLabel* m_mem_addr = nullptr;
|
||||||
QLabel* m_mem_hex;
|
QLabel* m_mem_hex = nullptr;
|
||||||
QLabel* m_mem_ascii;
|
QLabel* m_mem_ascii = nullptr;
|
||||||
|
|
||||||
QFontMetrics* m_fontMetrics;
|
QFontMetrics* m_fontMetrics = nullptr;
|
||||||
|
|
||||||
|
static constexpr int c_pad_memory_labels = 15;
|
||||||
|
|
||||||
|
QLineEdit* m_search_line = nullptr;
|
||||||
|
QCheckBox* m_chkbox_case_insensitive = nullptr;
|
||||||
|
QComboBox* m_cbox_input_mode = nullptr;
|
||||||
|
QHBoxLayout* m_hbox_mem_panel = nullptr;
|
||||||
|
QThread* m_search_thread = nullptr;
|
||||||
|
|
||||||
enum class thread_type
|
enum class thread_type
|
||||||
{
|
{
|
||||||
|
@ -70,6 +100,13 @@ private:
|
||||||
const std::shared_ptr<utils::shm> m_spu_shm;
|
const std::shared_ptr<utils::shm> m_spu_shm;
|
||||||
const u32 m_addr_mask;
|
const u32 m_addr_mask;
|
||||||
|
|
||||||
|
std::shared_ptr<CPUDisAsm> m_disasm;
|
||||||
|
|
||||||
|
const void* m_ptr = nullptr;
|
||||||
|
usz m_size = 0;
|
||||||
|
|
||||||
|
search_mode m_modes{};
|
||||||
|
|
||||||
std::string getHeaderAtAddr(u32 addr) const;
|
std::string getHeaderAtAddr(u32 addr) const;
|
||||||
void scroll(s32 steps);
|
void scroll(s32 steps);
|
||||||
void* to_ptr(u32 addr, u32 size = 1) const;
|
void* to_ptr(u32 addr, u32 size = 1) const;
|
||||||
|
@ -78,6 +115,7 @@ private:
|
||||||
virtual void ShowMemory();
|
virtual void ShowMemory();
|
||||||
|
|
||||||
void ShowImage(QWidget* parent, u32 addr, color_format format, u32 width, u32 height, bool flipv) const;
|
void ShowImage(QWidget* parent, u32 addr, color_format format, u32 width, u32 height, bool flipv) const;
|
||||||
|
u64 OnSearch(std::string wstr, u32 mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lifetime management with IDM
|
// Lifetime management with IDM
|
||||||
|
|
Loading…
Reference in New Issue