4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MDL-LIB version 2.2 の使い方

Last updated at Posted at 2023-10-14

はじめに

MSX0 Stack』楽しいですね。数十年ぶりに MSX 再入門を果たしました。

CP/M-80 用『Turbo Pascal 3.0』が MSX で使えるのは解って狂喜したのですが、イロイロ触っていると MSX 固有の機能を使うためのライブラリが欲しくなってきます。

MSX-DOS の BDOS は CP/M-80 互換なので Bdos() で簡単に呼び出せますし、ワークエリアは mem[アドレス] (や absolute) で参照できるのですが、肝心の BIOS の機能はインタースロットコールを使わないと呼び出せないので、少々面倒です。折角の Pascal なのに inline 文 (インライン機械語) をゴリゴリ書きたくはないですしね…。

驚いたことに、Turbo Pascal 用の MSX ライブラリはいくつも存在するようです。

MDL-LIB version 2.2

『MDL-LIB version 2.2』 は Martijn Dekker 氏によって作られた『Turbo Pascal 3.0』用 MSX ライブラリです (パブリックドメイン)。すべての BDOS や BIOS が網羅されているわけではありませんが、BDOS や BIOS をあまり意識する事なく MSX の固有機能が使えます。

MDL-LIB はドキュメントやコメントがオランダ語で書かれており、翻訳サイトに通すにしても、そのままテキストエディタで開くと文字化けしてしまうので、ドキュメントを UTF-8 に変換したものを用意しました。ドキュメントは PC で読む前提です (MSX-DOS 上で開かないでください)。

フォルダ 説明
DOC 各ライブラリのドキュメントです
LIB ライブラリ (インクルードファイル) です。
Turbo Pascal と同じフォルダにコピーして使います。
MDLDEMO MDL-LIB のデモプログラムです

leesmij.txt は英語で言うと README.TXT です。inleidng.txt は英語で言うと INTRO.TXT といったところでしょうか?

MDL-LIB ライブラリの概要

MDL-LIB ライブラリはインクルードファイルの形で用意されています。ファイルの拡張子は *.lib ですが、中身は (Turbo) Pascal のソースファイルです。

program TEST;

{$I MDLLIB.LIB}
{$I VRAM2.LIB}
{$I LOGOROUT.LIB}

begin
  ...
end;

{$I} コンパイラ指令を用い、インクルードして使います。

先述のように、MDL-LIB はドキュメントやコメントがオランダ語で書かれているのですが、手続き・関数宣言の仮パラメータがオランダ語で書かれている事があります。例えば色を指定するパラメータの識別子として kleur が使われています。本記事内では、一瞥して理解できないないようなものは、英語の識別子 (色の例だと Color) で置き換えてあります。

■ MDLLIB

最初にインクルードすべきライブラリです。他のライブラリで使われるルーチンが含まれています。

ファイル名 依存ライブラリ
MDLLIB.LIB

ルーチン

名前 定義 説明
Bios() procedure Bios(adres: integer); BIOS を呼び出す
SubRom() procedure SubRom(adres: integer); サブ ROM を呼び出す (MSX2 以降)
BiosMem() function BiosMem(adres: integer): byte; 結果を返す BIOS を呼び出す
CalBas() procedure CalBas(adres: integer); BASIC-ROM を呼び出す
WaitForInt() procedure WaitForInt; 次の割り込みまでプログラムを停止

名前 定義 説明
LibStr type LibStr = string[80]; 文字列描画用。GRAPMSX が使用
Reg_pack type Reg_pack=record
  case Boolean of
    True: AF, BC, DE, HL: integer;
    False: F, A, C, B, E, D, L, H: byte;
end;
レジスタを定義したレコード

変数

ワークエリアにマッピングされたシステム変数 (sys_~) が定義されています。

名前 定義 説明
LibRegs var LibRegs : reg_pack absolute $0103; レジスタ変数
sys_textwidth var sys_textwidth: byte absolute $F3B0; LINLEN: 現在の画面の 1 行の幅
sys_textlines var sys_textlines: byte absolute $F3B1; CRTCNT: 現在の画面の行数
sys_width0 var sys_width0: byte absolute $F3AE; LINL40: SCREEN 0 のときの 1 行の幅
sys_width1 var sys_width1: byte absolute $F3AF; LINL32: SCREEN 1 のときの 1 行の幅
sys_whereX var sys_whereX: byte absolute $F3DD; CSRX: カーソルの X 座標
sys_whereY var sys_whereY: byte absolute $F3DC; CSRY: カーソルの Y 座標
sys_timer var sys_timer: integer absolute $FC9E; JIFFY: PLAY 文が内部で使用する
sys_scrmod var sys_scrmod: byte absolute $FCAF; SCRMOD: 現在のスクリーンモードの番号
sys_forclr var sys_forclr: byte absolute $F3E9; FORCLR: 前景色
sys_bakclr var sys_bakclr: byte absolute $F3EA; BAKCLR: 背景色
sys_bdrclr var sys_bdrclr: byte absolute $F3EB; BDRCLR: 周辺色 (ボーダー色)
sys_cursor var sys_cursor: boolean absolute $FCA9; CSRSW: カーソル表示
(0=OFF、0 以外=ON)
sys_click var sys_click: :boolean absolute $F3DB; CLIKSW: キークリックスイッチ
(0=OFF、0 以外=ON)
sys_gxpos var sys_gxpos: integer absolute $FCB3; GXPOS: X 座標
sys_gypos var sys_gypos: integer absolute $FCB5; GYPOS: Y 座標
sys_cx var sys_cx: integer absolute $FCB7; GRPACX: グラフィックアキュムレータ (X 座標)
sys_cy var sys_cy: integer absolute $FCB9; GRPACY: グラフィックアキュムレータ (Y 座標)
sys_atrbyt var sys_atrby: byte absolute $F3F2; ATRBYT: グラフィック使用時のカラーコード
sys_dppage var sys_dppage: byte absolute $FAF5; DPPAGE: ディスプレイページ番号 (MSX2 以降)
sys_acpage var sys_acpage: byte absolute $FAF6; ACPAGE: アクティブページ番号 (MSX2 以降)

