TOP > プログラミング関係解説&調査 > サウンドについて > BGMIDの呼び出し

サウンドについて > BGMIDの呼び出し

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

サウンドの演奏では、BGMIDから実際に該当曲の演奏処理までを紹介している。
ここでは、BGMIDはどうやって呼び出しているのか? を、状況ごとに紹介する。

BGMIDを呼び出して、新たなBGMを演奏する場面は、

  • ゲーム開始時の「SQUARE SOFT」ボイス(BGMID$4A)
  • オープニングデモ中の「LIVE・A・LIVE」(BGMID$34)
  • シナリオ選択画面開始時の「SELECT・A・LIVE」(BGMID$25)
  • シナリオ開始時
  • LISTENING ROOM
  • セーブデータをロード時
  • フィールド移動時のマップ切り替えでBGMが変わるマップ
  • イベント中のBGM切り替え
  • 通常戦闘(シナリオ毎の通常戦闘BGM)
  • イベント戦闘・ボス戦

……などがあるが、以下では代表的なものを幾つか紹介する。
このページでは、$00:1D01にBGMIDを書き込むまでの処理を紹介する。

ゲーム開始時の「SQUARE SOFT」ボイス(BGMID$4A)

オープニングデモを流していると、「SQUARE SOFT」ボイス以降のゲーム画面でも効果音のみは流れるが、BGMで流れるのは「LIVE・A・LIVE」のみ(のはず)。

ゲーム開始(リセット)からオープニングデモにかけて、画面全体に文字が出て各シナリオの一場面、という切り替えが流れるが、この「画面全体に文字が出て各シナリオの一場面」のサブルーチンは、$C0/DACA~$C0/DC74が担っている(このサブルーチン内で$C0/DC75以降にもジャンプする)。
最後の「LIVE A LIVE」ロゴが出るあたりまでも$C0/DACA~$C0/DC74が担当し、以下で「LIVE・A・LIVE」のBGMID$34が呼び出される。

最初の「SQUARE SOFT」ボイスのID呼び出しは$C0/DAFFから。

$C0/DAFF LDA #$4A                ;Aに$4Aをロード
$C0/DB01 STA $30    [$00:0030]   ;Aを[$00:0030]に書き込み
$C0/DB03 LDA #$FF                ;Aに$FFをロード
$C0/DB05 STA $31    [$00:0031]   ;Aを[$00:0031]に書き込み
$C0/DB07 JSR $1121  [$C0:1121]   ;[$C0:1121]へジャンプ

$C0/1121 LDA #$10                ;Aに$10をロード
$C0/1123 JSR $12CF  [$C0:12CF]   ;[$C0:12CF]へジャンプ

$C0/12CF LDX #$1D00              ;Xに$1D00をロード
$C0/12D2 STA $00,x  [$00:1D00]   ;Aを[$00:1D00]に書き込み
$C0/12D4 LDA $30    [$00:0030]   ;Aに[$00:0030]をロード
$C0/12D6 STA $01,x  [$00:1D01]   ;Aを[$00:1D01]に書き込み
$C0/12D8 LDA $31    [$00:0031]   ;Aに[$00:0031]をロード
$C0/12DA STA $02,x  [$00:1D02]   ;Aを[$00:1D02]に書き込み
$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]へジャンプ(レジスタをスタックに積まない)

$C0/DAFF~で[$00:0030]に$4A、[$00:0031]に$FFをロードし、$C0/1121で$10をAにロードした後、$C0/12CFから以下のように値が入る。

アドレス値
[$00:1D00]$10
[$00:1D01]$4A
[$00:1D02]$FF

ここでBGMID$4Aが[$00:1D01]に入るので、「SQUARE SOFT」ボイスが呼び出される。
つまり、$C0/DAFF~$C0/DB07は「SQUARE SOFT」ボイス呼び出し専用処理だったことになる。

オープニングデモ中の「LIVE・A・LIVE」(BGMID$34)

「LIVE・A・LIVE」のID呼び出しは$C0/DF34から。

$C0/DF34 LDA #$10                ;Aに$10をロード
$C0/DF36 STA $212C  [$00:212C]   ;Aを[$00:212C]に書き込み TM (メインスクリーン指定) OBJ
$C0/DF39 LDA #$34                ;Aに$34をロード
$C0/DF3B STA $30    [$00:0030]   ;Aを[$00:0030]に書き込み
$C0/DF3D JSR $111D  [$C0:111D]   ;[$C0:111D]へジャンプ

