PageRenderTime 229ms CodeModel.GetById 4ms app.highlight 206ms RepoModel.GetById 1ms app.codeStats 1ms

/trunk/src/gba/Cheats.cpp

https://bitbucket.org/ZachThibeau/vba-m
C++ | 2898 lines | 2672 code | 147 blank | 79 comment | 411 complexity | 96eaf67ae726fe30025a4f45a60e51c6 MD5 | raw file
   1#include <memory.h>
   2#include <string.h>
   3#include <stdio.h>
   4#include <ctype.h>
   5
   6#include "GBA.h"
   7#include "GBAinline.h"
   8#include "Cheats.h"
   9#include "Globals.h"
  10#include "../NLS.h"
  11#include "../Util.h"
  12
  13/**
  14 * Gameshark code types: (based on AR v1.0)
  15 *
  16 * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM
  17 * DEADFACE XXXXXXXX - changes decryption seeds // Not supported by VBA.
  18 * 0AAAAAAA 000000YY - 8-bit constant write
  19 * 1AAAAAAA 0000YYYY - 16-bit constant write
  20 * 2AAAAAAA YYYYYYYY - 32-bit constant write
  21 * 30XXAAAA YYYYYYYY - 32bit Group Write, 8/16/32bit Sub/Add (depending on the XX value).
  22 * 6AAAAAAA Z000YYYY - 16-bit ROM Patch (address >> 1). Z selects the Rom Patching register.
  23 *                   - AR v1/2 hardware only supports Z=0.
  24 *                   - AR v3 hardware should support Z=0,1,2 or 3.
  25 * 8A1AAAAA 000000YY - 8-bit button write
  26 * 8A2AAAAA 0000YYYY - 16-bit button write
  27 * 8A4AAAAA YYYYYYYY - 32-bit button write // BUGGY ! Only writes 00000000 on the AR v1.0.
  28 * 80F00000 0000YYYY - button slow motion
  29 * DAAAAAAA 00Z0YYYY - Z = 0 : if 16-bit value at address != YYYY skip next line
  30 *                   - Z = 1 : if 16-bit value at address == YYYY skip next line
  31 *                   - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip next line
  32 *                   - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip next line
  33 * E0CCYYYY ZAAAAAAA - Z = 0 : if 16-bit value at address != YYYY skip CC lines
  34 *                   - Z = 1 : if 16-bit value at address == YYYY skip CC lines
  35 *                   - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip CC lines
  36 *                   - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip CC lines
  37 * FAAAAAAA 0000YYYY - Master code function
  38 *
  39 *
  40 *
  41 * CodeBreaker codes types: (based on the CBA clone "Cheatcode S" v1.1)
  42 *
  43 * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI)
  44 * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16)
  45 *                 + 0x08000100))
  46 * 2AAAAAAA YYYY - 16-bit or
  47 * 3AAAAAAA YYYY - 8-bit constant write
  48 * 4AAAAAAA YYYY - Slide code
  49 * XXXXCCCC IIII   (C is count and I is address increment, X is value incr.)
  50 * 5AAAAAAA CCCC - Super code (Write bytes to address, 2*CCCC is count)
  51 * BBBBBBBB BBBB
  52 * 6AAAAAAA YYYY - 16-bit and
  53 * 7AAAAAAA YYYY - if address contains 16-bit value enable next code
  54 * 8AAAAAAA YYYY - 16-bit constant write
  55 * 9AAAAAAA YYYY - change decryption (when first code only?)
  56 * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code
  57 * BAAAAAAA YYYY - if 16-bit value at address  <= YYYY skip next code
  58 * CAAAAAAA YYYY - if 16-bit value at address  >= YYYY skip next code
  59 * D00000X0 YYYY - if button keys ... enable next code (else skip next code)
  60 * EAAAAAAA YYYY - increase 16/32bit value stored in address
  61 * FAAAAAAA YYYY - if 16-bit value at address AND YYYY = 0 then skip next code
  62 **/
  63
  64#define UNKNOWN_CODE                  -1
  65#define INT_8_BIT_WRITE               0
  66#define INT_16_BIT_WRITE              1
  67#define INT_32_BIT_WRITE              2
  68#define GSA_16_BIT_ROM_PATCH          3
  69#define GSA_8_BIT_GS_WRITE            4
  70#define GSA_16_BIT_GS_WRITE           5
  71#define GSA_32_BIT_GS_WRITE           6
  72#define CBA_IF_KEYS_PRESSED           7
  73#define CBA_IF_TRUE                   8
  74#define CBA_SLIDE_CODE                9
  75#define CBA_IF_FALSE                  10
  76#define CBA_AND                       11
  77#define GSA_8_BIT_GS_WRITE2           12
  78#define GSA_16_BIT_GS_WRITE2          13
  79#define GSA_32_BIT_GS_WRITE2          14
  80#define GSA_16_BIT_ROM_PATCH2C        15
  81#define GSA_8_BIT_SLIDE               16
  82#define GSA_16_BIT_SLIDE              17
  83#define GSA_32_BIT_SLIDE              18
  84#define GSA_8_BIT_IF_TRUE             19
  85#define GSA_32_BIT_IF_TRUE            20
  86#define GSA_8_BIT_IF_FALSE            21
  87#define GSA_32_BIT_IF_FALSE           22
  88#define GSA_8_BIT_FILL                23
  89#define GSA_16_BIT_FILL               24
  90#define GSA_8_BIT_IF_TRUE2            25
  91#define GSA_16_BIT_IF_TRUE2           26
  92#define GSA_32_BIT_IF_TRUE2           27
  93#define GSA_8_BIT_IF_FALSE2           28
  94#define GSA_16_BIT_IF_FALSE2          29
  95#define GSA_32_BIT_IF_FALSE2          30
  96#define GSA_SLOWDOWN                  31
  97#define CBA_ADD                       32
  98#define CBA_OR                        33
  99#define CBA_LT                        34
 100#define CBA_GT                        35
 101#define CBA_SUPER                     36
 102#define GSA_8_BIT_POINTER             37
 103#define GSA_16_BIT_POINTER            38
 104#define GSA_32_BIT_POINTER            39
 105#define GSA_8_BIT_ADD                 40
 106#define GSA_16_BIT_ADD                41
 107#define GSA_32_BIT_ADD                42
 108#define GSA_8_BIT_IF_LOWER_U          43
 109#define GSA_16_BIT_IF_LOWER_U         44
 110#define GSA_32_BIT_IF_LOWER_U         45
 111#define GSA_8_BIT_IF_HIGHER_U         46
 112#define GSA_16_BIT_IF_HIGHER_U        47
 113#define GSA_32_BIT_IF_HIGHER_U        48
 114#define GSA_8_BIT_IF_AND              49
 115#define GSA_16_BIT_IF_AND             50
 116#define GSA_32_BIT_IF_AND             51
 117#define GSA_8_BIT_IF_LOWER_U2         52
 118#define GSA_16_BIT_IF_LOWER_U2        53
 119#define GSA_32_BIT_IF_LOWER_U2        54
 120#define GSA_8_BIT_IF_HIGHER_U2        55
 121#define GSA_16_BIT_IF_HIGHER_U2       56
 122#define GSA_32_BIT_IF_HIGHER_U2       57
 123#define GSA_8_BIT_IF_AND2             58
 124#define GSA_16_BIT_IF_AND2            59
 125#define GSA_32_BIT_IF_AND2            60
 126#define GSA_ALWAYS                    61
 127#define GSA_ALWAYS2                   62
 128#define GSA_8_BIT_IF_LOWER_S          63
 129#define GSA_16_BIT_IF_LOWER_S         64
 130#define GSA_32_BIT_IF_LOWER_S         65
 131#define GSA_8_BIT_IF_HIGHER_S         66
 132#define GSA_16_BIT_IF_HIGHER_S        67
 133#define GSA_32_BIT_IF_HIGHER_S        68
 134#define GSA_8_BIT_IF_LOWER_S2         69
 135#define GSA_16_BIT_IF_LOWER_S2        70
 136#define GSA_32_BIT_IF_LOWER_S2        71
 137#define GSA_8_BIT_IF_HIGHER_S2        72
 138#define GSA_16_BIT_IF_HIGHER_S2       73
 139#define GSA_32_BIT_IF_HIGHER_S2       74
 140#define GSA_16_BIT_WRITE_IOREGS       75
 141#define GSA_32_BIT_WRITE_IOREGS       76
 142#define GSA_CODES_ON                  77
 143#define GSA_8_BIT_IF_TRUE3            78
 144#define GSA_16_BIT_IF_TRUE3           79
 145#define GSA_32_BIT_IF_TRUE3           80
 146#define GSA_8_BIT_IF_FALSE3           81
 147#define GSA_16_BIT_IF_FALSE3          82
 148#define GSA_32_BIT_IF_FALSE3          83
 149#define GSA_8_BIT_IF_LOWER_S3         84
 150#define GSA_16_BIT_IF_LOWER_S3        85
 151#define GSA_32_BIT_IF_LOWER_S3        86
 152#define GSA_8_BIT_IF_HIGHER_S3        87
 153#define GSA_16_BIT_IF_HIGHER_S3       88
 154#define GSA_32_BIT_IF_HIGHER_S3       89
 155#define GSA_8_BIT_IF_LOWER_U3         90
 156#define GSA_16_BIT_IF_LOWER_U3        91
 157#define GSA_32_BIT_IF_LOWER_U3        92
 158#define GSA_8_BIT_IF_HIGHER_U3        93
 159#define GSA_16_BIT_IF_HIGHER_U3       94
 160#define GSA_32_BIT_IF_HIGHER_U3       95
 161#define GSA_8_BIT_IF_AND3             96
 162#define GSA_16_BIT_IF_AND3            97
 163#define GSA_32_BIT_IF_AND3            98
 164#define GSA_ALWAYS3                   99
 165#define GSA_16_BIT_ROM_PATCH2D        100
 166#define GSA_16_BIT_ROM_PATCH2E        101
 167#define GSA_16_BIT_ROM_PATCH2F        102
 168#define GSA_GROUP_WRITE               103
 169#define GSA_32_BIT_ADD2               104
 170#define GSA_32_BIT_SUB2               105
 171#define GSA_16_BIT_IF_LOWER_OR_EQ_U   106
 172#define GSA_16_BIT_IF_HIGHER_OR_EQ_U  107
 173#define GSA_16_BIT_MIF_TRUE           108
 174#define GSA_16_BIT_MIF_FALSE          109
 175#define GSA_16_BIT_MIF_LOWER_OR_EQ_U  110
 176#define GSA_16_BIT_MIF_HIGHER_OR_EQ_U 111
 177#define MASTER_CODE                   112
 178#define CHEATS_16_BIT_WRITE           114
 179#define CHEATS_32_BIT_WRITE           115
 180
 181CheatsData cheatsList[100];
 182int cheatsNumber = 0;
 183u32 rompatch2addr [4];
 184u16 rompatch2val [4];
 185u16 rompatch2oldval [4];
 186
 187u8 cheatsCBASeedBuffer[0x30];
 188u32 cheatsCBASeed[4];
 189u32 cheatsCBATemporaryValue = 0;
 190u16 cheatsCBATable[256];
 191bool cheatsCBATableGenerated = false;
 192u16 super = 0;
 193extern u32 mastercode;
 194
 195u8 cheatsCBACurrentSeed[12] = {
 196  0x00, 0x00, 0x00, 0x00,
 197  0x00, 0x00, 0x00, 0x00,
 198  0x00, 0x00, 0x00, 0x00
 199};
 200
 201u32 seeds_v1[4];
 202u32 seeds_v3[4];
 203
 204u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2);
 205
 206//seed tables for AR v1
 207u8 v1_deadtable1[256] = {
 208	0x31, 0x1C, 0x23, 0xE5, 0x89, 0x8E, 0xA1, 0x37, 0x74, 0x6D, 0x67, 0xFC, 0x1F, 0xC0, 0xB1, 0x94,
 209	0x3B, 0x05, 0x56, 0x86, 0x00, 0x24, 0xF0, 0x17, 0x72, 0xA2, 0x3D, 0x1B, 0xE3, 0x17, 0xC5, 0x0B,
 210	0xB9, 0xE2, 0xBD, 0x58, 0x71, 0x1B, 0x2C, 0xFF, 0xE4, 0xC9, 0x4C, 0x5E, 0xC9, 0x55, 0x33, 0x45,
 211	0x7C, 0x3F, 0xB2, 0x51, 0xFE, 0x10, 0x7E, 0x75, 0x3C, 0x90, 0x8D, 0xDA, 0x94, 0x38, 0xC3, 0xE9,
 212	0x95, 0xEA, 0xCE, 0xA6, 0x06, 0xE0, 0x4F, 0x3F, 0x2A, 0xE3, 0x3A, 0xE4, 0x43, 0xBD, 0x7F, 0xDA,
 213	0x55, 0xF0, 0xEA, 0xCB, 0x2C, 0xA8, 0x47, 0x61, 0xA0, 0xEF, 0xCB, 0x13, 0x18, 0x20, 0xAF, 0x3E,
 214	0x4D, 0x9E, 0x1E, 0x77, 0x51, 0xC5, 0x51, 0x20, 0xCF, 0x21, 0xF9, 0x39, 0x94, 0xDE, 0xDD, 0x79,
 215	0x4E, 0x80, 0xC4, 0x9D, 0x94, 0xD5, 0x95, 0x01, 0x27, 0x27, 0xBD, 0x6D, 0x78, 0xB5, 0xD1, 0x31,
 216	0x6A, 0x65, 0x74, 0x74, 0x58, 0xB3, 0x7C, 0xC9, 0x5A, 0xED, 0x50, 0x03, 0xC4, 0xA2, 0x94, 0x4B,
 217	0xF0, 0x58, 0x09, 0x6F, 0x3E, 0x7D, 0xAE, 0x7D, 0x58, 0xA0, 0x2C, 0x91, 0xBB, 0xE1, 0x70, 0xEB,
 218	0x73, 0xA6, 0x9A, 0x44, 0x25, 0x90, 0x16, 0x62, 0x53, 0xAE, 0x08, 0xEB, 0xDC, 0xF0, 0xEE, 0x77,
 219	0xC2, 0xDE, 0x81, 0xE8, 0x30, 0x89, 0xDB, 0xFE, 0xBC, 0xC2, 0xDF, 0x26, 0xE9, 0x8B, 0xD6, 0x93,
 220	0xF0, 0xCB, 0x56, 0x90, 0xC0, 0x46, 0x68, 0x15, 0x43, 0xCB, 0xE9, 0x98, 0xE3, 0xAF, 0x31, 0x25,
 221	0x4D, 0x7B, 0xF3, 0xB1, 0x74, 0xE2, 0x64, 0xAC, 0xD9, 0xF6, 0xA0, 0xD5, 0x0B, 0x9B, 0x49, 0x52,
 222	0x69, 0x3B, 0x71, 0x00, 0x2F, 0xBB, 0xBA, 0x08, 0xB1, 0xAE, 0xBB, 0xB3, 0xE1, 0xC9, 0xA6, 0x7F,
 223	0x17, 0x97, 0x28, 0x72, 0x12, 0x6E, 0x91, 0xAE, 0x3A, 0xA2, 0x35, 0x46, 0x27, 0xF8, 0x12, 0x50
 224};
 225u8 v1_deadtable2[256] = {
 226	0xD8, 0x65, 0x04, 0xC2, 0x65, 0xD5, 0xB0, 0x0C, 0xDF, 0x9D, 0xF0, 0xC3, 0x9A, 0x17, 0xC9, 0xA6,
 227	0xE1, 0xAC, 0x0D, 0x14, 0x2F, 0x3C, 0x2C, 0x87, 0xA2, 0xBF, 0x4D, 0x5F, 0xAC, 0x2D, 0x9D, 0xE1,
 228	0x0C, 0x9C, 0xE7, 0x7F, 0xFC, 0xA8, 0x66, 0x59, 0xAC, 0x18, 0xD7, 0x05, 0xF0, 0xBF, 0xD1, 0x8B,
 229	0x35, 0x9F, 0x59, 0xB4, 0xBA, 0x55, 0xB2, 0x85, 0xFD, 0xB1, 0x72, 0x06, 0x73, 0xA4, 0xDB, 0x48,
 230	0x7B, 0x5F, 0x67, 0xA5, 0x95, 0xB9, 0xA5, 0x4A, 0xCF, 0xD1, 0x44, 0xF3, 0x81, 0xF5, 0x6D, 0xF6,
 231	0x3A, 0xC3, 0x57, 0x83, 0xFA, 0x8E, 0x15, 0x2A, 0xA2, 0x04, 0xB2, 0x9D, 0xA8, 0x0D, 0x7F, 0xB8,
 232	0x0F, 0xF6, 0xAC, 0xBE, 0x97, 0xCE, 0x16, 0xE6, 0x31, 0x10, 0x60, 0x16, 0xB5, 0x83, 0x45, 0xEE,
 233	0xD7, 0x5F, 0x2C, 0x08, 0x58, 0xB1, 0xFD, 0x7E, 0x79, 0x00, 0x34, 0xAD, 0xB5, 0x31, 0x34, 0x39,
 234	0xAF, 0xA8, 0xDD, 0x52, 0x6A, 0xB0, 0x60, 0x35, 0xB8, 0x1D, 0x52, 0xF5, 0xF5, 0x30, 0x00, 0x7B,
 235	0xF4, 0xBA, 0x03, 0xCB, 0x3A, 0x84, 0x14, 0x8A, 0x6A, 0xEF, 0x21, 0xBD, 0x01, 0xD8, 0xA0, 0xD4,
 236	0x43, 0xBE, 0x23, 0xE7, 0x76, 0x27, 0x2C, 0x3F, 0x4D, 0x3F, 0x43, 0x18, 0xA7, 0xC3, 0x47, 0xA5,
 237	0x7A, 0x1D, 0x02, 0x55, 0x09, 0xD1, 0xFF, 0x55, 0x5E, 0x17, 0xA0, 0x56, 0xF4, 0xC9, 0x6B, 0x90,
 238	0xB4, 0x80, 0xA5, 0x07, 0x22, 0xFB, 0x22, 0x0D, 0xD9, 0xC0, 0x5B, 0x08, 0x35, 0x05, 0xC1, 0x75,
 239	0x4F, 0xD0, 0x51, 0x2D, 0x2E, 0x5E, 0x69, 0xE7, 0x3B, 0xC2, 0xDA, 0xFF, 0xF6, 0xCE, 0x3E, 0x76,
 240	0xE8, 0x36, 0x8C, 0x39, 0xD8, 0xF3, 0xE9, 0xA6, 0x42, 0xE6, 0xC1, 0x4C, 0x05, 0xBE, 0x17, 0xF2,
 241	0x5C, 0x1B, 0x19, 0xDB, 0x0F, 0xF3, 0xF8, 0x49, 0xEB, 0x36, 0xF6, 0x40, 0x6F, 0xAD, 0xC1, 0x8C
 242};
 243
 244//seed tables for AR v3
 245u8 v3_deadtable1[256] = {
 246    0xD0, 0xFF, 0xBA, 0xE5, 0xC1, 0xC7, 0xDB, 0x5B, 0x16, 0xE3, 0x6E, 0x26, 0x62, 0x31, 0x2E, 0x2A,
 247    0xD1, 0xBB, 0x4A, 0xE6, 0xAE, 0x2F, 0x0A, 0x90, 0x29, 0x90, 0xB6, 0x67, 0x58, 0x2A, 0xB4, 0x45,
 248    0x7B, 0xCB, 0xF0, 0x73, 0x84, 0x30, 0x81, 0xC2, 0xD7, 0xBE, 0x89, 0xD7, 0x4E, 0x73, 0x5C, 0xC7,
 249    0x80, 0x1B, 0xE5, 0xE4, 0x43, 0xC7, 0x46, 0xD6, 0x6F, 0x7B, 0xBF, 0xED, 0xE5, 0x27, 0xD1, 0xB5,
 250    0xD0, 0xD8, 0xA3, 0xCB, 0x2B, 0x30, 0xA4, 0xF0, 0x84, 0x14, 0x72, 0x5C, 0xFF, 0xA4, 0xFB, 0x54,
 251    0x9D, 0x70, 0xE2, 0xFF, 0xBE, 0xE8, 0x24, 0x76, 0xE5, 0x15, 0xFB, 0x1A, 0xBC, 0x87, 0x02, 0x2A,
 252    0x58, 0x8F, 0x9A, 0x95, 0xBD, 0xAE, 0x8D, 0x0C, 0xA5, 0x4C, 0xF2, 0x5C, 0x7D, 0xAD, 0x51, 0xFB,
 253    0xB1, 0x22, 0x07, 0xE0, 0x29, 0x7C, 0xEB, 0x98, 0x14, 0xC6, 0x31, 0x97, 0xE4, 0x34, 0x8F, 0xCC,
 254    0x99, 0x56, 0x9F, 0x78, 0x43, 0x91, 0x85, 0x3F, 0xC2, 0xD0, 0xD1, 0x80, 0xD1, 0x77, 0xA7, 0xE2,
 255    0x43, 0x99, 0x1D, 0x2F, 0x8B, 0x6A, 0xE4, 0x66, 0x82, 0xF7, 0x2B, 0x0B, 0x65, 0x14, 0xC0, 0xC2,
 256    0x1D, 0x96, 0x78, 0x1C, 0xC4, 0xC3, 0xD2, 0xB1, 0x64, 0x07, 0xD7, 0x6F, 0x02, 0xE9, 0x44, 0x31,
 257    0xDB, 0x3C, 0xEB, 0x93, 0xED, 0x9A, 0x57, 0x05, 0xB9, 0x0E, 0xAF, 0x1F, 0x48, 0x11, 0xDC, 0x35,
 258    0x6C, 0xB8, 0xEE, 0x2A, 0x48, 0x2B, 0xBC, 0x89, 0x12, 0x59, 0xCB, 0xD1, 0x18, 0xEA, 0x72, 0x11,
 259    0x01, 0x75, 0x3B, 0xB5, 0x56, 0xF4, 0x8B, 0xA0, 0x41, 0x75, 0x86, 0x7B, 0x94, 0x12, 0x2D, 0x4C,
 260    0x0C, 0x22, 0xC9, 0x4A, 0xD8, 0xB1, 0x8D, 0xF0, 0x55, 0x2E, 0x77, 0x50, 0x1C, 0x64, 0x77, 0xAA,
 261    0x3E, 0xAC, 0xD3, 0x3D, 0xCE, 0x60, 0xCA, 0x5D, 0xA0, 0x92, 0x78, 0xC6, 0x51, 0xFE, 0xF9, 0x30
 262};
 263u8 v3_deadtable2[256] = {
 264    0xAA, 0xAF, 0xF0, 0x72, 0x90, 0xF7, 0x71, 0x27, 0x06, 0x11, 0xEB, 0x9C, 0x37, 0x12, 0x72, 0xAA,
 265    0x65, 0xBC, 0x0D, 0x4A, 0x76, 0xF6, 0x5C, 0xAA, 0xB0, 0x7A, 0x7D, 0x81, 0xC1, 0xCE, 0x2F, 0x9F,
 266    0x02, 0x75, 0x38, 0xC8, 0xFC, 0x66, 0x05, 0xC2, 0x2C, 0xBD, 0x91, 0xAD, 0x03, 0xB1, 0x88, 0x93,
 267    0x31, 0xC6, 0xAB, 0x40, 0x23, 0x43, 0x76, 0x54, 0xCA, 0xE7, 0x00, 0x96, 0x9F, 0xD8, 0x24, 0x8B,
 268    0xE4, 0xDC, 0xDE, 0x48, 0x2C, 0xCB, 0xF7, 0x84, 0x1D, 0x45, 0xE5, 0xF1, 0x75, 0xA0, 0xED, 0xCD,
 269    0x4B, 0x24, 0x8A, 0xB3, 0x98, 0x7B, 0x12, 0xB8, 0xF5, 0x63, 0x97, 0xB3, 0xA6, 0xA6, 0x0B, 0xDC,
 270    0xD8, 0x4C, 0xA8, 0x99, 0x27, 0x0F, 0x8F, 0x94, 0x63, 0x0F, 0xB0, 0x11, 0x94, 0xC7, 0xE9, 0x7F,
 271    0x3B, 0x40, 0x72, 0x4C, 0xDB, 0x84, 0x78, 0xFE, 0xB8, 0x56, 0x08, 0x80, 0xDF, 0x20, 0x2F, 0xB9,
 272    0x66, 0x2D, 0x60, 0x63, 0xF5, 0x18, 0x15, 0x1B, 0x86, 0x85, 0xB9, 0xB4, 0x68, 0x0E, 0xC6, 0xD1,
 273    0x8A, 0x81, 0x2B, 0xB3, 0xF6, 0x48, 0xF0, 0x4F, 0x9C, 0x28, 0x1C, 0xA4, 0x51, 0x2F, 0xD7, 0x4B,
 274    0x17, 0xE7, 0xCC, 0x50, 0x9F, 0xD0, 0xD1, 0x40, 0x0C, 0x0D, 0xCA, 0x83, 0xFA, 0x5E, 0xCA, 0xEC,
 275    0xBF, 0x4E, 0x7C, 0x8F, 0xF0, 0xAE, 0xC2, 0xD3, 0x28, 0x41, 0x9B, 0xC8, 0x04, 0xB9, 0x4A, 0xBA,
 276    0x72, 0xE2, 0xB5, 0x06, 0x2C, 0x1E, 0x0B, 0x2C, 0x7F, 0x11, 0xA9, 0x26, 0x51, 0x9D, 0x3F, 0xF8,
 277    0x62, 0x11, 0x2E, 0x89, 0xD2, 0x9D, 0x35, 0xB1, 0xE4, 0x0A, 0x4D, 0x93, 0x01, 0xA7, 0xD1, 0x2D,
 278    0x00, 0x87, 0xE2, 0x2D, 0xA4, 0xE9, 0x0A, 0x06, 0x66, 0xF8, 0x1F, 0x44, 0x75, 0xB5, 0x6B, 0x1C,
 279    0xFC, 0x31, 0x09, 0x48, 0xA3, 0xFF, 0x92, 0x12, 0x58, 0xE9, 0xFA, 0xAE, 0x4F, 0xE2, 0xB4, 0xCC
 280};
 281
 282#define debuggerReadMemory(addr) \
 283  READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
 284
 285#define debuggerReadHalfWord(addr) \
 286  READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
 287
 288#define debuggerReadByte(addr) \
 289  map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
 290
 291#define debuggerWriteMemory(addr, value) \
 292  WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
 293
 294#define debuggerWriteHalfWord(addr, value) \
 295  WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
 296
 297#define debuggerWriteByte(addr, value) \
 298  map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
 299
 300
 301#define CHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9'))
 302
 303#define CHEAT_PATCH_ROM_16BIT(a,v) \
 304  WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v);
 305
 306#define CHEAT_PATCH_ROM_32BIT(a,v) \
 307  WRITE32LE(((u32 *)&rom[(a) & 0x1ffffff]), v);
 308
 309static bool isMultilineWithData(int i)
 310{
 311  // we consider it a multiline code if it has more than one line of data
 312  // otherwise, it can still be considered a single code
 313  // (Only CBA codes can be true multilines !!!)
 314  if(i < cheatsNumber && i >= 0)
 315    switch(cheatsList[i].size) {
 316    case INT_8_BIT_WRITE:
 317    case INT_16_BIT_WRITE:
 318    case INT_32_BIT_WRITE:
 319    case GSA_16_BIT_ROM_PATCH:
 320    case GSA_8_BIT_GS_WRITE:
 321    case GSA_16_BIT_GS_WRITE:
 322    case GSA_32_BIT_GS_WRITE:
 323    case CBA_AND:
 324    case CBA_IF_KEYS_PRESSED:
 325    case CBA_IF_TRUE:
 326    case CBA_IF_FALSE:
 327    case GSA_8_BIT_IF_TRUE:
 328    case GSA_32_BIT_IF_TRUE:
 329    case GSA_8_BIT_IF_FALSE:
 330    case GSA_32_BIT_IF_FALSE:
 331    case GSA_8_BIT_FILL:
 332    case GSA_16_BIT_FILL:
 333    case GSA_8_BIT_IF_TRUE2:
 334    case GSA_16_BIT_IF_TRUE2:
 335    case GSA_32_BIT_IF_TRUE2:
 336    case GSA_8_BIT_IF_FALSE2:
 337    case GSA_16_BIT_IF_FALSE2:
 338    case GSA_32_BIT_IF_FALSE2:
 339    case GSA_SLOWDOWN:
 340    case CBA_ADD:
 341    case CBA_OR:
 342    case CBA_LT:
 343    case CBA_GT:
 344    case GSA_8_BIT_POINTER:
 345    case GSA_16_BIT_POINTER:
 346    case GSA_32_BIT_POINTER:
 347    case GSA_8_BIT_ADD:
 348    case GSA_16_BIT_ADD:
 349    case GSA_32_BIT_ADD:
 350    case GSA_8_BIT_IF_LOWER_U:
 351    case GSA_16_BIT_IF_LOWER_U:
 352    case GSA_32_BIT_IF_LOWER_U:
 353    case GSA_8_BIT_IF_HIGHER_U:
 354    case GSA_16_BIT_IF_HIGHER_U:
 355    case GSA_32_BIT_IF_HIGHER_U:
 356    case GSA_8_BIT_IF_AND:
 357    case GSA_16_BIT_IF_AND:
 358    case GSA_32_BIT_IF_AND:
 359    case GSA_8_BIT_IF_LOWER_U2:
 360    case GSA_16_BIT_IF_LOWER_U2:
 361    case GSA_32_BIT_IF_LOWER_U2:
 362    case GSA_8_BIT_IF_HIGHER_U2:
 363    case GSA_16_BIT_IF_HIGHER_U2:
 364    case GSA_32_BIT_IF_HIGHER_U2:
 365    case GSA_8_BIT_IF_AND2:
 366    case GSA_16_BIT_IF_AND2:
 367    case GSA_32_BIT_IF_AND2:
 368    case GSA_ALWAYS:
 369    case GSA_ALWAYS2:
 370    case GSA_8_BIT_IF_LOWER_S:
 371    case GSA_16_BIT_IF_LOWER_S:
 372    case GSA_32_BIT_IF_LOWER_S:
 373    case GSA_8_BIT_IF_HIGHER_S:
 374    case GSA_16_BIT_IF_HIGHER_S:
 375    case GSA_32_BIT_IF_HIGHER_S:
 376    case GSA_8_BIT_IF_LOWER_S2:
 377    case GSA_16_BIT_IF_LOWER_S2:
 378    case GSA_32_BIT_IF_LOWER_S2:
 379    case GSA_8_BIT_IF_HIGHER_S2:
 380    case GSA_16_BIT_IF_HIGHER_S2:
 381    case GSA_32_BIT_IF_HIGHER_S2:
 382    case GSA_16_BIT_WRITE_IOREGS:
 383    case GSA_32_BIT_WRITE_IOREGS:
 384    case GSA_CODES_ON:
 385    case GSA_8_BIT_IF_TRUE3:
 386    case GSA_16_BIT_IF_TRUE3:
 387    case GSA_32_BIT_IF_TRUE3:
 388    case GSA_8_BIT_IF_FALSE3:
 389    case GSA_16_BIT_IF_FALSE3:
 390    case GSA_32_BIT_IF_FALSE3:
 391    case GSA_8_BIT_IF_LOWER_S3:
 392    case GSA_16_BIT_IF_LOWER_S3:
 393    case GSA_32_BIT_IF_LOWER_S3:
 394    case GSA_8_BIT_IF_HIGHER_S3:
 395    case GSA_16_BIT_IF_HIGHER_S3:
 396    case GSA_32_BIT_IF_HIGHER_S3:
 397    case GSA_8_BIT_IF_LOWER_U3:
 398    case GSA_16_BIT_IF_LOWER_U3:
 399    case GSA_32_BIT_IF_LOWER_U3:
 400    case GSA_8_BIT_IF_HIGHER_U3:
 401    case GSA_16_BIT_IF_HIGHER_U3:
 402    case GSA_32_BIT_IF_HIGHER_U3:
 403    case GSA_8_BIT_IF_AND3:
 404    case GSA_16_BIT_IF_AND3:
 405    case GSA_32_BIT_IF_AND3:
 406    case GSA_ALWAYS3:
 407    case GSA_8_BIT_GS_WRITE2:
 408    case GSA_16_BIT_GS_WRITE2:
 409    case GSA_32_BIT_GS_WRITE2:
 410    case GSA_16_BIT_ROM_PATCH2C:
 411    case GSA_16_BIT_ROM_PATCH2D:
 412    case GSA_16_BIT_ROM_PATCH2E:
 413    case GSA_16_BIT_ROM_PATCH2F:
 414    case GSA_8_BIT_SLIDE:
 415    case GSA_16_BIT_SLIDE:
 416    case GSA_32_BIT_SLIDE:
 417    case GSA_GROUP_WRITE:
 418    case GSA_32_BIT_ADD2:
 419    case GSA_32_BIT_SUB2:
 420    case GSA_16_BIT_IF_LOWER_OR_EQ_U:
 421    case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
 422    case GSA_16_BIT_MIF_TRUE:
 423    case GSA_16_BIT_MIF_FALSE:
 424    case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
 425    case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
 426    case MASTER_CODE:
 427    case CHEATS_16_BIT_WRITE:
 428    case CHEATS_32_BIT_WRITE:
 429      return false;
 430      // the codes below have two lines of data
 431    case CBA_SLIDE_CODE:
 432    case CBA_SUPER:
 433      return true;
 434    }
 435  return false;
 436}
 437
 438static int getCodeLength(int num)
 439{
 440  if(num >= cheatsNumber || num < 0)
 441    return 1;
 442
 443  // this is for all the codes that are true multiline
 444  switch(cheatsList[num].size) {
 445  case INT_8_BIT_WRITE:
 446  case INT_16_BIT_WRITE:
 447  case INT_32_BIT_WRITE:
 448  case GSA_16_BIT_ROM_PATCH:
 449  case GSA_8_BIT_GS_WRITE:
 450  case GSA_16_BIT_GS_WRITE:
 451  case GSA_32_BIT_GS_WRITE:
 452  case CBA_AND:
 453  case GSA_8_BIT_FILL:
 454  case GSA_16_BIT_FILL:
 455  case GSA_SLOWDOWN:
 456  case CBA_ADD:
 457  case CBA_OR:
 458  case GSA_8_BIT_POINTER:
 459  case GSA_16_BIT_POINTER:
 460  case GSA_32_BIT_POINTER:
 461  case GSA_8_BIT_ADD:
 462  case GSA_16_BIT_ADD:
 463  case GSA_32_BIT_ADD:
 464  case GSA_CODES_ON:
 465  case GSA_8_BIT_IF_TRUE3:
 466  case GSA_16_BIT_IF_TRUE3:
 467  case GSA_32_BIT_IF_TRUE3:
 468  case GSA_8_BIT_IF_FALSE3:
 469  case GSA_16_BIT_IF_FALSE3:
 470  case GSA_32_BIT_IF_FALSE3:
 471  case GSA_8_BIT_IF_LOWER_S3:
 472  case GSA_16_BIT_IF_LOWER_S3:
 473  case GSA_32_BIT_IF_LOWER_S3:
 474  case GSA_8_BIT_IF_HIGHER_S3:
 475  case GSA_16_BIT_IF_HIGHER_S3:
 476  case GSA_32_BIT_IF_HIGHER_S3:
 477  case GSA_8_BIT_IF_LOWER_U3:
 478  case GSA_16_BIT_IF_LOWER_U3:
 479  case GSA_32_BIT_IF_LOWER_U3:
 480  case GSA_8_BIT_IF_HIGHER_U3:
 481  case GSA_16_BIT_IF_HIGHER_U3:
 482  case GSA_32_BIT_IF_HIGHER_U3:
 483  case GSA_8_BIT_IF_AND3:
 484  case GSA_16_BIT_IF_AND3:
 485  case GSA_32_BIT_IF_AND3:
 486  case GSA_8_BIT_IF_LOWER_U:
 487  case GSA_16_BIT_IF_LOWER_U:
 488  case GSA_32_BIT_IF_LOWER_U:
 489  case GSA_8_BIT_IF_HIGHER_U:
 490  case GSA_16_BIT_IF_HIGHER_U:
 491  case GSA_32_BIT_IF_HIGHER_U:
 492  case GSA_8_BIT_IF_AND:
 493  case GSA_16_BIT_IF_AND:
 494  case GSA_32_BIT_IF_AND:
 495  case GSA_ALWAYS:
 496  case GSA_8_BIT_IF_LOWER_S:
 497  case GSA_16_BIT_IF_LOWER_S:
 498  case GSA_32_BIT_IF_LOWER_S:
 499  case GSA_8_BIT_IF_HIGHER_S:
 500  case GSA_16_BIT_IF_HIGHER_S:
 501  case GSA_32_BIT_IF_HIGHER_S:
 502  case GSA_16_BIT_WRITE_IOREGS:
 503  case GSA_32_BIT_WRITE_IOREGS:
 504  case GSA_8_BIT_GS_WRITE2:
 505  case GSA_16_BIT_GS_WRITE2:
 506  case GSA_32_BIT_GS_WRITE2:
 507  case GSA_16_BIT_ROM_PATCH2C:
 508  case GSA_16_BIT_ROM_PATCH2D:
 509  case GSA_16_BIT_ROM_PATCH2E:
 510  case GSA_16_BIT_ROM_PATCH2F:
 511  case GSA_8_BIT_SLIDE:
 512  case GSA_16_BIT_SLIDE:
 513  case GSA_32_BIT_SLIDE:
 514  case GSA_8_BIT_IF_TRUE:
 515  case GSA_32_BIT_IF_TRUE:
 516  case GSA_8_BIT_IF_FALSE:
 517  case GSA_32_BIT_IF_FALSE:
 518  case CBA_LT:
 519  case CBA_GT:
 520  case CBA_IF_TRUE:
 521  case CBA_IF_FALSE:
 522  case GSA_8_BIT_IF_TRUE2:
 523  case GSA_16_BIT_IF_TRUE2:
 524  case GSA_32_BIT_IF_TRUE2:
 525  case GSA_8_BIT_IF_FALSE2:
 526  case GSA_16_BIT_IF_FALSE2:
 527  case GSA_32_BIT_IF_FALSE2:
 528  case GSA_8_BIT_IF_LOWER_U2:
 529  case GSA_16_BIT_IF_LOWER_U2:
 530  case GSA_32_BIT_IF_LOWER_U2:
 531  case GSA_8_BIT_IF_HIGHER_U2:
 532  case GSA_16_BIT_IF_HIGHER_U2:
 533  case GSA_32_BIT_IF_HIGHER_U2:
 534  case GSA_8_BIT_IF_AND2:
 535  case GSA_16_BIT_IF_AND2:
 536  case GSA_32_BIT_IF_AND2:
 537  case GSA_ALWAYS2:
 538  case GSA_8_BIT_IF_LOWER_S2:
 539  case GSA_16_BIT_IF_LOWER_S2:
 540  case GSA_32_BIT_IF_LOWER_S2:
 541  case GSA_8_BIT_IF_HIGHER_S2:
 542  case GSA_16_BIT_IF_HIGHER_S2:
 543  case GSA_32_BIT_IF_HIGHER_S2:
 544  case GSA_GROUP_WRITE:
 545  case GSA_32_BIT_ADD2:
 546  case GSA_32_BIT_SUB2:
 547  case GSA_16_BIT_IF_LOWER_OR_EQ_U:
 548  case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
 549  case GSA_16_BIT_MIF_TRUE:
 550  case GSA_16_BIT_MIF_FALSE:
 551  case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
 552  case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
 553  case MASTER_CODE:
 554  case CHEATS_16_BIT_WRITE:
 555  case CHEATS_32_BIT_WRITE:
 556  case UNKNOWN_CODE:
 557    return 1;
 558  case CBA_IF_KEYS_PRESSED:
 559  case CBA_SLIDE_CODE:
 560    return 2;
 561  case CBA_SUPER:
 562    return ((((cheatsList[num].value-1) & 0xFFFF)/3) + 1);
 563  }
 564  return 1;
 565}
 566
 567int cheatsCheckKeys(u32 keys, u32 extended)
 568{
 569  bool onoff = true;
 570  int ticks = 0;
 571  int i;
 572  mastercode = 0;
 573
 574  for (i = 0; i<4; i++)
 575    if (rompatch2addr [i] != 0) {
 576      CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2oldval [i]);
 577      rompatch2addr [i] = 0;
 578    }
 579
 580  for (i = 0; i < cheatsNumber; i++) {
 581    if(!cheatsList[i].enabled) {
 582      // make sure we skip other lines in this code
 583      i += getCodeLength(i)-1;
 584      continue;
 585    }
 586    switch(cheatsList[i].size) {
 587    case GSA_CODES_ON:
 588      onoff = true;
 589      break;
 590    case GSA_SLOWDOWN:
 591      // check if button was pressed and released, if so toggle our state
 592      if((cheatsList[i].status & 4) && !(extended & 4))
 593        cheatsList[i].status ^= 1;
 594      if(extended & 4)
 595        cheatsList[i].status |= 4;
 596      else
 597        cheatsList[i].status &= ~4;
 598
 599      if(cheatsList[i].status & 1)
 600        ticks += ((cheatsList[i].value  & 0xFFFF) * 7);
 601      break;
 602    case GSA_8_BIT_SLIDE:
 603      i++;
 604      if(i < cheatsNumber) {
 605        u32 addr = cheatsList[i-1].value;
 606        u8 value = cheatsList[i].rawaddress;
 607        int vinc = (cheatsList[i].value >> 24) & 255;
 608        int count = (cheatsList[i].value >> 16) & 255;
 609        int ainc = (cheatsList[i].value & 0xffff);
 610        while(count > 0) {
 611          CPUWriteByte(addr, value);
 612          value += vinc;
 613          addr += ainc;
 614          count--;
 615        }
 616      }
 617      break;
 618    case GSA_16_BIT_SLIDE:
 619      i++;
 620      if(i < cheatsNumber) {
 621        u32 addr = cheatsList[i-1].value;
 622        u16 value = cheatsList[i].rawaddress;
 623        int vinc = (cheatsList[i].value >> 24) & 255;
 624        int count = (cheatsList[i].value >> 16) & 255;
 625        int ainc = (cheatsList[i].value & 0xffff)*2;
 626        while(count > 0) {
 627          CPUWriteHalfWord(addr, value);
 628          value += vinc;
 629          addr += ainc;
 630          count--;
 631        }
 632      }
 633      break;
 634    case GSA_32_BIT_SLIDE:
 635      i++;
 636      if(i < cheatsNumber) {
 637        u32 addr = cheatsList[i-1].value;
 638        u32 value = cheatsList[i].rawaddress;
 639        int vinc = (cheatsList[i].value >> 24) & 255;
 640        int count = (cheatsList[i].value >> 16) & 255;
 641        int ainc = (cheatsList[i].value & 0xffff)*4;
 642        while(count > 0) {
 643          CPUWriteMemory(addr, value);
 644          value += vinc;
 645          addr += ainc;
 646          count--;
 647        }
 648      }
 649      break;
 650    case GSA_8_BIT_GS_WRITE2:
 651      i++;
 652      if(i < cheatsNumber) {
 653        if(extended & 4) {
 654          CPUWriteByte(cheatsList[i-1].value, cheatsList[i].address);
 655        }
 656      }
 657      break;
 658    case GSA_16_BIT_GS_WRITE2:
 659      i++;
 660      if(i < cheatsNumber) {
 661        if(extended & 4) {
 662          CPUWriteHalfWord(cheatsList[i-1].value, cheatsList[i].address);
 663        }
 664      }
 665      break;
 666    case GSA_32_BIT_GS_WRITE2:
 667      i++;
 668      if(i < cheatsNumber) {
 669        if(extended & 4) {
 670          CPUWriteMemory(cheatsList[i-1].value, cheatsList[i].address);
 671        }
 672      }
 673      break;
 674      case GSA_16_BIT_ROM_PATCH:
 675        if((cheatsList[i].status & 1) == 0) {
 676          if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
 677            cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address);
 678            cheatsList[i].status |= 1;
 679            CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
 680          }
 681        }
 682        break;
 683    case GSA_16_BIT_ROM_PATCH2C:
 684      i++;
 685      if(i < cheatsNumber) {
 686		  rompatch2addr [0] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
 687		  rompatch2oldval [0] = CPUReadHalfWord(rompatch2addr [0]);
 688		  rompatch2val [0] = cheatsList[i].rawaddress & 0xFFFF;
 689      }
 690      break;
 691    case GSA_16_BIT_ROM_PATCH2D:
 692      i++;
 693      if(i < cheatsNumber) {
 694		  rompatch2addr [1] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
 695		  rompatch2oldval [1] = CPUReadHalfWord(rompatch2addr [1]);
 696		  rompatch2val [1] = cheatsList[i].rawaddress & 0xFFFF;
 697      }
 698      break;
 699    case GSA_16_BIT_ROM_PATCH2E:
 700      i++;
 701      if(i < cheatsNumber) {
 702		  rompatch2addr [2] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
 703		  rompatch2oldval [2] = CPUReadHalfWord(rompatch2addr [2]);
 704		  rompatch2val [2] = cheatsList[i].rawaddress & 0xFFFF;
 705      }
 706      break;
 707    case GSA_16_BIT_ROM_PATCH2F:
 708      i++;
 709      if(i < cheatsNumber) {
 710		  rompatch2addr [3] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
 711		  rompatch2oldval [3] = CPUReadHalfWord(rompatch2addr [3]);
 712		  rompatch2val [3] = cheatsList[i].rawaddress & 0xFFFF;
 713      }
 714      break;
 715    case MASTER_CODE:
 716        mastercode = cheatsList[i].address;
 717      break;
 718    }
 719    if (onoff) {
 720      switch(cheatsList[i].size) {
 721      case INT_8_BIT_WRITE:
 722        CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
 723        break;
 724      case INT_16_BIT_WRITE:
 725        CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
 726        break;
 727      case INT_32_BIT_WRITE:
 728        CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
 729        break;
 730      case GSA_8_BIT_GS_WRITE:
 731        if(extended & 4) {
 732          CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
 733        }
 734        break;
 735      case GSA_16_BIT_GS_WRITE:
 736        if(extended & 4) {
 737          CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
 738        }
 739        break;
 740      case GSA_32_BIT_GS_WRITE:
 741        if(extended & 4) {
 742          CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
 743        }
 744        break;
 745      case CBA_IF_KEYS_PRESSED:
 746        {
 747          u16 value = cheatsList[i].value;
 748          u32 addr = cheatsList[i].address;
 749          if((addr & 0xF0) == 0x20) {
 750            if((keys & value) == 0) {
 751              i++;
 752			}
 753		  } else if((addr & 0xF0) == 0x10) {
 754            if((keys & value) == value) {
 755              i++;
 756			}
 757		  } else if((addr & 0xF0) == 0x00) {
 758            if(((~keys) & 0x3FF) == value) {
 759              i++;
 760			}
 761		  }
 762		}
 763        break;
 764      case CBA_IF_TRUE:
 765        if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
 766          i++;
 767        }
 768        break;
 769      case CBA_SLIDE_CODE:
 770		{
 771          u32 address = cheatsList[i].address;
 772          u16 value = cheatsList[i].value;
 773          i++;
 774          if(i < cheatsNumber) {
 775            int count = ((cheatsList[i].address - 1) & 0xFFFF);
 776            u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF;
 777            int inc = cheatsList[i].value;
 778            for(int x = 0; x <= count ; x++) {
 779              CPUWriteHalfWord(address, value);
 780              address += inc;
 781              value += vinc;
 782			}
 783		  }
 784		}
 785        break;
 786      case CBA_IF_FALSE:
 787        if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value){
 788          i++;
 789        }
 790      break;
 791      case CBA_AND:
 792        CPUWriteHalfWord(cheatsList[i].address,
 793                         CPUReadHalfWord(cheatsList[i].address) &
 794                         cheatsList[i].value);
 795        break;
 796      case GSA_8_BIT_IF_TRUE:
 797        if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
 798          i++;
 799        }
 800        break;
 801      case GSA_32_BIT_IF_TRUE:
 802        if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
 803          i++;
 804        }
 805        break;
 806      case GSA_8_BIT_IF_FALSE:
 807        if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
 808          i++;
 809        }
 810        break;
 811      case GSA_32_BIT_IF_FALSE:
 812        if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
 813          i++;
 814        }
 815        break;
 816      case GSA_8_BIT_FILL:
 817		{
 818          u32 addr = cheatsList[i].address;
 819          u8 v = cheatsList[i].value & 0xff;
 820          u32 end = addr + (cheatsList[i].value >> 8);
 821          do {
 822            CPUWriteByte(addr, v);
 823            addr++;
 824		  } while (addr <= end);
 825		}
 826        break;
 827      case GSA_16_BIT_FILL:
 828		{
 829          u32 addr = cheatsList[i].address;
 830          u16 v = cheatsList[i].value & 0xffff;
 831          u32 end = addr + ((cheatsList[i].value >> 16) << 1);
 832          do {
 833            CPUWriteHalfWord(addr, v);
 834            addr+=2;
 835		  } while (addr <= end);
 836		}
 837        break;
 838      case GSA_8_BIT_IF_TRUE2:
 839        if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
 840          i+=2;
 841        }
 842        break;
 843      case GSA_16_BIT_IF_TRUE2:
 844        if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
 845          i+=2;
 846        }
 847        break;
 848      case GSA_32_BIT_IF_TRUE2:
 849        if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
 850          i+=2;
 851        }
 852        break;
 853      case GSA_8_BIT_IF_FALSE2:
 854        if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
 855          i+=2;
 856        }
 857        break;
 858      case GSA_16_BIT_IF_FALSE2:
 859        if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
 860          i+=2;
 861        }
 862        break;
 863      case GSA_32_BIT_IF_FALSE2:
 864        if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
 865          i+=2;
 866        }
 867        break;
 868      case CBA_ADD:
 869        if ((cheatsList[i].address & 1) == 0) {
 870          CPUWriteHalfWord(cheatsList[i].address,
 871                           CPUReadHalfWord(cheatsList[i].address) +
 872                           cheatsList[i].value);
 873        } else {
 874          CPUWriteMemory(cheatsList[i].address & 0x0FFFFFFE,
 875                           CPUReadMemory(cheatsList[i].address & 0x0FFFFFFE) +
 876                           cheatsList[i].value);
 877        }
 878        break;
 879      case CBA_OR:
 880        CPUWriteHalfWord(cheatsList[i].address,
 881                         CPUReadHalfWord(cheatsList[i].address) |
 882                         cheatsList[i].value);
 883        break;
 884      case CBA_GT:
 885        if (!(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value)){
 886          i++;
 887        }
 888        break;
 889      case CBA_LT:
 890        if (!(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value)){
 891          i++;
 892        }
 893        break;
 894      case CBA_SUPER:
 895		{
 896          int count = 2*((cheatsList[i].value -1) & 0xFFFF)+1;
 897          u32 address = cheatsList[i].address;
 898          for(int x = 0; x <= count; x++) {
 899            u8 b;
 900            int res = x % 6;
 901		    if (res==0)
 902		 	  i++;
 903            if(res < 4)
 904              b = (cheatsList[i].address >> (24-8*res)) & 0xFF;
 905            else
 906              b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0xFF;
 907            CPUWriteByte(address, b);
 908            address++;
 909		  }
 910		}
 911        break;
 912      case GSA_8_BIT_POINTER :
 913        if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
 914            ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
 915        {
 916          CPUWriteByte(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFFFF00) >> 8),
 917                       cheatsList[i].value & 0xFF);
 918        }
 919        break;
 920      case GSA_16_BIT_POINTER :
 921        if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
 922            ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
 923        {
 924          CPUWriteHalfWord(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFF0000) >> 15),
 925                       cheatsList[i].value & 0xFFFF);
 926        }
 927        break;
 928      case GSA_32_BIT_POINTER :
 929        if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
 930            ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
 931        {
 932          CPUWriteMemory(CPUReadMemory(cheatsList[i].address),
 933                       cheatsList[i].value);
 934        }
 935        break;
 936      case GSA_8_BIT_ADD :
 937        CPUWriteByte(cheatsList[i].address,
 938                    ((cheatsList[i].value & 0xFF) + CPUReadMemory(cheatsList[i].address)) & 0xFF);
 939        break;
 940      case GSA_16_BIT_ADD :
 941        CPUWriteHalfWord(cheatsList[i].address,
 942                        ((cheatsList[i].value & 0xFFFF) + CPUReadMemory(cheatsList[i].address)) & 0xFFFF);
 943        break;
 944      case GSA_32_BIT_ADD :
 945        CPUWriteMemory(cheatsList[i].address ,
 946                       (cheatsList[i].value + CPUReadMemory(cheatsList[i].address)) & 0xFFFFFFFF);
 947        break;
 948      case GSA_8_BIT_IF_LOWER_U:
 949        if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
 950          i++;
 951        }
 952        break;
 953      case GSA_16_BIT_IF_LOWER_U:
 954        if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
 955          i++;
 956        }
 957        break;
 958      case GSA_32_BIT_IF_LOWER_U:
 959        if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
 960          i++;
 961        }
 962        break;
 963      case GSA_8_BIT_IF_HIGHER_U:
 964        if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
 965          i++;
 966        }
 967        break;
 968      case GSA_16_BIT_IF_HIGHER_U:
 969        if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
 970          i++;
 971        }
 972        break;
 973      case GSA_32_BIT_IF_HIGHER_U:
 974        if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
 975          i++;
 976        }
 977        break;
 978      case GSA_8_BIT_IF_AND:
 979        if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
 980          i++;
 981        }
 982        break;
 983      case GSA_16_BIT_IF_AND:
 984        if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
 985          i++;
 986        }
 987        break;
 988      case GSA_32_BIT_IF_AND:
 989        if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
 990          i++;
 991        }
 992        break;
 993      case GSA_8_BIT_IF_LOWER_U2:
 994        if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
 995          i+=2;
 996        }
 997        break;
 998      case GSA_16_BIT_IF_LOWER_U2:
 999        if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
