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.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
91 gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
92
93 GBADMAInit(gba);
94 GBAVFameInit(&gba->memory.vfame);
95}
96
97void GBAMemoryDeinit(struct GBA* gba) {
98 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
99 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
100 if (gba->memory.rom) {
101 mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
102 }
103 gba->memory.savedata.maskWriteback = false;
104 GBASavedataUnmask(&gba->memory.savedata);
105 GBASavedataDeinit(&gba->memory.savedata);
106 if (gba->memory.savedata.realVf) {
107 gba->memory.savedata.realVf->close(gba->memory.savedata.realVf);
108 }
109
110 if (gba->memory.agbPrintBuffer) {
111 mappedMemoryFree(gba->memory.agbPrintBuffer, SIZE_AGB_PRINT);
112 }
113}
114
115void GBAMemoryReset(struct GBA* gba) {
116 if (gba->memory.wram && gba->memory.rom) {
117 memset(gba->memory.wram, 0, SIZE_WORKING_RAM);
118 }
119
120 if (gba->memory.iwram) {
121 memset(gba->memory.iwram, 0, SIZE_WORKING_IRAM);
122 }
123
124 memset(gba->memory.io, 0, sizeof(gba->memory.io));
125
126 gba->memory.agbPrint = 0;
127 memset(&gba->memory.agbPrintCtx, 0, sizeof(gba->memory.agbPrintCtx));
128 if (gba->memory.agbPrintBuffer) {
129 gba->memory.agbPrintBuffer = NULL;
130 }
131
132 gba->memory.prefetch = false;
133 gba->memory.lastPrefetchedPc = 0;
134
135 if (!gba->memory.wram || !gba->memory.iwram) {
136 GBAMemoryDeinit(gba);
137 mLOG(GBA_MEM, FATAL, "Could not map memory");
138 }
139
140 GBADMAReset(gba);
141}
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
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 mLOG(GBA_MEM, STUB, "Unimplemented memory Store32: 0x%08X", address);
753
754#define STORE_SRAM \
755 if (address & 0x3) { \
756 mLOG(GBA_MEM, GAME_ERROR, "Unaligned SRAM Store32: 0x%08X", address); \
757 value = 0; \
758 } \
759 GBAStore8(cpu, address & ~0x3, value, cycleCounter); \
760 GBAStore8(cpu, (address & ~0x3) | 1, value, cycleCounter); \
761 GBAStore8(cpu, (address & ~0x3) | 2, value, cycleCounter); \
762 GBAStore8(cpu, (address & ~0x3) | 3, value, cycleCounter);
763
764#define STORE_BAD \
765 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store32: 0x%08X", address);
766
767void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
768 struct GBA* gba = (struct GBA*) cpu->master;
769 struct GBAMemory* memory = &gba->memory;
770 int wait = 0;
771 int32_t oldValue;
772 char* waitstatesRegion = memory->waitstatesNonseq32;
773
774 switch (address >> BASE_OFFSET) {
775 case REGION_WORKING_RAM:
776 STORE_WORKING_RAM;
777 break;
778 case REGION_WORKING_IRAM:
779 STORE_WORKING_IRAM
780 break;
781 case REGION_IO:
782 STORE_IO;
783 break;
784 case REGION_PALETTE_RAM:
785 STORE_PALETTE_RAM;
786 break;
787 case REGION_VRAM:
788 STORE_VRAM;
789 break;
790 case REGION_OAM:
791 STORE_OAM;
792 break;
793 case REGION_CART0:
794 case REGION_CART0_EX:
795 case REGION_CART1:
796 case REGION_CART1_EX:
797 case REGION_CART2:
798 case REGION_CART2_EX:
799 STORE_CART;
800 break;
801 case REGION_CART_SRAM:
802 case REGION_CART_SRAM_MIRROR:
803 STORE_SRAM;
804 break;
805 default:
806 STORE_BAD;
807 break;
808 }
809
810 if (cycleCounter) {
811 ++wait;
812 if (address >> BASE_OFFSET < REGION_CART0) {
813 wait = GBAMemoryStall(cpu, wait);
814 }
815 *cycleCounter += wait;
816 }
817}
818
819void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
820 struct GBA* gba = (struct GBA*) cpu->master;
821 struct GBAMemory* memory = &gba->memory;
822 int wait = 0;
823 int16_t oldValue;
824
825 switch (address >> BASE_OFFSET) {
826 case REGION_WORKING_RAM:
827 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
828 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
829 break;
830 case REGION_WORKING_IRAM:
831 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
832 break;
833 case REGION_IO:
834 GBAIOWrite(gba, address & (OFFSET_MASK - 1), value);
835 break;
836 case REGION_PALETTE_RAM:
837 LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
838 if (oldValue != value) {
839 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
840 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
841 }
842 break;
843 case REGION_VRAM:
844 if ((address & 0x0001FFFF) < SIZE_VRAM) {
845 LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram);
846 if (value != oldValue) {
847 STORE_16(value, address & 0x0001FFFE, gba->video.vram);
848 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
849 }
850 } else {
851 LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram);
852 if (value != oldValue) {
853 STORE_16(value, address & 0x00017FFE, gba->video.vram);
854 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE);
855 }
856 }
857 break;
858 case REGION_OAM:
859 LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
860 if (value != oldValue) {
861 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
862 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
863 }
864 break;
865 case REGION_CART0:
866 if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFE)) {
867 uint32_t reg = address & 0xFFFFFE;
868 GBAHardwareGPIOWrite(&memory->hw, reg, value);
869 break;
870 }
871 // Fall through
872 case REGION_CART0_EX:
873 if ((address & 0x00FFFFFF) >= AGB_PRINT_BASE) {
874 uint32_t agbPrintAddr = address & 0x00FFFFFF;
875 if (agbPrintAddr == AGB_PRINT_PROTECT) {
876 memory->agbPrint = value;
877 _agbPrintStore(gba, address, value);
878 break;
879 }
880 if (memory->agbPrint == 0x20 && (agbPrintAddr < AGB_PRINT_TOP || (agbPrintAddr & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8))) {
881 _agbPrintStore(gba, address, value);
882 break;
883 }
884 }
885 mLOG(GBA_MEM, GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
886 break;
887 case REGION_CART2_EX:
888 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
889 mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
890 GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming);
891 }
892 GBASavedataWriteEEPROM(&memory->savedata, value, 1);
893 break;
894 case REGION_CART_SRAM:
895 case REGION_CART_SRAM_MIRROR:
896 GBAStore8(cpu, (address & ~0x1), value, cycleCounter);
897 GBAStore8(cpu, (address & ~0x1) | 1, value, cycleCounter);
898 break;
899 default:
900 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store16: 0x%08X", address);
901 break;
902 }
903
904 if (cycleCounter) {
905 ++wait;
906 if (address >> BASE_OFFSET < REGION_CART0) {
907 wait = GBAMemoryStall(cpu, wait);
908 }
909 *cycleCounter += wait;
910 }
911}
912
913void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
914 struct GBA* gba = (struct GBA*) cpu->master;
915 struct GBAMemory* memory = &gba->memory;
916 int wait = 0;
917 uint16_t oldValue;
918
919 switch (address >> BASE_OFFSET) {
920 case REGION_WORKING_RAM:
921 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
922 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
923 break;
924 case REGION_WORKING_IRAM:
925 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
926 break;
927 case REGION_IO:
928 GBAIOWrite8(gba, address & OFFSET_MASK, value);
929 break;
930 case REGION_PALETTE_RAM:
931 GBAStore16(cpu, address & ~1, ((uint8_t) value) | ((uint8_t) value << 8), cycleCounter);
932 break;
933 case REGION_VRAM:
934 if ((address & 0x0001FFFF) >= ((GBARegisterDISPCNTGetMode(gba->memory.io[REG_DISPCNT >> 1]) == 4) ? 0x00014000 : 0x00010000)) {
935 // TODO: check BG mode
936 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
937 break;
938 }
939 oldValue = gba->video.renderer->vram[(address & 0x1FFFE) >> 1];
940 if (oldValue != (((uint8_t) value) | (value << 8))) {
941 gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
942 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
943 }
944 break;
945 case REGION_OAM:
946 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
947 break;
948 case REGION_CART0:
949 mLOG(GBA_MEM, STUB, "Unimplemented memory Store8: 0x%08X", address);
950 break;
951 case REGION_CART_SRAM:
952 case REGION_CART_SRAM_MIRROR:
953 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
954 if (address == SAVEDATA_FLASH_BASE) {
955 mLOG(GBA_MEM, INFO, "Detected Flash savegame");
956 GBASavedataInitFlash(&memory->savedata, gba->realisticTiming);
957 } else {
958 mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
959 GBASavedataInitSRAM(&memory->savedata);
960 }
961 }
962 if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
963 GBASavedataWriteFlash(&memory->savedata, address, value);
964 } else if (memory->savedata.type == SAVEDATA_SRAM) {
965 if (memory->vfame.cartType) {
966 GBAVFameSramWrite(&memory->vfame, address, value, memory->savedata.data);
967 } else {
968 memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
969 }
970 memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
971 } else if (memory->hw.devices & HW_TILT) {
972 GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
973 } else {
974 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
975 }
976 wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
977 break;
978 default:
979 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store8: 0x%08X", address);
980 break;
981 }
982
983 if (cycleCounter) {
984 ++wait;
985 if (address >> BASE_OFFSET < REGION_CART0) {
986 wait = GBAMemoryStall(cpu, wait);
987 }
988 *cycleCounter += wait;
989 }
990}
991
992uint32_t GBAView32(struct ARMCore* cpu, uint32_t address) {
993 struct GBA* gba = (struct GBA*) cpu->master;
994 uint32_t value = 0;
995 address &= ~3;
996 switch (address >> BASE_OFFSET) {
997 case REGION_BIOS:
998 if (address < SIZE_BIOS) {
999 LOAD_32(value, address, gba->memory.bios);
1000 }
1001 break;
1002 case REGION_WORKING_RAM:
1003 case REGION_WORKING_IRAM:
1004 case REGION_PALETTE_RAM:
1005 case REGION_VRAM:
1006 case REGION_OAM:
1007 case REGION_CART0:
1008 case REGION_CART0_EX:
1009 case REGION_CART1:
1010 case REGION_CART1_EX:
1011 case REGION_CART2:
1012 case REGION_CART2_EX:
1013 value = GBALoad32(cpu, address, 0);
1014 break;
1015 case REGION_IO:
1016 if ((address & OFFSET_MASK) < REG_MAX) {
1017 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
1018 value |= gba->memory.io[((address & OFFSET_MASK) >> 1) + 1] << 16;
1019 }
1020 break;
1021 case REGION_CART_SRAM:
1022 value = GBALoad8(cpu, address, 0);
1023 value |= GBALoad8(cpu, address + 1, 0) << 8;
1024 value |= GBALoad8(cpu, address + 2, 0) << 16;
1025 value |= GBALoad8(cpu, address + 3, 0) << 24;
1026 break;
1027 default:
1028 break;
1029 }
1030 return value;
1031}
1032
1033uint16_t GBAView16(struct ARMCore* cpu, uint32_t address) {
1034 struct GBA* gba = (struct GBA*) cpu->master;
1035 uint16_t value = 0;
1036 address &= ~1;
1037 switch (address >> BASE_OFFSET) {
1038 case REGION_BIOS:
1039 if (address < SIZE_BIOS) {
1040 LOAD_16(value, address, gba->memory.bios);
1041 }
1042 break;
1043 case REGION_WORKING_RAM:
1044 case REGION_WORKING_IRAM:
1045 case REGION_PALETTE_RAM:
1046 case REGION_VRAM:
1047 case REGION_OAM:
1048 case REGION_CART0:
1049 case REGION_CART0_EX:
1050 case REGION_CART1:
1051 case REGION_CART1_EX:
1052 case REGION_CART2:
1053 case REGION_CART2_EX:
1054 value = GBALoad16(cpu, address, 0);
1055 break;
1056 case REGION_IO:
1057 if ((address & OFFSET_MASK) < REG_MAX) {
1058 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
1059 }
1060 break;
1061 case REGION_CART_SRAM:
1062 value = GBALoad8(cpu, address, 0);
1063 value |= GBALoad8(cpu, address + 1, 0) << 8;
1064 break;
1065 default:
1066 break;
1067 }
1068 return value;
1069}
1070
1071uint8_t GBAView8(struct ARMCore* cpu, uint32_t address) {
1072 struct GBA* gba = (struct GBA*) cpu->master;
1073 uint8_t value = 0;
1074 switch (address >> BASE_OFFSET) {
1075 case REGION_BIOS:
1076 if (address < SIZE_BIOS) {
1077 value = ((uint8_t*) gba->memory.bios)[address];
1078 }
1079 break;
1080 case REGION_WORKING_RAM:
1081 case REGION_WORKING_IRAM:
1082 case REGION_CART0:
1083 case REGION_CART0_EX:
1084 case REGION_CART1:
1085 case REGION_CART1_EX:
1086 case REGION_CART2:
1087 case REGION_CART2_EX:
1088 case REGION_CART_SRAM:
1089 value = GBALoad8(cpu, address, 0);
1090 break;
1091 case REGION_IO:
1092 case REGION_PALETTE_RAM:
1093 case REGION_VRAM:
1094 case REGION_OAM:
1095 value = GBAView16(cpu, address) >> ((address & 1) * 8);
1096 break;
1097 default:
1098 break;
1099 }
1100 return value;
1101}
1102
1103void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old) {
1104 struct GBA* gba = (struct GBA*) cpu->master;
1105 struct GBAMemory* memory = &gba->memory;
1106 int32_t oldValue = -1;
1107
1108 switch (address >> BASE_OFFSET) {
1109 case REGION_WORKING_RAM:
1110 LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 4), memory->wram);
1111 STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram);
1112 break;
1113 case REGION_WORKING_IRAM:
1114 LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1115 STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1116 break;
1117 case REGION_IO:
1118 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch32: 0x%08X", address);
1119 break;
1120 case REGION_PALETTE_RAM:
1121 LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
1122 STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette);
1123 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
1124 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16);
1125 break;
1126 case REGION_VRAM:
1127 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1128 LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram);
1129 STORE_32(value, address & 0x0001FFFC, gba->video.vram);
1130 } else {
1131 LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram);
1132 STORE_32(value, address & 0x00017FFC, gba->video.vram);
1133 }
1134 break;
1135 case REGION_OAM:
1136 LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw);
1137 STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
1138 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
1139 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) + 2) >> 1);
1140 break;
1141 case REGION_CART0:
1142 case REGION_CART0_EX:
1143 case REGION_CART1:
1144 case REGION_CART1_EX:
1145 case REGION_CART2:
1146 case REGION_CART2_EX:
1147 _pristineCow(gba);
1148 if ((address & (SIZE_CART0 - 4)) >= gba->memory.romSize) {
1149 gba->memory.romSize = (address & (SIZE_CART0 - 4)) + 4;
1150 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1151 }
1152 LOAD_32(oldValue, address & (SIZE_CART0 - 4), gba->memory.rom);
1153 STORE_32(value, address & (SIZE_CART0 - 4), gba->memory.rom);
1154 break;
1155 case REGION_CART_SRAM:
1156 case REGION_CART_SRAM_MIRROR:
1157 if (memory->savedata.type == SAVEDATA_SRAM) {
1158 LOAD_32(oldValue, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1159 STORE_32(value, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1160 } else {
1161 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1162 }
1163 break;
1164 default:
1165 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1166 break;
1167 }
1168 if (old) {
1169 *old = oldValue;
1170 }
1171}
1172
1173void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old) {
1174 struct GBA* gba = (struct GBA*) cpu->master;
1175 struct GBAMemory* memory = &gba->memory;
1176 int16_t oldValue = -1;
1177
1178 switch (address >> BASE_OFFSET) {
1179 case REGION_WORKING_RAM:
1180 LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 2), memory->wram);
1181 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
1182 break;
1183 case REGION_WORKING_IRAM:
1184 LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1185 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1186 break;
1187 case REGION_IO:
1188 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch16: 0x%08X", address);
1189 break;
1190 case REGION_PALETTE_RAM:
1191 LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1192 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1193 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
1194 break;
1195 case REGION_VRAM:
1196 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1197 LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram);
1198 STORE_16(value, address & 0x0001FFFE, gba->video.vram);
1199 } else {
1200 LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram);
1201 STORE_16(value, address & 0x00017FFE, gba->video.vram);
1202 }
1203 break;
1204 case REGION_OAM:
1205 LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
1206 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
1207 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
1208 break;
1209 case REGION_CART0:
1210 case REGION_CART0_EX:
1211 case REGION_CART1:
1212 case REGION_CART1_EX:
1213 case REGION_CART2:
1214 case REGION_CART2_EX:
1215 _pristineCow(gba);
1216 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1217 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1218 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1219 }
1220 LOAD_16(oldValue, address & (SIZE_CART0 - 2), gba->memory.rom);
1221 STORE_16(value, address & (SIZE_CART0 - 2), gba->memory.rom);
1222 break;
1223 case REGION_CART_SRAM:
1224 case REGION_CART_SRAM_MIRROR:
1225 if (memory->savedata.type == SAVEDATA_SRAM) {
1226 LOAD_16(oldValue, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1227 STORE_16(value, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1228 } else {
1229 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1230 }
1231 break;
1232 default:
1233 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1234 break;
1235 }
1236 if (old) {
1237 *old = oldValue;
1238 }
1239}
1240
1241void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) {
1242 struct GBA* gba = (struct GBA*) cpu->master;
1243 struct GBAMemory* memory = &gba->memory;
1244 int8_t oldValue = -1;
1245
1246 switch (address >> BASE_OFFSET) {
1247 case REGION_WORKING_RAM:
1248 oldValue = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
1249 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
1250 break;
1251 case REGION_WORKING_IRAM:
1252 oldValue = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
1253 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
1254 break;
1255 case REGION_IO:
1256 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1257 break;
1258 case REGION_PALETTE_RAM:
1259 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1260 break;
1261 case REGION_VRAM:
1262 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1263 break;
1264 case REGION_OAM:
1265 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1266 break;
1267 case REGION_CART0:
1268 case REGION_CART0_EX:
1269 case REGION_CART1:
1270 case REGION_CART1_EX:
1271 case REGION_CART2:
1272 case REGION_CART2_EX:
1273 _pristineCow(gba);
1274 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1275 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1276 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1277 }
1278 oldValue = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
1279 ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)] = value;
1280 break;
1281 case REGION_CART_SRAM:
1282 case REGION_CART_SRAM_MIRROR:
1283 if (memory->savedata.type == SAVEDATA_SRAM) {
1284 oldValue = ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)];
1285 ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)] = value;
1286 } else {
1287 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1288 }
1289 break;
1290 default:
1291 mLOG(GBA_MEM, WARN, "Bad memory Patch8: 0x%08X", address);
1292 break;
1293 }
1294 if (old) {
1295 *old = oldValue;
1296 }
1297}
1298
1299#define LDM_LOOP(LDM) \
1300 for (i = 0; i < 16; i += 4) { \
1301 if (UNLIKELY(mask & (1 << i))) { \
1302 LDM; \
1303 cpu->gprs[i] = value; \
1304 ++wait; \
1305 address += 4; \
1306 } \
1307 if (UNLIKELY(mask & (2 << i))) { \
1308 LDM; \
1309 cpu->gprs[i + 1] = value; \
1310 ++wait; \
1311 address += 4; \
1312 } \
1313 if (UNLIKELY(mask & (4 << i))) { \
1314 LDM; \
1315 cpu->gprs[i + 2] = value; \
1316 ++wait; \
1317 address += 4; \
1318 } \
1319 if (UNLIKELY(mask & (8 << i))) { \
1320 LDM; \
1321 cpu->gprs[i + 3] = value; \
1322 ++wait; \
1323 address += 4; \
1324 } \
1325 }
1326
1327uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1328 struct GBA* gba = (struct GBA*) cpu->master;
1329 struct GBAMemory* memory = &gba->memory;
1330 uint32_t value;
1331 char* waitstatesRegion = memory->waitstatesSeq32;
1332
1333 int i;
1334 int offset = 4;
1335 int popcount = 0;
1336 if (direction & LSM_D) {
1337 offset = -4;
1338 popcount = popcount32(mask);
1339 address -= (popcount << 2) - 4;
1340 }
1341
1342 if (direction & LSM_B) {
1343 address += offset;
1344 }
1345
1346 uint32_t addressMisalign = address & 0x3;
1347 int region = address >> BASE_OFFSET;
1348 if (region < REGION_CART_SRAM) {
1349 address &= 0xFFFFFFFC;
1350 }
1351 int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1352
1353 switch (region) {
1354 case REGION_BIOS:
1355 LDM_LOOP(LOAD_BIOS);
1356 break;
1357 case REGION_WORKING_RAM:
1358 LDM_LOOP(LOAD_WORKING_RAM);
1359 break;
1360 case REGION_WORKING_IRAM:
1361 LDM_LOOP(LOAD_WORKING_IRAM);
1362 break;
1363 case REGION_IO:
1364 LDM_LOOP(LOAD_IO);
1365 break;
1366 case REGION_PALETTE_RAM:
1367 LDM_LOOP(LOAD_PALETTE_RAM);
1368 break;
1369 case REGION_VRAM:
1370 LDM_LOOP(LOAD_VRAM);
1371 break;
1372 case REGION_OAM:
1373 LDM_LOOP(LOAD_OAM);
1374 break;
1375 case REGION_CART0:
1376 case REGION_CART0_EX:
1377 case REGION_CART1:
1378 case REGION_CART1_EX:
1379 case REGION_CART2:
1380 case REGION_CART2_EX:
1381 LDM_LOOP(LOAD_CART);
1382 break;
1383 case REGION_CART_SRAM:
1384 case REGION_CART_SRAM_MIRROR:
1385 LDM_LOOP(LOAD_SRAM);
1386 break;
1387 default:
1388 LDM_LOOP(LOAD_BAD);
1389 break;
1390 }
1391
1392 if (cycleCounter) {
1393 ++wait;
1394 if (address >> BASE_OFFSET < REGION_CART0) {
1395 wait = GBAMemoryStall(cpu, wait);
1396 }
1397 *cycleCounter += wait;
1398 }
1399
1400 if (direction & LSM_B) {
1401 address -= offset;
1402 }
1403
1404 if (direction & LSM_D) {
1405 address -= (popcount << 2) + 4;
1406 }
1407
1408 return address | addressMisalign;
1409}
1410
1411#define STM_LOOP(STM) \
1412 for (i = 0; i < 16; i += 4) { \
1413 if (UNLIKELY(mask & (1 << i))) { \
1414 value = cpu->gprs[i]; \
1415 STM; \
1416 ++wait; \
1417 address += 4; \
1418 } \
1419 if (UNLIKELY(mask & (2 << i))) { \
1420 value = cpu->gprs[i + 1]; \
1421 STM; \
1422 ++wait; \
1423 address += 4; \
1424 } \
1425 if (UNLIKELY(mask & (4 << i))) { \
1426 value = cpu->gprs[i + 2]; \
1427 STM; \
1428 ++wait; \
1429 address += 4; \
1430 } \
1431 if (UNLIKELY(mask & (8 << i))) { \
1432 value = cpu->gprs[i + 3]; \
1433 if (i + 3 == ARM_PC) { \
1434 value += WORD_SIZE_ARM; \
1435 } \
1436 STM; \
1437 ++wait; \
1438 address += 4; \
1439 } \
1440 }
1441
1442uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1443 struct GBA* gba = (struct GBA*) cpu->master;
1444 struct GBAMemory* memory = &gba->memory;
1445 uint32_t value;
1446 uint32_t oldValue;
1447 char* waitstatesRegion = memory->waitstatesSeq32;
1448
1449 int i;
1450 int offset = 4;
1451 int popcount = 0;
1452 if (direction & LSM_D) {
1453 offset = -4;
1454 popcount = popcount32(mask);
1455 address -= (popcount << 2) - 4;
1456 }
1457
1458 if (direction & LSM_B) {
1459 address += offset;
1460 }
1461
1462 uint32_t addressMisalign = address & 0x3;
1463 int region = address >> BASE_OFFSET;
1464 if (region < REGION_CART_SRAM) {
1465 address &= 0xFFFFFFFC;
1466 }
1467 int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1468
1469 switch (region) {
1470 case REGION_WORKING_RAM:
1471 STM_LOOP(STORE_WORKING_RAM);
1472 break;
1473 case REGION_WORKING_IRAM:
1474 STM_LOOP(STORE_WORKING_IRAM);
1475 break;
1476 case REGION_IO:
1477 STM_LOOP(STORE_IO);
1478 break;
1479 case REGION_PALETTE_RAM:
1480 STM_LOOP(STORE_PALETTE_RAM);
1481 break;
1482 case REGION_VRAM:
1483 STM_LOOP(STORE_VRAM);
1484 break;
1485 case REGION_OAM:
1486 STM_LOOP(STORE_OAM);
1487 break;
1488 case REGION_CART0:
1489 case REGION_CART0_EX:
1490 case REGION_CART1:
1491 case REGION_CART1_EX:
1492 case REGION_CART2:
1493 case REGION_CART2_EX:
1494 STM_LOOP(STORE_CART);
1495 break;
1496 case REGION_CART_SRAM:
1497 case REGION_CART_SRAM_MIRROR:
1498 STM_LOOP(STORE_SRAM);
1499 break;
1500 default:
1501 STM_LOOP(STORE_BAD);
1502 break;
1503 }
1504
1505 if (cycleCounter) {
1506 if (address >> BASE_OFFSET < REGION_CART0) {
1507 wait = GBAMemoryStall(cpu, wait);
1508 }
1509 *cycleCounter += wait;
1510 }
1511
1512 if (direction & LSM_B) {
1513 address -= offset;
1514 }
1515
1516 if (direction & LSM_D) {
1517 address -= (popcount << 2) + 4;
1518 }
1519
1520 return address | addressMisalign;
1521}
1522
1523void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
1524 struct GBAMemory* memory = &gba->memory;
1525 struct ARMCore* cpu = gba->cpu;
1526 int sram = parameters & 0x0003;
1527 int ws0 = (parameters & 0x000C) >> 2;
1528 int ws0seq = (parameters & 0x0010) >> 4;
1529 int ws1 = (parameters & 0x0060) >> 5;
1530 int ws1seq = (parameters & 0x0080) >> 7;
1531 int ws2 = (parameters & 0x0300) >> 8;
1532 int ws2seq = (parameters & 0x0400) >> 10;
1533 int prefetch = parameters & 0x4000;
1534
1535 memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1536 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1537 memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1538 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1539
1540 memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
1541 memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
1542 memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
1543
1544 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
1545 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
1546 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
1547
1548 memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
1549 memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
1550 memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
1551
1552 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
1553 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
1554 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
1555
1556 memory->prefetch = prefetch;
1557
1558 cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion];
1559 cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
1560
1561 cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
1562 cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
1563}
1564
1565int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) {
1566 struct GBA* gba = (struct GBA*) cpu->master;
1567 struct GBAMemory* memory = &gba->memory;
1568
1569 if (memory->activeRegion < REGION_CART0 || !memory->prefetch) {
1570 // The wait is the stall
1571 return wait;
1572 }
1573
1574 int32_t previousLoads = 0;
1575
1576 // Don't prefetch too much if we're overlapping with a previous prefetch
1577 uint32_t dist = (memory->lastPrefetchedPc - cpu->gprs[ARM_PC]);
1578 int32_t maxLoads = 8;
1579 if (dist < 16) {
1580 previousLoads = dist >> 1;
1581 maxLoads -= previousLoads;
1582 }
1583
1584 int32_t s = cpu->memory.activeSeqCycles16;
1585 int32_t n2s = cpu->memory.activeNonseqCycles16 - cpu->memory.activeSeqCycles16;
1586
1587 // Figure out how many sequential loads we can jam in
1588 int32_t stall = s;
1589 int32_t loads = 1;
1590
1591 while (stall < wait && loads < maxLoads) {
1592 stall += s;
1593 ++loads;
1594 }
1595 if (stall > wait) {
1596 // The wait cannot take less time than the prefetch stalls
1597 wait = stall;
1598 }
1599
1600 // This instruction used to have an N, convert it to an S.
1601 wait -= n2s;
1602
1603 memory->lastPrefetchedPc = cpu->gprs[ARM_PC] + WORD_SIZE_THUMB * (loads + previousLoads - 1);
1604
1605 // The next |loads|S waitstates disappear entirely, so long as they're all in a row
1606 cpu->cycles -= stall;
1607 return wait;
1608}
1609
1610void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state) {
1611 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1612 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1613}
1614
1615void GBAMemoryDeserialize(struct GBAMemory* memory, const struct GBASerializedState* state) {
1616 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1617 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1618}
1619
1620void _pristineCow(struct GBA* gba) {
1621 if (!gba->isPristine) {
1622 return;
1623 }
1624 void* newRom = anonymousMemoryMap(SIZE_CART0);
1625 memcpy(newRom, gba->memory.rom, gba->memory.romSize);
1626 memset(((uint8_t*) newRom) + gba->memory.romSize, 0xFF, SIZE_CART0 - gba->memory.romSize);
1627 if (gba->cpu->memory.activeRegion == gba->memory.rom) {
1628 gba->cpu->memory.activeRegion = newRom;
1629 }
1630 if (gba->romVf) {
1631#ifndef FIXED_ROM_BUFFER
1632 gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->memory.romSize);
1633#endif
1634 gba->romVf->close(gba->romVf);
1635 gba->romVf = NULL;
1636 }
1637 gba->memory.rom = newRom;
1638 gba->memory.hw.gpioBase = &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1];
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 ++gba->memory.agbPrintCtx.get;
1654 }
1655 _agbPrintStore(gba, AGB_PRINT_STRUCT + 4, gba->memory.agbPrintCtx.get);
1656
1657 mLOG(GBA_DEBUG, INFO, "%s", oolBuf);
1658}
1659
1660static void _agbPrintStore(struct GBA* gba, uint32_t address, int16_t value) {
1661 struct GBAMemory* memory = &gba->memory;
1662 if ((address & 0x00FFFFFF) < AGB_PRINT_TOP) {
1663 if (!memory->agbPrintBuffer) {
1664 memory->agbPrintBuffer = anonymousMemoryMap(SIZE_AGB_PRINT);
1665 }
1666 STORE_16(value, address & (SIZE_AGB_PRINT - 2), memory->agbPrintBuffer);
1667 } else if ((address & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8)) {
1668 (&memory->agbPrintCtx.request)[(address & 7) >> 1] = value;
1669 }
1670 if (memory->romSize == SIZE_CART0) {
1671 _pristineCow(gba);
1672 memcpy(&memory->rom[AGB_PRINT_FLUSH_ADDR >> 2], _agbPrintFunc, sizeof(_agbPrintFunc));
1673 STORE_16(value, address & (SIZE_CART0 - 2), memory->rom);
1674 }
1675}
1676
1677static int16_t _agbPrintLoad(struct GBA* gba, uint32_t address) {
1678 struct GBAMemory* memory = &gba->memory;
1679 int16_t value = 0xFFFF;
1680 if (address < AGB_PRINT_TOP) {
1681 LOAD_16(value, address & (SIZE_AGB_PRINT - 1), memory->agbPrintBuffer);
1682 } else if ((address & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8)) {
1683 value = (&memory->agbPrintCtx.request)[(address & 7) >> 1];
1684 }
1685 return value;
1686}