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