雑記帳

電子計算機の"明後日"から、他愛もない話まで。

電脳文庫近況 / Scrapstick概要(1)

長らく開発を続けている割りに今まで殆ど情報を出してこなかったのですが、さすがにモチベーションがアレ気味になってきたので、今回はプロジェクトの現況や概要について、かなり掘り下げて書いてみようと思います。

 

今着手しているのはOSの方です。名前は「Scrapstick(スクラップスティック)」と言います。Slapstickの書き間違いではありません。

 

「ソフト・ハードを問わないモジュール実装と高いモジュール可換性を実現する、新しいコンピュータシステムの開発」なんて掲げていますが、これ使って何がやりたいかというと、気軽にハードウェアの世界と戯れることができる環境と、そんな環境用に書いたコードを将来にわたって(何かしらの簡単な方法で)動かすことができる仕組みを両立させたい…というものです。

「あるOSの中でアプリどうしが通信しているのと、バス上で相互接続されたデバイスどうしが通信してるのって、細かい点は抜きにしてもやってること自体は似たようなもんだろ?」という点に着目して、

  • じゃあそれぞれ区別せずにまぜこぜで通信できるよな仕組みを作ってやれば良くね?
  • いっそ通信相手を(作者ではなく)利用者側都合で自由に差し替えられるようになってりゃ便利じゃね?
  • これ使えば、ハードべったりなコードがあったとしても、必要に応じてハード部をエミュレータへ簡単に差し替えられるので、実機無くなっても動かせるっしょ?
  • なんならこの仕組みにシェル(ユーザコンソール)でも付けてしまえばOSの代わりになるじゃねーか?

…といった発想の元に実装を進めています。OSだけでなくバスプロトコルの開発も視野に入れているのは、ネタの根本がこういったソフト / ハード界面みたいなところにある為です*1。当然、カーネルレベルでのPOSIX互換なんて一切取る気もありません。

 

通信相手がソフト実装かハード実装かを区別しない…ということから察しがつく方もいらっしゃると思いますが、このシステムで扱う通信は「バスアクセス」を抽象化したものです。ユーザモードにおけるコードフェッチやデータエリアのR/W、I/O操作に割り込み等々、大凡全てのバスアクセスがシステム管轄の通信として扱われます(!!)。当然マジメにそんなことしてたら死ぬほど遅くなるので、特定の条件を満たした場合に限ってカーネルを介さず直接ページアクセスできるようにする等の工夫を入れて、実用的な速度で動作するようにしています。また、バスに発行可能なアクセスのサイズは可変長としているので、ブロックI/O的な使い方で通信コスト(発行回数)を減らすことも可能です。この辺は、システムコール的なものを持たせない設計*2などと絡んでいる所でもあるのですが…細かい話はいずれ。

 

前掲の話ではハードモジュールをソフトモジュール(エミュレータ)で置き換えることだけ触れましたが、当然逆も可能です。つまり、元々ソフト実装モジュールだったものをハード実装のアクセラレータに、呼出元コードを弄ることなく利用者都合で自由に切り換えることができます。例えば、元々通信を伴うものや演算系等、処理の粒度が大きく、かつ各々一回の呼出で完結できるようなタイプの処理であれば威力を発揮できるはずです。特に、前述した直接アクセスの条件を満たしていればカーネルを介在せずに直接レジスタを叩くことができるので、大幅な高速化が期待できます。あまりにもソフト間通信コストが問題になった場合は、FPGAボードとかと組み合わせてこういう逃げ道もありますよということで…。

 

この辺をさらに発展させると、

  • デバイスドライバ」の概念は必ずしも必要ではなくなる。同時アクセス時の調停機能と、ハードウェアI/FをAPIが定めるI/Fに見せかける機能を持つエミュレータだったのだ…と解釈できるので、いずれも必要無ければ無くて良い。
  • デバドラが通常階層構造になっているように、エミュレータを多段に繋いでも良い。つまり、各エミュレータ段で直接叩いたつもりのレジスタが、実は他のモジュールでエミュレートされた代物だった…というのを多段に繰り返しても良い。
  • これより、わざわざ抽象化レイヤや共通APIを作らなくても上手くいく可能性が出てくる。例えば、機能Aの実現に使えるハードウェアが5種類位あるとして、作者側は手持ちにあわせてどれか1つのI/Fに合わせたコードを書けば良い。利用者側は、手持ちに合わせて、I/F変換のエミュレータを探すなり*3、作るなり*4すれば良い。恐らく、ユースケースが固まっておらずI/Fが乱立しがちな新規分野だったり、共通APIに集約する動機も無いようなニッチ分野で特に効果的。
  • メモリアクセスが通信である以上、メモリだと思って通信した相手が「本物のメモリ」である必要は無い。即ち、ディスクドライブ等を使ってエミュレートできる(メモリマップドディスク的な)。これより外部ストレージ・メモリ空間上の揮発 / 不揮発メモリ等々を全て等価に扱える。ごくごく自然に仮想記憶が実現できるとでも言うべきか。バス空間上に「ファイルシステム」をマップすることさえ可能。
  • CPUエミュレータを経由して他機種のマシン語で書かれたコードを実行しても、実機向けに書かれたコードと全く同等に扱える。バスアクセスを通信として使うので、通信相手から見ればどっちだろうと差異は無い。極端な話、例えばx64 PC上で、SPARC向けに書かれたアプリケーションが、68000向けに書かれたTCP/IPスタックとARM-v6向けに書かれたモデムドライバと実機モデムを経由して通信を行い、Z80向けに書かれたV9958を使うコンソールに結果を出力…なんてことも、ごくごく自然に行える。CPUエミュレータの多段も可(CPUエミュレータを別のCPUエミュレータ上で動かしたりできる)。
  • これをハードレイヤにも適用すると、ヘテロジニアスなマルチプロセッサ環境を自然に扱える。前述の通り、バスアクセスさえ発行できれば実行コンテキストのアーキテクチャは問わない為。DMAの処遇についても同様。但し、当然ながらカーネル側でも専用の対応が必要。
  • 所用の通信さえ実現できれば良いので、最終的に、Scrapstickの殆どの機能をハードウェア化したアーキテクチャのマシンを作ることも可能かもしれない(ただの浪漫)。

といったように、結構面白いプラットフォームになりそうです。「互換性の担保をエミュレータに押しつける」点や、それを利用して「新しく作る部分では互換性を無視して好き放題できるようにする」という思想については、使い方や目的は違えど、とても古のOSASKっぽい所だと思います(当然ですが、コレには多々強い影響を受けて育ちましたので…)。うまくいけば、コンピュータシステムの組み方・あり方を大きく変えることができるシステムに発展できるかもしれません。例えば、枯れた分野のハードウェアはよりインテリジェントなI/Fを持つ方向に進化することが簡単になるし…ストレージがファイルシステムを話すとか…、新たな分野ではI/Fの試行錯誤がより気軽に行えるようになるはずです*5

 

ここまでは割と美味い話ばっかり書いてきましたが、当然、この方式によるデメリットもあります。

先程からもちょこちょこ触れているように、まずは性能上の問題です。バスアクセス全てをカーネル管轄の通信として扱う以上、このコストがとんでもないことになるであろう予測が立ちます。前述したように、通常のコードフェッチやメモリの読み書き程度であれば、カーネルを介さず直接アクセスできるような細工を入れ込んではあるのですが、モジュール間通信部分はどう転んでもカーネル経由です。単段であればUnix系で言うところのパイプを介したプロセス間通信レベル + αで済むと考えられますが、エミュレータを多段で組むような状況下では各モジュール境界でそれぞれ通信が起きるので、マイクロカーネルでサーバ間通信が多発しているような状況 + α程度を覚悟しておくべきと思います。また、作成者都合で通信相手を限定できない(利用者側で勝手にエミュレータへ差し替えられる / 多段にできる)ことから、時間制約が厳しかったりリアルタイム性を保証しなければ動かない用途には不向きです。こういった性能上の懸念については、いくつか代替の腹案はあるのですが、当面は利便性の代償としてあきらめる方向で考えています。ただ、このシステムの中であっても、極力依存する外部モジュールを減らせばベアメタルに近い性能を出すことは可能と思われるので、必要であればその辺を駆使して乗り切ってほしいところです。

