diff --git a/CMakeLists.txt b/CMakeLists.txt index 40dba79f61..7d472b114d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -554,6 +554,7 @@ option(UNITTESTS "Build unitests" OFF) ######################################## # Start compiling our code # +add_definitions(-std=c++0x) add_subdirectory(Source) 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/WBEEJV.ini b/Data/User/GameConfig/WBEEJV.ini deleted file mode 100644 index e69de29bb2..0000000000 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] 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 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) { 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. diff --git a/Source/Core/Common/Src/Hash.cpp b/Source/Core/Common/Src/Hash.cpp index 62ea25519e..8e8d6f85bd 100644 --- a/Source/Core/Common/Src/Hash.cpp +++ b/Source/Core/Common/Src/Hash.cpp @@ -167,7 +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) samples = Step; + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; @@ -245,7 +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) samples = Step; + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -275,7 +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) samples = Step; + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -318,7 +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) samples = Step; + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; while(data < end) @@ -390,7 +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) samples = Step; + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; @@ -464,7 +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) samples = Step; + if(samples == 0) samples = max(Step, 1u); Step = Step / samples; if(Step < 1) Step = 1; while(data < end) diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp index c81c060f1d..acad498106 100644 --- a/Source/Core/Common/Src/IniFile.cpp +++ b/Source/Core/Common/Src/IniFile.cpp @@ -459,7 +459,11 @@ bool IniFile::Save(const char* filename) return false; } - for (std::vector
::const_iterator iter = sections.begin(); iter != sections.end(); ++iter) + // 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; diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h index ac10b5ef20..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 = 6969 + LINEAR_DISKCACHE_VER = 6972 }; // On disk format: 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/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 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; diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 9acfac5864..00c58a0fbc 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -834,6 +834,102 @@ 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);} + +//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 9ffb890f54..3b699c81a0 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,16 @@ 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); + + // 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/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. ====================================================================*/ 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/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(); + } } 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 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; 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)", 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 b214db804a..795d5cc367 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 @@ -120,7 +120,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 @@ -189,11 +189,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); @@ -203,10 +203,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; } @@ -266,24 +266,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: { @@ -383,7 +386,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); } @@ -551,11 +554,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()) { @@ -687,7 +685,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); @@ -1003,7 +1001,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]; } @@ -1025,11 +1023,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"); 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); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 9d9b57658b..c01c1b017b 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); @@ -177,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 367c7e8158..4980b4d7a4 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); + OR(32, R(EAX), Imm32(XER_CA_MASK)); + 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 @@ -122,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 @@ -908,33 +951,31 @@ 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)); - - // Convert carry to borrow - CMC(); + GetCarryEAXAndClear(); + 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 { - MOV(32, gpr.R(d), gpr.R(b)); - SBB(32, gpr.R(d), gpr.R(a)); + 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, true); + FinalizeCarryGenerateOverflowEAX(inst.OE, invertedCarry); gpr.UnlockAll(); } @@ -948,9 +989,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)); @@ -961,7 +1000,7 @@ void Jit64::subfmex(UGeckoInstruction inst) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } @@ -974,9 +1013,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)); @@ -987,7 +1025,7 @@ void Jit64::subfzex(UGeckoInstruction inst) { GenerateRC(); } - FinalizeCarryOverflow(inst.OE); + FinalizeCarryGenerateOverflowEAX(inst.OE); gpr.UnlockAll(); } @@ -1047,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(); } } @@ -1081,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) { @@ -1157,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); @@ -1166,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) @@ -1193,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 @@ -1264,31 +1523,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(); } } @@ -1340,31 +1597,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(); } } @@ -1380,31 +1635,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(); } } @@ -1581,7 +1834,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) { @@ -1651,9 +1904,22 @@ void Jit64::srwx(UGeckoInstruction inst) } else { +#ifdef _M_X64 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) + { + 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); MOV(32, R(ECX), gpr.R(b)); TEST(32, R(ECX), Imm32(32)); if (a != s) @@ -1666,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) @@ -1686,12 +1953,38 @@ 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, true, true); + 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); MOV(32, R(ECX), gpr.R(b)); TEST(32, R(ECX), Imm32(32)); if (a != s) @@ -1704,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 } } @@ -1720,19 +2014,37 @@ 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, true, true); + 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); JitClearCA(); MOV(32, R(ECX), gpr.R(b)); if (a != s) 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(); @@ -1746,7 +2058,7 @@ void Jit64::srawx(UGeckoInstruction inst) SetJumpTarget(nocarry2); gpr.UnlockAll(); gpr.UnlockAllX(); - +#endif if (inst.Rc) { ComputeRC(gpr.R(a)); } 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 diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.cpp b/Source/Core/DiscIO/Src/NANDContentLoader.cpp index c8e409636b..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; } @@ -536,20 +538,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 +554,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; 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 { 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/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp index e9089c6006..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 @@ -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); 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/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..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(); @@ -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; 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); diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp index 45e239a835..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."); @@ -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/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); } } 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/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(); 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 diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 1726855d54..fe5827de05 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -560,6 +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); + 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); @@ -1099,9 +1103,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 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 + 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); + WRITE(p, "%s=tex2D(samp%d, %s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap); } static const char *tevAlphaFuncsTable[] = 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/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 3550227389..cc14499330 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" @@ -23,28 +39,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()); @@ -88,12 +95,11 @@ 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) + 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++); @@ -135,7 +141,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); } } } @@ -167,19 +173,16 @@ void TextureCache::ClearRenderTargets() iter = textures.begin(), tcend = textures.end(); for (; iter!=tcend; ++iter) - iter->second->isRenderTarget = false; + 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) { - // 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; @@ -188,111 +191,82 @@ 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 = 0; - u64 texHash = 0; u32 texID = address; + 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; - 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; const bool isPaletteTexture = (texformat == GX_TF_C4 || texformat == GX_TF_C8 || texformat == GX_TF_C14X2); - 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) + 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(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + if (isPaletteTexture) { - texHash = GetHash64(ptr, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + const u32 palette_size = TexDecoder_GetPaletteSize(texformat); + tlut_hash = GetHash64(&texMem[tlutaddr], palette_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); - } - - if (g_ActiveConfig.bSafeTextureCache) - hash_value = texHash; + // 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 + texID ^= ((u32)tlut_hash) ^(u32)(tlut_hash >> 32); + tex_hash ^= tlut_hash; } TCacheEntryBase *entry = textures[texID]; if (entry) { - if (!g_ActiveConfig.bSafeTextureCache) - { - if (entry->isRenderTarget || entry->isDynamic) - { - if (!g_ActiveConfig.bCopyEFBToTexture) - { - hash_value = 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. + if (g_ActiveConfig.bCopyEFBToTexture && entry->IsEfbCopy()) + tex_hash = TEXHASH_INVALID; - if (isPaletteTexture) - { - hash_value ^= GetHash64(&texMem[tlutaddr], palette_size, - g_ActiveConfig.iSafeTextureCache_ColorSamples); - } - } - else - { - hash_value = 0; - } - } - else - { - hash_value = *(u32*)ptr; - } - } - else if ((entry->isRenderTarget || entry->isDynamic) && g_ActiveConfig.bCopyEFBToTexture) + // 2. a) For EFB copies, only the hash and the texture address need to match + if (entry->IsEfbCopy() && tex_hash == entry->hash && address == entry->addr) { - hash_value = 0; - } - - 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)) - { - entry->isDynamic = false; + // 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 && tex_hash == 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. + // + // 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_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 + } 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->realW && height == entry->realH && full_format == entry->format && entry->mipLevels == maxlevel) - || (entry->isDynamic && entry->realW == width && entry->realH == 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; } } - + if (g_ActiveConfig.bHiresTextures) { // Load Custom textures @@ -301,23 +275,24 @@ 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) { 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 } } + // 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, - expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + pcfmt = TexDecoder_Decode(temp, src_data, 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) ? GetPow2(std::max(width, height)) : !isPow2; @@ -329,40 +304,27 @@ 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 - entry->mipLevels = maxlevel; + // + // 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_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } - entry->addr = address; - entry->format = full_format; - entry->size_in_bytes = texture_size; - - entry->virtualW = width; - entry->virtualH = height; - - entry->realW = nativeW; - entry->realH = nativeH; - - entry->isRenderTarget = false; - entry->isNonPow2 = false; - entry->isDynamic = 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); + 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_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); @@ -370,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); - entry->Load(currentWidth, currentHeight, expandedWidth, level); + 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; @@ -404,7 +377,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); @@ -426,6 +399,45 @@ 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: + // 1a) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) + // 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 (type = TCET_EC_VRAM) + // - Store a hash of the encoded RAM data in the texcache entry. + // 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 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 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 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. + // 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; float *const ColorMask = colmat + 20; @@ -472,9 +484,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; @@ -628,15 +640,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->virtualW == scaled_tex_w && entry->virtualH == scaled_tex_h) - || (entry->isDynamic && entry->realW == tex_w && entry->realH == 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)) { - texture_is_dynamic = entry->isDynamic; + scaled_tex_w = tex_w; + scaled_tex_h = tex_h; } else { @@ -646,32 +658,16 @@ 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 textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); - entry->addr = dstAddr; - entry->hash = 0; - - entry->realW = tex_w; - entry->realH = tex_h; - - entry->virtualW = scaled_tex_w; - entry->virtualH = scaled_tex_h; - - entry->format = dstFormat; - entry->mipLevels = 0; - - entry->isRenderTarget = true; - entry->isNonPow2 = true; - entry->isDynamic = false; + // 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->SetHashes(TEXHASH_INVALID); + 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 1c86e64006..2924c5871f 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 @@ -14,47 +30,56 @@ class TextureCache { public: + enum TexCacheEntryType + { + 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 + }; + struct TCacheEntryBase { - // TODO: organize +#define TEXHASH_INVALID 0 + + // common members u32 addr; u32 size_in_bytes; u64 hash; - //u32 paletteHash; - u32 oldpixel; + //u32 pal_hash; u32 format; - + + 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 + + // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames 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. - unsigned int mipLevels; + 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; + } - bool isRenderTarget; // copied from EFB - bool isDynamic; // Used for hybrid EFB copies to enable checks for CPU modifications - bool isNonPow2; // doesn't seem to be used anywhere + 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; + } - //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(); @@ -62,13 +87,15 @@ 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, 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 @@ -87,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/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/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/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; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 53cf9fd4d9..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); @@ -748,7 +751,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; } @@ -1106,12 +1109,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); @@ -1428,4 +1430,4 @@ void Renderer::SetInterlacingMode() // TODO } -} // namespace DX11 \ No newline at end of file +} // namespace DX11 diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index 39018c83bc..e59fbd496e 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -102,12 +102,12 @@ 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 (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { 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 @@ -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_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index e1e40047e4..1079863347 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -228,12 +228,13 @@ 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) { // 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, tentry->virtual_width, tentry->virtual_height, 0, 0, API_D3D11); } else ERROR_LOG(VIDEO, "error loading texture"); @@ -242,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/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 93b37e211a..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(); } @@ -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; } @@ -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 { @@ -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_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 7c741e08a9..2a3f12ddcf 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" @@ -78,7 +79,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture(); - if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture) + if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { LPDIRECT3DSURFACE9 Rendersurf = NULL; texture->GetSurfaceLevel(0, &Rendersurf); @@ -90,15 +91,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 +134,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)); @@ -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 d14a3f29ea..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,76 +313,7 @@ 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) +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; @@ -440,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) @@ -490,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 aa4757e4c9..4036f21447 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h @@ -35,15 +35,13 @@ 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); 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_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index d9c33b67ef..2083d4f1d8 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -137,12 +137,13 @@ 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) { // 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, tentry->virtual_width, tentry->virtual_height, 0, 0, API_D3D9); } else ERROR_LOG(VIDEO, "error loading texture"); @@ -151,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/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) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index 4a9431a563..f78eb11905 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" @@ -124,7 +125,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, @@ -278,7 +279,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo GL_REPORT_ERRORD(); - if (false == isDynamic || g_ActiveConfig.bCopyEFBToTexture) + if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { if (s_TempFramebuffer == 0) glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer); @@ -294,7 +295,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 @@ -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); @@ -337,7 +347,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/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index c715775194..c73d3abdbf 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -250,78 +250,7 @@ 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) +int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) { u32 format = copyfmt; @@ -379,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 719ac1b7fc..4113778603 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h @@ -32,15 +32,13 @@ 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); 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); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 5144c328d9..5117f6ddb6 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -155,12 +155,13 @@ 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) { // 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, tentry->virtual_width, tentry->virtual_height, 0, 0, API_OPENGL); if (g_ActiveConfig.iLog & CONF_SAVETEXTURES) { @@ -178,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; 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; }