SEGADRIVE A21どおすりゃいいの?
ついさっき、五分ほど前(多分15分くらい前、気分優先)に、ついに諦めて、「A21」からやり直そうと、
別館から「A21」をDL。ここ2~3日。クラスライブラリ破壊したり、戻したり。
そんな事ばかり繰り返してたので、何処が不要で、どこがゴミルーチンか、ハッキリしてる。
その為5分くらい手を入れて、ゴミルーチンをばっさり削除。コンパイルしなおしてPSPで実行。
やはり、重くなってしまう。っていうか重くなる。なんつーか。fpsの数字も悪くなるんだが、
ゲームの動作全体も、まったりと遅くなる。(OutRunでテスト)
今、5分程作業した内容しか、変更してないんだから、自信をもって言うが、「どおすりゃいいの?」
なんつーか、fpsメーター隠しても、体感できるレベルで重くなる。はっきりいってアセンブラリストが
見れるのならば、それ見てちと検討比較してみたい。CPPの内部以外は全く弄っとりゃせんから、
GCCにそおいう機能があるのならば、読むべきアセンブラリストはホンの少しの筈だ。意味なんて全然
解からなくても、読みゃ何とでもなる筈。
困つたな。(注:拗音を小さく書くのって強制じゃないんだって、なるべくそお書いた方が望ましいんだって。)
(03/19、20:42)
■A21ってさ。別に速くなったからUPした訳ではないんよ。たまたま管理人がおなか減ったからUPしたの。
今なら上にも書いてあるでしょ?
「PSP SEGA DRIVE実験版 A21」UPしたけど、おなかすいたつ♪
ってさ。あくまでおなかのつごーでUPしたんだから、明らかにやりかけのソースな訳。だって、おなかすいたら、
UPするしかないじゃん。他に管理人にどおしろというの。
おなかすくんだもん。おなかすいたからUPしたんだもん。悪いことしてないし、悪いもん喰つた記憶はないもん。
でも、ここ2~3日。病気でへばってるから、やっぱ悪いもん喰ったかも。ケーキ以外で。
■さらに要らない部分を排除してみた。さすがにずっと弄ってると何処が要らないか直ぐ判る。
すこし、持ち直した。が、まだ元のA21に比べて重い。
ええとFSKIP2なのにfpsメーター値で(これは速度であってfpsとは関係がない)
-1~-2グライ。FSKIP2なんだから、極端なことを言えば、最小速度単位で、-3~-6遅くなってると、
言い直してもいい。(-値が遅いとする)
PSPのアッセンブラ全く解からないが、「不要な部分の削除」しかしてないので。アセンブラコードが、
小さくなっても、大きくなる事はあまりないだろう。だから、相対インデックスのような分岐命令は届くと思われる。
だから、純粋にALIGNなんじゃないの?見えないものは解からないんだけど。
(ワカラン、21:36)
■そういや「C言語」って関数名は実は変数なんだよね。って事は、何もCPPに頼らなくても、C言語で、
関数のALIGN記述出来るのかな?。関数のALIGNあわせをGCCが受け付けてくれれば、問題は一気に解決
する可能性がある。
変数のALIGNを受け付けるんだから、工夫すれば、関数のALIGNも受け付けるんじゃないかな。GCCが、
嫌がったら困るけど、ちと試しに記述してみよー。まーどーせコンパイルエラーの落ちだろうが、もしかしたら
もしかするかもしんないじゃん。やってみよ。
(やってみよ、21:45)
■駄目。どおがんばって記述してみてもALIGN受け付けてくんない。でもこれは理屈上おかしい話だ。
だって関数名==変数名なんだから。void型のポインタを用意して代入したら、理屈上意味がない。
実体にALIGNあわせてくれなくちゃ。実体にALIGN合わせるのは「-O3」が自動でやってくれるのかな。
それともやってくれないのかな。明らかに症状がALIGNっぽいけど、ALIGNと関係ないのかな。
詳しくないからワカンナイ。ああ、アセンブラなら物凄く簡単な事なのに。関数の直前に馬鹿みたいに毎回
ALIGN合わせ書くだけなのに。VisualC++なら、何にも言わなくてもちっとオプション弄るだけで、自動で
やってくれるのに。ああ、PSPワカンナイ。
(ワカンナイ、21:55)
■今度はもちっと不要なルーチンを削除し、ついでに某所の「安全弁」も解除した。
「安全弁」を解除したから、ゲームによってはおかしくなる可能性がある。が、管理人の直感で、
「まず100%OK」じゃろ。
ちなみに「不要なルーチンを削除」する過程で、分岐ルーチンも減っている。つまりPSPのミスキャッシュ
ペナルティーがどうのこうの(だって最悪70クロックとか言ってたジャン、2~3日前の日記)って話なら、
大幅に改善されて、然るべきだ。そこのルーチンはバリバリ使ってる場所で、不要なコードではあるけど、
バリバリ通って(実行して)いる部分。そこの分岐を削除したのだから、ええい要するにこう。
□初めの状態
if(式){//←この式が安全弁
使う
}else{
ゴミ
}
□さっきの状態
if(式){//←この式が安全弁
使う
}
□今の状態
使う
注:現実的に考えてこの「式」が成立しない可能性は考えがたい。
■なんと、上記のチェックを外すと「不思議ちゃん1」を実行させると暴走する。
つまりエミュ自体が落ちる。PSPの電源ボタン長押しである。
ちなみに、
起動しない「スラップファイトMD」
起動しない「サンダーフォースⅣ」
では大丈夫。
ここは、実機では、多分「アドレスエラー」になると思う。「アドレスエラー」になると、
スーパーバイザモードとユーザーモードが入れ替わって特定ベクタに復帰するんじゃなかったっけ?
うーん、よく覚えてないが、そんなよーな動作だったような。もしくはIRQが発生するのかな?
(注:m68000の場合NMIは番号忘れたがとにかくIRQ)
ちと調べて
みないと解からんが、「不思議ちゃん1」は「アドレスエラー」を発生させる。プログラムなんじゃないかな?
うーん、Z80からアクセスしてここにたどり着かなそうだし、m68000のbyte系の場合、特別にアドレスエラーに
ならないとしても、奇数番地WORDアクセスだよ?。ワカラン。
ちょっと調べないと判らんが、IRQの場合、実機で割り込み線を配線してない可能性がある。その場合、
そもそもアドレスエラーの割り込みがかからない。だから変なプログラムでもアドレスエラーで、止まる
事はない。強制的に次の命令を実行するし、スタックも変化しない。もしかしたらこういう風になってる
可能性もある。ハードウェアーの設計なんて、考え方によって様々だから、何も優等生的な設計になってる
必要等、何処にもない。ちと調べてみよ。
(23:30)
■もう一回、安全弁を戻してみた。
やはり、「不思議ちゃん1」は暴走しない。
つまり、差し当たり、ここの安全弁は解除してはいけない。場当たり的対応だが、仕方がない。
この安全弁は具体的にVDPコマンドのWORDアクセス、READとWRITEの二ヶ所。
この際、「不思議ちゃん1」は、どっちでこけてるのか確認しといた方が良いだろう。所詮二ヶ所なんだし、
果たしてREADかWRITEか。
(23:41)
■管理人の予想に反してなんとWRITEだった。確かに良く考えりゃPSPが落ちるんだからWRITEの
可能性が高い。がついうっかり無視した。心理的な問題である。
ということは、
メガドラは、「アドレスエラー」になった場合にIRQが発生しない可能性が高い。つまり配線してない。
X68000というパソコンの場合は、その線は(たったの一本だ)配線してあるので、「アドレスエラー」が
発生した場合IRQがかかりIRQベクタに飛ぶだろう。だがメガドラがその部分を配線してない場合、
端からIRQなど発生しない。が「アドレスエラー」には違いないので、SSPはどおなるのだろう。
少なくともスーパーバイザモードとユーザーモードが逆に切り替わるんじゃないか?
もし、めんどくさいからスーパーバイザで突っ走れ式のプログラムならその時点でスーパーバイザだった
ものがユーザーに切り替わってしまうのではないか?よく判らん。要調査だな。不思議なネタは尽きないな。
(あと3分で明日)
ああもうお昼(夜の0:00)だから寝よかな。
■何で重くなるの?
差し当たり、
static unsigned short vdp_readword(void)
{
unsigned short result=0;
    switch(rw_mode)
    {
    case 0x00: result=*((unsigned short*)&vram [vdp_address&0xffff]); break;
    case 0x20: result=*((unsigned short*)&cram [vdp_address&0x007f]); break;
    case 0x10: result=*((unsigned short*)&vsram[vdp_address&0x007f]); break;
    }
    result = (result << 8) | (result >> 8);
    vdp_address+=vdpreg15;
    return result;
}
を
static unsigned short vdp_readword(void)
{
    unsigned char* vvv=0;
        switch(rw_mode)
        {
        case 0x00: vvv=vram +(vdp_address&0xffff);break;
        case 0x10: vvv=vsram+(vdp_address&0x007f);break;
        case 0x20: vvv=cram +(vdp_address&0x007f);break;
        }
    vdp_address+=vdpreg15;
    return ((vvv[0]<<8)|vvv[1]);
}
にしてみた。要は全く同じ事をしてる。
そこの横のリンクから、PSPでの速いコードって書いてあるやり方に。
変更してみただけだ。
だが、OutRunは露骨に重くなる。FSKIP2で(-1~-2fps)グライ。
何で?
ああ、やっぱ、「=0」が悪いんだろうな、「プログラマー養成ギブス(-Werr)」外そうかな。ここに来る度=0のコードが
入るの嫌だからstaticにしようか。でもその場合、「別のデメリットが発生する可能性」すなわち
「レジスタ割付」してくんないと嫌だな。どおしよ。
昔のC言語みたいに、registerって書いていいんかいな?staticと両方書いてもレジスタ割付に共存してくれるの
かな?そんな予約語、廃止されてるんじゃなかったっけ?どおなんだろ。
(次の日00:34)
さしあたり、
	static unsigned char* vvv ;
