N80は、1993年暮れに開発を開始し、翌1994年に完成してから20周年になります。そこで、昔(1998年頃)に書いていたN80開発日記を再編集してここに公開します。
「PC-8001」がNECより発売された年だ。この頃はSHARPのMZ-80シリーズ、日立のベーシックマスタなどと競合していたが、貧弱なりにもカラーグラフィック機能を備え、他社より廉価だったPC-8001はすぐに人気マシンとなった。海外勢ではApple][、PET、TRS-80などが日本でも売られてはいたものの、とても高価で高嶺の花だったApple][やその他は知名度の低さから日本では国産マシンが主流になった。
私が"パーソナルコンピューター"を知ったのは、友人に連れられて初めて電気街へと足を運んだ時のことだった。まだ世に出て間もない「パソコン」(この名前が定着するまではマイコンとかパーコンとかも呼ばれていた)という商品は、ラジオ店や電子部品を扱うような電気屋で売られ、一般の家電屋で扱われるようになるのはしばらく後になってからのことだった。無線や電子工作にまったく興味のなかった私だったが、店頭でカラフルなデモやゲームを走らせているパソコンを見て一瞬で虜になってしまった(いや単純に自宅でゲーム出来たらいいな程度ではあったが)。幸か不幸か、この日を境にすっかりパソコン道を突き進むことになった。
1970年代後半は、私にとっては大きなイベントやトリガーになる出来事が多かった。1977年にAppleIIが発売され、映画スターウォーズが公開。1978年にはスペースインベーダーゲームが大流行しアーケードゲームは一気に花開き、1979年にはPC-8001が発売、そしてテレビアニメの機動戦士ガンダムが放映開始されたのもこの年だ。何だか、これから始まる近未来を髣髴とさせる気がした。
もう一回やれと言われても、二度と御免だ!と思える程、当時の8bitマシンは使うには不便な代物だった。フロッピーディスクドライブは本体より高価で手が届かず、ましてやネットなんてない。そんなご状況なので、ダウンロードなんて手段もなく、I/OやASCIIなどの雑誌に載ったプログラムのHEXダンプをチェックサムで確認しながら淡々と手入力し、カセットテープにピーゴロゴロと録音して保存。プログラムを読み込むには延々とLoadして、途中でエラーになり最初からやり直したり、テープが伸びたとか、音量が合わない、間違えて上書きしたとか、そんな事は日常茶飯事だった。
それでも楽しかった。とにかく面白かった(相当、思い出補正もされているだろうけど)。それまで映画やマンガでしか知らなかった「コンピューター」が我が家にあるのだから。「2001年宇宙の旅」に出てきたHALを想像してたのに、思った以上にバカで使えないことを知って少々ガッカリしたけれど、個人で所有できるコンピューターに代わりない。
拙いBASICやマシン語でコードを書いては、画面に点が描画されただけでも大喜びしていた。
それから月日が流れた1993年暮、それまで使っていた古いマシンを刷新することにした。長らくNEC PC-9801の天下であった国内市場にAT互換機と呼ばれる黒船が襲来しはじめた頃のことだ。訳あって当時の私には金銭的な余裕はなく、友人のお下がりの486SX(20MHz) CPUや各種拡張カードを元にAT互換機を1台組み立てることにした(当時はメーカー製の既製品よりパーツを買い集めて自分で組み立てるほうが安かった)。聞いたこともないような台湾製のM/Bや格安メモリーを購入し、さぁ帰って組み立てようかと帰路につく途中、友人宅に寄ることになった。
その友人宅の互換機には、目を疑うような光景が映し出されていた。あのApple][の画面がそこには映し出されていたのだ。そのエミュレータは完璧に動いていた。あの独特の画面のにじみ、CALL -151 なんて打ち込むと、ちゃんとモニタに切り替わり簡易アセンブラまでしっかり動く。勿論、ゲームだってちゃんと動いて音まで再現されていた。無骨な互換機の箱型筐体を除けば、画面の中身はまるでApple][そのものなのだ。
これは衝撃だった。しばしの間、そのAppleに夢中なっていた、、、
帰宅すると早速、買ったばかりのパーツを組み立て、慣れない環境に戸惑いながらも使える状態に整えた。そのスペックは当時でも互換機としては貧弱な486SX-20(オーバークロックで25MHzで使用)、8MBメモリー、お下がりのCirrusLogic VGAカードにSoundBluster(16じゃなくて無印)というお粗末なしろもの。しかしPC-DOS(MS-DOS)で使うにはこの程度で十分だ。フロッピー1枚で起動ディスクが作れてしまう、今では考えられない程シンプルなものだったのだ。
ここで、ふと、自分でもエミュレーターを作ってみたいという衝動に突き動かされた。
そしてターゲットに選んだのは、日本のマイコン時代の幕開けとともに一躍スターダムにのし上がった往年の名機、あの「PC-8001」だった。それは私自身の思い入れも強いマシンでもあったし、苦労して打ち込まれたプログラムのカセットテープを何とか復活、活用したいという思いもあった。
Apple][よりはいたって構造も単純なPC-8001なら、まともに動くエミュレータが作れるのではないかと思えた。使われているCPUも8bitではメジャーなZ80(正確にはuPD780というNEC製コンパチ)で、ほとんど割り込みも利用されていなかった。周りにもユーザの多かったこのマシンには当時の資料やソフトも残されていた。
それから創刊されて間もないDOS/Vマガジンや互換機に関する資料を集め、互換機の仕様、特にVGAの機能の下調べをした結果、なんだか実現出来そうな感触がつかめた。
CGA、EGAから、VGAへと進歩した、互換機のテキスト/グラフィック表示を行うデバイスだが、今回はテキストモードを使おうと決めていた。PC-8001は、基本的にテキスト表示しか行えず、これに属性(アトリビュート)情報を付加してやることで文字の表示色や装飾の設定、それに簡易グラフィックを表示するようになっていた(これはTRS-80やMZ-80でも同様のものがあった)。テキストに属性という構造はVGAのテキストモードでも似たような構造になっていた。
VGAでのテキスト表示には、CGAエミュレーションモードというものが用意されていたが、これにはユーザ定義のフォントを表示させるという機能が備えられていた。即ち、半角カタカナやPC-8001独自の記号やグラフィック文字、それに簡易グラフィックスも表示できるということを意味していた。
何事も形から入るタイプなので、このエミュレーターの名前は「N80」にしようと、作る前から決めていた。
さて、PC-8001のエミュレータを作ろうと決心したまではよかったが、ROMをどうやって抜き出そうか悩むことに。実機にはシリアルI/Fはなく、外部にインターフェースらしいきコネクタなんてない。ふと目に付いたのは、パラレル用のカードエッジコネクタだった。その形状はST-506(昔のHDD)によく似ていた。手持ちのジャンクを漁るとST-506のコネクタがあり、これなら口金が合いそうだ。このコネクタとパラレルポート用の口金を配線して半田付けし、これでPC互換機のパラレルとPC-8001を繋いでソフトによるハンドシェイクで吸い出すことにした。
PC-8801ならシリアル転送で楽が出来そうだが、当時はまだPC-8801のN-BASIC ROM(BASIC Ver も 1.2)でもエミュレータが作れるのかどうか謎だったので、安牌のPC-8001 ROMがどうしても必要だった。PC-8001と互換機に転送用プログラムを書いて(Z80のハンドアセンブルなんて何年ぶりだったろう)、何とか作業も無事完了した。何せMS-DOSと8bitマイコン間での作業なのでとにかく効率は悪かった。
これがないとコンピュータは動かない、そう肝心要のCPUだ。とにかくエミュレータのエンジン、心臓部とも言えるZ80エミュレータがないことには「N80」など実現できない。必然的にこのZ80から作ってみることにした。Z80エミュレータ単独でも動くよう、メモリアクセスとI/Oアクセスを外部関数にすることにした。
まずは、Z80と8086のインストラクション表を見比べて、最初はC言語で書き始めた。フラグの変化等、8086との差異に気を付けて、取り敢えずは8080系の命令や使用頻度の高そうなものだけを実装した。未実装命令に関しては、そこで警告を出すようにして、何とか必要最低限の命令セットを完成させた。簡単な実験を繰り返して動作確認し、テストプログラムは正常な結果を返しているようだった。
Cで書いたZ80エミュレータの実験を繰り返し、安定しできたところでアセンブラに切り替えた。とにかく486SX-20のCPUでは荷が重過ぎるのだ。ほんとに動くのかな?と確認の為に、DOSの標準入出力によるにわか作りのPC-8001テキスト表示(VRAM)部だけを実装してPC-8001のROMを走らせてみると、、、
NEC PC-8001 BASIC Ver 1.1
の文字列が表示された!これには身震いを覚えた。
それにしても、いくら構造が単純だとは言えVRAM部と簡単なKey入力実装だけで動いてしまったのには正直驚きだ。この時点で、PC-8001側の他のデバイスは一切実装されていないわけだし。いずれにせよ、これでエミュレーター製作の目処が付いた。こうして93年は暮れていった、、、
それまで、一応テストプログラムでZ80エミュレータのチェックはしていたものの、短いプログラムをちょこちょこと走らせて結果を見ていただけだった。そもそもZ80の動きがこれで合ってるのかどうかも怪しいところ。やはり、ここはPC-8001のROMという、まともな素材でテストするのがベストに思えた。幸いにも先の標準入出力による簡易エミュレータがあるので、簡単なBASICのプログラムなどを走らせてみた。
思いの外、順調に動作しているようなので、実数演算も試してみた。ところが、
PRINT 1/3
と打ってみると、当然.33333と表示されるはずのところ、まったく意味不明の数値が表示されてしまう、、、
生来、不精者の私は、Z80エミュレータにデバッグモードとか、リアルタイムでニーモニックを表示する機能なんて付けていなかった(というか全画面で動作するMS-DOSでは無理があった)。デバッグと言えば、printfという面倒臭がりやなのだ。効率は悪いと分かってはいたが、加算、減算、シフト系の命令のソースを片っ端から見直していくことにした。粘ること数時間、確かに16bit ADD命令に不具合を発見!その他にも演算命令でのフラグの変化にバグを見つけ、修正して再実験に挑むことに。
結果は無事、正しい数値を表示するようになった。
目に見えた不具合は収まったようなので、ここはひとまずZ80エミュレータに一段落つけ、いよいよPC-8001のエミュレータ部分に本格的に取り掛かることにした。
Z80エミュレータからはメモリやI/Oのアクセスを外部関数で実装するようにしていたので、徐々にI/O周りを追加していくことにした。
やはり、優先順位の高いデバイスと言えば"表示"でしょう。
以前、VGAについて下調べした時に課題となった主な点は:
・画面モード
・ユーザフォントの登録
・属性(アトリビュート)の扱い
以上の3点(いずれの問題にしても、基本的に私の知識、力不足に因るところが大きいのだが...)。属性については、そもそもCGAではハード的に上下線などの実現は難しく諦めることにした。画面モードについては、何故か画面の上半分だけに圧縮されて表示されてしまうという謎の症状が出た。未だに原因がわからないが、モードを2回切り替えると回避出切るのを発見し対処。ユーザフォントは、その手の記事を見たことがなかったので、VGAの解説本を頼りに手探りで何とか対処。そして、一番の悩みどころとなったのがPC-8001のアトリビュートを解釈し、VGAのアトリビュートに変換するアルゴリズムだ。
PC-8001では、テキストに色や装飾を指定したり、簡易グラフィックスを表示するためにVRAMに属性領域(アトリビュートエリア)を設けられている。しかし、一行辺り80桁の文字に対して20個の属性領域しか用意されていない。
この属性領域には、どの桁位置の文字に対して効果させるかという桁位置(範囲)情報も同時に記述するのだが、この桁位置情報がクセ者だった・・・、単純に昇順に桁位置(範囲)情報が記載されていれば簡単なのだが、これが必ずしもそうではないのだ。そうすると、思いも寄らぬ表示結果となってしまう。おまけに、このアトリビュートを司るCRTC μPD3301の仕様やデータシートなど持ちあわせていなかったし、チップの細かい動作までは把握していなかった。仕方ないので実機で実際に属性情報を実験しながらの手探りチューンで試行錯誤の上、今の形に落ち着いた(これは、かなり後になるまで行われた)。
それでも完璧なエミュレートとはいかなかった・・・
やはり、PC-8001と言えば、あのピーーッって鳴るビープ音だ。
当時のプログラマーは、この2400Hzの単純な正弦波(矩形波)をスイッチングのみで、ドレミの音階やゲームの効果音を作っていたものだ。しかも、タイマー割り込みなんてハードはないので、クロックとステート数からタイミングを計ってたのだから脱帽ものだ・・・幸い互換機でも単純なビープ機能があるので、周波数を合わせるパラメータをちょっと変更するだけで、実装は楽にできた。
当時の開発マシンの貧弱さは既述の通りだが、DOS環境下でマルチスレッドなど高度なテクニックは難しい。どういうことかと言うと、FDDの8031をどうするかということだった。インテリジェント型FDU 8031は内部に独立したZ80を備え、8255を介してPC-8001/8801とのデータアクセスする仕組みになっていた。そしてFDD搭載の上位機種のPC-8801 mk2登場以降ですら、この仕組みは変わらなかった。MS-DOS上の貧弱なCPUでは2つのZ80をエミュレートさせるのがとても難しいのとFDCのエミュレートも面倒臭そうだった。そもそもPC-8001時代にはFDDなど持っていなかったし、初代PC-8801を手に入れた後もしばらくはテープだけで使っていた(後に中古の80S31を手に入れるまでは)ので思い切ってFDDは無視することにした。個人的にフロッピー版のゲームには余り思い入れがなかったのであっさり決断されたw
まだOSという概念もあまりなく、起動するとBASICインタープリタが立ち上がるPC-8001ではハードのリソース管理というものも厳密に行われているわけではないので、少々デバイスを適当に実装してもエミュレータは動くようだった(そうでなくては、そもそもROMの起動実験など成功しなかった...)。
表示系も一応形になり、キーボード入力部も簡単にできたので、いよいよソフトの吸出しにとりかかることにする。残りのデバイス、Z80命令の実装や不具合の修正は同時進行となる。
しかしソフトの抜き出し方法まで考えてなかった...
ROMの吸出し時にも散々悩んだのだが、更に悩んだのがソフトの吸出しだった。
テープ中のソフトは、ロードという作業を経て始めてメモリに読み込まれる。そしてその時のロードされるアドレスや、ROMルーチンのワーク、マシンの状態も様々なわけだから、これをどうやってエミュレータに持って行けばよいのか...
テープ中のバイナリイメージを、そのまま取り出してエミュレータにテープ読み出しデバイスを実装すればよさそうなものだが、まだ必要最低限のデバイスしか実装していないし、実機側でもZ80のプログラムを組んでテープの吸出しプログラムを書かなくてはいけなくなる。ましてやROM内ルーチンの使い方やテープの読み出し方法なんてとっくに失われた(忘れた?)テクノロジーだっし、そもそも手間がかかってしようがない。
ROMの吸出し時に、実機から互換機への転送ルーチンは作ったので、それだけで何とか済ませたかった。
思案した結果、ある瞬間の実機の状態をそのまま保存(転送)し、その続きからエミュレータで再現するという方法を採ることにした。
これなら先の転送ルーチンだけで済みそうだし、何と言っても手間もかからない。幸いメモリの上位にROM(や多分ゲームでも)が使っていない領域があるので、そこに短い転送ルーチンを置いて、ゲームのBASICやマシン語を普通にロードした後(この時、決して誘惑に負けてゲームをRUNさせずに!)、モニタに移行し先の転送ルーチンを実行してRAM領域のほぼ全部を互換機に転送してしまおうということだ。
そして、まさに実機が転送ルーチンの実行からモニタへ戻るその瞬間からをエミュレータ側では再現させるという段取りだ。
この方法では、Z80レジスタも全てが保存されてないし、マシンの状態も保存されてないわけだが、後者に関しては、実機でのロード及び転送作業は電源ON直後に行うことで余計なメモリ書き換えやデバイスの状態変更が加わらないうちに済ませ、エミュレータ側も必ずリセット直後にメモリイメージファイルを読み込むという、かなり大雑把なルールのもとに運用するということにした。前者は、どうせZ80の事だから、ROM内ルーチンも必要なデータはメモリのワークに保存して必要に応じてそれを読み出しているだろうという勝手な前提のもとに、転送されるメモリのイメージにSPレジスタの値だけ記録させることにして、その他のレジスタ破壊は気にしないことにした。
まず最初に吸い出す実験には、I/O誌に載っていたパックマンを選んだ。
単に好きだったゲームということと、Beep音もコミカルだったので、まだ見ぬエミュレータ上でのゲーム実行にはもってこいのサンプルだと思われた。作業も順調に進み、いざファイルを読み込んでエミュレータで実行してみるがフリーズ...さすがに一発では動作しなかった。
しかし気を取り直して、エミュレータに手を加え、試行錯誤すること丸一日。何と動くようになった!(どこをどう修正したかはスッカリ忘れてしまったけど...)とにかく、あのパックマンが互換機上のVGA画面で動作しているのだ!この事実だけでも、これまでの苦労は消し飛んだ。
さすがに我ながら信じられないことだったが、あんなイイ加減な作戦は一応成功したのだ!
こうしてステキなBeepメロディーとともに見事パックマンが復活を遂げたのだった、そして、これがN80形式ファイルの始まりだった。
そうこうして、仲間内で集まってエミュレータのお披露目実演を行うことにした。また手間のかかるゲーム吸出し作業(とにかく600ボーのテープ速度だし)も我が家にて分担して行うことになった。各々、復活させたい思い入れのあるゲームが違うので、あれでもない、これでもないと喧喧諤諤、賑やかな内に作業は進行した。
多かれ少なかれ各人に影響し、当時の懐かしいゲーム達に再会し、またそれを堪能したのだった。
まだまだ全てのゲームが完全に動作したわけではないが、とにかくこのエミュレータでイケそうだという確信も得られたし、不具合はこれから徐々に修正、改善していけばよいのだから。
友人の元同僚で、このエミュレータの話を聞きつけ面白そうなんで是非見てみたいと一緒に我が家にやってきた人物がいた。彼自身もPC-8801のユーザで興味があったらしい。ともかく、これまでの成果であるN80で遊んでみてもらい、作業にも加わってもらうこととなった。そして、ASCII誌に掲載されていたFEEDORAというゲームを吸出し、エミュレータで走らせようとした時、彼の真価が発揮された。
N80は、まだまだ未完の部分が多く残されていた、ゲームを走らせながら足りない機能を追加し修正していったのだ。それは、Z80部分も同様で未実装の命令もまだまだ多かった。しかし、この時ばかりは様子が違った。N80では、未実装の命令に出くわすと、そのアドレスを表示して終了するようになっている、そしてそのアドレスに示されたコードを見て命令を追加していくのだが、今回そこに示されたコードは普通の命令セットには載っていないものだったのだ。
その見慣れぬ命令の16進コードを見て、彼は未定義命令じゃないかな?以前Z80の仕事の時にやったことあるから、今度メールでコード表送るよ という話になった。お恥ずかしい話だが、それまで私はZ80に未定義(いわゆる隠し)命令セットがあるなんてことは知らなかった。そして、後日送られてきたコード表の通り実装してみると確かにFEEDORAは動き出したのだった。
実は、その日の帰り際に、彼はN80のソースと簡単なロジック図を持ち帰っていった。それから数日後、彼はソースを解析してN80をPC-9801上に移植してしまったのだ!勿論、互換機とのハードの仕様の違いにより実装できない機能や仕様変更もあったのだが、確かにPC-9801でN80が動作している。これには正直驚いた、こんな短期間によくぞそこまでで・・・
改良も重ねられ、動作するソフトも増えて安定してきたので、次のステップに取り掛かることにする。
簡易グラフィックス表示ができるとはいえ、160×100という低解像度のPC-8001では、やはりゲームには無理があった。そこでHAL研究所からPCG-8100というプログラマブル・キャラクタ・ジェネレーターが販売されていた。これはROMのフォントパターンをユーザ定義のパターンに置き換えることを可能にするハードウェアだ。文字単位でしかキャラクター移動ができないが、やはり精巧なドットのキャラクタには魅力がある。
本体の蓋を開け、フォントのROMを引っこ抜き、そこにケーブルでPCG本体と接続するという、今の常識から考えると恐ろしい設置方法だったが、結構メジャーな機械で、これに対応したゲームも数々発表されていた。また、PCG機能だけでなく、Beep音も周波数を自由に設定できる独立したスピーカーが付いているので、ゲーマーにはたまらない装置だった。
VGAのユーザ定義フォントを動的に変更することで、PCGのエミュレートを行うことにした。
通常の文字表示でも、PC-8001フォントや簡易グラフィックスフォントでは同じ方法で実現されているので若干の変更で実装できた。手動でPCGのON/OFFを切り替える([F11]キーがトグルスイッチになっている)のが実用面で手間だが、まぁ仕方がない。
PCGサウンドの周波数は、内蔵されているi8253のカウンター値で設定するようになっているのだが、これは互換機のBeepでも同様だ。後は4MHz CLKを互換機の1.11938MHzに補正してしてやるだけで済むので楽だった。
それよりも、実機では独立しているPCGサウンドを、一つしかないPCスピーカーで共有して出して音は大丈夫なのかな?という懸念が先立った。Beep音>PCGサウンドという優先順位を付けて、交互に音を鳴らすようにして実装してみる・・・これも割とうまく鳴っているようなので一安心。
そして芸夢狂人氏のLUNA CITY SOS!!がPCGモードで動き出したのだった。
かなりのゲームを吸い出し、コレクションも増えていったのだが、まだ完全とは言えなかった。
いわゆる、オートスタート型のゲームは従来の方法ではうまく吸い出せないか、もしくは手動でバイナリを変更して転送する手間がかかるのだ。そこで、メモリイメージ(N80ファイル)以外にゲームをエミュレータに持っていく手段を考えることにした。そうして考えたのが、カセットテープの内容をそのままファイル(CMTファイル)に落とし、N80でcloadやモニタのLコマンドで読み込ませる方法だ。これならオートスタートのゲームでも問題なく実行できるし、何よりも純なデータとしてゲームを保存することができる(始めからこうすればよかったのかもしれないけど・・・)。
作業には実機側のマシンとしてRS-232Cの付いたPC-8801をN-MODEで使うことにした。それに空いているテキストRAMをバッファとして使うことも可能だ。
後はテープのフォーマットを調べる必要があった...
こんな時に役立つのは、結局当時に出版された解析本の類だった。
幸いにも、私自身が所有していたものや、友人から譲り受けたもの等で、かなり内部の情報とかも得られた。ほとんどROM解読に近い内容なのだが、おかげでカセットテープのデータ形式もマシン語、BASICともに知ることができた。
早速、PC-8801用に独自のテープリードプログラムを書き、ゲームのプログラムをそのまま吸い出す作業に取り掛かる。すっかり忘れていたBASICの文法やマシン語ルーチンの呼び出しも、先の資料に助けられ何とか仕上げることができた。
後は、N80にテープ読み出し機能(シリアルデバイス)を実装するだけだ...
PC-8001のテープ読み込みは、シリアルによるポーリング方式で行われている。
N80への実装は、シリアルの受信データ用のI/Oポートにリードに行ったときに、単純にカセットイメージファイル(CMTファイル)のデータを1バイトずつ渡してやればいいだろうと思ったのだが甘かった...
どうしても読み取りにデータの欠損が発生してしまうのだ。これは困ったとROMのカセット読み込みルーチン部分を調べてみると、シリアルチップ(i8251)をリセットすると直後に受信バッファを空にする為(だと思うけど)にリードさせていることが判明。そこでリセットをかけられたら直後のリードに対してはダミーのデータを渡すことで対処にした。
これでcloadやLコマンドによるテープの読み込みは成功したのだが・・・この仕様では独自にROMルーチンを使わずに読みに行くプログラムでは不具合が出かねないのだ。まぁそんなゲームはまだお目にかかってないので、そのままにしてある。
前述のように、当時の私の互換機は中古で買った486SX-20という貧弱なものだった。いくらプアなマシンでも快適に走るMS-DOS上とはいえ、これはきつかった。そこで、N80のプログラムの大半はアセンブラで記述されている。決して腕のいいプログラマーでもない私が取れる唯一の手段なのだ。その甲斐あってかエミュレーションの速度もSX-20で実機と同等くらいになっていた。
ところが、N80で遊んでいた友人からクレームが来た、
「スクランブルの速度なんとかなんないの? ゲームにならないよ・・・」
はて? 結構、カリカリにコーディングしてるんだけどなぁ、とよくよく話を聞いてみると486DX2-66の彼のマシンでは速すぎて遊べないってことだった・・・要するにウェイトを入れて速度を落とせるようにしろと。当時のDX2-66は9万円もしたのだ、到底、私に手が出せるわけもなかった。
この話の教訓は、「開発者にはプアなマシンを与えておけ」だ
私は細かいところまで凝ったことをするのが面倒な人間だ。不精者と言ってしまえばそれまでなのだが...
DOS版のN80では、実行中に[F9]キーを押すことでN80イメージファイルやCMTファイルを選択する画面に移行するわけだが、最初に作った画面はただ、ズラズラとディレクトリ内のファイル一覧が表示されるという身内で酷評を受けた使いにくいものだった
しかし、実用上は問題ないので私自身はこれでイイかと思っていたのだが、やっぱり許してもらえなかった・・・。泣く泣く現在のブルーのバックに、簡単な操作メニューを表示しながらのファイル選択操作画面へと改善したのだが、それでも私の汚名は拭えそうにもなかった・・・
1994年、こうして改良と機能追加を繰り返し、DOS版のN80は一通りの実装を行い、当初の目的であったカセットテープの復活と活用も達成された。これにてN80の完成とすることにした。しかし、N80の性質上、このプログラムは仲間内だけで遊ばれ、外部に公開されることはなかった。
1996年頃だっただろうか、友人がHPを立ち上げることとなり、そこでネタの補充にN80を公開してみては?という打診があった。
当時、私が加入していたプロバイダはHP開設は別料金だったので私自身はHPを持っていなかった。それに、N80は物がモノだけに元来、公開するつもりはなく身内で楽しんでいただけだったのだが、せっかくだから公開してみるのも悪くないと思った。ROMファイルを添付しなければ著作権的にも大丈夫だろうし。
公開版として本体にも若干の手直しをし、バラバラだったツール群やそのソースをまとめ、更にそれらの使用方法や解説などのドキュメント書きも行った。なかなかうまい文書が書けなくて、当時ダウンロードして頂いた方々には、何かと不備な点も多く、わかりにくかったと思われ申し訳ないのだが、何か反響でもあるのかな・・・?と楽しみにしつつ公開することになった。
丁度この頃、もうひとつ別のプロジェクトが進行していた。N80の開発もひと段落し、この資産を利用してPC-8801(無印)を作ろうと思い立ったのだ。PC-8801はPC-8001の上位互換機でPC-8001の資産もそのまま使えたこともあって、これまたベストセラーとなり、その後に数多くの派生シリーズも生み出されたマシンだ。
ハード的にも、PC-8001のI/Oポートなどを踏襲し上位設計されていたので、N80のコードを拡張するという形で実装出来そうだった。ただ、VGAのテキストモード(CGA)のみを利用していたN80とは異なり、PC-8801はバンク切り替えによる本物のグラフィック機能を搭載したマシンだった。VGAの制限上、テキストモード(CGA)とグラフィックモード(VGA)を同時に利用することはできなかったので、VGAの4枚あるVRAMのうち、3枚をPC-8801のVRAMにそのまま割り当て、残り1枚でテキストを実装するようにした。従って、N88ではテキストはモノクロでしか表示できないという制限が付いたが、テキストとグラフィックスの重ね合わせなど全てハード任せにし、非力なDOSマシンでも実機と同等の速度で動作させることが出来た。
その他にも、PC-8801では割り込みを利用していたり、複雑なメモリのバンク切り替えを行っていたのでメモリアクセスやZ80機能の強化を行う必要があったが、比較的短期間でN88は完成した。
何と言っても、動作させたかったのは森田氏のアルフォスだった。PC-8801mk2 SRが登場するまで、PC-8801のグラフィックスの重さには定評があった。そんな状況を少しでも改善しようとDMA転送を止める等、涙ぐましい努力が行われていた。そんな初代PC-8801でもアルフォスはサクサク動いたのだ。
アルフォスはN88上でも見事に動作してくれた。オープニングのBGMも軽快に鳴り、縦スクロールの画面も滑らかに動作していた。
しかし、時代はもうDOSからWindwsへと変わりつつあったたのと、他にもPC-8801エミュレータが登場するようになり、初代PC-8801の機能だけをエミュレートするN88は、これ以上発展することなくDOS版のみで終了した。
公開されたN80は一部で好評を得たのか、たくさんのメールを頂いたり、雑誌に掲載されたりした。やはり、あの時代にパソコン少年だった方々には同じ思いがあったようだ。あれも動きました!これも動きました!という報告のお便りを頂くと、思い切って公開してよかったなと思えた。また、あの月刊ASCII誌から、掲載の問合せが来た時には最初は冗談か?と思えた。掲載されたASCII誌やその他の雑誌は今でも大切に保存してある。
そんな反響のお便りの中で、Windows版も是非作って欲しいという要望をたくさん頂いた。ちょうど前年にWindows95がお祭り騒ぎと共に発売されたこともあり、時代はもう完全にDOSからWindows時代へと移行し始めていた。32bit時代の幕開けだ、もうFAR/NEAR CALLなんかで悩まされることもない広大でフラットな空間が待っている。そこで、Windows版を作ろうと決意することに。
既出のように、N80のソースの大半はアセンブラで書かれている。これが問題だった・・・
DOS版のプログラムであるから当然アセンブラも16bitコードとして書かれているのだが、これを32bit化するのに戸惑った。そもそも、32bitのオブジェクトファイルなんて吐き出すことができるんだろうか・・・?Win32プログラミングでアセンブラを使う機会など、VxDやデバドラ等の特殊なものを作らない限り一般的にはないだろうし・・・
かと言って、いちからC/C++やインラインアセンブラで書き直すのも面倒だ。できれば、そのままに近いソースコードを流用したい。そこでオプションスイッチとか見ているとCOFF形式とかそれっぽいのがあった。ものは試しで簡単なアセンブラ外部関数を書いてCから呼び出してみると、見事32bitコードでリンクされるではないか!見通しは明るそうだ。持ってる知識もたかが知れてるだけに、32bitで気楽にアセンブラが使えるという事実には結構感動してしまった。
初めてのプロテクトモードに、リアルモードとのアドレッシングの違いに戸惑いながらも順調にアセンブラソースのコンバートは進んでいた。
基本的には同じプロセッサーなのだから当然と言えば当然なのだが、なかなか勉強にもなった(役に立つかどうかは別として・・・)やはり、フラットモデルって楽だ。Z80部分はなんとかなるとしても、表示や入力といったWin32部分は未知の世界なのには変わりない。
基本的にハードウェアを直接叩くこともできないし、表示も自前で行わなければならないし、山のようにあるAPIから必要とするAPIを見つけるのには骨が折れる作業だった。慣れるまではAPI探しと習得だけに時間を取られた。
まだDirectXがまともに使える環境になかったので、WinGを使うことにした。GPUは貧弱で、ましてや直接アクセスする手立てのない状態だっただけに、ハードウェアの助けなしでのグラフィック描画はとにかく重かった。何とかWinGで動作するように作ってはみたものの、音も出すことも出来ず、とにかく重たくて使い物にならなかった。
一念発起して、DirectXに挑戦することにした。高速性が求められるゲームだけは、Windowsによるゲームは懐疑的でまだまだDOS版が多かったのだが、そんな疑念を払拭するためのマイクロソフトの解答がVRAMやSoundリソースに直結されたDirectX機能だった。Win32版のN80は、WinGによって既に骨組みは出来上がっていたので、描画周りをDirectX化するだけでよかった。Beepの再現はしばらくは直接I/Oポートを叩いていた。
試行錯誤してDirectX版はどうにか動作できる状態にまではなった。この頃には、私のマシンもそれなりに強化されていたにもかかわらず、Z80のエミュレーションとフルグラフィックによる画面描画は、この当時のマシンには荷が重かった。マルティメディア対応と謳われたMMX搭載のPentium用にMMX命令を組み入れたりしても結果は芳しくなかった。
実際、公開されたDirectX版N80には、チューニング希望の励ましが多かった。
この時期から、個人的に忙しくなったこともあって、N80の開発も滞りつつあった。当初の目的は達成されていた事もあって、多少、心残りではあったが事実上、開発は中断された。
後に気まぐれから再開され、残りの宿題が解決されたのは、この10年以上後のことだった。
Windows版の作成もひと段落ついて、N80は他機種に移植されることに。理由は単純で、私は所有したPCで必ず何か一本プログラムを作成する事にしていたからだ。根っからの貧乏性なのか、高価なマシンを手に入れてプログラムの一本でも書いてやらないと申し訳ない気がして、、、まぁ、散財への免罪符を自分に与えるというかw そんな時のお題として"N80"を選ぶことが多かった。
2005年製のZaurusを所有している。標準のOSからFecoraCore 10に換装したり、kernelを自分でビルドしたりカスタマイズしていたのだが、プログラムだけは書いていなかった。かつて、組み込みの仕事をしていた事もあり、ARMなら何とかなるかな?と始めたのだが、PXA270でどこまで出来るのかも気になった。
問題はZ80部分で、これは既出の通りx86向けのアセンブラで書いていた。ここに来て、ようやく重い腰を上げてZ80部分をC言語で書き換える事にした。試行錯誤して何とかC言語化し、描画部分にiWMMXt命令を使ったりして移植が完了。基本的にはLinux(UNIX)のプログラミングなので、そんなに手こずることはなかった。速度もそこそこちゃんと出て驚いた。
元々がApple2スタートなパソコン人生だったので、Apple信者とまでは言わないが、Apple製品は好きである。Macintosh時代にはMac plusを並行輸入で購入したり(正規品の半額くらいで買えた)もしていた。東レ、キャノン販売、日本法人と代理店の変遷もあったが、初期のMacはとても高価だった。Inside MacintoshというApple謹製の書籍を片手にThink Cでプログラムを書いたりもした。この時代のMacはMC68000系だったので扱いやすかった。未定義命令のA-Trapを使ったシステムコールやQuickDraw、GrafPortといった考え方は面白かった(同じ68kでもSHARPのX68kではF-Trapを使っていた)。その後、紆余曲折の上、復帰を果たしたJobsによってNeXTSTEPの流れをくむOS Xがリリースされ、CPUもモトローラ、PowerPC、Intelへと変遷した。
既にZ80部分はC言語になっていたので、問題はObjective-Cだった。C言語三兄弟の中でもなかなかの異端児であり、C/C++とは違った趣がある。お世辞にも人間からの可読性が良い書式とは言えないし、Lispのような括弧地獄には閉口した。更にInterfaceBuilderにも手を焼いた。全ては慣れの問題ではあるが、伝統的にAppleのIDEが使いやすかった試はない。
ここでOpenGLやSoundDeviceの使い方を覚えたのは後に役立つことに、、、いずれにせよ、何とかmacOSでも動作するようにはなった。
Xcodeの7からAppleへの年貢を納めていなくても実機によるデバッグが可能になった。そこで、iOSに移植してみることに。macOS用は作成していたので、Cocoa的な課題は既にある程度クリアされていた。折角なので、Swift2も使うことにして、Objective-C、Cの混合プロジェクトにしたのだが、正直、Swiftの使い勝手の悪さに閉口した。これ、本当に使いやすいですか?
Swift3で言語仕様がちょいちょい変更になり、iOSのアップデートが行われる度に何かしらビルドが通らなくなる、、、ここまでブレブレの言語も珍しいんじゃないだろうか。JavaやC#も出た直後から使っていたが、さすがにここまで酷くなかった。予約語を変更するなんて掟破り過ぎるw
我が家のサーバ省電化計画の為に購入したのだが、結局Atom PCに取って代わられ余っていたのでRetroPieを入れていた。折角なのでZaurus用のソースを改造してSDL2化するとあっさり動作した。さすが、UNIX系の枯れた技術。C言語で書いておけさえすれば永遠に動くんじゃないかと思えてしまう。因みにWindwos10 IoTも動いた、、、こんな5,000円程のワンボードでいろんな事が出来てしまうのが凄い。
1979年の販売から40周年記念としてPasocomMiniという形でPC-8001は復活していた(しかも作ったのはあのHAL研)。精巧に作られたミニチュアPC-8001ケースにラズパイを搭載し専用のエミュレータで動く代物だ。しかもちゃっかりPCG-8100のミニチュアまで別パーツとして用意されていた。
そんな中、ふとしたきっかけでPCGには後期モデルというものが存在し、3音発声出来るという事実を知った。確かにi8253には3chあるので構造的には3音出てもおかしくはなかったのだが、初期モデルしか知らなかった私には40年越しの衝撃だった。さすがに3ch対応の当時のゲームなど持っていなかったが、N80にも実装することにした。
ついでと言っては何だが、N80にWindowモードを実装して全画面と切り替えられるようにした。何を今更という感じではあるが、Windows(DirectX)版を作り始めた当時はマシンが非力だったこともあり、8bitパレットの256色モードで画面を描画させ少しでも負荷を減らしていたのだ。それには画面を強制的に8bitパレットモードに設定する必要があったのだが、これは全画面モードでしか出来なかった。その名残でずっとN80は全画面モードのみでしか動作しなかった。流石に、今時のマシンパワーなら普通に32bit色で画面を作成してもサクサク動くので直す事にした。
13歳で初めてパソコンに触れて以来、パソコンは今日も進化し続けています。黎明期からずっと、その進化をリアルタイムで見て、体験できたことはとても幸運だと思っています。CPUは8bitから16bitを経て32bit、更には64bitで動作するようになりました。
最初は虫かごでも飼えるトカゲ程度だったパソコンが、今では専門の飼育係でないと手に負えない恐竜になっていまいました。エンドユーザーが直接チップを叩くなんてことは、もう無いでしょう。
実を言うと、私が最初に所有したマシンはMZ-80K2でした。その後、Apple][ j-plusへとステップアップしました。今にして思えば、決して裕福でもない一般サラリーマン家庭だったのに、よくこんな高価なものを与えてくれたものだと両親には感謝しています(その甲斐あってか、何十年も経った今でもパソコンで何とか生計を立てています)。
その後、初代のPC-8801を所有するまで、友人のPC-8001でよく遊ばせて貰っていました。時にはAppleとしばらく交換して本体ごと借りたものです。80年代前半、雑誌に掲載される記事の多くは国産マシンに関するものが多く、どうしてもPC-8001/PC-8801に偏りがちでした。一方、Appleについては余りありませんでした。掲載されるゲームも同様で、ダンプを打ち込んで遊べるのは国産マシン用がほとんどでした。
Appleはモニタに簡易アセンブラが組み込まれており、マシン語を手軽に学ぶことが出来ました。6502の本を買って、少しずつ試しては躓きを繰り返し、楽しみながら学んでいったように思います。地元のラジオ店が東レの代理店をやていて、そこで購入したのですが、度々、Appleの勉強会のようなものが開かれていました。講師役の人がPascalを教えたり、周辺機器のデモをしたり、周りは大人だらけで私のような10代の若造は唯一人でした。それだけ、Appleはある程度余裕のある大人しか買えないものだったんですね、、、ホント、贅沢させて頂きました。
かなり昔の話なので、話が前後したり、記憶が曖昧になっている点もありますが、こんな感じでN80は生み出されました。