1
0
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:
DH 2013-08-17 01:22:26 +03:00
parent f42d4b6572
commit 0aff049960
21 changed files with 410 additions and 106 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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