Language: 日本語 · English · 简体中文
初代PlayStationのBIOSを、映像でもシリアルでもなく「音」で吸い出す。しかも目標は180秒以内。
所有する初代PlayStationの512 KiB BIOSを、アナログステレオ音声でブラウザへ転送するプロジェクト。PS1側はFPUを持たないため、固定小数点演算、SPU ADPCM、ダブルバッファDMAを総動員する。実データ転送はFSKではなく、44.1 kHzステレオOFDMのみ(512ポイントFFT、64サンプルCP、96搬送波、QPSK)。
このプロジェクトの出発点は、はむさん(@Imaha486)による「特別な改造機材を使わず、初代PlayStation自身にBIOSを読み出させ、外部へ運び出す」というアイデアだった。BIOSライタや基板へのはんだ付けを前提にせず、PlayStationがもともと持っている出力をデータ経路として使う。ゲーム機を壊さず、手元にある実機からバックアップを取るという発想が原点にある。
そこから「ブラウザだけで受け取れたら面白い」「映像や音声を通信路として本気で使ったら、どこまで速くできるか」という実験が始まった。単にBIOSを表示するのではなく、誤りを検出し、欠けたデータを訂正し、最終的に512 KiBのファイルをブラウザからダウンロードできるところまでを一つのシステムとして作ることにした。
最初の派生プロジェクト PS1 BIOS Ripper ZX は、PlayStationの映像出力をデータ伝送路にする方式だった。画面へ描いたパターンをビデオキャプチャで取り込み、ブラウザ側で画像解析してデータへ戻す。ZXで、受信ブロック表示、CRC検証、ブラウザだけでのBIOS再構成、CD起動イメージの配布という全体構成ができた。
次の SX は、通信路を映像からアナログ音声L/Rへ変更した。映像キャプチャの解像度や色変換ではなく、PlayStationのSPU、ADPCM、音声ケーブル、オーディオインターフェース、Web Audio APIを相手にする。ZXとSXは見た目やブラウザの設計思想を共有しているが、伝送方式は独立している。
通常のSXでは、まず「実機で安定して512 KiBを取り切る」ことを優先した。その経験から、安定性を保ったまま180秒以内を狙う別ラインとして Burst Edition を作った。FSKをデータ転送から外し、ステレオOFDMへ集中し、FEC、WASM復調、Worker並列処理まで含めて速度と耐障害性を詰めている。
ZXの履歴には「時間方向復号の改善」「実機UVC復号の追従性改善」「8色実機伝送の自己校正」が連続している。合成画像では読めても、実際のビデオキャプチャではフレームの重複や欠落、色の揺れ、タイミング差が出たためだ。そこでマルチスレッド復号、NTSCシミュレータ、パレット自己校正を追加し、さらにスマートフォン表示、60 fpsネイティブ受信、LZSS進捗表示まで直している。
SXの履歴はさらに試行錯誤が激しい。「PS1 OFDM modulatorを修正して実機音声を復号」「44.1 kHz AudioContext」「windowed-sinc再サンプリング」「Cデモジュレータ」「WASM接続」「RS(16+4)」と改善した一方、バッファを2048から8192へ広げた変更は悪化して即revert。ブロック情報をFSKからOFDMへ移す案も、実機で安定せずrevertした。FSKを300から400 baudへ上げる試みもロールバックされ、SPUの再生境界、FSK直後のOFDM同期、モノ伝送、片チャンネルだけ古い波形が出る現象まで追い込んだ。最後に「verified physical BIOS recovery」が記録され、ビルド成功ではなく実機からの512 KiB回収まで到達した。
Burst Editionの最初の本格コミットは55ファイル、約4700行規模で、OFDM送受信、FEC、WASM、合成WAVテスト、PS1 UI、Web UIを一体として作り直している。その後もスタートSE検出、言語切替、CDイメージ配布、CRC-guided補正を加えた。これは最初から正解が見えていた設計ではなく、ZXとSXの失敗ログを次の方式へ持ち込んだ結果である。
Burst Editionでは「180秒以内」が単なる目標値ではなく、常に画面上で競うタイムになった。ブロックを受信するたびに時間が進み、CRCエラーは失速、FEC訂正はピット作業、訂正不能はクラッシュに見える。ならば普通の四角いプログレスバーより、コースを一周するレーシングカーの方がこのプロジェクトらしい。
そこで、受信ブロックをサーキットの周回にし、車が通った区間だけ路面を塗り、CRC NG中はスピン、FEC中は復帰待ち、最終ブロックにはチェッカーフラッグ、完了時にはGOALと紙吹雪を出すUIになった。スタートSEの 2 → 1 → GO! もF1スタートを意識している。
ただし、この派手なレース表現の土台にあるのは、はむさんの「身近な出力だけでPS1 BIOSを救い出す」という原案である。F1化は原案を置き換えるものではなく、180秒への挑戦と、何度も失敗しては実機へ戻る開発過程を、敬意を持って見える形にした演出である。
スタートSEもPS1側で鳴らす三角波ADPCM。短音「ぴー、ぴー」→休符→長音「ぷーーー」の順で、ブラウザには 2 → 1 → GO! と表示される。この音は演出だけではない。オーディオ入力のレベルを合わせる基準、つまりFSKでいうキャリア調整の役目も持つ。なお、FSKを使うのはこの説明上の例えだけで、実データはOFDMで送る。
各グループは最大32データ+4パリティshard。GF(256)(多項式0x11d)のCauchy行列を使い、CRC不一致を「消失」としてガウス消去で欠損shardを復元する。復元後はパケットCRC32 → ブロックCRC32 → BIOS全体CRC32の三段チェック。FFT・同期・復調はC/C++系固定小数点コードをWebAssembly化し、専用Workerで実行する。WASMが使えない環境ではJavaScript版へフォールバックする。
アナログ音声は、デジタルケーブルのように毎回同じ値が届くわけではない。入力ゲイン、左右のバランス、サンプルクロック差、キャプチャ機器のフィルタ、瞬間的なノイズで、特定のOFDMパケットだけCRC不一致になる。そのため、CRC不一致を即終了にはせず、信頼度の低いビット候補、CRC-guided単一ビット補正、最後に32+4 FECという順で救済する。それでも復元できない場合は、壊れたBIOSを保存させず明示的に停止する。
送信順にも工夫がある。長いノイズが連続したパケットを壊しても、一つのFECグループへ損失が集中しないようshardを時間方向へ分散する。ブラウザではFEC処理を専用Workerへ渡し、重い復元中でもレベルメーターやコース表示が止まらないようにした。
PS1のSPU ADPCMは4-bit量子化で、ブロックごとに過去サンプルを参照する。PCで作った理想的なOFDM波形をそのまま出せるわけではなく、量子化誤差、予測フィルタ、ブロック境界、終端フラグ、DMA切替の影響を受ける。エミュレータでは正常でも、実機では前の音が片チャンネルへ再生されたように見える現象も起きた。
そこでスタートSE、OFDM本体、SPU RAM領域を分離し、古いADPCMバッファを再利用しないようにした。波形には短いフェードを入れ、固定小数点演算のオーバーフローも避けた。スタートSEに三角波を選んだのも、実機SPU ADPCMで作りやすく、音量と周波数をブラウザ側で判定しやすかったためである。
開発用MacはMacBook Neo(メモリ8GB)しかない。Codexで基本開発を進め、PS1アプリの重いビルドはMac Studio(512GB)へ渡した。まずDuckStationで起動とオーディオ・ループバックを確認し、次にCUE/BINをCD-Rへ焼いて実機へ。信号経路は次の通り。
PS1 アナログL/R → EP-136 ステレオ入力 → ブラウザ AudioWorklet
入力は44.1 kHzステレオ専用。AGC、ノイズ抑制、エコーキャンセルはすべてOFF。ゲイン調整はかなりシビアで、スタートSEが頼りになる。
開発は「ホスト上のcodec単体テスト → 合成PCM/WAVループバック → DuckStation → CD-R → 実機PlayStation → ブラウザで最終CRC確認」の順で進めた。エミュレータで動くことと、物理的な音声経路で動くことは別の証拠として扱った。実機ではケーブルを挿し直すだけで結果が変わることもあり、ログ、オシロ表示、L/Rピーク、SNR、EVM、CRCエラー位置を見ながら調整した。
Webアプリには、受信をレースに見立てたコース、走行中のF1カー、FEC中のスピン、ゴール演出、ラップタイムを入れた。長い転送を単なるプログレスバーにせず、「音の中からBIOSを回収している」過程そのものを見えるようにするためである。
| 品物 | 入手先 |
|---|---|
| PlayStation SCPH-3500 / SCPH-7500 | メルカリ |
| ビデオキャプチャ / オーディオケーブル | メルカリ |
| CD-Rメディア | あきばおー |
| Apple USB SuperDrive(CD-Rライタ) | メルカリ |
PlayStation 2台、ビデオキャプチャ、オーディオケーブルは総額約1万円。
| 担当 | クレジット |
|---|---|
| コンセプト・着想 | はむ(@Imaha486) |
| Webアプリ / PlayStationアプリ | Codexで開発 |
| ロゴ・イメージ画像 | ChatGPTで生成 |
| 開発・実機検証 | GOROman |
