TOP > プログラミング関係解説&調査 > サウンドについて > サウンドの演奏 (1) BGM演奏

サウンドについて > サウンドの演奏 (1) BGM演奏

当ページの内容は、ある程度のプログラミングの知識を必要とする。
まず、プログラミング関係解説&調査をひととおり読んでいただきたい。

このページでは、サウンドの演奏について説明していく。
先にサウンドについてをお読みいただきたい。

サウンドの演奏手順は、BGMと効果音とで異なるが、大まかな仕組みは、

「ARAMに送信されたサンプリングデータとシーケンスデータに対し、CPU側から演奏命令を出してSPC700が演奏する」

と、なる。
CPU側から出す演奏などの命令を「サウンドドライバファンクション」という。
シーケンスデータのコマンドや、サウンドドライバファンクションは、ゲーム毎にサウンドプログラマーが決めているが、「ライブ・ア・ライブ」と同時期に発売されたスクウェアのRPGには共通の仕様が見られる。
「ライブ・ア・ライブ」のサウンド・プログラムを手掛けた赤尾実氏(赤尾実 - Wikipedia)は、当時のスクウェアのゲームの大半のサウンド・プログラムを担当していており、先達による研究により判明している、「ファイナルファンタジー」4~6(ファイナルファンタジーは以降「FF」と省略する)、「クロノ・トリガー」、「ロマンシング・サガ」1~3(ロマンシング・サガは以降「ロマサガ」と省略する)のサウンド関連のデータを参考にさせていただいた。

シーケンスデータについては、シーケンスデータ調査のページで詳細に説明しているので参照していただきたい。
「ライブ・ア・ライブ」のシーケンスコマンドは、「ロマサガ2」とほぼ共通の仕様と思われる。

一方、サウンドドライバファンクションについては、似通った部分と、本作独自の部分とがあるようなので、実際の例と共に紹介していく。
一覧はサウンドドライバファンクションにあるので参照のこと。

このページでは、BGMの演奏について説明する。
効果音は別ページで紹介している。効果音の演奏を参照。

サウンドの演奏

大雑把な手順は以下のようになっている。
基本として、CPUからAPU(SPC700)へデータを送信する場合、互いのI/Oレジスタアドレスは、

$00:2140~$00:2143→ARAM$00F4~$00F7

と、それぞれ4バイトの領域を使っている。
$00:2140~$00:2143へコピーするデータとして$00:1D00~$00:1D03が確保されており、ほとんどの場合で、

$00:1D00~$00:1D03→$00:2140~$00:2143

という処理をしている。
サウンドドライバファンクションでSPC700に命令を送る際、だいたいの場合において、

アドレス内容
$00:1D00コマンド(1バイト)
$00:1D01引数1(1バイト)
$00:1D02引数2(1バイト)
$00:1D03引数3(1バイト)

と値をセットして、$00:2140~$00:2143に送信する。
引数(パラメータ)の有無はコマンドにより変わる。
送信時に使うサブルーチンが$C3/0004~$C3/017Fである(状況により例外あり)。

$00:1D00~$00:1D03→$00:2140~$00:2143

と書き込んでから、$00:2140が$00:1D00と同値を返してくるまでループ処理で待機し、同値を返してきたら$00:2140に$00を書き込んでCPUからの命令終了、という手順になる。
APU側はサウンド演奏も行っており、CPUから値の送信があるかどうかは1フレーム毎に確認している。
CPUからの送信を確認したら、「CPU側の値を受け取った」と、$00F4→$00:2140と値を返しているのである。

BGMの演奏

BGMを演奏する場合、サウンドドライバファンクションのコマンドは3種類ある。
更に、演奏前に、「フェードインしながら演奏開始する」「ボリュームを通常より下げて演奏する」「演奏速度やピッチを変更する」「一部チャネルの演奏はミュートにする」……といった設定もサウンドドライバファンクションのコマンドで可能になっている。

何にしても、まずは演奏するBGMのBGMIDが必要である。
戦闘に突入したら戦闘BGMの演奏を開始するが、シナリオ毎の通常戦闘BGMのIDはどう呼び出しているのか? ボス戦などはどう処理しているのか?
マップによりBGMを切り替える時、シナリオ進行によりBGMを変更する時などなど、BGMIDをどう計算しているのかだけでも話が長くなるため、それらは別ページで説明することにした。
BGMIDの呼び出しで紹介しているので参照のこと。

以降、「コマンド$nn 引数1xx 引数2yy」という形式で表記する。

BGM演奏開始コマンド

BGM演奏開始コマンドは3種類ある。

コマンド引数1xx引数2yy内容
$10 xx yyBGMID $00~$4D音量 $00~$FFBGM演奏開始(演奏中断設定込)
$11 xx yyBGMID $00~$4D音量 $00~$FFBGM演奏開始(バージョン違い)
$14 xx yyBGMID $00~$4D音量 $00~$FFBGM演奏開始(演奏中断割り込み用)

このコマンドを送信した後に、該当のBGMIDのサンプリングデータとシーケンスデータをARAMに送信(後のサンプリングデータの処理及び、シーケンスデータの処理を参照)。
送信し終わると演奏が開始になる($00:2140に転送はされないが、送信終了のタイミングで$00:1D00に$00が入る)。

コマンド$11は特殊で、以下のBGMIDを指定すると、バージョン違いの曲を演奏できる。
他のBGMIDもバージョン違いがあるかもしれないが、筆者が確認できたのは以下3曲である。
なお、バージョン違いの曲がない場合、コマンド$11はコマンド$10と同じ役割になるようだ。

BGMID曲名内容
$04WANDERER前奏なしバージョン
$08UNSEEN SYNDROMEチャネル2と3のみのバージョン(SF編オープニング)
$19届かぬ翼回想などで流れるスローバージョン(リメイクにおける「届かぬ翼 (回想)」)

コマンド$10と$14は、いわゆるレジューム演奏に使う。
例えばフィールドで雑魚戦に突入した時、フィールド曲から戦闘曲に切り替えになり、戦闘が終わると再びフィールド曲が演奏されるが、戦闘終了後、戦闘前に流れていたフィールド曲の中断箇所から演奏が開始される。毎回、フィールド曲の頭から演奏開始にはならない。
演奏を中断しても、次の演奏時に続きから演奏したい曲はコマンド$10で演奏開始し、割り込んで演奏する曲はコマンド$14で演奏するようである。
他にも、フィールドでアイテムを獲得する時や、味方キャラが加わった時に流れる、効果音のようなBGM(高原や功夫編キャラのボイスなど)でもレジューム機能でBGMを演奏している。
一方、近未来編のバーや、最終編の各地のダンジョンなどは、コマンド$10でBGMを流すため、フィールドに戻った時にフィールド曲がレジュームで再開されず、最初から演奏開始になる。

$C3/0004からのサブルーチンで演奏を指示する場合、途中で、

  • 今回演奏するBGMIDが、[$00:1D05](ひとつ前に演奏していたBGMID)と一致しない
  • BGMIDが[$C3:3FC8]($4E)以上ではない(BGMIDは$00~$4Dにしか曲が登録されていない)

という判定をしている。他にも各種分岐があるが説明は省略する。
大まかには以下の手順で処理される。

