ゲームポートのしくみ
- 公開日: 2016/10/01(土) 09:54[JST]
USBが普及する前にPC互換機で広く利用されたジョイスティック用の端子であるゲームポート(game port)について調べてみたのでまとめてみる。
ゲームポートとは
ゲームポートはDサブ15ピン(DA-15)のコネクタを介してジョイスティックとPCとを接続するインターフェースである。英語版Wikipediaによれば、ゲームポートは81年のIBM-PC登場時点で純正オプションとして用意されていたようだ。当初は単独のカードとして提供されていたが、その後はMulti/Super IOカードに含まれるようになったり、サウンドカードに含まれるようになった。
構造的には4軸のアナログ入力と4つのデジタル入力とを備えた端子であり、当初は二股ケーブルを用いて2軸、2ボタンのジョイスティックを2つ接続することを想定していた模様。そのためか端子の上段(ピン1~8)・下段(ピン9~15)のそれぞれに2軸、2ボタンの入力が割りあてられている。具体的にはピン3,6,11,13がアナログ入力で、ピン2,7,10,14がデジタル(ボタン)入力となっている。DOS時代末期はスロットルレバーを含めた3軸、4ボタン、8方向の視点切り替えスイッチ付きのフライトスティック等が登場している。
ジョイスティック側の構造
epanprama.netに記載のドキュメントによれば、ジョイスティックのXY軸(やスロットル)の傾きを検出するためにVccとアナログ入力端の間に100kΩの可変抵抗を配置するようになっている。そして、レバーやリンク機構などを用いてジョイスティックやスロットルを可変抵抗の回転つまみに連結し、これらの傾きによって可変抵抗の抵抗値が変化するようにする。なお、ボタンについてはアタリ規格等と同様各端子とGNDとの間にボタンを配置するようになっている。
PC側の構造
ボタンについては5V/1kΩで端子をプルアップしておく。アナログ入力についてはやや複雑で(epanorama.net参照)、アナログ端子を抵抗(2.2kΩ)やコンデンサ(22nF)とともにNE558等のタイマICに接続するようになっている。タイマICは、コンデンサが放電されてから所定の電圧まで充電されるまでの間、Hを出力する回路である(充電が終わるとLを出力し続ける状態になる)。マルツオンラインの解説によれば(ゲームポートに使用されているNE558はリンク先で説明されている555を4回路内蔵したIC)、NE558がHを出力し続ける時間は1.1CRとのことであり、最短(ジョイスティックの可変抵抗が0Ωの時)で2200*2.2*10^-8*1.1=約53マイクロ秒、最長(ジョイスティックの可変抵抗が100kΩの時)で(2200+100000)*2.2*10^-8*1.1=約2.5ミリ秒ということになる。(2016/10/7追記: epanorama.netの記載によればCrystal Semiconductor CD4376Bのリファレンスデザインとしてコンデンサは5.6nFのものを推奨しており、この場合はNE558がHを出力し続ける時間はおおよそ14~630マイクロ秒ということになる。また、PCI接続のサウンドコントローラの場合は計時用のカウンタ回路を内蔵している場合もあり、I/Oポートへのアクセスを数回に抑えることが可能である。無論専用のドライバが必要であるため基本的にはWindows向けの機能と思われ、多くのDOSゲームでは従来どおりCPUがちまちまと計時する必要がある)
(2016/12/31追記)IBM PC Technical Referenceによれば、タイマ時間は"24.2 + 0.011×抵抗値"(単位はマイクロ秒)とのこと。このことから純正ゲームポートカードに使用されているコンデンサは10nF、抵抗は2.2kΩと推定される。(追記終わり)
PCのCPUはIOを介して周期的にタイマICの出力をチェックし、出力H(負論理なのでI/Oポート上では0)を連続して検出した回数を持って上記時間を計測可能であり、計測した時間から可変抵抗の抵抗値を判断することができる。ゲームポートはこのように時間によってジョイスティックやスロットルの傾きを検出するものであり、タイマICの出力をチェックする間隔を短くすれば分解能は向上する。そのため、十分な分解能を得ようとする場合、ジョイスティックやスロットルの傾きによっては(可変抵抗の抵抗値を最大にしたとき)CPUは数百回I/Oポートにアクセスすることになる。
このように、タイマICをA/Dコンバータ代わりに使うテクニックはA/Dコンバータが高価だった当時は広く利用されていたらしく、AtariAgeのフォーラムによればAtari2600にも採用されていたとのこと(Atariの場合はTIAカスタムチップにタイマを内蔵)。
ジョイスティックの読み取り
Programming to Receive Joystick Input in Dosによれば、ジョイスティックの読み取りは以下の手順で行われる。
CPUへの割り込みを禁止する
ゲームポートにアサインされたI/Oポート(典型的には0x201)に0を書き込む。これによってコンデンサが放電されて充電が始まる
上記I/Oポートを読み出す。この時上位4ビットはボタンの状態を示し、下位4ビットの各々が4系統のタイマの出力値となる
下位4ビットのそれぞれについて、0が出力されていればカウントアップ
3~4の処理を、I/Oポートの読み出し値の下位4ビットがすべて1になるまで周期的に繰り返す。この結果、下位4ビットのそれぞれについて0が出力され続けた時間が計測される
CPUへの割り込み禁止を解除する
I/Oポートの上位4ビットの値からボタンの状態を判断する