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