remove more unportable ASM, obsoleting C_CORE define
[rofl0r-VisualBoyAdvance.git] / src / win32 / GBACheats.cpp
blobd7ee58663190296f2e64c6ab61dc8970720c45b1
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 // GBACheats.cpp : implementation file
22 #include "stdafx.h"
23 #include "vba.h"
24 #include "GBACheats.h"
26 #include "../System.h"
27 #include "../Cheats.h"
28 #include "../CheatSearch.h"
29 #include "../GBA.h"
30 #include "../Globals.h"
32 #include "Reg.h"
33 #include "StringTokenizer.h"
34 #include "WinResUtil.h"
36 #ifdef _DEBUG
37 #define new DEBUG_NEW
38 #undef THIS_FILE
39 static char THIS_FILE[] = __FILE__;
40 #endif
42 /////////////////////////////////////////////////////////////////////////////
43 // GBACheatSearch dialog
45 GBACheatSearch::GBACheatSearch(CWnd* pParent /*=NULL*/)
46 : CDialog(GBACheatSearch::IDD, pParent)
48 //{{AFX_DATA_INIT(GBACheatSearch)
49 valueType = -1;
50 sizeType = -1;
51 searchType = -1;
52 numberType = -1;
53 updateValues = FALSE;
54 //}}AFX_DATA_INIT
55 data = NULL;
58 GBACheatSearch::~GBACheatSearch()
60 if(data)
61 free(data);
64 void GBACheatSearch::DoDataExchange(CDataExchange* pDX)
66 CDialog::DoDataExchange(pDX);
67 //{{AFX_DATA_MAP(GBACheatSearch)
68 DDX_Control(pDX, IDC_VALUE, m_value);
69 DDX_Control(pDX, IDC_CHEAT_LIST, m_list);
70 DDX_Radio(pDX, IDC_OLD_VALUE, valueType);
71 DDX_Radio(pDX, IDC_SIZE_8, sizeType);
72 DDX_Radio(pDX, IDC_EQ, searchType);
73 DDX_Radio(pDX, IDC_SIGNED, numberType);
74 DDX_Check(pDX, IDC_UPDATE, updateValues);
75 //}}AFX_DATA_MAP
79 BEGIN_MESSAGE_MAP(GBACheatSearch, CDialog)
80 //{{AFX_MSG_MAP(GBACheatSearch)
81 ON_BN_CLICKED(ID_OK, OnOk)
82 ON_BN_CLICKED(IDC_START, OnStart)
83 ON_BN_CLICKED(IDC_SEARCH, OnSearch)
84 ON_BN_CLICKED(IDC_ADD_CHEAT, OnAddCheat)
85 ON_BN_CLICKED(IDC_UPDATE, OnUpdate)
86 ON_NOTIFY(LVN_GETDISPINFO, IDC_CHEAT_LIST, OnGetdispinfoCheatList)
87 ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHEAT_LIST, OnItemchangedCheatList)
88 ON_CONTROL_RANGE(BN_CLICKED, IDC_OLD_VALUE, IDC_SPECIFIC_VALUE, OnValueType)
89 ON_CONTROL_RANGE(BN_CLICKED, IDC_EQ, IDC_GE, OnSearchType)
90 ON_CONTROL_RANGE(BN_CLICKED, IDC_SIGNED, IDC_HEXADECIMAL, OnNumberType)
91 ON_CONTROL_RANGE(BN_CLICKED, IDC_SIZE_8, IDC_SIZE_32, OnSizeType)
92 //}}AFX_MSG_MAP
93 END_MESSAGE_MAP()
95 /////////////////////////////////////////////////////////////////////////////
96 // GBACheatSearch message handlers
98 void GBACheatSearch::OnOk()
100 EndDialog(TRUE);
103 void GBACheatSearch::OnStart()
105 if(cheatSearchData.count == 0) {
106 CheatSearchBlock *block = &cheatSearchData.blocks[0];
107 block->size = 0x40000;
108 block->offset = 0x2000000;
109 block->bits = (u8 *)malloc(0x40000>>3);
110 block->data = workRAM;
111 block->saved = (u8 *)malloc(0x40000);
113 block = &cheatSearchData.blocks[1];
114 block->size = 0x8000;
115 block->offset = 0x3000000;
116 block->bits = (u8 *)malloc(0x8000>>3);
117 block->data = internalRAM;
118 block->saved = (u8 *)malloc(0x8000);
120 cheatSearchData.count = 2;
123 cheatSearchStart(&cheatSearchData);
124 GetDlgItem(IDC_SEARCH)->EnableWindow(TRUE);
127 void GBACheatSearch::OnSearch()
129 CString buffer;
131 if(valueType == 0)
132 cheatSearch(&cheatSearchData,
133 searchType,
134 sizeType,
135 numberType == 0);
136 else {
137 m_value.GetWindowText(buffer);
138 if(buffer.IsEmpty()) {
139 systemMessage(IDS_NUMBER_CANNOT_BE_EMPTY, "Number cannot be empty");
140 return;
142 int value = 0;
143 switch(numberType) {
144 case 0:
145 sscanf(buffer, "%d", &value);
146 break;
147 case 1:
148 sscanf(buffer, "%u", &value);
149 break;
150 default:
151 sscanf(buffer, "%x", &value);
153 cheatSearchValue(&cheatSearchData,
154 searchType,
155 sizeType,
156 numberType == 0,
157 value);
160 addChanges(true);
162 if(updateValues)
163 cheatSearchUpdateValues(&cheatSearchData);
166 void GBACheatSearch::OnAddCheat()
168 int mark = m_list.GetSelectionMark();
170 if(mark != -1) {
171 LVITEM item;
172 memset(&item,0, sizeof(item));
173 item.mask = LVIF_PARAM;
174 item.iItem = mark;
175 if(m_list.GetItem(&item)) {
176 AddCheat dlg((u32)item.lParam);
177 dlg.DoModal();
182 void GBACheatSearch::OnUpdate()
184 if(GetDlgItem(IDC_UPDATE)->SendMessage(BM_GETCHECK,
186 0) & BST_CHECKED)
187 updateValues = true;
188 else
189 updateValues = false;
190 regSetDwordValue("cheatsUpdate", updateValues);
193 void GBACheatSearch::OnGetdispinfoCheatList(NMHDR* pNMHDR, LRESULT* pResult)
195 LV_DISPINFO* info = (LV_DISPINFO*)pNMHDR;
196 if(info->item.mask & LVIF_TEXT) {
197 int index = info->item.iItem;
198 int col = info->item.iSubItem;
200 switch(col) {
201 case 0:
202 strcpy(info->item.pszText, data[index].address);
203 break;
204 case 1:
205 strcpy(info->item.pszText, data[index].oldValue);
206 break;
207 case 2:
208 strcpy(info->item.pszText, data[index].newValue);
209 break;
212 *pResult = TRUE;
216 void GBACheatSearch::OnItemchangedCheatList(NMHDR* pNMHDR, LRESULT* pResult)
218 GetDlgItem(IDC_ADD_CHEAT)->EnableWindow(m_list.GetSelectionMark() != -1);
219 *pResult = TRUE;
222 BOOL GBACheatSearch::OnInitDialog()
224 CDialog::OnInitDialog();
226 CString temp = winResLoadString(IDS_ADDRESS);
228 m_list.InsertColumn(0, temp, LVCFMT_CENTER, 125, 0);
230 temp = winResLoadString(IDS_OLD_VALUE);
231 m_list.InsertColumn(1, temp, LVCFMT_CENTER, 125, 1);
233 temp = winResLoadString(IDS_NEW_VALUE);
234 m_list.InsertColumn(2, temp, LVCFMT_CENTER, 125, 2);
236 m_list.SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT)),
237 TRUE);
239 m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);
241 if(!cheatSearchData.count) {
242 GetDlgItem(IDC_SEARCH)->EnableWindow(FALSE);
243 GetDlgItem(IDC_ADD_CHEAT)->EnableWindow(FALSE);
246 valueType = regQueryDwordValue("cheatsValueType", 0);
247 if(valueType < 0 || valueType > 1)
248 valueType = 0;
250 searchType = regQueryDwordValue("cheatsSearchType", SEARCH_EQ);
251 if(searchType > 5 || searchType < 0)
252 searchType = 0;
254 numberType = regQueryDwordValue("cheatsNumberType", 2);
255 if(numberType < 0 || numberType > 2)
256 numberType = 2;
258 sizeType = regQueryDwordValue("cheatsSizeType", 0);
259 if(sizeType < 0 || sizeType > 2)
260 sizeType = 0;
262 updateValues = regQueryDwordValue("cheatsUpdate", 0) ?
263 true : false;
265 UpdateData(FALSE);
267 if(valueType == 0)
268 m_value.EnableWindow(FALSE);
269 CenterWindow();
271 if(cheatSearchData.count) {
272 addChanges(false);
275 return TRUE; // return TRUE unless you set the focus to a control
276 // EXCEPTION: OCX Property Pages should return FALSE
279 void GBACheatSearch::addChanges(bool showMsgs)
281 int count = cheatSearchGetCount(&cheatSearchData, sizeType);
283 m_list.DeleteAllItems();
285 if(count > 1000) {
286 if(showMsgs)
287 systemMessage(IDS_SEARCH_PRODUCED_TOO_MANY,
288 "Search produced %d results. Please refine better",
289 count);
290 return;
293 if(count == 0) {
294 if(showMsgs)
295 systemMessage(IDS_SEARCH_PRODUCED_NO_RESULTS,
296 "Search produced no results.");
297 return;
300 m_list.SetItemCount(count);
301 if(data)
302 free(data);
304 data = (WinCheatsData *)calloc(count,sizeof(WinCheatsData));
306 int inc = 1;
307 switch(sizeType) {
308 case 1:
309 inc = 2;
310 break;
311 case 2:
312 inc = 4;
313 break;
316 int index = 0;
317 if(numberType == 0) {
318 for(int i = 0; i < cheatSearchData.count; i++) {
319 CheatSearchBlock *block = &cheatSearchData.blocks[i];
321 for(int j = 0; j < block->size; j+= inc) {
322 if(IS_BIT_SET(block->bits, j)) {
323 addChange(index++,
324 block->offset | j,
325 cheatSearchSignedRead(block->saved,
327 sizeType),
328 cheatSearchSignedRead(block->data,
330 sizeType));
334 } else {
335 for(int i = 0; i < cheatSearchData.count; i++) {
336 CheatSearchBlock *block = &cheatSearchData.blocks[i];
338 for(int j = 0; j < block->size; j+= inc) {
339 if(IS_BIT_SET(block->bits, j)) {
340 addChange(index++,
341 block->offset | j,
342 cheatSearchRead(block->saved,
344 sizeType),
345 cheatSearchRead(block->data,
347 sizeType));
353 for(int i = 0; i < count; i++) {
354 LVITEM item;
356 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
357 item.iItem = i;
358 item.iSubItem = 0;
359 item.lParam = data[i].addr;
360 item.state = 0;
361 item.stateMask = 0;
362 item.pszText = LPSTR_TEXTCALLBACK;
363 m_list.InsertItem(&item);
365 m_list.SetItemText(i, 1, LPSTR_TEXTCALLBACK);
366 m_list.SetItemText(i, 2, LPSTR_TEXTCALLBACK);
370 void GBACheatSearch::addChange(int index, u32 address, u32 oldValue, u32 newValue)
372 data[index].addr = address;
373 sprintf(data[index].address, "%08x",address);
374 switch(numberType) {
375 case 0:
376 sprintf(data[index].oldValue, "%d", oldValue);
377 sprintf(data[index].newValue, "%d", newValue);
378 break;
379 case 1:
380 sprintf(data[index].oldValue, "%u", oldValue);
381 sprintf(data[index].newValue, "%u", newValue);
382 break;
383 case 2:
384 switch(sizeType) {
385 case 0:
386 sprintf(data[index].oldValue, "%02x", oldValue);
387 sprintf(data[index].newValue, "%02x", newValue);
388 break;
389 case 1:
390 sprintf(data[index].oldValue, "%04x", oldValue);
391 sprintf(data[index].newValue, "%04x", newValue);
392 break;
393 case 2:
394 sprintf(data[index].oldValue, "%08x", oldValue);
395 sprintf(data[index].newValue, "%08x", newValue);
396 break;
401 void GBACheatSearch::OnValueType(UINT id)
403 switch(id) {
404 case IDC_OLD_VALUE:
405 valueType = 0;
406 m_value.EnableWindow(FALSE);
407 regSetDwordValue("cheatsValueType", 0);
408 break;
409 case IDC_SPECIFIC_VALUE:
410 valueType = 1;
411 m_value.EnableWindow(TRUE);
412 regSetDwordValue("cheatsValueType", 1);
413 break;
417 void GBACheatSearch::OnSearchType(UINT id)
419 switch(id) {
420 case IDC_EQ:
421 searchType = SEARCH_EQ;
422 regSetDwordValue("cheatsSearchType", 0);
423 break;
424 case IDC_NE:
425 searchType = SEARCH_NE;
426 regSetDwordValue("cheatsSearchType", 1);
427 break;
428 case IDC_LT:
429 searchType = SEARCH_LT;
430 regSetDwordValue("cheatsSearchType", 2);
431 break;
432 case IDC_LE:
433 searchType = SEARCH_LE;
434 regSetDwordValue("cheatsSearchType", 3);
435 break;
436 case IDC_GT:
437 searchType = SEARCH_GT;
438 regSetDwordValue("cheatsSearchType", 4);
439 break;
440 case IDC_GE:
441 searchType = SEARCH_GE;
442 regSetDwordValue("cheatsSearchType", 5);
443 break;
447 void GBACheatSearch::OnNumberType(UINT id)
449 switch(id) {
450 case IDC_SIGNED:
451 numberType = 0;
452 regSetDwordValue("cheatsNumberType", 0);
453 if(m_list.GetItemCount()) {
454 addChanges(false);
456 break;
457 case IDC_UNSIGNED:
458 numberType = 1;
459 regSetDwordValue("cheatsNumberType", 1);
460 if(m_list.GetItemCount()) {
461 addChanges(false);
463 break;
464 case IDC_HEXADECIMAL:
465 numberType = 2;
466 regSetDwordValue("cheatsNumberType", 2);
467 if(m_list.GetItemCount()) {
468 addChanges(false);
470 break;
474 void GBACheatSearch::OnSizeType(UINT id)
476 switch(id) {
477 case IDC_SIZE_8:
478 sizeType = BITS_8;
479 regSetDwordValue("cheatsSizeType", 0);
480 if(m_list.GetItemCount()) {
481 addChanges(false);
483 break;
484 case IDC_SIZE_16:
485 sizeType = BITS_16;
486 regSetDwordValue("cheatsSizeType", 1);
487 if(m_list.GetItemCount()) {
488 addChanges(false);
490 break;
491 case IDC_SIZE_32:
492 sizeType = BITS_32;
493 regSetDwordValue("cheatsSizeType", 2);
494 if(m_list.GetItemCount()) {
495 addChanges(false);
497 break;
500 /////////////////////////////////////////////////////////////////////////////
501 // AddCheat dialog
504 AddCheat::AddCheat(u32 address, CWnd* pParent /*=NULL*/)
505 : CDialog(AddCheat::IDD, pParent)
507 //{{AFX_DATA_INIT(AddCheat)
508 sizeType = -1;
509 numberType = -1;
510 //}}AFX_DATA_INIT
511 this->address = address;
515 void AddCheat::DoDataExchange(CDataExchange* pDX)
517 CDialog::DoDataExchange(pDX);
518 //{{AFX_DATA_MAP(AddCheat)
519 DDX_Control(pDX, IDC_VALUE, m_value);
520 DDX_Control(pDX, IDC_DESC, m_desc);
521 DDX_Control(pDX, IDC_ADDRESS, m_address);
522 DDX_Radio(pDX, IDC_SIZE_8, sizeType);
523 DDX_Radio(pDX, IDC_SIGNED, numberType);
524 //}}AFX_DATA_MAP
528 BEGIN_MESSAGE_MAP(AddCheat, CDialog)
529 //{{AFX_MSG_MAP(AddCheat)
530 ON_BN_CLICKED(ID_OK, OnOk)
531 ON_BN_CLICKED(ID_CANCEL, OnCancel)
532 ON_CONTROL_RANGE(BN_CLICKED, IDC_SIGNED, IDC_HEXADECIMAL, OnNumberType)
533 ON_CONTROL_RANGE(BN_CLICKED, IDC_SIZE_8, IDC_SIZE_32, OnSizeType)
534 //}}AFX_MSG_MAP
535 END_MESSAGE_MAP()
537 /////////////////////////////////////////////////////////////////////////////
538 // AddCheat message handlers
540 void AddCheat::OnOk()
542 // add cheat
543 if(addCheat()) {
544 EndDialog(TRUE);
548 void AddCheat::OnCancel()
550 EndDialog(FALSE);
553 BOOL AddCheat::OnInitDialog()
555 CDialog::OnInitDialog();
557 if(address != 0) {
558 CString buffer;
559 buffer.Format("%08x", address);
560 m_address.SetWindowText(buffer);
561 m_address.EnableWindow(FALSE);
564 numberType = regQueryDwordValue("cheatsNumberType", 2);
565 if(numberType < 0 || numberType > 2)
566 numberType = 2;
568 sizeType = regQueryDwordValue("cheatsSizeType", 0);
569 if(sizeType < 0 || sizeType > 2)
570 sizeType = 0;
572 UpdateData(FALSE);
574 GetDlgItem(IDC_DESC)->SendMessage(EM_LIMITTEXT,
577 if(address != 0) {
578 GetDlgItem(IDC_SIZE_8)->EnableWindow(FALSE);
579 GetDlgItem(IDC_SIZE_16)->EnableWindow(FALSE);
580 GetDlgItem(IDC_SIZE_32)->EnableWindow(FALSE);
581 GetDlgItem(IDC_HEXADECIMAL)->EnableWindow(FALSE);
582 GetDlgItem(IDC_UNSIGNED)->EnableWindow(FALSE);
583 GetDlgItem(IDC_SIGNED)->EnableWindow(FALSE);
586 CenterWindow();
588 return TRUE; // return TRUE unless you set the focus to a control
589 // EXCEPTION: OCX Property Pages should return FALSE
592 void AddCheat::OnNumberType(UINT id)
594 switch(id) {
595 case IDC_SIGNED:
596 numberType = 0;
597 regSetDwordValue("cheatsNumberType", 0);
598 break;
599 case IDC_UNSIGNED:
600 numberType = 1;
601 regSetDwordValue("cheatsNumberType", 1);
602 break;
603 case IDC_HEXADECIMAL:
604 numberType = 2;
605 regSetDwordValue("cheatsNumberType", 2);
606 break;
610 void AddCheat::OnSizeType(UINT id)
612 switch(id) {
613 case IDC_SIZE_8:
614 sizeType = BITS_8;
615 regSetDwordValue("cheatsSizeType", 0);
616 break;
617 case IDC_SIZE_16:
618 sizeType = BITS_16;
619 regSetDwordValue("cheatsSizeType", 1);
620 break;
621 case IDC_SIZE_32:
622 sizeType = BITS_32;
623 regSetDwordValue("cheatsSizeType", 2);
624 break;
628 bool AddCheat::addCheat()
630 CString buffer;
631 CString code;
633 m_address.GetWindowText(buffer);
634 u32 address = 0;
635 sscanf(buffer, "%x", &address);
636 if((address >= 0x02000000 && address < 0x02040000) ||
637 (address >= 0x03000000 && address < 0x03008000)) {
638 } else {
639 systemMessage(IDS_INVALID_ADDRESS, "Invalid address: %08x", address);
640 return false;
642 if(sizeType != 0) {
643 if(sizeType == 1 && address & 1) {
644 systemMessage(IDS_MISALIGNED_HALFWORD,
645 "Misaligned half-word address: %08x", address);
646 return false;
648 if(sizeType == 2 && address & 3) {
649 systemMessage(IDS_MISALIGNED_WORD,
650 "Misaligned word address: %08x", address);
651 return false;
654 u32 value;
655 m_value.GetWindowText(buffer);
657 if(buffer.IsEmpty()) {
658 systemMessage(IDS_VALUE_CANNOT_BE_EMPTY, "Value cannot be empty");
659 return false;
662 switch(numberType) {
663 case 0:
664 sscanf(buffer, "%d", &value);
665 break;
666 case 1:
667 sscanf(buffer, "%u", &value);
668 break;
669 default:
670 sscanf(buffer, "%x", &value);
673 m_desc.GetWindowText(buffer);
675 switch(sizeType) {
676 case 0:
677 code.Format("%08x:%02x", address, value);
678 break;
679 case 1:
680 code.Format("%08x:%04x", address, value);
681 break;
682 case 2:
683 code.Format("%08x:%08x", address, value);
684 break;
687 cheatsAdd(code, buffer, address ,address, value,-1, sizeType);
688 return true;
690 /////////////////////////////////////////////////////////////////////////////
691 // GBACheatList dialog
694 GBACheatList::GBACheatList(CWnd* pParent /*=NULL*/)
695 : CDialog(GBACheatList::IDD, pParent)
697 //{{AFX_DATA_INIT(GBACheatList)
698 // NOTE: the ClassWizard will add member initialization here
699 //}}AFX_DATA_INIT
700 duringRefresh = false;
704 void GBACheatList::DoDataExchange(CDataExchange* pDX)
706 CDialog::DoDataExchange(pDX);
707 //{{AFX_DATA_MAP(GBACheatList)
708 DDX_Control(pDX, IDC_RESTORE, m_restore);
709 DDX_Control(pDX, IDC_CHEAT_LIST, m_list);
710 //}}AFX_DATA_MAP
714 BEGIN_MESSAGE_MAP(GBACheatList, CDialog)
715 //{{AFX_MSG_MAP(GBACheatList)
716 ON_BN_CLICKED(IDC_ADD_CHEAT, OnAddCheat)
717 ON_BN_CLICKED(IDC_ADD_CODE, OnAddCode)
718 ON_BN_CLICKED(IDC_ADD_CODEBREAKER, OnAddCodebreaker)
719 ON_BN_CLICKED(IDC_ADD_GAMESHARK, OnAddGameshark)
720 ON_BN_CLICKED(IDC_ENABLE, OnEnable)
721 ON_BN_CLICKED(IDC_REMOVE, OnRemove)
722 ON_BN_CLICKED(IDC_REMOVE_ALL, OnRemoveAll)
723 ON_BN_CLICKED(IDC_RESTORE, OnRestore)
724 ON_BN_CLICKED(ID_OK, OnOk)
725 ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHEAT_LIST, OnItemchangedCheatList)
726 //}}AFX_MSG_MAP
727 END_MESSAGE_MAP()
729 /////////////////////////////////////////////////////////////////////////////
730 // GBACheatList message handlers
732 void GBACheatList::OnAddCheat()
734 AddCheat dlg(0);
735 dlg.DoModal();
736 refresh();
739 void GBACheatList::OnAddCode()
741 AddCheatCode dlg;
742 dlg.DoModal();
743 refresh();
746 void GBACheatList::OnAddCodebreaker()
748 AddCBACode dlg;
749 dlg.DoModal();
750 refresh();
753 void GBACheatList::OnAddGameshark()
755 AddGSACode dlg;
756 dlg.DoModal();
757 refresh();
760 void GBACheatList::OnEnable()
762 int mark = m_list.GetSelectionMark();
763 int count = m_list.GetItemCount();
765 if(mark != -1) {
766 LVITEM item;
767 for(int i = 0; i < count; i++) {
768 memset(&item, 0, sizeof(item));
769 item.mask = LVIF_PARAM|LVIF_STATE;
770 item.stateMask = LVIS_SELECTED;
771 item.iItem = i;
772 if(m_list.GetItem(&item)) {
773 if(item.state & LVIS_SELECTED) {
774 if(cheatsList[item.lParam].enabled)
775 cheatsDisable((int)(item.lParam & 0xFFFFFFFF));
776 else
777 cheatsEnable((int)(item.lParam & 0xFFFFFFFF));
781 refresh();
785 void GBACheatList::OnRemove()
787 int mark = m_list.GetSelectionMark();
788 int count = m_list.GetItemCount();
790 if(mark != -1) {
791 for(int i = count - 1; i >= 0; i--) {
792 LVITEM item;
793 memset(&item,0, sizeof(item));
794 item.mask = LVIF_PARAM|LVIF_STATE;
795 item.iItem = i;
796 item.stateMask = LVIS_SELECTED;
797 if(m_list.GetItem(&item)) {
798 if(item.state & LVIS_SELECTED) {
799 cheatsDelete((int)(item.lParam & 0xFFFFFFFF), restoreValues);
803 refresh();
807 void GBACheatList::OnRemoveAll()
809 cheatsDeleteAll(restoreValues);
810 refresh();
814 void GBACheatList::OnRestore()
816 restoreValues = !restoreValues;
817 regSetDwordValue("cheatsRestore", restoreValues);
820 void GBACheatList::OnOk()
822 EndDialog(TRUE);
825 void GBACheatList::OnItemchangedCheatList(NMHDR* pNMHDR, LRESULT* pResult)
827 if(m_list.GetSelectionMark() != -1) {
828 GetDlgItem(IDC_REMOVE)->EnableWindow(TRUE);
829 GetDlgItem(IDC_ENABLE)->EnableWindow(TRUE);
830 } else {
831 GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE);
832 GetDlgItem(IDC_ENABLE)->EnableWindow(FALSE);
835 if(!duringRefresh) {
836 LPNMLISTVIEW l = (LPNMLISTVIEW)pNMHDR;
837 if(l->uChanged & LVIF_STATE) {
838 if(((l->uOldState & LVIS_STATEIMAGEMASK)>>12) !=
839 (((l->uNewState & LVIS_STATEIMAGEMASK)>>12))) {
840 if(m_list.GetCheck(l->iItem))
841 cheatsEnable((int)(l->lParam & 0xFFFFFFFF));
842 else
843 cheatsDisable((int)(l->lParam & 0xFFFFFFFF));
844 refresh();
849 *pResult = 0;
852 BOOL GBACheatList::OnInitDialog()
854 CDialog::OnInitDialog();
856 CString temp = winResLoadString(IDS_CODE);
857 m_list.InsertColumn(0, temp, LVCFMT_LEFT, 170, 0);
858 temp = winResLoadString(IDS_DESCRIPTION);
859 m_list.InsertColumn(1, temp, LVCFMT_LEFT, 150, 1);
860 temp = winResLoadString(IDS_STATUS);
861 m_list.InsertColumn(2, temp, LVCFMT_LEFT, 80, 1);
863 m_list.SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT)),
864 TRUE);
866 m_list.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
868 restoreValues = regQueryDwordValue("cheatsRestore", 0) ?
869 true : false;
871 m_restore.SetCheck(restoreValues);
873 refresh();
874 GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE);
875 GetDlgItem(IDC_ENABLE)->EnableWindow(FALSE);
876 CenterWindow();
878 return TRUE; // return TRUE unless you set the focus to a control
879 // EXCEPTION: OCX Property Pages should return FALSE
882 void GBACheatList::refresh()
884 duringRefresh = true;
885 m_list.DeleteAllItems();
887 CString buffer;
889 for(int i = 0; i < cheatsNumber; i++) {
890 LVITEM item;
892 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
893 item.iItem = i;
894 item.iSubItem = 0;
895 item.lParam = i;
896 item.state = 0;
897 item.stateMask = 0;
898 item.pszText = cheatsList[i].codestring;
899 m_list.InsertItem(&item);
901 m_list.SetCheck(i, (cheatsList[i].enabled) ? TRUE : FALSE);
903 m_list.SetItemText(i, 1, cheatsList[i].desc);
905 buffer = (cheatsList[i].enabled) ? 'E' : 'D';
906 m_list.SetItemText(i, 2, buffer);
908 duringRefresh = false;
910 /////////////////////////////////////////////////////////////////////////////
911 // AddGSACode dialog
914 AddGSACode::AddGSACode(CWnd* pParent /*=NULL*/)
915 : CDialog(AddGSACode::IDD, pParent)
917 //{{AFX_DATA_INIT(AddGSACode)
918 // NOTE: the ClassWizard will add member initialization here
919 //}}AFX_DATA_INIT
923 void AddGSACode::DoDataExchange(CDataExchange* pDX)
925 CDialog::DoDataExchange(pDX);
926 //{{AFX_DATA_MAP(AddGSACode)
927 DDX_Control(pDX, IDC_DESC, m_desc);
928 DDX_Control(pDX, IDC_CODE, m_code);
929 //}}AFX_DATA_MAP
933 BEGIN_MESSAGE_MAP(AddGSACode, CDialog)
934 //{{AFX_MSG_MAP(AddGSACode)
935 ON_BN_CLICKED(ID_OK, OnOk)
936 ON_BN_CLICKED(ID_CANCEL, OnCancel)
937 //}}AFX_MSG_MAP
938 END_MESSAGE_MAP()
940 /////////////////////////////////////////////////////////////////////////////
941 // AddGSACode message handlers
943 void AddGSACode::OnOk()
945 CString desc;
946 CString buffer;
947 CString part1;
948 CString code;
949 CString token;
951 m_code.GetWindowText(buffer);
952 m_desc.GetWindowText(desc);
954 StringTokenizer st(buffer, " \t\n\r");
955 part1.Empty();
956 const char *t = st.next();
957 while(t) {
958 token = t;
959 token.MakeUpper();
960 if(token.GetLength() == 16)
961 cheatsAddGSACode(token, desc, false);
962 else if(token.GetLength() == 12) {
963 code = token.Left(8);
964 code += " ";
965 code += token.Right(4);
966 cheatsAddCBACode(code, desc);
967 } else if(part1.IsEmpty())
968 part1 = token;
969 else {
970 if(token.GetLength() == 4) {
971 code = part1;
972 code += " ";
973 code += token;
974 cheatsAddCBACode(code, desc);
975 } else {
976 code = part1 + token;
977 cheatsAddGSACode(code, desc, true);
979 part1.Empty();
982 t = st.next();
984 EndDialog(TRUE);
987 void AddGSACode::OnCancel()
989 EndDialog(FALSE);
992 BOOL AddGSACode::OnInitDialog()
994 CDialog::OnInitDialog();
996 m_code.LimitText(1024);
997 m_desc.LimitText(32);
998 CString title = winResLoadString(IDS_ADD_GSA_CODE);
999 SetWindowText(title);
1000 CenterWindow();
1002 return TRUE; // return TRUE unless you set the focus to a control
1003 // EXCEPTION: OCX Property Pages should return FALSE
1006 /////////////////////////////////////////////////////////////////////////////
1007 // AddCBACode dialog
1010 AddCBACode::AddCBACode(CWnd* pParent /*=NULL*/)
1011 : CDialog(AddCBACode::IDD, pParent)
1013 //{{AFX_DATA_INIT(AddCBACode)
1014 // NOTE: the ClassWizard will add member initialization here
1015 //}}AFX_DATA_INIT
1019 void AddCBACode::DoDataExchange(CDataExchange* pDX)
1021 CDialog::DoDataExchange(pDX);
1022 //{{AFX_DATA_MAP(AddCBACode)
1023 DDX_Control(pDX, IDC_DESC, m_desc);
1024 DDX_Control(pDX, IDC_CODE, m_code);
1025 //}}AFX_DATA_MAP
1029 BEGIN_MESSAGE_MAP(AddCBACode, CDialog)
1030 //{{AFX_MSG_MAP(AddCBACode)
1031 ON_BN_CLICKED(ID_OK, OnOk)
1032 ON_BN_CLICKED(ID_CANCEL, OnCancel)
1033 //}}AFX_MSG_MAP
1034 END_MESSAGE_MAP()
1036 /////////////////////////////////////////////////////////////////////////////
1037 // AddCBACode message handlers
1039 void AddCBACode::OnOk()
1041 CString desc;
1042 CString buffer;
1043 CString part1;
1044 CString code;
1045 CString token;
1047 m_code.GetWindowText(buffer);
1048 m_desc.GetWindowText(desc);
1050 StringTokenizer st(buffer, " \t\n\r");
1051 part1.Empty();
1052 const char *t = st.next();
1053 while(t) {
1054 token = t;
1055 token.MakeUpper();
1056 if(token.GetLength() == 16)
1057 cheatsAddGSACode(token, desc, false);
1058 else if(token.GetLength() == 12) {
1059 code = token.Left(8);
1060 code += " ";
1061 code += token.Right(4);
1062 cheatsAddCBACode(code, desc);
1063 } else if(part1.IsEmpty())
1064 part1 = token;
1065 else {
1066 if(token.GetLength() == 4) {
1067 code = part1;
1068 code += " ";
1069 code += token;
1070 cheatsAddCBACode(code, desc);
1071 } else {
1072 code = part1 + token;
1073 cheatsAddGSACode(code, desc, true);
1075 part1.Empty();
1078 t = st.next();
1080 EndDialog(TRUE);
1083 void AddCBACode::OnCancel()
1085 EndDialog(FALSE);
1088 BOOL AddCBACode::OnInitDialog()
1090 CDialog::OnInitDialog();
1092 m_code.LimitText(1024);
1093 m_desc.LimitText(32);
1094 CString title = winResLoadString(IDS_ADD_CBA_CODE);
1095 SetWindowText(title);
1096 CenterWindow();
1098 return TRUE; // return TRUE unless you set the focus to a control
1099 // EXCEPTION: OCX Property Pages should return FALSE
1102 /////////////////////////////////////////////////////////////////////////////
1103 // AddCheatCode dialog
1106 AddCheatCode::AddCheatCode(CWnd* pParent /*=NULL*/)
1107 : CDialog(AddCheatCode::IDD, pParent)
1109 //{{AFX_DATA_INIT(AddCheatCode)
1110 // NOTE: the ClassWizard will add member initialization here
1111 //}}AFX_DATA_INIT
1115 void AddCheatCode::DoDataExchange(CDataExchange* pDX)
1117 CDialog::DoDataExchange(pDX);
1118 //{{AFX_DATA_MAP(AddCheatCode)
1119 DDX_Control(pDX, IDC_DESC, m_desc);
1120 DDX_Control(pDX, IDC_CODE, m_code);
1121 //}}AFX_DATA_MAP
1125 BEGIN_MESSAGE_MAP(AddCheatCode, CDialog)
1126 //{{AFX_MSG_MAP(AddCheatCode)
1127 ON_BN_CLICKED(ID_OK, OnOk)
1128 ON_BN_CLICKED(ID_CANCEL, OnCancel)
1129 //}}AFX_MSG_MAP
1130 END_MESSAGE_MAP()
1132 /////////////////////////////////////////////////////////////////////////////
1133 // AddCheatCode message handlers
1135 void AddCheatCode::OnOk()
1137 CString desc;
1138 CString buffer;
1139 CString token;
1141 m_code.GetWindowText(buffer);
1142 m_desc.GetWindowText(desc);
1144 StringTokenizer st(buffer, " \t\n\r");
1145 const char *t = st.next();
1146 while(t) {
1147 token = t;
1148 token.MakeUpper();
1149 cheatsAddCheatCode(token, desc);
1150 t = st.next();
1152 EndDialog(TRUE);
1155 void AddCheatCode::OnCancel()
1157 EndDialog(FALSE);
1160 BOOL AddCheatCode::OnInitDialog()
1162 CDialog::OnInitDialog();
1164 m_code.LimitText(1024);
1165 m_desc.LimitText(32);
1166 CString title = winResLoadString(IDS_ADD_CHEAT_CODE);
1167 SetWindowText(title);
1168 CenterWindow();
1170 return TRUE; // return TRUE unless you set the focus to a control
1171 // EXCEPTION: OCX Property Pages should return FALSE