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