$C3/0004 JMP $0131  [$C3:0131]   ;[$C3:0131]へジャンプ(レジスタをスタックに積まない)
$C3/0131 PHB                     ;DBレジスタをスタックにプッシュ
$C3/0132 PHD                     ;Dレジスタをスタックへプッシュ
$C3/0133 PHP                     ;ステータスレジスタをスタックへプッシュ
$C3/0134 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C3/0136 REP #$10                ;X/Yレジスタを16bit幅に変更、Xフラグをクリア
$C3/0138 PHA                     ;Aレジスタをスタックにプッシュ
$C3/0139 PHX                     ;Xレジスタをスタックにプッシュ
$C3/013A PHY                     ;Yレジスタをスタックへプッシュ
$C3/013B SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/013D LDA #$00                ;Aに$00をロード
$C3/013F PHA                     ;Aレジスタをスタックにプッシュ
$C3/0140 PLB                     ;DBレジスタにスタックからプル
$C3/0141 LDX #$1D00              ;Xに$1D00をロード
$C3/0144 PHX                     ;Xレジスタをスタックにプッシュ
$C3/0145 PLD                     ;Dレジスタにスタックからプル
$C3/0146 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/0148 LDA $00    [$00:1D00]   ;Aに[$00:1D00]をロード(10~14)
$C3/014A BEQ $25    [$0171]      ;ゼロフラグが立っているとき[$0171]分岐
$C3/014C BMI $19    [$0167]      ;ネガティブフラグが立っているとき[$0167]分岐
$C3/014E CMP #$10                ;Aと$10を減算比較(ステータスレジスタ変更のみ)
$C3/0150 BCC $1F    [$0171]      ;キャリーフラグが立っていないとき[$0171]分岐
$C3/0152 CMP #$18                ;Aと$18を減算比較(ステータスレジスタ変更のみ)
$C3/0154 BCS $0D    [$0163]      ;キャリーフラグが立っているとき[$0163]分岐 効果音演奏
$C3/0156 AND #$0F                ;Aと$0Fで論理積
$C3/0158 ASL A                   ;Aを算術左シフト *2
$C3/0159 XBA                     ;Aレジスタの上位バイトと下位バイトを交換
$C3/015A LDA #$00                ;Aに$00をロード
$C3/015C PHA                     ;Aレジスタをスタックにプッシュ
$C3/015D XBA                     ;Aレジスタの上位バイトと下位バイトを交換
$C3/015E PHA                     ;Aレジスタをスタックにプッシュ
$C3/015F PLX                     ;Xレジスタにスタックからプル
$C3/0160 JMP ($0734,x)[$C3:0180] ;[$C3:0180]へジャンプ(レジスタをスタックに積まない)
$C3/0180 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/0182 LDA $01    [$00:1D01]   ;Aに[$00:1D01]をロード BGMID
$C3/0184 CMP $05    [$00:1D05]   ;Aと[$00:1D05]を減算比較(ステータスレジスタ変更のみ)
$C3/0186 BEQ $E9    [$0171]      ;ゼロフラグが立っているとき[$0171]分岐(処理抜ける)
;ゼロフラグOFF ひとつ前に演奏していたBGMIDと今回演奏するBGMIDは一致しない
$C3/0188 CMP $C33FC8[$C3:3FC8]   ;Aと[$C3:3FC8]($4E)を減算比較(ステータスレジスタ変更のみ)
$C3/018C BCS $E3    [$0171]      ;キャリーフラグが立っているとき[$0171]分岐(処理抜ける)
;キャリーフラグON BGMIDが$4E以上(存在しない)
$C3/018E JSR $062F  [$C3:062F]   ;[$C3:062F]へジャンプ

$C3/062F PHP                     ;ステータスレジスタをスタックへプッシュ
$C3/0630 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/0632 LDA $00    [$00:1D00]   ;Aに[$00:1D00]をロード
$C3/0634 CMP #$14                ;Aと$14を減算比較(ステータスレジスタ変更のみ)
$C3/0636 BCS $10    [$0648]      ;キャリーフラグが立っているとき[$0648]分岐
;キャリーフラグOFF [$00:1D00]は10か11
$C3/0638 LDX #$0000              ;Xに$0000をロード
$C3/063B LDA $C30733,x[$C3:0733] ;Aに[$C3:0733,x]をロード
$C3/063F BMI $0D    [$064E]      ;ネガティブフラグが立っているとき[$064E]分岐
;キャリーフラグON [$00:1D00]は14
$C3/0641 CMP $01    [$00:1D01]   ;Aと[$00:1D01](BGMID)を減算比較(ステータスレジスタ変更のみ)
$C3/0643 BEQ $03    [$0648]      ;ゼロフラグが立っているとき[$0648]分岐
$C3/0645 INX                     ;Xをインクリメント +1
$C3/0646 BRA $F3    [$063B]      ;フラグにかかわりなく常に分岐[$063B]
$C3/0648 LDA #$04                ;Aに$04をロード
$C3/064A ORA $00    [$00:1D00]   ;Aと[$00:1D00]で論理和
$C3/064C STA $00    [$00:1D00]   ;Aを[$00:1D00]に書き込み
;処理合流
$C3/064E PLP                     ;Pレジスタにスタックからプル
$C3/064F RTS                     ;サブルーチン戻り

$C3/0191 LDA $F3    [$00:1DF3]   ;Aに[$00:1DF4][$00:1DF3]をロード
$C3/0193 BEQ $03    [$0198]      ;ゼロフラグが立っているとき[$0198]分岐
$C3/0198 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C3/019A LDA $01    [$00:1D01]   ;Aに[$00:1D02][$00:1D01]をロード
$C3/019C AND #$00FF              ;Aと$00FFで論理積
$C3/019F TAX                     ;Aの値をXレジスタに転送
;(中略)
$C3/01BF JSR $060E  [$C3:060E]   ;[$C3:060E]へジャンプ
;
;(中略 サンプリングデータとシーケンスデータをARAM送信)
;
$C3/0171 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/0173 STZ $00    [$00:1D00]   ;[$00:1D00]に$00を書き込み ARAM送信終了、演奏開始
$C3/0175 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C3/0177 REP #$10                ;X/Yレジスタを16bit幅に変更、Xフラグをクリア
$C3/0179 PLY                     ;Yレジスタにスタックからプル
$C3/017A PLX                     ;Xレジスタにスタックからプル
$C3/017B PLA                     ;Aレジスタにスタックからプル
$C3/017C PLP                     ;Pレジスタにスタックからプル
$C3/017D PLD                     ;Dレジスタにスタックからプル
$C3/017E PLB                     ;DBレジスタにスタックからプル
$C3/017F RTL                     ;サブルーチン戻り

BGM演奏各種指示

BGM演奏時は、ただ演奏するだけではなく、各種指示ができる。
代表的なものを紹介する。

$81 xx yy BGMフェード用音量倍率 設定/変化
引数
xx:音量変化時間 $00~$FF($00で音量変化時間なし)
yy:音量 $00~$FF($00で無音、$FFがデフォルト音量)
内容
BGMの音量を、音量変化時間yyかけて音量xxに設定する。

BGM演奏のフェードイン・フェードアウトに使う。
ゲーム内のほとんどの演奏は、演奏前にコマンド$81によるフェードインを設定、演奏終了時にフェードアウトを使っている。
演奏停止用のコマンドも別途あるが(コマンド$F0や$F1)、フェードアウトで音量$00まで落とすことで演奏停止としていることも多い。

$86 xx yy BGM演奏速度倍率 設定/変化
引数
xx:処理時間 $00~$FF
yy:演奏速度(倍率) $00~$FF(符号付き8ビット整数, 通常$00)
内容
処理時間xxかけて演奏速度をyyに変更する。演奏速度が負なら速度低下、正なら速度上昇。

本作のBGMの中に、元の楽曲の演奏速度を下げることで別BGMとしている曲がある。
BGMID$0B「PSYCHOで夜露死苦!!」(バー)や、BGMID$15「いいお天気でしょっ!」(夜)などが該当し、これらの曲の場合演奏開始時から演奏速度を下げるので、処理時間は0、演奏速度に負の値をセットしている。
本作において演奏中に演奏速度を下げていく(処理時間が0以上)という曲はおそらくない。

$89 xx yy BGMピッチ倍率 設定/変化
引数
xx:処理時間 $00~$FF
yy:ピッチ(倍率) $00~$FF(符号付き8ビット整数, 通常$00)
内容
処理時間xxかけてピッチをyyに変更する。ピッチが負ならピッチ低下、正ならピッチ上昇。

BGM演奏速度倍率同様に、演奏前に元の楽曲のピッチを下げて別BGMとしている曲がある。
BGMID$15「いいお天気でしょっ!」(夜)や、BGMID$0C「猛者達…」(敗北時)が該当。
こちらについても、演奏中にピッチを下げていく(処理時間が0以上)という曲はおそらくない。

$F5 xx BGMミュート設定 (チャネル選択)

引数
xx:ミュートするチャネル $00~$FF
内容
Bit0~7がチャネル0~7に対応しており、1が立っているチャネルはミュート(無音)処理される。

こちらも、演奏前に元の楽曲の一部チャネルをミュートすることにより別BGMにするパターン。
音量を0にするだけなので演奏自体は全チャネル行っている。
BGMID$35「CRY・A・LIVE」(ハープのみ)の場合、xxが$F7 = $1111 0111なので、0が立っているBit3、つまりチャネル3以外はミュート処理になる。
チャネル3がハープを担当しているので、ハープのみの演奏になる。

$FB ループ停止してコーダ部へ

内容
指定後、ループ処理せずコーダ部へ移行して演奏終了する。

コマンド$FBは特殊なパターンで、おそらくだが、BGMID$18「GO!GO!ブリキ大王!!」専用と思われる。
「GO!GO!ブリキ大王!!」は、ブリキ大王操作時や、LISTENING ROOMで聞く時は、

イントロ→メイン部分→イントロ→メイン部分→……

という感じでループ演奏される。
だが、近未来編のオープニングだと、

イントロ→メイン部分→イントロ+コーダ部

のような感じでループしない。
この、ループさせないための命令がコマンド$FBである。
演奏開始は通常通りだが、メイン部分の演奏中にコマンド$FBを送信すると、次のイントロ演奏でコーダ部に入り演奏終了する。
演奏開始時に同時にコマンド$FBを指示すると、最初のイントロでコーダ部に入って演奏が終わってしまうので、メイン部分の演奏中に送る必要がある。
実際のゲームプレイでは、「あつい心が呼びさます」の字幕が出る港のシーンから、全体マップに切り替わるタイミングでコマンド$FBが送信されている。

