all repos — mgba @ 9c030fb55315162419cfbde1229860a95a988426

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