タイニーゼビウスをX68000に移植してみた

一年前のメモから

2012年6月8日のことでした。6月8日はX68000の日らしく、twitterではX68000が好きな人達や、ライバル機種の人達が入り乱れて、各々が楽しく一日を過ごしていました。その様子は「2012年6月8日は「X68000」の日」にまとめられています。

うんうん、みんな楽しそうですネ・・・いやいや!P6er(※PC-6001ユーザのこと)としては、いくら格下の機種(PC-6001>越えられない壁>X68000という意味)とはいえ、ライバル機が活発に活動しているのを見過ごすわけにはいきませんから、ここは何か仕掛けねば!と一人勝手に思い立ちました。

とはいっても、当日に何かするには仕込み時間が無さ過ぎたので、1年後の2013年6月8日を目標日に定めました。変化の激しい時代になんと気の長い話。でもこの不安定なご時世(※2012年)に1年後のネタを考えるくらいの心のゆとりがあってもいいよね。

何をつくろか

まず最初に思いついたネタが、X68000の代表的なソフトをPC-6001に移植することです。
え、何言ってんのコイツと思われそうな妄想ですが、PC-6001には「タイニー移植テクニック」があるのです。つまり、どんな大作であってもタイトル名に「タイニー」を付ければ誰もが納得してしまう、そんなテクニックです。
例えば「タイニーグラディウス」とか「タイニーファイナルファンタジー」とかなら、グラフィックが物足りなくても速度が遅くても、なんだか許せてしまう雰囲気になるのです。(※1)

※1 タイニーという言葉をどうとらえるかは人それぞれですが、私はPC-6001らしさを表すとても良い意味の単語だと思っています。ばかにする意図はないです。

X68000の名作がP6でも動いちゃってるモンネーというのは愉快そうです。X68000のゲームで有名なものとなると、ジェノサイドやファランクス、魔神宮でしょうか。「タイニー魔神宮」なんてキャッチーじゃん!BASICでいいし!と思うのですが、このネタのギリギリ感を理解出来る人がPC-6001陣営どころかX68000組にも少ない気がします、ザイン。

そんな感じで、何を移植しようかなーとネットでX68000のタイトルを調べながらツイッターのTL眺めていたところ、「侵略!」の文字が目に飛び込んできました。2012年頃まだアニメイカ娘ブームの余韻があったのですね。・・・そっか、X68000のソフトをPC-6001に持ってくるより、積極的に侵略的な攻めの姿勢として、PC-6001のタイトルをX68000に移植して侵略すればいいんじゃね?と発想をひっくり返したのです。
PC-6001の雰囲気をX68000に持ち込むというよくわかんない移植ですが、これなら作業的にも趣味プログラムの範疇で無理がなさそうです。

移植するタイトルは・・・うん、PC-6001の代表的なソフトといえばタイニーゼビウスです。元々はアーケードの移植作ですが、PC-6001らしくアレンジされてますし、ネームバリューもあります。
移植作のタイトルは68秒だけ悩んで「タイニーゼビウスPRO68K」に決めました。

移植をするにあたっては2つの大きな問題がありました。

まず、タイニーゼビウスの内部的な作りがよくわかっていないことです。雰囲気移植(目コピー)でも充分だとは思ったのですが、グラフィックデータを目コピーするのは面倒ですし、グラフィックデータの吸い出すついでにマップデータの解析もすることにしました。

次の問題が、X68000での開発です。X68000は20年ほど前に色々といじっていたので、漠然と『68000アセンブラをHASとHLKを使ってなんかするんだよ』程度の記憶はあるのですが、スプライトコントローラのレジスタなどの資料を集める必要が出てきました。今の時代に68000アセンブラを書くのもなんですが、普段、PC-6001のプログラムを書くために使っているZ80に比べたら、豊富なレジスタと命令の直交性に優れている68000アセンブラは天国なはずです。
とはいっても、データやプログラムのタスク管理はC言語を使った方が断然ラクですし、タイニーゼビウスを動かすくらいであれば実行速度はそれほど必要じゃないので、GCCの開発環境を整えました。速度やファイルサイズに不満があったらコンパイラで生成されたアセンブラソースを手動で最適化すればいいですし。

