all repos — mgba @ bd4dd8de5ca3cd2c62c778c26114f685be6ac729

mGBA Game Boy Advance Emulator

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