OSDN Git Service

501edd8f9beb7d19391b5a8cb85c1e7b086579eb
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / keyboard.cpp
1 /*
2         FUJITSU FMR-50 Emulator 'eFMR-50'
3         FUJITSU FMR-60 Emulator 'eFMR-60'
4
5         Author : Takeda.Toshiya
6         Date   : 2008.05.01 -
7
8         [ keyboard ]
9 */
10
11 #include "keyboard.h"
12 #include "../i8259.h"
13 #include "../../fifo.h"
14
15 #define EVENT_KEY_CODE                          1
16 #define EVENT_DELAY_PUSH                        2
17
18 namespace FMTOWNS {
19 void KEYBOARD::initialize()
20 {
21         DEVICE::initialize();
22         key_buf = new FIFO(64);
23         cmd_buf = new FIFO(16);
24         event_keycode = -1;
25         event_key_reset = -1;
26         memset(table, 0, sizeof(table));
27         memset(boot_code, 0x00, sizeof(boot_code));
28         boot_ptr = 0;
29         boot_seq = false;
30         boot_code_ptr = 0;
31         repeat_start_ms = 400;
32         repeat_tick_ms = 30;
33         
34         special_boot_num = -1;
35 }
36
37 void KEYBOARD::release()
38 {
39         cmd_buf->release();
40         key_buf->release();
41         delete key_buf;
42         delete cmd_buf;
43 }
44         
45 void KEYBOARD::reset()
46 {
47 //      boot_seq = true;
48         reset_device();
49 }
50
51 void KEYBOARD::reset_device()
52 {
53         out_debug_log("RESET\n");
54         special_boot_num = -1;
55         
56         last_cmd = 0x00;
57         memset(table, 0, sizeof(table));
58         key_buf->clear();
59         cmd_buf->clear();
60         
61         kbstat = kbdata = kbint = kbmsk = 0;
62         device_order = false;
63         enable_double_pressed_cursor = true;
64         nmi_status = false;
65         reserved_key_num = -1;
66         if(event_keycode > -1) {
67                 cancel_event(this, event_keycode);
68                 event_keycode = -1;
69         }
70         if(event_key_reset > -1) {
71                 cancel_event(this, event_key_reset);
72         }
73         event_key_reset = -1;
74         write_signals(&output_intr_line, 0);
75         write_signals(&output_nmi_line, 0);
76 }
77
78 void KEYBOARD::enqueue_key(uint8_t code)
79 {
80         key_buf->write(0xa0);
81         key_buf->write(code);
82 }
83
84 void KEYBOARD::enqueue_key2(uint8_t code)
85 {
86         key_buf->write(0xf0);
87         key_buf->write(code);
88 }
89         
90 void KEYBOARD::special_reset(int num)
91 {
92         out_debug_log("SPECIAL RESET %d\n", num);       
93         memset(boot_code, 0x00, sizeof(boot_code));
94         if(num < 0) return;
95         if(num >= 12) return;
96         special_boot_num = num;
97         boot_ptr = 0;
98         boot_seq = true;
99         boot_code_ptr = 0;
100         kbstat |= 1;
101         key_buf->clear();
102         enqueue_key(0x7f);
103         
104         switch(num) {
105         case 11: // DEBUG
106                 enqueue_key(0x20);
107                 enqueue_key(0x13);
108                 enqueue_key(0x2E);
109                 enqueue_key(0x17);
110                 enqueue_key(0x22);
111                 break;
112         default:
113 //              register_event(this, EVENT_DELAY_PUSH, 1.0, false, NULL);
114                 event_callback(EVENT_DELAY_PUSH, 0); 
115 //              boot_seq = false;
116 //              kbstat &= ~1;
117 //              return;
118                 break;
119         }
120         
121         register_key_interrupt(true); // NEXT BYTE
122 }
123         
124 void KEYBOARD::register_key_interrupt(bool first)
125 {
126         double usec = (first) ? 1000.0 : 50.0;
127         if(event_keycode > -1) {
128                 cancel_event(this, event_keycode);
129         }
130         event_keycode = -1;
131         register_event(this, EVENT_KEY_CODE, usec, false, &event_keycode);
132 }
133         
134 void KEYBOARD::do_common_command(uint8_t cmd)
135 {
136         static const int type_start_ms[] = {400, 500, 300};
137         static const int type_repeat_ms[] = {50, 30, 20};
138         out_debug_log(_T("CMD %02X"), cmd);
139         switch(cmd) {
140         case 0xa0:
141                 this->reset_device(); // RESET
142                 // From Tsugaru
143 //              key_buf->write(0xa0);
144 //              key_buf->write(0x7f);
145 //              memset(boot_code, 0x00, sizeof(boot_code));
146 //              boot_ptr = 0;
147 //              boot_seq = false;
148 //              boot_code_ptr = false;
149                 break;
150         case 0xa1:
151                 if(last_cmd != 0xa0) {
152                         this->reset_device(); // RESET
153                         memset(boot_code, 0x00, sizeof(boot_code));
154                         boot_ptr = 0;
155                         boot_seq = false;
156                         boot_code_ptr = false;
157                 }
158                 break;
159         case 0xa4:
160                 // Check double press (for OYAYUBI-Shift)
161                 break;
162         case 0xa5:
163                 // Don't check double press (for OYAYUBI-Shift)
164                 break;
165         case 0xa9:
166         case 0xaa:
167         case 0xab:
168                 repeat_start_ms = type_start_ms[cmd - 0xa9];
169                 break;
170         case 0xac:
171         case 0xad:
172         case 0xae:
173                 repeat_tick_ms = type_repeat_ms[cmd - 0xac];
174                 break;
175         case 0xb0:
176                 enable_double_pressed_cursor = true;
177                 break;
178         case 0xb1:
179                 enable_double_pressed_cursor = false;
180                 break;
181         case 0xb2:
182                 write_signals(&output_nmi_line, 0);
183                 nmi_status = false;
184                 break;
185         default:
186                 break;
187         }
188         last_cmd = cmd;
189 }
190
191 // Mame 0.216
192 void KEYBOARD::write_io8(uint32_t addr, uint32_t data)
193 {
194 //      out_debug_log(_T("WRITE I/O ADDR=%04X VAL=%02X"), addr, data);
195         switch(addr) {
196         case 0x600:
197                 // data
198                 kbstat &= ~0x08;
199                 kbstat |= 1;
200                 break;
201         case 0x602:
202                 // command
203                 if((data & 0x80) == 0x00) {
204                         // Second byte
205                         if((device_order) && (cmd_buf->count() > 0)) {
206                                 cmd_buf->write(data & 0x7f);
207                         } else {
208                                 // Illegal
209                                 cmd_buf->clear();
210                                 device_order = false;
211                         }
212                         kbstat |= 0x08;
213                 } else if(data & 0xe0 == 0xc0) {
214                         // Device order
215                         if((cmd_buf->count() > 0) && (device_order)){
216                                 // DO DEVICE ORDER
217                         }
218                         cmd_buf->clear();
219                         cmd_buf->write(data & 0xff);
220                         device_order = false;
221                         kbstat |= 0x08;
222                 } else if(data & 0xe0 == 0xa0) {
223                         // Common order
224                         if((cmd_buf->count() > 0) && (device_order)){
225                                 // DO DEVICE ORDER
226                         }
227                         device_order = false;
228                         kbstat |= 0x08;
229                         do_common_command(data);
230                 }
231                 break;
232         case 0x604:
233                 kbmsk = data;
234                 break;
235         }
236 }
237
238 uint32_t KEYBOARD::read_io8(uint32_t addr)
239 {
240         uint8_t kbtmp;
241         kbtmp = kbdata;
242         
243         switch(addr) {
244         case 0x600:
245                 kbint &= ~1;
246                 write_signals(&output_intr_line, 0);
247                 if(key_buf->empty()) {
248                         kbstat &= ~1;
249                 } else {
250                         register_key_interrupt(false); // NEXT BYTE
251                 }
252                 out_debug_log(_T("READ I/O ADDR=%04X VAL=%02X"), addr, kbdata);
253                 return kbtmp;
254         case 0x602:
255 //              out_debug_log(_T("READ I/O ADDR=%04X VAL=%02X"), addr, kbstat);
256                 return kbstat;
257         case 0x604:
258 //              out_debug_log(_T("READ I/O ADDR=%04X VAL=%02X"), addr, kbint);
259                 return (((kbint & 1) != 0) ? 1 : 0) | ((nmi_status) ? 2 : 0);
260                 break;
261         }
262         return 0;
263 }
264
265 void KEYBOARD::event_callback(int event_id, int err)
266 {
267         switch(event_id) {
268         case EVENT_KEY_CODE:
269                 kbdata = key_buf->read();
270                 kbstat |= 1;
271                 if(kbmsk & 1) {
272                         kbint |= 1;
273                         write_signals(&output_intr_line, 0xffffffff);
274                 }
275                 event_keycode = -1;
276                 break;
277         case EVENT_DELAY_PUSH:
278                 if(boot_seq) {
279                         int num = special_boot_num;
280                         switch(special_boot_num) {
281                         case 0: //  CD
282                                 enqueue_key(0x2c);
283                                 enqueue_key(0x20);
284                                 enqueue_key(0x2c);
285                                 enqueue_key(0x20);
286                                 enqueue_key(0x2c);
287                                 enqueue_key2(0x20);
288                                 break;
289                         case 1: // F0
290                                 enqueue_key(0x21);
291                                 enqueue_key(0x0b);
292                                 enqueue_key(0x21);
293                                 enqueue_key(0x0b);
294                                 enqueue_key(0x21);
295                                 enqueue_key2(0x0b);
296                                 break;
297                         case 2: // F1
298                         case 3: // F2
299                         case 4: // F3
300                                 enqueue_key(0x21);
301                                 enqueue_key(0x01 + (num - 1));
302                                 enqueue_key(0x21);
303                                 enqueue_key(0x01 + (num - 1));
304                                 enqueue_key(0x21);
305                                 enqueue_key2(0x01 + (num - 1));
306                                 break;
307                         case 5: // H0
308                                 enqueue_key(0x23);
309                                 enqueue_key(0x0B);
310                                 enqueue_key(0x23);
311                                 enqueue_key(0x0B);
312                                 enqueue_key(0x23);
313                                 enqueue_key2(0x0B);
314                                 break;
315                         case 6: // H1 - H4
316                         case 7: // H1 - H4
317                         case 8: // H1 - H4
318                         case 9: // H1 - H4
319                                 enqueue_key(0x23);
320                                 enqueue_key(0x01 + (num - 5));
321                                 enqueue_key(0x23);
322                                 enqueue_key(0x01 + (num - 5));
323                                 enqueue_key(0x23);
324                                 enqueue_key2(0x01 + (num - 5));
325                                 break;
326                         case 10: // ICM
327                                 enqueue_key(0x18);
328                                 enqueue_key(0x2C);
329                                 enqueue_key(0x30);
330                                 enqueue_key(0x18);
331                                 enqueue_key(0x2C);
332                                 enqueue_key2(0x30);
333                                 break;
334                         }
335                 }
336                 boot_seq = false;
337                 boot_ptr = 0;
338                 boot_code_ptr = 0;
339                 special_boot_num = -1;
340                 memset(boot_code, 0x00, sizeof(boot_code));
341                 break;
342         }
343 }
344         
345
346 void KEYBOARD::key_down(int code)
347 {
348 //      if(!table[code]) {
349                 table[code] = 1;
350                 if(code = key_table[code]) {
351                         // $11:CTRL, $10:SHIFT
352                         if((code >= 0x70) && (code < 0x7a)) {
353                                 // If PFkey, press with /*SHIFT or */RALT, PF += 10.
354                                 if((table[0xa5]) /*|| (table[0x10])*/) { // RALT /*or SHIFT*/
355                                         static const int pf1xtbl[] = { 0x69, 0x5b, 0x74, 0x75, 0x76,
356                                                                                                    0x77, 0x78, 0x79, 0x7a, 0x7b};
357                                         code = pf1xtbl[code - 0x70];
358                                 }
359                         } else if((code == 0x7d)) { // Print Screen + RALT -> Kanji Jisho
360                                 if(table[0xa5]) { // RALT
361                                         code = 0x6b;
362                                 }
363                         } else if((code == 0x7c)) { // Pause Break + RALT -> Tango Touroku
364                                 if(table[0xa5]) { // RALT
365                                         code = 0x6d;
366                                 }
367                         } else if((code == 0x6c)) { // Scroll Lock + RALT -> Tango Massyou.
368                                 if(table[0xa5]) { // RALT
369                                         code = 0x6c;
370                                 }
371                         }
372                         key_buf->write(0xc0 | (table[0x11] ? 8 : 0) | (table[0x10] ? 4 : 0));
373                         key_buf->write(code & 0x7f);
374                         register_key_interrupt(true);
375                 }
376 //      }
377 }
378
379 void KEYBOARD::key_up(int code)
380 {
381 //      if(table[code]) {
382                 table[code] = 0;
383                 if(code = key_table[code]) {
384                         if((code >= 0x70) && (code < 0x7a)) {
385                                 // If PFkey, press with /*SHIFT or */RALT, PF += 10.
386                                 if((table[0xa5]) /*|| (table[0x10])*/) { // RALT /*or SHIFT*/
387                                         static const int pf1xtbl[] = { 0x69, 0x5b, 0x74, 0x75, 0x76,
388                                                                                                    0x77, 0x78, 0x79, 0x7a, 0x7b};
389                                         code = pf1xtbl[code - 0x70];
390                                 }
391                         } else if((code == 0x7d)) { // Print Screen + RALT -> Kanji Jisho
392                                 if(table[0xa5]) { // RALT
393                                         code = 0x6b;
394                                 }
395                         } else if((code == 0x7c)) { // Pause Break + RALT -> Tango Touroku
396                                 if(table[0xa5]) { // RALT
397                                         code = 0x6d;
398                                 }
399                         } else if((code == 0x6c)) { // Scroll Lock + RALT -> Tango Massyou.
400                                 if(table[0xa5]) { // RALT
401                                         code = 0x6c;
402                                 }
403                         }
404                         key_buf->write(0xd0 | (table[0x11] ? 8 : 0) | (table[0x10] ? 4 : 0));
405                         key_buf->write(code & 0x7f);
406                         register_key_interrupt(true);
407                 }
408 //      }
409 }
410
411 void KEYBOARD::write_signal(int id, uint32_t data, uint32_t mask)
412 {
413         switch(id) {
414         case SIG_KEYBOARD_BOOTSEQ_END:
415 //              out_debug_log(_T("SIG_KEYBOARD_BOOTSEQ_END"));
416                 break;
417         }
418 }
419         
420 #define STATE_VERSION   2
421
422 bool KEYBOARD::process_state(FILEIO* state_fio, bool loading)
423 {
424         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
425                 return false;
426         }
427         if(!state_fio->StateCheckInt32(this_device_id)) {
428                 return false;
429         }
430         if(!(key_buf->process_state((void *)state_fio, loading))) {
431                 return false;
432         }
433         if(!(cmd_buf->process_state((void *)state_fio, loading))) {
434                 return false;
435         }
436
437         state_fio->StateValue(last_cmd);
438         state_fio->StateValue(kbstat);
439         state_fio->StateValue(kbdata);
440         state_fio->StateValue(kbint);
441         state_fio->StateValue(kbmsk);
442         
443         state_fio->StateValue(nmi_status);
444         state_fio->StateValue(repeat_start_ms);
445         state_fio->StateValue(repeat_tick_ms);
446         state_fio->StateValue(enable_double_pressed_cursor);
447         state_fio->StateValue(device_order);
448
449         state_fio->StateArray(table, sizeof(table), 1);
450         state_fio->StateValue(reserved_key_num);
451         state_fio->StateValue(key_count_phase);
452         state_fio->StateValue(special_boot_num);
453         
454         state_fio->StateArray(boot_code, sizeof(boot_code), 1);
455         state_fio->StateValue(boot_ptr);
456         state_fio->StateValue(boot_seq);
457         state_fio->StateValue(boot_code_ptr);
458         
459         state_fio->StateValue(event_keycode);
460         state_fio->StateValue(event_key_reset);
461         return true;
462 }
463
464 }
465