■ VRAM

VRAM と VDP を操作する基本的なルーチンが含まれています。

ファイル名 依存ライブラリ
VRAM1.LIB MDLLIB.LIB
VRAM2.LIB (MSX2 以降用) MDLLIB.LIB

ルーチン

名前 定義 説明
ScrMode() procedure ScrMode(mode: byte); スクリーンモードを指定する
TextMode() procedure TextMode; 最後に使用したテキスト画面に設定する (SCREEN 0 or 1)
SetXY() procedure SetXY(x, y: integer); グラフィックカーソルを (x, y) に設定する
SetColor() procedure SetColor(color: byte); 文字色を設定する
Color() procedure Color(forclr, bakclr, bdrclr: integer); 前景色、背景色、境界色を設定する
DefColor() procedure DefColor(color, R, G, B: byte); 色を再定義する (MSX2 以降)
WriteVram() procedure WriteVram(adres: integer; data: byte); VRAM に 1 バイト書き込む
ReadVram() function ReadVram(adres: integer): byte; VRAM から 1 バイト読み出す
WriteVdp() procedure WriteVdp(reg, data: byte); VDP レジスタに書き込む
ReadVdp() function ReadVdp(reg: byte): byte; VDP レジスタから読み出す
ReadStatus() function ReadStatus: byte; VDP ステータスレジスタから読み出す (MSX1)
ReadStatus() function ReadStatus(reg: byte): byte; VDP ステータスレジスタから読み出す (MSX2 以降)
ReadVramPort() function ReadVramPort: byte; VDP 読み取りポートを返す
WriteVramPort() function WriteVramPort: byte; VDP 書き込みポートを返す
InitCharMode() procedure InitCharMode(width, char1, char2: byte); マルチカラー文字モードを設定する
TranspTable() function TranspTable: integer; VRAM アドレスのスプライトアトリビュートテーブルを返す
PattTable() function PattTable: integer; VRAM アドレスのスプライトパターンジェネレータテーブルを返す
ColorTable() function ColorTable: integer; VRAM アドレスのスプライトカラーテーブルを返す (MSX2 以降)
SpriteSize() procedure SpriteSize(size: byte); スプライトサイズを設定する
ClearSprites() procedure ClearSprites; すべてのスプライトをクリアする
ReadVdp() / ReadStatus() と BASIC の VDP() の関係
VDP レジスタ VDP() Read Write
R#0..7 VDP(0)..(7) ReadVdp(0)..(7) WriteVdp(0)..(7)
R#8..23 VDP(9)..(24) ReadVdp(8)..(23) WriteVdp(8)..(23)
S#0 VDP(8) ReadStatus (MSX1)
ReadStatus(0) (MSX2 以降)
S#1..9 VDP(-1)..(-9) ReadStatus(1)..(9) (MSX2 以降)
$00 □ (透明) $08 ■ 赤
$01 ■ 黒 $09 ■ 明るい赤
$02 ■ 緑 $0A ■ 黄色
$03 ■ 明るい緑 $0B ■ 明るい黄色
$04 ■ 暗い青 $0C ■ 暗い緑
$05 ■ 明るい青 $0D ■ 紫
$06 ■ 暗い赤 $0E ■ 灰色
$07 ■ 水色 $0F □ 白
SpriteSize()

size にはスプライトの大きさを表す値を指定します。

size 意味
0 8x8
1 16x16
2 8x8 (縦横 2 倍拡大)
3 16x16 (縦横 2 倍拡大)

変数

名前 定義 説明
Base var Base: array [0..19] of integer absolute $F3B3; VRAM のテーブル
LeftTextPos var LeftTextPos: integer absolute $F9F5; テキスト位置

■ GRAPMSX

グラフィック・ルーチンが含まれています。

ファイル名 依存ライブラリ
GRAPMSX1.LIB MDLLIB.LIB
GRAPMSX2.LIB (MSX2 以降用) MDLLIB.LIB

ルーチン

