all repos — mgba @ fb7ecb8079aa848c1b6811c8a5fdc692dd201bed

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