src/gba/memory.c (view raw)
1/* Copyright (c) 2013-2015 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 "memory.h"
7
8#include "macros.h"
9
10#include "decoder.h"
11#include "gba/hardware.h"
12#include "gba/io.h"
13#include "gba/serialize.h"
14#include "gba/hle-bios.h"
15#include "util/math.h"
16#include "util/memory.h"
17
18#define IDLE_LOOP_THRESHOLD 10000
19
20mLOG_DEFINE_CATEGORY(GBA_MEM, "GBA Memory");
21
22static void _pristineCow(struct GBA* gba);
23static uint32_t _deadbeef[1] = { 0xE710B710 }; // Illegal instruction on both ARM and Thumb
24
25static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
26static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
27static int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait);
28
29static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
30static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 9 };
31static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 };
32static const char GBA_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 9 };
33static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
34static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
35static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
36
37void GBAMemoryInit(struct GBA* gba) {
38 struct ARMCore* cpu = gba->cpu;
39 cpu->memory.load32 = GBALoad32;
40 cpu->memory.load16 = GBALoad16;
41 cpu->memory.load8 = GBALoad8;
42 cpu->memory.loadMultiple = GBALoadMultiple;
43 cpu->memory.store32 = GBAStore32;
44 cpu->memory.store16 = GBAStore16;
45 cpu->memory.store8 = GBAStore8;
46 cpu->memory.storeMultiple = GBAStoreMultiple;
47 cpu->memory.stall = GBAMemoryStall;
48
49 gba->memory.bios = (uint32_t*) hleBios;
50 gba->memory.fullBios = 0;
51 gba->memory.wram = 0;
52 gba->memory.iwram = 0;
53 gba->memory.rom = 0;
54 gba->memory.romSize = 0;
55 gba->memory.romMask = 0;
56 gba->memory.hw.p = gba;
57
58 int i;
59 for (i = 0; i < 16; ++i) {
60 gba->memory.waitstatesNonseq16[i] = GBA_BASE_WAITSTATES[i];
61 gba->memory.waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
62 gba->memory.waitstatesPrefetchNonseq16[i] = GBA_BASE_WAITSTATES[i];
63 gba->memory.waitstatesPrefetchSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
64 gba->memory.waitstatesNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
65 gba->memory.waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
66 gba->memory.waitstatesPrefetchNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
67 gba->memory.waitstatesPrefetchSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
68 }
69 for (; i < 256; ++i) {
70 gba->memory.waitstatesNonseq16[i] = 0;
71 gba->memory.waitstatesSeq16[i] = 0;
72 gba->memory.waitstatesNonseq32[i] = 0;
73 gba->memory.waitstatesSeq32[i] = 0;
74 }
75
76 gba->memory.activeRegion = -1;
77 cpu->memory.activeRegion = 0;
78 cpu->memory.activeMask = 0;
79 cpu->memory.setActiveRegion = GBASetActiveRegion;
80 cpu->memory.activeSeqCycles32 = 0;
81 cpu->memory.activeSeqCycles16 = 0;
82 cpu->memory.activeNonseqCycles32 = 0;
83 cpu->memory.activeNonseqCycles16 = 0;
84 gba->memory.biosPrefetch = 0;
85}
86
87void GBAMemoryDeinit(struct GBA* gba) {
88 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
89 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
90 if (gba->memory.rom) {
91 mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
92 }
93 GBASavedataDeinit(&gba->memory.savedata);
94}
95
96void GBAMemoryReset(struct GBA* gba) {
97 if (gba->memory.wram) {
98 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
99 }
100 gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
101 if (gba->pristineRom && !gba->memory.rom) {
102 // Multiboot
103 memcpy(gba->memory.wram, gba->pristineRom, gba->pristineRomSize);
104 }
105
106 if (gba->memory.iwram) {
107 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
108 }
109 gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
110
111 memset(gba->memory.io, 0, sizeof(gba->memory.io));
112 memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
113 int i;
114 for (i = 0; i < 4; ++i) {
115 gba->memory.dma[i].count = 0x4000;
116 gba->memory.dma[i].nextEvent = INT_MAX;
117 }
118 gba->memory.dma[3].count = 0x10000;
119 gba->memory.activeDMA = -1;
120 gba->memory.nextDMA = INT_MAX;
121 gba->memory.eventDiff = 0;
122
123 gba->memory.prefetch = false;
124 gba->memory.lastPrefetchedPc = 0;
125
126 if (!gba->memory.wram || !gba->memory.iwram) {
127 GBAMemoryDeinit(gba);
128 mLOG(GBA_MEM, FATAL, "Could not map memory");
129 }
130}
131
132static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t address) {
133 struct ARMInstructionInfo info;
134 uint32_t nextAddress = address;
135 memset(gba->taintedRegisters, 0, sizeof(gba->taintedRegisters));
136 if (cpu->executionMode == MODE_THUMB) {
137 while (true) {
138 uint16_t opcode;
139 LOAD_16(opcode, nextAddress & cpu->memory.activeMask, cpu->memory.activeRegion);
140 ARMDecodeThumb(opcode, &info);
141 switch (info.branchType) {
142 case ARM_BRANCH_NONE:
143 if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
144 if (info.mnemonic == ARM_MN_STR || gba->taintedRegisters[info.memory.baseReg]) {
145 gba->idleDetectionStep = -1;
146 return;
147 }
148 uint32_t loadAddress = gba->cachedRegisters[info.memory.baseReg];
149 uint32_t offset = 0;
150 if (info.memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
151 offset = info.memory.offset.immediate;
152 } else if (info.memory.format & ARM_MEMORY_REGISTER_OFFSET) {
153 int reg = info.memory.offset.reg;
154 if (gba->cachedRegisters[reg]) {
155 gba->idleDetectionStep = -1;
156 return;
157 }
158 offset = gba->cachedRegisters[reg];
159 }
160 if (info.memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
161 loadAddress -= offset;
162 } else {
163 loadAddress += offset;
164 }
165 if ((loadAddress >> BASE_OFFSET) == REGION_IO && !GBAIOIsReadConstant(loadAddress)) {
166 gba->idleDetectionStep = -1;
167 return;
168 }
169 if ((loadAddress >> BASE_OFFSET) < REGION_CART0 || (loadAddress >> BASE_OFFSET) > REGION_CART2_EX) {
170 gba->taintedRegisters[info.op1.reg] = true;
171 } else {
172 switch (info.memory.width) {
173 case 1:
174 gba->cachedRegisters[info.op1.reg] = GBALoad8(cpu, loadAddress, 0);
175 break;
176 case 2:
177 gba->cachedRegisters[info.op1.reg] = GBALoad16(cpu, loadAddress, 0);
178 break;
179 case 4:
180 gba->cachedRegisters[info.op1.reg] = GBALoad32(cpu, loadAddress, 0);
181 break;
182 }
183 }
184 } else if (info.operandFormat & ARM_OPERAND_AFFECTED_1) {
185 gba->taintedRegisters[info.op1.reg] = true;
186 }
187 nextAddress += WORD_SIZE_THUMB;
188 break;
189 case ARM_BRANCH:
190 if ((uint32_t) info.op1.immediate + nextAddress + WORD_SIZE_THUMB * 2 == address) {
191 gba->idleLoop = address;
192 gba->idleOptimization = IDLE_LOOP_REMOVE;
193 }
194 gba->idleDetectionStep = -1;
195 return;
196 default:
197 gba->idleDetectionStep = -1;
198 return;
199 }
200 }
201 } else {
202 gba->idleDetectionStep = -1;
203 }
204}
205
206static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
207 struct GBA* gba = (struct GBA*) cpu->master;
208 struct GBAMemory* memory = &gba->memory;
209
210 int newRegion = address >> BASE_OFFSET;
211 if (gba->idleOptimization >= IDLE_LOOP_REMOVE && memory->activeRegion != REGION_BIOS) {
212 if (address == gba->idleLoop) {
213 if (gba->haltPending) {
214 gba->haltPending = false;
215 GBAHalt(gba);
216 } else {
217 gba->haltPending = true;
218 }
219 } else if (gba->idleOptimization >= IDLE_LOOP_DETECT && newRegion == memory->activeRegion) {
220 if (address == gba->lastJump) {
221 switch (gba->idleDetectionStep) {
222 case 0:
223 memcpy(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters));
224 ++gba->idleDetectionStep;
225 break;
226 case 1:
227 if (memcmp(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters))) {
228 gba->idleDetectionStep = -1;
229 ++gba->idleDetectionFailures;
230 if (gba->idleDetectionFailures > IDLE_LOOP_THRESHOLD) {
231 gba->idleOptimization = IDLE_LOOP_IGNORE;
232 }
233 break;
234 }
235 _analyzeForIdleLoop(gba, cpu, address);
236 break;
237 }
238 } else {
239 gba->idleDetectionStep = 0;
240 }
241 }
242 }
243
244 gba->lastJump = address;
245 memory->lastPrefetchedPc = 0;
246 memory->lastPrefetchedLoads = 0;
247 if (newRegion == memory->activeRegion && (newRegion < REGION_CART0 || (address & (SIZE_CART0 - 1)) < memory->romSize)) {
248 return;
249 }
250
251 if (memory->activeRegion == REGION_BIOS) {
252 memory->biosPrefetch = cpu->prefetch[1];
253 }
254 memory->activeRegion = newRegion;
255 switch (newRegion) {
256 case REGION_BIOS:
257 cpu->memory.activeRegion = memory->bios;
258 cpu->memory.activeMask = SIZE_BIOS - 1;
259 break;
260 case REGION_WORKING_RAM:
261 cpu->memory.activeRegion = memory->wram;
262 cpu->memory.activeMask = SIZE_WORKING_RAM - 1;
263 break;
264 case REGION_WORKING_IRAM:
265 cpu->memory.activeRegion = memory->iwram;
266 cpu->memory.activeMask = SIZE_WORKING_IRAM - 1;
267 break;
268 case REGION_PALETTE_RAM:
269 cpu->memory.activeRegion = (uint32_t*) gba->video.palette;
270 cpu->memory.activeMask = SIZE_PALETTE_RAM - 1;
271 break;
272 case REGION_VRAM:
273 cpu->memory.activeRegion = (uint32_t*) gba->video.renderer->vram;
274 cpu->memory.activeMask = 0x0000FFFF;
275 break;
276 case REGION_OAM:
277 cpu->memory.activeRegion = (uint32_t*) gba->video.oam.raw;
278 cpu->memory.activeMask = SIZE_OAM - 1;
279 break;
280 case REGION_CART0:
281 case REGION_CART0_EX:
282 case REGION_CART1:
283 case REGION_CART1_EX:
284 case REGION_CART2:
285 case REGION_CART2_EX:
286 cpu->memory.activeRegion = memory->rom;
287 cpu->memory.activeMask = memory->romMask;
288 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
289 break;
290 }
291 // Fall through
292 default:
293 memory->activeRegion = -1;
294 cpu->memory.activeRegion = _deadbeef;
295 cpu->memory.activeMask = 0;
296 if (gba->yankedRomSize || !gba->hardCrash) {
297 mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address);
298 } else {
299 mLOG(GBA_MEM, FATAL, "Jumped to invalid address: %08X", address);
300 }
301 return;
302 }
303 cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion];
304 cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
305 cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
306 cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
307}
308
309#define LOAD_BAD \
310 if (gba->performingDMA) { \
311 value = gba->bus; \
312 } else { \
313 value = cpu->prefetch[1]; \
314 if (cpu->executionMode == MODE_THUMB) { \
315 /* http://ngemu.com/threads/gba-open-bus.170809/ */ \
316 switch (cpu->gprs[ARM_PC] >> BASE_OFFSET) { \
317 case REGION_BIOS: \
318 case REGION_OAM: \
319 /* This isn't right half the time, but we don't have $+6 handy */ \
320 value <<= 16; \
321 value |= cpu->prefetch[0]; \
322 break; \
323 case REGION_WORKING_IRAM: \
324 /* This doesn't handle prefetch clobbering */ \
325 if (cpu->gprs[ARM_PC] & 2) { \
326 value |= cpu->prefetch[0] << 16; \
327 } else { \
328 value <<= 16; \
329 value |= cpu->prefetch[0]; \
330 } \
331 default: \
332 value |= value << 16; \
333 } \
334 } \
335 }
336
337#define LOAD_BIOS \
338 if (address < SIZE_BIOS) { \
339 if (memory->activeRegion == REGION_BIOS) { \
340 LOAD_32(value, address, memory->bios); \
341 } else { \
342 mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load32: 0x%08X", address); \
343 value = memory->biosPrefetch; \
344 } \
345 } else { \
346 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load32: 0x%08X", address); \
347 LOAD_BAD; \
348 }
349
350#define LOAD_WORKING_RAM \
351 LOAD_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); \
352 wait += waitstatesRegion[REGION_WORKING_RAM];
353
354#define LOAD_WORKING_IRAM LOAD_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
355#define LOAD_IO value = GBAIORead(gba, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gba, (address & (SIZE_IO - 1)) | 2) << 16);
356
357#define LOAD_PALETTE_RAM \
358 LOAD_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
359 wait += waitstatesRegion[REGION_PALETTE_RAM];
360
361#define LOAD_VRAM \
362 if ((address & 0x0001FFFF) < SIZE_VRAM) { \
363 LOAD_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \
364 } else { \
365 LOAD_32(value, address & 0x00017FFC, gba->video.renderer->vram); \
366 } \
367 wait += waitstatesRegion[REGION_VRAM];
368
369#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
370
371#define LOAD_CART \
372 wait += waitstatesRegion[address >> BASE_OFFSET]; \
373 if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \
374 LOAD_32(value, address & (SIZE_CART0 - 4), memory->rom); \
375 } else { \
376 mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load32: 0x%08X", address); \
377 value = ((address & ~3) >> 1) & 0xFFFF; \
378 value |= (((address & ~3) + 2) >> 1) << 16; \
379 }
380
381#define LOAD_SRAM \
382 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; \
383 value = GBALoad8(cpu, address, 0); \
384 value |= value << 8; \
385 value |= value << 16;
386
387uint32_t GBALoadBad(struct ARMCore* cpu) {
388 struct GBA* gba = (struct GBA*) cpu->master;
389 uint32_t value = 0;
390 LOAD_BAD;
391 return value;
392}
393
394uint32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
395 struct GBA* gba = (struct GBA*) cpu->master;
396 struct GBAMemory* memory = &gba->memory;
397 uint32_t value = 0;
398 int wait = 0;
399 char* waitstatesRegion = memory->waitstatesNonseq32;
400
401 switch (address >> BASE_OFFSET) {
402 case REGION_BIOS:
403 LOAD_BIOS;
404 break;
405 case REGION_WORKING_RAM:
406 LOAD_WORKING_RAM;
407 break;
408 case REGION_WORKING_IRAM:
409 LOAD_WORKING_IRAM;
410 break;
411 case REGION_IO:
412 LOAD_IO;
413 break;
414 case REGION_PALETTE_RAM:
415 LOAD_PALETTE_RAM;
416 break;
417 case REGION_VRAM:
418 LOAD_VRAM;
419 break;
420 case REGION_OAM:
421 LOAD_OAM;
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 LOAD_CART;
430 break;
431 case REGION_CART_SRAM:
432 case REGION_CART_SRAM_MIRROR:
433 LOAD_SRAM;
434 break;
435 default:
436 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load32: 0x%08X", address);
437 LOAD_BAD;
438 break;
439 }
440
441 if (cycleCounter) {
442 wait += 2;
443 if (address >> BASE_OFFSET < REGION_CART0) {
444 wait = GBAMemoryStall(cpu, wait);
445 }
446 *cycleCounter += wait;
447 }
448 // Unaligned 32-bit loads are "rotated" so they make some semblance of sense
449 int rotate = (address & 3) << 3;
450 return ROR(value, rotate);
451}
452
453uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
454 struct GBA* gba = (struct GBA*) cpu->master;
455 struct GBAMemory* memory = &gba->memory;
456 uint32_t value = 0;
457 int wait = 0;
458
459 switch (address >> BASE_OFFSET) {
460 case REGION_BIOS:
461 if (address < SIZE_BIOS) {
462 if (memory->activeRegion == REGION_BIOS) {
463 LOAD_16(value, address, memory->bios);
464 } else {
465 mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load16: 0x%08X", address);
466 value = (memory->biosPrefetch >> ((address & 2) * 8)) & 0xFFFF;
467 }
468 } else {
469 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load16: 0x%08X", address);
470 LOAD_BAD;
471 value = (value >> ((address & 2) * 8)) & 0xFFFF;
472 }
473 break;
474 case REGION_WORKING_RAM:
475 LOAD_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
476 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
477 break;
478 case REGION_WORKING_IRAM:
479 LOAD_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
480 break;
481 case REGION_IO:
482 value = GBAIORead(gba, address & (SIZE_IO - 2));
483 break;
484 case REGION_PALETTE_RAM:
485 LOAD_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
486 break;
487 case REGION_VRAM:
488 if ((address & 0x0001FFFF) < SIZE_VRAM) {
489 LOAD_16(value, address & 0x0001FFFE, gba->video.renderer->vram);
490 } else {
491 LOAD_16(value, address & 0x00017FFE, gba->video.renderer->vram);
492 }
493 break;
494 case REGION_OAM:
495 LOAD_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
496 break;
497 case REGION_CART0:
498 case REGION_CART0_EX:
499 case REGION_CART1:
500 case REGION_CART1_EX:
501 case REGION_CART2:
502 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
503 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
504 LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
505 } else {
506 mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address);
507 value = (address >> 1) & 0xFFFF;
508 }
509 break;
510 case REGION_CART2_EX:
511 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
512 if (memory->savedata.type == SAVEDATA_EEPROM) {
513 value = GBASavedataReadEEPROM(&memory->savedata);
514 } else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
515 LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
516 } else {
517 mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address);
518 value = (address >> 1) & 0xFFFF;
519 }
520 break;
521 case REGION_CART_SRAM:
522 case REGION_CART_SRAM_MIRROR:
523 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
524 value = GBALoad8(cpu, address, 0);
525 value |= value << 8;
526 break;
527 default:
528 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load16: 0x%08X", address);
529 LOAD_BAD;
530 value = (value >> ((address & 2) * 8)) & 0xFFFF;
531 break;
532 }
533
534 if (cycleCounter) {
535 wait += 2;
536 if (address >> BASE_OFFSET < REGION_CART0) {
537 wait = GBAMemoryStall(cpu, wait);
538 }
539 *cycleCounter += wait;
540 }
541 // Unaligned 16-bit loads are "unpredictable", but the GBA rotates them, so we have to, too.
542 int rotate = (address & 1) << 3;
543 return ROR(value, rotate);
544}
545
546uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
547 struct GBA* gba = (struct GBA*) cpu->master;
548 struct GBAMemory* memory = &gba->memory;
549 uint32_t value = 0;
550 int wait = 0;
551
552 switch (address >> BASE_OFFSET) {
553 case REGION_BIOS:
554 if (address < SIZE_BIOS) {
555 if (memory->activeRegion == REGION_BIOS) {
556 value = ((uint8_t*) memory->bios)[address];
557 } else {
558 mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
559 value = (memory->biosPrefetch >> ((address & 3) * 8)) & 0xFF;
560 }
561 } else {
562 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load8: 0x%08x", address);
563 LOAD_BAD;
564 value = (value >> ((address & 3) * 8)) & 0xFF;
565 }
566 break;
567 case REGION_WORKING_RAM:
568 value = ((uint8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
569 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
570 break;
571 case REGION_WORKING_IRAM:
572 value = ((uint8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
573 break;
574 case REGION_IO:
575 value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
576 break;
577 case REGION_PALETTE_RAM:
578 value = ((uint8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
579 break;
580 case REGION_VRAM:
581 if ((address & 0x0001FFFF) < SIZE_VRAM) {
582 value = ((uint8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
583 } else {
584 value = ((uint8_t*) gba->video.renderer->vram)[address & 0x00017FFF];
585 }
586 break;
587 case REGION_OAM:
588 value = ((uint8_t*) gba->video.oam.raw)[address & (SIZE_OAM - 1)];
589 break;
590 case REGION_CART0:
591 case REGION_CART0_EX:
592 case REGION_CART1:
593 case REGION_CART1_EX:
594 case REGION_CART2:
595 case REGION_CART2_EX:
596 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
597 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
598 value = ((uint8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
599 } else {
600 mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load8: 0x%08X", address);
601 value = (address >> 1) & 0xFF;
602 }
603 break;
604 case REGION_CART_SRAM:
605 case REGION_CART_SRAM_MIRROR:
606 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
607 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
608 mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
609 GBASavedataInitSRAM(&memory->savedata);
610 }
611 if (gba->performingDMA == 1) {
612 break;
613 }
614 if (memory->savedata.type == SAVEDATA_SRAM) {
615 value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
616 } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
617 value = GBASavedataReadFlash(&memory->savedata, address);
618 } else if (memory->hw.devices & HW_TILT) {
619 value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK);
620 } else {
621 mLOG(GBA_MEM, GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
622 value = 0xFF;
623 }
624 value &= 0xFF;
625 break;
626 default:
627 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load8: 0x%08x", address);
628 LOAD_BAD;
629 value = (value >> ((address & 3) * 8)) & 0xFF;
630 break;
631 }
632
633 if (cycleCounter) {
634 wait += 2;
635 if (address >> BASE_OFFSET < REGION_CART0) {
636 wait = GBAMemoryStall(cpu, wait);
637 }
638 *cycleCounter += wait;
639 }
640 return value;
641}
642
643#define STORE_WORKING_RAM \
644 STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); \
645 wait += waitstatesRegion[REGION_WORKING_RAM];
646
647#define STORE_WORKING_IRAM \
648 STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
649
650#define STORE_IO \
651 GBAIOWrite32(gba, address & (SIZE_IO - 4), value);
652
653#define STORE_PALETTE_RAM \
654 STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
655 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); \
656 wait += waitstatesRegion[REGION_PALETTE_RAM]; \
657 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
658
659#define STORE_VRAM \
660 if ((address & 0x0001FFFF) < SIZE_VRAM) { \
661 STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \
662 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \
663 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \
664 } else { \
665 STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram); \
666 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \
667 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \
668 } \
669 wait += waitstatesRegion[REGION_VRAM];
670
671#define STORE_OAM \
672 STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); \
673 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
674 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
675
676#define STORE_CART \
677 wait += waitstatesRegion[address >> BASE_OFFSET]; \
678 mLOG(GBA_MEM, STUB, "Unimplemented memory Store32: 0x%08X", address);
679
680#define STORE_SRAM \
681 if (address & 0x3) { \
682 mLOG(GBA_MEM, GAME_ERROR, "Unaligned SRAM Store32: 0x%08X", address); \
683 value = 0; \
684 } \
685 GBAStore8(cpu, address & ~0x3, value, cycleCounter); \
686 GBAStore8(cpu, (address & ~0x3) | 1, value, cycleCounter); \
687 GBAStore8(cpu, (address & ~0x3) | 2, value, cycleCounter); \
688 GBAStore8(cpu, (address & ~0x3) | 3, value, cycleCounter);
689
690#define STORE_BAD \
691 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store32: 0x%08X", address);
692
693void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
694 struct GBA* gba = (struct GBA*) cpu->master;
695 struct GBAMemory* memory = &gba->memory;
696 int wait = 0;
697 char* waitstatesRegion = memory->waitstatesNonseq32;
698
699 switch (address >> BASE_OFFSET) {
700 case REGION_WORKING_RAM:
701 STORE_WORKING_RAM;
702 break;
703 case REGION_WORKING_IRAM:
704 STORE_WORKING_IRAM
705 break;
706 case REGION_IO:
707 STORE_IO;
708 break;
709 case REGION_PALETTE_RAM:
710 STORE_PALETTE_RAM;
711 break;
712 case REGION_VRAM:
713 STORE_VRAM;
714 break;
715 case REGION_OAM:
716 STORE_OAM;
717 break;
718 case REGION_CART0:
719 case REGION_CART0_EX:
720 case REGION_CART1:
721 case REGION_CART1_EX:
722 case REGION_CART2:
723 case REGION_CART2_EX:
724 STORE_CART;
725 break;
726 case REGION_CART_SRAM:
727 case REGION_CART_SRAM_MIRROR:
728 STORE_SRAM;
729 break;
730 default:
731 STORE_BAD;
732 break;
733 }
734
735 if (cycleCounter) {
736 ++wait;
737 if (address >> BASE_OFFSET < REGION_CART0) {
738 wait = GBAMemoryStall(cpu, wait);
739 }
740 *cycleCounter += wait;
741 }
742}
743
744void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
745 struct GBA* gba = (struct GBA*) cpu->master;
746 struct GBAMemory* memory = &gba->memory;
747 int wait = 0;
748
749 switch (address >> BASE_OFFSET) {
750 case REGION_WORKING_RAM:
751 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
752 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
753 break;
754 case REGION_WORKING_IRAM:
755 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
756 break;
757 case REGION_IO:
758 GBAIOWrite(gba, address & (SIZE_IO - 2), value);
759 break;
760 case REGION_PALETTE_RAM:
761 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
762 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
763 break;
764 case REGION_VRAM:
765 if ((address & 0x0001FFFF) < SIZE_VRAM) {
766 STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram);
767 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
768 } else {
769 STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram);
770 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE);
771 }
772 break;
773 case REGION_OAM:
774 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
775 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
776 break;
777 case REGION_CART0:
778 if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFE)) {
779 uint32_t reg = address & 0xFFFFFE;
780 GBAHardwareGPIOWrite(&memory->hw, reg, value);
781 } else {
782 mLOG(GBA_MEM, GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
783 }
784 break;
785 case REGION_CART2_EX:
786 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
787 mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
788 GBASavedataInitEEPROM(&memory->savedata);
789 }
790 GBASavedataWriteEEPROM(&memory->savedata, value, 1);
791 break;
792 case REGION_CART_SRAM:
793 case REGION_CART_SRAM_MIRROR:
794 GBAStore8(cpu, (address & ~0x1), value, cycleCounter);
795 GBAStore8(cpu, (address & ~0x1) | 1, value, cycleCounter);
796 break;
797 default:
798 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store16: 0x%08X", address);
799 break;
800 }
801
802 if (cycleCounter) {
803 ++wait;
804 if (address >> BASE_OFFSET < REGION_CART0) {
805 wait = GBAMemoryStall(cpu, wait);
806 }
807 *cycleCounter += wait;
808 }
809}
810
811void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
812 struct GBA* gba = (struct GBA*) cpu->master;
813 struct GBAMemory* memory = &gba->memory;
814 int wait = 0;
815
816 switch (address >> BASE_OFFSET) {
817 case REGION_WORKING_RAM:
818 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
819 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
820 break;
821 case REGION_WORKING_IRAM:
822 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
823 break;
824 case REGION_IO:
825 GBAIOWrite8(gba, address & (SIZE_IO - 1), value);
826 break;
827 case REGION_PALETTE_RAM:
828 GBAStore16(cpu, address & ~1, ((uint8_t) value) | ((uint8_t) value << 8), cycleCounter);
829 break;
830 case REGION_VRAM:
831 if ((address & 0x0001FFFF) >= ((GBARegisterDISPCNTGetMode(gba->memory.io[REG_DISPCNT >> 1]) == 4) ? 0x00014000 : 0x00010000)) {
832 // TODO: check BG mode
833 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
834 break;
835 }
836 gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
837 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
838 break;
839 case REGION_OAM:
840 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
841 break;
842 case REGION_CART0:
843 mLOG(GBA_MEM, STUB, "Unimplemented memory Store8: 0x%08X", address);
844 break;
845 case REGION_CART_SRAM:
846 case REGION_CART_SRAM_MIRROR:
847 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
848 if (address == SAVEDATA_FLASH_BASE) {
849 mLOG(GBA_MEM, INFO, "Detected Flash savegame");
850 GBASavedataInitFlash(&memory->savedata, gba->realisticTiming);
851 } else {
852 mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
853 GBASavedataInitSRAM(&memory->savedata);
854 }
855 }
856 if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
857 GBASavedataWriteFlash(&memory->savedata, address, value);
858 } else if (memory->savedata.type == SAVEDATA_SRAM) {
859 memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
860 memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
861 } else if (memory->hw.devices & HW_TILT) {
862 GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
863 } else {
864 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
865 }
866 wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
867 break;
868 default:
869 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store8: 0x%08X", address);
870 break;
871 }
872
873 if (cycleCounter) {
874 ++wait;
875 if (address >> BASE_OFFSET < REGION_CART0) {
876 wait = GBAMemoryStall(cpu, wait);
877 }
878 *cycleCounter += wait;
879 }
880}
881
882uint32_t GBAView32(struct ARMCore* cpu, uint32_t address) {
883 struct GBA* gba = (struct GBA*) cpu->master;
884 uint32_t value = 0;
885 address &= ~3;
886 switch (address >> BASE_OFFSET) {
887 case REGION_BIOS:
888 if (address < SIZE_BIOS) {
889 LOAD_32(value, address, gba->memory.bios);
890 }
891 break;
892 case REGION_WORKING_RAM:
893 case REGION_WORKING_IRAM:
894 case REGION_PALETTE_RAM:
895 case REGION_VRAM:
896 case REGION_OAM:
897 case REGION_CART0:
898 case REGION_CART0_EX:
899 case REGION_CART1:
900 case REGION_CART1_EX:
901 case REGION_CART2:
902 case REGION_CART2_EX:
903 value = GBALoad32(cpu, address, 0);
904 break;
905 case REGION_IO:
906 if ((address & OFFSET_MASK) < REG_MAX) {
907 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
908 value |= gba->memory.io[((address & OFFSET_MASK) >> 1) + 1] << 16;
909 }
910 break;
911 case REGION_CART_SRAM:
912 value = GBALoad8(cpu, address, 0);
913 value |= GBALoad8(cpu, address + 1, 0) << 8;
914 value |= GBALoad8(cpu, address + 2, 0) << 16;
915 value |= GBALoad8(cpu, address + 3, 0) << 24;
916 break;
917 default:
918 break;
919 }
920 return value;
921}
922
923uint16_t GBAView16(struct ARMCore* cpu, uint32_t address) {
924 struct GBA* gba = (struct GBA*) cpu->master;
925 uint16_t value = 0;
926 address &= ~1;
927 switch (address >> BASE_OFFSET) {
928 case REGION_BIOS:
929 if (address < SIZE_BIOS) {
930 LOAD_16(value, address, gba->memory.bios);
931 }
932 break;
933 case REGION_WORKING_RAM:
934 case REGION_WORKING_IRAM:
935 case REGION_PALETTE_RAM:
936 case REGION_VRAM:
937 case REGION_OAM:
938 case REGION_CART0:
939 case REGION_CART0_EX:
940 case REGION_CART1:
941 case REGION_CART1_EX:
942 case REGION_CART2:
943 case REGION_CART2_EX:
944 value = GBALoad16(cpu, address, 0);
945 break;
946 case REGION_IO:
947 if ((address & OFFSET_MASK) < REG_MAX) {
948 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
949 }
950 break;
951 case REGION_CART_SRAM:
952 value = GBALoad8(cpu, address, 0);
953 value |= GBALoad8(cpu, address + 1, 0) << 8;
954 break;
955 default:
956 break;
957 }
958 return value;
959}
960
961uint8_t GBAView8(struct ARMCore* cpu, uint32_t address) {
962 struct GBA* gba = (struct GBA*) cpu->master;
963 uint8_t value = 0;
964 switch (address >> BASE_OFFSET) {
965 case REGION_BIOS:
966 if (address < SIZE_BIOS) {
967 value = ((uint8_t*) gba->memory.bios)[address];
968 }
969 break;
970 case REGION_WORKING_RAM:
971 case REGION_WORKING_IRAM:
972 case REGION_CART0:
973 case REGION_CART0_EX:
974 case REGION_CART1:
975 case REGION_CART1_EX:
976 case REGION_CART2:
977 case REGION_CART2_EX:
978 case REGION_CART_SRAM:
979 value = GBALoad8(cpu, address, 0);
980 break;
981 case REGION_IO:
982 case REGION_PALETTE_RAM:
983 case REGION_VRAM:
984 case REGION_OAM:
985 value = GBAView16(cpu, address) >> ((address & 1) * 8);
986 break;
987 default:
988 break;
989 }
990 return value;
991}
992
993void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old) {
994 struct GBA* gba = (struct GBA*) cpu->master;
995 struct GBAMemory* memory = &gba->memory;
996 int32_t oldValue = -1;
997
998 switch (address >> BASE_OFFSET) {
999 case REGION_WORKING_RAM:
1000 LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 4), memory->wram);
1001 STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram);
1002 break;
1003 case REGION_WORKING_IRAM:
1004 LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1005 STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1006 break;
1007 case REGION_IO:
1008 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch32: 0x%08X", address);
1009 break;
1010 case REGION_PALETTE_RAM:
1011 LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
1012 STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette);
1013 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
1014 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16);
1015 break;
1016 case REGION_VRAM:
1017 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1018 LOAD_32(oldValue, address & 0x0001FFFC, gba->video.renderer->vram);
1019 STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram);
1020 } else {
1021 LOAD_32(oldValue, address & 0x00017FFC, gba->video.renderer->vram);
1022 STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram);
1023 }
1024 break;
1025 case REGION_OAM:
1026 LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw);
1027 STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
1028 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
1029 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) + 2) >> 1);
1030 break;
1031 case REGION_CART0:
1032 case REGION_CART0_EX:
1033 case REGION_CART1:
1034 case REGION_CART1_EX:
1035 case REGION_CART2:
1036 case REGION_CART2_EX:
1037 _pristineCow(gba);
1038 if ((address & (SIZE_CART0 - 4)) >= gba->memory.romSize) {
1039 gba->memory.romSize = (address & (SIZE_CART0 - 4)) + 4;
1040 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1041 }
1042 LOAD_32(oldValue, address & (SIZE_CART0 - 4), gba->memory.rom);
1043 STORE_32(value, address & (SIZE_CART0 - 4), gba->memory.rom);
1044 break;
1045 case REGION_CART_SRAM:
1046 case REGION_CART_SRAM_MIRROR:
1047 if (memory->savedata.type == SAVEDATA_SRAM) {
1048 LOAD_32(oldValue, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1049 STORE_32(value, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1050 } else {
1051 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1052 }
1053 break;
1054 default:
1055 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1056 break;
1057 }
1058 if (old) {
1059 *old = oldValue;
1060 }
1061}
1062
1063void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old) {
1064 struct GBA* gba = (struct GBA*) cpu->master;
1065 struct GBAMemory* memory = &gba->memory;
1066 int16_t oldValue = -1;
1067
1068 switch (address >> BASE_OFFSET) {
1069 case REGION_WORKING_RAM:
1070 LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 2), memory->wram);
1071 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
1072 break;
1073 case REGION_WORKING_IRAM:
1074 LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1075 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1076 break;
1077 case REGION_IO:
1078 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch16: 0x%08X", address);
1079 break;
1080 case REGION_PALETTE_RAM:
1081 LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1082 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1083 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
1084 break;
1085 case REGION_VRAM:
1086 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1087 LOAD_16(oldValue, address & 0x0001FFFE, gba->video.renderer->vram);
1088 STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram);
1089 } else {
1090 LOAD_16(oldValue, address & 0x00017FFE, gba->video.renderer->vram);
1091 STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram);
1092 }
1093 break;
1094 case REGION_OAM:
1095 LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
1096 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
1097 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
1098 break;
1099 case REGION_CART0:
1100 case REGION_CART0_EX:
1101 case REGION_CART1:
1102 case REGION_CART1_EX:
1103 case REGION_CART2:
1104 case REGION_CART2_EX:
1105 _pristineCow(gba);
1106 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1107 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1108 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1109 }
1110 LOAD_16(oldValue, address & (SIZE_CART0 - 2), gba->memory.rom);
1111 STORE_16(value, address & (SIZE_CART0 - 2), gba->memory.rom);
1112 break;
1113 case REGION_CART_SRAM:
1114 case REGION_CART_SRAM_MIRROR:
1115 if (memory->savedata.type == SAVEDATA_SRAM) {
1116 LOAD_16(oldValue, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1117 STORE_16(value, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1118 } else {
1119 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1120 }
1121 break;
1122 default:
1123 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1124 break;
1125 }
1126 if (old) {
1127 *old = oldValue;
1128 }
1129}
1130
1131void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) {
1132 struct GBA* gba = (struct GBA*) cpu->master;
1133 struct GBAMemory* memory = &gba->memory;
1134 int8_t oldValue = -1;
1135
1136 switch (address >> BASE_OFFSET) {
1137 case REGION_WORKING_RAM:
1138 oldValue = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
1139 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
1140 break;
1141 case REGION_WORKING_IRAM:
1142 oldValue = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
1143 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
1144 break;
1145 case REGION_IO:
1146 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1147 break;
1148 case REGION_PALETTE_RAM:
1149 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1150 break;
1151 case REGION_VRAM:
1152 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1153 break;
1154 case REGION_OAM:
1155 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1156 break;
1157 case REGION_CART0:
1158 case REGION_CART0_EX:
1159 case REGION_CART1:
1160 case REGION_CART1_EX:
1161 case REGION_CART2:
1162 case REGION_CART2_EX:
1163 _pristineCow(gba);
1164 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1165 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1166 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1167 }
1168 oldValue = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
1169 ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)] = value;
1170 break;
1171 case REGION_CART_SRAM:
1172 case REGION_CART_SRAM_MIRROR:
1173 if (memory->savedata.type == SAVEDATA_SRAM) {
1174 oldValue = ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)];
1175 ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)] = value;
1176 } else {
1177 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1178 }
1179 break;
1180 default:
1181 mLOG(GBA_MEM, WARN, "Bad memory Patch8: 0x%08X", address);
1182 break;
1183 }
1184 if (old) {
1185 *old = oldValue;
1186 }
1187}
1188
1189#define LDM_LOOP(LDM) \
1190 for (i = 0; i < 16; i += 4) { \
1191 if (UNLIKELY(mask & (1 << i))) { \
1192 LDM; \
1193 waitstatesRegion = memory->waitstatesSeq32; \
1194 cpu->gprs[i] = value; \
1195 ++wait; \
1196 address += 4; \
1197 } \
1198 if (UNLIKELY(mask & (2 << i))) { \
1199 LDM; \
1200 waitstatesRegion = memory->waitstatesSeq32; \
1201 cpu->gprs[i + 1] = value; \
1202 ++wait; \
1203 address += 4; \
1204 } \
1205 if (UNLIKELY(mask & (4 << i))) { \
1206 LDM; \
1207 waitstatesRegion = memory->waitstatesSeq32; \
1208 cpu->gprs[i + 2] = value; \
1209 ++wait; \
1210 address += 4; \
1211 } \
1212 if (UNLIKELY(mask & (8 << i))) { \
1213 LDM; \
1214 waitstatesRegion = memory->waitstatesSeq32; \
1215 cpu->gprs[i + 3] = value; \
1216 ++wait; \
1217 address += 4; \
1218 } \
1219 }
1220
1221uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1222 struct GBA* gba = (struct GBA*) cpu->master;
1223 struct GBAMemory* memory = &gba->memory;
1224 uint32_t value;
1225 int wait = 0;
1226 char* waitstatesRegion = memory->waitstatesNonseq32;
1227
1228 int i;
1229 int offset = 4;
1230 int popcount = 0;
1231 if (direction & LSM_D) {
1232 offset = -4;
1233 popcount = popcount32(mask);
1234 address -= (popcount << 2) - 4;
1235 }
1236
1237 if (direction & LSM_B) {
1238 address += offset;
1239 }
1240
1241 uint32_t addressMisalign = address & 0x3;
1242 if (address >> BASE_OFFSET < REGION_CART_SRAM) {
1243 address &= 0xFFFFFFFC;
1244 }
1245
1246 switch (address >> BASE_OFFSET) {
1247 case REGION_BIOS:
1248 LDM_LOOP(LOAD_BIOS);
1249 break;
1250 case REGION_WORKING_RAM:
1251 LDM_LOOP(LOAD_WORKING_RAM);
1252 break;
1253 case REGION_WORKING_IRAM:
1254 LDM_LOOP(LOAD_WORKING_IRAM);
1255 break;
1256 case REGION_IO:
1257 LDM_LOOP(LOAD_IO);
1258 break;
1259 case REGION_PALETTE_RAM:
1260 LDM_LOOP(LOAD_PALETTE_RAM);
1261 break;
1262 case REGION_VRAM:
1263 LDM_LOOP(LOAD_VRAM);
1264 break;
1265 case REGION_OAM:
1266 LDM_LOOP(LOAD_OAM);
1267 break;
1268 case REGION_CART0:
1269 case REGION_CART0_EX:
1270 case REGION_CART1:
1271 case REGION_CART1_EX:
1272 case REGION_CART2:
1273 case REGION_CART2_EX:
1274 LDM_LOOP(LOAD_CART);
1275 break;
1276 case REGION_CART_SRAM:
1277 case REGION_CART_SRAM_MIRROR:
1278 LDM_LOOP(LOAD_SRAM);
1279 break;
1280 default:
1281 LDM_LOOP(LOAD_BAD);
1282 break;
1283 }
1284
1285 if (cycleCounter) {
1286 ++wait;
1287 if (address >> BASE_OFFSET < REGION_CART0) {
1288 wait = GBAMemoryStall(cpu, wait);
1289 }
1290 *cycleCounter += wait;
1291 }
1292
1293 if (direction & LSM_B) {
1294 address -= offset;
1295 }
1296
1297 if (direction & LSM_D) {
1298 address -= (popcount << 2) + 4;
1299 }
1300
1301 return address | addressMisalign;
1302}
1303
1304#define STM_LOOP(STM) \
1305 for (i = 0; i < 16; i += 4) { \
1306 if (UNLIKELY(mask & (1 << i))) { \
1307 value = cpu->gprs[i]; \
1308 STM; \
1309 waitstatesRegion = memory->waitstatesSeq32; \
1310 ++wait; \
1311 address += 4; \
1312 } \
1313 if (UNLIKELY(mask & (2 << i))) { \
1314 value = cpu->gprs[i + 1]; \
1315 STM; \
1316 waitstatesRegion = memory->waitstatesSeq32; \
1317 ++wait; \
1318 address += 4; \
1319 } \
1320 if (UNLIKELY(mask & (4 << i))) { \
1321 value = cpu->gprs[i + 2]; \
1322 STM; \
1323 waitstatesRegion = memory->waitstatesSeq32; \
1324 ++wait; \
1325 address += 4; \
1326 } \
1327 if (UNLIKELY(mask & (8 << i))) { \
1328 value = cpu->gprs[i + 3]; \
1329 STM; \
1330 waitstatesRegion = memory->waitstatesSeq32; \
1331 ++wait; \
1332 address += 4; \
1333 } \
1334 }
1335
1336uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1337 struct GBA* gba = (struct GBA*) cpu->master;
1338 struct GBAMemory* memory = &gba->memory;
1339 uint32_t value;
1340 int wait = 0;
1341 char* waitstatesRegion = memory->waitstatesNonseq32;
1342
1343 int i;
1344 int offset = 4;
1345 int popcount = 0;
1346 if (direction & LSM_D) {
1347 offset = -4;
1348 popcount = popcount32(mask);
1349 address -= (popcount << 2) - 4;
1350 }
1351
1352 if (direction & LSM_B) {
1353 address += offset;
1354 }
1355
1356 uint32_t addressMisalign = address & 0x3;
1357 if (address >> BASE_OFFSET < REGION_CART_SRAM) {
1358 address &= 0xFFFFFFFC;
1359 }
1360
1361 switch (address >> BASE_OFFSET) {
1362 case REGION_WORKING_RAM:
1363 STM_LOOP(STORE_WORKING_RAM);
1364 break;
1365 case REGION_WORKING_IRAM:
1366 STM_LOOP(STORE_WORKING_IRAM);
1367 break;
1368 case REGION_IO:
1369 STM_LOOP(STORE_IO);
1370 break;
1371 case REGION_PALETTE_RAM:
1372 STM_LOOP(STORE_PALETTE_RAM);
1373 break;
1374 case REGION_VRAM:
1375 STM_LOOP(STORE_VRAM);
1376 break;
1377 case REGION_OAM:
1378 STM_LOOP(STORE_OAM);
1379 break;
1380 case REGION_CART0:
1381 case REGION_CART0_EX:
1382 case REGION_CART1:
1383 case REGION_CART1_EX:
1384 case REGION_CART2:
1385 case REGION_CART2_EX:
1386 STM_LOOP(STORE_CART);
1387 break;
1388 case REGION_CART_SRAM:
1389 case REGION_CART_SRAM_MIRROR:
1390 STM_LOOP(STORE_SRAM);
1391 break;
1392 default:
1393 STM_LOOP(STORE_BAD);
1394 break;
1395 }
1396
1397 if (cycleCounter) {
1398 if (address >> BASE_OFFSET < REGION_CART0) {
1399 wait = GBAMemoryStall(cpu, wait);
1400 }
1401 *cycleCounter += wait;
1402 }
1403
1404 if (direction & LSM_B) {
1405 address -= offset;
1406 }
1407
1408 if (direction & LSM_D) {
1409 address -= (popcount << 2) + 4;
1410 }
1411
1412 return address | addressMisalign;
1413}
1414
1415void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
1416 struct GBAMemory* memory = &gba->memory;
1417 struct ARMCore* cpu = gba->cpu;
1418 int sram = parameters & 0x0003;
1419 int ws0 = (parameters & 0x000C) >> 2;
1420 int ws0seq = (parameters & 0x0010) >> 4;
1421 int ws1 = (parameters & 0x0060) >> 5;
1422 int ws1seq = (parameters & 0x0080) >> 7;
1423 int ws2 = (parameters & 0x0300) >> 8;
1424 int ws2seq = (parameters & 0x0400) >> 10;
1425 int prefetch = parameters & 0x4000;
1426
1427 memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1428 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1429 memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1430 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1431
1432 memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
1433 memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
1434 memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
1435
1436 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
1437 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
1438 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
1439
1440 memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
1441 memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
1442 memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
1443
1444 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
1445 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
1446 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
1447
1448 memory->prefetch = prefetch;
1449
1450 cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion];
1451 cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
1452
1453 cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
1454 cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
1455}
1456
1457static bool _isValidDMASAD(int dma, uint32_t address) {
1458 if (dma == 0 && address >= BASE_CART0 && address < BASE_CART_SRAM) {
1459 return false;
1460 }
1461 return address >= BASE_WORKING_RAM;
1462}
1463
1464static bool _isValidDMADAD(int dma, uint32_t address) {
1465 return dma == 3 || address < BASE_CART0;
1466}
1467
1468uint32_t GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
1469 struct GBAMemory* memory = &gba->memory;
1470 address &= 0x0FFFFFFE;
1471 if (_isValidDMASAD(dma, address)) {
1472 memory->dma[dma].source = address;
1473 }
1474 return memory->dma[dma].source;
1475}
1476
1477uint32_t GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
1478 struct GBAMemory* memory = &gba->memory;
1479 address &= 0x0FFFFFFE;
1480 if (_isValidDMADAD(dma, address)) {
1481 memory->dma[dma].dest = address;
1482 }
1483 return memory->dma[dma].dest;
1484}
1485
1486void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
1487 struct GBAMemory* memory = &gba->memory;
1488 memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
1489}
1490
1491uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
1492 struct GBAMemory* memory = &gba->memory;
1493 struct GBADMA* currentDma = &memory->dma[dma];
1494 int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
1495 if (dma < 3) {
1496 control &= 0xF7E0;
1497 } else {
1498 control &= 0xFFE0;
1499 }
1500 currentDma->reg = control;
1501
1502 if (GBADMARegisterIsDRQ(currentDma->reg)) {
1503 mLOG(GBA_MEM, STUB, "DRQ not implemented");
1504 }
1505
1506 if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
1507 currentDma->nextSource = currentDma->source;
1508 currentDma->nextDest = currentDma->dest;
1509 currentDma->nextCount = currentDma->count;
1510 GBAMemoryScheduleDMA(gba, dma, currentDma);
1511 }
1512 // If the DMA has already occurred, this value might have changed since the function started
1513 return currentDma->reg;
1514};
1515
1516void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
1517 struct ARMCore* cpu = gba->cpu;
1518 switch (GBADMARegisterGetTiming(info->reg)) {
1519 case DMA_TIMING_NOW:
1520 info->nextEvent = cpu->cycles + 2;
1521 GBAMemoryUpdateDMAs(gba, -1);
1522 break;
1523 case DMA_TIMING_HBLANK:
1524 // Handled implicitly
1525 info->nextEvent = INT_MAX;
1526 break;
1527 case DMA_TIMING_VBLANK:
1528 // Handled implicitly
1529 info->nextEvent = INT_MAX;
1530 break;
1531 case DMA_TIMING_CUSTOM:
1532 info->nextEvent = INT_MAX;
1533 switch (number) {
1534 case 0:
1535 mLOG(GBA_MEM, WARN, "Discarding invalid DMA0 scheduling");
1536 break;
1537 case 1:
1538 case 2:
1539 GBAAudioScheduleFifoDma(&gba->audio, number, info);
1540 break;
1541 case 3:
1542 // GBAVideoScheduleVCaptureDma(dma, info);
1543 break;
1544 }
1545 }
1546}
1547
1548void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
1549 struct GBAMemory* memory = &gba->memory;
1550 struct GBADMA* dma;
1551 int i;
1552 for (i = 0; i < 4; ++i) {
1553 dma = &memory->dma[i];
1554 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK) {
1555 dma->nextEvent = cycles;
1556 }
1557 }
1558 GBAMemoryUpdateDMAs(gba, 0);
1559}
1560
1561void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
1562 struct GBAMemory* memory = &gba->memory;
1563 struct GBADMA* dma;
1564 int i;
1565 for (i = 0; i < 4; ++i) {
1566 dma = &memory->dma[i];
1567 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK) {
1568 dma->nextEvent = cycles;
1569 }
1570 }
1571 GBAMemoryUpdateDMAs(gba, 0);
1572}
1573
1574int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
1575 struct GBAMemory* memory = &gba->memory;
1576 if (memory->nextDMA == INT_MAX) {
1577 return INT_MAX;
1578 }
1579 memory->nextDMA -= cycles;
1580 memory->eventDiff += cycles;
1581 while (memory->nextDMA <= 0) {
1582 struct GBADMA* dma = &memory->dma[memory->activeDMA];
1583 GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
1584 GBAMemoryUpdateDMAs(gba, memory->eventDiff);
1585 memory->eventDiff = 0;
1586 }
1587 return memory->nextDMA;
1588}
1589
1590void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
1591 int i;
1592 struct GBAMemory* memory = &gba->memory;
1593 struct ARMCore* cpu = gba->cpu;
1594 memory->activeDMA = -1;
1595 memory->nextDMA = INT_MAX;
1596 for (i = 3; i >= 0; --i) {
1597 struct GBADMA* dma = &memory->dma[i];
1598 if (dma->nextEvent != INT_MAX) {
1599 dma->nextEvent -= cycles;
1600 if (GBADMARegisterIsEnable(dma->reg)) {
1601 memory->activeDMA = i;
1602 memory->nextDMA = dma->nextEvent;
1603 }
1604 }
1605 }
1606 if (memory->nextDMA < cpu->nextEvent) {
1607 cpu->nextEvent = memory->nextDMA;
1608 }
1609}
1610
1611void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
1612 struct GBAMemory* memory = &gba->memory;
1613 struct ARMCore* cpu = gba->cpu;
1614 uint32_t width = GBADMARegisterGetWidth(info->reg) ? 4 : 2;
1615 int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
1616 int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width;
1617 int32_t wordsRemaining = info->nextCount;
1618 uint32_t source = info->nextSource;
1619 uint32_t dest = info->nextDest;
1620 uint32_t sourceRegion = source >> BASE_OFFSET;
1621 uint32_t destRegion = dest >> BASE_OFFSET;
1622 int32_t cycles = 2;
1623
1624 if (source == info->source && dest == info->dest && wordsRemaining == info->count) {
1625 if (sourceRegion < REGION_CART0 || destRegion < REGION_CART0) {
1626 cycles += 2;
1627 }
1628 if (width == 4) {
1629 cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
1630 source &= 0xFFFFFFFC;
1631 dest &= 0xFFFFFFFC;
1632 } else {
1633 cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
1634 }
1635 } else {
1636 if (width == 4) {
1637 cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
1638 } else {
1639 cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
1640 }
1641 }
1642
1643 gba->performingDMA = 1 | (number << 1);
1644 int32_t word;
1645 if (width == 4) {
1646 word = cpu->memory.load32(cpu, source, 0);
1647 gba->bus = word;
1648 cpu->memory.store32(cpu, dest, word, 0);
1649 source += sourceOffset;
1650 dest += destOffset;
1651 --wordsRemaining;
1652 } else {
1653 if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
1654 word = GBASavedataReadEEPROM(&memory->savedata);
1655 gba->bus = word | (word << 16);
1656 cpu->memory.store16(cpu, dest, word, 0);
1657 source += sourceOffset;
1658 dest += destOffset;
1659 --wordsRemaining;
1660 } else if (destRegion == REGION_CART2_EX) {
1661 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
1662 mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
1663 GBASavedataInitEEPROM(&memory->savedata);
1664 }
1665 word = cpu->memory.load16(cpu, source, 0);
1666 gba->bus = word | (word << 16);
1667 GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
1668 source += sourceOffset;
1669 dest += destOffset;
1670 --wordsRemaining;
1671 } else {
1672 word = cpu->memory.load16(cpu, source, 0);
1673 gba->bus = word | (word << 16);
1674 cpu->memory.store16(cpu, dest, word, 0);
1675 source += sourceOffset;
1676 dest += destOffset;
1677 --wordsRemaining;
1678 }
1679 }
1680 gba->performingDMA = 0;
1681
1682 if (!wordsRemaining) {
1683 if (!GBADMARegisterIsRepeat(info->reg) || GBADMARegisterGetTiming(info->reg) == DMA_TIMING_NOW) {
1684 info->reg = GBADMARegisterClearEnable(info->reg);
1685 info->nextEvent = INT_MAX;
1686
1687 // Clear the enable bit in memory
1688 memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
1689 } else {
1690 info->nextCount = info->count;
1691 if (GBADMARegisterGetDestControl(info->reg) == DMA_INCREMENT_RELOAD) {
1692 info->nextDest = info->dest;
1693 }
1694 GBAMemoryScheduleDMA(gba, number, info);
1695 }
1696 if (GBADMARegisterIsDoIRQ(info->reg)) {
1697 GBARaiseIRQ(gba, IRQ_DMA0 + number);
1698 }
1699 } else {
1700 info->nextDest = dest;
1701 info->nextCount = wordsRemaining;
1702 }
1703 info->nextSource = source;
1704
1705 if (info->nextEvent != INT_MAX) {
1706 info->nextEvent += cycles;
1707 }
1708 cpu->cycles += cycles;
1709}
1710
1711int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) {
1712 struct GBA* gba = (struct GBA*) cpu->master;
1713 struct GBAMemory* memory = &gba->memory;
1714
1715 if (memory->activeRegion < REGION_CART0 || !memory->prefetch) {
1716 // The wait is the stall
1717 return wait;
1718 }
1719
1720 int32_t s = cpu->memory.activeSeqCycles16 + 1;
1721 int32_t n2s = cpu->memory.activeNonseqCycles16 - cpu->memory.activeSeqCycles16 + 1;
1722
1723 // Figure out how many sequential loads we can jam in
1724 int32_t stall = s;
1725 int32_t loads = 1;
1726 int32_t previousLoads = 0;
1727
1728 // Don't prefetch too much if we're overlapping with a previous prefetch
1729 uint32_t dist = (memory->lastPrefetchedPc - cpu->gprs[ARM_PC]) >> 1;
1730 if (dist < memory->lastPrefetchedLoads) {
1731 previousLoads = dist;
1732 }
1733 while (stall < wait) {
1734 stall += s;
1735 ++loads;
1736 }
1737 if (loads + previousLoads > 8) {
1738 int diff = (loads + previousLoads) - 8;
1739 loads -= diff;
1740 stall -= s * diff;
1741 } else if (stall > wait && loads == 1) {
1742 // We might need to stall a bit extra if we haven't finished the first S cycle
1743 wait = stall;
1744 }
1745 // This instruction used to have an N, convert it to an S.
1746 wait -= n2s;
1747
1748 // TODO: Invalidate prefetch on branch
1749 memory->lastPrefetchedLoads = loads;
1750 memory->lastPrefetchedPc = cpu->gprs[ARM_PC] + WORD_SIZE_THUMB * loads;
1751
1752 // The next |loads|S waitstates disappear entirely, so long as they're all in a row
1753 cpu->cycles -= (s - 1) * loads;
1754 return wait;
1755}
1756
1757void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state) {
1758 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1759 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1760}
1761
1762void GBAMemoryDeserialize(struct GBAMemory* memory, const struct GBASerializedState* state) {
1763 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1764 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1765}
1766
1767void _pristineCow(struct GBA* gba) {
1768 if (gba->memory.rom != gba->pristineRom) {
1769 return;
1770 }
1771 gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
1772 memcpy(gba->memory.rom, gba->pristineRom, gba->memory.romSize);
1773 memset(((uint8_t*) gba->memory.rom) + gba->memory.romSize, 0xFF, SIZE_CART0 - gba->memory.romSize);
1774}