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