OSDN Git Service

[VM][PC9801][MEMBUS] Split update_bios() to functions.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mc6820.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2011.06.02-
6
7         [ mc6820 ]
8 */
9
10 #include "mc6820.h"
11
12 /* note: ca2/cb2 output signals are not implemented */
13
14 void MC6820::reset()
15 {
16         for(int i = 0; i < 2; i++) {
17                 port[i].ctrl = 0x00;
18                 port[i].ddr = 0x00;
19                 port[i].c1 = port[i].c2 = false;
20                 port[i].first = true;
21         }
22 }
23
24 void MC6820::write_io8(uint32_t addr, uint32_t data)
25 {
26         int ch = (addr & 2) >> 1;
27         
28         switch(addr & 3) {
29         case 0:
30         case 2:
31                 if(port[ch].ctrl & 4) {
32                         if(port[ch].wreg != data || port[ch].first) {
33                                 write_signals(&port[ch].outputs, data);
34                                 port[ch].wreg = data;
35                                 port[ch].first = false;
36                         }
37                 } else {
38                         port[ch].ddr = data;
39                 }
40                 break;
41         case 1:
42         case 3:
43                 if(data & 0x20) {
44                         port[ch].ctrl &= ~0x40;
45                 }
46                 port[ch].ctrl = (port[ch].ctrl & 0xc0) | (data & 0x3f);
47                 break;
48         }
49 }
50
51 uint32_t MC6820::read_io8(uint32_t addr)
52 {
53         int ch = (addr & 2) >> 1;
54         
55         switch(addr & 3) {
56         case 0:
57         case 2:
58                 if(port[ch].ctrl & 4) {
59                         write_signals(&port[ch].outputs_irq, 0);
60                         port[ch].ctrl &= ~0xc0;
61                         return (port[ch].rreg & ~port[ch].ddr) | (port[ch].wreg & port[ch].ddr);
62                 } else {
63                         return port[ch].ddr;
64                 }
65         case 1:
66          case 3:
67                 return port[ch].ctrl;
68         }
69         return 0xff;
70 }
71
72 void MC6820::write_signal(int id, uint32_t data, uint32_t mask)
73 {
74         bool signal = ((data & mask) != 0);
75         int ch = id & 1;
76         
77         switch(id) {
78         case SIG_MC6820_PORT_A:
79         case SIG_MC6820_PORT_B:
80                 port[ch].rreg = (port[ch].rreg & ~mask) | (data & mask);
81                 break;
82         case SIG_MC6820_C1_A:
83         case SIG_MC6820_C1_B:
84                 if(((port[ch].ctrl & 2) && !port[ch].c1 && signal) || (!(port[ch].ctrl & 2) && port[ch].c1 && !signal)) {
85                         if(port[ch].ctrl & 1) {
86                                 write_signals(&port[ch].outputs_irq, 0xffffffff);
87                         }
88                         port[ch].ctrl |= 0x80;
89                 }
90                 port[ch].c1 = signal;
91                 break;
92         case SIG_MC6820_C2_A:
93         case SIG_MC6820_C2_B:
94                 if(port[ch].ctrl & 0x20) {
95                         // c2 is output
96                         break;
97                 }
98                 if(((port[ch].ctrl & 0x10) && !port[ch].c2 && signal) || (!(port[ch].ctrl & 0x10) && port[ch].c2 && !signal)) {
99                         if(port[ch].ctrl & 8) {
100                                 write_signals(&port[ch].outputs_irq, 0xffffffff);
101                         }
102                         port[ch].ctrl |= 0x40;
103                 }
104                 port[ch].c2 = signal;
105                 break;
106         }
107 }
108
109 #define STATE_VERSION   1
110
111 bool MC6820::process_state(FILEIO* state_fio, bool loading)
112 {
113         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
114                 return false;
115         }
116         if(!state_fio->StateCheckInt32(this_device_id)) {
117                 return false;
118         }
119         for(int i = 0; i < 2; i++) {
120                 state_fio->StateValue(port[i].wreg);
121                 state_fio->StateValue(port[i].rreg);
122                 state_fio->StateValue(port[i].ctrl);
123                 state_fio->StateValue(port[i].ddr);
124                 state_fio->StateValue(port[i].c1);
125                 state_fio->StateValue(port[i].c2);
126                 state_fio->StateValue(port[i].first);
127         }
128         return true;
129 }
130