シーケンスデータの構造

スーパードンキーコング および、Donkey Kong Country で使用されているRareWare Sound Driver のシーケンスデータの構造について説明します。
APU RAM上の各変数のアドレスについては APU RAMマップ を参照してください。

表記

このマニュアルでは、コマンドの構文を次のように表記します。

0x02, sbyte left, sbyte right

先頭がコマンドのバイト値、続いてパラメータの型と名前をデータ中の順に並べています。型は byte(符号なし8ビット)、sbyte(符号付き8ビット)、ushort(符号なし16ビット、リトルエンディアン)です。ただし、ノートの長さを16ビットで指定する場合のみビッグエンディアンになります。
アドレスはすべてAPU RAM上の絶対アドレスで、シーケンスデータ内のオフセットではありません。

シーケンスデータの配置

シーケンスデータは APU RAM の $12A0 から配置されます。ROMに格納されているシーケンスファイルは、先頭の4バイトのヘッダに従ってAPU RAMへ転送されます。前半2バイトは転送先(エントリポイント)で常に $12A0、後半2バイトはデータのサイズです。

ヘッダ

シーケンスデータの先頭には、曲のヘッダが置かれています。

オフセット型内容
+$00ushort[8]各BGMチャネル(0~7)のシーケンスの開始アドレス
+$10byteテンポの初期値
+$11byteSEテンポの初期値

曲の初期化時には8チャネルすべてが動作を開始します。使用しないチャネルも、コマンド 0x00 だけのシーケンスなど、有効なシーケンスを指している必要があります。

SE

SEデータ領域の先頭($2380)には、各SEのシーケンスの開始アドレス(ushort)がSE番号順に並んでいます。テーブルに登録数は格納されていません。
SE番号は2倍した値の下位8ビットで表を引くため、有効なSE番号は $00~$7F です。

SEは、CPUからの指示で指定したBGMチャネル n に対応するSEチャネル n+8 で再生されます。SEのシーケンスはBGMと同じ形式で、同じコマンドを使用できます。
SEの開始時、SEチャネルの音量は左右とも $7F、ADSRは ADSR1 = ADSR2 = 0に初期化されます。SEの再生中、BGMチャネル n はシーケンスの処理だけを続け、DSPへの書き込みを行いません。

イベント

シーケンスはイベントの並びです。イベントの1バイト目で種類が決まります。

1バイト目種類
0x00~0x30コマンド。パラメータの数はコマンドごとに決まっている
0x80休符
0x81~0xFFノート

コマンドは処理に時間がかからず、続くイベントが同じティックのうちに読み込まれます。時間が進むのはノートイベントと休符イベントだけです。そのため、ノートや休符を含まない無限ループを作るとドライバが停止します。
0x31~0x7Fを実行すると、コマンド処理テーブルの範囲外または不正なアドレスへジャンプし、ドライバが暴走します。

ノートの長さ

ノートイベントと休符イベントの長さはティック単位で指定します。長さの指定方法には次の3つのモードがあり、チャネルごとに切り替えます。

モード長さの指定切り替えコマンド
通常各イベントに1バイト-
デフォルト・デュレーション各イベントでは指定せず、コマンド 0x06 で設定した長さを使用0x06, 0x07
16ビット・デュレーション各イベントに2バイト(ビッグエンディアン)0x2B, 0x2C

デフォルト・デュレーション・モードと16ビット・デュレーション・モードを同時に有効にした場合は、コマンド 0x06 の引数が2バイトになり、各イベントでは長さを指定しません。

以下は、同じ内容を3つのモードで記述した例です。

// 通常
A5 10  A7 08  A9 08  AA 08  B1 10  00

// デフォルト・デュレーション
A5 10  06 08  A7  A9  AA  07  B1 10  00

// 16ビット・デュレーション
2B  A5 00 10  A7 00 08  A9 00 08  AA 00 08  B1 00 10  00

テンポとティック

ドライバはタイマー0の周期で動作します。タイマー0の分周値は初期値 60(約133.3Hz、約7.5ms周期)で、コマンド 0x2A で変更できます。
タイマー周期ごとにBGMとSEのテンポ加算器にそれぞれのテンポを8ビットで加算し、桁あふれが起きた側のシーケンスを1ティック進めます。
したがって、1秒あたりのティック数は (8000 ÷ タイマー0の分周値) × テンポ ÷ 256 です。たとえば四分音符を16ティックとした場合、テンポ(BPM)は 約 1.95 × テンポ になります。

エフェクトの時間単位

ピッチベンド、ビブラート、トレモロの時間(ディレイや間隔)は、テンポではなくタイマー周期を単位として数えられます。そのため、テンポを変えてもエフェクトの速さは変わりません(コマンド 0x2A でタイマー周期を変えると変わります)。

サブルーチン

コマンド 0x04 でサブルーチンを呼び出し、コマンド 0x05 で戻ります。コール・スタックはチャネルごとに8段で、深さの確認は行われません。
曲のループには コマンド 0x03 を使用します。ゲームの状況による分岐には コマンド 0x2D を使用します。

処理の流れ

タイマー周期ごとに、BGMチャネル0~7について次の処理を行います。

  1. BGMのティックが発生した場合は、残りティック数を1減らし、0になればイベントを読み込む。コマンドは続けて読み込み、ノートイベントか休符イベントで止まる。
  2. エフェクト(ピッチベンド、ビブラート、トレモロ)を処理する。
  3. 対応するSEチャネルでSEが再生中であれば、SEのティックについて同じ処理を行う。

BGMのティックが発生した場合は、チャネルの処理の前にフェードアウトの処理(コマンド 0x29)も行います。

参照

シーケンスコマンド一覧
APU RAMマップ