- add memory viewer features (navigate using a keyboard, toggle view all ASCII chars, saving latest 20 addresses to ini-file, go to address on [ENTER] key hit..)
This commit is contained in:
mtabachenko 2013-05-28 17:58:33 +00:00
parent 0567969202
commit d7b92c0840
4 changed files with 216 additions and 23 deletions

View File

@ -132,6 +132,9 @@ public:
// Refreshes the window. Called by RefreshAllToolWindows().
void Refresh() { InvalidateRect(hWnd, NULL, FALSE); }
// SetFocus
void SetFocus() { ::SetFocus(hWnd); }
// Double-linked toolwindow list.
CToolWindow* prev;
CToolWindow* next;

View File

@ -30,12 +30,15 @@
using namespace std;
#define MAX_ADDRESS_SAVE 20
typedef u32 HWAddressType;
enum RegionType {
MEMVIEW_ARM9 = 0,
MEMVIEW_ARM7,
MEMVIEW_FIRMWARE
MEMVIEW_FIRMWARE,
MEMVIEW_FULL
};
struct MemViewRegion
@ -43,7 +46,7 @@ struct MemViewRegion
char name[16]; // name of this region (ex. ARM9, region dropdown)
char longname[16]; // name of this region (ex. ARM9 memory, window title)
HWAddressType hardwareAddress; // hardware address of the start of this region
unsigned int size; // number of bytes to the end of this region
u32 size; // number of bytes to the end of this region
};
const HWAddressType arm9InitAddress = 0x02000000;
@ -51,9 +54,13 @@ const HWAddressType arm7InitAddress = 0x02000000;
static const MemViewRegion s_arm9Region = { "ARM9", "ARM9 memory", arm9InitAddress, 0x1000000 };
static const MemViewRegion s_arm7Region = { "ARM7", "ARM7 memory", arm7InitAddress, 0x1000000 };
static const MemViewRegion s_firmwareRegion = { "Firmware", "Firmware", 0x00000000, 0x40000 };
static const MemViewRegion s_fullRegion = { "Full", "Full dump", 0x00000000, 0xFFFFFFF0 };
typedef std::vector<MemViewRegion> MemoryList;
static MemoryList s_memoryRegions;
static HWND gAddrText = NULL;
static LONG_PTR oldEditAddrProc = NULL;
static HWND gAddress = NULL;
//////////////////////////////////////////////////////////////////////////////
@ -77,6 +84,9 @@ u8 memRead8 (RegionType regionType, HWAddressType address)
case MEMVIEW_FIRMWARE:
value = MMU.fw.data[address];
return value;
case MEMVIEW_FULL:
MMU_DumpMemBlock(0, address, 1, &value);
return value;
}
return 0;
}
@ -101,6 +111,9 @@ u16 memRead16 (RegionType regionType, HWAddressType address)
case MEMVIEW_FIRMWARE:
value = *(u16*)(&MMU.fw.data[address]);
return value;
case MEMVIEW_FULL:
MMU_DumpMemBlock(0, address, 2, (u8*)&value);
return value;
}
return 0;
}
@ -125,6 +138,9 @@ u32 memRead32 (RegionType regionType, HWAddressType address)
case MEMVIEW_FIRMWARE:
value = *(u32*)(&MMU.fw.data[address]);
return value;
case MEMVIEW_FULL:
MMU_DumpMemBlock(0, address, 4, (u8*)&value);
return value;
}
return 0;
}
@ -225,6 +241,7 @@ CMemView::CMemView()
s_memoryRegions.push_back(s_arm9Region);
s_memoryRegions.push_back(s_arm7Region);
s_memoryRegions.push_back(s_firmwareRegion);
s_memoryRegions.push_back(s_fullRegion);
}
PostInitialize();
@ -239,6 +256,24 @@ CMemView::~CMemView()
}
//////////////////////////////////////////////////////////////////////////////
INT_PTR CALLBACK EditAddrProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case CB_GETDROPPEDSTATE:
return 1;
case WM_KEYDOWN:
if (wParam == VK_RETURN)
{
SendMessage(GetParent(hWnd), WM_COMMAND, IDC_GO, 0);
return 1;
}
break;
}
return CallWindowProc((WNDPROC)oldEditAddrProc, hWnd, msg, wParam, lParam);
}
INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
@ -277,13 +312,56 @@ INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)"Halfwords");
SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)"Words");
SendMessage(cur, CB_SETCURSEL, 0, 0);
cur = GetDlgItem(hDlg, IDC_ADDRESS);
SendMessage(cur, EM_SETLIMITTEXT, 8, 0);
gAddress = GetDlgItem(hDlg, IDC_ADDRESS);
SendMessage(gAddress, EM_SETLIMITTEXT, 8, 0);
char addressText[9];
wsprintf(addressText, "%08X", wnd->address);
SetWindowText(cur, addressText);
SetWindowText(gAddress, addressText);
SendMessage(gAddress, CB_LIMITTEXT, 8, 0);
oldEditAddrProc = SetWindowLongPtr(gAddress, GWLP_WNDPROC, (LONG_PTR)EditAddrProc);
for (u16 i = 0; i < MAX_ADDRESS_SAVE; i++)
{
char hex[9] = {0};
char buf[9] = {0};
sprintf(buf, "addr%03d", i);
u16 len = GetPrivateProfileString("Tools.MemoryViewer", buf, 0, &hex[0], 8, IniName);
if (!len) break;
ComboBox_InsertString(gAddress, 0, hex);
}
gAddrText = GetDlgItem(hDlg, IDC_CURRENT_ADDR);
char buf[10] = {0};
sprintf(buf, "%08Xh", wnd->address);
SetWindowText(gAddrText, buf);
CheckDlgButton(hDlg, IDC_FULL_CHARS, MF_CHECKED);
wnd->sel = TRUE;
wnd->selAddress = wnd->address;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
wnd->Refresh();
wnd->SetFocus();
}
return 1;
case WM_DESTROY:
{
u16 num = ComboBox_GetCount(gAddress);
for (u16 i = 0; i < num; i++)
{
char hex[9] = {0};
char buf[9] = {0};
sprintf(buf, "addr%03d", i);
ComboBox_GetLBText(gAddress, i, (LPCTSTR)&hex[0]);
WritePrivateProfileString("Tools.MemoryViewer", buf, hex, IniName);
}
}
return 1;
@ -294,7 +372,7 @@ INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDCANCEL:
case IDCANCEL:
CloseToolWindow(wnd);
return 1;
@ -308,13 +386,14 @@ INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
SetScrollRange(GetDlgItem(hDlg, IDC_MEMVIEWBOX), SB_VERT, 0x00000000, (region.size - 1) >> 4, TRUE);
SetScrollPos(GetDlgItem(hDlg, IDC_MEMVIEWBOX), SB_VERT, 0x00000000, TRUE);
wnd->sel = FALSE;
wnd->selAddress = 0x00000000;
wnd->sel = TRUE;
wnd->selAddress = wnd->address;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
wnd->SetTitle(region.longname);
wnd->SetFocus();
wnd->Refresh();
}
return 1;
@ -324,11 +403,12 @@ INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
{
wnd->viewMode = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
wnd->sel = FALSE;
wnd->selAddress = 0x00000000;
wnd->sel = TRUE;
//wnd->selAddress = 0x00000000;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
wnd->SetFocus();
wnd->Refresh();
}
return 1;
@ -342,7 +422,7 @@ INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
BOOL error = FALSE;
u32 address = 0x00000000;
len = GetWindowText(GetDlgItem(hDlg, IDC_ADDRESS), addrstr, 9);
len = GetWindowText(gAddress, addrstr, 9);
for(i = 0; i < len; i++)
{
@ -367,7 +447,7 @@ INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
if(error)
{
MessageBox(hDlg, "Error:\nInvalid address specified.\nThe address must be an hexadecimal value.", "DeSmuME", (MB_OK | MB_ICONERROR));
SetWindowText(GetDlgItem(hDlg, IDC_ADDRESS), "");
SetWindowText(gAddress, "");
return 1;
}
@ -389,15 +469,20 @@ INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
region.hardwareAddress = address & 0xFF000000;
}
HWAddressType addrMin = (region.hardwareAddress) & 0xFFFFFF00;
HWAddressType addrMax = max(addrMin, (region.hardwareAddress + region.size - 0x100 - 1) & 0xFFFFFF00);
HWAddressType addrMax = max((u32)addrMin, (region.hardwareAddress + region.size - 0x100 - 1) & 0xFFFFFF00);
wnd->address = max((u32)addrMin, min((u32)addrMax, (address & 0xFFFFFFF0)));
wnd->sel = FALSE;
wnd->selAddress = 0x00000000;
wnd->sel = TRUE;
wnd->selAddress = wnd->address;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
if (ComboBox_GetCount(gAddress) == MAX_ADDRESS_SAVE)
ComboBox_DeleteString(gAddress, ComboBox_GetCount(gAddress) - 1);
ComboBox_InsertString(gAddress, 0, addrstr);
SetScrollPos(GetDlgItem(hDlg, IDC_MEMVIEWBOX), SB_VERT, (((wnd->address - region.hardwareAddress) >> 4) & 0x000FFFFF), TRUE);
wnd->Refresh();
}
@ -549,6 +634,10 @@ INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
case IDC_BIG_ENDIAN:
wnd->Refresh();
return 1;
case IDC_FULL_CHARS:
wnd->Refresh();
return 1;
}
return 0;
}
@ -758,17 +847,37 @@ LRESULT MemView_ViewBoxPaint(CMemView* wnd, HWND hCtl, WPARAM wParam, LPARAM lPa
SetBkColor(mem_hdc, RGB(255, 255, 255));
SetTextColor(mem_hdc, RGB(0, 0, 0));
for(i = 0; i < 16; i++)
u8 endChar = IsDlgCheckboxChecked(wnd->hWnd, IDC_FULL_CHARS)?0xFF:0x7F;
text[1] = 0; bool change = false;
for(i = 0; i < 16; i++, curx+=fontsize.cx)
{
u8 val = T1ReadByte(memory, ((line << 4) + i));
if((val >= 32) && (val <= 127))
text[i] = (char)val;
if(wnd->sel && wnd->selAddress == (addr + i))
{
SetBkColor(mem_hdc, GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(mem_hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
change = true;
}
else
text[i] = '.';
if (change)
{
SetBkColor(mem_hdc, RGB(255, 255, 255));
SetTextColor(mem_hdc, RGB(0, 0, 0));
change = false;
}
if((val >= 0x20) && (val <= endChar))
text[0] = (char)val;
else
text[0] = '.';
TextOut(mem_hdc, curx, cury, text, 1);
}
text[16] = '\0';
TextOut(mem_hdc, curx, cury, text, strlen(text));
SetBkColor(mem_hdc, RGB(255, 255, 255));
SetTextColor(mem_hdc, RGB(0, 0, 0));
cury += fontsize.cy;
}
@ -780,6 +889,10 @@ LRESULT MemView_ViewBoxPaint(CMemView* wnd, HWND hCtl, WPARAM wParam, LPARAM lPa
EndPaint(hCtl, &ps);
char buf[10] = {0};
sprintf(buf, "%08Xh", wnd->selAddress);
SetWindowText(gAddrText, buf);
return 0;
}
@ -884,6 +997,81 @@ LRESULT CALLBACK MemView_ViewBoxProc(HWND hCtl, UINT uMsg, WPARAM wParam, LPARAM
}
return 1;
case WM_KEYDOWN:
{
s16 offset = 0, offset2 = 0;
const u8 step[] = {1, 2, 4};
MemViewRegion& region = s_memoryRegions[wnd->region];
switch (wParam)
{
case VK_LEFT: offset -= step[wnd->viewMode]; break;
case VK_RIGHT: offset += step[wnd->viewMode]; break;
case VK_UP: offset -= 16; break;
case VK_DOWN: offset += 16; break;
case VK_PRIOR: offset -= 0x100; offset2 -= 0x100; break;
case VK_NEXT: offset += 0x100; offset2 += 0x100; break;
case VK_HOME:
if (GetKeyState(VK_LCONTROL) || GetKeyState(VK_RCONTROL))
{
wnd->address = region.hardwareAddress;
wnd->selAddress = wnd->address;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
SetScrollPos(hCtl, SB_VERT, 0, TRUE);
}
else
{
wnd->selAddress = wnd->address;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
}
break;
case VK_END:
if (GetKeyState(VK_LCONTROL) || GetKeyState(VK_RCONTROL))
{
wnd->address = (region.hardwareAddress + region.size - 0x100);
wnd->selAddress = wnd->address;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
SetScrollPos(hCtl, SB_VERT, (region.size - 1) >> 4, TRUE);
}
else
{
wnd->selAddress = wnd->address + 0xFF;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
}
break;
default:
return 0;
}
s64 addr = (s64)(wnd->selAddress + offset);
s64 addr2 = (s64)(wnd->address + offset2);
if (addr < region.hardwareAddress) return 1;
if (addr2 < region.hardwareAddress) return 1;
if (addr >= (region.hardwareAddress + region.size)) return 1;
if (addr2 >= (region.hardwareAddress + region.size)) return 1;
wnd->address = (u32)addr2;
wnd->selAddress = (u32)addr;
wnd->selPart = 0;
wnd->selNewVal = 0x00000000;
if (wnd->selAddress < wnd->address)
wnd->address -= 16;
if (wnd->selAddress >= wnd->address + 0x100)
wnd->address += 16;
SetScrollPos(hCtl, SB_VERT, (wnd->address - region.hardwareAddress) >> 4, TRUE);
wnd->Refresh();
}
return 1;
case WM_CHAR:
{
char ch = (char)wParam;
@ -924,7 +1112,7 @@ LRESULT CALLBACK MemView_ViewBoxProc(HWND hCtl, UINT uMsg, WPARAM wParam, LPARAM
{
MemViewRegion& region = s_memoryRegions[wnd->region];
HWAddressType addrMin = (region.hardwareAddress) & 0xFFFFFF00;
HWAddressType addrMax = max(addrMin, (region.hardwareAddress + region.size - 0x100 - 1) & 0xFFFFFF00);
HWAddressType addrMax = max((u32)addrMin, (region.hardwareAddress + region.size - 0x100 - 1) & 0xFFFFFF00);
if (wnd->address + 0x10 <= addrMax)
{
wnd->address += 0x10;

View File

@ -434,7 +434,9 @@
#define IDC_IMP_AUTO_ADVANSCENE 1054
#define IDC_JIT_BLOCK_SIZE 1054
#define IDC_SDEVELOPER 1054
#define IDC_CURRENT_ADDR 1054
#define IDC_IMP_MANUAL 1055
#define IDC_FULL_CHARS 1055
#define IDC_LIST1 1056
#define IDC_IMP_INFO_CURRENT 1056
#define IDC_BADD_AR 1057
@ -1021,7 +1023,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 128
#define _APS_NEXT_COMMAND_VALUE 40108
#define _APS_NEXT_CONTROL_VALUE 1054
#define _APS_NEXT_CONTROL_VALUE 1056
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Binary file not shown.