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