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);
11
12void GBIOInit(struct GB* gb) {
13 memset(gb->memory.io, 0, sizeof(gb->memory.io));
14}
15
16void GBIOReset(struct GB* gb) {
17 memset(gb->memory.io, 0, sizeof(gb->memory.io));
18
19 GBIOWrite(gb, 0x05, 0);
20 GBIOWrite(gb, 0x06, 0);
21 GBIOWrite(gb, 0x07, 0);
22 GBIOWrite(gb, 0x10, 0x80);
23 GBIOWrite(gb, 0x11, 0xBF);
24 GBIOWrite(gb, 0x12, 0xF3);
25 GBIOWrite(gb, 0x12, 0xF3);
26 GBIOWrite(gb, 0x14, 0xBF);
27 GBIOWrite(gb, 0x16, 0x3F);
28 GBIOWrite(gb, 0x17, 0x00);
29 GBIOWrite(gb, 0x19, 0xBF);
30 GBIOWrite(gb, 0x1A, 0x7F);
31 GBIOWrite(gb, 0x1B, 0xFF);
32 GBIOWrite(gb, 0x1C, 0x9F);
33 GBIOWrite(gb, 0x1E, 0xBF);
34 GBIOWrite(gb, 0x20, 0xFF);
35 GBIOWrite(gb, 0x21, 0x00);
36 GBIOWrite(gb, 0x22, 0x00);
37 GBIOWrite(gb, 0x23, 0xBF);
38 GBIOWrite(gb, 0x24, 0x77);
39 GBIOWrite(gb, 0x25, 0xF3);
40 GBIOWrite(gb, 0x26, 0xF1);
41 GBIOWrite(gb, 0x40, 0x91);
42 GBIOWrite(gb, 0x42, 0x00);
43 GBIOWrite(gb, 0x43, 0x00);
44 GBIOWrite(gb, 0x45, 0x00);
45 GBIOWrite(gb, 0x47, 0xFC);
46 GBIOWrite(gb, 0x48, 0xFF);
47 GBIOWrite(gb, 0x49, 0xFF);
48 GBIOWrite(gb, 0x4A, 0x00);
49 GBIOWrite(gb, 0x4B, 0x00);
50 GBIOWrite(gb, 0xFF, 0x00);
51}
52
53void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
54 switch (address) {
55 case REG_DIV:
56 GBTimerDivReset(&gb->timer);
57 return;
58 case REG_NR10:
59 GBAudioWriteNR10(&gb->audio, value);
60 break;
61 case REG_NR11:
62 GBAudioWriteNR11(&gb->audio, value);
63 break;
64 case REG_NR12:
65 GBAudioWriteNR12(&gb->audio, value);
66 break;
67 case REG_NR13:
68 GBAudioWriteNR13(&gb->audio, value);
69 break;
70 case REG_NR14:
71 GBAudioWriteNR14(&gb->audio, value);
72 break;
73 case REG_NR21:
74 GBAudioWriteNR21(&gb->audio, value);
75 break;
76 case REG_NR22:
77 GBAudioWriteNR22(&gb->audio, value);
78 break;
79 case REG_NR23:
80 GBAudioWriteNR23(&gb->audio, value);
81 break;
82 case REG_NR24:
83 GBAudioWriteNR24(&gb->audio, value);
84 break;
85 case REG_NR30:
86 GBAudioWriteNR30(&gb->audio, value);
87 break;
88 case REG_NR31:
89 GBAudioWriteNR31(&gb->audio, value);
90 break;
91 case REG_NR32:
92 GBAudioWriteNR32(&gb->audio, value);
93 break;
94 case REG_NR33:
95 GBAudioWriteNR33(&gb->audio, value);
96 break;
97 case REG_NR34:
98 GBAudioWriteNR34(&gb->audio, value);
99 break;
100 case REG_NR41:
101 GBAudioWriteNR41(&gb->audio, value);
102 break;
103 case REG_NR42:
104 GBAudioWriteNR42(&gb->audio, value);
105 break;
106 case REG_NR43:
107 GBAudioWriteNR43(&gb->audio, value);
108 break;
109 case REG_NR44:
110 GBAudioWriteNR44(&gb->audio, value);
111 break;
112 case REG_NR50:
113 GBAudioWriteNR50(&gb->audio, value);
114 break;
115 case REG_NR51:
116 GBAudioWriteNR51(&gb->audio, value);
117 break;
118 case REG_NR52:
119 GBAudioWriteNR52(&gb->audio, value);
120 break;
121 case REG_WAVE_0:
122 case REG_WAVE_1:
123 case REG_WAVE_2:
124 case REG_WAVE_3:
125 case REG_WAVE_4:
126 case REG_WAVE_5:
127 case REG_WAVE_6:
128 case REG_WAVE_7:
129 case REG_WAVE_8:
130 case REG_WAVE_9:
131 case REG_WAVE_A:
132 case REG_WAVE_B:
133 case REG_WAVE_C:
134 case REG_WAVE_D:
135 case REG_WAVE_E:
136 case REG_WAVE_F:
137 ((uint8_t*) gb->audio.ch3.wavedata)[address - REG_WAVE_0] = value; // TODO: Big endian
138 break;
139 case REG_JOYP:
140 case REG_TIMA:
141 case REG_TMA:
142 case REG_LYC:
143 // Handled transparently by the registers
144 break;
145 case REG_TAC:
146 value = GBTimerUpdateTAC(&gb->timer, value);
147 break;
148 case REG_IF:
149 gb->memory.io[REG_IF] = value | 0xE0;
150 GBUpdateIRQs(gb);
151 return;
152 case REG_LCDC:
153 // TODO: handle GBC differences
154 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
155 GBVideoWriteLCDC(&gb->video, value);
156 break;
157 case REG_DMA:
158 GBMemoryDMA(gb, value << 8);
159 break;
160 case REG_SCY:
161 case REG_SCX:
162 case REG_WY:
163 case REG_WX:
164 case REG_BGP:
165 case REG_OBP0:
166 case REG_OBP1:
167 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
168 break;
169 case REG_STAT:
170 GBVideoWriteSTAT(&gb->video, value);
171 break;
172 case REG_IE:
173 gb->memory.ie = value;
174 GBUpdateIRQs(gb);
175 return;
176 default:
177 mLOG(GB_MBC, STUB, "Writing to unknown register FF%02X:%02X", address, value);
178 if (address >= GB_SIZE_IO) {
179 return;
180 }
181 break;
182 }
183 gb->memory.io[address] = value;
184}
185
186static uint8_t _readKeys(struct GB* gb) {
187 uint8_t keys = *gb->keySource;
188 switch (gb->memory.io[REG_JOYP] & 0x30) {
189 case 0x20:
190 keys >>= 4;
191 break;
192 case 0x10:
193 break;
194 default:
195 // ???
196 keys = 0;
197 break;
198 }
199 return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
200}
201
202uint8_t GBIORead(struct GB* gb, unsigned address) {
203 switch (address) {
204 case REG_JOYP:
205 return _readKeys(gb);
206 case REG_IF:
207 break;
208 case REG_IE:
209 return gb->memory.ie;
210 case REG_DIV:
211 case REG_TIMA:
212 case REG_TMA:
213 case REG_TAC:
214 case REG_STAT:
215 case REG_LCDC:
216 case REG_SCY:
217 case REG_SCX:
218 case REG_LY:
219 case REG_LYC:
220 // Handled transparently by the registers
221 break;
222 default:
223 mLOG(GB_MBC, STUB, "Reading from unknown register FF%02X", address);
224 if (address >= GB_SIZE_IO) {
225 return 0;
226 }
227 break;
228 }
229 return gb->memory.io[address];
230}