//www.旧型、PSP開発幼稚園.game.jp/(本館) -102ページ目

#7GEN日記あれ?MUSASI3.3で重くなったよ。

2006-01/24 D #7GEN日記+雑日記

myDGEN日記#7(もう一週間かぁ)

(注:このDGENは1.00です。最新のDGENはもっとずっと進んでいます。
スキルがあり、開発をしたい方は開発者に直接コンタクトをとって下さい。
私は開発者とは全く関係のない第三者です。
あくまでこのページの話は実験用途(教育用)です。)

■MUSASI3.3をリンク中 MUSASI2.0A→3.3変更点(作成中)
〇1.MEMORY読み書き仕様が「INT」から「UNSIGNED INT」になった。 例えば、 int m68k_read_memory_16(int address);を unsigned int m68k_read_memory_16(unsigned int address); にする。 「INT」は(正確には)「SIGNED INT」なので、この方がいいと思う。 が、エラー-1って返す事ができなくなった。 この辺GCCのmallocと同じ。 が、エラー-1返す必要がないよ。この場合。(多分)
○2.IRQがシンプルになった。 m68k_assert_irq(4); m68k_clear_irq(4);を m68k_set_irq(4); 「680x0」のIRQはNMI(禁止できない割り込み)なのでこれで良い。 IRQを引き伸ばす事って、物理的にできないし、 どおしてもエミュでそれをする必要があるとは思えない。 上の2行は平たく言えば、 IRQ_信号ON(#4);IRQ_信号OFF(#4);を IRQ_信号発生(#4);に変更した。という事。 (IRQ_信号ON==IRQアサート) (IRQ_信号OFF==IRQネゲート) (IRQ_信号発生==IRQ割り込み発生。 周辺回路がアサートしてから、ネゲートするのか。 あるいはCPU内部でパルス発生を行うのか、わたしは知らない。)
○3.PEEK、POKE関数の廃止 内部CPUに簡易アクセスするこいつらは、廃止になった。 コンテキストを使ってアクセスしような。
/* look at the internals of the CPU */ int m68k_peek_dr(int reg_num); int m68k_peek_ar(int reg_num); unsigned int m68k_peek_pc(void); unsigned int m68k_peek_ppc(void); int m68k_peek_sr(void); int m68k_peek_ir(void); int m68k_peek_t1_flag(void); int m68k_peek_t0_flag(void); int m68k_peek_s_flag(void); int m68k_peek_m_flag(void); int m68k_peek_int_mask(void); int m68k_peek_x_flag(void); int m68k_peek_n_flag(void); int m68k_peek_z_flag(void); int m68k_peek_v_flag(void); int m68k_peek_c_flag(void); int m68k_peek_usp(void); int m68k_peek_isp(void); int m68k_peek_msp(void); /* poke values into the internals of the CPU */ void m68k_poke_dr(int reg_num, int value); void m68k_poke_ar(int reg_num, int value); void m68k_poke_pc(unsigned int value); void m68k_poke_sr(int value); void m68k_poke_ir(int value); void m68k_poke_t1_flag(int value); void m68k_poke_t0_flag(int value); void m68k_poke_s_flag(int value); void m68k_poke_m_flag(int value); void m68k_poke_int_mask(int value); void m68k_poke_x_flag(int value); void m68k_poke_n_flag(int value); void m68k_poke_z_flag(int value); void m68k_poke_v_flag(int value); void m68k_poke_c_flag(int value); void m68k_poke_usp(int value); void m68k_poke_isp(int value); void m68k_poke_msp(int value);
で、コンテキストを使った、新しいやり方。 PEEK系は全部これ、 unsigned int m68k_get_reg(void* context, m68k_register_t reg); POKE系は全部これ、 void m68k_set_reg(m68k_register_t reg, unsigned int value); 使用例:D3に99をセット 古い方法 m68k_poke_dr(3,99); 新しい方法 m68k_set_reg(M68K_REG_D3, 99);
○4.コンテキストの使い方は変わってないよ。 unsigned int m68k_get_context(void* dst); void m68k_set_context(void* dst);
■MUSASI3.3をリンク中(その2) さてと、のんびりやってますが、ちょっと他の用事があったからです。それはともかく、 まず、上記の違いがあることが判りました。管理人ごときがこのままがりがり書くと、 どこかで、エンバグするかも知れません。ここは少し遠回りでも確実な方法でいきたい所です。 「動かなくなっちゃったー。えーん、どこ直したのかわかんない→破棄。」 では、進むものも進まないし、時間の無駄ですよね。
上記(1.)これは変えてもOKでしょう。 上記(2.)これも変えてもOKでしょう。というのは、ソースを検索したら、 「mdfr.cpp」(メガドラのレンダー、フレーム単位の処理部分)の一部でしか、使ってないからです。 上記(3.)これはたくさんあります。 と、いうことで、問題は(3.)のみです。効率は悪くなるけど、「m68cpu.c」に旧関数を追加して、 対応する事にします。コンパイルと正常動作を確認後。もし、オーバーヘッドが気になるのなら、 これらの関数は最適化すれば良いでしょう。 そういう訳で、「m68k.h」に(何故か2つ全く同じものがあるので注意)とりあえず、 make弄るの嫌だったので、MUSASI2.0Aの前記の関数をすべて追加(プロトタイプ宣言)して、 コンパイルしてみました。 neo_geoなんたらってエラーとか出てたみたいだけど、基本的にはOKみたいですので、 「m68cpu.c」を書き換える(MUSASI3.3の奴に旧関数を追加)という方針で行く事にします。
neo_geoなんたらってエラーは、元がPSP_NEOGEOCDだったもので、現時点ではよく 判りませんが、そのうち判るでしょう。 →これは、元にしたソースがNEOGEO&CDエミュレーターでBIOSを使わなくても、 GAMEが(速く)動作する様に、CPUレベルでカスタマイズしてあるのが原因だった。 「m68kopac.c」
void m68k_op_1111(void) { #if 00 switch (REG_IR) { case 0xfabe: neogeo_exit(); break; case 0xfabf: img_display=1; neogeo_cdrom_load_files(); break; case 0xfac0: img_display=0; neogeo_cdrom_load_files(); break; case 0xfac1: neogeo_upload(); break; case 0xfac2: neogeo_prio_switch(); break; case 0xfac3: neogeo_cdda_control(); break; default: m68ki_exception_1111(); break; } #else m68ki_exception_1111(); #endif }
ここ(Aラインエミュレーターのフック)を無効にして、解決。 ここを書き換えちゃえば、仮にメモリがバグったとしても、 NEOGEOの場合ゲームが安定動作する(だろう)為。 (BIOSが殆ど何もしない)メガドラにはほぼ関係ない話だ。 メガCDのエミュもし作るのならば、ここにMEGA CD-BIOSの フック配置した方が速いかもしれない。 PSP_ON_MEGA_CDか。 メモカ安くなったら少し考えてもいいな。どおせ、安くなるんだし。
管理人。今日はずいぶんながなーーがWebサーフィン(死語?)してました。 メガドラのページですね。まあ、たまには他のこともしないと。
で、めんどくさくなってきたので、上の方にもっともらしそうに挙げてある。 コンテキスト関係の変換は、殆どSAVE.CPPで使っている事に目をつけ、 めんどくさいから、68関係のLOAD/SAVE部分を殺しました。 書き換えた部分はこんな感じ。内部変数を直接アクセスしているので、 予想していたようなオーバーヘッドはありませんでした。
/* The old API compatibles, but need set to bigin context to use it at once. */ /* Peek at the internals of the M68K */ int m68k_peek_dr(int reg_num) { return m68ki_cpu.dar[reg_num ]; } int m68k_peek_ar(int reg_num) { return m68ki_cpu.dar[reg_num+8]; } unsigned int m68k_peek_pc(void) { return MASK_OUT_ABOVE_32(m68ki_cpu.pc); } int m68k_peek_sr(void) { return m68ki_cpu.t1_flag | m68ki_cpu.t0_flag | (m68ki_cpu.s_flag << 11) | (m68ki_cpu.m_flag << 11) | m68ki_cpu.int_mask | ((m68ki_cpu.x_flag & XFLAG_SET) >> 4) | ((m68ki_cpu.n_flag & NFLAG_SET) >> 4) | ((!m68ki_cpu.not_z_flag) << 2) | ((m68ki_cpu.v_flag & VFLAG_SET) >> 6) | ((m68ki_cpu.c_flag & CFLAG_SET) >> 8); } //sp==a7 need it? int m68k_peek_usp(void) { return ( m68ki_cpu.s_flag ? m68ki_cpu.sp[ 0] : m68ki_cpu.dar[15]); } int m68k_peek_isp(void) { return m68ki_cpu.s_flag && (!m68ki_cpu.m_flag ? m68ki_cpu.dar[15] : m68ki_cpu.sp[ 4]); } int m68k_peek_msp(void) { return m68ki_cpu.s_flag && ( m68ki_cpu.m_flag ? m68ki_cpu.dar[15] : m68ki_cpu.sp[ 6]); } /* Poke data into the M68K */ void m68k_poke_dr(int reg_num, int value) { REG_D[reg_num] = MASK_OUT_ABOVE_32(value); } void m68k_poke_ar(int reg_num, int value) { REG_A[reg_num] = MASK_OUT_ABOVE_32(value); }
この辺までやって飽きた。(しょうもな)まあ後は単純作業だし、 フラグ関係はちょっと、「DGENのSAVE.CPP」の構造が悪いぞ。 (SRレジスタ一個で、済むんだからさぁ) で、残ったエラーが一個。
略 e.o psp/psp_menu.o psp/emu_config.o psp/psp_cfg_file.o psp/emu_cheat.o psp/emu_s tate.o psp/psp_bitmap.o psp/psp_data.o lib/libz.a lib/libpng.a lib/unziplib.a - lc -nostartfiles -Wl,-Ttext=0x08900000 -o dgen.out > dgen.map mdcore/mem.o: In function `md::misc_writebyte(unsigned int, unsigned int)': mem.cpp:(.text+0x494): undefined reference to `m68k_clks_left' mem.cpp:(.text+0x494): relocation truncated to fit: R_MIPS_GPREL16 against `m68k _clks_left' mem.cpp:(.text+0x5d4): undefined reference to `m68k_clks_left' mem.cpp:(.text+0x5d4): relocation truncated to fit: R_MIPS_GPREL16 against `m68k _clks_left' mem.cpp:(.text+0x6a0): undefined reference to `m68k_clks_left' mem.cpp:(.text+0x6a0): relocation truncated to fit: R_MIPS_GPREL16 against `m68k _clks_left' mdcore/mem.o: In function `md::misc_writeword(unsigned int, unsigned int)': mem.cpp:(.text+0x1300): undefined reference to `m68k_clks_left' mem.cpp:(.text+0x1300): relocation truncated to fit: R_MIPS_GPREL16 against `m68 k_clks_left' mem.cpp:(.text+0x1400): undefined reference to `m68k_clks_left' mem.cpp:(.text+0x1400): relocation truncated to fit: R_MIPS_GPREL16 against `m68 k_clks_left' collect2: ld returned 1 exit status make: *** [dgen.out] Error 1
要するに、`m68k_clks_left'がないって事です。MUSASI2.0Aにはありますが、 MUSASI3.3にはありません。
MUSASI2.0A「m68kcpu.h」は、 /* Use up clock cycles. * NOTE: clock cycles used in here are 99.9% correct for a 68000, not for the * higher processors. */ #define USE_CLKS(A) m68k_clks_left -= (A)
MUSASI3.3「m68kcpu.h」は /* ---------------------------- Cycle Counting ---------------------------- */ #define ADD_CYCLES(A) m68ki_remaining_cycles += (A) #define USE_CYCLES(A) m68ki_remaining_cycles -= (A) #define SET_CYCLES(A) m68ki_remaining_cycles = A #define GET_CYCLES() m68ki_remaining_cycles #define USE_ALL_CYCLES() m68ki_remaining_cycles = 0
で、いかにもこの辺が怪しいし、ソース見た限りでは、 「m68k_clks_left」→「m68ki_remaining_cycles」に単純に置き換えても良さそうです。 名前は「68が実行すべき残りサイクル」でしょうし。 clockで検索してもこの辺しかないから、この辺の事は間違いないようです。 で、「m68kcpu.c」を検討してOKっぽいんで、書き換えました。 対象ファイルは「md.h」と「mem.cpp」と「mdfr.cpp」です。 後でクロックの流れを仔細に再検討する必要があるかも知れません。
で、早速PSPに転送して、チェックしてみた。 MUSASI2.0AからMUSASI3.3に変更したら、 (うちのはGCC4.0.0) 5fpsグライ性能ダウンしてます。3fpsぐらいの誤差を見積もってです。 まあ、1STコンパイルだから、コンパイル時の68kの設定が悪いのかも知れないけど、 (例えば必要のない68020をインクルードしてるとか) ちょっと見てないです。今日は遅いから明日にします。 でも、早くなるとおもったのにぃ。
バーニングフォースは地面の位置が下に下がって遊びにくくなりました。 (一時期、Win版のGensがそういう状態になりましたね。今は完璧に直ってますが。) やっぱ、タイミング違うのかなあ。 とりあえず、チェックした、他のソフトは重くなったぐらいで動作には変化なし。 「BF03チェック」 この前(MUSASI2.0A/GCC4.0.0)
OFF79~80fps
補間付5512kHz72~73fps
補間付11025kHz70fps
22050kHz65~66fps
44100kHz60~61fps
今日(MUSASI3.3/GCC4.0.0)
OFF69fps-10~-11
補間付5512kHz63fps-9~-10
補間付11025kHz61~62fps-8~9
22050kHz57~58fps-8
44100kHz50~51fps-10
ね、重くなってる。 げげ、10fpsも重くなるとは、思わなかった。 以下は雑談で読む価値あんまない。と思う。
■雑談:だって今、1Gのメモカ6千円台だってさ。 半年前は、1万切って安くなったなあって思ったけど。 (2年前は9万だったらしい。たぶん1GのCFかなんかだと思うが。) 8Gや32Gのメモカが買える値段になる頃には、 1Gのメモカ在庫処分で千円で投売りされたって、管理人驚かないな。 それは今までの歴史が証明してるでしょ?少なくとも2年以内にはそうなりそうじゃん。 1Gあれば無圧縮のCD音声入れたって(MP3で負荷がかかるかも知れないから) 2つぐらい、入るもんね。(全部使い切ってないから) メガCDのタイトルそんなにないんだしさ。(日本では全部で数十タイトルしかない)
■雑談:「680x0」にはFラインエミュレーターとAラインエミュレーターという割り込みの仕組みがある。 これは、ハードウェアーレベルの割り込み。 「680x0」には「0xA???」と「0xF???」で始まる命令はない。このどちらかが、 初めにあると自動的に(確かマスクは出来るが)割り込みが発生。 「???」の番号のベクタ(これは予め特定メモリにアドレスを登録しておく)に登録してあるアドレスに、 ジャンプしてくれる。 これは「Z80」でいえば、RST38Hと同じ仕組み。 (RST38HはIMモード(割り込みモード、普通は一番単純な「IM0」)に関係なく使えたよな、確か) このベクタはソフトウェアーで使ってもいいし、予め特定の番号のベクタをハードウェアーで設計しておけば、 68系はメモリをハードウェアー設計次第で、8086系のポートの様にも使えるため、 ソフトウェアーで割り込みを発生させポートを叩く仕組みが簡単にできる。 「おい、何の話だ?俺様にはチンプンカンプンだ!」って君。要するに、メガドラのラスタ割り込みは、 この仕組みを利用している。だからハードウェアー設計上、当時は68系しかありえなかった。 まあ、アイレムだけは86でがんばってたけどさぁ。当時はセガもナムコもコナミも68系だし、 ファミコンだってスーファミだって68系に近い(けど遠い)メモリ型だし、 GBのZ80に至っては(シャープが)ハードウェアーレベルで、カスタマイズされてる。 (一部の命令を潰して、専用命令を配置) メガドラ、カートリッジの先頭の256バイト(68的にはもっと使える)は、要するにベクターで、 ハードウェアーのベクターが配置されている。正確には((256バイト/4)-2)。はじめの2つは特殊。 で64個。ソフトウェアーのベクターならそれ以降もつかえるので、IPLをずらしてあるソフト (電波新聞社マイコンソフトのアフターバーナーⅡとか)もあるが、どうせゲームでそんなに 沢山ベクター要らないので、実は単なる容量の無駄。
雑日記。(2006-01-24) ■別館にミラーを配置。 昨日までのコンテンツは、別館のミラーにも配置した。 <アドレス:http://psp.nukenin.jp/MIRROR/index.html> アメブロが混んでる時間帯(17:00頃と夜中)に、読みたければ、こちらをどうぞ。