$C0/274B LDA $8E00,y[$7F:97AA]   ;Aに[$7F:97AA](0B)をロード
$C0/274E REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C0/2750 AND #$00FF              ;Aと$00FFで論理積
$C0/2753 STA $32    [$00:0032]   ;Aを[$00:0032]に書き込み
$C0/2755 ASL A                   ;Aを算術左シフト *2
$C0/2756 TAX                     ;Aの値をXレジスタに転送 A:0016
$C0/2757 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C0/2759 INY                     ;Yをインクリメント +1
$C0/275A JMP ($4523,x)[$C0:282C] ;[$C0:282C]へジャンプ(レジスタをスタックに積まない)
$C0/282C JSR $12A6  [$C0:12A6]   ;[$C0:12A6]へジャンプ

$C0/12A6 LDA #$FB                ;Aに$FBをロード コマンド$FB
$C0/12A8 BRA $1E    [$12C8]      ;フラグにかかわりなく常に分岐[$12C8]
$C0/12C8 LDX #$1D00              ;Xに$1D00をロード
$C0/12CB STA $00,x  [$00:1D00]   ;Aを[$00:1D00]に書き込み
$C0/12CD BRA $0D    [$12DC]      ;フラグにかかわりなく常に分岐[$12DC]
$C0/12DC LDA $70    [$00:0070]   ;Aに[$00:0070]をロード
$C0/12DE CMP #$01                ;Aと$01を減算比較(ステータスレジスタ変更のみ)
$C0/12E0 BEQ $04    [$12E6]      ;ゼロフラグが立っているとき[$12E6]分岐
$C0/12E2 JSL $C30004[$C3:0004]   ;[$C3:0004]へジャンプ

$C3/0004 JMP $0131  [$C3:0131]   ;[$C3:0131]へジャンプ(レジスタをスタックに積まない)
;(中略)
$C3/017F RTL                     ;サブルーチン戻り

$C0/12E6 RTS                     ;サブルーチン戻り

$C0/282F BRL $F36F  [$1BA1]      ;フラグにかかわりなく常に分岐[$1BA1]

BGM演奏例

近未来編でザコ戦に突入する時、戦闘突入時の効果音の後、戦闘BGMであるBGMID$0B「PSYCHOで夜露死苦!!」を演奏する場合、コマンド送信は以下のようになる(実際には一回送信する度に$00:2140に00を送信しているが省略)。
筆者にはわからないコマンドも含まれているが、とりあえずわかる部分を説明していく。

内容$00:1DXX
XX00010203
BGM演奏速度倍率 設定/変化$86$00$00$00
BGMピッチ倍率 設定/変化$89$00$00$00
BGMミュート設定$F5$00$00$00
?(ループ設定?)$FA$00$00$00
BGM演奏開始(演奏中断割り込み用)$14$0B$FF$00

戦闘で演奏する「PSYCHOで夜露死苦!!」は、演奏速度、ピッチ、ミュート設定など、すべて$00である。
つまりシーケンスデータのまま演奏する。

近未来編のバーに全体マップから入った時、BGMID$0B「PSYCHOで夜露死苦!!」(バー)に演奏が切り替わる処理は以下のようになる。

回数$00:1DXX
XX00010203
BGMフェード用音量倍率 設定/変化$81$10$00$00
BGMミュート設定$F5$85$00$00
BGM演奏速度倍率 設定/変化$86$00$8C$00
BGM演奏開始(演奏中断設定込)$10$0B$FF$00

バーに入ると、まずコマンド$81で、フィールド曲をフェードアウトで停止する。
その後に、コマンド$F5のBGMミュート設定を$85に設定することでチャネル0, 2, 7をミュート処理、コマンド$86でBGM演奏速度倍率を$8Cに下げてから、「PSYCHOで夜露死苦!!」をコマンド$10で演奏する。
これにより、戦闘での演奏時とは異なり、スローテンポでキーも下がった「PSYCHOで夜露死苦!!」が演奏されることになる。
ミュート設定もあるので、メインメロディがない状態で演奏されることになる。

なお、フィールドにおけるBGMの演奏時、演奏設定は$00:0A60~$00:0A6Cに同時に書き込まれ、セーブデータにも記録される。
セーブデータをロードした時は以下の値からBGMの演奏を開始することになる。
ただし$00:0A62~$00:0A63は効果音設定であり、セーブデータをロードした時はどちらも$00が入っているようである。

アドレス内容
$00:0A60演奏中のBGMID
$00:0A61コマンド$81で設定されるBGMの音量(デフォルト値は$FF)
$00:0A62コマンド$82で設定される効果音の音量(デフォルト値は$FF)
$00:0A63コマンド$18で設定される効果音のPAN(音の定位)の値 $00 (左)~$80 (中央・モノラル)~$FF (右)
$00:0A64コマンド$86で設定されるBGMの演奏速度の値 $00~$FF(通常$00)
$00:0A65コマンド$89で設定されるBGMピッチの値 $00~$FF(通常$00)
$00:0A66コマンド$F5で設定されるBGMミュート設定 Bit0~7がチャネル0~7に対応しており、1が立っているチャネルはミュート(無音)処理
$00:0A67コマンド$F8で設定される値(内容不明)
$00:0A68演奏中のBGMID
$00:0A6Bコマンド$8Cで設定される値(内容不明)
$00:0A6Cコマンド$8Fで設定される値(内容不明)

サンプリングデータの処理

効果音用のサンプリングデータはゲーム開始の時点で読み込まれている。
効果音専用ではなくBGMにも使われていることがあり、例えば「CAPTAIN SQUARE」は効果音用の正弦波などが使われているため、「CAPTAIN SQUARE」の曲がゲーム内で流れる時、シーケンスデータの転送しかしていない。
ここではそれ以外のサンプリングデータについて記す。

演奏曲のサンプリングデータのIDは$00:1E00~$00:1E1Fから2バイトずつの値で入る。
更に、ARAMに既にそのサンプリングデータが存在している場合は、$00:1E00~$00:1E1Fからその値だけ抜いた分、つまり、これから演奏する曲に不足しているサンプリングデータIDだけ、$00:1E20~$00:1E3Fに入る。
これにより、実際にARAMへ転送する時は、$00:1E20~$00:1E3Fから計算したアドレスを使うことになる、という仕組み。
以上から、1曲あたりに使えるサンプリングデータの種類は最大16種ということになる(これはあくまでも本作の仕組みで、他ゲームでは異なるだろう)。
ただし本作で実際に使用している曲の設定を見ると、サンプリングデータの種類は最大でも13種である。
実際の演奏では最大16種のサンプリングデータから8種を選ぶ、という話は上でもした通り。

では、$00:1E00~$00:1E1Fに入る値はどういうサブルーチンで処理しているのか。
$00:1D01にBGMIDが入った後の処理になる。

$C3/01C5 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C3/01C7 LDX #$0020              ;Xに$0020をロード
;ループ処理
$C3/01CA STZ $1E1E,x[$00:1E3E]   ;[$00:1E3F][$00:1E3E]~[$00:1E2D][$00:1E1F]に$00を書き込み
$C3/01CD DEX                     ;Xをデクリメント -1
$C3/01CE BNE $FA    [$01CA]      ;ゼロフラグが立っていないとき[$01CA]分岐
;ループ処理ここまで
$C3/01D0 LDA #$1E00              ;Aに$1E00をロード
$C3/01D3 STA $10    [$00:1D10]   ;Aを[$00:1D11][$00:1D10]に書き込み
$C3/01D5 LDA #$1E20              ;Aに$1E20をロード
$C3/01D8 STA $12    [$00:1D12]   ;Aを[$00:1D13][$00:1D12]に書き込み
$C3/01DA LDA $00    [$00:1D00]   ;Aに[$00:1D01][$00:1D00]をロード
$C3/01DC AND #$FF00              ;Aと$FF00で論理積
$C3/01DF LSR A                   ;Aを論理右シフト (/2)
$C3/01E0 LSR A                   ;Aを論理右シフト (/2)
$C3/01E1 LSR A                   ;Aを論理右シフト (/2)
$C3/01E2 TAX                     ;Aの値をXレジスタに転送
$C3/01E3 ADC #$0020              ;A + $0020
$C3/01E6 STA $1C    [$00:1D1C]   ;Aを[$00:1D1C]に書き込み
;ループ処理
$C3/01E8 LDA $C343A4,x[$C3:4504] ;Aに[$C343A4,x+1][$C343A4,x]をロード サンプリングデータID
$C3/01EC STA ($10)  [$00:1E00]   ;Aを[$00:1E00 + n+1][$00:1E00 + n]に書き込み
$C3/01EE INC $10    [$00:1D10]   ;[$00:1D11][$00:1D10]をインクリメント +1
$C3/01F0 INC $10    [$00:1D10]   ;[$00:1D11][$00:1D10]をインクリメント +1
$C3/01F2 LDY #$0040              ;Yに$0040をロード
;ループ処理
$C3/01F5 CMP $1D1E,y[$00:1D5E]   ;Aと[$00:1D5F-2y][$00:1D5E-2y]を減算比較(ステータスレジスタ変更のみ)
$C3/01F8 BEQ $0A    [$0204]      ;ゼロフラグが立っているとき[$0204]分岐
$C3/01FA DEY                     ;Yをデクリメント -1
$C3/01FB DEY                     ;Yをデクリメント -1
$C3/01FC BNE $F7    [$01F5]      ;ゼロフラグが立っていないとき[$01F5]分岐
;ループ処理ここまで
;$C3/01F8の[$0204]分岐
$C3/0204 INX                     ;Xをインクリメント +1
$C3/0205 INX                     ;Xをインクリメント +1
$C3/0206 CPX $1C    [$00:1D1C]   ;Xと[$00:1D1D][$00:1D1C]を減算比較(ステータスレジスタ変更のみ)
$C3/0208 BNE $DE    [$01E8]      ;ゼロフラグが立っていないとき[$01E8]分岐
;ループ処理ここまで
(中略)
$C3/02E4 JSR $06BD  [$C3:06BD]   ;[$C3:06BD]へジャンプ

