PC-6001mkII版ハイドライドをSMC-777に移植

移植しようとしたきっかけとか、まるで無くて、なんとなーく移植してみたくなったので移植しました。オモチャ(SMC-777)が手元にあったから、という以外の理由が思い当たらず、趣味のプログラミングとして楽しんだというところです。かかる費用は自分の時間だけですし。

■ まずはトーフの表示

SMC-777の基本スペックはWikipediaでもみてください(間違いもありますが)。

SMC-777は仕様がオープンなマイコンです。というのも、付属のマニュアルにはハードウェアの回路図から各種設定項目まで全てが記載されています。

マニュアル一式

VRAMに何かを書き込みたければ、マニュアルを読めば手順がわかりますし、それなりに丁寧に説明がされています。だからといって、簡単に絵が描けるかというと、それほど甘くはありません。

グラフィック画面のスペックは、320×200ドット16色、もしくは640×200ドット4色です。今回は320×200ドットの画面モードを使います。その場合のVRAMアドレスはこのようになっています。

VRAM

1ドットは16色なので、1ドットあたり4ビット、1バイトには2ドット分の情報が詰まっていることになります。となりのバイトは2ドット隣になるので、1ドット単位で絵を動かすのが苦手(面倒)ということになります。もっとも、この時代のマイコンで1ドット単位で絵を動かす事は無理要求ではあります。

問題はVRAMのアドレスです。

2ドット隣は2バイト先のアドレスなので、1バイト当たりの座標は一致しているのですが、1バイト(2ドット)書き込む毎にアドレスを+2しなければならないので、横方向にドットを連続して打つコストが高めです。

縦方向は+$1000です。ただし、8ドット毎に+$A0されて、ついでに上位2バイトは$00にリセットされます。8×8ドットのものを描くのであればさほど苦労しませんが、8ドット目をまたぐ場合、ちょっと面倒なことになります。

面倒さはまだ続きます。

VRAMがどこにあるかというと、I/O空間にあります。SHARP X1と同じですね。VRAMサイズが32KByteで8ビット幅では足りないので、アドレスバス16ビットを使ってアクセスします。OUT (C),A命令を使うと、Cレジスタがアドレスバス下位に、Bレジスタがアドレスバスの上位に乗るというZ80の仕様を使ったハードウェア構成です。

ただし、SMC-777では、単純にZ80のアドレスバス16ビットがVRAMのアドレスバスに素直につながっているのではなく、上位8ビットと下位8ビットが入れ替わって接続されています。Cレジスタを固定してOUT (C),A → INC B → INC B → OUT (C),A…というように連続してVRAMに書き込みが出来るという、なんとなく効率よさそうな仕様なのですが、VRAMの並びが変則的なので、実際にはそんなに甘くありません。

まず、横方向については、Y座標が9の時とかでは、横方向のアドレスがBレジスタに収まらなくなり、桁あふれが起きます。つまり、INC BCのCが$FFを越える場合があるのです。INC BCはCレジスタの桁上がりが自動的にBレジスタに加算されますが、SMC-777では、BレジスタとCレジスタが逆並びでVRAMにつながっているので、INC CBという命令が欲しくなります。当然、そんな都合のいい命令はありません。

縦方向は先にも説明したとおり、Y+1ごとに+$1000だけども、8ドット毎に$A0され、尚且つ、+$1000されない(=$A0-$1000される)という条件になります。

このように線を1本描くだけでもレジスタのやり繰りが大変なのですね。Z80アセンブラ最適化ゲームとしてはなかなか面白いのかもしれませんが。

こういう仕様はカタログのスペック表からは読み取れませんから、よくあるマイコンスペック比較が無意味なのがよくわかります。

そんなSMC-777のハードウェア仕様を頭に入れて、VRAMに8×8ドットの白い四角が描けるようになれば、あとは応用でレンガ画像を敷き詰められるわけです。

レンガ

この画像だけで既にハイドライドっぽい!始まりの予感!

基本的にPC-6001mkII版のハイドライドは8×8ドットのパターンを並べて描画するようになっています。16×16ドットキャラや、縦線やボックスフィルのようなドット単位での描画処理もありますが、最初に8×8ドットが描ければ、そこから一気に移植が進むようになります。

アイテム

美しい・・・。

PC-6001mkIIとSMC-777は共に16色(P6mkIIは黒と透明黒があるので見た目は15色)が表示できますが、パレットは並びだけでなく色自体が違います。

PC-6001mkIIパレット

SMC-777パレット

