INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { CMemView* wnd = (CMemView*)GetWindowLongPtr(hDlg, DWLP_USER); if((wnd == NULL) && (uMsg != WM_INITDIALOG)) return 0; switch(uMsg) { case WM_INITDIALOG: { HWND cur; wnd = (CMemView*)lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG)wnd); SetWindowLongPtr(GetDlgItem(hDlg, IDC_MEMVIEWBOX), DWLP_USER, (LONG)wnd); wnd->font = CreateFont(16, 0, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, GetFontQuality(), FIXED_PITCH, "Courier New"); cur = GetDlgItem(hDlg, IDC_CPU); SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)"ARM9"); SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)"ARM7"); SendMessage(cur, CB_SETCURSEL, 0, 0); cur = GetDlgItem(hDlg, IDC_VIEWMODE); SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)"Bytes"); 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); SetWindowText(cur, "02000000"); wnd->Refresh(); } return 1; case WM_CLOSE: CloseToolWindow(wnd); return 1; case WM_COMMAND: switch(LOWORD(wParam)) { case IDCANCEL: CloseToolWindow(wnd); return 1; case IDC_CPU: if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == CBN_CLOSEUP)) { wnd->cpu = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); wnd->sel = FALSE; wnd->selAddress = 0x00000000; wnd->selPart = 0; wnd->selNewVal = 0x00000000; wnd->SetTitle((wnd->cpu == ARMCPU_ARM9) ? "ARM9 memory":"ARM7 memory"); wnd->Refresh(); } return 1; case IDC_VIEWMODE: if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == CBN_CLOSEUP)) { wnd->viewMode = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); wnd->sel = FALSE; wnd->selAddress = 0x00000000; wnd->selPart = 0; wnd->selNewVal = 0x00000000; wnd->Refresh(); } return 1; case IDC_GO: { char addrstr[9]; int len; int i; int shift; BOOL error = FALSE; u32 address = 0x00000000; len = GetWindowText(GetDlgItem(hDlg, IDC_ADDRESS), addrstr, 9); for(i = 0; i < len; i++) { char ch = addrstr[i]; if((ch >= '0') && (ch <= '9')) continue; if((ch >= 'A') && (ch <= 'F')) continue; if((ch >= 'a') && (ch <= 'f')) continue; if(ch == '\0') break; error = TRUE; break; } 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), ""); return 1; } for(i = (len-1), shift = 0; i >= 0; i--, shift += 4) { char ch = addrstr[i]; if((ch >= '0') && (ch <= '9')) address |= ((ch - '0') << shift); else if((ch >= 'A') && (ch <= 'F')) address |= ((ch - 'A' + 0xA) << shift); else if((ch >= 'a') && (ch <= 'f')) address |= ((ch - 'a' + 0xA) << shift); } wnd->address = min((u32)0xFFFFFF00, (address & 0xFFFFFFF0)); wnd->sel = FALSE; wnd->selAddress = 0x00000000; wnd->selPart = 0; wnd->selNewVal = 0x00000000; SetScrollPos(GetDlgItem(hDlg, IDC_MEMVIEWBOX), SB_VERT, ((wnd->address >> 4) & 0x000FFFFF), TRUE); wnd->Refresh(); } return 1; case IDC_TEXTDUMP: { char fileName[256] = ""; OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hDlg; ofn.lpstrFilter = "Text file (*.txt)\0*.txt\0Any file (*.*)\0*.*\0\0"; ofn.nFilterIndex = 1; ofn.lpstrFile = fileName; ofn.nMaxFile = 256; ofn.lpstrDefExt = "txt"; ofn.Flags = OFN_NOCHANGEDIR | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn)) { FILE *f; u8 memory[0x100]; int line; MMU_DumpMemBlock(wnd->cpu, wnd->address, 0x100, memory); f = fopen(fileName, "a"); for(line = 0; line < 16; line++) { int i; fprintf(f, "%08X\t\t", (wnd->address + (line << 4))); switch(wnd->viewMode) { case 0: { for(i = 0; i < 16; i++) { fprintf(f, "%02X ", T1ReadByte(memory, ((line << 4) + i))); } fprintf(f, "\t"); } break; case 1: { for(i = 0; i < 16; i += 2) { fprintf(f, "%04X ", T1ReadWord(memory, ((line << 4) + i))); } fprintf(f, "\t\t"); } break; case 2: { for(i = 0; i < 16; i += 4) { fprintf(f, "%08X ", T1ReadLong(memory, ((line << 4) + i))); } fprintf(f, "\t\t\t"); } break; } for(i = 0; i < 16; i++) { u8 val = T1ReadByte(memory, ((line << 4) + i)); if((val >= 32) && (val <= 127)) fprintf(f, "%c", (char)val); else fprintf(f, "."); } fprintf(f, "\n"); } fclose(f); } } return 1; case IDC_RAWDUMP: { char fileName[256] = ""; OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hDlg; ofn.lpstrFilter = "Binary file (*.bin)\0*.bin\0Any file (*.*)\0*.*\0\0"; ofn.nFilterIndex = 1; ofn.lpstrFile = fileName; ofn.nMaxFile = 256; ofn.lpstrDefExt = "bin"; ofn.Flags = OFN_NOCHANGEDIR | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn)) { FILE *f; u8 memory[0x100]; MMU_DumpMemBlock(wnd->cpu, wnd->address, 0x100, memory); f = fopen(fileName, "ab"); fwrite(memory, 0x100, 1, f); fclose(f); } } return 1; } return 0; } return 0; }
INT_PTR CALLBACK MemView_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { CMemView* wnd = (CMemView*)GetWindowLongPtr(hDlg, DWLP_USER); if((wnd == NULL) && (uMsg != WM_INITDIALOG)) return 0; switch(uMsg) { case WM_INITDIALOG: { wnd = (CMemView*)lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG)wnd); SetWindowLongPtr(GetDlgItem(hDlg, IDC_MEMVIEWBOX), DWLP_USER, (LONG)wnd); wnd->font = CreateFont(16, 0, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, GetFontQuality(), FIXED_PITCH, "Courier New"); s_memoryRegions[MEMVIEW_ARM9].hardwareAddress = arm9InitAddress; s_memoryRegions[MEMVIEW_ARM7].hardwareAddress = arm7InitAddress; if (wnd->address == 0xFFFFFFFF) wnd->address = s_memoryRegions.front().hardwareAddress; MemViewRegion& region = s_memoryRegions[wnd->region]; HWND cur = GetDlgItem(hDlg, IDC_REGION); u32 sel = 0; for(MemoryList::iterator iter = s_memoryRegions.begin(); iter != s_memoryRegions.end(); ++iter) { u32 id = SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)iter->name); if (iter->region == wnd->region) sel = id; } SendMessage(cur, CB_SETCURSEL, sel, 0); cur = GetDlgItem(hDlg, IDC_VIEWMODE); SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)"Bytes"); SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)"Halfwords"); SendMessage(cur, CB_ADDSTRING, 0, (LPARAM)"Words"); SendMessage(cur, CB_SETCURSEL, 0, 0); gAddress = GetDlgItem(hDlg, IDC_ADDRESS); SendMessage(gAddress, EM_SETLIMITTEXT, 8, 0); char addressText[9]; wsprintf(addressText, "%08X", wnd->address); 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[16] = {0}; char buf[16] = {0}; memset(&hex[0], 0, sizeof(hex)); sprintf(buf, "addr%03d", i); u16 len = GetPrivateProfileString("Tools.MemoryViewer", buf, 0, &hex[0], 9, IniName); if (!len) break; ComboBox_AddString(gAddress, 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->address & 0x0000000F); 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[16] = {0}; char buf[16] = {0}; memset(&hex[0], 0, sizeof(hex)); sprintf(buf, "addr%03d", i); ComboBox_GetLBText(gAddress, i, (LPCTSTR)&hex[0]); WritePrivateProfileString("Tools.MemoryViewer", buf, hex, IniName); } } return 1; case WM_CLOSE: CloseToolWindow(wnd); return 1; case WM_COMMAND: switch(LOWORD(wParam)) { case IDCANCEL: CloseToolWindow(wnd); return 1; case IDC_REGION: if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == CBN_CLOSEUP)) { wnd->region = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); MemViewRegion& region = s_memoryRegions[wnd->region]; wnd->address = region.hardwareAddress; SetScrollRange(GetDlgItem(hDlg, IDC_MEMVIEWBOX), SB_VERT, 0x00000000, (region.size - 1) >> 4, TRUE); SetScrollPos(GetDlgItem(hDlg, IDC_MEMVIEWBOX), SB_VERT, 0x00000000, TRUE); wnd->sel = TRUE; wnd->selAddress = wnd->address; wnd->selPart = 0; wnd->selNewVal = 0x00000000; wnd->SetTitle(region.longname); wnd->SetFocus(); wnd->Refresh(); } return 1; case IDC_VIEWMODE: if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == CBN_CLOSEUP)) { wnd->viewMode = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); wnd->sel = TRUE; //wnd->selAddress = 0x00000000; wnd->selPart = 0; wnd->selNewVal = 0x00000000; wnd->SetFocus(); wnd->Refresh(); } return 1; case IDC_GO: { char addrstr[9]; int len; int i; int shift; BOOL error = FALSE; u32 address = 0x00000000; len = GetWindowText(gAddress, addrstr, 9); for(i = 0; i < len; i++) { char ch = addrstr[i]; if((ch >= '0') && (ch <= '9')) continue; if((ch >= 'A') && (ch <= 'F')) continue; if((ch >= 'a') && (ch <= 'f')) continue; if(ch == '\0') break; error = TRUE; break; } if(error) { MessageBox(hDlg, "Error:\nInvalid address specified.\nThe address must be an hexadecimal value.", "DeSmuME", (MB_OK | MB_ICONERROR)); SetWindowText(gAddress, ""); return 1; } for(i = (len-1), shift = 0; i >= 0; i--, shift += 4) { char ch = addrstr[i]; if((ch >= '0') && (ch <= '9')) address |= ((ch - '0') << shift); else if((ch >= 'A') && (ch <= 'F')) address |= ((ch - 'A' + 0xA) << shift); else if((ch >= 'a') && (ch <= 'f')) address |= ((ch - 'a' + 0xA) << shift); } MemViewRegion& region = s_memoryRegions[wnd->region]; if (wnd->region == MEMVIEW_ARM9 || wnd->region == MEMVIEW_ARM7) { region.hardwareAddress = address & 0xFF000000; } HWAddressType addrMin = (region.hardwareAddress) & 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 = TRUE; wnd->selAddress = wnd->address + (address & 0x0000000F); wnd->selPart = 0; wnd->selNewVal = 0x00000000; // ====================== add address in list if (ComboBox_GetCount(gAddress) == MAX_ADDRESS_SAVE) ComboBox_DeleteString(gAddress, ComboBox_GetCount(gAddress) - 1); // remove duplicate address u16 num = ComboBox_GetCount(gAddress); for (u16 i = 0; i < num; i++) { char hex[16] = {0}; ComboBox_GetLBText(gAddress, i, (LPCTSTR)&hex[0]); if (strcmp(addrstr, hex) == 0) ComboBox_DeleteString(gAddress, i); } // add to list ComboBox_InsertString(gAddress, 0, addrstr); ComboBox_SetText(gAddress, addrstr); SetScrollPos(GetDlgItem(hDlg, IDC_MEMVIEWBOX), SB_VERT, (((wnd->address - region.hardwareAddress) >> 4) & 0x000FFFFF), TRUE); wnd->Refresh(); wnd->SetFocus(); } return 1; case IDC_TEXTDUMP: { char fileName[256] = ""; OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hDlg; ofn.lpstrFilter = "Text file (*.txt)\0*.txt\0Any file (*.*)\0*.*\0\0"; ofn.nFilterIndex = 1; ofn.lpstrFile = fileName; ofn.nMaxFile = 256; ofn.lpstrDefExt = "txt"; ofn.Flags = OFN_NOCHANGEDIR | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn)) { FILE *f; u8 memory[0x100]; int line; memRead(memory, (MemRegionType)wnd->region, wnd->address, 0x100); f = fopen(fileName, "a"); for(line = 0; line < 16; line++) { int i; fprintf(f, "%08X\t\t", (wnd->address + (line << 4))); switch(wnd->viewMode) { case 0: { for(i = 0; i < 16; i++) { fprintf(f, "%02X ", T1ReadByte(memory, ((line << 4) + i))); } fprintf(f, "\t"); } break; case 1: { for(i = 0; i < 16; i += 2) { fprintf(f, "%04X ", T1ReadWord(memory, ((line << 4) + i))); } fprintf(f, "\t\t"); } break; case 2: { for(i = 0; i < 16; i += 4) { fprintf(f, "%08X ", T1ReadLong(memory, ((line << 4) + i))); } fprintf(f, "\t\t\t"); } break; } for(i = 0; i < 16; i++) { u8 val = T1ReadByte(memory, ((line << 4) + i)); if((val >= 32) && (val <= 127)) fprintf(f, "%c", (char)val); else fprintf(f, "."); } fprintf(f, "\n"); } fclose(f); } } return 1; case IDC_DUMPALL: case IDC_RAWDUMP: { char fileName[256] = ""; OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hDlg; ofn.lpstrFilter = "Binary file (*.bin)\0*.bin\0Any file (*.*)\0*.*\0\0"; ofn.nFilterIndex = 1; ofn.lpstrFile = fileName; ofn.nMaxFile = 256; ofn.lpstrDefExt = "bin"; ofn.Flags = OFN_NOCHANGEDIR | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn)) { if(LOWORD(wParam) == IDC_RAWDUMP) { EMUFILE_FILE f(fileName,"ab"); u8 memory[0x100]; memRead(memory, (MemRegionType)wnd->region, wnd->address, 0x100); f.fwrite(memory, 0x100); } else { EMUFILE_FILE f(fileName,"wb"); switch(wnd->region) { case MEMVIEW_ARM9: case MEMVIEW_ARM7: DEBUG_dumpMemory(&f); break; default: { const size_t blocksize = 0x100; byte* memory = new byte[blocksize]; if (memory != NULL) { MemViewRegion& region = s_memoryRegions[wnd->region]; for (HWAddressType address = region.hardwareAddress; address < region.hardwareAddress + region.size; address += blocksize) { size_t size = blocksize; if (address + size > region.hardwareAddress + region.size) { size = region.size - (address - region.hardwareAddress); } memRead(memory, (MemRegionType)wnd->region, address, size); f.fwrite(memory, size); } delete [] memory; } } break; } } } } return 1; case IDC_BIG_ENDIAN: wnd->Refresh(); wnd->SetFocus(); return 1; case IDC_FULL_CHARS: wnd->Refresh(); wnd->SetFocus(); return 1; } return 0; }
LRESULT CALLBACK MemView_ViewBoxProc(HWND hCtl, UINT uMsg, WPARAM wParam, LPARAM lParam) { CMemView* wnd = (CMemView*)GetWindowLongPtr(hCtl, DWLP_USER); switch(uMsg) { case WM_NCCREATE: SetScrollRange(hCtl, SB_VERT, 0x00000000, 0x000FFFF0, TRUE); SetScrollPos(hCtl, SB_VERT, 0x00000000, TRUE); return 1; case WM_NCDESTROY: return 1; case WM_ERASEBKGND: return 1; case WM_PAINT: MemView_ViewBoxPaint(wnd, hCtl, wParam, lParam); return 1; case WM_LBUTTONDOWN: { HDC hdc; HFONT font; SIZE fontsize; int x, y; wnd->sel = FALSE; wnd->selAddress = 0x00000000; wnd->selPart = 0; wnd->selNewVal = 0x00000000; hdc = GetDC(hCtl); font = (HFONT)SelectObject(hdc, wnd->font); GetTextExtentPoint32(hdc, " ", 1, &fontsize); x = LOWORD(lParam); y = HIWORD(lParam); if((x >= ((fontsize.cx * 8) + 5)) && (y >= (fontsize.cy + 3))) { int line, col; x -= ((fontsize.cx * 8) + 5); y -= (fontsize.cy + 3); line = (y / fontsize.cy); switch(wnd->viewMode) { case 0: { if((x < (fontsize.cx * 2)) || (x >= (fontsize.cx * (2 + ((2+1) * 16))))) break; col = ((x - (fontsize.cx * 2)) / (fontsize.cx * (2+1))); wnd->sel = TRUE; } break; case 1: { if((x < (fontsize.cx * 6)) || (x >= (fontsize.cx * (6 + ((4+1) * 8))))) break; col = ((x - (fontsize.cx * 6)) / (fontsize.cx * (4+1)) * 2); wnd->sel = TRUE; } break; case 2: { if((x < (fontsize.cx * 8)) || (x >= (fontsize.cx * (8 + ((8+1) * 4))))) break; col = ((x - (fontsize.cx * 8)) / (fontsize.cx * (8+1)) * 4); wnd->sel = TRUE; } break; } wnd->selAddress = (wnd->address + (line << 4) + col); wnd->selPart = 0; wnd->selNewVal = 0x00000000; } SelectObject(hdc, font); ReleaseDC(hCtl, hdc); SetFocus(hCtl); /* Required to receive keyboard messages */ wnd->Refresh(); } return 1; case WM_CHAR: { char ch = (char)wParam; if(((ch >= '0') && (ch <= '9')) || ((ch >= 'A') && (ch <= 'F')) || ((ch >= 'a') && (ch <= 'f'))) { u8 maxSelPart[3] = {2, 4, 8}; wnd->selNewVal <<= 4; wnd->selPart++; if((ch >= '0') && (ch <= '9')) wnd->selNewVal |= (ch - '0'); else if((ch >= 'A') && (ch <= 'F')) wnd->selNewVal |= (ch - 'A' + 0xA); else if((ch >= 'a') && (ch <= 'f')) wnd->selNewVal |= (ch - 'a' + 0xA); if(wnd->selPart >= maxSelPart[wnd->viewMode]) { switch(wnd->viewMode) { case 0: MMU_write8(wnd->cpu, wnd->selAddress, (u8)wnd->selNewVal); wnd->selAddress++; break; case 1: MMU_write16(wnd->cpu, wnd->selAddress, (u16)wnd->selNewVal); wnd->selAddress += 2; break; case 2: MMU_write32(wnd->cpu, wnd->selAddress, wnd->selNewVal); wnd->selAddress += 4; break; } wnd->selPart = 0; wnd->selNewVal = 0x00000000; if(wnd->selAddress == 0x00000000) { wnd->sel = FALSE; } else if(wnd->selAddress >= (wnd->address + 0x100)) { wnd->address = min((u32)0xFFFFFF00, (wnd->address + 0x10)); SetScrollPos(hCtl, SB_VERT, ((wnd->address >> 4) & 0x000FFFFF), TRUE); } } } wnd->Refresh(); }