mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-16 23:17:29 +00: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)
|
||||
{
|
||||
if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX);
|
||||
CPU.FPR[frd] = static_cast<float>(1.0f/CPU.FPR[frb]);
|
||||
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
|
||||
CPU.FPSCR.FI = 0;
|
||||
CPU.FPSCR.FR = 0;
|
||||
double res;
|
||||
|
||||
if(_fpclass(CPU.FPR[frb]) >= _FPCLASS_NZ)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
void FMULS(u32 frd, u32 fra, u32 frc, bool rc)
|
||||
@ -3339,7 +3386,9 @@ private:
|
||||
}
|
||||
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]))
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
@ -3467,20 +3517,44 @@ private:
|
||||
}
|
||||
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();
|
||||
if(rc) UNK("fdiv.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
||||
}
|
||||
@ -3509,15 +3583,31 @@ private:
|
||||
}
|
||||
void FMUL(u32 frd, u32 fra, u32 frc, bool rc)
|
||||
{
|
||||
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc];
|
||||
CPU.FPSCR.FI = 0;
|
||||
CPU.FPSCR.FR = 0;
|
||||
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
|
||||
if((FPRdouble::IsINF(CPU.FPR[fra]) && CPU.FPR[frc] == 0.0) || (FPRdouble::IsINF(CPU.FPR[frc]) && CPU.FPR[fra] == 0.0))
|
||||
{
|
||||
CPU.SetFPSCRException(FPSCR_VXIMZ);
|
||||
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]);
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -3545,14 +3635,16 @@ private:
|
||||
}
|
||||
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]))
|
||||
{
|
||||
CPU.SetFPSCRException(FPSCR_VXSNAN);
|
||||
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);
|
||||
}
|
||||
@ -3560,11 +3652,12 @@ private:
|
||||
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)
|
||||
{
|
||||
CPU.FPR[frd] = ((u64&)CPU.FPR[frb]) ^ (1ULL << 63);
|
||||
CPU.FPR[frd] = -CPU.FPR[frb];
|
||||
if(rc) UNK("fneg.");//CPU.UpdateCR1(CPU.FPR[frd]);
|
||||
}
|
||||
void FMR(u32 frd, u32 frb, bool rc)
|
||||
@ -3574,7 +3667,7 @@ private:
|
||||
}
|
||||
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]);
|
||||
}
|
||||
void FABS(u32 frd, u32 frb, bool rc)
|
||||
@ -3685,7 +3778,24 @@ private:
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ void PPUThread::DoCode(const s32 code)
|
||||
|
||||
bool FPRdouble::IsINF(PPCdouble d)
|
||||
{
|
||||
return d.GetType() == FPR_INF;
|
||||
return ((u64&)d & 0x7FFFFFFFFFFFFFFFULL) == 0x7FF0000000000000ULL;
|
||||
}
|
||||
|
||||
bool FPRdouble::IsNaN(PPCdouble d)
|
||||
@ -224,12 +224,18 @@ bool FPRdouble::IsNaN(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)
|
||||
{
|
||||
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)
|
||||
|
@ -298,11 +298,11 @@ union VSCRhdr
|
||||
|
||||
enum FPRType
|
||||
{
|
||||
FPR_NORM,
|
||||
FPR_ZERO,
|
||||
FPR_SNAN,
|
||||
//FPR_NORM,
|
||||
//FPR_ZERO,
|
||||
//FPR_SNAN,
|
||||
//FPR_QNAN,
|
||||
FPR_INF,
|
||||
//FPR_INF,
|
||||
FPR_PZ = 0x2,
|
||||
FPR_PN = 0x4,
|
||||
FPR_PINF = 0x5,
|
||||
@ -357,7 +357,7 @@ struct PPCdouble
|
||||
|
||||
switch(fpc)
|
||||
{
|
||||
case _FPCLASS_SNAN: return FPR_SNAN;
|
||||
case _FPCLASS_SNAN:// return FPR_SNAN;
|
||||
case _FPCLASS_QNAN: return FPR_QNAN;
|
||||
case _FPCLASS_NINF: return FPR_NINF;
|
||||
case _FPCLASS_NN: return FPR_NN;
|
||||
|
@ -136,7 +136,7 @@ void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
|
||||
IniEntry<int> entries_count;
|
||||
entries_count.Init("count", "VFSManager");
|
||||
|
||||
int count;
|
||||
int count = 0;
|
||||
if(is_load)
|
||||
{
|
||||
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;
|
||||
|
||||
wxString cond;
|
||||
wxString cond = wxEmptyString;
|
||||
|
||||
if(src0.exec_if_gr)
|
||||
if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq)
|
||||
{
|
||||
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)
|
||||
if(src0.exec_if_gr)
|
||||
{
|
||||
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);
|
||||
Emu.Pause();
|
||||
@ -43,12 +46,12 @@ void FragmentDecompilerThread::AddCode(wxString code)
|
||||
{
|
||||
switch(src1.scale)
|
||||
{
|
||||
case 1: code = "(" + code + ") * 2"; break;
|
||||
case 2: code = "(" + code + ") * 4"; break;
|
||||
case 3: code = "(" + code + ") * 8"; break;
|
||||
case 5: code = "(" + code + ") / 2"; break;
|
||||
case 6: code = "(" + code + ") / 4"; break;
|
||||
case 7: code = "(" + code + ") / 8"; break;
|
||||
case 1: code = "(" + code + " * 2)"; break;
|
||||
case 2: code = "(" + code + " * 4)"; break;
|
||||
case 3: code = "(" + code + " * 8)"; break;
|
||||
case 5: code = "(" + code + " / 2)"; break;
|
||||
case 6: code = "(" + code + " / 4)"; break;
|
||||
case 7: code = "(" + code + " / 8)"; break;
|
||||
|
||||
default:
|
||||
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();
|
||||
|
||||
main += "\t" + code + ";\n";
|
||||
@ -66,18 +75,24 @@ wxString FragmentDecompilerThread::GetMask()
|
||||
{
|
||||
wxString ret = wxEmptyString;
|
||||
|
||||
if(dst.mask_x) ret += 'x';
|
||||
if(dst.mask_y) ret += 'y';
|
||||
if(dst.mask_z) ret += 'z';
|
||||
if(dst.mask_w) ret += 'w';
|
||||
static const char dst_mask[2][4] =
|
||||
{
|
||||
{'x', 'y', 'z', '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)
|
||||
{
|
||||
//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);
|
||||
}
|
||||
|
||||
@ -103,6 +118,8 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
|
||||
{
|
||||
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)
|
||||
{
|
||||
case 0: //tmp
|
||||
@ -148,14 +165,17 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
|
||||
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;
|
||||
swizzle += f[src.swizzle_x];
|
||||
swizzle += f[src.swizzle_y];
|
||||
swizzle += f[src.swizzle_z];
|
||||
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.neg) ret = "-" + ret;
|
||||
@ -280,7 +300,7 @@ void FragmentDecompilerThread::Task()
|
||||
}
|
||||
|
||||
ShaderProgram::ShaderProgram()
|
||||
: m_decompiler_thread(NULL)
|
||||
: m_decompiler_thread(nullptr)
|
||||
, id(0)
|
||||
{
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ struct FragmentDecompilerThread : public ThreadBase
|
||||
u32 swizzle_z : 2;
|
||||
u32 swizzle_w : 2;
|
||||
u32 neg : 1;
|
||||
u32 exec_if_le : 1;
|
||||
u32 exec_if_lt : 1;
|
||||
u32 exec_if_eq : 1;
|
||||
u32 exec_if_gr : 1;
|
||||
u32 cond_swizzle_x : 2;
|
||||
|
@ -36,6 +36,7 @@ void GLBufferObject::Delete()
|
||||
|
||||
void GLBufferObject::Bind(u32 type, u32 num)
|
||||
{
|
||||
assert(num < m_id.GetCount());
|
||||
glBindBuffer(type, m_id[num]);
|
||||
}
|
||||
|
||||
@ -105,10 +106,16 @@ void GLvao::Bind() const
|
||||
glBindVertexArray(m_id);
|
||||
}
|
||||
|
||||
void GLvao::Unbind()
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void GLvao::Delete()
|
||||
{
|
||||
if(!IsCreated()) return;
|
||||
|
||||
Unbind();
|
||||
glDeleteVertexArrays(1, &m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
|
||||
void Create();
|
||||
void Bind() const;
|
||||
static void Unbind();
|
||||
void Delete();
|
||||
bool IsCreated() const;
|
||||
};
|
@ -1,8 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "GLGSRender.h"
|
||||
#include "Emu/Cell/PPCInstrTable.h"
|
||||
|
||||
#define CMD_DEBUG 0
|
||||
#define DUMP_VERTEX_DATA 0
|
||||
#define DUMP_VERTEX_DATA 1
|
||||
|
||||
#if CMD_DEBUG
|
||||
#define CMD_LOG ConLog.Write
|
||||
@ -12,9 +13,8 @@
|
||||
|
||||
gcmBuffer gcmBuffers[2];
|
||||
|
||||
void checkForGlError(const char* situation)
|
||||
void printGlError(GLenum err, const char* situation)
|
||||
{
|
||||
GLenum err = glGetError();
|
||||
if(err != GL_NO_ERROR)
|
||||
{
|
||||
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
|
||||
#define checkForGlError(x) /*x*/
|
||||
#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;
|
||||
if(SemaphorePostAndWait(p.m_sem_flip)) continue;
|
||||
@ -279,7 +292,7 @@ void GLGSRender::Close()
|
||||
}
|
||||
|
||||
if(m_frame->IsShown()) m_frame->Hide();
|
||||
m_ctrl = NULL;
|
||||
m_ctrl = nullptr;
|
||||
}
|
||||
|
||||
void GLGSRender::EnableVertexData(bool indexed_draw)
|
||||
@ -425,6 +438,7 @@ void GLGSRender::DisableVertexData()
|
||||
m_vertex_data[i].data.Clear();
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
m_vao.Unbind();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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.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:
|
||||
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:
|
||||
{
|
||||
wxString log = GetMethodName(cmd);
|
||||
@ -1293,8 +1329,9 @@ void GLGSRender::ExecCMD()
|
||||
GLTexture& tex = m_frame->GetTexture(i);
|
||||
if(!tex.IsEnabled()) continue;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0_ARB + i);
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
checkForGlError("glActiveTexture");
|
||||
tex.Create();
|
||||
tex.Bind();
|
||||
checkForGlError("tex.Bind");
|
||||
m_program.SetTex(i);
|
||||
@ -1342,6 +1379,7 @@ void GLGSRender::ExecCMD()
|
||||
EnableVertexData();
|
||||
InitVertexData();
|
||||
m_vao.Bind();
|
||||
|
||||
glDrawArrays(m_draw_mode, 0, m_draw_array_count);
|
||||
checkForGlError("glDrawArrays");
|
||||
DisableVertexData();
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma comment(lib, "opengl32.lib")
|
||||
#pragma comment(lib, "gl.lib")
|
||||
|
||||
void printGlError(GLenum err, const char* situation);
|
||||
void checkForGlError(const char* situation);
|
||||
|
||||
class GLTexture
|
||||
@ -40,6 +41,11 @@ public:
|
||||
|
||||
void Create()
|
||||
{
|
||||
if(m_id)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
if(!m_id)
|
||||
{
|
||||
glGenTextures(1, &m_id);
|
||||
@ -83,24 +89,27 @@ public:
|
||||
void Init()
|
||||
{
|
||||
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
|
||||
checkForGlError("GLTexture::Init() -> glBindTexture");
|
||||
|
||||
switch(m_format & ~(0x20 | 0x40))
|
||||
{
|
||||
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");
|
||||
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_B, GL_RED);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_BLUE);
|
||||
|
||||
checkForGlError("GLTexture::Init() -> glTexParameteri");
|
||||
break;
|
||||
|
||||
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");
|
||||
break;
|
||||
|
||||
@ -112,13 +121,31 @@ public:
|
||||
|
||||
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];
|
||||
|
||||
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* alpha = new u8[m_width * m_height];
|
||||
|
||||
@ -164,6 +191,14 @@ public:
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void Delete()
|
||||
{
|
||||
if(m_id)
|
||||
{
|
||||
glDeleteTextures(1, &m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
}
|
||||
void Enable(bool enable) { m_enabled = enable; }
|
||||
bool IsEnabled() const { return m_enabled; }
|
||||
};
|
||||
|
@ -40,6 +40,9 @@ OPENGL_PROC(PFNGLDEPTHRANGEFPROC, DepthRangef);
|
||||
OPENGL_PROC(PFNGLUNIFORM1IPROC, Uniform1i);
|
||||
OPENGL_PROC(PFNGLUNIFORM1FPROC, Uniform1f);
|
||||
OPENGL_PROC(PFNGLUNIFORM4FPROC, Uniform4f);
|
||||
OPENGL_PROC(PFNGLPROGRAMUNIFORM1IPROC, ProgramUniform1i);
|
||||
OPENGL_PROC(PFNGLPROGRAMUNIFORM1FPROC, ProgramUniform1f);
|
||||
OPENGL_PROC(PFNGLPROGRAMUNIFORM4FPROC, ProgramUniform4f);
|
||||
OPENGL_PROC(PFNGLUNIFORMMATRIX4FVPROC, UniformMatrix4fv);
|
||||
OPENGL_PROC(PFNGLUSEPROGRAMPROC, UseProgram);
|
||||
OPENGL_PROC2(PFNWGLSWAPINTERVALEXTPROC, SwapInterval, wglSwapIntervalEXT);
|
||||
|
@ -89,8 +89,12 @@ void Program::SetTex(u32 index)
|
||||
{
|
||||
int loc = GetLocation(wxString::Format("tex%d", index));
|
||||
checkForGlError(wxString::Format("GetLocation(tex%d)", index));
|
||||
glUniform1i(loc, index);
|
||||
checkForGlError(wxString::Format("SetTex(%d - %d)", index, loc));
|
||||
glProgramUniform1i(id, loc, index);
|
||||
GLenum err = glGetError();
|
||||
if(err != 0x502)
|
||||
{
|
||||
printGlError(err, wxString::Format("SetTex(%d - %d - %d)", id, index, loc));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
@ -209,7 +216,7 @@ wxString VertexDecompilerThread::BuildCode()
|
||||
"#version 330\n"
|
||||
"\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);
|
||||
}
|
||||
@ -294,6 +301,7 @@ void VertexDecompilerThread::Task()
|
||||
}
|
||||
|
||||
m_shader = BuildCode();
|
||||
|
||||
main = wxEmptyString;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "Emu/GS/GCM.h"
|
||||
#include "Emu/SysCalls/Callback.h"
|
||||
|
||||
enum Method
|
||||
{
|
||||
@ -48,6 +49,7 @@ struct GSRender
|
||||
int m_flip_status;
|
||||
int m_flip_mode;
|
||||
volatile bool m_draw;
|
||||
Callback m_flip_handler;
|
||||
|
||||
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)
|
||||
{
|
||||
a1 = _a1;
|
||||
@ -21,13 +46,13 @@ void Callback::Handle(u64 _a1, u64 _a2, u64 _a3)
|
||||
m_has_data = true;
|
||||
}
|
||||
|
||||
void Callback::Branch()
|
||||
void Callback::Branch(bool wait)
|
||||
{
|
||||
m_has_data = false;
|
||||
|
||||
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.stack_size = 0x10000;
|
||||
new_thread.SetName("Callback");
|
||||
@ -40,7 +65,13 @@ void Callback::Branch()
|
||||
|
||||
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)
|
||||
|
@ -1,19 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
struct Callback
|
||||
class Callback
|
||||
{
|
||||
protected:
|
||||
u64 m_addr;
|
||||
u32 m_slot;
|
||||
|
||||
bool m_has_data;
|
||||
|
||||
public:
|
||||
u64 a1;
|
||||
u64 a2;
|
||||
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);
|
||||
void Handle(u64 a1, u64 a2, u64 a3);
|
||||
void Branch();
|
||||
Callback(u32 slot = 0, u64 addr = 0);
|
||||
void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0);
|
||||
void Branch(bool wait);
|
||||
|
||||
operator bool() const;
|
||||
};
|
||||
|
||||
struct Callback2 : public Callback
|
||||
@ -46,7 +56,7 @@ struct Callbacks
|
||||
{
|
||||
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);
|
||||
break;
|
||||
@ -62,10 +72,10 @@ struct Callbacks
|
||||
|
||||
for(u32 i=0; i<m_callbacks.GetCount(); ++i)
|
||||
{
|
||||
if(m_callbacks[i].m_has_data)
|
||||
if(m_callbacks[i].HasData())
|
||||
{
|
||||
handled = true;
|
||||
m_callbacks[i].Branch();
|
||||
m_callbacks[i].Branch(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,8 @@ void cellGcmSys_init()
|
||||
cellGcmSys.AddFunc(0xd8f88e1a, cellGcmSetFlipCommandWithWaitLabel);
|
||||
cellGcmSys.AddFunc(0xe315a0b2, cellGcmGetConfiguration);
|
||||
cellGcmSys.AddFunc(0x9dc04436, cellGcmBindZcull);
|
||||
|
||||
cellGcmSys.AddFunc(0x5a41c10f, cellGcmGetTimeStamp);
|
||||
cellGcmSys.AddFunc(0xd9b7653e, cellGcmUnbindTile);
|
||||
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 cellGcmUnbindTile(u8 index);
|
||||
extern int cellGcmUnbindZcull(u8 index);
|
||||
extern u64 cellGcmGetTimeStamp(u32 index);
|
||||
extern int cellGcmSetFlipHandler(u32 handler_addr);
|
||||
|
||||
//sys_tty
|
||||
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_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)
|
||||
{
|
||||
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());
|
||||
|
||||
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);
|
||||
callback.Handle(status);
|
||||
callback.Branch();
|
||||
callback.Branch(true);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
Loading…
Reference in New Issue
Block a user