1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 // GBMemoryViewerDlg.cpp : implementation file
20 //
21
22 #include "stdafx.h"
23 #include "vba.h"
24 #include "FileDlg.h"
25 #include "GBMemoryViewerDlg.h"
26 #include "MemoryViewerAddressSize.h"
27 #include "Reg.h"
28 #include "WinResUtil.h"
29
30 #include "../System.h"
31 #include "../gb/gbGlobals.h"
32
33 #ifdef _DEBUG
34 #define new DEBUG_NEW
35 #undef THIS_FILE
36 static char THIS_FILE[] = __FILE__;
37 #endif
38
GBMemoryViewer()39 GBMemoryViewer::GBMemoryViewer()
40 : MemoryViewer()
41 {
42 setAddressSize(1);
43 }
44
readData(u32 address,int len,u8 * data)45 void GBMemoryViewer::readData(u32 address, int len, u8 *data)
46 {
47 u16 addr = address & 0xffff;
48 if(emulating && gbRom != NULL) {
49 for(int i = 0; i < len; i++) {
50 *data++ = gbMemoryMap[addr >> 12][addr & 0xfff];
51 addr++;
52 }
53 } else {
54 for(int i = 0; i < len; i++) {
55 *data++ = 0;
56 addr++;
57 }
58 }
59 }
60
61 #define GB_READBYTE_QUICK(addr) \
62 gbMemoryMap[(addr) >> 12][(addr) & 0xfff]
63
64 #define GB_WRITEBYTE_QUICK(addr,v) \
65 gbMemoryMap[(addr) >> 12][(addr) & 0xfff] = (v)
66
editData(u32 address,int size,int mask,u32 value)67 void GBMemoryViewer::editData(u32 address, int size, int mask, u32 value)
68 {
69 u32 oldValue;
70 u16 addr = (u16)address & 0xffff;
71 switch(size) {
72 case 8:
73 oldValue = GB_READBYTE_QUICK(addr);
74 oldValue &= mask;
75 oldValue |= (u8)value;
76 GB_WRITEBYTE_QUICK(addr, oldValue);
77 break;
78 case 16:
79 oldValue = GB_READBYTE_QUICK(addr) |
80 (GB_READBYTE_QUICK(addr + 1) << 8);
81 oldValue &= mask;
82 oldValue |= (u16)value;
83 GB_WRITEBYTE_QUICK(addr, (oldValue & 255));
84 GB_WRITEBYTE_QUICK(addr+1, (oldValue >> 8));
85 break;
86 case 32:
87 oldValue = GB_READBYTE_QUICK(addr) |
88 (GB_READBYTE_QUICK(addr + 1) << 8) |
89 (GB_READBYTE_QUICK(addr + 2) << 16) |
90 (GB_READBYTE_QUICK(addr + 3) << 24);
91 oldValue &= mask;
92 oldValue |= (u32)value;
93 GB_WRITEBYTE_QUICK(addr, (oldValue & 255));
94 GB_WRITEBYTE_QUICK(addr+1, (oldValue >> 8));
95 GB_WRITEBYTE_QUICK(addr+2, (oldValue >> 16));
96 GB_WRITEBYTE_QUICK(addr+3, (oldValue >> 24));
97 break;
98 }
99 }
100
101 /////////////////////////////////////////////////////////////////////////////
102 // GBMemoryViewerDlg dialog
103
104
GBMemoryViewerDlg(CWnd * pParent)105 GBMemoryViewerDlg::GBMemoryViewerDlg(CWnd* pParent /*=NULL*/)
106 : ResizeDlg(GBMemoryViewerDlg::IDD, pParent)
107 {
108 //{{AFX_DATA_INIT(GBMemoryViewerDlg)
109 m_size = -1;
110 //}}AFX_DATA_INIT
111 autoUpdate = false;
112 }
113
114
DoDataExchange(CDataExchange * pDX)115 void GBMemoryViewerDlg::DoDataExchange(CDataExchange* pDX)
116 {
117 CDialog::DoDataExchange(pDX);
118 //{{AFX_DATA_MAP(GBMemoryViewerDlg)
119 DDX_Control(pDX, IDC_CURRENT_ADDRESS, m_current);
120 DDX_Control(pDX, IDC_ADDRESS, m_address);
121 DDX_Control(pDX, IDC_ADDRESSES, m_addresses);
122 DDX_Radio(pDX, IDC_8_BIT, m_size);
123 //}}AFX_DATA_MAP
124 DDX_Control(pDX, IDC_VIEWER, m_viewer);
125 }
126
127
BEGIN_MESSAGE_MAP(GBMemoryViewerDlg,CDialog)128 BEGIN_MESSAGE_MAP(GBMemoryViewerDlg, CDialog)
129 //{{AFX_MSG_MAP(GBMemoryViewerDlg)
130 ON_BN_CLICKED(IDC_CLOSE, OnClose)
131 ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
132 ON_BN_CLICKED(IDC_8_BIT, On8Bit)
133 ON_BN_CLICKED(IDC_16_BIT, On16Bit)
134 ON_BN_CLICKED(IDC_32_BIT, On32Bit)
135 ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)
136 ON_BN_CLICKED(IDC_GO, OnGo)
137 ON_CBN_SELCHANGE(IDC_ADDRESSES, OnSelchangeAddresses)
138 ON_BN_CLICKED(IDC_SAVE, OnSave)
139 ON_BN_CLICKED(IDC_LOAD, OnLoad)
140 //}}AFX_MSG_MAP
141 END_MESSAGE_MAP()
142
143 /////////////////////////////////////////////////////////////////////////////
144 // GBMemoryViewerDlg message handlers
145
146 BOOL GBMemoryViewerDlg::OnInitDialog()
147 {
148 CDialog::OnInitDialog();
149
150 DIALOG_SIZER_START( sz )
151 DIALOG_SIZER_ENTRY( IDC_VIEWER, DS_SizeX | DS_SizeY )
152 DIALOG_SIZER_ENTRY( IDC_REFRESH, DS_MoveY)
153 DIALOG_SIZER_ENTRY( IDC_CLOSE, DS_MoveY)
154 DIALOG_SIZER_ENTRY( IDC_LOAD, DS_MoveY)
155 DIALOG_SIZER_ENTRY( IDC_SAVE, DS_MoveY)
156 DIALOG_SIZER_ENTRY( IDC_AUTO_UPDATE, DS_MoveY)
157 DIALOG_SIZER_ENTRY( IDC_CURRENT_ADDRESS_LABEL, DS_MoveY | DS_MoveX)
158 DIALOG_SIZER_ENTRY( IDC_CURRENT_ADDRESS, DS_MoveY | DS_MoveX)
159 DIALOG_SIZER_END()
160 SetData(sz,
161 TRUE,
162 HKEY_CURRENT_USER,
163 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\GBMemoryView",
164 NULL);
165
166 m_viewer.setDialog(this);
167 m_viewer.ShowScrollBar(SB_VERT, TRUE);
168 m_viewer.EnableScrollBar(SB_VERT, ESB_ENABLE_BOTH);
169
170 LPCTSTR s[] = {
171 "0x0000 - ROM",
172 "0x4000 - ROM",
173 "0x8000 - VRAM",
174 "0xA000 - SRAM",
175 "0xC000 - RAM",
176 "0xD000 - WRAM",
177 "0xFF00 - I/O",
178 "0xFF80 - RAM"
179 };
180
181 for(int i = 0; i < 8; i++)
182 m_addresses.AddString(s[i]);
183
184 m_addresses.SetCurSel(0);
185
186 RECT cbSize;
187 int Height;
188
189 m_addresses.GetClientRect(&cbSize);
190 Height = m_addresses.GetItemHeight(-1);
191 Height += m_addresses.GetItemHeight(0) * (9);
192
193 // Note: The use of SM_CYEDGE assumes that we're using Windows '95
194 // Now add on the height of the border of the edit box
195 Height += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges
196
197 // The height of the border of the drop-down box
198 Height += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges
199
200 // now set the size of the window
201 m_addresses.SetWindowPos(NULL,
202 0, 0,
203 cbSize.right, Height,
204 SWP_NOMOVE | SWP_NOZORDER);
205
206 m_address.LimitText(8);
207
208 m_size = regQueryDwordValue("memViewerDataSize", 0);
209 if(m_size < 0 || m_size > 2)
210 m_size = 0;
211 m_viewer.setSize(m_size);
212 UpdateData(FALSE);
213
214 m_current.SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT)));
215
216 return TRUE; // return TRUE unless you set the focus to a control
217 // EXCEPTION: OCX Property Pages should return FALSE
218 }
219
OnClose()220 void GBMemoryViewerDlg::OnClose()
221 {
222 theApp.winRemoveUpdateListener(this);
223
224 DestroyWindow();
225 }
226
OnRefresh()227 void GBMemoryViewerDlg::OnRefresh()
228 {
229 m_viewer.Invalidate();
230 }
231
update()232 void GBMemoryViewerDlg::update()
233 {
234 OnRefresh();
235 }
236
On8Bit()237 void GBMemoryViewerDlg::On8Bit()
238 {
239 m_viewer.setSize(0);
240 regSetDwordValue("memViewerDataSize", 0);
241 }
242
On16Bit()243 void GBMemoryViewerDlg::On16Bit()
244 {
245 m_viewer.setSize(1);
246 regSetDwordValue("memViewerDataSize", 1);
247 }
248
On32Bit()249 void GBMemoryViewerDlg::On32Bit()
250 {
251 m_viewer.setSize(2);
252 regSetDwordValue("memViewerDataSize", 2);
253 }
254
OnAutoUpdate()255 void GBMemoryViewerDlg::OnAutoUpdate()
256 {
257 autoUpdate = !autoUpdate;
258 if(autoUpdate) {
259 theApp.winAddUpdateListener(this);
260 } else {
261 theApp.winRemoveUpdateListener(this);
262 }
263 }
264
OnGo()265 void GBMemoryViewerDlg::OnGo()
266 {
267 CString buffer;
268
269 m_address.GetWindowText(buffer);
270
271 u32 address;
272 sscanf(buffer, "%x", &address);
273 if(m_viewer.getSize() == 1)
274 address &= ~1;
275 else if(m_viewer.getSize() == 2)
276 address &= ~3;
277 m_viewer.setAddress(address);
278 }
279
OnSelchangeAddresses()280 void GBMemoryViewerDlg::OnSelchangeAddresses()
281 {
282 int cur = m_addresses.GetCurSel();
283
284 switch(cur) {
285 case 0:
286 m_viewer.setAddress(0x0000);
287 break;
288 case 1:
289 m_viewer.setAddress(0x4000);
290 break;
291 case 2:
292 m_viewer.setAddress(0x8000);
293 break;
294 case 3:
295 m_viewer.setAddress(0xa000);
296 break;
297 case 4:
298 m_viewer.setAddress(0xc000);
299 break;
300 case 5:
301 m_viewer.setAddress(0xd000);
302 break;
303 case 6:
304 m_viewer.setAddress(0xff00);
305 break;
306 case 7:
307 m_viewer.setAddress(0xff80);
308 break;
309 }
310 }
311
setCurrentAddress(u32 address)312 void GBMemoryViewerDlg::setCurrentAddress(u32 address)
313 {
314 CString buffer;
315
316 buffer.Format("0x%08X", address);
317 m_current.SetWindowText(buffer);
318 }
319
OnSave()320 void GBMemoryViewerDlg::OnSave()
321 {
322 MemoryViewerAddressSize dlg;
323 CString buffer;
324
325 dlg.setAddress(m_viewer.getCurrentAddress());
326
327 LPCTSTR exts[] = { ".dmp" };
328
329 CString filter = theApp.winLoadFilter(IDS_FILTER_DUMP);
330 CString title = winResLoadString(IDS_SELECT_DUMP_FILE);
331
332 if(dlg.DoModal() == IDOK) {
333 FileDlg file(this,
334 buffer,
335 filter,
336 0,
337 "DMP",
338 exts,
339 "",
340 title,
341 true);
342 if(file.DoModal() == IDOK) {
343 buffer = file.GetPathName();
344 FILE *f = fopen(buffer, "wb");
345
346 if(f == NULL) {
347 systemMessage(IDS_ERROR_CREATING_FILE, buffer);
348 return;
349 }
350
351 int size = dlg.getSize();
352 u16 addr = dlg.getAddress() & 0xffff;
353
354 for(int i = 0; i < size; i++) {
355 fputc(gbMemoryMap[addr >> 12][addr & 0xfff], f);
356 addr++;
357 }
358
359 fclose(f);
360 }
361 }
362 }
363
OnLoad()364 void GBMemoryViewerDlg::OnLoad()
365 {
366 CString buffer;
367 LPCTSTR exts[] = { ".dmp" };
368 CString filter = theApp.winLoadFilter(IDS_FILTER_DUMP);
369 CString title = winResLoadString(IDS_SELECT_DUMP_FILE);
370
371 FileDlg file(this,
372 buffer,
373 filter,
374 0,
375 "DMP",
376 exts,
377 "",
378 title,
379 false);
380
381 if(file.DoModal() == IDOK) {
382 buffer = file.GetPathName();
383 FILE *f = fopen(buffer, "rb");
384 if(f == NULL) {
385 systemMessage(IDS_CANNOT_OPEN_FILE,
386 "Cannot open file %s",
387 buffer);
388 return;
389 }
390
391 MemoryViewerAddressSize dlg;
392
393 fseek(f, 0, SEEK_END);
394 int size = ftell(f);
395
396 fseek(f, 0, SEEK_SET);
397
398 dlg.setAddress(m_viewer.getCurrentAddress());
399 dlg.setSize(size);
400
401 if(dlg.DoModal() == IDOK) {
402 int size = dlg.getSize();
403 u16 addr = dlg.getAddress() & 0xffff;
404
405 for(int i = 0; i < size; i++) {
406 int c = fgetc(f);
407 if(c == -1)
408 break;
409 gbMemoryMap[addr >> 12][addr & 0xfff] = c;
410 addr++;
411 }
412 OnRefresh();
413 }
414 fclose(f);
415 }
416 }
417
PostNcDestroy()418 void GBMemoryViewerDlg::PostNcDestroy()
419 {
420 delete this;
421 }
422