タイニーゼビウス 完全解析&解説

この記事は、サークル「TinyProject」によるPC-6001同人誌「PC6000NOTE No.5」に寄稿した記事をWeb用に再編集したものです。

画面の仕組み

タイニーゼビウスの画面は、PC-6001 BASICのSCREEN MODE3と同じモードで、横が128ドット、縦が192ドットの解像度に設定されています。この画面モードでは、PC-6001からテレビに表示される時に横方向が約2倍に広がります。

VRAMでの状態テレビに表示

タイニーゼビウスでは縦方向の解像度が96ドットモードになっていると思われがちですが、画面モードは縦192ドットの解像度になっています。ただ、プログラム内でのキャラクタデータや背景画像などの縦方向解像度は96ドット分になっていて、最終的に表示画面(VRAM)に転送する際に2ラインに同じ内容を描き込むことで192ドットにしています。

PC-6001の画面用IC(VDG)には、128×96というグラフィックモードがあり、このモードを使えばVRAMサイズが半分で済むだけでなく、2ラインに同じ内容を描画する処理をVDGがハードウェアで処理するため、CPUの処理を半減させることができるのですが、このグラフィックモードはPC-6001mkII以降の機種に対応していません。

[参考資料] 128×96モードを確認するBASICプログラム

10 SCREEN 3,2,2:CLS
20 LINE(20,20)-(70,70),3,B
30 FOR I=&HE000 TO &HE1FF:POKE I,&H84:NEXT

このプログラムについて簡単に説明すると、SCREEN MODE3のVRAMアトリビュート値は&H8Cなので、SCREEN命令を実行すると、VRAMアトリビュート値は全て&H8Cに初期化されます。この状態から128(256)×96モードにするにはアトリビュート値を全て&H84に書き換えます。上記のプログラムをPC-6001初代機で実行すると、LINE命令で描かれた箱が徐々に縦に伸びていく様子が見られるのですが、同じプログラムをPC-6001mkIIで実行しても、画面が変化しない(アトリビュート&H84に対応していない)ことがわかります。

タイニーゼビウスでは、画面表示用VRAMに直接、背景画像やキャラクタを描き込んではいません。背景専用の描画領域の内容を、重ね合わせ用の描画領域へとスクロール処理をしつつ転送して、その上にソルバルウや敵、弾などを描画してから、最終的に表示領用VRAMへと縦方向を2倍に(2度描き)しつつ転送しています。

背景専用の描画領域から、重ね合わせ用の描画領域への転送は次のような処理になっています。

まず、スクロールを表現するために背景用領域から1ライン(高さ1ドット)だけずらして描画領域へと転送します。背景のキャラクタデータは高さが8ライン分なので、8ライン分だけスクロールしたら、背景専用領域全体を1キャラクタ(8ライン分)だけ下に移動させて、最上段に1キャラクタ(8ライン)分だけ描画します。地上の敵は他の背景物(平地や森など)と同じ扱いになっています。

背景はグラフィックデータとは別に、現在表示されている背景の内容を1キャラクタあたり1Byteでメモリ管理しています。この管理領域を使って、ブラスターのヒットチェックや地上物からの弾の発射などの処理を行っています。背景1キャラクタ(8×8ドット)あたり1Byteで、画面には横16キャラクタ×縦12キャラクタが表示できますから、この領域はC0HByteだけ必要になるはずですが、実際には80HByte分しか用意されていません。これだと下部4段分の判定用背景データが無いことになりますが、ソルバルウの照準が画面下部に来る事はないので、上部8キャラクタ分で充分なのです。ただ、この理由から、画面下部の地上物は管理領域から外れるため、敵弾を発射する事ができなくなっています。

ソルバルウやザッパー、ブラスター、空中の敵、敵弾などは、先に背景が描き込まれた描画領域に対してAND/ORによるマスク処理を行って描画されます。例外は地上物をブラスターで破壊した時の爆発アニメーションで、これはマスク処理を行わずに地上物の上に直接描き込まれます。

描画処理は、最初に背景領域の内容を描画領域全体へと転送するので、それ以前の描画領域の内容は結果的にクリアされることになります。

一連の描画処理が完了した後に、描画領域の内容をVRAM領域へと転送しますが、この時に2ラインに同じ内容を転送することで縦方向の解像度を倍にしています。転送処理は1ラインにつきLDIRを2回行い、それを96回繰り返しています。

転送処理は表示領域のVRAMにLDIRで順次転送しているため、転送のタイミングによっては、画面にちらつきが出ることがあります(PC-6001では映像垂直同期信号の検出ができないのです)。

マップの構成

