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