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