src/gb/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 <mgba/internal/gb/overrides.h>
7
8#include <mgba/internal/gb/gb.h>
9#include <mgba/internal/gb/mbc.h>
10
11#include <mgba-util/configuration.h>
12#include <mgba-util/crc32.h>
13
14static const struct GBCartridgeOverride _overrides[] = {
15 // Pokemon Spaceworld 1997 demo
16 { 0x232a067d, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (debug)
17 { 0x630ed957, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (non-debug)
18 { 0x5aff0038, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Silver (debug)
19 { 0xa61856bd, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Silver (non-debug)
20
21 { 0, 0, 0, { 0 } }
22};
23
24bool GBOverrideFind(const struct Configuration* config, struct GBCartridgeOverride* override) {
25 override->model = GB_MODEL_AUTODETECT;
26 override->mbc = GB_MBC_AUTODETECT;
27 memset(override->gbColors, 0, sizeof(override->gbColors));
28 bool found = false;
29
30 int i;
31 for (i = 0; _overrides[i].headerCrc32; ++i) {
32 if (override->headerCrc32 == _overrides[i].headerCrc32) {
33 *override = _overrides[i];
34 found = true;
35 break;
36 }
37 }
38
39 if (config) {
40 char sectionName[24] = "";
41 snprintf(sectionName, sizeof(sectionName), "gb.override.%08X", override->headerCrc32);
42 const char* model = ConfigurationGetValue(config, sectionName, "model");
43 const char* mbc = ConfigurationGetValue(config, sectionName, "mbc");
44 const char* pal[12] = {
45 ConfigurationGetValue(config, sectionName, "pal[0]"),
46 ConfigurationGetValue(config, sectionName, "pal[1]"),
47 ConfigurationGetValue(config, sectionName, "pal[2]"),
48 ConfigurationGetValue(config, sectionName, "pal[3]"),
49 ConfigurationGetValue(config, sectionName, "pal[4]"),
50 ConfigurationGetValue(config, sectionName, "pal[5]"),
51 ConfigurationGetValue(config, sectionName, "pal[6]"),
52 ConfigurationGetValue(config, sectionName, "pal[7]"),
53 ConfigurationGetValue(config, sectionName, "pal[8]"),
54 ConfigurationGetValue(config, sectionName, "pal[9]"),
55 ConfigurationGetValue(config, sectionName, "pal[10]"),
56 ConfigurationGetValue(config, sectionName, "pal[11]")
57 };
58
59 if (model) {
60 override->model = GBNameToModel(model);
61 found = override->model != GB_MODEL_AUTODETECT;
62 }
63
64 if (mbc) {
65 char* end;
66 long type = strtoul(mbc, &end, 0);
67 if (end && !*end) {
68 override->mbc = type;
69 found = true;
70 }
71 }
72
73 for (i = 0; i < 12; ++i) {
74 if (!pal[i]) {
75 continue;
76 }
77 char* end;
78 unsigned long value = strtoul(pal[i], &end, 10);
79 if (end == &pal[i][1] && *end == 'x') {
80 value = strtoul(pal[i], &end, 16);
81 }
82 if (*end) {
83 continue;
84 }
85 value |= 0xFF000000;
86 override->gbColors[i] = value;
87 if (i < 8) {
88 override->gbColors[i + 4] = value;
89 }
90 if (i < 4) {
91 override->gbColors[i + 8] = value;
92 }
93 }
94 }
95 return found;
96}
97
98void GBOverrideSave(struct Configuration* config, const struct GBCartridgeOverride* override) {
99 char sectionName[24] = "";
100 snprintf(sectionName, sizeof(sectionName), "gb.override.%08X", override->headerCrc32);
101 const char* model = GBModelToName(override->model);
102 ConfigurationSetValue(config, sectionName, "model", model);
103
104 if (override->gbColors[0] & 0xFF000000) {
105 ConfigurationSetIntValue(config, sectionName, "pal[0]", override->gbColors[0] & ~0xFF000000);
106 }
107 if (override->gbColors[1] & 0xFF000000) {
108 ConfigurationSetIntValue(config, sectionName, "pal[1]", override->gbColors[1] & ~0xFF000000);
109 }
110 if (override->gbColors[2] & 0xFF000000) {
111 ConfigurationSetIntValue(config, sectionName, "pal[2]", override->gbColors[2] & ~0xFF000000);
112 }
113 if (override->gbColors[3] & 0xFF000000) {
114 ConfigurationSetIntValue(config, sectionName, "pal[3]", override->gbColors[3] & ~0xFF000000);
115 }
116 if (override->gbColors[4] & 0xFF000000) {
117 ConfigurationSetIntValue(config, sectionName, "pal[4]", override->gbColors[4] & ~0xFF000000);
118 }
119 if (override->gbColors[5] & 0xFF000000) {
120 ConfigurationSetIntValue(config, sectionName, "pal[5]", override->gbColors[5] & ~0xFF000000);
121 }
122 if (override->gbColors[6] & 0xFF000000) {
123 ConfigurationSetIntValue(config, sectionName, "pal[6]", override->gbColors[6] & ~0xFF000000);
124 }
125 if (override->gbColors[7] & 0xFF000000) {
126 ConfigurationSetIntValue(config, sectionName, "pal[7]", override->gbColors[7] & ~0xFF000000);
127 }
128 if (override->gbColors[8] & 0xFF000000) {
129 ConfigurationSetIntValue(config, sectionName, "pal[8]", override->gbColors[8] & ~0xFF000000);
130 }
131 if (override->gbColors[9] & 0xFF000000) {
132 ConfigurationSetIntValue(config, sectionName, "pal[9]", override->gbColors[9] & ~0xFF000000);
133 }
134 if (override->gbColors[10] & 0xFF000000) {
135 ConfigurationSetIntValue(config, sectionName, "pal[10]", override->gbColors[10] & ~0xFF000000);
136 }
137 if (override->gbColors[11] & 0xFF000000) {
138 ConfigurationSetIntValue(config, sectionName, "pal[11]", override->gbColors[11] & ~0xFF000000);
139 }
140
141 if (override->mbc != GB_MBC_AUTODETECT) {
142 ConfigurationSetIntValue(config, sectionName, "mbc", override->mbc);
143 } else {
144 ConfigurationClearValue(config, sectionName, "mbc");
145 }
146}
147
148void GBOverrideApply(struct GB* gb, const struct GBCartridgeOverride* override) {
149 if (override->model != GB_MODEL_AUTODETECT) {
150 gb->model = override->model;
151 }
152
153 if (override->mbc != GB_MBC_AUTODETECT) {
154 gb->memory.mbcType = override->mbc;
155 GBMBCInit(gb);
156 }
157
158 int i;
159 for (i = 0; i < 12; ++i) {
160 if (!(override->gbColors[i] & 0xFF000000)) {
161 continue;
162 }
163 GBVideoSetPalette(&gb->video, i, override->gbColors[i]);
164 if (i < 8) {
165 GBVideoSetPalette(&gb->video, i + 4, override->gbColors[i]);
166 }
167 if (i < 4) {
168 GBVideoSetPalette(&gb->video, i + 8, override->gbColors[i]);
169 }
170 }
171}
172
173void GBOverrideApplyDefaults(struct GB* gb) {
174 struct GBCartridgeOverride override;
175 override.headerCrc32 = doCrc32(&gb->memory.rom[0x100], sizeof(struct GBCartridge));
176 if (GBOverrideFind(0, &override)) {
177 GBOverrideApply(gb, &override);
178 }
179}