$C0/111D LDA #$FF                ;Aに$FFをロード
$C0/111F STA $31    [$00:0031]   ;Aを[$00:0031]に書き込み
$C0/1121 LDA #$10                ;Aに$10をロード
$C0/1123 JSR $12CF  [$C0:12CF]   ;[$C0:12CF]へジャンプ

$C0/12CF LDX #$1D00              ;Xに$1D00をロード
$C0/12D2 STA $00,x  [$00:1D00]   ;Aを[$00:1D00]に書き込み
$C0/12D4 LDA $30    [$00:0030]   ;Aに[$00:0030]をロード
$C0/12D6 STA $01,x  [$00:1D01]   ;Aを[$00:1D01]に書き込み
$C0/12D8 LDA $31    [$00:0031]   ;Aに[$00:0031]をロード
$C0/12DA STA $02,x  [$00:1D02]   ;Aを[$00:1D02]に書き込み
$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]へジャンプ

$C0/DF39で呼び出した$34が、最終的に[$00:1D01]に書き込まれており、「LIVE・A・LIVE」のID呼び出しになっている。

アドレス値
[$00:1D00]$10
[$00:1D01]$34
[$00:1D02]$FF

ニューゲーム、またはシナリオ選択画面の「SELECT・A・LIVE」(BGMID$25)

シナリオ選択画面やメニュー画面のサブルーチンはバンク$C2に入っているが、メニュー画面から聞ける「LISTENING ROOM」と似た処理があるのでふたつ続けて紹介する。

$C2/0726 BCS $06    [$072E]      ;キャリーフラグが立っているとき[$072E]分岐
$C2/0728 PER $0002  [$072D]      ;PCの値にオペランドとして指定した16bit値を足した値をスタックに積み[$072D]
$C2/072B JMP ($0532)[$C2:1BAA]   ;[$C2:1BAA]へジャンプ(レジスタをスタックに積まない)
$C2/1BAA LDA $0A00  [$7E:0A00]   ;Aに[$7E:0A01][$7E:0A00]をロード
$C2/1BAD CMP #$FF00              ;Aと$FF00を減算比較(ステータスレジスタ変更のみ)
$C2/1BB0 BEQ $0C    [$1BBE]      ;ゼロフラグが立っているとき[$1BBE]分岐
$C2/1BB2 LDA #$00FF              ;Aに$00FFをロード
$C2/1BB5 STA $1D02  [$7E:1D02]   ;Aを[$7E:1D03][$7E:1D02]に書き込み
$C2/1BB8 LDA #$2514              ;Aに$2514をロード
$C2/1BBB JSR $3CAC  [$C2:3CAC]   ;[$C2:3CAC]へジャンプ

$C2/3CAC STA $1D00  [$7E:1D00]   ;Aを[$7E:1D01][$7E:1D00]に書き込み
$C2/3CAF JSL $C30004[$C3:0004]   ;[$C3:0004]へジャンプ

$C2/1BAAでロードする[$7E:0A00]([$00:0A00]、バンク$7Eのミラーが$00)は本来シナリオIDが入るアドレスだが、シナリオ選択画面で各シナリオの主人公キャラの戦闘用スプライトを呼び出すために、[$7E:0A00]に$00~$07を書き込んでループ処理する仕組みがある(このため、一時的にバンク$C1の戦闘用サブルーチンを呼び出している)。
そのスプライトの呼び出しがすべて終わった状態、つまり[$7E:0A00]に$07が入った状態で上処理が入る。
結果、以下のように値が入る。

アドレス値
[$7E:1D00]$14
[$7E:1D01]$25
[$7E:1D02]$FF
[$7E:1D03]$00

BGMID$25が呼び出され、「SELECT・A・LIVE」が流れる。

LISTENING ROOM

ここでは例として、LISTENING ROOMが全開放されている状態で、最初に表示される「LIVE・A・LIVE」(BGMID$34)を選択した場合を紹介する。
LISTENING ROOMでは、カーソル位置にある曲のBGM関係のデータが、$C2/2305のMVN転送で、$C2:8Bnn(nnはLISTENING ROOMのページにより変動)から6バイトのデータが$7E:2EB5~$7E:2EBAに書き込まれる処理がある(サブルーチン省略)。
カーソル位置の曲を選択すると、その中の[$7E:2EB5]が下処理で[$7E:1D01]に書き込まれる仕組み。

