From e65e551f52458ca688ee6cdd8a16e82f155160f3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 15 Feb 2013 20:40:00 -0800 Subject: [PATCH 01/69] Fix VFPU D prefix handling for -0.0f. --- Core/MIPS/MIPSIntVFPU.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index edfa630ec3..1252dac564 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -150,7 +150,8 @@ void ApplyPrefixD(float *v, VectorSize size, bool onlyWriteMask = false) if (sat == 1) { if (v[i] > 1.0f) v[i] = 1.0f; - if (v[i] < 0.0f) v[i] = 0.0f; + // This includes -0.0f -> +0.0f. + if (v[i] <= 0.0f) v[i] = 0.0f; } else if (sat == 3) { From b1f31f052e64c910b926018047515244fcef5601 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 15 Feb 2013 21:09:22 -0800 Subject: [PATCH 02/69] Apply prefixes on vscl to t. It seems to do so with bugs on a real PSP. --- Core/MIPS/MIPSIntVFPU.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 1252dac564..ac012d8730 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -1183,6 +1183,7 @@ namespace MIPSInt ReadVector(s, sz, vs); ApplySwizzleS(s, sz); float scale = V(vt); + ApplySwizzleT(&scale, V_Single); int n = GetNumVectorElements(sz); for (int i = 0; i < n; i++) { From be8ddf12aa767604a162e6db89c334f9742b4aaf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 15 Feb 2013 21:49:20 -0800 Subject: [PATCH 03/69] Don't go out of bounds applying vfpu swizzle. --- Core/MIPS/MIPSIntVFPU.cpp | 5 +++++ Core/MIPS/x86/CompVFPU.cpp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index ac012d8730..9237beeef4 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -110,6 +110,11 @@ void ApplyPrefixST(float *v, u32 data, VectorSize size) if (!constants) { + // Prefix may say "z, z, z, z" but if this is a pair, we force to x. + // TODO: But some ops seem to use const 0 instead? + if (regnum >= n) + regnum = 0; + v[i] = origV[regnum]; if (abs) v[i] = fabs(v[i]); diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index e693afbba1..2ea60ad844 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -87,6 +87,7 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) { for (int i = 0; i < n; i++) { + // TODO: This needs to be the original values, not the original regs. (e.g. [-x, |x|, x]) origV[i] = vregs[i]; } @@ -98,6 +99,11 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) { int constants = (prefix >> (12+i)) & 1; if (!constants) { + // Prefix may say "z, z, z, z" but if this is a pair, we force to x. + // TODO: But some ops seem to use const 0 instead? + if (regnum > n) { + regnum = 0; + } vregs[i] = origV[regnum]; if (abs) { ANDPS(fpr.VX(vregs[i]), M((void *)&noSignMask)); From 0eabc80c3efc7f91874d944de1877e233e696e4d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 15 Feb 2013 21:41:29 +0100 Subject: [PATCH 04/69] Small optimizations and fixes to vertex decoder --- GPU/GLES/TransformPipeline.cpp | 12 ++++++++---- GPU/GLES/VertexDecoder.cpp | 33 +++++++++++++++++---------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 05297137b6..85fa40b631 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -283,8 +283,13 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ bool doSpecular = (comp != GE_LIGHTCOMP_ONLYDIFFUSE); bool poweredDiffuse = comp == GE_LIGHTCOMP_BOTHWITHPOWDIFFUSE; - float dot = toLight * norm; - + float distanceToLight = toLight.Length(); + float dot = 0.0f; + if (distanceToLight > 0.0f) + { + toLight /= distanceToLight; + dot = toLight * norm; + } // Clamp dot to zero. if (dot < 0.0f) dot = 0.0f; @@ -292,10 +297,9 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ dot = powf(dot, specCoef_); float lightScale = 1.0f; - float distance = toLight.Normalize(); if (type != GE_LIGHTTYPE_DIRECTIONAL) { - lightScale = 1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distance + gstate_c.lightatt[l][2]*distance*distance); + lightScale = 1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distanceToLight + gstate_c.lightatt[l][2]*distanceToLight*distanceToLight); if (lightScale > 1.0f) lightScale = 1.0f; } diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index 8bfc77a451..6e68bdec48 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -144,18 +144,16 @@ void VertexDecoder::Step_WeightsFloat() const void VertexDecoder::Step_TcU8() const { - u8 *uv = (u8*)(decoded_ + decFmt.uvoff); - const u8 *uvdata = (const u8*)(ptr_ + tcoff); - uv[0] = uvdata[0]; - uv[1] = uvdata[1]; + u16 *uv = (u16*)(decoded_ + decFmt.uvoff); + const u16 *uvdata = (const u16*)(ptr_ + tcoff); + *uv = *uvdata; } void VertexDecoder::Step_TcU16() const { - u16 *uv = (u16 *)(decoded_ + decFmt.uvoff); - const u16 *uvdata = (const u16*)(ptr_ + tcoff); - uv[0] = uvdata[0]; - uv[1] = uvdata[1]; + u32 *uv = (u32 *)(decoded_ + decFmt.uvoff); + const u32 *uvdata = (const u32*)(ptr_ + tcoff); + *uv = *uvdata; } void VertexDecoder::Step_TcU16Through() const @@ -305,7 +303,7 @@ void VertexDecoder::Step_NormalS16() const xorval = 0xFFFF; const s16 *sv = (const s16*)(ptr_ + nrmoff); for (int j = 0; j < 3; j++) - normal[j] = sv[j] ^ xorval ; + normal[j] = sv[j] ^ xorval; normal[3] = 0; } @@ -330,9 +328,10 @@ void VertexDecoder::Step_NormalS8Morph() const if (gstate.reversenormals & 1) { multiplier = -multiplier; } - const s8 *sv = (const s8*)(ptr_ + onesize_*n + nrmoff); + const s8 *bv = (const s8*)(ptr_ + onesize_*n + nrmoff); + multiplier *= (1.0f/127.0f); for (int j = 0; j < 3; j++) - normal[j] += (sv[j]/32767.0f) * multiplier; + normal[j] += bv[j] * multiplier; } } @@ -346,9 +345,10 @@ void VertexDecoder::Step_NormalS16Morph() const if (gstate.reversenormals & 1) { multiplier = -multiplier; } - const float *fv = (const float*)(ptr_ + onesize_*n + nrmoff); + const s16 *sv = (const s16 *)(ptr_ + onesize_*n + nrmoff); + multiplier *= (1.0f/32767.f); for (int j = 0; j < 3; j++) - normal[j] += fv[j] * multiplier; + normal[j] += sv[j] * multiplier; } } @@ -425,9 +425,10 @@ void VertexDecoder::Step_PosS8Morph() const float *v = (float *)(decoded_ + decFmt.posoff); memset(v, 0, sizeof(float) * 3); for (int n = 0; n < morphcount; n++) { + float multiplier = 1.0f / 127.0f; const s8 *sv = (const s8*)(ptr_ + onesize_*n + posoff); for (int j = 0; j < 3; j++) - v[j] += (sv[j] / 127.f) * gstate_c.morphWeights[n]; + v[j] += (float)sv[j] * (multiplier * gstate_c.morphWeights[n]); } } @@ -437,9 +438,9 @@ void VertexDecoder::Step_PosS16Morph() const memset(v, 0, sizeof(float) * 3); for (int n = 0; n < morphcount; n++) { float multiplier = 1.0f / 32767.0f; - const short *sv = (const short*)(ptr_ + onesize_*n + posoff); + const s16 *sv = (const s16*)(ptr_ + onesize_*n + posoff); for (int j = 0; j < 3; j++) - v[j] += (sv[j] * multiplier) * gstate_c.morphWeights[n]; + v[j] += (float)sv[j] * (multiplier * gstate_c.morphWeights[n]); } } From 909b768f47f39927298c250e2a938d4095f0ce63 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 15 Feb 2013 22:56:38 +0100 Subject: [PATCH 05/69] Don't need separate variables for writemask. Some optimizations. --- Core/HLE/sceChnnlsv.cpp | 2 +- Core/MIPS/MIPS.cpp | 10 ------- Core/MIPS/MIPS.h | 9 ++++-- Core/MIPS/MIPSIntVFPU.cpp | 3 -- Core/MIPS/MIPSVFPUUtils.cpp | 56 +++++++++++++++++++++---------------- Core/MIPS/x86/Jit.cpp | 6 ---- 6 files changed, 40 insertions(+), 46 deletions(-) diff --git a/Core/HLE/sceChnnlsv.cpp b/Core/HLE/sceChnnlsv.cpp index e5dd66b681..27c583819e 100644 --- a/Core/HLE/sceChnnlsv.cpp +++ b/Core/HLE/sceChnnlsv.cpp @@ -760,7 +760,7 @@ int sceSdSetMember_(pspChnnlsvContext2& ctx, u8* data, int alignedLen) { return 0; } - if (alignedLen & 0xF != 0) + if ((alignedLen & 0xF) != 0) { return -1025; } diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index b751f5ba4a..7fbaa7c974 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -79,9 +79,6 @@ void MIPSState::Reset() vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000; vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000; - bool b[4] = {false, false, false, false}; - SetWriteMask(b); - pc = 0; hi = 0; lo = 0; @@ -115,7 +112,6 @@ void MIPSState::DoState(PointerWrap &p) p.DoArray(f, sizeof(f) / sizeof(f[0])); p.DoArray(v, sizeof(v) / sizeof(v[0])); p.DoArray(vfpuCtrl, sizeof(vfpuCtrl) / sizeof(vfpuCtrl[0])); - p.DoArray(vfpuWriteMask, sizeof(vfpuWriteMask) / sizeof(vfpuWriteMask[0])); p.Do(pc); p.Do(nextPC); p.Do(downcount); @@ -131,12 +127,6 @@ void MIPSState::DoState(PointerWrap &p) p.DoMarker("MIPSState"); } -void MIPSState::SetWriteMask(const bool wm[4]) -{ - for (int i = 0; i < 4; i++) - vfpuWriteMask[i] = wm[i]; -} - void MIPSState::SingleStep() { int cycles = MIPS_SingleStep(); diff --git a/Core/MIPS/MIPS.h b/Core/MIPS/MIPS.h index ad0d51cfa6..30f9c616f0 100644 --- a/Core/MIPS/MIPS.h +++ b/Core/MIPS/MIPS.h @@ -120,7 +120,6 @@ public: float f[32]; float v[128]; u32 vfpuCtrl[16]; - bool vfpuWriteMask[4]; u32 pc; u32 nextPC; @@ -144,7 +143,13 @@ public: void WriteFCR(int reg, int value); u32 ReadFCR(int reg); - void SetWriteMask(const bool wm[4]); + + u8 VfpuWriteMask() const { + return (vfpuCtrl[VFPU_CTRL_DPREFIX] >> 8) & 0xF; + } + bool VfpuWriteMask(int i) const { + return (vfpuCtrl[VFPU_CTRL_DPREFIX] >> (8 + i)) & 1; + } void Irq(); void SWI(); diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 9237beeef4..4313f0101b 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -165,7 +165,6 @@ void ApplyPrefixD(float *v, VectorSize size, bool onlyWriteMask = false) } } } - currentMIPS->SetWriteMask(writeMask); } void EatPrefixes() @@ -173,8 +172,6 @@ void EatPrefixes() currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; // passthru currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX] = 0xe4; // passthru currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = 0; - static const bool noWriteMask[4] = {false, false, false, false}; - currentMIPS->SetWriteMask(noWriteMask); } namespace MIPSInt diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index 7ba55a120a..63881762a3 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -89,23 +89,20 @@ void ReadVector(float *rd, VectorSize size, int reg) int length = 0; int transpose = (reg>>5) & 1; - switch (size) - { + switch (size) { case V_Single: transpose = 0; row=(reg>>5)&3; length = 1; break; case V_Pair: row=(reg>>5)&2; length = 2; break; case V_Triple: row=(reg>>6)&1; length = 3; break; case V_Quad: row=(reg>>5)&2; length = 4; break; } - for (int i = 0; i < length; i++) - { - int index = mtx * 4; - if (transpose) - index += ((row+i)&3) + col*32; - else - index += col + ((row+i)&3)*32; - rd[i] = V(index); - } + if (transpose) { + for (int i = 0; i < length; i++) + rd[i] = V(mtx * 4 + ((row+i)&3) + col*32); + } else { + for (int i = 0; i < length; i++) + rd[i] = V(mtx * 4 + col + ((row+i)&3)*32); + } } void WriteVector(const float *rd, VectorSize size, int reg) @@ -124,18 +121,28 @@ void WriteVector(const float *rd, VectorSize size, int reg) case V_Quad: row=(reg>>5)&2; length = 4; break; } - for (int i = 0; i < length; i++) - { - if (!currentMIPS->vfpuWriteMask[i]) - { - int index = mtx * 4; - if (transpose) - index += ((row+i)&3) + col*32; - else - index += col + ((row+i)&3)*32; - V(index) = rd[i]; - } - } + if (currentMIPS->VfpuWriteMask() == 0) { + if (transpose) { + for (int i = 0; i < length; i++) + V(mtx * 4 + ((row+i)&3) + col*32) = rd[i]; + } else { + for (int i = 0; i < length; i++) + V(mtx * 4 + col + ((row+i)&3)*32) = rd[i]; + } + } else { + for (int i = 0; i < length; i++) + { + if (!currentMIPS->VfpuWriteMask(i)) + { + int index = mtx * 4; + if (transpose) + index += ((row+i)&3) + col*32; + else + index += col + ((row+i)&3)*32; + V(index) = rd[i]; + } + } + } } void ReadMatrix(float *rd, MatrixSize size, int reg) @@ -190,7 +197,8 @@ void WriteMatrix(const float *rd, MatrixSize size, int reg) { for (int j=0; jvfpuWriteMask[i]) + // Hm, I wonder if this should affect matrices at all. + if (!currentMIPS->VfpuWriteMask(i)) { int index = mtx * 4; if (transpose) diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 0a859ca2ae..9fb2487713 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -129,12 +129,6 @@ void Jit::FlushPrefixV() if ((js.prefixDFlag & JitState::PREFIX_DIRTY) != 0) { MOV(32, M((void *)&mips_->vfpuCtrl[VFPU_CTRL_DPREFIX]), Imm32(js.prefixD)); - - _dbg_assert_msg_(JIT, sizeof(bool) <= 4, "Bools shouldn't be that big?"); - const size_t bool_stride = 4 / sizeof(bool); - for (size_t i = 0; i < ARRAY_SIZE(mips_->vfpuWriteMask); i += bool_stride) - MOV(32, M((void *)&mips_->vfpuWriteMask[i]), Imm32(*(u32 *)&js.writeMask[i])); - js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY); } } From 159f42313531d7088ff388a3b0194f8a227e7842 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 15 Feb 2013 23:09:02 +0100 Subject: [PATCH 06/69] VFPUutil style & simplification --- Core/MIPS/MIPSVFPUUtils.cpp | 66 +++++++++++++++---------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index 63881762a3..fd94a6cf02 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -32,16 +32,14 @@ void GetVectorRegs(u8 regs[4], VectorSize N, int vectorReg) { int length = 0; int transpose = (vectorReg>>5) & 1; - switch (N) - { + switch (N) { case V_Single: transpose = 0; row=(vectorReg>>5)&3; length = 1; break; case V_Pair: row=(vectorReg>>5)&2; length = 2; break; case V_Triple: row=(vectorReg>>6)&1; length = 3; break; case V_Quad: row=(vectorReg>>5)&2; length = 4; break; } - for (int i = 0; i < length; i++) - { + for (int i = 0; i < length; i++) { int index = mtx * 4; if (transpose) index += ((row+i)&3) + col*32; @@ -58,8 +56,7 @@ void GetMatrixRegs(u8 regs[16], MatrixSize N, int matrixReg) { int row = 0; int side = 0; - switch (N) - { + switch (N) { case M_2x2: row = (matrixReg>>5)&2; side = 2; break; case M_3x3: row = (matrixReg>>6)&1; side = 3; break; case M_4x4: row = (matrixReg>>5)&2; side = 4; break; @@ -67,10 +64,8 @@ void GetMatrixRegs(u8 regs[16], MatrixSize N, int matrixReg) { int transpose = (matrixReg>>5) & 1; - for (int i = 0; i < side; i++) - { - for (int j = 0; j < side; j++) - { + for (int i = 0; i < side; i++) { + for (int j = 0; j < side; j++) { int index = mtx * 4; if (transpose) index += ((row+i)&3) + ((col+j)&3)*32; @@ -81,8 +76,7 @@ void GetMatrixRegs(u8 regs[16], MatrixSize N, int matrixReg) { } } -void ReadVector(float *rd, VectorSize size, int reg) -{ +void ReadVector(float *rd, VectorSize size, int reg) { int mtx = (reg >> 2) & 7; int col = reg & 3; int row = 0; @@ -97,24 +91,24 @@ void ReadVector(float *rd, VectorSize size, int reg) } if (transpose) { + int base = mtx * 4 + col * 32; for (int i = 0; i < length; i++) - rd[i] = V(mtx * 4 + ((row+i)&3) + col*32); + rd[i] = V(base + ((row+i)&3)); } else { + int base = mtx * 4 + col; for (int i = 0; i < length; i++) - rd[i] = V(mtx * 4 + col + ((row+i)&3)*32); + rd[i] = V(base + ((row+i)&3)*32); } } -void WriteVector(const float *rd, VectorSize size, int reg) -{ +void WriteVector(const float *rd, VectorSize size, int reg) { int mtx = (reg>>2)&7; int col = reg & 3; int row = 0; int length = 0; int transpose = (reg>>5)&1; - switch (size) - { + switch (size) { case V_Single: transpose = 0; row=(reg>>5)&3; length = 1; break; case V_Pair: row=(reg>>5)&2; length = 2; break; case V_Triple: row=(reg>>6)&1; length = 3; break; @@ -123,17 +117,17 @@ void WriteVector(const float *rd, VectorSize size, int reg) if (currentMIPS->VfpuWriteMask() == 0) { if (transpose) { + int base = mtx * 4 + col * 32; for (int i = 0; i < length; i++) - V(mtx * 4 + ((row+i)&3) + col*32) = rd[i]; + V(base + ((row+i)&3)) = rd[i]; } else { + int base = mtx * 4 + col; for (int i = 0; i < length; i++) - V(mtx * 4 + col + ((row+i)&3)*32) = rd[i]; + V(base + ((row+i)&3)*32) = rd[i]; } } else { - for (int i = 0; i < length; i++) - { - if (!currentMIPS->VfpuWriteMask(i)) - { + for (int i = 0; i < length; i++) { + if (!currentMIPS->VfpuWriteMask(i)) { int index = mtx * 4; if (transpose) index += ((row+i)&3) + col*32; @@ -145,16 +139,14 @@ void WriteVector(const float *rd, VectorSize size, int reg) } } -void ReadMatrix(float *rd, MatrixSize size, int reg) -{ +void ReadMatrix(float *rd, MatrixSize size, int reg) { int mtx = (reg >> 2) & 7; int col = reg & 3; int row = 0; int side = 0; - switch (size) - { + switch (size) { case M_2x2: row = (reg>>5)&2; side = 2; break; case M_3x3: row = (reg>>6)&1; side = 3; break; case M_4x4: row = (reg>>5)&2; side = 4; break; @@ -162,10 +154,8 @@ void ReadMatrix(float *rd, MatrixSize size, int reg) int transpose = (reg>>5) & 1; - for (int i = 0; i < side; i++) - { - for (int j = 0; j < side; j++) - { + for (int i = 0; i < side; i++) { + for (int j = 0; j < side; j++) { int index = mtx * 4; if (transpose) index += ((row+i)&3) + ((col+j)&3)*32; @@ -176,16 +166,14 @@ void ReadMatrix(float *rd, MatrixSize size, int reg) } } -void WriteMatrix(const float *rd, MatrixSize size, int reg) -{ +void WriteMatrix(const float *rd, MatrixSize size, int reg) { int mtx = (reg>>2)&7; int col = reg&3; int row = 0; int side = 0; - switch (size) - { + switch (size) { case M_2x2: row = (reg>>5)&2; side = 2; break; case M_3x3: row = (reg>>6)&1; side = 3; break; case M_4x4: row = (reg>>5)&2; side = 4; break; @@ -193,10 +181,8 @@ void WriteMatrix(const float *rd, MatrixSize size, int reg) int transpose = (reg>>5)&1; - for (int i=0; iVfpuWriteMask(i)) { From 37f998407b6df905d7be217b739daa88f4dcf373 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 16 Feb 2013 09:49:33 +0100 Subject: [PATCH 07/69] Replace "Core" with "Jit" in ini. Don't show Open dialog by default (use Ctrl+A or Ctrl+O to open it). Delete "Slightly Faster Interpreter". --- Core/Config.cpp | 6 +- Core/Config.h | 2 +- Core/CoreParameter.h | 1 - Core/MIPS/MIPS.cpp | 4 -- Core/MIPS/MIPSTables.cpp | 118 ------------------------------------ Core/MIPS/MIPSTables.h | 1 - Core/MemMapFunctions.cpp | 4 +- Windows/EmuThread.cpp | 2 +- Windows/WndMainWindow.cpp | 14 ++--- Windows/main.cpp | 12 ++-- Windows/ppsspp.rc | Bin 55936 -> 56832 bytes android/jni/EmuScreen.cpp | 2 +- android/jni/MenuScreens.cpp | 8 +-- android/jni/NativeApp.cpp | 8 +-- native | 2 +- 15 files changed, 22 insertions(+), 162 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 9b5cfe94b5..ae887f2cba 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -55,8 +55,8 @@ void CConfig::Load(const char *iniFileName) general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false); IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); - cpu->Get("Core", &iCpuCore, 2); - cpu->Get("FastMemory", &bFastMemory, false); + cpu->Get("Jit", &bJit, true); + cpu->Get("FastMemory", &bFastMemory, true); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); graphics->Get("ShowFPSCounter", &bShowFPSCounter, false); @@ -117,7 +117,7 @@ void CConfig::Save() general->Set("CurrentDirectory", currentDirectory); general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad); IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); - cpu->Set("Core", iCpuCore); + cpu->Set("Jit", bJit); cpu->Set("FastMemory", bFastMemory); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); diff --git a/Core/Config.h b/Core/Config.h index e14cfe06d4..de54372064 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -48,7 +48,7 @@ public: // Core bool bIgnoreBadMemAccess; bool bFastMemory; - int iCpuCore; + bool bJit; // GFX bool bDisplayFramebuffer; diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index 0ff37be9ed..3357fc027d 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -22,7 +22,6 @@ enum CPUCore { CPU_INTERPRETER, - CPU_FASTINTERPRETER, // unsafe, a bit faster than INTERPRETER CPU_JIT, }; diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index 7fbaa7c974..478d2c99e5 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -143,11 +143,7 @@ int MIPSState::RunLoopUntil(u64 globalTicks) MIPSComp::jit->RunLoopUntil(globalTicks); break; - case CPU_FASTINTERPRETER: // For jit-less platforms. Crashier than INTERPRETER. - return MIPSInterpret_RunFastUntil(globalTicks); - case CPU_INTERPRETER: - // INFO_LOG(CPU, "Entering run loop for %i ticks, pc=%08x", (int)globalTicks, mipsr4k.pc); return MIPSInterpret_RunUntil(globalTicks); } return 1; diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index ea58c8de4c..06e30466c3 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -1016,124 +1016,6 @@ static inline void DelayBranchTo(MIPSState *curMips, u32 where) curMips->inDelaySlot = true; } -// Optimized interpreter loop that shortcuts the most common instructions. -// For slow platforms without JITs. -#define SIMM16 (s32)(s16)(op & 0xFFFF) -#define UIMM16 (u32)(u16)(op & 0xFFFF) -#define SUIMM16 (u32)(s32)(s16)(op & 0xFFFF) -int MIPSInterpret_RunFastUntil(u64 globalTicks) -{ - MIPSState *curMips = currentMIPS; - while (coreState == CORE_RUNNING) - { - CoreTiming::Advance(); - - while (curMips->downcount >= 0 && coreState == CORE_RUNNING) // TODO: Try to get rid of the latter check - { - again: - bool wasInDelaySlot = curMips->inDelaySlot; - u32 op = Memory::ReadUnchecked_U32(curMips->pc); - switch (op >> 29) - { - case 0x0: - { - int imm = (s16)(op&0xFFFF) << 2; - int rs = _RS; - int rt = _RT; - u32 addr = curMips->pc + imm + 4; - switch (op >> 26) - { - case 4: if (R(rt) == R(rs)) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //beq - case 5: if (R(rt) != R(rs)) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //bne - case 6: if ((s32)R(rs) <= 0) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //blez - case 7: if ((s32)R(rs) > 0) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //bgtz - default: - goto interpret; - } - } - break; - - case 0x1: - { - int rt = _RT; - int rs = _RS; - switch (op >> 26) - { - case 8: R(rt) = R(rs) + SIMM16; break; //addi - case 9: R(rt) = R(rs) + SIMM16; break; //addiu - case 10: R(rt) = (s32)R(rs) < SIMM16; break; //slti - case 11: R(rt) = R(rs) < SUIMM16; break; //sltiu - case 12: R(rt) = R(rs) & UIMM16; break; //andi - case 13: R(rt) = R(rs) | UIMM16; break; //ori - case 14: R(rt) = R(rs) ^ UIMM16; break; //xori - case 15: R(rt) = UIMM16 << 16; break; //lui - default: - goto interpret; - } - currentMIPS->pc += 4; - } - break; - - case 0x4: - { - int rt = _RT; - int rs = _RS; - int imm = (s16)(op & 0xFFFF); - u32 addr = R(rs) + imm; - switch (op >> 26) - { - case 32: R(rt) = (u32)(s32)(s8) Memory::ReadUnchecked_U8(addr); break; //lb - case 33: R(rt) = (u32)(s32)(s16)Memory::ReadUnchecked_U16(addr); break; //lh - case 35: R(rt) = Memory::ReadUnchecked_U32(addr); break; //lw - case 36: R(rt) = Memory::ReadUnchecked_U8(addr); break; //lbu - case 37: R(rt) = Memory::ReadUnchecked_U16(addr); break; //lhu - default: - goto interpret; - } - currentMIPS->pc += 4; - } - break; - - case 0x5: - { - int rt = _RT; - int rs = _RS; - int imm = (s16)(op & 0xFFFF); - u32 addr = R(rs) + imm; - switch (op >> 26) - { - case 40: Memory::WriteUnchecked_U8(R(rt), addr); break; //sb - case 41: Memory::WriteUnchecked_U16(R(rt), addr); break; //sh - case 43: Memory::WriteUnchecked_U32(R(rt), addr); break; //sw - default: - goto interpret; - } - currentMIPS->pc += 4; - } - break; - - default: - interpret: - MIPSInterpret(op); - } - - if (curMips->inDelaySlot) - { - // The reason we have to check this is the delay slot hack in Int_Syscall. - if (wasInDelaySlot) - { - curMips->pc = curMips->nextPC; - curMips->inDelaySlot = false; - } - curMips->downcount -= 1; - goto again; - } - } - } - return 1; -} - - const char *MIPSGetName(u32 op) { static const char *noname = "unk"; diff --git a/Core/MIPS/MIPSTables.h b/Core/MIPS/MIPSTables.h index 9c15072b53..2d71bc73d1 100644 --- a/Core/MIPS/MIPSTables.h +++ b/Core/MIPS/MIPSTables.h @@ -57,7 +57,6 @@ void MIPSCompileOp(u32 op); void MIPSDisAsm(u32 op, u32 pc, char *out, bool tabsToSpaces = false); u32 MIPSGetInfo(u32 op); void MIPSInterpret(u32 op); //only for those rare ones -int MIPSInterpret_RunFastUntil(u64 globalTicks); int MIPSInterpret_RunUntil(u64 globalTicks); MIPSInterpretFunc MIPSGetInterpretFunc(u32 op); diff --git a/Core/MemMapFunctions.cpp b/Core/MemMapFunctions.cpp index ee2370c0da..d174cdb7e1 100644 --- a/Core/MemMapFunctions.cpp +++ b/Core/MemMapFunctions.cpp @@ -83,7 +83,7 @@ inline void ReadFromHardware(T &var, const u32 address) } else { - if (g_Config.iCpuCore == CPU_JIT) { + if (g_Config.bJit) { WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x", address); } else { WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); @@ -115,7 +115,7 @@ inline void WriteToHardware(u32 address, const T data) } else { - if (g_Config.iCpuCore == CPU_JIT) { + if (g_Config.bJit) { WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x", address); } else { WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index cd38e3ead5..ac7e4fc153 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -68,7 +68,7 @@ DWORD TheThread(LPVOID x) coreParameter.fileToStart = fileToStart; coreParameter.enableSound = true; coreParameter.gpuCore = GPU_GLES; - coreParameter.cpuCore = (CPUCore)g_Config.iCpuCore; + coreParameter.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER; coreParameter.enableDebugging = true; coreParameter.printfEmuLog = false; coreParameter.headLess = false; diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 8db545ffd4..b99eb0edbd 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -452,15 +452,11 @@ namespace MainWindow break; case ID_CPU_DYNAREC: - g_Config.iCpuCore = CPU_JIT; + g_Config.bJit = true; UpdateMenus(); break; case ID_CPU_INTERPRETER: - g_Config.iCpuCore = CPU_INTERPRETER; - UpdateMenus(); - break; - case ID_CPU_FASTINTERPRETER: - g_Config.iCpuCore = CPU_FASTINTERPRETER; + g_Config.bJit = false; UpdateMenus(); break; @@ -701,9 +697,8 @@ namespace MainWindow // CHECK(ID_OPTIONS_EMULATESYSCALL,g_bEmulateSyscall); CHECKITEM(ID_OPTIONS_DISPLAYRAWFRAMEBUFFER, g_Config.bDisplayFramebuffer); CHECKITEM(ID_OPTIONS_IGNOREILLEGALREADS,g_Config.bIgnoreBadMemAccess); - CHECKITEM(ID_CPU_INTERPRETER,g_Config.iCpuCore == CPU_INTERPRETER); - CHECKITEM(ID_CPU_FASTINTERPRETER,g_Config.iCpuCore == CPU_FASTINTERPRETER); - CHECKITEM(ID_CPU_DYNAREC,g_Config.iCpuCore == CPU_JIT); + CHECKITEM(ID_CPU_INTERPRETER,g_Config.bJit == true); + CHECKITEM(ID_CPU_DYNAREC,g_Config.bJit == false); CHECKITEM(ID_OPTIONS_BUFFEREDRENDERING, g_Config.bBufferedRendering); CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats); CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe); @@ -731,7 +726,6 @@ namespace MainWindow EnableMenuItem(menu,ID_FILE_QUICKLOADSTATE,!enable); EnableMenuItem(menu,ID_CPU_DYNAREC,enable); EnableMenuItem(menu,ID_CPU_INTERPRETER,enable); - EnableMenuItem(menu,ID_CPU_FASTINTERPRETER,enable); EnableMenuItem(menu,ID_DVD_INSERTISO,enable); EnableMenuItem(menu,ID_FILE_BOOTBIOS,enable); EnableMenuItem(menu,ID_EMULATION_STOP,!enable); diff --git a/Windows/main.cpp b/Windows/main.cpp index b568189d07..48fce377a6 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -76,15 +76,11 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin switch (__argv[i][1]) { case 'j': - g_Config.iCpuCore = CPU_JIT; + g_Config.bJit = true; g_Config.bSaveSettings = false; break; case 'i': - g_Config.iCpuCore = CPU_INTERPRETER; - g_Config.bSaveSettings = false; - break; - case 'f': - g_Config.iCpuCore = CPU_FASTINTERPRETER; + g_Config.bJit = false; g_Config.bSaveSettings = false; break; case 'l': @@ -163,8 +159,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin EmuThread_Start(fileToStart); } - else - MainWindow::BrowseAndBoot(); + // else + // MainWindow::BrowseAndBoot(); if (fileToStart != NULL && stateToLoad != NULL) SaveState::Load(stateToLoad); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index ae0ec17aca726288296c2fedbdc44e6521e70732..e0a82cd7f4231adcd17ae6abe95c146ffc5fc198 100644 GIT binary patch delta 1856 zcmZuxTTl~c6yAk2V92H+#gqZWEh26)4FM^alwyd0NF!1Vkp`p-#)uIi+*(Aif!1D> zsmiCtB9l^Nf&)>IMd}49Dqd>^8Ah!S4r3V~e4y5GtPdUA*~MDubav+Z&*eYoJLmj6 z$8o~bG3dG1I*%eGLrg=}{Sg1vOG?N(!#R~qi_R^z!>45w?X_Jq?XfqSy&z6aM@8$ixWA_|F8 zqKc@*^5$4Ps>^_yRv=#<0Naiu2=dh;;}bQk6-pfR-P`0)b4EoA3AZB#-;~J_<(Ce+ zJ`R0;Hni3!z%<{C)_OJA1_>U_?-k_pN)zaM5jS;Uio~>kH217I$^(YLCY)}GfKSjT zupCljAV`ZVhputAnw%t37bc^3{}HHZ295)2xFbSv5> zho1YoEt7;{Ne~>aWO%r&oTDRz`eutT7`{K{&NR3q5}?^B zMPfq;=cl1bF7b0Y$=!8kk=(uS~`z^P>z*aaJ@QW0096f_u3)rsK?LJQfCBj}{&AM%?I8fz~R8e0FUf zI=UG=*0Kmc&f?fREFK{%Pp{< z_=k%XWQ|#jI9(A!ug-A(sVjo{2NuIg76hMUkghkPzYODgBb=jBXim|{SfLPd zI$}g{uE@vpQ!H|ltwMcM$(3Nw%WSR%c=00)uO-3!xif@nwb`;)@J|*Hok9q6$N6X5LDaX@%nw zi%Xd%#9SW6bgmyJ-#3B1!U{cRu1|z4OOB~51^g#w=1Z?N!F9D7(rgJHt<4kalV*qE zpfLmVPYk5lH9|c9J`c0a`0V-sa+2i`uVc~mGlRx;MbO@0k(pBr@hBs3KF!I4bCiWV zR}bBo9vX8orpIa_&*e`QI&$Su-Au%EZaJKzVVKNOq9t#3ovcvbt@ZhEPSBt`rLcE( zA!=J3Zq$@`We_PuHj#{^?Tc{jLk;phqF&*b2L*CjBnmrwAudq*zFa4~hma7Fs4obF z$BqEx6a>A>TT+M&B3bZJs4G~=`vOCVJVHZ+2-aDCLP9Ki8UL(6DrBc$d_oMWZbzUk znufXaBqSUDkNlgjj>$t&1RYE6||z$MsFoLXH1& zB>mS;6`Ohax6Qn_&c>t9 z79PJ9a7po3B!wOUFK(?v@5FgLE0IzBB!nd`%$q8WCn=u1SIw3n-9=`uVm51pgy zE2`({_bb}w=v|eGb98yt+hWbJtAAapC=Op}e8%I|+*KgbV+(?iZuii^=1rvl}CC2EcTe5%IRa E0pB~nh5!Hn delta 3299 zcmbtWYfPKh8Gg+@AA}Hxo4M6E;5d%)<%>rgLWmPCfs_zR2uTR#;$RmTHI8i5SNT*I!g*4P3Q`Bt)tZcwWq#=4sTH|1kKMwxJ0w!{cFp^M-=Z5UWW;#PEJV~fc<>(mI(s62_COq+# zp(T-rO3C9FiFdH2)ZuE9p5b4U%vhh&p+4El=Jm;GSWT{EV_ix)!|9Y7Ci`sK#^$aW zas9=%a-;>8AkVX)IV~O9R3Ex;>#&(xDXm?FYTkl>T(iN)^H|*eD<(giUX{vGEj3XM zal~O#tw72SBlsJ7RDIZjPj?){v???8DA{O;hRMrfs@`s-h^VH@Fq@&1ahSWm7t=l~ z)_oQ5?ySJNPlu;F?+WpnfkGrQS`lq@fs-^+5axi$M!hMJtVZ6T-dqnseQ zJTiWw!&kZWQIt9qW{H*z{7Jz>p7$9Gv;Edh$n$jgB0s?Jy@ClwOGRM?(gHjd3NJ^5 ze`!I1XCLUL@W+KjV(r7+m^PojCZuANrEE4sj!k7Ywv>)A&nIWASy{N|ESOdmMQJIX zpNp_=(%%wG5j`b^$x_*&$85q%i7q1Mo!VVUD=mP}n~7Dm4qIwnqM3|j!Ca{U>!oJQ zm&%c+&Xq7b%S2}4NGbiKgfl%?)k;Z^9$RW2t9Nu*y`z;`FuBKo=SHdnaL7UZXfeAu*eI$3e9Aq z{n7ix*kI~C94{2KNq?&_vVj}uA`Ou<)V#&_eh8PY5i7cJY~7cmvCM(3`=es>?~as> z(fq{Ww;w5xX$UrrP&MkPT#GFt$C5D*TgoQnn(|mvbeohi`1lw9MQPkL z%H(fWc828I4|lV%?W_?cRl#)){!-P6WvkXcNd5E{^^unbX^fOqM?K^rFWJdWN@^gd zGhpJ;A{Tk7pVhaA zRG9Q;G1;$bL}CQO@6-x*HQ?*q0x4Ll8({O^$Y zVDyBIt*tdCfqUJ{R4ht(qOn8zHo*4FPnBcwWD7%clZYz}r^N5)wfN@LAd|V)JQ6FU zZS`cQL2`u!<9nkwz8RQl}9S!fUTiUy7g?O44Ki0Q*bhdk70jtf>~f2obRZ}7{=cptwR zv?b<9D20M9!8bMTc6H{wf=v{6?*gyCDdSN5&S4pc+p>O4^l*^J6=AW*i0SXE;g92F z;)TWQZ%S9$-)*m@2G16bO!${gk);ejF@mSl%%oyh2N_BAGJ(VqF9?*y6d)z3C|Y8_ zAaUfsNw}$loXk$}K8(^6et$@T6xt&LdE-zSCNv4SVm~3?75jo=8puFOI!YJmA}e0u zc6RPCrtH{J1_O?yqo-VA(Yl=o6<+mj+&OyIgYTgq|5cb|1u=TZx)0dbh~=D_AHVzs(n znu&YfB8JbrDNv1QARo3eygXb7)rb-Q9@arM(!tgiMoJidJu=Gh`uAoT+D5A|KiZ1< z(Q@d=bnKDi98206RlCgk>{u?dK3|#%*Kiu1kMa3YJA+Rm@yQ^i{Ga2+A%0{Viim{C zHg}_OqXh1ab74=u=v@tPZ^+TPS&6t!6;?J&!giZ_3!!1#vx=N2@5l9DW4HrRLM$fIkYSW09Zp8R2dScm=W>6_bvrN Date: Sat, 16 Feb 2013 01:48:28 -0800 Subject: [PATCH 08/69] Remove faster interpreter from headless. --- headless/Headless.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 3cc16ae7f9..7129523f43 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -66,7 +66,6 @@ void printUsage(const char *progname, const char *reason) } fprintf(stderr, " -i use the interpreter\n"); - fprintf(stderr, " -f use the fast interpreter\n"); fprintf(stderr, " -j use jit (default)\n"); fprintf(stderr, " -c, --compare compare with output in file.expected\n"); fprintf(stderr, "\nSee headless.txt for details.\n"); @@ -76,7 +75,6 @@ int main(int argc, const char* argv[]) { bool fullLog = false; bool useJit = false; - bool fastInterpreter = false; bool autoCompare = false; bool useGraphics = false; @@ -101,8 +99,6 @@ int main(int argc, const char* argv[]) useJit = false; else if (!strcmp(argv[i], "-j")) useJit = true; - else if (!strcmp(argv[i], "-f")) - fastInterpreter = true; else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compare")) autoCompare = true; else if (!strcmp(argv[i], "--graphics")) @@ -156,7 +152,7 @@ int main(int argc, const char* argv[]) coreParameter.fileToStart = bootFilename; coreParameter.mountIso = mountIso ? mountIso : ""; coreParameter.startPaused = false; - coreParameter.cpuCore = fastInterpreter ? CPU_FASTINTERPRETER : (useJit ? CPU_JIT : CPU_INTERPRETER); + coreParameter.cpuCore = useJit ? CPU_JIT : CPU_INTERPRETER; coreParameter.gpuCore = headlessHost->isGLWorking() ? GPU_GLES : GPU_NULL; coreParameter.enableSound = false; coreParameter.headLess = true; From 1ef4ccc5a1b222cc18c7710a00436d0794442c24 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 02:04:04 -0800 Subject: [PATCH 09/69] Log an error when vfpu swizzle is used badly. --- Core/MIPS/MIPSIntVFPU.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 4313f0101b..8466b5250c 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -113,7 +113,10 @@ void ApplyPrefixST(float *v, u32 data, VectorSize size) // Prefix may say "z, z, z, z" but if this is a pair, we force to x. // TODO: But some ops seem to use const 0 instead? if (regnum >= n) + { + ERROR_LOG(CPU, "Invalid VFPU swizzle: %08x / %d", data, size); regnum = 0; + } v[i] = origV[regnum]; if (abs) @@ -1185,7 +1188,11 @@ namespace MIPSInt ReadVector(s, sz, vs); ApplySwizzleS(s, sz); float scale = V(vt); - ApplySwizzleT(&scale, V_Single); + if (currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX] != 0xE4) + { + WARN_LOG(CPU, "Broken T prefix used with VScl: %08x / %08x", currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX], op); + ApplySwizzleT(&scale, V_Single); + } int n = GetNumVectorElements(sz); for (int i = 0; i < n; i++) { From 35537b3c97c09e5b48bd8da9bfe9e2aa544b38f7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 03:15:22 -0800 Subject: [PATCH 10/69] Add TEMP0 fpu regs to x86 like in armjit. But... will probably need more and the ability to swap into memory if we want to deal with prefixes. --- Core/MIPS/x86/CompVFPU.cpp | 53 +++++++++++++++++++++++++++++++---- Core/MIPS/x86/RegCacheFPU.cpp | 36 ++++++++++++++++++++++-- Core/MIPS/x86/RegCacheFPU.h | 15 ++++++++-- 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 2ea60ad844..dbc4733008 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -144,6 +144,24 @@ void Jit::ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWrit } } +// Vector regs can overlap in all sorts of swizzled ways. +bool DestRegOverlaps(int dreg, int sn, u8 sregs[], int tn, u8 tregs[]) +{ + for (int i = 0; i < sn; ++i) + { + if (sregs[i] == dreg) + return true; + } + for (int i = 0; i < tn; ++i) + { + if (tregs[i] == dreg) + return true; + } + + // Hurray, no overlap, we can write directly. + return false; +} + static u32 GC_ALIGNED16(ssLoadStoreTemp[1]); void Jit::Comp_SV(u32 op) { @@ -394,16 +412,39 @@ void Jit::Comp_VecDo3(u32 op) { } int n = GetNumVectorElements(sz); - // We need at least n temporaries... - if (n > 2) - fpr.Flush(); + + X64Reg tempxregs[4]; + for (int i = 0; i < n; ++i) + { + if (DestRegOverlaps(dregs[i], n, sregs, n, tregs)) + { + // On 32-bit we only have 6 xregs for mips regs, use XMM0/XMM1 if possible. + if (i < 2) + tempxregs[i] = (X64Reg) (XMM0 + i); + else + { + fpr.BindToRegister(TEMP0 + i, false, true); + fpr.SpillLock(TEMP0 + i); + tempxregs[i] = fpr.RX(TEMP0 + i); + } + } + else + { + fpr.MapRegV(dregs[i], MAP_NOINIT | MAP_DIRTY); + fpr.SpillLockV(dregs[i]); + tempxregs[i] = fpr.VX(dregs[i]); + } + } for (int i = 0; i < n; ++i) - MOVSS((X64Reg) (XMM0 + i), fpr.V(sregs[i])); + MOVSS(tempxregs[i], fpr.V(sregs[i])); for (int i = 0; i < n; ++i) - (this->*xmmop)((X64Reg) (XMM0 + i), fpr.V(tregs[i])); + (this->*xmmop)(tempxregs[i], fpr.V(tregs[i])); for (int i = 0; i < n; ++i) - MOVSS(fpr.V(dregs[i]), (X64Reg) (XMM0 + i)); + { + if (!fpr.R(dregs[i]).IsSimpleReg(tempxregs[i])) + MOVSS(fpr.V(dregs[i]), tempxregs[i]); + } fpr.ReleaseSpillLocks(); diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index 9c2cb9c837..f2356a6d57 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -97,7 +97,9 @@ void FPURegCache::BindToRegister(const int i, bool doLoad, bool makeDirty) { if (!regs[i].location.IsImm() && (regs[i].location.offset & 0x3)) { PanicAlert("WARNING - misaligned fp register location %i", i); } - emit->MOVSS(xr, regs[i].location); + if (i < TEMP0) { + emit->MOVSS(xr, regs[i].location); + } } regs[i].location = newloc; regs[i].away = true; @@ -124,8 +126,24 @@ void FPURegCache::StoreFromRegister(int i) { } } +void FPURegCache::DiscardR(int i) +{ + _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "FPU can't handle imm yet."); + if (regs[i].away) { + X64Reg xr = regs[i].location.GetSimpleReg(); + _assert_msg_(DYNA_REC, xr < NUM_X_FPREGS, "DiscardR: MipsReg had bad X64Reg"); + // Note that we DO NOT write it back here. That's the whole point of Discard. + xregs[xr].dirty = false; + xregs[xr].mipsReg = -1; + regs[i].location = GetDefaultLocation(i); + regs[i].away = false; + } else { + // _assert_msg_(DYNA_REC,0,"already stored"); + } +} + void FPURegCache::Flush() { - for (int i = 0; i < NUM_MIPS_FPRS; i++) { + for (int i = 0; i < TEMP0; i++) { if (regs[i].locked) { PanicAlert("Somebody forgot to unlock MIPS reg %i.", i); } @@ -141,6 +159,9 @@ void FPURegCache::Flush() { } } } + for (int i = TEMP0; i < TEMP0 + NUM_TEMPS; ++i) { + DiscardR(i); + } } OpArg FPURegCache::GetDefaultLocation(int reg) const { @@ -189,6 +210,15 @@ X64Reg FPURegCache::GetFreeXReg() { } //Okay, not found :( Force grab one + // Maybe a temp reg? + for (int i = TEMP0; i < NUM_MIPS_FPRS; ++i) { + if (regs[i].away && !regs[i].locked) { + X64Reg xr = regs[i].location.GetSimpleReg(); + DiscardR(i); + return xr; + } + } + //TODO - add a pass to grab xregs whose mipsreg is not used in the next 3 instructions for (int i = 0; i < aCount; i++) { X64Reg xr = (X64Reg)aOrder[i]; @@ -203,7 +233,7 @@ X64Reg FPURegCache::GetFreeXReg() { return (X64Reg) -1; } -void FPURegCache::FlushR(X64Reg reg) { +void FPURegCache::FlushX(X64Reg reg) { if (reg >= NUM_X_FPREGS) PanicAlert("Flushing non existent reg"); if (xregs[reg].mipsReg != -1) { diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index cb4db210df..804d367ab0 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -28,7 +28,14 @@ using namespace Gen; // GPRs are numbered 0 to 31 // VFPU regs are numbered 32 to 160. -#define NUM_MIPS_FPRS (32 + 128) +enum { + NUM_TEMPS = 4, + TEMP0 = 32 + 128, + TEMP1 = TEMP0 + 1, + TEMP2 = TEMP0 + 2, + TEMP3 = TEMP0 + 3, + NUM_MIPS_FPRS = 32 + 128 + NUM_TEMPS, +}; #ifdef _M_X64 #define NUM_X_FPREGS 16 @@ -68,6 +75,7 @@ public: StoreFromRegister(preg + 32); } OpArg GetDefaultLocation(int reg) const; + void DiscardR(int preg); void SetEmitter(XEmitter *emitter) {emit = emitter;} @@ -100,6 +108,9 @@ public: void MapRegV(int vreg, int flags); void MapRegsV(int vec, VectorSize vsz, int flags); void MapRegsV(const u8 *v, VectorSize vsz, int flags); + void SpillLockV(int vreg) { + SpillLock(vreg + 32); + } void SpillLockV(const u8 *v, VectorSize vsz); void SpillLockV(int vec, VectorSize vsz); @@ -107,7 +118,7 @@ public: private: X64Reg GetFreeXReg(); - void FlushR(X64Reg reg); + void FlushX(X64Reg reg); const int *GetAllocationOrder(int &count); MIPSCachedFPReg regs[NUM_MIPS_FPRS]; From 0d5da967eb76ff75f78172c3acb45328f87feec3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 03:27:48 -0800 Subject: [PATCH 11/69] Enable VDot and Vec3 in x86 jit. --- Core/MIPS/x86/CompVFPU.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index dbc4733008..c1687ed85a 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -310,7 +310,7 @@ void Jit::Comp_SVQ(u32 op) } void Jit::Comp_VDot(u32 op) { - DISABLE; + CONDITIONAL_DISABLE; // WARNING: No prefix support! if (js.MayHavePrefix()) { @@ -357,7 +357,7 @@ void Jit::Comp_VDot(u32 op) { } void Jit::Comp_VecDo3(u32 op) { - DISABLE; + CONDITIONAL_DISABLE; // WARNING: No prefix support! if (js.MayHavePrefix()) From b90b0854e08b0ecf432e351e9594e48a894834bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 16 Feb 2013 13:51:31 +0100 Subject: [PATCH 12/69] Fix input responsiveness --- Qt/EmuThread.cpp | 13 ------------- Qt/QtHost.cpp | 3 ++- Qt/mainwindow.cpp | 24 ++++++++++++------------ Qt/mainwindow.h | 2 ++ 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/Qt/EmuThread.cpp b/Qt/EmuThread.cpp index 44c3fc6366..3c41af0359 100644 --- a/Qt/EmuThread.cpp +++ b/Qt/EmuThread.cpp @@ -219,19 +219,6 @@ void EmuThread::run() host->BootDone(); needInitGame = false; } - UpdateInputState(input_state); - - for (int i = 0; i < controllistCount; i++) { - if (input_state->pad_buttons_down & controllist[i].emu_id) { - __CtrlButtonDown(controllist[i].psp_id); - } - if (input_state->pad_buttons_up & controllist[i].emu_id) { - __CtrlButtonUp(controllist[i].psp_id); - } - } - __CtrlSetAnalog(input_state->pad_lstick_x, input_state->pad_lstick_y); - - EndInputState(input_state); glstate.Restore(); glViewport(0, 0, pixel_xres, pixel_yres); diff --git a/Qt/QtHost.cpp b/Qt/QtHost.cpp index 78cc696698..5a8989ead8 100644 --- a/Qt/QtHost.cpp +++ b/Qt/QtHost.cpp @@ -48,7 +48,6 @@ void QtHost::SetWindowTitle(const char *message) void QtHost::UpdateUI() { - mainWindow->Update(); mainWindow->UpdateMenus(); } @@ -77,7 +76,9 @@ void QtHost::SetDebugMode(bool mode) void QtHost::BeginFrame() { + mainWindow->Update(); } + void QtHost::EndFrame() { } diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index c951d70f53..af4cf7776a 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -697,22 +697,12 @@ void MainWindow::keyPressEvent(QKeyEvent *e) return; } - for (int b = 0; b < controllistCount; b++) { - if (e->key() == controllist[b].key) - { - input_state.pad_buttons |= (controllist[b].emu_id); - } - } + pressedKeys.insert(e->key()); } void MainWindow::keyReleaseEvent(QKeyEvent *e) { - for (int b = 0; b < controllistCount; b++) { - if (e->key() == controllist[b].key) - { - input_state.pad_buttons &= ~(controllist[b].emu_id); - } - } + pressedKeys.remove(e->key()); } void MainWindow::on_MainWindow_destroyed() @@ -928,7 +918,17 @@ void MainWindow::ShowMemory(u32 addr) void MainWindow::Update() { + UpdateInputState(&input_state); + for (int i = 0; i < controllistCount; i++) + { + if (pressedKeys.contains(controllist[i].key) || + input_state.pad_buttons_down & controllist[i].emu_id) + __CtrlButtonDown(controllist[i].psp_id); + else + __CtrlButtonUp(controllist[i].psp_id); + } + __CtrlSetAnalog(input_state.pad_lstick_x, input_state.pad_lstick_y); } void MainWindow::on_action_EmulationReset_triggered() diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 9b83c867ae..14a1b8af75 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -192,6 +192,8 @@ private: Debugger_Memory *memoryWindow; Controls* controls; GamePadDialog* gamePadDlg; + + QSet pressedKeys; }; #endif // MAINWINDOW_H From 2b5beb8510cf8ae228fe7eeab342a1a24915080d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 16 Feb 2013 10:01:32 +0100 Subject: [PATCH 13/69] Allow moving Android version to SD/usbmem. --- android/AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 236c3630d5..30812f98fa 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,7 +2,8 @@ + android:versionName="0.61" + android:installLocation="auto" > From 686c083b6f7cc58b7576c10c3dc6e965a1c8bded Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 16 Feb 2013 13:02:53 +0100 Subject: [PATCH 14/69] sceSas: initialize some stuff --- Core/HLE/sceSas.cpp | 1 + Core/HW/SasAudio.cpp | 1 + Core/HW/SasAudio.h | 9 +++++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 0a2aa4e785..91e4b047f9 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -70,6 +70,7 @@ u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampl for (int i = 0; i < sas->maxVoices; i++) { sas->voices[i].sampleRate = sampleRate; sas->voices[i].playing = false; + sas->voices[i].loop = true; // inverted flag } return 0; } diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 83966df79e..97f1b8837a 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -551,6 +551,7 @@ ADSREnvelope::ADSREnvelope() : steps_(0), state_(STATE_OFF), height_(0) { + memset(this, 0, sizeof(*this)); } void ADSREnvelope::WalkCurve(int rate, int type) { diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 6529425d36..9cba6c10ef 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -157,7 +157,9 @@ private: struct SasVoice { SasVoice() - : playing(false), paused(false), on(false), + : playing(false), + paused(false), + on(false), type(VOICETYPE_OFF), vagAddr(0), vagSize(0), @@ -171,7 +173,10 @@ struct SasVoice volumeLeft(0), volumeRight(0), volumeLeftSend(0), - volumeRightSend(0) { + volumeRightSend(0), + effectLeft(0), + effectRight(0) { + memset(resampleHist, 0, sizeof(resampleHist)); } void Reset(); From 9de6b834b9aa6830da7b667913182041e76db4a2 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sat, 16 Feb 2013 21:24:02 +0800 Subject: [PATCH 15/69] Fix g_Config.bJit inverted --- Windows/WndMainWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index b99eb0edbd..2f3b07e531 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -697,8 +697,8 @@ namespace MainWindow // CHECK(ID_OPTIONS_EMULATESYSCALL,g_bEmulateSyscall); CHECKITEM(ID_OPTIONS_DISPLAYRAWFRAMEBUFFER, g_Config.bDisplayFramebuffer); CHECKITEM(ID_OPTIONS_IGNOREILLEGALREADS,g_Config.bIgnoreBadMemAccess); - CHECKITEM(ID_CPU_INTERPRETER,g_Config.bJit == true); - CHECKITEM(ID_CPU_DYNAREC,g_Config.bJit == false); + CHECKITEM(ID_CPU_INTERPRETER,g_Config.bJit == false); + CHECKITEM(ID_CPU_DYNAREC,g_Config.bJit == true); CHECKITEM(ID_OPTIONS_BUFFEREDRENDERING, g_Config.bBufferedRendering); CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats); CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe); From 0bd382c51803a18a98cad5c2e3947255d1647c07 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 10:18:13 -0800 Subject: [PATCH 16/69] Discard temp regs right away, some helper funcs. --- Core/MIPS/x86/RegCacheFPU.cpp | 18 +++++++----------- Core/MIPS/x86/RegCacheFPU.h | 10 ++++++++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index f2356a6d57..fa637f7fb5 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -82,6 +82,8 @@ void FPURegCache::MapRegsV(const u8 *v, VectorSize sz, int flags) { void FPURegCache::ReleaseSpillLocks() { for (int i = 0; i < NUM_MIPS_FPRS; i++) regs[i].locked = false; + for (int i = TEMP0; i < TEMP0 + NUM_TEMPS; ++i) + DiscardR(i); } void FPURegCache::BindToRegister(const int i, bool doLoad, bool makeDirty) { @@ -126,8 +128,7 @@ void FPURegCache::StoreFromRegister(int i) { } } -void FPURegCache::DiscardR(int i) -{ +void FPURegCache::DiscardR(int i) { _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "FPU can't handle imm yet."); if (regs[i].away) { X64Reg xr = regs[i].location.GetSimpleReg(); @@ -142,6 +143,10 @@ void FPURegCache::DiscardR(int i) } } +bool FPURegCache::IsTemp(X64Reg xr) { + return xregs[xr].mipsReg >= TEMP0; +} + void FPURegCache::Flush() { for (int i = 0; i < TEMP0; i++) { if (regs[i].locked) { @@ -210,15 +215,6 @@ X64Reg FPURegCache::GetFreeXReg() { } //Okay, not found :( Force grab one - // Maybe a temp reg? - for (int i = TEMP0; i < NUM_MIPS_FPRS; ++i) { - if (regs[i].away && !regs[i].locked) { - X64Reg xr = regs[i].location.GetSimpleReg(); - DiscardR(i); - return xr; - } - } - //TODO - add a pass to grab xregs whose mipsreg is not used in the next 3 instructions for (int i = 0; i < aCount; i++) { X64Reg xr = (X64Reg)aOrder[i]; diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index 804d367ab0..429c25b148 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -26,7 +26,8 @@ using namespace Gen; // GPRs are numbered 0 to 31 -// VFPU regs are numbered 32 to 160. +// VFPU regs are numbered 32 to 159. +// Then we have some temp regs for VFPU handling from 160 to 167. enum { NUM_TEMPS = 4, @@ -34,6 +35,7 @@ enum { TEMP1 = TEMP0 + 1, TEMP2 = TEMP0 + 2, TEMP3 = TEMP0 + 3, + TEMP4 = TEMP0 + 4, NUM_MIPS_FPRS = 32 + 128 + NUM_TEMPS, }; @@ -75,7 +77,11 @@ public: StoreFromRegister(preg + 32); } OpArg GetDefaultLocation(int reg) const; - void DiscardR(int preg); + void DiscardR(int freg); + void DiscardV(int vreg) { + DiscardR(vreg + 32); + } + bool IsTemp(X64Reg xreg); void SetEmitter(XEmitter *emitter) {emit = emitter;} From 1c4c5e718b03534be7e8ad11db43cad218fc7103 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 10:19:05 -0800 Subject: [PATCH 17/69] Optimize VDot and VecDo3 to avoid temporaries. --- Core/MIPS/x86/CompVFPU.cpp | 41 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index c1687ed85a..6338099eb6 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -145,11 +145,12 @@ void Jit::ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWrit } // Vector regs can overlap in all sorts of swizzled ways. -bool DestRegOverlaps(int dreg, int sn, u8 sregs[], int tn, u8 tregs[]) +// This does allow a single overlap in sregs[i]. +bool DestRegOverlaps(int dreg, int di, int sn, u8 sregs[], int tn, u8 tregs[]) { for (int i = 0; i < sn; ++i) { - if (sregs[i] == dreg) + if (sregs[i] == dreg && i != di) return true; } for (int i = 0; i < tn; ++i) @@ -332,25 +333,34 @@ void Jit::Comp_VDot(u32 op) { // TODO: applyprefixST here somehow (shuffle, etc...) - MOVSS(XMM0, fpr.V(sregs[0])); - MULSS(XMM0, fpr.V(tregs[0])); - int n = GetNumVectorElements(sz); + X64Reg tempxreg = XMM0; + if (!DestRegOverlaps(dregs[0], 0, n, sregs, n, tregs)) + { + fpr.MapRegsV(dregs, V_Single, MAP_NOINIT); + tempxreg = fpr.VX(dregs[0]); + } + + if (!fpr.V(sregs[0]).IsSimpleReg(tempxreg)) + MOVSS(tempxreg, fpr.V(sregs[0])); + MULSS(tempxreg, fpr.V(tregs[0])); + for (int i = 1; i < n; i++) { // sum += s[i]*t[i]; MOVSS(XMM1, fpr.V(sregs[i])); MULSS(XMM1, fpr.V(tregs[i])); - ADDSS(XMM0, R(XMM1)); + ADDSS(tempxreg, R(XMM1)); } - fpr.ReleaseSpillLocks(); - fpr.MapRegsV(dregs, V_Single, MAP_NOINIT); + if (!fpr.V(dregs[0]).IsSimpleReg(tempxreg)) + { + fpr.MapRegsV(dregs, V_Single, MAP_NOINIT); + MOVSS(fpr.V(dregs[0]), XMM0); + } // TODO: applyprefixD here somehow (write mask etc..) - MOVSS(fpr.V(vd), XMM0); - fpr.ReleaseSpillLocks(); js.EatPrefix(); @@ -416,7 +426,7 @@ void Jit::Comp_VecDo3(u32 op) { X64Reg tempxregs[4]; for (int i = 0; i < n; ++i) { - if (DestRegOverlaps(dregs[i], n, sregs, n, tregs)) + if (DestRegOverlaps(dregs[i], i, n, sregs, n, tregs)) { // On 32-bit we only have 6 xregs for mips regs, use XMM0/XMM1 if possible. if (i < 2) @@ -430,19 +440,22 @@ void Jit::Comp_VecDo3(u32 op) { } else { - fpr.MapRegV(dregs[i], MAP_NOINIT | MAP_DIRTY); + fpr.MapRegV(dregs[i], (dregs[i] == sregs[i] ? 0 : MAP_NOINIT) | MAP_DIRTY); fpr.SpillLockV(dregs[i]); tempxregs[i] = fpr.VX(dregs[i]); } } for (int i = 0; i < n; ++i) - MOVSS(tempxregs[i], fpr.V(sregs[i])); + { + if (!fpr.V(sregs[i]).IsSimpleReg(tempxregs[i])) + MOVSS(tempxregs[i], fpr.V(sregs[i])); + } for (int i = 0; i < n; ++i) (this->*xmmop)(tempxregs[i], fpr.V(tregs[i])); for (int i = 0; i < n; ++i) { - if (!fpr.R(dregs[i]).IsSimpleReg(tempxregs[i])) + if (!fpr.V(dregs[i]).IsSimpleReg(tempxregs[i])) MOVSS(fpr.V(dregs[i]), tempxregs[i]); } From b27701ac7d19d4672946e793ffe7ab15fb3c6921 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 10:37:42 -0800 Subject: [PATCH 18/69] Fix VDot returning -0.0 in x86 jit. --- Core/MIPS/x86/CompVFPU.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 6338099eb6..958f6baf37 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -49,7 +49,7 @@ namespace MIPSComp static const float one = 1.0f; static const float minus_one = -1.0f; -static const float zero = -1.0f; +static const float zero = 0.0f; const u32 GC_ALIGNED16( noSignMask[4] ) = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; const u32 GC_ALIGNED16( signBitLower[4] ) = {0x80000000, 0, 0, 0}; @@ -341,9 +341,10 @@ void Jit::Comp_VDot(u32 op) { tempxreg = fpr.VX(dregs[0]); } - if (!fpr.V(sregs[0]).IsSimpleReg(tempxreg)) - MOVSS(tempxreg, fpr.V(sregs[0])); - MULSS(tempxreg, fpr.V(tregs[0])); + MOVSS(tempxreg, M((void *) &zero)); + MOVSS(XMM1, fpr.V(sregs[0])); + MULSS(XMM1, fpr.V(tregs[0])); + ADDSS(tempxreg, R(XMM1)); for (int i = 1; i < n; i++) { From 49e04609a89a3c045e2c5911cceb4b52ddf7c0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sun, 17 Feb 2013 00:37:42 +0100 Subject: [PATCH 19/69] Remove fast interpreter option --- Qt/EmuThread.cpp | 2 +- Qt/mainwindow.cpp | 23 ++++++----------------- Qt/mainwindow.h | 2 -- Qt/mainwindow.ui | 9 --------- 4 files changed, 7 insertions(+), 29 deletions(-) diff --git a/Qt/EmuThread.cpp b/Qt/EmuThread.cpp index 3c41af0359..065e5c7707 100644 --- a/Qt/EmuThread.cpp +++ b/Qt/EmuThread.cpp @@ -185,7 +185,7 @@ void EmuThread::run() coreParameter.fileToStart = fileToStart.toStdString(); coreParameter.enableSound = true; coreParameter.gpuCore = GPU_GLES; - coreParameter.cpuCore = (CPUCore)g_Config.iCpuCore; + coreParameter.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER; coreParameter.enableDebugging = true; coreParameter.printfEmuLog = false; coreParameter.headLess = false; diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index af4cf7776a..8f8efc2269 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -109,15 +109,11 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co gfxLog = true; break; case 'j': - g_Config.iCpuCore = CPU_JIT; - g_Config.bSaveSettings = false; - break; - case 'f': - g_Config.iCpuCore = CPU_FASTINTERPRETER; + g_Config.bJit = true; g_Config.bSaveSettings = false; break; case 'i': - g_Config.iCpuCore = CPU_INTERPRETER; + g_Config.bJit = false; g_Config.bSaveSettings = false; break; case 'l': @@ -231,9 +227,8 @@ void MainWindow::UpdateMenus() { ui->action_OptionsDisplayRawFramebuffer->setChecked(g_Config.bDisplayFramebuffer); ui->action_OptionsIgnoreIllegalReadsWrites->setChecked(g_Config.bIgnoreBadMemAccess); - ui->action_CPUInterpreter->setChecked(g_Config.iCpuCore == CPU_INTERPRETER); - ui->action_CPUFastInterpreter->setChecked(g_Config.iCpuCore == CPU_FASTINTERPRETER); - ui->action_CPUDynarec->setChecked(g_Config.iCpuCore == CPU_JIT); + ui->action_CPUInterpreter->setChecked(!g_Config.bJit); + ui->action_CPUDynarec->setChecked(g_Config.bJit); ui->action_OptionsBufferedRendering->setChecked(g_Config.bBufferedRendering); ui->action_OptionsShowDebugStatistics->setChecked(g_Config.bShowDebugStats); ui->action_OptionsWireframe->setChecked(g_Config.bDrawWireframe); @@ -518,19 +513,13 @@ void MainWindow::on_action_FileExit_triggered() void MainWindow::on_action_CPUDynarec_triggered() { - g_Config.iCpuCore = CPU_JIT; + g_Config.bJit = true; UpdateMenus(); } void MainWindow::on_action_CPUInterpreter_triggered() { - g_Config.iCpuCore = CPU_INTERPRETER; - UpdateMenus(); -} - -void MainWindow::on_action_CPUFastInterpreter_triggered() -{ - g_Config.iCpuCore = CPU_FASTINTERPRETER; + g_Config.bJit = false; UpdateMenus(); } diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 14a1b8af75..013bb54e1b 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -81,8 +81,6 @@ private slots: void on_action_CPUInterpreter_triggered(); - void on_action_CPUFastInterpreter_triggered(); - void on_action_DebugLoadMapFile_triggered(); void on_action_DebugSaveMapFile_triggered(); diff --git a/Qt/mainwindow.ui b/Qt/mainwindow.ui index a167aad884..10f40c73a7 100644 --- a/Qt/mainwindow.ui +++ b/Qt/mainwindow.ui @@ -180,7 +180,6 @@ &Core - @@ -289,14 +288,6 @@ &Interpreter - - - true - - - &Slightly Faster Interpreter - - true From 2a6af9b8a3b4e00a1e6ee1f5a9912c2c03c04098 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sun, 17 Feb 2013 01:06:06 +0100 Subject: [PATCH 20/69] Add displayList debug dialog --- Core/Core.cpp | 2 + Core/Host.h | 5 +- GPU/GLES/DisplayListInterpreter.cpp | 5 + GPU/GLES/DisplayListInterpreter.h | 7 + GPU/GLES/Framebuffer.cpp | 20 + GPU/GLES/Framebuffer.h | 3 + GPU/GLES/TextureCache.cpp | 288 +++++ GPU/GLES/TextureCache.h | 2 + GPU/GPUCommon.cpp | 14 +- GPU/GPUCommon.h | 9 + GPU/GPUInterface.h | 15 + Qt/EmuThread.cpp | 24 +- Qt/QtHost.cpp | 36 +- Qt/QtHost.h | 6 +- Qt/ctrldisasmview.cpp | 17 +- Qt/ctrlmemview.cpp | 7 +- Qt/ctrlregisterlist.cpp | 11 +- Qt/ctrlvfpuview.cpp | 11 +- Qt/debugger_disasm.cpp | 130 +-- Qt/debugger_disasm.h | 5 - Qt/debugger_disasm.ui | 66 +- Qt/debugger_displaylist.cpp | 1520 +++++++++++++++++++++++++++ Qt/debugger_displaylist.h | 114 ++ Qt/debugger_displaylist.ui | 527 ++++++++++ Qt/debugger_memory.cpp | 6 +- Qt/debugger_memorytex.cpp | 93 ++ Qt/debugger_memorytex.h | 30 + Qt/debugger_memorytex.ui | 177 ++++ Qt/mainwindow.cpp | 31 +- Qt/mainwindow.h | 10 + Qt/mainwindow.ui | 9 +- 31 files changed, 2950 insertions(+), 250 deletions(-) create mode 100644 Qt/debugger_displaylist.cpp create mode 100644 Qt/debugger_displaylist.h create mode 100644 Qt/debugger_displaylist.ui create mode 100644 Qt/debugger_memorytex.cpp create mode 100644 Qt/debugger_memorytex.h create mode 100644 Qt/debugger_memorytex.ui diff --git a/Core/Core.cpp b/Core/Core.cpp index f66929d071..fb8f92966c 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -100,6 +100,8 @@ reswitch: case CORE_STEPPING: //1: wait for step command.. #if defined(USING_QT_UI) || defined(_DEBUG) + host->UpdateDisassembly(); + host->UpdateMemView(); host->SendCoreWait(true); #endif diff --git a/Core/Host.h b/Core/Host.h index f20277ac20..65d1782489 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -64,8 +64,9 @@ public: virtual void SendCoreWait(bool) {} virtual bool GpuStep() { return false; } - virtual void SendGPUWait() {} - virtual void SetGPUStep(bool value) {} + virtual void SendGPUStart() {} + virtual void SendGPUWait(u32 cmd) {} + virtual void SetGPUStep(bool value, int flag = 0) {} virtual void NextGPUStep() {} // Used for headless. diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 039fc97910..e9f1bb7854 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -1056,6 +1056,11 @@ void GLES_GPU::Resized() { framebufferManager_.Resized(); } +std::vector GLES_GPU::GetFramebufferList() +{ + return framebufferManager_.GetFramebufferList(); +} + void GLES_GPU::DoState(PointerWrap &p) { GPUCommon::DoState(p); diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 7054f60e14..52e1883730 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -59,6 +59,13 @@ public: // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. virtual void Resized(); + virtual bool DecodeTexture(u8* dest, GPUgstate state) + { + return textureCache_.DecodeTexture(dest, state); + } + + + std::vector GetFramebufferList(); private: void DoBlockTransfer(); diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 7ed3fefd6a..bc513f90e0 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -449,6 +449,26 @@ void FramebufferManager::SetDisplayFramebuffer(u32 framebuf, u32 stride, int for } } +std::vector FramebufferManager::GetFramebufferList() +{ + std::vector list; + + for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { + VirtualFramebuffer *vfb = *iter; + + FramebufferInfo info; + info.fb_address = vfb->fb_address; + info.z_address = vfb->z_address; + info.format = vfb->format; + info.width = vfb->width; + info.height = vfb->height; + info.fbo = vfb->fbo; + list.push_back(info); + } + + return list; +} + void FramebufferManager::DecimateFBOs() { for (auto iter = vfbs_.begin(); iter != vfbs_.end();) { VirtualFramebuffer *vfb = *iter; diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index dd7dcee56a..c5a86426c9 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -26,6 +26,7 @@ #include "../Globals.h" +#include "GPU/GPUCommon.h" struct GLSLProgram; class TextureCache; @@ -80,6 +81,8 @@ public: void SetDisplayFramebuffer(u32 framebuf, u32 stride, int format); size_t NumVFBs() const { return vfbs_.size(); } + std::vector GetFramebufferList(); + int GetRenderWidth() const { return currentRenderVfb_ ? currentRenderVfb_->renderWidth : 480; } int GetRenderHeight() const { return currentRenderVfb_ ? currentRenderVfb_->renderHeight : 272; } int GetTargetWidth() const { return currentRenderVfb_ ? currentRenderVfb_->width : 480; } diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 4b964a274e..6487e9ce36 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -1131,3 +1131,291 @@ void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level) GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA; glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, components, dstFmt, finalBuf); } + +bool TextureCache::DecodeTexture(u8* output, GPUgstate state) +{ + GPUgstate oldState = gstate; + gstate = state; + + u32 texaddr = (gstate.texaddr[0] & 0xFFFFF0) | ((gstate.texbufwidth[0]<<8) & 0x0F000000); + + if (!Memory::IsValidAddress(texaddr)) { + return false; + } + + u8 level = 0; + u32 format = gstate.texformat & 0xF; + if (format >= 11) { + ERROR_LOG(G3D, "Unknown texture format %i", format); + format = 0; + } + + u32 clutformat = gstate.clutformat & 3; + u32 clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2); + + const u8 *texptr = Memory::GetPointer(texaddr); + u32 texhash = texptr ? MiniHash((const u32*)texptr) : 0; + + u64 cachekey = texaddr ^ texhash; + if (formatUsesClut[format]) + cachekey |= (u64) clutaddr << 32; + + int bufw = gstate.texbufwidth[0] & 0x3ff; + + int w = 1 << (gstate.texsize[0] & 0xf); + int h = 1 << ((gstate.texsize[0]>>8) & 0xf); + + + GLenum dstFmt = 0; + u32 texByteAlign = 1; + + void *finalBuf = NULL; + + // TODO: Look into using BGRA for 32-bit textures when the GL_EXT_texture_format_BGRA8888 extension is available, as it's faster than RGBA on some chips. + + // TODO: Actually decode the mipmaps. + + switch (format) + { + case GE_TFMT_CLUT4: + dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3)); + + switch (clutformat) { + case GE_CMODE_16BIT_BGR5650: + case GE_CMODE_16BIT_ABGR5551: + case GE_CMODE_16BIT_ABGR4444: + { + ReadClut16(clutBuf16); + const u16 *clut = clutBuf16; + u32 clutSharingOff = 0;//gstate.mipmapShareClut ? 0 : level * 16; + texByteAlign = 2; + if (!(gstate.texmode & 1)) { + const u8 *addr = Memory::GetPointer(texaddr); + for (int i = 0; i < bufw * h; i += 2) + { + u8 index = *addr++; + tmpTexBuf16[i + 0] = clut[GetClutIndex((index >> 0) & 0xf) + clutSharingOff]; + tmpTexBuf16[i + 1] = clut[GetClutIndex((index >> 4) & 0xf) + clutSharingOff]; + } + } else { + UnswizzleFromMem(texaddr, 0, level); + for (int i = 0, j = 0; i < bufw * h; i += 8, j++) + { + u32 n = tmpTexBuf32[j]; + u32 k, index; + for (k = 0; k < 8; k++) { + index = (n >> (k * 4)) & 0xf; + tmpTexBuf16[i + k] = clut[GetClutIndex(index) + clutSharingOff]; + } + } + } + finalBuf = tmpTexBuf16; + } + break; + + case GE_CMODE_32BIT_ABGR8888: + { + ReadClut32(clutBuf32); + const u32 *clut = clutBuf32; + u32 clutSharingOff = 0;//gstate.mipmapShareClut ? 0 : level * 16; + if (!(gstate.texmode & 1)) { + const u8 *addr = Memory::GetPointer(texaddr); + for (int i = 0; i < bufw * h; i += 2) + { + u8 index = *addr++; + tmpTexBuf32[i + 0] = clut[GetClutIndex((index >> 0) & 0xf) + clutSharingOff]; + tmpTexBuf32[i + 1] = clut[GetClutIndex((index >> 4) & 0xf) + clutSharingOff]; + } + } else { + u32 pixels = bufw * h; + UnswizzleFromMem(texaddr, 0, level); + for (int i = pixels - 8, j = (pixels / 8) - 1; i >= 0; i -= 8, j--) { + u32 n = tmpTexBuf32[j]; + for (int k = 0; k < 8; k++) { + u32 index = (n >> (k * 4)) & 0xf; + tmpTexBuf32[i + k] = clut[GetClutIndex(index) + clutSharingOff]; + } + } + } + finalBuf = tmpTexBuf32; + } + break; + + default: + ERROR_LOG(G3D, "Unknown CLUT4 texture mode %d", (gstate.clutformat & 3)); + return false; + } + break; + + case GE_TFMT_CLUT8: + finalBuf = readIndexedTex(level, texaddr, 1); + dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3)); + texByteAlign = texByteAlignMap[(gstate.clutformat & 3)]; + break; + + case GE_TFMT_CLUT16: + finalBuf = readIndexedTex(level, texaddr, 2); + dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3)); + texByteAlign = texByteAlignMap[(gstate.clutformat & 3)]; + break; + + case GE_TFMT_CLUT32: + finalBuf = readIndexedTex(level, texaddr, 4); + dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3)); + texByteAlign = texByteAlignMap[(gstate.clutformat & 3)]; + break; + + case GE_TFMT_4444: + case GE_TFMT_5551: + case GE_TFMT_5650: + if (format == GE_TFMT_4444) + dstFmt = GL_UNSIGNED_SHORT_4_4_4_4; + else if (format == GE_TFMT_5551) + dstFmt = GL_UNSIGNED_SHORT_5_5_5_1; + else if (format == GE_TFMT_5650) + dstFmt = GL_UNSIGNED_SHORT_5_6_5; + texByteAlign = 2; + + if (!(gstate.texmode & 1)) { + int len = std::max(bufw, w) * h; + for (int i = 0; i < len; i++) + tmpTexBuf16[i] = Memory::ReadUnchecked_U16(texaddr + i * 2); + finalBuf = tmpTexBuf16; + } + else + finalBuf = UnswizzleFromMem(texaddr, 2, level); + break; + + case GE_TFMT_8888: + dstFmt = GL_UNSIGNED_BYTE; + if (!(gstate.texmode & 1)) { + int len = bufw * h; + for (int i = 0; i < len; i++) + tmpTexBuf32[i] = Memory::ReadUnchecked_U32(texaddr + i * 4); + finalBuf = tmpTexBuf32; + } + else + finalBuf = UnswizzleFromMem(texaddr, 4, level); + break; + + case GE_TFMT_DXT1: + dstFmt = GL_UNSIGNED_BYTE; + { + u32 *dst = tmpTexBuf32; + DXT1Block *src = (DXT1Block*)texptr; + + for (int y = 0; y < h; y += 4) { + u32 blockIndex = (y / 4) * (bufw / 4); + for (int x = 0; x < std::min(bufw, w); x += 4) { + decodeDXT1Block(dst + bufw * y + x, src + blockIndex, bufw); + blockIndex++; + } + } + finalBuf = tmpTexBuf32; + w = (w + 3) & ~3; + } + break; + + case GE_TFMT_DXT3: + dstFmt = GL_UNSIGNED_BYTE; + { + u32 *dst = tmpTexBuf32; + DXT3Block *src = (DXT3Block*)texptr; + + // Alpha is off + for (int y = 0; y < h; y += 4) { + u32 blockIndex = (y / 4) * (bufw / 4); + for (int x = 0; x < std::min(bufw, w); x += 4) { + decodeDXT3Block(dst + bufw * y + x, src + blockIndex, bufw); + blockIndex++; + } + } + w = (w + 3) & ~3; + finalBuf = tmpTexBuf32; + } + break; + + case GE_TFMT_DXT5: + ERROR_LOG(G3D, "Unhandled compressed texture, format %i! swizzle=%i", format, gstate.texmode & 1); + dstFmt = GL_UNSIGNED_BYTE; + { + u32 *dst = tmpTexBuf32; + DXT5Block *src = (DXT5Block*)texptr; + + // Alpha is almost right + for (int y = 0; y < h; y += 4) { + u32 blockIndex = (y / 4) * (bufw / 4); + for (int x = 0; x < std::min(bufw, w); x += 4) { + decodeDXT5Block(dst + bufw * y + x, src + blockIndex, bufw); + blockIndex++; + } + } + w = (w + 3) & ~3; + finalBuf = tmpTexBuf32; + } + break; + + default: + ERROR_LOG(G3D, "Unknown Texture Format %d!!!", format); + finalBuf = tmpTexBuf32; + return false; + } + + if (!finalBuf) { + ERROR_LOG(G3D, "NO finalbuf! Will crash!"); + } + + convertColors((u8*)finalBuf, dstFmt, bufw * h); + + if(dstFmt == GL_UNSIGNED_SHORT_4_4_4_4) + { + for(int x = 0; x < h; x++) + for(int y = 0; y < bufw; y++) + { + u32 val = ((u16*)finalBuf)[x*bufw + y]; + u32 a = (val & 0xF) * 255 / 15; + u32 r = ((val & 0xF) >> 24) * 255 / 15; + u32 g = ((val & 0xF) >> 16) * 255 / 15; + u32 b = ((val & 0xF) >> 8) * 255 / 15; + ((u32*)output)[x*w + y] = (a << 24) | (r << 16) | (g << 8) | b; + } + } + else if(dstFmt == GL_UNSIGNED_SHORT_5_5_5_1) + { + for(int x = 0; x < h; x++) + for(int y = 0; y < bufw; y++) + { + u32 val = ((u16*)finalBuf)[x*bufw + y]; + u32 a = (val & 0x1) * 255; + u32 r = ((val & 0x1F) >> 11) * 255 / 31; + u32 g = ((val & 0x1F) >> 6) * 255 / 31; + u32 b = ((val & 0x1F) >> 1) * 255 / 31; + ((u32*)output)[x*w + y] = (a << 24) | (r << 16) | (g << 8) | b; + } + } + else if(dstFmt == GL_UNSIGNED_SHORT_5_6_5) + { + for(int x = 0; x < h; x++) + for(int y = 0; y < bufw; y++) + { + u32 val = ((u16*)finalBuf)[x*bufw + y]; + u32 a = 0xFF; + u32 r = ((val & 0x1F) >> 11) * 255 / 31; + u32 g = ((val & 0x3F) >> 6) * 255 / 63; + u32 b = ((val & 0x1F)) * 255 / 31; + ((u32*)output)[x*w + y] = (a << 24) | (r << 16) | (g << 8) | b; + } + } + else + { + for(int x = 0; x < h; x++) + for(int y = 0; y < bufw; y++) + { + u32 val = ((u32*)finalBuf)[x*bufw + y]; + ((u32*)output)[x*w + y] = ((val & 0xFF000000)) | ((val & 0x00FF0000)>>16) | ((val & 0x0000FF00)) | ((val & 0x000000FF)<<16); + } + } + + gstate = oldState; + return true; +} diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index bb1958c365..764ad63735 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -19,6 +19,7 @@ #include "../Globals.h" #include "gfx_es2/fbo.h" +#include "GPU/GPUState.h" class TextureCache { @@ -42,6 +43,7 @@ public: return cache.size(); } + bool DecodeTexture(u8 *output, GPUgstate state); private: struct TexCacheEntry { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index d41ab94ab2..ff050581ed 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -76,6 +76,12 @@ bool GPUCommon::InterpretList(DisplayList &list) ERROR_LOG(G3D, "DL PC = %08x WTF!!!!", list.pc); return true; } +#if defined(USING_QT_UI) + if(host->GpuStep()) + { + host->SendGPUStart(); + } +#endif while (!finished) { @@ -85,14 +91,16 @@ bool GPUCommon::InterpretList(DisplayList &list) list.status = PSP_GE_LIST_STALL_REACHED; return false; } + + op = Memory::ReadUnchecked_U32(list.pc); //read from memory + u32 cmd = op >> 24; + #if defined(USING_QT_UI) if(host->GpuStep()) { - host->SendGPUWait(); + host->SendGPUWait(cmd); } #endif - op = Memory::ReadUnchecked_U32(list.pc); //read from memory - u32 cmd = op >> 24; u32 diff = op ^ gstate.cmdmem[cmd]; PreExecuteOp(op, diff); // TODO: Add a compiler flag to remove stuff like this at very-final build time. diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 66b6ccbdd8..8feb9cb569 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -62,4 +62,13 @@ public: { return currentList; } + virtual bool DecodeTexture(u8* dest, GPUgstate state) + { + return false; + } + std::vector GetFramebufferList() + { + return std::vector(); + } + }; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 07886c4e30..4edb5de1c5 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -18,6 +18,7 @@ #pragma once #include "../Globals.h" +#include "GPUState.h" #include class PointerWrap; @@ -32,6 +33,18 @@ enum DisplayListStatus PSP_GE_LIST_CANCEL_DONE = 5, // canceled? }; + +// Used for debug +struct FramebufferInfo +{ + u32 fb_address; + u32 z_address; + int format; + u32 width; + u32 height; + void* fbo; +}; + struct DisplayList { int id; @@ -94,4 +107,6 @@ public: virtual void DumpNextFrame() = 0; virtual const std::deque& GetDisplayLists() = 0; virtual DisplayList* GetCurrentDisplayList() = 0; + virtual bool DecodeTexture(u8* dest, GPUgstate state) = 0; + virtual std::vector GetFramebufferList() = 0; }; diff --git a/Qt/EmuThread.cpp b/Qt/EmuThread.cpp index 065e5c7707..4dd3a64570 100644 --- a/Qt/EmuThread.cpp +++ b/Qt/EmuThread.cpp @@ -152,7 +152,7 @@ void EmuThread::run() host->UpdateUI(); host->InitGL(); - glWindow->makeCurrent(); + EmuThread_LockDraw(true); #ifndef USING_GLES2 glewInit(); @@ -163,6 +163,8 @@ void EmuThread::run() QElapsedTimer timer; + EmuThread_LockDraw(false); + while(running) { //UpdateGamepad(*input_state); timer.start(); @@ -173,10 +175,7 @@ void EmuThread::run() if(gRun) { - - gameMutex->lock(); - - glWindow->makeCurrent(); + EmuThread_LockDraw(true); if(needInitGame) { g_State.bEmuThreadStarted = true; @@ -239,14 +238,12 @@ void EmuThread::run() qint64 time = timer.elapsed(); const int frameTime = (1.0f/60.0f) * 1000; - gameMutex->unlock(); if(time < frameTime) { - glWindow->doneCurrent(); + EmuThread_LockDraw(false); msleep(frameTime-time); - glWindow->makeCurrent(); + EmuThread_LockDraw(true); } - gameMutex->lock(); timer.start(); } @@ -276,13 +273,11 @@ void EmuThread::run() } #endif glWindow->swapBuffers(); - glWindow->doneCurrent(); - gameMutex->unlock(); + EmuThread_LockDraw(false); } else { - gameMutex->lock(); - glWindow->makeCurrent(); + EmuThread_LockDraw(true); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -323,8 +318,7 @@ void EmuThread::run() ui_draw2d.Flush(UIShader_Get()); glWindow->swapBuffers(); - glWindow->doneCurrent(); - gameMutex->unlock(); + EmuThread_LockDraw(false); qint64 time = timer.elapsed(); const int frameTime = (1.0f/60.0f) * 1000; if(time < frameTime) diff --git a/Qt/QtHost.cpp b/Qt/QtHost.cpp index 5a8989ead8..ca55e43879 100644 --- a/Qt/QtHost.cpp +++ b/Qt/QtHost.cpp @@ -12,6 +12,7 @@ #include "android/jni/EmuScreen.h" #include "android/jni/UIShader.h" #include "android/jni/ui_atlas.h" +#include "GPU/ge_constants.h" #include "EmuThread.h" std::string boot_filename = ""; @@ -65,6 +66,10 @@ void QtHost::UpdateDisassembly() mainWindow->GetDialogDisasm()->GotoPC(); mainWindow->GetDialogDisasm()->Update(); } + if(mainWindow->GetDialogDisplaylist()) + { + mainWindow->GetDialogDisplaylist()->Update(); + } } void QtHost::SetDebugMode(bool mode) @@ -145,19 +150,42 @@ bool QtHost::GpuStep() return m_GPUStep; } -void QtHost::SendGPUWait() +void QtHost::SendGPUStart() { EmuThread_LockDraw(false); - mainWindow->GetDialogDisasm()->UpdateDisplayList(); - m_hGPUStepEvent.wait(m_hGPUStepMutex); + if(m_GPUFlag == -1) + { + m_GPUFlag = 0; + } EmuThread_LockDraw(true); } -void QtHost::SetGPUStep(bool value) +void QtHost::SendGPUWait(u32 cmd) +{ + EmuThread_LockDraw(false); + + if((m_GPUFlag == 1 && (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE))) + { + // Break after the draw + m_GPUFlag = 0; + } + else if(m_GPUFlag == 0) + { + + mainWindow->GetDialogDisasm()->UpdateDisplayList(); + mainWindow->GetDialogDisplaylist()->Update(); + m_hGPUStepEvent.wait(m_hGPUStepMutex); + } + + EmuThread_LockDraw(true); +} + +void QtHost::SetGPUStep(bool value, int flag) { m_GPUStep = value; + m_GPUFlag = flag; } void QtHost::NextGPUStep() diff --git a/Qt/QtHost.h b/Qt/QtHost.h index b98ec8954e..8f578c9fd5 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -51,8 +51,9 @@ public: void SendCoreWait(bool); bool GpuStep(); - void SendGPUWait(); - void SetGPUStep(bool value); + void SendGPUWait(u32 cmd); + void SendGPUStart(); + void SetGPUStep(bool value, int flag = 0); void NextGPUStep(); signals: @@ -60,6 +61,7 @@ signals: private: MainWindow* mainWindow; bool m_GPUStep; + int m_GPUFlag; }; #endif // QTAPP_H diff --git a/Qt/ctrldisasmview.cpp b/Qt/ctrldisasmview.cpp index a2b7a00829..92d43f8e51 100644 --- a/Qt/ctrldisasmview.cpp +++ b/Qt/ctrldisasmview.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -164,9 +163,7 @@ void CtrlDisAsmView::GoToMemoryView() void CtrlDisAsmView::CopyAddress() { - char temp[16]; - sprintf(temp,"%08x",selection); - QApplication::clipboard()->setText(QString(temp)); + QApplication::clipboard()->setText(QString("%1").arg(selection,8,16,QChar('0'))); } void CtrlDisAsmView::CopyInstrDisAsm() @@ -178,11 +175,9 @@ void CtrlDisAsmView::CopyInstrDisAsm() void CtrlDisAsmView::CopyInstrHex() { - char temp[24]; EmuThread_LockDraw(true); - sprintf(temp,"%08x",debugger->readMemory(selection)); + QApplication::clipboard()->setText(QString("%1").arg(debugger->readMemory(selection),8,16,QChar('0'))); EmuThread_LockDraw(false); - QApplication::clipboard()->setText(temp); } void CtrlDisAsmView::SetNextStatement() @@ -234,8 +229,7 @@ void CtrlDisAsmView::RenameFunction() int sym = symbolMap.GetSymbolNum(selection); if (sym != -1) { - char name[256]; - strncpy(name, symbolMap.GetSymbolName(sym),256); + QString name = symbolMap.GetSymbolName(sym); bool ok; QString newname = QInputDialog::getText(this, tr("New function name"), tr("New function name:"), QLineEdit::Normal, @@ -300,8 +294,6 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *) int rowY1 = rect().bottom()/2 + rowHeight*i - rowHeight/2; int rowY2 = rect().bottom()/2 + rowHeight*i + rowHeight/2 - 1; - char temp[256]; - sprintf(temp,"%08x",address); lbr.setColor(marker==address?QColor(0xFFFFEEE0):QColor(debugger->getColor(address))); QColor bg = lbr.color(); @@ -319,7 +311,6 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *) if (address == debugger->getPC()) { painter.setBrush(pcBrush); - qDebug() << address; } painter.drawRect(16,rowY1,width-16-1,rowY2-rowY1); @@ -327,7 +318,7 @@ void CtrlDisAsmView::paintEvent(QPaintEvent *) QPen textPen = QPen(QColor(halfAndHalf(bg.rgba(),0))); painter.setPen(textPen); painter.setFont(alignedFont); - painter.drawText(17,rowY1-3+rowHeight,QString(temp)); + painter.drawText(17,rowY1-3+rowHeight,QString("%1").arg(address,8,16,QChar('0'))); painter.setFont(normalFont); textPen.setColor(QColor(0xFF000000)); painter.setPen(textPen); diff --git a/Qt/ctrlmemview.cpp b/Qt/ctrlmemview.cpp index ffc768c48f..c7c6637436 100644 --- a/Qt/ctrlmemview.cpp +++ b/Qt/ctrlmemview.cpp @@ -108,7 +108,6 @@ void CtrlMemView::paintEvent(QPaintEvent *) int rowY2 = rect().bottom()/2 + rowHeight*i + rowHeight/2; char temp[256]; - sprintf(temp,"%08x",address); painter.setBrush(currentBrush); @@ -123,7 +122,7 @@ void CtrlMemView::paintEvent(QPaintEvent *) textPen.setColor(0x600000); painter.setPen(textPen); painter.setFont(alignedFont); - painter.drawText(17,rowY1-2+rowHeight, temp); + painter.drawText(17,rowY1-2+rowHeight, QString("%1").arg(address,8,16,QChar('0'))); textPen.setColor(0xFF000000); painter.setPen(textPen); if (debugger->isAlive()) @@ -231,9 +230,7 @@ void CtrlMemView::contextMenu(const QPoint &pos) void CtrlMemView::CopyValue() { - char temp[24]; - sprintf(temp,"%08x",Memory::ReadUnchecked_U32(selection)); - QApplication::clipboard()->setText(temp); + QApplication::clipboard()->setText(QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0'))); } void CtrlMemView::Dump() diff --git a/Qt/ctrlregisterlist.cpp b/Qt/ctrlregisterlist.cpp index 09fa91632f..a52c5c88ab 100644 --- a/Qt/ctrlregisterlist.cpp +++ b/Qt/ctrlregisterlist.cpp @@ -236,14 +236,14 @@ void CtrlRegisterList::paintEvent(QPaintEvent *) painter.setBrush(currentBrush); if (iGetNumRegsInCategory(category)) { - char temp[256]; - sprintf(temp,"%s",cpu->GetRegName(category,i)); + QString regName = cpu->GetRegName(category,i); textPen.setColor(0x600000); painter.setPen(textPen); - painter.drawText(17,rowY1-3+rowHeight,temp); + painter.drawText(17,rowY1-3+rowHeight,regName); textPen.setColor(0xFF000000); painter.setPen(textPen); + char temp[256]; cpu->PrintRegValue(category,i,temp); if (category == 0 && changedCat0Regs[i]) { @@ -331,10 +331,7 @@ void CtrlRegisterList::CopyValue() u32 val = cpu->GetRegValue(cat,reg); EmuThread_LockDraw(false); - char temp[24]; - sprintf(temp,"%08x",val); - - QApplication::clipboard()->setText(temp); + QApplication::clipboard()->setText(QString("%1").arg(val,8,16,QChar('0'))); } void CtrlRegisterList::Change() diff --git a/Qt/ctrlvfpuview.cpp b/Qt/ctrlvfpuview.cpp index 5ce363dd95..cfdde62084 100644 --- a/Qt/ctrlvfpuview.cpp +++ b/Qt/ctrlvfpuview.cpp @@ -45,9 +45,7 @@ void CtrlVfpuView::paintEvent(QPaintEvent *) { int my = (int)(yStart + matrix * rowHeight * 5.5f); painter.drawRect(0, my, xStart-1, rowHeight-1); - char temp[256]; - sprintf(temp, "M%i00", matrix); - painter.drawText(3, my+rowHeight-3, temp); + painter.drawText(3, my+rowHeight-3, QString("M%1").arg(matrix)+"00"); painter.drawRect(xStart, my+rowHeight, columnWidth*4-1, 4*rowHeight-1); for (int column = 0; column<4; column++) @@ -56,13 +54,10 @@ void CtrlVfpuView::paintEvent(QPaintEvent *) int x = column * columnWidth + xStart; painter.drawRect(x, y, columnWidth-1, rowHeight - 1); - char temp[256]; - sprintf(temp, "R%i0%i", matrix, column); - painter.drawText(x+3, y-3+rowHeight, temp); + painter.drawText(x+3, y-3+rowHeight, QString("R%1").arg(matrix)+QString("0%1").arg(column)); painter.drawRect(0, y+rowHeight*(column+1), xStart - 1, rowHeight - 1); - sprintf(temp, "C%i%i0", matrix, column); - painter.drawText(3, y+rowHeight*(column+2)-3, temp); + painter.drawText(3, y+rowHeight*(column+2)-3, QString("C%1").arg(matrix)+QString("%1").arg(column)+"0"); y+=rowHeight; diff --git a/Qt/debugger_disasm.cpp b/Qt/debugger_disasm.cpp index bd1a007f07..2b670bb150 100644 --- a/Qt/debugger_disasm.cpp +++ b/Qt/debugger_disasm.cpp @@ -344,7 +344,7 @@ void Debugger_Disasm::FillFunctions() if(symbolMap.GetSymbolType(i) & ST_FUNCTION) { QListWidgetItem* item = new QListWidgetItem(); - item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QVariant(symbolMap.GetSymbolSize(i)).toString() +")"); + item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QString::number(symbolMap.GetSymbolSize(i)) +")"); item->setData(Qt::UserRole, symbolMap.GetAddress(i)); ui->FuncList->addItem(item); } @@ -372,9 +372,7 @@ void Debugger_Disasm::UpdateBreakpointsGUI() if(!CBreakPoints::IsTempBreakPoint(addr_)) { QTreeWidgetItem* item = new QTreeWidgetItem(); - char temp[24]; - sprintf(temp,"%08x",addr_); - item->setText(0,temp); + item->setText(0,QString("%1").arg(addr_,8,16,QChar('0'))); item->setData(0,Qt::UserRole,addr_); ui->breakpointsList->addTopLevelItem(item); if(curBpAddr == addr_) @@ -434,7 +432,7 @@ void Debugger_Disasm::UpdateThreadGUI() for(int i = 0; i < threads.size(); i++) { QTreeWidgetItem* item = new QTreeWidgetItem(); - item->setText(0,QVariant(threads[i].id).toString()); + item->setText(0,QString::number(threads[i].id)); item->setData(0,Qt::UserRole,threads[i].id); item->setText(1,threads[i].name); QString status = ""; @@ -445,12 +443,9 @@ void Debugger_Disasm::UpdateThreadGUI() if(threads[i].status & THREADSTATUS_DORMANT) status += "Dormant "; if(threads[i].status & THREADSTATUS_DEAD) status += "Dead "; item->setText(2,status); - char temp[24]; - sprintf(temp,"%08x",threads[i].curPC); - item->setText(3,temp); + item->setText(3,QString("%1").arg(threads[i].curPC,8,16,QChar('0'))); item->setData(3,Qt::UserRole,threads[i].curPC); - sprintf(temp,"%08x",threads[i].entrypoint); - item->setText(4,temp); + item->setText(4,QString("%1").arg(threads[i].entrypoint,8,16,QChar('0'))); item->setData(4,Qt::UserRole,threads[i].entrypoint); if(threads[i].isCurrent) @@ -461,6 +456,8 @@ void Debugger_Disasm::UpdateThreadGUI() ui->threadList->addTopLevelItem(item); } + for(int i = 0; i < ui->threadList->columnCount(); i++) + ui->threadList->resizeColumnToContents(i); } void Debugger_Disasm::on_threadList_itemClicked(QTreeWidgetItem *item, int column) @@ -542,7 +539,6 @@ void Debugger_Disasm::UpdateDisplayListGUI() curDlId = ui->displayList->currentItem()->data(0,Qt::UserRole).toInt(); ui->displayList->clear(); - ui->displayListData->clear(); EmuThread_LockDraw(true); const std::deque& dlQueue = gpu->GetDisplayLists(); @@ -551,7 +547,7 @@ void Debugger_Disasm::UpdateDisplayListGUI() if(dl) { QTreeWidgetItem* item = new QTreeWidgetItem(); - item->setText(0,QVariant(dl->id).toString()); + item->setText(0,QString::number(dl->id)); item->setData(0, Qt::UserRole, dl->id); switch(dl->status) { @@ -563,19 +559,15 @@ void Debugger_Disasm::UpdateDisplayListGUI() case PSP_GE_LIST_CANCEL_DONE: item->setText(1,"Cancel Done"); break; default: break; } - char temp[24]; - sprintf(temp,"%08x",dl->startpc); - item->setText(2,temp); + item->setText(2,QString("%1").arg(dl->startpc,8,16,QChar('0'))); item->setData(2, Qt::UserRole, dl->startpc); - sprintf(temp,"%08x",dl->pc); - item->setText(3,temp); + item->setText(3,QString("%1").arg(dl->pc,8,16,QChar('0'))); item->setData(3, Qt::UserRole, dl->pc); ui->displayList->addTopLevelItem(item); if(curDlId == dl->id) { ui->displayList->setCurrentItem(item); displayListRowSelected = item; - ShowDLCode(); } } @@ -584,7 +576,7 @@ void Debugger_Disasm::UpdateDisplayListGUI() if(dl && it->id == dl->id) continue; QTreeWidgetItem* item = new QTreeWidgetItem(); - item->setText(0,QVariant(it->id).toString()); + item->setText(0,QString::number(it->id)); item->setData(0, Qt::UserRole, it->id); switch(it->status) { @@ -596,21 +588,19 @@ void Debugger_Disasm::UpdateDisplayListGUI() case PSP_GE_LIST_CANCEL_DONE: item->setText(1,"Cancel Done"); break; default: break; } - char temp[24]; - sprintf(temp,"%08x",it->startpc); - item->setText(2,temp); + item->setText(2,QString("%1").arg(it->startpc,8,16,QChar('0'))); item->setData(2, Qt::UserRole, it->startpc); - sprintf(temp,"%08x",it->pc); - item->setText(3,temp); + item->setText(3,QString("%1").arg(it->pc,8,16,QChar('0'))); item->setData(3, Qt::UserRole, it->pc); ui->displayList->addTopLevelItem(item); if(curDlId == it->id) { ui->displayList->setCurrentItem(item); displayListRowSelected = item; - ShowDLCode(); } } + for(int i = 0; i < ui->displayList->columnCount(); i++) + ui->displayList->resizeColumnToContents(i); EmuThread_LockDraw(false); } @@ -621,96 +611,12 @@ void Debugger_Disasm::on_displayList_customContextMenuRequested(const QPoint &po { displayListRowSelected = item; - QMenu menu(this); + /*QMenu menu(this); QAction *showCode = new QAction(tr("Show code"), this); connect(showCode, SIGNAL(triggered()), this, SLOT(ShowDLCode())); - menu.addAction(showCode); + menu.addAction(showCode);*/ - menu.exec( ui->displayList->mapToGlobal(pos)); + //menu.exec( ui->displayList->mapToGlobal(pos)); } } - -void Debugger_Disasm::ShowDLCode() -{ - ui->displayListData->clear(); - ui->displayListData->setColumnWidth(0,70); - - u32 startPc = displayListRowSelected->data(2,Qt::UserRole).toInt(); - u32 curPc = displayListRowSelected->data(3,Qt::UserRole).toInt(); - - std::map data; - FillDisplayListCmd(data, startPc,0); - - for(std::map::iterator it = data.begin(); it != data.end(); it++) - { - QTreeWidgetItem* item = new QTreeWidgetItem(); - char temp[24]; - sprintf(temp,"%08x",it->first); - item->setText(0,temp); - item->setText(1,it->second.c_str()); - if(curPc == it->first) - { - for(int j = 0; j < 2; j++) - item->setTextColor(j, Qt::green); - } - ui->displayListData->addTopLevelItem(item); - } -} - -void Debugger_Disasm::FillDisplayListCmd(std::map& data, u32 pc, u32 prev) -{ - u32 curPc = pc; - int debugLimit = 10000; // Anti crash if this code is bugged - while(Memory::IsValidAddress(curPc) && debugLimit > 0) - { - if(data.find(curPc) != data.end()) - return; - - u32 op = Memory::ReadUnchecked_U32(curPc); //read from memory - u32 cmd = op >> 24; - u32 diff = op ^ gstate.cmdmem[cmd]; - char temp[256]; - GeDisassembleOp(curPc, op, prev, temp); - data[curPc] = temp; - prev = op; - if(cmd == GE_CMD_JUMP) - { - u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF; - FillDisplayListCmd(data, target, prev); - return; - } - else if(cmd == GE_CMD_CALL) - { - u32 target = gstate_c.getRelativeAddress(op & 0xFFFFFF); - FillDisplayListCmd(data, target, prev); - } - else if(cmd == GE_CMD_RET) - { - return; - } - else if(cmd == GE_CMD_FINISH) - { - return; - } - else if(cmd == GE_CMD_END) - { - if(prev >> 24 == GE_CMD_FINISH) - return; - } - curPc += 4; - debugLimit--; - } -} - -void Debugger_Disasm::on_nextGPU_clicked() -{ - host->SetGPUStep(true); - host->NextGPUStep(); -} - -void Debugger_Disasm::on_runBtn_clicked() -{ - host->SetGPUStep(false); - host->NextGPUStep(); -} diff --git a/Qt/debugger_disasm.h b/Qt/debugger_disasm.h index fb47a1935f..5ca646e4be 100644 --- a/Qt/debugger_disasm.h +++ b/Qt/debugger_disasm.h @@ -41,7 +41,6 @@ public: void UpdateDisplayList(); protected: void showEvent(QShowEvent *); - void FillDisplayListCmd(std::map& data, u32 pc, u32 prev); signals: void updateDisplayList_(); @@ -52,7 +51,6 @@ public slots: void Goto(u32 addr); void RemoveBreakpoint(); void GotoThreadEntryPoint(); - void ShowDLCode(); private slots: void UpdateDisplayListGUI(); @@ -103,9 +101,6 @@ private slots: void SetThreadStatusSuspend(); void on_displayList_customContextMenuRequested(const QPoint &pos); - void on_nextGPU_clicked(); - - void on_runBtn_clicked(); private: void SetThreadStatus(ThreadStatus status); diff --git a/Qt/debugger_disasm.ui b/Qt/debugger_disasm.ui index bcf992486f..0cc8967bcf 100644 --- a/Qt/debugger_disasm.ui +++ b/Qt/debugger_disasm.ui @@ -313,7 +313,7 @@ - 2 + 0 @@ -424,70 +424,6 @@ - - - - - - false - - - false - - - false - - - 2 - - - false - - - - 1 - - - - - 2 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Run - - - - - - - Step - - - - - - - diff --git a/Qt/debugger_displaylist.cpp b/Qt/debugger_displaylist.cpp new file mode 100644 index 0000000000..0f557354ca --- /dev/null +++ b/Qt/debugger_displaylist.cpp @@ -0,0 +1,1520 @@ +#include "debugger_displaylist.h" + +#include +#include + +#include "Core/CPU.h" +#include "ui_debugger_displaylist.h" +#include "GPU/GPUInterface.h" +#include "GPU/GeDisasm.h" +#include "EmuThread.h" +#include "Core/Host.h" +#include "base/display.h" +#include "mainwindow.h" +#include "GPU/GLES/VertexDecoder.h" +#include + + +Debugger_DisplayList::Debugger_DisplayList(DebugInterface *_cpu, MainWindow* mainWindow_, QWidget *parent) : + QDialog(parent), + ui(new Ui::Debugger_DisplayList), + cpu(_cpu), + mainWindow(mainWindow_), + currentRenderFrameDisplay(0), + currentTextureDisplay(0), + fboZoomFactor(1), + maxVtxDisplay(20), + maxIdxDisplay(20) +{ + ui->setupUi(this); + + QObject::connect(this, SIGNAL(updateDisplayList_()), this, SLOT(UpdateDisplayListGUI())); + QObject::connect(this, SIGNAL(updateRenderBufferList_()), this, SLOT(UpdateRenderBufferListGUI())); + +} + +Debugger_DisplayList::~Debugger_DisplayList() +{ + delete ui; +} + + +void Debugger_DisplayList::showEvent(QShowEvent *) +{ + +#ifdef Q_WS_X11 + // Hack to remove the X11 crash with threaded opengl when opening the first dialog + EmuThread_LockDraw(true); + QTimer::singleShot(100, this, SLOT(releaseLock())); +#endif + +} + +void Debugger_DisplayList::releaseLock() +{ + EmuThread_LockDraw(false); +} + + +void Debugger_DisplayList::UpdateDisplayList() +{ + emit updateDisplayList_(); +} + + +void Debugger_DisplayList::UpdateDisplayListGUI() +{ + u32 curDlId = 0; + QTreeWidgetItem* curItem = ui->displayList->currentItem(); + if(curItem) + curDlId = ui->displayList->currentItem()->data(0,Qt::UserRole).toInt(); + + displayListRowSelected = 0; + ui->displayList->clear(); + ui->displayListData->clear(); + + EmuThread_LockDraw(true); + const std::deque& dlQueue = gpu->GetDisplayLists(); + + DisplayList* dl = gpu->GetCurrentDisplayList(); + if(dl) + { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0,QString::number(dl->id)); + item->setData(0, Qt::UserRole, dl->id); + switch(dl->status) + { + case PSP_GE_LIST_DONE: item->setText(1,"Done"); break; + case PSP_GE_LIST_QUEUED: item->setText(1,"Queued"); break; + case PSP_GE_LIST_DRAWING: item->setText(1,"Drawing"); break; + case PSP_GE_LIST_STALL_REACHED: item->setText(1,"Stall Reached"); break; + case PSP_GE_LIST_END_REACHED: item->setText(1,"End Reached"); break; + case PSP_GE_LIST_CANCEL_DONE: item->setText(1,"Cancel Done"); break; + default: break; + } + item->setText(2,QString("%1").arg(dl->startpc,8,16,QChar('0'))); + item->setData(2, Qt::UserRole, dl->startpc); + item->setText(3,QString("%1").arg(dl->pc,8,16,QChar('0'))); + item->setData(3, Qt::UserRole, dl->pc); + ui->displayList->addTopLevelItem(item); + if(curDlId == dl->id) + { + ui->displayList->setCurrentItem(item); + displayListRowSelected = item; + ShowDLCode(); + } + } + + for(auto it = dlQueue.begin(); it != dlQueue.end(); ++it) + { + if(dl && it->id == dl->id) + continue; + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0,QString::number(it->id)); + item->setData(0, Qt::UserRole, it->id); + switch(it->status) + { + case PSP_GE_LIST_DONE: item->setText(1,"Done"); break; + case PSP_GE_LIST_QUEUED: item->setText(1,"Queued"); break; + case PSP_GE_LIST_DRAWING: item->setText(1,"Drawing"); break; + case PSP_GE_LIST_STALL_REACHED: item->setText(1,"Stall Reached"); break; + case PSP_GE_LIST_END_REACHED: item->setText(1,"End Reached"); break; + case PSP_GE_LIST_CANCEL_DONE: item->setText(1,"Cancel Done"); break; + default: break; + } + item->setText(2,QString("%1").arg(it->startpc,8,16,QChar('0'))); + item->setData(2, Qt::UserRole, it->startpc); + item->setText(3,QString("%1").arg(it->pc,8,16,QChar('0'))); + item->setData(3, Qt::UserRole, it->pc); + ui->displayList->addTopLevelItem(item); + if(curDlId == it->id) + { + ui->displayList->setCurrentItem(item); + displayListRowSelected = item; + ShowDLCode(); + } + } + for(int i = 0; i < ui->displayList->columnCount(); i++) + ui->displayList->resizeColumnToContents(i); + EmuThread_LockDraw(false); +} + + +void Debugger_DisplayList::ShowDLCode() +{ + ui->displayListData->clear(); + ui->displayListData->setColumnCount(4); + + u32 startPc = displayListRowSelected->data(2,Qt::UserRole).toInt(); + u32 curPc = displayListRowSelected->data(3,Qt::UserRole).toInt(); + + std::map data; + GPUgstate listState; + memset(&listState,0,sizeof(GPUgstate)); + drawGPUState.clear(); + vtxBufferSize.clear(); + idxBufferSize.clear(); + + FillDisplayListCmd(data, startPc,0, listState); + + u32 curTexAddr; + u32 curVtxAddr; + u32 curIdxAddr; + + for(std::map::iterator it = data.begin(); it != data.end(); it++) + { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0,QString("%1").arg(it->first,8,16,QChar('0'))); + item->setData(0, Qt::UserRole, it->first); + item->setText(1,QString("%1").arg(it->second.cmd,2,16,QChar('0'))); + item->setText(2,QString("%1").arg(it->second.data,6,16,QChar('0'))); + item->setText(3,it->second.comment); + if(curPc == it->first) + { + curTexAddr = it->second.texAddr; + curVtxAddr = it->second.vtxAddr; + curIdxAddr = it->second.idxAddr; + setCurrentFBO(it->second.fboAddr); + for(int j = 0; j < ui->displayListData->columnCount(); j++) + item->setTextColor(j, Qt::green); + } + if(it->second.implementationNotFinished) + { + for(int j = 0; j < ui->displayListData->columnCount(); j++) + item->setBackgroundColor(j, Qt::red); + } + ui->displayListData->addTopLevelItem(item); + + if(curPc == it->first) + { + ui->displayListData->setCurrentItem(item); + } + } + for(int j = 0; j < ui->displayListData->columnCount(); j++) + ui->displayListData->resizeColumnToContents(j); + + ui->texturesList->clear(); + ui->vertexData->clear(); + ui->vertexList->clear(); + ui->indexData->clear(); + ui->indexList->clear(); + + std::set usedTexAddr; + std::set usedVtxAddr; + std::set usedIdxAddr; + for(int i = 0; i < drawGPUState.size(); i++) + { + // Textures + QTreeWidgetItem* item = new QTreeWidgetItem(); + u32 texaddr = (drawGPUState[i].texaddr[0] & 0xFFFFF0) | ((drawGPUState[i].texbufwidth[0]<<8) & 0x0F000000); + if(!(usedTexAddr.find(texaddr) != usedTexAddr.end() || !Memory::IsValidAddress(texaddr))) + { + u32 format = drawGPUState[i].texformat & 0xF; + int w = 1 << (drawGPUState[i].texsize[0] & 0xf); + int h = 1 << ((drawGPUState[i].texsize[0]>>8) & 0xf); + + item->setText(0,QString("%1").arg(texaddr,8,16,QChar('0'))); + item->setData(0, Qt::UserRole, i); + item->setText(1,QString::number(w)); + item->setText(2,QString::number(h)); + item->setText(3,QString::number(format,16)); + ui->texturesList->addTopLevelItem(item); + if(curTexAddr == texaddr) + { + ui->texturesList->setCurrentItem(item); + for(int j = 0; j < ui->texturesList->columnCount(); j++) + item->setTextColor(j,Qt::green); + } + usedTexAddr.insert(texaddr); + } + + // Vertex + QTreeWidgetItem* vertexItem = new QTreeWidgetItem(); + u32 baseExtended = ((drawGPUState[i].base & 0x0F0000) << 8) | (drawGPUState[i].vaddr & 0xFFFFFF); + u32 vaddr = ((drawGPUState[i].offsetAddr & 0xFFFFFF) + baseExtended) & 0x0FFFFFFF; + if(!((drawGPUState[i].vaddr) == 0 || !Memory::IsValidAddress(vaddr) || usedVtxAddr.find(vaddr) != usedVtxAddr.end())) + { + vertexItem->setText(0, QString("%1").arg(vaddr,8,16,QChar('0'))); + vertexItem->setData(0,Qt::UserRole, i); + if((drawGPUState[i].vertType & GE_VTYPE_THROUGH_MASK) == GE_VTYPE_TRANSFORM) + vertexItem->setText(1, "Transform"); + else + vertexItem->setText(1, "Raw"); + vertexItem->setText(2, QString::number((drawGPUState[i].vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT)); + vertexItem->setText(3, QString::number((drawGPUState[i].vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT)); + switch(drawGPUState[i].vertType & GE_VTYPE_WEIGHT_MASK) + { + case GE_VTYPE_WEIGHT_8BIT: vertexItem->setText(4, "8bit"); break; + case GE_VTYPE_WEIGHT_16BIT: vertexItem->setText(4, "16bit"); break; + case GE_VTYPE_WEIGHT_FLOAT: vertexItem->setText(4, "float"); break; + default: vertexItem->setText(4, "No"); break; + } + switch(drawGPUState[i].vertType & GE_VTYPE_POS_MASK) + { + case GE_VTYPE_POS_8BIT: vertexItem->setText(5, "8bit"); break; + case GE_VTYPE_POS_16BIT: vertexItem->setText(5, "16bit"); break; + case GE_VTYPE_POS_FLOAT: vertexItem->setText(5, "float"); break; + default: vertexItem->setText(5, "No"); break; + } + switch(drawGPUState[i].vertType & GE_VTYPE_NRM_MASK) + { + case GE_VTYPE_NRM_8BIT: vertexItem->setText(6, "8bit"); break; + case GE_VTYPE_NRM_16BIT: vertexItem->setText(6, "16bit"); break; + case GE_VTYPE_NRM_FLOAT: vertexItem->setText(6, "float"); break; + default: vertexItem->setText(6, "No"); break; + } + switch(drawGPUState[i].vertType & GE_VTYPE_COL_MASK) + { + case GE_VTYPE_COL_4444: vertexItem->setText(7, "4444"); break; + case GE_VTYPE_COL_5551: vertexItem->setText(7, "5551"); break; + case GE_VTYPE_COL_565: vertexItem->setText(7, "565"); break; + case GE_VTYPE_COL_8888: vertexItem->setText(7, "8888"); break; + default: vertexItem->setText(7, "No"); break; + } + switch(drawGPUState[i].vertType & GE_VTYPE_TC_MASK) + { + case GE_VTYPE_TC_8BIT: vertexItem->setText(8, "8bit"); break; + case GE_VTYPE_TC_16BIT: vertexItem->setText(8, "16bit"); break; + case GE_VTYPE_TC_FLOAT: vertexItem->setText(8, "float"); break; + default: vertexItem->setText(8, "No"); break; + } + + ui->vertexList->addTopLevelItem(vertexItem); + if(curVtxAddr == vaddr) + { + ui->vertexList->setCurrentItem(vertexItem); + for(int j = 0; j < ui->vertexList->columnCount(); j++) + vertexItem->setTextColor(j,Qt::green); + } + usedVtxAddr.insert(vaddr); + } + + + // Index + QTreeWidgetItem* indexItem = new QTreeWidgetItem(); + baseExtended = ((drawGPUState[i].base & 0x0F0000) << 8) | (drawGPUState[i].iaddr & 0xFFFFFF); + u32 iaddr = ((drawGPUState[i].offsetAddr & 0xFFFFFF) + baseExtended) & 0x0FFFFFFF; + if(!((drawGPUState[i].iaddr & 0xFFFFFF) == 0 || !Memory::IsValidAddress(iaddr) || usedIdxAddr.find(iaddr) != usedIdxAddr.end())) + { + indexItem->setText(0, QString("%1").arg(iaddr,8,16,QChar('0'))); + indexItem->setData(0,Qt::UserRole, i); + + ui->indexList->addTopLevelItem(indexItem); + if(curIdxAddr == iaddr) + { + ui->indexList->setCurrentItem(indexItem); + for(int j = 0; j < ui->indexList->columnCount(); j++) + indexItem->setTextColor(j,Qt::green); + } + usedIdxAddr.insert(iaddr); + } + + for(int i = 0; i < ui->texturesList->columnCount(); i++) + ui->texturesList->resizeColumnToContents(i); + for(int i = 0; i < ui->vertexList->columnCount(); i++) + ui->vertexList->resizeColumnToContents(i); + for(int i = 0; i < ui->indexList->columnCount(); i++) + ui->indexList->resizeColumnToContents(i); + } + + UpdateVertexInfo(); + UpdateIndexInfo(); +} + + +QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUgstate& state) { + u32 cmd = op >> 24; + u32 data = op & 0xFFFFFF; + + // Handle control and drawing commands here directly. The others we delegate. + switch (cmd) + { + case GE_CMD_BASE: + return QString("BASE: %1").arg(data & 0xFFFFFF,6,16,QChar('0')); + break; + + case GE_CMD_VADDR: /// <<8???? + { + u32 baseExtended = ((state.base & 0x0F0000) << 8) | (data & 0xFFFFFF); + baseExtended = (state.offsetAddr + baseExtended) & 0x0FFFFFFF; + return QString("VADDR: %1").arg(baseExtended,6,16,QChar('0')); + break; + } + + case GE_CMD_IADDR: + { + u32 baseExtended = ((state.base & 0x0F0000) << 8) | (data & 0xFFFFFF); + baseExtended = (state.offsetAddr + baseExtended) & 0x0FFFFFFF; + return QString("IADDR: %1").arg(baseExtended,6,16,QChar('0')); + break; + } + + case GE_CMD_PRIM: + { + u32 count = data & 0xFFFF; + u32 type = data >> 16; + static const char* types[7] = { + "POINTS", + "LINES", + "LINE_STRIP", + "TRIANGLES", + "TRIANGLE_STRIP", + "TRIANGLE_FAN", + "RECTANGLES", + }; + return QString("DrawPrim type: %1 count: %2").arg(type < 7 ? types[type] : "INVALID").arg(count); + } + break; + + // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. + case GE_CMD_BEZIER: + { + int bz_ucount = data & 0xFF; + int bz_vcount = (data >> 8) & 0xFF; + return QString("DRAW BEZIER: %1 x %2").arg(bz_ucount).arg(bz_vcount); + } + break; + + case GE_CMD_SPLINE: + { + int sp_ucount = data & 0xFF; + int sp_vcount = (data >> 8) & 0xFF; + int sp_utype = (data >> 16) & 0x3; + int sp_vtype = (data >> 18) & 0x3; + return QString("DRAW SPLINE: %1 x %2, %3 x %4").arg(sp_ucount).arg(sp_vcount).arg(sp_utype).arg(sp_vtype); + } + break; + + case GE_CMD_JUMP: + { + u32 target = (((state.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF; + return QString("CMD JUMP - %1 to %2").arg(pc,8,16,QChar('0')).arg(target,8,16,QChar('0')); + } + break; + + case GE_CMD_CALL: + { + u32 retval = pc + 4; + u32 baseExtended = ((state.base & 0x0F0000) << 8) | (op & 0xFFFFFF); + u32 target = (state.offsetAddr + baseExtended) & 0x0FFFFFFF; + return QString("CMD CALL - %1 to %2, ret=%3").arg(pc,8,16,QChar('0')).arg(target,8,16,QChar('0')).arg(retval,8,16,QChar('0')); + } + break; + + case GE_CMD_RET: + return QString("CMD RET"); + break; + + case GE_CMD_SIGNAL: + return QString("GE_CMD_SIGNAL %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_FINISH: + return QString("CMD FINISH %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_END: + switch (prev >> 24) + { + case GE_CMD_SIGNAL: + { + // TODO: see http://code.google.com/p/jpcsp/source/detail?r=2935# + int behaviour = (prev >> 16) & 0xFF; + int signal = prev & 0xFFFF; + int enddata = data & 0xFFFF; + // We should probably defer to sceGe here, no sense in implementing this stuff in every GPU + switch (behaviour) { + case 1: // Signal with Wait + return QString("Signal with Wait UNIMPLEMENTED! signal/end: %1 %2").arg(signal,4,16,QChar('0')).arg(enddata,4,16,QChar('0')); + break; + case 2: + return QString("Signal without wait. signal/end: %1 %2").arg(signal,4,16,QChar('0')).arg(enddata,4,16,QChar('0')); + break; + case 3: + return QString("Signal with Pause UNIMPLEMENTED! signal/end: %1 %2").arg(signal,4,16,QChar('0')).arg(enddata,4,16,QChar('0')); + break; + case 0x10: + return QString("Signal with Jump UNIMPLEMENTED! signal/end: %1 %2").arg(signal,4,16,QChar('0')).arg(enddata,4,16,QChar('0')); + break; + case 0x11: + return QString("Signal with Call UNIMPLEMENTED! signal/end: %1 %2").arg(signal,4,16,QChar('0')).arg(enddata,4,16,QChar('0')); + break; + case 0x12: + return QString("Signal with Return UNIMPLEMENTED! signal/end: %1 %2").arg(signal,4,16,QChar('0')).arg(enddata,4,16,QChar('0')); + break; + default: + return QString("UNKNOWN Signal UNIMPLEMENTED %1 ! signal/end: %1 %2").arg(behaviour).arg(signal,4,16,QChar('0')).arg(enddata,4,16,QChar('0')); + break; + } + } + break; + case GE_CMD_FINISH: + break; + default: + return QString("Ah, not finished: %1").arg(prev & 0xFFFFFF,6,16,QChar('0')); + break; + } + return "CMD END"; + break; + + case GE_CMD_BJUMP: + // bounding box jump. Let's just not jump, for now. + return QString("BBOX JUMP - unimplemented"); + break; + + case GE_CMD_BOUNDINGBOX: + // bounding box test. Let's do nothing. + return QString("BBOX TEST - unimplemented"); + break; + + case GE_CMD_ORIGIN: + return QString("Origin: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_VERTEXTYPE: + return QString("SetVertexType: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_OFFSETADDR: + return QString("OffsetAddr: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_REGION1: + { + int x1 = data & 0x3ff; + int y1 = data >> 10; + //topleft + return QString("Region TL: %1 %2").arg(x1).arg(y1); + } + break; + + case GE_CMD_REGION2: + { + int x2 = data & 0x3ff; + int y2 = data >> 10; + return QString("Region BR: %1 %2").arg(x2).arg(y2); + } + break; + + case GE_CMD_CLIPENABLE: + return QString("Clip Enable: %1").arg(data); + break; + + case GE_CMD_CULLFACEENABLE: + return QString("CullFace Enable: %1").arg(data); + break; + + case GE_CMD_TEXTUREMAPENABLE: + return QString("Texture map enable: %1").arg(data); + break; + + case GE_CMD_LIGHTINGENABLE: + return QString("Lighting enable: %1").arg(data); + break; + + case GE_CMD_FOGENABLE: + return QString("Fog Enable: %1").arg(data); + break; + + case GE_CMD_DITHERENABLE: + return QString("Dither Enable: %1").arg(data); + break; + + case GE_CMD_OFFSETX: + return QString("Offset X: %1").arg(data); + break; + + case GE_CMD_OFFSETY: + return QString("Offset Y: %1").arg(data); + break; + + case GE_CMD_TEXSCALEU: + return QString("Texture U Scale: %1").arg(getFloat24(data)); + break; + + case GE_CMD_TEXSCALEV: + return QString("Texture V Scale: %1").arg(getFloat24(data)); + break; + + case GE_CMD_TEXOFFSETU: + return QString("Texture U Offset: %1").arg(getFloat24(data)); + break; + + case GE_CMD_TEXOFFSETV: + return QString("Texture V Offset: %1").arg(getFloat24(data)); + break; + + case GE_CMD_SCISSOR1: + { + int x1 = data & 0x3ff; + int y1 = data >> 10; + return QString("Scissor TL: %1, %2").arg(x1).arg(y1); + } + break; + case GE_CMD_SCISSOR2: + { + int x2 = data & 0x3ff; + int y2 = data >> 10; + return QString("Scissor BR: %1, %2").arg(x2).arg(y2); + } + break; + + case GE_CMD_MINZ: + { + float zMin = getFloat24(data) / 65535.f; + return QString("MinZ: %1").arg(zMin); + } + break; + + case GE_CMD_MAXZ: + { + float zMax = getFloat24(data) / 65535.f; + return QString("MaxZ: %1").arg(zMax); + } + break; + + case GE_CMD_FRAMEBUFPTR: + { + u32 ptr = op & 0xFFE000; + return QString("FramebufPtr: %1").arg(data,8,16,QChar('0')); + } + break; + + case GE_CMD_FRAMEBUFWIDTH: + { + return QString("FramebufWidth: %1").arg(data); + } + break; + + case GE_CMD_FRAMEBUFPIXFORMAT: + return QString("FramebufPixeFormat: %1").arg(data); + break; + + case GE_CMD_TEXADDR0: + case GE_CMD_TEXADDR1: + case GE_CMD_TEXADDR2: + case GE_CMD_TEXADDR3: + case GE_CMD_TEXADDR4: + case GE_CMD_TEXADDR5: + case GE_CMD_TEXADDR6: + case GE_CMD_TEXADDR7: + return QString("Texture address %1: %2").arg(cmd-GE_CMD_TEXADDR0).arg(data,6,16,QChar('0')); + break; + + case GE_CMD_TEXBUFWIDTH0: + case GE_CMD_TEXBUFWIDTH1: + case GE_CMD_TEXBUFWIDTH2: + case GE_CMD_TEXBUFWIDTH3: + case GE_CMD_TEXBUFWIDTH4: + case GE_CMD_TEXBUFWIDTH5: + case GE_CMD_TEXBUFWIDTH6: + case GE_CMD_TEXBUFWIDTH7: + return QString("Texture BUFWIDTHess %1: %2").arg(cmd-GE_CMD_TEXBUFWIDTH0).arg(data,6,16,QChar('0')); + break; + + case GE_CMD_CLUTADDR: + return QString("CLUT base addr: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_CLUTADDRUPPER: + return QString("CLUT addr upper %1").arg(data,8,16,QChar('0')); + break; + + case GE_CMD_LOADCLUT: + // This could be used to "dirty" textures with clut. + return QString("Clut load"); + break; + + case GE_CMD_TEXMAPMODE: + return QString("Tex map mode: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_TEXSHADELS: + return QString("Tex shade light sources: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_CLUTFORMAT: + { + return QString("Clut format: %1").arg(data,6,16,QChar('0')); + } + break; + + case GE_CMD_TRANSFERSRC: + { + return QString("Block Transfer Src: %1").arg(data,6,16,QChar('0')); + // Nothing to do, the next one prints + } + break; + + case GE_CMD_TRANSFERSRCW: + { + u32 xferSrc = state.transfersrc | ((data&0xFF0000)<<8); + u32 xferSrcW = state.transfersrcw & 1023; + return QString("Block Transfer Src: %1 W: %2").arg(xferSrc,8,16,QChar('0')).arg(xferSrcW); + break; + } + + case GE_CMD_TRANSFERDST: + { + // Nothing to do, the next one prints + return QString("Block Transfer Dst: %1").arg(data,6,16,QChar('0')); + } + break; + + case GE_CMD_TRANSFERDSTW: + { + u32 xferDst= state.transferdst | ((data&0xFF0000)<<8); + u32 xferDstW = state.transferdstw & 1023; + return QString("Block Transfer Dest: %1 W: %2").arg(xferDst,8,16,QChar('0')).arg(xferDstW); + break; + } + + case GE_CMD_TRANSFERSRCPOS: + { + u32 x = (data & 1023)+1; + u32 y = ((data>>10) & 1023)+1; + return QString("Block Transfer Src Rect TL: %1, %2").arg(x).arg(y); + break; + } + + case GE_CMD_TRANSFERDSTPOS: + { + u32 x = (data & 1023)+1; + u32 y = ((data>>10) & 1023)+1; + return QString("Block Transfer Dest Rect TL: %1, %2").arg(x).arg(y); + break; + } + + case GE_CMD_TRANSFERSIZE: + { + u32 w = (data & 1023)+1; + u32 h = ((data>>10) & 1023)+1; + return QString("Block Transfer Rect Size: %1 x %2").arg(w).arg(h); + break; + } + + case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK + { + return QString("Block Transfer Start"); + break; + } + + case GE_CMD_TEXSIZE0: + case GE_CMD_TEXSIZE1: + case GE_CMD_TEXSIZE2: + case GE_CMD_TEXSIZE3: + case GE_CMD_TEXSIZE4: + case GE_CMD_TEXSIZE5: + case GE_CMD_TEXSIZE6: + case GE_CMD_TEXSIZE7: + { + int w = 1 << (data & 0xf); + int h = 1 << ((data>>8) & 0xf); + return QString("Texture Size %1: %2, width : %3, height : %4").arg(cmd - GE_CMD_TEXSIZE0).arg(data,6,16,QChar('0')).arg(w).arg(h); + } + break; + + case GE_CMD_ZBUFPTR: + { + u32 ptr = op & 0xFFE000; + return QString("Zbuf Ptr: %1").arg(ptr,6,16,QChar('0')); + } + break; + + case GE_CMD_ZBUFWIDTH: + { + return QString("Zbuf Width: %1").arg(data,6,16,QChar('0')); + } + break; + + case GE_CMD_AMBIENTCOLOR: + return QString("Ambient Color: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_AMBIENTALPHA: + return QString("Ambient Alpha: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_MATERIALAMBIENT: + return QString("Material Ambient Color: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_MATERIALDIFFUSE: + return QString("Material Diffuse Color: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_MATERIALEMISSIVE: + return QString("Material Emissive Color: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_MATERIALSPECULAR: + return QString("Material Specular Color: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_MATERIALALPHA: + return QString("Material Alpha Color: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_MATERIALSPECULARCOEF: + return QString("Material specular coef: %1").arg(getFloat24(data)); + break; + + case GE_CMD_SHADEMODE: + return QString("Shade: %1 (%2)").arg(data,6,16,QChar('0')).arg(data ? "gouraud" : "flat"); + break; + + case GE_CMD_LIGHTMODE: + return QString("Lightmode: %1 (%2)").arg(data,6,16,QChar('0')).arg(data ? "separate spec" : "single color"); + break; + + case GE_CMD_LIGHTTYPE0: + case GE_CMD_LIGHTTYPE1: + case GE_CMD_LIGHTTYPE2: + case GE_CMD_LIGHTTYPE3: + return QString("Light %1 type: %2").arg(cmd-GE_CMD_LIGHTTYPE0).arg(data,6,16,QChar('0')); + break; + + case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0: + case GE_CMD_LX1:case GE_CMD_LY1:case GE_CMD_LZ1: + case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2: + case GE_CMD_LX3:case GE_CMD_LY3:case GE_CMD_LZ3: + { + int n = cmd - GE_CMD_LX0; + int l = n / 3; + int c = n % 3; + float val = getFloat24(data); + return QString("Light %1 %2 pos: %3").arg(l).arg(QChar('X')+c).arg(val); + } + break; + + case GE_CMD_LDX0:case GE_CMD_LDY0:case GE_CMD_LDZ0: + case GE_CMD_LDX1:case GE_CMD_LDY1:case GE_CMD_LDZ1: + case GE_CMD_LDX2:case GE_CMD_LDY2:case GE_CMD_LDZ2: + case GE_CMD_LDX3:case GE_CMD_LDY3:case GE_CMD_LDZ3: + { + int n = cmd - GE_CMD_LDX0; + int l = n / 3; + int c = n % 3; + float val = getFloat24(data); + return QString("Light %1 %2 dir: %3").arg(l).arg(QChar('X')+c).arg(val); + } + break; + + case GE_CMD_LKA0:case GE_CMD_LKB0:case GE_CMD_LKC0: + case GE_CMD_LKA1:case GE_CMD_LKB1:case GE_CMD_LKC1: + case GE_CMD_LKA2:case GE_CMD_LKB2:case GE_CMD_LKC2: + case GE_CMD_LKA3:case GE_CMD_LKB3:case GE_CMD_LKC3: + { + int n = cmd - GE_CMD_LKA0; + int l = n / 3; + int c = n % 3; + float val = getFloat24(data); + return QString("Light %1 %2 att: %3").arg(l).arg(QChar('X')+c).arg(val); + } + break; + + case GE_CMD_LAC0:case GE_CMD_LAC1:case GE_CMD_LAC2:case GE_CMD_LAC3: + case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3: + case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3: + { + float r = (float)(data & 0xff)/255.0f; + float g = (float)((data>>8) & 0xff)/255.0f; + float b = (float)(data>>16)/255.0f; + + int l = (cmd - GE_CMD_LAC0) / 3; + int t = (cmd - GE_CMD_LAC0) % 3; + return QString("Light %1 color %2: %3 %4 %5").arg(l).arg(t).arg(r).arg(g).arg(b); + } + break; + + case GE_CMD_VIEWPORTX1: + case GE_CMD_VIEWPORTY1: + case GE_CMD_VIEWPORTX2: + case GE_CMD_VIEWPORTY2: + return QString("Viewport param %1: %2").arg(cmd-GE_CMD_VIEWPORTX1).arg(getFloat24(data)); + break; + case GE_CMD_VIEWPORTZ1: + { + float zScale = getFloat24(data) / 65535.f; + return QString("Viewport Z scale: %1").arg(zScale); + } + break; + case GE_CMD_VIEWPORTZ2: + { + float zOff = getFloat24(data) / 65535.f; + return QString("Viewport Z pos: %1").arg(zOff); + } + break; + + case GE_CMD_LIGHTENABLE0: + case GE_CMD_LIGHTENABLE1: + case GE_CMD_LIGHTENABLE2: + case GE_CMD_LIGHTENABLE3: + return QString("Light %1 enable: %2").arg(cmd-GE_CMD_LIGHTENABLE0).arg(data); + break; + + case GE_CMD_CULL: + return QString("cull: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_PATCHDIVISION: + { + int patch_div_s = data & 0xFF; + int patch_div_t = (data >> 8) & 0xFF; + return QString("Patch subdivision: %1 x %2").arg(patch_div_s).arg(patch_div_t); + } + break; + + case GE_CMD_PATCHPRIMITIVE: + return QString("Patch Primitive: %1").arg(data); + break; + + case GE_CMD_PATCHFACING: + return QString( "Patch Facing: %1").arg(data); + break; + + case GE_CMD_REVERSENORMAL: + return QString("Reverse normal: %1").arg(data); + break; + + case GE_CMD_MATERIALUPDATE: + return QString("Material Update: %1").arg(data); + break; + + + ////////////////////////////////////////////////////////////////// + // CLEARING + ////////////////////////////////////////////////////////////////// + case GE_CMD_CLEARMODE: + // If it becomes a performance problem, check diff&1 + return QString("Clear mode: %1").arg(data,6,16,QChar('0')); + break; + + + ////////////////////////////////////////////////////////////////// + // ALPHA BLENDING + ////////////////////////////////////////////////////////////////// + case GE_CMD_ALPHABLENDENABLE: + return QString("Alpha blend enable: %1").arg(data); + break; + + case GE_CMD_BLENDMODE: + return QString("Blend mode: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_BLENDFIXEDA: + return QString("Blend fix A: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_BLENDFIXEDB: + return QString("Blend fix B: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_ALPHATESTENABLE: + return QString("Alpha test enable: %1").arg(data); + break; + + case GE_CMD_ALPHATEST: + return QString("Alpha test settings"); + break; + + case GE_CMD_ANTIALIASENABLE: + return QString("Antialias enable: %1").arg(data); + break; + + case GE_CMD_PATCHCULLENABLE: + return QString("Antialias enable: %1").arg(data); + break; + + case GE_CMD_COLORTESTENABLE: + return QString("Color Test enable: %1").arg(data); + break; + + case GE_CMD_LOGICOPENABLE: + return QString("Logic op enable: %1").arg(data); + break; + + case GE_CMD_TEXFUNC: + return QString("TexFunc %1").arg(data&7); + break; + + case GE_CMD_TEXFILTER: + { + int min = data & 7; + int mag = (data >> 8) & 1; + return QString("TexFilter min: %1 mag: %2").arg( min).arg(mag); + } + break; + + case GE_CMD_TEXENVCOLOR: + return QString("TexEnvColor %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_TEXMODE: + return QString("TexMode %1").arg(data,8,16,QChar('0')); + break; + + case GE_CMD_TEXFORMAT: + return QString("TexFormat %1").arg(data,8,16,QChar('0')); + break; + + case GE_CMD_TEXFLUSH: + return QString("TexFlush"); + break; + + case GE_CMD_TEXSYNC: + return QString("TexSync"); + break; + + case GE_CMD_TEXWRAP: + return QString("TexWrap %1").arg(data,8,16,QChar('0')); + break; + + case GE_CMD_TEXLEVEL: + return QString("TexWrap Mode: %1 Offset: %2").arg(data&3).arg(data >> 16); + break; + + case GE_CMD_FOG1: + return QString("Fog1 %1").arg(getFloat24(data)); + break; + + case GE_CMD_FOG2: + return QString( "Fog2 %1").arg(getFloat24(data)); + break; + + case GE_CMD_FOGCOLOR: + return QString("FogColor %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_TEXLODSLOPE: + return QString( "TexLodSlope %1").arg(data,6,16,QChar('0')); + break; + + ////////////////////////////////////////////////////////////////// + // Z/STENCIL TESTING + ////////////////////////////////////////////////////////////////// + + case GE_CMD_ZTESTENABLE: + return QString( "Z test enable: %1").arg(data&1); + break; + + case GE_CMD_STENCILOP: + return QString("Stencil op: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_STENCILTEST: + return QString("Stencil test: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_STENCILTESTENABLE: + return QString("Stencil test enable: %1").arg(data); + break; + + case GE_CMD_ZTEST: + return QString("Z test mode: %1").arg(data); + break; + + case GE_CMD_MORPHWEIGHT0: + case GE_CMD_MORPHWEIGHT1: + case GE_CMD_MORPHWEIGHT2: + case GE_CMD_MORPHWEIGHT3: + case GE_CMD_MORPHWEIGHT4: + case GE_CMD_MORPHWEIGHT5: + case GE_CMD_MORPHWEIGHT6: + case GE_CMD_MORPHWEIGHT7: + { + int index = cmd - GE_CMD_MORPHWEIGHT0; + float weight = getFloat24(data); + return QString("MorphWeight %1 = %2").arg(index).arg(weight); + } + break; + + case GE_CMD_DITH0: + case GE_CMD_DITH1: + case GE_CMD_DITH2: + case GE_CMD_DITH3: + return QString("DitherMatrix %1 = %2").arg(cmd-GE_CMD_DITH0).arg(data,6,16,QChar('0')); + break; + + case GE_CMD_LOGICOP: + return QString("LogicOp: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_ZWRITEDISABLE: + return QString("ZMask: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_COLORTEST: + return QString("ColorTest: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_COLORREF: + return QString("ColorRef: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_COLORTESTMASK: + return QString( "ColorTestMask: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_MASKRGB: + return QString("MaskRGB: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_MASKALPHA: + return QString("MaskAlpha: %1").arg(data,6,16,QChar('0')); + break; + + case GE_CMD_WORLDMATRIXNUMBER: + return QString("World # %1").arg(data & 0xF); + break; + + case GE_CMD_WORLDMATRIXDATA: + return QString("World data # %1").arg(getFloat24(data)); + break; + + case GE_CMD_VIEWMATRIXNUMBER: + return QString("VIEW # %1").arg(data & 0xF); + break; + + case GE_CMD_VIEWMATRIXDATA: + return QString("VIEW data # %1").arg(getFloat24(data)); + break; + + case GE_CMD_PROJMATRIXNUMBER: + return QString("PROJECTION # %1").arg(data & 0xF); + break; + + case GE_CMD_PROJMATRIXDATA: + return QString("PROJECTION matrix data # %1").arg(getFloat24(data)); + break; + + case GE_CMD_TGENMATRIXNUMBER: + return QString("TGEN # %1").arg(data & 0xF); + break; + + case GE_CMD_TGENMATRIXDATA: + return QString("TGEN data # %1").arg(getFloat24(data)); + break; + + case GE_CMD_BONEMATRIXNUMBER: + return QString("BONE #%1").arg(data); + break; + + case GE_CMD_BONEMATRIXDATA: + return QString("BONE data #%1 %2").arg(state.boneMatrixNumber & 0x7f).arg(getFloat24(data)); + break; + + default: + return QString("Unknown: %1").arg(op,8,16,QChar('0')); + break; + } +} + + +void Debugger_DisplayList::FillDisplayListCmd(std::map& data, u32 pc, u32 prevAddr, GPUgstate& state) +{ + u32 curPc = pc; + int debugLimit = 10000; // Anti crash if this code is bugged + while(Memory::IsValidAddress(curPc) && debugLimit > 0) + { + if(data.find(curPc) != data.end()) + return; + + u32 op = Memory::ReadUnchecked_U32(curPc); //read from memory + u32 cmd = op >> 24; + u32 data_ = op & 0xFFFFFF; + u32 diff = op ^ gstate.cmdmem[cmd]; + state.cmdmem[cmd] = op; + u32 prevOp = 0; + if(Memory::IsValidAddress(prevAddr)) + Memory::ReadUnchecked_U32(prevAddr); + data[curPc].comment = DisassembleOp(curPc, op, prevOp, state); + data[curPc].addr = curPc; + data[curPc].cmd = cmd; + data[curPc].data = data_; + data[curPc].implementationNotFinished = false; + data[curPc].texAddr = (gstate.texaddr[0] & 0xFFFFF0) | ((gstate.texbufwidth[0]<<8) & 0x0F000000); + data[curPc].fboAddr = state.fbptr & 0xFFFFFF; + u32 baseExtended = ((state.base & 0x0F0000) << 8) | (state.vaddr & 0xFFFFFF); + data[curPc].vtxAddr = ((state.offsetAddr & 0xFFFFFF) + baseExtended) & 0x0FFFFFFF; + baseExtended = ((state.base & 0x0F0000) << 8) | (state.iaddr & 0xFFFFFF); + data[curPc].idxAddr = ((state.offsetAddr & 0xFFFFFF) + baseExtended) & 0x0FFFFFFF; + // Add or remove bugged functions for highlight + if(cmd == GE_CMD_BEZIER || + cmd == GE_CMD_SPLINE || + cmd == GE_CMD_BJUMP || + cmd == GE_CMD_BOUNDINGBOX) + { + data[curPc].implementationNotFinished = true; + } + + // We are drawing, save the GPU state for texture, vertex and index list + if(cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE) + { + drawGPUState.push_back(state); + } + + if(cmd == GE_CMD_JUMP) + { + u32 baseExtended = ((state.base & 0x0F0000) << 8) | (data_ & 0xFFFFFF); + u32 target = (((state.offsetAddr & 0xFFFFFF) << 8) + baseExtended) & 0x0FFFFFFF; + FillDisplayListCmd(data, target, prevAddr, state); + return; + } + else if(cmd == GE_CMD_CALL) + { + u32 baseExtended = ((state.base & 0x0F0000) << 8) | (data_ & 0xFFFFFF); + u32 target = (((state.offsetAddr & 0xFFFFFF) << 8) + baseExtended) & 0x0FFFFFFF; + FillDisplayListCmd(data, target, prevAddr, state); + } + else if(cmd == GE_CMD_RET) + { + return; + } + else if(cmd == GE_CMD_FINISH) + { + return; + } + else if(cmd == GE_CMD_END) + { + if(prevOp >> 24 == GE_CMD_FINISH) + return; + } + prevAddr = curPc; + curPc += 4; + debugLimit--; + } +} + +void Debugger_DisplayList::Update() +{ + UpdateRenderBuffer(); + UpdateRenderBufferList(); + UpdateDisplayList(); +} + + +void Debugger_DisplayList::on_displayList_itemClicked(QTreeWidgetItem *item, int column) +{ + displayListRowSelected = item; + ShowDLCode(); +} + +void Debugger_DisplayList::on_stepBtn_clicked() +{ + host->SetGPUStep(true); + host->NextGPUStep(); +} + +void Debugger_DisplayList::on_runBtn_clicked() +{ + ui->displayList->clear(); + ui->displayListData->clear(); + host->SetGPUStep(false); + host->NextGPUStep(); +} + +void Debugger_DisplayList::on_stopBtn_clicked() +{ + host->SetGPUStep(true); +} + +void Debugger_DisplayList::UpdateRenderBuffer() +{ + EmuThread_LockDraw(true); + + gpu->Flush(); + + int FRAME_WIDTH; + int FRAME_HEIGHT; + u8 *data = 0; + int curTex; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &curTex); + if(currentTextureDisplay == 0) + { + FRAME_WIDTH = pixel_xres; + FRAME_HEIGHT = pixel_yres; + data = new u8[FRAME_WIDTH * FRAME_HEIGHT * 4]; + memset(data,0,FRAME_WIDTH * FRAME_HEIGHT * 4); + if(currentRenderFrameDisplay == 0) + { + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(0, 0, FRAME_WIDTH, FRAME_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, data); + } + else + { + glReadBuffer(GL_DEPTH_ATTACHMENT); + glReadPixels(0, 0, FRAME_WIDTH, FRAME_HEIGHT, GL_DEPTH_COMPONENT, GL_FLOAT, data); + } + } + else + { + fbo_get_dimensions(currentTextureDisplay, &FRAME_WIDTH, &FRAME_HEIGHT); + data = new u8[FRAME_WIDTH * FRAME_HEIGHT * 4]; + memset(data,0,FRAME_WIDTH * FRAME_HEIGHT * 4); + if(currentRenderFrameDisplay == 0) + { + fbo_bind_color_as_texture(currentTextureDisplay,0); + glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, data); + } + } + glBindTexture(GL_TEXTURE_2D, curTex); + + QImage img = QImage(data, FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH*4, QImage::Format_ARGB32).mirrored(false,true); + QPixmap pixmap = QPixmap::fromImage(img); + ui->fboImg->setPixmap(pixmap); + ui->fboImg->setMinimumWidth(pixmap.width() * fboZoomFactor); + ui->fboImg->setMinimumHeight(pixmap.height() * fboZoomFactor); + ui->fboImg->setMaximumWidth(pixmap.width() * fboZoomFactor); + ui->fboImg->setMaximumHeight(pixmap.height() * fboZoomFactor); + + delete[] data; + + EmuThread_LockDraw(false); +} + +void Debugger_DisplayList::on_nextDrawBtn_clicked() +{ + host->SetGPUStep(true, 1); + host->NextGPUStep(); +} + +void Debugger_DisplayList::on_gotoPCBtn_clicked() +{ + if(!displayListRowSelected) + return; + u32 currentPC = displayListRowSelected->data(3, Qt::UserRole).toInt(); + + for(int i = 0; i < ui->displayListData->topLevelItemCount(); i++) + { + if(ui->displayListData->topLevelItem(i)->data(0, Qt::UserRole).toInt() == currentPC) + { + ui->displayListData->setCurrentItem(ui->displayListData->topLevelItem(i)); + } + } +} + +void Debugger_DisplayList::on_texturesList_itemDoubleClicked(QTreeWidgetItem *item, int column) +{ + mainWindow->GetDialogMemoryTex()->ShowTex(drawGPUState[item->data(0,Qt::UserRole).toInt()]); +} + +void Debugger_DisplayList::on_comboBox_currentIndexChanged(int index) +{ + currentRenderFrameDisplay = index; + UpdateRenderBuffer(); +} + +void Debugger_DisplayList::UpdateRenderBufferList() +{ + emit updateRenderBufferList_(); +} + +void Debugger_DisplayList::UpdateRenderBufferListGUI() +{ + ui->fboList->clear(); + + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0,"Framebuffer"); + item->setData(0,Qt::UserRole, 0); + item->setText(1,QString::number(pixel_xres)); + item->setText(2,QString::number(pixel_yres)); + item->setText(3,QString::number(4)); + ui->fboList->addTopLevelItem(item); + + std::vector fboList = gpu->GetFramebufferList(); + + for(int i = 0; i < fboList.size(); i++) + { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0,QString("%1").arg(fboList[i].fb_address,8,16,QChar('0'))); + u64 addr = (u64)fboList[i].fbo; + item->setData(0,Qt::UserRole, addr); + item->setData(0,Qt::UserRole+1, fboList[i].fb_address); + item->setText(1,QString::number(fboList[i].width)); + item->setText(2,QString::number(fboList[i].height)); + item->setText(3,QString::number(fboList[i].format)); + + ui->fboList->addTopLevelItem(item); + } +} + +void Debugger_DisplayList::on_fboList_itemClicked(QTreeWidgetItem *item, int column) +{ + u64 addr = item->data(0,Qt::UserRole).toULongLong(); + FBO* fbo = (FBO*)addr; + currentTextureDisplay = fbo; + UpdateRenderBuffer(); +} + +void Debugger_DisplayList::on_nextDLBtn_clicked() +{ + host->SetGPUStep(true,-1); + host->NextGPUStep(); +} + +void Debugger_DisplayList::setCurrentFBO(u32 addr) +{ + for(int i = 0; i < ui->fboList->topLevelItemCount(); i++) + { + if(ui->fboList->topLevelItem(i)->data(0,Qt::UserRole+1).toInt() == addr) + { + for(int j = 0; j < ui->fboList->colorCount(); j++) + ui->fboList->topLevelItem(i)->setTextColor(j,Qt::green); + } + else + { + for(int j = 0; j < ui->fboList->colorCount(); j++) + ui->fboList->topLevelItem(i)->setTextColor(j,Qt::black); + } + } +} + +void Debugger_DisplayList::on_zoommBtn_clicked() +{ + fboZoomFactor *= 0.5; + ui->fboImg->setMinimumWidth(ui->fboImg->minimumWidth()*0.5); + ui->fboImg->setMinimumHeight(ui->fboImg->minimumHeight()*0.5); + ui->fboImg->setMaximumWidth(ui->fboImg->minimumWidth()*0.5); + ui->fboImg->setMaximumHeight(ui->fboImg->minimumHeight()*0.5); +} + +void Debugger_DisplayList::on_zoompBtn_clicked() +{ + fboZoomFactor *= 2; + ui->fboImg->setMinimumWidth(ui->fboImg->minimumWidth()*2); + ui->fboImg->setMinimumHeight(ui->fboImg->minimumHeight()*2); + ui->fboImg->setMaximumWidth(ui->fboImg->minimumWidth()*2); + ui->fboImg->setMaximumHeight(ui->fboImg->minimumHeight()*2); +} + +void Debugger_DisplayList::UpdateVertexInfo() +{ + ui->vertexData->clear(); + + QTreeWidgetItem* item = ui->vertexList->currentItem(); + if(item == 0) + return; + + GPUgstate state = drawGPUState[item->data(0,Qt::UserRole).toInt()]; + u32 baseExtended = ((state.base & 0x0F0000) << 8) | (state.vaddr & 0xFFFFFF); + u32 vaddr = ((state.offsetAddr & 0xFFFFFF) + baseExtended) & 0x0FFFFFFF; + + VertexDecoder vtcDec; + vtcDec.SetVertexType(state.vertType); + u8 tmp[20*vtcDec.GetDecVtxFmt().stride]; + vtcDec.DecodeVerts(tmp,Memory::GetPointer(vaddr),0,0,0,0,19); + VertexReader vtxRead(tmp,vtcDec.GetDecVtxFmt(),state.vertType); + + for(int i = 0; i < maxVtxDisplay; i++) + { + vtxRead.Goto(i); + QTreeWidgetItem* itemTop = new QTreeWidgetItem(); + itemTop->setText(0,QString::number(i)); + itemTop->setText(1,QString("%1").arg(vaddr+i*vtcDec.GetDecVtxFmt().stride,8,16,QChar('0'))); + ui->vertexData->addTopLevelItem(itemTop); + + if (vtxRead.hasNormal()) + { + float nrm[3]; + vtxRead.ReadNrm(nrm); + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(1,"Normal"); + item->setText(2,QString("X: %1, Y: %2, Z: %3").arg(nrm[0]).arg(nrm[1]).arg(nrm[2])); + itemTop->addChild(item); + } + if (vtxRead.hasUV()) { + float uv[2]; + vtxRead.ReadUV(uv); + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(1,"Uv"); + item->setText(2,QString("X: %1, Y: %2").arg(uv[0]).arg(uv[1])); + itemTop->addChild(item); + } + if (vtxRead.hasColor0()) { + float col0[4]; + vtxRead.ReadColor0(col0); + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(1,"Color0"); + item->setText(2,QString("X: %1, Y: %2, Z: %3").arg(col0[0]).arg(col0[1]).arg(col0[2])); + itemTop->addChild(item); + } + if (vtxRead.hasColor0()) { + float col1[3]; + vtxRead.ReadColor1(col1); + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(1,"Color1"); + item->setText(2,QString("X: %1, Y: %2, Z: %3").arg(col1[0]).arg(col1[1]).arg(col1[2])); + itemTop->addChild(item); + } + float pos[3]; + vtxRead.ReadPos(pos); + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(1,"Position"); + item->setText(2,QString("X: %1, Y: %2, Z: %3").arg(pos[0]).arg(pos[1]).arg(pos[2])); + itemTop->addChild(item); + } + for(int i = 0; i < ui->vertexData->columnCount(); i++) + { + ui->vertexData->resizeColumnToContents(i); + } +} + +void Debugger_DisplayList::on_vertexList_itemClicked(QTreeWidgetItem *item, int column) +{ + UpdateVertexInfo(); +} + +void Debugger_DisplayList::on_pushButton_clicked() +{ + maxVtxDisplay += 20; + UpdateVertexInfo(); +} + + +void Debugger_DisplayList::UpdateIndexInfo() +{ + ui->indexData->clear(); + + QTreeWidgetItem* item = ui->indexList->currentItem(); + if(item == 0) + return; + + GPUgstate state = drawGPUState[item->data(0,Qt::UserRole).toInt()]; + u32 baseExtended = ((state.base & 0x0F0000) << 8) | (state.iaddr & 0xFFFFFF); + u32 iaddr = ((state.offsetAddr & 0xFFFFFF) + baseExtended) & 0x0FFFFFFF; + + int sizeIdx = 1; + if((state.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT) + sizeIdx = 2; + + for(int i = 0; i < maxIdxDisplay; i++) + { + QTreeWidgetItem* itemTop = new QTreeWidgetItem(); + itemTop->setText(0,QString::number(i)); + itemTop->setText(1,QString("%1").arg(iaddr+i*sizeIdx,8,16,QChar('0'))); + int idx = 0; + if(sizeIdx == 1) + idx = Memory::Read_U8(iaddr+i*sizeIdx); + else + idx = Memory::Read_U16(iaddr+i*sizeIdx); + itemTop->setText(2,QString::number(idx)); + ui->indexData->addTopLevelItem(itemTop); + } + for(int i = 0; i < ui->indexData->columnCount(); i++) + { + ui->indexData->resizeColumnToContents(i); + } +} + + +void Debugger_DisplayList::on_nextIdx_clicked() +{ + maxIdxDisplay += 20; + UpdateIndexInfo(); +} + +void Debugger_DisplayList::on_indexList_itemClicked(QTreeWidgetItem *item, int column) +{ + UpdateIndexInfo(); +} diff --git a/Qt/debugger_displaylist.h b/Qt/debugger_displaylist.h new file mode 100644 index 0000000000..e237a84f31 --- /dev/null +++ b/Qt/debugger_displaylist.h @@ -0,0 +1,114 @@ +#ifndef DEBUGGER_DISPLAYLIST_H +#define DEBUGGER_DISPLAYLIST_H + +#include "Core/Debugger/DebugInterface.h" +#include +#include +#include "GPU/GPUState.h" +#include "native/gfx_es2/fbo.h" + +class MainWindow; +namespace Ui { +class Debugger_DisplayList; +} + + +class DListLine +{ +public: + u32 addr; + u32 cmd; + u32 data; + QString comment; + bool implementationNotFinished; + u32 texAddr; + u32 fboAddr; + u32 vtxAddr; + int vtxStart; + int vtxCount; + u32 idxAddr; + int idxStart; + int idxCount; +}; + +class Debugger_DisplayList : public QDialog +{ + Q_OBJECT + +public: + explicit Debugger_DisplayList(DebugInterface *_cpu, MainWindow *mainWindow_, QWidget *parent = 0); + ~Debugger_DisplayList(); + + void UpdateDisplayList(); + + void ShowDLCode(); + void FillDisplayListCmd(std::map &data, u32 pc, u32 prev, GPUgstate &state); + void Update(); + void UpdateRenderBuffer(); + void UpdateRenderBufferList(); + void UpdateVertexInfo(); + void UpdateIndexInfo(); +protected: + void showEvent(QShowEvent *); + +signals: + void updateDisplayList_(); + void updateRenderBufferList_(); + +private slots: + void UpdateDisplayListGUI(); + void UpdateRenderBufferListGUI(); + void releaseLock(); + + void on_displayList_itemClicked(QTreeWidgetItem *item, int column); + + void on_stepBtn_clicked(); + + void on_runBtn_clicked(); + + void on_stopBtn_clicked(); + + void on_nextDrawBtn_clicked(); + + void on_gotoPCBtn_clicked(); + + void on_texturesList_itemDoubleClicked(QTreeWidgetItem *item, int column); + + void on_comboBox_currentIndexChanged(int index); + + void on_fboList_itemClicked(QTreeWidgetItem *item, int column); + + void on_nextDLBtn_clicked(); + void setCurrentFBO(u32 addr); + + void on_zoommBtn_clicked(); + + void on_zoompBtn_clicked(); + + void on_vertexList_itemClicked(QTreeWidgetItem *item, int column); + + void on_pushButton_clicked(); + + void on_nextIdx_clicked(); + + void on_indexList_itemClicked(QTreeWidgetItem *item, int column); + +private: + QString DisassembleOp(u32 pc, u32 op, u32 prev, const GPUgstate &state); + + Ui::Debugger_DisplayList *ui; + DebugInterface* cpu; + MainWindow* mainWindow; + QTreeWidgetItem* displayListRowSelected; + int currentRenderFrameDisplay; + FBO* currentTextureDisplay; + float fboZoomFactor; + int maxVtxDisplay; + int maxIdxDisplay; + + std::vector drawGPUState; + std::map vtxBufferSize; + std::map idxBufferSize; +}; + +#endif // DEBUGGER_DISPLAYLIST_H diff --git a/Qt/debugger_displaylist.ui b/Qt/debugger_displaylist.ui new file mode 100644 index 0000000000..77a3ee5415 --- /dev/null +++ b/Qt/debugger_displaylist.ui @@ -0,0 +1,527 @@ + + + Debugger_DisplayList + + + + 0 + 0 + 795 + 506 + + + + Dialog + + + + + + Qt::Horizontal + + + + Qt::Vertical + + + + DisplayList + + + + + + Qt::CustomContextMenu + + + false + + + false + + + false + + + 30 + + + + Id + + + + + Status + + + + + Start Address + + + + + Current Address + + + + + + + + + + Run + + + + + + + Stop + + + + + + + Next DL + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + + + + Commands + + + + + + false + + + false + + + false + + + 2 + + + false + + + + 1 + + + + + 2 + + + + + + + + + + Step + + + + + + + Next Draw + + + + + + + Goto PC + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Textures + + + + + + + Address + + + + + Width + + + + + Height + + + + + Format + + + + + + + + + Vertex Buffer + + + + + + 30 + + + + Address + + + + + Coord Type + + + + + Number Morph + + + + + Number Weights + + + + + Has Weight + + + + + Has Position + + + + + Has Normal + + + + + Has Color + + + + + Has UV + + + + + + + + 30 + + + + Idx + + + + + Address + + + + + Values + + + + + + + + + + Next 20 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Index Buffer + + + + + + Qt::Vertical + + + + + Address + + + + + + 30 + + + + Idx + + + + + Adress + + + + + Value + + + + + + + + + + + Next 20 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Framebuffer + + + + + + Qt::Vertical + + + + + 0 + 0 + + + + + VAddress + + + + + Width + + + + + Height + + + + + Format + + + + + + + 0 + 0 + + + + true + + + + + 0 + 0 + 375 + 76 + + + + + + + QFrame::Box + + + + + + true + + + + + + + + + + + + + + Display : + + + + + + + + Color + + + + + Depth + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Zoom- + + + + + + + Zoom+ + + + + + + + + + + + + + + diff --git a/Qt/debugger_memory.cpp b/Qt/debugger_memory.cpp index 3f73ccefd9..3b5cdedf08 100644 --- a/Qt/debugger_memory.cpp +++ b/Qt/debugger_memory.cpp @@ -51,9 +51,7 @@ void Debugger_Memory::Goto(u32 addr) void Debugger_Memory::on_editAddress_textChanged(const QString &arg1) { - u32 addr; - sscanf(arg1.toStdString().c_str(),"%08x",&addr); - ui->memView->gotoAddr(addr & ~3); + ui->memView->gotoAddr(arg1.toInt(0,16) & ~3); } void Debugger_Memory::on_normalBtn_clicked() @@ -83,7 +81,7 @@ void Debugger_Memory::NotifyMapLoaded() if(symbolMap.GetSymbolType(i) & ST_DATA) { QListWidgetItem* item = new QListWidgetItem(); - item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QVariant(symbolMap.GetSymbolSize(i)).toString() +")"); + item->setText(QString(symbolMap.GetSymbolName(i)) + " ("+ QString::number(symbolMap.GetSymbolSize(i)) +")"); item->setData(Qt::UserRole, symbolMap.GetAddress(i)); ui->symbols->addItem(item); } diff --git a/Qt/debugger_memorytex.cpp b/Qt/debugger_memorytex.cpp new file mode 100644 index 0000000000..bc9ea6272d --- /dev/null +++ b/Qt/debugger_memorytex.cpp @@ -0,0 +1,93 @@ +#include "debugger_memorytex.h" +#include "gfx_es2/gl_state.h" +#include "gfx/gl_common.h" +#include "gfx/gl_lost_manager.h" +#include "ui_debugger_memorytex.h" +#include "Core/MemMap.h" +#include +#include +#include "Core/HLE/sceDisplay.h" +#include "GPU/GPUInterface.h" +#include "EmuThread.h" +#include "base/display.h" + +Debugger_MemoryTex::Debugger_MemoryTex(QWidget *parent) : + QDialog(parent), + ui(new Ui::Debugger_MemoryTex) +{ + ui->setupUi(this); +} + +Debugger_MemoryTex::~Debugger_MemoryTex() +{ + delete ui; +} + + +void Debugger_MemoryTex::showEvent(QShowEvent *) +{ + +#ifdef Q_WS_X11 + // Hack to remove the X11 crash with threaded opengl when opening the first dialog + EmuThread_LockDraw(true); + QTimer::singleShot(100, this, SLOT(releaseLock())); +#endif +} + +void Debugger_MemoryTex::releaseLock() +{ + EmuThread_LockDraw(false); +} + + +void Debugger_MemoryTex::ShowTex(const GPUgstate &state) +{ + ui->texaddr->setText(QString("%1").arg(state.texaddr[0] & 0xFFFFFF,8,16,QChar('0'))); + ui->texbufwidth0->setText(QString("%1").arg(state.texbufwidth[0] & 0xFFFFFF,8,16,QChar('0'))); + ui->texformat->setText(QString("%1").arg(state.texformat & 0xFFFFFF,8,16,QChar('0'))); + ui->texsize->setText(QString("%1").arg(state.texsize[0] & 0xFFFFFF,8,16,QChar('0'))); + ui->texmode->setText(QString("%1").arg(state.texmode & 0xFFFFFF,8,16,QChar('0'))); + ui->clutformat->setText(QString("%1").arg(state.clutformat & 0xFFFFFF,8,16,QChar('0'))); + ui->clutaddr->setText(QString("%1").arg(state.clutaddr & 0xFFFFFF,8,16,QChar('0'))); + ui->clutaddrupper->setText(QString("%1").arg(state.clutaddrupper & 0xFFFFFF,8,16,QChar('0'))); + ui->loadclut->setText(QString("%1").arg(state.loadclut & 0xFFFFFF,8,16,QChar('0'))); + on_readBtn_clicked(); + + show(); +} + +void Debugger_MemoryTex::on_readBtn_clicked() +{ + EmuThread_LockDraw(true); + + GPUgstate state; + state.texaddr[0] = ui->texaddr->text().toInt(0,16); + state.texbufwidth[0] = ui->texbufwidth0->text().toInt(0,16); + state.texformat = ui->texformat->text().toInt(0,16); + state.texsize[0] = ui->texsize->text().toInt(0,16); + state.texmode = ui->texmode->text().toInt(0,16); + state.clutformat = ui->clutformat->text().toInt(0,16); + state.clutaddr = ui->clutaddr->text().toInt(0,16); + state.clutaddrupper = ui->clutaddrupper->text().toInt(0,16); + state.loadclut = ui->loadclut->text().toInt(0,16); + int w = 1 << (state.texsize[0] & 0xf); + int h = 1 << ((state.texsize[0]>>8) & 0xf); + uchar* newData = new uchar[w*h*4]; + + if(gpu->DecodeTexture(newData, state)) + { + QImage img = QImage(newData, w, h, w*4, QImage::Format_ARGB32); // EmuThread_GrabBackBuffer(); + + QPixmap pixmap = QPixmap::fromImage(img); + ui->textureImg->setPixmap(pixmap); + ui->textureImg->setMinimumWidth(pixmap.width()); + ui->textureImg->setMinimumHeight(pixmap.height()); + ui->textureImg->setMaximumWidth(pixmap.width()); + ui->textureImg->setMaximumHeight(pixmap.height()); + } + + delete[] newData; + EmuThread_LockDraw(false); + + +} diff --git a/Qt/debugger_memorytex.h b/Qt/debugger_memorytex.h new file mode 100644 index 0000000000..c04677e8d2 --- /dev/null +++ b/Qt/debugger_memorytex.h @@ -0,0 +1,30 @@ +#ifndef DEBUGGER_MEMORYTEX_H +#define DEBUGGER_MEMORYTEX_H + +#include +#include "GPU/GPUState.h" + +namespace Ui { +class Debugger_MemoryTex; +} + +class Debugger_MemoryTex : public QDialog +{ + Q_OBJECT + +public: + explicit Debugger_MemoryTex(QWidget *parent = 0); + ~Debugger_MemoryTex(); + + void ShowTex(const GPUgstate& state); +protected: + void showEvent(QShowEvent *); +private slots: + void releaseLock(); + void on_readBtn_clicked(); + +private: + Ui::Debugger_MemoryTex *ui; +}; + +#endif // DEBUGGER_MEMORYTEX_H diff --git a/Qt/debugger_memorytex.ui b/Qt/debugger_memorytex.ui new file mode 100644 index 0000000000..b163010222 --- /dev/null +++ b/Qt/debugger_memorytex.ui @@ -0,0 +1,177 @@ + + + Debugger_MemoryTex + + + + 0 + 0 + 768 + 546 + + + + Dialog + + + + + + Qt::Horizontal + + + + + + + + + TexAddr + + + + + + + TexBufWidth0 + + + + + + + TexFormat + + + + + + + TexSize + + + + + + + ClutFormat + + + + + + + ClutAddr + + + + + + + ClutAddrUpper + + + + + + + LoadClut + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TexMode + + + + + + + + + + + + + + Read + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + true + + + + + 0 + 0 + 76 + 526 + + + + + + + QFrame::Box + + + + + + + + + + + + + + + + diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 8f8efc2269..d2980033f1 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -28,7 +28,9 @@ MainWindow::MainWindow(QWidget *parent) : ui(new Ui::MainWindow), nextState(CORE_POWERDOWN), dialogDisasm(0), - memoryWindow(0) + memoryWindow(0), + memoryTexWindow(0), + displaylistWindow(0) { ui->setupUi(this); qApp->installEventFilter(this); @@ -206,6 +208,8 @@ void MainWindow::Boot() on_action_OptionsFullScreen_triggered(); memoryWindow = new Debugger_Memory(currentDebugMIPS, this, this); + memoryTexWindow = new Debugger_MemoryTex(this); + displaylistWindow = new Debugger_DisplayList(currentDebugMIPS, this, this); if (dialogDisasm) dialogDisasm->NotifyMapLoaded(); @@ -259,13 +263,12 @@ void MainWindow::UpdateMenus() ui->action_FileLoadStateFile->setEnabled(!enable); ui->action_FileQuickloadState->setEnabled(!enable); ui->action_FileQuickSaveState->setEnabled(!enable); - ui->action_CPUDynarec->setEnabled(enable); - ui->action_CPUInterpreter->setEnabled(enable); - ui->action_CPUFastInterpreter->setEnabled(enable); ui->action_EmulationStop->setEnabled(!enable); ui->action_DebugDumpFrame->setEnabled(!enable); ui->action_DebugDisassembly->setEnabled(!enable); ui->action_DebugMemoryView->setEnabled(!enable); + ui->action_DebugMemoryViewTexture->setEnabled(!enable); + ui->action_DebugDisplayList->setEnabled(!enable); ui->action_OptionsScreen1x->setChecked(0 == (g_Config.iWindowZoom - 1)); ui->action_OptionsScreen2x->setChecked(1 == (g_Config.iWindowZoom - 1)); @@ -354,6 +357,10 @@ void MainWindow::on_action_EmulationStop_triggered() dialogDisasm->close(); if(memoryWindow && memoryWindow->isVisible()) memoryWindow->close(); + if(memoryTexWindow && memoryTexWindow->isVisible()) + memoryTexWindow->close(); + if(displaylistWindow && displaylistWindow->isVisible()) + displaylistWindow->close(); EmuThread_StopGame(); SetGameTitle(""); @@ -932,6 +939,10 @@ void MainWindow::on_action_EmulationReset_triggered() dialogDisasm->close(); if(memoryWindow) memoryWindow->close(); + if(memoryTexWindow) + memoryTexWindow->close(); + if(displaylistWindow) + displaylistWindow->close(); EmuThread_StopGame(); @@ -1016,3 +1027,15 @@ void MainWindow::on_action_Sound_triggered() g_Config.bEnableSound = !g_Config.bEnableSound; UpdateMenus(); } + +void MainWindow::on_action_DebugMemoryViewTexture_triggered() +{ + if(memoryTexWindow) + memoryTexWindow->show(); +} + +void MainWindow::on_action_DebugDisplayList_triggered() +{ + if(displaylistWindow) + displaylistWindow->show(); +} diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 013bb54e1b..d2de287927 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -8,6 +8,8 @@ #include "input/input_state.h" #include "debugger_disasm.h" #include "debugger_memory.h" +#include "debugger_memorytex.h" +#include "debugger_displaylist.h" #include "controls.h" #include "gamepaddialog.h" @@ -33,6 +35,8 @@ public: Debugger_Disasm* GetDialogDisasm() { return dialogDisasm; } Debugger_Memory* GetDialogMemory() { return memoryWindow; } + Debugger_MemoryTex* GetDialogMemoryTex() { return memoryTexWindow; } + Debugger_DisplayList* GetDialogDisplaylist() { return displaylistWindow; } CoreState GetNextState() { return nextState; } void closeEvent(QCloseEvent *event); void keyPressEvent(QKeyEvent *); @@ -169,6 +173,10 @@ private slots: void on_action_Sound_triggered(); + void on_action_DebugMemoryViewTexture_triggered(); + + void on_action_DebugDisplayList_triggered(); + private: void loadLanguage(const QString &language); void createLanguageMenu(); @@ -188,6 +196,8 @@ private: Debugger_Disasm *dialogDisasm; Debugger_Memory *memoryWindow; + Debugger_MemoryTex *memoryTexWindow; + Debugger_DisplayList *displaylistWindow; Controls* controls; GamePadDialog* gamePadDlg; diff --git a/Qt/mainwindow.ui b/Qt/mainwindow.ui index 10f40c73a7..a6ef9df025 100644 --- a/Qt/mainwindow.ui +++ b/Qt/mainwindow.ui @@ -44,7 +44,7 @@ 0 0 800 - 21 + 23 @@ -83,8 +83,10 @@ + + @@ -616,6 +618,11 @@ Memory View Texture... + + + DisplayList... + + true From 3a00e0b9cced423766dc7e52be0f70a1e9546da7 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sun, 17 Feb 2013 01:53:55 +0100 Subject: [PATCH 21/69] Oops, too much line deleted --- Qt/mainwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index d2980033f1..c6b45a5dcc 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -263,6 +263,8 @@ void MainWindow::UpdateMenus() ui->action_FileLoadStateFile->setEnabled(!enable); ui->action_FileQuickloadState->setEnabled(!enable); ui->action_FileQuickSaveState->setEnabled(!enable); + ui->action_CPUDynarec->setEnabled(enable); + ui->action_CPUInterpreter->setEnabled(enable); ui->action_EmulationStop->setEnabled(!enable); ui->action_DebugDumpFrame->setEnabled(!enable); ui->action_DebugDisassembly->setEnabled(!enable); From f41b3f7cf1bd0db390a3ab18100c66f71917692a Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 17 Feb 2013 09:45:20 +0800 Subject: [PATCH 22/69] sceSAS style & simplification --- Core/HLE/sceSas.cpp | 140 ++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 78 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 91e4b047f9..26ad93e6ab 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -61,9 +61,9 @@ void __SasShutdown() { } -u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampleRate) -{ +u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampleRate) { INFO_LOG(HLE,"sceSasInit(%08x, %i, %i, %i, %i)", core, grainSize, maxVoices, outputMode, sampleRate); + sas->SetGrainSize(grainSize); sas->maxVoices = maxVoices; sas->outputMode = outputMode; @@ -75,42 +75,43 @@ u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampl return 0; } -u32 sceSasGetEndFlag(u32 core) -{ +u32 sceSasGetEndFlag(u32 core) { u32 endFlag = 0; for (int i = 0; i < sas->maxVoices; i++) { if (!sas->voices[i].playing) endFlag |= (1 << i); } + DEBUG_LOG(HLE,"sceSasGetEndFlag(%08x)", endFlag); return endFlag; } // Runs the mixer -u32 _sceSasCore(u32 core, u32 outAddr) -{ +u32 _sceSasCore(u32 core, u32 outAddr) { DEBUG_LOG(HLE,"sceSasCore(%08x, %08x)", core, outAddr); + if (!Memory::IsValidAddress(outAddr)) { return ERROR_SAS_INVALID_PARAMETER; } + Memory::Memset(outAddr, 0, sas->GetGrainSize() * 2 * 2); sas->Mix(outAddr); return 0; } // Another way of running the mixer, what was the difference again? -u32 _sceSasCoreWithMix(u32 core, u32 outAddr, int leftVolume, int rightVolume) -{ +u32 _sceSasCoreWithMix(u32 core, u32 outAddr, int leftVolume, int rightVolume) { DEBUG_LOG(HLE,"sceSasCoreWithMix(%08x, %08x, %i, %i)", core , outAddr, leftVolume, rightVolume); + if (!Memory::IsValidAddress(outAddr)) { return ERROR_SAS_INVALID_PARAMETER; } + sas->Mix(outAddr); return 0; } -u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) -{ +u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) { DEBUG_LOG(HLE,"sceSasSetVoice(%08x, %i, %08x, %i, %i)", core, voiceNum, vagAddr, size, loop); if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { @@ -168,8 +169,7 @@ u32 sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop) return 0; } -u32 sceSasGetPauseFlag(u32 core) -{ +u32 sceSasGetPauseFlag(u32 core) { u32 pauseFlag = 0; for (int i = 0; i < sas->maxVoices; i++) { if (sas->voices[i].paused) @@ -180,24 +180,21 @@ u32 sceSasGetPauseFlag(u32 core) return pauseFlag; } -u32 sceSasSetPause(u32 core, int voicebit, int pause) -{ +u32 sceSasSetPause(u32 core, int voicebit, int pause) { DEBUG_LOG(HLE,"sceSasSetPause(%08x, %08x, %i)", core, voicebit, pause); + for (int i = 0; voicebit != 0; i++, voicebit >>= 1) { if (i < PSP_SAS_VOICES_MAX && i >= 0) { if ((voicebit & 1) != 0) sas->voices[i].paused = pause ? true : false; - } - // TODO: Correct error code? Mimana crashes otherwise. - else + } else // TODO: Correct error code? Mimana crashes otherwise. return ERROR_SAS_INVALID_VOICE; } return 0; } -u32 sceSasSetVolume(u32 core, int voiceNum, int leftVol, int rightVol, int effectLeftVol, int effectRightVol) -{ +u32 sceSasSetVolume(u32 core, int voiceNum, int leftVol, int rightVol, int effectLeftVol, int effectRightVol) { DEBUG_LOG(HLE,"sceSasSetVolume(%08x, %i, %i, %i, %i, %i)", core, voiceNum, leftVol, rightVol, effectLeftVol, effectRightVol); if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { @@ -213,8 +210,7 @@ u32 sceSasSetVolume(u32 core, int voiceNum, int leftVol, int rightVol, int effec return 0; } -u32 sceSasSetPitch(u32 core, int voiceNum, int pitch) -{ +u32 sceSasSetPitch(u32 core, int voiceNum, int pitch) { DEBUG_LOG(HLE,"sceSasSetPitch(%08x, %i, %i)", core, voiceNum, pitch); if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { @@ -228,8 +224,7 @@ u32 sceSasSetPitch(u32 core, int voiceNum, int pitch) return 0; } -u32 sceSasSetKeyOn(u32 core, int voiceNum) -{ +u32 sceSasSetKeyOn(u32 core, int voiceNum) { DEBUG_LOG(HLE,"sceSasSetKeyOn(%08x, %i)", core, voiceNum); if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { @@ -237,39 +232,38 @@ u32 sceSasSetKeyOn(u32 core, int voiceNum) return ERROR_SAS_INVALID_VOICE; } - SasVoice &v = sas->voices[voiceNum]; if (sas->voices[voiceNum].paused) { return ERROR_SAS_VOICE_PAUSED; } + SasVoice &v = sas->voices[voiceNum]; v.KeyOn(); return 0; } // sceSasSetKeyOff can be used to start sounds, that just sound during the Release phase! -u32 sceSasSetKeyOff(u32 core, int voiceNum) -{ +u32 sceSasSetKeyOff(u32 core, int voiceNum) { if (voiceNum == -1) { // TODO: Some games (like Every Extend Extra) deliberately pass voiceNum = -1. Does that mean all voices? for now let's ignore. DEBUG_LOG(HLE,"sceSasSetKeyOff(%08x, %i) - voiceNum = -1???", core, voiceNum); return 0; - } else if (voiceNum < 0 || voiceNum >= PSP_SAS_VOICES_MAX) { + } else if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { WARN_LOG(HLE, "%s: invalid voicenum %d", __FUNCTION__, voiceNum); return ERROR_SAS_INVALID_VOICE; } else { DEBUG_LOG(HLE,"sceSasSetKeyOff(%08x, %i)", core, voiceNum); - SasVoice &v = sas->voices[voiceNum]; + if (sas->voices[voiceNum].paused) { return ERROR_SAS_VOICE_PAUSED; } + SasVoice &v = sas->voices[voiceNum]; v.KeyOff(); return 0; } } -u32 sceSasSetNoise(u32 core, int voiceNum, int freq) -{ +u32 sceSasSetNoise(u32 core, int voiceNum, int freq) { DEBUG_LOG(HLE,"sceSasSetNoise(%08x, %i, %i)", core, voiceNum, freq); if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { @@ -284,8 +278,7 @@ u32 sceSasSetNoise(u32 core, int voiceNum, int freq) return 0; } -u32 sceSasSetSL(u32 core, int voiceNum, int level) -{ +u32 sceSasSetSL(u32 core, int voiceNum, int level) { DEBUG_LOG(HLE,"sceSasSetSL(%08x, %i, %i)", core, voiceNum, level); if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { @@ -298,8 +291,7 @@ u32 sceSasSetSL(u32 core, int voiceNum, int level) return 0; } -u32 sceSasSetADSR(u32 core, int voiceNum, int flag , int a, int d, int s, int r) -{ +u32 sceSasSetADSR(u32 core, int voiceNum, int flag , int a, int d, int s, int r) { DEBUG_LOG(HLE,"0=sceSasSetADSR(%08x, %i, %i, %08x, %08x, %08x, %08x)",core, voiceNum, flag, a, d, s, r) if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { @@ -315,8 +307,7 @@ u32 sceSasSetADSR(u32 core, int voiceNum, int flag , int a, int d, int s, int r) return 0; } -u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int r) -{ +u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int r) { DEBUG_LOG(HLE,"sceSasSetADSRMode(%08x, %i, %i, %08x, %08x, %08x, %08x)",core, voiceNum, flag, a,d,s,r) if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { @@ -333,21 +324,23 @@ u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int } -u32 sceSasSetSimpleADSR(u32 core, u32 voiceNum, u32 ADSREnv1, u32 ADSREnv2) -{ +u32 sceSasSetSimpleADSR(u32 core, int voiceNum, u32 ADSREnv1, u32 ADSREnv2) { DEBUG_LOG(HLE,"sasSetSimpleADSR(%08x, %i, %08x, %08x)", core, voiceNum, ADSREnv1, ADSREnv2); + + if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { + WARN_LOG(HLE, "%s: invalid voicenum %d", __FUNCTION__, voiceNum); + return ERROR_SAS_INVALID_VOICE; + } + SasVoice &v = sas->voices[voiceNum]; v.envelope.SetSimpleEnvelope(ADSREnv1 & 0xFFFF, ADSREnv2 & 0xFFFF); return 0; } -u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum) -{ - // Spam reduction - if (voiceNum == 17) { - DEBUG_LOG(HLE,"sceSasGetEnvelopeHeight(%08x, %i)", core, voiceNum); - } - if (voiceNum >= PSP_SAS_VOICES_MAX) { +u32 sceSasGetEnvelopeHeight(u32 core, int voiceNum) { + DEBUG_LOG(HLE,"sceSasGetEnvelopeHeight(%08x, %i)", core, voiceNum); + + if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { WARN_LOG(HLE, "%s: invalid voicenum %d", __FUNCTION__, voiceNum); return ERROR_SAS_INVALID_VOICE; } @@ -356,105 +349,96 @@ u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum) return v.envelope.GetHeight(); } -u32 sceSasRevType(u32 core, int type) -{ +u32 sceSasRevType(u32 core, int type) { DEBUG_LOG(HLE,"sceSasRevType(%08x, %i)", core, type); sas->waveformEffect.type = type; return 0; } -u32 sceSasRevParam(u32 core, int delay, int feedback) -{ +u32 sceSasRevParam(u32 core, int delay, int feedback) { DEBUG_LOG(HLE,"sceSasRevParam(%08x, %i, %i)", core, delay, feedback); sas->waveformEffect.delay = delay; sas->waveformEffect.feedback = feedback; return 0; } -u32 sceSasRevEVOL(u32 core, int lv, int rv) -{ +u32 sceSasRevEVOL(u32 core, int lv, int rv) { DEBUG_LOG(HLE,"sceSasRevEVOL(%08x, %i, %i)", core, lv, rv); sas->waveformEffect.leftVol = lv; sas->waveformEffect.rightVol = rv; return 0; } -u32 sceSasRevVON(u32 core, int dry, int wet) -{ +u32 sceSasRevVON(u32 core, int dry, int wet) { DEBUG_LOG(HLE,"sceSasRevVON(%08x, %i, %i)", core, dry, wet); sas->waveformEffect.isDryOn = (dry > 0); sas->waveformEffect.isWetOn = (wet > 0); return 0; } -u32 sceSasGetGrain(u32 core) -{ +u32 sceSasGetGrain(u32 core) { DEBUG_LOG(HLE,"sceSasGetGrain(%08x)", core); return sas->GetGrainSize(); } -u32 sceSasSetGrain(u32 core, int grain) -{ +u32 sceSasSetGrain(u32 core, int grain) { INFO_LOG(HLE,"sceSasSetGrain(%08x, %i)", core, grain); sas->SetGrainSize(grain); return 0; } -u32 sceSasGetOutputMode(u32 core) -{ +u32 sceSasGetOutputMode(u32 core) { DEBUG_LOG(HLE,"sceSasGetOutputMode(%08x)", core); return sas->outputMode; } -u32 sceSasSetOutputMode(u32 core, u32 outputMode) -{ +u32 sceSasSetOutputMode(u32 core, u32 outputMode) { DEBUG_LOG(HLE,"sceSasSetOutputMode(%08x, %i)", core, outputMode); sas->outputMode = outputMode; return 0; } -u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) -{ +u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) { DEBUG_LOG(HLE,"sceSasGetAllEnvelopeHeights(%08x, %i)", core, heightsAddr); - if (Memory::IsValidAddress(heightsAddr)) { - for (int i = 0; i < PSP_SAS_VOICES_MAX; i++) { + + if (!Memory::IsValidAddress(heightsAddr)) { + return ERROR_SAS_INVALID_PARAMETER; + } + + for (int i = 0; i < PSP_SAS_VOICES_MAX; i++) { int voiceHeight = sas->voices[i].envelope.GetHeight(); Memory::Write_U32(voiceHeight, heightsAddr + i * 4); - } } + return 0; } -u32 sceSasSetTriangularWave(u32 sasCore, int voice, int unknown) -{ +u32 sceSasSetTriangularWave(u32 sasCore, int voice, int unknown) { ERROR_LOG(HLE,"UNIMPL sceSasSetTriangularWave(%08x, %i, %i)", sasCore, voice, unknown); return 0; } -u32 sceSasSetSteepWave(u32 sasCore, int voice, int unknown) -{ +u32 sceSasSetSteepWave(u32 sasCore, int voice, int unknown) { ERROR_LOG(HLE,"UNIMPL sceSasSetSteepWave(%08x, %i, %i)", sasCore, voice, unknown); return 0; } -u32 __sceSasSetVoiceATRAC3(u32 core, int voice, int atrac3Context) -{ +u32 __sceSasSetVoiceATRAC3(u32 core, int voice, int atrac3Context) { ERROR_LOG(HLE,"UNIMPL __sceSasSetVoiceATRAC3(%08x, %i, %i)", core, voice, atrac3Context); return 0; } -u32 __sceSasConcatenateATRAC3(u32 core, int voice, u32 atrac3DataAddr, int atrac3DataLength) -{ +u32 __sceSasConcatenateATRAC3(u32 core, int voice, u32 atrac3DataAddr, int atrac3DataLength) { ERROR_LOG(HLE,"UNIMPL __sceSasConcatenateATRAC3(%08x, %i, %i)", core, voice, atrac3DataAddr, atrac3DataLength); return 0; } -u32 __sceSasUnsetATRAC3(u32 core, int voice) -{ +u32 __sceSasUnsetATRAC3(u32 core, int voice) { ERROR_LOG(HLE, "UNIMPL __sceSasUnsetATRAC3(%08x, %i)", core, voice); return 0; } + const HLEFunction sceSasCore[] = { {0x42778a9f, WrapU_UUUUU, "__sceSasInit"}, @@ -468,8 +452,8 @@ const HLEFunction sceSasCore[] = {0x019b25eb, WrapU_UIIIIII, "__sceSasSetADSR"}, {0x9ec3676a, WrapU_UIIIIII, "__sceSasSetADSRmode"}, {0x5f9529f6, WrapU_UII, "__sceSasSetSL"}, - {0x74ae582a, WrapU_UU, "__sceSasGetEnvelopeHeight"}, - {0xcbcd4f79, WrapU_UUUU, "__sceSasSetSimpleADSR"}, + {0x74ae582a, WrapU_UI, "__sceSasGetEnvelopeHeight"}, + {0xcbcd4f79, WrapU_UIUU, "__sceSasSetSimpleADSR"}, {0xa0cf2fa4, WrapU_UI, "__sceSasSetKeyOff"}, {0x76f01aca, WrapU_UI, "__sceSasSetKeyOn"}, {0xf983b186, WrapU_UII, "__sceSasRevVON"}, From 6eae8ed36a737a92248852b1d42353915502049d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 19:57:35 -0800 Subject: [PATCH 23/69] Disable VDot and Vec3 in x86 jit, broke things. --- Core/MIPS/x86/CompVFPU.cpp | 4 ++-- Core/MIPS/x86/RegCacheFPU.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 958f6baf37..8784d2cafc 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -311,7 +311,7 @@ void Jit::Comp_SVQ(u32 op) } void Jit::Comp_VDot(u32 op) { - CONDITIONAL_DISABLE; + DISABLE; // WARNING: No prefix support! if (js.MayHavePrefix()) { @@ -368,7 +368,7 @@ void Jit::Comp_VDot(u32 op) { } void Jit::Comp_VecDo3(u32 op) { - CONDITIONAL_DISABLE; + DISABLE; // WARNING: No prefix support! if (js.MayHavePrefix()) diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index 429c25b148..af5d2f4953 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -35,7 +35,6 @@ enum { TEMP1 = TEMP0 + 1, TEMP2 = TEMP0 + 2, TEMP3 = TEMP0 + 3, - TEMP4 = TEMP0 + 4, NUM_MIPS_FPRS = 32 + 128 + NUM_TEMPS, }; From 0fdc975fded82130f31825daafe6eaec30668abf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 20:22:08 -0800 Subject: [PATCH 24/69] Fix wrong type in x86 jit fpu/vfpu load store. --- Core/MIPS/x86/CompFPU.cpp | 2 +- Core/MIPS/x86/CompVFPU.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/MIPS/x86/CompFPU.cpp b/Core/MIPS/x86/CompFPU.cpp index f5ac3226ea..bee31435cc 100644 --- a/Core/MIPS/x86/CompFPU.cpp +++ b/Core/MIPS/x86/CompFPU.cpp @@ -87,7 +87,7 @@ void Jit::Comp_FPU3op(u32 op) } } -static u32 GC_ALIGNED16(ssLoadStoreTemp[1]); +static u32 GC_ALIGNED16(ssLoadStoreTemp); void Jit::Comp_FPULS(u32 op) { diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 8784d2cafc..8da64f6987 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -163,7 +163,7 @@ bool DestRegOverlaps(int dreg, int di, int sn, u8 sregs[], int tn, u8 tregs[]) return false; } -static u32 GC_ALIGNED16(ssLoadStoreTemp[1]); +static u32 GC_ALIGNED16(ssLoadStoreTemp); void Jit::Comp_SV(u32 op) { CONDITIONAL_DISABLE; From d99c9fb2ff2bf22eee63d884ca031a5434d35f28 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 17 Feb 2013 15:23:56 +1000 Subject: [PATCH 25/69] Fix Symbian JIT + FastMem by using a mapped virtual address RChunk. --- Common/MemArena.cpp | 54 +++++++++++++++++++++------------------- Common/MemArena.h | 8 ++++++ Common/MemoryUtil.h | 5 ---- Core/MIPS/ARM/ArmAsm.cpp | 4 --- Core/MemMap.h | 4 +-- 5 files changed, 39 insertions(+), 36 deletions(-) diff --git a/Common/MemArena.cpp b/Common/MemArena.cpp index dcb0c82e51..4fabb11237 100644 --- a/Common/MemArena.cpp +++ b/Common/MemArena.cpp @@ -131,8 +131,6 @@ void MemArena::GrabLowMemSpace(size_t size) ERROR_LOG(MEMMAP, "Failed to grab ashmem space of size: %08x errno: %d", (int)size, (int)(errno)); return; } -#elif defined(UNUSABLE_MMAP) - // Do nothing as we are using malloc() #else mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; fd = open(ram_temp_file.c_str(), O_RDWR | O_CREAT, mode); @@ -157,8 +155,9 @@ void MemArena::ReleaseSpace() #ifdef _WIN32 CloseHandle(hMemoryMapping); hMemoryMapping = 0; -#elif defined(UNUSABLE_MMAP) - // Do nothing as we are using malloc() +#elif defined(__SYMBIAN32__) + memmap->Close(); + delete memmap; #else close(fd); #endif @@ -170,20 +169,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base) #ifdef _WIN32 size = roundup(size); void *ptr = MapViewOfFileEx(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size, base); - if (!ptr) { - //ERROR_LOG(MEMMAP, "Failed to map memory: %08x %08x %08x : %s", (u32)offset, (u32)size, (u32)base, GetLastErrorMsg()); - } else { - //ERROR_LOG(MEMMAP, "Mapped memory: %08x %08x %08x : %s", (u32)offset, (u32)size, (u32)base, GetLastErrorMsg()); - } return ptr; -#elif defined(UNUSABLE_MMAP) - void *retval = malloc(size); - if (!retval) - { - NOTICE_LOG(MEMMAP, "malloc failed: %s", strerror(errno)); - return 0; - } - return retval; #else void *retval = mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED | ((base == 0) ? 0 : MAP_FIXED), fd, offset); @@ -202,14 +188,14 @@ void MemArena::ReleaseView(void* view, size_t size) { #ifdef _WIN32 UnmapViewOfFile(view); -#elif defined(UNUSABLE_MMAP) - free(view); +#elif defined(__SYMBIAN32__) + memmap->Decommit((int)view - (int)memmap->Base(), size); #else munmap(view, size); #endif } - +#ifndef __SYMBIAN32__ u8* MemArena::Find4GBBase() { #ifdef _M_X64 @@ -224,8 +210,8 @@ u8* MemArena::Find4GBBase() return reinterpret_cast(0x2300000000ULL); #endif -#else - // 32 bit +#else // 32 bit + #ifdef _WIN32 // The highest thing in any 1GB section of memory space is the locked cache. We only need to fit it. u8* base = (u8*)VirtualAlloc(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE); @@ -233,9 +219,6 @@ u8* MemArena::Find4GBBase() VirtualFree(base, 0, MEM_RELEASE); } return base; -#elif defined(UNUSABLE_MMAP) - // We are unable to use relative addresses due to lack of mmap() - return NULL; #else void* base = mmap(0, 0x10000000, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); @@ -248,6 +231,7 @@ u8* MemArena::Find4GBBase() #endif #endif } +#endif // yeah, this could also be done in like two bitwise ops... @@ -282,6 +266,12 @@ static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 if (view.flags & MV_MIRROR_PREVIOUS) { position = last_position; } else { +#ifdef __SYMBIAN32__ + *(view.out_ptr_low) = (u8*)((int)arena->memmap->Base() + view.virtual_address); + arena->memmap->Commit(view.virtual_address & 0x3FFFFFFF, view.size); + } + *(view.out_ptr) = (u8*)((int)arena->memmap->Base() + view.virtual_address & 0x3FFFFFFF); +#else *(view.out_ptr_low) = (u8*)arena->CreateView(position, view.size); if (!*view.out_ptr_low) goto bail; @@ -299,6 +289,8 @@ static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 if (!*view.out_ptr) goto bail; } +#endif + #endif last_position = position; position += roundup(view.size); @@ -344,7 +336,9 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena total_mem += roundup(views[i].size); } // Grab some pagefile backed memory out of the void ... +#ifndef __SYMBIAN32__ arena->GrabLowMemSpace(total_mem); +#endif // Now, create views in high memory where there's plenty of space. #ifdef _M_X64 @@ -374,6 +368,16 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena break; } } +#elif defined(__SYMBIAN32__) + arena->memmap = new RChunk(); + arena->memmap->CreateDisconnectedLocal(0 , 0, 0x10000000); + if (!Memory_TryBase(arena->memmap->Base(), views, num_views, flags, arena)) + { + PanicAlert("MemoryMap_Setup: Failed finding a memory base."); + exit(0); + return 0; + } + u8* base = arena->memmap->Base(); #else // Linux32 is fine with the x64 method, although limited to 32-bit with no automirrors. u8 *base = MemArena::Find4GBBase(); diff --git a/Common/MemArena.h b/Common/MemArena.h index 75dd738b0e..a12f8f493b 100644 --- a/Common/MemArena.h +++ b/Common/MemArena.h @@ -22,6 +22,10 @@ #include #endif +#ifdef __SYMBIAN32__ +#include +#endif + #include "Common.h" // This class lets you create a block of anonymous RAM, and then arbitrarily map views into it. @@ -36,8 +40,12 @@ public: void *CreateView(s64 offset, size_t size, void *base = 0); void ReleaseView(void *view, size_t size); +#ifdef __SYMBIAN32__ + RChunk* memmap; +#else // This only finds 1 GB in 32-bit static u8 *Find4GBBase(); +#endif private: #ifdef _WIN32 diff --git a/Common/MemoryUtil.h b/Common/MemoryUtil.h index f8c6ee6b1a..bafa7e4e88 100644 --- a/Common/MemoryUtil.h +++ b/Common/MemoryUtil.h @@ -23,11 +23,6 @@ #endif #include -#if defined(__SYMBIAN32__) - // Also Xbox 360 - #define UNUSABLE_MMAP 1 -#endif - void* AllocateExecutableMemory(size_t size, bool low = true); void* AllocateMemoryPages(size_t size); void FreeMemoryPages(void* ptr, size_t size); diff --git a/Core/MIPS/ARM/ArmAsm.cpp b/Core/MIPS/ARM/ArmAsm.cpp index 9a1ad4bc82..d7d1e4b907 100644 --- a/Core/MIPS/ARM/ArmAsm.cpp +++ b/Core/MIPS/ARM/ArmAsm.cpp @@ -113,11 +113,7 @@ void Jit::GenerateFixedCode() // * downcount // * R2-R4 // Really starting to run low on registers already though... -#ifdef UNUSABLE_MMAP - MOVI2R(R11, (u32)Memory::m_pRAM - 0x08000000); -#else MOVI2R(R11, (u32)Memory::base); -#endif MOVI2R(R10, (u32)mips_); MOVI2R(R9, (u32)GetBlockCache()->GetCodePointers()); diff --git a/Core/MemMap.h b/Core/MemMap.h index bf77692018..a7731d839f 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -36,9 +36,9 @@ #if defined(_DEBUG) //#define SAFE_MEMORY #endif -// Required for UNUSABLE_MMAP. Can define this in cmake instead later + #ifdef __SYMBIAN32__ -#define SAFE_MEMORY +//#define SAFE_MEMORY #endif From 106cbcfc5d3758929995475fdf3ea35440bc048e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Feb 2013 21:26:32 -0800 Subject: [PATCH 26/69] Fix possible overlap issue in VDot. --- Core/MIPS/MIPSIntVFPU.cpp | 1 + Core/MIPS/x86/CompVFPU.cpp | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 8466b5250c..7aa182f6b5 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -936,6 +936,7 @@ namespace MIPSInt } d = sum; ApplyPrefixD(&d,V_Single); + // TODO: Shouldn't this respect the mask? V(vd) = d; PC += 4; EatPrefixes(); diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 8da64f6987..b011c6ae52 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -146,21 +146,26 @@ void Jit::ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWrit // Vector regs can overlap in all sorts of swizzled ways. // This does allow a single overlap in sregs[i]. -bool DestRegOverlaps(int dreg, int di, int sn, u8 sregs[], int tn, u8 tregs[]) +bool IsOverlapSafeAllowS(int dreg, int di, int sn, u8 sregs[], int tn, u8 tregs[]) { for (int i = 0; i < sn; ++i) { if (sregs[i] == dreg && i != di) - return true; + return false; } for (int i = 0; i < tn; ++i) { if (tregs[i] == dreg) - return true; + return false; } // Hurray, no overlap, we can write directly. - return false; + return true; +} + +bool IsOverlapSafe(int dreg, int di, int sn, u8 sregs[], int tn, u8 tregs[]) +{ + return IsOverlapSafeAllowS(dreg, di, sn, sregs, tn, tregs) && sregs[di] != dreg; } static u32 GC_ALIGNED16(ssLoadStoreTemp); @@ -335,18 +340,15 @@ void Jit::Comp_VDot(u32 op) { int n = GetNumVectorElements(sz); X64Reg tempxreg = XMM0; - if (!DestRegOverlaps(dregs[0], 0, n, sregs, n, tregs)) + if (IsOverlapSafe(dregs[0], 0, n, sregs, n, tregs)) { fpr.MapRegsV(dregs, V_Single, MAP_NOINIT); tempxreg = fpr.VX(dregs[0]); } + // Need to start with +0.0f so it doesn't result in -0.0f. MOVSS(tempxreg, M((void *) &zero)); - MOVSS(XMM1, fpr.V(sregs[0])); - MULSS(XMM1, fpr.V(tregs[0])); - ADDSS(tempxreg, R(XMM1)); - - for (int i = 1; i < n; i++) + for (int i = 0; i < n; i++) { // sum += s[i]*t[i]; MOVSS(XMM1, fpr.V(sregs[i])); @@ -357,7 +359,7 @@ void Jit::Comp_VDot(u32 op) { if (!fpr.V(dregs[0]).IsSimpleReg(tempxreg)) { fpr.MapRegsV(dregs, V_Single, MAP_NOINIT); - MOVSS(fpr.V(dregs[0]), XMM0); + MOVSS(fpr.V(dregs[0]), tempxreg); } // TODO: applyprefixD here somehow (write mask etc..) @@ -427,7 +429,7 @@ void Jit::Comp_VecDo3(u32 op) { X64Reg tempxregs[4]; for (int i = 0; i < n; ++i) { - if (DestRegOverlaps(dregs[i], i, n, sregs, n, tregs)) + if (!IsOverlapSafeAllowS(dregs[i], i, n, sregs, n, tregs)) { // On 32-bit we only have 6 xregs for mips regs, use XMM0/XMM1 if possible. if (i < 2) From ff8390123a8ee551013a9909175325ec293dabdb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 00:38:50 -0800 Subject: [PATCH 27/69] Focus the main window when showing the log. --- Windows/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Windows/main.cpp b/Windows/main.cpp index 48fce377a6..f729c9abb8 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -161,6 +161,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } // else // MainWindow::BrowseAndBoot(); + if (!hideLog) + SetForegroundWindow(hwndMain); if (fileToStart != NULL && stateToLoad != NULL) SaveState::Load(stateToLoad); From a9eb6cf4a49a12953f63439e0dc4a737054b27fb Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 17 Feb 2013 20:21:42 +1000 Subject: [PATCH 28/69] Fix crash on Symbian when doing "Return to Menu" --- Common/MemArena.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/MemArena.cpp b/Common/MemArena.cpp index 4fabb11237..d2d03bd720 100644 --- a/Common/MemArena.cpp +++ b/Common/MemArena.cpp @@ -189,7 +189,7 @@ void MemArena::ReleaseView(void* view, size_t size) #ifdef _WIN32 UnmapViewOfFile(view); #elif defined(__SYMBIAN32__) - memmap->Decommit((int)view - (int)memmap->Base(), size); + memmap->Decommit(((int)view - (int)memmap->Base()) & 0x3FFFFFFF, size); #else munmap(view, size); #endif From 2bf958b06f199648067f7935a8e39f1f20a7bf01 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 17 Feb 2013 20:50:17 +0800 Subject: [PATCH 29/69] Stylish the case DEC_U8_2/DEC_U16_2/DEC_FLOAT_2 --- GPU/GLES/VertexDecoder.h | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index 0be7140f13..243983c5ac 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -239,23 +239,29 @@ public: } void ReadUV(float uv[2]) { - const u8 *b = (const u8 *)(data_ + decFmt_.uvoff); - const u16 *s = (const u16 *)(data_ + decFmt_.uvoff); - const float *f = (const float *)(data_ + decFmt_.uvoff); switch (decFmt_.uvfmt) { case DEC_U8_2: - uv[0] = b[0] * (1.f / 128.f); - uv[1] = b[1] * (1.f / 128.f); + { + const u8 *b = (const u8 *)(data_ + decFmt_.uvoff); + uv[0] = b[0] * (1.f / 128.f); + uv[1] = b[1] * (1.f / 128.f); + } break; case DEC_U16_2: - uv[0] = s[0] * (1.f / 32768.f); - uv[1] = s[1] * (1.f / 32768.f); + { + const u16 *s = (const u16 *)(data_ + decFmt_.uvoff); + uv[0] = s[0] * (1.f / 32768.f); + uv[1] = s[1] * (1.f / 32768.f); + } break; case DEC_FLOAT_2: - uv[0] = f[0] * 2.0f; - uv[1] = f[1] * 2.0f; + { + const float *f = (const float *)(data_ + decFmt_.uvoff); + uv[0] = f[0] * 2.0f; + uv[1] = f[1] * 2.0f; + } break; case DEC_U16A_2: From 45e4919fe95f55c9c751c0827aea1c6d6a7b72e9 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 17 Feb 2013 21:26:23 +0800 Subject: [PATCH 30/69] Change .f to .0f etc. --- GPU/GLES/VertexDecoder.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index 6e68bdec48..75614f67ea 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -197,7 +197,7 @@ void VertexDecoder::Step_Color5551() const c[0] = Convert5To8(cdata & 0x1f); c[1] = Convert5To8((cdata>>5) & 0x1f); c[2] = Convert5To8((cdata>>10) & 0x1f); - c[3] = (cdata>>15) ? 255 : 0; + c[3] = (cdata>>15) ? 255.0f : 0.0f; } void VertexDecoder::Step_Color4444() const @@ -222,15 +222,15 @@ void VertexDecoder::Step_Color565Morph() const { float w = gstate_c.morphWeights[n]; u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff); - col[0] += w * (cdata & 0x1f) / 31.f; - col[1] += w * ((cdata>>5) & 0x3f) / 63.f; - col[2] += w * ((cdata>>11) & 0x1f) / 31.f; + col[0] += w * (cdata & 0x1f) / 31.0f; + col[1] += w * ((cdata>>5) & 0x3f) / 63.0f; + col[2] += w * ((cdata>>11) & 0x1f) / 31.0f; } u8 *c = decoded_ + decFmt.c0off; for (int i = 0; i < 3; i++) { c[i] = (u8)(col[i] * 255.0f); } - c[3] = 255; + c[3] = 255.0f; } void VertexDecoder::Step_Color5551Morph() const @@ -240,9 +240,9 @@ void VertexDecoder::Step_Color5551Morph() const { float w = gstate_c.morphWeights[n]; u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff); - col[0] += w * (cdata & 0x1f) / 31.f; - col[1] += w * ((cdata>>5) & 0x1f) / 31.f; - col[2] += w * ((cdata>>10) & 0x1f) / 31.f; + col[0] += w * (cdata & 0x1f) / 31.0f; + col[1] += w * ((cdata>>5) & 0x1f) / 31.0f; + col[2] += w * ((cdata>>10) & 0x1f) / 31.0f; col[3] += w * ((cdata>>15) ? 1.0f : 0.0f); } u8 *c = decoded_ + decFmt.c0off; @@ -259,7 +259,7 @@ void VertexDecoder::Step_Color4444Morph() const float w = gstate_c.morphWeights[n]; u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff); for (int j = 0; j < 4; j++) - col[j] += w * ((cdata >> (j * 4)) & 0xF) / 15.f; + col[j] += w * ((cdata >> (j * 4)) & 0xF) / 15.0f; } u8 *c = decoded_ + decFmt.c0off; for (int i = 0; i < 4; i++) { @@ -346,7 +346,7 @@ void VertexDecoder::Step_NormalS16Morph() const multiplier = -multiplier; } const s16 *sv = (const s16 *)(ptr_ + onesize_*n + nrmoff); - multiplier *= (1.0f/32767.f); + multiplier *= (1.0f/32767.0f); for (int j = 0; j < 3; j++) normal[j] += sv[j] * multiplier; } From 8ba2769d5ebe8265bbce4c386da59fc12678192a Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 18 Feb 2013 00:04:44 +1000 Subject: [PATCH 31/69] iOS Objective-C code dump. ViewController courtesy of rock88. Made modifications for simplification and code-style. Still missing some files (eg. images). Also, CMake is not set up correctly yet. --- CMakeLists.txt | 19 +++- ios/AppDelegate.h | 13 +++ ios/AppDelegate.m | 25 +++++ ios/PPSSPP-Info.plist | 46 ++++++++ ios/PPSSPP-Prefix.pch | 9 ++ ios/ViewController.h | 8 ++ ios/ViewController.mm | 241 ++++++++++++++++++++++++++++++++++++++++ ios/ios.toolchain.cmake | 2 +- ios/main.m | 12 ++ 9 files changed, 371 insertions(+), 4 deletions(-) create mode 100644 ios/AppDelegate.h create mode 100644 ios/AppDelegate.m create mode 100644 ios/PPSSPP-Info.plist create mode 100644 ios/PPSSPP-Prefix.pch create mode 100644 ios/ViewController.h create mode 100644 ios/ViewController.mm create mode 100644 ios/main.m diff --git a/CMakeLists.txt b/CMakeLists.txt index 37509ed442..c0c7004b83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,6 +410,16 @@ if(ANDROID) native/android/native-audio-so.h) target_link_libraries(native_audio OpenSLES) # No target +elseif(IOS) + set(nativeExtra ${nativeExtra} + ios/main.m + ios/AppDelegate.m + ios/AppDelegate.h + ios/ViewController.mm + ios/ViewController.h) + set(CMAKE_EXE_LINKER_FLAGS "-framework Foundation -framework CoreGraphics -framework QuartzCore -framework OpenGLES -framework UIKit") + # No target + # set(TargetBin PPSSPP) elseif(USING_QT_UI) # Currently unused find_package(Qt4 COMPONENTS QtMultimedia QtOpenGL QtGui QtCore) @@ -433,9 +443,7 @@ elseif(SDL_FOUND) elseif(PANDORA) set(nativeExtraLibs ${nativeExtraLibs} pthread EGL X11) endif() - if(NOT IOS) # No target - set(TargetBin PPSSPPSDL) - endif() + set(TargetBin PPSSPPSDL) else() message(FATAL_ERROR "Could not find SDL. Failing.") endif() @@ -950,4 +958,9 @@ endif() file(INSTALL ${NativeAssets} DESTINATION assets) +# code signing +if (IOS) + set_target_properties(${NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST PPSSPP-Info.plist XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer: My Name") +endif() + #include(CPack) diff --git a/ios/AppDelegate.h b/ios/AppDelegate.h new file mode 100644 index 0000000000..263e85d369 --- /dev/null +++ b/ios/AppDelegate.h @@ -0,0 +1,13 @@ +// AppDelegate.h boilerplate + +#import + +@class ViewController; + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@property (strong, nonatomic) ViewController *viewController; + +@end diff --git a/ios/AppDelegate.m b/ios/AppDelegate.m new file mode 100644 index 0000000000..8601d4fee7 --- /dev/null +++ b/ios/AppDelegate.m @@ -0,0 +1,25 @@ +// AppDelegate.m boilerplate + +#import "AppDelegate.h" + +#import "ViewController.h" + +@implementation AppDelegate + +- (void)dealloc +{ + [_window release]; + [_viewController release]; + [super dealloc]; +} + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; + self.viewController = [[[ViewController alloc] init] autorelease]; + self.window.rootViewController = self.viewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end diff --git a/ios/PPSSPP-Info.plist b/ios/PPSSPP-Info.plist new file mode 100644 index 0000000000..5fe1a739c6 --- /dev/null +++ b/ios/PPSSPP-Info.plist @@ -0,0 +1,46 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.rock88dev.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/ios/PPSSPP-Prefix.pch b/ios/PPSSPP-Prefix.pch new file mode 100644 index 0000000000..6cc2cfc1a8 --- /dev/null +++ b/ios/PPSSPP-Prefix.pch @@ -0,0 +1,9 @@ +#import + +#ifndef __IPHONE_4_0 +#warning "This project uses features only available in iOS SDK 4.0 and later." +#endif + +#ifdef __OBJC__ + #import +#endif diff --git a/ios/ViewController.h b/ios/ViewController.h new file mode 100644 index 0000000000..b505050d44 --- /dev/null +++ b/ios/ViewController.h @@ -0,0 +1,8 @@ +// ViewController.h boilerplate + +#import +#import + +@interface ViewController : GLKViewController + +@end diff --git a/ios/ViewController.mm b/ios/ViewController.mm new file mode 100644 index 0000000000..576d3b68ca --- /dev/null +++ b/ios/ViewController.mm @@ -0,0 +1,241 @@ +// +// ViewController.m +// +// Created by rock88 +// Modified by xSacha +// + +#import "ViewController.h" +#import + +#include "base/display.h" +#include "base/timeutil.h" +#include "file/zip_read.h" +#include "input/input_state.h" +#include "net/resolve.h" +#include "ui_atlas.h" +#include "ui/screen.h" + +#include "Config.h" +#include "gfx_es2/fbo.h" + +#define IS_IPAD() ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) + +extern void UIUpdateMouse(int i, float x, float y, bool down); + +float dp_xscale = 1.0f; +float dp_yscale = 1.0f; + +static uint32_t pad_buttons_async_set = 0; +static uint32_t pad_buttons_async_clear = 0; + +extern ScreenManager *screenManager; +InputState input_state; + +extern std::string ram_temp_file; + +@interface ViewController () + +@property (strong, nonatomic) EAGLContext *context; +@property (nonatomic,retain) NSString* documentsPath; +@property (nonatomic,retain) NSString* bundlePath; +@property (nonatomic,retain) NSMutableArray* touches; + +@end + +@implementation ViewController +@synthesize documentsPath,bundlePath,touches; + +- (id)init +{ + self = [super init]; + if (self) { + self.touches = [[[NSMutableArray alloc] init] autorelease]; + + self.documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + self.bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/"]; + + memset(&input_state, 0, sizeof(input_state)); + + net::Init(); + + ram_temp_file = [[NSTemporaryDirectory() stringByAppendingPathComponent:@"ram_tmp.file"] fileSystemRepresentation]; + NativeInit(0, NULL, [self.bundlePath UTF8String], [self.documentsPath UTF8String], NULL); + + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.view.frame = [[UIScreen mainScreen] bounds]; + self.view.multipleTouchEnabled = YES; + self.context = [[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2] autorelease]; + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + [EAGLContext setCurrentContext:self.context]; + + float scale = [UIScreen mainScreen].scale; + CGSize size = [[UIApplication sharedApplication].delegate window].frame.size; + + if (size.height > size.width) { + float h = size.height; + size.height = size.width; + size.width = h; + } + + g_dpi = (IS_IPAD() ? 200 : 150) * scale; + g_dpi_scale = 240.0f / (float)g_dpi; + pixel_xres = size.width * scale; + pixel_yres = size.height * scale; + pixel_in_dps = (float)pixel_xres / (float)dp_xres; + + dp_xres = pixel_xres * g_dpi_scale; + dp_yres = pixel_yres * g_dpi_scale; + + NativeInitGraphics(); + + dp_xscale = (float)dp_xres / (float)pixel_xres; + dp_yscale = (float)dp_yres / (float)pixel_yres; + +/* + UISwipeGestureRecognizer* gesture = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)] autorelease]; + [self.view addGestureRecognizer:gesture]; +*/ +} + +- (void)viewDidUnload +{ + [super viewDidUnload]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; +} + +- (void)dealloc +{ + [self viewDidUnload]; + + self.touches = nil; + self.documentsPath = nil; + self.bundlePath = nil; + + NativeShutdown(); + [super dealloc]; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation +{ + return YES; +} + +//static BOOL menuDown = NO; + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + lock_guard guard(input_state.lock); + input_state.pad_buttons |= pad_buttons_async_set; + input_state.pad_buttons &= ~pad_buttons_async_clear; + UpdateInputState(&input_state); + + { + lock_guard guard(input_state.lock); + UIUpdateMouse(0, input_state.pointer_x[0], input_state.pointer_y[0], input_state.pointer_down[0]); + screenManager->update(input_state); + } + + { + lock_guard guard(input_state.lock); + EndInputState(&input_state); + } + + NativeRender(); + time_update(); +} + +- (void)swipeGesture:(id)sender +{ + // TODO: Use a swipe gesture to handle BACK +/* + pad_buttons_async_set |= PAD_BUTTON_MENU; + pad_buttons_async_clear &= PAD_BUTTON_MENU; + + int64_t delayInSeconds = 1.5; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + pad_buttons_async_set &= PAD_BUTTON_MENU; + pad_buttons_async_clear |= PAD_BUTTON_MENU; + }); + + if (g_Config.bBufferedRendering) + fbo_unbind(); + + screenManager->push(new InGameMenuScreen()); +*/ +} + +- (void)touchX:(float)x y:(float)y code:(int)code pointerId:(int)pointerId +{ + lock_guard guard(input_state.lock); + + float scale = [UIScreen mainScreen].scale; + + float scaledX = (int)(x * dp_xscale) * scale; + float scaledY = (int)(y * dp_yscale) * scale; + + input_state.pointer_x[pointerId] = scaledX; + input_state.pointer_y[pointerId] = scaledY; + if (code == 1) { + input_state.pointer_down[pointerId] = true; + } else if (code == 2) { + input_state.pointer_down[pointerId] = false; + } + input_state.mouse_valid = true; +} + +- (void)touchesBegan:(NSSet *)_touches withEvent:(UIEvent *)event +{ + for(UITouch* touch in _touches) { + [self.touches addObject:touch]; + CGPoint point = [touch locationInView:self.view]; + [self touchX:point.x y:point.y code:1 pointerId:[self.touches indexOfObject:touch]]; + } +} + +- (void)touchesMoved:(NSSet *)_touches withEvent:(UIEvent *)event +{ + for(UITouch* touch in _touches) { + CGPoint point = [touch locationInView:self.view]; + [self touchX:point.x y:point.y code:0 pointerId:[self.touches indexOfObject:touch]]; + } +} + +- (void)touchesEnded:(NSSet *)_touches withEvent:(UIEvent *)event +{ + for(UITouch* touch in _touches) { + CGPoint point = [touch locationInView:self.view]; + [self touchX:point.x y:point.y code:2 pointerId:[self.touches indexOfObject:touch]]; + [self.touches removeObject:touch]; + } +} + +void LaunchBrowser(char const* url) +{ + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithCString:url encoding:NSStringEncodingConversionAllowLossy]]]; +} + +void EnableFZ(){}; +void DisableFZ(){}; + +@end diff --git a/ios/ios.toolchain.cmake b/ios/ios.toolchain.cmake index 469e83acf1..eeb0fd3deb 100644 --- a/ios/ios.toolchain.cmake +++ b/ios/ios.toolchain.cmake @@ -141,7 +141,7 @@ set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS su # set the architecture for iOS # NOTE: Currently both ARCHS_STANDARD_32_BIT and ARCHS_UNIVERSAL_IPHONE_OS set armv7 only, so set both manually if (${IOS_PLATFORM} STREQUAL "OS") - set (IOS_ARCH armv6 armv7) + set (IOS_ARCH armv7) else (${IOS_PLATFORM} STREQUAL "OS") set (IOS_ARCH i386) endif (${IOS_PLATFORM} STREQUAL "OS") diff --git a/ios/main.m b/ios/main.m new file mode 100644 index 0000000000..2c76d754c1 --- /dev/null +++ b/ios/main.m @@ -0,0 +1,12 @@ +// main.m boilerplate + +#import + +#import "AppDelegate.h" + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} From 8c80641b288852f6a89bcc156dc86e2ebefdafdd Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 18 Feb 2013 00:41:51 +1000 Subject: [PATCH 32/69] iOS redundancies iOS simulator does not support requires GLES2.0 environment. Remove all references to simulator. Add support for armv7s (swift) arch. --- CMakeLists.txt | 4 +--- ios/ios.toolchain.cmake | 18 +++++------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0c7004b83..0a1402a5d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,9 +9,7 @@ if(ANDROID) endif() if (IOS) - if (${IOS_PLATFORM} STREQUAL "OS") - set(ARM ON) - endif() + set(ARM ON) endif() if(BLACKBERRY) diff --git a/ios/ios.toolchain.cmake b/ios/ios.toolchain.cmake index eeb0fd3deb..9af6cb06e6 100644 --- a/ios/ios.toolchain.cmake +++ b/ios/ios.toolchain.cmake @@ -4,10 +4,9 @@ # Options: # -# IOS_PLATFORM = OS (default) or SIMULATOR -# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders +# IOS_PLATFORM = OS (default) +# This needs to be OS as the simulator cannot use the required GLES2.0 environment. # OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch. -# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch. # # CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder # By default this location is automatcially chosen based on the IOS_PLATFORM value above. @@ -96,16 +95,11 @@ set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform") # Check the platform selection and setup for developer root if (${IOS_PLATFORM} STREQUAL "OS") set (IOS_PLATFORM_LOCATION "iPhoneOS.platform") - - # This causes the installers to properly locate the output libraries set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") - set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") - - # This causes the installers to properly locate the output libraries - set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") + message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. PPSSPP is unable to run on simulator") else (${IOS_PLATFORM} STREQUAL "OS") - message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR") + message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or leave default") endif (${IOS_PLATFORM} STREQUAL "OS") # Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT @@ -141,9 +135,7 @@ set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS su # set the architecture for iOS # NOTE: Currently both ARCHS_STANDARD_32_BIT and ARCHS_UNIVERSAL_IPHONE_OS set armv7 only, so set both manually if (${IOS_PLATFORM} STREQUAL "OS") - set (IOS_ARCH armv7) -else (${IOS_PLATFORM} STREQUAL "OS") - set (IOS_ARCH i386) + set (IOS_ARCH armv7 armv7s) endif (${IOS_PLATFORM} STREQUAL "OS") set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS") From 8425a123e2ac5924ce655542c4613380f1ebfd9a Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 18 Feb 2013 03:39:31 +0800 Subject: [PATCH 33/69] Browse and Boot --- Core/Config.cpp | 2 ++ Core/Config.h | 1 + Windows/main.cpp | 5 +++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index ae887f2cba..fc5019750c 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -49,6 +49,7 @@ void CConfig::Load(const char *iniFileName) general->Get("FirstRun", &bFirstRun, true); general->Get("AutoLoadLast", &bAutoLoadLast, false); general->Get("AutoRun", &bAutoRun, true); + general->Get("Browse", &bBrowse, false); general->Get("ConfirmOnQuit", &bConfirmOnQuit, false); general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true); general->Get("CurrentDirectory", ¤tDirectory, ""); @@ -112,6 +113,7 @@ void CConfig::Save() general->Set("FirstRun", bFirstRun); general->Set("AutoLoadLast", bAutoLoadLast); general->Set("AutoRun", bAutoRun); + general->Set("Browse", bBrowse); general->Set("ConfirmOnQuit", bConfirmOnQuit); general->Set("IgnoreBadMemAccess", bIgnoreBadMemAccess); general->Set("CurrentDirectory", currentDirectory); diff --git a/Core/Config.h b/Core/Config.h index de54372064..93554eeeb4 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -44,6 +44,7 @@ public: bool bSpeedLimit; bool bConfirmOnQuit; bool bAutoRun; // start immediately + bool bBrowse; // Core bool bIgnoreBadMemAccess; diff --git a/Windows/main.cpp b/Windows/main.cpp index f729c9abb8..b40541814f 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -159,8 +159,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin EmuThread_Start(fileToStart); } - // else - // MainWindow::BrowseAndBoot(); + if (g_Config.bBrowse) + MainWindow::BrowseAndBoot(); + if (!hideLog) SetForegroundWindow(hwndMain); From 6339c2fc9a2f909a291a2f44ffe61ef5a0f8a995 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sun, 17 Feb 2013 13:10:40 +0100 Subject: [PATCH 34/69] Correct crash when texture too small loaded in memory tex viewer Correct current thread PC in the list. --- Core/HLE/sceKernelThread.cpp | 5 ++++- Qt/debugger_memorytex.cpp | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index ea1f8730ef..52aa4981c5 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2805,7 +2805,10 @@ std::vector GetThreadsInfo() info.name[KERNELOBJECT_MAX_NAME_LENGTH+1] = 0; info.status = t->nt.status; info.entrypoint = t->nt.entrypoint; - info.curPC = t->context.pc; + if(*iter == currentThread) + info.curPC = currentMIPS->pc; + else + info.curPC = t->context.pc; info.isCurrent = (*iter == currentThread); threadList.push_back(info); } diff --git a/Qt/debugger_memorytex.cpp b/Qt/debugger_memorytex.cpp index bc9ea6272d..cdbf4ae640 100644 --- a/Qt/debugger_memorytex.cpp +++ b/Qt/debugger_memorytex.cpp @@ -70,8 +70,10 @@ void Debugger_MemoryTex::on_readBtn_clicked() state.clutaddr = ui->clutaddr->text().toInt(0,16); state.clutaddrupper = ui->clutaddrupper->text().toInt(0,16); state.loadclut = ui->loadclut->text().toInt(0,16); + int bufW = state.texbufwidth[0] & 0x3ff; int w = 1 << (state.texsize[0] & 0xf); int h = 1 << ((state.texsize[0]>>8) & 0xf); + w = std::max(bufW,w); uchar* newData = new uchar[w*h*4]; if(gpu->DecodeTexture(newData, state)) From 0fefca672d325fe15662cedd99ab1f2aff4fcde4 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sun, 17 Feb 2013 18:25:43 +0100 Subject: [PATCH 35/69] Add 2 step mode for display list : Go to selected line and go to next draw using selected texture --- Core/Host.h | 4 ++-- GPU/GPUCommon.cpp | 2 +- Qt/QtHost.cpp | 24 ++++++++++++++++--- Qt/QtHost.h | 5 ++-- Qt/debugger_displaylist.cpp | 47 +++++++++++++++++++++++++++++++++++++ Qt/debugger_displaylist.h | 8 +++++++ Qt/debugger_displaylist.ui | 6 +++++ 7 files changed, 88 insertions(+), 8 deletions(-) diff --git a/Core/Host.h b/Core/Host.h index 65d1782489..c60d270a66 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -65,8 +65,8 @@ public: virtual bool GpuStep() { return false; } virtual void SendGPUStart() {} - virtual void SendGPUWait(u32 cmd) {} - virtual void SetGPUStep(bool value, int flag = 0) {} + virtual void SendGPUWait(u32 cmd, u32 addr, void* data) {} + virtual void SetGPUStep(bool value, int flag = 0, int data = 0) {} virtual void NextGPUStep() {} // Used for headless. diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index ff050581ed..8d710972ff 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -98,7 +98,7 @@ bool GPUCommon::InterpretList(DisplayList &list) #if defined(USING_QT_UI) if(host->GpuStep()) { - host->SendGPUWait(cmd); + host->SendGPUWait(cmd, list.pc, &gstate); } #endif u32 diff = op ^ gstate.cmdmem[cmd]; diff --git a/Qt/QtHost.cpp b/Qt/QtHost.cpp index ca55e43879..4295edf126 100644 --- a/Qt/QtHost.cpp +++ b/Qt/QtHost.cpp @@ -28,6 +28,7 @@ recursive_mutex m_hGPUStepMutex; QtHost::QtHost(MainWindow *mainWindow_) : mainWindow(mainWindow_) , m_GPUStep(false) + , m_GPUFlag(0) { QObject::connect(this,SIGNAL(BootDoneSignal()),mainWindow,SLOT(Boot())); } @@ -162,7 +163,7 @@ void QtHost::SendGPUStart() EmuThread_LockDraw(true); } -void QtHost::SendGPUWait(u32 cmd) +void QtHost::SendGPUWait(u32 cmd, u32 addr, void *data) { EmuThread_LockDraw(false); @@ -173,19 +174,36 @@ void QtHost::SendGPUWait(u32 cmd) } else if(m_GPUFlag == 0) { - mainWindow->GetDialogDisasm()->UpdateDisplayList(); mainWindow->GetDialogDisplaylist()->Update(); m_hGPUStepEvent.wait(m_hGPUStepMutex); } + else if(m_GPUFlag == 2 && addr == m_GPUData) + { + mainWindow->GetDialogDisasm()->UpdateDisplayList(); + mainWindow->GetDialogDisplaylist()->Update(); + m_hGPUStepEvent.wait(m_hGPUStepMutex); + } + else if(m_GPUFlag == 3 && (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE)) + { + GPUgstate *state = (GPUgstate*)data; + u32 texAddr = (state->texaddr[0] & 0xFFFFF0) | ((state->texbufwidth[0]<<8) & 0x0F000000); + if(texAddr == m_GPUData) + { + mainWindow->GetDialogDisasm()->UpdateDisplayList(); + mainWindow->GetDialogDisplaylist()->Update(); + m_hGPUStepEvent.wait(m_hGPUStepMutex); + } + } EmuThread_LockDraw(true); } -void QtHost::SetGPUStep(bool value, int flag) +void QtHost::SetGPUStep(bool value, int flag, int data) { m_GPUStep = value; m_GPUFlag = flag; + m_GPUData = data; } void QtHost::NextGPUStep() diff --git a/Qt/QtHost.h b/Qt/QtHost.h index 8f578c9fd5..3e9305694d 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -51,9 +51,9 @@ public: void SendCoreWait(bool); bool GpuStep(); - void SendGPUWait(u32 cmd); + void SendGPUWait(u32 cmd, u32 addr, void* data); void SendGPUStart(); - void SetGPUStep(bool value, int flag = 0); + void SetGPUStep(bool value, int flag = 0, int data = 0); void NextGPUStep(); signals: @@ -62,6 +62,7 @@ private: MainWindow* mainWindow; bool m_GPUStep; int m_GPUFlag; + int m_GPUData; }; #endif // QTAPP_H diff --git a/Qt/debugger_displaylist.cpp b/Qt/debugger_displaylist.cpp index 0f557354ca..0d7dff132b 100644 --- a/Qt/debugger_displaylist.cpp +++ b/Qt/debugger_displaylist.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "Core/CPU.h" #include "ui_debugger_displaylist.h" @@ -1518,3 +1519,49 @@ void Debugger_DisplayList::on_indexList_itemClicked(QTreeWidgetItem *item, int c { UpdateIndexInfo(); } + +void Debugger_DisplayList::on_displayListData_customContextMenuRequested(const QPoint &pos) +{ + QTreeWidgetItem* item = ui->displayListData->itemAt(pos); + if(!item) + return; + displayListDataSelected = item; + + QMenu menu(this); + + QAction *runToHere = new QAction(tr("Run to here"), this); + connect(runToHere, SIGNAL(triggered()), this, SLOT(RunToDLPC())); + menu.addAction(runToHere); + + menu.exec( ui->displayListData->mapToGlobal(pos)); +} + +void Debugger_DisplayList::RunToDLPC() +{ + u32 addr = displayListDataSelected->text(0).toInt(0,16); + host->SetGPUStep(true, 2, addr); + host->NextGPUStep(); +} + +void Debugger_DisplayList::on_texturesList_customContextMenuRequested(const QPoint &pos) +{ + QTreeWidgetItem* item = ui->texturesList->itemAt(pos); + if(!item) + return; + textureDataSelected = item; + + QMenu menu(this); + + QAction *runToDraw = new QAction(tr("Run to draw using this texture"), this); + connect(runToDraw, SIGNAL(triggered()), this, SLOT(RunToDrawTex())); + menu.addAction(runToDraw); + + menu.exec( ui->texturesList->mapToGlobal(pos)); +} + +void Debugger_DisplayList::RunToDrawTex() +{ + u32 addr = textureDataSelected->text(0).toInt(0,16); + host->SetGPUStep(true, 3, addr); + host->NextGPUStep(); +} diff --git a/Qt/debugger_displaylist.h b/Qt/debugger_displaylist.h index e237a84f31..a4ae4a0648 100644 --- a/Qt/debugger_displaylist.h +++ b/Qt/debugger_displaylist.h @@ -93,6 +93,12 @@ private slots: void on_indexList_itemClicked(QTreeWidgetItem *item, int column); + void on_displayListData_customContextMenuRequested(const QPoint &pos); + + void on_texturesList_customContextMenuRequested(const QPoint &pos); + void RunToDLPC(); + void RunToDrawTex(); + private: QString DisassembleOp(u32 pc, u32 op, u32 prev, const GPUgstate &state); @@ -100,6 +106,8 @@ private: DebugInterface* cpu; MainWindow* mainWindow; QTreeWidgetItem* displayListRowSelected; + QTreeWidgetItem* displayListDataSelected; + QTreeWidgetItem* textureDataSelected; int currentRenderFrameDisplay; FBO* currentTextureDisplay; float fboZoomFactor; diff --git a/Qt/debugger_displaylist.ui b/Qt/debugger_displaylist.ui index 77a3ee5415..894a479ad2 100644 --- a/Qt/debugger_displaylist.ui +++ b/Qt/debugger_displaylist.ui @@ -118,6 +118,9 @@ + + Qt::CustomContextMenu + false @@ -192,6 +195,9 @@ + + Qt::CustomContextMenu + Address From 9e0bc2ae893e695c2c825c4b52af54cbee51c1bc Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sun, 17 Feb 2013 20:08:40 +0100 Subject: [PATCH 36/69] Better info for the display list code --- Qt/debugger_displaylist.cpp | 380 +++++++++++++++++++++++++++++++----- 1 file changed, 328 insertions(+), 52 deletions(-) diff --git a/Qt/debugger_displaylist.cpp b/Qt/debugger_displaylist.cpp index 0d7dff132b..0d9771ac7c 100644 --- a/Qt/debugger_displaylist.cpp +++ b/Qt/debugger_displaylist.cpp @@ -372,7 +372,7 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg { int bz_ucount = data & 0xFF; int bz_vcount = (data >> 8) & 0xFF; - return QString("DRAW BEZIER: %1 x %2").arg(bz_ucount).arg(bz_vcount); + return QString("DRAW BEZIER: U=%1 x V=%2").arg(bz_ucount).arg(bz_vcount); } break; @@ -380,9 +380,15 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg { int sp_ucount = data & 0xFF; int sp_vcount = (data >> 8) & 0xFF; + static const char* type[4] = { + "Close/Close", + "Open/Close", + "Close/Open", + "Open/Open" + }; int sp_utype = (data >> 16) & 0x3; int sp_vtype = (data >> 18) & 0x3; - return QString("DRAW SPLINE: %1 x %2, %3 x %4").arg(sp_ucount).arg(sp_vcount).arg(sp_utype).arg(sp_vtype); + return QString("DRAW SPLINE: U=%1 x V=%2, U Type = %3 , V Type = %4").arg(sp_ucount).arg(sp_vcount).arg(type[sp_utype]).arg(type[sp_vtype]); } break; @@ -459,13 +465,15 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_BJUMP: + { // bounding box jump. Let's just not jump, for now. - return QString("BBOX JUMP - unimplemented"); + u32 target = (((state.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF; + return QString("BBOX JUMP - %1 to %2").arg(pc,8,16,QChar('0')).arg(target,8,16,QChar('0')); break; - + } case GE_CMD_BOUNDINGBOX: // bounding box test. Let's do nothing. - return QString("BBOX TEST - unimplemented"); + return QString("BBOX TEST - number : %1").arg(data & 0xFFFF,4,16,QChar('0')); break; case GE_CMD_ORIGIN: @@ -473,9 +481,57 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_VERTEXTYPE: - return QString("SetVertexType: %1").arg(data,6,16,QChar('0')); - break; + { + const char* format[4] = + { + "No", + "8 Bits fixed", + "16 Bits fixed", + "Float" + }; + const char* colFormat[8] = + { + "No", + "", + "", + "", + "16-bit BGR-5650", + "16-bit ABGR-5551", + "16-bit ABGR-4444", + "32-bit ABGR-8888" + }; + QString retString = "SetVertexType:"; + u32 transform = data & GE_VTYPE_THROUGH_MASK; + retString += QString(" Transform : %1").arg(transform==0?"Transformed":"Raw"); + + u32 numVertMorph = (data & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT; + retString += QString(", Num Vtx Morph : %1").arg(numVertMorph); + + u32 numWeight = (data & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT; + retString += QString(", Num Weights : %1").arg(numWeight); + + u32 indexFmt = (data & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT; + retString += QString(", Index Format : %1").arg(format[indexFmt]); + + u32 weightFmt = (data & GE_VTYPE_WEIGHT_MASK) >> GE_VTYPE_WEIGHT_SHIFT; + retString += QString(", Weight Format : %1").arg(format[weightFmt]); + + u32 posFmt = (data & GE_VTYPE_POS_MASK) >> GE_VTYPE_POS_SHIFT; + retString += QString(", Position Format : %1").arg(format[posFmt]); + + u32 nrmFmt = (data & GE_VTYPE_NRM_MASK) >> GE_VTYPE_NRM_SHIFT; + retString += QString(", Normal Format : %1").arg(format[nrmFmt]); + + u32 colFmt = (data & GE_VTYPE_COL_MASK) >> GE_VTYPE_COL_SHIFT; + retString += QString(", Color Format : %1").arg(colFormat[colFmt]); + + u32 tcFmt = (data & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT; + retString += QString(", Texture UV Format : %1").arg(format[tcFmt]); + + return retString; + break; + } case GE_CMD_OFFSETADDR: return QString("OffsetAddr: %1").arg(data,6,16,QChar('0')); break; @@ -588,9 +644,17 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_FRAMEBUFPIXFORMAT: - return QString("FramebufPixeFormat: %1").arg(data); + { + const char* fmt[4] = + { + "16-bit BGR 5650", + "16-bit ABGR 5551", + "16-bit ABGR 4444", + "32-bit ABGR 8888" + }; + return QString("FramebufPixeFormat: %1").arg(fmt[data]); break; - + } case GE_CMD_TEXADDR0: case GE_CMD_TEXADDR1: case GE_CMD_TEXADDR2: @@ -610,7 +674,7 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg case GE_CMD_TEXBUFWIDTH5: case GE_CMD_TEXBUFWIDTH6: case GE_CMD_TEXBUFWIDTH7: - return QString("Texture BUFWIDTHess %1: %2").arg(cmd-GE_CMD_TEXBUFWIDTH0).arg(data,6,16,QChar('0')); + return QString("Texture BUFWIDTHess %1: %2 width : %3").arg(cmd-GE_CMD_TEXBUFWIDTH0).arg(data,6,16,QChar('0')).arg(data & 0xFFFF); break; case GE_CMD_CLUTADDR: @@ -623,20 +687,41 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg case GE_CMD_LOADCLUT: // This could be used to "dirty" textures with clut. - return QString("Clut load"); + return QString("Clut load, numColor : %1").arg(data*8); break; case GE_CMD_TEXMAPMODE: - return QString("Tex map mode: %1").arg(data,6,16,QChar('0')); + { + const char* texMapMode[3] = + { + "Texture Coordinates (UV)", + "Texture Matrix", + "Environment Map" + }; + const char* texProjMode[4] = + { + "Position", + "Texture Coordinates", + "Normalized Normal", + "Normal" + }; + return QString("Tex map mode: Map mode : %1, Proj Mode : %2").arg(texMapMode[data & 0x3]).arg(texProjMode[(data >> 8) & 0x3]); break; - + } case GE_CMD_TEXSHADELS: return QString("Tex shade light sources: %1").arg(data,6,16,QChar('0')); break; case GE_CMD_CLUTFORMAT: { - return QString("Clut format: %1").arg(data,6,16,QChar('0')); + const char* fmt[4] = + { + "16-bit BGR 5650", + "16-bit ABGR 5551", + "16-bit ABGR 4444", + "32-bit ABGR 8888" + }; + return QString("Clut format: %1 , Fmt : %2").arg(data,6,16,QChar('0')).arg(fmt[data & 0x3]); } break; @@ -696,7 +781,7 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK { - return QString("Block Transfer Start"); + return QString("Block Transfer Start : %1").arg(data ? "32-bit texel size" : "16-bit texel size"); break; } @@ -772,9 +857,22 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg case GE_CMD_LIGHTTYPE1: case GE_CMD_LIGHTTYPE2: case GE_CMD_LIGHTTYPE3: - return QString("Light %1 type: %2").arg(cmd-GE_CMD_LIGHTTYPE0).arg(data,6,16,QChar('0')); + { + const char* lightType[3] = + { + "Directional Light", + "Point Light", + "Spot Light" + }; + const char* lightComp[3] = + { + "Ambient & Diffuse", + "Diffuse & Specular", + "Unknown (diffuse color, affected by specular power)" + }; + return QString("Light %1 type: %2 %3").arg(cmd-GE_CMD_LIGHTTYPE0).arg(lightType[(data) >> 8 & 0x3]).arg(lightComp[data & 0x3]); break; - + } case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0: case GE_CMD_LX1:case GE_CMD_LY1:case GE_CMD_LZ1: case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2: @@ -855,42 +953,78 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_CULL: - return QString("cull: %1").arg(data,6,16,QChar('0')); + { + const char* cull[2] = + { + "Clockwise visible", + "Counter-clockwise visible" + }; + return QString("cull: %1").arg(cull[data & 0x1]); break; - + } case GE_CMD_PATCHDIVISION: { int patch_div_s = data & 0xFF; int patch_div_t = (data >> 8) & 0xFF; - return QString("Patch subdivision: %1 x %2").arg(patch_div_s).arg(patch_div_t); + return QString("Patch subdivision: S=%1 x T=%2").arg(patch_div_s).arg(patch_div_t); } break; case GE_CMD_PATCHPRIMITIVE: - return QString("Patch Primitive: %1").arg(data); + { + const char* type[3] = + { + "Triangles", + "Lines", + "Points" + }; + return QString("Patch Primitive: %1").arg(type[data]); break; - + } case GE_CMD_PATCHFACING: - return QString( "Patch Facing: %1").arg(data); + { + const char* val[2] = + { + "Clockwise", + "Counter-Clockwise" + }; + return QString( "Patch Facing: %1").arg(val[data]); break; - + } case GE_CMD_REVERSENORMAL: return QString("Reverse normal: %1").arg(data); break; case GE_CMD_MATERIALUPDATE: - return QString("Material Update: %1").arg(data); + { + QString txt = ""; + if(data & 1) txt += " Ambient"; + if(data & 2) txt += " Diffuse"; + if(data & 4) txt += " Specular"; + return QString("Material Update: %1").arg(txt); break; - + } ////////////////////////////////////////////////////////////////// // CLEARING ////////////////////////////////////////////////////////////////// case GE_CMD_CLEARMODE: + { // If it becomes a performance problem, check diff&1 - return QString("Clear mode: %1").arg(data,6,16,QChar('0')); + const char* clearMode[8] = + { + "", + "Clear Color Buffer", + "Clear Stencil/Alpha Buffer", + "", + "Clear Depth Buffer", + "", + "", + "" + }; + return QString("Clear mode: %1, enabled : %2").arg(clearMode[(data >> 8) & 0xF]).arg(data & 0x1); break; - + } ////////////////////////////////////////////////////////////////// // ALPHA BLENDING @@ -900,9 +1034,31 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_BLENDMODE: - return QString("Blend mode: %1").arg(data,6,16,QChar('0')); + { + const char* func[9] = + { + "Source Color", + "One Minus Source Color", + "Source Alpha", + "One Minus Source Alpha", + "Destination Color", + "One Minus Destination Color", + "Destination Alpha", + "One Minus Destination Alpha", + "Fix" + }; + const char* op[6] = + { + "Add", + "Subtract", + "Reverse Subtract", + "Minimum Value", + "Maximum Value", + "Absolute Value" + }; + return QString("Blend mode: Src : %1, Dest : %2, Op : %3").arg(func[(data >> 4) & 0xF]).arg(func[(data >> 8) & 0xF]).arg(op[(data) & 0x7]); break; - + } case GE_CMD_BLENDFIXEDA: return QString("Blend fix A: %1").arg(data,6,16,QChar('0')); break; @@ -916,9 +1072,21 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_ALPHATEST: - return QString("Alpha test settings"); + { + const char* testFunc[8] = + { + "Never pass pixel", + "Always pass pixel", + "Pass pixel if match", + "Pass pixel if difference", + "Pass pixel if less", + "Pass pixel if less or equal", + "Pass pixel if greater", + "Pass pixel if greater or equal" + }; + return QString("Alpha test settings, Mask : %1, Ref : %2, Test : %3").arg((data >> 8) & 0xFF).arg((data >> 16) & 0xFF).arg(testFunc[data & 0x7]); break; - + } case GE_CMD_ANTIALIASENABLE: return QString("Antialias enable: %1").arg(data); break; @@ -928,22 +1096,71 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_COLORTESTENABLE: - return QString("Color Test enable: %1").arg(data); + { + const char* colorTest[4] = + { + "Never pass pixel", + "Always pass pixel", + "Pass pixel if color matches", + "Pass pixel if color differs" + }; + return QString("Color Test enable: %1").arg(colorTest[data]); break; - + } case GE_CMD_LOGICOPENABLE: - return QString("Logic op enable: %1").arg(data); + { + const char* logicOp[16] = + { + "Clear", + "And", + "Reverse And", + "Copy", + "Inverted And", + "No Operation", + "Exclusive Or", + "Or", + "Negated Or", + "Equivalence", + "Inverted", + "Reverse Or", + "Inverted Copy", + "Inverted Or", + "Negated And", + "Set" + }; + return QString("Logic op enable: %1").arg(logicOp[data]); break; - + } case GE_CMD_TEXFUNC: - return QString("TexFunc %1").arg(data&7); + { + const char* effect[8] = + { + "Modulate", + "Decal", + "Blend", + "Replace", + "Add", + "","","" + }; + return QString("TexFunc %1 / %2 / %3").arg((data&0x100)?"Texture alpha is read":"Texture alpha is ignored").arg((data & 0x10000)?"Fragment color is doubled":"Fragment color is untouched").arg(effect[data & 0x7]); break; - + } case GE_CMD_TEXFILTER: { - int min = data & 7; - int mag = (data >> 8) & 1; - return QString("TexFilter min: %1 mag: %2").arg( min).arg(mag); + const char* filter[8]= + { + "Nearest", + "Linear", + "", + "", + "Nearest; Mipmap Nearest", + "Linear; Mipmap Nearest", + "Nearest; Mipmap Linear", + "Linear; Mipmap Linear" + }; + int min = data & 0x7; + int mag = (data >> 8) & 0x7; + return QString("TexFilter min: %1 mag: %2").arg(filter[min]).arg(filter[mag]); } break; @@ -952,13 +1169,30 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_TEXMODE: - return QString("TexMode %1").arg(data,8,16,QChar('0')); + { + u32 maxMipMap = (data >> 16) & 0xF; + return QString("TexMode MaxmipMap : %1, Swizzle : %2").arg(maxMipMap).arg(data & 0x1); break; - + } case GE_CMD_TEXFORMAT: - return QString("TexFormat %1").arg(data,8,16,QChar('0')); + { + const char* texFmt[11] = + { + "16-bit BGR 5650", + "16-bit ABGR 5551", + "16-bit ABGR 4444", + "32-bit ABGR 8888", + "4-bit indexed", + "8-bit indexed", + "16-bit indexed", + "32-bit indexed", + "DXT1", + "DXT3", + "DXT5" + }; + return QString("TexFormat %1").arg(texFmt[data]); break; - + } case GE_CMD_TEXFLUSH: return QString("TexFlush"); break; @@ -968,9 +1202,15 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_TEXWRAP: - return QString("TexWrap %1").arg(data,8,16,QChar('0')); + { + const char* wrapMode[2] = + { + "Repeat", + "Clamp" + }; + return QString("TexWrap U : %1, V : %2").arg(wrapMode[data & 0x1]).arg(wrapMode[(data >> 8) & 0x1]); break; - + } case GE_CMD_TEXLEVEL: return QString("TexWrap Mode: %1 Offset: %2").arg(data&3).arg(data >> 16); break; @@ -1000,21 +1240,57 @@ QString Debugger_DisplayList::DisassembleOp(u32 pc, u32 op, u32 prev, const GPUg break; case GE_CMD_STENCILOP: - return QString("Stencil op: %1").arg(data,6,16,QChar('0')); + { + const char* stencilOp[8] = + { + "Keep stencil value", + "Zero stencil value", + "Replace stencil value", + "Invert stencil value", + "Increment stencil value", + "Decrement stencil value", + "","" + }; + return QString("Stencil op: ZFail : %1, Fail : %2, Pass : %3").arg(stencilOp[(data >> 16) & 0x7]).arg(stencilOp[(data >> 8) & 0x7]).arg(stencilOp[(data) & 0x7]); break; - + } case GE_CMD_STENCILTEST: - return QString("Stencil test: %1").arg(data,6,16,QChar('0')); + { + const char* testFunc[8] = + { + "Never pass stencil pixel", + "Always pass stencil pixel", + "Pass test if match", + "Pass test if difference", + "Pass test if less", + "Pass test if less or equal", + "Pass test if greater", + "Pass test if greater or equal" + }; + return QString("Stencil test, Mask : %1, Ref : %2, Test : %3").arg((data >> 8) & 0xFF).arg((data >> 16) & 0xFF).arg(testFunc[data & 0x7]); break; + } case GE_CMD_STENCILTESTENABLE: return QString("Stencil test enable: %1").arg(data); break; case GE_CMD_ZTEST: - return QString("Z test mode: %1").arg(data); + { + const char* testFunc[8] = + { + "Never pass stencil pixel", + "Always pass stencil pixel", + "Pass pixel if match", + "Pass pixel if difference", + "Pass pixel if less", + "Pass pixel if less or equal", + "Pass pixel if greater", + "Pass pixel if greater or equal" + }; + return QString("Z test mode: %1").arg(testFunc[data & 0x7]); break; - + } case GE_CMD_MORPHWEIGHT0: case GE_CMD_MORPHWEIGHT1: case GE_CMD_MORPHWEIGHT2: From ec8d32378aacf67e5545af7ef45423a3266a9aeb Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sun, 17 Feb 2013 21:42:54 +0100 Subject: [PATCH 37/69] Add possibility to modify memory values Optim time when parsing DList for debug. --- Qt/ctrlmemview.cpp | 28 ++++++++++++++++++++++++++++ Qt/ctrlmemview.h | 1 + Qt/debugger_displaylist.cpp | 15 ++++++++------- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Qt/ctrlmemview.cpp b/Qt/ctrlmemview.cpp index c7c6637436..0ebaa97775 100644 --- a/Qt/ctrlmemview.cpp +++ b/Qt/ctrlmemview.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "EmuThread.h" #include "Core/MemMap.h" @@ -221,6 +222,10 @@ void CtrlMemView::contextMenu(const QPoint &pos) connect(copyValue, SIGNAL(triggered()), this, SLOT(CopyValue())); menu.addAction(copyValue); + QAction *changeValue = new QAction(tr("C&hange value"), this); + connect(changeValue, SIGNAL(triggered()), this, SLOT(Change())); + menu.addAction(changeValue); + QAction *dump = new QAction(tr("Dump..."), this); connect(dump, SIGNAL(triggered()), this, SLOT(Dump())); menu.addAction(dump); @@ -230,7 +235,9 @@ void CtrlMemView::contextMenu(const QPoint &pos) void CtrlMemView::CopyValue() { + EmuThread_LockDraw(true); QApplication::clipboard()->setText(QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0'))); + EmuThread_LockDraw(false); } void CtrlMemView::Dump() @@ -238,6 +245,27 @@ void CtrlMemView::Dump() QMessageBox::information(this,"Sorry","This feature has not been implemented.",QMessageBox::Ok); } + +void CtrlMemView::Change() +{ + EmuThread_LockDraw(true); + QString curVal = QString("%1").arg(Memory::ReadUnchecked_U32(selection),8,16,QChar('0')); + EmuThread_LockDraw(false); + + bool ok; + QString text = QInputDialog::getText(this, tr("Set new value"), + tr("Set new value:"), QLineEdit::Normal, + curVal, &ok); + if (ok && !text.isEmpty()) + { + EmuThread_LockDraw(true); + Memory::WriteUnchecked_U32(text.toInt(0,16),selection); + EmuThread_LockDraw(false); + redraw(); + } +} + + int CtrlMemView::yToAddress(int y) { int ydiff=y-rect().bottom()/2-rowHeight/2; diff --git a/Qt/ctrlmemview.h b/Qt/ctrlmemview.h index 070b1af7f9..cc7f31c506 100644 --- a/Qt/ctrlmemview.h +++ b/Qt/ctrlmemview.h @@ -72,6 +72,7 @@ signals: public slots: void CopyValue(); void Dump(); + void Change(); private: int curAddress; int align; diff --git a/Qt/debugger_displaylist.cpp b/Qt/debugger_displaylist.cpp index 0d9771ac7c..c5103192f9 100644 --- a/Qt/debugger_displaylist.cpp +++ b/Qt/debugger_displaylist.cpp @@ -309,15 +309,16 @@ void Debugger_DisplayList::ShowDLCode() } usedIdxAddr.insert(iaddr); } - - for(int i = 0; i < ui->texturesList->columnCount(); i++) - ui->texturesList->resizeColumnToContents(i); - for(int i = 0; i < ui->vertexList->columnCount(); i++) - ui->vertexList->resizeColumnToContents(i); - for(int i = 0; i < ui->indexList->columnCount(); i++) - ui->indexList->resizeColumnToContents(i); } + + for(int i = 0; i < ui->texturesList->columnCount(); i++) + ui->texturesList->resizeColumnToContents(i); + for(int i = 0; i < ui->vertexList->columnCount(); i++) + ui->vertexList->resizeColumnToContents(i); + for(int i = 0; i < ui->indexList->columnCount(); i++) + ui->indexList->resizeColumnToContents(i); + UpdateVertexInfo(); UpdateIndexInfo(); } From 20597e4990edeaf6b812f8571a8f0361f8f52bb8 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sun, 17 Feb 2013 22:05:31 +0100 Subject: [PATCH 38/69] Sync native Put gui command in the gui thread. --- Qt/debugger_displaylist.cpp | 10 ++++++++-- Qt/debugger_displaylist.h | 2 ++ native | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Qt/debugger_displaylist.cpp b/Qt/debugger_displaylist.cpp index c5103192f9..5b688d7337 100644 --- a/Qt/debugger_displaylist.cpp +++ b/Qt/debugger_displaylist.cpp @@ -31,6 +31,7 @@ Debugger_DisplayList::Debugger_DisplayList(DebugInterface *_cpu, MainWindow* mai QObject::connect(this, SIGNAL(updateDisplayList_()), this, SLOT(UpdateDisplayListGUI())); QObject::connect(this, SIGNAL(updateRenderBufferList_()), this, SLOT(UpdateRenderBufferListGUI())); + QObject::connect(this, SIGNAL(updateRenderBuffer_()), this, SLOT(UpdateRenderBufferGUI())); } @@ -1498,6 +1499,11 @@ void Debugger_DisplayList::on_stopBtn_clicked() } void Debugger_DisplayList::UpdateRenderBuffer() +{ + emit updateRenderBuffer_(); +} + +void Debugger_DisplayList::UpdateRenderBufferGUI() { EmuThread_LockDraw(true); @@ -1580,7 +1586,7 @@ void Debugger_DisplayList::on_texturesList_itemDoubleClicked(QTreeWidgetItem *it void Debugger_DisplayList::on_comboBox_currentIndexChanged(int index) { currentRenderFrameDisplay = index; - UpdateRenderBuffer(); + UpdateRenderBufferGUI(); } void Debugger_DisplayList::UpdateRenderBufferList() @@ -1622,7 +1628,7 @@ void Debugger_DisplayList::on_fboList_itemClicked(QTreeWidgetItem *item, int col u64 addr = item->data(0,Qt::UserRole).toULongLong(); FBO* fbo = (FBO*)addr; currentTextureDisplay = fbo; - UpdateRenderBuffer(); + UpdateRenderBufferGUI(); } void Debugger_DisplayList::on_nextDLBtn_clicked() diff --git a/Qt/debugger_displaylist.h b/Qt/debugger_displaylist.h index a4ae4a0648..7ecec82302 100644 --- a/Qt/debugger_displaylist.h +++ b/Qt/debugger_displaylist.h @@ -54,10 +54,12 @@ protected: signals: void updateDisplayList_(); void updateRenderBufferList_(); + void updateRenderBuffer_(); private slots: void UpdateDisplayListGUI(); void UpdateRenderBufferListGUI(); + void UpdateRenderBufferGUI(); void releaseLock(); void on_displayList_itemClicked(QTreeWidgetItem *item, int column); diff --git a/native b/native index f5e7bd5a9c..f7db8ff0be 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit f5e7bd5a9c3e4b39a4eac71b577f06ad54f2bc96 +Subproject commit f7db8ff0bea971ed6c1332ce746101d3f0146010 From 7f9516fce491e0b93337c964496515b9a706320b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 15:10:30 -0800 Subject: [PATCH 39/69] Use SSE2 in debug and x64, not just x86. Apples to apples is nice. More accurate floats in debug is bad. --- Core/Core.vcxproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 265a9fd0f4..50c55c3a01 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -68,6 +68,8 @@ Disabled ../common;..;../native;../native/ext/glew;../ext/zlib WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + StreamingSIMDExtensions2 + Fast true @@ -79,6 +81,8 @@ Disabled ../common;..;../native;../native/ext/glew;../ext/zlib WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + StreamingSIMDExtensions2 + Fast true @@ -108,6 +112,8 @@ true true ../common;..;../native;../native/ext/glew;../ext/zlib + StreamingSIMDExtensions2 + Fast true From be631dea64295256bbb83147012f5180fa548d08 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 15:11:14 -0800 Subject: [PATCH 40/69] Disasm transposed vectors properly. --- Core/MIPS/MIPSVFPUUtils.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index fd94a6cf02..21ebfb844b 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -278,7 +278,10 @@ const char *GetVectorNotation(int reg, VectorSize size) case V_Quad: c='C'; row=(reg>>5)&2; break; } if (transpose && c == 'C') c='R'; - sprintf(hej[yo],"%c%i%i%i",c,mtx,col,row); + if (transpose) + sprintf(hej[yo],"%c%i%i%i",c,mtx,row,col); + else + sprintf(hej[yo],"%c%i%i%i",c,mtx,col,row); return hej[yo]; } From 6191017a2cdc8967125cd30938a974f08dab854f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 15:21:51 -0800 Subject: [PATCH 41/69] Fix jit VDot mapping vd incorrectly to a quad. --- Core/MIPS/x86/CompVFPU.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index b011c6ae52..d8d0a0af8b 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -331,10 +331,10 @@ void Jit::Comp_VDot(u32 op) { VectorSize sz = GetVecSize(op); // TODO: Force read one of them into regs? probably not. - u8 sregs[4], tregs[4], dregs[4]; + u8 sregs[4], tregs[4], dregs[1]; GetVectorRegs(sregs, sz, vs); GetVectorRegs(tregs, sz, vt); - GetVectorRegs(dregs, sz, vd); + GetVectorRegs(dregs, V_Single, vd); // TODO: applyprefixST here somehow (shuffle, etc...) @@ -347,7 +347,7 @@ void Jit::Comp_VDot(u32 op) { } // Need to start with +0.0f so it doesn't result in -0.0f. - MOVSS(tempxreg, M((void *) &zero)); + XORPS(tempxreg, R(tempxreg)); for (int i = 0; i < n; i++) { // sum += s[i]*t[i]; From b4fb06f51c80615ca1ff411c242048dd2546aabf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 15:24:18 -0800 Subject: [PATCH 42/69] Respect the writemask in VDot. Although it's basically a no-op in that case... --- Core/MIPS/MIPSIntVFPU.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 7aa182f6b5..f861340d8c 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -936,8 +936,7 @@ namespace MIPSInt } d = sum; ApplyPrefixD(&d,V_Single); - // TODO: Shouldn't this respect the mask? - V(vd) = d; + WriteVector(&d, V_Single, vd); PC += 4; EatPrefixes(); } From 6b223cf7d7ca19315a62a616daf0806e5b1eba60 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 15:40:26 -0800 Subject: [PATCH 43/69] Add a flag for eating prefixes to the MIPS tables. Still incomplete, just filled in ones I've tested so far. --- Core/MIPS/MIPSTables.cpp | 14 ++++++------ Core/MIPS/MIPSTables.h | 48 +++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 06e30466c3..bcd83c2270 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -478,19 +478,19 @@ const MIPSInstruction tableCop1BC[32] = const MIPSInstruction tableVFPU0[8] = { - INSTR("vadd",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU), - INSTR("vsub",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU), + INSTR("vadd",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vsub",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU|OUT_EAT_PREFIX), INSTR("vsbn",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsbn, IS_VFPU), {-2}, {-2}, {-2}, {-2}, - INSTR("vdiv",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU), + INSTR("vdiv",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU|OUT_EAT_PREFIX), }; const MIPSInstruction tableVFPU1[8] = { - INSTR("vmul",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU), - INSTR("vdot",&Jit::Comp_VDot, Dis_VectorDot, Int_VDot, IS_VFPU), - INSTR("vscl",&Jit::Comp_Generic, Dis_VScl, Int_VScl, IS_VFPU), + INSTR("vmul",&Jit::Comp_VecDo3, Dis_VectorSet3, Int_VecDo3, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vdot",&Jit::Comp_VDot, Dis_VectorDot, Int_VDot, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vscl",&Jit::Comp_Generic, Dis_VScl, Int_VScl, IS_VFPU|OUT_EAT_PREFIX), {-2}, INSTR("vhdp",&Jit::Comp_Generic, Dis_Generic, Int_VHdp, IS_VFPU), INSTR("vcrs",&Jit::Comp_Generic, Dis_Vcrs, Int_Vcrs, IS_VFPU), @@ -582,7 +582,7 @@ const MIPSInstruction tableVFPU7[32] = // 110100 00000 10111 0000000000000000 const MIPSInstruction tableVFPU4[32] = //110100 00000 xxxxx { - INSTR("vmov", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU), + INSTR("vmov", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), INSTR("vabs", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU), INSTR("vneg", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU), INSTR("vidt", &Jit::Comp_Generic, Dis_VectorSet1, Int_Vidt,IS_VFPU), diff --git a/Core/MIPS/MIPSTables.h b/Core/MIPS/MIPSTables.h index 2d71bc73d1..18ee23b42f 100644 --- a/Core/MIPS/MIPSTables.h +++ b/Core/MIPS/MIPSTables.h @@ -19,31 +19,33 @@ #include "../../Globals.h" -#define IS_CONDBRANCH 0x100 -#define IS_JUMP 0x200 -#define IS_VFPU 0x80000000 -#define LIKELY 0x80 -#define UNCONDITIONAL 0x40 -#define BAD_INSTRUCTION 0x20 -#define DELAYSLOT 0x10 +#define DELAYSLOT 0x00000010 +#define BAD_INSTRUCTION 0x00000020 +#define UNCONDITIONAL 0x00000040 +#define LIKELY 0x00000080 +#define IS_CONDBRANCH 0x00000100 +#define IS_JUMP 0x00000200 -#define IN_RS_ADDR 0x800 -#define IN_RS_SHIFT 0x400 -#define IN_RS 0x1000 -#define IN_RT 0x2000 -#define IN_SA 0x4000 -#define IN_IMM16 0x8000 -#define IN_IMM26 0x10000 -#define IN_MEM 0x20000 -#define IN_OTHER 0x40000 -#define IN_FPUFLAG 0x80000 +#define IN_RS_SHIFT 0x00000400 +#define IN_RS_ADDR 0x00000800 +#define IN_RS 0x00001000 +#define IN_RT 0x00002000 +#define IN_SA 0x00004000 +#define IN_IMM16 0x00008000 +#define IN_IMM26 0x00010000 +#define IN_MEM 0x00020000 +#define IN_OTHER 0x00040000 +#define IN_FPUFLAG 0x00080000 -#define OUT_RT 0x100000 -#define OUT_RD 0x200000 -#define OUT_RA 0x400000 -#define OUT_MEM 0x800000 -#define OUT_OTHER 0x1000000 -#define OUT_FPUFLAG 0x2000000 +#define OUT_RT 0x00100000 +#define OUT_RD 0x00200000 +#define OUT_RA 0x00400000 +#define OUT_MEM 0x00800000 +#define OUT_OTHER 0x01000000 +#define OUT_FPUFLAG 0x02000000 +#define OUT_EAT_PREFIX 0x04000000 + +#define IS_VFPU 0x80000000 #ifndef CDECL #define CDECL From f5329513318d3342be2811bb98bb5c400d428481 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 15:50:31 -0800 Subject: [PATCH 44/69] Automatically eat prefixes in x86 jit. Simplifies the code and makes it easier to know they're eaten even for ops not yet jitted. --- Core/MIPS/ARM/ArmJit.h | 3 +++ Core/MIPS/MIPSTables.cpp | 4 ++++ Core/MIPS/x86/CompVFPU.cpp | 12 +++++------- Core/MIPS/x86/Jit.cpp | 3 ++- Core/MIPS/x86/Jit.h | 1 + 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 730a6938ce..0dc0338e7d 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -119,6 +119,9 @@ public: void ClearCache(); void ClearCacheAt(u32 em_address); + // TODO: Eat VFPU prefixes here. + void EatPrefix() { } + private: void GenerateFixedCode(); void FlushAll(); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index bcd83c2270..34319e8bae 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -868,6 +868,7 @@ void MIPSCompileOp(u32 op) if (op==0) return; const MIPSInstruction *instr = MIPSGetInstruction(op); + const int info = MIPSGetInfo(op); if (instr) { if (instr->compile) @@ -877,6 +878,9 @@ void MIPSCompileOp(u32 op) ERROR_LOG(CPU,"MIPSCompileOp %08x failed",op); //MessageBox(0,"ARGH2",0,0);//compile an interpreter call } + + if (info & OUT_EAT_PREFIX) + MIPSComp::jit->EatPrefix(); } else { diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index d8d0a0af8b..9cb5bf3306 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -318,10 +318,14 @@ void Jit::Comp_SVQ(u32 op) void Jit::Comp_VDot(u32 op) { DISABLE; + // No-op. + if (js.writeMask[0]) { + return; + } + // WARNING: No prefix support! if (js.MayHavePrefix()) { Comp_Generic(op); - js.EatPrefix(); return; } @@ -365,8 +369,6 @@ void Jit::Comp_VDot(u32 op) { // TODO: applyprefixD here somehow (write mask etc..) fpr.ReleaseSpillLocks(); - - js.EatPrefix(); } void Jit::Comp_VecDo3(u32 op) { @@ -376,7 +378,6 @@ void Jit::Comp_VecDo3(u32 op) { if (js.MayHavePrefix()) { Comp_Generic(op); - js.EatPrefix(); return; } @@ -420,7 +421,6 @@ void Jit::Comp_VecDo3(u32 op) { if (xmmop == NULL) { Comp_Generic(op); - js.EatPrefix(); return; } @@ -463,8 +463,6 @@ void Jit::Comp_VecDo3(u32 op) { } fpr.ReleaseSpillLocks(); - - js.EatPrefix(); } void Jit::Comp_Mftv(u32 op) { diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 9fb2487713..7a817e5c8b 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -283,7 +283,8 @@ void Jit::Comp_Generic(u32 op) _dbg_assert_msg_(JIT, 0, "Trying to compile instruction that can't be interpreted"); // Might have eaten prefixes, hard to tell... - if ((MIPSGetInfo(op) & IS_VFPU) != 0) + const int info = MIPSGetInfo(op); + if ((info & IS_VFPU) != 0 && (info & OUT_EAT_PREFIX) == 0) js.PrefixStart(); } diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 2d5f9ef3c1..4b20de372d 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -173,6 +173,7 @@ public: void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz); void ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWriteMask = false); + void EatPrefix() { js.EatPrefix(); } JitBlockCache *GetBlockCache() { return &blocks; } AsmRoutineManager &Asm() { return asm_; } From 7fee4dfd13e45d3ff8b553c613a484f976c999e3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 15:51:07 -0800 Subject: [PATCH 45/69] Re-enable vdot and vadd/etc. in x86 jit. --- Core/MIPS/x86/CompVFPU.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 9cb5bf3306..ff16fb25fb 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -316,7 +316,7 @@ void Jit::Comp_SVQ(u32 op) } void Jit::Comp_VDot(u32 op) { - DISABLE; + CONDITIONAL_DISABLE; // No-op. if (js.writeMask[0]) { @@ -372,7 +372,7 @@ void Jit::Comp_VDot(u32 op) { } void Jit::Comp_VecDo3(u32 op) { - DISABLE; + CONDITIONAL_DISABLE; // WARNING: No prefix support! if (js.MayHavePrefix()) From 25c42c3532a2ef464a20f84fefcd8cf4b29e815d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 17:32:29 -0800 Subject: [PATCH 46/69] Mark more instructions that eat prefixes. --- Core/MIPS/MIPSTables.cpp | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 34319e8bae..d792c800eb 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -502,8 +502,8 @@ const MIPSInstruction tableVFPU3[8] = //011011 xxx { INSTR("vcmp",&Jit::Comp_Generic, Dis_Vcmp, Int_Vcmp, IS_VFPU), {-2}, - INSTR("vmin",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU), - INSTR("vmax",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU), + INSTR("vmin",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmax",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU|OUT_EAT_PREFIX), {-2}, INSTR("vscmp",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vscmp, IS_VFPU), INSTR("vsge",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsge, IS_VFPU), @@ -583,30 +583,30 @@ const MIPSInstruction tableVFPU7[32] = const MIPSInstruction tableVFPU4[32] = //110100 00000 xxxxx { INSTR("vmov", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), - INSTR("vabs", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU), - INSTR("vneg", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU), + INSTR("vabs", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), + INSTR("vneg", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), INSTR("vidt", &Jit::Comp_Generic, Dis_VectorSet1, Int_Vidt,IS_VFPU), - INSTR("vsat0", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), - INSTR("vsat1", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), + INSTR("vsat0", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vsat1", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), INSTR("vzero", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU), INSTR("vone", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU), //8 {-2},{-2},{-2},{-2},{-2},{-2},{-2},{-2}, //16 - INSTR("vrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), - INSTR("vrsq", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), - INSTR("vsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), - INSTR("vcos", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), - INSTR("vexp2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), - INSTR("vlog2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), - INSTR("vsqrt", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), - INSTR("vasin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), + INSTR("vrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vrsq", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vcos", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vexp2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vlog2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vsqrt", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vasin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), //24 - INSTR("vnrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU), + INSTR("vnrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), {-2}, - INSTR("vnsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU), + INSTR("vnsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), {-2}, - INSTR("vrexp2",&Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU), + INSTR("vrexp2",&Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), {-2},{-2},{-2}, //32 }; @@ -651,10 +651,10 @@ const MIPSInstruction tableVFPU6[32] = //111100 xxx INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU), INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU), - INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU), - INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU), - INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU), - INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU), + INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX), //24 {-2}, {-2}, From d63548799b93f100dd41bb82c8746a1f9539fbf3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 22:18:46 -0800 Subject: [PATCH 47/69] Add more temp regs, allow swapping if necessary. --- Core/MIPS/x86/RegCacheFPU.cpp | 20 ++++++++++++-------- Core/MIPS/x86/RegCacheFPU.h | 16 ++++++++++++++-- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index fa637f7fb5..28ebf65c26 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -21,6 +21,8 @@ #include "Core/MIPS/MIPSAnalyst.h" #include "Core/MIPS/x86/RegCacheFPU.h" +u32 FPURegCache::tempValues[NUM_TEMPS]; + FPURegCache::FPURegCache() : emit(0), mips(0) { memset(regs, 0, sizeof(regs)); memset(xregs, 0, sizeof(xregs)); @@ -79,6 +81,11 @@ void FPURegCache::MapRegsV(const u8 *v, VectorSize sz, int flags) { } } +void FPURegCache::ReleaseSpillLock(int mipsreg) +{ + regs[mipsreg].locked = false; +} + void FPURegCache::ReleaseSpillLocks() { for (int i = 0; i < NUM_MIPS_FPRS; i++) regs[i].locked = false; @@ -99,9 +106,7 @@ void FPURegCache::BindToRegister(const int i, bool doLoad, bool makeDirty) { if (!regs[i].location.IsImm() && (regs[i].location.offset & 0x3)) { PanicAlert("WARNING - misaligned fp register location %i", i); } - if (i < TEMP0) { - emit->MOVSS(xr, regs[i].location); - } + emit->MOVSS(xr, regs[i].location); } regs[i].location = newloc; regs[i].away = true; @@ -148,7 +153,7 @@ bool FPURegCache::IsTemp(X64Reg xr) { } void FPURegCache::Flush() { - for (int i = 0; i < TEMP0; i++) { + for (int i = 0; i < NUM_MIPS_FPRS; i++) { if (regs[i].locked) { PanicAlert("Somebody forgot to unlock MIPS reg %i.", i); } @@ -164,16 +169,15 @@ void FPURegCache::Flush() { } } } - for (int i = TEMP0; i < TEMP0 + NUM_TEMPS; ++i) { - DiscardR(i); - } } OpArg FPURegCache::GetDefaultLocation(int reg) const { if (reg < 32) { return M(&mips->f[reg]); - } else { + } else if (reg < 32 + 128) { return M(&mips->v[reg - 32]); + } else { + return M(&tempValues[reg - 32 - 128]); } } diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index af5d2f4953..cda5793bf4 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -27,14 +27,22 @@ using namespace Gen; // GPRs are numbered 0 to 31 // VFPU regs are numbered 32 to 159. -// Then we have some temp regs for VFPU handling from 160 to 167. +// Then we have some temp regs for VFPU handling from 160 to 171. enum { - NUM_TEMPS = 4, + NUM_TEMPS = 12, TEMP0 = 32 + 128, TEMP1 = TEMP0 + 1, TEMP2 = TEMP0 + 2, TEMP3 = TEMP0 + 3, + TEMP4 = TEMP0 + 4, + TEMP5 = TEMP0 + 5, + TEMP6 = TEMP0 + 6, + TEMP7 = TEMP0 + 7, + TEMP8 = TEMP0 + 8, + TEMP9 = TEMP0 + 9, + TEMP10 = TEMP0 + 10, + TEMP11 = TEMP0 + 11, NUM_MIPS_FPRS = 32 + 128 + NUM_TEMPS, }; @@ -108,6 +116,7 @@ public: // Register locking. Prevents them from being spilled. void SpillLock(int p1, int p2=0xff, int p3=0xff, int p4=0xff); + void ReleaseSpillLock(int mipsrega); void ReleaseSpillLocks(); void MapRegV(int vreg, int flags); @@ -130,5 +139,8 @@ private: X64CachedFPReg xregs[NUM_X_FPREGS]; MIPSCachedFPReg *vregs; + // TEMP0, etc. are swapped in here if necessary (e.g. on x86.) + static u32 tempValues[NUM_TEMPS]; + XEmitter *emit; }; From 08a42a1aafd00666e3c9612cc0cb6ec354063f84 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 22:37:56 -0800 Subject: [PATCH 48/69] Preserve orig regs when applying vfpu prefixes. --- Core/MIPS/x86/CompVFPU.cpp | 21 +++++++++++++-------- Core/MIPS/x86/Jit.h | 8 +++++++- Core/MIPS/x86/RegCacheFPU.cpp | 13 ++++++++++++- Core/MIPS/x86/RegCacheFPU.h | 9 ++++++++- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index ff16fb25fb..e014ffe782 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -75,9 +75,6 @@ void Jit::Comp_VPFX(u32 op) } } - -// TODO: Got register value ownership issues. We need to be sure that if we modify input -// like this, it does NOT get written back! void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) { if (prefix == 0xE4) return; @@ -86,10 +83,7 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) { static const float constantArray[8] = {0.f, 1.f, 2.f, 0.5f, 3.f, 1.f/3.f, 0.25f, 1.f/6.f}; for (int i = 0; i < n; i++) - { - // TODO: This needs to be the original values, not the original regs. (e.g. [-x, |x|, x]) origV[i] = vregs[i]; - } for (int i = 0; i < n; i++) { @@ -98,22 +92,33 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) { int negate = (prefix >> (16+i)) & 1; int constants = (prefix >> (12+i)) & 1; + // Unchanged, hurray. + if (!constants && regnum == i && !abs && !negate) + continue; + + // This puts the value into a temp reg, so we won't write the modified value back. + vregs[i] = fpr.GetTempV(); + fpr.MapRegV(vregs[i], MAP_NOINIT | MAP_DIRTY); + if (!constants) { // Prefix may say "z, z, z, z" but if this is a pair, we force to x. // TODO: But some ops seem to use const 0 instead? if (regnum > n) { regnum = 0; } - vregs[i] = origV[regnum]; + MOVSS(fpr.VX(vregs[i]), fpr.V(origV[regnum])); if (abs) { ANDPS(fpr.VX(vregs[i]), M((void *)&noSignMask)); } - } else { + } else { MOVSS(fpr.VX(vregs[i]), M((void *)&constantArray[regnum + (abs<<2)])); } if (negate) XORPS(fpr.VX(vregs[i]), M((void *)&signBitLower)); + + // TODO: This probably means it will swap out soon, inefficiently... + fpr.ReleaseSpillLockV(vregs[i]); } } diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 4b20de372d..13c38b3548 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -79,7 +79,7 @@ struct JitState prefixDFlag = PREFIX_UNKNOWN; } bool MayHavePrefix() const { - if (!(prefixSFlag & PREFIX_KNOWN) || !(prefixTFlag & PREFIX_KNOWN) || !(prefixDFlag & PREFIX_KNOWN)) { + if (HasUnknownPrefix()) { return true; } else if (prefixS != 0xE4 || prefixT != 0xE4 || prefixD != 0) { return true; @@ -89,6 +89,12 @@ struct JitState return false; } + bool HasUnknownPrefix() const { + if (!(prefixSFlag & PREFIX_KNOWN) || !(prefixTFlag & PREFIX_KNOWN) || !(prefixDFlag & PREFIX_KNOWN)) { + return true; + } + return false; + } void EatPrefix() { if ((prefixSFlag & PREFIX_KNOWN) == 0 || prefixS != 0xE4) { prefixSFlag = PREFIX_KNOWN_DIRTY; diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index 28ebf65c26..34a03a47ee 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -148,10 +148,21 @@ void FPURegCache::DiscardR(int i) { } } -bool FPURegCache::IsTemp(X64Reg xr) { +bool FPURegCache::IsTempX(X64Reg xr) { return xregs[xr].mipsReg >= TEMP0; } +int FPURegCache::GetTempR() { + for (int r = TEMP0; r < TEMP0 + NUM_TEMPS; ++r) { + if (!regs[r].away) { + return r; + } + } + + _assert_msg_(DYNA_REC, 0, "Regcache ran out of temp regs, might need to DiscardR() some."); + return -1; +} + void FPURegCache::Flush() { for (int i = 0; i < NUM_MIPS_FPRS; i++) { if (regs[i].locked) { diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index cda5793bf4..772dd0cb35 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -88,7 +88,11 @@ public: void DiscardV(int vreg) { DiscardR(vreg + 32); } - bool IsTemp(X64Reg xreg); + bool IsTempX(X64Reg xreg); + int GetTempR(); + int GetTempV() { + return GetTempR() - 32; + } void SetEmitter(XEmitter *emitter) {emit = emitter;} @@ -127,6 +131,9 @@ public: } void SpillLockV(const u8 *v, VectorSize vsz); void SpillLockV(int vec, VectorSize vsz); + void ReleaseSpillLockV(int vreg) { + ReleaseSpillLock(vreg + 32); + } MIPSState *mips; From 27942606ad480910a5db9a3228a3dcf52fa2b481 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 22:46:12 -0800 Subject: [PATCH 49/69] Use prefixD directly in jit, just like interp now. --- Core/MIPS/MIPSIntVFPU.cpp | 29 ++++++++++++----------------- Core/MIPS/x86/CompVFPU.cpp | 35 +++++++++++++++++------------------ Core/MIPS/x86/Jit.h | 14 ++++++++++---- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index f861340d8c..d66f336308 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -145,27 +145,22 @@ inline void ApplySwizzleT(float *v, VectorSize size) void ApplyPrefixD(float *v, VectorSize size, bool onlyWriteMask = false) { u32 data = currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX]; - if (!data) + if (!data || onlyWriteMask) return; int n = GetNumVectorElements(size); - bool writeMask[4]; for (int i = 0; i < n; i++) { - int mask = (data >> (8 + i)) & 1; - writeMask[i] = mask ? true : false; - if (!onlyWriteMask) { - int sat = (data >> (i * 2)) & 3; - if (sat == 1) - { - if (v[i] > 1.0f) v[i] = 1.0f; - // This includes -0.0f -> +0.0f. - if (v[i] <= 0.0f) v[i] = 0.0f; - } - else if (sat == 3) - { - if (v[i] > 1.0f) v[i] = 1.0f; - if (v[i] < -1.0f) v[i] = -1.0f; - } + int sat = (data >> (i * 2)) & 3; + if (sat == 1) + { + if (v[i] > 1.0f) v[i] = 1.0f; + // This includes -0.0f -> +0.0f. + if (v[i] <= 0.0f) v[i] = 0.0f; + } + else if (sat == 3) + { + if (v[i] > 1.0f) v[i] = 1.0f; + if (v[i] < -1.0f) v[i] = -1.0f; } } } diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index e014ffe782..d4d689091c 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -124,27 +124,21 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) { void Jit::ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWriteMask) { _assert_(js.prefixDFlag & JitState::PREFIX_KNOWN); - if (!prefix) return; + if (!prefix || onlyWriteMask) return; int n = GetNumVectorElements(sz); for (int i = 0; i < n; i++) { - int mask = (prefix >> (8 + i)) & 1; - js.writeMask[i] = mask ? true : false; - if (onlyWriteMask) - continue; - if (!mask) { - int sat = (prefix >> (i * 2)) & 3; - if (sat == 1) - { - MAXSS(fpr.VX(vregs[i]), M((void *)&zero)); - MINSS(fpr.VX(vregs[i]), M((void *)&one)); - } - else if (sat == 3) - { - MAXSS(fpr.VX(vregs[i]), M((void *)&minus_one)); - MINSS(fpr.VX(vregs[i]), M((void *)&one)); - } + int sat = (prefix >> (i * 2)) & 3; + if (sat == 1) + { + MAXSS(fpr.VX(vregs[i]), M((void *)&zero)); + MINSS(fpr.VX(vregs[i]), M((void *)&one)); + } + else if (sat == 3) + { + MAXSS(fpr.VX(vregs[i]), M((void *)&minus_one)); + MINSS(fpr.VX(vregs[i]), M((void *)&one)); } } } @@ -323,8 +317,13 @@ void Jit::Comp_SVQ(u32 op) void Jit::Comp_VDot(u32 op) { CONDITIONAL_DISABLE; + if (js.HasUnknownPrefix()) { + Comp_Generic(op); + return; + } + // No-op. - if (js.writeMask[0]) { + if (js.VfpuWriteMask(0)) { return; } diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 13c38b3548..fadc83f9b7 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -69,7 +69,6 @@ struct JitState u32 prefixS; u32 prefixT; u32 prefixD; - bool writeMask[4]; PrefixState prefixSFlag; PrefixState prefixTFlag; PrefixState prefixDFlag; @@ -83,7 +82,7 @@ struct JitState return true; } else if (prefixS != 0xE4 || prefixT != 0xE4 || prefixD != 0) { return true; - } else if (writeMask[0] || writeMask[1] || writeMask[2] || writeMask[3]) { + } else if (VfpuWriteMask() != 0) { return true; } @@ -104,12 +103,19 @@ struct JitState prefixTFlag = PREFIX_KNOWN_DIRTY; prefixT = 0xE4; } - if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0 || writeMask[0] || writeMask[1] || writeMask[2] || writeMask[3]) { + if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0 || VfpuWriteMask() != 0) { prefixDFlag = PREFIX_KNOWN_DIRTY; prefixD = 0x0; - writeMask[0] = writeMask[1] = writeMask[2] = writeMask[3] = false; } } + u8 VfpuWriteMask() const { + _assert_(prefixDFlag & JitState::PREFIX_KNOWN); + return (prefixD >> 8) & 0xF; + } + bool VfpuWriteMask(int i) const { + _assert_(prefixDFlag & JitState::PREFIX_KNOWN); + return (prefixD >> (8 + i)) & 1; + } }; enum CompileDelaySlotFlags From 18c03d0816ab2a03050337d64d8ac74451f84d97 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 23:14:22 -0800 Subject: [PATCH 50/69] Handle temp regs better, no need for direct access. --- Core/MIPS/x86/RegCacheFPU.cpp | 5 ++++- Core/MIPS/x86/RegCacheFPU.h | 19 ++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index 34a03a47ee..f4279dd869 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -27,6 +27,7 @@ FPURegCache::FPURegCache() : emit(0), mips(0) { memset(regs, 0, sizeof(regs)); memset(xregs, 0, sizeof(xregs)); vregs = regs + 32; + tempRoundRobin = 0; } void FPURegCache::Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats) { @@ -153,7 +154,9 @@ bool FPURegCache::IsTempX(X64Reg xr) { } int FPURegCache::GetTempR() { - for (int r = TEMP0; r < TEMP0 + NUM_TEMPS; ++r) { + for (int i = 0; i < NUM_TEMPS; ++i) { + // Make sure we don't give out the same one over and over, even if not locked. + int r = TEMP0 + (tempRoundRobin++ + i) % NUM_TEMPS; if (!regs[r].away) { return r; } diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index 772dd0cb35..4fbdd10220 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -27,22 +27,14 @@ using namespace Gen; // GPRs are numbered 0 to 31 // VFPU regs are numbered 32 to 159. -// Then we have some temp regs for VFPU handling from 160 to 171. +// Then we have some temp regs for VFPU handling from 160 to 175. + +// Temp regs: 4 from S prefix, 4 from T prefix, 4 from D mask, and 4 for work (worst case.) +// But most of the time prefixes aren't used that heavily so we won't use all of them. enum { - NUM_TEMPS = 12, + NUM_TEMPS = 16, TEMP0 = 32 + 128, - TEMP1 = TEMP0 + 1, - TEMP2 = TEMP0 + 2, - TEMP3 = TEMP0 + 3, - TEMP4 = TEMP0 + 4, - TEMP5 = TEMP0 + 5, - TEMP6 = TEMP0 + 6, - TEMP7 = TEMP0 + 7, - TEMP8 = TEMP0 + 8, - TEMP9 = TEMP0 + 9, - TEMP10 = TEMP0 + 10, - TEMP11 = TEMP0 + 11, NUM_MIPS_FPRS = 32 + 128 + NUM_TEMPS, }; @@ -148,6 +140,7 @@ private: // TEMP0, etc. are swapped in here if necessary (e.g. on x86.) static u32 tempValues[NUM_TEMPS]; + int tempRoundRobin; XEmitter *emit; }; From 8ea59990ab8413c54ae83db69d3299f98e4b2d07 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Feb 2013 23:15:16 -0800 Subject: [PATCH 51/69] Make applying prefixes mostly automatic. And implement (hopefully) D prefixes. --- Core/MIPS/x86/CompVFPU.cpp | 51 ++++++++++++++++++++++++-------------- Core/MIPS/x86/Jit.h | 13 +++++++++- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index d4d689091c..16a59cd9ca 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -122,21 +122,42 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) { } } -void Jit::ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWriteMask) { +void Jit::GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg) { _assert_(js.prefixDFlag & JitState::PREFIX_KNOWN); - if (!prefix || onlyWriteMask) return; + + GetVectorRegs(regs, sz, vectorReg); + if (js.prefixD == 0) + return; int n = GetNumVectorElements(sz); for (int i = 0; i < n; i++) { - int sat = (prefix >> (i * 2)) & 3; + // Hopefully this is rare, we'll just write it into a reg we drop. + if (js.VfpuWriteMask(i)) + regs[i] = fpr.GetTempV(); + } +} + +void Jit::ApplyPrefixD(const u8 *vregs, VectorSize sz) { + _assert_(js.prefixDFlag & JitState::PREFIX_KNOWN); + if (!js.prefixD) return; + + int n = GetNumVectorElements(sz); + for (int i = 0; i < n; i++) + { + if (js.VfpuWriteMask(i)) + continue; + + int sat = (js.prefixD >> (i * 2)) & 3; if (sat == 1) { + fpr.MapRegV(vregs[i], MAP_DIRTY); MAXSS(fpr.VX(vregs[i]), M((void *)&zero)); MINSS(fpr.VX(vregs[i]), M((void *)&one)); } else if (sat == 3) { + fpr.MapRegV(vregs[i], MAP_DIRTY); MAXSS(fpr.VX(vregs[i]), M((void *)&minus_one)); MINSS(fpr.VX(vregs[i]), M((void *)&one)); } @@ -322,12 +343,7 @@ void Jit::Comp_VDot(u32 op) { return; } - // No-op. - if (js.VfpuWriteMask(0)) { - return; - } - - // WARNING: No prefix support! + // WARNING: No prefix support! (maybe soon) if (js.MayHavePrefix()) { Comp_Generic(op); return; @@ -340,11 +356,9 @@ void Jit::Comp_VDot(u32 op) { // TODO: Force read one of them into regs? probably not. u8 sregs[4], tregs[4], dregs[1]; - GetVectorRegs(sregs, sz, vs); - GetVectorRegs(tregs, sz, vt); - GetVectorRegs(dregs, V_Single, vd); - - // TODO: applyprefixST here somehow (shuffle, etc...) + GetVectorRegsPrefixS(sregs, sz, vs); + GetVectorRegsPrefixT(tregs, sz, vt); + GetVectorRegsPrefixD(dregs, V_Single, vd); int n = GetNumVectorElements(sz); X64Reg tempxreg = XMM0; @@ -370,7 +384,7 @@ void Jit::Comp_VDot(u32 op) { MOVSS(fpr.V(dregs[0]), tempxreg); } - // TODO: applyprefixD here somehow (write mask etc..) + ApplyPrefixD(dregs, V_Single); fpr.ReleaseSpillLocks(); } @@ -440,9 +454,10 @@ void Jit::Comp_VecDo3(u32 op) { tempxregs[i] = (X64Reg) (XMM0 + i); else { - fpr.BindToRegister(TEMP0 + i, false, true); - fpr.SpillLock(TEMP0 + i); - tempxregs[i] = fpr.RX(TEMP0 + i); + int reg = fpr.GetTempV(); + fpr.MapRegV(reg, MAP_NOINIT | MAP_DIRTY); + fpr.SpillLockV(reg); + tempxregs[i] = fpr.VX(reg); } } else diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index fadc83f9b7..a0f69d180a 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -184,7 +184,18 @@ public: void Comp_DoNothing(u32 op); void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz); - void ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWriteMask = false); + void ApplyPrefixD(const u8 *vregs, VectorSize sz); + void GetVectorRegsPrefixS(u8 *regs, VectorSize sz, int vectorReg) { + _assert_(js.prefixSFlag & JitState::PREFIX_KNOWN); + GetVectorRegs(regs, sz, vectorReg); + ApplyPrefixST(regs, js.prefixS, sz); + } + void GetVectorRegsPrefixT(u8 *regs, VectorSize sz, int vectorReg) { + _assert_(js.prefixTFlag & JitState::PREFIX_KNOWN); + GetVectorRegs(regs, sz, vectorReg); + ApplyPrefixST(regs, js.prefixT, sz); + } + void GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg); void EatPrefix() { js.EatPrefix(); } JitBlockCache *GetBlockCache() { return &blocks; } From 6855398add0235cecdf790a78b4965349e394c11 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 00:09:19 -0800 Subject: [PATCH 52/69] Support known prefixes in the vfpu jit. --- Core/MIPS/x86/CompVFPU.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 16a59cd9ca..6ebfb11fa7 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -104,6 +104,7 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) { // Prefix may say "z, z, z, z" but if this is a pair, we force to x. // TODO: But some ops seem to use const 0 instead? if (regnum > n) { + ERROR_LOG(CPU, "Invalid VFPU swizzle: %08x / %d", prefix, sz); regnum = 0; } MOVSS(fpr.VX(vregs[i]), fpr.V(origV[regnum])); @@ -343,12 +344,6 @@ void Jit::Comp_VDot(u32 op) { return; } - // WARNING: No prefix support! (maybe soon) - if (js.MayHavePrefix()) { - Comp_Generic(op); - return; - } - int vd = _VD; int vs = _VS; int vt = _VT; @@ -392,9 +387,7 @@ void Jit::Comp_VDot(u32 op) { void Jit::Comp_VecDo3(u32 op) { CONDITIONAL_DISABLE; - // WARNING: No prefix support! - if (js.MayHavePrefix()) - { + if (js.HasUnknownPrefix()) { Comp_Generic(op); return; } @@ -405,9 +398,9 @@ void Jit::Comp_VecDo3(u32 op) { VectorSize sz = GetVecSize(op); u8 sregs[4], tregs[4], dregs[4]; - GetVectorRegs(sregs, sz, vs); - GetVectorRegs(tregs, sz, vt); - GetVectorRegs(dregs, sz, vd); + GetVectorRegsPrefixS(sregs, sz, vs); + GetVectorRegsPrefixT(tregs, sz, vt); + GetVectorRegsPrefixD(dregs, sz, vd); void (XEmitter::*xmmop)(X64Reg, OpArg) = NULL; switch (op >> 26) @@ -481,6 +474,8 @@ void Jit::Comp_VecDo3(u32 op) { MOVSS(fpr.V(dregs[i]), tempxregs[i]); } + ApplyPrefixD(dregs, sz); + fpr.ReleaseSpillLocks(); } From 0bfc380575986ad8128639cfe041bc2834b9f261 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 00:32:42 -0800 Subject: [PATCH 53/69] Try to reuse temp regs for better caching. --- Core/MIPS/x86/CompVFPU.cpp | 1 + Core/MIPS/x86/RegCacheFPU.cpp | 11 ++++++----- Core/MIPS/x86/RegCacheFPU.h | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 6ebfb11fa7..3343bddac0 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -431,6 +431,7 @@ void Jit::Comp_VecDo3(u32 op) { if (xmmop == NULL) { + fpr.ReleaseSpillLocks(); Comp_Generic(op); return; } diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index f4279dd869..9256a6d8fa 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -27,7 +27,6 @@ FPURegCache::FPURegCache() : emit(0), mips(0) { memset(regs, 0, sizeof(regs)); memset(xregs, 0, sizeof(xregs)); vregs = regs + 32; - tempRoundRobin = 0; } void FPURegCache::Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats) { @@ -40,6 +39,7 @@ void FPURegCache::Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats) { regs[i].location = GetDefaultLocation(i); regs[i].away = false; regs[i].locked = false; + regs[i].tempLocked = false; } } @@ -144,8 +144,10 @@ void FPURegCache::DiscardR(int i) { xregs[xr].mipsReg = -1; regs[i].location = GetDefaultLocation(i); regs[i].away = false; + regs[i].tempLocked = false; } else { // _assert_msg_(DYNA_REC,0,"already stored"); + regs[i].tempLocked = false; } } @@ -154,10 +156,9 @@ bool FPURegCache::IsTempX(X64Reg xr) { } int FPURegCache::GetTempR() { - for (int i = 0; i < NUM_TEMPS; ++i) { - // Make sure we don't give out the same one over and over, even if not locked. - int r = TEMP0 + (tempRoundRobin++ + i) % NUM_TEMPS; - if (!regs[r].away) { + for (int r = TEMP0; r < TEMP0 + NUM_TEMPS; ++r) { + if (!regs[r].away && !regs[r].tempLocked) { + regs[r].tempLocked = true; return r; } } diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index 4fbdd10220..37d7c4c2e6 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -53,6 +53,8 @@ struct MIPSCachedFPReg { OpArg location; bool away; // value not in source register bool locked; + // Only for temp regs. + bool tempLocked; }; enum { @@ -140,7 +142,6 @@ private: // TEMP0, etc. are swapped in here if necessary (e.g. on x86.) static u32 tempValues[NUM_TEMPS]; - int tempRoundRobin; XEmitter *emit; }; From afb7c0b83c87cfbbe76c84c9ea023e8817f4b24c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 01:14:57 -0800 Subject: [PATCH 54/69] Assume prefixes start default until proven wrong. Currently this means nothing since the MIPSTables flags are wrong. It will blow the cache once, after the first vfpu op. --- Core/MIPS/MIPS.cpp | 9 +++++++-- Core/MIPS/x86/Jit.cpp | 23 ++++++++++++++++++++++- Core/MIPS/x86/Jit.h | 9 +++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index 478d2c99e5..f7fc64a752 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -45,8 +45,11 @@ MIPSState::MIPSState() MIPSState::~MIPSState() { - delete MIPSComp::jit; - MIPSComp::jit = 0; + if (MIPSComp::jit) + { + delete MIPSComp::jit; + MIPSComp::jit = 0; + } } void MIPSState::Reset() @@ -107,6 +110,8 @@ void MIPSState::DoState(PointerWrap &p) // Reset the jit if we're loading. if (p.mode == p.MODE_READ) Reset(); + if (MIPSComp::jit) + MIPSComp::jit->DoState(p); p.DoArray(r, sizeof(r) / sizeof(r[0])); p.DoArray(f, sizeof(f) / sizeof(f[0])); diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 7a817e5c8b..affcc7fd19 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -17,6 +17,7 @@ #include #include +#include "Common/ChunkFile.h" #include "../../Core.h" #include "../../CoreTiming.h" #include "../../Config.h" @@ -103,6 +104,15 @@ Jit::Jit(MIPSState *mips) : blocks(mips), mips_(mips) gpr.SetEmitter(this); fpr.SetEmitter(this); AllocCodeSpace(1024 * 1024 * 16); + + // TODO: If it becomes possible to switch from the interpreter, this should be set right. + js.startDefaultPrefix = true; +} + +void Jit::DoState(PointerWrap &p) +{ + p.Do(js.startDefaultPrefix); + p.DoMarker("Jit"); } void Jit::FlushAll() @@ -202,6 +212,17 @@ void Jit::Compile(u32 em_address) int block_num = blocks.AllocateBlock(em_address); JitBlock *b = blocks.GetBlock(block_num); blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, b)); + + // Drat. The VFPU hit an uneaten prefix at the end of a block. + if (js.startDefaultPrefix && js.MayHavePrefix()) + { + js.startDefaultPrefix = false; + // Our assumptions are all wrong so it's clean-slate time. + ClearCache(); + + // Let's try that one more time. We won't get back here because we toggled the value. + Compile(em_address); + } } void Jit::RunLoopUntil(u64 globalticks) @@ -285,7 +306,7 @@ void Jit::Comp_Generic(u32 op) // Might have eaten prefixes, hard to tell... const int info = MIPSGetInfo(op); if ((info & IS_VFPU) != 0 && (info & OUT_EAT_PREFIX) == 0) - js.PrefixStart(); + js.PrefixUnknown(); } void Jit::WriteExit(u32 destination, int exit_num) diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index a0f69d180a..cf86376393 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -66,6 +66,7 @@ struct JitState JitBlock *curBlock; // VFPU prefix magic + bool startDefaultPrefix; u32 prefixS; u32 prefixT; u32 prefixD; @@ -73,6 +74,13 @@ struct JitState PrefixState prefixTFlag; PrefixState prefixDFlag; void PrefixStart() { + if (startDefaultPrefix) { + EatPrefix(); + } else { + PrefixUnknown(); + } + } + void PrefixUnknown() { prefixSFlag = PREFIX_UNKNOWN; prefixTFlag = PREFIX_UNKNOWN; prefixDFlag = PREFIX_UNKNOWN; @@ -134,6 +142,7 @@ class Jit : public Gen::XCodeBlock { public: Jit(MIPSState *mips); + void DoState(PointerWrap &p); // Compiled ops should ignore delay slots // the compiler will take care of them by itself From dacbcbdf2bfeef7dd29e3e2ceccbd0395106137c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 01:18:46 -0800 Subject: [PATCH 55/69] Add a MIPSTables flag for ignoring the prefix. --- Core/MIPS/MIPSTables.cpp | 14 +++++++------- Core/MIPS/MIPSTables.h | 1 + Core/MIPS/x86/Jit.cpp | 9 ++++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index d792c800eb..3d42889125 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -147,22 +147,22 @@ const MIPSInstruction tableImmediate[64] = //xxxxxx ..... //48 INSTR("ll", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, 0), INSTR("lwc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, IN_RT|IN_RS_ADDR), - INSTR("lv.s", &Jit::Comp_SV, Dis_SV, Int_SV, IS_VFPU), + INSTR("lv.s", &Jit::Comp_SV, Dis_SV, Int_SV, IS_VFPU|VFPU_NO_PREFIX), {-2}, // HIT THIS IN WIPEOUT {VFPU4Jump}, - INSTR("lv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU), - INSTR("lv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU), //copU + INSTR("lv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU|VFPU_NO_PREFIX), + INSTR("lv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU|VFPU_NO_PREFIX), //copU {VFPU5}, //56 INSTR("sc", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, 0), INSTR("swc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, 0), //copU - INSTR("sv.s", &Jit::Comp_SV, Dis_SV, Int_SV,IS_VFPU), + INSTR("sv.s", &Jit::Comp_SV, Dis_SV, Int_SV,IS_VFPU|VFPU_NO_PREFIX), {-2}, //60 {VFPU6}, - INSTR("sv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU), //copU - INSTR("sv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU), - INSTR("vflush", &Jit::Comp_Generic, Dis_Vflush, Int_Vflush, IS_VFPU), + INSTR("sv", &Jit::Comp_SVQ, Dis_SVLRQ, Int_SVQ, IS_VFPU|VFPU_NO_PREFIX), //copU + INSTR("sv.q", &Jit::Comp_SVQ, Dis_SVQ, Int_SVQ, IS_VFPU|VFPU_NO_PREFIX), + INSTR("vflush", &Jit::Comp_Generic, Dis_Vflush, Int_Vflush, IS_VFPU|VFPU_NO_PREFIX), }; const MIPSInstruction tableSpecial[64] = /// 000000 ...... ...... .......... xxxxxx diff --git a/Core/MIPS/MIPSTables.h b/Core/MIPS/MIPSTables.h index 18ee23b42f..68e453af99 100644 --- a/Core/MIPS/MIPSTables.h +++ b/Core/MIPS/MIPSTables.h @@ -45,6 +45,7 @@ #define OUT_FPUFLAG 0x02000000 #define OUT_EAT_PREFIX 0x04000000 +#define VFPU_NO_PREFIX 0x08000000 #define IS_VFPU 0x80000000 #ifndef CDECL diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index affcc7fd19..5b56caad72 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -303,10 +303,13 @@ void Jit::Comp_Generic(u32 op) else _dbg_assert_msg_(JIT, 0, "Trying to compile instruction that can't be interpreted"); - // Might have eaten prefixes, hard to tell... const int info = MIPSGetInfo(op); - if ((info & IS_VFPU) != 0 && (info & OUT_EAT_PREFIX) == 0) - js.PrefixUnknown(); + if ((info & IS_VFPU) != 0 && (info & VFPU_NO_PREFIX) == 0) + { + // If it does eat them, it'll happen in MIPSCompileOp(). + if ((info & OUT_EAT_PREFIX) == 0) + js.PrefixUnknown(); + } } void Jit::WriteExit(u32 destination, int exit_num) From 33c1a2b4facc2e04ea484e153e0e61115e5cfd30 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 01:54:25 -0800 Subject: [PATCH 56/69] ARM buildfix. --- Core/MIPS/ARM/ArmJit.cpp | 5 +++++ Core/MIPS/ARM/ArmJit.h | 1 + 2 files changed, 6 insertions(+) diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 7933a76f5a..132b2e9f92 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -63,6 +63,11 @@ Jit::Jit(MIPSState *mips) : blocks(mips), gpr(mips), mips_(mips) GenerateFixedCode(); } +void Jit::DoState(PointerWrap &p) +{ + p.DoMarker("Jit"); +} + void Jit::FlushAll() { gpr.FlushAll(); diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 0dc0338e7d..1cb80e2d4f 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -64,6 +64,7 @@ class Jit : public ArmGen::ARMXCodeBlock { public: Jit(MIPSState *mips); + void DoState(PointerWrap &p); // Compiled ops should ignore delay slots // the compiler will take care of them by itself From 7f2e13c82abbb81aafb8457512486b182585e578 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 18 Feb 2013 23:55:41 +1000 Subject: [PATCH 57/69] Fix framebuffer init. Why was it like that? --- GPU/GLES/Framebuffer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index bc513f90e0..de4517bb6b 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -326,12 +326,12 @@ void FramebufferManager::SetRenderFrameBuffer() { vfb->renderHeight = (u16)(drawing_height * renderHeightFactor); vfb->format = fmt; - vfb->colorDepth = FBO_8888; switch (fmt) { - case GE_FORMAT_4444: vfb->colorDepth = FBO_4444; - case GE_FORMAT_5551: vfb->colorDepth = FBO_5551; - case GE_FORMAT_565: vfb->colorDepth = FBO_565; - case GE_FORMAT_8888: vfb->colorDepth = FBO_8888; + case GE_FORMAT_4444: vfb->colorDepth = FBO_4444; break; + case GE_FORMAT_5551: vfb->colorDepth = FBO_5551; break; + case GE_FORMAT_565: vfb->colorDepth = FBO_565; break; + case GE_FORMAT_8888: vfb->colorDepth = FBO_8888; break; + default: vfb->colorDepth = FBO_8888; break; } //#ifdef ANDROID // vfb->colorDepth = FBO_8888; From 9d490a8b508004ea04d86f085b95dde00d49c663 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 08:03:45 -0800 Subject: [PATCH 58/69] Proper ARM buildfix. --- Core/MIPS/ARM/ArmJit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 132b2e9f92..273b3e1bdd 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "Common/ChunkFile.h" #include "../../Core.h" #include "../../CoreTiming.h" #include "../MIPS.h" From d8b1ea22f5a7db0cf564b54a573edb587e7245e7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 08:34:51 -0800 Subject: [PATCH 59/69] Cleanup some warnings and reuse some vars. --- GPU/GLES/TextureCache.cpp | 10 +++++----- GPU/GLES/TextureCache.h | 4 ++-- GPU/GLES/TransformPipeline.cpp | 8 +++++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 6487e9ce36..96ccc7768b 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -684,6 +684,8 @@ void TextureCache::SetTexture() { clutformat = gstate.clutformat & 3; clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2); cachekey |= (u64)clutaddr << 32; + } else { + clutaddr = 0; } int maxLevel = ((gstate.texmode >> 16) & 0x7); @@ -725,7 +727,7 @@ void TextureCache::SetTexture() { entry->hash != texhash || entry->format != format || entry->maxLevel != maxLevel || - ((format >= GE_TFMT_CLUT4 && format <= GE_TFMT_CLUT32) && + (hasClut && (entry->clutformat != clutformat || entry->clutaddr != clutaddr || entry->cluthash != Memory::Read_U32(entry->clutaddr)))) @@ -810,9 +812,9 @@ void TextureCache::SetTexture() { entry->lodBias = 0.0f; - if (format >= GE_TFMT_CLUT4 && format <= GE_TFMT_CLUT32) { + if (hasClut) { entry->clutformat = clutformat; - entry->clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2); + entry->clutaddr = clutaddr; entry->cluthash = Memory::Read_U32(entry->clutaddr); } else { entry->clutaddr = 0; @@ -1173,8 +1175,6 @@ bool TextureCache::DecodeTexture(u8* output, GPUgstate state) // TODO: Look into using BGRA for 32-bit textures when the GL_EXT_texture_format_BGRA8888 extension is available, as it's faster than RGBA on some chips. - // TODO: Actually decode the mipmaps. - switch (format) { case GE_TFMT_CLUT4: diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index 764ad63735..65c64b4eb3 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -66,8 +66,8 @@ private: int numFrames; u32 framesUntilNextFullHash; u8 format; - u8 clutformat; u16 dim; + u8 clutformat; u32 clutaddr; u32 cluthash; u32 texture; //GLuint @@ -102,7 +102,7 @@ private: u32 *clutBuf32; u16 *clutBuf16; - int lastBoundTexture; + u32 lastBoundTexture; float maxAnisotropyLevel; }; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 85fa40b631..72b2066c57 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -53,12 +53,14 @@ enum { }; TransformDrawEngine::TransformDrawEngine() - : numDrawCalls(0), - collectedVerts(0), + : collectedVerts(0), prevPrim_(-1), lastVType_(-1), curVbo_(0), - shaderManager_(0) { + shaderManager_(0), + textureCache_(0), + framebufferManager_(0), + numDrawCalls(0) { // Allocate nicely aligned memory. Maybe graphics drivers will // appreciate it. // All this is a LOT of memory, need to see if we can cut down somehow. From 363d1dbe199eb8cca0454e558a7e0f989c5405fe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 08:44:59 -0800 Subject: [PATCH 60/69] Fix some misc. warnings. --- Common/ChunkFile.h | 2 +- Core/Dialog/SavedataParam.cpp | 2 +- Core/ELF/ElfReader.cpp | 2 +- Core/HLE/HLE.cpp | 2 +- Core/HW/SasAudio.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index 095831678a..0344483514 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -625,7 +625,7 @@ public: u8 *uncomp_buffer = new u8[header.UncompressedSize]; size_t uncomp_size = header.UncompressedSize; snappy_uncompress((const char *)buffer, sz, (char *)uncomp_buffer, &uncomp_size); - if (uncomp_size != header.UncompressedSize) { + if ((int)uncomp_size != header.UncompressedSize) { ERROR_LOG(COMMON,"Size mismatch: file: %i calc: %i", (int)header.UncompressedSize, (int)uncomp_size); } ptr = uncomp_buffer; diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 22762fbaa1..ce3b97089b 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -1080,7 +1080,7 @@ bool SavedataParam::CreatePNGIcon(u8* pngData, int pngSize, SaveFileInfo& info) u32 atlasPtr; if (success) atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); - if (success && atlasPtr != -1) + if (success && atlasPtr != (u32)-1) { info.textureData = atlasPtr; Memory::Memcpy(atlasPtr, textureData, texSize); diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 77ff90de4d..9054e68d6a 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -217,7 +217,7 @@ bool ElfReader::LoadInto(u32 loadAddress) vaddr = userMemory.Alloc(totalSize, false, "ELF"); } - if (vaddr == -1) { + if (vaddr == (u32)-1) { ERROR_LOG(LOADER, "Failed to allocate memory for ELF!"); return false; } diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 6e7087c04d..48c0f87688 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -297,7 +297,7 @@ bool hleExecuteDebugBreak(const HLEFunction &func) // Never break on these, they're noise. u32 blacklistedNIDs[] = {NID_SUSPEND_INTR, NID_RESUME_INTR, NID_IDLE}; - for (int i = 0; i < ARRAY_SIZE(blacklistedNIDs); ++i) + for (size_t i = 0; i < ARRAY_SIZE(blacklistedNIDs); ++i) { if (func.ID == blacklistedNIDs[i]) return false; diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 97f1b8837a..aa22d3b875 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -548,8 +548,8 @@ static int getExpCurveAt(int index, int duration) { } ADSREnvelope::ADSREnvelope() - : steps_(0), - state_(STATE_OFF), + : state_(STATE_OFF), + steps_(0), height_(0) { memset(this, 0, sizeof(*this)); } From 51d5b841082ffd79438deeedb31853942fff2d57 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 09:04:43 -0800 Subject: [PATCH 61/69] Fix some misc HLE warnings. --- Core/HLE/sceAtrac.cpp | 4 ++-- Core/HLE/sceCtrl.cpp | 8 ++++---- Core/HLE/sceGe.cpp | 4 ++-- Core/HLE/sceKernelInterrupt.cpp | 8 ++++---- Core/HLE/sceSas.cpp | 2 +- Core/MIPS/MIPSAnalyst.cpp | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 4e6604add6..5ea398ca07 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -187,7 +187,7 @@ u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF ret = ATRAC_ERROR_ALL_DATA_DECODED; } else { // TODO: This isn't at all right, but at least it makes the music "last" some time. - int numSamples = (atrac->decodeEnd - atrac->decodePos) / (sizeof(s16) * 2); + u32 numSamples = (atrac->decodeEnd - atrac->decodePos) / (sizeof(s16) * 2); if (atrac->decodePos >= atrac->decodeEnd) { numSamples = 0; } else if (numSamples > ATRAC_MAX_SAMPLES) { @@ -554,7 +554,7 @@ int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesConsumedAddr, u32 samplesAddr, u32 sampleBytesAddr) { - ERROR_LOG(HLE, "UNIMPL sceAtracLowLevelDecode(%i, %i, %08x, %08x, %08x, %08x)", atracID, sourceAddr, sourceBytesConsumedAddr, samplesAddr, sampleBytesAddr); + ERROR_LOG(HLE, "UNIMPL sceAtracLowLevelDecode(%i, %08x, %08x, %08x, %08x)", atracID, sourceAddr, sourceBytesConsumedAddr, samplesAddr, sampleBytesAddr); return 0; } diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 819b884819..348bdce8d2 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -35,7 +35,7 @@ const int PSP_CTRL_ERROR_INVALID_MODE = 0x80000107; const int PSP_CTRL_ERROR_INVALID_IDLE_PTR = 0x80000023; -const int NUM_CTRL_BUFFERS = 64; +const u32 NUM_CTRL_BUFFERS = 64; enum { @@ -68,8 +68,8 @@ static u32 ctrlOldButtons = 0; static _ctrl_data ctrlBufs[NUM_CTRL_BUFFERS]; static _ctrl_data ctrlCurrent; -static int ctrlBuf = 0; -static int ctrlBufRead = 0; +static u32 ctrlBuf = 0; +static u32 ctrlBufRead = 0; static CtrlLatch latch; static int ctrlIdleReset = -1; @@ -189,7 +189,7 @@ int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek) if (nBufs > NUM_CTRL_BUFFERS) return SCE_KERNEL_ERROR_INVALID_SIZE; - int resetRead = ctrlBufRead; + u32 resetRead = ctrlBufRead; u32 availBufs; // Peeks always work, they just go go from now X buffers. diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 16e790d342..11ea18c711 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -237,10 +237,10 @@ u32 sceGeSetCallback(u32 structAddr) DEBUG_LOG(HLE, "sceGeSetCallback(struct=%08x)", structAddr); int cbID = -1; - for (int i = 0; i < ARRAY_SIZE(ge_used_callbacks); ++i) + for (size_t i = 0; i < ARRAY_SIZE(ge_used_callbacks); ++i) if (!ge_used_callbacks[i]) { - cbID = i; + cbID = (int) i; break; } diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 5241b1d937..a4791308e8 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -213,7 +213,7 @@ void __InterruptsInit() { interruptsEnabled = 1; inInterrupt = false; - for(int i = 0; i < ARRAY_SIZE(intrHandlers); ++i) + for (size_t i = 0; i < ARRAY_SIZE(intrHandlers); ++i) intrHandlers[i] = new IntrHandler(i); intState.clear(); } @@ -246,11 +246,11 @@ void __InterruptsDoStateLate(PointerWrap &p) void __InterruptsShutdown() { - for (int i = 0; i < ARRAY_SIZE(intrHandlers); ++i) + for (size_t i = 0; i < ARRAY_SIZE(intrHandlers); ++i) intrHandlers[i]->clear(); - for(int i = 0; i < ARRAY_SIZE(intrHandlers); ++i) + for (size_t i = 0; i < ARRAY_SIZE(intrHandlers); ++i) { - if(intrHandlers[i]) + if (intrHandlers[i]) { delete intrHandlers[i]; intrHandlers[i] = 0; diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 26ad93e6ab..16f3fec15d 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -430,7 +430,7 @@ u32 __sceSasSetVoiceATRAC3(u32 core, int voice, int atrac3Context) { } u32 __sceSasConcatenateATRAC3(u32 core, int voice, u32 atrac3DataAddr, int atrac3DataLength) { - ERROR_LOG(HLE,"UNIMPL __sceSasConcatenateATRAC3(%08x, %i, %i)", core, voice, atrac3DataAddr, atrac3DataLength); + ERROR_LOG(HLE,"UNIMPL __sceSasConcatenateATRAC3(%08x, %i, %08x, %i)", core, voice, atrac3DataAddr, atrac3DataLength); return 0; } diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 82e771927b..c9c548a739 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -98,7 +98,7 @@ namespace MIPSAnalyst "slt", "sltu", }; const char *opName = MIPSGetName(op); - for (int i = 0; i < ARRAY_SIZE(safeOps); ++i) + for (size_t i = 0; i < ARRAY_SIZE(safeOps); ++i) { if (!strcmp(safeOps[i], opName)) return true; From 179fccaff7fed79fb32ac4a05240560da4871ead Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 12:59:41 -0800 Subject: [PATCH 62/69] Tests say matrices apply mask to last col (kinda.) It seems inconsistent but probably better than before. Also add an error. --- Core/MIPS/MIPSVFPUUtils.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index 21ebfb844b..0f6ad315eb 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -179,19 +179,23 @@ void WriteMatrix(const float *rd, MatrixSize size, int reg) { case M_4x4: row = (reg>>5)&2; side = 4; break; } - int transpose = (reg>>5)&1; + int transpose = (reg>>5)&1; + + if (currentMIPS->VfpuWriteMask() != 0) { + ERROR_LOG(CPU, "Write mask used with vfpu matrix instruction."); + } for (int i=0; iVfpuWriteMask(i)) + if (j != side -1 || !currentMIPS->VfpuWriteMask(i)) { - int index = mtx * 4; + int index = mtx * 4; if (transpose) - index += ((row+i)&3) + ((col+j)&3)*32; - else - index += ((col+j)&3) + ((row+i)&3)*32; - V(index) = rd[j*4+i]; + index += ((row+i)&3) + ((col+j)&3)*32; + else + index += ((col+j)&3) + ((row+i)&3)*32; + V(index) = rd[j*4+i]; } } } From 0e0b70bb8e49ee43be74da008aa3052cf2a7e6da Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 13:38:29 -0800 Subject: [PATCH 63/69] vi2uc, etc. should apply the D prefix as float. So say tests on an actual PSP. --- Core/MIPS/MIPSIntVFPU.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index d66f336308..d91aceb8e2 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -856,7 +856,7 @@ namespace MIPSInt _dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted"); break; } - ApplyPrefixD((float*)d,oz,true); + ApplyPrefixD((float*)d,oz); WriteVector((float*)d,oz,vd); PC += 4; EatPrefixes(); From d89a32e99f5440335f533559db6f1ae09351a9ff Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 14:37:53 -0800 Subject: [PATCH 64/69] Mark a bunch of VFPU functions which eat prefixes. --- Core/MIPS/MIPSIntVFPU.cpp | 3 +- Core/MIPS/MIPSTables.cpp | 80 +++++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index d91aceb8e2..f823a70a2a 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -722,7 +722,7 @@ namespace MIPSInt void Int_Vx2i(u32 op) { int s[4]; - u32 d[4] = {0}; + u32 d[4] = {0}; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); @@ -1205,6 +1205,7 @@ namespace MIPSInt int seed = VI(vd); currentMIPS->rng.Init(seed); PC += 4; + EatPrefixes(); } void Int_VrndX(u32 op) diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 3d42889125..4be8f58ce7 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -516,7 +516,7 @@ const MIPSInstruction tableVFPU4Jump[32] = //110100 xxxxx {VFPU4}, {VFPU7}, {VFPU9}, - INSTR("vcst", &Jit::Comp_Generic, Dis_Vcst, Int_Vcst, IS_VFPU), + INSTR("vcst", &Jit::Comp_Generic, Dis_Vcst, Int_Vcst, IS_VFPU|OUT_EAT_PREFIX), {-2},{-2},{-2},{-2}, //8 @@ -524,12 +524,12 @@ const MIPSInstruction tableVFPU4Jump[32] = //110100 xxxxx {-2},{-2},{-2},{-2}, //16 - INSTR("vf2in", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU), - INSTR("vf2iz", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU), - INSTR("vf2iu", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU), - INSTR("vf2id", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU), + INSTR("vf2in", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vf2iz", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vf2iu", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vf2id", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX), //20 - INSTR("vi2f", &Jit::Comp_Generic, Dis_Vf2i, Int_Vi2f, IS_VFPU), + INSTR("vi2f", &Jit::Comp_Generic, Dis_Vf2i, Int_Vi2f, IS_VFPU|OUT_EAT_PREFIX), INSTR("vcmov", &Jit::Comp_Generic, Dis_Vcmov,Int_Vcmov,IS_VFPU), {-2}, {-2}, @@ -546,10 +546,10 @@ const MIPSInstruction tableVFPU4Jump[32] = //110100 xxxxx const MIPSInstruction tableVFPU7[32] = { - INSTR("vrnds", &Jit::Comp_Generic, Dis_Generic, Int_Vrnds, IS_VFPU), - INSTR("vrndi", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU), - INSTR("vrndf1", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU), - INSTR("vrndf2", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU), + INSTR("vrnds", &Jit::Comp_Generic, Dis_Generic, Int_Vrnds, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vrndi", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vrndf1", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vrndf2", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU|OUT_EAT_PREFIX), {-2},{-2},{-2},{-2}, //8 @@ -559,8 +559,8 @@ const MIPSInstruction tableVFPU7[32] = //16 {-2}, {-2}, - INSTR("vf2h", &Jit::Comp_Generic, Dis_Generic, Int_Vf2h, IS_VFPU), - INSTR("vh2f", &Jit::Comp_Generic, Dis_Generic, Int_Vh2f, IS_VFPU), + INSTR("vf2h", &Jit::Comp_Generic, Dis_Generic, Int_Vf2h, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vh2f", &Jit::Comp_Generic, Dis_Generic, Int_Vh2f, IS_VFPU|OUT_EAT_PREFIX), {-2}, {-2}, @@ -572,10 +572,10 @@ const MIPSInstruction tableVFPU7[32] = INSTR("vus2i", &Jit::Comp_Generic, Dis_Vs2i, Int_Vx2i, IS_VFPU), INSTR("vs2i", &Jit::Comp_Generic, Dis_Vs2i, Int_Vx2i, IS_VFPU), - INSTR("vi2uc", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU), - INSTR("vi2c", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU), - INSTR("vi2us", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU), - INSTR("vi2s", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU), + INSTR("vi2uc", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vi2c", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vi2us", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vi2s", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU|OUT_EAT_PREFIX), }; // 110100 00000 10100 0000000000000000 @@ -585,11 +585,11 @@ const MIPSInstruction tableVFPU4[32] = //110100 00000 xxxxx INSTR("vmov", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), INSTR("vabs", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), INSTR("vneg", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU|OUT_EAT_PREFIX), - INSTR("vidt", &Jit::Comp_Generic, Dis_VectorSet1, Int_Vidt,IS_VFPU), + INSTR("vidt", &Jit::Comp_Generic, Dis_VectorSet1, Int_Vidt,IS_VFPU|OUT_EAT_PREFIX), INSTR("vsat0", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), INSTR("vsat1", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU|OUT_EAT_PREFIX), - INSTR("vzero", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU), - INSTR("vone", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU), + INSTR("vzero", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vone", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU|OUT_EAT_PREFIX), //8 {-2},{-2},{-2},{-2},{-2},{-2},{-2},{-2}, //16 @@ -626,25 +626,25 @@ MIPSInstruction tableVFPU5[8] = //110111 xxx const MIPSInstruction tableVFPU6[32] = //111100 xxx { //0 - INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU), - INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU), - INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU), - INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU), + INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), + INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), //8 - INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), + INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), - INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), - INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU), + INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), + INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), //16 INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU), INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU), @@ -662,22 +662,22 @@ const MIPSInstruction tableVFPU6[32] = //111100 xxx {-2}, {VFPUMatrix1}, - INSTR("vrot",&Jit::Comp_Generic, Dis_VRot, Int_Vrot, IS_VFPU), + INSTR("vrot",&Jit::Comp_Generic, Dis_VRot, Int_Vrot, IS_VFPU|OUT_EAT_PREFIX), {-2}, {-2}, }; const MIPSInstruction tableVFPUMatrixSet1[16] = //111100 11100 0xxxx (rm x is 16) { - INSTR("vmmov",&Jit::Comp_Generic, Dis_MatrixSet2, Int_Vmmov, IS_VFPU), + INSTR("vmmov",&Jit::Comp_Generic, Dis_MatrixSet2, Int_Vmmov, IS_VFPU|OUT_EAT_PREFIX), {-2}, {-2}, - INSTR("vmidt",&Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU), + INSTR("vmidt",&Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU|OUT_EAT_PREFIX), {-2}, {-2}, - INSTR("vmzero", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU), - INSTR("vmone", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU), + INSTR("vmzero", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmone", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU|OUT_EAT_PREFIX), {-2},{-2},{-2},{-2}, {-2},{-2},{-2},{-2}, From 653443070dfef504fedd91035025dbe56dceae5b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Feb 2013 15:13:46 -0800 Subject: [PATCH 65/69] Add a few more OUT_EAT_PREFIX flags to VFPU. --- Core/MIPS/MIPSTables.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 4be8f58ce7..821fd72c90 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -500,14 +500,14 @@ const MIPSInstruction tableVFPU1[8] = const MIPSInstruction tableVFPU3[8] = //011011 xxx { - INSTR("vcmp",&Jit::Comp_Generic, Dis_Vcmp, Int_Vcmp, IS_VFPU), + INSTR("vcmp",&Jit::Comp_Generic, Dis_Vcmp, Int_Vcmp, IS_VFPU|OUT_EAT_PREFIX), {-2}, INSTR("vmin",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU|OUT_EAT_PREFIX), - INSTR("vmax",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmax",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU|OUT_EAT_PREFIX), {-2}, - INSTR("vscmp",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vscmp, IS_VFPU), - INSTR("vsge",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsge, IS_VFPU), - INSTR("vslt",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vslt, IS_VFPU), + INSTR("vscmp",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vscmp, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vsge",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsge, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vslt",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vslt, IS_VFPU|OUT_EAT_PREFIX), }; @@ -530,7 +530,7 @@ const MIPSInstruction tableVFPU4Jump[32] = //110100 xxxxx INSTR("vf2id", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU|OUT_EAT_PREFIX), //20 INSTR("vi2f", &Jit::Comp_Generic, Dis_Vf2i, Int_Vi2f, IS_VFPU|OUT_EAT_PREFIX), - INSTR("vcmov", &Jit::Comp_Generic, Dis_Vcmov,Int_Vcmov,IS_VFPU), + INSTR("vcmov", &Jit::Comp_Generic, Dis_Vcmov,Int_Vcmov,IS_VFPU|OUT_EAT_PREFIX), {-2}, {-2}, @@ -646,10 +646,10 @@ const MIPSInstruction tableVFPU6[32] = //111100 xxx INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU|OUT_EAT_PREFIX), //16 - INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU), - INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU), - INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU), - INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU), + INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU|OUT_EAT_PREFIX), INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX), INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU|OUT_EAT_PREFIX), @@ -687,12 +687,12 @@ const MIPSInstruction tableVFPU9[32] = //110100 00010 xxxxx { INSTR("vsrt1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt1, IS_VFPU), INSTR("vsrt2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt2, IS_VFPU), - INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU), - INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU), + INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU|OUT_EAT_PREFIX), //4 INSTR("vocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vocp, IS_VFPU), // one's complement INSTR("vsocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsocp, IS_VFPU), - INSTR("vfad", &Jit::Comp_Generic, Dis_Vfad, Int_Vfad, IS_VFPU), + INSTR("vfad", &Jit::Comp_Generic, Dis_Vfad, Int_Vfad, IS_VFPU|OUT_EAT_PREFIX), INSTR("vavg", &Jit::Comp_Generic, Dis_Vfad, Int_Vavg, IS_VFPU), //8 INSTR("vsrt3", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt3, IS_VFPU), From f8058e4bae8393336499623813b52bd96cd81017 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 18 Feb 2013 23:22:41 +0100 Subject: [PATCH 66/69] Disable warning for bad prefix as it floods in Wipeout Pulse. Cleanups. --- Core/MIPS/MIPSIntVFPU.cpp | 2 +- GPU/GLES/DisplayListInterpreter.cpp | 4 ++-- android/jni/EmuScreen.cpp | 2 +- native | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index f823a70a2a..90b3fbface 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -1185,7 +1185,7 @@ namespace MIPSInt float scale = V(vt); if (currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX] != 0xE4) { - WARN_LOG(CPU, "Broken T prefix used with VScl: %08x / %08x", currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX], op); + // WARN_LOG(CPU, "Broken T prefix used with VScl: %08x / %08x", currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX], op); ApplySwizzleT(&scale, V_Single); } int n = GetNumVectorElements(sz); diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index e9f1bb7854..6bf4220d86 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -38,7 +38,7 @@ extern u32 curTextureWidth; extern u32 curTextureHeight; -static const int flushOnChangedBeforeCommandList[] = { +static const u8 flushOnChangedBeforeCommandList[] = { GE_CMD_VERTEXTYPE, GE_CMD_BLENDMODE, GE_CMD_BLENDFIXEDA, @@ -137,7 +137,7 @@ static const int flushOnChangedBeforeCommandList[] = { GE_CMD_ZBUFWIDTH, }; -static const int flushBeforeCommandList[] = { +static const u8 flushBeforeCommandList[] = { GE_CMD_BEZIER, GE_CMD_SPLINE, GE_CMD_SIGNAL, diff --git a/android/jni/EmuScreen.cpp b/android/jni/EmuScreen.cpp index b3eb28e4fb..8a0d13f84e 100644 --- a/android/jni/EmuScreen.cpp +++ b/android/jni/EmuScreen.cpp @@ -156,7 +156,7 @@ void EmuScreen::render() // We just run the CPU until we get to vblank. This will quickly sync up pretty nicely. // The actual number of cycles doesn't matter so much here as we will break due to CORE_NEXTFRAME, most of the time hopefully... - int blockTicks = usToCycles(1000000 / 2); + int blockTicks = usToCycles(1000000 / 10); // Run until CORE_NEXTFRAME while (coreState == CORE_RUNNING) { diff --git a/native b/native index f7db8ff0be..f5e7bd5a9c 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit f7db8ff0bea971ed6c1332ce746101d3f0146010 +Subproject commit f5e7bd5a9c3e4b39a4eac71b577f06ad54f2bc96 From cbb786c7f02270eb80a1949650d236ec21ca2819 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 18 Feb 2013 23:25:06 +0100 Subject: [PATCH 67/69] Restructure Windows "gameloop" to be more similar to others. --- Core/Core.cpp | 14 ++- Core/HLE/sceDisplay.cpp | 195 ++++++++++++++++++------------- Core/Host.h | 1 - Windows/OpenGLBase.cpp | 9 +- Windows/OpenGLBase.h | 5 +- Windows/WindowsHost.cpp | 5 - Windows/WindowsHost.h | 1 - android/jni/NativeApp.cpp | 1 - headless/Headless.cpp | 20 ++-- headless/StubHost.h | 6 +- headless/WindowsHeadlessHost.cpp | 4 +- headless/WindowsHeadlessHost.h | 3 +- 12 files changed, 150 insertions(+), 114 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index fb8f92966c..c2de39e787 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -22,6 +22,9 @@ #include "Core.h" #include "MemMap.h" #include "MIPS/MIPS.h" +#ifdef _WIN32 +#include "Windows/OpenGLBase.h" +#endif #include "Host.h" @@ -64,7 +67,16 @@ bool Core_IsStepping() void Core_RunLoop() { - currentMIPS->RunLoopUntil(0xFFFFFFFFFFFFFFFULL); + while (!coreState) { + currentMIPS->RunLoopUntil(0xFFFFFFFFFFFFFFFULL); + if (coreState == CORE_NEXTFRAME) + { +#ifdef _WIN32 + GL_SwapBuffers(); +#endif + coreState = CORE_RUNNING; + } + } } void Core_DoSingleStep() diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 86bf36750a..ed552dcbaa 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -80,6 +80,7 @@ static bool framebufIsLatched; static int enterVblankEvent = -1; static int leaveVblankEvent = -1; +static int afterFlipEvent = -1; static int hCount; static int hCountTotal; //unused @@ -107,6 +108,7 @@ enum { void hleEnterVblank(u64 userdata, int cyclesLate); void hleLeaveVblank(u64 userdata, int cyclesLate); +void hleAfterFlip(u64 userdata, int cyclesLate); void __DisplayInit() { gpuStats.reset(); @@ -118,6 +120,7 @@ void __DisplayInit() { enterVblankEvent = CoreTiming::RegisterEvent("EnterVBlank", &hleEnterVblank); leaveVblankEvent = CoreTiming::RegisterEvent("LeaveVBlank", &hleLeaveVblank); + afterFlipEvent = CoreTiming::RegisterEvent("AfterFlip", &hleAfterFlip); CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs), enterVblankEvent, 0); isVblank = 0; @@ -202,6 +205,93 @@ float calculateFPS() return fps; } +void DebugStats() +{ + gpu->UpdateStats(); + char stats[2048]; + + sprintf(stats, + "Frames: %i\n" + "DL processing time: %0.2f ms\n" + "Kernel processing time: %0.2f ms\n" + "Slowest syscall: %s : %0.2f ms\n" + "Most active syscall: %s : %0.2f ms\n" + "Draw calls: %i, flushes %i\n" + "Cached Draw calls: %i\n" + "Num Tracked Vertex Arrays: %i\n" + "Vertices Submitted: %i\n" + "Cached Vertices Drawn: %i\n" + "Uncached Vertices Drawn: %i\n" + "FBOs active: %i\n" + "Textures active: %i, decoded: %i\n" + "Texture invalidations: %i\n" + "Vertex shaders loaded: %i\n" + "Fragment shaders loaded: %i\n" + "Combined shaders loaded: %i\n", + gpuStats.numFrames, + gpuStats.msProcessingDisplayLists * 1000.0f, + kernelStats.msInSyscalls * 1000.0f, + kernelStats.slowestSyscallName ? kernelStats.slowestSyscallName : "(none)", + kernelStats.slowestSyscallTime * 1000.0f, + kernelStats.summedSlowestSyscallName ? kernelStats.summedSlowestSyscallName : "(none)", + kernelStats.summedSlowestSyscallTime * 1000.0f, + gpuStats.numDrawCalls, + gpuStats.numFlushes, + gpuStats.numCachedDrawCalls, + gpuStats.numTrackedVertexArrays, + gpuStats.numVertsSubmitted, + gpuStats.numCachedVertsDrawn, + gpuStats.numUncachedVertsDrawn, + gpuStats.numFBOs, + gpuStats.numTextures, + gpuStats.numTexturesDecoded, + gpuStats.numTextureInvalidations, + gpuStats.numVertexShaders, + gpuStats.numFragmentShaders, + gpuStats.numShaders + ); + + float zoom = 0.3f; /// g_Config.iWindowZoom; + float soff = 0.3f; + PPGeBegin(); + PPGeDrawText(stats, soff, soff, 0, zoom, 0xCC000000); + PPGeDrawText(stats, -soff, -soff, 0, zoom, 0xCC000000); + PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFFFFFFF); + PPGeEnd(); + + gpuStats.resetFrame(); + kernelStats.ResetFrame(); +} + +// Let's collect all the throttling and frameskipping logic here. +void DoFrameTiming(bool &throttle) { +#ifdef _WIN32 + throttle = !GetAsyncKeyState(VK_TAB); +#else + throttle = false; +#endif + if (PSP_CoreParameter().headLess) + throttle = false; + + if (throttle) { + // Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it. + time_update(); + if (lastFrameTime == 0.0) + lastFrameTime = time_now_d(); + + // First, check if we are already behind. + // Wait until it's time. + while (time_now_d() < lastFrameTime + 1.0 / 60.0) { + Common::SleepCurrentThread(1); + time_update(); + } + // Advance lastFrameTime by a constant amount each frame, + // but don't let it get too far behind. + lastFrameTime = std::max(lastFrameTime + 1.0 / 60.0, time_now_d() - 1.5 / 60.0); + } +} + + void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; @@ -223,7 +313,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { // Trigger VBlank interrupt handlers. __TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL); - CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount+1); + CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount + 1); // TODO: Should this be done here or in hleLeaveVblank? if (framebufIsLatched) { @@ -233,65 +323,11 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat); } - // Draw screen overlays before blitting. Saves and restores the Ge context. gpuStats.numFrames++; // Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc. if (g_Config.bShowDebugStats && gpuStats.numDrawCalls) { - gpu->UpdateStats(); - char stats[2048]; - - sprintf(stats, - "Frames: %i\n" - "DL processing time: %0.2f ms\n" - "Kernel processing time: %0.2f ms\n" - "Slowest syscall: %s : %0.2f ms\n" - "Most active syscall: %s : %0.2f ms\n" - "Draw calls: %i, flushes %i\n" - "Cached Draw calls: %i\n" - "Num Tracked Vertex Arrays: %i\n" - "Vertices Submitted: %i\n" - "Cached Vertices Drawn: %i\n" - "Uncached Vertices Drawn: %i\n" - "FBOs active: %i\n" - "Textures active: %i, decoded: %i\n" - "Texture invalidations: %i\n" - "Vertex shaders loaded: %i\n" - "Fragment shaders loaded: %i\n" - "Combined shaders loaded: %i\n", - gpuStats.numFrames, - gpuStats.msProcessingDisplayLists * 1000.0f, - kernelStats.msInSyscalls * 1000.0f, - kernelStats.slowestSyscallName ? kernelStats.slowestSyscallName : "(none)", - kernelStats.slowestSyscallTime * 1000.0f, - kernelStats.summedSlowestSyscallName ? kernelStats.summedSlowestSyscallName : "(none)", - kernelStats.summedSlowestSyscallTime * 1000.0f, - gpuStats.numDrawCalls, - gpuStats.numFlushes, - gpuStats.numCachedDrawCalls, - gpuStats.numTrackedVertexArrays, - gpuStats.numVertsSubmitted, - gpuStats.numCachedVertsDrawn, - gpuStats.numUncachedVertsDrawn, - gpuStats.numFBOs, - gpuStats.numTextures, - gpuStats.numTexturesDecoded, - gpuStats.numTextureInvalidations, - gpuStats.numVertexShaders, - gpuStats.numFragmentShaders, - gpuStats.numShaders - ); - - float zoom = 0.3f; /// g_Config.iWindowZoom; - float soff = 0.3f; - PPGeBegin(); - PPGeDrawText(stats, soff, soff, 0, zoom, 0xCC000000); - PPGeDrawText(stats, -soff, -soff, 0, zoom, 0xCC000000); - PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFFFFFFF); - PPGeEnd(); - - gpuStats.resetFrame(); - kernelStats.ResetFrame(); + DebugStats(); } if (g_Config.bShowFPSCounter) { @@ -313,41 +349,32 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { PPGeEnd(); } + // Draw screen overlays before blitting. Saves and restores the Ge context. // Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity // to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have // anything to draw here. gpu->CopyDisplayToOutput(); - host->EndFrame(); + bool throttle; + + DoFrameTiming(throttle); -#ifdef _WIN32 - // Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it. - time_update(); - if (lastFrameTime == 0.0) - lastFrameTime = time_now_d(); - if (!GetAsyncKeyState(VK_TAB) && !PSP_CoreParameter().headLess) { - while (time_now_d() < lastFrameTime + 1.0 / 60.0) { - Common::SleepCurrentThread(1); - time_update(); - } - // Advance lastFrameTime by a constant amount each frame, - // but don't let it get too far behind. - lastFrameTime = std::max(lastFrameTime + 1.0 / 60.0, time_now_d() - 1.5 / 60.0); - } - - // We are going to have to do something about audio timing for platforms that - // are vsynced to something that's not exactly 60fps.. - -#endif - - host->BeginFrame(); - gpu->BeginFrame(); - - // Tell the emu core that it's time to stop emulating - // Win32 doesn't need this. -#ifndef _WIN32 + // Setting CORE_NEXTFRAME causes a swap. coreState = CORE_NEXTFRAME; -#endif + + CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); + + // Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame). + // Right after, we regain control for a little bit in hleAfterFlip. I think that's a great + // place to do housekeeping. +} + +void hleAfterFlip(u64 userdata, int cyclesLate) +{ + // This checks input on PC. Fine to do even if not calling BeginFrame. + host->BeginFrame(); + + gpu->BeginFrame(); // doesn't really matter if begin or end of frame. } void hleLeaveVblank(u64 userdata, int cyclesLate) { diff --git a/Core/Host.h b/Core/Host.h index c60d270a66..01573a1e65 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -46,7 +46,6 @@ public: virtual void InitGL() = 0; virtual void BeginFrame() {} - virtual void EndFrame() {} virtual void ShutdownGL() = 0; virtual void InitSound(PMixer *mixer) = 0; diff --git a/Windows/OpenGLBase.cpp b/Windows/OpenGLBase.cpp index f739dcab1e..92d4af4c14 100644 --- a/Windows/OpenGLBase.cpp +++ b/Windows/OpenGLBase.cpp @@ -49,14 +49,7 @@ void GL_Resized() // Resize And Initialize The GL Window glstate.viewport.restore(); } - -void GL_BeginFrame() -{ - -} - - -void GL_EndFrame() +void GL_SwapBuffers() { SwapBuffers(hDC); } diff --git a/Windows/OpenGLBase.h b/Windows/OpenGLBase.h index 50a154089f..b26ed0ebfd 100644 --- a/Windows/OpenGLBase.h +++ b/Windows/OpenGLBase.h @@ -2,9 +2,10 @@ #pragma once +#define WIN32_LEAN_AND_MEAN +#include bool GL_Init(HWND window); void GL_Shutdown(); void GL_Resized(); -void GL_BeginFrame(); -void GL_EndFrame(); +void GL_SwapBuffers(); diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index f7afab484f..cef4e558e6 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -117,11 +117,6 @@ void WindowsHost::BeginFrame() for (auto iter = this->input.begin(); iter != this->input.end(); iter++) if ((*iter)->UpdateState() == 0) break; // *iter is std::shared_ptr, **iter is InputDevice - GL_BeginFrame(); -} -void WindowsHost::EndFrame() -{ - GL_EndFrame(); } void WindowsHost::BootDone() diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index c46c888543..923acf10b8 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -21,7 +21,6 @@ public: void InitGL(); void BeginFrame(); - void EndFrame(); void ShutdownGL(); void InitSound(PMixer *mixer); diff --git a/android/jni/NativeApp.cpp b/android/jni/NativeApp.cpp index 7bde05e9d2..786d51b9b7 100644 --- a/android/jni/NativeApp.cpp +++ b/android/jni/NativeApp.cpp @@ -101,7 +101,6 @@ public: virtual void InitGL() {} virtual void BeginFrame() {} - virtual void EndFrame() {} virtual void ShutdownGL() {} virtual void InitSound(PMixer *mixer); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 7129523f43..d9289c8cba 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -4,12 +4,13 @@ #include -#include "../Core/Config.h" -#include "../Core/Core.h" -#include "../Core/CoreTiming.h" -#include "../Core/System.h" -#include "../Core/MIPS/MIPS.h" -#include "../Core/Host.h" +#include "Core/Config.h" +#include "Core/Core.h" +#include "Core/CoreTiming.h" +#include "Core/System.h" +#include "Core/MIPS/MIPS.h" +#include "Core/Host.h" +#include "Windows/OpenGLBase.h" #include "Log.h" #include "LogManager.h" @@ -46,6 +47,9 @@ public: } }; +// Temporary hack around annoying linking error. +void GL_SwapBuffers() { } + void printUsage(const char *progname, const char *reason) { if (reason != NULL) @@ -192,8 +196,10 @@ int main(int argc, const char* argv[]) mipsr4k.RunLoopUntil(nowTicks + frameTicks); // If we were rendering, this might be a nice time to do something about it. - if (coreState == CORE_NEXTFRAME) + if (coreState == CORE_NEXTFRAME) { + headlessHost->SwapBuffers(); coreState = CORE_RUNNING; + } } host->ShutdownGL(); diff --git a/headless/StubHost.h b/headless/StubHost.h index 1533c381c3..19e71c3b68 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -35,7 +35,6 @@ public: virtual void InitGL() {} virtual void BeginFrame() {} - virtual void EndFrame() {} virtual void ShutdownGL() {} virtual void InitSound(PMixer *mixer) {} @@ -53,4 +52,9 @@ public: virtual void SetComparisonScreenshot(const std::string &filename) {} virtual bool isGLWorking() { return false; } + + + // Unique for HeadlessHost + virtual void SwapBuffers() {} + }; \ No newline at end of file diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index 5e7448ae23..a6629982f2 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -218,7 +218,7 @@ void WindowsHeadlessHost::BeginFrame() } -void WindowsHeadlessHost::EndFrame() +void WindowsHeadlessHost::SwapBuffers() { - SwapBuffers(hDC); + ::SwapBuffers(hDC); } diff --git a/headless/WindowsHeadlessHost.h b/headless/WindowsHeadlessHost.h index 5abc20ca05..d624f4d3cc 100644 --- a/headless/WindowsHeadlessHost.h +++ b/headless/WindowsHeadlessHost.h @@ -30,10 +30,11 @@ class WindowsHeadlessHost : public HeadlessHost public: virtual void InitGL(); virtual void BeginFrame(); - virtual void EndFrame(); virtual void ShutdownGL(); virtual bool isGLWorking() { return glOkay; } + virtual void SwapBuffers(); + virtual void SendDebugOutput(const std::string &output); virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h); virtual void SetComparisonScreenshot(const std::string &filename); From 7c91802e3cc32e17f914ea11c59ce84a52b842b7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 18 Feb 2013 23:44:32 +0100 Subject: [PATCH 68/69] Add some infrastructure to be used for frameskipping --- Core/HLE/sceDisplay.cpp | 29 ++++++++++++++++++++++------- GPU/GLES/DisplayListInterpreter.cpp | 3 +++ GPU/GLES/DisplayListInterpreter.h | 1 - GPU/GPUState.h | 8 +++++++- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index ed552dcbaa..9ec7d75303 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -86,6 +86,7 @@ static int hCount; static int hCountTotal; //unused static int vCount; static int isVblank; +static int numSkippedFrames; static bool hasSetMode; // Don't include this in the state, time increases regardless of state. static double lastFrameTime; @@ -113,6 +114,7 @@ void hleAfterFlip(u64 userdata, int cyclesLate); void __DisplayInit() { gpuStats.reset(); hasSetMode = false; + numSkippedFrames = 0; framebufIsLatched = false; framebuf.topaddr = 0x04000000; framebuf.pspFramebufFormat = PSP_DISPLAY_PIXEL_FORMAT_8888; @@ -264,12 +266,15 @@ void DebugStats() } // Let's collect all the throttling and frameskipping logic here. -void DoFrameTiming(bool &throttle) { +void DoFrameTiming(bool &throttle, bool &skipFrame, bool &skipFlip) { #ifdef _WIN32 throttle = !GetAsyncKeyState(VK_TAB); #else throttle = false; #endif + skipFlip = false; + skipFrame = false; + if (PSP_CoreParameter().headLess) throttle = false; @@ -353,16 +358,26 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { // Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity // to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have // anything to draw here. - gpu->CopyDisplayToOutput(); + gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME; - bool throttle; + bool throttle, skipFrame, skipFlip; - DoFrameTiming(throttle); + DoFrameTiming(throttle, skipFrame, skipFlip); // Setting CORE_NEXTFRAME causes a swap. - coreState = CORE_NEXTFRAME; - - CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); + if (skipFrame) { + gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME; + numSkippedFrames++; + } else { + numSkippedFrames = 0; + } + + if (!skipFlip) { + coreState = CORE_NEXTFRAME; + CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); + + gpu->CopyDisplayToOutput(); + } // Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame). // Right after, we regain control for a little bit in hleAfterFlip. I think that's a great diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 6bf4220d86..cde737fedd 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -330,6 +330,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_PRIM: { + if (gstate_c.skipDrawReason) + return; + framebufferManager_.SetRenderFrameBuffer(); u32 count = data & 0xFFFF; diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 52e1883730..048aab400b 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -64,7 +64,6 @@ public: return textureCache_.DecodeTexture(dest, state); } - std::vector GetFramebufferList(); private: diff --git a/GPU/GPUState.h b/GPU/GPUState.h index ca036b2506..8f12c7d045 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -224,7 +224,11 @@ struct GPUgstate // Real data in the context ends here }; - + +enum SkipDrawReasonFlags { + SKIPDRAW_SKIPFRAME = 1, +}; + // The rest is cached simplified/converted data for fast access. // Does not need to be saved when saving/restoring context. struct GPUStateCache @@ -236,6 +240,8 @@ struct GPUStateCache bool textureChanged; + int skipDrawReason; + float uScale,vScale; float uOff,vOff; bool flipTexture; From 1aa3a657c01c42f38f51b9594af5de3f5e911223 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 19 Feb 2013 00:44:22 +0100 Subject: [PATCH 69/69] Very rough and basic implementation of frameskipping. --- Core/Config.cpp | 2 + Core/Config.h | 1 + Core/HLE/sceDisplay.cpp | 69 ++++++++++++++++++++++++--------- Windows/PPSSPP.vcxproj.filters | 4 +- Windows/WndMainWindow.cpp | 9 ++++- Windows/ppsspp.rc | Bin 56832 -> 56972 bytes Windows/resource.h | 3 +- android/jni/MenuScreens.cpp | 3 ++ 8 files changed, 69 insertions(+), 22 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index fc5019750c..fd22d7b7df 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -68,6 +68,7 @@ void CConfig::Load(const char *iniFileName) graphics->Get("LinearFiltering", &bLinearFiltering, false); graphics->Get("SSAA", &SSAntiAliasing, 0); graphics->Get("VBO", &bUseVBO, false); + graphics->Get("FrameSkip", &iFrameSkip, 0); #ifdef USING_GLES2 graphics->Get("AnisotropyLevel", &iAnisotropyLevel, 0); #else @@ -131,6 +132,7 @@ void CConfig::Save() graphics->Set("LinearFiltering", bLinearFiltering); graphics->Set("SSAA", SSAntiAliasing); graphics->Set("VBO", bUseVBO); + graphics->Set("FrameSkip", iFrameSkip); graphics->Set("AnisotropyLevel", iAnisotropyLevel); graphics->Set("DisableG3DLog", bDisableG3DLog); graphics->Set("VertexCache", bVertexCache); diff --git a/Core/Config.h b/Core/Config.h index 93554eeeb4..d39325cc4e 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -59,6 +59,7 @@ public: bool bLinearFiltering; bool bUseVBO; bool bStretchToDisplay; + int iFrameSkip; // 0 = off; 1 = auto; (future: 2 = skip every 2nd frame; 3 = skip every 3rd frame etc). int iWindowZoom; // for Windows bool SSAntiAliasing; //for Windows, too diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 9ec7d75303..46b297a928 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -89,7 +89,8 @@ static int isVblank; static int numSkippedFrames; static bool hasSetMode; // Don't include this in the state, time increases regardless of state. -static double lastFrameTime; +static double curFrameTime; +static double nextFrameTime; std::vector vblankWaitingThreads; @@ -129,7 +130,8 @@ void __DisplayInit() { vCount = 0; hCount = 0; hCountTotal = 0; - lastFrameTime = 0; + curFrameTime = 0.0; + nextFrameTime = 0.0; InitGfxState(); } @@ -191,7 +193,7 @@ float calculateFPS() static int lastFpsFrame = 0; static double lastFpsTime = 0.0; static double fps = 0.0; - + time_update(); double now = time_now_d(); @@ -274,25 +276,56 @@ void DoFrameTiming(bool &throttle, bool &skipFrame, bool &skipFlip) { #endif skipFlip = false; skipFrame = false; - if (PSP_CoreParameter().headLess) throttle = false; - if (throttle) { - // Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it. - time_update(); - if (lastFrameTime == 0.0) - lastFrameTime = time_now_d(); - - // First, check if we are already behind. - // Wait until it's time. - while (time_now_d() < lastFrameTime + 1.0 / 60.0) { - Common::SleepCurrentThread(1); - time_update(); + // Check if the frameskipping code should be enabled. If neither throttling or frameskipping is on, + // we have nothing to do here. + bool doFrameSkip = g_Config.iFrameSkip == 1; + if (!throttle && !doFrameSkip) + return; + + time_update(); + + curFrameTime = time_now_d(); + if (nextFrameTime == 0.0) + nextFrameTime = time_now_d() + 1.0 / 60.0; + + if (curFrameTime > nextFrameTime && doFrameSkip) { + // Argh, we are falling behind! Let's skip a frame and see if we catch up. + skipFrame = true; + skipFlip = true; + INFO_LOG(HLE,"FRAMESKIP %i", numSkippedFrames); + } + + if (curFrameTime < nextFrameTime && throttle) + { + // If time gap is huge just jump (somebody unthrottled) + if (nextFrameTime - curFrameTime > 1.0 / 30.0) { + nextFrameTime = curFrameTime + 1.0 / 60.0; + } else { + // Wait until we've catched up. + while (time_now_d() < nextFrameTime) { + Common::SleepCurrentThread(1); + time_update(); + } } - // Advance lastFrameTime by a constant amount each frame, - // but don't let it get too far behind. - lastFrameTime = std::max(lastFrameTime + 1.0 / 60.0, time_now_d() - 1.5 / 60.0); + curFrameTime = time_now_d(); + } + // Advance lastFrameTime by a constant amount each frame, + // but don't let it get too far behind as things can get very jumpy. + const double maxFallBehindFrames = 5.5; + + if (throttle || doFrameSkip) { + nextFrameTime = std::max(nextFrameTime + 1.0 / 60.0, time_now_d() - maxFallBehindFrames / 60.0); + } else { + nextFrameTime = nextFrameTime + 1.0 / 60.0; + } + + // Max 6 skipped frames in a row - 10 fps is really the bare minimum for playability. + if (numSkippedFrames >= 4) { + skipFrame = false; + skipFlip = false; } } diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index d2538d562b..6c0a8b3408 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -209,10 +209,12 @@ Android - Android + + Windows + diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 2f3b07e531..b97678aad5 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -73,8 +73,7 @@ namespace MainWindow void Init(HINSTANCE hInstance) { -#ifdef THEMES - WTL::CTheme::IsThemingSupported(); +#ifdef THEMES WTL::CTheme::IsThemingSupported(); #endif //Register classes WNDCLASSEX wcex; @@ -447,6 +446,11 @@ namespace MainWindow gpu->Resized(); // easy way to force a clear... break; + case ID_OPTIONS_FRAMESKIP: + g_Config.iFrameSkip = !g_Config.iFrameSkip; + UpdateMenus(); + break; + case ID_FILE_EXIT: DestroyWindow(hWnd); break; @@ -712,6 +716,7 @@ namespace MainWindow CHECKITEM(ID_OPTIONS_DISABLEG3DLOG, g_Config.bDisableG3DLog); CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache); CHECKITEM(ID_OPTIONS_SHOWFPS, g_Config.bShowFPSCounter); + CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != 0); UINT enable = !Core_IsStepping() ? MF_GRAYED : MF_ENABLED; EnableMenuItem(menu,ID_EMULATION_RUN, g_State.bEmuThreadStarted ? enable : MF_GRAYED); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index e0a82cd7f4231adcd17ae6abe95c146ffc5fc198..8d0a8e1004b522d9c2d97aa8a0af3f5eafb8b817 100644 GIT binary patch delta 68 zcmZqJ!`!o%d4rADe YWpHH(X7Fb4WC)ntXqUXX!mDF40IV+)Y5)KL delta 18 acmeC#%iOSsd4rAD