IIDX自作コントローラー記事のソフト編(その2)です。
beatmania IIDX INFINITAS(beatmania IIDXのPC移植版。以下、略してINFと呼ぶ。)をプレーできる自作コントローラー仕様について調べてまとめました。
使えるコントローラーについて
とりあえず、INFの公式サイトはこちら。動作環境のページにもあるように、INFにおいてUSB HIDゲームパッドとしては公式コントローラーのみ動作することになっています。サードパーティーの作成したUSB HIDゲームパッド(有名どころだとDAOコンとか)の動作はサポートされておらず、JoyToKeyなどによってキーボード入力に変換して使用するのが一般的です*1。キーボードによる操作はサポートされているためです。
まあアプリをいちいち立ち上げて変換するのが面倒だったり、変換の際の遅延が心配だったり、なによりキーボードには出来ない動作が仕様上存在していて*2不便だったりといった問題があるため、今回は公式コン準拠の動作をするゲームパッドを作っていきましょう。今のところ発売されている公式コンは
の2種類。今回はフル機能を有するプレミアムモデルの再現をしていきます。
公式コンは、つないでゲームを起動するだけで普通に使えるみたいです。一方、ほかのコントローラーは一切反応しません。やはりここにも何かしらの認証プロセスが存在しているようです。
コントローラーが満たすべき仕様
いきなり結論なのですが、INFはコントローラーのベンダーID/プロダクトIDしか見ていません。これらの値が正しくてHIDレポートが同じ形式になっていれば、とりあえず動きます。細かいところは違っていて大丈夫です。ベンダーIDは公開情報なのでweb上のデータベースを引けばよくて、例えば以下のようなサイトを使うことで0x1CCFだとわかります。
USB ID Database::Vendor ID and Product ID list - the sz development
プロダクトIDは某掲示板で0x1CCFを手掛かりにちょっと調べると分かります。あるいは、DJ DAOの配布しているファームウエアをエディタで開き、0x1CCFに隣接する2バイトを読んできても良いです*3。コントローラー仕様はDJ DAOが詳細に公開しちゃってます。怒られないのかな…
youtu.be
まず、デバイス仕様は「2軸16ボタン」ですね。
キーアサインは
1鍵: 1 2鍵: 2 3鍵: 3 4鍵: 4 5鍵: 5 6鍵: 6 7鍵: 7 E1: 9 E2: 10 E3: 11 E4: 12 ターンテーブル: X軸循環
のようになっています。
各種ディスクリプターとして用いることができるものの例です。
/* Device Descriptor */ 18, // bLength 1, // bDescriptorType 0x00, 0x02, // bcdUSB 0, // bDeviceClass 0, // bDeviceSubClass 0, // bDeviceProtocol 64, // bMaxPacketSize0 0xcf, // idVendor[0] 0x1c, // idVendor[1] 0x48, // idProduct[0] 0x80, // idProduct[1] 0x00, 0x10, // bcdDevice (=version number) 1, // iManufacturer 2, // iProduct 0, // iSerialNumber 1 // bNumConfigurations /* Configuration Descriptor */ 9, // bLength; 2, // bDescriptorType; 34, 0, // wTotalLength 1, // bNumInterfaces 1, // bConfigurationValue 0, // iConfiguration 0x80, // bmAttributes 50, // bMaxPower // interface descriptor 9, // bLength 4, // bDescriptorType 0, // bInterfaceNumber 0, // bAlternateSetting 1, // bNumEndpoints (is 2 if the device has INTR_IN) 0x03, // bInterfaceClass (0x03 = HID) 0x00, // bInterfaceSubClass (0x00 = No Boot) 0x00, // bInterfaceProtocol (0x00 = No Protocol) 0, // iInterface // HID interface descriptor 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0, // bCountryCode 1, // bNumDescriptors 0x22, // bDescriptorType 50, 0, // wDescriptorLength // endpoint descriptor 7, // bLength 5, // bDescriptorType 1 | 0x80, // bEndpointAddress (|0x80=in) 0x03, // bmAttributes (0x03=intr) 64, 0, // wMaxPacketSize 4 // bInterval /* Report Descriptor */ 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x04, // Usage (Joystick) 0xA1, 0x01, // Collection (Application) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x75, 0x08, // Report Size (8) 0x95, 0x02, // Report Count (2) 0x81, 0x02, // Input (Data,Var,Abs) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (0x01) 0x29, 0x10, // Usage Maximum (0x10) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x10, // Report Count (16) 0x81, 0x02, // Input (Data,Var,Abs) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x81, 0x03, // Input (Const,Var,Abs) 0xC0, // End Collection 0xC0 // End Collection
あとは実装するだけでちゃんと公式コントローラーとして認識されます。なお、レポートディスクリプタにもある通りHIDレポートは5バイトで、
1: X軸(signed char) 2: Y軸(signed char) 3: ボタン(1~7鍵盤。順にbit0~6に対応) 4: ボタン(E1~4。順にbit0~3に対応) 5: 定数(0x00)
という構造になっています。次回は実装の解説をやっていきます。
まとめ
PS3への対応と比べてずいぶん簡単なコントローラー仕様解析でした。デバイスディスクリプタの時点で異なる2つのファームウエアを同じボード上に共存させる方法について、次回の記事でソースコードを具体的に示しながら解説していきます。ちょっとだけテクいのでお楽しみに(?)下のリンクからシェアやツイートなどしてもらえると大変執筆モチベが上がりありがたいです。良かったらぜひ。何か気になる点があったらコメントか
しありす (@cialis438) | Twitter
へのリプをお気軽にどうぞ。感想やコントローラー自作に関する雑談・質問なども歓迎です。