Skip to content

Instantly share code, notes, and snippets.

@GOROman
Last active August 30, 2026 16:54
Show Gist options
  • Select an option

  • Save GOROman/6c7e7f7e2cdffd929a0c718807e89ab6 to your computer and use it in GitHub Desktop.

Select an option

Save GOROman/6c7e7f7e2cdffd929a0c718807e89ab6 to your computer and use it in GitHub Desktop.
PS1 BIOS Audio Ripper SX 技術解説

PS1 BIOS Audio Ripper SX logo

PS1 BIOS Audio Ripper SX 技術解説

考案: はむ(@Imaha486)さん

概要

PS1 BIOS Audio Ripper SXは、自分が所有する初代PlayStationの512 KiB BIOSを、 本体のアナログ音声出力からバックアップするための実験的なツールです。

PS1側プログラムがBIOSを読み出し、圧縮・分割・誤り検出符号化したデータを FSKとOFDMの音声へ変換します。ブラウザ側はWeb Audio APIで音声を取り込み、 復調、FEC復元、CRC32検証、LZSS展開を行います。BIOSデータをサーバーへ送る 処理はなく、全処理はブラウザ内で完結します。

自分が所有する本体のBIOSをバックアップする用途で使用してください。

システム構成

  1. PS1上で専用CD-Rを起動する
  2. PS1の正常な音声出力チャンネルをPCまたはMacの音声入力へ接続する
  3. HTTPSの受信ページで入力デバイスを選び、「音声入力を開始」を押す
  4. PS1からFSKヘッダーとOFDMデータを送信する
  5. ブラウザが各パケット、ブロック、最終BIOSのCRC32を検証する
  6. 全検証に成功した場合だけ ps1-bios.bin を保存できる

BIOSコンテナ

  • 読み出し元: 0xBFC00000
  • 元サイズ: 524,288 bytes
  • 独立ブロック: 16 KiB
  • 圧縮: 4 KiBウィンドウ、最大一致長18 bytesのLZSS
  • 圧縮後が小さくならないブロックはRAWで格納
  • stored block CRC32、復元後block CRC32、BIOS全体CRC32を保持

分割ブロックが壊れても他ブロックへ展開履歴が波及しない設計です。

音声ワイヤ形式 V2/V5

転送開始時は300 baud BFSKを使います。

  • space: 1,200 Hz
  • mark: 2,400 Hz
  • サンプルレート: 44.1 kHz
  • 1 symbol: 147 samples
  • UART: ASCII / 8N1
  • 最初にLのみ、Rのみ、ステレオの3秒チャンネルチェック
  • 交互mark/space同期列、ネゴシエーション文字列、CRC付きブロックヘッダー

データ本体はOFDMです。

  • FFT: 512 samples
  • cyclic prefix: 64 samples
  • carriers: 96本、bin 24〜119
  • pilots: 8本
  • modulation: QPSK
  • packet: 176 bytes、うちpayload 144 bytes
  • FEC: 16 data shards + 4 parity shards
  • packet CRC32とブロックCRC32

ワイヤ形式はバージョン番号を持ち、既存デコーダーとの互換性を維持します。

モノをデフォルトにする理由

SX v0.3では、同じOFDM信号をL/Rへ送るモノモードをデフォルトにしています。 片チャンネル入力でも受信でき、両側が使える環境では受信側がチャネル電力に 応じて最大比合成します。

同期シンボルから96キャリア個別の複素チャネル応答を推定し、周波数ごとの 振幅差と位相差を補正してからQPSKを判定します。片側が無音の場合、その側の 合成重みは実質ゼロになります。

転送速度

モノOFDMのFEC込み理論実効レートは約7.84 kbpsです。4 KiBのワイヤブロックは 40パケットで運びます。

  • OFDM区間: 約4.72秒
  • FSK同期とヘッダー2コピー: 約1.03秒
  • OFDM開始ガード: 約0.09秒
  • 通常の4 KiBブロック合計: 約5.85秒
  • ブロック境界込み実効速度: 約5.6 kbps(約700 B/s)

最初のブロックには3秒のチャンネルチェックとネゴシエーションが加わるため、 約12.8秒かかります。実際のBIOS全体時間はLZSS圧縮後のコンテナサイズで変わります。

PS1側

初代PlayStationのCPUにはFPU(浮動小数点演算器)がありません。そのため モデム生成では浮動小数点処理を使わず、固定小数点IFFTでOFDM波形を生成します。 生成したPCMをSPU ADPCMへ変換し、SPU RAMのダブルバッファとDMAで連続再生します。 送信モード、ブロック番号、CRC、進捗はPS1画面に表示します。

SPU ADPCMはBIOSデータ自体の圧縮方式ではなく、生成済みOFDM音声をPS1のSPUから 再生するための格納形式です。176-byteパケットをQPSKへ割り当て、IFFTで得た 44.1 kHz/16-bit PCMを28 samplesずつ処理します。1ブロックは16 bytesで、 2-byteヘッダーと28個の4-bit量子化サンプル(14 bytes)からなります。

現在のリアルタイム高速エンコーダーはfilter 0を使い、各ブロックのピークに 合わせて量子化shiftを選びます。L/RのADPCM列はSPU RAMへDMA転送し、voice 0を L、voice 1をRへ振り分けます。SPUがハードウェアでPCMへ戻したアナログ波形を、 ブラウザがOFDMとして復調します。ブラウザがADPCMデータを直接読むわけでは ありません。

ステレオ時はL/Rへ別々のQPSKデータを載せます。モノ時は同じPCM波形をL/Rへ 複製し、それぞれを別のSPU ADPCM列にして再生します。片チャンネル入力として 取り込む場合も、同じワイヤ形式を復調できます。

ブラウザ側

ブラウザはステレオ音声入力を要求し、echo cancellation、noise suppression、 automatic gain controlを無効にします。

  • AudioWorklet: リアルタイム入力、レベル/RMS/peak、FSK復調
  • OFDM Worker: リサンプリング、同期探索、FFT、等化、QPSK復調
  • FEC Worker: GF(256)による欠損shard復元
  • UI: L/Rレベル、同期相関、SNR、EVM、packet CRC、block状態を表示

入力レベル表示は約29 Hzで更新し、重い波形スナップショットは約9.6 Hzへ 間引きます。画面側は描画フレームごとに最新値だけを反映し、古い更新を キューへ溜めません。

完了判定

次の条件をすべて満たすまでBIOSのダウンロードは有効になりません。

  • 必要な全ブロックを受信済み
  • stored block CRC32が一致
  • LZSS展開後の各block CRC32が一致
  • 復元サイズが524,288 bytes
  • BIOS全体CRC32がPS1側の値と一致

検証範囲

2026-08-30時点:

  • codec/packet/FEC単体テスト: PASS
  • 合成PCM + SPU ADPCMループバック: 160/160 packets、最終CRC一致
  • 片側無音のモノ受信テスト: PASS
  • Docker PSn00bSDKビルド: PASS
  • CD-R書き込みと実機PlayStationでの読み込み/起動: 確認済み
  • localhostでの実音声レベルメーター更新: 確認済み
  • 物理PlayStation音声からブラウザへの完全な512 KiB回収: PENDING / UNVERIFIED
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment