Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add +/- shortcuts on the memory viewer #1085

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/ui/viewmodels/MemoryViewerViewModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,45 @@ void MemoryViewerViewModel::RetreatCursorPage()
}
}

bool MemoryViewerViewModel::IncreaseCurrentValue(uint32_t nModifier)
{
if (m_bReadOnly)
return false;

const auto nAddress = GetAddress();
const auto& pEmulatorContext = ra::services::ServiceLocator::Get<ra::data::context::EmulatorContext>();
auto nMem = pEmulatorContext.ReadMemory(GetAddress(), GetSize());
auto const nMaxValue = ra::data::MemSizeMax(GetSize());

if (nMem >= nMaxValue)
return false;
if ((nMaxValue - nMem) < nModifier)
nModifier = (nMaxValue - nMem);
nMem += nModifier;

pEmulatorContext.WriteMemory(nAddress, GetSize(), nMem);
return true;
}

bool MemoryViewerViewModel::DecreaseCurrentValue(uint32_t nModifier)
{
if (m_bReadOnly)
return false;

auto const nAddress = GetAddress();
const auto& pEmulatorContext = ra::services::ServiceLocator::Get<ra::data::context::EmulatorContext>();
auto nMem = pEmulatorContext.ReadMemory(GetAddress(), GetSize());
Jamiras marked this conversation as resolved.
Show resolved Hide resolved

if (nMem == 0)
return false;
if (nMem < nModifier)
nModifier = nMem;
nMem -= nModifier;

pEmulatorContext.WriteMemory(nAddress, GetSize(), nMem);
return true;
}

void MemoryViewerViewModel::OnActiveGameChanged()
{
m_nNeedsRedraw |= REDRAW_ADDRESSES;
Expand Down
3 changes: 3 additions & 0 deletions src/ui/viewmodels/MemoryViewerViewModel.hh
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ public:
void AdvanceCursorPage();
void RetreatCursorPage();

bool IncreaseCurrentValue(uint32_t nModifier);
bool DecreaseCurrentValue(uint32_t nModifier);

protected:
void OnValueChanged(const IntModelProperty::ChangeArgs& args) override;

Expand Down
32 changes: 32 additions & 0 deletions src/ui/win32/bindings/MemoryViewerControlBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ bool MemoryViewerControlBinding::OnKeyDown(UINT nChar)

if (!m_pViewModel.IsAddressFixed())
bHandled = HandleNavigation(nChar);
if (!bHandled)
bHandled = HandleShortcut(nChar);

m_bSuppressMemoryViewerInvalidate = false;

Expand Down Expand Up @@ -236,6 +238,36 @@ bool MemoryViewerControlBinding::HandleNavigation(UINT nChar)
}
}

bool MemoryViewerControlBinding::HandleShortcut(UINT nChar)
{
const bool bShiftHeld = (GetKeyState(VK_SHIFT) < 0);
const bool bControlHeld = (GetKeyState(VK_CONTROL) < 0);

switch (nChar)
{
// Increment/Decrement value Shortcuts
case VK_ADD:
case VK_SUBTRACT:
Jamiras marked this conversation as resolved.
Show resolved Hide resolved
{
auto nModifier = 1;

// Increase/decrease by 1 or 2 on the high and lower nibble depending key pressed
if (bControlHeld)
nModifier *= 2;
if (bShiftHeld)
nModifier *= 16;

if (nChar == VK_ADD)
return m_pViewModel.IncreaseCurrentValue(nModifier);
else
return m_pViewModel.DecreaseCurrentValue(nModifier);
}

default:
return false;
}
}

bool MemoryViewerControlBinding::OnEditInput(UINT c)
{
// multiple properties may change while typing, we'll do a single Invalidate after we're done
Expand Down
1 change: 1 addition & 0 deletions src/ui/win32/bindings/MemoryViewerControlBinding.hh
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ protected:

private:
bool HandleNavigation(UINT nChar);
bool HandleShortcut(UINT nChar);
bool m_bSuppressMemoryViewerInvalidate = false;

ra::ui::viewmodels::MemoryViewerViewModel& m_pViewModel;
Expand Down
162 changes: 162 additions & 0 deletions tests/ui/viewmodels/MemoryViewerViewModel_Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1918,6 +1918,168 @@ TEST_CLASS(MemoryViewerViewModel_Tests)
Assert::IsTrue(viewer.NeedsRedraw());
viewer.MockRender();
}