上がPC-6001mkIIのパレットで下がSMC-777です。SMC-777の方が渋い色がありますね。これを見比べて、なんとなく似た感じの色を割り当てました。

SMC-777Cのパレット機能か、SMC-777用のパレットボードを装着してパレット機能を使えば、PC-6001mkIIと同じ色に出来ると思うのですが、残念ながら所有していないのでした。

■ メモリが足りない

PC-6001mkIIの16色(見た目は15色)モードでは、スクリーンのメモリ上の解像度が160×200ドットで、表示時に320×200へと横方向に2倍化されます。

それに対して、SMC-777は16色で320ドットの表示が出来ますから、横方向解像度はSMC-777の方が高いということになりますが、それが良いかと、そうでもありません。単純に考えても、画像のデータ量が2倍になります。PC-6001mkII版のハイドライドは、オンメモリ動作で、グラフィックデータが30Kバイト弱ほどあり、それ以外のプログラムやマップデータでほぼRAM 64Kバイトを使い切っていますから、画像データが2倍になると64KバイトのRAMには収まらなくなります。

ハイドライドでは全ての敵が一度に出ることは無く、多くても一画面あたりの敵は4種類程度ですから、データの圧縮を使ってやりくりする事はできます。ただ、そうなると320ドット用にドットを打ち直すことになりますし、PC-6001mkII版がSMC-777を侵略、じゃなかった、PC-6001mkII版を素直に移植するのとは違う話になるので、PC-6001mkIIの解像度を再現する事に決めました。

つまり、1ドット単位で描くのではなく、2ドット同時に同じ色を書き込むということで横2倍化にしています。幸いにも、SMC-777のVRAMは16色4ビット構造なので、1バイト書き込むと2ドットとして画面に表示されますから都合が良いです。

ざっとまとめると、メモリ上の画像データは横半分状態になっているので、描画ルーチンで2倍化、つまり、4ビットデータを8ビットに広げています(敷衍化?)。例えば、$12を$11,$22に展開してVRAMに2バイト書き込むのですね。

余裕があったら、PC-8801版の8色グラフィック画像に差し替える案も考えていたのですが、そんな時間的な余裕はなく、あと、SMC-777のVRAMは垂直型16色4ビットなのに対してPC-8801は水平型8色で、動的な画像変換が重そうだったのでやめました。

■ 移植話その1

PC-6001mkII版のプログラムコードは昔からちょっとずつ読み進めてて、7,8割くらいは解析してあります。一部の敵の動きのアルゴリズムを読んでなかったり、PC-6001mkII版ハイドライドのプログラムには自己書き換えがあったりもして、まだ知らないコードもあるのですが、PC-6001mkIIとSMC-777のCPUはどちらもZ80系ですし、RAMも64Kバイトなので、「I/O周りを整えれば同じように動作するでしょ」くらいの気楽さでPC-6001mkIIのコードをSMC-777にゴッソリ持ち込んでいます。

それに、元のハイドライドのプログラムが描画処理とそれ以外が比較的分離されていたので、移植しやすかったです。ハイドライドの神様に感謝です。

移植作業をもう少し具体的に説明すると、PC-6001エミュレータでハイドライドを起動して、テープロードが完了したゲーム開始前の状態のRAMをファイルに落として、必要な箇所だけを切り出して、それを逆アセンブルして、さらにそれをZ80のアセンブラ(今回はpasomoというアセンブラを使いました)でSMC-777のバイナリにして、D88形式のファイルに書き込んでいます。

D88形式のファイル生成には、bookwormさんのd88toolを使わせてもらっています。ただ、SMC-777エミュレータで扱えるD88形式はヘッダが異なるので、その辺は自作ツールで変更しています。

ハイドライドが、というより、Z80のアセンブルリストには絶対アドレスでのコードが含まれますから、逆アセンブラが絶対アドレスをラベル化してくれたとしても、そうそう都合の良い逆アセンブルリストにはなりません。1バイトでもコードを追加してからアセンブラを通すと様々な理由で動かなくなります。その辺を手作業で修正するか、何かしらの自動変換ツールを作る事も考えたのですが、それで原因不明の問題にハマるのもいやだったので、ズレが起きないように同じアドレス上で動かすようにしました。プログラムを追加したい時はjp命令で別のパッチ当てルーチンに飛ばしまくりです。描画ルーチンはまるごと自作してます。

PC-6001mkIIのVRAMはメインRAM上にありますが、SMC-777のVRAMはI/O空間にありますから、PC-6001mkIIのVRAM空間分がまるごと使えることになるので、パッチ当てする余裕はありました。

■ SMC-777のディスク起動

