JavaScriptを有効にすると、ここにメニューを表示します。

ysflight.com

FM77AV版夢幻戦士Valisの解析

2021/12/26

1986年、日本テレネットから発売された「夢幻戦士Valis」はなにかとインパクトが強いゲームだった(FM77AV版は1987年)。相当話題になったゲームで、自分でもプレイした記憶があるので、多分持っていた。当時ドラゴンバスターにはまっていた僕は、剣でばっさばっさと敵を斬っていくゲームかと思ったら、結局弾を撃って敵に当てて倒すゲームだったのでちょっとがっかりしたんだったような。今手元にはなぜか2セットのFM77AV用Valisが残っている。どっちもヤフオクで落としたもので、当時自分が持っていたディスクではない。

しかし、自分の記憶に内容がほとんど残っていないので、自分にとって「夢幻戦士Valis」はほぼまだプレイしていないゲームと言っていい。冬休みになったのでプレイしてみることにした。するなら、とことんやるよね、ってことで、一度普通にプレイしてから逆アセンブルしてプログラムの中身も調べてみた。

全マップ

まず、全マップ。アイテム、ボス、ワープの位置もすべて解明して記入してある。なお、「夢幻戦士Valis」は似たような場所を何度も通る。それはなぜかというと、当時のゲームはメモリの制約が非常に大きかったので、何種類かのマップのタイルを作っておいて、それをより大きな枠組みにはめ込むことで広いマップを実現していた。一応、解析中自分でこのタイルのことを「区画」と呼んでいたので、以下では区画と各ことにする。マップは、上下端、左右端がそれぞれつながっている。「夢幻戦士Valis」で工夫が見られたのは、例えばマップの左端から反対側の右端に移動して抜けたとき、必ずしも同じYの区画にジャンプしないように書いてあった。Act 2のマップの例を見ると、横にびろーんと長いマップで、右端から抜けると、今度は一段下がった左端に突入するようにできている。マップ全体は32x32区画でできているので、普通にこれを使うと横方向は32区画に制限されてしまうが、この工夫によりプレイヤーには横32区画よりもはるかに長いマップに見える。同様の工夫によりAct 9でもものすごく縦に長い穴を落ちていくシーンを実現している。以下のマップでは、この手法が使われている場合、赤字で反対側のどの座標にジャンプするのか書くようにした。

また、アイテム位置、ワープ位置、もすべて特定したので、マップ上に注釈として記入してある。Gが武器(GunのG)、Aが鎧(ArmorのA)、Kが敵全滅(Kill AllでK)、Iが一定時間無敵(Invulnerable)、Wがワープ、*は取ってしまうと一定時間敵に攻撃が当たらなくなるアイテム。また、VはAct開始時のValisの位置を大雑把に示している。

このマップを見るとAct 6のボスが壁の中に埋まっていて、Wizardryだったら「かべのなかにいる!」で勝手に消滅してしまいそうなのだが、この場合、プレイヤーが会敵できないためクリアできないように見える。この点については後述。

また、Act 3, Act 5, Act 9でワープを使うことができて、Act 3ではワープステージの(U,6)、Act 5では(1,4)、Act 9では(S,1)に入ることができる。そして、ワープステージ内のWに入ることでワープステージから通常のActに戻ることができる。なお、Act 5からワープした場合、Act 6はスキップしてAct 7に出る。また、普通にActをクリアすると次のActの開始時に盾が消えて探しなおしになるが、ワープステージ終了時は盾が消えないので、ワープステージ内の強力な盾を取っておくことで、次のステージの序盤が楽になる。

Act1


Act2


Act3


Act4


Act5


Act6


Act7


Act8


Act9


Act10


WARP


ゲームプレイ

このゲームのそれぞれのActですることは決まっている。まず、鎧をゲット。次に敵を倒して落ちてくるジェムを集めてLifeを貯める、必要に応じて武器もレベルアップ、そしてボス戦。

画面右下の矢印が大雑把にボスのいる方向を指し示してくれるが、バグなのか、意図的なのかときどきぜんぜん違う方向を指し示して袋小路に持っていかれる。なお、Act 5ではワープの方向を指し示すことがあるようだ。FM77AV版のAct 6が隠しキーを使わない限り実質クリア不能となっていてAct 5ではワープを使わざるを得ないことを考えると、これは意図的だったのかもしれない。

