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