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