MSX Datapack wiki化計画

3.3 FM BIOSの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
{{include unfinished_page}}
,{c B0},{BSIZE:0}
,{c S0},{SIZE:0}

,{t},{BSIZE:1 0|SIZE:100%}
,{BSIZE:0}← [[3.2 拡張BASIC|3.2 MSX-MUSIC 拡張BASIC]]                                        ,{BSIZE:0|RIGHT} [[3.4 YM2413(OPLL)]]                                                            →

!!3.3 FM BIOS

!3.3.1 概要
 MSX-MUSICには、アプリケーションソフトウェア用のサービスルーチンとして、MSX-MUSIC FM BIOSが用意されています。多くの場合、MSXの周辺機器は拡張BIOSコールにより、そのデバイスをアクセスしますが、FM BIOSはその方法をとらず、FM BIOSが存在するスロットを捜し、特定の番地を直接コールする仕組みになっています。

 高速処理を必要とする場合は、あらかじめスロットをイネーブルしておき、直接コールすることもできます。

 商用のアプリケーションソフトウェアは必ずこのFM BIOSを使って、OPLLをアクセスしてください。I/Oポートを直接操作した場合の互換性は保証できません。

 この章ではFM BIOSの機能、コール方法などを解説します。FM BIOSコールを使用するに当たっては、OPLL(YM2413)の知識が必須ですから、「3.4 YM2413(OPLL)」もあわせてご覧ください。ただし、「3.4 YM2413(OPLL)」はFM音源に関する解説ではないので、音の作り方などについては、専門の解説書をご参照ください。


!3.3.2 FM BIOSのサイズ

FM BIOSのサイズと格納番地は以下のとおりです。

{{svg 図7.19.svg,,size:230x170}}
'''図7.19 FM BIOSのサイズ'''

FM BIOSはワークエリアとして160バイト、スタックエリアとして32バイト使用します。


!3.3.3 FM BIOSの各機能

 FM BIOSは、インタースロットコールにより呼び出されます。以下でエントリ名と、その入出力の設定レジスタ、内容が変化するレジスタ、およびその機能について解説します。


::WRTOPL(4110H)
,{t},{BSIZE:1}
, 機 能 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,OPLLレジスタへデータを書き込みます。


,{t},{BSIZE:1}
, 入 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0|SIZE:60},{B0}
,,A     ,OPLLのレジスタ番号
,,E     ,書きこむデータ

,{t},{BSIZE:1}
, 出 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0|SIZE:60},{B0}
,,なし


,{t},{BSIZE:1}
,変更レジスタ{CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0|SIZE:60},{B0}
,,なし

,{t},{BSIZE:1}
, 解 説 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,Aレジスタで指定した番号のOPLLレジスタに、Eレジスタの内容を書き込みます。このエントリルーチン内では、割り込み禁止・解除をしていないので、必要に応じてDI、EIを行う必要があります。


::INIOPL(4113H)

,{t},{BSIZE:1}
, 機 能 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,FM BIOSの環境を整えます。

,{t},{BSIZE:1}
, 入 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0|SIZE:60},{B0}
,,HL    ,使用ワークエリアの先頭アドレス(偶数)


,{t},{BSIZE:1}
, 出 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし


