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