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