イジョケンむかしばなし
PS2で つかえる 専コンがいた
BMSで つかえる 専コンがいた
むかし USBでは 専コンは みんな
ただの ジョイパッドだったから
すきなように なのり
すきなように はなす
それが ふつうのことだった
10ねんまえの あるひ
むげんを なのる ゲームが あらわれた
PS2と ちがう おさら
VID PID の とびらの むこう
そこまで 15ねんの あいだ つくられてきた
専コンたちは すぐに いきばを うしなってしまった
15ねんで おおくの 専コンしょくにん たちは
すでに そのしごとを はなれて しまっていた
専コンたちは 対応基板を えることも なく
しずかに しんでいった…
いくたの しかばねの うえにある しんじだい
DJ DAOと なのる えいりきぎょうは
このよのはるを おうかしていた
ふぇにっくすわんは とても いい 専コンだ
でも 10ねんまえから みすてられた かこの 専コンたちは
かいかえて すててしまうか あやしい きばんに いれかえるしかない
このじだいは ほんとうに しあわせなのだろうか?
はじめに
シンオウむかしばなし改変で書こうとしたら原型が無くなりました。どうもkagura1050です。今回はなんと数か月ぶりの記事で済んでいるらしい。
この記事は「Raspberry Pi Advent Calendar 2025」の10日目の記事です。
https://adventar.org/calendars/11389昨日はあっきぃさん、明日は(null)さんです!
え!?アドカレ参戦は2年振り!?ウッ!
まあグダグダ書きましたが、古めの弐寺の専コンを持っていても、INFINITAS(PCで遊べるサブスク版beatmania IIDX。一部の主要な操作が公式コントローラーでないと行えない)環境を前にすると
- コントローラごと買い替える
- ただの特定のVID/PIDとPS2コンのプロトコルしゃべるだけの物体(よくわからん企業のようわからん基板(メインMCUの刻印が削ってある)とハーネス(18AWG用圧着端子に24AWG))に合計数万円出す
- ようわからん同人ハードを買う
しかないどう考えてものヤだよねというやつです。そもそもそれがBadUSBでない確証もないじゃんというのも。

OSSだとINFINITAS対応はちょいちょいあるんですが、PS2(PlayStation2でCS版が昔出ていた。版権曲や削除曲なども遊べるため一定の需要がある)では使えないのが多い。
今回はPS2対応のそれをPicoで、OSHWで作りましたという話です。
あ、ちなみに話の内容としてはPS2対応が10割です。INFINITAS対応は適当にソース読んでください
beatmania IIDXって?
今回目指すところ
既存の専コンをターゲットに、
- INFINITASで使えて
- PS2でも使える
二つの機能を備えた、RP2040-Zero搭載基板を制作していきます。
今回のターゲット
おそらくいま中古価格が一番安いであろう専用コントローラーであるところの「ビートマニアIIDX専用コントローラー」(RU029)をターゲットとして開発していきます。
安いからというか、自分が今メインで使っているからというのもある。
現状
2023年ごろに自作した基板を乗せています(執筆時点でもう実装まで終わっているので、「いました」が正しい)。
INFINITASにこそ対応していますがPS2には対応できていません。
ので、なんと我が家には複数台専コンがあります(ひとつはPS2用)

←PS2用 INFINITAS/BMS用→
PS2コントローラー対応は難しいとされている?
ひとことでいうと「SPIスレーブ」というわりとサンプルの少ないソレだから。
しかもデータ通信がトランザクション単位ではなく、トランザクションの1バイト目に送ってきたデータにより返すデータもデータ長も変わるし、ACKという独自信号が生えているというそこそこめんどくさい仕様。
しかもプロトコルもあまり明文化されておらず、PS2実機でしっかり認識させるには割と作りこんだ実装をしないといけません。
して、ネットの海を彷徨った結果おととしぐらいに見つけたのがコレ。
Emulating a Dualshock 1 controller in digital mode.
byu/darkgiuseppe inpsx
コメント欄に登場している野生のオタクが、AVR向けのシンプルな実装を公開してくれていました。
今回はこれをベースに実装を進めていきます。
プロトコルの解説
まず、PS2コントローラのきほんは
- 周波数250KHzで
- Mode3でLSB Firstの
- Slaveが1バイトごとに/ACKを返す必要がある
- SPIで
- DAT(MISO)と/ACKはオープンドレイン
です。
波形としてはこうなります(2バイト通信の例)。

