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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -43,6 +43,7 @@ public:
void Create();
void Bind() const;
static void Unbind();
void Delete();
bool IsCreated() const;
};

View File

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

View File

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

View File

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

View File

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

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

View File

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

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

View File

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

View File

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

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

View File

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

View File

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

View File

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