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