CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Windows/Debugger/DumpMemoryWindow.cpp
Views: 1401
#include <algorithm>1#include <cstdio>2#include <mutex>3#include "Common/Data/Encoding/Utf8.h"4#include "Core/Core.h"5#include "Core/HLE/ReplaceTables.h"6#include "Core/MemMap.h"7#include "Core/MIPS/JitCommon/JitBlockCache.h"8#include "Windows/Debugger/DumpMemoryWindow.h"9#include "Windows/resource.h"10#include "Windows/W32Util/ShellUtil.h"1112DumpMemoryWindow* DumpMemoryWindow::bp;1314void DumpMemoryWindow::HandleBrowseClick(HWND hwnd) {15std::wstring buffer;16HWND filenameWnd = GetDlgItem(hwnd, IDC_DUMP_FILENAME);17buffer.resize(GetWindowTextLengthW(filenameWnd) + 1);18GetWindowTextW(filenameWnd, &buffer[0], (int)buffer.size());19std::string fn = ConvertWStringToUTF8(buffer);2021bool result = W32Util::BrowseForFileName(false, hwnd, L"Select filename", NULL, NULL, NULL, fn);22if (result) {23filenameChosen_ = true;24buffer = ConvertUTF8ToWString(fn);25SetWindowTextW(filenameWnd, buffer.c_str());26}27}2829INT_PTR CALLBACK DumpMemoryWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)30{31switch (iMsg)32{33case WM_INITDIALOG:34bp->changeMode(hwnd,bp->selectedMode);35return TRUE;36case WM_COMMAND:37switch (LOWORD(wParam))38{39case IDC_DUMP_USERMEMORY:40switch (HIWORD(wParam))41{42case BN_CLICKED:43bp->changeMode(hwnd,MODE_RAM);44break;45}46break;47case IDC_DUMP_VRAM:48switch (HIWORD(wParam))49{50case BN_CLICKED:51bp->changeMode(hwnd,MODE_VRAM);52break;53}54break;55case IDC_DUMP_SCRATCHPAD:56switch (HIWORD(wParam))57{58case BN_CLICKED:59bp->changeMode(hwnd,MODE_SCRATCHPAD);60break;61}62break;63case IDC_DUMP_CUSTOMRANGE:64switch (HIWORD(wParam))65{66case BN_CLICKED:67bp->changeMode(hwnd,MODE_CUSTOM);68break;69}70break;71case IDC_DUMP_BROWSEFILENAME:72switch (HIWORD(wParam))73{74case BN_CLICKED:75bp->HandleBrowseClick(hwnd);76break;77}78break;79case IDOK:80if (bp->fetchDialogData(hwnd)) {81bool priorDumpWasStepping = Core_IsStepping();82if (!priorDumpWasStepping && PSP_IsInited()) {83// If emulator isn't paused force paused state, but wait before locking.84Core_EnableStepping(true, "memory.access", bp->start);85Core_WaitInactive();86}8788auto memLock = Memory::Lock();89if (!PSP_IsInited())90break;9192FILE *output = _wfopen(bp->fileName_.c_str(), L"wb");93if (output == nullptr) {94char errorMessage[2048];95snprintf(errorMessage, sizeof(errorMessage), "Could not open file \"%S\".", bp->fileName_.c_str());96MessageBoxA(hwnd, errorMessage, "Error", MB_OK);97break;98}99100bool includeReplacements = SendMessage(GetDlgItem(hwnd, IDC_DUMP_INCLUDEHACKS), BM_GETCHECK, 0, 0) != 0;101if (includeReplacements) {102fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);103} else {104auto savedReplacements = SaveAndClearReplacements();105std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);106if (MIPSComp::jit) {107auto savedBlocks = MIPSComp::jit->SaveAndClearEmuHackOps();108fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);109MIPSComp::jit->RestoreSavedEmuHackOps(savedBlocks);110} else {111fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);112}113RestoreSavedReplacements(savedReplacements);114}115116fclose(output);117if (!priorDumpWasStepping) {118// If emulator wasn't paused before memory dump resume emulation automatically.119Core_EnableStepping(false);120}121122MessageBoxA(hwnd, "Done.", "Information", MB_OK);123EndDialog(hwnd, true);124}125break;126case IDCANCEL:127EndDialog(hwnd,false);128break;129}130131case WM_KEYDOWN:132133break;134}135136return FALSE;137}138139static bool isInInterval(u32 start, u32 end, u32 value)140{141return start <= value && value < end;142}143144bool DumpMemoryWindow::fetchDialogData(HWND hwnd)145{146char str[256],errorMessage[256];147PostfixExpression exp;148149// parse start address150GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),str,256);151if (cpu->initExpression(str,exp) == false152|| cpu->parseExpression(exp,start) == false)153{154snprintf(errorMessage, sizeof(errorMessage), "Invalid address expression \"%s\".",str);155MessageBoxA(hwnd,errorMessage,"Error",MB_OK);156return false;157}158159// parse size160GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),str,256);161if (cpu->initExpression(str,exp) == false162|| cpu->parseExpression(exp,size) == false)163{164snprintf(errorMessage, sizeof(errorMessage), "Invalid size expression \"%s\".",str);165MessageBoxA(hwnd,errorMessage,"Error",MB_OK);166return false;167}168169if (size == 0)170{171MessageBoxA(hwnd,"Invalid size 0.","Error",MB_OK);172return false;173}174175// get filename176fileName_.resize(GetWindowTextLengthW(GetDlgItem(hwnd, IDC_DUMP_FILENAME)) + 1);177GetWindowTextW(GetDlgItem(hwnd, IDC_DUMP_FILENAME), &fileName_[0], (int)fileName_.size());178if (fileName_.size() == 0)179return false;180181// now check if data makes sense...182bool invalidSize = false;183bool invalidAddress = false;184if (isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start))185{186invalidSize = !isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start+size-1);187} else if (isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start))188{189invalidSize = !isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start+size-1);190} else if (isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start))191{192invalidSize = !isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start+size-1);193} else194{195invalidAddress = true;196}197198if (invalidAddress)199{200snprintf(errorMessage, sizeof(errorMessage), "Invalid address 0x%08X.",start);201MessageBoxA(hwnd,errorMessage,"Error",MB_OK);202return false;203} else if (invalidSize)204{205snprintf(errorMessage, sizeof(errorMessage), "Invalid end address 0x%08X.",start+size);206MessageBoxA(hwnd,errorMessage,"Error",MB_OK);207return false;208}209210return true;211}212213void DumpMemoryWindow::changeMode(HWND hwnd, Mode newMode)214{215char buffer[128];216selectedMode = newMode;217218SendMessage(GetDlgItem(hwnd,IDC_DUMP_USERMEMORY),BM_SETCHECK,selectedMode == MODE_RAM ? BST_CHECKED : BST_UNCHECKED,0);219SendMessage(GetDlgItem(hwnd,IDC_DUMP_VRAM),BM_SETCHECK,selectedMode == MODE_VRAM ? BST_CHECKED : BST_UNCHECKED,0);220SendMessage(GetDlgItem(hwnd,IDC_DUMP_SCRATCHPAD),BM_SETCHECK,selectedMode == MODE_SCRATCHPAD ? BST_CHECKED : BST_UNCHECKED,0);221SendMessage(GetDlgItem(hwnd,IDC_DUMP_CUSTOMRANGE),BM_SETCHECK,selectedMode == MODE_CUSTOM ? BST_CHECKED : BST_UNCHECKED,0);222223if (selectedMode == MODE_CUSTOM)224{225EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),TRUE);226EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),TRUE);227228if (filenameChosen_ == false)229SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),"Custom.dump");230} else {231u32 start = 0, size = 0;232const char *defaultFileName = "";233234switch (selectedMode) {235case MODE_RAM:236start = PSP_GetUserMemoryBase();237size = PSP_GetUserMemoryEnd()-start;238defaultFileName = "RAM.dump";239break;240case MODE_VRAM:241start = PSP_GetVidMemBase();242size = PSP_GetVidMemEnd()-start;243defaultFileName = "VRAM.dump";244break;245case MODE_SCRATCHPAD:246start = PSP_GetScratchpadMemoryBase();247size = PSP_GetScratchpadMemoryEnd()-start;248defaultFileName = "Scratchpad.dump";249break;250}251252snprintf(buffer, sizeof(buffer), "0x%08X", start);253SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),buffer);254EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),FALSE);255256snprintf(buffer, sizeof(buffer), "0x%08X", size);257SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),buffer);258EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),FALSE);259260if (filenameChosen_ == false)261SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),defaultFileName);262}263}264265bool DumpMemoryWindow::exec()266{267bp = this;268bool result = DialogBoxParam(GetModuleHandle(0),MAKEINTRESOURCE(IDD_DUMPMEMORY),parentHwnd,dlgFunc,(LPARAM)this) != 0;269return result;270}271272273