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 // NR41 is exempt, for some reason
188 GBAudioWriteNR41(&gb->audio, value);
189 break;
190 case REG_NR42:
191 if (gb->audio.enable) {
192 GBAudioWriteNR42(&gb->audio, value);
193 } else {
194 value = 0;
195 }
196 break;
197 case REG_NR43:
198 if (gb->audio.enable) {
199 GBAudioWriteNR43(&gb->audio, value);
200 } else {
201 value = 0;
202 }
203 break;
204 case REG_NR44:
205 if (gb->audio.enable) {
206 GBAudioWriteNR44(&gb->audio, value);
207 } else {
208 value = 0;
209 }
210 break;
211 case REG_NR50:
212 if (gb->audio.enable) {
213 GBAudioWriteNR50(&gb->audio, value);
214 } else {
215 value = 0;
216 }
217 break;
218 case REG_NR51:
219 if (gb->audio.enable) {
220 GBAudioWriteNR51(&gb->audio, value);
221 } else {
222 value = 0;
223 }
224 break;
225 case REG_NR52:
226 GBAudioWriteNR52(&gb->audio, value);
227 value &= 0x80;
228 value |= gb->memory.io[REG_NR52] & 0x0F;
229 break;
230 case REG_WAVE_0:
231 case REG_WAVE_1:
232 case REG_WAVE_2:
233 case REG_WAVE_3:
234 case REG_WAVE_4:
235 case REG_WAVE_5:
236 case REG_WAVE_6:
237 case REG_WAVE_7:
238 case REG_WAVE_8:
239 case REG_WAVE_9:
240 case REG_WAVE_A:
241 case REG_WAVE_B:
242 case REG_WAVE_C:
243 case REG_WAVE_D:
244 case REG_WAVE_E:
245 case REG_WAVE_F:
246 if (!gb->audio.playingCh3 || gb->audio.ch3.readable) {
247 gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
248 }
249 break;
250 case REG_JOYP:
251 case REG_TIMA:
252 case REG_TMA:
253 case REG_LYC:
254 // Handled transparently by the registers
255 break;
256 case REG_TAC:
257 value = GBTimerUpdateTAC(&gb->timer, value);
258 break;
259 case REG_IF:
260 gb->memory.io[REG_IF] = value | 0xE0;
261 GBUpdateIRQs(gb);
262 return;
263 case REG_LCDC:
264 // TODO: handle GBC differences
265 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
266 GBVideoWriteLCDC(&gb->video, value);
267 break;
268 case REG_DMA:
269 GBMemoryDMA(gb, value << 8);
270 break;
271 case REG_SCY:
272 case REG_SCX:
273 case REG_WY:
274 case REG_WX:
275 case REG_BGP:
276 case REG_OBP0:
277 case REG_OBP1:
278 GBVideoProcessDots(&gb->video);
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_WAVE_0:
325 case REG_WAVE_1:
326 case REG_WAVE_2:
327 case REG_WAVE_3:
328 case REG_WAVE_4:
329 case REG_WAVE_5:
330 case REG_WAVE_6:
331 case REG_WAVE_7:
332 case REG_WAVE_8:
333 case REG_WAVE_9:
334 case REG_WAVE_A:
335 case REG_WAVE_B:
336 case REG_WAVE_C:
337 case REG_WAVE_D:
338 case REG_WAVE_E:
339 case REG_WAVE_F:
340 if (gb->audio.playingCh3) {
341 if (gb->audio.ch3.readable) {
342 return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
343 } else {
344 return 0xFF;
345 }
346 } else {
347 return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
348 }
349 break;
350 case REG_IF:
351 case REG_NR10:
352 case REG_NR11:
353 case REG_NR12:
354 case REG_NR14:
355 case REG_NR21:
356 case REG_NR22:
357 case REG_NR24:
358 case REG_NR30:
359 case REG_NR32:
360 case REG_NR34:
361 case REG_NR41:
362 case REG_NR42:
363 case REG_NR43:
364 case REG_NR44:
365 case REG_NR50:
366 case REG_NR51:
367 case REG_NR52:
368 case REG_DIV:
369 case REG_TIMA:
370 case REG_TMA:
371 case REG_TAC:
372 case REG_STAT:
373 case REG_LCDC:
374 case REG_SCY:
375 case REG_SCX:
376 case REG_LY:
377 case REG_LYC:
378 case REG_BGP:
379 case REG_OBP0:
380 case REG_OBP1:
381 case REG_WY:
382 case REG_WX:
383 // Handled transparently by the registers
384 break;
385 default:
386 mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
387 return 0xFF;
388 }
389 return gb->memory.io[address] | _registerMask[address];
390}