#9きょうはどおしよ(2006-02/18)
■少し、雑談。メガドラのチラツキが重要なゲームって、FSKIP2に設定すると、ゲームになるのな。知らん
かった。FSKIP0は当然遊べるが、(その速度で動けば)。FSKIP1はチラツキが重要なゲームでは、
FSKIP2の方がずっと遊べる。管理人以外のエミュでもこの技は有効だから試してみてね。
パノラマコットンは、画面バグバグだがFSKIP2、44100で遊ぼう。チラツキは再現されるし。それ程極端に
がたつく訳でもない。ダライアスⅡとかデンジャラスシードとかもこの技は有効。
でも、バーニングフォースはゲームにならん。やっぱFSKIP0、5512の方が良い。
■昨日(厳密には今日)、ごちゃごちゃ。やったから、別にダイエットするのは、悪くないケド。
本質的でない事にも、気が付いちゃったしなぁ。
お魚さんの奴が、自前のは別として、標準のもリンクできてるのは謎だなあ。なんでだろ。
■今日は、今後の戦略を練る為に、ちと、/psp_mame04/src/psp/の下を見て過ごすか。
「video.c」:32ビット以外殺してあるから、PSPは32ビットカラーだな。このPSP以下のレンダーは、
詰まる所、(SYS1専用エミュの場合)16ビット→32ビット変換以外の、変換機能はすべて削除して
いい事になるな。
これMSDOSのソースとほぼ同じものだから、懐かしいな。管理人、昔持ってたNOTEPCが、256色以外は、
MAMEがとろかったんで、ここを書き換えたよ。
static struct
{
int r;
int g;
int b;
} palette_bits[] =
{
/* r g b */
{ 6, 6, 6 },
{ 5, 5, 5 },
{ 4, 4, 4 },
{ 3, 3, 3 },
{ 3, 3, 2 },
};
の最後の行を。
{ 2, 3, 3 },
にすると、256カラーでは、格段に画質がアップするんだ。ぱっと見に16ビットカラーと見間違う位まで回復
したので、感動したな。ゲームならではの技だな。画像処理の本ばっかり、読んでるからついBを2にしちゃう
んだろな。ゲームで何が重要なのかが、解かってれば、こんなミスは犯さない筈だよ。いや、それ以前に、
256カラーなんて誰も使ってないな。今時。昔のMAMEは、このリアルタイムパレット機能はなくて。
(いやあったが全然別の方式で、それはそれで良かった。)このタイプにMAMEが変更になった時代は、
管理人60fps出ないと嫌だから、しばらくMAMEを乗り換えなかった記憶がある。当時のPCはMAMEの
この辺無改造なら、(ここのみの)レンダー負荷が20%近くあった。当時はドライバやメモリは一生懸命速く
して遊んだけど、この辺は未知の世界で弄ったりしなかったから、ここがボトルネックになってる事など、
気づきもしなかった。
(注:ここ、ってのは、/mame_XXX/src/msdos/の下。これは、/psp_mame04/src/psp/の下と事情が全く同じ)
しばらくして、profilerをリンクする技を身につけ、他が最適化して早くなってるので、ここが、50%強に達して
いるのを、発見。大改造してMMX化したら、(もちろんそのPC専用!)エミュ自体が滅茶苦茶速くなった
(そりゃそうだ)ただしVRAMアクセスでセレクタが変わるのか。CSもDSも、とにかくあらゆる物を退避、
復活させたし。終わったら、emmsもしたし。それでも、コンパイルして、実行が上手くいったり、暴走したり。
でも、レイフォース60fpsの誘惑は捨てがたく、今でもどっかにある。が、弄る気はない。
という懐かしい思い出が管理人にはよぎるのだった。そうそう、MAMEのこの自動FSKIP機能も
バカなんだよね。全然PCの機能を活かしてくれない。ここは殺して、他のタイプを実装せんとfpsが
30を切る重いゲームは遊べない。(開発版は0.5fpsとかからスタートする。)ここは自動学習型の
自動追尾fps処理が有効だ。ただし、20fpsを超える頃から、この方式は無力になる。
(どうがんばって調整しても、上手く追尾出来ない)ちょうど、お魚さんに乗ってた自動fps装置も、
(あれは単純な方式だが)エミュの速度がこの領域に入ってしまったので、上手く追尾
出来なくなったんだろう。60fpsと30fpsの差は1フレームしかないので、ここは誰がやっても
上手くいかない。大体MAMEの
static const int skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS] =
{
{ 0,0,0,0,0,0,0,0,0,0,0,0 },60fps
{ 0,0,0,0,0,0,0,0,0,0,0,1 },55fps
{ 0,0,0,0,0,1,0,0,0,0,0,1 },50fps
{ 0,0,0,1,0,0,0,1,0,0,0,1 },45fps
{ 0,0,1,0,0,1,0,0,1,0,0,1 },40fps
{ 0,1,0,0,1,0,1,0,0,1,0,1 },35fps
{ 0,1,0,1,0,1,0,1,0,1,0,1 },30fps
{ 0,1,0,1,1,0,1,0,1,1,0,1 },25fps
{ 0,1,1,0,1,1,0,1,1,0,1,1 },20fps
{ 0,1,1,1,0,1,1,1,0,1,1,1 },15fps
{ 0,1,1,1,1,1,0,1,1,1,1,1 },10fps
{ 0,1,1,1,1,1,1,1,1,1,1,1 } 5fps
};(「0の数」x5=##fps)
こんな粗いテーブルじゃ、全然ダメで、最低でも4倍は細かくしないと(20fps以下の領域でさえ)
ゲームになんない。このテーブルは横軸が時間(フレーム)で0が描画、1が飛ばす。
上下はレベルで負荷が高いと(独自のプログラムで)判断すれば、レベルダウン。(下に下がる)
負荷が低いと(独自のプログラムで)判断すれば、レベルアップ。(上に行く)
static struct
{
int r;
int g;
int b;
} palette_bits[] =
{
/* r g b */
{ 6, 6, 6 },
{ 5, 5, 5 },
{ 4, 4, 4 },
{ 3, 3, 3 },
{ 3, 3, 2 },ここが332だから、古いコードだ。新しい奴なら233にFIXされてる筈。
};
int frameskip,autoframeskip_mode;
#define FRAMESKIP_LEVELS 24
#define FRAMESKIP_LIMIT (FRAMESKIP_LEVELS-1)
static const int skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS] =
{
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* 1 [0] */
{ 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* 1_[1] */
{ 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 }, /* 2 [2] */
{ 0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0 }, /* 2_[3] */
{ 1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0 }, /* 3 [4] */
{ 0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0 }, /* 3_[5] */
{ 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 }, /* 4 [6] */
{ 0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0 }, /* 4_[7] */
{ 1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0 }, /* 5 [8] */
{ 0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1 }, /* 5_[9] */
{ 1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0 }, /* 6 [10]*/
{ 0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1 }, /* 6_[11]*/
{ 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 }, /* 7 [12] */
{ 1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,1,0 }, /* 7_[13] */
{ 0,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,1 }, /* 8 [14] */
{ 1,0,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,0,1,1,0,1 }, /* 8_[15] */
{ 0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1 }, /* 9 [16] */
{ 1,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,1 }, /* 9_[17] */
{ 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1 }, /*10 [18] */
{ 1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1 }, /*10_[19] */
{ 0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1 }, /*11 [20] */
{ 1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1 }, /*11_[21] */
{ 0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1 }, /*12 [22] */
{ 1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, /*12_[23] */レベルが(上下に)移動した時負荷が
大きく変動しないように0の位置は、テーブル全域に渡ってずらす様配慮(計算で求めた)されている。
MAMEの奴は、その辺何にも考えてないだろ。レベルは移動するに決まってるんだから、
その辺も考慮に入れないと現実のゲームで遊べる筈がないだろ。
};
ほら、出てきた昔のソースの一部だな。これくらいはやらんと、ゲームにならん。このままMAMEの
調整ルーチンに移植しても駄目だからな。MAMEの奴は重い/軽いの判断がその場限りだから、
最低でも経験値式にして、少し長い目をもたせな、あかん。その上で、ゲームというのは、突然重くなる事が
あるので、その場合への対策コードを実装する必要がある。その辺までやったら少しは遊べたな。まあ、過去の
話やけど。そろそろこの話も、飽きてきたんで
switch(autoframeskip_mode)
{
//case 0: /* Safety(frameskip_counter == 0)?? */
//case 1: /* ? */
case 2: /* Auto frame skip adjust. */
{
static signed int fast_exp=(576/2); /* (to start exp at half) check computer fast? */
frameskipadjust =(/*performance->*/p_game_speed_percent);
if ( 75>frameskipadjust) { fast_exp-=16; /* 1/2 level down */ frameskip=20; /* force low 16% */ }
else if ( 80>frameskipadjust) { fast_exp-=8; /* 1/4 level down */ frameskip=19; /* force mid 20% */ }
else if ( 90>frameskipadjust) { fast_exp-=4; /* 1/8 level down */ frameskip=19; /* force mid 20% */ }
else if (100>frameskipadjust) { fast_exp--; fast_exp--; /* 1/16 level down */
if(fast_exp<0) fast_exp=0;
frameskip=((1184-fast_exp)>>6); /* 1184 = (19+18) x 32. [(19+18-(fast_exp>>5))>>1] set to (mid_20% + high_adjust)/2. */
}
else { /* 100% over'n,. doubt host was fast machine? */
fast_exp++;
if(fast_exp<0) fast_exp=0;
if(576<fast_exp) fast_exp=576; /* 576 = 18 x 32 */ /* oops,. fast computer it. */
frameskip=18-(fast_exp>>5); /* 1/32 */ /* [fast's clip low 25%.(small value to fast level)]-[now auto exp]. */
}
}
このコードどのレベルまでやったか忘れたけど、(古いコードだから)多分調整前のやつだな。
とにかくPSPに戻るぞ。(10:35)
■今なMAMEの古いコード(MSDOSの下)漁ってたら、「SNPRINTF.C」(20kb)っての見つけた。
これ「SPRINTF」の変わりに、使えんかな。LIBC実装するって話。PSPに移植するなら、最低でもPC
で動作させて正当性のチェックをせなあかん。VCPPとGCCとLSICでチェックすれば、まあPSPで動く
じゃろ(11:10)
■さてSYS1(PSP MAME)に戻る。現状memcpyだのmemcmpだのアホくさいエラーを回避する為。
-lcでチェックしている。-lcをつける位置で意味が変わる事を知らん奴は、昨日の日記を読め。
エラーはこんなん。
pmain.o obj/namcos1psp2/psp/menu.o obj/namcos1psp2/psp/y_malloc.o obj/namcos1psp
2/psp/v_malloc.o obj/namcos1psp2/libz.a ./unziplib.a ./libgcc.a ./libgcov.a -lc
-M -Ttext 8810000 -q -o out > main.map
obj/namcos1psp2/mame.o: In function `run_game':
mame.c:(.text+0xddc): undefined reference to `drivers'
mame.c:(.text+0xde0): undefined reference to `drivers'
obj/namcos1psp2/usrintrf.o: In function `showgamewarnings':
usrintrf.c:(.text+0x5dc8): undefined reference to `drivers'
usrintrf.c:(.text+0x5db8): undefined reference to `drivers'
usrintrf.c:(.text+0x5dcc): undefined reference to `drivers'
obj/namcos1psp2/usrintrf.o:usrintrf.c:(.text+0x5dd4): more undefined references
to `drivers' follow
make: *** [EBOOT.PBP] Interrupt
このMAMEの標準のDRIVERが見えないってのはDRIVERがグローバル変数で、遠すぎるから
見えないんだろ。理屈上。OBJの配置を工夫するだけでなくて、どのCのソースファイルにどのCのファイルを
いれるか工夫しなくちゃいけない。そんなめんどくさい事するくらいなら、DGENみたいにCPPの
クラスライブラリにして、クラスの中に閉じ込めるか。1つのクラスにして、DGENでやったのと同じように、
すべての関連ファイルをひとつのファイルからインクルードしてしまえば、それは、コンパイラの仕事になって、
リンカは関係がなくなる。
■ちょっと初心者向けTips:GCC-4.0.0ってのは「コンパイラ本体」でも「リンカ本体」でも、ないんだよ。
あれは厳密には「コンパイラドライバ」と言われるもので、ほいってファイルを渡すと、「拡張子」から何の
ファイルかにゃ?って判断して「コンパイラ本体」なり「リンカ本体」なり「アセンブラ本体」なりにそいつを渡して
実行して(変換の仕事をして)もらう。
出来上がった結果を、さも自分がやったみたいな顔をして、「出来ますた」っていってmakeに返す。勘違いしちゃ
いけない。あいつは単なる取次ぎ役で、実際は「アセンブル」も「リンク」も「コンパイル」も仕事をしない。
取り次ぎ役を使わないで、直接仕事を発注する事も可能だ。「CC」や「AS」や「LD」うちではGCC400なので、
536,064 05-06-17 19:43 psp-addr2line.exe
507,392 05-06-17 19:43 psp-ar.exeアーカイバ
873,472 05-06-17 19:43 psp-as.exeアセンブラ
109,568 05-06-21 18:36 psp-cpp.exeC言語のプリプロセッサ(インクルードやデファイン等マクロ処理を担当、これはC++とは関係がないよ。あくまでC言語。変な勘違いをしないように)
534,528 05-06-17 19:43 psp-c++filt.exe(こいつもC++言語。翻訳が複雑だから、2パスに別けたんだろ?多分)
110,080 05-06-21 18:36 psp-c++.exe(こいつはC++言語)
48,128 05-06-21 18:36 psp-gcov.exe(多分コフ形式に変換する奴。)
108,032 05-06-21 18:36 psp-gcc-4.0.0(これがコンパイラドライバ。受け付け嬢だな)
15,740 05-06-21 18:34 psp-gccbug(パッチあてかな?)
780,800 05-06-17 19:44 psp-ld.exe(これはリンカ)
547,328 05-06-17 19:43 psp-nm.exe
691,712 05-06-17 19:43 psp-objcopy.exe
762,880 05-06-17 19:43 psp-objdump.exe
507,904 05-06-17 19:43 psp-ranlib.exeランリブ
220,672 05-06-17 19:43 psp-readelf.exe
491,520 05-06-17 19:43 psp-size.exe
491,520 05-06-17 19:43 psp-strings.exe
691,712 05-06-17 19:43 psp-strip.exeストリップ
コンパイルは誰がやるの?いい質問だ。多分、分散してみんなでやるんだな。みんなってのは、こいつらで
全部。GCCの実装方法の場合。コンパイラドライバもいろいろやるかもしれん。少し有能な受け付け嬢だな。
秘書も兼ねてるかもしれん。
(コンパイルってのは、使う側の概念で、現実に変換する側からみると、大雑把すぎる概念だって事)
実装は解からなくても、ファイルサイズから仕事量が想像つくだろ。
要は仕事してる奴程、ファイルサイズがでかいんだよ。(今13:00)
■
えっと前の話に戻る。
↑ここにWARPボタン貼り付けよーっと思って、
過去日記読んでたら、「06-02/11 DG #11 UPdate1合成 」(DGEN100A16開発版)
BF03チェックの話が載ってたんで、
(ちなみに管理人がコンパイルしてない元のDGEN100のパフォーマンスはここ「06-01/19 DG GEN日記#3遅」)
今のDGEN100A16Bとパフォーマンス比較してみたら、44100こそ変わらないものの、
遅くなってんじゃん!しょうがない。今はやりたくないから、別館にA16の過去版、上げとく。
が、この辺は基本的にソースの無駄なルーチンを削除しかしてないぞ。コンパイルの都合で
こうも変わるんだなって例。急がない人には全く関係のない話。
だが、管理人の試した範囲ではパフォーマンスはでないが新しい版の方がゲームは速かった。
最近はFSKIP2、44100という軟弱な設定がMDのゲームは効果がある事が解かったし。
(2006-02-18、13:33)
■
関係ないけどさ、「バーニングフォース(アーケード版)」の3-2で「平成元年ステージ(隠し面)」に行く、
裏技があるだろ。(CDにも「やり方」は載ってない「キャラ」は出てるけどな)
「あれ、どうやったら、行けるんだ?」
(1-1からノーミスで行って、ボーナスステージで点かせぎもして、
ルーレットみたいな変な機械の☆マークに突っ込むあたりまでは、
判るんだが詳細のやり方が判らん。何度やっても再現しないぞ。)
管理人、うっかり裏面に行ったけど、動揺して死んだら、表面の3-2に戻されちゃったよ。
超マニアなネタだが、誰か知らんか?知ってたらぜひコメント入れてよ。
メガドラ版は裏面は移植されてない。まあ、あの完成度じゃ仕方ない。表面だってちゃんと移植出来てない
別ゲームだもんな。特に電車面以降は、雰囲気すら、全く違う。全然違うゲームじゃねぇか。まあ、
コンシューマーに、開発期間取れないんだから仕方がないけどさ。
「平成元年ステージ」が裏技なんだから、もう20年近く前のゲームなんだな。
(2006-02/18、14:45)
■なんだあ。LIBCあるじゃん。
/cygwin/を「libc」で検索したら、
/usr/local/pspdev/psp/psp/lib/に
「libc.a(2,691kb)」「libcfe.a(86kb)」発見!
早速リンクしてトライしてみたけど変わらず。
$(LD) -O0 $^ $(LIBS) ./libgcc.a ./libgcov.a ./libc.a ./libcfe.a -lc -M -Ttext 8810000 -q -o out > main.map
ちとライブラリが多すぎるみたいだ。
組み合わせを変えていろいろトライしてみるか。(これ以外にも「UNZIPLIB.A」と「ZIPLIB.A」もリンクしてる)
FM音源が遠くなっちゃったよぉ。MACHINEのドライバ(旧)「machine/namcos1.c」とくっつけちまうか。
(2006-02-18、15:29)
「libgcc.a」「libgcov.a」は要らんと思われるので、外してリトライ。
結果変わらず。原因はlibc.aが2.7MBもあってでかすぎるのが原因だろう。
「.A」の癖に、リンカが切り出してリンクする事が、できないのだろう...。多分な。
そんな機能は実装されてない。って落ちだろ。
つまりRUKAさんのように「UNZIPLIB.A」みたいな、オリジナルなライブラリを構築しないと、
このままの状態では、コンパイルがいくら正常でも、実際のEBOOT.PBPにはならん。という仕掛けだ。
1.ソースを見直して、ライブラリを使わないように書き換えるか、
2.オリジナルのLIBC.Aライブラリを構築するか、(RUKAさんの様に)
方針は2通り。
両方の線から、攻めてみるよ。
お魚さんのは何で、とどくんだろな。やっぱ、小さいと、とどくのかな(13:45)
追加の方針
3.DGENみたいにC++のクラスにして遠い/近い問題を封じ込める。
■「GCC4.0.0用のunziplib_v1_00src.zipコンパイル用Makefile」
それはともかく、管理人何か勘違いしてたみたい。RUKAさんの「UNZIPLIB.A」って、
本当にZIP以外のライブラリ入ってないよ。
いまソース開けて調べたんだから。間違いない。
ってことは、お魚さんの奴は、それと全く同じOBJを作る。Makefileを公開しないと、
ソース全部公開した事にならんな。今すぐ作るよ。まったく同じバイナリになる奴を。
あれは、単にNesterJをコンパイルした奴から抜いてきただけなんだけど。出所が、
全てクリーンでないと、気持ち悪いでしょ?
じゃ、今からその作業な。(17:00)
BINARY = out
OBJECTS = adler32.o crc32.o infback.o inffast.o inflate.o inftrees.o\
ioapi.o uncompr.o unzip.o zlibFileMemory.o zlibInterface.o\
zutil.o
all: $(BINARY)
$(BINARY): $(OBJECTS)
psp-ar rcs unziplib.a $(OBJECTS)
%.o : %.c
psp-gcc-4.0.0 -O3 -fomit-frame-pointer -g -mgp32 -mlong32 -c $< -o $@
clean:
del /s /f *.o *.map
作らなくてもMakefileが見つかったから、もう検証せんよ。
RUKAさんのページから、「unziplib_v1_00src.zip」を落としてきて、ZIP展開し、Makefileを上記に書き換えて、
コンパイルすれば、まったく同じものが出来るよ。
要するに、上のは「GCC4.0.0用のunziplib_v1_00src.zipコンパイル用Makefile」だ。
お魚さんに添付した奴と、バイナリレベルで一致する筈だ。次のVERから、ソースに混ぜとくわ。(17:10)