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