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