Make sure to reserve() exactly the right amount of elements for the std::vector before filling it with CheatSearchResult's, in order to prevent automatic re-allocations.
It turns out that this (somewhat) gets rid of memory-related exceptions which used to occur (especially) during 8-bit cheat searches. At least this is the case with my computer that has 3GB of RAM (the issue didn't seem to be caused by 100% of RAM usage, however). Hopefully you'll be able to perform the following steps without errors now: 1. Open any game in Dolphin; 2. Go to Tools->Cheats Manager, and open the "Cheat Search" tab; 3. Preferably set the "Data Size" to 8-bit (the smaller, the more initial search results); 4. Press the "New Scan" button; 5. Use the "Unknown" search filter (which won't narrow the results down at all); 6. Press the "Next Scan" button. (oh, and fix a typo in a comment I introduced in r6791 :p) Anyway, make sure to tell me any eventual errors/regressions. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7596 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
c84cddc83a
commit
98536df915
|
@ -159,7 +159,7 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
|
||||||
std::string FileName = name + ext;
|
std::string FileName = name + ext;
|
||||||
|
|
||||||
// Decode entities of invalid file system characters so that
|
// Decode entities of invalid file system characters so that
|
||||||
// games (such as HB:HBP) will be able to find what they expect.
|
// games (such as HP:HBP) will be able to find what they expect.
|
||||||
for (Common::replace_v::const_iterator it = replacements.begin(); it != replacements.end(); ++it)
|
for (Common::replace_v::const_iterator it = replacements.begin(); it != replacements.end(); ++it)
|
||||||
{
|
{
|
||||||
for (size_t j = 0; (j = FileName.find(it->second, j)) != FileName.npos; ++j)
|
for (size_t j = 0; (j = FileName.find(it->second, j)) != FileName.npos; ++j)
|
||||||
|
|
|
@ -350,32 +350,33 @@ void wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& W
|
||||||
|
|
||||||
void CheatSearchTab::StartNewSearch(wxCommandEvent& WXUNUSED (event))
|
void CheatSearchTab::StartNewSearch(wxCommandEvent& WXUNUSED (event))
|
||||||
{
|
{
|
||||||
search_results.clear();
|
|
||||||
|
|
||||||
const u8* const memptr = Memory::GetPointer(0);
|
const u8* const memptr = Memory::GetPointer(0);
|
||||||
if (NULL == memptr)
|
if (NULL == memptr)
|
||||||
{
|
{
|
||||||
PanicAlertT("A game is not currently running.");
|
PanicAlertT("A game is not currently running.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// Determine the user-selected data size for this search.
|
||||||
|
search_type_size =
|
||||||
|
size_radiobtn.rad_8->GetValue() +
|
||||||
|
(size_radiobtn.rad_16->GetValue() << 1) +
|
||||||
|
(size_radiobtn.rad_32->GetValue() << 2);
|
||||||
|
|
||||||
|
// Set up the search results efficiently to prevent automatic re-allocations.
|
||||||
|
search_results.clear();
|
||||||
|
search_results.reserve(Memory::RAM_SIZE / search_type_size);
|
||||||
|
|
||||||
|
// Enable the "Next Scan" button.
|
||||||
|
btnNextScan->Enable();
|
||||||
|
|
||||||
|
CheatSearchResult r;
|
||||||
|
// can I assume cheatable values will be aligned like this?
|
||||||
|
for (u32 addr = 0; addr != Memory::RAM_SIZE; addr += search_type_size)
|
||||||
{
|
{
|
||||||
// enable the next scan button
|
r.address = addr;
|
||||||
btnNextScan->Enable();
|
memcpy(&r.old_value, memptr + addr, search_type_size);
|
||||||
|
search_results.push_back(r);
|
||||||
// determine the search data size
|
|
||||||
search_type_size =
|
|
||||||
size_radiobtn.rad_8->GetValue() +
|
|
||||||
(size_radiobtn.rad_16->GetValue() << 1) +
|
|
||||||
(size_radiobtn.rad_32->GetValue() << 2);
|
|
||||||
|
|
||||||
CheatSearchResult r;
|
|
||||||
// can I assume cheatable values will be aligned like this?
|
|
||||||
for (u32 addr = 0; addr != Memory::RAM_SIZE; addr += search_type_size)
|
|
||||||
{
|
|
||||||
r.address = addr;
|
|
||||||
memcpy(&r.old_value, memptr + addr, search_type_size);
|
|
||||||
search_results.push_back(r);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateCheatSearchResultsList();
|
UpdateCheatSearchResultsList();
|
||||||
|
@ -387,99 +388,101 @@ void CheatSearchTab::FilterCheatSearchResults(wxCommandEvent&)
|
||||||
if (NULL == memptr)
|
if (NULL == memptr)
|
||||||
{
|
{
|
||||||
PanicAlertT("A game is not currently running.");
|
PanicAlertT("A game is not currently running.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
std::vector<CheatSearchResult>::iterator
|
||||||
|
i = search_results.begin(),
|
||||||
|
e = search_results.end();
|
||||||
|
|
||||||
|
// Set up the sub-search results efficiently to prevent automatic re-allocations.
|
||||||
|
std::vector<CheatSearchResult> filtered_results;
|
||||||
|
filtered_results.reserve(search_results.size());
|
||||||
|
|
||||||
|
|
||||||
|
// determine the selected filter
|
||||||
|
// 1 : equal
|
||||||
|
// 2 : greater-than
|
||||||
|
// 4 : less-than
|
||||||
|
|
||||||
|
const int filters[] = {7, 6, 1, 2, 4};
|
||||||
|
int filter_mask = filters[search_type->GetSelection()];
|
||||||
|
|
||||||
|
if (value_x_radiobtn.rad_oldvalue->GetValue()) // using old value comparison
|
||||||
{
|
{
|
||||||
std::vector<CheatSearchResult>::iterator
|
for (; i!=e; ++i)
|
||||||
i = search_results.begin(),
|
|
||||||
e = search_results.end();
|
|
||||||
std::vector<CheatSearchResult> filtered_results;
|
|
||||||
|
|
||||||
|
|
||||||
// determine the selected filter
|
|
||||||
// 1 : equal
|
|
||||||
// 2 : greater-than
|
|
||||||
// 4 : less-than
|
|
||||||
|
|
||||||
const int filters[] = {7, 6, 1, 2, 4};
|
|
||||||
int filter_mask = filters[search_type->GetSelection()];
|
|
||||||
|
|
||||||
if (value_x_radiobtn.rad_oldvalue->GetValue()) // using old value comparison
|
|
||||||
{
|
{
|
||||||
for (; i!=e; ++i)
|
// with big endian, can just use memcmp for ><= comparison
|
||||||
{
|
int cmp_result = memcmp(memptr + i->address, &i->old_value, search_type_size);
|
||||||
// with big endian, can just use memcmp for ><= comparison
|
if (cmp_result < 0)
|
||||||
int cmp_result = memcmp(memptr + i->address, &i->old_value, search_type_size);
|
cmp_result = 4;
|
||||||
if (cmp_result < 0)
|
else
|
||||||
cmp_result = 4;
|
cmp_result = cmp_result ? 2 : 1;
|
||||||
else
|
|
||||||
cmp_result = cmp_result ? 2 : 1;
|
|
||||||
|
|
||||||
if (cmp_result & filter_mask)
|
if (cmp_result & filter_mask)
|
||||||
{
|
{
|
||||||
memcpy(&i->old_value, memptr + i->address, search_type_size);
|
memcpy(&i->old_value, memptr + i->address, search_type_size);
|
||||||
filtered_results.push_back(*i);
|
filtered_results.push_back(*i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // using user entered x value comparison
|
|
||||||
{
|
|
||||||
u32 user_x_val;
|
|
||||||
|
|
||||||
// parse the user entered x value
|
|
||||||
if (filter_mask != 7) // don't need the value for the "None" filter
|
|
||||||
{
|
|
||||||
unsigned long parsed_x_val = 0;
|
|
||||||
wxString x_val = textctrl_value_x->GetLabel();
|
|
||||||
|
|
||||||
if (!x_val.ToULong(&parsed_x_val, 0))
|
|
||||||
{
|
|
||||||
PanicAlertT("You must enter a valid decimal, hexadecimal or octal value.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
user_x_val = (u32)parsed_x_val;
|
|
||||||
|
|
||||||
// #ifdef LIL_ENDIAN :p
|
|
||||||
switch (search_type_size)
|
|
||||||
{
|
|
||||||
case 1 :
|
|
||||||
break;
|
|
||||||
case 2 :
|
|
||||||
*(u16*)&user_x_val = Common::swap16((u8*)&user_x_val);
|
|
||||||
break;
|
|
||||||
case 4 :
|
|
||||||
user_x_val = Common::swap32(user_x_val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// #elseif BIG_ENDIAN
|
|
||||||
// would have to move <u32 vals (8/16bit) to start of the user_x_val for the comparisons i use below
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i!=e; ++i)
|
|
||||||
{
|
|
||||||
// with big endian, can just use memcmp for ><= comparison
|
|
||||||
int cmp_result = memcmp(memptr + i->address, &user_x_val, search_type_size);
|
|
||||||
if (cmp_result < 0)
|
|
||||||
cmp_result = 4;
|
|
||||||
else if (cmp_result)
|
|
||||||
cmp_result = 2;
|
|
||||||
else
|
|
||||||
cmp_result = 1;
|
|
||||||
|
|
||||||
if (cmp_result & filter_mask)
|
|
||||||
{
|
|
||||||
memcpy(&i->old_value, memptr + i->address, search_type_size);
|
|
||||||
filtered_results.push_back(*i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
search_results.swap(filtered_results);
|
|
||||||
|
|
||||||
UpdateCheatSearchResultsList();
|
|
||||||
}
|
}
|
||||||
|
else // using user entered x value comparison
|
||||||
|
{
|
||||||
|
u32 user_x_val;
|
||||||
|
|
||||||
|
// parse the user entered x value
|
||||||
|
if (filter_mask != 7) // don't need the value for the "None" filter
|
||||||
|
{
|
||||||
|
unsigned long parsed_x_val = 0;
|
||||||
|
wxString x_val = textctrl_value_x->GetLabel();
|
||||||
|
|
||||||
|
if (!x_val.ToULong(&parsed_x_val, 0))
|
||||||
|
{
|
||||||
|
PanicAlertT("You must enter a valid decimal, hexadecimal or octal value.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user_x_val = (u32)parsed_x_val;
|
||||||
|
|
||||||
|
// #ifdef LIL_ENDIAN :p
|
||||||
|
switch (search_type_size)
|
||||||
|
{
|
||||||
|
case 1 :
|
||||||
|
break;
|
||||||
|
case 2 :
|
||||||
|
*(u16*)&user_x_val = Common::swap16((u8*)&user_x_val);
|
||||||
|
break;
|
||||||
|
case 4 :
|
||||||
|
user_x_val = Common::swap32(user_x_val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// #elseif BIG_ENDIAN
|
||||||
|
// would have to move <u32 vals (8/16bit) to start of the user_x_val for the comparisons i use below
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i!=e; ++i)
|
||||||
|
{
|
||||||
|
// with big endian, can just use memcmp for ><= comparison
|
||||||
|
int cmp_result = memcmp(memptr + i->address, &user_x_val, search_type_size);
|
||||||
|
if (cmp_result < 0)
|
||||||
|
cmp_result = 4;
|
||||||
|
else if (cmp_result)
|
||||||
|
cmp_result = 2;
|
||||||
|
else
|
||||||
|
cmp_result = 1;
|
||||||
|
|
||||||
|
if (cmp_result & filter_mask)
|
||||||
|
{
|
||||||
|
memcpy(&i->old_value, memptr + i->address, search_type_size);
|
||||||
|
filtered_results.push_back(*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
search_results.swap(filtered_results);
|
||||||
|
|
||||||
|
UpdateCheatSearchResultsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheatSearchTab::ApplyFocus(wxCommandEvent&)
|
void CheatSearchTab::ApplyFocus(wxCommandEvent&)
|
||||||
|
|
Loading…
Reference in New Issue