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