all repos — mgba @ 70eb3634a060debee6b9f89044ed2ca42b26253b

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