src/gba/context/overrides.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "overrides.h"
7
8#include "gba/gba.h"
9#include "gba/hardware.h"
10
11#include "util/configuration.h"
12
13static const struct GBACartridgeOverride _overrides[] = {
14 // Advance Wars
15 { "AWRE", SAVEDATA_FLASH512, HW_NONE, 0x8038810 },
16 { "AWRP", SAVEDATA_FLASH512, HW_NONE, 0x8038810 },
17
18 // Advance Wars 2: Black Hole Rising
19 { "AW2E", SAVEDATA_FLASH512, HW_NONE, 0x8036E08 },
20 { "AW2P", SAVEDATA_FLASH512, HW_NONE, 0x803719C },
21
22 // Boktai: The Sun is in Your Hand
23 { "U3IJ", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE },
24 { "U3IE", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE },
25 { "U3IP", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE },
26
27 // Boktai 2: Solar Boy Django
28 { "U32J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE },
29 { "U32E", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE },
30 { "U32P", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE },
31
32 // Dragon Ball Z - The Legacy of Goku
33 { "ALGP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE },
34
35 // Dragon Ball Z - Taiketsu
36 { "BDBE", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE },
37 { "BDBP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE },
38
39 // Drill Dozer
40 { "V49J", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE },
41 { "V49E", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE },
42
43 // Final Fantasy Tactics Advance
44 { "AFXE", SAVEDATA_FLASH512, HW_NONE, 0x8000428 },
45
46 // F-Zero - Climax
47 { "BFTJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
48
49 // Golden Sun: The Lost Age
50 { "AGFE", SAVEDATA_FLASH512, HW_NONE, 0x801353A },
51
52 // Koro Koro Puzzle - Happy Panechu!
53 { "KHPJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE },
54
55 // Mega Man Battle Network
56 { "AREE", SAVEDATA_SRAM, HW_NONE, 0x800032E },
57
58 // Mega Man Zero
59 { "AZCE", SAVEDATA_SRAM, HW_NONE, 0x80004E8 },
60
61 // Metal Slug Advance
62 { "BSME", SAVEDATA_EEPROM, HW_NONE, 0x8000290 },
63
64 // Pokemon Ruby
65 { "AXVJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
66 { "AXVE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
67 { "AXVP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
68 { "AXVI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
69 { "AXVS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
70 { "AXVD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
71 { "AXVF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
72
73 // Pokemon Sapphire
74 { "AXPJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
75 { "AXPE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
76 { "AXPP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
77 { "AXPI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
78 { "AXPS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
79 { "AXPD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
80 { "AXPF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
81
82 // Pokemon Emerald
83 { "BPEJ", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
84 { "BPEE", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
85 { "BPEP", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
86 { "BPEI", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
87 { "BPES", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
88 { "BPED", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
89 { "BPEF", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
90
91 // Pokemon Mystery Dungeon
92 { "B24J", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
93 { "B24E", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
94 { "B24P", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
95 { "B24U", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
96
97 // Pokemon FireRed
98 { "BPRJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
99 { "BPRE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
100 { "BPRP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
101 { "BPRI", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
102 { "BPRS", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
103 { "BPRD", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
104 { "BPRF", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
105
106 // Pokemon LeafGreen
107 { "BPGJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
108 { "BPGE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
109 { "BPGP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
110 { "BPGI", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
111 { "BPGS", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
112 { "BPGD", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
113 { "BPGF", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
114
115 // RockMan EXE 4.5 - Real Operation
116 { "BR4J", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE },
117
118 // Rocky
119 { "AR8E", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE },
120 { "AROP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE },
121
122 // Sennen Kazoku
123 { "BKAJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
124
125 // Shin Bokura no Taiyou: Gyakushuu no Sabata
126 { "U33J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE },
127
128 // Super Mario Advance 2
129 { "AA2J", SAVEDATA_EEPROM, HW_NONE, 0x800052E },
130 { "AA2E", SAVEDATA_EEPROM, HW_NONE, 0x800052E },
131 { "AA2P", SAVEDATA_AUTODETECT, HW_NONE, 0x800052E },
132
133 // Super Mario Advance 3
134 { "A3AJ", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C },
135 { "A3AE", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C },
136 { "A3AP", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C },
137
138 // Super Mario Advance 4
139 { "AX4J", SAVEDATA_FLASH1M, HW_NONE, 0x800072A },
140 { "AX4E", SAVEDATA_FLASH1M, HW_NONE, 0x800072A },
141 { "AX4P", SAVEDATA_FLASH1M, HW_NONE, 0x800072A },
142
143 // Top Gun - Combat Zones
144 { "A2YE", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE },
145
146 // Wario Ware Twisted
147 { "RZWJ", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE },
148 { "RZWE", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE },
149 { "RZWP", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE },
150
151 // Yoshi's Universal Gravitation
152 { "KYGJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE },
153 { "KYGE", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE },
154 { "KYGP", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE },
155
156 { { 0, 0, 0, 0 }, 0, 0, IDLE_LOOP_NONE }
157};
158
159bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOverride* override) {
160 override->savetype = SAVEDATA_AUTODETECT;
161 override->hardware = HW_NONE;
162 override->idleLoop = IDLE_LOOP_NONE;
163 bool found = false;
164
165 if (override->id[0] == 'F') {
166 // Classic NES Series
167 override->savetype = SAVEDATA_EEPROM;
168 found = true;
169 } else {
170 int i;
171 for (i = 0; _overrides[i].id[0]; ++i) {
172 if (memcmp(override->id, _overrides[i].id, sizeof(override->id)) == 0) {
173 *override = _overrides[i];
174 found = true;
175 break;
176 }
177 }
178 }
179
180 if (config) {
181 char sectionName[16];
182 snprintf(sectionName, sizeof(sectionName), "override.%c%c%c%c", override->id[0], override->id[1], override->id[2], override->id[3]);
183 const char* savetype = ConfigurationGetValue(config, sectionName, "savetype");
184 const char* hardware = ConfigurationGetValue(config, sectionName, "hardware");
185 const char* idleLoop = ConfigurationGetValue(config, sectionName, "idleLoop");
186
187 if (savetype) {
188 if (strcasecmp(savetype, "SRAM") == 0) {
189 found = true;
190 override->savetype = SAVEDATA_SRAM;
191 } else if (strcasecmp(savetype, "EEPROM") == 0) {
192 found = true;
193 override->savetype = SAVEDATA_EEPROM;
194 } else if (strcasecmp(savetype, "FLASH512") == 0) {
195 found = true;
196 override->savetype = SAVEDATA_FLASH512;
197 } else if (strcasecmp(savetype, "FLASH1M") == 0) {
198 found = true;
199 override->savetype = SAVEDATA_FLASH1M;
200 } else if (strcasecmp(savetype, "NONE") == 0) {
201 found = true;
202 override->savetype = SAVEDATA_FORCE_NONE;
203 }
204 }
205
206 if (hardware) {
207 char* end;
208 long type = strtoul(hardware, &end, 0);
209 if (end && !*end) {
210 override->hardware = type;
211 found = true;
212 }
213 }
214
215 if (idleLoop) {
216 char* end;
217 uint32_t address = strtoul(idleLoop, &end, 16);
218 if (end && !*end) {
219 override->idleLoop = address;
220 found = true;
221 }
222 }
223 }
224 return found;
225}
226
227void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOverride* override) {
228 char sectionName[16];
229 snprintf(sectionName, sizeof(sectionName), "override.%c%c%c%c", override->id[0], override->id[1], override->id[2], override->id[3]);
230 const char* savetype = 0;
231 switch (override->savetype) {
232 case SAVEDATA_SRAM:
233 savetype = "SRAM";
234 break;
235 case SAVEDATA_EEPROM:
236 savetype = "EEPROM";
237 break;
238 case SAVEDATA_FLASH512:
239 savetype = "FLASH512";
240 break;
241 case SAVEDATA_FLASH1M:
242 savetype = "FLASH1M";
243 break;
244 case SAVEDATA_FORCE_NONE:
245 savetype = "NONE";
246 break;
247 case SAVEDATA_AUTODETECT:
248 break;
249 }
250 ConfigurationSetValue(config, sectionName, "savetype", savetype);
251
252 if (override->hardware != HW_NO_OVERRIDE) {
253 ConfigurationSetIntValue(config, sectionName, "hardware", override->hardware);
254 } else {
255 ConfigurationClearValue(config, sectionName, "hardware");
256 }
257
258 if (override->idleLoop != IDLE_LOOP_NONE) {
259 ConfigurationSetUIntValue(config, sectionName, "idleLoop", override->idleLoop);
260 } else {
261 ConfigurationClearValue(config, sectionName, "idleLoop");
262 }
263}
264
265void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* override) {
266 if (override->savetype != SAVEDATA_AUTODETECT) {
267 GBASavedataForceType(&gba->memory.savedata, override->savetype, gba->realisticTiming);
268 }
269
270 if (override->hardware != HW_NO_OVERRIDE) {
271 GBAHardwareClear(&gba->memory.hw);
272
273 if (override->hardware & HW_RTC) {
274 GBAHardwareInitRTC(&gba->memory.hw);
275 }
276
277 if (override->hardware & HW_GYRO) {
278 GBAHardwareInitGyro(&gba->memory.hw);
279 }
280
281 if (override->hardware & HW_RUMBLE) {
282 GBAHardwareInitRumble(&gba->memory.hw);
283 }
284
285 if (override->hardware & HW_LIGHT_SENSOR) {
286 GBAHardwareInitLight(&gba->memory.hw);
287 }
288
289 if (override->hardware & HW_TILT) {
290 GBAHardwareInitTilt(&gba->memory.hw);
291 }
292
293 if (override->hardware & HW_GB_PLAYER_DETECTION) {
294 gba->memory.hw.devices |= HW_GB_PLAYER_DETECTION;
295 } else {
296 gba->memory.hw.devices &= ~HW_GB_PLAYER_DETECTION;
297 }
298 }
299
300 if (override->idleLoop != IDLE_LOOP_NONE) {
301 gba->idleLoop = override->idleLoop;
302 if (gba->idleOptimization == IDLE_LOOP_DETECT) {
303 gba->idleOptimization = IDLE_LOOP_REMOVE;
304 }
305 }
306}
307
308void GBAOverrideApplyDefaults(struct GBA* gba) {
309 struct GBACartridgeOverride override;
310 const struct GBACartridge* cart = (const struct GBACartridge*) gba->memory.rom;
311 memcpy(override.id, &cart->id, sizeof(override.id));
312 if (GBAOverrideFind(0, &override)) {
313 GBAOverrideApply(gba, &override);
314 }
315}