Mercurial > vba-clojure
diff src/gb/gbCheats.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children | 5e8e5083da94 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/gb/gbCheats.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,477 @@ 1.4 +#include <cstdio> 1.5 +#include <cstdlib> 1.6 +#include <cctype> 1.7 +#include <cstring> 1.8 + 1.9 +#include "../NLS.h" 1.10 +#include "../common/System.h" 1.11 +#include "../common/Util.h" 1.12 + 1.13 +#include "gbCheats.h" 1.14 +#include "gbGlobals.h" 1.15 + 1.16 +gbCheat gbCheatList[100]; 1.17 +int gbCheatNumber = 0; 1.18 +bool gbCheatMap[0x10000]; 1.19 + 1.20 +extern bool8 cheatsEnabled; 1.21 + 1.22 +#define GBCHEAT_IS_HEX(a) (((a) >= 'A' && (a) <= 'F') || ((a) >= '0' && (a) <= '9')) 1.23 +#define GBCHEAT_HEX_VALUE(a) ((a) >= 'A' ? (a) - 'A' + 10 : (a) - '0') 1.24 + 1.25 +void gbCheatUpdateMap() 1.26 +{ 1.27 + memset(gbCheatMap, 0, 0x10000); 1.28 + 1.29 + for (int i = 0; i < gbCheatNumber; i++) 1.30 + { 1.31 + if (gbCheatList[i].enabled) 1.32 + gbCheatMap[gbCheatList[i].address] = true; 1.33 + } 1.34 +} 1.35 + 1.36 +void gbCheatsSaveGame(gzFile gzFile) 1.37 +{ 1.38 + utilWriteInt(gzFile, gbCheatNumber); 1.39 + if (gbCheatNumber) 1.40 + utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); 1.41 +} 1.42 + 1.43 +void gbCheatsReadGame(gzFile gzFile, int version) 1.44 +{ 1.45 + if (version <= 8) 1.46 + { 1.47 + int gbGgOn = utilReadInt(gzFile); 1.48 + 1.49 + if (gbGgOn) 1.50 + { 1.51 + int n = utilReadInt(gzFile); 1.52 + gbXxCheat tmpCheat; 1.53 + for (int i = 0; i < n; i++) 1.54 + { 1.55 + utilGzRead(gzFile, &tmpCheat, sizeof(gbXxCheat)); 1.56 + gbAddGgCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc); 1.57 + } 1.58 + } 1.59 + 1.60 + int gbGsOn = utilReadInt(gzFile); 1.61 + 1.62 + if (gbGsOn) 1.63 + { 1.64 + int n = utilReadInt(gzFile); 1.65 + gbXxCheat tmpCheat; 1.66 + for (int i = 0; i < n; i++) 1.67 + { 1.68 + utilGzRead(gzFile, &tmpCheat, sizeof(gbXxCheat)); 1.69 + gbAddGsCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc); 1.70 + } 1.71 + } 1.72 + } 1.73 + else 1.74 + { 1.75 + gbCheatNumber = utilReadInt(gzFile); 1.76 + 1.77 + if (gbCheatNumber) 1.78 + { 1.79 + utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); 1.80 + } 1.81 + } 1.82 + 1.83 + gbCheatUpdateMap(); 1.84 +} 1.85 + 1.86 +void gbCheatsSaveCheatList(const char *file) 1.87 +{ 1.88 + if (gbCheatNumber == 0) 1.89 + return; 1.90 + FILE *f = fopen(file, "wb"); 1.91 + if (f == NULL) 1.92 + return; 1.93 + int version = 1; 1.94 + fwrite(&version, 1, sizeof(version), f); 1.95 + int type = 1; 1.96 + fwrite(&type, 1, sizeof(type), f); 1.97 + fwrite(&gbCheatNumber, 1, sizeof(gbCheatNumber), f); 1.98 + fwrite(gbCheatList, 1, sizeof(gbCheatList), f); 1.99 + fclose(f); 1.100 +} 1.101 + 1.102 +bool gbCheatsLoadCheatList(const char *file) 1.103 +{ 1.104 + gbCheatNumber = 0; 1.105 + 1.106 + gbCheatUpdateMap(); 1.107 + 1.108 + int count = 0; 1.109 + 1.110 + FILE *f = fopen(file, "rb"); 1.111 + 1.112 + if (f == NULL) 1.113 + return false; 1.114 + 1.115 + int version = 0; 1.116 + 1.117 + if (fread(&version, 1, sizeof(version), f) != sizeof(version)) 1.118 + { 1.119 + fclose(f); 1.120 + return false; 1.121 + } 1.122 + 1.123 + if (version != 1) 1.124 + { 1.125 + systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION, 1.126 + N_("Unsupported cheat list version %d"), version); 1.127 + fclose(f); 1.128 + return false; 1.129 + } 1.130 + 1.131 + int type = 0; 1.132 + if (fread(&type, 1, sizeof(type), f) != sizeof(type)) 1.133 + { 1.134 + fclose(f); 1.135 + return false; 1.136 + } 1.137 + 1.138 + if (type != 1) 1.139 + { 1.140 + systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE, 1.141 + N_("Unsupported cheat list type %d"), type); 1.142 + fclose(f); 1.143 + return false; 1.144 + } 1.145 + 1.146 + if (fread(&count, 1, sizeof(count), f) != sizeof(count)) 1.147 + { 1.148 + fclose(f); 1.149 + return false; 1.150 + } 1.151 + 1.152 + if (fread(gbCheatList, 1, sizeof(gbCheatList), f) != sizeof(gbCheatList)) 1.153 + { 1.154 + fclose(f); 1.155 + return false; 1.156 + } 1.157 + 1.158 + fclose(f); 1.159 + gbCheatNumber = count; 1.160 + gbCheatUpdateMap(); 1.161 + 1.162 + return true; 1.163 +} 1.164 + 1.165 +bool gbVerifyGsCode(const char *code) 1.166 +{ 1.167 + int len = strlen(code); 1.168 + 1.169 + if (len == 0) 1.170 + return true; 1.171 + 1.172 + if (len != 8) 1.173 + return false; 1.174 + 1.175 + for (int i = 0; i < 8; i++) 1.176 + if (!GBCHEAT_IS_HEX(code[i])) 1.177 + return false; 1.178 + 1.179 + int address = GBCHEAT_HEX_VALUE(code[6]) << 12 | 1.180 + GBCHEAT_HEX_VALUE(code[7]) << 8 | 1.181 + GBCHEAT_HEX_VALUE(code[4]) << 4 | 1.182 + GBCHEAT_HEX_VALUE(code[5]); 1.183 + 1.184 + if (address < 0xa000 || 1.185 + address > 0xdfff) 1.186 + return false; 1.187 + 1.188 + return true; 1.189 +} 1.190 + 1.191 +void gbAddGsCheat(const char *code, const char *desc) 1.192 +{ 1.193 + if (gbCheatNumber > 99) 1.194 + { 1.195 + systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS, 1.196 + N_("Maximum number of cheats reached.")); 1.197 + return; 1.198 + } 1.199 + 1.200 + if (!gbVerifyGsCode(code)) 1.201 + { 1.202 + systemMessage(MSG_INVALID_GAMESHARK_CODE, 1.203 + N_("Invalid GameShark code: %s"), code); 1.204 + return; 1.205 + } 1.206 + 1.207 + int i = gbCheatNumber; 1.208 + 1.209 + strcpy(gbCheatList[i].cheatCode, code); 1.210 + strcpy(gbCheatList[i].cheatDesc, desc); 1.211 + 1.212 + gbCheatList[i].code = GBCHEAT_HEX_VALUE(code[0]) << 4 | 1.213 + GBCHEAT_HEX_VALUE(code[1]); 1.214 + 1.215 + gbCheatList[i].value = GBCHEAT_HEX_VALUE(code[2]) << 4 | 1.216 + GBCHEAT_HEX_VALUE(code[3]); 1.217 + 1.218 + gbCheatList[i].address = GBCHEAT_HEX_VALUE(code[6]) << 12 | 1.219 + GBCHEAT_HEX_VALUE(code[7]) << 8 | 1.220 + GBCHEAT_HEX_VALUE(code[4]) << 4 | 1.221 + GBCHEAT_HEX_VALUE(code[5]); 1.222 + 1.223 + gbCheatList[i].compare = 0; 1.224 + 1.225 + gbCheatList[i].enabled = true; 1.226 + 1.227 + gbCheatMap[gbCheatList[i].address] = true; 1.228 + 1.229 + gbCheatNumber++; 1.230 +} 1.231 + 1.232 +bool gbVerifyGgCode(const char *code) 1.233 +{ 1.234 + int len = strlen(code); 1.235 + 1.236 + if (len != 11 && 1.237 + len != 7 && 1.238 + len != 6 && 1.239 + len != 0) 1.240 + return false; 1.241 + 1.242 + if (len == 0) 1.243 + return true; 1.244 + 1.245 + if (!GBCHEAT_IS_HEX(code[0])) 1.246 + return false; 1.247 + if (!GBCHEAT_IS_HEX(code[1])) 1.248 + return false; 1.249 + if (!GBCHEAT_IS_HEX(code[2])) 1.250 + return false; 1.251 + if (code[3] != '-') 1.252 + return false; 1.253 + if (!GBCHEAT_IS_HEX(code[4])) 1.254 + return false; 1.255 + if (!GBCHEAT_IS_HEX(code[5])) 1.256 + return false; 1.257 + if (!GBCHEAT_IS_HEX(code[6])) 1.258 + return false; 1.259 + if (code[7] != 0) 1.260 + { 1.261 + if (code[7] != '-') 1.262 + return false; 1.263 + if (code[8] != 0) 1.264 + { 1.265 + if (!GBCHEAT_IS_HEX(code[8])) 1.266 + return false; 1.267 + if (!GBCHEAT_IS_HEX(code[9])) 1.268 + return false; 1.269 + if (!GBCHEAT_IS_HEX(code[10])) 1.270 + return false; 1.271 + } 1.272 + } 1.273 + 1.274 + // int replace = (GBCHEAT_HEX_VALUE(code[0]) << 4) + 1.275 + // GBCHEAT_HEX_VALUE(code[1]); 1.276 + 1.277 + int address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + 1.278 + (GBCHEAT_HEX_VALUE(code[4]) << 4) + 1.279 + (GBCHEAT_HEX_VALUE(code[5])) + 1.280 + ((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12); 1.281 + 1.282 + if (address >= 0x8000 && address <= 0x9fff) 1.283 + return false; 1.284 + 1.285 + if (address >= 0xc000) 1.286 + return false; 1.287 + 1.288 + if (code[7] == 0 || code[8] == '0') 1.289 + return true; 1.290 + 1.291 + int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + 1.292 + (GBCHEAT_HEX_VALUE(code[10])); 1.293 + compare = compare ^ 0xff; 1.294 + compare = (compare >> 2) | ((compare << 6) & 0xc0); 1.295 + compare ^= 0x45; 1.296 + 1.297 + int cloak = (GBCHEAT_HEX_VALUE(code[8])) ^ (GBCHEAT_HEX_VALUE(code[9])); 1.298 + 1.299 + if (cloak >= 1 && cloak <= 7) 1.300 + return false; 1.301 + 1.302 + return true; 1.303 +} 1.304 + 1.305 +void gbAddGgCheat(const char *code, const char *desc) 1.306 +{ 1.307 + if (gbCheatNumber > 99) 1.308 + { 1.309 + systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS, 1.310 + N_("Maximum number of cheats reached.")); 1.311 + return; 1.312 + } 1.313 + 1.314 + if (!gbVerifyGgCode(code)) 1.315 + { 1.316 + systemMessage(MSG_INVALID_GAMEGENIE_CODE, 1.317 + N_("Invalid GameGenie code: %s"), code); 1.318 + return; 1.319 + } 1.320 + 1.321 + int i = gbCheatNumber; 1.322 + 1.323 + int len = strlen(code); 1.324 + 1.325 + strcpy(gbCheatList[i].cheatCode, code); 1.326 + strcpy(gbCheatList[i].cheatDesc, desc); 1.327 + 1.328 + gbCheatList[i].code = 1; 1.329 + gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) + 1.330 + GBCHEAT_HEX_VALUE(code[1]); 1.331 + 1.332 + gbCheatList[i].address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + 1.333 + (GBCHEAT_HEX_VALUE(code[4]) << 4) + 1.334 + (GBCHEAT_HEX_VALUE(code[5])) + 1.335 + ((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12); 1.336 + 1.337 + gbCheatList[i].compare = 0; 1.338 + 1.339 + if (len != 7 && len != 8) 1.340 + { 1.341 + int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + 1.342 + (GBCHEAT_HEX_VALUE(code[10])); 1.343 + compare = compare ^ 0xff; 1.344 + compare = (compare >> 2) | ((compare << 6) & 0xc0); 1.345 + compare ^= 0x45; 1.346 + 1.347 + gbCheatList[i].compare = compare; 1.348 + gbCheatList[i].code = 0; 1.349 + } 1.350 + 1.351 + gbCheatList[i].enabled = true; 1.352 + 1.353 + gbCheatMap[gbCheatList[i].address] = true; 1.354 + 1.355 + gbCheatNumber++; 1.356 +} 1.357 + 1.358 +void gbCheatRemove(int i) 1.359 +{ 1.360 + if (i < 0 || i >= gbCheatNumber) 1.361 + { 1.362 + systemMessage(MSG_INVALID_CHEAT_TO_REMOVE, 1.363 + N_("Invalid cheat to remove %d"), i); 1.364 + return; 1.365 + } 1.366 + 1.367 + if ((i+1) < gbCheatNumber) 1.368 + { 1.369 + memcpy(&gbCheatList[i], &gbCheatList[i+1], sizeof(gbCheat)* 1.370 + (gbCheatNumber-i-1)); 1.371 + } 1.372 + 1.373 + gbCheatNumber--; 1.374 + 1.375 + gbCheatUpdateMap(); 1.376 +} 1.377 + 1.378 +void gbCheatRemoveAll() 1.379 +{ 1.380 + gbCheatNumber = 0; 1.381 + gbCheatUpdateMap(); 1.382 +} 1.383 + 1.384 +void gbCheatEnable(int i) 1.385 +{ 1.386 + if (i >= 0 && i < gbCheatNumber) 1.387 + { 1.388 + if (!gbCheatList[i].enabled) 1.389 + { 1.390 + gbCheatList[i].enabled = true; 1.391 + gbCheatUpdateMap(); 1.392 + } 1.393 + } 1.394 +} 1.395 + 1.396 +void gbCheatDisable(int i) 1.397 +{ 1.398 + if (i >= 0 && i < gbCheatNumber) 1.399 + { 1.400 + if (gbCheatList[i].enabled) 1.401 + { 1.402 + gbCheatList[i].enabled = false; 1.403 + gbCheatUpdateMap(); 1.404 + } 1.405 + } 1.406 +} 1.407 + 1.408 +bool gbCheatReadGSCodeFile(const char *fileName) 1.409 +{ 1.410 + FILE *file = fopen(fileName, "rb"); 1.411 + 1.412 + if (!file) 1.413 + return false; 1.414 + 1.415 + fseek(file, 0x18, SEEK_SET); 1.416 + int count = 0; 1.417 + fread(&count, 1, 2, file); 1.418 + int dummy = 0; 1.419 + gbCheatRemoveAll(); 1.420 + char desc[13]; 1.421 + char code[9]; 1.422 + int i; 1.423 + for (i = 0; i < count; i++) 1.424 + { 1.425 + fread(&dummy, 1, 2, file); 1.426 + fread(desc, 1, 12, file); 1.427 + desc[12] = 0; 1.428 + fread(code, 1, 8, file); 1.429 + code[8] = 0; 1.430 + gbAddGsCheat(code, desc); 1.431 + } 1.432 + 1.433 + for (i = 0; i < gbCheatNumber; i++) 1.434 + gbCheatDisable(i); 1.435 + 1.436 + fclose(file); 1.437 + return true; 1.438 +} 1.439 + 1.440 +u8 gbCheatRead(u16 address) 1.441 +{ 1.442 + if (!cheatsEnabled) 1.443 + return gbReadMemoryQuick(address); 1.444 + 1.445 + for (int i = 0; i < gbCheatNumber; i++) 1.446 + { 1.447 + if (gbCheatList[i].enabled && gbCheatList[i].address == address) 1.448 + { 1.449 + switch (gbCheatList[i].code) 1.450 + { 1.451 + case 0x100: // GameGenie support 1.452 + if (gbReadMemoryQuick(address) == gbCheatList[i].compare) 1.453 + return gbCheatList[i].value; 1.454 + break; 1.455 + case 0x00: 1.456 + case 0x01: 1.457 + case 0x80: 1.458 + return gbCheatList[i].value; 1.459 + case 0x90: 1.460 + case 0x91: 1.461 + case 0x92: 1.462 + case 0x93: 1.463 + case 0x94: 1.464 + case 0x95: 1.465 + case 0x96: 1.466 + case 0x97: 1.467 + if (address >= 0xd000 && address < 0xe000) 1.468 + { 1.469 + if (((gbMemoryMap[0x0d] - gbWram)/0x1000) == 1.470 + (gbCheatList[i].code - 0x90)) 1.471 + return gbCheatList[i].value; 1.472 + } 1.473 + else 1.474 + return gbCheatList[i].value; 1.475 + } 1.476 + } 1.477 + } 1.478 + return gbReadMemoryQuick(address); 1.479 +} 1.480 +