$C3/01DA~$C3/01E2で、

([$00:1D01][$00:1D00] & $FF00) /$8

を計算してXレジスタに転送している。
「[$00:1D01][$00:1D00] & $FF00」は実質、[$00:1D01] * $100と同じことであり、[$00:1D01]にはBGMのIDが入るので、

([$00:1D01][$00:1D00] & $FF00) /$8
= BGMID * $100 / $8
= BGMID * $20

である。
$C3/01E8から$C3/0208までが外側のループ処理で、ここで呼び出しているのが[$C343A4,x+1][$C343A4,x]なのだが、これが演奏曲のサンプリングデータIDの1番目の値である。
この値が[$00:1E00 + n+1][$00:1E00 + n](nはループ回数)に書き込まれるから、[$00:1E00]から順に2バイトずつ書き込まれていく。
つまり、

$C343A4 + BGMID * $20

でアドレスが計算できる。
更に、ループ回数は$C3/01E3~$C3/01E6の処理とループ処理後半からして、$10回=16回であり、16種類のサンプリングデータIDを$00:1E00~$00:1E1Fへ20バイト分書き込むということがわかる。

先に述べたが、実際には、ARAMに既に該当のサンプリングデータIDのデータがある場合、後でサンプリングデータのARAMへの転送はスキップされる。
処理は省くが、$00:1D20~$00:1D5Fの$40バイト分の領域に、現在ARAMに入っているサンプリングデータ最大32種類が2バイトデータで記録されている。
$00:1D20~$00:1D5Fに被りがないかどうかは、内側のループ処理$C3/01F5~$C3/01FCでチェックしている。
[$00:1D5F][$00:1D5E]~[$00:1D21][$00:1D20]まで2バイトずつ$40バイト分のデータが、今回ロードしたサンプリングデータIDと一致しているかどうかのチェックであり、一致していた場合はARAMへの転送をスキップする。
つまり、$00:1D20~$00:1D5Fは、現在ARAMに入っているサンプリングデータIDを記録している領域なのである。
2バイトずつ$40バイト分の領域があるということは、ARAMにおいておけるサンプリングデータは最大$20種類=32種類だということがわかる。

さて、サンプリングデータ開始アドレスの計算方法がわかったから、「$C343A4 + BGMID * $20」をBGMID$01~$4Dの分計算して、実際の値を見てみよう。
ちなみに後々の計算の都合で、音色1種あたり2バイトの値になるものの上1バイトは必ず$00である。
このため下表では、上1バイトの$00は省略し、下1バイトの値だけ掲載した。

BGMID曲名サンプリングデータ
開始アドレス
サンプリングデータID
$0$1$2$3$4$5$6$7$8$9$A$B$C$D$E$F
$01魔王への叙曲$C3:43C4~$12$13$20$07$0B$23$0E$0C$19$1F$13$48$00$00$00$00
$02凛然たる戦い$C3:43E4~$35$03$34$12$17$1F$09$06$05$00$00$00$00$00$00$00
$03忍音$C3:4404~$35$34$21$0B$1E$22$0D$01$1D$02$00$00$07$00$00$00
$04WANDERER$C3:4424~$3D$01$19$08$04$1C$1B$1A$0A$07$16$00$00$00$00$00
$05殺陣!$C3:4444~$0F$01$35$14$10$11$22$18$15$23$00$00$00$00$00$00
$06THE WILDS$C3:4464~$3D$01$19$04$12$08$00$00$00$00$00$00$00$00$00$00
$07UNDER THE FAKE$C3:4484~$3D$35$34$08$04$1F$3B$33$1B$15$38$00$00$00$00$00
$08UNSEEN SYNDROME$C3:44A4~$0A$01$15$25$39$36$3E$00$00$00$00$00$00$00$00$00
$09NATIVE LIFE$C3:44C4~$37$24$1E$0A$21$1C$1A$31$1F$32$3C$0B$00$00$00$00
$0AWAIT FOR TRUTH$C3:44E4~$2B$01$35$34$2C$30$18$15$23$21$00$00$00$00$00$00
$0BPSYCHOで夜露死苦!!$C3:4504~$2B$2D$35$34$21$28$29$2A$18$15$23$00$00$00$00$00
$0C猛者達…$C3:4524~$35$34$06$05$28$08$09$18$15$00$00$00$00$00$00$00
$0D鳥児在天空飛翔 魚児在河里游泳$C3:4544~$2E$12$27$3A$20$39$3B$48$48$00$00$00$00$00$00$00
$0E在中国的戦闘$C3:4564~$0B$01$35$34$21$12$3A$39$36$30$00$00$00$00$00$00
$0F効果音(幕末編・天井裏カラクリ音)$C3:4584~$00$00$00$00$00$00$00$00$00$00$00$00$07$00$00$00
$10KNOCK YOU DOWN!$C3:45A4~$09$2D$35$34$21$28$29$08$45$15$18$00$00$00$00$00
$11効果音(馬が走る音)$C3:45C4~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$12効果音(SF編・宇宙船内)$C3:45E4~$0A$01$15$25$39$36$3E$00$00$00$00$00$00$00$00$00
$13効果音(近未来編・港)$C3:4604~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$14老拳師下深山$C3:4624~$0E$01$19$26$17$0A$3B$2E$00$00$00$00$00$00$00$00
$15いいお天気でしょっ!$C3:4644~$0B$01$35$34$2A$1C$1A$1F$23$44$00$00$00$00$00$00
$16KISS OF JEALOUSY$C3:4664~$2D$35$34$21$1C$09$1B$49$36$1A$4B$00$00$00$00$00
$17密命$C3:4684~$0F$01$1E$35$34$11$10$0A$22$1D$17$00$00$00$00$00
$18GO!GO!ブリキ大王!!$C3:46A4~$49$2D$35$34$21$28$09$20$12$15$00$00$00$00$00$00
$19届かぬ翼$C3:46C4~$12$0C$26$0E$0B$46$3B$1F$48$00$00$00$00$00$00$00
$1A魔王山を往く$C3:46E4~$12$0A$2F$20$0C$48$00$00$00$00$00$00$00$00$00$00
$1B魔王オディオ$C3:4704~$2F$0A$07$00$00$00$3E$43$00$00$00$00$00$00$00$00
$1CPURE ODIO$C3:4724~$35$14$1F$09$0A$01$28$29$2F$26$07$30$42$00$00$00
$1D効果音(アキラ レベルアップ音)$C3:4744~$3C$33$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$1E効果音(木魚のポクポク音)$C3:4764~$33$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$1F効果音(風の吹く音)$C3:4784~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$20効果音(キューブの機械音)$C3:47A4~$3E$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$21効果音(オルステッド レベルアップ音)$C3:47C4~$3F$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$22効果音(おぼろ丸 レベルアップ音)$C3:47E4~$40$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$23効果音(サモ・ユン レベルアップ音・アチョーボイス)$C3:4804~$41$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$24効果音(レイ レベルアップ音・ボイス)$C3:4824~$42$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$25SELECT・A・LIVE$C3:4844~$0C$12$0A$26$23$07$00$00$00$00$00$00$00$00$00$00
$26効果音(ポゴ レベルアップ音・ボイス)$C3:4864~$43$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$27効果音(ゴリのボイス/馬のいななき 兼用)$C3:4884~$44$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$28効果音(高原日勝 レベルアップ音・ボイス)$C3:48A4~$45$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$29効果音(サンダウン レベルアップ音・銃声)$C3:48C4~$47$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$2A効果音(近未来編・木琴)$C3:48E4~$39$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$2BMEGALOMANIA$C3:4904~$35$14$1F$34$09$01$28$29$2F$00$00$00$00$00$00$00
$2C効果音(強風の吹く音)$C3:4924~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$2D効果音(SF編/近未来編・パソコン効果音)$C3:4944~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$2E効果音(近未来編・筑波研究所最奥)$C3:4964~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$2F効果音(功夫編 銅鑼)$C3:4984~$3A$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$30効果音(西部編 鐘)$C3:49A4~$07$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$31効果音(幕末編 アイテム入手時)$C3:49C4~$0F$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$32効果音(原始編 ウホウホ)$C3:49E4~$43$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$33最強-VICTORY ROAD-$C3:4A04~$28$06$05$35$34$0A$09$3C$0B$07$00$00$00$00$00$00
$34LIVE・A・LIVE$C3:4A24~$12$01$09$46$0B$20$19$3C$07$23$00$00$00$00$00$00
$35CRY・A・LIVE$C3:4A44~$2E$0E$12$0C$0A$26$3E$00$00$00$00$00$00$00$00$00
$36WARM・A・LIVE$C3:4A64~$12$0C$07$46$0B$0E$48$00$00$00$00$00$00$00$00$00
$37絶望の都$C3:4A84~$12$0A$48$2F$23$0B$46$0C$20$0E$07$00$00$00$00$00
$38Sancho・de・Los・Panchoz$C3:4AA4~$08$04$1B$00$00$00$00$00$00$00$00$00$00$00$00$00
$39効果音(マラカス)$C3:4AC4~$1B$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$3A効果音(各シナリオ開始時の低い音)$C3:4AE4~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$3B原始編・宴(リメイク版の「生贄の宴」)$C3:4B04~$43$1E$1C$1A$3B$1F$21$00$00$00$00$00$00$00$00$00
$3CSilent Labyrinth$C3:4B24~$0A$12$26$0C$17$35$23$30$00$00$00$00$00$00$00$00
$3DARMAGEDDON$C3:4B44~$2F$0A$07$00$00$00$00$00$00$00$00$00$00$00$00$00
$3ECAPTAIN SQUARE$C3:4B64~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$3F星屑のキャプテン$C3:4B84~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$40効果音(近未来編・オルガン むすんでひらいて)$C3:4BA4~$2C$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$41効果音(近未来編・オルガン 猫ふんじゃった)$C3:4BC4~$2C$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$42効果音(近未来編・オルガン トッカータとフーガ)$C3:4BE4~$2C$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$43効果音(近未来編・オルガン チョコボのテーマ)$C3:4C04~$2C$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$44Live over Again$C3:4C24~$2E$26$12$0C$0A$0B$00$00$00$00$00$00$00$00$00$00
$45Live for Live$C3:4C44~$35$34$21$01$12$0A$09$04$08$28$0B$0E$00$00$00$00
$46効果音(崩壊)$C3:4C64~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$47効果音(SF編・警告音)$C3:4C84~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$48効果音(功夫編・夜 虫の音)$C3:4CA4~$31$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$49CAPTAIN SQUARE$C3:4CC4~$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$4A効果音(ゲーム開始時「SQUARE SOFT」ボイス)$C3:4CE4~$4A$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00
$4BILLUSION…$C3:4D04~$2F$12$24$09$0A$35$19$1F$15$18$20$26$03$00$00$00
$4CVersus!$C3:4D24~$35$34$21$23$09$2A$06$05$00$00$00$00$00$00$00$00
$4D原始編・宴 ボイスのみ$C3:4D44~$43$00$00$00$00$00$00$00$00$00$00$00$00$00$00$00

