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