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