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