グラフィックV-RAM
グラフィックV-RAMとは
グラフィックV-RAMは通常、J-3100やPC/AT互換機でいうところのV-RAMのことです。文字専用ではないため、自由にドット単位で図形や絵などが表示可能です。
ただし、PC-9801ではテキストV-RAMが存在する関係でグラフィックV-RAMは多くの機種で低速です。テキストの表示はできる限りテキストV-RAMを使い、グラフィックV-RAMは罫線程度のものを表示するぐらいに留めておいた方が良いです。
ただし、PC-9801ではテキストV-RAMが存在する関係でグラフィックV-RAMは多くの機種で低速です。テキストの表示はできる限りテキストV-RAMを使い、グラフィックV-RAMは罫線程度のものを表示するぐらいに留めておいた方が良いです。
デジタルモードとアナログモード
PC-9801は当初ビジネスマシンとして発売されたものです。なので、初期の機種ではデジタル8色表示でした。その後、PC-9801VMが発売されると、4096色中16表示が可能になり、以降PC-9801では4096色中16色表示が標準となりました。
PC-9801のBIOSではデジタル8色モードに関する機能は用意されていますが、アナログモードに関する機能が用意されていません。そのため、アナログ16色モードを使うためには、I/Oポートの操作が必要となります。
パソコンでプログラムを作る時、特にMSXやPC/AT互換機のような異なるメーカーで互換性を保つような機種では、極力ROM内ルーチンを直接コールしたりI/Oポートを直接操作したりしないのが普通ですが、NECのPCシリーズ・・・とりわけPC-9801シリーズでは直接I/Oポートを操作しなければならない場面が普通に出てきます。
PC/AT互換機とPC-9801では歴史的な経緯の違いにより互換性を保つ手段が異なります。PC/AT互換機は異なるコントローラーでBIOS上で互換性を保つように作られていたため、BIOSが充実していてI/Oポートを直接操作する必要はめったにありませんが、PC-9801はコントローラーコマンドといったハード上での互換性を保つように作られたため、BIOSはさほど充実してないようです。
パソコンでプログラムを作る時、特にMSXやPC/AT互換機のような異なるメーカーで互換性を保つような機種では、極力ROM内ルーチンを直接コールしたりI/Oポートを直接操作したりしないのが普通ですが、NECのPCシリーズ・・・とりわけPC-9801シリーズでは直接I/Oポートを操作しなければならない場面が普通に出てきます。
PC/AT互換機とPC-9801では歴史的な経緯の違いにより互換性を保つ手段が異なります。PC/AT互換機は異なるコントローラーでBIOS上で互換性を保つように作られていたため、BIOSが充実していてI/Oポートを直接操作する必要はめったにありませんが、PC-9801はコントローラーコマンドといったハード上での互換性を保つように作られたため、BIOSはさほど充実してないようです。
V-RAM
V-RAMの構造は、PC/AT互換機と同じようにプレーン0からプレーン3まであります。ただし、PC/AT互換機とは異なり同じ各プレーンが同じアドレスにマッピングされているわけではなく、それぞれ異なるアドレスにマッピングされています。また、歴史的な経緯により16色モードは建て増しで作られたため、プレーン3はアドレスが飛んでいます。

プレーン0~2はそれぞれBRGの発色を担当しており、プレーン3はPC/AT互換機と同じく明るい色にするかどうかを区別します。
また、V-RAMの同じアドレスに「表バンク」「裏バンク」がマッピングされており、表と裏を切り替える事でアニメーションを作ったり(裏バンクに画像を転送しておいてバンク切り替えによって高速に画面を切り替える)、裏バンクをワークエリアに使ったりする事ができます。

