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