OSDN Git Service

df8204f1bfd152c4efd9834e39b60358ba3a0f1c
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc100 / ioctrl.cpp
1 /*
2         NEC PC-100 Emulator 'ePC-100'
3
4         Author : Takeda.Toshiya
5         Date   : 2008.07.14 -
6
7         [ i/o controller ]
8 */
9
10 #include "ioctrl.h"
11 #include "../beep.h"
12 #include "../i8259.h"
13 #include "../pcm1bit.h"
14 #include "../upd765a.h"
15 #include "../../fifo.h"
16
17 static const int key_table[256] = {
18           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x18,0x12,  -1,  -1,  -1,0x38,  -1,  -1,
19           -1,0x04,0x05,0x09,  -1,  -1,  -1,  -1,  -1,0x10,  -1,0x11,  -1,  -1,  -1,  -1,
20         0x4A,  -1,  -1,0x5B,0x5A,0x15,0x13,0x16,0x14,  -1,  -1,  -1,  -1,0x17,  -1,  -1,
21         0x27,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x26,  -1,  -1,  -1,  -1,  -1,  -1,
22           -1,0x31,0x45,0x43,0x33,0x23,0x34,0x35,0x36,0x30,0x3F,0x40,0x3B,0x47,0x46,0x2B,
23         0x29,0x21,0x2C,0x32,0x2D,0x2F,0x44,0x22,0x3A,0x2E,0x39,  -1,  -1,  -1,  -1,  -1,
24         0x4B,0x4F,0x50,0x51,0x52,0x53,0x54,0x56,0x57,0x58,0x59,0x55,  -1,0x5C,0x4D,0x5D,
25         0x0B,0x0C,0x0D,0x0E,0x0F,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
26           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
27           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
28           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
29           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x3D,0x3C,0x48,0x28,0x41,0x42,
30         0x2A,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
31           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x37,0x25,0x3E,0x24,  -1,
32           -1,  -1,0x49,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
33           -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1
34 };
35
36 #define EVENT_KEY       0
37 #define EVENT_600HZ     1
38 #define EVENT_100HZ     2
39 #define EVENT_50HZ      3
40 #define EVENT_10HZ      4
41
42 void IOCTRL::initialize()
43 {
44         // init keyboard
45         key_stat = emu->get_key_buffer();
46         mouse_stat = emu->get_mouse_buffer();
47         key_buf = new FIFO(64);
48         caps = kana = false;
49         
50         // timer
51         ts = 0;
52         
53         // register event
54         register_event_by_clock(this, EVENT_600HZ, CPU_CLOCKS / 600, true, NULL);
55         register_event_by_clock(this, EVENT_100HZ, CPU_CLOCKS / 100, true, NULL);
56         register_event_by_clock(this, EVENT_50HZ, CPU_CLOCKS / 50, true, NULL);
57         register_event_by_clock(this, EVENT_10HZ, CPU_CLOCKS / 10, true, NULL);
58 }
59
60 void IOCTRL::release()
61 {
62         key_buf->release();
63         delete key_buf;
64 }
65
66 void IOCTRL::reset()
67 {
68         key_val = key_mouse = 0;
69         key_prev = -1;
70         key_res = false;
71         key_done = true;
72         key_buf->clear();
73         key_buf->write(0x1f0);
74         key_buf->write(0x100);
75         register_id = -1;
76         update_key();
77 }
78
79 void IOCTRL::write_io8(uint32_t addr, uint32_t data)
80 {
81         switch(addr & 0x3f0) {
82         case 0x22:
83                 ts = (data >> 3) & 3;
84                 d_beep->write_signal(SIG_BEEP_ON, ~data, 0x40);         // tone (2400hz)
85                 d_pcm->write_signal(SIG_PCM1BIT_ON, data, 0x40);        // direct
86                 d_pcm->write_signal(SIG_PCM1BIT_SIGNAL, data, 0x80);    // signal
87                 break;
88         case 0x24:
89                 // tc/vfo
90                 d_fdc->write_signal(SIG_UPD765A_TC, data, 0x40);
91                 break;
92         }
93 }
94
95 uint32_t IOCTRL::read_io8(uint32_t addr)
96 {
97         switch(addr & 0x3ff) {
98         case 0x20:
99                 key_done = true;
100                 update_key();
101                 return key_val;
102         case 0x22:
103                 // bit1: 0 = Color Mode, 1 = Monochrome Mode
104                 // bit2: 1 = Double FDD, 0 = Single FDD
105                 // bit3: 1 = 2D, 0 = 2DD
106                 // bit4: 1 = KD, 0 = MD
107                 // bit5: 1 = Horizontal Monitor, 0 = Virtical Monitor
108                 {
109                         uint32_t value = key_mouse | 0x05;
110                         if(!config.drive_type) {
111                                 value |= 0x08; // 2D
112                         }
113                         if(!config.monitor_type) {
114                                 value |= 0x20; // Horizontal Monitor
115                         }
116                         return value;
117                 }
118         }
119         return 0xff;
120 }
121
122 void IOCTRL::event_callback(int event_id, int err)
123 {
124         if(event_id == EVENT_KEY) {
125                 if(!key_buf->empty()) {
126                         key_val = key_buf->read();
127                         key_mouse = (key_val & 0x100) ? 0x10 : 0;
128                         key_val &= 0xff;
129                         key_done = false;
130                         d_pic->write_signal(SIG_I8259_IR3, 1, 1);
131                 }
132                 register_id = -1;
133         } else if(event_id == EVENT_600HZ) {
134                 if(ts == 0) {
135                         d_pic->write_signal(SIG_I8259_IR2, 1, 1);
136                 }
137         } else if(event_id == EVENT_100HZ) {
138                 if(ts == 1) {
139                         d_pic->write_signal(SIG_I8259_IR2, 1, 1);
140                 }
141         } else if(event_id == EVENT_50HZ) {
142                 if(ts == 2) {
143                         d_pic->write_signal(SIG_I8259_IR2, 1, 1);
144                 }
145                 // mouse
146                 if(key_buf->empty()) {
147                         uint8_t val = 0;
148                         if(!(mouse_stat[2] & 1)) val |= 1;
149                         if(!(mouse_stat[2] & 2)) val |= 2;
150                         if(caps) val |= 0x10;
151                         if(kana) val |= 0x20;
152                         if(key_stat[0xa0]) val |= 0x40; // lshift
153                         if(key_stat[0xa1]) val |= 0x80; // rshift
154                         if(mouse_stat[0] || mouse_stat[1]) {
155                                 key_buf->write(val | 4);
156                                 key_buf->write(mouse_stat[0] & 0xff);
157                                 key_buf->write(mouse_stat[1] & 0xff);
158                                 update_key();
159                                 key_prev = val;
160                         } else if(key_prev != val) {
161                                 key_buf->write(val);
162                                 update_key();
163                                 key_prev = val;
164                         }
165                 }
166         } else if(event_id == EVENT_10HZ) {
167                 if(ts == 3) {
168                         d_pic->write_signal(SIG_I8259_IR2, 1, 1);
169                 }
170         }
171 }
172
173 void IOCTRL::write_signal(int id, uint32_t data, uint32_t mask)
174 {
175         bool next = ((data & mask) != 0);
176         if(!key_res && next) {
177                 // reset
178                 caps = kana = false;
179                 key_buf->clear();
180                 key_buf->write(0x1f0);  // dummy
181                 key_buf->write(0x1f0);  // init code
182                 key_buf->write(0x100);  // error code
183                 key_done = true;
184                 update_key();
185         }
186         key_res = next;
187 }
188
189 void IOCTRL::key_down(int code)
190 {
191         if(code == 0x14) {
192                 caps = !caps;
193         } else if(code == 0x15) {
194                 kana = !kana;
195         } else if((code = key_table[code & 0xff]) != -1) {
196                 code |= 0x80;
197                 key_buf->write(code | 0x100);
198                 update_key();
199         }
200 }
201
202 void IOCTRL::key_up(int code)
203 {
204         if((code = key_table[code & 0xff]) != -1) {
205                 code &= ~0x80;
206                 key_buf->write(code | 0x100);
207                 update_key();
208         }
209 }
210
211 void IOCTRL::update_key()
212 {
213         if(key_done && !key_buf->empty()) {
214                 if(register_id == -1) {
215                         register_event(this, EVENT_KEY, 1000, false, &register_id);
216                 }
217         }
218 }
219
220 #define STATE_VERSION   1
221
222 bool IOCTRL::process_state(FILEIO* state_fio, bool loading)
223 {
224         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
225                 return false;
226         }
227         if(!state_fio->StateCheckInt32(this_device_id)) {
228                 return false;
229         }
230         state_fio->StateBool(caps);
231         state_fio->StateBool(kana);
232         if(!key_buf->process_state((void *)state_fio, loading)) {
233                 return false;
234         }
235         state_fio->StateUint32(key_val);
236         state_fio->StateUint32(key_mouse);
237         state_fio->StateInt32(key_prev);
238         state_fio->StateBool(key_res);
239         state_fio->StateBool(key_done);
240         state_fio->StateInt32(register_id);
241         state_fio->StateUint8(ts);
242         return true;
243 }