all repos — mgba @ ed46d63ebda06a3a1889ebc72cd49573b804f2d8

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