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