src/gba.c (view raw)
1#include "gba.h"
2
3#include "debugger.h"
4
5#include <stdarg.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <sys/mman.h>
10#include <unistd.h>
11
12static const char* GBA_CANNOT_MMAP = "Could not map memory";
13
14static int32_t GBALoad32(struct ARMMemory* memory, uint32_t address);
15static int16_t GBALoad16(struct ARMMemory* memory, uint32_t address);
16static uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address);
17static int8_t GBALoad8(struct ARMMemory* memory, uint32_t address);
18static uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address);
19
20static void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value);
21static void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value);
22static void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value);
23
24static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region);
25static void GBAHitStub(struct ARMBoard* board, uint32_t opcode);
26
27static void _GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value);
28
29void GBAInit(struct GBA* gba) {
30 gba->errno = GBA_NO_ERROR;
31 gba->errstr = 0;
32
33 ARMInit(&gba->cpu);
34
35 gba->memory.p = gba;
36 GBAMemoryInit(&gba->memory);
37 ARMAssociateMemory(&gba->cpu, &gba->memory.d);
38
39 gba->board.p = gba;
40 GBABoardInit(&gba->board);
41 ARMAssociateBoard(&gba->cpu, &gba->board.d);
42
43 ARMReset(&gba->cpu);
44}
45
46void GBADeinit(struct GBA* gba) {
47 GBAMemoryDeinit(&gba->memory);
48}
49
50void GBAMemoryInit(struct GBAMemory* memory) {
51 memory->d.load32 = GBALoad32;
52 memory->d.load16 = GBALoad16;
53 memory->d.loadU16 = GBALoadU16;
54 memory->d.load8 = GBALoad8;
55 memory->d.loadU8 = GBALoadU8;
56 memory->d.store32 = GBAStore32;
57 memory->d.store16 = GBAStore16;
58 memory->d.store8 = GBAStore8;
59
60 memory->bios = 0;
61 memory->wram = mmap(0, SIZE_WORKING_RAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
62 memory->iwram = mmap(0, SIZE_WORKING_IRAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
63 memory->rom = 0;
64 memset(memory->io, 0, sizeof(memory->io));
65
66 if (!memory->wram || !memory->iwram) {
67 GBAMemoryDeinit(memory);
68 memory->p->errno = GBA_OUT_OF_MEMORY;
69 memory->p->errstr = GBA_CANNOT_MMAP;
70 }
71
72 memory->d.activeRegion = 0;
73 memory->d.activeMask = 0;
74 memory->d.setActiveRegion = GBASetActiveRegion;
75}
76
77void GBAMemoryDeinit(struct GBAMemory* memory) {
78 munmap(memory->wram, SIZE_WORKING_RAM);
79 munmap(memory->iwram, SIZE_WORKING_IRAM);
80}
81
82void GBABoardInit(struct GBABoard* board) {
83 board->d.reset = GBABoardReset;
84 board->d.hitStub = GBAHitStub;
85}
86
87void GBABoardReset(struct ARMBoard* board) {
88 struct ARMCore* cpu = board->cpu;
89 ARMSetPrivilegeMode(cpu, MODE_IRQ);
90 cpu->gprs[ARM_SP] = SP_BASE_IRQ;
91 ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
92 cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
93 ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
94 cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
95}
96
97void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) {
98 ARMDebuggerInit(debugger, &gba->cpu);
99 gba->debugger = debugger;
100}
101
102void GBALoadROM(struct GBA* gba, int fd) {
103 gba->memory.rom = mmap(0, SIZE_CART0, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);
104 // TODO: error check
105}
106
107static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) {
108 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
109
110 switch (address & ~OFFSET_MASK) {
111 case BASE_BIOS:
112 memory->activeRegion = gbaMemory->bios;
113 memory->activeMask = 0;
114 break;
115 case BASE_WORKING_RAM:
116 memory->activeRegion = gbaMemory->wram;
117 memory->activeMask = SIZE_WORKING_RAM - 1;
118 break;
119 case BASE_WORKING_IRAM:
120 memory->activeRegion = gbaMemory->iwram;
121 memory->activeMask = SIZE_WORKING_IRAM - 1;
122 break;
123 case BASE_CART0:
124 case BASE_CART0_EX:
125 case BASE_CART1:
126 case BASE_CART1_EX:
127 case BASE_CART2:
128 case BASE_CART2_EX:
129 memory->activeRegion = gbaMemory->rom;
130 memory->activeMask = SIZE_CART0 - 1;
131 break;
132 default:
133 memory->activeRegion = 0;
134 memory->activeMask = 0;
135 break;
136 }
137}
138
139int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) {
140 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
141
142 switch (address & ~OFFSET_MASK) {
143 case BASE_BIOS:
144 break;
145 case BASE_WORKING_RAM:
146 return gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2];
147 case BASE_WORKING_IRAM:
148 return gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2];
149 case BASE_IO:
150 break;
151 case BASE_PALETTE_RAM:
152 break;
153 case BASE_VRAM:
154 break;
155 case BASE_OAM:
156 break;
157 case BASE_CART0:
158 case BASE_CART0_EX:
159 case BASE_CART1:
160 case BASE_CART1_EX:
161 case BASE_CART2:
162 case BASE_CART2_EX:
163 return gbaMemory->rom[(address & (SIZE_CART0 - 1)) >> 2];
164 case BASE_CART_SRAM:
165 break;
166 default:
167 break;
168 }
169
170 return 0;
171}
172
173int16_t GBALoad16(struct ARMMemory* memory, uint32_t address) {
174 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
175
176 switch (address & ~OFFSET_MASK) {
177 case BASE_BIOS:
178 break;
179 case BASE_WORKING_RAM:
180 return ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1];
181 case BASE_WORKING_IRAM:
182 return ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1];
183 case BASE_IO:
184 break;
185 case BASE_PALETTE_RAM:
186 break;
187 case BASE_VRAM:
188 break;
189 case BASE_OAM:
190 break;
191 case BASE_CART0:
192 case BASE_CART0_EX:
193 case BASE_CART1:
194 case BASE_CART1_EX:
195 case BASE_CART2:
196 case BASE_CART2_EX:
197 return ((int16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1];
198 case BASE_CART_SRAM:
199 break;
200 default:
201 break;
202 }
203
204 return 0;
205}
206
207uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address) {
208 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
209
210 switch (address & ~OFFSET_MASK) {
211 case BASE_BIOS:
212 break;
213 case BASE_WORKING_RAM:
214 return ((uint16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1];
215 case BASE_WORKING_IRAM:
216 return ((uint16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1];
217 case BASE_IO:
218 break;
219 case BASE_PALETTE_RAM:
220 break;
221 case BASE_VRAM:
222 break;
223 case BASE_OAM:
224 break;
225 case BASE_CART0:
226 case BASE_CART0_EX:
227 case BASE_CART1:
228 case BASE_CART1_EX:
229 case BASE_CART2:
230 case BASE_CART2_EX:
231 return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1];
232 case BASE_CART_SRAM:
233 break;
234 default:
235 break;
236 }
237
238 return 0;
239}
240
241int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) {
242 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
243
244 switch (address & ~OFFSET_MASK) {
245 case BASE_BIOS:
246 break;
247 case BASE_WORKING_RAM:
248 return ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
249 case BASE_WORKING_IRAM:
250 return ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
251 case BASE_IO:
252 break;
253 case BASE_PALETTE_RAM:
254 break;
255 case BASE_VRAM:
256 break;
257 case BASE_OAM:
258 break;
259 case BASE_CART0:
260 case BASE_CART0_EX:
261 case BASE_CART1:
262 case BASE_CART1_EX:
263 case BASE_CART2:
264 case BASE_CART2_EX:
265 return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
266 case BASE_CART_SRAM:
267 break;
268 default:
269 break;
270 }
271
272 return 0;
273}
274
275uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address) {
276 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
277
278 switch (address & ~OFFSET_MASK) {
279 case BASE_BIOS:
280 break;
281 case BASE_WORKING_RAM:
282 return ((uint8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
283 break;
284 case BASE_WORKING_IRAM:
285 return ((uint8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
286 break;
287 case BASE_IO:
288 break;
289 case BASE_PALETTE_RAM:
290 break;
291 case BASE_VRAM:
292 break;
293 case BASE_OAM:
294 break;
295 case BASE_CART0:
296 case BASE_CART0_EX:
297 case BASE_CART1:
298 case BASE_CART1_EX:
299 case BASE_CART2:
300 case BASE_CART2_EX:
301 return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
302 case BASE_CART_SRAM:
303 break;
304 default:
305 break;
306 }
307
308 return 0;
309}
310
311void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) {
312 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
313
314 switch (address & ~OFFSET_MASK) {
315 case BASE_WORKING_RAM:
316 gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2] = value;
317 break;
318 case BASE_WORKING_IRAM:
319 gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2] = value;
320 break;
321 case BASE_IO:
322 break;
323 case BASE_PALETTE_RAM:
324 break;
325 case BASE_VRAM:
326 break;
327 case BASE_OAM:
328 break;
329 case BASE_CART0:
330 break;
331 case BASE_CART2_EX:
332 break;
333 case BASE_CART_SRAM:
334 break;
335 default:
336 break;
337 }
338}
339
340void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) {
341 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
342
343 switch (address & ~OFFSET_MASK) {
344 case BASE_WORKING_RAM:
345 ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1] = value;
346 break;
347 case BASE_WORKING_IRAM:
348 ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1] = value;
349 break;
350 case BASE_IO:
351 _GBAIOWrite(gbaMemory->p, address & (SIZE_IO - 1), value);
352 break;
353 case BASE_PALETTE_RAM:
354 break;
355 case BASE_VRAM:
356 break;
357 case BASE_OAM:
358 break;
359 case BASE_CART0:
360 break;
361 case BASE_CART2_EX:
362 break;
363 case BASE_CART_SRAM:
364 break;
365 default:
366 break;
367 }
368}
369
370void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) {
371 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
372
373 switch (address & ~OFFSET_MASK) {
374 case BASE_WORKING_RAM:
375 ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
376 break;
377 case BASE_WORKING_IRAM:
378 ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
379 break;
380 case BASE_IO:
381 break;
382 case BASE_PALETTE_RAM:
383 break;
384 case BASE_VRAM:
385 break;
386 case BASE_OAM:
387 break;
388 case BASE_CART0:
389 break;
390 case BASE_CART2_EX:
391 break;
392 case BASE_CART_SRAM:
393 break;
394 default:
395 break;
396 }
397}
398
399void GBALog(int level, const char* format, ...) {
400 va_list args;
401 va_start(args, format);
402 vprintf(format, args);
403 va_end(args);
404 printf("\n");
405}
406
407void GBAHitStub(struct ARMBoard* board, uint32_t opcode) {
408 GBALog(GBA_LOG_STUB, "Stub opcode: %08x", opcode);
409 struct GBABoard* gbaBoard = (struct GBABoard*) board;
410 if (!gbaBoard->p->debugger) {
411 abort();
412 } else {
413 ARMDebuggerEnter(gbaBoard->p->debugger);
414 }
415}
416
417static void _GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
418 switch (address) {
419 default:
420 GBALog(GBA_LOG_STUB, "Stub I/O register: %03x", address);
421 break;
422 }
423}