src/gba/gba-io.c (view raw)
1#include "gba-io.h"
2
3#include "gba-rr.h"
4#include "gba-serialize.h"
5#include "gba-sio.h"
6#include "gba-video.h"
7
8static const int _isValidRegister[REG_MAX >> 1] = {
9 // Video
10 1, 0, 1, 1, 1, 1, 1, 1,
11 1, 1, 1, 1, 1, 1, 1, 1,
12 1, 1, 1, 1, 1, 1, 1, 1,
13 1, 1, 1, 1, 1, 1, 1, 1,
14 1, 1, 1, 1, 1, 1, 1, 0,
15 1, 1, 1, 0, 0, 0, 0, 0,
16 // Audio
17 1, 1, 1, 0, 1, 0, 1, 0,
18 1, 1, 1, 0, 1, 0, 1, 0,
19 1, 1, 1, 0, 1, 0, 0, 0,
20 1, 1, 1, 1, 1, 1, 1, 1,
21 1, 1, 1, 1, 1, 0, 0, 0,
22 // DMA
23 1, 1, 1, 1, 1, 1, 1, 1,
24 1, 1, 1, 1, 1, 1, 1, 1,
25 1, 1, 1, 1, 1, 1, 1, 1,
26 0, 0, 0, 0, 0, 0, 0, 0,
27 0, 0, 0, 0, 0, 0, 0, 0,
28 // Timers
29 1, 1, 1, 1, 1, 1, 1, 1,
30 0, 0, 0, 0, 0, 0, 0, 0,
31 // SIO
32 1, 1, 1, 1, 1, 0, 0, 0,
33 1, 1, 1, 0, 0, 0, 0, 0,
34 1, 0, 0, 0, 0, 0, 0, 0,
35 1, 0, 1, 0, 1, 0, 0, 0,
36 0, 0, 0, 0, 0, 0, 0, 0,
37 0, 0, 0, 0, 0, 0, 0, 0,
38 0, 0, 0, 0, 0, 0, 0, 0,
39 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0,
42 0, 0, 0, 0, 0, 0, 0, 0,
43 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0,
46 // Interrupts
47 1, 1, 1, 0, 1
48};
49
50static const int _isSpecialRegister[REG_MAX >> 1] = {
51 // Video
52 0, 0, 0, 1, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0,
58 // Audio
59 0, 0, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 0, 0,
61 0, 0, 0, 0, 0, 0, 0, 0,
62 1, 1, 1, 1, 1, 1, 1, 1,
63 1, 1, 1, 1, 0, 0, 0, 0,
64 // DMA
65 0, 0, 0, 0, 0, 0, 0, 0,
66 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0,
70 // Timers
71 1, 1, 1, 1, 1, 1, 1, 1,
72 0, 0, 0, 0, 0, 0, 0, 0,
73 // SIO
74 1, 1, 1, 1, 1, 0, 0, 0,
75 1, 1, 1, 0, 0, 0, 0, 0,
76 1, 0, 0, 0, 0, 0, 0, 0,
77 1, 0, 1, 0, 1, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0,
81 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0,
85 0, 0, 0, 0, 0, 0, 0, 0,
86 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0,
88 // Interrupts
89 1, 1, 1, 0, 1
90};
91
92void GBAIOInit(struct GBA* gba) {
93 gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
94 gba->memory.io[REG_RCNT >> 1] = RCNT_INITIAL;
95 gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
96 gba->memory.io[REG_SOUNDBIAS >> 1] = 0x200;
97}
98
99void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
100 if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
101 value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
102 } else {
103 switch (address) {
104 // Video
105 case REG_DISPSTAT:
106 value &= 0xFFF8;
107 GBAVideoWriteDISPSTAT(&gba->video, value);
108 break;
109
110 // Audio
111 case REG_SOUND1CNT_LO:
112 GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
113 value &= 0x00FF;
114 break;
115 case REG_SOUND1CNT_HI:
116 GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
117 break;
118 case REG_SOUND1CNT_X:
119 GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
120 value &= 0x47FF;
121 break;
122 case REG_SOUND2CNT_LO:
123 GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
124 break;
125 case REG_SOUND2CNT_HI:
126 GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
127 value &= 0x47FF;
128 break;
129 case REG_SOUND3CNT_LO:
130 GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
131 value &= 0x00E0;
132 break;
133 case REG_SOUND3CNT_HI:
134 GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
135 value &= 0xE000;
136 break;
137 case REG_SOUND3CNT_X:
138 GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
139 // TODO: The low bits need to not be readable, but still 8-bit writable
140 value &= 0x43FF;
141 break;
142 case REG_SOUND4CNT_LO:
143 GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
144 value &= 0xFF00;
145 break;
146 case REG_SOUND4CNT_HI:
147 GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
148 value &= 0x40FF;
149 break;
150 case REG_SOUNDCNT_LO:
151 GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
152 break;
153 case REG_SOUNDCNT_HI:
154 GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
155 break;
156 case REG_SOUNDCNT_X:
157 GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
158 break;
159 case REG_SOUNDBIAS:
160 GBAAudioWriteSOUNDBIAS(&gba->audio, value);
161 break;
162
163 case REG_WAVE_RAM0_LO:
164 case REG_WAVE_RAM1_LO:
165 case REG_WAVE_RAM2_LO:
166 case REG_WAVE_RAM3_LO:
167 case REG_FIFO_A_LO:
168 case REG_FIFO_B_LO:
169 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
170 break;
171
172 case REG_WAVE_RAM0_HI:
173 case REG_WAVE_RAM1_HI:
174 case REG_WAVE_RAM2_HI:
175 case REG_WAVE_RAM3_HI:
176 case REG_FIFO_A_HI:
177 case REG_FIFO_B_HI:
178 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
179 break;
180
181 // DMA
182 case REG_DMA0SAD_LO:
183 case REG_DMA0DAD_LO:
184 case REG_DMA1SAD_LO:
185 case REG_DMA1DAD_LO:
186 case REG_DMA2SAD_LO:
187 case REG_DMA2DAD_LO:
188 case REG_DMA3SAD_LO:
189 case REG_DMA3DAD_LO:
190 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
191 break;
192
193 case REG_DMA0SAD_HI:
194 case REG_DMA0DAD_HI:
195 case REG_DMA1SAD_HI:
196 case REG_DMA1DAD_HI:
197 case REG_DMA2SAD_HI:
198 case REG_DMA2DAD_HI:
199 case REG_DMA3SAD_HI:
200 case REG_DMA3DAD_HI:
201 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
202 break;
203
204 case REG_DMA0CNT_LO:
205 GBAMemoryWriteDMACNT_LO(gba, 0, value);
206 break;
207 case REG_DMA0CNT_HI:
208 value = GBAMemoryWriteDMACNT_HI(gba, 0, value);
209 break;
210 case REG_DMA1CNT_LO:
211 GBAMemoryWriteDMACNT_LO(gba, 1, value);
212 break;
213 case REG_DMA1CNT_HI:
214 value = GBAMemoryWriteDMACNT_HI(gba, 1, value);
215 break;
216 case REG_DMA2CNT_LO:
217 GBAMemoryWriteDMACNT_LO(gba, 2, value);
218 break;
219 case REG_DMA2CNT_HI:
220 value = GBAMemoryWriteDMACNT_HI(gba, 2, value);
221 break;
222 case REG_DMA3CNT_LO:
223 GBAMemoryWriteDMACNT_LO(gba, 3, value);
224 break;
225 case REG_DMA3CNT_HI:
226 value = GBAMemoryWriteDMACNT_HI(gba, 3, value);
227 break;
228
229 // Timers
230 case REG_TM0CNT_LO:
231 GBATimerWriteTMCNT_LO(gba, 0, value);
232 return;
233 case REG_TM1CNT_LO:
234 GBATimerWriteTMCNT_LO(gba, 1, value);
235 return;
236 case REG_TM2CNT_LO:
237 GBATimerWriteTMCNT_LO(gba, 2, value);
238 return;
239 case REG_TM3CNT_LO:
240 GBATimerWriteTMCNT_LO(gba, 3, value);
241 return;
242
243 case REG_TM0CNT_HI:
244 value &= 0x00C7;
245 GBATimerWriteTMCNT_HI(gba, 0, value);
246 break;
247 case REG_TM1CNT_HI:
248 value &= 0x00C7;
249 GBATimerWriteTMCNT_HI(gba, 1, value);
250 break;
251 case REG_TM2CNT_HI:
252 value &= 0x00C7;
253 GBATimerWriteTMCNT_HI(gba, 2, value);
254 break;
255 case REG_TM3CNT_HI:
256 value &= 0x00C7;
257 GBATimerWriteTMCNT_HI(gba, 3, value);
258 break;
259
260 // SIO
261 case REG_SIOCNT:
262 GBASIOWriteSIOCNT(&gba->sio, value);
263 break;
264 case REG_RCNT:
265 value &= 0xC1FF;
266 GBASIOWriteRCNT(&gba->sio, value);
267 break;
268 case REG_SIOMLT_SEND:
269 GBASIOWriteSIOMLT_SEND(&gba->sio, value);
270 break;
271
272 // Interrupts and misc
273 case REG_WAITCNT:
274 GBAAdjustWaitstates(gba, value);
275 break;
276 case REG_IE:
277 GBAWriteIE(gba, value);
278 break;
279 case REG_IF:
280 value = gba->memory.io[REG_IF >> 1] & ~value;
281 break;
282 case REG_IME:
283 GBAWriteIME(gba, value);
284 break;
285 case REG_MAX:
286 // Some bad interrupt libraries will write to this
287 break;
288 default:
289 GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address);
290 break;
291 }
292 }
293 gba->memory.io[address >> 1] = value;
294}
295
296void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
297 if (address == REG_HALTCNT) {
298 value &= 0x80;
299 if (!value) {
300 GBAHalt(gba);
301 } else {
302 GBALog(gba, GBA_LOG_STUB, "Stop unimplemented");
303 }
304 return;
305 }
306 uint16_t value16 = value << (8 * (address & 1));
307 value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
308 GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
309}
310
311void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
312 switch (address) {
313 case REG_WAVE_RAM0_LO:
314 GBAAudioWriteWaveRAM(&gba->audio, 0, value);
315 break;
316 case REG_WAVE_RAM1_LO:
317 GBAAudioWriteWaveRAM(&gba->audio, 1, value);
318 break;
319 case REG_WAVE_RAM2_LO:
320 GBAAudioWriteWaveRAM(&gba->audio, 2, value);
321 break;
322 case REG_WAVE_RAM3_LO:
323 GBAAudioWriteWaveRAM(&gba->audio, 3, value);
324 break;
325 case REG_FIFO_A_LO:
326 case REG_FIFO_B_LO:
327 GBAAudioWriteFIFO(&gba->audio, address, value);
328 break;
329 case REG_DMA0SAD_LO:
330 GBAMemoryWriteDMASAD(gba, 0, value);
331 break;
332 case REG_DMA0DAD_LO:
333 GBAMemoryWriteDMADAD(gba, 0, value);
334 break;
335 case REG_DMA1SAD_LO:
336 GBAMemoryWriteDMASAD(gba, 1, value);
337 break;
338 case REG_DMA1DAD_LO:
339 GBAMemoryWriteDMADAD(gba, 1, value);
340 break;
341 case REG_DMA2SAD_LO:
342 GBAMemoryWriteDMASAD(gba, 2, value);
343 break;
344 case REG_DMA2DAD_LO:
345 GBAMemoryWriteDMADAD(gba, 2, value);
346 break;
347 case REG_DMA3SAD_LO:
348 GBAMemoryWriteDMASAD(gba, 3, value);
349 break;
350 case REG_DMA3DAD_LO:
351 GBAMemoryWriteDMADAD(gba, 3, value);
352 break;
353 default:
354 GBAIOWrite(gba, address, value & 0xFFFF);
355 GBAIOWrite(gba, address | 2, value >> 16);
356 return;
357 }
358 gba->memory.io[address >> 1] = value;
359 gba->memory.io[(address >> 1) + 1] = value >> 16;
360}
361
362uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
363 switch (address) {
364 case REG_TM0CNT_LO:
365 GBATimerUpdateRegister(gba, 0);
366 break;
367 case REG_TM1CNT_LO:
368 GBATimerUpdateRegister(gba, 1);
369 break;
370 case REG_TM2CNT_LO:
371 GBATimerUpdateRegister(gba, 2);
372 break;
373 case REG_TM3CNT_LO:
374 GBATimerUpdateRegister(gba, 3);
375 break;
376
377 case REG_KEYINPUT:
378 if (GBARRIsPlaying(gba->rr)) {
379 return 0x3FF ^ GBARRQueryInput(gba->rr);
380 } else if (gba->keySource) {
381 uint16_t input = *gba->keySource;
382 if (GBARRIsRecording(gba->rr)) {
383 GBARRLogInput(gba->rr, input);
384 }
385 return 0x3FF ^ input;
386 }
387 break;
388
389 case REG_SIOCNT:
390 return gba->sio.siocnt;
391 case REG_RCNT:
392 return gba->sio.rcnt;
393
394 case REG_DMA0CNT_LO:
395 case REG_DMA1CNT_LO:
396 case REG_DMA2CNT_LO:
397 case REG_DMA3CNT_LO:
398 // Write-only register
399 return 0;
400 case REG_DISPCNT:
401 case REG_DISPSTAT:
402 case REG_VCOUNT:
403 case REG_BG0CNT:
404 case REG_BG1CNT:
405 case REG_BG2CNT:
406 case REG_BG3CNT:
407 case REG_WININ:
408 case REG_WINOUT:
409 case REG_BLDCNT:
410 case REG_SOUND1CNT_LO:
411 case REG_SOUND1CNT_HI:
412 case REG_SOUND1CNT_X:
413 case REG_SOUND2CNT_LO:
414 case REG_SOUND2CNT_HI:
415 case REG_SOUND3CNT_LO:
416 case REG_SOUND3CNT_HI:
417 case REG_SOUND3CNT_X:
418 case REG_SOUND4CNT_LO:
419 case REG_SOUND4CNT_HI:
420 case REG_SOUNDCNT_LO:
421 case REG_SOUNDCNT_HI:
422 case REG_DMA0CNT_HI:
423 case REG_DMA1CNT_HI:
424 case REG_DMA2CNT_HI:
425 case REG_DMA3CNT_HI:
426 case REG_SIOMULTI0:
427 case REG_SIOMULTI1:
428 case REG_SIOMULTI2:
429 case REG_SIOMULTI3:
430 case REG_SIOMLT_SEND:
431 case REG_IE:
432 case REG_IF:
433 case REG_WAITCNT:
434 case REG_IME:
435 // Handled transparently by registers
436 break;
437 case REG_MAX:
438 // Some bad interrupt libraries will read from this
439 break;
440 default:
441 GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
442 break;
443 }
444 return gba->memory.io[address >> 1];
445}
446
447void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
448 int i;
449 for (i = 0; i < REG_MAX; i += 2) {
450 if (_isSpecialRegister[i >> 1]) {
451 state->io[i >> 1] = gba->memory.io[i >> 1];
452 } else if (_isValidRegister[i >> 1]) {
453 state->io[i >> 1] = GBAIORead(gba, i);
454 }
455 }
456
457 for (i = 0; i < 4; ++i) {
458 state->dma[i].nextSource = gba->memory.dma[i].nextSource;
459 state->dma[i].nextDest = gba->memory.dma[i].nextDest;
460 state->dma[i].nextCount = gba->memory.dma[i].nextCount;
461 state->dma[i].nextEvent = gba->memory.dma[i].nextEvent;
462 }
463
464 memcpy(state->timers, gba->timers, sizeof(state->timers));
465 GBAGPIOSerialize(&gba->memory.gpio, state);
466}
467
468void GBAIODeserialize(struct GBA* gba, struct GBASerializedState* state) {
469 int i;
470 for (i = 0; i < REG_MAX; i += 2) {
471 if (_isSpecialRegister[i >> 1]) {
472 gba->memory.io[i >> 1] = state->io[i >> 1];
473 } else if (_isValidRegister[i >> 1]) {
474 GBAIOWrite(gba, i, state->io[i >> 1]);
475 }
476 }
477
478 gba->timersEnabled = 0;
479 memcpy(gba->timers, state->timers, sizeof(gba->timers));
480 for (i = 0; i < 4; ++i) {
481 gba->memory.dma[i].nextSource = state->dma[i].nextSource;
482 gba->memory.dma[i].nextDest = state->dma[i].nextDest;
483 gba->memory.dma[i].nextCount = state->dma[i].nextCount;
484 gba->memory.dma[i].nextEvent = state->dma[i].nextEvent;
485 if (gba->memory.dma[i].timing != DMA_TIMING_NOW) {
486 GBAMemoryScheduleDMA(gba, i, &gba->memory.dma[i]);
487 }
488
489 if (gba->timers[i].enable) {
490 gba->timersEnabled |= 1 << i;
491 }
492 }
493 GBAGPIODeserialize(&gba->memory.gpio, state);
494}