MSX Datapack wiki化計画

6章 内部ルーチン

 6.1 PLAY文BIOS

6.1.1 概要

 MSXはPSGの音楽を割り込みルーチン内で演奏しています。BASICではPLAY文がMML(Music Macro Language)を割り込みルーチンが解釈できる形に変換してキューに書き込み、あるフラグをセットします。割り込みルーチンはそのフラグを見て、キューにデータが書かれたことを知り、キューからデータを取り出して演奏します。
 演奏はキューから取り出したデータがEND MARKのときに終了します。このキューは各チャンネルごとに1本ずつで、合計3本あります。

6.1.2 キューの構造

 まず、【QUEUES(0F3F3H,2)】というワークエリアがあり、これがQCB(Queue Control Block)という構造体の配列の先頭を指しています。QCB構造体の配列は、通常【QUETAB(0F959H,24)】にあり、要素数は4つです。しかし、最後の1つはPLAY文では使用しません。1つのQCBは次のような構造をしています。

表2.19 QCBの構造

開始番地からのオフセット用途
0 PUTオフセットキューにデータを書き込むときのオフセット
1 GETオフセットキューからデータを読み出すときのオフセット
2 バックアップキャラクタ
キューにデータを書き込むときに一時的に使われる
3 キューの長さ 実際のキューの長さ-1。取り得る値は2のn乗-1(nは2から8)。単位はバイト。通常は127
4、5キューの開始番地
実際のキューの開始番地。通常、以下のキューを指している
チャンネル1【VOICAQ(0F975H,128)】
チャンネル2【VOICBQ(0F9F5H,128)】
チャンネル3【VOICCQ(0FA75H,128)】

6.1.3 キューデータの解説

 キューには1回の割り込み処理中に設定されるデータが可変長で入っています。最初の2バイトの上位3ビットはその割り込み処理中に処理されるデータが何バイトであるかを指定します。指定できる範囲は1から5です。残りの13ビットは次のでデータの処理するまでの時間をタイマー割り込みの回数を指定します。この2バイトのデータは上位バイトが先になります。終了はこの2バイトの代わりに、1バイトのFFHが入ります。残りのデータは次の4種類のうちのどれかが入っているかで異なります。

  1. 音程を設定するデータ(MMLのAからG、Nに相当する)
  2. 音程を設定するデータ(Vに相当する)
  3. エンベロープの形状を設定するデータ(Sに相当する)
  4. エンベロープの周期を設定するデータ(Mに相当する)

 各々の詳細な形式を以下で説明します。PSGに設定するデータの詳細は、「第6部 1章 PSGと音声出力」を参照してください。

1.音程を設定するデータ
 音程を設定するデータは2バイトで構成されます。上位2ビットは音程を設定するデータでることを示すために、「00」とします。残りの14ビットでPSGに設定する音色をそのまま指定しますが、PSGでは下位12ビットのみ有効です。上位バイトが先になります。

2.音声を設定するデータ
 音量を設定するデータは1バイトで構成されます。上位4ビットは音量を設定するデータであることを示すために、「1000」とします。残りの4ビットでPSGに設定する音量をそのまま指定します。

3.エンベロープの形状を設定するデータ
 エンベロープの形状を設定するデータは1バイトで構成されます。上位4ビットはエンベロープの形状を設定するデータであることを示すために、「1001」とします。残りの4ビットでPSGに設定するエンベロープの形状をそのまま設定します。

4.エンベロープの周期を設定するデータ
 エンベロープの周期を設定するデータは3バイトで構成されます。最初の1バイトはエンベロープの周期を設定するデータであることを示すために「40H」とします。残りの2バイトでPSGに設定するエンベロープの周期をそのまま指定します。この2バイトは上位バイトが先になります。

5.エンベロープの形状と周期を同時に設定するデータ
 このデータは3バイトで構成されます。最初の1バイトのうち、上位4ビットは「1101」とします。下位4ビットはPSGに設定するエンベロープの形状をそのまま指定します。残りの2バイトでPSGに設定するエンベロープの周期をそのまま指定します。この2バイトは上位バイトが先になります。

6.1.4 データの具体例

 MMLで"T120L4V8O4CDE"とした場合(以下16進数)

60,1E3バイトのデータがあり、0.5秒間続ける
88音量は8
01,AC音程は01ACH
60,1E3バイトのデータがあり、0.5秒間続ける
88音量は8
01,7D音程は017DH
60,1E3バイトのデータがあり、0.5秒間続ける
88音量は8
01,53音程は0153H
FF 終了

6.1.5 BIOS

 BIOSはSTRTMS(0099H/MAIN)という名前のルーチンがあります。これを呼ぶことにより、演奏を始めることができます。以下のサンプルプログラムを参照してください。

リスト2.8 STRTMSの使用例

           strtms    equ    0099h
           musicf    equ    0fb3fh     ; 音楽演奏用の割り込みフラグ
           plycnt    equ    0fb40h     ; キューされているPLAY文の数
           quetab    equ    0f959h     ; キューテーブル
           qcblen    equ    6          ; QCBの長さ
           cseg
music:
           ld      a,(musicf)       ; 演奏中?
           or      a
           jr      nz,music         ; 演奏中なら、終わるまで待つ
           di
           ld      de,quetab
           ld      hl,queini
           ld      bc,qcblen * 3
           ldir                     ; QCBの設定
           ld      a,1
           ld      (plycnt),a
           call    strtms           ; 演奏開始
           ei
           ret
queini:
           db      0ffh
           db      0
           db      0
           db      0ffh
           dw      queue1
           db      0ffh
           db      0
           db      0
           db      0ffh
           dw      queue2
           db      0ffh
           db      0
           db      0
           db      0ffh
           dw      queue3