名前 定義 説明
Draw() procedure Draw(x1, y1, x2, y2, color: integer); 線を描画する
DrawTo() procedure DrawTo(x, y, color: integer); 最後の座標から線を描画する
Plot() procedure Plot(x, y, color: integer); 点を描画する
Ellipse() procedure Ellipse(x, y, radius, color, startangle, endangle: integer; flattening: real); 楕円を描画する
Arc() procedure Arc(x, y, angle, radius, color: integer); 円弧を描画する
Circle() procedure Circle(x, y, radius, color: integer); 円を描画する
GetDotColor() function GetDotColor(x, y: integer): integer; 指定された座標の色を得る
Box() procedure Box(x1, y1, x2, y2, color: integer); 四角形を描画する
FillBox() procedure FillBox(x1, y1, x2, y2, color: integer); 四角形を塗りつぶす
Logical() procedure Logical(opr: byte); 描画の際のロジカルオペレーションを指定する (MSX2 以降)
FillScreen() procedure FillScreen(color: integer); 画面全体を塗りつぶす
Pattern() procedure Pattern(p : Pattern_Type); 塗りつぶしパターンを指定する
FillPattern() procedure FillPattern(x1, y1, x2, y2, color: integer); 領域をパターンで塗りつぶす
Gwrite() procedure Gwrite(x, y: integer; txt: libstr); グラフィックス画面にテキストを書き込む
SetPage() procedure SetPage(projection, work: byte); 画面ページを設定する (MSX2 以降)
GetPic() procedure GetPic(x1, y1, x2, y2: integer; var buffer); 領域の画像を変数にコピーする (MSX2 以降)
PutPic() procedure PutPic(var buffer; x, y: integer); 変数に格納された画像を指定座標に描画する (MSX2 以降)
CopyPic() procedure CopyPic(x1, y1, x2, y2, sourcepage, xd, yd, destpage:integer); 指定ページの領域の画像を転送先ページの指定座標に描画する (MSX2 以降)
Gml() procedure Gml(commands: libstr); 任意の図形を描く (グラフィックマクロ言語)
Logical()

BASIC のものと同じ定数は用意されていないため、値で指定するか、定数を独自に定義します。

BASIC 説明
PSET 0 転送する色がそのままの色で表示される。
AND 1 転送する色のカラーコードと転送先の色のカラーコードとの間で論理積を行う。
OR 2 転送する色のカラーコードと転送先の色のカラーコードとの間で論理和を行う。
XOR 3 転送する色のカラーコードと転送先の色のカラーコードとの間で排他的論理和を行う。
PRESET
(NOT)
4 転送する色のカラーコードの各桁の 0 と 1 を反転させる。転送先のカラーコードは関係しない。
TPSET 8 転送する色が、そのままの色で表示される。転送する色に透明があれば透明になる。
TAND 9 転送する色のカラーコードと転送先の色のカラーコードとの間で論理積を行う。転送する色に透明があれば透明になる。
TOR 10 転送する色のカラーコードと転送先の色のカラーコードとの間で論理和を行う。転送する色に透明があれば透明になる。
TXOR 11 転送する色のカラーコードと転送先の色のカラーコードとの間で排他的論理和を行う。転送する色に透明があれば透明になる。
TPRESET
(TNOT)
12 転送する色のカラーコードの各桁の 0 と 1 を反転させる。転送先のカラーコードは関係しない。転送する色に透明があれば透明になる。

名前 定義 説明
Pattern_Type type Pattern_Type = array [0..7] of byte; 塗りつぶしパターンを格納する

■ LOGOROUT

LOGO のタートルグラフィックスルーチンが含まれています。

ファイル名 依存ライブラリ
LOGOROUT.LIB MDLLIB.LIB, VRAM1 (または VRAM2)

ルーチン

名前 定義 説明
InitLogo() procedure InitLogo; LOGO ルーチンを初期化する
ClearScreen() procedure ClearScreen; 画面を消去し Home() を実行する
ShowTurtle() procedure ShowTurtle; タートルを表示する
HideTurtle() procedure HideTurtle; タートルを非表示にする
TurtleThere() function TurtleThere: boolean; タートルが画面内にいるかを返す
TurtleDelay() procedure TurtleDelay(millisec: integer); 指定ミリ秒待つ
SetHeading() procedure SetHeading(angle: integer); タートルの向きを設定する (0..359)
Heading() function Heading: integer; タートルの向きを返す (0..359)
TurnLeft() procedure TurnLeft(angle: integer); タートルを反時計回りに angle の角度だけ回転させる
TurnRight() procedure TurnRight(angle: integer); タートルを時計回りに angle の角度だけ回転させる
Home() procedure Home; タートルをホームポジションに移動し、北を向かせる
SetPosition() procedure SetPosition(x, y: integer); タートルの位置を設定する
PenDown() procedure PenDown; ペンを下げる
PenUp() procedure PenUp; ペンを上げる
SetPenColor() procedure SetPenColor(color: integer); ペンの色を変える (色は MSX カラーコード)
ForWd() procedure ForWd(dist: integer); タートルを dist の分だけ前進させる
Back() procedure Back(dist: integer); タートルを dist の分だけ後退させる

定数

名前 定義 説明
north const north = 0; タートルの向き: 北
east const east = 90; タートルの向き: 東
south const south = 180; タートルの向き: 南
west const west = 270; タートルの向き: 西

変数

名前 定義 説明
Correction var correction: real; ドットの縦横比を考慮するための補正値 (デフォルト = 1)

■ GAMEIO

ジョイスティック、パドル、タッチパッド、マウス (MSX2)、ライトペン (MSX2) 用のルーチンが含まれています。

ファイル名 依存ライブラリ
GAMEIO.LIB MDLLIB.LIB

ルーチン

名前 定義 説明
Pad() function Pad(ID: byte): byte; コントローラの状態を返す
Strig() function Strig(ID: byte): boolean; コントローラのボタンの状態を返す
Stick() function Stick(ID: byte): byte; コントローラの向きの状態を返す
PAD()

・グラフィックタブレット/タッチパッド

ポート #1 ポート #2 説明
0 4 タッチパッドに触れていれば -1、触れていなければ 0
1 5 タッチパッドに触れた時の X 座標
2 6 タッチパッドに触れた時の Y 座標
3 7 タッチパッドのスイッチが押されていれば -1、押されていなければ 0

