Skip to content

Memory Observer improvements:#1927

Open
notdodgeball wants to merge 4 commits into
grumpycoders:mainfrom
notdodgeball:memory-observer
Open

Memory Observer improvements:#1927
notdodgeball wants to merge 4 commits into
grumpycoders:mainfrom
notdodgeball:memory-observer

Conversation

@notdodgeball
Copy link
Copy Markdown

• proper TextFlags in input box
• new remove button in address tables
• changed position for "fixed-point values" checkbox
• new buttons for (un)freeze/all
• smaller buttons for read and write breakpoints, unified in a single column
• validate sequence size to prevent error

• proper TextFlags in input box
• remove button in address tables
• new position for "fixed-point values" checkbox
• new buttons for (un)freeze/all
• smaller buttons for read and write breakpoints
• validate sequence size to prevent error
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2025

Review Change Stack

📝 Walkthrough

Walkthrough

UI changes to the memory observer: Pattern input character filtering by Hex state; per-row Remove buttons in Plain and Delta-over-time results; Delta-over-time adds New scan, conditional fixed-point display, bulk Freeze/Unfreeze/Remove frozen controls, expanded result columns with Freeze and Read/Write breakpoints; Pattern search truncates sequences for fixed sizes.

Changes

Memory observer UI

Layer / File(s) Summary
Plain search input & results
src/gui/widgets/memory_observer.cc
Pattern input now filters characters to hex or decimal based on the Hex checkbox; "Found values" gains a Remove column and per-row Remove button that erases addresses and restarts the clipper.
Delta-over-time scan & bulk controls
src/gui/widgets/memory_observer.cc
Adds "New scan" initialization/clear behavior, conditional "Display as fixed-point values" checkbox (!hex && stride>1), enables/disables value input per scan type, and Next-scan guarded by existing results. Adds bulk "Freeze all" / "Unfreeze all" / "Remove frozen addresses" actions; expands results table to Address, Current, Previous, Freeze (per-row), Access, Breakpoint (Read/Write), and Remove; per-row Freeze captures frozenValue.
Pattern size truncation
src/gui/widgets/memory_observer.cc
When switching to 8-byte or 16-byte fast sequence sizes, truncates the existing sequence string by inserting a null terminator at the chosen size.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant GUI
  participant MemoryObserver

  User->>GUI: Enter value in "Plain search" input
  GUI->>GUI: Filter input characters (hex or decimal)

  User->>GUI: Click "Remove" on a found address
  GUI->>MemoryObserver: Remove address and update results

  User->>GUI: Use "Delta-over-time" controls (New scan, Freeze all, etc.)
  GUI->>MemoryObserver: Initialize/clear results, apply bulk freeze/unfreeze/remove

  User->>GUI: Select sequence size in "Pattern search"
  GUI->>GUI: Truncate sequence string if it exceeds selected size
Loading

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • nicolasnoble

Poem

In memory meadows I hop and stare,
Buttons to freeze and rows to pare.
Hex or decimal, precise in sight,
Remove and truncate—everything's right.
A rabbit claps for the GUI's new light. 🐇✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Memory Observer improvements' is vague and generic, using non-descriptive language that doesn't convey the specific changes made to the pull request. Consider a more specific title that highlights the main change, such as 'Add UI improvements to Memory Observer: remove buttons, freeze actions, and input validation' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly relates to the changeset, listing specific improvements including TextFlags, remove buttons, checkbox repositioning, freeze/unfreeze buttons, breakpoint buttons, and sequence validation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nicolasnoble nicolasnoble requested a review from Copilot April 24, 2025 21:09
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refines the Memory Observer widget with improved input handling, new removal buttons, updated layout for checkboxes and breakpoints, and sequence size validation to prevent errors.

  • Enhanced the TextFlags for the pattern input to support hexadecimal/decimal validation
  • Added new buttons for removing addresses and for freezing/unfreezing memory addresses
  • Implemented sequence length truncation when selecting preset sequence sizes
Comments suppressed due to low confidence (1)

src/gui/widgets/memory_observer.cc:443

  • Truncating m_sequence in the radio button selection logic may inadvertently remove valid data if the sequence exceeds the expected length; please verify that this behavior is intended and consider adding a clarifying comment or test to document it.
