角丸長方形はどこにでもある!

Folklore.org: Round Rects Are Everywhere! アンディ・ハーツフェルドの記事の翻訳。Macintosh開発当時の興味深い話です。

 

角丸長方形はどこにでもある!
著者:アンディ・ハーツフェルド
時期:1981年
登場人物:スティーブ・ジョブズビル・アトキンソン

http://www.folklore.org/images/Macintosh/roundrects.jpg

ビル・アトキンソンは多くの仕事を自宅でこなしていたが、何か重要なことがあれば即座にAppleに駆けつけ、それを理解できる人間に見せていた。今回彼は、ほんとにすごいアルゴリズムを思いつき、それを使った円弧の描画ルーチンを実装したので、テキサコタワーのマッキントッシュオフィスにやってきたのだった。

ビルは、当時まだLisaGrafと呼ばれていたMacintoshの描画ライブラリ、QuickDrawに円と円弧を描く新しいコードを追加した。円の数学が平方根を必要とするが、LisaとMacが使用していた68000CPUは浮動小数点演算を扱えなかったので、これは難しい問題だった。ビルは非常に賢いやりかたで、円の計算を足し算と引き算だけでできるものにしてしまった。68000は掛け算や割り算も使えたのだが、これらは遅かった。

ビルの工夫は、奇数の数列を足したものは常に自乗の数列になるということだった(1 + 3 = 4, 1 + 3 + 5 = 9, 1 + 3 + 5 + 7 = 16)。これを使用することでループ変数の脱出条件を簡単に求めることが出来、QuickDrawは円弧の描画を非常に素早く行うことが出来た。

これを使ったデモは、Lisaの画面をランダムなサイズの楕円が埋め尽くし、しかもはるかに想像をこえた速度だった。だが、スティーブ・ジョブズはこれになにか不満だったようだ。「なるほど、円と楕円はうまくいった。ところで角の丸まった長方形はどうだ?同じようにできるか?」

「いやそれは無理です。角丸長方形を実現するのは遥かに難しい。それにそんなもの必要ですか?」ビルはスティーブが円の高速描画を思ったほど評価せず、より多くを望んだことにムッと来ていたと思う。

スティーブは急に怒り出した。「角の丸まった長方形はどこにでもある! この部屋の中を見てみるといい!」実際そういう形はそこらじゅうに存在した。ホワイトボードもデスクも角丸長方形だった。次に彼は窓の外を指さした。「外を見てみろ!もっともっとあるだろう」彼はビルを連れ出して、角の丸まった長方形のものを見るたびに説得した。

最終的に角の丸い「駐車禁止標識」を示されたところでビルが折れた。「負けましたよ。どんなに困難でもやります」彼はその作業をやるために家に戻っていった。

何日か後の午後、ビルは満面の笑顔でテキサコタワーに戻ってきた。新しいデモは美しく角の丸まった長方形を猛烈な速度で描画していた。それはただの長方形を描くのと殆ど変わらなかった。このコードをLisaGrafに加える際、彼はこの角丸長方形を「RoundRects」と命名した。その後の何ヶ月かで角丸長方形は多くのユーザーインターフェース部品に取り入れられ、欠かせない要素になったのだった。

 初期のMacでDA用ウィンドウや、ボタンの描画に角丸長方形が多用されていたが、Windowsも、X11の各種ウィジェットも、角丸長方形をほとんど使用しない時代が長く続いた。輪郭に明色と暗色を使って立体的にするような発展はあったけど、ボタンは長い間四角いままだった。Windowsをバカにする系の典型的マカーだった僕がWindowsを使用するようになるのは、ボタンの角が丸くなったXPからである。それほど各丸長方形は重要だと思う。なんでWindows10でまたカクカクになるんだよおい(笑)

昔のMacintoshの仕組み3 意外と原始的なイベントドリブンとマルチタスク化

