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