mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
- Improved Vertex & Fragment Shader Decompilers.
- Fixed some FPR instructions. - Implemented more GCM syscalls. - Fixed callbacks alert.
This commit is contained in:
parent
f42d4b6572
commit
0aff049960
@ -3236,11 +3236,58 @@ private:
|
|||||||
}
|
}
|
||||||
void FRES(u32 frd, u32 frb, bool rc)
|
void FRES(u32 frd, u32 frb, bool rc)
|
||||||
{
|
{
|
||||||
if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX);
|
double res;
|
||||||
CPU.FPR[frd] = static_cast<float>(1.0f/CPU.FPR[frb]);
|
|
||||||
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
|
if(_fpclass(CPU.FPR[frb]) >= _FPCLASS_NZ)
|
||||||
CPU.FPSCR.FI = 0;
|
{
|
||||||
CPU.FPSCR.FR = 0;
|
res = static_cast<float>(1.0 / CPU.FPR[frb]);
|
||||||
|
if(FPRdouble::IsINF(res) && CPU.FPR[frb] != 0.0)
|
||||||
|
{
|
||||||
|
if(res > 0.0)
|
||||||
|
{
|
||||||
|
(u64&)res = 0x47EFFFFFE0000000ULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(u64&)res = 0xC7EFFFFFE0000000ULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 v = CPU.FPR[frb];
|
||||||
|
|
||||||
|
if(v == 0ULL)
|
||||||
|
{
|
||||||
|
v = 0x7FF0000000000000ULL;
|
||||||
|
}
|
||||||
|
else if(v == 0x8000000000000000ULL)
|
||||||
|
{
|
||||||
|
v = 0xFFF0000000000000ULL;
|
||||||
|
}
|
||||||
|
else if(FPRdouble::IsNaN(CPU.FPR[frb]))
|
||||||
|
{
|
||||||
|
v = 0x7FF8000000000000ULL;
|
||||||
|
}
|
||||||
|
else if(CPU.FPR[frb] < 0.0)
|
||||||
|
{
|
||||||
|
v = 0x8000000000000000ULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v = 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = (double&)v;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(CPU.FPR[frb] == 0.0)
|
||||||
|
{
|
||||||
|
CPU.SetFPSCRException(FPSCR_ZX);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU.FPR[frd] = res;
|
||||||
|
|
||||||
if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
||||||
}
|
}
|
||||||
void FMULS(u32 frd, u32 fra, u32 frc, bool rc)
|
void FMULS(u32 frd, u32 fra, u32 frc, bool rc)
|
||||||
@ -3339,7 +3386,9 @@ private:
|
|||||||
}
|
}
|
||||||
void FCMPU(u32 crfd, u32 fra, u32 frb)
|
void FCMPU(u32 crfd, u32 fra, u32 frb)
|
||||||
{
|
{
|
||||||
if((CPU.FPSCR.FPRF = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb])) == 1)
|
int cmp_res = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb]);
|
||||||
|
|
||||||
|
if(cmp_res == CR_SO)
|
||||||
{
|
{
|
||||||
if(FPRdouble::IsSNaN(CPU.FPR[fra]) || FPRdouble::IsSNaN(CPU.FPR[frb]))
|
if(FPRdouble::IsSNaN(CPU.FPR[fra]) || FPRdouble::IsSNaN(CPU.FPR[frb]))
|
||||||
{
|
{
|
||||||
@ -3347,7 +3396,8 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU.SetCR(crfd, CPU.FPSCR.FPRF);
|
CPU.FPSCR.FPRF = cmp_res;
|
||||||
|
CPU.SetCR(crfd, cmp_res);
|
||||||
}
|
}
|
||||||
void FRSP(u32 frd, u32 frb, bool rc)
|
void FRSP(u32 frd, u32 frb, bool rc)
|
||||||
{
|
{
|
||||||
@ -3467,20 +3517,44 @@ private:
|
|||||||
}
|
}
|
||||||
void FDIV(u32 frd, u32 fra, u32 frb, bool rc)
|
void FDIV(u32 frd, u32 fra, u32 frb, bool rc)
|
||||||
{
|
{
|
||||||
if(FPRdouble::IsINF(CPU.FPR[fra]) == 0.0 && CPU.FPR[frb] == 0.0)
|
double res;
|
||||||
|
|
||||||
|
if(FPRdouble::IsNaN(CPU.FPR[fra]))
|
||||||
{
|
{
|
||||||
CPU.FPSCR.VXZDZ = 1;
|
res = CPU.FPR[fra];
|
||||||
}
|
}
|
||||||
else if(FPRdouble::IsINF(CPU.FPR[fra]) && FPRdouble::IsINF(CPU.FPR[frb]))
|
else if(FPRdouble::IsNaN(CPU.FPR[frb]))
|
||||||
{
|
{
|
||||||
CPU.FPSCR.VXIDI = 1;
|
res = CPU.FPR[frb];
|
||||||
}
|
}
|
||||||
else if(CPU.FPR[fra] != 0.0 && CPU.FPR[frb] == 0.0)
|
else
|
||||||
{
|
{
|
||||||
CPU.SetFPSCRException(FPSCR_ZX);
|
if(CPU.FPR[frb] == 0.0)
|
||||||
|
{
|
||||||
|
if(CPU.FPR[fra] == 0.0)
|
||||||
|
{
|
||||||
|
CPU.FPSCR.VXZDZ = 1;
|
||||||
|
res = FPR_NAN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = CPU.FPR[fra] / CPU.FPR[frb];
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU.SetFPSCRException(FPSCR_ZX);
|
||||||
|
}
|
||||||
|
else if(FPRdouble::IsINF(CPU.FPR[fra]) && FPRdouble::IsINF(CPU.FPR[frb]))
|
||||||
|
{
|
||||||
|
CPU.FPSCR.VXIDI = 1;
|
||||||
|
res = FPR_NAN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = CPU.FPR[fra] / CPU.FPR[frb];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU.FPR[frd] = CPU.FPR[fra] / CPU.FPR[frb];
|
CPU.FPR[frd] = res;
|
||||||
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
|
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
|
||||||
if(rc) UNK("fdiv.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
if(rc) UNK("fdiv.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
||||||
}
|
}
|
||||||
@ -3509,15 +3583,31 @@ private:
|
|||||||
}
|
}
|
||||||
void FMUL(u32 frd, u32 fra, u32 frc, bool rc)
|
void FMUL(u32 frd, u32 fra, u32 frc, bool rc)
|
||||||
{
|
{
|
||||||
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc];
|
if((FPRdouble::IsINF(CPU.FPR[fra]) && CPU.FPR[frc] == 0.0) || (FPRdouble::IsINF(CPU.FPR[frc]) && CPU.FPR[fra] == 0.0))
|
||||||
CPU.FPSCR.FI = 0;
|
{
|
||||||
CPU.FPSCR.FR = 0;
|
CPU.SetFPSCRException(FPSCR_VXIMZ);
|
||||||
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
|
CPU.FPR[frd] = FPR_NAN;
|
||||||
|
CPU.FPSCR.FI = 0;
|
||||||
|
CPU.FPSCR.FR = 0;
|
||||||
|
CPU.FPSCR.FPRF = FPR_QNAN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(FPRdouble::IsSNaN(CPU.FPR[fra]) || FPRdouble::IsSNaN(CPU.FPR[frc]))
|
||||||
|
{
|
||||||
|
CPU.SetFPSCRException(FPSCR_VXSNAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc];
|
||||||
|
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
|
||||||
|
}
|
||||||
|
|
||||||
if(rc) UNK("fmul.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
if(rc) UNK("fmul.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
||||||
}
|
}
|
||||||
void FRSQRTE(u32 frd, u32 frb, bool rc)
|
void FRSQRTE(u32 frd, u32 frb, bool rc)
|
||||||
{
|
{
|
||||||
//if(CPU.FPR[frb].
|
UNIMPLEMENTED();
|
||||||
|
//CPU.FPR[frd] = 1.0f / (float)sqrt(CPU.FPR[frb]);
|
||||||
}
|
}
|
||||||
void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
|
void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
|
||||||
{
|
{
|
||||||
@ -3545,14 +3635,16 @@ private:
|
|||||||
}
|
}
|
||||||
void FCMPO(u32 crfd, u32 fra, u32 frb)
|
void FCMPO(u32 crfd, u32 fra, u32 frb)
|
||||||
{
|
{
|
||||||
if((CPU.FPSCR.FPRF = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb])) == 1)
|
int cmp_res = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb]);
|
||||||
|
|
||||||
|
if(cmp_res == CR_SO)
|
||||||
{
|
{
|
||||||
if(FPRdouble::IsSNaN(CPU.FPR[fra]) || FPRdouble::IsSNaN(CPU.FPR[frb]))
|
if(FPRdouble::IsSNaN(CPU.FPR[fra]) || FPRdouble::IsSNaN(CPU.FPR[frb]))
|
||||||
{
|
{
|
||||||
CPU.SetFPSCRException(FPSCR_VXSNAN);
|
CPU.SetFPSCRException(FPSCR_VXSNAN);
|
||||||
if(!CPU.FPSCR.VE) CPU.SetFPSCRException(FPSCR_VXVC);
|
if(!CPU.FPSCR.VE) CPU.SetFPSCRException(FPSCR_VXVC);
|
||||||
}
|
}
|
||||||
else if(FPRdouble::IsQNaN(CPU.FPR[fra]) || FPRdouble::IsQNaN(CPU.FPR[frb]))
|
else
|
||||||
{
|
{
|
||||||
CPU.SetFPSCRException(FPSCR_VXVC);
|
CPU.SetFPSCRException(FPSCR_VXVC);
|
||||||
}
|
}
|
||||||
@ -3560,11 +3652,12 @@ private:
|
|||||||
CPU.FPSCR.FX = 1;
|
CPU.FPSCR.FX = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU.SetCR(crfd, CPU.FPSCR.FPRF);
|
CPU.FPSCR.FPRF = cmp_res;
|
||||||
|
CPU.SetCR(crfd, cmp_res);
|
||||||
}
|
}
|
||||||
void FNEG(u32 frd, u32 frb, bool rc)
|
void FNEG(u32 frd, u32 frb, bool rc)
|
||||||
{
|
{
|
||||||
CPU.FPR[frd] = ((u64&)CPU.FPR[frb]) ^ (1ULL << 63);
|
CPU.FPR[frd] = -CPU.FPR[frb];
|
||||||
if(rc) UNK("fneg.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
if(rc) UNK("fneg.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
||||||
}
|
}
|
||||||
void FMR(u32 frd, u32 frb, bool rc)
|
void FMR(u32 frd, u32 frb, bool rc)
|
||||||
@ -3574,7 +3667,7 @@ private:
|
|||||||
}
|
}
|
||||||
void FNABS(u32 frd, u32 frb, bool rc)
|
void FNABS(u32 frd, u32 frb, bool rc)
|
||||||
{
|
{
|
||||||
(u64&)CPU.FPR[frd] = (u64&)CPU.FPR[frb] | 0x8000000000000000ULL;
|
CPU.FPR[frd] = -fabs(CPU.FPR[frb]);
|
||||||
if(rc) UNK("fnabs.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
if(rc) UNK("fnabs.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
||||||
}
|
}
|
||||||
void FABS(u32 frd, u32 frb, bool rc)
|
void FABS(u32 frd, u32 frb, bool rc)
|
||||||
@ -3685,7 +3778,24 @@ private:
|
|||||||
}
|
}
|
||||||
void FCFID(u32 frd, u32 frb, bool rc)
|
void FCFID(u32 frd, u32 frb, bool rc)
|
||||||
{
|
{
|
||||||
CPU.FPR[frd] = (double)(u64&)CPU.FPR[frb];
|
s64 bi = (s64&)CPU.FPR[frb];
|
||||||
|
double bf = (double)bi;
|
||||||
|
s64 bfi = (s64)bf;
|
||||||
|
|
||||||
|
if(bi == bfi)
|
||||||
|
{
|
||||||
|
CPU.SetFPSCR_FI(0);
|
||||||
|
CPU.FPSCR.FR = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPU.SetFPSCR_FI(1);
|
||||||
|
CPU.FPSCR.FR = abs(bfi) > abs(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU.FPR[frd] = bf;
|
||||||
|
|
||||||
|
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
|
||||||
if(rc) UNK("fcfid.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
if(rc) UNK("fcfid.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ void PPUThread::DoCode(const s32 code)
|
|||||||
|
|
||||||
bool FPRdouble::IsINF(PPCdouble d)
|
bool FPRdouble::IsINF(PPCdouble d)
|
||||||
{
|
{
|
||||||
return d.GetType() == FPR_INF;
|
return ((u64&)d & 0x7FFFFFFFFFFFFFFFULL) == 0x7FF0000000000000ULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FPRdouble::IsNaN(PPCdouble d)
|
bool FPRdouble::IsNaN(PPCdouble d)
|
||||||
@ -224,12 +224,18 @@ bool FPRdouble::IsNaN(PPCdouble d)
|
|||||||
|
|
||||||
bool FPRdouble::IsQNaN(PPCdouble d)
|
bool FPRdouble::IsQNaN(PPCdouble d)
|
||||||
{
|
{
|
||||||
return d.GetType() == FPR_QNAN;
|
return
|
||||||
|
((u64&)d & 0x7FF0000000000000ULL) == 0x7FF0000000000000ULL &&
|
||||||
|
((u64&)d & 0x0007FFFFFFFFFFFULL) == 0ULL &&
|
||||||
|
((u64&)d & 0x000800000000000ULL) != 0ULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FPRdouble::IsSNaN(PPCdouble d)
|
bool FPRdouble::IsSNaN(PPCdouble d)
|
||||||
{
|
{
|
||||||
return d.GetType() == FPR_SNAN;
|
return
|
||||||
|
((u64&)d & 0x7FF0000000000000ULL) == 0x7FF0000000000000ULL &&
|
||||||
|
((u64&)d & 0x000FFFFFFFFFFFFFULL) != 0ULL &&
|
||||||
|
((u64&)d & 0x0008000000000000ULL) == 0ULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FPRdouble::Cmp(PPCdouble a, PPCdouble b)
|
int FPRdouble::Cmp(PPCdouble a, PPCdouble b)
|
||||||
|
@ -298,11 +298,11 @@ union VSCRhdr
|
|||||||
|
|
||||||
enum FPRType
|
enum FPRType
|
||||||
{
|
{
|
||||||
FPR_NORM,
|
//FPR_NORM,
|
||||||
FPR_ZERO,
|
//FPR_ZERO,
|
||||||
FPR_SNAN,
|
//FPR_SNAN,
|
||||||
//FPR_QNAN,
|
//FPR_QNAN,
|
||||||
FPR_INF,
|
//FPR_INF,
|
||||||
FPR_PZ = 0x2,
|
FPR_PZ = 0x2,
|
||||||
FPR_PN = 0x4,
|
FPR_PN = 0x4,
|
||||||
FPR_PINF = 0x5,
|
FPR_PINF = 0x5,
|
||||||
@ -357,7 +357,7 @@ struct PPCdouble
|
|||||||
|
|
||||||
switch(fpc)
|
switch(fpc)
|
||||||
{
|
{
|
||||||
case _FPCLASS_SNAN: return FPR_SNAN;
|
case _FPCLASS_SNAN:// return FPR_SNAN;
|
||||||
case _FPCLASS_QNAN: return FPR_QNAN;
|
case _FPCLASS_QNAN: return FPR_QNAN;
|
||||||
case _FPCLASS_NINF: return FPR_NINF;
|
case _FPCLASS_NINF: return FPR_NINF;
|
||||||
case _FPCLASS_NN: return FPR_NN;
|
case _FPCLASS_NN: return FPR_NN;
|
||||||
|
@ -136,7 +136,7 @@ void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
|
|||||||
IniEntry<int> entries_count;
|
IniEntry<int> entries_count;
|
||||||
entries_count.Init("count", "VFSManager");
|
entries_count.Init("count", "VFSManager");
|
||||||
|
|
||||||
int count;
|
int count = 0;
|
||||||
if(is_load)
|
if(is_load)
|
||||||
{
|
{
|
||||||
count = entries_count.LoadValue(count);
|
count = entries_count.LoadValue(count);
|
||||||
|
@ -5,34 +5,37 @@ void FragmentDecompilerThread::AddCode(wxString code)
|
|||||||
{
|
{
|
||||||
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return;
|
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return;
|
||||||
|
|
||||||
wxString cond;
|
wxString cond = wxEmptyString;
|
||||||
|
|
||||||
if(src0.exec_if_gr)
|
if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq)
|
||||||
{
|
{
|
||||||
cond = ">";
|
if(src0.exec_if_gr)
|
||||||
}
|
|
||||||
else if(src0.exec_if_lt)
|
|
||||||
{
|
|
||||||
cond = "<";
|
|
||||||
}
|
|
||||||
else if(src0.exec_if_eq)
|
|
||||||
{
|
|
||||||
cond = "=";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(src0.exec_if_eq)
|
|
||||||
{
|
|
||||||
cond += "=";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(src0.exec_if_gr && src0.exec_if_lt)
|
|
||||||
{
|
{
|
||||||
cond = "!=";
|
cond = ">";
|
||||||
|
}
|
||||||
|
else if(src0.exec_if_lt)
|
||||||
|
{
|
||||||
|
cond = "<";
|
||||||
|
}
|
||||||
|
else if(src0.exec_if_eq)
|
||||||
|
{
|
||||||
|
cond = "=";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(src0.exec_if_eq)
|
||||||
|
{
|
||||||
|
cond += "=";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(src0.exec_if_gr && src0.exec_if_lt)
|
||||||
|
{
|
||||||
|
cond = "!=";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cond)
|
if(cond.Len())
|
||||||
{
|
{
|
||||||
ConLog.Error("cond! [eq: %d gr: %d lt: %d] (%s)", src0.exec_if_eq, src0.exec_if_gr, src0.exec_if_lt, cond);
|
ConLog.Error("cond! [eq: %d gr: %d lt: %d] (%s)", src0.exec_if_eq, src0.exec_if_gr, src0.exec_if_lt, cond);
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
@ -43,12 +46,12 @@ void FragmentDecompilerThread::AddCode(wxString code)
|
|||||||
{
|
{
|
||||||
switch(src1.scale)
|
switch(src1.scale)
|
||||||
{
|
{
|
||||||
case 1: code = "(" + code + ") * 2"; break;
|
case 1: code = "(" + code + " * 2)"; break;
|
||||||
case 2: code = "(" + code + ") * 4"; break;
|
case 2: code = "(" + code + " * 4)"; break;
|
||||||
case 3: code = "(" + code + ") * 8"; break;
|
case 3: code = "(" + code + " * 8)"; break;
|
||||||
case 5: code = "(" + code + ") / 2"; break;
|
case 5: code = "(" + code + " / 2)"; break;
|
||||||
case 6: code = "(" + code + ") / 4"; break;
|
case 6: code = "(" + code + " / 4)"; break;
|
||||||
case 7: code = "(" + code + ") / 8"; break;
|
case 7: code = "(" + code + " / 8)"; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ConLog.Error("Bad scale: %d", src1.scale);
|
ConLog.Error("Bad scale: %d", src1.scale);
|
||||||
@ -57,6 +60,12 @@ void FragmentDecompilerThread::AddCode(wxString code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(dst.fp16)
|
||||||
|
{
|
||||||
|
//HACK! TODO: fp16 -> fp32
|
||||||
|
code = "/*" + code + "*/ vec4(1.0, 1.0, 1.0, 1.0)";
|
||||||
|
}
|
||||||
|
|
||||||
code = AddReg(dst.dest_reg, dst.fp16) + GetMask() + " = " + code + GetMask();
|
code = AddReg(dst.dest_reg, dst.fp16) + GetMask() + " = " + code + GetMask();
|
||||||
|
|
||||||
main += "\t" + code + ";\n";
|
main += "\t" + code + ";\n";
|
||||||
@ -66,18 +75,24 @@ wxString FragmentDecompilerThread::GetMask()
|
|||||||
{
|
{
|
||||||
wxString ret = wxEmptyString;
|
wxString ret = wxEmptyString;
|
||||||
|
|
||||||
if(dst.mask_x) ret += 'x';
|
static const char dst_mask[2][4] =
|
||||||
if(dst.mask_y) ret += 'y';
|
{
|
||||||
if(dst.mask_z) ret += 'z';
|
{'x', 'y', 'z', 'w'},
|
||||||
if(dst.mask_w) ret += 'w';
|
{'r', 'g', 'b', 'a'}
|
||||||
|
};
|
||||||
|
|
||||||
return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret);
|
if(dst.mask_x) ret += dst_mask[dst.dest_reg == 0][0];
|
||||||
|
if(dst.mask_y) ret += dst_mask[dst.dest_reg == 0][1];
|
||||||
|
if(dst.mask_z) ret += dst_mask[dst.dest_reg == 0][2];
|
||||||
|
if(dst.mask_w) ret += dst_mask[dst.dest_reg == 0][3];
|
||||||
|
|
||||||
|
return ret.IsEmpty() || strncmp(ret, dst_mask[dst.dest_reg == 0], 4) == 0 ? wxEmptyString : ("." + ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString FragmentDecompilerThread::AddReg(u32 index, int fp16)
|
wxString FragmentDecompilerThread::AddReg(u32 index, int fp16)
|
||||||
{
|
{
|
||||||
//if(!index) return "gl_FragColor";
|
//if(!index) return "gl_FragColor";
|
||||||
return m_parr.AddParam(index ? PARAM_NONE : PARAM_OUT, "vec4",
|
return m_parr.AddParam((index || fp16) ? PARAM_NONE : PARAM_OUT, "vec4",
|
||||||
wxString::Format((fp16 ? "h%d" : "r%d"), index), (index || fp16) ? -1 : 0);
|
wxString::Format((fp16 ? "h%d" : "r%d"), index), (index || fp16) ? -1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +118,8 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
|
|||||||
{
|
{
|
||||||
wxString ret = wxEmptyString;
|
wxString ret = wxEmptyString;
|
||||||
|
|
||||||
|
bool is_color = src.reg_type == 0 || (src.reg_type == 1 && dst.src_attr_reg_num >= 1 && dst.src_attr_reg_num <= 3);
|
||||||
|
|
||||||
switch(src.reg_type)
|
switch(src.reg_type)
|
||||||
{
|
{
|
||||||
case 0: //tmp
|
case 0: //tmp
|
||||||
@ -148,14 +165,17 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char f[4] = {'x', 'y', 'z', 'w'};
|
static const char f_pos[4] = {'x', 'y', 'z', 'w'};
|
||||||
|
static const char f_col[4] = {'r', 'g', 'b', 'a'};
|
||||||
|
const char *f = is_color ? f_col : f_pos;
|
||||||
|
|
||||||
wxString swizzle = wxEmptyString;
|
wxString swizzle = wxEmptyString;
|
||||||
swizzle += f[src.swizzle_x];
|
swizzle += f[src.swizzle_x];
|
||||||
swizzle += f[src.swizzle_y];
|
swizzle += f[src.swizzle_y];
|
||||||
swizzle += f[src.swizzle_z];
|
swizzle += f[src.swizzle_z];
|
||||||
swizzle += f[src.swizzle_w];
|
swizzle += f[src.swizzle_w];
|
||||||
|
|
||||||
if(swizzle != "xyzw") ret += "." + swizzle;
|
if(strncmp(swizzle, f, 4) != 0) ret += "." + swizzle;
|
||||||
|
|
||||||
if(src.abs) ret = "abs(" + ret + ")";
|
if(src.abs) ret = "abs(" + ret + ")";
|
||||||
if(src.neg) ret = "-" + ret;
|
if(src.neg) ret = "-" + ret;
|
||||||
@ -280,7 +300,7 @@ void FragmentDecompilerThread::Task()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShaderProgram::ShaderProgram()
|
ShaderProgram::ShaderProgram()
|
||||||
: m_decompiler_thread(NULL)
|
: m_decompiler_thread(nullptr)
|
||||||
, id(0)
|
, id(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ struct FragmentDecompilerThread : public ThreadBase
|
|||||||
u32 swizzle_z : 2;
|
u32 swizzle_z : 2;
|
||||||
u32 swizzle_w : 2;
|
u32 swizzle_w : 2;
|
||||||
u32 neg : 1;
|
u32 neg : 1;
|
||||||
u32 exec_if_le : 1;
|
u32 exec_if_lt : 1;
|
||||||
u32 exec_if_eq : 1;
|
u32 exec_if_eq : 1;
|
||||||
u32 exec_if_gr : 1;
|
u32 exec_if_gr : 1;
|
||||||
u32 cond_swizzle_x : 2;
|
u32 cond_swizzle_x : 2;
|
||||||
|
@ -36,6 +36,7 @@ void GLBufferObject::Delete()
|
|||||||
|
|
||||||
void GLBufferObject::Bind(u32 type, u32 num)
|
void GLBufferObject::Bind(u32 type, u32 num)
|
||||||
{
|
{
|
||||||
|
assert(num < m_id.GetCount());
|
||||||
glBindBuffer(type, m_id[num]);
|
glBindBuffer(type, m_id[num]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,10 +106,16 @@ void GLvao::Bind() const
|
|||||||
glBindVertexArray(m_id);
|
glBindVertexArray(m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLvao::Unbind()
|
||||||
|
{
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
void GLvao::Delete()
|
void GLvao::Delete()
|
||||||
{
|
{
|
||||||
if(!IsCreated()) return;
|
if(!IsCreated()) return;
|
||||||
|
|
||||||
|
Unbind();
|
||||||
glDeleteVertexArrays(1, &m_id);
|
glDeleteVertexArrays(1, &m_id);
|
||||||
m_id = 0;
|
m_id = 0;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
|
|
||||||
void Create();
|
void Create();
|
||||||
void Bind() const;
|
void Bind() const;
|
||||||
|
static void Unbind();
|
||||||
void Delete();
|
void Delete();
|
||||||
bool IsCreated() const;
|
bool IsCreated() const;
|
||||||
};
|
};
|
@ -1,8 +1,9 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "GLGSRender.h"
|
#include "GLGSRender.h"
|
||||||
#include "Emu/Cell/PPCInstrTable.h"
|
#include "Emu/Cell/PPCInstrTable.h"
|
||||||
|
|
||||||
#define CMD_DEBUG 0
|
#define CMD_DEBUG 0
|
||||||
#define DUMP_VERTEX_DATA 0
|
#define DUMP_VERTEX_DATA 1
|
||||||
|
|
||||||
#if CMD_DEBUG
|
#if CMD_DEBUG
|
||||||
#define CMD_LOG ConLog.Write
|
#define CMD_LOG ConLog.Write
|
||||||
@ -12,9 +13,8 @@
|
|||||||
|
|
||||||
gcmBuffer gcmBuffers[2];
|
gcmBuffer gcmBuffers[2];
|
||||||
|
|
||||||
void checkForGlError(const char* situation)
|
void printGlError(GLenum err, const char* situation)
|
||||||
{
|
{
|
||||||
GLenum err = glGetError();
|
|
||||||
if(err != GL_NO_ERROR)
|
if(err != GL_NO_ERROR)
|
||||||
{
|
{
|
||||||
ConLog.Error("%s: opengl error 0x%04x", situation, err);
|
ConLog.Error("%s: opengl error 0x%04x", situation, err);
|
||||||
@ -22,6 +22,11 @@ void checkForGlError(const char* situation)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkForGlError(const char* situation)
|
||||||
|
{
|
||||||
|
printGlError(glGetError(), situation);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define checkForGlError(x) /*x*/
|
#define checkForGlError(x) /*x*/
|
||||||
#endif
|
#endif
|
||||||
@ -168,7 +173,15 @@ void GLRSXThread::Task()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(draw) p.m_frame->Flip();
|
if(draw)
|
||||||
|
{
|
||||||
|
p.m_frame->Flip();
|
||||||
|
if(p.m_flip_handler)
|
||||||
|
{
|
||||||
|
p.m_flip_handler.Handle(1, 0, 0);
|
||||||
|
p.m_flip_handler.Branch(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p.m_flip_status = 0;
|
p.m_flip_status = 0;
|
||||||
if(SemaphorePostAndWait(p.m_sem_flip)) continue;
|
if(SemaphorePostAndWait(p.m_sem_flip)) continue;
|
||||||
@ -279,7 +292,7 @@ void GLGSRender::Close()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(m_frame->IsShown()) m_frame->Hide();
|
if(m_frame->IsShown()) m_frame->Hide();
|
||||||
m_ctrl = NULL;
|
m_ctrl = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGSRender::EnableVertexData(bool indexed_draw)
|
void GLGSRender::EnableVertexData(bool indexed_draw)
|
||||||
@ -425,6 +438,7 @@ void GLGSRender::DisableVertexData()
|
|||||||
m_vertex_data[i].data.Clear();
|
m_vertex_data[i].data.Clear();
|
||||||
glDisableVertexAttribArray(i);
|
glDisableVertexAttribArray(i);
|
||||||
}
|
}
|
||||||
|
m_vao.Unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGSRender::LoadVertexData(u32 first, u32 count)
|
void GLGSRender::LoadVertexData(u32 first, u32 count)
|
||||||
@ -509,7 +523,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
|
|||||||
index, offset, location, cubemap, dimension, format, mipmap);
|
index, offset, location, cubemap, dimension, format, mipmap);
|
||||||
|
|
||||||
u32 tex_addr = GetAddress(offset, location);
|
u32 tex_addr = GetAddress(offset, location);
|
||||||
ConLog.Warning("texture addr = 0x%x", tex_addr);
|
//ConLog.Warning("texture addr = 0x%x", tex_addr);
|
||||||
tex.SetOffset(tex_addr);
|
tex.SetOffset(tex_addr);
|
||||||
tex.SetFormat(cubemap, dimension, format, mipmap);
|
tex.SetFormat(cubemap, dimension, format, mipmap);
|
||||||
}
|
}
|
||||||
@ -1141,6 +1155,28 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
|
|||||||
case NV4097_SET_SCULL_CONTROL:
|
case NV4097_SET_SCULL_CONTROL:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NV4097_GET_REPORT:
|
||||||
|
{
|
||||||
|
u32 a0 = args[0];
|
||||||
|
u8 type = a0 >> 24;
|
||||||
|
u32 offset = a0 & 0xffffff;
|
||||||
|
|
||||||
|
u64 data;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
data = std::chrono::steady_clock::now().time_since_epoch().count();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ConLog.Error("NV4097_GET_REPORT: bad type %d", type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Memory.Write64(m_localAddress + offset, data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
wxString log = GetMethodName(cmd);
|
wxString log = GetMethodName(cmd);
|
||||||
@ -1293,8 +1329,9 @@ void GLGSRender::ExecCMD()
|
|||||||
GLTexture& tex = m_frame->GetTexture(i);
|
GLTexture& tex = m_frame->GetTexture(i);
|
||||||
if(!tex.IsEnabled()) continue;
|
if(!tex.IsEnabled()) continue;
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0_ARB + i);
|
glActiveTexture(GL_TEXTURE0 + i);
|
||||||
checkForGlError("glActiveTexture");
|
checkForGlError("glActiveTexture");
|
||||||
|
tex.Create();
|
||||||
tex.Bind();
|
tex.Bind();
|
||||||
checkForGlError("tex.Bind");
|
checkForGlError("tex.Bind");
|
||||||
m_program.SetTex(i);
|
m_program.SetTex(i);
|
||||||
@ -1342,6 +1379,7 @@ void GLGSRender::ExecCMD()
|
|||||||
EnableVertexData();
|
EnableVertexData();
|
||||||
InitVertexData();
|
InitVertexData();
|
||||||
m_vao.Bind();
|
m_vao.Bind();
|
||||||
|
|
||||||
glDrawArrays(m_draw_mode, 0, m_draw_array_count);
|
glDrawArrays(m_draw_mode, 0, m_draw_array_count);
|
||||||
checkForGlError("glDrawArrays");
|
checkForGlError("glDrawArrays");
|
||||||
DisableVertexData();
|
DisableVertexData();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#pragma comment(lib, "opengl32.lib")
|
#pragma comment(lib, "opengl32.lib")
|
||||||
#pragma comment(lib, "gl.lib")
|
#pragma comment(lib, "gl.lib")
|
||||||
|
|
||||||
|
void printGlError(GLenum err, const char* situation);
|
||||||
void checkForGlError(const char* situation);
|
void checkForGlError(const char* situation);
|
||||||
|
|
||||||
class GLTexture
|
class GLTexture
|
||||||
@ -40,6 +41,11 @@ public:
|
|||||||
|
|
||||||
void Create()
|
void Create()
|
||||||
{
|
{
|
||||||
|
if(m_id)
|
||||||
|
{
|
||||||
|
Delete();
|
||||||
|
}
|
||||||
|
|
||||||
if(!m_id)
|
if(!m_id)
|
||||||
{
|
{
|
||||||
glGenTextures(1, &m_id);
|
glGenTextures(1, &m_id);
|
||||||
@ -83,24 +89,27 @@ public:
|
|||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
Bind();
|
Bind();
|
||||||
ConLog.Warning("texture addr = 0x%x, width = %d, height = %d", m_offset, m_width, m_height);
|
//ConLog.Warning("texture addr = 0x%x, width = %d, height = %d", m_offset, m_width, m_height);
|
||||||
//TODO: safe init
|
//TODO: safe init
|
||||||
checkForGlError("GLTexture::Init() -> glBindTexture");
|
checkForGlError("GLTexture::Init() -> glBindTexture");
|
||||||
|
|
||||||
switch(m_format & ~(0x20 | 0x40))
|
switch(m_format & ~(0x20 | 0x40))
|
||||||
{
|
{
|
||||||
case 0x81:
|
case 0x81:
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RED, GL_UNSIGNED_BYTE, Memory.GetMemFromAddr(m_offset));
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BLUE, GL_UNSIGNED_BYTE, Memory.GetMemFromAddr(m_offset));
|
||||||
checkForGlError("GLTexture::Init() -> glTexImage2D");
|
checkForGlError("GLTexture::Init() -> glTexImage2D");
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_BLUE);
|
||||||
|
|
||||||
checkForGlError("GLTexture::Init() -> glTexParameteri");
|
checkForGlError("GLTexture::Init() -> glTexParameteri");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x85:
|
case 0x85:
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, Memory.GetMemFromAddr(m_offset));
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, Memory.GetMemFromAddr(m_offset));
|
||||||
checkForGlError("GLTexture::Init() -> glTexImage2D");
|
checkForGlError("GLTexture::Init() -> glTexImage2D");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -112,13 +121,31 @@ public:
|
|||||||
|
|
||||||
void Save(const wxString& name)
|
void Save(const wxString& name)
|
||||||
{
|
{
|
||||||
if(!m_id || !m_offset) return;
|
if(!m_id || !m_offset || !m_width || !m_height) return;
|
||||||
|
|
||||||
u32* alldata = new u32[m_width * m_height];
|
u32* alldata = new u32[m_width * m_height];
|
||||||
|
|
||||||
Bind();
|
Bind();
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata);
|
|
||||||
|
|
||||||
|
switch(m_format & ~(0x20 | 0x40))
|
||||||
|
{
|
||||||
|
case 0x81:
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x85:
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, alldata);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
delete[] alldata;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
wxFile f(name + ".raw", wxFile::write);
|
||||||
|
f.Write(alldata, m_width * m_height * 4);
|
||||||
|
}
|
||||||
u8* data = new u8[m_width * m_height * 3];
|
u8* data = new u8[m_width * m_height * 3];
|
||||||
u8* alpha = new u8[m_width * m_height];
|
u8* alpha = new u8[m_width * m_height];
|
||||||
|
|
||||||
@ -164,6 +191,14 @@ public:
|
|||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Delete()
|
||||||
|
{
|
||||||
|
if(m_id)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &m_id);
|
||||||
|
m_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
void Enable(bool enable) { m_enabled = enable; }
|
void Enable(bool enable) { m_enabled = enable; }
|
||||||
bool IsEnabled() const { return m_enabled; }
|
bool IsEnabled() const { return m_enabled; }
|
||||||
};
|
};
|
||||||
|
@ -40,6 +40,9 @@ OPENGL_PROC(PFNGLDEPTHRANGEFPROC, DepthRangef);
|
|||||||
OPENGL_PROC(PFNGLUNIFORM1IPROC, Uniform1i);
|
OPENGL_PROC(PFNGLUNIFORM1IPROC, Uniform1i);
|
||||||
OPENGL_PROC(PFNGLUNIFORM1FPROC, Uniform1f);
|
OPENGL_PROC(PFNGLUNIFORM1FPROC, Uniform1f);
|
||||||
OPENGL_PROC(PFNGLUNIFORM4FPROC, Uniform4f);
|
OPENGL_PROC(PFNGLUNIFORM4FPROC, Uniform4f);
|
||||||
|
OPENGL_PROC(PFNGLPROGRAMUNIFORM1IPROC, ProgramUniform1i);
|
||||||
|
OPENGL_PROC(PFNGLPROGRAMUNIFORM1FPROC, ProgramUniform1f);
|
||||||
|
OPENGL_PROC(PFNGLPROGRAMUNIFORM4FPROC, ProgramUniform4f);
|
||||||
OPENGL_PROC(PFNGLUNIFORMMATRIX4FVPROC, UniformMatrix4fv);
|
OPENGL_PROC(PFNGLUNIFORMMATRIX4FVPROC, UniformMatrix4fv);
|
||||||
OPENGL_PROC(PFNGLUSEPROGRAMPROC, UseProgram);
|
OPENGL_PROC(PFNGLUSEPROGRAMPROC, UseProgram);
|
||||||
OPENGL_PROC2(PFNWGLSWAPINTERVALEXTPROC, SwapInterval, wglSwapIntervalEXT);
|
OPENGL_PROC2(PFNWGLSWAPINTERVALEXTPROC, SwapInterval, wglSwapIntervalEXT);
|
||||||
|
@ -89,8 +89,12 @@ void Program::SetTex(u32 index)
|
|||||||
{
|
{
|
||||||
int loc = GetLocation(wxString::Format("tex%d", index));
|
int loc = GetLocation(wxString::Format("tex%d", index));
|
||||||
checkForGlError(wxString::Format("GetLocation(tex%d)", index));
|
checkForGlError(wxString::Format("GetLocation(tex%d)", index));
|
||||||
glUniform1i(loc, index);
|
glProgramUniform1i(id, loc, index);
|
||||||
checkForGlError(wxString::Format("SetTex(%d - %d)", index, loc));
|
GLenum err = glGetError();
|
||||||
|
if(err != 0x502)
|
||||||
|
{
|
||||||
|
printGlError(err, wxString::Format("SetTex(%d - %d - %d)", id, index, loc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Program::Delete()
|
void Program::Delete()
|
||||||
|
@ -181,7 +181,14 @@ void VertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
|
|||||||
cond = wxString::Format("if(tmp%d.x %s 0) ", d0.dst_tmp, cond);
|
cond = wxString::Format("if(tmp%d.x %s 0) ", d0.dst_tmp, cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
code = cond + GetDST(is_sca) + GetMask(is_sca) + " = " + (src_mask ? code + GetMask(is_sca) : code);
|
wxString value = src_mask ? code + GetMask(is_sca) : code;
|
||||||
|
|
||||||
|
if(d0.staturate)
|
||||||
|
{
|
||||||
|
value = "clamp(" + value + ", 0.0, 1.0)";
|
||||||
|
}
|
||||||
|
|
||||||
|
code = cond + GetDST(is_sca) + GetMask(is_sca) + " = " + value;
|
||||||
|
|
||||||
main += "\t" + code + ";\n";
|
main += "\t" + code + ";\n";
|
||||||
}
|
}
|
||||||
@ -209,7 +216,7 @@ wxString VertexDecompilerThread::BuildCode()
|
|||||||
"#version 330\n"
|
"#version 330\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%s\n"
|
"%s\n"
|
||||||
"void main()\n{\n%s}\n";
|
"void main()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n%s}\n";
|
||||||
|
|
||||||
return wxString::Format(prot, p, main);
|
return wxString::Format(prot, p, main);
|
||||||
}
|
}
|
||||||
@ -294,6 +301,7 @@ void VertexDecompilerThread::Task()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_shader = BuildCode();
|
m_shader = BuildCode();
|
||||||
|
|
||||||
main = wxEmptyString;
|
main = wxEmptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Emu/GS/GCM.h"
|
#include "Emu/GS/GCM.h"
|
||||||
|
#include "Emu/SysCalls/Callback.h"
|
||||||
|
|
||||||
enum Method
|
enum Method
|
||||||
{
|
{
|
||||||
@ -48,6 +49,7 @@ struct GSRender
|
|||||||
int m_flip_status;
|
int m_flip_status;
|
||||||
int m_flip_mode;
|
int m_flip_mode;
|
||||||
volatile bool m_draw;
|
volatile bool m_draw;
|
||||||
|
Callback m_flip_handler;
|
||||||
|
|
||||||
GSRender();
|
GSRender();
|
||||||
|
|
||||||
|
@ -13,6 +13,31 @@ Callback::Callback(u32 slot, u64 addr)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 Callback::GetSlot() const
|
||||||
|
{
|
||||||
|
return m_slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Callback::GetAddr() const
|
||||||
|
{
|
||||||
|
return m_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Callback::SetSlot(u32 slot)
|
||||||
|
{
|
||||||
|
m_slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Callback::SetAddr(u64 addr)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Callback::HasData() const
|
||||||
|
{
|
||||||
|
return m_has_data;
|
||||||
|
}
|
||||||
|
|
||||||
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3)
|
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3)
|
||||||
{
|
{
|
||||||
a1 = _a1;
|
a1 = _a1;
|
||||||
@ -21,13 +46,13 @@ void Callback::Handle(u64 _a1, u64 _a2, u64 _a3)
|
|||||||
m_has_data = true;
|
m_has_data = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Callback::Branch()
|
void Callback::Branch(bool wait)
|
||||||
{
|
{
|
||||||
m_has_data = false;
|
m_has_data = false;
|
||||||
|
|
||||||
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU);
|
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU);
|
||||||
|
|
||||||
new_thread.SetPc(m_addr);
|
new_thread.SetEntry(m_addr);
|
||||||
new_thread.SetPrio(1001);
|
new_thread.SetPrio(1001);
|
||||||
new_thread.stack_size = 0x10000;
|
new_thread.stack_size = 0x10000;
|
||||||
new_thread.SetName("Callback");
|
new_thread.SetName("Callback");
|
||||||
@ -40,7 +65,13 @@ void Callback::Branch()
|
|||||||
|
|
||||||
new_thread.Exec();
|
new_thread.Exec();
|
||||||
|
|
||||||
GetCurrentPPCThread()->Wait(new_thread);
|
if(wait)
|
||||||
|
GetCurrentPPCThread()->Wait(new_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
Callback::operator bool() const
|
||||||
|
{
|
||||||
|
return GetAddr() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Callback2::Callback2(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr)
|
Callback2::Callback2(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr)
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct Callback
|
class Callback
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
u64 m_addr;
|
u64 m_addr;
|
||||||
u32 m_slot;
|
u32 m_slot;
|
||||||
|
|
||||||
|
bool m_has_data;
|
||||||
|
|
||||||
|
public:
|
||||||
u64 a1;
|
u64 a1;
|
||||||
u64 a2;
|
u64 a2;
|
||||||
u64 a3;
|
u64 a3;
|
||||||
|
|
||||||
bool m_has_data;
|
u32 GetSlot() const;
|
||||||
|
u64 GetAddr() const;
|
||||||
|
void SetSlot(u32 slot);
|
||||||
|
void SetAddr(u64 addr);
|
||||||
|
bool HasData() const;
|
||||||
|
|
||||||
Callback(u32 slot, u64 addr);
|
Callback(u32 slot = 0, u64 addr = 0);
|
||||||
void Handle(u64 a1, u64 a2, u64 a3);
|
void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0);
|
||||||
void Branch();
|
void Branch(bool wait);
|
||||||
|
|
||||||
|
operator bool() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Callback2 : public Callback
|
struct Callback2 : public Callback
|
||||||
@ -46,7 +56,7 @@ struct Callbacks
|
|||||||
{
|
{
|
||||||
for(u32 i=0; i<m_callbacks.GetCount(); ++i)
|
for(u32 i=0; i<m_callbacks.GetCount(); ++i)
|
||||||
{
|
{
|
||||||
if(m_callbacks[i].m_slot == slot)
|
if(m_callbacks[i].GetSlot() == slot)
|
||||||
{
|
{
|
||||||
m_callbacks.RemoveAt(i);
|
m_callbacks.RemoveAt(i);
|
||||||
break;
|
break;
|
||||||
@ -62,10 +72,10 @@ struct Callbacks
|
|||||||
|
|
||||||
for(u32 i=0; i<m_callbacks.GetCount(); ++i)
|
for(u32 i=0; i<m_callbacks.GetCount(); ++i)
|
||||||
{
|
{
|
||||||
if(m_callbacks[i].m_has_data)
|
if(m_callbacks[i].HasData())
|
||||||
{
|
{
|
||||||
handled = true;
|
handled = true;
|
||||||
m_callbacks[i].Branch();
|
m_callbacks[i].Branch(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,8 @@ void cellGcmSys_init()
|
|||||||
cellGcmSys.AddFunc(0xd8f88e1a, cellGcmSetFlipCommandWithWaitLabel);
|
cellGcmSys.AddFunc(0xd8f88e1a, cellGcmSetFlipCommandWithWaitLabel);
|
||||||
cellGcmSys.AddFunc(0xe315a0b2, cellGcmGetConfiguration);
|
cellGcmSys.AddFunc(0xe315a0b2, cellGcmGetConfiguration);
|
||||||
cellGcmSys.AddFunc(0x9dc04436, cellGcmBindZcull);
|
cellGcmSys.AddFunc(0x9dc04436, cellGcmBindZcull);
|
||||||
|
cellGcmSys.AddFunc(0x5a41c10f, cellGcmGetTimeStamp);
|
||||||
cellGcmSys.AddFunc(0xd9b7653e, cellGcmUnbindTile);
|
cellGcmSys.AddFunc(0xd9b7653e, cellGcmUnbindTile);
|
||||||
cellGcmSys.AddFunc(0xa75640e8, cellGcmUnbindZcull);
|
cellGcmSys.AddFunc(0xa75640e8, cellGcmUnbindZcull);
|
||||||
|
cellGcmSys.AddFunc(0xa41ef7e8, cellGcmSetFlipHandler);
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,8 @@ extern int cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize);
|
|||||||
extern int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size);
|
extern int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size);
|
||||||
extern int cellGcmUnbindTile(u8 index);
|
extern int cellGcmUnbindTile(u8 index);
|
||||||
extern int cellGcmUnbindZcull(u8 index);
|
extern int cellGcmUnbindZcull(u8 index);
|
||||||
|
extern u64 cellGcmGetTimeStamp(u32 index);
|
||||||
|
extern int cellGcmSetFlipHandler(u32 handler_addr);
|
||||||
|
|
||||||
//sys_tty
|
//sys_tty
|
||||||
extern int sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr);
|
extern int sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr);
|
||||||
|
@ -258,4 +258,22 @@ int cellGcmUnbindZcull(u8 index)
|
|||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cellGcmGetTimeStamp(u32 index)
|
||||||
|
{
|
||||||
|
cellGcmSys.Log("cellGcmGetTimeStamp(index=%d)", index);
|
||||||
|
return Memory.Read64(Memory.RSXFBMem.GetStartAddr() + index * 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cellGcmSetFlipHandler(u32 handler_addr)
|
||||||
|
{
|
||||||
|
cellGcmSys.Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler_addr);
|
||||||
|
if(!Memory.IsGoodAddr(handler_addr) && handler_addr != 0)
|
||||||
|
{
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr);
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -12,7 +12,15 @@ enum
|
|||||||
|
|
||||||
int sys_ppu_thread_exit(int errorcode)
|
int sys_ppu_thread_exit(int errorcode)
|
||||||
{
|
{
|
||||||
sysPrxForUser.Log("sys_ppu_thread_exit(errorcode=%d)", errorcode);
|
if(errorcode == 0)
|
||||||
|
{
|
||||||
|
sysPrxForUser.Log("sys_ppu_thread_exit(errorcode=%d)", errorcode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sysPrxForUser.Warning("sys_ppu_thread_exit(errorcode=%d)", errorcode);
|
||||||
|
}
|
||||||
|
|
||||||
Emu.GetCPU().RemoveThread(GetCurrentPPUThread().GetId());
|
Emu.GetCPU().RemoveThread(GetCurrentPPUThread().GetId());
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
@ -70,7 +70,7 @@ int cellMsgDialogOpen2(u32 type, u32 msgString_addr, u32 callback_addr, u32 user
|
|||||||
|
|
||||||
Callback2 callback(0, callback_addr, userData);
|
Callback2 callback(0, callback_addr, userData);
|
||||||
callback.Handle(status);
|
callback.Handle(status);
|
||||||
callback.Branch();
|
callback.Branch(true);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user