GUIな環境では基本的に上から下への手続き、バッチ処理的なプログラムではなく、マウスクリックやウィンドウの表示、サイズ変更といった各種イベントに従って動作を記述する「イベントドリブン」というプログラミング手法が必要になる。当然初期のMacもイベントドリブンなのだが、そのイベントの扱い方が今想像されるものとは若干異なっていた。

 

現代的なGUI OSにおいてイベント処理はどうするのが普通だろうか。各種イベントをOS側で監視して、アプリケーションが設定した適切なイベントハンドラを呼び出すのが普通の考え方だろう。それがオブジェクト指向っぽいし。

 

ところが昔のMacでは、OS側がやってくれるのはイベントをキューに追加するところまでである。アプリケーション側でGetNextEvent()という関数を呼んで、キューからイベントを取り出し、それがどんなイベントであるかイベントマスクで検査し、「あ、マウスクリックだね、じゃあこれ」「ウィンドウ隠れたのね、じゃあこれ」みたいにいちいち自分で分岐処理を書かなければいけなかった。なので一般的なアプリケーションは、初期化処理のあとで無限ループを書いて、その中でGetNextEvent()を呼び、必要な処理を行うということになる。こういう形だとスムーズなタスク切り替え出来ないんじゃないかと思うでしょう。ご安心下さい。Macはもともとシングルタスクでした。Macを起動すると、デスクトップを表示し、アイコンを操作するFinderというアプリケーションが自動的に起動するけど、これは単にディスクのブートブロックに書かれているので優先的に起動するだけの、ただのアプリケーション。Finderの上でアイコンをダブルクリックすると、FInderは終了し、ダブルクリックしたアプリケーションが起動する。アプリケーションはメモリもCPUも、すべての資源を独占して動作するわけで、マルチタスク的な気を使う部分はなかったわけである。Macの前のLisaがマルチタスクだったのに、Macがいろいろ捨ててたのはなんでか。それはやはりメモリが128KBと、とても少なかったことに起因するのだと思う。

 

Macのメモリが512KBになった頃 Switcherというアプリケーションがリリースされる。これはFInderを作ったアンディ・ハーツフェルドという天才プログラマが作ったもので、複数のアプリケーションを同時に立ち上げて、素早く切り替えられるようにしたものだ。それまでMacの全メモリをアプリケーションに割り当てていたのを、Switcherが適切なメモリを分割して割当てるのだが、もともとマルチタスクに対応していなかったMacで極力互換性の問題が生じないようにしたためだろう。画面には同時に立ちあがっているプログラムの一つだけが表示される仕組みだった。これはシングルタスクのMacの画面そのものである。メニューバーの右端にタスク切り替えボタンが表示され、これをクリックすると、メニューバーを含む画面全体が「ズバッ!」と横にスライドして次の画面が現れるのである。なお、これは正確にはマルチタスクとはいえない。複数のアプリケーションが同時にメモリ上に読み込まれて入るが、バックグランドに行っているアプリケーションは停止状態で待機することになる。しかし、Macの多くのアプリケーションはバックグラウンドで長時間計算し続けるようなたぐいのものではなく、ユーザーがインタラクティブに操作するものであったので、十分実用的だった。

 

Switcherは大変安定動作したうえ、増えたメモリを有効活用できたため、Appleから商品化されることになり、それなりに普及していた。その後アンディ・ハーツフェルドはさらに考えを進めたServantというソフトを作り上げる。

Switcherの場合、「Switcherというアプリケーションの設定画面」で同時起動するアプリケーションを登録する必要があった。だが、Servantは、Finderを置き換える本格的なGUIシェルであり、かつFinderとほとんど画面も操作も一緒でいわば拡張されたFinderであった。デスクトップから普通に次々アプリケーションを立ち上げ、後ろには他のアプリケーションのウィンドウがそのまま見えていて、クリックすれば前面にきて操作ができる。今のMacWindowsとほぼ同じである。ただし、やはり後ろに回ったアプリケーションはCPUタイムをもらえず。停止状態であった。まあ、OSそのものに時分割機能もないし、アプリケーションからタスクを他に回すAPIなんかもServantというアプリケーションでは追加しようがなかったし。しょうがない。

 

