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 GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame");
369 GBASavedataInitSRAM(&memory->savedata);
370 }
371 if (memory->savedata.type == SAVEDATA_SRAM) {
372 value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
373 } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
374 value = GBASavedataReadFlash(&memory->savedata, address);
375 }
376 break;
377 default:
378 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
379 value = cpu->prefetch & 0xFF;
380 break;
381 }
382
383 if (cycleCounter) {
384 *cycleCounter += 2 + wait;
385 }
386 return value;
387}
388
389void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
390 struct GBA* gba = (struct GBA*) cpu->master;
391 struct GBAMemory* memory = &gba->memory;
392 int wait = 0;
393
394 switch (address >> BASE_OFFSET) {
395 case REGION_WORKING_RAM:
396 STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
397 wait = memory->waitstatesNonseq32[REGION_WORKING_RAM];
398 break;
399 case REGION_WORKING_IRAM:
400 STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
401 break;
402 case REGION_IO:
403 GBAIOWrite32(gba, address & (SIZE_IO - 1), value);
404 break;
405 case REGION_PALETTE_RAM:
406 STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
407 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16);
408 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
409 break;
410 case REGION_VRAM:
411 if ((address & OFFSET_MASK) < SIZE_VRAM) {
412 STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram);
413 } else if ((address & OFFSET_MASK) < 0x00020000) {
414 STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram);
415 }
416 break;
417 case REGION_OAM:
418 STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
419 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
420 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
421 break;
422 case REGION_CART0:
423 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
424 break;
425 case REGION_CART_SRAM:
426 case REGION_CART_SRAM_MIRROR:
427 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
428 break;
429 default:
430 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
431 break;
432 }
433
434 if (cycleCounter) {
435 *cycleCounter += 1 + wait;
436 }
437}
438
439void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
440 struct GBA* gba = (struct GBA*) cpu->master;
441 struct GBAMemory* memory = &gba->memory;
442 int wait = 0;
443
444 switch (address >> BASE_OFFSET) {
445 case REGION_WORKING_RAM:
446 STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
447 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
448 break;
449 case REGION_WORKING_IRAM:
450 STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
451 break;
452 case REGION_IO:
453 GBAIOWrite(gba, address & (SIZE_IO - 1), value);
454 break;
455 case REGION_PALETTE_RAM:
456 STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
457 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
458 break;
459 case REGION_VRAM:
460 if ((address & OFFSET_MASK) < SIZE_VRAM) {
461 STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
462 } else if ((address & OFFSET_MASK) < 0x00020000) {
463 STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram);
464 }
465 break;
466 case REGION_OAM:
467 STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
468 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
469 break;
470 case REGION_CART0:
471 if (IS_GPIO_REGISTER(address & 0xFFFFFF)) {
472 uint32_t reg = address & 0xFFFFFF;
473 GBAGPIOWrite(&memory->gpio, reg, value);
474 } else {
475 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
476 }
477 break;
478 case REGION_CART2_EX:
479 if (memory->savedata.type == SAVEDATA_NONE) {
480 GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
481 GBASavedataInitEEPROM(&memory->savedata);
482 }
483 GBASavedataWriteEEPROM(&memory->savedata, value, 1);
484 break;
485 case REGION_CART_SRAM:
486 case REGION_CART_SRAM_MIRROR:
487 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store16: 0x%08X", address);
488 break;
489 default:
490 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store16: 0x%08X", address);
491 break;
492 }
493
494 if (cycleCounter) {
495 *cycleCounter += 1 + wait;
496 }
497}
498
499void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
500 struct GBA* gba = (struct GBA*) cpu->master;
501 struct GBAMemory* memory = &gba->memory;
502 int wait = 0;
503
504 switch (address >> BASE_OFFSET) {
505 case REGION_WORKING_RAM:
506 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
507 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
508 break;
509 case REGION_WORKING_IRAM:
510 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
511 break;
512 case REGION_IO:
513 GBAIOWrite8(gba, address & (SIZE_IO - 1), value);
514 break;
515 case REGION_PALETTE_RAM:
516 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
517 break;
518 case REGION_VRAM:
519 if (address >= 0x06018000) {
520 // TODO: check BG mode
521 GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
522 break;
523 }
524 ((int8_t*) gba->video.renderer->vram)[address & 0x1FFFE] = value;
525 ((int8_t*) gba->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
526 break;
527 case REGION_OAM:
528 GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
529 break;
530 case REGION_CART0:
531 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
532 break;
533 case REGION_CART_SRAM:
534 case REGION_CART_SRAM_MIRROR:
535 if (memory->savedata.type == SAVEDATA_NONE) {
536 if (address == SAVEDATA_FLASH_BASE) {
537 GBALog(gba, GBA_LOG_INFO, "Detected Flash savegame");
538 GBASavedataInitFlash(&memory->savedata);
539 } else {
540 GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame");
541 GBASavedataInitSRAM(&memory->savedata);
542 }
543 }
544 if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
545 GBASavedataWriteFlash(&memory->savedata, address, value);
546 } else if (memory->savedata.type == SAVEDATA_SRAM) {
547 memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
548 }
549 wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
550 break;
551 default:
552 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store8: 0x%08X", address);
553 break;
554 }
555
556 if (cycleCounter) {
557 *cycleCounter += 1 + wait;
558 }
559}
560
561static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count) {
562 struct GBA* gba = (struct GBA*) cpu->master;
563 struct GBAMemory* memory = &gba->memory;
564 int wait = 1 + memory->waitstatesNonseq32[startAddress >> BASE_OFFSET];
565 wait += (1 + memory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1);
566 return wait;
567}
568
569void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
570 struct GBAMemory* memory = &gba->memory;
571 struct ARMCore* cpu = gba->cpu;
572 int sram = parameters & 0x0003;
573 int ws0 = (parameters & 0x000C) >> 2;
574 int ws0seq = (parameters & 0x0010) >> 4;
575 int ws1 = (parameters & 0x0060) >> 5;
576 int ws1seq = (parameters & 0x0080) >> 7;
577 int ws2 = (parameters & 0x0300) >> 8;
578 int ws2seq = (parameters & 0x0400) >> 10;
579 int prefetch = parameters & 0x4000;
580
581 memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
582 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
583 memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
584 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
585
586 memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
587 memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
588 memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
589
590 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
591 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
592 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
593
594 memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
595 memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
596 memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
597
598 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
599 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
600 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
601
602 if (!prefetch) {
603 memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0];
604 memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1];
605 memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2];
606
607 memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = memory->waitstatesSeq32[REGION_CART0];
608 memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = memory->waitstatesSeq32[REGION_CART1];
609 memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = memory->waitstatesSeq32[REGION_CART2];
610
611 memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0];
612 memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1];
613 memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2];
614
615 memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq32[REGION_CART0];
616 memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq32[REGION_CART1];
617 memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq32[REGION_CART2];
618 } else {
619 memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = 0;
620 memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = 0;
621 memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = 0;
622
623 memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = 0;
624 memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = 0;
625 memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = 0;
626
627 memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = 0;
628 memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = 0;
629 memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = 0;
630
631 memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = 0;
632 memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = 0;
633 memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = 0;
634 }
635
636 cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
637 cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
638
639 cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
640 cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
641
642 cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
643 cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
644}
645
646void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
647 struct GBAMemory* memory = &gba->memory;
648 memory->dma[dma].source = address & 0xFFFFFFFE;
649}
650
651void GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
652 struct GBAMemory* memory = &gba->memory;
653 memory->dma[dma].dest = address & 0xFFFFFFFE;
654}
655
656void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
657 struct GBAMemory* memory = &gba->memory;
658 memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
659}
660
661uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
662 struct GBAMemory* memory = &gba->memory;
663 struct GBADMA* currentDma = &memory->dma[dma];
664 int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
665 currentDma->reg = control;
666
667 if (GBADMARegisterIsDRQ(currentDma->reg)) {
668 GBALog(gba, GBA_LOG_STUB, "DRQ not implemented");
669 }
670
671 if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
672 currentDma->nextSource = currentDma->source;
673 currentDma->nextDest = currentDma->dest;
674 currentDma->nextCount = currentDma->count;
675 GBAMemoryScheduleDMA(gba, dma, currentDma);
676 }
677 // If the DMA has already occurred, this value might have changed since the function started
678 return currentDma->reg;
679};
680
681void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
682 struct ARMCore* cpu = gba->cpu;
683 switch (GBADMARegisterGetTiming(info->reg)) {
684 case DMA_TIMING_NOW:
685 info->nextEvent = cpu->cycles;
686 GBAMemoryUpdateDMAs(gba, 0);
687 break;
688 case DMA_TIMING_HBLANK:
689 // Handled implicitly
690 info->nextEvent = INT_MAX;
691 break;
692 case DMA_TIMING_VBLANK:
693 // Handled implicitly
694 info->nextEvent = INT_MAX;
695 break;
696 case DMA_TIMING_CUSTOM:
697 info->nextEvent = INT_MAX;
698 switch (number) {
699 case 0:
700 GBALog(gba, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
701 break;
702 case 1:
703 case 2:
704 GBAAudioScheduleFifoDma(&gba->audio, number, info);
705 break;
706 case 3:
707 // GBAVideoScheduleVCaptureDma(dma, info);
708 break;
709 }
710 }
711}
712
713void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
714 struct GBAMemory* memory = &gba->memory;
715 struct GBADMA* dma;
716 int i;
717 for (i = 0; i < 4; ++i) {
718 dma = &memory->dma[i];
719 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK) {
720 dma->nextEvent = cycles;
721 }
722 }
723 GBAMemoryUpdateDMAs(gba, 0);
724}
725
726void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
727 struct GBAMemory* memory = &gba->memory;
728 struct GBADMA* dma;
729 int i;
730 for (i = 0; i < 4; ++i) {
731 dma = &memory->dma[i];
732 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK) {
733 dma->nextEvent = cycles;
734 }
735 }
736 GBAMemoryUpdateDMAs(gba, 0);
737}
738
739int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
740 struct GBAMemory* memory = &gba->memory;
741 if (memory->nextDMA == INT_MAX) {
742 return INT_MAX;
743 }
744 memory->nextDMA -= cycles;
745 memory->eventDiff += cycles;
746 if (memory->nextDMA <= 0) {
747 struct GBADMA* dma = &memory->dma[memory->activeDMA];
748 GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
749 GBAMemoryUpdateDMAs(gba, memory->eventDiff);
750 memory->eventDiff = 0;
751 }
752 return memory->nextDMA;
753}
754
755void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
756 int i;
757 struct GBAMemory* memory = &gba->memory;
758 struct ARMCore* cpu = gba->cpu;
759 memory->activeDMA = -1;
760 memory->nextDMA = INT_MAX;
761 for (i = 3; i >= 0; --i) {
762 struct GBADMA* dma = &memory->dma[i];
763 if (dma->nextEvent != INT_MAX) {
764 dma->nextEvent -= cycles;
765 if (GBADMARegisterIsEnable(dma->reg)) {
766 memory->activeDMA = i;
767 memory->nextDMA = dma->nextEvent;
768 }
769 }
770 }
771 if (memory->nextDMA < cpu->nextEvent) {
772 cpu->nextEvent = memory->nextDMA;
773 }
774}
775
776void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
777 struct GBAMemory* memory = &gba->memory;
778 struct ARMCore* cpu = gba->cpu;
779 uint32_t width = GBADMARegisterGetWidth(info->reg) ? 4 : 2;
780 int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
781 int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width;
782 int32_t wordsRemaining = info->nextCount;
783 uint32_t source = info->nextSource;
784 uint32_t dest = info->nextDest;
785 uint32_t sourceRegion = source >> BASE_OFFSET;
786 uint32_t destRegion = dest >> BASE_OFFSET;
787 int32_t cycles = 0;
788
789 if (source == info->source) {
790 // TODO: support 4 cycles for ROM access
791 cycles += 2;
792 if (width == 4) {
793 cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
794 source &= 0xFFFFFFFC;
795 dest &= 0xFFFFFFFC;
796 } else {
797 cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
798 }
799 } else {
800 if (width == 4) {
801 cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
802 } else {
803 cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
804 }
805 }
806
807 if (width == 4) {
808 int32_t word;
809 word = cpu->memory.load32(cpu, source, 0);
810 cpu->memory.store32(cpu, dest, word, 0);
811 source += sourceOffset;
812 dest += destOffset;
813 --wordsRemaining;
814 } else {
815 uint16_t word;
816 if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
817 word = GBASavedataReadEEPROM(&memory->savedata);
818 cpu->memory.store16(cpu, dest, word, 0);
819 source += sourceOffset;
820 dest += destOffset;
821 --wordsRemaining;
822 } else if (destRegion == REGION_CART2_EX) {
823 if (memory->savedata.type == SAVEDATA_NONE) {
824 GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
825 GBASavedataInitEEPROM(&memory->savedata);
826 }
827 word = cpu->memory.load16(cpu, source, 0);
828 GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
829 source += sourceOffset;
830 dest += destOffset;
831 --wordsRemaining;
832 } else {
833 word = cpu->memory.load16(cpu, source, 0);
834 cpu->memory.store16(cpu, dest, word, 0);
835 source += sourceOffset;
836 dest += destOffset;
837 --wordsRemaining;
838 }
839 }
840
841 if (!wordsRemaining) {
842 if (!GBADMARegisterIsRepeat(info->reg)) {
843 info->reg = GBADMARegisterClearEnable(info->reg);
844 info->nextEvent = INT_MAX;
845
846 // Clear the enable bit in memory
847 memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
848 } else {
849 info->nextCount = info->count;
850 if (GBADMARegisterGetDestControl(info->reg) == DMA_INCREMENT_RELOAD) {
851 info->nextDest = info->dest;
852 }
853 GBAMemoryScheduleDMA(gba, number, info);
854 }
855 if (GBADMARegisterIsDoIRQ(info->reg)) {
856 GBARaiseIRQ(gba, IRQ_DMA0 + number);
857 }
858 } else {
859 info->nextDest = dest;
860 info->nextCount = wordsRemaining;
861 }
862 info->nextSource = source;
863
864 if (info->nextEvent != INT_MAX) {
865 info->nextEvent += cycles;
866 }
867 cpu->cycles += cycles;
868}
869
870void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {
871 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
872 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
873}
874
875void GBAMemoryDeserialize(struct GBAMemory* memory, struct GBASerializedState* state) {
876 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
877 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
878}