・マウス/トラックボール

ポート #1 ポート #2 説明
12 16 マウス/トラックボールに対する入力要求 (常に -1 を返す)
13 17 マウス/トラックボールの X 座標
14 18 マウス/トラックボールの Y 座標
15 19 予約 (常に 0 を返す)

・ライトペン

MSX1 内蔵
または外部
MSX2 内蔵 説明
8 20 ライトペンの準備ができていれば -1、できていなければ 0
9 21 ライトペンの X 座標
10 22 ライトペンの Y 座標
11 23 ライトペンのスイッチが押されていれば -1、押されていなければ 0
Strig()

・パラメータ

ポート #1 ポート #2 説明
1 2 コントローラーのボタン 1
3 4 コントローラーのボタン 2

※ 0 はスペースキーの状態を返す。

・結果
コントローラーのボタンが押されていれば -1 を、押されていなければ 0 を返す。

Stick()

・パラメータ

ID 説明
0 カーソルキー
1 ポート #1 のコントローラー
2 ポート #2 のコントローラー

・結果

結果 説明
0 ニュートラル
1
2 右上
3
4 右下
5
6 左下
7
8 左上

GAME というより、入力装置関連ですね。

■ SOUNDS

サウンド用のルーチンが含まれています。

ファイル名 依存ライブラリ
SOUNDS.LIB MDLLIB.LIB

ルーチン

名前 定義 説明
WritePsg() procedure WritePsg(reg, data: byte); PSG レジスタに書き込む
ReadPsg() function ReadPsg(reg: byte): byte; PSG レジスタから読み出す
Tone() procedure Tone(channel: byte; Hz: integer); トーンを設定する (channel = 0..2, Hz >= 28)
Noise() procedure Noise(height: byte); ノイズを設定する (0..31)
Volume() procedure Volume(channel, vol: byte); 音量を設定 (channel = 0..2, vol = 0..15)
Effect() procedure Effect(channels: SetOfChannel; Num: byte; time: integer); チャンネルにエフェクトを設定
SwitchSound() procedure SwitchSound(tchannels, nchannels: SetOfChannel); トーンとノイズをチャンネル毎に ON/OFF する
ResetPsg() procedure ResetPsg; PSG をリセットする
SetClick() procedure SetClick(status: boolean); 1 ビット I/O ポートのステータスを変更する
Effect()

image.png

名前 定義 説明
SetOfChannel type SetOfChannel = set of 0..2; チャンネルの集合

■ DISKTOOL

ディスク操作用のルーチンが含まれています。

ファイル名 依存ライブラリ
DISKTOOL.LIB MDLLIB.LIB

ルーチン

名前 定義 説明
MsxBdos() procedure MsxBdos; MSX-BDOS を呼び出す
SetDrive() procedure SetDrive(drive: byte); ドライブを設定する (0=カレントドライブ)
LoggedDrive() procedure LoggedDrive: byte; カレントドライブ番号を返す
ReadSector() procedure ReadSector(drive: byte; start: integer; num: byte; var sectoren); ディスクからセクタを読み出す
WriteSector() procedure WriteSector(drive: byte; start: integer; num: byte; var sectoren); セクタをディスクに書き込む
SearchFirst() function SearchFirst(var FCB; var info): boolean; 最初のファイルを検索する
SearchNext() function SearchNext(var info): boolean; 次のファイルを検索する
Dskf() procedure Dskf(drive: byte): integer; 指定したドライブ番号の空きディスク容量を KB 単位で返す

■ TAPE

カセットレコーダー (CMT) 操作用のルーチンが含まれています。

ファイル名 依存ライブラリ
TAPE.LIB MDLLIB.LIB

ルーチン

名前 定義 説明
TapeRead() procedure TapeRead(var buffer; len: integer; var success: boolean); カセットからブロックを読み出す
Motor() procedure Motor(status: byte); カセットのモーターを制御する (0=停止, 1=巻き戻し, 255=モーター状態の反転)
Baud() procedure Baud(rate: integer); カセットのボーレートを設定する (600 刻みで 600..3600)
DriveOff() procedure DriveOff;
OpenCasOutput() procedure OpenCasOutput(name: libstr; var success: boolean); 出力用に ASCII ファイルを開く
WriteToCas() procedure WriteToCas(wrstr: libstr; var success: boolean); ASCII ファイルに書き込む
CloseCasOutput() procedure CloseCasOutput(var success: boolean); 出力 ASCII ファイルを閉じる
OpenCasInput() procedure OpenCasInput(var name: libstr; var success: boolean); 入力用に ASCII ファイルを開く
ReadFromCas() procedure ReadFromCas(var rdstr: libstr; var success: boolean; var eof: boolean); ASCII ファイルから読み出す

カセットからファイルを検索する例です。

procedure FindFile(name: libstr; var success: boolean);
{ 'name' という名前の ASCII ファイルをテープから検索します。
  見つかった場合は自動的に開きます。}
var 
  found_name: libstr;
begin
  repeat
    OpenCasInput(found_name, success);
    if success then
      if found_name <> name then
        write('Skip :') 
      else 
        write('Found:');
    writeLn(found_name);
  until (found_name = name) or (not success);
end;

入力用 ASCII ファイルを閉じる必要はありません。

■ DATA

