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