src/gba/gba-memory.c (view raw)
1#include "gba-memory.h"
2
3#include "gba-gpio.h"
4#include "gba-io.h"
5#include "gba-serialize.h"
6#include "hle-bios.h"
7#include "memory.h"
8
9#include <limits.h>
10#include <stdlib.h>
11#include <string.h>
12
13static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region);
14static int GBAWaitMultiple(struct ARMMemory* memory, uint32_t startAddress, int count);
15static void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* info);
16
17static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
18static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 7, 7, 9, 9, 13, 13, 9 };
19static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 };
20static const char GBA_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 5, 5, 9, 9, 17, 17, 9 };
21static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
22static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
23static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
24
25void GBAMemoryInit(struct GBAMemory* memory) {
26 memory->d.load32 = GBALoad32;
27 memory->d.load16 = GBALoad16;
28 memory->d.loadU16 = GBALoadU16;
29 memory->d.load8 = GBALoad8;
30 memory->d.loadU8 = GBALoadU8;
31 memory->d.store32 = GBAStore32;
32 memory->d.store16 = GBAStore16;
33 memory->d.store8 = GBAStore8;
34
35 memory->bios = (uint32_t*) hleBios;
36 memory->fullBios = 0;
37 memory->wram = anonymousMemoryMap(SIZE_WORKING_RAM);
38 memory->iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
39 memory->rom = 0;
40 memory->gpio.p = memory->p;
41 memset(memory->io, 0, sizeof(memory->io));
42 memset(memory->dma, 0, sizeof(memory->dma));
43 int i;
44 for (i = 0; i < 4; ++i) {
45 memory->dma[i].count = 0x10000;
46 memory->dma[i].nextEvent = INT_MAX;
47 }
48 memory->activeDMA = -1;
49 memory->nextDMA = INT_MAX;
50
51 if (!memory->wram || !memory->iwram) {
52 GBAMemoryDeinit(memory);
53 GBALog(memory->p, GBA_LOG_FATAL, "Could not map memory");
54 return;
55 }
56
57 for (i = 0; i < 16; ++i) {
58 memory->waitstates16[i] = GBA_BASE_WAITSTATES[i];
59 memory->waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
60 memory->waitstatesPrefetch16[i] = GBA_BASE_WAITSTATES_SEQ[i];
61 memory->waitstates32[i] = GBA_BASE_WAITSTATES_32[i];
62 memory->waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
63 memory->waitstatesPrefetch32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
64 }
65 for (; i < 256; ++i) {
66 memory->waitstates16[i] = 0;
67 memory->waitstatesSeq16[i] = 0;
68 memory->waitstatesPrefetch16[i] = 0;
69 memory->waitstates32[i] = 0;
70 memory->waitstatesSeq32[i] = 0;
71 memory->waitstatesPrefetch32[i] = 0;
72 }
73
74 memory->activeRegion = -1;
75 memory->d.activeRegion = 0;
76 memory->d.activeMask = 0;
77 memory->d.setActiveRegion = GBASetActiveRegion;
78 memory->d.activePrefetchCycles32 = 0;
79 memory->d.activePrefetchCycles16 = 0;
80 memory->biosPrefetch = 0;
81 memory->d.waitMultiple = GBAWaitMultiple;
82}
83
84void GBAMemoryDeinit(struct GBAMemory* memory) {
85 mappedMemoryFree(memory->wram, SIZE_WORKING_RAM);
86 mappedMemoryFree(memory->iwram, SIZE_WORKING_IRAM);
87 GBASavedataDeinit(&memory->savedata);
88}
89
90static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) {
91 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
92
93 int newRegion = address >> BASE_OFFSET;
94 if (newRegion == gbaMemory->activeRegion) {
95 return;
96 }
97 if (gbaMemory->activeRegion == REGION_BIOS) {
98 gbaMemory->biosPrefetch = memory->load32(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_ARM * 2, 0);
99 }
100 gbaMemory->activeRegion = newRegion;
101 memory->activePrefetchCycles32 = gbaMemory->waitstatesPrefetch32[gbaMemory->activeRegion];
102 memory->activePrefetchCycles16 = gbaMemory->waitstatesPrefetch16[gbaMemory->activeRegion];
103 memory->activeNonseqCycles32 = gbaMemory->waitstates32[gbaMemory->activeRegion];
104 memory->activeNonseqCycles16 = gbaMemory->waitstates16[gbaMemory->activeRegion];
105 switch (address & ~OFFSET_MASK) {
106 case BASE_BIOS:
107 memory->activeRegion = gbaMemory->bios;
108 memory->activeMask = SIZE_BIOS - 1;
109 break;
110 case BASE_WORKING_RAM:
111 memory->activeRegion = gbaMemory->wram;
112 memory->activeMask = SIZE_WORKING_RAM - 1;
113 break;
114 case BASE_WORKING_IRAM:
115 memory->activeRegion = gbaMemory->iwram;
116 memory->activeMask = SIZE_WORKING_IRAM - 1;
117 break;
118 case BASE_CART0:
119 case BASE_CART0_EX:
120 case BASE_CART1:
121 case BASE_CART1_EX:
122 case BASE_CART2:
123 case BASE_CART2_EX:
124 memory->activeRegion = gbaMemory->rom;
125 memory->activeMask = SIZE_CART0 - 1;
126 break;
127 default:
128 memory->activeRegion = 0;
129 memory->activeMask = 0;
130 GBALog(gbaMemory->p, GBA_LOG_FATAL, "Jumped to invalid address");
131 break;
132 }
133}
134
135int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
136 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
137 uint32_t value = 0;
138 int wait = 0;
139
140 switch (address & ~OFFSET_MASK) {
141 case BASE_BIOS:
142 if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) {
143 if (address < SIZE_BIOS) {
144 LOAD_32(value, address, gbaMemory->bios);
145 } else {
146 value = 0;
147 }
148 } else {
149 value = gbaMemory->biosPrefetch;
150 }
151 break;
152 case BASE_WORKING_RAM:
153 LOAD_32(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
154 wait = gbaMemory->waitstates32[REGION_WORKING_RAM];
155 break;
156 case BASE_WORKING_IRAM:
157 LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
158 break;
159 case BASE_IO:
160 value = GBAIORead(gbaMemory->p, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gbaMemory->p, (address & (SIZE_IO - 1)) | 2) << 16);
161 break;
162 case BASE_PALETTE_RAM:
163 LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
164 break;
165 case BASE_VRAM:
166 LOAD_32(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
167 break;
168 case BASE_OAM:
169 LOAD_32(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
170 break;
171 case BASE_CART0:
172 case BASE_CART0_EX:
173 case BASE_CART1:
174 case BASE_CART1_EX:
175 case BASE_CART2:
176 case BASE_CART2_EX:
177 wait = gbaMemory->waitstates32[address >> BASE_OFFSET];
178 if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
179 LOAD_32(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
180 }
181 break;
182 case BASE_CART_SRAM:
183 case BASE_CART_SRAM_MIRROR:
184 GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address);
185 break;
186 default:
187 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address);
188 if (gbaMemory->p->cpu.executionMode == MODE_ARM) {
189 value = memory->load32(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_ARM * 2, 0);
190 } else {
191 value = memory->load16(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_THUMB * 2, 0);
192 value |= value << 16;
193 }
194 break;
195 }
196
197
198 if (cycleCounter) {
199 *cycleCounter += 2 + wait;
200 }
201 // Unaligned 32-bit loads are "rotated" so they make some semblance of sense
202 int rotate = (address & 3) << 3;
203 return (value >> rotate) | (value << (32 - rotate));
204}
205
206uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
207 return GBALoad16(memory, address, cycleCounter);
208}
209
210int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
211 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
212 uint16_t value = 0;
213 int wait = 0;
214
215 switch (address & ~OFFSET_MASK) {
216 case BASE_BIOS:
217 if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) {
218 if (address < SIZE_BIOS) {
219 LOAD_16(value, address, gbaMemory->bios);
220 } else {
221 value = 0;
222 }
223 } else {
224 value = gbaMemory->biosPrefetch;
225 }
226 break;
227 case BASE_WORKING_RAM:
228 LOAD_16(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
229 wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
230 break;
231 case BASE_WORKING_IRAM:
232 LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
233 break;
234 case BASE_IO:
235 value = GBAIORead(gbaMemory->p, address & (SIZE_IO - 1));
236 break;
237 case BASE_PALETTE_RAM:
238 LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
239 break;
240 case BASE_VRAM:
241 LOAD_16(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
242 break;
243 case BASE_OAM:
244 LOAD_16(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
245 break;
246 case BASE_CART0:
247 case BASE_CART0_EX:
248 case BASE_CART1:
249 case BASE_CART1_EX:
250 case BASE_CART2:
251 wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
252 if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
253 LOAD_16(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
254 }
255 break;
256 case BASE_CART2_EX:
257 wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
258 if (gbaMemory->savedata.type == SAVEDATA_EEPROM) {
259 value = GBASavedataReadEEPROM(&gbaMemory->savedata);
260 } else if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
261 LOAD_16(value, address & (SIZE_CART0 - 1), gbaMemory->rom);
262 }
263 break;
264 case BASE_CART_SRAM:
265 case BASE_CART_SRAM_MIRROR:
266 GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Load16: 0x%08X", address);
267 break;
268 default:
269 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
270 value = memory->load16(memory, gbaMemory->p->cpu.currentPC + (gbaMemory->p->cpu.executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0);
271 break;
272 }
273
274 if (cycleCounter) {
275 *cycleCounter += 2 + wait;
276 }
277 // Unaligned 16-bit loads are "unpredictable", but the GBA rotates them, so we have to, too.
278 int rotate = (address & 1) << 3;
279 return (value >> rotate) | (value << (16 - rotate));
280}
281
282uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
283 return GBALoad8(memory, address, cycleCounter);
284}
285
286int8_t GBALoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) {
287 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
288 int8_t value = 0;
289 int wait = 0;
290
291 switch (address & ~OFFSET_MASK) {
292 case BASE_BIOS:
293 if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) {
294 if (address < SIZE_BIOS) {
295 value = ((int8_t*) gbaMemory->bios)[address];
296 } else {
297 value = 0;
298 }
299 } else {
300 value = gbaMemory->biosPrefetch;
301 }
302 break;
303 case BASE_WORKING_RAM:
304 value = ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
305 wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
306 break;
307 case BASE_WORKING_IRAM:
308 value = ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
309 break;
310 case BASE_IO:
311 value = (GBAIORead(gbaMemory->p, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
312 break;
313 case BASE_PALETTE_RAM:
314 value = ((int8_t*) gbaMemory->p->video.renderer->palette)[address & (SIZE_PALETTE_RAM - 1)];
315 break;
316 case BASE_VRAM:
317 value = ((int8_t*) gbaMemory->p->video.renderer->vram)[address & 0x0001FFFF];
318 break;
319 case BASE_OAM:
320 GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
321 break;
322 case BASE_CART0:
323 case BASE_CART0_EX:
324 case BASE_CART1:
325 case BASE_CART1_EX:
326 case BASE_CART2:
327 case BASE_CART2_EX:
328 wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
329 if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) {
330 value = ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
331 }
332 break;
333 case BASE_CART_SRAM:
334 case BASE_CART_SRAM_MIRROR:
335 wait = gbaMemory->waitstates16[address >> BASE_OFFSET];
336 if (gbaMemory->savedata.type == SAVEDATA_NONE) {
337 GBASavedataInitSRAM(&gbaMemory->savedata);
338 }
339 if (gbaMemory->savedata.type == SAVEDATA_SRAM) {
340 value = gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)];
341 } else if (gbaMemory->savedata.type == SAVEDATA_FLASH512 || gbaMemory->savedata.type == SAVEDATA_FLASH1M) {
342 value = GBASavedataReadFlash(&gbaMemory->savedata, address);
343 }
344 break;
345 default:
346 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
347 value = memory->load16(memory, gbaMemory->p->cpu.currentPC + (gbaMemory->p->cpu.executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0) >> ((address & 1) << 3);
348 break;
349 }
350
351 if (cycleCounter) {
352 *cycleCounter += 2 + wait;
353 }
354 return value;
355}
356
357void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value, int* cycleCounter) {
358 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
359 int wait = 0;
360
361 switch (address & ~OFFSET_MASK) {
362 case BASE_WORKING_RAM:
363 STORE_32(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
364 wait = gbaMemory->waitstates32[REGION_WORKING_RAM];
365 break;
366 case BASE_WORKING_IRAM:
367 STORE_32(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
368 break;
369 case BASE_IO:
370 GBAIOWrite32(gbaMemory->p, address & (SIZE_IO - 1), value);
371 break;
372 case BASE_PALETTE_RAM:
373 STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
374 gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16);
375 gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
376 break;
377 case BASE_VRAM:
378 if ((address & OFFSET_MASK) < SIZE_VRAM - 2) {
379 STORE_32(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
380 }
381 break;
382 case BASE_OAM:
383 STORE_32(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
384 gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
385 gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
386 break;
387 case BASE_CART0:
388 GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
389 break;
390 case BASE_CART_SRAM:
391 case BASE_CART_SRAM_MIRROR:
392 GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
393 break;
394 default:
395 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
396 break;
397 }
398
399 if (cycleCounter) {
400 *cycleCounter += 1 + wait;
401 }
402}
403
404void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value, int* cycleCounter) {
405 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
406 int wait = 0;
407
408 switch (address & ~OFFSET_MASK) {
409 case BASE_WORKING_RAM:
410 STORE_16(value, address & (SIZE_WORKING_RAM - 1), gbaMemory->wram);
411 wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
412 break;
413 case BASE_WORKING_IRAM:
414 STORE_16(value, address & (SIZE_WORKING_IRAM - 1), gbaMemory->iwram);
415 break;
416 case BASE_IO:
417 GBAIOWrite(gbaMemory->p, address & (SIZE_IO - 1), value);
418 break;
419 case BASE_PALETTE_RAM:
420 STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gbaMemory->p->video.palette);
421 gbaMemory->p->video.renderer->writePalette(gbaMemory->p->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
422 break;
423 case BASE_VRAM:
424 if ((address & OFFSET_MASK) < SIZE_VRAM) {
425 STORE_16(value, address & 0x0001FFFF, gbaMemory->p->video.renderer->vram);
426 }
427 break;
428 case BASE_OAM:
429 STORE_16(value, address & (SIZE_OAM - 1), gbaMemory->p->video.oam.raw);
430 gbaMemory->p->video.renderer->writeOAM(gbaMemory->p->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
431 break;
432 case BASE_CART0:
433 if (IS_GPIO_REGISTER(address & 0xFFFFFF)) {
434 uint32_t reg = address & 0xFFFFFF;
435 GBAGPIOWrite(&gbaMemory->gpio, reg, value);
436 } else {
437 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
438 }
439 break;
440 case BASE_CART2_EX:
441 if (gbaMemory->savedata.type == SAVEDATA_NONE) {
442 GBASavedataInitEEPROM(&gbaMemory->savedata);
443 }
444 GBASavedataWriteEEPROM(&gbaMemory->savedata, value, 1);
445 break;
446 case BASE_CART_SRAM:
447 case BASE_CART_SRAM_MIRROR:
448 GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store16: 0x%08X", address);
449 break;
450 default:
451 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Store16: 0x%08X", address);
452 break;
453 }
454
455 if (cycleCounter) {
456 *cycleCounter += 1 + wait;
457 }
458}
459
460void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value, int* cycleCounter) {
461 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
462 int wait = 0;
463
464 switch (address & ~OFFSET_MASK) {
465 case BASE_WORKING_RAM:
466 ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
467 wait = gbaMemory->waitstates16[REGION_WORKING_RAM];
468 break;
469 case BASE_WORKING_IRAM:
470 ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
471 break;
472 case BASE_IO:
473 GBAIOWrite8(gbaMemory->p, address & (SIZE_IO - 1), value);
474 break;
475 case BASE_PALETTE_RAM:
476 GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
477 break;
478 case BASE_VRAM:
479 if (address >= 0x06018000) {
480 // TODO: check BG mode
481 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
482 break;
483 }
484 ((int8_t*) gbaMemory->p->video.renderer->vram)[address & 0x1FFFE] = value;
485 ((int8_t*) gbaMemory->p->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
486 break;
487 case BASE_OAM:
488 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
489 break;
490 case BASE_CART0:
491 GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
492 break;
493 case BASE_CART_SRAM:
494 case BASE_CART_SRAM_MIRROR:
495 if (gbaMemory->savedata.type == SAVEDATA_NONE) {
496 if (address == SAVEDATA_FLASH_BASE) {
497 GBASavedataInitFlash(&gbaMemory->savedata);
498 } else {
499 GBASavedataInitSRAM(&gbaMemory->savedata);
500 }
501 }
502 if (gbaMemory->savedata.type == SAVEDATA_FLASH512 || gbaMemory->savedata.type == SAVEDATA_FLASH1M) {
503 GBASavedataWriteFlash(&gbaMemory->savedata, address, value);
504 } else if (gbaMemory->savedata.type == SAVEDATA_SRAM) {
505 gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
506 }
507 wait = gbaMemory->waitstates16[REGION_CART_SRAM];
508 break;
509 default:
510 GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Store8: 0x%08X", address);
511 break;
512 }
513
514 if (cycleCounter) {
515 *cycleCounter += 1 + wait;
516 }
517}
518
519static int GBAWaitMultiple(struct ARMMemory* memory, uint32_t startAddress, int count) {
520 struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
521 int wait = 1 + gbaMemory->waitstates32[startAddress >> BASE_OFFSET];
522 wait += (1 + gbaMemory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1);
523 return wait;
524}
525
526void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) {
527 int sram = parameters & 0x0003;
528 int ws0 = (parameters & 0x000C) >> 2;
529 int ws0seq = (parameters & 0x0010) >> 4;
530 int ws1 = (parameters & 0x0060) >> 5;
531 int ws1seq = (parameters & 0x0080) >> 7;
532 int ws2 = (parameters & 0x0300) >> 8;
533 int ws2seq = (parameters & 0x0400) >> 10;
534 int prefetch = parameters & 0x4000;
535
536 memory->waitstates16[REGION_CART_SRAM] = memory->waitstates16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
537 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
538 memory->waitstates32[REGION_CART_SRAM] = memory->waitstates32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
539 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
540
541 memory->waitstates16[REGION_CART0] = memory->waitstates16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
542 memory->waitstates16[REGION_CART1] = memory->waitstates16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
543 memory->waitstates16[REGION_CART2] = memory->waitstates16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
544
545 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
546 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
547 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
548
549 memory->waitstates32[REGION_CART0] = memory->waitstates32[REGION_CART0_EX] = memory->waitstates16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
550 memory->waitstates32[REGION_CART1] = memory->waitstates32[REGION_CART1_EX] = memory->waitstates16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
551 memory->waitstates32[REGION_CART2] = memory->waitstates32[REGION_CART2_EX] = memory->waitstates16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
552
553 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
554 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
555 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
556
557 if (!prefetch) {
558 memory->waitstatesPrefetch16[REGION_CART0] = memory->waitstatesPrefetch16[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0];
559 memory->waitstatesPrefetch16[REGION_CART1] = memory->waitstatesPrefetch16[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1];
560 memory->waitstatesPrefetch16[REGION_CART2] = memory->waitstatesPrefetch16[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2];
561
562 memory->waitstatesPrefetch32[REGION_CART0] = memory->waitstatesPrefetch32[REGION_CART0_EX] = memory->waitstatesSeq32[REGION_CART0];
563 memory->waitstatesPrefetch32[REGION_CART1] = memory->waitstatesPrefetch32[REGION_CART1_EX] = memory->waitstatesSeq32[REGION_CART1];
564 memory->waitstatesPrefetch32[REGION_CART2] = memory->waitstatesPrefetch32[REGION_CART2_EX] = memory->waitstatesSeq32[REGION_CART2];
565 } else {
566 memory->waitstatesPrefetch16[REGION_CART0] = memory->waitstatesPrefetch16[REGION_CART0_EX] = 0;
567 memory->waitstatesPrefetch16[REGION_CART1] = memory->waitstatesPrefetch16[REGION_CART1_EX] = 0;
568 memory->waitstatesPrefetch16[REGION_CART2] = memory->waitstatesPrefetch16[REGION_CART2_EX] = 0;
569
570 memory->waitstatesPrefetch32[REGION_CART0] = memory->waitstatesPrefetch32[REGION_CART0_EX] = 0;
571 memory->waitstatesPrefetch32[REGION_CART1] = memory->waitstatesPrefetch32[REGION_CART1_EX] = 0;
572 memory->waitstatesPrefetch32[REGION_CART2] = memory->waitstatesPrefetch32[REGION_CART2_EX] = 0;
573 }
574
575 memory->d.activePrefetchCycles32 = memory->waitstatesPrefetch32[memory->activeRegion];
576 memory->d.activePrefetchCycles16 = memory->waitstatesPrefetch16[memory->activeRegion];
577 memory->d.activeNonseqCycles32 = memory->waitstates32[memory->activeRegion];
578 memory->d.activeNonseqCycles16 = memory->waitstates16[memory->activeRegion];
579}
580
581void GBAMemoryWriteDMASAD(struct GBAMemory* memory, int dma, uint32_t address) {
582 memory->dma[dma].source = address & 0xFFFFFFFE;
583}
584
585void GBAMemoryWriteDMADAD(struct GBAMemory* memory, int dma, uint32_t address) {
586 memory->dma[dma].dest = address & 0xFFFFFFFE;
587}
588
589void GBAMemoryWriteDMACNT_LO(struct GBAMemory* memory, int dma, uint16_t count) {
590 memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
591}
592
593uint16_t GBAMemoryWriteDMACNT_HI(struct GBAMemory* memory, int dma, uint16_t control) {
594 struct GBADMA* currentDma = &memory->dma[dma];
595 int wasEnabled = currentDma->enable;
596 currentDma->packed = control;
597
598 if (currentDma->drq) {
599 GBALog(memory->p, GBA_LOG_STUB, "DRQ not implemented");
600 }
601
602 if (!wasEnabled && currentDma->enable) {
603 currentDma->nextSource = currentDma->source;
604 currentDma->nextDest = currentDma->dest;
605 currentDma->nextCount = currentDma->count;
606 GBAMemoryScheduleDMA(memory, dma, currentDma);
607 }
608 // If the DMA has already occurred, this value might have changed since the function started
609 return currentDma->packed;
610};
611
612void GBAMemoryScheduleDMA(struct GBAMemory* memory, int number, struct GBADMA* info) {
613 switch (info->timing) {
614 case DMA_TIMING_NOW:
615 info->nextEvent = memory->p->cpu.cycles;
616 GBAMemoryUpdateDMAs(memory, 0);
617 break;
618 case DMA_TIMING_HBLANK:
619 // Handled implicitly
620 info->nextEvent = INT_MAX;
621 break;
622 case DMA_TIMING_VBLANK:
623 // Handled implicitly
624 info->nextEvent = INT_MAX;
625 break;
626 case DMA_TIMING_CUSTOM:
627 info->nextEvent = INT_MAX;
628 switch (number) {
629 case 0:
630 GBALog(memory->p, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
631 break;
632 case 1:
633 case 2:
634 GBAAudioScheduleFifoDma(&memory->p->audio, number, info);
635 break;
636 case 3:
637 // GBAVideoScheduleVCaptureDma(dma, info);
638 break;
639 }
640 }
641}
642
643void GBAMemoryRunHblankDMAs(struct GBAMemory* memory, int32_t cycles) {
644 struct GBADMA* dma;
645 int i;
646 for (i = 0; i < 4; ++i) {
647 dma = &memory->dma[i];
648 if (dma->enable && dma->timing == DMA_TIMING_HBLANK) {
649 dma->nextEvent = cycles;
650 }
651 }
652 GBAMemoryUpdateDMAs(memory, 0);
653}
654
655void GBAMemoryRunVblankDMAs(struct GBAMemory* memory, int32_t cycles) {
656 struct GBADMA* dma;
657 int i;
658 for (i = 0; i < 4; ++i) {
659 dma = &memory->dma[i];
660 if (dma->enable && dma->timing == DMA_TIMING_VBLANK) {
661 dma->nextEvent = cycles;
662 }
663 }
664 GBAMemoryUpdateDMAs(memory, 0);
665}
666
667int32_t GBAMemoryRunDMAs(struct GBAMemory* memory, int32_t cycles) {
668 if (memory->nextDMA == INT_MAX) {
669 return INT_MAX;
670 }
671 memory->nextDMA -= cycles;
672 memory->eventDiff += cycles;
673 if (memory->nextDMA <= 0) {
674 struct GBADMA* dma = &memory->dma[memory->activeDMA];
675 GBAMemoryServiceDMA(memory, memory->activeDMA, dma);
676 GBAMemoryUpdateDMAs(memory, memory->eventDiff);
677 memory->eventDiff = 0;
678 }
679 return memory->nextDMA;
680}
681
682void GBAMemoryUpdateDMAs(struct GBAMemory* memory, int32_t cycles) {
683 int i;
684 memory->activeDMA = -1;
685 memory->nextDMA = INT_MAX;
686 for (i = 3; i >= 0; --i) {
687 struct GBADMA* dma = &memory->dma[i];
688 if (dma->nextEvent != INT_MAX) {
689 dma->nextEvent -= cycles;
690 if (dma->enable) {
691 memory->activeDMA = i;
692 memory->nextDMA = dma->nextEvent;
693 }
694 }
695 }
696 if (memory->nextDMA < memory->p->cpu.nextEvent) {
697 memory->p->cpu.nextEvent = memory->nextDMA;
698 }
699}
700
701void GBAMemoryServiceDMA(struct GBAMemory* memory, int number, struct GBADMA* info) {
702 uint32_t width = info->width ? 4 : 2;
703 int sourceOffset = DMA_OFFSET[info->srcControl] * width;
704 int destOffset = DMA_OFFSET[info->dstControl] * width;
705 int32_t wordsRemaining = info->nextCount;
706 uint32_t source = info->nextSource;
707 uint32_t dest = info->nextDest;
708 uint32_t sourceRegion = source >> BASE_OFFSET;
709 uint32_t destRegion = dest >> BASE_OFFSET;
710 int32_t cycles = 0;
711
712 if (source == info->source) {
713 // TODO: support 4 cycles for ROM access
714 cycles += 2;
715 if (width == 4) {
716 cycles += memory->waitstates32[sourceRegion] + memory->waitstates32[destRegion];
717 source &= 0xFFFFFFFC;
718 dest &= 0xFFFFFFFC;
719 } else {
720 cycles += memory->waitstates16[sourceRegion] + memory->waitstates16[destRegion];
721 }
722 } else {
723 if (width == 4) {
724 cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
725 } else {
726 cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
727 }
728 }
729
730 if (width == 4) {
731 int32_t word;
732 word = memory->d.load32(&memory->d, source, 0);
733 memory->d.store32(&memory->d, dest, word, 0);
734 source += sourceOffset;
735 dest += destOffset;
736 --wordsRemaining;
737 } else {
738 uint16_t word;
739 if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
740 word = GBASavedataReadEEPROM(&memory->savedata);
741 memory->d.store16(&memory->d, dest, word, 0);
742 source += sourceOffset;
743 dest += destOffset;
744 --wordsRemaining;
745 } else if (destRegion == REGION_CART2_EX) {
746 if (memory->savedata.type == SAVEDATA_NONE) {
747 GBASavedataInitEEPROM(&memory->savedata);
748 }
749 word = memory->d.load16(&memory->d, source, 0);
750 GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
751 source += sourceOffset;
752 dest += destOffset;
753 --wordsRemaining;
754 } else {
755 word = memory->d.load16(&memory->d, source, 0);
756 memory->d.store16(&memory->d, dest, word, 0);
757 source += sourceOffset;
758 dest += destOffset;
759 --wordsRemaining;
760 }
761 }
762
763 if (!wordsRemaining) {
764 if (!info->repeat) {
765 info->enable = 0;
766 info->nextEvent = INT_MAX;
767
768 // Clear the enable bit in memory
769 memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
770 } else {
771 info->nextCount = info->count;
772 if (info->dstControl == DMA_INCREMENT_RELOAD) {
773 info->nextDest = info->dest;
774 }
775 GBAMemoryScheduleDMA(memory, number, info);
776 }
777 if (info->doIrq) {
778 GBARaiseIRQ(memory->p, IRQ_DMA0 + number);
779 }
780 } else {
781 info->nextDest = dest;
782 info->nextCount = wordsRemaining;
783 }
784 info->nextSource = source;
785
786 int i;
787 for (i = 0; i < 4; ++i) {
788 if (memory->dma[i].nextEvent != INT_MAX) {
789 memory->dma[i].nextEvent += cycles;
790 }
791 }
792 memory->p->cpu.cycles += cycles;
793}
794
795void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {
796 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
797 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
798}
799
800void GBAMemoryDeserialize(struct GBAMemory* memory, struct GBASerializedState* state) {
801 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
802 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
803}