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