all repos — mgba @ 1d445958c97d8578dab30972e450f62f84857a2c

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