Mercurial > vba-linux
diff src/gba/GBACheats.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/gba/GBACheats.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,1822 @@ 1.4 +#include <cstdio> 1.5 +#include <cctype> 1.6 +#include <cstring> 1.7 + 1.8 +#include "../common/System.h" 1.9 +#include "../common/Util.h" 1.10 +#include "../NLS.h" 1.11 +#include "GBACheats.h" 1.12 +#include "GBA.h" 1.13 +#include "GBAinline.h" 1.14 +#include "GBAGlobals.h" 1.15 + 1.16 +/** 1.17 + * Gameshark code types: 1.18 + * 1.19 + * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM 1.20 + * DEADFACE XXXXXXXX - changes decryption seeds 1.21 + * 0AAAAAAA 000000YY - 8-bit constant write 1.22 + * 1AAAAAAA 0000YYYY - 16-bit constant write 1.23 + * 2AAAAAAA YYYYYYYY - 32-bit constant write 1.24 + * 3AAAAAAA YYYYYYYY - ?? 1.25 + * 6AAAAAAA 0000YYYY - 16-bit ROM Patch (address >> 1) 1.26 + * 6AAAAAAA 1000YYYY - 16-bit ROM Patch ? (address >> 1) 1.27 + * 6AAAAAAA 2000YYYY - 16-bit ROM Patch ? (address >> 1) 1.28 + * 8A1AAAAA 000000YY - 8-bit button write 1.29 + * 8A2AAAAA 0000YYYY - 16-bit button write 1.30 + * 8A3AAAAA YYYYYYYY - 32-bit button write 1.31 + * 80F00000 0000YYYY - button slow motion 1.32 + * DAAAAAAA 0000YYYY - if address contains 16-bit value enable next code 1.33 + * FAAAAAAA 0000YYYY - Master code function 1.34 + * 1.35 + * CodeBreaker codes types: 1.36 + * 1.37 + * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI) 1.38 + * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16) 1.39 + * + 0x08000100)) 1.40 + * 2AAAAAAA YYYY - 16-bit or 1.41 + * 3AAAAAAA YYYY - 8-bit constant write 1.42 + * 4AAAAAAA YYYY - Slide code 1.43 + * XXXXCCCC IIII (C is count and I is address increment, X is value incr.) 1.44 + * 5AAAAAAA CCCC - Super code (Write bytes to address, CCCC is count) 1.45 + * BBBBBBBB BBBB 1.46 + * 6AAAAAAA YYYY - 16-bit and 1.47 + * 7AAAAAAA YYYY - if address contains 16-bit value enable next code 1.48 + * 8AAAAAAA YYYY - 16-bit constant write 1.49 + * 9AAAAAAA YYYY - change decryption (when first code only?) 1.50 + * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code 1.51 + * BAAAAAAA YYYY - if 16-bit < YYYY 1.52 + * CAAAAAAA YYYY - if 16-bit > YYYY 1.53 + * D0000020 YYYY - if button keys equal value enable next code 1.54 + * EAAAAAAA YYYY - increase value stored in address 1.55 + */ 1.56 +#define UNKNOWN_CODE -1 1.57 +#define INT_8_BIT_WRITE 0 1.58 +#define INT_16_BIT_WRITE 1 1.59 +#define INT_32_BIT_WRITE 2 1.60 +#define GSA_16_BIT_ROM_PATCH 3 1.61 +#define GSA_8_BIT_GS_WRITE 4 1.62 +#define GSA_16_BIT_GS_WRITE 5 1.63 +#define GSA_32_BIT_GS_WRITE 6 1.64 +#define CBA_IF_KEYS_PRESSED 7 1.65 +#define CBA_IF_TRUE 8 1.66 +#define CBA_SLIDE_CODE 9 1.67 +#define CBA_IF_FALSE 10 1.68 +#define CBA_AND 11 1.69 +#define GSA_8_BIT_GS_WRITE2 12 1.70 +#define GSA_16_BIT_GS_WRITE2 13 1.71 +#define GSA_32_BIT_GS_WRITE2 14 1.72 +#define GSA_16_BIT_ROM_PATCH2 15 1.73 +#define GSA_8_BIT_SLIDE 16 1.74 +#define GSA_16_BIT_SLIDE 17 1.75 +#define GSA_32_BIT_SLIDE 18 1.76 +#define GSA_8_BIT_IF_TRUE 19 1.77 +#define GSA_32_BIT_IF_TRUE 20 1.78 +#define GSA_8_BIT_IF_FALSE 21 1.79 +#define GSA_32_BIT_IF_FALSE 22 1.80 +#define GSA_8_BIT_FILL 23 1.81 +#define GSA_16_BIT_FILL 24 1.82 +#define GSA_8_BIT_IF_TRUE2 25 1.83 +#define GSA_16_BIT_IF_TRUE2 26 1.84 +#define GSA_32_BIT_IF_TRUE2 27 1.85 +#define GSA_8_BIT_IF_FALSE2 28 1.86 +#define GSA_16_BIT_IF_FALSE2 29 1.87 +#define GSA_32_BIT_IF_FALSE2 30 1.88 +#define GSA_SLOWDOWN 31 1.89 +#define CBA_ADD 32 1.90 +#define CBA_OR 33 1.91 +#define CBA_LT 34 1.92 +#define CBA_GT 35 1.93 +#define CBA_SUPER 36 1.94 + 1.95 +CheatsData cheatsList[100]; 1.96 +int cheatsNumber = 0; 1.97 + 1.98 +u8 cheatsCBASeedBuffer[0x30]; 1.99 +u32 cheatsCBASeed[4]; 1.100 +u32 cheatsCBATemporaryValue = 0; 1.101 +u16 cheatsCBATable[256]; 1.102 +bool cheatsCBATableGenerated = false; 1.103 + 1.104 +u8 cheatsCBACurrentSeed[12] = { 1.105 + 0x00, 0x00, 0x00, 0x00, 1.106 + 0x00, 0x00, 0x00, 0x00, 1.107 + 0x00, 0x00, 0x00, 0x00 1.108 +}; 1.109 + 1.110 +#define CHEAT_IS_HEX(a) (((a) >= 'A' && (a) <= 'F') || ((a) >= '0' && (a) <= '9')) 1.111 + 1.112 +#define CHEAT_PATCH_ROM_16BIT(a, v) \ 1.113 + WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v); 1.114 + 1.115 +static bool isMultilineWithData(int i) 1.116 +{ 1.117 + // we consider it a multiline code if it has more than one line of data 1.118 + // otherwise, it can still be considered a single code 1.119 + if (i < cheatsNumber && i >= 0) 1.120 + switch (cheatsList[i].size) 1.121 + { 1.122 + case INT_8_BIT_WRITE: 1.123 + case INT_16_BIT_WRITE: 1.124 + case INT_32_BIT_WRITE: 1.125 + case GSA_16_BIT_ROM_PATCH: 1.126 + case GSA_8_BIT_GS_WRITE: 1.127 + case GSA_16_BIT_GS_WRITE: 1.128 + case GSA_32_BIT_GS_WRITE: 1.129 + case CBA_AND: 1.130 + case CBA_IF_KEYS_PRESSED: 1.131 + case CBA_IF_TRUE: 1.132 + case CBA_IF_FALSE: 1.133 + case GSA_8_BIT_IF_TRUE: 1.134 + case GSA_32_BIT_IF_TRUE: 1.135 + case GSA_8_BIT_IF_FALSE: 1.136 + case GSA_32_BIT_IF_FALSE: 1.137 + case GSA_8_BIT_FILL: 1.138 + case GSA_16_BIT_FILL: 1.139 + case GSA_8_BIT_IF_TRUE2: 1.140 + case GSA_16_BIT_IF_TRUE2: 1.141 + case GSA_32_BIT_IF_TRUE2: 1.142 + case GSA_8_BIT_IF_FALSE2: 1.143 + case GSA_16_BIT_IF_FALSE2: 1.144 + case GSA_32_BIT_IF_FALSE2: 1.145 + case GSA_SLOWDOWN: 1.146 + case CBA_ADD: 1.147 + case CBA_OR: 1.148 + return false; 1.149 + // the codes below have two lines of data 1.150 + case CBA_SLIDE_CODE: 1.151 + case GSA_8_BIT_GS_WRITE2: 1.152 + case GSA_16_BIT_GS_WRITE2: 1.153 + case GSA_32_BIT_GS_WRITE2: 1.154 + case GSA_16_BIT_ROM_PATCH2: 1.155 + case GSA_8_BIT_SLIDE: 1.156 + case GSA_16_BIT_SLIDE: 1.157 + case GSA_32_BIT_SLIDE: 1.158 + case CBA_LT: 1.159 + case CBA_GT: 1.160 + case CBA_SUPER: 1.161 + return true; 1.162 + } 1.163 + return false; 1.164 +} 1.165 + 1.166 +static int getCodeLength(int num) 1.167 +{ 1.168 + if (num >= cheatsNumber || num < 0) 1.169 + return 1; 1.170 + 1.171 + // this is for all the codes that are true multiline 1.172 + switch (cheatsList[num].size) 1.173 + { 1.174 + case INT_8_BIT_WRITE: 1.175 + case INT_16_BIT_WRITE: 1.176 + case INT_32_BIT_WRITE: 1.177 + case GSA_16_BIT_ROM_PATCH: 1.178 + case GSA_8_BIT_GS_WRITE: 1.179 + case GSA_16_BIT_GS_WRITE: 1.180 + case GSA_32_BIT_GS_WRITE: 1.181 + case CBA_AND: 1.182 + case GSA_8_BIT_FILL: 1.183 + case GSA_16_BIT_FILL: 1.184 + case GSA_SLOWDOWN: 1.185 + case CBA_ADD: 1.186 + case CBA_OR: 1.187 + return 1; 1.188 + case CBA_IF_KEYS_PRESSED: 1.189 + case CBA_IF_TRUE: 1.190 + case CBA_IF_FALSE: 1.191 + case CBA_SLIDE_CODE: 1.192 + case GSA_8_BIT_GS_WRITE2: 1.193 + case GSA_16_BIT_GS_WRITE2: 1.194 + case GSA_32_BIT_GS_WRITE2: 1.195 + case GSA_16_BIT_ROM_PATCH2: 1.196 + case GSA_8_BIT_SLIDE: 1.197 + case GSA_16_BIT_SLIDE: 1.198 + case GSA_32_BIT_SLIDE: 1.199 + case GSA_8_BIT_IF_TRUE: 1.200 + case GSA_32_BIT_IF_TRUE: 1.201 + case GSA_8_BIT_IF_FALSE: 1.202 + case GSA_32_BIT_IF_FALSE: 1.203 + case CBA_LT: 1.204 + case CBA_GT: 1.205 + return 2; 1.206 + case GSA_8_BIT_IF_TRUE2: 1.207 + case GSA_16_BIT_IF_TRUE2: 1.208 + case GSA_32_BIT_IF_TRUE2: 1.209 + case GSA_8_BIT_IF_FALSE2: 1.210 + case GSA_16_BIT_IF_FALSE2: 1.211 + case GSA_32_BIT_IF_FALSE2: 1.212 + return 3; 1.213 + case CBA_SUPER: 1.214 + return (cheatsList[num].value+5)/6; 1.215 + } 1.216 + return 1; 1.217 +} 1.218 + 1.219 +int cheatsCheckKeys(u32 keys, u32 extended) 1.220 +{ 1.221 + int ticks = 0; 1.222 + for (int i = 0; i < cheatsNumber; i++) 1.223 + { 1.224 + if (!cheatsList[i].enabled) 1.225 + { 1.226 + // make sure we skip other lines in this code 1.227 + i += getCodeLength(i)-1; 1.228 + continue; 1.229 + } 1.230 + switch (cheatsList[i].size) 1.231 + { 1.232 + case INT_8_BIT_WRITE: 1.233 + CPUWriteByte(cheatsList[i].address, cheatsList[i].value); 1.234 + break; 1.235 + case INT_16_BIT_WRITE: 1.236 + CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value); 1.237 + break; 1.238 + case INT_32_BIT_WRITE: 1.239 + CPUWriteMemory(cheatsList[i].address, cheatsList[i].value); 1.240 + break; 1.241 + case GSA_16_BIT_ROM_PATCH: 1.242 + if ((cheatsList[i].status & 1) == 0) 1.243 + { 1.244 + if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) 1.245 + { 1.246 + cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address); 1.247 + cheatsList[i].status |= 1; 1.248 + CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value); 1.249 + } 1.250 + } 1.251 + break; 1.252 + case GSA_8_BIT_GS_WRITE: 1.253 + if (extended & 4) 1.254 + { 1.255 + CPUWriteByte(cheatsList[i].address, cheatsList[i].value); 1.256 + } 1.257 + break; 1.258 + case GSA_16_BIT_GS_WRITE: 1.259 + if (extended & 4) 1.260 + { 1.261 + CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value); 1.262 + } 1.263 + break; 1.264 + case GSA_32_BIT_GS_WRITE: 1.265 + if (extended & 4) 1.266 + { 1.267 + CPUWriteMemory(cheatsList[i].address, cheatsList[i].value); 1.268 + } 1.269 + break; 1.270 + case CBA_IF_KEYS_PRESSED: 1.271 + { 1.272 + u16 value = cheatsList[i].value; 1.273 + u32 addr = cheatsList[i].address; 1.274 + if ((addr & 0x30) == 0x20) 1.275 + { 1.276 + if ((keys & value) != value) 1.277 + { 1.278 + i++; 1.279 + } 1.280 + } 1.281 + else if ((addr & 0x30) == 0x10) 1.282 + { 1.283 + if ((keys & value) == value) 1.284 + { 1.285 + i++; 1.286 + } 1.287 + } 1.288 + break; 1.289 + } 1.290 + case CBA_IF_TRUE: 1.291 + if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) 1.292 + { 1.293 + i++; 1.294 + } 1.295 + break; 1.296 + case CBA_SLIDE_CODE: 1.297 + { 1.298 + u32 address = cheatsList[i].address; 1.299 + u16 value = cheatsList[i].value; 1.300 + i++; 1.301 + if (i < cheatsNumber) 1.302 + { 1.303 + int count = (cheatsList[i].address & 0xFFFF); 1.304 + u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF; 1.305 + int inc = cheatsList[i].value; 1.306 + 1.307 + for (int x = 0; x < count; x++) 1.308 + { 1.309 + CPUWriteHalfWord(address, value); 1.310 + address += inc; 1.311 + value += vinc; 1.312 + } 1.313 + } 1.314 + break; 1.315 + } 1.316 + case CBA_IF_FALSE: 1.317 + if (CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) 1.318 + { 1.319 + i++; 1.320 + } 1.321 + break; 1.322 + case CBA_AND: 1.323 + CPUWriteHalfWord(cheatsList[i].address, 1.324 + CPUReadHalfWord(cheatsList[i].address) & 1.325 + cheatsList[i].value); 1.326 + break; 1.327 + case GSA_8_BIT_GS_WRITE2: 1.328 + i++; 1.329 + if (i < cheatsNumber) 1.330 + { 1.331 + if (extended & 4) 1.332 + { 1.333 + CPUWriteByte(cheatsList[i-1].value, cheatsList[i].address); 1.334 + } 1.335 + } 1.336 + break; 1.337 + case GSA_16_BIT_GS_WRITE2: 1.338 + i++; 1.339 + if (i < cheatsNumber) 1.340 + { 1.341 + if (extended & 4) 1.342 + { 1.343 + CPUWriteHalfWord(cheatsList[i-1].value, cheatsList[i].address); 1.344 + } 1.345 + } 1.346 + break; 1.347 + case GSA_32_BIT_GS_WRITE2: 1.348 + i++; 1.349 + if (i < cheatsNumber) 1.350 + { 1.351 + if (extended & 4) 1.352 + { 1.353 + CPUWriteMemory(cheatsList[i-1].value, cheatsList[i].address); 1.354 + } 1.355 + } 1.356 + break; 1.357 + case GSA_16_BIT_ROM_PATCH2: 1.358 + i++; 1.359 + if (i < cheatsNumber) 1.360 + { 1.361 + if ((cheatsList[i-1].status & 1) == 0) 1.362 + { 1.363 + u32 addr = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000; 1.364 + if (CPUReadHalfWord(addr) != (cheatsList[i].address & 0xFFFF)) 1.365 + { 1.366 + cheatsList[i-1].oldValue = CPUReadHalfWord(addr); 1.367 + cheatsList[i-1].status |= 1; 1.368 + CHEAT_PATCH_ROM_16BIT(addr, cheatsList[i].address & 0xFFFF); 1.369 + } 1.370 + } 1.371 + } 1.372 + break; 1.373 + case GSA_8_BIT_SLIDE: 1.374 + i++; 1.375 + if (i < cheatsNumber) 1.376 + { 1.377 + u32 addr = cheatsList[i-1].value; 1.378 + u8 value = cheatsList[i].address; 1.379 + int vinc = (cheatsList[i].value >> 24) & 255; 1.380 + int count = (cheatsList[i].value >> 16) & 255; 1.381 + int ainc = (cheatsList[i].value & 0xffff); 1.382 + while (count > 0) 1.383 + { 1.384 + CPUWriteByte(addr, value); 1.385 + value += vinc; 1.386 + addr += ainc; 1.387 + count--; 1.388 + } 1.389 + } 1.390 + break; 1.391 + case GSA_16_BIT_SLIDE: 1.392 + i++; 1.393 + if (i < cheatsNumber) 1.394 + { 1.395 + u32 addr = cheatsList[i-1].value; 1.396 + u16 value = cheatsList[i].address; 1.397 + int vinc = (cheatsList[i].value >> 24) & 255; 1.398 + int count = (cheatsList[i].value >> 16) & 255; 1.399 + int ainc = (cheatsList[i].value & 0xffff)*2; 1.400 + while (count > 0) 1.401 + { 1.402 + CPUWriteHalfWord(addr, value); 1.403 + value += vinc; 1.404 + addr += ainc; 1.405 + count--; 1.406 + } 1.407 + } 1.408 + break; 1.409 + case GSA_32_BIT_SLIDE: 1.410 + i++; 1.411 + if (i < cheatsNumber) 1.412 + { 1.413 + u32 addr = cheatsList[i-1].value; 1.414 + u32 value = cheatsList[i].address; 1.415 + int vinc = (cheatsList[i].value >> 24) & 255; 1.416 + int count = (cheatsList[i].value >> 16) & 255; 1.417 + int ainc = (cheatsList[i].value & 0xffff)*4; 1.418 + while (count > 0) 1.419 + { 1.420 + CPUWriteMemory(addr, value); 1.421 + value += vinc; 1.422 + addr += ainc; 1.423 + count--; 1.424 + } 1.425 + } 1.426 + break; 1.427 + case GSA_8_BIT_IF_TRUE: 1.428 + if (CPUReadByte(cheatsList[i].address) != cheatsList[i].value) 1.429 + { 1.430 + i++; 1.431 + } 1.432 + break; 1.433 + case GSA_32_BIT_IF_TRUE: 1.434 + if (CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) 1.435 + { 1.436 + i++; 1.437 + } 1.438 + break; 1.439 + case GSA_8_BIT_IF_FALSE: 1.440 + if (CPUReadByte(cheatsList[i].address) == cheatsList[i].value) 1.441 + { 1.442 + i++; 1.443 + } 1.444 + break; 1.445 + case GSA_32_BIT_IF_FALSE: 1.446 + if (CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) 1.447 + { 1.448 + i++; 1.449 + } 1.450 + break; 1.451 + case GSA_8_BIT_FILL: 1.452 + { 1.453 + u32 addr = cheatsList[i].address; 1.454 + u8 v = cheatsList[i].value & 0xff; 1.455 + u32 end = addr + (cheatsList[i].value >> 8); 1.456 + do 1.457 + { 1.458 + CPUWriteByte(addr, v); 1.459 + addr++; 1.460 + } 1.461 + while (addr <= end); 1.462 + break; 1.463 + } 1.464 + case GSA_16_BIT_FILL: 1.465 + { 1.466 + u32 addr = cheatsList[i].address; 1.467 + u16 v = cheatsList[i].value & 0xffff; 1.468 + u32 end = addr + ((cheatsList[i].value >> 16) << 1); 1.469 + do 1.470 + { 1.471 + CPUWriteHalfWord(addr, v); 1.472 + addr += 2; 1.473 + } 1.474 + while (addr <= end); 1.475 + break; 1.476 + } 1.477 + case GSA_8_BIT_IF_TRUE2: 1.478 + if (CPUReadByte(cheatsList[i].address) != cheatsList[i].value) 1.479 + { 1.480 + i += 2; 1.481 + } 1.482 + break; 1.483 + case GSA_16_BIT_IF_TRUE2: 1.484 + if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) 1.485 + { 1.486 + i += 2; 1.487 + } 1.488 + break; 1.489 + case GSA_32_BIT_IF_TRUE2: 1.490 + if (CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) 1.491 + { 1.492 + i += 2; 1.493 + } 1.494 + break; 1.495 + case GSA_8_BIT_IF_FALSE2: 1.496 + if (CPUReadByte(cheatsList[i].address) == cheatsList[i].value) 1.497 + { 1.498 + i += 2; 1.499 + } 1.500 + break; 1.501 + case GSA_16_BIT_IF_FALSE2: 1.502 + if (CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) 1.503 + { 1.504 + i += 2; 1.505 + } 1.506 + break; 1.507 + case GSA_32_BIT_IF_FALSE2: 1.508 + if (CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) 1.509 + { 1.510 + i += 2; 1.511 + } 1.512 + break; 1.513 + case GSA_SLOWDOWN: 1.514 + // check if button was pressed and released, if so toggle our state 1.515 + if ((cheatsList[i].status & 4) && !(extended & 4)) 1.516 + cheatsList[i].status ^= 1; 1.517 + if (extended & 4) 1.518 + cheatsList[i].status |= 4; 1.519 + else 1.520 + cheatsList[i].status &= ~4; 1.521 + 1.522 + if (cheatsList[i].status & 1) 1.523 + ticks += 2*256*((cheatsList[i].value >> 8) & 255); 1.524 + break; 1.525 + case CBA_ADD: 1.526 + CPUWriteHalfWord(cheatsList[i].address, 1.527 + CPUReadHalfWord(cheatsList[i].address) + 1.528 + (u16)cheatsList[i].value); 1.529 + break; 1.530 + case CBA_OR: 1.531 + CPUWriteHalfWord(cheatsList[i].address, 1.532 + CPUReadHalfWord(cheatsList[i].address) | 1.533 + cheatsList[i].value); 1.534 + break; 1.535 + case CBA_LT: 1.536 + if (CPUReadHalfWord(cheatsList[i].address) >= cheatsList[i].value) 1.537 + i++; 1.538 + break; 1.539 + case CBA_GT: 1.540 + if (CPUReadHalfWord(cheatsList[i].address) <= cheatsList[i].value) 1.541 + i++; 1.542 + break; 1.543 + case CBA_SUPER: 1.544 + { 1.545 + int count = 2*cheatsList[i].value; 1.546 + u32 address = cheatsList[i].address; 1.547 + for (int x = 0; x < count; x++) 1.548 + { 1.549 + u8 b; 1.550 + int res = x % 6; 1.551 + if (res < 4) 1.552 + b = (cheatsList[i].address >> (24-8*res)) & 0xFF; 1.553 + else 1.554 + b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0x0FF; 1.555 + CPUWriteByte(address, b); 1.556 + address++; 1.557 + if (x && !res) 1.558 + i++; 1.559 + } 1.560 + if (count % 6) 1.561 + i++; 1.562 + break; 1.563 + } 1.564 + } 1.565 + } 1.566 + return ticks; 1.567 +} 1.568 + 1.569 +void cheatsAdd(const char *codeStr, 1.570 + const char *desc, 1.571 + u32 address, 1.572 + u32 value, 1.573 + int code, 1.574 + int size) 1.575 +{ 1.576 + if (cheatsNumber < 100) 1.577 + { 1.578 + int x = cheatsNumber; 1.579 + cheatsList[x].code = code; 1.580 + cheatsList[x].size = size; 1.581 + cheatsList[x].address = address; 1.582 + cheatsList[x].value = value; 1.583 + strcpy(cheatsList[x].codestring, codeStr); 1.584 + strcpy(cheatsList[x].desc, desc); 1.585 + cheatsList[x].enabled = true; 1.586 + cheatsList[x].status = 0; 1.587 + 1.588 + // we only store the old value for this simple codes. ROM patching 1.589 + // is taken care when it actually patches the ROM 1.590 + switch (cheatsList[x].size) 1.591 + { 1.592 + case INT_8_BIT_WRITE: 1.593 + cheatsList[x].oldValue = CPUReadByte(address); 1.594 + break; 1.595 + case INT_16_BIT_WRITE: 1.596 + cheatsList[x].oldValue = CPUReadHalfWord(address); 1.597 + break; 1.598 + case INT_32_BIT_WRITE: 1.599 + cheatsList[x].oldValue = CPUReadMemory(address); 1.600 + break; 1.601 + } 1.602 + cheatsNumber++; 1.603 + } 1.604 +} 1.605 + 1.606 +void cheatsDelete(int number, bool restore) 1.607 +{ 1.608 + if (number < cheatsNumber && number >= 0) 1.609 + { 1.610 + int x = number; 1.611 + 1.612 + if (restore) 1.613 + { 1.614 + switch (cheatsList[x].size) 1.615 + { 1.616 + case INT_8_BIT_WRITE: 1.617 + CPUWriteByte(cheatsList[x].address, (u8)cheatsList[x].oldValue); 1.618 + break; 1.619 + case INT_16_BIT_WRITE: 1.620 + CPUWriteHalfWord(cheatsList[x].address, (u16)cheatsList[x].oldValue); 1.621 + break; 1.622 + case INT_32_BIT_WRITE: 1.623 + CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue); 1.624 + break; 1.625 + case GSA_16_BIT_ROM_PATCH: 1.626 + if (cheatsList[x].status & 1) 1.627 + { 1.628 + cheatsList[x].status &= ~1; 1.629 + CHEAT_PATCH_ROM_16BIT(cheatsList[x].address, 1.630 + cheatsList[x].oldValue); 1.631 + } 1.632 + break; 1.633 + case GSA_16_BIT_ROM_PATCH2: 1.634 + if (cheatsList[x].status & 1) 1.635 + { 1.636 + cheatsList[x].status &= ~1; 1.637 + CHEAT_PATCH_ROM_16BIT(((cheatsList[x].value & 0x00FFFFFF) << 1)+ 1.638 + 0x8000000, 1.639 + cheatsList[x].oldValue); 1.640 + } 1.641 + break; 1.642 + } 1.643 + } 1.644 + if ((x+1) < cheatsNumber) 1.645 + { 1.646 + memcpy(&cheatsList[x], &cheatsList[x+1], sizeof(CheatsData)* 1.647 + (cheatsNumber-x-1)); 1.648 + } 1.649 + cheatsNumber--; 1.650 + } 1.651 +} 1.652 + 1.653 +void cheatsDeleteAll(bool restore) 1.654 +{ 1.655 + for (int i = cheatsNumber-1; i >= 0; i--) 1.656 + { 1.657 + cheatsDelete(i, restore); 1.658 + } 1.659 +} 1.660 + 1.661 +void cheatsEnable(int i) 1.662 +{ 1.663 + if (i >= 0 && i < cheatsNumber) 1.664 + { 1.665 + cheatsList[i].enabled = true; 1.666 + } 1.667 +} 1.668 + 1.669 +void cheatsDisable(int i) 1.670 +{ 1.671 + if (i >= 0 && i < cheatsNumber) 1.672 + { 1.673 + switch (cheatsList[i].size) 1.674 + { 1.675 + case GSA_16_BIT_ROM_PATCH: 1.676 + if (cheatsList[i].status & 1) 1.677 + { 1.678 + cheatsList[i].status &= ~1; 1.679 + CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, 1.680 + cheatsList[i].oldValue); 1.681 + } 1.682 + break; 1.683 + case GSA_16_BIT_ROM_PATCH2: 1.684 + if (cheatsList[i].status & 1) 1.685 + { 1.686 + cheatsList[i].status &= ~1; 1.687 + CHEAT_PATCH_ROM_16BIT(((cheatsList[i].value & 0x00FFFFFF) << 1)+ 1.688 + 0x8000000, 1.689 + cheatsList[i].oldValue); 1.690 + } 1.691 + break; 1.692 + } 1.693 + cheatsList[i].enabled = false; 1.694 + } 1.695 +} 1.696 + 1.697 +bool cheatsVerifyCheatCode(const char *code, const char *desc) 1.698 +{ 1.699 + int len = strlen(code); 1.700 + if (len != 11 && len != 13 && len != 17) 1.701 + { 1.702 + systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code); 1.703 + return false; 1.704 + } 1.705 + 1.706 + if (code[8] != ':') 1.707 + { 1.708 + systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code); 1.709 + return false; 1.710 + } 1.711 + 1.712 + int i; 1.713 + for (i = 0; i < 8; i++) 1.714 + { 1.715 + if (!CHEAT_IS_HEX(code[i])) 1.716 + { 1.717 + // wrong cheat 1.718 + systemMessage(MSG_INVALID_CHEAT_CODE, 1.719 + N_("Invalid cheat code '%s'"), code); 1.720 + return false; 1.721 + } 1.722 + } 1.723 + for (i = 9; i < len; i++) 1.724 + { 1.725 + if (!CHEAT_IS_HEX(code[i])) 1.726 + { 1.727 + // wrong cheat 1.728 + systemMessage(MSG_INVALID_CHEAT_CODE, 1.729 + N_("Invalid cheat code '%s'"), code); 1.730 + return false; 1.731 + } 1.732 + } 1.733 + 1.734 + u32 address = 0; 1.735 + u32 value = 0; 1.736 + 1.737 + char buffer[10]; 1.738 + strncpy(buffer, code, 8); 1.739 + buffer[8] = 0; 1.740 + sscanf(buffer, "%x", &address); 1.741 + 1.742 + switch (address >> 24) 1.743 + { 1.744 + case 2: 1.745 + case 3: 1.746 + break; 1.747 + default: 1.748 + systemMessage(MSG_INVALID_CHEAT_CODE_ADDRESS, 1.749 + N_("Invalid cheat code address: %08x"), 1.750 + address); 1.751 + return false; 1.752 + } 1.753 + 1.754 + strncpy(buffer, &code[9], 8); 1.755 + sscanf(buffer, "%x", &value); 1.756 + int type = 0; 1.757 + if (len == 13) 1.758 + type = 1; 1.759 + if (len == 17) 1.760 + type = 2; 1.761 + cheatsAdd(code, desc, address, value, type, type); 1.762 + return true; 1.763 +} 1.764 + 1.765 +void cheatsAddCheatCode(const char *code, const char *desc) 1.766 +{ 1.767 + cheatsVerifyCheatCode(code, desc); 1.768 +} 1.769 + 1.770 +void cheatsDecryptGSACode(u32& address, u32& value, bool v3) 1.771 +{ 1.772 + u32 rollingseed = 0xC6EF3720; 1.773 + u32 seeds_v1[] = { 0x09F4FBBD, 0x9681884A, 0x352027E9, 0xF3DEE5A7 }; 1.774 + u32 seeds_v3[] = { 0x7AA9648F, 0x7FAE6994, 0xC0EFAAD5, 0x42712C57 }; 1.775 + u32 *seeds = v3 ? seeds_v3 : seeds_v1; 1.776 + 1.777 + int bitsleft = 32; 1.778 + while (bitsleft > 0) 1.779 + { 1.780 + value -= ((((address << 4) + seeds[2]) ^ (address + rollingseed)) ^ 1.781 + ((address >> 5) + seeds[3])); 1.782 + address -= ((((value << 4) + seeds[0]) ^ (value + rollingseed)) ^ 1.783 + ((value >> 5) + seeds[1])); 1.784 + rollingseed -= 0x9E3779B9; 1.785 + bitsleft--; 1.786 + } 1.787 +} 1.788 + 1.789 +void cheatsAddGSACode(const char *code, const char *desc, bool v3) 1.790 +{ 1.791 + if (strlen(code) != 16) 1.792 + { 1.793 + // wrong cheat 1.794 + systemMessage(MSG_INVALID_GSA_CODE, 1.795 + N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY")); 1.796 + return; 1.797 + } 1.798 + 1.799 + int i; 1.800 + for (i = 0; i < 16; i++) 1.801 + { 1.802 + if (!CHEAT_IS_HEX(code[i])) 1.803 + { 1.804 + // wrong cheat 1.805 + systemMessage(MSG_INVALID_GSA_CODE, 1.806 + N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY")); 1.807 + return; 1.808 + } 1.809 + } 1.810 + 1.811 + char buffer[10]; 1.812 + strncpy(buffer, code, 8); 1.813 + buffer[8] = 0; 1.814 + u32 address; 1.815 + sscanf(buffer, "%x", &address); 1.816 + strncpy(buffer, &code[8], 8); 1.817 + buffer[8] = 0; 1.818 + u32 value; 1.819 + sscanf(buffer, "%x", &value); 1.820 + 1.821 + cheatsDecryptGSACode(address, value, v3); 1.822 + 1.823 + if (value == 0x1DC0DE) 1.824 + { 1.825 + u32 gamecode = READ32LE(((u32 *)&rom[0xac])); 1.826 + if (gamecode != address) 1.827 + { 1.828 + char buffer[5]; 1.829 + *((u32 *)buffer) = address; 1.830 + buffer[4] = 0; 1.831 + char buffer2[5]; 1.832 + *((u32 *)buffer2) = READ32LE(((u32 *)&rom[0xac])); 1.833 + buffer2[4] = 0; 1.834 + systemMessage(MSG_GBA_CODE_WARNING, 1.835 + N_("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly."), 1.836 + buffer, buffer2); 1.837 + } 1.838 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, v3 ? 257 : 256, 1.839 + UNKNOWN_CODE); 1.840 + return; 1.841 + } 1.842 + if (isMultilineWithData(cheatsNumber-1)) 1.843 + { 1.844 + cheatsAdd(code, desc, address, value, v3 ? 257 : 256, UNKNOWN_CODE); 1.845 + return; 1.846 + } 1.847 + if (v3) 1.848 + { 1.849 + int type = (address >> 25) & 127; 1.850 + u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF); 1.851 + switch (type) 1.852 + { 1.853 + case 0x00: 1.854 + if (address == 0) 1.855 + { 1.856 + type = (value >> 25) & 127; 1.857 + addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF); 1.858 + switch (type) 1.859 + { 1.860 + case 0x04: 1.861 + cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN); 1.862 + break; 1.863 + case 0x08: 1.864 + cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_GS_WRITE2); 1.865 + break; 1.866 + case 0x09: 1.867 + cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_GS_WRITE2); 1.868 + break; 1.869 + case 0x0a: 1.870 + cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_GS_WRITE2); 1.871 + break; 1.872 + case 0x0c: 1.873 + case 0x0d: 1.874 + case 0x0e: 1.875 + case 0x0f: 1.876 + cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2); 1.877 + break; 1.878 + case 0x40: 1.879 + cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_SLIDE); 1.880 + break; 1.881 + case 0x41: 1.882 + cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_SLIDE); 1.883 + break; 1.884 + case 0x42: 1.885 + cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_SLIDE); 1.886 + break; 1.887 + default: 1.888 + cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE); 1.889 + break; 1.890 + } 1.891 + } 1.892 + else 1.893 + cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_FILL); 1.894 + break; 1.895 + case 0x01: 1.896 + cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_FILL); 1.897 + break; 1.898 + case 0x02: 1.899 + cheatsAdd(code, desc, addr, value, 257, INT_32_BIT_WRITE); 1.900 + break; 1.901 + case 0x04: 1.902 + cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE); 1.903 + break; 1.904 + case 0x05: 1.905 + cheatsAdd(code, desc, addr, value, 257, CBA_IF_TRUE); 1.906 + break; 1.907 + case 0x06: 1.908 + cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE); 1.909 + break; 1.910 + case 0x08: 1.911 + cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE); 1.912 + break; 1.913 + case 0x09: 1.914 + cheatsAdd(code, desc, addr, value, 257, CBA_IF_FALSE); 1.915 + break; 1.916 + case 0x0a: 1.917 + cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE); 1.918 + break; 1.919 + case 0x24: 1.920 + cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE2); 1.921 + break; 1.922 + case 0x25: 1.923 + cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_TRUE2); 1.924 + break; 1.925 + case 0x26: 1.926 + cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE2); 1.927 + break; 1.928 + case 0x28: 1.929 + cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE2); 1.930 + break; 1.931 + case 0x29: 1.932 + cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_FALSE2); 1.933 + break; 1.934 + case 0x2a: 1.935 + cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE2); 1.936 + break; 1.937 + default: 1.938 + cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE); 1.939 + break; 1.940 + } 1.941 + } 1.942 + else 1.943 + { 1.944 + int type = (address >> 28) & 15; 1.945 + switch (type) 1.946 + { 1.947 + case 0: 1.948 + case 1: 1.949 + case 2: 1.950 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, type); 1.951 + break; 1.952 + case 6: 1.953 + address <<= 1; 1.954 + type = (address >> 28) & 15; 1.955 + if (type == 0x0c) 1.956 + { 1.957 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, 1.958 + GSA_16_BIT_ROM_PATCH); 1.959 + break; 1.960 + } 1.961 + // unsupported code 1.962 + cheatsAdd(code, desc, address, value, 256, 1.963 + UNKNOWN_CODE); 1.964 + break; 1.965 + case 8: 1.966 + switch ((address >> 20) & 15) 1.967 + { 1.968 + case 1: 1.969 + cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, 1.970 + GSA_8_BIT_GS_WRITE); 1.971 + break; 1.972 + case 2: 1.973 + cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, 1.974 + GSA_16_BIT_GS_WRITE); 1.975 + break; 1.976 + case 3: 1.977 + cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, 1.978 + GSA_32_BIT_GS_WRITE); 1.979 + case 15: 1.980 + cheatsAdd(code, desc, 0, value & 0xFF00, 256, GSA_SLOWDOWN); 1.981 + break; 1.982 + default: 1.983 + // unsupported code 1.984 + cheatsAdd(code, desc, address, value, 256, 1.985 + UNKNOWN_CODE); 1.986 + break; 1.987 + } 1.988 + break; 1.989 + case 0x0d: 1.990 + if (address != 0xDEADFACE) 1.991 + { 1.992 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, 1.993 + CBA_IF_TRUE); 1.994 + } 1.995 + else 1.996 + cheatsAdd(code, desc, address, value, 256, 1.997 + UNKNOWN_CODE); 1.998 + break; 1.999 + default: 1.1000 + // unsupported code 1.1001 + cheatsAdd(code, desc, address, value, 256, 1.1002 + UNKNOWN_CODE); 1.1003 + break; 1.1004 + } 1.1005 + } 1.1006 +} 1.1007 + 1.1008 +bool cheatsImportGSACodeFile(const char *name, int game, bool v3) 1.1009 +{ 1.1010 + FILE *f = fopen(name, "rb"); 1.1011 + if (!f) 1.1012 + return false; 1.1013 + 1.1014 + int games = 0; 1.1015 + int len = 0; 1.1016 + fseek(f, 0x1e, SEEK_CUR); 1.1017 + fread(&games, 1, 4, f); 1.1018 + bool found = false; 1.1019 + int g = 0; 1.1020 + while (games > 0) 1.1021 + { 1.1022 + if (g == game) 1.1023 + { 1.1024 + found = true; 1.1025 + break; 1.1026 + } 1.1027 + fread(&len, 1, 4, f); 1.1028 + fseek(f, len, SEEK_CUR); 1.1029 + int codes = 0; 1.1030 + fread(&codes, 1, 4, f); 1.1031 + while (codes > 0) 1.1032 + { 1.1033 + fread(&len, 1, 4, f); 1.1034 + fseek(f, len, SEEK_CUR); 1.1035 + fseek(f, 8, SEEK_CUR); 1.1036 + fread(&len, 1, 4, f); 1.1037 + fseek(f, len*12, SEEK_CUR); 1.1038 + codes--; 1.1039 + } 1.1040 + games--; 1.1041 + g++; 1.1042 + } 1.1043 + if (found) 1.1044 + { 1.1045 + char desc[256]; 1.1046 + char code[17]; 1.1047 + fread(&len, 1, 4, f); 1.1048 + fseek(f, len, SEEK_CUR); 1.1049 + int codes = 0; 1.1050 + fread(&codes, 1, 4, f); 1.1051 + while (codes > 0) 1.1052 + { 1.1053 + fread(&len, 1, 4, f); 1.1054 + fread(desc, 1, len, f); 1.1055 + desc[len] = 0; 1.1056 + desc[31] = 0; 1.1057 + fread(&len, 1, 4, f); 1.1058 + fseek(f, len, SEEK_CUR); 1.1059 + fseek(f, 4, SEEK_CUR); 1.1060 + fread(&len, 1, 4, f); 1.1061 + while (len) 1.1062 + { 1.1063 + fseek(f, 4, SEEK_CUR); 1.1064 + fread(code, 1, 8, f); 1.1065 + fseek(f, 4, SEEK_CUR); 1.1066 + fread(&code[8], 1, 8, f); 1.1067 + code[16] = 0; 1.1068 + cheatsAddGSACode(code, desc, v3); 1.1069 + len -= 2; 1.1070 + } 1.1071 + codes--; 1.1072 + } 1.1073 + } 1.1074 + fclose(f); 1.1075 + return false; 1.1076 +} 1.1077 + 1.1078 +void cheatsCBAReverseArray(u8 *array, u8 *dest) 1.1079 +{ 1.1080 + dest[0] = array[3]; 1.1081 + dest[1] = array[2]; 1.1082 + dest[2] = array[1]; 1.1083 + dest[3] = array[0]; 1.1084 + dest[4] = array[5]; 1.1085 + dest[5] = array[4]; 1.1086 +} 1.1087 + 1.1088 +void chatsCBAScramble(u8 *array, int count, u8 b) 1.1089 +{ 1.1090 + u8 *x = array + (count >> 3); 1.1091 + u8 *y = array + (b >> 3); 1.1092 + u32 z = *x & (1 << (count & 7)); 1.1093 + u32 x0 = (*x & (~(1 << (count & 7)))); 1.1094 + if (z != 0) 1.1095 + z = 1; 1.1096 + if ((*y & (1 << (b & 7))) != 0) 1.1097 + x0 |= (1 << (count & 7)); 1.1098 + *x = x0; 1.1099 + u32 temp = *y & (~(1 << (b & 7))); 1.1100 + if (z != 0) 1.1101 + temp |= (1 << (b & 7)); 1.1102 + *y = temp; 1.1103 +} 1.1104 + 1.1105 +u32 cheatsCBAGetValue(u8 *array) 1.1106 +{ 1.1107 + return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24; 1.1108 +} 1.1109 + 1.1110 +u16 cheatsCBAGetData(u8 *array) 1.1111 +{ 1.1112 + return array[4] | array[5]<<8; 1.1113 +} 1.1114 + 1.1115 +void cheatsCBAArrayToValue(u8 *array, u8 *dest) 1.1116 +{ 1.1117 + dest[0] = array[3]; 1.1118 + dest[1] = array[2]; 1.1119 + dest[2] = array[1]; 1.1120 + dest[3] = array[0]; 1.1121 + dest[4] = array[5]; 1.1122 + dest[5] = array[4]; 1.1123 +} 1.1124 + 1.1125 +void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array) 1.1126 +{ 1.1127 + array[0] = 1; 1.1128 + array[1] = value & 0xFF; 1.1129 + array[2] = (address >> 0x10) & 0xFF; 1.1130 + array[3] = (value >> 8) & 0xFF; 1.1131 + array[4] = (address >> 0x18) & 0x0F; 1.1132 + array[5] = address & 0xFFFF; 1.1133 + array[6] = address; 1.1134 + array[7] = value; 1.1135 +} 1.1136 + 1.1137 +u32 cheatsCBAEncWorker() 1.1138 +{ 1.1139 + u32 x = (cheatsCBATemporaryValue * 0x41c64e6d) + 0x3039; 1.1140 + u32 y = (x * 0x41c64e6d) + 0x3039; 1.1141 + u32 z = x >> 0x10; 1.1142 + x = ((y >> 0x10) & 0x7fff) << 0x0f; 1.1143 + z = (z << 0x1e) | x; 1.1144 + x = (y * 0x41c64e6d) + 0x3039; 1.1145 + cheatsCBATemporaryValue = x; 1.1146 + return z | ((x >> 0x10) & 0x7fff); 1.1147 +} 1.1148 + 1.1149 +#define ROR(v, s) \ 1.1150 + (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s)))) 1.1151 + 1.1152 +u32 cheatsCBACalcIndex(u32 x, u32 y) 1.1153 +{ 1.1154 + if (y != 0) 1.1155 + { 1.1156 + if (y == 1) 1.1157 + x = 0; 1.1158 + else if (x == y) 1.1159 + x = 0; 1.1160 + if (y < 1) 1.1161 + return x; 1.1162 + else if (x < y) 1.1163 + return x; 1.1164 + u32 x0 = 1; 1.1165 + 1.1166 + while (y < 0x10000000) 1.1167 + { 1.1168 + if (y < x) 1.1169 + { 1.1170 + y = y << 4; 1.1171 + x0 = x0 << 4; 1.1172 + } 1.1173 + else 1.1174 + break; 1.1175 + } 1.1176 + 1.1177 + while (y < 0x80000000) 1.1178 + { 1.1179 + if (y < x) 1.1180 + { 1.1181 + y = y << 1; 1.1182 + x0 = x0 << 1; 1.1183 + } 1.1184 + else 1.1185 + break; 1.1186 + } 1.1187 + 1.1188 +loop: 1.1189 + u32 z = 0; 1.1190 + if (x >= y) 1.1191 + x -= y; 1.1192 + if (x >= (y >> 1)) 1.1193 + { 1.1194 + x -= (y >> 1); 1.1195 + z |= ROR(x0, 1); 1.1196 + } 1.1197 + if (x >= (y >> 2)) 1.1198 + { 1.1199 + x -= (y >> 2); 1.1200 + z |= ROR(x0, 2); 1.1201 + } 1.1202 + if (x >= (y >> 3)) 1.1203 + { 1.1204 + x -= (y >> 3); 1.1205 + z |= ROR(x0, 3); 1.1206 + } 1.1207 + 1.1208 + u32 temp = x0; 1.1209 + 1.1210 + if (x != 0) 1.1211 + { 1.1212 + x0 = x0 >> 4; 1.1213 + if (x0 != 0) 1.1214 + { 1.1215 + y = y >> 4; 1.1216 + goto loop; 1.1217 + } 1.1218 + } 1.1219 + 1.1220 + z = z & 0xe0000000; 1.1221 + 1.1222 + if (z != 0) 1.1223 + { 1.1224 + if ((temp & 7) == 0) 1.1225 + return x; 1.1226 + } 1.1227 + else 1.1228 + return x; 1.1229 + 1.1230 + if ((z & ROR(temp, 3)) != 0) 1.1231 + x += y >> 3; 1.1232 + if ((z & ROR(temp, 2)) != 0) 1.1233 + x += y >> 2; 1.1234 + if ((z & ROR(temp, 1)) != 0) 1.1235 + x += y >> 1; 1.1236 + return x; 1.1237 + } 1.1238 + else 1.1239 + {} 1.1240 + // should not happen in the current code 1.1241 + return 0; 1.1242 +} 1.1243 + 1.1244 +void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count) 1.1245 +{ 1.1246 + int i; 1.1247 + for (i = 0; i < count; i++) 1.1248 + buffer[i] = i; 1.1249 + for (i = 0; (u32)i < a; i++) 1.1250 + { 1.1251 + u32 a = cheatsCBACalcIndex(cheatsCBAEncWorker(), count); 1.1252 + u32 b = cheatsCBACalcIndex(cheatsCBAEncWorker(), count); 1.1253 + u32 t = buffer[a]; 1.1254 + buffer[a] = buffer[b]; 1.1255 + buffer[b] = t; 1.1256 + } 1.1257 +} 1.1258 + 1.1259 +void cheatsCBAChangeEncryption(u32 *seed) 1.1260 +{ 1.1261 + int i; 1.1262 + 1.1263 + cheatsCBATemporaryValue = (seed[1] ^ 0x1111); 1.1264 + cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30); 1.1265 + cheatsCBATemporaryValue = 0x4efad1c3; 1.1266 + 1.1267 + for (i = 0; (u32)i < seed[4]; i++) 1.1268 + { 1.1269 + cheatsCBATemporaryValue = cheatsCBAEncWorker(); 1.1270 + } 1.1271 + cheatsCBASeed[2] = cheatsCBAEncWorker(); 1.1272 + cheatsCBASeed[3] = cheatsCBAEncWorker(); 1.1273 + 1.1274 + cheatsCBATemporaryValue = seed[3] ^ 0xf254; 1.1275 + 1.1276 + for (i = 0; (u32)i < seed[3]; i++) 1.1277 + { 1.1278 + cheatsCBATemporaryValue = cheatsCBAEncWorker(); 1.1279 + } 1.1280 + 1.1281 + cheatsCBASeed[0] = cheatsCBAEncWorker(); 1.1282 + cheatsCBASeed[1] = cheatsCBAEncWorker(); 1.1283 + 1.1284 + *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6]; 1.1285 + *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7]; 1.1286 + *((u32 *)&cheatsCBACurrentSeed[8]) = 0; 1.1287 +} 1.1288 + 1.1289 +u16 cheatsCBAGenValue(u32 x, u32 y, u32 z) 1.1290 +{ 1.1291 + y <<= 0x10; 1.1292 + z <<= 0x10; 1.1293 + x <<= 0x18; 1.1294 + u32 x0 = (int)y >> 0x10; 1.1295 + z = (int)z >> 0x10; 1.1296 + x = (int)x >> 0x10; 1.1297 + for (int i = 0; i < 8; i++) 1.1298 + { 1.1299 + u32 temp = z ^ x; 1.1300 + if ((int)temp >= 0) 1.1301 + { 1.1302 + temp = z << 0x11; 1.1303 + } 1.1304 + else 1.1305 + { 1.1306 + temp = z << 0x01; 1.1307 + temp ^= x0; 1.1308 + temp = temp << 0x10; 1.1309 + } 1.1310 + z = (int)temp >> 0x10; 1.1311 + temp = x << 0x11; 1.1312 + x = (int)temp >> 0x10; 1.1313 + } 1.1314 + return z & 0xffff; 1.1315 +} 1.1316 + 1.1317 +void cheatsCBAGenTable() 1.1318 +{ 1.1319 + for (int i = 0; i < 0x100; i++) 1.1320 + { 1.1321 + cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0); 1.1322 + } 1.1323 + cheatsCBATableGenerated = true; 1.1324 +} 1.1325 + 1.1326 +u16 cheatsCBACalcCRC(u8 *rom, int count) 1.1327 +{ 1.1328 + u32 crc = 0xffffffff; 1.1329 + 1.1330 + if (count & 3) 1.1331 + { 1.1332 + // 0x08000EAE 1.1333 + } 1.1334 + else 1.1335 + { 1.1336 + count = (count >> 2) - 1; 1.1337 + if (count != -1) 1.1338 + { 1.1339 + while (count != -1) 1.1340 + { 1.1341 + crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18) 1.1342 + ^ *rom++]) << 0x10) >> 0x10; 1.1343 + crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18) 1.1344 + ^ *rom++]) << 0x10) >> 0x10; 1.1345 + crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18) 1.1346 + ^ *rom++]) << 0x10) >> 0x10; 1.1347 + crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18) 1.1348 + ^ *rom++]) << 0x10) >> 0x10; 1.1349 + count--; 1.1350 + } 1.1351 + } 1.1352 + } 1.1353 + return crc & 0xffff; 1.1354 +} 1.1355 + 1.1356 +void cheatsCBADecrypt(u8 *decrypt) 1.1357 +{ 1.1358 + u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 1.1359 + u8 *array = &buffer[1]; 1.1360 + 1.1361 + cheatsCBAReverseArray(decrypt, array); 1.1362 + 1.1363 + for (int count = 0x2f; count >= 0; count--) 1.1364 + { 1.1365 + chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]); 1.1366 + } 1.1367 + cheatsCBAArrayToValue(array, decrypt); 1.1368 + *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^ 1.1369 + cheatsCBASeed[0]; 1.1370 + *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^ 1.1371 + cheatsCBASeed[1]) & 0xffff; 1.1372 + 1.1373 + cheatsCBAReverseArray(decrypt, array); 1.1374 + 1.1375 + u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed); 1.1376 + for (int i = 0; i <= 4; i++) 1.1377 + { 1.1378 + array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ; 1.1379 + } 1.1380 + 1.1381 + array[5] = (cs >> 8) ^ array[5]; 1.1382 + 1.1383 + for (int j = 5; j >= 0; j--) 1.1384 + { 1.1385 + array[j] = (cs ^ array[j-1]) ^ array[j]; 1.1386 + } 1.1387 + 1.1388 + cheatsCBAArrayToValue(array, decrypt); 1.1389 + 1.1390 + *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) 1.1391 + ^ cheatsCBASeed[2]; 1.1392 + *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) 1.1393 + ^ cheatsCBASeed[3]) & 0xffff; 1.1394 +} 1.1395 + 1.1396 +int cheatsCBAGetCount() 1.1397 +{ 1.1398 + int count = 0; 1.1399 + for (int i = 0; i < cheatsNumber; i++) 1.1400 + { 1.1401 + if (cheatsList[i].code == 512) 1.1402 + count++; 1.1403 + } 1.1404 + return count; 1.1405 +} 1.1406 + 1.1407 +bool cheatsCBAShouldDecrypt() 1.1408 +{ 1.1409 + for (int i = 0; i < cheatsNumber; i++) 1.1410 + { 1.1411 + if (cheatsList[i].code == 512) 1.1412 + { 1.1413 + return (cheatsList[i].codestring[0] == '9'); 1.1414 + } 1.1415 + } 1.1416 + return false; 1.1417 +} 1.1418 + 1.1419 +void cheatsAddCBACode(const char *code, const char *desc) 1.1420 +{ 1.1421 + if (strlen(code) != 13) 1.1422 + { 1.1423 + // wrong cheat 1.1424 + systemMessage(MSG_INVALID_CBA_CODE, 1.1425 + N_("Invalid CBA code. Format is XXXXXXXX YYYY.")); 1.1426 + return; 1.1427 + } 1.1428 + 1.1429 + int i; 1.1430 + for (i = 0; i < 8; i++) 1.1431 + { 1.1432 + if (!CHEAT_IS_HEX(code[i])) 1.1433 + { 1.1434 + // wrong cheat 1.1435 + systemMessage(MSG_INVALID_CBA_CODE, 1.1436 + N_("Invalid CBA code. Format is XXXXXXXX YYYY.")); 1.1437 + return; 1.1438 + } 1.1439 + } 1.1440 + 1.1441 + if (code[8] != ' ') 1.1442 + { 1.1443 + systemMessage(MSG_INVALID_CBA_CODE, 1.1444 + N_("Invalid CBA code. Format is XXXXXXXX YYYY.")); 1.1445 + return; 1.1446 + } 1.1447 + 1.1448 + for (i = 9; i < 13; i++) 1.1449 + { 1.1450 + if (!CHEAT_IS_HEX(code[i])) 1.1451 + { 1.1452 + // wrong cheat 1.1453 + systemMessage(MSG_INVALID_CBA_CODE, 1.1454 + N_("Invalid CBA code. Format is XXXXXXXX YYYY.")); 1.1455 + return; 1.1456 + } 1.1457 + } 1.1458 + 1.1459 + char buffer[10]; 1.1460 + strncpy(buffer, code, 8); 1.1461 + buffer[8] = 0; 1.1462 + u32 address; 1.1463 + sscanf(buffer, "%x", &address); 1.1464 + strncpy(buffer, &code[9], 4); 1.1465 + buffer[4] = 0; 1.1466 + u32 value; 1.1467 + sscanf(buffer, "%x", &value); 1.1468 + 1.1469 + u8 array[8] = { 1.1470 + address &255, 1.1471 + (address >> 8) & 255, 1.1472 + (address >> 16) & 255, 1.1473 + (address >> 24) & 255, 1.1474 + (value & 255), 1.1475 + (value >> 8) & 255, 1.1476 + 0, 1.1477 + 0 1.1478 + }; 1.1479 + 1.1480 + if (cheatsCBAGetCount() == 0 && 1.1481 + (address >> 28) == 9) 1.1482 + { 1.1483 + u32 seed[8]; 1.1484 + cheatsCBAParseSeedCode(address, value, seed); 1.1485 + cheatsCBAChangeEncryption(seed); 1.1486 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE); 1.1487 + } 1.1488 + else 1.1489 + { 1.1490 + if (cheatsCBAShouldDecrypt()) 1.1491 + cheatsCBADecrypt(array); 1.1492 + 1.1493 + address = READ32LE(((u32 *)array)); 1.1494 + value = READ16LE(((u16 *)&array[4])); 1.1495 + 1.1496 + int type = (address >> 28) & 15; 1.1497 + 1.1498 + if (isMultilineWithData(cheatsNumber-1)) 1.1499 + { 1.1500 + cheatsAdd(code, desc, address, value, 512, UNKNOWN_CODE); 1.1501 + return; 1.1502 + } 1.1503 + 1.1504 + switch (type) 1.1505 + { 1.1506 + case 0x00: 1.1507 + { 1.1508 + if (!cheatsCBATableGenerated) 1.1509 + cheatsCBAGenTable(); 1.1510 + u32 crc = cheatsCBACalcCRC(rom, 0x10000); 1.1511 + if (crc != address) 1.1512 + { 1.1513 + systemMessage(MSG_CBA_CODE_WARNING, 1.1514 + N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly.")); 1.1515 + } 1.1516 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1517 + UNKNOWN_CODE); 1.1518 + break; 1.1519 + } 1.1520 + case 0x02: 1.1521 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1522 + CBA_OR); 1.1523 + break; 1.1524 + case 0x03: 1.1525 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1526 + INT_8_BIT_WRITE); 1.1527 + break; 1.1528 + case 0x04: 1.1529 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1530 + CBA_SLIDE_CODE); 1.1531 + break; 1.1532 + case 0x05: 1.1533 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1534 + CBA_SUPER); 1.1535 + break; 1.1536 + case 0x06: 1.1537 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1538 + CBA_AND); 1.1539 + break; 1.1540 + case 0x07: 1.1541 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1542 + CBA_IF_TRUE); 1.1543 + break; 1.1544 + case 0x08: 1.1545 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1546 + INT_16_BIT_WRITE); 1.1547 + break; 1.1548 + case 0x0a: 1.1549 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1550 + CBA_IF_FALSE); 1.1551 + break; 1.1552 + case 0x0b: 1.1553 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1554 + CBA_LT); 1.1555 + break; 1.1556 + case 0x0c: 1.1557 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1558 + CBA_GT); 1.1559 + break; 1.1560 + case 0x0d: 1.1561 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1562 + CBA_IF_KEYS_PRESSED); 1.1563 + break; 1.1564 + case 0x0e: 1.1565 + cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, 1.1566 + CBA_ADD); 1.1567 + break; 1.1568 + default: 1.1569 + // unsupported code 1.1570 + cheatsAdd(code, desc, address & 0xFFFFFFFF, value, 512, 1.1571 + UNKNOWN_CODE); 1.1572 + break; 1.1573 + } 1.1574 + } 1.1575 +} 1.1576 + 1.1577 +void cheatsSaveGame(gzFile file) 1.1578 +{ 1.1579 + utilWriteInt(file, cheatsNumber); 1.1580 + 1.1581 + utilGzWrite(file, cheatsList, sizeof(cheatsList)); 1.1582 +} 1.1583 + 1.1584 +void cheatsReadGame(gzFile file) 1.1585 +{ 1.1586 + cheatsNumber = 0; 1.1587 + 1.1588 + cheatsNumber = utilReadInt(file); 1.1589 + 1.1590 + utilGzRead(file, cheatsList, sizeof(cheatsList)); 1.1591 + 1.1592 + bool firstCodeBreaker = true; 1.1593 + 1.1594 + for (int i = 0; i < cheatsNumber; i++) 1.1595 + { 1.1596 + cheatsList[i].status = 0; 1.1597 + if (!cheatsList[i].codestring[0]) 1.1598 + { 1.1599 + switch (cheatsList[i].size) 1.1600 + { 1.1601 + case 0: 1.1602 + sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address, 1.1603 + cheatsList[i].value); 1.1604 + break; 1.1605 + case 1: 1.1606 + sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address, 1.1607 + cheatsList[i].value); 1.1608 + break; 1.1609 + case 2: 1.1610 + sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address, 1.1611 + cheatsList[i].value); 1.1612 + break; 1.1613 + } 1.1614 + } 1.1615 + 1.1616 + if (cheatsList[i].enabled) 1.1617 + { 1.1618 + cheatsEnable(i); 1.1619 + } 1.1620 + 1.1621 + if (cheatsList[i].code == 512 && firstCodeBreaker) 1.1622 + { 1.1623 + firstCodeBreaker = false; 1.1624 + char buffer[10]; 1.1625 + strncpy(buffer, cheatsList[i].codestring, 8); 1.1626 + buffer[8] = 0; 1.1627 + u32 address; 1.1628 + sscanf(buffer, "%x", &address); 1.1629 + if ((address >> 28) == 9) 1.1630 + { 1.1631 + strncpy(buffer, &cheatsList[i].codestring[9], 4); 1.1632 + buffer[4] = 0; 1.1633 + u32 value; 1.1634 + sscanf(buffer, "%x", &value); 1.1635 + 1.1636 + u32 seed[8]; 1.1637 + cheatsCBAParseSeedCode(address, value, seed); 1.1638 + cheatsCBAChangeEncryption(seed); 1.1639 + } 1.1640 + } 1.1641 + } 1.1642 +} 1.1643 + 1.1644 +void cheatsSaveCheatList(const char *file) 1.1645 +{ 1.1646 + if (cheatsNumber == 0) 1.1647 + return; 1.1648 + FILE *f = fopen(file, "wb"); 1.1649 + if (f == NULL) 1.1650 + return; 1.1651 + int version = 1; 1.1652 + fwrite(&version, 1, sizeof(version), f); 1.1653 + int type = 0; 1.1654 + fwrite(&type, 1, sizeof(type), f); 1.1655 + fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f); 1.1656 + fwrite(cheatsList, 1, sizeof(cheatsList), f); 1.1657 + fclose(f); 1.1658 +} 1.1659 + 1.1660 +bool cheatsLoadCheatList(const char *file) 1.1661 +{ 1.1662 + cheatsNumber = 0; 1.1663 + 1.1664 + int count = 0; 1.1665 + 1.1666 + FILE *f = fopen(file, "rb"); 1.1667 + 1.1668 + if (f == NULL) 1.1669 + return false; 1.1670 + 1.1671 + int version = 0; 1.1672 + 1.1673 + if (fread(&version, 1, sizeof(version), f) != sizeof(version)) 1.1674 + { 1.1675 + fclose(f); 1.1676 + return false; 1.1677 + } 1.1678 + 1.1679 + if (version != 1) 1.1680 + { 1.1681 + systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION, 1.1682 + N_("Unsupported cheat list version %d"), version); 1.1683 + fclose(f); 1.1684 + return false; 1.1685 + } 1.1686 + 1.1687 + int type = 0; 1.1688 + if (fread(&type, 1, sizeof(type), f) != sizeof(type)) 1.1689 + { 1.1690 + fclose(f); 1.1691 + return false; 1.1692 + } 1.1693 + 1.1694 + if (type != 0) 1.1695 + { 1.1696 + systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE, 1.1697 + N_("Unsupported cheat list type %d"), type); 1.1698 + fclose(f); 1.1699 + return false; 1.1700 + } 1.1701 + 1.1702 + if (fread(&count, 1, sizeof(count), f) != sizeof(count)) 1.1703 + { 1.1704 + fclose(f); 1.1705 + return false; 1.1706 + } 1.1707 + 1.1708 + if (fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) 1.1709 + { 1.1710 + fclose(f); 1.1711 + return false; 1.1712 + } 1.1713 + 1.1714 + bool firstCodeBreaker = true; 1.1715 + 1.1716 + for (int i = 0; i < count; i++) 1.1717 + { 1.1718 + cheatsList[i].status = 0; // remove old status as it is not used 1.1719 + if (!cheatsList[i].codestring[0]) 1.1720 + { 1.1721 + switch (cheatsList[i].size) 1.1722 + { 1.1723 + case 0: 1.1724 + sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address, 1.1725 + cheatsList[i].value); 1.1726 + break; 1.1727 + case 1: 1.1728 + sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address, 1.1729 + cheatsList[i].value); 1.1730 + break; 1.1731 + case 2: 1.1732 + sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address, 1.1733 + cheatsList[i].value); 1.1734 + break; 1.1735 + } 1.1736 + } 1.1737 + 1.1738 + if (cheatsList[i].code == 512 && firstCodeBreaker) 1.1739 + { 1.1740 + firstCodeBreaker = false; 1.1741 + char buffer[10]; 1.1742 + strncpy(buffer, cheatsList[i].codestring, 8); 1.1743 + buffer[8] = 0; 1.1744 + u32 address; 1.1745 + sscanf(buffer, "%x", &address); 1.1746 + if ((address >> 28) == 9) 1.1747 + { 1.1748 + strncpy(buffer, &cheatsList[i].codestring[9], 4); 1.1749 + buffer[4] = 0; 1.1750 + u32 value; 1.1751 + sscanf(buffer, "%x", &value); 1.1752 + 1.1753 + u32 seed[8]; 1.1754 + cheatsCBAParseSeedCode(address, value, seed); 1.1755 + cheatsCBAChangeEncryption(seed); 1.1756 + } 1.1757 + } 1.1758 + } 1.1759 + cheatsNumber = count; 1.1760 + fclose(f); 1.1761 + return true; 1.1762 +} 1.1763 + 1.1764 +extern int *extCpuLoopTicks; 1.1765 +extern int *extClockTicks; 1.1766 +extern int *extTicks; 1.1767 +extern int cpuSavedTicks; 1.1768 + 1.1769 +extern void debuggerBreakOnWrite(u32 *, u32, u32, int); 1.1770 + 1.1771 +#define CPU_BREAK_LOOP2 \ 1.1772 + cpuSavedTicks = cpuSavedTicks - *extCpuLoopTicks; \ 1.1773 + *extCpuLoopTicks = *extClockTicks; \ 1.1774 + *extTicks = *extClockTicks; 1.1775 + 1.1776 +void cheatsWriteMemory(u32 *address, u32 value, u32 mask) 1.1777 +{ 1.1778 +#ifdef BKPT_SUPPORT 1.1779 +#ifdef SDL 1.1780 + if (cheatsNumber == 0) 1.1781 + { 1.1782 + debuggerBreakOnWrite(address, *address, value, 2); 1.1783 + CPU_BREAK_LOOP2; 1.1784 + *address = value; 1.1785 + return; 1.1786 + } 1.1787 +#endif 1.1788 +#endif 1.1789 +} 1.1790 + 1.1791 +void cheatsWriteHalfWord(u16 *address, u16 value, u16 mask) 1.1792 +{ 1.1793 +#ifdef BKPT_SUPPORT 1.1794 +#ifdef SDL 1.1795 + if (cheatsNumber == 0) 1.1796 + { 1.1797 + debuggerBreakOnWrite((u32 *)address, *address, value, 1); 1.1798 + CPU_BREAK_LOOP2; 1.1799 + *address = value; 1.1800 + return; 1.1801 + } 1.1802 +#endif 1.1803 +#endif 1.1804 +} 1.1805 + 1.1806 +#if defined BKPT_SUPPORT && defined SDL 1.1807 +void cheatsWriteByte(u8 *address, u8 value) 1.1808 +#else 1.1809 +void cheatsWriteByte(u8 *, u8) 1.1810 +#endif 1.1811 +{ 1.1812 +#ifdef BKPT_SUPPORT 1.1813 +#ifdef SDL 1.1814 + if (cheatsNumber == 0) 1.1815 + { 1.1816 + debuggerBreakOnWrite((u32 *)address, *address, value, 0); 1.1817 + CPU_BREAK_LOOP2; 1.1818 + *address = value; 1.1819 + return; 1.1820 + } 1.1821 +#endif 1.1822 +#endif 1.1823 +} 1.1824 + 1.1825 +#undef CPU_BREAK_LOOP2