先に記したが、「CAPTAIN SQUARE」はサンプリングデータの転送はなくシーケンスデータのみ転送される。
上表を見ると、ID$3Eの「CAPTAIN SQUARE」のサンプリングデータはすべて$00で埋まっている。
つまりBGM用に転送するサンプリングデータはないということである。
他にもID$1F「効果音(風の吹く音)」などもサンプリングデータなしで、効果音用のサンプリングデータだけで鳴らしているのだということが推測できる。
無音である$00以外の数値を見ると、サンプリングデータIDは$01~$4Bまでの75種類と見て良いようだ。

サンプリングデータのアドレス・容量

どの曲が何のサンプリングデータを使うのか、ということは上処理の内容でわかった。
では、具体的にサンプリングデータID$01~$4B、75種類のデータはどのアドレスにあるのか。

サンプリングデータの開始アドレスは以下サブルーチンで計算される。

$C3/0311 STA $1E    [$00:1D1E]   ;Aを[$00:1D1E]に書き込み
$C3/0313 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C3/0315 INY                     ;Yをインクリメント +1
$C3/0316 INY                     ;Yをインクリメント +1
$C3/0317 CPY #$0040              ;Yと$0040を減算比較(ステータスレジスタ変更のみ)
$C3/031A BNE $A5    [$02C1]      ;ゼロフラグが立っていないとき[$02C1]分岐
$C3/02C1 LDA $1D20,y[$00:1D2E]   ;Aに[$00:1D2F][$00:1D2E]をロード
$C3/02C4 BNE $4D    [$0313]      ;ゼロフラグが立っていないとき[$0313]分岐
$C3/02C6 TYX                     ;Yレジスタの値をXレジスタに転送
$C3/02C7 BRA $04    [$02CD]      ;フラグにかかわりなく常に分岐[$02CD]
$C3/02CD INX                     ;Xをインクリメント +1
$C3/02CE INX                     ;Xをインクリメント +1
$C3/02CF CPX #$0040              ;Xと$0040を減算比較(ステータスレジスタ変更のみ)
$C3/02D2 BNE $F5    [$02C9]      ;ゼロフラグが立っていないとき[$02C9]分岐
;ループ処理
$C3/02C9 LDA $20,x               ;Aに[$00:1D31][$00:1D30]~[$00:1D5F][$00:1D5E]をロード
$C3/02CB BNE $09    [$02D6]      ;ゼロフラグが立っていないとき[$02D6]分岐
$C3/02CD INX                     ;Xをインクリメント +1
$C3/02CE INX                     ;Xをインクリメント +1
$C3/02CF CPX #$0040              ;Xと$0040を減算比較(ステータスレジスタ変更のみ)
$C3/02D2 BNE $F5    [$02C9]      ;ゼロフラグが立っていないとき[$02C9]分岐
;ループ処理ここまで
$C3/02D4 BRA $46    [$031C]      ;フラグにかかわりなく常に分岐[$031C]
$C3/031C SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/031E LDA #$F0                ;Aに$F0をロード
$C3/0320 STA $1E    [$00:1D1E]   ;Aを[$00:1D1E]に書き込み
$C3/0322 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/0324 LDX #$0000              ;Xに$0000をロード
;ループ処理
$C3/0327 LDA $20,x               ;Aに[$00:1D21][$00:1D20]~[$00:1D2F][$00:1D2E]をロード
$C3/0329 BEQ $0E    [$0339]      ;ゼロフラグが立っているとき[$0339]分岐
$C3/032B INX                     ;Xをインクリメント +1
$C3/032C INX                     ;Xをインクリメント +1
$C3/032D CPX #$0040              ;Xと$0040を減算比較(ステータスレジスタ変更のみ)
$C3/0330 BNE $F5    [$0327]      ;ゼロフラグが立っていないとき[$0327]分岐
;ループ処理ここまで
;$C3/0329ゼロフラグ分岐
$C3/0339 LDY #$0000              ;Yに$0000をロード
$C3/033C REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C3/033E LDA $1E20,y             ;Aに[$00:1E21+y][$00:1E20+y]をロード サンプリングデータID
$C3/0341 BEQ $34    [$0377]      ;ゼロフラグが立っているとき[$0377]分岐
$C3/0343 STA $20,x  [$00:1D2E]   ;Aを[$00:1D2F][$00:1D2E]に書き込み
$C3/0345 PHY                     ;Yレジスタをスタックへプッシュ
$C3/0346 PHX                     ;Xレジスタをスタックにプッシュ
$C3/0347 DEC A                   ;Aをデクリメント -1
$C3/0348 STA $E2    [$00:1DE2]   ;Aを[$00:1DE3][$00:1DE2]に書き込み
$C3/034A ASL A                   ;Aを算術左シフト *2
$C3/034B CLC                     ;キャリーフラグクリア
$C3/034C ADC $E2    [$00:1DE2]   ;A + [$00:1DE2]
$C3/034E TAX                     ;Aの値をXレジスタに転送
$C3/034F SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/0351 LDA $C33FC9,x           ;Aに[$C3:3FC9,x]をロード
$C3/0355 STA $10    [$00:1D10]   ;Aを[$00:1D10]に書き込み
$C3/0357 LDA $C33FCA,x           ;Aに[$C3:3FCA,x]をロード
$C3/035B STA $11    [$00:1D11]   ;Aを[$00:1D11]に書き込み
$C3/035D LDA $C33FCB,x           ;Aに[$C3:3FCB,x]をロード
$C3/0361 STA $12    [$00:1D12]   ;Aを[$00:1D12]に書き込み
$C3/0363 LDY $10    [$00:1D10]   ;Yに[$00:1D10]をロード
$C3/0365 STZ $10    [$00:1D10]   ;[$00:1D10]に$00を書き込み
$C3/0367 STZ $11    [$00:1D11]   ;[$00:1D11]に$00を書き込み
$C3/0369 PLX                     ;Xレジスタにスタックからプル
$C3/036A JSR $037A  [$C3:037A]   ;[$C3:037A]へジャンプ

