#11MATH.H使ったら駄目なんだ。(多分)(2006-02/20)
■
管理人の訳解からんエラー達。何度も掲載してもしょうもないから、昨日も沢山出てた。
リンカででる、fなんとかって奴。
cpuexec.c:(.text+0x2014): undefined reference to `__extendsfdf2'
cpuexec.c:(.text+0x2028): undefined reference to `__gedf2'
cpuexec.c:(.text+0x2138): undefined reference to `__fixsfdi'
../../../../../newlib/libc/stdlib/dtoa.c:511: undefined reference to `__muldf3'
../../../../../newlib/libc/stdlib/dtoa.c:513: undefined reference to `__fixdfsi'
../../../../../newlib/libc/stdlib/dtoa.c:514: undefined reference to `__floatsidf'
../../../../../newlib/libc/stdlib/dtoa.c:514: undefined reference to `__subdf3'
../../../../../newlib/libc/stdlib/dtoa.c:518: undefined reference to `__adddf3'
../../../../../newlib/libc/stdlib/dtoa.c:518: undefined reference to `__ltdf2'
要するにこんなの。
これって、もしかして、浮動小数点関係?と思い。SYS1全体を「sin(」で検索。
(「sin」、や「cos」では、他の物が引っかかる。「nam[cos]1」とか)
「src/sound/filter.c」が引っかかる。
何故、超越関数を検索したかというと、sin(int)なんて事はありえないでしょ?
sin(float)か、sin(double)の筈。従ってsin()って書いたら、標準のmath.hが使われる筈。
因みに、現状のSYS1はdoubleを総べて、排除してある。標準でもfloatカットマクロが、
PSP_MAME04のソース入ってはいたが、やっぱ怪しいので使わないように変更した。
■
double→floatに変更すると、確かにおかしくなる、可能性はある。
MAME0.82ベースで作った管理人版の「F3専用エミュ」はこれが原因で、
一面の途中で珠に少し(2秒ぐらい?)止まったりした記憶がある。
(記憶違いで、これが原因ではないかも知れないが。)
が、管理人が、もっとずっと昔のMAMEをベースにした「SYS1専用エミュ」では、
「double→floatに変更」しても、全然全く問題なく動いていた。
この「double→floatに変更」がMAMEで問題になるのは、主に「timer.h」を周辺とした、CPU関係の
時間管理の精度の話だからな。それ以外の変更に関してはこんな高精度。
はなから要らないので、論外だ。
(例えばFM音源とか、その他雑用とか、doubleの精度を要求する訳がない。但しFM音源でも
内蔵タイマーやMAMEタイマーとの兼ね合いは別問題だからな。)
現状の「double→floatに変更」してある「timer.h」の一部。
#define MAME_TIME_TO_CYCLES(cpu,t) ((t).seconds * cycles_per_second[cpu] + (t).subseconds / subseconds_per_cycle[cpu])
#define MAME_TIME_IN_CYCLES(c,cpu) (make_mame_time((c) / cycles_per_second[cpu], (c) * subseconds_per_cycle[cpu]))
/*-------------------------------------------------
timing macros
-------------------------------------------------*/
extern float cycles_to_sec[];
extern float sec_to_cycles[];
#define TIME_IN_HZ(hz) (1.0 / (float)(hz))
#define TIME_IN_CYCLES(c,cpu) ((float)(c) * cycles_to_sec[cpu])
#define TIME_IN_SEC(s) ((float)(s))
#define TIME_IN_MSEC(ms) ((float)(ms) * (1.0 / 1000.0))
#define TIME_IN_USEC(us) ((float)(us) * (1.0 / 1000000.0))
#define TIME_IN_NSEC(us) ((float)(us) * (1.0 / 1000000000.0))
// c must be greater then 1000pF to use this function
// r is in Ohms. c is in Farads.
#define TIME_OF_74LS123(r,c) (0.45 * (float)(r) * ((float)(c))いらねー。
#define TIME_NOW (0.0)
#define TIME_NEVER (1.0e30) ←ここはdoubleの場合だから、変えなきゃいかんのか。
それともこのままでいいのかな、よくわかんない。floatではいくつぐらいが、適当なでかい数なんだろ。
ここがオーバーフローで、「管理人版F3」が上手くいかなかった可能性はあるな。
#define TIME_TO_CYCLES(cpu,t) ((int)((t) * sec_to_cycles[cpu]))
typedef struct _mame_timer mame_timer;
ナノ秒の単位でどうこうするのは、現状では厳しいかもしれん。
■
初めて見た人は、「えええええ何これ。なんでこんな頭の悪い事してんの?
そもそも浮動少数点なぞ、使うなよ。int組み合わせてなんとかしろ。」
と思うだろう。管理人もそう思う、だが、外のソース。特にCPU(CPUEXEC、CPUINTRF)、
割り込み(INT)、メモリ関連(MEMORY)。その辺を、見るとMAMEの実装では確かに楽だから仕方が
ないかなって思えてくる。
(趣旨と外れるが、この方式は割り算を排除出来る利点が、ある。分母が定数ならば、逆数にして掛けて
しまえば、「割り算→掛け算」になり、当時のCPUでは速かった。要は「fff/3.0」は「fff * (1.0/3.0)」
という事。3.0は定数、fffはどっかの式。)
大昔のMAMEはこういう方式ではなかった。現実のMAMEを実行するCPUも1997年は、Pentiumに
毛の生えたようなCPUだったし、その頃は、現実的には「K6」が主流で、「K6」は「PenMMX」に比べて、
不動少数点演算に弱い。
その頃のMAMEのCPUコアを移植すれば、この問題は解決する可能性がある。具体的には、
MAME0.28以前のVERだよ。管理人の記憶が間違いなければこの頃だ。ちょっと調べてみるかな。
0.1 mame01.zip, 205 kB 1997-02-05 ←この頃は、管理人。MAMEが実行できるPCは持ってなかった。
唯一可能性があったのは、セガの「TERA DRIVE」これは286PCで(仮に出来たとしても実行速度が)
話にならん。仕方がないので、MAME為に1997年の夏頃、30万グライ出してPCを買った。
(生まれて初めて自作PCを作った。初めてだから変な妥協はせず、高くついた)
まだ子供だったから、痛い出費だった。貯金はみーーんな、なくなっちゃったから、FDの一枚も買えず、
秋葉の只FDを何十枚も仕入れて凌いだ。(MAMEとその他(汗)を持ってくるのにFDが必要だった。)
(この頃2DDのFDを只でまいてた、この年の後半は2HDにグレードアップしたので、人気で手に
入りにくくなった。ほら、青いFDの「Quantum Disk Manager」の事だよ。2HD版は黒。)
モニター(ディスプレイ)も総額30万グライではとても買えず、「TERA MONITOR」を流用した。
標準では800x600までなので、開発にはきついから、「1024x768i@130Hz」グライで使用していた。
インターレースだが、ちらつきは見えない。W95標準の「NEC 3Dg」のプロファイルを改造すれば、
そういう離れ技が出来た。
当時TEST REPORTとかいって、(プログラムが良く解からないんだから、それぐらいしか出来ない)
英語でNicolaさんにe-mailを出したり、返事がきたりしてたが、
「be sorry my cheap english that, ...」とか書いてある奴。
まさか子供から来てるとは、思いもつかなかったろうな。多分。(管理人、今でも英語は怪しいです。)
0.26 mame026b.zip, 345 kB mame026s.zip, 731 kB 1997-07-14
0.261 mame261b.zip, 364 kB mame261s.zip, 722 kB 1997-07-18
0.27 mame027b.zip, 392 kB mame027s.zip, 858 kB 1997-08-10
0.28 mame028b.zip, 493 kB mame028s.zip, 968 kB 1997-09-07 ←良く覚えてないが、
この近辺で、システムが大幅に変わったような記憶がある。
0.29 mame029b.zip, 574 kB mame029s.zip, 1113 kB 1997-10-20
0.30 mame030b.zip, 735 kB mame030s.zip, 1428 kB 1998-01-08
0.31 mame031b.zip, 921 kB mame031s.zip, 1868 kB 1998-04-25
■
いつの間にやら、無駄話全開モードに移行してるんで、話を元にもどして。
とにかく超越関数を検索し、MAMEの「src/sound/filter.c」で、floatのsin()、cos()を使ってる部分を発見、と。
for(i=1;i<=midorder;++i) {
/* number of the sample starting from 0 to (order-1) included */
unsigned n = i + midorder;
/* sample value */
float c = sin(2*M_PI*freq*i) / (M_PI*i);
/* apply only one window or none */
/* float w = 2 - 2*n/(order-1); */ /* Bartlett (triangular) */
/* float w = 0.5 * (1 - cos(2*M_PI*n/(order-1))); */ /* Hanning */
float w = 0.54 - 0.46 * cos(2*M_PI*n/(order-1)); /* Hamming */
/* float w = 0.42 - 0.5 * cos(2*M_PI*n/(order-1)) + 0.08 * cos(4*M_PI*n/(order-1)); */ /* Blackman */
ほら、使ってるだろ。
で、コンパイルな。
filter.c:(.text+0x1f8): undefined reference to `__eqdf2'
filter.c:(.text+0x22c): undefined reference to `__floatsidf'
filter.c:(.text+0x240): undefined reference to `__eqdf2'
filter.c:(.text+0x2f0): undefined reference to `__extendsfdf2'
filter.c:(.text+0x304): undefined reference to `__muldf3'
filter.c:(.text+0x318): undefined reference to `__floatsidf'
filter.c:(.text+0x338): undefined reference to `__muldf3'
filter.c:(.text+0x344): undefined reference to `sin'
filter.c:(.text+0x360): undefined reference to `__muldf3'
filter.c:(.text+0x374): undefined reference to `__divdf3'
filter.c:(.text+0x380): undefined reference to `__truncdfsf2'
filter.c:(.text+0x38c): undefined reference to `__floatsidf'
filter.c:(.text+0x3b0): undefined reference to `__muldf3'
filter.c:(.text+0x3c4): undefined reference to `__divdf3'
filter.c:(.text+0x3d0): undefined reference to `cos'
filter.c:(.text+0x3e4): undefined reference to `__muldf3'
filter.c:(.text+0x3f8): undefined reference to `__adddf3'
filter.c:(.text+0x404): undefined reference to `__truncdfsf2'
filter.c:(.text+0x430): undefined reference to `__floatsidf'
filter.c:(.text+0x454): undefined reference to `__adddf3'
filter.c:(.text+0x46c): undefined referenmake: *** [EBOOT.PBP] Interrupt
ほら、出来ない。
別に[filter.c]自体まったく要らないんだが、(16ビット44100でレンダーしてるのを、デジタルフィルター
かまして、わざわざ音質落としてどおする。MAMEは標準では、わざわざ音質落として出力してるんだよ。
秘密だけどな。管理人は耳だけはいいから、サウンドボード改造して、ハードの問題をなくし、原因を探ったら
ここに辿り付いた経歴がある。まあ、大昔の話だが)
「filter.c」の始めのほう。
#include "filter.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
で、この辺で<math.h>が臭いんじゃないかと、思い始め。
/cygwin/home/を「math.h」で検索。
お魚さんは使ってない。
DGENも外してコンパイル出来た。
(ついでにエンバグ発見。「psp_menu.c」「psp_bitmap.c」の2ヶ所の
「#include "psp_screen.h"」を「#include "pg.h"」にして下さい。これが何時からなのかは、わからない。
もし、別館に挙がってる「A17」のコンパイルが通らなかったら、これ以外はない筈)
つまり、両方とも<math.h>は使ってない。
話が超越関数だけなら、簡単なLIBで回避できる。別館のmoya02に入ってる奴がそれだ。
// *******************************************************************
#define SIN 1
#define COS 2
#define TAN 3
#define EXP 4
#define SINH 5
#define COSH 6
#define TANH 7
#define PI 3.1415926536 // or use atan(1)*4.0
// *******************************************************************
unsigned int sqrtu(unsigned int x)
{
unsigned int r = 0;
int n = 15;
for(n = 15; n >= 0; n--)
{
unsigned int t = r + (1<<n);
if(x >= t << n)
{
x -= t << n;
r |= 2 << n;
}
}
return r >> 1;
}
// *******************************************************************
//
// generate 7 transcendental values with one function
// p = function selector, #define the following:
// SIN 1 COS 2 TAN 3 EXP 4 SINH 5 COSH 6 TANH 7
// n = convergence cutoff, n = 3 is typical,
// higher n gives higher precision, but slower execution
//
float trigfunc(int p, int n, float x)
{
int k;
float r, s, t;
if (p <= 3)
{
r = - x * x; // trig
}
else
{
r = x * x; // hyperbolic
}
s = 4 * n + 2;
for (k = n; k > 0; k--)
{
s = 4 * k - 2 + r/s;
}
switch (p & 3)
{
case 0: t = (s + x)/(s - x); break; // exp
case 1: t = 2 * x * s /(s * s - r); break; // sin, sinh
case 2: t = (s * s + r)/(s * s - r); break; // cos, cosh
case 3: t = 2 * x * s /(s * s + r); break; // tan, tanh
}
return (t);
}
// ********************************************************
こんなんだね。ハイパーボリックも含めて6つ全部使える。高校では半分の3つまでしか教えないが、
あれは6つ纏めて覚えると、暗記しなくてもいいんだよ。六つ書いて真中に「1」を書く。表になってるから、
見ればすぐ対応が解かる仕掛け。数学得意な人は多分みんな知ってる。そんなん、教えてあげないだけ。
■
管理人がGCC400でコンパイルに、一応成功した、
RIN132と、(「src/lib/pngconf.h」のマクロが良く判らんが、多分)
NESTERJ101と、
NESTERJ101、
は、<math.h>を使ってない。
一方、コンパイル成功してない。
PSPGENESISと
NEOPSP05、
は、<math.h>を使ってる。
やっぱり、<math.h>が原因ではないのか?
SYS1から、<math.h>を外してみよう。
■
なんでか知らんが、アメブロ混んでてやりにくいから、オフラインで、勝手に進めるよ。
ここはしばらく更新せん(13:05)
つもりだったけど、500か。すげえな。1kの半分かい。工学的には0.5k[人]って所だな。5.0e2[人]とかな。
おっと、「src/sound/filter.c」でエラーが出た。
owld,&driver_soukobdx,&driver_splatter,&driver_tankfrce,&driver_tankfrcj,&driver
_wldcourt,&driver_ws,&driver_ws89,&driver_ws90,&driver_yokaidko,&driver_youkaidk
" -DHAS_M6809=1 -DHAS_HD63701=1 -DHAS_CUSTOM=0 -DHAS_SAMPLES=0 -DHAS_DAC=1 -DHAS
_YM2151=1 -DHAS_YM2151_ALT=0 -DHAS_NAMCO=1 -DHAS_NAMCO_15XX=0 -DHAS_NAMCO_CUS30=
1 -DHAS_NAMCO_52XX=0 -DHAS_NAMCO_54XX=0 -DHAS_NAMCO_63701X=0 -std=gnu99 -Isrc
-Isrc/includes -Isrc/debug -Isrc/psp -DNDEBUG -mabi=eabi -mgp32 -mlong32 -msin
gle-float -include src/psp/floatonly.h -include src/psp/stdout.h -O3 -fomit-fram
e-pointer -fno-strict-aliasing -Wall -Wno-sign-compare -Wunused -Wpointer-arith
-Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wundef -Wformat-security -
Wwrite-strings -Wdisabled-optimization -Isrc/zlib -c src/sound/filter.c -o obj/
namcos1psp2/sound/filter.o
src/sound/filter.c: In function 'filter_lp_fir_alloc':
src/sound/filter.c:95: warning: implicit declaration of function 'sin'
src/sound/filter.c:95: warning: incompatible implicit declaration of built-in fu
nction 'sin'
src/sound/filter.c:95: error: 'M_PI' undeclared (first use in this function)
src/sound/filter.c:95: error: (Each undeclared identifier is reported only once
src/sound/filter.c:95: error: for each function it appears in.)
src/sound/filter.c:100: warning: implicit declaration of function 'cos'
src/sound/filter.c:100: warning: incompatible implicit declaration of built-in f
unction 'cos'
make: *** [obj/namcos1psp2/sound/filter.o] Error 1
#define MY_PI 3.1415926536 // or use atan(1)*4.0
extern float fcos(float angle);
extern float fsin(float angle);
として「M_PI」→「MY_PI」、「sin()」→「fsin()」、「cos()」→「fcos()」に
しよう。
「moya02」の偽CLIBを、リンクしてあるから大丈夫な筈。
「moya02」で、PSP上できちんと動いた実績があるからな。あれの光源計算は、
こいつでやってる。精度が足りないと、上手く光源計算の方向ベクトルが算出できずに、
真っ白な画面になってしまう。精度が足りてるから、変な絵がちゃんと出てるだろ。
■
-Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wundef -Wformat-security -
Wwrite-strings -Wdisabled-optimization -Isrc/zlib -c src/sound/fm.c -o obj/namc
os1psp2/sound/fm.o
src/sound/fm.c: In function 'init_tables':
src/sound/fm.c:1468: warning: implicit declaration of function 'pow'
src/sound/fm.c:1468: warning: incompatible implicit declaration of built-in func
tion 'pow'
src/sound/fm.c:1469: warning: implicit declaration of function 'floor'
src/sound/fm.c:1469: warning: incompatible implicit declaration of built-in func
tion 'floor'
src/sound/fm.c:1504: warning: implicit declaration of function 'sin'
src/sound/fm.c:1504: warning: incompatible implicit declaration of built-in func
tion 'sin'
src/sound/fm.c:1504: error: 'M_PI' undeclared (first use in this function)
src/sound/fm.c:1504: error: (Each undeclared identifier is reported only once
src/sound/fm.c:1504: error: for each function it appears in.)
src/sound/fm.c:1509: warning: implicit declaration of function 'log'
src/sound/fm.c:1509: warning: incompatible implicit declaration of built-in func
tion 'log'
src/sound/fm.c:1511: warning: incompatible implicit declaration of built-in func
tion 'log'
make: *** [obj/namcos1psp2/sound/fm.o] Error 1
今度は、powとfloorとlogかあ、
どっかから抜いてきてもいいけど、差し当たりexternで誤魔化すか、さっきのfilter.cも
元に戻して、
#include <math.h>を
#include"my_math.h"
に変更しよう。
「my_math.h」の中身は、
#ifndef MY_MATH_H
#define MY_MATH_H
/* my_math.h */
#define M_PI 3.1415926536 // or use atan(1)*4.0
extern float cos(float a);
extern float sin(float a);
extern float pow(float a,float b);
extern float floor(float a);
extern float log(float a);
#endif
とりあえず、これでええじゃろ。
In file included from src/sound/filter.c:5:
src/my_math.h:8: warning: conflicting types for built-in function 'cos'
src/my_math.h:9: warning: conflicting types for built-in function 'sin'
src/my_math.h:10: warning: conflicting types for built-in function 'pow'
src/my_math.h:11: warning: conflicting types for built-in function 'floor'
src/my_math.h:12: warning: conflicting types for built-in function 'log'
make: *** [obj/namcos1psp2/sound/filter.o] Interrupt
こういうワーニング出るけど、ズルしてるんだから仕方がない。
リンカに'-lc'付けないでやったら、出なくなるかもしれん。(現状は-lc付き)
大体さあ、世の中には「PTA」とかいうすばらしいシステムもあるし、
「プレステ」とか言うお家でゲームな機械もあるんだから、
管理人が本物のゲーセンに行って「SYS1」だの「SYS2」だの
遊んだことが、<ピー>なくらい判るだろ。
でもな、「ナムコミュージアム」とか「MAME」とか遊んでると、
管理人、嗅覚が鋭いから、これは絶対に「本物」とは違う。とか、判るんだよ。
(いろいろ証拠があるんだよ)
だから、自作エミュ作りに走るわけ。本当の本物は想像するしかない訳だけど、
少なくとも、「ナムコミュージアム」や「MAME」より本物に近いものを再現せねば、
あかんな。という事だ。エミュ作った事ある奴なら、薄々何の事か判るじゃろ。
(今14:15)