ボス戦は、基本的に敵に弾を当てたら反対側に逃げる。すると左右どちらかからボスがまた接近してくるので、弾を当てて逃げる。これを繰り返すだけ。ラスボスもそう。多くのボスはほぼノーダメージで倒すことができる。Act 9ではこれが通用しないからきつい。Act 9は、ドラゴンバスターで言うところの「壁ひっつき」の技を使って、フィールド右下角にしゃがんでひたすら弾を連射する方法で勝てた。が、あえてAct 9のボスを倒したい理由が無ければワープしてしまったらいい。

各Actが実質的に鎧探しゲームになってしまうが、マップが無い時点では、あまりにも広大なマップのどこに鎧が落ちているのかわからず、またラスボス方向を指し示すはずの矢印がとんでもない方向を頻繁に指すので、かなり忍耐力を要するゲームだったが、マップがあれば割とスムーズに進めることができると思う。

発見したこと

FM77AV版はAct6がクリアできない?

上のAct 6マップを見ると、ボスが壁の中にいるため、ボス戦を開始することができない。コピープロテクトかと思って調べたが、Act 6突入時にチェッカーが動いている様子はなかった。Valisは原本ディスクを2セット持っていて、1セットはトラック0のサイド1にエラーがあって起動できないのだが、その部分をもう一セットのディスクイメージからコピーしてフランケンイメージにすることで起動できる。しかし、どちらのセットから作ったディスクイメージを使っても結果は同じだった。この2枚のディスクは、一部だけ微妙に内容が違っているので、片方がバグフィックス版ではないかと思ったが、両方で動作が同じであること考えるとその可能性は無さそう。これはFM77AV版のバグだったのかもしれない。

まず、当時のゲームの中にはコピープロテクトチェッカーが、途中までゲームが進んだところで発動して以後進めなくするという仕掛けがよくあった。FM77AV版「夢幻戦士Valis」の場合は、F7セクタの一部のバイトが読むたびに値が不定になることを利用したものだった。基本的にF7セクタを読み込んでいる個所を探せばチェッカーは特定できる。その要領で調べたところ、どうもチェッカーは起動時に一度作動しているだけで、ゲーム開始後は作動していないようだった。未知の方法(例えばセクタは読まないけど、アドレスマークをチェックするとか)が無いとは言い切れないのだが、どうもAct 6がクリアできないのがプロテクトの影響では無さそう。FM77AV版「夢幻戦士Valis」にはチェッカーが二か所あるという説もあったのだが、どうも、これは二か所あるのではなく、出荷時期によって使っているプロテクトの種類が違うというものだったらしい。

そして、このAct 6は、このPC88版のプレイ動画を見ると、どうも区画(G,S)付近でボス戦開始になるべきらしい。開始地点から右に移動して、次の通路に到達する前に降下、その後左に移動して、中空の床などが無い通路でボス戦が開始しているようなので、区画(G,S)あるいは(F,S)がPC88版のボスの位置と見て多分間違いない。 これは非常にもっともらしい場所で、基本すべてのActで、ボス戦は水平方向に長い場所で発生するようにできている。縦方向の移動が異常につらいこのゲームで縦移動を使ってボスと戦うのはあまりにも難しいという判断だったのではないかと思う。そうであれば、FM77AV版のAct 6はボス戦の区画座標が間違っていることになる。

このFM77AV版のプレイ動画では、Act 5のワープを使ってAct 6を避けている。果たしてAct 6が普通の方法で突破不能だからこのようにしたのかは不明。

問題のボス戦の区画座標は、Disk 2のシリンダ18、サイド1、セクタ1のオフセット$02A5にある。

  
02a0 1b 1c 1d 1e 1f 03 08 09 09 10 16 00 00 08 04 0c|................ ^^ ^^
なぜかYとXが入れ替わっている。プログラム中では、EXG A,BしてからメインRAM$0D26の2バイトと比較している。もしも、コピープロテクトにひっかかっているとすれば、セクタを読み込んだ後でプロテクトをチェック、あるいはそれより前にプロテクトをチェックして立ててあったフラグを見て値を変更するはず。Y=$1C, X=$0FまたはX=$10であるべき。しかし、そのような兆候は無かった。起動時のチェッカーがメモリに書き込んだ値は全てプログラム本体によって上書きされているようだ。また、フラグをチェックしているような個所も発見できなかった。

こうなると、実機で確認するしかない。フロッピーディスクは使うたびにすり減るメディアだから、なるべく原本ディスクは使わないことにしているが、この際仕方ない。問題のマップとボスの位置は、FM-7シリーズの裏RAMと呼ばれる領域、メインRAMの$8000~$FBFFの間にある。この領域はリセットしてもクリアされない。実機でAct 6まで進めた上でリセットをかけることでメモリダンプを取ることができる。1987年当時と同じ条件で、原本のディスクで実機で起動するわけだから、このやり方でクリアできないならば本当にクリアできないはず。


