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