補助変数なしで 2 つの変数の内容を交換する VarSwap() と、配列を高速にソートできる Sort() が含まれています。

ファイル名 依存ライブラリ
DATA.LIB MDLLIB.LIB

ルーチン

名前 定義 説明
VarSwap() procedure VarSwap(var var1; var var2; size: integer); 2 つの変数の内容を交換する
Sort() procedure Sort(var data; NumOfRecords, size, funcaddr: integer); 配列を高速にソートする

VarSwap() の使用例を次に示します。

var a, b: real;
VarSwap(a, b, SizeOf(real));

Sort() の使用例を次に示します。

var 
  tabel: array [1..100] of real;
  function Compare_real(var var1, var2: real): boolean;
  begin
    Compare_real := (var1 >= var2)
  end; { Compare_real }
begin
  ...

  Sort(tabel, 100, SizeOf(real), Addr(Compare_real));

  ...
end.

■ MISC

その他の分類しにくいルーチンです。

ファイル名 依存ライブラリ
MISC.LIB MDLLIB.LIB

ルーチン

名前 定義 説明
MSXversion() function MSXversion: byte; MSX のバージョンを返す
Beep() procedure Beep; Beep を鳴らす
OnLine() function OnLine: boolean; プリンタがオンラインかどうかを返す
CtrlStop() function CtrlStop: boolean; 〔Ctrl〕+〔Stop〕 が押されているかどうかを返す
Key() procedure Key(st: boolean); ファンクションキーの表示を設定する
DefKey() procedure DefKey(number: integer; text: LibStr); ファンクションキーにテキストを割り当てる
ShowPrompt() procedure ShowPrompt; BASIC のプロンプトを表示する (MSX2 以降)
ResetScreen() procedure ResetScreen; BASIC の SET SCREEN で設定した値を元に画面をリセットする (MSX2 以降)
ClrEos() procedure ClrEos; カーソル位置から画面下までをクリアします
ClrY() procedure ClrY(y1, y2: byte); y1 行から y2 行までをクリアします
KillBuffer() procedure KillBuffer; キーボードバッファをクリアします
Screen() procedure Screen(st: boolean); 画面を ON/OFF します
SetAdjust() procedure SetAdjust(x, y: integer); 画面位置を調整します
FormatNumber() function FormatNumber(number: real; commas, asterisk, dollar, plus, sign, exp: boolean; digits, decimals: byte): libStr; 数値をフォーマットした文字列で返す
MSXversion()

定数は用意されていません。

機種
MSX1 1
MSX2 2
MSX2+ 3
MSXturboR 4

追加のライブラリ

独自に追加した MDL-LIB 用のライブラリです。

■ MSXUTILS

個人的に必要そうなものを MSXUTILS.LIB として別途定義します。アーカイブには含まれていません。

ファイル名 依存ライブラリ
MSXUTILS.LIB MDLLIB.LIB
MSXUTILS.LIB
(*
    MSXUTILS.LIB
*)

type
  TQCB = record
    POffset: byte;
    GOffset: byte;
    Backup: byte;
    QueLen: byte;
    QueAddr: integer;
  end;

const
  QCBInit: TQCB = (POffset:$ff;GOffset:0;Backup:0;QueLen:$ff;QueAddr:0);
  NullPlayData: array [0..1] of byte = ($00, $ff);

var
  sys_quetab: array [0..3] of TQCB absolute $F959;
  sys_musicf: byte absolute $FB3F;
  sys_plycnt: byte absolute $FB40;
  sys_oldkey: array [0..10] of byte absolute $FBDA;
  sys_newkey: array [0..10] of byte absolute $FBE5;
  sys_kanamd: byte absolute $FCAD; { Key layout }

{ Play MML Intermediate Code }

procedure Play(Cnt: byte);
begin
  sys_plycnt := Cnt;
  Bios($0099);
end;

{ Sense the key matrix }

function SenseKB(row: byte): byte;
begin
  libregs.A := row;
  Bios($0141);
  SenseKB := libregs.A
end;

ルーチン

名前 定義 説明
SenseKB() function SenseKB(row: byte): byte; キースキャンを行う
Play() procedure Play(Cnt: byte); MML 中間形式データを再生する

名前 定義 説明
TQCB type
  TQCB = record
    POffset: byte;
    GOffset: byte;
    Backup: Byte;
    QueLen: Byte;
    QueAddr: Integer;
end;
キューコントロールブロックレコード

定数

名前 定義 説明
QCBInit const QCBInit: TQCB = (POffset:\$ff;GOffset:0;Backup:0;QueLen:\$ff;QueAddr:0); QCB レコード初期化用定数
NullPlayData const NullPlayData: array [0..1] of byte = (\$00, \$ff); 空の再生データ

変数

名前 定義 説明
sys_quetab var sys_quetab: array [0..3] of TQCB absolute $F959; QUETAB: キューテーブル
sys_musicf var sys_musicf: byte absolute $FB3F; KANAMD: 音楽演奏用の割り込みフラグ
sys_plycnt var sys_plycnt: byte absolute $FB40; MUSICF: キューされている PLAY 文の数
sys_oldkey var sys_oldkey: array [0..10] of byte absolute $FBDA; OLDKEY: 旧キーの状態
sys_newkey var sys_newkey: array [0..10] of byte absolute $FBE5; NEWKEY: 新キーの状態
sys_kanamd var sys_kanamd: byte absolute $FCAD; KANAMD: キー配列
(0=五十音配列, 0以外=JIS配列)

