Gigamix Online

懐かしの8bitおもちゃPC「MSX」を骨までしゃぶり尽くそう。MSXの最新ニュース、ブログ、自作ソフトの配布など。

MGSDRV プログラムインターフェイス(API) 仕様書

 最近MGSDRVに関するAPI・プログラミングのお問い合わせが増えてきていますので、「プログラムインターフェイス(API)仕様書」をこちらへ転載いたします。

 ここで掲載する内容は当サイトの「ダウンロード」で配布しているアーカイブと同等です。

gigamix.jp

 なお、当サイトの仕様書に対応するMGSDRVのバージョンは 3.15 です。2020年10月現在の最新バージョンは 3.20 ですが、APIに関しては 3.15から変更ありません。

ドキュメントヘッダ

項目 内訳
タイトル MGSDRV v3.15仕様書
カテゴリ テキストファイル
ファイル名 MGSDRSPC.LZH
著作者 Ain
動作環境 Shift-JIS形式のファイルが読めるマシン
圧縮形式 -lh5-
転載の可否 可能

v3.15の仕様書です。.relは別配布にしました(本アーカイブには含まれていません)。

<< Filename:MGSDRSPC.LZH >>

Ain

MGSDRVプログラムインターフェイス仕様書(ver3.15用)

始めに

 本仕様書は外部からMGSDRVを使用するにあたって必要な情報について記述しています。MGSDRV対応の外部プログラム(誰か作って下さい(笑))を作成される際や、ソフトに組み込んで使用される場合などの資料として利用して下さい。

 MGSDRVには以下のような特徴があります。

  • FM、PSG、SCCを最大で17音まで演奏可能(FMとSCCは無くても動作)
  • DOS/BASICどちらの環境でも動作可能
  • RAMなしSCC(スナッチャー以外のSCC)も自動的に検索
  • 完全リロケーターブルな演奏データ(いくつものデータをオンメモリで扱えます)
  • 任意のトラック毎に中断、再開ができる(効果音出力も可能)
  • Turbo Rの高速モードに対応(自動判別)
  • マスタ音量を自由に操作可能(トラック独立、全体の2系統)

