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 // DMA
21 case REG_DMA0SAD_LO:
22 case REG_DMA0DAD_LO:
23 case REG_DMA1SAD_LO:
24 case REG_DMA1DAD_LO:
25 case REG_DMA2SAD_LO:
26 case REG_DMA2DAD_LO:
27 case REG_DMA3SAD_LO:
28 case REG_DMA3DAD_LO:
29 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
30 break;
31
32 case REG_DMA0SAD_HI:
33 case REG_DMA0DAD_HI:
34 case REG_DMA1SAD_HI:
35 case REG_DMA1DAD_HI:
36 case REG_DMA2SAD_HI:
37 case REG_DMA2DAD_HI:
38 case REG_DMA3SAD_HI:
39 case REG_DMA3DAD_HI:
40 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
41 break;
42
43 case REG_DMA0CNT_LO:
44 GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
45 break;
46 case REG_DMA0CNT_HI:
47 value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
48 break;
49 case REG_DMA1CNT_LO:
50 GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
51 break;
52 case REG_DMA1CNT_HI:
53 value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
54 break;
55 case REG_DMA2CNT_LO:
56 GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
57 break;
58 case REG_DMA2CNT_HI:
59 value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
60 break;
61 case REG_DMA3CNT_LO:
62 GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
63 break;
64 case REG_DMA3CNT_HI:
65 value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
66 break;
67
68 // Timers
69 case REG_TM0CNT_LO:
70 GBATimerWriteTMCNT_LO(gba, 0, value);
71 return;
72 case REG_TM1CNT_LO:
73 GBATimerWriteTMCNT_LO(gba, 1, value);
74 return;
75 case REG_TM2CNT_LO:
76 GBATimerWriteTMCNT_LO(gba, 2, value);
77 return;
78 case REG_TM3CNT_LO:
79 GBATimerWriteTMCNT_LO(gba, 3, value);
80 return;
81
82 case REG_TM0CNT_HI:
83 value &= 0x00C7;
84 GBATimerWriteTMCNT_HI(gba, 0, value);
85 break;
86 case REG_TM1CNT_HI:
87 value &= 0x00C7;
88 GBATimerWriteTMCNT_HI(gba, 1, value);
89 break;
90 case REG_TM2CNT_HI:
91 value &= 0x00C7;
92 GBATimerWriteTMCNT_HI(gba, 2, value);
93 break;
94 case REG_TM3CNT_HI:
95 value &= 0x00C7;
96 GBATimerWriteTMCNT_HI(gba, 3, value);
97 break;
98
99 // Interrupts and misc
100 case REG_WAITCNT:
101 GBAAdjustWaitstates(&gba->memory, value);
102 break;
103 case REG_IE:
104 GBAWriteIE(gba, value);
105 break;
106 case REG_IF:
107 value = gba->memory.io[REG_IF >> 1] & ~value;
108 break;
109 case REG_IME:
110 GBAWriteIME(gba, value);
111 break;
112 case REG_HALTCNT:
113 value &= 0x80;
114 if (!value) {
115 GBAHalt(gba);
116 } else {
117 GBALog(GBA_LOG_STUB, "Stop unimplemented");
118 }
119 return;
120 default:
121 GBALog(GBA_LOG_STUB, "Stub I/O register write: %03x", address);
122 break;
123 }
124 }
125 gba->memory.io[address >> 1] = value;
126}
127
128void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
129 switch (address) {
130 case REG_DMA0SAD_LO:
131 GBAMemoryWriteDMASAD(&gba->memory, 0, value);
132 break;
133 case REG_DMA0DAD_LO:
134 GBAMemoryWriteDMADAD(&gba->memory, 0, value);
135 break;
136 case REG_DMA1SAD_LO:
137 GBAMemoryWriteDMASAD(&gba->memory, 1, value);
138 break;
139 case REG_DMA1DAD_LO:
140 GBAMemoryWriteDMADAD(&gba->memory, 1, value);
141 break;
142 case REG_DMA2SAD_LO:
143 GBAMemoryWriteDMASAD(&gba->memory, 2, value);
144 break;
145 case REG_DMA2DAD_LO:
146 GBAMemoryWriteDMADAD(&gba->memory, 2, value);
147 break;
148 case REG_DMA3SAD_LO:
149 GBAMemoryWriteDMASAD(&gba->memory, 3, value);
150 break;
151 case REG_DMA3DAD_LO:
152 GBAMemoryWriteDMADAD(&gba->memory, 3, value);
153 break;
154 default:
155 GBAIOWrite(gba, address, value & 0xFFFF);
156 GBAIOWrite(gba, address | 2, value >> 16);
157 return;
158 }
159 gba->memory.io[address >> 1] = value;
160 gba->memory.io[(address >> 1) + 1] = value >> 16;
161}
162
163uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
164 switch (address) {
165 case REG_DISPSTAT:
166 return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
167 break;
168
169 case REG_TM0CNT_LO:
170 GBATimerUpdateRegister(gba, 0);
171 break;
172 case REG_TM1CNT_LO:
173 GBATimerUpdateRegister(gba, 1);
174 break;
175 case REG_TM2CNT_LO:
176 GBATimerUpdateRegister(gba, 2);
177 break;
178 case REG_TM3CNT_LO:
179 GBATimerUpdateRegister(gba, 3);
180 break;
181
182 case REG_KEYINPUT:
183 if (gba->keySource) {
184 return 0x3FF ^ *gba->keySource;
185 }
186 break;
187
188 case REG_DMA0CNT_LO:
189 case REG_DMA1CNT_LO:
190 case REG_DMA2CNT_LO:
191 case REG_DMA3CNT_LO:
192 // Write-only register
193 return 0;
194 case REG_VCOUNT:
195 case REG_DMA0CNT_HI:
196 case REG_DMA1CNT_HI:
197 case REG_DMA2CNT_HI:
198 case REG_DMA3CNT_HI:
199 case REG_IE:
200 case REG_IF:
201 case REG_WAITCNT:
202 case REG_IME:
203 // Handled transparently by registers
204 break;
205 default:
206 GBALog(GBA_LOG_STUB, "Stub I/O register read: %03x", address);
207 break;
208 }
209 return gba->memory.io[address >> 1];
210}