WebMSXの挙動に疑義あり

2017/6/14 | 投稿者: ghost

表題は釣りタイトル(いったい誰を釣るつもりなんだ!?)であって、決して嘘・誇張はないが実質的には何ら問題のない話である。有り体に言えば以下に書き記すことは、ボクがそれを面白おかしく思っていること、それ以外には何ら有益性のない与太話だ、ということをご理解いただいた上で、それでも読みたい暇人だけが読めば宜しかろう。

*     *     *

事の発端は、ある時点において開発中の件のゲームのROMイメージを実行した場合の挙動が、ボクが普段使いしているWebMSXと、OpenMSXおよびblueMSXの各エミュレータで異なることに気づいた(現在は解決済み)ところに遡る。建前上、これらのエミュレータは同じMSX規格を再現したものなのだから、ここにROMカートリッジ相当のファイルを与えて電源投入した直後からの挙動に差異が出る、というのは、かなり異常な事態である。

さて、ここで現象の組み合わせが、

 OpenMSX:正常
 blueMSX:正常
 WebMSX:異常

だったら、さほどボクも驚かなかった。これらのエミュレータの中ではWebMSXが最も後発であり、かつ技術的に最も無茶をやらかしていて、かつ、どちらかと言えばカジュアルユーザー(有り体に言えばWAREZで遊ぶことのみを目的としたユーザー)向けの存在であることを思えば、未発見のバグが埋もれていたとしても驚くには値しないからだ。

が、実際には、

 OpenMSX:異常
 blueMSX:異常
 WebMSX:正常

の挙動を示したので、ボクはとても驚かされたのである。

いやまぁ、この時点で既に出オチ感がアリアリなのだが、もちろんこれはOpenMSXとblueMSXにバグがある、という話ではあり得ないのであって、要するに正常/異常の判断の元になっているボクの書いたプログラムが本来のMSX規格的に異常だったのであり、WebMSXがたまたまその異常を許容する問題を抱えているがために正常動作してしまった(あぁ、異常なのか正常なのかややこしい!)という話なのである。

クレバーな人には、もう何が起こったのか、WebMSXがどんな問題を有しているのか(そして何故それが今日まで誰からも問題視されていないのか)想像がついたことと思う。かく言うボクもこの現象の組み合わせから原因を直感し、対処してみたら正解だった。なんてクレバーなボクちゃん。いや、本当にクレバーだったらそもそもこういうバグ持ちプログラムを書くなよ、と。まぁ、そういう冗談はともかくとして(例によって以下も全部冗談なのだが)ともかくそういうクレバーな人は、もう続きは読むに及ばない。また、この時点で何の話をしているのかさっぱりわからない人も、続きを読んでもきっとやはりさっぱりわからないので続きを読む必要はない。

いまひとつピンと来なかったが、さりとてどういうことであるか知りたい、という無駄な好奇心を有する方のみ、今少しお付き合いいただくことにしよう。


結論から先に言うと、ボクが犯していたミスというのは、電源投入直後にRAMの内容を初期化していなかった、というものである。

なぜこれがOpen/blueMSXとWebMSXの間に挙動の差を生むのか、そもそもボクはどうしてその初期化をしていなかったのか、そのあたりをご理解いただくために、まずはMSXの“スロット”について概説することにする。

MSXのCPUであるZ80は、アドレスバスが16ビットしかなく、同時にアクセスできるメモリは64KBに限定されている。MSXはこの64KBを16KB毎の4ページに分割し、このそれぞれのページに割り当てる物理メモリをある範囲内で切り替えることができる。と言うか、そのように動作し、かつ、その切替方法や現在割り当てられていない資源へのアクセス手段が標準化されているハードウェアのことをMSXと呼ぶ、と言うのが厳密には正しいかも知れない。

クリックすると元のサイズで表示します

上掲図は、MSXが動作中に、各ページにどのように物理メモリを割り当てているかを模式化したものだ。やや単純化し過ぎな物言いになるが、このページに割り当てられたり外されてCPUからアクセスされなくなったりする物理メモリの束を“スロット”と呼ぶ。図の一番左が、ROMカートリッジを何も挿さずにMSXを起動させた際の標準構成になる。青で示した部分はMSXのシステムROMであり、BASICインタプリタのプログラムはここに収まっている。ユーザーは赤で示したRAM部分にプログラムを書いたりロードしたりして利用する。

対して左から2番めの図が、目下開発中のゲームを含む、32KBサイズのROMカートリッジ(緑色部分)を挿してMSXを起動した場合の構成になる。プログラマは自身の書いたプログラムが収まる32KBの他、システムROMのBIOS(MSXの標準機能サブルーチン集)と、16KBのRAMをプログラム実行時のワークエリアとして利用することになる。念のために申し添えれば、ROMとは書き換え不能なメモリなのであって、ゲーム等の複雑なプログラムを実行するには、刻々と変化する得点やキャラクタの位置情報などを管理するRAM=ワークエリアを利用することが必須となる。