SMC-777にはOSディスクが付属しています。CP/MっぽいOSで、SONY FILERという名前が付いてます。アセンブラとデバッガも付属しています。テキストエディタでコードを書いて、アセンブラに通すと、SONY FILERから起動するバイナリ(.COMファイル?)が生成されるようです。

ただ、SMC-777付属のZ80アセンブラは文法にクセがあるそうですし、Windows上で動作するZ80アセンブラを使いたかったのと、SONY FILERからファイルを選んで起動するんじゃなくて、ディスクをガシャコンと入れたら、即、ゲームが起動する方がカッコイイよな!という理由で、SONY FILERに頼らずに起動できるように、まずはSMC-777のBIOSのブート部分+SONY FILERのIPLの解析をしました。

SMC-777のBIOSはトリッキーなコードで読みにくかったです・・・。

オープン仕様なSMC-777ですが、マニュアルには起動シーケンスについての情報がありません。そこはSONY FILERに任せてね、ということなのでしょう。

■ 移植話その2

アイテムと妖精が表示できるようになった後はタイトル画面のテキスト表示ですが、テキスト表示前に、グルグル描画があります。

グルグル

グルグル描画からストーリーが表示される、このグルグル表示が移植作業で初めてSMC-777で動きのあるものだったので、ここがテンションマックスでした。それに、ハイドライドはこの画面から始まるのだという(PC-6001mkIIテープ版ユーザの)気持ちで胸一杯になるのです。

でも、ここにくるまでには、問題が色々と出ましたよ・・・

画面壊れる

壊れる。

画面壊れる

壊れる。

画面壊れる

簡単に壊れる。

バグを潰して、最初にゲーム画面が表示できた時にも感動したかというと、そうでもありませんでした。

最初のゲーム画面

『あーうーん、キャラクタデータが未変換なのはさておき、地面や木の置き換えパレット色が見苦しくて気に入らないなぁ・・・』とか考えながら自動操作のデモプレイを観ていたら

ゲーム開始後暴走

オオゥ・・・画面が壊れて、しばらくすると暴走。

暴走調査は手探りで大変でした。原因の大半はメモリ破壊です。PC-6001mkIIのVRAMは実RAM上にマッピングされているので、画像の書き込みはRAMへの書き込みになります。SMC-777への移植では、そのVRAM領域にもプログラムを置いているので、元のプログラムを書き換えないと、プログラム領域をガンガン壊していくことになります。自己書き換えや、描画ルーチンを使わない描画処理(高速化のため?)があるので、それを探していきます。

また、SMC-777のVRAMはI/O側にあり、I/O側にはグラフィックVRAM以外にもテキストVRAMや周辺回路が繋がっているので、書き込み先が間違っていると上記のような画面になります。

色々とバグをつぶす作業の気分転換に、JIMのキャラデータを変換して表示してみました。

JIM表示

それと併せて、メモリ破壊の原因を探るためにジョイスティック処理を実装したのですが、ジョイスティックでJIMを動かせるようになったら、とたんに面白さが沸き上がってきました。ほんと、ハイドライドは歩き回ってるだけで楽しいんですよ。

地面のグラフィックがワカメ模様なのは今でも納得いっていません。PC-6001mkII版は、明るい緑と黄色との混ぜ合わせ色なのですが、SMC-777には無い色なのですね。思い切ってMSX版のように緑だけにもしてみたのですが、木や岩とのバランスが崩れて、それはそれで見苦しくなってしまいましたし、こうなるとドットを打ち直したくなるのですが、それを始めるとプログラムの移植作業が止まってしまうので、手をつけないことにしました、ぐぬぬ。

■ SMC-777のキーボード処理

SMC-777のハードウェアにおけるキー処理は、キーが押されると割込みが発生し、I/Oポートからキーコードが拾えます。キーが離されたという状態は検出されません。ただ、SMC-777はキーボードの割込間隔を非常に短くすることが出来るので、その辺を理解してプログラムを作れば、富士通の某-7のようなアレな事を避けられるようです。

また、SMC-777のカーソルパッドとスペースキーは、側面のジョイスティックポートと連動しているので、ジョイスティックポートからの状態読み出しは、カーソルとスペースキーの状態も読み取りにもなるので便利です。

PC-6001mkIIも、キーボード周りはSUB CPUが管理していて、Z80側から任意のキーの状態を知ることが出来ないのですが、例外的にカーソルやスペースキーのような一部のキーは、Z80側から任意のタイミングで状態を知ることが出来るようになっています。PC-8801に至っては、いつでも全てのキーの状態を読み取れます。