$C2/2352 LDA #$00FF              ;Aに$00FFをロード
$C2/2355 STA $1D02  [$7E:1D02]   ;Aを[$7E:1D03][$7E:1D02]に書き込み
$C2/2358 LDA $2EB5  [$7E:2EB5]   ;Aに[$7E:2EB6][$7E:2EB5]をロード
$C2/235B AND #$00FF              ;Aと$00FFで論理積
$C2/235E XBA                     ;Aレジスタの上位バイトと下位バイトを交換
$C2/235F ORA #$0010              ;Aと$0010で論理和
$C2/2362 JSR $3CAC  [$C2:3CAC]   ;[$C2:3CAC]へジャンプ

$C2/3CAC STA $1D00  [$7E:1D00]   ;Aを[$7E:1D01][$7E:1D00]に書き込み
$C2/3CAF JSL $C30004[$C3:0004]   ;[$C3:0004]へジャンプ
アドレス値
[$7E:1D00]$10
[$7E:1D01][$7E:2EB5]
[$7E:1D02]$FF
[$7E:1D03]$00

シナリオ開始時

シナリオ開始時を含め、フィールドでBGMを演奏開始する時のサブルーチンは$C0/12E7~$C0/1316が共通処理と思われる。
$C0/12E7までに、[$00:0030]にBGMIDが書き込まれた上で以下処理になる。

$C0/12E7 PHA                     ;Aレジスタをスタックにプッシュ
$C0/12E8 LDA $30    [$00:0030]   ;Aに[$00:0030]をロード
$C0/12EA CMP $000A68[$00:0A68]   ;Aと[$00:0A68]を減算比較(ステータスレジスタ変更のみ)
$C0/12EE BNE $06    [$12F6]      ;ゼロフラグが立っていないとき[$12F6]分岐
$C0/12F6 CMP $000A60[$00:0A60]   ;Aと[$00:0A60](現在のBGMID)を減算比較(ステータスレジスタ変更のみ)
$C0/12FA BEQ $25    [$1321]      ;ゼロフラグが立っているとき[$1321]分岐
$C0/12FC STA $000A60[$00:0A60]   ;Aを[$00:0A60]に書き込み
$C0/1300 CMP #$FF                ;Aと$FFを減算比較(ステータスレジスタ変更のみ)
$C0/1302 BEQ $1D    [$1321]      ;ゼロフラグが立っているとき[$1321]分岐
$C0/1304 PLA                     ;Aレジスタにスタックからプル
$C0/1305 LDX #$1D00              ;Xに$1D00をロード
$C0/1308 STA $00,x  [$00:1D00]   ;Aを[$00:1D00]に書き込み
$C0/130A LDA $30    [$00:0030]   ;Aに[$00:0030]をロード
$C0/130C STA $01,x  [$00:1D01]   ;Aを[$00:1D01]に書き込み
$C0/130E LDA $31    [$00:0031]   ;Aに[$00:0031]をロード
$C0/1310 STA $02,x  [$00:1D02]   ;Aを[$00:1D02]に書き込み
$C0/1312 LDA $70    [$00:0070]   ;Aに[$00:0070]をロード
$C0/1314 BNE $0A    [$1320]      ;ゼロフラグが立っていないとき[$1320]分岐
$C0/1316 JSR $102F  [$C0:102F]   ;[$C0:102F]へジャンプ

フィールドでは、[$00:0A60]に現在のBGMIDが入っており、$C0/12F6~$C0/12FCの処理は[$00:0030]と現在のBGMIDが同値ならBGMの演奏は行わない(現在のBGMを継続)という処理。
そうでない場合、[$00:0030]が新たな現在のBGMIDとして[$00:0A60]に入る。

アドレス値
[$00:1D00]$C0/12E7の時点のAレジスタの値
[$00:1D01][$00:0030]
[$00:1D02][$00:0031]

では、[$00:0030]はどのように計算されているのか。
これはシナリオによりまったく変わってくるのだが、例えば幕末編なら、冒頭で$3A(低い効果音のような音)が流れる。

$C0/1C2A JMP ($429F,x)[$C0:1D4B] ;[$C0:1D4B]へジャンプ(レジスタをスタックに積まない)
$C0/1D4B LDA $8E00,y[$7F:9021]   ;Aに[$7F:9021]をロード
$C0/1D4E STA $30    [$00:0030]   ;Aを[$00:0030]に書き込み
$C0/1D50 LDA #$20                ;Aに$20をロード
$C0/1D52 STA $31    [$00:0031]   ;Aを[$00:0031]に書き込み
$C0/1D54 PHY                     ;Yレジスタをスタックへプッシュ
$C0/1D55 JSR $10D8  [$C0:10D8]   ;[$C0:10D8]へジャンプ

