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