7.1 概要
MSXではハードウェアを拡張する際は、そのハードウェアをカートリッジスロットに接続します。そして、そのハードウェアを制御するソフトウェアは、ROMの形でそのハードウェア上に実装されます。
もし、その制御用ソフトウェアが拡張BASICステートメントの形式であれば、ユーザーはプログラミングのときにスロットの切り換えなどを意識する必要はありません。
しかし、機械語やそれに準ずる言語(例えば、C言語など)でそのハードウェアや制御用ソフトウェアをアクセスする場合、どのスロットに呼び出し先のハードウェアが接続されているかがわからなければなりません。
この問題を解決するために定められたのが、拡張BIOSという手法です。拡張BIOSコールを使えば、
- 何の拡張ハードウェアがシステムに実装されているか
- その数はいくつか
- どのカートリッジスロットに接続されているか
などを調べることができます。
この章では、拡張BIOSコールを使用する方法と拡張BIOSそのものを作成するために必要な情報を解説します。
7.2 拡張BIOSにおけるデバイス
拡張BIOSでは、拡張ハードウェアとその制御用ソフトウェアの組み合わせを「デバイス」、とし、0〜255の番号を割り当てています、違う種類のデバイスに同じ番号をつけることはできません。したがって、デバイス番号はアスキーが登録・管理しています。
デバイス番号を拡張BIOSに渡すには、呼び出しの際にDレジスタに番号を入れます。
現在登録されているデバイス番号は以下のとおりです。
表7.100 登録されているデバイスー覧
| 番 号 | デバイス | |
| 0 | 全てのデバイスを意味する | |
| 1〜3 | 未使用 | |
| 4 | MSX-DOS2(メモリマッパーサポート) | |
| 5〜7 | 未使用 | |
| 8 | RS232C、MSX-MODEM | |
| 9 | 未使用 | |
| 10 | MSX-AUDIO | |
| 11 | MSX-MIDI | |
| 12〜15 | 未使用 | |
| 16 | MSX-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を実現するためのデバイス側のプログラムについて説明します。
デバイス側のソフトウェアは、まず次のような手順で環境を整えます。
- 【HOKVLD(0FB20H)】の内容を調べ、「0」ならばこれを「1」にして、【EXTBIO(0FFCAH)】からの29バイトにC9H(RET命令)を書く。
- 自分の後に【EXTBIO(0FFCAH)】を使用するデバイス側のプログラムのために、【EXTBIO(0FFCAH)】からの5バイトを自分のワークエリアにセーブする。処理の最後で、セーブしたワークエリアにジャンプすることで、複数のデバイスのデバイスが同じワークエリア(EXTBIO)を使うことができる(「INIEXBIO.MAC」参照)。
- 自分の拡張BIOSのエントリへのインタースロットコール命令を【EXTBIO(0FFCAH)】からに書く。
- DISINT、ENAINTのプログラムを図7.52の指定アドレスに書く。
図7.52 拡張BIOSエントリの記憶領域
添付のフロッピーディスクに、拡張BIOSを設定するためのサンプルプログラム「lNIEXBIO.MAC」が入っていますので、参照して下さい。
このプログラム中にGETSLTというルーチンがあります.これはスロット切り換えをしないで、CPUが直接アクセスできるメモリ(メインRAM)のスロットアドレスを得るものです。このプログラムは以降のプログラム例でも使います。
スロットアドレスとは各スロットにつけられたアドレスで、8ビットで表されます。その形式は以下のとおりです。
7.5 拡張BIOSの機能
拡張BIOSの機能は以下の3つに分けられます。
- デバイス番号0によるブロードキャストコマンド(すべてのデバイスの呼び出し)
- デバイス番号による個々のデバイスの呼び出し
- デバイス番号255によるシステムエクスクルーシブ(そのデバイスのメーカーが独自の拡張BIOSを組み入れる場合)
なお、拡張BIOSには、以下ような制限があります。
拡張BIOSはインタースロットコールで呼び出され、しかもネストしています。そのためデバイスが1つ呼ばれるたびに最低16バイトのスタックエリアが必要になります。また、8000H〜BFFFHに拡張BIOSのプログラムが配置されていることもあります。したがって、拡張BIOSを呼び出す際のスタックポインタはC000Hよりも上位のアドレスになければなりません。
デバイスの制御プログラム(拡張BIOS)は、ブロードキャストコマンドと各々のデバイスの呼び出しコマンドを必ずサポートして下さい。
機能の選択はEレジスタに機能番号を入れて行います、各機能は以下で説明します。
7.5.1 ブロードキャストコマンド
デバイス番号0による全デバイスの選択です。ブロードキャストコマンドには、以下の機能があります。
| 機能番号 | 意味 | |
| 0 | デバイス番号の取得 | |
| 1 | トラップ使用数の取得 | |
| 2 | 割り込み禁止の宣言 | |
| 3 | 割り込み許可の宣言 |
- 機能番号0
| 機 能 |
デバイス番号を取得します、
| 解 説 |
呼び出し元に制御が戻ったとき、ポインタは最後に書き込まれたアドレス+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〜16 | ON 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
| 機 能 |
割り込みの禁止を宣言します。
| 解 説 |
これを避けるために、長期間割り込みを禁止する場合は、その前にこのエントリを呼び出します。割り込みを禁止する時間の長さは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
| 機 能 |
割り込みの許可を宣言します。
| 解 説 |
リスト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
| 機 能 |
エントリアドレスを取得します。
| 解 説 |
呼び出し元に制御が戻ったとき、ポインタは最後に書き込まれたアドレス+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
| 機 能 |
エントリアドレスを取得します。
| 解 説 |
テーブルのポインタは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一覧 → |