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/memory.h"
16
17#define IDLE_LOOP_THRESHOLD 10000
18
19static uint32_t _popcount32(unsigned bits);
20static uint32_t _deadbeef[2] = { 0xDEADBEEF, 0xFEEDFACE };
21
22static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
23static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
24
25static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
26static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 7, 7, 9, 9, 13, 13, 9 };
27static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 };
28static const char GBA_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 5, 5, 9, 9, 17, 17, 9 };
29static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
30static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
31static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
32
33void GBAMemoryInit(struct GBA* gba) {
34 struct ARMCore* cpu = gba->cpu;
35 cpu->memory.load32 = GBALoad32;
36 cpu->memory.load16 = GBALoad16;
37 cpu->memory.load8 = GBALoad8;
38 cpu->memory.loadMultiple = GBALoadMultiple;
39 cpu->memory.store32 = GBAStore32;
40 cpu->memory.store16 = GBAStore16;
41 cpu->memory.store8 = GBAStore8;
42 cpu->memory.storeMultiple = GBAStoreMultiple;
43
44 gba->memory.bios = (uint32_t*) hleBios;
45 gba->memory.fullBios = 0;
46 gba->memory.wram = 0;
47 gba->memory.iwram = 0;
48 gba->memory.rom = 0;
49 gba->memory.hw.p = gba;
50
51 int i;
52 for (i = 0; i < 16; ++i) {
53 gba->memory.waitstatesNonseq16[i] = GBA_BASE_WAITSTATES[i];
54 gba->memory.waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
55 gba->memory.waitstatesPrefetchNonseq16[i] = GBA_BASE_WAITSTATES[i];
56 gba->memory.waitstatesPrefetchSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
57 gba->memory.waitstatesNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
58 gba->memory.waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
59 gba->memory.waitstatesPrefetchNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
60 gba->memory.waitstatesPrefetchSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
61 }
62 for (; i < 256; ++i) {
63 gba->memory.waitstatesNonseq16[i] = 0;
64 gba->memory.waitstatesSeq16[i] = 0;
65 gba->memory.waitstatesNonseq32[i] = 0;
66 gba->memory.waitstatesSeq32[i] = 0;
67 }
68
69 gba->memory.activeRegion = -1;
70 cpu->memory.activeRegion = 0;
71 cpu->memory.activeMask = 0;
72 cpu->memory.setActiveRegion = GBASetActiveRegion;
73 cpu->memory.activeSeqCycles32 = 0;
74 cpu->memory.activeSeqCycles16 = 0;
75 cpu->memory.activeNonseqCycles32 = 0;
76 cpu->memory.activeNonseqCycles16 = 0;
77 cpu->memory.activeUncachedCycles32 = 0;
78 cpu->memory.activeUncachedCycles16 = 0;
79 gba->memory.biosPrefetch = 0;
80}
81
82void GBAMemoryDeinit(struct GBA* gba) {
83 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
84 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
85 if (gba->memory.rom) {
86 mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
87 }
88 GBASavedataDeinit(&gba->memory.savedata);
89}
90
91void GBAMemoryReset(struct GBA* gba) {
92 if (gba->memory.wram) {
93 mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
94 }
95 gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
96
97 if (gba->memory.iwram) {
98 mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
99 }
100 gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
101
102 memset(gba->memory.io, 0, sizeof(gba->memory.io));
103 memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
104 int i;
105 for (i = 0; i < 4; ++i) {
106 gba->memory.dma[i].count = 0x4000;
107 gba->memory.dma[i].nextEvent = INT_MAX;
108 }
109 gba->memory.dma[3].count = 0x10000;
110 gba->memory.activeDMA = -1;
111 gba->memory.nextDMA = INT_MAX;
112 gba->memory.eventDiff = 0;
113
114 if (!gba->memory.wram || !gba->memory.iwram) {
115 GBAMemoryDeinit(gba);
116 GBALog(gba, GBA_LOG_FATAL, "Could not map memory");
117 }
118}
119
120static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t address) {
121 struct ARMInstructionInfo info;
122 uint32_t nextAddress = address;
123 memset(gba->taintedRegisters, 0, sizeof(gba->taintedRegisters));
124 if (cpu->executionMode == MODE_THUMB) {
125 while (true) {
126 uint16_t opcode;
127 LOAD_16(opcode, nextAddress & cpu->memory.activeMask, cpu->memory.activeRegion);
128 ARMDecodeThumb(opcode, &info);
129 switch (info.branchType) {
130 case ARM_BRANCH_NONE:
131 if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
132 if (info.mnemonic == ARM_MN_STR || gba->taintedRegisters[info.memory.baseReg]) {
133 gba->idleDetectionStep = -1;
134 return;
135 }
136 uint32_t loadAddress = gba->cachedRegisters[info.memory.baseReg];
137 uint32_t offset = 0;
138 if (info.memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
139 offset = info.memory.offset.immediate;
140 } else if (info.memory.format & ARM_MEMORY_REGISTER_OFFSET) {
141 int reg = info.memory.offset.reg;
142 if (gba->cachedRegisters[reg]) {
143 gba->idleDetectionStep = -1;
144 return;
145 }
146 offset = gba->cachedRegisters[reg];
147 }
148 if (info.memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
149 loadAddress -= offset;
150 } else {
151 loadAddress += offset;
152 }
153 if ((loadAddress >> BASE_OFFSET) == REGION_IO) {
154 gba->idleDetectionStep = -1;
155 return;
156 }
157 if ((loadAddress >> BASE_OFFSET) < REGION_CART0 || (loadAddress >> BASE_OFFSET) > REGION_CART2_EX) {
158 gba->taintedRegisters[info.op1.reg] = true;
159 } else {
160 switch (info.memory.width) {
161 case 1:
162 gba->cachedRegisters[info.op1.reg] = GBALoad8(cpu, loadAddress, 0);
163 break;
164 case 2:
165 gba->cachedRegisters[info.op1.reg] = GBALoad16(cpu, loadAddress, 0);
166 break;
167 case 4:
168 gba->cachedRegisters[info.op1.reg] = GBALoad32(cpu, loadAddress, 0);
169 break;
170 }
171 }
172 } else if (info.operandFormat & ARM_OPERAND_AFFECTED_1) {
173 gba->taintedRegisters[info.op1.reg] = true;
174 }
175 nextAddress += WORD_SIZE_THUMB;
176 break;
177 case ARM_BRANCH:
178 if ((uint32_t) info.op1.immediate + nextAddress + WORD_SIZE_THUMB * 2 == address) {
179 gba->idleLoop = address;
180 gba->idleOptimization = IDLE_LOOP_REMOVE;
181 }
182 gba->idleDetectionStep = -1;
183 return;
184 default:
185 gba->idleDetectionStep = -1;
186 return;
187 }
188 }
189 } else {
190 gba->idleDetectionStep = -1;
191 }
192}
193
194static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
195 struct GBA* gba = (struct GBA*) cpu->master;
196 struct GBAMemory* memory = &gba->memory;
197
198 int newRegion = address >> BASE_OFFSET;
199 if (gba->idleOptimization >= IDLE_LOOP_REMOVE && memory->activeRegion != REGION_BIOS) {
200 if (address == gba->idleLoop) {
201 if (gba->haltPending) {
202 gba->haltPending = false;
203 GBAHalt(gba);
204 } else {
205 gba->haltPending = true;
206 }
207 } else if (gba->idleOptimization >= IDLE_LOOP_DETECT && newRegion == memory->activeRegion) {
208 if (address == gba->lastJump) {
209 switch (gba->idleDetectionStep) {
210 case 0:
211 memcpy(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters));
212 ++gba->idleDetectionStep;
213 break;
214 case 1:
215 if (memcmp(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters))) {
216 gba->idleDetectionStep = -1;
217 ++gba->idleDetectionFailures;
218 if (gba->idleDetectionFailures > IDLE_LOOP_THRESHOLD) {
219 gba->idleOptimization = IDLE_LOOP_IGNORE;
220 }
221 break;
222 }
223 _analyzeForIdleLoop(gba, cpu, address);
224 break;
225 }
226 } else {
227 gba->idleDetectionStep = 0;
228 }
229 }
230 }
231
232 gba->lastJump = address;
233 if (newRegion == memory->activeRegion) {
234 return;
235 }
236
237 if (memory->activeRegion == REGION_BIOS) {
238 memory->biosPrefetch = cpu->prefetch[1];
239 }
240 memory->activeRegion = newRegion;
241 switch (address & ~OFFSET_MASK) {
242 case BASE_BIOS:
243 cpu->memory.activeRegion = memory->bios;
244 cpu->memory.activeMask = SIZE_BIOS - 1;
245 break;
246 case BASE_WORKING_RAM:
247 cpu->memory.activeRegion = memory->wram;
248 cpu->memory.activeMask = SIZE_WORKING_RAM - 1;
249 break;
250 case BASE_WORKING_IRAM:
251 cpu->memory.activeRegion = memory->iwram;
252 cpu->memory.activeMask = SIZE_WORKING_IRAM - 1;
253 break;
254 case BASE_VRAM:
255 cpu->memory.activeRegion = (uint32_t*) gba->video.renderer->vram;
256 cpu->memory.activeMask = 0x0000FFFF;
257 break;
258 case BASE_CART0:
259 case BASE_CART0_EX:
260 case BASE_CART1:
261 case BASE_CART1_EX:
262 case BASE_CART2:
263 case BASE_CART2_EX:
264 cpu->memory.activeRegion = memory->rom;
265 cpu->memory.activeMask = SIZE_CART0 - 1;
266 break;
267 default:
268 cpu->memory.activeRegion = _deadbeef;
269 cpu->memory.activeMask = 0;
270 GBALog(gba, GBA_LOG_FATAL, "Jumped to invalid address");
271 break;
272 }
273 cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
274 cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
275 cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
276 cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
277 cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
278 cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
279}
280
281#define LOAD_BAD \
282 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); \
283 if (gba->performingDMA) { \
284 value = gba->bus; \
285 } else { \
286 value = cpu->prefetch[1]; \
287 if (cpu->executionMode == MODE_THUMB) { \
288 value |= value << 16; \
289 } \
290 }
291
292#define LOAD_BIOS \
293 if (address < SIZE_BIOS) { \
294 if (memory->activeRegion == REGION_BIOS) { \
295 LOAD_32(value, address, memory->bios); \
296 } else { \
297 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load32: 0x%08X", address); \
298 value = memory->biosPrefetch; \
299 } \
300 } else { \
301 LOAD_BAD; \
302 }
303
304#define LOAD_WORKING_RAM \
305 LOAD_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); \
306 wait += waitstatesRegion[REGION_WORKING_RAM];
307
308#define LOAD_WORKING_IRAM LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
309#define LOAD_IO value = GBAIORead(gba, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gba, (address & (SIZE_IO - 1)) | 2) << 16);
310
311#define LOAD_PALETTE_RAM \
312 LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); \
313 ++wait;
314
315#define LOAD_VRAM \
316 if ((address & 0x0001FFFF) < SIZE_VRAM) { \
317 LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
318 } else { \
319 LOAD_32(value, address & 0x00017FFF, gba->video.renderer->vram); \
320 } \
321 ++wait;
322
323#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
324
325#define LOAD_CART \
326 wait += waitstatesRegion[address >> BASE_OFFSET]; \
327 if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \
328 LOAD_32(value, address & (SIZE_CART0 - 1), memory->rom); \
329 } else { \
330 GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load32: 0x%08X", address); \
331 value = (address >> 1) & 0xFFFF; \
332 value |= value << 16; \
333 }
334
335#define LOAD_SRAM \
336 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; \
337 value = GBALoad8(cpu, address, 0); \
338 value |= value << 8; \
339 value |= value << 16;
340
341uint32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
342 struct GBA* gba = (struct GBA*) cpu->master;
343 struct GBAMemory* memory = &gba->memory;
344 uint32_t value = 0;
345 int wait = 0;
346 char* waitstatesRegion = memory->waitstatesNonseq32;
347
348 switch (address >> BASE_OFFSET) {
349 case REGION_BIOS:
350 LOAD_BIOS;
351 break;
352 case REGION_WORKING_RAM:
353 LOAD_WORKING_RAM;
354 break;
355 case REGION_WORKING_IRAM:
356 LOAD_WORKING_IRAM;
357 break;
358 case REGION_IO:
359 LOAD_IO;
360 break;
361 case REGION_PALETTE_RAM:
362 LOAD_PALETTE_RAM;
363 break;
364 case REGION_VRAM:
365 LOAD_VRAM;
366 break;
367 case REGION_OAM:
368 LOAD_OAM;
369 break;
370 case REGION_CART0:
371 case REGION_CART0_EX:
372 case REGION_CART1:
373 case REGION_CART1_EX:
374 case REGION_CART2:
375 case REGION_CART2_EX:
376 LOAD_CART;
377 break;
378 case REGION_CART_SRAM:
379 case REGION_CART_SRAM_MIRROR:
380 LOAD_SRAM;
381 break;
382 default:
383 LOAD_BAD;
384 break;
385 }
386
387 if (cycleCounter) {
388 *cycleCounter += 2 + wait;
389 }
390 // Unaligned 32-bit loads are "rotated" so they make some semblance of sense
391 int rotate = (address & 3) << 3;
392 return ROR(value, rotate);
393}
394
395uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
396 struct GBA* gba = (struct GBA*) cpu->master;
397 struct GBAMemory* memory = &gba->memory;
398 uint32_t value = 0;
399 int wait = 0;
400
401 switch (address >> BASE_OFFSET) {
402 case REGION_BIOS:
403 if (address < SIZE_BIOS) {
404 if (memory->activeRegion == REGION_BIOS) {
405 LOAD_16(value, address, memory->bios);
406 } else {
407 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load16: 0x%08X", address);
408 LOAD_16(value, address & 2, &memory->biosPrefetch);
409 }
410 } else {
411 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
412 if (gba->performingDMA) {
413 LOAD_16(value, address & 2, &gba->bus);
414 } else {
415 uint32_t prefetch = cpu->prefetch[1];
416 if (cpu->executionMode == MODE_THUMB) {
417 prefetch |= prefetch << 16;
418 }
419 LOAD_16(value, address & 2, &prefetch);
420 }
421 }
422 break;
423 case REGION_WORKING_RAM:
424 LOAD_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
425 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
426 break;
427 case REGION_WORKING_IRAM:
428 LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
429 break;
430 case REGION_IO:
431 value = GBAIORead(gba, address & (SIZE_IO - 1));
432 break;
433 case REGION_PALETTE_RAM:
434 LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
435 break;
436 case REGION_VRAM:
437 if ((address & 0x0001FFFF) < SIZE_VRAM) {
438 LOAD_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
439 } else {
440 LOAD_16(value, address & 0x00017FFF, gba->video.renderer->vram);
441 }
442 break;
443 case REGION_OAM:
444 LOAD_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
445 break;
446 case REGION_CART0:
447 case REGION_CART0_EX:
448 case REGION_CART1:
449 case REGION_CART1_EX:
450 case REGION_CART2:
451 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
452 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
453 LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
454 } else {
455 GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address);
456 value = (address >> 1) & 0xFFFF; \
457 }
458 break;
459 case REGION_CART2_EX:
460 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
461 if (memory->savedata.type == SAVEDATA_EEPROM) {
462 value = GBASavedataReadEEPROM(&memory->savedata);
463 } else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
464 LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
465 } else {
466 GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address);
467 value = (address >> 1) & 0xFFFF; \
468 }
469 break;
470 case REGION_CART_SRAM:
471 case REGION_CART_SRAM_MIRROR:
472 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
473 value = GBALoad8(cpu, address, 0);
474 value |= value << 8;
475 break;
476 default:
477 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
478 if (gba->performingDMA) {
479 LOAD_16(value, address & 2, &gba->bus);
480 } else {
481 uint32_t prefetch = cpu->prefetch[1];
482 if (cpu->executionMode == MODE_THUMB) {
483 prefetch |= prefetch << 16;
484 }
485 LOAD_16(value, address & 2, &prefetch);
486 }
487 break;
488 }
489
490 if (cycleCounter) {
491 *cycleCounter += 2 + wait;
492 }
493 // Unaligned 16-bit loads are "unpredictable", but the GBA rotates them, so we have to, too.
494 int rotate = (address & 1) << 3;
495 return ROR(value, rotate);
496}
497
498uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
499 struct GBA* gba = (struct GBA*) cpu->master;
500 struct GBAMemory* memory = &gba->memory;
501 uint8_t value = 0;
502 int wait = 0;
503
504 switch (address >> BASE_OFFSET) {
505 case REGION_BIOS:
506 if (address < SIZE_BIOS) {
507 if (memory->activeRegion == REGION_BIOS) {
508 value = ((int8_t*) memory->bios)[address];
509 } else {
510 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
511 value = ((uint8_t*) &memory->biosPrefetch)[address & 3];
512 }
513 } else {
514 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
515 if (gba->performingDMA) {
516 value = ((uint8_t*) &gba->bus)[address & 3];
517 } else {
518 uint32_t prefetch = cpu->prefetch[1];
519 if (cpu->executionMode == MODE_THUMB) {
520 prefetch |= prefetch << 16;
521 }
522 value = ((uint8_t*) &prefetch)[address & 3];
523 }
524 }
525 break;
526 case REGION_WORKING_RAM:
527 value = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
528 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
529 break;
530 case REGION_WORKING_IRAM:
531 value = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
532 break;
533 case REGION_IO:
534 value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
535 break;
536 case REGION_PALETTE_RAM:
537 value = ((int8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
538 break;
539 case REGION_VRAM:
540 if ((address & 0x0001FFFF) < SIZE_VRAM) {
541 value = ((int8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
542 } else {
543 value = ((int8_t*) gba->video.renderer->vram)[address & 0x00017FFF];
544 }
545 break;
546 case REGION_OAM:
547 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
548 break;
549 case REGION_CART0:
550 case REGION_CART0_EX:
551 case REGION_CART1:
552 case REGION_CART1_EX:
553 case REGION_CART2:
554 case REGION_CART2_EX:
555 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
556 if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
557 value = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
558 } else {
559 GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load8: 0x%08X", address);
560 value = (address >> 1) & 0xFF; \
561 }
562 break;
563 case REGION_CART_SRAM:
564 case REGION_CART_SRAM_MIRROR:
565 wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
566 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
567 GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame");
568 GBASavedataInitSRAM(&memory->savedata);
569 }
570 if (memory->savedata.type == SAVEDATA_SRAM) {
571 value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
572 } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
573 value = GBASavedataReadFlash(&memory->savedata, address);
574 } else if (memory->hw.devices & HW_TILT) {
575 value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK);
576 } else {
577 GBALog(gba, GBA_LOG_GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
578 value = 0xFF;
579 }
580 break;
581 default:
582 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
583 if (gba->performingDMA) {
584 value = ((uint8_t*) &gba->bus)[address & 3];
585 } else {
586 uint32_t prefetch = cpu->prefetch[1];
587 if (cpu->executionMode == MODE_THUMB) {
588 prefetch |= prefetch << 16;
589 }
590 value = ((uint8_t*) &prefetch)[address & 3];
591 }
592 break;
593 }
594
595 if (cycleCounter) {
596 *cycleCounter += 2 + wait;
597 }
598 return value;
599}
600
601#define STORE_WORKING_RAM \
602 STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); \
603 wait += waitstatesRegion[REGION_WORKING_RAM];
604
605#define STORE_WORKING_IRAM \
606 STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
607
608#define STORE_IO \
609 GBAIOWrite32(gba, address & (SIZE_IO - 1), value);
610
611#define STORE_PALETTE_RAM \
612 STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); \
613 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16); \
614 ++wait; \
615 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
616
617#define STORE_VRAM \
618 if ((address & 0x0001FFFF) < SIZE_VRAM) { \
619 STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
620 } else { \
621 STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram); \
622 } \
623 ++wait;
624
625#define STORE_OAM \
626 STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw); \
627 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
628 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
629
630#define STORE_CART \
631 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
632
633#define STORE_SRAM \
634 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
635
636#define STORE_BAD \
637 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
638
639void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
640 struct GBA* gba = (struct GBA*) cpu->master;
641 struct GBAMemory* memory = &gba->memory;
642 int wait = 0;
643 char* waitstatesRegion = memory->waitstatesNonseq32;
644
645 switch (address >> BASE_OFFSET) {
646 case REGION_WORKING_RAM:
647 STORE_WORKING_RAM;
648 break;
649 case REGION_WORKING_IRAM:
650 STORE_WORKING_IRAM
651 break;
652 case REGION_IO:
653 STORE_IO;
654 break;
655 case REGION_PALETTE_RAM:
656 STORE_PALETTE_RAM;
657 break;
658 case REGION_VRAM:
659 STORE_VRAM;
660 break;
661 case REGION_OAM:
662 STORE_OAM;
663 break;
664 case REGION_CART0:
665 case REGION_CART0_EX:
666 case REGION_CART1:
667 case REGION_CART1_EX:
668 case REGION_CART2:
669 case REGION_CART2_EX:
670 STORE_CART;
671 break;
672 case REGION_CART_SRAM:
673 case REGION_CART_SRAM_MIRROR:
674 STORE_SRAM;
675 break;
676 default:
677 STORE_BAD;
678 break;
679 }
680
681 if (cycleCounter) {
682 *cycleCounter += 1 + wait;
683 }
684}
685
686void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
687 struct GBA* gba = (struct GBA*) cpu->master;
688 struct GBAMemory* memory = &gba->memory;
689 int wait = 0;
690
691 switch (address >> BASE_OFFSET) {
692 case REGION_WORKING_RAM:
693 STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
694 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
695 break;
696 case REGION_WORKING_IRAM:
697 STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
698 break;
699 case REGION_IO:
700 GBAIOWrite(gba, address & (SIZE_IO - 1), value);
701 break;
702 case REGION_PALETTE_RAM:
703 STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
704 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
705 break;
706 case REGION_VRAM:
707 if ((address & 0x0001FFFF) < SIZE_VRAM) {
708 STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
709 } else {
710 STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram);
711 }
712 break;
713 case REGION_OAM:
714 STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
715 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
716 break;
717 case REGION_CART0:
718 if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFF)) {
719 uint32_t reg = address & 0xFFFFFF;
720 GBAHardwareGPIOWrite(&memory->hw, reg, value);
721 } else {
722 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
723 }
724 break;
725 case REGION_CART2_EX:
726 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
727 GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
728 GBASavedataInitEEPROM(&memory->savedata);
729 }
730 GBASavedataWriteEEPROM(&memory->savedata, value, 1);
731 break;
732 case REGION_CART_SRAM:
733 case REGION_CART_SRAM_MIRROR:
734 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store16: 0x%08X", address);
735 break;
736 default:
737 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store16: 0x%08X", address);
738 break;
739 }
740
741 if (cycleCounter) {
742 *cycleCounter += 1 + wait;
743 }
744}
745
746void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
747 struct GBA* gba = (struct GBA*) cpu->master;
748 struct GBAMemory* memory = &gba->memory;
749 int wait = 0;
750
751 switch (address >> BASE_OFFSET) {
752 case REGION_WORKING_RAM:
753 ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
754 wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
755 break;
756 case REGION_WORKING_IRAM:
757 ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
758 break;
759 case REGION_IO:
760 GBAIOWrite8(gba, address & (SIZE_IO - 1), value);
761 break;
762 case REGION_PALETTE_RAM:
763 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
764 break;
765 case REGION_VRAM:
766 if (address >= 0x06018000) {
767 // TODO: check BG mode
768 GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
769 break;
770 }
771 ((int8_t*) gba->video.renderer->vram)[address & 0x1FFFE] = value;
772 ((int8_t*) gba->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
773 break;
774 case REGION_OAM:
775 GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
776 break;
777 case REGION_CART0:
778 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
779 break;
780 case REGION_CART_SRAM:
781 case REGION_CART_SRAM_MIRROR:
782 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
783 if (address == SAVEDATA_FLASH_BASE) {
784 GBALog(gba, GBA_LOG_INFO, "Detected Flash savegame");
785 GBASavedataInitFlash(&memory->savedata);
786 } else {
787 GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame");
788 GBASavedataInitSRAM(&memory->savedata);
789 }
790 }
791 if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
792 GBASavedataWriteFlash(&memory->savedata, address, value);
793 } else if (memory->savedata.type == SAVEDATA_SRAM) {
794 memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
795 } else if (memory->hw.devices & HW_TILT) {
796 GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
797 } else {
798 GBALog(gba, GBA_LOG_GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
799 }
800 wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
801 break;
802 default:
803 GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store8: 0x%08X", address);
804 break;
805 }
806
807 if (cycleCounter) {
808 *cycleCounter += 1 + wait;
809 }
810}
811
812void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old) {
813 struct GBA* gba = (struct GBA*) cpu->master;
814 struct GBAMemory* memory = &gba->memory;
815 int32_t oldValue = -1;
816
817 switch (address >> BASE_OFFSET) {
818 case REGION_WORKING_RAM:
819 LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 1), memory->wram);
820 STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
821 break;
822 case REGION_WORKING_IRAM:
823 LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
824 STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
825 break;
826 case REGION_IO:
827 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Patch32: 0x%08X", address);
828 break;
829 case REGION_PALETTE_RAM:
830 LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
831 STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
832 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
833 gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16);
834 break;
835 case REGION_VRAM:
836 if ((address & 0x0001FFFF) < SIZE_VRAM) {
837 LOAD_32(oldValue, address & 0x0001FFFF, gba->video.renderer->vram);
838 STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram);
839 } else {
840 LOAD_32(oldValue, address & 0x00017FFF, gba->video.renderer->vram);
841 STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram);
842 }
843 break;
844 case REGION_OAM:
845 LOAD_32(oldValue, address & (SIZE_OAM - 1), gba->video.oam.raw);
846 STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
847 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
848 gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 1)) + 2) >> 1);
849 break;
850 case REGION_CART0:
851 case REGION_CART0_EX:
852 case REGION_CART1:
853 case REGION_CART1_EX:
854 case REGION_CART2:
855 case REGION_CART2_EX:
856 if ((address & (SIZE_CART0 - 1)) < gba->memory.romSize) {
857 LOAD_32(oldValue, address & (SIZE_CART0 - 1), gba->memory.rom);
858 STORE_32(value, address & (SIZE_CART0 - 1), gba->memory.rom);
859 } else {
860 GBALog(gba, GBA_LOG_WARN, "Bad memory Patch32: 0x%08X", address);
861 }
862 break;
863 case REGION_CART_SRAM:
864 case REGION_CART_SRAM_MIRROR:
865 if (memory->savedata.type == SAVEDATA_SRAM) {
866 LOAD_32(oldValue, address & (SIZE_CART_SRAM - 1), memory->savedata.data);
867 STORE_32(value, address & (SIZE_CART_SRAM - 1), memory->savedata.data);
868 } else {
869 GBALog(gba, GBA_LOG_GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
870 }
871 break;
872 default:
873 GBALog(gba, GBA_LOG_WARN, "Bad memory Patch16: 0x%08X", address);
874 break;
875 }
876 if (old) {
877 *old = oldValue;
878 }
879}
880
881void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old) {
882 struct GBA* gba = (struct GBA*) cpu->master;
883 struct GBAMemory* memory = &gba->memory;
884 int16_t oldValue = -1;
885
886 switch (address >> BASE_OFFSET) {
887 case REGION_WORKING_RAM:
888 LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 1), memory->wram);
889 STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
890 break;
891 case REGION_WORKING_IRAM:
892 LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
893 STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
894 break;
895 case REGION_IO:
896 GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Patch16: 0x%08X", address);
897 break;
898 case REGION_PALETTE_RAM:
899 LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
900 STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
901 gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
902 break;
903 case REGION_VRAM:
904 if ((address & 0x0001FFFF) < SIZE_VRAM) {
905 LOAD_16(oldValue, address & 0x0001FFFF, gba->video.renderer->vram);
906 STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
907 } else {
908 LOAD_16(oldValue, address & 0x00017FFF, gba->video.renderer->vram);
909 STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram);
910 }
911 break;
912 case REGION_OAM:
913 LOAD_16(oldValue, address & (SIZE_OAM - 1), gba->video.oam.raw);
914 STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
915 gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
916 break;
917 case REGION_CART0:
918 case REGION_CART0_EX:
919 case REGION_CART1:
920 case REGION_CART1_EX:
921 case REGION_CART2:
922 case REGION_CART2_EX:
923 if ((address & (SIZE_CART0 - 1)) < gba->memory.romSize) {
924 LOAD_16(oldValue, address & (SIZE_CART0 - 1), gba->memory.rom);
925 STORE_16(value, address & (SIZE_CART0 - 1), gba->memory.rom);
926 } else {
927 GBALog(gba, GBA_LOG_WARN, "Bad memory Patch16: 0x%08X", address);
928 }
929 break;
930 case REGION_CART_SRAM:
931 case REGION_CART_SRAM_MIRROR:
932 if (memory->savedata.type == SAVEDATA_SRAM) {
933 LOAD_16(oldValue, address & (SIZE_CART_SRAM - 1), memory->savedata.data);
934 STORE_16(value, address & (SIZE_CART_SRAM - 1), memory->savedata.data);
935 } else {
936 GBALog(gba, GBA_LOG_GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
937 }
938 break;
939 default:
940 GBALog(gba, GBA_LOG_WARN, "Bad memory Patch16: 0x%08X", address);
941 break;
942 }
943 if (old) {
944 *old = oldValue;
945 }
946}
947
948#define LDM_LOOP(LDM) \
949 for (i = 0; i < 16; i += 4) { \
950 if (UNLIKELY(mask & (1 << i))) { \
951 LDM; \
952 waitstatesRegion = memory->waitstatesSeq32; \
953 cpu->gprs[i] = value; \
954 ++wait; \
955 address += 4; \
956 } \
957 if (UNLIKELY(mask & (2 << i))) { \
958 LDM; \
959 waitstatesRegion = memory->waitstatesSeq32; \
960 cpu->gprs[i + 1] = value; \
961 ++wait; \
962 address += 4; \
963 } \
964 if (UNLIKELY(mask & (4 << i))) { \
965 LDM; \
966 waitstatesRegion = memory->waitstatesSeq32; \
967 cpu->gprs[i + 2] = value; \
968 ++wait; \
969 address += 4; \
970 } \
971 if (UNLIKELY(mask & (8 << i))) { \
972 LDM; \
973 waitstatesRegion = memory->waitstatesSeq32; \
974 cpu->gprs[i + 3] = value; \
975 ++wait; \
976 address += 4; \
977 } \
978 }
979
980uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
981 struct GBA* gba = (struct GBA*) cpu->master;
982 struct GBAMemory* memory = &gba->memory;
983 uint32_t value;
984 int wait = 0;
985 char* waitstatesRegion = memory->waitstatesNonseq32;
986
987 int i;
988 int offset = 4;
989 int popcount = 0;
990 if (direction & LSM_D) {
991 offset = -4;
992 popcount = _popcount32(mask);
993 address -= (popcount << 2) - 4;
994 }
995
996 if (direction & LSM_B) {
997 address += offset;
998 }
999
1000 uint32_t addressMisalign = address & 0x3;
1001 address &= 0xFFFFFFFC;
1002
1003 switch (address >> BASE_OFFSET) {
1004 case REGION_BIOS:
1005 LDM_LOOP(LOAD_BIOS);
1006 break;
1007 case REGION_WORKING_RAM:
1008 LDM_LOOP(LOAD_WORKING_RAM);
1009 break;
1010 case REGION_WORKING_IRAM:
1011 LDM_LOOP(LOAD_WORKING_IRAM);
1012 break;
1013 case REGION_IO:
1014 LDM_LOOP(LOAD_IO);
1015 break;
1016 case REGION_PALETTE_RAM:
1017 LDM_LOOP(LOAD_PALETTE_RAM);
1018 break;
1019 case REGION_VRAM:
1020 LDM_LOOP(LOAD_VRAM);
1021 break;
1022 case REGION_OAM:
1023 LDM_LOOP(LOAD_OAM);
1024 break;
1025 case REGION_CART0:
1026 case REGION_CART0_EX:
1027 case REGION_CART1:
1028 case REGION_CART1_EX:
1029 case REGION_CART2:
1030 case REGION_CART2_EX:
1031 LDM_LOOP(LOAD_CART);
1032 break;
1033 case REGION_CART_SRAM:
1034 case REGION_CART_SRAM_MIRROR:
1035 LDM_LOOP(LOAD_SRAM);
1036 break;
1037 default:
1038 LDM_LOOP(LOAD_BAD);
1039 break;
1040 }
1041
1042 if (cycleCounter) {
1043 *cycleCounter += wait;
1044 }
1045
1046 if (direction & LSM_B) {
1047 address -= offset;
1048 }
1049
1050 if (direction & LSM_D) {
1051 address -= (popcount << 2) + 4;
1052 }
1053
1054 return address | addressMisalign;
1055}
1056
1057#define STM_LOOP(STM) \
1058 for (i = 0; i < 16; i += 4) { \
1059 if (UNLIKELY(mask & (1 << i))) { \
1060 value = cpu->gprs[i]; \
1061 STM; \
1062 waitstatesRegion = memory->waitstatesSeq32; \
1063 ++wait; \
1064 address += 4; \
1065 } \
1066 if (UNLIKELY(mask & (2 << i))) { \
1067 value = cpu->gprs[i + 1]; \
1068 STM; \
1069 waitstatesRegion = memory->waitstatesSeq32; \
1070 ++wait; \
1071 address += 4; \
1072 } \
1073 if (UNLIKELY(mask & (4 << i))) { \
1074 value = cpu->gprs[i + 2]; \
1075 STM; \
1076 waitstatesRegion = memory->waitstatesSeq32; \
1077 ++wait; \
1078 address += 4; \
1079 } \
1080 if (UNLIKELY(mask & (8 << i))) { \
1081 value = cpu->gprs[i + 3]; \
1082 STM; \
1083 waitstatesRegion = memory->waitstatesSeq32; \
1084 ++wait; \
1085 address += 4; \
1086 } \
1087 }
1088
1089uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1090 struct GBA* gba = (struct GBA*) cpu->master;
1091 struct GBAMemory* memory = &gba->memory;
1092 uint32_t value;
1093 int wait = 0;
1094 char* waitstatesRegion = memory->waitstatesNonseq32;
1095
1096 int i;
1097 int offset = 4;
1098 int popcount = 0;
1099 if (direction & LSM_D) {
1100 offset = -4;
1101 popcount = _popcount32(mask);
1102 address -= (popcount << 2) - 4;
1103 }
1104
1105 if (direction & LSM_B) {
1106 address += offset;
1107 }
1108
1109 uint32_t addressMisalign = address & 0x3;
1110 address &= 0xFFFFFFFC;
1111
1112 switch (address >> BASE_OFFSET) {
1113 case REGION_WORKING_RAM:
1114 STM_LOOP(STORE_WORKING_RAM);
1115 break;
1116 case REGION_WORKING_IRAM:
1117 STM_LOOP(STORE_WORKING_IRAM);
1118 break;
1119 case REGION_IO:
1120 STM_LOOP(STORE_IO);
1121 break;
1122 case REGION_PALETTE_RAM:
1123 STM_LOOP(STORE_PALETTE_RAM);
1124 break;
1125 case REGION_VRAM:
1126 STM_LOOP(STORE_VRAM);
1127 break;
1128 case REGION_OAM:
1129 STM_LOOP(STORE_OAM);
1130 break;
1131 case REGION_CART0:
1132 case REGION_CART0_EX:
1133 case REGION_CART1:
1134 case REGION_CART1_EX:
1135 case REGION_CART2:
1136 case REGION_CART2_EX:
1137 STM_LOOP(STORE_CART);
1138 break;
1139 case REGION_CART_SRAM:
1140 case REGION_CART_SRAM_MIRROR:
1141 STM_LOOP(STORE_SRAM);
1142 break;
1143 default:
1144 STM_LOOP(STORE_BAD);
1145 break;
1146 }
1147
1148 if (cycleCounter) {
1149 *cycleCounter += wait;
1150 }
1151
1152 if (direction & LSM_B) {
1153 address -= offset;
1154 }
1155
1156 if (direction & LSM_D) {
1157 address -= (popcount << 2) + 4;
1158 }
1159
1160 return address | addressMisalign;
1161}
1162
1163void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
1164 struct GBAMemory* memory = &gba->memory;
1165 struct ARMCore* cpu = gba->cpu;
1166 int sram = parameters & 0x0003;
1167 int ws0 = (parameters & 0x000C) >> 2;
1168 int ws0seq = (parameters & 0x0010) >> 4;
1169 int ws1 = (parameters & 0x0060) >> 5;
1170 int ws1seq = (parameters & 0x0080) >> 7;
1171 int ws2 = (parameters & 0x0300) >> 8;
1172 int ws2seq = (parameters & 0x0400) >> 10;
1173 int prefetch = parameters & 0x4000;
1174
1175 memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1176 memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1177 memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1178 memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1179
1180 memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
1181 memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
1182 memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
1183
1184 memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
1185 memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
1186 memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
1187
1188 memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
1189 memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
1190 memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
1191
1192 memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
1193 memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
1194 memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
1195
1196 if (!prefetch) {
1197 memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0];
1198 memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1];
1199 memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2];
1200
1201 memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = memory->waitstatesSeq32[REGION_CART0];
1202 memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = memory->waitstatesSeq32[REGION_CART1];
1203 memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = memory->waitstatesSeq32[REGION_CART2];
1204
1205 memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0];
1206 memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1];
1207 memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2];
1208
1209 memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq32[REGION_CART0];
1210 memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq32[REGION_CART1];
1211 memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq32[REGION_CART2];
1212 } else {
1213 memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = 0;
1214 memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = 0;
1215 memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = 0;
1216
1217 memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = 0;
1218 memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = 0;
1219 memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = 0;
1220
1221 memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = 0;
1222 memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = 0;
1223 memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = 0;
1224
1225 memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = 0;
1226 memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = 0;
1227 memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = 0;
1228 }
1229
1230 cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
1231 cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
1232
1233 cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
1234 cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
1235
1236 cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
1237 cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
1238}
1239
1240void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
1241 struct GBAMemory* memory = &gba->memory;
1242 memory->dma[dma].source = address & 0x0FFFFFFE;
1243}
1244
1245void GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
1246 struct GBAMemory* memory = &gba->memory;
1247 memory->dma[dma].dest = address & 0x0FFFFFFE;
1248}
1249
1250void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
1251 struct GBAMemory* memory = &gba->memory;
1252 memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
1253}
1254
1255uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
1256 struct GBAMemory* memory = &gba->memory;
1257 struct GBADMA* currentDma = &memory->dma[dma];
1258 int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
1259 currentDma->reg = control;
1260
1261 if (GBADMARegisterIsDRQ(currentDma->reg)) {
1262 GBALog(gba, GBA_LOG_STUB, "DRQ not implemented");
1263 }
1264
1265 if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
1266 currentDma->nextSource = currentDma->source;
1267 currentDma->nextDest = currentDma->dest;
1268 currentDma->nextCount = currentDma->count;
1269 GBAMemoryScheduleDMA(gba, dma, currentDma);
1270 }
1271 // If the DMA has already occurred, this value might have changed since the function started
1272 return currentDma->reg;
1273};
1274
1275void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
1276 struct ARMCore* cpu = gba->cpu;
1277 switch (GBADMARegisterGetTiming(info->reg)) {
1278 case DMA_TIMING_NOW:
1279 info->nextEvent = cpu->cycles;
1280 GBAMemoryUpdateDMAs(gba, 0);
1281 break;
1282 case DMA_TIMING_HBLANK:
1283 // Handled implicitly
1284 info->nextEvent = INT_MAX;
1285 break;
1286 case DMA_TIMING_VBLANK:
1287 // Handled implicitly
1288 info->nextEvent = INT_MAX;
1289 break;
1290 case DMA_TIMING_CUSTOM:
1291 info->nextEvent = INT_MAX;
1292 switch (number) {
1293 case 0:
1294 GBALog(gba, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
1295 break;
1296 case 1:
1297 case 2:
1298 GBAAudioScheduleFifoDma(&gba->audio, number, info);
1299 break;
1300 case 3:
1301 // GBAVideoScheduleVCaptureDma(dma, info);
1302 break;
1303 }
1304 }
1305}
1306
1307void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
1308 struct GBAMemory* memory = &gba->memory;
1309 struct GBADMA* dma;
1310 int i;
1311 for (i = 0; i < 4; ++i) {
1312 dma = &memory->dma[i];
1313 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK) {
1314 dma->nextEvent = cycles;
1315 }
1316 }
1317 GBAMemoryUpdateDMAs(gba, 0);
1318}
1319
1320void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
1321 struct GBAMemory* memory = &gba->memory;
1322 struct GBADMA* dma;
1323 int i;
1324 for (i = 0; i < 4; ++i) {
1325 dma = &memory->dma[i];
1326 if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK) {
1327 dma->nextEvent = cycles;
1328 }
1329 }
1330 GBAMemoryUpdateDMAs(gba, 0);
1331}
1332
1333int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
1334 struct GBAMemory* memory = &gba->memory;
1335 if (memory->nextDMA == INT_MAX) {
1336 return INT_MAX;
1337 }
1338 memory->nextDMA -= cycles;
1339 memory->eventDiff += cycles;
1340 if (memory->nextDMA <= 0) {
1341 struct GBADMA* dma = &memory->dma[memory->activeDMA];
1342 GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
1343 GBAMemoryUpdateDMAs(gba, memory->eventDiff);
1344 memory->eventDiff = 0;
1345 }
1346 return memory->nextDMA;
1347}
1348
1349void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
1350 int i;
1351 struct GBAMemory* memory = &gba->memory;
1352 struct ARMCore* cpu = gba->cpu;
1353 memory->activeDMA = -1;
1354 memory->nextDMA = INT_MAX;
1355 for (i = 3; i >= 0; --i) {
1356 struct GBADMA* dma = &memory->dma[i];
1357 if (dma->nextEvent != INT_MAX) {
1358 dma->nextEvent -= cycles;
1359 if (GBADMARegisterIsEnable(dma->reg)) {
1360 memory->activeDMA = i;
1361 memory->nextDMA = dma->nextEvent;
1362 }
1363 }
1364 }
1365 if (memory->nextDMA < cpu->nextEvent) {
1366 cpu->nextEvent = memory->nextDMA;
1367 }
1368}
1369
1370void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
1371 struct GBAMemory* memory = &gba->memory;
1372 struct ARMCore* cpu = gba->cpu;
1373 uint32_t width = GBADMARegisterGetWidth(info->reg) ? 4 : 2;
1374 int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
1375 int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width;
1376 int32_t wordsRemaining = info->nextCount;
1377 uint32_t source = info->nextSource;
1378 uint32_t dest = info->nextDest;
1379 uint32_t sourceRegion = source >> BASE_OFFSET;
1380 uint32_t destRegion = dest >> BASE_OFFSET;
1381 int32_t cycles = 2;
1382
1383 if (source == info->source) {
1384 // TODO: support 4 cycles for ROM access
1385 cycles += 2;
1386 if (width == 4) {
1387 cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
1388 source &= 0xFFFFFFFC;
1389 dest &= 0xFFFFFFFC;
1390 } else {
1391 cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
1392 }
1393 } else {
1394 if (width == 4) {
1395 cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
1396 } else {
1397 cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
1398 }
1399 }
1400
1401 gba->performingDMA = true;
1402 int32_t word;
1403 if (width == 4) {
1404 word = cpu->memory.load32(cpu, source, 0);
1405 gba->bus = word;
1406 cpu->memory.store32(cpu, dest, word, 0);
1407 source += sourceOffset;
1408 dest += destOffset;
1409 --wordsRemaining;
1410 } else {
1411 if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
1412 word = GBASavedataReadEEPROM(&memory->savedata);
1413 gba->bus = word | (word << 16);
1414 cpu->memory.store16(cpu, dest, word, 0);
1415 source += sourceOffset;
1416 dest += destOffset;
1417 --wordsRemaining;
1418 } else if (destRegion == REGION_CART2_EX) {
1419 if (memory->savedata.type == SAVEDATA_AUTODETECT) {
1420 GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
1421 GBASavedataInitEEPROM(&memory->savedata);
1422 }
1423 word = cpu->memory.load16(cpu, source, 0);
1424 gba->bus = word | (word << 16);
1425 GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
1426 source += sourceOffset;
1427 dest += destOffset;
1428 --wordsRemaining;
1429 } else {
1430 word = cpu->memory.load16(cpu, source, 0);
1431 gba->bus = word | (word << 16);
1432 cpu->memory.store16(cpu, dest, word, 0);
1433 source += sourceOffset;
1434 dest += destOffset;
1435 --wordsRemaining;
1436 }
1437 }
1438 gba->performingDMA = false;
1439
1440 if (!wordsRemaining) {
1441 if (!GBADMARegisterIsRepeat(info->reg) || GBADMARegisterGetTiming(info->reg) == DMA_TIMING_NOW) {
1442 info->reg = GBADMARegisterClearEnable(info->reg);
1443 info->nextEvent = INT_MAX;
1444
1445 // Clear the enable bit in memory
1446 memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
1447 } else {
1448 info->nextCount = info->count;
1449 if (GBADMARegisterGetDestControl(info->reg) == DMA_INCREMENT_RELOAD) {
1450 info->nextDest = info->dest;
1451 }
1452 GBAMemoryScheduleDMA(gba, number, info);
1453 }
1454 if (GBADMARegisterIsDoIRQ(info->reg)) {
1455 GBARaiseIRQ(gba, IRQ_DMA0 + number);
1456 }
1457 } else {
1458 info->nextDest = dest;
1459 info->nextCount = wordsRemaining;
1460 }
1461 info->nextSource = source;
1462
1463 if (info->nextEvent != INT_MAX) {
1464 info->nextEvent += cycles;
1465 }
1466 cpu->cycles += cycles;
1467}
1468
1469void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state) {
1470 memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1471 memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1472}
1473
1474void GBAMemoryDeserialize(struct GBAMemory* memory, const struct GBASerializedState* state) {
1475 memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1476 memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1477}
1478
1479uint32_t _popcount32(unsigned bits) {
1480 bits = bits - ((bits >> 1) & 0x55555555);
1481 bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
1482 return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
1483}