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