$C0/10D8 LDA $31    [$00:0031]   ;Aに[$00:0031]をロード
$C0/10DA STA $000A61[$00:0A61]   ;Aを[$00:0A61]に書き込み
$C0/10DE LDA #$10                ;Aに$10をロード
$C0/10E0 JSR $12E7  [$C0:12E7]   ;[$C0:12E7]へジャンプ

[$7F:9021]にロードしたシナリオ用の値が入っている。
一方功夫編だと開始直後からBGMID$14「老拳師下深山」が流れるが、

$C0/1C2A JMP ($429F,x)[$C0:1CBC] ;[$C0:1CBC]へジャンプ(レジスタをスタックに積まない)
$C0/1CBC LDA $8E00,y[$7F:900D]   ;Aに[$7F:900D]をロード
$C0/1CBF STA $30    [$00:0030]   ;Aを[$00:0030]に書き込み
$C0/1CC1 PHY                     ;Yレジスタをスタックへプッシュ
$C0/1CC2 LDA #$FF                ;Aに$FFをロード
$C0/1CC4 STA $31    [$00:0031]   ;Aを[$00:0031]に書き込み
$C0/1CC6 JSR $10D8  [$C0:10D8]   ;[$C0:10D8]へジャンプ

$C0/10D8 LDA $31    [$00:0031]   ;Aに[$00:0031]をロード
$C0/10DA STA $000A61[$00:0A61]   ;Aを[$00:0A61]に書き込み
$C0/10DE LDA #$10                ;Aに$10をロード
$C0/10E0 JSR $12E7  [$C0:12E7]   ;[$C0:12E7]へジャンプ

[$7F:900D]が入っている。
$7F:9000~は、シナリオで固定の値であり、シナリオ進行に関する定数のようなものなので、各シナリオで処理が変わってくる。

セーブデータをロード時

セーブデータをロードする場合、セーブデータ内に[$00:0A60](セーブした時点での現在のフィールドBGMのID)が保存されているため、それを[$00:0030]に書き込んでいる。

$C0/06FA LDA $10E7  [$00:10E7]   ;Aに[$00:10E7]をロード
$C0/06FD BNE $35    [$0734]      ;ゼロフラグが立っていないとき[$0734]分岐
$C0/06FF LDA $0A60  [$00:0A60]   ;Aに[$00:0A60]をロード
$C0/0702 CMP #$FF                ;Aと$FFを減算比較(ステータスレジスタ変更のみ)
$C0/0704 BEQ $0A    [$0710]      ;ゼロフラグが立っているとき[$0710]分岐
$C0/0706 STA $30    [$00:0030]   ;Aを[$00:0030]に書き込み
$C0/0708 LDA #$FF                ;Aに$FFをロード
$C0/070A STA $0A60  [$00:0A60]   ;Aを[$00:0A60]に書き込み
$C0/070D JSR $10CC  [$C0:10CC]   ;[$C0:10CC]へジャンプ

$C0/10CC LDA $000A61[$00:0A61]   ;Aに[$00:0A61]をロード
$C0/10D0 STA $31    [$00:0031]   ;Aを[$00:0031]に書き込み
$C0/10D2 LDA #$10                ;Aに$10をロード
$C0/10D4 JSR $12E7  [$C0:12E7]   ;[$C0:12E7]へジャンプ

$C0/10CC~$C0/10D4の処理は、この後のマップでのBGM切り替え時の処理と兼用。

フィールド移動時のマップ切り替えでBGMが変わるマップ

マップ切り替え時、切り替え先(移動先)のマップのBGMIDが[$00:0119]に入るのだが、[$00:0119]と、それまでのマップのBGMID[$00:0A60]の値が一致しない場合はマップ切り替えでBGMが変動し、新たなBGMを演奏する処理が入る。
[$00:0119]の計算は$C0/48B0~$C0/4A47の中の$C0/49A5~$C0/49C0で行われている。
サブルーチン冒頭の$C0/48B8で[$00:0A02](マップ番号)を呼び出しており、ここから各種パラメータを計算している。
マップのBGMIDもそうだし、$C0/4A47の後は$CE/D47Eにジャンプしグラフィックデータの処理が始まるのでマップのグラフィックデータ関係のパラメータも呼び出しているようである。

以下は一例として、最終編でルクレチアの森から力のダンジョンに入った時の処理を紹介する。

