OSDN Git Service

[VM] TRY:Use namespace {VMNAME} to separate around VMs. This feature still apply...
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / keyboard.cpp
index d19ee5f..f479e55 100644 (file)
@@ -6,29 +6,58 @@
  *  Feb 12, 2015 : Initial 
  */
 
+#include "vm.h"
+#include "emu.h"
 #include "../../fifo.h"
 #include "../device.h"
-#include "fm7_keyboard.h"
 
+#include "fm7_keyboard.h"
 #include "keyboard_tables.h"
 
+#if defined(_FM77AV_VARIANTS)
+#include "../beep.h"
+
+namespace FM7 {
+       #include "fm77av_hidden_message_keyboard.h"
+}
+#endif
+
+namespace FM7 {
+
+enum {
+       ID_KEYBOARD_RXRDY_OK = 1,
+       ID_KEYBOARD_ACK,
+       ID_KEYBOARD_RXRDY_BUSY,
+       ID_KEYBOARD_RTC_COUNTUP,
+       ID_KEYBOARD_INT,
+       ID_KEYBOARD_AUTOREPEAT_FIRST,
+       ID_KEYBOARD_AUTOREPEAT,
+       ID_KEYBOARD_HIDDENMESSAGE_AV,
+       ID_KEYBOARD_HIDDEN_BEEP_ON,
+       ID_KEYBOARD_HIDDEN_BEEP_OFF,
+       ID_KEYBOARD_AUTO_8KEY_START,
+       ID_KEYBOARD_AUTO_8KEY_END,
+       ID_KEYBOARD_AUTO_5KEY_START,
+       ID_KEYBOARD_AUTO_5KEY_END,
+       ID_KEYBOARD_BREAK_ONESHOT,
+};
+
 //
 /*
  * I/O API (subio)
  */
 // 0xd400(SUB) or 0xfd00(MAIN)
-uint8 KEYBOARD::get_keycode_high(void)
+uint8_t KEYBOARD::get_keycode_high(void)
 {
-       uint8 data = 0x00;
+       uint8_t data = 0x00;
        if((keycode_7 & 0x0100) != 0) data = 0x80;
-       //this->write_signals(&int_line, 0x00000000);
        return data;
 }
 
 // 0xd401(SUB) or 0xfd01(MAIN)
-uint8 KEYBOARD::get_keycode_low(void)
+uint8_t KEYBOARD::get_keycode_low(void)
 {
-       uint8 data = keycode_7 & 0xff;
+       uint8_t data = keycode_7 & 0xff;
        this->write_signals(&int_line, 0x00000000);
        return data;
 }
@@ -36,20 +65,21 @@ uint8 KEYBOARD::get_keycode_low(void)
 // 0xd40d : R
 void KEYBOARD::turn_on_ins_led(void)
 {
-       this->write_signals(&ins_led, 0xff);
+       ins_led_status = true;
 }
 
 // 0xd40d : W
 void KEYBOARD::turn_off_ins_led(void)
 {
-       this->write_signals(&ins_led, 0x00);
+       ins_led_status = false;
 }
 
 // UI Handler. 
-uint16 KEYBOARD::vk2scancode(uint32 vk)
+uint16_t KEYBOARD::vk2scancode(uint32_t vk)
 {
-       uint16 i;
+       uint16_t i;
        i = 0;
+       if(vk == VK_PAUSE) vk = VK_KANJI; // Workaround some desktop environments for [ESC].
        do {
                if(vk_matrix_106[i] == vk) return i;
                i++;
@@ -57,7 +87,7 @@ uint16 KEYBOARD::vk2scancode(uint32 vk)
        return 0x0000;
 }
 
-bool KEYBOARD::isModifier(uint16 sc)
+bool KEYBOARD::isModifier(uint8_t sc)
 {
        if(((sc >= 0x52) && (sc <= 0x56)) || // CTRL LSHIFT RSHIFT CAPS GRPH
                (sc == 0x5a) || (sc == 0x5c)) { // KANA BREAK
@@ -66,24 +96,18 @@ bool KEYBOARD::isModifier(uint16 sc)
        return false;
 }
 
-void KEYBOARD::set_modifiers(uint16 sc, bool flag)
+void KEYBOARD::set_modifiers(uint8_t sc, bool flag)
 {
        if(sc == 0x52) { // CTRL
                ctrl_pressed = flag; 
        } else if(sc == 0x53) { // LSHIFT
                lshift_pressed = flag;
-               if(rshift_pressed) {
-                       shift_pressed = true;
-               } else {
-                       shift_pressed = flag;
-               }
+               shift_pressed = lshift_pressed | rshift_pressed;
+               //printf("LSHIFT : %d\n", flag ? 1 : 0);
        } else if(sc == 0x54) { // RSHIFT
                rshift_pressed = flag;
-               if(lshift_pressed) {
-                 shift_pressed = true;
-               } else {
-                 shift_pressed = flag;
-               }
+               shift_pressed = lshift_pressed | rshift_pressed;
+               //printf("RSHIFT : %d\n", flag ? 1 : 0);
        } else if(sc == 0x56) { // GRPH
                graph_pressed = flag;
        } else if(sc == 0x55) { // CAPS
@@ -94,7 +118,7 @@ void KEYBOARD::set_modifiers(uint16 sc, bool flag)
                        } else {
                                caps_pressed = true;
                        }
-                       if(keymode == KEYMODE_STANDARD) this->write_signals(&caps_led, caps_pressed ? 0xff : 0x00);
+                       if(keymode == KEYMODE_STANDARD) caps_led_status = caps_pressed;
                }
        } else if(sc == 0x5a) { // KANA
                // Toggle on press.
@@ -104,19 +128,21 @@ void KEYBOARD::set_modifiers(uint16 sc, bool flag)
                        } else {
                                kana_pressed = true;
                        }
-                       if(keymode == KEYMODE_STANDARD) this->write_signals(&kana_led, kana_pressed ? 0xff : 0x00);
+                       if(keymode == KEYMODE_STANDARD) kana_led_status = kana_pressed;
                }
        } else if(sc == 0x5c) { // Break
-               break_pressed = flag;
+               if(!override_break_key) {
+                       break_pressed = flag;
+               }
        }
 }
 
