all repos — mgba @ 5147a5160f1bb46590f19119e3ae424f1ee57fbf

mGBA Game Boy Advance Emulator

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