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