;           
; "T120L4V8O4CDE"
queue1:
           db      0                       ; a dummy
           db      60h,1eh,88h,01h,0ach    ; T120L4V8C
           db      60h,1eh,88h,01h,7dh     ; T120L4V8D
           db      60h,1eh,88h,01h,53h     ; T120L4V8E
           db      0ffh                    ; end mark
queue2:
           db      0
           db      0ffh
queue3:
           db      0
           db      0ffh

           end

 6.2 ビットブロックトランスファ

 ビットブロックトランスファとは、RAM、VRAM、ディスク間でデータを転送するSUB ROM内ルーチンです。本来、MSX2で拡張されたBASICのCOPY命令用のルーチンですが、完全なサブルーチンの形式になっているので、BIOSのようにユーザープログラムから利用できます。
 なお、ビットブロックトランスファルーチンが使用可能な画像データは、BASICのCOPY命令で作成されたデータです。BSAVE"ファイル名",&Hxxxx,&Hxxxx,Sで作成されたデータは使用できません。


図2.28 COPY命令で作成した画像ファイルのヘッダ情報

COPY (0,0)-(10,20) TO "TEST.PIC"

で作成したTEST.PICは、0BH、00H、15H、00H、.... となる。

6.2.1 VRAM間の転送

BLTVV(0191H/SUB)
機能

VRAM領域内で転送を行います。

コール手順
HL0F562H

さらに以下のパラメータを設定する。