タイニーゼビウスで分かりにくいのがエリアの構成でしょう。タイニーゼビウスは全16エリアという作りになっているのですが、マップの情報とエリア番号が一致していないのです。

アーケード版のゼビウスは、どのエリアのマップも必ず同じ内容で変化しません。これがゼビウスの基本形です。タイニーゼビウスでは、そのルールが守られていません。かといって、マップがランダムに表示・生成されるのではないということは、ゲーム開始直後の地形が常に同じ事からもわかると思います。タイニーゼビウスの全体マップは、次の図のようになっています。

エリアマップ

各エリアの1枚分のマップは、8×8ドット(表示時は16×16)のマップチップを16×16個分だけ敷き詰めて構成されています。ただしエリア16は3枚分の大きさです。

エリア16スタート地点

エリア15スタート地点

エリア14スタート地点

エリア13スタート地点

エリア12スタート地点

エリア11スタート地点

エリア10スタート地点

エリア9スタート地点

エリア8スタート地点

エリア7スタート地点

エリア6スタート地点

エリア5スタート地点

エリア4スタート地点

エリア3スタート地点

エリア2スタート地点

エリア1スタート地点

エリア1スタート地点のマップはゲーム開始直後にいつも表示される地形なので見覚えがあると思いますが、ゲーム中では、その先のエリア2スタート地点と、エリア3スタート地点の間に海(湖?)があります。また、エリア2スタート地点といっても、そこがエリア2というわけではないのです。このあたりがタイニーゼビウスのマップとエリアの関係を難しくしているところで、この話は次の“イベント処理”で説明します。

イベント処理

先に述べたように、タイニーゼビウスは全16エリアという構成になっていますが、その構成はマップを基準としたものではありません。まず、エリア1の構成は次のような処理の流れになっています。

トーロイド
タルケン
トーロイド
タルケン
パックマンかアカベエの表示
背景キャラが弾を発射
背景キャラが弾を発射
MAPつなぎ目表示(平地から海)
海上(グロブダー&バキュラ)
ジアラ
ジアラ
エリア番号+1
MAPつなぎ目処理(海から平地)
つなぎ目の平地、森1画面表示、つなぎ目の森から平地を表示

実際にゲームを始めると、最初にトーロイドが出現し、そのあとにタルケンが出現し、そしてまたトーロイドが出現するという、このフローの通りだということがわかります。

プログラムの作りは、各処理(イベント)がサブルーチン化されていて、それをフロー図の順にCALLしているという構造になっています。

	;--------------------------------
	; AREA1 MAIN
	;--------------------------------
Z0645:
	; トーロイドの処理
	CALL	Z0629		;D799	CD 8A D0
	; タルケンの処理
	CALL	Z0623		;D79C	CD C9 D0
	; トーロイドの処理
	CALL	Z0629		;D79F	CD 8A D0
	; タルケンの処理
	CALL	Z0623		;D7A2	CD C9 D0
	; パックマンかアカベエの表示処理
	CALL	Z0630		;D7A5	CD CB D2
	; 背景キャラの発弾と移動
	CALL	Z0631		;D7A8	CD C7 D1
	CALL	Z0631		;D7AB	CD C7 D1
	; MAPのつなぎ目部分の処理:平地から海へ
	CALL	Z0632		;D7AE	CD E3 D2
	; 海上の処理(グロブダーの生成&移動, バキュラの生成&移動)
	CALL	Z0633		;D7B1	CD 97 D4
	; ジアラの処理
	CALL	Z0634		;D7B4	CD 8F D0
	CALL	Z0634		;D7B7	CD 8F D0
	; 次のAREAへ
	LD	A,01H		;D7BA	3E 01
	LD	(0D651H),A	;D7BC	32 51 D6
	; MAPのつなぎ目部分の処理:海から平地へ
	CALL	Z0635		;D7BF	CD FC D2
	; 平地から森、森を1画面、森から平地の画面を表示、スクロールする
	CALL	Z0636		;D7C2	CD E8 DA

背景スクロール処理、ソルバルウの移動、敵が弾を発射した際の弾の移動&接触処理などは、それぞれのイベント処理内に含まれています。つまり"トーロイドの処理”というのは、トーロイドが出現してから画面から消えるまでの間の画面全ての処理ということになります。トーロイドを移動して、ソルバルウを移動して、ソルバルウの爆発判定をして、背景をスクロールさせるというような画面上で起きる全ての処理をトーロイドが消失するまで繰り返します。トーロイドが消えるまでがイベント処理ですから、画面上の全てのトーロイドが画面から消えない限り、次のタルケンの処理へは進みません。同様に"タルケンの処理”内でも、ソルバルウの移動や背景のスクロールの処理を実行しています。割込みやタスクスイッチを用いず、実直に各処理を順番に実行していて、何かしらの同期処理もしていません。

