- サウンドドライバに求められる機能
- 高速動作
- 省メモリ
- 音質
続いて省メモリ。Z80のメモリ空間は64KBしかありません、ROMカセットなら、割り込み発生時に切り替えてしまえばこの問題はある程度解決するものの、テープロードが大半でゲーム稼働中はオンメモリが前提となる PC-8001やMZ-80K等では、サウンドドライバとデータが閉める割合は決して小さくありません。そこで、ドライバそのもののサイズを小さくする工夫に加えて、データサイズも小さくする必要があります。
そして音質です。これは往々にしてドライバの機能アップに比例して、音質は向上していきますが、残念ながら実行速度や省メモリが犠牲になっていきます。どこまでの音で許容するのか、この線引きが後々まで尾を引くことになります。そのため、なるべくゲーム制作の早い段階で仕様を決めておくべきでしょう。
- サウンド再生対象のハードウェア調査
PCG8100 の音は PSG ではなく ビープ音(チップは 8253)です。音階の変更が出来るビープです。ハードウェア要件を確認すると
* 音程
* キーのオン/オフ
* 3チャンネル(1チャンネルも考慮)
このような単純な内容となります。MSX や PC-6001 等に搭載されている PSG AY-3-8910 の場合は上記に加えて
* 音量
* エンベロープ
* ノイズ
と、設定できることが多くなります。FM音源はさらに多くなりますが、趣旨から外れていきますのでこの辺りで(苦笑)。以下、3チャンネルがあるハードウェアという前提で話を進めます。
- 呼び出し頻度
PC-8001 では垂直基線割り込みの状態変化を確認して、裏から表に行ったタイミングで処理をするようにすると良いでしょう。垂直帰線が裏側にある瞬間だけ、CPUはクロック通りの速度で動作しますので、もし、高速に処理するとかノイズが出ないように配慮する処理が無ければ。サウンドドライバの呼び出しを裏に回しても宜しいかと思います。
ハードウェア割り込みがある機種の場合、調子に乗って 1/1000 で処理する等と割り込み速度を上げると、ゲーム本体の進行速度に影響が出ます。この辺りはバランスですので、ご自身が判断する必要があります。
- サウンドドライバの全体の流れ

私の場合、サウンドドライバは全体的な処理部 SNDTimer と、チャンネル毎の処理である SNDPlayer に分けて設計します。これは、チャンネルが増えても呼び出しを増やすだけで済みますし、ワークが連続していなくても対応出来る等のメリットがあります。
フローチャート内の汎用カウンタとは、ゲームの全体進行やビブラートやトレモロ等の時系列管理のために使用します。さほど処理時間を食うワケでもないので、このように単純にインクリメントしておきます。SNDPlayer 呼び出しの際は、各チャンネル毎のワークエリアの先頭を引数としてレジスタ渡ししています。
全部でハードウェア的には3チャンネルしかありませんが、仮想4チャンネル目としてSE再生専用を用意しています。実際の発音処理では、効果音が鳴っていれば、3ch(または2ch)を SEチャンネルに置き換えて再生する事で、フルチャンネルで音楽演奏しながら効果音も鳴らせるのです。

実際の処理部であるSNDPlayerの簡易的な構造説明用フローです。ワークエリアとして、現在処理しているコマンドデータアドレス(以下ポインタと略す)があり、それが 0x0000 なら再生していないと判断しています。続いて、今演奏されている音がいつまで鳴り続けるのかという音長カウンタを参照して、ゼロ以外であればデクリメントして現状を維持します。
音長がゼロなら次の発音のための処理に入ります。ポインタから1バイトデータを取得します。同時にポインタは+1更新します。終了コマンドであれば、データアドレスなどを 0x0000 クリアして終了します。コマンドが音階であれば、発音カウント値の取得、設定、音長カウンタ値の初期化を行い、ポインタもワークに格納して終了します。そして、コマンドがそれ以外であれば、その他コマンドの種別判定と処理を行い、再びコマンド取得ループに戻ります。このサンプルフローでは、終了と音階以外には音長しか用意していませんが、ここに音楽性に拘るのなら、ビブラート等のコマンド拡張を行います。
第1回:ASM サウンドドライバの構造
第2回:PCG8100 から発音させる
コメント