PC-98HA(HANDY98)を使う!その3

せっかくPC-98HAが動くようになっているので、何か動かせないかと考えていた。

640x400ドットで、カラー使って無くて、プログラムが小さくて、簡単に入手できるヤツ……要はできる限り手抜き出来るものを探していた(^^;;

 

ふと…そういえば昔のI/Oに3Dパッケージが載っていたことを思い出した。

確かPC-9801とMZ-5500、そして後にFP-3000に移植されていた気がする。

ということは、計算部分と表示部分がキレイに分離されているような予感。

これならば移植がしやすいかも!という安易な理由でチャレンジしてみた!w

 

月刊I/O1984年1月号に掲載されていた「8086 3Dパッケージ」。

ローダーとして存在する数行のBASICプログラムと、マシン語ダンプが3KBほど。

これはもうOCRしちゃえばあっという間にバイナリ化出来る!

印刷の状態が良かったおかげか、間違いも数か所程度で済んだ!

 

解析開始

残念ながらアセンブルリストが載っているわけではないので、マシン語ダンプリストを解析していくしか無い!

こういうバイナリの解析って…週に何回ってレベルでやってる気がするんだけど、なんでだろ?(^^;; 既視感がスゴいw

 

以前にも何度と無くご紹介しているけれど、今回も書く!w

私は逆アセンブラに自作のものを使っている。

↑こんな感じのエントリアドレスやコメントデータを逆アセンブラに食わせると…

アセンブル時にコメントとして書き込んでいってくれるモノだ!(^^)

こうする事によって、解析できたところに逐次コメントを入れてけば、逆アセンブルするたびに読みやすい状態となって出てくる!

 

この時代のプログラムなので、あまり凝った作りにはなってないだろう…という勝手な想像の元、解析を進める。

 

I/OポートのアクセスはGDCだろう、INTxx(ソフトウェア割り込み)は何かの初期化なんだろう、積和演算してる辺りはおそらく行列計算、除算してるのはきっと透視変換…等々、さんざんっぱら仕事で3D計算してたのが今になって生きてくるww

 

軽く解析してみた結果、

・1周を256度ではなく360度として計算してる素直な実装

・テキスト画面はOFF

・LINE描画はGDCのコマンドを発行している

・画面切り替えはパレット操作

という感じが読み取れた。

特に高速化などを行った感じはなく、素直でキレイなプログラミング。

 

プログラムの開始アドレスが0100から始まる辺り、MS-DOSで開発していた可能性を感じる。おかげでMS-DOSのCOMファイル形式のコマンドとして改造する事も簡単だった!(^-^)

 

これ、3Dパッケージとして利用してもらいたかったのならば、アセンブラソースを公開した方が良かったんじゃないのかなぁ…と強く思う(^^)

 

なんでも良いけれども……

8086のアセンブラを完全に暗記しているわけではないので、取り組む時には机に資料が散乱するw

とりあえずこのくらいあったら作業はできそうかな…(^^;;

 

PC-98HA対応に改造

アセンブルリストからアセンブラファイルを作り、その上でプログラムを改造していく手法でも良かったのだけど、やはり作者様の著作物であるという事は意識したい。

いつもの通り、プログラムのバイナリにパッチを当てて行くよ!!(^o^)/

 

たくさんのコードを書くとバグが出る可能性が高くなるので、最低限のパッチ当てだけで動かすことを目標にしてみたい!

その流れから最初に決めた方針は「コードサイズが大きくなりそうなLINEルーチンはBIOSを利用する」という事だった。

 

まず、PC-9801特有の初期化をなくす。

VRAM各プレーンのクリア、パレット初期化は何もせずRETにする。

 

スクリーンの切り替え(パレット操作)は、VRAMクリアに置き換える。

画面は点滅しまくってしまうけれど、それは後で対応すれば良い。

まずは動かすのが優先よ(^-^)b

 

そしてLINE描画は、HAのBIOSに用意されている INT 1Dh(AH=07h)を使うように改造。

XY座標が格納されているワークから、BIOSが参照するワークへコピーしてBIOSを呼び出す。

 

初めてPC-98LT系のBIOSを使ってみたが、DS(データセグメント)の先頭から600バイトくらいがワークとして利用されるという不思議な仕様となっていて、これはとても困惑した(T-T)

 

そして動かしてみたのが、こちらのツイート。

バリバリに点滅しまくっているけれど、なんとなく飛行機が飛んでるのが見える!

まぁとりあえず移植は出来たから、これで良いか!

……とはならなかったww

 

点滅しない画面が見たいんだ!

やっぱり画面がビカビカ点滅してしまうのは気になる!

でもコレを直すのは簡単じゃない!

 

簡単ではない理由はすごく簡単で(どっち?)、BIOSのLINE描画がVRAMへ行われるためだ。

本来であれば、画面に見えない部分で描画をしておいて、そこで作られた画像情報をVRAMへ転送する事で、画面の点滅を防ぐ。

しかしBIOSの描画対象がVRAMである以上、これは出来ない。

 

BIOSの描画対象を動かす(VRAM以外のメモリを指定する等の)方法があるのかなぁ…と思ってみたが、それはBIOSを解析する事になるので手間が爆増する(T-T)

もしもその結果、ROMにハードコーディングされていたら手が出せない。

 

それだったら……LINE描画処理を独自で書いちゃう???(@_@;;

いやまて、LINEを描画するプログラムをアセンブラでごりごり書くのは簡単じゃないぞ!そんな若くもないww

 

そう思いつつ、ChatGPTに教えてもらった(!?)ブレゼンハム線分発生アルゴリズムを、LSI C-86(試食版)で書いてみる。

うーん……悪くないww

BASICでも同じ処理を書いてみた。

お、BASICと遜色ない速度でLINE描画が出来てるって事がわかった!

うーむむむ……悪くないなぁ…(^^;;

 

パッチ当てふたたび!

このLSI C-86(試食版)で作ったLINEルーチンを、3Dパッケージに載せてみる!

 

8086の場合、プログラムを実行するアドレスがズレる事について、そこまで神経質である必要がない。いろんなコードが相対アドレッシングで出ているので、まとまった単位で移動させる分にはアドレスはズレない。

 

問題はデータを参照するためのDSの状態が違うために、グローバルなワークエリアのアドレスがずれたり、関数外にデータを参照するような時もずれてしまう。

この2つを解決するためには、使用するワークエリアはauto変数のみ、外部のデータは参照せず計算で作り出せるものは作る、という対処をした。

パッチを当てる部分は、こんな感じでハンドアセンブルしたデータを上書きしてる!

実際にはMS-DOS上でSYMDEBを利用したワンラインアセンブルしたものを取り込んでいる。

使えるツールはなんでも使ってラクするのがポリシーだww

 

そして画面を切り替えるのは、

・描画したバッファをVRAMへ転送した

・次の描画のためにバッファをクリア

…というコードを追加する。

8086で領域クリアってrep stoswが最速??

V30シリーズはストリング系命令が速かった記憶がある!(^^;

元々のエリアが小さくてプログラムが入り切らないので、適当なアドレスにプログラムを配置して、そこへジャンプさせるようにした!

メモリの中はわりかし適当でぐちゃぐちゃだ(^^;;

 

そして出来上がったのがこちら!(^-^)

LINE描画と転送&クリアの速度が遅いけど、むしろ速すぎてウェイトを入れたいと思っていたくらいなのでちょうど良い!(^^)

画面が点滅しないだけでもこんな見やすくなるのかーw

いいね!いいね!!(^o^)

 

おわりに

今回はPC-9801のソフトを移植するということをやってみた。

元のプログラムがすっきり作られていたおかげで、解析&移植は楽しめる範囲で出来た!

 

そもそもソースが存在しないものを移植するというのが簡単じゃないと想像していたけど、意外にも簡単に出来ちゃうんだなーと驚いた(^^)

 

PC-98HAはこれからも安定して動きそうな気がするけど、こればっかりも触っていられないので、一旦キリを付けます(^^)

 

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