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 Gold Spaceworld 1997 demo
16 { 0x232a067d, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } },
17
18 { 0, 0, 0, { 0 } }
19};
20
21bool GBOverrideFind(const struct Configuration* config, struct GBCartridgeOverride* override) {
22 override->model = GB_MODEL_AUTODETECT;
23 override->mbc = GB_MBC_AUTODETECT;
24 bool found = false;
25
26 int i;
27 for (i = 0; _overrides[i].headerCrc32; ++i) {
28 if (override->headerCrc32 == _overrides[i].headerCrc32) {
29 *override = _overrides[i];
30 found = true;
31 break;
32 }
33 }
34
35 if (config) {
36 char sectionName[24] = "";
37 snprintf(sectionName, sizeof(sectionName), "gb.override.%08X", override->headerCrc32);
38 const char* model = ConfigurationGetValue(config, sectionName, "model");
39 const char* mbc = ConfigurationGetValue(config, sectionName, "mbc");
40 const char* pal[4] = {
41 ConfigurationGetValue(config, sectionName, "pal[0]"),
42 ConfigurationGetValue(config, sectionName, "pal[1]"),
43 ConfigurationGetValue(config, sectionName, "pal[2]"),
44 ConfigurationGetValue(config, sectionName, "pal[3]")
45 };
46
47 if (model) {
48 if (strcasecmp(model, "DMG") == 0) {
49 found = true;
50 override->model = GB_MODEL_DMG;
51 } else if (strcasecmp(model, "CGB") == 0) {
52 found = true;
53 override->model = GB_MODEL_CGB;
54 } else if (strcasecmp(model, "AGB") == 0) {
55 found = true;
56 override->model = GB_MODEL_AGB;
57 } else if (strcasecmp(model, "SGB") == 0) {
58 found = true;
59 override->model = GB_MODEL_DMG; // TODO
60 } else if (strcasecmp(model, "MGB") == 0) {
61 found = true;
62 override->model = GB_MODEL_DMG; // TODO
63 }
64 }
65
66 if (mbc) {
67 char* end;
68 long type = strtoul(mbc, &end, 0);
69 if (end && !*end) {
70 override->mbc = type;
71 found = true;
72 }
73 }
74
75 if (pal[0] && pal[1] && pal[2] && pal[3]) {
76 int i;
77 for (i = 0; i < 4; ++i) {
78 char* end;
79 unsigned long value = strtoul(pal[i], &end, 10);
80 if (end == &pal[i][1] && *end == 'x') {
81 value = strtoul(pal[i], &end, 16);
82 }
83 if (*end) {
84 continue;
85 }
86 override->gbColors[i] = 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 = 0;
97 switch (override->model) {
98 case GB_MODEL_DMG:
99 model = "DMG";
100 break;
101 case GB_MODEL_SGB:
102 model = "SGB";
103 break;
104 case GB_MODEL_CGB:
105 model = "CGB";
106 break;
107 case GB_MODEL_AGB:
108 model = "AGB";
109 break;
110 case GB_MODEL_AUTODETECT:
111 break;
112 }
113 ConfigurationSetValue(config, sectionName, "model", model);
114
115 if (override->gbColors[0] | override->gbColors[1] | override->gbColors[2] | override->gbColors[3]) {
116 ConfigurationSetIntValue(config, sectionName, "pal[0]", override->gbColors[0]);
117 ConfigurationSetIntValue(config, sectionName, "pal[1]", override->gbColors[1]);
118 ConfigurationSetIntValue(config, sectionName, "pal[2]", override->gbColors[2]);
119 ConfigurationSetIntValue(config, sectionName, "pal[3]", override->gbColors[3]);
120 }
121 if (override->mbc != GB_MBC_AUTODETECT) {
122 ConfigurationSetIntValue(config, sectionName, "mbc", override->mbc);
123 } else {
124 ConfigurationClearValue(config, sectionName, "mbc");
125 }
126}
127
128void GBOverrideApply(struct GB* gb, const struct GBCartridgeOverride* override) {
129 if (override->model != GB_MODEL_AUTODETECT) {
130 gb->model = override->model;
131 }
132
133 if (override->mbc != GB_MBC_AUTODETECT) {
134 gb->memory.mbcType = override->mbc;
135 GBMBCInit(gb);
136 }
137
138 if (override->gbColors[0] | override->gbColors[1] | override->gbColors[2] | override->gbColors[3]) {
139 GBVideoSetPalette(&gb->video, 0, override->gbColors[0]);
140 GBVideoSetPalette(&gb->video, 1, override->gbColors[1]);
141 GBVideoSetPalette(&gb->video, 2, override->gbColors[2]);
142 GBVideoSetPalette(&gb->video, 3, override->gbColors[3]);
143 }
144}
145
146void GBOverrideApplyDefaults(struct GB* gb) {
147 struct GBCartridgeOverride override;
148 override.headerCrc32 = doCrc32(&gb->memory.rom[0x100], sizeof(struct GBCartridge));
149 if (GBOverrideFind(0, &override)) {
150 GBOverrideApply(gb, &override);
151 }
152}