なんでも世の中には、クロス開発できるX68000をターゲットマシンにしたGCCがあるようです。すごく興味深いのですが、開発環境上の問題にあたるのは避けたかったので、今回は充分に枯れているHuman68K上で動くGCCを使いました。

ざっと開発環境を説明すると、X68000エミュレータ上で動いているHuman68KにGCC環境を構築して、WindowsのドライブをHuman68Kから見えるようにWINDRV.SYSを使ってマウントして、Windows上でソースを書いてエミュレータでコンパイルしています。

資料集めですが、X68000でC言語による開発といえば、C MagazineでX68000のGCC言語でゲームを作る連載記事があったことを思い出しました。たしか、その連載をまとめたような本が出ていたような気がしたので検索して「GCCによるX680x0ゲームプログラミング」という書籍にたどり着き、さっそくAmazonで注文しました。書籍代は1円で送料の方が高くなるというよくあるAmazonっぽい本の買い方です。

その他は、昔から持っていた「INSIDE X68000」と「プログラマーのためのX68000環境ハンドブック」、それと、「ぷにぐらまーずまにゅある」を参考にさせてもらいました。

開発環境を整えながら、タイニーゼビウスのグラフィックデータとマップデータの解析を進めたのですが、ここでいきなり誤算が発生しました。タイニーゼビウスのプログラム解析作業が楽しくなってしまったのです。マップデータの展開ルーチンを読むにはスクロール処理や画像データの転送処理なども理解しなければならなかったのですが、その延長で他の処理も読みたくなり、結果的に、逆アセンブルした全プログラムを読み終えてしまいました。

当初の目的から外れた副産物であるタイニーゼビウスの解析結果は、@Hashiさんが執筆されているPC-6001の同人誌、PC6000NOTE No.5に収録されています。タイニーゼビウスの処理内容や様々な疑問点への解答など、一通り網羅しています。
現時点では通販はされていませんが、定期的にコミケやゲームレジェンドなどのイベントでTinyProjectというサークルとして頒布されています。→2015年にWebで公開しました。タイニーゼビウス 完全解析&解説

PC6000NOTE 同人誌

どう移植するか

タイニーゼビウス解析した結果としては、X68000への完全移植は無茶な課題だなと思いました。一般論というか常識として、PC-6001とX68000の大雑把な意味でのスペック比較はPC-6001 >> 越えられない壁 >> X68000なのですが、まぁ、そのへんの事はひとまず脇に置いておくとして、完全移植が難しい理由の一つが、PC-6001のタイニーゼビウスは同期を取らずに全力で動作しているという点です。

同期というのはテレビの垂直同期とか音楽の再生時間などですが、そういったものに依存せずに背景のスクロールやキャラクタの移動処理を常に全力で行っています。ですので、表示するキャラクタの増減、つまり処理量によってゲームの進行速度や音の再生速度が微妙に変化しているのです。これを再現するにはZ80のクロック数やPC-6001の各種割り込みタイミングを考えないといけなくなるのですが、こうなるとX68000上で動作するPC-6001エミュレータを作った方が手っ取り早くなってきます。ただ、X68000にはそこまでのCPUパワーはありません。コードコンバートしてクロック数を数えながら調整して動かすという方法もありますが、、その労力に見合わないネタ企画なので、雰囲気が似てれば細かいところはいいやと早々に割り切りました。

スプライトとBGを試す

X68000の特徴の一つはスプライトです。家庭用向けのパソコンにスプライトを搭載しているというのは今からみても尖った仕様ですね。シャープやるね!

ゲーム機ではなく、16bitどころか32Bitといわれてもおかしくない高価なパソコンに搭載されているスプライト機能ですから、タイニーゼビウスのキャラクタならゴッソリとキャラ定義できる、と思っていたのですが・・・X68000のスプライトって
定義できる数が足りない・・・なんてこと・・・。こんなんだっけ?
特にBG面への割当数制限が厳しいです。タイニーゼビウスのキャラクタ数くらいなら余裕と思っていたのに。
これなら、スプライトを使わないでグラフィック面に全部描画してもいいんじゃないかなーと思いました。処理速度は間に合いそうですし。
でも、せっかくのX68000のゲームでスプライトを使わないのも残念すぎるので、キャラクタ管理をするということで。XSPとかのスプライトドライバを使うことも考えましたが、そこまでじゃないかなと思ったので、それなりに自前で管理します。