プレーン0~2はそれぞれBRGの発色を担当しており、プレーン3はPC/AT互換機と同じく明るい色にするかどうかを区別します。
また、V-RAMの同じアドレスに「表バンク」「裏バンク」がマッピングされており、表と裏を切り替える事でアニメーションを作ったり(裏バンクに画像を転送しておいてバンク切り替えによって高速に画面を切り替える)、裏バンクをワークエリアに使ったりする事ができます。
グラフィックV-RAM使用開始
初期状態ではグラフィックV-RAMは使わない設定になっているので、グラフィックV-RAMに書き込みをしても何も表示されません。そこで、グラフィックV-RAMを使う前にコントローラーに使用開始を命令します。I/Oポートを操作してもできますが、互換性を考えてできる限りBIOSでできるものはBIOSで行います。
AH=40H グラフィックV-RAMの使用開始
AH=40H グラフィックV-RAMの使用開始
MOV AH,40H INT 18H
AH=41H グラフィックV-RAMの使用停止
MOV AH,41H INT 18H
AH=42H 400ラインモードか200ラインモードかを指定します。
CHレジスターでモードを指定します。
200ラインアッパーにすると、V-RAMはオフセット0000Hから、200ラインローワーにすると、V-RAMはオフセット3E80Hから使われます。
| ビット | 意味 |
|---|---|
| 7~6 | ビット7・6がそれぞれ、 01 200ライン(アッパー) 10 200ライン(ローワー) 11 400ライン |
| 5 | 0 カラー 1 モノクロ |
| 4 | 0 表バンク使用 1 裏バンク使用 |
| 3~0 | 未使用 |
200ラインアッパーにすると、V-RAMはオフセット0000Hから、200ラインローワーにすると、V-RAMはオフセット3E80Hから使われます。
MOV AH,42H MOV CH,192 INT 18H
この例では、400ライン・カラー・バンク0を指定しています。
デジタルパレット
デジタル8色パレットを変更します。
AH=43H
CS:BX パレットのデーター 4ビットずつ指定します。
使い道とすれば、SA・ZI・RIやリバイバーで夜になった効果(全体的に青っぽくなる)ぐらいでしょうか。あと、アクションゲームで背景を1つのプレーン、キャラクターで他の2プレーンに使い不自然にならない配色にするとか。
ドラゴンスレイヤー英雄伝説みたいに画面がフェードアウトするような効果はアナログパレットを使わないと無理ですね。
AH=43H
CS:BX パレットのデーター 4ビットずつ指定します。
| アドレス | 意味 | |
|---|---|---|
| +0 | ビット0~3 | カラーコード7のカラー |
| ビット4~7 | カラーコード6のカラー | |
| +1 | ビット0~3 | カラーコード5のカラー |
| ビット4~7 | カラーコード4のカラー | |
| +2 | ビット0~3 | カラーコード3のカラー |
| ビット4~7 | カラーコード2のカラー | |
| +3 | ビット0~3 | カラーコード1のカラー |
| ビット4~7 | カラーコード0のカラー | |
使い道とすれば、SA・ZI・RIやリバイバーで夜になった効果(全体的に青っぽくなる)ぐらいでしょうか。あと、アクションゲームで背景を1つのプレーン、キャラクターで他の2プレーンに使い不自然にならない配色にするとか。
ドラゴンスレイヤー英雄伝説みたいに画面がフェードアウトするような効果はアナログパレットを使わないと無理ですね。
アナログパレット
アナログモードに関しては、後から追加したためかBIOSにアナログパレットを操作する機能がありません。仕方がないのでI/Oポートを操作します。というかINT
18Hを拡張してアナログパレットを操作できるようにしてくれてもバチは当たらないような気もしますが。このように、PC-9801ではI/Oポートを操作しなければならない場面が頻繁に出てきます。
デジタル8色モードにする
デジタル8色モードにする
MOV AL,0 OUT 06AH,AL
アナログ4096色中16色モードにする
MOV AL,1 OUT 06AH,AL
アナログパレットはデフォルトでこのようになっています。PC/AT互換機のような、暗い黄色のところに茶色に当てられたりはしていません。
変更するためには、以下のI/OポートにWriteします。
まず、A8Hに設定したいパレット番号をWriteした後に、AAH、ACH、AEHにBRGそれぞれの明るさを4ビットでwriteします。パレット番号は0~15まで、BRGそれぞれの明るさも0~15までです。したがって、16×16×16=4096色中の16色が同時に発色できます。
| プレーン | 色 | デフォルトの明るさ (BRG) |
デフォルトの パレット番号 |
|||
|---|---|---|---|---|---|---|
| 3 | 2 | 1 | 0 | |||
| 0 | 0 | 0 | 0 | 黒 | 000H | 00H |
| 0 | 0 | 0 | 1 | 暗い青 | 007H | 01H |
| 0 | 0 | 1 | 0 | 暗い赤 | 070H | 02H |
| 0 | 0 | 1 | 1 | 暗いマゼンダ | 077H | 03H |
| 0 | 1 | 0 | 0 | 暗い緑 | 700H | 04H |
| 0 | 1 | 0 | 1 | 暗いシアン | 707H | 05H |
| 0 | 1 | 1 | 0 | 暗い黄色 | 770H | 06H |
| 0 | 1 | 1 | 1 | 暗い白 | 777H | 07H |
| 1 | 0 | 0 | 0 | 明るい黒 | 444H | 08H |
| 1 | 0 | 0 | 1 | 明るい青 | 00FH | 09H |
| 1 | 0 | 1 | 0 | 明るい赤 | 0F0H | 0AH |
| 1 | 0 | 1 | 1 | 明るいマゼンダ | 0FFH | 0BH |
| 1 | 1 | 0 | 0 | 明るい緑 | F00H | 0CH |
| 1 | 1 | 0 | 1 | 明るいシアン | F0FH | 0DH |
| 1 | 1 | 1 | 0 | 明るい黄色 | FF0H | 0EH |
| 1 | 1 | 1 | 1 | 明るい白 | FFFH | 0FH |
変更するためには、以下のI/OポートにWriteします。
| アドレス | 意味 | |
|---|---|---|
| A8H | ビット0~3 | パレット番号 |
| ビット4~7 | 未使用 | |
| AAH | ビット0~3 | 緑の明るさ |
| ビット4~7 | 未使用 | |
| ACH | ビット0~3 | 赤の明るさ |
| ビット4~7 | 未使用 | |
| AEH | ビット0~3 | 青の明るさ |
| ビット4~7 | 未使用 | |
V-RAMの開始アドレス
V-RAMの横幅はPC/AT互換機のVGAと同じく640ドット80バイトですので、左上を(0,0)右下を(639,399)とすると、座標(X,Y)のアドレスは、(Y*80)+(X/8)となり、
;==============================================================================
; 開始アドレスセット
; In:GX1 GY1 Out:SADDR
;==============================================================================
CSET: MOV AX,[GX1]
SHR AX,1
SHR AX,1
SHR AX,1
MOV [K1],AX
MOV AX,[GY1]
MOV BX,80
MUL BX
MOV [K2],AX
MOV AX,[K1]
ADD AX,[K2]
MOV [SADDR],AX
RET
というようなサブルーチンを作っておくと便利です。「処理に変数が多すぎて実用的ではありません(©虎鉄)」って言われそうですけど、そこはまあご愛嬌で。
GRCGを使ったプレーンの操作
V-RAMはプレーン0~3まであり、それぞれのプレーンに同じ物を書いていたのでは処理の低速化を招きます。そこで、GRCGを使って書き込むプレーンを指定しておき、あとは代表的にプレーン0にだけ書き込めば処理は高速化されます。
まずモードレジスタ7CHでGRCGの使用、使用するプレーンを選択します。PC/AT互換機でいうところの「マップマスクレジスタ」「リードマップセレクトレジスタ」のようなものですね。
モードレジスタ7CH
ポート7CHのビット7に1を書き込みGRCGを有効にすると、ポート7EHはタイルレジスタとして動作します。1回書き込むたびにプレーン0、プレーン1、プレーン2、プレーン3に対するタイルパターンの設定になります。PC/AT互換機でいうところの「ビットマスクレジスタ」のようなものですね。タイルレジスタは必ずプレーン0~3までセットで指定しなければなりません。
タイルレジスタ 7EH
参考文献(PC-9801スーパーテクニック)では、タイルレジスタとして7CHに書き込んでましたけど、多分ミスプリじゃないかと思います。どうでもいいけど、この本けっこうミスプリが多いです。(もっとも、このサイトも人の事いえないぐらい多いですが)
例) [IRO]にカラーコード、タイルパターンは全プレーン255(全ビットオン)として、
まずモードレジスタ7CHでGRCGの使用、使用するプレーンを選択します。PC/AT互換機でいうところの「マップマスクレジスタ」「リードマップセレクトレジスタ」のようなものですね。
モードレジスタ7CH
| ビット | 意味 |
|---|---|
| 7 | 0 GRCG無効 1 GRCG有効 |
| 6 | 0 TDW/TCRモード 1 RMWモード |
| 5~4 | 未使用 |
| 3 | プーン3へのアクセス指定(0で有効) |
| 2 | プーン2へのアクセス指定(0で有効) |
| 1 | プーン1へのアクセス指定(0で有効) |
| 0 | プーン0へのアクセス指定(0で有効) |
ポート7CHのビット7に1を書き込みGRCGを有効にすると、ポート7EHはタイルレジスタとして動作します。1回書き込むたびにプレーン0、プレーン1、プレーン2、プレーン3に対するタイルパターンの設定になります。PC/AT互換機でいうところの「ビットマスクレジスタ」のようなものですね。タイルレジスタは必ずプレーン0~3までセットで指定しなければなりません。
タイルレジスタ 7EH
| 書き込み回数 | 意味 |
|---|---|
| 1回目 | プレーン0へのタイルパターンの設定 |
| 2回目 | プレーン1へのタイルパターンの設定 |
| 3回目 | プレーン2へのタイルパターンの設定 |
| 4回目 | プレーン3へのタイルパターンの設定 |
例) [IRO]にカラーコード、タイルパターンは全プレーン255(全ビットオン)として、
;-------------- GRCG有効、RMWモード、全プレーン有効 MOV AL,192 OUT 7CH,AL ;-------------- タイルレジスタ設定 ;----------- (1) MOV AL,[IRO] AND AL,1 CMP AL,0 JE TAIL_SET1 MOV AL,255 OUT 7EH,AL JMP TAIL_SET2 TAIL_SET1 = $ MOV AL,0 OUT 7EH,AL ;----------- (2) TAIL_SET2 = $ MOV AL,[IRO] AND AL,4 CMP AL,0 JE TAIL_SET3 MOV AL,255 OUT 7EH,AL JMP TAIL_SET4 TAIL_SET3 = $ MOV AL,0 OUT 7EH,AL ;----------- (3) TAIL_SET4 = $ MOV AL,[IRO] AND AL,2 CMP AL,0 JE TAIL_SET5 MOV AL,255 OUT 7EH,AL JMP TAIL_SET6 TAIL_SET5 = $ MOV AL,0 OUT 7EH,AL ;----------- (4) TAIL_SET6 = $ MOV AL,[IRO] AND AL,8 CMP AL,0 JE TAIL_SET7 MOV AL,255 OUT 7EH,AL JMP TAIL_SET8 TAIL_SET7 = $ MOV AL,0 OUT 7EH,AL TAIL_SET8 = $
TDWモードで書き込むと、V-RAMに何を書いてもタイルレジスタの値が書き込まれます。特定のビットパターンで書き込みたい時に便利です。また、RMWモードで書き込むと、V-RAMに書いたデーターとタイルレジスタとANDを取った値が書き込まれます。特定の箇所を消したい時に便利です。
TCRモードで読み込むと、各タイルレジスター0~3とプレーン0~3、それぞれとANDを取った値が読み出されます。特定のプレーンの特定の場所にドットがあるかどうか調べたい時は、各プレーンに対応するタイルレジスタの調べたい場所のビットを立てておいて、読み込んで0かどうかで判別します。また、特定のプレーン全体を調べたい時は、調べたいプレーンのタイルレジスターを0FFHにしておき、他のプレーンのタイルレジスタを00Hにしておきます。
残念なのは、GRCGにはVGA搭載のPC/AT互換機のようなデーターローテートレジスタがない事です。ビット演算が必要な時はEGCを使う必要があります。
TCRモードで読み込むと、各タイルレジスター0~3とプレーン0~3、それぞれとANDを取った値が読み出されます。特定のプレーンの特定の場所にドットがあるかどうか調べたい時は、各プレーンに対応するタイルレジスタの調べたい場所のビットを立てておいて、読み込んで0かどうかで判別します。また、特定のプレーン全体を調べたい時は、調べたいプレーンのタイルレジスターを0FFHにしておき、他のプレーンのタイルレジスタを00Hにしておきます。
残念なのは、GRCGにはVGA搭載のPC/AT互換機のようなデーターローテートレジスタがない事です。ビット演算が必要な時はEGCを使う必要があります。
EGCを使ったプレーンの操作
EGCを使う事でVGA搭載のPC/AT互換機のような高速で複雑なV-RAMの操作ができます。しかし、EGCを使うと対応機種が「VX/UX以降」になります。とはいえ、PC-9801が本格的にゲーム機として使われだしたのはVX/UXが発売されて以降なので、ゲームソフトを作る上では特に障害にはならなかったようです。PC-9801のアクションゲームに「VX/UX以降」が多いのはこのためです。
EGC搭載機種であってもGRCGを使う事もできます。これは、PC-9801の歴史的な経緯により、上位互換を保ちつつコントローラーを後付けで建て増しを続けたためです。
ポート6AH EGCを有効にする
EGCを有効にするためには、(1)モード変更可(2)拡張モード(3)モード変更不可と3段階の操作が必要です。これは通常はモード変更不可の状態にしておく必要があるためです。
例)拡張モードオンにする
EGC搭載機種であってもGRCGを使う事もできます。これは、PC-9801の歴史的な経緯により、上位互換を保ちつつコントローラーを後付けで建て増しを続けたためです。
ポート6AH EGCを有効にする
EGCを有効にするためには、(1)モード変更可(2)拡張モード(3)モード変更不可と3段階の操作が必要です。これは通常はモード変更不可の状態にしておく必要があるためです。
| 値 | 意味 |
|---|---|
| 7 | モード変更可 |
| 6 | モード変更不可 |
| 5 | 拡張モード |
| 4 | GRCG互換モード |
例)拡張モードオンにする
;---------- 拡張モードON MOV AL,7 OUT 6AH,AL MOV AL,5 OUT 6AH,AL MOV AL,6 OUT 6AH,AL
ポート04A0H 書き込みプレーンの指定
どのプレーンに対して書き込むかを指定します。GRCGとは異なり16ビット長で、ワード単位で書き込みます。
どのプレーンに対して書き込むかを指定します。GRCGとは異なり16ビット長で、ワード単位で書き込みます。
| ビット | 意味 |
|---|---|
| 15~4 | 常に1 |
| 3 | プーン3へのアクセス指定(0で有効) |
| 2 | プーン2へのアクセス指定(0で有効) |
| 1 | プーン1へのアクセス指定(0で有効) |
| 0 | プーン0へのアクセス指定(0で有効) |
;--------- 全プレーン動作 MOV DX,04A0H MOV AX,0FFF0H OUT DX,AX
ポート 04A2H 読み込むプレーンとフォアグランドカラー、バックグランドカラーの指定
読み込むプレーン、フォアグランドカラー、バックグランドカラーの有効/無効を指定します。
ポート04A4H ビット演算指定
GRCGではできなかったビット演算の指定ができます。
ここでビット7~0の該当するビットを立てておくと、V-RAMに書き込む際に、有効になっている各プレーンに対して、CPUデーター、V-RAMデーター、パターンレジスタのそれぞれとANDを取った値が書き込まれます。複数のビットを立てておくと、それぞれの値とORを取った値が書き込まれます。
使い道ですが・・・よくわかりません。参考文献(PC-9801スーパーテクニック)でも肝心の説明の部分にミスプリがあったりしてよくわかりませんでした。市販の文献にもミスプリはあるもんだなーと。
で、文献によると、
RMWモード: V-RAMデーターとタイルレジスタのANDを取った値→ 2CACH
上書きモード:V-RAMデーターに関係なくCPUデーターとタイルレジスタのANDの値→2CA0H
らしいので、仕方がないのでこの2つだけを使ってました。根拠となる計算式は難しくて私にはわかりませんでした。
どうもPC-9801のプログラムは一見さんお断りみたいな所があって難しいです。複雑な演算が可能な反面、設定が難しいです。PC/AT互換機のデーターローテートレジスタみたいにシンプルにできなかったものかと。
ポート04A6H フォアグランドカラーの指定
GRCGを使う場合、カラーコードを判断して各プレーンに対してタイルレジスターを00HやFFHを設定しました。EGCではフォアグランドカラー/バックグランドカラーを有効にすると、タイルレジスターを使わずにカラーコードを指定する事で同様の処理ができます。
ポート04AAH バックグランドカラーの指定
該当するビットが1のドットがフォアグランドカラー、0のドットがバックグランドカラーで描画されます。
ポート04A8H マスクレジスタの指定
16ビット幅あり、該当ビットを0にしておくとV-RAMへのライトがマスクされます。全てのプレーンに対してマスクされます。
ブロック転送
カラーモード時にV-RAMのプレーン0~3をまとめて別の場所に移動させたい時がよくあります。この場合、プレーン0~3をそれぞれ4回ブロック転送すれば良いわけですが、それだとスクロールさせた時にRBGが別々にスクロールする事になり美しくないです。そこで、全てのプレーンを同時に動かす事ができます。VGA搭載のPC/AT互換機のグラフィックコントローラーにある「書き込みモード1」のようなものです。
4ACH ビットアドレスの指定
キャラクター単位でスクロールさせるのではなく、ドット単位で横スクロールさせたい時は、ビット0~7で先頭のビットアドレスを指定します。
4AEH ビット長の指定
ブロック転送する時のビット長を指定します。0~4095を指定します。結果、1~4096ビットまで同時に転送ができます。
実際にブロック転送をする時は、DSレジスターとESレジスターにA800H、SIレジスターに転送元アドレス、DIレジスターに転送先アドレスをセットして、MOVSB命令を発動します。4AEHにセットしたビット長がブロック転送されます。4096バイト以上転送する時は、CXレジスターに繰り返す回数をセットしておいて、
CLD
REP MOVSB
のようにします。
例)ワプの翼の効果(WPCLS98)の一部
読み込むプレーン、フォアグランドカラー、バックグランドカラーの有効/無効を指定します。
| ビット | 意味 |
|---|---|
| 15 | 常に0 |
| 14 | フォアグランドカラーを有行為にする(1で有効) |
| 13 | バックグランドカラーを有行為にする(1で有効) |
| 12 | 常に0 |
| 11 | プレーン3に対する読み込み指定(0で有効) |
| 10 | プレーン2に対する読み込み指定(0で有効) |
| 9 | プレーン1に対する読み込み指定(0で有効) |
| 8 | プレーン0に対する読み込み指定(0で有効) |
| 7~0 | 常に1 |
ポート04A4H ビット演算指定
GRCGではできなかったビット演算の指定ができます。
| ビット | 意味 |
|---|---|
| 15 | 常に0 |
| 14 | 常に0 |
| 13 | コンペアリード 0する 1しない |
| 12~11 | ビット12・11が、 00: CPUデーター 01: ラスタオペレーションの結果 10: パターンレジスタの値 |
| 10 | 読み込んだ場合に返す値 0 V-RAMデーター 1 CPUデーター |
| 9 | 0 パターンレジスタ変更なし 1 書き込み時に前のV-RAMデーターをパターンレジスタにセットしてから書き込む |
| 8 | 0 パターンレジスタ変更なし 1 読み込む時にV-RAMのデーターがパターンレジスタにセットされる |
| 7~0 | ビット演算指定 |
ここでビット7~0の該当するビットを立てておくと、V-RAMに書き込む際に、有効になっている各プレーンに対して、CPUデーター、V-RAMデーター、パターンレジスタのそれぞれとANDを取った値が書き込まれます。複数のビットを立てておくと、それぞれの値とORを取った値が書き込まれます。
| ビット | パターンレジスタ | CPUデーター | V-RAMデーター |
|---|---|---|---|
| 7 | |||
| 6 | NOT | ||
| 5 | NOT | ||
| 4 | NOT | NOT | |
| 3 | NOT | ||
| 2 | NOT | NOT | |
| 1 | NOT | NOT | |
| 0 | NOT | NOT | NOT |
使い道ですが・・・よくわかりません。参考文献(PC-9801スーパーテクニック)でも肝心の説明の部分にミスプリがあったりしてよくわかりませんでした。市販の文献にもミスプリはあるもんだなーと。
で、文献によると、
RMWモード: V-RAMデーターとタイルレジスタのANDを取った値→ 2CACH
上書きモード:V-RAMデーターに関係なくCPUデーターとタイルレジスタのANDの値→2CA0H
らしいので、仕方がないのでこの2つだけを使ってました。根拠となる計算式は難しくて私にはわかりませんでした。
どうもPC-9801のプログラムは一見さんお断りみたいな所があって難しいです。複雑な演算が可能な反面、設定が難しいです。PC/AT互換機のデーターローテートレジスタみたいにシンプルにできなかったものかと。
ポート04A6H フォアグランドカラーの指定
GRCGを使う場合、カラーコードを判断して各プレーンに対してタイルレジスターを00HやFFHを設定しました。EGCではフォアグランドカラー/バックグランドカラーを有効にすると、タイルレジスターを使わずにカラーコードを指定する事で同様の処理ができます。
| ビット | 意味 |
|---|---|
| 7~4 | 常に0 |
| 3~0 | フォアグランドカラー 0~15 |
ポート04AAH バックグランドカラーの指定
| ビット | 意味 |
|---|---|
| 7~4 | 常に0 |
| 3~0 | バックグランドカラー 0~15 |
ポート04A8H マスクレジスタの指定
16ビット幅あり、該当ビットを0にしておくとV-RAMへのライトがマスクされます。全てのプレーンに対してマスクされます。
ブロック転送
カラーモード時にV-RAMのプレーン0~3をまとめて別の場所に移動させたい時がよくあります。この場合、プレーン0~3をそれぞれ4回ブロック転送すれば良いわけですが、それだとスクロールさせた時にRBGが別々にスクロールする事になり美しくないです。そこで、全てのプレーンを同時に動かす事ができます。VGA搭載のPC/AT互換機のグラフィックコントローラーにある「書き込みモード1」のようなものです。
4ACH ビットアドレスの指定
| ビット | 意味 |
|---|---|
| 15~13 | 常に0 |
| 12 | 0 アドレスの低い方から高い方へ転送 1 アドレスの高い方から低い方へ |
| 7~4 | ソースビットアドレス |
| 3~0 | ディスティネーションビットアドレス |
4AEH ビット長の指定
| ビット | 意味 |
|---|---|
| 15~12 | 常に0 |
| 11~0 | 転送ビット長-1 |
実際にブロック転送をする時は、DSレジスターとESレジスターにA800H、SIレジスターに転送元アドレス、DIレジスターに転送先アドレスをセットして、MOVSB命令を発動します。4AEHにセットしたビット長がブロック転送されます。4096バイト以上転送する時は、CXレジスターに繰り返す回数をセットしておいて、
CLD
REP MOVSB
のようにします。
例)ワプの翼の効果(WPCLS98)の一部
;---------- EGCを動作可能にする
PUSH ES
MOV AX,0
MOV ES,AX
PUSHF
CLI
MOV AL,128
OUT 7CH,AL
MOV ES:[0495H],AL
POPF
POP ES
;---------- 拡張モードON
MOV AL,07H
OUT 6AH,AL
MOV AL,5
OUT 6AH,AL
MOV AL,06H
OUT 6AH,AL
;--------- 全プレーン動作、パターンレジスタを使用
MOV DX,04A0H
MOV AX,0FFF0H
OUT DX,AX
MOV DX,04A2H
MOV AX,255
OUT DX,AX
;-------- マスクなし ビットアドレス0 ビット長16
MOV DX,04A8H
MOV AX,0FFFFH
OUT DX,AX
MOV DX,04ACH
MOV AX,0
OUT DX,AX
MOV DX,04AEH
MOV AX,15
OUT DX,AX
;-------------------------------------------------------------------
; スクロールメイン
;-------------------------------------------------------------------
SCROL EQU $
MOV [CHURCH],BYTE PTR 3
MOV [GENKAI],BYTE PTR 0
MOV [MOU],BYTE PTR 3
SCROL2 EQU $
MOV [BY1],BYTE PTR 3
SCROL3 EQU $
CALL PUTB
MOV AL,[BY1]
CMP AL,[CHURCH]
JAE SCROL4
ADD [BY1],BYTE PTR 1
CMP [BY1],BYTE PTR 48
JA SCROL5
JMP SCROL3
SCROL4 EQU $
SUB [MOU],BYTE PTR 1
CMP [MOU],BYTE PTR 0
JNE SCROL2
ADD [CHURCH],BYTE PTR 2
MOV [MOU],BYTE PTR 3
JMP SCROL2
SCROL5 EQU $
CALL SIRO
ADD [GENKAI],BYTE PTR 1
CMP [GENKAI],BYTE PTR 25
JA SCROL6
JMP SCROL2
SCROL6 EQU $
JMP OWARI
;-------------------------------------------------------------------
; 四角のBLOCKを1ブロック上に複写
;
; In:BY1 Out:なし
;-------------------------------------------------------------------
PUTB EQU $
;------- VRAMをパターンレジスタにいれて、パターンレジスタをライト
MOV DX,04A4H
MOV AX,0011000110000000B
OUT DX,AX
MOV AL,[BY1]
CMP AL,1
JBE PUTBEN
CMP AL,50
JA PUTBEN
MOV [GX1],WORD PTR 0
MOV [GX2],WORD PTR 0
MOV AL,[BY1]
SUB AL,1
MOV AH,0
SHL AX,1
SHL AX,1
SHL AX,1
MOV [GY1],AX
JMP L8
PUTBEN: RET
;-------------------------------------------------------------------
; 四角PUT
;
;-------------------------------------------------------------------
L8 = $
;-------------------------------------------------------------------
; カラー用
;-------------------------------------------------------------------
COLL81 = $
CALL CSSET
MOV BX,[SADDR]
MOV DX,BX
SUB DX,280H
SUB DX,280H
PUSH DS
MOV AX,0A800H
MOV DS,AX
MOV ES,AX
MOV SI,BX
MOV DI,DX
MOV CX,640
CLD
REP MOVSB
POP DS
RET
;-------------------------------------------------------------------
; 黒い四角のLINEを最下段に引く
;
; In:BY1 Out:なし
;-------------------------------------------------------------------
SIRO = $
;-----------カラー用
CSIRO = $
;------- VRAMをパターンレジスタにいれて、CPUデータをライト
MOV DX,04A4H
MOV AX,0000000110000000B
OUT DX,AX
MOV CX,640
MOV SI,7800H
MOV AX,0
PUSH DS
MOV BX,0A800H
MOV DS,BX
MOV ES,BX
CLD
REP STOSW
POP DS
CSL8EN = $
腕の見せ所
BIOSが貧弱な分、PC-9801はI/Oポートを直接操作したさまざまなライブラリが作られ、プログラマのスキル次第で極めれば本体性能を120%引き出したような高速処理も可能でした。
しかし、残念ながら当時は今のようにインターネットがあるわけではなく、プログラマ同士の情報交換はパソコン通信ぐらいしかなく、同じ処理(画面に罫線や矩形を描く)にしても、それぞれ皆が別々に作ってました。
また、せっかくPC-9801でのテクニックを極めても、現在のWindowsでプログラミングする上でほとんど経験が役に立たないのも残念です。
しかし、残念ながら当時は今のようにインターネットがあるわけではなく、プログラマ同士の情報交換はパソコン通信ぐらいしかなく、同じ処理(画面に罫線や矩形を描く)にしても、それぞれ皆が別々に作ってました。
また、せっかくPC-9801でのテクニックを極めても、現在のWindowsでプログラミングする上でほとんど経験が役に立たないのも残念です。
参考文献
『PC‐9801スーパーテクニック』 1992年 小高輝真、清水和文、速水祐 著 アスキー
『J-3100解析ハンドブック』 1989年 土屋勝著 ナツメ社
『DOS/Vテクニカル・リファレンス・マニュアル』 1993年 芦達剛著 ソフトバンク
『PC‐9801スーパーテクニック』 1992年 小高輝真、清水和文、速水祐 著 アスキー
『J-3100解析ハンドブック』 1989年 土屋勝著 ナツメ社
『DOS/Vテクニカル・リファレンス・マニュアル』 1993年 芦達剛著 ソフトバンク
このページの先頭へ
広告