Servantではバックに回ったアプリケーションにイベントもいかないし、前面のウィンドウによって隠れたりした部分がどうなるか、白く抜けてしまってウィンドウ動かしたらみっともないことになるんじゃないかと思ったが、そういうことは起きず。前面ウィンドウの移動に従って隠れていた部分がきれいに復帰するのだ。おそらくアプリケーションの前後関係が変更されるタイミングでアプリケーション配下のウィンドウのビットマップを保存していたのだろうと思う。

 

Switcherでは各アプリケーションが使用するメモリ割り当てはSwitcherが勝手に行っていたが、Servantではユーザーがアプリケーションの情報ウィンドウで最大メモリサイズを設定することができるようになった。

 

他にもServantは、ファインダー上のアイコンのサイズを手軽に変更できたり、スクロールバー以外の部分をハンドツールでスクロールできるようにしたり、さらにはファイルの中に収められたリソースを覗くことができたりと、ずいぶんラジカルに機能を追加していた。ただ、このソフトはついに正式版になることはなく、β版として流通した後開発は中止される。

 

Servantがすっかり過去のものになった頃、ついにMacマルチタスク化されることになった。Finderが MultiFinderになったのだ。これが出た時驚いた。Servantのラジカルすぎる部分をそぎ落として、今までのFinderにマルチタスク機能を足したものにしか見えなかったからだ。起動アプリの一覧表示、「情報を見る」からのメモリ割り当てなど、MultiFinderとServantは驚くほど似ていた。ただし、こんどはバックグラウンドアプリにもタスクが回されるようになって、ほんとに一応マルチタスクになってはいたのだけど。当時のAppleの公式見解として、「Servantとは独立して開発された」というものがあった。逆にそう言わざるをえないほど似ていたという話だ。

「一応マルチタスクになった」と書いたのはわけがある。このときのマルチタスク化は、今のMacOSWindowsのような、プリエンプティブ・マルチタスクではなく、コオペラティブ・マルチタスクだった。プリエンプティブ・マルチタスクというのは、OSが強制的にアプリケーションのタスクを区切って次次タスクを切り替える方式だが、コオペラティブ・マルチタスクというのは、アプリケーションが「はい一旦スタジオにお返しします」とOSに制御を戻し、OSが次のアプリケーションに仕事を回すという手順が必要な方式だ。協調的マルチタスクとも言う。

さて、もともとシングルタスクだったMacのアプリケーションは、行儀よく協調的に書かれているわけではない。他のアプリケーションが同時に動くことなんかそもそも想定してすらいない。それなのにこの方式で動いたのはなぜか。

どんなMacアプリでもまず確実に、超頻繁に呼び出すAPIがある。GetNextEvent()だ。なので、GetNextEvent()を呼び出されたタイミングでOSが他のアプリに切り替えるようにしたのだ。これでスムーズにタスクスイッチングが可能になった。ただし、もともとGetNextEvent()は、「今最新のイベントを返して」っていうAPIであり、この呼び出しに時間がかかることは想定されていない。アプリケーションとしては即座に返事が帰ると思ってるAPIであまり長々よそ見をしてもらっては困る。なのでOSもこのAPIで呼ばれたときには、タスク切り替え一周したらできるだけ速やかに戻ってくるようにしていた。

ただ、イベント取得は実際には必ずしもすぐに来なくてもいいものだ。「キー入力が来るまで待ちたい」ときに「まだ?まだキー来ない?」となんども呼び出すのは効率が悪い。自分だけがMacを専有していたときはそれでもよかったのだが、複数のアプリが強調するなら、ここは効率を重視したい。

 

