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_BIOS:
684 LDM_LOOP_BEGIN;
685 LOAD_BIOS;
686 LDM_LOOP_END;
687 break;
688 case REGION_WORKING_RAM:
689 LDM_LOOP_BEGIN;
690 LOAD_WORKING_RAM;
691 LDM_LOOP_END;
692 break;
693 case REGION_WORKING_IRAM:
694 LDM_LOOP_BEGIN;
695 LOAD_WORKING_IRAM;
696 LDM_LOOP_END;
697 break;
698 case REGION_IO:
699 LDM_LOOP_BEGIN;
700 LOAD_IO;
701 LDM_LOOP_END;
702 break;
703 case REGION_PALETTE_RAM:
704 LDM_LOOP_BEGIN;
705 LOAD_PALETTE_RAM;
706 LDM_LOOP_END;
707 break;
708 case REGION_VRAM:
709 LDM_LOOP_BEGIN;
710 LOAD_VRAM;
711 LDM_LOOP_END;
712 break;
713 case REGION_OAM:
714 LDM_LOOP_BEGIN;
715 LOAD_OAM;
716 LDM_LOOP_END;
717 break;
718 case REGION_CART0:
719 case REGION_CART0_EX:
720 case REGION_CART1:
721 case REGION_CART1_EX:
722 case REGION_CART2:
723 case REGION_CART2_EX:
724 LDM_LOOP_BEGIN;
725 LOAD_CART;
726 LDM_LOOP_END;
727 break;
728 case REGION_CART_SRAM:
729 case REGION_CART_SRAM_MIRROR:
730 LDM_LOOP_BEGIN;
731 LOAD_SRAM;
732 LDM_LOOP_END;
733 break;
734 default:
735 LDM_LOOP_BEGIN;
736 LOAD_BAD;
737 LDM_LOOP_END;
738 break;
739 }
740
741 if (cycleCounter) {
742 *cycleCounter += wait;
743 }
744
745 if (direction & LSM_B) {
746 address -= offset;
747 }
748
749 if (direction & LSM_D) {
750 address -= (popcount << 2) + 4;
751 }
752
753 return address | addressMisalign;
754}
755
756#define STM_LOOP_BEGIN \
757 for (i = 0; i < 16; ++i) { \
758 if (!(mask & (1 << i))) { \
759 continue; \
760 } \
761 value = cpu->gprs[i];
762
763#define STM_LOOP_END \
764 waitstatesRegion = memory->waitstatesSeq32; \
765 ++wait; \
766 address += 4; \
767 }
768
769uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
770 struct GBA* gba = (struct GBA*) cpu->master;
771 struct GBAMemory* memory = &gba->memory;
772 uint32_t value;
773 int wait = 0;
774 char* waitstatesRegion = memory->waitstatesNonseq32;
775
776 int i;
777 int offset = 4;
778 int popcount = 0;
779 if (direction & LSM_D) {
780 offset = -4;
781 popcount = _popcount32(mask);
782 address -= (popcount << 2) - 4;
783 }
784
785 if (direction & LSM_B) {
786 address += offset;
787 }
788
789 uint32_t addressMisalign = address & 0x3;
790 address &= 0xFFFFFFFC;
791
792 switch (address >> BASE_OFFSET) {
793 case REGION_WORKING_RAM:
794 STM_LOOP_BEGIN;
795 STORE_WORKING_RAM;
796 STM_LOOP_END;
797 break;
798 case REGION_WORKING_IRAM:
799 STM_LOOP_BEGIN;
800 STORE_WORKING_IRAM;
801 STM_LOOP_END;
802 break;
803 case REGION_IO:
804 STM_LOOP_BEGIN;
805 STORE_IO;
806 STM_LOOP_END;
807 break;
808 case REGION_PALETTE_RAM:
809 STM_LOOP_BEGIN;
810 STORE_PALETTE_RAM;
811 STM_LOOP_END;
812 break;
813 case REGION_VRAM:
814 STM_LOOP_BEGIN;
815 STORE_VRAM;
816 STM_LOOP_END;
817 break;
818 case REGION_OAM:
819 STM_LOOP_BEGIN;
820 STORE_OAM;
821 STM_LOOP_END;
822 break;
823 case REGION_CART0:
824 case REGION_CART0_EX:
825 case REGION_CART1:
826 case REGION_CART1_EX:
827 case REGION_CART2:
828 case REGION_CART2_EX:
829 STM_LOOP_BEGIN;
830 STORE_CART;
831 STM_LOOP_END;
832 break;
833 case REGION_CART_SRAM:
834 case REGION_CART_SRAM_MIRROR:
835 STM_LOOP_BEGIN;
836 STORE_SRAM;
837 STM_LOOP_END;
838 break;
839 default:
840 STM_LOOP_BEGIN;
841 STORE_BAD;
842 STM_LOOP_END;
843 break;
844 }
845
846 if (cycleCounter) {
847 *cycleCounter += wait;
848 }
849
850 if (direction & LSM_B) {
851 address -= offset;
852 }
853
854 if (direction & LSM_D) {
855 address -= (popcount << 2) + 4;
856 }
857
858 return address | addressMisalign;
859}
860
861void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
862 struct GBAMemory* memory = &gba->memory;
863 struct ARMCore* cpu = gba->cpu;
864 int sram = parameters & 0x0003;
865 int ws0 = (parameters & 0x000C) >> 2;
866 int ws0seq = (parameters & 0x0010) >> 4;
867 int ws1 = (parameters & 0x0060) >> 5;
868 int ws1seq = (parameters & 0x0080) >> 7;
869 int ws2 = (parameters & 0x0300) >> 8;
870 int ws2seq = (parameters & 0x0400) >> 10;
871 int prefetch = parameters & 0x4000;
872
873 memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
874 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
875 memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
876 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
877
878 memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
879 memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
880 memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
881
882 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
883 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
884 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
885
886 memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
887 memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
888 memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
889
890 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
891 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
892 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
893
894 if (!prefetch) {
895 memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0];
896 memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1];
897 memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2];
898
899 memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = memory->waitstatesSeq32[REGION_CART0];
900 memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = memory->waitstatesSeq32[REGION_CART1];
901 memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = memory->waitstatesSeq32[REGION_CART2];
902
903 memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0];
904 memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1];
905 memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2];
906
907 memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq32[REGION_CART0];
908 memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq32[REGION_CART1];
909 memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq32[REGION_CART2];
910 } else {
911 memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = 0;
912 memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = 0;
913 memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = 0;
914
915 memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = 0;
916 memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = 0;
917 memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = 0;
918
919 memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = 0;
920 memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = 0;
921 memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = 0;
922
923 memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = 0;
924 memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = 0;
925 memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = 0;
926 }
927
928 cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
929 cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
930
931 cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
932 cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
933
934 cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
935 cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
936}
937
938void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
939 struct GBAMemory* memory = &gba->memory;
940 memory->dma[dma].source = address & 0xFFFFFFFE;
941}
942
943void GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
944 struct GBAMemory* memory = &gba->memory;
945 memory->dma[dma].dest = address & 0xFFFFFFFE;
946}
947
948void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
949 struct GBAMemory* memory = &gba->memory;
950 memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
951}
952
953uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
954 struct GBAMemory* memory = &gba->memory;
955 struct GBADMA* currentDma = &memory->dma[dma];
956 int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
957 currentDma->reg = control;
958
959 if (GBADMARegisterIsDRQ(currentDma->reg)) {
960 GBALog(gba, GBA_LOG_STUB, "DRQ not implemented");
961 }
962
963 if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
964 currentDma->nextSource = currentDma->source;
965 currentDma->nextDest = currentDma->dest;
966 currentDma->nextCount = currentDma->count;
967 GBAMemoryScheduleDMA(gba, dma, currentDma);
968 }
969 // If the DMA has already occurred, this value might have changed since the function started
970 return currentDma->reg;
971};
972
973void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
974 struct ARMCore* cpu = gba->cpu;
975 switch (GBADMARegisterGetTiming(info->reg)) {
976 case DMA_TIMING_NOW:
977 info->nextEvent = cpu->cycles;
978 GBAMemoryUpdateDMAs(gba, 0);
979 break;
980 case DMA_TIMING_HBLANK:
981 // Handled implicitly
982 info->nextEvent = INT_MAX;
983 break;
984 case DMA_TIMING_VBLANK:
985 // Handled implicitly
986 info->nextEvent = INT_MAX;
987 break;
988 case DMA_TIMING_CUSTOM:
989 info->nextEvent = INT_MAX;
990 switch (number) {
991 case 0:
992 GBALog(gba, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
993 break;
994 case 1:
995 case 2:
996 GBAAudioScheduleFifoDma(&gba->audio, number, info);
997 break;
998 case 3:
999 // GBAVideoScheduleVCaptureDma(dma, info);
1000 break;
1001 }
1002 }
1003}
1004
1005void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
1006 struct GBAMemory* memory = &gba->memory;
1007 struct GBADMA* dma;
1008 int i;
1009 for (i = 0; i < 4; ++i) {
1010 dma = &memory->dma[i];
1011 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK) {
1012 dma->nextEvent = cycles;
1013 }
1014 }
1015 GBAMemoryUpdateDMAs(gba, 0);
1016}
1017
1018void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
1019 struct GBAMemory* memory = &gba->memory;
1020 struct GBADMA* dma;
1021 int i;
1022 for (i = 0; i < 4; ++i) {
1023 dma = &memory->dma[i];
1024 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK) {
1025 dma->nextEvent = cycles;
1026 }
1027 }
1028 GBAMemoryUpdateDMAs(gba, 0);
1029}
1030
1031int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
1032 struct GBAMemory* memory = &gba->memory;
1033 if (memory->nextDMA == INT_MAX) {
1034 return INT_MAX;
1035 }
1036 memory->nextDMA -= cycles;
1037 memory->eventDiff += cycles;
1038 if (memory->nextDMA <= 0) {
1039 struct GBADMA* dma = &memory->dma[memory->activeDMA];
1040 GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
1041 GBAMemoryUpdateDMAs(gba, memory->eventDiff);
1042 memory->eventDiff = 0;
1043 }
1044 return memory->nextDMA;
1045}
1046
1047void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
1048 int i;
1049 struct GBAMemory* memory = &gba->memory;
1050 struct ARMCore* cpu = gba->cpu;
1051 memory->activeDMA = -1;
1052 memory->nextDMA = INT_MAX;
1053 for (i = 3; i >= 0; --i) {
1054 struct GBADMA* dma = &memory->dma[i];
1055 if (dma->nextEvent != INT_MAX) {
1056 dma->nextEvent -= cycles;
1057 if (GBADMARegisterIsEnable(dma->reg)) {
1058 memory->activeDMA = i;
1059 memory->nextDMA = dma->nextEvent;
1060 }
1061 }
1062 }
1063 if (memory->nextDMA < cpu->nextEvent) {
1064 cpu->nextEvent = memory->nextDMA;
1065 }
1066}
1067
1068void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
1069 struct GBAMemory* memory = &gba->memory;
1070 struct ARMCore* cpu = gba->cpu;
1071 uint32_t width = GBADMARegisterGetWidth(info->reg) ? 4 : 2;
1072 int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
1073 int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width;
1074 int32_t wordsRemaining = info->nextCount;
1075 uint32_t source = info->nextSource;
1076 uint32_t dest = info->nextDest;
1077 uint32_t sourceRegion = source >> BASE_OFFSET;
1078 uint32_t destRegion = dest >> BASE_OFFSET;
1079 int32_t cycles = 0;
1080
1081 if (source == info->source) {
1082 // TODO: support 4 cycles for ROM access
1083 cycles += 2;
1084 if (width == 4) {
1085 cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
1086 source &= 0xFFFFFFFC;
1087 dest &= 0xFFFFFFFC;
1088 } else {
1089 cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
1090 }
1091 } else {
1092 if (width == 4) {
1093 cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
1094 } else {
1095 cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
1096 }
1097 }
1098
1099 if (width == 4) {
1100 int32_t word;
1101 word = cpu->memory.load32(cpu, source, 0);
1102 cpu->memory.store32(cpu, dest, word, 0);
1103 source += sourceOffset;
1104 dest += destOffset;
1105 --wordsRemaining;
1106 } else {
1107 uint16_t word;
1108 if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
1109 word = GBASavedataReadEEPROM(&memory->savedata);
1110 cpu->memory.store16(cpu, dest, word, 0);
1111 source += sourceOffset;
1112 dest += destOffset;
1113 --wordsRemaining;
1114 } else if (destRegion == REGION_CART2_EX) {
1115 if (memory->savedata.type == SAVEDATA_NONE) {
1116 GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
1117 GBASavedataInitEEPROM(&memory->savedata);
1118 }
1119 word = cpu->memory.load16(cpu, source, 0);
1120 GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
1121 source += sourceOffset;
1122 dest += destOffset;
1123 --wordsRemaining;
1124 } else {
1125 word = cpu->memory.load16(cpu, source, 0);
1126 cpu->memory.store16(cpu, dest, word, 0);
1127 source += sourceOffset;
1128 dest += destOffset;
1129 --wordsRemaining;
1130 }
1131 }
1132
1133 if (!wordsRemaining) {
1134 if (!GBADMARegisterIsRepeat(info->reg)) {
1135 info->reg = GBADMARegisterClearEnable(info->reg);
1136 info->nextEvent = INT_MAX;
1137
1138 // Clear the enable bit in memory
1139 memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
1140 } else {
1141 info->nextCount = info->count;
1142 if (GBADMARegisterGetDestControl(info->reg) == DMA_INCREMENT_RELOAD) {
1143 info->nextDest = info->dest;
1144 }
1145 GBAMemoryScheduleDMA(gba, number, info);
1146 }
1147 if (GBADMARegisterIsDoIRQ(info->reg)) {
1148 GBARaiseIRQ(gba, IRQ_DMA0 + number);
1149 }
1150 } else {
1151 info->nextDest = dest;
1152 info->nextCount = wordsRemaining;
1153 }
1154 info->nextSource = source;
1155
1156 if (info->nextEvent != INT_MAX) {
1157 info->nextEvent += cycles;
1158 }
1159 cpu->cycles += cycles;
1160}
1161
1162void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {
1163 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1164 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1165}
1166
1167void GBAMemoryDeserialize(struct GBAMemory* memory, struct GBASerializedState* state) {
1168 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1169 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1170}
1171
1172uint32_t _popcount32(unsigned bits) {
1173 bits = bits - ((bits >> 1) & 0x55555555);
1174 bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
1175 return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
1176}