FUZIXをビルドしてみよう【0.4pre1版】

Tweet

 FUZIXというプロジェクトをご存じでしょうか。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と、なかなかの広がりを見せています。

 そこに現れたのがCox氏による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年以上前のものとは言えビルド手順が通しで書かれていたことから、大変参考にさせてもらいました。

 その後月日が流れ、ブログも閉じられ、FUZIXのバージョンも0.4が目前となり、どうやらこのページが参考になりにくいぐらい変わってきているらしいことを知って最新版にて改訂することにしました。例によって2021年5月現在の備忘録ということになります。なお今回は「FuzixBuildNotes」という記事を参考にさせていただきました。

 なお、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について

と書かれています。今回試した限りではz80pack向けにはパッチバージョンでなくてもよいようなので、素直に最新版をダウンロードしておきます。実際にはバージョンが3.6.0以降でないとコンパイルできなかったりもするようなので、現時点でパッチに意味があるのか怪しい気もします("The newest SDCC has the essential parts of the entry size patches merged."とあるので、改めてのパッチは不要なんでは…?)が、近い将来MZへのポーティングの際に改めて検討することにしましょう。

>tar xjvf sdcc-src-4.1.0.tar.bz2
>cd sdcc
>./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のリポジトリからクローンして取得します。

 まずはカーネルをコンパイルします。プラットフォームに対応したマクロを指定します。

>git clone https://github.com/EtchedPixels/FUZIX.git
>cd FUZIX/Kernel
>make TARGET=z80pack

 リポジトリのKernelフォルダを見てみると、platform-xxxxなどというフォルダが並んでいます。この中にあるのが機種依存のソースや設定で、TARGETマクロにてそれを教えるわけです。KernelフォルダにはCPU-xxxなどというCPU固有のソースや設定が収められたフォルダがありますが、platform-xxxxにあるtarget.mkにて自動的に指定してくれます。

 従って、ポーティングにあたっては新規にplatform-xxxxとかいうフォルダを作って、他の機種も参考にしながら機種依存情報を構築するのが主な作業ということになるでしょうか。

クロス開発用ツールのコンパイル

 まだ(ずっと?)FUZIXではセルフコンパイルができませんので、アプリ開発のためにはクロス開発環境を整える必要があります。SDCCをUNIXライクな環境に合わせるためのラッパーとしてfccというものが用意されており、これをコンパイルします。

>cd ../Library
>make
>sudo make USERCPU=z80 install

 これで/optとそれ以下のディレクトリが作成され、/opt/fcc/binと/opt/fcc/includeに必要なファイルが転送されます。

ライブラリのコンパイル

 今度はライブラリです。

>cd libs
>(Makefile.z80を編集)
>make -f Makefile.z80 USERCPU=z80
>sudo make -f Makefile.z80 USERCPU=z80 install

 ライブラリはfccでコンパイルする必要があるのですが、今さっきインストールしたばっかりでPATHにも追加してませんから、コンパイルに失敗するのは明白です。ということで手っ取り早くMakefileを変更することにします。

FUZIX/Library/libs/Makefile.z80
CC = fcc -m$(USERCPU)
 ↓
CC = ../tools/fcc -m$(USERCPU)

 これでクロス開発環境が整いました。

 これ本当はFUZIX/Libraryの下でmakeしたらlibsの下にも入って全部自動的にコンパイルするはずのものよね…Makefile.z80を指定してるのに別にUSERCPUも指定しないと通らないのは納得いかんよ…。

コマンド等のコンパイル

 FUZIX上で使用するコマンドやアプリをコンパイルします。Makefileにて先ほどコンパイルしたバイナリが指定されているのですが、一部漏れているのであらかじめ修正します。

>cd ../../Applications
(Makefileの編集)
>make USERCPU=z80
FUZIX/Application/cave/Makefile.z80
FUZIX/Application/cpm/Makefile.z80
FUZIX/Application/as09/Makefile.z80
FUZIX/Application/ld09/Makefile.z80
FUZIX/Application/netd/Makefile.z80
FUZIX/Application/SmallC/Makefile.z80
FUZIX/Application/ue/Makefile.z80
FUZIX/Application/plato/Makefile.z80
fcc
 ↓
../../Library/tools/fcc
FUZIX/Application/cpmfs/src/Makefile.z80
fcc
 ↓
../../../Library/tools/fcc

 マクロで定義しているところは一カ所で済みますが、たまにそうじゃないものもありますので編集漏れに注意。

ユーティリティのコンパイル

 ユーティリティをコンパイルします。後で起動ディスクを作る際に利用されるプログラムが含まれています。

>cd ../Standalone
>make

ルートファイルシステムイメージの作成

 コンパイルができたら、イメージ作成のスクリプトを走らせます。スクリプトの本体は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の設定では基本コマンドばかりで、アプリケーションが皆無ではあまりに使いづらいですからもうちょっと遊べる設定を作りたいところですね。パッケージファイルの中身やドキュメントを見て、オリジナルのパッケージを作ると良いと思います。

ブートイメージの作成

 次に起動ディスクのイメージを作るのですが、以前のバージョンと違いプロジェクトで提供されているプログラムで作ってくれたりしません。手動でもいいんですが、せっかくスクリプトを作ってくれてる人がいるので、ありがたく拝借しましょう。私はホームディレクトリに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フロッピーでも収まる大きさか…。

FUZIXを動かす!

 いよいよFUZIXを起動させます。先ほど作成したディスクイメージを所定のディレクトリにコピーして、シミュレータを実行するのです。

>cp drivea.dsk ./z80pack-1.37/cpmsim/disks
>cp ./FUZIX/Standalone/filesystem-src/fuzix.dsk ./z80pack-1.37/cpmsim/disks/drivei.dsk
>cd ~/z80pack-1.37/cpmsim
>./cpmsim

 先ほど作成したディスクイメージというのは、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にも対応するシミュレータだからか…。

ソフトウェアの開発

 何も手をつけていませんのでほとんど当てずっぽうですが、FUZIX用アプリケーションは基本的にクロス開発で、SDCCではなくfccを用いることになります。/opt/fcc/binをPATHに加えておけばいいんでしょうね。

 問題は出来上がったプログラムをFUZIXにて使えるようにする、具体的にはディスクイメージに書き込む方法です。そのためにucpというユーティリティが用意されていて、先ほどもディスクイメージを作る際スクリプトから呼び出されていました。使い方は

ucp ディスクイメージのファイル コマンド

で、コマンドの指定に空白が含まれる場合はダブルクォーテーションでくくり、複数の処理はセミコロンで区切ることで指定できます。またパイプでつなげば複数行にわたってコマンドを記述することができます(その場合はucpに対してコマンドを書かない)。どんなコマンドが使えるかはucpのソースを見て下さい。プログラムやデータをディスクイメージに書き込むにはbgetコマンドを使えばいいようです。

ポーティングについて

 シミュレータで動かしてるだけじゃなくて、やはり扱い慣れたレトロPCで動かしたいと思いますよね。FUZIX/Kernelを見ると多くのCPUと多くのプラットフォームに対してポーティングされているらしいことがわかります。ここら辺をあちこち見比べながら移植の方針を考えることになるのでしょう。

 例えばz80packとmsx1を比べてみても、同じZ80ではあってもメモリマップに差異があって、しかもZ80用のはリロケータブルではないそうなので、プログラムをバイナリの状態では融通できないことになります。あくまでソース互換ということにして、CPUが違うマシンに移植したのと同然であると割り切った方がいいのでしょうね。むしろこれは移植を「やりたいようにやる」ってことで構わないのだと考えることにしましょう。

戻る