実機による実験風景。FM77AVが2台と隣は今回は使わなかったFM TOWNS 2MX。

まずは、ボス座標を調べる。リセット後、F-BASICのMONコマンドを使って、以下のプログラムを入力して、EXEC &H2000で実行。これによって、裏RAMの$9DE0~の256バイトを$5000~に転送できる。転送後、$5004, $5005の値がボス座標となる。

  
2000 ORG $2000 2000 3401 PSHS CC 2002 1A50 ORCC #$50 2004 B7FD0F STA $FD0F ; Switch to shadow RAM 2007 8E9DE0 LDX #$9DE0 200A CE5000 LDU #$5000 200D 5F CLRB 200E A680 LOOP LDA ,X+ 2010 A7C0 STA ,U+ 2012 5A DECB 2013 26F9 BNE LOOP 2015 B6FD0F LDA $FD0F ; Switch back to F-BASIC ROM 2018 3581 PULS CC,PC

結果、まず、問題の$9DE4, $9DE5の値は、$10, $16だった。下のスクリーンショットで$5004, $5005の値が$10, $16であることがわかる。

次に区画マップを調べる。今度は、$8000~の1024バイトなのでプログラムを以下のように書き直す。

  
2000 ORG $2000 2000 3401 PSHS CC 2002 1A50 ORCC #$50 2004 B7FD0F STA $FD0F ; Switch to shadow RAM 2007 108E8000 LDY #$8000 200B CE5000 LDU #$5000 200E 8E0400 LDX #$400 2011 A6A0 LOOP LDA ,Y+ 2013 A7C0 STA ,U+ 2015 301F LEAX -1,X 2017 26F8 BNE LOOP 2019 B6FD0F LDA $FD0F ; Switch back to F-BASIC ROM 201C 3581 PULS CC,PC

以下のスクリーンショットは、EXEC &H2000の後$5000~に転送された区画マップのダンプ。

画面サイズの都合で全部表示しきれなくてパターンがわからないので、RS232CでTeraTERMに転送するプログラムを書く。

このプログラムで転送した結果がこれ。

202020201E202020202020201E202020202020201E202020202020201E202020
202020201F202020202020201F202020202020201F202020202020201F202020
202020110F1520202020201309172020202020140D162020202020120B182020
20201208090A1620202014100F0E1820202011080B0E1720202013100D0A1520
1B1C0D0B0C0D0B191A1C0B0D0C0B0D191B1C0F090C0F09191A1C090F0C090F19
2020000E0F1005202020020A090807202020030A0D1006202020010E0B080420
2020200109042020202020030F062020202020000B052020202020020D072020
202020201D202020202020201D202020202020201D202020202020201D202020
202020201E202020202020201E202020202020201E202020202020201E202020
202020201F202020202020201F202020202020201F202020202020201F202020
202020120B182020202020110F1520202020201309172020202020140D162020
202013100D0A152020201208090A1620222014100F0E1820202011080B0E1720
1A1C090F0C090F191B1C0D0B0C0D0B191A1C0B0D0C0B0D191B1C0F090C0F0919
2020010E0B0804202020000E0F1005202020020A090807202020030A0D100620
202020020D0720202020200109042020202020030F062020202020000B052020
202020201D202020202020201D202020202020201D202020202020201D202020
202020201E202020202020201E202020202020201E202020202020201E202020
202020201F202020202020201F202020202020201F202020202020201F202020
202020140D162020202020120B182020202020110F1520202020201309172020
202011080B0E1720202013100D0A152020201208090A1620202014100F0E1820
1B1C0F090C0F09191A1C090F0C090F191B1C0D0B0C0D0B191A1C0B0D0C0B0D19
2020030A0D1006202020010E0B0804202020000E0F1005202020020A09080720
202020000B052020202020020D0720202020200109042020202020030F062020
202020201D202020202020201D202020202020201D202020202020201D202020
202020201E202020202022201E202020202020201E202020202020201E202020
202020201F202020202020201F202020202020201F202020202020201F202020
2020201309172020202020140D162020202020120B182020202020110F152020
202014100F0E1820202011080B0E1720202013100D0A152020201208090A1620
1A1C0B0D0C0B0D191B1C0F090C0F09191A1C090F0C090F191B1C0D0B0C0D0B19
2020020A090807202020030A0D1006202020010E0B0804202020000E0F100520
202020030F062020202020000B052020202020020D0720202020200109042020
202020201D202020202020201D202020202020201D202020202020201D202020
わかりにくいので、問題のボス戦の区画を赤く表示した。この区画コード$20は完全にソリッドな壁。そして、その周囲も$20に囲まれているので、この区画に進入するのは完全に不可能。実機の原本ディスクを使ってもボス区画への進入は不可能であることがわかった。