サンプル

ドレミを鳴らします。sys_musicf を見て再生中でなければキューテーブルに再生データ情報を書き込んで Play() で鳴らします。再生データは一つだけなのでパラメータに 1 を渡しています。

PLAYTEST.PAS
program PLAYTEST;

{$I MDLLIB.LIB}
{$I MSXUTILS.LIB}

const
  PlayData: array [0..16] of byte =
    ($00,
     $60,$1e,$88,$01,$ac,
     $60,$1e,$88,$01,$7d,
     $60,$1e,$88,$01,$53,
     $ff
    );
begin
  while sys_musicf <> 0 do;

  sys_quetab[0] := QCBinit;
  sys_quetab[0].QueAddr := Addr(PlayData);
  sys_quetab[1] := QCBinit;
  sys_quetab[1].QueAddr := Addr(NullPlayData);
  sys_quetab[2] := QCBinit;
  sys_quetab[2].QueAddr := Addr(NullPlayData);

  Play(1);
end.

MSXUTILS.LIB は予告なく変更になる事があります。

■ EXTBIOS

拡張 BIOS 関連を EXTBIOS.LIB として別途定義します。アーカイブには含まれていません。

ファイル名 依存ライブラリ
EXTBIOS.LIB MDLLIB.LIB
EXTBIOS.LIB
(*
    EXTBIOS.LIB
*)

  procedure ExtBios;
  var
    raf : integer absolute $0103;
    rbc : integer absolute $0105;
    rde : integer absolute $0107;
    rhl : integer absolute $0109;
  begin
    inline($2A/raf/       { LD HL,(raf)     }
           $E5/           { PUSH HL         }
           $F1/           { POP AF          }
           $ED/$4B/rbc/   { LD BC,(rbc)     }
           $ED/$5B/rde/   { LD DE,(rde)     }
           $2A/rhl/       { LD HL,(rhl)     }
           $CD/$CA/$FF/   { CALL EXTBIO     }
           $ED/$43/rbc/   { LD (rbc),BC     }
           $ED/$53/rde/   { LD (rde),DE     }
           $22/rhl/       { LD (rhl),HL     }
           $F5/           { PUSH AF         }
           $E1/           { POP HL          }
           $22/raf);      { LD (raf),HL     }
  end;

  function GetKMode: Byte;
  begin
    LibRegs.D := $11;
    LibRegs.E := $00;
    LibRegs.A := $FF;
    ExtBios;
    GetKMode := LibRegs.A;
  end;
  
  procedure SetKMode(Mode: Byte);
  begin
    if not (Mode in [0..4]) then
      Mode := 0;
    LibRegs.D := $11;
    LibRegs.E := $01;
    LibRegs.A := Mode;
    ExtBios;
  end;

ルーチン

名前 定義 説明
ExtBios() procedure ExtBios; 拡張 BIOS を呼び出す
GetKMode() function GetKMode; 現在の漢字モードを返す。0xFF が返った場合には漢字ドライバが読み込まれていない
SetKMode() procedure SetKMode(Mode: byte); 漢字モードを設定する

EXTBIOS.LIB は予告なく変更になる事があります。

■ SPRITE

スプライト関連を SPRITE1.LIB / SPRITE2.LIB として別途定義します。アーカイブには含まれていません。

ファイル名 依存ライブラリ
SPRITE1.LIB MDLLIB.LIB, VRAM1.LIB
SPRITE2.LIB MDLLIB.LIB, VRAM2.LIB

SPRITE2.LIB はスプライトモード 2 対応 (MSX2 以降) です。

SPRITE1.LIB
(*
    SPRITE1.LIB
*)

type
  TSpDat8 = array [0..7] of byte;
  TSpDat16 = array [0..31] of byte;
  TSpAtr =
    record
      Row: byte;
      Col: byte;
      PtnNo: byte;
      Color: byte;
    end;

var
  _SpPtnAddr: Integer;
  _SpAtrAddr: Integer;
  _SpPtnSize: byte;

procedure InitSprite(Size: byte);
begin
  _SpPtnAddr := PattTable;
  _SpAtrAddr := TranspTable;
  if (Size mod 2) = 0 then
    _SpPtnSize := 8
  else
    _SpPtnSize := 32;
  ClearSprites;
  SpriteSize(Size);
end;

function CalcSpPtnAddr(PtnNo: byte): Integer;
begin
  CalcSpPtnAddr := _SpPtnAddr + PtnNo * _SpPtnSize;
end;

function CalcSpAtrAddr(Plane: byte): Integer;
begin
  CalcSpAtrAddr := _SpAtrAddr + Plane * 4;
end;

procedure SetSpritePtn(PtnNo: byte; var Ptn);
begin
  LibRegs.BC := _SpPtnSize;
  LibRegs.DE := _SpPtnAddr + PtnNo * LibRegs.BC;
  LibRegs.HL := Addr(Ptn);
  Bios($005C);
end;

procedure PutSprite(Plane: byte; X, Y: byte; Color: byte; PtnNo: byte);
var
  Atr: TSpAtr;
begin
  Atr.Col := X;
  Atr.Row := Y;
  Atr.PtnNo := PtnNo;
  Atr.Color := Color;
  LibRegs.HL := Addr(Atr);
  LibRegs.BC := 4;
  LibRegs.DE := _SpAtrAddr + Plane * LibRegs.BC;
  Bios($005C);
end;