次はこの通信方式に関する点です。モジュール間通信の界面は所定のバスアクセスの形で行う必要があるため、既存のシステムで良く見られる関数呼出スタイルのAPI / ライブラリを、そのまま別モジュールとして切り出すことができません。どうしてもやりたければ、呼出元にラッパ関数を噛ませて、その中で通信を発行する形にする必要があります。これはシステムコールをCから呼ぶラッパ等と同種といえば同種ですが、差し替え可能にしたい部分は全てこの形式にしておく必要があるため、他のシステム用に書いたコードをScrapstickへ移植する場合などはこの点をよく意識しておかないと、折角のメリットが全く得られないハメになるかもしれません。

 

システムの概要をざっくり書いてしまうとこんな感じです。じゃあ後はどこまで形になってるのか…という話なのですが…、以前の記事にも書いたように、現在はWindows上で動く版(以下Win32版と呼びます)を書いていまして、その上でI/Fの確認などの実験を重ねています。流石に記事当時よりも実験が進み、Win32版内蔵のQuark D1000エミュレータ( + α相当。i386Flatモデル固定にして命令を減らしたようなヤツ)上でCで書いた実験アプリを走らせて機能や使い勝手を確認できたりする状態です。詳細は後述しますが、ようやく長年の懸念事項があらかた片づき、今後システムの大改造を伴うような手戻りは無いであろう段階まで来たので、あと2~3機能程、ユースケースとして実現性を確認しておきたい大物が上手くいけば(ハマらなければ)公開に踏み切れると思います。

前述の記事でも少し触れていますが、実機版が完成した暁には、何らかのシリアル通信I/F経由でそのまま協調動作できるようになる予定です。ようはバスアクセスをシステム間でまたいで伝達することができれば、相手方が持つアドレス空間の一部(公開されている領域)をローカルに(仮想的に)マッピングしてアクセスできることを利用して、実機版で走るアプリからWin32版のウィンドウマネージャを叩き、ウィンドウを生成してボタン操作やら入出力やらを受け付けたり、逆にWin32版で走るアプリから実機版のI/Oエリアを叩いたりすることなどに使えます(当然、実機のシェル代わりや各種デバッグにも使えます)。最初に公開するのはこのWin32版の予定です。こっちだけだと魅力半減ですが、どういうものかは伝わるかなぁ…と。

 

(以下、2018/12/29修正)

流石に時間かかりすぎじゃねーの…という話なんですが、実は2012~15年にかけて作っていた代物(1回だけ人目に出したことがあります)を一旦放棄したりと、結構大きな手戻りを何度もやらかしてしまっています(実験的要素しかないので仕方ない部分ではあるのですが…もどかしい)。本稿で書いたことのうちの大半は、この放棄したものでも仕組みとしては実現できる構造だったのですが、一言で言ってしまうと「プラットフォーム性」とでも表現できるでしょうか、使い勝手上の難があった為、その仕組みのままI/F類を整備する気になれず、本格的な実験(特に、発展に書いたような部分の確認)にまで至れませんでした。

この「プラットフォーム性」について具体的に言うと、例えば、自分が書いたコードを他の人にも手軽に使ってもらえるように、或いは他の方が作ってくれたコードを手元で手軽に使えるように…というのは当然ですし、システムを使い込んだ際にスケールしないようでは困りますし(例えばシステムが扱うアドレス空間。フラット・固定長でスケールする訳が無い)、何がどこにあるのかわからずとっちらかったり、システムの扱いが複雑怪奇になりすぎても困ります。この辺り、割とUnix(当初の)やPlan9辺りはバランスが良いんですよねぇ(そしてSmalltalk、テメーはダメだ)。

これらを本来やりたいことと両立して実現できる仕組みに組み上げるのがなかなか厄介で、さりとてノウハウも無いので何度も作っては壊しして進めているような状態です。現在の実装についても、大枠となるブレイクスルーは2017年前半までに得られたのですが、やはり使ってみるとどうしても気になる点が次々出てきて、最近まで長期スパンで大改造を繰り返し行っていた位ですので…。そしてこの部分こそ、システムの根幹を成す「Scrapstickバス」です。少々毛色は違いますが、UnixPlan9で言うところのファイルシステムみたいな立ち位置ですかね。これまで「カーネル管轄の通信」と書いていたのは、このバス上で扱う通信のことです。こいつの概要も書いておきたいところですが、ちょっと長くなりすぎたので年明け以降にでも別途改めて書くことにします。

 

それでは皆様よいお年を。

*1:まぁ単独のバスとして使えるもの方はいつ着手できるかわかりませんが…

*2:HLT等、プロセッサ機能に絡む内容以外のカーネルとの対話は、全て通信経由で行う必要がある

*3:単独では揃わなくとも、多段にすれば揃う可能性が高まる

*4:必ずしもフル機能を作る必要は無く、そのアプリが動く程度のザルいものでOK

*5:I/Fが固まるより前に生まれた徒花たちを、エミュレータさえ書けば後世にも使い続けることができる可能性が高まる。よって、書き捨てることに後ろめたさが無くなる

本体サイト移転のお知らせ

本体サイトの方ですが、ホスティングに使用しているYahoo!ジオシティーズが2019/03/31でサービスを終了するとの報がありましたので、これを機にGitHub Pagesへ移転することにしました。新しいアドレスは下記の通りです。

https://kiyoto-y.github.io/

恐れ入りますが、お暇な時にでもブックマーク・リンクの更新をして頂けると有り難いです。フォルダ構成もそのまま維持していますので、直リンクの場合は頭だけ差し替える形でご対応下さい。サービス終了までの間は両サイトの内容を同期しておきますので、ぼちぼちで結構です。また、このブログや掲示板については移転せず現行のままです。


しかし、他のホスティングサービスが終了していくのを横目に見続けてきましたが、とうとう自分にもお鉢が回ってきました…。元々ジオシティーズ自体じわじわ提供機能を減らしていて(直接喰らったものだけでも、独自メールサービス、初期に掲示板として使っていたジオボード、果てはカウンタ、ゲストブック、ジオログ等々)長期に渡る撤退戦のような状況でしたので、一ユーザとしてはやっぱり…というか、寧ろよくここまで持ちこたえたなという印象です。

そういや上記消えた機能を列挙しながら思い出しましたが、ジオのアカウントは当初自分専用のメアドが欲しくて作って、せっかくだから作ったソフト公開するようにしようかみたいな感じでサイトを開設した記憶があります(尤も、メールの方は数年持たずサービス終了してしまいましたが…)。サイト開設は2001年だったと記憶しているので、約17年ですねぇ。当時中学生だった私ももう三十路ですよ…時の流れは恐ろしい…。しかしまぁ、それだけの期間同一アドレスで細々と成果物を公開し続けることができたのを幸運と見るべきなのかもしれません*1。おかげさまで、あんなニッチな代物しか置いてないサイトなのに、今に至るまでコンスタントに誰かしら見て下さっているようですので。