他のゲームなら、ある条件を満たすことでボス戦につながる道が開けるような仕掛けがありそうだが、「夢幻戦士Valis」ではAct 6以外でそのような仕掛けは一か所も存在しない。また、このステージだけが特別であるという理由も見当たらない。仮に、マップが変化するような仕掛けがAct 6に発生するならば、同様の仕掛けがAct 7以降に存在しないのはあまりにも不自然。少なくともPC88版では特別なことをしなくてもボス戦に到達することができるようなので、FM77AV版でそうではない理由は考えられない。

やはりこれはバグだった可能性が高いように思う。そうであるならば、バグ修正版が果たして存在したのか? これは、解明するのが難しい。ヤフオクで片っ端からFM77AV用Valisが出るたびにを買って調べると破産してしまうし。

そこで、ゲーム保存協会にご協力いただいて、なんと! 合計11枚のFM77AV用「夢幻戦士Valis」のディスク2の当該セクタを調べていただいた。結果、Act 6のボス座標はすべてY=$10,X=$16ということがわかった。この枚数を調べて修正版が見つからないということは、バグ修正は無かったと考えても間違いなさそうだ。

このAct 6問題はなぜ問題にならなかったのか? 当時の記事でFM77AV版「夢幻戦士Valis」についての記述を確認できたのは、Oh!FM 1987年 9月号 82ページのみだった。それ以外での記述は今のところ発見できていない。この記事は最終ステージ、Act 10の写真が掲載している。ソフトバンクのOh!FM編集部では最終ステージAct 10まで進出できたと見るべき。ただし、テレネットから編集部に記事執筆のために隠しキーの情報が渡っていた可能性も排除はできない。

この件に関しては、実はAct 5は本来ワープすべきステージだった可能性がある。このゲームでは、ステージクリアに向かう方向を画面右下の矢印が指し示すことになっている。その矢印の方向はメインRAM $A000~に1バイトあたり2区画で書かれている。各バイトの上位・下位4ビットが矢印方向。値が5の場合は矢印は更新されない(直前に表示されていたものがそのまま残る)。6以上の場合は、値から1を引く。さらにその値から1を引いて、最終的に$3139~の変換テーブルで矢印方向が決定する。矢印方向は上が0、反時計回りに7まで45度単位で定義される。Act 5のこの矢印をプロットしたのが、次の図。

開始地点から素直に矢印に沿って進んでいった場合、次の図の赤い線で示したように、ワープポイントに誘導される。ここは袋小路だが、何かないのか探しているうちにワープにヒットする可能性はかなり高い。実際、自分は解析するまえのプレイでこのワープに誘導されたたためAct 6は飛ばしてAct 7に進んだ。

では、仮にここのワープに入らなかったとして、ボス戦に向かっていこうとしたらどうなるか? ボスに向かうには、次の図で赤で囲った区画(E,1)または(E,3)を通らなくてはならない。しかし、どちらの区画も矢印はボスから遠ざかる方を指す。矢印を信じて進むプレイヤーは絶対ボス戦にたどり着かないようになっている。このことから考えられるのは、Act 5でプレイヤーはワープを発見するはずだったという可能性がある。せっかくワープステージを作ってもプレイヤーが発見しないのでは意味が無い。仮にプレイヤーがワープステージをここで発見すると、過去のActにもワープがあった可能性も考えるし、以後のステージでもワープを探すようになるだろう。従って、Act 5は意図的にワープするように仕組まれたステージだった可能性が高い。

では、FM77AV版Act 6では矢印はプレイヤーをどこに誘導するのか? 上に挙げたこのPC88版のプレイ動画では、プレイヤーは普通に矢印の方向に進んでいくことでボス戦に到達できている。ところが、FM77AV版のAct 6では矢印はまったくでたらめで誘導になっていない。まず、開始位置(G,C)では、右に向かうように誘導されるが、通路を抜けると左に戻るように矢印の方向が変わる。ここで既に詰んでいる。しかし、それを無視して真横に進むと、(K,C)では上向きに、(K,D)では下向きに、微妙な違いによってまったく反対方向に向かうように指示される。仮に下に向かったとしよう。(K,F)までは矢印は下向き。ところが、(K,G)では矢印は上を向く。ただし、矢印の表示は画面の左上角にあたるブロックが元になっているので、プレイヤーのいるブロックのひとつ左のブロックの方向が表示されるが、この場合結果は同じ。マップ内の適当な場所から矢印をたどってみるとわかるのだが、どこから初めてもでたらめな場所に誘導されてしまい、何のヒントにもならないことがわかる。このことからも、FM77AV版ValisのAct 6は意図的に仕掛けられたトラップだった可能性が考えられる。


