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