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 GBAudioWriteNR11(&gb->audio, value & _registerMask[REG_NR11]);
100 value = 0;
101 }
102 break;
103 case REG_NR12:
104 if (gb->audio.enable) {
105 GBAudioWriteNR12(&gb->audio, value);
106 } else {
107 value = 0;
108 }
109 break;
110 case REG_NR13:
111 if (gb->audio.enable) {
112 GBAudioWriteNR13(&gb->audio, value);
113 } else {
114 value = 0;
115 }
116 break;
117 case REG_NR14:
118 if (gb->audio.enable) {
119 GBAudioWriteNR14(&gb->audio, value);
120 } else {
121 value = 0;
122 }
123 break;
124 case REG_NR21:
125 if (gb->audio.enable) {
126 GBAudioWriteNR21(&gb->audio, value);
127 } else {
128 GBAudioWriteNR21(&gb->audio, value & _registerMask[REG_NR21]);
129 value = 0;
130 }
131 break;
132 case REG_NR22:
133 if (gb->audio.enable) {
134 GBAudioWriteNR22(&gb->audio, value);
135 } else {
136 value = 0;
137 }
138 break;
139 case REG_NR23:
140 if (gb->audio.enable) {
141 GBAudioWriteNR23(&gb->audio, value);
142 } else {
143 value = 0;
144 }
145 break;
146 case REG_NR24:
147 if (gb->audio.enable) {
148 GBAudioWriteNR24(&gb->audio, value);
149 } else {
150 value = 0;
151 }
152 break;
153 case REG_NR30:
154 if (gb->audio.enable) {
155 GBAudioWriteNR30(&gb->audio, value);
156 } else {
157 value = 0;
158 }
159 break;
160 case REG_NR31:
161 if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
162 GBAudioWriteNR31(&gb->audio, value);
163 } else {
164 value = 0;
165 }
166 break;
167 case REG_NR32:
168 if (gb->audio.enable) {
169 GBAudioWriteNR32(&gb->audio, value);
170 } else {
171 value = 0;
172 }
173 break;
174 case REG_NR33:
175 if (gb->audio.enable) {
176 GBAudioWriteNR33(&gb->audio, value);
177 } else {
178 value = 0;
179 }
180 break;
181 case REG_NR34:
182 if (gb->audio.enable) {
183 GBAudioWriteNR34(&gb->audio, value);
184 } else {
185 value = 0;
186 }
187 break;
188 case REG_NR41:
189 if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
190 GBAudioWriteNR41(&gb->audio, value);
191 } else {
192 value = 0;
193 }
194 break;
195 case REG_NR42:
196 if (gb->audio.enable) {
197 GBAudioWriteNR42(&gb->audio, value);
198 } else {
199 value = 0;
200 }
201 break;
202 case REG_NR43:
203 if (gb->audio.enable) {
204 GBAudioWriteNR43(&gb->audio, value);
205 } else {
206 value = 0;
207 }
208 break;
209 case REG_NR44:
210 if (gb->audio.enable) {
211 GBAudioWriteNR44(&gb->audio, value);
212 } else {
213 value = 0;
214 }
215 break;
216 case REG_NR50:
217 if (gb->audio.enable) {
218 GBAudioWriteNR50(&gb->audio, value);
219 } else {
220 value = 0;
221 }
222 break;
223 case REG_NR51:
224 if (gb->audio.enable) {
225 GBAudioWriteNR51(&gb->audio, value);
226 } else {
227 value = 0;
228 }
229 break;
230 case REG_NR52:
231 GBAudioWriteNR52(&gb->audio, value);
232 value &= 0x80;
233 value |= gb->memory.io[REG_NR52] & 0x0F;
234 break;
235 case REG_WAVE_0:
236 case REG_WAVE_1:
237 case REG_WAVE_2:
238 case REG_WAVE_3:
239 case REG_WAVE_4:
240 case REG_WAVE_5:
241 case REG_WAVE_6:
242 case REG_WAVE_7:
243 case REG_WAVE_8:
244 case REG_WAVE_9:
245 case REG_WAVE_A:
246 case REG_WAVE_B:
247 case REG_WAVE_C:
248 case REG_WAVE_D:
249 case REG_WAVE_E:
250 case REG_WAVE_F:
251 if (!gb->audio.playingCh3) {
252 gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
253 } else if(gb->audio.ch3.readable) {
254 gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value;
255 }
256 break;
257 case REG_JOYP:
258 case REG_TIMA:
259 case REG_TMA:
260 case REG_LYC:
261 // Handled transparently by the registers
262 break;
263 case REG_TAC:
264 value = GBTimerUpdateTAC(&gb->timer, value);
265 break;
266 case REG_IF:
267 gb->memory.io[REG_IF] = value | 0xE0;
268 GBUpdateIRQs(gb);
269 return;
270 case REG_LCDC:
271 // TODO: handle GBC differences
272 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
273 GBVideoWriteLCDC(&gb->video, value);
274 break;
275 case REG_DMA:
276 GBMemoryDMA(gb, value << 8);
277 break;
278 case REG_SCY:
279 case REG_SCX:
280 case REG_WY:
281 case REG_WX:
282 case REG_BGP:
283 case REG_OBP0:
284 case REG_OBP1:
285 GBVideoProcessDots(&gb->video);
286 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
287 break;
288 case REG_STAT:
289 GBVideoWriteSTAT(&gb->video, value);
290 break;
291 case REG_IE:
292 gb->memory.ie = value;
293 GBUpdateIRQs(gb);
294 return;
295 default:
296 mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
297 if (address >= GB_SIZE_IO) {
298 return;
299 }
300 break;
301 }
302 gb->memory.io[address] = value;
303}
304
305static uint8_t _readKeys(struct GB* gb) {
306 uint8_t keys = *gb->keySource;
307 switch (gb->memory.io[REG_JOYP] & 0x30) {
308 case 0x20:
309 keys >>= 4;
310 break;
311 case 0x10:
312 break;
313 default:
314 // ???
315 keys = 0;
316 break;
317 }
318 return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
319}
320
321uint8_t GBIORead(struct GB* gb, unsigned address) {
322 switch (address) {
323 case REG_JOYP:
324 return _readKeys(gb);
325 case REG_SB:
326 case REG_SC:
327 // TODO
328 break;
329 case REG_IE:
330 return gb->memory.ie;
331 case REG_WAVE_0:
332 case REG_WAVE_1:
333 case REG_WAVE_2:
334 case REG_WAVE_3:
335 case REG_WAVE_4:
336 case REG_WAVE_5:
337 case REG_WAVE_6:
338 case REG_WAVE_7:
339 case REG_WAVE_8:
340 case REG_WAVE_9:
341 case REG_WAVE_A:
342 case REG_WAVE_B:
343 case REG_WAVE_C:
344 case REG_WAVE_D:
345 case REG_WAVE_E:
346 case REG_WAVE_F:
347 if (gb->audio.playingCh3) {
348 if (gb->audio.ch3.readable) {
349 return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
350 } else {
351 return 0xFF;
352 }
353 } else {
354 return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
355 }
356 break;
357 case REG_IF:
358 case REG_NR10:
359 case REG_NR11:
360 case REG_NR12:
361 case REG_NR14:
362 case REG_NR21:
363 case REG_NR22:
364 case REG_NR24:
365 case REG_NR30:
366 case REG_NR32:
367 case REG_NR34:
368 case REG_NR41:
369 case REG_NR42:
370 case REG_NR43:
371 case REG_NR44:
372 case REG_NR50:
373 case REG_NR51:
374 case REG_NR52:
375 case REG_DIV:
376 case REG_TIMA:
377 case REG_TMA:
378 case REG_TAC:
379 case REG_STAT:
380 case REG_LCDC:
381 case REG_SCY:
382 case REG_SCX:
383 case REG_LY:
384 case REG_LYC:
385 case REG_BGP:
386 case REG_OBP0:
387 case REG_OBP1:
388 case REG_WY:
389 case REG_WX:
390 // Handled transparently by the registers
391 break;
392 default:
393 mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
394 return 0xFF;
395 }
396 return gb->memory.io[address] | _registerMask[address];
397}