$C0/48B0 STZ $011C  [$00:011C]   ;[$00:011C]に$00を書き込み
$C0/48B3 PHB                     ;DBレジスタをスタックにプッシュ
$C0/48B4 LDA #$7F                ;Aに$7Fをロード
$C0/48B6 PHA                     ;Aレジスタをスタックにプッシュ
$C0/48B7 PLB                     ;DBレジスタにスタックからプル
$C0/48B8 LDA $000A02[$00:0A02]   ;Aに[$00:0A02](マップ番号)をロード
$C0/48BC REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
(中略)
$C0/49A5 LDA $000C,x[$7F:65AF]   ;Aに[$7F:65AF]をロード
$C0/49A8 AND #$40                ;Aと$40で論理積
$C0/49AA LSR A                   ;Aを論理右シフト (/2)
$C0/49AB LSR A                   ;Aを論理右シフト (/2)
$C0/49AC LSR A                   ;Aを論理右シフト (/2)
$C0/49AD LSR A                   ;Aを論理右シフト (/2)
$C0/49AE ORA $00011A[$00:011A]   ;Aと[$00:011A]で論理和
$C0/49B2 STA $00011A[$00:011A]   ;Aを[$00:011A]に書き込み
$C0/49B6 LDA $000F,x[$7F:65B2]   ;Aに[$7F:65B2]をロード
$C0/49B9 STA $000123[$00:0123]   ;Aを[$00:0123]に書き込み
$C0/49BD LDA $000E,x[$7F:65B1]   ;Aに[$7F:65B1]をロード
$C0/49C0 STA $000119[$00:0119]   ;Aを[$00:0119]に書き込み
(中略)
$C0/4A47 JSL $CED47E[$CE:D47E]   ;[$CE:D47E]へジャンプ

$C0/49BDで呼び出す[$7F:65B1]が、最終編だと$3C(BGMID$3C「Silent Labyrinth」)である。

その後、まず$C0/06B5~$C0/070Dの処理が入る。

$C0/06B5 LDA $010F  [$00:010F]   ;Aに[$00:010F]をロード
$C0/06B8 BNE $25    [$06DF]      ;ゼロフラグが立っていないとき[$06DF]分岐
$C0/06BA LDA $010E  [$00:010E]   ;Aに[$00:010E]をロード
$C0/06BD BNE $38    [$06F7]      ;ゼロフラグが立っていないとき[$06F7]分岐
$C0/06BF LDA $0200  [$00:0200]   ;Aに[$00:0200]をロード
$C0/06C2 BEQ $0F    [$06D3]      ;ゼロフラグが立っているとき[$06D3]分岐
;$C0/06C2 ゼロフラグOFF [$00:0200]が$00以外
$C0/06C4 CMP #$FF                ;Aと$FFを減算比較(ステータスレジスタ変更のみ)
$C0/06C6 BEQ $48    [$0710]      ;ゼロフラグが立っているとき[$0710]分岐
$C0/06C8 LDA $0A60  [$00:0A60]   ;Aに[$00:0A60]をロード
$C0/06CB CMP #$FF                ;Aと$FFを減算比較(ステータスレジスタ変更のみ)
$C0/06CD BEQ $41    [$0710]      ;ゼロフラグが立っているとき[$0710]分岐
$C0/06CF STA $30    [$00:0030]   ;Aを[$00:0030]に書き込み
$C0/06D1 BRA $3A    [$070D]      ;フラグにかかわりなく常に分岐[$070D]
;$C0/06C2 ゼロフラグON [$00:0200]が$00
$C0/06D3 LDA $0A6A  [$00:0A6A]   ;Aに[$00:0A6A]をロード
$C0/06D6 BNE $38    [$0710]      ;ゼロフラグが立っていないとき[$0710]分岐
$C0/06D8 LDA $0119  [$00:0119]   ;Aに[$00:0119]をロード
$C0/06DB STA $30    [$00:0030]   ;Aを[$00:0030]に書き込み
$C0/06DD BRA $2E    [$070D]      ;フラグにかかわりなく常に分岐[$070D]
;$C0/06DF~$C0/070A省略
;処理合流
$C0/070D JSR $10CC  [$C0:10CC]   ;[$C0:10CC]へジャンプ

[$00:0200]の値によって分岐するのだが、

[$00:0200]が$00の場合:
[$00:0119]→[$00:0030]

[$00:0200]が$00以外の場合:
[$00:0A60]→[$00:0030]

[$00:0200]の値により[$00:0030]に入る値が変わる。
[$00:0200]が$00以外だとBGMが変動することがある、らしい。

