home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / win32 / GBACheats.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  27.6 KB  |  1,173 lines

  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4.  
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2, or(at your option)
  8. // any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software Foundation,
  17. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. // GBACheats.cpp : implementation file
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "vba.h"
  24. #include "GBACheats.h"
  25.  
  26. #include "../System.h"
  27. #include "../Cheats.h"
  28. #include "../CheatSearch.h"
  29. #include "../GBA.h"
  30. #include "../Globals.h"
  31.  
  32. #include "Reg.h"
  33. #include "StringTokenizer.h"
  34. #include "WinResUtil.h"
  35.  
  36. #ifdef _DEBUG
  37. #define new DEBUG_NEW
  38. #undef THIS_FILE
  39. static char THIS_FILE[] = __FILE__;
  40. #endif
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // GBACheatSearch dialog
  44.  
  45. GBACheatSearch::GBACheatSearch(CWnd* pParent /*=NULL*/)
  46.   : CDialog(GBACheatSearch::IDD, pParent)
  47. {
  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;
  56. }
  57.  
  58. GBACheatSearch::~GBACheatSearch()
  59. {
  60.   if(data)
  61.     free(data);
  62. }
  63.  
  64. void GBACheatSearch::DoDataExchange(CDataExchange* pDX)
  65. {
  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
  76. }
  77.  
  78.  
  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()
  94.  
  95.   /////////////////////////////////////////////////////////////////////////////
  96. // GBACheatSearch message handlers
  97.  
  98. void GBACheatSearch::OnOk() 
  99. {
  100.   EndDialog(TRUE);
  101. }
  102.  
  103. void GBACheatSearch::OnStart() 
  104. {
  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);
  112.     
  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);
  119.     
  120.     cheatSearchData.count = 2;
  121.   }
  122.  
  123.   cheatSearchStart(&cheatSearchData);
  124.   GetDlgItem(IDC_SEARCH)->EnableWindow(TRUE);
  125. }
  126.  
  127. void GBACheatSearch::OnSearch() 
  128. {
  129.   CString buffer;
  130.  
  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;
  141.     }
  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);
  152.     }
  153.     cheatSearchValue(&cheatSearchData,
  154.                      searchType,
  155.                      sizeType,
  156.                      numberType == 0,
  157.                      value);
  158.   }
  159.   
  160.   addChanges(true);
  161.  
  162.   if(updateValues)
  163.     cheatSearchUpdateValues(&cheatSearchData);
  164. }
  165.  
  166. void GBACheatSearch::OnAddCheat() 
  167. {
  168.   int mark = m_list.GetSelectionMark();
  169.   
  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();
  178.     }
  179.   }
  180. }
  181.  
  182. void GBACheatSearch::OnUpdate() 
  183. {
  184.   if(GetDlgItem(IDC_UPDATE)->SendMessage(BM_GETCHECK,
  185.                                          0,
  186.                                          0) & BST_CHECKED)
  187.     updateValues = true;
  188.   else
  189.     updateValues = false;
  190.   regSetDwordValue("cheatsUpdate", updateValues);
  191. }
  192.  
  193. void GBACheatSearch::OnGetdispinfoCheatList(NMHDR* pNMHDR, LRESULT* pResult) 
  194. {
  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;
  199.     
  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;
  210.     }
  211.   }
  212.   *pResult = TRUE;
  213.  
  214. }
  215.  
  216. void GBACheatSearch::OnItemchangedCheatList(NMHDR* pNMHDR, LRESULT* pResult) 
  217. {
  218.   GetDlgItem(IDC_ADD_CHEAT)->EnableWindow(m_list.GetSelectionMark() != -1);
  219.   *pResult = TRUE;
  220. }
  221.  
  222. BOOL GBACheatSearch::OnInitDialog() 
  223. {
  224.   CDialog::OnInitDialog();
  225.   
  226.   CString temp = winResLoadString(IDS_ADDRESS);
  227.  
  228.   m_list.InsertColumn(0, temp, LVCFMT_CENTER, 125, 0);
  229.  
  230.   temp = winResLoadString(IDS_OLD_VALUE);
  231.   m_list.InsertColumn(1, temp, LVCFMT_CENTER, 125, 1);
  232.  
  233.   temp = winResLoadString(IDS_NEW_VALUE);
  234.   m_list.InsertColumn(2, temp, LVCFMT_CENTER, 125, 2);
  235.   
  236.   m_list.SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT)),
  237.                  TRUE);
  238.  
  239.   m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);
  240.   
  241.   if(!cheatSearchData.count) {
  242.     GetDlgItem(IDC_SEARCH)->EnableWindow(FALSE);
  243.     GetDlgItem(IDC_ADD_CHEAT)->EnableWindow(FALSE);
  244.   }
  245.   
  246.   valueType = regQueryDwordValue("cheatsValueType", 0);
  247.   if(valueType < 0 || valueType > 1)
  248.     valueType = 0;
  249.  
  250.   searchType = regQueryDwordValue("cheatsSearchType", SEARCH_EQ);
  251.   if(searchType > 5 || searchType < 0)
  252.     searchType = 0;
  253.   
  254.   numberType = regQueryDwordValue("cheatsNumberType", 2);
  255.   if(numberType < 0 || numberType > 2)
  256.     numberType = 2;
  257.   
  258.   sizeType = regQueryDwordValue("cheatsSizeType", 0);
  259.   if(sizeType < 0 || sizeType > 2)
  260.     sizeType = 0;
  261.   
  262.   updateValues = regQueryDwordValue("cheatsUpdate", 0) ?
  263.     true : false;
  264.  
  265.   UpdateData(FALSE);
  266.  
  267.   if(valueType == 0)
  268.     m_value.EnableWindow(FALSE);
  269.   CenterWindow();
  270.  
  271.   if(cheatSearchData.count) {
  272.     addChanges(false);
  273.   }
  274.   
  275.   return TRUE;  // return TRUE unless you set the focus to a control
  276.                 // EXCEPTION: OCX Property Pages should return FALSE
  277. }
  278.  
  279. void GBACheatSearch::addChanges(bool showMsgs)
  280. {
  281.   int count = cheatSearchGetCount(&cheatSearchData, sizeType);
  282.   
  283.   m_list.DeleteAllItems();
  284.  
  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;
  291.   }
  292.  
  293.   if(count == 0) {
  294.     if(showMsgs)
  295.       systemMessage(IDS_SEARCH_PRODUCED_NO_RESULTS,
  296.                     "Search produced no results.");
  297.     return;
  298.   }
  299.   
  300.   m_list.SetItemCount(count);  
  301.   if(data)
  302.     free(data);
  303.   
  304.   data = (WinCheatsData *)calloc(count,sizeof(WinCheatsData));
  305.   
  306.   int inc = 1;
  307.   switch(sizeType) {
  308.   case 1:
  309.     inc = 2;
  310.     break;
  311.   case 2:
  312.     inc = 4;
  313.     break;
  314.   }
  315.   
  316.   int index = 0;
  317.   if(numberType == 0) {
  318.     for(int i = 0; i < cheatSearchData.count; i++) {
  319.       CheatSearchBlock *block = &cheatSearchData.blocks[i];
  320.       
  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,
  326.                                           j,
  327.                                           sizeType),
  328.                     cheatSearchSignedRead(block->data,
  329.                                           j,
  330.                                           sizeType));
  331.         }
  332.       }
  333.     }
  334.   } else {
  335.     for(int i = 0; i < cheatSearchData.count; i++) {
  336.       CheatSearchBlock *block = &cheatSearchData.blocks[i];
  337.       
  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,
  343.                                     j,
  344.                                     sizeType),
  345.                     cheatSearchRead(block->data,
  346.                                     j,
  347.                                     sizeType));
  348.         }
  349.       }
  350.     }
  351.   }
  352.  
  353.   for(int i = 0; i < count; i++) {
  354.     LVITEM item;
  355.  
  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);
  364.  
  365.     m_list.SetItemText(i, 1, LPSTR_TEXTCALLBACK);
  366.     m_list.SetItemText(i, 2, LPSTR_TEXTCALLBACK);
  367.   }  
  368. }
  369.  
  370. void GBACheatSearch::addChange(int index, u32 address, u32 oldValue, u32 newValue)
  371. {
  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;
  397.     }
  398.   }
  399. }
  400.  
  401. void GBACheatSearch::OnValueType(UINT id)
  402. {
  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;
  414.   }
  415. }
  416.  
  417. void GBACheatSearch::OnSearchType(UINT id)
  418. {
  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;
  444.   }
  445. }
  446.  
  447. void GBACheatSearch::OnNumberType(UINT id)
  448. {
  449.   switch(id) {
  450.   case IDC_SIGNED:
  451.     numberType = 0;
  452.     regSetDwordValue("cheatsNumberType", 0);
  453.     if(m_list.GetItemCount()) {
  454.       addChanges(false);
  455.     }
  456.     break;
  457.   case IDC_UNSIGNED:
  458.     numberType = 1;
  459.     regSetDwordValue("cheatsNumberType", 1);
  460.     if(m_list.GetItemCount()) {
  461.       addChanges(false);
  462.     }
  463.     break;
  464.   case IDC_HEXADECIMAL:
  465.     numberType = 2;
  466.     regSetDwordValue("cheatsNumberType", 2);
  467.     if(m_list.GetItemCount()) {
  468.       addChanges(false);
  469.     }
  470.     break;
  471.   }
  472. }
  473.  
  474. void GBACheatSearch::OnSizeType(UINT id)
  475. {
  476.   switch(id) {
  477.   case IDC_SIZE_8:
  478.     sizeType = BITS_8;
  479.     regSetDwordValue("cheatsSizeType", 0);
  480.     if(m_list.GetItemCount()) {
  481.       addChanges(false);
  482.     }
  483.     break;
  484.   case IDC_SIZE_16:
  485.     sizeType = BITS_16;
  486.     regSetDwordValue("cheatsSizeType", 1);
  487.     if(m_list.GetItemCount()) {
  488.       addChanges(false);
  489.     }
  490.     break;
  491.   case IDC_SIZE_32:
  492.     sizeType = BITS_32;
  493.     regSetDwordValue("cheatsSizeType", 2);
  494.     if(m_list.GetItemCount()) {
  495.       addChanges(false);
  496.     }
  497.     break;
  498.   }
  499. }
  500. /////////////////////////////////////////////////////////////////////////////
  501. // AddCheat dialog
  502.  
  503.  
  504. AddCheat::AddCheat(u32 address, CWnd* pParent /*=NULL*/)
  505.   : CDialog(AddCheat::IDD, pParent)
  506. {
  507.   //{{AFX_DATA_INIT(AddCheat)
  508.   sizeType = -1;
  509.   numberType = -1;
  510.   //}}AFX_DATA_INIT
  511.   this->address = address;
  512. }
  513.  
  514.  
  515. void AddCheat::DoDataExchange(CDataExchange* pDX)
  516. {
  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
  525. }
  526.  
  527.  
  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()
  536.  
  537.   /////////////////////////////////////////////////////////////////////////////
  538. // AddCheat message handlers
  539.  
  540. void AddCheat::OnOk() 
  541. {
  542.   // add cheat
  543.   if(addCheat()) {
  544.     EndDialog(TRUE);
  545.   }
  546. }
  547.  
  548. void AddCheat::OnCancel() 
  549. {
  550.   EndDialog(FALSE);
  551. }
  552.  
  553. BOOL AddCheat::OnInitDialog() 
  554. {
  555.   CDialog::OnInitDialog();
  556.   
  557.   if(address != 0) {
  558.     CString buffer;
  559.     buffer.Format("%08x", address);
  560.     m_address.SetWindowText(buffer);
  561.     m_address.EnableWindow(FALSE);
  562.   }
  563.   
  564.   numberType = regQueryDwordValue("cheatsNumberType", 2);
  565.   if(numberType < 0 || numberType > 2)
  566.     numberType = 2;
  567.   
  568.   sizeType = regQueryDwordValue("cheatsSizeType", 0);
  569.   if(sizeType < 0 || sizeType > 2)
  570.     sizeType = 0;
  571.  
  572.   UpdateData(FALSE);
  573.   
  574.   GetDlgItem(IDC_DESC)->SendMessage(EM_LIMITTEXT,
  575.                                     32,
  576.                                     0);
  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);        
  584.   }
  585.  
  586.   CenterWindow();
  587.   
  588.   return TRUE;  // return TRUE unless you set the focus to a control
  589.                 // EXCEPTION: OCX Property Pages should return FALSE
  590. }
  591.  
  592. void AddCheat::OnNumberType(UINT id)
  593. {
  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;
  607.   }
  608. }
  609.  
  610. void AddCheat::OnSizeType(UINT id)
  611. {
  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;
  625.   }
  626. }
  627.  
  628. bool AddCheat::addCheat()
  629. {
  630.   CString buffer;
  631.   CString code;
  632.  
  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;
  641.   }
  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;
  647.     }
  648.     if(sizeType == 2 && address & 3) {
  649.       systemMessage(IDS_MISALIGNED_WORD,
  650.                     "Misaligned word address: %08x", address);
  651.       return false;
  652.     }    
  653.   }
  654.   u32 value;
  655.   m_value.GetWindowText(buffer);
  656.   
  657.   if(buffer.IsEmpty()) {
  658.     systemMessage(IDS_VALUE_CANNOT_BE_EMPTY, "Value cannot be empty");
  659.     return false;
  660.   }
  661.   
  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);
  671.   }
  672.  
  673.   m_desc.GetWindowText(buffer);
  674.  
  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;
  685.   }
  686.   
  687.   cheatsAdd(code, buffer,address, value,-1, sizeType);
  688.   return true;
  689. }
  690. /////////////////////////////////////////////////////////////////////////////
  691. // GBACheatList dialog
  692.  
  693.  
  694. GBACheatList::GBACheatList(CWnd* pParent /*=NULL*/)
  695.   : CDialog(GBACheatList::IDD, pParent)
  696. {
  697.   //{{AFX_DATA_INIT(GBACheatList)
  698.   // NOTE: the ClassWizard will add member initialization here
  699.   //}}AFX_DATA_INIT
  700.   duringRefresh = false;
  701. }
  702.  
  703.  
  704. void GBACheatList::DoDataExchange(CDataExchange* pDX)
  705. {
  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
  711. }
  712.  
  713.  
  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()
  728.  
  729.   /////////////////////////////////////////////////////////////////////////////
  730. // GBACheatList message handlers
  731.  
  732. void GBACheatList::OnAddCheat() 
  733. {
  734.   AddCheat dlg(0);
  735.   dlg.DoModal();
  736.   refresh();
  737. }
  738.  
  739. void GBACheatList::OnAddCode() 
  740. {
  741.   AddCheatCode dlg;
  742.   dlg.DoModal();
  743.   refresh();
  744. }
  745.  
  746. void GBACheatList::OnAddCodebreaker() 
  747. {
  748.   AddCBACode dlg;
  749.   dlg.DoModal();
  750.   refresh();
  751. }
  752.  
  753. void GBACheatList::OnAddGameshark() 
  754. {
  755.   AddGSACode dlg;
  756.   dlg.DoModal();
  757.   refresh();
  758. }
  759.  
  760. void GBACheatList::OnEnable() 
  761. {
  762.   int mark = m_list.GetSelectionMark();
  763.   int count = m_list.GetItemCount();
  764.   
  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(item.lParam);
  776.           else
  777.             cheatsEnable(item.lParam);
  778.         }
  779.       }
  780.     }
  781.     refresh();
  782.   }
  783. }
  784.  
  785. void GBACheatList::OnRemove() 
  786. {
  787.   int mark = m_list.GetSelectionMark();
  788.   int count = m_list.GetItemCount();
  789.   
  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(item.lParam, restoreValues);
  800.         }
  801.       }
  802.     }
  803.     refresh();
  804.   }         
  805. }
  806.  
  807. void GBACheatList::OnRemoveAll() 
  808. {
  809.   cheatsDeleteAll(restoreValues);
  810.   refresh();
  811. }
  812.  
  813.  
  814. void GBACheatList::OnRestore() 
  815. {
  816.   restoreValues = !restoreValues;
  817.   regSetDwordValue("cheatsRestore", restoreValues);
  818. }
  819.  
  820. void GBACheatList::OnOk() 
  821. {
  822.   EndDialog(TRUE);
  823. }
  824.  
  825. void GBACheatList::OnItemchangedCheatList(NMHDR* pNMHDR, LRESULT* pResult) 
  826. {
  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);
  833.   }
  834.   
  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(l->lParam);
  842.         else
  843.           cheatsDisable(l->lParam);
  844.         refresh();
  845.       }
  846.     }
  847.   }
  848.   
  849.   *pResult = 0;
  850. }
  851.  
  852. BOOL GBACheatList::OnInitDialog() 
  853. {
  854.   CDialog::OnInitDialog();
  855.   
  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);
  862.   
  863.   m_list.SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT)),
  864.                  TRUE);
  865.  
  866.   m_list.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);  
  867.   
  868.   restoreValues = regQueryDwordValue("cheatsRestore", 0) ?
  869.     true : false;
  870.   
  871.   m_restore.SetCheck(restoreValues);
  872.   
  873.   refresh();
  874.   GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE);
  875.   GetDlgItem(IDC_ENABLE)->EnableWindow(FALSE);
  876.   CenterWindow();
  877.   
  878.   return TRUE;  // return TRUE unless you set the focus to a control
  879.                 // EXCEPTION: OCX Property Pages should return FALSE
  880. }
  881.  
  882. void GBACheatList::refresh()
  883. {
  884.   duringRefresh = true;
  885.   m_list.DeleteAllItems();
  886.   
  887.   CString buffer;
  888.   
  889.   for(int i = 0; i < cheatsNumber; i++) {
  890.     LVITEM item;
  891.  
  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);
  900.  
  901.     m_list.SetCheck(i, (cheatsList[i].enabled) ? TRUE : FALSE);
  902.  
  903.     m_list.SetItemText(i, 1, cheatsList[i].desc);
  904.     
  905.     buffer = (cheatsList[i].enabled) ? 'E' : 'D';    
  906.     m_list.SetItemText(i, 2, buffer);
  907.   }
  908.   duringRefresh = false;
  909. }
  910. /////////////////////////////////////////////////////////////////////////////
  911. // AddGSACode dialog
  912.  
  913.  
  914. AddGSACode::AddGSACode(CWnd* pParent /*=NULL*/)
  915.   : CDialog(AddGSACode::IDD, pParent)
  916. {
  917.   //{{AFX_DATA_INIT(AddGSACode)
  918.   // NOTE: the ClassWizard will add member initialization here
  919.   //}}AFX_DATA_INIT
  920. }
  921.  
  922.  
  923. void AddGSACode::DoDataExchange(CDataExchange* pDX)
  924. {
  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
  930. }
  931.  
  932.  
  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()
  939.  
  940.   /////////////////////////////////////////////////////////////////////////////
  941. // AddGSACode message handlers
  942.  
  943. void AddGSACode::OnOk() 
  944. {
  945.   CString desc;
  946.   CString buffer;
  947.   CString part1;
  948.   CString code;
  949.   CString token;  
  950.  
  951.   m_code.GetWindowText(buffer);
  952.   m_desc.GetWindowText(desc);
  953.   
  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);
  978.       }
  979.       part1.Empty();
  980.     }
  981.  
  982.     t = st.next();
  983.   }
  984.   EndDialog(TRUE);
  985. }
  986.  
  987. void AddGSACode::OnCancel() 
  988. {
  989.   EndDialog(FALSE);
  990. }
  991.  
  992. BOOL AddGSACode::OnInitDialog() 
  993. {
  994.   CDialog::OnInitDialog();
  995.   
  996.   m_code.LimitText(1024);
  997.   m_desc.LimitText(32);
  998.   CString title = winResLoadString(IDS_ADD_GSA_CODE);
  999.   SetWindowText(title);
  1000.   CenterWindow();
  1001.   
  1002.   return TRUE;  // return TRUE unless you set the focus to a control
  1003.                 // EXCEPTION: OCX Property Pages should return FALSE
  1004. }
  1005.  
  1006. /////////////////////////////////////////////////////////////////////////////
  1007. // AddCBACode dialog
  1008.  
  1009.  
  1010. AddCBACode::AddCBACode(CWnd* pParent /*=NULL*/)
  1011.   : CDialog(AddCBACode::IDD, pParent)
  1012. {
  1013.   //{{AFX_DATA_INIT(AddCBACode)
  1014.   // NOTE: the ClassWizard will add member initialization here
  1015.   //}}AFX_DATA_INIT
  1016. }
  1017.  
  1018.  
  1019. void AddCBACode::DoDataExchange(CDataExchange* pDX)
  1020. {
  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
  1026. }
  1027.  
  1028.  
  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()
  1035.  
  1036.   /////////////////////////////////////////////////////////////////////////////
  1037. // AddCBACode message handlers
  1038.  
  1039. void AddCBACode::OnOk() 
  1040. {
  1041.   CString desc;
  1042.   CString buffer;
  1043.   CString part1;
  1044.   CString code;
  1045.   CString token;
  1046.  
  1047.   m_code.GetWindowText(buffer);
  1048.   m_desc.GetWindowText(desc);
  1049.   
  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);
  1074.       }
  1075.       part1.Empty();
  1076.     }
  1077.  
  1078.     t = st.next();
  1079.   }
  1080.   EndDialog(TRUE);
  1081. }
  1082.  
  1083. void AddCBACode::OnCancel() 
  1084. {
  1085.   EndDialog(FALSE);
  1086. }
  1087.  
  1088. BOOL AddCBACode::OnInitDialog() 
  1089. {
  1090.   CDialog::OnInitDialog();
  1091.   
  1092.   m_code.LimitText(1024);
  1093.   m_desc.LimitText(32);
  1094.   CString title = winResLoadString(IDS_ADD_CBA_CODE);
  1095.   SetWindowText(title);
  1096.   CenterWindow();
  1097.   
  1098.   return TRUE;  // return TRUE unless you set the focus to a control
  1099.                 // EXCEPTION: OCX Property Pages should return FALSE
  1100. }
  1101.  
  1102. /////////////////////////////////////////////////////////////////////////////
  1103. // AddCheatCode dialog
  1104.  
  1105.  
  1106. AddCheatCode::AddCheatCode(CWnd* pParent /*=NULL*/)
  1107.   : CDialog(AddCheatCode::IDD, pParent)
  1108. {
  1109.   //{{AFX_DATA_INIT(AddCheatCode)
  1110.   // NOTE: the ClassWizard will add member initialization here
  1111.   //}}AFX_DATA_INIT
  1112. }
  1113.  
  1114.  
  1115. void AddCheatCode::DoDataExchange(CDataExchange* pDX)
  1116. {
  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
  1122. }
  1123.  
  1124.  
  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()
  1131.  
  1132.   /////////////////////////////////////////////////////////////////////////////
  1133. // AddCheatCode message handlers
  1134.  
  1135. void AddCheatCode::OnOk() 
  1136. {
  1137.   CString desc;
  1138.   CString buffer;
  1139.   CString token;
  1140.  
  1141.   m_code.GetWindowText(buffer);
  1142.   m_desc.GetWindowText(desc);
  1143.   
  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();
  1151.   }
  1152.   EndDialog(TRUE);
  1153. }
  1154.  
  1155. void AddCheatCode::OnCancel() 
  1156. {
  1157.   EndDialog(FALSE);
  1158. }
  1159.  
  1160. BOOL AddCheatCode::OnInitDialog() 
  1161. {
  1162.   CDialog::OnInitDialog();
  1163.   
  1164.   m_code.LimitText(1024);
  1165.   m_desc.LimitText(32);
  1166.   CString title = winResLoadString(IDS_ADD_CHEAT_CODE);
  1167.   SetWindowText(title);
  1168.   CenterWindow();
  1169.   
  1170.   return TRUE;  // return TRUE unless you set the focus to a control
  1171.                 // EXCEPTION: OCX Property Pages should return FALSE
  1172. }
  1173.