Merge branch 'master' into wii-network

This commit is contained in:
Shawn Hoffman 2012-02-27 22:36:41 -08:00
commit 6eb2cb2666
103 changed files with 1527 additions and 824 deletions

View File

@ -554,6 +554,7 @@ option(UNITTESTS "Build unitests" OFF)
########################################
# Start compiling our code
#
add_definitions(-std=c++0x)
add_subdirectory(Source)

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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) {

View File

@ -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.

View File

@ -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)

View File

@ -459,7 +459,11 @@ bool IniFile::Save(const char* filename)
return false;
}
for (std::vector<Section>::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;

View File

@ -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:

View File

@ -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<std::mutex> lk(m_log_lock);
m_logfile << msg << std::flush;
}
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
{
#if _MSC_VER
::OutputDebugStringA(msg);
#endif
}

View File

@ -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;

View File

@ -7,7 +7,9 @@
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
// GCC 4.4 provides <thread>
#ifndef _GLIBCXX_USE_SCHED_YIELD
#define _GLIBCXX_USE_SCHED_YIELD
#endif
#include <thread>
#else

View File

@ -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<u16>(bufferSize, dataLength));
return true;
}
return false;

View File

@ -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)

View File

@ -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);}

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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.
====================================================================*/

View File

@ -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)

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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

View File

@ -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<bool>([[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;

View File

@ -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;

View File

@ -95,6 +95,7 @@ private:
void ThreadFunc();
bool m_connected;
bool m_motion_plus_inside;
std::thread m_wiimote_thread;
Common::FifoQueue<Report> m_read_reports;
Common::FifoQueue<Report> m_write_reports;

View File

@ -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)",

View File

@ -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");

View File

@ -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);
}

View File

@ -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);

View File

@ -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}},

View File

@ -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));
}

View File

@ -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<std::wstring>& _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)

View File

@ -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

View File

@ -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

View File

@ -29,7 +29,7 @@
namespace DiscIO
{
bool Add_Ticket(u64 TitleID, const u8 *p_tik, u32 tikSize);
struct SNANDContent
{
u32 m_ContentID;

View File

@ -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
{

View File

@ -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

View File

@ -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<GeckoCode::Code>::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);

View File

@ -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);
}

View File

@ -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());
}
}

View File

@ -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);

View File

@ -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));
}

View File

@ -65,7 +65,7 @@ private:
bool m_ignoreLogTimer;
LogManager *m_LogManager;
std::queue<std::pair<u8, wxString> > msgQueue;
bool m_writeFile, m_writeConsole, m_writeWindow, m_LogAccess;
bool m_writeFile, m_writeConsole, m_writeWindow, m_writeDebugger, m_LogAccess;
// Controls
wxBoxSizer *sBottom;

View File

@ -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);

View File

@ -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);

View File

@ -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();
}

View File

@ -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<int>(VideoInterface::TargetRefreshRate)};
s_Stream->codec->gop_size = 12;
s_Stream->codec->pix_fmt = g_Config.bUseFFV1 ? PIX_FMT_BGRA : PIX_FMT_YUV420P;

View File

@ -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<int>(((u32*)&bpmem)[i])};
BPWritten(bp);
}
}

View File

@ -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

View File

@ -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;
// ------------------------------------------------

View File

@ -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

View File

@ -158,6 +158,7 @@ void UpdateInterruptsFromVideoBackend(u64 userdata);
bool AllowIdleSkipping();
void SetCpClearRegister();
void SetCpControlRegister();
void SetCpStatusRegister();
void SetOverflowStatusFromGatherPipe();

View File

@ -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

View File

@ -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[] =

View File

@ -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

View File

@ -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<<i))
SetPSVirtualTexScalePair(i/2);
}
s_nVirtualTexScalesChanged = 0;
}
if (s_bAlphaChanged)
{
SetPSConstant4f(C_ALPHA, (lastAlpha&0xff)/255.0f, ((lastAlpha>>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)

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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]);

View File

@ -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);

View File

@ -129,7 +129,6 @@ struct VideoConfig
bool bOSDHotKey;
bool bCopyEFBToTexture;
bool bCopyEFBScaled;
bool bSafeTextureCache;
int iSafeTextureCache_ColorSamples;
int iPhackvalue[4];
std::string sPhackvalue[2];

View File

@ -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;

View File

@ -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
} // namespace DX11

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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))
{

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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)

Some files were not shown because too many files have changed in this diff Show More