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