OSDN Git Service

[VM][General][WIP] Apply new (Upstream 2016-02-21) APIs to VMs.
[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 addr, uint32 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 IOCTRL::read_io8(uint32 addr)
96 {
97         switch(addr & 0x3ff) {
98         case 0x20:
99                 key_done = true;
100                 update_key();
101                 return key_val;
102         case 0x22:
103                 if(config.monitor_type) {
104                         return key_mouse | 0x0d;        // virt monitor
105                 } else {
106                         return key_mouse | 0x2d;        // horiz monitor
107                 }
108         }
109         return 0xff;
110 }
111
112 void IOCTRL::event_callback(int event_id, int err)
113 {
114         if(event_id == EVENT_KEY) {
115                 if(!key_buf->empty()) {
116                         key_val = key_buf->read();
117                         key_mouse = (key_val & 0x100) ? 0x10 : 0;
118                         key_val &= 0xff;
119                         key_done = false;
120                         d_pic->write_signal(SIG_I8259_IR3, 1, 1);
121                 }
122                 register_id = -1;
123         } else if(event_id == EVENT_600HZ) {
124                 if(ts == 0) {
125                         d_pic->write_signal(SIG_I8259_IR2, 1, 1);
126                 }
127         } else if(event_id == EVENT_100HZ) {
128                 if(ts == 1) {
129                         d_pic->write_signal(SIG_I8259_IR2, 1, 1);
130                 }
131         } else if(event_id == EVENT_50HZ) {
132                 if(ts == 2) {
133                         d_pic->write_signal(SIG_I8259_IR2, 1, 1);
134                 }
135                 // mouse
136                 if(key_buf->empty()) {
137                         uint8 val = 0;
138                         if(!(mouse_stat[2] & 1)) val |= 1;
139                         if(!(mouse_stat[2] & 2)) val |= 2;
140                         if(caps) val |= 0x10;
141                         if(kana) val |= 0x20;
142                         if(key_stat[0xa0]) val |= 0x40; // lshift
143                         if(key_stat[0xa1]) val |= 0x80; // rshift
144                         if(mouse_stat[0] || mouse_stat[1]) {
145                                 key_buf->write(val | 4);
146                                 key_buf->write(mouse_stat[0] & 0xff);
147                                 key_buf->write(mouse_stat[1] & 0xff);
148                                 update_key();
149                                 key_prev = val;
150                         } else if(key_prev != val) {
151                                 key_buf->write(val);
152                                 update_key();
153                                 key_prev = val;
154                         }
155                 }
156         } else if(event_id == EVENT_10HZ) {
157                 if(ts == 3) {
158                         d_pic->write_signal(SIG_I8259_IR2, 1, 1);
159                 }
160         }
161 }
162
163 void IOCTRL::write_signal(int id, uint32 data, uint32 mask)
164 {
165         bool next = ((data & mask) != 0);
166         if(!key_res && next) {
167                 // reset
168                 caps = kana = false;
169                 key_buf->clear();
170                 key_buf->write(0x1f0);  // dummy
171                 key_buf->write(0x1f0);  // init code
172                 key_buf->write(0x100);  // error code
173                 key_done = true;
174                 update_key();
175         }
176         key_res = next;
177 }
178
179 void IOCTRL::key_down(int code)
180 {
181         if(code == 0x14) {
182                 caps = !caps;
183         } else if(code == 0x15) {
184                 kana = !kana;
185         } else if((code = key_table[code & 0xff]) != -1) {
186                 code |= 0x80;
187                 key_buf->write(code | 0x100);
188                 update_key();
189         }
190 }
191
192 void IOCTRL::key_up(int code)
193 {
194         if((code = key_table[code & 0xff]) != -1) {
195                 code &= ~0x80;
196                 key_buf->write(code | 0x100);
197                 update_key();
198         }
199 }
200
201 void IOCTRL::update_key()
202 {
203         if(key_done && !key_buf->empty()) {
204                 if(register_id == -1) {
205                         register_event(this, EVENT_KEY, 1000, false, &register_id);
206                 }
207         }
208 }
209
210 #define STATE_VERSION   1
211
212 void IOCTRL::save_state(FILEIO* state_fio)
213 {
214         state_fio->FputUint32(STATE_VERSION);
215         state_fio->FputInt32(this_device_id);
216         
217         state_fio->FputBool(caps);
218         state_fio->FputBool(kana);
219         key_buf->save_state((void *)state_fio);
220         state_fio->FputUint32(key_val);
221         state_fio->FputUint32(key_mouse);
222         state_fio->FputInt32(key_prev);
223         state_fio->FputBool(key_res);
224         state_fio->FputBool(key_done);
225         state_fio->FputInt32(register_id);
226         state_fio->FputUint8(ts);
227 }
228
229 bool IOCTRL::load_state(FILEIO* state_fio)
230 {
231         if(state_fio->FgetUint32() != STATE_VERSION) {
232                 return false;
233         }
234         if(state_fio->FgetInt32() != this_device_id) {
235                 return false;
236         }
237         caps = state_fio->FgetBool();
238         kana = state_fio->FgetBool();
239         if(!key_buf->load_state((void *)state_fio)) {
240                 return false;
241         }
242         key_val = state_fio->FgetUint32();
243         key_mouse = state_fio->FgetUint32();
244         key_prev = state_fio->FgetInt32();
245         key_res = state_fio->FgetBool();
246         key_done = state_fio->FgetBool();
247         register_id = state_fio->FgetInt32();
248         ts = state_fio->FgetUint8();
249         return true;
250 }
251