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 LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
687 if (oldValue != value) { \
688 STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
689 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); \
690 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value); \
691 } \
692 wait += waitstatesRegion[REGION_PALETTE_RAM];
693
694#define STORE_VRAM \
695 if ((address & 0x0001FFFF) < SIZE_VRAM) { \
696 LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram); \
697 if (oldValue != value) { \
698 STORE_32(value, address & 0x0001FFFC, gba->video.vram); \
699 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \
700 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \
701 } \
702 } else { \
703 LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram); \
704 if (oldValue != value) { \
705 STORE_32(value, address & 0x00017FFC, gba->video.vram); \
706 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \
707 gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \
708 } \
709 } \
710 wait += waitstatesRegion[REGION_VRAM];
711
712#define STORE_OAM \
713 LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw); \
714 if (oldValue != value) { \
715 STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); \
716 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
717 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1); \
718 }
719
720#define STORE_CART \
721 wait += waitstatesRegion[address >> BASE_OFFSET]; \
722 mLOG(GBA_MEM, STUB, "Unimplemented memory Store32: 0x%08X", address);
723
724#define STORE_SRAM \
725 if (address & 0x3) { \
726 mLOG(GBA_MEM, GAME_ERROR, "Unaligned SRAM Store32: 0x%08X", address); \
727 value = 0; \
728 } \
729 GBAStore8(cpu, address & ~0x3, value, cycleCounter); \
730 GBAStore8(cpu, (address & ~0x3) | 1, value, cycleCounter); \
731 GBAStore8(cpu, (address & ~0x3) | 2, value, cycleCounter); \
732 GBAStore8(cpu, (address & ~0x3) | 3, value, cycleCounter);
733
734#define STORE_BAD \
735 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store32: 0x%08X", address);
736
737void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
738 struct GBA* gba = (struct GBA*) cpu->master;
739 struct GBAMemory* memory = &gba->memory;
740 int wait = 0;
741 int32_t oldValue;
742 char* waitstatesRegion = memory->waitstatesNonseq32;
743
744 switch (address >> BASE_OFFSET) {
745 case REGION_WORKING_RAM:
746 STORE_WORKING_RAM;
747 break;
748 case REGION_WORKING_IRAM:
749 STORE_WORKING_IRAM
750 break;
751 case REGION_IO:
752 STORE_IO;
753 break;
754 case REGION_PALETTE_RAM:
755 STORE_PALETTE_RAM;
756 break;
757 case REGION_VRAM:
758 STORE_VRAM;
759 break;
760 case REGION_OAM:
761 STORE_OAM;
762 break;
763 case REGION_CART0:
764 case REGION_CART0_EX:
765 case REGION_CART1:
766 case REGION_CART1_EX:
767 case REGION_CART2:
768 case REGION_CART2_EX:
769 STORE_CART;
770 break;
771 case REGION_CART_SRAM:
772 case REGION_CART_SRAM_MIRROR:
773 STORE_SRAM;
774 break;
775 default:
776 STORE_BAD;
777 break;
778 }
779
780 if (cycleCounter) {
781 ++wait;
782 if (address >> BASE_OFFSET < REGION_CART0) {
783 wait = GBAMemoryStall(cpu, wait);
784 }
785 *cycleCounter += wait;
786 }
787}
788
789void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
790 struct GBA* gba = (struct GBA*) cpu->master;
791 struct GBAMemory* memory = &gba->memory;
792 int wait = 0;
793 int16_t oldValue;
794
795 switch (address >> BASE_OFFSET) {
796 case REGION_WORKING_RAM:
797 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
798 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
799 break;
800 case REGION_WORKING_IRAM:
801 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
802 break;
803 case REGION_IO:
804 GBAIOWrite(gba, address & (OFFSET_MASK - 1), value);
805 break;
806 case REGION_PALETTE_RAM:
807 LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
808 if (oldValue != value) {
809 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
810 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
811 }
812 break;
813 case REGION_VRAM:
814 if ((address & 0x0001FFFF) < SIZE_VRAM) {
815 LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram);
816 if (value != oldValue) {
817 STORE_16(value, address & 0x0001FFFE, gba->video.vram);
818 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
819 }
820 } else {
821 LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram);
822 if (value != oldValue) {
823 STORE_16(value, address & 0x00017FFE, gba->video.vram);
824 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE);
825 }
826 }
827 break;
828 case REGION_OAM:
829 LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
830 if (value != oldValue) {
831 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
832 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
833 }
834 break;
835 case REGION_CART0:
836 if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFE)) {
837 uint32_t reg = address & 0xFFFFFE;
838 GBAHardwareGPIOWrite(&memory->hw, reg, value);
839 } else {
840 mLOG(GBA_MEM, GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
841 }
842 break;
843 case REGION_CART2_EX:
844 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
845 mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
846 GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming);
847 }
848 GBASavedataWriteEEPROM(&memory->savedata, value, 1);
849 break;
850 case REGION_CART_SRAM:
851 case REGION_CART_SRAM_MIRROR:
852 GBAStore8(cpu, (address & ~0x1), value, cycleCounter);
853 GBAStore8(cpu, (address & ~0x1) | 1, value, cycleCounter);
854 break;
855 default:
856 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store16: 0x%08X", address);
857 break;
858 }
859
860 if (cycleCounter) {
861 ++wait;
862 if (address >> BASE_OFFSET < REGION_CART0) {
863 wait = GBAMemoryStall(cpu, wait);
864 }
865 *cycleCounter += wait;
866 }
867}
868
869void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
870 struct GBA* gba = (struct GBA*) cpu->master;
871 struct GBAMemory* memory = &gba->memory;
872 int wait = 0;
873 uint16_t oldValue;
874
875 switch (address >> BASE_OFFSET) {
876 case REGION_WORKING_RAM:
877 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
878 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
879 break;
880 case REGION_WORKING_IRAM:
881 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
882 break;
883 case REGION_IO:
884 GBAIOWrite8(gba, address & OFFSET_MASK, value);
885 break;
886 case REGION_PALETTE_RAM:
887 GBAStore16(cpu, address & ~1, ((uint8_t) value) | ((uint8_t) value << 8), cycleCounter);
888 break;
889 case REGION_VRAM:
890 if ((address & 0x0001FFFF) >= ((GBARegisterDISPCNTGetMode(gba->memory.io[REG_DISPCNT >> 1]) == 4) ? 0x00014000 : 0x00010000)) {
891 // TODO: check BG mode
892 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
893 break;
894 }
895 oldValue = gba->video.renderer->vram[(address & 0x1FFFE) >> 1];
896 if (oldValue != (((uint8_t) value) | (value << 8))) {
897 gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
898 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
899 }
900 break;
901 case REGION_OAM:
902 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
903 break;
904 case REGION_CART0:
905 mLOG(GBA_MEM, STUB, "Unimplemented memory Store8: 0x%08X", address);
906 break;
907 case REGION_CART_SRAM:
908 case REGION_CART_SRAM_MIRROR:
909 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
910 if (address == SAVEDATA_FLASH_BASE) {
911 mLOG(GBA_MEM, INFO, "Detected Flash savegame");
912 GBASavedataInitFlash(&memory->savedata, gba->realisticTiming);
913 } else {
914 mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
915 GBASavedataInitSRAM(&memory->savedata);
916 }
917 }
918 if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
919 GBASavedataWriteFlash(&memory->savedata, address, value);
920 } else if (memory->savedata.type == SAVEDATA_SRAM) {
921 if (memory->vfame.cartType) {
922 GBAVFameSramWrite(&memory->vfame, address, value, memory->savedata.data);
923 } else {
924 memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
925 }
926 memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
927 } else if (memory->hw.devices & HW_TILT) {
928 GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
929 } else {
930 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
931 }
932 wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
933 break;
934 default:
935 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store8: 0x%08X", address);
936 break;
937 }
938
939 if (cycleCounter) {
940 ++wait;
941 if (address >> BASE_OFFSET < REGION_CART0) {
942 wait = GBAMemoryStall(cpu, wait);
943 }
944 *cycleCounter += wait;
945 }
946}
947
948uint32_t GBAView32(struct ARMCore* cpu, uint32_t address) {
949 struct GBA* gba = (struct GBA*) cpu->master;
950 uint32_t value = 0;
951 address &= ~3;
952 switch (address >> BASE_OFFSET) {
953 case REGION_BIOS:
954 if (address < SIZE_BIOS) {
955 LOAD_32(value, address, gba->memory.bios);
956 }
957 break;
958 case REGION_WORKING_RAM:
959 case REGION_WORKING_IRAM:
960 case REGION_PALETTE_RAM:
961 case REGION_VRAM:
962 case REGION_OAM:
963 case REGION_CART0:
964 case REGION_CART0_EX:
965 case REGION_CART1:
966 case REGION_CART1_EX:
967 case REGION_CART2:
968 case REGION_CART2_EX:
969 value = GBALoad32(cpu, address, 0);
970 break;
971 case REGION_IO:
972 if ((address & OFFSET_MASK) < REG_MAX) {
973 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
974 value |= gba->memory.io[((address & OFFSET_MASK) >> 1) + 1] << 16;
975 }
976 break;
977 case REGION_CART_SRAM:
978 value = GBALoad8(cpu, address, 0);
979 value |= GBALoad8(cpu, address + 1, 0) << 8;
980 value |= GBALoad8(cpu, address + 2, 0) << 16;
981 value |= GBALoad8(cpu, address + 3, 0) << 24;
982 break;
983 default:
984 break;
985 }
986 return value;
987}
988
989uint16_t GBAView16(struct ARMCore* cpu, uint32_t address) {
990 struct GBA* gba = (struct GBA*) cpu->master;
991 uint16_t value = 0;
992 address &= ~1;
993 switch (address >> BASE_OFFSET) {
994 case REGION_BIOS:
995 if (address < SIZE_BIOS) {
996 LOAD_16(value, address, gba->memory.bios);
997 }
998 break;
999 case REGION_WORKING_RAM:
1000 case REGION_WORKING_IRAM:
1001 case REGION_PALETTE_RAM:
1002 case REGION_VRAM:
1003 case REGION_OAM:
1004 case REGION_CART0:
1005 case REGION_CART0_EX:
1006 case REGION_CART1:
1007 case REGION_CART1_EX:
1008 case REGION_CART2:
1009 case REGION_CART2_EX:
1010 value = GBALoad16(cpu, address, 0);
1011 break;
1012 case REGION_IO:
1013 if ((address & OFFSET_MASK) < REG_MAX) {
1014 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
1015 }
1016 break;
1017 case REGION_CART_SRAM:
1018 value = GBALoad8(cpu, address, 0);
1019 value |= GBALoad8(cpu, address + 1, 0) << 8;
1020 break;
1021 default:
1022 break;
1023 }
1024 return value;
1025}
1026
1027uint8_t GBAView8(struct ARMCore* cpu, uint32_t address) {
1028 struct GBA* gba = (struct GBA*) cpu->master;
1029 uint8_t value = 0;
1030 switch (address >> BASE_OFFSET) {
1031 case REGION_BIOS:
1032 if (address < SIZE_BIOS) {
1033 value = ((uint8_t*) gba->memory.bios)[address];
1034 }
1035 break;
1036 case REGION_WORKING_RAM:
1037 case REGION_WORKING_IRAM:
1038 case REGION_CART0:
1039 case REGION_CART0_EX:
1040 case REGION_CART1:
1041 case REGION_CART1_EX:
1042 case REGION_CART2:
1043 case REGION_CART2_EX:
1044 case REGION_CART_SRAM:
1045 value = GBALoad8(cpu, address, 0);
1046 break;
1047 case REGION_IO:
1048 case REGION_PALETTE_RAM:
1049 case REGION_VRAM:
1050 case REGION_OAM:
1051 value = GBAView16(cpu, address) >> ((address & 1) * 8);
1052 break;
1053 default:
1054 break;
1055 }
1056 return value;
1057}
1058
1059void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old) {
1060 struct GBA* gba = (struct GBA*) cpu->master;
1061 struct GBAMemory* memory = &gba->memory;
1062 int32_t oldValue = -1;
1063
1064 switch (address >> BASE_OFFSET) {
1065 case REGION_WORKING_RAM:
1066 LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 4), memory->wram);
1067 STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram);
1068 break;
1069 case REGION_WORKING_IRAM:
1070 LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1071 STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1072 break;
1073 case REGION_IO:
1074 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch32: 0x%08X", address);
1075 break;
1076 case REGION_PALETTE_RAM:
1077 LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
1078 STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette);
1079 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
1080 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16);
1081 break;
1082 case REGION_VRAM:
1083 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1084 LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram);
1085 STORE_32(value, address & 0x0001FFFC, gba->video.vram);
1086 } else {
1087 LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram);
1088 STORE_32(value, address & 0x00017FFC, gba->video.vram);
1089 }
1090 break;
1091 case REGION_OAM:
1092 LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw);
1093 STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
1094 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
1095 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) + 2) >> 1);
1096 break;
1097 case REGION_CART0:
1098 case REGION_CART0_EX:
1099 case REGION_CART1:
1100 case REGION_CART1_EX:
1101 case REGION_CART2:
1102 case REGION_CART2_EX:
1103 _pristineCow(gba);
1104 if ((address & (SIZE_CART0 - 4)) >= gba->memory.romSize) {
1105 gba->memory.romSize = (address & (SIZE_CART0 - 4)) + 4;
1106 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1107 }
1108 LOAD_32(oldValue, address & (SIZE_CART0 - 4), gba->memory.rom);
1109 STORE_32(value, address & (SIZE_CART0 - 4), gba->memory.rom);
1110 break;
1111 case REGION_CART_SRAM:
1112 case REGION_CART_SRAM_MIRROR:
1113 if (memory->savedata.type == SAVEDATA_SRAM) {
1114 LOAD_32(oldValue, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1115 STORE_32(value, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1116 } else {
1117 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1118 }
1119 break;
1120 default:
1121 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1122 break;
1123 }
1124 if (old) {
1125 *old = oldValue;
1126 }
1127}
1128
1129void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old) {
1130 struct GBA* gba = (struct GBA*) cpu->master;
1131 struct GBAMemory* memory = &gba->memory;
1132 int16_t oldValue = -1;
1133
1134 switch (address >> BASE_OFFSET) {
1135 case REGION_WORKING_RAM:
1136 LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 2), memory->wram);
1137 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
1138 break;
1139 case REGION_WORKING_IRAM:
1140 LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1141 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1142 break;
1143 case REGION_IO:
1144 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch16: 0x%08X", address);
1145 break;
1146 case REGION_PALETTE_RAM:
1147 LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1148 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1149 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
1150 break;
1151 case REGION_VRAM:
1152 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1153 LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram);
1154 STORE_16(value, address & 0x0001FFFE, gba->video.vram);
1155 } else {
1156 LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram);
1157 STORE_16(value, address & 0x00017FFE, gba->video.vram);
1158 }
1159 break;
1160 case REGION_OAM:
1161 LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
1162 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
1163 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
1164 break;
1165 case REGION_CART0:
1166 case REGION_CART0_EX:
1167 case REGION_CART1:
1168 case REGION_CART1_EX:
1169 case REGION_CART2:
1170 case REGION_CART2_EX:
1171 _pristineCow(gba);
1172 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1173 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1174 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1175 }
1176 LOAD_16(oldValue, address & (SIZE_CART0 - 2), gba->memory.rom);
1177 STORE_16(value, address & (SIZE_CART0 - 2), gba->memory.rom);
1178 break;
1179 case REGION_CART_SRAM:
1180 case REGION_CART_SRAM_MIRROR:
1181 if (memory->savedata.type == SAVEDATA_SRAM) {
1182 LOAD_16(oldValue, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1183 STORE_16(value, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1184 } else {
1185 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1186 }
1187 break;
1188 default:
1189 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1190 break;
1191 }
1192 if (old) {
1193 *old = oldValue;
1194 }
1195}
1196
1197void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) {
1198 struct GBA* gba = (struct GBA*) cpu->master;
1199 struct GBAMemory* memory = &gba->memory;
1200 int8_t oldValue = -1;
1201
1202 switch (address >> BASE_OFFSET) {
1203 case REGION_WORKING_RAM:
1204 oldValue = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
1205 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
1206 break;
1207 case REGION_WORKING_IRAM:
1208 oldValue = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
1209 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
1210 break;
1211 case REGION_IO:
1212 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1213 break;
1214 case REGION_PALETTE_RAM:
1215 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1216 break;
1217 case REGION_VRAM:
1218 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1219 break;
1220 case REGION_OAM:
1221 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1222 break;
1223 case REGION_CART0:
1224 case REGION_CART0_EX:
1225 case REGION_CART1:
1226 case REGION_CART1_EX:
1227 case REGION_CART2:
1228 case REGION_CART2_EX:
1229 _pristineCow(gba);
1230 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1231 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1232 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1233 }
1234 oldValue = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
1235 ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)] = value;
1236 break;
1237 case REGION_CART_SRAM:
1238 case REGION_CART_SRAM_MIRROR:
1239 if (memory->savedata.type == SAVEDATA_SRAM) {
1240 oldValue = ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)];
1241 ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)] = value;
1242 } else {
1243 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1244 }
1245 break;
1246 default:
1247 mLOG(GBA_MEM, WARN, "Bad memory Patch8: 0x%08X", address);
1248 break;
1249 }
1250 if (old) {
1251 *old = oldValue;
1252 }
1253}
1254
1255#define LDM_LOOP(LDM) \
1256 for (i = 0; i < 16; i += 4) { \
1257 if (UNLIKELY(mask & (1 << i))) { \
1258 LDM; \
1259 cpu->gprs[i] = value; \
1260 ++wait; \
1261 address += 4; \
1262 } \
1263 if (UNLIKELY(mask & (2 << i))) { \
1264 LDM; \
1265 cpu->gprs[i + 1] = value; \
1266 ++wait; \
1267 address += 4; \
1268 } \
1269 if (UNLIKELY(mask & (4 << i))) { \
1270 LDM; \
1271 cpu->gprs[i + 2] = value; \
1272 ++wait; \
1273 address += 4; \
1274 } \
1275 if (UNLIKELY(mask & (8 << i))) { \
1276 LDM; \
1277 cpu->gprs[i + 3] = value; \
1278 ++wait; \
1279 address += 4; \
1280 } \
1281 }
1282
1283uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1284 struct GBA* gba = (struct GBA*) cpu->master;
1285 struct GBAMemory* memory = &gba->memory;
1286 uint32_t value;
1287 char* waitstatesRegion = memory->waitstatesSeq32;
1288
1289 int i;
1290 int offset = 4;
1291 int popcount = 0;
1292 if (direction & LSM_D) {
1293 offset = -4;
1294 popcount = popcount32(mask);
1295 address -= (popcount << 2) - 4;
1296 }
1297
1298 if (direction & LSM_B) {
1299 address += offset;
1300 }
1301
1302 uint32_t addressMisalign = address & 0x3;
1303 int region = address >> BASE_OFFSET;
1304 if (region < REGION_CART_SRAM) {
1305 address &= 0xFFFFFFFC;
1306 }
1307 int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1308
1309 switch (region) {
1310 case REGION_BIOS:
1311 LDM_LOOP(LOAD_BIOS);
1312 break;
1313 case REGION_WORKING_RAM:
1314 LDM_LOOP(LOAD_WORKING_RAM);
1315 break;
1316 case REGION_WORKING_IRAM:
1317 LDM_LOOP(LOAD_WORKING_IRAM);
1318 break;
1319 case REGION_IO:
1320 LDM_LOOP(LOAD_IO);
1321 break;
1322 case REGION_PALETTE_RAM:
1323 LDM_LOOP(LOAD_PALETTE_RAM);
1324 break;
1325 case REGION_VRAM:
1326 LDM_LOOP(LOAD_VRAM);
1327 break;
1328 case REGION_OAM:
1329 LDM_LOOP(LOAD_OAM);
1330 break;
1331 case REGION_CART0:
1332 case REGION_CART0_EX:
1333 case REGION_CART1:
1334 case REGION_CART1_EX:
1335 case REGION_CART2:
1336 case REGION_CART2_EX:
1337 LDM_LOOP(LOAD_CART);
1338 break;
1339 case REGION_CART_SRAM:
1340 case REGION_CART_SRAM_MIRROR:
1341 LDM_LOOP(LOAD_SRAM);
1342 break;
1343 default:
1344 LDM_LOOP(LOAD_BAD);
1345 break;
1346 }
1347
1348 if (cycleCounter) {
1349 ++wait;
1350 if (address >> BASE_OFFSET < REGION_CART0) {
1351 wait = GBAMemoryStall(cpu, wait);
1352 }
1353 *cycleCounter += wait;
1354 }
1355
1356 if (direction & LSM_B) {
1357 address -= offset;
1358 }
1359
1360 if (direction & LSM_D) {
1361 address -= (popcount << 2) + 4;
1362 }
1363
1364 return address | addressMisalign;
1365}
1366
1367#define STM_LOOP(STM) \
1368 for (i = 0; i < 16; i += 4) { \
1369 if (UNLIKELY(mask & (1 << i))) { \
1370 value = cpu->gprs[i]; \
1371 STM; \
1372 ++wait; \
1373 address += 4; \
1374 } \
1375 if (UNLIKELY(mask & (2 << i))) { \
1376 value = cpu->gprs[i + 1]; \
1377 STM; \
1378 ++wait; \
1379 address += 4; \
1380 } \
1381 if (UNLIKELY(mask & (4 << i))) { \
1382 value = cpu->gprs[i + 2]; \
1383 STM; \
1384 ++wait; \
1385 address += 4; \
1386 } \
1387 if (UNLIKELY(mask & (8 << i))) { \
1388 value = cpu->gprs[i + 3]; \
1389 if (i + 3 == ARM_PC) { \
1390 value += WORD_SIZE_ARM; \
1391 } \
1392 STM; \
1393 ++wait; \
1394 address += 4; \
1395 } \
1396 }
1397
1398uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1399 struct GBA* gba = (struct GBA*) cpu->master;
1400 struct GBAMemory* memory = &gba->memory;
1401 uint32_t value;
1402 uint32_t oldValue;
1403 char* waitstatesRegion = memory->waitstatesSeq32;
1404
1405 int i;
1406 int offset = 4;
1407 int popcount = 0;
1408 if (direction & LSM_D) {
1409 offset = -4;
1410 popcount = popcount32(mask);
1411 address -= (popcount << 2) - 4;
1412 }
1413
1414 if (direction & LSM_B) {
1415 address += offset;
1416 }
1417
1418 uint32_t addressMisalign = address & 0x3;
1419 int region = address >> BASE_OFFSET;
1420 if (region < REGION_CART_SRAM) {
1421 address &= 0xFFFFFFFC;
1422 }
1423 int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1424
1425 switch (region) {
1426 case REGION_WORKING_RAM:
1427 STM_LOOP(STORE_WORKING_RAM);
1428 break;
1429 case REGION_WORKING_IRAM:
1430 STM_LOOP(STORE_WORKING_IRAM);
1431 break;
1432 case REGION_IO:
1433 STM_LOOP(STORE_IO);
1434 break;
1435 case REGION_PALETTE_RAM:
1436 STM_LOOP(STORE_PALETTE_RAM);
1437 break;
1438 case REGION_VRAM:
1439 STM_LOOP(STORE_VRAM);
1440 break;
1441 case REGION_OAM:
1442 STM_LOOP(STORE_OAM);
1443 break;
1444 case REGION_CART0:
1445 case REGION_CART0_EX:
1446 case REGION_CART1:
1447 case REGION_CART1_EX:
1448 case REGION_CART2:
1449 case REGION_CART2_EX:
1450 STM_LOOP(STORE_CART);
1451 break;
1452 case REGION_CART_SRAM:
1453 case REGION_CART_SRAM_MIRROR:
1454 STM_LOOP(STORE_SRAM);
1455 break;
1456 default:
1457 STM_LOOP(STORE_BAD);
1458 break;
1459 }
1460
1461 if (cycleCounter) {
1462 if (address >> BASE_OFFSET < REGION_CART0) {
1463 wait = GBAMemoryStall(cpu, wait);
1464 }
1465 *cycleCounter += wait;
1466 }
1467
1468 if (direction & LSM_B) {
1469 address -= offset;
1470 }
1471
1472 if (direction & LSM_D) {
1473 address -= (popcount << 2) + 4;
1474 }
1475
1476 return address | addressMisalign;
1477}
1478
1479void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
1480 struct GBAMemory* memory = &gba->memory;
1481 struct ARMCore* cpu = gba->cpu;
1482 int sram = parameters & 0x0003;
1483 int ws0 = (parameters & 0x000C) >> 2;
1484 int ws0seq = (parameters & 0x0010) >> 4;
1485 int ws1 = (parameters & 0x0060) >> 5;
1486 int ws1seq = (parameters & 0x0080) >> 7;
1487 int ws2 = (parameters & 0x0300) >> 8;
1488 int ws2seq = (parameters & 0x0400) >> 10;
1489 int prefetch = parameters & 0x4000;
1490
1491 memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1492 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1493 memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1494 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1495
1496 memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
1497 memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
1498 memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
1499
1500 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
1501 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
1502 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
1503
1504 memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
1505 memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
1506 memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
1507
1508 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
1509 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
1510 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
1511
1512 memory->prefetch = prefetch;
1513
1514 cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion];
1515 cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
1516
1517 cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
1518 cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
1519}
1520
1521int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) {
1522 struct GBA* gba = (struct GBA*) cpu->master;
1523 struct GBAMemory* memory = &gba->memory;
1524
1525 if (memory->activeRegion < REGION_CART0 || !memory->prefetch) {
1526 // The wait is the stall
1527 return wait;
1528 }
1529
1530 int32_t previousLoads = 0;
1531
1532 // Don't prefetch too much if we're overlapping with a previous prefetch
1533 uint32_t dist = (memory->lastPrefetchedPc - cpu->gprs[ARM_PC]) >> 1;
1534 if (dist < 8) {
1535 previousLoads = dist;
1536 }
1537
1538 int32_t s = cpu->memory.activeSeqCycles16;
1539 int32_t n2s = cpu->memory.activeNonseqCycles16 - cpu->memory.activeSeqCycles16;
1540
1541 // Figure out how many sequential loads we can jam in
1542 int32_t stall = s;
1543 int32_t loads = 1;
1544
1545 if (stall < wait) {
1546 int32_t maxLoads = 8 - previousLoads;
1547 while (stall < wait && loads < maxLoads) {
1548 stall += s;
1549 ++loads;
1550 }
1551 }
1552 if (stall > wait) {
1553 // The wait cannot take less time than the prefetch stalls
1554 wait = stall;
1555 }
1556
1557 // This instruction used to have an N, convert it to an S.
1558 wait -= n2s;
1559
1560 memory->lastPrefetchedPc = cpu->gprs[ARM_PC] + WORD_SIZE_THUMB * (loads + previousLoads - 1);
1561
1562 // The next |loads|S waitstates disappear entirely, so long as they're all in a row
1563 cpu->cycles -= stall;
1564 return wait;
1565}
1566
1567void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state) {
1568 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1569 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1570}
1571
1572void GBAMemoryDeserialize(struct GBAMemory* memory, const struct GBASerializedState* state) {
1573 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1574 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1575}
1576
1577void _pristineCow(struct GBA* gba) {
1578 if (!gba->isPristine) {
1579 return;
1580 }
1581 void* newRom = anonymousMemoryMap(SIZE_CART0);
1582 memcpy(newRom, gba->memory.rom, gba->memory.romSize);
1583 memset(((uint8_t*) newRom) + gba->memory.romSize, 0xFF, SIZE_CART0 - gba->memory.romSize);
1584 if (gba->cpu->memory.activeRegion == gba->memory.rom) {
1585 gba->cpu->memory.activeRegion = newRom;
1586 }
1587 if (gba->romVf) {
1588#ifndef FIXED_ROM_BUFFER
1589 gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->memory.romSize);
1590#endif
1591 gba->romVf->close(gba->romVf);
1592 gba->romVf = NULL;
1593 }
1594 gba->memory.rom = newRom;
1595 gba->memory.hw.gpioBase = &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1];
1596}