all repos — mgba @ 9a11b1459eb5d8ad9a7135b50471f16533081837

mGBA Game Boy Advance Emulator

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}