Skip to content

Commit

Permalink
Add support for viewing a subsection of memory in MemoryView.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpd002 committed Mar 20, 2024
1 parent 820768d commit 7446037
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 37 deletions.
4 changes: 2 additions & 2 deletions Source/ui_qt/DebugSupport/DebugView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <QVBoxLayout>

CDebugView::CDebugView(QWidget* parent, QMdiArea* mdiArea, CVirtualMachine& virtualMachine, CMIPS* ctx,
const StepFunction& stepFunction, CBiosDebugInfoProvider* biosDebugInfoProvider, const char* name, int size, CQtDisAsmTableModel::DISASM_TYPE disAsmType)
const StepFunction& stepFunction, CBiosDebugInfoProvider* biosDebugInfoProvider, const char* name, uint64 memorySize, CQtDisAsmTableModel::DISASM_TYPE disAsmType)
: m_virtualMachine(virtualMachine)
, m_ctx(ctx)
, m_name(name)
Expand All @@ -21,7 +21,7 @@ CDebugView::CDebugView(QWidget* parent, QMdiArea* mdiArea, CVirtualMachine& virt
m_regViewWnd->setWidget(regViewWnd);
m_regViewWnd->setWindowTitle("Registers");

auto memoryViewWnd = new CMemoryViewMIPSWnd(parent, virtualMachine, m_ctx, size);
auto memoryViewWnd = new CMemoryViewMIPSWnd(parent, virtualMachine, m_ctx, memorySize);
m_memoryViewWnd = new QMdiSubWindow(mdiArea);
m_memoryViewWnd->setWidget(memoryViewWnd);
m_memoryViewWnd->setWindowTitle("Memory View");
Expand Down
2 changes: 1 addition & 1 deletion Source/ui_qt/DebugSupport/DebugView.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CDebugView : public CVirtualMachineStateView
public:
typedef std::function<void(void)> StepFunction;

CDebugView(QWidget*, QMdiArea*, CVirtualMachine&, CMIPS*, const StepFunction&, CBiosDebugInfoProvider*, const char*, int, CQtDisAsmTableModel::DISASM_TYPE = CQtDisAsmTableModel::DISASM_STANDARD);
CDebugView(QWidget*, QMdiArea*, CVirtualMachine&, CMIPS*, const StepFunction&, CBiosDebugInfoProvider*, const char*, uint64, CQtDisAsmTableModel::DISASM_TYPE = CQtDisAsmTableModel::DISASM_STANDARD);
virtual ~CDebugView();

void HandleMachineStateChange() override;
Expand Down
9 changes: 5 additions & 4 deletions Source/ui_qt/DebugSupport/MemoryViewMIPS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ void CMemoryViewMIPS::PopulateContextMenu(QMenu* rightClickMenu)
}

{
uint32 selection = m_selected;
if((selection & 0x03) == 0)
if((m_selected & 0x03) == 0)
{
uint32 valueAtSelection = m_context->m_pMemoryMap->GetWord(selection);
uint32 physAddr = m_context->m_pAddrTranslator(m_context, m_selected);
uint32 valueAtSelection = m_context->m_pMemoryMap->GetWord(physAddr);
auto followPointerText = string_format("Follow Pointer (0x%08X)", valueAtSelection);
auto itemAction = rightClickMenu->addAction(followPointerText.c_str());
connect(itemAction, &QAction::triggered, std::bind(&CMemoryViewMIPS::FollowPointer, this));
Expand Down Expand Up @@ -88,6 +88,7 @@ void CMemoryViewMIPS::FollowPointer()
return;
}

uint32 valueAtSelection = m_context->m_pMemoryMap->GetWord(m_selected);
uint32 physAddr = m_context->m_pAddrTranslator(m_context, m_selected);
uint32 valueAtSelection = m_context->m_pMemoryMap->GetWord(physAddr);
SetSelectionStart(valueAtSelection);
}
9 changes: 6 additions & 3 deletions Source/ui_qt/DebugSupport/MemoryViewMIPSWnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@
#include "string_format.h"
#include "ui_MemoryViewMIPSWnd.h"

CMemoryViewMIPSWnd::CMemoryViewMIPSWnd(QWidget* parent, CVirtualMachine& virtualMachine, CMIPS* ctx, int size)
constexpr uint64 g_viewWindowThreshold = 0x100000;

