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}