$C3/033Eで、ARAMにはない、被りなしのサンプリングデータIDがロードされ、値が00でなければアドレス計算に進む。
$C3/0351~$C3/0361でロードされる3バイト[$C33FC9,x][$C33FCA,x][$C33FCB,x]を逆から読むと、$C3/033Eで読み込まれたサンプリングデータのデータ開始アドレスになる。
$C3/0351の時点のXは、

X = (サンプリングデータID - 1) *2 + (サンプリングデータID - 1)
= (サンプリングデータID - 1) * 3

である。
つまり、$C3:3FC9から3バイトずつ値を取ってひっくり返せばサンプリングデータのデータ開始アドレスである。
ただし、上で計算したアドレスは、サンプリングデータのデータ容量2バイトの開始位置になる。
実際のサンプリングデータは+2バイトしたアドレスから。

そのため、開始アドレスがわかれば、容量と終了アドレスもわかる。
実際のデータを見てみると、以下のようになる。
アドレス計算値はデータ容量2バイトの読み込み位置であることに注意。実際のデータは+2バイトから。

音波形
データID
アドレス
計算値
サンプリングデータ
アドレス
容量
$01$C3:3FC9$C3:4D64$03A8
$02$C3:3FCC$C3:510E$0201
$03$C3:3FCF$C3:5311$00D8
$04$C3:3FD2$C3:53EB$05BB
$05$C3:3FD5$C3:59A8$0369
$06$C3:3FD8$C3:5D13$0711
$07$C3:3FDB$C3:6426$0369
$08$C3:3FDE$C3:6791$0144
$09$C3:3FE1$C3:68D7$1C0E
$10$C3:3FE4$C3:84E7$1035
$11$C3:3FE7$C2:FBBA$042F
$12$C3:3FEA$C3:951E$0666
$13$C3:3FED$C3:9B86$0843
$14$C3:3FF0$C3:A3CB$0156
$15$C3:3FF3$C3:A523$0AB9
$16$C3:3FF6$C3:AFDE$0CBA
$17$C3:3FF9$C3:BC9A$0E10
$18$C3:3FFC$C3:CAAC$172B
$19$C3:3FFF$C3:E1D9$03DE
$20$C3:4002$C3:E5B9$09AB
$21$C3:4005$C3:EF66$041D
$22$C3:4008$C3:F385$0F5D
$23$C3:400B$C4:02E4$02FD
$24$C3:400E$C4:05E3$0A4D
$25$C3:4011$CC:F000$0AF8
$26$C3:4014$C4:1032$0465
$27$C3:4017$C4:1499$0384
$28$C3:401A$C4:181F$0465
$29$C3:401D$C4:1C86$069C
$30$C3:4020$C4:2324$093F
$31$C3:4023$C4:2C65$04D1
$32$C3:4026$C4:3138$0B01
$33$C3:4029$C2:EBE6$0FD2
$34$C3:402C$C4:3C3B$0936
$35$C3:402F$C2:DC00$0FE4
$36$C3:4032$C4:4573$04BF
$37$C3:4035$C4:4A34$0201
$38$C3:4038$C4:4C37$08E5
$39$C3:403B$C4:551E$0759
$40$C3:403E$C4:5C79$077D
$41$C3:4041$C4:63F8$123F
$42$C3:4044$C4:7639$071A
$43$C3:4047$C4:7D55$0426
$44$C3:404A$C4:817D$0213
$45$C3:404D$C4:8392$015F
$46$C3:4050$C4:84F3$0D0B
$47$C3:4053$C4:9200$03CC
$48$C3:4056$C4:95CE$04A4
$49$C3:4059$C4:9A74$03F9
$0A$C3:405C$C4:9E6F$0951
$0B$C3:405F$C4:A7C2$02A3
$0C$C3:4062$C4:AA67$15F9
$0D$C3:4065$C4:C062$06B7
$0E$C3:4068$C4:C71B$0225
$0F$C3:406B$C4:C942$0D38
$1A$C3:406E$C4:D67C$01D4
$1B$C3:4071$C4:D852$03DE
$1C$C3:4074$C4:DC32$181E
$1D$C3:4077$C4:F452$0FC0
$1E$C3:407A$C5:0414$06C0
$1F$C3:407D$C5:0AD6$0A17
$2A$C3:4080$C5:14EF$04D1
$2B$C3:4083$C5:19C2$06ED
$2C$C3:4086$C5:20B1$0558
$2D$C3:4089$C5:260B$0693
$2E$C3:408C$C5:2CA0$09F3
$2F$C3:408F$C5:3695$03F9
$3A$C3:4092$C5:3A90$0E46
$3B$C3:4095$C5:48D8$07E9
$3C$C3:4098$C5:50C3$0522
$3D$C3:409B$C5:55E7$0936
$3E$C3:409E$C5:5F1F$0678
$3F$C3:40A1$CC:FAFA$04FE
$4A$C3:40A4$C5:6599$13CB
$4B$C3:40A7$C5:7966$04D1

サンプリングデータは$C2:DC00~$C2:FFE9, $C3:4D64~$C5:7E37, $CC:F000~$CC:FFF8に入っていることがわかる。
サウンド関係のプログラムはバンク$C3の前半に入っているので、できるだけプログラムに近い位置にデータを格納しているのかもしれない。
また、波形データのサイズは$0144バイト~$1C0Eバイトとまちまち。

バンク$CCに入っているのはID$25と$3Fだけ。
ID$25を使っているのは曲$08「UNSEEN SYNDROME」と曲$12「効果音(SF編・宇宙船内)」、ID$3Fを使っているのは曲$21「効果音(オルステッド レベルアップ音)」のみであり、楽器音というよりは効果音なのだろう。

サンプリングデータアドレス位置がわかれば、後は必要な分をARAMに転送することになる。
転送先はARAMアドレス$4C50~からなのだが、サンプリングデータ1つ目はARAMアドレスのここから、2つめはARAMアドレスのここから……というように指定されているのではない。
転送するデータは複数のサンプリングデータを連続して送る。

ARAMに送ったサンプリングデータにはナンバリングがなされ、BGMデータだと$20(32)から順に番号がつく。
演奏中、ナンバリングの数値は、S-DSPのアドレス$00n4(V0SRCN~V7SRCN, nはチャネル0~7)に入る。
ここではソース番号としておく。
なぜ$20からなのかというと、$00~$1Fには既にARAMにアップロード済みの効果音用のサンプリングデータが入っているからである。
効果音用のサンプリングデータしか使っていない「CAPTAIN SQUARE」は、$03, $06, $08, $05を使って演奏をしている。
$05は打楽器っぽい音で、$03と$06は正弦波っぽい音、$08はややピアノっぽい音のようであるが、筆者は音楽の専門家ではないので実際に何の音かはよくわからない。
$06はキャンセル音、$0Aはカーソル移動音、$02は決定音、$00は装備変更音、$04は装備を外す音……などの元となっているサンプリングデータになるが、それらは別途効果音の話で紹介する。

BGMの話に戻す。
例えば「魔王への叙曲」(BGMID$01)は、サンプリングデータ16枠に、ID$12, $13, $20, $07……と値が入っている。ID順ではない。

ソース
番号
音波形
データID
$20$12
$21$13
$22$20
$23$07
$24$0B
$25$23
$26$0E
$27$0C
$28$19
$29$1F
$2A$13
$2B$48
$2C-
$2D-
$2E-
$2F-

このようにソース番号$20~$2Fにサンプリングデータが割り振られる。
$0Bはフルート、$0Eはクラリネット、$0Cはピアノ、$19や$20、$34は太鼓系、 というようなことがなんとなくわかるが、筆者は音楽の専門家ではないので、これがどの楽器の音と断言できないのは申し訳なく思う。
うさんくさい一覧表はサウンド(BGM・効果音) > BGM用 サンプリングデータIDにある。参考程度にしていただきたい。

