all repos — mgba @ bdf6d7f7ec86fa7e8d934333455f44ceb53b2b2e

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