TEST_METHOD(TestIncreaseCurrentValueByOne)
{
MemoryViewerViewModelHarness viewer;
viewer.InitializeMemory(256);

// ignore if readonly
Assert::IsTrue(viewer.IsReadOnly());
Assert::IsFalse(viewer.IncreaseCurrentValue(1));

viewer.SetReadOnly(false);
Assert::IsFalse(viewer.IsReadOnly());

viewer.SetAddress(0x0U);
Assert::AreEqual({ 0U }, viewer.GetAddress());
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Increase by 1 from 0x0 should result to 0X1
Assert::IsTrue(viewer.IncreaseCurrentValue(1));
Assert::AreEqual({ 0x1U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Increase by 1 from 0xFE should result to 0XFF
viewer.mockEmulatorContext.WriteMemoryByte(0x0U, 0XFEU);
Assert::IsTrue(viewer.IncreaseCurrentValue(1));
Assert::AreEqual({ 0xFFU }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Increase by 1 from 0xFF should not change the value
Assert::IsFalse(viewer.IncreaseCurrentValue(1));
Assert::AreEqual({ 0xFFU }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Increase by 1 from 0x0 should result to 0X0001
viewer.mockEmulatorContext.WriteMemory(0x0U, MemSize::SixteenBit, 0X0U);
Assert::IsTrue(viewer.IncreaseCurrentValue(1));
Assert::AreEqual({ 0x1U }, viewer.mockEmulatorContext.ReadMemory(0U, MemSize::SixteenBit));

// Increase by 1 from 0xFFFF should not change the value
viewer.mockEmulatorContext.WriteMemory(0x0U, MemSize::SixteenBit, 0XFFFFU);
Assert::IsFalse(viewer.IncreaseCurrentValue(1));
Assert::AreEqual({ 0xFFFFU }, viewer.mockEmulatorContext.ReadMemory(0U, MemSize::SixteenBit));
}

TEST_METHOD(TestIncreaseCurrentValueBySixTeen)
Vancleeff marked this conversation as resolved.
Show resolved Hide resolved
{
MemoryViewerViewModelHarness viewer;
viewer.InitializeMemory(256);

// ignore if readonly
Assert::IsTrue(viewer.IsReadOnly());
Assert::IsFalse(viewer.IncreaseCurrentValue(16));

viewer.SetReadOnly(false);
Assert::IsFalse(viewer.IsReadOnly());

viewer.SetAddress(0x0U);
Assert::AreEqual({ 0U }, viewer.GetAddress());
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Increase by 16 from 0x0 should result to 0X10
Assert::IsTrue(viewer.IncreaseCurrentValue(16));
Assert::AreEqual({ 0x10U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Increase by 16 from 0xFE should result to 0XFF
viewer.mockEmulatorContext.WriteMemoryByte(0x0U, 0XFEU);
Assert::IsTrue(viewer.IncreaseCurrentValue(16));
Assert::AreEqual({ 0xFFU }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Increase by 16 from 0xFF should not change the value
Assert::IsFalse(viewer.IncreaseCurrentValue(16));
Assert::AreEqual({ 0xFFU }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Increase by 16 from 0x0 should result to 0X0010
viewer.mockEmulatorContext.WriteMemory(0x0U, MemSize::SixteenBit, 0X0U);
Assert::IsTrue(viewer.IncreaseCurrentValue(16));
Assert::AreEqual({ 0x10U }, viewer.mockEmulatorContext.ReadMemory(0U, MemSize::SixteenBit));

// Increase by 16 from 0xFFFF should not change the value
viewer.mockEmulatorContext.WriteMemory(0x0U, MemSize::SixteenBit, 0XFFFFU);
Assert::IsFalse(viewer.IncreaseCurrentValue(16));
Assert::AreEqual({ 0xFFFFU }, viewer.mockEmulatorContext.ReadMemory(0U, MemSize::SixteenBit));
}

TEST_METHOD(TestDecreaseCurrentValueByOne)
{
MemoryViewerViewModelHarness viewer;
viewer.InitializeMemory(256);

// ignore if readonly
Assert::IsTrue(viewer.IsReadOnly());
Assert::IsFalse(viewer.DecreaseCurrentValue(1));

viewer.SetReadOnly(false);
Assert::IsFalse(viewer.IsReadOnly());

viewer.SetAddress(0x0U);
Assert::AreEqual({ 0U }, viewer.GetAddress());
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Decrease by 1 from 0x0 should not change the value
Assert::IsFalse(viewer.DecreaseCurrentValue(1));
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Decrease by 1 from 0xFF should result to 0XFE
viewer.mockEmulatorContext.WriteMemoryByte(0x0U, 0XFFU);
Assert::IsTrue(viewer.DecreaseCurrentValue(1));
Assert::AreEqual({ 0xFEU }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Decrease by 1 from 0x1 should result to 0X0
viewer.mockEmulatorContext.WriteMemoryByte(0x0U, 0X1U);
Assert::IsTrue(viewer.DecreaseCurrentValue(1));
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Decrease by 1 from 0x0 should not change the value
viewer.mockEmulatorContext.WriteMemory(0x0U, MemSize::SixteenBit, 0X0U);
Assert::IsFalse(viewer.DecreaseCurrentValue(1));
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemory(0U, MemSize::SixteenBit));

// Decrease by 1 from 0xFFFF should result to 0XFFFE
viewer.mockEmulatorContext.WriteMemory(0x0U, MemSize::SixteenBit, 0XFFFFU);
Assert::IsTrue(viewer.DecreaseCurrentValue(1));
Assert::AreEqual({ 0xFFFEU }, viewer.mockEmulatorContext.ReadMemory(0U, MemSize::SixteenBit));
}

TEST_METHOD(TestDecreaseCurrentValueBySixteen)
{
MemoryViewerViewModelHarness viewer;
viewer.InitializeMemory(256);

// ignore if readonly
Assert::IsTrue(viewer.IsReadOnly());
Assert::IsFalse(viewer.DecreaseCurrentValue(16));

viewer.SetReadOnly(false);
Assert::IsFalse(viewer.IsReadOnly());

viewer.SetAddress(0x0U);
Assert::AreEqual({ 0U }, viewer.GetAddress());
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Decrease by 16 from 0x0 should not change the value
Assert::IsFalse(viewer.DecreaseCurrentValue(16));
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Decrease by 16 from 0xFF should result to 0XEF
viewer.mockEmulatorContext.WriteMemoryByte(0x0U, 0XFFU);
Assert::IsTrue(viewer.DecreaseCurrentValue(16));
Assert::AreEqual({ 0xEFU }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Decrease by 16 from 0x1 should result to 0X0
viewer.mockEmulatorContext.WriteMemoryByte(0x0U, 0X1U);
Assert::IsTrue(viewer.DecreaseCurrentValue(16));
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemoryByte(0U));

// Decrease by 16 from 0x0 should not change the value
viewer.mockEmulatorContext.WriteMemory(0x0U, MemSize::SixteenBit, 0X0U);
Assert::IsFalse(viewer.DecreaseCurrentValue(16));
Assert::AreEqual({ 0x0U }, viewer.mockEmulatorContext.ReadMemory(0U, MemSize::SixteenBit));

// Decrease by 16 from 0xFFFF should result to 0XFFEF
viewer.mockEmulatorContext.WriteMemory(0x0U, MemSize::SixteenBit, 0XFFFFU);
Assert::IsTrue(viewer.DecreaseCurrentValue(16));
Assert::AreEqual({ 0xFFEFU }, viewer.mockEmulatorContext.ReadMemory(0U, MemSize::SixteenBit));
}
};

} // namespace tests
Expand Down
Loading