トーロイドは画面上方(画面外)のランダムな位置に出現してから移動し、ランダムなタイミングでX方向の進行方向を変えます。また、タルケンも同様にランダムに出現して、ランダムなタイミングで進行方向の反転と弾を発射します。ですので、敵が現れてから敵や弾が画面から消えるまでの時間は一定ではないことになります。この事はイベントの発生タイミングにも影響を与えます。例えば、2度目のタルケンの処理のあとは、"パックマンかアカベエの表示処理”に進みますが、この処理では、このイベントが発生した時、画面最上段にパックマン(またはアカベエ)を表示するようになっています。これにより、パックマン(アカベエ)がマップ上のどこに表示されるのかというと、タルケンとタルケンが発射した弾が全て画面から消えた直後の最上段(X方向はランダム)ということになるので、パックマン(アカベエ)表示位置は遊ぶたびに変わってきます。

続く背景キャラの発弾と移動(弾の移動処理)イベントも同様で、このイベントはパックマン(アカベエ)の表示処理の後ですから、その前のタルケンの処理状況によって背景キャラが弾を発射するタイミングが変わることになりますし、パックマン(アカベエ)の表示処理が終わらない限り、背景キャラが弾を発射することはありません。また、背景キャラが弾を発射するイベントが2回続いていますが、最初の発射イベント完了は画面から全ての弾が消えるまでですので、画面から全ての弾が消えると同時に背景キャラは即座に次の弾を発射することになります。

このようなイベント単位の動作を意識してゲームを遊んでみると、この仕組みを理解してもらえると思います。

ところで、このイベント単位の処理ですが、一つのイベントが終了しないとどうなるのでしょうか。実際には、そのような事態になることはありませんが、仮に、画面上に敵が居座り続けたり、敵の弾がものすごく遅い速度で移動して画面から消えるのに時間がかかったりするような状態になったとします。その場合、最も影響を受けるのは背景です。イベントの進行状況に関わらず背景は常にスクロールしなければなりませんから、エリア1スタート地点から始まったマップはエリア2スタート地点へと進んでしまうことになるのです。同様に、エリア2スタート地点のマップが終了したらエリア3スタート地点のマップが現れます。このように背景の進み具合とイベントの進行が分離しているのがタイニーゼビウスの特徴です。

エリア1からエリア2へと進むための条件は、"ジアラの処理イベント"が2回消化された直後で、現在のエリア番号(変数)を更新する処理が実行される事です。ジアラのイベントが2度消化されるまではエリア番号はエリア1という状態ですから、それ以前にソルバルウが破壊されるような事があると、エリア1のイベントを最初から実行する事になります。この時、マップの表示開始位置はエリア1スタート地点と書かれた場所からになります。つまり、マップがどれだけ先にスクロールしていても、ソルバルウが破壊されると、現在のエリア番号に該当する位置からマップが表示開始されるということです。

さらにエリアとマップの関係を複雑にしているのが、海上のイベントと森のイベントです。エリア1の途中には海のイベントがあるのですが、海のイベントの直前に"MAPつなぎ目表示(平地から海へ)"というイベントがあり、ここではマップが区切りのいいところまでスクロールするようになっています。区切りのいいところとは、マップのエリアスタート地点の区切りのことです。実際のゲームプレイをみても、マップ区切りの途中で海になったり森になったりすることはなく、必ずエリア単位のマップで切り替えが発生しているのがわかると思います。

また、海のイベント処理では、バキュラとグロブダーが表示し終える(=画面下方に消える)まで海が続きます。バキュラとグロブダーのY方向表示開始位置はランダムに決まるので表示時間は毎回異なりますから、海の長さも一定ではないということになります。

ここではエリア1の全イベントを掲載しましたが、このようなイベントの固まりと現在のエリア番号を更新する処理が16個あるので、全16エリアという表現になります。

アーケード版ゼビウスと同様、現在のエリアが画面に表示されるわけではないので、ゲームの進行具合を把握するのは難しいのですが、各エリアのイベントの終わりでは森を一画面分だけ表示するようになっているので、それがエリアの区切りの目安になります。

ちなみにエリア16を越えるとエリア1に戻ります。

それぞれの敵の攻撃や動き

ザッパーで破壊できる空中の敵は、画面上に最大で5機まで現れます。出現する数は必ず5機で、出現処理のタイミングは同じなのですが、縦方向の表示開始位置が画面外の位置でランダムに決まるため、若干のばらつきと共に画面に表示されることになります。出現のタイミングと移動方向によっては即座に画面から退場してしまう事もあります。

イベント処理の項目で説明したように、敵の動きはまとまって処理されますから、色々な敵が混在する事はありません。地上の背景キャラもイベントとして処理されますから、空中の敵と地上の敵が同時に弾を発射するという事もありません。必ず、空中の敵と、敵から発射された弾が全て画面に消えてから、地上物から弾が発射されます。

タルケンやゾシーは移動途中で弾を発射します。この弾の個数も最大で5発で、全て同時に発射されます。ただし、弾の発射以前に敵自身がザッパーによって倒されている場合は発射されませんから、画面に表示される敵弾の数は敵の数と必ず同じになります。

地上物からの発弾も5発で、5発が同時に発弾されます。先のイベント処理で説明したように、地上物の発弾もイベントの一つですから、イベント発生のタイミングで発射されることになります。例えばエリア1であれば、2度目のタルケンが全て画面から消え、その直後にパックマン(アカベエ)が表示された直後ということになります。

どの地上物が弾を発射するのかは法則性があります。

図の斜線の範囲で、右下から左上へと左方向&上方向の順に地上物を調べていき、弾を発射できる地上物があれば、そこから弾が発射されます。弾を発射できる地上物にはログラムやガルデロータなど何種類かありますが、処理に違いはありません。地上物からは最大で5発分までの弾が発射されますが、一つの地上物からは1発です。なぜ、このような画面の上部側の範囲なのかというと、地上物の管理方法と関係してきます。画面上のグラフィックとは別に、現在表示している地上のグラフィックのパターン番号を1キャラクタ1Byteで管理しているのですが、その管理領域が画面の上部分しかないからです。この管理領域はブラスターの着弾場所に破壊できる地上物があるかどうかを調べるために使われるのですが、ブラスターの着弾場所、つまり、ソルバルウの照準の位置はソルバルウの移動範囲よりも上方に限定されるので、下側の領域は不要なのです。この管理方法だと、背景画像の管理領域を元にした背景グラフィックの描画が完全には出来ないように思えますが、そもそもタイニーゼビウスでは、背景の管理領域と現在表示されている背景画像に直接の関連性はなく、背景画像は常に最上段のみを更新するだけで、あとはひたすら下方向に転送を繰り返しているだけなのです(例外的に地上物を破壊した時の爆撃痕と、ソルの表示は、所定の場所のグラフィックを更新します)。このため、破壊できる地上物の位置やソルの表示位置は背景の管理領域内、つまり画面上部側に限定されますし、最初に述べたとおり、地上物からの発弾もこの範囲に限定されます。

敵弾の移動方向ですが、アマチュアモードでは垂直に移動し、プロモードを選択した場合には5方向のいずれかに移動します。

敵弾のX方向移動速度は5方向のいずれかですが、Y方向の移動速度はゲームの進行状況によって変化します(FAQ参照)。プロフェッショナルモードでの敵弾のX方向の移動量は敵弾の発生位置(弾を発射する敵の位置)とソルバルウの位置によって決まります。弾はソルバルウ側へと移動しますが、移動量が1と2のいずれかになるかはY方向の差で決まります。

敵弾のY方向移動量は必ず画面下方へと進むので、敵弾が画面上方や左右水平に移動することはありません。また、X方向とY方向の移動量計算は別々に算出され、単位時間あたりの弾の移動速度(移動量)は考慮されませんから、斜めの移動速度が速くなります。これは敵やソルバルウの移動も同様で、斜め移動が速くなっています。(アーケード版のソルバルウも斜めに移動した方が速くなります)

続いて、各敵の動きを説明していきます。

トーロイド&ジアラ

トーロイドとジアラは移動処理がまったく一緒で、違いはグラフィックだけです。画面上方に出現した後、5機全てが同じX方向に移動します。画面外Y座標の発生位置が微妙に異なるので、画面内に現れるタイミングに違いがあります。

Y方向は常に一定の速度です。移動ルーチンを8回繰り返した後に、5機全てがX方向の方向転換を行いますが、この際にX方向の移動速度は倍になります。

5機全てが破壊されるか画面外に移動すると移動処理(トーロイド&ジアラのイベント処理)が終了します。

タルケン&カピ

タルケンとカピも移動処理がまったく一緒で、違いはグラフィックだけです。画面上部に出現した後、垂直に降下移動します。画面に現れた5機のいずれかのY座標が80の位置に到達したら、5機全てが弾を発射し、Y方向反転して上昇移動に移ります。Y方向の移動速度に比べるとザッパーの移動速度は約1.3倍程度なので、ザッパーが当たりにくいです。

