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}