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