というわけで、MultiFInder導入と同時に、GetNextEvent()の上位版API。WaitNextEvent()が登場する。これはGetNextEvent()とほぼ同じだが、待ち時間の引数が追加されて指定した時間の間待つから帰ってこなくていいよ。というものだ。つまりあるアプリケーションが「100msの間もどってこなくていいよ」といえば他のタスクにその分CPUを割り当てることが可能になる。

 

なお、これもやはり待ち時間をどうするかなどめんどくさいところが多かったし、プリエンプティブ・マルチタスクMacOSXが導入されるとプリエンプティブなタスク切り替えとコオペラティブなそれが競合してしまってはなおさら無意味になる、結局昔のMacの互換APIであるCarbonは、Carbon Event Modelという、イベントハンドラをOSが適切に呼び出す形式のAPIを追加することになった。まあ、そんなすったもんだのあげくに互換性を保ちながらモダンになりかけてたCarbonもあっさり64bit非対応で廃止されちゃったんですけどね。

昔のMacintoshの仕組み2 リソースとファイルタイプ

一般的なコンピューターのファイルと言うものは、ファイル名で検索される単一データの塊である。「ファイル」の「中身」は当然一つであった。"readme.txt"というファイルはテキストファイルであり、その中身はユーザーに読んでもらうためのテキストであるのが当たり前と思うだろう。

 

ところがMacにおいてファイルと言うものは2つの「中身」からなっていた。あるファイル名で示されるファイルには2つの「中身」があった。それはデータフォークとリソースフォークである。データフォークは通常のデータであり、他のコンピューターでいう「ファイルの中身」である。一方リソースフォークには整理された任意の、様々な情報を格納できた。ファイルマネージャーがファイルのデータフォークを読み書きする。これは他のOSにおける基本的なファイルI/Oとだいたい同じで、オープンし、頭から読み書きし、あるいは任意のバイト数までシークし、クローズする。一方同じファイルをリソースマネージャーを通じてアクセスすると、4バイトのリソースタイプと、整数のリソースIDで管理されるデータの塊にアクセすることが出来た。リソースはバイト数での位置などを考慮することなく、様々なデータ、画像や文字の属性、アイコンなどといったものを名前で格納することができた。つまりリソースはもう一つのファイルシステムのように扱えたのだ。

 

アプリケーション・プログラムの実行コードはCODEリソースとして格納されていたし、アプリケーションや書類のアイコンはICONリソースだった。スプラッシュスクリーンに表示される画像などは「PICT」リソースとして格納されていた。

 

Macにおいてアプリケーションや書類のアイコンは、アプリケーションファイルのリソースフォークに収められていた。アプリケーションバイナリの収録されたフロッピーディスクMacに挿入すればマウントされているハードディスクなどの上にある「デスクトップファイル」もしくは「デスクトップデータベース」に「アプリケーションのアイコン」「そのアプリケーションで作成される書類のアイコン」「アプリケーションと書類の関係」がコピーされ、自動的に書類のアイコンも更新された。なのでファイルの関連付けを行うインストーラは不要で、アプリケーションファイルをハードディスクにコピーするだけでOKだったのだ。

昔のMacintoshにおいて、拡張子というものはなかった。書類の種類を示す情報はファイルのメタ情報である「ファイルタイプ」に収められていた。テキストファイルのファイルタイプは「TEXT」であり、アプリケーションファイルのファイルタイプは「APPL」と決められていた。デスクトップでアイコンをダブルクリックすると、ファインダーがそのファイルのタイプがなんであるかを調べ、「APPL」であれば実行ファイルとしてメモリに読み込み実行する。「TEXT」であれば、デスクトップデータベースを検索してテキストファイルを扱えるアプリケーションを探し、それを実行する。

 