procedure SetSpriteAtr(Plane: byte; var Atr: TSpAtr);
begin
  LibRegs.HL := Addr(Atr);
  LibRegs.BC := 4;
  LibRegs.DE := _SpAtrAddr + Plane * LibRegs.BC;
  Bios($005C);
end;
SPRITE2.LIB
(*
    SPRITE2.LIB
*)

type
  TSpDat8 = array [0..7] of byte;
  TSpDat16 = array [0..31] of byte;
  TSpAtr =
    record
      Row: byte;
      Col: byte;
      PtnNo: byte;
      Color: byte;
    end;
  TSpClrs = array [0..15] of byte;

var
  _SpPtnAddr: Integer;
  _SpAtrAddr: Integer;
  _SpClrAddr: Integer;
  _SpPtnSize: byte;

procedure InitSprite(Size: byte);
begin
  _SpPtnAddr := PattTable;
  _SpAtrAddr := TranspTable;
  _SpClrAddr := ColorTable;
  if (Size mod 2) = 0 then
    _SpPtnSize := 8
  else
    _SpPtnSize := 32;
  ClearSprites;
  SpriteSize(Size);
end;

function CalcSpPtnAddr(PtnNo: byte): Integer;
begin
  CalcSpPtnAddr := _SpPtnAddr + PtnNo * _SpPtnSize;
end;

function CalcSpAtrAddr(Plane: byte): Integer;
begin
  CalcSpAtrAddr := _SpAtrAddr + Plane * 4;
end;

function CalcSpClrAddr(Plane: byte): Integer;
begin
  CalcSpClrAddr := _SpClrAddr + Plane * 16;
end;

procedure SetSpritePtn(PtnNo: byte; var Ptn);
begin
  LibRegs.BC := _SpPtnSize;
  LibRegs.DE := _SpPtnAddr + PtnNo * LibRegs.BC;
  LibRegs.HL := Addr(Ptn);
  Bios($005C);
end;

procedure ColorSprite(Plane: byte; var Colors: TSpClrs);
begin
  LibRegs.HL := Addr(Colors);
  LibRegs.BC := 16;
  LibRegs.DE := _SpClrAddr + Plane * LibRegs.BC;
  Bios($005C);
end;

procedure PutSprite(Plane: byte; X, Y: byte; Color: byte; PtnNo: byte);
var
  Atr: TSpAtr;
begin
  Atr.Col := X;
  Atr.Row := Y;
  Atr.PtnNo := PtnNo;
  Atr.Color := Color;
  LibRegs.HL := Addr(Atr);
  LibRegs.BC := 4;
  LibRegs.DE := _SpAtrAddr + Plane * LibRegs.BC;
  Bios($005C);
end;

procedure SetSpriteAtr(Plane: byte; var Atr: TSpAtr);
begin
  LibRegs.HL := Addr(Atr);
  LibRegs.BC := 4;
  LibRegs.DE := _SpAtrAddr + Plane * LibRegs.BC;
  Bios($005C);
end;

procedure ShowSprite(Flg: Boolean);
begin
  WriteVdp(8, (ReadVdp(8) and $FD) or (Ord(not Flg) shl 1));
end;     

ルーチン

『MSX-C Library』のスプライト関連関数と似たような使い方ができます。

名前 定義 説明
InitSprite() procedure InitSprite(Size: byte); スプライトを初期化する
CalcSpPtnAddr() function CalcSpPtnAddr(PtnNo: byte): Integer; 指定したパターン番号のスプライトパターンジェネレータテーブルのアドレスを返す
CalcSpAtrAddr() function CalcSpAtrAddr(Plane: byte): Integer; 指定したプレーン番号のスプライトアトリビュートテーブルのアドレスを返す
CalcSpClrAddr() function CalcSpClrAddr(Plane: byte): Integer; 指定したプレーン番号のスプライトカラーテーブルのアドレスを返す
SetSpritePtn() procedure SetSpritePtn(PtnNo: byte; var Ptn); スプライトパターンを設定する
ColorSprite() procedure ColorSprite(Plane: byte; var Colors: TSpClrs); 指定したプレーン番号のスプライトのライン毎の色を設定する
PutSprite() procedure PutSprite(Plane: byte; X, Y: byte; Color: byte; PtnNo: byte); 指定したプレーン番号のスプライトを表示する
SetSpriteAtr() procedure SetSpriteAtr(Plane: byte; var Atr: TSpAtr); 指定したプレーン番号のスプライトのスプライトの属性を設定する (PutSprite() と引数が異なるだけ)
ShowSprite() procedure ShowSprite(Flg: Boolean); スプライトの表示/非表示を切り替える
PutSprite()

スプライトモード 2 (MSX2 以降 / SCREEN 4 以降) では、パラメータ Color で指定した色は無視されます。ColorSprite() を使って色を指定してください。

名前 定義 説明
TSpDat8 type
   TSpDat8 = array [0..7] of byte;
8x8 スプライトパターンジェネレータテーブル用配列
TSpDat16 type
   TSpDat16 = array [0..31] of byte;
16x16 スプライトパターンジェネレータテーブル用配列
TSpAtr type
  TSpAtr =
    record
      Row: byte;
      Col: byte;
      PtnNo: byte;
      Color: byte;
    end;
スプライトアトリビュートテーブルレコード
TSpClrs type
   TSpClrs = array [0..15] of byte;
スプライトカラーテーブル用配列

変数