で、良いらしい。WARNINGが出ないから、STATICでレジスタ割付してくれると信じよう。さしあたり
確認する方法もないし。で、OBJコードが0xCDB6Cから0xCDB8Cに増えた。
常識で考えれば、メモリ割付したから、OBJコードが増えたと考えがちだが、
ここはレジスタ割付したから、OBJコードが増えたんだろう。さしあたり、確認の方法もないし。
で、速度、実験してみよう。
なんつーか、さっきよりは速くなった。
今OutRunFSKIP2、22050のチェックは止めて、
FSKIP0、22050にチェックの方法を変更した。
現状FSKIP0、22050は、とてもゲームになるスピードではなく生理的に不快だが、いづれはたどり着かなければ
ならない場所だろ?FSKIP0、22050の場合微妙に速いような?
FSKIP2、22050の場合は速くなったり遅くなったり。
もう、FSKIP2のチェックは止めようか。FSKIP2を基準にしてる限り、現状を見誤るんじゃないか?
とにかくstaticは(可能な場合は)レジスタ割付されるらしい事が判明したな。これは儲けものだな。
いろいろ、staticにして実験してみよう。特にメモリ周りのルーチンはちょっと変えるだけで速くなるかもしれん。
今日は不要なルーチン削除しかやってないのに、A21より遅いレベルにある。明らかに遅いんだケドもう戻すの
やだよ。だって、使ってないの削除すると、遅くなるんだもん。ちょっと変えても遅くなるんだもん。何だか今日も
疲れたよ。もう寝るっていうか。ここの更新はこの辺にしとく(つもり)おやすみ。(01:12)