791 lines
26 KiB
C++
791 lines
26 KiB
C++
/****************************************************************************
|
|
* *
|
|
* Project 64 - A Nintendo 64 emulator. *
|
|
* http://www.pj64-emu.com/ *
|
|
* Copyright (C) 2012 Project64. All rights reserved. *
|
|
* *
|
|
* License: *
|
|
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
|
* *
|
|
****************************************************************************/
|
|
#include "stdafx.h"
|
|
|
|
#include "Debugger UI.h"
|
|
|
|
CDebugMemorySearch::CDebugMemorySearch(CDebuggerUI * debugger) :
|
|
CDebugDialog<CDebugMemorySearch>(debugger),
|
|
m_MemoryState(NULL),
|
|
m_MemoryStateSize(0)
|
|
{
|
|
}
|
|
|
|
CDebugMemorySearch::~CDebugMemorySearch()
|
|
{
|
|
if (m_MemoryState)
|
|
{
|
|
delete m_MemoryState;
|
|
}
|
|
}
|
|
|
|
void CDebugMemorySearch::AddAlignmentOptions(CComboBox & ctrl)
|
|
{
|
|
int Index = ctrl.AddString("32 bits (aligned)");
|
|
ctrl.SetItemData(Index, _32Bit);
|
|
Index = ctrl.AddString("16bits (aligned)");
|
|
ctrl.SetItemData(Index, _16Bit);
|
|
Index = ctrl.AddString("8bits");
|
|
ctrl.SetCurSel(Index);
|
|
ctrl.SetItemData(Index, _8Bit);
|
|
}
|
|
|
|
LRESULT CDebugMemorySearch::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
{
|
|
m_PAddrStart.Attach(GetDlgItem(IDC_PADDR_START));
|
|
m_PAddrStart.SetDisplayType(CEditNumber::DisplayHex);
|
|
m_SearchLen.Attach(GetDlgItem(IDC_ADDR_END));
|
|
m_SearchLen.SetDisplayType(CEditNumber::DisplayHex);
|
|
m_SearchValue.Attach(GetDlgItem(IDC_SEARCH_VALUE));
|
|
m_SearchValue.SetDisplayType(CEditNumber::DisplayDec);
|
|
m_SearchValue.SetValue(0);
|
|
m_MaxSearch.Attach(GetDlgItem(IDC_MAX_SEARCH));
|
|
m_MaxSearch.SetDisplayType(CEditNumber::DisplayDec);
|
|
m_MaxSearch.SetValue(50000);
|
|
m_UnknownSize.Attach(GetDlgItem(IDC_UNKNOWN_ALIGN));
|
|
AddAlignmentOptions(m_UnknownSize);
|
|
m_ValueSize.Attach(GetDlgItem(IDC_VALUE_ALIGN));
|
|
AddAlignmentOptions(m_ValueSize);
|
|
m_SearchResults.Attach(GetDlgItem(IDC_LST_RESULTS));
|
|
m_SearchResults.AddColumn("ID", 0);
|
|
m_SearchResults.AddColumn("PAddr", 1);
|
|
m_SearchResults.AddColumn("Value", 2);
|
|
m_SearchResults.SetColumnWidth(0, 50);
|
|
m_SearchResults.SetColumnWidth(1, 75);
|
|
m_SearchResults.SetColumnWidth(2, 75);
|
|
m_SearchResults.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
|
|
m_UnknownOptions.Attach(GetDlgItem(IDC_CMB_UNKNOWN));
|
|
m_HaveResults = false;
|
|
FixUnknownOptions(true);
|
|
|
|
SendMessage(GetDlgItem(IDC_RADIO_VALUE), BM_SETCHECK, BST_CHECKED, 0);
|
|
|
|
BOOL bHandled;
|
|
OnClicked(0, IDC_BTN_RDRAM, NULL, bHandled);
|
|
OnClicked(0, IDC_RADIO_VALUE, NULL, bHandled);
|
|
WindowCreated();
|
|
return TRUE;
|
|
}
|
|
|
|
LRESULT CDebugMemorySearch::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/)
|
|
{
|
|
switch (wID)
|
|
{
|
|
case IDCANCEL:
|
|
EndDialog(0);
|
|
break;
|
|
case IDC_BTN_RDRAM:
|
|
m_PAddrStart.SetValue(0, true, true);
|
|
m_SearchLen.SetValue(g_MMU->RdramSize(), true, true);
|
|
break;
|
|
case IDC_BTN_ROM:
|
|
m_PAddrStart.SetValue(0x10000000, true, true);
|
|
m_SearchLen.SetValue(g_Rom->GetRomSize(), true, true);
|
|
break;
|
|
case IDC_BTN_SPMEM:
|
|
m_PAddrStart.SetValue(0x04000000, true, true);
|
|
m_SearchLen.SetValue(0x2000, true, true);
|
|
break;
|
|
case IDC_SEARCH_HEX:
|
|
{
|
|
bool bChecked = (SendMessage(hWndCtl, BM_GETSTATE, 0, 0) & BST_CHECKED) != 0;
|
|
m_SearchValue.SetDisplayType(bChecked ? CEditNumber::DisplayHex : CEditNumber::DisplayDec);
|
|
}
|
|
break;
|
|
case ID_POPUP_SHOWINMEMORYVIEWER:
|
|
{
|
|
LONG iItem = m_SearchResults.GetNextItem(-1, LVNI_SELECTED);
|
|
if (iItem == -1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
int ItemId = m_SearchResults.GetItemData(iItem);
|
|
SearchResultItem & Result = m_SearchResult[ItemId];
|
|
m_Debugger->Debug_ShowMemoryLocation(Result.PAddr, false);
|
|
}
|
|
break;
|
|
case IDC_RADIO_UNKNOWN:
|
|
EnableUnknownOptions(true);
|
|
EnableValueOptions(false);
|
|
EnableTextOptions(false);
|
|
EnableJalOptions(false);
|
|
break;
|
|
case IDC_RADIO_VALUE:
|
|
EnableUnknownOptions(false);
|
|
EnableValueOptions(true);
|
|
EnableTextOptions(false);
|
|
EnableJalOptions(false);
|
|
break;
|
|
case IDC_RADIO_TEXT:
|
|
EnableUnknownOptions(false);
|
|
EnableValueOptions(false);
|
|
EnableTextOptions(true);
|
|
EnableJalOptions(false);
|
|
break;
|
|
case IDC_RADIO_JAL:
|
|
EnableUnknownOptions(false);
|
|
EnableValueOptions(false);
|
|
EnableTextOptions(false);
|
|
EnableJalOptions(true);
|
|
break;
|
|
case IDC_BTN_SEARCH:
|
|
if (SendMessage(GetDlgItem(IDC_RADIO_UNKNOWN), BM_GETSTATE, 0, 0) == BST_CHECKED)
|
|
{
|
|
g_BaseSystem->ExternalEvent(SysEvent_PauseCPU_SearchMemory);
|
|
SearchForUnknown();
|
|
g_BaseSystem->ExternalEvent(SysEvent_ResumeCPU_SearchMemory);
|
|
break;
|
|
}
|
|
if (SendMessage(GetDlgItem(IDC_RADIO_VALUE), BM_GETSTATE, 0, 0) == BST_CHECKED)
|
|
{
|
|
g_BaseSystem->ExternalEvent(SysEvent_PauseCPU_SearchMemory);
|
|
SearchForValue();
|
|
g_BaseSystem->ExternalEvent(SysEvent_ResumeCPU_SearchMemory);
|
|
break;
|
|
}
|
|
if (SendMessage(GetDlgItem(IDC_RADIO_TEXT), BM_GETSTATE, 0, 0) == BST_CHECKED)
|
|
{
|
|
g_BaseSystem->ExternalEvent(SysEvent_PauseCPU_SearchMemory);
|
|
SearchForText();
|
|
g_BaseSystem->ExternalEvent(SysEvent_ResumeCPU_SearchMemory);
|
|
break;
|
|
}
|
|
case IDC_RESET_BUTTON:
|
|
Reset();
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
LRESULT CDebugMemorySearch::OnResultRClick(LPNMHDR /*lpnmh*/)
|
|
{
|
|
LONG iItem = m_SearchResults.GetNextItem(-1, LVNI_SELECTED);
|
|
if (iItem == -1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
//Load the menu
|
|
HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MEM_SEARCH));
|
|
HMENU hPopupMenu = GetSubMenu(hMenu, 0);
|
|
|
|
//Get the current Mouse location
|
|
POINT Mouse;
|
|
GetCursorPos(&Mouse);
|
|
|
|
//Show the menu
|
|
TrackPopupMenu(hPopupMenu, 0, Mouse.x, Mouse.y, 0, m_hWnd, NULL);
|
|
DestroyMenu(hMenu);
|
|
return true;
|
|
}
|
|
|
|
void CDebugMemorySearch::EnableValueOptions(bool Enable)
|
|
{
|
|
if (Enable)
|
|
{
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), m_HaveResults ? "Search Results" : "Search");
|
|
}
|
|
::EnableWindow(GetDlgItem(IDC_SEARCH_VALUE), Enable);
|
|
::EnableWindow(GetDlgItem(IDC_SEARCH_HEX), Enable);
|
|
::EnableWindow(GetDlgItem(IDC_VALUE_ALIGN), m_HaveResults ? false : Enable);
|
|
}
|
|
|
|
void CDebugMemorySearch::EnableTextOptions(bool Enable)
|
|
{
|
|
if (Enable)
|
|
{
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), m_HaveResults ? "Search Results" : "Search");
|
|
}
|
|
::EnableWindow(GetDlgItem(IDC_SEARCH_TEXT), Enable);
|
|
::EnableWindow(GetDlgItem(IDC_CASE_SENSITIVE), Enable);
|
|
}
|
|
|
|
void CDebugMemorySearch::EnableJalOptions(bool Enable)
|
|
{
|
|
if (Enable)
|
|
{
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), m_HaveResults ? "Search Results" : "Search");
|
|
}
|
|
::EnableWindow(GetDlgItem(IDC_JAL_ADDR), Enable);
|
|
}
|
|
|
|
void CDebugMemorySearch::EnableUnknownOptions(bool Enable)
|
|
{
|
|
if (m_UnknownOptions.GetCount() > 1)
|
|
{
|
|
::EnableWindow(GetDlgItem(IDC_UNKNOWN_ALIGN), m_HaveResults ? false : Enable);
|
|
if (Enable)
|
|
{
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), m_HaveResults ? "Search Results" : "Search");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
::EnableWindow(GetDlgItem(IDC_UNKNOWN_ALIGN), false);
|
|
if (Enable)
|
|
{
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), "Create");
|
|
}
|
|
}
|
|
::EnableWindow(GetDlgItem(IDC_CMB_UNKNOWN), Enable);
|
|
}
|
|
|
|
void CDebugMemorySearch::SearchForValue(void)
|
|
{
|
|
MemorySize Size = (MemorySize)m_ValueSize.GetItemData(m_ValueSize.GetCurSel());
|
|
DWORD Value = m_SearchValue.GetValue();
|
|
DWORD StartAddress = m_PAddrStart.GetValue();
|
|
DWORD Len = m_SearchLen.GetValue();
|
|
DWORD MaxSearch = m_MaxSearch.GetValue();
|
|
|
|
DWORD MoveSize = (Size == _32Bit ? 4 : (Size == _16Bit ? 2 : 1));
|
|
|
|
m_UnknownSize.SetCurSel(m_ValueSize.GetCurSel());
|
|
|
|
LPCTSTR DisplayStr = "0x%08X";
|
|
if (Size == _16Bit)
|
|
{
|
|
DisplayStr = "0x%04X";
|
|
}
|
|
else if (Size == _8Bit)
|
|
{
|
|
DisplayStr = "0x%04X";
|
|
}
|
|
|
|
if (!m_HaveResults)
|
|
{
|
|
m_HaveResults = true;
|
|
|
|
FixUnknownOptions(false);
|
|
m_SearchResults.DeleteAllItems();
|
|
DWORD ItemsAdded = 0;
|
|
|
|
while (SearchForValue(Value, Size, StartAddress, Len))
|
|
{
|
|
SearchResultItem Result;
|
|
Result.PAddr = StartAddress;
|
|
Result.Value = Value;
|
|
|
|
char LocationStr[20];
|
|
sprintf(LocationStr, "%d", ItemsAdded + 1);
|
|
int Index = m_SearchResults.AddItem(ItemsAdded, 0, LocationStr);
|
|
m_SearchResults.SetItemData(Index, m_SearchResult.size());
|
|
m_SearchResult.push_back(Result);
|
|
sprintf(LocationStr, "0x%08X", StartAddress);
|
|
m_SearchResults.SetItemText(Index, 1, LocationStr);
|
|
sprintf(LocationStr, DisplayStr, Value);
|
|
m_SearchResults.SetItemText(Index, 2, LocationStr);
|
|
sprintf(LocationStr, DisplayStr, Value);
|
|
m_SearchResults.SetItemText(Index, 3, LocationStr);
|
|
StartAddress += MoveSize;
|
|
Len -= MoveSize;
|
|
ItemsAdded += 1;
|
|
if (ItemsAdded >= MaxSearch)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), "Search Results");
|
|
::ShowWindow(GetDlgItem(IDC_RESET_BUTTON), SW_SHOW);
|
|
::EnableWindow(GetDlgItem(IDC_VALUE_ALIGN), false);
|
|
}
|
|
else
|
|
{
|
|
int ItemCount = m_SearchResults.GetItemCount();
|
|
for (int i = ItemCount - 1; i >= 0; i--)
|
|
{
|
|
int ItemId = m_SearchResults.GetItemData(i);
|
|
SearchResultItem & Result = m_SearchResult[ItemId];
|
|
|
|
DWORD NewValue = 0;
|
|
bool valid = false;
|
|
|
|
switch (Size)
|
|
{
|
|
case _8Bit:
|
|
{
|
|
BYTE mem = 0;
|
|
valid = g_MMU->LB_PAddr(Result.PAddr, mem);
|
|
NewValue = mem;
|
|
}
|
|
break;
|
|
case _16Bit:
|
|
{
|
|
WORD mem = 0;
|
|
valid = g_MMU->LH_PAddr(Result.PAddr, mem);
|
|
NewValue = mem;
|
|
}
|
|
break;
|
|
case _32Bit:
|
|
valid = g_MMU->LW_PAddr(Result.PAddr, (uint32_t &)NewValue);
|
|
break;
|
|
default:
|
|
g_Notify->BreakPoint(__FILEW__, __LINE__);
|
|
}
|
|
|
|
if (Value == NewValue)
|
|
{
|
|
char LocationStr[20];
|
|
sprintf(LocationStr, DisplayStr, NewValue);
|
|
m_SearchResults.SetItemText(i, 2, LocationStr);
|
|
sprintf(LocationStr, DisplayStr, Result.Value);
|
|
m_SearchResults.SetItemText(i, 3, LocationStr);
|
|
Result.Value = NewValue;
|
|
}
|
|
else
|
|
{
|
|
m_SearchResults.DeleteItem(i);
|
|
}
|
|
}
|
|
}
|
|
::SetWindowText(GetDlgItem(IDC_BORDER_RESULTS), stdstr_f("Results (%d)", m_SearchResults.GetItemCount()).c_str());
|
|
}
|
|
|
|
void CDebugMemorySearch::SearchForUnknown()
|
|
{
|
|
SearchMemChangeState Option = (SearchMemChangeState)m_UnknownOptions.GetItemData(m_UnknownOptions.GetCurSel());
|
|
if (Option == SearchChangeState_Reset)
|
|
{
|
|
m_SearchResults.DeleteAllItems();
|
|
SearchSetBaseForChanges();
|
|
FixUnknownOptions(false);
|
|
::ShowWindow(GetDlgItem(IDC_RESET_BUTTON), SW_SHOW);
|
|
::EnableWindow(GetDlgItem(IDC_UNKNOWN_ALIGN), true);
|
|
return;
|
|
}
|
|
MemorySize Size = (MemorySize)m_UnknownSize.GetItemData(m_UnknownSize.GetCurSel());
|
|
m_ValueSize.SetCurSel(m_UnknownSize.GetCurSel());
|
|
LPCTSTR DisplayStr = "0x%08X";
|
|
if (Size == _16Bit)
|
|
{
|
|
DisplayStr = "0x%04X";
|
|
}
|
|
else if (Size == _8Bit)
|
|
{
|
|
DisplayStr = "0x%04X";
|
|
}
|
|
if (!m_HaveResults)
|
|
{
|
|
m_HaveResults = true;
|
|
|
|
::EnableWindow(GetDlgItem(IDC_UNKNOWN_ALIGN), false);
|
|
DWORD StartAddress = m_PAddrStart.GetValue();
|
|
DWORD Len = m_SearchLen.GetValue();
|
|
DWORD MaxSearch = m_MaxSearch.GetValue();
|
|
|
|
DWORD MoveSize = (Size == _32Bit ? 4 : (Size == _16Bit ? 2 : 1));
|
|
|
|
for (int i = 2; i < 10; i++)
|
|
{
|
|
if (!m_SearchResults.DeleteColumn(i))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
m_SearchResults.AddColumn("New Value", 2);
|
|
m_SearchResults.AddColumn("Old Value", 3);
|
|
m_SearchResults.SetColumnWidth(0, 50);
|
|
m_SearchResults.SetColumnWidth(1, 75);
|
|
m_SearchResults.SetColumnWidth(2, 75);
|
|
m_SearchResults.SetColumnWidth(3, 75);
|
|
|
|
m_SearchResults.DeleteAllItems();
|
|
DWORD ItemsAdded = 0, OldValue, NewValue;
|
|
|
|
while (SearchForChanges(Option, Size, StartAddress, Len, OldValue, NewValue))
|
|
{
|
|
SearchResultItem Result;
|
|
Result.PAddr = StartAddress;
|
|
Result.Value = NewValue;
|
|
|
|
//if list size > max, then break
|
|
char LocationStr[20];
|
|
sprintf(LocationStr, "%d", ItemsAdded + 1);
|
|
int Index = m_SearchResults.AddItem(ItemsAdded, 0, LocationStr);
|
|
m_SearchResults.SetItemData(Index, m_SearchResult.size());
|
|
m_SearchResult.push_back(Result);
|
|
sprintf(LocationStr, "0x%08X", StartAddress);
|
|
m_SearchResults.SetItemText(Index, 1, LocationStr);
|
|
sprintf(LocationStr, DisplayStr, NewValue);
|
|
m_SearchResults.SetItemText(Index, 2, LocationStr);
|
|
sprintf(LocationStr, DisplayStr, OldValue);
|
|
m_SearchResults.SetItemText(Index, 3, LocationStr);
|
|
StartAddress += MoveSize;
|
|
Len -= MoveSize;
|
|
ItemsAdded += 1;
|
|
if (ItemsAdded >= MaxSearch)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), "Search Results");
|
|
::ShowWindow(GetDlgItem(IDC_RESET_BUTTON), SW_SHOW);
|
|
::EnableWindow(GetDlgItem(IDC_RADIO_TEXT), false);
|
|
::EnableWindow(GetDlgItem(IDC_RADIO_JAL), false);
|
|
}
|
|
else
|
|
{
|
|
int ItemCount = m_SearchResults.GetItemCount();
|
|
for (int i = ItemCount - 1; i >= 0; i--)
|
|
{
|
|
int ItemId = m_SearchResults.GetItemData(i);
|
|
SearchResultItem & Result = m_SearchResult[ItemId];
|
|
|
|
bool UpdateResult = false;
|
|
DWORD NewValue = 0;
|
|
bool valid = false;
|
|
|
|
switch (Size)
|
|
{
|
|
case _8Bit:
|
|
{
|
|
BYTE mem = 0;
|
|
valid = g_MMU->LB_PAddr(Result.PAddr, mem);
|
|
NewValue = mem;
|
|
}
|
|
break;
|
|
case _16Bit:
|
|
{
|
|
WORD mem = 0;
|
|
valid = g_MMU->LH_PAddr(Result.PAddr, mem);
|
|
NewValue = mem;
|
|
}
|
|
break;
|
|
case _32Bit:
|
|
valid = g_MMU->LW_PAddr(Result.PAddr, (uint32_t &)NewValue);
|
|
break;
|
|
default:
|
|
g_Notify->BreakPoint(__FILEW__, __LINE__);
|
|
}
|
|
|
|
switch (Option)
|
|
{
|
|
case SearchChangeState_Changed:
|
|
if (Result.Value != NewValue)
|
|
{
|
|
UpdateResult = true;
|
|
}
|
|
break;
|
|
case SearchChangeState_Unchanged:
|
|
if (Result.Value == NewValue)
|
|
{
|
|
UpdateResult = true;
|
|
}
|
|
break;
|
|
case SearchChangeState_Greater:
|
|
if (NewValue > Result.Value)
|
|
{
|
|
UpdateResult = true;
|
|
}
|
|
break;
|
|
case SearchChangeState_Lessthan:
|
|
if (NewValue < Result.Value)
|
|
{
|
|
UpdateResult = true;
|
|
}
|
|
break;
|
|
default:
|
|
g_Notify->BreakPoint(__FILEW__, __LINE__);
|
|
}
|
|
|
|
if (UpdateResult)
|
|
{
|
|
char LocationStr[20];
|
|
sprintf(LocationStr, DisplayStr, NewValue);
|
|
m_SearchResults.SetItemText(i, 2, LocationStr);
|
|
sprintf(LocationStr, DisplayStr, Result.Value);
|
|
m_SearchResults.SetItemText(i, 3, LocationStr);
|
|
Result.Value = NewValue;
|
|
}
|
|
else
|
|
{
|
|
m_SearchResults.DeleteItem(i);
|
|
}
|
|
}
|
|
}
|
|
::SetWindowText(GetDlgItem(IDC_BORDER_RESULTS), stdstr_f("Results (%d)", m_SearchResults.GetItemCount()).c_str());
|
|
}
|
|
|
|
void CDebugMemorySearch::SearchForText()
|
|
{
|
|
g_Notify->BreakPoint(__FILEW__, __LINE__);
|
|
}
|
|
|
|
void CDebugMemorySearch::Reset(void)
|
|
{
|
|
m_HaveResults = false;
|
|
SendMessage(GetDlgItem(IDC_RADIO_VALUE), BM_SETCHECK, BST_CHECKED, 0);
|
|
EnableUnknownOptions(false);
|
|
EnableValueOptions(true);
|
|
EnableTextOptions(false);
|
|
EnableJalOptions(false);
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), "Search");
|
|
::SetWindowText(GetDlgItem(IDC_BORDER_RESULTS), "Results");
|
|
::ShowWindow(GetDlgItem(IDC_RESET_BUTTON), SW_HIDE);
|
|
::EnableWindow(GetDlgItem(IDC_RADIO_UNKNOWN), true);
|
|
::EnableWindow(GetDlgItem(IDC_RADIO_VALUE), true);
|
|
::EnableWindow(GetDlgItem(IDC_RADIO_TEXT), false);
|
|
::EnableWindow(GetDlgItem(IDC_RADIO_JAL), false);
|
|
for (int i = 1; i < 10; i++)
|
|
{
|
|
if (!m_SearchResults.DeleteColumn(i))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
m_SearchResults.AddColumn("Value", 2);
|
|
m_SearchResults.DeleteAllItems();
|
|
m_SearchResults.SetColumnWidth(0, 50);
|
|
m_SearchResults.SetColumnWidth(1, 75);
|
|
m_SearchResults.SetColumnWidth(2, 75);
|
|
m_SearchResults.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
|
|
FixUnknownOptions(true);
|
|
}
|
|
|
|
void CDebugMemorySearch::FixUnknownOptions(bool Reset)
|
|
{
|
|
CComboBox & cb = m_UnknownOptions;
|
|
|
|
if (!Reset && cb.GetCount() > 1)
|
|
{
|
|
return;
|
|
}
|
|
cb.ResetContent();
|
|
if (Reset)
|
|
{
|
|
cb.SetItemData(cb.AddString("Create compare base"), SearchChangeState_Reset);
|
|
cb.SetCurSel(0);
|
|
return;
|
|
}
|
|
cb.SetItemData(cb.AddString("memory changed"), SearchChangeState_Changed);
|
|
cb.SetItemData(cb.AddString("memory unchanged"), SearchChangeState_Unchanged);
|
|
cb.SetItemData(cb.AddString("Value has increased"), SearchChangeState_Greater);
|
|
cb.SetItemData(cb.AddString("Value has descreased"), SearchChangeState_Lessthan);
|
|
cb.SetCurSel(1);
|
|
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), "Search");
|
|
}
|
|
|
|
bool CDebugMemorySearch::SearchSetBaseForChanges(void)
|
|
{
|
|
if (m_MemoryState != NULL)
|
|
{
|
|
delete[] m_MemoryState;
|
|
}
|
|
m_MemoryStateSize = g_MMU->RdramSize();
|
|
m_MemoryState = new BYTE[m_MemoryStateSize];
|
|
memcpy(m_MemoryState, g_MMU->Rdram(), m_MemoryStateSize);
|
|
return true;
|
|
}
|
|
|
|
bool CDebugMemorySearch::SearchForChanges(SearchMemChangeState SearchType, MemorySize Size,
|
|
DWORD &StartAddress, DWORD &Len,
|
|
DWORD &OldValue, DWORD &NewValue)
|
|
{
|
|
if (g_MMU == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (SearchType == SearchChangeState_Reset)
|
|
{
|
|
g_Notify->BreakPoint(__FILEW__, __LINE__);
|
|
}
|
|
if (Size == _32Bit) { StartAddress = ((StartAddress + 3) & ~3); }
|
|
if (Size == _16Bit) { StartAddress = ((StartAddress + 1) & ~1); }
|
|
|
|
//search memory
|
|
if (StartAddress < g_MMU->RdramSize())
|
|
{
|
|
DWORD EndMemSearchAddr = StartAddress + Len;
|
|
if (EndMemSearchAddr > g_MMU->RdramSize())
|
|
{
|
|
EndMemSearchAddr = g_MMU->RdramSize();
|
|
}
|
|
|
|
DWORD pos;
|
|
switch (Size)
|
|
{
|
|
case _32Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos += 4)
|
|
{
|
|
OldValue = *(DWORD *)(m_MemoryState + pos);
|
|
NewValue = *(DWORD *)(g_MMU->Rdram() + pos);
|
|
if ((SearchType == SearchChangeState_Changed && NewValue != OldValue) ||
|
|
(SearchType == SearchChangeState_Unchanged && NewValue == OldValue) ||
|
|
(SearchType == SearchChangeState_Greater && NewValue > OldValue) ||
|
|
(SearchType == SearchChangeState_Lessthan && NewValue < OldValue))
|
|
{
|
|
*(DWORD *)(m_MemoryState + pos) = NewValue;
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case _16Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos += 2)
|
|
{
|
|
OldValue = *(WORD *)(m_MemoryState + (pos ^ 2));
|
|
NewValue = *(WORD *)(g_MMU->Rdram() + (pos ^ 2));
|
|
if ((SearchType == SearchChangeState_Changed && NewValue != OldValue) ||
|
|
(SearchType == SearchChangeState_Unchanged && NewValue == OldValue) ||
|
|
(SearchType == SearchChangeState_Greater && NewValue > OldValue) ||
|
|
(SearchType == SearchChangeState_Lessthan && NewValue < OldValue))
|
|
{
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case _8Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos++)
|
|
{
|
|
OldValue = *(BYTE *)(m_MemoryState + (pos ^ 3));
|
|
NewValue = *(BYTE *)(g_MMU->Rdram() + (pos ^ 3));
|
|
if ((SearchType == SearchChangeState_Changed && NewValue != OldValue) ||
|
|
(SearchType == SearchChangeState_Unchanged && NewValue == OldValue) ||
|
|
(SearchType == SearchChangeState_Greater && NewValue > OldValue) ||
|
|
(SearchType == SearchChangeState_Lessthan && NewValue < OldValue))
|
|
{
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
g_Notify->BreakPoint(__FILEW__, __LINE__);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CDebugMemorySearch::SearchForValue(DWORD Value, MemorySize Size, DWORD &StartAddress, DWORD &Len)
|
|
{
|
|
if (g_MMU == NULL || g_Rom == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (Size == _32Bit)
|
|
{
|
|
StartAddress = ((StartAddress + 3) & ~3);
|
|
}
|
|
if (Size == _16Bit)
|
|
{
|
|
StartAddress = ((StartAddress + 1) & ~1);
|
|
}
|
|
|
|
//search memory
|
|
if (StartAddress < g_MMU->RdramSize())
|
|
{
|
|
DWORD EndMemSearchAddr = StartAddress + Len;
|
|
if (EndMemSearchAddr > g_MMU->RdramSize())
|
|
{
|
|
EndMemSearchAddr = g_MMU->RdramSize();
|
|
}
|
|
|
|
DWORD pos;
|
|
BYTE * RDRAM = g_MMU->Rdram();
|
|
switch (Size)
|
|
{
|
|
case _32Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos += 4)
|
|
{
|
|
if (*(DWORD *)(RDRAM + pos) == Value)
|
|
{
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case _16Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos += 2)
|
|
{
|
|
if (*(WORD *)(RDRAM + (pos ^ 2)) == (WORD)Value)
|
|
{
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case _8Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos++)
|
|
{
|
|
if (*(BYTE *)(RDRAM + (pos ^ 3)) == (BYTE)Value)
|
|
{
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
g_Notify->BreakPoint(__FILEW__, __LINE__);
|
|
}
|
|
}
|
|
if (StartAddress >= 0x10000000)
|
|
{
|
|
DWORD EndMemSearchAddr = StartAddress + Len - 0x10000000;
|
|
if (EndMemSearchAddr > g_Rom->GetRomSize())
|
|
{
|
|
EndMemSearchAddr = g_Rom->GetRomSize();
|
|
}
|
|
StartAddress -= 0x10000000;
|
|
|
|
DWORD pos;
|
|
BYTE * ROM = g_Rom->GetRomAddress();
|
|
switch (Size)
|
|
{
|
|
case _32Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos += 4)
|
|
{
|
|
if (*(DWORD *)(ROM + pos) == Value)
|
|
{
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos + 0x10000000;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case _16Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos += 2)
|
|
{
|
|
if (*(WORD *)(ROM + (pos ^ 2)) == (WORD)Value)
|
|
{
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos + 0x10000000;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case _8Bit:
|
|
for (pos = StartAddress; pos < EndMemSearchAddr; pos++)
|
|
{
|
|
if (*(BYTE *)(ROM + (pos ^ 3)) == (BYTE)Value)
|
|
{
|
|
Len -= pos - StartAddress;
|
|
StartAddress = pos + 0x10000000;
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
g_Notify->BreakPoint(__FILEW__, __LINE__);
|
|
}
|
|
}
|
|
return false;
|
|
}
|