1000          i+=2;
1001        }
1002        break;
1003      case GSA_32_BIT_IF_LOWER_U2:
1004        if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
1005          i+=2;
1006        }
1007        break;
1008      case GSA_8_BIT_IF_HIGHER_U2:
1009        if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
1010          i+=2;
1011        }
1012        break;
1013      case GSA_16_BIT_IF_HIGHER_U2:
1014        if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
1015          i+=2;
1016        }
1017        break;
1018      case GSA_32_BIT_IF_HIGHER_U2:
1019        if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
1020          i+=2;
1021        }
1022        break;
1023      case GSA_8_BIT_IF_AND2:
1024        if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
1025          i+=2;
1026        }
1027        break;
1028      case GSA_16_BIT_IF_AND2:
1029        if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
1030          i+=2;
1031        }
1032        break;
1033      case GSA_32_BIT_IF_AND2:
1034        if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
1035          i+=2;
1036        }
1037        break;
1038      case GSA_ALWAYS:
1039        i++;
1040        break;
1041      case GSA_ALWAYS2:
1042        i+=2;
1043        break;
1044      case GSA_8_BIT_IF_LOWER_S:
1045        if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
1046          i++;
1047        }
1048        break;
1049      case GSA_16_BIT_IF_LOWER_S:
1050        if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
1051          i++;
1052        }
1053        break;
1054      case GSA_32_BIT_IF_LOWER_S:
1055        if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
1056          i++;
1057        }
1058        break;
1059      case GSA_8_BIT_IF_HIGHER_S:
1060        if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
1061          i++;
1062        }
1063        break;
1064      case GSA_16_BIT_IF_HIGHER_S:
1065        if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
1066          i++;
1067        }
1068        break;
1069      case GSA_32_BIT_IF_HIGHER_S:
1070        if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
1071          i++;
1072        }
1073        break;
1074      case GSA_8_BIT_IF_LOWER_S2:
1075        if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
1076          i+=2;
1077        }
1078        break;
1079      case GSA_16_BIT_IF_LOWER_S2:
1080        if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
1081          i+=2;
1082        }
1083        break;
1084      case GSA_32_BIT_IF_LOWER_S2:
1085        if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
1086          i+=2;
1087        }
1088        break;
1089      case GSA_8_BIT_IF_HIGHER_S2:
1090        if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
1091          i+=2;
1092        }
1093        break;
1094      case GSA_16_BIT_IF_HIGHER_S2:
1095        if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
1096          i+=2;
1097        }
1098        break;
1099      case GSA_32_BIT_IF_HIGHER_S2:
1100        if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
1101          i+=2;
1102        }
1103        break;
1104      case GSA_16_BIT_WRITE_IOREGS:
1105        if ((cheatsList[i].address <= 0x3FF) && (cheatsList[i].address != 0x6) &&
1106            (cheatsList[i].address != 0x130))
1107          ioMem[cheatsList[i].address & 0x3FE]=cheatsList[i].value & 0xFFFF;
1108        break;
1109      case GSA_32_BIT_WRITE_IOREGS:
1110        if (cheatsList[i].address<=0x3FF)
1111        {
1112          if (((cheatsList[i].address & 0x3FC) != 0x6) && ((cheatsList[i].address & 0x3FC) != 0x130))
1113            ioMem[cheatsList[i].address & 0x3FC]= (cheatsList[i].value & 0xFFFF);
1114          if ((((cheatsList[i].address & 0x3FC)+2) != 0x6) && ((cheatsList[i].address & 0x3FC) +2) != 0x130)
1115            ioMem[(cheatsList[i].address & 0x3FC) + 2 ]= ((cheatsList[i].value>>16 ) & 0xFFFF);
1116        }
1117        break;
1118      case GSA_8_BIT_IF_TRUE3:
1119        if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
1120          onoff=false;
1121        }
1122        break;
1123      case GSA_16_BIT_IF_TRUE3:
1124        if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
1125          onoff=false;
1126        }
1127        break;
1128      case GSA_32_BIT_IF_TRUE3:
1129        if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
1130          onoff=false;
1131        }
1132        break;
1133      case GSA_8_BIT_IF_FALSE3:
1134        if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
1135          onoff=false;
1136        }
1137        break;
1138      case GSA_16_BIT_IF_FALSE3:
1139        if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
1140          onoff=false;
1141        }
1142        break;
1143      case GSA_32_BIT_IF_FALSE3:
1144        if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
1145          onoff=false;
1146        }
1147        break;
1148      case GSA_8_BIT_IF_LOWER_S3:
1149        if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
1150          onoff=false;
1151        }
1152        break;
1153      case GSA_16_BIT_IF_LOWER_S3:
1154        if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
1155          onoff=false;
1156        }
1157        break;
1158      case GSA_32_BIT_IF_LOWER_S3:
1159        if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
1160          onoff=false;
1161        }
1162        break;
1163      case GSA_8_BIT_IF_HIGHER_S3:
1164        if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
1165          onoff=false;
1166        }
1167        break;
1168      case GSA_16_BIT_IF_HIGHER_S3:
1169        if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
1170          onoff=false;
1171        }
1172        break;
1173      case GSA_32_BIT_IF_HIGHER_S3:
1174        if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
1175          onoff=false;
1176        }
1177        break;
1178      case GSA_8_BIT_IF_LOWER_U3:
1179        if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
1180          onoff=false;
1181        }
1182        break;
1183      case GSA_16_BIT_IF_LOWER_U3:
1184        if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
1185          onoff=false;
1186        }
1187        break;
1188      case GSA_32_BIT_IF_LOWER_U3:
1189        if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
1190          onoff=false;
1191        }
1192        break;
1193      case GSA_8_BIT_IF_HIGHER_U3:
1194        if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
1195          onoff=false;
1196        }
1197        break;
1198      case GSA_16_BIT_IF_HIGHER_U3:
1199        if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
1200          onoff=false;
1201        }
1202        break;
1203      case GSA_32_BIT_IF_HIGHER_U3:
1204        if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
1205          onoff=false;
1206        }
1207        break;
1208      case GSA_8_BIT_IF_AND3:
1209        if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
1210          onoff=false;
1211        }
1212        break;
1213      case GSA_16_BIT_IF_AND3:
1214        if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
1215          onoff=false;
1216        }
1217        break;
1218      case GSA_32_BIT_IF_AND3:
1219        if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
1220          onoff=false;
1221        }
1222        break;
1223      case GSA_ALWAYS3:
1224        if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
1225          onoff=false;
1226        }
1227        break;
1228      case GSA_GROUP_WRITE:
1229      	{
1230          int count = ((cheatsList[i].address) & 0xFFFE) +1;
1231          u32 value = cheatsList[i].value;
1232		  if (count==0)
1233			  i++;
1234		  else
1235            for (int x = 1; x <= count; x++) {
1236				if ((x % 2) ==0){
1237					if (x<count)
1238						i++;
1239					CPUWriteMemory(cheatsList[i].rawaddress, value);
1240				}
1241				else
1242					CPUWriteMemory(cheatsList[i].value, value);
1243			}
1244		}
1245		break;
1246      case GSA_32_BIT_ADD2:
1247        CPUWriteMemory(cheatsList[i].value ,
1248                       (CPUReadMemory(cheatsList[i].value) + cheatsList[i+1].rawaddress) & 0xFFFFFFFF);
1249        i++;
1250		break;
1251      case GSA_32_BIT_SUB2:
1252        CPUWriteMemory(cheatsList[i].value ,
1253                       (CPUReadMemory(cheatsList[i].value) - cheatsList[i+1].rawaddress) & 0xFFFFFFFF);
1254        i++;
1255		break;
1256      case GSA_16_BIT_IF_LOWER_OR_EQ_U:
1257        if(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value) {
1258          i++;
1259        }
1260        break;
1261      case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
1262        if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) {
1263          i++;
1264        }
1265        break;
1266      case GSA_16_BIT_MIF_TRUE:
1267        if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
1268          i+=((cheatsList[i].rawaddress >> 0x10) & 0xFF);
1269        }
1270        break;
1271      case GSA_16_BIT_MIF_FALSE:
1272        if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
1273          i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
1274        }
1275        break;
1276      case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
1277        if(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value) {
1278          i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
1279        }
1280        break;
1281      case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
1282        if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) {
1283          i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
1284        }
1285        break;
1286      case CHEATS_16_BIT_WRITE:
1287        if ((cheatsList[i].address>>24)>=0x08) {
1288          CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
1289        } else {
1290          CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
1291        }
1292        break;
1293      case CHEATS_32_BIT_WRITE:
1294        if ((cheatsList[i].address>>24)>=0x08) {
1295          CHEAT_PATCH_ROM_32BIT(cheatsList[i].address, cheatsList[i].value);
1296        } else {
1297          CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
1298        }
1299        break;
1300      }
1301    }
1302  }
1303  for (i = 0; i<4; i++)
1304    if (rompatch2addr [i] != 0)
1305      CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2val [i]);
1306  return ticks;
1307}
1308
1309void cheatsAdd(const char *codeStr,
1310               const char *desc,
1311               u32 rawaddress,
1312               u32 address,
1313               u32 value,
1314               int code,
1315               int size)
1316{
1317  if(cheatsNumber < 100) {
1318    int x = cheatsNumber;
1319    cheatsList[x].code = code;
1320    cheatsList[x].size = size;
1321    cheatsList[x].rawaddress = rawaddress;
1322    cheatsList[x].address = address;
1323    cheatsList[x].value = value;
1324    strcpy(cheatsList[x].codestring, codeStr);
1325    strcpy(cheatsList[x].desc, desc);
1326    cheatsList[x].enabled = true;
1327    cheatsList[x].status = 0;
1328
1329    // we only store the old value for this simple codes. ROM patching
1330    // is taken care when it actually patches the ROM
1331    switch(cheatsList[x].size) {
1332    case INT_8_BIT_WRITE:
1333      cheatsList[x].oldValue = CPUReadByte(address);
1334      break;
1335    case INT_16_BIT_WRITE:
1336      cheatsList[x].oldValue = CPUReadHalfWord(address);
1337      break;
1338    case INT_32_BIT_WRITE:
1339      cheatsList[x].oldValue = CPUReadMemory(address);
1340      break;
1341    case CHEATS_16_BIT_WRITE:
1342      cheatsList[x].oldValue = CPUReadHalfWord(address);
1343      break;
1344    case CHEATS_32_BIT_WRITE:
1345      cheatsList[x].oldValue = CPUReadMemory(address);
1346      break;
1347    }
1348    cheatsNumber++;
1349  }
1350}
1351
1352void cheatsDelete(int number, bool restore)
1353{
1354  if(number < cheatsNumber && number >= 0) {
1355    int x = number;
1356
1357    if(restore) {
1358      switch(cheatsList[x].size) {
1359      case INT_8_BIT_WRITE:
1360        CPUWriteByte(cheatsList[x].address, (u8)cheatsList[x].oldValue);
1361        break;
1362      case INT_16_BIT_WRITE:
1363        CPUWriteHalfWord(cheatsList[x].address, (u16)cheatsList[x].oldValue);
1364        break;
1365      case INT_32_BIT_WRITE:
1366        CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
1367        break;
1368      case CHEATS_16_BIT_WRITE:
1369        if ((cheatsList[x].address>>24)>=0x08) {
1370          CHEAT_PATCH_ROM_16BIT(cheatsList[x].address, cheatsList[x].oldValue);
1371        } else {
1372          CPUWriteHalfWord(cheatsList[x].address, cheatsList[x].oldValue);
1373        }
1374        break;
1375      case CHEATS_32_BIT_WRITE:
1376        if ((cheatsList[x].address>>24)>=0x08) {
1377          CHEAT_PATCH_ROM_32BIT(cheatsList[x].address, cheatsList[x].oldValue);
1378        } else {
1379          CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
1380        }
1381      case GSA_16_BIT_ROM_PATCH:
1382        if(cheatsList[x].status & 1) {
1383          cheatsList[x].status &= ~1;
1384          CHEAT_PATCH_ROM_16BIT(cheatsList[x].address,
1385                                cheatsList[x].oldValue);
1386        }
1387        break;
1388      case GSA_16_BIT_ROM_PATCH2C:
1389      case GSA_16_BIT_ROM_PATCH2D:
1390      case GSA_16_BIT_ROM_PATCH2E:
1391      case GSA_16_BIT_ROM_PATCH2F:
1392        if(cheatsList[x].status & 1) {
1393          cheatsList[x].status &= ~1;
1394        }
1395        break;
1396      case MASTER_CODE:
1397        mastercode=0;
1398        break;
1399      }
1400    }
1401    if((x+1) <  cheatsNumber) {
1402      memcpy(&cheatsList[x], &cheatsList[x+1], sizeof(CheatsData)*
1403             (cheatsNumber-x-1));
1404    }
1405    cheatsNumber--;
1406  }
1407}
1408
1409void cheatsDeleteAll(bool restore)
1410{
1411  for(int i = cheatsNumber-1; i >= 0; i--) {
1412    cheatsDelete(i, restore);
1413  }
1414}
1415
1416void cheatsEnable(int i)
1417{
1418  if(i >= 0 && i < cheatsNumber) {
1419    cheatsList[i].enabled = true;
1420    mastercode = 0;
1421  }
1422}
1423
1424void cheatsDisable(int i)
1425{
1426  if(i >= 0 && i < cheatsNumber) {
1427    switch(cheatsList[i].size) {
1428    case GSA_16_BIT_ROM_PATCH:
1429      if(cheatsList[i].status & 1) {
1430        cheatsList[i].status &= ~1;
1431        CHEAT_PATCH_ROM_16BIT(cheatsList[i].address,
1432                              cheatsList[i].oldValue);
1433      }
1434      break;
1435    case GSA_16_BIT_ROM_PATCH2C:
1436    case GSA_16_BIT_ROM_PATCH2D:
1437    case GSA_16_BIT_ROM_PATCH2E:
1438    case GSA_16_BIT_ROM_PATCH2F:
1439      if(cheatsList[i].status & 1) {
1440        cheatsList[i].status &= ~1;
1441      }
1442      break;
1443    case MASTER_CODE:
1444        mastercode=0;
1445      break;
1446    }
1447    cheatsList[i].enabled = false;
1448  }
1449}
1450
1451bool cheatsVerifyCheatCode(const char *code, const char *desc)
1452{
1453  size_t len = strlen(code);
1454  if(len != 11 && len != 13 && len != 17) {
1455    systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s': wrong length"), code);
1456    return false;
1457  }
1458
1459  if(code[8] != ':') {
1460    systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s': no colon"), code);
1461    return false;
1462  }
1463
1464  size_t i;
1465  for(i = 0; i < 8; i++) {
1466    if(!CHEAT_IS_HEX(code[i])) {
1467      // wrong cheat
1468      systemMessage(MSG_INVALID_CHEAT_CODE,
1469                    N_("Invalid cheat code '%s': first part is not hex"), code);
1470      return false;
1471    }
1472  }
1473  for(i = 9; i < len; i++) {
1474    if(!CHEAT_IS_HEX(code[i])) {
1475      // wrong cheat
1476      systemMessage(MSG_INVALID_CHEAT_CODE,
1477                    N_("Invalid cheat code '%s' second part is not hex"), code);
1478      return false;
1479    }
1480  }
1481
1482  u32 address = 0;
1483  u32 value = 0;
1484
1485  char buffer[10];
1486  strncpy(buffer, code, 8);
1487  buffer[8] = 0;
1488  sscanf(buffer, "%x", &address);
1489
1490  switch(address >> 24) {
1491  case 0x02:
1492  case 0x03:
1493  case 0x04:
1494  case 0x05:
1495  case 0x06:
1496  case 0x07:
1497  case 0x08:
1498  case 0x09:
1499  case 0x0A:
1500  case 0x0B:
1501  case 0x0C:
1502  case 0x0D:
1503    break;
1504  default:
1505    systemMessage(MSG_INVALID_CHEAT_CODE_ADDRESS,
1506                  N_("Invalid cheat code address: %08x"),
1507                  address);
1508    return false;
1509  }
1510
1511  strncpy(buffer, &code[9], 8);
1512  sscanf(buffer, "%x", &value);
1513  int type = 0;
1514  if(len == 13)
1515    type = 114;
1516  if(len == 17)
1517    type = 115;
1518  cheatsAdd(code, desc, address, address, value, type, type);
1519  return true;
1520}
1521
1522void cheatsAddCheatCode(const char *code, const char *desc)
1523{
1524  cheatsVerifyCheatCode(code, desc);
1525}
1526
1527u16 cheatsGSAGetDeadface(bool v3)
1528{
1529  for(int i = cheatsNumber-1; i >= 0; i--)
1530    if ((cheatsList[i].address == 0xDEADFACE) && (cheatsList[i].code == (v3 ? 257 : 256)))
1531      return cheatsList[i].value & 0xFFFF;
1532	return 0;
1533}
1534
1535void cheatsGSAChangeEncryption(u16 value, bool v3) {
1536	int i;
1537	u8 *deadtable1, *deadtable2;
1538
1539	if (v3) {
1540		deadtable1 = (u8*)(&v3_deadtable1);
1541		deadtable2 = (u8*)(&v3_deadtable2);
1542	        for (i = 0; i < 4; i++)
1543		  seeds_v3[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2);
1544	}
1545	else {
1546		deadtable1 = (u8*)(&v1_deadtable1);
1547		deadtable2 = (u8*)(&v1_deadtable2);
1548		for (i = 0; i < 4; i++){
1549		  seeds_v1[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2);
1550		}
1551	}
1552}
1553
1554u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2) {
1555	int i;
1556	u32 newseed = 0;
1557
1558	for (i = 0; i < 4; i++)
1559		newseed = ((newseed << 8) | ((deadtable1[(i + upper) & 0xFF] + deadtable2[seed]) & 0xFF));
1560
1561	return newseed;
1562}
1563
1564void cheatsDecryptGSACode(u32& address, u32& value, bool v3)
1565{
1566  u32 rollingseed = 0xC6EF3720;
1567  u32 *seeds = v3 ? seeds_v3 : seeds_v1;
1568
1569  int bitsleft = 32;
1570  while (bitsleft > 0) {
1571    value -= ((((address << 4) + seeds[2]) ^ (address + rollingseed)) ^
1572              ((address >> 5) + seeds[3]));
1573    address -= ((((value << 4) + seeds[0]) ^ (value + rollingseed)) ^
1574                ((value >> 5) + seeds[1]));
1575    rollingseed -= 0x9E3779B9;
1576    bitsleft--;
1577  }
1578}
1579
1580void cheatsAddGSACode(const char *code, const char *desc, bool v3)
1581{
1582  if(strlen(code) != 16) {
1583    // wrong cheat
1584    systemMessage(MSG_INVALID_GSA_CODE,
1585                  N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
1586    return;
1587  }
1588
1589  int i;
1590  for(i = 0; i < 16; i++) {
1591    if(!CHEAT_IS_HEX(code[i])) {
1592      // wrong cheat
1593      systemMessage(MSG_INVALID_GSA_CODE,
1594                    N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
1595      return;
1596    }
1597  }
1598
1599  char buffer[10];
1600  strncpy(buffer, code, 8);
1601  buffer[8] = 0;
1602  u32 address;
1603  sscanf(buffer, "%x", &address);
1604  strncpy(buffer, &code[8], 8);
1605  buffer[8] = 0;
1606  u32 value;
1607  sscanf(buffer, "%x", &value);
1608  cheatsGSAChangeEncryption(cheatsGSAGetDeadface (v3), v3);
1609  cheatsDecryptGSACode(address, value, v3);
1610
1611  if(value == 0x1DC0DE) {
1612    u32 gamecode = READ32LE(((u32 *)&rom[0xac]));
1613    if(gamecode != address) {
1614      char buffer[5];
1615      *((u32 *)buffer) = address;
1616      buffer[4] = 0;
1617      char buffer2[5];
1618      *((u32 *)buffer2) = READ32LE(((u32 *)&rom[0xac]));
1619      buffer2[4] = 0;
1620      systemMessage(MSG_GBA_CODE_WARNING, N_("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly."),
1621                    buffer, buffer2);
1622    }
1623    cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, v3 ? 257 : 256,
1624              UNKNOWN_CODE);
1625    return;
1626  }
1627  if(isMultilineWithData(cheatsNumber-1)) {
1628    cheatsAdd(code, desc, address, address, value, v3 ? 257 : 256, UNKNOWN_CODE);
1629    return;
1630  }
1631  if(v3) {
1632    int type = ((address >> 25) & 127) | ((address >> 17) & 0x80);
1633    u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF);
1634    u16 mcode = (address>>24 & 0xFF);
1635
1636    if ((mcode & 0xFE) == 0xC4)
1637    {
1638      cheatsAdd(code, desc, address, (address & 0x1FFFFFF) | (0x08000000),
1639        value, 257, MASTER_CODE);
1640      mastercode = (address & 0x1FFFFFF) | (0x08000000);
1641    }
1642    else
1643    switch(type) {
1644    case 0x00:
1645      if(address == 0) {
1646        type = (value >> 25) & 127;
1647        addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF);
1648        switch(type) {
1649        case 0x04:
1650          cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN);
1651          break;
1652        case 0x08:
1653          cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_GS_WRITE2);
1654          break;
1655        case 0x09:
1656          cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_GS_WRITE2);
1657          break;
1658        case 0x0a:
1659          cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_GS_WRITE2);
1660          break;
1661        case 0x0c:
1662          cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2C);
1663          break;
1664        case 0x0d:
1665          cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2D);
1666          break;
1667        case 0x0e:
1668          cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2E);
1669          break;
1670        case 0x0f:
1671          cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2F);
1672          break;
1673        case 0x20:
1674          cheatsAdd(code, desc, address, 0, addr, 257, GSA_CODES_ON);
1675          break;
1676        case 0x40:
1677          cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_SLIDE);
1678          break;
1679        case 0x41:
1680          cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_SLIDE);
1681          break;
1682        case 0x42:
1683          cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_SLIDE);
1684          break;
1685        default:
1686          cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE);
1687          break;
1688        }
1689      } else
1690        cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_FILL);
1691      break;
1692    case 0x01:
1693      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_FILL);
1694      break;
1695    case 0x02:
1696      cheatsAdd(code, desc, address, addr, value, 257, INT_32_BIT_WRITE);
1697      break;
1698    case 0x04:
1699      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE);
1700      break;
1701    case 0x05:
1702      cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_TRUE);
1703      break;
1704    case 0x06:
1705      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE);
1706      break;
1707    case 0x07:
1708      cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS);
1709      break;
1710    case 0x08:
1711      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE);
1712      break;
1713    case 0x09:
1714      cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_FALSE);
1715      break;
1716    case 0x0a:
1717      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE);
1718      break;
1719    case 0xc:
1720      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S);
1721      break;
1722    case 0xd:
1723      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S);
1724      break;
1725    case 0xe:
1726      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S);
1727      break;
1728    case 0x10:
1729      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S);
1730      break;
1731    case 0x11:
1732      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S);
1733      break;
1734    case 0x12:
1735      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S);
1736      break;
1737    case 0x14:
1738      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U);
1739      break;
1740    case 0x15:
1741      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U);
1742      break;
1743    case 0x16:
1744      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U);
1745      break;
1746    case 0x18:
1747      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U);
1748      break;
1749    case 0x19:
1750      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U);
1751      break;
1752    case 0x1A:
1753      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U);
1754      break;
1755    case 0x1C:
1756      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND);
1757      break;
1758    case 0x1D:
1759      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND);
1760      break;
1761    case 0x1E:
1762      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND);
1763      break;
1764    case 0x20:
1765      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_POINTER);
1766      break;
1767    case 0x21:
1768      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_POINTER);
1769      break;
1770    case 0x22:
1771      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_POINTER);
1772      break;
1773    case 0x24:
1774      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE2);
1775      break;
1776    case 0x25:
1777      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE2);
1778      break;
1779    case 0x26:
1780      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE2);
1781      break;
1782    case 0x27:
1783      cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS2);
1784      break;
1785    case 0x28:
1786      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE2);
1787      break;
1788    case 0x29:
1789      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE2);
1790      break;
1791    case 0x2a:
1792      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE2);
1793      break;
1794    case 0x2c:
1795      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S2);
1796      break;
1797    case 0x2d:
1798      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S2);
1799      break;
1800    case 0x2e:
1801      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S2);
1802      break;
1803    case 0x30:
1804      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S2);
1805      break;
1806    case 0x31:
1807      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S2);
1808      break;
1809    case 0x32:
1810      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S2);
1811      break;
1812    case 0x34:
1813      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U2);
1814      break;
1815    case 0x35:
1816      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U2);
1817      break;
1818    case 0x36:
1819      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U2);
1820      break;
1821    case 0x38:
1822      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U2);
1823      break;
1824    case 0x39:
1825      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U2);
1826      break;
1827    case 0x3A:
1828      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U2);
1829      break;
1830    case 0x3C:
1831      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND2);
1832      break;
1833    case 0x3D:
1834      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND2);
1835      break;
1836    case 0x3E:
1837      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND2);
1838      break;
1839    case 0x40:
1840      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_ADD);
1841      break;
1842    case 0x41:
1843      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_ADD);
1844      break;
1845    case 0x42:
1846      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_ADD);
1847      break;
1848    case 0x44:
1849      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE3);
1850      break;
1851    case 0x45:
1852      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE3);
1853      break;
1854    case 0x46:
1855      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE3);
1856      break;
1857	  case 0x47:
1858      cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS3);
1859      break;
1860    case 0x48:
1861      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE3);
1862      break;
1863    case 0x49:
1864      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE3);
1865      break;
1866    case 0x4a:
1867      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE3);
1868      break;
1869    case 0x4c:
1870      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S3);
1871      break;
1872    case 0x4d:
1873      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S3);
1874      break;
1875    case 0x4e:
1876      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S3);
1877      break;
1878    case 0x50:
1879      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S3);
1880      break;
1881    case 0x51:
1882      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S3);
1883      break;
1884    case 0x52:
1885      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S3);
1886      break;
1887    case 0x54:
1888      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U3);
1889      break;
1890    case 0x55:
1891      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U3);
1892      break;
1893    case 0x56:
1894      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U3);
1895      break;
1896    case 0x58:
1897      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U3);
1898      break;
1899    case 0x59:
1900      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U3);
1901      break;
1902    case 0x5a:
1903      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U3);
1904      break;
1905    case 0x5c:
1906      cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND3);
1907      break;
1908    case 0x5d:
1909      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND3);
1910      break;
1911    case 0x5e:
1912      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND3);
1913      break;
1914    case 0x63:
1915      cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_WRITE_IOREGS);
1916      break;
1917    case 0xE3:
1918      cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_WRITE_IOREGS);
1919      break;
1920    default:
1921      cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE);
1922      break;
1923    }
1924  } else {
1925    int type = (address >> 28) & 15;
1926    switch(type) {
1927    case 0:
1928    case 1:
1929    case 2:
1930      cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, type);
1931      break;
1932    case 3:
1933	  switch ((address >> 0x10) & 0xFF){
1934	  case 0x00:
1935        cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_GROUP_WRITE);
1936	    break;
1937	  case 0x10:
1938	    cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFF, 256, GSA_32_BIT_ADD );
1939	    break;
1940	  case 0x20:
1941	    cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFF)+1), 256, GSA_32_BIT_ADD );
1942	    break;
1943	  case 0x30:
1944	    cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, GSA_32_BIT_ADD );
1945	    break;
1946	  case 0x40:
1947	    cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFFFF)+1), 256, GSA_32_BIT_ADD );
1948	    break;
1949	  case 0x50:
1950	    cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_ADD2);
1951	    break;
1952	  case 0x60:
1953	    cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_SUB2);
1954	    break;
1955      default:
1956        // unsupported code
1957        cheatsAdd(code, desc, address, address, value, 256,
1958                  UNKNOWN_CODE);
1959        break;
1960      }
1961      break;
1962    case 6:
1963      address <<= 1;
1964      type = (value >> 24) & 0xFF;
1965      if(type == 0x00) {
1966        cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
1967                  GSA_16_BIT_ROM_PATCH);
1968        break;
1969      }
1970      // unsupported code
1971      cheatsAdd(code, desc, address, address, value, 256,
1972                UNKNOWN_CODE);
1973      break;
1974    case 8:
1975      switch((address >> 20) & 15) {
1976      case 1:
1977        cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256,
1978                  GSA_8_BIT_GS_WRITE);
1979        break;
1980      case 2:
1981        cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256,
1982                  GSA_16_BIT_GS_WRITE);
1983        break;
1984      case 4:
1985		// This code is buggy : the value is always set to 0 !
1986        cheatsAdd(code, desc, address, address & 0x0F0FFFFF, 0, 256,
1987                  GSA_32_BIT_GS_WRITE);
1988        break;
1989      case 15:
1990        cheatsAdd(code, desc, address, 0, value & 0xFFFF, 256, GSA_SLOWDOWN);
1991        break;
1992      default:
1993        // unsupported code
1994        cheatsAdd(code, desc, address, address, value, 256,
1995                  UNKNOWN_CODE);
1996        break;
1997      }
1998      break;
1999    case 0x0d:
2000      if(address != 0xDEADFACE) {
2001        switch((value >> 20) & 0xF) {
2002        case 0:
2003        cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
2004                  CBA_IF_TRUE);
2005          break;
2006        case 1:
2007        cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
2008                  CBA_IF_FALSE);
2009          break;
2010        case 2:
2011        cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
2012                  GSA_16_BIT_IF_LOWER_OR_EQ_U);
2013          break;
2014        case 3:
2015        cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
2016                  GSA_16_BIT_IF_HIGHER_OR_EQ_U);
2017          break;
2018        default:
2019        // unsupported code
2020        cheatsAdd(code, desc, address, address, value, 256,
2021                  UNKNOWN_CODE);
2022          break;
2023		}
2024      } else
2025        cheatsAdd(code, desc, address, address, value, 256,
2026                  UNKNOWN_CODE);
2027      break;
2028    case 0x0e:
2029      switch((value >> 28) & 0xF) {
2030      case 0:
2031      cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
2032                GSA_16_BIT_MIF_TRUE);
2033        break;
2034      case 1:
2035      cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
2036                GSA_16_BIT_MIF_FALSE);
2037        break;
2038      case 2:
2039      cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
2040                GSA_16_BIT_MIF_LOWER_OR_EQ_U);
2041        break;
2042      case 3:
2043      cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
2044                GSA_16_BIT_MIF_HIGHER_OR_EQ_U);
2045        break;
2046      default:
2047        // unsupported code
2048        cheatsAdd(code, desc, address, address, value, 256,
2049                  UNKNOWN_CODE);
2050        break;
2051      }
2052      break;
2053      case 0x0f:
2054        cheatsAdd(code, desc, address, (address & 0xFFFFFFF), value, 256, MASTER_CODE);
2055        mastercode = (address & 0xFFFFFFF);
2056        break;
2057      default:
2058      // unsupported code
2059      cheatsAdd(code, desc, address, address, value, 256,
2060                UNKNOWN_CODE);
2061      break;
2062    }
2063  }
2064}
2065
2066bool cheatsImportGSACodeFile(const char *name, int game, bool v3)
2067{
2068  FILE *f = fopen(name, "rb");
2069  if(!f)
2070    return false;
2071
2072  int games = 0;
2073  int len = 0;
2074  fseek(f, 0x1e, SEEK_CUR);
2075  fread(&games, 1, 4, f);
2076  bool found = false;
2077  int g = 0;
2078  while(games > 0) {
2079    if(g == game) {
2080      found = true;
2081      break;
2082    }
2083    fread(&len, 1, 4, f);
2084    fseek(f,len,SEEK_CUR);
2085    int codes = 0;
2086    fread(&codes, 1, 4, f);
2087    while(codes > 0) {
2088      fread(&len, 1, 4, f);
2089      fseek(f, len, SEEK_CUR);
2090      fseek(f, 8, SEEK_CUR);
2091      fread(&len, 1, 4, f);
2092      fseek(f, len*12, SEEK_CUR);
2093      codes--;
2094    }
2095    games--;
2096    g++;
2097  }
2098  if(found) {
2099    char desc[256];
2100    char code[17];
2101    fread(&len, 1, 4, f);
2102    fseek(f, len, SEEK_CUR);
2103    int codes = 0;
2104    fread(&codes, 1, 4, f);
2105    while(codes > 0) {
2106      fread(&len, 1, 4, f);
2107      fread(desc, 1, len, f);
2108      desc[len] =0;
2109      desc[31] = 0;
2110      fread(&len, 1, 4, f);
2111      fseek(f, len, SEEK_CUR);
2112      fseek(f, 4, SEEK_CUR);
2113      fread(&len, 1, 4, f);
2114      while(len) {
2115        fseek(f, 4, SEEK_CUR);
2116        fread(code, 1, 8, f);
2117        fseek(f, 4, SEEK_CUR);
2118        fread(&code[8], 1, 8, f);
2119        code[16] = 0;
2120        cheatsAddGSACode(code, desc, v3);
2121        len -= 2;
2122      }
2123      codes--;
2124    }
2125  }
2126  fclose(f);
2127  return false;
2128}
2129
2130void cheatsCBAReverseArray(u8 *array, u8 *dest)
2131{
2132  dest[0] = array[3];
2133  dest[1] = array[2];
2134  dest[2] = array[1];
2135  dest[3] = array[0];
2136  dest[4] = array[5];
2137  dest[5] = array[4];
2138}
2139
2140void chatsCBAScramble(u8 *array, int count, u8 b)
2141{
2142  u8 *x = array + (count >> 3);
2143  u8 *y = array + (b >> 3);
2144  u32 z = *x & (1 << (count & 7));
2145  u32 x0 = (*x & (~(1 << (count & 7))));
2146  if (z != 0)
2147    z = 1;
2148  if ((*y & (1 << (b & 7))) != 0)
2149    x0 |= (1 << (count & 7));
2150  *x = x0;
2151  u32 temp = *y & (~(1 << (b & 7)));
2152  if (z != 0)
2153    temp |= (1 << (b & 7));
2154  *y = temp;
2155}
2156
2157u32 cheatsCBAGetValue(u8 *array)
2158{
2159  return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24;
2160}
2161
2162u16 cheatsCBAGetData(u8 *array)
2163{
2164  return array[4] | array[5]<<8;
2165}
2166
2167void cheatsCBAArrayToValue(u8 *array, u8 *dest)
2168{
2169  dest[0] = array[3];
2170  dest[1] = array[2];
2171  dest[2] = array[1];
2172  dest[3] = array[0];
2173  dest[4] = array[5];
2174  dest[5] = array[4];
2175}
2176
2177void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array)
2178{
2179  array[0] = 1;
2180  array[1] = value & 0xFF;
2181  array[2] = (address >> 0x10) & 0xFF;
2182  array[3] = (value >> 8) & 0xFF;
2183  array[4] = (address >> 0x18) & 0x0F;
2184  array[5] = address & 0xFFFF;
2185  array[6] = address;
2186  array[7] = value;
2187}
2188
2189u32 cheatsCBAEncWorker()
2190{
2191  u32 x = (cheatsCBATemporaryValue * 0x41c64e6d) + 0x3039;
2192  u32 y = (x * 0x41c64e6d) + 0x3039;
2193  u32 z = x >> 0x10;
2194  x = ((y >> 0x10) & 0x7fff) << 0x0f;
2195  z = (z << 0x1e) | x;
2196  x = (y * 0x41c64e6d) + 0x3039;
2197  cheatsCBATemporaryValue = x;
2198  return z | ((x >> 0x10) & 0x7fff);
2199}
2200
2201#define ROR(v, s) \
2202  (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
2203
2204u32 cheatsCBACalcIndex(u32 x, u32 y)
2205{
2206  if(y != 0) {
2207    if(y == 1)
2208      x = 0;
2209    else if(x == y)
2210      x = 0;
2211    if(y < 1)
2212      return x;
2213    else if(x < y)
2214      return x;
2215    u32 x0 = 1;
2216
2217    while(y < 0x10000000) {
2218      if(y < x) {
2219        y = y << 4;
2220        x0 = x0 << 4;
2221      } else break;
2222    }
2223
2224    while(y < 0x80000000) {
2225      if(y < x) {
2226        y = y << 1;
2227        x0 = x0 << 1;
2228      } else break;
2229    }
2230
2231  loop:
2232    u32 z = 0;
2233    if(x >= y)
2234      x -= y;
2235    if(x >= (y >> 1)) {
2236      x -= (y >> 1);
2237      z |= ROR(x0, 1);
2238    }
2239    if(x >= (y >> 2)) {
2240      x -= (y >> 2);
2241      z |= ROR(x0, 2);
2242    }
2243    if(x >= (y >> 3)) {
2244      x -= (y >> 3);
2245      z |= ROR(x0, 3);
2246    }
2247
2248    u32 temp = x0;
2249
2250    if(x != 0) {
2251      x0 = x0 >> 4;
2252      if(x0 != 0) {
2253        y = y >> 4;
2254        goto loop;
2255      }
2256    }
2257
2258    z = z & 0xe0000000;
2259
2260    if(z != 0) {
2261      if((temp & 7) == 0)
2262        return x;
2263    } else
2264      return x;
2265
2266    if((z & ROR(temp, 3)) != 0)
2267      x += y >> 3;
2268    if((z & ROR(temp, 2)) != 0)
2269      x += y >> 2;
2270    if((z & ROR(temp, 1)) != 0)
2271      x += y >> 1;
2272    return x;
2273  } else {
2274  }
2275  // should not happen in the current code
2276  return 0;
2277}
2278
2279void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count)
2280{
2281  int i;
2282  for(i = 0; i < count; i++)
2283    buffer[i] = i;
2284  for(i = 0; (u32)i < a; i++) {
2285    u32 a = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
2286    u32 b = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
2287    u32 t = buffer[a];
2288    buffer[a] = buffer[b];
2289    buffer[b] = t;
2290  }
2291}
2292
2293void cheatsCBAChangeEncryption(u32 *seed)
2294{
2295  int i;
2296
2297  cheatsCBATemporaryValue = (seed[1] ^ 0x1111);
2298  cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30);
2299  cheatsCBATemporaryValue = 0x4efad1c3;
2300
2301  for(i = 0; (u32)i < seed[4]; i++) {
2302    cheatsCBATemporaryValue = cheatsCBAEncWorker();
2303  }
2304  cheatsCBASeed[2] = cheatsCBAEncWorker();
2305  cheatsCBASeed[3] = cheatsCBAEncWorker();
2306
2307  cheatsCBATemporaryValue = seed[3] ^ 0xf254;
2308
2309  for(i = 0; (u32)i < seed[3]; i++) {
2310    cheatsCBATemporaryValue = cheatsCBAEncWorker();
2311  }
2312
2313  cheatsCBASeed[0] = cheatsCBAEncWorker();
2314  cheatsCBASeed[1] = cheatsCBAEncWorker();
2315
2316  *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6];
2317  *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7];
2318  *((u32 *)&cheatsCBACurrentSeed[8]) = 0;
2319}
2320
2321u16 cheatsCBAGenValue(u32 x, u32 y, u32 z)
2322{
2323  y <<= 0x10;
2324  z <<= 0x10;
2325  x <<= 0x18;
2326  u32 x0 = (int)y >> 0x10;
2327  z = (int)z >> 0x10;
2328  x = (int)x >> 0x10;
2329  for(int i = 0; i < 8; i++) {
2330    u32 temp = z ^ x;
2331    if ((int)temp >= 0) {
2332      temp = z << 0x11;
2333    }
2334    else {
2335      temp = z << 0x01;
2336      temp ^= x0;
2337      temp = temp << 0x10;
2338    }
2339    z = (int)temp >> 0x10;
2340    temp = x << 0x11;
2341    x = (int)temp >> 0x10;
2342  }
2343  return z & 0xffff;
2344}
2345
2346void cheatsCBAGenTable() {
2347  for (int i = 0; i < 0x100; i++) {
2348    cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0);
2349  }
2350  cheatsCBATableGenerated = true;
2351}
2352
2353u16 cheatsCBACalcCRC(u8 *rom, int count)
2354{
2355  u32 crc = 0xffffffff;
2356
2357  if (count & 3) {
2358    // 0x08000EAE
2359  } else {
2360    count = (count >> 2) - 1;
2361    if(count != -1) {
2362      while(count != -1) {
2363        crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
2364                                               ^ *rom++]) << 0x10) >> 0x10;
2365        crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
2366                                               ^ *rom++]) << 0x10) >> 0x10;
2367        crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
2368                                               ^ *rom++]) << 0x10) >> 0x10;
2369        crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
2370                                               ^ *rom++]) << 0x10) >> 0x10;
2371        count--;
2372      }
2373    }
2374  }
2375  return crc & 0xffff;
2376}
2377
2378void cheatsCBADecrypt(u8 *decrypt)
2379{
2380  u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
2381  u8 *array = &buffer[1];
2382
2383  cheatsCBAReverseArray(decrypt, array);
2384
2385  for(int count = 0x2f; count >= 0; count--) {
2386    chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]);
2387  }
2388  cheatsCBAArrayToValue(array, decrypt);
2389  *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^
2390    cheatsCBASeed[0];
2391  *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^
2392                           cheatsCBASeed[1]) & 0xffff;
2393
2394  cheatsCBAReverseArray(decrypt, array);
2395
2396  u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed);
2397  for(int i = 0; i <= 4; i++) {
2398    array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ;
2399  }
2400
2401  array[5] = (cs >> 8) ^ array[5];
2402
2403  for(int j = 5; j >=0; j--) {
2404    array[j] = (cs ^ array[j-1]) ^ array[j];
2405  }
2406
2407  cheatsCBAArrayToValue(array, decrypt);
2408
2409  *((u32 *)decrypt) = cheatsCBAGetValue(decrypt)
2410    ^ cheatsCBASeed[2];
2411  *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt)
2412                           ^ cheatsCBASeed[3]) & 0xffff;
2413}
2414
2415int cheatsCBAGetCount()
2416{
2417  int count = 0;
2418  for(int i = 0; i < cheatsNumber; i++) {
2419    if(cheatsList[i].code == 512)
2420      count++;
2421  }
2422  return count;
2423}
2424
2425bool cheatsCBAShouldDecrypt()
2426{
2427  for(int i = 0; i < cheatsNumber; i++) {
2428    if(cheatsList[i].code == 512) {
2429      return (cheatsList[i].codestring[0] == '9');
2430    }
2431  }
2432  return false;
2433}
2434
2435void cheatsAddCBACode(const char *code, const char *desc)
2436{
2437  if(strlen(code) != 13) {
2438    // wrong cheat
2439    systemMessage(MSG_INVALID_CBA_CODE,
2440                  N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
2441    return;
2442  }
2443
2444  int i;
2445  for(i = 0; i < 8; i++) {
2446    if(!CHEAT_IS_HEX(code[i])) {
2447      // wrong cheat
2448      systemMessage(MSG_INVALID_CBA_CODE,
2449                    N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
2450      return;
2451    }
2452  }
2453
2454  if(code[8] != ' ') {
2455    systemMessage(MSG_INVALID_CBA_CODE,
2456                  N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
2457    return;
2458  }
2459
2460  for(i = 9; i < 13; i++) {
2461    if(!CHEAT_IS_HEX(code[i])) {
2462      // wrong cheat
2463      systemMessage(MSG_INVALID_CBA_CODE,
2464                    N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
2465      return;
2466    }
2467  }
2468
2469  char buffer[10];
2470  strncpy(buffer, code, 8);
2471  buffer[8] = 0;
2472  u32 address;
2473  sscanf(buffer, "%x", &address);
2474  strncpy(buffer, &code[9], 4);
2475  buffer[4] = 0;
2476  u32 value;
2477  sscanf(buffer, "%x", &value);
2478
2479  u8 array[8] = {
2480    address & 255,
2481    (address >> 8) & 255,
2482    (address >> 16) & 255,
2483    (address >> 24) & 255,
2484    (value & 255),
2485    (value >> 8) & 255,
2486    0,
2487    0
2488  };
2489
2490  if(cheatsCBAGetCount() == 0 &&
2491     (address >> 28) == 9) {
2492    u32 seed[8];
2493    cheatsCBAParseSeedCode(address, value, seed);
2494    cheatsCBAChangeEncryption(seed);
2495    cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE);
2496  } else {
2497    if(cheatsCBAShouldDecrypt())
2498      cheatsCBADecrypt(array);
2499
2500    address = READ32LE(((u32 *)array));
2501    value = READ16LE(((u16 *)&array[4]));
2502
2503    int type = (address >> 28) & 15;
2504
2505    if(isMultilineWithData(cheatsNumber-1) || (super>0)) {
2506      cheatsAdd(code, desc, address, address, value, 512, UNKNOWN_CODE);
2507	  if (super>0)
2508		  super-= 1;
2509      return;
2510    }
2511
2512    switch(type) {
2513    case 0x00:
2514      {
2515        if(!cheatsCBATableGenerated)
2516          cheatsCBAGenTable();
2517        u32 crc = cheatsCBACalcCRC(rom, 0x10000);
2518        if(crc != address) {
2519          systemMessage(MSG_CBA_CODE_WARNING,
2520                        N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly."));
2521        }
2522        cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512,
2523                  UNKNOWN_CODE);
2524      }
2525      break;
2526    case 0x01:
2527      cheatsAdd(code, desc, address, (address & 0x1FFFFFF) | 0x08000000, value, 512, MASTER_CODE);
2528      mastercode = (address & 0x1FFFFFF) | 0x08000000;
2529      break;
2530    case 0x02:
2531      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2532                CBA_OR);
2533      break;
2534    case 0x03:
2535      cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512,
2536                INT_8_BIT_WRITE);
2537      break;
2538    case 0x04:
2539      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2540                CBA_SLIDE_CODE);
2541      break;
2542    case 0x05:
2543		cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2544                  CBA_SUPER);
2545		super = getCodeLength(cheatsNumber-1);
2546      break;
2547    case 0x06:
2548      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2549                CBA_AND);
2550      break;
2551    case 0x07:
2552      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2553                CBA_IF_TRUE);
2554      break;
2555    case 0x08:
2556      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2557                INT_16_BIT_WRITE);
2558      break;
2559    case 0x0a:
2560      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2561                CBA_IF_FALSE);
2562      break;
2563    case 0x0b:
2564      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2565                CBA_GT);
2566      break;
2567    case 0x0c:
2568      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2569                CBA_LT);
2570      break;
2571    case 0x0d:
2572		if ((address & 0xF0)<0x30)
2573      cheatsAdd(code, desc, address, address & 0xF0, value, 512,
2574                CBA_IF_KEYS_PRESSED);
2575      break;
2576    case 0x0e:
2577      cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0x8000 ? value | 0xFFFF0000 : value, 512,
2578                CBA_ADD);
2579      break;
2580    case 0x0f:
2581      cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
2582                GSA_16_BIT_IF_AND);
2583      break;
2584    default:
2585      // unsupported code
2586      cheatsAdd(code, desc, address, address & 0xFFFFFFFF, value, 512,
2587                UNKNOWN_CODE);
2588      break;
2589    }
2590  }
2591}
2592
2593void cheatsSaveGame(gzFile file)
2594{
2595  utilWriteInt(file, cheatsNumber);
2596
2597  utilGzWrite(file, cheatsList, sizeof(cheatsList));
2598}
2599
2600void cheatsReadGame(gzFile file, int version)
2601{
2602  cheatsNumber = 0;
2603
2604  cheatsNumber = utilReadInt(file);
2605
2606  if (version > 8)
2607    utilGzRead(file, cheatsList, sizeof(cheatsList));
2608
2609
2610  bool firstCodeBreaker = true;
2611
2612  for(int i = 0; i < cheatsNumber; i++) {
2613    if (version <9)
2614    {
2615        cheatsList[i].code = utilReadInt(file);
2616        cheatsList[i].size = utilReadInt(file);
2617        cheatsList[i].status = utilReadInt(file);
2618        cheatsList[i].enabled = utilReadInt(file) ? true : false;
2619        utilGzRead(file, &cheatsList[i].address, sizeof(u32));
2620        cheatsList[i].rawaddress = cheatsList[i].address;
2621        utilGzRead(file, &cheatsList[i].value, sizeof(u32));
2622        utilGzRead(file, &cheatsList[i].oldValue, sizeof(u32));
2623        utilGzRead(file, &cheatsList[i].codestring, 20*sizeof(char));
2624        utilGzRead(file, &cheatsList[i].desc, 32*sizeof(char));
2625    }
2626
2627    cheatsList[i].status = 0;
2628    if(!cheatsList[i].codestring[0]) {
2629      switch(cheatsList[i].size) {
2630      case 0:
2631        sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
2632                cheatsList[i].value);
2633        break;
2634      case 1:
2635        sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
2636                cheatsList[i].value);
2637        break;
2638      case 2:
2639        sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
2640                cheatsList[i].value);
2641        break;
2642      }
2643    }
2644
2645    if(cheatsList[i].enabled) {
2646      cheatsEnable(i);
2647    }
2648
2649    if(cheatsList[i].code == 512 && firstCodeBreaker) {
2650      firstCodeBreaker = false;
2651      char buffer[10];
2652      strncpy(buffer, cheatsList[i].codestring, 8);
2653      buffer[8] = 0;
2654      u32 address;
2655      sscanf(buffer, "%x", &address);
2656      if((address >> 28) == 9) {
2657        strncpy(buffer, &cheatsList[i].codestring[9], 4);
2658        buffer[4] = 0;
2659        u32 value;
2660        sscanf(buffer, "%x", &value);
2661
2662        u32 seed[8];
2663        cheatsCBAParseSeedCode(address, value, seed);
2664        cheatsCBAChangeEncryption(seed);
2665      }
2666    }
2667  }
2668}
2669
2670
2671// skip the cheat list data
2672void cheatsReadGameSkip( gzFile file, int version )
2673{
2674  int nCheats = 0;
2675  nCheats = utilReadInt( file );
2676
2677  if( version >= 9 ) {
2678    utilGzSeek( file, sizeof( cheatsList ), SEEK_CUR );
2679  }
2680
2681  for( int i = 0; i < nCheats; i++ ) {
2682    if( version < 9 ) {
2683      utilGzSeek( file, ( 7 * sizeof(int) ) + ( 52 * sizeof(char) ), SEEK_CUR );
2684    }
2685  }
2686}
2687
2688
2689void cheatsSaveCheatList(const char *file)
2690{
2691  if(cheatsNumber == 0)
2692    return;
2693  FILE *f = fopen(file, "wb");
2694  if(f == NULL)
2695    return;
2696  int version = 1;
2697  fwrite(&version, 1, sizeof(version), f);
2698  int type = 1;
2699  fwrite(&type, 1, sizeof(type), f);
2700  fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f);
2701  fwrite(cheatsList, 1, sizeof(cheatsList), f);
2702  fclose(f);
2703}
2704
2705bool cheatsLoadCheatList(const char *file)
2706{
2707
2708  int count = 0;
2709
2710  FILE *f = fopen(file, "rb");
2711
2712  if(f == NULL)
2713    return false;
2714
2715  int version = 0;
2716
2717  if(fread(&version, 1, sizeof(version), f) != sizeof(version)) {
2718    fclose(f);
2719    return false;
2720  }
2721
2722  if(version != 1) {
2723    systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
2724                  N_("Unsupported cheat list version %d"), version);
2725    fclose(f);
2726    return false;
2727  }
2728
2729  int type = 0;
2730  if(fread(&type, 1, sizeof(type), f) != sizeof(type)) {
2731    fclose(f);
2732    return false;
2733  }
2734
2735
2736  if((type != 0) && (type != 1)) {
2737    systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
2738                  N_("Unsupported cheat list type %d"), type);
2739    fclose(f);
2740    return false;
2741  }
2742
2743  if(fread(&count, 1, sizeof(count), f) != sizeof(count)) {
2744    fclose(f);
2745    return false;
2746  }
2747  if (type == 1)
2748  {
2749    if(fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) {
2750      fclose(f);
2751      return false;
2752    }
2753  }
2754  else if (type == 0)
2755  {
2756    for(int i = 0; i < count; i++) {
2757      fread(&cheatsList[i].code, 1, sizeof(int),f);
2758      fread(&cheatsList[i].size, 1, sizeof(int),f);
2759      fread(&cheatsList[i].status, 1, sizeof(int),f);
2760      fread(&cheatsList[i].enabled, 1, sizeof(int),f);
2761      cheatsList[i].enabled = cheatsList[i].enabled ? true : false;
2762      fread(&cheatsList[i].address, 1, sizeof(u32),f);
2763      cheatsList[i].rawaddress = cheatsList[i].address;
2764      fread(&cheatsList[i].value, 1, sizeof(u32),f);
2765      fread(&cheatsList[i].oldValue, 1, sizeof(u32),f);
2766      fread(&cheatsList[i].codestring, 1, 20*sizeof(char),f);
2767      if(fread(&cheatsList[i].desc, 1, 32*sizeof(char),f) != 32*sizeof(char)) {
2768        fclose(f);
2769        return false;
2770      }
2771    }
2772  }
2773
2774  bool firstCodeBreaker = true;
2775
2776  for(int i = 0; i < count; i++) {
2777    cheatsList[i].status = 0; // remove old status as it is not used
2778    if(!cheatsList[i].codestring[0]) {
2779      switch(cheatsList[i].size) {
2780      case 0:
2781        sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
2782                cheatsList[i].value);
2783        break;
2784      case 1:
2785        sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
2786                cheatsList[i].value);
2787        break;
2788      case 2:
2789        sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
2790                cheatsList[i].value);
2791        break;
2792      }
2793    }
2794
2795    if(cheatsList[i].code == 512 && firstCodeBreaker) {
2796      firstCodeBreaker = false;
2797      char buffer[10];
2798      strncpy(buffer, cheatsList[i].codestring, 8);
2799      buffer[8] = 0;
2800      u32 address;
2801      sscanf(buffer, "%x", &address);
2802      if((address >> 28) == 9) {
2803        strncpy(buffer, &cheatsList[i].codestring[9], 4);
2804        buffer[4] = 0;
2805        u32 value;
2806        sscanf(buffer, "%x", &value);
2807
2808        u32 seed[8];
2809        cheatsCBAParseSeedCode(address, value, seed);
2810        cheatsCBAChangeEncryption(seed);
2811      }
2812    }
2813  }
2814  cheatsNumber = count;
2815  fclose(f);
2816  return true;
2817}
2818
2819extern int cpuNextEvent;
2820
2821extern void debuggerBreakOnWrite(u32 , u32, u32, int, int);
2822
2823#ifdef BKPT_SUPPORT
2824static u8 cheatsGetType(u32 address)
2825{
2826  switch(address >> 24) {
2827  case 2:
2828    return freezeWorkRAM[address & 0x3FFFF];
2829  case 3:
2830    return freezeInternalRAM[address & 0x7FFF];
2831  case 5:
2832    return freezePRAM[address & 0x3FC];
2833  case 6:
2834    if (address > 0x06010000)
2835      return freezeVRAM[address & 0x17FFF];
2836    else
2837      return freezeVRAM[address & 0x1FFFF];
2838  case 7:
2839    return freezeOAM[address & 0x3FC];
2840  }
2841  return 0;
2842}
2843#endif
2844
2845void cheatsWriteMemory(u32 address, u32 value)
2846{
2847#ifdef BKPT_SUPPORT
2848#ifdef SDL
2849  if(cheatsNumber == 0) {
2850    int type = cheatsGetType(address);
2851    u32 oldValue = debuggerReadMemory(address);
2852    if(type == 1 || (type == 2 && oldValue != value)) {
2853      debuggerBreakOnWrite(address, oldValue, value, 2, type);
2854      cpuNextEvent = 0;
2855    }
2856    debuggerWriteMemory(address, value);
2857  }
2858#endif
2859#endif
2860}
2861
2862void cheatsWriteHalfWord(u32 address, u16 value)
2863{
2864#ifdef BKPT_SUPPORT
2865#ifdef SDL
2866  if(cheatsNumber == 0) {
2867    int type = cheatsGetType(address);
2868    u16 oldValue = debuggerReadHalfWord(address);
2869    if(type == 1 || (type == 2 && oldValue != value)) {
2870      debuggerBreakOnWrite(address, oldValue, value, 1, type);
2871      cpuNextEvent = 0;
2872    }
2873    debuggerWriteHalfWord(address, value);
2874  }
2875#endif
2876#endif
2877}
2878
2879#if defined BKPT_SUPPORT && defined SDL
2880void cheatsWriteByte(u32 address, u8 value)
2881#else
2882void cheatsWriteByte(u32, u8)
2883#endif
2884{
2885#ifdef BKPT_SUPPORT
2886#ifdef SDL
2887  if(cheatsNumber == 0) {
2888    int type = cheatsGetType(address);
2889    u8 oldValue = debuggerReadByte(address);
2890    if(type == 1 || (type == 2 && oldValue != value)) {
2891      debuggerBreakOnWrite(address, oldValue, value, 0, type);
2892      cpuNextEvent = 0;
2893    }
2894    debuggerWriteByte(address, value);
2895  }
2896#endif
2897#endif
2898}