reman3/Rayman_X/cpa/tempgrp/SND/src/sndreal.c

184 lines
4.6 KiB
C

/*
//////////////////////////////////////////////////////
// SNDREAL.CXX - Librairie SOUNDxd version 2.0 //
//////////////////////////////////////////////////////
// Fonctions de gestion des pseudo-reels //
//////////////////////////////////////////////////////
*/
#include "SND\snddef.h"
#include "SNDinc.h"
#ifdef U64
#include <ultra.h>
#else
#ifdef PSX
#include <stddef.h>
#include <libgte.h>
#else
#include <math.h>
#endif
#endif
#include "sndvect.h"
/*---------------------------------------------------------*/
/* MulRealRealSnd: multiplication exacte de 2 SndReal*/
/* Entrees:r1,r2=reels à multiplier*/
/* Sortie:resultat (r1*r2)*/
/*--------------------------------------------------------*/
SndReal SND_CALL SND_fn_rMulRealRealSnd(SndReal r1,SndReal r2)
{
unsigned long r1p,r2p,t1,t2,t3,t4,r3p;
r1p=abs(r1);
r2p=abs(r2);
if ((r1p<0x800) && (r2p<0x800) && (r1p>0xFF) && (r2p>0xFF))
return ((r1>>8)*(r2>>8));
if (r1p<0x7F)
return ((r1 * (r2>>8))>>8);
if (r2p<0x7F)
return ((r2 * (r1>>8))>>8);
t1=(r1p & 0xFFFF) * (r2p & 0xFFFF);
t2=(r1p & 0xFFFF) * (r2p>>16);
t3=(r1p>>16) * (r2p & 0xFFFF);
t4=(r1p>>16) * (r2p >>16);
r3p=(t1>>16)+t2+t3+(t4<<16);
if ((r1<0)^(r2<0))
return (SndReal)(0-r3p);
else
return (SndReal)r3p;
}
/*---------------------------------------------------------*/
/* MulRealRealQuickSnd: multiplication rapide de 2 SndReal*/
/* Entrees:r1,r2=reels à multiplier*/
/* Sortie:resultat (r1*r2)*/
/* Valide ssi -abs(ri)>0x800; octet de poid faible non valide*/
/*--------------------------------------------------------*/
SndReal SND_CALL SND_fn_rMulRealRealQuickSnd(SndReal r1,SndReal r2)
{
return ((r1>>8)*(r2>>8));
}
/*---------------------------------------------------------*/
/* SqrtRealSnd: racine carre d'un SndReal*/
/* Entrees:r dont il faut extraire la racine*/
/* Sortie:racine carre de r*/
/*--------------------------------------------------------*/
SndReal SND_CALL SND_fn_rSqrtRealSnd(SndReal r)
{
#ifdef U64
return M_DoubleToRealSnd(sqrtf(M_RealToDoubleSnd(r)));
#else
#ifdef PSX
return M_DoubleToRealSnd(csqrt(M_RealToDoubleSnd(r)));
#else
return M_DoubleToRealSnd(sqrt(M_RealToDoubleSnd(r)));
#endif
#endif
}
/*---------------------------------------------------------*/
/* DivRealRealSnd: division d'un SndReal par un autre SndReal*/
/* avec peut de precision (1/65000 à 1/256)*/
/* Entrees:r1=dividente*/
/* r2=diviseur*/
/* Sortie:resultat de r1/r2*/
/*--------------------------------------------------------*/
SndReal SND_CALL SND_fn_rDivRealRealQuickSnd(SndReal r1,SndReal r2)
{
/*il faut retourner 2^16*r1/r2, c.a.d.*/
/* r1 !0 7f !80 !8000 !800000 */
/*r2 ! ! ! ! */
/*------+----------------------------------------*/
/*0 7f ! r1<<16 ! ? !r2>>16 */
/*80 ! . . !r1<<8 !.*/
/*8000 ! . . !r1<<8 !.*/
/*800000! . . !r1<<8 !.*/
if (SND_fn_rAbsRealSnd(r1)<0x8000)
{/*r1 suffisament petit*/
snd_assert(r2);
/*r2 null -> division by zero*/
return ((r1<<16)/r2);
}
if (SND_fn_rAbsRealSnd(r1)<0x800000)
{/*r1 moyen*/
snd_assert(r2>>8);/* trop grand e=ecart entre r1 et r2*/
return ((r1<<8)/(r2>>8));
}
/*r1 grand*/
if (SND_fn_rAbsRealSnd(r2)>0x8000)
{/*r2 grand*/
snd_assert(r2>>8);
return ((r1/(r2>>8))<<8);
}
/*vaillle que vaille*/
snd_assert(r2);
return (r1/r2)<<16;
}
/*---------------------------------------------------------*/
/* DivRealRealSnd: division d'un SndReal par un autre SndReal*/
/* avec precision */
/* Entrees:r1=dividente*/
/* r2=diviseur*/
/* Sortie:resultat de r1/r2*/
/*--------------------------------------------------------*/
SndReal SND_CALL SND_fn_rDivRealRealSnd(SndReal r1,SndReal r2)
{
#ifdef PSX
return SND_fn_rDivRealRealQuickSnd(r1,r2);
#else
/*il faut retourner 2^16*r1/r2, c.a.d.*/
return M_DoubleToRealSnd(
(float)r1
/(float)r2);
#endif
}
/*-----------------------------------*/
/* Valeur absolu*/
/*-----------------------------------*/
SndReal SND_CALL SND_fn_rAbsRealSnd(SndReal r)
{
return abs(r);
}
/*------------------------------------------------*/
/* Calcul rapide et approche de sqrt(a^2+b^2+c^2)*/
/*------------------------------------------------*/
SndReal SND_CALL SND_fn_rPseudoNormeRealSnd(SndReal r1,SndReal r2,SndReal r3)
{
SndVector v;
v.x=r1;
v.y=r2;
v.z=r3;
return SND_fn_rPseudoNormeVectorSnd(&v);
}
void SND_CALL SND_fn_vSndRealTwinToSndReal(SndRealTwin rtwin,SndReal* pr1,SndReal* pr2)
{
if (pr1)
*pr1=(rtwin>>16)<<8;
if (pr2)
*pr2=(rtwin<<16)>>8;
}
SndRealTwin SND_CALL SND_fn_rtSndRealToSndRealTwin(SndReal r1,SndReal r2)
{
snd_assert(r1<M_DoubleToRealSnd(127.0));snd_assert(r2<M_DoubleToRealSnd(127.0));
return ((r1<<8)&0xFFFF0000) | ((r2>>8)&0xFFFF);
}