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 <mgba/internal/gba/overrides.h>
7 
8 #include <mgba/internal/gba/gba.h>
9 #include <mgba/internal/gba/hardware.h>
10 
11 #include <mgba-util/configuration.h>
12 
13 static const struct GBACartridgeOverride _overrides[] = {
14 	// Advance Wars
15 	{ "AWRE", SAVEDATA_FLASH512, HW_NONE, 0x8038810, false },
16 	{ "AWRP", SAVEDATA_FLASH512, HW_NONE, 0x8038810, false },
17 
18 	// Advance Wars 2: Black Hole Rising
19 	{ "AW2E", SAVEDATA_FLASH512, HW_NONE, 0x8036E08, false },
20 	{ "AW2P", SAVEDATA_FLASH512, HW_NONE, 0x803719C, false },
21 
22 	// Boktai: The Sun is in Your Hand
23 	{ "U3IJ", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false },
24 	{ "U3IE", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false },
25 	{ "U3IP", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false },
26 
27 	// Boktai 2: Solar Boy Django
28 	{ "U32J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false },
29 	{ "U32E", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false },
30 	{ "U32P", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false },
31 
32 	// Crash Bandicoot 2 - N-Tranced
33 	{ "AC8J", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
34 	{ "AC8E", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
35 	{ "AC8P", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
36 
37 	// DigiCommunication Nyo - Datou! Black Gemagema Dan
38 	{ "BDKJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
39 
40 	// Dragon Ball Z - The Legacy of Goku
41 	{ "ALGP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
42 
43 	// Dragon Ball Z - The Legacy of Goku II
44 	{ "ALFJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
45 	{ "ALFE", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
46 	{ "ALFP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
47 
48 	// Dragon Ball Z - Taiketsu
49 	{ "BDBE", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
50 	{ "BDBP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
51 
52 	// Drill Dozer
53 	{ "V49J", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE, false },
54 	{ "V49E", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE, false },
55 	{ "V49P", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE, false },
56 
57 	// e-Reader
58 	{ "PEAJ", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE },
59 	{ "PSAJ", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE },
60 	{ "PSAE", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE },
61 
62 	// Final Fantasy Tactics Advance
63 	{ "AFXE", SAVEDATA_FLASH512, HW_NONE, 0x8000428, false },
64 
65 	// F-Zero - Climax
66 	{ "BFTJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
67 
68 	// Iridion II
69 	{ "AI2E", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false },
70 	{ "AI2P", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false },
71 
72 	// Golden Sun: The Lost Age
73 	{ "AGFE", SAVEDATA_FLASH512, HW_NONE, 0x801353A, false },
74 
75 	// Koro Koro Puzzle - Happy Panechu!
76 	{ "KHPJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false },
77 
78 	// Legendz - Yomigaeru Shiren no Shima
79 	{ "BLJJ", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
80 	{ "BLJK", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
81 
82 	// Legendz - Sign of Nekuromu
83 	{ "BLVJ", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
84 
85 	// Mega Man Battle Network
86 	{ "AREE", SAVEDATA_SRAM, HW_NONE, 0x800032E, false },
87 
88 	// Mega Man Zero
89 	{ "AZCE", SAVEDATA_SRAM, HW_NONE, 0x80004E8, false },
90 
91 	// Metal Slug Advance
92 	{ "BSME", SAVEDATA_EEPROM, HW_NONE, 0x8000290, false },
93 
94 	// Pokemon Ruby
95 	{ "AXVJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
96 	{ "AXVE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
97 	{ "AXVP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
98 	{ "AXVI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
99 	{ "AXVS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
100 	{ "AXVD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
101 	{ "AXVF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
102 
103 	// Pokemon Sapphire
104 	{ "AXPJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
105 	{ "AXPE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
106 	{ "AXPP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
107 	{ "AXPI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
108 	{ "AXPS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
109 	{ "AXPD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
110 	{ "AXPF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
111 
112 	// Pokemon Emerald
113 	{ "BPEJ", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false },
114 	{ "BPEE", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false },
115 	{ "BPEP", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false },
116 	{ "BPEI", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false },
117 	{ "BPES", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false },
118 	{ "BPED", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false },
119 	{ "BPEF", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false },
120 
121 	// Pokemon Mystery Dungeon
122 	{ "B24J", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
123 	{ "B24E", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
124 	{ "B24P", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
125 	{ "B24U", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
126 
127 	// Pokemon FireRed
128 	{ "BPRJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
129 	{ "BPRE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
130 	{ "BPRP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
131 	{ "BPRI", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
132 	{ "BPRS", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
133 	{ "BPRD", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
134 	{ "BPRF", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
135 
136 	// Pokemon LeafGreen
137 	{ "BPGJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
138 	{ "BPGE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
139 	{ "BPGP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
140 	{ "BPGI", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
141 	{ "BPGS", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
142 	{ "BPGD", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
143 	{ "BPGF", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false },
144 
145 	// RockMan EXE 4.5 - Real Operation
146 	{ "BR4J", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false },
147 
148 	// Rocky
149 	{ "AR8E", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
150 	{ "AROP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
151 
152 	// Sennen Kazoku
153 	{ "BKAJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false },
154 
155 	// Shin Bokura no Taiyou: Gyakushuu no Sabata
156 	{ "U33J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false },
157 
158 	// Super Mario Advance 2
159 	{ "AA2J", SAVEDATA_EEPROM, HW_NONE, 0x800052E, false },
160 	{ "AA2E", SAVEDATA_EEPROM, HW_NONE, 0x800052E, false },
161 	{ "AA2P", SAVEDATA_AUTODETECT, HW_NONE, 0x800052E, false },
162 
163 	// Super Mario Advance 3
164 	{ "A3AJ", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C, false },
165 	{ "A3AE", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C, false },
166 	{ "A3AP", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C, false },
167 
168 	// Super Mario Advance 4
169 	{ "AX4J", SAVEDATA_FLASH1M, HW_NONE, 0x800072A, false },
170 	{ "AX4E", SAVEDATA_FLASH1M, HW_NONE, 0x800072A, false },
171 	{ "AX4P", SAVEDATA_FLASH1M, HW_NONE, 0x800072A, false },
172 
173 	// Super Monkey Ball Jr.
174 	{ "ALUE", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
175 	{ "ALUP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
176 
177 	// Top Gun - Combat Zones
178 	{ "A2YE", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false },
179 
180 	// Ueki no Housoku - Jingi Sakuretsu! Nouryokusha Battle
181 	{ "BUHJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
182 
183 	// Wario Ware Twisted
184 	{ "RZWJ", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE, false },
185 	{ "RZWE", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE, false },
186 	{ "RZWP", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE, false },
187 
188 	// Yoshi's Universal Gravitation
189 	{ "KYGJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false },
190 	{ "KYGE", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false },
191 	{ "KYGP", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false },
192 
193 	// Aging cartridge
194 	{ "TCHK", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
195 
196 	// Famicom Mini series 3 (FDS), some aren't mirrored (22 - 28)
197 	// See https://forum.no-intro.org/viewtopic.php?f=2&t=4221 for discussion
198 	{ "FNMJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
199 	{ "FMRJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
200 	{ "FPTJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
201 	{ "FLBJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
202 	{ "FFMJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
203 	{ "FTKJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
204 	{ "FTUJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false },
205 
206 	{ { 0, 0, 0, 0 }, 0, 0, IDLE_LOOP_NONE, false }
207 };
208 
GBAOverrideFind(const struct Configuration * config,struct GBACartridgeOverride * override)209 bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOverride* override) {
210 	override->savetype = SAVEDATA_AUTODETECT;
211 	override->hardware = HW_NONE;
212 	override->idleLoop = IDLE_LOOP_NONE;
213 	override->mirroring = false;
214 	override->vbaBugCompat = false;
215 	bool found = false;
216 
217 	int i;
218 	for (i = 0; _overrides[i].id[0]; ++i) {
219 		if (memcmp(override->id, _overrides[i].id, sizeof(override->id)) == 0) {
220 			*override = _overrides[i];
221 			found = true;
222 			break;
223 		}
224 	}
225 	if (!found && override->id[0] == 'F') {
226 		// Classic NES Series
227 		override->savetype = SAVEDATA_EEPROM;
228 		override->mirroring = true;
229 		found = true;
230 	}
231 
232 	if (config) {
233 		char sectionName[16];
234 		snprintf(sectionName, sizeof(sectionName), "override.%c%c%c%c", override->id[0], override->id[1], override->id[2], override->id[3]);
235 		const char* savetype = ConfigurationGetValue(config, sectionName, "savetype");
236 		const char* hardware = ConfigurationGetValue(config, sectionName, "hardware");
237 		const char* idleLoop = ConfigurationGetValue(config, sectionName, "idleLoop");
238 
239 		if (savetype) {
240 			if (strcasecmp(savetype, "SRAM") == 0) {
241 				found = true;
242 				override->savetype = SAVEDATA_SRAM;
243 			} else if (strcasecmp(savetype, "EEPROM") == 0) {
244 				found = true;
245 				override->savetype = SAVEDATA_EEPROM;
246 			} else if (strcasecmp(savetype, "EEPROM512") == 0) {
247 				found = true;
248 				override->savetype = SAVEDATA_EEPROM512;
249 			} else if (strcasecmp(savetype, "FLASH512") == 0) {
250 				found = true;
251 				override->savetype = SAVEDATA_FLASH512;
252 			} else if (strcasecmp(savetype, "FLASH1M") == 0) {
253 				found = true;
254 				override->savetype = SAVEDATA_FLASH1M;
255 			} else if (strcasecmp(savetype, "NONE") == 0) {
256 				found = true;
257 				override->savetype = SAVEDATA_FORCE_NONE;
258 			}
259 		}
260 
261 		if (hardware) {
262 			char* end;
263 			long type = strtoul(hardware, &end, 0);
264 			if (end && !*end) {
265 				override->hardware = type;
266 				found = true;
267 			}
268 		}
269 
270 		if (idleLoop) {
271 			char* end;
272 			uint32_t address = strtoul(idleLoop, &end, 16);
273 			if (end && !*end) {
274 				override->idleLoop = address;
275 				found = true;
276 			}
277 		}
278 	}
279 	return found;
280 }
281 
GBAOverrideSave(struct Configuration * config,const struct GBACartridgeOverride * override)282 void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOverride* override) {
283 	char sectionName[16];
284 	snprintf(sectionName, sizeof(sectionName), "override.%c%c%c%c", override->id[0], override->id[1], override->id[2], override->id[3]);
285 	const char* savetype = 0;
286 	switch (override->savetype) {
287 	case SAVEDATA_SRAM:
288 		savetype = "SRAM";
289 		break;
290 	case SAVEDATA_EEPROM:
291 		savetype = "EEPROM";
292 		break;
293 	case SAVEDATA_EEPROM512:
294 		savetype = "EEPROM512";
295 		break;
296 	case SAVEDATA_FLASH512:
297 		savetype = "FLASH512";
298 		break;
299 	case SAVEDATA_FLASH1M:
300 		savetype = "FLASH1M";
301 		break;
302 	case SAVEDATA_FORCE_NONE:
303 		savetype = "NONE";
304 		break;
305 	case SAVEDATA_AUTODETECT:
306 		break;
307 	}
308 	ConfigurationSetValue(config, sectionName, "savetype", savetype);
309 
310 	if (override->hardware != HW_NO_OVERRIDE) {
311 		ConfigurationSetIntValue(config, sectionName, "hardware", override->hardware);
312 	} else {
313 		ConfigurationClearValue(config, sectionName, "hardware");
314 	}
315 
316 	if (override->idleLoop != IDLE_LOOP_NONE) {
317 		ConfigurationSetUIntValue(config, sectionName, "idleLoop", override->idleLoop);
318 	} else {
319 		ConfigurationClearValue(config, sectionName, "idleLoop");
320 	}
321 }
322 
GBAOverrideApply(struct GBA * gba,const struct GBACartridgeOverride * override)323 void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* override) {
324 	if (override->savetype != SAVEDATA_AUTODETECT) {
325 		GBASavedataForceType(&gba->memory.savedata, override->savetype);
326 	}
327 
328 	gba->vbaBugCompat = override->vbaBugCompat;
329 
330 	if (override->hardware != HW_NO_OVERRIDE) {
331 		GBAHardwareClear(&gba->memory.hw);
332 
333 		if (override->hardware & HW_RTC) {
334 			GBAHardwareInitRTC(&gba->memory.hw);
335 		}
336 
337 		if (override->hardware & HW_GYRO) {
338 			GBAHardwareInitGyro(&gba->memory.hw);
339 		}
340 
341 		if (override->hardware & HW_RUMBLE) {
342 			GBAHardwareInitRumble(&gba->memory.hw);
343 		}
344 
345 		if (override->hardware & HW_LIGHT_SENSOR) {
346 			GBAHardwareInitLight(&gba->memory.hw);
347 		}
348 
349 		if (override->hardware & HW_TILT) {
350 			GBAHardwareInitTilt(&gba->memory.hw);
351 		}
352 
353 		if (override->hardware & HW_EREADER) {
354 			GBAHardwareInitEReader(&gba->memory.hw);
355 		}
356 
357 		if (override->hardware & HW_GB_PLAYER_DETECTION) {
358 			gba->memory.hw.devices |= HW_GB_PLAYER_DETECTION;
359 		} else {
360 			gba->memory.hw.devices &= ~HW_GB_PLAYER_DETECTION;
361 		}
362 	}
363 
364 	if (override->idleLoop != IDLE_LOOP_NONE) {
365 		gba->idleLoop = override->idleLoop;
366 		if (gba->idleOptimization == IDLE_LOOP_DETECT) {
367 			gba->idleOptimization = IDLE_LOOP_REMOVE;
368 		}
369 	}
370 
371 	if (override->mirroring) {
372 		gba->memory.mirroring = true;
373 	}
374 }
375 
GBAOverrideApplyDefaults(struct GBA * gba,const struct Configuration * overrides)376 void GBAOverrideApplyDefaults(struct GBA* gba, const struct Configuration* overrides) {
377 	struct GBACartridgeOverride override = { .idleLoop = IDLE_LOOP_NONE };
378 	const struct GBACartridge* cart = (const struct GBACartridge*) gba->memory.rom;
379 	if (cart) {
380 		memcpy(override.id, &cart->id, sizeof(override.id));
381 
382 		static const uint32_t pokemonTable[] = {
383 			// Emerald
384 			0x4881F3F8, // BPEJ
385 			0x8C4D3108, // BPES
386 			0x1F1C08FB, // BPEE
387 			0x34C9DF89, // BPED
388 			0xA3FDCCB1, // BPEF
389 			0xA0AEC80A, // BPEI
390 
391 			// FireRed
392 			0x1A81EEDF, // BPRD
393 			0x3B2056E9, // BPRJ
394 			0x5DC668F6, // BPRF
395 			0x73A72167, // BPRI
396 			0x84EE4776, // BPRE rev 1
397 			0x9F08064E, // BPRS
398 			0xBB640DF7, // BPRJ rev 1
399 			0xDD88761C, // BPRE
400 
401 			// Ruby
402 			0x61641576, // AXVE rev 1
403 			0xAEAC73E6, // AXVE rev 2
404 			0xF0815EE7, // AXVE
405 		};
406 
407 		bool isPokemon = false;
408 		isPokemon = isPokemon || !strncmp("pokemon red version", &((const char*) gba->memory.rom)[0x108], 20);
409 		isPokemon = isPokemon || !strncmp("pokemon emerald version", &((const char*) gba->memory.rom)[0x108], 24);
410 		isPokemon = isPokemon || !strncmp("AXVE", &((const char*) gba->memory.rom)[0xAC], 4);
411 		bool isKnownPokemon = false;
412 		if (isPokemon) {
413 			size_t i;
414 			for (i = 0; !isKnownPokemon && i < sizeof(pokemonTable) / sizeof(*pokemonTable); ++i) {
415 				isKnownPokemon = gba->romCrc32 == pokemonTable[i];
416 			}
417 		}
418 
419 		if (isPokemon && !isKnownPokemon) {
420 			// Enable FLASH1M and RTC on Pokémon ROM hacks
421 			override.savetype = SAVEDATA_FLASH1M;
422 			override.hardware = HW_RTC;
423 			override.vbaBugCompat = true;
424 			GBAOverrideApply(gba, &override);
425 		} else if (GBAOverrideFind(overrides, &override)) {
426 			GBAOverrideApply(gba, &override);
427 		}
428 	}
429 }
430