ただ一方で、今の形式のままやるのもどうなのかなぁという気がしています。というのも、やり方を変えずに版数管理やら整合性やらを含めてちゃんとやろうとすると、間違いなく続けられないと思うので、そこはテクノロジに頼って解決したいという思いはずっとあって、例えば文章をブログに上げたりはその一環だったりした訳です。一方、ソフトの方はこれまでの蓄積(lzh/zip配布で公開した代物)が多い分、前との整合性の兼ね合いもあって、1個だけ試しにGitHubで公開して以降は元のアーカイブ配布に戻していました。いちいちアーカイブ作って周辺ページを手打ちで書き換える現行スタイルよりは、Readmeを説明ページ代わりにした上でgitの日常操作のままアップできるGitHubの方がラクではあるので、折角だからこれを機にスタイルを改めたい感情の方が勝ってきました。

そこで今後、新規で公開するソフト・ハード等はGitHubGitLabリポジトリを作るようにして、サイトの成果物公開機能については概ねアーカイブにしてしまおうかと考えています(つまり、移行先に持っていきディレクトリ構造も維持するが、これ以上の更新はしない)。まだ更新・修正を続ける意志があるものについても公開リポジトリ作ってそちらへ移管しようかと考えていますが、既存のReadmeはShift-JISのせいでGitHub上から上手く表示できない問題があったり、ローカルリポジトリのファイル配置がリリースと異なるものがあったり、残念なコミットログを晒すのに抵抗があったりと、そのまま公開できる状況ではないものが多いので、暇をみつけてぼちぼちやることになりそうです。これはまだ公開してない代物にも言えることです。まぁReadmeの文字コードはともかく、他は気取って使おうと思わなきゃいいだけの話なんでしょうけど…でも抵抗あるなぁ。

また、文章については当面このブログをメインに考えていますが、Yahoo!ブログはWiki文法使用時のクセが強く、特に(よく使う)箇条書きが隠し機能になってたり、それを無理やり使う場合は工夫しないと書式が崩れたりするので、ちゃんとした文章を書く場合は、何らかの静的サイトジェネレータを使ったシステムに移行するかもしれません。本体サイトの既存の記事については、修正がなければこのままにする予定です(つまり、移行先に持っていきディレクトリ構造も維持するが、更新はしない)。電脳文庫関連はアクティブなので(そうは見えないのが心苦しいですが)、前述の通りに更新を継続する予定です。こちらについては近々近況を追記しようと思います。

さらに、前回の反省もあって、試運転さんのアドバイスも参考に、質問や記載ミス・バグのレポートのための雛型の準備と、連絡手段を追加(各リポジトリのIssuesを使用する運用に)してみました。後者の手段を使うと私宛にメールが飛ぶので、ジャンクメール判定さえされなければ見落とす可能性は低いはずです。雛型はについてはひとまずこのサイトのリポジトリに作成しておきましたが、このままではGitHubアカウントを持っている方しかやりとりできない・雛型を使えない為、掲示板からでも雛型を参照できるように別途リンクを貼っていこうと考えています(リポジトリを新設するものについては、Readmeを仕立て直す際にリンクを張るなど)。お気軽にお使い下さい。

今後のやり方は少々変わりますが、趣味の成果物置き場としての立ち位置は変わらず、ましてや現在あるファイルの配置はそのままで、これからも細く続けていく所存です。移転後も引き続き宜しくお願いいたします。


オマケで、ジオからの移転先としてGitHub Pages / GitLab Pagesを検討している方向けのメモなど。

  • GitHub Pagesについて、masterブランチを使わない方法は古い説明なので、無視して良いと思います。
  • GitLab PagesはCI機能の一環として実装されているようです。このため、ただリポジトリ上のファイルを公開するだけでもこれのように、実質何もしないスクリプトリポジトリに突っ込んでおく必要があるようです。
  • また、GitLab Pagesは./publicフォルダ以下のファイルを公開するので、これのようにリポジトリ内の全ファイルを./publicフォルダへコピーするスクリプトにしておくと、GitHub Pagesと同じファイル配置のリポジトリ(rootにindex.htmlを置く)にすることができるようです。
  • Shift-JIS / EUC-JP等のファイルは文字化けするようです(HTTPヘッダか何かで強制的にUTF-8だと通知している??)。各ファイルをUTF-8に変換してしまえば問題ありません。
  • 通信がHTTPS化される為、カウンタ等、外部サイトのコンテンツがブラウザにブロックされる場合があります。相手がHTTPS対応サービスであれば、リンクのアドレスを変更するなりして表示できるように対応すべきです。
  • どちらも、Pushしてから反映されるまでに少々時間がかかります(特にGitLab)。
  • privateリポジトリにしなければコミットログが公開される為、いちいち更新履歴をページ内に書かず、そちらを直接参照させる運用もできるかもしれません(個人的にやりたい)。
  • 見慣れた自サイトに広告が出ないのはチョット嬉しい。

*1:実は、一度古い番地表記アドレスの旧システムからID表記アドレスの新システムへ移行させられたのですが、現時点でも古いアドレスからの転送が残り続けています

Win10(1709~)起動時に前回セッションのアプリが勝手に立ち上がる件の対策

表題の件です。

具体的に言うと、Win10 1709以降で、前回セッションを再起動・シャットダウンで終わらせる際、起動したままになっていたアプリの内一部が、次回ログインする際勝手に立ち上がる…というものです。全てのアプリが自動起動の対象となるわけではないようなのですが、少なくともVisualStudioとタスクマネージャは該当しました。

これに関する日本語の情報としては、この辺を辿った先などで色々な手を使った回避策が紹介されていますが、どうもその後、この機能を正規に無効化する手段が用意されたようです(下記最初のページのコメントによると、1709では2018/02/01のKB4058258以降。1803では最初から)。

参考までに、日本語環境でのスクショを上げておきます。以下の設定をOFFにすることで、スタートメニュー経由などから普通にシャットダウン操作を行っても、前述のアプリが自動起動することはなくなりました。

イメージ 1

尚、Explorerで開いていたフォルダウィンドウをログイン時に復元する機能については、Win95の頃から元々ある別の機能なので、上記オプションの埒外です。こちらは今までどおり、独立してフォルダオプションから設定できますので、必要に応じて設定すると良いと思います(すべてのコントロール パネル項目 > エクスプローラーのオプション > 表示 > 詳細設定: > ログオン時に以前のフォルダー ウィンドウを表示する)。

本当はこんなところに書かないで上記スレッドに追記してあげれば良いのでしょうけど、該当するスレッドが軒並み2018/02にロックされていた為、できませんでした。スレッドによっては、対策がリリースされて暫く経過してからロックされていたものもありましたので、せめて最新の情報に更新してからロックしてほしかったなぁという気がします。

Windows8以降のIME状態通知に関するお詫びと訂正

随分前になりますが、Windows8.1で「親指の友」が動かない件(原因と対策)という記事の中で、「Windows 8.1以降では旧来の親指シフトドライバで必要な通知が飛ばなくなった」という趣旨の記述をしていたのですが、別件を発端とする調査の結果、これが一部事実と異なることがわかりました。

既に当時調査を行った機体もWin10化してしまっているので、再度Win8.1で確認し直すことはできないのですが、少なくともWin10(1709)では、以下の挙動が確認できました。

  • x86版かつPS/2接続のキーボードに紐付くドライバ宛には、正しくIME状態の通知が行われるように見える
    これは、Windows付属KB211用ドライバ(親指シフト PS/2 キーボード)のモード同期処理が正しく動作することを意味します(ストアアプリ相手であってもOKでした)。同じ仕組みを利用する初代親指の友ドライバも正しく動作する可能性が高いです。
  • x64版ではIME状態の通知を受け取る部分の処理が消されているらしく、IME状態の通知を行っても何も起こらない
    つまり、Windows付属の親指シフトキーボードドライバ(FMV-KB211用)を入れても、キーボード側の入力モードがずれます。
    調査手法の都合上、そもそも通知を飛ばす機能自体が生きているのかどうかの確認は行えていません。
  • USB接続のキーボードに紐付くドライバ宛には、一切のIME状態通知が行われない。もしくは、キーボードクラスドライバのインスタンス番号が先頭以外のキーボードに紐付くドライバ宛には、一切のIME状態通知が行われない(この調査のみ、Win10 1803 x86)。
    調査手法・手持ち機材の都合上、どちらが正解なのか確認できていません(USB接続 かつ インスタンス番号先頭の場合や、PS/2接続 かつ インスタンス番号が先頭以外の場合が確認できていません)。

