annotate src/gba/GBACheats.cpp @ 336:25b7bb7da3b1

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