この辺のハードウェア構成も、マシンのスペック表からは読み取れない、とても重要な性能の違いです。そう考えると、NECの方が、お客さんが求めているものを分かっていたような気がします。いやこれは私の勝手な想像ですが。PC-8801の価格は高いのですが、キーボードマトリックスを8bit×I/Oポート12個で読み取れるとか、コストをかけるところはちゃんとかけていたのだなぁと。

■ 音

SMC-777の音源はSN76489です。あとはBEEP的な音源もあります。SN76489はセガ・マークIIIにも採用されていますね。PC-6001mkIIの音源であるAY-3-8910と性能・機能が似ています。以前、MSX(AY-3-8910搭載)のゲームをセガ・マークIIIに移植しようとした事があったので、その頃の資料を元に周波数データを変換しました。
簡単に説明すると、AY-3-8910の方が低音(低い周波数の音)を出せます。ハイドライドは低い周波数の音を使っていなかったので、問題なしです。

音を出すには、大事な要素がもう一つあって、発音のタイミングをどうするか、です。

SMC-777には、タイマ割込みがあり、60Hz間隔の約16.666…ミリ秒なのに対して、PC-6001mkIIでは2ミリ秒(初代PC-6001では1ミリ秒も可)ですから、PC-6001mkIIの方が速い曲を流せます。単純に移植するとSMC-777で8.888…倍ほど遅いテンポで曲が流れる事になります。SMC-777と同じく、約60Hzの割込み機能を持つMSX版のハイドライドをYOUTUBEで観てみると、なるほどなるほど・・・という気持ちになれます。

だからといって、曲のデータを8倍速くすればいいかというと、PC-6001mkII版のハイドライドの曲はテンポが早く、曲データに短い音があるので、綺麗に8倍化できないのです。

そんな事情もあって、移植版はPC-6001mkII版よりも曲のテンポが若干ですが違います。

ちなみに、SMC-777の割込みはキーボードとタイマの2種類があり、その割込みアドレスが一緒という扱いにくさもスペック表からは読み取れない仕様です。参考話ですが、PC-8801mkIISRは、内蔵のFM音源が持っている高精度タイマ割込みをZ80が拾い上げるように設計されているので、音周りの強みがあります。やはり、NECは顧客が求めてるものをわかっていたのだと思わずにはいられません。えぇ、ただのNEC贔屓ですが。

■ 移植話その3

VRAMの構造や、画像データ展開の負荷があり、どの程度のゲーム速度が出るのかまったくわからなかったのですが、SMC-777の描画は周辺プロセッサ任せでCPU時間を使わないのと、PC-6001mkIIはCPUの処理速度が低めなのに加えて、実はPC-6001mkII版ハイドライドには大きめのウェイトが入っているので、SMC-777でも充分な速度で動きました。PC-6001mkII版のウェイトを1/7くらいにして同じくらいの速度です。ウェイトを完全に取ってしまうと操作が難しくなるくらい高速に動かせます。

同じ時間でのCPU処理量だけでみたらPC-6001mkIIよりSMC-777の方が上なので、タイトル画面の待ち時間のようなタイマを使わない箇所だと、SMC-777版の方が速くなってしまいますから、その辺は微調整しています。

■ 実機動作

あっさり動きました。フロッピーディスクへの書き込みは、Ndittを使って、エミュレータ用のD88を実ディスクに書き込みます。MS-DOSを用意しなくてもWindowsXP/7から1D/1DDディスクへの書き込みが出来るので、とても便利です。

そうそう、SMC-777エミュレータのWinSMCが無ければ、今回の移植は実現しませんでした。作者様には大感謝です。

と言っておいてなんですが、WinSMCはデバッガ周りの機能がそれほど充実していないので、バグが出た時の調査は大変でした・・・。

■ 移植おわった?

JIMがダメージを負った時、たまーに体力バーの表示がおかしくなります、謎。
それから、終盤の敵のデータを入れ込んでないのと、あと、まだエンディングまでプレイしてないので、どんなバグが残っているのやら・・・。
そういえば、セーブとロードも未実装でした。ディスクへの書き込みは試したことがないですけど、読み込みは出来ているので、あとはその応用ですね。ちなみにSMC-777に搭載されているFDCはMB8877Aです。

でももう、SMC-777での趣味プログラミングは充分に楽しんだので、もういいかなと。

地面のグラフィックデータはちょっとだけ悔いが残ってますが、その悔いエネルギーは(SMC-777以外の)別の事に使おうと思います。

ディスクラベル

フロッピーディスク

コメントは受け付けていません。