all repos — mgba @ 201d34a4d7580f1d2ab1cd357580c365324fb04c

mGBA Game Boy Advance Emulator

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}