From 60cddf0823a05a1f4b8690e23b267bc20f5d80fc Mon Sep 17 00:00:00 2001 From: calc84maniac Date: Thu, 5 Jan 2012 18:27:04 -0500 Subject: [PATCH 01/65] Fixed some BindToRegister calls (removing unnecessary MOV instructions for speedup) --- Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index 367c7e8158..b3c38efd3a 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -1581,7 +1581,7 @@ void Jit64::rlwnmx(UGeckoInstruction inst) { gpr.FlushLockX(ECX); gpr.Lock(a, b, s); - gpr.BindToRegister(a, true, true); + gpr.BindToRegister(a, (a == b || a == s), true); MOV(32, R(ECX), gpr.R(b)); if (a != s) { @@ -1653,7 +1653,7 @@ void Jit64::srwx(UGeckoInstruction inst) { gpr.FlushLockX(ECX); gpr.Lock(a, b, s); - gpr.BindToRegister(a, true, true); + gpr.BindToRegister(a, (a == b || a == s), true); MOV(32, R(ECX), gpr.R(b)); TEST(32, R(ECX), Imm32(32)); if (a != s) @@ -1691,7 +1691,7 @@ void Jit64::slwx(UGeckoInstruction inst) { gpr.FlushLockX(ECX); gpr.Lock(a, b, s); - gpr.BindToRegister(a, true, true); + gpr.BindToRegister(a, (a == b || a == s), true); MOV(32, R(ECX), gpr.R(b)); TEST(32, R(ECX), Imm32(32)); if (a != s) @@ -1722,7 +1722,7 @@ void Jit64::srawx(UGeckoInstruction inst) int s = inst.RS; gpr.Lock(a, s, b); gpr.FlushLockX(ECX); - gpr.BindToRegister(a, true, true); + gpr.BindToRegister(a, (a == s || a == b), true); JitClearCA(); MOV(32, R(ECX), gpr.R(b)); if (a != s) From a7a6a1859e2a96ea356c9b4e6e8f5a52be604fa5 Mon Sep 17 00:00:00 2001 From: calc84maniac Date: Thu, 5 Jan 2012 19:07:31 -0500 Subject: [PATCH 02/65] subfex optimization when RD==RA --- .../Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index b3c38efd3a..4b68b32036 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -913,28 +913,31 @@ void Jit64::subfex(UGeckoInstruction inst) JitClearCAOV(inst.OE); SHR(32, R(EAX), Imm8(30)); - // Convert carry to borrow - CMC(); - + bool invertedCarry = false; if (d == b) { + // Convert carry to borrow + CMC(); SBB(32, gpr.R(d), gpr.R(a)); + invertedCarry = true; } else if (d == a) { - MOV(32, R(EAX), gpr.R(a)); - MOV(32, gpr.R(d), gpr.R(b)); - SBB(32, gpr.R(d), R(EAX)); + NOT(32, gpr.R(d)); + ADC(32, gpr.R(d), gpr.R(b)); } else { + // Convert carry to borrow + CMC(); MOV(32, gpr.R(d), gpr.R(b)); SBB(32, gpr.R(d), gpr.R(a)); + invertedCarry = true; } if (inst.Rc) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE, true); + FinalizeCarryOverflow(inst.OE, invertedCarry); gpr.UnlockAll(); } From 5a15d58964e29149634a47edae9edb887fe020d8 Mon Sep 17 00:00:00 2001 From: calc84maniac Date: Thu, 5 Jan 2012 22:36:27 -0500 Subject: [PATCH 03/65] Added emitters for BT/BTR/BTS/BTC x86 instructions, optimized extended arithmetic PowerPC instructions --- Source/Core/Common/Src/x64Emitter.cpp | 33 ++++++ Source/Core/Common/Src/x64Emitter.h | 7 ++ Source/Core/Core/Src/PowerPC/Jit64/Jit.h | 2 + .../Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 112 +++++++++++------- 4 files changed, 111 insertions(+), 43 deletions(-) diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 9acfac5864..7583ef0fc3 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -834,6 +834,39 @@ void XEmitter::SHL(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, sh void XEmitter::SHR(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, shift, 5);} void XEmitter::SAR(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, shift, 7);} +// index can be either imm8 or register, don't use memory destination because it's slow +void XEmitter::WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext) +{ + if (dest.IsImm()) + { + _assert_msg_(DYNA_REC, 0, "WriteBitTest - can't test imms"); + } + if ((index.IsImm() && index.GetImmBits() != 8)) + { + _assert_msg_(DYNA_REC, 0, "WriteBitTest - illegal argument"); + } + if (bits == 16) Write8(0x66); + if (index.IsImm()) + { + dest.WriteRex(this, bits, bits); + Write8(0x0F); Write8(0xBA); + dest.WriteRest(this, 1, (X64Reg)ext); + Write8((u8)index.offset); + } + else + { + X64Reg operand = index.GetSimpleReg(); + dest.WriteRex(this, bits, bits, operand); + Write8(0x0F); Write8(0x83 + 8*ext); + dest.WriteRest(this, 1, operand); + } +} + +void XEmitter::BT(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 4);} +void XEmitter::BTS(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 5);} +void XEmitter::BTR(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 6);} +void XEmitter::BTC(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 7);} + void OpArg::WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg _operandReg, int bits) { if (bits == 16) diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 9ffb890f54..6bd9291eea 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -249,6 +249,7 @@ private: void WriteMulDivType(int bits, OpArg src, int ext); void WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2); void WriteShift(int bits, OpArg dest, OpArg &shift, int ext); + void WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext); void WriteMXCSR(OpArg arg, int ext); void WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0); void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2); @@ -374,6 +375,12 @@ public: void SHR(int bits, OpArg dest, OpArg shift); void SAR(int bits, OpArg dest, OpArg shift); + // Bit Test + void BT(int bits, OpArg dest, OpArg index); + void BTS(int bits, OpArg dest, OpArg index); + void BTR(int bits, OpArg dest, OpArg index); + void BTC(int bits, OpArg dest, OpArg index); + // Extend EAX into EDX in various ways void CWD(int bits = 16); inline void CDQ() {CWD(32);} diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 9d9b57658b..8a13af741a 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -150,6 +150,8 @@ public: void GenerateConstantOverflow(bool overflow); void GenerateOverflow(); void FinalizeCarryOverflow(bool oe, bool inv = false); + void GetCarryEAXAndClear(); + void FinalizeCarryGenerateOverflowEAX(bool oe, bool inv = false); void GenerateCarry(); void GenerateRC(); void ComputeRC(const Gen::OpArg & arg); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index 4b68b32036..7c79fce963 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -73,13 +73,53 @@ void Jit64::FinalizeCarryOverflow(bool oe, bool inv) } else { - // Output carry is inverted + // Do carry FixupBranch carry1 = J_CC(inv ? CC_C : CC_NC); JitSetCA(); SetJumpTarget(carry1); } } +void Jit64::GetCarryEAXAndClear() +{ + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + BTR(32, R(EAX), Imm8(29)); +} + +// Assumes that XER is in EAX and that the CA bit is clear. +void Jit64::FinalizeCarryGenerateOverflowEAX(bool oe, bool inv) +{ + // USES_XER + if (oe) + { + FixupBranch jno = J_CC(CC_NO); + // Do carry + FixupBranch carry1 = J_CC(inv ? CC_C : CC_NC); + OR(32, R(EAX), Imm32(XER_CA_MASK)); + SetJumpTarget(carry1); + //XER[OV/SO] = 1 + OR(32, R(EAX), Imm32(XER_SO_MASK | XER_OV_MASK)); + FixupBranch exit = J(); + SetJumpTarget(jno); + // Do carry + FixupBranch carry2 = J_CC(inv ? CC_C : CC_NC); + JitSetCA(); + SetJumpTarget(carry2); + //XER[OV] = 0 + AND(32, R(EAX), Imm32(~XER_OV_MASK)); + SetJumpTarget(exit); + } + else + { + // Do carry + FixupBranch carry1 = J_CC(inv ? CC_C : CC_NC); + OR(32, R(EAX), Imm32(XER_CA_MASK)); + SetJumpTarget(carry1); + } + // Dump EAX back into XER + MOV(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(EAX)); +} + // Assumes that the flags were just set through an addition. void Jit64::GenerateCarry() { // USES_XER @@ -908,10 +948,7 @@ void Jit64::subfex(UGeckoInstruction inst) gpr.Lock(a, b, d); gpr.BindToRegister(d, (d == a || d == b), true); - // Get CA and clear it (along with OV if applicable) - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); + GetCarryEAXAndClear(); bool invertedCarry = false; if (d == b) @@ -928,16 +965,14 @@ void Jit64::subfex(UGeckoInstruction inst) } else { - // Convert carry to borrow - CMC(); - MOV(32, gpr.R(d), gpr.R(b)); - SBB(32, gpr.R(d), gpr.R(a)); - invertedCarry = true; + MOV(32, gpr.R(d), gpr.R(a)); + NOT(32, gpr.R(d)); + ADC(32, gpr.R(d), gpr.R(b)); } if (inst.Rc) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE, invertedCarry); + FinalizeCarryGenerateOverflowEAX(inst.OE, invertedCarry); gpr.UnlockAll(); } @@ -951,9 +986,7 @@ void Jit64::subfmex(UGeckoInstruction inst) gpr.Lock(a, d); gpr.BindToRegister(d, d == a); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + GetCarryEAXAndClear(); if (d != a) { MOV(32, gpr.R(d), gpr.R(a)); @@ -964,7 +997,7 @@ void Jit64::subfmex(UGeckoInstruction inst) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } @@ -977,9 +1010,8 @@ void Jit64::subfzex(UGeckoInstruction inst) gpr.Lock(a, d); gpr.BindToRegister(d, d == a); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + + GetCarryEAXAndClear(); if (d != a) { MOV(32, gpr.R(d), gpr.R(a)); @@ -990,7 +1022,7 @@ void Jit64::subfzex(UGeckoInstruction inst) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } @@ -1267,31 +1299,29 @@ void Jit64::addex(UGeckoInstruction inst) { gpr.Lock(a, b, d); gpr.BindToRegister(d, true); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + + GetCarryEAXAndClear(); ADC(32, gpr.R(d), gpr.R((d == a) ? b : a)); if (inst.Rc) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } else { gpr.Lock(a, b, d); gpr.BindToRegister(d, false); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + + GetCarryEAXAndClear(); MOV(32, gpr.R(d), gpr.R(a)); ADC(32, gpr.R(d), gpr.R(b)); if (inst.Rc) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } } @@ -1343,31 +1373,29 @@ void Jit64::addmex(UGeckoInstruction inst) { gpr.Lock(d); gpr.BindToRegister(d, true); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + + GetCarryEAXAndClear(); ADC(32, gpr.R(d), Imm32(0xFFFFFFFF)); if (inst.Rc) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } else { gpr.Lock(a, d); gpr.BindToRegister(d, false); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + + GetCarryEAXAndClear(); MOV(32, gpr.R(d), gpr.R(a)); ADC(32, gpr.R(d), Imm32(0xFFFFFFFF)); if (inst.Rc) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } } @@ -1383,31 +1411,29 @@ void Jit64::addzex(UGeckoInstruction inst) { gpr.Lock(d); gpr.BindToRegister(d, true); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + + GetCarryEAXAndClear(); ADC(32, gpr.R(d), Imm8(0)); if (inst.Rc) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } else { gpr.Lock(a, d); gpr.BindToRegister(d, false); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - JitClearCAOV(inst.OE); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + + GetCarryEAXAndClear(); MOV(32, gpr.R(d), gpr.R(a)); ADC(32, gpr.R(d), Imm8(0)); if (inst.Rc) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } } From 8fb1a02f6bb2eb83bfe9bfbc95eb260ca7feef4b Mon Sep 17 00:00:00 2001 From: calc84maniac Date: Thu, 5 Jan 2012 22:39:17 -0500 Subject: [PATCH 04/65] Fixed small error for instructions with overflow enabled --- Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index 7c79fce963..8df9853781 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -103,7 +103,7 @@ void Jit64::FinalizeCarryGenerateOverflowEAX(bool oe, bool inv) SetJumpTarget(jno); // Do carry FixupBranch carry2 = J_CC(inv ? CC_C : CC_NC); - JitSetCA(); + OR(32, R(EAX), Imm32(XER_CA_MASK)); SetJumpTarget(carry2); //XER[OV] = 0 AND(32, R(EAX), Imm32(~XER_OV_MASK)); From b33be736cd41292c964611385c1dc792364a1119 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 6 Jan 2012 13:45:51 +0100 Subject: [PATCH 05/65] D3D9/11: Degrade a PanicAlert related to EFB format changes to an ERROR_LOG --- Source/Plugins/Plugin_VideoDX11/Src/Render.cpp | 4 ++-- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 53cf9fd4d9..07fe88d2b5 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -748,7 +748,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8(true); else { - PanicAlert("Trying to reinterpret pixel data with unsupported conversion type %d", convtype); + ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype); return; } @@ -1428,4 +1428,4 @@ void Renderer::SetInterlacingMode() // TODO } -} // namespace DX11 \ No newline at end of file +} // namespace DX11 diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 93b37e211a..773172b0b8 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -761,7 +761,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8(); else { - PanicAlert("Trying to reinterpret pixel data with unsupported conversion type %d", convtype); + ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype); return; } From 9ab69febe546ed498f3a6831c2c8ff363a373352 Mon Sep 17 00:00:00 2001 From: nitsuja Date: Sat, 7 Jan 2012 20:46:41 -0800 Subject: [PATCH 06/65] fix for stack corruption caused by certain DSP LLE JIT ABI calls. if you were getting crashes or freezes as a result of using the "DSP LLE on Thread" option, this might fix that. --- Source/Core/Common/Src/ABI.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/Core/Common/Src/ABI.cpp b/Source/Core/Common/Src/ABI.cpp index 08e021f083..63a8e76934 100644 --- a/Source/Core/Common/Src/ABI.cpp +++ b/Source/Core/Common/Src/ABI.cpp @@ -189,7 +189,7 @@ unsigned int XEmitter::ABI_GetAlignedFrameSize(unsigned int frameSize) { #ifdef __GNUC__ (frameSize + 15) & -16; #else - frameSize; + (frameSize + 3) & -4; #endif return alignedSize; } @@ -200,16 +200,15 @@ void XEmitter::ABI_AlignStack(unsigned int frameSize) { // Linux requires the stack to be 16-byte aligned before calls that put SSE // vectors on the stack, but since we do not keep track of which calls do that, // it is effectively every call as well. -// Windows binaries compiled with MSVC do not have such a restriction, but I +// Windows binaries compiled with MSVC do not have such a restriction*, but I // expect that GCC on Windows acts the same as GCC on Linux in this respect. // It would be nice if someone could verify this. -#ifdef __GNUC__ +// *However, the MSVC optimizing compiler assumes a 4-byte-aligned stack at times. unsigned int fillSize = ABI_GetAlignedFrameSize(frameSize) - (frameSize + 4); if (fillSize != 0) { SUB(32, R(ESP), Imm8(fillSize)); } -#endif } void XEmitter::ABI_RestoreStack(unsigned int frameSize) { From 31ff1907a4718c7323acc8b8a8c59795697f6643 Mon Sep 17 00:00:00 2001 From: nitsuja Date: Fri, 23 Dec 2011 11:55:17 -0600 Subject: [PATCH 07/65] added an option to log to the attached Windows debugger (so e.g. NOTICE_LOG messages can show up in Visual Studio's output window) --- Source/Core/Common/Src/LogManager.cpp | 13 +++++ Source/Core/Common/Src/LogManager.h | 12 +++++ Source/Core/DolphinWX/Src/LogConfigWindow.cpp | 53 ++++++++++++++++++- Source/Core/DolphinWX/Src/LogConfigWindow.h | 5 +- Source/Core/DolphinWX/Src/LogWindow.cpp | 16 ++++++ Source/Core/DolphinWX/Src/LogWindow.h | 2 +- 6 files changed, 97 insertions(+), 4 deletions(-) diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp index d95e76ac5b..a79c413cf8 100644 --- a/Source/Core/Common/Src/LogManager.cpp +++ b/Source/Core/Common/Src/LogManager.cpp @@ -85,12 +85,17 @@ LogManager::LogManager() m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str()); m_consoleLog = new ConsoleListener(); + m_debuggerLog = new DebuggerLogListener(); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) { m_Log[i]->SetEnable(true); m_Log[i]->AddListener(m_fileLog); m_Log[i]->AddListener(m_consoleLog); +#ifdef _MSC_VER + if (IsDebuggerPresent()) + m_Log[i]->AddListener(m_debuggerLog); +#endif } } @@ -100,6 +105,7 @@ LogManager::~LogManager() { m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog); m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog); + m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog); } for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) @@ -187,3 +193,10 @@ void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) std::lock_guard lk(m_log_lock); m_logfile << msg << std::flush; } + +void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) +{ +#if _MSC_VER + ::OutputDebugStringA(msg); +#endif +} diff --git a/Source/Core/Common/Src/LogManager.h b/Source/Core/Common/Src/LogManager.h index 3f2b5cd168..1722c0b1bf 100644 --- a/Source/Core/Common/Src/LogManager.h +++ b/Source/Core/Common/Src/LogManager.h @@ -58,6 +58,12 @@ private: bool m_enable; }; +class DebuggerLogListener : public LogListener +{ +public: + void Log(LogTypes::LOG_LEVELS, const char *msg); +}; + class LogContainer { public: @@ -97,6 +103,7 @@ private: LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS]; FileLogListener *m_fileLog; ConsoleListener *m_consoleLog; + DebuggerLogListener *m_debuggerLog; static LogManager *m_logManager; // Singleton. Ugh. LogManager(); @@ -153,6 +160,11 @@ public: return m_consoleLog; } + DebuggerLogListener *GetDebuggerListener() const + { + return m_debuggerLog; + } + static LogManager* GetInstance() { return m_logManager; diff --git a/Source/Core/DolphinWX/Src/LogConfigWindow.cpp b/Source/Core/DolphinWX/Src/LogConfigWindow.cpp index f8219b179e..d771a75c30 100644 --- a/Source/Core/DolphinWX/Src/LogConfigWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogConfigWindow.cpp @@ -62,6 +62,14 @@ void LogConfigWindow::CreateGUIControls() _connect_macro_(m_writeConsoleCB, LogConfigWindow::OnWriteConsoleChecked, wxEVT_COMMAND_CHECKBOX_CLICKED, this); m_writeWindowCB = new wxCheckBox(this, wxID_ANY, _("Write to Window")); _connect_macro_(m_writeWindowCB, LogConfigWindow::OnWriteWindowChecked, wxEVT_COMMAND_CHECKBOX_CLICKED, this); + m_writeDebuggerCB = NULL; +#ifdef _MSC_VER + if (IsDebuggerPresent()) + { + m_writeDebuggerCB = new wxCheckBox(this, wxID_ANY, _("Write to Debugger")); + _connect_macro_(m_writeDebuggerCB, LogConfigWindow::OnWriteDebuggerChecked, wxEVT_COMMAND_CHECKBOX_CLICKED, this); + } +#endif wxButton *btn_toggle_all = new wxButton(this, wxID_ANY, _("Toggle All Log Types"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); @@ -75,7 +83,17 @@ void LogConfigWindow::CreateGUIControls() wxStaticBoxSizer* sbOutputs = new wxStaticBoxSizer(wxVERTICAL, this, _("Logger Outputs")); sbOutputs->Add(m_writeFileCB, 0, wxDOWN, 1); sbOutputs->Add(m_writeConsoleCB, 0, wxDOWN, 1); - sbOutputs->Add(m_writeWindowCB, 0); +#ifdef _MSC_VER + if (m_writeDebuggerCB) + { + sbOutputs->Add(m_writeWindowCB, 0, wxDOWN, 1); + sbOutputs->Add(m_writeDebuggerCB, 0); + } + else +#endif + { + sbOutputs->Add(m_writeWindowCB, 0); + } wxStaticBoxSizer* sbLogTypes = new wxStaticBoxSizer(wxVERTICAL, this, _("Log Types")); sbLogTypes->Add(m_checks, 1, wxEXPAND); @@ -107,6 +125,17 @@ void LogConfigWindow::LoadSettings() m_writeConsoleCB->SetValue(m_writeConsole); ini.Get("Options", "WriteToWindow", &m_writeWindow, true); m_writeWindowCB->SetValue(m_writeWindow); +#ifdef _MSC_VER + if (IsDebuggerPresent()) + { + ini.Get("Options", "WriteToDebugger", &m_writeDebugger, true); + m_writeDebuggerCB->SetValue(m_writeDebugger); + } + else +#endif + { + m_writeDebugger = false; + } for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) { bool log_enabled; @@ -125,6 +154,10 @@ void LogConfigWindow::SaveSettings() ini.Set("Options", "WriteToFile", m_writeFile); ini.Set("Options", "WriteToConsole", m_writeConsole); ini.Set("Options", "WriteToWindow", m_writeWindow); +#ifdef _MSC_VER + if (IsDebuggerPresent()) + ini.Set("Options", "WriteToDebugger", m_writeDebugger); +#endif for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) ini.Set("Logs", m_LogManager->GetShortName((LogTypes::LOG_TYPE)i), m_checks->IsChecked(i)); ini.Save(File::GetUserPath(F_LOGGERCONFIG_IDX)); @@ -183,6 +216,21 @@ void LogConfigWindow::OnWriteWindowChecked(wxCommandEvent& event) } } +void LogConfigWindow::OnWriteDebuggerChecked(wxCommandEvent& event) +{ + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) + { + m_writeDebugger = event.IsChecked(); + if (m_checks->IsChecked(i)) + { + if (m_writeDebugger) + m_LogManager->AddListener((LogTypes::LOG_TYPE)i, (LogListener *)m_LogManager->GetDebuggerListener()); + else + m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, (LogListener *)m_LogManager->GetDebuggerListener()); + } + } +} + void LogConfigWindow::OnToggleAll(wxCommandEvent& WXUNUSED(event)) { for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) @@ -207,12 +255,15 @@ void LogConfigWindow::ToggleLog(int _logType, bool enable) m_LogManager->AddListener(logType, m_LogManager->GetFileListener()); if (m_writeConsole) m_LogManager->AddListener(logType, m_LogManager->GetConsoleListener()); + if (m_writeDebugger) + m_LogManager->AddListener(logType, m_LogManager->GetDebuggerListener()); } else { m_LogManager->RemoveListener(logType, (LogListener *)m_LogWindow); m_LogManager->RemoveListener(logType, m_LogManager->GetFileListener()); m_LogManager->RemoveListener(logType, m_LogManager->GetConsoleListener()); + m_LogManager->RemoveListener(logType, m_LogManager->GetDebuggerListener()); } } diff --git a/Source/Core/DolphinWX/Src/LogConfigWindow.h b/Source/Core/DolphinWX/Src/LogConfigWindow.h index ac3f4409a2..5a08486409 100644 --- a/Source/Core/DolphinWX/Src/LogConfigWindow.h +++ b/Source/Core/DolphinWX/Src/LogConfigWindow.h @@ -37,11 +37,11 @@ public: private: LogManager *m_LogManager; CLogWindow *m_LogWindow; - bool m_writeFile, m_writeConsole, m_writeWindow; + bool m_writeFile, m_writeConsole, m_writeWindow, m_writeDebugger; bool enableAll; // Controls - wxCheckBox *m_writeFileCB, *m_writeConsoleCB, *m_writeWindowCB; + wxCheckBox *m_writeFileCB, *m_writeConsoleCB, *m_writeWindowCB, *m_writeDebuggerCB; wxCheckListBox* m_checks; wxRadioBox *m_verbosity; @@ -50,6 +50,7 @@ private: void OnWriteFileChecked(wxCommandEvent& event); void OnWriteConsoleChecked(wxCommandEvent& event); void OnWriteWindowChecked(wxCommandEvent& event); + void OnWriteDebuggerChecked(wxCommandEvent& event); void OnToggleAll(wxCommandEvent& event); void ToggleLog(int _logType, bool enable); void OnLogCheck(wxCommandEvent& event); diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp index 489d81c08d..f2a1b3d8b8 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogWindow.cpp @@ -85,6 +85,16 @@ void CLogWindow::CreateGUIControls() ini.Get("Options", "WriteToFile", &m_writeFile, false); ini.Get("Options", "WriteToConsole", &m_writeConsole, true); ini.Get("Options", "WriteToWindow", &m_writeWindow, true); +#ifdef _MSC_VER + if (IsDebuggerPresent()) + { + ini.Get("Options", "WriteToDebugger", &m_writeDebugger, true); + } + else +#endif + { + m_writeDebugger = false; + } for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) { bool enable; @@ -104,6 +114,12 @@ void CLogWindow::CreateGUIControls() m_LogManager->AddListener((LogTypes::LOG_TYPE)i, m_LogManager->GetConsoleListener()); else m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetConsoleListener()); + + if (m_writeDebugger && enable) + m_LogManager->AddListener((LogTypes::LOG_TYPE)i, m_LogManager->GetDebuggerListener()); + else + m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetDebuggerListener()); + m_LogManager->SetLogLevel((LogTypes::LOG_TYPE)i, (LogTypes::LOG_LEVELS)(verbosity)); } diff --git a/Source/Core/DolphinWX/Src/LogWindow.h b/Source/Core/DolphinWX/Src/LogWindow.h index a4b25f12c3..86fd1d3b4f 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.h +++ b/Source/Core/DolphinWX/Src/LogWindow.h @@ -65,7 +65,7 @@ private: bool m_ignoreLogTimer; LogManager *m_LogManager; std::queue > msgQueue; - bool m_writeFile, m_writeConsole, m_writeWindow, m_LogAccess; + bool m_writeFile, m_writeConsole, m_writeWindow, m_writeDebugger, m_LogAccess; // Controls wxBoxSizer *sBottom; From 79ca43226cfa5363bf6826d14c9518c7b26f6078 Mon Sep 17 00:00:00 2001 From: calc84maniac Date: Mon, 9 Jan 2012 00:10:13 -0500 Subject: [PATCH 08/65] Added SHRD/SHLD x86 emitters, further optimized srawx --- Source/Core/Common/Src/x64Emitter.cpp | 63 +++++++++++++++++++ Source/Core/Common/Src/x64Emitter.h | 4 ++ .../Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 5 +- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 7583ef0fc3..00c58a0fbc 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -867,6 +867,69 @@ void XEmitter::BTS(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, void XEmitter::BTR(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 6);} void XEmitter::BTC(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 7);} +//shift can be either imm8 or cl +void XEmitter::SHRD(int bits, OpArg dest, OpArg src, OpArg shift) +{ + bool writeImm = false; + if (dest.IsImm()) + { + _assert_msg_(DYNA_REC, 0, "SHRD - can't use imms as destination"); + } + if (!src.IsSimpleReg()) + { + _assert_msg_(DYNA_REC, 0, "SHRD - must use simple register as source"); + } + if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8)) + { + _assert_msg_(DYNA_REC, 0, "SHRD - illegal shift"); + } + if (bits == 16) Write8(0x66); + X64Reg operand = src.GetSimpleReg(); + dest.WriteRex(this, bits, bits, operand); + if (shift.GetImmBits() == 8) + { + Write8(0x0F); Write8(0xAC); + dest.WriteRest(this, 1, operand); + Write8((u8)shift.offset); + } + else + { + Write8(0x0F); Write8(0xAD); + dest.WriteRest(this, 0, operand); + } +} + +void XEmitter::SHLD(int bits, OpArg dest, OpArg src, OpArg shift) +{ + bool writeImm = false; + if (dest.IsImm()) + { + _assert_msg_(DYNA_REC, 0, "SHLD - can't use imms as destination"); + } + if (!src.IsSimpleReg()) + { + _assert_msg_(DYNA_REC, 0, "SHLD - must use simple register as source"); + } + if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8)) + { + _assert_msg_(DYNA_REC, 0, "SHLD - illegal shift"); + } + if (bits == 16) Write8(0x66); + X64Reg operand = src.GetSimpleReg(); + dest.WriteRex(this, bits, bits, operand); + if (shift.GetImmBits() == 8) + { + Write8(0x0F); Write8(0xA4); + dest.WriteRest(this, 1, operand); + Write8((u8)shift.offset); + } + else + { + Write8(0x0F); Write8(0xA5); + dest.WriteRest(this, 0, operand); + } +} + void OpArg::WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg _operandReg, int bits) { if (bits == 16) diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 6bd9291eea..3b699c81a0 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -381,6 +381,10 @@ public: void BTR(int bits, OpArg dest, OpArg index); void BTC(int bits, OpArg dest, OpArg index); + // Double-Precision Shift + void SHRD(int bits, OpArg dest, OpArg src, OpArg shift); + void SHLD(int bits, OpArg dest, OpArg src, OpArg shift); + // Extend EAX into EDX in various ways void CWD(int bits = 16); inline void CDQ() {CWD(32);} diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index 8df9853781..21ae8908c8 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -1758,10 +1758,9 @@ void Jit64::srawx(UGeckoInstruction inst) MOV(32, gpr.R(a), gpr.R(s)); TEST(32, R(ECX), Imm32(32)); FixupBranch topBitSet = J_CC(CC_NZ); - LEA(32, EAX, MComplex(gpr.RX(a), gpr.RX(a), 1, 0)); + XOR(32, R(EAX), R(EAX)); + SHRD(32, R(EAX), gpr.R(a), R(ECX)); SAR(32, gpr.R(a), R(ECX)); - NOT(32, R(ECX)); - SHL(32, R(EAX), R(ECX)); TEST(32, R(EAX), gpr.R(a)); FixupBranch nocarry1 = J_CC(CC_Z); JitSetCA(); From bef3d7229eca9a7f9568abf72de6b4d467feee9f Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Sun, 27 Nov 2011 23:17:10 -0800 Subject: [PATCH 09/65] Ensure comment strings in CBannerLoaderWii::SWiiBanner are null-terminated. Fixes issue 5012. Signed-off-by: Shawn Hoffman --- Source/Core/DiscIO/Src/BannerLoaderWii.cpp | 95 ++++++++++------------ Source/Core/DiscIO/Src/BannerLoaderWii.h | 25 ++++-- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp index ab66a346d4..b23dc4d91a 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp @@ -144,43 +144,57 @@ bool CBannerLoaderWii::GetBanner(u32* _pBannerImage) return true; } -bool CBannerLoaderWii::GetName(std::string* _rName) +bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& s) +{ + bool ret = false; + + if (IsValid()) + { + // find Banner type + SWiiBanner *pBanner = (SWiiBanner*)m_pBannerFile; + + // Ensure the string is null-terminating, since the banner format + // doesn't require it + u16 *src = new u16[COMMENT_SIZE + 1]; + memcpy(src, &pBanner->m_Comment[index], COMMENT_SIZE * sizeof(u16)); + src[COMMENT_SIZE] = 0; + + ret = CopyBeUnicodeToString(s, src, COMMENT_SIZE + 1); + + delete [] src; + } + + return ret; +} + +bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::wstring& s) { if (IsValid()) { // find Banner type SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; - std::string name; - if (CopyBeUnicodeToString(name, pBanner->m_Comment[0], WII_BANNER_COMMENT_SIZE)) - { - for (int i = 0; i < 6; i++) - { - _rName[i] = name; - } - return true; - } + std::wstring description; + for (int i = 0; i < COMMENT_SIZE; ++i) + description.push_back(Common::swap16(pBanner->m_Comment[index][i])); + + s = description; + return true; } return false; } +bool CBannerLoaderWii::GetName(std::string* _rName) +{ + return GetStringFromComments(NAME_IDX, *_rName); +} + bool CBannerLoaderWii::GetName(std::vector& _rNames) { - if (IsValid()) - { - // find Banner type - SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; - - std::wstring temp; - for (int i = 0; i < WII_BANNER_COMMENT_SIZE; ++i) - { - temp.push_back(Common::swap16(pBanner->m_Comment[0][i])); - } - _rNames.push_back(temp); - return true; - } - - return false; + std::wstring temp; + bool ret = GetStringFromComments(NAME_IDX, temp); + _rNames.push_back(temp); + return ret; } bool CBannerLoaderWii::GetCompany(std::string& _rCompany) @@ -191,39 +205,12 @@ bool CBannerLoaderWii::GetCompany(std::string& _rCompany) bool CBannerLoaderWii::GetDescription(std::string* _rDescription) { - if (IsValid()) - { - // find Banner type - SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; - - std::string description; - if (CopyBeUnicodeToString(description, pBanner->m_Comment[1], WII_BANNER_COMMENT_SIZE)) - { - for (int i = 0; i< 6; i++) - { - _rDescription[i] = description; - } - return true; - } - } - return false; + return GetStringFromComments(DESC_IDX, *_rDescription); } bool CBannerLoaderWii::GetDescription(std::wstring& _rDescription) { - if (IsValid()) - { - // find Banner type - SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; - - std::wstring description; - for (int i = 0; i < WII_BANNER_COMMENT_SIZE; ++i) - description.push_back(Common::swap16(pBanner->m_Comment[1][i])); - - _rDescription = description; - return true; - } - return false; + return GetStringFromComments(DESC_IDX, _rDescription); } void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height) diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.h b/Source/Core/DiscIO/Src/BannerLoaderWii.h index bfc87dc19e..83733cf5ed 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.h +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.h @@ -47,9 +47,18 @@ class CBannerLoaderWii private: - #define WII_BANNER_TEXTURE_SIZE (192 * 64 * 2) - #define WII_BANNER_ICON_SIZE ( 48 * 48 * 2) - #define WII_BANNER_COMMENT_SIZE 32 + enum + { + TEXTURE_SIZE = 192 * 64 * 2, + ICON_SIZE = 48 * 48 * 2, + COMMENT_SIZE = 32 + }; + + enum CommentIndex + { + NAME_IDX, + DESC_IDX + }; struct SWiiBanner { @@ -59,9 +68,10 @@ class CBannerLoaderWii u16 m_Speed; u8 m_Unknown[22]; - u16 m_Comment[2][WII_BANNER_COMMENT_SIZE]; - u8 m_BannerTexture[WII_BANNER_TEXTURE_SIZE]; - u8 m_IconTexture[8][WII_BANNER_ICON_SIZE]; + // Not null terminated! + u16 m_Comment[2][COMMENT_SIZE]; + u8 m_BannerTexture[TEXTURE_SIZE]; + u8 m_IconTexture[8][ICON_SIZE]; } ; u8* m_pBannerFile; @@ -69,6 +79,9 @@ class CBannerLoaderWii bool m_IsValid; void decode5A3image(u32* dst, u16* src, int width, int height); + + bool GetStringFromComments(const CommentIndex index, std::string& s); + bool GetStringFromComments(const CommentIndex index, std::wstring& s); }; } // namespace From 96d56cd8effd5fd847ea489bb48a9b02fe6fb2ec Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Wed, 18 Jan 2012 22:41:35 -0800 Subject: [PATCH 10/65] fix for memcard manager using sjis for ascii encoded string thanks to gerbilsoft for finding my mistake, fixes issue 5148 --- Source/Core/Core/Src/HW/GCMemcard.cpp | 4 ++-- Source/Core/Core/Src/HW/GCMemcard.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp index 2471e76599..cab7d950a2 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.cpp +++ b/Source/Core/Core/Src/HW/GCMemcard.cpp @@ -1126,7 +1126,7 @@ bool GCMemcard::Format(u8 * card_data, bool sjis, u16 SizeMb) gcp.bat_backup = (BlockAlloc *)(card_data + BLOCK_SIZE*4); *(u16*)gcp.hdr->SizeMb = BE16(SizeMb); - *(u16*)gcp.hdr->Encoding = BE16(sjis ? 1 : 0); + gcp.hdr->Encoding = BE16(sjis ? 1 : 0); FormatInternal(gcp); return true; @@ -1148,7 +1148,7 @@ bool GCMemcard::Format(bool sjis, u16 SizeMb) gcp.bat_backup = &bat_backup; *(u16*)hdr.SizeMb = BE16(SizeMb); - *(u16*)hdr.Encoding = BE16(sjis ? 1 : 0); + hdr.Encoding = BE16(sjis ? 1 : 0); FormatInternal(gcp); m_sizeMb = SizeMb; diff --git a/Source/Core/Core/Src/HW/GCMemcard.h b/Source/Core/Core/Src/HW/GCMemcard.h index 5aa0a3c97f..8c7baa4774 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.h +++ b/Source/Core/Core/Src/HW/GCMemcard.h @@ -91,7 +91,7 @@ private: // end Serial in libogc u8 deviceID[2]; //0x0020 2 0 if formated in slot A 1 if formated in slot B u8 SizeMb[2]; //0x0022 2 size of memcard in Mbits - u8 Encoding[2]; //0x0024 2 encoding (ASCII or japanese) + u16 Encoding; //0x0024 2 encoding (ASCII or japanese) u8 Unused1[468]; //0x0026 468 unused (0xff) u8 UpdateCounter[2];//0x01fa 2 update Counter (?, probably unused) u16 Checksum; //0x01fc 2 Additive Checksum From 2d6d73df95ff064f43260570f3f6487d55385585 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sat, 21 Jan 2012 14:58:29 +0100 Subject: [PATCH 11/65] [maintenance] Add a note explaining why we aren't emulating CP clear register writes. For further reference, see also r700f5eabc752. --- Source/Core/VideoCommon/Src/CommandProcessor.cpp | 13 ++++++++----- Source/Core/VideoCommon/Src/CommandProcessor.h | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index 67c8f411fa..fc85b8e39d 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -311,6 +311,7 @@ void Write16(const u16 _Value, const u32 _Address) UCPClearReg tmpCtrl(_Value); m_CPClearReg.Hex = tmpCtrl.Hex; DEBUG_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x", _Value); + SetCpClearRegister(); } break; @@ -677,13 +678,15 @@ void SetCpControlRegister() } +// NOTE: The implementation of this function should be correct, but we intentionally aren't using it at the moment. +// We don't emulate proper GP timing anyway at the moment, so this code would just slow down emulation. void SetCpClearRegister() { - if (IsOnThread()) - { - if (!m_CPClearReg.ClearFifoUnderflow && m_CPClearReg.ClearFifoOverflow) - bProcessFifoToLoWatermark = true; - } +// if (IsOnThread()) +// { +// if (!m_CPClearReg.ClearFifoUnderflow && m_CPClearReg.ClearFifoOverflow) +// bProcessFifoToLoWatermark = true; +// } } } // end of namespace CommandProcessor diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.h b/Source/Core/VideoCommon/Src/CommandProcessor.h index 7fb4e5a45f..db6772d66d 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.h +++ b/Source/Core/VideoCommon/Src/CommandProcessor.h @@ -158,6 +158,7 @@ void UpdateInterruptsFromVideoBackend(u64 userdata); bool AllowIdleSkipping(); +void SetCpClearRegister(); void SetCpControlRegister(); void SetCpStatusRegister(); void SetOverflowStatusFromGatherPipe(); From a7f3f61598132c1524d8a2b3d659bf73a0ae4db3 Mon Sep 17 00:00:00 2001 From: calc84maniac Date: Sun, 22 Jan 2012 19:56:53 -0500 Subject: [PATCH 12/65] [Jit64] Constant unsigned division and constant multiplication optimizations. Also, signed division can now be recompiled. --- Source/Core/Core/Src/PowerPC/Jit64/Jit.h | 1 + .../Core/Src/PowerPC/Jit64/Jit64_Tables.cpp | 4 +- .../Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 244 +++++++++++++++++- 3 files changed, 237 insertions(+), 12 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 8a13af741a..c01c1b017b 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -179,6 +179,7 @@ public: void mulhwux(UGeckoInstruction inst); void mullwx(UGeckoInstruction inst); void divwux(UGeckoInstruction inst); + void divwx(UGeckoInstruction inst); void srawix(UGeckoInstruction inst); void srawx(UGeckoInstruction inst); void addex(UGeckoInstruction inst); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp index 474dabdd2f..93963513ee 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp @@ -311,8 +311,8 @@ static GekkoOPTemplate table31_2[] = {138, &Jit64::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {234, &Jit64::addmex}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {202, &Jit64::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, - {491, &Jit64::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, - {1003, &Jit64::Default}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {491, &Jit64::divwx}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {1003, &Jit64::divwx}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, {459, &Jit64::divwux}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, {971, &Jit64::divwux}, //"divwuox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, {75, &Jit64::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index 21ae8908c8..ba51309c85 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -162,7 +162,10 @@ void Jit64::ComputeRC(const Gen::OpArg & arg) { } else { - CMP(32, arg, Imm8(0)); + if (arg.IsSimpleReg()) + TEST(32, arg, arg); + else + CMP(32, arg, Imm8(0)); FixupBranch pLesser = J_CC(CC_L); FixupBranch pGreater = J_CC(CC_G); MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2)); // _x86Reg == 0 @@ -1082,17 +1085,39 @@ void Jit64::mulli(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(Integer) int a = inst.RA, d = inst.RD; + u32 imm = inst.SIMM_16; if (gpr.R(a).IsImm()) { - gpr.SetImmediate32(d, (s32)gpr.R(a).offset * (s32)inst.SIMM_16); + gpr.SetImmediate32(d, (u32)gpr.R(a).offset * imm); } else { gpr.Lock(a, d); gpr.BindToRegister(d, (d == a), true); - gpr.KillImmediate(a, true, false); - IMUL(32, gpr.RX(d), gpr.R(a), Imm32((u32)(s32)inst.SIMM_16)); + if (imm == 0) + XOR(32, gpr.R(d), gpr.R(d)); + else if(imm == -1) + { + if (d != a) + MOV(32, gpr.R(d), gpr.R(a)); + NEG(32, gpr.R(d)); + } + else if((imm & (imm - 1)) == 0) + { + u32 shift = 0; + if (imm & 0xFFFF0000) shift |= 16; + if (imm & 0xFF00FF00) shift |= 8; + if (imm & 0xF0F0F0F0) shift |= 4; + if (imm & 0xCCCCCCCC) shift |= 2; + if (imm & 0xAAAAAAAA) shift |= 1; + if (d != a) + MOV(32, gpr.R(d), gpr.R(a)); + if (shift) + SHL(32, gpr.R(d), Imm8(shift)); + } + else + IMUL(32, gpr.RX(d), gpr.R(a), Imm32(imm)); gpr.UnlockAll(); } } @@ -1116,13 +1141,42 @@ void Jit64::mullwx(UGeckoInstruction inst) { gpr.Lock(a, b, d); gpr.BindToRegister(d, (d == a || d == b), true); - if (d == a) { + if (gpr.R(a).IsImm() || gpr.R(b).IsImm()) + { + u32 imm = gpr.R(a).IsImm() ? (u32)gpr.R(a).offset : (u32)gpr.R(b).offset; + int src = gpr.R(a).IsImm() ? b : a; + if (imm == 0) + XOR(32, gpr.R(d), gpr.R(d)); + else if(imm == -1) + { + if (d != src) + MOV(32, gpr.R(d), gpr.R(src)); + NEG(32, gpr.R(d)); + } + else if((imm & (imm - 1)) == 0 && !inst.OE) + { + u32 shift = 0; + if (imm & 0xFFFF0000) shift |= 16; + if (imm & 0xFF00FF00) shift |= 8; + if (imm & 0xF0F0F0F0) shift |= 4; + if (imm & 0xCCCCCCCC) shift |= 2; + if (imm & 0xAAAAAAAA) shift |= 1; + if (d != src) + MOV(32, gpr.R(d), gpr.R(src)); + if (shift) + SHL(32, gpr.R(d), Imm8(shift)); + } + else + IMUL(32, gpr.RX(d), gpr.R(src), Imm32(imm)); + } + else if (d == a) IMUL(32, gpr.RX(d), gpr.R(b)); - } else if (d == b) { - IMUL(32, gpr.RX(d), gpr.R(a)); - } else { - MOV(32, gpr.R(d), gpr.R(b)); + else if (d == b) IMUL(32, gpr.RX(d), gpr.R(a)); + else + { + MOV(32, gpr.R(d), gpr.R(b)); + IMUL(32, gpr.RX(d), gpr.R(a)); } if (inst.OE) { @@ -1192,6 +1246,103 @@ void Jit64::divwux(UGeckoInstruction inst) } } } + else if (gpr.R(b).IsImm()) + { + u32 divisor = (u32)gpr.R(b).offset; + if (divisor == 0) + { + gpr.SetImmediate32(d, 0); + if (inst.OE) + { + GenerateConstantOverflow(true); + } + } + else + { + u32 shift = 31; + while(!(divisor & (1 << shift))) + shift--; + + if (divisor == (1 << shift)) + { + gpr.Lock(a, b, d); + gpr.BindToRegister(d, d == a, true); + if (d != a) + MOV(32, gpr.R(d), gpr.R(a)); + if (shift) + SHR(32, gpr.R(d), Imm8(shift)); + } + else + { + u64 magic_dividend = 0x100000000ULL << shift; + u32 magic = (u32)(magic_dividend / divisor); + u32 max_quotient = magic >> shift; + + // Test for failure in round-up method + if (((u64)(magic+1) * (max_quotient*divisor-1)) >> (shift + 32) != max_quotient-1) + { + // If failed, use slower round-down method +#ifdef _M_X64 + gpr.Lock(a, b, d); + gpr.BindToRegister(d, d == a, true); + MOV(32, R(EAX), Imm32(magic)); + if (d != a) + MOV(32, gpr.R(d), gpr.R(a)); + IMUL(64, gpr.RX(d), R(RAX)); + ADD(64, gpr.R(d), R(RAX)); + SHR(64, gpr.R(d), Imm8(shift+32)); +#else + gpr.FlushLockX(EDX); + gpr.Lock(a, b, d); + gpr.BindToRegister(d, d == a, true); + MOV(32, R(EAX), Imm32(magic)); + MUL(32, gpr.R(a)); + XOR(32, gpr.R(d), gpr.R(d)); + ADD(32, R(EAX), Imm32(magic)); + ADC(32, gpr.R(d), R(EDX)); + if (shift) + SHR(32, gpr.R(d), Imm8(shift)); + gpr.UnlockAllX(); +#endif + } + else + { + // If success, use faster round-up method +#ifdef _M_X64 + gpr.Lock(a, b, d); + gpr.BindToRegister(a, true, false); + gpr.BindToRegister(d, false, true); + if (d == a) + { + MOV(32, R(EAX), Imm32(magic+1)); + IMUL(64, gpr.RX(d), R(RAX)); + } + else + { + MOV(32, gpr.R(d), Imm32(magic+1)); + IMUL(64, gpr.RX(d), gpr.R(a)); + } + SHR(64, gpr.R(d), Imm8(shift+32)); +#else + gpr.FlushLockX(EDX); + gpr.Lock(a, b, d); + gpr.BindToRegister(d, d == a, true); + MOV(32, R(EAX), Imm32(magic+1)); + MUL(32, gpr.R(a)); + MOV(32, gpr.R(d), R(EDX)); + if (shift) + SHR(32, gpr.R(d), Imm8(shift)); + gpr.UnlockAllX(); +#endif + } + } + if (inst.OE) + { + GenerateConstantOverflow(false); + } + gpr.UnlockAll(); + } + } else { gpr.FlushLockX(EDX); @@ -1201,7 +1352,6 @@ void Jit64::divwux(UGeckoInstruction inst) XOR(32, R(EDX), R(EDX)); gpr.KillImmediate(b, true, false); CMP(32, gpr.R(b), Imm32(0)); - // doesn't handle if OE is set, but int doesn't either... FixupBranch not_div_by_zero = J_CC(CC_NZ); MOV(32, gpr.R(d), R(EDX)); if (inst.OE) @@ -1228,6 +1378,80 @@ void Jit64::divwux(UGeckoInstruction inst) } } +void Jit64::divwx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + int a = inst.RA, b = inst.RB, d = inst.RD; + + if (gpr.R(a).IsImm() && gpr.R(b).IsImm()) + { + s32 i = (s32)gpr.R(a).offset, j = (s32)gpr.R(b).offset; + if( j == 0 || i == 0x80000000 && j == -1) + { + gpr.SetImmediate32(d, (i >> 31) ^ j); + if (inst.OE) + { + GenerateConstantOverflow(true); + } + } + else + { + gpr.SetImmediate32(d, i / j); + if (inst.OE) + { + GenerateConstantOverflow(false); + } + } + } + else + { + gpr.FlushLockX(EDX); + gpr.Lock(a, b, d); + gpr.BindToRegister(d, (d == a || d == b), true); + MOV(32, R(EAX), gpr.R(a)); + CDQ(); + gpr.BindToRegister(b, true, false); + TEST(32, gpr.R(b), gpr.R(b)); + FixupBranch not_div_by_zero = J_CC(CC_NZ); + MOV(32, gpr.R(d), R(EDX)); + if (inst.OE) + { + GenerateConstantOverflow(true); + } + FixupBranch end1 = J(); + SetJumpTarget(not_div_by_zero); + CMP(32, gpr.R(b), R(EDX)); + FixupBranch not_div_by_neg_one = J_CC(CC_NZ); + MOV(32, gpr.R(d), R(EAX)); + NEG(32, gpr.R(d)); + FixupBranch no_overflow = J_CC(CC_NO); + XOR(32, gpr.R(d), gpr.R(d)); + if (inst.OE) + { + GenerateConstantOverflow(true); + } + FixupBranch end2 = J(); + SetJumpTarget(not_div_by_neg_one); + IDIV(32, gpr.R(b)); + MOV(32, gpr.R(d), R(EAX)); + SetJumpTarget(no_overflow); + if (inst.OE) + { + GenerateConstantOverflow(false); + } + SetJumpTarget(end1); + SetJumpTarget(end2); + gpr.UnlockAll(); + gpr.UnlockAllX(); + } + + if (inst.Rc) + { + ComputeRC(gpr.R(d)); + } +} + void Jit64::addx(UGeckoInstruction inst) { INSTRUCTION_START From fd616ccb0c09ab8f7cc2fb10a762e93b33c5c609 Mon Sep 17 00:00:00 2001 From: calc84maniac Date: Sun, 22 Jan 2012 21:54:39 -0500 Subject: [PATCH 13/65] [Jit64] Register-based shift instructions optimized on 64-bit processors --- .../Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 72 +++++++++++++++++-- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index ba51309c85..4980b4d7a4 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -1904,6 +1904,19 @@ void Jit64::srwx(UGeckoInstruction inst) } else { +#ifdef _M_X64 + gpr.FlushLockX(ECX); + gpr.Lock(a, b, s); + gpr.BindToRegister(a, (a == b || a == s), true); + MOV(32, R(ECX), gpr.R(b)); + if (a != s) + { + MOV(32, gpr.R(a), gpr.R(s)); + } + SHR(64, gpr.R(a), R(ECX)); + gpr.UnlockAll(); + gpr.UnlockAllX(); +#else gpr.FlushLockX(ECX); gpr.Lock(a, b, s); gpr.BindToRegister(a, (a == b || a == s), true); @@ -1919,6 +1932,7 @@ void Jit64::srwx(UGeckoInstruction inst) SHR(32, gpr.R(a), R(ECX)); gpr.UnlockAll(); gpr.UnlockAllX(); +#endif } // Shift of 0 doesn't update flags, so compare manually just in case if (inst.Rc) @@ -1939,9 +1953,35 @@ void Jit64::slwx(UGeckoInstruction inst) { u32 amount = (u32)gpr.R(b).offset; gpr.SetImmediate32(a, (amount & 0x20) ? 0 : (u32)gpr.R(s).offset << amount); + if (inst.Rc) + { + ComputeRC(gpr.R(a)); + } } else { +#ifdef _M_X64 + gpr.FlushLockX(ECX); + gpr.Lock(a, b, s); + gpr.BindToRegister(a, (a == b || a == s), true); + MOV(32, R(ECX), gpr.R(b)); + if (a != s) + { + MOV(32, gpr.R(a), gpr.R(s)); + } + SHL(64, gpr.R(a), R(ECX)); + if (inst.Rc) + { + AND(32, gpr.R(a), gpr.R(a)); + GenerateRC(); + } + else + { + MOV(32, gpr.R(a), gpr.R(a)); + } + gpr.UnlockAll(); + gpr.UnlockAllX(); +#else gpr.FlushLockX(ECX); gpr.Lock(a, b, s); gpr.BindToRegister(a, (a == b || a == s), true); @@ -1957,11 +1997,12 @@ void Jit64::slwx(UGeckoInstruction inst) SHL(32, gpr.R(a), R(ECX)); gpr.UnlockAll(); gpr.UnlockAllX(); - } - // Shift of 0 doesn't update flags, so compare manually just in case - if (inst.Rc) - { - ComputeRC(gpr.R(a)); + // Shift of 0 doesn't update flags, so compare manually just in case + if (inst.Rc) + { + ComputeRC(gpr.R(a)); + } +#endif } } @@ -1973,6 +2014,25 @@ void Jit64::srawx(UGeckoInstruction inst) int a = inst.RA; int b = inst.RB; int s = inst.RS; +#ifdef _M_X64 + gpr.Lock(a, s, b); + gpr.FlushLockX(ECX); + gpr.BindToRegister(a, (a == s || a == b), true); + JitClearCA(); + MOV(32, R(ECX), gpr.R(b)); + if (a != s) + MOV(32, gpr.R(a), gpr.R(s)); + SHL(64, gpr.R(a), Imm8(32)); + SAR(64, gpr.R(a), R(ECX)); + MOV(32, R(EAX), gpr.R(a)); + SHR(64, gpr.R(a), Imm8(32)); + TEST(32, gpr.R(a), R(EAX)); + FixupBranch nocarry = J_CC(CC_Z); + JitSetCA(); + SetJumpTarget(nocarry); + gpr.UnlockAll(); + gpr.UnlockAllX(); +#else gpr.Lock(a, s, b); gpr.FlushLockX(ECX); gpr.BindToRegister(a, (a == s || a == b), true); @@ -1998,7 +2058,7 @@ void Jit64::srawx(UGeckoInstruction inst) SetJumpTarget(nocarry2); gpr.UnlockAll(); gpr.UnlockAllX(); - +#endif if (inst.Rc) { ComputeRC(gpr.R(a)); } From 04a7e33f0b629622ff851f962b9ab707f70a1b35 Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Fri, 27 Jan 2012 00:30:52 -0800 Subject: [PATCH 14/65] proper unicode literal and wstring to wxstring conversions. Fixes issue 5156. --- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 45 +++++++++----------- Source/Core/DolphinWX/Src/ISOProperties.cpp | 12 +++--- Source/Core/DolphinWX/Src/LogWindow.cpp | 2 +- Source/Core/DolphinWX/Src/MemcardManager.cpp | 2 +- 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index 9dbbf656e9..8e0a498915 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -448,7 +448,7 @@ void CGameListCtrl::InsertItemInReportView(long _Index) #else // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(L"CP932"); + wxCSConv SJISConv(wxT("CP932")); #endif GameListItem& rISOFile = *m_ISOFiles[_Index]; @@ -468,10 +468,13 @@ void CGameListCtrl::InsertItemInReportView(long _Index) // Set the game's banner in the second column SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex); - std::wstring wname; - const std::wstring& wdescription = rISOFile.GetDescription(); + std::wstring wstring_name; + const std::wstring& wstring_description = rISOFile.GetDescription(); std::string company; + wxString name; + wxString description; + // We show the company string on Gamecube only // On Wii we show the description instead as the company string is empty if (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC) @@ -482,13 +485,11 @@ void CGameListCtrl::InsertItemInReportView(long _Index) case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_JAPAN: { - rISOFile.GetName(wname, -1); - wxString name = wxString(rISOFile.GetName(0).c_str(), SJISConv); + rISOFile.GetName(wstring_name, -1); + name = wxString(rISOFile.GetName(0).c_str(), SJISConv); m_gameList.append(StringFromFormat("%s (J)\n", (const char *)name.c_str())); - SetItem(_Index, COLUMN_TITLE, name, -1); - SetItem(_Index, COLUMN_NOTES, wxString(company.size() ? - company.c_str() : rISOFile.GetDescription(0).c_str(), - SJISConv), -1); + description = wxString(company.size() ? company.c_str() : + rISOFile.GetDescription(0).c_str(), SJISConv); } break; case DiscIO::IVolume::COUNTRY_USA: @@ -496,28 +497,24 @@ void CGameListCtrl::InsertItemInReportView(long _Index) default: { wxCSConv WindowsCP1252(wxFontMapper::GetEncodingName(wxFONTENCODING_CP1252)); - rISOFile.GetName(wname, SelectedLanguage); + rISOFile.GetName(wstring_name, SelectedLanguage); - SetItem(_Index, COLUMN_TITLE, - wxString( - rISOFile.GetName(SelectedLanguage).c_str(), WindowsCP1252), - -1); + name = wxString(rISOFile.GetName(SelectedLanguage).c_str(), WindowsCP1252); m_gameList.append(StringFromFormat("%s (%c)\n", rISOFile.GetName(SelectedLanguage).c_str(), (rISOFile.GetCountry() == DiscIO::IVolume::COUNTRY_USA)?'U':'E')); - SetItem(_Index, COLUMN_NOTES, - wxString(company.size() ? - company.c_str() : - rISOFile.GetDescription(SelectedLanguage).c_str(), WindowsCP1252), - -1); + description = wxString(company.size() ? company.c_str() : + rISOFile.GetDescription(SelectedLanguage).c_str(), WindowsCP1252); } break; } - if (wname.length()) - SetItem(_Index, COLUMN_TITLE, wname, -1); - if (wdescription.length()) - SetItem(_Index, COLUMN_NOTES, wdescription, -1); - + if (wstring_name.length()) + name = wstring_name.c_str(); + if (wstring_description.length()) + description = wstring_description.c_str(); + + SetItem(_Index, COLUMN_TITLE, name, -1); + SetItem(_Index, COLUMN_NOTES, description, -1); #ifndef _WIN32 // Emulation state diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index 85b95f3cb4..b5e5c82d1d 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -158,7 +158,7 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW std::wstring wname; wxString name; if (OpenGameListItem->GetName(wname)) - name = wname; + name = wname.c_str(); else name = wxString(OpenISO->GetName().c_str(), wxConvUTF8); m_Name->SetValue(name); @@ -1280,7 +1280,7 @@ void CISOProperties::ChangeBannerDetails(int lang) #else // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(L"CP932"); + wxCSConv SJISConv(wxT("CP932")); #endif switch (OpenGameListItem->GetCountry()) { @@ -1288,11 +1288,11 @@ void CISOProperties::ChangeBannerDetails(int lang) case DiscIO::IVolume::COUNTRY_JAPAN: if (OpenGameListItem->GetName(wname, -1)) - shortName = wname; + shortName = wname.c_str(); else shortName = wxString(OpenGameListItem->GetName(0).c_str(), SJISConv); - if ((comment = OpenGameListItem->GetDescription()).size() == 0) + if ((comment = OpenGameListItem->GetDescription().c_str()).size() == 0) comment = wxString(OpenGameListItem->GetDescription(0).c_str(), SJISConv); maker = wxString(OpenGameListItem->GetCompany().c_str(), SJISConv); break; @@ -1302,10 +1302,10 @@ void CISOProperties::ChangeBannerDetails(int lang) { wxCSConv WindowsCP1252(wxFontMapper::GetEncodingName(wxFONTENCODING_CP1252)); if (OpenGameListItem->GetName(wname, lang)) - shortName = wname; + shortName = wname.c_str(); else shortName = wxString(OpenGameListItem->GetName(lang).c_str(), WindowsCP1252); - if ((comment = OpenGameListItem->GetDescription()).size() == 0) + if ((comment = OpenGameListItem->GetDescription().c_str()).size() == 0) comment = wxString(OpenGameListItem->GetDescription(lang).c_str(), WindowsCP1252); maker = wxString(OpenGameListItem->GetCompany().c_str(), WindowsCP1252); } diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp index f2a1b3d8b8..0d11ef0142 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogWindow.cpp @@ -56,7 +56,7 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos, #else // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) // it returns CP-932, in order to use iconv we need to use CP932 - m_SJISConv = wxCSConv(L"CP932"); + m_SJISConv = wxCSConv(wxT("CP932")); #endif m_LogManager = LogManager::GetInstance(); diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp index 68ae0f9ff2..98390122e2 100644 --- a/Source/Core/DolphinWX/Src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp @@ -716,7 +716,7 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card) #else // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(L"CP932"); + wxCSConv SJISConv(wxT("CP932")); #endif wxTitle = wxString(title, ascii ? *wxConvCurrent : SJISConv); wxComment = wxString(comment, ascii ? *wxConvCurrent : SJISConv); From c5008fe9dea7baf3368e214fe70e148d3bcca83b Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 17:35:27 +0100 Subject: [PATCH 15/65] TextureCache: Renaming some variables OGL: Fix a possible bug at texture dumping OGL: Add a TODO about a possible bug --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 30 +++++++++---------- .../Core/VideoCommon/Src/TextureCacheBase.h | 26 ++++++++-------- .../Plugin_VideoDX11/Src/TextureCache.cpp | 2 +- .../Plugin_VideoDX11/Src/VertexManager.cpp | 2 +- .../Plugin_VideoDX9/Src/TextureCache.cpp | 10 +++---- .../Plugin_VideoDX9/Src/VertexManager.cpp | 2 +- .../Plugin_VideoOGL/Src/TextureCache.cpp | 6 ++-- .../Plugin_VideoOGL/Src/VertexManager.cpp | 2 +- 8 files changed, 41 insertions(+), 39 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 3550227389..b56dc171aa 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -266,7 +266,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } if (((entry->isRenderTarget || entry->isDynamic) && hash_value == entry->hash && address == entry->addr) - || ((address == entry->addr) && (hash_value == entry->hash) && full_format == entry->format && entry->mipLevels == maxlevel)) + || ((address == entry->addr) && (hash_value == entry->hash) && full_format == entry->format && entry->num_mipmaps == maxlevel)) { entry->isDynamic = false; goto return_entry; @@ -279,8 +279,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, texture_is_dynamic = (entry->isRenderTarget || entry->isDynamic) && !g_ActiveConfig.bCopyEFBToTexture; if (!entry->isRenderTarget && - ((!entry->isDynamic && width == entry->realW && height == entry->realH && full_format == entry->format && entry->mipLevels == maxlevel) - || (entry->isDynamic && entry->realW == width && entry->realH == height))) + ((!entry->isDynamic && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) + || (entry->isDynamic && entry->native_width == width && entry->native_height == height))) { // reuse the texture } @@ -332,7 +332,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // Sometimes, we can get around recreating a texture if only the number of mip levels gets changes // e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states // Thus, we don't update this member for every Load, but just whenever the texture gets recreated - entry->mipLevels = maxlevel; + entry->num_mipmaps = maxlevel; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } @@ -341,11 +341,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, entry->format = full_format; entry->size_in_bytes = texture_size; - entry->virtualW = width; - entry->virtualH = height; + entry->native_width = nativeW; + entry->native_height = nativeH; - entry->realW = nativeW; - entry->realH = nativeH; + entry->virtual_width = width; + entry->virtual_height = height; entry->isRenderTarget = false; entry->isNonPow2 = false; @@ -633,8 +633,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TCacheEntryBase *entry = textures[dstAddr]; if (entry) { - if ((entry->isRenderTarget && entry->virtualW == scaled_tex_w && entry->virtualH == scaled_tex_h) - || (entry->isDynamic && entry->realW == tex_w && entry->realH == tex_h)) + if ((entry->isRenderTarget && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h) + || (entry->isDynamic && entry->native_width == tex_w && entry->native_height == tex_h)) { texture_is_dynamic = entry->isDynamic; } @@ -660,14 +660,14 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->addr = dstAddr; entry->hash = 0; - entry->realW = tex_w; - entry->realH = tex_h; + entry->native_width = tex_w; + entry->native_height = tex_h; - entry->virtualW = scaled_tex_w; - entry->virtualH = scaled_tex_h; + entry->virtual_width = scaled_tex_w; + entry->virtual_height = scaled_tex_h; entry->format = dstFormat; - entry->mipLevels = 0; + entry->num_mipmaps = 0; entry->isRenderTarget = true; entry->isNonPow2 = true; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 1c86e64006..f115b367b4 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -16,29 +16,31 @@ class TextureCache public: struct TCacheEntryBase { - // TODO: organize + // common members u32 addr; u32 size_in_bytes; u64 hash; - //u32 paletteHash; - u32 oldpixel; + //u32 pal_hash; u32 format; - - int frameCount; - unsigned int realW, realH; // Texture dimensions from the GameCube's point of view - unsigned int virtualW, virtualH; // Texture dimensions from OUR point of view - // Real and virtual dimensions are usually the same, but may be - // different if e.g. we use high-res textures. Then, realW,realH will - // be the dimensions of the original GameCube texture and - // virtualW,virtualH will be the dimensions of the high-res texture. + //bool is_preloaded; - unsigned int mipLevels; + unsigned int num_mipmaps; + unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view + unsigned int virtual_width, virtual_height; // Texture dimensions from OUR point of view - for hires textures or scaled EFB copies + + // EFB copies bool isRenderTarget; // copied from EFB bool isDynamic; // Used for hybrid EFB copies to enable checks for CPU modifications + + // deprecated members + u32 oldpixel; + int frameCount; bool isNonPow2; // doesn't seem to be used anywhere + + //TCacheEntryBase() //{ // // TODO: remove these diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index 39018c83bc..b1a5398d7d 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -107,7 +107,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo g_renderer->ResetAPIState(); // stretch picture with increased internal resolution - const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtualW, (float)virtualH); + const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtual_width, (float)virtual_height); D3D::context->RSSetViewports(1, &vp); // set transformation diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index e1e40047e4..9087b6dac1 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -233,7 +233,7 @@ void VertexManager::vFlush() if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); } else ERROR_LOG(VIDEO, "error loading texture"); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 7c741e08a9..3f12678ca4 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -90,15 +90,15 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo // Stretch picture with increased internal resolution vp.X = 0; vp.Y = 0; - vp.Width = virtualW; - vp.Height = virtualH; + vp.Width = virtual_width; + vp.Height = virtual_height; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; D3D::dev->SetViewport(&vp); RECT destrect; - destrect.bottom = virtualH; + destrect.bottom = virtual_height; destrect.left = 0; - destrect.right = virtualW; + destrect.right = virtual_width; destrect.top = 0; PixelShaderManager::SetColorMatrix(colmat); // set transformation @@ -133,7 +133,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo D3D::drawShadedTexQuad(read_texture, &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), - virtualW, virtualH, + virtual_width, virtual_height, // TODO: why is D3DFMT_D24X8 singled out here? why not D3DFMT_D24X4S4/D24S8/D24FS8/D32/D16/D15S1 too, or none of them? PixelShaderCache::GetDepthMatrixProgram(SSAAMode, (srcFormat == PIXELFMT_Z24) && bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8), VertexShaderCache::GetSimpleVertexShader(SSAAMode)); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index d9c33b67ef..c6bddb7468 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -142,7 +142,7 @@ void VertexManager::vFlush() if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); } else ERROR_LOG(VIDEO, "error loading texture"); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index 4a9431a563..91cc48d7d9 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -124,7 +124,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[]) std::string tga_filename(filename); tga_filename.replace(tga_filename.size() - 3, 3, "tga"); - return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, realW, realH); + return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height); } TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, @@ -294,7 +294,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo glEnable(GL_TEXTURE_RECTANGLE_ARB); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture); - glViewport(0, 0, virtualW, virtualH); + glViewport(0, 0, virtual_width, virtual_height); PixelShaderCache::SetCurrentShader((srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram()); PixelShaderManager::SetColorMatrix(colmat); // set transformation @@ -337,7 +337,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo { static int count = 0; SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - count++).c_str(), GL_TEXTURE_2D, texture, realW, realH); + count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height); } } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 5144c328d9..e3b55987ec 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -160,7 +160,7 @@ void VertexManager::vFlush() if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); if (g_ActiveConfig.iLog & CONF_SAVETEXTURES) { From 94a8536b8cc44ab1435982695bc4a245e9f38f75 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 18:05:01 +0100 Subject: [PATCH 16/65] TextureCacheBase: Simplify texture cache entry initialization --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 52 ++++++------------- .../Core/VideoCommon/Src/TextureCacheBase.h | 29 +++++++++++ 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index b56dc171aa..a5db110c7a 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -135,7 +135,7 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); if (0 == rangePosition) { - iter->second->hash = 0; + iter->second->SetHashes(TEXHASH_INVALID); } } } @@ -190,8 +190,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, const unsigned int nativeH = height; bool isPow2; - u64 hash_value = 0; - u64 texHash = 0; + u64 hash_value = TEXHASH_INVALID; + u64 texHash = TEXHASH_INVALID; u32 texID = address; u32 full_format = texformat; const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); @@ -252,7 +252,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } else { - hash_value = 0; + hash_value = TEXHASH_INVALID; } } else @@ -262,7 +262,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } else if ((entry->isRenderTarget || entry->isDynamic) && g_ActiveConfig.bCopyEFBToTexture) { - hash_value = 0; + hash_value = TEXHASH_INVALID; } if (((entry->isRenderTarget || entry->isDynamic) && hash_value == entry->hash && address == entry->addr) @@ -332,24 +332,15 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // Sometimes, we can get around recreating a texture if only the number of mip levels gets changes // e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states // Thus, we don't update this member for every Load, but just whenever the texture gets recreated - entry->num_mipmaps = maxlevel; + entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage... GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } - entry->addr = address; - entry->format = full_format; - entry->size_in_bytes = texture_size; - - entry->native_width = nativeW; - entry->native_height = nativeH; - - entry->virtual_width = width; - entry->virtual_height = height; - - entry->isRenderTarget = false; + entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); + entry->SetDimensions(nativeW, nativeH, width, height); + entry->SetEFBCopyParameters(false, texture_is_dynamic); entry->isNonPow2 = false; - entry->isDynamic = texture_is_dynamic; entry->oldpixel = *(u32*)ptr; @@ -472,9 +463,9 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat cbufid = 5; break; - case 12: // Z16L - copy lower 16 depth bits - // expected to be used as an IA8 texture (upper 8 bits stored as intensity, lower 8 bits stored as alpha) - // Used e.g. in Zelda: Skyward Sword + case 12: // Z16L - copy lower 16 depth bits + // expected to be used as an IA8 texture (upper 8 bits stored as intensity, lower 8 bits stored as alpha) + // Used e.g. in Zelda: Skyward Sword colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f; cbufid = 6; break; @@ -657,21 +648,12 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // create the texture textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); - entry->addr = dstAddr; - entry->hash = 0; - - entry->native_width = tex_w; - entry->native_height = tex_h; - - entry->virtual_width = scaled_tex_w; - entry->virtual_height = scaled_tex_h; - - entry->format = dstFormat; - entry->num_mipmaps = 0; - - entry->isRenderTarget = true; + // TODO: Using the wrong dstFormat, dumb... + entry->SetGeneralParameters(dstAddr, 0, dstFormat, 0); + entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); + entry->SetEFBCopyParameters(true, false); + entry->SetHashes(TEXHASH_INVALID); entry->isNonPow2 = true; - entry->isDynamic = false; } entry->frameCount = frameCount; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index f115b367b4..5ef0c3c464 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -16,6 +16,8 @@ class TextureCache public: struct TCacheEntryBase { +#define TEXHASH_INVALID 0 + // common members u32 addr; u32 size_in_bytes; @@ -29,6 +31,33 @@ public: unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view unsigned int virtual_width, virtual_height; // Texture dimensions from OUR point of view - for hires textures or scaled EFB copies + void SetGeneralParameters(u32 addr, u32 size, u32 format, unsigned int num_mipmaps) + { + this->addr = addr; + this->size_in_bytes = size; + this->format = format; + this->num_mipmaps = num_mipmaps; + } + + void SetDimensions(unsigned int native_width, unsigned int native_height, unsigned int virtual_width, unsigned int virtual_height) + { + this->native_width = native_width; + this->native_height = native_height; + this->virtual_width = virtual_width; + this->virtual_height = virtual_height; + } + + void SetHashes(u64 hash/*, u32 pal_hash*/) + { + this->hash = hash; + //this->pal_hash = pal_hash; + } + + void SetEFBCopyParameters(bool is_efb_copy, bool is_dynamic) + { + isRenderTarget = is_efb_copy; + isDynamic = is_dynamic; + } // EFB copies bool isRenderTarget; // copied from EFB From 9c39952c3415e1592098b46c801d668b3049fa83 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 18:33:05 +0100 Subject: [PATCH 17/65] TextureCacheBase: Kill deprecated entry member isNonPow2 TextureCacheBase: Add a TODO about a potential bug --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 4 +- .../Core/VideoCommon/Src/TextureCacheBase.h | 38 ++++++------------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index a5db110c7a..8bca9e36d9 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -93,7 +93,7 @@ void TextureCache::Cleanup() tcend = textures.end(); while (iter != tcend) { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) + if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) // TODO: Deleting EFB copies might not be a good idea here... { delete iter->second; textures.erase(iter++); @@ -340,7 +340,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); entry->SetEFBCopyParameters(false, texture_is_dynamic); - entry->isNonPow2 = false; entry->oldpixel = *(u32*)ptr; @@ -653,7 +652,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); entry->SetEFBCopyParameters(true, false); entry->SetHashes(TEXHASH_INVALID); - entry->isNonPow2 = true; } entry->frameCount = frameCount; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 5ef0c3c464..5625958b76 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -31,6 +31,17 @@ public: unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view unsigned int virtual_width, virtual_height; // Texture dimensions from OUR point of view - for hires textures or scaled EFB copies + // EFB copies + bool isRenderTarget; // copied from EFB + bool isDynamic; // Used for hybrid EFB copies to enable checks for CPU modifications + + // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames + int frameCount; + + // deprecated members + u32 oldpixel; + + void SetGeneralParameters(u32 addr, u32 size, u32 format, unsigned int num_mipmaps) { this->addr = addr; @@ -59,33 +70,6 @@ public: isDynamic = is_dynamic; } - // EFB copies - bool isRenderTarget; // copied from EFB - bool isDynamic; // Used for hybrid EFB copies to enable checks for CPU modifications - - // deprecated members - u32 oldpixel; - int frameCount; - bool isNonPow2; // doesn't seem to be used anywhere - - - - //TCacheEntryBase() - //{ - // // TODO: remove these - // isRenderTarget = 0; - // hash = 0; - // //paletteHash = 0; - // oldpixel = 0; - // addr = 0; - // size_in_bytes = 0; - // frameCount = 0; - // isNonPow2 = true; - // w = 0; - // h = 0; - // scaledW = 0; - // scaledH = 0; - //} virtual ~TCacheEntryBase(); From 8bc9e443fd5ceb7b5f4b11ccf600d6ca5f332427 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 18:45:22 +0100 Subject: [PATCH 18/65] TextureCacheBase: De-uglify entry lookup a bit --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 38 +++++++------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 8bca9e36d9..e2d74e18e5 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -88,9 +88,8 @@ TextureCache::~TextureCache() void TextureCache::Cleanup() { - TexCache::iterator - iter = textures.begin(), - tcend = textures.end(); + TexCache::iterator iter = textures.begin(); + TexCache::iterator tcend = textures.end(); while (iter != tcend) { if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) // TODO: Deleting EFB copies might not be a good idea here... @@ -236,33 +235,24 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, TCacheEntryBase *entry = textures[texID]; if (entry) { - if (!g_ActiveConfig.bSafeTextureCache) + if (g_ActiveConfig.bSafeTextureCache) { - if (entry->isRenderTarget || entry->isDynamic) + if (g_ActiveConfig.bCopyEFBToTexture && (entry->isRenderTarget || entry->isDynamic)) + hash_value = TEXHASH_INVALID; + } + else + { + if (!(entry->isRenderTarget || entry->isDynamic)) + hash_value = *(u32*)ptr; + else if (g_ActiveConfig.bCopyEFBToTexture) + hash_value = TEXHASH_INVALID; + else { - if (!g_ActiveConfig.bCopyEFBToTexture) - { hash_value = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); if (isPaletteTexture) - { - hash_value ^= GetHash64(&texMem[tlutaddr], palette_size, - g_ActiveConfig.iSafeTextureCache_ColorSamples); - } - } - else - { - hash_value = TEXHASH_INVALID; - } + hash_value ^= GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); } - else - { - hash_value = *(u32*)ptr; - } - } - else if ((entry->isRenderTarget || entry->isDynamic) && g_ActiveConfig.bCopyEFBToTexture) - { - hash_value = TEXHASH_INVALID; } if (((entry->isRenderTarget || entry->isDynamic) && hash_value == entry->hash && address == entry->addr) From dcf18fbaaf20cf1eade8c76eccd7fcd279b43957 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 19:17:04 +0100 Subject: [PATCH 19/65] TextureCacheBase: Force autogenerating mipmaps if custom textures are used --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index e2d74e18e5..afe4ce8abc 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -282,7 +282,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } } } - + if (g_ActiveConfig.bHiresTextures) { // Load Custom textures @@ -298,16 +298,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, { expandedWidth = width = newWidth; expandedHeight = height = newHeight; - - // TODO: shouldn't generating mips be forced on now? - // native mips with a custom texture wouldn't make sense } } if (pcfmt == PC_TEX_FMT_NONE) pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, - expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + UseNativeMips = UseNativeMips && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions isPow2 = !((width & (width - 1)) || (height & (height - 1))); texLevels = (isPow2 && UseNativeMips && maxlevel) ? GetPow2(std::max(width, height)) : !isPow2; @@ -330,13 +328,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); entry->SetEFBCopyParameters(false, texture_is_dynamic); - entry->oldpixel = *(u32*)ptr; if (g_ActiveConfig.bSafeTextureCache || entry->isDynamic) entry->hash = hash_value; else - // don't like rand() here entry->hash = *(u32*)ptr = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); // load texture From f68ee87e0e03b909d66a8a333297499d357aa22b Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 19:45:13 +0100 Subject: [PATCH 20/65] TextureCacheBase: De-uglify texcache entry lookup even more + documentation --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index afe4ce8abc..1c6f8a4718 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -235,6 +235,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, TCacheEntryBase *entry = textures[texID]; if (entry) { + // 1. Adjust reference hash: + // safe texcache: reference hash was calculated above for normal textures. 0 for virtual EFB copies. + // unsafe texcache: 0 for virtual EFB copies. Safe hash for dynamic EFB copies. First pixel for normal textures. if (g_ActiveConfig.bSafeTextureCache) { if (g_ActiveConfig.bCopyEFBToTexture && (entry->isRenderTarget || entry->isDynamic)) @@ -255,31 +258,38 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } } - if (((entry->isRenderTarget || entry->isDynamic) && hash_value == entry->hash && address == entry->addr) - || ((address == entry->addr) && (hash_value == entry->hash) && full_format == entry->format && entry->num_mipmaps == maxlevel)) + // 2. a) For EFB copies, only the hash and the texture address need to match + if ((entry->isRenderTarget || entry->isDynamic) && hash_value == entry->hash && address == entry->addr) { + // TODO: Print a warning if the format changes! In this case, we could reinterpret the internal texture object data to the new pixel format (similiar to what is already being done in Renderer::ReinterpretPixelFormat()) entry->isDynamic = false; goto return_entry; } + + // 2. b) For normal textures, all texture parameters need to match + if (address == entry->addr && hash_value == entry->hash && full_format == entry->format && + entry->num_mipmaps == maxlevel && entry->native_width == nativeW && entry->native_height == nativeH) + { + goto return_entry; + } + + // 3. If we reach this line, we'll have to upload the new texture data to VRAM. + // If we're lucky, the texture parameters didn't change and we can reuse the internal texture object instead of destroying and recreating it. + texture_is_dynamic = (entry->isRenderTarget || entry->isDynamic) && !g_ActiveConfig.bCopyEFBToTexture; + + // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? + // TODO: Actually, it should be enough if the internal texture format matches... + if (!entry->isRenderTarget && + ((!entry->isDynamic && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) + || (entry->isDynamic && entry->native_width == width && entry->native_height == height))) + { + // reuse the texture + } else { - // Let's reload the new texture data into the same texture, - // instead of destroying it and having to create a new one. - // Might speed up movie playback very, very slightly. - texture_is_dynamic = (entry->isRenderTarget || entry->isDynamic) && !g_ActiveConfig.bCopyEFBToTexture; - - if (!entry->isRenderTarget && - ((!entry->isDynamic && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) - || (entry->isDynamic && entry->native_width == width && entry->native_height == height))) - { - // reuse the texture - } - else - { - // delete the texture and make a new one - delete entry; - entry = NULL; - } + // delete the texture and make a new one + delete entry; + entry = NULL; } } From 0c1e015ec3172ecab09f0315b98aeadd1191f4a4 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 20:05:32 +0100 Subject: [PATCH 21/65] TextureCacheBase: Small change --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 2 +- Source/Core/VideoCommon/Src/TextureCacheBase.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 1c6f8a4718..c29646273a 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -367,7 +367,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, expandedHeight = (currentHeight + bsh) & (~bsh); TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); - entry->Load(currentWidth, currentHeight, expandedWidth, level); + entry->Load(currentWidth, currentHeight, expandedWidth, level, false); ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1); mipWidth >>= 1; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 5625958b76..7b14d737d2 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -77,7 +77,7 @@ public: virtual bool Save(const char filename[]) = 0; virtual void Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int level, bool autogen_mips = false) = 0; + unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0; virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf, unsigned int cbufid, From 93dbd93a8d35e3a87ae1c918369e952be3404b59 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 21:11:31 +0100 Subject: [PATCH 22/65] TextureCacheBase: More cleanup... --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index c29646273a..926b86b29a 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -191,10 +191,10 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, u64 hash_value = TEXHASH_INVALID; u64 texHash = TEXHASH_INVALID; + u64 tlut_hash = TEXHASH_INVALID; u32 texID = address; u32 full_format = texformat; const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); - const u32 palette_size = TexDecoder_GetPaletteSize(texformat); bool texture_is_dynamic = false; unsigned int texLevels; PC_TexFormat pcfmt = PC_TEX_FMT_NONE; @@ -204,37 +204,40 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, if (isPaletteTexture) full_format = texformat | (tlutfmt << 16); - // hires texture loading and texture dumping require accurate hashes - if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures) + if (isPaletteTexture && (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures)) { - texHash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); - - if (isPaletteTexture) - { - // WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up) - // tlut size can be up to 32768B (GX_TF_C14X2) but Safer == Slower. - // This trick (to change the texID depending on the TLUT addr) is a trick to get around - // an issue with metroid prime's fonts, where it has multiple sets of fonts on top of - // each other stored in a single texture, and uses the palette to make different characters - // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, - // we must make sure that texture with different tluts get different IDs. - - const u64 tlutHash = GetHash64(texMem + tlutaddr, palette_size, - g_ActiveConfig.iSafeTextureCache_ColorSamples); - - texHash ^= tlutHash; - - if (g_ActiveConfig.bSafeTextureCache) - texID ^= ((u32)tlutHash) ^ (u32)(tlutHash >> 32); - } + const u32 palette_size = TexDecoder_GetPaletteSize(texformat); + tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + // NOTE: For non-paletted textures, texID is equal to the texture address. + // A paletted texture, however, may have multiple texIDs assigned though depending on the currently used tlut. + // This (changing texID depending on the tlut_hash) is a trick to get around + // an issue with Metroid Prime's fonts (it has multiple sets of fonts on each other + // stored in a single texture and uses the palette to make different characters + // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, + // we must make sure that a paletted texture gets assigned multiple IDs for each tlut used. + // + // TODO: Because texID isn't always the same as the address now, CopyRenderTargetToTexture might be broken now if (g_ActiveConfig.bSafeTextureCache) - hash_value = texHash; + texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); } + TCacheEntryBase *entry = textures[texID]; if (entry) { + // hires texture loading and texture dumping require accurate hashes + if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures) + { + texHash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + + if (isPaletteTexture) + texHash ^= tlut_hash; + + if (g_ActiveConfig.bSafeTextureCache) + hash_value = texHash; + } + // 1. Adjust reference hash: // safe texcache: reference hash was calculated above for normal textures. 0 for virtual EFB copies. // unsafe texcache: 0 for virtual EFB copies. Safe hash for dynamic EFB copies. First pixel for normal textures. @@ -254,7 +257,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, hash_value = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); if (isPaletteTexture) - hash_value ^= GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + hash_value ^= tlut_hash; // TODO: Ugly, this is using Safe Texture Cache parameters in nonsafe TC } } From 8c2d87f668ccc2f210bfbd379a04ced272a52d54 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 21:37:18 +0100 Subject: [PATCH 23/65] TextureCacheBase: Move around stuff, add some TODOs --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 926b86b29a..e7df59275e 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -173,12 +173,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, u32 address, unsigned int width, unsigned int height, int texformat, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel) { - // necessary? if (0 == address) return NULL; - u8* ptr = Memory::GetPointer(address); - // TexelSizeInNibbles(format)*width*height/16; const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat) - 1; const unsigned int bsh = TexDecoder_GetBlockHeightInTexels(texformat) - 1; @@ -187,20 +184,17 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, unsigned int expandedHeight = (height + bsh) & (~bsh); const unsigned int nativeW = width; const unsigned int nativeH = height; - bool isPow2; - u64 hash_value = TEXHASH_INVALID; - u64 texHash = TEXHASH_INVALID; - u64 tlut_hash = TEXHASH_INVALID; + // TODO: Force STC enabled when using custom textures or when dumping textures. There's no need for having two different texture hashes then. u32 texID = address; + u64 hash_value = TEXHASH_INVALID; // Hash assigned to texcache entry + u64 texHash = TEXHASH_INVALID; // Accurate hash used for texture dumping, hires texture lookup. Equal to hash_value with STC. + u64 tlut_hash = TEXHASH_INVALID; + u32 full_format = texformat; - const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); - bool texture_is_dynamic = false; - unsigned int texLevels; PC_TexFormat pcfmt = PC_TEX_FMT_NONE; const bool isPaletteTexture = (texformat == GX_TF_C4 || texformat == GX_TF_C8 || texformat == GX_TF_C14X2); - if (isPaletteTexture) full_format = texformat | (tlutfmt << 16); @@ -223,6 +217,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } + bool texture_is_dynamic = false; + const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); + + u8* ptr = Memory::GetPointer(address); + TCacheEntryBase *entry = textures[texID]; if (entry) { @@ -318,6 +317,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + bool isPow2; + unsigned int texLevels; UseNativeMips = UseNativeMips && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions isPow2 = !((width & (width - 1)) || (height & (height - 1))); texLevels = (isPow2 && UseNativeMips && maxlevel) ? @@ -333,6 +334,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // Sometimes, we can get around recreating a texture if only the number of mip levels gets changes // e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states // Thus, we don't update this member for every Load, but just whenever the texture gets recreated + // + // TODO: Won't we end up recreating textures all the time because maxlevel doesn't necessarily equal texLevels? entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage... GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); From 5239ba88c99c5516b412aa3dc408a448b2bd7eba Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 22:04:59 +0100 Subject: [PATCH 24/65] TextureCache: Remove unsafe texture cache --- Source/Core/DolphinWX/Src/VideoConfigDiag.cpp | 14 ++-- Source/Core/DolphinWX/Src/VideoConfigDiag.h | 7 +- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 64 ++++--------------- .../Core/VideoCommon/Src/TextureCacheBase.h | 3 - Source/Core/VideoCommon/Src/VideoConfig.cpp | 12 +--- Source/Core/VideoCommon/Src/VideoConfig.h | 1 - .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 7 +- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 7 +- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 3 +- 9 files changed, 26 insertions(+), 92 deletions(-) diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp index 45e239a835..8e1d221c39 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp @@ -455,18 +455,14 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con wxStaticBoxSizer* const szr_safetex = new wxStaticBoxSizer(wxHORIZONTAL, page_hacks, _("Texture Cache")); // TODO: Use wxSL_MIN_MAX_LABELS or wxSL_VALUE_LABEL with wx 2.9.1 - wxSlider* const stc_slider = new wxSlider(page_hacks, wxID_ANY, 0, 0, 3, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL|wxSL_BOTTOM); + wxSlider* const stc_slider = new wxSlider(page_hacks, wxID_ANY, 0, 0, 2, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL|wxSL_BOTTOM); _connect_macro_(stc_slider, VideoConfigDiag::Event_Stc, wxEVT_COMMAND_SLIDER_UPDATED, this); RegisterControl(stc_slider, wxGetTranslation(stc_desc)); - if (vconfig.bSafeTextureCache) - { - if (vconfig.iSafeTextureCache_ColorSamples == 0) stc_slider->SetValue(0); - else if (vconfig.iSafeTextureCache_ColorSamples == 512) stc_slider->SetValue(1); - else if (vconfig.iSafeTextureCache_ColorSamples == 128) stc_slider->SetValue(2); - else stc_slider->Disable(); // Using custom number of samples; TODO: Inform the user why this is disabled.. - } - else stc_slider->SetValue(3); + if (vconfig.iSafeTextureCache_ColorSamples == 0) stc_slider->SetValue(0); + else if (vconfig.iSafeTextureCache_ColorSamples == 512) stc_slider->SetValue(1); + else if (vconfig.iSafeTextureCache_ColorSamples == 128) stc_slider->SetValue(2); + else stc_slider->Disable(); // Using custom number of samples; TODO: Inform the user why this is disabled.. szr_safetex->Add(new wxStaticText(page_hacks, wxID_ANY, _("Accuracy:")), 0, wxALL, 5); szr_safetex->AddStretchSpacer(1); diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.h b/Source/Core/DolphinWX/Src/VideoConfigDiag.h index 5765524f03..e6b13a4092 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.h +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.h @@ -120,12 +120,7 @@ protected: void Event_Stc(wxCommandEvent &ev) { int samples[] = { 0, 512, 128 }; - if (ev.GetInt() < 3) - { - vconfig.iSafeTextureCache_ColorSamples = samples[ev.GetInt()]; - vconfig.bSafeTextureCache = true; - } - else vconfig.bSafeTextureCache = false; + vconfig.iSafeTextureCache_ColorSamples = samples[ev.GetInt()]; ev.Skip(); } diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index e7df59275e..369712bede 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -23,28 +23,19 @@ enum TextureCache *g_texture_cache; - GC_ALIGNED16(u8 *TextureCache::temp) = NULL; +GC_ALIGNED16(u8 *TextureCache::temp) = NULL; TextureCache::TexCache TextureCache::textures; bool TextureCache::DeferredInvalidate; TextureCache::TCacheEntryBase::~TCacheEntryBase() { - if (0 == addr) - return; - - if (!isRenderTarget && !g_ActiveConfig.bSafeTextureCache) - { - u32 *const ptr = (u32*)Memory::GetPointer(addr); - if (ptr && *ptr == hash) - *ptr = oldpixel; - } } TextureCache::TextureCache() { if (!temp) - temp =(u8*) AllocateAlignedMemory(TEMP_SIZE,16); + temp = (u8*)AllocateAlignedMemory(TEMP_SIZE,16); TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); @@ -198,7 +189,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, if (isPaletteTexture) full_format = texformat | (tlutfmt << 16); - if (isPaletteTexture && (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures)) + if (isPaletteTexture) { const u32 palette_size = TexDecoder_GetPaletteSize(texformat); tlut_hash = GetHash64(&texMem[tlutaddr], palette_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); @@ -212,8 +203,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // we must make sure that a paletted texture gets assigned multiple IDs for each tlut used. // // TODO: Because texID isn't always the same as the address now, CopyRenderTargetToTexture might be broken now - if (g_ActiveConfig.bSafeTextureCache) - texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); + texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); } @@ -225,40 +215,15 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, TCacheEntryBase *entry = textures[texID]; if (entry) { - // hires texture loading and texture dumping require accurate hashes - if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures) - { - texHash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + // 1. Calculate reference hash: + // calculated from RAM texture data for normal textures. Hashes for paletted textures are modified by tlut_hash. 0 for virtual EFB copies. + hash_value = texHash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); - if (isPaletteTexture) - texHash ^= tlut_hash; + if (isPaletteTexture) + hash_value = texHash ^= tlut_hash; - if (g_ActiveConfig.bSafeTextureCache) - hash_value = texHash; - } - - // 1. Adjust reference hash: - // safe texcache: reference hash was calculated above for normal textures. 0 for virtual EFB copies. - // unsafe texcache: 0 for virtual EFB copies. Safe hash for dynamic EFB copies. First pixel for normal textures. - if (g_ActiveConfig.bSafeTextureCache) - { - if (g_ActiveConfig.bCopyEFBToTexture && (entry->isRenderTarget || entry->isDynamic)) - hash_value = TEXHASH_INVALID; - } - else - { - if (!(entry->isRenderTarget || entry->isDynamic)) - hash_value = *(u32*)ptr; - else if (g_ActiveConfig.bCopyEFBToTexture) - hash_value = TEXHASH_INVALID; - else - { - hash_value = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); - - if (isPaletteTexture) - hash_value ^= tlut_hash; // TODO: Ugly, this is using Safe Texture Cache parameters in nonsafe TC - } - } + if (g_ActiveConfig.bCopyEFBToTexture && (entry->isRenderTarget || entry->isDynamic)) + hash_value = TEXHASH_INVALID; // 2. a) For EFB copies, only the hash and the texture address need to match if ((entry->isRenderTarget || entry->isDynamic) && hash_value == entry->hash && address == entry->addr) @@ -344,12 +309,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); entry->SetEFBCopyParameters(false, texture_is_dynamic); - entry->oldpixel = *(u32*)ptr; - - if (g_ActiveConfig.bSafeTextureCache || entry->isDynamic) - entry->hash = hash_value; - else - entry->hash = *(u32*)ptr = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); + entry->hash = hash_value; // load texture entry->Load(width, height, expandedWidth, 0, (texLevels == 0)); diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 7b14d737d2..7bc8c01480 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -38,9 +38,6 @@ public: // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames int frameCount; - // deprecated members - u32 oldpixel; - void SetGeneralParameters(u32 addr, u32 size, u32 format, unsigned int num_mipmaps) { diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index b6ba76f45e..5bb6e4dd99 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -57,12 +57,8 @@ void VideoConfig::Load(const char *ini_file) iniFile.Get("Settings", "Crop", &bCrop, false); iniFile.Get("Settings", "UseXFB", &bUseXFB, 0); iniFile.Get("Settings", "UseRealXFB", &bUseRealXFB, 0); - iniFile.Get("Settings", "UseNativeMips", &bUseNativeMips, false); - - iniFile.Get("Settings", "SafeTextureCache", &bSafeTextureCache, true); // Settings - //Safe texture cache params + iniFile.Get("Settings", "UseNativeMips", &bUseNativeMips, false); iniFile.Get("Settings", "SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples,128); - iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings iniFile.Get("Settings", "ShowInputDisplay", &bShowInputDisplay, false); iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false); @@ -134,7 +130,6 @@ void VideoConfig::GameIniLoad(const char *ini_file) iniFile.GetIfExists("Video_Settings", "UseXFB", &bUseXFB); iniFile.GetIfExists("Video_Settings", "UseRealXFB", &bUseRealXFB); iniFile.GetIfExists("Video_Settings", "UseNativeMips", &bUseNativeMips); - iniFile.GetIfExists("Video_Settings", "SafeTextureCache", &bSafeTextureCache); iniFile.GetIfExists("Video_Settings", "SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples); iniFile.GetIfExists("Video_Settings", "DLOptimize", &iCompileDLsLevel); iniFile.GetIfExists("Video_Settings", "HiresTextures", &bHiresTextures); @@ -196,11 +191,7 @@ void VideoConfig::Save(const char *ini_file) iniFile.Set("Settings", "UseXFB", bUseXFB); iniFile.Set("Settings", "UseRealXFB", bUseRealXFB); iniFile.Set("Settings", "UseNativeMips", bUseNativeMips); - - iniFile.Set("Settings", "SafeTextureCache", bSafeTextureCache); - //safe texture cache params iniFile.Set("Settings", "SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples); - iniFile.Set("Settings", "ShowFPS", bShowFPS); iniFile.Set("Settings", "ShowInputDisplay", bShowInputDisplay); iniFile.Set("Settings", "OverlayStats", bOverlayStats); @@ -279,7 +270,6 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini) SET_IF_DIFFERS("Video_Settings", "UseXFB", bUseXFB); SET_IF_DIFFERS("Video_Settings", "UseRealXFB", bUseRealXFB); SET_IF_DIFFERS("Video_Settings", "UseNativeMips", bUseNativeMips); - SET_IF_DIFFERS("Video_Settings", "SafeTextureCache", bSafeTextureCache); SET_IF_DIFFERS("Video_Settings", "SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples); SET_IF_DIFFERS("Video_Settings", "DLOptimize", iCompileDLsLevel); SET_IF_DIFFERS("Video_Settings", "HiresTextures", bHiresTextures); diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 3bd833cc73..7c846676bb 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -129,7 +129,6 @@ struct VideoConfig bool bOSDHotKey; bool bCopyEFBToTexture; bool bCopyEFBScaled; - bool bSafeTextureCache; int iSafeTextureCache_ColorSamples; int iPhackvalue[4]; std::string sPhackvalue[2]; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 07fe88d2b5..9328969abf 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -1106,12 +1106,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons DLCache::ProgressiveCleanup(); TextureCache::Cleanup(); - // reload textures if these settings changed - if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache || - g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) + // Reload textures if this settings changes + if (g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) TextureCache::Invalidate(false); - // Enable any configuration changes + // Enable configuration changes UpdateActiveConfig(); SetWindowSize(fbWidth, fbHeight); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 773172b0b8..f649323b73 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -1114,12 +1114,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons DLCache::ProgressiveCleanup(); TextureCache::Cleanup(); - // reload textures if these settings changed - if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache || - g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) + // Reload textures if these settings changed + if (g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) TextureCache::Invalidate(false); - // Enable any configuration changes + // Enable configuration changes UpdateActiveConfig(); SetWindowSize(fbWidth, fbHeight); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index e4c9dd8511..9883d35fbb 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -1394,8 +1394,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons g_Config.iSaveTargetId = 0; // reload textures if these settings changed - if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache || - g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) + if (g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) TextureCache::Invalidate(false); if (g_Config.bCopyEFBToTexture != g_ActiveConfig.bCopyEFBToTexture) From 67129404dd8d6944ccc5ad1ae24ece33ae5c8bba Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 26 Dec 2011 23:14:12 +0100 Subject: [PATCH 25/65] TextureCacheBase: Small bugfix Added documentation for hybrid EFB copy stuff --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 48 +++++++++++++++---- .../Core/VideoCommon/Src/TextureCacheBase.h | 2 +- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 369712bede..7c78b6f937 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -189,6 +189,10 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, if (isPaletteTexture) full_format = texformat | (tlutfmt << 16); + u8* ptr = Memory::GetPointer(address); + const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); + + hash_value = texHash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); if (isPaletteTexture) { const u32 palette_size = TexDecoder_GetPaletteSize(texformat); @@ -204,24 +208,15 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // // TODO: Because texID isn't always the same as the address now, CopyRenderTargetToTexture might be broken now texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); + hash_value = texHash ^= tlut_hash; } - bool texture_is_dynamic = false; - const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); - - u8* ptr = Memory::GetPointer(address); - TCacheEntryBase *entry = textures[texID]; if (entry) { // 1. Calculate reference hash: // calculated from RAM texture data for normal textures. Hashes for paletted textures are modified by tlut_hash. 0 for virtual EFB copies. - hash_value = texHash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); - - if (isPaletteTexture) - hash_value = texHash ^= tlut_hash; - if (g_ActiveConfig.bCopyEFBToTexture && (entry->isRenderTarget || entry->isDynamic)) hash_value = TEXHASH_INVALID; @@ -378,6 +373,39 @@ return_entry: void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) { + // Emulation methods: + // - EFB to RAM: + // Encodes the requested EFB data at its native resolution to the emulated RAM using shaders. + // Load() decodes the data from there again (using TextureDecoder) if the EFB copy is being used as a texture again. + // Advantage: CPU can read data from the EFB copy and we don't lose any important updates to the texture + // Disadvantage: Encoding+decoding steps often are redundant because only some games read or modify EFB copies before using them as textures. + // - EFB to texture: + // Copies the requested EFB data to a texture object in VRAM, performing any color conversion using shaders. + // Advantage: Works for many games, since in most cases EFB copies aren't read or modified at all before being used as a texture again. + // Since we don't do any further encoding or decoding here, this method is much faster. + // It also allows enhancing the visual quality by doing scaled EFB copies. + // - hybrid EFB copies: + // 1) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) + // 2a) If we haven't copied to the specified dstAddr yet, copy the requested EFB data to a texture object in VRAM as well (like EFB to texture) + // Create a texture cache entry for the render target (isRenderTarget = true, isDynamic = false) + // Store a hash of the encoded RAM data in the texcache entry. + // 2b) If we already have created a texcache entry for dstAddr (i.e. if we copied to dstAddr before) AND isDynamic is false: + // Do the same like above, but reuse the old texcache entry instead of creating a new one. + // 2c) If we already have created a texcache entry for dstAddr AND isDynamic is true (isRenderTarget will be false then) + // Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. + // Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd end up deleting it and reloading the data from RAM again anyway. + // 3) If the EFB copy gets used as a texture, compare the source RAM hash with the hash you stored when encoding the EFB data to RAM. + // 3a) If the two hashes match AND isDynamic is still false, reuse the VRAM copy you created + // 3b) If the two hashes differ AND isDynamic is still false, screw your existing VRAM copy. Set isRenderTarget to false and isDynamic to true. + // Redecode the source RAM data to a VRAM object. The entry basically behaves like a normal texture now. + // 3c) If isDynamic is true, treat the EFB copy like a normal texture. + // Advantage: Neither as fast as EFB to texture nor as slow as EFB to RAM, so it's a good compromise. + // Non-dynamic EFB copies can be visually enhanced like with EFB to texture. + // Compatibility ideally is as good as with EFB to RAM. + // Disadvantage: Depends on accurate texture hashing being enabled. However, with accurate hashing you end up being as slow as EFB to RAM anyway. + // + // Disadvantage of all methods: Calling this function requires the GPU to perform a pipeline flush which stalls any further CPU processing. + float colmat[28] = {0}; float *const fConstAdd = colmat + 16; float *const ColorMask = colmat + 20; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 7bc8c01480..6062e5accb 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -33,7 +33,7 @@ public: // EFB copies bool isRenderTarget; // copied from EFB - bool isDynamic; // Used for hybrid EFB copies to enable checks for CPU modifications + bool isDynamic; // Used for hybrid EFB copies to enable checks for CPU modifications, see CopyFromRenderTarget for details // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames int frameCount; From 3b38295cbd08c98e7654e8715a88f4456cd61de5 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 27 Dec 2011 00:05:26 +0100 Subject: [PATCH 26/65] TextureCacheBase: De-uglify hybrid EFB copies (documentation needs updating though) TextureCacheBase: Fixed dynamic EFB copies being set to normal textures. --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 36 ++++++++----------- .../Core/VideoCommon/Src/TextureCacheBase.h | 18 +++++----- .../Plugin_VideoDX11/Src/TextureCache.cpp | 2 +- .../Plugin_VideoDX9/Src/TextureCache.cpp | 2 +- .../Plugin_VideoOGL/Src/TextureCache.cpp | 2 +- 5 files changed, 27 insertions(+), 33 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 7c78b6f937..9b4891b98e 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -157,7 +157,7 @@ void TextureCache::ClearRenderTargets() iter = textures.begin(), tcend = textures.end(); for (; iter!=tcend; ++iter) - iter->second->isRenderTarget = false; + iter->second->efbcopy_state = EC_NO_COPY; } TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, @@ -211,20 +211,18 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, hash_value = texHash ^= tlut_hash; } - bool texture_is_dynamic = false; TCacheEntryBase *entry = textures[texID]; if (entry) { // 1. Calculate reference hash: // calculated from RAM texture data for normal textures. Hashes for paletted textures are modified by tlut_hash. 0 for virtual EFB copies. - if (g_ActiveConfig.bCopyEFBToTexture && (entry->isRenderTarget || entry->isDynamic)) + if (g_ActiveConfig.bCopyEFBToTexture && entry->IsEfbCopy()) hash_value = TEXHASH_INVALID; // 2. a) For EFB copies, only the hash and the texture address need to match - if ((entry->isRenderTarget || entry->isDynamic) && hash_value == entry->hash && address == entry->addr) + if (entry->IsEfbCopy() && hash_value == entry->hash && address == entry->addr) { // TODO: Print a warning if the format changes! In this case, we could reinterpret the internal texture object data to the new pixel format (similiar to what is already being done in Renderer::ReinterpretPixelFormat()) - entry->isDynamic = false; goto return_entry; } @@ -237,13 +235,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // 3. If we reach this line, we'll have to upload the new texture data to VRAM. // If we're lucky, the texture parameters didn't change and we can reuse the internal texture object instead of destroying and recreating it. - texture_is_dynamic = (entry->isRenderTarget || entry->isDynamic) && !g_ActiveConfig.bCopyEFBToTexture; - + // // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... - if (!entry->isRenderTarget && - ((!entry->isDynamic && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) - || (entry->isDynamic && entry->native_width == width && entry->native_height == height))) + if ((entry->efbcopy_state == EC_NO_COPY && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) + || (entry->efbcopy_state == EC_VRAM_DYNAMIC && entry->native_width == width && entry->native_height == height)) { // reuse the texture } @@ -297,14 +293,16 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // // TODO: Won't we end up recreating textures all the time because maxlevel doesn't necessarily equal texLevels? entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage... + entry->efbcopy_state = EC_NO_COPY; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); - entry->SetEFBCopyParameters(false, texture_is_dynamic); entry->hash = hash_value; + if (g_ActiveConfig.bCopyEFBToTexture) entry->efbcopy_state = EC_NO_COPY; + else if (entry->IsEfbCopy()) entry->efbcopy_state = EC_VRAM_DYNAMIC; // load texture entry->Load(width, height, expandedWidth, 0, (texLevels == 0)); @@ -608,15 +606,15 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat unsigned int scaled_tex_w = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledX(tex_w) : tex_w; unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h; - bool texture_is_dynamic = false; TCacheEntryBase *entry = textures[dstAddr]; if (entry) { - if ((entry->isRenderTarget && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h) - || (entry->isDynamic && entry->native_width == tex_w && entry->native_height == tex_h)) + if ((entry->efbcopy_state == EC_VRAM_READY && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h) + || (entry->efbcopy_state == EC_VRAM_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h)) { - texture_is_dynamic = entry->isDynamic; + scaled_tex_w = tex_w; + scaled_tex_h = tex_h; } else { @@ -626,12 +624,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat } } - if (texture_is_dynamic) - { - scaled_tex_w = tex_w; - scaled_tex_h = tex_h; - } - if (NULL == entry) { // create the texture @@ -640,8 +632,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat, 0); entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); - entry->SetEFBCopyParameters(true, false); entry->SetHashes(TEXHASH_INVALID); + entry->efbcopy_state = EC_VRAM_READY; } entry->frameCount = frameCount; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 6062e5accb..88a76776df 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -14,6 +14,13 @@ class TextureCache { public: + enum EFBCopyState + { + EC_NO_COPY, + EC_VRAM_READY, + EC_VRAM_DYNAMIC, + }; + struct TCacheEntryBase { #define TEXHASH_INVALID 0 @@ -32,8 +39,9 @@ public: unsigned int virtual_width, virtual_height; // Texture dimensions from OUR point of view - for hires textures or scaled EFB copies // EFB copies - bool isRenderTarget; // copied from EFB - bool isDynamic; // Used for hybrid EFB copies to enable checks for CPU modifications, see CopyFromRenderTarget for details + enum EFBCopyState efbcopy_state; + + bool IsEfbCopy() { return efbcopy_state != EC_NO_COPY; } // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames int frameCount; @@ -61,12 +69,6 @@ public: //this->pal_hash = pal_hash; } - void SetEFBCopyParameters(bool is_efb_copy, bool is_dynamic) - { - isRenderTarget = is_efb_copy; - isDynamic = is_dynamic; - } - virtual ~TCacheEntryBase(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index b1a5398d7d..05f0fa8629 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -102,7 +102,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo bool isIntensity, bool scaleByHalf, unsigned int cbufid, const float *colmat) { - if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture) + if (efbcopy_state != EC_VRAM_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { g_renderer->ResetAPIState(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 3f12678ca4..3bbd622c66 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -78,7 +78,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture(); - if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture) + if (efbcopy_state != EC_VRAM_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { LPDIRECT3DSURFACE9 Rendersurf = NULL; texture->GetSurfaceLevel(0, &Rendersurf); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index 91cc48d7d9..cc50cdc753 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -278,7 +278,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo GL_REPORT_ERRORD(); - if (false == isDynamic || g_ActiveConfig.bCopyEFBToTexture) + if (efbcopy_state != EC_VRAM_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { if (s_TempFramebuffer == 0) glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer); From a02df43e6d6b3950561c8df85851e5f24284c0fb Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Thu, 29 Dec 2011 23:48:08 +0100 Subject: [PATCH 27/65] TextureConverter (OGL/D3D9): Kill EncodeToRam because it wasn't used anywhere and it basically does the same as EncodeToRamFromTexture anyway --- .../Plugin_VideoDX9/Src/TextureConverter.cpp | 69 ------------------ .../Plugin_VideoDX9/Src/TextureConverter.h | 3 - .../Plugin_VideoOGL/Src/TextureConverter.cpp | 71 ------------------- .../Plugin_VideoOGL/Src/TextureConverter.h | 3 - 4 files changed, 146 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp index d14a3f29ea..e52cc4ebfb 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp @@ -313,75 +313,6 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr hr = s_texConvReadSurface->UnlockRect(); } -void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) -{ - u32 format = copyfmt; - - if (bFromZBuffer) - { - format |= _GX_TF_ZTF; - if (copyfmt == 11) - format = GX_TF_Z16; - else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) - format |= _GX_TF_CTF; - } - else - if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt)) - format |= _GX_TF_CTF; - - LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format); - if (!texconv_shader) - return; - - u8 *dest_ptr = Memory::GetPointer(address); - - LPDIRECT3DTEXTURE9 source_texture = bFromZBuffer ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture(); - int width = (source.right - source.left) >> bScaleByHalf; - int height = (source.bottom - source.top) >> bScaleByHalf; - - int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format); - - // Invalidate any existing texture covering this memory range. - // TODO - don't delete the texture if it already exists, just replace the contents. - TextureCache::InvalidateRange(address, size_in_bytes); - - u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; - u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; - u16 samples = TextureConversionShader::GetEncodedSampleCount(format); - - // only copy on cache line boundaries - // extra pixels are copied but not displayed in the resulting texture - s32 expandedWidth = (width + blkW) & (~blkW); - s32 expandedHeight = (height + blkH) & (~blkH); - - float sampleStride = bScaleByHalf ? 2.f : 1.f; - TextureConversionShader::SetShaderParameters( - (float)expandedWidth, - (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this? - (float)Renderer::EFBToScaledX(source.left), - (float)Renderer::EFBToScaledY(source.top), - Renderer::EFBToScaledXf(sampleStride), - Renderer::EFBToScaledYf(sampleStride), - (float)Renderer::GetTargetWidth(), - (float)Renderer::GetTargetHeight()); - - TargetRectangle scaledSource; - scaledSource.top = 0; - scaledSource.bottom = expandedHeight; - scaledSource.left = 0; - scaledSource.right = expandedWidth / samples; - int cacheBytes = 32; - if ((format & 0x0f) == 6) - cacheBytes = 64; - - int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); - g_renderer->ResetAPIState(); - EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0,1.0f); - D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); - D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - g_renderer->RestoreAPIState(); -} - u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) { u32 format = copyfmt; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h index aa4757e4c9..ca19d864e9 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h @@ -35,9 +35,6 @@ namespace TextureConverter void Init(); void Shutdown(); -void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, - u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); - void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight,float Gamma); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index c715775194..688c7cd5bc 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -250,77 +250,6 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar } -void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) -{ - u32 format = copyfmt; - - if (bFromZBuffer) - { - format |= _GX_TF_ZTF; - if (copyfmt == 11) - format = GX_TF_Z16; - else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) - format |= _GX_TF_CTF; - } - else - if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt)) - format |= _GX_TF_CTF; - - FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format); - if (texconv_shader.glprogid == 0) - return; - - u8 *dest_ptr = Memory::GetPointer(address); - - GLuint source_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source) : FramebufferManager::ResolveAndGetRenderTarget(source); - - int width = (source.right - source.left) >> bScaleByHalf; - int height = (source.bottom - source.top) >> bScaleByHalf; - - int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format); - - // Invalidate any existing texture covering this memory range. - // TODO - don't delete the texture if it already exists, just replace the contents. - TextureCache::InvalidateRange(address, size_in_bytes); - - u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; - u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; - u16 samples = TextureConversionShader::GetEncodedSampleCount(format); - - // only copy on cache line boundaries - // extra pixels are copied but not displayed in the resulting texture - s32 expandedWidth = (width + blkW) & (~blkW); - s32 expandedHeight = (height + blkH) & (~blkH); - - float sampleStride = bScaleByHalf ? 2.f : 1.f; - TextureConversionShader::SetShaderParameters( - (float)expandedWidth, - (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this? - (float)Renderer::EFBToScaledX(source.left), - (float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight), - Renderer::EFBToScaledXf(sampleStride), - Renderer::EFBToScaledYf(sampleStride)); - - TargetRectangle scaledSource; - scaledSource.top = 0; - scaledSource.bottom = expandedHeight; - scaledSource.left = 0; - scaledSource.right = expandedWidth / samples; - int cacheBytes = 32; - if ((format & 0x0f) == 6) - cacheBytes = 64; - - int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); - g_renderer->ResetAPIState(); - EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0); - FramebufferManager::SetFramebuffer(0); - VertexShaderManager::SetViewportChanged(); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - TextureCache::DisableStage(0); - g_renderer->RestoreAPIState(); - GL_REPORT_ERRORD(); -} - u64 EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) { u32 format = copyfmt; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h index 719ac1b7fc..7748b798c6 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h @@ -32,9 +32,6 @@ namespace TextureConverter void Init(); void Shutdown(); -void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, - u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); - void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight); From cc54ee7d946da000b635beae03d998543a02d71d Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 30 Dec 2011 01:00:34 +0100 Subject: [PATCH 28/65] TextureCache: Move EFB copy cache code from TextureConverter to TextureCache --- .../Plugin_VideoDX11/Src/TextureCache.cpp | 18 +++++------ .../Plugin_VideoDX9/Src/TextureCache.cpp | 30 ++++++++++++------- .../Plugin_VideoDX9/Src/TextureConverter.cpp | 21 ++++--------- .../Plugin_VideoDX9/Src/TextureConverter.h | 3 +- .../Plugin_VideoOGL/Src/TextureCache.cpp | 12 +++++++- .../Plugin_VideoOGL/Src/TextureConverter.cpp | 15 ++-------- .../Plugin_VideoOGL/Src/TextureConverter.h | 3 +- 7 files changed, 51 insertions(+), 51 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index 05f0fa8629..ce9bee771e 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -149,17 +149,15 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (!g_ActiveConfig.bCopyEFBToTexture) { u8* dst = Memory::GetPointer(dstAddr); - size_t encodeSize = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf); - hash = GetHash64(dst, encodeSize, g_ActiveConfig.iSafeTextureCache_ColorSamples); - if (g_ActiveConfig.bEFBCopyCacheEnable) - { - // If the texture in RAM is already in the texture cache, - // do not copy it again as it has not changed. - if (TextureCache::Find(dstAddr, hash)) - return; - } + size_t encoded_size = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf); - TextureCache::MakeRangeDynamic(dstAddr, encodeSize); + hash = GetHash64(dst, (int)encoded_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date + if (!g_ActiveConfig.bEFBCopyCacheEnable) + TextureCache::MakeRangeDynamic(addr, (u32)encoded_size); + else if (!TextureCache::Find(addr, hash)) + TextureCache::MakeRangeDynamic(addr, (u32)encoded_size); } } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 3bbd622c66..bc84857795 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -21,6 +21,7 @@ #include "Statistics.h" #include "MemoryUtil.h" #include "Hash.h" +#include "HW/Memmap.h" #include "CommonPaths.h" #include "FileUtil.h" @@ -143,16 +144,25 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (!g_ActiveConfig.bCopyEFBToTexture) { - hash = TextureConverter::EncodeToRamFromTexture( - addr, - read_texture, - Renderer::GetTargetWidth(), - Renderer::GetTargetHeight(), - srcFormat == PIXELFMT_Z24, - isIntensity, - dstFormat, - scaleByHalf, - srcRect); + int encoded_size = TextureConverter::EncodeToRamFromTexture( + addr, + read_texture, + Renderer::GetTargetWidth(), + Renderer::GetTargetHeight(), + srcFormat == PIXELFMT_Z24, + isIntensity, + dstFormat, + scaleByHalf, + srcRect); + + u8* dst = Memory::GetPointer(addr); + hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date + if (!g_ActiveConfig.bEFBCopyCacheEnable) + TextureCache::MakeRangeDynamic(addr,encoded_size); + else if (!TextureCache::Find(addr, hash)) + TextureCache::MakeRangeDynamic(addr,encoded_size); } D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp index e52cc4ebfb..7c38b154b9 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp @@ -252,10 +252,10 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr s_texConvReadSurface = TrnBuffers[index].ReadSurface; Rendersurf = TrnBuffers[index].RenderSurface; - + hr = D3D::dev->SetDepthStencilSurface(NULL); hr = D3D::dev->SetRenderTarget(0, Rendersurf); - + if (linearFilter) { D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); @@ -290,7 +290,7 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); // .. and then read back the results. // TODO: make this less slow. - + hr = D3D::dev->GetRenderTargetData(Rendersurf,s_texConvReadSurface); D3DLOCKED_RECT drect; @@ -313,7 +313,7 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr hr = s_texConvReadSurface->UnlockRect(); } -u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) +int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) { u32 format = copyfmt; @@ -371,16 +371,7 @@ u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 So int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0,1.0f); - u64 hash = GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); - if (g_ActiveConfig.bEFBCopyCacheEnable) - { - // If the texture in RAM is already in the texture cache, do not copy it again as it has not changed. - if (TextureCache::Find(address, hash)) - return hash; - } - - TextureCache::MakeRangeDynamic(address,size_in_bytes); - return hash; + return size_in_bytes; // TODO: D3D11 is calculating this value differently! } void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight,float Gamma) @@ -421,7 +412,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE destTexture->GetSurfaceLevel(0,&Rendersurf); D3D::dev->SetDepthStencilSurface(NULL); D3D::dev->SetRenderTarget(0, Rendersurf); - + D3DVIEWPORT9 vp; // Stretch picture with increased internal resolution diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h index ca19d864e9..4036f21447 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h @@ -40,7 +40,8 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture); -u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); +// returns size of the encoded data (in bytes) +int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index cc50cdc753..a1a7691907 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -39,6 +39,7 @@ #include "Globals.h" #include "Hash.h" #include "HiresTextures.h" +#include "HW/Memmap.h" #include "ImageWrite.h" #include "MemoryUtil.h" #include "PixelShaderCache.h" @@ -317,7 +318,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (false == g_ActiveConfig.bCopyEFBToTexture) { - hash = TextureConverter::EncodeToRamFromTexture( + int encoded_size = TextureConverter::EncodeToRamFromTexture( addr, read_texture, srcFormat == PIXELFMT_Z24, @@ -325,6 +326,15 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo dstFormat, scaleByHalf, srcRect); + + u8* dst = Memory::GetPointer(addr); + hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date + if (!g_ActiveConfig.bEFBCopyCacheEnable) + TextureCache::MakeRangeDynamic(addr,encoded_size); + else if (!TextureCache::Find(addr, hash)) + TextureCache::MakeRangeDynamic(addr,encoded_size); } FramebufferManager::SetFramebuffer(0); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index 688c7cd5bc..c73d3abdbf 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -250,7 +250,7 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar } -u64 EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) +int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) { u32 format = copyfmt; @@ -308,19 +308,8 @@ u64 EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer); + return size_in_bytes; // TODO: D3D11 is calculating this value differently! - u64 hash = GetHash64(dest_ptr, size_in_bytes, - g_ActiveConfig.iSafeTextureCache_ColorSamples); - if (g_ActiveConfig.bEFBCopyCacheEnable) - { - // If the texture in RAM is already in the texture cache, - // do not copy it again as it has not changed. - if (TextureCache::Find(address, hash)) - return hash; - } - - TextureCache::MakeRangeDynamic(address,size_in_bytes); - return hash; } void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h index 7748b798c6..4113778603 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h @@ -37,7 +37,8 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture); -u64 EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); +// returns size of the encoded data (in bytes) +int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); } From 9fed10fc75d63f38f97acbfcf68d4b1ee67ebb2a Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 30 Dec 2011 01:10:42 +0100 Subject: [PATCH 29/65] Remove SaveTexture declaration in VideoCommon since it's only actually defined in OpenGL --- Source/Core/VideoCommon/Src/ImageWrite.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Core/VideoCommon/Src/ImageWrite.h b/Source/Core/VideoCommon/Src/ImageWrite.h index 962ee5b5e7..9ea6cab859 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.h +++ b/Source/Core/VideoCommon/Src/ImageWrite.h @@ -21,7 +21,6 @@ #include "Common.h" bool SaveTGA(const char* filename, int width, int height, void* pdata); -bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height); bool SaveData(const char* filename, const char* pdata); #endif // _IMAGEWRITE_H From b34b6e47f20b055e3b35f28f04e99fc6de86415b Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 24 Jan 2012 15:25:01 +0100 Subject: [PATCH 30/65] TextureCacheBase: Remove a redundant variable --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 9b4891b98e..6f2c9ebd0c 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -176,10 +176,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, const unsigned int nativeW = width; const unsigned int nativeH = height; - // TODO: Force STC enabled when using custom textures or when dumping textures. There's no need for having two different texture hashes then. u32 texID = address; - u64 hash_value = TEXHASH_INVALID; // Hash assigned to texcache entry - u64 texHash = TEXHASH_INVALID; // Accurate hash used for texture dumping, hires texture lookup. Equal to hash_value with STC. + u64 tex_hash = TEXHASH_INVALID; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup) u64 tlut_hash = TEXHASH_INVALID; u32 full_format = texformat; @@ -192,7 +190,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, u8* ptr = Memory::GetPointer(address); const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); - hash_value = texHash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + tex_hash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); if (isPaletteTexture) { const u32 palette_size = TexDecoder_GetPaletteSize(texformat); @@ -208,7 +206,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // // TODO: Because texID isn't always the same as the address now, CopyRenderTargetToTexture might be broken now texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); - hash_value = texHash ^= tlut_hash; + tex_hash ^= tlut_hash; } TCacheEntryBase *entry = textures[texID]; @@ -217,17 +215,17 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // 1. Calculate reference hash: // calculated from RAM texture data for normal textures. Hashes for paletted textures are modified by tlut_hash. 0 for virtual EFB copies. if (g_ActiveConfig.bCopyEFBToTexture && entry->IsEfbCopy()) - hash_value = TEXHASH_INVALID; + tex_hash = TEXHASH_INVALID; // 2. a) For EFB copies, only the hash and the texture address need to match - if (entry->IsEfbCopy() && hash_value == entry->hash && address == entry->addr) + if (entry->IsEfbCopy() && tex_hash == entry->hash && address == entry->addr) { // TODO: Print a warning if the format changes! In this case, we could reinterpret the internal texture object data to the new pixel format (similiar to what is already being done in Renderer::ReinterpretPixelFormat()) goto return_entry; } // 2. b) For normal textures, all texture parameters need to match - if (address == entry->addr && hash_value == entry->hash && full_format == entry->format && + if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format && entry->num_mipmaps == maxlevel && entry->native_width == nativeW && entry->native_height == nativeH) { goto return_entry; @@ -259,7 +257,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, unsigned int newWidth = width; unsigned int newHeight = height; - sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (texHash & 0x00000000FFFFFFFFLL), texformat); + sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat); pcfmt = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, texformat, temp); if (pcfmt != PC_TEX_FMT_NONE) @@ -300,7 +298,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); - entry->hash = hash_value; + entry->hash = tex_hash; if (g_ActiveConfig.bCopyEFBToTexture) entry->efbcopy_state = EC_NO_COPY; else if (entry->IsEfbCopy()) entry->efbcopy_state = EC_VRAM_DYNAMIC; @@ -349,7 +347,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), - (u32) (texHash & 0x00000000FFFFFFFFLL), texformat); + (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat); if (false == File::Exists(szTemp)) entry->Save(szTemp); From cf899781f980ecf7dbe373a36c78a2a302e3951d Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 24 Jan 2012 16:38:27 +0100 Subject: [PATCH 31/65] TextureCacheBase: Update and improve documentation for EFB copies --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 40 +++++++++++-------- .../Core/VideoCommon/Src/TextureCacheBase.h | 6 +-- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 6f2c9ebd0c..0a59aeefa4 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -377,30 +377,36 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // Disadvantage: Encoding+decoding steps often are redundant because only some games read or modify EFB copies before using them as textures. // - EFB to texture: // Copies the requested EFB data to a texture object in VRAM, performing any color conversion using shaders. - // Advantage: Works for many games, since in most cases EFB copies aren't read or modified at all before being used as a texture again. + // Advantage: Works for many games, since in most cases EFB copies aren't read or modified at all before being used as a texture again. // Since we don't do any further encoding or decoding here, this method is much faster. // It also allows enhancing the visual quality by doing scaled EFB copies. // - hybrid EFB copies: - // 1) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) - // 2a) If we haven't copied to the specified dstAddr yet, copy the requested EFB data to a texture object in VRAM as well (like EFB to texture) - // Create a texture cache entry for the render target (isRenderTarget = true, isDynamic = false) - // Store a hash of the encoded RAM data in the texcache entry. - // 2b) If we already have created a texcache entry for dstAddr (i.e. if we copied to dstAddr before) AND isDynamic is false: - // Do the same like above, but reuse the old texcache entry instead of creating a new one. - // 2c) If we already have created a texcache entry for dstAddr AND isDynamic is true (isRenderTarget will be false then) - // Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. - // Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd end up deleting it and reloading the data from RAM again anyway. + // 1a) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) + // 1b) Set efbcopy_state to EC_VRAM_DYNAMIC for all texture cache entries in the destination address range. + // If EFB copy caching is enabled, further checks will (try to) prevent redundant EFB copies. + // 2) Check if a texture cache entry for the specified dstAddr already exists (i.e. if an EFB copy was triggered to that address before): + // 2a) Entry doesn't exist: + // - Also copy the requested EFB data to a texture object in VRAM (like EFB to texture) + // - Create a texture cache entry for the target (efbcopy_state = EC_VRAM_READY) + // - Store a hash of the encoded RAM data in the texcache entry. + // 2b) Entry exists AND efbcopy_state is EC_VRAM_READY: + // - Like case 2a, but reuse the old texcache entry instead of creating a new one. + // 2c) Entry exists AND efbcopy_state is EC_VRAM_DYNAMIC: + // - Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. + // - Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd always end up deleting it and reloading the data from RAM anyway. // 3) If the EFB copy gets used as a texture, compare the source RAM hash with the hash you stored when encoding the EFB data to RAM. - // 3a) If the two hashes match AND isDynamic is still false, reuse the VRAM copy you created - // 3b) If the two hashes differ AND isDynamic is still false, screw your existing VRAM copy. Set isRenderTarget to false and isDynamic to true. + // 3a) If the two hashes match AND efbcopy_state is EC_VRAM_READY, reuse the VRAM copy you created + // 3b) If the two hashes differ AND efbcopy_state is EC_VRAM_READY, screw your existing VRAM copy. Set efbcopy_state to EC_VRAM_DYNAMIC. // Redecode the source RAM data to a VRAM object. The entry basically behaves like a normal texture now. - // 3c) If isDynamic is true, treat the EFB copy like a normal texture. - // Advantage: Neither as fast as EFB to texture nor as slow as EFB to RAM, so it's a good compromise. - // Non-dynamic EFB copies can be visually enhanced like with EFB to texture. - // Compatibility ideally is as good as with EFB to RAM. - // Disadvantage: Depends on accurate texture hashing being enabled. However, with accurate hashing you end up being as slow as EFB to RAM anyway. + // 3c) If efbcopy_state is EC_VRAM_DYNAMIC, treat the EFB copy like a normal texture. + // Advantage: Non-dynamic EFB copies can be visually enhanced like with EFB to texture. + // Compatibility is as good as EFB to RAM. + // Disadvantage: Slower than EFB to texture and often even slower than EFB to RAM. + // EFB copy cache depends on accurate texture hashing being enabled. However, with accurate hashing you end up being as slow as without a copy cache anyway. // // Disadvantage of all methods: Calling this function requires the GPU to perform a pipeline flush which stalls any further CPU processing. + // + // For historical reasons, Dolphin doesn't actually implement "pure" EFB to RAM emulation, but only EFB to texture and hybrid EFB copies. float colmat[28] = {0}; float *const fConstAdd = colmat + 16; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 88a76776df..59960c7fb8 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -16,9 +16,9 @@ class TextureCache public: enum EFBCopyState { - EC_NO_COPY, - EC_VRAM_READY, - EC_VRAM_DYNAMIC, + EC_NO_COPY, // regular texture + EC_VRAM_READY, // EFB copy sits in VRAM and is ready to use + EC_VRAM_DYNAMIC, // EFB copy sits in RAM and needs to be decoded before using it as a texture }; struct TCacheEntryBase From 1446fb33d515fc300c33afd535b22f441544b86e Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sun, 29 Jan 2012 20:24:23 +0100 Subject: [PATCH 32/65] TextureCacheBase: Replace the efbcopy_state member variable of texture cache entries with a more general "texture type" --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 32 +++++++++---------- .../Core/VideoCommon/Src/TextureCacheBase.h | 18 +++++------ .../Plugin_VideoDX11/Src/TextureCache.cpp | 2 +- .../Plugin_VideoDX9/Src/TextureCache.cpp | 2 +- .../Plugin_VideoOGL/Src/TextureCache.cpp | 2 +- 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 0a59aeefa4..885116ae18 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -157,7 +157,7 @@ void TextureCache::ClearRenderTargets() iter = textures.begin(), tcend = textures.end(); for (; iter!=tcend; ++iter) - iter->second->efbcopy_state = EC_NO_COPY; + iter->second->type = TCET_AUTOFETCH; } TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, @@ -236,8 +236,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... - if ((entry->efbcopy_state == EC_NO_COPY && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) - || (entry->efbcopy_state == EC_VRAM_DYNAMIC && entry->native_width == width && entry->native_height == height)) + if ((entry->type == TCET_AUTOFETCH && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) + || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) { // reuse the texture } @@ -291,7 +291,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // // TODO: Won't we end up recreating textures all the time because maxlevel doesn't necessarily equal texLevels? entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage... - entry->efbcopy_state = EC_NO_COPY; + entry->type = TCET_AUTOFETCH; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } @@ -299,8 +299,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); entry->hash = tex_hash; - if (g_ActiveConfig.bCopyEFBToTexture) entry->efbcopy_state = EC_NO_COPY; - else if (entry->IsEfbCopy()) entry->efbcopy_state = EC_VRAM_DYNAMIC; + if (g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_AUTOFETCH; + else if (entry->IsEfbCopy()) entry->type = TCET_EC_DYNAMIC; // load texture entry->Load(width, height, expandedWidth, 0, (texLevels == 0)); @@ -382,23 +382,23 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // It also allows enhancing the visual quality by doing scaled EFB copies. // - hybrid EFB copies: // 1a) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) - // 1b) Set efbcopy_state to EC_VRAM_DYNAMIC for all texture cache entries in the destination address range. + // 1b) Set type to TCET_EC_DYNAMIC for all texture cache entries in the destination address range. // If EFB copy caching is enabled, further checks will (try to) prevent redundant EFB copies. // 2) Check if a texture cache entry for the specified dstAddr already exists (i.e. if an EFB copy was triggered to that address before): // 2a) Entry doesn't exist: // - Also copy the requested EFB data to a texture object in VRAM (like EFB to texture) - // - Create a texture cache entry for the target (efbcopy_state = EC_VRAM_READY) + // - Create a texture cache entry for the target (type = TCET_EC_VRAM) // - Store a hash of the encoded RAM data in the texcache entry. - // 2b) Entry exists AND efbcopy_state is EC_VRAM_READY: + // 2b) Entry exists AND type is TCET_EC_VRAM: // - Like case 2a, but reuse the old texcache entry instead of creating a new one. - // 2c) Entry exists AND efbcopy_state is EC_VRAM_DYNAMIC: + // 2c) Entry exists AND type is TCET_EC_DYNAMIC: // - Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. // - Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd always end up deleting it and reloading the data from RAM anyway. // 3) If the EFB copy gets used as a texture, compare the source RAM hash with the hash you stored when encoding the EFB data to RAM. - // 3a) If the two hashes match AND efbcopy_state is EC_VRAM_READY, reuse the VRAM copy you created - // 3b) If the two hashes differ AND efbcopy_state is EC_VRAM_READY, screw your existing VRAM copy. Set efbcopy_state to EC_VRAM_DYNAMIC. + // 3a) If the two hashes match AND type is TCET_EC_VRAM, reuse the VRAM copy you created + // 3b) If the two hashes differ AND type is TCET_EC_VRAM, screw your existing VRAM copy. Set type to TCET_EC_DYNAMIC. // Redecode the source RAM data to a VRAM object. The entry basically behaves like a normal texture now. - // 3c) If efbcopy_state is EC_VRAM_DYNAMIC, treat the EFB copy like a normal texture. + // 3c) If type is TCET_EC_DYNAMIC, treat the EFB copy like a normal texture. // Advantage: Non-dynamic EFB copies can be visually enhanced like with EFB to texture. // Compatibility is as good as EFB to RAM. // Disadvantage: Slower than EFB to texture and often even slower than EFB to RAM. @@ -614,8 +614,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TCacheEntryBase *entry = textures[dstAddr]; if (entry) { - if ((entry->efbcopy_state == EC_VRAM_READY && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h) - || (entry->efbcopy_state == EC_VRAM_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h)) + if ((entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h) + || (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h)) { scaled_tex_w = tex_w; scaled_tex_h = tex_h; @@ -637,7 +637,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->SetGeneralParameters(dstAddr, 0, dstFormat, 0); entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); entry->SetHashes(TEXHASH_INVALID); - entry->efbcopy_state = EC_VRAM_READY; + entry->type = TCET_EC_VRAM; } entry->frameCount = frameCount; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 59960c7fb8..b27663dd81 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -14,11 +14,12 @@ class TextureCache { public: - enum EFBCopyState + enum TexCacheEntryType { - EC_NO_COPY, // regular texture - EC_VRAM_READY, // EFB copy sits in VRAM and is ready to use - EC_VRAM_DYNAMIC, // EFB copy sits in RAM and needs to be decoded before using it as a texture + TCET_AUTOFETCH, // Most textures, automatically fetched whenever they change +// TCET_PRELOADED, // Textures which reside in TMEM areas which are manually managed by the game + TCET_EC_VRAM, // EFB copy which sits in VRAM and is ready to be used + TCET_EC_DYNAMIC, // EFB copy which sits in RAM and needs to be decoded before being used }; struct TCacheEntryBase @@ -32,17 +33,12 @@ public: //u32 pal_hash; u32 format; - //bool is_preloaded; + enum TexCacheEntryType type; unsigned int num_mipmaps; unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view unsigned int virtual_width, virtual_height; // Texture dimensions from OUR point of view - for hires textures or scaled EFB copies - // EFB copies - enum EFBCopyState efbcopy_state; - - bool IsEfbCopy() { return efbcopy_state != EC_NO_COPY; } - // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames int frameCount; @@ -83,6 +79,8 @@ public: const float *colmat) = 0; int IntersectsMemoryRange(u32 range_address, u32 range_size) const; + + bool IsEfbCopy() { return (type == TCET_EC_VRAM || type == TCET_EC_DYNAMIC); } }; virtual ~TextureCache(); // needs virtual for DX11 dtor diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index ce9bee771e..e59fbd496e 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -102,7 +102,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo bool isIntensity, bool scaleByHalf, unsigned int cbufid, const float *colmat) { - if (efbcopy_state != EC_VRAM_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) + if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { g_renderer->ResetAPIState(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index bc84857795..2a3f12ddcf 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -79,7 +79,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture(); - if (efbcopy_state != EC_VRAM_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) + if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { LPDIRECT3DSURFACE9 Rendersurf = NULL; texture->GetSurfaceLevel(0, &Rendersurf); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index a1a7691907..f78eb11905 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -279,7 +279,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo GL_REPORT_ERRORD(); - if (efbcopy_state != EC_VRAM_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) + if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { if (s_TempFramebuffer == 0) glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer); From d1605abfa98c39de0e9b9e57944f9dc864c03b42 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sun, 29 Jan 2012 21:55:07 +0100 Subject: [PATCH 33/65] Add license header for TextureCacheBase files --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 16 ++++++++++++++++ Source/Core/VideoCommon/Src/TextureCacheBase.h | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 885116ae18..f37e4b2dd5 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -1,3 +1,19 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ #include "MemoryUtil.h" diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index b27663dd81..7ae650a927 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -1,3 +1,19 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ #ifndef _TEXTURECACHEBASE_H #define _TEXTURECACHEBASE_H From 1f83078b5f1b00beff173510838b64be5b0434fa Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Sun, 21 Aug 2011 17:36:02 -0700 Subject: [PATCH 34/65] add some new game inis --- Data/User/GameConfig/G3LE8P.ini | 15 +++++++++++++++ Data/User/GameConfig/GP8EAF.ini | 15 +++++++++++++++ Data/User/GameConfig/JAEE01.ini | 9 +++++++++ Data/User/GameConfig/JBKP01.ini | 15 +++++++++++++++ Data/User/GameConfig/R8XE52.ini | 15 +++++++++++++++ Data/User/GameConfig/R9IE01.ini | 15 +++++++++++++++ Data/User/GameConfig/RBME5G.ini | 15 +++++++++++++++ Data/User/GameConfig/RGHE52.ini | 16 ++++++++++++++++ Data/User/GameConfig/RLBEWR.ini | 15 +++++++++++++++ Data/User/GameConfig/RS8J8N.ini | 15 +++++++++++++++ Data/User/GameConfig/SDFE4Q.ini | 15 +++++++++++++++ Data/User/GameConfig/SS3EWR.ini | 15 +++++++++++++++ Data/User/GameConfig/STEETR.ini | 15 +++++++++++++++ Data/User/GameConfig/WBME01.ini | 15 +++++++++++++++ Data/User/GameConfig/WPPJJF.ini | 15 +++++++++++++++ 15 files changed, 220 insertions(+) create mode 100644 Data/User/GameConfig/G3LE8P.ini create mode 100644 Data/User/GameConfig/GP8EAF.ini create mode 100644 Data/User/GameConfig/JAEE01.ini create mode 100644 Data/User/GameConfig/JBKP01.ini create mode 100644 Data/User/GameConfig/R8XE52.ini create mode 100644 Data/User/GameConfig/R9IE01.ini create mode 100644 Data/User/GameConfig/RBME5G.ini create mode 100644 Data/User/GameConfig/RGHE52.ini create mode 100644 Data/User/GameConfig/RLBEWR.ini create mode 100644 Data/User/GameConfig/RS8J8N.ini create mode 100644 Data/User/GameConfig/SDFE4Q.ini create mode 100644 Data/User/GameConfig/SS3EWR.ini create mode 100644 Data/User/GameConfig/STEETR.ini create mode 100644 Data/User/GameConfig/WBME01.ini create mode 100644 Data/User/GameConfig/WPPJJF.ini diff --git a/Data/User/GameConfig/G3LE8P.ini b/Data/User/GameConfig/G3LE8P.ini new file mode 100644 index 0000000000..88222a8531 --- /dev/null +++ b/Data/User/GameConfig/G3LE8P.ini @@ -0,0 +1,15 @@ +# G3LE8P - Super Monkey Ball Adventures (TM) +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/GP8EAF.ini b/Data/User/GameConfig/GP8EAF.ini new file mode 100644 index 0000000000..3a93ca340c --- /dev/null +++ b/Data/User/GameConfig/GP8EAF.ini @@ -0,0 +1,15 @@ +# GP8EAF - Pac-Man World 3 +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/JAEE01.ini b/Data/User/GameConfig/JAEE01.ini new file mode 100644 index 0000000000..136ba5f4b8 --- /dev/null +++ b/Data/User/GameConfig/JAEE01.ini @@ -0,0 +1,9 @@ +# JAEE01 - Donkey Kong Country +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +[Gecko] diff --git a/Data/User/GameConfig/JBKP01.ini b/Data/User/GameConfig/JBKP01.ini new file mode 100644 index 0000000000..28a848d52d --- /dev/null +++ b/Data/User/GameConfig/JBKP01.ini @@ -0,0 +1,15 @@ +# JBKP01 - +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/R8XE52.ini b/Data/User/GameConfig/R8XE52.ini new file mode 100644 index 0000000000..d5bddaa3fb --- /dev/null +++ b/Data/User/GameConfig/R8XE52.ini @@ -0,0 +1,15 @@ +# R8XE52 - Jurassic: The Hunted +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/R9IE01.ini b/Data/User/GameConfig/R9IE01.ini new file mode 100644 index 0000000000..c35e5b3d74 --- /dev/null +++ b/Data/User/GameConfig/R9IE01.ini @@ -0,0 +1,15 @@ +# R9IE01 - PIKMIN1 for Wii +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/RBME5G.ini b/Data/User/GameConfig/RBME5G.ini new file mode 100644 index 0000000000..d19e1189ba --- /dev/null +++ b/Data/User/GameConfig/RBME5G.ini @@ -0,0 +1,15 @@ +# RBME5G - Bust-a-Move BASH! +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/RGHE52.ini b/Data/User/GameConfig/RGHE52.ini new file mode 100644 index 0000000000..19739a552b --- /dev/null +++ b/Data/User/GameConfig/RGHE52.ini @@ -0,0 +1,16 @@ +# RGHE52 - Sample Game Name +[Core] Values set here will override the main dolphin settings. +FastDiscSpeed = 0 +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/RLBEWR.ini b/Data/User/GameConfig/RLBEWR.ini new file mode 100644 index 0000000000..b935a961b3 --- /dev/null +++ b/Data/User/GameConfig/RLBEWR.ini @@ -0,0 +1,15 @@ +# RLBEWR - LEGO Batman +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/RS8J8N.ini b/Data/User/GameConfig/RS8J8N.ini new file mode 100644 index 0000000000..156babedd9 --- /dev/null +++ b/Data/User/GameConfig/RS8J8N.ini @@ -0,0 +1,15 @@ +# RS8J8N - SHANGHAI +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/SDFE4Q.ini b/Data/User/GameConfig/SDFE4Q.ini new file mode 100644 index 0000000000..70292b9974 --- /dev/null +++ b/Data/User/GameConfig/SDFE4Q.ini @@ -0,0 +1,15 @@ +# SDFE4Q - Disney Sing It: Family Hits +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/SS3EWR.ini b/Data/User/GameConfig/SS3EWR.ini new file mode 100644 index 0000000000..185bc0b34d --- /dev/null +++ b/Data/User/GameConfig/SS3EWR.ini @@ -0,0 +1,15 @@ +# SS3EWR - Elmo's A to Zoo Adventure +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 5 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/STEETR.ini b/Data/User/GameConfig/STEETR.ini new file mode 100644 index 0000000000..e83497c5d9 --- /dev/null +++ b/Data/User/GameConfig/STEETR.ini @@ -0,0 +1,15 @@ +# STEETR - Tetris Party Deluxe +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/WBME01.ini b/Data/User/GameConfig/WBME01.ini new file mode 100644 index 0000000000..770a1b6b9e --- /dev/null +++ b/Data/User/GameConfig/WBME01.ini @@ -0,0 +1,15 @@ +# WBME01 - My Pokémon Ranch +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/WPPJJF.ini b/Data/User/GameConfig/WPPJJF.ini new file mode 100644 index 0000000000..4ecb121356 --- /dev/null +++ b/Data/User/GameConfig/WPPJJF.ini @@ -0,0 +1,15 @@ +# WPPJJF - JM‰OÔóÝóWii +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 0 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] From 3fb42f6bb618aa70c5879806885d838e920611cf Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Sun, 21 Aug 2011 18:20:22 -0700 Subject: [PATCH 35/65] split adding the ticket to its own function (installing a wad) --- Source/Core/DiscIO/Src/NANDContentLoader.cpp | 28 ++++++++++++-------- Source/Core/DiscIO/Src/NANDContentLoader.h | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.cpp b/Source/Core/DiscIO/Src/NANDContentLoader.cpp index c8e409636b..3e799ffd8b 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.cpp +++ b/Source/Core/DiscIO/Src/NANDContentLoader.cpp @@ -536,20 +536,14 @@ u64 CNANDContentManager::Install_WiiWAD(std::string &fileName) pTMDFile.Close(); + + + //Extract and copy WAD's ticket to ticket directory - std::string TicketFileName = Common::GetTicketFileName(TitleID); - - File::CreateFullPath(TicketFileName); - File::IOFile pTicketFile(TicketFileName, "wb"); - if (!pTicketFile) + if (!Add_Ticket(TitleID, ContentLoader.GetTIK(), ContentLoader.GetTIKSize())) { - PanicAlertT("WAD installation failed: error creating %s", TicketFileName.c_str()); + PanicAlertT("WAD installation failed: error creating ticket"); return 0; - } - - if (ContentLoader.GetTIK()) - { - pTicketFile.WriteBytes(ContentLoader.GetTIK(), ContentLoader.GetTIKSize()); } cUIDsys::AccessInstance().AddTitle(TitleID); @@ -558,6 +552,18 @@ u64 CNANDContentManager::Install_WiiWAD(std::string &fileName) return TitleID; } +bool Add_Ticket(u64 TitleID, const u8 *p_tik, u32 tikSize) +{ + std::string TicketFileName = Common::GetTicketFileName(TitleID); + File::CreateFullPath(TicketFileName); + File::IOFile pTicketFile(TicketFileName, "wb"); + if (!pTicketFile || !p_tik) + { + //PanicAlertT("WAD installation failed: error creating %s", TicketFileName.c_str()); + return false; + } + return pTicketFile.WriteBytes(p_tik, tikSize); +} } // namespace end diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.h b/Source/Core/DiscIO/Src/NANDContentLoader.h index 14a2062641..63135df693 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.h +++ b/Source/Core/DiscIO/Src/NANDContentLoader.h @@ -29,7 +29,7 @@ namespace DiscIO { - + bool Add_Ticket(u64 TitleID, const u8 *p_tik, u32 tikSize); struct SNANDContent { u32 m_ContentID; From 303d1b83eb09472a3f9a635d8c3b794a6c9b0286 Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Sun, 21 Aug 2011 18:25:01 -0700 Subject: [PATCH 36/65] minor cleanup to /dev/es, fix for grabbing titleid from the disc, and es_gettitledir --- .../Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 83c7544734..2a33d01ed9 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -93,7 +93,7 @@ bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode) { // blindly grab the titleID from the disc - it's unencrypted at: // offset 0x0F8001DC and 0x0F80044C - VolumeHandler::RAWReadToPtr((u8*)&m_TitleID, (u64)0x0F8001DC, 8); + VolumeHandler::GetVolume()->GetTitleID((u8*)&m_TitleID); m_TitleID = Common::swap64(m_TitleID); } else @@ -177,11 +177,11 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - const DiscIO::INANDContentLoader& rNANDCOntent = AccessContentDevice(TitleID); + const DiscIO::INANDContentLoader& rNANDContent = AccessContentDevice(TitleID); u16 NumberOfPrivateContent = 0; - if (rNANDCOntent.IsValid()) // Not sure if dolphin will ever fail this check + if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check { - NumberOfPrivateContent = rNANDCOntent.GetNumEntries(); + NumberOfPrivateContent = rNANDContent.GetNumEntries(); if ((u32)(TitleID>>32) == 0x00010000) Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address); @@ -191,10 +191,10 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) Memory::Write_U32(0, _CommandAddress + 0x4); } else - Memory::Write_U32((u32)rNANDCOntent.GetContentSize(), _CommandAddress + 0x4); + Memory::Write_U32((u32)rNANDContent.GetContentSize(), _CommandAddress + 0x4); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTSCNT: TitleID: %08x/%08x content count %i", - (u32)(TitleID>>32), (u32)TitleID, rNANDCOntent.IsValid() ? NumberOfPrivateContent : (u32)rNANDCOntent.GetContentSize()); + (u32)(TitleID>>32), (u32)TitleID, rNANDContent.IsValid() ? NumberOfPrivateContent : (u32)rNANDContent.GetContentSize()); return true; } @@ -371,7 +371,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); char* Path = (char*)Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); - sprintf(Path, "/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID); + sprintf(Path, "/title/%08x/%08x/data", (u32)(TitleID >> 32), (u32)TitleID); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLEDIR: %s", Path); } @@ -539,11 +539,6 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) const DiscIO::INANDContentLoader& Loader = AccessContentDevice(TitleID); - // Assert if title is not a disc title and the loader is not valid - _dbg_assert_msg_(WII_IPC_ES, ((u32)(TitleID >> 32) == 0x00010000) || - ((u32)(TitleID >> 32) == 0x00010004) || Loader.IsValid(), - "Loader not valid for TitleID %08x/%08x", (u32)(TitleID >> 32), (u32)TitleID); - u32 TMDViewCnt = 0; if (Loader.IsValid()) { @@ -675,7 +670,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) // TODO: actually use this param in when writing to the outbuffer :/ MaxCount = Memory::Read_U32(Buffer.InBuffer[1].m_Address); } - const DiscIO::INANDContentLoader& Loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(TitleID); + const DiscIO::INANDContentLoader& Loader = AccessContentDevice(TitleID); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount); @@ -856,7 +851,7 @@ const DiscIO::INANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u6 m_NANDContent[_TitleID] = &DiscIO::CNANDContentManager::Access().GetNANDLoader(_TitleID); - _dbg_assert_msg_(WII_IPC_ES, m_NANDContent[_TitleID]->IsValid(), "NandContent not valid for TitleID %08x/%08x", (u32)(_TitleID >> 32), (u32)_TitleID); + _dbg_assert_msg_(WII_IPC_ES, ((u32)(_TitleID >> 32) == 0x00010000) || m_NANDContent[_TitleID]->IsValid(), "NandContent not valid for TitleID %08x/%08x", (u32)(_TitleID >> 32), (u32)_TitleID); return *m_NANDContent[_TitleID]; } @@ -878,11 +873,10 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz) { return -1; } - std::string tmdPath = Common::GetTMDFileName(tmdTitleID), - dataPath = Common::GetTitleDataPath(tmdTitleID); + std::string tmdPath = Common::GetTMDFileName(tmdTitleID); File::CreateFullPath(tmdPath); - File::CreateFullPath(dataPath); + File::CreateFullPath(Common::GetTitleDataPath(tmdTitleID)); if(!File::Exists(tmdPath)) { File::IOFile _pTMDFile(tmdPath, "wb"); From 60594c079d2412e928aff6308cfce34cd6bec07d Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Sun, 21 Aug 2011 18:27:48 -0700 Subject: [PATCH 37/65] allow just ejecting the disc by canceling the file dialog --- Source/Core/DolphinWX/Src/FrameTools.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 2ca28ce4dd..607c920906 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -678,11 +678,8 @@ void CFrame::DoOpen(bool Boot) File::SetCurrentDir(currentDir); } - if (path.IsEmpty()) - return; - // Should we boot a new game or just change the disc? - if (Boot) + if (Boot && !path.IsEmpty()) BootGame(std::string(path.mb_str())); else { From c3e46d5b454738e96d2d62ed783573fe701b5c0b Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Sun, 21 Aug 2011 18:33:21 -0700 Subject: [PATCH 38/65] partial fix for issue 4742 --- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp index c02ada362f..126f3daeb4 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp @@ -211,7 +211,9 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 // Don't do anything if the log is unselected if (LogManager::GetInstance()->IsEnabled(LogTypes::FILEMON)) { - const char *pFilename = m_pFileSystem->GetFileName(DVDAddress); + const char *pFilename = NULL; + if (m_pFileSystem) + pFilename = m_pFileSystem->GetFileName(DVDAddress); if (pFilename != NULL) { INFO_LOG(WII_IPC_DVD, "DVDLowRead: %s (0x%llx) - (DVDAddr: 0x%llx, Size: 0x%x)", @@ -233,7 +235,7 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 if (!VolumeHandler::ReadToPtr(Memory::GetPointer(_BufferOut), DVDAddress, Size)) { - PanicAlertT("Cant read from DVD_Plugin - DVD-Interface: Fatal Error"); + PanicAlertT("DVDLowRead - Fatal Error: failed to read from volume"); } } break; @@ -325,10 +327,9 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 PanicAlertT("Detected attempt to read more data from the DVD than fit inside the out buffer. Clamp."); Size = _BufferOutSize; } - - if (!VolumeHandler::RAWReadToPtr(Memory::GetPointer(_BufferOut), DVDAddress, Size)) + if(!VolumeHandler::RAWReadToPtr(Memory::GetPointer(_BufferOut), DVDAddress, Size)) { - PanicAlertT("Cant read from DVD_Plugin - DVD-Interface: Fatal Error"); + PanicAlertT("DVDLowUnencryptedRead - Fatal Error: failed to read from volume"); } } break; @@ -348,7 +349,9 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 case DVDLowSeek: { u64 DVDAddress = Memory::Read_U32(_BufferIn + 0x4) << 2; - const char *pFilename = m_pFileSystem->GetFileName(DVDAddress); + const char *pFilename = NULL; + if (m_pFileSystem) + pFilename = m_pFileSystem->GetFileName(DVDAddress); if (pFilename != NULL) { INFO_LOG(WII_IPC_DVD, "DVDLowSeek: %s (0x%llx) - (DVDAddr: 0x%llx)", From 8e332948bff6355daaac33da013a05f8919ad084 Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Sun, 21 Aug 2011 21:09:18 -0700 Subject: [PATCH 39/65] less log noise from CNandContentLoader --- Source/Core/DiscIO/Src/NANDContentLoader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.cpp b/Source/Core/DiscIO/Src/NANDContentLoader.cpp index 3e799ffd8b..f010b7ed98 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.cpp +++ b/Source/Core/DiscIO/Src/NANDContentLoader.cpp @@ -191,6 +191,8 @@ const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const bool CNANDContentLoader::Initialize(const std::string& _rName) { + if (_rName.empty()) + return false; m_Path = _rName; WiiWAD Wad(_rName); u8* pDataApp = NULL; @@ -221,7 +223,7 @@ bool CNANDContentLoader::Initialize(const std::string& _rName) File::IOFile pTMDFile(TMDFileName, "rb"); if (!pTMDFile) { - ERROR_LOG(DISCIO, "CreateFromDirectory: error opening %s", + DEBUG_LOG(DISCIO, "CreateFromDirectory: error opening %s", TMDFileName.c_str()); return false; } From a0d6d682434852068fca1f6411dd130ebca366bb Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Sun, 21 Aug 2011 21:10:58 -0700 Subject: [PATCH 40/65] sysconf SetArayData use the minimum of the buffersize or the dataLength --- Source/Core/Common/Src/SysConf.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/Core/Common/Src/SysConf.h b/Source/Core/Common/Src/SysConf.h index 119cc3c45a..fb9c775828 100644 --- a/Source/Core/Common/Src/SysConf.h +++ b/Source/Core/Common/Src/SysConf.h @@ -66,10 +66,9 @@ struct SSysConfEntry } bool SetArrayData(u8* buffer, u16 bufferSize) { - - if (buffer && bufferSize <= dataLength) + if (buffer) { - memcpy(data, buffer, bufferSize); + memcpy(data, buffer, min(bufferSize, dataLength)); return true; } return false; From a78c5f984feaac4fce6d77e9329ef3dbb17d3b22 Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Tue, 31 Jan 2012 20:31:30 -0800 Subject: [PATCH 41/65] download codes for virtualconsole titles --- Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp index e9089c6006..dccc697942 100644 --- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp +++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp @@ -151,9 +151,18 @@ void CodeConfigPanel::DownloadCodes(wxCommandEvent&) std::string gameid = m_gameid; - // WiiWare are identified by their first four characters - if (m_gameid[0] == 'W') + + switch (m_gameid[0]) + { + case 'R': + case 'S': + case 'G': + break; + default: + // All channels (WiiWare, VirtualConsole, etc) are identified by their first four characters gameid = m_gameid.substr(0, 4); + break; + } sf::Http::Request req; req.SetURI("/txt.php?txt=" + gameid); From d6de53f235a269c484f5f12f8adcc8ab9f62ef10 Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Tue, 31 Jan 2012 23:49:47 -0800 Subject: [PATCH 42/65] convert name, notes and creator to wxstring using *wxConvCurrent instead of FromAscii. fix issue 5069 --- Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp index dccc697942..cffeb25e7f 100644 --- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp +++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp @@ -78,7 +78,7 @@ void CodeConfigPanel::UpdateCodeList() gcodes_end = m_gcodes.end(); for (; gcodes_iter!=gcodes_end; ++gcodes_iter) { - m_listbox_gcodes->Append(wxString::FromAscii(gcodes_iter->name.c_str())); + m_listbox_gcodes->Append(wxString(gcodes_iter->name.c_str(), *wxConvCurrent)); if (gcodes_iter->enabled) m_listbox_gcodes->Check(m_listbox_gcodes->GetCount()-1, true); } @@ -111,7 +111,7 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&) if (sel > -1) { - m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + wxString::FromAscii(m_gcodes[sel].name.c_str())); + m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + wxString(m_gcodes[sel].name.c_str(), *wxConvCurrent)); // notes textctrl m_infobox.textctrl_notes->Clear(); @@ -119,10 +119,10 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&) notes_iter = m_gcodes[sel].notes.begin(), notes_end = m_gcodes[sel].notes.end(); for (; notes_iter!=notes_end; ++notes_iter) - m_infobox.textctrl_notes->AppendText(wxString::FromAscii(notes_iter->c_str())); + m_infobox.textctrl_notes->AppendText(wxString(notes_iter->c_str(), *wxConvCurrent)); m_infobox.textctrl_notes->ScrollLines(-99); // silly - m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + wxString::FromAscii(m_gcodes[sel].creator.c_str())); + m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + wxString(m_gcodes[sel].creator.c_str(), *wxConvCurrent)); // add codes to info listbox std::vector::const_iterator From 20a4735b4da47b13ee56954bb09ae5b02f944165 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Thu, 2 Feb 2012 14:02:39 +0100 Subject: [PATCH 43/65] Update some license headers. --- Source/Core/Core/Src/DSP/DSPCore.cpp | 2 +- Source/Core/Core/Src/DSP/DSPCore.h | 2 +- Source/Core/Core/Src/DSP/DSPHWInterface.cpp | 2 +- Source/Core/Core/Src/DSP/DSPHWInterface.h | 2 +- Source/Core/Core/Src/DSP/DSPIntExtOps.h | 2 +- Source/Core/Core/Src/DSP/DSPIntUtil.h | 2 +- Source/Core/Core/Src/DSP/DSPInterpreter.cpp | 2 +- Source/Core/Core/Src/DSP/DSPMemoryMap.cpp | 2 +- Source/Core/Core/Src/DSP/DSPMemoryMap.h | 2 +- Source/Core/Core/Src/DSP/DSPStacks.cpp | 2 +- Source/Core/Core/Src/DSP/DSPStacks.h | 2 +- Source/Core/Core/Src/DSP/disassemble.cpp | 2 +- Source/Core/Core/Src/DSP/disassemble.h | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Source/Core/Core/Src/DSP/DSPCore.cpp b/Source/Core/Core/Src/DSP/DSPCore.cpp index bd2b3aa8e6..972eb53858 100644 --- a/Source/Core/Core/Src/DSP/DSPCore.cpp +++ b/Source/Core/Core/Src/DSP/DSPCore.cpp @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPCore.h b/Source/Core/Core/Src/DSP/DSPCore.h index f6a3b4e51f..34466ea4ad 100644 --- a/Source/Core/Core/Src/DSP/DSPCore.h +++ b/Source/Core/Core/Src/DSP/DSPCore.h @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp index 63cff1651f..f2cbbc2b9f 100644 --- a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp +++ b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPHWInterface.h b/Source/Core/Core/Src/DSP/DSPHWInterface.h index d44bc70ea7..13ea8cf7a1 100644 --- a/Source/Core/Core/Src/DSP/DSPHWInterface.h +++ b/Source/Core/Core/Src/DSP/DSPHWInterface.h @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPIntExtOps.h b/Source/Core/Core/Src/DSP/DSPIntExtOps.h index 33420a5b76..fa6d22edba 100644 --- a/Source/Core/Core/Src/DSP/DSPIntExtOps.h +++ b/Source/Core/Core/Src/DSP/DSPIntExtOps.h @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPIntUtil.h b/Source/Core/Core/Src/DSP/DSPIntUtil.h index 1da1c4eb21..49f8c209c2 100644 --- a/Source/Core/Core/Src/DSP/DSPIntUtil.h +++ b/Source/Core/Core/Src/DSP/DSPIntUtil.h @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPInterpreter.cpp b/Source/Core/Core/Src/DSP/DSPInterpreter.cpp index 8c3a59dbd9..4a841b41e5 100644 --- a/Source/Core/Core/Src/DSP/DSPInterpreter.cpp +++ b/Source/Core/Core/Src/DSP/DSPInterpreter.cpp @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPMemoryMap.cpp b/Source/Core/Core/Src/DSP/DSPMemoryMap.cpp index 408cb48465..1cbced0713 100644 --- a/Source/Core/Core/Src/DSP/DSPMemoryMap.cpp +++ b/Source/Core/Core/Src/DSP/DSPMemoryMap.cpp @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPMemoryMap.h b/Source/Core/Core/Src/DSP/DSPMemoryMap.h index 8aa0d77647..c271537130 100644 --- a/Source/Core/Core/Src/DSP/DSPMemoryMap.h +++ b/Source/Core/Core/Src/DSP/DSPMemoryMap.h @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPStacks.cpp b/Source/Core/Core/Src/DSP/DSPStacks.cpp index 511dd623ae..d1e70a616a 100644 --- a/Source/Core/Core/Src/DSP/DSPStacks.cpp +++ b/Source/Core/Core/Src/DSP/DSPStacks.cpp @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/DSPStacks.h b/Source/Core/Core/Src/DSP/DSPStacks.h index 1a5b9e872c..cb808ee8a7 100644 --- a/Source/Core/Core/Src/DSP/DSPStacks.h +++ b/Source/Core/Core/Src/DSP/DSPStacks.h @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/disassemble.cpp b/Source/Core/Core/Src/DSP/disassemble.cpp index 3547e7d766..99bd2811b3 100644 --- a/Source/Core/Core/Src/DSP/disassemble.cpp +++ b/Source/Core/Core/Src/DSP/disassemble.cpp @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ diff --git a/Source/Core/Core/Src/DSP/disassemble.h b/Source/Core/Core/Src/DSP/disassemble.h index dba9f36287..c9c0a304c1 100644 --- a/Source/Core/Core/Src/DSP/disassemble.h +++ b/Source/Core/Core/Src/DSP/disassemble.h @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ====================================================================*/ From dabb35afce2539b312935d2fcfe264018d24dbec Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sun, 29 Jan 2012 21:17:22 +0100 Subject: [PATCH 44/65] Prepare texture preloading support --- .../Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp | 8 ++-- Source/Core/VideoCommon/Src/BPMemory.h | 41 +++++++++++++------ Source/Core/VideoCommon/Src/BPStructs.cpp | 27 ++++++++---- Source/Core/VideoCommon/Src/TextureDecoder.h | 4 +- .../Plugin_VideoSoftware/Src/BPMemLoader.cpp | 6 +-- 5 files changed, 56 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp index 4b22e8f851..58ad9eded3 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoAnalyzer.cpp @@ -85,14 +85,14 @@ void LoadBPReg(const BPCmd &bp, BPMemory &bpMem) void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem) { - tlutAddr = (bpMem.tlutXferDest & 0x3FF) << 9; - tlutXferCount = (bpMem.tlutXferDest & 0x1FFC00) >> 5; + tlutAddr = (bpMem.tmem_config.tlut_dest & 0x3FF) << 9; + tlutXferCount = (bpMem.tmem_config.tlut_dest & 0x1FFC00) >> 5; // TODO - figure out a cleaner way. if (Core::g_CoreStartupParameter.bWii) - memAddr = bpmem.tlutXferSrc << 5; + memAddr = bpmem.tmem_config.tlut_src << 5; else - memAddr = (bpmem.tlutXferSrc & 0xFFFFF) << 5; + memAddr = (bpmem.tmem_config.tlut_src & 0xFFFFF) << 5; } void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem) diff --git a/Source/Core/VideoCommon/Src/BPMemory.h b/Source/Core/VideoCommon/Src/BPMemory.h index 1f6f453a77..0bb2bf9013 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.h +++ b/Source/Core/VideoCommon/Src/BPMemory.h @@ -65,10 +65,10 @@ #define BPMEM_UNKOWN_57 0x57 #define BPMEM_REVBITS 0x58 #define BPMEM_SCISSOROFFSET 0x59 -#define BPMEM_UNKNOWN_60 0x60 -#define BPMEM_UNKNOWN_61 0x61 -#define BPMEM_UNKNOWN_62 0x62 -#define BPMEM_TEXMODESYNC 0x63 +#define BPMEM_PRELOAD_ADDR 0x60 +#define BPMEM_PRELOAD_TMEMEVEN 0x61 +#define BPMEM_PRELOAD_TMEMODD 0x62 +#define BPMEM_PRELOAD_MODE 0x63 #define BPMEM_LOADTLUT0 0x64 #define BPMEM_LOADTLUT1 0x65 #define BPMEM_TEXINVALIDATE 0x66 @@ -487,10 +487,10 @@ union TexImage1 { struct { - u32 tmem_offset : 15; // we ignore texture caching for now, we do it ourselves - u32 cache_width : 3; + u32 tmem_even : 15; // tmem line index for even LODs + u32 cache_width : 3; u32 cache_height : 3; - u32 image_type : 1; + u32 image_type : 1; // 1 if this texture is managed manually (0 means we'll autofetch the texture data whenever it changes) }; u32 hex; }; @@ -499,7 +499,7 @@ union TexImage2 { struct { - u32 tmem_offset : 15; // we ignore texture caching for now, we do it ourselves + u32 tmem_odd : 15; // tmem line index for odd LODs u32 cache_width : 3; u32 cache_height : 3; }; @@ -893,6 +893,25 @@ union UPE_Copy } }; +union BPU_PreloadTileInfo +{ + u32 hex; + struct { + u32 count : 15; + u32 type : 2; + }; +}; + +struct BPS_TmemConfig +{ + u32 preload_addr; + u32 preload_tmem_even; + u32 preload_tmem_odd; + BPU_PreloadTileInfo preload_tile_info; + u32 tlut_src; + u32 tlut_dest; + u32 texinvalidate; +}; // All of BP memory @@ -951,10 +970,8 @@ struct BPMemory u32 boundbox1;//56 u32 unknown7[2];//57,58 X10Y10 scissorOffset; //59 - u32 unknown8[10]; //5a,5b,5c,5d, 5e,5f,60,61, 62, 63 (GXTexModeSync), 0x60-0x63 have to do with preloaded textures? - u32 tlutXferSrc; //64 - u32 tlutXferDest; //65 - u32 texinvalidate;//66 + u32 unknown8[6]; //5a,5b,5c,5d, 5e,5f + BPS_TmemConfig tmem_config; // 60-66 u32 metric; //67 FieldMode fieldmode;//68 u32 unknown10[7];//69-6F diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index d06f1de8b9..6cb102555b 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -30,6 +30,7 @@ #include "VertexLoader.h" #include "VertexShaderManager.h" #include "Thread.h" +#include "HW/Memmap.h" using namespace BPFunctions; @@ -301,14 +302,14 @@ void BPWritten(const BPCmd& bp) // TODO - figure out a cleaner way. if (GetConfig(CONFIG_ISWII)) - ptr = GetPointer(bpmem.tlutXferSrc << 5); + ptr = GetPointer(bpmem.tmem_config.tlut_src << 5); else - ptr = GetPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5); + ptr = GetPointer((bpmem.tmem_config.tlut_src & 0xFFFFF) << 5); if (ptr) memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount); else - PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5); + PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5); // TODO(ector) : kill all textures that use this palette // Not sure if it's a good idea, though. For now, we hash texture palettes @@ -466,14 +467,22 @@ void BPWritten(const BPCmd& bp) DEBUG_LOG(VIDEO, "Uknown BP Reg 0x57: %08x", bp.newvalue); break; - case BPMEM_UNKNOWN_60: - case BPMEM_UNKNOWN_61: - case BPMEM_UNKNOWN_62: - // Cases added due to: http://code.google.com/p/dolphin-emu/issues/detail?id=360#c90 - // Are these related to BBox? + case BPMEM_PRELOAD_ADDR: + case BPMEM_PRELOAD_TMEMEVEN: + case BPMEM_PRELOAD_TMEMODD: // Used when PRELOAD_MODE is set break; - case BPMEM_TEXMODESYNC: // Always set to 0 when GX_TexModeSync() is called. + case BPMEM_PRELOAD_MODE: // Set to 0 when GX_TexModeSync() is called. + // if this is different from 0, manual TMEM management is used. + if (bp.newvalue != 0) + { + // NOTE(neobrain): Apparently tmemodd doesn't affect hardware behavior at all (libogc uses it just as a buffer and switches its contents with tmemeven whenever this is called) + BPS_TmemConfig& tmem_cfg = bpmem.tmem_config; + u8* ram_ptr = Memory::GetPointer(tmem_cfg.preload_addr << 5); + u32 tmem_addr = tmem_cfg.preload_tmem_even * TMEM_LINE_SIZE; + u32 size = tmem_cfg.preload_tile_info.count * 32; + memcpy(texMem + tmem_addr, ram_ptr, size); + } break; // ------------------------------------------------ diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.h b/Source/Core/VideoCommon/Src/TextureDecoder.h index d990d21545..1901c86d27 100644 --- a/Source/Core/VideoCommon/Src/TextureDecoder.h +++ b/Source/Core/VideoCommon/Src/TextureDecoder.h @@ -20,8 +20,8 @@ #include "Hash.h" enum { - TMEM_SIZE = 1024*1024, - HALFTMEM_SIZE = 512*1024 + TMEM_SIZE = 1024*1024, + TMEM_LINE_SIZE = 32, }; extern GC_ALIGNED16(u8 texMem[TMEM_SIZE]); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp index 404424f634..95ec555181 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp @@ -101,14 +101,14 @@ void SWBPWritten(int address, int newvalue) // TODO - figure out a cleaner way. if (Core::g_CoreStartupParameter.bWii) - ptr = Memory::GetPointer(bpmem.tlutXferSrc << 5); + ptr = Memory::GetPointer(bpmem.tmem_config.tlut_src << 5); else - ptr = Memory::GetPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5); + ptr = Memory::GetPointer((bpmem.tmem_config.tlut_src & 0xFFFFF) << 5); if (ptr) memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount); else - PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5); + PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5); break; } From eb01a110c9573ae0e822eefd3cc8c58d92774588 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sun, 29 Jan 2012 21:49:50 +0100 Subject: [PATCH 45/65] Implement texture preloading --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 42 ++++++++++++------- .../Core/VideoCommon/Src/TextureCacheBase.h | 5 +-- .../Plugin_VideoDX11/Src/VertexManager.cpp | 3 +- .../Plugin_VideoDX9/Src/VertexManager.cpp | 3 +- .../Plugin_VideoOGL/Src/VertexManager.cpp | 3 +- 5 files changed, 36 insertions(+), 20 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index f37e4b2dd5..7873d1474e 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -173,12 +173,12 @@ void TextureCache::ClearRenderTargets() iter = textures.begin(), tcend = textures.end(); for (; iter!=tcend; ++iter) - iter->second->type = TCET_AUTOFETCH; + iter->second->type = TCET_NORMAL; } TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, u32 address, unsigned int width, unsigned int height, int texformat, - unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel) + unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem) { if (0 == address) return NULL; @@ -203,10 +203,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, if (isPaletteTexture) full_format = texformat | (tlutfmt << 16); - u8* ptr = Memory::GetPointer(address); const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); + u8* src_data; + if (from_tmem) src_data = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE]; + else src_data = Memory::GetPointer(address); - tex_hash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + tex_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); if (isPaletteTexture) { const u32 palette_size = TexDecoder_GetPaletteSize(texformat); @@ -225,7 +227,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, tex_hash ^= tlut_hash; } - TCacheEntryBase *entry = textures[texID]; + TCacheEntryBase *entry = textures[texID]; // TODO: Should use a different texID for preloaded textures! if (entry) { // 1. Calculate reference hash: @@ -252,7 +254,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... - if ((entry->type == TCET_AUTOFETCH && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) + if ((entry->type == TCET_NORMAL && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) { // reuse the texture @@ -283,8 +285,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } } + // TODO: RGBA8 textures are stored non-continuously in tmem, that might cause problems when preloading is enabled if (pcfmt == PC_TEX_FMT_NONE) - pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, + pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); bool isPow2; @@ -301,13 +304,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, if (NULL == entry) { textures[texID] = entry = g_texture_cache->CreateTexture(width, height, expandedWidth, texLevels, pcfmt); - // Sometimes, we can get around recreating a texture if only the number of mip levels gets changes + // Sometimes, we can get around recreating a texture if only the number of mip levels changes // e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states // Thus, we don't update this member for every Load, but just whenever the texture gets recreated // // TODO: Won't we end up recreating textures all the time because maxlevel doesn't necessarily equal texLevels? entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage... - entry->type = TCET_AUTOFETCH; + entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } @@ -315,13 +318,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); entry->hash = tex_hash; - if (g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_AUTOFETCH; + if (g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_NORMAL; else if (entry->IsEfbCopy()) entry->type = TCET_EC_DYNAMIC; // load texture entry->Load(width, height, expandedWidth, 0, (texLevels == 0)); - // load mips + // load mips - TODO: Loading mipmaps from tmem is untested! if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE) { const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat); @@ -329,20 +332,31 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, unsigned int level = 1; unsigned int mipWidth = (width + 1) >> 1; unsigned int mipHeight = (height + 1) >> 1; - ptr += texture_size; + + u8* ptr_even = NULL, *ptr_odd = NULL; + if (from_tmem) + { + ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size]; + ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; + } + src_data += texture_size; while ((mipHeight || mipWidth) && (level < texLevels)) { + u8** ptr; + if (from_tmem) ptr = (level % 2) ? &ptr_odd : &ptr_even; + else ptr = &src_data; + const unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1; const unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1; expandedWidth = (currentWidth + bsw) & (~bsw); expandedHeight = (currentHeight + bsh) & (~bsh); - TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); entry->Load(currentWidth, currentHeight, expandedWidth, level, false); - ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1); + *ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1); mipWidth >>= 1; mipHeight >>= 1; ++level; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 7ae650a927..2924c5871f 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -32,8 +32,7 @@ class TextureCache public: enum TexCacheEntryType { - TCET_AUTOFETCH, // Most textures, automatically fetched whenever they change -// TCET_PRELOADED, // Textures which reside in TMEM areas which are manually managed by the game + TCET_NORMAL, TCET_EC_VRAM, // EFB copy which sits in VRAM and is ready to be used TCET_EC_DYNAMIC, // EFB copy which sits in RAM and needs to be decoded before being used }; @@ -115,7 +114,7 @@ public: virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0; static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height, - int format, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel); + int format, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem); static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index 9087b6dac1..d0f5a1c338 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -228,7 +228,8 @@ void VertexManager::vFlush() tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, (tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips, - (tex.texMode1[i&3].max_lod >> 4)); + tex.texMode1[i&3].max_lod >> 4, + tex.texImage1[i&3].image_type); if (tentry) { diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index c6bddb7468..c4e8225db1 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -137,7 +137,8 @@ void VertexManager::vFlush() tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, (tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips, - (tex.texMode1[i&3].max_lod >> 4)); + tex.texMode1[i&3].max_lod >> 4, + tex.texImage1[i&3].image_type); if (tentry) { diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index e3b55987ec..dff7f8299e 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -155,7 +155,8 @@ void VertexManager::vFlush() tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, (tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips, - (tex.texMode1[i&3].max_lod >> 4)); + tex.texMode1[i&3].max_lod >> 4, + tex.texImage1[i&3].image_type); if (tentry) { From ea2e0e90633535112c95e999634b1bb1111a98bd Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 4 Feb 2012 13:25:04 +1100 Subject: [PATCH 46/65] Added the HID2.WPE condition to dcbz. Fixes issue 5114. --- .../Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp index b2a51b3e6f..a7955c0982 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -401,7 +401,7 @@ void Interpreter::dcbtst(UGeckoInstruction _inst) void Interpreter::dcbz(UGeckoInstruction _inst) { // HACK but works... we think - if (!HID0.DCFA) + if (HID2.WPE || !HID0.DCFA) Memory::Memset(Helper_Get_EA_X(_inst) & (~31), 0, 32); } From 439613b83352d59ebaff25d35151e25f616804b4 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sat, 4 Feb 2012 13:01:52 +0100 Subject: [PATCH 47/65] TextureCacheBase: Remove a superfluous TODO (texture hashing takes care of that stuff) --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 7873d1474e..cc14499330 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -227,7 +227,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, tex_hash ^= tlut_hash; } - TCacheEntryBase *entry = textures[texID]; // TODO: Should use a different texID for preloaded textures! + TCacheEntryBase *entry = textures[texID]; if (entry) { // 1. Calculate reference hash: From c53283185da77405d893e2c302319564423214dc Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 5 Feb 2012 16:16:33 +1100 Subject: [PATCH 48/65] Added an error check for invalid contents in ES_OPENCONTENT. Fixes Jungle Speed and Doc's Punch Out. Fixes issue 3035. --- .../Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 2a33d01ed9..3bfeb847aa 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -254,24 +254,27 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) } break; - case IOCTL_ES_OPENCONTENT: - { - _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); - _dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0); + case IOCTL_ES_OPENCONTENT: + { + _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); + _dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0); - u32 CFD = AccessIdentID++; - u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address); + u32 CFD = AccessIdentID++; + u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address); - m_ContentAccessMap[CFD].m_Position = 0; - m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index); - _dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL); + m_ContentAccessMap[CFD].m_Position = 0; + m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index); + _dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL); - Memory::Write_U32(CFD, _CommandAddress + 0x4); + if (m_ContentAccessMap[CFD].m_pContent == NULL) + CFD = 0xffffffff; //TODO: what is the correct error value here? - INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); - return true; - } - break; + Memory::Write_U32(CFD, _CommandAddress + 0x4); + + INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); + return true; + } + break; case IOCTL_ES_READCONTENT: { From 8f83a89416c6e13f23af19c5b329acbd271ef596 Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 5 Feb 2012 17:18:11 +1100 Subject: [PATCH 49/65] Removed the busy-wait from DSP LLE on thread. Reduces the CPU usage in this scenario by around a third. --- Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp index 7ee5f68001..a795b4966d 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp @@ -49,6 +49,9 @@ DSPLLE::DSPLLE() { m_cycle_count = 0; } +Common::Event dspEvent; +Common::Event ppcEvent; + void DSPLLE::DoState(PointerWrap &p) { p.Do(g_dsp.r); @@ -96,7 +99,10 @@ void DSPLLE::dsp_thread(DSPLLE *dsp_lle) Common::AtomicStore(dsp_lle->m_cycle_count, 0); } else - Common::YieldCPU(); + { + ppcEvent.Set(); + dspEvent.Wait(); + } } } @@ -138,6 +144,8 @@ void DSPLLE::DSP_StopSoundStream() m_bIsRunning = false; if (m_bDSPThread) { + ppcEvent.Set(); + dspEvent.Set(); m_hDSPThread.join(); } } @@ -274,9 +282,10 @@ void DSPLLE::DSP_Update(int cycles) else { // Wait for dsp thread to complete its cycle. Note: this logic should be thought through. - while (m_cycle_count != 0) - ; + ppcEvent.Wait(); Common::AtomicStore(m_cycle_count, dsp_cycles); + dspEvent.Set(); + } } From 25eae39b7c6af2bfdbec1c64310b56affa7b923e Mon Sep 17 00:00:00 2001 From: skidau Date: Mon, 6 Feb 2012 20:51:24 +1100 Subject: [PATCH 50/65] Rearranged the SSE detection. Patch by lordlyhobo. Fixes issue 5172. --- Source/Core/Common/Src/Common.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h index f08a4d1bfe..db889f7ddf 100644 --- a/Source/Core/Common/Src/Common.h +++ b/Source/Core/Common/Src/Common.h @@ -139,14 +139,18 @@ private: // wxWidgets does not have a true dummy macro for this. #define _trans(a) a -#if defined __APPLE__ && defined __i386__ -#define _M_SSE 0x300 -#elif defined __APPLE__ && defined __x86_64__ -#define _M_SSE 0x301 -#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) -#define _M_SSE 0x301 +#if defined __GNUC__ +# if defined __SSE4_2__ +# define _M_SSE 0x402 +# elif defined __SSE4_1__ +# define _M_SSE 0x401 +# elif defined __SSSE3__ +# define _M_SSE 0x301 +# elif defined __SSE3__ +# define _M_SSE 0x300 +# endif #elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008 -#define _M_SSE 0x402 +# define _M_SSE 0x402 #endif // Host communication. From c9dfcf8cf7d500d58cd8f2b375be123f5b99bb52 Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Fri, 3 Feb 2012 21:46:10 -0800 Subject: [PATCH 51/65] Add Support for Wii Motion Plus INSIDE Wii Remotes on Mac OS X. This patch makes a few changes necessary for support for the new Wii Remotes: - For all OSes: - Adds a new bool member variable m_motion_plus_inside to identify the new Wii Remotes. - If we have a new Wii Remote, use a head byte of 0xa2. We could just change this behavior for all Wii Remotes, but an existing comment suggests that would break 3rd party Wii Remotes. - On Mac OS X: - Expand the search criteria for the bluetooth scan. This is necessary because the new Wii Remote identifies with minor class kBluetoothDeviceClassMinorPeripheral2Gamepad, but the old Wii Remotes use minor class kBluetoothDeviceClassMinorPeripheral2Joystick (1). - Send commands on the interrupt channel, not the control channel. The new Wii Remotes require this; old ones are compatible with this. Note: 3rd party Wii Remots are untested with this change; the hope is they are still functional. - Get the name of the bluetooth device and see if it ends in "-TR". If so, set a member variable so we know it's the new kind of Wii Remote. This should fix issue 5011 for Mac OS X: http://code.google.com/p/dolphin-emu/issues/detail?id=5011 --- Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 8 ++++++-- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 10 ++++++---- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h | 1 + 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 0c2f742987..a899dac201 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -129,7 +129,7 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes) [bti setInquiryLength: 5]; [bti setSearchCriteria: kBluetoothServiceClassMajorAny majorDeviceClass: kBluetoothDeviceClassMajorPeripheral - minorDeviceClass: kBluetoothDeviceClassMinorPeripheral2Joystick + minorDeviceClass: kBluetoothDeviceClassMinorAny ]; [bti setUpdateNewDeviceNames: NO]; @@ -177,6 +177,10 @@ bool Wiimote::Connect() if (IsConnected()) return false; + if ([btd remoteNameRequest:nil] == kIOReturnSuccess) + m_motion_plus_inside = + static_cast([[btd getName] hasSuffix:@"-TR"]); + [btd openL2CAPChannelSync: &cchan withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt]; [btd openL2CAPChannelSync: &ichan @@ -244,7 +248,7 @@ int Wiimote::IOWrite(unsigned char *buf, int len) if (!IsConnected()) return 0; - ret = [cchan writeAsync: buf length: len refcon: nil]; + ret = [ichan writeAsync: buf length: len refcon: nil]; if (ret == kIOReturnSuccess) return len; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index f5ded4125d..1ac0823ebb 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -50,6 +50,7 @@ Wiimote::Wiimote(const unsigned int _index) #endif , leds(0), m_last_data_report(Report((u8 *)NULL, 0)) , m_channel(0), m_connected(false) + , m_motion_plus_inside(false) { #if defined(__linux__) && HAVE_BLUEZ bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}}; @@ -142,15 +143,16 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const rpt.second = (u8)size; memcpy(rpt.first, (u8*)data, size); - // Convert output DATA packets to SET_REPORT packets. - // Nintendo Wiimotes work without this translation, but 3rd + // Convert output DATA packets to SET_REPORT packets for non-TR + // Wiimotes. Nintendo Wiimotes work without this translation, but 3rd // party ones don't. + u8 head = m_motion_plus_inside ? 0xa2 : 0x52; if (rpt.first[0] == 0xa2) { - rpt.first[0] = 0x52; + rpt.first[0] = head; } - if (rpt.first[0] == 0x52 && rpt.first[1] == 0x18 && rpt.second == 23) + if (rpt.first[0] == head && rpt.first[1] == 0x18 && rpt.second == 23) { m_audio_reports.Push(rpt); return; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index f3c5b884f8..8229abee52 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -95,6 +95,7 @@ private: void ThreadFunc(); bool m_connected; + bool m_motion_plus_inside; std::thread m_wiimote_thread; Common::FifoQueue m_read_reports; Common::FifoQueue m_write_reports; From fc3eb7c6a7e2ea6d636889f49d72ba0d2ac45bcd Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Thu, 9 Feb 2012 17:18:46 +1300 Subject: [PATCH 52/65] Fixed a few warnings. --- Source/Plugins/Plugin_VideoDX11/Src/Render.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 9328969abf..69f0d0215a 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -695,15 +695,18 @@ void Renderer::UpdateViewport(Matrix44& vpCorrection) int Ht = intendedHt; if (Y + Ht > GetTargetHeight()) Ht = GetTargetHeight() - Y; - + // If GX viewport is off the render target, we must clamp our viewport // within the bounds. Use the correction matrix to compensate. ViewportCorrectionMatrix(vpCorrection, - intendedX, intendedY, intendedWd, intendedHt, - X, Y, Wd, Ht); + (float)intendedX, (float)intendedY, + (float)intendedWd, (float)intendedHt, + (float)X, (float)Y, + (float)Wd, (float)Ht); // Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work - D3D11_VIEWPORT vp = CD3D11_VIEWPORT(X, Y, Wd, Ht, + D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)X, (float)Y, + (float)Wd, (float)Ht, 0.f, // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f; 1.f); // xfregs.viewport.farZ / 16777216.0f; D3D::context->RSSetViewports(1, &vp); From cbab8329076320f27e7286b436fef9f4a3296f57 Mon Sep 17 00:00:00 2001 From: parlane Date: Wed, 15 Feb 2012 20:52:03 +0000 Subject: [PATCH 53/65] Updated English translation, fixes issue 5214. --- Languages/po/en.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Languages/po/en.po b/Languages/po/en.po index f08b1e1cdf..cf04ba0512 100644 --- a/Languages/po/en.po +++ b/Languages/po/en.po @@ -4588,7 +4588,7 @@ msgid "" "The safer you adjust this, the less likely the emulator will be missing any " "texture updates from RAM.\n" "\n" -"If unsure, use the second-fastest value from the right." +"If unsure, use the rightmost value." msgstr "" #: Source/Core/DolphinWX/Src/MemcardManager.cpp:447 From bea635d1d5690c96030e576d70375fb01315b45d Mon Sep 17 00:00:00 2001 From: parlane Date: Wed, 15 Feb 2012 20:56:50 +0000 Subject: [PATCH 54/65] Fixes issue 5214 for real! --- Source/Core/DolphinWX/Src/VideoConfigDiag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp index 8e1d221c39..75252cdc67 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp @@ -95,7 +95,7 @@ wxString efb_emulate_format_changes_desc = wxTRANSLATE("Ignore any changes to th wxString efb_copy_desc = wxTRANSLATE("Disable emulation of EFB copies.\nThese are often used for post-processing or render-to-texture effects, so while checking this setting gives a great speedup it almost always also causes issues.\n\nIf unsure, leave this unchecked."); wxString efb_copy_texture_desc = wxTRANSLATE("Store EFB copies in GPU texture objects.\nThis is not so accurate, but it works well enough for most games and gives a great speedup over EFB to RAM.\n\nIf unsure, leave this checked."); wxString efb_copy_ram_desc = wxTRANSLATE("Accurately emulate EFB copies.\nSome games depend on this for certain graphical effects or gameplay functionality.\n\nIf unsure, check EFB to Texture instead."); -wxString stc_desc = wxTRANSLATE("The safer you adjust this, the less likely the emulator will be missing any texture updates from RAM.\n\nIf unsure, use the second-fastest value from the right."); +wxString stc_desc = wxTRANSLATE("The safer you adjust this, the less likely the emulator will be missing any texture updates from RAM.\n\nIf unsure, use the rightmost value."); wxString wireframe_desc = wxTRANSLATE("Render the scene as a wireframe.\n\nIf unsure, leave this unchecked."); wxString disable_lighting_desc = wxTRANSLATE("Improves performance but causes lighting to disappear in most games.\n\nIf unsure, leave this unchecked."); wxString disable_textures_desc = wxTRANSLATE("Disable texturing.\n\nIf unsure, leave this unchecked."); From e58692653afda21f7593d340025c9d4328689244 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 17 Feb 2012 17:09:17 +0100 Subject: [PATCH 55/65] PixelShaderGen: Use correct texel to pixel mapping when sampling textures (D3D9 only) Fixes issue 2068. Fixes issue 5158. --- Source/Core/Common/Src/LinearDiskCache.h | 2 +- Source/Core/VideoCommon/Src/PixelShaderGen.cpp | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h index ac10b5ef20..edc851c9ac 100644 --- a/Source/Core/Common/Src/LinearDiskCache.h +++ b/Source/Core/Common/Src/LinearDiskCache.h @@ -24,7 +24,7 @@ // Increment this every time you change shader generation code. enum { - LINEAR_DISKCACHE_VER = 6969 + LINEAR_DISKCACHE_VER = 6970 }; // On disk format: diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 1726855d54..5e54b01129 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -1099,9 +1099,15 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType) void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType) { if (ApiType == API_D3D11) - WRITE(p, "%s=Tex%d.Sample(samp%d,%s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap,texmap, texcoords, texmap, texswap); + WRITE(p, "%s=Tex%d.Sample(samp%d, %s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap,texmap, texcoords, texmap, texswap); + else if (ApiType & API_D3D9) + { + // D3D9 uses different pixel to texel mapping, so we need to offset our base address by half a pixel. + // Read the MSDN article "Directly Mapping Texels to Pixels (Direct3D 9)" for further info. + WRITE(p, "%s=tex2D(samp%d, (%s.xy + float2(0.5f,0.5f)) * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap); + } else - WRITE(p, "%s=tex2D(samp%d,%s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap); + WRITE(p, "%s=tex2D(samp%d, %s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap); } static const char *tevAlphaFuncsTable[] = From d068686a7f32b9d771baafb4d25601afe31f78dd Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 20 Feb 2012 11:51:40 +0100 Subject: [PATCH 56/65] Revert revision f7d757b46eaa271e7f58e1c61df4fb34b5ff47f9. --- .../Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp | 24 ++++++++----------- Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h | 4 ++-- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 6 ++--- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp index cfb74df225..3a4b5d0699 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp @@ -434,15 +434,13 @@ void drawShadedTexSubQuad(IDirect3DTexture9 *texture, // Fills a certain area of the current render target with the specified color // Z buffer disabled; destination coordinates normalized to (-1;1) -void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1, float x2, float y2) +void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2) { - float dw = 1.f / (float)DestWidth; - float dh = 1.f / (float)DestHeight; struct CQVertex { float x, y, z, rhw; u32 col; } coords[4] = { - { x1-dw, y2+dh, 0.f, 1.f, Color }, - { x2-dw, y2+dh, 0.f, 1.f, Color }, - { x1-dw, y1+dh, 0.f, 1.f, Color }, - { x2-dw, y1+dh, 0.f, 1.f, Color }, + { x1, y2, 0.f, 1.f, Color }, + { x2, y2, 0.f, 1.f, Color }, + { x1, y1, 0.f, 1.f, Color }, + { x2, y1, 0.f, 1.f, Color }, }; dev->SetVertexShader(VertexShaderCache::GetClearVertexShader()); dev->SetPixelShader(PixelShaderCache::GetClearProgram()); @@ -451,15 +449,13 @@ void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1, RestoreShaders(); } -void drawClearQuad(int DestWidth, int DestHeight, u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader) +void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader) { - float dw = 1.f / (float)DestWidth; - float dh = 1.f / (float)DestHeight; struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = { - {-1.0f-dw, 1.0f+dh, z, 1.0f, Color}, - { 1.0f-dw, 1.0f+dh, z, 1.0f, Color}, - { 1.0f-dw, -1.0f+dh, z, 1.0f, Color}, - {-1.0f-dw, -1.0f+dh, z, 1.0f, Color} + {-1.0f, 1.0f, z, 1.0f, Color}, + { 1.0f, 1.0f, z, 1.0f, Color}, + { 1.0f, -1.0f, z, 1.0f, Color}, + {-1.0f, -1.0f, z, 1.0f, Color} }; dev->SetVertexShader(Vshader); dev->SetPixelShader(PShader); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h index 93e60f938b..882f112ece 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h @@ -82,8 +82,8 @@ namespace D3D IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader, float Gamma = 1.0f); - void drawClearQuad(int DestWidth, int DestHeight, u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader); - void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1, float x2, float y2); + void drawClearQuad(u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader); + void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2); void SaveRenderStates(); void RestoreRenderStates(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index f649323b73..a5aaa6485b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -622,7 +622,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { // TODO: Speed this up by batching pokes? ResetAPIState(); - D3D::drawColorQuad(GetTargetWidth(), GetTargetHeight(), poke_data, + D3D::drawColorQuad(poke_data, (float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f, - (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f, (float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f, @@ -747,7 +747,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE vp.MinZ = 0.0; vp.MaxZ = 1.0; D3D::dev->SetViewport(&vp); - D3D::drawClearQuad(GetTargetWidth(), GetTargetHeight(), color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); + D3D::drawClearQuad(color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); RestoreAPIState(); } @@ -896,7 +896,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons vp.MinZ = 0.0f; vp.MaxZ = 1.0f; D3D::dev->SetViewport(&vp); - D3D::drawClearQuad(GetTargetWidth(), GetTargetHeight(), 0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); + D3D::drawClearQuad(0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); } else { From 9adc119e3c2f845c0172b012badbbc86addad4a5 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 20 Feb 2012 17:55:18 +0100 Subject: [PATCH 57/65] PixelShaderGen: For custom textures and scaled EFB copies, use correct texel to pixel mapping when sampling textures (D3D9 only) This is basically the same as revision e58692653afd, just for scaled textures and with a LOT more work... --- Source/Core/Common/Src/LinearDiskCache.h | 2 +- .../Core/VideoCommon/Src/PixelShaderGen.cpp | 5 ++- Source/Core/VideoCommon/Src/PixelShaderGen.h | 19 +++++---- .../VideoCommon/Src/PixelShaderManager.cpp | 42 ++++++++++++++++--- .../Core/VideoCommon/Src/PixelShaderManager.h | 6 ++- .../Plugin_VideoDX11/Src/VertexManager.cpp | 4 +- .../Plugin_VideoDX9/Src/VertexManager.cpp | 4 +- .../Plugin_VideoOGL/Src/VertexManager.cpp | 4 +- 8 files changed, 61 insertions(+), 25 deletions(-) diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h index edc851c9ac..e4cb0cbd17 100644 --- a/Source/Core/Common/Src/LinearDiskCache.h +++ b/Source/Core/Common/Src/LinearDiskCache.h @@ -24,7 +24,7 @@ // Increment this every time you change shader generation code. enum { - LINEAR_DISKCACHE_VER = 6970 + LINEAR_DISKCACHE_VER = 6971 }; // On disk format: diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 5e54b01129..ed504f1c82 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -560,6 +560,7 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType WRITE(p, "uniform float4 "I_KCOLORS"[4] : register(c%d);\n", C_KCOLORS); WRITE(p, "uniform float4 "I_ALPHA"[1] : register(c%d);\n", C_ALPHA); WRITE(p, "uniform float4 "I_TEXDIMS"[8] : register(c%d);\n", C_TEXDIMS); + WRITE(p, "uniform float4 "I_VTEXSCALE"[8] : register(c%d);\n", C_VTEXSCALE); WRITE(p, "uniform float4 "I_ZBIAS"[2] : register(c%d);\n", C_ZBIAS); WRITE(p, "uniform float4 "I_INDTEXSCALE"[2] : register(c%d);\n", C_INDTEXSCALE); WRITE(p, "uniform float4 "I_INDTEXMTX"[6] : register(c%d);\n", C_INDTEXMTX); @@ -1102,9 +1103,9 @@ void SampleTexture(char *&p, const char *destination, const char *texcoords, con WRITE(p, "%s=Tex%d.Sample(samp%d, %s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap,texmap, texcoords, texmap, texswap); else if (ApiType & API_D3D9) { - // D3D9 uses different pixel to texel mapping, so we need to offset our base address by half a pixel. + // D3D9 uses different pixel to texel mapping, so we need to offset our sampling address by half a pixel (assuming native and virtual texture dimensions match each other, otherwise some math is involved). // Read the MSDN article "Directly Mapping Texels to Pixels (Direct3D 9)" for further info. - WRITE(p, "%s=tex2D(samp%d, (%s.xy + float2(0.5f,0.5f)) * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap); + WRITE(p, "%s=tex2D(samp%d, (%s.xy + 0.5f*"I_VTEXSCALE"[%d].%s) * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap/2, (texmap&1)?"zw":"xy", texmap, texswap); } else WRITE(p, "%s=tex2D(samp%d, %s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap); diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.h b/Source/Core/VideoCommon/Src/PixelShaderGen.h index 31242a916e..7374251c96 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.h +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.h @@ -24,26 +24,27 @@ #define I_KCOLORS "k" #define I_ALPHA "alphaRef" #define I_TEXDIMS "texdim" +#define I_VTEXSCALE "vtexscale" #define I_ZBIAS "czbias" #define I_INDTEXSCALE "cindscale" #define I_INDTEXMTX "cindmtx" #define I_FOG "cfog" #define I_PLIGHTS "cLights" -#define I_PMATERIALS "cmtrl" +#define I_PMATERIALS "cmtrl" #define C_COLORMATRIX 0 // 0 #define C_COLORS 0 // 0 #define C_KCOLORS (C_COLORS + 4) // 4 #define C_ALPHA (C_KCOLORS + 4) // 8 #define C_TEXDIMS (C_ALPHA + 1) // 9 -#define C_ZBIAS (C_TEXDIMS + 8) //17 -#define C_INDTEXSCALE (C_ZBIAS + 2) //19 -#define C_INDTEXMTX (C_INDTEXSCALE + 2) //21 -#define C_FOG (C_INDTEXMTX + 6) //27 - -#define C_PLIGHTS (C_FOG + 3) -#define C_PMATERIALS (C_PLIGHTS + 40) -#define C_PENVCONST_END (C_PMATERIALS + 4) +#define C_VTEXSCALE (C_TEXDIMS + 8) //17 - virtual texture scaling factor (e.g. custom textures, scaled EFB copies) +#define C_ZBIAS (C_VTEXSCALE + 4) //21 +#define C_INDTEXSCALE (C_ZBIAS + 2) //23 +#define C_INDTEXMTX (C_INDTEXSCALE + 2) //25 +#define C_FOG (C_INDTEXMTX + 6) //31 +#define C_PLIGHTS (C_FOG + 3) //34 +#define C_PMATERIALS (C_PLIGHTS + 40) //74 +#define C_PENVCONST_END (C_PMATERIALS + 4) //78 #define PIXELSHADERUID_MAX_VALUES 70 #define PIXELSHADERUID_MAX_VALUES_SAFE 120 diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp index 2521f80500..3e0f6d73c4 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp @@ -36,9 +36,11 @@ static bool s_bFogRangeAdjustChanged; static int nLightsChanged[2]; // min,max static float lastRGBAfull[2][4][4]; static u8 s_nTexDimsChanged; +static u8 s_nVirtualTexScalesChanged; static u8 s_nIndTexScaleChanged; static u32 lastAlpha; static u32 lastTexDims[8]; // width | height << 16 | wrap_s << 28 | wrap_t << 30 +static float lastVirtualTexScales[16]; // even fields: width ratio; odd fields: height ratio static u32 lastZBias; static int nMaterialsChanged; @@ -61,6 +63,7 @@ void PixelShaderManager::Init() { lastAlpha = 0; memset(lastTexDims, 0, sizeof(lastTexDims)); + memset(lastVirtualTexScales, 0, sizeof(lastVirtualTexScales)); lastZBias = 0; memset(lastRGBAfull, 0, sizeof(lastRGBAfull)); Dirty(); @@ -70,6 +73,7 @@ void PixelShaderManager::Dirty() { s_nColorsChanged[0] = s_nColorsChanged[1] = 15; s_nTexDimsChanged = 0xFF; + s_nVirtualTexScalesChanged = 0xFF; s_nIndTexScaleChanged = 0xFF; s_nIndTexMtxChanged = 15; s_bAlphaChanged = s_bZBiasChanged = s_bZTextureTypeChanged = s_bDepthRangeChanged = true; @@ -83,7 +87,7 @@ void PixelShaderManager::Shutdown() } -void PixelShaderManager::SetConstants() +void PixelShaderManager::SetConstants(API_TYPE api_type) { for (int i = 0; i < 2; ++i) { @@ -109,6 +113,16 @@ void PixelShaderManager::SetConstants() s_nTexDimsChanged = 0; } + if ((api_type & API_D3D9) && s_nVirtualTexScalesChanged) + { + for (int i = 0; i < 8; i += 2) + { + if (s_nVirtualTexScalesChanged & (3<>8)&0xff)/255.0f, 0, ((lastAlpha>>16)&0xff)/255.0f); @@ -338,6 +352,13 @@ void PixelShaderManager::SetPSTextureDims(int texid) SetPSConstant4fv(C_TEXDIMS + texid, fdims); } +void PixelShaderManager::SetPSVirtualTexScalePair(int texpairid) +{ + PRIM_LOG("vtexscale%d: %f %f %f %f\n", texpairid, lastVirtualTexScales[texpairid*4], lastVirtualTexScales[texpairid*4+1], + lastVirtualTexScales[texpairid*4+2], lastVirtualTexScales[texpairid*4+3]); + SetPSConstant4fv(C_VTEXSCALE + texpairid, &lastVirtualTexScales[texpairid*4]); +} + // This one is high in profiles (0.5%). TODO: Move conversion out, only store the raw color value // and update it when the shader constant is set, only. void PixelShaderManager::SetColorChanged(int type, int num, bool high) @@ -376,14 +397,25 @@ void PixelShaderManager::SetDestAlpha(const ConstantAlpha& alpha) } } -void PixelShaderManager::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt) +void PixelShaderManager::SetTexDims(int texmapid, u32 width, u32 height, u32 virtual_width, u32 virtual_height, u32 wraps, u32 wrapt, API_TYPE api_type) { u32 wh = width | (height << 16) | (wraps << 28) | (wrapt << 30); - if (lastTexDims[texmapid] != wh) + + bool refresh = lastTexDims[texmapid] != wh; + if (api_type & API_D3D9) { - lastTexDims[texmapid] = wh; + refresh |= (lastVirtualTexScales[texmapid*2] != (float)width / (float)virtual_width); + refresh |= (lastVirtualTexScales[texmapid*2+1] != (float)height / (float)virtual_height); + } + + if (refresh) + { + lastTexDims[texmapid] = wh; + lastVirtualTexScales[texmapid*2] = (float)width / (float)virtual_width; + lastVirtualTexScales[texmapid*2+1] = (float)height / (float)virtual_height; s_nTexDimsChanged |= 1 << texmapid; - } + s_nVirtualTexScalesChanged |= 1 << texmapid; + } } void PixelShaderManager::SetZTextureBias(u32 bias) diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.h b/Source/Core/VideoCommon/Src/PixelShaderManager.h index 2d1c01cad6..5cbe86cae4 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderManager.h +++ b/Source/Core/VideoCommon/Src/PixelShaderManager.h @@ -26,18 +26,20 @@ class PixelShaderManager { static void SetPSTextureDims(int texid); + static void SetPSVirtualTexScalePair(int texpairid); + public: static void Init(); static void Dirty(); static void Shutdown(); - static void SetConstants(); // sets pixel shader constants + static void SetConstants(API_TYPE api_type); // sets pixel shader constants // constant management, should be called after memory is committed static void SetColorChanged(int type, int index, bool high); static void SetAlpha(const AlphaFunc& alpha); static void SetDestAlpha(const ConstantAlpha& alpha); - static void SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt); + static void SetTexDims(int texmapid, u32 width, u32 height, u32 virtual_width, u32 virtual_height, u32 wraps, u32 wrapt, API_TYPE api_type); static void SetZTextureBias(u32 bias); static void SetViewportChanged(); static void SetIndMatrixChanged(int matrixidx); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index d0f5a1c338..1079863347 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -234,7 +234,7 @@ void VertexManager::vFlush() if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_D3D11); } else ERROR_LOG(VIDEO, "error loading texture"); @@ -243,7 +243,7 @@ void VertexManager::vFlush() // set global constants VertexShaderManager::SetConstants(); - PixelShaderManager::SetConstants(); + PixelShaderManager::SetConstants(API_D3D11); bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index c4e8225db1..2083d4f1d8 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -143,7 +143,7 @@ void VertexManager::vFlush() if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_D3D9); } else ERROR_LOG(VIDEO, "error loading texture"); @@ -152,7 +152,7 @@ void VertexManager::vFlush() // set global constants VertexShaderManager::SetConstants(); - PixelShaderManager::SetConstants(); + PixelShaderManager::SetConstants(API_D3D9); if (!PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components)) { diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index dff7f8299e..5117f6ddb6 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -161,7 +161,7 @@ void VertexManager::vFlush() if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_OPENGL); if (g_ActiveConfig.iLog & CONF_SAVETEXTURES) { @@ -179,7 +179,7 @@ void VertexManager::vFlush() // set global constants VertexShaderManager::SetConstants(); - PixelShaderManager::SetConstants(); + PixelShaderManager::SetConstants(API_OPENGL); bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; From 3a9fed0ba285b3c2bb80de408ac1a9da9ca774b6 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 21 Feb 2012 12:51:41 +0100 Subject: [PATCH 58/65] PixelShaderGen: Fix a bug introduced in revision 9adc119e3c2f. D3D11: Fix shader constant mapping. --- Source/Core/Common/Src/LinearDiskCache.h | 2 +- .../Core/VideoCommon/Src/PixelShaderGen.cpp | 5 +++- .../Plugin_VideoDX11/Src/PixelShaderCache.cpp | 28 ++++++++++--------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h index e4cb0cbd17..f6e0d95f8c 100644 --- a/Source/Core/Common/Src/LinearDiskCache.h +++ b/Source/Core/Common/Src/LinearDiskCache.h @@ -24,7 +24,7 @@ // Increment this every time you change shader generation code. enum { - LINEAR_DISKCACHE_VER = 6971 + LINEAR_DISKCACHE_VER = 6972 }; // On disk format: diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index ed504f1c82..fe5827de05 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -560,7 +560,10 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType WRITE(p, "uniform float4 "I_KCOLORS"[4] : register(c%d);\n", C_KCOLORS); WRITE(p, "uniform float4 "I_ALPHA"[1] : register(c%d);\n", C_ALPHA); WRITE(p, "uniform float4 "I_TEXDIMS"[8] : register(c%d);\n", C_TEXDIMS); - WRITE(p, "uniform float4 "I_VTEXSCALE"[8] : register(c%d);\n", C_VTEXSCALE); + if (ApiType & API_D3D9) + { + WRITE(p, "uniform float4 "I_VTEXSCALE"[4] : register(c%d);\n", C_VTEXSCALE); + } WRITE(p, "uniform float4 "I_ZBIAS"[2] : register(c%d);\n", C_ZBIAS); WRITE(p, "uniform float4 "I_INDTEXSCALE"[2] : register(c%d);\n", C_INDTEXSCALE); WRITE(p, "uniform float4 "I_INDTEXMTX"[6] : register(c%d);\n", C_INDTEXMTX); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp index 56f3719057..fe33c4db80 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp @@ -552,20 +552,22 @@ static const unsigned int ps_constant_offset_table[] = { 16, 20, 24, 28, // C_KCOLORS, 16 32, // C_ALPHA, 4 36, 40, 44, 48, 52, 56, 60, 64, // C_TEXDIMS, 32 - 68, 72, // C_ZBIAS, 8 - 76, 80, // C_INDTEXSCALE, 8 - 84, 88, 92, 96, 100, 104, // C_INDTEXMTX, 24 - 108, 112, 116, // C_FOG, 12 - 120, 124, 128, 132, 136, // C_PLIGHTS0, 20 - 140, 144, 148, 152, 156, // C_PLIGHTS1, 20 - 160, 164, 168, 172, 176, // C_PLIGHTS2, 20 - 180, 184, 188, 192, 196, // C_PLIGHTS3, 20 - 200, 204, 208, 212, 216, // C_PLIGHTS4, 20 - 220, 224, 228, 232, 236, // C_PLIGHTS5, 20 - 240, 244, 248, 252, 256, // C_PLIGHTS6, 20 - 260, 264, 268, 272, 276, // C_PLIGHTS7, 20 - 280, 284, 288, 292 // C_PMATERIALS, 16 + 68, 72, 76, 80, // C_VTEXSCALE, 16 (unused) + 84, 88, // C_ZBIAS, 8 + 92, 96, // C_INDTEXSCALE, 8 + 100, 104, 108, 112, 116, 120, // C_INDTEXMTX, 24 + 124, 128, 132, // C_FOG, 12 + 136, 140, 144, 148, 152, // C_PLIGHTS0, 20 + 156, 160, 164, 168, 172, // C_PLIGHTS1, 20 + 176, 180, 184, 188, 192, // C_PLIGHTS2, 20 + 196, 200, 204, 208, 212, // C_PLIGHTS3, 20 + 216, 220, 224, 228, 232, // C_PLIGHTS4, 20 + 236, 240, 244, 248, 252, // C_PLIGHTS5, 20 + 256, 260, 264, 268, 272, // C_PLIGHTS6, 20 + 276, 280, 284, 288, 292, // C_PLIGHTS7, 20 + 296, 300, 304, 308, // C_PMATERIALS, 16 }; + void Renderer::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { psconstants[ps_constant_offset_table[const_number] ] = f1; From b251880d8b3887e6d4119559c5efa1fd39a075b2 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 24 Feb 2012 17:31:17 +0100 Subject: [PATCH 59/65] GameConfig: Remove an empty file --- Data/User/GameConfig/WBEEJV.ini | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Data/User/GameConfig/WBEEJV.ini diff --git a/Data/User/GameConfig/WBEEJV.ini b/Data/User/GameConfig/WBEEJV.ini deleted file mode 100644 index e69de29bb2..0000000000 From f15aeb26b37d88c451887709ead523e5aeb49390 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 24 Feb 2012 19:20:17 -0600 Subject: [PATCH 60/65] Use an auto typed variable in IniFile.cpp --- Source/Core/Common/Src/IniFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp index c81c060f1d..f51e8850d3 100644 --- a/Source/Core/Common/Src/IniFile.cpp +++ b/Source/Core/Common/Src/IniFile.cpp @@ -459,7 +459,7 @@ bool IniFile::Save(const char* filename) return false; } - for (std::vector
::const_iterator iter = sections.begin(); iter != sections.end(); ++iter) + for (auto iter = sections.begin(); iter != sections.end(); ++iter) { const Section& section = *iter; From 8a8dc77ef19446f97d210f0602aaa218144adf0e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 24 Feb 2012 14:19:24 -0600 Subject: [PATCH 61/65] enable c++11 compilation in cmakelists --- CMakeLists.txt | 1 + Source/Core/Common/Src/StdThread.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80584b2555..c59e3f7c07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -552,6 +552,7 @@ option(UNITTESTS "Build unitests" OFF) ######################################## # Start compiling our code # +add_definitions(-std=c++0x) add_subdirectory(Source) diff --git a/Source/Core/Common/Src/StdThread.h b/Source/Core/Common/Src/StdThread.h index 6e9e903561..b64dbf2c4e 100644 --- a/Source/Core/Common/Src/StdThread.h +++ b/Source/Core/Common/Src/StdThread.h @@ -7,7 +7,9 @@ #if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ // GCC 4.4 provides +#ifndef _GLIBCXX_USE_SCHED_YIELD #define _GLIBCXX_USE_SCHED_YIELD +#endif #include #else From f92d1e1e931db66d10db4cb2377bcb794dc898ee Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 24 Feb 2012 14:25:02 -0600 Subject: [PATCH 62/65] fix some clang compilation errors --- Source/Core/VideoCommon/Src/AVIDump.cpp | 2 +- Source/Core/VideoCommon/Src/BPMemory.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp index 469e00d9f5..670693690b 100644 --- a/Source/Core/VideoCommon/Src/AVIDump.cpp +++ b/Source/Core/VideoCommon/Src/AVIDump.cpp @@ -263,7 +263,7 @@ bool AVIDump::CreateFile() s_Stream->codec->bit_rate = 400000; s_Stream->codec->width = s_width; s_Stream->codec->height = s_height; - s_Stream->codec->time_base = (AVRational){1, VideoInterface::TargetRefreshRate}; + s_Stream->codec->time_base = (AVRational){1, static_cast(VideoInterface::TargetRefreshRate)}; s_Stream->codec->gop_size = 12; s_Stream->codec->pix_fmt = g_Config.bUseFFV1 ? PIX_FMT_BGRA : PIX_FMT_YUV420P; diff --git a/Source/Core/VideoCommon/Src/BPMemory.cpp b/Source/Core/VideoCommon/Src/BPMemory.cpp index da09893f35..5c4ed457e3 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.cpp +++ b/Source/Core/VideoCommon/Src/BPMemory.cpp @@ -61,7 +61,7 @@ void BPReload() // Cases in which we DON'T want to reload the BP continue; default: - BPCmd bp = {i, 0xFFFFFF, ((u32*)&bpmem)[i]}; + BPCmd bp = {i, 0xFFFFFF, static_cast(((u32*)&bpmem)[i])}; BPWritten(bp); } } From b8bef29bcc5a8cd18625efb7e6ce37f0f263c393 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 25 Feb 2012 20:36:49 +1100 Subject: [PATCH 63/65] Fixed a divide by zero error in the hash functions --- Source/Core/Common/Src/Hash.cpp | 48 ++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/Source/Core/Common/Src/Hash.cpp b/Source/Core/Common/Src/Hash.cpp index 62ea25519e..46747ce157 100644 --- a/Source/Core/Common/Src/Hash.cpp +++ b/Source/Core/Common/Src/Hash.cpp @@ -167,7 +167,13 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) const u8 * data = (const u8*)src; const int nblocks = len / 16; u32 Step = (len / 8); - if(samples == 0) samples = Step; + if(samples == 0) + { + if (Step == 0) + samples = 1; + else + samples = Step; + } Step = Step / samples; if(Step < 1) Step = 1; @@ -245,7 +251,13 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) samples = Step; + if(samples == 0) + { + if (Step == 0) + samples = 1; + else + samples = Step; + } Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -275,7 +287,13 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) samples = Step; + if(samples == 0) + { + if (Step == 0) + samples = 1; + else + samples = Step; + } Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -318,7 +336,13 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) u32 Step = (len/4); const u32 *data = (const u32 *)src; const u32 *end = data + Step; - if(samples == 0) samples = Step; + if(samples == 0) + { + if (Step == 0) + samples = 1; + else + samples = Step; + } Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -390,7 +414,13 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) u32 out[2]; const int nblocks = len / 8; u32 Step = (len / 4); - if(samples == 0) samples = Step; + if(samples == 0) + { + if (Step == 0) + samples = 1; + else + samples = Step; + } Step = Step / samples; if(Step < 1) Step = 1; @@ -464,7 +494,13 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) samples = Step; + if(samples == 0) + { + if (Step == 0) + samples = 1; + else + samples = Step; + } Step = Step / samples; if(Step < 1) Step = 1; while(data < end) From c3293b1a1cea3cdd9858b00c2a34d783347e72c3 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sat, 25 Feb 2012 10:49:04 +0100 Subject: [PATCH 64/65] Improvement to revision b8bef29bcc5a .. :P --- Source/Core/Common/Src/Hash.cpp | 48 +++++---------------------------- 1 file changed, 6 insertions(+), 42 deletions(-) diff --git a/Source/Core/Common/Src/Hash.cpp b/Source/Core/Common/Src/Hash.cpp index 46747ce157..8e8d6f85bd 100644 --- a/Source/Core/Common/Src/Hash.cpp +++ b/Source/Core/Common/Src/Hash.cpp @@ -167,13 +167,7 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) const u8 * data = (const u8*)src; const int nblocks = len / 16; u32 Step = (len / 8); - if(samples == 0) - { - if (Step == 0) - samples = 1; - else - samples = Step; - } + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; @@ -251,13 +245,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) - { - if (Step == 0) - samples = 1; - else - samples = Step; - } + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -287,13 +275,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) - { - if (Step == 0) - samples = 1; - else - samples = Step; - } + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -336,13 +318,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) u32 Step = (len/4); const u32 *data = (const u32 *)src; const u32 *end = data + Step; - if(samples == 0) - { - if (Step == 0) - samples = 1; - else - samples = Step; - } + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -414,13 +390,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) u32 out[2]; const int nblocks = len / 8; u32 Step = (len / 4); - if(samples == 0) - { - if (Step == 0) - samples = 1; - else - samples = Step; - } + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; @@ -494,13 +464,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) - { - if (Step == 0) - samples = 1; - else - samples = Step; - } + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; while(data < end) From 38823b63716b46ec00337f20127de43661deac8b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 28 Feb 2012 00:27:16 -0600 Subject: [PATCH 65/65] Add comment here so people know what's up. --- Source/Core/Common/Src/IniFile.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp index f51e8850d3..acad498106 100644 --- a/Source/Core/Common/Src/IniFile.cpp +++ b/Source/Core/Common/Src/IniFile.cpp @@ -459,6 +459,10 @@ bool IniFile::Save(const char* filename) return false; } + // Currently testing if dolphin community can handle the requirements of C++11 compilation + // If you get a compiler error on this line, your compiler is probably old. + // Update to g++ 4.4 or a recent version of clang (XCode 4.2 on OS X). + // If you don't want to update, complain in a google code issue, the dolphin forums or #dolphin-emu. for (auto iter = sections.begin(); iter != sections.end(); ++iter) { const Section& section = *iter;