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