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