非 Windows 環境用 PC-6001 エミュレータ
PC-6001エミュレータといえば Windows 用の PC-6001V および PC-6001VW が有名ですが、 PC6001V をベースに Linux等へ移植したものとして eighttails さん による PC-6001VX が存在します。
README に「PC6001VXの末尾のXはクロスプラットフォームのXです」とあるとおり、Linux移植版であるにもかかわらずあえて Windows 版バイナリもリリースされているところにも、「移植性」に対するこだわりが感じられます。
もともと Windows (MSYS2) でも Linux でも同じソースツリーでビルドできるくらいなので、 pkgsrc の枠組みを使えば NetBSD で動かすのもそんなに難しくはないだろうな、とは思っていました。
PC6001VX を pkgsrc に入れるhttps://t.co/9IoK0jy7Iu
— Izumi Tsutsui (@tsutsuii) 2016年5月19日
という課題は無いでもない
が、自分自身が Qt に縁がなくクロスプラットフォーム環境対応のビルド方法を知らなかったということと、 README に書かれているビルド方法の説明が
PC6001VX.proをQtCreatorで開いてビルドしてください。
IDEが嫌な人はQtCreatorの代わりにqmakeとqtライブラリを揃えればビルドできるでしょう。
という「わかる人向け」という感じだったこともあり、長いことほったらかしにしていました。
ここに来て「冬休みの課題」ということでいろいろやってみたところ、わりとあっさり動いたのでまとめてみました。
まとめ
WIP pkgsrc ファイル一式
とりあえずで github に投棄してあります。
Qt アプリのビルド
基本はこれだけっぽいです。
pkgsrc 記述
- 以下のパッケージを先に入れる (依存パッケージとして記述する)
x11/qt5-qtbase
x11/qt5-qtmultimedia
x11/qt5-qtx11extras
devel/SDL2
multimedia/ffmpeg3
- pkgsrc ビルド前の
do-configure
で qmake を実行 do-install
で手動でバイナリと README をインストール
(qmake で作られる Makefile にはmake install
のターゲット記載がないようなので)
パッチによる修正箇所
PC6001VX.pro
の記述について以下を修正
- 非Linux用の X11 関連ライブラリ記述を追加
- libavformat, libavcodec, libswscale の指定について ffmpeg3 付属のものを使用できるように
pkg-config
を使った記載に修正
以下は詳細というか作業メモ
依存パッケージ
README にある debian での説明では
apt-get install build-essential libx11-dev mesa-common-dev libsdl2-dev qtcreator qt5-default qtmultimedia5-dev libqt5x11extras5-dev libqt5multimedia5-plugins libavformat-dev libavcodec-dev libswscale-dev
を実行。
とありました。pkgsrc でどうすべきかを適当に考えると
- X11 は NetBSD だと標準で入るし pkgsrc でも良きに計らってくれるはず
- mesa もたぶん X11 とセット
- libsdl2 は
pkgsrc/devel/SDL2
- qtcreator は開発環境っぽいので無くてもいいはず?
- qt5 関連はとりあえず
pkgsrc/x11
の下に qt5-qtbase と qt5-qttools というのがあるからとりあえずそのへんを入れてみよう - libavformat, libavcodec, libswscale はそれっぽいパッケージがないけれど、同名のライブラリは ffmpeg3 の
PLIST
の中にある
という感じで、とりあえずそんな具合で Makefile その他のファイルを用意しました。
pkgsrc Makefile
pkgsrcをいじるのは「自分が使いたいアプリを楽にビルドしたい」という理由なので、 pkgsrc そのものを調べずに設定を書いては怒られるという感じなのですが、今回もとりあえず見よう見まねというか行きあたりばったり方式でした。
DISTNAME
ftp で配布ファイルを取得する時の名前なので、配布ファイルの PC6001VX_2.30.0_src.tar.gz
に基づいてそのまま記述
PKGNAME
pkgsrc的には [アプリ名]-[バージョン番号] というスキームが必要っぽいので適当に他のパッケージの Makefile を真似して文字列を置き換え
MASTER_SITES
ftp その他でバイナリを持ってくるためのURLとして使われるはずなので、ダウンロードページのソース tar.gz のリンクのファイル名を除いた部分を記載
do-configure
適当に既存パッケージの Makefile を "qmake" で grep して
「${WRKSRC}
ディレクトリに入って ${QTDIR}
の suffix を使って qmake を呼び出し」
で記述
do-install
事前にインストール必要な設定ファイルは特になく "PC6001VX" のバイナリを実行するだけで動くようだったので ${INSTALL_PROGRAM}
で /usr/pkg/bin
に入れるだけ
USE_TOOLS
PC6001VX.pro
の設定ファイルを見ると pkg-config
を呼んでいるようなのでそれを記載
USE_LANGUAGES
その他
上記以外は適当でもとりあえずビルドには困らないので後回し
とりあえずビルド
まずは pkgsrc 以前に「バイナリとしてビルドできるのか」「ビルドできたとしてまともに動くのか」という問題があるので、依存パッケージ(と思われるもの)を入れた後にいわゆる野良ビルドから始めました。これが昨日の深夜。
qmake を実行しても無言のままなので Makefile
が作られていることに気づかなかったとか、qt5-qttools の依存パッケージを含めたビルドにやたら時間がかかって待たされたとか、しょうもないハマりはありましたが、わかってしまえばわりとあっさりとビルドが始まりました。
ビルドにおける最初のエラーは
「<libavcodec/avcodec.h>
のヘッダが見つからない」
というものでした。先ほど書いたように libavcodec は ffmpeg3 に付属していて /usr/pkg/include/ffmpeg3
以下に入っているのですが、とりあえず pkgsrc 的作法の前にバイナリの動作確認のほうが先ということで Makefile に直接 -I/usr/pkg/include/ffmpeg3
の記載を足して誤魔化しました。
ヘッダだけではなくライブラリのリンクでも文句を言われるので、リンカの引数として適当に-L/usr/X11R7/lib -Wl,-rpath,/usr/X11R7/lib -L/usr/pkg/lib/ffmpeg3 -Wl,-rpath,/usr/pkg/lib/ffmpeg3
といった記述も先に足してやります。すると、わりとあっさりとリンクまで通りました。
できあがった PC6001VX のバイナリをおもむろに実行してみると
「~/.pc6001vx/rom
以下に ROM がない」
と怒られたもの、 ROMファイルをコピーしてやるとこれまたあっさりと Windows では見慣れているウインドウが出てきました。
おもむろに PC6001VX on NetBSD/i386 テスト中。起動するけどすぐ落ちるところまでは動いたので寝ます pic.twitter.com/PcoQFdT8vl
— Izumi Tsutsui (@tsutsuii) 2016年12月29日
ざっとデバッガで見てみると OpenGL 関連のライブラリから X11 ライブラリ内の関数の memcpy() で落ちていましたが、とりあえずわりと行けそうか? という感触でした。
pkgsrc 化
ffmpeg3 関連
事前野良ビルドでは Makefile 手編集で ffmpeg3 関連のパスの記載を追加しましたが、 pkgsrc ではそのあたりをちゃんと(?)する必要があります。
pkgsrc の ffmpeg3 で入る libavcodec とかを pkg-config で取るにはどうするのが正しいんだ……。定義は /usr/pkg/lib/ffmpeg3/pkgconfig 以下に入っているっぽいけど
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
pkgsrc/multimedia/ffmpeg3/buildlink3.mk の BUILDLINK_FNAME_TRANSFORM.ffmpeg3 とかが良きに計らってくれて pkgsrc ビルド中はそのままでも認識してくれるということなのかしらん
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
いろいろ知らなすぎて遠回りしましたが、 ffmpeg2 および ffmpeg3 等を共存させるために以下のような仕組みになっていると判断しました。
- ffmpeg のバージョンごとに別の場所にインストールする
- ビルドの際に、そのパッケージで選択されたバージョンを
BUILDLINK_FNAME_TRANSFORM.ffmpeg3
等の定義で選択し、ビルド作業ディレクトリの${WRKDIR}/.buildlink
の中にシンボリックリンクを作成する
問題の本質は PC6001VX 配布中の PC6001VX.pro
の中で libavcodec その他の定義に pkg-config
を使っていないこと なので、ここは pkgsrc の枠組みでパッチを当ててやることにします。
X11ライブラリ
Makefile
で ${INSTALL_DIRS}
等々を設定してバイナリを入れようとすると今度は X11 関連で怒られました。
ERROR: bin/PC6001VX: missing library: libGL.so.2
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
ERROR: bin/PC6001VX: missing library: libX11-xcb.so.1
うー。 qt5-qtbase/buildlink3.mk だけじゃだめ?
libavcodec と同様、 PC6001VX.pro
の X11 関連の定義にも pkg-config
が使われていない のでそこを修正してみたものの、なぜかエラーが消えません。というかリンク時にもそれっぽい定義が出てきません。
と、よく見ると上記の定義は「linux」の条件文っぽいところの内側だったので、その外側に else 節を足してそこに同様の定義で pkg-config
を使うようにすることで解決しました。
SIGSEGV問題
次に、できあがったバイナリを実行すると昨晩の野良ビルド同様、「起動して少し時間が経つと core を吐いて落ちる」という問題がありました。
落ちているのが OpenGL 関連だったので、とりあえず PC6001VX.pro
中の "NOOPENGL
" の定義を有効にしてやると落ちずに動くようだったので当初はそれでパッチを作成しました。これでとりあえず動くようになったというのが以下のツイートです。
PC6001VX (cross platform PC-6001 emulator) on NetBSD/i386 7.0.2 with WIP pkgsrc
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
動きました(゜∀。) pic.twitter.com/2r433lDLfk
ちなみに作者の eighttails さんにも早速捕捉されてしまいました(^^;)
おお、ついにBSDにP6VX来ましたなあ。 https://t.co/h2MZs6S5Np
— Tadahito Yao(八尾 唯仁) (@eighttails) 2016年12月30日
NOOPENGL
について改めて調べたところ、前項に書いた PC6001VX.pro
の X11 関連の定義の「linux以外」の部分で記載するところに「QT += x11extras
」を書き忘れていたのが原因ということがわかりました。
「QT += x11extras
」の記載を追加して、さらに pkgsrc/x11/qt5-qt5tools
では入らない pkgsrc/x11/qt5-qtx11extras
をインストールしてやることで NOOPENGL
を定義しなくても正常に動くバイナリが作成されるようになりました。
PC6001VX はいろいろ試した結果 NOOPENGL 無しというか OPENGLあり設定でも動いた。最初に試した時に qtx11extras がちゃんと有効になっていなかったからっぽい。
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
pkgsrc的整備
一応 pkgsrc の枠組みでも動くものができたので、後は細々と記載を整備して一応完了です。
- 依存バイナリの精査
→ qmake は qtbase にあって qttools は不要。 qtbase, qtmultimedia, qtx11extra のみでOK README.html
のインストール (man がないので)pkglint
実行と修正- パッチのコメント追加
とりあえずこのままコミットしてしまってもいいとは思うのですが、 pkgsrc は担当外なのもあって新規パッケージ追加にはそれなりに気合いが必要なのと、書いた当日にコミットすると速攻でミスを指摘されるという経験則があるので、しばらく置いてからなんとかします。
pkgsrc 化してみて
自分の慣れた環境で「思いついたらすぐにソースから修正していろいろ試せるようになった」というのは大きいですね。
PC6001VX で src/tape.h の DEFAULT_CMT_HZ をいじってストップビット7ビット相当設定にしたらあぴミクさんデモのテープ裏読みも動いた。これでYS2EDも動くはず。動的に可変にするのは大変そうだけど pic.twitter.com/OMAoT7bpWQ
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
音を出すところはサンプリングレートを1バイトあたりの時間で割って前のビットから音を割り当てて、ストップビット1ビットとデータ8ビットの9ビット分を割り当てた残りの時間をストップビットとみなして Hの音で埋めてる感じ。なので DEFAULT_CMT_HZ を変えるだけで何とかなる感
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
当然かもしれませんが、Tiny野郎さんのイース2デモもエンディングは動きました。
テープの P6 ファイルを実テープwav作成用の分割バージョンにしたら YS2ED デモも完走した。PC600V/VX だとテープを入れ替えずに複数回オープンした際に最初にしかピー音ヘッダを付けないのでそれで時間がズレるっぽい pic.twitter.com/up0kbwWz24
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
ただし、 PC-6001用互換BASIC だとイース2オープニングは何かしらおかしいようです。エミュレータの問題ではないと思いますが、これもせっかくなので調べてみたいところです。
※2017/2/17追記: 互換BASIC 0.6.1 の更新で動くようになりました
PC-6001用互換BASIC でイース2 OPデモを試してみたら
— Izumi Tsutsui (@tsutsuii) 2016年12月30日
・「見てみるとしようぞ」まではOK
・オープニング画面の「NOW LOADING」のXORで画面が崩れる?
・テープ裏読みスクロール開始直後にBGMが停止
という感じ pic.twitter.com/X993YFUE9c
テープのヘッダ音時間やストップビット長の設定については、タイニーあぴミクさんデモやテグザーエンディングデモの実行にも影響する(ロードして即VRAM転送、つまりロードにかかる実時間がそのまま描画時間になるので、それでBGMとタイミングを合わせている)ので、こちらもそのうちなんとかしたいですね……。