MSX Datapack wiki化計画

7章 MSX拡張BIOS仕様

 7.1 概要

 MSXではハードウェアを拡張する際は、そのハードウェアをカートリッジスロットに接続します。そして、そのハードウェアを制御するソフトウェアは、ROMの形でそのハードウェア上に実装されます。
 もし、その制御用ソフトウェアが拡張BASICステートメントの形式であれば、ユーザーはプログラミングのときにスロットの切り換えなどを意識する必要はありません。
 しかし、機械語やそれに準ずる言語(例えば、C言語など)でそのハードウェアや制御用ソフトウェアをアクセスする場合、どのスロットに呼び出し先のハードウェアが接続されているかがわからなければなりません。
 この問題を解決するために定められたのが、拡張BIOSという手法です。拡張BIOSコールを使えば、

  • 何の拡張ハードウェアがシステムに実装されているか
  • その数はいくつか
  • どのカートリッジスロットに接続されているか

などを調べることができます。
 この章では、拡張BIOSコールを使用する方法と拡張BIOSそのものを作成するために必要な情報を解説します。

 7.2 拡張BIOSにおけるデバイス

 拡張BIOSでは、拡張ハードウェアとその制御用ソフトウェアの組み合わせを「デバイス」、とし、0〜255の番号を割り当てています、違う種類のデバイスに同じ番号をつけることはできません。したがって、デバイス番号はアスキーが登録・管理しています。
 デバイス番号を拡張BIOSに渡すには、呼び出しの際にDレジスタに番号を入れます。
 現在登録されているデバイス番号は以下のとおりです。

   表7.100 登録されているデバイスー覧

番 号デバイス
0全てのデバイスを意味する
1〜3未使用
4MSX-DOS2(メモリマッパーサポート)
5〜7未使用
8RS232C、MSX-MODEM
9未使用
10MSX-AUDIO
11MSX-MIDI
12〜15未使用
16MSX-JE
17漢字ドライバ
18〜254未使用
255システムエクスクルーシブ

 7.3 拡張BIOSの呼び出し

 ここでは、拡張BIOSの呼び出し方について説明します。
 【HOKVLD(FB20H)】のビット0を調べ、「0」ならば拡張BIOSはありません。「1」ならば拡張BIOSが設定されているので、ルールに従い【EXTBIO(FFCAH)】を呼び出します。
 詳しくは、各デバイスの拡張BIOSの説明をご参照下さい。
 リスト7.6は、アプリケーションプログラムが拡張BIOSの「割り込み禁止の宣言」を呼び出す例です。

hokvld equ    0fb20h        ;address of Extended BIOS valid flag
extbio equ    0ffcah        ;entry address of extended BIOS

       ld     a,(hokvld)    ;get valid flag
       rrca                 ;is the extended BIOS valid?
       jr     nc,noextbio   ;no..
       ld     d,0           ;broad-cast command
       ld     e,2           ;say 'disable interrupt'
       call   extbio        ;call extended BIOS
              .
              .
 ;
 ;Enters here when no extended BIOS
 ;
 noextbio:
       di
       halt                ;halt here
       jr     noextbio

 7.4 拡張BIOSの実現方法

 ここでは、拡張BIOSを実現するためのデバイス側のプログラムについて説明します。
 デバイス側のソフトウェアは、まず次のような手順で環境を整えます。

  1. 【HOKVLD(0FB20H)】の内容を調べ、「0」ならばこれを「1」にして、【EXTBIO(0FFCAH)】からの29バイトにC9H(RET命令)を書く。
  2. 自分の後に【EXTBIO(0FFCAH)】を使用するデバイス側のプログラムのために、【EXTBIO(0FFCAH)】からの5バイトを自分のワークエリアにセーブする。処理の最後で、セーブしたワークエリアにジャンプすることで、複数のデバイスのデバイスが同じワークエリア(EXTBIO)を使うことができる(「INIEXBIO.MAC」参照)。
  3. 自分の拡張BIOSのエントリへのインタースロットコール命令を【EXTBIO(0FFCAH)】からに書く。
  4. DISINT、ENAINTのプログラムを図7.52の指定アドレスに書く。