このとき、テキストファイルを扱えるアプリケーションが複数あったらどうしたらいいのだろう。その場合、ファイルに付けられたもう一つのメタデータ「クリエイター」を調べる。「クリエイター」は、そのファイルを作成したアプリケーションのID情報である。すべてのアプリケーションは「クリエイター」をもち、それらは重なってはいけないものとされていた。たとえばPhotoshopのクリエイターコードは「8BIM」だった。なお、Photoshopが作成するPSDファイルのファイルタイプは「8BPS」である。クリエイターコードは、アプリケーションを開発したらAppleに登録する必要があった。ファイル保存時には、ファイルタイプと自分自身のクリエイターをメタデータに保存する。

 

なので、基本的にファイルをダブルクリックすれば、前回それを編集したアプリケーションが立ちあがって、それを開くことになっていた。

 

このような、複数の中身を持ち、ファイルタイプやクリエイターと言うメタデータを持つファイルはパソコン通信やインターネットでは扱いにくかった。Macにおいては当然保持すべき情報だが、他機種では無意味である。Mac拡張子を使わない文化だった(拡張子にあたる情報がファイルタイプだった)ため、ファイル名にいちいち「.txt」だの「.psd」だの付ける必要がなかった。ネットワークでファイルをやり取りする際にもメタデータやリソースフォークを保持するようにした。これがMacBinaryである。メタデータやリソースフォーク、データフォークをシリアル化して送受信する仕組みで、本来通信ソフトが勝手にエンコード、デコードすることを想定したものだった。つまりMacから送信時自動的にMacBinaryにエンコードされ、別のMacで受信する際Macファイルシステムに会うようにデコードされるはずだった。ところが、ただのJPEGGIFファイルみたいな汎用データにもメタデータがついてしまうため、これを他機種でダウンロードすると表示できないということになった。汎用の通信に出す場合MacBinaryエンコードせずに送信するなどの工夫が必要だったのだが、Mac初心者がよくわからないままMacBinaryデータをばらまき、他機種ユーザーに蛇蝎の如く嫌われることになったのだった。

パソコンがプログラミングなしでは何も出来なかった時代

MZ-80やPC-8001が登場してマイコンブームが巻き起こった1980年頃、市販の実用ソフトは皆無だった。当時パソコンに触れた少年たちは、そのほとんどがマイコン雑誌に掲載されたゲームなどのプログラムリストを打ち込み、実行して楽しんだ。

そして、なにしろプログラムのソースコードが雑誌に掲載されているのだから、それを改造して楽しんだりも当然できた。ソフトが売ってないんだから、自分でプログラム作るか、他人のプログラムを打ち込むしかなかったのだ。そういう意味で、あの時代のマイコンユーザーは、そのすべてがプログラマかその予備軍だったといえる。まあ、雑誌掲載プログラムをその雑誌がカセットテープに録音して通販してたりもしたので、当時でもソフトを買うという行動はあったのだけど、お金のない少年たちは、打ち込めばタダなソフトに金を払う習慣を形成するのに時間がかかったと思う。通販って当時的にはわりと敷居高かったし。

 

まあそういったわけで、パソコンというものはその出始めの時期には「プログラミングを楽しむ」機械だったわけだ。そもそも起動とともにプログラミング環境であるBASICが動いていたのだから、電源入れるたびに「さあ、今日はどんなプログラムを作りますか?」と言われているようなものである。

 

CP/MみたいなOSが一般にはあまり普及せず、BASICが基本ソフトとして受け入れられていたので、パソコンを使うこと=BASICを覚えることとされていたきらいもある。サラリーマンが電車の中でBASICの入門書を読んでたりしたわけだ。

 

そんなパソコン環境の中でBASICでゲームを作り、高速化を狙ってコンパイラアセンブラに手を出しという感じで、初期のパソコンプログラマは育ってった。

 

