src/gba/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 "gba-overrides.h"
7
8#include "gba.h"
9#include "gba-gpio.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, GPIO_RTC | GPIO_LIGHT_SENSOR, -1 },
16 { "U3IE", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, -1 },
17 { "U3IP", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, -1 },
18
19 // Boktai 2: Solar Boy Django
20 { "U32J", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, -1 },
21 { "U32E", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, -1 },
22 { "U32P", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, -1 },
23
24 // Drill Dozer
25 { "V49J", SAVEDATA_SRAM, GPIO_RUMBLE, -1 },
26 { "V49E", SAVEDATA_SRAM, GPIO_RUMBLE, -1 },
27
28 // Final Fantasy Tactics Advance
29 { "AFXE", SAVEDATA_FLASH512, GPIO_NONE, 0x8000418 },
30
31 // Koro Koro Puzzle - Happy Panechu!
32 { "KHPJ", SAVEDATA_EEPROM, GPIO_TILT, -1 },
33
34 // Mega Man Battle Network
35 { "AREE", SAVEDATA_SRAM, GPIO_NONE, 0x800032E },
36
37 // Pokemon Ruby
38 { "AXVJ", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
39 { "AXVE", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
40 { "AXVP", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
41 { "AXVI", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
42 { "AXVS", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
43 { "AXVD", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
44 { "AXVF", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
45
46 // Pokemon Sapphire
47 { "AXPJ", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
48 { "AXPE", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
49 { "AXPP", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
50 { "AXPI", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
51 { "AXPS", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
52 { "AXPD", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
53 { "AXPF", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
54
55 // Pokemon Emerald
56 { "BPEJ", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
57 { "BPEE", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
58 { "BPEP", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
59 { "BPEI", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
60 { "BPES", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
61 { "BPED", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
62 { "BPEF", SAVEDATA_FLASH1M, GPIO_RTC, -1 },
63
64 // Pokemon Mystery Dungeon
65 { "B24J", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
66 { "B24E", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
67 { "B24P", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
68 { "B24U", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
69
70 // Pokemon FireRed
71 { "BPRJ", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
72 { "BPRE", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
73 { "BPRP", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
74
75 // Pokemon LeafGreen
76 { "BPGJ", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
77 { "BPGE", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
78 { "BPGP", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
79
80 // RockMan EXE 4.5 - Real Operation
81 { "BR4J", SAVEDATA_FLASH512, GPIO_RTC, -1 },
82
83 // Shin Bokura no Taiyou: Gyakushuu no Sabata
84 { "U33J", SAVEDATA_EEPROM, GPIO_RTC | GPIO_LIGHT_SENSOR, -1 },
85
86 // Super Mario Advance 4
87 { "AX4J", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
88 { "AX4E", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
89 { "AX4P", SAVEDATA_FLASH1M, GPIO_NONE, -1 },
90
91 // Top Gun - Combat Zones
92 { "A2YE", SAVEDATA_FORCE_NONE, GPIO_NONE, -1 },
93
94 // Wario Ware Twisted
95 { "RZWJ", SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO, -1 },
96 { "RZWE", SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO, -1 },
97 { "RZWP", SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO, -1 },
98
99 // Yoshi's Universal Gravitation
100 { "KYGJ", SAVEDATA_EEPROM, GPIO_TILT, -1 },
101 { "KYGE", SAVEDATA_EEPROM, GPIO_TILT, -1 },
102 { "KYGP", SAVEDATA_EEPROM, GPIO_TILT, -1 },
103
104 { { 0, 0, 0, 0 }, 0, 0, -1 }
105};
106
107bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOverride* override) {
108 override->savetype = SAVEDATA_AUTODETECT;
109 override->hardware = GPIO_NONE;
110 override->idleLoop = -1;
111 bool found;
112
113 if (override->id[0] == 'F') {
114 // Classic NES Series
115 override->savetype = SAVEDATA_EEPROM;
116 found = true;
117 } else {
118 int i;
119 for (i = 0; _overrides[i].id[0]; ++i) {
120 if (memcmp(override->id, _overrides[i].id, sizeof(override->id)) == 0) {
121 *override = _overrides[i];
122 found = true;
123 break;
124 }
125 }
126 }
127
128 if (config) {
129 char sectionName[16];
130 snprintf(sectionName, sizeof(sectionName), "override.%c%c%c%c", override->id[0], override->id[1], override->id[2], override->id[3]);
131 const char* savetype = ConfigurationGetValue(config, sectionName, "savetype");
132 const char* hardware = ConfigurationGetValue(config, sectionName, "hardware");
133 const char* idleLoop = ConfigurationGetValue(config, sectionName, "idleLoop");
134
135 if (savetype) {
136 if (strcasecmp(savetype, "SRAM") == 0) {
137 found = true;
138 override->savetype = SAVEDATA_SRAM;
139 } else if (strcasecmp(savetype, "EEPROM") == 0) {
140 found = true;
141 override->savetype = SAVEDATA_EEPROM;
142 } else if (strcasecmp(savetype, "FLASH512") == 0) {
143 found = true;
144 override->savetype = SAVEDATA_FLASH512;
145 } else if (strcasecmp(savetype, "FLASH1M") == 0) {
146 found = true;
147 override->savetype = SAVEDATA_FLASH1M;
148 } else if (strcasecmp(savetype, "NONE") == 0) {
149 found = true;
150 override->savetype = SAVEDATA_FORCE_NONE;
151 }
152 }
153
154 if (hardware) {
155 char* end;
156 long type = strtoul(hardware, &end, 0);
157 if (end && !*end) {
158 override->hardware = type;
159 found = true;
160 }
161 }
162
163 if (idleLoop) {
164 char* end;
165 uint32_t address = strtoul(idleLoop, &end, 16);
166 if (end && !*end) {
167 override->idleLoop = address;
168 found = true;
169 }
170 }
171 }
172 return found;
173}
174
175void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* override) {
176 GBASavedataForceType(&gba->memory.savedata, override->savetype);
177
178 if (override->hardware & GPIO_RTC) {
179 GBAGPIOInitRTC(&gba->memory.gpio);
180 }
181
182 if (override->hardware & GPIO_GYRO) {
183 GBAGPIOInitGyro(&gba->memory.gpio);
184 }
185
186 if (override->hardware & GPIO_RUMBLE) {
187 GBAGPIOInitRumble(&gba->memory.gpio);
188 }
189
190 if (override->hardware & GPIO_LIGHT_SENSOR) {
191 GBAGPIOInitLightSensor(&gba->memory.gpio);
192 }
193
194 if (override->hardware & GPIO_TILT) {
195 GBAGPIOInitTilt(&gba->memory.gpio);
196 }
197
198 gba->busyLoop = override->idleLoop;
199}