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