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 } else if (memory->savedata.type == SAVEDATA_AUTODETECT) {
921 mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
922 GBASavedataInitEEPROM(&memory->savedata);
923 }
924 if (memory->savedata.type == SAVEDATA_EEPROM512 || memory->savedata.type == SAVEDATA_EEPROM) {
925 GBASavedataWriteEEPROM(&memory->savedata, value, 1);
926 break;
927 }
928 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store16: 0x%08X", address);
929 break;
930 case REGION_CART_SRAM:
931 case REGION_CART_SRAM_MIRROR:
932 if (address & 1) {
933 mLOG(GBA_MEM, GAME_ERROR, "Unaligned SRAM Store16: 0x%08X", address);
934 break;
935 }
936 GBAStore8(cpu, address, value, cycleCounter);
937 GBAStore8(cpu, address | 1, value, cycleCounter);
938 break;
939 default:
940 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store16: 0x%08X", address);
941 break;
942 }
943
944 if (cycleCounter) {
945 ++wait;
946 if (address >> BASE_OFFSET < REGION_CART0) {
947 wait = GBAMemoryStall(cpu, wait);
948 }
949 *cycleCounter += wait;
950 }
951}
952
953void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
954 struct GBA* gba = (struct GBA*) cpu->master;
955 struct GBAMemory* memory = &gba->memory;
956 int wait = 0;
957 uint16_t oldValue;
958
959 switch (address >> BASE_OFFSET) {
960 case REGION_WORKING_RAM:
961 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
962 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
963 break;
964 case REGION_WORKING_IRAM:
965 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
966 break;
967 case REGION_IO:
968 GBAIOWrite8(gba, address & OFFSET_MASK, value);
969 break;
970 case REGION_PALETTE_RAM:
971 GBAStore16(cpu, address & ~1, ((uint8_t) value) | ((uint8_t) value << 8), cycleCounter);
972 break;
973 case REGION_VRAM:
974 if ((address & 0x0001FFFF) >= ((GBARegisterDISPCNTGetMode(gba->memory.io[REG_DISPCNT >> 1]) >= 3) ? 0x00014000 : 0x00010000)) {
975 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
976 break;
977 }
978 oldValue = gba->video.renderer->vram[(address & 0x1FFFE) >> 1];
979 if (oldValue != (((uint8_t) value) | (value << 8))) {
980 gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
981 gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
982 }
983 break;
984 case REGION_OAM:
985 mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
986 break;
987 case REGION_CART0:
988 mLOG(GBA_MEM, STUB, "Unimplemented memory Store8: 0x%08X", address);
989 break;
990 case REGION_CART_SRAM:
991 case REGION_CART_SRAM_MIRROR:
992 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
993 if (address == SAVEDATA_FLASH_BASE) {
994 mLOG(GBA_MEM, INFO, "Detected Flash savegame");
995 GBASavedataInitFlash(&memory->savedata);
996 } else {
997 mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
998 GBASavedataInitSRAM(&memory->savedata);
999 }
1000 }
1001 if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) {
1002 GBAHardwareEReaderWriteFlash(&memory->hw, address, value);
1003 } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
1004 GBASavedataWriteFlash(&memory->savedata, address, value);
1005 } else if (memory->savedata.type == SAVEDATA_SRAM) {
1006 if (memory->vfame.cartType) {
1007 GBAVFameSramWrite(&memory->vfame, address, value, memory->savedata.data);
1008 } else {
1009 memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
1010 }
1011 memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
1012 } else if (memory->hw.devices & HW_TILT) {
1013 GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
1014 } else {
1015 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1016 }
1017 wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
1018 break;
1019 default:
1020 mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store8: 0x%08X", address);
1021 break;
1022 }
1023
1024 if (cycleCounter) {
1025 ++wait;
1026 if (address >> BASE_OFFSET < REGION_CART0) {
1027 wait = GBAMemoryStall(cpu, wait);
1028 }
1029 *cycleCounter += wait;
1030 }
1031}
1032
1033uint32_t GBAView32(struct ARMCore* cpu, uint32_t address) {
1034 struct GBA* gba = (struct GBA*) cpu->master;
1035 uint32_t value = 0;
1036 address &= ~3;
1037 switch (address >> BASE_OFFSET) {
1038 case REGION_BIOS:
1039 if (address < SIZE_BIOS) {
1040 LOAD_32(value, address, gba->memory.bios);
1041 }
1042 break;
1043 case REGION_WORKING_RAM:
1044 case REGION_WORKING_IRAM:
1045 case REGION_PALETTE_RAM:
1046 case REGION_VRAM:
1047 case REGION_OAM:
1048 case REGION_CART0:
1049 case REGION_CART0_EX:
1050 case REGION_CART1:
1051 case REGION_CART1_EX:
1052 case REGION_CART2:
1053 case REGION_CART2_EX:
1054 value = GBALoad32(cpu, address, 0);
1055 break;
1056 case REGION_IO:
1057 if ((address & OFFSET_MASK) < REG_MAX) {
1058 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
1059 value |= gba->memory.io[((address & OFFSET_MASK) >> 1) + 1] << 16;
1060 }
1061 break;
1062 case REGION_CART_SRAM:
1063 value = GBALoad8(cpu, address, 0);
1064 value |= GBALoad8(cpu, address + 1, 0) << 8;
1065 value |= GBALoad8(cpu, address + 2, 0) << 16;
1066 value |= GBALoad8(cpu, address + 3, 0) << 24;
1067 break;
1068 default:
1069 break;
1070 }
1071 return value;
1072}
1073
1074uint16_t GBAView16(struct ARMCore* cpu, uint32_t address) {
1075 struct GBA* gba = (struct GBA*) cpu->master;
1076 uint16_t value = 0;
1077 address &= ~1;
1078 switch (address >> BASE_OFFSET) {
1079 case REGION_BIOS:
1080 if (address < SIZE_BIOS) {
1081 LOAD_16(value, address, gba->memory.bios);
1082 }
1083 break;
1084 case REGION_WORKING_RAM:
1085 case REGION_WORKING_IRAM:
1086 case REGION_PALETTE_RAM:
1087 case REGION_VRAM:
1088 case REGION_OAM:
1089 case REGION_CART0:
1090 case REGION_CART0_EX:
1091 case REGION_CART1:
1092 case REGION_CART1_EX:
1093 case REGION_CART2:
1094 case REGION_CART2_EX:
1095 value = GBALoad16(cpu, address, 0);
1096 break;
1097 case REGION_IO:
1098 if ((address & OFFSET_MASK) < REG_MAX) {
1099 value = gba->memory.io[(address & OFFSET_MASK) >> 1];
1100 }
1101 break;
1102 case REGION_CART_SRAM:
1103 value = GBALoad8(cpu, address, 0);
1104 value |= GBALoad8(cpu, address + 1, 0) << 8;
1105 break;
1106 default:
1107 break;
1108 }
1109 return value;
1110}
1111
1112uint8_t GBAView8(struct ARMCore* cpu, uint32_t address) {
1113 struct GBA* gba = (struct GBA*) cpu->master;
1114 uint8_t value = 0;
1115 switch (address >> BASE_OFFSET) {
1116 case REGION_BIOS:
1117 if (address < SIZE_BIOS) {
1118 value = ((uint8_t*) gba->memory.bios)[address];
1119 }
1120 break;
1121 case REGION_WORKING_RAM:
1122 case REGION_WORKING_IRAM:
1123 case REGION_CART0:
1124 case REGION_CART0_EX:
1125 case REGION_CART1:
1126 case REGION_CART1_EX:
1127 case REGION_CART2:
1128 case REGION_CART2_EX:
1129 case REGION_CART_SRAM:
1130 value = GBALoad8(cpu, address, 0);
1131 break;
1132 case REGION_IO:
1133 case REGION_PALETTE_RAM:
1134 case REGION_VRAM:
1135 case REGION_OAM:
1136 value = GBAView16(cpu, address) >> ((address & 1) * 8);
1137 break;
1138 default:
1139 break;
1140 }
1141 return value;
1142}
1143
1144void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old) {
1145 struct GBA* gba = (struct GBA*) cpu->master;
1146 struct GBAMemory* memory = &gba->memory;
1147 int32_t oldValue = -1;
1148
1149 switch (address >> BASE_OFFSET) {
1150 case REGION_WORKING_RAM:
1151 LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 4), memory->wram);
1152 STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram);
1153 break;
1154 case REGION_WORKING_IRAM:
1155 LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1156 STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1157 break;
1158 case REGION_IO:
1159 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch32: 0x%08X", address);
1160 break;
1161 case REGION_PALETTE_RAM:
1162 LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
1163 STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette);
1164 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
1165 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16);
1166 break;
1167 case REGION_VRAM:
1168 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1169 LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram);
1170 STORE_32(value, address & 0x0001FFFC, gba->video.vram);
1171 } else {
1172 LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram);
1173 STORE_32(value, address & 0x00017FFC, gba->video.vram);
1174 }
1175 break;
1176 case REGION_OAM:
1177 LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw);
1178 STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
1179 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
1180 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) + 2) >> 1);
1181 break;
1182 case REGION_CART0:
1183 case REGION_CART0_EX:
1184 case REGION_CART1:
1185 case REGION_CART1_EX:
1186 case REGION_CART2:
1187 case REGION_CART2_EX:
1188 _pristineCow(gba);
1189 if ((address & (SIZE_CART0 - 4)) >= gba->memory.romSize) {
1190 gba->memory.romSize = (address & (SIZE_CART0 - 4)) + 4;
1191 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1192 }
1193 LOAD_32(oldValue, address & (SIZE_CART0 - 4), gba->memory.rom);
1194 STORE_32(value, address & (SIZE_CART0 - 4), gba->memory.rom);
1195 break;
1196 case REGION_CART_SRAM:
1197 case REGION_CART_SRAM_MIRROR:
1198 if (memory->savedata.type == SAVEDATA_SRAM) {
1199 LOAD_32(oldValue, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1200 STORE_32(value, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1201 } else {
1202 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1203 }
1204 break;
1205 default:
1206 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1207 break;
1208 }
1209 if (old) {
1210 *old = oldValue;
1211 }
1212}
1213
1214void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old) {
1215 struct GBA* gba = (struct GBA*) cpu->master;
1216 struct GBAMemory* memory = &gba->memory;
1217 int16_t oldValue = -1;
1218
1219 switch (address >> BASE_OFFSET) {
1220 case REGION_WORKING_RAM:
1221 LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 2), memory->wram);
1222 STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
1223 break;
1224 case REGION_WORKING_IRAM:
1225 LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1226 STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1227 break;
1228 case REGION_IO:
1229 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch16: 0x%08X", address);
1230 break;
1231 case REGION_PALETTE_RAM:
1232 LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1233 STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1234 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
1235 break;
1236 case REGION_VRAM:
1237 if ((address & 0x0001FFFF) < SIZE_VRAM) {
1238 LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram);
1239 STORE_16(value, address & 0x0001FFFE, gba->video.vram);
1240 } else {
1241 LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram);
1242 STORE_16(value, address & 0x00017FFE, gba->video.vram);
1243 }
1244 break;
1245 case REGION_OAM:
1246 LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
1247 STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
1248 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
1249 break;
1250 case REGION_CART0:
1251 case REGION_CART0_EX:
1252 case REGION_CART1:
1253 case REGION_CART1_EX:
1254 case REGION_CART2:
1255 case REGION_CART2_EX:
1256 _pristineCow(gba);
1257 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1258 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1259 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1260 }
1261 LOAD_16(oldValue, address & (SIZE_CART0 - 2), gba->memory.rom);
1262 STORE_16(value, address & (SIZE_CART0 - 2), gba->memory.rom);
1263 break;
1264 case REGION_CART_SRAM:
1265 case REGION_CART_SRAM_MIRROR:
1266 if (memory->savedata.type == SAVEDATA_SRAM) {
1267 LOAD_16(oldValue, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1268 STORE_16(value, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1269 } else {
1270 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1271 }
1272 break;
1273 default:
1274 mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1275 break;
1276 }
1277 if (old) {
1278 *old = oldValue;
1279 }
1280}
1281
1282void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) {
1283 struct GBA* gba = (struct GBA*) cpu->master;
1284 struct GBAMemory* memory = &gba->memory;
1285 int8_t oldValue = -1;
1286
1287 switch (address >> BASE_OFFSET) {
1288 case REGION_WORKING_RAM:
1289 oldValue = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
1290 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
1291 break;
1292 case REGION_WORKING_IRAM:
1293 oldValue = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
1294 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
1295 break;
1296 case REGION_IO:
1297 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1298 break;
1299 case REGION_PALETTE_RAM:
1300 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1301 break;
1302 case REGION_VRAM:
1303 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1304 break;
1305 case REGION_OAM:
1306 mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1307 break;
1308 case REGION_CART0:
1309 case REGION_CART0_EX:
1310 case REGION_CART1:
1311 case REGION_CART1_EX:
1312 case REGION_CART2:
1313 case REGION_CART2_EX:
1314 _pristineCow(gba);
1315 if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1316 gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1317 gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1318 }
1319 oldValue = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
1320 ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)] = value;
1321 break;
1322 case REGION_CART_SRAM:
1323 case REGION_CART_SRAM_MIRROR:
1324 if (memory->savedata.type == SAVEDATA_SRAM) {
1325 oldValue = ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)];
1326 ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)] = value;
1327 } else {
1328 mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1329 }
1330 break;
1331 default:
1332 mLOG(GBA_MEM, WARN, "Bad memory Patch8: 0x%08X", address);
1333 break;
1334 }
1335 if (old) {
1336 *old = oldValue;
1337 }
1338}
1339
1340#define LDM_LOOP(LDM) \
1341 if (UNLIKELY(!mask)) { \
1342 LDM; \
1343 cpu->gprs[ARM_PC] = value; \
1344 wait += 16; \
1345 address += 64; \
1346 } \
1347 for (i = 0; i < 16; i += 4) { \
1348 if (UNLIKELY(mask & (1 << i))) { \
1349 LDM; \
1350 cpu->gprs[i] = value; \
1351 ++wait; \
1352 address += 4; \
1353 } \
1354 if (UNLIKELY(mask & (2 << i))) { \
1355 LDM; \
1356 cpu->gprs[i + 1] = value; \
1357 ++wait; \
1358 address += 4; \
1359 } \
1360 if (UNLIKELY(mask & (4 << i))) { \
1361 LDM; \
1362 cpu->gprs[i + 2] = value; \
1363 ++wait; \
1364 address += 4; \
1365 } \
1366 if (UNLIKELY(mask & (8 << i))) { \
1367 LDM; \
1368 cpu->gprs[i + 3] = value; \
1369 ++wait; \
1370 address += 4; \
1371 } \
1372 }
1373
1374uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1375 struct GBA* gba = (struct GBA*) cpu->master;
1376 struct GBAMemory* memory = &gba->memory;
1377 uint32_t value;
1378 char* waitstatesRegion = memory->waitstatesSeq32;
1379
1380 int i;
1381 int offset = 4;
1382 int popcount = 0;
1383 if (direction & LSM_D) {
1384 offset = -4;
1385 popcount = popcount32(mask);
1386 address -= (popcount << 2) - 4;
1387 }
1388
1389 if (direction & LSM_B) {
1390 address += offset;
1391 }
1392
1393 uint32_t addressMisalign = address & 0x3;
1394 int region = address >> BASE_OFFSET;
1395 if (region < REGION_CART_SRAM) {
1396 address &= 0xFFFFFFFC;
1397 }
1398 int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1399
1400 switch (region) {
1401 case REGION_BIOS:
1402 LDM_LOOP(LOAD_BIOS);
1403 break;
1404 case REGION_WORKING_RAM:
1405 LDM_LOOP(LOAD_WORKING_RAM);
1406 break;
1407 case REGION_WORKING_IRAM:
1408 LDM_LOOP(LOAD_WORKING_IRAM);
1409 break;
1410 case REGION_IO:
1411 LDM_LOOP(LOAD_IO);
1412 break;
1413 case REGION_PALETTE_RAM:
1414 LDM_LOOP(LOAD_PALETTE_RAM);
1415 break;
1416 case REGION_VRAM:
1417 LDM_LOOP(LOAD_VRAM);
1418 break;
1419 case REGION_OAM:
1420 LDM_LOOP(LOAD_OAM);
1421 break;
1422 case REGION_CART0:
1423 case REGION_CART0_EX:
1424 case REGION_CART1:
1425 case REGION_CART1_EX:
1426 case REGION_CART2:
1427 case REGION_CART2_EX:
1428 LDM_LOOP(LOAD_CART);
1429 break;
1430 case REGION_CART_SRAM:
1431 case REGION_CART_SRAM_MIRROR:
1432 LDM_LOOP(LOAD_SRAM);
1433 break;
1434 default:
1435 LDM_LOOP(LOAD_BAD);
1436 break;
1437 }
1438
1439 if (cycleCounter) {
1440 ++wait;
1441 if (address >> BASE_OFFSET < REGION_CART0) {
1442 wait = GBAMemoryStall(cpu, wait);
1443 }
1444 *cycleCounter += wait;
1445 }
1446
1447 if (direction & LSM_B) {
1448 address -= offset;
1449 }
1450
1451 if (direction & LSM_D) {
1452 address -= (popcount << 2) + 4;
1453 }
1454
1455 return address | addressMisalign;
1456}
1457
1458#define STM_LOOP(STM) \
1459 if (UNLIKELY(!mask)) { \
1460 value = cpu->gprs[ARM_PC] + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB); \
1461 STM; \
1462 wait += 16; \
1463 address += 64; \
1464 } \
1465 for (i = 0; i < 16; i += 4) { \
1466 if (UNLIKELY(mask & (1 << i))) { \
1467 value = cpu->gprs[i]; \
1468 STM; \
1469 ++wait; \
1470 address += 4; \
1471 } \
1472 if (UNLIKELY(mask & (2 << i))) { \
1473 value = cpu->gprs[i + 1]; \
1474 STM; \
1475 ++wait; \
1476 address += 4; \
1477 } \
1478 if (UNLIKELY(mask & (4 << i))) { \
1479 value = cpu->gprs[i + 2]; \
1480 STM; \
1481 ++wait; \
1482 address += 4; \
1483 } \
1484 if (UNLIKELY(mask & (8 << i))) { \
1485 value = cpu->gprs[i + 3]; \
1486 if (i + 3 == ARM_PC) { \
1487 value += WORD_SIZE_ARM; \
1488 } \
1489 STM; \
1490 ++wait; \
1491 address += 4; \
1492 } \
1493 }
1494
1495uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1496 struct GBA* gba = (struct GBA*) cpu->master;
1497 struct GBAMemory* memory = &gba->memory;
1498 uint32_t value;
1499 uint32_t oldValue;
1500 char* waitstatesRegion = memory->waitstatesSeq32;
1501
1502 int i;
1503 int offset = 4;
1504 int popcount = 0;
1505 if (direction & LSM_D) {
1506 offset = -4;
1507 popcount = popcount32(mask);
1508 address -= (popcount << 2) - 4;
1509 }
1510
1511 if (direction & LSM_B) {
1512 address += offset;
1513 }
1514
1515 uint32_t addressMisalign = address & 0x3;
1516 int region = address >> BASE_OFFSET;
1517 if (region < REGION_CART_SRAM) {
1518 address &= 0xFFFFFFFC;
1519 }
1520 int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1521
1522 switch (region) {
1523 case REGION_WORKING_RAM:
1524 STM_LOOP(STORE_WORKING_RAM);
1525 break;
1526 case REGION_WORKING_IRAM:
1527 STM_LOOP(STORE_WORKING_IRAM);
1528 break;
1529 case REGION_IO:
1530 STM_LOOP(STORE_IO);
1531 break;
1532 case REGION_PALETTE_RAM:
1533 STM_LOOP(STORE_PALETTE_RAM);
1534 break;
1535 case REGION_VRAM:
1536 STM_LOOP(STORE_VRAM);
1537 break;
1538 case REGION_OAM:
1539 STM_LOOP(STORE_OAM);
1540 break;
1541 case REGION_CART0:
1542 case REGION_CART0_EX:
1543 case REGION_CART1:
1544 case REGION_CART1_EX:
1545 case REGION_CART2:
1546 case REGION_CART2_EX:
1547 STM_LOOP(STORE_CART);
1548 break;
1549 case REGION_CART_SRAM:
1550 case REGION_CART_SRAM_MIRROR:
1551 STM_LOOP(STORE_SRAM);
1552 break;
1553 default:
1554 STM_LOOP(STORE_BAD);
1555 break;
1556 }
1557
1558 if (cycleCounter) {
1559 if (address >> BASE_OFFSET < REGION_CART0) {
1560 wait = GBAMemoryStall(cpu, wait);
1561 }
1562 *cycleCounter += wait;
1563 }
1564
1565 if (direction & LSM_B) {
1566 address -= offset;
1567 }
1568
1569 if (direction & LSM_D) {
1570 address -= (popcount << 2) + 4;
1571 }
1572
1573 return address | addressMisalign;
1574}
1575
1576void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
1577 struct GBAMemory* memory = &gba->memory;
1578 struct ARMCore* cpu = gba->cpu;
1579 int sram = parameters & 0x0003;
1580 int ws0 = (parameters & 0x000C) >> 2;
1581 int ws0seq = (parameters & 0x0010) >> 4;
1582 int ws1 = (parameters & 0x0060) >> 5;
1583 int ws1seq = (parameters & 0x0080) >> 7;
1584 int ws2 = (parameters & 0x0300) >> 8;
1585 int ws2seq = (parameters & 0x0400) >> 10;
1586 int prefetch = parameters & 0x4000;
1587
1588 memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1589 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1590 memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1591 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1592
1593 memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
1594 memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
1595 memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
1596
1597 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
1598 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
1599 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
1600
1601 memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
1602 memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
1603 memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
1604
1605 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
1606 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
1607 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
1608
1609 memory->prefetch = prefetch;
1610
1611 cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion];
1612 cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
1613
1614 cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
1615 cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
1616}
1617
1618int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) {
1619 struct GBA* gba = (struct GBA*) cpu->master;
1620 struct GBAMemory* memory = &gba->memory;
1621
1622 if (memory->activeRegion < REGION_CART0 || !memory->prefetch) {
1623 // The wait is the stall
1624 return wait;
1625 }
1626
1627 int32_t previousLoads = 0;
1628
1629 // Don't prefetch too much if we're overlapping with a previous prefetch
1630 uint32_t dist = (memory->lastPrefetchedPc - cpu->gprs[ARM_PC]);
1631 int32_t maxLoads = 8;
1632 if (dist < 16) {
1633 previousLoads = dist >> 1;
1634 maxLoads -= previousLoads;
1635 }
1636
1637 int32_t s = cpu->memory.activeSeqCycles16;
1638 int32_t n2s = cpu->memory.activeNonseqCycles16 - cpu->memory.activeSeqCycles16 + 1;
1639
1640 // Figure out how many sequential loads we can jam in
1641 int32_t stall = s + 1;
1642 int32_t loads = 1;
1643
1644 while (stall < wait && loads < maxLoads) {
1645 stall += s;
1646 ++loads;
1647 }
1648 memory->lastPrefetchedPc = cpu->gprs[ARM_PC] + WORD_SIZE_THUMB * (loads + previousLoads - 1);
1649
1650 if (stall > wait) {
1651 // The wait cannot take less time than the prefetch stalls
1652 wait = stall;
1653 }
1654
1655 // This instruction used to have an N, convert it to an S.
1656 wait -= n2s;
1657
1658 // The next |loads|S waitstates disappear entirely, so long as they're all in a row
1659 wait -= stall - 1;
1660
1661 return wait;
1662}
1663
1664void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state) {
1665 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1666 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1667}
1668
1669void GBAMemoryDeserialize(struct GBAMemory* memory, const struct GBASerializedState* state) {
1670 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1671 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1672}
1673
1674void _pristineCow(struct GBA* gba) {
1675 if (!gba->isPristine) {
1676 return;
1677 }
1678#if !defined(FIXED_ROM_BUFFER) && !defined(__wii__)
1679 void* newRom = anonymousMemoryMap(SIZE_CART0);
1680 memcpy(newRom, gba->memory.rom, gba->memory.romSize);
1681 memset(((uint8_t*) newRom) + gba->memory.romSize, 0xFF, SIZE_CART0 - gba->memory.romSize);
1682 if (gba->cpu->memory.activeRegion == gba->memory.rom) {
1683 gba->cpu->memory.activeRegion = newRom;
1684 }
1685 if (gba->romVf) {
1686 gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->memory.romSize);
1687 gba->romVf->close(gba->romVf);
1688 gba->romVf = NULL;
1689 }
1690 gba->memory.rom = newRom;
1691 gba->memory.hw.gpioBase = &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1];
1692#endif
1693 gba->isPristine = false;
1694}
1695
1696void GBAPrintFlush(struct GBA* gba) {
1697 if (!gba->memory.agbPrintBuffer) {
1698 return;
1699 }
1700
1701 char oolBuf[0x101];
1702 size_t i;
1703 for (i = 0; gba->memory.agbPrintCtx.get != gba->memory.agbPrintCtx.put && i < 0x100; ++i) {
1704 int16_t value;
1705 LOAD_16(value, gba->memory.agbPrintCtx.get & -2, gba->memory.agbPrintBuffer);
1706 if (gba->memory.agbPrintCtx.get & 1) {
1707 value >>= 8;
1708 } else {
1709 value &= 0xFF;
1710 }
1711 oolBuf[i] = value;
1712 oolBuf[i + 1] = 0;
1713 ++gba->memory.agbPrintCtx.get;
1714 }
1715 _agbPrintStore(gba, AGB_PRINT_STRUCT + 4, gba->memory.agbPrintCtx.get);
1716
1717 mLOG(GBA_DEBUG, INFO, "%s", oolBuf);
1718}
1719
1720static void _agbPrintStore(struct GBA* gba, uint32_t address, int16_t value) {
1721 struct GBAMemory* memory = &gba->memory;
1722 if ((address & 0x00FFFFFF) < AGB_PRINT_TOP) {
1723 if (!memory->agbPrintBuffer) {
1724 memory->agbPrintBuffer = anonymousMemoryMap(SIZE_AGB_PRINT);
1725 }
1726 STORE_16(value, address & (SIZE_AGB_PRINT - 2), memory->agbPrintBuffer);
1727 } else if ((address & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8)) {
1728 (&memory->agbPrintCtx.request)[(address & 7) >> 1] = value;
1729 }
1730 if (memory->romSize == SIZE_CART0) {
1731 _pristineCow(gba);
1732 memcpy(&memory->rom[AGB_PRINT_FLUSH_ADDR >> 2], _agbPrintFunc, sizeof(_agbPrintFunc));
1733 STORE_16(value, address & (SIZE_CART0 - 2), memory->rom);
1734 } else if (memory->agbPrintCtx.bank == 0xFD && memory->romSize >= SIZE_CART0 / 2) {
1735 _pristineCow(gba);
1736 STORE_16(value, address & (SIZE_CART0 / 2 - 2), memory->rom);
1737 }
1738}
1739
1740static int16_t _agbPrintLoad(struct GBA* gba, uint32_t address) {
1741 struct GBAMemory* memory = &gba->memory;
1742 int16_t value = address >> 1;
1743 if (address < AGB_PRINT_TOP && memory->agbPrintBuffer) {
1744 LOAD_16(value, address & (SIZE_AGB_PRINT - 1), memory->agbPrintBuffer);
1745 } else if ((address & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8)) {
1746 value = (&memory->agbPrintCtx.request)[(address & 7) >> 1];
1747 }
1748 return value;
1749}