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