Merge remote-tracking branch 'origin/master' into wiimote-netplay

This commit is contained in:
Rachel Bryk
2013-08-15 09:00:04 -04:00
1553 changed files with 36545 additions and 17291 deletions
-1
View File
@@ -20,7 +20,6 @@ set(SRCS Src/BreakPoints.cpp
Src/Thread.cpp
Src/Timer.cpp
Src/Version.cpp
Src/VideoBackendBase.cpp
Src/x64ABI.cpp
Src/x64Analyzer.cpp
Src/x64Emitter.cpp
+1 -3
View File
@@ -195,7 +195,6 @@
<ClCompile Include="Src\Thread.cpp" />
<ClCompile Include="Src\Timer.cpp" />
<ClCompile Include="Src\Version.cpp" />
<ClCompile Include="Src\VideoBackendBase.cpp" />
<ClCompile Include="Src\x64ABI.cpp" />
<ClCompile Include="Src\x64Analyzer.cpp" />
<ClCompile Include="Src\x64CPUDetect.cpp" />
@@ -250,7 +249,6 @@
<ClInclude Include="Src\Thread.h" />
<ClInclude Include="Src\Thunk.h" />
<ClInclude Include="Src\Timer.h" />
<ClInclude Include="Src\VideoBackendBase.h" />
<ClInclude Include="Src\x64ABI.h" />
<ClInclude Include="Src\x64Analyzer.h" />
<ClInclude Include="Src\x64Emitter.h" />
@@ -261,4 +259,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+1 -3
View File
@@ -23,7 +23,6 @@
<ClCompile Include="Src\Thread.cpp" />
<ClCompile Include="Src\Timer.cpp" />
<ClCompile Include="Src\Version.cpp" />
<ClCompile Include="Src\VideoBackendBase.cpp" />
<ClCompile Include="Src\x64Analyzer.cpp" />
<ClCompile Include="Src\x64Emitter.cpp" />
<ClCompile Include="Src\LogManager.cpp">
@@ -92,7 +91,6 @@
<ClInclude Include="Src\Thread.h" />
<ClInclude Include="Src\Thunk.h" />
<ClInclude Include="Src\Timer.h" />
<ClInclude Include="Src\VideoBackendBase.h" />
<ClInclude Include="Src\x64Analyzer.h" />
<ClInclude Include="Src\x64Emitter.h" />
<ClInclude Include="Src\Log.h">
@@ -134,4 +132,4 @@
<UniqueIdentifier>{f078f36e-a0ff-4cd0-95f8-476100d68e68}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>
+6
View File
@@ -68,6 +68,9 @@ unsigned char GetCPUImplementer()
sscanf(implementer_string, "0x%02hhx", &implementer);
break;
}
free(implementer_string);
return implementer;
}
@@ -92,6 +95,9 @@ unsigned short GetCPUPart()
sscanf(part_string, "0x%03hx", &part);
break;
}
free(part_string);
return part;
}
+2 -1
View File
@@ -136,7 +136,6 @@ static BOOL GetModuleNameFromAddress( UINT address, LPTSTR lpszModule )
static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol )
{
BOOL ret = FALSE;
DWORD dwDisp = 0;
DWORD dwSymSize = 10000;
TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?");
CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?";
@@ -153,9 +152,11 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
// Get symbol info for IP
#ifndef _M_X64
DWORD dwDisp = 0;
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) )
#else
//makes it compile but hell im not sure if this works...
DWORD64 dwDisp = 0;
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) )
#endif
{
+17 -37
View File
@@ -20,45 +20,30 @@
namespace {
static void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut)
static void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut)
{
if (line[0] == '#')
return;
int FirstEquals = (int)line.find("=", 0);
int FirstCommentChar = -1;
// Comments
if (FirstCommentChar < 0)
FirstCommentChar =
(int)line.find("#", FirstEquals > 0 ? FirstEquals : 0);
if (FirstCommentChar < 0 && line[0] == ';')
FirstCommentChar = 0;
// Allow preservation of spacing before comment
if (FirstCommentChar > 0)
{
while (line[FirstCommentChar - 1] == ' ' || line[FirstCommentChar - 1] == 9) // 9 == tab
{
FirstCommentChar--;
}
}
if ((FirstEquals >= 0) && ((FirstCommentChar < 0) || (FirstEquals < FirstCommentChar)))
if (FirstEquals >= 0)
{
// Yes, a valid line!
*keyOut = StripSpaces(line.substr(0, FirstEquals));
if (commentOut) *commentOut = FirstCommentChar > 0 ? line.substr(FirstCommentChar) : std::string("");
if (valueOut) *valueOut = StripQuotes(StripSpaces(line.substr(FirstEquals + 1, FirstCommentChar - FirstEquals - 1)));
if (valueOut) *valueOut = StripQuotes(StripSpaces(line.substr(FirstEquals + 1, std::string::npos)));
}
}
}
std::string* IniFile::Section::GetLine(const char* key, std::string* valueOut, std::string* commentOut)
std::string* IniFile::Section::GetLine(const char* key, std::string* valueOut)
{
for (std::vector<std::string>::iterator iter = lines.begin(); iter != lines.end(); ++iter)
{
std::string& line = *iter;
std::string lineKey;
ParseLine(line, &lineKey, valueOut, commentOut);
ParseLine(line, &lineKey, valueOut);
if (!strcasecmp(lineKey.c_str(), key))
return &line;
}
@@ -67,12 +52,12 @@ std::string* IniFile::Section::GetLine(const char* key, std::string* valueOut, s
void IniFile::Section::Set(const char* key, const char* newValue)
{
std::string value, commented;
std::string* line = GetLine(key, &value, &commented);
std::string value;
std::string* line = GetLine(key, &value);
if (line)
{
// Change the value - keep the key and comment
*line = StripSpaces(key) + " = " + newValue + commented;
*line = StripSpaces(key) + " = " + newValue;
}
else
{
@@ -91,7 +76,7 @@ void IniFile::Section::Set(const char* key, const std::string& newValue, const s
bool IniFile::Section::Get(const char* key, std::string* value, const char* defaultValue)
{
std::string* line = GetLine(key, value, 0);
std::string* line = GetLine(key, value);
if (!line)
{
if (defaultValue)
@@ -224,7 +209,7 @@ bool IniFile::Section::Exists(const char *key) const
for (std::vector<std::string>::const_iterator iter = lines.begin(); iter != lines.end(); ++iter)
{
std::string lineKey;
ParseLine(*iter, &lineKey, NULL, NULL);
ParseLine(*iter, &lineKey, NULL);
if (!strcasecmp(lineKey.c_str(), key))
return true;
}
@@ -233,7 +218,7 @@ bool IniFile::Section::Exists(const char *key) const
bool IniFile::Section::Delete(const char *key)
{
std::string* line = GetLine(key, 0, 0);
std::string* line = GetLine(key, 0);
for (std::vector<std::string>::iterator liter = lines.begin(); liter != lines.end(); ++liter)
{
if (line == &*liter)
@@ -313,7 +298,7 @@ bool IniFile::DeleteKey(const char* sectionName, const char* key)
Section* section = GetSection(sectionName);
if (!section)
return false;
std::string* line = section->GetLine(key, 0, 0);
std::string* line = section->GetLine(key, 0);
for (std::vector<std::string>::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
{
if (line == &(*liter))
@@ -335,7 +320,7 @@ bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) c
for (std::vector<std::string>::const_iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
{
std::string key;
ParseLine(*liter, &key, 0, 0);
ParseLine(*liter, &key, 0);
keys.push_back(key);
}
return true;
@@ -421,11 +406,6 @@ bool IniFile::Load(const char* filename)
// New section!
std::string sub = line.substr(1, endpos - 1);
sections.push_back(Section(sub));
if (endpos + 1 < line.size())
{
sections[sections.size() - 1].comment = line.substr(endpos + 1);
}
}
}
else
@@ -459,7 +439,7 @@ bool IniFile::Save(const char* filename)
if (section.name != "")
{
out << "[" << section.name << "]" << section.comment << std::endl;
out << "[" << section.name << "]" << std::endl;
}
for (std::vector<std::string>::const_iterator liter = section.lines.begin(); liter != section.lines.end(); ++liter)
+1 -2
View File
@@ -25,7 +25,7 @@ public:
bool Exists(const char *key) const;
bool Delete(const char *key);
std::string* GetLine(const char* key, std::string* valueOut, std::string* commentOut);
std::string* GetLine(const char* key, std::string* valueOut);
void Set(const char* key, const char* newValue);
void Set(const char* key, const std::string& newValue, const std::string& defaultValue);
@@ -70,7 +70,6 @@ public:
protected:
std::vector<std::string> lines;
std::string name;
std::string comment;
};
bool Load(const char* filename);
+15 -29
View File
@@ -20,6 +20,7 @@
#include <linux/ashmem.h>
#endif
#endif
#include <set>
#if defined(__APPLE__)
static const char* ram_temp_file = "/tmp/gc_mem.tmp";
@@ -214,27 +215,7 @@ static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32
bail:
// Argh! ERROR! Free what we grabbed so far so we can try again.
for (int j = 0; j <= i; j++)
{
SKIP(flags, views[i].flags);
if (views[j].out_ptr_low && *views[j].out_ptr_low)
{
arena->ReleaseView(*views[j].out_ptr_low, views[j].size);
*views[j].out_ptr_low = NULL;
}
if (*views[j].out_ptr)
{
#ifdef _M_X64
arena->ReleaseView(*views[j].out_ptr, views[j].size);
#else
if (!(views[j].flags & MV_MIRROR_PREVIOUS))
{
arena->ReleaseView(*views[j].out_ptr, views[j].size);
}
#endif
*views[j].out_ptr = NULL;
}
}
MemoryMap_Shutdown(views, i+1, flags, arena);
return false;
}
@@ -300,15 +281,20 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemArena *arena)
{
std::set<void*> freeset;
for (int i = 0; i < num_views; i++)
{
SKIP(flags, views[i].flags);
if (views[i].out_ptr_low && *views[i].out_ptr_low)
arena->ReleaseView(*views[i].out_ptr_low, views[i].size);
if (*views[i].out_ptr && (views[i].out_ptr_low && *views[i].out_ptr != *views[i].out_ptr_low))
arena->ReleaseView(*views[i].out_ptr, views[i].size);
*views[i].out_ptr = NULL;
if (views[i].out_ptr_low)
*views[i].out_ptr_low = NULL;
const MemoryView* view = &views[i];
u8** outptrs[2] = {view->out_ptr_low, view->out_ptr};
for (int j = 0; j < 2; j++)
{
u8** outptr = outptrs[j];
if (outptr && *outptr && !freeset.count(*outptr))
{
arena->ReleaseView(*outptr, view->size);
freeset.insert(*outptr);
*outptr = NULL;
}
}
}
}
+34 -3
View File
@@ -34,7 +34,39 @@ bool AsciiToHex(const char* _szValue, u32& result)
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args)
{
int writtenCount = vsnprintf(out, outsize, format, args);
int writtenCount;
#ifdef _WIN32
// You would think *printf are simple, right? Iterate on each character,
// if it's a format specifier handle it properly, etc.
//
// Nooooo. Not according to the C standard.
//
// According to the C99 standard (7.19.6.1 "The fprintf function")
// The format shall be a multibyte character sequence
//
// Because some character encodings might have '%' signs in the middle of
// a multibyte sequence (SJIS for example only specifies that the first
// byte of a 2 byte sequence is "high", the second byte can be anything),
// printf functions have to decode the multibyte sequences and try their
// best to not screw up.
//
// Unfortunately, on Windows, the locale for most languages is not UTF-8
// as we would need. Notably, for zh_TW, Windows chooses EUC-CN as the
// locale, and completely fails when trying to decode UTF-8 as EUC-CN.
//
// On the other hand, the fix is simple: because we use UTF-8, no such
// multibyte handling is required as we can simply assume that no '%' char
// will be present in the middle of a multibyte sequence.
//
// This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l.
static locale_t c_locale = NULL;
if (!c_locale)
c_locale = _create_locale(LC_ALL, ".1252");
writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args);
#else
writtenCount = vsnprintf(out, outsize, format, args);
#endif
if (writtenCount > 0 && writtenCount < outsize)
{
@@ -58,10 +90,9 @@ std::string StringFromFormat(const char* format, ...)
va_start(args, format);
required = _vscprintf(format, args);
buf = new char[required + 1];
vsnprintf(buf, required, format, args);
CharArrayFromFormatV(buf, required + 1, format, args);
va_end(args);
buf[required] = '\0';
std::string temp = buf;
delete[] buf;
#else
+2 -2
View File
@@ -58,8 +58,8 @@ var describe = GetFirstStdOutLine(gitexe + cmd_describe);
var branch = GetFirstStdOutLine(gitexe + cmd_branch);
var isMaster = +("master" == branch);
// remove hash from description
describe = describe.replace(/-[^-]+(-dirty)?$/, '$1');
// remove hash (and trailing "-0" if needed) from description
describe = describe.replace(/(-0)?-[^-]+(-dirty)?$/, '$2');
var out_contents =
"#define SCM_REV_STR \"" + revision + "\"\n" +
+1
View File
@@ -210,6 +210,7 @@ if(_M_ARM)
Src/PowerPC/JitArm32/JitArm_Integer.cpp
Src/PowerPC/JitArm32/JitArm_LoadStore.cpp
Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp
Src/PowerPC/JitArm32/JitArm_Paired.cpp
Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp
Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp)
endif()
+4 -1
View File
@@ -311,7 +311,10 @@ bool SCoreStartupParameter::AutoSetup(EBootBS2 _BootBS2)
m_strSRAM = File::GetUserPath(F_GCSRAM_IDX);
if (!bWii)
{
m_strBootROM = File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + Region + DIR_SEP GC_IPL;
m_strBootROM = File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + Region + DIR_SEP GC_IPL;
if (!File::Exists(m_strBootROM))
m_strBootROM = File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + Region + DIR_SEP GC_IPL;
if (!bHLE_BS2)
{
if (!File::Exists(m_strBootROM))
@@ -1255,8 +1255,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandInquiry(u8* _Input)
{
// Inquiry should not be called normally
PanicAlertT("HCI_CMD_INQUIRY is called, please report!");
hci_inquiry_cp* pInquiry = (hci_inquiry_cp*)_Input;
INFO_LOG(WII_IPC_WIIMOTE, "Command: HCI_CMD_INQUIRY:");
@@ -1862,8 +1860,6 @@ CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305::AccessWiiMote(const b
}
ERROR_LOG(WII_IPC_WIIMOTE,"Can't find WiiMote by bd: %02x:%02x:%02x:%02x:%02x:%02x",
_rAddr.b[0], _rAddr.b[1], _rAddr.b[2], _rAddr.b[3], _rAddr.b[4], _rAddr.b[5]);
PanicAlertT("Can't find WiiMote by bd: %02x:%02x:%02x:%02x:%02x:%02x",
_rAddr.b[0], _rAddr.b[1], _rAddr.b[2], _rAddr.b[3], _rAddr.b[4], _rAddr.b[5]);
return NULL;
}
+2
View File
@@ -703,6 +703,8 @@ bool NetPlayServer::StopGame()
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac);
m_is_running = false;
return true;
}
@@ -116,6 +116,11 @@ public:
void GenerateRC(int cr = 0);
void ComputeRC(int cr = 0);
void ComputeRC(s32 value, int cr);
void ComputeCarry();
void GetCarryAndClear(ARMReg reg);
void FinalizeCarry(ARMReg reg);
// OPCODES
void unknown_instruction(UGeckoInstruction _inst);
@@ -143,6 +148,8 @@ public:
void addi(UGeckoInstruction _inst);
void addis(UGeckoInstruction _inst);
void addx(UGeckoInstruction _inst);
void addcx(UGeckoInstruction _inst);
void addex(UGeckoInstruction _inst);
void cmp (UGeckoInstruction _inst);
void cmpi(UGeckoInstruction _inst);
void cmpl(UGeckoInstruction _inst);
@@ -153,6 +160,9 @@ public:
void oris(UGeckoInstruction _inst);
void orx(UGeckoInstruction _inst);
void xorx(UGeckoInstruction _inst);
void andx(UGeckoInstruction _inst);
void andi_rc(UGeckoInstruction _inst);
void andis_rc(UGeckoInstruction _inst);
void rlwimix(UGeckoInstruction _inst);
void rlwinmx(UGeckoInstruction _inst);
void subfx(UGeckoInstruction _inst);
@@ -183,12 +193,22 @@ public:
// Floating point
void fabsx(UGeckoInstruction _inst);
void faddsx(UGeckoInstruction _inst);
void faddx(UGeckoInstruction _inst);
void fsubsx(UGeckoInstruction _inst);
void fsubx(UGeckoInstruction _inst);
void fmulsx(UGeckoInstruction _inst);
void fmulx(UGeckoInstruction _inst);
void fmrx(UGeckoInstruction _inst);
// Floating point loadStore
void lfs(UGeckoInstruction _inst);
void lfd(UGeckoInstruction _inst);
// Paired Singles
void ps_add(UGeckoInstruction _inst);
void ps_sub(UGeckoInstruction _inst);
void ps_mul(UGeckoInstruction _inst);
};
#endif // _JIT64_H
@@ -51,6 +51,21 @@ void JitArm::fabsx(UGeckoInstruction inst)
if (inst.Rc) Helper_UpdateCR1(vD);
}
void JitArm::faddsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
ARMReg vD0 = fpr.R0(inst.FD);
ARMReg vD1 = fpr.R1(inst.FD);
ARMReg vA = fpr.R0(inst.FA);
ARMReg vB = fpr.R0(inst.FB);
VADD(vD0, vA, vB);
VADD(vD1, vA, vB);
if (inst.Rc) Helper_UpdateCR1(vD0);
}
void JitArm::faddx(UGeckoInstruction inst)
{
INSTRUCTION_START
@@ -64,6 +79,65 @@ void JitArm::faddx(UGeckoInstruction inst)
if (inst.Rc) Helper_UpdateCR1(vD);
}
// Breaks Animal crossing
void JitArm::fsubsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
Default(inst); return;
ARMReg vD0 = fpr.R0(inst.FD);
ARMReg vD1 = fpr.R1(inst.FD);
ARMReg vA = fpr.R0(inst.FA);
ARMReg vB = fpr.R0(inst.FB);
VSUB(vD0, vA, vB);
VSUB(vD1, vA, vB);
if (inst.Rc) Helper_UpdateCR1(vD0);
}
void JitArm::fsubx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
ARMReg vD = fpr.R0(inst.FD);
ARMReg vA = fpr.R0(inst.FA);
ARMReg vB = fpr.R0(inst.FB);
VSUB(vD, vA, vB);
if (inst.Rc) Helper_UpdateCR1(vD);
}
// Breaks animal crossing
void JitArm::fmulsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
Default(inst); return;
ARMReg vD0 = fpr.R0(inst.FD);
ARMReg vD1 = fpr.R1(inst.FD);
ARMReg vA = fpr.R0(inst.FA);
ARMReg vC = fpr.R0(inst.FC);
VMUL(vD0, vA, vC);
VMUL(vD1, vA, vC);
if (inst.Rc) Helper_UpdateCR1(vD0);
}
void JitArm::fmulx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
ARMReg vD0 = fpr.R0(inst.FD);
ARMReg vA = fpr.R0(inst.FA);
ARMReg vC = fpr.R0(inst.FC);
VMUL(vD0, vA, vC);
if (inst.Rc) Helper_UpdateCR1(vD0);
}
void JitArm::fmrx(UGeckoInstruction inst)
{
INSTRUCTION_START
@@ -54,6 +54,57 @@ void JitArm::ComputeRC(int cr) {
STRB(rB, R9, PPCSTATE_OFF(cr_fast) + cr);
gpr.Unlock(rB);
}
void JitArm::ComputeRC(s32 value, int cr) {
ARMReg rB = gpr.GetReg();
if (value < 0)
MOV(rB, 0x8);
else if (value > 0)
MOV(rB, 0x4);
else
MOV(rB, 0x2);
STRB(rB, R9, PPCSTATE_OFF(cr_fast) + cr);
gpr.Unlock(rB);
}
void JitArm::ComputeCarry()
{
ARMReg tmp = gpr.GetReg();
Operand2 mask = Operand2(2, 2); // XER_CA_MASK
LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
SetCC(CC_CS);
ORR(tmp, tmp, mask);
SetCC(CC_CC);
BIC(tmp, tmp, mask);
SetCC();
STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
gpr.Unlock(tmp);
}
void JitArm::GetCarryAndClear(ARMReg reg)
{
ARMReg tmp = gpr.GetReg();
Operand2 mask = Operand2(2, 2); // XER_CA_MASK
LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
AND(reg, tmp, mask);
BIC(tmp, tmp, mask);
STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
gpr.Unlock(tmp);
}
void JitArm::FinalizeCarry(ARMReg reg)
{
ARMReg tmp = gpr.GetReg();
Operand2 mask = Operand2(2, 2); // XER_CA_MASK
SetCC(CC_CS);
ORR(reg, reg, mask);
SetCC();
LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
ORR(tmp, tmp, reg);
STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
gpr.Unlock(tmp);
}
void JitArm::addi(UGeckoInstruction inst)
{
@@ -103,23 +154,70 @@ void JitArm::addx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
ARMReg RA = gpr.R(inst.RA);
ARMReg RB = gpr.R(inst.RB);
ARMReg RD = gpr.R(inst.RD);
u32 a = inst.RA, b = inst.RB, d = inst.RD;
if (gpr.IsImm(a) && gpr.IsImm(b))
{
gpr.SetImmediate(d, gpr.GetImm(a) + gpr.GetImm(b));
if (inst.Rc) ComputeRC(gpr.GetImm(d), 0);
return;
}
ARMReg RA = gpr.R(a);
ARMReg RB = gpr.R(b);
ARMReg RD = gpr.R(d);
ADDS(RD, RA, RB);
if (inst.Rc) ComputeRC();
}
void JitArm::addcx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
u32 a = inst.RA, b = inst.RB, d = inst.RD;
ARMReg RA = gpr.R(a);
ARMReg RB = gpr.R(b);
ARMReg RD = gpr.R(d);
ADDS(RD, RA, RB);
ComputeCarry();
if (inst.Rc) ComputeRC();
}
void JitArm::addex(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
u32 a = inst.RA, b = inst.RB, d = inst.RD;
Default(inst); return;
ARMReg RA = gpr.R(a);
ARMReg RB = gpr.R(b);
ARMReg RD = gpr.R(d);
ARMReg rA = gpr.GetReg();
GetCarryAndClear(rA);
ADDS(RD, RA, RB);
FinalizeCarry(rA);
if (inst.Rc) ComputeRC();
gpr.Unlock(rA);
}
void JitArm::subfx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
ARMReg RA = gpr.R(inst.RA);
ARMReg RB = gpr.R(inst.RB);
ARMReg RD = gpr.R(inst.RD);
SUBS(RD, RB, RA);
u32 a = inst.RA, b = inst.RB, d = inst.RD;
if (inst.OE) PanicAlert("OE: subfx");
if (gpr.IsImm(a) && gpr.IsImm(b))
{
gpr.SetImmediate(d, gpr.GetImm(b) - gpr.GetImm(a));
if (inst.Rc) ComputeRC(gpr.GetImm(d), 0);
return;
}
ARMReg RA = gpr.R(a);
ARMReg RB = gpr.R(b);
ARMReg RD = gpr.R(d);
SUBS(RD, RB, RA);
if (inst.Rc) GenerateRC();
}
void JitArm::mulli(UGeckoInstruction inst)
@@ -149,7 +247,7 @@ void JitArm::ori(UGeckoInstruction inst)
if (gpr.IsImm(s))
{
gpr.SetImmediate(s, gpr.GetImm(a) | inst.UIMM);
gpr.SetImmediate(a, gpr.GetImm(s) | inst.UIMM);
return;
}
ARMReg RA = gpr.R(a);
@@ -163,9 +261,15 @@ void JitArm::oris(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
u32 a = inst.RA, s = inst.RS;
ARMReg RA = gpr.R(inst.RA);
ARMReg RS = gpr.R(inst.RS);
if (gpr.IsImm(s))
{
gpr.SetImmediate(a, gpr.GetImm(s) | (inst.UIMM << 16));
return;
}
ARMReg RA = gpr.R(a);
ARMReg RS = gpr.R(s);
ARMReg rA = gpr.GetReg();
MOVI2R(rA, inst.UIMM << 16);
ORR(RA, RS, rA);
@@ -176,10 +280,17 @@ void JitArm::orx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
u32 a = inst.RA, b = inst.RB, s = inst.RS;
ARMReg rA = gpr.R(inst.RA);
ARMReg rS = gpr.R(inst.RS);
ARMReg rB = gpr.R(inst.RB);
if (gpr.IsImm(b) && gpr.IsImm(s))
{
gpr.SetImmediate(a, gpr.GetImm(s) | gpr.GetImm(b));
if (inst.Rc) ComputeRC(gpr.GetImm(a), 0);
return;
}
ARMReg rA = gpr.R(a);
ARMReg rB = gpr.R(b);
ARMReg rS = gpr.R(s);
ORRS(rA, rS, rB);
if (inst.Rc)
ComputeRC();
@@ -190,23 +301,100 @@ void JitArm::xorx(UGeckoInstruction inst)
INSTRUCTION_START
JITDISABLE(Integer)
ARMReg rA = gpr.R(inst.RA);
ARMReg rS = gpr.R(inst.RS);
ARMReg rB = gpr.R(inst.RB);
u32 a = inst.RA, b = inst.RB, s = inst.RS;
if (gpr.IsImm(b) && gpr.IsImm(s))
{
gpr.SetImmediate(a, gpr.GetImm(s) ^ gpr.GetImm(b));
if (inst.Rc) ComputeRC(gpr.GetImm(a), 0);
return;
}
ARMReg rA = gpr.R(a);
ARMReg rB = gpr.R(b);
ARMReg rS = gpr.R(s);
EORS(rA, rS, rB);
if (inst.Rc)
ComputeRC();
}
void JitArm::andx(UGeckoInstruction inst)
{
u32 a = inst.RA, b = inst.RB, s = inst.RS;
if (gpr.IsImm(s) && gpr.IsImm(b))
{
gpr.SetImmediate(a, gpr.GetImm(s) & gpr.GetImm(b));
if (inst.Rc) ComputeRC(gpr.GetImm(a), 0);
return;
}
ARMReg rA = gpr.R(a);
ARMReg rB = gpr.R(b);
ARMReg rS = gpr.R(s);
ANDS(rA, rS, rB);
if (inst.Rc) ComputeRC();
}
void JitArm::andi_rc(UGeckoInstruction inst)
{
u32 a = inst.RA, s = inst.RS;
if (gpr.IsImm(s))
{
gpr.SetImmediate(a, gpr.GetImm(s) & inst.UIMM);
ComputeRC(gpr.GetImm(a), 0);
return;
}
ARMReg rA = gpr.R(a);
ARMReg rS = gpr.R(s);
ARMReg RA = gpr.GetReg();
MOVI2R(RA, inst.UIMM);
ANDS(rA, rS, RA);
ComputeRC();
gpr.Unlock(RA);
}
void JitArm::andis_rc(UGeckoInstruction inst)
{
u32 a = inst.RA, s = inst.RS;
if (gpr.IsImm(s))
{
gpr.SetImmediate(a, gpr.GetImm(s) & ((u32)inst.UIMM << 16));
ComputeRC(gpr.GetImm(a), 0);
return;
}
ARMReg rA = gpr.R(a);
ARMReg rS = gpr.R(s);
ARMReg RA = gpr.GetReg();
MOVI2R(RA, (u32)inst.UIMM << 16);
ANDS(rA, rS, RA);
ComputeRC();
gpr.Unlock(RA);
}
void JitArm::extshx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
ARMReg RA, RS;
RA = gpr.R(inst.RA);
RS = gpr.R(inst.RS);
SXTH(RA, RS);
u32 a = inst.RA, s = inst.RS;
if (gpr.IsImm(s))
{
gpr.SetImmediate(a, (u32)(s32)(s16)gpr.GetImm(s));
if (inst.Rc) ComputeRC(gpr.GetImm(a), 0);
return;
}
ARMReg rA = gpr.R(a);
ARMReg rS = gpr.R(s);
SXTH(rA, rS);
if (inst.Rc){
CMP(RA, 0);
CMP(rA, 0);
ComputeRC();
}
}
@@ -214,12 +402,19 @@ void JitArm::extsbx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
ARMReg RA, RS;
RA = gpr.R(inst.RA);
RS = gpr.R(inst.RS);
SXTB(RA, RS);
u32 a = inst.RA, s = inst.RS;
if (gpr.IsImm(s))
{
gpr.SetImmediate(a, (u32)(s32)(s8)gpr.GetImm(s));
if (inst.Rc) ComputeRC(gpr.GetImm(a), 0);
return;
}
ARMReg rA = gpr.R(a);
ARMReg rS = gpr.R(s);
SXTB(rA, rS);
if (inst.Rc){
CMP(RA, 0);
CMP(rA, 0);
ComputeRC();
}
}
@@ -228,31 +423,43 @@ void JitArm::cmp (UGeckoInstruction inst)
INSTRUCTION_START
JITDISABLE(Integer)
ARMReg RA = gpr.R(inst.RA);
ARMReg RB = gpr.R(inst.RB);
int crf = inst.CRFD;
u32 a = inst.RA, b = inst.RB;
if (gpr.IsImm(a) && gpr.IsImm(b))
{
ComputeRC((s32)gpr.GetImm(a) - (s32)gpr.GetImm(b), crf);
return;
}
ARMReg RA = gpr.R(a);
ARMReg RB = gpr.R(b);
CMP(RA, RB);
ComputeRC(crf);
}
void JitArm::cmpi(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Integer)
ARMReg RA = gpr.R(inst.RA);
u32 a = inst.RA;
int crf = inst.CRFD;
if (inst.SIMM_16 >= 0 && inst.SIMM_16 < 256)
{
CMP(RA, inst.SIMM_16);
}
if (gpr.IsImm(a))
ComputeRC((s32)gpr.GetImm(a) - inst.SIMM_16, crf);
else
{
ARMReg rA = gpr.GetReg();
MOVI2R(rA, inst.SIMM_16);
CMP(RA, rA);
gpr.Unlock(rA);
ARMReg RA = gpr.R(a);
if (inst.SIMM_16 >= 0 && inst.SIMM_16 < 256)
CMP(RA, inst.SIMM_16);
else
{
ARMReg rA = gpr.GetReg();
MOVI2R(rA, inst.SIMM_16);
CMP(RA, rA);
gpr.Unlock(rA);
}
ComputeRC(crf);
}
ComputeRC(crf);
}
void JitArm::cmpl(UGeckoInstruction inst)
{
@@ -0,0 +1,90 @@
// 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 "Common.h"
#include "Thunk.h"
#include "../../Core.h"
#include "../PowerPC.h"
#include "../../CoreTiming.h"
#include "../PPCTables.h"
#include "ArmEmitter.h"
#include "Jit.h"
#include "JitRegCache.h"
#include "JitAsm.h"
// Wrong, THP videos like SMS and Ikaruga show artifacts
void JitArm::ps_add(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
Default(inst); return;
u32 a = inst.FA, b = inst.FB, d = inst.FD;
if (inst.Rc){
Default(inst); return;
}
ARMReg vA0 = fpr.R0(a);
ARMReg vA1 = fpr.R1(a);
ARMReg vB0 = fpr.R0(b);
ARMReg vB1 = fpr.R1(b);
ARMReg vD0 = fpr.R0(d, false);
ARMReg vD1 = fpr.R1(d, false);
VADD(vD0, vA0, vB0);
VADD(vD1, vA1, vB1);
}
void JitArm::ps_sub(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
u32 a = inst.FA, b = inst.FB, d = inst.FD;
if (inst.Rc){
Default(inst); return;
}
ARMReg vA0 = fpr.R0(a);
ARMReg vA1 = fpr.R1(a);
ARMReg vB0 = fpr.R0(b);
ARMReg vB1 = fpr.R1(b);
ARMReg vD0 = fpr.R0(d, false);
ARMReg vD1 = fpr.R1(d, false);
VSUB(vD0, vA0, vB0);
VSUB(vD1, vA1, vB1);
}
void JitArm::ps_mul(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
u32 a = inst.FA, c = inst.FC, d = inst.FD;
if (inst.Rc){
Default(inst); return;
}
ARMReg vA0 = fpr.R0(a);
ARMReg vA1 = fpr.R1(a);
ARMReg vC0 = fpr.R0(c);
ARMReg vC1 = fpr.R1(c);
ARMReg vD0 = fpr.R0(d, false);
ARMReg vD1 = fpr.R1(d, false);
VMUL(vD0, vA0, vC0);
VMUL(vD1, vA1, vC1);
}
@@ -75,8 +75,8 @@ static GekkoOPTemplate primarytable[] =
{25, &JitArm::oris}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{26, &JitArm::Default}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{27, &JitArm::Default}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{28, &JitArm::Default}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{29, &JitArm::Default}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{28, &JitArm::andi_rc}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{29, &JitArm::andis_rc}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{32, &JitArm::lwz}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{33, &JitArm::Default}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
@@ -150,11 +150,11 @@ static GekkoOPTemplate table4_2[] =
{14, &JitArm::Default}, //"ps_madds0", OPTYPE_PS, 0}},
{15, &JitArm::Default}, //"ps_madds1", OPTYPE_PS, 0}},
{18, &JitArm::Default}, //"ps_div", OPTYPE_PS, 0, 16}},
{20, &JitArm::Default}, //"ps_sub", OPTYPE_PS, 0}},
{21, &JitArm::Default}, //"ps_add", OPTYPE_PS, 0}},
{20, &JitArm::ps_sub}, //"ps_sub", OPTYPE_PS, 0}},
{21, &JitArm::ps_add}, //"ps_add", OPTYPE_PS, 0}},
{23, &JitArm::Default}, //"ps_sel", OPTYPE_PS, 0}},
{24, &JitArm::Default}, //"ps_res", OPTYPE_PS, 0}},
{25, &JitArm::Default}, //"ps_mul", OPTYPE_PS, 0}},
{25, &JitArm::ps_mul}, //"ps_mul", OPTYPE_PS, 0}},
{26, &JitArm::Default}, //"ps_rsqrte", OPTYPE_PS, 0, 1}},
{28, &JitArm::Default}, //"ps_msub", OPTYPE_PS, 0}},
{29, &JitArm::Default}, //"ps_madd", OPTYPE_PS, 0}},
@@ -194,7 +194,7 @@ static GekkoOPTemplate table19[] =
static GekkoOPTemplate table31[] =
{
{28, &JitArm::Default}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{28, &JitArm::andx}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{60, &JitArm::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{444, &JitArm::orx}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{124, &JitArm::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
@@ -309,8 +309,8 @@ static GekkoOPTemplate table31_2[] =
{
{266, &JitArm::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{778, &JitArm::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{10, &JitArm::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{138, &JitArm::Default}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{10, &JitArm::addcx}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{138, &JitArm::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{234, &JitArm::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{202, &JitArm::Default}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{491, &JitArm::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
@@ -333,11 +333,11 @@ static GekkoOPTemplate table31_2[] =
static GekkoOPTemplate table59[] =
{
{18, &JitArm::Default}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
{20, &JitArm::Default}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitArm::Default}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}},
{20, &JitArm::fsubsx}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitArm::faddsx}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}},
// {22, &JitArm::Default}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko
{24, &JitArm::Default}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitArm::Default}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitArm::fmulsx}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}},
{28, &JitArm::Default}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{29, &JitArm::Default}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
{30, &JitArm::Default}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
@@ -367,11 +367,11 @@ static GekkoOPTemplate table63[] =
static GekkoOPTemplate table63_2[] =
{
{18, &JitArm::Default}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}},
{20, &JitArm::Default}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{20, &JitArm::fsubx}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitArm::faddx}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}},
{22, &JitArm::Default}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}},
{23, &JitArm::Default}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitArm::Default}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitArm::fmulx}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}},
{26, &JitArm::Default}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}},
{28, &JitArm::Default}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{29, &JitArm::Default}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
-11
View File
@@ -117,17 +117,6 @@ void Init(int cpu_core)
{
FPURoundMode::SetPrecisionMode(FPURoundMode::PREC_53);
memset(ppcState.mojs, 0, sizeof(ppcState.mojs));
memset(ppcState.sr, 0, sizeof(ppcState.sr));
ppcState.DebugCount = 0;
ppcState.dtlb_last = 0;
ppcState.dtlb_last = 0;
memset(ppcState.dtlb_va, 0, sizeof(ppcState.dtlb_va));
memset(ppcState.dtlb_pa, 0, sizeof(ppcState.dtlb_pa));
ppcState.itlb_last = 0;
memset(ppcState.itlb_va, 0, sizeof(ppcState.itlb_va));
memset(ppcState.itlb_pa, 0, sizeof(ppcState.itlb_pa));
memset(ppcState.mojs, 0, sizeof(ppcState.mojs));
memset(ppcState.sr, 0, sizeof(ppcState.sr));
ppcState.DebugCount = 0;
+1
View File
@@ -1049,6 +1049,7 @@ void CFrame::DoStop()
DoRecordingSave();
if(Movie::IsPlayingInput() || Movie::IsRecordingInput())
Movie::EndPlayInput(false);
NetPlay::StopGame();
wxBeginBusyCursor();
BootManager::Stop();
+3
View File
@@ -263,6 +263,9 @@ bool DolphinApp::OnInit()
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
File::CreateFullPath(File::GetUserPath(D_MAILLOGS_IDX));
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + USA_DIR DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + EUR_DIR DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + JAP_DIR DIR_SEP);
LogManager::Init();
SConfig::Init();
+21 -13
View File
@@ -17,6 +17,7 @@
#include <string>
#define NETPLAY_TITLEBAR "Dolphin NetPlay"
#define INITIAL_PAD_BUFFER_SIZE 20
BEGIN_EVENT_TABLE(NetPlayDiag, wxFrame)
EVT_COMMAND(wxID_ANY, wxEVT_THREAD, NetPlayDiag::OnThread)
@@ -246,6 +247,7 @@ void NetPlaySetupDiag::OnHost(wxCommandEvent&)
m_host_port_text->GetValue().ToULong(&port);
netplay_server = new NetPlayServer(u16(port));
netplay_server->ChangeGame(game);
netplay_server->AdjustPadBufferSize(INITIAL_PAD_BUFFER_SIZE);
if (netplay_server->is_connected)
{
#ifdef USE_UPNP
@@ -281,6 +283,7 @@ NetPlayDiag::NetPlayDiag(wxWindow* const parent, const CGameListCtrl* const game
: wxFrame(parent, wxID_ANY, wxT(NETPLAY_TITLEBAR), wxDefaultPosition, wxDefaultSize)
, m_selected_game(game)
, m_game_list(game_list)
, m_start_btn(NULL)
{
wxPanel* const panel = new wxPanel(this);
@@ -338,15 +341,13 @@ NetPlayDiag::NetPlayDiag(wxWindow* const parent, const CGameListCtrl* const game
wxBoxSizer* const bottom_szr = new wxBoxSizer(wxHORIZONTAL);
if (is_hosting)
{
wxButton* const start_btn = new wxButton(panel, wxID_ANY, _("Start"));
start_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlayDiag::OnStart, this);
bottom_szr->Add(start_btn);
wxButton* const stop_btn = new wxButton(panel, wxID_ANY, _("Stop"));
stop_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlayDiag::OnStop, this);
bottom_szr->Add(stop_btn);
m_start_btn = new wxButton(panel, wxID_ANY, _("Start"));
m_start_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlayDiag::OnStart, this);
bottom_szr->Add(m_start_btn);
bottom_szr->Add(new wxStaticText(panel, wxID_ANY, _("Buffer:")), 0, wxLEFT | wxCENTER, 5 );
wxSpinCtrl* const padbuf_spin = new wxSpinCtrl(panel, wxID_ANY, wxT("20")
, wxDefaultPosition, wxSize(64, -1), wxSP_ARROW_KEYS, 0, 200, 20);
, wxDefaultPosition, wxSize(64, -1), wxSP_ARROW_KEYS, 0, 200, INITIAL_PAD_BUFFER_SIZE);
padbuf_spin->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &NetPlayDiag::OnAdjustBuffer, this);
bottom_szr->Add(padbuf_spin, 0, wxCENTER);
}
@@ -409,7 +410,7 @@ void NetPlayDiag::GetNetSettings(NetSettings &settings)
settings.m_Controllers[i] = SConfig::GetInstance().m_SIDevice[i];
}
const std::string& NetPlayDiag::FindGame()
std::string NetPlayDiag::FindGame()
{
// find path for selected game, sloppy..
for (u32 i = 0 ; auto game = m_game_list->GetISO(i); ++i)
@@ -428,11 +429,6 @@ void NetPlayDiag::OnStart(wxCommandEvent&)
netplay_server->StartGame(FindGame());
}
void NetPlayDiag::OnStop(wxCommandEvent&)
{
netplay_server->StopGame();
}
void NetPlayDiag::BootGame(const std::string& filename)
{
main_frame->BootGame(filename);
@@ -469,12 +465,16 @@ void NetPlayDiag::OnMsgStartGame()
{
wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_START_GAME);
GetEventHandler()->AddPendingEvent(evt);
if (m_start_btn)
m_start_btn->Disable();
}
void NetPlayDiag::OnMsgStopGame()
{
wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_STOP_GAME);
GetEventHandler()->AddPendingEvent(evt);
if (m_start_btn)
m_start_btn->Enable();
}
void NetPlayDiag::OnAdjustBuffer(wxCommandEvent& event)
@@ -685,3 +685,11 @@ void PadMapDiag::OnAdjust(wxCommandEvent& event)
m_wiimapping[i] = m_map_cbox[i+4]->GetSelection() - 1;
}
}
void NetPlay::StopGame()
{
if (netplay_server != NULL)
netplay_server->StopGame();
// TODO: allow non-hosting clients to close the window
}
+7 -2
View File
@@ -67,7 +67,6 @@ public:
Common::FifoQueue<std::string> chat_msgs;
void OnStart(wxCommandEvent& event);
void OnStop(wxCommandEvent& event);
// implementation of NetPlayUI methods
void BootGame(const std::string& filename);
@@ -92,7 +91,7 @@ private:
void OnAdjustBuffer(wxCommandEvent& event);
void OnConfigPads(wxCommandEvent& event);
void GetNetSettings(NetSettings &settings);
const std::string& FindGame();
std::string FindGame();
wxListBox* m_player_lbox;
wxTextCtrl* m_chat_text;
@@ -101,6 +100,7 @@ private:
std::string m_selected_game;
wxButton* m_game_btn;
wxButton* m_start_btn;
std::vector<int> m_playerids;
@@ -134,5 +134,10 @@ private:
int* const m_wiimapping;
};
namespace NetPlay
{
void StopGame();
}
#endif // _NETWINDOW_H_
+1
View File
@@ -33,6 +33,7 @@ set(SRCS Src/BPFunctions.cpp
Src/VertexManagerBase.cpp
Src/VertexShaderGen.cpp
Src/VertexShaderManager.cpp
Src/VideoBackendBase.cpp
Src/VideoConfig.cpp
Src/VideoState.cpp
Src/XFMemory.cpp
-35
View File
@@ -299,38 +299,3 @@ void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size
#undef SetRegName
}
}
AlphaTest::TEST_RESULT AlphaTest::TestResult()
{
switch(logic)
{
case 0: // AND
if (comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_ALWAYS)
return PASS;
if (comp0 == ALPHACMP_NEVER || comp1 == ALPHACMP_NEVER)
return FAIL;
break;
case 1: // OR
if (comp0 == ALPHACMP_ALWAYS || comp1 == ALPHACMP_ALWAYS)
return PASS;
if (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_NEVER)
return FAIL;
break;
case 2: // XOR
if ((comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_NEVER) || (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_ALWAYS))
return PASS;
if ((comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_ALWAYS) || (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_NEVER))
return FAIL;
break;
case 3: // XNOR
if ((comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_NEVER) || (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_ALWAYS))
return FAIL;
if ((comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_ALWAYS) || (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_NEVER))
return PASS;
break;
}
return UNDETERMINED;
}
+38 -1
View File
@@ -805,6 +805,7 @@ union PE_CONTROL
u32 unused : 17;
u32 rid : 8;
};
u32 hex;
};
@@ -884,7 +885,40 @@ union AlphaTest
PASS = 2,
};
TEST_RESULT TestResult();
inline TEST_RESULT TestResult() const
{
switch(logic)
{
case 0: // AND
if (comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_ALWAYS)
return PASS;
if (comp0 == ALPHACMP_NEVER || comp1 == ALPHACMP_NEVER)
return FAIL;
break;
case 1: // OR
if (comp0 == ALPHACMP_ALWAYS || comp1 == ALPHACMP_ALWAYS)
return PASS;
if (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_NEVER)
return FAIL;
break;
case 2: // XOR
if ((comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_NEVER) || (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_ALWAYS))
return PASS;
if ((comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_ALWAYS) || (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_NEVER))
return FAIL;
break;
case 3: // XNOR
if ((comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_NEVER) || (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_ALWAYS))
return FAIL;
if ((comp0 == ALPHACMP_ALWAYS && comp1 == ALPHACMP_ALWAYS) || (comp0 == ALPHACMP_NEVER && comp1 == ALPHACMP_NEVER))
return PASS;
break;
}
return UNDETERMINED;
}
};
union UPE_Copy
@@ -1005,6 +1039,9 @@ struct BPMemory
TevKSel tevksel[8];//0xf6,0xf7,f8,f9,fa,fb,fc,fd
u32 bpMask; //0xFE
u32 unknown18; //ff
bool UseEarlyDepthTest() const { return zcontrol.early_ztest && zmode.testenable; }
bool UseLateDepthTest() const { return !zcontrol.early_ztest && zmode.testenable; }
};
#pragma pack()
+4 -1
View File
@@ -153,7 +153,10 @@ void BPWritten(const BPCmd& bp)
bpmem.genMode.numtexgens, bpmem.genMode.numcolchans,
bpmem.genMode.multisampling, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode,
bpmem.genMode.numindstages, bpmem.genMode.zfreeze);
SetGenerationMode();
// Only call SetGenerationMode when cull mode changes.
if (bp.changes & 0xC000)
SetGenerationMode();
break;
}
case BPMEM_IND_MTXA: // Index Matrix Changed
+34 -45
View File
@@ -9,40 +9,22 @@
#include "NativeVertexFormat.h"
#include "XFMemory.h"
static const char* LightCol(const char* lightsName, unsigned int index, const char* swizzle)
{
static char result[32];
snprintf(result, sizeof(result), "%s[5*%d].%s", lightsName, index, swizzle);
return result;
}
static const char* LightCosAtt(const char* lightsName, unsigned int index)
{
static char result[32];
snprintf(result, sizeof(result), "%s[5*%d+1]", lightsName, index);
return result;
}
#define LIGHT_COL "%s[5*%d].%s"
#define LIGHT_COL_PARAMS(lightsName, index, swizzle) (lightsName), (index), (swizzle)
static const char* LightDistAtt(const char* lightsName, unsigned int index)
{
static char result[32];
snprintf(result, sizeof(result), "%s[5*%d+2]", lightsName, index);
return result;
}
#define LIGHT_COSATT "%s[5*%d+1]"
#define LIGHT_COSATT_PARAMS(lightsName, index) (lightsName), (index)
static const char* LightPos(const char* lightsName, unsigned int index)
{
static char result[32];
snprintf(result, sizeof(result), "%s[5*%d+3]", lightsName, index);
return result;
}
#define LIGHT_DISTATT "%s[5*%d+2]"
#define LIGHT_DISTATT_PARAMS(lightsName, index) (lightsName), (index)
#define LIGHT_POS "%s[5*%d+3]"
#define LIGHT_POS_PARAMS(lightsName, index) (lightsName), (index)
#define LIGHT_DIR "%s[5*%d+4]"
#define LIGHT_DIR_PARAMS(lightsName, index) (lightsName), (index)
static const char* LightDir(const char* lightsName, unsigned int index)
{
static char result[32];
snprintf(result, sizeof(result), "%s[5*%d+4]", lightsName, index);
return result;
}
template<class T>
static void GenerateLightShader(T& object, LightingUidData& uid_data, int index, int litchan_index, const char* lightsName, int coloralpha)
@@ -62,13 +44,13 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
object.Write("lacc.%s += %s;\n", swizzle, LightCol(lightsName, index, swizzle));
object.Write("lacc.%s += " LIGHT_COL";\n", swizzle, LIGHT_COL_PARAMS(lightsName, index, swizzle));
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
object.Write("ldir = normalize(%s.xyz - pos.xyz);\n", LightPos(lightsName, index));
object.Write("lacc.%s += %sdot(ldir, _norm0)) * %s;\n",
swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", LightCol(lightsName, index, swizzle));
object.Write("ldir = normalize(" LIGHT_POS".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("lacc.%s += %sdot(ldir, _norm0)) * " LIGHT_COL";\n",
swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", LIGHT_COL_PARAMS(lightsName, index, swizzle));
break;
default: _assert_(0);
}
@@ -77,31 +59,34 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
{
if (chan.attnfunc == 3)
{ // spot
object.Write("ldir = %s.xyz - pos.xyz;\n", LightPos(lightsName, index));
object.Write("ldir = " LIGHT_POS".xyz - pos.xyz;\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("dist2 = dot(ldir, ldir);\n"
"dist = sqrt(dist2);\n"
"ldir = ldir / dist;\n"
"attn = max(0.0f, dot(ldir, %s.xyz));\n", LightDir(lightsName, index));
object.Write("attn = max(0.0f, dot(%s.xyz, float3(1.0f, attn, attn*attn))) / dot(%s.xyz, float3(1.0f,dist,dist2));\n", LightCosAtt(lightsName, index), LightDistAtt(lightsName, index));
"attn = max(0.0f, dot(ldir, " LIGHT_DIR".xyz));\n",
LIGHT_DIR_PARAMS(lightsName, index));
object.Write("attn = max(0.0f, dot(" LIGHT_COSATT".xyz, float3(1.0f, attn, attn*attn))) / dot(" LIGHT_DISTATT".xyz, float3(1.0f,dist,dist2));\n",
LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index));
}
else if (chan.attnfunc == 1)
{ // specular
object.Write("ldir = normalize(%s.xyz);\n", LightPos(lightsName, index));
object.Write("attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, %s.xyz)) : 0.0f;\n", LightDir(lightsName, index));
object.Write("attn = max(0.0f, dot(%s.xyz, float3(1,attn,attn*attn))) / dot(%s.xyz, float3(1,attn,attn*attn));\n", LightCosAtt(lightsName, index), LightDistAtt(lightsName, index));
object.Write("ldir = normalize(" LIGHT_POS".xyz);\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, " LIGHT_DIR".xyz)) : 0.0f;\n", LIGHT_DIR_PARAMS(lightsName, index));
object.Write("attn = max(0.0f, dot(" LIGHT_COSATT".xyz, float3(1,attn,attn*attn))) / dot(" LIGHT_DISTATT".xyz, float3(1,attn,attn*attn));\n",
LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index));
}
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
object.Write("lacc.%s += attn * %s;\n", swizzle, LightCol(lightsName, index, swizzle));
object.Write("lacc.%s += attn * " LIGHT_COL";\n", swizzle, LIGHT_COL_PARAMS(lightsName, index, swizzle));
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
object.Write("lacc.%s += attn * %sdot(ldir, _norm0)) * %s;\n",
object.Write("lacc.%s += attn * %sdot(ldir, _norm0)) * " LIGHT_COL";\n",
swizzle,
chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(",
LightCol(lightsName, index, swizzle));
LIGHT_COL_PARAMS(lightsName, index, swizzle));
break;
default: _assert_(0);
}
@@ -150,7 +135,10 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
else if (components & VB_HAS_COL0 )
object.Write("lacc = %s0;\n", inColorName);
else
object.Write("lacc = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
// TODO: this isn't verified. Here we want to read the ambient from the vertex,
// but the vertex itself has no color. So we don't know which value to read.
// Returing 1.0 is the same as disabled lightning, so this could be fine
object.Write("lacc = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
}
else // from color
{
@@ -191,7 +179,8 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
else if (components & VB_HAS_COL0 )
object.Write("lacc.w = %s0.w;\n", inColorName);
else
object.Write("lacc.w = 0.0f;\n");
// TODO: The same for alpha: We want to read from vertex, but the vertex has no color
object.Write("lacc.w = 1.0f;\n");
}
else // from color
{
@@ -1,3 +1,9 @@
#include "PerfQueryBase.h"
#include "VideoConfig.h"
PerfQueryBase* g_perf_query = 0;
bool PerfQueryBase::ShouldEmulate() const
{
return g_ActiveConfig.bPerfQueriesEnable;
}
+4 -1
View File
@@ -25,9 +25,12 @@ enum PerfQueryGroup
class PerfQueryBase
{
public:
PerfQueryBase() {};
PerfQueryBase() {}
virtual ~PerfQueryBase() {}
// Checks if performance queries are enabled in the gameini configuration.
bool ShouldEmulate() const;
// Begin querying the specified value for the following host GPU commands
virtual void EnableQuery(PerfQueryGroup type) {}
+50 -30
View File
@@ -216,7 +216,7 @@ static char swapModeTable[4][5];
static char text[16384];
static void BuildSwapModeTable()
static inline void BuildSwapModeTable()
{
static const char *swapColors = "rgba";
for (int i = 0; i < 4; i++)
@@ -229,13 +229,13 @@ static void BuildSwapModeTable()
}
}
template<class T> static void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, API_TYPE ApiType, RegisterState RegisterStates[4]);
template<class T> static void SampleTexture(T& out, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType);
template<class T> static void WriteAlphaTest(T& out, pixel_shader_uid_data& uid_data, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth);
template<class T> static void WriteFog(T& out, pixel_shader_uid_data& uid_data);
template<class T> static inline void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, API_TYPE ApiType, RegisterState RegisterStates[4]);
template<class T> static inline void SampleTexture(T& out, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType);
template<class T> static inline void WriteAlphaTest(T& out, pixel_shader_uid_data& uid_data, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth);
template<class T> static inline void WriteFog(T& out, pixel_shader_uid_data& uid_data);
template<class T>
static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
{
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
pixel_shader_uid_data dummy_data;
@@ -243,23 +243,25 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
? out.template GetUidData<pixel_shader_uid_data>() : dummy_data;
out.SetBuffer(text);
const bool is_writing_shadercode = (out.GetBuffer() != NULL);
#ifndef ANDROID
locale_t locale;
locale_t old_locale;
if (out.GetBuffer() != NULL)
if (is_writing_shadercode)
{
locale = newlocale(LC_NUMERIC_MASK, "C", NULL); // New locale for compilation
old_locale = uselocale(locale); // Apply the locale for this thread
}
#endif
text[sizeof(text) - 1] = 0x7C; // canary
if (is_writing_shadercode)
text[sizeof(text) - 1] = 0x7C; // canary
unsigned int numStages = bpmem.genMode.numtevstages + 1;
unsigned int numTexgen = bpmem.genMode.numtexgens;
const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.zcontrol.early_ztest && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED);
const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest && bpmem.zmode.testenable) || (!g_ActiveConfig.bFastDepthCalc && !forced_early_z);
const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED);
const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z);
out.Write("//Pixel Shader for TEV stages\n");
out.Write("//%i TEV stages, %i texgens, %i IND stages\n",
@@ -331,7 +333,7 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
out.Write("VARYIN float4 colors_02;\n");
out.Write("VARYIN float4 colors_12;\n");
// compute window position if needed because binding semantic WPOS is not widely supported
// Let's set up attributes
if (xfregs.numTexGen.numTexGens < 7)
@@ -365,18 +367,37 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
}
out.Write("float4 clipPos;\n");
}
if (forced_early_z)
{
// HACK: This doesn't force the driver to write to depth buffer if alpha test fails.
// It just allows it, but it seems that all drivers do.
out.Write("layout(early_fragment_tests) in;\n");
}
else if (bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED) && is_writing_shadercode)
{
static bool warn_once = true;
if (warn_once)
WARN_LOG(VIDEO, "Early z test enabled but not possible to emulate with current configuration. Make sure to use the D3D11 or OpenGL backend and enable fast depth calculations. If this message still shows up your hardware isn't able to emulate the feature properly (a GPU which supports D3D 11.0 / OGL 4.2 is required).");
warn_once = false;
}
out.Write("void main()\n{\n");
}
else
{
if (forced_early_z)
{
out.Write("[earlydepthstencil]\n");
}
else if (bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED) && is_writing_shadercode)
{
static bool warn_once = true;
if (warn_once)
WARN_LOG(VIDEO, "Early z test enabled but not possible to emulate with current configuration. Make sure to use the D3D11 or OpenGL backend and enable fast depth calculations. If this message still shows up your hardware isn't able to emulate the feature properly (a GPU which supports D3D 11.0 / OGL 4.2 is required).");
warn_once = false;
}
out.Write("void main(\n");
if(ApiType != API_D3D11)
{
@@ -481,7 +502,6 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
{
uid_data.xfregs_numTexGen_numTexGens = xfregs.numTexGen.numTexGens;
if (xfregs.numTexGen.numTexGens < 7)
{
out.Write("\tfloat3 _norm0 = normalize(Normal.xyz);\n\n");
@@ -630,11 +650,11 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
uid_data.per_pixel_depth = per_pixel_depth;
uid_data.forced_early_z = forced_early_z;
uid_data.fast_depth_calc = g_ActiveConfig.bFastDepthCalc;
uid_data.early_ztest = bpmem.zcontrol.early_ztest;
uid_data.early_ztest = bpmem.UseEarlyDepthTest();
uid_data.fog_fsel = bpmem.fog.c_proj_fsel.fsel;
// Note: z-textures are not written to depth buffer if early depth test is used
if (per_pixel_depth && bpmem.zcontrol.early_ztest)
if (per_pixel_depth && bpmem.UseEarlyDepthTest())
out.Write("depth = zCoord;\n");
// Note: depth texture output is only written to depth buffer if late depth test is used
@@ -652,7 +672,7 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
out.Write("zCoord = zCoord * (16777216.0f/16777215.0f);\n");
}
if (per_pixel_depth && !bpmem.zcontrol.early_ztest)
if (per_pixel_depth && bpmem.UseLateDepthTest())
out.Write("depth = zCoord;\n");
if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
@@ -687,16 +707,16 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
out.Write("}\n");
if (text[sizeof(text) - 1] != 0x7C)
PanicAlert("PixelShader generator - buffer too small, canary has been eaten!");
if (is_writing_shadercode)
{
if (text[sizeof(text) - 1] != 0x7C)
PanicAlert("PixelShader generator - buffer too small, canary has been eaten!");
#ifndef ANDROID
if (out.GetBuffer() != NULL)
{
uselocale(old_locale); // restore locale
freelocale(locale);
}
#endif
}
}
@@ -744,7 +764,7 @@ static const char *TEVCMPAlphaOPTable[16] =
};
template<class T>
static void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, API_TYPE ApiType, RegisterState RegisterStates[4])
static inline void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, API_TYPE ApiType, RegisterState RegisterStates[4])
{
int texcoord = bpmem.tevorders[n/2].getTexCoord(n&1);
bool bHasTexCoord = (u32)texcoord < bpmem.genMode.numtexgens;
@@ -887,7 +907,7 @@ static void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, API_TYPE
char *texswap = swapModeTable[bpmem.combiners[n].alphaC.tswap];
int texmap = bpmem.tevorders[n/2].getTexMap(n&1);
uid_data.SetTevindrefTexmap(i, texmap);
out.Write("textemp = ");
SampleTexture<T>(out, "tevcoord", texswap, texmap, ApiType);
}
@@ -1114,7 +1134,7 @@ template<class T>
void SampleTexture(T& out, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType)
{
out.SetConstantsUsed(C_TEXDIMS+texmap,C_TEXDIMS+texmap);
if (ApiType == API_D3D11)
out.Write("Tex%d.Sample(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", texmap,texmap, texcoords, texmap, texswap);
else
@@ -1142,7 +1162,7 @@ static const char *tevAlphaFunclogicTable[] =
};
template<class T>
static void WriteAlphaTest(T& out, pixel_shader_uid_data& uid_data, API_TYPE ApiType, DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth)
static inline void WriteAlphaTest(T& out, pixel_shader_uid_data& uid_data, API_TYPE ApiType, DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth)
{
static const char *alphaRef[2] =
{
@@ -1185,11 +1205,11 @@ static void WriteAlphaTest(T& out, pixel_shader_uid_data& uid_data, API_TYPE Api
// We implement "depth test before texturing" by disabling alpha test when early-z is in use.
// It seems to be less buggy than not to update the depth buffer if alpha test fails,
// but both ways wouldn't be accurate.
// OpenGL 4.2 has a flag which allows the driver to still update the depth buffer
// if alpha test fails. The driver doesn't have to, but I assume they all do because
// it's the much faster code path for the GPU.
uid_data.alpha_test_use_zcomploc_hack = bpmem.zcontrol.early_ztest && bpmem.zmode.updateenable && !g_ActiveConfig.backend_info.bSupportsEarlyZ;
uid_data.alpha_test_use_zcomploc_hack = bpmem.UseEarlyDepthTest() && bpmem.zmode.updateenable && !g_ActiveConfig.backend_info.bSupportsEarlyZ;
if (!uid_data.alpha_test_use_zcomploc_hack)
{
out.Write("\t\tdiscard;\n");
@@ -1213,7 +1233,7 @@ static const char *tevFogFuncsTable[] =
};
template<class T>
static void WriteFog(T& out, pixel_shader_uid_data& uid_data)
static inline void WriteFog(T& out, pixel_shader_uid_data& uid_data)
{
uid_data.fog_fsel = bpmem.fog.c_proj_fsel.fsel;
if(bpmem.fog.c_proj_fsel.fsel == 0)
@@ -1255,7 +1275,7 @@ static void WriteFog(T& out, pixel_shader_uid_data& uid_data)
}
else
{
if (bpmem.fog.c_proj_fsel.fsel != 2)
if (bpmem.fog.c_proj_fsel.fsel != 2 && out.GetBuffer() != NULL)
WARN_LOG(VIDEO, "Unknown Fog Type! %08x", bpmem.fog.c_proj_fsel.fsel);
}
+17 -23
View File
@@ -63,18 +63,30 @@ struct pixel_shader_uid_data
u32 num_values; // TODO: Shouldn't be a u32
u32 NumValues() const { return num_values; }
u32 components;
u32 components : 23;
u32 dstAlphaMode : 2;
u32 Pretest : 2;
u32 nIndirectStagesUsed : 4;
u32 pad0 : 1;
u32 genMode_numtexgens : 4;
u32 genMode_numtevstages : 4;
u32 genMode_numindstages : 3;
u32 nIndirectStagesUsed : 8;
u32 alpha_test_comp0 : 3;
u32 alpha_test_comp1 : 3;
u32 alpha_test_logic : 2;
u32 alpha_test_use_zcomploc_hack : 1;
u32 fog_proj : 1;
u32 fog_fsel : 3;
u32 fog_RangeBaseEnabled : 1;
u32 ztex_op : 2;
u32 fast_depth_calc : 1;
u32 per_pixel_depth : 1;
u32 forced_early_z : 1;
u32 early_ztest : 1;
u32 pad1 : 1;
u32 texMtxInfo_n_projection : 8; // 8x1 bit
u32 tevindref_bi0 : 3;
u32 tevindref_bc0 : 3;
u32 tevindref_bi1 : 3;
@@ -83,6 +95,7 @@ struct pixel_shader_uid_data
u32 tevindref_bc3 : 3;
u32 tevindref_bi4 : 3;
u32 tevindref_bc4 : 3;
inline void SetTevindrefValues(int index, u32 texcoord, u32 texmap)
{
if (index == 0) { tevindref_bc0 = texcoord; tevindref_bi0 = texmap; }
@@ -98,25 +111,6 @@ struct pixel_shader_uid_data
else if (index == 3) { tevindref_bi4 = texmap; }
}
u32 alpha_test_comp0 : 3;
u32 alpha_test_comp1 : 3;
u32 alpha_test_logic : 2;
u32 alpha_test_use_zcomploc_hack : 1;
u32 fog_proj : 1;
u32 fog_fsel : 3;
u32 fog_RangeBaseEnabled : 1;
u32 ztex_op : 2;
u32 fast_depth_calc : 1;
u32 per_pixel_depth : 1;
u32 forced_early_z : 1;
u32 early_ztest : 1;
u32 xfregs_numTexGen_numTexGens : 4;
struct {
// TODO: Can save a lot space by removing the padding bits
u32 cc : 24;
@@ -173,7 +173,7 @@ private:
};
template<class T>
static void WriteRegister(T& object, API_TYPE ApiType, const char *prefix, const u32 num)
static inline void WriteRegister(T& object, API_TYPE ApiType, const char *prefix, const u32 num)
{
if (ApiType == API_OPENGL)
return; // Nothing to do here
@@ -182,7 +182,7 @@ static void WriteRegister(T& object, API_TYPE ApiType, const char *prefix, const
}
template<class T>
static void WriteLocation(T& object, API_TYPE ApiType, bool using_ubos)
static inline void WriteLocation(T& object, API_TYPE ApiType, bool using_ubos)
{
if (using_ubos)
return;
@@ -191,7 +191,7 @@ static void WriteLocation(T& object, API_TYPE ApiType, bool using_ubos)
}
template<class T>
static void DeclareUniform(T& object, API_TYPE api_type, bool using_ubos, const u32 num, const char* type, const char* name)
static inline void DeclareUniform(T& object, API_TYPE api_type, bool using_ubos, const u32 num, const char* type, const char* name)
{
WriteLocation(object, api_type, using_ubos);
object.Write("%s %s ", type, name);
+18 -32
View File
@@ -38,7 +38,7 @@ static void DefineVSOutputStructMember(T& object, API_TYPE api_type, const char*
}
template<class T>
static void GenerateVSOutputStruct(T& object, u32 components, API_TYPE api_type)
static inline void GenerateVSOutputStruct(T& object, u32 components, API_TYPE api_type)
{
object.Write("struct VS_OUTPUT {\n");
DefineVSOutputStructMember(object, api_type, "float4", "pos", -1, "POSITION");
@@ -67,7 +67,7 @@ static void GenerateVSOutputStruct(T& object, u32 components, API_TYPE api_type)
}
template<class T>
static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
{
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
vertex_shader_uid_data dummy_data;
@@ -75,22 +75,23 @@ static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
? out.template GetUidData<vertex_shader_uid_data>() : dummy_data;
out.SetBuffer(text);
const bool is_writing_shadercode = (out.GetBuffer() != NULL);
#ifndef ANDROID
locale_t locale;
locale_t old_locale;
if (out.GetBuffer() != NULL)
if (is_writing_shadercode)
{
locale = newlocale(LC_NUMERIC_MASK, "C", NULL); // New locale for compilation
old_locale = uselocale(locale); // Apply the locale for this thread
}
#endif
text[sizeof(text) - 1] = 0x7C; // canary
if (is_writing_shadercode)
text[sizeof(text) - 1] = 0x7C; // canary
_assert_(bpmem.genMode.numtexgens == xfregs.numTexGen.numTexGens);
_assert_(bpmem.genMode.numcolchans == xfregs.numChan.numColorChans);
bool is_d3d = (api_type & API_D3D9 || api_type == API_D3D11);
// uniforms
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
out.Write("layout(std140) uniform VSBlock {\n");
@@ -174,19 +175,9 @@ static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
if (components & VB_HAS_NRM0)
out.Write(" float3 rawnorm0 : NORMAL0,\n");
if (components & VB_HAS_NRM1)
{
if (is_d3d)
out.Write(" float3 rawnorm1 : NORMAL1,\n");
else
out.Write(" float3 rawnorm1 : ATTR%d,\n", SHADER_NORM1_ATTRIB);
}
out.Write(" float3 rawnorm1 : NORMAL1,\n");
if (components & VB_HAS_NRM2)
{
if (is_d3d)
out.Write(" float3 rawnorm2 : NORMAL2,\n");
else
out.Write(" float3 rawnorm2 : ATTR%d,\n", SHADER_NORM2_ATTRIB);
}
out.Write(" float3 rawnorm2 : NORMAL2,\n");
if (components & VB_HAS_COL0)
out.Write(" float4 color0 : COLOR0,\n");
if (components & VB_HAS_COL1)
@@ -198,12 +189,7 @@ static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
out.Write(" float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
}
if (components & VB_HAS_POSMTXIDX)
{
if (is_d3d)
out.Write(" float4 blend_indices : BLENDINDICES,\n");
else
out.Write(" float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB);
}
out.Write(" float4 blend_indices : BLENDINDICES,\n");
out.Write(" float4 rawpos : POSITION) {\n");
}
out.Write("VS_OUTPUT o;\n");
@@ -225,7 +211,7 @@ static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
out.Write("int posmtx = int(fposmtx);\n");
}
if (DriverDetails::HasBug(DriverDetails::BUG_NODYNUBOACCESS))
if (is_writing_shadercode && DriverDetails::HasBug(DriverDetails::BUG_NODYNUBOACCESS))
{
// This'll cause issues, but it can't be helped
out.Write("float4 pos = float4(dot(" I_TRANSFORMMATRICES"[0], rawpos), dot(" I_TRANSFORMMATRICES"[1], rawpos), dot(" I_TRANSFORMMATRICES"[2], rawpos), 1);\n");
@@ -353,7 +339,7 @@ static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
// transform the light dir into tangent space
uid_data.texMtxInfo[i].embosslightshift = xfregs.texMtxInfo[i].embosslightshift;
uid_data.texMtxInfo[i].embosssourceshift = xfregs.texMtxInfo[i].embosssourceshift;
out.Write("ldir = normalize(%s.xyz - pos.xyz);\n", LightPos(I_LIGHTS, texinfo.embosslightshift));
out.Write("ldir = normalize(" LIGHT_POS".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(I_LIGHTS, texinfo.embosslightshift));
out.Write("o.tex%d.xyz = o.tex%d.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0f);\n", i, texinfo.embosssourceshift);
}
else
@@ -468,7 +454,7 @@ static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
//write the true depth value, if the game uses depth textures pixel shaders will override with the correct values
//if not early z culling will improve speed
if (is_d3d)
if (api_type & API_D3D9 || api_type == API_D3D11)
{
out.Write("o.pos.z = " I_DEPTHPARAMS".x * o.pos.w + o.pos.z * " I_DEPTHPARAMS".y;\n");
}
@@ -547,16 +533,16 @@ static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
out.Write("return o;\n}\n");
}
if (text[sizeof(text) - 1] != 0x7C)
PanicAlert("VertexShader generator - buffer too small, canary has been eaten!");
if (is_writing_shadercode)
{
if (text[sizeof(text) - 1] != 0x7C)
PanicAlert("VertexShader generator - buffer too small, canary has been eaten!");
#ifndef ANDROID
if (out.GetBuffer() != NULL)
{
uselocale(old_locale); // restore locale
freelocale(locale);
}
#endif
}
}
void GetVertexShaderUid(VertexShaderUid& object, u32 components, API_TYPE api_type)
@@ -69,12 +69,12 @@ struct vertex_shader_uid_data
{
u32 NumValues() const { return sizeof(vertex_shader_uid_data); }
u32 components;
u32 numColorChans : 2;
u32 components : 23;
u32 numTexGens : 4;
u32 numColorChans : 2;
u32 dualTexTrans_enabled : 1;
u32 pixel_lighting : 1;
u32 pad0 : 1;
u32 texMtxInfo_n_projection : 16; // Stored separately to guarantee that the texMtxInfo struct is 8 bits wide
struct {
@@ -19,6 +19,8 @@ VideoBackend* g_video_backend = NULL;
static VideoBackend* s_default_backend = NULL;
#ifdef _WIN32
#include <windows.h>
// http://msdn.microsoft.com/en-us/library/ms725491.aspx
static bool IsGteVista()
{
@@ -181,6 +181,7 @@ void VideoConfig::GameIniLoad(const char *ini_file)
iniFile.GetIfExists("Video", "PH_ZFar", &sPhackvalue[1]);
iniFile.GetIfExists("Video", "ZTPSpeedupHack", &bZTPSpeedHack);
iniFile.GetIfExists("Video", "UseBBox", &bUseBBox);
iniFile.GetIfExists("Video", "PerfQueriesEnable", &bPerfQueriesEnable);
}
void VideoConfig::VerifyValidity()
@@ -108,6 +108,7 @@ struct VideoConfig
// Hacks
bool bEFBAccessEnable;
bool bDlistCachingEnable;
bool bPerfQueriesEnable;
bool bEFBCopyEnable;
bool bEFBCopyCacheEnable;
@@ -213,6 +213,7 @@
<ClCompile Include="Src\VertexManagerBase.cpp" />
<ClCompile Include="Src\VertexShaderGen.cpp" />
<ClCompile Include="Src\VertexShaderManager.cpp" />
<ClCompile Include="Src\VideoBackendBase.cpp" />
<ClCompile Include="Src\VideoConfig.cpp" />
<ClCompile Include="Src\VideoState.cpp" />
<ClCompile Include="Src\x64DLCache.cpp" />
@@ -266,6 +267,7 @@
<ClInclude Include="Src\VertexShaderGen.h" />
<ClInclude Include="Src\VertexShaderManager.h" />
<ClInclude Include="Src\VideoCommon.h" />
<ClInclude Include="Src\VideoBackendBase.h" />
<ClInclude Include="Src\VideoConfig.h" />
<ClInclude Include="Src\VideoState.h" />
<ClInclude Include="Src\XFMemory.h" />
@@ -4,6 +4,7 @@
<ClCompile Include="Src\CommandProcessor.cpp" />
<ClCompile Include="Src\memcpy_amd.cpp" />
<ClCompile Include="Src\PixelEngine.cpp" />
<ClCompile Include="Src\VideoBackendBase.cpp" />
<ClCompile Include="Src\VideoConfig.cpp" />
<ClCompile Include="Src\VertexLoader.cpp">
<Filter>Vertex Loading</Filter>
@@ -128,6 +129,7 @@
<ClInclude Include="Src\NativeVertexFormat.h" />
<ClInclude Include="Src\PixelEngine.h" />
<ClInclude Include="Src\VideoCommon.h" />
<ClInclude Include="Src\VideoBackendBase.h" />
<ClInclude Include="Src\VideoConfig.h" />
<ClInclude Include="Src\DataReader.h">
<Filter>Vertex Loading</Filter>