MSX用のPSGサウンドドライバです。
z88dk(zcc)でコンパイルできる形にしています。
サポートしている機能は以下となります。
- 効果音の割り込み再生に対応
- 効果音の再生優先度(プライオリティ)を設定可能
- ノイズON/OFF、トーン、ノイズトーン、ボリューム、デチューンに対応
lc2asm.py
で、LovelyComposerで制作したデータを変換して使用可能(制約あり)
以下のURLでサンプルプログラムを用いたドライバの動作確認ができます。
このプロジェクトに含まれているCMakeLists.txt
を編集し、このプレイヤーのソース(psgdriver.asm
)と作成したソースを指定します。
たとえば、サンプルプログラムの場合は以下の定義になっています。
add_source_files(
./src/msx/sample.asm
./src/msx/psgdriver.asm
)
そして、makeファイルを生成するため、プロジェクトのルートディレクトリで以下のコマンドを実行します。(初回のみ、2回目以降は不要)
$ mkdir build && cd build
$ cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/z88dk.cmake ..
ビルドはbuild
ディレクトリで以下のコマンドを実行します。
$ make clean && make
.rom
ファイルはdist
ディレクトリに作成されます。
ソースディレクトリに入り、以下コマンドを実行します。(ソースファイル名は、適宜変更してください)
コマンドはzcc
ですが、アセンブラでもCでも同じです。
includeファイルのパス指定など、他オプションの詳細についてはzcc -h
で表示されるヘルプを参照ください。
$ zcc +msx -create-app -subtype=rom psgdriver.asm sample.asm -o=../../dist/build.rom
z88dkに含まれるz88dk-z80asmや他のアセンブラを利用することも可能です。
詳しくはz88dk-z80asmのドキュメントを参照してください。
他のアセンブラでも、マクロなどz88dk固有の機能はほとんど使用していないため、少しの修正で対応できると思います。
注意 :
以下のラベル定義部分以降についてはワークエリアです。
zccでコンパイルする場合は適切にアドレッシングされますが、そうでない場合はRAM($8000〜など)にアドレッシングされるようにORG指定してください。
- SOUNDDRV_WORKAREA : 120byte
この内訳は以下のようになっています。(配置順は変えないでください)
- SOUNDDRV_H_TIMI_BACKUP : 5byte
- SOUNDDRV_STATE : 1byte
- SOUNDDRV_WK_MIXING_TONE : 1byte
- SOUNDDRV_WK_MIXING_NOISE : 1byte
- SOUNDDRV_BGMWK : 48byte
- SOUNDDRV_DUMMYWK : 16byte
- SOUNDDRV_SFXWK : 48byte
- プログラムソースの先頭で、以下の指定を行います。
EXTERN SOUNDDRV_INIT
EXTERN SOUNDDRV_EXEC
EXTERN SOUNDDRV_BGMPLAY
EXTERN SOUNDDRV_SFXPLAY
EXTERN SOUNDDRV_STOP
EXTERN SOUNDDRV_PAUSE
EXTERN SOUNDDRV_RESUME
EXTERN SOUNDDRV_STATUS
- プログラムの初期処理で、ドライバの初期化ルーチン(
SOUNDDRV_INIT
)をCALLします。- この初期化ルーチンの中で
H.TIMI
フックのコード(5byte)をバックアップし、ドライバを実行するように書き換えを行います。 - アプリケーション側でもH.TIMIフックで実行する処理がある場合、必ずH.TIMIから5バイトのバックアップを取っておき、処理の最後でバックアップしたアドレスにJPしてください。
- なお、アプリケーションでドライバの初期化ルーチンをCALLするのは、H.TIMIフックの書き替え前/後のどちらでも構いません。
- この初期化ルーチンの中で
CALL SOUNDDRV_INIT ; サウンドドライバ初期化
- 次の「ドライバのAPI」を参照ください。
上記の事前準備を行った後は、ユーザープログラムからは以下の手順で制御できます。
SOUNDDRV_BGMPLAY
- BGMの再生を開始する。
- HLレジスタに再生するBGMデータのアドレスを指定する。
LD HL,BGMDATA
CALL SOUNDDRV_BGMPLAY
SOUNDDRV_SFXPLAY
- 効果音を再生する。既にプライオリティの高い効果音が再生中の場合は再生しない。
- HLレジスタに再生する効果音データのアドレスを指定する。
LD HL,SFXDATA
CALL SOUNDDRV_SFXPLAY
SOUNDDRV_STOP
- BGM、効果音の再生を停止する。
CALL SOUNDDRV_STOP
SOUNDDRV_PAUSE
- BGM、効果音の再生を一時停止する。
CALL SOUNDDRV_PAUSE
SOUNDDRV_RESUME
- BGM、効果音の一時停止を解除する。
- 再生中に呼び出した場合は、何も処理しない。
CALL SOUNDDRV_RESUME
SOUNDDRV_STATUS
- ドライバのステータスを取得する。
- bit 0は再生中であれば1、停止中であれば0となる。
- bit 1は一時停止中であれば1、以外は0となる。
LD A,(SOUNDDRV_STATUS)
このドライバで扱うデータ構造は、以下のイメージです。
BGM、効果音共に同じ構成になります。
[BGM/SFX Data]
+- [Priority](1byte)
+- [Track 1 Data Address](2byte)
+- [Track 2 Data Address](2byte)
+- [Track 3 Data Address](2byte)
[Track 1 Data]
[Track 2 Data]
[Track 3 Data]
すなわち、効果音として作成したデータをBGMとして鳴らすこともできますし、その逆も可能です。
また、上記のように、トラックデータの集まりを曲データとしているため、複数のBGM/効果音で同じトラックを使いまわすこともできます。
BGM/効果音データの構成を定義します。
- プライオリティ(1byte):0~255(低~高)、効果音発声時のみ有効、BGMでは無視される。
- トラック1のデータアドレス(2byte):ない場合は
$0000
を設定する。 - トラック2のデータアドレス(2byte):ない場合は
$0000
を設定する。 - トラック3のデータアドレス(2byte):ない場合は
$0000
を設定する。
トラックデータは、以下で構成されます。
コマンド | 意味 | 概要 |
---|---|---|
0〜95 ($00〜$5F) |
ノート番号 (設定値は後述の「ノート番号表」を参照) |
ノート番号の後に音長(n/60)を指定する。 (音長についての詳細は後述の「音長について」を参照) |
200〜215 ($CB〜$D7) |
ボリューム | コマンドの値が0〜15に対応。(PSGレジスタ#8〜#10に設定する値と同じ) 値の設定は不要。 |
216 ($D8) |
ノイズトーン | 216,<値> の形式で指定。値に0〜31を指定。(PSGレジスタ#6に設定する値と同じ) |
217 ($D9) |
ミキシング | 217,<値> の形式で指定。値に0〜3を指定。(bit0=Tone/bit1=Noise、1=off/0=on) 例)%10 = トーンON、ノイズOFF |
218 ($DA) |
デチューン | 218,<値> の形式で指定。値にノートに対する補正値を指定。 |
253 ($FD) |
ループ開始位置 | なし |
254 ($FE) |
データ終端(トラック先頭、またはループ開始位置に戻る) | なし |
255 ($FF) |
データ終端(再生終了) | なし |
ノート番号(音階)には、以下のトーンテーブルの値を設定します。
オクターブ | C | C+ (D-) |
D | D+ (E-) |
E | F | F+ (G-) |
G | G+ (A-) |
A | A+ (B-) |
B |
---|---|---|---|---|---|---|---|---|---|---|---|---|
o1 | $00 | $01 | $02 | $03 | $04 | $05 | $06 | $07 | $08 | $09 | $0A | $0B |
o2 | $0C | $0D | $0E | $0F | $10 | $11 | $12 | $13 | $14 | $15 | $16 | $17 |
o3 | $18 | $19 | $1A | $1B | $1C | $1D | $1E | $1F | $20 | $21 | $22 | $23 |
o4 | $24 | $25 | $26 | $27 | $28 | $29 | $2A | $2B | $2C | $2D | $2E | $2F |
o5 | $30 | $31 | $32 | $33 | $34 | $35 | $36 | $37 | $38 | $39 | $3A | $3B |
o6 | $3C | $3D | $3E | $3F | $40 | $41 | $42 | $43 | $44 | $45 | $46 | $47 |
o7 | $48 | $49 | $4A | $4B | $4C | $4D | $4E | $4F | $50 | $51 | $52 | $53 |
o8 | $54 | $55 | $56 | $57 | $58 | $59 | $5A | $5B | $5C | $5D | $5E | $5F |
音長は以下で求めることが可能です。
- 1秒あたりの発音数:<テンポ>/60秒
- 4分音符の音長:60/(1秒あたりの発音数)
- 8分音符の音長:4分音符の音長/2
- 16分音符の音長:8分音符の音長/2
例)テンポ=120の場合 (=1分間に4分音符を120回鳴らす速度)
- 1秒あたりの発音数:120 / 60秒 = 2
- 4分音符の音長:60 / 2 = 30
- 8分音符の音長:30 / 2 = 15
- 16分音符の音長:15 / 2 = 7.5
データに設定する値は整数なので、端数が出る場合は、ノートの音長の合計で辻褄が合うように調整してください。
作曲ツール「LovelyComposer」で作成したデータを、当ドライバ用のデータに変換するツールを用意しています。(src/python/lc2asm.py
)
pythonが必要ですので、別途インストールしてください。
なお、LovelyComposerは以下のサイトで購入できます。
BOOTH
itch.io
lc2asm.pyのあるディレクトリに移動し、以下で実行すると、.jsonlファイルのある場所に.asmファイルを作成します。
python lc2asm.py <jsonlファイルパス>
作成された.asmファイルは、ソースに直接取り込むか、INCLUDE
してください。
指定可能なオプションは以下のとおりです。
- --outfile/-o : 出力ファイルパスを指定
- --force/-f : 出力ファイルを上書きする
- --version/-v : バージョンを表示する
- --help/-h : ヘルプを表示する
LovelyComposerの以下の機能に対応しています。
- 各ノートのボリューム指定に対応しています。
- ループ開始・終了の指定に対応しています。
- 1ページ単位のノート数の変更、テンポの変更に対応しています。
LovelyComposerの機能に対し、作成されるデータには以下の制約があります。
- 利用できる音色は、「SQUARE WAVE」「NOISE」の2つです。
- 利用できるチャンネルは、1〜3の3つです。(チャンネル4、コードチャンネルは無視されます)
- テンポは処理の都合上、完全に同一にはならず、近似値になります。(違和感はないはずです)
- パン指定は無視されます。
2023/06/11 Version 1.6.1
- lc2asm.py
- 出力ファイルのラベルがフルパスになっていた不具合を修正
2023/06/10 Version 1.6
- lc2asm.py
- 入力・出力ファイルのパス周りの処理修正、オプションの追加
2023/02/12 Version 1.5.1
- psgdriver.asm
- include廃止、ワークエリアの先頭にラベル追加
2022/08/14 Version 1.5.0
- psgdriver.asm
- 一時停止(SOUNDDRV_PAUSE)/再開(SOUNDDRV_RESUME)のAPIを追加
- ドライバの状態を取得するAPI(SOUNDDRV_STATUS)を追加
2022/08/06 Version 1.4.1
- psgdriver.asm
- includeのパス区切り文字のミスを修正
2022/07/24 Version 1.4.0
- psgdriver.asm
- SFX再生時にBGMのプライオリティも判断するように修正
(プライオリティを最高に設定したBGMの演奏中はSFXが再生されなくなります)
- SFX再生時にBGMのプライオリティも判断するように修正
2022/05/29 Version 1.3.0
- psgdriver.asm
- バージョン表記をセマンティックバージョニングに合わせて修正
- H.TIMIフックのコールチェインができるよう、バックアップを保存し処理の最後でCALLするように修正。
2022/05/07 Version 1.20
-
psgdriver.asm
- ボリュームデータの構成変更、併せて他コマンドのデータ変更。1.1までと互換性がないのでご注意ください。
-
lc2asm.py
- ボリュームデータの構成変更、併せて他コマンドのデータ変更に対応。
2021/12/04 Version 1.11
- psgdriver.asm
- ページ単位のノート数・SPEED値の変更、全ページ数の変更に対応。
2021/11/28 Version 1.10
-
psgdriver.asm
- LovelyComposerのループ開始・終了位置の指定に対応
-
lc2asm.py
- ループ終了の指定があるときはループあり、指定がない場合はループ無しのデータを出力するように修正
2021/11/19 Version 1.00
-
psgdriver.asm
- 初期作成
-
lc2asm.py
- 初期作成