--- nono/vm/keyboard.h 2026/04/29 17:04:35 1.1.1.4 +++ nono/vm/keyboard.h 2026/04/29 17:04:55 1.1.1.7 @@ -7,6 +7,9 @@ #pragma once #include "device.h" +#include "event.h" +#include "fixedqueue.h" +#include class Keyboard : public Device { @@ -14,12 +17,14 @@ class Keyboard : public Device protected: Keyboard(); public: - ~Keyboard() override; + virtual ~Keyboard() override; - // キーを押した - virtual void MakeKey(uint) = 0; - // キーを離した - virtual void BreakKey(uint) = 0; + virtual void ResetHard() override; + + // キーを押した (外部から呼ばれる) + void MakeKey(uint keycode); + // キーを離した (外部から呼ばれる) + void BreakKey(uint keycode); // マウス入力 // x, y は X, Y の前回からの移動量。 @@ -32,13 +37,65 @@ class Keyboard : public Device // ホストからの制御コマンド virtual void Command(uint32 data) = 0; + // 指定のキーの押し下げ状態取得 (ソフトウェアキーボードなどから) + bool IsPressed(uint keycode) const { + assert(keycode < pressed.size()); + return pressed[keycode]; + } + + // 全てのキーの押し下げ状態取得 (ソフトウェアキーボードなどから) + const std::vector& GetPressed() const { return pressed; } + // LED 状態取得 (ソフトウェアキーボードなどから) const std::vector& GetLED() const { return led; } + // シフト状態なら true を返す + // シフトキーは機種によって処理が異なるため、この関数を使って + // 状態を取得すること。 + virtual bool IsShift() const = 0; + // キー名を返す (主にデバッグ表示用) - static const std::string GetName(uint code); + static const std::string GetKeyName(uint code); protected: + // キーコードには、 + // o 共通キーコード(コードのみ)、 + // o 共通キーコード(コードと Make/Break フラグあり)、 + // o 機種依存キーコード + // の3つがあり、どれも uint なので変数名で区別することにする。 + // o keycode .. 共通キーコード + // o keystat .. フラグ付き共通キーコード + // o mdkey .. 機種依存キーコード + + // 共通キーコードを機種別のキーコードに変換する + virtual uint KeyToMDKey(uint keycode) const = 0; + + // キーを1つ処理する + virtual void KeyInput(uint keystat) = 0; + + // キーを処理する (共通部分) + bool KeyInputCommon(uint keystat); + + // キーを VM に送信する MD 処理 + virtual void SendStart() = 0; + + // どのキーが押されているか (共通キーコード) + std::vector pressed {}; + + // 現在押されているキーの総数 + int num_of_pressed {}; + + // ホストから来たキー入力をバッファする。 + // 実際には固定長でない普通のキューで構わないんだけど、モニタ用に中身を + // 覗き見したいとか思うと、ほぼそのための FixedQueue を使うほうがいい。 + // 固定長である必要はないけど、無限に可変長である必要もないので。 + + // UI からの入力を VM スレッドへ引き渡すためのバッファ。 + FixedQueue inputqueue {}; + + // 入力されたキーを VM へ送信するときのバッファ。 + FixedQueue sendqueue {}; + // LED (true で点灯)。 // GetLED() あたりが同じ形式で済むのでここにあるけど、機種によって // LED 数が違うので、何番がどのキーに対応するかの取り決めや、初期化も @@ -46,6 +103,11 @@ class Keyboard : public Device std::vector led {}; private: + // キー入力を VM スレッドで処理するためのイベント + void KeyInputCallback(Event& ev); + Event keyinput_event { this }; + std::mutex mtx {}; + static std::vector keyname; }; @@ -56,6 +118,18 @@ extern std::unique_ptr gKeyboa // 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 @@ -71,7 +145,6 @@ extern std::unique_ptr gKeyboa #define KC_kana (0x0b) // かな #define KC_SHIFT_L (0x0c) // SHIFT(左) #define KC_SHIFT_R (0x0d) // SHIFT(右) -#define KC_SHIFT KC_SHIRT_L // 区別がない場合は L のほうを使う #define KC_CAPS (0x0e) #define KC_SF (0x0f) // [LUNA] S.F @@ -187,5 +260,6 @@ extern std::unique_ptr gKeyboa #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 (0x85) +#define KC_max (0x86)