OSDN Git Service

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