src/gba/io.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 <mgba/internal/gba/io.h>
7
8#include <mgba/internal/arm/macros.h>
9#include <mgba/internal/gba/dma.h>
10#include <mgba/internal/gba/gba.h>
11#include <mgba/internal/gba/rr/rr.h>
12#include <mgba/internal/gba/serialize.h>
13
14mLOG_DEFINE_CATEGORY(GBA_IO, "GBA I/O", "gba.io");
15
16const char* const GBAIORegisterNames[] = {
17 // Video
18 "DISPCNT",
19 0,
20 "DISPSTAT",
21 "VCOUNT",
22 "BG0CNT",
23 "BG1CNT",
24 "BG2CNT",
25 "BG3CNT",
26 "BG0HOFS",
27 "BG0VOFS",
28 "BG1HOFS",
29 "BG1VOFS",
30 "BG2HOFS",
31 "BG2VOFS",
32 "BG3HOFS",
33 "BG3VOFS",
34 "BG2PA",
35 "BG2PB",
36 "BG2PC",
37 "BG2PD",
38 "BG2X_LO",
39 "BG2X_HI",
40 "BG2Y_LO",
41 "BG2Y_HI",
42 "BG3PA",
43 "BG3PB",
44 "BG3PC",
45 "BG3PD",
46 "BG3X_LO",
47 "BG3X_HI",
48 "BG3Y_LO",
49 "BG3Y_HI",
50 "WIN0H",
51 "WIN1H",
52 "WIN0V",
53 "WIN1V",
54 "WININ",
55 "WINOUT",
56 "MOSAIC",
57 0,
58 "BLDCNT",
59 "BLDALPHA",
60 "BLDY",
61 0,
62 0,
63 0,
64 0,
65 0,
66
67 // Sound
68 "SOUND1CNT_LO",
69 "SOUND1CNT_HI",
70 "SOUND1CNT_X",
71 0,
72 "SOUND2CNT_LO",
73 0,
74 "SOUND2CNT_HI",
75 0,
76 "SOUND3CNT_LO",
77 "SOUND3CNT_HI",
78 "SOUND3CNT_X",
79 0,
80 "SOUND4CNT_LO",
81 0,
82 "SOUND4CNT_HI",
83 0,
84 "SOUNDCNT_LO",
85 "SOUNDCNT_HI",
86 "SOUNDCNT_X",
87 0,
88 "SOUNDBIAS",
89 0,
90 0,
91 0,
92 "WAVE_RAM0_LO",
93 "WAVE_RAM0_HI",
94 "WAVE_RAM1_LO",
95 "WAVE_RAM1_HI",
96 "WAVE_RAM2_LO",
97 "WAVE_RAM2_HI",
98 "WAVE_RAM3_LO",
99 "WAVE_RAM3_HI",
100 "FIFO_A_LO",
101 "FIFO_A_HI",
102 "FIFO_B_LO",
103 "FIFO_B_HI",
104 0,
105 0,
106 0,
107 0,
108
109 // DMA
110 "DMA0SAD_LO",
111 "DMA0SAD_HI",
112 "DMA0DAD_LO",
113 "DMA0DAD_HI",
114 "DMA0CNT_LO",
115 "DMA0CNT_HI",
116 "DMA1SAD_LO",
117 "DMA1SAD_HI",
118 "DMA1DAD_LO",
119 "DMA1DAD_HI",
120 "DMA1CNT_LO",
121 "DMA1CNT_HI",
122 "DMA2SAD_LO",
123 "DMA2SAD_HI",
124 "DMA2DAD_LO",
125 "DMA2DAD_HI",
126 "DMA2CNT_LO",
127 "DMA2CNT_HI",
128 "DMA3SAD_LO",
129 "DMA3SAD_HI",
130 "DMA3DAD_LO",
131 "DMA3DAD_HI",
132 "DMA3CNT_LO",
133 "DMA3CNT_HI",
134
135 0, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0,
137
138 // Timers
139 "TM0CNT_LO",
140 "TM0CNT_HI",
141 "TM1CNT_LO",
142 "TM1CNT_HI",
143 "TM2CNT_LO",
144 "TM2CNT_HI",
145 "TM3CNT_LO",
146 "TM3CNT_HI",
147
148 0, 0, 0, 0, 0, 0, 0, 0,
149
150 // SIO
151 "SIOMULTI0",
152 "SIOMULTI1",
153 "SIOMULTI2",
154 "SIOMULTI3",
155 "SIOCNT",
156 "SIOMLT_SEND",
157 0,
158 0,
159 "KEYINPUT",
160 "KEYCNT",
161 "RCNT",
162 0,
163 0,
164 0,
165 0,
166 0,
167 "JOYCNT",
168 0,
169 0,
170 0,
171 0,
172 0,
173 0,
174 0,
175 "JOY_RECV_LO",
176 "JOY_RECV_HI",
177 "JOY_TRANS_LO",
178 "JOY_TRANS_HI",
179 "JOYSTAT",
180 0,
181 0,
182 0,
183
184 0, 0, 0, 0, 0, 0, 0, 0,
185 0, 0, 0, 0, 0, 0, 0, 0,
186 0, 0, 0, 0, 0, 0, 0, 0,
187 0, 0, 0, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0, 0,
190 0, 0, 0, 0, 0, 0, 0, 0,
191 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0, 0, 0, 0,
194
195 // Interrupts, etc
196 "IE",
197 "IF",
198 "WAITCNT",
199 0,
200 "IME"
201};
202
203static const int _isValidRegister[REG_MAX >> 1] = {
204 // Video
205 1, 0, 1, 1, 1, 1, 1, 1,
206 1, 1, 1, 1, 1, 1, 1, 1,
207 1, 1, 1, 1, 1, 1, 1, 1,
208 1, 1, 1, 1, 1, 1, 1, 1,
209 1, 1, 1, 1, 1, 1, 1, 0,
210 1, 1, 1, 0, 0, 0, 0, 0,
211 // Audio
212 1, 1, 1, 0, 1, 0, 1, 0,
213 1, 1, 1, 0, 1, 0, 1, 0,
214 1, 1, 1, 0, 1, 0, 0, 0,
215 1, 1, 1, 1, 1, 1, 1, 1,
216 1, 1, 1, 1, 0, 0, 0, 0,
217 // DMA
218 1, 1, 1, 1, 1, 1, 1, 1,
219 1, 1, 1, 1, 1, 1, 1, 1,
220 1, 1, 1, 1, 1, 1, 1, 1,
221 0, 0, 0, 0, 0, 0, 0, 0,
222 0, 0, 0, 0, 0, 0, 0, 0,
223 // Timers
224 1, 1, 1, 1, 1, 1, 1, 1,
225 0, 0, 0, 0, 0, 0, 0, 0,
226 // SIO
227 1, 1, 1, 1, 1, 0, 0, 0,
228 1, 1, 1, 0, 0, 0, 0, 0,
229 1, 0, 0, 0, 0, 0, 0, 0,
230 1, 0, 1, 0, 1, 0, 0, 0,
231 0, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0,
234 0, 0, 0, 0, 0, 0, 0, 0,
235 0, 0, 0, 0, 0, 0, 0, 0,
236 0, 0, 0, 0, 0, 0, 0, 0,
237 0, 0, 0, 0, 0, 0, 0, 0,
238 0, 0, 0, 0, 0, 0, 0, 0,
239 0, 0, 0, 0, 0, 0, 0, 0,
240 0, 0, 0, 0, 0, 0, 0, 0,
241 // Interrupts
242 1, 1, 1, 0, 1
243};
244
245static const int _isRSpecialRegister[REG_MAX >> 1] = {
246 // Video
247 0, 0, 1, 1, 0, 0, 0, 0,
248 1, 1, 1, 1, 1, 1, 1, 1,
249 1, 1, 1, 1, 1, 1, 1, 1,
250 1, 1, 1, 1, 1, 1, 1, 1,
251 1, 1, 1, 1, 1, 1, 1, 1,
252 1, 1, 1, 1, 1, 1, 1, 1,
253 // Audio
254 0, 0, 1, 0, 0, 0, 1, 0,
255 0, 0, 1, 0, 0, 0, 1, 0,
256 0, 0, 0, 0, 1, 0, 0, 0,
257 1, 1, 1, 1, 1, 1, 1, 1,
258 1, 1, 1, 1, 0, 0, 0, 0,
259 // DMA
260 1, 1, 1, 1, 1, 1, 1, 1,
261 1, 1, 1, 1, 1, 1, 1, 1,
262 1, 1, 1, 1, 1, 1, 1, 1,
263 0, 0, 0, 0, 0, 0, 0, 0,
264 0, 0, 0, 0, 0, 0, 0, 0,
265 // Timers
266 1, 1, 1, 1, 1, 1, 1, 1,
267 0, 0, 0, 0, 0, 0, 0, 0,
268 // SIO
269 1, 1, 1, 1, 1, 0, 0, 0,
270 1, 1, 1, 0, 0, 0, 0, 0,
271 1, 0, 0, 0, 0, 0, 0, 0,
272 1, 0, 1, 0, 1, 0, 0, 0,
273 0, 0, 0, 0, 0, 0, 0, 0,
274 0, 0, 0, 0, 0, 0, 0, 0,
275 0, 0, 0, 0, 0, 0, 0, 0,
276 0, 0, 0, 0, 0, 0, 0, 0,
277 0, 0, 0, 0, 0, 0, 0, 0,
278 0, 0, 0, 0, 0, 0, 0, 0,
279 0, 0, 0, 0, 0, 0, 0, 0,
280 0, 0, 0, 0, 0, 0, 0, 0,
281 0, 0, 0, 0, 0, 0, 0, 0,
282 0, 0, 0, 0, 0, 0, 0, 0,
283 // Interrupts
284};
285
286static const int _isWSpecialRegister[REG_MAX >> 1] = {
287 // Video
288 0, 0, 1, 1, 0, 0, 0, 0,
289 0, 0, 0, 0, 0, 0, 0, 0,
290 0, 0, 0, 0, 0, 0, 0, 0,
291 0, 0, 0, 0, 0, 0, 0, 0,
292 0, 0, 0, 0, 0, 0, 0, 0,
293 0, 0, 0, 0, 0, 0, 0, 0,
294 // Audio
295 1, 1, 1, 0, 1, 0, 1, 0,
296 1, 1, 1, 0, 1, 0, 1, 0,
297 1, 0, 1, 0, 0, 0, 0, 0,
298 1, 1, 1, 1, 1, 1, 1, 1,
299 1, 1, 1, 1, 0, 0, 0, 0,
300 // DMA
301 0, 0, 0, 0, 0, 1, 0, 0,
302 0, 0, 0, 1, 0, 0, 0, 0,
303 0, 1, 0, 0, 0, 0, 0, 1,
304 0, 0, 0, 0, 0, 0, 0, 0,
305 0, 0, 0, 0, 0, 0, 0, 0,
306 // Timers
307 1, 1, 1, 1, 1, 1, 1, 1,
308 0, 0, 0, 0, 0, 0, 0, 0,
309 // SIO
310 1, 1, 1, 1, 1, 0, 0, 0,
311 1, 1, 1, 0, 0, 0, 0, 0,
312 1, 0, 0, 0, 0, 0, 0, 0,
313 1, 0, 1, 0, 1, 0, 0, 0,
314 0, 0, 0, 0, 0, 0, 0, 0,
315 0, 0, 0, 0, 0, 0, 0, 0,
316 0, 0, 0, 0, 0, 0, 0, 0,
317 0, 0, 0, 0, 0, 0, 0, 0,
318 0, 0, 0, 0, 0, 0, 0, 0,
319 0, 0, 0, 0, 0, 0, 0, 0,
320 0, 0, 0, 0, 0, 0, 0, 0,
321 0, 0, 0, 0, 0, 0, 0, 0,
322 0, 0, 0, 0, 0, 0, 0, 0,
323 0, 0, 0, 0, 0, 0, 0, 0,
324 // Interrupts
325 1, 1, 0, 0, 1
326};
327
328void GBAIOInit(struct GBA* gba) {
329 gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
330 gba->memory.io[REG_RCNT >> 1] = RCNT_INITIAL;
331 gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
332 gba->memory.io[REG_SOUNDBIAS >> 1] = 0x200;
333 gba->memory.io[REG_BG2PA >> 1] = 0x100;
334 gba->memory.io[REG_BG2PD >> 1] = 0x100;
335 gba->memory.io[REG_BG3PA >> 1] = 0x100;
336 gba->memory.io[REG_BG3PD >> 1] = 0x100;
337
338 if (!gba->biosVf) {
339 gba->memory.io[REG_VCOUNT >> 1] = 0x7E;
340 gba->memory.io[REG_POSTFLG >> 1] = 1;
341 }
342}
343
344void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
345 if (address < REG_SOUND1CNT_LO && (address > REG_VCOUNT || address == REG_DISPCNT)) {
346 value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
347 } else {
348 switch (address) {
349 // Video
350 case REG_DISPSTAT:
351 value &= 0xFFF8;
352 GBAVideoWriteDISPSTAT(&gba->video, value);
353 return;
354
355 case REG_VCOUNT:
356 mLOG(GBA_IO, GAME_ERROR, "Write to read-only I/O register: %03X", address);
357 return;
358
359 // Audio
360 case REG_SOUND1CNT_LO:
361 GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
362 value &= 0x007F;
363 break;
364 case REG_SOUND1CNT_HI:
365 GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
366 break;
367 case REG_SOUND1CNT_X:
368 GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
369 value &= 0x47FF;
370 break;
371 case REG_SOUND2CNT_LO:
372 GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
373 break;
374 case REG_SOUND2CNT_HI:
375 GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
376 value &= 0x47FF;
377 break;
378 case REG_SOUND3CNT_LO:
379 GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
380 value &= 0x00E0;
381 break;
382 case REG_SOUND3CNT_HI:
383 GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
384 value &= 0xE03F;
385 break;
386 case REG_SOUND3CNT_X:
387 GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
388 // TODO: The low bits need to not be readable, but still 8-bit writable
389 value &= 0x47FF;
390 break;
391 case REG_SOUND4CNT_LO:
392 GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
393 value &= 0xFF3F;
394 break;
395 case REG_SOUND4CNT_HI:
396 GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
397 value &= 0x40FF;
398 break;
399 case REG_SOUNDCNT_LO:
400 GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
401 value &= 0xFF77;
402 break;
403 case REG_SOUNDCNT_HI:
404 GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
405 value &= 0x770F;
406 break;
407 case REG_SOUNDCNT_X:
408 GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
409 value &= 0x0080;
410 value |= gba->memory.io[REG_SOUNDCNT_X >> 1] & 0xF;
411 break;
412 case REG_SOUNDBIAS:
413 GBAAudioWriteSOUNDBIAS(&gba->audio, value);
414 break;
415
416 case REG_WAVE_RAM0_LO:
417 case REG_WAVE_RAM1_LO:
418 case REG_WAVE_RAM2_LO:
419 case REG_WAVE_RAM3_LO:
420 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
421 break;
422
423 case REG_WAVE_RAM0_HI:
424 case REG_WAVE_RAM1_HI:
425 case REG_WAVE_RAM2_HI:
426 case REG_WAVE_RAM3_HI:
427 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
428 break;
429
430 case REG_FIFO_A_LO:
431 case REG_FIFO_B_LO:
432 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
433 break;
434
435 case REG_FIFO_A_HI:
436 case REG_FIFO_B_HI:
437 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
438 break;
439
440 // DMA
441 case REG_DMA0SAD_LO:
442 case REG_DMA0DAD_LO:
443 case REG_DMA1SAD_LO:
444 case REG_DMA1DAD_LO:
445 case REG_DMA2SAD_LO:
446 case REG_DMA2DAD_LO:
447 case REG_DMA3SAD_LO:
448 case REG_DMA3DAD_LO:
449 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
450 break;
451
452 case REG_DMA0SAD_HI:
453 case REG_DMA0DAD_HI:
454 case REG_DMA1SAD_HI:
455 case REG_DMA1DAD_HI:
456 case REG_DMA2SAD_HI:
457 case REG_DMA2DAD_HI:
458 case REG_DMA3SAD_HI:
459 case REG_DMA3DAD_HI:
460 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
461 break;
462
463 case REG_DMA0CNT_LO:
464 GBADMAWriteCNT_LO(gba, 0, value);
465 break;
466 case REG_DMA0CNT_HI:
467 value = GBADMAWriteCNT_HI(gba, 0, value);
468 break;
469 case REG_DMA1CNT_LO:
470 GBADMAWriteCNT_LO(gba, 1, value);
471 break;
472 case REG_DMA1CNT_HI:
473 value = GBADMAWriteCNT_HI(gba, 1, value);
474 break;
475 case REG_DMA2CNT_LO:
476 GBADMAWriteCNT_LO(gba, 2, value);
477 break;
478 case REG_DMA2CNT_HI:
479 value = GBADMAWriteCNT_HI(gba, 2, value);
480 break;
481 case REG_DMA3CNT_LO:
482 GBADMAWriteCNT_LO(gba, 3, value);
483 break;
484 case REG_DMA3CNT_HI:
485 value = GBADMAWriteCNT_HI(gba, 3, value);
486 break;
487
488 // Timers
489 case REG_TM0CNT_LO:
490 GBATimerWriteTMCNT_LO(&gba->timers[0], value);
491 return;
492 case REG_TM1CNT_LO:
493 GBATimerWriteTMCNT_LO(&gba->timers[1], value);
494 return;
495 case REG_TM2CNT_LO:
496 GBATimerWriteTMCNT_LO(&gba->timers[2], value);
497 return;
498 case REG_TM3CNT_LO:
499 GBATimerWriteTMCNT_LO(&gba->timers[3], value);
500 return;
501
502 case REG_TM0CNT_HI:
503 value &= 0x00C7;
504 GBATimerUpdateRegister(gba, 0);
505 GBATimerWriteTMCNT_HI(&gba->timers[0], &gba->timing, gba->cpu, &gba->memory.io[REG_TM0CNT_LO >> 1], value);
506 break;
507 case REG_TM1CNT_HI:
508 value &= 0x00C7;
509 GBATimerUpdateRegister(gba, 1);
510 GBATimerWriteTMCNT_HI(&gba->timers[1], &gba->timing, gba->cpu, &gba->memory.io[REG_TM1CNT_LO >> 1], value);
511 break;
512 case REG_TM2CNT_HI:
513 value &= 0x00C7;
514 GBATimerUpdateRegister(gba, 2);
515 GBATimerWriteTMCNT_HI(&gba->timers[2], &gba->timing, gba->cpu, &gba->memory.io[REG_TM2CNT_LO >> 1], value);
516 break;
517 case REG_TM3CNT_HI:
518 value &= 0x00C7;
519 GBATimerUpdateRegister(gba, 3);
520 GBATimerWriteTMCNT_HI(&gba->timers[3], &gba->timing, gba->cpu, &gba->memory.io[REG_TM3CNT_LO >> 1], value);
521 break;
522
523 // SIO
524 case REG_SIOCNT:
525 GBASIOWriteSIOCNT(&gba->sio, value);
526 break;
527 case REG_RCNT:
528 value &= 0xC1FF;
529 GBASIOWriteRCNT(&gba->sio, value);
530 break;
531 case REG_JOY_TRANS_LO:
532 case REG_JOY_TRANS_HI:
533 gba->memory.io[REG_JOYSTAT >> 1] |= JOYSTAT_TRANS_BIT;
534 // Fall through
535 case REG_SIOMLT_SEND:
536 case REG_JOYCNT:
537 case REG_JOYSTAT:
538 case REG_JOY_RECV_LO:
539 case REG_JOY_RECV_HI:
540 value = GBASIOWriteRegister(&gba->sio, address, value);
541 break;
542
543 // Interrupts and misc
544 case REG_WAITCNT:
545 value &= 0x5FFF;
546 GBAAdjustWaitstates(gba, value);
547 break;
548 case REG_IE:
549 GBAWriteIE(gba, value);
550 break;
551 case REG_IF:
552 gba->springIRQ &= ~value;
553 value = gba->memory.io[REG_IF >> 1] & ~value;
554 break;
555 case REG_IME:
556 GBAWriteIME(gba, value);
557 break;
558 case REG_MAX:
559 // Some bad interrupt libraries will write to this
560 break;
561 case REG_DEBUG_ENABLE:
562 gba->debug = value == 0xC0DE;
563 return;
564 case REG_DEBUG_FLAGS:
565 if (gba->debug) {
566 GBADebug(gba, value);
567 return;
568 }
569 // Fall through
570 default:
571 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
572 STORE_16LE(value, address - REG_DEBUG_STRING, gba->debugString);
573 return;
574 }
575 mLOG(GBA_IO, STUB, "Stub I/O register write: %03X", address);
576 if (address >= REG_MAX) {
577 mLOG(GBA_IO, GAME_ERROR, "Write to unused I/O register: %03X", address);
578 return;
579 }
580 break;
581 }
582 }
583 gba->memory.io[address >> 1] = value;
584}
585
586void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
587 if (address == REG_HALTCNT) {
588 value &= 0x80;
589 if (!value) {
590 GBAHalt(gba);
591 } else {
592 GBAStop(gba);
593 }
594 return;
595 }
596 if (address == REG_POSTFLG) {
597 gba->memory.io[(address & (SIZE_IO - 1)) >> 1] = value;
598 return;
599 }
600 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
601 gba->debugString[address - REG_DEBUG_STRING] = value;
602 return;
603 }
604 if (address > SIZE_IO) {
605 return;
606 }
607 uint16_t value16 = value << (8 * (address & 1));
608 value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
609 GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
610}
611
612void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
613 switch (address) {
614 case REG_WAVE_RAM0_LO:
615 GBAAudioWriteWaveRAM(&gba->audio, 0, value);
616 break;
617 case REG_WAVE_RAM1_LO:
618 GBAAudioWriteWaveRAM(&gba->audio, 1, value);
619 break;
620 case REG_WAVE_RAM2_LO:
621 GBAAudioWriteWaveRAM(&gba->audio, 2, value);
622 break;
623 case REG_WAVE_RAM3_LO:
624 GBAAudioWriteWaveRAM(&gba->audio, 3, value);
625 break;
626 case REG_FIFO_A_LO:
627 case REG_FIFO_B_LO:
628 GBAAudioWriteFIFO(&gba->audio, address, value);
629 break;
630 case REG_DMA0SAD_LO:
631 value = GBADMAWriteSAD(gba, 0, value);
632 break;
633 case REG_DMA0DAD_LO:
634 value = GBADMAWriteDAD(gba, 0, value);
635 break;
636 case REG_DMA1SAD_LO:
637 value = GBADMAWriteSAD(gba, 1, value);
638 break;
639 case REG_DMA1DAD_LO:
640 value = GBADMAWriteDAD(gba, 1, value);
641 break;
642 case REG_DMA2SAD_LO:
643 value = GBADMAWriteSAD(gba, 2, value);
644 break;
645 case REG_DMA2DAD_LO:
646 value = GBADMAWriteDAD(gba, 2, value);
647 break;
648 case REG_DMA3SAD_LO:
649 value = GBADMAWriteSAD(gba, 3, value);
650 break;
651 case REG_DMA3DAD_LO:
652 value = GBADMAWriteDAD(gba, 3, value);
653 break;
654 default:
655 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
656 STORE_32LE(value, address - REG_DEBUG_STRING, gba->debugString);
657 return;
658 }
659 GBAIOWrite(gba, address, value & 0xFFFF);
660 GBAIOWrite(gba, address | 2, value >> 16);
661 return;
662 }
663 gba->memory.io[address >> 1] = value;
664 gba->memory.io[(address >> 1) + 1] = value >> 16;
665}
666
667bool GBAIOIsReadConstant(uint32_t address) {
668 switch (address) {
669 default:
670 return false;
671 case REG_BG0CNT:
672 case REG_BG1CNT:
673 case REG_BG2CNT:
674 case REG_BG3CNT:
675 case REG_WININ:
676 case REG_WINOUT:
677 case REG_BLDCNT:
678 case REG_BLDALPHA:
679 case REG_SOUND1CNT_LO:
680 case REG_SOUND1CNT_HI:
681 case REG_SOUND1CNT_X:
682 case REG_SOUND2CNT_LO:
683 case REG_SOUND2CNT_HI:
684 case REG_SOUND3CNT_LO:
685 case REG_SOUND3CNT_HI:
686 case REG_SOUND3CNT_X:
687 case REG_SOUND4CNT_LO:
688 case REG_SOUND4CNT_HI:
689 case REG_SOUNDCNT_LO:
690 case REG_SOUNDCNT_HI:
691 case REG_TM0CNT_HI:
692 case REG_TM1CNT_HI:
693 case REG_TM2CNT_HI:
694 case REG_TM3CNT_HI:
695 case REG_KEYINPUT:
696 case REG_IE:
697 return true;
698 }
699}
700
701uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
702 if (!GBAIOIsReadConstant(address)) {
703 // Most IO reads need to disable idle removal
704 gba->haltPending = false;
705 }
706
707 switch (address) {
708 case REG_TM0CNT_LO:
709 GBATimerUpdateRegister(gba, 0);
710 break;
711 case REG_TM1CNT_LO:
712 GBATimerUpdateRegister(gba, 1);
713 break;
714 case REG_TM2CNT_LO:
715 GBATimerUpdateRegister(gba, 2);
716 break;
717 case REG_TM3CNT_LO:
718 GBATimerUpdateRegister(gba, 3);
719 break;
720
721 case REG_KEYINPUT:
722 if (gba->rr && gba->rr->isPlaying(gba->rr)) {
723 return 0x3FF ^ gba->rr->queryInput(gba->rr);
724 } else {
725 uint16_t input = 0x3FF;
726 if (gba->keyCallback) {
727 input = gba->keyCallback->readKeys(gba->keyCallback);
728 } else if (gba->keySource) {
729 input = *gba->keySource;
730 }
731 if (!gba->allowOpposingDirections) {
732 unsigned rl = input & 0x030;
733 unsigned ud = input & 0x0C0;
734 input &= 0x30F;
735 if (rl != 0x030) {
736 input |= rl;
737 }
738 if (ud != 0x0C0) {
739 input |= ud;
740 }
741 }
742 if (gba->rr && gba->rr->isRecording(gba->rr)) {
743 gba->rr->logInput(gba->rr, input);
744 }
745 return 0x3FF ^ input;
746 }
747
748 case REG_SIOCNT:
749 return gba->sio.siocnt;
750 case REG_RCNT:
751 return gba->sio.rcnt;
752
753 case REG_BG0HOFS:
754 case REG_BG0VOFS:
755 case REG_BG1HOFS:
756 case REG_BG1VOFS:
757 case REG_BG2HOFS:
758 case REG_BG2VOFS:
759 case REG_BG3HOFS:
760 case REG_BG3VOFS:
761 case REG_BG2PA:
762 case REG_BG2PB:
763 case REG_BG2PC:
764 case REG_BG2PD:
765 case REG_BG2X_LO:
766 case REG_BG2X_HI:
767 case REG_BG2Y_LO:
768 case REG_BG2Y_HI:
769 case REG_BG3PA:
770 case REG_BG3PB:
771 case REG_BG3PC:
772 case REG_BG3PD:
773 case REG_BG3X_LO:
774 case REG_BG3X_HI:
775 case REG_BG3Y_LO:
776 case REG_BG3Y_HI:
777 case REG_WIN0H:
778 case REG_WIN1H:
779 case REG_WIN0V:
780 case REG_WIN1V:
781 case REG_MOSAIC:
782 case REG_BLDY:
783 case REG_FIFO_A_LO:
784 case REG_FIFO_A_HI:
785 case REG_FIFO_B_LO:
786 case REG_FIFO_B_HI:
787 case REG_DMA0SAD_LO:
788 case REG_DMA0SAD_HI:
789 case REG_DMA0DAD_LO:
790 case REG_DMA0DAD_HI:
791 case REG_DMA1SAD_LO:
792 case REG_DMA1SAD_HI:
793 case REG_DMA1DAD_LO:
794 case REG_DMA1DAD_HI:
795 case REG_DMA2SAD_LO:
796 case REG_DMA2SAD_HI:
797 case REG_DMA2DAD_LO:
798 case REG_DMA2DAD_HI:
799 case REG_DMA3SAD_LO:
800 case REG_DMA3SAD_HI:
801 case REG_DMA3DAD_LO:
802 case REG_DMA3DAD_HI:
803 // Write-only register
804 mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
805 return GBALoadBad(gba->cpu);
806
807 case REG_DMA0CNT_LO:
808 case REG_DMA1CNT_LO:
809 case REG_DMA2CNT_LO:
810 case REG_DMA3CNT_LO:
811 // Write-only register
812 mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
813 return 0;
814
815 case REG_JOY_RECV_LO:
816 case REG_JOY_RECV_HI:
817 gba->memory.io[REG_JOYSTAT >> 1] &= ~JOYSTAT_RECV_BIT;
818 break;
819
820 case REG_SOUNDBIAS:
821 case REG_KEYCNT:
822 case REG_POSTFLG:
823 mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address);
824 break;
825 case REG_SOUND1CNT_LO:
826 case REG_SOUND1CNT_HI:
827 case REG_SOUND1CNT_X:
828 case REG_SOUND2CNT_LO:
829 case REG_SOUND2CNT_HI:
830 case REG_SOUND3CNT_LO:
831 case REG_SOUND3CNT_HI:
832 case REG_SOUND3CNT_X:
833 case REG_SOUND4CNT_LO:
834 case REG_SOUND4CNT_HI:
835 case REG_SOUNDCNT_LO:
836 case REG_SOUNDCNT_HI:
837 if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) {
838 // TODO: Is writing allowed when the circuit is disabled?
839 return 0;
840 }
841 // Fall through
842 case REG_DISPCNT:
843 case REG_DISPSTAT:
844 case REG_VCOUNT:
845 case REG_BG0CNT:
846 case REG_BG1CNT:
847 case REG_BG2CNT:
848 case REG_BG3CNT:
849 case REG_WININ:
850 case REG_WINOUT:
851 case REG_BLDCNT:
852 case REG_BLDALPHA:
853 case REG_SOUNDCNT_X:
854 case REG_WAVE_RAM0_LO:
855 case REG_WAVE_RAM0_HI:
856 case REG_WAVE_RAM1_LO:
857 case REG_WAVE_RAM1_HI:
858 case REG_WAVE_RAM2_LO:
859 case REG_WAVE_RAM2_HI:
860 case REG_WAVE_RAM3_LO:
861 case REG_WAVE_RAM3_HI:
862 case REG_DMA0CNT_HI:
863 case REG_DMA1CNT_HI:
864 case REG_DMA2CNT_HI:
865 case REG_DMA3CNT_HI:
866 case REG_TM0CNT_HI:
867 case REG_TM1CNT_HI:
868 case REG_TM2CNT_HI:
869 case REG_TM3CNT_HI:
870 case REG_SIOMULTI0:
871 case REG_SIOMULTI1:
872 case REG_SIOMULTI2:
873 case REG_SIOMULTI3:
874 case REG_SIOMLT_SEND:
875 case REG_JOYCNT:
876 case REG_JOY_TRANS_LO:
877 case REG_JOY_TRANS_HI:
878 case REG_JOYSTAT:
879 case REG_IE:
880 case REG_IF:
881 case REG_WAITCNT:
882 case REG_IME:
883 // Handled transparently by registers
884 break;
885 case REG_MAX:
886 // Some bad interrupt libraries will read from this
887 break;
888 case 0x66:
889 case 0x6E:
890 case 0x76:
891 case 0x7A:
892 case 0x7E:
893 case 0x86:
894 case 0x8A:
895 mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
896 return 0;
897 case REG_DEBUG_ENABLE:
898 if (gba->debug) {
899 return 0x1DEA;
900 }
901 // Fall through
902 default:
903 mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
904 return GBALoadBad(gba->cpu);
905 }
906 return gba->memory.io[address >> 1];
907}
908
909void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
910 int i;
911 for (i = 0; i < REG_MAX; i += 2) {
912 if (_isRSpecialRegister[i >> 1]) {
913 STORE_16(gba->memory.io[i >> 1], i, state->io);
914 } else if (_isValidRegister[i >> 1]) {
915 uint16_t reg = GBAIORead(gba, i);
916 STORE_16(reg, i, state->io);
917 }
918 }
919
920 for (i = 0; i < 4; ++i) {
921 STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
922 STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
923 STORE_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
924 STORE_32(gba->timers[i].lastEvent - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].lastEvent);
925 STORE_32(gba->timers[i].event.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextEvent);
926 STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
927 STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
928 STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
929 STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
930 STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
931 STORE_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
932 }
933
934 GBAHardwareSerialize(&gba->memory.hw, state);
935}
936
937void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
938 int i;
939 for (i = 0; i < REG_MAX; i += 2) {
940 if (_isWSpecialRegister[i >> 1]) {
941 LOAD_16(gba->memory.io[i >> 1], i, state->io);
942 } else if (_isValidRegister[i >> 1]) {
943 uint16_t reg;
944 LOAD_16(reg, i, state->io);
945 GBAIOWrite(gba, i, reg);
946 }
947 }
948
949 uint32_t when;
950 for (i = 0; i < 4; ++i) {
951 LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
952 LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
953 LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
954 LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
955 if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) {
956 // Overwrite invalid values in savestate
957 gba->timers[i].lastEvent = 0;
958 } else {
959 LOAD_32(when, 0, &state->timers[i].lastEvent);
960 gba->timers[i].lastEvent = when + mTimingCurrentTime(&gba->timing);
961 }
962 LOAD_32(when, 0, &state->timers[i].nextEvent);
963 if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
964 mTimingSchedule(&gba->timing, &gba->timers[i].event, when);
965 }
966
967 LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
968 LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
969 LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
970 LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
971 LOAD_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
972 if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != DMA_TIMING_NOW) {
973 GBADMASchedule(gba, i, &gba->memory.dma[i]);
974 }
975 }
976 GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
977 GBADMAUpdate(gba);
978 GBAHardwareDeserialize(&gba->memory.hw, state);
979}