--- nono/vm/keyboard.h 2026/04/29 17:04:55 1.1.1.7 +++ nono/vm/keyboard.h 2026/04/29 17:05:33 1.1.1.14 @@ -4,29 +4,51 @@ // Licensed under nono-license.txt // +// +// キーボード (基本クラス) +// + #pragma once #include "device.h" -#include "event.h" #include "fixedqueue.h" -#include +#include "message.h" + +class Syncer; -class Keyboard : public Device +// 文字入力しか持たないキーボードの下位クラス。 +class DumbKeyboard : public Device { using inherited = Device; + public: + DumbKeyboard(); + ~DumbKeyboard() override; + + // 文字入力によるキーエミュレーション (外部から呼ばれる) + virtual void CharInput(uint charcode) = 0; +}; + +// 通常のキーボード +class Keyboard : public DumbKeyboard +{ + using inherited = DumbKeyboard; protected: Keyboard(); public: - virtual ~Keyboard() override; + ~Keyboard() override; - virtual void ResetHard() override; + bool Init() override; + void ResetHard(bool poweron) override; + void PowerOff() override; // キーを押した (外部から呼ばれる) void MakeKey(uint keycode); // キーを離した (外部から呼ばれる) void BreakKey(uint keycode); + // 文字入力によるキーエミュレーション (外部から呼ばれる) + void CharInput(uint charcode) override; - // マウス入力 + // マウス入力。 // x, y は X, Y の前回からの移動量。 // X は画面右に動く方向をプラス、Y は画面下に動く方向をプラスとする。 // 移動量が VM で扱える範囲内か、それを越えていたらどうするかは @@ -34,6 +56,9 @@ class Keyboard : public Device // rb, lb, mb はボタンの状態。true なら押下中。 virtual void MouseInput(int x, int y, bool rb, bool lb, bool mb) = 0; + // マウスデータを VM に送信する MD 処理 + virtual void MouseSendStart() = 0; + // ホストからの制御コマンド virtual void Command(uint32 data) = 0; @@ -54,10 +79,23 @@ class Keyboard : public Device // 状態を取得すること。 virtual bool IsShift() const = 0; + // キーボードを接続する + void Connect(bool connect); + + // キーボードが接続されていれば true を返す + bool IsConnected() const { return is_connected; } + // キー名を返す (主にデバッグ表示用) static const std::string GetKeyName(uint code); protected: + // キーボードの接続処理の実体 + void DoConnect(); + void DoDisconnect(); + + virtual void MDConnect() = 0; + virtual void MDDisconnect() = 0; + // キーコードには、 // o 共通キーコード(コードのみ)、 // o 共通キーコード(コードと Make/Break フラグあり)、 @@ -76,23 +114,18 @@ class Keyboard : public Device // キーを処理する (共通部分) bool KeyInputCommon(uint keystat); + // キーが1つでも押されていれば true + bool Any() const; + // キーを VM に送信する MD 処理 virtual void SendStart() = 0; + // キーボードが接続されているとき true + bool is_connected {}; + // どのキーが押されているか (共通キーコード) std::vector pressed {}; - // 現在押されているキーの総数 - int num_of_pressed {}; - - // ホストから来たキー入力をバッファする。 - // 実際には固定長でない普通のキューで構わないんだけど、モニタ用に中身を - // 覗き見したいとか思うと、ほぼそのための FixedQueue を使うほうがいい。 - // 固定長である必要はないけど、無限に可変長である必要もないので。 - - // UI からの入力を VM スレッドへ引き渡すためのバッファ。 - FixedQueue inputqueue {}; - // 入力されたキーを VM へ送信するときのバッファ。 FixedQueue sendqueue {}; @@ -102,34 +135,68 @@ class Keyboard : public Device // 含めたコードはすべて派生クラス側で用意すること。 std::vector led {}; + // マウス状態 + int mouse_x {}; // 前回送信から現在までの積算値 + int mouse_y {}; + bool mouse_r {}; // 現在値 + bool mouse_l {}; + bool mouse_m {}; + bool prev_r {}; // 前回送信時の値 + bool prev_l {}; + bool prev_m {}; + + Syncer *syncer {}; + private: - // キー入力を VM スレッドで処理するためのイベント - void KeyInputCallback(Event& ev); - Event keyinput_event { this }; - std::mutex mtx {}; + void KeyInputMessage(MessageID, uint32); static std::vector keyname; + static std::vector char_key; }; -extern std::unique_ptr gKeyboard; +// フルキーボードの取得 (シリアルキーボードは含まない) +static inline Keyboard *GetKeyboard() { + return Object::GetObject(OBJ_KEYBOARD); +} + +// keystat は下位 8bit がキーコード。 +// 上位(今の所 8bit) は各種フラグ。 +// +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +// |M/B|UI | LED | 0 | KM_* | Keycode | +// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +// | | | | +// | | | +-- キャラクタ入力でのモディファイヤフラグ +// | | +------------------ LUNA の LED キー送信フラグ +// | +------------------------ char 入力モードでキーコードを UI に通知 +// | (inputqueue 内で使用する) +// +---------------------------- キーの Make/Break + +#define KM_SHIFT (0x0100) // char モードで SHIFT 押下 +#define KM_CTRL (0x0200) // char モードで CTRL 押下 + +#define KC_FLAG_LED_MAKE (0x1000) // LUNA LED キーの押下を送信 +#define KC_FLAG_LED_BREAK (0x2000) // LUNA LED キーの開放を送信 +#define KC_FLAG_LED_DROP (0x3000) // LUNA LED キーを送信しない + +#define KC_FLAG_POST (0x4000) // キーコードを UI に通知 + +#define KC_FLAG_MAKE (0x0000) // キー押下 (値は 0 だが便宜上) +#define KC_FLAG_BREAK (0x8000) // キー開放 + +// keystat のアクセスマクロ +#define KC_CODE(x) ((x) & 0x00ff) // keycode を取得 +#define KC_FLAG_LED(x) ((x) & 0x3000) // LUNA LED キー動作を取得 +#define KC_IS_POST(x) (((x) & KC_FLAG_POST) != 0) // UI に通知なら true +#define KC_IS_MAKE(x) (((x) & KC_FLAG_BREAK) == 0) // キー押下なら true +#define KC_IS_BREAK(x) (((x) & KC_FLAG_BREAK) != 0) // キー開放なら true // 抽象化キーボードレイヤーでのキーコード。 // wxWidgets で受け取ったキーコードをこれに変換して VM に入力する。 // VM のキーボードデバイスがこれを当該機種ごとのキーコードなり何なりに // 変換して入力する。 -// keystat のフラグ -#define KC_FLAG_MAKE (0x0000) // 押した -#define KC_FLAG_BREAK (0x8000) // 離した -#define KC_IS_MAKE(x) (((x) & KC_FLAG_BREAK) == 0) -#define KC_IS_BREAK(x) (((x) & KC_FLAG_BREAK) != 0) - -// keystat からフラグだけ取り出す -#define KC_FLAG(x) ((x) & 0x8000) - -// keystat からキーコードだけ取り出す -#define KC_CODE(x) ((x) & 0x7fff) - #define KC_none (0) #define KC_BREAK (0x01) // [X68k] BREAK @@ -139,7 +206,7 @@ extern std::unique_ptr gKeyboa #define KC_kigou (0x05) // [X68k] 記号入力 #define KC_touroku (0x06) // [X68k] 登録 #define KC_HELP (0x07) // [X68k] HELP -#define KC_HOME (0x08) // [X68k] HOME +#define KC_SHIFT (0x08) // [X68k] SHIFT (左右の区別なし) #define KC_TAB (0x09) #define KC_CTRL (0x0a) #define KC_kana (0x0b) // かな @@ -180,7 +247,7 @@ extern std::unique_ptr gKeyboa #define KC_minus (0x2c) #define KC_circum (0x2d) // ^~ #define KC_backslash (0x2e) // \| -#define KC_UNDO (0x2f) // [X68k] UNDO +#define KC_buzzer (0x2f) // [LUNA] ブザー発声 (キーではない) #define KC_OPT1 (0x30) // [X68k] OPT.1 #define KC_OPT2 (0x31) // [X68k] OPT.2 @@ -199,6 +266,8 @@ extern std::unique_ptr gKeyboa #define KC_hira (0x3e) // [X68k] ひらがな #define KC_zenkaku (0x3f) // [X68k] 全角 +#define KC_HOME (0x40) // [X68k] HOME +#define KC_UNDO (0x41) // [X68k] UNDO #define KC_A (0x42) #define KC_S (0x43) #define KC_D (0x44) @@ -212,6 +281,8 @@ extern std::unique_ptr gKeyboa #define KC_colon (0x4c) #define KC_bracketright (0x4d) // ']' +#define KC_XF1 (0x50) // [X68k] XF1 +#define KC_XF2 (0x51) // [X68k] XF2 #define KC_Z (0x52) #define KC_X (0x53) #define KC_C (0x54) @@ -223,6 +294,9 @@ extern std::unique_ptr gKeyboa #define KC_period (0x5a) #define KC_slash (0x5b) #define KC_underscore (0x5c) +#define KC_XF3 (0x5d) // [X68k] XF3 +#define KC_XF4 (0x5e) // [X68k] XF4 +#define KC_XF5 (0x5f) // [X68k] XF5 #define KC_PAD_plus (0x61) #define KC_PAD_minus (0x62) @@ -255,11 +329,25 @@ extern std::unique_ptr gKeyboa #define KC_PAD_equal (0x7e) #define KC_PAD_comma (0x7f) -#define KC_XF1 (0x80) // [X68k] XF1 -#define KC_XF2 (0x81) // [X68k] XF2 -#define KC_XF3 (0x82) // [X68k] XF3 -#define KC_XF4 (0x83) // [X68k] XF4 -#define KC_XF5 (0x84) // [X68k] XF5 -#define KC_SHIFT (0x85) // [X68k] SHIFT (左右の区別なし) +#define KC_max (0x80) + +// 文字入力モードの拡張部分 +#define CC_NUL (0x80) // NUL (Ctrl + @) +#define CC_F1 (0x81) +#define CC_F2 (0x82) +#define CC_F3 (0x83) +#define CC_F4 (0x84) +#define CC_F5 (0x85) +#define CC_F6 (0x86) +#define CC_F7 (0x87) +#define CC_F8 (0x88) +#define CC_F9 (0x89) +#define CC_F10 (0x8a) + +#define CC_up (0x8c) +#define CC_left (0x8d) +#define CC_right (0x8e) +#define CC_down (0x8f) -#define KC_max (0x86) +#define CC_disconnect (0x90) // キーボードを取り外す +#define CC_connect (0x91) // キーボードを接続する