ver3.14からの変更点

  • 曲データ用セグメントの最大数が10個になった(常駐時)。
  • プライマリスロットにしか常駐しないようになったので、ij_chgdrv, ij_revdrv, ij_calmgs でスロット切り替えを行わないようにした。このためMGSDRVを使用するソフト側がスロットをプライマリ以外に切り替えていると動作しなくなる可能性がありますが、ほとんど大丈夫でしょう^^;
  • _MSVSTのバグを直したつもりが、またバグっていたので直した(^^;;
  • 常駐部のデータブロックの構造を変更した。また記述が間違っていたので直した。

MGSDRVの構造

 MGSDRVは演奏以外の処理はほとんど行ないません。ディスクから演奏データを読み込んだり、演奏開始の前に割り込みを接続するなどの処理はユーザ側で処理しなければなりません。これらのすべての処理を行なってしまうと、特定の環境で不都合が発生する可能性があるためです。割り込みの接続に関して、MSXでは必ずしもH.TIMIにフックをセットする必要はありませんし、ディスクから演奏データを読み込むにしてもFCBを使用する以外に様々な方法があります(論理セクタをアクセスするなど)。

 スロット切り替えに関しても自分自身が必要な場合のみ(SCC音源のアクセス)しか行ないませんので、演奏データが置かれているページに切り替えたりするのは、これもユーザの責任になります。

 BIOSは_SYSCKでRDSLT,WRSLT,ENASLT,CALSLTが使用されます。他のルーチンではBIOSをアクセスしませんので、ページ0がどのように状態でも動作します。スロットとセグメントの状態はすべてのルーチンで保存されます。

スタックポインタおよびMGSDRVの配置アドレスについて

 MGSDRVはSCCをアクセスする際に、内部スタックに切り替えますので、スタックポインタは何処に置いても構いません。ユーザ側ではスタックを最低32バイトは用意しておいて下さい(ルーチンによってはスタックを大量に消費します)。

 SCCアクセス時は、ページ2を直接切り替えますので、MGSDRV自体はページ2に置くことはできません。それ以外のアドレスなら何処へでも配置可能です。ページ0に置くことも可能ですが、一部のMSX/MSX2ではページ0をインタースロットコール出来ないマシンがあるらしい(詳細は不明)ので注意して下さい。

演奏データについて

 MGSDRV version 3で演奏可能なデータはヘッダに"MGSxxx"(xxはバージョン番号)と書かれているものに限ります。これは、MGSCで作成されたものかMGSCNV.COMでversion 3へコンバートされたものです。ヘッダはTYPEコマンドで表示できます。

 演奏データは最大16kバイトになります。実際は16kバイトを超える演奏データでも正常に処理されますが、MGSCでは16kバイトまでしか作成しません。_PLYSTルーチンでは演奏データがversion3のものであるかは判断していません(これらは演奏とは直接関係ないため)。必要ならば事前に_DATCKをコールして演奏できるかどうかを確認して下さい。

 ヘッダはASCIIヘッダ(取りあえずこう呼ぶことにします)とバイナリヘッダに分離されます。ASCIIヘッダはファイルの先頭からコードまでを示し、前述したバージョン番号とタイトル名などが入っています。バイナリヘッダとはMGSDRVが演奏に必要なデータを保存しているところです。ASCIIヘッダはバージョンチェックとタイトル名の参照に用いられるだけで、演奏時には必要ありません。例えば、バージョンエラーが絶対に起こらないようなソフト(読み込むデータが決まっているもの)では、このヘッダを取り除いても構いません。ただし、_DATCKはASCIIヘッダを見て判断しているため、使用すると必ずエラーを返します。

 MGSARC.COMで圧縮されたデータを使用する場合には、演奏データ用領域を16kバイト確保しておかなければなりません(与えられたアドレスから16kバイトが展開用ワークエリアとして使用されます)。ソフトに組み込んで使用する場合は無圧縮データを使用する方がいいでしょう。

 演奏データは、MGSDRV自体と重ならないアドレスなら何処へでも置くことができます。

MIB (Mgsdrv Information Block)について

 MIB(Mgsdrv Information Block)は、アプリケーションからアクセス可能なワークエリアです。先頭アドレスは_SYSCKで獲得できます。主にドライバ全体に関する情報を保持しています。「ラベル」はソースプログラム内で使用しているラベル名。「アドレス」はMIB先頭からのバイト数を示しています(Z80のIXレジスタを使用するなら(IX+アドレス)でアクセス出来ます)。

 ラベルの先頭に"☆"がついているワークエリアは「書き込み不可」の意味です。このワークエリアには絶対に書き込みを行なわないで下さい。書き込んだ場合、動作の保証はしません。

ラベル アドレス 内容
FM_SLT 0 FM音源のスロット番号(無しの場合は0FFH)
SC_SLT 1 SCC音源のスロット番号(無しの場合は0FFH)
MAXCHN 2 演奏トラック数(15又は、17)
PSGENF 3 PSGレジスタ6,11,12,13への書き込みフラグ
MASVOL 4 現在のマスタボリウム値
LOOPCT 5 ループカウンタ
JUMPCT 6 "J"コマンドの通過カウンタ
SOLWFG 7 スローモーションフラグ
PLAYFG 8 演奏中の総トラック数
9 PLAYFGの保存用として使用(アクセス禁止)
CNTSTR 10 制御文字列アドレス
FADEFG 12 @fコマンド通過カウンタ

☆FM_SLT
MSX-MUSICのスロット番号です。無しならFFHになっています。

☆SC_SLT
SCC音源のスロット番号です。無しならFFHになっています。

☆MAXCHN
演奏トラック数を示します。演奏中は、15又は17がセットされています。初期化時(_INITM実行時)に0に初期化されます。

★PSGENF
この値が1ならPSGレジスタ6,11,12,13への書き込みを行ない0ならば行ないません(内部では保持しているので、_TMST1等で復帰させる事が出来ます)。_PLYST実行直後は、1になっています。PSGを使用した効果音発生時などに使用して下さい。

☆MASVOL
現在のマスタボリウム値を示します(_MSVSTによって変化します)。

★LOOPCT
演奏中の曲が何ループしたかを保持しています。_PLYST実行直後は0に初期化されています。v2と異なり、"$"コマンドの通過カウンタではありません。曲がループした時にカウントアップされます。

★JUMPCT
"$"コマンド(MGSC v1.06以降)の通過数カウンタです。_PLYST実行直後は0に初期化されています。

★SLOWFG
この値が0以外ならば、割り込みルーチンを実行しません。(_INTERから何もせずに戻ります)

☆PLAYFG
現在演奏中のトラック数を示します。0になったら、演奏が終了したという事になります。

★CNTSTR
MMLの@mコマンドによって呼び出された制御文字列のアドレスを保持しています。_PLYST実行直後は0000Hに初期化されています。CNTSTRの更新フラグはありませんが、CNTSTRを読み込んだ直後に0000Hを書き込めば更新されたかを調べる事ができます。制御文字列は00Hで終わるASCIIZ文字列です。

★FADEFG
MMLの@fコマンドが通過する毎にインクリメントされます。_PLAYST実行時は0にリセットされています。なお、これは単なるコマンド通過カウンタですので、書き換えてもフェードアウトしたりはしません(^_^;

MGSDRVの呼び出し方法

 MGSDRVはジャンプテーブルをコールする事により呼びだします。括弧内の数値は、MGSDRV先頭からのオフセットアドレスです。これらのルーチンを呼ぶと、ほとんどのレジスタが破壊されます(IX,IY,裏レジスタを含む)。

 _SYSCK、_INTER、_FMWRT、_DATCK以外のエントリは、必ず割り込みを禁止してから戻ります。それらのルーチンは実行中も割り込みを禁止したままですので、DOS上でページ0を他のスロットに切り換えたり、割り込みルーチン内で呼び出したりしても問題はありません(実際にMGSDRV v3.13(常駐時)で行っています)。

_SYSCK (0010H)

【機能】音源のスロットを調べて初期化します。

【入力】なし

【出力】
D = MSX-MUSIC のスロット番号
A = E = SCC音源のスロット番号
HL = バージョン番号
IX = MIBの先頭アドレス
IY = トラックワークエリアの先頭アドレス
BC = トラックワークエリアの1トラック分のバイト数

【解説】 このルーチンは必ず最初に呼んで下さい。FM音源、SCC音源の有無を調べ、DレジスタFM音源のスロット番号を、AレジスタへSCC音源のスロット番号を返します。FM音源が発見されなかった場合は、DレジスタにFFHを、SCC音源が発見されなかった場合は、A=E=FFHを返します。

HLレジスタにはバージョン番号が返ってきます。version 2.36ならHL=0236Hです。スロット番号の形式はBIOSのRDSLTに準じます。

余談ですが、拡張スロット(NEOS製EX-4)に2つ以上の音源カートリッジやモデムカートリッジを挿入すると正常に動作しないという事例が報告されていますので注意してください。割り込みは許可されます。

_INITM (0013H)

【機能】演奏を止めて、ドライバを初期化します。

【入力】なし

【出力】なし

【解説】演奏を停止させ、全ての音源レジスタおよびドライバを初期化します。

_PLYST (0016H)

【機能】演奏を開始する。

【入力】
DE = 演奏データのアドレス
BHL = 演奏トラック指定

【出力】A = 総トラック数(MAXCHNに記録されるものと同一)

【解説】 演奏を開始します。演奏トラック指定の意味は以下の通りです(右からトラック順に並んでいるだけ)。

''' B H L *******? ???????? ???????? ("" は未使用です) | | | | |||+トラック 1(PSG Ch.1) | | | | ||+-トラック 2(PSG Ch.2) | | | | |+--トラック 3(PSG Ch.3) | | | | +---トラック 4(SCC ch.1) | | | +-------トラック 8(SCC Ch.5) | | +---------トラック 9(FM Ch.1) | +----------------トラック 16(FM ch.8) +------------------トラック 17(FM ch.9) '''

ビットは1がON、0がOFFです。全てのトラックを演奏する場合は、B=H=L=0FFHとでも設定して下さい。

Aレジスタには、そのデータのモード(MGSCの#opll_modeで設定されたもの)での最大トラック数(15又は、17)を返します。

演奏データは、どこへ置いても構いませんが、あらかじめページが選択されていなければなりません。

_TMST1 (0019H)

【機能】トラックの状態を変更する。

【入力】
C = 機能番号
BHL = トラック指定

【出力】なし

【解説】 トラックの状態を変更します。Cレジスタに入力する機能番号は、

数値 機能
0 そのトラックの演奏を中断させる(演奏は進まない)
1 そのトラックの演奏を演奏状態にする(再開させる)
2 そのトラックをOFF状態にする(音は出ていないが演奏は進む)

該当するビットが0で指定されたトラックは、Cレジスタの状態になり、1で指定さたトラックはC=1(再開)の状態になります。

0で演奏を中断状態にする場合は、全てのトラックを同時に中断しないと、再開した時に演奏がズレます。

2で指定されたトラックは内部で演奏が進んでいるだけで、音源レジスタをアクセスしません。ただし、OPLLのオリジナル音色やPSGのノイズ周波数の設定など、効果が他のトラックにも影響するものは、そのトラックの状態に係わらず音源レジスタをアクセスします(PSGに関してはMIBのPSGENFにより書き込みを完全に禁止することも可能です)。

_TMST2 (001CH)

【機能】_TMST1のPSG専用版

【入力】
C = 機能番号(_TMST2と同じ)
BHL = トラック指定(Lレジスタの下位3ビットのみ有効)

【出力】なし

【解説】 _TMST1のPSG専用ルーチンです。PSGのみの処理しか行なわない為、_TMST1に比べて高速です。

_INTER (001FH)

【機能】割り込みルーチンの入り口

【入力】なし

【出力】
A = PLAYFG(MIB)の値
E = JUMPCT(MIB)の値
D = LOOPCT(MIB)の値

【解説】 割り込みルーチンのエントリです。H.TIMIなどから、このアドレスをコールさせるようにして下さい。このルーチンでは演奏データを参照しますので、呼ぶ前にデータが存在するスロット(セグメント)へ切り替えておいて下さい。_INITM実行前にコールした場合、動作の保証はできません。

_MSVST (0022H)

【機能】マスタボリウムをセットする

【入力】
A = マスタボリウム値(0~17)
B = 音量更新フラグ(0~1)

【出力】なし

【解説】 マスタボリウムを変更します。Aレジスタに設定する値は、

数値 機能
0~15 その値をマスタボリウムとして設定 (0が最大)
16 演奏を中断状態にする
17 演奏を再開させる

これ以外の値を設定して呼んだ場合、動作の保証は出来ません。設定された値は、再度設定されない限り変化しません。

Bレジスタに設定する値が、1(正確には0以外)の場合は音量は1/60秒以内に変更されますが、0の場合は音譜の発生と同期して変更されます。

フェードアウトに使用する場合は0を設定した方が滑らかに聞こえます。Aレジスタに16または17が入力された場合、内部で_TMST1をコールします。割り込みは禁止して戻ります。

_WRTFM (0025H)

【機能】 OPLLのレジスタへデータを書き込む

【入力】
A = レジスタ番号
E = データ

【出力】 なし

【解説】 OPLLのレジスタへデータを書き込みます。破壊されるレジスタは、A'のみです。割り込みは変化しません。

演奏中に呼ぶ場合は、MGSDRVとの競合を防ぐため必ず割り込みを禁止して下さい。turbo Rの場合は適切なウェイトが掛かります。

_DATCK (0028H)

【機能】演奏データのヘッダを調べる

【入力】HL = 演奏データのアドレス

【出力】
Z = 1 演奏可能
Z = 0 演奏不可能

【解説】 演奏データが正常であるかを調べます。HLレジスタには演奏データのスタートアドレスを渡し、結果はZフラグに返されます。

Z = 0だった場合は、そのデータは演奏出来ません(バージョンが違う場合など)

このルーチンで行なっている具体的な動作は、HLレジスタから3バイトに"MGS"があるかをチェックして、次の3バイトと自分自身のバージョン番号を比較しているだけです。

_FFWAT (002BH)

【機能】早送り用ウェイト待ち

【入力】なし

【出力】なし

【解説】 早送り(_interの連続コール)する際に、適切なウェイトを入れます。

CPUがR800の場合、スピートが異常に早くなってしまうので、それを防ぐ場合に有効です。Z80だと何もせずに戻ります。

割り込みの状態は変化しません。DIした状態で使用して下さい。

トラックワークエリア

トラックワークエリアは、各トラックの状態を保持しているワークエリアです。リアルタイムで変化するものもあれば、ある特定のコマンドが実行された時などに限り変化するもの、参照のみに用いられるワークなどがあります。MGSDRVの場合これらのワークをトラック毎にまとめて管理しています。ワークエリアの先頭アドレス、サイズ(1トラック当りの)は、_SYSCKでそれぞれIY,BCに返されます。nトラックの先頭アドレスは、先頭アドレス+n*サイズで求められます(ただしnは0~16)。

トラック15(0から数えると14)は、モードによってリズムにもFM音源パートにもなりますが、これはMAXCHN(MIB)の値を調べる事で判断できます。MAXCHNが15ならリズム、17ならFM音源です。

以下に外部プログラムにとって、有用と思われるもののみを記します(全部書きたいところなんですが、資料が残っていなくて・・・^^; これらも自分のプログラムを覗いて書いているという始末です^^;)。左端の数字は16進です。そのトラックの先頭アドレスからのバイト数を示しています。

00:トラックの状態(0:OFF,1:ON,2:無音) byte

現在のトラックの状態を示しています。0なら既に演奏が終了しているか、最初から演奏されていない、1は現在演奏中、2は_TMST1などによって音が出ていない状態になっている事を示します。_PLYST直後にこの内容を調べれば、演奏トラックを獲得する事が出来ます。ただし、SCC音源やFM音源が無い場合でも、そのトラックのデータがあればON状態になっていますので、音源の接続状態を調べて適当にマスクしなければなりません。

01:GATEタイムカウンタ(音が出ている長さ) word

音が実際にキーオンされている長さです。割り込み毎にカウントダウンされ、0になるとキーオフされます。処理の都合上、FM音源以外のトラックでは負の数になることもありますので、ここを参照しても意味のある値は返ってこない事があります。普通は、負の数になると既にキーオフしている事を示します。

03:STEPタイムカウンタ(音符の長さ) word

現在発生中の音の長さです。割り込み毎にカウントダウンされ、0になると次のコマンドの処理に移ります。

09:デチューン(符号付き) word

PSG,SCC音源では@pの値が入っています。FM音源では使用されません(無意味な値が入ってる可能性有り)。

07:周波数データの保存 word

発生中の周波数データです。デチューンなどの処理を行った後の周波数データが保持されています。

0B:現在発生中の音程データ word

発生中の周波数データです。こちらはLFOなどによってリアルタイムに変化します。

11:現在指定中の音色番号(0~31) byte

@で指定された音色番号です。

12:トラックボリウム(0~15) byte

そのトラックの最大音量です。ここを書き換えると、トラック毎の音量をリアルタイムで操作出来ます。

14:Qコマンドの値(0~8) byte

Qコマンドの値です。

15:オクターブ(0~7) byte

現在のオクターブ値です。ポルタメントが実行された場合は、終点のオクターブが入ります。

16:フラグ

ビット単位で構成される各種フラグです。

Bit 状態
B7 タイのフラグ(1ならタイが指定されている)
B6 不明(をぃをぃ(^_^;;)
B5 ↑同じ^^;
B4 Key on flag(キーオンされると1)
B3 Key off flag(gateタイムによって音が切れると1)
B2
B1 未使用・・・らしい(^_^;;;
B0

B4,B3は外部プログラムの為にただフラグを立てるだけですので外部プログラムがリセットしない限り値は変わりません(通常、値を読みだした後00011000BとANDを取って書き込みます)。B4は音階又はリズムが発生されて、更にタイがセットされていない場合(本当の意味でのキーオンの時)のみセットされます。B3はゲートタイムによって音が切れた場合にセットされます(リズム音ではゲートタイムの処理を行ないませんのでこのフラグはセットされません)。

16:フラグの注意点① オフセットの位置が違う?

【注意】オリジナルのドキュメントでは「16:フラグ」ではなく「22:フラグ」と記載してありますが、「16:フラグ」の間違いである可能性があります

16:フラグの注意点② MGSDRV自身も使用する?

【注意】このフラグは前述の「ただフラグを立てるだけ」ではなく、MGSDRV自身も使用するフラグである可能性があるようです。

17:Vコマンドで指定された音量 byte

vコマンドで設定された値を保持しています。リズムではvコマンド(全ての楽器の音量)の設定のみで変化し、楽器毎の音量設定では変化しません。

26:デチューンの値(符号付き) byte

\コマンドの値です。

3A:音程No.(0=C 1=C# 2=D 3=D# 4=E 5=F 6=F# 7=G 8=G# 9=A 10=A# 11=B 12,13=R)

 現在処理中のオクターブ内での音程番号です。リズムの場合、20H+レジスタ出力値が入っています。ポルタメントが実行された場合は、終点の音程番号が入ります。

MGSDRV.COMについて

 本アーカイブはMGSDRV.COMを含んでいませんので、別に入手して下さい。

 MGSDRV.COMにはMGSDRV本体を6000Hへリロケートしたものが含まれています。他にも常駐/開放を行なうルーチンなども含まれていますが、MGSDRVはそれ自体で独立していますので、別のプログラムからMGSDRVだけを読み込んで使用することができます。

 +0000:C3 xxxx     MGSDRV.COMのメインルーチンへのJPコード
 +0003:DB "MGSDRV"    MGSDRVのID
 +0009:DW size        MGSDRV本体のサイズ
 +000B:DW version MGSDRVのバージョン(下位、上位の順)
 +000D:DS 16      ヘッダエリア(MGSDRVプログラム本体開始)
 +001D:JP xxxx... ジャンプテーブル
    :

+0003 ----- MGSDRVのID

 MGSELやMGSCなどが本当にMGSDRV.COMであるかどうか(圧縮されていないかなど)を判断するため使用します。

+0009 ----- MGSDRV本体のサイズ

 MGSDRV本体のバイト数を示します。このバイト数はワークエリアを含んだ値です。(ワークエリアはアドレスが設定されているだけですので、無意味な値で埋まって います)。LDIRなどを使用して+000Dからをsizeバイト分だけ転送して下さい。

+000B ----- MGSDRVのバージョン番号

_SYSCKでHLレジスタに返されるものと同じです。

+000D ----- ヘッダエリア(MGSDRVプログラム本体開始)

MGSDRVの内部情報、外部プログラムとの受け渡しデータなどか入っています。

+000D   常駐ルーチンが使用する   
+000E   強制的にSCCと見なすスロット番号(初期値FFH) \_SYSCKでSCCを検索して見つからなかった場合にこの値が参照され、値がFFH以外なら、そのスロットを以後SCCとして処理します。MGSDRV.comの/Sオプションなどで書き換えられます。このエリアは、v3.13とは異なります。
    +000F   常駐部のジャンプテーブルへのアドレスが書き込まれます。常駐ルーチンのみが使用。

+0011~+001C

現在未使用

+001D ----- ジャンプテーブルの先頭アドレス

MGSDRVのジャンプテーブルの先頭アドレスです。+000DからMGSDRV本体ということになっていますので、+000Dからを6000Hへ転送しなければなりません。つまりジャンプテーブルは6010Hから始まることになります。

常駐環境(DOS2のみ)について

常駐環境でも各ファンクション、MIB等の使用方法は基本的には通常と変わりありません。ただしMGSDRV本体(MIB,トラックワークを含む)、演奏データが全てマッパ に配置されますので、それらのデータを参照するときはマッパを切り替えなくてはなりません。MGSDRVが常駐するのはプライマリマッパのみですので、スロットはプ ライマリ以外に切り替わっていない限り切り替える必要はありません。常駐環境で提供されているルーチンは呼び出し元のスロットがプライマリであり、変更されて ない事を前提にしています(セグメントしか切り替えない)。

 常駐時はマッパを最低2つ(32k)使用します。片方にはMGSDRV本体が転送され、もう片方(/Bを指定して常駐した場合は複数存在します)は演奏データ領域として用い られます。通常は、必要に応じてそれぞれページ1,2に割り当てて使用します。MGSDRVは6000Hから転送されるので、実際は8kバイト(4000H-5FFFH)空いています。この範囲は全く使用しませんので、外部プログラムが使用しても(必要があれば)構いません。演奏データは必ず8000H(マッパの先頭)に読み込むようにして下さい。

 MGSDRVが常駐しているかどうかは拡張BIOSを使用して調べます。MGSDRVのデバイスIDはF0Hです。常駐していればA=FFHで返りますが、常駐していない時は全てのレジスタは変更されません。

例:
    xor a       ;ffh以外なら何でもいいのだけど・・・
    ld  de,0f000h   ;dにデバイスID,eは取り敢えず00h
    call    0ffcah      ;拡張BIOSを呼び出す
    inc a       ;0ffhになってるかどうか?
    jr  nz,     ;MGSDRV無し(AがFFHではない)
            :           ;ここに来ればMGSDRV有り

 MGSDRVが存在していた場合、BCレジスタには常駐部のパラメーターブロックのアドレスが、HLレジスタには常駐部のジャンプテーブル(_SYSCKなどではありません)が返ります。

 パラメーターブロックは、常にページ3に存在していて、以下の様な構造になっています。ラベルは説明の都合で私が適当に付けたものです(^_^;;

    id_drvslt   equ 0       ;MGSDRV本体のスロット情報
    id_drvseg   equ 1       ;MGSDRV本体のセグメント情報
    id_datslt   equ 2       ;演奏データ領域のスロット情報
    id_datseg   equ 3       ;演奏データ領域のセグメント情報
    id_drvsiz   equ 4       ;MGSDRV本体のサイズ
    id_chfomm   equ 6       ;切り替え用のスロット情報(メイン)
    id_chfome   equ 7       ;切り替え用のスロット情報(拡張)
    id_mgsver   equ 8       ;MGSDRVのバージョン
    id_mibadr   equ 10      ;MIBへのアドレス
    id_trwadr   equ 12      ;トラックワークのアドレス
    id_trwsiz   equ 14      ;トラックワークのサイズ
    id_keyasw   equ 16      ;キー割り込み処理許可フラグ
    id_segmax   equ 17      ;確保した曲データセグメントの数
    id_segnum   equ 18      ;選択中の曲データ番号
    id_segtab   equ 19      ;確保した曲データセグメントのテーブル

 id_mgsverからid_trwsizは常駐時にコールされた_SYSCKの返り値です。スロット情報、セグメント情報などはそのままBIOSに渡せる形式で格納されています。

 id_ch????は、内部のスロット切り替えルーチンが使用する(スロットレジスタの値をマスクして、orして書き込む)形式なのでBIOSとは関係ありません。MIBやトラックワークを参照する時は、パラメーターブロックからアドレスを獲得して下さい。常駐環境で_SYSCKを行って獲得しようとすると、異常動作する事があります(一部自己書換されているため)。

 id_keyswはCTRL + Tenkeyなどで行われるキー割り込み処理の許可フラグです。常駐直後などは1(許可状態)になっています。処理を禁止させたい場合は0(不許可)に書き 換えてください。キー割り込み処理はH.KEYAを使用しているので、このフックを使用しない環境ならばH.KEYAにC9H(RET)を書き込むだけでも禁止出来ます。

 id_segnumには現在選択されている曲データのセグメント番号(メモリマッパのセグメント番号ではなく、使用中の曲データセグメント番号(0から始まる))です。

 id_segmaxにはMGSDRVが確保しているセグメントの最大数を保持しています。1-10の範囲(最低でも1つ)です。

 id_segtabには曲データ用セグメントとして確保されている、マッパサポートルーチに渡すセグメント番号を保持しているテーブルです。必ず10バイトありますが、id_segmaxの数までが有効なセグメントです。id_segtab + (id_segnum)で示されるアドレスの内容が実際に使用中のセグメントです(ここら辺ややこしい^^;)。

 HLレジスタに返されるジャンプテーブルは、主にMGSDRVを使用する外部プログラムのために用意したもので、以下のようなルーチンがあります。

    ij_interv   equ 0
    ij_chgdrv   equ 3
    ij_revdrv   equ 6
    ij_calmgs   equ 9
    ij_chgseg   equ 12

 ij_intervはH.TIMIからコールされるルーチンです。競合を防ぐため、必ず割り込みを禁止した状態でコールして下さい。スロット、セグメントはどのような状態でもかまいません。通常は使用しないで下さい(必要もないと思います)。

 ij_chgdrvは現在のセグメントを内部ワークに保存してページ1をMGSDRV、ページ2を演奏データのセグメントへ切り替えます。スタックはページ1,2以外でないと暴走します。セグメントの状態を保存するワークは1つしか無いので、重複してコールしないで下さい。割り込みは禁止されて戻ります。

 ij_revdrvはij_chgdrvで変更したセグメントを元の状態に復帰させます。内部ワークは変更されないので、必要ならば何回コールしても構いません。割り込みは禁止されて戻ります。

 ij_calmgsはセグメントを保存して、MGSDRVのスロットへ切り替えてから、IXで指定されたアドレスをコールします。BIOSで言う、CALSLTと似たようなルーチンです。裏レジスタは呼び出し時のワークとして用いられますので、全て破壊されます。内部でij_chgdrv,ij_revdrvを使用しているため、スタックがページ1,2以外でないと暴走します。割り込みは禁止されて戻ります。

 ij_chgsegは曲データセグメントを切り替えるルーチンです。現在のセグメントをいきなり切り替えるのではなく内部のスロット切り替えデータを修正(具体的には、id_datsegとid_segnumだけを書き換える)して、ij_chgdrvなどで新しいセグメントへ切り替えられるようにします。Aレジスタに切り替えるセグメント番号(0-9)を入れてコールします。エラーが発生(指定出来る最大のセグメント数を超えている場合など)すると、キャリーフラグを1にして戻ります。必ず演奏を停止させて、割り込みを禁止した状態から呼んで下さい。

sample:(再演奏をする)
    xor a
    ld  de,0f000h
    call    0ffcah
    or  a
    ret z       ;mgsdrv無し
    ld  de,jptab    ;ジャンプテーブル転送
    ld  bc,12
    ldir
;   di
;   ld  a,??        ;セグメントを切り替えたりする場合
;   call    jptab+12
    ld  ix,6028h    ;演奏データの検査
    ld  hl,8000h
    call    jptab+9
    ret nz      ;エラー発生
    ld  ix,6016h    ;演奏開始
    ld  b,-1
    ld  hl,-1
    ld  de,8000h
    call    jptab+9
    ei
    ret
jptab:
    db  0,0,0       ;id_interv
    db  0,0,0       ;id_chgdrv
    db  0,0,0       ;id_revdrv
    db  0,0,0       ;id_calmgs
    db  0,0,0       ;id_chgseg

 MSP,MSFのソースを公開していますので、それも併せて参照して下さい。

mgsdrvl.relについて(付属していませんので別に入手して下さい)

 mgsdrvl.relはソースファイルをm80でアセンブルしたリロケーターブルなモジュールです(当然、使用するにはl80が必要です)。mgsdrvの先頭アドレスは外部シンボル "mgsdrv"で定義されています。先頭にヘッダエリアが16バイトありますので、ジャンプテーブルはmgsdrv + 16から始まります。mgsdrvが使用する最終アドレス(ワークエリアを含む)は外部シンボル"mgsend"(モジュールのサイズとは異なります)です。

超手抜きなsample:
    
    extrn   mgsdrv
    
    _sysck  equ mgsdrv+16+3*0
    _initm  equ mgsdrv+16+3*1
    
    call    _sysck
    ld  (mibadr),ix
    ld  (trwadr),iy
    ld  (trwsiz),bc
    ld  (mgsver).hl
    call    _initm
     :
     :
     :

 常駐環境の説明に関しては以上です。まだ書き足りない箇所が結構あるのですが、今まで特に問い合わせも無いし(まともに読んでる人なんていないのではなかろうか)、聞かれもしない事を書いても疲れるだけなのでやめておきます。私のプログラムもこれに書いてある所位しか使っていないので、大抵のプログラムは組めると思いますが・・・。不明な点などがありましたらお知らせください。

そのほか

  • 営利、非営利を問わず組み込んで使用して下さって構いません。事前に連絡は不用ですが、何処かに一言使用している事を書いて下さると嬉しいです(^^;
  • 作者はMGSDRVを使用した結果による被害、バグ等の責任は一切負いません。
  • 本仕様書の配布、転載は自由に行なって下さい。
  • 要望、質問等は以下のIDまでメール等でお願いします。

NATSUME NET:NAT25667
FALCON NET :FALC0180
MARIO NET :AIN

  Ain