画面モードの話

タイニーゼビウスの画面モードは256×192です。VRAM上のドット数は128×96なのですが、表示する時に拡大されます。
X68000でスプライトが扱える画面モードは256×256か512×512で、PC-6001横方向の解像度を収めるには512×512ということになるのですが、このモードだとドットが細かすぎるので、裏技的な384×256モードに設定します。この辺のCRTC設定値とかはネット上の資料がほとんどなかったのですが、X68000programing
というページに書かれていて助かりました。ありがたや。

CRTC周りの設定はアセンブラで記述して、ゲーム本体のC言語のプログラムとリンクしたかったのですが、えっと、C言語とアセンブラのコード呼び出しってどうやったっけ?というレベルから思い出しプログラミングです。最近では、アセンブラ混じりのC言語を使う機会はないのでしょうがないよね。

久々のC言語

マップなどのデータを外部ファイルに持ち、それらのファイルをメモリに読み込むのにfread()とかmalloc()といったCのライブラリを使う事には多少の抵抗がありました。というのも、昔、X68000のプログラムを書いていた頃はアセンブラを使っていて、DOS CALLかIOCS CALLが基本だったので、メモリや処理速度にオーバーヘッドのあるライブラリを使うのはやだなぁと。あと、当時はGCCのコンパイル速度が遅くて、X68000ではC言語自体が使いにくいなぁと。
今ではエミュレータのメモリを12M一杯まで載せて、MPU速度を無制限ぶんぶん回せばあっという間にコンパイルできちゃうのでラクラクです。

それにしても、平成が20年も過ぎるとさすがにC言語でmalloc()してメモリ確保なんていうプログラムを書く機会はほぼないので、懐かしさと自前でメモリ管理をする不安感とで不思議な感じがしました。

BG面を表示する

X68000の仕様を確かめつつテストプログラムを書いて、背景の表示とスクロール処理ができました。

capture0

楽しくなってきた!

グラフィック面を調べる

タイニーゼビウスの背景はBG面に描画しますが、タイニーゼビウスはX68000の384×256ドット上の320×192分しか使いません。BG面をスクロールさせる時に画面書き換えの一部が見えてしまうので、BG面の上にグラフィック面を乗せてマスクします。

X68000のグラフィックモードは512×512ドットの画面サイズだと65535色1面か256色2面か16色4面が使えます。今回は16色4面モードにして、そのうちのグラフィック1枚だけを使います。X68000はVRAMが512KByteもあるのに、今回は384×256を4bitカラーで使うわけですから使用するVRAMは48KByteです。なんというもったいなさ!余ったVRAMを作業用メモリとしても使えるのがX68000の使い勝手のいいところです。

しかし、PCGを使う場合は定義用のメモリが足りなくて困るのに、グラフィックでは余るんですよね。妙なバランスだなーと思いますが、メモリをやりくりする楽しさはあります。これがギガ単位のVRAMになるとノーミソ内だけでどうこうするっていうレベルではないですね。

それはともかく、このマスクを描画するために単純にVRAMを青色の単色で埋めてるわけですが、遅い・・・目に見えて遅いのです。なんかこう、BASICのPAINT文で画面を塗りつぶしてるかのような。単純にC言語のfor()で回して処理しているからしょうがないのかもしれません。ここで初めてgccの最適化オプションを有効にしたら、ちょっとはマシになりました。X68000にはVRAMの高速クリア機能とかあったような気がしますが使ってません。

capture01

画面は整ってきたけど、余白が多くてちょっと寂しい感じ。実際のPC-6001では余白部分の色は青ではなく緑っぽい色です。目視で描画ミスを見つけやすくするために開発中ではゲーム画面で使われていない色にしてあります。

スプライトの表示とキーボード&スティック入力