CMemoryViewMIPSWnd::CMemoryViewMIPSWnd(QWidget* parent, CVirtualMachine& virtualMachine, CMIPS* ctx, uint64 size)
: QWidget(parent)
, ui(new Ui::CMemoryViewMIPSWnd)
{
ui->setupUi(this);

auto getByte = [ctx](uint32 address) {
return ctx->m_pMemoryMap->GetByte(address);
uint32 physAddr = ctx->m_pAddrTranslator(ctx, address);
return ctx->m_pMemoryMap->GetByte(physAddr);
};

ui->tableView->SetContext(&virtualMachine, ctx);
ui->tableView->SetData(getByte, size);
ui->tableView->SetData(getByte, size, (size > g_viewWindowThreshold) ? g_viewWindowThreshold : 0);

UpdateStatusBar(0);
m_OnSelectionChangeConnection = ui->tableView->OnSelectionChange.Connect(std::bind(&CMemoryViewMIPSWnd::UpdateStatusBar, this, std::placeholders::_1));
Expand Down
2 changes: 1 addition & 1 deletion Source/ui_qt/DebugSupport/MemoryViewMIPSWnd.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Ui
class CMemoryViewMIPSWnd : public QWidget, public CVirtualMachineStateView
{
public:
CMemoryViewMIPSWnd(QWidget*, CVirtualMachine&, CMIPS*, int);
CMemoryViewMIPSWnd(QWidget*, CVirtualMachine&, CMIPS*, uint64);
~CMemoryViewMIPSWnd();

void HandleMachineStateChange() override;
Expand Down
6 changes: 4 additions & 2 deletions Source/ui_qt/DebugSupport/MemoryViewTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ int CMemoryViewTable::ComputeItemCellWidth() const
return result;
}

void CMemoryViewTable::SetData(CQtMemoryViewModel::getByteProto getByte, int size)
void CMemoryViewTable::SetData(CQtMemoryViewModel::getByteProto getByte, uint64 size, uint32 windowSize)
{
m_model->SetData(getByte, size);
m_model->SetData(getByte, size, windowSize);
}

void CMemoryViewTable::ShowEvent()
Expand Down Expand Up @@ -184,6 +184,8 @@ void CMemoryViewTable::SetActiveUnit(int index)

void CMemoryViewTable::SetSelectionStart(uint32 address)
{
m_model->SetWindowCenter(address);
m_model->Redraw();
auto index = m_model->TranslateAddressToModelIndex(address);
selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
scrollTo(index, QAbstractItemView::PositionAtCenter);
Expand Down
2 changes: 1 addition & 1 deletion Source/ui_qt/DebugSupport/MemoryViewTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class CMemoryViewTable : public QTableView
int GetBytesPerLine();
void SetBytesPerLine(int);

void SetData(CQtMemoryViewModel::getByteProto, int);
void SetData(CQtMemoryViewModel::getByteProto, uint64, uint32 = 0);
void SetSelectionStart(uint32);

void ShowEvent();
Expand Down
4 changes: 2 additions & 2 deletions Source/ui_qt/DebugSupport/QtDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ QtDebugger::QtDebugger(CPS2VM& virtualMachine)
m_nCurrentView = -1;

m_pView[DEBUGVIEW_EE] = new CDebugView(this, ui->mdiArea, m_virtualMachine, &m_virtualMachine.m_ee->m_EE,
std::bind(&CPS2VM::StepEe, &m_virtualMachine), m_virtualMachine.m_ee->m_os, "EmotionEngine", PS2::EE_RAM_SIZE + PS2::EE_BIOS_SIZE);
std::bind(&CPS2VM::StepEe, &m_virtualMachine), m_virtualMachine.m_ee->m_os, "EmotionEngine", static_cast<uint64>(UINT32_MAX) + 1);
m_pView[DEBUGVIEW_VU0] = new CDebugView(this, ui->mdiArea, m_virtualMachine, &m_virtualMachine.m_ee->m_VU0,
std::bind(&CPS2VM::StepVu0, &m_virtualMachine), nullptr, "Vector Unit 0", PS2::VUMEM0SIZE, CQtDisAsmTableModel::DISASM_VU);
m_pView[DEBUGVIEW_VU1] = new CDebugView(this, ui->mdiArea, m_virtualMachine, &m_virtualMachine.m_ee->m_VU1,
std::bind(&CPS2VM::StepVu1, &m_virtualMachine), nullptr, "Vector Unit 1", PS2::VUMEM1SIZE, CQtDisAsmTableModel::DISASM_VU);
m_pView[DEBUGVIEW_IOP] = new CDebugView(this, ui->mdiArea, m_virtualMachine, &m_virtualMachine.m_iop->m_cpu,
std::bind(&CPS2VM::StepIop, &m_virtualMachine), m_virtualMachine.m_iop->m_bios.get(), "IO Processor", PS2::IOP_RAM_SIZE);
std::bind(&CPS2VM::StepIop, &m_virtualMachine), m_virtualMachine.m_iop->m_bios.get(), "IO Processor", static_cast<uint64>(UINT32_MAX) + 1);

