--- nono/vm/x68kkbd.cpp 2026/04/29 17:04:53 1.1.1.5 +++ nono/vm/x68kkbd.cpp 2026/04/29 17:04:56 1.1.1.6 @@ -25,6 +25,10 @@ X68030Keyboard::X68030Keyboard() { led.resize(7); + + rept_event.func = (DeviceCallback_t)&X68030Keyboard::ReptCallback; + rept_event.time = 0; + rept_event.SetName("Keyboard Repeat"); } // デストラクタ @@ -38,8 +42,10 @@ X68030Keyboard::ResetHard() { inherited::ResetHard(); - rept_delay = 500; - rept_time = 110; + rept_delay = 500_msec; + rept_time = 110_msec; + rept_key = KC_none; + rept_event.Stop(); for (int i = 0; i < led.size(); i++) { led[i] = false; @@ -66,48 +72,69 @@ X68030Keyboard::IsShift() const return pressed[KC_SHIFT]; } -// keycode を前処理して返す。 -uint -X68030Keyboard::PreprocessKey(uint keystat) +// キー入力を1つ処理する +void +X68030Keyboard::KeyInput(uint keystat) { + uint keycode = KC_CODE(keystat); + bool ismake = KC_IS_MAKE(keystat); + + assert(keycode < KC_max); + // X68k のキーボードは左右の [SHIFT] の区別がない。 // KC_SHIFT_L はホストの物理キー左 [SHIFT] に対応、 // KC_SHIFT_R はホストの物理キー右 [SHIFT] に対応、 // KC_SHIFT はソフトウェアキーボードからの左右のない [SHIFT] に対応。 // どのキーコードで問い合わせをされても KC_SHIFT_L と KC_SHIFT_R の OR が // [SHIFT] キーの状態である。 - - uint keycode = KC_CODE(keystat); - if (keycode == KC_SHIFT_L || keycode == KC_SHIFT_R) { // KC_SHIFT_L, R に対する pressed は内部の OR 処理用 - pressed[keycode] = KC_IS_MAKE(keystat); + pressed[keycode] = ismake; if (keycode == KC_SHIFT_L && pressed[KC_SHIFT_R]) { - return KC_none; + return; } if (keycode == KC_SHIFT_R && pressed[KC_SHIFT_L]) { - return KC_none; + return; } - return KC_SHIFT | KC_FLAG(keystat); - } else { - return keystat; + keycode = KC_SHIFT; + // keycode を変更したので keystat も更新 + keystat = keycode | (ismake ? KC_FLAG_MAKE : KC_FLAG_BREAK); } -} -#if 0 -// ProcessKey で処理することがいまのところ無い + // 共通処理へ + if (KeyInputCommon(keystat) == false) { + return; + } -// キー処理 (MD固有部分) -bool -X68030Keyboard::ProcessKey(uint keystat) -{ // LED は MPU 側から点灯/消灯指示が来るのでここでは何もしなくてよい - // XXX ここでキーリピート? + // ここでキーリピートのイベント開始処理 + if (ismake) { + // いま起きているリピートは中止 + rept_event.Stop(); + rept_key = keycode; + rept_event.time = rept_delay; + rept_event.Start(); + } else { + if (keycode == rept_key) { + // 同じキーのブレークでのみリピートを終了する + rept_event.Stop(); + rept_key = KC_none; + } + } +} - return true; +void +X68030Keyboard::ReptCallback(Event& ev) +{ + // リピート + sendqueue.Enqueue(rept_key); + SendStart(); + + // 二回目以降のリピートは rept_time 間隔で発生 + rept_event.time = rept_time; + rept_event.Start(); } -#endif // MFP、システムポートと、キーボードの関係。 // @@ -226,13 +253,15 @@ X68030Keyboard::Command(uint32 data) } else if (data < 0x70) { // $60-$6f リピートまでの時間 - rept_delay = 200 + (data & 15) * 100; - putlog(1, "Command Repeat Delay %d (%d msec)", (data & 15), rept_delay); + rept_delay = 200_msec + (data & 15) * 100_msec; + putlog(1, "Command Repeat Delay %d (%d msec)", (data & 15), + (int)(rept_delay / 1_msec)); } else if (data < 0x80) { // $70-$7f リピート間隔 - rept_time = 30 + (data & 15) * (data & 15) * 5; - putlog(1, "Command Repeat time %d (%d msec)", (data & 15), rept_time); + rept_time = 30_msec + (data & 15) * (data & 15) * 5_msec; + putlog(1, "Command Repeat time %d (%d msec)", (data & 15), + (int)(rept_time / 1_msec)); } else { // $80-$ff LED 制御