ここまで来たら、次はソルバルウを動かしたくなりますから、スプライトの表示とキーボードからの入力処理を実装しました。

capture02

これまでの準備期間に比べたら実にアッサリと実装できてしまったので拍子抜けです。キーボード周りはもう少し厳密に処理しないといけないかなと思う箇所もあります。例えば、X68000では、OPT.2キーを押しながら何かしらの別のキーを押すと専用テレビをコントロールすることが出来るので、その辺の除外処理を考慮しなければなりません。こういう細かいところは最後の段階でまとめて実装します(こういう作業が積もりすぎるとハマるんですが)。

PCGを入れ替える

この後は特に問題も無く実装作業が続きました。ちょっとだけ悩んだのが、やはりPCG定義数の少なさです。

タイニーゼビウスに出現するキャラクタで最大のものはアンドアジェネシスで、16×16ドットのパターンが縦横に6個で36個のキャラクタデータになります。タイニーゼビウスのアンドアジェネシスはファミコン版と違い、アーケード版準拠で背景と別れていて浮遊しています。
また、X68000の正方形ドットモードではBG面を1枚しか持てず、そのBG面は背景に使っています。となると、アンドアジェネシスはスプライトか、グラフィックか、テキスト面(X68000のテキスト面は16色限定でグラフィック面と同じように扱えます)のいずれかで描き、BG面の上にのせる必要があります。
グラフィック面は16色モードであれば4枚持てるので、マスク用の画像面とは別にアンドア専用に割り当てることもできるのですが、重ね合わせの問題があります。というのも、BG面の上にスプライト面があり、その上にグラフィック面という重ね合わせ順では、アンドアジェネシスをグラフィック面に書いてしまうと、アンドアジェネシスから発射されるスパリオがアンドアの下に隠れてしまいます。
となると、アンドアジェネシスの上に表示されるものをグラフィック面に描くことになりますが、まぁ面倒かなと。まだテキスト面が余っていますが、それはもっと面倒かなと。スプライトを使った方が断然楽なのです。

スプライトの表示数は問題ありません。X68000では最大128個のスプライトを表示できて、ソルバルウ、ザッパーが3発、敵キャラが最大で5機、スパリオが5発、バキュラが13枚程度としても、アンドアジェネシスに36個分のスプライトを使ってもまだまだ余裕があります。
その気になれば、「無理だ、こんなに表示できるわけがない!!」だって出来ます。

ただ、そのキャラクタ定義数の上限が128個で、トーロイドやらタルケンやら背景面のパーツやらで
かなりギリギリなのです。幸い、タイニーゼビウスでは敵キャラは画面上に1種類しか表示されないので(バキュラは別)、その都度、キャラクタ定義をし直せば(ゲーム中に差し替えれば)よさそうです。
このやり方の不安点は、アンドアジェネシスのキャラクタデータ36パターンを定義し直した際に処理落ちするのではないかということした。キャラクタデータの差し替えはテレビの描画タイミングを避けなければならず、その処理時間はあまり多くはありません。1キャラあたり128Byteで36キャラで4608Byteを転送しきれるかどうか実際に試してみたところ、最初に作成したプログラムではみごとに処理落ちして画面がちらついてしまいました。
めんどくさがらずにデータ構造を見直して転送方法も書き直したら若干マシになりましたが、それでも10MHzのX68000だと若干ですが画面がちらついてしまいます。まだまだX68000テクニックが足りてないのですが、そもそも、もうちょっとX68000のキャラクタ定義数が多かったらよかったのになーとは思います。

andor

音を出すよ

タイニーゼビウスの音の出し方は大きく分けて2種類あります。一つはBASICのPLAY文を使った曲の演奏で、もう一つがPC-6001に搭載されているPSG音源を直接操作した効果音です。BASICのPLAY文を使うといっても、タイニーゼビウスのプログラムはオールマシン語で、BASICのPLAY文の内部ルーチンをマシン語から呼び出して実行するという仕組みになっています。
PLAY文のデータはBASICからPLAY文を実行する時と同じものでMMLの記述形式になっています。PLAY”cdefgab”みたいなBASIC文法の引数そのままです。

