Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/Debugger/DumpMemoryWindow.cpp
3186 views
1
#include <algorithm>
2
#include <cstdio>
3
#include <mutex>
4
#include "Common/Data/Encoding/Utf8.h"
5
#include "Core/Core.h"
6
#include "Core/System.h"
7
#include "Core/HLE/ReplaceTables.h"
8
#include "Core/MemMap.h"
9
#include "Core/MIPS/MIPSDebugInterface.h"
10
#include "Windows/Debugger/DumpMemoryWindow.h"
11
#include "Windows/resource.h"
12
#include "Windows/W32Util/ShellUtil.h"
13
14
DumpMemoryWindow* DumpMemoryWindow::bp;
15
16
void DumpMemoryWindow::HandleBrowseClick(HWND hwnd) {
17
std::wstring buffer;
18
HWND filenameWnd = GetDlgItem(hwnd, IDC_DUMP_FILENAME);
19
buffer.resize(GetWindowTextLengthW(filenameWnd) + 1);
20
GetWindowTextW(filenameWnd, &buffer[0], (int)buffer.size());
21
std::string fn = ConvertWStringToUTF8(buffer);
22
23
bool result = W32Util::BrowseForFileName(false, hwnd, L"Select filename", NULL, NULL, NULL, fn);
24
if (result) {
25
filenameChosen_ = true;
26
buffer = ConvertUTF8ToWString(fn);
27
SetWindowTextW(filenameWnd, buffer.c_str());
28
}
29
}
30
31
INT_PTR CALLBACK DumpMemoryWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
32
{
33
switch (iMsg)
34
{
35
case WM_INITDIALOG:
36
bp->changeMode(hwnd,bp->selectedMode);
37
return TRUE;
38
case WM_COMMAND:
39
switch (LOWORD(wParam))
40
{
41
case IDC_DUMP_USERMEMORY:
42
switch (HIWORD(wParam))
43
{
44
case BN_CLICKED:
45
bp->changeMode(hwnd,MODE_RAM);
46
break;
47
}
48
break;
49
case IDC_DUMP_VRAM:
50
switch (HIWORD(wParam))
51
{
52
case BN_CLICKED:
53
bp->changeMode(hwnd,MODE_VRAM);
54
break;
55
}
56
break;
57
case IDC_DUMP_SCRATCHPAD:
58
switch (HIWORD(wParam))
59
{
60
case BN_CLICKED:
61
bp->changeMode(hwnd,MODE_SCRATCHPAD);
62
break;
63
}
64
break;
65
case IDC_DUMP_CUSTOMRANGE:
66
switch (HIWORD(wParam))
67
{
68
case BN_CLICKED:
69
bp->changeMode(hwnd,MODE_CUSTOM);
70
break;
71
}
72
break;
73
case IDC_DUMP_BROWSEFILENAME:
74
switch (HIWORD(wParam))
75
{
76
case BN_CLICKED:
77
bp->HandleBrowseClick(hwnd);
78
break;
79
}
80
break;
81
case IDOK:
82
if (bp->fetchDialogData(hwnd)) {
83
bool priorDumpWasStepping = Core_IsStepping();
84
if (!priorDumpWasStepping && PSP_IsInited()) {
85
// If emulator isn't paused force paused state, but wait before locking.
86
Core_Break(BreakReason::MemoryAccess, bp->start);
87
Core_WaitInactive();
88
}
89
90
auto memLock = Memory::Lock();
91
if (!PSP_IsInited())
92
break;
93
94
FILE *output = _wfopen(bp->fileName_.c_str(), L"wb");
95
if (output == nullptr) {
96
char errorMessage[2048];
97
snprintf(errorMessage, sizeof(errorMessage), "Could not open file \"%S\".", bp->fileName_.c_str());
98
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
99
break;
100
}
101
102
bool includeReplacements = SendMessage(GetDlgItem(hwnd, IDC_DUMP_INCLUDEHACKS), BM_GETCHECK, 0, 0) != 0;
103
if (includeReplacements) {
104
fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);
105
} else {
106
auto savedReplacements = SaveAndClearReplacements();
107
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
108
if (MIPSComp::jit) {
109
auto savedBlocks = MIPSComp::jit->SaveAndClearEmuHackOps();
110
fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);
111
MIPSComp::jit->RestoreSavedEmuHackOps(savedBlocks);
112
} else {
113
fwrite(Memory::GetPointer(bp->start), 1, bp->size, output);
114
}
115
RestoreSavedReplacements(savedReplacements);
116
}
117
118
fclose(output);
119
if (!priorDumpWasStepping) {
120
// If emulator wasn't paused before memory dump resume emulation automatically.
121
Core_Resume();
122
}
123
124
MessageBoxA(hwnd, "Done.", "Information", MB_OK);
125
EndDialog(hwnd, true);
126
}
127
break;
128
case IDCANCEL:
129
EndDialog(hwnd,false);
130
break;
131
}
132
133
case WM_KEYDOWN:
134
135
break;
136
}
137
138
return FALSE;
139
}
140
141
static bool isInInterval(u32 start, u32 end, u32 value)
142
{
143
return start <= value && value < end;
144
}
145
146
bool DumpMemoryWindow::fetchDialogData(HWND hwnd)
147
{
148
char str[256],errorMessage[256];
149
PostfixExpression exp;
150
151
// parse start address
152
GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),str,256);
153
if (initExpression(cpu, str,exp) == false
154
|| parseExpression(cpu, exp,start) == false)
155
{
156
snprintf(errorMessage, sizeof(errorMessage), "Invalid address expression \"%s\".",str);
157
MessageBoxA(hwnd,errorMessage,"Error",MB_OK);
158
return false;
159
}
160
161
// parse size
162
GetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),str,256);
163
if (initExpression(cpu, str,exp) == false
164
|| parseExpression(cpu, exp,size) == false)
165
{
166
snprintf(errorMessage, sizeof(errorMessage), "Invalid size expression \"%s\".",str);
167
MessageBoxA(hwnd,errorMessage,"Error",MB_OK);
168
return false;
169
}
170
171
if (size == 0)
172
{
173
MessageBoxA(hwnd,"Invalid size 0.","Error",MB_OK);
174
return false;
175
}
176
177
// get filename
178
fileName_.resize(GetWindowTextLengthW(GetDlgItem(hwnd, IDC_DUMP_FILENAME)) + 1);
179
GetWindowTextW(GetDlgItem(hwnd, IDC_DUMP_FILENAME), &fileName_[0], (int)fileName_.size());
180
if (fileName_.size() == 0)
181
return false;
182
183
// now check if data makes sense...
184
bool invalidSize = false;
185
bool invalidAddress = false;
186
if (isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start))
187
{
188
invalidSize = !isInInterval(PSP_GetScratchpadMemoryBase(),PSP_GetScratchpadMemoryEnd(),start+size-1);
189
} else if (isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start))
190
{
191
invalidSize = !isInInterval(PSP_GetVidMemBase(),PSP_GetVidMemEnd(),start+size-1);
192
} else if (isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start))
193
{
194
invalidSize = !isInInterval(PSP_GetKernelMemoryBase(),PSP_GetUserMemoryEnd(),start+size-1);
195
} else
196
{
197
invalidAddress = true;
198
}
199
200
if (invalidAddress)
201
{
202
snprintf(errorMessage, sizeof(errorMessage), "Invalid address 0x%08X.",start);
203
MessageBoxA(hwnd,errorMessage,"Error",MB_OK);
204
return false;
205
} else if (invalidSize)
206
{
207
snprintf(errorMessage, sizeof(errorMessage), "Invalid end address 0x%08X.",start+size);
208
MessageBoxA(hwnd,errorMessage,"Error",MB_OK);
209
return false;
210
}
211
212
return true;
213
}
214
215
void DumpMemoryWindow::changeMode(HWND hwnd, Mode newMode)
216
{
217
char buffer[128];
218
selectedMode = newMode;
219
220
SendMessage(GetDlgItem(hwnd,IDC_DUMP_USERMEMORY),BM_SETCHECK,selectedMode == MODE_RAM ? BST_CHECKED : BST_UNCHECKED,0);
221
SendMessage(GetDlgItem(hwnd,IDC_DUMP_VRAM),BM_SETCHECK,selectedMode == MODE_VRAM ? BST_CHECKED : BST_UNCHECKED,0);
222
SendMessage(GetDlgItem(hwnd,IDC_DUMP_SCRATCHPAD),BM_SETCHECK,selectedMode == MODE_SCRATCHPAD ? BST_CHECKED : BST_UNCHECKED,0);
223
SendMessage(GetDlgItem(hwnd,IDC_DUMP_CUSTOMRANGE),BM_SETCHECK,selectedMode == MODE_CUSTOM ? BST_CHECKED : BST_UNCHECKED,0);
224
225
if (selectedMode == MODE_CUSTOM)
226
{
227
EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),TRUE);
228
EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),TRUE);
229
230
if (filenameChosen_ == false)
231
SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),"Custom.dump");
232
} else {
233
u32 start = 0, size = 0;
234
const char *defaultFileName = "";
235
236
switch (selectedMode) {
237
case MODE_RAM:
238
start = PSP_GetUserMemoryBase();
239
size = PSP_GetUserMemoryEnd()-start;
240
defaultFileName = "RAM.dump";
241
break;
242
case MODE_VRAM:
243
start = PSP_GetVidMemBase();
244
size = PSP_GetVidMemEnd()-start;
245
defaultFileName = "VRAM.dump";
246
break;
247
case MODE_SCRATCHPAD:
248
start = PSP_GetScratchpadMemoryBase();
249
size = PSP_GetScratchpadMemoryEnd()-start;
250
defaultFileName = "Scratchpad.dump";
251
break;
252
case MODE_CUSTOM:
253
break;
254
}
255
256
snprintf(buffer, sizeof(buffer), "0x%08X", start);
257
SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),buffer);
258
EnableWindow(GetDlgItem(hwnd,IDC_DUMP_STARTADDRESS),FALSE);
259
260
snprintf(buffer, sizeof(buffer), "0x%08X", size);
261
SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_SIZE),buffer);
262
EnableWindow(GetDlgItem(hwnd,IDC_DUMP_SIZE),FALSE);
263
264
if (filenameChosen_ == false)
265
SetWindowTextA(GetDlgItem(hwnd,IDC_DUMP_FILENAME),defaultFileName);
266
}
267
}
268
269
bool DumpMemoryWindow::exec()
270
{
271
bp = this;
272
bool result = DialogBoxParam(GetModuleHandle(0),MAKEINTRESOURCE(IDD_DUMPMEMORY),parentHwnd,dlgFunc,(LPARAM)this) != 0;
273
return result;
274
}
275
276