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