図7.52 拡張BIOSエントリの記憶領域

 添付のフロッピーディスクに、拡張BIOSを設定するためのサンプルプログラム「lNIEXBIO.MAC」が入っていますので、参照して下さい。
 このプログラム中にGETSLTというルーチンがあります.これはスロット切り換えをしないで、CPUが直接アクセスできるメモリ(メインRAM)のスロットアドレスを得るものです。このプログラムは以降のプログラム例でも使います。
 スロットアドレスとは各スロットにつけられたアドレスで、8ビットで表されます。その形式は以下のとおりです。

図7.53 スロットアドレスの形式

 7.5 拡張BIOSの機能

 拡張BIOSの機能は以下の3つに分けられます。

  1. デバイス番号0によるブロードキャストコマンド(すべてのデバイスの呼び出し)
  2. デバイス番号による個々のデバイスの呼び出し
  3. デバイス番号255によるシステムエクスクルーシブ(そのデバイスのメーカーが独自の拡張BIOSを組み入れる場合)

 なお、拡張BIOSには、以下ような制限があります。

 拡張BIOSはインタースロットコールで呼び出され、しかもネストしています。そのためデバイスが1つ呼ばれるたびに最低16バイトのスタックエリアが必要になります。また、8000H〜BFFFHに拡張BIOSのプログラムが配置されていることもあります。したがって、拡張BIOSを呼び出す際のスタックポインタはC000Hよりも上位のアドレスになければなりません。
 デバイスの制御プログラム(拡張BIOS)は、ブロードキャストコマンドと各々のデバイスの呼び出しコマンドを必ずサポートして下さい。
 機能の選択はEレジスタに機能番号を入れて行います、各機能は以下で説明します。

7.5.1 ブロードキャストコマンド

 デバイス番号0による全デバイスの選択です。ブロードキャストコマンドには、以下の機能があります。

機能番号意味
0 デバイス番号の取得
1 トラップ使用数の取得
2 割り込み禁止の宣言
3 割り込み許可の宣言
機能番号0
機 能

デバイス番号を取得します、

解 説
システムにどんなデバイスがあるかを調べます、各々のデバイスは呼び出し元が用意したテーブルに自分のデバイス番号を書き込んだ後、テーブルのポインタを1つインクリメントして、次のデバイスに制御を渡します。
呼び出し元に制御が戻ったとき、ポインタは最後に書き込まれたアドレス+1を指しています。
テーブルのポインタはBレジスタとHLレジスタで指定します。Bレジスタはテーブルが存在するメモリのスロットアドレスで、HLレジスタはメモリアドレスです。

■テーブルの例(デバイスが4つ存在している場合)

リスト7.7は、アプリケーションプログラムがブロードキャストコマンドの「デバイス番号の取得」を呼び出す例です。

  リスト7.7 デバイス番号の取得例

;
; GETDEV - Get device number
; Entry  :none
; Return :carry flag is set if no devices
; Modify :all
;
extbio  equ     0ffcah       ;entry address of extended BIOS
getdev:
        ld      bc,table
        call    getslt       ;get slot address of the TABLE
        ld      h,b
        ld      l,c
        ld      b,a
        ld      d,0          ;broad-cast command
        ld      e,0          ;'get device number' command
        push    hl           ;save TABLE address
        call    extbio
        pop     de           ;restore TABLE address
        or      a
        sbc     hl,de        ;how many devices ?
        ret     nz           ; there are some devices
        scf                  ; no devices
        ret
table:
        ds      32           ;assume maximum 32 devices
機能番号1
機 能

トラップ使用数を取得します。
MSX BASICには、「ON STOP」や「ON SPRITE」などのトラップ機能があります。
このエントリはトラップ機能を外部で拡張するために使用します。MSX BASICは内部で26個のイベントを管理しています。その内訳は以下のとおりです。

