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