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