Mercurial > vba-clojure
comparison src/win32/GBACheatsDlg.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // GBACheats.cpp : implementation file | |
2 // | |
3 | |
4 #include "stdafx.h" | |
5 #include "resource.h" | |
6 #include "GBACheatsDlg.h" | |
7 #include "Reg.h" | |
8 #include "StringTokenizer.h" | |
9 #include "WinResUtil.h" | |
10 #include "Sound.h" | |
11 #include "VBA.h" | |
12 | |
13 #include "../gba/GBACheats.h" | |
14 #include "../gba/GBAGlobals.h" | |
15 #include "../common/CheatSearch.h" | |
16 | |
17 //////////////////////////////// | |
18 | |
19 bool winGbaCheatReaddress() | |
20 { | |
21 if (cheatSearchData.count != 2) | |
22 return false; | |
23 | |
24 CheatSearchBlock *block = &cheatSearchData.blocks[0]; | |
25 block->data = workRAM; | |
26 | |
27 block = &cheatSearchData.blocks[1]; | |
28 block->data = internalRAM; | |
29 | |
30 cheatSearchData.count = 2; | |
31 return true; | |
32 } | |
33 | |
34 ///////////////////////////////////////////////////////////////////////////// | |
35 // GBACheatSearch dialog | |
36 | |
37 GBACheatSearch::GBACheatSearch(CWnd*pParent /*=NULL*/) | |
38 : CDialog(GBACheatSearch::IDD, pParent) | |
39 { | |
40 //{{AFX_DATA_INIT(GBACheatSearch) | |
41 valueType = -1; | |
42 sizeType = -1; | |
43 searchType = -1; | |
44 numberType = -1; | |
45 updateValues = FALSE; | |
46 //}}AFX_DATA_INIT | |
47 data = NULL; | |
48 } | |
49 | |
50 GBACheatSearch::~GBACheatSearch() | |
51 { | |
52 if (data) | |
53 free(data); | |
54 } | |
55 | |
56 void GBACheatSearch::DoDataExchange(CDataExchange*pDX) | |
57 { | |
58 CDialog::DoDataExchange(pDX); | |
59 //{{AFX_DATA_MAP(GBACheatSearch) | |
60 DDX_Control(pDX, IDC_VALUE, m_value); | |
61 DDX_Control(pDX, IDC_CHEAT_LIST, m_list); | |
62 DDX_Radio(pDX, IDC_OLD_VALUE, valueType); | |
63 DDX_Radio(pDX, IDC_SIZE_8, sizeType); | |
64 DDX_Radio(pDX, IDC_EQ, searchType); | |
65 DDX_Radio(pDX, IDC_SIGNED, numberType); | |
66 DDX_Check(pDX, IDC_UPDATE, updateValues); | |
67 //}}AFX_DATA_MAP | |
68 } | |
69 | |
70 BEGIN_MESSAGE_MAP(GBACheatSearch, CDialog) | |
71 //{{AFX_MSG_MAP(GBACheatSearch) | |
72 ON_BN_CLICKED(ID_OK, OnOk) | |
73 ON_BN_CLICKED(IDC_START, OnStart) | |
74 ON_BN_CLICKED(IDC_SEARCH, OnSearch) | |
75 ON_BN_CLICKED(IDC_ADD_CHEAT, OnAddCheat) | |
76 ON_BN_CLICKED(IDC_UPDATE, OnUpdate) | |
77 ON_NOTIFY(LVN_GETDISPINFO, IDC_CHEAT_LIST, OnGetdispinfoCheatList) | |
78 ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHEAT_LIST, OnItemchangedCheatList) | |
79 ON_CONTROL_RANGE(BN_CLICKED, IDC_OLD_VALUE, IDC_SPECIFIC_VALUE, OnValueType) | |
80 ON_CONTROL_RANGE(BN_CLICKED, IDC_EQ, IDC_GE, OnSearchType) | |
81 ON_CONTROL_RANGE(BN_CLICKED, IDC_SIGNED, IDC_HEXADECIMAL, OnNumberType) | |
82 ON_CONTROL_RANGE(BN_CLICKED, IDC_SIZE_8, IDC_SIZE_32, OnSizeType) | |
83 //}}AFX_MSG_MAP | |
84 ON_WM_CLOSE() | |
85 ON_BN_CLICKED(IDC_CHEATREFRESHBUTTON, OnBnClickedCheatrefreshbutton) | |
86 //ON_WM_DESTROY() | |
87 //ON_WM_NCDESTROY() | |
88 //ON_WM_SYSCOMMAND() | |
89 //ON_WM_ACTIVATE() | |
90 END_MESSAGE_MAP() | |
91 | |
92 ///////////////////////////////////////////////////////////////////////////// | |
93 // GBACheatSearch message handlers | |
94 | |
95 void GBACheatSearch::OnOk() | |
96 { | |
97 if (theApp.modelessCheatDialogIsOpen) | |
98 { | |
99 theApp.modelessCheatDialogIsOpen = false; | |
100 DestroyWindow(); | |
101 } | |
102 else | |
103 { | |
104 EndDialog(TRUE); | |
105 } | |
106 } | |
107 | |
108 void GBACheatSearch::OnClose() | |
109 { | |
110 CDialog::OnClose(); | |
111 if (theApp.modelessCheatDialogIsOpen) | |
112 { | |
113 theApp.modelessCheatDialogIsOpen = false; | |
114 DestroyWindow(); | |
115 } | |
116 else | |
117 { | |
118 EndDialog(FALSE); | |
119 } | |
120 } | |
121 | |
122 void GBACheatSearch::OnStart() | |
123 { | |
124 if (cheatSearchData.count == 0) | |
125 { | |
126 CheatSearchBlock *block = &cheatSearchData.blocks[0]; | |
127 block->data = workRAM; | |
128 block->offset = 0x2000000; | |
129 block->size = 0x40000; | |
130 block->saved = (u8 *)malloc(0x40000); | |
131 block->bits = (u8 *)malloc(0x40000>>3); | |
132 | |
133 block = &cheatSearchData.blocks[1]; | |
134 block->data = internalRAM; | |
135 block->offset = 0x3000000; | |
136 block->size = 0x8000; | |
137 block->saved = (u8 *)malloc(0x8000); | |
138 block->bits = (u8 *)malloc(0x8000>>3); | |
139 | |
140 cheatSearchData.count = 2; | |
141 } | |
142 | |
143 cheatSearchStart(&cheatSearchData); | |
144 GetDlgItem(IDC_SEARCH)->EnableWindow(TRUE); | |
145 | |
146 if (theApp.modelessCheatDialogIsOpen) | |
147 { | |
148 GetDlgItem(IDC_CHEATREFRESHBUTTON)->ShowWindow(TRUE); | |
149 GetDlgItem(IDC_CHEATREFRESHBUTTON)->EnableWindow(FALSE); | |
150 } | |
151 } | |
152 | |
153 void GBACheatSearch::OnSearch() | |
154 { | |
155 CString buffer; | |
156 | |
157 if (valueType == 0) | |
158 cheatSearch(&cheatSearchData, | |
159 searchType, | |
160 sizeType, | |
161 numberType == 0); | |
162 else | |
163 { | |
164 m_value.GetWindowText(buffer); | |
165 if (buffer.IsEmpty()) | |
166 { | |
167 systemMessage(IDS_NUMBER_CANNOT_BE_EMPTY, "Number cannot be empty"); | |
168 return; | |
169 } | |
170 int value = 0; | |
171 switch (numberType) | |
172 { | |
173 case 0: | |
174 sscanf(buffer, "%d", &value); | |
175 break; | |
176 case 1: | |
177 sscanf(buffer, "%u", &value); | |
178 break; | |
179 default: | |
180 sscanf(buffer, "%x", &value); | |
181 } | |
182 cheatSearchValue(&cheatSearchData, | |
183 searchType, | |
184 sizeType, | |
185 numberType == 0, | |
186 value); | |
187 } | |
188 | |
189 addChanges(true); | |
190 | |
191 if (updateValues) | |
192 cheatSearchUpdateValues(&cheatSearchData); | |
193 | |
194 if (theApp.modelessCheatDialogIsOpen) | |
195 GetDlgItem(IDC_CHEATREFRESHBUTTON)->EnableWindow(cheatSearchGetCount(&cheatSearchData, sizeType) == 0 ? FALSE : TRUE); | |
196 | |
197 if (0 == cheatSearchGetCount(&cheatSearchData, sizeType)) | |
198 OnStart(); | |
199 } | |
200 | |
201 void GBACheatSearch::OnAddCheat() | |
202 { | |
203 int mark = m_list.GetSelectionMark(); | |
204 | |
205 if (mark != -1) | |
206 { | |
207 LVITEM item; | |
208 memset(&item, 0, sizeof(item)); | |
209 item.mask = LVIF_PARAM; | |
210 item.iItem = mark; | |
211 if (m_list.GetItem(&item)) | |
212 { | |
213 AddCheat dlg((u32)item.lParam); | |
214 dlg.DoModal(); | |
215 } | |
216 } | |
217 } | |
218 | |
219 void GBACheatSearch::OnUpdate() | |
220 { | |
221 if (GetDlgItem(IDC_UPDATE)->SendMessage(BM_GETCHECK, | |
222 0, | |
223 0) & BST_CHECKED) | |
224 updateValues = true; | |
225 else | |
226 updateValues = false; | |
227 regSetDwordValue("cheatsUpdate", updateValues); | |
228 } | |
229 | |
230 void GBACheatSearch::OnGetdispinfoCheatList(NMHDR*pNMHDR, LRESULT*pResult) | |
231 { | |
232 LV_DISPINFO*info = (LV_DISPINFO *)pNMHDR; | |
233 if (info->item.mask & LVIF_TEXT) | |
234 { | |
235 int index = info->item.iItem; | |
236 int col = info->item.iSubItem; | |
237 | |
238 switch (col) | |
239 { | |
240 case 0: | |
241 strcpy(info->item.pszText, data[index].address); | |
242 break; | |
243 case 1: | |
244 strcpy(info->item.pszText, data[index].oldValue); | |
245 break; | |
246 case 2: | |
247 strcpy(info->item.pszText, data[index].newValue); | |
248 break; | |
249 } | |
250 } | |
251 *pResult = TRUE; | |
252 } | |
253 | |
254 void GBACheatSearch::OnItemchangedCheatList(NMHDR*pNMHDR, LRESULT*pResult) | |
255 { | |
256 GetDlgItem(IDC_ADD_CHEAT)->EnableWindow(m_list.GetSelectionMark() != -1); | |
257 *pResult = TRUE; | |
258 } | |
259 | |
260 BOOL GBACheatSearch::OnInitDialog() | |
261 { | |
262 CDialog::OnInitDialog(); | |
263 | |
264 CString temp = winResLoadString(IDS_ADDRESS); | |
265 | |
266 m_list.InsertColumn(0, temp, LVCFMT_CENTER, 125, 0); | |
267 | |
268 temp = winResLoadString(IDS_OLD_VALUE); | |
269 m_list.InsertColumn(1, temp, LVCFMT_CENTER, 125, 1); | |
270 | |
271 temp = winResLoadString(IDS_NEW_VALUE); | |
272 m_list.InsertColumn(2, temp, LVCFMT_CENTER, 125, 2); | |
273 | |
274 m_list.SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT)), | |
275 TRUE); | |
276 | |
277 m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT); | |
278 | |
279 if (!cheatSearchData.count) | |
280 { | |
281 GetDlgItem(IDC_SEARCH)->EnableWindow(FALSE); | |
282 GetDlgItem(IDC_ADD_CHEAT)->EnableWindow(FALSE); | |
283 } | |
284 | |
285 valueType = regQueryDwordValue("cheatsValueType", 0); | |
286 if (valueType < 0 || valueType > 1) | |
287 valueType = 0; | |
288 | |
289 searchType = regQueryDwordValue("cheatsSearchType", SEARCH_EQ); | |
290 if (searchType > 5 || searchType < 0) | |
291 searchType = 0; | |
292 | |
293 numberType = regQueryDwordValue("cheatsNumberType", 2); | |
294 if (numberType < 0 || numberType > 2) | |
295 numberType = 2; | |
296 | |
297 sizeType = regQueryDwordValue("cheatsSizeType", 0); | |
298 if (sizeType < 0 || sizeType > 2) | |
299 sizeType = 0; | |
300 | |
301 updateValues = regQueryDwordValue("cheatsUpdate", 0) ? | |
302 true : false; | |
303 | |
304 UpdateData(FALSE); | |
305 | |
306 if (valueType == 0) | |
307 m_value.EnableWindow(FALSE); | |
308 CenterWindow(); | |
309 | |
310 if (theApp.modelessCheatDialogIsOpen) | |
311 GetDlgItem(IDC_CHEATREFRESHBUTTON)->ShowWindow(TRUE); | |
312 | |
313 if (cheatSearchData.count) | |
314 { | |
315 addChanges(false); | |
316 if (theApp.modelessCheatDialogIsOpen) | |
317 GetDlgItem(IDC_CHEATREFRESHBUTTON)->EnableWindow(cheatSearchGetCount(&cheatSearchData, | |
318 sizeType) == 0 ? FALSE : TRUE); | |
319 } | |
320 else | |
321 { | |
322 if (theApp.modelessCheatDialogIsOpen) | |
323 GetDlgItem(IDC_CHEATREFRESHBUTTON)->EnableWindow(FALSE); | |
324 } | |
325 | |
326 return TRUE; // return TRUE unless you set the focus to a control | |
327 // EXCEPTION: OCX Property Pages should return FALSE | |
328 } | |
329 | |
330 void GBACheatSearch::addChanges(bool showMsgs) | |
331 { | |
332 int count = cheatSearchGetCount(&cheatSearchData, sizeType); | |
333 | |
334 m_list.DeleteAllItems(); | |
335 | |
336 if (count > 4000) | |
337 { | |
338 if (showMsgs) | |
339 systemMessage( | |
340 IDS_SEARCH_PRODUCED_TOO_MANY, | |
341 "Search produced %d results.\nThey have been remembered, but are too many to display.\nPlease refine it better by performing additional searches.", | |
342 count); | |
343 return; | |
344 } | |
345 | |
346 if (count == 0) | |
347 { | |
348 if (showMsgs) | |
349 systemMessage(IDS_SEARCH_PRODUCED_NO_RESULTS, "Search produced no results."); | |
350 return; | |
351 } | |
352 | |
353 m_list.SetItemCount(count); | |
354 if (data) | |
355 free(data); | |
356 | |
357 data = (WinCheatsData *)calloc(count, sizeof(WinCheatsData)); | |
358 | |
359 int inc = 1; | |
360 switch (sizeType) | |
361 { | |
362 case 1: | |
363 inc = 2; | |
364 break; | |
365 case 2: | |
366 inc = 4; | |
367 break; | |
368 } | |
369 | |
370 int index = 0; | |
371 if (numberType == 0) | |
372 { | |
373 for (int i = 0; i < cheatSearchData.count; i++) | |
374 { | |
375 CheatSearchBlock *block = &cheatSearchData.blocks[i]; | |
376 | |
377 for (int j = 0; j < block->size; j += inc) | |
378 { | |
379 if (IS_BIT_SET(block->bits, j)) | |
380 { | |
381 addChange(index++, | |
382 block->offset | j, | |
383 cheatSearchSignedRead(block->saved, | |
384 j, | |
385 sizeType), | |
386 cheatSearchSignedRead(block->data, | |
387 j, | |
388 sizeType)); | |
389 } | |
390 } | |
391 } | |
392 } | |
393 else | |
394 { | |
395 for (int i = 0; i < cheatSearchData.count; i++) | |
396 { | |
397 CheatSearchBlock *block = &cheatSearchData.blocks[i]; | |
398 | |
399 for (int j = 0; j < block->size; j += inc) | |
400 { | |
401 if (IS_BIT_SET(block->bits, j)) | |
402 { | |
403 addChange(index++, | |
404 block->offset | j, | |
405 cheatSearchRead(block->saved, | |
406 j, | |
407 sizeType), | |
408 cheatSearchRead(block->data, | |
409 j, | |
410 sizeType)); | |
411 } | |
412 } | |
413 } | |
414 } | |
415 | |
416 for (int i = 0; i < count; i++) | |
417 { | |
418 LVITEM item; | |
419 | |
420 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; | |
421 item.iItem = i; | |
422 item.iSubItem = 0; | |
423 item.lParam = data[i].addr; | |
424 item.state = 0; | |
425 item.stateMask = 0; | |
426 item.pszText = LPSTR_TEXTCALLBACK; | |
427 m_list.InsertItem(&item); | |
428 | |
429 m_list.SetItemText(i, 1, LPSTR_TEXTCALLBACK); | |
430 m_list.SetItemText(i, 2, LPSTR_TEXTCALLBACK); | |
431 } | |
432 } | |
433 | |
434 void GBACheatSearch::addChange(int index, u32 address, u32 oldValue, u32 newValue) | |
435 { | |
436 data[index].addr = address; | |
437 sprintf(data[index].address, "%08x", address); | |
438 switch (numberType) | |
439 { | |
440 case 0: | |
441 sprintf(data[index].oldValue, "%d", oldValue); | |
442 sprintf(data[index].newValue, "%d", newValue); | |
443 break; | |
444 case 1: | |
445 sprintf(data[index].oldValue, "%u", oldValue); | |
446 sprintf(data[index].newValue, "%u", newValue); | |
447 break; | |
448 case 2: | |
449 switch (sizeType) | |
450 { | |
451 case 0: | |
452 sprintf(data[index].oldValue, "%02x", oldValue); | |
453 sprintf(data[index].newValue, "%02x", newValue); | |
454 break; | |
455 case 1: | |
456 sprintf(data[index].oldValue, "%04x", oldValue); | |
457 sprintf(data[index].newValue, "%04x", newValue); | |
458 break; | |
459 case 2: | |
460 sprintf(data[index].oldValue, "%08x", oldValue); | |
461 sprintf(data[index].newValue, "%08x", newValue); | |
462 break; | |
463 } | |
464 } | |
465 } | |
466 | |
467 void GBACheatSearch::OnValueType(UINT id) | |
468 { | |
469 switch (id) | |
470 { | |
471 case IDC_OLD_VALUE: | |
472 valueType = 0; | |
473 m_value.EnableWindow(FALSE); | |
474 regSetDwordValue("cheatsValueType", 0); | |
475 break; | |
476 case IDC_SPECIFIC_VALUE: | |
477 valueType = 1; | |
478 m_value.EnableWindow(TRUE); | |
479 regSetDwordValue("cheatsValueType", 1); | |
480 break; | |
481 } | |
482 } | |
483 | |
484 void GBACheatSearch::OnSearchType(UINT id) | |
485 { | |
486 switch (id) | |
487 { | |
488 case IDC_EQ: | |
489 searchType = SEARCH_EQ; | |
490 regSetDwordValue("cheatsSearchType", 0); | |
491 break; | |
492 case IDC_NE: | |
493 searchType = SEARCH_NE; | |
494 regSetDwordValue("cheatsSearchType", 1); | |
495 break; | |
496 case IDC_LT: | |
497 searchType = SEARCH_LT; | |
498 regSetDwordValue("cheatsSearchType", 2); | |
499 break; | |
500 case IDC_LE: | |
501 searchType = SEARCH_LE; | |
502 regSetDwordValue("cheatsSearchType", 3); | |
503 break; | |
504 case IDC_GT: | |
505 searchType = SEARCH_GT; | |
506 regSetDwordValue("cheatsSearchType", 4); | |
507 break; | |
508 case IDC_GE: | |
509 searchType = SEARCH_GE; | |
510 regSetDwordValue("cheatsSearchType", 5); | |
511 break; | |
512 } | |
513 } | |
514 | |
515 void GBACheatSearch::OnNumberType(UINT id) | |
516 { | |
517 switch (id) | |
518 { | |
519 case IDC_SIGNED: | |
520 numberType = 0; | |
521 regSetDwordValue("cheatsNumberType", 0); | |
522 if (m_list.GetItemCount()) | |
523 { | |
524 addChanges(false); | |
525 } | |
526 break; | |
527 case IDC_UNSIGNED: | |
528 numberType = 1; | |
529 regSetDwordValue("cheatsNumberType", 1); | |
530 if (m_list.GetItemCount()) | |
531 { | |
532 addChanges(false); | |
533 } | |
534 break; | |
535 case IDC_HEXADECIMAL: | |
536 numberType = 2; | |
537 regSetDwordValue("cheatsNumberType", 2); | |
538 if (m_list.GetItemCount()) | |
539 { | |
540 addChanges(false); | |
541 } | |
542 break; | |
543 } | |
544 } | |
545 | |
546 void GBACheatSearch::OnSizeType(UINT id) | |
547 { | |
548 switch (id) | |
549 { | |
550 case IDC_SIZE_8: | |
551 sizeType = BITS_8; | |
552 regSetDwordValue("cheatsSizeType", 0); | |
553 if (m_list.GetItemCount()) | |
554 { | |
555 addChanges(false); | |
556 } | |
557 break; | |
558 case IDC_SIZE_16: | |
559 sizeType = BITS_16; | |
560 regSetDwordValue("cheatsSizeType", 1); | |
561 if (m_list.GetItemCount()) | |
562 { | |
563 addChanges(false); | |
564 } | |
565 break; | |
566 case IDC_SIZE_32: | |
567 sizeType = BITS_32; | |
568 regSetDwordValue("cheatsSizeType", 2); | |
569 if (m_list.GetItemCount()) | |
570 { | |
571 addChanges(false); | |
572 } | |
573 break; | |
574 } | |
575 } | |
576 | |
577 ///////////////////////////////////////////////////////////////////////////// | |
578 // AddCheat dialog | |
579 | |
580 AddCheat::AddCheat(u32 address, CWnd*pParent /*=NULL*/) | |
581 : CDialog(AddCheat::IDD, pParent) | |
582 { | |
583 //{{AFX_DATA_INIT(AddCheat) | |
584 numberType = regQueryDwordValue("cheatsNumberType", 2); | |
585 if (numberType < 0 || numberType > 2) | |
586 numberType = 2; | |
587 sizeType = regQueryDwordValue("cheatsSizeType", 0); | |
588 if (sizeType < 0 || sizeType > 2) | |
589 sizeType = 0; | |
590 //}}AFX_DATA_INIT | |
591 this->address = address; | |
592 } | |
593 | |
594 void AddCheat::DoDataExchange(CDataExchange*pDX) | |
595 { | |
596 CDialog::DoDataExchange(pDX); | |
597 //{{AFX_DATA_MAP(AddCheat) | |
598 DDX_Control(pDX, IDC_VALUE, m_value); | |
599 DDX_Control(pDX, IDC_DESC, m_desc); | |
600 DDX_Control(pDX, IDC_ADDRESS, m_address); | |
601 DDX_Radio(pDX, IDC_SIZE_8, sizeType); | |
602 DDX_Radio(pDX, IDC_SIGNED, numberType); | |
603 //}}AFX_DATA_MAP | |
604 } | |
605 | |
606 BEGIN_MESSAGE_MAP(AddCheat, CDialog) | |
607 //{{AFX_MSG_MAP(AddCheat) | |
608 ON_BN_CLICKED(ID_OK, OnOk) | |
609 ON_BN_CLICKED(ID_CANCEL, OnCancel) | |
610 ON_CONTROL_RANGE(BN_CLICKED, IDC_SIGNED, IDC_HEXADECIMAL, OnNumberType) | |
611 ON_CONTROL_RANGE(BN_CLICKED, IDC_SIZE_8, IDC_SIZE_32, OnSizeType) | |
612 //}}AFX_MSG_MAP | |
613 END_MESSAGE_MAP() | |
614 | |
615 ///////////////////////////////////////////////////////////////////////////// | |
616 // AddCheat message handlers | |
617 | |
618 void AddCheat::OnOk() | |
619 { | |
620 // add cheat | |
621 if (addCheat()) | |
622 { | |
623 EndDialog(TRUE); | |
624 } | |
625 } | |
626 | |
627 void AddCheat::OnCancel() | |
628 { | |
629 EndDialog(FALSE); | |
630 } | |
631 | |
632 BOOL AddCheat::OnInitDialog() | |
633 { | |
634 CDialog::OnInitDialog(); | |
635 | |
636 if (address != 0) | |
637 { | |
638 CString buffer; | |
639 buffer.Format("%08x", address); | |
640 m_address.SetWindowText(buffer); | |
641 m_address.EnableWindow(FALSE); | |
642 } | |
643 | |
644 UpdateData(FALSE); | |
645 | |
646 GetDlgItem(IDC_DESC)->SendMessage(EM_LIMITTEXT, | |
647 32, | |
648 0); | |
649 if (address != 0) | |
650 { | |
651 GetDlgItem(IDC_SIZE_8)->EnableWindow(FALSE); | |
652 GetDlgItem(IDC_SIZE_16)->EnableWindow(FALSE); | |
653 GetDlgItem(IDC_SIZE_32)->EnableWindow(FALSE); | |
654 GetDlgItem(IDC_HEXADECIMAL)->EnableWindow(FALSE); | |
655 GetDlgItem(IDC_UNSIGNED)->EnableWindow(FALSE); | |
656 GetDlgItem(IDC_SIGNED)->EnableWindow(FALSE); | |
657 } | |
658 | |
659 CenterWindow(); | |
660 | |
661 return TRUE; // return TRUE unless you set the focus to a control | |
662 // EXCEPTION: OCX Property Pages should return FALSE | |
663 } | |
664 | |
665 void AddCheat::OnNumberType(UINT id) | |
666 { | |
667 switch (id) | |
668 { | |
669 case IDC_SIGNED: | |
670 numberType = 0; | |
671 regSetDwordValue("cheatsNumberType", 0); | |
672 break; | |
673 case IDC_UNSIGNED: | |
674 numberType = 1; | |
675 regSetDwordValue("cheatsNumberType", 1); | |
676 break; | |
677 case IDC_HEXADECIMAL: | |
678 numberType = 2; | |
679 regSetDwordValue("cheatsNumberType", 2); | |
680 break; | |
681 } | |
682 } | |
683 | |
684 void AddCheat::OnSizeType(UINT id) | |
685 { | |
686 switch (id) | |
687 { | |
688 case IDC_SIZE_8: | |
689 sizeType = BITS_8; | |
690 regSetDwordValue("cheatsSizeType", 0); | |
691 break; | |
692 case IDC_SIZE_16: | |
693 sizeType = BITS_16; | |
694 regSetDwordValue("cheatsSizeType", 1); | |
695 break; | |
696 case IDC_SIZE_32: | |
697 sizeType = BITS_32; | |
698 regSetDwordValue("cheatsSizeType", 2); | |
699 break; | |
700 } | |
701 } | |
702 | |
703 bool AddCheat::addCheat() | |
704 { | |
705 CString buffer; | |
706 CString code; | |
707 | |
708 m_address.GetWindowText(buffer); | |
709 u32 address = 0; | |
710 sscanf(buffer, "%x", &address); | |
711 if ((address >= 0x02000000 && address < 0x02040000) || | |
712 (address >= 0x03000000 && address < 0x03008000)) | |
713 {} | |
714 else | |
715 { | |
716 systemMessage(IDS_INVALID_ADDRESS, "Invalid address: %08x", address); | |
717 return false; | |
718 } | |
719 if (sizeType != 0) | |
720 { | |
721 if (sizeType == 1 && address & 1) | |
722 { | |
723 systemMessage(IDS_MISALIGNED_HALFWORD, "Misaligned half-word address: %08x", address); | |
724 return false; | |
725 } | |
726 if (sizeType == 2 && address & 3) | |
727 { | |
728 systemMessage(IDS_MISALIGNED_WORD, "Misaligned word address: %08x", address); | |
729 return false; | |
730 } | |
731 } | |
732 u32 value; | |
733 m_value.GetWindowText(buffer); | |
734 | |
735 if (buffer.IsEmpty()) | |
736 { | |
737 systemMessage(IDS_VALUE_CANNOT_BE_EMPTY, "Value cannot be empty"); | |
738 return false; | |
739 } | |
740 | |
741 switch (numberType) | |
742 { | |
743 case 0: | |
744 sscanf(buffer, "%d", &value); | |
745 break; | |
746 case 1: | |
747 sscanf(buffer, "%u", &value); | |
748 break; | |
749 default: | |
750 sscanf(buffer, "%x", &value); | |
751 } | |
752 | |
753 m_desc.GetWindowText(buffer); | |
754 | |
755 switch (sizeType) | |
756 { | |
757 case 0: | |
758 code.Format("%08x:%02x", address, value); | |
759 break; | |
760 case 1: | |
761 code.Format("%08x:%04x", address, value); | |
762 break; | |
763 case 2: | |
764 code.Format("%08x:%08x", address, value); | |
765 break; | |
766 } | |
767 | |
768 cheatsAdd(code, buffer, address, value, -1, sizeType); | |
769 return true; | |
770 } | |
771 | |
772 ///////////////////////////////////////////////////////////////////////////// | |
773 // GBACheatList dialog | |
774 | |
775 GBACheatList::GBACheatList(CWnd*pParent /*=NULL*/) | |
776 : CDialog(GBACheatList::IDD, pParent) | |
777 { | |
778 //{{AFX_DATA_INIT(GBACheatList) | |
779 // NOTE: the ClassWizard will add member initialization here | |
780 //}}AFX_DATA_INIT | |
781 } | |
782 | |
783 void GBACheatList::DoDataExchange(CDataExchange*pDX) | |
784 { | |
785 CDialog::DoDataExchange(pDX); | |
786 //{{AFX_DATA_MAP(GBACheatList) | |
787 DDX_Control(pDX, IDC_RESTORE, m_restore); | |
788 DDX_Control(pDX, IDC_CHEAT_LIST, m_list); | |
789 //}}AFX_DATA_MAP | |
790 } | |
791 | |
792 BEGIN_MESSAGE_MAP(GBACheatList, CDialog) | |
793 //{{AFX_MSG_MAP(GBACheatList) | |
794 ON_BN_CLICKED(IDC_ADD_CHEAT, OnAddCheat) | |
795 ON_BN_CLICKED(IDC_ADD_CODE, OnAddCode) | |
796 ON_BN_CLICKED(IDC_ADD_CODEBREAKER, OnAddCodebreaker) | |
797 ON_BN_CLICKED(IDC_ADD_GAMESHARK, OnAddGameshark) | |
798 ON_BN_CLICKED(IDC_ENABLE, OnEnable) | |
799 ON_BN_CLICKED(IDC_REMOVE, OnRemove) | |
800 ON_BN_CLICKED(IDC_REMOVE_ALL, OnRemoveAll) | |
801 ON_BN_CLICKED(IDC_RESTORE, OnRestore) | |
802 ON_BN_CLICKED(ID_OK, OnOk) | |
803 ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHEAT_LIST, OnItemchangedCheatList) | |
804 //}}AFX_MSG_MAP | |
805 END_MESSAGE_MAP() | |
806 | |
807 ///////////////////////////////////////////////////////////////////////////// | |
808 // GBACheatList message handlers | |
809 | |
810 void GBACheatList::OnAddCheat() | |
811 { | |
812 AddCheat dlg(0); | |
813 dlg.DoModal(); | |
814 refresh(); | |
815 } | |
816 | |
817 void GBACheatList::OnAddCode() | |
818 { | |
819 AddCheatCode dlg; | |
820 dlg.DoModal(); | |
821 refresh(); | |
822 } | |
823 | |
824 void GBACheatList::OnAddCodebreaker() | |
825 { | |
826 AddCBACode dlg; | |
827 dlg.DoModal(); | |
828 refresh(); | |
829 } | |
830 | |
831 void GBACheatList::OnAddGameshark() | |
832 { | |
833 AddGSACode dlg; | |
834 dlg.DoModal(); | |
835 refresh(); | |
836 } | |
837 | |
838 void GBACheatList::OnEnable() | |
839 { | |
840 int mark = m_list.GetSelectionMark(); | |
841 int count = m_list.GetItemCount(); | |
842 | |
843 if (mark != -1) | |
844 { | |
845 LVITEM item; | |
846 for (int i = 0; i < count; i++) | |
847 { | |
848 memset(&item, 0, sizeof(item)); | |
849 item.mask = LVIF_PARAM|LVIF_STATE; | |
850 item.stateMask = LVIS_SELECTED; | |
851 item.iItem = i; | |
852 if (m_list.GetItem(&item)) | |
853 { | |
854 if (item.state & LVIS_SELECTED) | |
855 { | |
856 if (cheatsList[item.lParam].enabled) | |
857 cheatsDisable(item.lParam); | |
858 else | |
859 cheatsEnable(item.lParam); | |
860 } | |
861 } | |
862 } | |
863 refresh(); | |
864 } | |
865 } | |
866 | |
867 void GBACheatList::OnRemove() | |
868 { | |
869 int mark = m_list.GetSelectionMark(); | |
870 int count = m_list.GetItemCount(); | |
871 | |
872 if (mark != -1) | |
873 { | |
874 for (int i = count - 1; i >= 0; i--) | |
875 { | |
876 LVITEM item; | |
877 memset(&item, 0, sizeof(item)); | |
878 item.mask = LVIF_PARAM|LVIF_STATE; | |
879 item.iItem = i; | |
880 item.stateMask = LVIS_SELECTED; | |
881 if (m_list.GetItem(&item)) | |
882 { | |
883 if (item.state & LVIS_SELECTED) | |
884 { | |
885 cheatsDelete(item.lParam, restoreValues); | |
886 } | |
887 } | |
888 } | |
889 refresh(); | |
890 } | |
891 } | |
892 | |
893 void GBACheatList::OnRemoveAll() | |
894 { | |
895 cheatsDeleteAll(restoreValues); | |
896 refresh(); | |
897 } | |
898 | |
899 void GBACheatList::OnRestore() | |
900 { | |
901 restoreValues = !restoreValues; | |
902 regSetDwordValue("cheatsRestore", restoreValues); | |
903 } | |
904 | |
905 void GBACheatList::OnOk() | |
906 { | |
907 EndDialog(TRUE); | |
908 } | |
909 | |
910 void GBACheatList::OnItemchangedCheatList(NMHDR*pNMHDR, LRESULT*pResult) | |
911 { | |
912 if (m_list.GetSelectionMark() != -1) | |
913 { | |
914 GetDlgItem(IDC_REMOVE)->EnableWindow(TRUE); | |
915 GetDlgItem(IDC_ENABLE)->EnableWindow(TRUE); | |
916 } | |
917 else | |
918 { | |
919 GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE); | |
920 GetDlgItem(IDC_ENABLE)->EnableWindow(FALSE); | |
921 } | |
922 | |
923 if (!duringRefresh) | |
924 { | |
925 LPNMLISTVIEW l = (LPNMLISTVIEW)pNMHDR; | |
926 if (l->uChanged & LVIF_STATE) | |
927 { | |
928 if (((l->uOldState & LVIS_STATEIMAGEMASK)>>12) != | |
929 (((l->uNewState & LVIS_STATEIMAGEMASK)>>12))) | |
930 { | |
931 if (m_list.GetCheck(l->iItem)) | |
932 cheatsEnable(l->lParam); | |
933 else | |
934 cheatsDisable(l->lParam); | |
935 refresh(); | |
936 } | |
937 } | |
938 } | |
939 | |
940 *pResult = 0; | |
941 } | |
942 | |
943 BOOL GBACheatList::OnInitDialog() | |
944 { | |
945 CDialog::OnInitDialog(); | |
946 | |
947 CString temp = winResLoadString(IDS_CODE); | |
948 m_list.InsertColumn(0, temp, LVCFMT_LEFT, 170, 0); | |
949 temp = winResLoadString(IDS_DESCRIPTION); | |
950 m_list.InsertColumn(1, temp, LVCFMT_LEFT, 150, 1); | |
951 temp = winResLoadString(IDS_STATUS); | |
952 m_list.InsertColumn(2, temp, LVCFMT_LEFT, 80, 1); | |
953 | |
954 m_list.SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT)), | |
955 TRUE); | |
956 | |
957 m_list.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT); | |
958 | |
959 duringRefresh = false; | |
960 | |
961 restoreValues = regQueryDwordValue("cheatsRestore", 0) ? | |
962 true : false; | |
963 | |
964 m_restore.SetCheck(restoreValues); | |
965 | |
966 refresh(); | |
967 GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE); | |
968 GetDlgItem(IDC_ENABLE)->EnableWindow(FALSE); | |
969 CenterWindow(); | |
970 | |
971 return TRUE; // return TRUE unless you set the focus to a control | |
972 // EXCEPTION: OCX Property Pages should return FALSE | |
973 } | |
974 | |
975 void GBACheatList::refresh() | |
976 { | |
977 duringRefresh = true; | |
978 m_list.DeleteAllItems(); | |
979 | |
980 CString buffer; | |
981 | |
982 for (int i = 0; i < cheatsNumber; i++) | |
983 { | |
984 LVITEM item; | |
985 | |
986 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; | |
987 item.iItem = i; | |
988 item.iSubItem = 0; | |
989 item.lParam = i; | |
990 item.state = 0; | |
991 item.stateMask = 0; | |
992 item.pszText = cheatsList[i].codestring; | |
993 m_list.InsertItem(&item); | |
994 | |
995 m_list.SetCheck(i, (cheatsList[i].enabled) ? TRUE : FALSE); | |
996 | |
997 m_list.SetItemText(i, 1, cheatsList[i].desc); | |
998 | |
999 buffer = (cheatsList[i].enabled) ? 'E' : 'D'; | |
1000 m_list.SetItemText(i, 2, buffer); | |
1001 } | |
1002 duringRefresh = false; | |
1003 } | |
1004 | |
1005 ///////////////////////////////////////////////////////////////////////////// | |
1006 // AddGSACode dialog | |
1007 | |
1008 AddGSACode::AddGSACode(CWnd*pParent /*=NULL*/) | |
1009 : CDialog(AddGSACode::IDD, pParent) | |
1010 { | |
1011 //{{AFX_DATA_INIT(AddGSACode) | |
1012 // NOTE: the ClassWizard will add member initialization here | |
1013 //}}AFX_DATA_INIT | |
1014 } | |
1015 | |
1016 void AddGSACode::DoDataExchange(CDataExchange*pDX) | |
1017 { | |
1018 CDialog::DoDataExchange(pDX); | |
1019 //{{AFX_DATA_MAP(AddGSACode) | |
1020 DDX_Control(pDX, IDC_DESC, m_desc); | |
1021 DDX_Control(pDX, IDC_CODE, m_code); | |
1022 //}}AFX_DATA_MAP | |
1023 } | |
1024 | |
1025 BEGIN_MESSAGE_MAP(AddGSACode, CDialog) | |
1026 //{{AFX_MSG_MAP(AddGSACode) | |
1027 ON_BN_CLICKED(ID_OK, OnOk) | |
1028 ON_BN_CLICKED(ID_CANCEL, OnCancel) | |
1029 //}}AFX_MSG_MAP | |
1030 END_MESSAGE_MAP() | |
1031 | |
1032 ///////////////////////////////////////////////////////////////////////////// | |
1033 // AddGSACode message handlers | |
1034 | |
1035 void AddGSACode::OnOk() | |
1036 { | |
1037 CString desc; | |
1038 CString buffer; | |
1039 CString part1; | |
1040 CString code; | |
1041 CString token; | |
1042 | |
1043 m_code.GetWindowText(buffer); | |
1044 m_desc.GetWindowText(desc); | |
1045 | |
1046 StringTokenizer st(buffer, " \t\n\r"); | |
1047 part1.Empty(); | |
1048 const char *t = st.next(); | |
1049 while (t) | |
1050 { | |
1051 token = t; | |
1052 token.MakeUpper(); | |
1053 if (token.GetLength() == 16) | |
1054 cheatsAddGSACode(token, desc, false); | |
1055 else if (token.GetLength() == 12) | |
1056 { | |
1057 code = token.Left(8); | |
1058 code += " "; | |
1059 code += token.Right(4); | |
1060 cheatsAddCBACode(code, desc); | |
1061 } | |
1062 else if (part1.IsEmpty()) | |
1063 part1 = token; | |
1064 else | |
1065 { | |
1066 if (token.GetLength() == 4) | |
1067 { | |
1068 code = part1; | |
1069 code += " "; | |
1070 code += token; | |
1071 cheatsAddCBACode(code, desc); | |
1072 } | |
1073 else | |
1074 { | |
1075 code = part1 + token; | |
1076 cheatsAddGSACode(code, desc, true); | |
1077 } | |
1078 part1.Empty(); | |
1079 } | |
1080 | |
1081 t = st.next(); | |
1082 } | |
1083 EndDialog(TRUE); | |
1084 } | |
1085 | |
1086 void AddGSACode::OnCancel() | |
1087 { | |
1088 EndDialog(FALSE); | |
1089 } | |
1090 | |
1091 BOOL AddGSACode::OnInitDialog() | |
1092 { | |
1093 CDialog::OnInitDialog(); | |
1094 | |
1095 m_code.LimitText(1024); | |
1096 m_desc.LimitText(32); | |
1097 CString title = winResLoadString(IDS_ADD_GSA_CODE); | |
1098 SetWindowText(title); | |
1099 CenterWindow(); | |
1100 | |
1101 return TRUE; // return TRUE unless you set the focus to a control | |
1102 // EXCEPTION: OCX Property Pages should return FALSE | |
1103 } | |
1104 | |
1105 ///////////////////////////////////////////////////////////////////////////// | |
1106 // AddCBACode dialog | |
1107 | |
1108 AddCBACode::AddCBACode(CWnd*pParent /*=NULL*/) | |
1109 : CDialog(AddCBACode::IDD, pParent) | |
1110 { | |
1111 //{{AFX_DATA_INIT(AddCBACode) | |
1112 // NOTE: the ClassWizard will add member initialization here | |
1113 //}}AFX_DATA_INIT | |
1114 } | |
1115 | |
1116 void AddCBACode::DoDataExchange(CDataExchange*pDX) | |
1117 { | |
1118 CDialog::DoDataExchange(pDX); | |
1119 //{{AFX_DATA_MAP(AddCBACode) | |
1120 DDX_Control(pDX, IDC_DESC, m_desc); | |
1121 DDX_Control(pDX, IDC_CODE, m_code); | |
1122 //}}AFX_DATA_MAP | |
1123 } | |
1124 | |
1125 BEGIN_MESSAGE_MAP(AddCBACode, CDialog) | |
1126 //{{AFX_MSG_MAP(AddCBACode) | |
1127 ON_BN_CLICKED(ID_OK, OnOk) | |
1128 ON_BN_CLICKED(ID_CANCEL, OnCancel) | |
1129 //}}AFX_MSG_MAP | |
1130 END_MESSAGE_MAP() | |
1131 | |
1132 ///////////////////////////////////////////////////////////////////////////// | |
1133 // AddCBACode message handlers | |
1134 | |
1135 void AddCBACode::OnOk() | |
1136 { | |
1137 CString desc; | |
1138 CString buffer; | |
1139 CString part1; | |
1140 CString code; | |
1141 CString token; | |
1142 | |
1143 m_code.GetWindowText(buffer); | |
1144 m_desc.GetWindowText(desc); | |
1145 | |
1146 StringTokenizer st(buffer, " \t\n\r"); | |
1147 part1.Empty(); | |
1148 const char *t = st.next(); | |
1149 while (t) | |
1150 { | |
1151 token = t; | |
1152 token.MakeUpper(); | |
1153 if (token.GetLength() == 16) | |
1154 cheatsAddGSACode(token, desc, false); | |
1155 else if (token.GetLength() == 12) | |
1156 { | |
1157 code = token.Left(8); | |
1158 code += " "; | |
1159 code += token.Right(4); | |
1160 cheatsAddCBACode(code, desc); | |
1161 } | |
1162 else if (part1.IsEmpty()) | |
1163 part1 = token; | |
1164 else | |
1165 { | |
1166 if (token.GetLength() == 4) | |
1167 { | |
1168 code = part1; | |
1169 code += " "; | |
1170 code += token; | |
1171 cheatsAddCBACode(code, desc); | |
1172 } | |
1173 else | |
1174 { | |
1175 code = part1 + token; | |
1176 cheatsAddGSACode(code, desc, true); | |
1177 } | |
1178 part1.Empty(); | |
1179 } | |
1180 | |
1181 t = st.next(); | |
1182 } | |
1183 EndDialog(TRUE); | |
1184 } | |
1185 | |
1186 void AddCBACode::OnCancel() | |
1187 { | |
1188 EndDialog(FALSE); | |
1189 } | |
1190 | |
1191 BOOL AddCBACode::OnInitDialog() | |
1192 { | |
1193 CDialog::OnInitDialog(); | |
1194 | |
1195 m_code.LimitText(1024); | |
1196 m_desc.LimitText(32); | |
1197 CString title = winResLoadString(IDS_ADD_CBA_CODE); | |
1198 SetWindowText(title); | |
1199 CenterWindow(); | |
1200 | |
1201 return TRUE; // return TRUE unless you set the focus to a control | |
1202 // EXCEPTION: OCX Property Pages should return FALSE | |
1203 } | |
1204 | |
1205 ///////////////////////////////////////////////////////////////////////////// | |
1206 // AddCheatCode dialog | |
1207 | |
1208 AddCheatCode::AddCheatCode(CWnd*pParent /*=NULL*/) | |
1209 : CDialog(AddCheatCode::IDD, pParent) | |
1210 { | |
1211 //{{AFX_DATA_INIT(AddCheatCode) | |
1212 // NOTE: the ClassWizard will add member initialization here | |
1213 //}}AFX_DATA_INIT | |
1214 } | |
1215 | |
1216 void AddCheatCode::DoDataExchange(CDataExchange*pDX) | |
1217 { | |
1218 CDialog::DoDataExchange(pDX); | |
1219 //{{AFX_DATA_MAP(AddCheatCode) | |
1220 DDX_Control(pDX, IDC_DESC, m_desc); | |
1221 DDX_Control(pDX, IDC_CODE, m_code); | |
1222 //}}AFX_DATA_MAP | |
1223 } | |
1224 | |
1225 BEGIN_MESSAGE_MAP(AddCheatCode, CDialog) | |
1226 //{{AFX_MSG_MAP(AddCheatCode) | |
1227 ON_BN_CLICKED(ID_OK, OnOk) | |
1228 ON_BN_CLICKED(ID_CANCEL, OnCancel) | |
1229 //}}AFX_MSG_MAP | |
1230 END_MESSAGE_MAP() | |
1231 | |
1232 ///////////////////////////////////////////////////////////////////////////// | |
1233 // AddCheatCode message handlers | |
1234 | |
1235 void AddCheatCode::OnOk() | |
1236 { | |
1237 CString desc; | |
1238 CString buffer; | |
1239 CString token; | |
1240 | |
1241 m_code.GetWindowText(buffer); | |
1242 m_desc.GetWindowText(desc); | |
1243 | |
1244 StringTokenizer st(buffer, " \t\n\r"); | |
1245 const char * t = st.next(); | |
1246 while (t) | |
1247 { | |
1248 token = t; | |
1249 token.MakeUpper(); | |
1250 cheatsAddCheatCode(token, desc); | |
1251 t = st.next(); | |
1252 } | |
1253 EndDialog(TRUE); | |
1254 } | |
1255 | |
1256 void AddCheatCode::OnCancel() | |
1257 { | |
1258 EndDialog(FALSE); | |
1259 } | |
1260 | |
1261 BOOL AddCheatCode::OnInitDialog() | |
1262 { | |
1263 CDialog::OnInitDialog(); | |
1264 | |
1265 m_code.LimitText(1024); | |
1266 m_desc.LimitText(32); | |
1267 CString title = winResLoadString(IDS_ADD_CHEAT_CODE); | |
1268 SetWindowText(title); | |
1269 CenterWindow(); | |
1270 | |
1271 return TRUE; // return TRUE unless you set the focus to a control | |
1272 // EXCEPTION: OCX Property Pages should return FALSE | |
1273 } | |
1274 | |
1275 void GBACheatSearch::OnBnClickedCheatrefreshbutton() | |
1276 { | |
1277 addChanges(false); | |
1278 } | |
1279 |