#9きょうはどおしよ(2006-02/18) | //www.旧型、PSP開発幼稚園.game.jp/(本館)

#9きょうはどおしよ(2006-02/18)

#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)