if (ImGui::RadioButton(_("8 bytes (fast)"), &m_sequenceSize, 8) && strlen(m_sequence) > 8) {

notdodgeball and others added 3 commits July 31, 2025 11:17
Add column for freeze action
Change button order, one less button
Use std::erase_if instead of std::remove_if
Disable input when not needed
Finally, change the Next Scan button to underneath it all to stop hitting it accidentally
@pull-request-size pull-request-size Bot added size/L and removed size/M labels May 28, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/gui/widgets/memory_observer.cc`:
- Around line 211-252: The final stride-aligned block never gets evaluated
because the switch handling accumulated memValue only runs when i % stride == 0
inside the loop; after the loop ends you must run the same switch on the last
accumulated memValue (the block that covers memBase + memSize - stride .. end)
and push matches into m_addressValuePairs; implement this by either extracting
the switch logic into a helper (e.g., ProcessScannedValue(int64_t value,
uint32_t addr) and call it inside the loop and once after the loop) or by
duplicating the switch after the loop using the same conditions (use m_scanType,
m_value, memValue, memBase, stride, getValueAsSelectedType, memData to compute
the correct address).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d234f543-ec13-425e-b029-e3402d3f6c31

📥 Commits

Reviewing files that changed from the base of the PR and between 943c847 and 0653755.

📒 Files selected for processing (1)
  • src/gui/widgets/memory_observer.cc

Comment on lines +211 to +252
if (ImGui::Button(_("New scan"))) {
if (m_addressValuePairs.empty()) {
int64_t memValue = 0;

for (uint32_t i = 0; i < memSize; ++i) {
if (i != 0 && i % stride == 0) {
switch (m_scanType) {
case ScanType::ExactValue:
if (memValue == m_value) {
m_addressValuePairs.push_back({memBase + i - stride, memValue});
}
break;
case ScanType::GreaterThan:
if (memValue > m_value) {
m_addressValuePairs.push_back({memBase + i - stride, memValue});
}
break;
case ScanType::LessThan:
if (memValue < m_value) {
m_addressValuePairs.push_back({memBase + i - stride, memValue});
}
break;
case ScanType::Changed:
case ScanType::Unchanged:
case ScanType::Increased:
case ScanType::Decreased:
break;
case ScanType::UnknownInitialValue:
m_addressValuePairs.push_back({memBase + i - stride, memValue});
}
break;
case ScanType::Changed:
case ScanType::Unchanged:
case ScanType::Increased:
case ScanType::Decreased:
break;
case ScanType::UnknownInitialValue:
m_addressValuePairs.push_back({memBase + i - stride, memValue});
break;
break;
}

memValue = 0;
}

memValue = 0;
const uint8_t currentByte = memData[i];
const uint8_t leftShift = 8 * (i % stride);
const uint32_t mask = 0xffffffff ^ (0xff << leftShift);
const int byteToWrite = currentByte << leftShift;
memValue = (memValue & mask) | byteToWrite;
memValue = getValueAsSelectedType(memValue);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Last stride-aligned memory block is never scanned.

The loop processes accumulated memValue at stride boundaries (when i != 0 && i % stride == 0), but the final block accumulated during the last stride iterations is never evaluated after the loop exits. This causes the addresses from memBase + memSize - stride onward to be missing from scan results.

Proposed fix: process the final block after the loop
                         memValue = getValueAsSelectedType(memValue);
                     }
+                    // Process the final accumulated value
+                    switch (m_scanType) {
+                        case ScanType::ExactValue:
+                            if (memValue == m_value) {
+                                m_addressValuePairs.push_back({memBase + memSize - stride, memValue});
+                            }
+                            break;
+                        case ScanType::GreaterThan:
+                            if (memValue > m_value) {
+                                m_addressValuePairs.push_back({memBase + memSize - stride, memValue});
+                            }
+                            break;
+                        case ScanType::LessThan:
+                            if (memValue < m_value) {
+                                m_addressValuePairs.push_back({memBase + memSize - stride, memValue});
+                            }
+                            break;
+                        case ScanType::Changed:
+                        case ScanType::Unchanged:
+                        case ScanType::Increased:
+                        case ScanType::Decreased:
+                            break;
+                        case ScanType::UnknownInitialValue:
+                            m_addressValuePairs.push_back({memBase + memSize - stride, memValue});
+                            break;
+                    }
                 } else {
                     m_addressValuePairs.clear();

Alternatively, refactor the loop to process after accumulation or extract the switch logic into a helper function to avoid duplication.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gui/widgets/memory_observer.cc` around lines 211 - 252, The final
stride-aligned block never gets evaluated because the switch handling
accumulated memValue only runs when i % stride == 0 inside the loop; after the
loop ends you must run the same switch on the last accumulated memValue (the
block that covers memBase + memSize - stride .. end) and push matches into
m_addressValuePairs; implement this by either extracting the switch logic into a
helper (e.g., ProcessScannedValue(int64_t value, uint32_t addr) and call it
inside the loop and once after the loop) or by duplicating the switch after the
loop using the same conditions (use m_scanType, m_value, memValue, memBase,
stride, getValueAsSelectedType, memData to compute the correct address).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants