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