OSDN Git Service

ad508e640f9137adaa73fa10d861520f5883b2d2
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / keyboard.cpp
1 /*
2  * Common Source code Project -> VM -> FM-7/77AV -> Keyboard
3  * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
4  * Licence: GPLv2
5  * History : 
6  *  Feb 12, 2015 : Initial 
7  */
8
9 #include "../../fifo.h"
10 #include "../device.h"
11 #include "fm7_keyboard.h"
12
13 #include "keyboard_tables.h"
14 #if defined(_FM77AV_VARIANTS)
15 #include "../beep.h"
16 #include "fm77av_hidden_message_keyboard.h"
17 #endif
18 enum {
19         ID_KEYBOARD_RXRDY_OK = 1,
20         ID_KEYBOARD_ACK,
21         ID_KEYBOARD_RXRDY_BUSY,
22         ID_KEYBOARD_RTC_COUNTUP,
23         ID_KEYBOARD_INT,
24         ID_KEYBOARD_AUTOREPEAT_FIRST,
25         ID_KEYBOARD_AUTOREPEAT,
26         ID_KEYBOARD_HIDDENMESSAGE_AV,
27         ID_KEYBOARD_HIDDEN_BEEP_ON,
28         ID_KEYBOARD_HIDDEN_BEEP_OFF,
29         ID_KEYBOARD_AUTO_8KEY_START,
30         ID_KEYBOARD_AUTO_8KEY_END,
31         ID_KEYBOARD_AUTO_5KEY_START,
32         ID_KEYBOARD_AUTO_5KEY_END,
33         ID_KEYBOARD_BREAK_ONESHOT,
34 };
35
36 //
37 /*
38  * I/O API (subio)
39  */
40 // 0xd400(SUB) or 0xfd00(MAIN)
41 uint8_t KEYBOARD::get_keycode_high(void)
42 {
43         uint8_t data = 0x00;
44         if((keycode_7 & 0x0100) != 0) data = 0x80;
45         return data;
46 }
47
48 // 0xd401(SUB) or 0xfd01(MAIN)
49 uint8_t KEYBOARD::get_keycode_low(void)
50 {
51         uint8_t data = keycode_7 & 0xff;
52         this->write_signals(&int_line, 0x00000000);
53         return data;
54 }
55
56 // 0xd40d : R
57 void KEYBOARD::turn_on_ins_led(void)
58 {
59         this->write_signals(&ins_led, 0xff);
60 }
61
62 // 0xd40d : W
63 void KEYBOARD::turn_off_ins_led(void)
64 {
65         this->write_signals(&ins_led, 0x00);
66 }
67
68 // UI Handler. 
69 uint16_t KEYBOARD::vk2scancode(uint32_t vk)
70 {
71         uint16_t i;
72         i = 0;
73         if(vk == VK_PAUSE) vk = VK_KANJI; // Workaround some desktop environments for [ESC].
74         do {
75                 if(vk_matrix_106[i] == vk) return i;
76                 i++;
77         } while(vk_matrix_106[i] != 0xffff);
78         return 0x0000;
79 }
80
81 bool KEYBOARD::isModifier(uint8_t sc)
82 {
83         if(((sc >= 0x52) && (sc <= 0x56)) || // CTRL LSHIFT RSHIFT CAPS GRPH
84                 (sc == 0x5a) || (sc == 0x5c)) { // KANA BREAK
85                 return true;
86         }
87         return false;
88 }
89
90 void KEYBOARD::set_modifiers(uint8_t sc, bool flag)
91 {
92         if(sc == 0x52) { // CTRL
93                 ctrl_pressed = flag; 
94         } else if(sc == 0x53) { // LSHIFT
95                 lshift_pressed = flag;
96                 shift_pressed = lshift_pressed | rshift_pressed;
97                 //printf("LSHIFT : %d\n", flag ? 1 : 0);
98         } else if(sc == 0x54) { // RSHIFT
99                 rshift_pressed = flag;
100                 shift_pressed = lshift_pressed | rshift_pressed;
101                 //printf("RSHIFT : %d\n", flag ? 1 : 0);
102         } else if(sc == 0x56) { // GRPH
103                 graph_pressed = flag;
104         } else if(sc == 0x55) { // CAPS
105                 // Toggle on press.
106                 if(flag) {
107                         if(caps_pressed) {
108                                 caps_pressed = false;
109                         } else {
110                                 caps_pressed = true;
111                         }
112                         if(keymode == KEYMODE_STANDARD) this->write_signals(&caps_led, caps_pressed ? 0xff : 0x00);
113                 }
114         } else if(sc == 0x5a) { // KANA
115                 // Toggle on press.
116                 if(flag) {
117                         if(kana_pressed) {
118                                 kana_pressed = false;
119                         } else {
120                                 kana_pressed = true;
121                         }
122                         if(keymode == KEYMODE_STANDARD) this->write_signals(&kana_led, kana_pressed ? 0xff : 0x00);
123                 }
124         } else if(sc == 0x5c) { // Break
125                 break_pressed = flag;
126         }
127 }
128
129 uint16_t KEYBOARD::scan2fmkeycode(uint8_t sc)
130 {
131         const struct key_tbl_t *keyptr = NULL;
132         bool stdkey = false;
133         int i;
134         uint16_t retval;
135         
136         if((sc == 0) || (sc >= 0x67)) return 0xffff;
137         // Set repeat flag(s)
138         if(shift_pressed && ctrl_pressed) {
139                 switch(sc) {
140                         case 0x02: // 1
141                         case 0x42: // 1
142                                 repeat_mode = true;
143                                 return 0xffff;
144                                 break;
145                         case 0x0b: // 0
146                         case 0x46: // 0
147                                 repeat_mode = false;
148                                 return 0xffff;
149                                 break;
150                 }
151         }
152         if(keymode == KEYMODE_STANDARD) {
153                 if(ctrl_pressed) {
154                         if(shift_pressed) {
155                                 keyptr = ctrl_shift_key;
156                         } else {
157                                 keyptr = ctrl_key;
158                         }
159                 } else if(graph_pressed) {
160                         if(shift_pressed) {
161                                 keyptr = graph_shift_key;
162                         } else {
163                                 keyptr = graph_key;
164                         }
165                 } else if(kana_pressed) {
166                         if(shift_pressed) {
167                                 keyptr = kana_shift_key;
168                         } else {
169                                 keyptr = kana_key;
170                         }
171                 } else { // Standard
172                         stdkey = true;
173                         if(shift_pressed) {
174                                 keyptr = standard_shift_key;
175                         } else {
176                                 keyptr = standard_key;
177                         }
178                 }
179         }
180 #if defined(_FM77AV_VARIANTS)
181         else    if(shift_pressed) {
182           // DO super-impose mode:
183           // F7 : PC
184           // F8 : IMPOSE (High brightness)
185           // F9 : IMPOSE (Low brightness)
186           // F10: TV
187         }
188         if(keymode == KEYMODE_SCAN) {
189                 retval = (uint16_t)sc;
190                 return retval;
191         } else if(keymode == KEYMODE_16BETA) { // Will Implement
192                 if(ctrl_pressed) {
193                         if(shift_pressed) {
194                                 keyptr = ctrl_shift_key_16beta;
195                         } else {
196                                 keyptr = ctrl_key_16beta;
197                         }
198                 } else if(graph_pressed) {
199                         if(shift_pressed) {
200                                 keyptr = graph_shift_key_16beta;
201                         } else {
202                                 keyptr = graph_key_16beta;
203                         }
204                 } else if(kana_pressed) {
205                         if(shift_pressed) {
206                                 keyptr = kana_shift_key_16beta;
207                         } else {
208                                 keyptr = kana_key_16beta;
209                         }
210                 } else { // Standard
211                         stdkey = true;
212                         if(shift_pressed) {
213                                 keyptr = standard_shift_key_16beta;
214                         } else {
215                                 keyptr = standard_key_16beta;
216                         }
217                 }
218         }
219 #endif //_FM77AV_VARIANTS       
220         i = 0;
221         retval = 0xffff;
222         if (keyptr == NULL) return 0xffff;
223         do {
224                 if(keyptr[i].phy == (uint16_t)sc) {
225                         retval = keyptr[i].code;
226                         break;
227                 }
228                 i++;
229         } while(keyptr[i].phy != 0xffff);
230         if(keyptr[i].phy == 0xffff) return 0x00;
231         if(stdkey) {
232                 if((retval >= 'A') && (retval <= 'Z')) {
233                         if(caps_pressed) {
234                                 retval += 0x20;
235                         }
236                 } else if((retval >= 'a') && (retval <= 'z')) {
237                         if(caps_pressed) {
238                                 retval -= 0x20;
239                         }
240                 }
241         }
242         return retval;
243 }
244
245 void KEYBOARD::key_up_main(uint8_t bak_scancode)
246 {
247         bool stat_break = break_pressed;
248         older_vk = 0;
249         if(bak_scancode == 0) return;
250         if((event_keyrepeat >= 0) && (repeat_keycode == bak_scancode)) { // Not Break
251                 cancel_event(this, event_keyrepeat);
252                 event_keyrepeat = -1;
253                 repeat_keycode = 0;
254         }
255         if(keymode != KEYMODE_SCAN) {
256                 if(this->isModifier(bak_scancode)) {
257                         set_modifiers(bak_scancode, false);
258                         if(break_pressed != stat_break) { // Break key UP.
259                                 this->write_signals(&break_line, 0x00);
260                         }
261                 }
262                 if((config.dipswitch & FM7_DIPSW_AUTO_5_OR_8KEY) != 0) {
263                         if((config.dipswitch & FM7_DIPSW_SELECT_5_OR_8KEY) == 0) { // Auto 8
264                                 switch(bak_scancode) {
265                                         case 0x42: // 1
266                                         case 0x43: // 2
267                                         case 0x44: // 3
268                                         case 0x3f: // 5
269                                         case 0x46: // 0
270                                                 register_event(this,
271                                                                            ID_KEYBOARD_AUTO_8KEY_START,
272                                                                            10.0 * 1000.0, false, NULL);
273                                                 break;
274                                         default:
275                                                 if(autokey_backup != 0) key_fifo->write(scan2fmkeycode(autokey_backup));
276                                                 break;
277                                 }
278                         } else { // Auto 5
279                                 switch(bak_scancode) {
280                                         case 0x42: // 1
281                                         case 0x43: // 2
282                                         case 0x44: // 3
283                                         case 0x3e: // 4
284                                         case 0x40: // 6
285                                         case 0x3a: // 7
286                                         case 0x3b: // 8
287                                         case 0x3c: // 9
288                                                 register_event(this,
289                                                                            ID_KEYBOARD_AUTO_5KEY_START,
290                                                                            10.0 * 1000.0, false, NULL);
291                                                 break;
292                                         default:
293                                                 if(autokey_backup != 0) key_fifo->write(scan2fmkeycode(autokey_backup));
294                                                 break;
295                                 }
296                         }                               
297                 }
298         } else {
299                 //scancode = 0;
300                 if(bak_scancode != 0) { // Notify even key-up, when using SCAN mode.
301                         uint8_t code = (bak_scancode & 0x7f) | 0x80;
302                         if(this->isModifier(bak_scancode)) {
303                                 set_modifiers(bak_scancode, false);
304                         }
305 #if defined(_FM77AV_VARIANTS)      
306                         if(bak_scancode != 0x5c) {
307                                 if(beep_phase == 1) {
308                                         if(break_pressed) this->write_signals(&break_line, 0x00);
309                                         break_pressed = false;
310                                         beep_phase++;
311                                         bak_scancode = 0x7f;
312                                         code = 0xff;
313                                 } else if(beep_phase == 2) {
314                                         beep_phase = 0;
315                                         register_event(this,
316                                                                    ID_KEYBOARD_HIDDEN_BEEP_ON,
317                                                                    100.0, false, NULL); // 100.0 us is dummy.
318                                         bak_scancode = 0x7f;
319                                         code = 0xff;
320                                 }
321                         } else { // 0x5c : BREAK is up.
322                                 beep_phase = 0;
323                                 if(stat_break) this->write_signals(&break_line, 0x00);
324                         }
325 #endif             
326                         if(code != 0x80) {
327                                 key_fifo->write(code);
328                                 scancode = bak_scancode;
329                         }
330                 }
331         }
332 }
333
334 void KEYBOARD::key_up(uint32_t vk)
335 {
336         uint8_t bak_scancode = (uint8_t)(vk2scancode(vk) & 0x00ff);
337         key_up_main(bak_scancode);
338 }
339
340 void KEYBOARD::key_down(uint32_t vk)
341 {
342         if(older_vk == vk) return;
343         older_vk = vk;
344         
345         scancode = (uint8_t)vk2scancode(vk);
346 #if defined(_FM77AV_VARIANTS)
347         // Below are FM-77AV's hidden message , see :
348         // https://twitter.com/maruan/status/499558392092831745
349         //if(caps_pressed && kana_pressed) {
350         //      if(ctrl_pressed && lshift_pressed && rshift_pressed && graph_pressed) {
351         if(caps_pressed && kana_pressed && graph_pressed && shift_pressed && ctrl_pressed && !did_hidden_message_av_1) { // IT's deprecated key pressing
352                 if(scancode == 0x15) { // "T"
353                         if(event_hidden1_av < 0) {
354                                 hidden1_ptr = 0;
355                                 did_hidden_message_av_1 = true;
356                                 register_event(this,
357                                                 ID_KEYBOARD_HIDDENMESSAGE_AV,
358                                                 130.0 * 1000, true, &event_hidden1_av);
359                         }
360                         return;
361                 }
362         }
363 #endif 
364         key_down_main(true);
365 }
366
367 void KEYBOARD::key_down_main(bool repeat_auto_key)
368 {
369         bool stat_break = break_pressed;
370         uint32_t code;
371         if(scancode == 0) return;
372         if(keymode == KEYMODE_SCAN) {
373                 code = scancode & 0x7f;
374                 if(this->isModifier(scancode)) {  // modifiers
375                         set_modifiers(scancode, true);
376                 }
377 #if defined(_FM77AV_VARIANTS)
378                 if(break_pressed) {
379                         if(!stat_break) {
380                                 beep_phase = 1;
381                                 // It's dirty hack for AMNORK ; Set dead zone for FIRQ to 0.25sec.
382                                 // I wish to replace this solution to more simple. 
383                                 register_event(this,
384                                                            ID_KEYBOARD_BREAK_ONESHOT,
385                                                            250.0 * 1000.0, false, NULL);
386                         } else if(beep_phase == 1) {
387                                 if(code != 0x5c) {
388                                         if(break_pressed) this->write_signals(&break_line, 0x00);
389                                         break_pressed = false;
390                                         beep_phase++;
391                                         code = 0x7f; // Special
392                                         scancode = 0x7f;        
393                                 }
394                         }
395                 }
396 #endif
397
398                 if(code != 0) {
399                         key_fifo->write(code);
400                         // NOTE: With scan key code mode, auto repeat seems to be not effectable.
401                         // See : http://hanabi.2ch.net/test/read.cgi/i4004/1430836648/607
402                         // 20160409 K.Ohta
403                 }
404         } else {
405                 if(this->isModifier(scancode)) {  // modifiers
406                         set_modifiers(scancode, true);
407                         if(break_pressed != stat_break) { // Break key Down.
408                                 this->write_signals(&break_line, 0xff);
409                         }
410                         return;
411                 }
412                 code = scan2fmkeycode(scancode);
413                 if((code > 0x3ff) || (code == 0)) return;
414                 if((config.dipswitch & FM7_DIPSW_AUTO_5_OR_8KEY) != 0) {
415                         if((config.dipswitch & FM7_DIPSW_SELECT_5_OR_8KEY) == 0) { // Auto 8
416                                 switch(scancode) {
417                                         case 0x42: // 1
418                                         case 0x43: // 2
419                                         case 0x44: // 3
420                                         case 0x3f: // 5
421                                         case 0x46: // 0
422                                                 autokey_backup = scancode;
423                                                 break;
424                                 }
425                         } else { // Auto 5
426                                 switch(scancode) {
427                                         case 0x42: // 1
428                                         case 0x43: // 2
429                                         case 0x44: // 3
430                                         case 0x3e: // 4
431                                         case 0x40: // 6
432                                         case 0x3a: // 7
433                                         case 0x3b: // 8
434                                         case 0x3c: // 9
435                                                 autokey_backup = scancode;
436                                                 break;
437                                 }
438                         }                               
439                 } else {
440                         autokey_backup = 0x00;
441                 }
442                 if(code != 0) {
443                         key_fifo->write(code);
444                         if((scancode < 0x5c) && repeat_auto_key) {
445                                 double usec = (double)repeat_time_long * 1000.0;
446                                 if((repeat_keycode == 0) && repeat_mode) {
447                                         if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
448                                         event_keyrepeat = -1;
449                                         register_event(this,
450                                                                    ID_KEYBOARD_AUTOREPEAT_FIRST,
451                                                                    usec, false, &event_keyrepeat);
452                                 }
453                                 repeat_keycode = scancode;
454                         }
455                 }
456         }
457 }
458
459 #if defined(_FM77AV_VARIANTS)
460 void KEYBOARD::adjust_rtc(void)
461 {
462         get_host_time(&cur_time);
463         rtc_yy = cur_time.year % 100;
464         rtc_mm = cur_time.month;
465         rtc_dd = cur_time.day;
466
467         rtc_dayofweek = cur_time.day_of_week;
468         if(rtc_count24h) {
469                 rtc_ispm = (cur_time.hour >= 12) ? true : false;
470                 rtc_hour = cur_time.hour % 12;
471         } else {
472                 rtc_ispm = false;
473                 rtc_hour = cur_time.hour;
474         }
475         rtc_minute = cur_time.minute;
476         rtc_sec = cur_time.second;
477         if(event_key_rtc >= 0) {
478                 cancel_event(this, event_key_rtc);
479         }
480         register_event(this, ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
481 }
482 #endif
483
484 void KEYBOARD::do_repeatkey(uint8_t sc)
485 {
486         uint16_t code;
487         if((sc == 0) || (sc >= 0x5c)) return; // scancode overrun.
488         if(!repeat_mode) {
489                 if(event_keyrepeat >= 0) {
490                         cancel_event(this, event_keyrepeat);
491                         event_keyrepeat = -1;
492                 }
493                 return;
494         }
495         if(keymode == KEYMODE_SCAN) {
496                 code = (uint16_t)(sc & 0x7f);
497                 key_fifo->write((uint32_t)code); // Make
498                 //key_fifo->write((uint32_t)(code | 0x80)); // Break
499         } else {
500                 code = scan2fmkeycode(sc);
501                 if(code < 0x400) {
502                         key_fifo->write((uint32_t)code);
503                 }
504         }
505 }
506
507 void KEYBOARD::event_callback(int event_id, int err)
508 {
509 #if defined(_FM77AV_VARIANTS)
510         if(event_id == ID_KEYBOARD_RXRDY_OK) {
511                 rxrdy_status = true;
512                 write_signals(&rxrdy, 0xff);
513         } else if(event_id == ID_KEYBOARD_RXRDY_BUSY) {
514                 rxrdy_status = false;
515                 write_signals(&rxrdy, 0x00);
516         } else if(event_id == ID_KEYBOARD_ACK) {
517                 key_ack_status = true;
518                 write_signals(&key_ack, 0xff);
519         } else if(event_id == ID_KEYBOARD_RTC_COUNTUP) {
520                 rtc_count();
521         } else if(event_id == ID_KEYBOARD_HIDDENMESSAGE_AV) {
522                 if(hidden_message_77av_1[hidden1_ptr] == 0x00) {
523                         cancel_event(this, event_hidden1_av);
524                         event_hidden1_av = -1;
525                         hidden1_ptr = 0;
526                 } else {
527                         key_fifo->write(hidden_message_77av_1[hidden1_ptr++]);
528                 }
529                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
530                 beep->write_signal(SIG_BEEP_ON, 1, 1);
531                 register_event(this,
532                        ID_KEYBOARD_HIDDEN_BEEP_OFF,
533                        25.0 * 1000.0, false, NULL);
534         } else  if(event_id == ID_KEYBOARD_HIDDEN_BEEP_ON) {
535                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
536                 beep->write_signal(SIG_BEEP_ON, 1, 1);
537                 register_event(this,
538                        ID_KEYBOARD_HIDDEN_BEEP_OFF,
539                        25.0 * 1000.0, false, NULL);
540
541         } else  if(event_id == ID_KEYBOARD_HIDDEN_BEEP_OFF) {
542                 beep->write_signal(SIG_BEEP_MUTE, 0, 1);
543                 beep->write_signal(SIG_BEEP_ON, 0, 1);
544         } else if(event_id == ID_KEYBOARD_BREAK_ONESHOT) {
545                 if(break_pressed) this->write_signals(&break_line, 0xff);
546         } else
547 #endif
548         if(event_id == ID_KEYBOARD_AUTOREPEAT_FIRST) {
549                 double usec = (double)repeat_time_short * 1000.0;
550
551                 do_repeatkey(repeat_keycode);
552                 register_event(this,
553                                ID_KEYBOARD_AUTOREPEAT,
554                                usec, true, &event_keyrepeat);
555                 // Key repeat.
556         } else if(event_id == ID_KEYBOARD_AUTOREPEAT){
557                 if(repeat_keycode != 0) {
558                         do_repeatkey(repeat_keycode);
559                 } else {
560                         cancel_event(this, event_keyrepeat);
561                         event_keyrepeat = -1;
562                 }
563         } else if(event_id == ID_KEYBOARD_INT) {
564                 if(!(key_fifo->empty())) {
565                         keycode_7 = key_fifo->read();
566                         this->write_signals(&int_line, 0xffffffff);
567                 }
568         } else if(event_id == ID_KEYBOARD_AUTO_8KEY_START) {
569                 if(keymode != KEYMODE_SCAN) {
570                         scancode = 0x3b; // 8
571                         autokey_backup = 0x00;
572                         key_down_main(false);
573                         register_event(this,
574                                                    ID_KEYBOARD_AUTO_8KEY_END,
575                                                    50.0 * 1000.0, false, NULL);
576                 }
577         } else if(event_id == ID_KEYBOARD_AUTO_8KEY_END) {
578                 key_up_main(0x3b); // 8
579         } else if(event_id == ID_KEYBOARD_AUTO_5KEY_START) {
580                 if(keymode != KEYMODE_SCAN) {
581                         scancode = 0x3f; // 5
582                         autokey_backup = 0x00;
583                         key_down_main(false);
584                         register_event(this,
585                                                    ID_KEYBOARD_AUTO_5KEY_END,
586                                                    50.0 * 1000.0, false, NULL);
587                 }
588         } else if(event_id == ID_KEYBOARD_AUTO_5KEY_END) {
589                 key_up_main(0x3f); // 5
590         }
591 }
592
593 // Commands
594 void KEYBOARD::reset_unchange_mode(void)
595 {
596         repeat_time_short = 70; // mS
597         repeat_time_long = 700; // mS
598         repeat_mode = true;
599         older_vk = 0;
600
601         lshift_pressed = false;
602         rshift_pressed = false;
603         shift_pressed = false;
604         ctrl_pressed   = false;
605         graph_pressed = false;
606         kana_pressed = false;
607         caps_pressed = false;
608         //      ins_pressed = false;
609         datareg = 0x00;
610         repeat_keycode = 0x00;
611         autokey_backup = 0x00;
612
613 #if defined(_FM77AV_VARIANTS)
614         cmd_fifo->clear();
615         data_fifo->clear();
616         if(event_key_rtc >= 0) {
617                 cancel_event(this, event_key_rtc);
618         }
619         register_event(this,ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
620
621         cmd_phase = 0;
622         if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
623         event_keyrepeat = -1;
624    
625         if(event_hidden1_av >= 0) cancel_event(this, event_hidden1_av);
626         event_hidden1_av = -1;
627         hidden1_ptr = 0;
628 #endif
629         // Bus
630         this->write_signals(&break_line, 0x00);
631 #if defined(_FM77AV_VARIANTS)
632         rxrdy_status = false;
633         key_ack_status = true;
634         this->write_signals(&rxrdy, 0x00);                
635         this->write_signals(&key_ack, 0xff);              
636 #endif
637         this->write_signals(&kana_led, 0x00);             
638         this->write_signals(&caps_led, 0x00);             
639         this->write_signals(&ins_led, 0x00);
640 }
641
642
643 void KEYBOARD::reset(void)
644 {
645         keymode = KEYMODE_STANDARD;
646         scancode = 0x00;
647
648         keycode_7 = 0xffffffff; 
649         reset_unchange_mode();
650         this->write_signals(&int_line, 0x00000000);
651         key_fifo->clear();
652 #if defined(_FM77AV_VARIANTS)  
653         adjust_rtc();
654         did_hidden_message_av_1 = false;
655         beep_phase = 0;
656 #endif
657         
658         if(event_int >= 0) cancel_event(this, event_int);
659         register_event(this,
660                        ID_KEYBOARD_INT,
661                        20000.0, true, &event_int);
662 }
663
664
665 #if defined(_FM77AV_VARIANTS)  
666 // 0xd431 : Read
667 uint8_t KEYBOARD::read_data_reg(void)
668 {
669         if(!data_fifo->empty()) {
670                 datareg = data_fifo->read() & 0xff;
671         }
672         if(!data_fifo->empty()) {
673                 rxrdy_status = true;
674                 write_signals(&rxrdy, 0xff);
675         } else {
676                 rxrdy_status = false;
677                 write_signals(&rxrdy, 0x00);
678         }
679         return datareg;
680 }
681
682 // 0xd432
683 uint8_t KEYBOARD::read_stat_reg(void)
684 {
685         uint8_t data = 0xff;
686         if(rxrdy_status) {
687                 data &= 0x7f;
688         }
689         if(!key_ack_status) {
690                 data &= 0xfe;
691         }
692         // Digityze : bit0 = '0' when waiting,
693         return data;
694 }
695
696 void KEYBOARD::set_mode(void)
697 {
698         int count = cmd_fifo->count();
699         int cmd;
700         int mode;
701         if(count < 2) return;
702         cmd = cmd_fifo->read();
703         mode = cmd_fifo->read();
704         if(mode <= KEYMODE_SCAN) {
705                 keymode = mode;
706                 //printf("Keymode : %d\n", keymode);
707                 //reset_unchange_mode();
708                 beep_phase = 0;
709                 autokey_backup = 0x00;
710                 this->write_signals(&break_line, 0x00);
711                 if(scancode != 0) key_down_main(true); 
712         }
713         cmd_fifo->clear();
714         data_fifo->clear(); // right?
715         rxrdy_status = false;
716         write_signals(&rxrdy, 0x00);
717 }
718
719 void KEYBOARD::get_mode(void)
720 {
721         int cmd;
722         int dummy;
723         cmd = cmd_fifo->read();
724         if(data_fifo->full()) {
725                 dummy = data_fifo->read();
726         }
727         data_fifo->write(keymode);
728         rxrdy_status = true;
729         write_signals(&rxrdy, 0xff);
730 }
731
732 void KEYBOARD::set_leds(void)
733 {
734         int count = cmd_fifo->count();
735         int cmd;
736         int ledvar;
737         if(count < 2) return;
738         cmd = cmd_fifo->read();
739         ledvar = cmd_fifo->read();
740         if(ledvar < 4) {
741                 if((ledvar & 0x02) != 0) {
742                         // Kana
743                         kana_pressed = ((ledvar & 0x01) == 0);
744                         write_signals(&kana_led, kana_pressed);
745                 } else {
746                         // Caps
747                         caps_pressed = ((ledvar & 0x01) == 0);
748                         write_signals(&caps_led, caps_pressed);
749                 }
750         }
751         cmd_fifo->clear();
752         data_fifo->clear(); // right?
753         rxrdy_status = false;
754         write_signals(&rxrdy, 0x00);
755 }
756
757 void KEYBOARD::get_leds(void)
758 {
759         uint8_t ledvar = 0x00;
760         data_fifo->clear();
761         ledvar |= caps_pressed ? 0x01 : 0x00;
762         ledvar |= kana_pressed ? 0x02 : 0x00;
763         data_fifo->write(ledvar);
764         cmd_fifo->clear();
765         rxrdy_status = true;
766         write_signals(&rxrdy, 0xff);
767 }
768
769 void KEYBOARD::set_repeat_type(void)
770 {
771         int cmd;
772         int modeval;
773
774         cmd = cmd_fifo->read();
775         if(!cmd_fifo->empty()) {
776                 modeval = cmd_fifo->read();
777                 if((modeval < 2) && (modeval >= 0)) {
778                         repeat_mode = (modeval == 0);
779                         if(repeat_mode) {
780                                 //scancode = 0x00;
781                                 //keycode_7 = 0x00;
782                                 key_fifo->clear();
783                         }
784                 }
785         }
786         data_fifo->clear();
787         cmd_fifo->clear();
788         rxrdy_status = false;
789         write_signals(&rxrdy, 0x00);
790 }
791
792 void KEYBOARD::set_repeat_time(void)
793 {
794         int cmd;
795         uint32_t time_high = 0;
796         uint32_t time_low = 0;
797         cmd = cmd_fifo->read();
798         if(cmd_fifo->empty()) goto _end;
799         time_high = cmd_fifo->read();
800         if(cmd_fifo->empty()) goto _end;
801         time_low = cmd_fifo->read();
802 _end:
803         if((time_high == 0) || (time_low == 0)) {
804                 repeat_time_long = 700;
805                 repeat_time_short = 70;
806         } else {
807                 repeat_time_long = (int)time_high * 10;
808                 repeat_time_short = (int)time_low * 10;
809         }
810         data_fifo->clear();
811         cmd_fifo->clear();
812         rxrdy_status = false;
813         write_signals(&rxrdy, 0x00);
814 }
815
816 void KEYBOARD::set_rtc(void)
817 {
818         int cmd;
819         int tmp;
820         int localcmd;
821         if(cmd_fifo->count() < 9) return;
822         cmd = cmd_fifo->read();
823         localcmd = cmd_fifo->read();
824         // YY
825         tmp = cmd_fifo->read();
826         rtc_yy = ((tmp >> 4) * 10) | (tmp & 0x0f);
827         // MM
828         tmp = cmd_fifo->read();
829         rtc_mm = ((tmp >> 4) * 10) | (tmp & 0x0f);
830         // DD
831         tmp = cmd_fifo->read();
832         rtc_dd = (((tmp & 0x30) >> 4) * 10) | (tmp & 0x0f);
833         // DayOfWeek + Hour
834         tmp = cmd_fifo->read();
835         rtc_count24h = ((tmp & 0x08) != 0);
836         if(!rtc_count24h) {
837                 rtc_ispm = ((tmp & 0x04) != 0);
838         }
839         rtc_dayofweek = (tmp >> 4) % 0x07;
840         rtc_hour = ((tmp & 0x03) * 10);
841         // Low
842         tmp = cmd_fifo->read();
843         rtc_hour = rtc_hour | (tmp >> 4);
844         if(rtc_count24h) {
845           rtc_ispm = (rtc_hour >= 12);
846         }
847         rtc_minute = (tmp & 0x0f) * 10;
848         
849         tmp = cmd_fifo->read();
850         rtc_minute = rtc_minute | (tmp >> 4);
851         rtc_sec = (tmp & 0x0f) * 10;
852         
853         tmp = cmd_fifo->read();
854         rtc_sec = rtc_sec | (tmp >> 4);
855         
856         data_fifo->clear();
857         cmd_fifo->clear();
858         if(event_key_rtc >= 0) {
859                 cancel_event(this, event_key_rtc);
860         }
861         register_event(this, ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
862         rxrdy_status = false;
863         write_signals(&rxrdy, 0x00);
864 }
865
866 void KEYBOARD::get_rtc(void)
867 {
868         int tmp;
869         data_fifo->clear();
870         // YY
871         tmp = ((rtc_yy / 10) << 4) | (rtc_yy % 10);
872         data_fifo->write(tmp);
873         // MM
874         tmp = ((rtc_mm / 10) << 4) | (rtc_mm % 10);
875         data_fifo->write(tmp);
876         // DD
877         tmp = ((rtc_dd / 10) << 4) | (rtc_dd % 10);
878         tmp = tmp | (0 << 6); // leap
879         data_fifo->write(tmp);
880         // DayOfWeek + Hour
881         tmp = rtc_dayofweek << 4;
882         tmp = tmp | (rtc_hour / 10);
883         if(rtc_count24h) {
884           tmp = tmp | 0x08;
885         } else {
886           if(rtc_ispm) {
887             tmp = tmp | 0x04;
888           }
889         }
890         data_fifo->write(tmp);
891         // Low
892         tmp = (rtc_hour % 10) << 4;
893         tmp = tmp | (rtc_minute / 10);
894         data_fifo->write(tmp);
895         
896         tmp = (rtc_minute % 10) << 4;
897         tmp = tmp | (rtc_sec / 10);
898         data_fifo->write(tmp);
899         
900         tmp = (rtc_sec % 10) << 4;
901         data_fifo->write(tmp);
902         
903         cmd_fifo->clear();
904         rxrdy_status = true;
905         write_signals(&rxrdy, 0xff);
906 }
907
908 const int rtc_month_days[12] = {
909         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
910 };
911
912 void KEYBOARD::rtc_count(void)
913 {
914         // count per 1sec
915         rtc_sec++;
916         if(rtc_sec >= 60) {
917                 rtc_sec = 0;
918                 rtc_minute++;
919                 if(rtc_minute >= 60) {
920                         rtc_minute = 0;
921                         rtc_hour++;
922                         if(rtc_count24h) {
923                                 rtc_ispm = (rtc_hour >= 12);
924                                 if(rtc_hour < 24) return;
925                         } else {
926                                 if(rtc_ispm) {
927                                         if(rtc_hour < 12) return;
928                                 } else {
929                                         if(rtc_hour < 12) return;
930                                         rtc_ispm = true;
931                                         rtc_hour = 0;
932                                         return;
933                                 }
934                         }
935                         // Day count up
936                         rtc_hour = 0;
937                         rtc_dd++;
938                         rtc_dayofweek++;
939                         if(rtc_dayofweek >= 7) rtc_dayofweek = 0;
940                         if(rtc_dd > rtc_month_days[rtc_mm]){
941                                 if((rtc_mm ==1) && (rtc_dd == 29)) {
942                                         if((rtc_yy % 4) == 0) return;
943                                 }
944                                 rtc_dd = 1;
945                                 rtc_mm++;
946                                 if(rtc_mm >= 12) {
947                                         rtc_yy++;
948                                         rtc_mm = 0;
949                                         if(rtc_yy >= 100) rtc_yy = 0;
950                                 }
951                         }
952                 }
953         }
954 }
955 #endif // FM77AV_VARIANTS
956
957 uint32_t KEYBOARD::read_signal(int id)
958 {
959         if(id == SIG_FM7KEY_BREAK_KEY) {
960                 return break_pressed ? 0xfffffff : 0x00000000;
961         }
962         return 0;
963 }
964
965
966 void KEYBOARD::write_signal(int id, uint32_t data, uint32_t mask)
967 {
968         if(id == SIG_FM7KEY_SET_INSLED) {
969                 write_signals(&ins_led, data & mask);
970         }
971 #if defined(_FM77AV_VARIANTS)  
972          else if(id == SIG_FM7KEY_PUSH_TO_ENCODER) {
973                 /*
974                  * I refered XM7's sourcecode : VM/keyboard.c act of key-encoder.
975                  * Thanks to Ryu.Takegami and PI.
976                  */
977                 int count;
978                 if(!key_ack_status) return; // If (not(ACK)) noop.
979
980                 if(cmd_fifo->full()) {
981                         cmd_fifo->clear();
982                 }
983                 if(cmd_fifo->empty()) {
984                         cmd_phase = data & 0xff;
985                 }
986                 
987                 cmd_fifo->write(data & 0xff);
988                 count = cmd_fifo->count();
989                 
990                 rxrdy_status = false;
991                 key_ack_status = false;
992                 write_signals(&key_ack, 0x00);
993                 write_signals(&rxrdy, 0x00);
994             
995                 switch(cmd_phase) {
996                         case 0: // Set mode
997                                 if(count >= 2) {
998                                         set_mode();
999                                         if(keymode == KEYMODE_SCAN) key_down_main(true);
1000                                         cmd_phase = -1;
1001                                         cmd_fifo->clear();
1002                                 }
1003                                 break;
1004                         case 1: // Get mode
1005                                 get_mode();
1006                                 cmd_fifo->clear();
1007                                 cmd_phase = -1;
1008                                 break;
1009                         case 2: // Set LED Phase
1010                                 if(count >= 2) {
1011                                         set_leds();
1012                                         if(keymode == KEYMODE_SCAN) key_down_main(true);
1013                                         cmd_phase = -1;
1014                                         cmd_fifo->clear();
1015                                 }
1016                                 break;
1017                         case 3: // Get LED Phase
1018                                 get_leds();
1019                                 cmd_phase = -1;
1020                                 cmd_fifo->clear();
1021                                 break;
1022                         case 4:
1023                                 if(count >= 2) {
1024                                         set_repeat_type();
1025                                         cmd_phase = -1;
1026                                         cmd_fifo->clear();
1027                                 }
1028                                 break;
1029                         case 5:
1030                                 if(count >= 3) {
1031                                         set_repeat_time();
1032                                         cmd_phase = -1;
1033                                         cmd_fifo->clear();
1034                                 }
1035                                 break;
1036                         case 0x80: // Communicate to/from RTC.
1037                                 if(count == 1) {
1038                                         rtc_set = false;
1039                                 }
1040                                 if(count == 2) {
1041                                         if((data & 0xff) == 0) { // Get
1042                                                 get_rtc();
1043                                                 cmd_phase = -1;
1044                                                 cmd_fifo->clear();
1045                                         } else if((data & 0xff) == 1) { // Set
1046                                                 rtc_set_flag = true;
1047                                         } else { // Illegal
1048                                                 cmd_fifo->clear();
1049                                                 cmd_phase = -1;
1050                                         }
1051                                 }
1052                                 if(rtc_set_flag) {
1053                                         if(count >= 9) {
1054                                                 set_rtc();
1055                                                 cmd_fifo->clear();
1056                                                 cmd_phase = -1;
1057                                         }
1058                                 }
1059                                 break;
1060                         case 0x81: // Digitize.
1061                                 if(count >= 2) {
1062                                         do_digitize(); // WILL Implement?
1063                                         cmd_fifo->clear();
1064                                         cmd_phase = -1;
1065                                 }
1066                                 break;
1067                         case 0x82:
1068                                 if(count >= 2) {
1069                                         set_screen_mode(); // WILL Implement?
1070                                         cmd_fifo->clear();
1071                                         cmd_phase = -1;
1072                                 }
1073                                 break;
1074                         case 0x83:
1075                                 get_screen_mode(); // WILL Implement?
1076                                 cmd_fifo->clear();
1077                                 cmd_phase = -1;
1078                                 break;
1079                         case 0x84:
1080                                 if(count >= 2) {
1081                                         set_brightness(); // WILL Implement?
1082                                         cmd_fifo->clear();
1083                                         cmd_phase = -1;
1084                                 }
1085                                 break;
1086                         default:
1087                                 cmd_fifo->clear();
1088                                 cmd_phase = -1;
1089                                 break;
1090                 }
1091                 register_event(this, ID_KEYBOARD_ACK, 5, false, NULL); // Delay 5us until ACK is up.
1092         } else if(id == SIG_FM7KEY_RXRDY) {
1093                 rxrdy_status = ((data & mask) != 0);
1094                 //write_signals(&rxrdy, (rxrdy_status) ? 0xffffffff : 0x00000000);
1095         } else if(id == SIG_FM7KEY_ACK) {
1096                 key_ack_status = ((data & mask) != 0);
1097                 //write_signals(&key_ack, (key_ack_status) ? 0xffffffff : 0x00000000);
1098         }
1099
1100 #endif
1101 }
1102
1103 uint32_t KEYBOARD::read_data8(uint32_t addr)
1104 {
1105         uint32_t retval = 0xff;
1106         switch(addr) {
1107                 case 0x00:
1108                         retval = get_keycode_high();
1109                         break;
1110                 case 0x01:
1111                         retval = get_keycode_low();
1112                         break;
1113 #if defined(_FM77AV_VARIANTS)                   
1114                 case 0x31:
1115                         retval = read_data_reg();
1116                         break;
1117                 case 0x32:
1118                         retval = read_stat_reg();
1119                         break;
1120 #endif
1121                 default:
1122                         break;
1123         }
1124         return retval;
1125 }
1126
1127 void KEYBOARD::write_data8(uint32_t addr, uint32_t data)
1128 {
1129         switch(addr) {
1130 #if defined(_FM77AV_VARIANTS)                   
1131                 case 0x31:
1132                         this->write_signal(SIG_FM7KEY_PUSH_TO_ENCODER, data, 0x000000ff);
1133                         break;
1134 #endif
1135         }
1136 }
1137
1138 KEYBOARD::KEYBOARD(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
1139 {
1140         p_vm = parent_vm;
1141         p_emu = parent_emu;
1142         
1143 #if defined(_FM77AV_VARIANTS)
1144         beep = NULL;
1145 #endif  
1146         keycode_7 = 0xffffffff;
1147    
1148         ctrl_pressed = false; 
1149         lshift_pressed = false; 
1150         rshift_pressed = false; 
1151         shift_pressed = false; 
1152         graph_pressed = false;
1153         caps_pressed = false;
1154         kana_pressed = false;
1155         break_pressed = false;
1156         event_keyrepeat = -1;
1157         autokey_backup = 0x00;
1158
1159         keymode = KEYMODE_STANDARD;
1160 #if defined(_FM77AV_VARIANTS)
1161         cmd_fifo = new FIFO(16);
1162         data_fifo = new FIFO(16);
1163         rxrdy_status = true;
1164         key_ack_status = false;
1165         initialize_output_signals(&rxrdy);
1166         initialize_output_signals(&key_ack);
1167         
1168         rtc_count24h = false;
1169         rtc_dayofweek = 0;
1170         rtc_ispm = false;
1171         rtc_set = false;
1172         rtc_set_flag = false;
1173         rtc_yy = 0;
1174         rtc_mm = 0;
1175         rtc_dd = 0;
1176         rtc_hour = 0;
1177         rtc_minute = 0;
1178         rtc_sec = 0;
1179         event_key_rtc = -1;
1180         event_hidden1_av = -1;
1181         hidden1_ptr = 0;
1182 #endif
1183         key_fifo = new FIFO(512);
1184         event_int = -1;
1185         
1186         initialize_output_signals(&break_line);
1187         initialize_output_signals(&int_line);
1188         
1189         initialize_output_signals(&kana_led);
1190         initialize_output_signals(&caps_led);
1191         initialize_output_signals(&ins_led);
1192         set_device_name(_T("KEYBOARD SUBSYSTEM"));
1193 }
1194
1195 void KEYBOARD::release(void)
1196 {
1197 #if defined(_FM77AV_VARIANTS)
1198         cmd_fifo->release();
1199         data_fifo->release();
1200         delete cmd_fifo;
1201         delete data_fifo;
1202 #endif   
1203         key_fifo->release();
1204         delete key_fifo;
1205 }
1206
1207
1208
1209 KEYBOARD::~KEYBOARD()
1210 {
1211 }
1212
1213 #define STATE_VERSION 4
1214 void KEYBOARD::save_state(FILEIO *state_fio)
1215 {
1216         state_fio->FputUint32_BE(STATE_VERSION);
1217         state_fio->FputInt32_BE(this_device_id);
1218         this->out_debug_log("Save State: KEYBOARD: id=%d ver=%d\n", this_device_id, STATE_VERSION);
1219
1220         // Version 1
1221         {
1222                 state_fio->FputUint32_BE(keycode_7);
1223                 state_fio->FputInt32_BE(keymode);
1224            
1225                 state_fio->FputBool(ctrl_pressed);
1226                 state_fio->FputBool(lshift_pressed);
1227                 state_fio->FputBool(rshift_pressed);
1228                 state_fio->FputBool(shift_pressed);
1229                 state_fio->FputBool(graph_pressed);
1230                 state_fio->FputBool(caps_pressed);
1231                 state_fio->FputBool(kana_pressed);
1232                 state_fio->FputBool(break_pressed);
1233
1234                 state_fio->FputInt32_BE(event_keyrepeat);
1235            
1236                 state_fio->FputUint8(scancode); // After V.4, uint8_t
1237                 state_fio->FputUint8(datareg);
1238                 state_fio->FputUint32(older_vk);
1239            
1240                 state_fio->FputBool(repeat_mode);
1241                 state_fio->FputInt32_BE(repeat_time_short);
1242                 state_fio->FputInt32_BE(repeat_time_long);
1243                 state_fio->FputUint8(repeat_keycode);
1244            
1245 #if defined(_FM77AV_VARIANTS)
1246                 state_fio->FputInt32_BE(event_key_rtc);
1247   
1248                 state_fio->FputUint8(rtc_yy);
1249                 state_fio->FputUint8(rtc_mm);
1250                 state_fio->FputUint8(rtc_dd);
1251                 state_fio->FputUint8(rtc_dayofweek);
1252                 state_fio->FputUint8(rtc_hour);
1253                 state_fio->FputUint8(rtc_minute);
1254                 state_fio->FputUint8(rtc_sec);
1255
1256                 state_fio->FputBool(rtc_count24h);
1257                 state_fio->FputBool(rtc_ispm);
1258
1259                 state_fio->FputBool(rtc_set);
1260                 state_fio->FputBool(rtc_set_flag);
1261                 state_fio->FputBool(rxrdy_status);
1262                 state_fio->FputBool(key_ack_status);
1263                 state_fio->FputInt32_BE(cmd_phase);
1264
1265                 state_fio->FputInt32_BE(event_hidden1_av);
1266                 state_fio->FputUint16_BE(hidden1_ptr);
1267
1268                 cmd_fifo->save_state((void *)state_fio);
1269                 data_fifo->save_state((void *)state_fio);
1270                 cur_time.save_state((void *)state_fio);
1271 #endif
1272                 state_fio->FputInt32_BE(event_int);
1273                 key_fifo->save_state((void *)state_fio);
1274         }
1275         // Version 2
1276         {
1277 #if defined(_FM77AV_VARIANTS)
1278                 state_fio->FputBool(did_hidden_message_av_1);
1279 #endif
1280         }
1281         // Version 3
1282         {
1283 #if defined(_FM77AV_VARIANTS)
1284                 state_fio->FputInt32_BE(beep_phase);
1285 #endif
1286         }
1287         // Version 4
1288         state_fio->FputUint8(autokey_backup);
1289 }
1290
1291 bool KEYBOARD::load_state(FILEIO *state_fio)
1292 {
1293         uint32_t version;
1294         
1295         version = state_fio->FgetUint32_BE();
1296         if(this_device_id != state_fio->FgetInt32_BE()) return false;
1297         this->out_debug_log("Load State: KEYBOARD: id=%d ver=%d\n", this_device_id, version);
1298
1299         if(version >= 1) {
1300                 keycode_7 = state_fio->FgetUint32_BE();
1301                 keymode = state_fio->FgetInt32_BE();
1302            
1303                 ctrl_pressed = state_fio->FgetBool();
1304                 lshift_pressed = state_fio->FgetBool();
1305                 rshift_pressed = state_fio->FgetBool();
1306                 shift_pressed = state_fio->FgetBool();
1307                 graph_pressed = state_fio->FgetBool();
1308                 caps_pressed = state_fio->FgetBool();
1309                 kana_pressed = state_fio->FgetBool();
1310                 break_pressed = state_fio->FgetBool();
1311
1312                 event_keyrepeat = state_fio->FgetInt32_BE();
1313            
1314                 scancode = state_fio->FgetUint8();
1315                 datareg = state_fio->FgetUint8();
1316                 older_vk = state_fio->FgetUint32();
1317            
1318                 repeat_mode = state_fio->FgetBool();
1319                 repeat_time_short = state_fio->FgetInt32_BE();
1320                 repeat_time_long = state_fio->FgetInt32_BE();
1321                 repeat_keycode = state_fio->FgetUint8();
1322            
1323 #if defined(_FM77AV_VARIANTS)
1324                 event_key_rtc = state_fio->FgetInt32_BE();
1325                 rtc_yy = state_fio->FgetUint8();
1326                 rtc_mm = state_fio->FgetUint8();
1327                 rtc_dd = state_fio->FgetUint8();
1328                 rtc_dayofweek = state_fio->FgetUint8();
1329                 rtc_hour = state_fio->FgetUint8();
1330                 rtc_minute = state_fio->FgetUint8();
1331                 rtc_sec = state_fio->FgetUint8();
1332
1333                 rtc_count24h = state_fio->FgetBool();
1334                 rtc_ispm = state_fio->FgetBool();
1335
1336                 rtc_set = state_fio->FgetBool();
1337                 rtc_set_flag = state_fio->FgetBool();
1338                 rxrdy_status = state_fio->FgetBool();
1339                 key_ack_status = state_fio->FgetBool();
1340                 cmd_phase = state_fio->FgetInt32_BE();
1341
1342                 event_hidden1_av = state_fio->FgetInt32_BE();
1343                 hidden1_ptr = state_fio->FgetUint16_BE();
1344
1345                 cmd_fifo->load_state((void *)state_fio);
1346                 data_fifo->load_state((void *)state_fio);
1347                 cur_time.load_state((void *)state_fio);
1348 #endif
1349                 event_int = state_fio->FgetInt32_BE();
1350                 key_fifo->load_state((void *)state_fio);
1351                 if(version == 1) return true;
1352         }
1353         // Version 2
1354         {
1355 #if defined(_FM77AV_VARIANTS)
1356                 did_hidden_message_av_1 = state_fio->FgetBool();
1357 #endif
1358         }
1359         // Version 3
1360         {
1361 #if defined(_FM77AV_VARIANTS)
1362                 beep_phase = state_fio->FgetInt32_BE();
1363 #endif
1364         }
1365         // Version 4
1366         autokey_backup = state_fio->FgetUint8();
1367         if(version == STATE_VERSION) {
1368                 return true;
1369         }
1370         return false;
1371 }
1372
1373