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}