File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / keyboard.h
Revision 1.1.1.18 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:00 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

//
// キーボード (基本クラス)
//

#pragma once

#include "device.h"
#include "fixedqueue.h"
#include "message.h"

class Syncer;
class UIMessage;

// 文字入力しか持たないキーボードの下位クラス。
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:
	~Keyboard() 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 で扱える範囲内か、それを越えていたらどうするかは
	// 継承クラスが処理する。
	// 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];
	}

	// LED 状態取得 (ソフトウェアキーボードなどから)
	const std::vector<bool>& GetLED() const { return led; }

	// シフト状態なら true を返す
	// シフトキーは機種によって処理が異なるため、この関数を使って
	// 状態を取得すること。
	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 フラグあり)、
	// o 機種依存キーコード
	// の3つがあり、どれも uint なので変数名で区別することにする。
	// o keycode .. 共通キーコード
	// o keystat .. フラグ付き共通キーコード
	// o mdkey   .. 機種依存キーコード

	// 共通キーコードを機種別のキーコードに変換する
	virtual uint KeyToMDKey(uint keycode) const = 0;

	// キーを1つ処理する
	virtual void KeyInput(uint keystat) = 0;

	// キーの押し下げ状態を設定する
	void SetPressed(uint keycode, bool ismake);

	// キーを処理する (共通部分)
	bool KeyInputCommon(uint keystat);

	// キーが1つでも押されていれば true
	bool Any() const;

	// キーを VM に送信する MD 処理
	virtual void SendStart() = 0;

	// キーボードが接続されているとき true
	bool is_connected {};

	// どのキーが押されているか (共通キーコード)
	std::vector<bool> pressed {};

	// 入力されたキーを VM へ送信するときのバッファ。
	FixedQueue<uint, 8> sendqueue {};

	// LED (true で点灯)。
	// GetLED() あたりが同じ形式で済むのでここにあるけど、機種によって
	// LED 数が違うので、何番がどのキーに対応するかの取り決めや、初期化も
	// 含めたコードはすべて派生クラス側で用意すること。
	std::vector<bool> 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 {};
	UIMessage *uimessage {};

 private:
	void KeyInputMessage(MessageID, uint32);

	static std::vector<const char *> keyname;
	static std::vector<uint> char_key;
};

