--- nono/vm/keyboard.h 2026/04/29 17:04:29 1.1.1.2 +++ nono/vm/keyboard.h 2026/04/29 17:04:58 1.1.1.8 @@ -1,24 +1,30 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #pragma once #include "device.h" +#include "event.h" +#include "fixedqueue.h" +#include class Keyboard : public Device { - typedef Device inherited; + using inherited = Device; protected: Keyboard(); public: - virtual ~Keyboard(); + 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 の前回からの移動量。 @@ -28,20 +34,115 @@ 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; + + // 指定のキーの押し下げ状態取得 (ソフトウェアキーボードなどから) + 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 数が違うので、何番がどのキーに対応するかの取り決めや、初期化も + // 含めたコードはすべて派生クラス側で用意すること。 + 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 {}; private: + // キー入力を VM スレッドで処理するためのイベント + void KeyInputCallback(Event& ev); + Event keyinput_event { this }; + std::mutex mtx {}; + static std::vector keyname; }; -extern Keyboard *gKeyboard; +extern std::unique_ptr gKeyboard; // 抽象化キーボードレイヤーでのキーコード。 // 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 @@ -57,7 +158,6 @@ extern Keyboard *gKeyboard; #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 @@ -173,5 +273,6 @@ extern Keyboard *gKeyboard; #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)