パソコンが、自分でプログラムを組むのではなく、遊びや仕事に必要なソフトを買ってきて動かすランチャーになったのはいつからだろう。ゲームのクリアに本気になれるRPGが出た時か、ビジカルクみたいなほんとに業務に使えるソフトが一般化した時か、それとも実質プログラム作成が不可能と言ってもいいほど切り詰めたMac128kが出た時か。それはそれで正しい進化である。パソコンが「なんだかすごいなんでもできる夢のマシン」という曖昧さを捨てて、「実用的な道具」になったわけだから。ただ、BASICの点滅するプロンプトにわくわくしながら AUTOと打ち込んでアイデアを実現しようとしてた何十年前の少年たちは、あの感動をいまの子どもたち、自分の息子や娘に味わってほしいと思い、ときにあまりにも時代遅れなプロダクトを生み出すのである。IchigoJamとか…

ichigojam.net

 

 

 

MSXが終わらないIF物小説を誰か書かないか

1990年に発表されたMSXturboRはひどく挑戦的で、しかしダメなマシンだった。CPUが衝撃的にすごくなったのに、VDPがMSX2+のまま。おかげで高速CPUにもウェイトが入りまくる有様。というかすでに90年という時期にはIBMPC互換機を除く独自アーキテクチャのパソコンは死滅に向かいつつあった。Macintoshでさえ、衰退しつつあり、21世紀を迎えて生き残れたのはスティーブ・ジョブズの復帰という奇跡がなければありえなかったかもしれない。

なので現実的問題としては、あの時点でなにをどうしようと時代遅れの8ビット規格を継承したMSXが生き残るすべはなかったろう。

 

とはいえ、MSXが好きだった人間としては、「あのときああだったら、こうだったら」という想像はついついしてしまうものである。せめて誰かフィクションでいいからMSX大勝利のお話を作ってくれないか。バブル時代を代表するホイチョイプロダクションがバブルへGO!!なんて映画でバブル崩壊を防ぐ歴史改変に挑むことが許される時代なのだから、MSXを復活させるストーリーだってありだろう。

 

たとえばそうだなあ。少年時代MSXに惚れ込んでプログラム書いたりハードウエアいじったりしてたエンジニアが、ある日突然タイムスリップして1988年、MSX2+発表のあたりに転移する。MSX2の頃はまだ夢があったが、マイナーチェンジっぽい2+はそろそろ暗雲が見えてきている。実際この規格の参加メーカーは三洋、松下、ソニーだけだった。かつて国内外の主要家電メーカー、三番手以下のコンピューターメーカーがこぞって採用したMSXがたったの三社からしか出ないというのは、恐れおののくべき非常事態である。でも当時のユーザーは「おお、スムーズな横スクロールできるようになったんだ」「自然画モードすげー、19000色って最強じゃん」と思って全然危機感を抱いていなかった。主人公はまずこの危機感をアスキー西和彦に訴えるわけだ。

 

西和彦も黙ってはいない、MSX2+は、型番からもわかるようにMSX2のマイナーバージョンアップだ。本命はMSX3。互換性を保ったまま16ビット化を果たし、グラフィックも大幅強化される予定である。しかし主人公は実際の歴史を知っているのでそれを否定する。

「1990年にあなたはMSX3でなくMSXturboRを発表する。ヤマハの新VDPの開発が間に合わないのだ。結果的に採用するのは松下一社だけ。結果すみやかにMSX規格は終演を迎える。西さん、あなたはアスキーを首になり、2ちゃんねるで叩かれて1ch.tvを立ち上げるがトラブル続きで表舞台から姿を消す事になる」

「なんだねその2ちゃんねるというのは」

「ああ~まだないかー。てかインターネットも普及してないし、…あのですね、21世紀にはアスキー大変ですよ。雑誌は次々潰れて最終的に角川書店に買収されます」

「なんと!いやそうか、うちが先鞭切って進めてきたデジタル化の波か。第三の波ってやつだな、アルビン・トフラーの、知ってる?」

「ああ、はい、そういうやつです。てかアルビン・トフラーとか古いっすよ」