つまり、[$00:0200]の値は、BGM切り替えの判定に使っていることがわかる。
ちなみにマップ切り替えだけではなく、メニュー画面切り替え時や、プレイヤーが操作できないイベント中も$00以外の値が入ることがある(詳細は未調査)
[$00:0200]自体はBGM切り替えの判定も含め他にも様々な判定に使っている。

なお、$C0/06B5~$C0/070Dの中には他にも分岐があるが、[$00:0119]→[$00:0030]の処理は[$00:0200]が$00の場合のみである。

その後、[$00:0200]が$00以外だと以下処理で[$00:0119]が[$00:0030]に入る。

$C0/40C8 LDA $0A6A  [$00:0A6A]   ;Aに[$00:0A6A]をロード
$C0/40CB BNE $0C    [$40D9]      ;ゼロフラグが立っていないとき[$40D9]分岐
$C0/40CD LDA $0119  [$00:0119]   ;Aに[$00:0119]をロード $3C	Silent Labyrinth
$C0/40D0 CMP #$FF                ;Aと$FFを減算比較(ステータスレジスタ変更のみ)
$C0/40D2 BEQ $05    [$40D9]      ;ゼロフラグが立っているとき[$40D9]分岐
$C0/40D4 STA $30    [$00:0030]   ;Aを[$00:0030]に書き込み
$C0/40D6 JSR $10CC  [$C0:10CC]   ;[$C0:10CC]へジャンプ

結果として[$00:0200]が何であろうと[$00:0119]→[$00:0030]とコピーするのだが、[$00:0030]が移動前のマップのBGMIDと同一でない場合のみ、BGMが変更されることになる。
あとはセーブデータのロード時と同じく、$C0/10CC~$C0/10D4、$C0/12E7~と処理が進む。

通常戦闘(シナリオ毎の通常戦闘BGM)

シナリオ毎の通常戦闘BGMIDは、シナリオ開始時、以下処理で計算されて[$00:10E5]に書き込まれる。
[$00:10E5]はセーブデータに記録される領域内のアドレスなので、何かしらのシナリオをプレイしている間はずっと同じ値が入っている。

$C0/046C LDA $0A00  [$00:0A00]   ;Aに[$00:0A00](シナリオID)をロード
$C0/046F TAX                     ;Aの値をXレジスタに転送
$C0/0470 PHB                     ;DBレジスタをスタックにプッシュ
$C0/0471 LDA #$C0                ;Aに$C0をロード
$C0/0473 PHA                     ;Aレジスタをスタックにプッシュ
$C0/0474 PLB                     ;DBレジスタにスタックからプル
$C0/0475 LDA $1353,x             ;Aに[$1353,x]をロード
$C0/0478 PLB                     ;DBレジスタにスタックからプル
$C0/0479 STA $10E5  [$00:10E5]   ;Aを[$00:10E5]に書き込み
$C0/047C JSR $119B  [$C0:119B]   ;[$C0:119B]へジャンプ

「$C0:1353 + シナリオID」のアドレスに通常戦闘BGMIDが入っている、ということである。

ただし、通常戦闘BGMを使うイベント戦闘の場合は、[$00:10E5]の値をBGMIDとして使うことはない。
幕末編の場合、雑魚戦であっても、ほとんどの戦闘で戦闘前に会話イベントがあるため、だいたいがイベント戦闘扱いのようである。

シンボルエンカウントでシンボルに接触するとすぐ戦闘になる場合や、ランダムエンカウント時には以下処理でシナリオ毎の通常戦闘BGMIDが読み込まれる。

$C0/1B7B LDA #$01                ;Aに$01をロード
$C0/1B7D STA $0200  [$00:0200]   ;Aを[$00:0200]に書き込み
$C0/1B80 STZ $0214  [$00:0214]   ;[$00:0214]に$00を書き込み
$C0/1B83 STZ $021A  [$00:021A]   ;[$00:021A]に$00を書き込み
$C0/1B86 STZ $0202  [$00:0202]   ;[$00:0202]に$00を書き込み
$C0/1B89 STZ $0203  [$00:0203]   ;[$00:0203]に$00を書き込み
;(中略)
$C0/31A6 LDA $0010E5[$00:10E5]   ;Aに[$00:10E5]をロード
$C0/31AA STA $44    [$00:0044]   ;Aを[$00:0044]に書き込み
$C0/31AC PHY                     ;Yレジスタをスタックへプッシュ
$C0/31AD PHB                     ;DBレジスタをスタックにプッシュ
$C0/31AE LDA #$00                ;Aに$00をロード
$C0/31B0 PHA                     ;Aレジスタをスタックにプッシュ
$C0/31B1 PLB                     ;DBレジスタにスタックからプル
$C0/31B2 JSR $181B  [$C0:181B]   ;[$C0:181B]へジャンプ

