Pocket386でアルフォスを動かした!

衝動的にPocket386というコンピュータを手に入れた!


CPUに386SXを積んだPC/AT互換機で、主OSがMS-DOSという「昭和の時代?!」と思うようなコンピュータだ!
以前から気になっていたんだけど、ここんところのストレスが半端なくて指が勝手にクリックしてしまった!(イイワケ

 

見よ!この勇姿!!(^o^)

そして起動と同時にコマンドプロンプトが出るユーザーの突き放し方!(^^;;

 

基本的な使い方はMS-DOSでアプリやゲームを動かすんだと思う。

そしてたまにWindows3.xを動かして優越感に浸る…(^^;


……それだけ?
……使い方としてはそんな感じ??
………それ、本当に今の時代に必要?(^^;;;

いかん!

ここで使い方を見失ってしまうと、手に入れた大義名分が無くなってしまう!(^^;

 

せっかくだから、最近流行ってるっぽいメキシカンハットでも表示させてみようかな!
最初からGW-BASICが入ってるから利用は簡単だけど…GW-BASICってグラフィック使えるんだっけ??
CP/MのMBASICではグラフィックが使えなかったので、当然のように使えないと思っていたのだが……。

 

GW-BASICのリファレンスを調べてみたら、驚いたことにPSETやLINE、PAINTといったグラフィックを扱う命令が用意されていた!

 

知らんかったー!

GW-BASICってグラフィック使えたんだ(^^;;

とりあえずPSET命令があればメキシカンハットは作れるけれど……

BASICで書いただけってのも味がないなー。

でも試しにやってみるけどね!(^^;;

 

せめてC言語で書いてみるのはどうだろうと思った時、はて、AT互換機でVRAMにアクセスするのはどうしたら良いんだろう?と疑問に…。

 

AT互換機でグラフィックを扱ったのは、Linuxがまだ1.0に達していなかった頃に使っていたX-Windowの、XFree86のVideo Driverを書いたのが最初で最後だ。この時はMach32というグラフィックチップのアクセラレーションを使うプログラムだった。

 

そんな事情で、MS-DOSでグラフィックを扱うプログラムは書いたことがないのだ!
CPUから直接VRAMにアクセスが出来るのか、はたまたやっぱりアクセラレーションを使わなければならないのか…すら知らない(^^;

 

そんなことを思いながら調べてみたのだが……興味深い事に気がついた。

EGAという規格で640x200ドット16色というモードが存在していた。
え?これって日本で良く使われるドット数じゃないのさ。
てっきりVGAに代表される640x480とか240とかだと思っていたのに!

 

もう少し調べてみたら、EGAってVGAが出てくる前の規格だったのね!
EGAが1984年、VGAが1987年に登場。
てっきりVGAのEnhancedな規格だからEGAだとか思い込んでたw(実際にEGA=Enhanced Graphics Adapterだし…)

 

そしてVRAM構成は、640x200のデータが4プレーンあるらしい。


うおお!それってPC-9801と同じ…というか、PC-8801とも同じじゃん。
PC-9801の場合はプレーンによってアドレス(というかセグメントというか…)がずれる。

EGAではアクセスするプレーンが違ってもアドレスは変化せず、I/Oポートにプレーンの情報を出力すれば良いらしい。
うむむ……見れば見るほどPC-9801のプログラムが移植できそうな気がしてならない…。

 

めちゃくちゃ興奮してきた気持ちを抑えつつ、もう少し詳しく調べてみると、やはり最初に想像したよりも簡単な話ではない事がわかってきた。


まずPC-9801はテキストVRAMとグラフィックが分離している。この両方を巧みに使っているプログラムはうまく動かせられない。スコア表示をテキストで…とか画面の一部をテキストでマスクして…みたいなタイプがソレだ。

 

さらにGDCの機能はPocket386には存在しないため、その機能を利用したモノもダメだ。

この時点でPC-9801用ゲームのギガンテスは候補から外れた(GDCの機能を利用して横512ドットに切り替えている)。

pocketgriffon.hatenablog.com

 

そんなことを考えていたら、まさに条件に合いそうなものが頭に浮かんだ!
そう…過去に開発した「PC-9801CV21の上で、PC-8801のアルフォスを動かした」プログラムだ!

pocketgriffon.hatenablog.com

これはPC-8801のプログラムPC-9801で動かすために表示周りを細工している。
これを上手に変更することで、Pocket386でも動かせるのでは??
そんな妄想をしちゃったから、さー大変だ!!

 

本当に移植できるのか??

これをちゃんと説明するためには、PC-9801で動いてるアルフォスの内部構造を詳しく説明する必要がある。
正直、かなり面倒だ(^^;;
でもきっと読む側から見たら面白い情報かも知れないので、頑張って説明を書いてみようと思う。

 

まずPC-8801用のアルフォスPC-9801で動かすためには、以下の要素が必要だ。
Z80エミュレータ
・メモリウィンドウの実現
・640x200x8色の画面モード
・パレット機能

 

Z80エミュレータ

要であるZ80CPUのエミュレータは、V30用のアセンブラ言語で書かれている。
オールアセンブラで4000行以上もあるプログラムだが、残念ながらZ80の全命令が実装されているわけではない。N88-BASICとアルフォスを動かすためだけに作られているので、これらで使われていない(特に2バイト長の)命令は実装されていない!(^^;


エミュレータを作る上で最も面倒と思われるフラグ生成は、V30自体での計算結果で得られたフラグそのものを利用する構造となっている。
多分、V30で動くZ80エミュレータとしては最速に近いだろう(^^)
このプログラムはPC-9801には依存していないため、Pocket386でもそのまま動く。

 

メモリウィンドウの実現

PC-8801にはメモリウィンドウという厄介な機能が備わっている。
これはバンク切り替えなどで複雑なメモリ構成を持つPC-8801において、64KBのメモリ(RAM)空間を効率アクセスするための機構で、1KBの範囲で任意のRAMを覗き見する事ができる"すぐれモノ"だ。

 

N88-BASICのインタプリタはこの機能を巧みに活用して動いている。
私が所有しているアルフォスはテープ版であり、ローダーはBASICで書かれている。
そのため、BASICを動かすためにメモリウィンドウを実装する必要があった。


このメモリウィンドウをきちんと処理しようとすると、メモリアクセスのたびにアドレスチェックと変換が必要となり、10MHzのV30でまともな速度で動かなくなってしまう。
そこで64KBのメモリ空間を64つに分割して、それぞれの領域でのセグメントを設定するテーブルを持つ事にした。

一種のMMUもどきっぽい構造を入れたわけだ。

世にも恐ろしい手書きの概念図…

この構造のおかげで、本来であればバンク切り替えしなくては見ることの出来ないN88-BASICのROMなどでも、面倒なアドレス変換を意識する必要が無くなった。

その代わり……と言うには大きすぎる代償だが、メモリアクセスは全領域で一様に"遅く"なる事となった(TT)

 

640x200x8色の画面モード

PC-8801では640x200x8色の画面を、アドレスC000h以降の16KBをバンク切り替えする事で、RGBの各プレーン用VRAMメモリを用意している。
青、赤、緑の3プレーン分あり、必要に応じてバンクを切り替えながら絵を描画する。

バンクの切り替えはI/Oポートに値を出力する事で行われる。

 

PC-9801上のエミュレータではI/Oポートを監視していて、バンクを切り替える動作がくると上記のMMUのようなセグメントテーブルを書き換えて、別のアドレス(本来のPC-9801でのVRAM)を指すように工夫をした。
これで面倒なアドレス変換をせずとも高速にVRAMへアクセスする事ができる。

 

解像度については、そもそもPC-9801には640x200x8色を表示出来る機能が備わっている。おそらくPC-8801との(BASIC上の)互換性維持のためと思われるが、これはアルフォスを動かすことにおいて有利に働いた。

 

パレット機能

パレット機能についてはPC-8801PC-9801でほぼ同じ機能があるが、パレットレジスタへ書き込むデータについてPC-8801との互換性がない。

ここは簡単なプログラムでこねくり回し、問題が出ないようにしていた。

 

Pocket386で動かすために…

まずは画面モードの設定が必要だ。
PC-9801ではハード的に640x200ドットモードに切り替えをしているが、この部分をEGAモードで初期化するプログラムに置き換える。

この辺りはBIOSの機能があるので、それを利用した。

ちなみにコンパイラはLSIC-86を使用している。

マジックナンバー多いのはごめん(TT)

 

次にVRAMのバンク切り替えについて検討する。
PC-9801ではMMUっぽい構造を利用してアドレス変換をしていたが、Pocket386ではVRAMのアドレスは変えず、書き込みポートを操作するコードを追加した。
例えば青プレーンの選択はこんな感じ。

マジックナンバー多いのは(以下略

 

パレットの切り替えについては思いっきりドハマリした。
先に結論を言ってしまえば、カラー番号がPC-9801とIBMPCとでは違うのだ(^^;;
日本人的な常識(?!)としては、COLOR1は、COLOR2は、COLOR4がだろう。

だけどAT互換機の世界では、COLOR1が、COLOR2が、そしてCOLOR4がなのだ!

 

早い話がVRAMのプレーン012が青赤緑なのか、青緑赤なのかの差だ。

この違いにしばらく気が付かず、なぜパレット変換に失敗するのだろう…と悩んだ(TT)
気がついてしまえば一瞬だけど、これは思い込みによる盲点としか言いようがない(^^;

 

移植してみる!

上記の情報に基づいて、PC-9801上で動いているPC-8801アルフォスを移植する。

DOSBoxで動かしたプログラムの実行結果と、Pocket386の動作結果が同じになることから、移植作業については、DOSBoxを積極的に活用する流れとした。

DOSBoxの結果

Pocket386実機の結果

 

まずはビデオモードを切り替えるコードを追加。

え!?

ビデオモードを切り替えただけで、画面にそれっぽい絵が表示された!

そうか、PC-9801とAT互換機ではVRAMのアドレスが重なってるところがあるのか!

これは画面見ながら動作確認が出来るのでラッキーだ!

ゲーム画面で化けたような文字が見えるのは、PC-8801のテキスト画面への出力が化けて見えているのが原因だ(そもそも表示してるのがダメ)。

 

次にVRAMの各プレーンに対しての書き込みを修正しつつ、テキストVRAMへの出力を廃止した。

よしよし、なんとなく見慣れた感じの色化けをした画面になった!(^^;;
ちゃんと各プレーンに対しての書き込みが出来るようになった証拠だ!

 

そして最後にパレット情報をAT互換機の機能と合わせてみる。

んー???なんとなく色が違うぞ??

そうか、16色表示出来るからカラー番号の0〜7はちょっと暗いのか。

そう思って色番号を+8してみたが、どうも色が合わない。

仕方ないので1色ずつパレット番号を合わせる仕組みを入れてみた。

変換するパレット番号を先頭から0,9,4,5,12,13,14,15にした。

そうそうそう!こんな感じの色よ!(^-^)/

DOSBoxでビルドしたEXEファイルを、Pocket386へコピーして動かしてみる。

おお!一発完動!(^-^)/

あれ?1時間もしないうちに移植作業が終わってしまった…(^^;;

PC-9801からのプログラム移植作業って、こんな簡単に済んでしまうのか……。

これはすごくない??

もっとPC-9801からのゲームが移植されてもいいのに…と思ったよ!(^-^)

 

おわりに

元々PC-9801で動かしていた時点でもゲームが出来る状態ではなく、基本はデモを見てるだけの機能しか無かった。つまり構造的にキー入力が入らないのだ(^^;;

せっかくPocket386で動かせたのだから実際に遊んでみたいな…と思ったけれど、エミュレータの構造を変更せねばならず簡単ではない事がわかった。

今回も見るだけアルフォスとなってしまったけど、自己満足度は高い!

 

みんなもPC-9801からのプログラム移植やってみよう!(^-^)

 

ではまた次回!(^^)ノ