サンプリングデータの転送にそこそこの時間がかかるのは、LISTENING ROOMで曲を聞く時になんとなくわかると思う。
曲を決定してから実際に再生されるまで、曲にもよるが長いと1~2秒はあるような感じがするかもしれないが、おそらくサンプリングデータがARAMにない時に大量にデータを送る必要があるからである。
逆に、一度聞いた曲をキャンセルしてすぐにもう一度聞く時は、再生までの時間が短くなる。これはARAMにサンプリングデータが残っているため。

シーケンスデータの処理

シーケンスデータの開始位置は、以下処理で計算されている。

$C3/04F1 STA $1E    [$00:1D1E]   ;Aを[$00:1D1E]に書き込み
$C3/04F3 INY                     ;Yをインクリメント +1
$C3/04F4 INY                     ;Yをインクリメント +1
$C3/04F5 CPY #$0020              ;Yと$0020を減算比較(ステータスレジスタ変更のみ)
$C3/04F8 BNE $E1    [$04DB]      ;ゼロフラグが立っていないとき[$04DB]分岐
$C3/04FA LDA #$F0                ;Aに$F0をロード
$C3/04FC STA $1E    [$00:1D1E]   ;Aを[$00:1D1E]に書き込み
$C3/04FE SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/0500 LDA $05    [$00:1D05]   ;Aに[$00:1D05]をロード
$C3/0502 BMI $08    [$050C]      ;ネガティブフラグが立っているとき[$050C]分岐
$C3/0504 LDX $04    [$00:1D04]   ;Xに[$00:1D05][$00:1D04]をロード
$C3/0506 STX $08    [$00:1D08]   ;Xを[$00:1D09][$00:1D08]に書き込み
$C3/0508 LDX $06    [$00:1D06]   ;Xに[$00:1D07][$00:1D06]をロード
$C3/050A STX $0A    [$00:1D0A]   ;Xを[$00:1D0B][$00:1D0A]に書き込み
$C3/050C LDX $00    [$00:1D00]   ;Xに[$00:1D01][$00:1D00]をロード
$C3/050E STX $04    [$00:1D04]   ;Xを[$00:1D05][$00:1D04]に書き込み
$C3/0510 LDX $02    [$00:1D02]   ;Xに[$00:1D03][$00:1D02]をロード
$C3/0512 STX $06    [$00:1D06]   ;Xを[$00:1D07][$00:1D06]に書き込み
$C3/0514 LDX #$1C00              ;Xに$1C00をロード
$C3/0517 STX $2142  [$00:2142]   ;Xを[$00:2142]に書き込み
$C3/051A LDA #$02                ;Aに$02をロード
$C3/051C STA $2141  [$00:2141]   ;Aを[$00:2141]に書き込み
$C3/051F LDA $1E    [$00:1D1E]   ;Aに[$00:1D1E]をロード
$C3/0521 STA $2140  [$00:2140]   ;Aを[$00:2140]に書き込み
;ループ処理
$C3/0524 CMP $2140  [$00:2140]   ;Aと[$00:2140]を減算比較(ステータスレジスタ変更のみ)
$C3/0527 BNE $FB    [$0524]      ;ゼロフラグが立っていないとき[$0524]分岐
;ループ処理ここまで
$C3/0529 INC A                   ;Aをインクリメント +1
$C3/052A AND #$7F                ;Aと$7Fで論理積
$C3/052C STA $1E    [$00:1D1E]   ;Aを[$00:1D1E]に書き込み
$C3/052E REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C3/0530 LDA $01    [$00:1D01]   ;Aに[$00:1D02][$00:1D01](BGMID)をロード
$C3/0532 AND #$00FF              ;Aと$00FFで論理積
$C3/0535 STA $E2    [$00:1DE2]   ;Aを[$00:1DE3][$00:1DE2]に書き込み
$C3/0537 ASL A                   ;Aを算術左シフト *2
$C3/0538 CLC                     ;キャリーフラグクリア
$C3/0539 ADC $E2    [$00:1DE2]   ;A + [$00:1DE3][$00:1DE2]
$C3/053B TAX                     ;Aの値をXレジスタに転送
$C3/053C SEP #$20                ;MフラグON Aレジスタは8bit幅
$C3/053E LDA $C3426C,x           ;Aに[$C3:426C,x]をロード
$C3/0542 STA $10    [$00:1D10]   ;Aを[$00:1D10]に書き込み
$C3/0544 LDA $C3426D,x           ;Aに[$C3:426D,x]をロード
$C3/0548 STA $11    [$00:1D11]   ;Aを[$00:1D11]に書き込み
$C3/054A LDA $C3426E,x           ;Aに[$C3:426E,x]をロード
$C3/054E STA $12    [$00:1D12]   ;Aを[$00:1D12]に書き込み
$C3/0550 LDY $10    [$00:1D10]   ;Yに[$00:1D11][$00:1D10]をロード
$C3/0552 STZ $10    [$00:1D10]   ;[$00:1D10]に$00を書き込み
$C3/0554 STZ $11    [$00:1D11]   ;[$00:1D11]に$00を書き込み
$C3/0556 LDA [$10],y             ;Aに[$10],yをロード
$C3/0558 STA $1C    [$00:1D1C]   ;Aを[$00:1D1C]に書き込み
$C3/055A INY                     ;Yをインクリメント +1
$C3/055B BNE $02    [$055F]      ;ゼロフラグが立っていないとき[$055F]分岐
$C3/055F LDA [$10],y             ;Aに[$10],yをロード
$C3/0561 STA $1D    [$00:1D1D]   ;Aを[$00:1D1D]に書き込み
$C3/0563 INY                     ;Yをインクリメント +1
$C3/0564 BNE $02    [$0568]      ;ゼロフラグが立っていないとき[$0568]分岐
$C3/0568 LDX $1C    [$00:1D1C]   ;Xに[$00:1D1C]をロード
$C3/056A CPX #$1000              ;Xと$1000を減算比較(ステータスレジスタ変更のみ)
$C3/056D BCC $02    [$0571]      ;キャリーフラグが立っていないとき[$0571]分岐
$C3/0571 LDA [$10],y             ;Aに[$10],yをロード
$C3/0573 STA $2142  [$00:2142]   ;Aを[$00:2142]に書き込み
$C3/0576 INY                     ;Yをインクリメント +1
$C3/0577 BNE $02    [$057B]      ;ゼロフラグが立っていないとき[$057B]分岐
$C3/057B LDA [$10],y             ;Aに[$10],yをロード
$C3/057D STA $2143  [$00:2143]   ;Aを[$00:2143]に書き込み
$C3/0580 INY                     ;Yをインクリメント +1
$C3/0581 BNE $02    [$0585]      ;ゼロフラグが立っていないとき[$0585]分岐
$C3/0585 LDA $1E    [$00:1D1E]   ;Aに[$00:1D1E]をロード
$C3/0587 JSR $06BD  [$C3:06BD]   ;[$C3:06BD]へジャンプ

$C3/0530~$C3/0587で決まる、

バンク:[$C3426E,x]
アドレス:[$C3426C,x][$C3426D,x]
x = 曲ID * 3

これが、シーケンスデータの開始位置である。
ただしこのアドレスから2バイト分はシーケンスデータの容量(単位:バイト)で、その次からがARAMに転送される実際のシーケンスデータになる。
例えば曲ID$01(魔王への叙曲)なら、

バンク:[$C3426E,3]
アドレス:[$C3426C,3][$C3426D,3]
x = $01 * 3

なので、$C3:426F~$C3:4271を逆から読み、+2した値がシーケンスデータ開始位置である。

曲ID($01~$4D)から計算してみると、以下のようになる。

