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