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}