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