NDP (PSG Driver for MSX) Programmed by naruto2413 -------------------------------------------------------------------- #MSXNDP version 1.00 ドライバ仕様 あくまで現バージョンの仕様であり、今後の更新で変更される可能性があります。 特にアドレス関連は流動的なので、組み込みの際はご注意ください。 使用条件は、 1_基本説明.txt の「自作ソフトにドライバを組み込む際の条件など」をご参照ください。 【driverフォルダのファイル構成】  NDP .ASM -- 下記の2ファイルをインクルードしてアセンブルするためのファイル  NDP_DRV.ASM -- ドライバ本体  NDP_WRK.ASM -- コールエントリ/ワークエリア/テーブル  NDP .BIN -- 上記ソース群をアセンブルしたドライバ  ドライバ本体の中では自己書換を行っていませんので、ROMにも置けるはずです(未検証)。  ワークエリアは頻繁に書き換えますので、原則としてページ3のRAMに配置してください。 ▼メモリ配置 (標準の場合) 4000-7FFFH 曲データ (デフォルト) 下記注意事項あり C000- ドライバ本体 ドライバのADRSETエントリにより曲データの開始アドレスを変更できますが、 タイマ割り込み実行後はページ0(0000-3FFFH)がメインROMになるため、 ページ0に曲データを配置することはできません。 スロット構成によってはページ1(4000-7FFFH)にも置けないことがあります(要検証)。 必要に応じてタイマ割り込みフックへの接続をインタースロットコールにするなど、 ソースを改造して対策していただければ幸いです。 ▼エントリ (標準の場合) これらのエントリは現時点のものであり、今後の更新で変更される可能性がありますのでご注意ください。 【一覧】 C000H NDPINI ドライバ初期化 (タイマ割り込みフックにドライバを接続) C003H MSTART 演奏開始 (ワークエリアをゼロクリアし演奏開始。フックは操作しない) C006H MSTOP 演奏停止 (演奏停止してPSGレジスタを初期化。フックは操作しない) C009H INTRPT 割り込み処理 (フックに接続せずに自前で割り込みルーチンを呼ぶ際に使用) C00CH U_ADR (※)曲データ開始アドレス設定 (引数で指定。デフォルトの04000Hなら設定不要) C00FH U_OFF1 (※)Ch.A 一時ミュート (ミュートするフレーム数を引数で指定 [2~254/1=解除/255=常時ミュート]) C012H U_OFF2 (※)Ch.B 〃 C015H U_OFF3 (※)Ch.C 〃 C018H U_MV (※)マスター音量オフセット (引数で渡した値を音量値から減算する) C01BH U_MFO (※)フェードアウト (引数で渡したフレーム数ずつフェードアウト) C01EH U_MFI (※)フェードインしながら演奏開始 (引数で渡したフレーム数ずつフェードイン) C021H U_SE (※)効果音発音 (効果音データのアドレスを引数で指定) C024H CH1OFF Ch.A 一時ミュート (D←ミュートするフレーム数 [2~254/1=解除/255=常時ミュート]) C027H CH2OFF Ch.B 〃 C02AH CH3OFF Ch.C 〃 C02DH MVSET マスター音量オフセット (A←音量値から減算する値) C030H MFOSET フェードアウト (A←各段階のフレーム数) C033H RDSTAT 演奏状態→A (0:停止中 1:演奏中) C036H RDENDT 各トラックの演奏が終端まで達したかどうか→A (0000321Rのビットフィールド) C039H RDLOOP 曲がループした回数→A (曲データの+0BHを見て無限ループしない曲なら演奏終了時に255が返る) C03CH ADRSET 曲データ開始アドレス設定 (DE←アドレス。デフォルトの04000Hなら設定不要) C03FH MPLAYF フェードインしながら演奏開始 (A←各段階のフレーム数) C042H SEPLAY 効果音発音 (DE←効果音データのアドレス) C045H VSET 音色データをドライバに反映 (HL←音色定義データのアドレス) C048H SYSVER ドライバのバージョン番号→HL (L=小数点以下、H=整数部。整数部が0なら0.9として扱う) C04BH NDPOFF ドライバ終了 (タイマ割り込みフックからドライバを切り離して発音停止) C04EH SETHF タイマ割り込みフック接続フラグ←A C051H KSSPLY 退避したH.TIMIをRETで潰して演奏開始 (KSSプレイヤー用) ※ エントリ名の先頭に「U_」が付いているものは、BASICのUSR文から引数を渡す前提となっています。 [例] DEFUSR3=&HC00F:U=USR3(60) 'Ch.Aを1秒ミュート 【詳細】 NDPINI (C000H) ・ドライバ初期化 タイマ割り込みフックにドライバを接続し、タイマ割り込みフック接続フラグを1にします。 ドライバのロード後に必ず一度実行してください。 実行後、EI状態となります。 ※タイマ割り込みフック接続フラグが0以外のときは処理を行わずにRETします。 (すでにドライバが接続されている状態で多重に接続しようとすると暴走するため、その対策です) ※ROM化するなど、RAMの状態が不定な場合はNDPINIをCALLする前に後述のSETHFでフラグを0にしておいてください。 (ディスクからロードする場合はあらかじめ0が設定されますので、別途設定する必要はありません) ※下記のエントリはすべてタイマ割り込みにドライバが接続されている前提で処理されます。 MSTART (C003H) ・演奏開始 演奏用のワークエリアを初期化し、演奏開始します。 タイマ割り込みフックの操作は行いませんので、必ずNDPINIを実行した後にコールしてください。 実行後、EI状態となります。 MSTOP (C006H) ・演奏停止 演奏停止し、PSGレジスタを規定値で初期化します。 タイマ割り込みフックの操作は行いませんので、必ずNDPINIを実行した後にコールしてください。 実行後、EI状態となります。 INTRPT (C009H) ・割り込み処理 タイマ割り込みフックにドライバを接続せずに自前で割り込みルーチンを呼ぶ際に使用します。 通常はNDPINIとNDPOFFでフックへの接続と切り離しを行うため、このエントリは使用しません。 実行後、EI状態となります。 CH1OFF (C024H) ・Ch.A 一時ミュート 一時的に該当チャンネルの音量を0、ミックスモードをトーンにします。 実行中はレジスタの操作を行わなくなりますので、自前で効果音を処理する場合に有用です。 Dにミュートするフレーム数を入れてCALLしてください(2~254。255は常時ミュート)。 1でレジスタを復帰せずに即ミュート解除となります。通常は2以上を指定してください。 実行後、EI状態となります。 CH2OFF (C027H) ・Ch.B 一時ミュート 使用方法はCh.Aと同じです。 実行後、EI状態となります。 CH3OFF (C02AH) ・Ch.C 一時ミュート 使用方法はCh.Aと同じです。 実行後、EI状態となります。 MVSET (C02DH) ・マスター音量オフセット Aレジスタに0~15を入れてCALLすると、曲データの音量値から指定値だけ減算して音量レジスタに書き込みます。 演奏中の音量をリアルタイムで絞る際などに有用です。0で曲データ本来の音量となります。 MFOSET (C030H) ・フェードアウト Aレジスタにフレーム数を入れてCALLすると、1段階ごとに指定フレームずつ待ちながらフェードアウトします。 RDSTAT (C033H) ・演奏状態の取得 CALLすると、演奏中なら1、停止中なら0がAレジスタに入ります。 RDENDT (C036H) ・各トラックの終端チェック CALLすると、各トラックの演奏が終端まで達したかどうかがAレジスタに入ります。 0000321Rのビットフィールド。 ※全トラックが終端に到達すると0にリセットされるため、曲を最後まで演奏したかどうかのチェックには非推奨 RDLOOP (C039H) ・ループした回数、または演奏終了したかどうかの取得 CALLすると、曲全体のループした回数がAレジスタに入ります。 ループしない曲の場合、演奏終了したら255になります。 ADRSET (C03CH) ・曲データ開始アドレス設定 DEレジスタに曲データ開始アドレスを入れてCALLすると設定されます。 デフォルトでは4000Hがセットされているため、変更しない場合にはこのエントリは使用しません。 なお、タイマ割り込み実行後はページ0(0000-3FFFH)がメインROMになるため、 ページ0に曲データを配置することはできません。 また、スロット構成によってはページ1(4000-7FFFH)にも置けないことがあるようです。 その場合はページ2(8000-BFFFH)をご使用ください。 MPLAYF (C03FH) ・フェードインしながら演奏開始 Aレジスタにフレーム数を入れてCALLすると、 指定フレームごとにマスターボリュームを加算しながら演奏開始します。 SEPLAY (C042H) ・効果音発音 DEレジスタに効果音データのアドレス(※)を入れてCALLすると発音されます。 ※効果音データは、MMLエディタ上で#ADDRESS-SEヘッダを設定せずに保存すると  先頭に個数(1バイト)とデータ先頭からの相対アドレス(2バイト×個数)が付加されますので、  適宜ご活用ください。 VSET (C045H) ・音色定義データをドライバに反映 音色定義データ(音色、リズム音色、ビブラート、ピッチエンベロープ、ノートエンベロープを ひとまとめにしたデータ)のアドレスをHLレジスタに入れてCALLすると、ドライバに反映されます。 SYSVER (C048H) ・ドライバのバージョン番号を取得 CALLすると、バージョン番号がHLレジスタに入ります。 Lレジスタは小数部、Hレジスタは整数部ですが、整数部の値が0のときは0.9として扱います。 [例1] H=0、L=3 の場合 … バージョン0.9.3 [例2] H=1、L=0AH の場合 … バージョン1.10 NDPOFF (C04BH) ・ドライバ終了 タイマ割り込みフックからドライバを切り離し、発音を停止し、タイマ割り込みフック接続フラグを0にします。 プログラム終了時に実行してください。 実行後、EI状態となります。 ※タイマ割り込みフック接続フラグが0のときは処理を行わずにRETします。 SETHF (C04EH) ・タイマ割り込みフック接続フラグのセット Aレジスタに任意の値を入れてCALLすると、その値がタイマ割り込みフック接続フラグに書き込まれます。 実行後、EI状態となります。 ※ディスクからNDP.BINをロードする場合は自動的にセットされますので、このエントリを使う必要はありません。  ROM化するなど、RAMの状態が不定な場合はNDPINIをCALLする前に必ず0をセットしておいてください。 ▼曲データ構造 +00 01 トラックR開始アドレス(先頭オフセット値) +02 03 トラック1開始アドレス(先頭オフセット値) +04 05 トラック2開始アドレス(先頭オフセット値) +06 07 トラック3開始アドレス(先頭オフセット値) +08 09 音色定義データトラック開始アドレス(4000H未満なら先頭オフセット値、4000H以上なら実アドレス) +0A 予約 +0B ビット0が立っていたら無限ループするトラックが存在しない、ビット1が立っていたらメタデータが存在する +0C データ作成に使用したコンパイラのバージョン番号(小数部) +0D データ作成に使用したコンパイラのバージョン番号(整数部) ※0の場合は0.9として扱う +0E ~ データエリア 音色トラック開始アドレスを除き、データ内に絶対アドレス値は持たず、すべて相対アドレス値になっています。 (データをリロケート可能にするため) 【メタデータについて】 +0BHのビット1が立っている場合、曲データの+0EHからテキスト情報が存在します。 #TITLE、#COMPOSER、#ARRANGER、#PROGRAMMER、#MEMOの順にShift_JISで格納されます。 各内容の終端は0FFHです。 (エディタの [出力]→[テキスト情報を曲データ内に格納する] を無効にすると出力されません) 【バージョン番号の例】  +0C +0D  03H 00H = バージョン0.9.3  0AH 01H = バージョン1.10 【効果音データについて】 基本的なフォーマットは曲データと同じですが、音色定義データなどが曲データと共用、 かつ無限ループも存在しないため、+08~0Eの内容は含みません。 なお、MMLエディタ上で#ADDRESS-SEヘッダを設定せずに効果音データを保存すると 先頭に個数(1バイト)とデータ先頭からの相対アドレス(2バイト×個数)が付加されますので、 適宜ご活用ください。 ◆ROM化などにあたっての諸注意 ・ドライバ本体(NDP_DRV.ASM)の中では自己書き換えなどは行っていませんので、ROM上に置くことができます。 ・ワークエリア(NDP_WRK.ASM)は随時ドライバによって書き換えられますので、コールエントリを除いてRAM上に置く必要があります。 ・初期化の必要なワークエリアはMSTARTエントリ内で設定されますので、原則として別途初期化する必要はありません。 ・NDPINIエントリとNDPOFFエントリでドライバの接続と解除を行う際、初回はフック接続フラグが0になっていることを前提としています。  ROM化するなど、RAMの値が不定になる条件でNDPINIエントリを使う場合は初回実行前にSETHFエントリで0にしておいてください。  (ディスクからNDP.BINをロードする場合はあらかじめ0が設定されますので、特にSETHFは実行しなくても問題ありません) ・アドレスを変更しての再アセンブルなどは特に制限しませんが、フックをインタースロットコールにするなどの対策が必要となります。 ▼データ仕様 ・Tr.1~3 00~5FH 音程。00=休符、05F=08B-。 続くデータが音長。音長が255の場合は次の1バイトも音長。 値と音程との相関は次の通り。 C C+ D D+ E F F+ G G+ A A+ B 01 02 03 04 05 06 07 08 09 0A 0B 0C O1 0D 0E 0F 10 11 12 13 14 15 16 17 18 O2 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 O3 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 O4 31 32 33 34 35 36 37 38 39 3A 3B 3C O5 3D 3E 3F 40 41 42 43 44 45 46 47 48 O6 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 O7 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 O8 60~6FH 音量。60=v15 ~ 6F=v0。 70~7FH 音色。70=@0 ~ 7F=@15。 80H ピッチエンベのディレイ値を書き換える (続く1バイトがディレイ値) 81H ミックスモード。続く1バイトが0=無音 1=トーン 2=ノイズ 3=トーン+ノイズ。 82H ピッチエンベロープ指定。 続く1バイトによって機能が決まる。 0=OFF ビット0~4 (1~16)=ピッチエンベロープ番号 ビット5が有効なら元の音程からの相対値、無効なら前のフレームからの相対値 ビット6が有効ならディレイカウンタだけ進めてピッチは変更しない(疑似ポルタメント時に処理させないため) ビット7が有効ならキーオフ時に音程を戻す 83H ノイズ周波数。続く1バイトで値を指定(ノイズ周波数+32を指定する必要がある)。 84H レガートオフ。 85H レガートオン。 86H Q(ゲートタイム)、またはQ+(ゲートタイム加算)指定。 続く1バイトは割合(0~8)。 ※0ならレガートオン。その状態で0以外を指定するとレガートオフ。 87H デチューン(1バイト版)。続く1バイトでデチューン値。 88H ポルタメント。続く1バイトで変化量。0でOFF。 89H 相対デチューン。続く2バイトで相対デチューン値。 8AH リリースディレイOFF。 8BH リリースディレイON。音符を進めるフレーム数はデフォルト指定 (255フレーム) 8CH リリースディレイON。続く1バイトは音符を進めるフレーム数 (255で進めない) 8DH リリース音量。 続く1バイトは、ビット7が0ならリリース時に引く音量を設定。 ビット7が1なら下位5ビットの値で現在のリリース音量を即座に書き換える(設定値には影響しない)。 8EH デチューン(2バイト版)。続く2バイトでデチューン値。 8FH ピッチエンベのディレイカウンタだけ進めてピッチを変更しないモードをワークのピッチエンベ番号に設定する。(続く1バイトが0なら無効、1なら有効) 90~9FH ハードエンベロープタイプ。下位4ビットはエンベロープ番号。続く1バイトは音量を半減するフレーム数。 A0H ハードエンベロープ周期。続く2バイトが値。 A1H 直後の1音のみにポルタメントをかける。 続く2バイトがポルタメント値(小数部+整数部)。さらに次の1バイトが開始音程(01~5FH)。 A2H @Q(ゲートタイム2)指定。 続く1バイトでフレーム数を指定。0~128のときは減算、129~255のときは128引いた値を加算。 A3H サスティン(リリースレート)。続く1バイトがサスティン値(リリースカウンタ)。0でOFF。 A4H ノートエンベロープ指定。続く1バイトが0=OFF、1~16=ノートエンベロープ番号。 A5H 音量インターバル。続く1バイトが0=OFF、1~127=音量加算フレーム数、128~255=音量減算フレーム数。 A6H 周波数テーブル再設定。続く1バイトがノート番号*2、さらに続く2バイトがピッチレジスタの値。 A7H 音量インターバル到達音量設定。続く1バイトが値。 A8H ポルタメントピッチ設定。続く1バイトがノート番号。 A9H リリースディレイのピッチのみリセット。 AAH @Q%(固定ゲートタイム)指定。続く1バイトでフレーム数を指定。 ABH パラメータ退避・復帰。 続く1バイトの下位7ビットがワークエリアのオフセット。bit7が0なら退避、1なら復帰。 ※現状、下位7ビットは見ずに音量(+3)に決め打ち ACH 効果音を発音。 続く2バイトが効果音データのアドレスで、4000H以下なら曲データの先頭アドレスからの相対値。 B0~BFH 相対音量加算。 C0~CFH 相対音量減算。 F0H フェードアウト。続く2バイトでフレーム数とループ数を指定。 F1H リピート開始。 F2H リピート脱出。 F3H リピート終了。続く1バイトがリピート回数。 FCH Yコマンド。続く1バイトがレジスタ、次の1バイトがデータ。 FDH スロー再生。続く1バイトがスロー再生用パラメータ。(割り込みのたびにローテートして1ならドライバ本体を呼ばない) FEH 早送りフラグ操作。続く1バイトがフラグ。(0以外で早送りON、0でOFF) FFH トラック終了。 続く2バイトが0000H以外ならループポイントの相対アドレス。(曲データの先頭アドレスに加算) ・Tr.R 00H 休符。 001nnnnnB (20-3FH) リズム発音 (nはリズム音色番号。0~25) 010nnnnnB (40-5FH) リズム相対音量減算 (nはリズム音色番号。0~25。31で全リズム) 011nnnnnB (60-7FH) リズム相対音量加算 (nはリズム音色番号。0~25。31で全リズム) 101nnnnnB (A0-BFH) リズム音量 (nはリズム音色番号。0~25。31で全リズム) F0H フェードアウト。Tr.1~3と同じ。 F1H リピート開始。 F2H リピート脱出。 F3H リピート終了。続く1バイトがリピート回数。 F4H 割り込みトラック選択。続く1バイトがトラック番号(3=CH.A 2=CH.B 1=CH.C) FCH Yコマンド。Tr.1~3と同じ。 FDH スロー再生。Tr.1~3と同じ。 FEH 早送りフラグ操作。Tr.1~3と同じ。 FFH トラック終了。 続く2バイトが0000H以外ならループポイントの相対アドレス。 ・音色定義データトラック 00~15 音色番号(このアドレス+1をドライバ初期化時の音色アドレステーブルに設定) データ長(1バイト)と データ(任意バイト)が続く 16~47 リズム音色番号(このアドレス+1をドライバ初期化時の音色アドレステーブルに設定) データ長(1バイト)と データ(任意バイト)が続く 48~63 ピッチエンベロープ番号(このアドレス+1をドライバ初期化時の音色アドレステーブルに設定) データ長(1バイト)と データ(任意バイト)が続く 64~79 ノートエンベロープ番号(このアドレス+1をドライバ初期化時の音色アドレステーブルに設定) データ長(1バイト)と データ(任意バイト)が続く 255 トラック終了 ・音色データ 0n~9nH ウェイト数 n=音量(0~F) A0H 1フレームウェイト A1H 周波数を0にする A2H 続く1バイトでピッチエンベロープ値を指定 A3H 周波数を元の値に戻す A4H 続く1バイトでノートエンベロープ値を指定 A5H 続く1バイトで相対音量変化フレーム数を指定(1~127でnフレームずつ加算、-1~128でnフレームずつ減算) B0H~BFH ハードエンベロープ(下位4ビットがR#13に) CnH n=0~3 トーン・ノイズ設定 (n=4 続く1バイトがハードエンベロープ周期) ※未実装 D0~EFH ノイズ周波数(下位5ビットがR#6に) FnH 終端(演奏ポインタをnバイト戻す) ・リズム音色データ 01H 音量(続く1バイトが音量) そのまま書き込まずにトラックの音量設定を考慮して加減算 02H ピッチ書き込み(続く2バイトがピッチ。ここだけビッグエンディアン) 06~0FH レジスタ番号 R#6 ノイズ周波数 R#11,12 エンベロープ周期 R#13 エンベロープ波形 続く1バイトが書き込みデータ 10H 1フレーム待機 20~23H ミックスモード(20H=OFF 21H=トーン 22H=ノイズ 23=トーン+ノイズ) FFH 終端 ・ピッチエンベロープデータ 1バイト目 ウェイト数 (1=ウェイトなし 2~=1フレーム~) 2バイト目以降 データ データ内容 00-7FH 0 ~ 127 (前フレームからの相対ピッチ) 81-FFH -127 ~ -1 (〃) 80H 続く1バイトは参照アドレスを戻すバイト数 ・ノートエンベロープデータ 00-7FH 0 ~ 127 (半音単位) 81-FFH -127 ~ -1 (〃) 80H 続く1バイトは参照アドレスを戻すバイト数。0ならノートエンベロープ終了(キーオンで再開)