src/gba/gba-memory.c (view raw)
1#include "gba-memory.h"
2
3#include "macros.h"
4
5#include "gba-gpio.h"
6#include "gba-io.h"
7#include "gba-serialize.h"
8#include "hle-bios.h"
9#include "util/memory.h"
10
11static uint32_t _popcount32(unsigned bits);
12
13static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
14static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
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 GBA* gba) {
25 struct ARMCore* cpu = gba->cpu;
26 cpu->memory.load32 = GBALoad32;
27 cpu->memory.load16 = GBALoad16;
28 cpu->memory.loadU16 = GBALoadU16;
29 cpu->memory.load8 = GBALoad8;
30 cpu->memory.loadU8 = GBALoadU8;
31 cpu->memory.loadMultiple = GBALoadMultiple;
32 cpu->memory.store32 = GBAStore32;
33 cpu->memory.store16 = GBAStore16;
34 cpu->memory.store8 = GBAStore8;
35 cpu->memory.storeMultiple = GBAStoreMultiple;
36
37 gba->memory.bios = (uint32_t*) hleBios;
38 gba->memory.fullBios = 0;
39 gba->memory.wram = 0;
40 gba->memory.iwram = 0;
41 gba->memory.rom = 0;
42 gba->memory.gpio.p = gba;
43
44 int i;
45 for (i = 0; i < 16; ++i) {
46 gba->memory.waitstatesNonseq16[i] = GBA_BASE_WAITSTATES[i];
47 gba->memory.waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
48 gba->memory.waitstatesPrefetchNonseq16[i] = GBA_BASE_WAITSTATES[i];
49 gba->memory.waitstatesPrefetchSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
50 gba->memory.waitstatesNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
51 gba->memory.waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
52 gba->memory.waitstatesPrefetchNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
53 gba->memory.waitstatesPrefetchSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
54 }
55 for (; i < 256; ++i) {
56 gba->memory.waitstatesNonseq16[i] = 0;
57 gba->memory.waitstatesSeq16[i] = 0;
58 gba->memory.waitstatesNonseq32[i] = 0;
59 gba->memory.waitstatesSeq32[i] = 0;
60 }
61
62 gba->memory.activeRegion = -1;
63 cpu->memory.activeRegion = 0;
64 cpu->memory.activeMask = 0;
65 cpu->memory.setActiveRegion = GBASetActiveRegion;
66 cpu->memory.activeSeqCycles32 = 0;
67 cpu->memory.activeSeqCycles16 = 0;
68 cpu->memory.activeNonseqCycles32 = 0;
69 cpu->memory.activeNonseqCycles16 = 0;
70 cpu->memory.activeUncachedCycles32 = 0;
71 cpu->memory.activeUncachedCycles16 = 0;
72 gba->memory.biosPrefetch = 0;
73}
74
75void GBAMemoryDeinit(struct GBA* gba) {
76 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
77 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
78 if (gba->memory.rom) {
79 mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
80 }
81 GBASavedataDeinit(&gba->memory.savedata);
82}
83
84void GBAMemoryReset(struct GBA* gba) {
85 if (gba->memory.wram) {
86 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
87 }
88 gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
89
90 if (gba->memory.iwram) {
91 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
92 }
93 gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
94
95 memset(gba->memory.io, 0, sizeof(gba->memory.io));
96 memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
97 int i;
98 for (i = 0; i < 4; ++i) {
99 gba->memory.dma[i].count = 0x10000;
100 gba->memory.dma[i].nextEvent = INT_MAX;
101 }
102 gba->memory.activeDMA = -1;
103 gba->memory.nextDMA = INT_MAX;
104 gba->memory.eventDiff = 0;
105
106 if (!gba->memory.wram || !gba->memory.iwram) {
107 GBAMemoryDeinit(gba);
108 GBALog(gba, GBA_LOG_FATAL, "Could not map memory");
109 }
110}
111
112static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
113 struct GBA* gba = (struct GBA*) cpu->master;
114 struct GBAMemory* memory = &gba->memory;
115
116 if (address == gba->busyLoop && memory->activeRegion != REGION_BIOS) {
117 GBAHalt(gba);
118 }
119
120 int newRegion = address >> BASE_OFFSET;
121 if (newRegion == memory->activeRegion) {
122 return;
123 }
124 if (memory->activeRegion == REGION_BIOS) {
125 memory->biosPrefetch = cpu->prefetch;
126 }
127 memory->activeRegion = newRegion;
128 switch (address & ~OFFSET_MASK) {
129 case BASE_BIOS:
130 cpu->memory.activeRegion = memory->bios;
131 cpu->memory.activeMask = SIZE_BIOS - 1;
132 break;
133 case BASE_WORKING_RAM:
134 cpu->memory.activeRegion = memory->wram;
135 cpu->memory.activeMask = SIZE_WORKING_RAM - 1;
136 break;
137 case BASE_WORKING_IRAM:
138 cpu->memory.activeRegion = memory->iwram;
139 cpu->memory.activeMask = SIZE_WORKING_IRAM - 1;
140 break;
141 case BASE_VRAM:
142 cpu->memory.activeRegion = (uint32_t*) gba->video.renderer->vram;
143 cpu->memory.activeMask = 0x0000FFFF;
144 break;
145 case BASE_CART0:
146 case BASE_CART0_EX:
147 case BASE_CART1:
148 case BASE_CART1_EX:
149 case BASE_CART2:
150 case BASE_CART2_EX:
151 cpu->memory.activeRegion = memory->rom;
152 cpu->memory.activeMask = SIZE_CART0 - 1;
153 break;
154 default:
155 cpu->memory.activeRegion = 0;
156 cpu->memory.activeMask = 0;
157 GBALog(gba, GBA_LOG_FATAL, "Jumped to invalid address");
158 break;
159 }
160 cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
161 cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
162 cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
163 cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
164 cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
165 cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
166}
167
168#define LOAD_BIOS \
169 if (memory->activeRegion == REGION_BIOS) { \
170 if (address < SIZE_BIOS) { \
171 LOAD_32(value, address, memory->bios); \
172 } else { \
173 value = 0; \
174 } \
175 } else { \
176 value = memory->biosPrefetch; \
177 }
178
179#define LOAD_WORKING_RAM \
180 LOAD_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); \
181 wait += waitstatesRegion[REGION_WORKING_RAM];
182
183#define LOAD_WORKING_IRAM LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
184#define LOAD_IO value = GBAIORead(gba, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gba, (address & (SIZE_IO - 1)) | 2) << 16);
185
186#define LOAD_PALETTE_RAM \
187 LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); \
188 ++wait;
189
190#define LOAD_VRAM \
191 LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
192 ++wait;
193
194#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
195
196#define LOAD_CART \
197 wait += waitstatesRegion[address >> BASE_OFFSET]; \
198 if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \
199 LOAD_32(value, address & (SIZE_CART0 - 1), memory->rom); \
200 } else { \
201 value = (address >> 1) & 0xFFFF; \
202 }
203
204#define LOAD_SRAM \
205 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address); \
206 value = 0xDEADBEEF;
207
208#define LOAD_BAD \
209 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); \
210 value = cpu->prefetch; \
211 if (cpu->executionMode == MODE_THUMB) { \
212 value |= value << 16; \
213 }
214
215int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
216 struct GBA* gba = (struct GBA*) cpu->master;
217 struct GBAMemory* memory = &gba->memory;
218 uint32_t value = 0;
219 int wait = 0;
220 char* waitstatesRegion = memory->waitstatesNonseq32;
221
222 switch (address >> BASE_OFFSET) {
223 case REGION_BIOS:
224 LOAD_BIOS;
225 break;
226 case REGION_WORKING_RAM:
227 LOAD_WORKING_RAM;
228 break;
229 case REGION_WORKING_IRAM:
230 LOAD_WORKING_IRAM;
231 break;
232 case REGION_IO:
233 LOAD_IO;
234 break;
235 case REGION_PALETTE_RAM:
236 LOAD_PALETTE_RAM;
237 break;
238 case REGION_VRAM:
239 LOAD_VRAM;
240 break;
241 case REGION_OAM:
242 LOAD_OAM;
243 break;
244 case REGION_CART0:
245 case REGION_CART0_EX:
246 case REGION_CART1:
247 case REGION_CART1_EX:
248 case REGION_CART2:
249 case REGION_CART2_EX:
250 LOAD_CART;
251 break;
252 case REGION_CART_SRAM:
253 case REGION_CART_SRAM_MIRROR:
254 LOAD_SRAM;
255 break;
256 default:
257 LOAD_BAD;
258 break;
259 }
260
261 if (cycleCounter) {
262 *cycleCounter += 2 + wait;
263 }
264 // Unaligned 32-bit loads are "rotated" so they make some semblance of sense
265 int rotate = (address & 3) << 3;
266 return (value >> rotate) | (value << (32 - rotate));
267}
268
269uint16_t GBALoadU16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
270 return GBALoad16(cpu, address, cycleCounter);
271}
272
273int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
274 struct GBA* gba = (struct GBA*) cpu->master;
275 struct GBAMemory* memory = &gba->memory;
276 uint16_t value = 0;
277 int wait = 0;
278
279 switch (address >> BASE_OFFSET) {
280 case REGION_BIOS:
281 if (memory->activeRegion == REGION_BIOS) {
282 if (address < SIZE_BIOS) {
283 LOAD_16(value, address, memory->bios);
284 } else {
285 value = 0;
286 }
287 } else {
288 value = memory->biosPrefetch;
289 }
290 break;
291 case REGION_WORKING_RAM:
292 LOAD_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
293 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
294 break;
295 case REGION_WORKING_IRAM:
296 LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
297 break;
298 case REGION_IO:
299 value = GBAIORead(gba, address & (SIZE_IO - 1));
300 break;
301 case REGION_PALETTE_RAM:
302 LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
303 break;
304 case REGION_VRAM:
305 LOAD_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
306 break;
307 case REGION_OAM:
308 LOAD_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
309 break;
310 case REGION_CART0:
311 case REGION_CART0_EX:
312 case REGION_CART1:
313 case REGION_CART1_EX:
314 case REGION_CART2:
315 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
316 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
317 LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
318 }
319 break;
320 case REGION_CART2_EX:
321 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
322 if (memory->savedata.type == SAVEDATA_EEPROM) {
323 value = GBASavedataReadEEPROM(&memory->savedata);
324 } else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
325 LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
326 }
327 break;
328 case REGION_CART_SRAM:
329 case REGION_CART_SRAM_MIRROR:
330 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load16: 0x%08X", address);
331 break;
332 default:
333 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
334 value = cpu->prefetch;
335 break;
336 }
337
338 if (cycleCounter) {
339 *cycleCounter += 2 + wait;
340 }
341 // Unaligned 16-bit loads are "unpredictable", but the GBA rotates them, so we have to, too.
342 int rotate = (address & 1) << 3;
343 return (value >> rotate) | (value << (16 - rotate));
344}
345
346uint8_t GBALoadU8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
347 return GBALoad8(cpu, address, cycleCounter);
348}
349
350int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
351 struct GBA* gba = (struct GBA*) cpu->master;
352 struct GBAMemory* memory = &gba->memory;
353 int8_t value = 0;
354 int wait = 0;
355
356 switch (address >> BASE_OFFSET) {
357 case REGION_BIOS:
358 if (memory->activeRegion == REGION_BIOS) {
359 if (address < SIZE_BIOS) {
360 value = ((int8_t*) memory->bios)[address];
361 } else {
362 value = 0;
363 }
364 } else {
365 value = memory->biosPrefetch;
366 }
367 break;
368 case REGION_WORKING_RAM:
369 value = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
370 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
371 break;
372 case REGION_WORKING_IRAM:
373 value = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
374 break;
375 case REGION_IO:
376 value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
377 break;
378 case REGION_PALETTE_RAM:
379 value = ((int8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
380 break;
381 case REGION_VRAM:
382 value = ((int8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
383 break;
384 case REGION_OAM:
385 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
386 break;
387 case REGION_CART0:
388 case REGION_CART0_EX:
389 case REGION_CART1:
390 case REGION_CART1_EX:
391 case REGION_CART2:
392 case REGION_CART2_EX:
393 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
394 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
395 value = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
396 }
397 break;
398 case REGION_CART_SRAM:
399 case REGION_CART_SRAM_MIRROR:
400 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
401 if (memory->savedata.type == SAVEDATA_NONE) {
402 GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame");
403 GBASavedataInitSRAM(&memory->savedata);
404 }
405 if (memory->savedata.type == SAVEDATA_SRAM) {
406 value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
407 } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
408 value = GBASavedataReadFlash(&memory->savedata, address);
409 }
410 break;
411 default:
412 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
413 value = cpu->prefetch & 0xFF;
414 break;
415 }
416
417 if (cycleCounter) {
418 *cycleCounter += 2 + wait;
419 }
420 return value;
421}
422
423#define STORE_WORKING_RAM \
424 STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); \
425 wait += waitstatesRegion[REGION_WORKING_RAM];
426
427#define STORE_WORKING_IRAM \
428 STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
429
430#define STORE_IO \
431 GBAIOWrite32(gba, address & (SIZE_IO - 1), value);
432
433#define STORE_PALETTE_RAM \
434 STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); \
435 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16); \
436 ++wait; \
437 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
438
439#define STORE_VRAM \
440 if ((address & OFFSET_MASK) < SIZE_VRAM) { \
441 STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
442 } else if ((address & OFFSET_MASK) < 0x00020000) { \
443 STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram); \
444 } \
445 ++wait;
446
447#define STORE_OAM \
448 STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw); \
449 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
450 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
451
452#define STORE_CART \
453 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
454
455#define STORE_SRAM \
456 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
457
458#define STORE_BAD \
459 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
460
461void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
462 struct GBA* gba = (struct GBA*) cpu->master;
463 struct GBAMemory* memory = &gba->memory;
464 int wait = 0;
465 char* waitstatesRegion = memory->waitstatesNonseq32;
466
467 switch (address >> BASE_OFFSET) {
468 case REGION_WORKING_RAM:
469 STORE_WORKING_RAM;
470 break;
471 case REGION_WORKING_IRAM:
472 STORE_WORKING_IRAM
473 break;
474 case REGION_IO:
475 STORE_IO;
476 break;
477 case REGION_PALETTE_RAM:
478 STORE_PALETTE_RAM;
479 break;
480 case REGION_VRAM:
481 STORE_VRAM;
482 break;
483 case REGION_OAM:
484 STORE_OAM;
485 break;
486 case REGION_CART0:
487 case REGION_CART0_EX:
488 case REGION_CART1:
489 case REGION_CART1_EX:
490 case REGION_CART2:
491 case REGION_CART2_EX:
492 STORE_CART;
493 break;
494 case REGION_CART_SRAM:
495 case REGION_CART_SRAM_MIRROR:
496 STORE_SRAM;
497 break;
498 default:
499 STORE_BAD;
500 break;
501 }
502
503 if (cycleCounter) {
504 *cycleCounter += 1 + wait;
505 }
506}
507
508void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
509 struct GBA* gba = (struct GBA*) cpu->master;
510 struct GBAMemory* memory = &gba->memory;
511 int wait = 0;
512
513 switch (address >> BASE_OFFSET) {
514 case REGION_WORKING_RAM:
515 STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
516 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
517 break;
518 case REGION_WORKING_IRAM:
519 STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
520 break;
521 case REGION_IO:
522 GBAIOWrite(gba, address & (SIZE_IO - 1), value);
523 break;
524 case REGION_PALETTE_RAM:
525 STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
526 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
527 break;
528 case REGION_VRAM:
529 if ((address & OFFSET_MASK) < SIZE_VRAM) {
530 STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
531 } else if ((address & OFFSET_MASK) < 0x00020000) {
532 STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram);
533 }
534 break;
535 case REGION_OAM:
536 STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
537 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
538 break;
539 case REGION_CART0:
540 if (IS_GPIO_REGISTER(address & 0xFFFFFF)) {
541 uint32_t reg = address & 0xFFFFFF;
542 GBAGPIOWrite(&memory->gpio, reg, value);
543 } else {
544 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
545 }
546 break;
547 case REGION_CART2_EX:
548 if (memory->savedata.type == SAVEDATA_NONE) {
549 GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
550 GBASavedataInitEEPROM(&memory->savedata);
551 }
552 GBASavedataWriteEEPROM(&memory->savedata, value, 1);
553 break;
554 case REGION_CART_SRAM:
555 case REGION_CART_SRAM_MIRROR:
556 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store16: 0x%08X", address);
557 break;
558 default:
559 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store16: 0x%08X", address);
560 break;
561 }
562
563 if (cycleCounter) {
564 *cycleCounter += 1 + wait;
565 }
566}
567
568void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
569 struct GBA* gba = (struct GBA*) cpu->master;
570 struct GBAMemory* memory = &gba->memory;
571 int wait = 0;
572
573 switch (address >> BASE_OFFSET) {
574 case REGION_WORKING_RAM:
575 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
576 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
577 break;
578 case REGION_WORKING_IRAM:
579 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
580 break;
581 case REGION_IO:
582 GBAIOWrite8(gba, address & (SIZE_IO - 1), value);
583 break;
584 case REGION_PALETTE_RAM:
585 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
586 break;
587 case REGION_VRAM:
588 if (address >= 0x06018000) {
589 // TODO: check BG mode
590 GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
591 break;
592 }
593 ((int8_t*) gba->video.renderer->vram)[address & 0x1FFFE] = value;
594 ((int8_t*) gba->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
595 break;
596 case REGION_OAM:
597 GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
598 break;
599 case REGION_CART0:
600 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
601 break;
602 case REGION_CART_SRAM:
603 case REGION_CART_SRAM_MIRROR:
604 if (memory->savedata.type == SAVEDATA_NONE) {
605 if (address == SAVEDATA_FLASH_BASE) {
606 GBALog(gba, GBA_LOG_INFO, "Detected Flash savegame");
607 GBASavedataInitFlash(&memory->savedata);
608 } else {
609 GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame");
610 GBASavedataInitSRAM(&memory->savedata);
611 }
612 }
613 if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
614 GBASavedataWriteFlash(&memory->savedata, address, value);
615 } else if (memory->savedata.type == SAVEDATA_SRAM) {
616 memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
617 }
618 wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
619 break;
620 default:
621 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store8: 0x%08X", address);
622 break;
623 }
624
625 if (cycleCounter) {
626 *cycleCounter += 1 + wait;
627 }
628}
629
630#define LDM_LOOP_BEGIN \
631 for (i = 0; i < 16; ++i) { \
632 if (!(mask & (1 << i))) { \
633 continue; \
634 }
635
636#define LDM_LOOP_END \
637 waitstatesRegion = memory->waitstatesSeq32; \
638 cpu->gprs[i] = value; \
639 ++wait; \
640 address += 4; \
641 }
642
643uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
644 struct GBA* gba = (struct GBA*) cpu->master;
645 struct GBAMemory* memory = &gba->memory;
646 uint32_t value;
647 int wait = 0;
648 char* waitstatesRegion = memory->waitstatesNonseq32;
649
650 int i;
651 int offset = 4;
652 int popcount = 0;
653 if (direction & LSM_D) {
654 offset = -4;
655 popcount = _popcount32(mask);
656 address -= (popcount << 2) - 4;
657 }
658
659 if (direction & LSM_B) {
660 address += offset;
661 }
662
663 address &= 0xFFFFFFFC;
664
665 switch (address >> BASE_OFFSET) {
666 case REGION_WORKING_RAM:
667 LDM_LOOP_BEGIN;
668 LOAD_WORKING_RAM;
669 LDM_LOOP_END;
670 break;
671 case REGION_WORKING_IRAM:
672 LDM_LOOP_BEGIN;
673 LOAD_WORKING_IRAM;
674 LDM_LOOP_END;
675 break;
676 case REGION_IO:
677 LDM_LOOP_BEGIN;
678 LOAD_IO;
679 LDM_LOOP_END;
680 break;
681 case REGION_PALETTE_RAM:
682 LDM_LOOP_BEGIN;
683 LOAD_PALETTE_RAM;
684 LDM_LOOP_END;
685 break;
686 case REGION_VRAM:
687 LDM_LOOP_BEGIN;
688 LOAD_VRAM;
689 LDM_LOOP_END;
690 break;
691 case REGION_OAM:
692 LDM_LOOP_BEGIN;
693 LOAD_OAM;
694 LDM_LOOP_END;
695 break;
696 case REGION_CART0:
697 case REGION_CART0_EX:
698 case REGION_CART1:
699 case REGION_CART1_EX:
700 case REGION_CART2:
701 case REGION_CART2_EX:
702 LDM_LOOP_BEGIN;
703 LOAD_CART;
704 LDM_LOOP_END;
705 break;
706 case REGION_CART_SRAM:
707 case REGION_CART_SRAM_MIRROR:
708 LDM_LOOP_BEGIN;
709 LOAD_SRAM;
710 LDM_LOOP_END;
711 break;
712 default:
713 LDM_LOOP_BEGIN;
714 LOAD_BAD;
715 LDM_LOOP_END;
716 break;
717 }
718
719 if (cycleCounter) {
720 *cycleCounter += wait;
721 }
722
723 if (direction & LSM_B) {
724 address -= offset;
725 }
726
727 if (direction & LSM_D) {
728 address -= (popcount << 2) + 4;
729 }
730
731 return address;
732}
733
734#define STM_LOOP_BEGIN \
735 for (i = 0; i < 16; ++i) { \
736 if (!(mask & (1 << i))) { \
737 continue; \
738 } \
739 value = cpu->gprs[i];
740
741#define STM_LOOP_END \
742 waitstatesRegion = memory->waitstatesSeq32; \
743 ++wait; \
744 address += 4; \
745 }
746
747uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
748 struct GBA* gba = (struct GBA*) cpu->master;
749 struct GBAMemory* memory = &gba->memory;
750 uint32_t value;
751 int wait = 0;
752 char* waitstatesRegion = memory->waitstatesNonseq32;
753
754 int i;
755 int offset = 4;
756 int popcount = 0;
757 if (direction & LSM_D) {
758 offset = -4;
759 popcount = _popcount32(mask);
760 address -= (popcount << 2) - 4;
761 }
762
763 if (direction & LSM_B) {
764 address += offset;
765 }
766
767 address &= 0xFFFFFFFC;
768
769 switch (address >> BASE_OFFSET) {
770 case REGION_WORKING_RAM:
771 STM_LOOP_BEGIN;
772 STORE_WORKING_RAM;
773 STM_LOOP_END;
774 break;
775 case REGION_WORKING_IRAM:
776 STM_LOOP_BEGIN;
777 STORE_WORKING_IRAM;
778 STM_LOOP_END;
779 break;
780 case REGION_IO:
781 STM_LOOP_BEGIN;
782 STORE_IO;
783 STM_LOOP_END;
784 break;
785 case REGION_PALETTE_RAM:
786 STM_LOOP_BEGIN;
787 STORE_PALETTE_RAM;
788 STM_LOOP_END;
789 break;
790 case REGION_VRAM:
791 STM_LOOP_BEGIN;
792 STORE_VRAM;
793 STM_LOOP_END;
794 break;
795 case REGION_OAM:
796 STM_LOOP_BEGIN;
797 STORE_OAM;
798 STM_LOOP_END;
799 break;
800 case REGION_CART0:
801 case REGION_CART0_EX:
802 case REGION_CART1:
803 case REGION_CART1_EX:
804 case REGION_CART2:
805 case REGION_CART2_EX:
806 STM_LOOP_BEGIN;
807 STORE_CART;
808 STM_LOOP_END;
809 break;
810 case REGION_CART_SRAM:
811 case REGION_CART_SRAM_MIRROR:
812 STM_LOOP_BEGIN;
813 STORE_SRAM;
814 STM_LOOP_END;
815 break;
816 default:
817 STM_LOOP_BEGIN;
818 STORE_BAD;
819 STM_LOOP_END;
820 break;
821 }
822
823 if (cycleCounter) {
824 *cycleCounter += wait;
825 }
826
827 if (direction & LSM_B) {
828 address -= offset;
829 }
830
831 if (direction & LSM_D) {
832 address -= (popcount << 2) + 4;
833 }
834
835 return address;
836}
837
838void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
839 struct GBAMemory* memory = &gba->memory;
840 struct ARMCore* cpu = gba->cpu;
841 int sram = parameters & 0x0003;
842 int ws0 = (parameters & 0x000C) >> 2;
843 int ws0seq = (parameters & 0x0010) >> 4;
844 int ws1 = (parameters & 0x0060) >> 5;
845 int ws1seq = (parameters & 0x0080) >> 7;
846 int ws2 = (parameters & 0x0300) >> 8;
847 int ws2seq = (parameters & 0x0400) >> 10;
848 int prefetch = parameters & 0x4000;
849
850 memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
851 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
852 memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
853 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
854
855 memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
856 memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
857 memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
858
859 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
860 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
861 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
862
863 memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
864 memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
865 memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
866
867 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
868 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
869 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
870
871 if (!prefetch) {
872 memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0];
873 memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1];
874 memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2];
875
876 memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = memory->waitstatesSeq32[REGION_CART0];
877 memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = memory->waitstatesSeq32[REGION_CART1];
878 memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = memory->waitstatesSeq32[REGION_CART2];
879
880 memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0];
881 memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1];
882 memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2];
883
884 memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq32[REGION_CART0];
885 memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq32[REGION_CART1];
886 memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq32[REGION_CART2];
887 } else {
888 memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = 0;
889 memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = 0;
890 memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = 0;
891
892 memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = 0;
893 memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = 0;
894 memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = 0;
895
896 memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = 0;
897 memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = 0;
898 memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = 0;
899
900 memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = 0;
901 memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = 0;
902 memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = 0;
903 }
904
905 cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
906 cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
907
908 cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
909 cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
910
911 cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
912 cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
913}
914
915void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
916 struct GBAMemory* memory = &gba->memory;
917 memory->dma[dma].source = address & 0xFFFFFFFE;
918}
919
920void GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
921 struct GBAMemory* memory = &gba->memory;
922 memory->dma[dma].dest = address & 0xFFFFFFFE;
923}
924
925void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
926 struct GBAMemory* memory = &gba->memory;
927 memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
928}
929
930uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
931 struct GBAMemory* memory = &gba->memory;
932 struct GBADMA* currentDma = &memory->dma[dma];
933 int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
934 currentDma->reg = control;
935
936 if (GBADMARegisterIsDRQ(currentDma->reg)) {
937 GBALog(gba, GBA_LOG_STUB, "DRQ not implemented");
938 }
939
940 if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
941 currentDma->nextSource = currentDma->source;
942 currentDma->nextDest = currentDma->dest;
943 currentDma->nextCount = currentDma->count;
944 GBAMemoryScheduleDMA(gba, dma, currentDma);
945 }
946 // If the DMA has already occurred, this value might have changed since the function started
947 return currentDma->reg;
948};
949
950void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
951 struct ARMCore* cpu = gba->cpu;
952 switch (GBADMARegisterGetTiming(info->reg)) {
953 case DMA_TIMING_NOW:
954 info->nextEvent = cpu->cycles;
955 GBAMemoryUpdateDMAs(gba, 0);
956 break;
957 case DMA_TIMING_HBLANK:
958 // Handled implicitly
959 info->nextEvent = INT_MAX;
960 break;
961 case DMA_TIMING_VBLANK:
962 // Handled implicitly
963 info->nextEvent = INT_MAX;
964 break;
965 case DMA_TIMING_CUSTOM:
966 info->nextEvent = INT_MAX;
967 switch (number) {
968 case 0:
969 GBALog(gba, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
970 break;
971 case 1:
972 case 2:
973 GBAAudioScheduleFifoDma(&gba->audio, number, info);
974 break;
975 case 3:
976 // GBAVideoScheduleVCaptureDma(dma, info);
977 break;
978 }
979 }
980}
981
982void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
983 struct GBAMemory* memory = &gba->memory;
984 struct GBADMA* dma;
985 int i;
986 for (i = 0; i < 4; ++i) {
987 dma = &memory->dma[i];
988 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK) {
989 dma->nextEvent = cycles;
990 }
991 }
992 GBAMemoryUpdateDMAs(gba, 0);
993}
994
995void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
996 struct GBAMemory* memory = &gba->memory;
997 struct GBADMA* dma;
998 int i;
999 for (i = 0; i < 4; ++i) {
1000 dma = &memory->dma[i];
1001 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK) {
1002 dma->nextEvent = cycles;
1003 }
1004 }
1005 GBAMemoryUpdateDMAs(gba, 0);
1006}
1007
1008int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
1009 struct GBAMemory* memory = &gba->memory;
1010 if (memory->nextDMA == INT_MAX) {
1011 return INT_MAX;
1012 }
1013 memory->nextDMA -= cycles;
1014 memory->eventDiff += cycles;
1015 if (memory->nextDMA <= 0) {
1016 struct GBADMA* dma = &memory->dma[memory->activeDMA];
1017 GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
1018 GBAMemoryUpdateDMAs(gba, memory->eventDiff);
1019 memory->eventDiff = 0;
1020 }
1021 return memory->nextDMA;
1022}
1023
1024void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
1025 int i;
1026 struct GBAMemory* memory = &gba->memory;
1027 struct ARMCore* cpu = gba->cpu;
1028 memory->activeDMA = -1;
1029 memory->nextDMA = INT_MAX;
1030 for (i = 3; i >= 0; --i) {
1031 struct GBADMA* dma = &memory->dma[i];
1032 if (dma->nextEvent != INT_MAX) {
1033 dma->nextEvent -= cycles;
1034 if (GBADMARegisterIsEnable(dma->reg)) {
1035 memory->activeDMA = i;
1036 memory->nextDMA = dma->nextEvent;
1037 }
1038 }
1039 }
1040 if (memory->nextDMA < cpu->nextEvent) {
1041 cpu->nextEvent = memory->nextDMA;
1042 }
1043}
1044
1045void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
1046 struct GBAMemory* memory = &gba->memory;
1047 struct ARMCore* cpu = gba->cpu;
1048 uint32_t width = GBADMARegisterGetWidth(info->reg) ? 4 : 2;
1049 int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
1050 int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width;
1051 int32_t wordsRemaining = info->nextCount;
1052 uint32_t source = info->nextSource;
1053 uint32_t dest = info->nextDest;
1054 uint32_t sourceRegion = source >> BASE_OFFSET;
1055 uint32_t destRegion = dest >> BASE_OFFSET;
1056 int32_t cycles = 0;
1057
1058 if (source == info->source) {
1059 // TODO: support 4 cycles for ROM access
1060 cycles += 2;
1061 if (width == 4) {
1062 cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
1063 source &= 0xFFFFFFFC;
1064 dest &= 0xFFFFFFFC;
1065 } else {
1066 cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
1067 }
1068 } else {
1069 if (width == 4) {
1070 cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
1071 } else {
1072 cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
1073 }
1074 }
1075
1076 if (width == 4) {
1077 int32_t word;
1078 word = cpu->memory.load32(cpu, source, 0);
1079 cpu->memory.store32(cpu, dest, word, 0);
1080 source += sourceOffset;
1081 dest += destOffset;
1082 --wordsRemaining;
1083 } else {
1084 uint16_t word;
1085 if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
1086 word = GBASavedataReadEEPROM(&memory->savedata);
1087 cpu->memory.store16(cpu, dest, word, 0);
1088 source += sourceOffset;
1089 dest += destOffset;
1090 --wordsRemaining;
1091 } else if (destRegion == REGION_CART2_EX) {
1092 if (memory->savedata.type == SAVEDATA_NONE) {
1093 GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
1094 GBASavedataInitEEPROM(&memory->savedata);
1095 }
1096 word = cpu->memory.load16(cpu, source, 0);
1097 GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
1098 source += sourceOffset;
1099 dest += destOffset;
1100 --wordsRemaining;
1101 } else {
1102 word = cpu->memory.load16(cpu, source, 0);
1103 cpu->memory.store16(cpu, dest, word, 0);
1104 source += sourceOffset;
1105 dest += destOffset;
1106 --wordsRemaining;
1107 }
1108 }
1109
1110 if (!wordsRemaining) {
1111 if (!GBADMARegisterIsRepeat(info->reg)) {
1112 info->reg = GBADMARegisterClearEnable(info->reg);
1113 info->nextEvent = INT_MAX;
1114
1115 // Clear the enable bit in memory
1116 memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
1117 } else {
1118 info->nextCount = info->count;
1119 if (GBADMARegisterGetDestControl(info->reg) == DMA_INCREMENT_RELOAD) {
1120 info->nextDest = info->dest;
1121 }
1122 GBAMemoryScheduleDMA(gba, number, info);
1123 }
1124 if (GBADMARegisterIsDoIRQ(info->reg)) {
1125 GBARaiseIRQ(gba, IRQ_DMA0 + number);
1126 }
1127 } else {
1128 info->nextDest = dest;
1129 info->nextCount = wordsRemaining;
1130 }
1131 info->nextSource = source;
1132
1133 if (info->nextEvent != INT_MAX) {
1134 info->nextEvent += cycles;
1135 }
1136 cpu->cycles += cycles;
1137}
1138
1139void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {
1140 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1141 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1142}
1143
1144void GBAMemoryDeserialize(struct GBAMemory* memory, struct GBASerializedState* state) {
1145 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1146 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1147}
1148
1149uint32_t _popcount32(unsigned bits) {
1150 bits = bits - ((bits >> 1) & 0x55555555);
1151 bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
1152 return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
1153}