また、x86版側の挙動については、Win XP(SP3)環境でも相違ないことが確認できました。x64版XPは環境が無い為不明です。XPでの挙動から察するに、8.1でも上記と同様の動作だった可能性が高いと考えられます(勿論、一時的におかしくなっていたのが後に修正された可能性もゼロでは無いですが…)。

 

もし、当時その記事(や、その続きの記事)をご覧になり、Win7からのアップグレードを控えられたり、或いはそれを機に(Windows標準ドライバが同じ機能に依存している)KB211等のキーボードを予備役にしてしまった方等がいらっしゃいましたら、大変申し訳ないです。お詫びして訂正します。少なくとも現行Win10のx86版(32bit版)をお使いであれば、PS/2接続など特定の条件下で通知に依存するドライバも正しく動作するようですので、お試しください。

 

また、旧Oyayusbyに付属する説明書等には「WindowsはカナロックLEDの制御を行わない」と書いていましたが、これも誤りで、正確には「カナロックLEDの制御自体は今(Win10 1709/1803 x86/x64)でも行われるが、IMEの状態や実際の入力状況とは特に連動しておらず、IME OFF状態でカナロック操作(Ctrl + Shift + カタカナひらがな)を行った時にトグルする以外は挙動不審(IME OFFでLED点灯状態なのに入力は英字…なども普通に起こる)」というものでした。重ねて訂正いたします。尚、これはカナロックLEDが存在すると通知したUSB HIDキーボード(ようはOyayusby)での挙動なので、AXキーボードなど、AT / PS/2接続のものでも同じかどうかは不明です(自分が持つLEDの通知手段が無いので…)。

 

以下、前者の件についての詳細を書きます。

 

発覚までの経緯と確認内容

掲示板の方でリクエストがあった、OyayusbyをKB211と組み合わせて使う為のカナロック制御アプリ(Oyayusby Utility)を開発するにあたって実験を行っていた時の話です。グローバルフックの実験が上手くいき、IMEの状態も取れたので、試しにPS/2接続用親指シフトキーボードドライバのモード同期を行う機能を組み込んでテストしようとしていました。

ここで比較用として、このアプリを走らせない状態での挙動(x86)を確認したところ、意図に反してIME状態の同期が行われてしまったことから、今回の件が発覚しました。具体的には、Windows標準のKB211用親指シフトキーボードドライバ(親指シフト PS/2 キーボード)をインストールし、マウス操作でIMEの入力モードを変化させ(英小⇔かな)、そのモードで正しく入力できるかどうかを確認しました。かなに切り換えると正しく入力できない(対応するキーのJISかなが入力される)挙動を期待していたのですが、実際には正しく追随されてしまった…という訳です。

原因特定の為に調査を進める過程で、機材の都合からx64版の環境を使用したところ、今度は一切IME状態の同期が行われなかったことから、x64版とx86版で動作が異なることが判明しました。上記実験アプリを使っても同期不可です(この件の詳細は後述します)。本当はJapanistの有無で挙動が異なるかを見ようとしたのですが、こちらは関係無かったようです(2003 / 10共に、あっても無くても挙動は変わりませんでした)。

さらに、当時記事を書くにあたってテストした環境と近い状態で確認すべく、同一の機体(ASUS T100TA-DK32G。但し、OSはWin8.1ではなく、Win10 1709 x86)にて旧親指の友ドライバのかな入力時同時打鍵が効くか試したところ、こちらは当時と同じで正しく入力できませんでした(つまり、IME状態の通知が来ていない)。当該機体にPS/2ポートは無く、キーボードドックのキーボードはUSB HIDキーボードとして認識されている為、USBキーボード限定で通知が来ていなかった可能性が出てきました。

そこで、PS/2ポートを持つ機体(Win10 1709 x86)にOyayusby + 初代親指の友ドライバを接続し、初代親指の友ドライバのレイアウトファイルが使用される状況下で同様の調査を行いましたが、やはりUSB HIDキーボード側ではかな入力時の同時打鍵操作が正しく行えませんでした。

しかし、わざわざIME状態通知を飛ばす側でPS/2キーボードかUSB HIDキーボードかを見て、前者の場合だけ通知を飛ばす…みたいな器用なことをやってるのか甚だ疑問です(できなくはなさそうだが、かなり面倒そうに見える)。特に、T100TA-DK32Gは本体の音量調整ボタンなどもキーボードとして認識されており、キーボードクラスドライバインスタンスはキーボードドック取り付け時点で2つになっています。そこで、キーボードクラスドライバインスタンスの列挙順で先頭のものに決め打ちで通知を飛ばしているのでは? と仮説を立ててみました。キーボードクラスのインスタンス番号とキーボードデバイスの対応は以下のレジストリキー以下で確認できそうです。

HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e96b-e325-11ce-bfc1-08002be10318}

これまで試して上手くいかなかったキーボードのインスタンス番号はいずれも0001となっており、先頭に他のデバイスが割り当てられている状態でした(PS/2ポートがある機体ではPS/2接続のキーボード。T100TA-DK32Gでは音量調整等のGPIOボタン)。T100TA-DK32G(但し、上述の調査から時間が空いてから実施した為、Win10 1803 x86環境に変更済)で確認する限り、先頭インスタンスのデバイスを削除・再起動することでこの順序の入れ換えができるようでしたので、この操作の後にキーボードドックの初代親指の友ドライバでかな入力が正しく行えるかを見てみました…が、ダメでした。

改めて確認してみると、

  • 他にもkbdclassのインスタンス列挙に関係してそうなエントリがある
    HKLM\SYSTEM\CurrentControlSet\Services\kbdclass\Enum
    削除・再起動後にここを確認すると、前述のキーと異なり、順序の入れ換えが行えていません(GPIOボタン側が先頭のまま)。
    但し削除後・再起動前に見ると、先頭(0番)にUSBキーボードが来ます(一時的)。
  • 実際にキーボードクラスドライバへ通知を飛ばす際に必要なハンドルを取る手段として、レジストリを参照せずに行う古いやり方がある
    以下のパスをCreateFile()で直接開くことで、該当するキーボードドライバのハンドルを得ることが可能です。
    \\.\Device\KeyboardClass*
    ※(*は0~)
    削除後・再起動前に、SysinternalsのWinObjで上記オブジェクトが存在するか見ると、KeyboardClass0側が消えていて、KeyboardClass1は残っています。
  • 先の列挙方法も含めた3つとも、列挙される順序は連動して無いように見える
    <divそれぞれ番号がずれる場面があるので(削除後・再起動前)。

となっていました。また、GPIOボタン側の削除・再起動を繰り返しても同上でした。PS/2ポートを持つ機体については、そもそもPS/2キーボードを削除したときの挙動が見れなかった為(再起動するまで削除されない・再起動するとPnPで自動的に再インストールされる)、ハンドル側の挙動について上記に当てはまるか不明です。

上記ハンドルを取る手段については他の方法(Setup API経由での列挙。順序は最初に紹介したレジストリキーと同一でした)よりお手軽ですし、Win2000より前にはSetup APIが存在しなかった為、IME状態通知の歴史(恐らく初期のNTから存在する)を考えると、このオブジェクトを使っている可能性が一番疑わしいのではと考えています。具体的に起こっている状況を想像すると、

  1. システム側のIME状態通知送信部の内部実装が\\.\Device\KeyboardClass0を決め打ちで開いている
  2. KeyboardClass*の割り当て順序にある程度の法則性がある
    例えば、脱着不可なレガシデバイス(PS/2)やルートバスに近い方(GPIOボタン等)から順にハンドル生成される等。