X68000で曲を演奏するにあたっては、新たにミュージックドライバを作るのも面倒な話なので、既存のドライバで使い勝手のよさそうなものを調べてみました。

ZMUSICはドライバ自体のファイルサイズが大きくて重そうな印象が(最初頃のバージョンだけかも)。
MXDRVはお手軽そうですがX68000の音楽ドライバとしては初期のものなので、この際だから、新しいドライバがいいなーと探してみたところ、MCDRVが技術資料と一緒になって配布されていたので、MCDRVを使う事にしました。MCDRVはライセンス上の制限が非常にゆるかったというのもあります。もっとも移植したタイニーゼビウス自体を配布できませんが。

PC-6001のPLAY文の曲データをMCDRVのMMLに書き直すだけですから作業は簡単そうです。FM音源の音色をどうするかは効果音の出し方と一緒に調べることにしました。

PC-6001のPSGを直接操作して効果音を出す方法をX68000で再現するにあたって、X68000に搭載されている音源IC YM2151について調べたのですが、いやまぁこれがよくわからないのです。ネットにまとまった資料がないのですよ。アルゴリズム(こういう図)に辿り着くのも一苦労で。あるところにはあるというか、それこそ本家YAMAHAにFM音源の詳しい解説ページがあるという事をずいぶん後になって知りました。Google検索さんがんばれ。

結局のところ、YM2151については書籍のinside X68000の資料が一番充実してました。著者の桒野さんにはぜひ、outside X68000と共に電子書籍化して頂きたいです。

でも、資料を集めて読み進めてわかったのですが、YM2151の詳細機能は原則非公開なのですね。それで実際にYM2151のパラメータ(レジスタ)をいじってみたのですが、もしかしてYM2151って任意周波数の矩形波やら三角波を出せない・・・?ということに気がつきました(いまさら)。YM2151はなんでもかんでもサイン波で出すらしく、PSGみたいな矩形波三角波を直接出すことは出来ないようです。使い勝手悪し!やっぱPSG最高だな!
矩形波はサイン波の合成波で表せるじゃん・・・?とか考えましたが、面倒すぎるのでやめました。断続的にキーオン/オフを繰り返して矩形波を作るとか出来そうなんですが。あ、そういえばS44PLAYとかありましたね。

いっそのこと、効果音はすべてADPCMでいいんじゃね?と思ったのですが、とにかくPSG音を再現出来なくても雰囲気的に似た音が出ればいいという事にしました。YM2151はすばらしい音源ですが、自分の力量が足りないのですはい。なんというか、個人的にはX68000のジョイスティックポートに接続するAY3-8910ボードでも作った方がよっぽど楽だよ!とか思ったり。

音楽ドライバMCDRVの制御はC言語ではなくアセンブラで記述しています。68000アセンブラは10年以上使っていなくて、lea.lとmove.lとpea.lとか混乱もしましたが、書き始めると結構スラスラと命令が出てくるものですね。
ここでつまづいたのは、C言語からアセンブラへのデータの引き渡しとその逆のやり方です。
C言語のプログラムとアセンブラの組み合わせをするには、どういうやり取りが必要なのか忘れちゃってました。PlayStation2やPICやAVRの開発だとC言語&アセンブラという組み合わせをやったことがあるし、ネットで資料を探すと出て来るのですが、68000上でのやり方は資料が見当たらなくて。レジスタ引き渡しとスタック渡しの違いってなんだっけ。
これは探すよりも自分で調べた方が早いかなと思ったので、関数呼び出しをする単純なC言語のプログラムを記述しコンパイルして完成した実行ファイルを逆アセンブルしてパラメータのやり取りを調べました。
アセブラからC言語への戻り値はd0.l、その逆はスタックに積んでパラメータを受け取るみたいでいいようです。C言語からアセンブラに引き渡すパラメータ数が少ない場合はレジスタ経由でも渡せたような気がしたのですが、スタックで済むならそれでいいかなと。
アセンブラ側ではd0以外のすべてのレジスタを保持する為に、movemでレジスタをスタックに一括待避するのですが、これをやると引数格納先のアドレスがずれるんですけど、これってどうやって解決するのがスマートなのかわかってません。link/unlinkとかだっけ?