ゾシー

画面上方から出現して8回の移動処理毎にランダムに移動方向を変えます。ちなみにタイニーゼビウスの乱数処理はRレジスタを使ったものです。移動途中に必ず弾を発射するように処理されていて、画面上から全ての弾が消えたらすかさず次の弾を発射するようになっています。

グロブダー

タイニーゼビウスでは、海上にしか出現しません。他の地上物とは違う扱いで、専用の移動&表示処理になっていて、海上に入ると同時にブラスターの処理がグロブダー専用のブラスター判定ルーチンに書き換えられます。この判定ルーチンでは、他の地上物と異なり、ブラスターのヒット判定を一度しか行っていないため、隣り合った2台のグロブダーを1発のブラスターで破壊しようとしても1台しか壊せないという仕様になっています。

グロブダーは画面に最大5台まで表示され、その処理が5回繰り返されます。つまり、海上イベント中には常に25台のグロブダーが表示されることになります。表示位置はランダムに決定されます。25台分のグロブダーが全て画面から消え去ると海上の終了が近づきますが、海上面のイベントはグロブダーと共に表示されるバキュラが画面から消えるまで続きます。

バキュラ

海上面でのみ表示されます。表示位置はランダムで決まり、画面には最大13枚まで表示されます。グロブダー25台分が画面から消え去るまで、バキュラの生成処理が継続します。グロブダー25台分が画面から消失した後に、画面から全てのバキュラが消え去ると海上面が終了します。

余談ですが、バキュラがクルクルと回転するアニメーションの処理について説明します。

単純に想像すると、画面に表示されるバキュラそれぞれに、表示位置のXとYと現在のアニメーションパターン番号という3つのパラメータ(3Byte)があればよさそうです(移動速度は一定ですので、速度パラメータは不要です)。しかし、タイニーゼビウスでは、2Byte(X,Y座標) × バキュラの枚数(13枚) + 1Byteというワークエリアで構成されています。この1Byteというのがアニメーション番号を記録している領域です。これだと全てのバキュラが同じ動きになってしまうように思えますが、実際のゲーム画面を観るとバキュラのアニメーションはバラバラです。これはちょっとした算数パズルなのですが、バキュラのアニメーションパターンは4種類で、画面に表示されるバキュラの数は13枚です。つまり、バキュラを表示する毎に1Byteの領域を0~3で巡回させて、その数値でそれぞれのバキュラの画像番号を表示すると、4の倍数の12では13には1余りますから、次のバキュラ表示処理では+1された画像番号で表示されることになるのです。これでワークエリアを12Byte節約すると同時に、ちょっとだけ判定処理が軽く少なくなります。

アンドアジェネシス

アーケード版と異なり、コアのみブラスターで破壊することができます。一定時間放置しておくと、画面上方へと消えていきます。アンドアジェネシスの出現中は、敵弾が5発まとめてランダムな位置に生成されます。5発全てが画面外へと移動すると、即座に新しく5発の弾が生成されます。アンドアジェネシスがいる時の背景は常に森です。

ソル

ソルの表示位置はタイニーゼビウスの中での大きな謎だと思います。タイニーゼビウスではアーケード版と異なり、マップの特定の位置にソルが埋め込まれているのではありません。また、ソルバルウのブラスターによって出現するのではなく、自動的に生えてきます。生えるタイミングですが、ソルの表示もイベントの一つとして処理されますので、その前のイベントの終了直後になります。具体的な例を挙げると、最初にソルが表示されるのは、エリア3のトーロイドが2回表示された後です。とはいっても、プレイ中にエリア表示がないのでどのあたりがエリア3なのかつかみにくいのですが、もう少しわかりやすい説明をすると、ゲーム開始後の2度目のパックマン(アカベエ)が表示されるあたりがエリア3です。2度目のパックマン(アカベエ)が表示され、トーロイドが2回現れてから画面外に消えた直後にソルが出現します。エリア3のソルは4本です。ただし、2度目のパックマン(アカベエ)のイベント処理の直前にエリアの繰り上げ処理、つまり、アーケード版でいうところの70%ライン通過が発生するので、トーロイドの攻撃を受けてソルバルウが破壊されてしまうと、ソルの表示イベントを飛ばしてエリア4へと進んでしまいます。

ソルの出現位置は次のようにして決定されます。まず、背景画像用のメモリ領域を右下から左上方向に水平順に走査していき、平地部分を探します(図の網掛け部分)。最上段の左上隅は対象外です。

