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
10void GBIOInit(struct GB* gb) {
11 memset(gb->memory.io, 0, sizeof(gb->memory.io));
12}
13
14void GBIOReset(struct GB* gb) {
15 memset(gb->memory.io, 0, sizeof(gb->memory.io));
16
17 GBIOWrite(gb, 0x05, 0);
18 GBIOWrite(gb, 0x06, 0);
19 GBIOWrite(gb, 0x07, 0);
20 GBIOWrite(gb, 0x10, 0x80);
21 GBIOWrite(gb, 0x11, 0xBF);
22 GBIOWrite(gb, 0x12, 0xF3);
23 GBIOWrite(gb, 0x12, 0xF3);
24 GBIOWrite(gb, 0x14, 0xBF);
25 GBIOWrite(gb, 0x16, 0x3F);
26 GBIOWrite(gb, 0x17, 0x00);
27 GBIOWrite(gb, 0x19, 0xBF);
28 GBIOWrite(gb, 0x1A, 0x7F);
29 GBIOWrite(gb, 0x1B, 0xFF);
30 GBIOWrite(gb, 0x1C, 0x9F);
31 GBIOWrite(gb, 0x1E, 0xBF);
32 GBIOWrite(gb, 0x20, 0xFF);
33 GBIOWrite(gb, 0x21, 0x00);
34 GBIOWrite(gb, 0x22, 0x00);
35 GBIOWrite(gb, 0x23, 0xBF);
36 GBIOWrite(gb, 0x24, 0x77);
37 GBIOWrite(gb, 0x25, 0xF3);
38 GBIOWrite(gb, 0x26, 0xF1);
39 GBIOWrite(gb, 0x40, 0x91);
40 GBIOWrite(gb, 0x42, 0x00);
41 GBIOWrite(gb, 0x43, 0x00);
42 GBIOWrite(gb, 0x45, 0x00);
43 GBIOWrite(gb, 0x47, 0xFC);
44 GBIOWrite(gb, 0x48, 0xFF);
45 GBIOWrite(gb, 0x49, 0xFF);
46 GBIOWrite(gb, 0x4A, 0x00);
47 GBIOWrite(gb, 0x4B, 0x00);
48 GBIOWrite(gb, 0xFF, 0x00);
49}
50
51void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
52 switch (address) {
53 case REG_DIV:
54 GBTimerDivReset(&gb->timer);
55 return;
56 case REG_TIMA:
57 // ???
58 return;
59 case REG_TMA:
60 // Handled transparently by the registers
61 break;
62 case REG_TAC:
63 value = GBTimerUpdateTAC(&gb->timer, value);
64 break;
65 case REG_IF:
66 gb->memory.io[REG_IF] = value | 0xE0;
67 GBUpdateIRQs(gb);
68 return;
69 case REG_LCDC:
70 // TODO: handle GBC differences
71 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
72 GBVideoWriteLCDC(&gb->video, value);
73 break;
74 case REG_SCY:
75 case REG_SCX:
76 case REG_WY:
77 case REG_WX:
78 case REG_BGP:
79 case REG_OBP0:
80 case REG_OBP1:
81 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
82 break;
83 case REG_STAT:
84 GBVideoWriteSTAT(&gb->video, value);
85 break;
86 case REG_IE:
87 gb->memory.ie = value;
88 GBUpdateIRQs(gb);
89 return;
90 default:
91 // TODO: Log
92 if (address >= GB_SIZE_IO) {
93 return;
94 }
95 break;
96 }
97 gb->memory.io[address] = value;
98}
99
100static uint8_t _readKeys(struct GB* gb) {
101 uint8_t keys = *gb->keySource;
102 switch (gb->memory.io[REG_JOYP] & 0x30) {
103 case 0x20:
104 keys >>= 4;
105 break;
106 case 0x10:
107 break;
108 default:
109 // ???
110 keys = 0;
111 break;
112 }
113 return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
114}
115
116uint8_t GBIORead(struct GB* gb, unsigned address) {
117 switch (address) {
118 case REG_JOYP:
119 return _readKeys(gb);
120 case REG_IF:
121 break;
122 case REG_IE:
123 return gb->memory.ie;
124 case REG_DIV:
125 case REG_TIMA:
126 case REG_TMA:
127 case REG_TAC:
128 case REG_LY:
129 // Handled transparently by the registers
130 break;
131 default:
132 // TODO: Log
133 if (address >= GB_SIZE_IO) {
134 return 0;
135 }
136 break;
137 }
138 return gb->memory.io[address];
139}