Path: blob/master/Windows/Debugger/DumpMemoryWindow.cpp
3186 views
#include <algorithm>1#include <cstdio>2#include <mutex>3#include "Common/Data/Encoding/Utf8.h"4#include "Core/Core.h"5#include "Core/System.h"6#include "Core/HLE/ReplaceTables.h"7#include "Core/MemMap.h"8#include "Core/MIPS/MIPSDebugInterface.h"9#include "Windows/Debugger/DumpMemoryWindow.h"10#include "Windows/resource.h"11#include "Windows/W32Util/ShellUtil.h"1213DumpMemoryWindow* DumpMemoryWindow::bp;1415void DumpMemoryWindow::HandleBrowseClick(HWND hwnd) {16std::wstring buffer;17HWND filenameWnd = GetDlgItem(hwnd, IDC_DUMP_FILENAME);18buffer.resize(GetWindowTextLengthW(filenameWnd) + 1);19GetWindowTextW(filenameWnd, &buffer[0], (int)buffer.size());20std::string fn = ConvertWStringToUTF8(buffer);2122bool result = W32Util::BrowseForFileName(false, hwnd, L"Select filename", NULL, NULL, NULL, fn);23if (result) {24filenameChosen_ = true;25buffer = ConvertUTF8ToWString(fn);26SetWindowTextW(filenameWnd, buffer.c_str());27}28}2930INT_PTR CALLBACK DumpMemoryWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)31{32switch (iMsg)33{34case WM_INITDIALOG:35bp->changeMode(hwnd,bp->selectedMode);36return TRUE;37case WM_COMMAND:38switch (LOWORD(wParam))39{40case IDC_DUMP_USERMEMORY:41switch (HIWORD(wParam))42{43case BN_CLICKED:44bp->changeMode(hwnd,MODE_RAM);45break;46}47break;48case IDC_DUMP_VRAM:49switch (HIWORD(wParam))50{51case BN_CLICKED:52bp->changeMode(hwnd,MODE_VRAM);53break;54}55break;56case IDC_DUMP_SCRATCHPAD:57switch (HIWORD(wParam))58{59case BN_CLICKED:60bp->changeMode(hwnd,MODE_SCRATCHPAD);61break;62}63break;64case IDC_DUMP_CUSTOMRANGE:65switch (HIWORD(wParam))66{67case BN_CLICKED:68bp->changeMode(hwnd,MODE_CUSTOM);69break;70}71break;72case IDC_DUMP_BROWSEFILENAME:73switch (HIWORD(wParam))74{75case BN_CLICKED:76bp->HandleBrowseClick(hwnd);77break;78}79break;80case IDOK:81if (bp->fetchDialogData(hwnd)) {82bool priorDumpWasStepping = Core_IsStepping();83if (!priorDumpWasStepping && PSP_IsInited()) {84// If emulator isn't paused force paused state, but wait before locking.85Core_Break(BreakReason::MemoryAccess, bp->start);86Core_WaitInactive();87}8889auto memLock = Memory::Lock();90if (!PSP_IsInited())91break;9293FILE *output = _wfopen(bp->fileName_.c_str(), L"wb");94if (output == nullptr) {95char errorMessage[2048];96snprintf(errorMessage, sizeof(errorMessage), "Could not open file \"%S\".", bp->fileName_.c_str());97MessageBoxA(hwnd, errorMessage, "Error", MB_OK);98break;99}100101bool includeReplacements = SendMessage(GetDlgItem(hwnd, IDC_DUMP_INCLUDEHACKS), BM_GETCHECK, 0, 0) != 0;102if (includeReplacements) {103fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);104} else {105auto savedReplacements = SaveAndClearReplacements();106std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);107if (MIPSComp::jit) {108auto savedBlocks = MIPSComp::jit->SaveAndClearEmuHackOps();109fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);110MIPSComp::jit->RestoreSavedEmuHackOps(savedBlocks);111} else {112fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);113}114RestoreSavedReplacements(savedReplacements);115}116117fclose(output);118if (!priorDumpWasStepping) {119// If emulator wasn't paused before memory dump resume emulation automatically.120Core_Resume();121}122123MessageBoxA(hwnd, "Done.", "Information", MB_OK);124EndDialog(hwnd, true);125}126break;127case IDCANCEL:128EndDialog(hwnd,false);129break;130}131132case WM_KEYDOWN:133134break;135}136137return FALSE;138}139140static bool isInInterval(u32 start, u32 end, u32 value)141{142return start <= value && value < end;143}144145bool DumpMemoryWindow::fetchDialogData(HWND hwnd)146{147char str[256],errorMessage[256];148PostfixExpression exp;149150// parse start address151GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),str,256);152if (initExpression(cpu, str,exp) == false153|| parseExpression(cpu, exp,start) == false)154{155snprintf(errorMessage, sizeof(errorMessage), "Invalid address expression \"%s\".",str);156MessageBoxA(hwnd,errorMessage,"Error",MB_OK);157return false;158}159160// parse size161GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),str,256);162if (initExpression(cpu, str,exp) == false163|| parseExpression(cpu, exp,size) == false)164{165snprintf(errorMessage, sizeof(errorMessage), "Invalid size expression \"%s\".",str);166MessageBoxA(hwnd,errorMessage,"Error",MB_OK);167return false;168}169170if (size == 0)171{172MessageBoxA(hwnd,"Invalid size 0.","Error",MB_OK);173return false;174}175176// get filename177fileName_.resize(GetWindowTextLengthW(GetDlgItem(hwnd, IDC_DUMP_FILENAME)) + 1);178GetWindowTextW(GetDlgItem(hwnd, IDC_DUMP_FILENAME), &fileName_[0], (int)fileName_.size());179if (fileName_.size() == 0)180return false;181182// now check if data makes sense...183bool invalidSize = false;184bool invalidAddress = false;185if (isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start))186{187invalidSize = !isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start+size-1);188} else if (isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start))189{190invalidSize = !isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start+size-1);191} else if (isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start))192{193invalidSize = !isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start+size-1);194} else195{196invalidAddress = true;197}198199if (invalidAddress)200{201snprintf(errorMessage, sizeof(errorMessage), "Invalid address 0x%08X.",start);202MessageBoxA(hwnd,errorMessage,"Error",MB_OK);203return false;204} else if (invalidSize)205{206snprintf(errorMessage, sizeof(errorMessage), "Invalid end address 0x%08X.",start+size);207MessageBoxA(hwnd,errorMessage,"Error",MB_OK);208return false;209}210211return true;212}213214void DumpMemoryWindow::changeMode(HWND hwnd, Mode newMode)215{216char buffer[128];217selectedMode = newMode;218219SendMessage(GetDlgItem(hwnd,IDC_DUMP_USERMEMORY),BM_SETCHECK,selectedMode == MODE_RAM ? BST_CHECKED : BST_UNCHECKED,0);220SendMessage(GetDlgItem(hwnd,IDC_DUMP_VRAM),BM_SETCHECK,selectedMode == MODE_VRAM ? BST_CHECKED : BST_UNCHECKED,0);221SendMessage(GetDlgItem(hwnd,IDC_DUMP_SCRATCHPAD),BM_SETCHECK,selectedMode == MODE_SCRATCHPAD ? BST_CHECKED : BST_UNCHECKED,0);222SendMessage(GetDlgItem(hwnd,IDC_DUMP_CUSTOMRANGE),BM_SETCHECK,selectedMode == MODE_CUSTOM ? BST_CHECKED : BST_UNCHECKED,0);223224if (selectedMode == MODE_CUSTOM)225{226EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),TRUE);227EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),TRUE);228229if (filenameChosen_ == false)230SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),"Custom.dump");231} else {232u32 start = 0, size = 0;233const char *defaultFileName = "";234235switch (selectedMode) {236case MODE_RAM:237start = PSP_GetUserMemoryBase();238size = PSP_GetUserMemoryEnd()-start;239defaultFileName = "RAM.dump";240break;241case MODE_VRAM:242start = PSP_GetVidMemBase();243size = PSP_GetVidMemEnd()-start;244defaultFileName = "VRAM.dump";245break;246case MODE_SCRATCHPAD:247start = PSP_GetScratchpadMemoryBase();248size = PSP_GetScratchpadMemoryEnd()-start;249defaultFileName = "Scratchpad.dump";250break;251case MODE_CUSTOM:252break;253}254255snprintf(buffer, sizeof(buffer), "0x%08X", start);256SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),buffer);257EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),FALSE);258259snprintf(buffer, sizeof(buffer), "0x%08X", size);260SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),buffer);261EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),FALSE);262263if (filenameChosen_ == false)264SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),defaultFileName);265}266}267268bool DumpMemoryWindow::exec()269{270bp = this;271bool result = DialogBoxParam(GetModuleHandle(0),MAKEINTRESOURCE(IDD_DUMPMEMORY),parentHwnd,dlgFunc,(LPARAM)this) != 0;272return result;273}274275276