-uint16 KEYBOARD::scan2fmkeycode(uint16 sc)
+uint16_t KEYBOARD::scan2fmkeycode(uint8_t sc)
 {
        const struct key_tbl_t *keyptr = NULL;
        bool stdkey = false;
        int i;
-       uint16 retval;
+       uint16_t retval;
        
        if((sc == 0) || (sc >= 0x67)) return 0xffff;
        // Set repeat flag(s)
@@ -135,7 +161,6 @@ uint16 KEYBOARD::scan2fmkeycode(uint16 sc)
                }
        }
        if(keymode == KEYMODE_STANDARD) {
-               bool dmy = isModifier(sc);
                if(ctrl_pressed) {
                        if(shift_pressed) {
                                keyptr = ctrl_shift_key;
@@ -172,11 +197,9 @@ uint16 KEYBOARD::scan2fmkeycode(uint16 sc)
          // F10: TV
        }
        if(keymode == KEYMODE_SCAN) {
-               bool dmy = isModifier(sc);
-               retval = sc;
+               retval = (uint16_t)sc;
                return retval;
        } else if(keymode == KEYMODE_16BETA) { // Will Implement
-               bool dmy = isModifier(sc);
                if(ctrl_pressed) {
                        if(shift_pressed) {
                                keyptr = ctrl_shift_key_16beta;
@@ -209,13 +232,13 @@ uint16 KEYBOARD::scan2fmkeycode(uint16 sc)
        retval = 0xffff;
        if (keyptr == NULL) return 0xffff;
        do {
-               if(keyptr[i].phy == sc) {
+               if(keyptr[i].phy == (uint16_t)sc) {
                        retval = keyptr[i].code;
                        break;
                }
                i++;
        } while(keyptr[i].phy != 0xffff);
-
+       if(keyptr[i].phy == 0xffff) return 0x00;
        if(stdkey) {
                if((retval >= 'A') && (retval <= 'Z')) {
                        if(caps_pressed) {
@@ -230,81 +253,224 @@ uint16 KEYBOARD::scan2fmkeycode(uint16 sc)
        return retval;
 }
 
-void KEYBOARD::key_up(uint32 vk)
+void KEYBOARD::key_up_main(uint8_t bak_scancode)
 {
-       uint16 bak_scancode = vk2scancode(vk);
        bool stat_break = break_pressed;
        older_vk = 0;
-       if(scancode == 0) return;
-       if((event_keyrepeat >= 0) && (bak_scancode != 0x5c)) { // Not Break
+       if(bak_scancode == 0) return;
+       if((event_keyrepeat >= 0) && (repeat_keycode == bak_scancode)) { // Not Break
                cancel_event(this, event_keyrepeat);
                event_keyrepeat = -1;
+               repeat_keycode = 0;
        }
-       if(this->isModifier(scancode)) {
-               set_modifiers(bak_scancode, false);
-               if(break_pressed != stat_break) { // Break key UP.
-                       this->write_signals(&break_line, 0x00);
+       if(keymode != KEYMODE_SCAN) {
+               if(this->isModifier(bak_scancode)) {
+                       set_modifiers(bak_scancode, false);
+                       if(break_pressed != stat_break) { // Break key UP.
+                               this->write_signals(&break_line, 0x00);
+                       }
                }
-       }
-       if(key_pressed_flag[bak_scancode] == false) return; 
-       key_pressed_flag[bak_scancode] = false; 
-       if(keymode == KEYMODE_SCAN) { // Notify even key-up, when using SCAN mode.
-               if(scancode !=  0) {   
-                       keycode_7 = (bak_scancode & 0x7f)| 0x80;
-                       this->write_signals(&int_line, 0xffffffff);
+               if((config.dipswitch & FM7_DIPSW_AUTO_5_OR_8KEY) != 0) {
+                       if((config.dipswitch & FM7_DIPSW_SELECT_5_OR_8KEY) == 0) { // Auto 8
+                               switch(bak_scancode) {
+                                       case 0x42: // 1
+                                       case 0x43: // 2
+                                       case 0x44: // 3
+                                       case 0x3f: // 5
+                                       case 0x46: // 0
+                                               register_event(this,
+                                                                          ID_KEYBOARD_AUTO_8KEY_START,
+                                                                          10.0 * 1000.0, false, NULL);
+                                               break;
+                                       default:
+                                               if(autokey_backup != 0) key_fifo->write(scan2fmkeycode(autokey_backup));
+                                               break;
+                               }
+                       } else { // Auto 5
+                               switch(bak_scancode) {
+                                       case 0x42: // 1
+                                       case 0x43: // 2
+                                       case 0x44: // 3
+                                       case 0x3e: // 4
+                                       case 0x40: // 6
+                                       case 0x3a: // 7
+                                       case 0x3b: // 8
+                                       case 0x3c: // 9
+                                               register_event(this,
+                                                                          ID_KEYBOARD_AUTO_5KEY_START,
+                                                                          10.0 * 1000.0, false, NULL);
+                                               break;
+                                       default:
+                                               if(autokey_backup != 0) key_fifo->write(scan2fmkeycode(autokey_backup));
+                                               break;
+                               }
+                       }                               
+               }
+       } else {
+               //scancode = 0;
+               if(bak_scancode != 0) { // Notify even key-up, when using SCAN mode.
+                       uint8_t code = (bak_scancode & 0x7f) | 0x80;
+                       if(this->isModifier(bak_scancode)) {
+                               set_modifiers(bak_scancode, false);
+                       }
+#if defined(_FM77AV_VARIANTS)     
+                       if(bak_scancode != 0x5c) {
+                               if(beep_phase == 1) {
+                                       if(break_pressed) this->write_signals(&break_line, 0x00);
+                                       break_pressed = false;
+                                       beep_phase++;
+                                       bak_scancode = 0x7f;
+                                       code = 0xff;
+                               } else if(beep_phase == 2) {
+                                       beep_phase = 0;
+                                       register_event(this,
+                                                                  ID_KEYBOARD_HIDDEN_BEEP_ON,
+                                                                  100.0, false, NULL); // 100.0 us is dummy.
+                                       bak_scancode = 0x7f;
+                                       code = 0xff;
+                               }
+                       } else { // 0x5c : BREAK is up.
+                               beep_phase = 0;
+                               if(stat_break) this->write_signals(&break_line, 0x00);
+                       }
+#endif            
+                       if(code != 0x80) {
+                               key_fifo->write(code);
+                               scancode = bak_scancode;
+                       }
                }
        }
 }
 
-void KEYBOARD::key_down(uint32 vk)
+void KEYBOARD::key_up(uint32_t vk)
+{
+       uint8_t bak_scancode = (uint8_t)(vk2scancode(vk) & 0x00ff);
+       key_up_main(bak_scancode);
+}
+
+void KEYBOARD::key_down(uint32_t vk)
 {
        if(older_vk == vk) return;
        older_vk = vk;
        
-       scancode = vk2scancode(vk);
-       key_down_main();
+       scancode = (uint8_t)vk2scancode(vk);
+#if defined(_FM77AV_VARIANTS)
+       // Below are FM-77AV's hidden message , see :
+       // https://twitter.com/maruan/status/499558392092831745
+       //if(caps_pressed && kana_pressed) {
+       //      if(ctrl_pressed && lshift_pressed && rshift_pressed && graph_pressed) {
+       if(caps_pressed && kana_pressed && graph_pressed && shift_pressed && ctrl_pressed && !did_hidden_message_av_1) { // IT's deprecated key pressing
+               if(scancode == 0x15) { // "T"
+                       if(event_hidden1_av < 0) {
+                               hidden1_ptr = 0;
+                               did_hidden_message_av_1 = true;
+                               register_event(this,
+                                               ID_KEYBOARD_HIDDENMESSAGE_AV,
+                                               130.0 * 1000, true, &event_hidden1_av);
+                       }
+                       return;
+               }
+       }
+#endif 
+       key_down_main(true);
 }
 
-void KEYBOARD::key_down_main(void)
+void KEYBOARD::key_down_main(bool repeat_auto_key)
 {
-       double usec = (double)repeat_time_long * 1000.0;
-       uint32 code_7;
        bool stat_break = break_pressed;
-
+       uint32_t code;
        if(scancode == 0) return;
-       if(this->isModifier(scancode)) {  // modifiers
-               set_modifiers(scancode, true);
-               if(break_pressed != stat_break) { // Break key Down.
-                       this->write_signals(&break_line, 0xff);
-               }
-               //printf("DOWN SCAN=%04x break=%d\n", scancode, break_pressed);
-       }
-       code_7 = scan2fmkeycode(scancode);
        if(keymode == KEYMODE_SCAN) {
-               code_7 = scancode & 0x7f;
-       }
-       //if(key_pressed_flag[scancode] != false) return;
-       if(code_7 < 0x200) {
-               keycode_7 = code_7;
-               if(code_7 != 0) this->write_signals(&int_line, 0xffffffff);
-       }
-   
-       // If repeat && !(PF) && !(BREAK) 
-       if((scancode < 0x5c) && (code_7 != 0xffff)) {
-               if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
-               event_keyrepeat = -1;
-               if(repeat_mode) register_event(this,
-                              ID_KEYBOARD_AUTOREPEAT_FIRST + scancode,
-                              usec, false, &event_keyrepeat);
-       }
-       key_pressed_flag[scancode] = true;
+               code = scancode & 0x7f;
+               if(this->isModifier(scancode)) {  // modifiers
+                       set_modifiers(scancode, true);
+               }
+#if defined(_FM77AV_VARIANTS)
+               if(break_pressed) {
+                       if(!stat_break) {
+                               beep_phase = 1;
+                               // It's dirty hack for AMNORK ; Set dead zone for FIRQ to 0.25sec.
+                               // I wish to replace this solution to more simple. 
+                               register_event(this,
+                                                          ID_KEYBOARD_BREAK_ONESHOT,
+                                                          250.0 * 1000.0, false, NULL);
+                       } else if(beep_phase == 1) {
+                               if(code != 0x5c) {
+                                       if(break_pressed) this->write_signals(&break_line, 0x00);
+                                       break_pressed = false;
+                                       beep_phase++;
+                                       code = 0x7f; // Special
+                                       scancode = 0x7f;        
+                               }
+                       }
+               }
+#endif
 
+               if(code != 0) {
+                       key_fifo->write(code);
+                       // NOTE: With scan key code mode, auto repeat seems to be not effectable.
+                       // See : http://hanabi.2ch.net/test/read.cgi/i4004/1430836648/607
+                       // 20160409 K.Ohta
+               }
+       } else {
+               if(this->isModifier(scancode)) {  // modifiers
+                       set_modifiers(scancode, true);
+                       if(break_pressed != stat_break) { // Break key Down.
+                               this->write_signals(&break_line, 0xff);
+                       }
+                       return;
+               }
+               code = scan2fmkeycode(scancode);
+               if((code > 0x3ff) || (code == 0)) return;
+               if((config.dipswitch & FM7_DIPSW_AUTO_5_OR_8KEY) != 0) {
+                       if((config.dipswitch & FM7_DIPSW_SELECT_5_OR_8KEY) == 0) { // Auto 8
+                               switch(scancode) {
+                                       case 0x42: // 1
+                                       case 0x43: // 2
+                                       case 0x44: // 3
+                                       case 0x3f: // 5
+                                       case 0x46: // 0
+                                               autokey_backup = scancode;
+                                               break;
+                               }
+                       } else { // Auto 5
+                               switch(scancode) {
+                                       case 0x42: // 1
+                                       case 0x43: // 2
+                                       case 0x44: // 3
+                                       case 0x3e: // 4
+                                       case 0x40: // 6
+                                       case 0x3a: // 7
+                                       case 0x3b: // 8
+                                       case 0x3c: // 9
+                                               autokey_backup = scancode;
+                                               break;
+                               }
+                       }                               
+               } else {
+                       autokey_backup = 0x00;
+               }
+               if(code != 0) {
+                       key_fifo->write(code);
+                       if((scancode < 0x5c) && repeat_auto_key) {
+                               double usec = (double)repeat_time_long * 1000.0;
+                               if((repeat_keycode == 0) && repeat_mode) {
+                                       if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
+                                       event_keyrepeat = -1;
+                                       register_event(this,
+                                                                  ID_KEYBOARD_AUTOREPEAT_FIRST,
+                                                                  usec, false, &event_keyrepeat);
+                               }
+                               repeat_keycode = scancode;
+                       }
+               }
+       }
 }
 
 #if defined(_FM77AV_VARIANTS)
 void KEYBOARD::adjust_rtc(void)
 {
-       p_emu->get_host_time(&cur_time);
+       get_host_time(&cur_time);
        rtc_yy = cur_time.year % 100;
        rtc_mm = cur_time.month;
        rtc_dd = cur_time.day;
@@ -326,10 +492,10 @@ void KEYBOARD::adjust_rtc(void)
 }
 #endif
 
-void KEYBOARD::do_repeatkey(uint16 sc)
+void KEYBOARD::do_repeatkey(uint8_t sc)
 {
-       uint16 code_7;
-       if((sc == 0) || (sc >= 0x67)) return; // scancode overrun.
+       uint16_t code;
+       if((sc == 0) || (sc >= 0x5c)) return; // scancode overrun.
        if(!repeat_mode) {
                if(event_keyrepeat >= 0) {
                        cancel_event(this, event_keyrepeat);
@@ -337,14 +503,15 @@ void KEYBOARD::do_repeatkey(uint16 sc)
                }
                return;
        }
-       key_pressed_flag[sc] = true;
-       code_7 = scan2fmkeycode(sc);
        if(keymode == KEYMODE_SCAN) {
-               code_7 = sc;
-       }
-       if(code_7 < 0x200) {
-               keycode_7 = code_7;
-               this->write_signals(&int_line, 0xffffffff);
+               code = (uint16_t)(sc & 0x7f);
+               key_fifo->write((uint32_t)code); // Make
+               //key_fifo->write((uint32_t)(code | 0x80)); // Break
+       } else {
+               code = scan2fmkeycode(sc);
+               if(code < 0x400) {
+                       key_fifo->write((uint32_t)code);
+               }
        }
 }
 
@@ -362,40 +529,102 @@ void KEYBOARD::event_callback(int event_id, int err)
                write_signals(&key_ack, 0xff);
        } else if(event_id == ID_KEYBOARD_RTC_COUNTUP) {
                rtc_count();
+       } else if(event_id == ID_KEYBOARD_HIDDENMESSAGE_AV) {
+               if(hidden_message_77av_1[hidden1_ptr] == 0x00) {
+                       cancel_event(this, event_hidden1_av);
+                       event_hidden1_av = -1;
+                       hidden1_ptr = 0;
+               } else {
+                       key_fifo->write(hidden_message_77av_1[hidden1_ptr++]);
+               }
+               beep->write_signal(SIG_BEEP_MUTE, 0, 1);
+               beep->write_signal(SIG_BEEP_ON, 1, 1);
+               register_event(this,
+                      ID_KEYBOARD_HIDDEN_BEEP_OFF,
+                      25.0 * 1000.0, false, NULL);
+       } else  if(event_id == ID_KEYBOARD_HIDDEN_BEEP_ON) {
+               beep->write_signal(SIG_BEEP_MUTE, 0, 1);
+               beep->write_signal(SIG_BEEP_ON, 1, 1);
+               register_event(this,
+                      ID_KEYBOARD_HIDDEN_BEEP_OFF,
+                      25.0 * 1000.0, false, NULL);
+
+       } else  if(event_id == ID_KEYBOARD_HIDDEN_BEEP_OFF) {
+               beep->write_signal(SIG_BEEP_MUTE, 0, 1);
+               beep->write_signal(SIG_BEEP_ON, 0, 1);
+       } else if(event_id == ID_KEYBOARD_BREAK_ONESHOT) {
+               if(break_pressed) this->write_signals(&break_line, 0xff);
        } else
 #endif
-       if((event_id >= ID_KEYBOARD_AUTOREPEAT_FIRST) && (event_id <= (ID_KEYBOARD_AUTOREPEAT_FIRST + 0x1ff))) {
-               uint32 sc = event_id - ID_KEYBOARD_AUTOREPEAT_FIRST;
+       if(event_id == ID_KEYBOARD_AUTOREPEAT_FIRST) {
                double usec = (double)repeat_time_short * 1000.0;
 
-               if((sc >= 0x67) || (sc == 0)) return;
-               do_repeatkey((uint16)sc);
+               do_repeatkey(repeat_keycode);
                register_event(this,
-                              ID_KEYBOARD_AUTOREPEAT + sc,
+                              ID_KEYBOARD_AUTOREPEAT,
                               usec, true, &event_keyrepeat);
                // Key repeat.
-       } else if((event_id >= ID_KEYBOARD_AUTOREPEAT) && (event_id <= (ID_KEYBOARD_AUTOREPEAT + 0x1ff))){
-               uint32 sc = event_id - ID_KEYBOARD_AUTOREPEAT;
-               do_repeatkey((uint16)sc);
+       } else if(event_id == ID_KEYBOARD_AUTOREPEAT){
+               if(repeat_keycode != 0) {
+                       do_repeatkey(repeat_keycode);
+               } else {
+                       cancel_event(this, event_keyrepeat);
+                       event_keyrepeat = -1;
+               }
+       } else if(event_id == ID_KEYBOARD_INT) {
+               if(!(key_fifo->empty())) {
+                       keycode_7 = key_fifo->read();
+                       this->write_signals(&int_line, 0xffffffff);
+               }
+       } else if(event_id == ID_KEYBOARD_AUTO_8KEY_START) {
+               if(keymode != KEYMODE_SCAN) {
+                       scancode = 0x3b; // 8
+                       autokey_backup = 0x00;
+                       key_down_main(false);
+                       register_event(this,
+                                                  ID_KEYBOARD_AUTO_8KEY_END,
+                                                  50.0 * 1000.0, false, NULL);
+               }
+       } else if(event_id == ID_KEYBOARD_AUTO_8KEY_END) {
+               key_up_main(0x3b); // 8
+       } else if(event_id == ID_KEYBOARD_AUTO_5KEY_START) {
+               if(keymode != KEYMODE_SCAN) {
+                       scancode = 0x3f; // 5
+                       autokey_backup = 0x00;
+                       key_down_main(false);
+                       register_event(this,
+                                                  ID_KEYBOARD_AUTO_5KEY_END,
+                                                  50.0 * 1000.0, false, NULL);
+               }
+       } else if(event_id == ID_KEYBOARD_AUTO_5KEY_END) {
+               key_up_main(0x3f); // 5
        }
 }
 
 // Commands
 void KEYBOARD::reset_unchange_mode(void)
 {
-       int i;
        repeat_time_short = 70; // mS
        repeat_time_long = 700; // mS
        repeat_mode = true;
-       keycode_7 = 0x00;
        older_vk = 0;
 
        lshift_pressed = false;
        rshift_pressed = false;
+       shift_pressed = false;
        ctrl_pressed   = false;
        graph_pressed = false;
-       //      ins_pressed = false;
+       kana_pressed = false;
+       caps_pressed = false;
+       ins_led_status = false;
+       kana_led_status = false;
+       caps_led_status = false;
        datareg = 0x00;
+       repeat_keycode = 0x00;
+       autokey_backup = 0x00;
+
+       if(override_break_key) write_signals(&break_line, (break_pressed) ? 0xff : 0);
+       key_fifo->clear();
 #if defined(_FM77AV_VARIANTS)
        cmd_fifo->clear();
        data_fifo->clear();
@@ -405,9 +634,12 @@ void KEYBOARD::reset_unchange_mode(void)
        register_event(this,ID_KEYBOARD_RTC_COUNTUP, 1000.0 * 1000.0, true, &event_key_rtc);
 
        cmd_phase = 0;
-       if(event_keyrepeat >= 0) cancel_event(this,event_keyrepeat);
+       if(event_keyrepeat >= 0) cancel_event(this, event_keyrepeat);
        event_keyrepeat = -1;
-       for(i = 0; i < 0x70; i++) key_pressed_flag[i] = false;
+   
+       if(event_hidden1_av >= 0) cancel_event(this, event_hidden1_av);
+       event_hidden1_av = -1;
+       hidden1_ptr = 0;
 #endif
        // Bus
        this->write_signals(&break_line, 0x00);
@@ -417,9 +649,6 @@ void KEYBOARD::reset_unchange_mode(void)
        this->write_signals(&rxrdy, 0x00);                
        this->write_signals(&key_ack, 0xff);              
 #endif
-       this->write_signals(&kana_led, 0x00);             
-       this->write_signals(&caps_led, 0x00);             
-       this->write_signals(&ins_led, 0x00);              
 }
 
 
@@ -427,17 +656,30 @@ void KEYBOARD::reset(void)
 {
        keymode = KEYMODE_STANDARD;
        scancode = 0x00;
-       keycode_7 = 0x00; 
+
+       keycode_7 = 0xffffffff; 
+       //keycode_7 = 0; 
        reset_unchange_mode();
+       this->write_signals(&int_line, 0x00000000);
+
 #if defined(_FM77AV_VARIANTS)  
        adjust_rtc();
+       did_hidden_message_av_1 = false;
+       beep_phase = 0;
 #endif
+
+       if(override_break_key) write_signals(&break_line, (break_pressed) ? 0xff : 0);
+
+       if(event_int >= 0) cancel_event(this, event_int);
+       register_event(this,
+                                  ID_KEYBOARD_INT,
+                                  20000.0, true, &event_int);
 }
 
 
 #if defined(_FM77AV_VARIANTS)  
 // 0xd431 : Read
-uint8 KEYBOARD::read_data_reg(void)
+uint8_t KEYBOARD::read_data_reg(void)
 {
        if(!data_fifo->empty()) {
                datareg = data_fifo->read() & 0xff;
@@ -453,9 +695,9 @@ uint8 KEYBOARD::read_data_reg(void)
 }
 
 // 0xd432
-uint8 KEYBOARD::read_stat_reg(void)
+uint8_t KEYBOARD::read_stat_reg(void)
 {
-       uint8 data = 0xff;
+       uint8_t data = 0xff;
        if(rxrdy_status) {
                data &= 0x7f;
        }
@@ -476,7 +718,12 @@ void KEYBOARD::set_mode(void)
        mode = cmd_fifo->read();
        if(mode <= KEYMODE_SCAN) {
                keymode = mode;
-               reset_unchange_mode();
+               //printf("Keymode : %d\n", keymode);
+               //reset_unchange_mode();
+               beep_phase = 0;
+               autokey_backup = 0x00;
+               this->write_signals(&break_line, 0x00);
+               if(scancode != 0) key_down_main(true); 
        }
        cmd_fifo->clear();
        data_fifo->clear(); // right?
@@ -509,11 +756,11 @@ void KEYBOARD::set_leds(void)
                if((ledvar & 0x02) != 0) {
                        // Kana
                        kana_pressed = ((ledvar & 0x01) == 0);
-                       write_signals(&kana_led, kana_pressed);
+                       kana_led_status = kana_pressed;
                } else {
                        // Caps
                        caps_pressed = ((ledvar & 0x01) == 0);
-                       write_signals(&caps_led, caps_pressed);
+                       caps_led_status = caps_pressed;
                }
        }
        cmd_fifo->clear();
@@ -524,7 +771,7 @@ void KEYBOARD::set_leds(void)
 
 void KEYBOARD::get_leds(void)
 {
-       uint8 ledvar = 0x00;
+       uint8_t ledvar = 0x00;
        data_fifo->clear();
        ledvar |= caps_pressed ? 0x01 : 0x00;
        ledvar |= kana_pressed ? 0x02 : 0x00;
@@ -545,8 +792,9 @@ void KEYBOARD::set_repeat_type(void)
                if((modeval < 2) && (modeval >= 0)) {
                        repeat_mode = (modeval == 0);
                        if(repeat_mode) {
-                               keycode_7 = 0x00;
-                               scancode = 0x00;
+                               //scancode = 0x00;
+                               //keycode_7 = 0x00;
+                               key_fifo->clear();
                        }
                }
        }
@@ -559,21 +807,20 @@ void KEYBOARD::set_repeat_type(void)
 void KEYBOARD::set_repeat_time(void)
 {
        int cmd;
-       int time_high = 0;
-       int time_low = 0;
+       uint32_t time_high = 0;
+       uint32_t time_low = 0;
        cmd = cmd_fifo->read();
        if(cmd_fifo->empty()) goto _end;
        time_high = cmd_fifo->read();
        if(cmd_fifo->empty()) goto _end;
        time_low = cmd_fifo->read();
-//     if(cmd_fifo->empty()) goto _end;
 _end:
        if((time_high == 0) || (time_low == 0)) {
                repeat_time_long = 700;
                repeat_time_short = 70;
        } else {
-               repeat_time_long = time_high * 10;
-               repeat_time_short = time_low * 10;
+               repeat_time_long = (int)time_high * 10;
+               repeat_time_short = (int)time_low * 10;
        }
        data_fifo->clear();
        cmd_fifo->clear();
@@ -722,19 +969,27 @@ void KEYBOARD::rtc_count(void)
 }
 #endif // FM77AV_VARIANTS
 
-uint32 KEYBOARD::read_signal(int id)
+uint32_t KEYBOARD::read_signal(int id)
 {
        if(id == SIG_FM7KEY_BREAK_KEY) {
                return break_pressed ? 0xfffffff : 0x00000000;
+       } else if(id == SIG_FM7KEY_LED_STATUS) {
+               uint32_t _l;
+               _l  = (ins_led_status) ? 0x00000001 : 0;
+               _l |= (kana_led_status) ? 0x00000002 : 0;
+               _l |= (caps_led_status) ? 0x00000004 : 0;
+               return _l;
        }
        return 0;
 }
 
 
-void KEYBOARD::write_signal(int id, uint32 data, uint32 mask)
+void KEYBOARD::write_signal(int id, uint32_t data, uint32_t mask)
 {
        if(id == SIG_FM7KEY_SET_INSLED) {
-               write_signals(&ins_led, data & mask);
+               ins_led_status = ((data & mask) != 0);
+       } else if(id == SIG_FM7KEY_OVERRIDE_PRESS_BREAK) {
+               override_break_key = ((data & mask) != 0);
        }
 #if defined(_FM77AV_VARIANTS)  
         else if(id == SIG_FM7KEY_PUSH_TO_ENCODER) {
@@ -764,7 +1019,7 @@ void KEYBOARD::write_signal(int id, uint32 data, uint32 mask)
                        case 0: // Set mode
                                if(count >= 2) {
                                        set_mode();
-                                       if(keymode == KEYMODE_SCAN) key_down_main();
+                                       if(keymode == KEYMODE_SCAN) key_down_main(true);
                                        cmd_phase = -1;
                                        cmd_fifo->clear();
                                }
@@ -777,7 +1032,7 @@ void KEYBOARD::write_signal(int id, uint32 data, uint32 mask)
                        case 2: // Set LED Phase
                                if(count >= 2) {
                                        set_leds();
-                                       if(keymode == KEYMODE_SCAN) key_down_main();
+                                       if(keymode == KEYMODE_SCAN) key_down_main(true);
                                        cmd_phase = -1;
                                        cmd_fifo->clear();
                                }
@@ -868,9 +1123,9 @@ void KEYBOARD::write_signal(int id, uint32 data, uint32 mask)
 #endif
 }
 
-uint32 KEYBOARD::read_data8(uint32 addr)
+uint32_t KEYBOARD::read_data8(uint32_t addr)
 {
-       uint32 retval = 0xff;
+       uint32_t retval = 0xff;
        switch(addr) {
                case 0x00:
                        retval = get_keycode_high();
@@ -892,7 +1147,7 @@ uint32 KEYBOARD::read_data8(uint32 addr)
        return retval;
 }
 
-void KEYBOARD::write_data8(uint32 addr, uint32 data)
+void KEYBOARD::write_data8(uint32_t addr, uint32_t data)
 {
        switch(addr) {
 #if defined(_FM77AV_VARIANTS)                  
@@ -903,13 +1158,12 @@ void KEYBOARD::write_data8(uint32 addr, uint32 data)
        }
 }
 
-KEYBOARD::KEYBOARD(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
+KEYBOARD::KEYBOARD(VM_TEMPLATE* parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
 {
-       int i;
-       p_vm = parent_vm;
-       p_emu = parent_emu;
-  
-       keycode_7 = 0;
+#if defined(_FM77AV_VARIANTS)
+       beep = NULL;
+#endif 
+       keycode_7 = 0xffffffff;
    
        ctrl_pressed = false; 
        lshift_pressed = false; 
@@ -920,19 +1174,17 @@ KEYBOARD::KEYBOARD(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_em
        kana_pressed = false;
        break_pressed = false;
        event_keyrepeat = -1;
-   
-       for(i = 0; i < 0x70; i++) {
-               key_pressed_flag[i] = false;
-       }
+       autokey_backup = 0x00;
 
        keymode = KEYMODE_STANDARD;
+       override_break_key = false;
 #if defined(_FM77AV_VARIANTS)
        cmd_fifo = new FIFO(16);
        data_fifo = new FIFO(16);
        rxrdy_status = true;
        key_ack_status = false;
-       init_output_signals(&rxrdy);
-       init_output_signals(&key_ack);
+       initialize_output_signals(&rxrdy);
+       initialize_output_signals(&key_ack);
        
        rtc_count24h = false;
        rtc_dayofweek = 0;
@@ -946,14 +1198,19 @@ KEYBOARD::KEYBOARD(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_em
        rtc_minute = 0;
        rtc_sec = 0;
        event_key_rtc = -1;
+       event_hidden1_av = -1;
+       hidden1_ptr = 0;
 #endif
+       key_fifo = new FIFO(512);
+       event_int = -1;
        
-       init_output_signals(&break_line);
-       init_output_signals(&int_line);
+       initialize_output_signals(&break_line);
+       initialize_output_signals(&int_line);
        
-       init_output_signals(&kana_led);
-       init_output_signals(&caps_led);
-       init_output_signals(&ins_led);
+       ins_led_status = false;
+       kana_led_status = false;
+       caps_led_status = false;
+       set_device_name(_T("KEYBOARD SUBSYSTEM"));
 }
 
 void KEYBOARD::release(void)
@@ -964,134 +1221,120 @@ void KEYBOARD::release(void)
        delete cmd_fifo;
        delete data_fifo;
 #endif   
+       key_fifo->release();
+       delete key_fifo;
 }
 
+
+
 KEYBOARD::~KEYBOARD()
 {
 }
 
-#define STATE_VERSION 1
-void KEYBOARD::save_state(FILEIO *state_fio)
+#define STATE_VERSION 9
+//#if defined(Q_OS_WIN)
+//DLL_PREFIX_I struct cur_time_s cur_time;
+//#endif
+
+bool KEYBOARD::decl_state(FILEIO *state_fio, bool loading)
 {
-       int ch;
-       int addr;
-       state_fio->FputUint32_BE(STATE_VERSION);
-       state_fio->FputInt32_BE(this_device_id);
-
-       // Version 1
-       {
-               int id;
-               state_fio->FputUint32_BE(keycode_7);
-               state_fio->FputInt32_BE(keymode);
-          
-               state_fio->FputBool(ctrl_pressed);
-               state_fio->FputBool(lshift_pressed);
-               state_fio->FputBool(rshift_pressed);
-               state_fio->FputBool(shift_pressed);
-               state_fio->FputBool(graph_pressed);
-               state_fio->FputBool(caps_pressed);
-               state_fio->FputBool(kana_pressed);
-               state_fio->FputBool(break_pressed);
-
-               state_fio->FputInt32_BE(event_keyrepeat);
-               for(id = 0; id < 0x70; id++) state_fio->FputBool(key_pressed_flag[id]);
-          
-               state_fio->FputUint32(scancode);
-               state_fio->FputUint8(datareg);
-               state_fio->FputUint32(older_vk);
+       if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+               return false;
+       }
+       if(!state_fio->StateCheckInt32(this_device_id)) {
+               return false;
+       }
+       
+       state_fio->StateUint32(keycode_7);
+       state_fio->StateInt32(keymode);
+       state_fio->StateBool(ctrl_pressed);
+       state_fio->StateBool(lshift_pressed);
+       state_fio->StateBool(rshift_pressed);
+       state_fio->StateBool(shift_pressed);
+       state_fio->StateBool(graph_pressed);
+       state_fio->StateBool(caps_pressed);
+       state_fio->StateBool(kana_pressed);
+       state_fio->StateBool(break_pressed);
+
+       state_fio->StateInt32(event_keyrepeat);
           
-               state_fio->FputBool(repeat_mode);
-               state_fio->FputInt32_BE(repeat_time_short);
-               state_fio->FputInt32_BE(repeat_time_long);
+       state_fio->StateUint8(scancode); // After V.4, uint8_t
+       state_fio->StateUint8(datareg);
+       state_fio->StateUint32(older_vk);
           
+       state_fio->StateBool(repeat_mode);
+       state_fio->StateInt32(repeat_time_short);
+       state_fio->StateInt32(repeat_time_long);
+       state_fio->StateUint8(repeat_keycode);
+          
 #if defined(_FM77AV_VARIANTS)
-               state_fio->FputInt32_BE(event_key_rtc);
-  
-               state_fio->FputUint8(rtc_yy);
-               state_fio->FputUint8(rtc_mm);
-               state_fio->FputUint8(rtc_dd);
-               state_fio->FputUint8(rtc_dayofweek);
-               state_fio->FputUint8(rtc_hour);
-               state_fio->FputUint8(rtc_minute);
-               state_fio->FputUint8(rtc_sec);
-
-               state_fio->FputBool(rtc_count24h);
-               state_fio->FputBool(rtc_ispm);
-
-               state_fio->FputBool(rtc_set);
-               state_fio->FputBool(rtc_set_flag);
-               state_fio->FputBool(rxrdy_status);
-               state_fio->FputBool(key_ack_status);
-               state_fio->FputInt32_BE(cmd_phase);
-
-               cmd_fifo->save_state((void *)state_fio);
-               data_fifo->save_state((void *)state_fio);
-               cur_time.save_state((void *)state_fio);
+       state_fio->StateInt32(event_key_rtc);
+       state_fio->StateUint8(rtc_yy);
+       state_fio->StateUint8(rtc_mm);
+       state_fio->StateUint8(rtc_dd);
+       state_fio->StateUint8(rtc_dayofweek);
+       state_fio->StateUint8(rtc_hour);
+       state_fio->StateUint8(rtc_minute);
+       state_fio->StateUint8(rtc_sec);
+
+       state_fio->StateBool(rtc_count24h);
+       state_fio->StateBool(rtc_ispm);
+
+       state_fio->StateBool(rtc_set);
+       state_fio->StateBool(rtc_set_flag);
+       state_fio->StateBool(rxrdy_status);
+       state_fio->StateBool(key_ack_status);
+               
+       state_fio->StateBool(did_hidden_message_av_1);
+       state_fio->StateInt32(event_hidden1_av);
+
+       state_fio->StateInt32(cmd_phase);
+       state_fio->StateUint16(hidden1_ptr);
+       state_fio->StateInt32(beep_phase);
+       
+       if(!cmd_fifo->process_state(state_fio, loading)) {
+               return false;
+       }
+       if(!data_fifo->process_state(state_fio, loading)) {
+               return false;
+       }
+       if(!cur_time.process_state(state_fio, loading)) {
+               return false;
+       }
 #endif
+       if(!key_fifo->process_state(state_fio, loading)) {
+               return false;
        }
+       state_fio->StateInt32(event_int);
+       state_fio->StateUint8(autokey_backup);
+       // Version 5
+       state_fio->StateBool(ins_led_status);
+       state_fio->StateBool(kana_led_status);
+       state_fio->StateBool(caps_led_status);
+       // Version 6
+       state_fio->StateBool(override_break_key);
+
+       return true;
 }
 
+void KEYBOARD::save_state(FILEIO *state_fio)
+{
+       decl_state(state_fio, false);
+       //state_fio->FputUint32_BE(STATE_VERSION);
+       //state_fio->FputInt32_BE(this_device_id);
+       this->out_debug_log(_T("Save State: KEYBOARD: id=%d ver=%d\n"), this_device_id, STATE_VERSION);
+}
 bool KEYBOARD::load_state(FILEIO *state_fio)
 {
-       int ch;
-       int addr;
-       bool stat = false;
-       uint32 version;
-       
-       version = state_fio->FgetUint32_BE();
-       if(this_device_id != state_fio->FgetInt32_BE()) return false;
-
-       if(version >= 1) {
-               int id;
-               keycode_7 = state_fio->FgetUint32_BE();
-               keymode = state_fio->FgetInt32_BE();
-          
-               ctrl_pressed = state_fio->FgetBool();
-               lshift_pressed = state_fio->FgetBool();
-               rshift_pressed = state_fio->FgetBool();
-               shift_pressed = state_fio->FgetBool();
-               graph_pressed = state_fio->FgetBool();
-               caps_pressed = state_fio->FgetBool();
-               kana_pressed = state_fio->FgetBool();
-               break_pressed = state_fio->FgetBool();
-
-               event_keyrepeat = state_fio->FgetInt32_BE();
-               for(id = 0; id < 0x70; id++) key_pressed_flag[id] = state_fio->FgetBool();
-          
-               scancode = state_fio->FgetUint32();
-               datareg = state_fio->FgetUint8();
-               older_vk = state_fio->FgetUint32();
-          
-               repeat_mode = state_fio->FgetBool();
-               repeat_time_short = state_fio->FgetInt32_BE();
-               repeat_time_long = state_fio->FgetInt32_BE();
-          
-#if defined(_FM77AV_VARIANTS)
-               event_key_rtc = state_fio->FgetInt32_BE();
-               rtc_yy = state_fio->FgetUint8();
-               rtc_mm = state_fio->FgetUint8();
-               rtc_dd = state_fio->FgetUint8();
-               rtc_dayofweek = state_fio->FgetUint8();
-               rtc_hour = state_fio->FgetUint8();
-               rtc_minute = state_fio->FgetUint8();
-               rtc_sec = state_fio->FgetUint8();
-
-               rtc_count24h = state_fio->FgetBool();
-               rtc_ispm = state_fio->FgetBool();
-
-               rtc_set = state_fio->FgetBool();
-               rtc_set_flag = state_fio->FgetBool();
-               rxrdy_status = state_fio->FgetBool();
-               key_ack_status = state_fio->FgetBool();
-               cmd_phase = state_fio->FgetInt32_BE();
-
-               cmd_fifo->load_state((void *)state_fio);
-               data_fifo->load_state((void *)state_fio);
-               cur_time.load_state((void *)state_fio);
-#endif
-               if(version == 1) return true;
-       }
-       return false;
+       uint32_t version;
+       
+       //version = state_fio->FgetUint32_BE();
+       //if(this_device_id != state_fio->FgetInt32_BE()) return false;
+       //this->out_debug_log(_T("Load State: KEYBOARD: id=%d ver=%d\n"), this_device_id, version);
+       bool mb = decl_state(state_fio, true);
+       if(!mb) return false;
+       return true;
 }
 
-   
+}