こういうC言語とアセンブラを組み合わせる作業をしてると、プログラムを書くということは、CPUのプリミティブな命令を実行する事なのだというのがよく見えてきます。C言語は古い言語で、私も普段はPHP、ActionScript、C#などを使ってゆるーくプログラムを書く事しかないのですが、低レベル言語にはそれはそれでコンピュータを直接触る楽しさがあると思います。仕事ではやりたくないですけど。

さて、これでビックリするほどあっさり曲が流れました。まずなにより、MCDRVの作者様に大感謝ですが、疑問点がいくつか。

曲の無限再生の方法がわかりませんでした。もしかしてできないのかな?ゲーム中のBGMを延々と流したい場合ですね。普通のゲームであれば、1曲が5分くらいで1面の長さが1時間くらいかかるゲームだとしても(グラディウスVとかそんなん?)、12回ループさせれば済みます。MCDRVでも最大で255回までループできるので、RPGで寝落ちしてもまぁ一晩くらい同じ曲をほぼ無限に再生させる事はできると思います。
ただ、タイニーゼビウスのBGM(ブーンっていう音)では、単発の短い音(1秒くらい)が延々と繰り返されるので255回じゃ足りないのです。
今回は、単発音をずらずらっと並べておいて、さらにそれをループさせるという方法で回避しました。なので、70分くらい死なずに遊んでいると、255回ループしてBGMが途切れます。短音だと288バイトの曲ファイルが、この方法だと2キロバイトにもなってしまってカッコワルイのですけど、いい解決方法が思いつきませんでした。
また、MCDRVには曲の終了などのタイミングでイベントが発生するので、それを利用する方法も試してみたのですけど、イベント発生時に呼び出される処理中に曲の再生を実行すると、さらにイベント呼び出しが発生して…と無限ループにおちいるみたいでうまくいきませんでした。

あと、mml変換をするmcc.xは曲の長さが70分を越えると総演奏時間が0秒に戻ってしまうとか、MAコマンドのエラーメッセージがMPと混ざってるとか振幅パラメータがマニュアルと違うとかあるのですが、1998年で更新が止まっているソフトの不具合報告を作者様にしても困ってしまうでしょうから、ここに止めておく話ということで。

で、結局、音周りはあまり時間をかけることが出来ませんでした。
特に、タイニーゼビウスではノイズ音を多用しているのですが、YM2151ではノイズが1つしかないので、アンドア出現時のノイズ音とブラスターのノイズ音が重なると片方が消えてしまって、これはイカンということで、結局、ブラスターの着弾音にはADPCMを使う事にしました。

音の出し方を試行錯誤しつつキャラを表示させたりして息抜き。

SOL

タイニーゼビウスのソルは勝手に生えてきます。

bacura

タイニーゼビウスのバキュラとグロブダはズッ友。

余白を活かす

PC-6001の実機画面では、上下左右に色の付いた余白が出来ます。PC-6001初代機のモード3では
緑か白、PC-6001mkII以降では黒色で塗りつぶされます。この塗りつぶし処理はVDG(VDP)が自動的に行います。

X68000の画面にPC-6001の画面を再現するとなると、同じように塗りつぶし処理を記述することになるのですが、言い換えると何を書いてもよいということになります。プログラムを書き始めた頃は、余白部分にスコアや残機を表示しようかなーと考えていたのですが、タイニーゼビウスでは、ゲーム開始前に軽快な音楽と共にスコアと残機が表示されるので、

intro

この上にスコアされたら妙です。だったらゲーム開始前画面の表示内容を変えてもよかったのですが、この手の改変作業を始めると、オリジナルを出来るだけ忠実に再現するのとは別のものになってしまいます。その辺は自重して元のゲームのシステムには手を加えない事にしました。

ただ、画面のどこかにPC-6001の文字を常に表示しようと思っていたので、

ILOVENEC6001

こんな感じに右下にゼビウスフォントで文字を描いてみました。オリジナルのゼビウスフォントってハイフン(マイナス)の文字がないので、自作(というほどの文字じゃないけど)しています。NECの文字が赤いのは経営が赤字だからとかでなくて、昔のNECのロゴは赤かったからですヨ!

