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