余談になるが、上掲図には参考までにMSXの標準OSであるMSX-DOSをブートした状態、およびMSXとして認められる最小構成となる本体実装RAM8KBに16KBのROMカートリッジを挿した状態も例示してみた。今日的なコンピューティングの常識から考えれば、こんな仕掛けを少なからずプログラマが意識してコーディングしなければならないシステムなどというものはナンセンスの極みであるが、MSX規格が登場した1980年代前半の時点では、限られたアドレスバス制約の中でそれを超えるメモリ資源にアクセスするための、これはこれでなかなかイケている設計ではあった。

閑話休題。以前にも書いたが、今回の開発がボク個人にとってはこのROMカートリッジ方式を採用するゲーム開発の初体験となっている。誰に言い訳する必要もないのだが、メモリの初期化を怠る、というズボンもパンツも履かずに外出するかの如き初歩的ミスを犯した理由も、実はここに帰着する。

さて、ボクはMSXでプログラミングするに際し、上図の一番左の状態を前提としていつもコードを書いてきた。この状態で、アセンブラ言語でワークエリアを確保する場合、以下のような記述をするのが普通である。

クリックすると元のサイズで表示します

これは、WORK1というラベル名に8バイト、WORK2というラベル名に4バイトのメモリを割り当て、そのメモリには0を配置する、という意味の記述になっている。これで、他のプログラムの部分からは、それぞれのワークエリアが具体的にどのアドレス(0000h〜FFFFhの64KBのメモリ空間のどこか)であるかを意識することなく利用することができるようになる。

このコードをアセンブルすると、アセンブラがWORK1およびWORK2のラベル名に割り当てたアドレスに、それぞれ8コ、または4コの0が書き込まれたファイルが出来上がる。最終的にそれは、上図の赤で示したRAMにロードされて実行される。

が、血の巡りの良い人は既にピンと来ていると思うが、ROMカートリッジ形式の開発ではこの方法は使えない。仮に同じコードをアセンブルしても、WORK1およびWORK2に割り当てられるアドレスは図中で緑で示した部分になり、そこは文字通りROMカートリッジ上なので書き換え不能なのであって、そこには、どこぞの三文小説ではないが「永遠の0」が居座ることになる。これではワークエリアにならない。

そこで、一般的には以下のような記述でワークエリアを確保することになる。

クリックすると元のサイズで表示します

上記は前例と同じことをやっている記述になる。まず、WORK1とはC000h番地、すなわちRAMの先頭アドレスであることを宣言する。続いて、WORK2は、WORK1に8を加えたアドレスである、と宣言している。これによって、WORK1は連続する8バイトのワークエリアの先頭アドレスとして意味を持つ。WORK2については、仮に次下のWORK3宣言に際し、WORK2 + 4と記述することで、4バイトのワークエリアが確定する。

これが、先の例と大きくことなるのは、このやり方の場合、WORK1およびWORK2というラベル名の具体的なアドレスがアセンブル時こそ解決するものの、アセンブルされた結果生み出されるファイルには、そのアドレスのデータが含まれない、という点である。つまり、このデータをROMカートリッジとしてであれ、ファイルからのロードであれ、メモリ上に展開しても、WORK1とWORK2のアドレスに対しては何も書き込まれないのだ。この時点でのWORK1およびWORK2のワークエリアの中身は、電源投入時のMSXのメモリ状態に依存する。

するとどうなるか。ここでようやく話がWebMSX特有の挙動に戻ってくる。

ボクは当初、従来の自身のMSXプログラミングの思考様式のままに、ただワークエリア宣言の書式のみをROMカートリッジ方式に準じて書く、という愚を犯したのだった。ボクのコードは、DEFS疑似命令がワークエリアに0を書き込んでくれていることを暗に期待して組まれている。が、実は電源投入直後のRAMの中身は、意外なことに必ずしも0ではないのである。

特にこれ以上明らかにすることにメリットがなかったので、実はちゃんと確認まではしていないのだが、上記の問題を含んだ拙プログラムの挙動から判断するに、OpenMSXおよびblueMSXの起動時のRAMの中身はFFh、つまり8ビットのすべてが立った状態と思われる。

両エミュレータの狂信的な開発ポリシーから鑑みるに、大半のMSXの物理実機も同様の挙動を示すのだろう。ちなみに、MSX規格の言葉を正しく拾えば、電源投入時のRAMの状態は「不確定」ということになる。つまり、プログラマは、ボクがそうしてしまったように、そこに0が予めあることを期待してコーディングしてはいけませんよ、という意味。

そして、でありながら、初期化を怠った拙プログラムがボクの意図通りに動作したWebMSXは、OpenMSXやblueMSXとは異なり、起動時にRAMの中身が0になっている、ということになる。事実、この現象に気づいてワークエリアをすべて0で埋め尽くすロジックを冒頭に追記したところ、3エミュレータの挙動は見事に(まぁ、当たり前なのだが)同じに揃った。

無論、前述したようにMSXの電源投入時のRAMの状態は「不確定」であるのが正しい仕様であり、不確定の中には0も含まれるのだから、本稿冒頭に書いたようにWebMSXのこの挙動は実質的には何ら問題のない話であり、単にボクがアホだからこれに気づいた……いや、これに気づいてこうして解説を書いているボクは結構頭がいいのではないだろうか……だけの話なのである。



コメントを書く

名前
メールアドレス
コメント本文(1000文字まで)
URL





AutoPage最新お知らせ