もっとデカデカと左右に

デカモジ

PC-6001と表示してPC-6001を主張することも考えたのですが、ちょっと品がなさすぎなので自重しました。

ゼビウスフォントの表示はグラフィックRAMに書き込んでいます。グラフィックRAMを操作していて気がついたのですが、キャプチャ画面をよく見ると、BG/スプライト面の上に重ねているグラフィック面のマスクの最下段(=ゲーム画面の最下段)に黒いラインが見えていますね。最初は座標計算を間違えたのかなと思ったのですが、よくよく調べていると、グラフィック面のY位置が1ピクセルだけ上にずれていました。つまり、最上段が画面外にあります。386×256モードの画面設定で何かミスってるのか、それともそういうハード仕様なのかわかりません。XM6gでは発生しているのですが、WinX68K高速版では起きてません。実機だと最初は発生していなかったのですが、なぜか途中から発生するようになってしまいました、謎すぎる。ちゃんと調べてないのでわかりません。

エミュレータの妙な挙動といえば、XM6gで129個目以上のスプライトレジスタに書き込みをするとエミュレータ自体がフリーズします。メモリを壊してるのかな?Windowsのタスクマネージャから強制的に停止させてエミュレータを再起動したらディスクイメージが壊れてた、ということが何度かありました。

ただ、こういう細かい不具合を抜きにしてもXM6gがなかったら移植作業は進まなかったのでエミュレータ作者様には本当に感謝しています。贅沢を言えば、「MPUだけ最高速で動かす」をショートカットキーで切り換えられるといいなーと思いました。コンパイル時だけ高速化するのに便利なので。

初めての実機

開発作業の区切りのいいところで実機で実行してみました。さぁどうだ!

fault

なんたる無慈悲!エミュレータでは動くのに実機では動かないってデバッグが大変なパターンじゃないですかー。
セグメンテーションフォルトってどこのUNIXか!みたいな気がしますが、教えてくれるだけ親切ですね。GCCを使ってなかったら白窓バスエラーが表示されてたのかな。

この原因を調べる前に、XM6gだけでなくWinX68k高速版でも試してみたのですが、どちらのエミュレータでも問題なく動いたので、実機向けにデバッグ用のコードを埋め込んだプログラムを作って原因を突き止めました。
開発はWindows機上のX68000エミュレータで、エミュレータ内で生成されたファイルはWindows上のエクスプローラからもアクセスできるのですが、それを実機に持って行くのには実メディアを使ってのやり取りをしています。もうひたすら行ったり来たりの繰り返しでした。この辺、簡単にやり取りできる方法があればいいのですが、Nereidでnfsとかが簡単なのかな、誰かNereidください。

起動しない原因ですが、Human68K+command.x起動時の初期画面モードではスプライトコントローラのバスが切り離されているらしく、この状態ではスプライトコントローラ(シンシアさん?)にアクセス出来ないというものでした。もしかしたら十数年以上前に同じ経験をした経験があったのか、なんとなく怪しいところが直感的に閃いたので、問題箇所の特定にはそれほど時間がかかりませんでした。
メディアのコピーや実機X68000の再起動の待ち時間にiPadでツイッターを見始めて気がついたら時間が経過してたりとか、そっちの方がよっぽど時間泥棒。

画面周りの設定を済ませてからスプライトの定義を行うようにプログラムを書き換えたところ、起動時のエラーを切り抜けて無事にタイトル画面が出・・・

white

タイトルが真っ白に化けてるしー!まったくもってままならぬ!

この現象はXM6gでは出なかったのですが、WinX68k高速版では

bug

見事に色化けしたので、エミュレータ上で原因を追える分、原因追及作業はしやすかったのですが、問題解決は先のバスエラー以上に面倒でした。