なんてことになっていて、上記2つより、

  1. PS/2ポートを持つ機体では、このポートが常にKeyboardClass0になっていて、親指シフトキーボード用ドライバの動作に支障がないように働いている
  2. 脱着可能かつUSBポート経由のキーボードドックはGPIOボタンよりオブジェクト生成順序が後ろになり、IME状態通知が来ることはない

みたいな状況になっている可能性は割と考えられます。このハンドルが具体的にどういう順序で生成されるのか、あるいは現状どのインスタンスと結びついてるかを手軽に見る方法があると良いのですが、前者はざっと調べた限り具体的な情報は見つかりませんでしたし、後者もkd使わないとダメそうなようなので(RS-232Cで2台直結…)、今回これ以上の深追いはあきらめました。

尚、GPIOボタン側にダミーのフィルタドライバ(IME状態通知が来たときにログ出力等)を仕込めば切り分けは可能ですが、今回はそこまでは実施しませんでした(或いは、キーボードクラスドライバのインスタンスがUSB HIDキーボードしか存在しない機材が手元にあれば良かったのですが…)。

 

なんで当時間違えたか

ひとえに「実験環境の組み方が悪かった(ことに気づかなかった)」という点に尽きます。

当該Win8.1機(ASUS T100TA-DK32G)は当時の手持ちで唯一となるWin8以降の環境(但し32bit)であり、かつ唯一PS/2ポートを持たない機体でした(これは今でもそうです)。前述の通り、当該機体のUSB HID経由のキーボードドライバには通知が来ないようなので、これを以て「通知が来ないよう変更された」と思ってしまった訳です。

このドライバは元々PS/2ポートでの使用を前提としていて、複数インスタンスが実行されることは考慮しておらず(一応最低限の行儀は満たしていますので、複数動作させてワークを破壊したりすることは無いです)、この件以前に複数のキーボードクラスが登録された環境での動作や、USBキーボードへのアタッチ動作を確認したことはありませんでした(Oyayusby作る前はUSBキーボードが手元に無かったというのもありますが)。今冷静に考えると「じゃあ真っ先に疑うべきはUSB化 / 複数インスタンス化だったろ」という話なのですが、当時の状況を思い出せる限り確認したり再現実験を行ったりした限り、infの改造でUSBキーボードへのドライバ導入ができることを以て「フィルタドライバから見たキーボードの通信I/Fは同じ」と判断し、IME状態通知が一部のキーボード宛にしか来ないことについては想像が及ばなかったようです…。

また、残りの環境をWin10化した時点では既にMk-2ドライバしか使用しておらず、旧作ドライバ等のテストも(Win8.1時代の結論より、ハナから使えないと思って)しなかったことや、Win7以前のx64版を常用する機会に恵まれなかったことなど、本件に気づくきっかけを悉く逃していたのも重なってしまいました。

 

x64版でIME状態通知を受け付けない件の詳細

無理やり投げてみても動かなかった…というのは上述の通りですが、じゃあなんで?という話です。

Windows付属KB211用ドライバで、実際に通知を受けてキーボードへのコマンドを発行しているのは、Windows標準のPS/2ポートドライバ(i8042prt.sys)です。なんでそんなことがわかるのかというと、実は2003 Server頃の古いDDKには、こいつのソースがサンプルとして同封されていた為です(input\pnpi8042として収録)。現在のWDKサンプルには含まれていないようですが、本記事投稿時点ではまだ2003DDKの入手が可能のようですので、見てみたい方はこちらから。

こいつを見ますと、IME状態通知関連の部分が、軒並み以下のようなifdefで切られています。

#if defined(_X86_)

昔読んだときは純粋に「Alpha / MIPS / PowerPC避け」だと解釈したのですが(多分書いた人の意図も同様と思います。i8042prtのPnP対応が行われたのは恐らくWin2000の時で、当時x64版はまだ存在しませんでした)、改めて今見ると、これじゃぁx64版も除外されてしまうのですよねぇ…(x64版は_AMD64_。x86の表記自体はx64を内包する使い方もあるのでマジ紛らわしい…)。

そもそもx64版とx86版でこの部分の挙動を変える必然性がイマイチ謎ですし(Alpha等の除外については、これらを積んだFMVが無い為…と解釈できます)、x64版にも「親指シフト PS/2 キーボード」のinfエントリやら専用レイアウトファイル(f3ahvoas.dll)やらが含まれているのを考えると、x64版で使えないのは単なるミスで、中の人が誰も気づいてないだけなのでは?…という気がします。

ついでに言うと、たとえ非IA-32機であってもPS/2ポートを持つ機体ならKB211を差すこともできたでしょうから(しかもこいつはスキャンコード3に対応してたので、これが必要なWSとかでも使えたはずなんですよね)、#if definedで切る必要すらないと思うのですが…やっぱしFMVのオプションという位置づけの対応なんですかねぇ…。

尚、ソースが見れるのはi8042prt.sysの中身だけなので、送信側がどういう風になっているのかは不明です。現状送信されているのかどうかについても、ダミーのレイアウト / フィルタドライバを差さないと見れないので、こちらでは調べていません。

 

あとがき

思えばこれまでも、Win8対応富士通製ドライバのうち、x86版だけなぜかWin7までのドライバと同じバージョン表記のバイナリ(但しタイムスタンプやサイズは異なる)になっていたり、Win8.1や10にしつこく標準親指シフトドライバが残っているのを確認していたりしたので、そこでちゃんと深追いしておけばもっと早く気づけたのかなという気がしています…。思い込みと切り分けの甘さは今後注意していく所存です。

しかしながら、このような「割と巨大なブラックボックスを相手にニッチな機能の正確な挙動を調べる」というのを一人の個人だけがやってるのは、どうやっても正確性の面で厳しいのでは? とも感じています。私が用意できる環境には限りがあるので、どうしてもその範囲内で観測できたことしか気づきませんし、その中での調査しかできません。ですので、もし他にも私が思いっきり間違えたことを書いてるような箇所がありましたら、遠慮なくご指摘頂けると幸いです。調査のきっかけは単なる好奇心でだったり必要に迫られたもの(親指絡みではこっちが多いかも)だったりしますが、折角調べたので自分以外の誰かも必要としているなら…と思って掲載しています。間違いがそのままになっているのは不本意ですので、お手元での追試結果が記載内容と違ったりしたら是非教えて頂けると有り難いです。

Intel CPUの詳しい(古い)資料など

IA-32上で走るOSや486辺りのエミュレータ、或いはパチモンのRTLを書いたりする場合、CPU実機の細かい挙動を知りたくなることがあるかもしれません。通常、詳しい公式資料というと「IA-32 インテルアーキテクチャ ソフトウェア・デベロッパーズ・マニュアル」を見ることが多いのではと思うのですが、これはあくまでもアーキテクチャ共通の記述しかなく、各プロセッサ固有の事柄についてはあまり触れられていません*1

実は、古いモデル(特に386)についてはデータシートや関連するドキュメントの記載が充実していまして、命令セット表やバスサイクルの解説などと一緒にこういった細かな情報についても書かれていました*2。486DX4の頃になるとデータシートは幾分寂しいものになってしまいますが、エンベデット版固有のドキュメントで同じレベルの記載が残りました。一方、Pentium以降はデータシートやWeb上に上がっている文書からは細かい挙動がわかりにくくなってしまったようです。

ということで、486DX4までであれば比較的詳しい説明が得られます。

