all repos — mgba @ 7a1a0f5165155adea72de253fe858061ac969892

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 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}