走査領域は画面の上部7段分です。走査中に平地部分が2つ連続している箇所があると、そこがソルの出現箇所に決定されます。走査処理は単純に背景の仮想メモリを調べているだけですので、画面の左右をまたいでいても対象となりますから、ソルバルウが移動できない画面の隅にソルが表示されたり、画面右端に生えたソルの影が画面の左端に表示されたりすることもあります。画面全体を走査した結果、ソルを表示する場所が見つからなかった場合には、ソルの表示はキャンセルされます。

ソルは2段階のアニメーションで出現し、アニメーションの終了までがソルの出現イベントになります。ソルが表示されると背景データの管理領域はソルに書き換えられます。

最初にソルが表示されるのはエリア3で、ここでは4回連続してソルの表示イベントが実行されます。横方向に連続した平地があるような場所では、ソルが横に4本並んで表示されそうに思えますが、実際にはそうなることはほとんどありません。というのも、ソルのイベント途中には画面のスクロール処理も実行されるのですが、ソルの表示イベント内での背景スクロール量が背景の1キャラ分の高さに該当するからです。つまり、最初にソルを表示した場所が図の網掛け部分の最下段の場合、1キャラクタ分だけ画面が下にスクロールすると、次のソルの発生場所が最初にソルが出てきたX座標と同じ、つまり最初に表示されたソルの1段上の位置になる可能性が高くなり、平地の左右方向よりも上下方向が表示位置として優先されやすくなっています。言葉で説明すると難しいのですが、この処理方法の結果として、ソルは縦方向に並んで表示されやすくなります。

このような処理内容でソルの発生位置が決まるので、イベントの進み具合とマップの位置によってソルの出現位置は毎回変化します。

ソルの発生位置決定処理は画面下部から走査するので、ブラスターの照準に入れにくく破壊するのが難しいのですが、プログラム上はちゃんと破壊可能でスコアも入るようになっています。ソルは右下に出現しやすいので、あらかじめ右下で待機していると破壊できる可能性が上がります。

ソルの出現回数はエリア3で4本、エリア7で1本、エリア12で2本、エリア16では8本に設定されています。8本のソルが生えてくる様は見応えがありそうですが、どういうわけかエリア16のソル出現イベントの直前が森の表示イベントになっていて、画面全体が森になります。これでは画面に平地がまったくない状態なので、ソルの出現処理がスキップされてしまいますから、どうやっても8本のソルが出現することはありません。

シオナイト

特に説明することはありません。アーケード版と同じ雰囲気盛り上げキャラです。

ザカート

画面上に突然、敵弾が現れることがありますが、これもイベントの一つです。パッケージ背面のキャラ一覧ではザカートとして紹介されています。弾の数は5発で、弾の動きは地上物などから発射される弾と同じです。

ブラグザカート

出現位置と分裂場所はランダムに決まります。分裂後、ソルバルウの位置とは無関係に常に決まった5方向に弾をばらまきます。

バグ?

プログラムに致命的なバグはなさそうですが、気になる箇所がありました。マップの描画処理は最初に説明したとおりですが、マップの区切りから海や森へと移動していく時には、つなぎ目の画像が表示されます。エリア2の場合、この箇所です。

このようなマップ間のつなぎ目には、平地から海、平地から森、海から平地、森から平地への4種類があります。

平地→海
海→平地
平地→森
森→平地

この4種類の画像データは、それぞれ20H(32)Byteのデータで成り立っていて、画像の展開ルーチンでは、その終端のアドレスが指定されるのですが、

なぜか、森から平地への参照アドレスが9CFFHではなく、9CEFHになっているのです。そのため、実際のゲーム中には次のような、つなぎ目の画像が展開されてしまいます。

森→平地

4種類のつなぎ目データは全て同じデータサイズであることを考えると、参照アドレスが間違っているように思えます。これは次のような可能性が考えられます。

3番目については、ネットにUpされている2つの動画(Up主/Up先が異なる動画です)と見比べたのですが、いずれも全て同じつなぎ目画像が展開されていますし、私の手元にある2本のテープからイメージを作成&比較してみたところ同一の内容でしたので、可能性としては無いでしょう。

動作にはなんの影響もないだけに気がつきにくい箇所です。ただ、このような些細な事さえも何か深い意味があるのではと考察してしまうのがゼビウスですね。

タイニーゼビウスMKIIへ

ちょっとだけ無粋で非常に大人気ない話をします。

タイニーゼビウスの逆アセンブルリストは非常に読み解きやすい内容でした。それだけプログラムが素直に記述されていました。ただ、それは低速なCPUでのマシン語プログラムとしては好ましいことではありません。1バイトを切り詰め、1クロックでも高速に動作させるようなプログラムでなければ、マシンのパワーを引き出せないのです。