色バケした色をみると、テキストプレーンに設定されてる色だとわかるので、これはテキストとBGとで共有しているパレット番号0番を使ってるということであって、つまるところ、パレット設定がうまくいってない、と気がつきました。
どうやら、スプライトコントローラには8ビット単位でアクセスしちゃダメというのが理由みたいです、たぶん。プログラムではC言語の共用体を使ってスプライトコントローラにパラメータを設定してるのですが、スプライトのパレットとキャラコードは同じスプライトレジスタに割り当てられていて、そこを8Bit単位で別々に更新しようとして失敗していたみたいです。スプライトコントローラに8ビットで書き込むと上位バイトが00hの16Bit値として書き込まれるのかな。

ファイルサイズ

ソースは混じりっけ無しの純粋C言語で4700行ほどでした。一通り実機で動くようになった状態での実行ファイルのファイルサイズは約55キロバイトです。曲データも内部に持っているのでちょっと大きめです。gccのデバッグ情報やシンボル情報は削ってあります。キャラデータやマップデータなどの外部ファイルは圧縮してなくてトータルで50キロバイトほどになりました。X68Kにしては少ないんだか多いんだかビミョーな。

source

libiocsをリンクしていますが、B_SUPER()とBITSNS()くらいしか使っていないので、これをインラインアセンブラに置き換えればlibiocsを使わずに済んだかも。同様にlibdosはデバッグとロードエラー時のprintf()だけしか使ってないので、これは完全に無くすことが出来ます。数値演算周りが手抜きなので、float2.xが必要っぽいです。
まだまだファイルサイズを縮める余地はあるのですが、そこにこだわる理由はないのでいいかなと。

当初は、プログラム本体のロード時やデータファイルの読み込み時にピーガッガーというBGMを流すつもりでいました。ただ、実機のフロッピーベースで動作させてみたところ、ロード時間が思っていたよりも短かったので、わざわざピーガッガーを聞くための待ち時間を組み込むのも本末転倒なのでやめました。あと、テープのロード音って、分かる人が聴くと『なつかしい!』と思ってもらえるのですが、それを知らないとテープのロード音ってタダのノイズでしかなくて、ADPCMが壊れたようにしか聞こえないかなと。プログラムがバグって変な音がします!ってアンケートハガキを送られても困ります。

あと、やりたかったけど技術的に出来なかったのが、Human68K無しの起動です。モトスとか超人みたいにIPLからゲームが起動しちゃうようなX68000の電源を入れた段階からまるでPC-6001が動いているかのように振る舞う、なんて事をしたかったのですが、どうやったらいいのかさっぱり。
たぶん、X68000のIPLはTrack0Sector1の512Byteを既定のアドレスに読み込むとかなんとかしてて、そこからディスク上のZ形式で作ったバイナリプログラムをIOCSを使って読み出して実行すればいいのかなーとか想像してるのですが、周辺回路の初期化とかがわからないので手を付けられませんでした、残念。実現するには音源ドライバも自作しないといけないですしね。

パッケージとフロッピーラベル

テキトーに。緑色が薄かったというか、うちのプリンタはカラーマッチングできてないのがよくわかりました。今年のエイプリルフールネタのゲームボーイツイッターに比べたら雑にちゃっちゃと作りました。

パッケージとディスク

完成したの?

現時点で未実装な箇所はエリア5以降のデータの入力と動作確認くらいで、プログラムはほぼ完成状態です。COPYキーやらインタラプトキー処理やら細かい未実装はありますが。

こうしてプログラムをちゃんと作っているのでフェイクではないです。ただ、著作権を考慮してプログラムの配布は絶対にしないと決めているので、それ故にフェイクプログラムだと言われても配布できない以上は証明できないですし、未完成でいいかどうかは自分の気持ちの問題だけですね。

何かしらのイベントであれば、たぶん、著作権法第38条の範囲で上映プレイする事はできるのかもしれませんが、そういう話が出たらPC-6001実機とデータレコーダとタイニーゼビウスのテープを持って行くと思います、P6erとして!

まとめ

移植作業終盤の実機バグ取りは大変でしたが、おおむね楽しかったです。

「最近、X68000界って何か話題あったっけ?」→「タイニーゼビウスが動いてるらしいぜ」→「PC-6001か!」という流れでPC-6001の事を思い出してくれる人が増えてくれるといいなと思います。

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