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

MemoryWidget: Add negative offset search support #10079

Merged
merged 1 commit into from Mar 25, 2022

Conversation

sepalani
Copy link
Contributor

@sepalani sepalani commented Sep 1, 2021

This PR allows to search/replace value from the Memory widget using a negative offset.

Ready to be reviewed & merged.

@sepalani sepalani changed the title MemoryWidget:: Add negative offset search support MemoryWidget: Add negative offset search support Sep 1, 2021
@JMC47
Copy link
Contributor

JMC47 commented Sep 1, 2021

I ran into this the other day. Thought it was really stupid that we couldn't do negative offset. +1

@@ -446,7 +446,7 @@ void MemoryWidget::OnSearchAddress()
bool good_addr, good_offset;
// Returns 0 if conversion fails
const u32 addr = m_search_address->text().toUInt(&good_addr, 16);
const u32 offset = m_search_offset->text().toUInt(&good_offset, 16);
const s32 offset = m_search_offset->text().toInt(&good_offset, 16);
Copy link
Member

Choose a reason for hiding this comment

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

note that without casts below, this introduces an implicit sign/unsigned mismatch in terms of arithmetic. Ditto for the other cases as well

@sepalani
Copy link
Contributor Author

sepalani commented Sep 1, 2021

@lioncash
Done. I changed my approach and used the GetTargetAddress method to compute the address and perform sanity checks. It also fixes bugs like being able to search values even if the address is invalid.

Copy link
Contributor

@Dentomologist Dentomologist left a comment

Choose a reason for hiding this comment

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

This is a good feature to have, and it also lets you write values without needing an offset which was annoying.

@@ -651,22 +647,53 @@ std::vector<u8> MemoryWidget::GetValueData() const
return search_for;
}

u32 MemoryWidget::GetTargetAddress(bool* good_address, bool* good_offset) const
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
u32 MemoryWidget::GetTargetAddress(bool* good_address, bool* good_offset) const
u32 MemoryWidget::GetTargetAddress(bool* const good_address, bool* const good_offset) const

*good_address |= m_search_address->text().isEmpty();
const s32 offset = m_search_offset->text().toInt(good_offset, 16);
*good_offset |= m_search_offset->text().isEmpty();
*good_offset &= offset >= 0 || u32(-offset) <= addr;
Copy link
Contributor

Choose a reason for hiding this comment

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

A few edge cases:

  • This wraps addresses from the top of the address space to the bottom but not vice versa.
  • I think -offset is undefined behavior if offset == -INT_MIN. It works anyway on my computer, but nasal demons.
  • Offsets can't be more than half the size of the address space.

Would it make sense to parse everything as s64 then manually validate the ranges? That would allow everything to have the full range of values that make sense while avoiding signed/unsigned conversion issues.

@sepalani
Copy link
Contributor Author

@Dentomologist Done.

I addressed the offset checks by doing it both way and using s16 instead to prevent nasal demons.

@Dentomologist
Copy link
Contributor

Making the offsets s16 fixes the UB but limits them to +- 32k; I don't know how often people need offsets larger than that, but I would guess that it's not so rare as to not be worth supporting.

@@ -57,6 +57,7 @@ class MemoryWidget : public QDockWidget
void OnDumpFakeVMEM();

std::vector<u8> GetValueData() const;
u32 GetTargetAddress(bool* good_address, bool* good_offset) const;
Copy link
Member

Choose a reason for hiding this comment

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

Any reason this doesn't return a struct like:

struct SomeName
{
  u32 address = 0;
  bool is_good_address = false;
  bool is_good_offset = false;
};

?

This would get rid of the out parameters and allow structured bindings.

It also gets rid of the uninitialized reads that are present in the existing code from forgetting to initialize the bools before calling the function (since |= is used in the function)

Copy link
Contributor

Choose a reason for hiding this comment

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

The struct sounds good to me.

Pedantic: good_address and good_offset are initialized by QString's toUInt and toShort functions before the |=s, but the fact that isn't obvious is a point in favor of the struct.

@sepalani
Copy link
Contributor Author

@lioncash
@Dentomologist
Done.

@AdmiralCurtiss
Copy link
Contributor

This is still limited to +/- 32k offsets.

@sepalani sepalani force-pushed the neg-offset branch 4 times, most recently from 92cea60 to 45ae9fc Compare March 24, 2022 18:47
@sepalani
Copy link
Contributor Author

@AdmiralCurtiss
Should be fixed, now.

Copy link
Contributor

@AdmiralCurtiss AdmiralCurtiss left a comment

Choose a reason for hiding this comment

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

Looks good now.

@AdmiralCurtiss AdmiralCurtiss merged commit e58cf36 into dolphin-emu:master Mar 25, 2022
@sepalani sepalani deleted the neg-offset branch April 9, 2022 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
5 participants