スクロール処理はLDDRを多用していますが、これよりも高速な転送方法はあります。また、敵の弾のワークエリアは敵の種類だけありますが、画面には常に5発の弾しか表示されないので、ワークエリアを共通化することでメモリを節約できます。さらに、ワークエリアの領域自体もカセットに収録されているため、これを省けば、テープの読み込み時間を短縮できます。

こうしてプログラム全体を見直してみると、さすがに拡張RAMカートリッジ無しのPC-6001(6K RAM)で動作させることは出来なさそうですが、数KByte単位で使用メモリを減らすことができそうですから、より多くの敵やマップを追加できるはずです。

ただ、このような事を誰よりもより深く考えたのは、タイニーゼビウスの作者である松島氏でしょう。動作速度の向上と効率の良いメモリの使い方を突きつめる作業を続けると、おのずとアーケード版のマップを再現できるようになり、敵の動きを増やせるようになり、ゲームの動作が滑らかになり、そうやって完成したのが後に発売されたタイニーゼビウスMKIIなのだなと気がついた時、この解析作業自体が、当時の出来事をなぞっているように思えてきて、少しだけ感慨深いものがありました。

FAQコーナー

Q) アマチュアモードとプロフェッショナルモードの違いは?
A) 敵の弾の移動方向が違います。他に違いはありません。
Q) スコア上限は?
A) スコアは2Byteの16進数で管理し、表示する際に10進数に変換しています。10進数表示で1の桁には常に0が表示されますから、表現上は655350がスコアの上限です。また、スコア加算処理では上限のチェックをしていないので655350点を越えると0点に戻ります。
Q) 残機の増え方は?
A) 60000点毎に1UPします。ただ、1UPの処理方法が少々変わっています。プログラムでは、ソルバルウの残機を保持しているのではなく、ソルバルウが打ち落とされた回数を記録しています。ソルバルウが破壊された後は、ゲームオーバー処理に分岐するかどうかを判断していますが、そこではまず、現在のスコアを60000で割って、1UPした回数をカウントします。そこに最初のソルバルウ数(5機)を加えてから、これまでのソルバルウ破壊回数と比較しているのです。なので、スコアが655350点から巡回して0点に戻ると、1UP回数は0回ということになるので、それまでに5回以上ソルバルウが破壊されていて、次の撃墜時に60000点未満だとゲームオーバーになってしまいます。このように、1UPの計算方法の違いから、アーケード版のような1000万点直前の無限増殖は発生しません。
Q) 難易度調整システムは搭載されてる?
A) ありません。
Q) パックマンとアカベエってなんなの?
A) 謎と夢を壊してしまって申し訳ないのですが、特に意味はありません。ブラスターやザッパーの反応処理自体がありません。パックマンもしくはアカベエを表示するというイベント処理が起きると、どちらを表示するか乱数(Z80 Rレジスタの最下位Bit)で決めてから、最上段のランダムなX座標に表示します。マップ上の地上物に無条件で上書きします。
Q) バキュラにザッパーを256発当てると壊せるの?
A) 壊せません。ザッパーとの接触判定後、効果音を出してザッパーを消しているだけです。
Q) 一周すると?
A) エリア16を抜けるとエリア1のイベントに戻ります。その際、敵の弾のY方向の速度が上がります。ゲーム開始時、敵弾のY方向速度は毎フレーム4(描画8)ドットですが、周を重ねる毎にY方向の速度が+1ドットされていきます。上限は毎フレーム8(描画16)ドットです。
Q) スペシャルフラッグある?
A) ありません。その他の隠しグラフィックも無いようです。テープから読み込まれる内容には、プログラム的に意味をなさないデータが何カ所かありましたが、キャラクタデータとしてはデータ量が不足しているので、隠しキャラではなさそうです。
Q) 隠しマップは?
A) プログラムから参照されないマップデータが1枚分だけ存在します。

