From 3fc471eb322c0902f2559383e99f4c4753763437 Mon Sep 17 00:00:00 2001 From: raven02 Date: Wed, 17 Dec 2014 22:01:59 +0800 Subject: [PATCH 01/36] RSX: shaders fix and vertex texture implementation --- Utilities/StrFmt.cpp | 9 +- rpcs3/Emu/FS/VFS.cpp | 15 +- rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp | 517 +++++++++++++--------- rpcs3/Emu/RSX/GL/GLFragmentProgram.h | 1 + rpcs3/Emu/RSX/GL/GLGSRender.cpp | 51 ++- rpcs3/Emu/RSX/GL/GLGSRender.h | 1 + rpcs3/Emu/RSX/GL/GLProgram.cpp | 7 + rpcs3/Emu/RSX/GL/GLProgram.h | 1 + rpcs3/Emu/RSX/GL/GLShaderParam.h | 108 ++++- rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 216 ++++++--- rpcs3/Emu/RSX/GL/GLVertexProgram.h | 3 + rpcs3/Emu/RSX/RSXTexture.cpp | 203 +++++++++ rpcs3/Emu/RSX/RSXTexture.h | 63 ++- rpcs3/Emu/RSX/RSXThread.cpp | 52 ++- rpcs3/Emu/RSX/RSXThread.h | 1 + rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/sceNp.cpp | 11 +- rpcs3/Gui/MainFrame.cpp | 4 + rpcs3/Ini.h | 4 + rpcs3/rpcs3.cpp | 164 ++++++- 20 files changed, 1101 insertions(+), 334 deletions(-) diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 991f63ec35..8fbdeda31c 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -137,14 +137,17 @@ std::vector fmt::split(const std::string& source, std::initializer_ std::string fmt::merge(std::vector source, const std::string& separator) { + if (!source.size()) + return ""; + std::string result; - for (auto &s : source) + for (int i = 0; i < source.size() - 1; ++i) { - result += s + separator; + result += source[i] + separator; } - return result; + return result + source[source.size() - 1]; } std::string fmt::merge(std::initializer_list> sources, const std::string& separator) diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index d963d9c91f..01489759a6 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -32,21 +32,12 @@ std::string simplify_path(const std::string& path, bool is_dir) { std::vector path_blocks = simplify_path_blocks(path); - std::string result; - if (path_blocks.empty()) - return result; + return ""; - if (is_dir) - { - result = fmt::merge(path_blocks, "/"); - } - else - { - result = fmt::merge(std::vector(path_blocks.begin(), path_blocks.end() - 1), "/") + path_blocks[path_blocks.size() - 1]; - } + std::string result = fmt::merge(path_blocks, "/"); - return result; + return is_dir ? result + "/" : result; } VFS::~VFS() diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index f72d5f9350..e62608832d 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -6,9 +6,9 @@ void GLFragmentDecompilerThread::SetDst(std::string code, bool append_mask) { - 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; - switch(src1.scale) + switch (src1.scale) { case 0: break; case 1: code = "(" + code + " * 2.0)"; break; @@ -21,27 +21,39 @@ void GLFragmentDecompilerThread::SetDst(std::string code, bool append_mask) default: LOG_ERROR(RSX, "Bad scale: %d", fmt::by_value(src1.scale)); Emu.Pause(); - break; + break; } - if(dst.saturate) + if (dst.saturate) { code = "clamp(" + code + ", 0.0, 1.0)"; } - std::string dest; + code += (append_mask ? "$m" : ""); + + if (dst.no_dest) + { + if (dst.set_cond) + { + AddCode("$ifcond " + m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(src0.cond_mod_reg_index)) + "$m = " + code + ";"); + } + else + { + AddCode("$ifcond " + code + ";"); + } + + return; + } + + std::string dest = AddReg(dst.dest_reg, dst.fp16) + "$m"; + + AddCodeCond(dest, code); + //AddCode("$ifcond " + dest + code + (append_mask ? "$m;" : ";")); if (dst.set_cond) { - dest += m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(src0.cond_mod_reg_index)) + "$m = "; + AddCode(m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(src0.cond_mod_reg_index)) + "$m = " + dest + ";"); } - - if (!dst.no_dest) - { - dest += AddReg(dst.dest_reg, dst.fp16) + "$m = "; - } - - AddCode("$ifcond " + dest + code + (append_mask ? "$m;" : ";")); } void GLFragmentDecompilerThread::AddCode(const std::string& code) @@ -58,17 +70,17 @@ std::string GLFragmentDecompilerThread::GetMask() 'x', 'y', 'z', 'w', }; - if(dst.mask_x) ret += dst_mask[0]; - if(dst.mask_y) ret += dst_mask[1]; - if(dst.mask_z) ret += dst_mask[2]; - if(dst.mask_w) ret += dst_mask[3]; + if (dst.mask_x) ret += dst_mask[0]; + if (dst.mask_y) ret += dst_mask[1]; + if (dst.mask_z) ret += dst_mask[2]; + if (dst.mask_w) ret += dst_mask[3]; return ret.empty() || strncmp(ret.c_str(), dst_mask, 4) == 0 ? "" : ("." + ret); } std::string GLFragmentDecompilerThread::AddReg(u32 index, int fp16) { - return m_parr.AddParam(PARAM_NONE, "vec4", std::string(fp16 ? "h" : "r") + std::to_string(index), "vec4(0.0, 0.0, 0.0, 0.0)"); + return m_parr.AddParam(PARAM_NONE, "vec4", std::string(fp16 ? "h" : "r") + std::to_string(index), "vec4(0.0)"); } bool GLFragmentDecompilerThread::HasReg(u32 index, int fp16) @@ -79,13 +91,13 @@ bool GLFragmentDecompilerThread::HasReg(u32 index, int fp16) std::string GLFragmentDecompilerThread::AddCond() { - return m_parr.AddParam(PARAM_NONE , "vec4", "cc" + std::to_string(src0.cond_reg_index)); + return m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(src0.cond_reg_index)); } std::string GLFragmentDecompilerThread::AddConst() { std::string name = std::string("fc") + std::to_string(m_size + 4 * 4); - if(m_parr.HasParam(PARAM_UNIFORM, "vec4", name)) + if (m_parr.HasParam(PARAM_UNIFORM, "vec4", name)) { return name; } @@ -118,11 +130,11 @@ std::string GLFragmentDecompilerThread::Format(const std::string& code) { "$t", std::bind(std::mem_fn(&GLFragmentDecompilerThread::AddTex), this) }, { "$m", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetMask), this) }, { "$ifcond ", [this]() -> std::string - { - const std::string& cond = GetCond(); - if (cond == "true") return ""; - return "if(" + cond + ") "; - } + { + const std::string& cond = GetCond(); + if (cond == "true") return ""; + return "if(" + cond + ") "; + } }, { "$cond", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetCond), this) }, { "$c", std::bind(std::mem_fn(&GLFragmentDecompilerThread::AddConst), this) } @@ -179,15 +191,83 @@ std::string GLFragmentDecompilerThread::GetCond() return "any(" + cond + "(" + AddCond() + swizzle + ", vec4(0.0)))"; } +void GLFragmentDecompilerThread::AddCodeCond(const std::string& dst, const std::string& src) +{ + if (src0.exec_if_gr && src0.exec_if_lt && src0.exec_if_eq) + { + AddCode(dst + " = " + src + ";"); + return; + } + + if (!src0.exec_if_gr && !src0.exec_if_lt && !src0.exec_if_eq) + { + AddCode("//" + dst + " = " + src + ";"); + return; + } + + static const char f[4] = { 'x', 'y', 'z', 'w' }; + + std::string swizzle, cond; + swizzle += f[src0.cond_swizzle_x]; + swizzle += f[src0.cond_swizzle_y]; + swizzle += f[src0.cond_swizzle_z]; + swizzle += f[src0.cond_swizzle_w]; + swizzle = swizzle == "xyzw" ? "" : "." + swizzle; + + if (src0.exec_if_gr && src0.exec_if_eq) + { + cond = "greaterThanEqual"; + } + else if (src0.exec_if_lt && src0.exec_if_eq) + { + cond = "lessThanEqual"; + } + else if (src0.exec_if_gr && src0.exec_if_lt) + { + cond = "notEqual"; + } + else if (src0.exec_if_gr) + { + cond = "greaterThan"; + } + else if (src0.exec_if_lt) + { + cond = "lessThan"; + } + else //if(src0.exec_if_eq) + { + cond = "equal"; + } + + cond = cond + "(" + AddCond() + swizzle + ", vec4(0.0))"; + + ShaderVar dst_var(dst); + dst_var.symplify(); + + //const char *c_mask = f; + + if (dst_var.swizzles[0].length() == 1) + { + AddCode("if (" + cond + ".x) " + dst + " = vec4(" + src + ").x;"); + } + else + { + for (int i = 0; i < dst_var.swizzles[0].length(); ++i) + { + AddCode("if (" + cond + "." + f[i] + ") " + dst + "." + f[i] + " = " + src + "." + f[i] + ";"); + } + } +} + template std::string GLFragmentDecompilerThread::GetSRC(T src) { std::string ret; - switch(src.reg_type) + switch (src.reg_type) { case 0: //tmp ret += AddReg(src.tmp_reg_index, src.fp16); - break; + break; case 1: //input { @@ -200,11 +280,11 @@ template std::string GLFragmentDecompilerThread::GetSRC(T src) "ssa" }; - switch(dst.src_attr_reg_num) + switch (dst.src_attr_reg_num) { case 0x00: ret += reg_table[0]; break; default: - if(dst.src_attr_reg_num < sizeof(reg_table)/sizeof(reg_table[0])) + if (dst.src_attr_reg_num < sizeof(reg_table) / sizeof(reg_table[0])) { ret += m_parr.AddParam(PARAM_IN, "vec4", reg_table[dst.src_attr_reg_num]); } @@ -214,22 +294,22 @@ template std::string GLFragmentDecompilerThread::GetSRC(T src) ret += m_parr.AddParam(PARAM_IN, "vec4", "unk"); Emu.Pause(); } - break; + break; } } break; case 2: //const ret += AddConst(); - break; + break; default: LOG_ERROR(RSX, "Bad src type %d", fmt::by_value(src.reg_type)); Emu.Pause(); - break; + break; } - static const char f[4] = {'x', 'y', 'z', 'w'}; + static const char f[4] = { 'x', 'y', 'z', 'w' }; std::string swizzle = ""; swizzle += f[src.swizzle_x]; @@ -237,10 +317,10 @@ template std::string GLFragmentDecompilerThread::GetSRC(T src) swizzle += f[src.swizzle_z]; swizzle += f[src.swizzle_w]; - if(strncmp(swizzle.c_str(), f, 4) != 0) ret += "." + swizzle; + if (strncmp(swizzle.c_str(), f, 4) != 0) ret += "." + swizzle; - if(src.abs) ret = "abs(" + ret + ")"; - if(src.neg) ret = "-" + ret; + if (src.abs) ret = "abs(" + ret + ")"; + if (src.neg) ret = "-" + ret; return ret; } @@ -251,10 +331,9 @@ std::string GLFragmentDecompilerThread::BuildCode() const std::pair table[] = { { "ocol0", m_ctrl & 0x40 ? "r0" : "h0" }, - { "ocol1", m_ctrl & 0x40 ? "r2" : "h2" }, - { "ocol2", m_ctrl & 0x40 ? "r3" : "h4" }, - { "ocol3", m_ctrl & 0x40 ? "r4" : "h6" }, - { "ocol4", m_ctrl & 0x40 ? "r5" : "h8" }, + { "ocol1", m_ctrl & 0x40 ? "r2" : "h4" }, + { "ocol2", m_ctrl & 0x40 ? "r3" : "h6" }, + { "ocol3", m_ctrl & 0x40 ? "r4" : "h8" }, }; for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) @@ -263,7 +342,7 @@ std::string GLFragmentDecompilerThread::BuildCode() AddCode(m_parr.AddParam(PARAM_OUT, "vec4", table[i].first, i) + " = " + table[i].second + ";"); } - if (m_ctrl & 0xe) main += "\tgl_FragDepth = r1.z;\n"; + if (m_ctrl & 0xe) main += m_ctrl & 0x40 ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h2.z;\n"; std::string p; @@ -285,7 +364,16 @@ void GLFragmentDecompilerThread::Task() m_loop_count = 0; m_code_level = 1; - while(true) + enum + { + FORCE_NONE, + FORCE_SCT, + FORCE_SCB, + }; + + int forced_unit = FORCE_NONE; + + while (true) { for (auto finded = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size); finded != m_end_offsets.end(); @@ -318,164 +406,195 @@ void GLFragmentDecompilerThread::Task() const u32 opcode = dst.opcode | (src1.opcode_is_branch << 6); - switch(opcode) + auto SCT = [&]() + { + switch (opcode) + { + case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); break; + case RSX_FP_OPCODE_DIV: SetDst("($0 / $1)"); break; + case RSX_FP_OPCODE_DIVSQ: SetDst("($0 / sqrt($1))"); break; + case RSX_FP_OPCODE_DP2: SetDst("vec4(dot($0.xy, $1.xy))"); break; + case RSX_FP_OPCODE_DP3: SetDst("vec4(dot($0.xyz, $1.xyz))"); break; + case RSX_FP_OPCODE_DP4: SetDst("vec4(dot($0, $1))"); break; + case RSX_FP_OPCODE_DP2A: SetDst("vec4($0.x * $1.x + $0.y * $1.y + $2.x)"); break; + case RSX_FP_OPCODE_MAD: SetDst("($0 * $1 + $2)"); break; + case RSX_FP_OPCODE_MAX: SetDst("max($0, $1)"); break; + case RSX_FP_OPCODE_MIN: SetDst("min($0, $1)"); break; + case RSX_FP_OPCODE_MOV: SetDst("$0"); break; + case RSX_FP_OPCODE_MUL: SetDst("($0 * $1)"); break; + case RSX_FP_OPCODE_RCP: SetDst("1 / $0"); break; + case RSX_FP_OPCODE_RSQ: SetDst("inversesqrt(abs($0))"); break; + case RSX_FP_OPCODE_SEQ: SetDst("vec4(equal($0, $1))"); break; + case RSX_FP_OPCODE_SFL: SetDst("vec4(0.0)"); break; + case RSX_FP_OPCODE_SGE: SetDst("vec4(greaterThanEqual($0, $1))"); break; + case RSX_FP_OPCODE_SGT: SetDst("vec4(greaterThan($0, $1))"); break; + case RSX_FP_OPCODE_SLE: SetDst("vec4(lessThanEqual($0, $1))"); break; + case RSX_FP_OPCODE_SLT: SetDst("vec4(lessThan($0, $1))"); break; + case RSX_FP_OPCODE_SNE: SetDst("vec4(notEqual($0, $1))"); break; + case RSX_FP_OPCODE_STR: SetDst("vec4(1.0)"); break; + + default: + return false; + } + + return true; + }; + + auto SCB = [&]() + { + switch (opcode) + { + case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); break; + case RSX_FP_OPCODE_COS: SetDst("cos($0)"); break; + case RSX_FP_OPCODE_DP2: SetDst("vec4(dot($0.xy, $1.xy))"); break; + case RSX_FP_OPCODE_DP3: SetDst("vec4(dot($0.xyz, $1.xyz))"); break; + case RSX_FP_OPCODE_DP4: SetDst("vec4(dot($0, $1))"); break; + case RSX_FP_OPCODE_DP2A: SetDst("vec4($0.x * $1.x + $0.y * $1.y + $2.x)"); break; + case RSX_FP_OPCODE_DST: SetDst("vec4(distance($0, $1))"); break; + case RSX_FP_OPCODE_EX2: SetDst("exp2($0)"); break; + case RSX_FP_OPCODE_FLR: SetDst("floor($0)"); break; + case RSX_FP_OPCODE_FRC: SetDst("fract($0)"); break; + case RSX_FP_OPCODE_LIF: SetDst("vec4(1.0, $0.y, ($0.y > 0 ? pow(2.0, $0.w) : 0.0), 1.0)"); break; + case RSX_FP_OPCODE_LG2: SetDst("log2($0)"); break; + case RSX_FP_OPCODE_MAD: SetDst("($0 * $1 + $2)"); break; + case RSX_FP_OPCODE_MAX: SetDst("max($0, $1)"); break; + case RSX_FP_OPCODE_MIN: SetDst("min($0, $1)"); break; + case RSX_FP_OPCODE_MOV: SetDst("$0"); break; + case RSX_FP_OPCODE_MUL: SetDst("($0 * $1)"); break; + case RSX_FP_OPCODE_PK2: LOG_ERROR(RSX, "Unimplemented SCB instruction: PK2"); break; + case RSX_FP_OPCODE_PK4: LOG_ERROR(RSX, "Unimplemented SCB instruction: PK4"); break; + case RSX_FP_OPCODE_PK16: LOG_ERROR(RSX, "Unimplemented SCB instruction: PK16"); break; + case RSX_FP_OPCODE_PKB: LOG_ERROR(RSX, "Unimplemented SCB instruction: PKB"); break; + case RSX_FP_OPCODE_PKG: LOG_ERROR(RSX, "Unimplemented SCB instruction: PKG"); break; + case RSX_FP_OPCODE_SEQ: SetDst("vec4(equal($0, $1))"); break; + case RSX_FP_OPCODE_SFL: SetDst("vec4(0.0)"); break; + case RSX_FP_OPCODE_SGE: SetDst("vec4(greaterThanEqual($0, $1))"); break; + case RSX_FP_OPCODE_SGT: SetDst("vec4(greaterThan($0, $1))"); break; + case RSX_FP_OPCODE_SIN: SetDst("sin($0)"); break; + case RSX_FP_OPCODE_SLE: SetDst("vec4(lessThanEqual($0, $1))"); break; + case RSX_FP_OPCODE_SLT: SetDst("vec4(lessThan($0, $1))"); break; + case RSX_FP_OPCODE_SNE: SetDst("vec4(notEqual($0, $1))"); break; + case RSX_FP_OPCODE_STR: SetDst("vec4(1.0)"); break; + + default: + return false; + } + + return true; + }; + + auto TEX_SRB = [&]() + { + switch (opcode) + { + case RSX_FP_OPCODE_DDX: SetDst("dFdx($0)"); break; + case RSX_FP_OPCODE_DDY: SetDst("dFdy($0)"); break; + case RSX_FP_OPCODE_NRM: SetDst("normalize($0)"); break; + case RSX_FP_OPCODE_TEX: SetDst("texture($t, $0.xy)"); break; + case RSX_FP_OPCODE_TXP: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXP"); break; + case RSX_FP_OPCODE_TXD: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXD"); break; + case RSX_FP_OPCODE_TXB: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXB"); break; + case RSX_FP_OPCODE_TXL: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXL"); break; + case RSX_FP_OPCODE_UP2: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UP2"); break; + case RSX_FP_OPCODE_UP4: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UP4"); break; + case RSX_FP_OPCODE_UP16: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UP16"); break; + case RSX_FP_OPCODE_UPB: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UPB"); break; + case RSX_FP_OPCODE_UPG: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UPG"); break; + + default: + return false; + } + + return true; + }; + + auto SIP = [&]() + { + switch (opcode) + { + case RSX_FP_OPCODE_BRK: SetDst("break"); break; + case RSX_FP_OPCODE_CAL: LOG_ERROR(RSX, "Unimplemented SIP instruction: CAL"); break; + case RSX_FP_OPCODE_FENCT: forced_unit = FORCE_SCT; break; + case RSX_FP_OPCODE_FENCB: forced_unit = FORCE_SCB; break; + case RSX_FP_OPCODE_IFE: + AddCode("if($cond)"); + m_else_offsets.push_back(src1.else_offset << 2); + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + break; + case RSX_FP_OPCODE_LOOP: + if (!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) + { + AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //LOOP", + m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment, src2.end_offset)); + } + else + { + AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) //LOOP", + m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment)); + m_loop_count++; + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + } + break; + case RSX_FP_OPCODE_REP: + if (!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) + { + AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //REP", + m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment, src2.end_offset)); + } + else + { + AddCode(fmt::Format("if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //REP", + m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment)); + m_loop_count++; + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + } + break; + case RSX_FP_OPCODE_RET: SetDst("return"); break; + + default: + return false; + } + + return true; + }; + + switch (opcode) { case RSX_FP_OPCODE_NOP: break; - case RSX_FP_OPCODE_MOV: SetDst("$0"); break; - case RSX_FP_OPCODE_MUL: SetDst("($0 * $1)"); break; - case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); break; - case RSX_FP_OPCODE_MAD: SetDst("($0 * $1 + $2)"); break; - case RSX_FP_OPCODE_DP3: SetDst("vec4(dot($0.xyz, $1.xyz))"); break; - case RSX_FP_OPCODE_DP4: SetDst("vec4(dot($0, $1))"); break; - case RSX_FP_OPCODE_DST: SetDst("vec4(distance($0, $1))"); break; - case RSX_FP_OPCODE_MIN: SetDst("min($0, $1)"); break; - case RSX_FP_OPCODE_MAX: SetDst("max($0, $1)"); break; - case RSX_FP_OPCODE_SLT: SetDst("vec4(lessThan($0, $1))"); break; - case RSX_FP_OPCODE_SGE: SetDst("vec4(greaterThanEqual($0, $1))"); break; - case RSX_FP_OPCODE_SLE: SetDst("vec4(lessThanEqual($0, $1))"); break; - case RSX_FP_OPCODE_SGT: SetDst("vec4(greaterThan($0, $1))"); break; - case RSX_FP_OPCODE_SNE: SetDst("vec4(notEqual($0, $1))"); break; - case RSX_FP_OPCODE_SEQ: SetDst("vec4(equal($0, $1))"); break; - case RSX_FP_OPCODE_FRC: SetDst("fract($0)"); break; - case RSX_FP_OPCODE_FLR: SetDst("floor($0)"); break; case RSX_FP_OPCODE_KIL: SetDst("discard", false); break; - case RSX_FP_OPCODE_PK4: - LOG_ERROR(RSX, "Unimplemented fp_opcode PK4"); - break; - case RSX_FP_OPCODE_UP4: - LOG_ERROR(RSX, "Unimplemented fp_opcode UP4"); - break; - case RSX_FP_OPCODE_DDX: SetDst("dFdx($0)"); break; - case RSX_FP_OPCODE_DDY: SetDst("dFdy($0)"); break; - case RSX_FP_OPCODE_TEX: SetDst("texture($t, $0.xy)"); break; - case RSX_FP_OPCODE_TXP: - LOG_ERROR(RSX, "Unimplemented fp_opcode TXP"); - break; - case RSX_FP_OPCODE_TXD: - LOG_ERROR(RSX, "Unimplemented fp_opcode TXD"); - break; - case RSX_FP_OPCODE_RCP: SetDst("(1 / $0)"); break; - case RSX_FP_OPCODE_RSQ: SetDst("inversesqrt(abs($0))"); break; - case RSX_FP_OPCODE_EX2: SetDst("exp2($0)"); break; - case RSX_FP_OPCODE_LG2: SetDst("log2($0)"); break; - case RSX_FP_OPCODE_LIT: SetDst("vec4(1.0, $0.x, ($0.x > 0 ? exp2($0.w * log2($0.y)) : 0.0), 1.0)"); break; - case RSX_FP_OPCODE_LRP: SetDst("($0 * ($1 - $2) + $2)"); break; - case RSX_FP_OPCODE_STR: SetDst("vec4(equal($0, vec4(1.0)))"); break; - case RSX_FP_OPCODE_SFL: SetDst("vec4(equal($0, vec4(0.0)))"); break; - case RSX_FP_OPCODE_COS: SetDst("cos($0)"); break; - case RSX_FP_OPCODE_SIN: SetDst("sin($0)"); break; - case RSX_FP_OPCODE_PK2: - LOG_ERROR(RSX, "Unimplemented fp_opcode PK2"); - break; - case RSX_FP_OPCODE_UP2: - LOG_ERROR(RSX, "Unimplemented fp_opcode UP2"); - break; - case RSX_FP_OPCODE_POW: SetDst("pow($0, $1)"); break; - case RSX_FP_OPCODE_PKB: - LOG_ERROR(RSX, "Unimplemented fp_opcode PKB"); - break; - case RSX_FP_OPCODE_UPB: - LOG_ERROR(RSX, "Unimplemented fp_opcode UPB"); - break; - case RSX_FP_OPCODE_PK16: - LOG_ERROR(RSX, "Unimplemented fp_opcode PK16"); - break; - case RSX_FP_OPCODE_UP16: - LOG_ERROR(RSX, "Unimplemented fp_opcode UP16"); - break; - case RSX_FP_OPCODE_BEM: - LOG_ERROR(RSX, "Unimplemented fp_opcode BEM"); - break; - case RSX_FP_OPCODE_PKG: - LOG_ERROR(RSX, "Unimplemented fp_opcode PKG"); - break; - case RSX_FP_OPCODE_UPG: - LOG_ERROR(RSX, "Unimplemented fp_opcode UPG"); - break; - case RSX_FP_OPCODE_DP2A: SetDst("($0.x * $1.x + $0.y * $1.y + $2.x)"); break; - case RSX_FP_OPCODE_TXL: break; - LOG_ERROR(RSX, "Unimplemented fp_opcode TXL"); - break; - case RSX_FP_OPCODE_TXB: break; - LOG_ERROR(RSX, "Unimplemented fp_opcode TXB"); - break; - case RSX_FP_OPCODE_TEXBEM: - LOG_ERROR(RSX, "Unimplemented fp_opcode TEXBEM"); - break; - case RSX_FP_OPCODE_TXPBEM: - LOG_ERROR(RSX, "Unimplemented fp_opcode TXPBEM"); - break; - case RSX_FP_OPCODE_BEMLUM: - LOG_ERROR(RSX, "Unimplemented fp_opcode BEMLUM"); - break; - case RSX_FP_OPCODE_REFL: SetDst("($0 - 2.0 * $1 * dot($0, $1))"); break; - case RSX_FP_OPCODE_TIMESWTEX: - LOG_ERROR(RSX, "Unimplemented fp_opcode TIMESWTEX"); - break; - case RSX_FP_OPCODE_DP2: SetDst("vec4(dot($0.xy, $1.xy))"); break; - case RSX_FP_OPCODE_NRM: SetDst("normalize($0.xyz)"); break; - case RSX_FP_OPCODE_DIV: SetDst("($0 / $1)"); break; - case RSX_FP_OPCODE_DIVSQ: SetDst("($0 / sqrt($1))"); break; - case RSX_FP_OPCODE_LIF: SetDst("vec4(1.0, $0.y, ($0.y > 0 ? pow(2.0, $0.w) : 0.0), 1.0)"); break; - case RSX_FP_OPCODE_FENCT: break; - case RSX_FP_OPCODE_FENCB: break; - case RSX_FP_OPCODE_BRK: SetDst("break"); break; - case RSX_FP_OPCODE_CAL: - LOG_ERROR(RSX, "Unimplemented fp_opcode CAL"); - break; - case RSX_FP_OPCODE_IFE: - AddCode("if($cond)"); - m_else_offsets.push_back(src1.else_offset << 2); - m_end_offsets.push_back(src2.end_offset << 2); - AddCode("{"); - m_code_level++; - break; - - case RSX_FP_OPCODE_LOOP: - if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) - { - AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //LOOP", - m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment, src2.end_offset)); - } - else - { - AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) //LOOP", - m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment)); - m_loop_count++; - m_end_offsets.push_back(src2.end_offset << 2); - AddCode("{"); - m_code_level++; - } - break; - case RSX_FP_OPCODE_REP: - if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) - { - AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //REP", - m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment, src2.end_offset)); - } - else - { - AddCode(fmt::Format("if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //REP", - m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment)); - m_loop_count++; - m_end_offsets.push_back(src2.end_offset << 2); - AddCode("{"); - m_code_level++; - } - break; - case RSX_FP_OPCODE_RET: - SetDst("return"); - break; default: - LOG_ERROR(RSX, "Unknown fp opcode 0x%x (inst %d)", opcode, m_size / (4 * 4)); - Emu.Pause(); - break; + if (forced_unit == FORCE_NONE) + { + if (SIP()) break; + if (SCT()) break; + if (TEX_SRB()) break; + if (SCB()) break; + } + else if (forced_unit == FORCE_SCT) + { + forced_unit = FORCE_NONE; + if (SCT()) break; + } + else if (forced_unit == FORCE_SCB) + { + forced_unit = FORCE_NONE; + if (SCB()) break; + } + + LOG_ERROR(RSX, "Unknown/illegal instruction: 0x%x (forced unit %d)", opcode, forced_unit); + break; } m_size += m_offset; - if(dst.end) break; + if (dst.end) break; assert(m_offset % sizeof(u32) == 0); data += m_offset / sizeof(u32); @@ -488,7 +607,7 @@ void GLFragmentDecompilerThread::Task() m_parr.params.clear(); } -GLShaderProgram::GLShaderProgram() +GLShaderProgram::GLShaderProgram() : m_decompiler_thread(nullptr) , m_id(0) { @@ -496,14 +615,14 @@ GLShaderProgram::GLShaderProgram() GLShaderProgram::~GLShaderProgram() { - if(m_decompiler_thread) + if (m_decompiler_thread) { Wait(); - if(m_decompiler_thread->IsAlive()) + if (m_decompiler_thread->IsAlive()) { m_decompiler_thread->Stop(); } - + delete m_decompiler_thread; m_decompiler_thread = nullptr; } @@ -513,7 +632,7 @@ GLShaderProgram::~GLShaderProgram() void GLShaderProgram::Wait() { - if(m_decompiler_thread && m_decompiler_thread->IsAlive()) + if (m_decompiler_thread && m_decompiler_thread->IsAlive()) { m_decompiler_thread->Join(); } @@ -527,14 +646,14 @@ void GLShaderProgram::Decompile(RSXShaderProgram& prog) void GLShaderProgram::DecompileAsync(RSXShaderProgram& prog) { - if(m_decompiler_thread) + if (m_decompiler_thread) { Wait(); - if(m_decompiler_thread->IsAlive()) + if (m_decompiler_thread->IsAlive()) { m_decompiler_thread->Stop(); } - + delete m_decompiler_thread; m_decompiler_thread = nullptr; } diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.h b/rpcs3/Emu/RSX/GL/GLFragmentProgram.h index f05dfc30e0..9666035d07 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.h +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.h @@ -155,6 +155,7 @@ struct GLFragmentDecompilerThread : public ThreadBase std::string AddTex(); std::string Format(const std::string& code); + void AddCodeCond(const std::string& dst, const std::string& src); std::string GetCond(); template std::string GetSRC(T src); std::string BuildCode(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 9e9fdd70de..c55c1962a4 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -425,7 +425,7 @@ void GLTexture::Init(RSXTexture& tex) free(unswizzledPixels); } - break; break; + break; case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN): { @@ -450,7 +450,7 @@ void GLTexture::Init(RSXTexture& tex) free(unswizzledPixels); } - break; break; + break; default: LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, (is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40); @@ -1647,6 +1647,21 @@ void GLGSRender::InitDrawBuffers() LOG_ERROR(RSX, "Bad surface color target: %d", m_surface_color_target); break; } + + if (m_read_buffer) + { + u32 format = GL_BGRA; + CellGcmDisplayInfo* buffers = vm::get_ptr(m_gcm_buffers_addr); + u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); + + if (Memory.IsGoodAddr(addr)) + { + u32 width = buffers[m_gcm_current_buffer].width; + u32 height = buffers[m_gcm_current_buffer].height; + + glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, vm::get_ptr(addr)); + } + } } void GLGSRender::ExecCMD(u32 cmd) @@ -1721,24 +1736,6 @@ void GLGSRender::ExecCMD() checkForGlError("glColorMask"); } - if (!m_indexed_array.m_count && !m_draw_array_count) - { - u32 min_vertex_size = ~0; - for(auto &i : m_vertex_data) - { - if (!i.size) - continue; - - u32 vertex_size = i.data.size() / (i.size * i.GetTypeSize()); - - if (min_vertex_size > vertex_size) - min_vertex_size = vertex_size; - } - - m_draw_array_count = min_vertex_size; - m_draw_array_first = 0; - } - Enable(m_set_depth_test, GL_DEPTH_TEST); Enable(m_set_alpha_test, GL_ALPHA_TEST); Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT); @@ -1995,6 +1992,20 @@ void GLGSRender::ExecCMD() checkForGlError(fmt::Format("m_gl_textures[%d].Init", i)); } + for (u32 i = 0; i < m_textures_count; ++i) + { + if (!m_vertex_textures[i].IsEnabled()) continue; + + glActiveTexture(GL_TEXTURE0 + m_textures_count + i); + checkForGlError("glActiveTexture"); + m_gl_vertex_textures[i].Create(); + m_gl_vertex_textures[i].Bind(); + checkForGlError(fmt::Format("m_gl_vertex_textures[%d].Bind", i)); + m_program.SetTex(i); + m_gl_vertex_textures[i].Init(m_vertex_textures[i]); + checkForGlError(fmt::Format("m_gl_vertex_textures[%d].Init", i)); + } + m_vao.Bind(); if(m_indexed_array.m_count) { diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index a598404c8a..b89484fb87 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -148,6 +148,7 @@ private: GLVertexProgram m_vertex_prog; GLTexture m_gl_textures[m_textures_count]; + GLTexture m_gl_vertex_textures[m_textures_count]; GLvao m_vao; GLvbo m_vbo; diff --git a/rpcs3/Emu/RSX/GL/GLProgram.cpp b/rpcs3/Emu/RSX/GL/GLProgram.cpp index e7e7fdaa0a..32f9d709bd 100644 --- a/rpcs3/Emu/RSX/GL/GLProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLProgram.cpp @@ -98,6 +98,13 @@ void GLProgram::SetTex(u32 index) checkForGlError(fmt::Format("SetTex(%u - %d - %d)", id, index, loc)); } +void GLProgram::SetVTex(u32 index) +{ + int loc = GetLocation(fmt::Format("vtex%u", index)); + glProgramUniform1i(id, loc, index); + checkForGlError(fmt::Format("SetVTex(%u - %d - %d)", id, index, loc)); +} + void GLProgram::Delete() { if(!IsCreated()) return; diff --git a/rpcs3/Emu/RSX/GL/GLProgram.h b/rpcs3/Emu/RSX/GL/GLProgram.h index 321a2e3cf5..076b3ce01f 100644 --- a/rpcs3/Emu/RSX/GL/GLProgram.h +++ b/rpcs3/Emu/RSX/GL/GLProgram.h @@ -24,5 +24,6 @@ public: void Use(); void UnUse(); void SetTex(u32 index); + void SetVTex(u32 index); void Delete(); }; diff --git a/rpcs3/Emu/RSX/GL/GLShaderParam.h b/rpcs3/Emu/RSX/GL/GLShaderParam.h index 80fa5a3dec..f90402eda0 100644 --- a/rpcs3/Emu/RSX/GL/GLShaderParam.h +++ b/rpcs3/Emu/RSX/GL/GLShaderParam.h @@ -1,5 +1,6 @@ #pragma once #include "OpenGL.h" +#include enum GLParamFlag { @@ -41,9 +42,9 @@ struct GLParamType bool SearchName(const std::string& name) { - for(u32 i=0; iSearchName(name)) t->items.emplace_back(name, -1, value); + if (!t->SearchName(name)) t->items.emplace_back(name, -1, value); } else { @@ -125,9 +126,9 @@ struct GLParamArray type = GetParamFlag(flag) + type; GLParamType* t = SearchParam(type); - if(t) + if (t) { - if(!t->SearchName(name)) t->items.emplace_back(name, location); + if (!t->SearchName(name)) t->items.emplace_back(name, location); } else { @@ -139,3 +140,90 @@ struct GLParamArray return name; } }; + +class ShaderVar +{ +public: + std::string name; + std::vector swizzles; + + ShaderVar() = default; + ShaderVar(const std::string& var) + { + auto var_blocks = fmt::split(var, { "." }); + + if (var_blocks.size() == 0) + { + assert(0); + } + + name = var_blocks[0]; + + if (var_blocks.size() == 1) + { + swizzles.push_back("xyzw"); + } + else + { + swizzles = std::vector(var_blocks.begin() + 1, var_blocks.end()); + } + } + + int get_vector_size() const + { + return swizzles[swizzles.size() - 1].length(); + } + + ShaderVar& symplify() + { + std::unordered_map swizzle; + + static std::unordered_map pos_to_swizzle = + { + { 0, 'x' }, + { 1, 'y' }, + { 2, 'z' }, + { 3, 'w' } + }; + + for (auto &i : pos_to_swizzle) + { + swizzle[i.second] = swizzles[0].length() > i.first ? swizzles[0][i.first] : 0; + } + + for (int i = 1; i < swizzles.size(); ++i) + { + std::unordered_map new_swizzle; + + for (auto &sw : pos_to_swizzle) + { + new_swizzle[sw.second] = swizzle[swizzles[i].length() <= sw.first ? '\0' : swizzles[i][sw.first]]; + } + + swizzle = new_swizzle; + } + + swizzles.clear(); + std::string new_swizzle; + + for (auto &i : pos_to_swizzle) + { + if (swizzle[i.second] != '\0') + new_swizzle += swizzle[i.second]; + } + + swizzles.push_back(new_swizzle); + + return *this; + } + + std::string get() const + { + if (swizzles.size() == 1 && swizzles[0] == "xyzw") + { + return name; + } + + return name + "." + fmt::merge({ swizzles }, "."); + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index fffaf8f42a..fe99a79847 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -8,19 +8,19 @@ std::string GLVertexDecompilerThread::GetMask(bool is_sca) { std::string ret; - if(is_sca) + if (is_sca) { - if(d3.sca_writemask_x) ret += "x"; - if(d3.sca_writemask_y) ret += "y"; - if(d3.sca_writemask_z) ret += "z"; - if(d3.sca_writemask_w) ret += "w"; + if (d3.sca_writemask_x) ret += "x"; + if (d3.sca_writemask_y) ret += "y"; + if (d3.sca_writemask_z) ret += "z"; + if (d3.sca_writemask_w) ret += "w"; } else { - if(d3.vec_writemask_x) ret += "x"; - if(d3.vec_writemask_y) ret += "y"; - if(d3.vec_writemask_z) ret += "z"; - if(d3.vec_writemask_w) ret += "w"; + if (d3.vec_writemask_x) ret += "x"; + if (d3.vec_writemask_y) ret += "y"; + if (d3.vec_writemask_z) ret += "z"; + if (d3.vec_writemask_w) ret += "w"; } return ret.empty() || ret == "xyzw" ? "" : ("." + ret); @@ -40,17 +40,17 @@ std::string GLVertexDecompilerThread::GetDST(bool isSca) { std::string ret; - switch(isSca ? 0x1f : d3.dst) + switch (isSca ? 0x1f : d3.dst) { case 0x1f: ret += m_parr.AddParam(PARAM_NONE, "vec4", std::string("tmp") + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp)); - break; + break; default: if (d3.dst > 15) LOG_ERROR(RSX, "dst index out of range: %u", d3.dst); ret += m_parr.AddParam(PARAM_NONE, "vec4", std::string("dst_reg") + std::to_string(d3.dst), d3.dst == 0 ? "vec4(0.0f, 0.0f, 0.0f, 1.0f)" : "vec4(0.0)"); - break; + break; } return ret; @@ -58,7 +58,7 @@ std::string GLVertexDecompilerThread::GetDST(bool isSca) std::string GLVertexDecompilerThread::GetSRC(const u32 n) { - static const std::string reg_table[] = + static const std::string reg_table[] = { "in_pos", "in_weight", "in_normal", "in_diff_color", "in_spec_color", @@ -70,13 +70,13 @@ std::string GLVertexDecompilerThread::GetSRC(const u32 n) std::string ret; - switch(src[n].reg_type) + switch (src[n].reg_type) { case 1: //temp ret += m_parr.AddParam(PARAM_NONE, "vec4", "tmp" + std::to_string(src[n].tmp_src)); - break; + break; case 2: //input - if (d1.input_src < (sizeof(reg_table)/sizeof(reg_table[0]))) + if (d1.input_src < (sizeof(reg_table) / sizeof(reg_table[0]))) { ret += m_parr.AddParam(PARAM_IN, "vec4", reg_table[d1.input_src], d1.input_src); } @@ -85,16 +85,16 @@ std::string GLVertexDecompilerThread::GetSRC(const u32 n) LOG_ERROR(RSX, "Bad input src num: %d", fmt::by_value(d1.input_src)); ret += m_parr.AddParam(PARAM_IN, "vec4", "in_unk", d1.input_src); } - break; + break; case 3: //const m_parr.AddParam(PARAM_UNIFORM, "vec4", std::string("vc[468]")); ret += std::string("vc[") + std::to_string(d1.const_src) + (d3.index_const ? " + " + AddAddrReg() : "") + "]"; - break; + break; default: LOG_ERROR(RSX, "Bad src%u reg type: %d", n, fmt::by_value(src[n].reg_type)); Emu.Pause(); - break; + break; } static const std::string f = "xyzw"; @@ -106,26 +106,26 @@ std::string GLVertexDecompilerThread::GetSRC(const u32 n) swizzle += f[src[n].swz_z]; swizzle += f[src[n].swz_w]; - if(swizzle != f) ret += '.' + swizzle; + if (swizzle != f) ret += '.' + swizzle; bool abs; - - switch(n) + + switch (n) { case 0: abs = d0.src0_abs; break; case 1: abs = d0.src1_abs; break; case 2: abs = d0.src2_abs; break; } - - if(abs) ret = "abs(" + ret + ")"; - if(src[n].neg) ret = "-" + ret; + + if (abs) ret = "abs(" + ret + ")"; + if (src[n].neg) ret = "-" + ret; return ret; } void GLVertexDecompilerThread::SetDST(bool is_sca, std::string value) { - if(d0.cond == 0) return; + if (d0.cond == 0) return; enum { @@ -138,12 +138,12 @@ void GLVertexDecompilerThread::SetDST(bool is_sca, std::string value) value += mask; - if(is_sca && d0.vec_result) + if (is_sca && d0.vec_result) { - value = "vec4(" + value + ")" + mask; + //value = "vec4(" + value + ")"; } - if(d0.staturate) + if (d0.staturate) { value = "clamp(" + value + ", 0.0, 1.0)"; } @@ -152,22 +152,20 @@ void GLVertexDecompilerThread::SetDST(bool is_sca, std::string value) if (d0.cond_update_enable_0 && d0.cond_update_enable_1) { - dest += m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(d0.cond_reg_sel_1), "vec4(0.0)") + mask + " = "; + dest = m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(d0.cond_reg_sel_1), "vec4(0.0)") + mask; } - - if (d3.dst != 0x1f || (is_sca ? d3.sca_dst_tmp != 0x3f : d0.dst_tmp != 0x3f)) + else if (d3.dst != 0x1f || (is_sca ? d3.sca_dst_tmp != 0x3f : d0.dst_tmp != 0x3f)) { - dest += GetDST(is_sca) + mask + " = "; + dest = GetDST(is_sca) + mask; } - std::string code; + //std::string code; + //if (d0.cond_test_enable) + // code += "$ifcond "; + //code += dest + value; + //AddCode(code + ";"); - if (d0.cond_test_enable) - code += "$ifcond "; - - code += dest + value; - - AddCode(code + ";"); + AddCodeCond(dest, value); } std::string GLVertexDecompilerThread::GetFunc() @@ -188,6 +186,11 @@ std::string GLVertexDecompilerThread::GetFunc() return name + "()"; } +std::string GLVertexDecompilerThread::GetTex() +{ + return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", std::string("vtex") + std::to_string(/*?.tex_num*/0)); +} + std::string GLVertexDecompilerThread::Format(const std::string& code) { const std::pair> repl_list[] = @@ -200,14 +203,16 @@ std::string GLVertexDecompilerThread::Format(const std::string& code) { "$am", std::bind(std::mem_fn(&GLVertexDecompilerThread::AddAddrMask), this) }, { "$a", std::bind(std::mem_fn(&GLVertexDecompilerThread::AddAddrReg), this) }, - { "$fa", [this]()->std::string {return std::to_string(GetAddr()); } }, + { "$t", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetTex), this) }, + + { "$fa", [this]()->std::string { return std::to_string(GetAddr()); } }, { "$f()", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetFunc), this) }, { "$ifcond ", [this]() -> std::string - { - const std::string& cond = GetCond(); - if (cond == "true") return ""; - return "if(" + cond + ") "; - } + { + const std::string& cond = GetCond(); + if (cond == "true") return ""; + return "if(" + cond + ") "; + } }, { "$cond", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetCond), this) } }; @@ -252,6 +257,70 @@ std::string GLVertexDecompilerThread::GetCond() return fmt::Format("any(%s(cc%d%s, vec4(0.0)%s))", cond_string_table[d0.cond], d0.cond_reg_sel_1, swizzle.c_str(), swizzle.c_str()); } +void GLVertexDecompilerThread::AddCodeCond(const std::string& dst, const std::string& src) +{ + enum + { + lt = 0x1, + eq = 0x2, + gt = 0x4, + }; + + + if (!d0.cond_test_enable || d0.cond == (lt | gt | eq)) + { + AddCode(dst + " = " + src + ";"); + return; + } + + if (d0.cond == 0) + { + AddCode("//" + dst + " = " + src + ";"); + return; + } + + static const char* cond_string_table[(lt | gt | eq) + 1] = + { + "error", + "lessThan", + "equal", + "lessThanEqual", + "greaterThan", + "notEqual", + "greaterThanEqual", + "error" + }; + + static const char f[4] = { 'x', 'y', 'z', 'w' }; + + std::string swizzle; + swizzle += f[d0.mask_x]; + swizzle += f[d0.mask_y]; + swizzle += f[d0.mask_z]; + swizzle += f[d0.mask_w]; + + swizzle = swizzle == "xyzw" ? "" : "." + swizzle; + + std::string cond = fmt::Format("%s(cc%d%s, vec4(0.0))", cond_string_table[d0.cond], d0.cond_reg_sel_1, swizzle.c_str()); + + ShaderVar dst_var(dst); + dst_var.symplify(); + + //const char *c_mask = f; + + if (dst_var.swizzles[0].length() == 1) + { + AddCode("if (" + cond + ".x) " + dst + " = vec4(" + src + ").x;"); + } + else + { + for (int i = 0; i < dst_var.swizzles[0].length(); ++i) + { + AddCode("if (" + cond + "." + f[i] + ") " + dst + "." + f[i] + " = " + src + "." + f[i] + ";"); + } + } +} + std::string GLVertexDecompilerThread::AddAddrMask() { @@ -290,21 +359,21 @@ std::string GLVertexDecompilerThread::BuildFuncBody(const FuncInfo& func) { std::string result; - for(uint i=func.offset; i 0 ? exp2($s.w * log2($s.y)) : 0.0), 1.0)"); break; + case RSX_SCA_OPCODE_LIT: SetDSTSca("vec4(1.0, $s.x, ($s.x > 0.0 ? exp($s.w * log2($s.y)) : 0.0), 1.0)"); break; case RSX_SCA_OPCODE_BRA: { AddCode("$if ($cond)"); @@ -599,33 +668,33 @@ void GLVertexDecompilerThread::Task() break; case RSX_SCA_OPCODE_CAL: // works same as BRI - AddCode("$ifcond $f(); //CAL"); + AddCode("$ifcond $f(); //CAL"); break; - case RSX_SCA_OPCODE_CLI: + case RSX_SCA_OPCODE_CLI: // works same as BRI - AddCode("$ifcond $f(); //CLI"); + AddCode("$ifcond $f(); //CLI"); break; case RSX_SCA_OPCODE_RET: // works like BRI but shorter (RET o[1].x(TR);) - AddCode("$ifcond return;"); + AddCode("$ifcond return;"); break; case RSX_SCA_OPCODE_LG2: SetDSTSca("log2($s)"); break; case RSX_SCA_OPCODE_EX2: SetDSTSca("exp2($s)"); break; case RSX_SCA_OPCODE_SIN: SetDSTSca("sin($s)"); break; case RSX_SCA_OPCODE_COS: SetDSTSca("cos($s)"); break; - case RSX_SCA_OPCODE_BRB: + case RSX_SCA_OPCODE_BRB: // works differently (BRB o[1].x !b0, L0;) LOG_ERROR(RSX, "Unimplemented sca_opcode BRB"); break; - case RSX_SCA_OPCODE_CLB: break; + case RSX_SCA_OPCODE_CLB: break; // works same as BRB LOG_ERROR(RSX, "Unimplemented sca_opcode CLB"); break; - case RSX_SCA_OPCODE_PSH: break; + case RSX_SCA_OPCODE_PSH: break; // works differently (PSH o[1].x A0;) LOG_ERROR(RSX, "Unimplemented sca_opcode PSH"); break; - case RSX_SCA_OPCODE_POP: break; + case RSX_SCA_OPCODE_POP: break; // works differently (POP o[1].x;) LOG_ERROR(RSX, "Unimplemented sca_opcode POP"); break; @@ -634,7 +703,7 @@ void GLVertexDecompilerThread::Task() AddCode(fmt::Format("//Unknown vp sca_opcode 0x%x", fmt::by_value(d1.sca_opcode))); LOG_ERROR(RSX, "Unknown vp sca_opcode 0x%x", fmt::by_value(d1.sca_opcode)); Emu.Pause(); - break; + break; } switch (d1.vec_opcode) @@ -662,12 +731,13 @@ void GLVertexDecompilerThread::Task() case RSX_VEC_OPCODE_SNE: SetDSTVec("vec4(notEqual($0, $1))"); break; case RSX_VEC_OPCODE_STR: SetDSTVec("vec4(equal($0, vec4(1.0)))"); break; case RSX_VEC_OPCODE_SSG: SetDSTVec("sign($0)"); break; + case RSX_VEC_OPCODE_TEX: SetDSTVec("texture($t, $0.xy)"); break; default: AddCode(fmt::Format("//Unknown vp opcode 0x%x", fmt::by_value(d1.vec_opcode))); LOG_ERROR(RSX, "Unknown vp opcode 0x%x", fmt::by_value(d1.vec_opcode)); Emu.Pause(); - break; + break; } if (d3.end) @@ -710,10 +780,10 @@ GLVertexProgram::GLVertexProgram() GLVertexProgram::~GLVertexProgram() { - if(m_decompiler_thread) + if (m_decompiler_thread) { Wait(); - if(m_decompiler_thread->IsAlive()) + if (m_decompiler_thread->IsAlive()) { m_decompiler_thread->Stop(); } @@ -727,7 +797,7 @@ GLVertexProgram::~GLVertexProgram() void GLVertexProgram::Wait() { - if(m_decompiler_thread && m_decompiler_thread->IsAlive()) + if (m_decompiler_thread && m_decompiler_thread->IsAlive()) { m_decompiler_thread->Join(); } @@ -759,7 +829,7 @@ void GLVertexProgram::DecompileAsync(RSXVertexProgram& prog) void GLVertexProgram::Compile() { - if(id) glDeleteShader(id); + if (id) glDeleteShader(id); id = glCreateShader(GL_VERTEX_SHADER); @@ -768,16 +838,16 @@ void GLVertexProgram::Compile() glShaderSource(id, 1, &str, &strlen); glCompileShader(id); - + GLint r = GL_FALSE; glGetShaderiv(id, GL_COMPILE_STATUS, &r); - if(r != GL_TRUE) + if (r != GL_TRUE) { glGetShaderiv(id, GL_INFO_LOG_LENGTH, &r); - if(r) + if (r) { - char* buf = new char[r+1](); + char* buf = new char[r + 1](); GLsizei len; glGetShaderInfoLog(id, r, &len, buf); LOG_ERROR(RSX, "Failed to compile vertex shader: %s", buf); @@ -796,7 +866,7 @@ void GLVertexProgram::Delete() parr.params.clear(); shader.clear(); - if(id) + if (id) { if (Emu.IsStopped()) { diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.h b/rpcs3/Emu/RSX/GL/GLVertexProgram.h index af8a666200..de4c3d07cd 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.h +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.h @@ -54,6 +54,7 @@ enum vec_opcode RSX_VEC_OPCODE_SNE = 0x14, RSX_VEC_OPCODE_STR = 0x15, RSX_VEC_OPCODE_SSG = 0x16, + RSX_VEC_OPCODE_TEX = 0x19, }; struct GLVertexDecompilerThread : public ThreadBase @@ -237,12 +238,14 @@ struct GLVertexDecompilerThread : public ThreadBase std::string GetDST(bool is_sca = false); std::string GetSRC(const u32 n); std::string GetFunc(); + std::string GetTex(); std::string GetCond(); std::string AddAddrMask(); std::string AddAddrReg(); u32 GetAddr(); std::string Format(const std::string& code); + void AddCodeCond(const std::string& dst, const std::string& src); void AddCode(const std::string& code); void SetDST(bool is_sca, std::string value); void SetDSTVec(const std::string& code); diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index 6904da2420..7a21e076d3 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -210,3 +210,206 @@ void RSXTexture::SetControl3(u16 depth, u32 pitch) m_depth = depth; m_pitch = pitch; } + +RSXVertexTexture::RSXVertexTexture() : RSXTexture() +{ +} + +RSXVertexTexture::RSXVertexTexture(u8 index) : RSXTexture(index) +{ +} + +void RSXVertexTexture::Init() +{ + // Offset + methodRegisters[NV4097_SET_VERTEX_TEXTURE_OFFSET + (m_index * 32)] = 0; + + // Format + methodRegisters[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 32)] = 0; + + // Address + methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)] = + ((/*wraps*/1) | ((/*anisoBias*/0) << 4) | ((/*wrapt*/1) << 8) | ((/*unsignedRemap*/0) << 12) | + ((/*wrapr*/3) << 16) | ((/*gamma*/0) << 20) | ((/*signedRemap*/0) << 24) | ((/*zfunc*/0) << 28)); + + // Control0 + methodRegisters[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 32)] = + (((/*alphakill*/0) << 2) | (/*maxaniso*/0) << 4) | ((/*maxlod*/0xc00) << 7) | ((/*minlod*/0) << 19) | ((/*enable*/0) << 31); + + // Control1 + //methodRegisters[NV4097_SET_VERTEX_TEXTURE_CONTROL1 + (m_index * 32)] = 0xE4; + + // Filter + methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)] = + ((/*bias*/0) | ((/*conv*/1) << 13) | ((/*min*/5) << 16) | ((/*mag*/2) << 24) + | ((/*as*/0) << 28) | ((/*rs*/0) << 29) | ((/*gs*/0) << 30) | ((/*bs*/0) << 31)); + + // Image Rect + methodRegisters[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 32)] = (/*height*/1) | ((/*width*/1) << 16); + + // Border Color + methodRegisters[NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + (m_index * 32)] = 0; +} + +u32 RSXVertexTexture::GetOffset() const +{ + return methodRegisters[NV4097_SET_VERTEX_TEXTURE_OFFSET + (m_index * 32)]; +} + +u8 RSXVertexTexture::GetLocation() const +{ + return (methodRegisters[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 32)] & 0x3) - 1; +} + +bool RSXVertexTexture::isCubemap() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 32)] >> 2) & 0x1); +} + +u8 RSXVertexTexture::GetBorderType() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 32)] >> 3) & 0x1); +} + +u8 RSXVertexTexture::GetDimension() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 32)] >> 4) & 0xf); +} + +u8 RSXVertexTexture::GetFormat() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 32)] >> 8) & 0xff); +} + +u16 RSXVertexTexture::GetMipmap() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 32)] >> 16) & 0xffff); +} + +u8 RSXVertexTexture::GetWrapS() const +{ + return 1; + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)]) & 0xf); +} + +u8 RSXVertexTexture::GetWrapT() const +{ + return 1; + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)] >> 8) & 0xf); +} + +u8 RSXVertexTexture::GetWrapR() const +{ + return 1; + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)] >> 16) & 0xf); +} + +u8 RSXVertexTexture::GetUnsignedRemap() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)] >> 12) & 0xf); +} + +u8 RSXVertexTexture::GetZfunc() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)] >> 28) & 0xf); +} + +u8 RSXVertexTexture::GetGamma() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)] >> 20) & 0xf); +} + +u8 RSXVertexTexture::GetAnisoBias() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)] >> 4) & 0xf); +} + +u8 RSXVertexTexture::GetSignedRemap() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 32)] >> 24) & 0xf); +} + +bool RSXVertexTexture::IsEnabled() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 32)] >> 31) & 0x1); +} + +u16 RSXVertexTexture::GetMinLOD() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 32)] >> 19) & 0xfff); +} + +u16 RSXVertexTexture::GetMaxLOD() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 32)] >> 7) & 0xfff); +} + +u8 RSXVertexTexture::GetMaxAniso() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 32)] >> 4) & 0x7); +} + +bool RSXVertexTexture::IsAlphaKillEnabled() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 32)] >> 2) & 0x1); +} + +u32 RSXVertexTexture::GetRemap() const +{ + return 0 | (1 << 2) | (2 << 4) | (3 << 6);//(methodRegisters[NV4097_SET_VERTEX_TEXTURE_CONTROL1 + (m_index * 32)]); +} + +u16 RSXVertexTexture::GetBias() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)]) & 0x1fff); +} + +u8 RSXVertexTexture::GetMinFilter() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)] >> 16) & 0x7); +} + +u8 RSXVertexTexture::GetMagFilter() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)] >> 24) & 0x7); +} + +u8 RSXVertexTexture::GetConvolutionFilter() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)] >> 13) & 0xf); +} + +bool RSXVertexTexture::isASigned() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)] >> 28) & 0x1); +} + +bool RSXVertexTexture::isRSigned() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)] >> 29) & 0x1); +} + +bool RSXVertexTexture::isGSigned() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)] >> 30) & 0x1); +} + +bool RSXVertexTexture::isBSigned() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 32)] >> 31) & 0x1); +} + +u16 RSXVertexTexture::GetWidth() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 32)] >> 16) & 0xffff); +} + +u16 RSXVertexTexture::GetHeight() const +{ + return ((methodRegisters[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 32)]) & 0xffff); +} + +u32 RSXVertexTexture::GetBorderColor() const +{ + return methodRegisters[NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + (m_index * 32)]; +} \ No newline at end of file diff --git a/rpcs3/Emu/RSX/RSXTexture.h b/rpcs3/Emu/RSX/RSXTexture.h index d5db3480fb..c595dba082 100644 --- a/rpcs3/Emu/RSX/RSXTexture.h +++ b/rpcs3/Emu/RSX/RSXTexture.h @@ -2,6 +2,7 @@ class RSXTexture { +protected: u8 m_index; public: @@ -11,6 +12,64 @@ public: public: RSXTexture(); RSXTexture(u8 index); + virtual void Init(); + + // Offset + virtual u32 GetOffset() const; + + // Format + virtual u8 GetLocation() const; + virtual bool isCubemap() const; + virtual u8 GetBorderType() const; + virtual u8 GetDimension() const; + virtual u8 GetFormat() const; + virtual u16 GetMipmap() const; + + // Address + virtual u8 GetWrapS() const; + virtual u8 GetWrapT() const; + virtual u8 GetWrapR() const; + virtual u8 GetUnsignedRemap() const; + virtual u8 GetZfunc() const; + virtual u8 GetGamma() const; + virtual u8 GetAnisoBias() const; + virtual u8 GetSignedRemap() const; + + // Control0 + virtual bool IsEnabled() const; + virtual u16 GetMinLOD() const; + virtual u16 GetMaxLOD() const; + virtual u8 GetMaxAniso() const; + virtual bool IsAlphaKillEnabled() const; + + // Control1 + virtual u32 GetRemap() const; + + // Filter + virtual u16 GetBias() const; + virtual u8 GetMinFilter() const; + virtual u8 GetMagFilter() const; + virtual u8 GetConvolutionFilter() const; + virtual bool isASigned() const; + virtual bool isRSigned() const; + virtual bool isGSigned() const; + virtual bool isBSigned() const; + + // Image Rect + virtual u16 GetWidth() const; + virtual u16 GetHeight() const; + + // Border Color + virtual u32 GetBorderColor() const; + + void SetControl3(u16 depth, u32 pitch); +}; + +class RSXVertexTexture : public RSXTexture +{ +public: + RSXVertexTexture(); + RSXVertexTexture(u8 index); void Init(); // Offset @@ -60,6 +119,4 @@ public: // Border Color u32 GetBorderColor() const; - - void SetControl3(u16 depth, u32 pitch); -}; +}; \ No newline at end of file diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 311dd3143c..62606796a8 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -181,6 +181,12 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, cons return 0; } +#define case_4(a, m) \ + case a + m: \ + case a + m * 2: \ + case a + m * 3: \ + index = (cmd - a) / m; \ + case a \ #define case_16(a, m) \ case a + m: \ @@ -252,8 +258,6 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_used_gcm_commands.insert(cmd); - //static u32 draw_array_count = 0; - switch(cmd) { // NV406E @@ -392,6 +396,29 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const } break; + // Vertex Texture + case_4(NV4097_SET_VERTEX_TEXTURE_FORMAT, 0x20) : + case_4(NV4097_SET_VERTEX_TEXTURE_OFFSET, 0x20) : + case_4(NV4097_SET_VERTEX_TEXTURE_FILTER, 0x20) : + case_4(NV4097_SET_VERTEX_TEXTURE_ADDRESS, 0x20) : + case_4(NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT, 0x20) : + case_4(NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR, 0x20) : + case_4(NV4097_SET_VERTEX_TEXTURE_CONTROL0, 0x20) : + { + // Done using methodRegisters in RSXTexture.cpp + } + break; + + case_4(NV4097_SET_VERTEX_TEXTURE_CONTROL3, 0x20) : + { + RSXVertexTexture& tex = m_vertex_textures[index]; + const u32 a0 = ARGS(0); + u32 pitch = a0 & 0xFFFFF; + u16 depth = a0 >> 20; + tex.SetControl3(depth, pitch); + } + break; + // Vertex data case_16(NV4097_SET_VERTEX_DATA4UB_M, 4): { @@ -971,10 +998,27 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u32 a0 = ARGS(0); //LOG_WARNING(RSX, "NV4097_SET_BEGIN_END: 0x%x", a0); + if (!m_indexed_array.m_count && !m_draw_array_count) + { + u32 min_vertex_size = ~0; + for (auto &i : m_vertex_data) + { + if (!i.size) + continue; - m_read_buffer = false; + u32 vertex_size = i.data.size() / (i.size * i.GetTypeSize()); - if(a0) + if (min_vertex_size > vertex_size) + min_vertex_size = vertex_size; + } + + m_draw_array_count = min_vertex_size; + m_draw_array_first = 0; + } + + m_read_buffer = Ini.GSReadColorBuffer.GetValue() || (!m_indexed_array.m_count && !m_draw_array_count); + + if (a0) { Begin(a0); } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index d38b45fec1..e93af15a85 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -106,6 +106,7 @@ public: GcmTileInfo m_tiles[m_tiles_count]; GcmZcullInfo m_zculls[m_zculls_count]; RSXTexture m_textures[m_textures_count]; + RSXVertexTexture m_vertex_textures[m_textures_count]; RSXVertexData m_vertex_data[m_vertex_count]; RSXIndexArrayData m_indexed_array; std::vector m_fragment_constants; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 2f6b5a5bd0..8e08a1faf7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -369,7 +369,7 @@ s32 _cellGcmInitBody(vm::ptr context, u32 cmdSize, u32 ioSiz u32 ctx_begin = ioAddress/* + 0x1000*/; u32 ctx_size = 0x6ffc; current_context.begin = ctx_begin; - current_context.end = ctx_begin + ctx_size; + current_context.end = ctx_begin + ctx_size - 4; current_context.current = current_context.begin; current_context.callback.set(be_t::make(Emu.GetRSXCallback() - 4)); @@ -1172,7 +1172,7 @@ s32 cellGcmCallback(vm::ptr context, u32 count) GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); - if (1) + if (0) { auto& ctrl = vm::get_ref(gcm_info.control_addr); be_t res = be_t::make(context->current - context->begin - ctrl.put.read_relaxed()); diff --git a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp index ab3645a1cb..a05edc415c 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp @@ -116,17 +116,16 @@ int npDrmIsAvailable(u32 k_licensee_addr, vm::ptr drm_path) std::string rap_path("/dev_hdd0/home/" + pf_str + "/exdata/"); // Search dev_usb000 for a compatible RAP file. - vfsDir *raps_dir = new vfsDir(rap_path); - if (!raps_dir->IsOpened()) + vfsDir raps_dir(rap_path); + if (!raps_dir.IsOpened()) sceNp->Warning("npDrmIsAvailable: Can't find RAP file for DRM!"); else { - const std::vector &entries = raps_dir->GetEntries(); - for (auto &entry : entries) + for (const DirEntryInfo *entry : raps_dir) { - if (entry.name.find(titleID) != std::string::npos) + if (entry->name.find(titleID) != std::string::npos) { - rap_path += entry.name; + rap_path += entry->name; break; } } diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 6c096cda47..b64f1aad56 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -414,6 +414,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxCheckBox* chbox_gs_log_prog = new wxCheckBox(p_graphics, wxID_ANY, "Log vertex/fragment programs"); wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(p_graphics, wxID_ANY, "Write Depth Buffer"); wxCheckBox* chbox_gs_dump_color = new wxCheckBox(p_graphics, wxID_ANY, "Write Color Buffers"); + wxCheckBox* chbox_gs_read_color = new wxCheckBox(p_graphics, wxID_ANY, "Read Color Buffer"); wxCheckBox* chbox_gs_vsync = new wxCheckBox(p_graphics, wxID_ANY, "VSync"); wxCheckBox* chbox_gs_3dmonitor = new wxCheckBox(p_graphics, wxID_ANY, "3D Monitor"); wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file"); @@ -501,6 +502,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) chbox_gs_log_prog ->SetValue(Ini.GSLogPrograms.GetValue()); chbox_gs_dump_depth ->SetValue(Ini.GSDumpDepthBuffer.GetValue()); chbox_gs_dump_color ->SetValue(Ini.GSDumpColorBuffers.GetValue()); + chbox_gs_read_color ->SetValue(Ini.GSReadColorBuffer.GetValue()); chbox_gs_vsync ->SetValue(Ini.GSVSyncEnable.GetValue()); chbox_gs_3dmonitor ->SetValue(Ini.GS3DTV.GetValue()); chbox_audio_dump ->SetValue(Ini.AudioDumpToFile.GetValue()); @@ -568,6 +570,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) s_subpanel_graphics->Add(chbox_gs_log_prog, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_dump_depth, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_dump_color, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel_graphics->Add(chbox_gs_read_color, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_3dmonitor, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -628,6 +631,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) Ini.GSLogPrograms.SetValue(chbox_gs_log_prog->GetValue()); Ini.GSDumpDepthBuffer.SetValue(chbox_gs_dump_depth->GetValue()); Ini.GSDumpColorBuffers.SetValue(chbox_gs_dump_color->GetValue()); + Ini.GSReadColorBuffer.SetValue(chbox_gs_read_color->GetValue()); Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue()); Ini.GS3DTV.SetValue(chbox_gs_3dmonitor->GetValue()); Ini.PadHandlerMode.SetValue(cbox_pad_handler->GetSelection()); diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index cbfc6d9fe4..732d2b43d6 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -107,6 +107,7 @@ public: IniEntry GSLogPrograms; IniEntry GSDumpColorBuffers; IniEntry GSDumpDepthBuffer; + IniEntry GSReadColorBuffer; IniEntry GSVSyncEnable; IniEntry GS3DTV; @@ -182,6 +183,7 @@ public: GSLogPrograms.Init("GS_LogPrograms", path); GSDumpColorBuffers.Init("GS_DumpColorBuffers", path); GSDumpDepthBuffer.Init("GS_DumpDepthBuffer", path); + GSReadColorBuffer.Init("GS_GSReadColorBuffer", path); GSVSyncEnable.Init("GS_VSyncEnable", path); GS3DTV.Init("GS_3DTV", path); @@ -253,6 +255,7 @@ public: GSLogPrograms.Load(false); GSDumpColorBuffers.Load(false); GSDumpDepthBuffer.Load(false); + GSReadColorBuffer.Load(false); GSVSyncEnable.Load(false); GS3DTV.Load(false); @@ -325,6 +328,7 @@ public: GSLogPrograms.Save(); GSDumpColorBuffers.Save(); GSDumpDepthBuffer.Save(); + GSReadColorBuffer.Save(); GSVSyncEnable.Save(); GS3DTV.Save(); diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index 2ec10d0ce1..93ad015b74 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -42,6 +42,163 @@ Rpcs3App* TheApp; std::string simplify_path(const std::string& path, bool is_dir); +typedef be_t CGprofile; +typedef int CGbool; +typedef be_t CGresource; +typedef be_t CGenum; +typedef be_t CGtype; + +typedef be_t CgBinaryOffset; +typedef CgBinaryOffset CgBinaryEmbeddedConstantOffset; +typedef CgBinaryOffset CgBinaryFloatOffset; +typedef CgBinaryOffset CgBinaryStringOffset; +typedef CgBinaryOffset CgBinaryParameterOffset; + +// a few typedefs +typedef struct CgBinaryParameter CgBinaryParameter; +typedef struct CgBinaryEmbeddedConstant CgBinaryEmbeddedConstant; +typedef struct CgBinaryVertexProgram CgBinaryVertexProgram; +typedef struct CgBinaryFragmentProgram CgBinaryFragmentProgram; +typedef struct CgBinaryProgram CgBinaryProgram; + +// fragment programs have their constants embedded in the microcode +struct CgBinaryEmbeddedConstant +{ + be_t ucodeCount; // occurances + be_t ucodeOffset[1]; // offsets that need to be patched follow +}; + +// describe a binary program parameter (CgParameter is opaque) +struct CgBinaryParameter +{ + CGtype type; // cgGetParameterType() + CGresource res; // cgGetParameterResource() + CGenum var; // cgGetParameterVariability() + be_t resIndex; // cgGetParameterResourceIndex() + CgBinaryStringOffset name; // cgGetParameterName() + CgBinaryFloatOffset defaultValue; // default constant value + CgBinaryEmbeddedConstantOffset embeddedConst; // embedded constant information + CgBinaryStringOffset semantic; // cgGetParameterSemantic() + CGenum direction; // cgGetParameterDirection() + be_t paramno; // 0..n: cgGetParameterIndex() -1: globals + CGbool isReferenced; // cgIsParameterReferenced() + CGbool isShared; // cgIsParameterShared() +}; + +// attributes needed for vshaders +struct CgBinaryVertexProgram +{ + be_t instructionCount; // #instructions + be_t instructionSlot; // load address (indexed reads!) + be_t registerCount; // R registers count + be_t attributeInputMask; // attributes vs reads from + be_t attributeOutputMask; // attributes vs writes (uses SET_VERTEX_ATTRIB_OUTPUT_MASK bits) + be_t userClipMask; // user clip plane enables (for SET_USER_CLIP_PLANE_CONTROL) +}; + +typedef enum { + CgBinaryPTTNone = 0, + CgBinaryPTT2x16 = 1, + CgBinaryPTT1x32 = 2, +} CgBinaryPartialTexType; + +// attributes needed for pshaders +struct CgBinaryFragmentProgram +{ + be_t instructionCount; // #instructions + be_t attributeInputMask; // attributes fp reads (uses SET_VERTEX_ATTRIB_OUTPUT_MASK bits) + be_t partialTexType; // texid 0..15 use two bits each marking whether the texture format requires partial load: see CgBinaryPartialTexType + be_t texCoordsInputMask; // tex coords used by frag prog. (tex is bit n) + be_t texCoords2D; // tex coords that are 2d (tex is bit n) + be_t texCoordsCentroid; // tex coords that are centroid (tex is bit n) + unsigned char registerCount; // R registers count + unsigned char outputFromH0; // final color from R0 or H0 + unsigned char depthReplace; // fp generated z epth value + unsigned char pixelKill; // fp uses kill operations +}; + +#include "Emu/RSX/GL/GLFragmentProgram.h" +#include "Emu/RSX/GL/GLVertexProgram.h" +// defines a binary program -- *all* address/offsets are relative to the begining of CgBinaryProgram +struct CgBinaryProgram +{ + // vertex/pixel shader identification (BE/LE as well) + CGprofile profile; + + // binary revision (used to verify binary and driver structs match) + be_t binaryFormatRevision; + + // total size of this struct including profile and totalSize field! + be_t totalSize; + + // parameter usually queried using cgGet[First/Next]LeafParameter + be_t parameterCount; + CgBinaryParameterOffset parameterArray; + + // depending on profile points to a CgBinaryVertexProgram or CgBinaryFragmentProgram struct + CgBinaryOffset program; + + // raw ucode data + be_t ucodeSize; + CgBinaryOffset ucode; + + // variable length data follows + unsigned char data[1]; +}; + +void compile_shader(std::string path) +{ + ShaderVar var("r0.yz.x"); + var.symplify(); + LOG_ERROR(GENERAL, var.get().c_str()); + + u32 ptr; + { + wxFile f(path); + + if (!f.IsOpened()) + return; + + size_t size = f.Length(); + vm::ps3::init(); + ptr = vm::alloc(size); + f.Read(vm::get_ptr(ptr), size); + f.Close(); + } + + CgBinaryProgram& prog = vm::get_ref(ptr); + LOG_ERROR(GENERAL, "%d - %x", (u32)prog.profile, (u32)prog.binaryFormatRevision); + + std::string shader; + GLParamArray param_array; + u32 size; + + if (prog.profile == 7004) + { + CgBinaryFragmentProgram& fprog = vm::get_ref(ptr + prog.program); + + u32 ctrl = (fprog.outputFromH0 ? 0 : 0x40) | (fprog.depthReplace ? 0xe : 0); + + GLFragmentDecompilerThread(shader, param_array, ptr + prog.ucode, size, ctrl).Task(); + } + else + { + CgBinaryVertexProgram& vprog = vm::get_ref(ptr + prog.program); + + std::vector data; + be_t* vdata = vm::get_ptr>(ptr + prog.ucode); + for (u32 i = 0; i < prog.ucodeSize; ++i, ++vdata) + { + data.push_back(vdata[i]); + } + + GLVertexDecompilerThread(data, shader, param_array).Task(); + } + + LOG_ERROR(GENERAL, shader.c_str()); + vm::close(); +} + bool Rpcs3App::OnInit() { SetSendDbgCommandCallback([](DbgCommand id, CPUThread* t) @@ -146,6 +303,9 @@ bool Rpcs3App::OnInit() OnArguments(); + compile_shader("compile_shader0.spo"); + compile_shader("compile_shader1.spo"); + return true; } @@ -187,9 +347,9 @@ Rpcs3App::Rpcs3App() timeBeginPeriod(1); #endif - #if defined(__unix__) && !defined(__APPLE__) +#if defined(__unix__) && !defined(__APPLE__) XInitThreads(); - #endif +#endif } GameInfo CurGameInfo; From 114550b0f7abe854cae9767cb5580d0d21fcded4 Mon Sep 17 00:00:00 2001 From: raven02 Date: Wed, 17 Dec 2014 22:59:28 +0800 Subject: [PATCH 02/36] Temporary disable compile_shader() --- rpcs3/rpcs3.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index 93ad015b74..1793ebb7c6 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -48,7 +48,7 @@ typedef be_t CGresource; typedef be_t CGenum; typedef be_t CGtype; -typedef be_t CgBinaryOffset; +typedef be_t CgBinaryOffset; typedef CgBinaryOffset CgBinaryEmbeddedConstantOffset; typedef CgBinaryOffset CgBinaryFloatOffset; typedef CgBinaryOffset CgBinaryStringOffset; @@ -74,13 +74,13 @@ struct CgBinaryParameter CGtype type; // cgGetParameterType() CGresource res; // cgGetParameterResource() CGenum var; // cgGetParameterVariability() - be_t resIndex; // cgGetParameterResourceIndex() + be_t resIndex; // cgGetParameterResourceIndex() CgBinaryStringOffset name; // cgGetParameterName() CgBinaryFloatOffset defaultValue; // default constant value CgBinaryEmbeddedConstantOffset embeddedConst; // embedded constant information CgBinaryStringOffset semantic; // cgGetParameterSemantic() CGenum direction; // cgGetParameterDirection() - be_t paramno; // 0..n: cgGetParameterIndex() -1: globals + be_t paramno; // 0..n: cgGetParameterIndex() -1: globals CGbool isReferenced; // cgIsParameterReferenced() CGbool isShared; // cgIsParameterShared() }; @@ -303,8 +303,8 @@ bool Rpcs3App::OnInit() OnArguments(); - compile_shader("compile_shader0.spo"); - compile_shader("compile_shader1.spo"); + //compile_shader("compile_shader0.spo"); + //compile_shader("compile_shader1.spo"); return true; } From 52bf72787f5b7316af03a75fcc6a767150a8dec5 Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 18 Dec 2014 00:05:29 +0800 Subject: [PATCH 03/36] Revert VFS --- rpcs3/Emu/FS/VFS.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index 01489759a6..d963d9c91f 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -32,12 +32,21 @@ std::string simplify_path(const std::string& path, bool is_dir) { std::vector path_blocks = simplify_path_blocks(path); + std::string result; + if (path_blocks.empty()) - return ""; + return result; - std::string result = fmt::merge(path_blocks, "/"); + if (is_dir) + { + result = fmt::merge(path_blocks, "/"); + } + else + { + result = fmt::merge(std::vector(path_blocks.begin(), path_blocks.end() - 1), "/") + path_blocks[path_blocks.size() - 1]; + } - return is_dir ? result + "/" : result; + return result; } VFS::~VFS() From 37838a49ec825318765e0a4e2300e83dc7be7a8a Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 18 Dec 2014 00:10:20 +0800 Subject: [PATCH 04/36] Revert fmt::merge --- Utilities/StrFmt.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 8fbdeda31c..ae150c4f79 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -137,17 +137,14 @@ std::vector fmt::split(const std::string& source, std::initializer_ std::string fmt::merge(std::vector source, const std::string& separator) { - if (!source.size()) - return ""; - std::string result; - for (int i = 0; i < source.size() - 1; ++i) + for (auto &s : source) { - result += source[i] + separator; + result += s + separator; } - return result + source[source.size() - 1]; + return result; } std::string fmt::merge(std::initializer_list> sources, const std::string& separator) @@ -167,4 +164,4 @@ std::string fmt::tolower(std::string source) std::transform(source.begin(), source.end(), source.begin(), ::tolower); return source; -} \ No newline at end of file +} From ce853bc2521f8d005e1076d9619ffc84e3c6b92f Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Fri, 19 Dec 2014 13:31:52 +0200 Subject: [PATCH 05/36] cellSail updates and many various fixes --- rpcs3/Emu/CPU/CPUThreadManager.cpp | 2 +- rpcs3/Emu/SysCalls/LogBase.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 4 ++-- rpcs3/{ => Emu/SysCalls/Modules}/cellMic.h | 0 rpcs3/Emu/SysCalls/Modules/cellSail.cpp | 16 ++++++++++------ rpcs3/Emu/SysCalls/Modules/cellSail.h | 8 ++++---- rpcs3/Emu/SysCalls/lv2/sys_process.cpp | 3 ++- rpcs3/emucore.vcxproj | 4 ++-- rpcs3/emucore.vcxproj.filters | 6 +++--- 9 files changed, 25 insertions(+), 20 deletions(-) rename rpcs3/{ => Emu/SysCalls/Modules}/cellMic.h (100%) diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp index b745da0177..86608f2602 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.cpp +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -139,7 +139,7 @@ void CPUThreadManager::Exec() { std::lock_guard lock(m_mtx_thread); - for(u32 i=0; iExec(); } diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index 24b257d472..d3aa862efb 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -36,7 +36,7 @@ public: template __noinline void Notice(const char* fmt, Targs... args) const { - LogOutput(LogNotice, " : ", fmt::Format(fmt, args...)); + LogOutput(LogNotice, ": ", fmt::Format(fmt, args...)); } template __forceinline void Log(const char* fmt, Targs... args) const diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 8e08a1faf7..99ddaa6c98 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -195,7 +195,7 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location) } if (location == CELL_GCM_LOCATION_MAIN) { - if (index >= 1024*1024) { + if (index >= 1024 * 1024) { cellGcmSys->Error("cellGcmGetTimeStampLocation: Wrong main index (%d)", index); return 0; } @@ -300,7 +300,7 @@ u32 cellGcmGetTiledPitchSize(u32 size) { cellGcmSys->Log("cellGcmGetTiledPitchSize(size=%d)", size); - for (size_t i=0; i < sizeof(tiled_pitches)/sizeof(tiled_pitches[0]) - 1; i++) { + for (size_t i=0; i < sizeof(tiled_pitches) / sizeof(tiled_pitches[0]) - 1; i++) { if (tiled_pitches[i] < size && size <= tiled_pitches[i+1]) { return tiled_pitches[i+1]; } diff --git a/rpcs3/cellMic.h b/rpcs3/Emu/SysCalls/Modules/cellMic.h similarity index 100% rename from rpcs3/cellMic.h rename to rpcs3/Emu/SysCalls/Modules/cellMic.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp b/rpcs3/Emu/SysCalls/Modules/cellSail.cpp index b4d1eba987..d240fd2c62 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSail.cpp @@ -11,6 +11,7 @@ int cellSailMemAllocatorInitialize(vm::ptr pSelf, vm::ptr< cellSail->Warning("cellSailMemAllocatorInitialize(pSelf_addr=0x%x, pCallbacks_addr=0x%x)", pSelf.addr(), pCallbacks.addr()); pSelf->callbacks = pCallbacks; + // TODO: Create a cellSail thread return CELL_OK; } @@ -629,15 +630,18 @@ int cellSailPlayerCreateDescriptor(vm::ptr pSelf, s32 streamType //CellSailDescriptor *pDesc = new CellSailDescriptor(); //u32 descriptorAddress = pSelf->allocator->callbacks->pAlloc(pSelf->allocator->pArg, sizeof(CellSailDescriptor), sizeof(CellSailDescriptor)); u32 descriptorAddress = Memory.Alloc(sizeof(CellSailDescriptor), sizeof(CellSailDescriptor)); - cellSail->Error("Address: 0x%x", descriptorAddress); + //CellSailMemAllocatorFuncAlloc test = pSelf->allocator->callbacks->pAlloc.call(Emu.GetCPU()); + //u32 descriptorAddress2 = test(pSelf->allocator->pArg, sizeof(CellSailDescriptor), sizeof(CellSailDescriptor)); + //cellSail->Error("Address: 0x%x", pSelf->allocator->callbacks.addr()); + //cellSail->Error("Address 2: 0x%x", descriptorAddress2); //vm::ptr descriptor = vm::ptr::make(Memory.RealToVirtualAddr(&descriptorAddress)); - vm::ptr descriptor = vm::ptr::make(descriptorAddress); - //descriptor->streamType = streamType; - //descriptor->registered = false; + ppDesc = vm::ptr::make(descriptorAddress); + //cellSail->Error("Address 2: 0x%x", ppDesc.addr()); + ppDesc->streamType = streamType; + ppDesc->registered = false; - pSelf->descriptors = 0; + //pSelf->descriptors = 0; pSelf->repeatMode = 0; - //ppDesc = descriptor; //cellSail->Todo("pSelf_addr=0x%x, pDesc_addr=0x%x", pSelf.addr(), descriptor.addr()); //cellSailPlayerAddDescriptor(pSelf, ppDesc); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSail.h b/rpcs3/Emu/SysCalls/Modules/cellSail.h index eb518f110d..d0244fed6d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSail.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSail.h @@ -679,8 +679,8 @@ typedef void(*CellSailPlayerFuncNotified)(u32 pArg, vm::ptr event struct CellSailMemAllocatorFuncs { - CellSailMemAllocatorFuncAlloc pAlloc; - CellSailMemAllocatorFuncFree pFree; + vm::ptr pAlloc; + vm::ptr pFree; }; struct CellSailMemAllocator @@ -691,8 +691,8 @@ struct CellSailMemAllocator struct CellSailFuture { - u32 mutex_id; - u32 cond_id; + be_t mutex_id; + be_t cond_id; volatile be_t flags; be_t result; be_t userParam; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp index b041044f95..f74b438775 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp @@ -110,7 +110,8 @@ void sys_game_process_exitspawn(vm::ptr path, u32 argv_addr, u32 env else if (_path.substr(1, 8) == "dev_hdd1") device = 1; - Emu.BootGame(_path.c_str(), true, device); + if (device != 0) + Emu.BootGame(_path.c_str(), true, device); return; } diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index b0990ba2f6..79a1d44d55 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -283,7 +283,6 @@ - @@ -420,8 +419,9 @@ - + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 9335c19690..d32c333bf4 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -742,6 +742,9 @@ Emu\SysCalls\Modules + + Emu\SysCalls\Modules + Emu\SysCalls\Modules @@ -1252,9 +1255,6 @@ Crypto - - Emu\SysCalls\Modules - Emu\CPU\Cell From c5ca1991636be922e64d65ec63d8207e33961c61 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Fri, 19 Dec 2014 16:02:11 +0200 Subject: [PATCH 06/36] Implement CELL_SAVEDATA_FILEOP_WRITE_NOTRUNC --- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 79cfb5e18a..13f3b56690 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -279,7 +279,10 @@ s32 modifySaveDataFiles(vm::ptr funcFile, vm::ptrWarning("modifySaveDataFiles: File operation CELL_SAVEDATA_FILEOP_WRITE_NOTRUNC not yet implemented"); + // Does it really write without trunctation? + Emu.GetVFS().CreateFile(filepath); + file = Emu.GetVFS().OpenFile(filepath, vfsWrite); + fileGet->excSize = (u32)file->Write(buf, (u32)std::min(fileSet->fileSize, fileSet->fileBufSize)); // TODO: This may fail for big files because of the dest pointer. break; default: From 2545372a760c7ee5bc4fc84afb3f560af052961c Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Fri, 19 Dec 2014 17:19:23 +0200 Subject: [PATCH 07/36] Revert "Implement CELL_SAVEDATA_FILEOP_WRITE_NOTRUNC" This reverts commit c5ca1991636be922e64d65ec63d8207e33961c61. --- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 13f3b56690..79cfb5e18a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -279,10 +279,7 @@ s32 modifySaveDataFiles(vm::ptr funcFile, vm::ptrexcSize = (u32)file->Write(buf, (u32)std::min(fileSet->fileSize, fileSet->fileBufSize)); // TODO: This may fail for big files because of the dest pointer. + cellSysutil->Warning("modifySaveDataFiles: File operation CELL_SAVEDATA_FILEOP_WRITE_NOTRUNC not yet implemented"); break; default: From 29036504e6a0f6199ad9dba4f64c2f4e9ce730ba Mon Sep 17 00:00:00 2001 From: darkf Date: Fri, 19 Dec 2014 23:05:42 -0800 Subject: [PATCH 08/36] cellSail: fix wrong argument type --- rpcs3/Emu/SysCalls/Modules/cellSail.cpp | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp b/rpcs3/Emu/SysCalls/Modules/cellSail.cpp index d240fd2c62..c06942ecc7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSail.cpp @@ -617,28 +617,18 @@ int cellSailPlayerAddDescriptor(vm::ptr pSelf, vm::ptr pSelf, s32 streamType, vm::ptr pMediaInfo, vm::ptr pUri, vm::ptr ppDesc) +int cellSailPlayerCreateDescriptor(vm::ptr pSelf, s32 streamType, vm::ptr pMediaInfo, vm::ptr pUri, vm::ptr ppDesc) { cellSail->Todo("cellSailPlayerCreateDescriptor(pSelf_addr=0x%x, streamType=%d, pMediaInfo_addr=0x%x, pUri_addr=0x%x, ppDesc_addr=0x%x)", pSelf.addr(), streamType, pMediaInfo.addr(), pUri.addr(), ppDesc.addr()); - //cellSail->Todo("Descriptor: %i", sizeof(CellSailDescriptor)); - //cellSail->Todo("Player: %i", sizeof(CellSailPlayer)); - // TODO: Let the game allocate memory for the descriptor, setup the descriptor and pass it back to the game - //CellSailDescriptor *pDesc = new CellSailDescriptor(); - //u32 descriptorAddress = pSelf->allocator->callbacks->pAlloc(pSelf->allocator->pArg, sizeof(CellSailDescriptor), sizeof(CellSailDescriptor)); - u32 descriptorAddress = Memory.Alloc(sizeof(CellSailDescriptor), sizeof(CellSailDescriptor)); - //CellSailMemAllocatorFuncAlloc test = pSelf->allocator->callbacks->pAlloc.call(Emu.GetCPU()); - //u32 descriptorAddress2 = test(pSelf->allocator->pArg, sizeof(CellSailDescriptor), sizeof(CellSailDescriptor)); - //cellSail->Error("Address: 0x%x", pSelf->allocator->callbacks.addr()); - //cellSail->Error("Address 2: 0x%x", descriptorAddress2); - //vm::ptr descriptor = vm::ptr::make(Memory.RealToVirtualAddr(&descriptorAddress)); - ppDesc = vm::ptr::make(descriptorAddress); - //cellSail->Error("Address 2: 0x%x", ppDesc.addr()); - ppDesc->streamType = streamType; - ppDesc->registered = false; + u32 descriptorAddress = Memory.Alloc(sizeof(CellSailDescriptor), 1); + auto descriptor = vm::ptr::make(descriptorAddress); + *ppDesc = descriptorAddress; + descriptor->streamType = streamType; + descriptor->registered = false; //pSelf->descriptors = 0; pSelf->repeatMode = 0; From 980b9aaab3b525f30815b6eebe9321b9d3d57596 Mon Sep 17 00:00:00 2001 From: darkf Date: Sat, 20 Dec 2014 03:45:27 -0800 Subject: [PATCH 09/36] cellSaveData: allocate file list properly --- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 79cfb5e18a..becafff4c5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -215,11 +215,11 @@ void getSaveDataStat(SaveDataEntry entry, vm::ptr statGet) } } - // TODO: Fix the crash - // statGet's fileList doesn't seem to be initiliazed properly, when called by cellSaveDataAutoSave2, thus causing a crash during memcpy. - statGet->fileList = vm::bptr::make(be_t::make((u32)Memory.Alloc(sizeof(CellSaveDataFileStat) * (u32)fileEntries.size(), sizeof(CellSaveDataFileStat)))); - for (u32 i = 0; i < fileEntries.size(); i++) - memcpy(&statGet->fileList[i], &fileEntries[i], sizeof(CellSaveDataFileStat)); + statGet->fileList = vm::ptr::make((u32)Memory.Alloc(sizeof(CellSaveDataFileStat) * fileEntries.size(), 8)); + for (u32 i = 0; i < fileEntries.size(); i++) { + CellSaveDataFileStat *dst = &statGet->fileList[i]; + memcpy(dst, &fileEntries[i], sizeof(CellSaveDataFileStat)); + } } s32 modifySaveDataFiles(vm::ptr funcFile, vm::ptr result, const std::string& saveDataDir) From e0ff129dd173b932833491856816ff4574312def Mon Sep 17 00:00:00 2001 From: darkf Date: Sat, 20 Dec 2014 03:46:09 -0800 Subject: [PATCH 10/36] vfsLocalFile: log when Create fails --- rpcs3/Emu/FS/vfsLocalFile.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/FS/vfsLocalFile.cpp b/rpcs3/Emu/FS/vfsLocalFile.cpp index aea1e02e0c..0e716c40af 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.cpp +++ b/rpcs3/Emu/FS/vfsLocalFile.cpp @@ -75,7 +75,12 @@ bool vfsLocalFile::Create(const std::string& path) if(m != '/' && m != '\\' && !rExists(path)) // ??? { rFile f; - return f.Create(path); + if (!f.Create(path)) { + LOG_NOTICE(HLE, "vfsLocalFile::Create: couldn't create file"); + return false; + } + else + return true; } return true; From c76dd371f3d1c746e9e2c4eb0aba5f5782640549 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 21 Dec 2014 01:13:10 +0800 Subject: [PATCH 11/36] RSX: vertex data regression fix --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index c55c1962a4..a2c202f0c8 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -984,7 +984,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw) LOG_ERROR(RSX, "GLGSRender::EnableVertexData: Bad vertex data type (%d)!", m_vertex_data[i].type); } - if(0 && !m_vertex_data[i].addr) + if(!m_vertex_data[i].addr) { switch(m_vertex_data[i].type) { From c63f370d8bed36331a9a7a790907ebccade4c039 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 21 Dec 2014 01:14:27 +0800 Subject: [PATCH 12/36] regression fix #1 --- rpcs3/Emu/RSX/RSXThread.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 62606796a8..11f6b14668 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3,7 +3,7 @@ #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/RSX/GSManager.h" +#include "Emu/RSX/GSManage #include "RSXThread.h" #include "Emu/SysCalls/Callback.h" @@ -95,11 +95,11 @@ RSXVertexData::RSXVertexData() void RSXVertexData::Reset() { - //frequency = 0; - //stride = 0; - //size = 0; - //type = 0; - //addr = 0; + frequency = 0; + stride = 0; + size = 0; + type = 0; + addr = 0; data.clear(); } @@ -428,7 +428,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u8 v2 = a0 >> 16; u8 v3 = a0 >> 24; - //m_vertex_data[index].Reset(); + m_vertex_data[index].Reset(); m_vertex_data[index].size = 4; m_vertex_data[index].type = CELL_GCM_VERTEX_UB; m_vertex_data[index].data.push_back(v0); @@ -447,7 +447,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const float v0 = (float&)a0; float v1 = (float&)a1; - //m_vertex_data[index].Reset(); + m_vertex_data[index].Reset(); m_vertex_data[index].type = CELL_GCM_VERTEX_F; m_vertex_data[index].size = 2; u32 pos = m_vertex_data[index].data.size(); @@ -471,7 +471,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const float v2 = (float&)a2; float v3 = (float&)a3; - //m_vertex_data[index].Reset(); + m_vertex_data[index].Reset(); m_vertex_data[index].type = CELL_GCM_VERTEX_F; m_vertex_data[index].size = 4; u32 pos = m_vertex_data[index].data.size(); @@ -2418,4 +2418,4 @@ void RSXThread::WriteIO32(u32 addr, u32 value) { throw fmt::Format("%s(rsxio_addr=0x%x): RSXIO memory not mapped", __FUNCTION__, addr); } -} \ No newline at end of file +} From 612d11bd0387863293c217e12479d92fce36c5a7 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 21 Dec 2014 01:42:15 +0800 Subject: [PATCH 13/36] Minor fix --- rpcs3/Emu/RSX/RSXThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 11f6b14668..a16d538fef 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3,7 +3,7 @@ #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/RSX/GSManage +#include "Emu/RSX/GSManager.h #include "RSXThread.h" #include "Emu/SysCalls/Callback.h" From 7c9062fd3d6b7ff5c4edb0050f7d2b9c7fc59037 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 21 Dec 2014 01:54:01 +0800 Subject: [PATCH 14/36] fix :) --- rpcs3/Emu/RSX/RSXThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index a16d538fef..e3b1281fd6 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3,7 +3,7 @@ #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/RSX/GSManager.h +#include "Emu/RSX/GSManager.h" #include "RSXThread.h" #include "Emu/SysCalls/Callback.h" From 0506bf03525b84b0d8a7fa92e15ab8ad01523c3a Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 21 Dec 2014 07:30:30 +0800 Subject: [PATCH 15/36] Reapply fmt::merge change --- Utilities/StrFmt.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index ae150c4f79..c17d374fe5 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -137,14 +137,17 @@ std::vector fmt::split(const std::string& source, std::initializer_ std::string fmt::merge(std::vector source, const std::string& separator) { + if (!source.size()) + return ""; + std::string result; - for (auto &s : source) + for (int i = 0; i < source.size() - 1; ++i) { - result += s + separator; + result += source[i] + separator; } - return result; + return result + source[source.size() - 1]; } std::string fmt::merge(std::initializer_list> sources, const std::string& separator) From c6a00e157d2cdec92ec7a60b2bd40b6a7b35a066 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 21 Dec 2014 07:32:19 +0800 Subject: [PATCH 16/36] Reapply VFS change --- rpcs3/Emu/FS/VFS.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index d963d9c91f..01489759a6 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -32,21 +32,12 @@ std::string simplify_path(const std::string& path, bool is_dir) { std::vector path_blocks = simplify_path_blocks(path); - std::string result; - if (path_blocks.empty()) - return result; + return ""; - if (is_dir) - { - result = fmt::merge(path_blocks, "/"); - } - else - { - result = fmt::merge(std::vector(path_blocks.begin(), path_blocks.end() - 1), "/") + path_blocks[path_blocks.size() - 1]; - } + std::string result = fmt::merge(path_blocks, "/"); - return result; + return is_dir ? result + "/" : result; } VFS::~VFS() From 1e6a533ac78ec7696bd25e653e83c0a701bf2cc5 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 21 Dec 2014 07:35:29 +0800 Subject: [PATCH 17/36] PARAM.SFO path change --- rpcs3/Emu/SysCalls/Modules/cellGame.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 227d43ca96..30fdb0533d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -30,7 +30,7 @@ int cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptrsysSizeKB = 0; } - vfsFile f("/app_home/../PARAM.SFO"); + vfsFile f("/app_home/../../PARAM.SFO"); if (!f.IsOpened()) { cellGame->Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)"); @@ -100,7 +100,7 @@ int cellGamePatchCheck(vm::ptr size, u32 reserved_addr) size->sysSizeKB = 0; } - vfsFile f("/app_home/../PARAM.SFO"); + vfsFile f("/app_home/../../PARAM.SFO"); if (!f.IsOpened()) { cellGame->Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)"); @@ -335,7 +335,7 @@ int cellGameGetParamInt(u32 id, vm::ptr value) cellGame->Warning("cellGameGetParamInt(id=%d, value_addr=0x%x)", id, value.addr()); // TODO: Access through cellGame***Check functions - vfsFile f("/app_home/../PARAM.SFO"); + vfsFile f("/app_home/../../PARAM.SFO"); PSFLoader psf(f); if(!psf.Load(false)) return CELL_GAME_ERROR_FAILURE; @@ -358,7 +358,7 @@ int cellGameGetParamString(u32 id, vm::ptr buf, u32 bufsize) cellGame->Warning("cellGameGetParamString(id=%d, buf_addr=0x%x, bufsize=%d)", id, buf.addr(), bufsize); // TODO: Access through cellGame***Check functions - vfsFile f("/app_home/../PARAM.SFO"); + vfsFile f("/app_home/../../PARAM.SFO"); PSFLoader psf(f); if(!psf.Load(false)) return CELL_GAME_ERROR_FAILURE; From e98d1c0cb7bb0ff7708367ea463acf4cf0f4af76 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 21 Dec 2014 07:36:17 +0800 Subject: [PATCH 18/36] Trophy.trp path change --- rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp index 0cfbcf4f75..0b2f5331de 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp @@ -96,7 +96,7 @@ int sceNpTrophyCreateContext(vm::ptr context, vm::ptr // TODO: There are other possible errors // TODO: Is the TROPHY.TRP file necessarily located in this path? - vfsDir dir("/app_home/../TROPDIR/"); + vfsDir dir("/app_home/../../TROPDIR/"); if(!dir.IsOpened()) return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST; @@ -105,7 +105,7 @@ int sceNpTrophyCreateContext(vm::ptr context, vm::ptr { if (entry->flags & DirEntry_TypeDir) { - vfsStream* stream = Emu.GetVFS().OpenFile("/app_home/../TROPDIR/" + entry->name + "/TROPHY.TRP", vfsRead); + vfsStream* stream = Emu.GetVFS().OpenFile("/app_home/../../TROPDIR/" + entry->name + "/TROPHY.TRP", vfsRead); if (stream && stream->IsOpened()) { From 5f3b25b43a9ad62e3ba3a47942a0603b82961c2c Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 21 Dec 2014 12:56:38 +0200 Subject: [PATCH 19/36] Update ASMJIT --- asmjit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asmjit b/asmjit index 1318c9aff7..48da90ded7 160000 --- a/asmjit +++ b/asmjit @@ -1 +1 @@ -Subproject commit 1318c9aff7137b30aec7dee2ababb2b313ae0f06 +Subproject commit 48da90ded775fa2ba0fd3f15522890ad631ad6de From b2b31b04211216726d23c412c2a5ff5e6b450d71 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 21 Dec 2014 12:58:30 +0200 Subject: [PATCH 20/36] Update FFMPEG --- ffmpeg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffmpeg b/ffmpeg index 352fdfbbfa..79a2d7a9f7 160000 --- a/ffmpeg +++ b/ffmpeg @@ -1 +1 @@ -Subproject commit 352fdfbbfa6d7b26142f00b43d7e1802a03c68a8 +Subproject commit 79a2d7a9f780ad27d1622010cb1cb8396c3701e9 From b3be4d11e3d2572c50ea168c47cf4d29dc3509e5 Mon Sep 17 00:00:00 2001 From: Oil Date: Sun, 21 Dec 2014 20:29:51 +0400 Subject: [PATCH 21/36] Show more information in GSFrame, some changes in cellAudio --- rpcs3/Emu/Audio/cellAudio.h | 2 + rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 103 ++++++++++++++++++++++- rpcs3/Emu/System.cpp | 14 ++- rpcs3/Emu/System.h | 12 +++ rpcs3/Gui/GLGSFrame.cpp | 5 +- rpcs3/Gui/GameViewer.h | 3 +- 6 files changed, 130 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/Audio/cellAudio.h b/rpcs3/Emu/Audio/cellAudio.h index ff6e463065..b448dcfe16 100644 --- a/rpcs3/Emu/Audio/cellAudio.h +++ b/rpcs3/Emu/Audio/cellAudio.h @@ -82,6 +82,8 @@ struct AudioPortConfig u64 attr; u64 tag; u64 counter; // copy of global counter + u32 addr; + u32 read_index_addr; }; struct AudioConfig //custom structure diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index f302a9fc2f..8186beef87 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -527,6 +527,8 @@ int cellAudioPortOpen(vm::ptr audioParam, vm::ptr portN port.channel = (u8)audioParam->nChannel; port.block = (u8)audioParam->nBlock; port.attr = audioParam->attr; + port.addr = m_config.m_buffer + (128 * 1024 * i); + port.read_index_addr = m_config.m_indexes + (sizeof(u64) * i); if (port.attr & CELL_AUDIO_PORTATTR_INITLEVEL) { port.level = audioParam->level; @@ -579,8 +581,8 @@ int cellAudioGetPortConfig(u32 portNum, vm::ptr portConfig) portConfig->nChannel = port.channel; portConfig->nBlock = port.block; portConfig->portSize = port.channel * port.block * 256 * sizeof(float); - portConfig->portAddr = m_config.m_buffer + (128 * 1024 * portNum); // 0x20020000 - portConfig->readIndexAddr = m_config.m_indexes + (sizeof(u64) * portNum); // 0x20010010 on ps3 + portConfig->portAddr = port.addr; // 0x20020000 + portConfig->readIndexAddr = port.read_index_addr; // 0x20010010 on ps3 cellAudio->Log("*** port config: nChannel=%d, nBlock=%d, portSize=0x%x, portAddr=0x%x, readIndexAddr=0x%x", (u32)portConfig->nChannel, (u32)portConfig->nBlock, (u32)portConfig->portSize, (u32)portConfig->portAddr, (u32)portConfig->readIndexAddr); @@ -731,6 +733,28 @@ int cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr tag) int cellAudioSetPortLevel(u32 portNum, float level) { cellAudio->Todo("cellAudioSetPortLevel(portNum=0x%x, level=%f)", portNum, level); + + AudioPortConfig& port = m_config.m_ports[portNum]; + + if (portNum >= m_config.AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!port.m_is_audio_port_opened) + { + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + } + + if (!port.m_is_audio_port_started) + { + return CELL_AUDIO_ERROR_PORT_NOT_RUN; + } + + std::lock_guard lock(audioMutex); + + port.level = level; // TODO + return CELL_OK; } @@ -841,21 +865,94 @@ int cellAudioRemoveNotifyEventQueueEx(u64 key, u32 iFlags) return CELL_OK; } -int cellAudioAddData(u32 portNum, vm::ptr> src, u32 samples, float volume) +int cellAudioAddData(u32 portNum, vm::ptr src, u32 samples, float volume) { cellAudio->Todo("cellAudioAddData(portNum=0x%x, src_addr=0x%x, samples=%d, volume=%f)", portNum, src.addr(), samples, volume); + + AudioPortConfig& port = m_config.m_ports[portNum]; + + if (portNum >= m_config.AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!port.m_is_audio_port_opened) + { + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + } + + if (!port.m_is_audio_port_started) + { + return CELL_AUDIO_ERROR_PORT_NOT_RUN; + } + + std::lock_guard lock(audioMutex); + + //u32 addr = port.addr; + //for (u32 i = 0; i < samples; i++) + //{ + // vm::write32(addr, src[i]); + // addr += port.channel * port.block * sizeof(float); + //} + + m_config.m_buffer = src.addr(); // TODO: write data from src in selected port + return CELL_OK; } int cellAudioAdd2chData(u32 portNum, vm::ptr> src, u32 samples, float volume) { cellAudio->Todo("cellAudioAdd2chData(portNum=0x%x, src_addr=0x%x, samples=%d, volume=%f)", portNum, src.addr(), samples, volume); + + AudioPortConfig& port = m_config.m_ports[portNum]; + + if (portNum >= m_config.AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!port.m_is_audio_port_opened) + { + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + } + + if (!port.m_is_audio_port_started) + { + return CELL_AUDIO_ERROR_PORT_NOT_RUN; + } + + std::lock_guard lock(audioMutex); + + m_config.m_buffer = src.addr(); // TODO + return CELL_OK; } int cellAudioAdd6chData(u32 portNum, vm::ptr> src, float volume) { cellAudio->Todo("cellAudioAdd6chData(portNum=0x%x, src_addr=0x%x, volume=%f)", portNum, src.addr(), volume); + + AudioPortConfig& port = m_config.m_ports[portNum]; + + if (portNum >= m_config.AUDIO_PORT_COUNT) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!port.m_is_audio_port_opened) + { + return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + } + + if (!port.m_is_audio_port_started) + { + return CELL_AUDIO_ERROR_PORT_NOT_RUN; + } + + std::lock_guard lock(audioMutex); + + m_config.m_buffer = src.addr(); // TODO + return CELL_OK; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 4c271aaac9..05adca06f5 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -101,6 +101,11 @@ void Emulator::SetTitleID(const std::string& id) m_title_id = id; } +void Emulator::SetTitle(const std::string& title) +{ + m_title = title; +} + void Emulator::CheckStatus() { std::vector& threads = GetCPU().GetThreads(); @@ -149,7 +154,7 @@ bool Emulator::BootGame(const std::string& path, bool direct, int device) "/BOOT.BIN", "/PS3_GAME/USRDIR/EBOOT.BIN", "/USRDIR/EBOOT.BIN", - "/EBOOT.BIN", + "/EBOOT.BIN" }; auto curpath = path; @@ -228,7 +233,7 @@ void Emulator::Load() } LOG_NOTICE(LOADER, " ");//used to be skip_line - vfsFile sfo("/app_home/../PARAM.SFO"); + vfsFile sfo("/app_home/../../PARAM.SFO"); PSFLoader psf(sfo); psf.Load(false); std::string title = psf.GetString("TITLE"); @@ -236,6 +241,9 @@ void Emulator::Load() LOG_NOTICE(LOADER, "Title: %s", title.c_str()); LOG_NOTICE(LOADER, "Serial: %s", title_id.c_str()); + title.length() ? SetTitle(title) : SetTitle(m_path); + SetTitleID(title_id); + // bdvd inserting imitation vfsFile f1("/app_home/../dev_bdvd.path"); if (f1.IsOpened()) @@ -271,7 +279,7 @@ void Emulator::Load() } // trying to load some info from PARAM.SFO - vfsFile f2("/app_home/../PARAM.SFO"); + vfsFile f2("/app_home/../../PARAM.SFO"); if (f2.IsOpened()) { PSFLoader psf(f2); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 06046cc1ce..b9a9d4b638 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -115,6 +115,7 @@ public: std::string m_elf_path; std::string m_emu_path; std::string m_title_id; + std::string m_title; s32 m_sdk_version; Emulator(); @@ -123,6 +124,7 @@ public: void Init(); void SetPath(const std::string& path, const std::string& elf_path = ""); void SetTitleID(const std::string& id); + void SetTitle(const std::string& title); std::string GetPath() const { @@ -134,6 +136,16 @@ public: return m_emu_path; } + std::string GetTitleID() const + { + return m_title_id; + } + + std::string GetTitle() const + { + return m_title; + } + void SetEmulatorPath(const std::string& path) { m_emu_path = path; diff --git a/rpcs3/Gui/GLGSFrame.cpp b/rpcs3/Gui/GLGSFrame.cpp index 8a0fc1aab7..c3f34c14eb 100644 --- a/rpcs3/Gui/GLGSFrame.cpp +++ b/rpcs3/Gui/GLGSFrame.cpp @@ -1,5 +1,6 @@ #include "stdafx_gui.h" #include "Emu/Memory/Memory.h" +#include "Emu/System.h" #include "GLGSFrame.h" #include "Utilities/Timer.h" @@ -61,10 +62,12 @@ void GLGSFrame::Flip(void* context) canvas->SwapBuffers(); m_frames++; + const std::string sub_title = Emu.GetTitle() += Emu.GetTitleID().length() ? " [" + Emu.GetTitleID() + "] | " : " | "; + if (fps_t.GetElapsedTimeInSec() >= 0.5) { // can freeze on exit - SetTitle(wxString::Format("FPS: %.2f", (double)m_frames / fps_t.GetElapsedTimeInSec())); + SetTitle(sub_title + wxString::Format("FPS: %.2f", (double)m_frames / fps_t.GetElapsedTimeInSec())); m_frames = 0; fps_t.Start(); } diff --git a/rpcs3/Gui/GameViewer.h b/rpcs3/Gui/GameViewer.h index 21c90077b3..b0b968b7e9 100644 --- a/rpcs3/Gui/GameViewer.h +++ b/rpcs3/Gui/GameViewer.h @@ -157,7 +157,7 @@ public: { list->DeleteAllItems(); list->SetImageList(m_img_list, wxIMAGE_LIST_SMALL); - for(int c=0; cGetColumnCount(); ++c) + for(int c=1; cGetColumnCount(); ++c) { Column* col = GetColumnByPos(c); @@ -175,7 +175,6 @@ public: list->SetItemData(i, i); } list->SetItem(i, c, fmt::FromUTF8(col->data[i])); - list->SetItem(i, 0, wxEmptyString); // don't insert icon path list->SetItemColumnImage(i, 0, m_icon_indexes[i]); } } From 688e5a3af61ca78fab59a45d6a8bd673e583bcb8 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Sun, 21 Dec 2014 21:44:07 +0200 Subject: [PATCH 22/36] Fix compiling --- rpcs3/Emu/Cell/SPURecompilerCore.cpp | 2 +- rpcs3/Gui/MemoryViewer.cpp | 60 ++++++++++++++-------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/rpcs3/Emu/Cell/SPURecompilerCore.cpp b/rpcs3/Emu/Cell/SPURecompilerCore.cpp index c5edf35a7b..8d733bd8b4 100644 --- a/rpcs3/Emu/Cell/SPURecompilerCore.cpp +++ b/rpcs3/Emu/Cell/SPURecompilerCore.cpp @@ -25,7 +25,7 @@ SPURecompilerCore::SPURecompilerCore(SPUThread& cpu) memset(entry, 0, sizeof(entry)); X86CpuInfo inf; X86CpuUtil::detect(&inf); - if (!inf.hasFeature(kX86CpuFeatureSse41)) + if (!inf.hasFeature(kX86CpuFeatureSSE4_1)) { LOG_ERROR(SPU, "SPU JIT requires SSE4.1 instruction set support"); Emu.Pause(); diff --git a/rpcs3/Gui/MemoryViewer.cpp b/rpcs3/Gui/MemoryViewer.cpp index 73b57c835e..59f3917713 100644 --- a/rpcs3/Gui/MemoryViewer.cpp +++ b/rpcs3/Gui/MemoryViewer.cpp @@ -22,12 +22,12 @@ MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent) wxStaticBoxSizer* s_tools_mem = new wxStaticBoxSizer(wxHORIZONTAL, this, "Memory Viewer Options"); wxStaticBoxSizer* s_tools_mem_addr = new wxStaticBoxSizer(wxHORIZONTAL, this, "Address"); - t_addr = new wxTextCtrl(this, wxID_ANY, "00000000", wxDefaultPosition, wxSize(60,-1)); + t_addr = new wxTextCtrl(this, wxID_ANY, "00000000", wxDefaultPosition, wxSize(60, -1)); t_addr->SetMaxLength(8); s_tools_mem_addr->Add(t_addr); wxStaticBoxSizer* s_tools_mem_bytes = new wxStaticBoxSizer(wxHORIZONTAL, this, "Bytes"); - sc_bytes = new wxSpinCtrl(this, wxID_ANY, "16", wxDefaultPosition, wxSize(44,-1)); + sc_bytes = new wxSpinCtrl(this, wxID_ANY, "16", wxDefaultPosition, wxSize(44, -1)); sc_bytes->SetRange(1, 16); s_tools_mem_bytes->Add(sc_bytes); @@ -49,8 +49,8 @@ MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent) wxStaticBoxSizer* s_tools_img = new wxStaticBoxSizer(wxHORIZONTAL, this, "Raw Image Preview"); wxStaticBoxSizer* s_tools_img_size = new wxStaticBoxSizer(wxHORIZONTAL, this, "Size"); - sc_img_size_x = new wxSpinCtrl(this, wxID_ANY, "256", wxDefaultPosition, wxSize(60,-1)); - sc_img_size_y = new wxSpinCtrl(this, wxID_ANY, "256", wxDefaultPosition, wxSize(60,-1)); + sc_img_size_x = new wxSpinCtrl(this, wxID_ANY, "256", wxDefaultPosition, wxSize(60, -1)); + sc_img_size_y = new wxSpinCtrl(this, wxID_ANY, "256", wxDefaultPosition, wxSize(60, -1)); s_tools_img_size->Add(sc_img_size_x); s_tools_img_size->Add(new wxStaticText(this, wxID_ANY, " x ")); s_tools_img_size->Add(sc_img_size_y); @@ -72,7 +72,7 @@ MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent) //Tools: Run tools wxStaticBoxSizer* s_tools_buttons = new wxStaticBoxSizer(wxVERTICAL, this, "Tools"); - wxButton* b_img = new wxButton(this, wxID_ANY, "View\nimage", wxDefaultPosition, wxSize(52,-1)); + wxButton* b_img = new wxButton(this, wxID_ANY, "View\nimage", wxDefaultPosition, wxSize(52, -1)); s_tools_buttons->Add(b_img); //Tools: Tools = Memory Viewer Options + Raw Image Preview Options + Buttons @@ -108,8 +108,8 @@ MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent) //Memory Panel: Set size of the wxTextCtrl's int x, y; t_mem_hex->GetTextExtent(wxT("T"), &x, &y); - t_mem_hex->SetMinSize(wxSize(x * 3*m_colcount + 6, 228)); - t_mem_hex->SetMaxSize(wxSize(x * 3*m_colcount + 6, 228)); + t_mem_hex->SetMinSize(wxSize(x * 3 * m_colcount + 6, 228)); + t_mem_hex->SetMaxSize(wxSize(x * 3 * m_colcount + 6, 228)); t_mem_ascii->SetMinSize(wxSize(x * m_colcount + 6, 228)); t_mem_ascii->SetMaxSize(wxSize(x * m_colcount + 6, 228)); @@ -156,8 +156,8 @@ void MemoryViewerPanel::OnChangeToolsBytes(wxCommandEvent& event) int x, y; t_mem_hex->GetTextExtent(wxT("T"), &x, &y); - t_mem_hex->SetMinSize(wxSize(x * 3*m_colcount + 6, 228)); - t_mem_hex->SetMaxSize(wxSize(x * 3*m_colcount + 6, 228)); + t_mem_hex->SetMinSize(wxSize(x * 3 * m_colcount + 6, 228)); + t_mem_hex->SetMaxSize(wxSize(x * 3 * m_colcount + 6, 228)); t_mem_ascii->SetMinSize(wxSize(x * m_colcount + 6, 228)); t_mem_ascii->SetMaxSize(wxSize(x * m_colcount + 6, 228)); this->Layout(); @@ -242,43 +242,43 @@ void MemoryViewerPanel::ShowImage(wxWindow* parent, u32 addr, int mode, u32 widt break; case(1): // ARGB - for (u32 y=0; y Date: Sun, 21 Dec 2014 22:42:15 +0200 Subject: [PATCH 23/36] Implemented frame limiter Some errors in unpkg replaced with warnings --- rpcs3/Crypto/unpkg.cpp | 8 ++--- rpcs3/Emu/RSX/RSXThread.cpp | 20 +++++++++++ rpcs3/Emu/RSX/RSXThread.h | 3 ++ rpcs3/Gui/MainFrame.cpp | 9 +++++ rpcs3/Ini.h | 4 +++ rpcs3/emucore.vcxproj.filters | 66 +++++++++++++++++------------------ rpcs3/rpcs3.vcxproj | 3 ++ rpcs3/rpcs3.vcxproj.filters | 3 ++ 8 files changed, 79 insertions(+), 37 deletions(-) diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index 39f4bf99a8..5d7846046f 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -43,13 +43,13 @@ bool CheckHeader(rFile& pkg_f, PKGHeader* m_header) } if (m_header->pkg_size != pkg_f.Length()) { - LOG_ERROR(LOADER, "PKG: File size mismatch."); - return false; + LOG_WARNING(LOADER, "PKG: File size mismatch."); + //return false; } if (m_header->data_size + m_header->data_offset + 0x60 != pkg_f.Length()) { - LOG_ERROR(LOADER, "PKG: Data size mismatch."); - return false; + LOG_WARNING(LOADER, "PKG: Data size mismatch."); + //return false; } return true; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index e3b1281fd6..328b7a7b73 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -335,6 +335,26 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const }); } + auto sync = [&]() + { + double limit; + switch (Ini.GSFrameLimit.GetValue()) + { + case 1: limit = 50.0; break; + case 2: limit = 59.94; break; + case 3: limit = m_fps_limit; break; //TODO + + case 0: + default: + return; + } + + std::this_thread::sleep_for(std::chrono::milliseconds((s64)(1000.0 / limit - m_timer_sync.GetElapsedTimeInMilliSec()))); + m_timer_sync.Start(); + }; + + sync(); + //Emu.Pause(); } break; diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index e93af15a85..0f132e8c11 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -7,6 +7,7 @@ #include #include "Utilities/SSemaphore.h" #include "Utilities/Thread.h" +#include "Utilities/Timer.h" enum Method { @@ -101,6 +102,8 @@ public: protected: std::stack m_call_stack; CellGcmControl* m_ctrl; + Timer m_timer_sync; + double m_fps_limit = 59.94; public: GcmTileInfo m_tiles[m_tiles_count]; diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index b64f1aad56..6a9ff7013c 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -378,6 +378,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxStaticBoxSizer* s_round_gs_render = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Render")); wxStaticBoxSizer* s_round_gs_res = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Default resolution")); wxStaticBoxSizer* s_round_gs_aspect = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Default aspect ratio")); + wxStaticBoxSizer* s_round_gs_frame_limit = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Frame limit")); // Input / Output wxStaticBoxSizer* s_round_io_pad_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Pad Handler")); @@ -402,6 +403,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxComboBox* cbox_gs_render = new wxComboBox(p_graphics, wxID_ANY); wxComboBox* cbox_gs_resolution = new wxComboBox(p_graphics, wxID_ANY); wxComboBox* cbox_gs_aspect = new wxComboBox(p_graphics, wxID_ANY); + wxComboBox* cbox_gs_frame_limit = new wxComboBox(p_graphics, wxID_ANY); wxComboBox* cbox_pad_handler = new wxComboBox(p_io, wxID_ANY); wxComboBox* cbox_keyboard_handler = new wxComboBox(p_io, wxID_ANY); wxComboBox* cbox_mouse_handler = new wxComboBox(p_io, wxID_ANY); @@ -448,6 +450,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) cbox_gs_aspect->Append("4:3"); cbox_gs_aspect->Append("16:9"); + for (auto item : { "Off", "50", "59.94", "Auto" }) + cbox_gs_frame_limit->Append(item); + cbox_pad_handler->Append("Null"); cbox_pad_handler->Append("Windows"); #if defined (_WIN32) @@ -523,6 +528,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) cbox_gs_render ->SetSelection(Ini.GSRenderMode.GetValue()); cbox_gs_resolution ->SetSelection(ResolutionIdToNum(Ini.GSResolution.GetValue()) - 1); cbox_gs_aspect ->SetSelection(Ini.GSAspectRatio.GetValue() - 1); + cbox_gs_frame_limit ->SetSelection(Ini.GSFrameLimit.GetValue()); cbox_pad_handler ->SetSelection(Ini.PadHandlerMode.GetValue()); cbox_keyboard_handler->SetSelection(Ini.KeyboardHandlerMode.GetValue()); cbox_mouse_handler ->SetSelection(Ini.MouseHandlerMode.GetValue()); @@ -545,6 +551,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) s_round_gs_render->Add(cbox_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_gs_res->Add(cbox_gs_resolution, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_gs_aspect->Add(cbox_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs_frame_limit->Add(cbox_gs_frame_limit, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_io_pad_handler->Add(cbox_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_io_keyboard_handler->Add(cbox_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -567,6 +574,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) s_subpanel_graphics->Add(s_round_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(s_round_gs_res, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(s_round_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel_graphics->Add(s_round_gs_frame_limit, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_log_prog, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_dump_depth, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_graphics->Add(chbox_gs_dump_color, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -628,6 +636,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) Ini.GSRenderMode.SetValue(cbox_gs_render->GetSelection()); Ini.GSResolution.SetValue(ResolutionNumToId(cbox_gs_resolution->GetSelection() + 1)); Ini.GSAspectRatio.SetValue(cbox_gs_aspect->GetSelection() + 1); + Ini.GSFrameLimit.SetValue(cbox_gs_frame_limit->GetSelection()); Ini.GSLogPrograms.SetValue(chbox_gs_log_prog->GetValue()); Ini.GSDumpDepthBuffer.SetValue(chbox_gs_dump_depth->GetValue()); Ini.GSDumpColorBuffers.SetValue(chbox_gs_dump_color->GetValue()); diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index 732d2b43d6..6b3b9b1e02 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -104,6 +104,7 @@ public: IniEntry GSRenderMode; IniEntry GSResolution; IniEntry GSAspectRatio; + IniEntry GSFrameLimit; IniEntry GSLogPrograms; IniEntry GSDumpColorBuffers; IniEntry GSDumpDepthBuffer; @@ -180,6 +181,7 @@ public: GSRenderMode.Init("GS_RenderMode", path); GSResolution.Init("GS_Resolution", path); GSAspectRatio.Init("GS_AspectRatio", path); + GSFrameLimit.Init("GS_FrameLimit", path); GSLogPrograms.Init("GS_LogPrograms", path); GSDumpColorBuffers.Init("GS_DumpColorBuffers", path); GSDumpDepthBuffer.Init("GS_DumpDepthBuffer", path); @@ -252,6 +254,7 @@ public: GSRenderMode.Load(1); GSResolution.Load(4); GSAspectRatio.Load(2); + GSFrameLimit.Load(0); GSLogPrograms.Load(false); GSDumpColorBuffers.Load(false); GSDumpDepthBuffer.Load(false); @@ -325,6 +328,7 @@ public: GSRenderMode.Save(); GSResolution.Save(); GSAspectRatio.Save(); + GSFrameLimit.Save(); GSLogPrograms.Save(); GSDumpColorBuffers.Save(); GSDumpDepthBuffer.Save(); diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index d32c333bf4..9ca5b30f98 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -69,16 +69,16 @@ {1d9e6fc4-9a79-4329-a8b5-081e24822aaa} - + {6674e2ab-90cd-47de-a852-d21643ab18c2} - + {fadb4b36-57af-4583-891d-d22ff369e266} - + {4adca4fa-b90f-4662-9eb0-1d29cf3cd2eb} - + {6f1da5b2-52c5-416b-9b5c-b9897bc1b300} @@ -558,37 +558,37 @@ Emu\SysCalls\Modules - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX Emu\SysCalls\lv2 @@ -1127,58 +1127,58 @@ Emu\SysCalls - GPU\RSX\Null + Emu\GPU\RSX\Null - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX\GL + Emu\GPU\RSX\GL - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX - GPU\RSX + Emu\GPU\RSX Emu\SysCalls\lv2 diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 946b6cb66e..76bec7e9fb 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -231,6 +231,9 @@ {c4a10229-4712-4bd2-b63e-50d93c67a038} + + + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 5fce1aa362..f840ef10d7 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -192,4 +192,7 @@ Gui + + + \ No newline at end of file From 52467c54e33b07ba40578aaa28662a3da57aa57a Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 22 Dec 2014 05:37:43 +0800 Subject: [PATCH 24/36] Fix callback hangup in Adreko game series --- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 99ddaa6c98..94d14f347e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -1172,7 +1172,7 @@ s32 cellGcmCallback(vm::ptr context, u32 count) GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); - if (0) + if (1) { auto& ctrl = vm::get_ref(gcm_info.control_addr); be_t res = be_t::make(context->current - context->begin - ctrl.put.read_relaxed()); From 7464843e53b00e24877212e45a7629d82559324a Mon Sep 17 00:00:00 2001 From: Dante38490 Date: Mon, 22 Dec 2014 00:06:25 +0100 Subject: [PATCH 25/36] Update MainFrame.cpp Fix Size Setting panel for Tab Graphic --- rpcs3/Gui/MainFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 6a9ff7013c..ee19b62c23 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -342,7 +342,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxDialog diag(this, wxID_ANY, "Settings", wxDefaultPosition); static const u32 width = 425; - static const u32 height = 400; + static const u32 height = 460; // Settings panels wxNotebook* nb_config = new wxNotebook(&diag, wxID_ANY, wxPoint(6,6), wxSize(width, height)); From e1ea7a28c3718fb44ae3fa77a60a848d34c69158 Mon Sep 17 00:00:00 2001 From: DHrpcs3 Date: Mon, 22 Dec 2014 01:10:22 +0200 Subject: [PATCH 26/36] Fixed condition decompilation in vertex & fragment shaders Added 30 & 60 modes to frame limiter --- rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp | 2 +- rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 4 ++-- rpcs3/Emu/RSX/RSXThread.cpp | 6 ++++-- rpcs3/Gui/MainFrame.cpp | 2 +- rpcs3/rpcs3.vcxproj | 3 --- rpcs3/rpcs3.vcxproj.filters | 3 --- 6 files changed, 8 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index e62608832d..984aa82eee 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -47,7 +47,7 @@ void GLFragmentDecompilerThread::SetDst(std::string code, bool append_mask) std::string dest = AddReg(dst.dest_reg, dst.fp16) + "$m"; - AddCodeCond(dest, code); + AddCodeCond(Format(dest), code); //AddCode("$ifcond " + dest + code + (append_mask ? "$m;" : ";")); if (dst.set_cond) diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index fe99a79847..186c70ed29 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -165,7 +165,7 @@ void GLVertexDecompilerThread::SetDST(bool is_sca, std::string value) //code += dest + value; //AddCode(code + ";"); - AddCodeCond(dest, value); + AddCodeCond(Format(dest), value); } std::string GLVertexDecompilerThread::GetFunc() @@ -454,7 +454,7 @@ std::string GLVertexDecompilerThread::BuildCode() std::string fp; - for (int i = m_funcs.size() - 1; i>0; --i) + for (int i = m_funcs.size() - 1; i > 0; --i) { fp += fmt::Format("void %s();\n", m_funcs[i].name.c_str()); } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 328b7a7b73..7e92b8642b 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -340,9 +340,11 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const double limit; switch (Ini.GSFrameLimit.GetValue()) { - case 1: limit = 50.0; break; + case 1: limit = 50.; break; case 2: limit = 59.94; break; - case 3: limit = m_fps_limit; break; //TODO + case 3: limit = 30.; break; + case 4: limit = 60.; break; + case 5: limit = m_fps_limit; break; //TODO case 0: default: diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 6a9ff7013c..2530f1de4b 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -450,7 +450,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) cbox_gs_aspect->Append("4:3"); cbox_gs_aspect->Append("16:9"); - for (auto item : { "Off", "50", "59.94", "Auto" }) + for (auto item : { "Off", "50", "59.94", "30", "60", "Auto" }) cbox_gs_frame_limit->Append(item); cbox_pad_handler->Append("Null"); diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 76bec7e9fb..946b6cb66e 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -231,9 +231,6 @@ {c4a10229-4712-4bd2-b63e-50d93c67a038} - - - diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index f840ef10d7..5fce1aa362 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -192,7 +192,4 @@ Gui - - - \ No newline at end of file From 642e850dfe57f16c32a7af3c2115c3d29f6f4fd3 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Wed, 24 Dec 2014 20:47:56 +0200 Subject: [PATCH 27/36] cellSail PAMF creation and 3D availability fix --- rpcs3/Emu/RSX/sysutil_video.h | 11 ++-- rpcs3/Emu/SysCalls/Modules/cellPamf.h | 2 + rpcs3/Emu/SysCalls/Modules/cellSail.cpp | 56 +++++++++++++++++++-- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 10 ++-- 5 files changed, 65 insertions(+), 16 deletions(-) diff --git a/rpcs3/Emu/RSX/sysutil_video.h b/rpcs3/Emu/RSX/sysutil_video.h index e501f73b03..9975a33046 100644 --- a/rpcs3/Emu/RSX/sysutil_video.h +++ b/rpcs3/Emu/RSX/sysutil_video.h @@ -31,11 +31,12 @@ enum CellVideoOutResolutionId CELL_VIDEO_OUT_RESOLUTION_1440x1080 = 11, CELL_VIDEO_OUT_RESOLUTION_1280x1080 = 12, CELL_VIDEO_OUT_RESOLUTION_960x1080 = 13, - CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING = 0x81, - CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING = 0x88, - CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING = 0x89, - CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING = 0x8a, - CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING = 0x8b, + CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING = 0x81, + CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING = 0x88, + CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING = 0x89, + CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING = 0x8a, + CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING = 0x8b, + CELL_VIDEO_OUT_RESOLUTION_720_SIMULVIEW_FRAME_PACKING = 0x91, }; enum CellVideoOutScanMode diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.h b/rpcs3/Emu/SysCalls/Modules/cellPamf.h index 13a051285c..33904beb97 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.h @@ -391,3 +391,5 @@ struct CellPamfReader }; static_assert(sizeof(CellPamfReader) == 128, "Invalid CellPamfReader size"); + +s32 cellPamfReaderInitialize(vm::ptr pSelf, vm::ptr pAddr, u64 fileSize, u32 attribute); \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp b/rpcs3/Emu/SysCalls/Modules/cellSail.cpp index c06942ecc7..3c5bdad60e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSail.cpp @@ -1,8 +1,10 @@ #include "stdafx.h" #include "Emu/Memory/Memory.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/FS/vfsFile.h" #include "cellSail.h" +#include "cellPamf.h" Module *cellSail = nullptr; @@ -92,9 +94,22 @@ int cellSailDescriptorIsAutoSelection(vm::ptr pSelf) return CELL_OK; } -int cellSailDescriptorCreateDatabase() +int cellSailDescriptorCreateDatabase(vm::ptr pSelf, vm::ptr pDatabase, be_t size, be_t arg) { - UNIMPLEMENTED_FUNC(cellSail); + cellSail->Warning("cellSailDescriptorCreateDatabase(pSelf=0x%x, pDatabase=0x%x, size=0x%x, arg=0x%x", pSelf.addr(), pDatabase.addr(), size, arg); + + switch (pSelf->streamType) { + case CELL_SAIL_STREAM_PAMF: + { + u32 addr = pSelf->internalData[1]; + auto ptr = vm::ptr::make(addr); + memcpy(pDatabase.get_ptr(), ptr.get_ptr(), sizeof(CellPamfReader)); + break; + } + default: + cellSail->Error("Unhandled stream type: %d", pSelf->streamType); + } + return CELL_OK; } @@ -619,11 +634,9 @@ int cellSailPlayerAddDescriptor(vm::ptr pSelf, vm::ptr pSelf, s32 streamType, vm::ptr pMediaInfo, vm::ptr pUri, vm::ptr ppDesc) { - cellSail->Todo("cellSailPlayerCreateDescriptor(pSelf_addr=0x%x, streamType=%d, pMediaInfo_addr=0x%x, pUri_addr=0x%x, ppDesc_addr=0x%x)", pSelf.addr(), streamType, + cellSail->Warning("cellSailPlayerCreateDescriptor(pSelf_addr=0x%x, streamType=%d, pMediaInfo_addr=0x%x, pUri_addr=0x%x, ppDesc_addr=0x%x)", pSelf.addr(), streamType, pMediaInfo.addr(), pUri.addr(), ppDesc.addr()); - // TODO: Let the game allocate memory for the descriptor, setup the descriptor and pass it back to the game - u32 descriptorAddress = Memory.Alloc(sizeof(CellSailDescriptor), 1); auto descriptor = vm::ptr::make(descriptorAddress); *ppDesc = descriptorAddress; @@ -633,6 +646,39 @@ int cellSailPlayerCreateDescriptor(vm::ptr pSelf, s32 streamType //pSelf->descriptors = 0; pSelf->repeatMode = 0; + switch (streamType) + { + case CELL_SAIL_STREAM_PAMF: + { + std::string uri = pUri.get_ptr(); + if (uri.substr(0, 12) == "x-cell-fs://") { + std::string path = uri.substr(12); + vfsFile f; + if (f.Open(path)) { + u64 size = f.GetSize(); + u32 buf_ = Memory.Alloc(size, 1); + auto bufPtr = vm::ptr::make(buf_); + PamfHeader *buf = const_cast(bufPtr.get_ptr()); + assert(f.Read(buf, size) == size); + u32 sp_ = Memory.Alloc(sizeof(CellPamfReader), 1); + auto sp = vm::ptr::make(sp_); + u32 r = cellPamfReaderInitialize(sp, bufPtr, size, 0); + + descriptor->internalData[0] = buf_; + descriptor->internalData[1] = sp_; + } + else + cellSail->Warning("Couldn't open PAMF: %s", uri.c_str()); + + } + else + cellSail->Warning("Unhandled uri: %s", uri.c_str()); + break; + } + default: + cellSail->Error("Unhandled stream type: %d", streamType); + } + //cellSail->Todo("pSelf_addr=0x%x, pDesc_addr=0x%x", pSelf.addr(), descriptor.addr()); //cellSailPlayerAddDescriptor(pSelf, ppDesc); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index becafff4c5..8b1d80dcd7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -112,7 +112,7 @@ void setSaveDataList(std::vector& saveEntries, vm::ptrdirName == (char*)fixedList[j].dirName) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index aa7458e940..d620fd22ab 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -286,13 +286,13 @@ int cellVideoOutGetNumberOfDevice(u32 videoOut) int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 aspect, u32 option) { - cellSysutil->Warning("cellVideoOutGetResolutionAvailability(videoOut=%d, resolutionId=0x%x, option_addr=0x%x, aspect=0x%x, option=0x%x)", + cellSysutil->Warning("cellVideoOutGetResolutionAvailability(videoOut=%d, resolutionId=0x%x, option_addr=0x%x, aspect=%d, option=%d)", videoOut, resolutionId, aspect, option); - if(!ResolutionIdToNum(resolutionId)) - { - return CELL_EINVAL; - } + if (!Ini.GS3DTV.GetValue() && resolutionId == CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING || resolutionId == CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING || + resolutionId == CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING || resolutionId == CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING || + resolutionId == CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING) + return 0; switch(videoOut) { From cf1bd9b61b9dc46ae0da68cd7ca90351d8fd0230 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Wed, 24 Dec 2014 21:03:52 +0200 Subject: [PATCH 28/36] Fix compiling --- rpcs3/Emu/SysCalls/Modules/cellSail.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp b/rpcs3/Emu/SysCalls/Modules/cellSail.cpp index 3c5bdad60e..9e5ee1fc73 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSail.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSail.cpp @@ -98,7 +98,7 @@ int cellSailDescriptorCreateDatabase(vm::ptr pSelf, vm::ptr< { cellSail->Warning("cellSailDescriptorCreateDatabase(pSelf=0x%x, pDatabase=0x%x, size=0x%x, arg=0x%x", pSelf.addr(), pDatabase.addr(), size, arg); - switch (pSelf->streamType) { + switch ((s32)pSelf->streamType) { case CELL_SAIL_STREAM_PAMF: { u32 addr = pSelf->internalData[1]; From a94a7d4495e2bb9710f0c17a47f84ddb02d1609c Mon Sep 17 00:00:00 2001 From: darkf Date: Wed, 24 Dec 2014 20:39:57 -0800 Subject: [PATCH 29/36] Add a memory ASCII string search --- rpcs3/Gui/MainFrame.cpp | 11 +++++ rpcs3/Gui/MainFrame.h | 1 + rpcs3/Gui/MemoryStringSearcher.cpp | 74 ++++++++++++++++++++++++++++++ rpcs3/Gui/MemoryStringSearcher.h | 19 ++++++++ rpcs3/rpcs3.vcxproj | 1 + rpcs3/rpcs3.vcxproj.filters | 3 ++ 6 files changed, 109 insertions(+) create mode 100644 rpcs3/Gui/MemoryStringSearcher.cpp create mode 100644 rpcs3/Gui/MemoryStringSearcher.h diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 2235c8e63d..595d207423 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -20,6 +20,7 @@ #include "Gui/KernelExplorer.h" #include "Gui/MemoryViewer.h" #include "Gui/RSXDebugger.h" +#include "Gui/MemoryStringSearcher.h" #include "Gui/LLEModulesManager.h" #include @@ -51,6 +52,7 @@ enum IDs id_tools_kernel_explorer, id_tools_memory_viewer, id_tools_rsx_debugger, + id_tools_string_search, id_help_about, id_update_dbg, }; @@ -112,6 +114,7 @@ MainFrame::MainFrame() menu_tools->Append(id_tools_kernel_explorer, "&Kernel Explorer")->Enable(false); menu_tools->Append(id_tools_memory_viewer, "&Memory Viewer")->Enable(false); menu_tools->Append(id_tools_rsx_debugger, "&RSX Debugger")->Enable(false); + menu_tools->Append(id_tools_string_search, "&String Search")->Enable(false); wxMenu* menu_help = new wxMenu(); menubar->Append(menu_help, "&Help"); @@ -151,6 +154,7 @@ MainFrame::MainFrame() Bind(wxEVT_MENU, &MainFrame::OpenKernelExplorer, this, id_tools_kernel_explorer); Bind(wxEVT_MENU, &MainFrame::OpenMemoryViewer, this, id_tools_memory_viewer); Bind(wxEVT_MENU, &MainFrame::OpenRSXDebugger, this, id_tools_rsx_debugger); + Bind(wxEVT_MENU, &MainFrame::OpenStringSearch, this, id_tools_string_search); Bind(wxEVT_MENU, &MainFrame::AboutDialogHandler, this, id_help_about); @@ -720,6 +724,10 @@ void MainFrame::OpenRSXDebugger(wxCommandEvent& WXUNUSED(event)) (new RSXDebugger(this)) -> Show(); } +void MainFrame::OpenStringSearch(wxCommandEvent& WXUNUSED(event)) +{ + (new MemoryStringSearcher(this)) -> Show(); +} void MainFrame::AboutDialogHandler(wxCommandEvent& WXUNUSED(event)) { @@ -818,9 +826,12 @@ void MainFrame::UpdateUI(wxCommandEvent& event) wxMenuItem& kernel_explorer = *menubar.FindItem(id_tools_kernel_explorer); wxMenuItem& memory_viewer = *menubar.FindItem(id_tools_memory_viewer); wxMenuItem& rsx_debugger = *menubar.FindItem(id_tools_rsx_debugger); + wxMenuItem& string_search = *menubar.FindItem(id_tools_string_search); kernel_explorer.Enable(!is_stopped); memory_viewer.Enable(!is_stopped); rsx_debugger.Enable(!is_stopped); + string_search.Enable(!is_stopped); + //m_aui_mgr.Update(); diff --git a/rpcs3/Gui/MainFrame.h b/rpcs3/Gui/MainFrame.h index 359e932c6a..3de2d38e6a 100644 --- a/rpcs3/Gui/MainFrame.h +++ b/rpcs3/Gui/MainFrame.h @@ -45,6 +45,7 @@ private: void OpenKernelExplorer(wxCommandEvent& evt); void OpenMemoryViewer(wxCommandEvent& evt); void OpenRSXDebugger(wxCommandEvent& evt); + void OpenStringSearch(wxCommandEvent& evt); void OpenFnIdGenerator(wxCommandEvent& evt); void AboutDialogHandler(wxCommandEvent& event); void UpdateUI(wxCommandEvent& event); diff --git a/rpcs3/Gui/MemoryStringSearcher.cpp b/rpcs3/Gui/MemoryStringSearcher.cpp new file mode 100644 index 0000000000..8676d57371 --- /dev/null +++ b/rpcs3/Gui/MemoryStringSearcher.cpp @@ -0,0 +1,74 @@ +#include "stdafx_gui.h" +#include "rpcs3/Ini.h" +#include "Utilities/rPlatform.h" +#include "Utilities/Log.h" +#include "Emu/Memory/Memory.h" +#include "Emu/System.h" + +#include "MemoryStringSearcher.h" +#include "Emu/RSX/sysutil_video.h" +#include "Emu/RSX/GSManager.h" +//#include "Emu/RSX/GCM.h" + +#include + +MemoryStringSearcher::MemoryStringSearcher(wxWindow* parent) + : wxFrame(parent, wxID_ANY, "String Searcher", wxDefaultPosition, wxSize(545, 64)) + , exit(false) +{ + this->SetBackgroundColour(wxColour(240,240,240)); + //wxBoxSizer* s_panel = new wxBoxSizer(wxHORIZONTAL); + + //Tools + //wxBoxSizer* s_tools = new wxBoxSizer(wxVERTICAL); + + //Tabs + //wxNotebook* nb_rsx = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(482,475)); + + s_panel = new wxBoxSizer(wxHORIZONTAL); + t_addr = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(482, -1)); + b_search = new wxButton(this, wxID_ANY, "Search", wxPoint(482, 0), wxSize(40, -1)); + b_search->Bind(wxEVT_BUTTON, &MemoryStringSearcher::Search, this); + s_panel->Add(t_addr); + s_panel->Add(b_search); +}; + +void MemoryStringSearcher::Search(wxCommandEvent& event) +{ + const wxString wstr = t_addr->GetValue(); + const char *str = wstr.c_str(); + const u32 len = wstr.length(); + + LOG_NOTICE(GENERAL, "Searching for string %s", str); + + // Search the address space for the string + u32 strIndex = 0; + u32 numFound = 0; + for (u32 addr = Memory.MainMem.GetStartAddr(); addr < Memory.MainMem.GetEndAddr(); addr++) { + if (!Memory.IsGoodAddr(addr)) { + strIndex = 0; + continue; + } + + u8 byte = vm::read8(addr); + if (byte == str[strIndex]) { + if (strIndex == len) { + // Found it + LOG_NOTICE(GENERAL, "Found @ %04x", addr - len); + numFound++; + strIndex = 0; + continue; + } + + strIndex++; + } + else + strIndex = 0; + + if (addr % (1024 * 1024 * 64) == 0) { // Log every 64mb + LOG_NOTICE(GENERAL, "Searching %04x ...", addr); + } + } + + LOG_NOTICE(GENERAL, "Search completed (found %d matches)", numFound); +} \ No newline at end of file diff --git a/rpcs3/Gui/MemoryStringSearcher.h b/rpcs3/Gui/MemoryStringSearcher.h new file mode 100644 index 0000000000..9af71fee89 --- /dev/null +++ b/rpcs3/Gui/MemoryStringSearcher.h @@ -0,0 +1,19 @@ +#pragma once +#include + +class MemoryStringSearcher : public wxFrame +{ + wxTextCtrl* t_addr; + wxBoxSizer* s_panel; + wxButton* b_search; + +public: + bool exit; + MemoryStringSearcher(wxWindow* parent); + ~MemoryStringSearcher() + { + exit = true; + } + + void MemoryStringSearcher::Search(wxCommandEvent& event); +}; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 946b6cb66e..44c219a587 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -175,6 +175,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 5fce1aa362..71062a8296 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -93,6 +93,9 @@ Gui + + Gui + From efde3219bd86e9c4882b1e02fe427b9c49e49045 Mon Sep 17 00:00:00 2001 From: darkf Date: Thu, 25 Dec 2014 00:32:18 -0800 Subject: [PATCH 30/36] cellSaveData: terminate callback loop when asked to --- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 8b1d80dcd7..e96037f8f5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -238,7 +238,7 @@ s32 modifySaveDataFiles(vm::ptr funcFile, vm::ptrError("modifySaveDataFiles: CellSaveDataFileCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } - if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) { + if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST || result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM) { break; } From efd729d0b8e81c123f6c2e418b26c44649d901cb Mon Sep 17 00:00:00 2001 From: darkf Date: Thu, 25 Dec 2014 00:53:56 -0800 Subject: [PATCH 31/36] MemoryStringSearcher: drop superfluous qualifier --- rpcs3/Gui/MemoryStringSearcher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Gui/MemoryStringSearcher.h b/rpcs3/Gui/MemoryStringSearcher.h index 9af71fee89..f0928afe2d 100644 --- a/rpcs3/Gui/MemoryStringSearcher.h +++ b/rpcs3/Gui/MemoryStringSearcher.h @@ -15,5 +15,5 @@ public: exit = true; } - void MemoryStringSearcher::Search(wxCommandEvent& event); + void Search(wxCommandEvent& event); }; From bc8fba9cc48a26fc90a0e52973fa4354964acab6 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 26 Dec 2014 00:46:33 +0800 Subject: [PATCH 32/36] Revert "Check address is not null for cellGcmAddressToOffset" --- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 94d14f347e..3e5c5f4239 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -805,8 +805,7 @@ s32 cellGcmAddressToOffset(u64 address, vm::ptr> offset) cellGcmSys->Log("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset.addr()); // Address not on main memory or local memory - if (!address || address >= 0xD0000000) { - cellGcmSys->Error("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset.addr()); + if (address >= 0xD0000000) { return CELL_GCM_ERROR_FAILURE; } From 3f7e6c990f39bff1fb159b79e85a42a0978ab700 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 26 Dec 2014 06:54:36 +0800 Subject: [PATCH 33/36] Not always flush in callback --- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 3e5c5f4239..c8e0b87038 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -1169,12 +1169,16 @@ s32 cellGcmCallback(vm::ptr context, u32 count) { cellGcmSys->Log("cellGcmCallback(context_addr=0x%x, count=0x%x)", context.addr(), count); - GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); - if (1) { auto& ctrl = vm::get_ref(gcm_info.control_addr); be_t res = be_t::make(context->current - context->begin - ctrl.put.read_relaxed()); + + if (res != 0) + { + GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); + } + memmove(vm::get_ptr(context->begin), vm::get_ptr(context->current - res), res); context->current = context->begin + res; From 97d50a0692c0b5f3c613d07218bd8169ce033ec3 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 26 Dec 2014 13:59:47 +0800 Subject: [PATCH 34/36] Formatting RSX thread --- rpcs3/Emu/RSX/RSXThread.cpp | 351 ++++++++++++++++++------------------ rpcs3/Emu/RSX/RSXThread.h | 14 +- 2 files changed, 188 insertions(+), 177 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 7e92b8642b..dbd4404a1d 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -14,34 +14,42 @@ u32 methodRegisters[0xffff]; -void RSXThread::nativeRescale(float width, float height) +void RSXThread::NativeRescale(float width, float height) { switch (Ini.GSResolution.GetValue()) { case 1: // 1920x1080 window size + { m_width_scale = 1920 / width * 2.0f; m_height_scale = 1080 / height * 2.0f; m_width = 1920; m_height = 1080; - break; + } + break; case 2: // 1280x720 window size + { m_width_scale = 1280 / width * 2.0f; m_height_scale = 720 / height * 2.0f; m_width = 1280; m_height = 720; - break; + } + break; case 4: // 720x480 window size + { m_width_scale = 720 / width * 2.0f; m_height_scale = 480 / height * 2.0f; m_width = 720; m_height = 480; - break; + } + break; case 5: // 720x576 window size + { m_width_scale = 720 / width * 2.0f; m_height_scale = 576 / height * 2.0f; m_width = 720; m_height = 576; - break; + } + break; } } @@ -49,7 +57,7 @@ u32 GetAddress(u32 offset, u32 location) { u32 res = 0; - switch(location) + switch (location) { case CELL_GCM_LOCATION_LOCAL: { @@ -105,18 +113,18 @@ void RSXVertexData::Reset() void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0) { - if(!addr) return; + if (!addr) return; const u32 tsize = GetTypeSize(); data.resize((start + count) * tsize * size); - for(u32 i=start; i(addr + baseOffset + stride * (i + baseIndex)); u8* dst = &data[i * tsize * size]; - switch(tsize) + switch (tsize) { case 1: { @@ -128,7 +136,7 @@ void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0) { const u16* c_src = (const u16*)src; u16* c_dst = (u16*)dst; - for(u32 j=0; j::make(args_addr); std::string debug = GetMethodName(cmd); debug += "("; - for(u32 i=0; i> 31); CMD_LOG("num=%d, addr=0x%x", index, addr); @@ -518,7 +481,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const } break; - case_16(NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 4): + case_16(NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 4) { const u32 a0 = ARGS(0); u16 frequency = a0 >> 16; @@ -542,7 +505,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: 0x%x", ARGS(0)); + } //VertexData[0].prog.attributeInputMask = ARGS(0); } @@ -551,7 +516,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: 0x%x", ARGS(0)); + } //VertexData[0].prog.attributeOutputMask = ARGS(0); //FragmentData.prog.attributeInputMask = ARGS(0)/* & ~0x20*/; @@ -574,7 +541,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_COLOR_MASK_MRT: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_COLOR_MASK_MRT: 0x%x", ARGS(0)); + } } break; @@ -678,7 +647,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_BLEND_COLOR2: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_BLEND_COLOR2: 0x % x", ARGS(0)); + } } break; @@ -693,7 +664,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_REDUCE_DST_COLOR: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_REDUCE_DST_COLOR: 0x%x", ARGS(0)); + } } break; @@ -869,8 +842,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { u32 a0 = ARGS(0); - if(a0 & 0x01) m_clear_surface_z = m_clear_z; - if(a0 & 0x02) m_clear_surface_s = m_clear_s; + if (a0 & 0x01) m_clear_surface_z = m_clear_z; + if (a0 & 0x02) m_clear_surface_s = m_clear_s; m_clear_surface_mask |= a0 & 0x3; } @@ -880,12 +853,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { const u32 a0 = ARGS(0); - if(a0 & 0x01) m_clear_surface_z = m_clear_z; - if(a0 & 0x02) m_clear_surface_s = m_clear_s; - if(a0 & 0x10) m_clear_surface_color_r = m_clear_color_r; - if(a0 & 0x20) m_clear_surface_color_g = m_clear_color_g; - if(a0 & 0x40) m_clear_surface_color_b = m_clear_color_b; - if(a0 & 0x80) m_clear_surface_color_a = m_clear_color_a; + if (a0 & 0x01) m_clear_surface_z = m_clear_z; + if (a0 & 0x02) m_clear_surface_s = m_clear_s; + if (a0 & 0x10) m_clear_surface_color_r = m_clear_color_r; + if (a0 & 0x20) m_clear_surface_color_g = m_clear_color_g; + if (a0 & 0x40) m_clear_surface_color_b = m_clear_color_b; + if (a0 & 0x80) m_clear_surface_color_a = m_clear_color_a; m_clear_surface_mask = a0; ExecCMD(NV4097_CLEAR_SURFACE); @@ -913,21 +886,25 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_CLEAR_RECT_HORIZONTAL: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_HORIZONTAL: 0x%x", ARGS(0)); + } } break; case NV4097_SET_CLEAR_RECT_VERTICAL: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_VERTICAL: 0x%x", ARGS(0)); + } } break; // Arrays case NV4097_DRAW_ARRAYS: { - for(u32 c=0; c> 24) + 1; - if(first < m_indexed_array.m_first) m_indexed_array.m_first = first; + if (first < m_indexed_array.m_first) m_indexed_array.m_first = first; - for(u32 i=first; i<_count; ++i) + for (u32 i = first; i < _count; ++i) { u32 index; - switch(m_indexed_array.m_type) + switch (m_indexed_array.m_type) { case 0: { @@ -989,8 +966,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const break; } - if(index < m_indexed_array.index_min) m_indexed_array.index_min = index; - if(index > m_indexed_array.index_max) m_indexed_array.index_max = index; + if (index < m_indexed_array.index_min) m_indexed_array.index_min = index; + if (index > m_indexed_array.index_max) m_indexed_array.index_max = index; } m_indexed_array.m_count += _count; @@ -1031,7 +1008,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 vertex_size = i.data.size() / (i.size * i.GetTypeSize()); if (min_vertex_size > vertex_size) + { min_vertex_size = vertex_size; + } } m_draw_array_count = min_vertex_size; @@ -1095,10 +1074,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const if (count == 2) { - const u32 start = ARGS(1); - if (start) + if (ARGS(1)) { - LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_LOAD: start = %d", start); + LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_LOAD: start = %d", ARGS(0)); } } } @@ -1106,51 +1084,51 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_TRANSFORM_PROGRAM_START: { - const u32 start = ARGS(0); - if (start) + if (ARGS(0)) { - LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_START: start = %d", start); + LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_START: start = %d", ARGS(0)); } } break; - case_32(NV4097_SET_TRANSFORM_PROGRAM, 4): + case_32(NV4097_SET_TRANSFORM_PROGRAM, 4) { //LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM[%d](%d)", index, count); - if(!m_cur_vertex_prog) + if (!m_cur_vertex_prog) { LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog == NULL"); break; } - for(u32 i=0; idata.push_back(ARGS(i)); + for (u32 i = 0; i < count; ++i) m_cur_vertex_prog->data.push_back(ARGS(i)); } break; case NV4097_SET_TRANSFORM_TIMEOUT: - + { // TODO: // (cmd)[1] = CELL_GCM_ENDIAN_SWAP((count) | ((registerCount) << 16)); \ - if(!m_cur_vertex_prog) + if (!m_cur_vertex_prog) { LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_TIMEOUT: m_cur_vertex_prog == NULL"); break; } //m_cur_vertex_prog->Decompile(); + } break; case NV4097_SET_TRANSFORM_CONSTANT_LOAD: { - if((count - 1) % 4) + if ((count - 1) % 4) { CMD_LOG("NV4097_SET_TRANSFORM_CONSTANT_LOAD [%d]", count); break; } - for(u32 id = ARGS(0), i = 1; i= 2) + if (count >= 2) { m_set_stencil_func_ref = true; m_stencil_func_ref = ARGS(1); - if(count >= 3) + if (count >= 3) { m_set_stencil_func_mask = true; m_stencil_func_mask = ARGS(2); @@ -1276,12 +1258,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_stencil_fail = true; m_stencil_fail = ARGS(0); - if(count >= 2) + if (count >= 2) { m_set_stencil_zfail = true; m_stencil_zfail = ARGS(1); - if(count >= 3) + if (count >= 3) { m_set_stencil_zpass = true; m_stencil_zpass = ARGS(2); @@ -1302,12 +1284,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_back_stencil_func = true; m_back_stencil_func = ARGS(0); - if(count >= 2) + if (count >= 2) { m_set_back_stencil_func_ref = true; m_back_stencil_func_ref = ARGS(1); - if(count >= 3) + if (count >= 3) { m_set_back_stencil_func_mask = true; m_back_stencil_func_mask = ARGS(2); @@ -1335,12 +1317,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_stencil_fail = true; m_stencil_fail = ARGS(0); - if(count >= 2) + if (count >= 2) { m_set_back_stencil_zfail = true; m_back_stencil_zfail = ARGS(1); - if(count >= 3) + if (count >= 3) { m_set_back_stencil_zpass = true; m_back_stencil_zpass = ARGS(2); @@ -1352,7 +1334,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_SCULL_CONTROL: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_SCULL_CONTROL: 0x%x", ARGS(0)); + } //This is stencil culling , nothing to do with stencil masking on regular color or depth buffer //const u32 a0 = ARGS(0); @@ -1390,7 +1374,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_POINT_PARAMS_ENABLE: { if (ARGS(0)) + { LOG_ERROR(RSX, "NV4097_SET_POINT_PARAMS_ENABLE: 0x%x", ARGS(0)); + } } break; @@ -1417,7 +1403,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_scissor_x = ARGS(0) & 0xffff; m_scissor_w = ARGS(0) >> 16; - if(count == 2) + if (count == 2) { m_set_scissor_vertical = true; m_scissor_y = ARGS(1) & 0xffff; @@ -1460,7 +1446,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_height = buffers[m_gcm_current_buffer].height; // Rescale native resolution to fit 1080p/720p/480p/576p window size - nativeRescale((float)m_width, (float)m_height); + NativeRescale((float)m_width, (float)m_height); } break; @@ -1575,7 +1561,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_context_dma_color_c = true; m_context_dma_color_c = ARGS(0); - if(count > 1) + if (count > 1) { m_set_context_dma_color_d = true; m_context_dma_color_d = ARGS(1); @@ -1600,14 +1586,18 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_CONTEXT_DMA_SEMAPHORE: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0)); + } } break; case NV4097_SET_CONTEXT_DMA_NOTIFIES: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_NOTIFIES: 0x%x", ARGS(0)); + } } break; @@ -1619,7 +1609,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_surface_clip_x = a0; m_surface_clip_w = a0 >> 16; - if(count == 2) + if (count == 2) { const u32 a1 = ARGS(1); m_set_surface_clip_vertical = true; @@ -1718,7 +1708,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_ZCULL_CONTROL0: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL0: 0x%x", ARGS(0)); + } //m_set_depth_func = true; //m_depth_func = ARGS(0) >> 4; @@ -1728,7 +1720,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_ZCULL_CONTROL1: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL1: 0x%x", ARGS(0)); + } //m_set_depth_func = true; //m_depth_func = ARGS(0) >> 4; @@ -1738,14 +1732,18 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_ZCULL_STATS_ENABLE: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_SET_ZCULL_STATS_ENABLE: 0x%x", ARGS(0)); + } } break; case NV4097_ZCULL_SYNC: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: 0x%x", ARGS(0)); + } } break; @@ -1840,8 +1838,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u8 cullNearFarEnable = ARGS(0) & 0xf; const u8 zclampEnable = (ARGS(0) >> 4) & 0xf; const u8 cullIgnoreW = (ARGS(0) >> 8) & 0xf; - LOG_WARNING(RSX, "TODO: NV4097_SET_ZMIN_MAX_CONTROL: cullNearFarEnable=%d, zclampEnable=%d, cullIgnoreW=%d", - cullNearFarEnable, zclampEnable, cullIgnoreW); + LOG_WARNING(RSX, "TODO: NV4097_SET_ZMIN_MAX_CONTROL: cullNearFarEnable=%d, zclampEnable=%d, cullIgnoreW=%d", cullNearFarEnable, zclampEnable, cullIgnoreW); } break; @@ -1920,6 +1917,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const if (!offset) { + // } else { @@ -1931,14 +1929,18 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV0039_PITCH_IN: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV0039_PITCH_IN: 0x%x", ARGS(0)); + } } break; case NV0039_BUFFER_NOTIFY: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: 0x%x", ARGS(0)); + } } break; @@ -1967,7 +1969,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV309E_SET_CONTEXT_DMA_IMAGE: { if (ARGS(0)) + { LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: 0x%x", ARGS(0)); + } } break; @@ -2009,21 +2013,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const c.y = (float&)a; } - if(count >= 3) + if (count >= 3) { u32 a = ARGS(2); a = a << 16 | a >> 16; c.z = (float&)a; } - if(count >= 4) + if (count >= 4) { u32 a = ARGS(3); a = a << 16 | a >> 16; c.w = (float&)a; } - if(count >= 5) + if (count >= 5) { LOG_WARNING(RSX, "NV308A_COLOR: count = %d", count); } @@ -2070,9 +2074,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_WARNING(RSX, "*** m_dst_offset=0x%x, m_color: conv_in_h=0x%x, format_src_pitch=0x%x, conv_in_x=0x%x, conv_in_y=0x%x, conv_out_x=0x%x, conv_out_y=0x%x", m_dst_offset, m_color_conv_in_h, m_color_format_src_pitch, m_color_conv_in_x, m_color_conv_in_y, m_color_conv_out_x, m_color_conv_out_y); - for(u16 y=0; y lock(m_cs_main); - inc=1; + inc = 1; u32 get = m_ctrl->get.read_sync(); u32 put = m_ctrl->put.read_sync(); - if(put == get || !Emu.IsRunning()) + if (put == get || !Emu.IsRunning()) { - if(put == get) + if (put == get) { - if(m_flip_status == 0) + if (m_flip_status == 0) + { m_sem_flip.post_and_wait(); + } m_sem_flush.post_and_wait(); } @@ -2316,52 +2322,54 @@ void RSXThread::Task() continue; } - //ConLog.Write("addr = 0x%x", m_ioAddress + get); + const u32 cmd = ReadIO32(get); const u32 count = (cmd >> 18) & 0x7ff; - //if(cmd == 0) continue; if (Ini.RSXLogging.GetValue()) + { LOG_NOTICE(Log::RSX, "%s (cmd=0x%x)", GetMethodName(cmd & 0xffff).c_str(), cmd); + } - //LOG_NOTICE(Log::RSX, "put=0x%x, get=0x%x, cmd=0x%x (%s)", put, get, cmd, GetMethodName(cmd & 0xffff).c_str()); - - if(cmd & CELL_GCM_METHOD_FLAG_JUMP) + if (cmd & CELL_GCM_METHOD_FLAG_JUMP) { u32 offs = cmd & 0x1fffffff; - //LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put); + //LOG_WARNING(RSX, "RSX: jump cmd (0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put); m_ctrl->get.exchange(be_t::make(offs)); continue; } - if(cmd & CELL_GCM_METHOD_FLAG_CALL) + + if (cmd & CELL_GCM_METHOD_FLAG_CALL) { m_call_stack.push(get + 4); u32 offs = cmd & ~3; - //u32 addr = offs; - //LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get); + //LOG_WARNING(RSX, "RSX: call cmd (0x%x) #0x%x - 0x%x", offs, cmd, get); m_ctrl->get.exchange(be_t::make(offs)); continue; } - if(cmd == CELL_GCM_METHOD_FLAG_RETURN) + + if (cmd == CELL_GCM_METHOD_FLAG_RETURN) { //LOG_WARNING(RSX, "rsx return!"); u32 get = m_call_stack.top(); m_call_stack.pop(); - //LOG_WARNING(RSX, "rsx return(0x%x)", get); + //LOG_WARNING(RSX, "RSX: return cmd (0x%x)", get); m_ctrl->get.exchange(be_t::make(get)); continue; } - if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) + + if (cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) { - //LOG_WARNING(RSX, "non increment cmd! 0x%x", cmd); + //LOG_WARNING(RSX,"RSX: non-increment cmd! 0x%x", cmd); inc = 0; } else { - //LOG_WARNING(RSX, "increment cmd! 0x%x", cmd); + //LOG_WARNING(RSX, "RSX: increment cmd! 0x%x", cmd); + inc++; } - if(cmd == 0) //nop + if (cmd == 0) //nop { m_ctrl->get.atomic_op([](be_t& value) { @@ -2372,7 +2380,7 @@ void RSXThread::Task() auto args = vm::ptr::make((u32)Memory.RSXIOMem.RealAddr(get + 4)); - for(u32 i=0; i Date: Fri, 26 Dec 2014 15:26:43 +0800 Subject: [PATCH 35/36] ELF loader : small bug fix --- rpcs3/Loader/ELF32.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index cbfb8a0317..31925d4b57 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -55,7 +55,7 @@ namespace loader { m_shdrs.resize(m_ehdr.is_le() ? m_ehdr.data_le.e_shnum : m_ehdr.data_be.e_shnum); m_stream->Seek(handler::get_stream_offset() + (m_ehdr.is_le() ? m_ehdr.data_le.e_shoff : m_ehdr.data_be.e_shoff)); - size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_shnum : m_ehdr.data_be.e_shnum) * sizeof(phdr); + size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_shnum : m_ehdr.data_be.e_shnum) * sizeof(shdr); if (m_stream->Read(m_shdrs.data(), size) != size) return broken_file; @@ -284,4 +284,4 @@ namespace loader return ok; } } -} \ No newline at end of file +} From 052692ac8cb97804c01ad5ce4b02b132b75cce69 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Fri, 26 Dec 2014 10:06:12 +0200 Subject: [PATCH 36/36] Improvements to saving and cellFsStat --- rpcs3/Emu/RSX/RSXThread.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 39 +++++++++-- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 4 +- rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp | 71 +++++++++++++++++++-- rpcs3/Emu/SysCalls/lv2/sys_process.cpp | 4 ++ rpcs3/Emu/System.cpp | 2 + 6 files changed, 110 insertions(+), 14 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 7e92b8642b..8acd8de425 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1845,12 +1845,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const } break; - // Windows Clipping + // Windows Clipping (Doesn't seem to be relevant?) case NV4097_SET_WINDOW_OFFSET: { const u16 x = ARGS(0); const u16 y = ARGS(0) >> 16; - LOG_WARNING(RSX, "TODO: NV4097_SET_WINDOW_OFFSET: x=%d, y=%d", x, y); + //LOG_WARNING(RSX, "TODO: NV4097_SET_WINDOW_OFFSET: x=%d, y=%d", x, y); } break; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 8b1d80dcd7..9e79e0015c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -10,6 +10,14 @@ #include "Loader/PSF.h" #include "cellSaveData.h" +#ifdef _WIN32 + #include + #undef CreateFile +#else + #include + #include +#endif + extern Module *cellSysutil; // Auxiliary Classes @@ -39,7 +47,6 @@ public: } }; - // Auxiliary Functions u64 getSaveDataSize(const std::string& dirName) { @@ -69,6 +76,28 @@ void addSaveDataEntry(std::vector& saveEntries, const std::string std::string localPath; Emu.GetVFS().GetDevice(saveDir + "/ICON0.PNG", localPath); + u64 atime = 0; + u64 mtime = 0; + u64 ctime = 0; + + cellSysutil->Error("Running _stat in cellSaveData. Please report this to a RPCS3 developer!"); + + std::string pathy; + + Emu.GetVFS().GetDevice("dev_hdd0", pathy); + + struct stat buf; + int result = stat((pathy.substr(0, pathy.length() - 9) + f.GetPath()).c_str(), &buf); + + if (result != 0) + cellSysutil->Error("_stat failed! (%s)", (pathy.substr(0, pathy.length() - 9) + f.GetPath()).c_str()); + else + { + atime = buf.st_atime; + mtime = buf.st_mtime; + ctime = buf.st_ctime; + } + SaveDataEntry saveEntry; saveEntry.dirName = psf.GetString("SAVEDATA_DIRECTORY"); saveEntry.listParam = psf.GetString("SAVEDATA_LIST_PARAM"); @@ -76,9 +105,9 @@ void addSaveDataEntry(std::vector& saveEntries, const std::string saveEntry.subtitle = psf.GetString("SUB_TITLE"); saveEntry.details = psf.GetString("DETAIL"); saveEntry.sizeKB = (u32)(getSaveDataSize(saveDir) / 1024); - saveEntry.st_atime_ = 0; // TODO - saveEntry.st_mtime_ = 0; // TODO - saveEntry.st_ctime_ = 0; // TODO + saveEntry.st_atime_ = atime; + saveEntry.st_mtime_ = mtime; + saveEntry.st_ctime_ = ctime; saveEntry.iconBuf = NULL; // TODO: Here should be the PNG buffer saveEntry.iconBufSize = 0; // TODO: Size of the PNG file saveEntry.isNew = false; @@ -238,7 +267,7 @@ s32 modifySaveDataFiles(vm::ptr funcFile, vm::ptrError("modifySaveDataFiles: CellSaveDataFileCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message. return CELL_SAVEDATA_ERROR_CBRESULT; } - if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) { + if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST || result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM) { break; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index d620fd22ab..5afa9e72dc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -289,9 +289,9 @@ int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 as cellSysutil->Warning("cellVideoOutGetResolutionAvailability(videoOut=%d, resolutionId=0x%x, option_addr=0x%x, aspect=%d, option=%d)", videoOut, resolutionId, aspect, option); - if (!Ini.GS3DTV.GetValue() && resolutionId == CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING || resolutionId == CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING || + if (!Ini.GS3DTV.GetValue() && (resolutionId == CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING || resolutionId == CELL_VIDEO_OUT_RESOLUTION_1024x720_3D_FRAME_PACKING || resolutionId == CELL_VIDEO_OUT_RESOLUTION_960x720_3D_FRAME_PACKING || resolutionId == CELL_VIDEO_OUT_RESOLUTION_800x720_3D_FRAME_PACKING || - resolutionId == CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING) + resolutionId == CELL_VIDEO_OUT_RESOLUTION_640x720_3D_FRAME_PACKING)) return 0; switch(videoOut) diff --git a/rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp b/rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp index 6a67a2c334..071497cfe3 100644 --- a/rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp @@ -9,6 +9,14 @@ #include "Emu/FS/vfsDir.h" #include "lv2Fs.h" +#ifdef _WIN32 + #include + #undef CreateFile +#else + #include + #include +#endif + extern Module *sys_fs; struct FsRingBufferConfig @@ -235,16 +243,66 @@ s32 cellFsStat(vm::ptr path, vm::ptr sb) const std::string _path = path.get_ptr(); + u32 mode = 0; + s32 uid = 0; + s32 gid = 0; + u64 atime = 0; + u64 mtime = 0; + u64 ctime = 0; + u64 size = 0; + + int device = -1; + + if (_path.substr(1, 8) == "dev_hdd0") + device = 0; + else if (_path.substr(1, 8) == "dev_hdd1") + device = 1; + else if (_path.substr(1, 8) == "dev_bdvd") + device = 2; + + std::string pathy; + + if (device == 0) + Emu.GetVFS().GetDevice("dev_hdd0", pathy); + else if (device == 1) + Emu.GetVFS().GetDevice("dev_hdd1", pathy); + else if (device == 2) + Emu.GetVFS().GetDevice("dev_bdvd", pathy); + + struct stat buf; + int result = 1; + + if (device == 2) + result = stat((pathy + _path.substr(9, _path.length())).c_str(), &buf); + else + result = stat((pathy.substr(0, pathy.length() - 9) + _path).c_str(), &buf); + + if (result != 0) + sys_fs->Error("_stat failed! (%s)", (pathy.substr(0, pathy.length() - 9) + _path).c_str()); + else + { + mode = buf.st_mode; + uid = buf.st_uid; + gid = buf.st_gid; + atime = buf.st_atime; + mtime = buf.st_mtime; + ctime = buf.st_ctime; + size = buf.st_size; + } + sb->st_mode = CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR | CELL_FS_S_IRGRP | CELL_FS_S_IWGRP | CELL_FS_S_IXGRP | CELL_FS_S_IROTH | CELL_FS_S_IWOTH | CELL_FS_S_IXOTH; - sb->st_uid = 0; - sb->st_gid = 0; - sb->st_atime_ = 0; //TODO - sb->st_mtime_ = 0; //TODO - sb->st_ctime_ = 0; //TODO + if (sb->st_mode == mode) + sys_fs->Error("Mode is the same. Report this to a RPCS3 developer! (%d)", mode); + + sb->st_uid = uid; + sb->st_gid = gid; + sb->st_atime_ = atime; + sb->st_mtime_ = mtime; + sb->st_ctime_ = ctime; sb->st_blksize = 4096; { @@ -266,6 +324,9 @@ s32 cellFsStat(vm::ptr path, vm::ptr sb) } } + if (sb->st_size == size && size != 0) + sys_fs->Error("Size is the same. Report this to a RPCS3 developer! (%d)", size); + sys_fs->Warning("cellFsStat: \"%s\" not found.", path.get_ptr()); return CELL_ENOENT; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp index f74b438775..c8781b56c4 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp @@ -109,6 +109,8 @@ void sys_game_process_exitspawn(vm::ptr path, u32 argv_addr, u32 env device = 0; else if (_path.substr(1, 8) == "dev_hdd1") device = 1; + else if (_path.substr(1, 8) == "dev_bdvd") + device = 2; if (device != 0) Emu.BootGame(_path.c_str(), true, device); @@ -189,6 +191,8 @@ void sys_game_process_exitspawn2(vm::ptr path, u32 argv_addr, u32 en device = 0; else if (_path.substr(1, 8) == "dev_hdd1") device = 1; + else if (_path.substr(1, 8) == "dev_bdvd") + device = 2; Emu.BootGame(_path.c_str(), true, device); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 05adca06f5..f1dd6d79e1 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -181,6 +181,8 @@ bool Emulator::BootGame(const std::string& path, bool direct, int device) Emu.GetVFS().GetDevice("dev_hdd0", pathy); else if (device == 1) Emu.GetVFS().GetDevice("dev_hdd1", pathy); + else if (device == 2) + Emu.GetVFS().GetDevice("dev_bdvd", pathy); curpath = pathy.substr(0, pathy.length() - 9) + path;