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