肝心の入手方法ですが、当然ながら今のIntelのサイトには上がっていません。そこでInternet Archiveの出番です。以下にリンクを張っておきますのでご利用下さい。尚、各文書について、ダウンロード先サーバの選択ではHTTPのみが使えるようですのでご注意を。

特に有用そうなものを列挙しておきます。

何か必要そうな情報がありそうだと思った方はぜひ活用してみて下さい。

 


 

結局今年は親指シフトネタばっかりで全然OS関係のブツを上げられませんでした。Galileoディスコンにも間に合わなかったし…。かなりフラストレーションが溜まっています。ということで、今年最後の悪あがきでOSネタと関連する記事を書いてみました。

外には情報を上げてないのでアレですが、開発中のOSは今年一年でかなり良い方向に進化してきました。これに関連して書きたいことも大量に溜まっています。個人的には、ある程度動くブツをリリースした上で書く方がやりやすい気がしているのですが、頭を整理する為にも、少しずつ文章化して公開していった方が良いのかもしれません。この辺は暫く考えたいと思います。

直近で嵌まって暫く開発が止まったりもしたのですが、まぁアレですね、やりたい事(例えばアプリケーションとか)がかなり明確になっている以上、欲張っちゃいかん…と。最低限必要なネタ以外はある程度割り切って、ちゃっちゃか進めたいと考えているところです。春までに成果物が何か公開できれば良いなぁ…と思います。

 

それでは、皆様良いお年を。

*1:例えば、プリフェッチバッファのサイズはいくらか・キャッシュやTLBヒットミス時のペナルティは何クロックなのか…など

*2:よく非ARM系の組み込み用の石とかでも、データシートに命令セットが書いてあるやつがありますよね。あれと同じノリだと思います

親指シフトキーボードをリモートデスクトップ経由で使う方法

以前、ちょっと実験で、PS/2接続の親指シフトキーボードを接続した環境から別のマシンにリモート接続を行い、そちらで動作するアプリケーション内で親指シフト入力を行えるか試したところ、少し弄る程度で上手くいってしまいました。そのための環境構築手順と、内部動作の詳細について記載してみたいと思います。

 

ここでの記載内容は、Windows 10(1607又は1703) + 親指の友 Mk-2ドライバを使って確認した内容です。富士通謹製のキーボードドライバを使う場合も似たような方法でいけるのでは? と踏んでいますが、レイアウトファイルとして指定されるものとは別のDLLが同封されていたりと、動作が私のドライバと異なる可能性もありますので、上手くいかなかった場合はごめんなさい。また、PS/2タイプの親指シフトキーボードをWindows標準の親指シフトキーボードドライバで使う場合は、ここで書かれた内容相当のものがシステム標準で実装されていますので、改めてこの記事の内容を行う必要はありません(ただ、ホスト側・コンソール側のどちらかがWin8以降の場合、モードずれ対策の制御が効くかどうかは不明です)。

尚、親指の友 Mk-2ドライバは未署名のため、x64環境下で使うのがそれなりに面倒なのですが、ホスト側(サーバ側・リモートでの接続を受け付ける側)をx64版・コンソール側(つまり、操作するキーボードが接続されている側)をx86版のシステムとすると、署名作業を行う必要がなくなります*1

 

超ざっくりした手順

  1. コンソール側に、使用したいキーボードドライバをインストールし、使用可能な状態にします。
  2. ホスト側に、コンソール側で使用されるものと同じキーボードレイアウトファイル(例えば、親指の友 Mk-2ドライバであれば、kbol_611.dllかkbol_oas.dll)を、ホスト側の%SystemRoot%\System32\以下にコピーします。ホスト側にも同じドライバがインストールされていれば、既にファイルがあるはずですが、そうでない場合(そうしたくない場合)は手動でコピーしてください。
  3. ホスト側の以下のレジストリ値を、使用したいレイアウトファイルの名前に書き換えます。
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\KeyboardType Mapping\JPN\00000002

    "00000002"はレイアウトファイルとして親指の友 Mk-2ドライバのものを使う場合です。富士通製ドライバでどの値が来るかは不明ですが、もし左記を試して上手くいかないようであれば、"00020002"、"00000502"、"00020502"辺りを試してみて下さい(値が無い場合は作成)。

これで導入完了です。

 

リモート接続時に行われていること

リモートデスクトッププロトコル上、端末間で転送されるキーコードは「コンソール側キーボードドライバから通知されたスキャンコード」です。つまり、スキャンコードを仮想キーコードや対応する文字として解釈する判断は、全てホスト側で行います(一応、コンソール側からUnicodeキャラクタを送ることもできるようなのですが、これ送ったらどういう扱いになるのだろう…。通常はこっちではなく、前者の方が使われているようです)。

このため、ホスト・コンソール間で使用するキーボードレイアウトの同期が必要です。この情報(キーボードレイアウトの識別子)の転送はセッション開始時に行われます(この辺りの詳しい動作は後述します)。ホスト側はこの情報より、必要なキーボードレイアウトを自身のシステム上で探してロードします。これによって、コンソール側のキーボードドライバが受信・処理したスキャンコードを、ホスト側で正しく扱うことができるようになる…という訳です。

これらの動作を、親指の友 Mk-2ドライバを使う場合の機能分担として示すと、親指シフトの同時打鍵処理(レイアウトファイルが理解できるキーシーケンスに変換する)やキー置換、零遅延モードの処理などは全てコンソール側で行われます。一方、スキャンコードから仮想キーコードへの変換(PF20や英字といった特殊なキーを含む)や、仮想キーコードから文字への変換(NICOLA配列のカナ等を含む)などはホスト側で処理されます。つまり、時間制約がシビアな処理については全てコンソール側で行われることになります

このため、表示上のラグは感じるかもしれませんが、誤打鍵などの問題は特に発生しないはずです(普通にローカルで入力する場合と同程度)。また、ドライバの挙動はコンソール側で設定した内容がそのまま使えますので、コンソール側における普段使いの感覚で自然に使用できるのではないかと思います。

 

レイアウトファイルが選ばれるまでの挙動

システムが使用するキーボードレイアウトの情報は、全てレジストリ上に登録されています。この辺りの情報は「入力ロケール」として、一緒に使用するIME等と共にまとめて管理されているようです。

システムにインストールされている入力ロケールは以下のレジストリキーに登録されています。

HKEY_CURRENT_USER\Keyboard Layout\Preload\

ここで指定する値に対応する入力ロケールは、以下のレジストリキーに登録されています。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\

但し、新しいI/Fを使うIME(IMM32ではなくTSFを使うもの)の場合は、IMEに関する情報はこの辺りには現れないようです。例えば、Japnist 10とMS-IMEのみがインストールされている環境では、データが"00000411"になっているエントリ1つだけが存在します。"00000411"は前述したKeyboard Layouts\を見て頂くと分かるとおり、日本語入力ロケールに対応しているエントリです(IMEに関する情報を含まない)。

この入力ロケール毎キー配下に"Layout File"なる値があります。ここが、この入力ロケールで使用されるキーボードレイアウトファイル名です。ところが、試しにKeyboard Layouts\00000411\の値を見て頂くと分かると思いますが、ここには"kbdjpn.dll"が指定されています。お使いのキーボード配列がどうなっていようと、恐らく通常はこのような状態になっているはずです(US配列に設定していようが、富士通製ドライバを導入していようが、親指の友ドライバを使っていようが)。

 

実は、kbdjpn.dllには他のキーボードレイアウトを参照して渡す処理が実装されています(一応、自分自身が持つデフォルトの日本語配列を返す機能も持っているようなのですが)。現在の言語が日本語かつリモート接続ではない場合、以下のレジストリエントリで指定されたレイアウトファイルを参照します。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters\LayerDriver JPN

