mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
interp: Handle vrot prefixes mostly correctly.
Still some issues with 1/2 results and negate on swizzle.
This commit is contained in:
parent
8fd8dce185
commit
26b1368f7b
2 changed files with 32 additions and 9 deletions
|
@ -1338,23 +1338,45 @@ namespace MIPSInt
|
|||
|
||||
// Generates one line of a rotation matrix around one of the three axes
|
||||
void Int_Vrot(MIPSOpcode op) {
|
||||
// Note: prefixes behave strangely for this.
|
||||
float d[4]{};
|
||||
int vd = _VD;
|
||||
int vs = _VS;
|
||||
int imm = (op >> 16) & 0x1f;
|
||||
VectorSize sz = GetVecSize(op);
|
||||
bool negSin = (imm & 0x10) ? true : false;
|
||||
bool negSin = (imm & 0x10) != 0;
|
||||
int sineLane = (imm >> 2) & 3;
|
||||
int cosineLane = imm & 3;
|
||||
|
||||
float sine, cosine;
|
||||
vfpu_sincos(V(vs), sine, cosine);
|
||||
if (negSin)
|
||||
sine = -sine;
|
||||
float d[4] = {0};
|
||||
if (((imm >> 2) & 3) == (imm & 3)) {
|
||||
if (currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX] == 0x000E4) {
|
||||
vfpu_sincos(V(vs), sine, cosine);
|
||||
if (negSin)
|
||||
sine = -sine;
|
||||
} else {
|
||||
// Swizzle on S is a bit odd here, but generally only applies to sine.
|
||||
float s[4]{};
|
||||
ReadVector(s, V_Single, vs);
|
||||
u32 sprefixRemove = VFPU_NEGATE(1, 0, 0, 0);
|
||||
u32 sprefixAdd = VFPU_NEGATE(negSin, 0, 0, 0);
|
||||
// TODO: Minor, but negate shouldn't apply to invalid here. Maybe always?
|
||||
ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Single);
|
||||
|
||||
// Cosine ignores all prefixes, so take the original.
|
||||
cosine = vfpu_cos(V(vs));
|
||||
sine = vfpu_sin(s[0]);
|
||||
}
|
||||
|
||||
if (sineLane == cosineLane) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
d[i] = sine;
|
||||
} else {
|
||||
d[sineLane] = sine;
|
||||
}
|
||||
d[(imm >> 2) & 3] = sine;
|
||||
d[imm & 3] = cosine;
|
||||
d[cosineLane] = cosine;
|
||||
|
||||
// D prefix works, just not for x.
|
||||
currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] &= 0xFFEFC;
|
||||
ApplyPrefixD(d, sz);
|
||||
WriteVector(d, sz, vd);
|
||||
PC += 4;
|
||||
EatPrefixes();
|
||||
|
|
|
@ -35,6 +35,7 @@ inline int Xpose(int v) {
|
|||
|
||||
// Some games depend on exact values, but sinf() and cosf() aren't always precise.
|
||||
// Stepping down to [0, 2pi) helps, but we also check common exact-result values.
|
||||
// TODO: cos(2) and sin(1) should be -0.0, but doing that gives wrong results (possibly from floorf.)
|
||||
|
||||
inline float vfpu_sin(float angle) {
|
||||
angle -= floorf(angle * 0.25f) * 4.f;
|
||||
|
|
Loading…
Add table
Reference in a new issue