src/gba/memory.c (view raw)
1/* Copyright (c) 2013-2016 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 <mgba/internal/gba/memory.h>
7
8#include <mgba/internal/arm/decoder.h>
9#include <mgba/internal/arm/macros.h>
10#include <mgba/internal/gba/gba.h>
11#include <mgba/internal/gba/dma.h>
12#include <mgba/internal/gba/io.h>
13#include <mgba/internal/gba/serialize.h>
14#include "gba/hle-bios.h"
15
16#include <mgba-util/math.h>
17#include <mgba-util/memory.h>
18#include <mgba-util/vfs.h>
19
20#define IDLE_LOOP_THRESHOLD 10000
21
22mLOG_DEFINE_CATEGORY(GBA_MEM, "GBA Memory", "gba.memory");
23
24static void _pristineCow(struct GBA* gba);
25static uint32_t _deadbeef[1] = { 0xE710B710 }; // Illegal instruction on both ARM and Thumb
26
27static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
28static int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait);
29
30static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
31static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 9 };
32static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 };
33static const char GBA_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 9 };
34static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
35static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 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.waitstatesNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
63 gba->memory.waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
64 }
65 for (; i < 256; ++i) {
66 gba->memory.waitstatesNonseq16[i] = 0;
67 gba->memory.waitstatesSeq16[i] = 0;
68 gba->memory.waitstatesNonseq32[i] = 0;
69 gba->memory.waitstatesSeq32[i] = 0;
70 }
71
72 gba->memory.activeRegion = -1;
73 cpu->memory.activeRegion = 0;
74 cpu->memory.activeMask = 0;
75 cpu->memory.setActiveRegion = GBASetActiveRegion;
76 cpu->memory.activeSeqCycles32 = 0;
77 cpu->memory.activeSeqCycles16 = 0;
78 cpu->memory.activeNonseqCycles32 = 0;
79 cpu->memory.activeNonseqCycles16 = 0;
80 gba->memory.biosPrefetch = 0;
81 gba->memory.mirroring = false;
82
83 GBADMAInit(gba);
84 GBAVFameInit(&gba->memory.vfame);
85}
86
87void GBAMemoryDeinit(struct GBA* gba) {
88 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
89 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
90 if (gba->memory.rom) {
91 mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
92 }
93 GBASavedataUnmask(&gba->memory.savedata);
94 GBASavedataDeinit(&gba->memory.savedata);
95 if (gba->memory.savedata.realVf) {
96 gba->memory.savedata.realVf->close(gba->memory.savedata.realVf);
97 }
98}
99
100void GBAMemoryReset(struct GBA* gba) {
101 if (gba->memory.rom || gba->memory.fullBios || !gba->memory.wram) {
102 // Not multiboot
103 if (gba->memory.wram) {
104 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
105 }
106 gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
107 }
108
109 if (gba->memory.iwram) {
110 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
111 }
112 gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
113
114 memset(gba->memory.io, 0, sizeof(gba->memory.io));
115
116 gba->memory.prefetch = false;
117 gba->memory.lastPrefetchedPc = 0;
118
119 if (!gba->memory.wram || !gba->memory.iwram) {
120 GBAMemoryDeinit(gba);
121 mLOG(GBA_MEM, FATAL, "Could not map memory");
122 }
123
124 GBADMAReset(gba);
125}
126
127static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t address) {
128 struct ARMInstructionInfo info;
129 uint32_t nextAddress = address;
130 memset(gba->taintedRegisters, 0, sizeof(gba->taintedRegisters));
131 if (cpu->executionMode == MODE_THUMB) {
132 while (true) {
133 uint16_t opcode;
134 LOAD_16(opcode, nextAddress & cpu->memory.activeMask, cpu->memory.activeRegion);
135 ARMDecodeThumb(opcode, &info);
136 switch (info.branchType) {
137 case ARM_BRANCH_NONE:
138 if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
139 if (info.mnemonic == ARM_MN_STR || gba->taintedRegisters[info.memory.baseReg]) {
140 gba->idleDetectionStep = -1;
141 return;
142 }
143 uint32_t loadAddress = gba->cachedRegisters[info.memory.baseReg];
144 uint32_t offset = 0;
145 if (info.memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
146 offset = info.memory.offset.immediate;
147 } else if (info.memory.format & ARM_MEMORY_REGISTER_OFFSET) {
148 int reg = info.memory.offset.reg;
149 if (gba->cachedRegisters[reg]) {
150 gba->idleDetectionStep = -1;
151 return;
152 }
153 offset = gba->cachedRegisters[reg];
154 }
155 if (info.memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
156 loadAddress -= offset;
157 } else {
158 loadAddress += offset;
159 }
160 if ((loadAddress >> BASE_OFFSET) == REGION_IO && !GBAIOIsReadConstant(loadAddress)) {
161 gba->idleDetectionStep = -1;
162 return;
163 }
164 if ((loadAddress >> BASE_OFFSET) < REGION_CART0 || (loadAddress >> BASE_OFFSET) > REGION_CART2_EX) {
165 gba->taintedRegisters[info.op1.reg] = true;
166 } else {
167 switch (info.memory.width) {
168 case 1:
169 gba->cachedRegisters[info.op1.reg] = GBALoad8(cpu, loadAddress, 0);
170 break;
171 case 2:
172 gba->cachedRegisters[info.op1.reg] = GBALoad16(cpu, loadAddress, 0);
173 break;
174 case 4:
175 gba->cachedRegisters[info.op1.reg] = GBALoad32(cpu, loadAddress, 0);
176 break;
177 }
178 }
179 } else if (info.operandFormat & ARM_OPERAND_AFFECTED_1) {
180 gba->taintedRegisters[info.op1.reg] = true;
181 }
182 nextAddress += WORD_SIZE_THUMB;
183 break;
184 case ARM_BRANCH:
185 if ((uint32_t) info.op1.immediate + nextAddress + WORD_SIZE_THUMB * 2 == address) {
186 gba->idleLoop = address;
187 gba->idleOptimization = IDLE_LOOP_REMOVE;
188 }
189 gba->idleDetectionStep = -1;
190 return;
191 default:
192 gba->idleDetectionStep = -1;
193 return;
194 }
195 }
196 } else {
197 gba->idleDetectionStep = -1;
198 }
199}
200
201static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
202 struct GBA* gba = (struct GBA*) cpu->master;
203 struct GBAMemory* memory = &gba->memory;
204
205 int newRegion = address >> BASE_OFFSET;
206 if (gba->idleOptimization >= IDLE_LOOP_REMOVE && memory->activeRegion != REGION_BIOS) {
207 if (address == gba->idleLoop) {
208 if (gba->haltPending) {
209 gba->haltPending = false;
210 GBAHalt(gba);
211 } else {
212 gba->haltPending = true;
213 }
214 } else if (gba->idleOptimization >= IDLE_LOOP_DETECT && newRegion == memory->activeRegion) {
215 if (address == gba->lastJump) {
216 switch (gba->idleDetectionStep) {
217 case 0:
218 memcpy(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters));
219 ++gba->idleDetectionStep;
220 break;
221 case 1:
222 if (memcmp(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters))) {
223 gba->idleDetectionStep = -1;
224 ++gba->idleDetectionFailures;
225 if (gba->idleDetectionFailures > IDLE_LOOP_THRESHOLD) {
226 gba->idleOptimization = IDLE_LOOP_IGNORE;
227 }
228 break;
229 }
230 _analyzeForIdleLoop(gba, cpu, address);
231 break;
232 }
233 } else {
234 gba->idleDetectionStep = 0;
235 }
236 }
237 }
238
239 gba->lastJump = address;
240 memory->lastPrefetchedPc = 0;
241 if (newRegion == memory->activeRegion) {
242 if (newRegion < REGION_CART0 || (address & (SIZE_CART0 - 1)) < memory->romSize) {
243 return;
244 }
245 if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
246 return;
247 }
248 }
249
250 if (memory->activeRegion == REGION_BIOS) {
251 memory->biosPrefetch = cpu->prefetch[1];
252 }
253 memory->activeRegion = newRegion;
254 switch (newRegion) {
255 case REGION_BIOS:
256 cpu->memory.activeRegion = memory->bios;
257 cpu->memory.activeMask = SIZE_BIOS - 1;
258 break;
259 case REGION_WORKING_RAM:
260 cpu->memory.activeRegion = memory->wram;
261 cpu->memory.activeMask = SIZE_WORKING_RAM - 1;
262 break;
263 case REGION_WORKING_IRAM:
264 cpu->memory.activeRegion = memory->iwram;
265 cpu->memory.activeMask = SIZE_WORKING_IRAM - 1;
266 break;
267 case REGION_PALETTE_RAM:
268 cpu->memory.activeRegion = (uint32_t*) gba->video.palette;
269 cpu->memory.activeMask = SIZE_PALETTE_RAM - 1;
270 break;
271 case REGION_VRAM:
272 if (address & 0x10000) {
273 cpu->memory.activeRegion = (uint32_t*) &gba->video.vram[0x8000];
274 cpu->memory.activeMask = 0x00007FFF;
275 } else {
276 cpu->memory.activeRegion = (uint32_t*) gba->video.vram;
277 cpu->memory.activeMask = 0x0000FFFF;
278 }
279 break;
280 case REGION_OAM:
281 cpu->memory.activeRegion = (uint32_t*) gba->video.oam.raw;
282 cpu->memory.activeMask = SIZE_OAM - 1;
283 break;
284 case REGION_CART0:
285 case REGION_CART0_EX:
286 case REGION_CART1:
287 case REGION_CART1_EX:
288 case REGION_CART2:
289 case REGION_CART2_EX:
290 cpu->memory.activeRegion = memory->rom;
291 cpu->memory.activeMask = memory->romMask;
292 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
293 break;
294 }
295 // Fall through
296 default:
297 memory->activeRegion = -1;
298 cpu->memory.activeRegion = _deadbeef;
299 cpu->memory.activeMask = 0;
300 if (gba->yankedRomSize || !gba->hardCrash) {
301 mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address);
302 } else if (mCoreCallbacksListSize(&gba->coreCallbacks)) {
303 mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address);
304 size_t c;
305 for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
306 struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
307 if (callbacks->coreCrashed) {
308 callbacks->coreCrashed(callbacks->context);
309 }
310 }
311 } else {
312 mLOG(GBA_MEM, FATAL, "Jumped to invalid address: %08X", address);
313 }
314 return;
315 }
316 cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion];
317 cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
318 cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
319 cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
320}
321
322#define LOAD_BAD \
323 if (gba->performingDMA) { \
324 value = gba->bus; \
325 } else { \
326 value = cpu->prefetch[1]; \
327 if (cpu->executionMode == MODE_THUMB) { \
328 /* http://ngemu.com/threads/gba-open-bus.170809/ */ \
329 switch (cpu->gprs[ARM_PC] >> BASE_OFFSET) { \
330 case REGION_BIOS: \
331 case REGION_OAM: \
332 /* This isn't right half the time, but we don't have $+6 handy */ \
333 value <<= 16; \
334 value |= cpu->prefetch[0]; \
335 break; \
336 case REGION_WORKING_IRAM: \
337 /* This doesn't handle prefetch clobbering */ \
338 if (cpu->gprs[ARM_PC] & 2) { \
339 value |= cpu->prefetch[0] << 16; \
340 } else { \
341 value <<= 16; \
342 value |= cpu->prefetch[0]; \
343 } \
344 default: \
345 value |= value << 16; \
346 } \
347 } \
348 }
349
350#define LOAD_BIOS \
351 if (address < SIZE_BIOS) { \
352 if (memory->activeRegion == REGION_BIOS) { \
353 LOAD_32(value, address & -4, memory->bios); \
354 } else { \
355 mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load32: 0x%08X", address); \
356 value = memory->biosPrefetch; \
357 } \
358 } else { \
359 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load32: 0x%08X", address); \
360 LOAD_BAD; \
361 }
362
363#define LOAD_WORKING_RAM \
364 LOAD_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); \
365 wait += waitstatesRegion[REGION_WORKING_RAM];
366
367#define LOAD_WORKING_IRAM LOAD_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
368#define LOAD_IO value = GBAIORead(gba, address & OFFSET_MASK & ~2) | (GBAIORead(gba, (address & OFFSET_MASK) | 2) << 16);
369
370#define LOAD_PALETTE_RAM \
371 LOAD_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
372 wait += waitstatesRegion[REGION_PALETTE_RAM];
373
374#define LOAD_VRAM \
375 if ((address & 0x0001FFFF) < SIZE_VRAM) { \
376 LOAD_32(value, address & 0x0001FFFC, gba->video.vram); \
377 } else { \
378 LOAD_32(value, address & 0x00017FFC, gba->video.vram); \
379 } \
380 wait += waitstatesRegion[REGION_VRAM];
381
382#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
383
384#define LOAD_CART \
385 wait += waitstatesRegion[address >> BASE_OFFSET]; \
386 if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \
387 LOAD_32(value, address & (SIZE_CART0 - 4), memory->rom); \
388 } else if (memory->mirroring && (address & memory->romMask) < memory->romSize) { \
389 LOAD_32(value, address & memory->romMask & -4, memory->rom); \
390 } else if (memory->vfame.cartType) { \
391 value = GBAVFameGetPatternValue(address, 32); \
392 } else { \
393 mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load32: 0x%08X", address); \
394 value = ((address & ~3) >> 1) & 0xFFFF; \
395 value |= (((address & ~3) + 2) >> 1) << 16; \
396 }
397
398#define LOAD_SRAM \
399 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; \
400 value = GBALoad8(cpu, address, 0); \
401 value |= value << 8; \
402 value |= value << 16;
403
404uint32_t GBALoadBad(struct ARMCore* cpu) {
405 struct GBA* gba = (struct GBA*) cpu->master;
406 uint32_t value = 0;
407 LOAD_BAD;
408 return value;
409}
410
411uint32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
412 struct GBA* gba = (struct GBA*) cpu->master;
413 struct GBAMemory* memory = &gba->memory;
414 uint32_t value = 0;
415 int wait = 0;
416 char* waitstatesRegion = memory->waitstatesNonseq32;
417
418 switch (address >> BASE_OFFSET) {
419 case REGION_BIOS:
420 LOAD_BIOS;
421 break;
422 case REGION_WORKING_RAM:
423 LOAD_WORKING_RAM;
424 break;
425 case REGION_WORKING_IRAM:
426 LOAD_WORKING_IRAM;
427 break;
428 case REGION_IO:
429 LOAD_IO;
430 break;
431 case REGION_PALETTE_RAM:
432 LOAD_PALETTE_RAM;
433 break;
434 case REGION_VRAM:
435 LOAD_VRAM;
436 break;
437 case REGION_OAM:
438 LOAD_OAM;
439 break;
440 case REGION_CART0:
441 case REGION_CART0_EX:
442 case REGION_CART1:
443 case REGION_CART1_EX:
444 case REGION_CART2:
445 case REGION_CART2_EX:
446 LOAD_CART;
447 break;
448 case REGION_CART_SRAM:
449 case REGION_CART_SRAM_MIRROR:
450 LOAD_SRAM;
451 break;
452 default:
453 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load32: 0x%08X", address);
454 LOAD_BAD;
455 break;
456 }
457
458 if (cycleCounter) {
459 wait += 2;
460 if (address >> BASE_OFFSET < REGION_CART0) {
461 wait = GBAMemoryStall(cpu, wait);
462 }
463 *cycleCounter += wait;
464 }
465 // Unaligned 32-bit loads are "rotated" so they make some semblance of sense
466 int rotate = (address & 3) << 3;
467 return ROR(value, rotate);
468}
469
470uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
471 struct GBA* gba = (struct GBA*) cpu->master;
472 struct GBAMemory* memory = &gba->memory;
473 uint32_t value = 0;
474 int wait = 0;
475
476 switch (address >> BASE_OFFSET) {
477 case REGION_BIOS:
478 if (address < SIZE_BIOS) {
479 if (memory->activeRegion == REGION_BIOS) {
480 LOAD_16(value, address & -2, memory->bios);
481 } else {
482 mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load16: 0x%08X", address);
483 value = (memory->biosPrefetch >> ((address & 2) * 8)) & 0xFFFF;
484 }
485 } else {
486 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load16: 0x%08X", address);
487 LOAD_BAD;
488 value = (value >> ((address & 2) * 8)) & 0xFFFF;
489 }
490 break;
491 case REGION_WORKING_RAM:
492 LOAD_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
493 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
494 break;
495 case REGION_WORKING_IRAM:
496 LOAD_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
497 break;
498 case REGION_IO:
499 value = GBAIORead(gba, address & (OFFSET_MASK - 1));
500 break;
501 case REGION_PALETTE_RAM:
502 LOAD_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
503 break;
504 case REGION_VRAM:
505 if ((address & 0x0001FFFF) < SIZE_VRAM) {
506 LOAD_16(value, address & 0x0001FFFE, gba->video.vram);
507 } else {
508 LOAD_16(value, address & 0x00017FFE, gba->video.vram);
509 }
510 break;
511 case REGION_OAM:
512 LOAD_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
513 break;
514 case REGION_CART0:
515 case REGION_CART0_EX:
516 case REGION_CART1:
517 case REGION_CART1_EX:
518 case REGION_CART2:
519 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
520 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
521 LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
522 } else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
523 LOAD_16(value, address & memory->romMask, memory->rom);
524 } else if (memory->vfame.cartType) {
525 value = GBAVFameGetPatternValue(address, 16);
526 } else {
527 mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address);
528 value = (address >> 1) & 0xFFFF;
529 }
530 break;
531 case REGION_CART2_EX:
532 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
533 if (memory->savedata.type == SAVEDATA_EEPROM) {
534 value = GBASavedataReadEEPROM(&memory->savedata);
535 } else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
536 LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
537 } else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
538 LOAD_16(value, address & memory->romMask, memory->rom);
539 } else if (memory->vfame.cartType) {
540 value = GBAVFameGetPatternValue(address, 16);
541 } else {
542 mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address);
543 value = (address >> 1) & 0xFFFF;
544 }
545 break;
546 case REGION_CART_SRAM:
547 case REGION_CART_SRAM_MIRROR:
548 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
549 value = GBALoad8(cpu, address, 0);
550 value |= value << 8;
551 break;
552 default:
553 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load16: 0x%08X", address);
554 LOAD_BAD;
555 value = (value >> ((address & 2) * 8)) & 0xFFFF;
556 break;
557 }
558
559 if (cycleCounter) {
560 wait += 2;
561 if (address >> BASE_OFFSET < REGION_CART0) {
562 wait = GBAMemoryStall(cpu, wait);
563 }
564 *cycleCounter += wait;
565 }
566 // Unaligned 16-bit loads are "unpredictable", but the GBA rotates them, so we have to, too.
567 int rotate = (address & 1) << 3;
568 return ROR(value, rotate);
569}
570
571uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
572 struct GBA* gba = (struct GBA*) cpu->master;
573 struct GBAMemory* memory = &gba->memory;
574 uint32_t value = 0;
575 int wait = 0;
576
577 switch (address >> BASE_OFFSET) {
578 case REGION_BIOS:
579 if (address < SIZE_BIOS) {
580 if (memory->activeRegion == REGION_BIOS) {
581 value = ((uint8_t*) memory->bios)[address];
582 } else {
583 mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
584 value = (memory->biosPrefetch >> ((address & 3) * 8)) & 0xFF;
585 }
586 } else {
587 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load8: 0x%08x", address);
588 LOAD_BAD;
589 value = (value >> ((address & 3) * 8)) & 0xFF;
590 }
591 break;
592 case REGION_WORKING_RAM:
593 value = ((uint8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
594 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
595 break;
596 case REGION_WORKING_IRAM:
597 value = ((uint8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
598 break;
599 case REGION_IO:
600 value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
601 break;
602 case REGION_PALETTE_RAM:
603 value = ((uint8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
604 break;
605 case REGION_VRAM:
606 if ((address & 0x0001FFFF) < SIZE_VRAM) {
607 value = ((uint8_t*) gba->video.vram)[address & 0x0001FFFF];
608 } else {
609 value = ((uint8_t*) gba->video.vram)[address & 0x00017FFF];
610 }
611 break;
612 case REGION_OAM:
613 value = ((uint8_t*) gba->video.oam.raw)[address & (SIZE_OAM - 1)];
614 break;
615 case REGION_CART0:
616 case REGION_CART0_EX:
617 case REGION_CART1:
618 case REGION_CART1_EX:
619 case REGION_CART2:
620 case REGION_CART2_EX:
621 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
622 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
623 value = ((uint8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
624 } else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
625 value = ((uint8_t*) memory->rom)[address & memory->romMask];
626 } else if (memory->vfame.cartType) {
627 value = GBAVFameGetPatternValue(address, 8);
628 } else {
629 mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load8: 0x%08X", address);
630 value = (address >> 1) & 0xFF;
631 }
632 break;
633 case REGION_CART_SRAM:
634 case REGION_CART_SRAM_MIRROR:
635 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
636 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
637 mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
638 GBASavedataInitSRAM(&memory->savedata);
639 }
640 if (gba->performingDMA == 1) {
641 break;
642 }
643 if (memory->savedata.type == SAVEDATA_SRAM) {
644 value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
645 } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
646 value = GBASavedataReadFlash(&memory->savedata, address);
647 } else if (memory->hw.devices & HW_TILT) {
648 value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK);
649 } else {
650 mLOG(GBA_MEM, GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
651 value = 0xFF;
652 }
653 value &= 0xFF;
654 break;
655 default:
656 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load8: 0x%08x", address);
657 LOAD_BAD;
658 value = (value >> ((address & 3) * 8)) & 0xFF;
659 break;
660 }
661
662 if (cycleCounter) {
663 wait += 2;
664 if (address >> BASE_OFFSET < REGION_CART0) {
665 wait = GBAMemoryStall(cpu, wait);
666 }
667 *cycleCounter += wait;
668 }
669 return value;
670}
671
672#define STORE_WORKING_RAM \
673 STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); \
674 wait += waitstatesRegion[REGION_WORKING_RAM];
675
676#define STORE_WORKING_IRAM \
677 STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
678
679#define STORE_IO \
680 GBAIOWrite32(gba, address & (OFFSET_MASK - 3), value);
681
682#define STORE_PALETTE_RAM \
683 STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
684 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); \
685 wait += waitstatesRegion[REGION_PALETTE_RAM]; \
686 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
687
688#define STORE_VRAM \
689 if ((address & 0x0001FFFF) < SIZE_VRAM) { \
690 STORE_32(value, address & 0x0001FFFC, gba->video.vram); \
691 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \
692 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \
693 } else { \
694 STORE_32(value, address & 0x00017FFC, gba->video.vram); \
695 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \
696 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \
697 } \
698 wait += waitstatesRegion[REGION_VRAM];
699
700#define STORE_OAM \
701 STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); \
702 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
703 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
704
705#define STORE_CART \
706 wait += waitstatesRegion[address >> BASE_OFFSET]; \
707 mLOG(GBA_MEM, STUB, "Unimplemented memory Store32: 0x%08X", address);
708
709#define STORE_SRAM \
710 if (address & 0x3) { \
711 mLOG(GBA_MEM, GAME_ERROR, "Unaligned SRAM Store32: 0x%08X", address); \
712 value = 0; \
713 } \
714 GBAStore8(cpu, address & ~0x3, value, cycleCounter); \
715 GBAStore8(cpu, (address & ~0x3) | 1, value, cycleCounter); \
716 GBAStore8(cpu, (address & ~0x3) | 2, value, cycleCounter); \
717 GBAStore8(cpu, (address & ~0x3) | 3, value, cycleCounter);
718
719#define STORE_BAD \
720 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store32: 0x%08X", address);
721
722void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
723 struct GBA* gba = (struct GBA*) cpu->master;
724 struct GBAMemory* memory = &gba->memory;
725 int wait = 0;
726 char* waitstatesRegion = memory->waitstatesNonseq32;
727
728 switch (address >> BASE_OFFSET) {
729 case REGION_WORKING_RAM:
730 STORE_WORKING_RAM;
731 break;
732 case REGION_WORKING_IRAM:
733 STORE_WORKING_IRAM
734 break;
735 case REGION_IO:
736 STORE_IO;
737 break;
738 case REGION_PALETTE_RAM:
739 STORE_PALETTE_RAM;
740 break;
741 case REGION_VRAM:
742 STORE_VRAM;
743 break;
744 case REGION_OAM:
745 STORE_OAM;
746 break;
747 case REGION_CART0:
748 case REGION_CART0_EX:
749 case REGION_CART1:
750 case REGION_CART1_EX:
751 case REGION_CART2:
752 case REGION_CART2_EX:
753 STORE_CART;
754 break;
755 case REGION_CART_SRAM:
756 case REGION_CART_SRAM_MIRROR:
757 STORE_SRAM;
758 break;
759 default:
760 STORE_BAD;
761 break;
762 }
763
764 if (cycleCounter) {
765 ++wait;
766 if (address >> BASE_OFFSET < REGION_CART0) {
767 wait = GBAMemoryStall(cpu, wait);
768 }
769 *cycleCounter += wait;
770 }
771}
772
773void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
774 struct GBA* gba = (struct GBA*) cpu->master;
775 struct GBAMemory* memory = &gba->memory;
776 int wait = 0;
777
778 switch (address >> BASE_OFFSET) {
779 case REGION_WORKING_RAM:
780 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
781 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
782 break;
783 case REGION_WORKING_IRAM:
784 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
785 break;
786 case REGION_IO:
787 GBAIOWrite(gba, address & (OFFSET_MASK - 1), value);
788 break;
789 case REGION_PALETTE_RAM:
790 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
791 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
792 break;
793 case REGION_VRAM:
794 if ((address & 0x0001FFFF) < SIZE_VRAM) {
795 STORE_16(value, address & 0x0001FFFE, gba->video.vram);
796 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
797 } else {
798 STORE_16(value, address & 0x00017FFE, gba->video.vram);
799 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE);
800 }
801 break;
802 case REGION_OAM:
803 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
804 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
805 break;
806 case REGION_CART0:
807 if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFE)) {
808 uint32_t reg = address & 0xFFFFFE;
809 GBAHardwareGPIOWrite(&memory->hw, reg, value);
810 } else {
811 mLOG(GBA_MEM, GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
812 }
813 break;
814 case REGION_CART2_EX:
815 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
816 mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
817 GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming);
818 }
819 GBASavedataWriteEEPROM(&memory->savedata, value, 1);
820 break;
821 case REGION_CART_SRAM:
822 case REGION_CART_SRAM_MIRROR:
823 GBAStore8(cpu, (address & ~0x1), value, cycleCounter);
824 GBAStore8(cpu, (address & ~0x1) | 1, value, cycleCounter);
825 break;
826 default:
827 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store16: 0x%08X", address);
828 break;
829 }
830
831 if (cycleCounter) {
832 ++wait;
833 if (address >> BASE_OFFSET < REGION_CART0) {
834 wait = GBAMemoryStall(cpu, wait);
835 }
836 *cycleCounter += wait;
837 }
838}
839
840void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
841 struct GBA* gba = (struct GBA*) cpu->master;
842 struct GBAMemory* memory = &gba->memory;
843 int wait = 0;
844
845 switch (address >> BASE_OFFSET) {
846 case REGION_WORKING_RAM:
847 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
848 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
849 break;
850 case REGION_WORKING_IRAM:
851 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
852 break;
853 case REGION_IO:
854 GBAIOWrite8(gba, address & OFFSET_MASK, value);
855 break;
856 case REGION_PALETTE_RAM:
857 GBAStore16(cpu, address & ~1, ((uint8_t) value) | ((uint8_t) value << 8), cycleCounter);
858 break;
859 case REGION_VRAM:
860 if ((address & 0x0001FFFF) >= ((GBARegisterDISPCNTGetMode(gba->memory.io[REG_DISPCNT >> 1]) == 4) ? 0x00014000 : 0x00010000)) {
861 // TODO: check BG mode
862 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
863 break;
864 }
865 gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
866 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
867 break;
868 case REGION_OAM:
869 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
870 break;
871 case REGION_CART0:
872 mLOG(GBA_MEM, STUB, "Unimplemented memory Store8: 0x%08X", address);
873 break;
874 case REGION_CART_SRAM:
875 case REGION_CART_SRAM_MIRROR:
876 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
877 if (address == SAVEDATA_FLASH_BASE) {
878 mLOG(GBA_MEM, INFO, "Detected Flash savegame");
879 GBASavedataInitFlash(&memory->savedata, gba->realisticTiming);
880 } else {
881 mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
882 GBASavedataInitSRAM(&memory->savedata);
883 }
884 }
885 if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
886 GBASavedataWriteFlash(&memory->savedata, address, value);
887 } else if (memory->savedata.type == SAVEDATA_SRAM) {
888 if (memory->vfame.cartType) {
889 GBAVFameSramWrite(&memory->vfame, address, value, memory->savedata.data);
890 } else {
891 memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
892 }
893 memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
894 } else if (memory->hw.devices & HW_TILT) {
895 GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
896 } else {
897 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
898 }
899 wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
900 break;
901 default:
902 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store8: 0x%08X", address);
903 break;
904 }
905
906 if (cycleCounter) {
907 ++wait;
908 if (address >> BASE_OFFSET < REGION_CART0) {
909 wait = GBAMemoryStall(cpu, wait);
910 }
911 *cycleCounter += wait;
912 }
913}
914
915uint32_t GBAView32(struct ARMCore* cpu, uint32_t address) {
916 struct GBA* gba = (struct GBA*) cpu->master;
917 uint32_t value = 0;
918 address &= ~3;
919 switch (address >> BASE_OFFSET) {
920 case REGION_BIOS:
921 if (address < SIZE_BIOS) {
922 LOAD_32(value, address, gba->memory.bios);
923 }
924 break;
925 case REGION_WORKING_RAM:
926 case REGION_WORKING_IRAM:
927 case REGION_PALETTE_RAM:
928 case REGION_VRAM:
929 case REGION_OAM:
930 case REGION_CART0:
931 case REGION_CART0_EX:
932 case REGION_CART1:
933 case REGION_CART1_EX:
934 case REGION_CART2:
935 case REGION_CART2_EX:
936 value = GBALoad32(cpu, address, 0);
937 break;
938 case REGION_IO:
939 if ((address & OFFSET_MASK) < REG_MAX) {
940 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
941 value |= gba->memory.io[((address & OFFSET_MASK) >> 1) + 1] << 16;
942 }
943 break;
944 case REGION_CART_SRAM:
945 value = GBALoad8(cpu, address, 0);
946 value |= GBALoad8(cpu, address + 1, 0) << 8;
947 value |= GBALoad8(cpu, address + 2, 0) << 16;
948 value |= GBALoad8(cpu, address + 3, 0) << 24;
949 break;
950 default:
951 break;
952 }
953 return value;
954}
955
956uint16_t GBAView16(struct ARMCore* cpu, uint32_t address) {
957 struct GBA* gba = (struct GBA*) cpu->master;
958 uint16_t value = 0;
959 address &= ~1;
960 switch (address >> BASE_OFFSET) {
961 case REGION_BIOS:
962 if (address < SIZE_BIOS) {
963 LOAD_16(value, address, gba->memory.bios);
964 }
965 break;
966 case REGION_WORKING_RAM:
967 case REGION_WORKING_IRAM:
968 case REGION_PALETTE_RAM:
969 case REGION_VRAM:
970 case REGION_OAM:
971 case REGION_CART0:
972 case REGION_CART0_EX:
973 case REGION_CART1:
974 case REGION_CART1_EX:
975 case REGION_CART2:
976 case REGION_CART2_EX:
977 value = GBALoad16(cpu, address, 0);
978 break;
979 case REGION_IO:
980 if ((address & OFFSET_MASK) < REG_MAX) {
981 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
982 }
983 break;
984 case REGION_CART_SRAM:
985 value = GBALoad8(cpu, address, 0);
986 value |= GBALoad8(cpu, address + 1, 0) << 8;
987 break;
988 default:
989 break;
990 }
991 return value;
992}
993
994uint8_t GBAView8(struct ARMCore* cpu, uint32_t address) {
995 struct GBA* gba = (struct GBA*) cpu->master;
996 uint8_t value = 0;
997 switch (address >> BASE_OFFSET) {
998 case REGION_BIOS:
999 if (address < SIZE_BIOS) {
1000 value = ((uint8_t*) gba->memory.bios)[address];
1001 }
1002 break;
1003 case REGION_WORKING_RAM:
1004 case REGION_WORKING_IRAM:
1005 case REGION_CART0:
1006 case REGION_CART0_EX:
1007 case REGION_CART1:
1008 case REGION_CART1_EX:
1009 case REGION_CART2:
1010 case REGION_CART2_EX:
1011 case REGION_CART_SRAM:
1012 value = GBALoad8(cpu, address, 0);
1013 break;
1014 case REGION_IO:
1015 case REGION_PALETTE_RAM:
1016 case REGION_VRAM:
1017 case REGION_OAM:
1018 value = GBAView16(cpu, address) >> ((address & 1) * 8);
1019 break;
1020 default:
1021 break;
1022 }
1023 return value;
1024}
1025
1026void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old) {
1027 struct GBA* gba = (struct GBA*) cpu->master;
1028 struct GBAMemory* memory = &gba->memory;
1029 int32_t oldValue = -1;
1030
1031 switch (address >> BASE_OFFSET) {
1032 case REGION_WORKING_RAM:
1033 LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 4), memory->wram);
1034 STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram);
1035 break;
1036 case REGION_WORKING_IRAM:
1037 LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1038 STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1039 break;
1040 case REGION_IO:
1041 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch32: 0x%08X", address);
1042 break;
1043 case REGION_PALETTE_RAM:
1044 LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
1045 STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette);
1046 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
1047 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16);
1048 break;
1049 case REGION_VRAM:
1050 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1051 LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram);
1052 STORE_32(value, address & 0x0001FFFC, gba->video.vram);
1053 } else {
1054 LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram);
1055 STORE_32(value, address & 0x00017FFC, gba->video.vram);
1056 }
1057 break;
1058 case REGION_OAM:
1059 LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw);
1060 STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
1061 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
1062 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) + 2) >> 1);
1063 break;
1064 case REGION_CART0:
1065 case REGION_CART0_EX:
1066 case REGION_CART1:
1067 case REGION_CART1_EX:
1068 case REGION_CART2:
1069 case REGION_CART2_EX:
1070 _pristineCow(gba);
1071 if ((address & (SIZE_CART0 - 4)) >= gba->memory.romSize) {
1072 gba->memory.romSize = (address & (SIZE_CART0 - 4)) + 4;
1073 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1074 }
1075 LOAD_32(oldValue, address & (SIZE_CART0 - 4), gba->memory.rom);
1076 STORE_32(value, address & (SIZE_CART0 - 4), gba->memory.rom);
1077 break;
1078 case REGION_CART_SRAM:
1079 case REGION_CART_SRAM_MIRROR:
1080 if (memory->savedata.type == SAVEDATA_SRAM) {
1081 LOAD_32(oldValue, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1082 STORE_32(value, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1083 } else {
1084 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1085 }
1086 break;
1087 default:
1088 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1089 break;
1090 }
1091 if (old) {
1092 *old = oldValue;
1093 }
1094}
1095
1096void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old) {
1097 struct GBA* gba = (struct GBA*) cpu->master;
1098 struct GBAMemory* memory = &gba->memory;
1099 int16_t oldValue = -1;
1100
1101 switch (address >> BASE_OFFSET) {
1102 case REGION_WORKING_RAM:
1103 LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 2), memory->wram);
1104 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
1105 break;
1106 case REGION_WORKING_IRAM:
1107 LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1108 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1109 break;
1110 case REGION_IO:
1111 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch16: 0x%08X", address);
1112 break;
1113 case REGION_PALETTE_RAM:
1114 LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1115 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1116 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
1117 break;
1118 case REGION_VRAM:
1119 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1120 LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram);
1121 STORE_16(value, address & 0x0001FFFE, gba->video.vram);
1122 } else {
1123 LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram);
1124 STORE_16(value, address & 0x00017FFE, gba->video.vram);
1125 }
1126 break;
1127 case REGION_OAM:
1128 LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
1129 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
1130 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
1131 break;
1132 case REGION_CART0:
1133 case REGION_CART0_EX:
1134 case REGION_CART1:
1135 case REGION_CART1_EX:
1136 case REGION_CART2:
1137 case REGION_CART2_EX:
1138 _pristineCow(gba);
1139 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1140 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1141 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1142 }
1143 LOAD_16(oldValue, address & (SIZE_CART0 - 2), gba->memory.rom);
1144 STORE_16(value, address & (SIZE_CART0 - 2), gba->memory.rom);
1145 break;
1146 case REGION_CART_SRAM:
1147 case REGION_CART_SRAM_MIRROR:
1148 if (memory->savedata.type == SAVEDATA_SRAM) {
1149 LOAD_16(oldValue, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1150 STORE_16(value, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1151 } else {
1152 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1153 }
1154 break;
1155 default:
1156 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1157 break;
1158 }
1159 if (old) {
1160 *old = oldValue;
1161 }
1162}
1163
1164void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) {
1165 struct GBA* gba = (struct GBA*) cpu->master;
1166 struct GBAMemory* memory = &gba->memory;
1167 int8_t oldValue = -1;
1168
1169 switch (address >> BASE_OFFSET) {
1170 case REGION_WORKING_RAM:
1171 oldValue = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
1172 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
1173 break;
1174 case REGION_WORKING_IRAM:
1175 oldValue = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
1176 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
1177 break;
1178 case REGION_IO:
1179 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1180 break;
1181 case REGION_PALETTE_RAM:
1182 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1183 break;
1184 case REGION_VRAM:
1185 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1186 break;
1187 case REGION_OAM:
1188 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1189 break;
1190 case REGION_CART0:
1191 case REGION_CART0_EX:
1192 case REGION_CART1:
1193 case REGION_CART1_EX:
1194 case REGION_CART2:
1195 case REGION_CART2_EX:
1196 _pristineCow(gba);
1197 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1198 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1199 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1200 }
1201 oldValue = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
1202 ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)] = value;
1203 break;
1204 case REGION_CART_SRAM:
1205 case REGION_CART_SRAM_MIRROR:
1206 if (memory->savedata.type == SAVEDATA_SRAM) {
1207 oldValue = ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)];
1208 ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)] = value;
1209 } else {
1210 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1211 }
1212 break;
1213 default:
1214 mLOG(GBA_MEM, WARN, "Bad memory Patch8: 0x%08X", address);
1215 break;
1216 }
1217 if (old) {
1218 *old = oldValue;
1219 }
1220}
1221
1222#define LDM_LOOP(LDM) \
1223 for (i = 0; i < 16; i += 4) { \
1224 if (UNLIKELY(mask & (1 << i))) { \
1225 LDM; \
1226 cpu->gprs[i] = value; \
1227 ++wait; \
1228 address += 4; \
1229 } \
1230 if (UNLIKELY(mask & (2 << i))) { \
1231 LDM; \
1232 cpu->gprs[i + 1] = value; \
1233 ++wait; \
1234 address += 4; \
1235 } \
1236 if (UNLIKELY(mask & (4 << i))) { \
1237 LDM; \
1238 cpu->gprs[i + 2] = value; \
1239 ++wait; \
1240 address += 4; \
1241 } \
1242 if (UNLIKELY(mask & (8 << i))) { \
1243 LDM; \
1244 cpu->gprs[i + 3] = value; \
1245 ++wait; \
1246 address += 4; \
1247 } \
1248 }
1249
1250uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1251 struct GBA* gba = (struct GBA*) cpu->master;
1252 struct GBAMemory* memory = &gba->memory;
1253 uint32_t value;
1254 char* waitstatesRegion = memory->waitstatesSeq32;
1255
1256 int i;
1257 int offset = 4;
1258 int popcount = 0;
1259 if (direction & LSM_D) {
1260 offset = -4;
1261 popcount = popcount32(mask);
1262 address -= (popcount << 2) - 4;
1263 }
1264
1265 if (direction & LSM_B) {
1266 address += offset;
1267 }
1268
1269 uint32_t addressMisalign = address & 0x3;
1270 int region = address >> BASE_OFFSET;
1271 if (region < REGION_CART_SRAM) {
1272 address &= 0xFFFFFFFC;
1273 }
1274 int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1275
1276 switch (region) {
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 ++wait; \
1340 address += 4; \
1341 } \
1342 if (UNLIKELY(mask & (2 << i))) { \
1343 value = cpu->gprs[i + 1]; \
1344 STM; \
1345 ++wait; \
1346 address += 4; \
1347 } \
1348 if (UNLIKELY(mask & (4 << i))) { \
1349 value = cpu->gprs[i + 2]; \
1350 STM; \
1351 ++wait; \
1352 address += 4; \
1353 } \
1354 if (UNLIKELY(mask & (8 << i))) { \
1355 value = cpu->gprs[i + 3]; \
1356 if (i + 3 == ARM_PC) { \
1357 value += WORD_SIZE_ARM; \
1358 } \
1359 STM; \
1360 ++wait; \
1361 address += 4; \
1362 } \
1363 }
1364
1365uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1366 struct GBA* gba = (struct GBA*) cpu->master;
1367 struct GBAMemory* memory = &gba->memory;
1368 uint32_t value;
1369 char* waitstatesRegion = memory->waitstatesSeq32;
1370
1371 int i;
1372 int offset = 4;
1373 int popcount = 0;
1374 if (direction & LSM_D) {
1375 offset = -4;
1376 popcount = popcount32(mask);
1377 address -= (popcount << 2) - 4;
1378 }
1379
1380 if (direction & LSM_B) {
1381 address += offset;
1382 }
1383
1384 uint32_t addressMisalign = address & 0x3;
1385 int region = address >> BASE_OFFSET;
1386 if (region < REGION_CART_SRAM) {
1387 address &= 0xFFFFFFFC;
1388 }
1389 int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1390
1391 switch (region) {
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
1487int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) {
1488 struct GBA* gba = (struct GBA*) cpu->master;
1489 struct GBAMemory* memory = &gba->memory;
1490
1491 if (memory->activeRegion < REGION_CART0 || !memory->prefetch) {
1492 // The wait is the stall
1493 return wait;
1494 }
1495
1496 int32_t previousLoads = 0;
1497
1498 // Don't prefetch too much if we're overlapping with a previous prefetch
1499 uint32_t dist = (memory->lastPrefetchedPc - cpu->gprs[ARM_PC]) >> 1;
1500 if (dist < 8) {
1501 previousLoads = dist;
1502 }
1503
1504 int32_t s = cpu->memory.activeSeqCycles16;
1505 int32_t n2s = cpu->memory.activeNonseqCycles16 - cpu->memory.activeSeqCycles16;
1506
1507 // Figure out how many sequential loads we can jam in
1508 int32_t stall = s;
1509 int32_t loads = 1;
1510
1511 if (stall < wait) {
1512 int32_t maxLoads = 8 - previousLoads;
1513 while (stall < wait && loads < maxLoads) {
1514 stall += s;
1515 ++loads;
1516 }
1517 }
1518 if (stall > wait) {
1519 // The wait cannot take less time than the prefetch stalls
1520 wait = stall;
1521 }
1522
1523 // This instruction used to have an N, convert it to an S.
1524 wait -= n2s;
1525
1526 memory->lastPrefetchedPc = cpu->gprs[ARM_PC] + WORD_SIZE_THUMB * (loads + previousLoads - 1);
1527
1528 // The next |loads|S waitstates disappear entirely, so long as they're all in a row
1529 cpu->cycles -= stall;
1530 return wait;
1531}
1532
1533void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state) {
1534 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1535 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1536}
1537
1538void GBAMemoryDeserialize(struct GBAMemory* memory, const struct GBASerializedState* state) {
1539 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1540 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1541}
1542
1543void _pristineCow(struct GBA* gba) {
1544 if (!gba->isPristine) {
1545 return;
1546 }
1547 void* newRom = anonymousMemoryMap(SIZE_CART0);
1548 memcpy(newRom, gba->memory.rom, gba->memory.romSize);
1549 memset(((uint8_t*) newRom) + gba->memory.romSize, 0xFF, SIZE_CART0 - gba->memory.romSize);
1550 if (gba->cpu->memory.activeRegion == gba->memory.rom) {
1551 gba->cpu->memory.activeRegion = newRom;
1552 }
1553 if (gba->romVf) {
1554#ifndef _3DS
1555 gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->memory.romSize);
1556#endif
1557 gba->romVf->close(gba->romVf);
1558 gba->romVf = NULL;
1559 }
1560 gba->memory.rom = newRom;
1561 gba->memory.hw.gpioBase = &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1];
1562}