all repos — mgba @ be021605bc04cf61712cdc36bb77cd854d281350

mGBA Game Boy Advance Emulator

src/gba.c (view raw)

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