Merge pull request #13706 from hrydgard/vfpu-sincos-double-compat

Add back the old implementation of vfpu_sin/cos/sincos.
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2020-11-24 09:08:50 +01:00
commit 51b213e689
6 files changed
+103 -27

No files matched your search

+1
View File
@@ -75,6 +75,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
CheckSetting(iniFile, gameID, "MemstickFixedFree", &flags_.MemstickFixedFree);
CheckSetting(iniFile, gameID, "DateLimited", &flags_.DateLimited);
CheckSetting(iniFile, gameID, "ReinterpretFramebuffers", &flags_.ReinterpretFramebuffers);
CheckSetting(iniFile, gameID, "DoublePrecisionSinCos", &flags_.DoublePrecisionSinCos);
}
void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) {
+1
View File
@@ -73,6 +73,7 @@ struct CompatFlags {
bool MemstickFixedFree;
bool DateLimited;
bool ReinterpretFramebuffers;
bool DoublePrecisionSinCos;
};
class IniFile;
+83
View File
@@ -895,3 +895,86 @@ float vfpu_rsqrt(float a) {
return val.f;
}
float vfpu_sin_single(float angle) {
angle -= floorf(angle * 0.25f) * 4.f;
if (angle == 0.0f || angle == 2.0f) {
return 0.0f;
} else if (angle == 1.0f) {
return 1.0f;
} else if (angle == 3.0f) {
return -1.0f;
}
angle *= (float)M_PI_2;
return sinf(angle);
}
float vfpu_cos_single(float angle) {
angle -= floorf(angle * 0.25f) * 4.f;
if (angle == 1.0f || angle == 3.0f) {
return 0.0f;
} else if (angle == 0.0f) {
return 1.0f;
} else if (angle == 2.0f) {
return -1.0f;
}
angle *= (float)M_PI_2;
return cosf(angle);
}
void vfpu_sincos_single(float angle, float &sine, float &cosine) {
angle -= floorf(angle * 0.25f) * 4.f;
if (angle == 0.0f) {
sine = 0.0f;
cosine = 1.0f;
} else if (angle == 1.0f) {
sine = 1.0f;
cosine = 0.0f;
} else if (angle == 2.0f) {
sine = 0.0f;
cosine = -1.0f;
} else if (angle == 3.0f) {
sine = -1.0f;
cosine = 0.0f;
} else {
angle *= (float)M_PI_2;
#if defined(__linux__)
sincosf(angle, &sine, &cosine);
#else
sine = sinf(angle);
cosine = cosf(angle);
#endif
}
}
float vfpu_sin_double(float angle) {
return (float)sin((double)angle * M_PI_2);
}
float vfpu_cos_double(float angle) {
return (float)cos((double)angle * M_PI_2);
}
void vfpu_sincos_double(float angle_f, float &sine, float &cosine) {
double angle = (double)angle_f * M_PI_2;
#if defined(__linux__)
double d_sine;
double d_cosine;
sincos(angle, &d_sine, &d_cosine);
sine = (float)d_sine;
cosine = (float)d_cosine;
#else
sine = (float)sin(angle);
cosine = (float)cos(angle);
#endif
}
float (*vfpu_sin)(float);
float (*vfpu_cos)(float);
void (*vfpu_sincos)(float, float&, float&);
void InitVFPUSinCos(bool useDoublePrecision) {
vfpu_sin = useDoublePrecision ? vfpu_sin_double : vfpu_sin_single;
vfpu_cos = useDoublePrecision ? vfpu_cos_double : vfpu_cos_single;
vfpu_sincos = useDoublePrecision ? vfpu_sincos_double : vfpu_sincos_single;
}
+12 -26
View File
@@ -35,44 +35,29 @@ inline int Xpose(int v) {
#endif
// The VFPU uses weird angles where 4.0 represents a full circle. This makes it possible to return
// exact 1.0/-1.0 values at certain angles. We get close enough for #2921 and #12900 by computing
// things in double precision, multiplying the input by pi/2.
// exact 1.0/-1.0 values at certain angles. We currently just scale, and special case the cardinal directions.
//
// Stepping down to [0, 2pi) helps, but we also check common exact-result values.
// TODO: cos(1) and sin(2) should be -0.0, but doing that gives wrong results (possibly from floorf.)
//
// We also try an alternative solution, computing things in double precision, multiplying the input by pi/2.
// This fixes #12900 (Hitman Reborn 2) but breaks #13705 (Cho Aniki Zero) and #13671 (Hajime no Ippo).
// #2921 is still fine. So the alt solution (vfpu_sin_double etc) are behind a compat flag.
//
// A better solution would be to tailor some sine approximation for the 0..90 degrees range, compute
// modulo manually and mirror that around the circle. Also correctly special casing for inf/nan inputs
// and just trying to match it as closely as possible to the real PSP.
//
// Stepping down to [0, 2pi) helps, but we also check common exact-result values.
// TODO: cos(1) and sin(2) should be -0.0, but doing that gives wrong results (possibly from floorf.)
// Messing around with the modulo functions? try https://www.desmos.com/calculator.
inline float vfpu_sin(float angle) {
return (float)sin((double)angle * M_PI_2);
}
inline float vfpu_cos(float angle) {
return (float)cos((double)angle * M_PI_2);
}
extern float (*vfpu_sin)(float);
extern float (*vfpu_cos)(float);
extern void (*vfpu_sincos)(float, float&, float&);
inline float vfpu_asin(float angle) {
return asinf(angle) / M_PI_2;
}
inline void vfpu_sincos(float angle_f, float &sine, float &cosine) {
double angle = (double)angle_f * M_PI_2;
#if defined(__linux__)
double d_sine;
double d_cosine;
sincos(angle, &d_sine, &d_cosine);
sine = (float)d_sine;
cosine = (float)d_cosine;
#else
sine = (float)sin(angle);
cosine = (float)cos(angle);
#endif
}
inline float vfpu_clamp(float v, float min, float max) {
// Note: NAN is preserved, and -0.0 becomes +0.0 if min=+0.0.
return v >= max ? max : (v <= min ? min : v);
@@ -230,3 +215,4 @@ int GetVectorOverlap(int reg1, VectorSize size1, int reg2, VectorSize size2);
bool GetVFPUCtrlMask(int reg, u32 *mask);
float Float16ToFloat32(unsigned short l);
void InitVFPUSinCos(bool useDoublePrecision);
+3 -1
View File
@@ -44,6 +44,7 @@
#include "Core/HDRemaster.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "Core/MIPS/MIPSVFPUUtils.h"
#include "Core/Debugger/SymbolMap.h"
#include "Core/Host.h"
#include "Core/System.h"
@@ -66,7 +67,6 @@
#include "Common/LogManager.h"
#include "Common/ExceptionHandlerSetup.h"
#include "Core/HLE/sceAudiocodec.h"
#include "GPU/GPUState.h"
#include "GPU/GPUInterface.h"
#include "GPU/Debugger/RecordFormat.h"
@@ -287,6 +287,8 @@ bool CPU_Init() {
// likely to collide with any commercial ones.
coreParameter.compat.Load(discID);
InitVFPUSinCos(coreParameter.compat.flags().DoublePrecisionSinCos);
HLEPlugins::Init();
if (!Memory::Init()) {
// We're screwed.
+3
View File
@@ -808,3 +808,6 @@ ULKS46087 = true
# ULJM05533 = true
# NPJH50006 = true
[DoublePrecisionSinCos]
# Hitman Reborn Battle Arena 2 (#12900)
ULJS00218 = true