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