src/gb/io.c (view raw)
1/* Copyright (c) 2013-2016 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "io.h"
7
8#include "gb/gb.h"
9
10mLOG_DEFINE_CATEGORY(GB_IO, "GB I/O");
11
12const static uint8_t _registerMask[] = {
13 [REG_SC] = 0x7E, // TODO: GBC differences
14 [REG_IF] = 0xE0,
15 [REG_TAC] = 0xF8,
16 [REG_NR10] = 0x80,
17 [REG_NR11] = 0x3F,
18 [REG_NR12] = 0x00,
19 [REG_NR13] = 0xFF,
20 [REG_NR14] = 0xBF,
21 [REG_NR21] = 0x3F,
22 [REG_NR22] = 0x00,
23 [REG_NR23] = 0xFF,
24 [REG_NR24] = 0xBF,
25 [REG_NR30] = 0x7F,
26 [REG_NR31] = 0xFF,
27 [REG_NR32] = 0x9F,
28 [REG_NR33] = 0xFF,
29 [REG_NR34] = 0xBF,
30 [REG_NR41] = 0xFF,
31 [REG_NR42] = 0x00,
32 [REG_NR43] = 0x00,
33 [REG_NR44] = 0xBF,
34 [REG_NR50] = 0x00,
35 [REG_NR51] = 0x00,
36 [REG_NR52] = 0x70,
37 [REG_STAT] = 0x80,
38 [REG_IE] = 0xE0,
39};
40
41void GBIOInit(struct GB* gb) {
42 memset(gb->memory.io, 0, sizeof(gb->memory.io));
43}
44
45void GBIOReset(struct GB* gb) {
46 memset(gb->memory.io, 0, sizeof(gb->memory.io));
47
48 GBIOWrite(gb, REG_TIMA, 0);
49 GBIOWrite(gb, REG_TMA, 0);
50 GBIOWrite(gb, REG_TAC, 0);
51 GBIOWrite(gb, REG_IF, 1);
52 GBIOWrite(gb, REG_NR52, 0xF1);
53 GBIOWrite(gb, REG_NR10, 0x80);
54 GBIOWrite(gb, REG_NR11, 0xBF);
55 GBIOWrite(gb, REG_NR12, 0xF3);
56 GBIOWrite(gb, REG_NR13, 0xF3);
57 GBIOWrite(gb, REG_NR14, 0xBF);
58 GBIOWrite(gb, REG_NR21, 0x3F);
59 GBIOWrite(gb, REG_NR22, 0x00);
60 GBIOWrite(gb, REG_NR24, 0xBF);
61 GBIOWrite(gb, REG_NR30, 0x7F);
62 GBIOWrite(gb, REG_NR31, 0xFF);
63 GBIOWrite(gb, REG_NR32, 0x9F);
64 GBIOWrite(gb, REG_NR34, 0xBF);
65 GBIOWrite(gb, REG_NR41, 0xFF);
66 GBIOWrite(gb, REG_NR42, 0x00);
67 GBIOWrite(gb, REG_NR43, 0x00);
68 GBIOWrite(gb, REG_NR44, 0xBF);
69 GBIOWrite(gb, REG_NR50, 0x77);
70 GBIOWrite(gb, REG_NR51, 0xF3);
71 GBIOWrite(gb, REG_LCDC, 0x91);
72 GBIOWrite(gb, REG_SCY, 0x00);
73 GBIOWrite(gb, REG_SCX, 0x00);
74 GBIOWrite(gb, REG_LYC, 0x00);
75 GBIOWrite(gb, REG_BGP, 0xFC);
76 GBIOWrite(gb, REG_OBP0, 0xFF);
77 GBIOWrite(gb, REG_OBP1, 0xFF);
78 GBIOWrite(gb, REG_WY, 0x00);
79 GBIOWrite(gb, REG_WX, 0x00);
80 GBIOWrite(gb, REG_IE, 0x00);
81}
82
83void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
84 switch (address) {
85 case REG_DIV:
86 GBTimerDivReset(&gb->timer);
87 return;
88 case REG_NR10:
89 if (gb->audio.enable) {
90 GBAudioWriteNR10(&gb->audio, value);
91 } else {
92 value = 0;
93 }
94 break;
95 case REG_NR11:
96 if (gb->audio.enable) {
97 GBAudioWriteNR11(&gb->audio, value);
98 } else {
99 value = 0;
100 }
101 break;
102 case REG_NR12:
103 if (gb->audio.enable) {
104 GBAudioWriteNR12(&gb->audio, value);
105 } else {
106 value = 0;
107 }
108 break;
109 case REG_NR13:
110 if (gb->audio.enable) {
111 GBAudioWriteNR13(&gb->audio, value);
112 } else {
113 value = 0;
114 }
115 break;
116 case REG_NR14:
117 if (gb->audio.enable) {
118 GBAudioWriteNR14(&gb->audio, value);
119 } else {
120 value = 0;
121 }
122 break;
123 case REG_NR21:
124 if (gb->audio.enable) {
125 GBAudioWriteNR21(&gb->audio, value);
126 } else {
127 value = 0;
128 }
129 break;
130 case REG_NR22:
131 if (gb->audio.enable) {
132 GBAudioWriteNR22(&gb->audio, value);
133 } else {
134 value = 0;
135 }
136 break;
137 case REG_NR23:
138 if (gb->audio.enable) {
139 GBAudioWriteNR23(&gb->audio, value);
140 } else {
141 value = 0;
142 }
143 break;
144 case REG_NR24:
145 if (gb->audio.enable) {
146 GBAudioWriteNR24(&gb->audio, value);
147 } else {
148 value = 0;
149 }
150 break;
151 case REG_NR30:
152 if (gb->audio.enable) {
153 GBAudioWriteNR30(&gb->audio, value);
154 } else {
155 value = 0;
156 }
157 break;
158 case REG_NR31:
159 if (gb->audio.enable) {
160 GBAudioWriteNR31(&gb->audio, value);
161 } else {
162 value = 0;
163 }
164 break;
165 case REG_NR32:
166 if (gb->audio.enable) {
167 GBAudioWriteNR32(&gb->audio, value);
168 } else {
169 value = 0;
170 }
171 break;
172 case REG_NR33:
173 if (gb->audio.enable) {
174 GBAudioWriteNR33(&gb->audio, value);
175 } else {
176 value = 0;
177 }
178 break;
179 case REG_NR34:
180 if (gb->audio.enable) {
181 GBAudioWriteNR34(&gb->audio, value);
182 } else {
183 value = 0;
184 }
185 break;
186 case REG_NR41:
187 if (gb->audio.enable) {
188 GBAudioWriteNR41(&gb->audio, value);
189 } else {
190 value = 0;
191 }
192 break;
193 case REG_NR42:
194 if (gb->audio.enable) {
195 GBAudioWriteNR42(&gb->audio, value);
196 } else {
197 value = 0;
198 }
199 break;
200 case REG_NR43:
201 if (gb->audio.enable) {
202 GBAudioWriteNR43(&gb->audio, value);
203 } else {
204 value = 0;
205 }
206 break;
207 case REG_NR44:
208 if (gb->audio.enable) {
209 GBAudioWriteNR44(&gb->audio, value);
210 } else {
211 value = 0;
212 }
213 break;
214 case REG_NR50:
215 if (gb->audio.enable) {
216 GBAudioWriteNR50(&gb->audio, value);
217 } else {
218 value = 0;
219 }
220 break;
221 case REG_NR51:
222 if (gb->audio.enable) {
223 GBAudioWriteNR51(&gb->audio, value);
224 } else {
225 value = 0;
226 }
227 break;
228 case REG_NR52:
229 GBAudioWriteNR52(&gb->audio, value);
230 value &= 0x80;
231 value |= gb->memory.io[REG_NR52] & 0x0F;
232 break;
233 case REG_WAVE_0:
234 case REG_WAVE_1:
235 case REG_WAVE_2:
236 case REG_WAVE_3:
237 case REG_WAVE_4:
238 case REG_WAVE_5:
239 case REG_WAVE_6:
240 case REG_WAVE_7:
241 case REG_WAVE_8:
242 case REG_WAVE_9:
243 case REG_WAVE_A:
244 case REG_WAVE_B:
245 case REG_WAVE_C:
246 case REG_WAVE_D:
247 case REG_WAVE_E:
248 case REG_WAVE_F:
249 ((uint8_t*) gb->audio.ch3.wavedata)[address - REG_WAVE_0] = value; // TODO: Big endian
250 break;
251 case REG_JOYP:
252 case REG_TIMA:
253 case REG_TMA:
254 case REG_LYC:
255 // Handled transparently by the registers
256 break;
257 case REG_TAC:
258 value = GBTimerUpdateTAC(&gb->timer, value);
259 break;
260 case REG_IF:
261 gb->memory.io[REG_IF] = value | 0xE0;
262 GBUpdateIRQs(gb);
263 return;
264 case REG_LCDC:
265 // TODO: handle GBC differences
266 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
267 GBVideoWriteLCDC(&gb->video, value);
268 break;
269 case REG_DMA:
270 GBMemoryDMA(gb, value << 8);
271 break;
272 case REG_SCY:
273 case REG_SCX:
274 case REG_WY:
275 case REG_WX:
276 case REG_BGP:
277 case REG_OBP0:
278 case REG_OBP1:
279 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
280 break;
281 case REG_STAT:
282 GBVideoWriteSTAT(&gb->video, value);
283 break;
284 case REG_IE:
285 gb->memory.ie = value;
286 GBUpdateIRQs(gb);
287 return;
288 default:
289 mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
290 if (address >= GB_SIZE_IO) {
291 return;
292 }
293 break;
294 }
295 gb->memory.io[address] = value;
296}
297
298static uint8_t _readKeys(struct GB* gb) {
299 uint8_t keys = *gb->keySource;
300 switch (gb->memory.io[REG_JOYP] & 0x30) {
301 case 0x20:
302 keys >>= 4;
303 break;
304 case 0x10:
305 break;
306 default:
307 // ???
308 keys = 0;
309 break;
310 }
311 return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
312}
313
314uint8_t GBIORead(struct GB* gb, unsigned address) {
315 switch (address) {
316 case REG_JOYP:
317 return _readKeys(gb);
318 case REG_SB:
319 case REG_SC:
320 // TODO
321 break;
322 case REG_IE:
323 return gb->memory.ie;
324 case REG_IF:
325 case REG_NR10:
326 case REG_NR11:
327 case REG_NR12:
328 case REG_NR14:
329 case REG_NR21:
330 case REG_NR22:
331 case REG_NR24:
332 case REG_NR30:
333 case REG_NR32:
334 case REG_NR34:
335 case REG_NR41:
336 case REG_NR42:
337 case REG_NR43:
338 case REG_NR44:
339 case REG_NR50:
340 case REG_NR51:
341 case REG_NR52:
342 case REG_WAVE_0:
343 case REG_WAVE_1:
344 case REG_WAVE_2:
345 case REG_WAVE_3:
346 case REG_WAVE_4:
347 case REG_WAVE_5:
348 case REG_WAVE_6:
349 case REG_WAVE_7:
350 case REG_WAVE_8:
351 case REG_WAVE_9:
352 case REG_WAVE_A:
353 case REG_WAVE_B:
354 case REG_WAVE_C:
355 case REG_WAVE_D:
356 case REG_WAVE_E:
357 case REG_WAVE_F:
358 case REG_DIV:
359 case REG_TIMA:
360 case REG_TMA:
361 case REG_TAC:
362 case REG_STAT:
363 case REG_LCDC:
364 case REG_SCY:
365 case REG_SCX:
366 case REG_LY:
367 case REG_LYC:
368 case REG_BGP:
369 case REG_OBP0:
370 case REG_OBP1:
371 case REG_WY:
372 case REG_WX:
373 // Handled transparently by the registers
374 break;
375 default:
376 mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
377 return 0xFF;
378 }
379 return gb->memory.io[address] | _registerMask[address];
380}