m_OnExecutableChangeConnection = m_virtualMachine.m_ee->m_os->OnExecutableChange.Connect(std::bind(&QtDebugger::OnExecutableChange, this));
m_OnExecutableUnloadingConnection = m_virtualMachine.m_ee->m_os->OnExecutableUnloading.Connect(std::bind(&QtDebugger::OnExecutableUnloading, this));
Expand Down
40 changes: 33 additions & 7 deletions Source/ui_qt/DebugSupport/QtMemoryViewModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ CQtMemoryViewModel::CQtMemoryViewModel(QObject* parent)

int CQtMemoryViewModel::rowCount(const QModelIndex& /*parent*/) const
{
return std::ceil((m_size * 1.f) / m_bytesPerRow);
return std::ceil((m_windowSize * 1.f) / m_bytesPerRow);
}

int CQtMemoryViewModel::columnCount(const QModelIndex& /*parent*/) const
Expand Down Expand Up @@ -76,7 +76,7 @@ QVariant CQtMemoryViewModel::headerData(int section, Qt::Orientation orientation
}
else
{
auto address = section * m_bytesPerRow;
auto address = (section * m_bytesPerRow) + m_windowStart;
return QString::fromStdString(string_format("0x%08X", address));
}
}
Expand Down Expand Up @@ -155,25 +155,44 @@ void CQtMemoryViewModel::SetBytesPerRow(unsigned int bytesPerRow)
m_bytesPerRow = bytesPerRow;
}

void CQtMemoryViewModel::SetWindowCenter(uint32 windowCenter)
{
int64 lowerBound = static_cast<int64>(windowCenter) - static_cast<int64>(m_windowSize / 2);
int64 upperBound = static_cast<int64>(windowCenter) + static_cast<int64>(m_windowSize / 2);
if(lowerBound < 0)
{
m_windowStart = 0;
}
else if(upperBound >= m_size)
{
m_windowStart = static_cast<uint32>(m_size - static_cast<uint64>(m_windowSize));
}
else
{
m_windowStart = static_cast<uint32>(lowerBound);
}
}

uint32 CQtMemoryViewModel::TranslateModelIndexToAddress(const QModelIndex& index) const
{
uint32 address = index.row() * m_bytesPerRow;
if((columnCount() - 1) != index.column())
{
address += index.column() * GetBytesPerUnit();
}
return address;
return address + m_windowStart;
}

QModelIndex CQtMemoryViewModel::TranslateAddressToModelIndex(uint32 address) const
{
if(static_cast<int32>(address) < 0)
if(address <= m_windowStart)
{
return index(0, 0);
}
if(static_cast<int32>(address) >= m_size)
address -= m_windowStart;
if(address >= m_windowSize)
{
address = (m_size - 1);
address = (m_windowSize - 1);
}
uint32 row = address / m_bytesPerRow;
uint32 col = address - (row * m_bytesPerRow);
Expand Down Expand Up @@ -201,9 +220,16 @@ unsigned int CQtMemoryViewModel::CharsPerUnit() const
return g_units[m_activeUnit].charsPerUnit;
}

void CQtMemoryViewModel::SetData(getByteProto getByte, int size)
void CQtMemoryViewModel::SetData(getByteProto getByte, uint64 size, uint32 windowSize)
{
if(windowSize == 0)
{
assert(size <= UINT32_MAX);
windowSize = static_cast<uint32>(size);
}
m_getByte = getByte;
m_size = size;
m_windowStart = 0;
m_windowSize = windowSize;
Redraw();
}
7 changes: 5 additions & 2 deletions Source/ui_qt/DebugSupport/QtMemoryViewModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class CQtMemoryViewModel : public QAbstractTableModel
unsigned int GetBytesPerUnit() const;
unsigned int CharsPerUnit() const;

void SetData(getByteProto, int);
void SetData(getByteProto, uint64, uint32 = 0);
void SetWindowCenter(uint32);

uint32 TranslateModelIndexToAddress(const QModelIndex&) const;
QModelIndex TranslateAddressToModelIndex(uint32) const;
Expand All @@ -55,6 +56,8 @@ class CQtMemoryViewModel : public QAbstractTableModel

getByteProto m_getByte;
int m_activeUnit = 0;
unsigned int m_size = 0;
uint32 m_windowStart = 0;
uint32 m_windowSize = 0;
uint64 m_size = 0;
unsigned int m_bytesPerRow = 0x2;
};
80 changes: 68 additions & 12 deletions Source/ui_qt/DebugSupport/tests/QtMemoryViewModelTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ void CQtMemoryViewModelTests::RunTests()
m_getByteFunction = [this](uint32 address) { return GetByte(address); };
TestSimpleBytes();
TestOutOfBounds();
TestWindowOutOfBounds();
TestAddressToModelIndex();
TestAddressToModelIndexWord();
TestAddressToModelIndexWindowed();
TestModelIndexToAddress();
TestModelIndexToAddressWord();
}
Expand Down Expand Up @@ -54,6 +56,28 @@ void CQtMemoryViewModelTests::TestOutOfBounds()
TEST_VERIFY(model->data(model->index(1, 0x10)) == "........ ");
}