これがかの有名な、日本語ロケールにおけるレイアウトファイルを変更する場合に触るレジストリ値の正体です(よくUS配列を使いたい場合とかに弄られている印象があります)。親指の友 Mk-2ドライバをインストールする際にも、ここを書き換えて同封のレイアウトファイルが読み込まれるようにすることで親指シフト配列を実現しています。

 

一方、リモート接続された場合は少し挙動が変わります。リモートデスクトッププロトコルでは、セッション開始時にコンソール側で使用しているキーボードレイアウトの識別子をホストへ伝達します(Client MCS Connect Initial PDU with GCC Conference Create Request時に送る、TS_UD_CS_COREのkeyboardType / keyboardSubType)。この識別子は、恐らくコンソール側で使用しているキーボードレイアウトファイル内に記載されているdwType / dwSubTypeの値を使うのですが、通常日本語配列のキーボードレイアウトでは、別途コンソール側のレジストリ設定で上書きしているようです。これは以下で指定します。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters\OverrideKeyboardType 及び OverrideKeyboardSubtype

通常の106キーボードであれば0x07(日本語) / 0x02(Microsoft / 106配列)になっているはずです。親指の友 Mk-2ドライバでは0x07 / 0x52(富士通 / FMV親指)にしています…が、レイアウトファイル内のNLS設定にて106キーボードを装うようにフラグを立てている為、Overrideの値をさらに上書きして、対外的には0x07 / 0x02として動作します(ややこしい…)。

ホスト側では、コンソールから送信されたこのType / SubTypeを用いて、このセッションで使用するキーボードレイアウトファイルを検索します。この為のテーブルもレジストリ上に登録されていまして、以下のキーが対応します。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\KeyboardType Mapping\JPN (Typeが0x07の場合…日本語なので)

各値の名前は、SubTypeバイトの上位ニブルのみ4ビット左シフトしたもののようなのですが、テーブルを見ていただければ分かる通り、他にも謎のビットが使われていたりして、正直よくわかりません。唯一Windows SDK付属のkbd.hから伺える変則タイプの挙動として、富士通親指シフトキーボードをリモートデスクトップ経由で使う場合はSubTypeを0x00020002として扱うようです(なのでテーブル上でも、"00020002"のエントリはf3ahvoas.dllというWindows標準親指シフトドライバのレイアウトファイルが指定されています)。

尚、前述の通り、親指の友 Mk-2ドライバのレイアウトファイルを使う場合は00000002の値を弄ればOKです。

 

終わりに

ひとまずこれで、親指シフトキーボード使用時にもリモート接続を活用しやすくなるのではないかと思います。また、レイアウトファイル周りの解析結果については、他のマイナー配列使いの方にとっても応用が効くかもしれません。

尚、記載内容の多くは、関連するDLLの解析(主にinput.dll、kbdjpn.dll)や外部I/F操作による値変化の追跡などから得ていますので、将来に渡って通用するかどうかの保証はありません。例によって、記載内容を使用する場合は自己責任の下でお願いします。
リモートデスクトッププロトコルについてはマトモな資料が存在しますので、詳しく知りたい方はそちらも参照してみてください。

*1:ホスト側では当該ドライバのカーネルモードモジュールをインストールする必要がない為。レイアウトファイルはユーザモードDLLですので、署名が無くてもx64環境下でロードさせることは可能です

帰ってきたJapanist(Japanist 10レビュー)

まさかまさか、あのJapanistがUWPアプリ対応になって帰って来ました。

なぜかJapanist 2003が同封されている…という点が諸々不安を感じさせるところですが、早速入手し(V10.0 L10 rel.001)人柱になってみましたのでWindows 10(1703 x86版)上で使って気づいた点などをまとめてみようと思います。尚、キーボードドライバは親指の友 Mk-2ドライバ V2.0L23、Japanist上のキーボード指定は「OASYSキーボード(実行付き)」にしてあります。

 

OAK使いのための初期設定

Japanist 10では、2003にあった「環境スタイル」機能が無く、また、各種設定の初期値が「MS-IME風」っぽい動作になっているようです。

このため、OAK風の挙動を再現する為には逐一手動で設定してやる必要があります*1

Japanist 2003を使っているのであれば、そっちの動作環境と見比べながら設定していけば良いのですが、将来Japanist 10へ完全移行することになった場合など、手元に参考資料がない場面も想定できるので、設定値のメモを載せておきます。宜しければお使いください。

尚、ここで言うOAKはFM TOWNS版(またはFMRのMS-DOS版)を指します。Japanist 2003の標準スタイルでいうOAKはWindows 3.1版っぽいので、ここでは「OASYS V」スタイルの設定値を表示します*2

 

イメージ 1

イメージ 2

イメージ 3

イメージ 4

イメージ 5

イメージ 6

 

よくなったところ

気を取り直して、個人的に感じた改善点を列挙してみたいと思います。

 

UWPアプリ対応

OS標準アプリのUWPアプリ化もじわじわ進んでいるご時世ですので、この対応は有り難いです。EdgeだろうがSticky NotesだろうがOneNoteだろうが、問題なく入力することが可能です。

しかしながら、Windows Store経由で入手するアプリすべてがUWPアプリ対応のIMEを要求するのかというと、どうもそうではないようでして、例えば秀丸のストアアプリ版のように、Desktop Bridgeで移植されたものについては旧仕様のIMEでも使えるようです(秀丸にてJapanist 2003が使えるっぽいことを確認しました)。なので、もし2003をお持ちの方が導入を検討しているのであれば、使用したいソフトが本当に新仕様のIMEを使う必要があるのかどうか、手元で確認してみると良いと思います。

 

タスクバー形式の入力モード通知が見やすくなった

ようやく白文字デザインになったので、通知が使い物になるようになりました*3

 

コマンドプロンプト上でもとりあえず動く

Readmeには「対応していない。使うな」とありますが、一応動きはするようです。

尚、2003だとコンソール上では一切入力を受け付けませんでした(あれ、そうだっけ? いつのまにかこっちも旧式IMEはダメになったのか??)*4

 

Unicode基本多言語面以外に対応

個人的にはJIS2004対応よりもこっちのほうが嬉しいかもしれません(開発環境等のUTF-8化が進んでいるので)。つまり、絵文字とかヒエログリフとか楔形文字とかを、マルチボードで入力したり単語登録したりできるようになります。

これを組み合わせて何ができるかというと、例えばこんな使い方ですね。

イメージ 7
コメント・コミットログ、はたまたブランチ名など、これでいくらでも気軽に汚染させることができます ;-)
(失礼しました…。)

 

一部のテキストボックスでの動作改善

具体的には、VisualStudio2017のXAMLデザイナのプロパティページのテキストボックスで文字入力ができるようになりました。2003では直接入力すら反応しませんでしたので、もしかするとここだけTSF使ったIMEを要求する代物だったのかもしれません。

尚、親指の友 Mk-2ドライバを使った場合は、カナのバンク切り換えが正しく行えず、まともに使えません(つまり、IEで正しく入力できない症状と同じ)。これはIME側の問題ではないので、快速親指シフトを使う場合は正しく動く可能性が高いです(確認してません)。純正ドライバだとどうなんでしょうねぇ…。

 

引き続き使えるマイナー機能

「単語登録」「漢字辞書」などの富士通拡張な仮想キーコード

正直、FMR版 Windows NTのキーボードレイアウトの残骸位でしか見かけないOEMコードなのですが、なぜか対応しています(そして、その残骸は、なぜか今でも最新のWindows SDKに残っているという…)。
親指の友Mk-2ドライバでは配列置換などを使ってこの仮想キーコードを投げることができるので、興味がある人は試してみて下さい。

 

消えた?機能

公式に触れられている削除機能(OASYS固有の特殊入力…半角ひらがな・4倍角など…、JEF入力など)以外に、ざっと動作環境画面を見た限りでも、

  • 変換状態の色設定がない(TSFでは描画をIME側ではなくアプリケーション側で行うからだと思います)
  • 変換方式の設定がない(単文節変換固定にできない)