名前 定義 説明
_SpPtnAddr var _SpPtnAddr: Integer; スプライトパターンジェネレータテーブルの先頭アドレス
_SpAtrAddr var _SpAtrAddr: Integer; スプライトアトリビュートテーブルの先頭アドレス
_SpClrAddr var _SpClrAddr: Integer; スプライトカラーテーブルの先頭アドレス
_SpPtnSize var _SpPtnSize: byte; スプライトパターンのデータ長

サンプル

8x8 スプライトをスプライトモード 1 で拡大表示します。

SpriteTest1.pas
program SpriteTest1;
{$I MDLLIB.LIB}
{$I VRAM1.LIB}
{$I SPRITE1.LIB}
const
  Data: TSpDat8 = (
    $3C, $7E, $D7, $D7, $FF, $7E, $24, $C3);
begin
  Color(1, 1, 1);
  ScrMode(2);

  InitSprite(2);
  SetSpritePtn(0, Data);
  PutSprite(0, $60, $60,  6, 0);
  PutSprite(1, $70, $60, 12, 0);
  PutSprite(2, $80, $60,  4, 0);

  Readln;
  ScrMode(0);
  Color(15, 4, 7);
  TextMode;
end.

image.png

16x16 スプライトをスプライトモード 2 (MSX2 以降) で拡大表示します。

SpriteTest4.pas
program SpriteTest4;
{$I MDLLIB.LIB}
{$I VRAM2.LIB}
{$I SPRITE2.LIB}
const
  Data: TSpDat16 = (
    $40, $E0, $40, $41, $43, $47, $47, $4F,
    $6F, $FF, $7D, $4C, $4E, $4F, $4F, $5F,
    $0C, $12, $17, $F2, $FA, $FC, $FC, $5E,
    $5F, $FE, $16, $06, $0E, $FE, $FE, $1F);
  Colors1: TSpClrs = (
    $02, $03, $04, $05, $06, $07, $08, $09, 
    $0A, $0B, $0C, $0D, $0E, $0F, $02, $03);
  Colors2: TSpClrs = (
    $04, $05, $06, $07, $08, $09, $0A, $0B, 
    $0C, $0D, $0E, $0F, $02, $03, $04, $05);
  Colors3: TSpClrs = (
    $06, $07, $08, $09, $0A, $0B, $0C, $0D, 
    $0E, $0F, $02, $03, $04, $05, $06, $07);
begin
  Color(1, 1, 1);
  ScrMode(4);

  InitSprite(3);
  SetSpritePtn(0, Data);
  PutSprite(0, $50, $50, $00, 0);
  ColorSprite(0, Colors1);
  PutSprite(1, $70, $50, $00, 0);
  ColorSprite(1, Colors2);
  PutSprite(2, $90, $50, $00, 0);
  ColorSprite(2, Colors3);

  Readln;
  ScrMode(0);
  Color(15, 4, 7);
  TextMode;
end.

image.png

SPRITE1.LIB / SPRITE2.LIB は予告なく変更になる事があります。

トランジェントコマンド

本記事にあるライブラリを用いて作られたトランジェントコマンド (外部コマンド) です。アーカイブには実行形式ファイル (*.COM) とソースファイル (*.PAS) が含まれています。

MSX-DOS2 上でコンパイルされているため、少なくとも MSX0 上で動作しない事はないと思います (MSX-DOS の方が TPA の空き領域が広いため、MSX-DOS 上でそのままコンパイルすると MSX-DOS2 で動作しない事があり得る)。

記事中のトランジェントコマンドのソースコード/バイナリは GitHub からもダウンロードできます。

■ M0SETCLR

前景色、背景色、ボーダー色を設定する。

image.png
image.png

Usage
Usage: M0SETCLR [/Fnum] [/Bnum] [/Dnum]
  • パラメータなしで実行すると、現在の設定を表示します。
  • スイッチは - でも / でもよく、大文字/小文字も判断しません。
  • 無効なスイッチは無視されます。
  • MSX0 固有の機能に依存していません。

Download: M0SetClr_100.zip (ht-deko.com)

■ TPKEYS

Turbo Pascal 用ファンクションキーの設定と表示切替を行う。

image.png

Usage
Usage: TPKEYS [/B] [/I] [/P] [/T] [/S] [/H] [/R<:file>] [/W<:file>]
  • /B または /I でファンクションキーの内容を初期化 (BASIC) します。
  • /P または /T でファンクションキーの内容を Turbo Pascal 用に設定します。
  • /S でファンクションキーの内容を表示します。
  • /H でファンクションキーの内容を非表示にします。
  • /R で設定をファイル (ファイル名省略時 FUNCKEYS.DAT) から読み込みます。
  • /W で現在の設定をファイル (ファイル名省略時 FUNCKEYS.DAT) へ書き出します。
  • 複数のスイッチを指定できます (左から順に実行されます)。
  • スイッチは - でも / でもよく、大文字/小文字も区別しません。
  • 無効なスイッチは無視されます。
  • MSX0 固有の機能に依存していません。

FUNCKEYS.DAT の先頭 4 バイトはファイルヘッダです (編集不可)。次に 16文字x10個のデータ (160 バイト) が続きます。以後、256 バイト目 (ファイル末) までのデータはゴミです。

おわりに

Delphi 使いはニッコリかもですね。Turbo Pascal 自身が持つルーチンについては次の記事を参考にしてください。

車輪の再発明をせず、アプリケーションのためのコードだけを書けばいいって幸せですね。MDL-LIB の作者に感謝です。

See also:

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?