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