エリア16のマップは他のエリアと異なり3枚構成なのですが、その後にもう1枚だけ上記のマップデータがありました。ただ、プログラム上、表示されることはありません。
Q) 画面の左右の隅っこに移動できないの?
A) 地上物は画面の隅に表示される事があるのに、ソルバルウはその位置まで移動できないようになっています。これは推測ですが、左端での移動判定や接触判定の計算結果が0未満の値になるのを避けるためだと思われます。例えば-1は16進数でFFH、つまり255になってしまいますから、単純な大小比較では処理できなくなります。プログラムを読んだ感じでは、移動後の値がマイナスになる事を考慮していないように思えます。右隅も同様ですね。
Q) アンドアジェネシスが浮いてる!
A) ファミコン版ゼビウスではアンドアジェネシスの出現中は背景のスクロールが止まってしまいますが、タイニーゼビウスではちゃんと背景がスクロールしています。この重ね合わせ処理のために、アンドアジェネシスの背景との重ね合わせが必要になる縁の部分(アンドアジェネシスの周りの部分)の画像データの1bitをマスク用として利用しています。そのため、アンドアジェネシスの縁の部分はSCREEN MODE3の4色中の3色のみで表現されています。
Q) アセンブラ?ハンドアセンブル?
A) 逆アセンブルしたリストからは判断できませんでした。画像などのデータ領域がプログラムの前半にあり、上位バイトを固定して下位バイトのみを書き換える手法でメモリアクセスをするようなプログラムの記述が何カ所かにあるので、ハンドアセンブルのようにもみえるのですが、プログラム領域に無駄な空間があまりなく、比較的綺麗にコードが並んでいるのでアセンブラを利用しているようにも思えます。プログラム自体のコード量はさほど多くないので、ハンドアセンブルの可能性の方が高いですが、こればかりは松島さんご本人に聞いてみないとわからないですネ。
Q) 動作速度を速くできる?
A) タイニーゼビウスのプログラムは、ウェイトをまったくかけずに全力で動作しています。速度調整もしていません。プログラムの一部をちょっとだけ書き換えるとウェイトが外れて動作速度が速くなるといったことは出来ません。
Q) 無敵改造したい!
A) マル忍改造キタコレ!当時のテクポリに掲載されていたような気がします。
CLOAD
140 DATAAA,1A,C9,00,00,00,00,00
と入力後、RUN
テープ読み込み完了後、OKと表示されるので
POKE &HC891,&HC9:EXEC&HD4F9
と入力
エミュレータのデバッグモードであれば、テープの読み込み終了後、RAMのC891HにC9Hを書き込むと無敵になります。PC-6001VWの場合は、テープを読み込み終わった後(ゲーム中でも構いません)、ALT+F6を押してから、w 0xc891,0xc9を入力、gを入力、です。エミュレータを高速モードにして背景を流し観すると楽しいです。
Q) 音はどうやって鳴らしているの?
A) ゲーム開始直後の曲はBASICのPLAY文フォーマットになっていました。ゲーム中のBGMはSOUND文と同等の処理でPSGのレジスタを書き換えています。一度だけ書き換えれば、あとはずっと同じ音を繰り返すようになっています。効果音も同様で、その都度、PSGのレジスタを書き換えています。タイマー割り込みを使った演奏はしていません。
Q) ジョイスティックだとザッパーとブラスターの撃ち分けできないの?
A) タイニーゼビウスのジョイスティック入力は、BASIC ROMの1CA6Hにあるジョイスティック読み込みルーチンを利用しています。PC-Techknow6000Vol.1などの技術書では、このルーチンがトリガー1つ分しか取得できないように記述されていますが、実際には2ボタンにも対応しているようです。ただ、タイニーゼビウスの判定ルーチンでは1ボタン分の判定しかしていないため撃ち分けができない作りになっています。おそらく、当時のPC-6001用ジョイスティックはNEC純正のPC-6052も含めて1ボタンのものが主流だったので、2ボタンによる撃ち分けが出来るようにしてしまうと、1ボタンジョイスティックではザッパーかブラスターのどちらかしか発射できなくなってしまうので、その辺を考慮したのかもしれません。
Q) なんで、タイトルに「タイニー」ってついてるの?
A) 解析記事の趣旨と離れてしまうので説明はしませんが、3人の天才が生んだパソコン移植版「ゼビウス」のコメント欄にて、遠藤さんが語られています。

あとがき

以上、タイニーゼビウスの内部処理を一通り説明してきました。

解析結果が曖昧なところは、バキュラの近くでザッパーを撃つとザッパーが通り抜ける事があるのですが、これ原因を調べきれていません。なんとなく想像はつくのですが、ソルバルウの移動処理と弾の発射処理(表示開始処理)、バキュラの移動処理、バキュラとザッパーの接触処理の順序によるものだと思われます。この手の処理順序による不思議な現象としては、ソルバルウ撃墜直後に地上物破壊音が鳴ったり、敵弾が1発だけ画面に表示されたりするようなものがあります。 あと、空中の敵にザッパーを当てると破壊音が出るのですが、実機でバキュラにザッパーを当てると、それ以降、空中の敵にザッパーを当てても破壊音が出なくなるような気がします(PC-6001の機種によって違う?)。エミュレータだと必ず音が出るのでよくわかりません。

おまけ資料


M.M / 2015