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, 0, 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 & 0x3FFF);
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 & 0x3FFF);
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 & 0x3FFF);
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, 0, value);
491 return;
492 case REG_TM1CNT_LO:
493 GBATimerWriteTMCNT_LO(gba, 1, value);
494 return;
495 case REG_TM2CNT_LO:
496 GBATimerWriteTMCNT_LO(gba, 2, value);
497 return;
498 case REG_TM3CNT_LO:
499 GBATimerWriteTMCNT_LO(gba, 3, value);
500 return;
501
502 case REG_TM0CNT_HI:
503 value &= 0x00C7;
504 GBATimerWriteTMCNT_HI(gba, 0, value);
505 break;
506 case REG_TM1CNT_HI:
507 value &= 0x00C7;
508 GBATimerWriteTMCNT_HI(gba, 1, value);
509 break;
510 case REG_TM2CNT_HI:
511 value &= 0x00C7;
512 GBATimerWriteTMCNT_HI(gba, 2, value);
513 break;
514 case REG_TM3CNT_HI:
515 value &= 0x00C7;
516 GBATimerWriteTMCNT_HI(gba, 3, value);
517 break;
518
519 // SIO
520 case REG_SIOCNT:
521 GBASIOWriteSIOCNT(&gba->sio, value);
522 break;
523 case REG_RCNT:
524 value &= 0xC1FF;
525 GBASIOWriteRCNT(&gba->sio, value);
526 break;
527 case REG_JOY_TRANS_LO:
528 case REG_JOY_TRANS_HI:
529 gba->memory.io[REG_JOYSTAT >> 1] |= JOYSTAT_TRANS_BIT;
530 // Fall through
531 case REG_SIOMLT_SEND:
532 case REG_JOYCNT:
533 case REG_JOYSTAT:
534 case REG_JOY_RECV_LO:
535 case REG_JOY_RECV_HI:
536 value = GBASIOWriteRegister(&gba->sio, address, value);
537 break;
538
539 // Interrupts and misc
540 case REG_KEYCNT:
541 value &= 0xC3FF;
542 gba->memory.io[address >> 1] = value;
543 GBATestKeypadIRQ(gba);
544 return;
545 case REG_WAITCNT:
546 value &= 0x5FFF;
547 GBAAdjustWaitstates(gba, value);
548 break;
549 case REG_IE:
550 gba->memory.io[REG_IE >> 1] = value;
551 GBATestIRQ(gba, 1);
552 return;
553 case REG_IF:
554 value = gba->memory.io[REG_IF >> 1] & ~value;
555 gba->memory.io[REG_IF >> 1] = value;
556 GBATestIRQ(gba, 1);
557 return;
558 case REG_IME:
559 gba->memory.io[REG_IME >> 1] = value;
560 GBATestIRQ(gba, 1);
561 return;
562 case REG_MAX:
563 // Some bad interrupt libraries will write to this
564 break;
565 case REG_DEBUG_ENABLE:
566 gba->debug = value == 0xC0DE;
567 return;
568 case REG_DEBUG_FLAGS:
569 if (gba->debug) {
570 GBADebug(gba, value);
571 return;
572 }
573 // Fall through
574 default:
575 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
576 STORE_16LE(value, address - REG_DEBUG_STRING, gba->debugString);
577 return;
578 }
579 mLOG(GBA_IO, STUB, "Stub I/O register write: %03X", address);
580 if (address >= REG_MAX) {
581 mLOG(GBA_IO, GAME_ERROR, "Write to unused I/O register: %03X", address);
582 return;
583 }
584 break;
585 }
586 }
587 gba->memory.io[address >> 1] = value;
588}
589
590void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
591 if (address == REG_HALTCNT) {
592 value &= 0x80;
593 if (!value) {
594 GBAHalt(gba);
595 } else {
596 GBAStop(gba);
597 }
598 return;
599 }
600 if (address == REG_POSTFLG) {
601 gba->memory.io[(address & (SIZE_IO - 1)) >> 1] = value;
602 return;
603 }
604 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
605 gba->debugString[address - REG_DEBUG_STRING] = value;
606 return;
607 }
608 if (address > SIZE_IO) {
609 return;
610 }
611 uint16_t value16 = value << (8 * (address & 1));
612 value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
613 GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
614}
615
616void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
617 switch (address) {
618 case REG_WAVE_RAM0_LO:
619 GBAAudioWriteWaveRAM(&gba->audio, 0, value);
620 break;
621 case REG_WAVE_RAM1_LO:
622 GBAAudioWriteWaveRAM(&gba->audio, 1, value);
623 break;
624 case REG_WAVE_RAM2_LO:
625 GBAAudioWriteWaveRAM(&gba->audio, 2, value);
626 break;
627 case REG_WAVE_RAM3_LO:
628 GBAAudioWriteWaveRAM(&gba->audio, 3, value);
629 break;
630 case REG_FIFO_A_LO:
631 case REG_FIFO_B_LO:
632 GBAAudioWriteFIFO(&gba->audio, address, value);
633 break;
634 case REG_DMA0SAD_LO:
635 value = GBADMAWriteSAD(gba, 0, value);
636 break;
637 case REG_DMA0DAD_LO:
638 value = GBADMAWriteDAD(gba, 0, value);
639 break;
640 case REG_DMA1SAD_LO:
641 value = GBADMAWriteSAD(gba, 1, value);
642 break;
643 case REG_DMA1DAD_LO:
644 value = GBADMAWriteDAD(gba, 1, value);
645 break;
646 case REG_DMA2SAD_LO:
647 value = GBADMAWriteSAD(gba, 2, value);
648 break;
649 case REG_DMA2DAD_LO:
650 value = GBADMAWriteDAD(gba, 2, value);
651 break;
652 case REG_DMA3SAD_LO:
653 value = GBADMAWriteSAD(gba, 3, value);
654 break;
655 case REG_DMA3DAD_LO:
656 value = GBADMAWriteDAD(gba, 3, value);
657 break;
658 default:
659 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
660 STORE_32LE(value, address - REG_DEBUG_STRING, gba->debugString);
661 return;
662 }
663 GBAIOWrite(gba, address, value & 0xFFFF);
664 GBAIOWrite(gba, address | 2, value >> 16);
665 return;
666 }
667 gba->memory.io[address >> 1] = value;
668 gba->memory.io[(address >> 1) + 1] = value >> 16;
669}
670
671bool GBAIOIsReadConstant(uint32_t address) {
672 switch (address) {
673 default:
674 return false;
675 case REG_BG0CNT:
676 case REG_BG1CNT:
677 case REG_BG2CNT:
678 case REG_BG3CNT:
679 case REG_WININ:
680 case REG_WINOUT:
681 case REG_BLDCNT:
682 case REG_BLDALPHA:
683 case REG_SOUND1CNT_LO:
684 case REG_SOUND1CNT_HI:
685 case REG_SOUND1CNT_X:
686 case REG_SOUND2CNT_LO:
687 case REG_SOUND2CNT_HI:
688 case REG_SOUND3CNT_LO:
689 case REG_SOUND3CNT_HI:
690 case REG_SOUND3CNT_X:
691 case REG_SOUND4CNT_LO:
692 case REG_SOUND4CNT_HI:
693 case REG_SOUNDCNT_LO:
694 case REG_SOUNDCNT_HI:
695 case REG_TM0CNT_HI:
696 case REG_TM1CNT_HI:
697 case REG_TM2CNT_HI:
698 case REG_TM3CNT_HI:
699 case REG_KEYINPUT:
700 case REG_KEYCNT:
701 case REG_IE:
702 return true;
703 }
704}
705
706uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
707 if (!GBAIOIsReadConstant(address)) {
708 // Most IO reads need to disable idle removal
709 gba->haltPending = false;
710 }
711
712 switch (address) {
713 // Reading this takes two cycles (1N+1I), so let's remove them preemptively
714 case REG_TM0CNT_LO:
715 GBATimerUpdateRegister(gba, 0, 4);
716 break;
717 case REG_TM1CNT_LO:
718 GBATimerUpdateRegister(gba, 1, 4);
719 break;
720 case REG_TM2CNT_LO:
721 GBATimerUpdateRegister(gba, 2, 4);
722 break;
723 case REG_TM3CNT_LO:
724 GBATimerUpdateRegister(gba, 3, 4);
725 break;
726
727 case REG_KEYINPUT:
728 {
729 size_t c;
730 for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
731 struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
732 if (callbacks->keysRead) {
733 callbacks->keysRead(callbacks->context);
734 }
735 }
736 }
737 if (gba->rr && gba->rr->isPlaying(gba->rr)) {
738 return 0x3FF ^ gba->rr->queryInput(gba->rr);
739 } else {
740 uint16_t input = 0;
741 if (gba->keyCallback) {
742 input = gba->keyCallback->readKeys(gba->keyCallback);
743 if (gba->keySource) {
744 *gba->keySource = input;
745 }
746 } else if (gba->keySource) {
747 input = *gba->keySource;
748 if (!gba->allowOpposingDirections) {
749 unsigned rl = input & 0x030;
750 unsigned ud = input & 0x0C0;
751 input &= 0x30F;
752 if (rl != 0x030) {
753 input |= rl;
754 }
755 if (ud != 0x0C0) {
756 input |= ud;
757 }
758 }
759 }
760 if (gba->rr && gba->rr->isRecording(gba->rr)) {
761 gba->rr->logInput(gba->rr, input);
762 }
763 return 0x3FF ^ input;
764 }
765
766 case REG_SIOCNT:
767 return gba->sio.siocnt;
768 case REG_RCNT:
769 return gba->sio.rcnt;
770
771 case REG_BG0HOFS:
772 case REG_BG0VOFS:
773 case REG_BG1HOFS:
774 case REG_BG1VOFS:
775 case REG_BG2HOFS:
776 case REG_BG2VOFS:
777 case REG_BG3HOFS:
778 case REG_BG3VOFS:
779 case REG_BG2PA:
780 case REG_BG2PB:
781 case REG_BG2PC:
782 case REG_BG2PD:
783 case REG_BG2X_LO:
784 case REG_BG2X_HI:
785 case REG_BG2Y_LO:
786 case REG_BG2Y_HI:
787 case REG_BG3PA:
788 case REG_BG3PB:
789 case REG_BG3PC:
790 case REG_BG3PD:
791 case REG_BG3X_LO:
792 case REG_BG3X_HI:
793 case REG_BG3Y_LO:
794 case REG_BG3Y_HI:
795 case REG_WIN0H:
796 case REG_WIN1H:
797 case REG_WIN0V:
798 case REG_WIN1V:
799 case REG_MOSAIC:
800 case REG_BLDY:
801 case REG_FIFO_A_LO:
802 case REG_FIFO_A_HI:
803 case REG_FIFO_B_LO:
804 case REG_FIFO_B_HI:
805 case REG_DMA0SAD_LO:
806 case REG_DMA0SAD_HI:
807 case REG_DMA0DAD_LO:
808 case REG_DMA0DAD_HI:
809 case REG_DMA1SAD_LO:
810 case REG_DMA1SAD_HI:
811 case REG_DMA1DAD_LO:
812 case REG_DMA1DAD_HI:
813 case REG_DMA2SAD_LO:
814 case REG_DMA2SAD_HI:
815 case REG_DMA2DAD_LO:
816 case REG_DMA2DAD_HI:
817 case REG_DMA3SAD_LO:
818 case REG_DMA3SAD_HI:
819 case REG_DMA3DAD_LO:
820 case REG_DMA3DAD_HI:
821 // Write-only register
822 mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
823 return GBALoadBad(gba->cpu);
824
825 case REG_DMA0CNT_LO:
826 case REG_DMA1CNT_LO:
827 case REG_DMA2CNT_LO:
828 case REG_DMA3CNT_LO:
829 // Write-only register
830 mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
831 return 0;
832
833 case REG_JOY_RECV_LO:
834 case REG_JOY_RECV_HI:
835 gba->memory.io[REG_JOYSTAT >> 1] &= ~JOYSTAT_RECV_BIT;
836 break;
837
838 case REG_SOUNDBIAS:
839 case REG_POSTFLG:
840 mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address);
841 break;
842 case REG_SOUND1CNT_LO:
843 case REG_SOUND1CNT_HI:
844 case REG_SOUND1CNT_X:
845 case REG_SOUND2CNT_LO:
846 case REG_SOUND2CNT_HI:
847 case REG_SOUND3CNT_LO:
848 case REG_SOUND3CNT_HI:
849 case REG_SOUND3CNT_X:
850 case REG_SOUND4CNT_LO:
851 case REG_SOUND4CNT_HI:
852 case REG_SOUNDCNT_LO:
853 if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) {
854 // TODO: Is writing allowed when the circuit is disabled?
855 return 0;
856 }
857 // Fall through
858 case REG_DISPCNT:
859 case REG_DISPSTAT:
860 case REG_VCOUNT:
861 case REG_BG0CNT:
862 case REG_BG1CNT:
863 case REG_BG2CNT:
864 case REG_BG3CNT:
865 case REG_WININ:
866 case REG_WINOUT:
867 case REG_BLDCNT:
868 case REG_BLDALPHA:
869 case REG_SOUNDCNT_HI:
870 case REG_SOUNDCNT_X:
871 case REG_WAVE_RAM0_LO:
872 case REG_WAVE_RAM0_HI:
873 case REG_WAVE_RAM1_LO:
874 case REG_WAVE_RAM1_HI:
875 case REG_WAVE_RAM2_LO:
876 case REG_WAVE_RAM2_HI:
877 case REG_WAVE_RAM3_LO:
878 case REG_WAVE_RAM3_HI:
879 case REG_DMA0CNT_HI:
880 case REG_DMA1CNT_HI:
881 case REG_DMA2CNT_HI:
882 case REG_DMA3CNT_HI:
883 case REG_TM0CNT_HI:
884 case REG_TM1CNT_HI:
885 case REG_TM2CNT_HI:
886 case REG_TM3CNT_HI:
887 case REG_KEYCNT:
888 case REG_SIOMULTI0:
889 case REG_SIOMULTI1:
890 case REG_SIOMULTI2:
891 case REG_SIOMULTI3:
892 case REG_SIOMLT_SEND:
893 case REG_JOYCNT:
894 case REG_JOY_TRANS_LO:
895 case REG_JOY_TRANS_HI:
896 case REG_JOYSTAT:
897 case REG_IE:
898 case REG_IF:
899 case REG_WAITCNT:
900 case REG_IME:
901 // Handled transparently by registers
902 break;
903 case REG_MAX:
904 // Some bad interrupt libraries will read from this
905 case 0x066:
906 case 0x06E:
907 case 0x076:
908 case 0x07A:
909 case 0x07E:
910 case 0x086:
911 case 0x08A:
912 case 0x136:
913 case 0x142:
914 case 0x15A:
915 case 0x206:
916 mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
917 return 0;
918 case REG_DEBUG_ENABLE:
919 if (gba->debug) {
920 return 0x1DEA;
921 }
922 // Fall through
923 default:
924 mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
925 return GBALoadBad(gba->cpu);
926 }
927 return gba->memory.io[address >> 1];
928}
929
930void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
931 int i;
932 for (i = 0; i < REG_MAX; i += 2) {
933 if (_isRSpecialRegister[i >> 1]) {
934 STORE_16(gba->memory.io[i >> 1], i, state->io);
935 } else if (_isValidRegister[i >> 1]) {
936 uint16_t reg = GBAIORead(gba, i);
937 STORE_16(reg, i, state->io);
938 }
939 }
940
941 for (i = 0; i < 4; ++i) {
942 STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
943 STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
944 STORE_32(gba->timers[i].lastEvent - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].lastEvent);
945 STORE_32(gba->timers[i].event.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextEvent);
946 STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
947 STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
948 STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
949 STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
950 STORE_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
951 }
952
953 state->dmaTransferRegister = gba->memory.dmaTransferRegister;
954
955 GBAHardwareSerialize(&gba->memory.hw, state);
956}
957
958void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
959 int i;
960 for (i = 0; i < REG_MAX; i += 2) {
961 if (_isWSpecialRegister[i >> 1]) {
962 LOAD_16(gba->memory.io[i >> 1], i, state->io);
963 } else if (_isValidRegister[i >> 1]) {
964 uint16_t reg;
965 LOAD_16(reg, i, state->io);
966 GBAIOWrite(gba, i, reg);
967 }
968 }
969
970 uint32_t when;
971 for (i = 0; i < 4; ++i) {
972 LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
973 LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
974 if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) {
975 // Overwrite invalid values in savestate
976 gba->timers[i].lastEvent = 0;
977 } else {
978 LOAD_32(when, 0, &state->timers[i].lastEvent);
979 gba->timers[i].lastEvent = when + mTimingCurrentTime(&gba->timing);
980 }
981 LOAD_32(when, 0, &state->timers[i].nextEvent);
982 if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
983 mTimingSchedule(&gba->timing, &gba->timers[i].event, when);
984 }
985
986 LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
987 LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
988 LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
989 LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
990 LOAD_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
991 if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != GBA_DMA_TIMING_NOW) {
992 GBADMASchedule(gba, i, &gba->memory.dma[i]);
993 }
994 }
995 GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
996 gba->memory.dmaTransferRegister = state->dmaTransferRegister;
997 GBADMAUpdate(gba);
998 GBAHardwareDeserialize(&gba->memory.hw, state);
999}