// フルキーボードの取得 (シリアルキーボードは含まない)
inline Keyboard *GetKeyboard() {
	return Object::GetObject<Keyboard>(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 のキーボードデバイスがこれを当該機種ごとのキーコードなり何なりに
// 変換して入力する。

#define KC_none			(0)

#define KC_BREAK		(0x01)	// [X68k] BREAK
#define KC_romaji		(0x03)	// [X68k] ローマ字
#define KC_code			(0x04)	// [X68k] コード入力
#define KC_kigou		(0x05)	// [X68k] 記号入力
#define KC_touroku		(0x06)	// [X68k] 登録
#define KC_HELP			(0x07)	// [X68k] HELP
#define KC_SHIFT		(0x08)	// [X68k] SHIFT (左右の区別なし)
#define KC_TAB			(0x09)
#define KC_CTRL			(0x0a)
#define KC_kana			(0x0b)	// かな
#define KC_SHIFT_L		(0x0c)	// SHIFT(左) / [LUNA-88K] (右)
#define KC_SHIFT_R		(0x0d)	// SHIFT(右) / [LUNA-88K] (左)
#define KC_CAPS			(0x0e)
#define KC_SF			(0x0f)	// [LUNA-I] S.F / [LUNA-88K] META

#define KC_ESC			(0x10)
#define KC_BS			(0x11)	// BackSpace
#define KC_enter		(0x12)	// Enter (Return)
#define KC_space		(0x14)
#define KC_DEL			(0x15)
#define KC_XFER			(0x16)	// [LUNA] XFER (変換)
#define KC_VALID		(0x17)	// [LUNA] VALID(確定)
#define KC_PF11			(0x18)	// [LUNA] PF11
#define KC_PF12			(0x19)	// [LUNA] PF12
#define KC_PF13			(0x1a)	// [LUNA] PF13
#define KC_PF14			(0x1b)	// [LUNA] PF14
#define KC_up			(0x1c)	// cursor up
#define KC_left			(0x1d)	// cursor left
#define KC_right		(0x1e)	// cursor right
#define KC_down			(0x1f)	// cursor down

#define KC_INS			(0x20)	// [LUNA-88K] INSERT / [X68k] INS
#define KC_COPY			(0x21)	// [LUNA-88K] [X68k]
#define KC_1			(0x22)
#define KC_2			(0x23)
#define KC_3			(0x24)
#define KC_4			(0x25)
#define KC_5			(0x26)
#define KC_6			(0x27)
#define KC_7			(0x28)
#define KC_8			(0x29)
#define KC_9			(0x2a)
#define KC_0			(0x2b)
#define KC_minus		(0x2c)
#define KC_circum		(0x2d)	// ^~
#define KC_backslash	(0x2e)	// \|
#define KC_buzzer		(0x2f)	// [LUNA] ブザー発声 (キーではない)

#define KC_CUT			(0x30)	// [LUNA-88K]
#define KC_PASTE		(0x31)	// [LUNA-88K]
#define KC_Q			(0x32)
#define KC_W			(0x33)
#define KC_E			(0x34)
#define KC_R			(0x35)
#define KC_T			(0x36)
#define KC_Y			(0x37)
#define KC_U			(0x38)
#define KC_I			(0x39)
#define KC_O			(0x3a)
#define KC_P			(0x3b)
#define KC_at			(0x3c)
#define KC_bracketleft	(0x3d)	// '['
#define KC_hira			(0x3e)	// [X68k] ひらがな
#define KC_zenkaku		(0x3f)	// [X68k] 全角

#define KC_UNDO			(0x41)	// [X68k] UNDO
#define KC_A			(0x42)
#define KC_S			(0x43)
#define KC_D			(0x44)
#define KC_F			(0x45)
#define KC_G			(0x46)
#define KC_H			(0x47)
#define KC_J			(0x48)
#define KC_K			(0x49)
#define KC_L			(0x4a)
#define KC_semicolon	(0x4b)
#define KC_colon		(0x4c)
#define KC_bracketright	(0x4d)	// ']'
#define KC_OPT1			(0x4e)	// [X68k] OPT.1
#define KC_OPT2			(0x4f)	// [X68k] OPT.2

#define KC_XF1			(0x50)	// [X68k] XF1
#define KC_XF2			(0x51)	// [X68k] XF2
#define KC_Z			(0x52)
#define KC_X			(0x53)
#define KC_C			(0x54)
#define KC_V			(0x55)
#define KC_B			(0x56)
#define KC_N			(0x57)
#define KC_M			(0x58)
#define KC_comma		(0x59)
#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_HOME			(0x60)	// [LUNA-88K] [X68k]
#define KC_PAD_plus		(0x61)
#define KC_PAD_minus	(0x62)
#define KC_PAD_7		(0x63)
#define KC_PAD_8		(0x64)
#define KC_PAD_9		(0x65)
#define KC_PAD_4		(0x66)
#define KC_PAD_5		(0x67)
#define KC_PAD_6		(0x68)
#define KC_PAD_1		(0x69)
#define KC_PAD_2		(0x6a)
#define KC_PAD_3		(0x6b)
#define KC_PAD_0		(0x6c)
#define KC_PAD_decimal	(0x6d)	// .
#define KC_PAD_enter	(0x6e)
#define KC_PAD_CLR		(0x6f)	// [X68k] CLR

#define KC_ROLLUP		(0x70)	// [X68k] ROLL UP
#define KC_ROLLDOWN		(0x71)	// [X68k] ROLL DOWN
#define KC_F1			(0x72)
#define KC_F2			(0x73)
#define KC_F3			(0x74)
#define KC_F4			(0x75)
#define KC_F5			(0x76)
#define KC_F6			(0x77)
#define KC_F7			(0x78)
#define KC_F8			(0x79)
#define KC_F9			(0x7a)
#define KC_F10			(0x7b)
#define KC_PAD_multiply	(0x7c)
#define KC_PAD_divide	(0x7d)
#define KC_PAD_equal	(0x7e)
#define KC_PAD_comma	(0x7f)

#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 CC_disconnect	(0x90)	// キーボードを取り外す
#define CC_connect		(0x91)	// キーボードを接続する

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.