ふつうこういうことをやるならSPIペリフェラルを使いますが、今回はまたRP2040で殴ってしまおう、ということで以前失敗した「core1を使ったポーリング」にチャレンジしてみました。(ペリフェラル触るのがめんどかったとも言う)
以下、通信内容の説明です(適当に書いたらなんか硬い文章になった)
TL;DR : これ通り実装してうごきました
通信内容
※本章で登場するMUST, SHOULD等の単語の意味はRFC2119/8174に従うものとします
実はコントローラはメモリカードと同じバスにつながっているのですが(!)、そのおかげかややインテリジェンスなコマンド構成となっており、パッドはそれに対して正しく応答する(または、応答しない)ことが求められます(MUST)。
情報元 : ps_jpn.txt
フェーズ1 検出
このフェーズでは、PlayStation本体(以下、本体)がコントローラ(以下、パッド)が接続されている/いないことを検出します。

/ATTがアサートされた後、データ01hを受け取った場合、コントローラは100μs以内に/ACKを2μs以上引き下げる必要があります(MUST)。引き下げない場合、本体はパッドが未接続であるとみなします。
このとき、データが01hでない場合はパッドは/ACKを引き下げてはいけません(MUST NOT)。(参考:81hはメモリカード)
本体が/ACKの引き下げを確認した場合、/ATTがアサートされたまま次のフェーズに移行します。
Tips: 図に示したようにここではDATは厳密には不定である(パッド/メモリカードどちらも駆動していない)。本体側を実装する場合はきちんとプルアップするなど適切な対応をすること
フェーズ2 応答IDの報告
このフェーズでは、パッドが本体に応答IDの送信を行います。

応答IDは2バイトからなります:
- 1バイト目 上位4bitがコントローラ種別、下位4bitがデータ長/2
- 図ではコントローラ種別 = 4, データ長 = 2バイトとなる
- 2バイト目 5Ah固定
1バイト目の下位4bitが0であった場合、データ長は32バイトとみなされます。
ここで応答IDが得られた場合、本体はATTをアサートしたまま次のフェーズへ移行します。
フェーズ3 データの転送とトランザクションの終了
このフェーズはトランザクションの最終フェーズです。
実際にパッドからのデータ転送を行います。

ここでは本体はデータ長分の00hを送信し、それに合わせてパッド側はボタンデータを送信します。
送信データにおけるボタンの対応は以下の通りです。(0 = 押下)


パッド側は最終バイトの転送後、/ACKを引き下げないことができます(MAY)。また、本体側がデータ長以上の転送を行ってくる可能性を考慮すべきです(SHOULD)
本体側が(データ長ぶんの転送終了、/ACKの無応答等をもって)転送終了を判断した場合、/ATTがデアサートされてトランザクションが完了します。
Tips: もちろん本体側もデータ長以上の転送は行わないべき(SHOULD NOT)


基板
して、ソフトができたら次はハードです(逆で、実はハード先行で実装していた)
KiCADでざっくり作って

JLCに発注して

実装!

完成
IIDX CS 3rd/9th/DD, beatmania 2ndMIX/YEBISU Mix/3rdMIX/4thMIX/GOTTAMIX、beatoraja、IIDX INFINITASで動作確認しました。
リポジトリはこちら!
感想
やっぱりRP2040は速い!
RP2350も今度使ってみます。

そういえばこの記事は3939文字らしいです。初音ミクV2はいいぞ!
Project DIVA Mega39's+の専コンもいまらずぴこで作ってるので、そのうちブログに書いたりGitHubに放流したいね!