2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
13 #define BIT_IBF_A 0x20 // PC5
14 #define BIT_STB_A 0x10 // PC4
15 #define BIT_STB_B 0x04 // PC2
16 #define BIT_IBF_B 0x02 // PC1
18 #define BIT_OBF_A 0x80 // PC7
19 #define BIT_ACK_A 0x40 // PC6
20 #define BIT_ACK_B 0x04 // PC2
21 #define BIT_OBF_B 0x02 // PC1
23 #define BIT_INTR_A 0x08 // PC3
24 #define BIT_INTR_B 0x01 // PC0
26 void I8255::initialize()
29 __I8255_AUTO_HAND_SHAKE = osd->check_feature(_T("I8255_AUTO_HAND_SHAKE"));
34 for(int i = 0; i < 3; i++) {
41 void I8255::write_io8(uint32_t addr, uint32_t data)
49 if(port[ch].wreg != data || port[ch].first) {
50 write_signals(&port[ch].outputs, port[ch].wreg = data);
51 port[ch].first = false;
53 //#ifndef I8255_AUTO_HAND_SHAKE
54 if(__I8255_AUTO_HAND_SHAKE) break;
56 if(port[0].mode == 1 || port[0].mode == 2) {
57 uint32_t val = port[2].wreg & ~BIT_OBF_A;
58 if(port[2].wreg & BIT_ACK_A) {
64 if(port[1].mode == 1) {
65 uint32_t val = port[2].wreg & ~BIT_OBF_B;
66 if(port[2].wreg & BIT_ACK_B) {
76 port[0].mode = (data & 0x40) ? 2 : ((data >> 5) & 1);
77 port[0].rmask = (port[0].mode == 2) ? 0xff : (data & 0x10) ? 0xff : 0;
78 port[1].mode = (data >> 2) & 1;
79 port[1].rmask = (data & 2) ? 0xff : 0;
80 port[2].rmask = ((data & 8) ? 0xf0 : 0) | ((data & 1) ? 0xf : 0);
82 if(clear_ports_by_cmdreg) {
87 // setup control signals
88 if(port[0].mode != 0 || port[1].mode != 0) {
89 uint32_t val = port[2].wreg;
90 if(port[0].mode == 1 || port[0].mode == 2) {
95 if(port[1].mode == 1) {
96 if(port[1].mode == 0xff) {
106 uint32_t val = port[2].wreg;
107 int bit = (data >> 1) & 7;
119 uint32_t I8255::read_io8(uint32_t addr)
128 if(port[0].mode == 1 || port[0].mode == 2) {
129 uint32_t val = port[2].wreg & ~BIT_IBF_A;
130 if(port[2].wreg & BIT_STB_A) {
136 if(port[1].mode == 1) {
137 uint32_t val = port[2].wreg & ~BIT_IBF_B;
138 if(port[2].wreg & BIT_STB_B) {
144 return (port[ch].rreg & port[ch].rmask) | (port[ch].wreg & ~port[ch].rmask);
149 void I8255::write_signal(int id, uint32_t data, uint32_t mask)
152 case SIG_I8255_PORT_A:
153 port[0].rreg = (port[0].rreg & ~mask) | (data & mask);
154 //#ifdef I8255_AUTO_HAND_SHAKE
155 if(!__I8255_AUTO_HAND_SHAKE) break;
156 if(port[0].mode == 1 || port[0].mode == 2) {
157 uint32_t val = port[2].wreg | BIT_IBF_A;
158 if(port[2].wreg & BIT_STB_A) {
165 case SIG_I8255_PORT_B:
166 port[1].rreg = (port[1].rreg & ~mask) | (data & mask);
167 //#ifdef I8255_AUTO_HAND_SHAKE
168 if(!__I8255_AUTO_HAND_SHAKE) break;
169 if(port[1].mode == 1) {
170 uint32_t val = port[2].wreg | BIT_IBF_B;
171 if(port[2].wreg & BIT_STB_B) {
178 case SIG_I8255_PORT_C:
179 //#ifndef I8255_AUTO_HAND_SHAKE
180 if(!__I8255_AUTO_HAND_SHAKE) {
181 if(port[0].mode == 1 || port[0].mode == 2) {
182 if(mask & BIT_STB_A) {
183 if((port[2].rreg & BIT_STB_A) && !(data & BIT_STB_A)) {
184 write_io8(2, port[2].wreg | BIT_IBF_A);
185 } else if(!(port[2].rreg & BIT_STB_A) && (data & BIT_STB_A)) {
186 if(port[2].wreg & BIT_STB_A) {
187 write_io8(2, port[2].wreg | BIT_INTR_A);
191 if(mask & BIT_ACK_A) {
192 if((port[2].rreg & BIT_ACK_A) && !(data & BIT_ACK_A)) {
193 write_io8(2, port[2].wreg | BIT_OBF_A);
194 } else if(!(port[2].rreg & BIT_ACK_A) && (data & BIT_ACK_A)) {
195 if(port[2].wreg & BIT_ACK_A) {
196 write_io8(2, port[2].wreg | BIT_INTR_A);
201 if(port[1].mode == 1) {
202 if(port[0].rmask == 0xff) {
203 if(mask & BIT_STB_B) {
204 if((port[2].rreg & BIT_STB_B) && !(data & BIT_STB_B)) {
205 write_io8(2, port[2].wreg | BIT_IBF_B);
206 } else if(!(port[2].rreg & BIT_STB_B) && (data & BIT_STB_B)) {
207 if(port[2].wreg & BIT_STB_B) {
208 write_io8(2, port[2].wreg | BIT_INTR_B);
213 if(mask & BIT_ACK_B) {
214 if((port[2].rreg & BIT_ACK_B) && !(data & BIT_ACK_B)) {
215 write_io8(2, port[2].wreg | BIT_OBF_B);
216 } else if(!(port[2].rreg & BIT_ACK_B) && (data & BIT_ACK_B)) {
217 if(port[2].wreg & BIT_ACK_B) {
218 write_io8(2, port[2].wreg | BIT_INTR_B);
226 port[2].rreg = (port[2].rreg & ~mask) | (data & mask);
231 uint32_t I8255::read_signal(int id)
234 case SIG_I8255_PORT_A:
236 case SIG_I8255_PORT_B:
238 case SIG_I8255_PORT_C:
244 #define STATE_VERSION 1
246 bool I8255::process_state(FILEIO* state_fio, bool loading)
248 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
251 if(!state_fio->StateCheckInt32(this_device_id)) {
254 for(int i = 0; i < 3; i++) {
255 state_fio->StateValue(port[i].wreg);
256 state_fio->StateValue(port[i].rreg);
257 state_fio->StateValue(port[i].rmask);
258 state_fio->StateValue(port[i].mode);
259 state_fio->StateValue(port[i].first);