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