「えええ???。ま、まあいい。ならば半導体事業に手を出したの正解だったな」

「あ、アスキー半導体事業MSXturboRのCPU作った後あっさり潰れます」

「なんだってーーーー?!」

 

やばい。MSX復活プロットにつながらない…

 

日立のZ80互換強化CPU、HD64180がザイログに採用されてZ180になったりとかいう事実もあるわけで、そういう感じでR800が継続されてゆくゆくは32ビット、64ビット化を果たすとか、1990年にturboRを発表するの待って、1,2年後にヤマハのV9990を採用、互換モード用に東芝MSX Engine3というZ80と周辺チップ+V9958を統合したチップを作ってもらって、X68000に匹敵するMSX3を規格化してもらう。あと当時のマルチメディアに特化した将来構想を持ってた西和彦氏に、「ゲーム作るためにすげえスプライト機能必須ですよ、このままだとMSXを支えてるコナミも見放しますよ」と説得してVDPの進化をうながす。

 

こんな話を小説化とかしてくれたら、わりと僕とかすげえ読みたいんだけどみんなはどうかなあ。

MSX用クロス開発のすすめ(z88dk)

今の時代MSX用にプログラムを開発する際、実機もしくはエミュレータ上でアセンブラコンパイラを使うのは苦痛でしかない。コマンドラインのエディタ。K&R時代のコンパイラと付き合って、当時のままの重く、メモリも足りない環境で開発するのはあまりよい方法ではない。とはいえ、Windows上などでクロス開発するのは敷居が高いと思うだろう。いわゆる「マイコンクロス開発」と同様に、コンパイルしたバイナリを転送して、動かして、デバッグも大変でと、クロス開発ならではの苦労も想像できる。でもMSXエミュレータとホストOSの関係は実は意外と軽い。

 

openMSXというMSXエミュレータは、ホストOS上のディレクトリをフロッピーとしてマウントする機能をもっている。

f:id:juangotoh:20151029220047p:plain

 

これを使うとMSXエミュレータからWindows上のファイルがそのままMSX-DOSのファイルとして見え、実行することもできる。なのでそこにMSX用ソフトを出力するようにすればWindowsMSXの開発が行えるのだ。

 

で、MSX用に開発できるクロス開発環境を考える。さすがにかつてのMSX-DOS TOOLSで実現されてるほどにBASICと遜色ない環境を整えているものはない。だが、まあMSXにはBIOSとBDOSという、アセンブラからでも比較的容易に使える機能がてんこもりなので、とりあえず「動く」バイナリが出力できればなんとかなる。その上でいいなと思ったのがz88dkというC開発環境である。

 

z88dkはZ80を使用した様々なコンピューター用の実行ファイルを作成することを目的にした開発環境である。サンプルの豊富さなどからシンクレアZXスペクトラム用がもともとの用途なのだと思うが、TRS-80、コレコビジョン、CP/M、S-OS、シャープMZシリーズおよびX1、NEC PC6001シリーズ、セガSC-3000とマスターシステム、ソードM5なんかにも対応している。出力するプログラムも、カセットテープ用音声ファイルからディスクBASICでBLOADして動かすバイナリ、ロムカセット、DOS用などを切り替えられるという親切さだ。もちろんMSX向けにも出力できる。

安定版のインストーラも提供されているが、最後の安定版が出てから大きく改良されているのでNightlyビルド版をダウンロードした方がいい。プログラムのビルド方法なども変化しているし。

たとえばWindowsなら、

http://nightly.z88dk.org/z88dk-win32-latest.zip

をダウンロード、展開して、どこでも好きな場所に置く。cドライブ直下にz88dkフォルダを置いたとして説明すると、このあと環境変数をいくつか設定する。コントロールパネルの「システム」を開いて、「システムの詳細設定」から「環境変数」を開く

f:id:juangotoh:20151029222717p:plain

PATHの末尾に ;c:\z88dk\bin

を追加。