まず$C0/31A6~$C0/31AAで、[$00:10E5]が[$00:0044]にコピーされる。

$C1/12C8 LDA $0070  [$00:0070]   ;Aに[$00:0070]をロード
$C1/12CB CMP #$01                ;Aと$01を減算比較(ステータスレジスタ変更のみ)
$C1/12CD BNE $01    [$12D0]      ;ゼロフラグが立っていないとき[$12D0]分岐
$C1/12D0 LDA $0044  [$00:0044]   ;Aに[$00:0044](通常戦闘BGMID)をロード
$C1/12D3 BNE $29    [$12FE]      ;ゼロフラグが立っていないとき[$12FE]分岐
$C1/12FE STA $10    [$00:0310]   ;Aを[$00:0310]に書き込み
$C1/1300 LDA $AA    [$00:03AA]   ;Aに[$00:03AA]をロード
$C1/1302 BEQ $04    [$1308]      ;ゼロフラグが立っているとき[$1308]分岐
$C1/1308 LDA #$86                ;Aに$86をロード
$C1/130A STA $1D00  [$00:1D00]   ;Aを[$00:1D00]に書き込み
$C1/130D LDA #$00                ;Aに$00をロード
$C1/130F STA $1D01  [$00:1D01]   ;Aを[$00:1D01]に書き込み
$C1/1312 STA $1D02  [$00:1D02]   ;Aを[$00:1D02]に書き込み
$C1/1315 JSR $11D8  [$C1:11D8]   ;[$C1:11D8]へジャンプ

更に、[$00:0044]→[$00:0310]とコピーされる。
このタイミングで[$00:1D01]に$00が入るのは戦闘突入時の効果音が終わるため。

$C1/1342 LDA #$14                ;Aに$14をロード
$C1/1344 STA $1D00  [$00:1D00]   ;Aを[$00:1D00]に書き込み
$C1/1347 LDA $10    [$00:0310]   ;Aに[$00:0310](通常戦闘BGMID)をロード
$C1/1349 AND #$7F                ;Aと$7Fで論理積
$C1/134B STA $1D01  [$00:1D01]   ;Aを[$00:1D01]に書き込み
$C1/134E LDA #$FF                ;Aに$FFをロード
$C1/1350 STA $1D02  [$00:1D02]   ;Aを[$00:1D02]に書き込み
$C1/1353 JSR $11D8  [$C1:11D8]   ;[$C1:11D8]へジャンプ

$C1/11D8 LDA $0040  [$00:0040]   ;Aに[$00:0040]をロード
$C1/11DB CMP #$04                ;Aと$04を減算比較(ステータスレジスタ変更のみ)
$C1/11DD BEQ $04    [$11E3]      ;ゼロフラグが立っているとき[$11E3]分岐
$C1/11DF JSL $C30004[$C3:0004]   ;[$C3:0004]へジャンプ

最終的に[$00:0310] & $7Fが[$00:1D01]に入る。

アドレス値
[$00:1D00]$14
[$00:1D01][$00:0310] & $7F(通常戦闘BGMID)
[$00:1D02]$FF

BGMIDは$4D以下にしかBGMが入っていないので、$7F(%0111 1111)と論理積を取る意味がなさそうに思えるが、実際にはこの後に紹介するイベント戦闘で関係してくる。

イベント戦闘・ボス戦

イベント戦闘は通常戦闘BGMが流れる・流れないに関わらず、以下処理で戦闘BGMIDが計算されている。

$C0/30C5 LDA $8E00,y             ;Aに[$8E00,y]をロード
$C0/30C8 STA $40    [$00:0040]   ;Aを[$00:0040]に書き込み
$C0/30CA LDA #$01                ;Aに$01をロード
$C0/30CC STA $43    [$00:0043]   ;Aを[$00:0043]に書き込み
$C0/30CE LDA $8E01,y             ;Aに[$8E01,y]をロード
$C0/30D1 STA $44    [$00:0044]   ;Aを[$00:0044]に書き込み
$C0/30D3 INY                     ;Yをインクリメント +1
$C0/30D4 INY                     ;Yをインクリメント +1
$C0/30D5 PHY                     ;Yレジスタをスタックへプッシュ
$C0/30D6 PHB                     ;DBレジスタをスタックにプッシュ
$C0/30D7 LDA #$00                ;Aに$00をロード
$C0/30D9 PHA                     ;Aレジスタをスタックにプッシュ
$C0/30DA PLB                     ;DBレジスタにスタックからプル
$C0/30DB JSR $181B  [$C0:181B]   ;[$C0:181B]へジャンプ

