src/gba/gba-io.c (view raw)
1#include "gba-io.h"
2
3#include "gba-serialize.h"
4#include "gba-video.h"
5
6void GBAIOInit(struct GBA* gba) {
7 gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
8 gba->memory.io[REG_RCNT >> 1] = 0x8000;
9 gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
10}
11
12void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
13 if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
14 value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
15 } else {
16 switch (address) {
17 // Video
18 case REG_DISPSTAT:
19 value &= 0xFFF8;
20 GBAVideoWriteDISPSTAT(&gba->video, value);
21 break;
22
23 // Audio
24 case REG_SOUND1CNT_LO:
25 GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
26 value &= 0x00FF;
27 break;
28 case REG_SOUND1CNT_HI:
29 GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
30 break;
31 case REG_SOUND1CNT_X:
32 GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
33 value &= 0x47FF;
34 break;
35 case REG_SOUND2CNT_LO:
36 GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
37 break;
38 case REG_SOUND2CNT_HI:
39 GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
40 value &= 0x47FF;
41 break;
42 case REG_SOUND3CNT_LO:
43 GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
44 value &= 0x00E0;
45 break;
46 case REG_SOUND3CNT_HI:
47 GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
48 value &= 0xE000;
49 break;
50 case REG_SOUND3CNT_X:
51 GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
52 value &= 0x4000;
53 break;
54 case REG_SOUND4CNT_LO:
55 GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
56 value &= 0xFF00;
57 break;
58 case REG_SOUND4CNT_HI:
59 GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
60 value &= 0x40FF;
61 break;
62 case REG_SOUNDCNT_LO:
63 GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
64 break;
65 case REG_SOUNDCNT_HI:
66 GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
67 break;
68 case REG_SOUNDCNT_X:
69 GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
70 break;
71
72 case REG_WAVE_RAM0_LO:
73 case REG_WAVE_RAM1_LO:
74 case REG_WAVE_RAM2_LO:
75 case REG_WAVE_RAM3_LO:
76 case REG_FIFO_A_LO:
77 case REG_FIFO_B_LO:
78 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
79 break;
80
81 case REG_WAVE_RAM0_HI:
82 case REG_WAVE_RAM1_HI:
83 case REG_WAVE_RAM2_HI:
84 case REG_WAVE_RAM3_HI:
85 case REG_FIFO_A_HI:
86 case REG_FIFO_B_HI:
87 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
88 break;
89
90 // DMA
91 case REG_DMA0SAD_LO:
92 case REG_DMA0DAD_LO:
93 case REG_DMA1SAD_LO:
94 case REG_DMA1DAD_LO:
95 case REG_DMA2SAD_LO:
96 case REG_DMA2DAD_LO:
97 case REG_DMA3SAD_LO:
98 case REG_DMA3DAD_LO:
99 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
100 break;
101
102 case REG_DMA0SAD_HI:
103 case REG_DMA0DAD_HI:
104 case REG_DMA1SAD_HI:
105 case REG_DMA1DAD_HI:
106 case REG_DMA2SAD_HI:
107 case REG_DMA2DAD_HI:
108 case REG_DMA3SAD_HI:
109 case REG_DMA3DAD_HI:
110 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
111 break;
112
113 case REG_DMA0CNT_LO:
114 GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
115 break;
116 case REG_DMA0CNT_HI:
117 value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
118 break;
119 case REG_DMA1CNT_LO:
120 GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
121 break;
122 case REG_DMA1CNT_HI:
123 value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
124 break;
125 case REG_DMA2CNT_LO:
126 GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
127 break;
128 case REG_DMA2CNT_HI:
129 value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
130 break;
131 case REG_DMA3CNT_LO:
132 GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
133 break;
134 case REG_DMA3CNT_HI:
135 value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
136 break;
137
138 // Timers
139 case REG_TM0CNT_LO:
140 GBATimerWriteTMCNT_LO(gba, 0, value);
141 return;
142 case REG_TM1CNT_LO:
143 GBATimerWriteTMCNT_LO(gba, 1, value);
144 return;
145 case REG_TM2CNT_LO:
146 GBATimerWriteTMCNT_LO(gba, 2, value);
147 return;
148 case REG_TM3CNT_LO:
149 GBATimerWriteTMCNT_LO(gba, 3, value);
150 return;
151
152 case REG_TM0CNT_HI:
153 value &= 0x00C7;
154 GBATimerWriteTMCNT_HI(gba, 0, value);
155 break;
156 case REG_TM1CNT_HI:
157 value &= 0x00C7;
158 GBATimerWriteTMCNT_HI(gba, 1, value);
159 break;
160 case REG_TM2CNT_HI:
161 value &= 0x00C7;
162 GBATimerWriteTMCNT_HI(gba, 2, value);
163 break;
164 case REG_TM3CNT_HI:
165 value &= 0x00C7;
166 GBATimerWriteTMCNT_HI(gba, 3, value);
167 break;
168
169 // Interrupts and misc
170 case REG_WAITCNT:
171 GBAAdjustWaitstates(&gba->memory, value);
172 break;
173 case REG_IE:
174 GBAWriteIE(gba, value);
175 break;
176 case REG_IF:
177 value = gba->memory.io[REG_IF >> 1] & ~value;
178 break;
179 case REG_IME:
180 GBAWriteIME(gba, value);
181 break;
182 case 0x20A:
183 // Some bad interrupt libraries will write to this
184 break;
185 default:
186 GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address);
187 break;
188 }
189 }
190 gba->memory.io[address >> 1] = value;
191}
192
193void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
194 if (address == REG_HALTCNT) {
195 value &= 0x80;
196 if (!value) {
197 GBAHalt(gba);
198 } else {
199 GBALog(gba, GBA_LOG_STUB, "Stop unimplemented");
200 }
201 return;
202 }
203 uint16_t value16 = value << (8 * (address & 1));
204 value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
205 GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
206}
207
208void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
209 switch (address) {
210 case REG_WAVE_RAM0_LO:
211 GBAAudioWriteWaveRAM(&gba->audio, 0, value);
212 break;
213 case REG_WAVE_RAM1_LO:
214 GBAAudioWriteWaveRAM(&gba->audio, 1, value);
215 break;
216 case REG_WAVE_RAM2_LO:
217 GBAAudioWriteWaveRAM(&gba->audio, 2, value);
218 break;
219 case REG_WAVE_RAM3_LO:
220 GBAAudioWriteWaveRAM(&gba->audio, 3, value);
221 break;
222 case REG_FIFO_A_LO:
223 case REG_FIFO_B_LO:
224 GBAAudioWriteFIFO(&gba->audio, address, value);
225 break;
226 case REG_DMA0SAD_LO:
227 GBAMemoryWriteDMASAD(&gba->memory, 0, value);
228 break;
229 case REG_DMA0DAD_LO:
230 GBAMemoryWriteDMADAD(&gba->memory, 0, value);
231 break;
232 case REG_DMA1SAD_LO:
233 GBAMemoryWriteDMASAD(&gba->memory, 1, value);
234 break;
235 case REG_DMA1DAD_LO:
236 GBAMemoryWriteDMADAD(&gba->memory, 1, value);
237 break;
238 case REG_DMA2SAD_LO:
239 GBAMemoryWriteDMASAD(&gba->memory, 2, value);
240 break;
241 case REG_DMA2DAD_LO:
242 GBAMemoryWriteDMADAD(&gba->memory, 2, value);
243 break;
244 case REG_DMA3SAD_LO:
245 GBAMemoryWriteDMASAD(&gba->memory, 3, value);
246 break;
247 case REG_DMA3DAD_LO:
248 GBAMemoryWriteDMADAD(&gba->memory, 3, value);
249 break;
250 default:
251 GBAIOWrite(gba, address, value & 0xFFFF);
252 GBAIOWrite(gba, address | 2, value >> 16);
253 return;
254 }
255 gba->memory.io[address >> 1] = value;
256 gba->memory.io[(address >> 1) + 1] = value >> 16;
257}
258
259uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
260 switch (address) {
261 case REG_DISPSTAT:
262 return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
263 break;
264
265 case REG_TM0CNT_LO:
266 GBATimerUpdateRegister(gba, 0);
267 break;
268 case REG_TM1CNT_LO:
269 GBATimerUpdateRegister(gba, 1);
270 break;
271 case REG_TM2CNT_LO:
272 GBATimerUpdateRegister(gba, 2);
273 break;
274 case REG_TM3CNT_LO:
275 GBATimerUpdateRegister(gba, 3);
276 break;
277
278 case REG_KEYINPUT:
279 if (gba->keySource) {
280 return 0x3FF ^ *gba->keySource;
281 }
282 break;
283
284 case REG_DMA0CNT_LO:
285 case REG_DMA1CNT_LO:
286 case REG_DMA2CNT_LO:
287 case REG_DMA3CNT_LO:
288 // Write-only register
289 return 0;
290 case REG_DISPCNT:
291 case REG_VCOUNT:
292 case REG_BG0CNT:
293 case REG_BG1CNT:
294 case REG_BG2CNT:
295 case REG_BG3CNT:
296 case REG_WININ:
297 case REG_WINOUT:
298 case REG_BLDCNT:
299 case REG_SOUND1CNT_LO:
300 case REG_SOUND1CNT_HI:
301 case REG_SOUND1CNT_X:
302 case REG_SOUND2CNT_LO:
303 case REG_SOUND2CNT_HI:
304 case REG_SOUND3CNT_LO:
305 case REG_SOUND3CNT_HI:
306 case REG_SOUND3CNT_X:
307 case REG_SOUND4CNT_LO:
308 case REG_SOUND4CNT_HI:
309 case REG_SOUNDCNT_LO:
310 case REG_SOUNDCNT_HI:
311 case REG_DMA0CNT_HI:
312 case REG_DMA1CNT_HI:
313 case REG_DMA2CNT_HI:
314 case REG_DMA3CNT_HI:
315 case REG_IE:
316 case REG_IF:
317 case REG_WAITCNT:
318 case REG_IME:
319 // Handled transparently by registers
320 break;
321 case 0x20A:
322 // Some bad interrupt libraries will read from this
323 break;
324 default:
325 GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
326 break;
327 }
328 return gba->memory.io[address >> 1];
329}
330
331void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
332 memcpy(state->io, gba->memory.io, SIZE_IO);
333}
334
335void GBAIODeserialize(struct GBA* gba, struct GBASerializedState* state) {
336 // TODO: Actually fill this out
337 int i;
338 for (i = 0; i < REG_SOUND1CNT_LO; i += 2) {
339 GBAIOWrite(gba, i, state->io[i >> 1]);
340 }
341}