はじめに
『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()
型
名前 | 定義 | 説明 |
---|---|---|
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
*)
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 を渡しています。
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
*)
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
*)
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
*)
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 で拡大表示します。
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.
16x16 スプライトをスプライトモード 2 (MSX2 以降) で拡大表示します。
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.
SPRITE1.LIB / SPRITE2.LIB は予告なく変更になる事があります。
トランジェントコマンド
本記事にあるライブラリを用いて作られたトランジェントコマンド (外部コマンド) です。アーカイブには実行形式ファイル (*.COM
) とソースファイル (*.PAS
) が含まれています。
MSX-DOS2 上でコンパイルされているため、少なくとも MSX0 上で動作しない事はないと思います (MSX-DOS の方が TPA の空き領域が広いため、MSX-DOS 上でそのままコンパイルすると MSX-DOS2 で動作しない事があり得る)。
記事中のトランジェントコマンドのソースコード/バイナリは GitHub からもダウンロードできます。
■ M0SETCLR
前景色、背景色、ボーダー色を設定する。
Usage: M0SETCLR [/Fnum] [/Bnum] [/Dnum]
- パラメータなしで実行すると、現在の設定を表示します。
- スイッチは
-
でも/
でもよく、大文字/小文字も判断しません。 - 無効なスイッチは無視されます。
- MSX0 固有の機能に依存していません。
Download: M0SetClr_100.zip (ht-deko.com)
■ TPKEYS
Turbo Pascal 用ファンクションキーの設定と表示切替を行う。
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: