home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / Cheats.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  43.2 KB  |  1,675 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. #include <memory.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23.  
  24. #include "GBA.h"
  25. #include "GBAinline.h"
  26. #include "Cheats.h"
  27. #include "Globals.h"
  28. #include "NLS.h"
  29. #include "Util.h"
  30.  
  31. /**
  32.  * Gameshark code types:
  33.  *
  34.  * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM
  35.  * DEADFACE XXXXXXXX - changes decryption seeds
  36.  * 0AAAAAAA 000000YY - 8-bit constant write
  37.  * 1AAAAAAA 0000YYYY - 16-bit constant write
  38.  * 2AAAAAAA YYYYYYYY - 32-bit constant write
  39.  * 3AAAAAAA YYYYYYYY - ??
  40.  * 6AAAAAAA 0000YYYY - 16-bit ROM Patch (address >> 1)
  41.  * 6AAAAAAA 1000YYYY - 16-bit ROM Patch ? (address >> 1)
  42.  * 6AAAAAAA 2000YYYY - 16-bit ROM Patch ? (address >> 1)
  43.  * 8A1AAAAA 000000YY - 8-bit button write
  44.  * 8A2AAAAA 0000YYYY - 16-bit button write
  45.  * 8A3AAAAA YYYYYYYY - 32-bit button write
  46.  * 80F00000 0000YYYY - button slow motion
  47.  * DAAAAAAA 0000YYYY - if address contains 16-bit value enable next code
  48.  * FAAAAAAA 0000YYYY - Master code function
  49.  *
  50.  * CodeBreaker codes types:
  51.  *
  52.  * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI)
  53.  * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16)
  54.  *                 + 0x08000100))
  55.  * 2AAAAAAA YYYY - 16-bit or
  56.  * 3AAAAAAA YYYY - 8-bit constant write
  57.  * 4AAAAAAA YYYY - Slide code
  58.  * XXXXCCCC IIII   (C is count and I is address increment, X is value incr.)
  59.  * 5AAAAAAA CCCC - Super code (Write bytes to address, CCCC is count)
  60.  * BBBBBBBB BBBB 
  61.  * 6AAAAAAA YYYY - 16-bit and
  62.  * 7AAAAAAA YYYY - if address contains 16-bit value enable next code
  63.  * 8AAAAAAA YYYY - 16-bit constant write
  64.  * 9AAAAAAA YYYY - change decryption (when first code only?)
  65.  * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code
  66.  * BAAAAAAA YYYY - if 16-bit < YYYY
  67.  * CAAAAAAA YYYY - if 16-bit > YYYY
  68.  * D0000020 YYYY - if button keys equal value enable next code
  69.  * EAAAAAAA YYYY - increase value stored in address
  70.  */
  71. #define UNKNOWN_CODE           -1
  72. #define INT_8_BIT_WRITE        0
  73. #define INT_16_BIT_WRITE       1
  74. #define INT_32_BIT_WRITE       2
  75. #define GSA_16_BIT_ROM_PATCH   3
  76. #define GSA_8_BIT_GS_WRITE     4
  77. #define GSA_16_BIT_GS_WRITE    5
  78. #define GSA_32_BIT_GS_WRITE    6
  79. #define CBA_IF_KEYS_PRESSED    7
  80. #define CBA_IF_TRUE            8
  81. #define CBA_SLIDE_CODE         9
  82. #define CBA_IF_FALSE           10
  83. #define CBA_AND                11
  84. #define GSA_8_BIT_GS_WRITE2    12
  85. #define GSA_16_BIT_GS_WRITE2   13
  86. #define GSA_32_BIT_GS_WRITE2   14
  87. #define GSA_16_BIT_ROM_PATCH2  15
  88. #define GSA_8_BIT_SLIDE        16
  89. #define GSA_16_BIT_SLIDE       17
  90. #define GSA_32_BIT_SLIDE       18
  91. #define GSA_8_BIT_IF_TRUE      19
  92. #define GSA_32_BIT_IF_TRUE     20
  93. #define GSA_8_BIT_IF_FALSE     21
  94. #define GSA_32_BIT_IF_FALSE    22
  95. #define GSA_8_BIT_FILL         23
  96. #define GSA_16_BIT_FILL        24
  97. #define GSA_8_BIT_IF_TRUE2     25
  98. #define GSA_16_BIT_IF_TRUE2    26
  99. #define GSA_32_BIT_IF_TRUE2    27
  100. #define GSA_8_BIT_IF_FALSE2    28
  101. #define GSA_16_BIT_IF_FALSE2   29
  102. #define GSA_32_BIT_IF_FALSE2   30
  103. #define GSA_SLOWDOWN           31
  104. #define CBA_ADD                32
  105. #define CBA_OR                 33
  106. #define CBA_LT                 34
  107. #define CBA_GT                 35 
  108. #define CBA_SUPER              36
  109.  
  110. CheatsData cheatsList[100];
  111. int cheatsNumber = 0;
  112.  
  113. u8 cheatsCBASeedBuffer[0x30];
  114. u32 cheatsCBASeed[4];
  115. u32 cheatsCBATemporaryValue = 0;
  116. u16 cheatsCBATable[256];
  117. bool cheatsCBATableGenerated = false;
  118.  
  119. u8 cheatsCBACurrentSeed[12] = {
  120.   0x00, 0x00, 0x00, 0x00,
  121.   0x00, 0x00, 0x00, 0x00,
  122.   0x00, 0x00, 0x00, 0x00
  123. };
  124.  
  125. #define CHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9'))
  126.  
  127. #define CHEAT_PATCH_ROM_16BIT(a,v) \
  128.   WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v); 
  129.  
  130. static bool isMultilineWithData(int i)
  131. {
  132.   // we consider it a multiline code if it has more than one line of data
  133.   // otherwise, it can still be considered a single code
  134.   if(i < cheatsNumber && i >= 0)
  135.     switch(cheatsList[i].size) {
  136.     case INT_8_BIT_WRITE:
  137.     case INT_16_BIT_WRITE:
  138.     case INT_32_BIT_WRITE:
  139.     case GSA_16_BIT_ROM_PATCH:
  140.     case GSA_8_BIT_GS_WRITE:
  141.     case GSA_16_BIT_GS_WRITE:
  142.     case GSA_32_BIT_GS_WRITE:
  143.     case CBA_AND:
  144.     case CBA_IF_KEYS_PRESSED:
  145.     case CBA_IF_TRUE:
  146.     case CBA_IF_FALSE:
  147.     case GSA_8_BIT_IF_TRUE:
  148.     case GSA_32_BIT_IF_TRUE:
  149.     case GSA_8_BIT_IF_FALSE:
  150.     case GSA_32_BIT_IF_FALSE:
  151.     case GSA_8_BIT_FILL:
  152.     case GSA_16_BIT_FILL:
  153.     case GSA_8_BIT_IF_TRUE2:
  154.     case GSA_16_BIT_IF_TRUE2:
  155.     case GSA_32_BIT_IF_TRUE2:
  156.     case GSA_8_BIT_IF_FALSE2:
  157.     case GSA_16_BIT_IF_FALSE2:
  158.     case GSA_32_BIT_IF_FALSE2:
  159.     case GSA_SLOWDOWN:
  160.     case CBA_ADD:
  161.     case CBA_OR:
  162.       return false;
  163.       // the codes below have two lines of data
  164.     case CBA_SLIDE_CODE:
  165.     case GSA_8_BIT_GS_WRITE2:
  166.     case GSA_16_BIT_GS_WRITE2:
  167.     case GSA_32_BIT_GS_WRITE2:
  168.     case GSA_16_BIT_ROM_PATCH2:
  169.     case GSA_8_BIT_SLIDE:
  170.     case GSA_16_BIT_SLIDE:
  171.     case GSA_32_BIT_SLIDE:
  172.     case CBA_LT:
  173.     case CBA_GT:
  174.     case CBA_SUPER:
  175.       return true;
  176.     }
  177.   return false;
  178. }
  179.  
  180. static int getCodeLength(int num)
  181. {
  182.   if(num >= cheatsNumber || num < 0)
  183.     return 1;
  184.  
  185.   // this is for all the codes that are true multiline
  186.   switch(cheatsList[num].size) {
  187.   case INT_8_BIT_WRITE:
  188.   case INT_16_BIT_WRITE:
  189.   case INT_32_BIT_WRITE:
  190.   case GSA_16_BIT_ROM_PATCH:
  191.   case GSA_8_BIT_GS_WRITE:
  192.   case GSA_16_BIT_GS_WRITE:
  193.   case GSA_32_BIT_GS_WRITE:
  194.   case CBA_AND:
  195.   case GSA_8_BIT_FILL:
  196.   case GSA_16_BIT_FILL:
  197.   case GSA_SLOWDOWN:
  198.   case CBA_ADD:
  199.   case CBA_OR:
  200.     return 1;
  201.   case CBA_IF_KEYS_PRESSED:
  202.   case CBA_IF_TRUE:
  203.   case CBA_IF_FALSE:
  204.   case CBA_SLIDE_CODE:
  205.   case GSA_8_BIT_GS_WRITE2:
  206.   case GSA_16_BIT_GS_WRITE2:
  207.   case GSA_32_BIT_GS_WRITE2:
  208.   case GSA_16_BIT_ROM_PATCH2:
  209.   case GSA_8_BIT_SLIDE:
  210.   case GSA_16_BIT_SLIDE:
  211.   case GSA_32_BIT_SLIDE:
  212.   case GSA_8_BIT_IF_TRUE:
  213.   case GSA_32_BIT_IF_TRUE:
  214.   case GSA_8_BIT_IF_FALSE:
  215.   case GSA_32_BIT_IF_FALSE:
  216.   case CBA_LT:
  217.   case CBA_GT:
  218.     return 2;
  219.   case GSA_8_BIT_IF_TRUE2:
  220.   case GSA_16_BIT_IF_TRUE2:
  221.   case GSA_32_BIT_IF_TRUE2:
  222.   case GSA_8_BIT_IF_FALSE2:
  223.   case GSA_16_BIT_IF_FALSE2:
  224.   case GSA_32_BIT_IF_FALSE2:
  225.     return 3;
  226.   case CBA_SUPER:
  227.     return (cheatsList[num].value+5)/6;
  228.   }
  229.   return 1;
  230. }
  231.  
  232. int cheatsCheckKeys(u32 keys, u32 extended)
  233. {
  234.   int ticks = 0;
  235.   for(int i = 0; i < cheatsNumber; i++) {
  236.     if(!cheatsList[i].enabled) {
  237.       // make sure we skip other lines in this code
  238.       i += getCodeLength(i)-1;
  239.       continue;
  240.     }
  241.     switch(cheatsList[i].size) {
  242.     case INT_8_BIT_WRITE:
  243.       CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
  244.       break;
  245.     case INT_16_BIT_WRITE:
  246.       CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
  247.       break;
  248.     case INT_32_BIT_WRITE:
  249.       CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
  250.       break;
  251.     case GSA_16_BIT_ROM_PATCH:
  252.       if((cheatsList[i].status & 1) == 0) {
  253.         if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
  254.           cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address);
  255.           cheatsList[i].status |= 1;
  256.           CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
  257.         }
  258.       }
  259.       break;
  260.     case GSA_8_BIT_GS_WRITE:
  261.       if(extended & 4) {
  262.         CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
  263.       }
  264.       break;
  265.     case GSA_16_BIT_GS_WRITE:
  266.       if(extended & 4) {
  267.         CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);   
  268.       }
  269.       break;
  270.     case GSA_32_BIT_GS_WRITE:
  271.       if(extended & 4) {
  272.         CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);     
  273.       }
  274.       break;
  275.     case CBA_IF_KEYS_PRESSED:
  276.       {
  277.         u16 value = cheatsList[i].value;
  278.         u32 addr = cheatsList[i].address;
  279.         if((addr & 0x30) == 0x20) {
  280.           if((keys & value) != value) {
  281.             i++;
  282.           }
  283.         } else if((addr & 0x30) == 0x10) {
  284.           if((keys & value) == value) {
  285.             i++;
  286.           }
  287.         }
  288.       }
  289.       break;
  290.     case CBA_IF_TRUE:
  291.       if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
  292.         i++;
  293.       }
  294.       break;
  295.     case CBA_SLIDE_CODE:
  296.       {
  297.         u32 address = cheatsList[i].address;
  298.         u16 value = cheatsList[i].value;
  299.         i++;
  300.         if(i < cheatsNumber) {
  301.           int count = (cheatsList[i].address & 0xFFFF);
  302.           u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF;
  303.           int inc = cheatsList[i].value;
  304.  
  305.           for(int x = 0; x < count; x++) {
  306.             CPUWriteHalfWord(address, value);
  307.             address += inc;
  308.             value += vinc;
  309.           }
  310.         }
  311.       }
  312.       break;
  313.     case CBA_IF_FALSE:
  314.       if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
  315.         i++;
  316.       }
  317.       break;
  318.     case CBA_AND:
  319.       CPUWriteHalfWord(cheatsList[i].address,
  320.                        CPUReadHalfWord(cheatsList[i].address) &
  321.                        cheatsList[i].value);
  322.       break;
  323.     case GSA_8_BIT_GS_WRITE2:
  324.       i++;
  325.       if(i < cheatsNumber) {
  326.         if(extended & 4) {
  327.           CPUWriteByte(cheatsList[i-1].value, cheatsList[i].address);
  328.         }
  329.       }
  330.       break;
  331.     case GSA_16_BIT_GS_WRITE2:
  332.       i++;
  333.       if(i < cheatsNumber) {
  334.         if(extended & 4) {
  335.           CPUWriteHalfWord(cheatsList[i-1].value, cheatsList[i].address);
  336.         }
  337.       }
  338.       break;
  339.     case GSA_32_BIT_GS_WRITE2:
  340.       i++;
  341.       if(i < cheatsNumber) {
  342.         if(extended & 4) {
  343.           CPUWriteMemory(cheatsList[i-1].value, cheatsList[i].address);
  344.         }
  345.       }
  346.       break;
  347.     case GSA_16_BIT_ROM_PATCH2:
  348.       i++;
  349.       if(i < cheatsNumber) {
  350.         if((cheatsList[i-1].status & 1) == 0) {
  351.           u32 addr = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
  352.           if(CPUReadHalfWord(addr) != (cheatsList[i].address & 0xFFFF)) {
  353.             cheatsList[i-1].oldValue = CPUReadHalfWord(addr);
  354.             cheatsList[i-1].status |= 1;
  355.             CHEAT_PATCH_ROM_16BIT(addr,cheatsList[i].address & 0xFFFF);
  356.           }
  357.         }
  358.       }
  359.       break;
  360.     case GSA_8_BIT_SLIDE:
  361.       i++;
  362.       if(i < cheatsNumber) {
  363.         u32 addr = cheatsList[i-1].value;
  364.         u8 value = cheatsList[i].address;
  365.         int vinc = (cheatsList[i].value >> 24) & 255;
  366.         int count = (cheatsList[i].value >> 16) & 255;
  367.         int ainc = (cheatsList[i].value & 0xffff);
  368.         while(count > 0) {
  369.           CPUWriteByte(addr, value);
  370.           value += vinc;
  371.           addr += ainc;
  372.           count--;
  373.         }
  374.       }
  375.       break;
  376.     case GSA_16_BIT_SLIDE:
  377.       i++;
  378.       if(i < cheatsNumber) {
  379.         u32 addr = cheatsList[i-1].value;
  380.         u16 value = cheatsList[i].address;
  381.         int vinc = (cheatsList[i].value >> 24) & 255;
  382.         int count = (cheatsList[i].value >> 16) & 255;
  383.         int ainc = (cheatsList[i].value & 0xffff)*2;
  384.         while(count > 0) {
  385.           CPUWriteHalfWord(addr, value);
  386.           value += vinc;
  387.           addr += ainc;
  388.           count--;
  389.         }
  390.       }
  391.       break;
  392.     case GSA_32_BIT_SLIDE:
  393.       i++;
  394.       if(i < cheatsNumber) {
  395.         u32 addr = cheatsList[i-1].value;
  396.         u32 value = cheatsList[i].address;
  397.         int vinc = (cheatsList[i].value >> 24) & 255;
  398.         int count = (cheatsList[i].value >> 16) & 255;
  399.         int ainc = (cheatsList[i].value & 0xffff)*4;
  400.         while(count > 0) {
  401.           CPUWriteMemory(addr, value);
  402.           value += vinc;
  403.           addr += ainc;
  404.           count--;
  405.         }
  406.       }
  407.       break;
  408.     case GSA_8_BIT_IF_TRUE:
  409.       if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
  410.         i++;
  411.       }
  412.       break;
  413.     case GSA_32_BIT_IF_TRUE:
  414.       if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
  415.         i++;
  416.       }
  417.       break;
  418.     case GSA_8_BIT_IF_FALSE:
  419.       if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
  420.         i++;
  421.       }
  422.       break;
  423.     case GSA_32_BIT_IF_FALSE:
  424.       if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
  425.         i++;
  426.       }
  427.       break;
  428.     case GSA_8_BIT_FILL:
  429.       {
  430.         u32 addr = cheatsList[i].address;
  431.         u8 v = cheatsList[i].value & 0xff;
  432.         u32 end = addr + (cheatsList[i].value >> 8);
  433.         do {
  434.           CPUWriteByte(addr, v);
  435.           addr++;
  436.         } while (addr <= end);
  437.       }
  438.       break;
  439.     case GSA_16_BIT_FILL:
  440.       {
  441.         u32 addr = cheatsList[i].address;
  442.         u16 v = cheatsList[i].value & 0xffff;
  443.         u32 end = addr + ((cheatsList[i].value >> 16) << 1);
  444.         do {
  445.           CPUWriteHalfWord(addr, v);
  446.           addr+=2;
  447.         } while (addr <= end);
  448.       }
  449.       break;
  450.     case GSA_8_BIT_IF_TRUE2:
  451.       if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
  452.         i+=2;
  453.       }
  454.       break;
  455.     case GSA_16_BIT_IF_TRUE2:
  456.       if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
  457.         i+=2;
  458.       }
  459.       break;
  460.     case GSA_32_BIT_IF_TRUE2:
  461.       if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
  462.         i+=2;
  463.       }
  464.       break;
  465.     case GSA_8_BIT_IF_FALSE2:
  466.       if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
  467.         i+=2;
  468.       }
  469.       break;
  470.     case GSA_16_BIT_IF_FALSE2:
  471.       if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
  472.         i+=2;
  473.       }
  474.       break;
  475.     case GSA_32_BIT_IF_FALSE2:
  476.       if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
  477.         i+=2;
  478.       }
  479.       break;
  480.     case GSA_SLOWDOWN:
  481.       // check if button was pressed and released, if so toggle our state
  482.       if((cheatsList[i].status & 4) && !(extended & 4))
  483.         cheatsList[i].status ^= 1;
  484.       if(extended & 4)
  485.         cheatsList[i].status |= 4;
  486.       else
  487.         cheatsList[i].status &= ~4;
  488.       
  489.       if(cheatsList[i].status & 1)
  490.         ticks += 2*256*((cheatsList[i].value >> 8) & 255);
  491.       break;
  492.     case CBA_ADD:
  493.       CPUWriteHalfWord(cheatsList[i].address, 
  494.                        CPUReadHalfWord(cheatsList[i].address) +
  495.                        (u16)cheatsList[i].value);
  496.       break;
  497.     case CBA_OR:
  498.       CPUWriteHalfWord(cheatsList[i].address,
  499.                        CPUReadHalfWord(cheatsList[i].address) |
  500.                        cheatsList[i].value);
  501.       break;
  502.     case CBA_LT:
  503.       if(CPUReadHalfWord(cheatsList[i].address) >= cheatsList[i].value)
  504.         i++;
  505.       break;
  506.     case CBA_GT:
  507.       if(CPUReadHalfWord(cheatsList[i].address) <= cheatsList[i].value)
  508.         i++;
  509.       break;
  510.     case CBA_SUPER:
  511.       {
  512.         int count = 2*cheatsList[i].value;
  513.         u32 address = cheatsList[i].address;
  514.         for(int x = 0; x < count; x++) {
  515.           u8 b;
  516.           int res = x % 6;
  517.           if(res < 4)
  518.             b = (cheatsList[i].address >> (24-8*res)) & 0xFF;
  519.           else
  520.             b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0x0FF;
  521.           CPUWriteByte(address, b);
  522.           address++;
  523.           if(x && !res)
  524.             i++;
  525.         }
  526.         if(count % 6)
  527.           i++;
  528.       }
  529.       break;
  530.     }
  531.   }
  532.   return ticks;
  533. }
  534.  
  535. void cheatsAdd(const char *codeStr,
  536.                const char *desc,
  537.                u32 address,
  538.                u32 value,
  539.                int code,
  540.                int size)
  541. {
  542.   if(cheatsNumber < 100) {
  543.     int x = cheatsNumber;
  544.     cheatsList[x].code = code;
  545.     cheatsList[x].size = size;
  546.     cheatsList[x].address = address;
  547.     cheatsList[x].value = value;
  548.     strcpy(cheatsList[x].codestring, codeStr);
  549.     strcpy(cheatsList[x].desc, desc);
  550.     cheatsList[x].enabled = true;
  551.     cheatsList[x].status = 0;
  552.  
  553.     // we only store the old value for this simple codes. ROM patching
  554.     // is taken care when it actually patches the ROM
  555.     switch(cheatsList[x].size) {
  556.     case INT_8_BIT_WRITE:
  557.       cheatsList[x].oldValue = CPUReadByte(address);
  558.       break;
  559.     case INT_16_BIT_WRITE:
  560.       cheatsList[x].oldValue = CPUReadHalfWord(address);
  561.       break;
  562.     case INT_32_BIT_WRITE:
  563.       cheatsList[x].oldValue = CPUReadMemory(address);
  564.       break;
  565.     }
  566.     cheatsNumber++;
  567.   }
  568. }
  569.  
  570. void cheatsDelete(int number, bool restore)
  571. {
  572.   if(number < cheatsNumber && number >= 0) {
  573.     int x = number;
  574.  
  575.     if(restore) {
  576.       switch(cheatsList[x].size) {
  577.       case INT_8_BIT_WRITE:
  578.         CPUWriteByte(cheatsList[x].address, (u8)cheatsList[x].oldValue);
  579.         break;
  580.       case INT_16_BIT_WRITE:
  581.         CPUWriteHalfWord(cheatsList[x].address, (u16)cheatsList[x].oldValue);
  582.         break;
  583.       case INT_32_BIT_WRITE:
  584.         CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
  585.         break;
  586.       case GSA_16_BIT_ROM_PATCH:
  587.         if(cheatsList[x].status & 1) {
  588.           cheatsList[x].status &= ~1;
  589.           CHEAT_PATCH_ROM_16BIT(cheatsList[x].address,
  590.                                 cheatsList[x].oldValue);  
  591.         }
  592.         break;
  593.       case GSA_16_BIT_ROM_PATCH2:
  594.         if(cheatsList[x].status & 1) {
  595.           cheatsList[x].status &= ~1;
  596.           CHEAT_PATCH_ROM_16BIT(((cheatsList[x].value & 0x00FFFFFF) << 1)+
  597.                                 0x8000000,
  598.                                 cheatsList[x].oldValue);
  599.         }
  600.         break;
  601.       }
  602.     }
  603.     if((x+1) <  cheatsNumber) {
  604.       memcpy(&cheatsList[x], &cheatsList[x+1], sizeof(CheatsData)*
  605.              (cheatsNumber-x-1));
  606.     }
  607.     cheatsNumber--;
  608.   }
  609. }
  610.  
  611. void cheatsDeleteAll(bool restore)
  612. {
  613.   for(int i = cheatsNumber-1; i >= 0; i--) {
  614.     cheatsDelete(i, restore);
  615.   }
  616. }
  617.  
  618. void cheatsEnable(int i)
  619. {
  620.   if(i >= 0 && i < cheatsNumber) {
  621.     cheatsList[i].enabled = true;
  622.   }
  623. }
  624.  
  625. void cheatsDisable(int i)
  626. {
  627.   if(i >= 0 && i < cheatsNumber) {
  628.     switch(cheatsList[i].size) {
  629.     case GSA_16_BIT_ROM_PATCH:
  630.       if(cheatsList[i].status & 1) {
  631.         cheatsList[i].status &= ~1;
  632.         CHEAT_PATCH_ROM_16BIT(cheatsList[i].address,
  633.                               cheatsList[i].oldValue);
  634.       }
  635.       break;
  636.     case GSA_16_BIT_ROM_PATCH2:
  637.       if(cheatsList[i].status & 1) {
  638.         cheatsList[i].status &= ~1;
  639.         CHEAT_PATCH_ROM_16BIT(((cheatsList[i].value & 0x00FFFFFF) << 1)+
  640.                               0x8000000,
  641.                               cheatsList[i].oldValue);
  642.       }
  643.       break;
  644.     }
  645.     cheatsList[i].enabled = false;
  646.   }
  647. }
  648.  
  649. bool cheatsVerifyCheatCode(const char *code, const char *desc)
  650. {
  651.   int len = strlen(code);
  652.   if(len != 11 && len != 13 && len != 17) {
  653.     systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
  654.     return false;
  655.   }
  656.  
  657.   if(code[8] != ':') {
  658.     systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
  659.     return false;    
  660.   }
  661.  
  662.   int i;
  663.   for(i = 0; i < 8; i++) {
  664.     if(!CHEAT_IS_HEX(code[i])) {
  665.       // wrong cheat
  666.       systemMessage(MSG_INVALID_CHEAT_CODE,
  667.                     N_("Invalid cheat code '%s'"), code);
  668.       return false;
  669.     }
  670.   }
  671.   for(i = 9; i < len; i++) {
  672.     if(!CHEAT_IS_HEX(code[i])) {
  673.       // wrong cheat
  674.       systemMessage(MSG_INVALID_CHEAT_CODE,
  675.                     N_("Invalid cheat code '%s'"), code);
  676.       return false;
  677.     }
  678.   }
  679.   
  680.   u32 address = 0;
  681.   u32 value = 0;
  682.   
  683.   char buffer[10];
  684.   strncpy(buffer, code, 8);
  685.   buffer[8] = 0;
  686.   sscanf(buffer, "%x", &address);
  687.  
  688.   switch(address >> 24) {
  689.   case 2:
  690.   case 3:
  691.     break;
  692.   default:
  693.     systemMessage(MSG_INVALID_CHEAT_CODE_ADDRESS,
  694.                   N_("Invalid cheat code address: %08x"),
  695.                   address);
  696.     return false;
  697.   }
  698.   
  699.   strncpy(buffer, &code[9], 8);  
  700.   sscanf(buffer, "%x", &value);
  701.   int type = 0;
  702.   if(len == 13)
  703.     type = 1;
  704.   if(len == 17)
  705.     type = 2;
  706.   cheatsAdd(code, desc, address, value, type, type);
  707.   return true;
  708. }
  709.  
  710. void cheatsAddCheatCode(const char *code, const char *desc)
  711. {
  712.   cheatsVerifyCheatCode(code, desc);
  713. }
  714.  
  715. void cheatsDecryptGSACode(u32& address, u32& value, bool v3) 
  716. {
  717.   u32 rollingseed = 0xC6EF3720;
  718.   u32 seeds_v1[] =  { 0x09F4FBBD, 0x9681884A, 0x352027E9, 0xF3DEE5A7 }; 
  719.   u32 seeds_v3[] = { 0x7AA9648F, 0x7FAE6994, 0xC0EFAAD5, 0x42712C57 };
  720.   u32 *seeds = v3 ? seeds_v3 : seeds_v1;
  721.   
  722.   int bitsleft = 32;
  723.   while (bitsleft > 0) {
  724.     value -= ((((address << 4) + seeds[2]) ^ (address + rollingseed)) ^
  725.               ((address >> 5) + seeds[3]));
  726.     address -= ((((value << 4) + seeds[0]) ^ (value + rollingseed)) ^
  727.                 ((value >> 5) + seeds[1]));
  728.     rollingseed -= 0x9E3779B9;
  729.     bitsleft--;
  730.   }
  731. }
  732.  
  733. void cheatsAddGSACode(const char *code, const char *desc, bool v3)
  734. {
  735.   if(strlen(code) != 16) {
  736.     // wrong cheat
  737.     systemMessage(MSG_INVALID_GSA_CODE,
  738.                   N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
  739.     return;
  740.   }
  741.   
  742.   int i;
  743.   for(i = 0; i < 16; i++) {
  744.     if(!CHEAT_IS_HEX(code[i])) {
  745.       // wrong cheat
  746.       systemMessage(MSG_INVALID_GSA_CODE,
  747.                     N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
  748.       return;
  749.     }
  750.   }
  751.   
  752.   char buffer[10];
  753.   strncpy(buffer, code, 8);
  754.   buffer[8] = 0;
  755.   u32 address;
  756.   sscanf(buffer, "%x", &address);
  757.   strncpy(buffer, &code[8], 8);
  758.   buffer[8] = 0;
  759.   u32 value;
  760.   sscanf(buffer, "%x", &value);
  761.  
  762.   cheatsDecryptGSACode(address, value, v3);
  763.  
  764.   if(value == 0x1DC0DE) {
  765.     u32 gamecode = READ32LE(((u32 *)&rom[0xac]));
  766.     if(gamecode != address) {
  767.       char buffer[5];
  768.       *((u32 *)buffer) = address;
  769.       buffer[4] = 0;
  770.       char buffer2[5];
  771.       *((u32 *)buffer2) = READ32LE(((u32 *)&rom[0xac]));
  772.       buffer2[4] = 0;
  773.       systemMessage(MSG_GBA_CODE_WARNING, N_("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly."),
  774.                     buffer, buffer2);
  775.     }
  776.     cheatsAdd(code, desc, address & 0x0FFFFFFF, value, v3 ? 257 : 256, 
  777.               UNKNOWN_CODE);
  778.     return;
  779.   }
  780.   if(isMultilineWithData(cheatsNumber-1)) {
  781.     cheatsAdd(code, desc, address, value, v3 ? 257 : 256, UNKNOWN_CODE);
  782.     return;
  783.   }
  784.   if(v3) {
  785.     int type = (address >> 25) & 127;
  786.     u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF);
  787.     switch(type) {
  788.     case 0x00:
  789.       if(address == 0) {
  790.         type = (value >> 25) & 127;
  791.         addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF);
  792.         switch(type) {
  793.         case 0x04:
  794.           cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN);
  795.           break;
  796.         case 0x08:
  797.           cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_GS_WRITE2);
  798.           break;
  799.         case 0x09:
  800.           cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_GS_WRITE2);
  801.           break;
  802.         case 0x0a:
  803.           cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_GS_WRITE2);
  804.           break;
  805.         case 0x0c:
  806.         case 0x0d:
  807.         case 0x0e:
  808.         case 0x0f:
  809.           cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2);
  810.           break;
  811.         case 0x40:
  812.           cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_SLIDE);
  813.           break;
  814.         case 0x41:
  815.           cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_SLIDE);
  816.           break;
  817.         case 0x42:
  818.           cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_SLIDE);
  819.           break;
  820.         default:
  821.           cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE);
  822.           break;
  823.         }
  824.       } else
  825.         cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_FILL);
  826.       break;
  827.     case 0x01:
  828.       cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_FILL);
  829.       break;
  830.     case 0x02:
  831.       cheatsAdd(code, desc, addr, value, 257, INT_32_BIT_WRITE);
  832.       break;
  833.     case 0x04:
  834.       cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE);
  835.       break;
  836.     case 0x05:
  837.       cheatsAdd(code, desc, addr, value, 257, CBA_IF_TRUE);
  838.       break;
  839.     case 0x06:
  840.       cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE);
  841.       break;
  842.     case 0x08:
  843.       cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE);
  844.       break;
  845.     case 0x09:
  846.       cheatsAdd(code, desc, addr, value, 257, CBA_IF_FALSE);
  847.       break;
  848.     case 0x0a:
  849.       cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE);
  850.       break;
  851.     case 0x24:
  852.       cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE2);
  853.       break;
  854.     case 0x25:
  855.       cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_TRUE2);
  856.       break;
  857.     case 0x26:
  858.       cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE2);
  859.       break;
  860.     case 0x28:
  861.       cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE2);
  862.       break;
  863.     case 0x29:
  864.       cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_FALSE2);
  865.       break;
  866.     case 0x2a:
  867.       cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE2);
  868.       break;
  869.     default:
  870.       cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE);
  871.       break;
  872.     }
  873.   } else {
  874.     int type = (address >> 28) & 15;  
  875.     switch(type) {
  876.     case 0:
  877.     case 1:
  878.     case 2:
  879.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, type);
  880.       break;
  881.     case 6:
  882.       address <<= 1;
  883.       type = (address >> 28) & 15;
  884.       if(type == 0x0c) {
  885.         cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, 
  886.                   GSA_16_BIT_ROM_PATCH);
  887.         break;
  888.       }
  889.       // unsupported code
  890.       cheatsAdd(code, desc, address, value, 256, 
  891.                 UNKNOWN_CODE);
  892.       break;
  893.     case 8:
  894.       switch((address >> 20) & 15) {
  895.       case 1:
  896.         cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, 
  897.                   GSA_8_BIT_GS_WRITE);
  898.         break;
  899.       case 2:
  900.         cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, 
  901.                   GSA_16_BIT_GS_WRITE);
  902.         break;
  903.       case 3:
  904.         cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, 
  905.                   GSA_32_BIT_GS_WRITE);
  906.       case 15:
  907.         cheatsAdd(code, desc, 0, value & 0xFF00, 256, GSA_SLOWDOWN);
  908.         break;
  909.       default:
  910.         // unsupported code
  911.         cheatsAdd(code, desc, address, value, 256, 
  912.                   UNKNOWN_CODE);
  913.         break;
  914.       }
  915.       break;
  916.     case 0x0d:
  917.       if(address != 0xDEADFACE) {
  918.         cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, 
  919.                   CBA_IF_TRUE);
  920.       } else
  921.         cheatsAdd(code, desc, address, value, 256, 
  922.                   UNKNOWN_CODE);
  923.       break;
  924.     default:
  925.       // unsupported code
  926.       cheatsAdd(code, desc, address, value, 256, 
  927.                 UNKNOWN_CODE);
  928.       break;
  929.     }
  930.   }
  931. }
  932.  
  933. bool cheatsImportGSACodeFile(const char *name, int game, bool v3)
  934. {
  935.   FILE *f = fopen(name, "rb");
  936.   if(!f)
  937.     return false;
  938.   
  939.   int games = 0;
  940.   int len = 0;
  941.   fseek(f, 0x1e, SEEK_CUR);
  942.   fread(&games, 1, 4, f);
  943.   bool found = false;
  944.   int g = 0;
  945.   while(games > 0) {
  946.     if(g == game) {
  947.       found = true;
  948.       break;
  949.     }
  950.     fread(&len, 1, 4, f);
  951.     fseek(f,len,SEEK_CUR);
  952.     int codes = 0;
  953.     fread(&codes, 1, 4, f);
  954.     while(codes > 0) {
  955.       fread(&len, 1, 4, f);
  956.       fseek(f, len, SEEK_CUR);
  957.       fseek(f, 8, SEEK_CUR);
  958.       fread(&len, 1, 4, f);
  959.       fseek(f, len*12, SEEK_CUR);
  960.       codes--;
  961.     }
  962.     games--;
  963.     g++;
  964.   }
  965.   if(found) {
  966.     char desc[256];
  967.     char code[17];
  968.     fread(&len, 1, 4, f);
  969.     fseek(f, len, SEEK_CUR);
  970.     int codes = 0;
  971.     fread(&codes, 1, 4, f);
  972.     while(codes > 0) {
  973.       fread(&len, 1, 4, f);
  974.       fread(desc, 1, len, f);
  975.       desc[len] =0;
  976.       desc[31] = 0;
  977.       fread(&len, 1, 4, f);
  978.       fseek(f, len, SEEK_CUR);
  979.       fseek(f, 4, SEEK_CUR);
  980.       fread(&len, 1, 4, f);
  981.       while(len) {
  982.         fseek(f, 4, SEEK_CUR);
  983.         fread(code, 1, 8, f);
  984.         fseek(f, 4, SEEK_CUR);
  985.         fread(&code[8], 1, 8, f);
  986.         code[16] = 0;
  987.         cheatsAddGSACode(code, desc, v3);
  988.         len -= 2;
  989.       }
  990.       codes--;
  991.     }
  992.   }
  993.   fclose(f);
  994.   return false;
  995. }
  996.  
  997. void cheatsCBAReverseArray(u8 *array, u8 *dest)
  998. {
  999.   dest[0] = array[3];
  1000.   dest[1] = array[2];
  1001.   dest[2] = array[1];
  1002.   dest[3] = array[0];
  1003.   dest[4] = array[5];
  1004.   dest[5] = array[4];
  1005. }
  1006.  
  1007. void chatsCBAScramble(u8 *array, int count, u8 b)
  1008. {
  1009.   u8 *x = array + (count >> 3);
  1010.   u8 *y = array + (b >> 3);
  1011.   u32 z = *x & (1 << (count & 7));
  1012.   u32 x0 = (*x & (~(1 << (count & 7))));
  1013.   if (z != 0)
  1014.     z = 1;
  1015.   if ((*y & (1 << (b & 7))) != 0)
  1016.     x0 |= (1 << (count & 7));
  1017.   *x = x0;
  1018.   u32 temp = *y & (~(1 << (b & 7)));
  1019.   if (z != 0)
  1020.     temp |= (1 << (b & 7));
  1021.   *y = temp;
  1022. }
  1023.  
  1024. u32 cheatsCBAGetValue(u8 *array)
  1025. {
  1026.   return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24;
  1027. }
  1028.  
  1029. u16 cheatsCBAGetData(u8 *array)
  1030. {
  1031.   return array[4] | array[5]<<8;
  1032. }
  1033.  
  1034. void cheatsCBAArrayToValue(u8 *array, u8 *dest)
  1035. {
  1036.   dest[0] = array[3];
  1037.   dest[1] = array[2];
  1038.   dest[2] = array[1];
  1039.   dest[3] = array[0];
  1040.   dest[4] = array[5];
  1041.   dest[5] = array[4];
  1042. }
  1043.  
  1044. void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array)
  1045. {
  1046.   array[0] = 1;
  1047.   array[1] = value & 0xFF;
  1048.   array[2] = (address >> 0x10) & 0xFF;
  1049.   array[3] = (value >> 8) & 0xFF;
  1050.   array[4] = (address >> 0x18) & 0x0F;
  1051.   array[5] = address & 0xFFFF;
  1052.   array[6] = address;
  1053.   array[7] = value;
  1054. }
  1055.  
  1056. u32 cheatsCBAEncWorker()
  1057. {
  1058.   u32 x = (cheatsCBATemporaryValue * 0x41c64e6d) + 0x3039;
  1059.   u32 y = (x * 0x41c64e6d) + 0x3039;
  1060.   u32 z = x >> 0x10;
  1061.   x = ((y >> 0x10) & 0x7fff) << 0x0f;
  1062.   z = (z << 0x1e) | x;
  1063.   x = (y * 0x41c64e6d) + 0x3039;
  1064.   cheatsCBATemporaryValue = x;
  1065.   return z | ((x >> 0x10) & 0x7fff);
  1066. }
  1067.  
  1068. #define ROR(v, s) \
  1069.   (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
  1070.  
  1071. u32 cheatsCBACalcIndex(u32 x, u32 y)
  1072. {
  1073.   if(y != 0) {
  1074.     if(y == 1)
  1075.       x = 0;
  1076.     else if(x == y)
  1077.       x = 0;
  1078.     if(y < 1)
  1079.       return x;
  1080.     else if(x < y)
  1081.       return x;
  1082.     u32 x0 = 1;
  1083.  
  1084.     while(y < 0x10000000) {
  1085.       if(y < x) {
  1086.         y = y << 4;
  1087.         x0 = x0 << 4;
  1088.       } else break;
  1089.     }
  1090.  
  1091.     while(y < 0x80000000) {
  1092.       if(y < x) {
  1093.         y = y << 1;
  1094.         x0 = x0 << 1;
  1095.       } else break;
  1096.     }
  1097.  
  1098.   loop:
  1099.     u32 z = 0;
  1100.     if(x >= y)
  1101.       x -= y;
  1102.     if(x >= (y >> 1)) {
  1103.       x -= (y >> 1);
  1104.       z |= ROR(x0, 1);
  1105.     }
  1106.     if(x >= (y >> 2)) {
  1107.       x -= (y >> 2);
  1108.       z |= ROR(x0, 2);
  1109.     }
  1110.     if(x >= (y >> 3)) {
  1111.       x -= (y >> 3);
  1112.       z |= ROR(x0, 3);
  1113.     }
  1114.  
  1115.     u32 temp = x0;
  1116.  
  1117.     if(x != 0) {
  1118.       x0 = x0 >> 4;
  1119.       if(x0 != 0) {
  1120.         y = y >> 4;
  1121.         goto loop;
  1122.       }
  1123.     }
  1124.  
  1125.     z = z & 0xe0000000;
  1126.  
  1127.     if(z != 0) {
  1128.       if((temp & 7) == 0)
  1129.         return x;
  1130.     } else
  1131.       return x;
  1132.  
  1133.     if((z & ROR(temp, 3)) != 0)
  1134.       x += y >> 3;
  1135.     if((z & ROR(temp, 2)) != 0)
  1136.       x += y >> 2;
  1137.     if((z & ROR(temp, 1)) != 0)
  1138.       x += y >> 1;
  1139.     return x;
  1140.   } else {
  1141.   }
  1142.   // should not happen in the current code
  1143.   return 0;
  1144. }
  1145.  
  1146. void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count)
  1147. {
  1148.   int i;
  1149.   for(i = 0; i < count; i++)
  1150.     buffer[i] = i;
  1151.   for(i = 0; (u32)i < a; i++) {
  1152.     u32 a = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
  1153.     u32 b = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
  1154.     u32 t = buffer[a];
  1155.     buffer[a] = buffer[b];
  1156.     buffer[b] = t;
  1157.   }
  1158. }
  1159.  
  1160. void cheatsCBAChangeEncryption(u32 *seed)
  1161. {
  1162.   int i;
  1163.  
  1164.   cheatsCBATemporaryValue = (seed[1] ^ 0x1111);
  1165.   cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30);
  1166.   cheatsCBATemporaryValue = 0x4efad1c3;
  1167.  
  1168.   for(i = 0; (u32)i < seed[4]; i++) {
  1169.     cheatsCBATemporaryValue = cheatsCBAEncWorker();
  1170.   }
  1171.   cheatsCBASeed[2] = cheatsCBAEncWorker();
  1172.   cheatsCBASeed[3] = cheatsCBAEncWorker();
  1173.  
  1174.   cheatsCBATemporaryValue = seed[3] ^ 0xf254;
  1175.  
  1176.   for(i = 0; (u32)i < seed[3]; i++) {
  1177.     cheatsCBATemporaryValue = cheatsCBAEncWorker();
  1178.   }
  1179.  
  1180.   cheatsCBASeed[0] = cheatsCBAEncWorker();
  1181.   cheatsCBASeed[1] = cheatsCBAEncWorker();
  1182.  
  1183.   *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6];
  1184.   *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7];
  1185.   *((u32 *)&cheatsCBACurrentSeed[8]) = 0;
  1186. }
  1187.  
  1188. u16 cheatsCBAGenValue(u32 x, u32 y, u32 z)
  1189. {
  1190.   y <<= 0x10;
  1191.   z <<= 0x10;
  1192.   x <<= 0x18;
  1193.   u32 x0 = (int)y >> 0x10;
  1194.   z = (int)z >> 0x10;
  1195.   x = (int)x >> 0x10;
  1196.   for(int i = 0; i < 8; i++) {
  1197.     u32 temp = z ^ x;
  1198.     if ((int)temp >= 0) {
  1199.       temp = z << 0x11;
  1200.     }
  1201.     else {
  1202.       temp = z << 0x01;
  1203.       temp ^= x0;
  1204.       temp = temp << 0x10;
  1205.     }
  1206.     z = (int)temp >> 0x10;
  1207.     temp = x << 0x11;
  1208.     x = (int)temp >> 0x10;
  1209.   }
  1210.   return z & 0xffff;
  1211. }
  1212.  
  1213. void cheatsCBAGenTable() {
  1214.   for (int i = 0; i < 0x100; i++) {
  1215.     cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0);
  1216.   }
  1217.   cheatsCBATableGenerated = true;
  1218. }
  1219.  
  1220. u16 cheatsCBACalcCRC(u8 *rom, int count)
  1221. {
  1222.   u32 crc = 0xffffffff;
  1223.   
  1224.   if (count & 3) {
  1225.     // 0x08000EAE
  1226.   } else {
  1227.     count = (count >> 2) - 1;
  1228.     if(count != -1) {
  1229.       while(count != -1) {
  1230.         crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
  1231.                                                ^ *rom++]) << 0x10) >> 0x10;
  1232.         crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
  1233.                                                ^ *rom++]) << 0x10) >> 0x10;
  1234.         crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
  1235.                                                ^ *rom++]) << 0x10) >> 0x10;
  1236.         crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
  1237.                                                ^ *rom++]) << 0x10) >> 0x10;
  1238.         count--;
  1239.       }
  1240.     }
  1241.   }
  1242.   return crc & 0xffff;
  1243. }
  1244.  
  1245. void cheatsCBADecrypt(u8 *decrypt)
  1246. {
  1247.   u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  1248.   u8 *array = &buffer[1];
  1249.  
  1250.   cheatsCBAReverseArray(decrypt, array);
  1251.  
  1252.   for(int count = 0x2f; count >= 0; count--) {
  1253.     chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]);
  1254.   }
  1255.   cheatsCBAArrayToValue(array, decrypt);
  1256.   *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^
  1257.     cheatsCBASeed[0];
  1258.   *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^
  1259.                            cheatsCBASeed[1]) & 0xffff;
  1260.  
  1261.   cheatsCBAReverseArray(decrypt, array);
  1262.  
  1263.   u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed);
  1264.   for(int i = 0; i <= 4; i++) {
  1265.     array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ;
  1266.   }
  1267.  
  1268.   array[5] = (cs >> 8) ^ array[5];
  1269.  
  1270.   for(int j = 5; j >=0; j--) {
  1271.     array[j] = (cs ^ array[j-1]) ^ array[j];
  1272.   }
  1273.  
  1274.   cheatsCBAArrayToValue(array, decrypt);
  1275.  
  1276.   *((u32 *)decrypt) = cheatsCBAGetValue(decrypt)
  1277.     ^ cheatsCBASeed[2];
  1278.   *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt)
  1279.                            ^ cheatsCBASeed[3]) & 0xffff;
  1280. }
  1281.  
  1282. int cheatsCBAGetCount()
  1283. {
  1284.   int count = 0;
  1285.   for(int i = 0; i < cheatsNumber; i++) {
  1286.     if(cheatsList[i].code == 512)
  1287.       count++;
  1288.   }
  1289.   return count;
  1290. }
  1291.  
  1292. bool cheatsCBAShouldDecrypt()
  1293. {
  1294.   for(int i = 0; i < cheatsNumber; i++) {
  1295.     if(cheatsList[i].code == 512) {
  1296.       return (cheatsList[i].codestring[0] == '9');
  1297.     }
  1298.   }
  1299.   return false;
  1300. }
  1301.  
  1302. void cheatsAddCBACode(const char *code, const char *desc)
  1303. {
  1304.   if(strlen(code) != 13) {
  1305.     // wrong cheat
  1306.     systemMessage(MSG_INVALID_CBA_CODE,
  1307.                   N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
  1308.     return;
  1309.   }
  1310.   
  1311.   int i;
  1312.   for(i = 0; i < 8; i++) {
  1313.     if(!CHEAT_IS_HEX(code[i])) {
  1314.       // wrong cheat
  1315.       systemMessage(MSG_INVALID_CBA_CODE,
  1316.                     N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
  1317.       return;
  1318.     }
  1319.   }
  1320.  
  1321.   if(code[8] != ' ') {
  1322.     systemMessage(MSG_INVALID_CBA_CODE,
  1323.                   N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
  1324.     return;    
  1325.   }
  1326.   
  1327.   for(i = 9; i < 13; i++) {
  1328.     if(!CHEAT_IS_HEX(code[i])) {
  1329.       // wrong cheat
  1330.       systemMessage(MSG_INVALID_CBA_CODE,
  1331.                     N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
  1332.       return;
  1333.     }
  1334.   }  
  1335.   
  1336.   char buffer[10];
  1337.   strncpy(buffer, code, 8);
  1338.   buffer[8] = 0;
  1339.   u32 address;
  1340.   sscanf(buffer, "%x", &address);
  1341.   strncpy(buffer, &code[9], 4);
  1342.   buffer[4] = 0;
  1343.   u32 value;
  1344.   sscanf(buffer, "%x", &value);
  1345.  
  1346.   u8 array[8] = {
  1347.     address & 255,
  1348.     (address >> 8) & 255,
  1349.     (address >> 16) & 255,
  1350.     (address >> 24) & 255,
  1351.     (value & 255),
  1352.     (value >> 8) & 255,
  1353.     0,
  1354.     0
  1355.   };
  1356.  
  1357.   if(cheatsCBAGetCount() == 0 &&
  1358.      (address >> 28) == 9) {
  1359.     u32 seed[8];
  1360.     cheatsCBAParseSeedCode(address, value, seed);
  1361.     cheatsCBAChangeEncryption(seed);
  1362.     cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE);
  1363.   } else {
  1364.     if(cheatsCBAShouldDecrypt())
  1365.       cheatsCBADecrypt(array);
  1366.  
  1367.     address = READ32LE(((u32 *)array));
  1368.     value = READ16LE(((u16 *)&array[4]));
  1369.     
  1370.     int type = (address >> 28) & 15;
  1371.  
  1372.     if(isMultilineWithData(cheatsNumber-1)) {
  1373.       cheatsAdd(code, desc, address, value, 512, UNKNOWN_CODE);
  1374.       return;
  1375.     }
  1376.     
  1377.     switch(type) {
  1378.     case 0x00:
  1379.       {
  1380.         if(!cheatsCBATableGenerated)
  1381.           cheatsCBAGenTable();
  1382.         u32 crc = cheatsCBACalcCRC(rom, 0x10000);
  1383.         if(crc != address) {
  1384.           systemMessage(MSG_CBA_CODE_WARNING,
  1385.                         N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly."));
  1386.         }
  1387.         cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1388.                   UNKNOWN_CODE);
  1389.       }
  1390.       break;
  1391.     case 0x02:
  1392.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1393.                 CBA_OR);
  1394.       break;
  1395.     case 0x03:
  1396.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1397.                 INT_8_BIT_WRITE);
  1398.       break;
  1399.     case 0x04:
  1400.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1401.                 CBA_SLIDE_CODE);
  1402.       break;
  1403.     case 0x05:
  1404.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
  1405.                 CBA_SUPER);
  1406.       break;
  1407.     case 0x06:
  1408.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1409.                 CBA_AND);
  1410.       break;
  1411.     case 0x07:
  1412.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1413.                 CBA_IF_TRUE);
  1414.       break;
  1415.     case 0x08:
  1416.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1417.                 INT_16_BIT_WRITE);
  1418.       break;
  1419.     case 0x0a:
  1420.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1421.                 CBA_IF_FALSE);
  1422.       break;
  1423.     case 0x0b:
  1424.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1425.                 CBA_LT);
  1426.       break;
  1427.     case 0x0c:
  1428.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1429.                 CBA_GT);
  1430.       break;
  1431.     case 0x0d:
  1432.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 
  1433.                 CBA_IF_KEYS_PRESSED);
  1434.       break;
  1435.     case 0x0e:
  1436.       cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
  1437.                 CBA_ADD);
  1438.       break;
  1439.     default:
  1440.       // unsupported code
  1441.       cheatsAdd(code, desc, address & 0xFFFFFFFF, value, 512, 
  1442.                 UNKNOWN_CODE);
  1443.       break;
  1444.     }
  1445.   }
  1446. }
  1447.  
  1448. void cheatsSaveGame(gzFile file)
  1449. {
  1450.   utilWriteInt(file, cheatsNumber);
  1451.   
  1452.   utilGzWrite(file, cheatsList, sizeof(cheatsList));
  1453. }
  1454.  
  1455. void cheatsReadGame(gzFile file)
  1456. {
  1457.   cheatsNumber = 0;
  1458.   
  1459.   cheatsNumber = utilReadInt(file);
  1460.  
  1461.   utilGzRead(file, cheatsList, sizeof(cheatsList));
  1462.  
  1463.   bool firstCodeBreaker = true;
  1464.   
  1465.   for(int i = 0; i < cheatsNumber; i++) {
  1466.     cheatsList[i].status = 0;
  1467.     if(!cheatsList[i].codestring[0]) {
  1468.       switch(cheatsList[i].size) {
  1469.       case 0:
  1470.         sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
  1471.                 cheatsList[i].value);
  1472.         break;
  1473.       case 1:
  1474.         sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
  1475.                 cheatsList[i].value);
  1476.         break;
  1477.       case 2:
  1478.         sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
  1479.                 cheatsList[i].value);
  1480.         break;
  1481.       }
  1482.     }
  1483.  
  1484.     if(cheatsList[i].enabled) {
  1485.       cheatsEnable(i);
  1486.     }
  1487.  
  1488.     if(cheatsList[i].code == 512 && firstCodeBreaker) {
  1489.       firstCodeBreaker = false;
  1490.       char buffer[10];
  1491.       strncpy(buffer, cheatsList[i].codestring, 8);
  1492.       buffer[8] = 0;
  1493.       u32 address;
  1494.       sscanf(buffer, "%x", &address);
  1495.       if((address >> 28) == 9) {
  1496.         strncpy(buffer, &cheatsList[i].codestring[9], 4);
  1497.         buffer[4] = 0;
  1498.         u32 value;
  1499.         sscanf(buffer, "%x", &value);
  1500.         
  1501.         u32 seed[8];
  1502.         cheatsCBAParseSeedCode(address, value, seed);
  1503.         cheatsCBAChangeEncryption(seed);
  1504.       }
  1505.     }
  1506.   }
  1507. }
  1508.  
  1509. void cheatsSaveCheatList(const char *file)
  1510. {
  1511.   if(cheatsNumber == 0)
  1512.     return;
  1513.   FILE *f = fopen(file, "wb");
  1514.   if(f == NULL)
  1515.     return;
  1516.   int version = 1;
  1517.   fwrite(&version, 1, sizeof(version), f);
  1518.   int type = 0;
  1519.   fwrite(&type, 1, sizeof(type), f);
  1520.   fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f);
  1521.   fwrite(cheatsList, 1, sizeof(cheatsList), f);
  1522.   fclose(f);
  1523. }
  1524.  
  1525. bool cheatsLoadCheatList(const char *file)
  1526. {
  1527.   cheatsNumber = 0;
  1528.  
  1529.   int count = 0;
  1530.  
  1531.   FILE *f = fopen(file, "rb");
  1532.  
  1533.   if(f == NULL)
  1534.     return false;
  1535.  
  1536.   int version = 0;
  1537.  
  1538.   if(fread(&version, 1, sizeof(version), f) != sizeof(version)) {
  1539.     fclose(f);
  1540.     return false;
  1541.   }
  1542.      
  1543.   if(version != 1) {
  1544.     systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
  1545.                   N_("Unsupported cheat list version %d"), version);
  1546.     fclose(f);
  1547.     return false;
  1548.   }
  1549.  
  1550.   int type = 0;
  1551.   if(fread(&type, 1, sizeof(type), f) != sizeof(type)) {
  1552.     fclose(f);
  1553.     return false;
  1554.   }
  1555.  
  1556.   if(type != 0) {
  1557.     systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
  1558.                   N_("Unsupported cheat list type %d"), type);
  1559.     fclose(f);
  1560.     return false;
  1561.   }
  1562.   
  1563.   if(fread(&count, 1, sizeof(count), f) != sizeof(count)) {
  1564.     fclose(f);
  1565.     return false;
  1566.   }
  1567.   
  1568.   if(fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) {
  1569.     fclose(f);
  1570.     return false;
  1571.   }
  1572.  
  1573.   bool firstCodeBreaker = true;
  1574.   
  1575.   for(int i = 0; i < count; i++) {
  1576.     cheatsList[i].status = 0; // remove old status as it is not used
  1577.     if(!cheatsList[i].codestring[0]) {
  1578.       switch(cheatsList[i].size) {
  1579.       case 0:
  1580.         sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
  1581.                 cheatsList[i].value);
  1582.         break;
  1583.       case 1:
  1584.         sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
  1585.                 cheatsList[i].value);
  1586.         break;
  1587.       case 2:
  1588.         sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
  1589.                 cheatsList[i].value);
  1590.         break;
  1591.       }
  1592.     }
  1593.     
  1594.     if(cheatsList[i].code == 512 && firstCodeBreaker) {
  1595.       firstCodeBreaker = false;
  1596.       char buffer[10];
  1597.       strncpy(buffer, cheatsList[i].codestring, 8);
  1598.       buffer[8] = 0;
  1599.       u32 address;
  1600.       sscanf(buffer, "%x", &address);
  1601.       if((address >> 28) == 9) {
  1602.         strncpy(buffer, &cheatsList[i].codestring[9], 4);
  1603.         buffer[4] = 0;
  1604.         u32 value;
  1605.         sscanf(buffer, "%x", &value);
  1606.         
  1607.         u32 seed[8];
  1608.         cheatsCBAParseSeedCode(address, value, seed);
  1609.         cheatsCBAChangeEncryption(seed);
  1610.       }    
  1611.     }
  1612.   }
  1613.   cheatsNumber = count;
  1614.   fclose(f);
  1615.   return true;
  1616. }
  1617.  
  1618. extern int *extCpuLoopTicks;
  1619. extern int *extClockTicks;
  1620. extern int *extTicks;
  1621. extern int cpuSavedTicks;
  1622.  
  1623. extern void debuggerBreakOnWrite(u32 *, u32, u32, int); 
  1624.  
  1625. #define CPU_BREAK_LOOP \
  1626.   cpuSavedTicks = cpuSavedTicks - *extCpuLoopTicks;\
  1627.   *extCpuLoopTicks = *extClockTicks;\
  1628.   *extTicks = *extClockTicks;
  1629.  
  1630. void cheatsWriteMemory(u32 *address, u32 value, u32 mask)
  1631. {
  1632. #ifdef BKPT_SUPPORT
  1633. #ifdef SDL
  1634.   if(cheatsNumber == 0) {
  1635.     debuggerBreakOnWrite(address, *address, value, 2);
  1636.     CPU_BREAK_LOOP;
  1637.     *address = value;
  1638.     return;
  1639.   }
  1640. #endif
  1641. #endif
  1642. }
  1643.  
  1644. void cheatsWriteHalfWord(u16 *address, u16 value, u16 mask)
  1645. {
  1646. #ifdef BKPT_SUPPORT
  1647. #ifdef SDL
  1648.   if(cheatsNumber == 0) {
  1649.     debuggerBreakOnWrite((u32 *)address, *address, value, 1);
  1650.     CPU_BREAK_LOOP;
  1651.     *address = value;
  1652.     return;
  1653.   }
  1654. #endif
  1655. #endif
  1656. }
  1657.  
  1658. #if defined BKPT_SUPPORT && defined SDL
  1659. void cheatsWriteByte(u8 *address, u8 value)
  1660. #else
  1661. void cheatsWriteByte(u8 *, u8)
  1662. #endif
  1663. {
  1664. #ifdef BKPT_SUPPORT
  1665. #ifdef SDL
  1666.   if(cheatsNumber == 0) {
  1667.     debuggerBreakOnWrite((u32 *)address, *address, value, 0);
  1668.     CPU_BREAK_LOOP;
  1669.     *address = value;
  1670.     return;
  1671.   }
  1672. #endif
  1673. #endif
  1674. }
  1675.