all repos — mgba @ 7c906e855866d015ae23c35c35066d6838ecec21

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