all repos — mgba @ c14da05d8dca225010677643c32fea5c0ac8517a

mGBA Game Boy Advance Emulator

src/gba/context/context.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 "gba/context/context.h"
  7
  8#include "gba/context/overrides.h"
  9
 10#include "util/memory.h"
 11#include "util/vfs.h"
 12
 13bool GBAContextInit(struct GBAContext* context, const char* port) {
 14	context->gba = anonymousMemoryMap(sizeof(struct GBA));
 15	context->cpu = anonymousMemoryMap(sizeof(struct ARMCore));
 16	context->rom = 0;
 17	context->fname = 0;
 18	context->save = 0;
 19	context->renderer = 0;
 20	memset(context->components, 0, sizeof(context->components));
 21
 22	if (!context->gba || !context->cpu) {
 23		if (context->gba) {
 24			mappedMemoryFree(context->gba, sizeof(struct GBA));
 25		}
 26		if (context->cpu) {
 27			mappedMemoryFree(context->cpu, sizeof(struct ARMCore));
 28		}
 29		return false;
 30	}
 31
 32	GBAConfigInit(&context->config, port);
 33	if (port) {
 34		GBAConfigLoad(&context->config);
 35	}
 36
 37	GBACreate(context->gba);
 38	ARMSetComponents(context->cpu, &context->gba->d, 0, context->components);
 39	ARMInit(context->cpu);
 40
 41	context->gba->sync = 0;
 42	return true;
 43}
 44
 45void GBAContextDeinit(struct GBAContext* context) {
 46	ARMDeinit(context->cpu);
 47	GBADestroy(context->gba);
 48	mappedMemoryFree(context->gba, 0);
 49	mappedMemoryFree(context->cpu, 0);
 50	GBAConfigDeinit(&context->config);
 51}
 52
 53bool GBAContextLoadROM(struct GBAContext* context, const char* path, bool autoloadSave) {
 54	context->rom = VFileOpen(path, O_RDONLY);
 55	if (!context->rom) {
 56		return false;
 57	}
 58
 59	if (!GBAIsROM(context->rom)) {
 60		context->rom->close(context->rom);
 61		context->rom = 0;
 62		return false;
 63	}
 64
 65	context->fname = path;
 66	if (autoloadSave) {
 67		context->save = VDirOptionalOpenFile(0, path, 0, ".sav", O_RDWR | O_CREAT);
 68	}
 69	return true;
 70}
 71
 72void GBAContextUnloadROM(struct GBAContext* context) {
 73	GBAUnloadROM(context->gba);
 74	if (context->bios) {
 75		context->bios->close(context->bios);
 76		context->bios = 0;
 77	}
 78	if (context->rom) {
 79		context->rom->close(context->rom);
 80		context->rom = 0;
 81	}
 82	if (context->save) {
 83		context->save->close(context->save);
 84		context->save = 0;
 85	}
 86}
 87
 88bool GBAContextLoadROMFromVFile(struct GBAContext* context, struct VFile* rom, struct VFile* save) {
 89	context->rom = rom;
 90	if (!GBAIsROM(context->rom)) {
 91		context->rom = 0;
 92		return false;
 93	}
 94	context->save = save;
 95	return true;
 96}
 97
 98bool GBAContextLoadBIOS(struct GBAContext* context, const char* path) {
 99	context->bios = VFileOpen(path, O_RDONLY);
100	if (!context->bios) {
101		return false;
102	}
103
104	if (!GBAIsBIOS(context->bios)) {
105		context->bios->close(context->bios);
106		context->bios = 0;
107		return false;
108	}
109	return true;
110}
111
112bool GBAContextLoadBIOSFromVFile(struct GBAContext* context, struct VFile* bios) {
113	context->bios = bios;
114	if (!GBAIsBIOS(context->bios)) {
115		context->bios = 0;
116		return false;
117	}
118	return true;
119}
120
121bool GBAContextStart(struct GBAContext* context) {
122	struct GBAOptions opts = { .bios = 0 };
123
124	if (context->renderer) {
125		GBAVideoAssociateRenderer(&context->gba->video, context->renderer);
126	}
127
128	if (!GBALoadROM(context->gba, context->rom, context->save, context->fname)) {
129		return false;
130	}
131
132	GBAConfigMap(&context->config, &opts);
133	if (opts.useBios && context->bios) {
134		GBALoadBIOS(context->gba, context->bios);
135	}
136	context->gba->logLevel = opts.logLevel;
137	context->gba->idleOptimization = opts.idleOptimization;
138
139	ARMReset(context->cpu);
140
141	if (opts.skipBios) {
142		GBASkipBIOS(context->cpu);
143	}
144
145	struct GBACartridgeOverride override;
146	const struct GBACartridge* cart = (const struct GBACartridge*) context->gba->memory.rom;
147	memcpy(override.id, &cart->id, sizeof(override.id));
148	if (GBAOverrideFind(GBAConfigGetOverrides(&context->config), &override)) {
149		GBAOverrideApply(context->gba, &override);
150	}
151	GBAConfigFreeOpts(&opts);
152	return true;
153}
154
155void GBAContextStop(struct GBAContext* context) {
156	UNUSED(context);
157	// TODO?
158}
159
160void GBAContextFrame(struct GBAContext* context, uint16_t keys) {
161	int activeKeys = keys;
162	context->gba->keySource = &activeKeys;
163
164	int frameCounter = context->gba->video.frameCounter;
165	while (frameCounter == context->gba->video.frameCounter) {
166		ARMRunLoop(context->cpu);
167	}
168}