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