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