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