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