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