イベント番号用途
0〜9 ON KEY GOSUB
10 ON STOP GOSUB
11 ON SPRITE GOSUB
12〜16ON STRIG GOSUB
17 ON INTERVAL GOSUB
18〜23拡張デバイス用
24〜25システム予約(使用禁止)

18番目から23番目までを拡張デバイスに使用することができます。トラップを使用するデバイスはイニシャライズ時にこの機能を呼び出し、他のデバイスが幾つ使うかを調べて、18+(この機能の返り値)番目のトラップから使用します。
この機能を呼び出す際には。Aレジスタに「0」をセットして下さい。また、戻り値(各デバイスが使っているトラップの数)はAレジスタに入ります。
リスト7.8は、アプリケーションプログラムがブロードキャストコマンドの「トラップ使用数の取得」を呼び出す例です。

リスト7.8 トラップ使用数の取得例

; GETTRP  - get how many traps are already used
; Entry   : none
; Return  : [A] = number of traps are already used
; Modify  : [Flag]、[DE]
;
gettrp:
      xor   a                ;clear number of traps
      ld    d,0              ;broad-cast command
      ld    e,1              ;'get number of traps' command
      call  extbio
      ret
機能番号2
機 能

割り込みの禁止を宣言します。

解 説
CPUの割り込み機能を利用するデバイスがある場合、別のデバイスが割り込みを一定期間以上禁止すると割り込み処理に不都合が生じることがあります。例えば、RS-232Cカートリッジは受信割り込みを使用するので、別のデバイスが長期問割り込みを禁止してしまうと、受信データを取りこぼしてしまいます。
これを避けるために、長期間割り込みを禁止する場合は、その前にこのエントリを呼び出します。割り込みを禁止する時間の長さは1mS以上の場合とします(1mS以上割り込みが禁止されると9600bpsの通信で受信ができなくなる)。
呼ばれたデバイス側では、割り込みが禁止されても都合の良いように内部で処理し(RS-232CではXOFFを送るなど)戻ります。割り込みを許可するときは、次の「割り込み許可の宣言」を必ず呼び出して下さい。

リスト7.9は、アプリケーションプログラムがブロードキャストコマンドの「割り込み禁止の宣言」を呼び出す例です。
この機能には、レジスタへの設定値や戻り値はありません。

リスト7.9 割り込み禁止の宣言例

;
; DISINT   - disable interrupt while long time
; Entry    : none
; Return   : none
; Modify   : none
disint:
      ld     d,0                ;broad-cast command
      ld     e,2                ;'disable interrupt' command
      call   EXTBIO
      ret
機能番号3
機 能

割り込みの許可を宣言します。

解 説
機能番号2で禁止宣言されていた割り込みを許可します。
リスト7.10は、アプリケーションプログラムがブロードキャストコマンドの「割り込み許可の宣言」を呼び出す例です。
この機能には、レジスタへの設定値や戻り値はありません。

リスト7.10 割り込み許可の宣言例

;
; ENAINT  - enable interrupt
; Entry   : none
; Return  : none
; Modify  : none
;
disint:
disint:
      ld     d,0                ;broad-cast command
      ld     e,3                ;'enable interrupt' command
      call   extbio
      ret

7.5.2 各デバイスに対するコマンド

 各々のデバイスを選択して発行するコマンドです、各デバイスに対しては、機能番号0のみが決められており、その他の機能はデバイスによって異なります。
 詳しくは、各デバイスの拡張BIOSの説明を参照して下さい。

機能番号0
機 能

エントリアドレスを取得します。

