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 // Metal Slug Advance
55 { "BSME", SAVEDATA_EEPROM, HW_NONE, 0x8000290 },
56
57 // Pokemon Ruby
58 { "AXVJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
59 { "AXVE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
60 { "AXVP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
61 { "AXVI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
62 { "AXVS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
63 { "AXVD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
64 { "AXVF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
65
66 // Pokemon Sapphire
67 { "AXPJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
68 { "AXPE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
69 { "AXPP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
70 { "AXPI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
71 { "AXPS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
72 { "AXPD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
73 { "AXPF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
74
75 // Pokemon Emerald
76 { "BPEJ", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
77 { "BPEE", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
78 { "BPEP", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
79 { "BPEI", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
80 { "BPES", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
81 { "BPED", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
82 { "BPEF", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 },
83
84 // Pokemon Mystery Dungeon
85 { "B24J", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
86 { "B24E", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
87 { "B24P", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
88 { "B24U", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
89
90 // Pokemon FireRed
91 { "BPRJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
92 { "BPRE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
93 { "BPRP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
94 { "BPRI", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
95 { "BPRS", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
96 { "BPRD", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
97 { "BPRF", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
98
99 // Pokemon LeafGreen
100 { "BPGJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
101 { "BPGE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
102 { "BPGP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
103 { "BPGI", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
104 { "BPGS", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
105 { "BPGD", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
106 { "BPGF", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE },
107
108 // RockMan EXE 4.5 - Real Operation
109 { "BR4J", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE },
110
111 // Rocky
112 { "AR8E", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE },
113 { "AROP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE },
114
115 // Sennen Kazoku
116 { "BKAJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE },
117
118 // Shin Bokura no Taiyou: Gyakushuu no Sabata
119 { "U33J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE },
120
121 // Super Mario Advance 2
122 { "AA2J", SAVEDATA_EEPROM, HW_NONE, 0x800052E },
123 { "AA2E", SAVEDATA_EEPROM, HW_NONE, 0x800052E },
124 { "AA2P", SAVEDATA_EEPROM, HW_NONE, 0x800052E },
125
126 // Super Mario Advance 3
127 { "A3AJ", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C },
128 { "A3AE", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C },
129 { "A3AP", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C },
130
131 // Super Mario Advance 4
132 { "AX4J", SAVEDATA_FLASH1M, HW_NONE, 0x800072A },
133 { "AX4E", SAVEDATA_FLASH1M, HW_NONE, 0x800072A },
134 { "AX4P", SAVEDATA_FLASH1M, HW_NONE, 0x800072A },
135
136 // Top Gun - Combat Zones
137 { "A2YE", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE },
138
139 // Wario Ware Twisted
140 { "RZWJ", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE },
141 { "RZWE", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE },
142 { "RZWP", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE },
143
144 // Yoshi's Universal Gravitation
145 { "KYGJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE },
146 { "KYGE", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE },
147 { "KYGP", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE },
148
149 { { 0, 0, 0, 0 }, 0, 0, IDLE_LOOP_NONE }
150};
151
152bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOverride* override) {
153 override->savetype = SAVEDATA_AUTODETECT;
154 override->hardware = HW_NONE;
155 override->idleLoop = IDLE_LOOP_NONE;
156 bool found;
157
158 if (override->id[0] == 'F') {
159 // Classic NES Series
160 override->savetype = SAVEDATA_EEPROM;
161 found = true;
162 } else {
163 int i;
164 for (i = 0; _overrides[i].id[0]; ++i) {
165 if (memcmp(override->id, _overrides[i].id, sizeof(override->id)) == 0) {
166 *override = _overrides[i];
167 found = true;
168 break;
169 }
170 }
171 }
172
173 if (config) {
174 char sectionName[16];
175 snprintf(sectionName, sizeof(sectionName), "override.%c%c%c%c", override->id[0], override->id[1], override->id[2], override->id[3]);
176 const char* savetype = ConfigurationGetValue(config, sectionName, "savetype");
177 const char* hardware = ConfigurationGetValue(config, sectionName, "hardware");
178 const char* idleLoop = ConfigurationGetValue(config, sectionName, "idleLoop");
179
180 if (savetype) {
181 if (strcasecmp(savetype, "SRAM") == 0) {
182 found = true;
183 override->savetype = SAVEDATA_SRAM;
184 } else if (strcasecmp(savetype, "EEPROM") == 0) {
185 found = true;
186 override->savetype = SAVEDATA_EEPROM;
187 } else if (strcasecmp(savetype, "FLASH512") == 0) {
188 found = true;
189 override->savetype = SAVEDATA_FLASH512;
190 } else if (strcasecmp(savetype, "FLASH1M") == 0) {
191 found = true;
192 override->savetype = SAVEDATA_FLASH1M;
193 } else if (strcasecmp(savetype, "NONE") == 0) {
194 found = true;
195 override->savetype = SAVEDATA_FORCE_NONE;
196 }
197 }
198
199 if (hardware) {
200 char* end;
201 long type = strtoul(hardware, &end, 0);
202 if (end && !*end) {
203 override->hardware = type;
204 found = true;
205 }
206 }
207
208 if (idleLoop) {
209 char* end;
210 uint32_t address = strtoul(idleLoop, &end, 16);
211 if (end && !*end) {
212 override->idleLoop = address;
213 found = true;
214 }
215 }
216 }
217 return found;
218}
219
220void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOverride* override) {
221 char sectionName[16];
222 snprintf(sectionName, sizeof(sectionName), "override.%c%c%c%c", override->id[0], override->id[1], override->id[2], override->id[3]);
223 const char* savetype = 0;
224 switch (override->savetype) {
225 case SAVEDATA_SRAM:
226 savetype = "SRAM";
227 break;
228 case SAVEDATA_EEPROM:
229 savetype = "EEPROM";
230 break;
231 case SAVEDATA_FLASH512:
232 savetype = "FLASH512";
233 break;
234 case SAVEDATA_FLASH1M:
235 savetype = "FLASH1M";
236 break;
237 case SAVEDATA_FORCE_NONE:
238 savetype = "NONE";
239 break;
240 case SAVEDATA_AUTODETECT:
241 break;
242 }
243 ConfigurationSetValue(config, sectionName, "savetype", savetype);
244
245 if (override->hardware != HW_NO_OVERRIDE) {
246 ConfigurationSetIntValue(config, sectionName, "hardware", override->hardware);
247 } else {
248 ConfigurationClearValue(config, sectionName, "hardware");
249 }
250
251 if (override->idleLoop != IDLE_LOOP_NONE) {
252 ConfigurationSetUIntValue(config, sectionName, "idleLoop", override->idleLoop);
253 } else {
254 ConfigurationClearValue(config, sectionName, "idleLoop");
255 }
256}
257
258void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* override) {
259 if (override->savetype != SAVEDATA_AUTODETECT) {
260 GBASavedataForceType(&gba->memory.savedata, override->savetype);
261 }
262
263 if (override->hardware != HW_NO_OVERRIDE) {
264 GBAHardwareClear(&gba->memory.hw);
265
266 if (override->hardware & HW_RTC) {
267 GBAHardwareInitRTC(&gba->memory.hw);
268 }
269
270 if (override->hardware & HW_GYRO) {
271 GBAHardwareInitGyro(&gba->memory.hw);
272 }
273
274 if (override->hardware & HW_RUMBLE) {
275 GBAHardwareInitRumble(&gba->memory.hw);
276 }
277
278 if (override->hardware & HW_LIGHT_SENSOR) {
279 GBAHardwareInitLight(&gba->memory.hw);
280 }
281
282 if (override->hardware & HW_TILT) {
283 GBAHardwareInitTilt(&gba->memory.hw);
284 }
285 }
286
287 if (override->idleLoop != IDLE_LOOP_NONE) {
288 gba->idleLoop = override->idleLoop;
289 if (gba->idleOptimization == IDLE_LOOP_DETECT) {
290 gba->idleOptimization = IDLE_LOOP_REMOVE;
291 }
292 }
293}