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