#? お魚さんmemcpyの謎。(2006-02/20) | //www.旧型、PSP開発幼稚園.game.jp/(本館)

#? お魚さんmemcpyの謎。(2006-02/20)

#? お魚さんmemcpyの謎。(2006-02/20)

今、解らないのが「お魚さんmemcpyの謎」

「src/loadrom.c」というプログラム。(日本語で注記した点以外重要な点はない。これを詳しく読んでも意味はない。)
int funcUnzipCallback(int nCallbackId,省略,unsigned long ulUserData) { const char *pszFileName; const unsigned char *pbData; switch(nCallbackId) { case UZCB_FIND_FILE: pszFileName = (const char *)pData; switch( ulUserData ){ case 0: { char path[MAXPATH]; memcpy( path, (unsigned char*)pszFileName, MAXPATH);←ここは「UNZIPLIB.A」のmemcpyを使う。 if( !smdchk(path) ){ return UZCBR_PASS; }else if( ulExtractSize < 0x400000 ){ char patch[MAXPATH]; fsize=0; return UZCBR_OK; }else{ return UZCBR_CANCEL; } } break; } break; case UZCB_EXTRACT_PROGRESS: pbData = (const unsigned char *)pData; switch( ulUserData ){ case 0: { char *p=(void *)ulCurrentPosition; _memcpy( (void *)&cart_rom[fsize], (void *)pData, ulDataSize);←ここは「_CLIB.C」の_memcpyを使う。 fsize += ulDataSize; } break; 以下略
長いコメントは省略した。 どおして、同じ、スイッチ内で、違うmemcpyを呼んでるんだ? 中身はこう。
「UNZIPLIB.A」のmemcpy
void* ___memcpy(void *buf1, const void *buf2, int n) //←この'const'はあくまでこの関数内で、値が変わらないだろう事を保証してるに過ぎない。念のため。 { while(n-->0) ((unsigned char*)buf1)[n] = ((unsigned char*)buf2)[n]; return buf1;                    // ←さしあたり使用してないので、あってもなくても「src/loadrom.c」にとっては、同じ }
「_CLIB.C」のmemcpy
void _memcpy(void *d, void *s, unsigned long n) { /* このコメント内は書式が違うだけで、(考え方は)上とほぼ同じもの。(但しコードは変わるはず) GCC400なら、「(*(((unsigned char *)d++))=*(((unsigned char *)s++)));」と書かないと、コンパイルが、 通らない。( -std=gnu99 とかいうオプションの「数字(年度)」を古くすれば通るのかも知れない。) for (; n>0; n--) { (*(((unsigned char *)d)++)=*(((unsigned char *)s)++)); } */ if( (unsigned int)d & 3 || (unsigned int)s & 3 || n & 3 ){ char *g=s; char *p=d; while(n--)*p++=*g++; }else{ unsigned int *g=s; unsigned int *p=d; n>>=2; while(n--)*p++=*g++; } }
「UNZIPLIB.A」のmemcpyは、void型のポインタを返しているが、お魚さんでそれを利用している場所は、 一ヶ所もないので、お魚さんにとっては、あってもなくても同じ。(UNZIPLIB.A内では違うかもしれん) 「_CLIB.C」のmemcpyはalignを考えて転送してるが、もしこの問題がないのならば(ないと踏んでいる) 基本的に(「UNZIPLIB.A」のmemcpyと「_CLIB.C」の_memcpyは)動作はまったく一緒。
で、「src/loadrom.c」で、上に揚げた部分の「_memcpy」を「memcpy」に変えて、コンパイルしてみると、 なんとコンパイルが通らない。 なんで?? (管理人、C++なら納得するよ、引数違うもん。でもこれは純粋なC言語だよ。ワーニングが出てて、 仮にキャストされないとしても(されるに決まってるが)リンク出来ないのは明らかにおかしい。)
標準の場合 $ make psp-gcc-4.0.0 -O3 -mgp32 -mlong32 -msingle-float -mabi=eabi -c src/loadrom.c -o obj/loadrom.o src/loadrom.c: In function 'funcUnzipCallback': src/loadrom.c:59: warning: incompatible implicit declaration of built-in functio n 'memcpy' ld -O0 obj/startup.o obj/error.o obj/io.o obj/cpu/m68kcpu.o obj/cpu/m68kops.o ob j/cpu/m68kopac.o obj/cpu/m68kopdm.o obj/cpu/m68kopnz.o obj/cpu/z80.o obj/sound/f m.o obj/sound/sn76496.o obj/sound/sound.o obj/render.o obj/system.o obj/vdp.o ob j/loadrom.o obj/genesis.o obj/mem68k.o obj/membnk.o obj/memvdp.o obj/memz80.o ob j/_clib.o obj/pg.o obj/main.o obj/main_sub.o obj/main_text.o obj/main_sound.o ob j/menu.o unziplib.a -M -Ttext 8900000 -q -o mdpsp.out > main.map ./outpatch.exe mdpsp.out mdpsp.outp "USERPROG" successed filesize:00158497 modulename:000CCEA4 scemoduleinfo:000F7967 ./elf2pbp.exe mdpsp.outp "MEGADRIVE0.22A04A(for JIKKEN)" ICON0.PNG Elf2Pbp v0.3 - loser 2005 +PNG successfully generated pbp file
ワーニングが出るものの。コンパイル成功EBOOT.PBP作成。OK.
「src/loadrom.c」で、上に揚げた部分の「_memcpy」を「memcpy」に変えた場合。 $ make psp-gcc-4.0.0 -O3 -mgp32 -mlong32 -msingle-float -mabi=eabi -c src/loadrom.c -o obj/loadrom.o src/loadrom.c: In function 'funcUnzipCallback': src/loadrom.c:59: warning: incompatible implicit declaration of built-in functio n 'memcpy' src/loadrom.c:93: warning: incompatible implicit declaration of built-in functio n 'memcpy' ld -O0 obj/startup.o obj/error.o obj/io.o obj/cpu/m68kcpu.o obj/cpu/m68kops.o ob j/cpu/m68kopac.o obj/cpu/m68kopdm.o obj/cpu/m68kopnz.o obj/cpu/z80.o obj/sound/f m.o obj/sound/sn76496.o obj/sound/sound.o obj/render.o obj/system.o obj/vdp.o ob j/loadrom.o obj/genesis.o obj/mem68k.o obj/membnk.o obj/memvdp.o obj/memz80.o ob j/_clib.o obj/pg.o obj/main.o obj/main_sub.o obj/main_text.o obj/main_sound.o ob j/menu.o unziplib.a -M -Ttext 8900000 -q -o mdpsp.out > main.map obj/loadrom.o: In function `funcUnzipCallback': loadrom.c:(.text+0x5ec): undefined reference to `memcpy' make: *** [mdpsp.out] Error 1 一つ目のワーニングはさっきと同じもの。 ワーニングが出て。コンパイルは出来るが、リンカでこける(SYS1と同じ状態) EBOOT.PBP作成出来ない。
これが噂の「遠い近い問題」なんだろうか。この件が解決しない限り、SYS1は出来ないし、 ソースのそこらじゅうに、似たようなルーチンをちりばめなくてはならなくなる。
しかし、何で同じスイッチ内で、こんな事がおきるのだ?詳しく調査する必要がある。
要は現状のSYS1がEBOOT.PBPにならない問題を解りやすく纏めてみた。不思議でしょ? (2006-02/20、19:33)
現状別館にあがってる、「MD022A04A」で全く同じ実験が出来る。 (だってSYS1ばっかやって、そっちは進んでないもん)
ちなみに、MAPファイルを出力させ、比較してみたが、全く同じものを吐いた。 memcpyと_memcpyのエントリーは、(MAPファイルだよ)
.text 0x000000000898b9c8 0x2ec obj/_clib.o 0x000000000898b9f0 _strcat 0x000000000898ba2c _strncpy 0x000000000898bbd4 _memcpy   ←これが_CLIB.C版 0x000000000898bad4 _memset 0x000000000898ba64 _strchr 0x000000000898b9c8 _strcpy 0x000000000898bb5c _memcmp 0x000000000898bc48 _strrchr 0x000000000898baa8 _strlen
.text 0x0000000008991550 0x4d4 unziplib.a(zlibFileMemory.o) 0x000000000899167c ___ftell 0x0000000008991718 _(float, long double,...)(...) 0x00000000089917c8 ___strcat 0x0000000008991638 ___fopen 0x000000000899184c ___itoa 0x00000000089916e0 ___fread 0x0000000008991684 ___fseek 0x00000000089916d8 ___ferror 0x0000000008991550 ___memcpy   ←これがUNZIPLIB.A版 0x0000000008991674 ___fwrite 0x0000000008991584 ___strcmp 0x00000000089915c8 ___strlen 0x00000000089916b4 ___fclose 0x0000000008991720 ___calloc 0x00000000089915f4 ___strcpy 0x000000000899175c ___strrev 0x0000000008991948 ___itoa32 0x0000000008991728 ___malloc
■ ■