X1オリジナルのアクションゲーム「ホバーアタック」をPC-6001mkII/6601/SRに移植してみました。
PC-6001mkIIでホバーアタック
I/O 1984年8月号 p236-241掲載のX1用ホバーアタックへのパッチとデータ変換プログラムを公開します(変換に必要なのはp237-239です)。市販されたものとは面数や敵の種類などが異なるようです。当該号は国会図書館に所蔵されているので、遠隔複写サービスの利用が可能です (要登録)。
補給船とロボットを操って、敵メインベースの破壊を目指します。ロボットは機動力と攻撃力に優れますが、ミサイルに限りがあり、時々補給を受ける必要があります。また、しゃがみジャンプで通常より高いジャンプが可能です。
キー | 動作 |
---|---|
カーソル左右 | 左右移動 |
カーソル上 | ジャンプ |
カーソル下 | しゃがむ |
スペース | ロボットの分離・収容 |
z | 左下方向へミサイル発射 |
x | 左方向へミサイル発射 |
c | 左上方向へミサイル発射 |
MODE | 簡易表示モード切り替え(3段階) |
PAGE | バスリクエストON/OFF切り替え(SRのみ) |
表示 | 意味 |
---|---|
H(over) | 残りホバー |
M(issile) | 残りミサイル |
F(ighter) | ロボットの耐久力 |
C(arrier) | 補給船の耐久力 |
S(core) | スコア |
ウットイを移植した時のことです。オリジナルのFM-7ウットイが掲載された号を眺めていたところ、同じ号にホバーアタックも載っているのが目に留まりました。
「そう言えば、ホバーアタックってどんな機種に移植されたんだっけ?」
当時のI/Oでは、ウットイ、ホバーアタック、走れスカイライン、ザ・コックピットなど、オリジナルゲームが多くの機種に移植されて人気を博していたのです。ネットで検索してみると、色々な機種への移植情報がヒットします。PC-8801、PC-8001mkII、PC-9801、FM-7、S1、MZ-2500、MZ-2000、MZ-1500、MZ-80K……MZ-80K?グラフィックのないMZ-80Kでどういう風に移植したんだろう?
MZ-80Kのプログラムリストが掲載されたPiO Specialを確認してみると、PCGと内蔵キャラクタでの表示の両方に対応しているようです。画面写真はPCG版しか載っていなかったので、キャラグラ版を見るためリストを打ち込んで動かすことにしました。MZ-80Kは互換モニタが公開されているので、実機を持っていなくても、マシン語のみのゲームであればかなり高い確率でエミュレータで遊ぶことができるのです。ありがたや。で遊んでみたのですが、これが決して悪くない。元がPCGのゲームなので文字単位の表示で全く問題なく遊べますし、やや記号的なキャラ表示ですが、メカものであることも手伝ってか違和感はあまりありません。
テキスト表示ならスピードも稼げるし、これならキャラクタテーブルを書き換えればP6にも簡単に移植できるんじゃね?そう安易に考えた自分は、MZ版を改造して、P6mk2のセミグラキャラクタを駆使したバージョンを作り上げました。
ロボットかっこわるい
しかし、どうやってもロボットがイメージ通りになりません。こんなのは俺が憧れたホバーアタックじゃない!キャラグラにはセンスが必要ということを改めて思い知り、やむを得ずグラフィックを使うよう更なる改造を始めることになったのでした。
グラフィックはオリジナルのPCGデータを機械的に変換するようにしました。X1では横8ドット×縦8ドットのキャラクタを40桁×25行モードで表示しています。色はRGB8色です。これを解像度はそのままで、P6mk2のスクリーンモード4、320×200の4色用に変換しました。地の黒と印象的な地形の赤を残したかったので、黒青赤マゼンタのモードを使っています。赤はそのまま、青と緑のORをとって青とする変換としました。視認性は悪くないと思うのですが、横長ドットで色を増やす方がいいのか、悩ましいところです。
X1版では得点やホバーメーターが重ね合わせで表示され非常にカッコいいのですが、これについては遅くなりそうな気がしてあっさり諦めました。MZ-80K版に倣って上部に表示してあります。また、操作説明画面やリプレイ確認の文字は、オリジナルでは内蔵フォントなのですが(BASICのPRINT文)、この移植では得点部のフォントに似せて必要な文字の分を作成してみました。
説明画面
PCG機能のあるX1と違い、P6mk2でグラフィック表示をするとなると、いかに遅くならないようにするかが問題です。Bookwormさんの「縦画面シューティングをつくる」などをお手本に、表示部分は以下のようなプログラムとしました。
表示そのものの部分のコードはこんな感じです。(1キャラクタ=8ドット×8ドット×4色=1バイト×縦8×2プレーン)
;8回繰り返し(add hl,bcは7回)
pop de ;グラフィックデータ読み込み
ld (hl),e
set 5,h ;+2000h,プレーン1→プレーン2
ld (hl),d
add hl,bc ;bc=28h-2000h, 次の行のプレーン1へ
差分表示を行う場合、「変化がないので何もしない時」と「変化があったので表示を行う時」とで、処理量にトレードオフが発生することがあります。例えば表示用VRAMアドレスの計算です。1行分の比較が終わるたびにVRAMアドレスを1行分加算しておけば、いざ表示する時に時間のかかる乗算処理やテーブル参照を行う必要がなくなります。一方、表示する時だけアドレス計算するようにすれば、表示しない時のオーバーヘッドを減らせます。
どちらを選ぶべきかは難しいところなのですが、画面全体に対する描き直し部分の割合と処理量を比較し、損益分岐点がどの辺になるかを考えながらプログラムを進めました。目安とした値は、「描き直し率が20%以下なら速くなる」or「描き直し率が5%以上なら速くなる」辺りです。描き直し数をカウントするルーチンを組み込んで何度か遊んでみたところ、多い時で5-15%程度だったので、そこが速くなるのであればいいかな、という感じで。かなり適当な基準ですけども。
あとはちまちまステート数を数えて削りました。細かい工夫としては以下のようなものがあります。
できれば色々やるのは表示部分だけにして、オリジナルのままで動く部分はいじらずに済ませたかったのですが、結局メイン処理部分にも若干手を入れました。
ホバーアタックはミサイルが軌跡を残して飛ぶところが最高にカッコいいわけですが、実はこの処理量がかなり多いようです。軌跡(煙)は表示されるキャラクタの一つ一つが4バイトのデータを持っており(位置、消えるまでの時間、上書きの有無)、ミサイルが1キャラ分進むたびに煙用ワークエリアから空き領域を探して、新しく増える煙キャラに割り当てるようになっています。メモリ割り当てルーチンは、呼ばれるたびにワークエリアの先頭から順に空きを探すのですが、ミサイルの数が多いと先頭の方は大抵使用済みなので、かなり先まで探さないと見つかりません。これをミサイルの数だけ繰り返すので、結局「使用されている領域のサイズ×ミサイルの数」に近い処理量が発生します。
このゲームでは、画面に表示されるかどうかに関わらず、敵やミサイルは常に動き続けています。マップのどこかで絶えず敵がミサイルをぶっ放しているのですね。そのため、スタートしてからしばらく経つと自然とミサイルの数が増えて処理量が増大し、以降はスタート直後より1.5倍くらい遅い状態が継続してしまいます。
元々のメモリ割り当てルーチンが遅いのは、様々なオブジェクトで使える汎用的な作りになっているせいもあるようです。そこで、煙ワーク専用に処理量を減らしたルーチンを新しく作ることにします。このルーチンでは、見つかった空き領域のアドレスを覚えておき、次に探す時はそのすぐ後ろの領域から探し始める(煙用ワークエリアの最後まで行ったら先頭に戻る)ように変更しました。煙の表示寿命はみな同じなので、一周する頃には先頭の辺りはもう空いているだろう、という目論みです。これにより、ほぼ一発で空きが見つかるようになって速度が改善しました。たぶん処理量がO(n^2)からO(n)に近くなったんではないでしょうか。
以上、色々と手を尽くしたつもりなのですが、恐らくオリジナルに比べるとまだ数十%程度遅いと思われます。そこで苦肉の策として、簡易表示モードとバスリクエストON/OFF切り替え機能(SRのみ)を用意しました。
ゲーム中にMODEキーを1回押すと、表示回数を1回間引くモードになります。このゲームでは、自機や敵機が1キャラ分動く間にミサイルは2キャラ分動くので、それに合わせてメインループ1回中に画面表示ルーチンを2回呼ぶようになっているのですね。それを1回サボります。ミサイルは一気に2キャラ分動くように見えます。もう1回押すと、間引きに加えて表示を1ライン飛ばしで行うモードになります。若干寂しい見た目になりますが、まあ視認性に問題はない範囲ではないかと思います。もう1回押すとノーマルモードに戻ります。
SRで実行する場合は、PAGEキーを押すとバスリクエストのON/OFF切り替えが可能です。バスリクエストOFF時はそのままだと速すぎるのでウェイトが入ります。ウェイト量は適当に決めたのですが、オリジナルの速度と比べてどんなもんでしょうか。
1ライン飛ばし表示
X1版は要G-RAMのプログラムになっており、そこに32KB使ってマップ全体の仮想画面を置いているのですが、P6では全部メインメモリに置かなければなりません。また、グラフィックデータもメモリ上に置いておく必要があります。X1では一度PCG定義してしまえは終わりなんですが……。そんなこんなで、結局64KBのほとんどを使っています。
実は移植が終わってから、I/O別冊の「X1シリーズ活用研究」にも別バージョンのプログラムが載っていることに気が付きました。こちらは敵の種類などが市販版に近く、コンストラクション付きで面数も5面まであるようです。が、プログラムサイズがより大きいため、こちらをベースにするのは難しそうです。拡張RAMを使うか、表示をテキストにしてうまくやりくりすれば入るかもしれません。
P6版アドレス | X1版アドレス(括弧内はI/O) | 内容 |
---|---|---|
0000-3FFF | (3000-3FFF) | VRAM |
4000-BFFF | (4000-BFFF) | 仮想画面 |
C000-D42F | C000-D42F | プログラム |
D430-DBFF | P6用追加プログラム | |
DC00-DFFF | 比較用仮想画面 | |
E000-EFFF | グラフィックデータ | |
F000-F9FF | B600-BFFF | ワークエリア |
FA00-FFFF | ROMルーチン用ワーク、割り込みルーチン、スタック |
トップ > 雑多なもの > PC-6001mkIIでホバーアタックを