void CQtMemoryViewModelTests::TestWindowOutOfBounds()
{
uint32 memorySize = 256;
uint32 windowSize = 32;
m_memory.clear();
m_memory.resize(memorySize);

uint32 bytesPerRow = 16;

auto model = std::make_unique<CQtMemoryViewModel>(nullptr);
model->SetData(m_getByteFunction, memorySize, windowSize);
model->SetBytesPerRow(bytesPerRow);

model->SetWindowCenter(245);
TEST_VERIFY(model->TranslateModelIndexToAddress(model->index(0, 0)) == (memorySize - windowSize));
TEST_VERIFY(model->TranslateModelIndexToAddress(model->index(1, 15)) == (memorySize - 1));

model->SetWindowCenter(13);
TEST_VERIFY(model->TranslateModelIndexToAddress(model->index(0, 0)) == 0);
TEST_VERIFY(model->TranslateModelIndexToAddress(model->index(1, 15)) == (windowSize - 1));
}

void CQtMemoryViewModelTests::TestAddressToModelIndex()
{
uint32 memorySize = 256;
Expand Down Expand Up @@ -83,13 +107,6 @@ void CQtMemoryViewModelTests::TestAddressToModelIndex()
TEST_VERIFY(modelIndex.column() == 3);
}

//An item below
{
auto modelIndex = model->TranslateAddressToModelIndex(-1);
TEST_VERIFY(modelIndex.row() == 0);
TEST_VERIFY(modelIndex.column() == 0);
}

//An item beyond
{
auto modelIndex = model->TranslateAddressToModelIndex(memorySize * 2);
Expand Down Expand Up @@ -136,17 +153,56 @@ void CQtMemoryViewModelTests::TestAddressToModelIndexWord()
TEST_VERIFY(modelIndex.column() == 1);
}

//An item below
//An item beyond
{
auto modelIndex = model->TranslateAddressToModelIndex(-1);
auto modelIndex = model->TranslateAddressToModelIndex(memorySize * 2);
TEST_VERIFY(modelIndex == model->TranslateAddressToModelIndex(memorySize - 1));
}
}

void CQtMemoryViewModelTests::TestAddressToModelIndexWindowed()
{
uint32 memorySize = 0x100;
m_memory.clear();
m_memory.resize(memorySize);

uint32 bytesPerRow = 13;

auto model = std::make_unique<CQtMemoryViewModel>(nullptr);
model->SetData(m_getByteFunction, memorySize, 64);
model->SetWindowCenter(128);
model->SetBytesPerRow(bytesPerRow);

//Window spans from addresses 96 to 159

//ceil(64 / 13) = 3
TEST_VERIFY(model->rowCount() == 5);

//Start of window
{
auto modelIndex = model->TranslateAddressToModelIndex(96);
TEST_VERIFY(modelIndex.row() == 0);
TEST_VERIFY(modelIndex.column() == 0);
}

//An item beyond
//End of window
{
auto modelIndex = model->TranslateAddressToModelIndex(memorySize * 2);
TEST_VERIFY(modelIndex == model->TranslateAddressToModelIndex(memorySize - 1));
auto modelIndex = model->TranslateAddressToModelIndex(159);
TEST_VERIFY(modelIndex.row() == 4);
TEST_VERIFY(modelIndex.column() == 11);
}

//Before window
{
auto modelIndex = model->TranslateAddressToModelIndex(4);
TEST_VERIFY(modelIndex.row() == 0);
TEST_VERIFY(modelIndex.column() == 0);
}

//After window
{
auto modelIndex = model->TranslateAddressToModelIndex(200);
TEST_VERIFY(modelIndex == model->TranslateAddressToModelIndex(159));
}
}

Expand Down
2 changes: 2 additions & 0 deletions Source/ui_qt/DebugSupport/tests/QtMemoryViewModelTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ class CQtMemoryViewModelTests

void TestSimpleBytes();
void TestOutOfBounds();
void TestWindowOutOfBounds();
void TestAddressToModelIndex();
void TestAddressToModelIndexWord();
void TestAddressToModelIndexWindowed();
void TestModelIndexToAddress();
void TestModelIndexToAddressWord();

Expand Down

0 comments on commit 7446037

Please sign in to comment.