解 説
各デバイスが持っているBIOSのジャンプテーブルの先頭アドレスとスロットアドレスを調べます。各々のデバイスはデバイス番号を見て、自分が処理すべき命令かどうかを判断し、違うときは次のデバイスに制御を渡します。自分が処理すべき命令ならば、呼び出し元が用意したテーブルにジャンプテーブルの先頭アドレスとスロットアドレスを書き込んだ後、次のデバイスに制御を渡します。
呼び出し元に制御が戻ったとき、ポインタは最後に書き込まれたアドレス+1を指しています。
テーブルのポインタはBレジスタとHLレジスタで指定します。Bレジスタはテーブルのあるメモリのスロットアドレスで、HLレジスタはメモリアドレスです。

■テーブル例(同じ番号のデバイスが2つ存在している場合)

リスト7.11は、アプリケーションプログラムが各デバイスの「エントリアドレスの取得」
を呼び出す例です。

 リスト7.11 各デバイスのエントリアドレスの取得

;
; GETENT  - Get entry address
; Entry   :none
; Return  :carry flag is set if no devices
; Modify  :all
;
device  equ   8                   ;device #8 is RS-232C
getent:
        ld    bc,table
        call  getsit              ;get slot address of TABLE
        ld    h,b
        ld    l,c
        ld    b,a
        ld    d,device            ;set deice number
        ld    e,0                 ;'get entry address' command
        push  hl                  ;save TABLE address
        call  extbio
        pop   de                  ;restore TABLE address
        or    a
        sbc   hl,de               ;how many devices ?
        ret   nz                  ; there are some devices
        scf                       ; no devices
        ret
table:
        ds    32*4                ;assume maximum 32 devices

7.5.3 システムエクスクルーシブ

機能番号0
機 能

エントリアドレスを取得します。

解 説
各デバイスが持っているメーカー独自の拡張BIOSのジャンプテーブルの先頭アドレスとスロットアドレスおよびメーカーコードを調べます。各々のデバイスは、呼び出し元が用意したテーブルにジャンプテーブルの先頭アドレスとスロットアドレスおよびメーカーコードを書き込んだ後、次のデバイスに制御を渡します。呼び出し元に制御が戻ったとき、ポインタは最後に書き込まれたアドレス+1を指しています。全てのデバイスが値を返してきますので、特定のデバイスを選択するときは、「7.5.2 各デバイスに対するコマンド(機能番号O)」と併用するようにします。
テーブルのポインタはBレジスタとHLレジスタで指定します。Bレジスタはテーブルのあるメモリのスロットアドレスで、HLレジスタはメモリアドレスです。

■テーブルの例(メーカー独自のデバイスが2つ存在している場合)

 リスト7.12は、アプリケーションプログラムがシステムエクスクルーシブの「エントリアドレスの取得」を呼び出す例です。

リスト7.12 システムエクスクルーシブのエントリアドレスの取得例

;
; SYSENT  - Get entry address
; Entry   :none
; Return  :carry flag is set if no devices
; Modify  :all
;
systent:
        ld    bc,table
        call  getsit              ;get slot address of TABLE
        ld    h,b
        ld    l,c
        ld    b,a
        ld    d,0ffh              ;system exclusive
        ld    e,0                 ;'get entry address' command
        push  hl                  ;save TABLE address
        call  extbio
        pop   de                  ;restore TABLE address
        or    a
        sbc   hl,de               ;how many devices ?
        ret   nz                  ; there are some devices
        scf                       ; no devices
        ret
table:
        ds    32*5                ;assume maximum 32 devices

 表7.101 メーカーコード一覧

コードメーカー名
0 アスキー
1 マイクロソフト
2 キヤノン
3 カシオ計算機
4 富士通
5 富士通ゼネラル
6 日立製作所
7 京セラ
8 松下電器産業
9 三菱電機
10 日本電気
11 ヤマハ
12 日本ビクター
13 フィリップス
14 パイオニア
15 三洋電機
16 シャープ
17 ソニー
18 スペクトラビデオ
19 東芝
20 ミツミ電機
21 テレマティカ
22 グラディエンテ
23 シャープドブラジル
24 GOLD STAR
25 DAEWOO *
26 Samsung *

6章 24トッド漢字プリンタ? A.1 BIOS一覧