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