以上で計算された[$00:0044]が、通常戦闘BGMと同じく、

[$00:0044]→[$00:0310]→[$00:0310] & $7Fが[$00:1D01]に入る

となる。
[$00:0044]は[$8E01,y]で、バンク$7Fの何かしらの値になるが、各シナリオの進行度合いなどフラグで決まる値なので割愛。

例えばブリキ大王を操作しての戦闘(近未来編ラストバトル除く)だと、

$C0/30C5 LDA $8E00,y[$7F:D664]   ;Aに[$7F:D664]をロード
$C0/30C8 STA $40    [$00:0040]   ;Aを[$00:0040]に書き込み
$C0/30CA LDA #$01                ;Aに$01をロード
$C0/30CC STA $43    [$00:0043]   ;Aを[$00:0043]に書き込み
$C0/30CE LDA $8E01,y[$7F:D665]   ;Aに[$7F:D665]をロード
$C0/30D1 STA $44    [$00:0044]   ;Aを[$00:0044]に書き込み
$C0/30D3 INY                     ;Yをインクリメント +1
$C0/30D4 INY                     ;Yをインクリメント +1
$C0/30D5 PHY                     ;Yレジスタをスタックへプッシュ
$C0/30D6 PHB                     ;DBレジスタをスタックにプッシュ
$C0/30D7 LDA #$00                ;Aに$00をロード
$C0/30D9 PHA                     ;Aレジスタをスタックにプッシュ
$C0/30DA PLB                     ;DBレジスタにスタックからプル
$C0/30DB JSR $181B  [$C0:181B]   ;[$C0:181B]へジャンプ

[$7F:D665]($98)が[$00:0044]に入る。
$98はBGMIDには存在しないが、最終的に[$00:0310] & $7Fを計算すると$98 & $7F = $18(GO!GO!ブリキ大王!!)である。

SF編ラストバトルなら、[$00:0044]にSF編での[$7F:DF72]($2B)が入って、そのままBGMID$2B「MEGALOMANIA」が呼び出される。
幕末編の5忍者戦だと、幕末編の[$7F:AAEE]($05)が入って、通常戦闘BGMの「殺陣!」が呼び出される。通常戦闘BGMIDが入っている[$00:10E5]は関係ない。

BGMIDを指定する特殊な戦闘は、最終編のオディオアイ・オディオマウス・オディオモール戦、そして戦闘途中でBGMが切り替わって開始になるピュアオディオ戦である。
オディオ戦の解説も参照していただきたい。

オディオ戦(開始時)

$C1/833C LDA $50    [$00:0350]   ;Aに[$00:0350]をロード
$C1/833E CMP #$FF                ;Aと$FFを減算比較(ステータスレジスタ変更のみ)
$C1/8340 BNE $03    [$8345]      ;ゼロフラグが立っていないとき[$8345]分岐
$C1/8342 BRL $FB59  [$7E9E]      ;フラグにかかわりなく常に分岐[$7E9E]
$C1/7E9E LDA #$4B                ;Aに$4Bをロード(BGMID$4B「ILLUSION…」)
$C1/7EA0 JSR $12FE  [$C1:12FE]   ;[$C1:12FE]へジャンプ

$C1/12FE STA $10    [$00:0310]   ;Aを[$00:0310]に書き込み
(中略)
$C1/1353 JSR $11D8  [$C1:11D8]   ;[$C1:11D8]へジャンプ

$C1/7E9E以降で、$4Bが[$00:0310]に直接書き込まれ、後は$C1/1342以降で共通処理である。

オディオ戦(ピュアオディオ移行)

$C1/7BDE LDA #$1C                ;Aに$1Cをロード(BGMID$1C「PURE ODIO」)
$C1/7BE0 JSR $12FE  [$C1:12FE]   ;[$C1:12FE]へジャンプ

$C1/12FE STA $10    [$00:0310]   ;Aを[$00:0310]に書き込み
(中略)
$C1/1353 JSR $11D8  [$C1:11D8]   ;[$C1:11D8]へジャンプ

ピュアオディオ出現時には$C1/7BDE以降で、$1C[$00:0310]に直接書き込まれ、後は$C1/1342以降で共通処理。



このページをシェアする

上へ