何をしているのか
今回は ChatGPT GPT-6.1 Sol のウルトラを使用して調査を行っています。以下の記述についても草稿を書いてもらってそちらを私が修正しています。
以下の雑誌の付録「サウンドミニアーケードスティック」に入っている音声を、再生可能なファイルとして取り出せないか調べています。
外付けフラッシュメモリを読み出せば音声が見つかるかと思いましたが、独自形式と思われる圧縮データが入っており、まだWAVへの変換には成功していません。
一方で、ダンプから286個のデータを切り出し、実機の通信を測定することで、すべてのデータをキャラクターとボタン操作に対応付けることができました。今回は、そこまでの調査をまとめます。
フラッシュメモリを読み出す
基板には音声出力用のTRSF1602Aと、外付けSPIフラッシュメモリが搭載されています。フラッシュメモリの刻印は、見る限りMacronixのMX25R3235Fです。
メモリを基板から取り外し、ElnecのBeeProg2で読み出しました。ただし、ここで少し気になることがありました。MX25R3235Fを選択してDevice IDのチェックを有効にすると、次のエラーが出ます。
Manufacturer / device ID check error! (C2/25/36)
繰り返しても同じ値になり、選択したデバイスの期待値とは一致しません。読み出し時のVCCは、テスターで3.3Vと確認しました。
Device IDのチェックを無効にするとSPI*1で読み出せます。同じ条件で再取得したファイルも完全に一致したため、以降はこのダンプを解析対象としています。ただし、IDが一致しない理由までは解決していません。また、SPI*4では読み出せませんでしたが、そちらはフラッシュメモリの Status Register にある QE(Quad Enable)の設定を変更しないと対応出来ないためと思われます。
取得したファイルは、次のサイズでした。
- ファイル名:
sound_mini_arcade_stick.bin - サイズ:4,195,328バイト
- 内訳:4MiB+1KiB
末尾の1KiBは、後から確認したElnecのソフトウェアの説明により、バッファ末尾に配置されるSecured OTP領域と分かりました。今回のダンプでは、この領域はすべてFFでした。
元ファイルは保持し、切り出しや解析の出力は別ファイルにしています。
先頭に286件の位置表があった
ダンプを調べると、先頭付近に音声データの位置を示す表が見つかりました。
| 範囲 | 内容 |
|---|---|
0x000000~0x00000F |
意味が未解明の16バイト |
0x000010~0x000487 |
286件の位置表 |
0x000488~0x3B72AF |
音声データの領域 |
0x3B72B0~0x400000 |
80で埋められた領域 |
0x400000~0x400400 |
OTP領域 |
位置表は32ビットのリトルエンディアンで格納され、各値はダンプ先頭からの絶対バイト位置になっています。
最初の値は0x488で、位置表の直後を指していました。また、全286件が単調増加し、それぞれの位置に共通の先頭バイト列A7 00 48がありました。
この表を使って、データを286個の個別binに切り出しました。最後のデータだけは次の位置表エントリーがないため、後続の長い充填領域から終端を推定しています。
切り出したデータと、その前後の領域を再結合すると、元ファイルと全バイト一致します。ただし、これは切り出しが可逆であることの確認であり、音声を正しく復号できたという意味ではありません。
切り出したbinは、そのままでは再生できない
音声データには、WAVなどで見かける一般的なファイルヘッダーがありませんでした。
データをさらに圧縮してもあまり小さくならないことからも、すでに圧縮されている可能性があります。ただし、この特徴だけでMP3などの方式を特定できるわけではありません。
調査したTRSFシリーズの資料には、Subband系やADPCM系の音声処理が登場します。このため独自のSubband系形式を候補としましたが、使用されている方式はまだ確定していません。
開発ツールやサンプル、ライブラリも探しましたが、今回のデータに適用できる復号仕様やデコーダーは入手できませんでした。
そこで、実機がフラッシュをどう読んでいるかを観測することにしました。
電源とオシロスコープで実機の動作を追う
測定には、Keysightの直流電源E36313AとオシロスコープDSOX1204Gを使用しました。
基板の電源は3.0V、電流制限100mAに設定し、電源のON/OFFで同じ起動動作を再現します。さらに、ボタン入力も電源の別チャンネルで操作できるようにしました。
最初はSPIのCS#、MISO、MOSI、SCLKを観測し、その後はPWM出力やボタン入力へ接続を変更しながら測定しました。
ボタンを押してフラッシュメモリのMISOとSCLKの波形からビット列を復元し、元のダンプと照合することでどの音声データを読んでいるか判定しています。
「258種類」と「286個」の差は何だったのか
製品の案内では音声は258種類とされています。一方、ダンプの位置表には286件ありました。
最初は隠し音声の可能性も考えましたが、差はちょうど28件です。この製品には28キャラクターがあり、キャラクターを切り替えたときにも音声が再生されます。
ボタンの役割は次のとおりです。
- ボタン1:キャラクター切替
- ボタン2:通常の必殺技音声
- ボタン3:OD必殺技音声
- ボタン4:SA・CA音声
各キャラクターを選択し、技ボタンを最初の音声番号へ戻るまで繰り返し操作しました。これにより、一巡内の音声数と順序を調べられます。
全28キャラを測定した結果、次の内訳になりました。
| 種別 | 異なる音声データ数 |
|---|---|
| ボタン2:通常必殺技 | 75 |
| ボタン3:OD必殺技 | 66 |
| ボタン4:SA・CA | 117 |
| 技音声の合計 | 258 |
| 起動・キャラクター切替 | 28 |
| 全体 | 286 |
技音声だけで258種類、キャラクター切替音声を加えると286種類となり、位置表の件数と一致しました。
今回切り出した全286ブロックは、これらの操作へ対応付けられています。
キャラクターごとの音声数
キャラクター名は、選択順との対応情報をもとに付けました。電源投入直後はルークで、イングリッドの次に切替ボタンを押すとルークへ戻ります。
以下は、戻り確認の重複再生を除いた、一巡内の異なる音声データ数です。キャラクター切替音声は含めていません。
| 順番 | キャラクター | 通常 | OD | SA・CA | 計 |
|---|---|---|---|---|---|
| 1 | ルーク | 3 | 3 | 4 | 10 |
| 2 | ジェイミー | 2 | 4 | 4 | 10 |
| 3 | マノン | 2 | 3 | 4 | 9 |
| 4 | キンバリー | 2 | 3 | 4 | 9 |
| 5 | マリーザ | 2 | 1 | 4 | 7 |
| 6 | リリー | 2 | 2 | 4 | 8 |
| 7 | JP | 3 | 3 | 4 | 10 |
| 8 | ジュリ | 3 | 2 | 4 | 9 |
| 9 | ディージェイ | 3 | 2 | 4 | 9 |
| 10 | キャミィ | 3 | 2 | 4 | 9 |
| 11 | リュウ | 5 | 2 | 6 | 13 |
| 12 | エドモンド本田 | 2 | 3 | 4 | 9 |
| 13 | ブランカ | 1 | 1 | 4 | 6 |
| 14 | ガイル | 3 | 2 | 4 | 9 |
| 15 | ケン | 4 | 2 | 4 | 10 |
| 16 | 春麗 | 5 | 1 | 4 | 10 |
| 17 | ザンギエフ | 1 | 3 | 4 | 8 |
| 18 | ダルシム | 2 | 1 | 4 | 7 |
| 19 | ラシード | 3 | 1 | 4 | 8 |
| 20 | A.K.I. | 2 | 3 | 4 | 9 |
| 21 | ED | 2 | 3 | 4 | 9 |
| 22 | 豪鬼 | 1 | 4 | 6 | 11 |
| 23 | ベガ | 1 | 1 | 4 | 6 |
| 24 | エレナ | 1 | 4 | 4 | 9 |
| 25 | サガット | 3 | 1 | 4 | 8 |
| 26 | C・ヴァイパー | 3 | 1 | 4 | 8 |
| 27 | アレックス | 4 | 4 | 5 | 13 |
| 28 | イングリッド | 7 | 4 | 4 | 15 |
| 合計 | 75 | 66 | 117 | 258 |
キャラクターによって数にかなり差があります。たとえばイングリッドは通常技だけで7種類、合計15種類。一方、ブランカとベガは合計6種類でした。
ただし、ここで数えているのは異なる音声データの数です。技名や発話内容そのものの分類までは行っていません。
圧縮方式の解析はどこまで進んだか
SPIの読出し量や間隔、圧縮データのビット配列、PWM出力を手掛かりに、符号構造も調べています。
繰り返し現れる51ビットの並びや、16ビット単位の読出し、データ中のビット配列と読出し間隔の関連などが手掛かりになりました。
ただし、繰り返しがあることと、それがコーデックの1フレームであることは別です。また、フラッシュから読み出した量と、復号器がその時点で消費した量も、先読みがあれば一致しません。
Rice符号やExp-Golomb符号などを仮定し、読取り処理とSPIの待ち時間を比較する検証も行いました。しかし、ある音声で選んだモデルが別の音声でも共通して良い結果になるところまでは進みませんでした。
現時点では、次の点は未確定です。
- 圧縮符号の正確な構造
- フレームや記号の境界
- サンプル数とサンプリング周波数
- 量子化値や予測処理
- 音声を合成するフィルターなどの処理
TRSF1602AのAuto-FIFO機能についても、今回の観測だけでは使用の有無を確定できていません。
現在の到達点と次の課題
今回できたのは、フラッシュの内容を読み出し、286個の圧縮データへ分割し、それぞれをキャラクターとボタン操作に対応付けるところまでです。
「どの操作で、ダンプのどの部分が読まれるか」は分かりました。一方、その圧縮データから正しいPCM波形を生成するデコーダーは、まだ完成していません。
今後は、対応が分かった音声を使った追加の比較や、予備フラッシュに一部を変更したデータを書き込む実験などが候補になります。後者はまだ実施していませんが、変更したビットと出力の変化を対応付けられれば、受動的な観測だけでは判断できなかった構造に迫れるかもしれません。
当初の目標だった「音声ファイルとして取り出す」ところまでは、もう少しかかりそうです。それでも、位置表の286件が製品の全音声とどう対応しているかを実測で埋められたことで、次の解析に使える土台は整いました。