,{t},{BSIZE:1}
,変更レジスタ{CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,AF、BC、DE、HL、IX、IY

,{t},{BSIZE:1}
, 解 説 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,HLレジスタで指定されたアドレス(偶数)に、FM BIOSで使用するワークエリアを設定し、全てのFM BIOS用のワークエリアおよびOPLLレジスタを初期化します。ワークエリアの先頭アドレス(偶数)は、【SLTWRK(0FD09H〜)】に格納されます。HLレジスタで指定されたエリアがRAMでない場合の動作保証はありません。
FM BIOSをコールするときは、最初にINIOPLを呼び出さなくてはなりません。このルーチンを1度も呼び出さずに、他のエントリルーチンを呼び出したときは、正常には動作しません。
このBIOSはEI状態でリターンします。
,,FM BIOSをコールするときは、最初にINIOPLを呼び出さなくてはなりません。このルーチンを1度も呼び出さずに、他のエントリルーチンを呼び出したときは、正常には動作しません。
,,このBIOSはEI状態でリターンします。



::MSTART(4116H)

,{t},{BSIZE:1}
, 機 能 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,音楽の演奏を開始します。


,{t},{BSIZE:1}
, 入 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{BSIZE:0|SIZE:50},{BSIZE:0|SIZE:80},{BSIZE:0|SIZE:80},{BSIZE:0|SIZE:400}
,,HL    ,音楽データの先頭アドレス{COLS:2},
,,A     ,エンドレスフラグ{COLS:2},
,,      ,0       ,無限ループ
,,      ,1〜254  ,繰り返し演奏回数の指定
,,      ,255     ,設定してはならない
,,(HL)* ,0EH     ,リズムモード(FM6音+リズム部)
,,      ,12H     ,メロディモード(FM9音)
 *(HL)はデータとして持っているので、新たに書き込む必要はありません。

,{t},{BSIZE:1}
, 出 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし


,{t},{BSIZE:1}
,変更レジスタ{CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,AF、BC、DE、HL、IX、IY

,{t},{BSIZE:1}
, 解 説 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,HLレジスタで指定されたアドレスに置かれている音楽データのヘッダ(後述)をもとに、MSX-MUSICのワークエリアを音楽演奏用に設定します。ただし、【H.TIMI(0FD9FH)】からOPLDRVを呼び出すように、あらかじめ設定しておかなければ、音楽の演奏はしません。
,,このBIOSはEI状態でリターンします。


::MSTOP(4119H)

,{t},{BSIZE:1}
, 機 能 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,音楽演奏を中止します。


,{t},{BSIZE:1}
, 入 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし

,{t},{BSIZE:1}
, 出 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし


,{t},{BSIZE:1}
,変更レジスタ{CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,AF、BC、DE、HL、IX、IY

,{t},{BSIZE:1}
, 解 説 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,現在出力しているOPLLのすべての音の発生を止め、MSX-MUSICのワークエリアも初期化します。
,,このBIOSはEI状態でリターンします。


::RDDATA(411CH)

,{t},{BSIZE:1}
, 機 能 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,ROM内の音色データを読み出します。


,{t},{BSIZE:1}
, 入 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0|SIZE:60},{B0}
,,HL     ,データ読み出し用ワークエリアの先頭アドレス
,,A      ,音色ナンバー(0〜63)


,{t},{BSIZE:1}
, 出 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし


,{t},{BSIZE:1}
,変更レジスタ{CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,F

,{t},{BSIZE:1}
, 解 説 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,ROMに内蔵されている音色を読み出し、指定のワークエリアに格納します。


::OPLDRV(411FH)

,{t},{BSIZE:1}
, 機 能 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,OPLLドライバへのインタラプトのエントリアドレスです。

,{t},{BSIZE:1}
, 入 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし

,{t},{BSIZE:1}
, 出 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし


,{t},{BSIZE:1}
,変更レジスタ{CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし

,{t},{BSIZE:1}
, 解 説 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,音楽演奏を実際に行うOPLLドライバのエントリアドレスです。H.TIMIフックを書き換えて、このOPLDRVを呼び出すようにして下さい。ただし、このBIOSを使用する前に、必ず1度はINIOPLをコールして、FM BIOS用のワークエリアとOPLLレジスタを初期化してください。そうでなければ、その後の動作は保証できません。


::TSTBGM(4122H)

,{t},{BSIZE:1}
, 機 能 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,演奏終了をチェックします。

,{t},{BSIZE:1}
, 入 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,なし

,{t},{BSIZE:1}
, 出 力 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0|SIZE:60},{B0|SIZE:60},{B0}
,,A      ,0       ,演奏終了
,,       ,0以外   ,演奏中


,{t},{BSIZE:1}
,変更レジスタ{CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,AF

,{t},{BSIZE:1}
, 解 説 {CENTER|SIZE:100}

,{t},{BSIZE:0}
,{c},{B0|SIZE:50},{B0}
,,MSTARTにて演奏を開始した音楽が、現在演奏中かどうかを調べます。割り込み禁止・解除の設定はしていません。


!3.3.4 FM BIOSで使用するデータ構造

FMBIOSで演奏可能なデータは、ヘッダ部とデータ部に分類されます。
FM BIOSで演奏可能なデータは、ヘッダ部とデータ部に分類されます。

'''1.ヘッダ部'''
 このヘッダ部によって、リズム部を使用するかどうかの設定や各ボイスチャンネル用データの先頭アドレスを求めることができます。

■FM6音+リズム部構成の場合
{{svg 図7.20.svg,,size:500x350}}
'''図7.20 FM6音+リズム部構成のヘッダ'''

■FM9音構成の場合
{{svg 図7.21.svg,,size:500x400}}
'''図7.21 FM BIOSのFM9音構成のヘッダ'''

'''2.データ部'''
■メロディ部(FM部)

,{t},{BSIZE:2 0}
,{c},{BSIZE:1 0|SIZE:100},{BSIZE:1 0}
,アドレス,意 味
,{c},{TOP|B0},{B0}
,00H〜5FH ,音程を指定します。この数値自身が音域を含む全ての音階の状態を表します。続くデータが音長データです。音長データが0FFHのときは、さらに次の1バイトも音長データとして加算されます。この音長読み出しは、その読み出された値が255以外になるまで続けられます。
,60H〜6FH ,音量を指定します。この数値から60Hを引いた値が、実際の音量データです。
,70H〜7FH ,音色を指定します。音色選択レジスタに書き込む実際の値は、この数値から70Hを引いた値です。
,"80H,81H"  ,サスティンを指定します。80Hでサスティン解除、81Hでサスティン設定です。
,82H      ,拡張音色を指定します。続く1バイトの値(0〜63)が、ROMの内蔵音色ナンバーです。この音色ナンバーの読み出しは最上位ビットが無視されます。
,83H      ,ユーザー音色を指定します。続く2バイトの値(下位、上位)が、音色データの格納されている先頭アドレスを示します。
,84H      ,レガートオフです。音を音符毎に切ります。
,85H      ,レガートオンです。音を切らずにつなぎます。
,86H      ,Q指定です。続く1バイト(1〜8)で指定します。レガートオンのときは、Q指定は実行しません。
,87H〜0FEH,未使用
,0FFH     ,そのボイス毎のチャンネルデータの終了コードです。

■リズム部
{{svg 図7.21.1.svg,,size:650x250}}

'''3.音色データ格納形式'''
 図7.22はユーザ音色データ(オリジナル音色データ)を作成し、このFM BIOSに組み込む場合のデータ形式です。ROMに格納されている音色データも、この形式で格納されています。

{{svg 図7.22.svg,,size:560x280}}
'''図7.22 FM BIOSの音色データ格納形式'''

 音色データはOPLLのレジスタ00〜07の順番に並んでいます。1音のデータは8バイトで構成されます。したがって、ROM内蔵の音色データは全部で200H(512)バイトとなります。

!3.3.5 FM BIOS使用上の注意

'''1.ワークエリア'''
 ワークエリアはいかなる場合においても、ページ1に指定することはできません。できるだけページ2かページ3に指定してください。ページ2とページ3にまたがって指定することも可能です。スロット管理を適切に行なったときに限り、ページ0にワークエリアを指定することができます。ただし、ページ0からページ1にまたがって指定はできません。

 また、ワークエリアの先頭アドレスは必ず偶数でなければなりません。これはMSX-MUSICの拡張BASICと【SLTWRK(0FD09H)】を共用するための制限事項です。

!3.3.6 FM BIOSの呼び出し方

 全スロットをサーチして、401CH番地からに「OPLL」という文字列を持ったスロットを捜します。そして、「OPLL」という文字列を持ったスロットの4110H番地からがFM BIOSのエントリです。

'''1.注意事項'''
 FM BIOSのエントリINIOPLが呼ばれたとき、内部で他のスロットにFM BIOSが存在するかどうかを調べるためにENASLTを用いてスロットを切り替えて、スロット0から順次ROM内の401CH番地からのIDをチェックしています。もし、対象スロットが拡張されている場合には、同様に拡張スロットの0から走査しますが、この場合は走査終了時に拡張スロットセレクトレジスタを保存せず、常に拡張スロット3を選択したままにしてしまいます。
 FM BIOSのエントリINIOPLが呼ばれたとき、内部で他のスロットにFM BIOSが存在するかどうかを調べるためにENASLTを用いてスロットを切り換えて、スロット0から順次ROM内の401CH番地からのIDをチェックしています。もし、対象スロットが拡張されている場合には、同様に拡張スロットの0から走査しますが、この場合は走査終了時に拡張スロットセレクトレジスタを保存せず、常に拡張スロット3を選択したままにしてしまいます。
 したがって、このチェックが終わった段階で、各スロットが拡張されていた場合には、それらスロットのページ1(4000Hから7FFFH)は拡張スロット3のままになっています。
 FM BIOSはこのままの状態で呼び出し元のアプリケーションに戻るため、
■アプリケーションがページ2からFM BIOSを呼び出し、
■ページ1に現れているスロットが拡張スロットだった場合、
常にそのページは拡張スロット3が現われてしまいます。

'''2.具体的な例'''
 以下の2つの条件を同時に満たす場合、
■スロット0が拡張されてスロット0の拡張スロット0にBASICがあった場合
■スロット1からスロット3のどれかにFM BIOSがあった場合
BASICプログラムからUSR文で呼び出されるプログラムがFM BIOSのINIOPLをコールして帰ってきたとき動作異常が起こります。
 この原因は、ページ1にはスロット0の拡張スロット3が現われているため、USR文で呼び出されたプログラムがBASICに戻るときに戻れないためです。

'''3.対処方法'''
 INIOPLを呼び出す前のページ1のスロットを覚えておき、INIOPLから戻ってきたときにもとのスロットに戻します。
 INIOPLを呼び出す前のページ1のスロットを覚えておき、INIOPLから戻ってきたときに元のスロットに戻します。
 サンプルプログラム「OPLL.MAC」を参照して下さい。


,{t},{BSIZE:1 0|SIZE:100%}
,{BSIZE:0}← [[3.2 拡張BASIC|3.2 MSX-MUSIC 拡張BASIC]]                                        ,{BSIZE:0|RIGHT} [[3.4 YM2413(OPLL)]]                                                            →