等々、随分削ぎ落とされた印象です。その他細かいものの重要な機能について以下にまとめておきます。

 

「自動的に起動する」

Japanist 2003まではこの機能を入れることで、IMEを自動的に立ち上げることができていました。例えば、テキストボックスにフォーカスを移して無変換を押すだけでかな入力を始めることができていたのですが、この機能が無いせいで、各々初回のみいちいちAlt + 半角/全角を押す必要があります。はっきり言ってめんどい。

この辺については、MS-IMEでもWin10搭載版から初期入力モード設定が無くなっているようなので、もしかすると、MSのガイドラインか何かのせいで組み込めなかったのではないかという気がしなくもないです。

もしそうならこの機能が復活する可能性は期待薄ですけど、であれば、IME OFF状態をal/ALモード相当と考えて、無変換/変換キーでIME ON + かなモードへ(対称性が問題になるなら、オプションとして英字キーでIME OFFへ)遷移できるようにアップデートとかで変更対応して頂けると大変有り難いですねぇ…。

 

「確定時の機能キーを有効とする」

この機能を使うと、例えば変換候補を出した状態でEnterキーを押すことで、結果の確定と改行入力を同時に行うことができていました。これが無いとワンテンポ操作が増えてめんどいです。

こっちはなんだろう…実装上なんか問題があるのかなぁ。それとも単に「正直誰も使ってなくね?」みたいなノリで消されたのか?? 俺愛用してるよ!! 復活してほしいなぁ…。

 

バグ?

Win16アプリで使用できない

半分冗談で試してみましたが、IME ONにもできなければ(利かない)、他IMEから切り換えて無理やり立ち上げることもできません(NTVDMの応答がなくなる)。

さすがに、こんなん現役で使っている人はごくわずかだと思いますが、もし本当に必要としている人がいるなら、おとなしく同封の2003を使うのが良いと思います。こっちならちゃんと動作します*5

 

Windows 10側の謎挙動

直接Japanist 10に関係する話ではないのですが、恐らくこれを検討している方の多くはJapanist 2003をお持ちで、購入後も当面は共存して使うのではないかと思います。ただその際、そういった環境に起因すると思われるWin10側の不具合っぽい挙動がありますので、その解決策を書いておきます。

 

IMEの既定値が変わらない

具体的には、「既定の入力方式の上書き」で指定したものにならない場合があります。

2018/05/21追記

April 2018 Update(1803)では、いずれのIMEであっても「既定の入力方式の上書き」が利くよう修正されている模様です(既にJapanist10/2003が入っている環境をアップデートしたもので確認)。

このバージョンからはコントロールパネルの「言語」が消えた為、ここに記載の回避方法は実施できなくなっていたのですが、そもそも根本の問題から治療されていましたので大変良かったと思います。

これどうも、旧方式のIME(IMM32を使うもの)とUWPアプリ対応のIME(というより、恐らくTSFを使うもの)とが共存しているときにのみ起こる問題のようで、「言語リスト」の一番上にあるものがUWPアプリ対応のIMEであれば、UWPアプリ対応IME同士による上書きのみが可能で、旧方式のIMEを指定しても無視されます。例えば、言語リストの一番上がJapanist 2003であれば、MS-IMEJapanist 10を指定しても設定が効かず、強制的にJapanist 2003が既定値として使われてしまいます。一方、MS-IMEになっていればJapnist 10で上書きすることが可能です。

では、どうすれば設定不可能なIMEを既定値にできるかというと…、そもそもこの言語リストの並びを変えてしまえばいい訳ですね。

言語リストの実体は「コントロール パネル\すべてのコントロール パネル項目\言語\言語のオプション」にある「日本語」→「オプション」内の「入力方式」です。このリストの一番上にあるものが、「既定の入力方式の上書き」を指定しない場合に使われるIMEの既定値です(言語設定で日本語しか入っていない場合)。

イメージ 8

残念ながらリストの順序を変えるためのコマンドがありません。しかし、ここでの「削除」はアンインストールではなく、切り替え対象から一時的に外すことを意味しているので、気軽に削除・再追加が可能です。よって、これを利用してリストの順序を変えてしまえば、「既定の入力方式の上書き」に頼らずともデフォルトのIMEを変更することができます。

具体的には、

  1. リストの先頭に持ってきたいIMEをアクティブにする(そのIMEへ切り換える)
  2. それ以外のIMEを全て削除し、「保存」
  3. 「入力方式の追加」で、必要なIMEを好きな順番で追加し、「保存」

こうすることで、Japanist 2003だろうが10だろうが、お好きなIMEを既定値として使うことが可能です。他のIMEについても同様と思いますので、お困りの方は参考にどうぞ。

 

終わりに

Windows側のI/F変化にJapanistがちゃんとついてきてくれたのは大変良かったと思います。モダンなアプリケーションでも引き続き手慣れた操作を使い続けられるというのは大きな安心であるとともに、既に出来上がった手癖を直さなくて良いことがわかった分、より一層他のことに注力できるというものです。さらにいえば、公式の完全な親指シフト環境が整ったことで、機械周りに疎い親指シフターにとっても参入敷居が大きく下がったのではないでしょうか。これで親指の友 Mk-2ドライバについても、安心して元のキワモノポジションに戻ることができます(笑)。

また、思いの外ちゃんと動いたので安心しました。Readmeで特記がある内容以外の不審な動きは、今のところ特に見当たりません(さすがにWin16の件はノーカンです)。Japanist 2003を付けてきたのは完成度が酷いからではなく、「10で削った機能を当面補うため」という位置づけなのかもしれません。

一方で、OASYS→OAK→Japanistと受け継がれている操作体系の一部が再現できなくなった点・再現させるまでの設定が面倒になった点については残念に思います。実はこういう操作感とか、感覚的に訴えてくる部分みたいなところが一番替えが利かない点(つまり、人を製品に繋ぎ止めるための最強の力)だと思うので、技術的な制約はあるでしょうが上手く回避しつつ復活させて欲しいなと思います。

幸いリリース前より「再変換機能はアップデートで対応」との記載があるので、これで完成!…という訳ではなく当分機能追加が続くのでしょう。あわよくば、前述の消えた機能の復活を願いつつ、気長に次のアップデートを待ちたいと思います。

2019/08/24追記

とか言いながら既に2年近く音沙汰なしですが…(2003はまさかの令和対応アップデートが来たのに…)。

こんだけ引っ張る以上、再変換以外にもここで挙げた「削られた機能」の追加実装が行われているなど、勝手に色々期待しておくことにします(笑)。

*1:これはMS-IME + 親指シフトエミュレータ使いな人の移行を狙ってるのだろうか?
私はOAK風の操作がそのまま使えることに期待してJapanist買ってる人なので、MS-IME風を初期値にする感覚はよくわからないです。

*2:そういや、設定値の初期化・エクスポート・インポートもできなくなったのな…。

*3:そもそも、タスクバーの色が淡色→透過処理→濃色と変化してアイコンデザインと合わなくなったのが問題なので、2003でもアイコンを白縁取り化するアップデートとかしてくれりゃ良かったのでは? という気がしなくもないですが…。

*4:2003のReadmeにも、Vista以降については同様の記述があるので、もしかするとコンソールがTSFを要求していたのかも?
ただ、使うなとある以上、常用しようと企む方は自己責任で。

*5:そもそも25年近く前のアプリがフツーに動くWindowsの互換性よ…。
尚、MS-IMEの方は入力・変換こそできるものの、変換候補リストの文字が消えたり、アプリ終了時にNTVDMが固まったりと、色々挙動不審です。多分MSもテストしてないんでしょうねぇ。
なので、JapanistにWin16対応を求めるのは酷。