
[2005.05.21]
PSのエミュレータを作りはじめました。
PSは、対応ソフトがPS2で遊べるという意味で、まだ現役のゲーム機と考えます。
よって、エミュレータのソースおよび実行ファイルを公開する予定はありません。
現役でなくなったら公開するかもしれません。
体感完成度(2005.07.17):
まずは BIOS データをとり出します。特別な機材は何も持っていないので、 これまでに製作・利用してきたいろんなモノをかき集め、ROM に配線を直結して読み出します。
実機上でいろいろ試してみたいことが出てくると思うので、 今回もROMエミュレータを作成することにしました。
しばらく自前でクロス開発環境の構築を試みましたが、 なかなかうまく行きません。 とりあえず今は bero氏の NOT YAROZEからリンクされている co氏の開発環境 (mipsgcc) で開発しています。
とりあえずシェルスクリプトを書いてますが、うまくいく気配がありません。 アーカイブのバージョンが少し古いのは、どこかのページで「この組み合わせがいい」 というようなことが書いてあったからです(一応最新も試みた)。
ついでに貴重な週末の6時間を無駄にしたガラクタスクリプトも掲載しておきます。 開発環境が windows 寄りなので、できれば windows で構築したいところです。 cygwin 系ではやはりうまくいかないんでしょうか...。 私はタコなので、まだ理解が甘いのかもしれません。 スクリプトには binutils の構築部分しかないですが、この段階ですでに コケるので、 gcc の構築部分は省略しました。
#!/bin/sh
TARGET=mips-ecoff
PREFIX=/home/Ki/xgcc/mips-ecoff
GCCWORK=/home/Ki/xgcc/gcctmp
BINUTILS_VERSION=2.13.2
GCC_VERSION=3.1.1
NEWLIB_VERSION=1.10.0
PATH=${PREFIX}/bin:$PATH
cd ${GCCWORK}
# ---------------
# build binutils
# ---------------
tar xzvf binutils-$BINUTILS_VERSION.tar.gz
mkdir build-binutils
cd build-binutils
../binutils-$BINUTILS_VERSION/configure --prefix=$PREFIX --target=$TARGET
make
sudo make install
巷では PSP のプログラミングがトレンドのようですが、 そんなことはおかまいナシ。 PS のプログラミングもなかなか興味深いです。 プロセッサの資料が集めにくいのがやや痛いですけど...
bero 氏のページにあったデモプログラムに少し手を加えて実行してみました。 左上の三角形はフラットシェーディング、残りと背景はグーローシェーディングで 描いてます。
実機とも比較してみました。PSCE の方が三角形が大きい気がしますね... あとはゲームを移植してみたり、PC2E を「とりあえず動かす」程度に PS に移植してみました。でもスピードは多分 1[fps] もでてないです。

テストプログラムを作ってみました。オールソフトで 32bpp で float 演算なので やや重いです。

[参考URL]
宇治社中改 (旧URL: http://www.cc.rim.or.jp/~devilman/)
現在は↓からログが読めます。
http://web.archive.org/web/20021128053856/http://www.cc.rim.or.jp/~devilman/
上のテストプログラムを固定少数点のみで動作するように変更し、さらに PS に移植してみました。 sin/cos を 256 分割しているので、動きがかなりガタガタになっていますが、 本質的な問題ではないのでとりあえず対応は後回しにします。
オール固定少数点版テストプログラムのソースと実行ファイル(Win32)をダウンロードするコンパイルは MinGW + DirectX5 の環境で行なえます。makefile のコメント部分を変更することで 浮動小数点版をビルドできます。
↓実行画面
上のプログラムを PS に移植しました。 とはいえ、もともと全てソフトでやっているので、とりあえず動かすだけなら PS 用にコンパイルし直すだけでほぼ完了します。現時点では GTE を利用した頂点計算や Ordering Table を利用した Z-sorting などは行なっていませんが、 これらを利用してゴリゴリやるのは PS プログラミングの醍醐味だと思うので 近いうちにやりたいです。 開発環境は CO 氏の mipsgcc + Rob Withey's PSX library + Jum Hig's update です。ライブラリはここから入手可能です。
↓ePSXe での実行画面

実行ファイルですが、とりあえずソースだけ公開します。
(src2html で HTML 化してみた版)
実行ファイルを作成したい場合は、上のリンクから開発環境を入手してください。
謝辞:整数版 sqrt に
「あゆしゃ法」による平方根算出プログラム
を利用させていただきました。
PS の Z-ソート法は普通の方法とは少し違うようです。 PS では頂点の座標が固定少数点表現なのを利用して、 視点座標系における Z 値を優先順位として Ordering Table (リスト) に登録する方式を採っています。この Ordering Table の長さは有限なので、 Z 値がこのテーブルの範囲内に収まるように調整する必要があります。 この調整は Z 値を何ビットか右シフトする(定数で割る)ことによって行なわれるようです。 このため GTE ではポリゴンの頂点の平均 Z 値を求めた後、これをさらに4で割る機能が 搭載されています。 つまりこれは4で割って Ordering Table に収まるように、あらかじめ Z の範囲と Ordering Table の長さをうまく決めてくれ、ということでしょうか。
ところで、Z-ソート法は Z の平均値を描画の優先順位とするので、 X, Y, Z 値が互いに近い図形同士の描画順位に誤差が出てきます。 これは、例えば複数のポリゴンから成るオブジェクトを互いに近い距離で描画するとき、 本当はオブジェクトAの方がオブジェクトBよりも手前にあるはずなのに、 Z 値の誤判定によりオブジェクトBを構成する一部のポリゴンがオブジェクトA よりも手前に描画されてしまうという結果になります。 こういう現象をみていると、Z-ソート法でポリゴン単位で描画順位を正確に 決定するのはあきらめた方がよさそうです。
上の問題の対策として、PS では「上書き禁止ピクセル」というのを指定することができます。 オブジェクトを描画するときに、「上書き禁止ピクセルには上書きしない」 という設定と、「描画するピクセルは『上書き禁止』にする」という2つの 指定が可能です。例えば上のオブジェクトAとオブジェクトBの例では、 まず手前のオブジェクトAを「上書き禁止」ピクセルで描画し、 オブジェクトBを「上書き禁止ピクセルには上書きしない」モードで描画すれば、 オブジェクトAが描かれていないところのみオブジェクトBが描画され、 結果的にオブジェクトBがオブジェクトAの背面にあるように見えます。
結局 PS に備わっている機能を使って、きちんと優先順位順に描画を行なうためには、 「上書き禁止」指定で手前にあるオブジェクトから順にポリゴン単位ではなく オブジェクト単位で描画する、ということになるでしょうか。