あとZ80_OZFILESという変数を作成して変数値を c:\z88dk\Lib

ZCCCFGという変数を作成して変数値を c:\z88dk\Lib\Config

としておく。これでOK。あとはopenMSXにマウントしたフォルダ上でターミナルを開き、ソースファイルをコンパイルして、そのままエミュ上で実行可能になる。

例えば

#include <stdio.h>

main()
{
printf("Hello World");
}

 これをtest.cとして保存し、ターミナルでコンパイルする

zcc +msx -subtype=msxdos test.c -o test.com

f:id:juangotoh:20151029234006p:plain

これをmsxエミュレータMSX-DOSから実行する

f:id:juangotoh:20151029223910p:plain

 

コンパイルオプションで '+msx'とつけることでMSX用になる。 -subtypeを指定しない場合、BASICからBLOADで読み込んで実行するバイナリになるようだ。-subtype=romというのもあって、ROMカセット形式のバイナリを作成できる。

 

なお、デフォルトではディスクI/Oをダミー関数に置き換えたndosライブラリがリンクされ、ファイルの読み書きができない。ゲームを作るなら構わないだろうが、普通にファイルの読み書きをするプログラムを書く場合はz88dk\lib\config\msx.cfgを編集して

CLIB      default -lmsx_clib -lndos

とある行を

CLIB      default -lmsx_clib

と書き換えるといい。-lndosオプションがダミーライブラリの指定になっているのでこれを削除すれば普通にファイルI/Oが使えるようになる。

 

ちなみにMSX-Cと違って、z88dkは32ビットのlong型も普通に使えるし、ほぼANSI-C準拠なのでわりと今時の感覚で使える。

 

なお、M80用のアセンブラをz88dkのz80asmで通るようにするには以下のようにする。

equによる定数は使えない。

FOO equ 0FF00H

みたいな指定は

DEFC FOO = 0FF00H

と書き換える。DEFCは32ビット定数の宣言。

マクロは使えないっぽいので展開して書き換える。

コードとデータのセクション設定は

SECTION code

SECTION data

などと書く。

DB DWなどの定数擬似命令はエラーになるようだ。

DEFB DEFWと書き換えればOK

 

V9990はMSX1だけじゃなくMSX2,2+との互換性もいろいろ欠けてるような気が

http://www.msxarchive.nl/pub/msx/docs/datasheets/v9990.pdf

 

これざっと読んでみると、V9990は8×8ドットのタイルを並べて画面を作るP1,P2モード(パターンモード)と、ビットマップで画面を作るB1~B6モード(ビットマップモード)があって、前者はタイルごとに32768色中16色、パレットが4個。ということは画面全体では64色使えるということかな?その画面上で16×16ドットのスプライトが125個同時表示、横方向に並べられるスプライトは16個。確かになかなかなんだけど、問題はビットマップモードではスプライトの代わりに「ハードウェアカーソル」が使用可能で、これは位置画面に二個だけ。サイズは32×32ドットだけど、単色だし。ほんとマウスカーソルみたいな用途専用みたい。

 

つまり、MSX2のSCREEN8で256色の背景にスプライト並べてゲームやることを考えて、それと同じモードを探すと、B1モードの256×212、8ビット/ピクセルが背景には同じ色数になるが、MSX2では32個使えるスプライトが、このモードではは二個しか使えない。

 

早い話、V9990はいままでのMSXシリーズが使ってたVDPと重なる部分が少ないのだ。これを搭載したMSX3が出たとしたら、いままでのプログラムのうち、グラフィックを使うものははほとんど動かないだろう。ちなみにV9978という型番だった時も、ほぼ同じようなスペックだった。

 

しかしこれがMSX3用だったというのは事実らしいので、MSX3という規格は従来のMSXシリーズと全くといっていいほど互換性を切り捨てた新規格か、またはV9990とV9958をダブルで載せて互換性をとるかどちらかだったと思われる。