--- nono/vm/x68kkbd.cpp 2026/04/29 17:04:53 1.1.1.5 +++ nono/vm/x68kkbd.cpp 2026/04/29 17:05:07 1.1.1.9 @@ -19,12 +19,25 @@ #include "x68kkbd.h" #include "mfp.h" +#include "scc.h" #include "sysport.h" // コンストラクタ X68030Keyboard::X68030Keyboard() { led.resize(7); + + rept_event.func = (DeviceCallback_t)&X68030Keyboard::ReptCallback; + rept_event.time = 0; + rept_event.SetName("Keyboard Repeat"); + + for (int i = 0; i < mouse_event.size(); i++) { + mouse_event[i].dev = this; + mouse_event[i].func = (DeviceCallback_t)&X68030Keyboard::MouseCallback; + // 700us 後から 11bit を 4800 bps の速度で送る + mouse_event[i].time = 700_usec + 1_sec * 11 * (i + 1) / 4800; + mouse_event[i].SetName(string_format("Mouse Data %d", i)); + } } // デストラクタ @@ -38,25 +51,36 @@ 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; } led_darkness = 0; + + for (int i = 0; i < mouse_event.size(); i++) { + mouse_event[i].Stop(); + } } -// 共通キーコードを X680x0 キーコードに変換して返す。 +// 共通 keystat を X680x0 キーコードに変換して返す。 // 対応する X680x0 のキーがなければ 0 を返す。 uint -X68030Keyboard::KeyToMDKey(uint keycode) const +X68030Keyboard::KeyToMDKey(uint keystat) const { + uint keycode = KC_CODE(keystat); if (keycode >= countof(keycode2x68kkey_table)) { return 0; } - return keycode2x68kkey_table[keycode]; + uint mdkey = keycode2x68kkey_table[keycode]; + if (mdkey && KC_IS_BREAK(keystat)) { + mdkey |= 0x80; + } + return mdkey; } // シフト状態なら true を返す @@ -66,48 +90,70 @@ 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 = (keystat & 0xff00) | keycode; } -} -#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(KeyToMDKey(rept_key)); + SendStart(); + + // 二回目以降のリピートは rept_time 間隔で発生 + rept_event.time = rept_time; + rept_event.Start(); } -#endif // MFP、システムポートと、キーボードの関係。 // @@ -150,23 +196,17 @@ X68030Keyboard::Ready() if (gSysport->GetKeyCtrl()) { // KEYCTRL が有効なら処理する - // ここで取り出せるのは keystat。 - uint keystat; - if (sendqueue.Dequeue(&keystat)) { + // ここで取り出せるのは MDKey。 + uint x68kkey; + if (sendqueue.Dequeue(&x68kkey)) { // あれば送信 // 呼ばれたからには送信できるはず assert(gMFP->RxIsReady() == true); - uint keycode = KC_CODE(keystat); - // ここで X68k キーコードに変換 (変換できないはずはない) - uint x68kkey = KeyToMDKey(keycode); assert(x68kkey != 0); // 送信 - if (KC_IS_BREAK(keystat)) { - x68kkey |= 0x80; - } gMFP->Rx(x68kkey); } else { // なければ何もせず終了 @@ -183,6 +223,62 @@ X68030Keyboard::Ready() void X68030Keyboard::MouseInput(int x, int y, bool rb, bool lb, bool mb) { + // ホストからマウスイベントのたびに呼ばれるので、ここで積算。 + // 20msec ごとのサンプリングのタイミングで積算結果を処理する。 + // X68k のマウスの Y 方向は下に動く方向がプラス。 + mouse_x += x; + mouse_y += y; + mouse_r = rb; + mouse_l = lb; +} + +// マウスデータを VM に送信 +void +X68030Keyboard::MouseSendStart() +{ + uint8 status = 0; + + // 最後のバイトを送るまでは、次は受け付けられない + if (mouse_event[2].IsRunning()) { + return; + } + + if (mouse_x > 127) { + status |= XOVFL; + mouse_x = 127; + } + if (mouse_x < -128) { + status |= XUNFL; + mouse_x = -128; + } + if (mouse_y > 127) { + status |= YOVFL; + mouse_y = 127; + } + if (mouse_y < -128) { + status |= YUNFL; + mouse_y = -128; + } + status |= mouse_l ? SW_L : 0; + status |= mouse_r ? SW_R : 0; + + mouse_event[0].code = status; + mouse_event[1].code = mouse_x; + mouse_event[2].code = mouse_y; + + mouse_x = 0; + mouse_y = 0; + + mouse_event[0].Start(); + mouse_event[1].Start(); + mouse_event[2].Start(); +} + +void +X68030Keyboard::MouseCallback(Event& ev) +{ + // LUNA とオブジェクトが違うだけ + gSCC->Rx(1, ev.code); } // ホストからの制御 @@ -226,13 +322,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 制御 @@ -259,7 +357,7 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_kigou, // [05] X68kKey_touroku, // [06] X68kKey_HELP, // [07] - X68kKey_HOME, // [08] + X68kKey_SHIFT, // [08] X68kKey_TAB, // [09] X68kKey_CTRL, // [0a] X68kKey_kana, // [0b] @@ -300,7 +398,7 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_minus, // [2c] X68kKey_circum, // [2d] X68kKey_backslash, // [2e] - X68kKey_UNDO, // [2f] + NoKey, // [2f] X68kKey_OPT1, // [30] X68kKey_OPT2, // [31] @@ -319,8 +417,8 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_hira, // [3e] X68kKey_zenkaku, // [3f] - NoKey, // [40] - NoKey, // [41] + X68kKey_HOME, // [40] + X68kKey_UNDO, // [41] X68kKey_A, // [42] X68kKey_S, // [43] X68kKey_D, // [44] @@ -336,8 +434,8 @@ X68030Keyboard::keycode2x68kkey_table[KC NoKey, // [4e] NoKey, // [4f] - NoKey, // [50] - NoKey, // [51] + X68kKey_XF1, // [50] + X68kKey_XF2, // [51] X68kKey_Z, // [52] X68kKey_X, // [53] X68kKey_C, // [54] @@ -349,9 +447,9 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_period, // [5a] X68kKey_slash, // [5b] X68kKey_underscore, // [5c] - NoKey, // [5d] - NoKey, // [5e] - NoKey, // [5f] + X68kKey_XF3, // [5d] + X68kKey_XF4, // [5e] + X68kKey_XF5, // [5f] NoKey, // [60] X68kKey_PAD_plus, // [61] @@ -386,11 +484,4 @@ X68030Keyboard::keycode2x68kkey_table[KC X68kKey_PAD_divide, // [7d] X68kKey_PAD_equal, // [7e] X68kKey_PAD_comma, // [7f] - - X68kKey_XF1, // [80] - X68kKey_XF2, // [81] - X68kKey_XF3, // [82] - X68kKey_XF4, // [83] - X68kKey_XF5, // [84] - X68kKey_SHIFT, // [85] };