FUZIXをビルドしてみよう【0.4版】
TweetFUZIXというプロジェクトをご存じでしょうか。Linuxのバージョンが2.2〜2.4の時代にメンテナーとして有名だったAlan Cox氏による、主に8bitのパソコンで動かすUNIXライクな環境です。もちろんRaspberry PiみたいなGUI環境を想像したらガッカリするとは思いますが、それでもCP/Mとも違うもっと高度なOSの出現にはワクワクさせられます。
そもそもはDoug Braun氏によるUZI(Unix: Z80 Implementation)というプロジェクトが発端でした。明らかに無茶な試みなんですが惹かれるものがあったのでしょうね、Braun氏自身の手によるUZI280(当時の次世代Z80であるZ280用)の他にも、H. Bower氏によるUZI180(HD64180/Z80180用)や、MSX用に移植されたUZIX(本家/日本語)、さらにそれをシャープMZ-800に移植したuMZixと、なかなかの広がりを見せています。
そこに現れたのがAlan氏によるFUZIXです。名称に含まれるZの文字はZ80のZだったはずなのですが、対象を6502や6809・68000・ARMに広げるなどマルチプラットフォームという顔を持つようになりました。GitHubでの公開によりコントリビューターも増えてきて、さらにはCox氏の経歴を考えれば将来はすごいシステムに化けるのではなかろうかと淡い期待を抱かずにはいられません。
2014年秋の第一報以来私もずっと気になっていたのですが、ふとその気になって一通りビルドだけは試してみることにしました。2017年に参考にしたのは「Running Alan Cox’s Fuzix OS on a Z80 emulator」というブログ記事で、仮想環境で動かせるようCP/Mシミュレータを流用したものです。内容的にはさらに2年以上前のものとは言えビルド手順が通しで書かれていたことから、大変参考にさせてもらいました。
それから4年後、ふと気づくとFUZIXのバージョンが更新された影響でどうやらこのページが参考になりにくいぐらい変わってきているらしいことを知り、最新版にて改訂しました。その時は「FuzixBuildNotes」という記事を参考にさせていただきました。
そして今回、2023年8月に0.4というタグがリポジトリに打たれてバージョン0.5の開発に移行し、本家サイトでの配布バージョンが0.4に改訂されたのを受けて、改めてfixしているバージョン0.4のビルド手順をまとめることにしました。
なお、CPUやメモリ構成などの条件が合えば本家サイトにビルド済みイメージがありますので、ビルドではなく実際に動かす方を試したい方はそちらを検討されても良いかと思います。
対象
環境
Ubuntu20.04を使用しました。Windows環境でも不可能ではないと思いますが、Cygwinその他「ちょっと変わった環境」でトラブルになるのも面倒だったので、素直にLinuxにて試すことにしました。
ビルドにあたって以下のパッケージが必要です。
なおbyaccについては次の後処理をしておいてください。
>sudo apt install byacc
>sudo update-alternatives --set yacc /usr/bin/byacc
SDCCのインストール
FUZIXプロジェクトがZ80用にCソースをコンパイルする際に前提となっているSDCCを導入します。10年、あるいはもっと以前に使ってみた個人的な印象では、ループ変数の演算がちょっと複雑になるとコードが出力されなかったりあまり良い思い出がなかったりしたのですが、今はC99やC11も受け付けられるモダンなコンパイラに変貌しているようです。
FUZIXのドキュメントにはこれまでもSDCCについてバージョン依存の問題やパッチの有無などの注意点が書かれていたのですが、そのあたりを全てクリアした独自パッチ版をAlan氏自ら公開することで解決されることになりました。
以前は素直に最新版を使用していたのですが、Alan氏の3.9.1版でFUZIXのテストが行われているそうなので、こちらも合わせておきましょう。
>git clone https://github.com/EtchedPixels/sdcc280.git
>cd sdcc280
>./configure --prefix=/usr --disable-pic14-port --disable-pic16-port
>make
>sudo make install
PIC14やPIC16以外にdisableにしておくアーキテクチャがあってもいいとは思いますが…。
z80packのインストール
CP/Mシミュレータを含むz80packを導入します。
>wget http://www.autometer.de/unix4fun/z80pack/ftp/z80pack-1.37.tgz
>tar xzvf z80pack-1.37.tgz
>cd z80pack-1.37/cpmsim/srcsim
>make
>cd ../srctools
>make
>make install
カーネルのコンパイル
いよいよ本題のFUZIXのビルドです。GitHubのリポジトリからクローンして取得します。そのままでは開発途中のバージョン0.5になってしまうので、今回ビルドするバージョン0.4のタグを指定してチェックアウトします。
>git clone https://github.com/EtchedPixels/FUZIX.git
>cd FUZIX
>git checkout refs/tags/v0.4
ブランチを指定しないので文句を言われますが、ビルドするだけなので気にしなくてOKです。
コンパイルに先立って、Makefileのターゲットシステムの指定を書き換えます。
FUZIX/Makefile TARGET = rc2014
↓
TARGET = z80pack
これで準備は整いました。sudo付きでコンパイルすれば、多少時間はかかりますが自動的に処理されます。
>sudo make
そう、以前はそれぞれのディレクトリに潜ってmakeしていましたが、実はバージョン0.4からトップのMakefileで全てビルドできるようになっているのです。0.3時代の記憶のままムダに作業していたというわけだったのです…。
コンパイルが終わったら、引き続きディスクイメージの作成を行います。これもmakeを実行するのみです。
>sudo make diskimage
するとFUZIX/Image/z80packの下にいくつかファイルが作成されます。ファイル作成自体はユーザー権限で行えるものですが、makeの実行で一部特権が必要なのでsudo付きで実行します。
FUZIXを動かす!
いよいよFUZIXを起動させます。先ほど作成したディスクイメージを所定のディレクトリにコピーして、シミュレータを実行するのです。
>cp Images/z80pack/boot.dsk ../z80pack-1.37/cpmsim/disks/drivea.dsk
>cp Images/z80pack/hd-fuzix.dsk ../z80pack-1.37/cpmsim/disks/drivei.dsk
>cd ~/z80pack-1.37/cpmsim
>./cpmsim
先ほど作成したディスクイメージのうち、boot.dskがカーネルの入った起動ドライブでフロッピーディスクのイメージ、hd-fuzix.dskがルートファイルシステムの収められたハードディスクのイメージです。それぞれdrivea.dsk・drivei.dskという名前でコピーします。
起動するとこんな画面になります。
bootdevというプロンプトには0と入力します。するとinitが実行され、ログインプロンプトが出てきます。
"root"と入力すればログインできます。ルートのファイルシステムはマウントされていて、pathも通っていますのでちょっと使ってみたのがこちら。
終了するには、shutdownコマンドを実行(パラメータはありません)してhaltしたら、Ctrl-\を押します。強引にcpmsimのプロセスをkillしてしまったらFUZIXのディスクがクラッシュすることがあるので注意してください。
そろそろ察しが付いてきた頃かと思いますが、CP/Mシミュレータと言いつつ、CP/Mのファンクションコールを仮想的に実装するのではなく素のZ80マシンのシミュレータを動かしているだけなんですね。だからCP/Mではないシステムを起動させることができるわけで…やろうと思えばS-OSだって搭載可能なのでしょう。
しかしアレですね…CP/MシミュレータなのにRAMが480KBもあるんだ…ああ、CP/M3にも対応するシミュレータだからか…。
リポジトリの中身
以前のビルドでせっかく中に潜ってmakeしていたのですから、ちょっとばかりリポジトリの中身について解説を加えることにします(ひとはそれを負け惜しみと言う)。といっても詳細レベルまでやると時間がいくらあっても足りませんので、さらっと触れる程度なのですが。
カーネルに関するファイルがあります。フォルダにはplatform-xxxxなどというフォルダが並んでいます。この中にあるのが機種依存のソースや設定で、TARGETマクロにてそれを教えるわけです。KernelフォルダにはCPU-xxxなどというCPU固有のソースや設定が収められたフォルダがありますが、platform-xxxxにあるtarget.mkにて自動的に指定してくれます。
従って、ポーティングにあたっては新規にplatform-xxxxとかいうフォルダを作って、他の機種も参考にしながら機種依存情報を構築するのが主な作業ということになるでしょうか。
まだFUZIXではセルフコンパイルができませんので、アプリ開発のためにはクロス開発環境を整える必要があります。SDCCをUNIXライクな環境に合わせるためのラッパーとしてfccというものが用意されています。/opt/fcc以下にインストールされます。このfccでクロスコンパイル用のライブラリもコンパイルします。
FUZIX上で使用するコマンドやアプリが含まれます。UNIX系でよく見るコマンドやゲームなんかもあります。SmallCやBCPLなどセルフ開発ができそうなものもありますが…バージョン0.5ではCコンパイラも開発されつつあるので、乞うご期待。
FUZIXのディスクイメージ(ルートファイルシステム)を作成するプログラムが含まれます。
イメージ作成にはbuild-filesystem-ngというスクリプトが使われます。-hオプションでヘルプメッセージを出力してみたところがこちら。
>cd filesystem-src
>./build-filesystem-ng -h
build-filesystem-ng [options]
Options:
-h print help and exit
-v enable more verbose output during execution
-p PKG enable package named PKG
-x swizzle disk image (for big-endian processors like 6809). Default: no swizzle.
-f FILENAME filename of disk image. Default: fuzix.dsk
-g N M disk geometry N=inode size, M=block size. Default: 256 65535
-y run fsck without interactive prompt
オプションがいろいろありますが、特に何も指定せず
>./build-filesystem-ng
と実行してもfuzix.dskというファイルが32MBの大きさで作られます(途中でfsckなどの実行を確認するプロンプトが出ます)。これらは-fと-gオプションで変更することができます。
オプションの-xはビッグエンディアン用イメージの作成を指示します。今回はZ80用ですから無指定とします。それよりも-pオプションの方が重要ですね。
-pオプションの説明は有効なパッケージ名を指定するとありますが、パッケージとは何かと言うと、ルートファイルシステムに入れるファイル群のことで、xxxxというパッケージはfuzix-xxxx.pkgという名前のファイルにその収納ルールが記述されるようになっています。いわゆるディストリビューションなどと同様のものですね。イメージ作成スクリプトのあるフォルダにも
というパッケージファイルがあります。また、Applicationsフォルダの下にある多数のソフトにもそれぞれのパッケージファイルがあって、どのファイルがどこにどういう属性で収められるか書かれています。build-file-system-ngスクリプトはそれぞれのパッケージファイルを参照しながら、ルートファイルシステムにインストールしていってくれます。
デフォルトのままだとほぼ全てのソフトが収められることもあり、かなり大きなディスク容量が必要になります。ハードディスクではなくフロッピーディスクにルートを入れたいと思っても溢れてしまうので、そういう場合のためにfuzix-mini.pkgという名前で最小構成のパッケージファイルが用意されています。例えば1.44MBフロッピーのサイズのイメージの場合、
>./build-filesystem-ng -g 64 2880 -p mini
とすれば最小構成のルートファイルシステムが作られるわけです。
さすがにfuzix-mini.pkgの設定では基本コマンドばかりで、アプリケーションが皆無ではあまりに使いづらいですからもうちょっと遊べる設定を作りたいところですね。パッケージファイルの中身やドキュメントを見て、オリジナルのパッケージを作ると良いと思います。
なお起動ディスクのイメージはユーティリティではなくddコマンドを駆使して作られます。以前のビルドで使用したスクリプトを参考用に残しておきます。当時の私はホームディレクトリにmakebootという名前で次のファイルを作りました。
makeboot #!/bin/bash
#
# try to make a fuzix boot floppy
# size is 77 * 26 * 128 = 256256 bytes
echo "Creating $1 as bootdisk"
dd if=/dev/zero of=$1 bs=1 count=256256
dd if=~/FUZIX/Kernel/fuzix.bin of=$1 bs=1 seek=193024 conv=notrunc
dd if=~/FUZIX/Kernel/platform-z80pack/bootblock.bin of=$1 bs=1 count=128 conv=notrunc
実行属性をつけるのを忘れずに。スクリプト内のパスはスクリプトを配置する場所によって適宜書き換えてください。次のように実行すると、指定した名前のイメージファイルが作成されます。
>cd
>./makeboot drivea.dsk
ちなみにdrivea.dskのサイズは、1行目のddコマンドのオプションからわかるように256256バイトあります。こっちは2Dフロッピーでも収まる大きさか…。
Makefileでディスクイメージを作る際の出力先フォルダです。この下にプラットフォーム(z80packとか)のフォルダが作られ、さらにその下にディスクイメージが並びます。
何かグラフィック環境が作られようとしていますが、今のところ何か成果物があるわけではないようです。
6809関連のファイルが集まっていますが、既に古く、使われていないようにも見えます。
FUZIXのドキュメントの集積場なのですが、全体的に古くなっているようにも見えます。他のドキュメントとの齟齬もありそうです。
ソフトウェアの開発
何も手をつけていませんのでほとんど当てずっぽうですが、FUZIX用アプリケーションは基本的にクロス開発で、SDCCではなくfccを用いることになります。/opt/fcc/binをPATHに加えておけばいいんでしょうね。
問題は出来上がったプログラムをFUZIXにて使えるようにする、具体的にはディスクイメージに書き込む方法です。そのためにucpというユーティリティが用意されていて、先ほどもディスクイメージを作る際スクリプトから呼び出されていました。使い方は
ucp ディスクイメージのファイル コマンド
で、コマンドの指定に空白が含まれる場合はダブルクォーテーションでくくり、複数の処理はセミコロンで区切ることで指定できます。またパイプでつなげば複数行にわたってコマンドを記述することができます(その場合はucpに対してコマンドを書かない)。どんなコマンドが使えるかはucpのソースを見て下さい。プログラムやデータをディスクイメージに書き込むにはbgetコマンドを使えばいいようです。
ポーティングについて
シミュレータで動かしてるだけじゃなくて、やはり扱い慣れたレトロPCで動かしたいと思いますよね。FUZIX/Kernelを見ると多くのCPUと多くのプラットフォームに対してポーティングされているらしいことがわかります。ここら辺をあちこち見比べながら移植の方針を考えることになるのでしょう。
例えばz80packとmsx1を比べてみても、同じZ80ではあってもメモリマップに差異があって、しかもZ80用のはリロケータブルではないそうなので、プログラムをバイナリの状態では融通できないことになります。あくまでソース互換ということにして、CPUが違うマシンに移植したのと同然であると割り切った方がいいのでしょうね。むしろこれは移植を「やりたいようにやる」ってことで構わないのだと考えることにしましょう。