SX(0F562H,2) ; 転送元基準点 X座標
SY(0F564H,2) ; 転送元基準点 Y座標
DX(0F566H,2) ; 転送先基準点 X座標
DY(0F568H,2) ; 転送先基準点 Y座標
NX(0F56AH,2) ; X方向転送ドット数
NY(0F56CH,2) ; Y方向転送ドット数
CDUMMY(0F56EH,1) ; ダミー(セットする必要はない)
ARG(0F56FH,1) ; 方向と拡張RAMの選択(VDPのR#45と同じ)
LOGOP(0F570H,1) ; ロジカルオペレーション

戻り値

CYフラグをリセット

変更レジスタ

すべて

; COPY (0,0)-(255,99) TO (0,100)

bltvv    equ    0191h
extrom   equ    015fh
         ld     hl,0
         ld     (sx),hl          ; 転送元基準点は(0,0)
         ld     (sy),hl
         ld     (dx),hl          ; 転送先基準点は(0,100)
         ld     l,100
         ld     (dy),hl
         ld     hl,255-0+1       ; Y方向転送ドット数の設定
         ld     (nx),hl
         ld     hl,99-0+1        ; X方向転送ドット数の設定
         ld     (ny),hl
         xor    a                ; 方向の設定
         ld     (arg),a
         ld     (l_op),a         ; operation is 'replace'
         
         ld     hl,0f562h
         ld     ix,bltvv
         call   extrom
                 :
                 :
                 :

6.2.2 RAMとVRAM間のデータ転送

 以下のルーチンを使う場合、グラフィックのデータ領域として、スクリーンモードによって次のような大きさの領域を確保しておく必要があります。

表 2.20 スクリーンモード別確保領域の算出法

スクリーンモード領域の大きさ
6 X方向のドット数×Y方向のドット数÷4+4
5、7 X方向のドット数×Y方向のドット数÷2+4
8 X方向のドット数×Y方向のドット数+4

注意

割り算の端数は切り上げて下さい。

 なお、ディスクやRAMでは配列データと同様にサイズを示すデータが付加されます。このデータは先頭から2バイトがX方向のドット数、次の2バイトがY方向のドット数を示しています。

BLTVM(0195H/SUB)
機能

配列をVRAMに転送します。

コール手順
HL0F562H

さらに以下のパラメータを設定する。

DPTR(0F562H,2) ; メモリの転送元アドレス
DUMMY(0F564H,2) ; ダミー(セットする必要はない)
DX(0F566H,2) ; 転送先基準点 X座標
DY(0F568H,2) ; 転送先基準点 Y座標
NX(0F56AH,2) ; X方向転送ドット数(セットする必要はない)
NY(0F56CH,2) ; Y方向転送ドット数(セットする必要はない)
CDUMMY(0F56EH,1) ; ダミー(セットする必要はない)
ARG(0F56FH,1) ; 方向と拡張RAMの選択(VDPのR#45と同じ)
LOGOP(0F570H,1) ; ロジカルオペレーション

戻り値

転送するデータの個数がおかしければCYフラグをセット

変更レジスタ

すべて

; COPY <B000H> TO (5,6)

bltvm    equ    0195h
extrom   equ    015fh
         ld     hl,0b000h
         ld     (dptr),hl        ; データはB000Hにある
         ld     hl,5
         ld     (dx),hl          ; 転送先基準点は(5,6)
         inc    hl
         ld     (dy),hl
         xor    a                ; 方向の設定
         ld     (arg),a
         ld     (l_op),a         ; operation is 'replace'
         
         ld     hl,0f562h
         ld     ix,bltvm
         call   extrom
                 :
                 :
                 :
BLTMV(0199H/SUB)
機能

VRAMから配列に転送します。

コール手順
HL0F562H

さらに以下のパラメータを設定する。

SX(0F562H,2) ; 転送元基準点 X座標
SY(0F564H,2) ; 転送元基準点 Y座標
DPTR(0F566H,2) ; メモリの転送元アドレス
DUMMY(0F568H,2) ; ダミー(セットする必要はない)
NX(0F56AH,2) ; X方向転送ドット数
NY(0F56CH,2) ; Y方向転送ドット数
CDUMMY(0F56EH,1) ; ダミー(セットする必要はない)
ARG(0F56FH,1) ; 方向と拡張RAMの選択(VDPのR#45と同じ)

戻り値

CYフラグをリセット

変更レジスタ

すべて

; COPY (10,20)-(50,25) TO <B000H>

bltmv    equ    0199h
extrom   equ    015fh
         ld     hl,0b000h
         ld     (dptr),hl        ; データはB000Hにある
         ld     hl,10
         ld     (sx),hl          ; 転送元基準点は(10,20)
         ld     hl,20
         ld     (sy),hl
         ld     hl,50-10+1       ; Y方向転送ドット数の設定
         ld     (nx),hl
         ld     hl,25-20+1       ; X方向転送ドット数の設定
         ld     (ny),hl
         xor    a                ; 方向の設定
         ld     (arg),a
         
         ld     hl,0f562h        ;
         ld     ix,bltvm
         call   extrom
                 :
                 :
                 :

6.2.3 ディスクとRAM、VRAM間の転送

 ディスクを使う場合、まずファイル名を設定する必要があります(ファイル名はBASICと同様に指定)。例を次に示します。

                 :
                 :
         ld     hl,fname          ; ファイル名へのポインタの獲得
         ld     (fnptr),hl        ; パラメータエリアに設定
                 :
                 :
fname: db 22h,'b:test.pic',22h,0  ; "TEST.PIC",end mark

 ここで、何かエラーが起きれば、BASICインタープリタのエラーハンドラーへジャンプします。そのため、自分のプログラム内でエラーをハンドリングしたい場合やMSX-DOS、ROMカートリッジでこのルーチンを呼ぶ場合、フックをセットする必要があります。このフックは【ERRO(0FFB1H)】です。

BLTVD(019DH/SUB)
機能

ディスクからVRAMへ転送します。

コール手順
HL0F562H

さらに以下のパラメータを設定する。

FNPTR(0F562H,2) ; ファイル名のあるアドレス
DUMMY(0F564H,2) ; ダミー(セットする必要はない)
DX(0F566H,2) ; 転送先基準点 X座標
DY(0F568H,2) ; 転送先基準点 Y座標
NX(0F56AH,2) ; X方向転送ドット数(セットする必要はない)
NY(0F56CH,2) ; Y方向転送ドット数(セットする必要はない)
CDUMMY(0F56EH,1) ; ダミー(セットする必要はない)
ARG(0F56FH,1) ; 方向と拡張RAMの選択(VDPのR#45と同じ)

戻り値

CYフラグをリセット

変更レジスタ

すべて

; COPY "TEST.PIC" TO (3,2)

bltvd    equ    019dh
extrom   equ    015fh
         ld     hl,filename
         ld     (fnptr),hl       ; ファイル名へのポインタの設定
         ld     hl,3
         ld     (dx),hl          ; 転送先基準点は(3,2)
         dec    hl
         ld     (dy),hl
         xor    a                ; 方向の設定
         ld     (arg),a
         ld     (l_op),a         ; operation is 'replace'
         
         ld     hl,0f562h
         ld     ix,bltvd
         call   extrom
                 :
                 :
filename:db     22h,'test.pic',22h,0
                 :
                 :
BLTDV(01A1H/SUB)
機能

VRAMからディスクへ転送します。

コール手順
HL0F562H

さらに以下のパラメータを設定する。

FNPTR(0F562H,2) ; ファイル名のあるアドレス
DUMMY(0F564H,2) ; ダミー(セットする必要はない)
SX(0F562H,2) ; 転送元基準点 X座標
SY(0F564H,2) ; 転送元基準点 Y座標
NX(0F56AH,2) ; X方向転送ドット数
NY(0F56CH,2) ; Y方向転送ドット数
CDUMMY(0F56EH,1) ; ダミー(セットする必要はない)
ARG(0F56FH,1) ; 方向と拡張RAMの選択(VDPのR#45と同じ)

戻り値

CYフラグをリセット

変更レジスタ

すべて

; COPY (10,20)-(50,25) TO "A:TEST.PIC"

bltdv    equ    01a1h
extrom   equ    015fh
         ld     hl,filename
         ld     (fnptr),hl       ; ファイル名へのポインタの設定
         ld     hl,10
         ld     (sx),hl          ; 転送元基準点は(10,20)
         ld     hl,20
         ld     (sy),hl
         ld     hl,50-10+1       ; X方向転送ドット数の設定
         ld     (nx),hl
         ld     hl,25-20+1       ; Y方向転送ドット数の設定
         ld     (ny),hl
         xor    a                ; 方向の設定
         ld     (arg),a
         
         ld     hl,0f562h
         ld     ix,bltdv
         call   extrom
                 :
                 :
filename:db     22h,'a:test.pic',22h,0
                 :
                 :
BLTMD(01A5H/SUB)
機能

ディスクから配列データをロードします。

コール手順
HL0F562H

さらに以下のパラメータを設定する。

FNPTR(0F562H,2) ; ファイル名のあるアドレス
SY(0F564H,2) ; ダミー(セットする必要はない)
SPTR(0F566H,2) ; ロードする先頭アドレス
EPTR(0F568H,2) ; ロードする最終アドレス

戻り値

CYフラグをリセット

変更レジスタ

すべて

bltmd    equ    01a5h
extrom   equ    015fh
         ld     hl,filename      ; ファイル名へのポインタの設定
         ld     (fnptr),hl
         ld     hl,8000h         ; 先頭アドレスの設定
         ld     (sptr),hl
         ld     hl,0afffh        ; 最終アドレスの設定
         ld     (eptr),hl
                                 ;
         ld     hl,0f562h
         ld     ix,bltmd
         call   extrom
                 :
                 :
filename:db     22h,'test.bin',22h,0
                 :
                 :
BLTDM(01A9H/SUB)
機能

ディスクへ配列データをセーブします。

コール手順
HL0F562H

さらに以下のパラメータを設定する。

SPTR(0F562H,2) ; セーブする先頭アドレス
EPTR(0F564H,2) ; セーブする最終アドレス
FNPTR(0F566H,2) ; ファイル名のあるアドレス

戻り値

CYフラグをリセット

変更レジスタ

すべて

bltmd    equ    01a9h
extrom   equ    015fh
         ld     hl,filename      ; ファイル名へのポインタの設定
         ld     (fnptr),hl
         ld     hl,8000h         ; 先頭アドレスの設定
         ld     (sptr),hl
         ld     hl,0afffh        ; 最終アドレスの設定
         ld     (eptr),hl
                                 ;
         ld     hl,0f562h
         ld     ix,bltdm
         call   extrom
                 :
                 :
filename:db     22h,'a:test.bin',22h,0
                 :
                 :

6.2.4 ビットブロックトランスファの利用法

1.BASICの環境から利用する場合
 定められたワークエリアに値を入れて、HLレジスタが0F562Hを指すようにセットし、SUB ROM内のアドレスをコールします。
 以下のサンプルプログラムは、「MSX-DOS TOOLS」を使用し、BASICの環境からマシン語のプログラムをメモリ上にロードし、実行するものです。

リスト2.9 BASIC環境でのビットブロックトランスファ使用例

; 
;        BLTVV.MAC  sample program
;
bltvv    equ    0191h
sx       equ    0f562h
sy       equ    0f564h
dx       equ    0f566h
dy       equ    0f568h
nx       equ    0f56ah
ny       equ    0f56ch
cdummy   equ    0f56eh
arg      equ    0f56fh
logop    equ    0f570h
extrom   equ    015fh
start::
         ld     de,0
         ld     (sx),de          ; 転送元基準点は(0,0)
         ld     (sy),de
         ld     (dx),de          ; 転送先基準点は(0,100)
         ld     de,100
         ld     (dy),de
         ld     (nx),de          ; X方向転送ドット数を100に設定
         ld     (ny),de          ; Y方向転送ドット数を100に設定
         ld     a,00000000b      ; VRAMに対してコピーする
         ld     (arg),a          ; 方向は、X方向が右、Y方向が下
         ld     (logop),a        ; ロジカルオペレーションはIMP
         ld     ix,bltvv
         call   extrom           ; SUB ROM コール
         ret

         end

 以下のバッチファイルは、上記のアセンブラプログラムをBASICからBLOADするバイナリプログラムにするものです。

m80 = bltvv
l80 /p:c000,bltvv,bltvv /n/n/e:start
bsave bltvv.hex > bltvv.bin

こうして作成したバイナリファイルを実行するには、以下のBASICプログラムを使用します。

10 CLEAR 300,&HBFFF
20 BLOAD"bltvv.bin"
30 SCREEN 8:COPY "sample.pic" TO (0,0)
40 DEFUSR0=&HC000
50 A=USR(0)
60 A$=INKEY$:IF A$="" THEN GOTO 60

2.MSX-DOSの環境から利用する場合
 ビットブロックトランスファルーチンは、本来BASICのCOPY命令で使用するものですから、BASIC環境での動作を前提に作られています。したがって、MSX-DOSのプログラムからビットブロックトランスファを利用する場合には、BASIC環境からアクセスする手順に加えて、以下の手続きが必要になります。

1)ビットブロックトランスファルーチンは、SPと【STREND(0F6C6H)】が指す番地までをディスクアクセス時のバッファとして使用するので、STRENDに値を設定しなければならない。
2)ディスクをアクセスするルーチン使用時に設定するFNAMEの内容は、ページ2かページ3になければならない。

リスト2.10 DOS環境でのビットブロックトランスファ使用例

; 
;        BLTVD sample program
;
strend   equ    0f6c6h
bltvd    equ    019dh
calslt   equ    001ch
exptbl   equ    0fcc1h
exbrsa   equ    0faf8h
fnptr    equ    0f562h
dx       equ    0f566h
dy       equ    0f568h
arg      equ    0f56fh
l_op     equ    0f570h
chgmod   equ    005fh
         extrn  _calsub
;
start:
         ld     sp,(6)           ; スタックを設定
         ld     hl,0c000h        ; STRENDをC000Hに設定
         ld     (strend),hl
         ld     bc,11            ; FNAMEの内容をB000Hからにブロック転送
         ld     de,0b000h
         ld     hl,fname
         ldir
         ld     a,8              ; スクリーン8
         ld     iy,(exptbl-1)
         ld     ix,chgmod
         call   calslt
         ld     hl,0b000h        ; ブロック転送したアドレスを設定
         ld     (fnptr),hl
         ld     de,0
         ld     (dx),de
         ld     (dy),de
         xor    a

         ld     (arg),a
         ld     (l_op),a
         ld     hl,0f562h
         ld     ix,bltvd
         call   _calsub
         
         ld     a,0              ; スクリーンをテキストモードに戻す
         ld     iy,(exptbl-1)
         ld     ix,chgmod
         call   calslt
         jp     0
;
fname:   db     22h,'test.pic',22h,0
;
         end

 6.3 Math-Pack

 Math-Pach とは、MSX−BASIC の数値演算ルーチンの中核をなすもので、これらをマシン語から呼び出すことにより、簡単に浮動小数点演算や三角関数ルーチンを利用することができます。
 Math-Pack での実数演算はすべて BCD (Binary Coded Decimal = 2進化10進法)表現によって行われます。また、実数表現には、「単精度」と「倍精度」の2種類があり、単精度(6桁)は4バイト、倍精度(14桁)は8バイトで表現されます。(図2.29、図2.30)

図2.29 BCDによる実数表現のフォーマット

図2.30 実数の表現例

 1つの実数は、符号部、指数部、仮数部から成り立っています。符号部とはこの仮数部の符号を表し、0ならば正、1ならば負となります。指数部はバイナリ表現であり、+63乗〜 -63乗まで表すことができます(図 2.31)。倍精度実数の有効範囲を図2.32に示します。

注意
「×」はその値が1または0のどちらであっても関係が無いことを表します。
図2.31 指数部フォーマット

図2.32 倍精度実数表現の有効範囲

 Math-Packでは、演算の対象となるメモリがあらかじめ決められています。このメモリエリアを【DAC (Decimal ACcumlator - 0F7F6H)】と呼び、DACと演算対象となる数値を格納するエリアを【ARG(0F847H)】といいます。例えば、乗算ルーチンの場合、DACに入っている数とARGに入っている数の積が計算され、その結果がDACに入ることになります。
 DACには、単精度実数、倍精度実数、2バイト整数を格納することができますが、これらのうちのどれが入っているのかを示すために【VALTYP (0F663H)】が使われ、それぞれの場合について4、8、2の値が入ります。
 単精度実数と倍精度実数は、いずれもDACの先頭から数値を格納しなければなりません。ただし、2バイト整数の場合だけは、下位、上位をDAC+2、+3に格納して下さい。
 演算の対象が明記されていない演算は【VALTYP(0F663H)】によって値の型を参照するので、呼び出す前に正しい型を設定して下さい。
 Math-PackはBASICの内部ルーチンであるため、エラーが起きた場合(0除算やオーバーフローなど)はそれに応じたエラールーチンへ自動的に分岐し、その後BASICコマンドレベルに戻ります。それを避けたいときは、【H.ERRO (0FFB1H)】を書き換えて、アプリケーションプログラム側のエラー処理ルーチンへジャンプするようにして下さい。

6.3.1 Math-Pack ワークエリア

ラベルアドレスサイズ意味
VALTYPF663H1 DACに入っている数の形式を表す
DAC F7F6H16BCD形式の浮動小数点アキュムレータ
ARG F847H16DACの演算対象

6.3.2 Math-Pack エントリ

1.基本演算

ラベルアドレス意味変化するレジスタ
DECSUB 268CHDAC ← DAC-ARG すべて
DECADD 269AHDAC ← DAC+ARG すべて
DECNRM 26FAHDAC を正規化する (*1) すべて
DECROU(*2)273CHDAC を四捨五入する すべて
DECMUL 27E6HDAC ← DAC*DAC すべて
DECDIV 289FHDAC ← DAC/DAC すべて

注 意

これらは、いずれも DAC, ARG にある数を倍精度実数として扱う。
*1 仮数部の不要な 0 を取り去ること (0.00123 → 0.123E-2)
*2 DECROUは倍精度の値の最終桁+1(15桁目)に対して演算を行う。
<演算の例>
1.23456789012345→DECROU→1.2345678901235
1.11111111111114→DECROU→1.1111111111111
1.11111111111115→DECROU→1.1111111111112
1.99999999999999→DECROU→2.0

2.関数1

ラベルアドレス機能変化するレジスタ
COS2993HDAC ← COS(DAC)すべて
SIN29ACHDAC ← SIN(DAC)すべて
TAN29FBHDAC ← TAN(DAC)すべて
ATN2A14HDAC ← ATN(DAC)すべて
LOG2A72HDAC ← LOG(DAC)すべて
SQR2AFFHDAC ← SQR(DAC)すべて
EXP2B4AHDAC ← EXP(DAC)すべて
RND2BDFHDAC ← RND(DAC)すべて
INT30CFHDAC ← INT(DAC)すべて

注意

すべて、BASICにおける同名の関数の処理ルーチン。
変化するレジスタすべてとは、A、B、C、D、E、H、Lの各レジスタを指す。

3.関数2

ラベルアドレス機能変化するレジスタ
SIGN 2E71HA ← DAC の符号A
ABSFN 2E82HDAC ← ABS(DAC)すべて
NEG 2E8DHDAC ← NEG(DAC)A、H、L
SGN 2E97HDAC ← SGN(DAC)A、H、L

4.移動

ラベルアドレス機能対象変化するレジスタ
MAF 2C4DHARG ← DAC 倍精度A、B、D、E、H、L
MAM 2C50HARG ← [HL] 倍精度A、B、D、E、H、L
MOV8DH 2C53H[DE] ← [HL] 倍精度A、B、D、E、H、L
MFA 2C59HDAC ← ARG 倍精度A、B、D、E、H、L
MFM 2C5CHDAC ← [HL] 倍精度A、B、D、E、H、L
MMF 2C67H[HL] ← DAC 倍精度A、B、D、E、H、L
MOV8HD 2C6AH[HL] ← [DE] 倍精度A、B、D、E、H、L
XTF 2C6FH[SP] ←→ DAC 倍精度A、B、D、E、H、L
PHA 2CC7HARG → [SP] 倍精度A、B、D、E、H、L
PHF 2CCCHDAC → [SP] 倍精度A、B、D、E、H、L
PPA 2CDCH[SP] → ARG 倍精度A、B、D、E、H、L
PPF 2CE1H[SP] → DAC 倍精度A、B、D、E、H、L
PUSHF 2EB1HDAC → [SP] 単精度D、E
MOVFM 2EBEHDAC ← [HL] 単精度B、C、D、E、H、L
MOVFR 2EC1HDAC ← (CBED) 単精度D、E
MOVRF 2ECCH(CBED) ← DAC 単精度B、C、D、E、H、L
MOVRMI 2ED6H(CBED) ← [HL]単精度B、C、D、E、H、L
MOVRM 2EDFH(BCDE) ← [HL]単精度B、C、D、E、H、L
MOVMF 2EE8H[HL] ← DAC 単精度B、C、D、E、H、L
MOVE 2EEBH[HL] ← [DE] 単精度B、C、D、E、H、L
VMOVAM 2EEFHARG ← [HL] VALTYPB、C、D、E、H、L
MOVVFM 2EF2H[DE] ← [HL] VALTYPB、C、D、E、H、L
VMOVE 2EF3H[HL] ← [DE] VALTYPB、C、D、E、H、L
VMOVFA 2F05HDAC ← ARG VALTYPB、C、D、E、H、L
VMOVFM 2F08HDAC ← [HL] VALTYPB、C、D、E、H、L
VMOVAF 2F0DHARG ← DAC VALTYPB、C、D、E、H、L
VMOVMF 2F10H[HL] ← DAC VALTYPB、C、D、E、H、L

注意

[HL]、[DE]は、それぞれHL、DEレジスタが指したメモリ上の数値を示す。
()内の4レジスタ名は、左から(符号+指数部)、(仮数部1、2桁)、(仮数部3、4桁)、(仮数部5、6桁)を示す単精度実数である。
移動の対象がVALTYPとなっているものは、【VALTYP(F663H)】に示されている型に応じた移動(2、4、8バイト)を行う。

5.比較

ラベルアドレス対象左辺右辺変化するレジスタ
FCOMP 2F21H単精度実数 CBED DAC HL
ICOMP 2F4DH2バイト整数DE HL HL
XDCOMP 2F5CH倍精度実数 ARG DAC すべて

注意

結果はすべて A レジスタに入る。レジスタの意味は、
A=1 → 左辺 < 右辺
A=0 → 左辺 = 右辺
A=-1 → 左辺 > 右辺
単精度の比較で、左辺のCBEDとは各レジスタに、それぞれ単精度の(符号+指数部)、(仮数部1、2桁)、(仮数部3、4桁)、(仮数部5、6桁)が入ることを意味する。


6.浮動小数点入出力

ラベルアドレス機能
FIN3299H浮動小数点を表す文字列を実数表現に変換して、DACに格納する。

コール手順
HL文字列の先頭アドレス
戻り値
DAC 実数
C FFH = 小数点なし、0 = 小数点あり
B 小数点以降の桁数
D 総桁数
ラベルアドレス機能
FOUT 3425HDACに入っている実数表現の数を文字列に変換する(フォーマット指定なし)
PUFOUT3426HDACに入っている実数表現の数を文字列に変換する(フォーマット指定あり)
コール手順
A変換のフォーマット
bit70=フォーマット指定なし、1=フォーマット指定あり
bit60=カンマ(,)による区切りなし、1=3ごとにカンマ(,)で区切る
bit50=意味無し、1=先頭のスペースを「*」で埋める
bit40=意味無し、1=数値の前に「$」をつける
bit30=意味無し、1=正の場合も符号「+」をつける
bit20=意味無し、1=数値の後ろに符号をつける
bit1未使用
bit00=固定小数点、1=浮動小数点
B小数点を含まない、小数点以前の桁数
C小数点を含む、小数点以降の桁数
戻り値
HL文字列の先頭アドレス
ラベルアドレス機能
FOUTB371AHDAC+2、+3に入っている2バイト整数を2進表現の文字列に変換する
FOUTO371EHDAC+2、+3に入っている2バイト整数を8進表現の文字列に変換する
FOUTH3722HDAC+2、+3に入っている2バイト整数を16進表現の文字列に変換する
コール手順
DAC+2 2バイト整数
VALTYP2
戻り値
HL文字列の先頭アドレス
注意

レジスタはいずれも保存されない。
出力ルーチンにおける文字列先頭アドレスは、通常、【FBUFFR(F7C5H〜)】内となるが、場合により先頭アドレスは前後する。
FOUTB、FOUTO、FOUTHに限らずDAC+2に入れた整数を扱うときには、【VALTYP(F663H番地)】に必ず「2」を入れなければならない。

7.型変換

ラベルアドレス機能
FRCINT 2F8AHDACを2バイト整数にする (DAC+2、+3)
FRCSNG 2FB2HDACを単精度実数にする
FRCDBL 303AHDACを倍精度実数にする
FIXER 30BEHDAC←SGN(DAC)×INT(ABS(DAC))

注意

実行後【VALTYP(F663H)】にはDACの型を表す数(2、4、8)が入る。
レジスタはいずれも保存されない。

8.整数演算

ラベルアドレス機能変化するレジスタ
UMULT314AHDE←BC×DEA、B、C、D、E
ISUB 3167HHL←DE-HLすべて
IADD 3172HHL←DE+HLすべて
IMULT3193HHL←DE×HLすべて
IDIV 31E6HHL←DE÷HLすべて
IMOD 323AHHL←DE mod HL (DE ← DE/HL)すべて

注意

ISUB、IADD、IMULT、IDIV、IMODについては、演算結果はDAC+2にも入る。

9.べき乗

ラベルアドレス機能基数指数結果
SNGEXP37C8H単精度実数のべき乗を求める DACARGDAC
DBLEXP37D7H倍精度実数のべき乗を求める DACARGDAC
INTEXP383FH2バイト整数のべき乗を求めるDE HL DAC

注意

レジスタは、いずれも保存されない。

6.3.3 Math-PackをMSX-DOS上のプログラムから使用する方法

 Math-Packはその本体の大部分はPage 0にありますが、一部のルーチンがPage 1にあるために、MSX-DOSからコールした場合に正しい計算ができません。
 それを回避するためには、以下のようにします。

リスト2.11 Math-PackをDOS環境で使用する方法
406fh、4666h、4eb8h、5439hにそれぞれ以下のルーチンを置く。

calbas     equ     0159h
;
;          at 406fh
;
           ld ix,406f
           jp calbas
;
;          at 4666h
;
           ld ix,4666
           jp calbas
;
;          at 4eb8h
;
           ld ix,4eb8
           jp calbas
;
;          at 5439h
;
           ld ix,5439h
           jp calbas

5597hに以下のルーチンを置く。

;
;          at 5597h
;
getypr:
           ld    a,(valtyp)
           cp    8
           jr    nc,double
           sub   3
           or    a
           scf
           ret
;
double:
           sub   3
           or    a
           ret

66a7hに以下のルーチンを置く。

;
;          at 66a7h
;
ppswrt:
           pop   af
           ret

 6.4 MSX 漢字ドライバ

 MSX漢字ドライバは、BASICやDOSで統一的に日本語入出力を行うためのシステムソフトウェアです。

6.4.1 特徴

 MSX漢字ドライバには以下のような特長があります。

  1. BIOSを使って文字の入出力をしているソフトウェアであれば、プログラムを変更しないで漢字の入出力ができる。
  2. テキスト画面で、文字ごとに色を変えることができる。
  3. JIS第二水準の漢字をサポートしている。
  4. 漢字プリンタへの漢字出力をサポートしている。
  5. MSX-JE(MSX日本語フロントエンドプロセッサ)がなくても、単漢字変換機能で漢字の入力ができる。
  6. グラフィック画面に対し、LOCATE文やPRINT文で文字の表示ができる。

6.4.2 注意点

1.PRINT文
 MSX漢字ドライバでは、グラフィック画面に対して、PRINT文を使って文字を表示することができますが、以下の点を注意しなければなりません。

  1. LOCATE文で指定するカーソルポジションは、半角の文字単位です。
  2. カーソルポジションを保存しているワークエリアはひとつしかないので、SET PAGE命令でアクティブページを変更しながらPRINTすると、ほかのページで変更したカーソルポジションに続きに文字が表示されます。
  3. インタレースモード(KANJI2、KANJI3)で文字を表示する際には、SCREEN文でEVEN/ODDのインタレースモード(SCREEN ,,,,,3)に設定して、SET PAGE文で表示ページを奇数ページに、アクティブページを表示ページ-1に設定しなければなりません。

2.SCREEN文
 従来は、SCREENモードを変更しただけでは、スプライト表示禁止ビット(VDPレジスタ8)やインタレースモード(VDPレジスタ9)は変化しませんでしたが、漢字モードでは両方ともクリアされます。ただし、インタレースモードはSCREEN文の第6パラメータを同時に指定した場合は、正しく設定されます。

3.ユーザーエリア
 MSX-JEが実装されているシステムで、CALL KANJI命令を実行すると、MSX-JE用のワークエリアが確保されます。一度確保されたMSX-JE用のワークエリアはたとえ、CALL ANK命令を実行した場合でも解放することはできません。
 そのため、アプリケーションプログラムによっては、メモリ不足のために漢字モードから起動できないものがあるかもしれません。その場合は、一度リセットしてANKモードで起動してください。
 なお、確保されるワークエリアの大きさは、フロントエンドプロセッサによって異なります。

6.4.3 拡張BIOS

 漢字ドライバは、アプリケーションソフトウェアからその機能の一部を使用できるように、拡張BIOSを準備しています。MSX漢字ドライバの拡張BIOSでは、現在の画面モードを返したり、画面を希望するモードに変更できます。
 漢字はいち文字出力のBIOSコールや、BIOSのCHPUTをコールして表示します。

1.拡張BIOSの使用法
 MSX漢字ドライバの拡張BIOSは以下の手順で使用します。
 スタックポインタは0C000H番地以上を指すようにしてください。

  1. DレジスタにMSX漢字ドライバのデバイス番号である11Hを、Eレジスタに拡張BIOSファンクション番号を入れる。
  2. Eレジスタにセットした拡張BIOSファンクションに必要なレジスタの設定を行う。
  3. 0FFCAHをコールする。

6.4.4 拡張BIOSファンクション

モードの取得
機能

現在の画面モードを数値で返します。

入力
E0(モードの取得)
Aインストール検出(下記参照)
出力
A モード
0=ANK
1=KANJI0
2=KANJI1
3=KANJI2
4=KANJI3
解説

漢字ドライバがインストールされていない場合は[A]が不変で返ってきます。これを利用して、[A]を0FFHにして呼ぶことにより、漢字ドライバがそもそもインストールされているのか否かが判ります。単にモードが知りたいだけなら、[A]を0にして呼んでください。

モードの設定
機能

画面モードを設定します。

入力
E1(モードの設定)
Aモード
0=ANK
1=KANJI0
2=KANJI1
3=KANJI2
4=KANJI3
出力

なし

解説

スクリーンを指定されたモードに設定します。漢字ドライバがインストールされていないと無視されます。

 6.5 漢字ROM

6.5.1 漢字ROMのI/Oサポート

 漢字ROMは以下のI/Oポートに接続されています。

表2.21 漢字ROMとI/Oポート

アドレス用途INOUT
第1水準
0D8H 第1水準漢字ROMフォントデータ漢字番号の下位6ビット
0D9H 漢字番号の上位6ビット
第2水準
0DAH 第2水準漢字ROMフォントデータ漢字番号の下位6ビット
0DBH 漢字番号の上位6ビット

6.5.2 フォントデータの読み出し

 MSXの漢字ROMは、読み出したい文字の漢字番号を1回設定した後、32回I/Oポートを読み出すとデータを獲得できます。内部にアドレスカウンタを持っているので、番号を変えてフォントデータを読み込む必要はありません。

1.漢字番号の計算方法

漢字番号
第一水準〜15 (区×96+点)
16〜 (区×96+点-512)
第二水準(区-48)×96+点)
 フォントイメージの並び方は8バイトごとに、左上、右上、右下、右下、の順です。
 また、MSXの漢字ROM仕様では、フォントの形は決まっていません。フォントパターンは各メーカーによって異なっています。しかし、MSXの漢字ROM仕様では、ある特定のフォントのパターンを規定しており、そのパターンの有無をチェックすることにより、漢字ROMがシステムに実装されているかどうかの判断を行います。
 JISの句点コードで規定されていない部分は統一されていません。

2.第一水準漢字ROMのチェック
 第一水準では、JISコード2140H(1区32点)の左上部分が、次のようなフォントになっています。

○○○○○○○○
○●○○○○○○
○○●○○○○○
○○○●○○○○
○○○○●○○○
○○○○○●○○
○○○○○○●○
○○○○○○○●

3.第二水準漢字ROMのチェック
 第二水準では、JISコード737EH(83区94点)の漢字(○の中に■)の始め8バイトのデータのチェックサムが95Hになるようになっています。

例 01 02 0C 37 C0 3B 2A 2A

リスト2.12 第二水準漢字ROM実装のチェックプログラム

;
;  第二水準漢字ROMが実装されているかどうかを調べるルーチン
;
          .Z80
;
;  followings are definitions of Kanji ROM port addresses
;
kan2w0    defl     0dah         ; Kanji ROM port address of lower 6bit
kan2w1    defl     0dbh         ; Kanji ROM port address of higher 6bit
kan2rd    defl     0dbh         ; Kanji ROM port address of data read

;
;  このプログラムは、JISコードの737EH(83区94点)のフォントデータのうち、
;  最初の8バイトを呼んで、チェックサムを計算します。そして、その値が95H
;  であれば、Zフラグをセットしてリターンします。
;

kancod    defl     737eh
kanval    defl     95h
;
;  Calculate Kanji ROM address
;
romtmp    defl     kancod-5000h    ; Subtract offset of 1st level Knaji code
romadd    defl     (high romtmp) * 96+(low romtmp)-20h
romlog    defl     romadd mod 64
romhi     defl     romadd/64

kanchk:   ld       a,romlow        ; Low order byte
          out      (kan2w0),a      ; Set Kanji ROM lower 6 bit address
          ld       a,romhi         ; High order byte
          out      (kan2w1),a      ; Set Kanji ROM higher 6 bit address
          ld       c,0             ; Clera check sum accumulator
          ld       b,8             ; Loop count
chklop:   in       a,(kan2rd)      ; Read the character data
          add      a,c             ; Calculater check sum
          ld       c,a             ; loop till all done
          djnz     chklop          ; Set zero flag if Kanji ROM found
          cp       kanval
          ret
          
          end

6.5.3 デバイスイネーブル

 漢字ROMを内蔵するMSXシステムは、外部スロットから漢字ROMが挿入された場合のバスの競合を避けるために、システムソフトウェアにより内蔵ROMのアクセスを制御しなくてはなりません。つまり、I/OアドレスF5H番地のビット1に0が書き込まれた場合は、外部に漢字ROMが存在することを示しているわけですから、内蔵ROMのアクセスを禁止しなければなりません。

6.5.4 JISから区点コードへの変換例

リスト2.13 JISから区点コードへの変換例

10 DEFINT A-Z
20 DIM P(31)
30 'INPUT JIS CODE IN HEX(4 DIGITS) THEN CONVERT TO ROM CODE
40 INPUT N$:L=VAL("&H"+RIGHT$(N$,2)):H=VAL("&H"+LEFT$(N$,2))
50 N=(H-32)*96+L-32:IF H=>&H30 THEN N=N-512
60 L=N AND 63:H=N\64
70 'ROM CODE OUT
80 OUT &HD8,L
90 OUT &HD9,H
100 PRINT "LOW =";L,"HIGH =";H
110 'GET PATTERN
120 FOR I=0 TO 31
130 P(I)=INP(&HD9)
140 NEXT I
150 'PRINT OUT PATTERN
160 FOR I=0 TO 7
170 P$=RIGHT$("00000000"+BIN$(P(I)),8):GOSUB 250
180 P$=RIGHT$("00000000"+BIN$(P(I+8)),8):GOSUB 250:PRINT
190 NEXT I
200 FOR I=16 TO 23
210 P$=RIGHT$("00000000"+BIN$(P(I)),8):GOSUB 250
220 P$=RIGHT$("00000000"+BIN$(P(I+8)),8):GOSUB 250:PRINT
230 NEXT I
240 GOTO 40
250 FOR J=1 TO 8
260 IF MID$(P$,J,1)="0" THEN PRINT " "; ELSE PRINT "*";
270 NEXT J
280 RETURN

6.5.5 シフトJISからJISへの変換例

 ファイル上で上位(変数H)、下位(変数L)の順番に2バイトづつデータが入っている場合、

リスト2.14 シフトJISからJISへの変換例

100 IF &H80<=H AND H<&HA0 THEN H=H-&H70:GOTO 130
110 IF &HE0<=H AND H<&HF0 THEN H=H-&HB0:GOTO 130
120 GOTO 160
130 H=H+H:IF L>=&H80 THEN L=L-1
140 IF L<&H9E THEN H=H-1 ELSE L=L-&H5E
150 L=L-&H1F
160 REN End conversion

の方法を取り、HとLを16進4桁の上位、下位に変換する。

6.5.6 サンプルプログラム

 添付のフロッピーディスクに、漢字ROMをアクセスするためのサンプルプログラム(ファイル名「KANJIROM.MAC」が入っています。