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