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_DISPSTAT:
359 return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
360 break;
361
362 case REG_TM0CNT_LO:
363 GBATimerUpdateRegister(gba, 0);
364 break;
365 case REG_TM1CNT_LO:
366 GBATimerUpdateRegister(gba, 1);
367 break;
368 case REG_TM2CNT_LO:
369 GBATimerUpdateRegister(gba, 2);
370 break;
371 case REG_TM3CNT_LO:
372 GBATimerUpdateRegister(gba, 3);
373 break;
374
375 case REG_KEYINPUT:
376 if (gba->keySource) {
377 return 0x3FF ^ *gba->keySource;
378 }
379 break;
380
381 case REG_SIOCNT:
382 return gba->sio.siocnt;
383 case REG_RCNT:
384 return gba->sio.rcnt;
385
386 case REG_DMA0CNT_LO:
387 case REG_DMA1CNT_LO:
388 case REG_DMA2CNT_LO:
389 case REG_DMA3CNT_LO:
390 // Write-only register
391 return 0;
392 case REG_DISPCNT:
393 case REG_VCOUNT:
394 case REG_BG0CNT:
395 case REG_BG1CNT:
396 case REG_BG2CNT:
397 case REG_BG3CNT:
398 case REG_WININ:
399 case REG_WINOUT:
400 case REG_BLDCNT:
401 case REG_SOUND1CNT_LO:
402 case REG_SOUND1CNT_HI:
403 case REG_SOUND1CNT_X:
404 case REG_SOUND2CNT_LO:
405 case REG_SOUND2CNT_HI:
406 case REG_SOUND3CNT_LO:
407 case REG_SOUND3CNT_HI:
408 case REG_SOUND3CNT_X:
409 case REG_SOUND4CNT_LO:
410 case REG_SOUND4CNT_HI:
411 case REG_SOUNDCNT_LO:
412 case REG_SOUNDCNT_HI:
413 case REG_DMA0CNT_HI:
414 case REG_DMA1CNT_HI:
415 case REG_DMA2CNT_HI:
416 case REG_DMA3CNT_HI:
417 case REG_SIOMULTI0:
418 case REG_SIOMULTI1:
419 case REG_SIOMULTI2:
420 case REG_SIOMULTI3:
421 case REG_SIOMLT_SEND:
422 case REG_IE:
423 case REG_IF:
424 case REG_WAITCNT:
425 case REG_IME:
426 // Handled transparently by registers
427 break;
428 case REG_MAX:
429 // Some bad interrupt libraries will read from this
430 break;
431 default:
432 GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
433 break;
434 }
435 return gba->memory.io[address >> 1];
436}
437
438void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
439 int i;
440 for (i = 0; i < REG_MAX; i += 2) {
441 if (_isSpecialRegister[i >> 1]) {
442 state->io[i >> 1] = gba->memory.io[i >> 1];
443 } else if (_isValidRegister[i >> 1]) {
444 state->io[i >> 1] = GBAIORead(gba, i);
445 }
446 }
447
448 for (i = 0; i < 4; ++i) {
449 state->dma[i].nextSource = gba->memory.dma[i].nextSource;
450 state->dma[i].nextDest = gba->memory.dma[i].nextDest;
451 state->dma[i].nextCount = gba->memory.dma[i].nextCount;
452 state->dma[i].nextEvent = gba->memory.dma[i].nextEvent;
453 }
454
455 memcpy(state->timers, gba->timers, sizeof(state->timers));
456}
457
458void GBAIODeserialize(struct GBA* gba, struct GBASerializedState* state) {
459 int i;
460 for (i = 0; i < REG_MAX; i += 2) {
461 if (_isSpecialRegister[i >> 1]) {
462 gba->memory.io[i >> 1] = state->io[i >> 1];
463 } else if (_isValidRegister[i >> 1]) {
464 GBAIOWrite(gba, i, state->io[i >> 1]);
465 }
466 }
467
468 for (i = 0; i < 4; ++i) {
469 gba->memory.dma[i].nextSource = state->dma[i].nextSource;
470 gba->memory.dma[i].nextDest = state->dma[i].nextDest;
471 gba->memory.dma[i].nextCount = state->dma[i].nextCount;
472 gba->memory.dma[i].nextEvent = state->dma[i].nextEvent;
473 }
474
475 memcpy(state->timers, gba->timers, sizeof(gba->timers));
476}