all repos — mgba @ 475954aff13370093efa3303b36d0e8b975152e7

mGBA Game Boy Advance Emulator

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