曲ID曲名アドレス計算値シーケンスデータ開始位置シーケンスデータ容量
$01魔王への叙曲$C3:426F~$C3:4271$C5:7E5F$0FF8
$02凛然たる戦い$C3:4272~$C3:4274$C5:8E59$0FD0
$03忍音$C3:4275~$C3:4277$C5:9E2B$0D24
$04WANDERER$C3:4278~$C3:427A$C5:AB51$0D7C
$05殺陣!$C3:427B~$C3:427D$C5:B8CF$0B98
$06THE WILDS$C3:427E~$C3:4280$C5:C469$07FC
$07UNDER THE FAKE$C3:4281~$C3:4283$C5:CC67$0645
$08UNSEEN SYNDROME$C3:4284~$C3:4286$C5:D2AE$03B8
$09NATIVE LIFE$C3:4287~$C3:4289$C5:D668$0574
$0AWAIT FOR TRUTH$C3:428A~$C3:428C$C5:DBDE$0A2A
$0BPSYCHOで夜露死苦!!$C3:428D~$C3:428F$C5:E60A$0867
$0C猛者達…$C3:4290~$C3:4292$C5:EE73$024B
$0D鳥児在天空飛翔 魚児在河里游泳$C3:4293~$C3:4295$C5:F0C0$05F3
$0E在中国的戦闘$C3:4296~$C3:4298$C5:F6B5$0547
$0F効果音(幕末編・天井裏カラクリ音)$C3:4299~$C3:429B$C5:FBFE$0068
$10KNOCK YOU DOWN!$C3:429C~$C3:429E$C5:FC68$0D9B
$11効果音(馬が走る音)$C3:429F~$C3:42A1$C6:0A05$0076
$12効果音(SF編・宇宙船内)$C3:42A2~$C3:42A4$C6:0A7D$005B
$13効果音(近未来編・港)$C3:42A5~$C3:42A7$C6:0ADA$07D7
$14老拳師下深山$C3:42A8~$C3:42AA$C6:0B95$05E5
$15いいお天気でしょっ!$C3:42AB~$C3:42AD$C6:117C$07B0
$16KISS OF JEALOUSY$C3:42AE~$C3:42B0$C6:192E$09FA
$17密命$C3:42B1~$C3:42B3$C6:232A$0AEC
$18GO!GO!ブリキ大王!!$C3:42B4~$C3:42B6$C6:2E18$0CAE
$19届かぬ翼$C3:42B7~$C3:42B9$C6:3AC8$09C1
$1A魔王山を往く$C3:42BA~$C3:42BC$C6:448B$04E3
$1B魔王オディオ$C3:42BD~$C3:42BF$C6:4970$0462
$1CPURE ODIO$C3:42C0~$C3:42C2$C6:4DD4$0FFD
$1D効果音(アキラ レベルアップ音)$C3:42C3~$C3:42C5$C6:5DD3$007F
$1E効果音(木魚のポクポク音)$C3:42C6~$C3:42C8$C6:5E54$0046
$1F効果音(風の吹く音)$C3:42C9~$C3:42CB$C6:5E9C$0041
$20効果音(キューブの機械音)$C3:42CC~$C3:42CE$C6:5EDF$0039
$21効果音(オルステッド レベルアップ音)$C3:42CF~$C3:42D1$C6:5F1A$0052
$22効果音(おぼろ丸 レベルアップ音)$C3:42D2~$C3:42D4$C6:5F6E$0046
$23効果音(サモ・ユン レベルアップ音・アチョーボイス)$C3:42D5~$C3:42D7$C6:5FB6$004A
$24効果音(レイ レベルアップ音・ボイス)$C3:42D8~$C3:42DA$C6:6002$004A
$25SELECT・A・LIVE$C3:42DB~$C3:42DD$C6:604E$03F2
$26効果音(ポゴ レベルアップ音・ボイス)$C3:42DE~$C3:42E0$C6:6442$0044
$27効果音(ゴリのボイス/馬のいななき 兼用)$C3:42E1~$C3:42E3$C6:6488$0047
$28効果音(高原日勝 レベルアップ音・ボイス)$C3:42E4~$C3:42E6$C6:64D1$004E
$29効果音(サンダウン レベルアップ音・銃声)$C3:42E7~$C3:42E9$C6:6521$0049
$2A効果音(近未来編・木琴)$C3:42EA~$C3:42EC$C6:656C$0040
$2BMEGALOMANIA$C3:42ED~$C3:42EF$C6:65AE$07C9
$2C効果音(強風の吹く音)$C3:42F0~$C3:42F2$C6:6D79$00AF
$2D効果音(SF編/近未来編・パソコン効果音)$C3:42F3~$C3:42F5$C6:6E2A$00F6
$2E効果音(近未来編・筑波研究所最奥)$C3:42F6~$C3:42F8$C6:6F22$00BA
$2F効果音(功夫編 銅鑼)$C3:42F9~$C3:42FB$C6:6FDE$0060
$30効果音(西部編 鐘)$C3:42FC~$C3:42FE$C6:7040$006E
$31効果音(幕末編 アイテム入手時)$C3:42FF~$C3:4301$C6:70B0$006D
$32効果音(原始編 ウホウホ)$C3:4302~$C3:4304$C6:711F$0046
$33最強-VICTORY ROAD-$C3:4305~$C3:4307$C6:7167$0A4B
$34LIVE・A・LIVE$C3:4308~$C3:430A$C6:7BB4$0B2C
$35CRY・A・LIVE$C3:430B~$C3:430D$C6:86E2$03DD
$36WARM・A・LIVE$C3:430E~$C3:4310$C6:8AC1$05EA
$37絶望の都$C3:4311~$C3:4313$C6:90AD$0C74
$38Sancho・de・Los・Panchoz$C3:4314~$C3:4316$C6:9D23$03F6
$39効果音(マラカス)$C3:4317~$C3:4319$C6:A11B$0047
$3A効果音(各シナリオ開始時の低い音)$C3:431A~$C3:431C$C6:A164$00A2
$3B原始編・宴(リメイク版の「生贄の宴」)$C3:431D~$C3:431F$C6:A208$0123
$3CSilent Labyrinth$C3:4320~$C3:4322$C6:A32D$05BA
$3DARMAGEDDON$C3:4323~$C3:4325$C6:A8E9$0778
$3ECAPTAIN SQUARE$C3:4326~$C3:4328$C6:B063$05F4
$3F星屑のキャプテン$C3:4329~$C3:432B$C6:B659$06D0
$40効果音(近未来編・オルガン むすんでひらいて)$C3:432C~$C3:432E$C6:BD2B$0046
$41効果音(近未来編・オルガン 猫ふんじゃった)$C3:432F~$C3:4331$C6:BD73$0052
$42効果音(近未来編・オルガン トッカータとフーガ)$C3:4332~$C3:4334$C6:BDC7$004A
$43効果音(近未来編・オルガン チョコボのテーマ)$C3:4335~$C3:4337$C6:BE13$004F
$44Live over Again$C3:4338~$C3:433A$C6:BE64$054D
$45Live for Live$C3:433B~$C3:433D$C6:C3B3$2AB7
$46効果音(崩壊)$C3:433E~$C3:4340$C6:EE6C$0046
$47効果音(SF編・警告音)$C3:4341~$C3:4343$C6:EEB4$0042
$48効果音(功夫編・夜 虫の音)$C3:4344~$C3:4346$C6:EEF8$00C7
$49CAPTAIN SQUARE$C3:4347~$C3:4349$C6:B063$05F4
$4A効果音(ゲーム開始時「SQUARE SOFT」ボイス)$C3:434A~$C3:434C$C6:EFC1$0046
$4BILLUSION…$C3:434D~$C3:434F$C6:F009$0A0B
$4CVersus!$C3:4350~$C3:4352$C6:FA16$01D6
$4D原始編・宴 ボイスのみ$C3:4353~$C3:4355$C6:FBEE$005D

このようになる。

曲によりシーケンスデータのサイズはまったく異なるのだが、ARAMのアドレス$1C00~$2BFFがシーケンスデータ転送位置のため、サイズは$1000バイト以下でなければならない。
ARAMのアドレス$2C00~$47FFは、効果音用シーケンスデータの領域であり、タイトル画面をロードした時点で書き込まれている。
だが、エンディング曲の「Live for Live」だけ$2AB7バイトとサイズがはみ出している。
「Live for Live」はどうなるかというと、ARAMのアドレス$1C00を転送開始位置として、ARAMのアドレス$2C00を越えて上書きするのである。
エンディング曲の後は各キャラの効果音を鳴らして終了となりタイトル画面に戻るため、効果音関係のデータを上書きしても問題ないということであろう。

ARAMメモリマッピング

ARAMのメモリマッピングについて、ひとまずまとめるとだいたい以下のようになると思われる。

ARAMアドレス内容
$0000~$00EFメモリ領域(0ページ)
$00F0~$00FFSPC700レジスタ(I/Oポートアドレス)
$0200~$19C8SPC700用プログラム($C3:0746~$C3:1F0E)
$1A00~$1A17効果音用サンプリングデータ($C3:23AE~$C3:23C5)
$1A80~$1A97効果音用サンプリングデータ($C3:2394~$C3:23AB)
$1B00~$1B2B効果音用サンプリングデータ($C3:2366~$C3:2390)
$1B80~$1BBFWRAM$00:1E80~$00:1EBFと同値
$1C00~$2BFF演奏中のBGM用シーケンスデータ
$2C00~$47FF効果音用シーケンスデータ($C3:23C8~$C3:3FC7)
$4800~$4C34効果音用サンプリングデータ($C3:1F11~$C3:2365)
$4C50~$????演奏中のBGM用サンプリングデータ
$FFC0~$FFFFIPL ROM 64バイト(初期化用プログラム)

なお、$0002~$0012の$10バイト(16バイト)は、2バイトずつ、現在チャネル0~7で演奏している音が入るようである。



このページをシェアする

上へ