Act 5では、矢印に沿って行くとワープ地点に誘導されるので、無理やりボス戦に勝ってAct 6に進むのは罠だった、と説明されても当時なら納得されてしまったかもしれない。また、Act 6の矢印がプレイヤーを混乱させるような方向に設定されていることから、実際にAct 6は意図的に仕掛けられた罠であった可能性もある。


Act 5この地点から真上にジャンプするとワープ

隠しキー

マニュアルでは、PAUSEが可能と公式には書いていないが、ESCキーを押すとPAUSEすることができる。PAUSE中、隠しキーコンビネーションを使うことができる。これは、メインRAM $2528~の隠しキーチェックルーチンの解析でわかったこと。

アイテムコード

1-6
7-10
11 敵全滅
12 一定時間無敵
13 一定時間敵に攻撃できなくなる
14 ワープ(なんとワープ地点はアイテムだった)

メモリマップ

$0D02 Act番号。最初のActが1。ワープステージは、Act 3からのワープが$FF, Act 5が$FE, Act 9が$FD。
$0D07 1を書き込むとボス戦突入。
$0D0A 1を書き込むといきなりActクリア。
$0D0B 1を書き込むとワープ。
$0D0D 画面右下の矢印の方向。0:上 1左上 2:左 以下7まで反時計回り FF:未表示(ボス戦中?)
$0D0E 0以外の値を書き込むとステージセレクト。
1~10($0A)でそれぞれのActにジャンプ。11($0B)でエンディング。$FF,$FD,$FB,$F9,$F7を書き込むとAct 1。$FE,$FC,$FA,$F8,$F6を書き込むとワープステージ。ただし、壁の中に出現したりする。
$0D26,$0D27 画面左上の区画座標
$0D28,$0D29 画面左上の区画内座標
$0D43 マップ内アイテムテーブルへのポインタ。6バイト単位で、+0=(00:存在 FF:取った後)、+1=アイテムコード、(+2,+3)=区画座標、(+4,+5)=区画内座標。
$0E80~ キーステート。FM77AVのキーコードで、押してるキーがFF,押してないキーが00。
$8000-$83FF 32x32の区画マップ。
$8400-$9CFF それぞれの区画内マップ。各区画は20x10ブロックで、200バイト単位。$4*,$5*が床(下からジャンプして乗れる)、$8*,$C*,$D*が通行不能な壁。0は何もない背景で、それ以外はただの模様らしい。
$9D60-$9D7F 32<=区画X座標になったときの区画Y座標の変換テーブル
$9D80-$9D9F 区画X座標<0になったときの区画Y座標の変換テーブル
$9DA0-$9DBF 32<=区画Y座標になったときの区画X座標の変換テーブル
$9DC0-$9DDF 区画Y座標<0になったときの区画X座標の変換テーブル
$9DE4 ボスの区画座標
$A000 0x200バイト。1バイトあたり2区画分の矢印表示方向。区画Xが奇数だと上位4ビット。
4ビットが5の場合未定義。6以上の場合は1を引く。
さらにその値から1を引いて、最終的に$3139からの変換テーブルで矢印方向になる。
変換テーブル{03,04,05,02,06,01,00,07}={左下、下、右下、左、右、左上、上、右上}
$A800 現在の画面上のブロック (20x10)
$B800 $2Dバイト単位で9個の構造体がキャラクタらしい。$B800は優子本人。
$B815 無敵時間の残り。
$B80A 優子画面上のブロック座標X。半ブロック単位で動くため2倍になっている模様。
$B80B 優子画面上のブロック座標Y。半ブロック単位で動くため2倍になっている模様。
$B81D 持ってる剣
$B81E 持ってる鎧
$B995- $2Dバイト単位で画面内に見えているアイテム情報。(+4=アイテム構造体へのポインタ、+10=画面上のブロック座標X、+11=画面上のブロック座標Y)

Comments are welcome.  Send E-Mail to: 

Back to http://www.ysflight.com