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