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