mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-23 03:02:53 +01:00
Implemented binary fragment program disassembler
This commit is contained in:
parent
bdad5ef745
commit
e84f356a29
477
rpcs3/Emu/RSX/CgBinaryFragmentProgram.cpp
Normal file
477
rpcs3/Emu/RSX/CgBinaryFragmentProgram.cpp
Normal file
@ -0,0 +1,477 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "CgBinaryProgram.h"
|
||||
#include "Emu/RSX/RSXFragmentProgram.h"
|
||||
|
||||
void CgBinaryDisasm::AddCodeAsm(const std::string& code)
|
||||
{
|
||||
std::string op_name = "";
|
||||
|
||||
if (dst.dest_reg == 63)
|
||||
{
|
||||
m_dst_reg_name = fmt::format("RC%s, ", GetMask().c_str());
|
||||
op_name = rsx_fp_op_names[m_opcode] + "XC";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
m_dst_reg_name = fmt::format("%s%d%s, ", dst.fp16 ? "H" : "R", dst.dest_reg, GetMask().c_str());
|
||||
op_name = rsx_fp_op_names[m_opcode] + std::string(dst.fp16 ? "H" : "R");
|
||||
}
|
||||
|
||||
switch (m_opcode)
|
||||
{
|
||||
case RSX_FP_OPCODE_BRK:
|
||||
case RSX_FP_OPCODE_CAL:
|
||||
case RSX_FP_OPCODE_FENCT:
|
||||
case RSX_FP_OPCODE_FENCB:
|
||||
case RSX_FP_OPCODE_IFE:
|
||||
case RSX_FP_OPCODE_KIL:
|
||||
case RSX_FP_OPCODE_LOOP:
|
||||
case RSX_FP_OPCODE_NOP:
|
||||
case RSX_FP_OPCODE_REP:
|
||||
case RSX_FP_OPCODE_RET: m_dst_reg_name = ""; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_arb_shader += (op_name + " " + m_dst_reg_name + FormatDisAsm(code) + ";" + "\n");
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::GetMask()
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
static const char dst_mask[4] =
|
||||
{
|
||||
'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];
|
||||
|
||||
return ret.empty() || strncmp(ret.c_str(), dst_mask, 4) == 0 ? "" : ("." + ret);
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::AddRegDisAsm(u32 index, int fp16)
|
||||
{
|
||||
return std::string(fp16 ? "H" : "R") + std::to_string(index);
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::AddConstDisAsm()
|
||||
{
|
||||
u32* data = (u32*)&m_buffer[m_offset + m_size + 4 * sizeof(u32)];
|
||||
|
||||
m_step = 2 * 4 * sizeof(u32);
|
||||
const u32 x = GetData(data[0]);
|
||||
const u32 y = GetData(data[1]);
|
||||
const u32 z = GetData(data[2]);
|
||||
const u32 w = GetData(data[3]);
|
||||
|
||||
char buf[1024];
|
||||
sprintf(buf, "{0x%08x(%g), 0x%08x(%g), 0x%08x(%g), 0x%08x(%g)}", x, (float&)x, y, (float&)y, z, (float&)z, w, (float&)w);
|
||||
|
||||
return fmt::format(buf);
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::AddTexDisAsm()
|
||||
{
|
||||
return (std::string("TEX") + std::to_string(dst.tex_num));
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::GetCondDisAsm()
|
||||
{
|
||||
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];
|
||||
|
||||
if (swizzle == "xxxx") swizzle = "x";
|
||||
if (swizzle == "yyyy") swizzle = "y";
|
||||
if (swizzle == "zzzz") swizzle = "z";
|
||||
if (swizzle == "wwww") swizzle = "w";
|
||||
|
||||
swizzle = swizzle == "xyzw" ? "" : "." + swizzle;
|
||||
|
||||
if (src0.exec_if_gr && src0.exec_if_eq)
|
||||
{
|
||||
cond = "GE";
|
||||
}
|
||||
else if (src0.exec_if_lt && src0.exec_if_eq)
|
||||
{
|
||||
cond = "LE";
|
||||
}
|
||||
else if (src0.exec_if_gr && src0.exec_if_lt)
|
||||
{
|
||||
cond = "NE";
|
||||
}
|
||||
else if (src0.exec_if_gr)
|
||||
{
|
||||
cond = "GT";
|
||||
}
|
||||
else if (src0.exec_if_lt)
|
||||
{
|
||||
cond = "LT";
|
||||
}
|
||||
else if (src0.exec_if_eq)
|
||||
{
|
||||
cond = "FL";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
cond = "TR";
|
||||
}
|
||||
|
||||
return cond + swizzle;
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::FormatDisAsm(const std::string& code)
|
||||
{
|
||||
const std::pair<std::string, std::function<std::string()>> repl_list[] =
|
||||
{
|
||||
{ "$$", []() -> std::string { return "$"; } },
|
||||
{ "$0", std::bind(std::mem_fn(&CgBinaryDisasm::GetSrcDisAsm<SRC0>), this, src0) },
|
||||
{ "$1", std::bind(std::mem_fn(&CgBinaryDisasm::GetSrcDisAsm<SRC1>), this, src1) },
|
||||
{ "$2", std::bind(std::mem_fn(&CgBinaryDisasm::GetSrcDisAsm<SRC2>), this, src2) },
|
||||
{ "$t", std::bind(std::mem_fn(&CgBinaryDisasm::AddTexDisAsm), this) },
|
||||
{ "$m", std::bind(std::mem_fn(&CgBinaryDisasm::GetMask), this) },
|
||||
{ "$cond", std::bind(std::mem_fn(&CgBinaryDisasm::GetCondDisAsm), this) },
|
||||
{ "$c", std::bind(std::mem_fn(&CgBinaryDisasm::AddConstDisAsm), this) }
|
||||
};
|
||||
|
||||
return fmt::replace_all(code, repl_list);
|
||||
}
|
||||
|
||||
template<typename T> std::string CgBinaryDisasm::GetSrcDisAsm(T src)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
switch (src.reg_type)
|
||||
{
|
||||
case 0: //tmp
|
||||
ret += AddRegDisAsm(src.tmp_reg_index, src.fp16);
|
||||
break;
|
||||
|
||||
case 1: //input
|
||||
{
|
||||
static const std::string reg_table[] =
|
||||
{
|
||||
"WPOS", "COL0", "COL1", "FOGC", "TEX0",
|
||||
"TEX1", "TEX2", "TEX3", "TEX4", "TEX5",
|
||||
"TEX6", "TEX7", "TEX8", "TEX9", "SSA"
|
||||
};
|
||||
|
||||
const std::string perspective_correction = src2.perspective_corr ? "g" : "f";
|
||||
const std::string input_attr_reg = reg_table[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]))
|
||||
{
|
||||
ret += fmt::format("%s[%s]", perspective_correction.c_str(), input_attr_reg.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(RSX, "Bad src reg num: %d", fmt::by_value(dst.src_attr_reg_num));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: //const
|
||||
ret += AddConstDisAsm();
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR(RSX, "Bad src type %d", fmt::by_value(src.reg_type));
|
||||
break;
|
||||
}
|
||||
|
||||
static const char f[4] = { 'x', 'y', 'z', 'w' };
|
||||
|
||||
std::string swizzle = "";
|
||||
swizzle += f[src.swizzle_x];
|
||||
swizzle += f[src.swizzle_y];
|
||||
swizzle += f[src.swizzle_z];
|
||||
swizzle += f[src.swizzle_w];
|
||||
|
||||
if (swizzle == "xxxx") swizzle = "x";
|
||||
if (swizzle == "yyyy") swizzle = "y";
|
||||
if (swizzle == "zzzz") swizzle = "z";
|
||||
if (swizzle == "wwww") swizzle = "w";
|
||||
|
||||
if (strncmp(swizzle.c_str(), f, 4) != 0) ret += "." + swizzle;
|
||||
|
||||
if (src.neg) ret = "-" + ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CgBinaryDisasm::TaskFP()
|
||||
{
|
||||
m_size = 0;
|
||||
u32* data = (u32*)&m_buffer[m_offset];
|
||||
assert((m_buffer_size - m_offset) % sizeof(u32) == 0);
|
||||
for (u32 i = 0; i < (m_buffer_size - m_offset) / sizeof(u32); i++)
|
||||
{
|
||||
data[i] = re32(data[i]);
|
||||
}
|
||||
|
||||
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();
|
||||
finded = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size))
|
||||
{
|
||||
m_end_offsets.erase(finded);
|
||||
m_arb_shader += "ENDIF;\n";
|
||||
}
|
||||
|
||||
for (auto finded = std::find(m_loop_end_offsets.begin(), m_loop_end_offsets.end(), m_size);
|
||||
finded != m_loop_end_offsets.end();
|
||||
finded = std::find(m_loop_end_offsets.begin(), m_loop_end_offsets.end(), m_size))
|
||||
{
|
||||
m_loop_end_offsets.erase(finded);
|
||||
m_arb_shader += "ENDLOOP;\n";
|
||||
}
|
||||
|
||||
for (auto finded = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size);
|
||||
finded != m_else_offsets.end();
|
||||
finded = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size))
|
||||
{
|
||||
m_else_offsets.erase(finded);
|
||||
m_arb_shader += "ELSE;\n";
|
||||
}
|
||||
|
||||
dst.HEX = GetData(data[0]);
|
||||
src0.HEX = GetData(data[1]);
|
||||
src1.HEX = GetData(data[2]);
|
||||
src2.HEX = GetData(data[3]);
|
||||
|
||||
m_step = 4 * sizeof(u32);
|
||||
m_opcode = dst.opcode | (src1.opcode_is_branch << 6);
|
||||
|
||||
auto SCT = [&]()
|
||||
{
|
||||
switch (m_opcode)
|
||||
{
|
||||
case RSX_FP_OPCODE_ADD: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DIV: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DIVSQ: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DP2: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DP3: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DP4: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DP2A: AddCodeAsm("$0, $1, $2"); break;
|
||||
case RSX_FP_OPCODE_MAD: AddCodeAsm("$0, $1, $2"); break;
|
||||
case RSX_FP_OPCODE_MAX: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_MIN: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_MOV: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_MUL: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_RCP: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_RSQ: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_SEQ: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SFL: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SGE: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SGT: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SLE: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SLT: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SNE: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_STR: AddCodeAsm("$0, $1"); break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
auto SCB = [&]()
|
||||
{
|
||||
switch (m_opcode)
|
||||
{
|
||||
case RSX_FP_OPCODE_ADD: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_COS: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_DP2: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DP3: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DP4: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_DP2A: AddCodeAsm("$0, $1, $2"); break;
|
||||
case RSX_FP_OPCODE_DST: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_REFL: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_EX2: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_FLR: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_FRC: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_LIT: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_LIF: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_LRP: AddCodeAsm("# WARNING"); break;
|
||||
case RSX_FP_OPCODE_LG2: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_MAD: AddCodeAsm("$0, $1, $2"); break;
|
||||
case RSX_FP_OPCODE_MAX: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_MIN: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_MOV: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_MUL: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_PK2: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_PK4: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_PK16: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_PKB: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_PKG: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_SEQ: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SFL: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SGE: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SGT: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SIN: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_SLE: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SLT: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_SNE: AddCodeAsm("$0, $1"); break;
|
||||
case RSX_FP_OPCODE_STR: AddCodeAsm("$0, $1"); break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
auto TEX_SRB = [&]()
|
||||
{
|
||||
switch (m_opcode)
|
||||
{
|
||||
case RSX_FP_OPCODE_DDX: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_DDY: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_NRM: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_BEM: AddCodeAsm("# WARNING"); break;
|
||||
case RSX_FP_OPCODE_TEX: AddCodeAsm("$0, $t"); break;
|
||||
case RSX_FP_OPCODE_TEXBEM: AddCodeAsm("# WARNING"); break;
|
||||
case RSX_FP_OPCODE_TXP: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_TXPBEM: AddCodeAsm("# WARNING"); break;
|
||||
case RSX_FP_OPCODE_TXD: AddCodeAsm("$0, $1, $t"); break;
|
||||
case RSX_FP_OPCODE_TXB: AddCodeAsm("$0, $t"); break;
|
||||
case RSX_FP_OPCODE_TXL: AddCodeAsm("$0, $t"); break;
|
||||
case RSX_FP_OPCODE_UP2: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_UP4: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_UP16: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_UPB: AddCodeAsm("$0"); break;
|
||||
case RSX_FP_OPCODE_UPG: AddCodeAsm("$0"); break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
auto SIP = [&]()
|
||||
{
|
||||
switch (m_opcode)
|
||||
{
|
||||
case RSX_FP_OPCODE_BRK: AddCodeAsm("$cond"); break;
|
||||
case RSX_FP_OPCODE_CAL: AddCodeAsm("$cond"); break;
|
||||
case RSX_FP_OPCODE_FENCT: AddCodeAsm(""); break;
|
||||
case RSX_FP_OPCODE_FENCB: AddCodeAsm(""); break;
|
||||
|
||||
case RSX_FP_OPCODE_IFE:
|
||||
{
|
||||
m_else_offsets.push_back(src1.else_offset << 2);
|
||||
m_end_offsets.push_back(src2.end_offset << 2);
|
||||
AddCodeAsm("($cond)");
|
||||
}
|
||||
break;
|
||||
|
||||
case RSX_FP_OPCODE_LOOP:
|
||||
{
|
||||
if (!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt)
|
||||
{
|
||||
AddCodeAsm(fmt::Format("{ %u, %u, %u }", src1.end_counter, src1.init_counter, src1.increment));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_loop_end_offsets.push_back(src2.end_offset << 2);
|
||||
AddCodeAsm(fmt::Format("{ %u, %u, %u }", src1.end_counter, src1.init_counter, src1.increment));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RSX_FP_OPCODE_REP:
|
||||
{
|
||||
if (!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt)
|
||||
{
|
||||
m_arb_shader += "# RSX_FP_OPCODE_REP_1\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_end_offsets.push_back(src2.end_offset << 2);
|
||||
m_arb_shader += "# RSX_FP_OPCODE_REP_2\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RSX_FP_OPCODE_RET: AddCodeAsm("$cond"); break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
switch (m_opcode)
|
||||
{
|
||||
case RSX_FP_OPCODE_NOP: AddCodeAsm(""); break;
|
||||
case RSX_FP_OPCODE_KIL: AddCodeAsm("$cond"); break;
|
||||
|
||||
default:
|
||||
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)", m_opcode, forced_unit);
|
||||
break;
|
||||
}
|
||||
|
||||
m_size += m_step;
|
||||
|
||||
if (dst.end)
|
||||
{
|
||||
m_arb_shader.pop_back();
|
||||
m_arb_shader += " # last inctruction\nEND\n";
|
||||
break;
|
||||
}
|
||||
|
||||
assert(m_step % sizeof(u32) == 0);
|
||||
data += m_step / sizeof(u32);
|
||||
}
|
||||
}
|
367
rpcs3/Emu/RSX/CgBinaryProgram.h
Normal file
367
rpcs3/Emu/RSX/CgBinaryProgram.h
Normal file
@ -0,0 +1,367 @@
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include "Utilities/rFile.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/RSX/GL/GLVertexProgram.h"
|
||||
#include "Emu/RSX/GL/GLFragmentProgram.h"
|
||||
|
||||
typedef be_t<u32> CGprofile;
|
||||
typedef be_t<s32> CGbool;
|
||||
typedef be_t<u32> CGresource;
|
||||
typedef be_t<u32> CGenum;
|
||||
typedef be_t<u32> CGtype;
|
||||
|
||||
typedef be_t<u32> 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<u32> ucodeCount; // occurances
|
||||
be_t<u32> 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<s32> resIndex; // cgGetParameterResourceIndex()
|
||||
CgBinaryStringOffset name; // cgGetParameterName()
|
||||
CgBinaryFloatOffset defaultValue; // default constant value
|
||||
CgBinaryEmbeddedConstantOffset embeddedConst; // embedded constant information
|
||||
CgBinaryStringOffset semantic; // cgGetParameterSemantic()
|
||||
CGenum direction; // cgGetParameterDirection()
|
||||
be_t<s32> paramno; // 0..n: cgGetParameterIndex() -1: globals
|
||||
CGbool isReferenced; // cgIsParameterReferenced()
|
||||
CGbool isShared; // cgIsParameterShared()
|
||||
};
|
||||
|
||||
// attributes needed for vshaders
|
||||
struct CgBinaryVertexProgram
|
||||
{
|
||||
be_t<u32> instructionCount; // #instructions
|
||||
be_t<u32> instructionSlot; // load address (indexed reads!)
|
||||
be_t<u32> registerCount; // R registers count
|
||||
be_t<u32> attributeInputMask; // attributes vs reads from
|
||||
be_t<u32> attributeOutputMask; // attributes vs writes (uses SET_VERTEX_ATTRIB_OUTPUT_MASK bits)
|
||||
be_t<u32> 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<u32> instructionCount; // #instructions
|
||||
be_t<u32> attributeInputMask; // attributes fp reads (uses SET_VERTEX_ATTRIB_OUTPUT_MASK bits)
|
||||
be_t<u32> partialTexType; // texid 0..15 use two bits each marking whether the texture format requires partial load: see CgBinaryPartialTexType
|
||||
be_t<u16> texCoordsInputMask; // tex coords used by frag prog. (tex<n> is bit n)
|
||||
be_t<u16> texCoords2D; // tex coords that are 2d (tex<n> is bit n)
|
||||
be_t<u16> texCoordsCentroid; // tex coords that are centroid (tex<n> is bit n)
|
||||
u8 registerCount; // R registers count
|
||||
u8 outputFromH0; // final color from R0 or H0
|
||||
u8 depthReplace; // fp generated z epth value
|
||||
u8 pixelKill; // fp uses kill operations
|
||||
};
|
||||
|
||||
struct CgBinaryProgram
|
||||
{
|
||||
// vertex/pixel shader identification (BE/LE as well)
|
||||
CGprofile profile;
|
||||
|
||||
// binary revision (used to verify binary and driver structs match)
|
||||
be_t<u32> binaryFormatRevision;
|
||||
|
||||
// total size of this struct including profile and totalSize field
|
||||
be_t<u32> totalSize;
|
||||
|
||||
// parameter usually queried using cgGet[First/Next]LeafParameter
|
||||
be_t<u32> parameterCount;
|
||||
CgBinaryParameterOffset parameterArray;
|
||||
|
||||
// depending on profile points to a CgBinaryVertexProgram or CgBinaryFragmentProgram struct
|
||||
CgBinaryOffset program;
|
||||
|
||||
// raw ucode data
|
||||
be_t<u32> ucodeSize;
|
||||
CgBinaryOffset ucode;
|
||||
|
||||
// variable length data follows
|
||||
u8 data[1];
|
||||
};
|
||||
|
||||
class CgBinaryDisasm
|
||||
{
|
||||
private:
|
||||
std::string m_path; // used for FP decompiler thread, delete this later
|
||||
|
||||
u8* m_buffer;
|
||||
size_t m_buffer_size;
|
||||
std::string m_arb_shader;
|
||||
std::string m_glsl_shader;
|
||||
std::string m_dst_reg_name;
|
||||
|
||||
// FP members
|
||||
u32 m_offset;
|
||||
u32 m_opcode;
|
||||
u32 m_step;
|
||||
u32 m_size;
|
||||
std::vector<u32> m_end_offsets;
|
||||
std::vector<u32> m_else_offsets;
|
||||
std::vector<u32> m_loop_end_offsets;
|
||||
|
||||
// VP members
|
||||
static const size_t m_max_instr_count = 512;
|
||||
size_t m_instr_count;
|
||||
std::vector<u32> m_data;
|
||||
|
||||
public:
|
||||
|
||||
std::string GetArbShader() const { return m_arb_shader; }
|
||||
std::string GetGlslShader() const { return m_glsl_shader; }
|
||||
|
||||
// FP functions
|
||||
std::string GetMask();
|
||||
void AddCodeAsm(const std::string& code);
|
||||
std::string AddRegDisAsm(u32 index, int fp16);
|
||||
std::string AddConstDisAsm();
|
||||
std::string AddTexDisAsm();
|
||||
std::string FormatDisAsm(const std::string& code);
|
||||
std::string GetCondDisAsm();
|
||||
template<typename T> std::string GetSrcDisAsm(T src);
|
||||
|
||||
CgBinaryDisasm(const std::string& path)
|
||||
: m_path(path)
|
||||
, m_buffer(nullptr)
|
||||
, m_buffer_size(0)
|
||||
, m_offset(0)
|
||||
, m_opcode(0)
|
||||
, m_step(0)
|
||||
, m_size(0)
|
||||
, m_arb_shader("")
|
||||
, m_dst_reg_name("")
|
||||
{
|
||||
rFile f(path);
|
||||
if (!f.IsOpened())
|
||||
return;
|
||||
|
||||
m_buffer_size = f.Length();
|
||||
m_buffer = new u8[m_buffer_size];
|
||||
f.Read(m_buffer, m_buffer_size);
|
||||
f.Close();
|
||||
m_arb_shader += fmt::format("Loading... [%s]\n", path.c_str());
|
||||
}
|
||||
|
||||
~CgBinaryDisasm()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
std::string GetCgParamType(u32 type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 1045: return "float";
|
||||
case 1046:
|
||||
case 1047:
|
||||
case 1048: return fmt::format("float%d", type - 1044);
|
||||
case 1064: return "float4x4";
|
||||
case 1066: return "sampler2D";
|
||||
case 1069: return "samplerCUBE";
|
||||
|
||||
default: return fmt::format("!UnkCgType(%d)", type);
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetCgParamName(u32 offset) const
|
||||
{
|
||||
std::stringstream str_stream;
|
||||
std::string name = "";
|
||||
while (m_buffer[offset] != 0)
|
||||
{
|
||||
str_stream << m_buffer[offset];
|
||||
offset++;
|
||||
}
|
||||
name += str_stream.str();
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string GetCgParamRes(u32 offset) const
|
||||
{
|
||||
// LOG_WARNING(GENERAL, "GetCgParamRes offset 0x%x", offset);
|
||||
// TODO
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string GetCgParamSemantic(u32 offset) const
|
||||
{
|
||||
std::stringstream str_stream;
|
||||
std::string semantic = "";
|
||||
while (m_buffer[offset] != 0)
|
||||
{
|
||||
str_stream << m_buffer[offset];
|
||||
offset++;
|
||||
}
|
||||
semantic += str_stream.str();
|
||||
return semantic;
|
||||
}
|
||||
|
||||
std::string GetCgParamValue(u32 offset, u32 end_offset) const
|
||||
{
|
||||
std::string offsets = "offsets:";
|
||||
|
||||
u32 num = 0;
|
||||
offset += 6;
|
||||
while (offset < end_offset)
|
||||
{
|
||||
offsets += fmt::format(" %d,", m_buffer[offset] << 8 | m_buffer[offset + 1]);
|
||||
offset += 4;
|
||||
num++;
|
||||
}
|
||||
|
||||
if (num > 4)
|
||||
return "";
|
||||
|
||||
offsets.pop_back();
|
||||
return fmt::format("num %d ", num) + offsets;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& GetCgRef(const u32 offset)
|
||||
{
|
||||
return reinterpret_cast<T&>(m_buffer[offset]);
|
||||
}
|
||||
|
||||
void BuildShaderBody()
|
||||
{
|
||||
GLParamArray param_array;
|
||||
|
||||
auto& prog = GetCgRef<CgBinaryProgram>(0);
|
||||
|
||||
if (prog.profile == 7004)
|
||||
{
|
||||
auto& fprog = GetCgRef<CgBinaryFragmentProgram>(prog.program);
|
||||
m_arb_shader += "\n";
|
||||
m_arb_shader += fmt::format("# binaryFormatRevision 0x%x\n", (u32)prog.binaryFormatRevision);
|
||||
m_arb_shader += fmt::format("# profile sce_fp_rsx\n");
|
||||
m_arb_shader += fmt::format("# parameterCount %d\n", (u32)prog.parameterCount);
|
||||
m_arb_shader += fmt::format("# instructionCount %d\n", (u32)fprog.instructionCount);
|
||||
m_arb_shader += fmt::format("# attributeInputMask 0x%x\n", (u32)fprog.attributeInputMask);
|
||||
m_arb_shader += fmt::format("# registerCount %d\n\n", (u32)fprog.registerCount);
|
||||
|
||||
CgBinaryParameterOffset offset = prog.parameterArray;
|
||||
for (u32 i = 0; i < (u32)prog.parameterCount; i++)
|
||||
{
|
||||
auto& fparam = GetCgRef<CgBinaryParameter>(offset);
|
||||
|
||||
std::string param_type = GetCgParamType(fparam.type) + " ";
|
||||
std::string param_name = GetCgParamName(fparam.name) + " ";
|
||||
std::string param_res = GetCgParamRes(fparam.res) + " ";
|
||||
std::string param_semantic = GetCgParamSemantic(fparam.semantic) + " ";
|
||||
std::string param_const = GetCgParamValue(fparam.embeddedConst, fparam.name);
|
||||
|
||||
m_arb_shader += fmt::format("#%d ", i) + param_type + param_name + param_semantic + param_const + "\n";
|
||||
|
||||
offset += sizeof(CgBinaryParameter);
|
||||
}
|
||||
|
||||
m_arb_shader += "\n";
|
||||
m_offset = prog.ucode;
|
||||
TaskFP();
|
||||
|
||||
// reload binary data in the virtual memory, temporary solution
|
||||
{
|
||||
u32 ptr;
|
||||
{
|
||||
rFile f(m_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();
|
||||
}
|
||||
|
||||
auto& vmprog = vm::get_ref<CgBinaryProgram>(ptr);
|
||||
auto& vmfprog = vm::get_ref<CgBinaryFragmentProgram>(ptr + vmprog.program);
|
||||
u32 size;
|
||||
u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0);
|
||||
GLFragmentDecompilerThread(m_glsl_shader, param_array, ptr + vmprog.ucode, size, ctrl).Task();
|
||||
vm::close();
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
auto& vprog = GetCgRef<CgBinaryVertexProgram>(prog.program);
|
||||
m_arb_shader += "\n";
|
||||
m_arb_shader += fmt::format("# binaryFormatRevision 0x%x\n", (u32)prog.binaryFormatRevision);
|
||||
m_arb_shader += fmt::format("# profile sce_vp_rsx\n");
|
||||
m_arb_shader += fmt::format("# parameterCount %d\n", (u32)prog.parameterCount);
|
||||
m_arb_shader += fmt::format("# instructionCount %d\n", (u32)vprog.instructionCount);
|
||||
m_arb_shader += fmt::format("# registerCount %d\n", (u32)vprog.registerCount);
|
||||
m_arb_shader += fmt::format("# attributeInputMask 0x%x\n", (u32)vprog.attributeInputMask);
|
||||
m_arb_shader += fmt::format("# attributeOutputMask 0x%x\n\n", (u32)vprog.attributeOutputMask);
|
||||
|
||||
CgBinaryParameterOffset offset = prog.parameterArray;
|
||||
for (u32 i = 0; i < (u32)prog.parameterCount; i++)
|
||||
{
|
||||
auto& vparam = GetCgRef<CgBinaryParameter>(offset);
|
||||
|
||||
std::string param_type = GetCgParamType(vparam.type) + " ";
|
||||
std::string param_name = GetCgParamName(vparam.name) + " ";
|
||||
std::string param_res = GetCgParamRes(vparam.res) + " ";
|
||||
std::string param_semantic = GetCgParamSemantic(vparam.semantic) + " ";
|
||||
std::string param_const = GetCgParamValue(vparam.embeddedConst, vparam.name);
|
||||
|
||||
m_arb_shader += fmt::format("#%d ", i) + param_type + param_name + param_semantic + param_const + "\n";
|
||||
|
||||
offset += sizeof(CgBinaryParameter);
|
||||
}
|
||||
|
||||
m_arb_shader += "\n";
|
||||
m_offset = prog.ucode;
|
||||
|
||||
u32* vdata = (u32*)&m_buffer[m_offset];
|
||||
assert((m_buffer_size - m_offset) % sizeof(u32) == 0);
|
||||
for (u32 i = 0; i < (m_buffer_size - m_offset) / sizeof(u32); i++)
|
||||
{
|
||||
vdata[i] = re32(vdata[i]);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < prog.ucodeSize / sizeof(u32); i++)
|
||||
{
|
||||
m_data.push_back(vdata[i]);
|
||||
}
|
||||
|
||||
//TaskVP();
|
||||
GLVertexDecompilerThread(m_data, m_glsl_shader, param_array).Task();
|
||||
}
|
||||
}
|
||||
|
||||
u32 GetData(const u32 d) const { return d << 16 | d >> 16; }
|
||||
void TaskFP();
|
||||
//void TaskVP(); // TODO
|
||||
};
|
@ -5,118 +5,6 @@
|
||||
|
||||
struct GLFragmentDecompilerThread : public ThreadBase
|
||||
{
|
||||
union OPDEST
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 end : 1; // Set to 1 if this is the last instruction
|
||||
u32 dest_reg : 6; // Destination register index
|
||||
u32 fp16 : 1; // Destination is a half register (H0 to H47)
|
||||
u32 set_cond : 1; // Condition Code Registers (CC0 and CC1) are updated
|
||||
u32 mask_x : 1;
|
||||
u32 mask_y : 1;
|
||||
u32 mask_z : 1;
|
||||
u32 mask_w : 1;
|
||||
u32 src_attr_reg_num : 4;
|
||||
u32 tex_num : 4;
|
||||
u32 exp_tex : 1; // _bx2
|
||||
u32 prec : 2;
|
||||
u32 opcode : 6;
|
||||
u32 no_dest : 1;
|
||||
u32 saturate : 1; // _sat
|
||||
};
|
||||
} dst;
|
||||
|
||||
union SRC0
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_reg_index : 6;
|
||||
u32 fp16 : 1;
|
||||
u32 swizzle_x : 2;
|
||||
u32 swizzle_y : 2;
|
||||
u32 swizzle_z : 2;
|
||||
u32 swizzle_w : 2;
|
||||
u32 neg : 1;
|
||||
u32 exec_if_lt : 1;
|
||||
u32 exec_if_eq : 1;
|
||||
u32 exec_if_gr : 1;
|
||||
u32 cond_swizzle_x : 2;
|
||||
u32 cond_swizzle_y : 2;
|
||||
u32 cond_swizzle_z : 2;
|
||||
u32 cond_swizzle_w : 2;
|
||||
u32 abs : 1;
|
||||
u32 cond_mod_reg_index : 1;
|
||||
u32 cond_reg_index : 1;
|
||||
};
|
||||
} src0;
|
||||
|
||||
union SRC1
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_reg_index : 6;
|
||||
u32 fp16 : 1;
|
||||
u32 swizzle_x : 2;
|
||||
u32 swizzle_y : 2;
|
||||
u32 swizzle_z : 2;
|
||||
u32 swizzle_w : 2;
|
||||
u32 neg : 1;
|
||||
u32 abs : 1;
|
||||
u32 input_mod_src0 : 3;
|
||||
u32 : 6;
|
||||
u32 scale : 3;
|
||||
u32 opcode_is_branch : 1;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 else_offset : 31;
|
||||
u32 : 1;
|
||||
};
|
||||
|
||||
// LOOP, REP
|
||||
struct
|
||||
{
|
||||
u32 : 2;
|
||||
u32 end_counter : 8; // End counter value for LOOP or rep count for REP
|
||||
u32 init_counter : 8; // Initial counter value for LOOP
|
||||
u32 : 1;
|
||||
u32 increment : 8; // Increment value for LOOP
|
||||
};
|
||||
} src1;
|
||||
|
||||
union SRC2
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
u32 end_offset;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_reg_index : 6;
|
||||
u32 fp16 : 1;
|
||||
u32 swizzle_x : 2;
|
||||
u32 swizzle_y : 2;
|
||||
u32 swizzle_z : 2;
|
||||
u32 swizzle_w : 2;
|
||||
u32 neg : 1;
|
||||
u32 abs : 1;
|
||||
u32 addr_reg : 11;
|
||||
u32 use_index_reg : 1;
|
||||
u32 perspective_corr : 1;
|
||||
};
|
||||
} src2;
|
||||
|
||||
std::string main;
|
||||
std::string& m_shader;
|
||||
GLParamArray& m_parr;
|
||||
|
@ -4,184 +4,8 @@
|
||||
#include "Utilities/Thread.h"
|
||||
#include <set>
|
||||
|
||||
enum sca_opcode
|
||||
{
|
||||
RSX_SCA_OPCODE_NOP = 0x00,
|
||||
RSX_SCA_OPCODE_MOV = 0x01,
|
||||
RSX_SCA_OPCODE_RCP = 0x02,
|
||||
RSX_SCA_OPCODE_RCC = 0x03,
|
||||
RSX_SCA_OPCODE_RSQ = 0x04,
|
||||
RSX_SCA_OPCODE_EXP = 0x05,
|
||||
RSX_SCA_OPCODE_LOG = 0x06,
|
||||
RSX_SCA_OPCODE_LIT = 0x07,
|
||||
RSX_SCA_OPCODE_BRA = 0x08,
|
||||
RSX_SCA_OPCODE_BRI = 0x09,
|
||||
RSX_SCA_OPCODE_CAL = 0x0a,
|
||||
RSX_SCA_OPCODE_CLI = 0x0b,
|
||||
RSX_SCA_OPCODE_RET = 0x0c,
|
||||
RSX_SCA_OPCODE_LG2 = 0x0d,
|
||||
RSX_SCA_OPCODE_EX2 = 0x0e,
|
||||
RSX_SCA_OPCODE_SIN = 0x0f,
|
||||
RSX_SCA_OPCODE_COS = 0x10,
|
||||
RSX_SCA_OPCODE_BRB = 0x11,
|
||||
RSX_SCA_OPCODE_CLB = 0x12,
|
||||
RSX_SCA_OPCODE_PSH = 0x13,
|
||||
RSX_SCA_OPCODE_POP = 0x14,
|
||||
};
|
||||
|
||||
enum vec_opcode
|
||||
{
|
||||
RSX_VEC_OPCODE_NOP = 0x00,
|
||||
RSX_VEC_OPCODE_MOV = 0x01,
|
||||
RSX_VEC_OPCODE_MUL = 0x02,
|
||||
RSX_VEC_OPCODE_ADD = 0x03,
|
||||
RSX_VEC_OPCODE_MAD = 0x04,
|
||||
RSX_VEC_OPCODE_DP3 = 0x05,
|
||||
RSX_VEC_OPCODE_DPH = 0x06,
|
||||
RSX_VEC_OPCODE_DP4 = 0x07,
|
||||
RSX_VEC_OPCODE_DST = 0x08,
|
||||
RSX_VEC_OPCODE_MIN = 0x09,
|
||||
RSX_VEC_OPCODE_MAX = 0x0a,
|
||||
RSX_VEC_OPCODE_SLT = 0x0b,
|
||||
RSX_VEC_OPCODE_SGE = 0x0c,
|
||||
RSX_VEC_OPCODE_ARL = 0x0d,
|
||||
RSX_VEC_OPCODE_FRC = 0x0e,
|
||||
RSX_VEC_OPCODE_FLR = 0x0f,
|
||||
RSX_VEC_OPCODE_SEQ = 0x10,
|
||||
RSX_VEC_OPCODE_SFL = 0x11,
|
||||
RSX_VEC_OPCODE_SGT = 0x12,
|
||||
RSX_VEC_OPCODE_SLE = 0x13,
|
||||
RSX_VEC_OPCODE_SNE = 0x14,
|
||||
RSX_VEC_OPCODE_STR = 0x15,
|
||||
RSX_VEC_OPCODE_SSG = 0x16,
|
||||
RSX_VEC_OPCODE_TEX = 0x19,
|
||||
};
|
||||
|
||||
struct GLVertexDecompilerThread : public ThreadBase
|
||||
{
|
||||
union D0
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 addr_swz : 2;
|
||||
u32 mask_w : 2;
|
||||
u32 mask_z : 2;
|
||||
u32 mask_y : 2;
|
||||
u32 mask_x : 2;
|
||||
u32 cond : 3;
|
||||
u32 cond_test_enable : 1;
|
||||
u32 cond_update_enable_0 : 1;
|
||||
u32 dst_tmp : 6;
|
||||
u32 src0_abs : 1;
|
||||
u32 src1_abs : 1;
|
||||
u32 src2_abs : 1;
|
||||
u32 addr_reg_sel_1 : 1;
|
||||
u32 cond_reg_sel_1 : 1;
|
||||
u32 staturate : 1;
|
||||
u32 index_input : 1;
|
||||
u32 : 1;
|
||||
u32 cond_update_enable_1 : 1;
|
||||
u32 vec_result : 1;
|
||||
u32 : 1;
|
||||
};
|
||||
} d0;
|
||||
|
||||
union D1
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src0h : 8;
|
||||
u32 input_src : 4;
|
||||
u32 const_src : 10;
|
||||
u32 vec_opcode : 5;
|
||||
u32 sca_opcode : 5;
|
||||
};
|
||||
} d1;
|
||||
|
||||
union D2
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src2h : 6;
|
||||
u32 src1 : 17;
|
||||
u32 src0l : 9;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 iaddrh : 6;
|
||||
u32 : 26;
|
||||
};
|
||||
} d2;
|
||||
|
||||
union D3
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 end : 1;
|
||||
u32 index_const : 1;
|
||||
u32 dst : 5;
|
||||
u32 sca_dst_tmp : 6;
|
||||
u32 vec_writemask_w : 1;
|
||||
u32 vec_writemask_z : 1;
|
||||
u32 vec_writemask_y : 1;
|
||||
u32 vec_writemask_x : 1;
|
||||
u32 sca_writemask_w : 1;
|
||||
u32 sca_writemask_z : 1;
|
||||
u32 sca_writemask_y : 1;
|
||||
u32 sca_writemask_x : 1;
|
||||
u32 src2l : 11;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 : 29;
|
||||
u32 iaddrl : 3;
|
||||
};
|
||||
} d3;
|
||||
|
||||
union SRC
|
||||
{
|
||||
union
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src0l : 9;
|
||||
u32 src0h : 8;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src1 : 17;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src2l : 11;
|
||||
u32 src2h : 6;
|
||||
};
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_src : 6;
|
||||
u32 swz_w : 2;
|
||||
u32 swz_z : 2;
|
||||
u32 swz_y : 2;
|
||||
u32 swz_x : 2;
|
||||
u32 neg : 1;
|
||||
};
|
||||
} src[3];
|
||||
|
||||
struct FuncInfo
|
||||
{
|
||||
u32 offset;
|
||||
|
@ -71,6 +71,139 @@ enum
|
||||
RSX_FP_OPCODE_RET = 0x45, // Return
|
||||
};
|
||||
|
||||
static union OPDEST
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 end : 1; // Set to 1 if this is the last instruction
|
||||
u32 dest_reg : 6; // Destination register index
|
||||
u32 fp16 : 1; // Destination is a half register (H0 to H47)
|
||||
u32 set_cond : 1; // Condition Code Registers (CC0 and CC1) are updated
|
||||
u32 mask_x : 1;
|
||||
u32 mask_y : 1;
|
||||
u32 mask_z : 1;
|
||||
u32 mask_w : 1;
|
||||
u32 src_attr_reg_num : 4;
|
||||
u32 tex_num : 4;
|
||||
u32 exp_tex : 1; // _bx2
|
||||
u32 prec : 2;
|
||||
u32 opcode : 6;
|
||||
u32 no_dest : 1;
|
||||
u32 saturate : 1; // _sat
|
||||
};
|
||||
} dst;
|
||||
|
||||
static union SRC0
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_reg_index : 6;
|
||||
u32 fp16 : 1;
|
||||
u32 swizzle_x : 2;
|
||||
u32 swizzle_y : 2;
|
||||
u32 swizzle_z : 2;
|
||||
u32 swizzle_w : 2;
|
||||
u32 neg : 1;
|
||||
u32 exec_if_lt : 1;
|
||||
u32 exec_if_eq : 1;
|
||||
u32 exec_if_gr : 1;
|
||||
u32 cond_swizzle_x : 2;
|
||||
u32 cond_swizzle_y : 2;
|
||||
u32 cond_swizzle_z : 2;
|
||||
u32 cond_swizzle_w : 2;
|
||||
u32 abs : 1;
|
||||
u32 cond_mod_reg_index : 1;
|
||||
u32 cond_reg_index : 1;
|
||||
};
|
||||
} src0;
|
||||
|
||||
static union SRC1
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_reg_index : 6;
|
||||
u32 fp16 : 1;
|
||||
u32 swizzle_x : 2;
|
||||
u32 swizzle_y : 2;
|
||||
u32 swizzle_z : 2;
|
||||
u32 swizzle_w : 2;
|
||||
u32 neg : 1;
|
||||
u32 abs : 1;
|
||||
u32 input_mod_src0 : 3;
|
||||
u32 : 6;
|
||||
u32 scale : 3;
|
||||
u32 opcode_is_branch : 1;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 else_offset : 31;
|
||||
u32 : 1;
|
||||
};
|
||||
|
||||
// LOOP, REP
|
||||
struct
|
||||
{
|
||||
u32 : 2;
|
||||
u32 end_counter : 8; // End counter value for LOOP or rep count for REP
|
||||
u32 init_counter : 8; // Initial counter value for LOOP
|
||||
u32 : 1;
|
||||
u32 increment : 8; // Increment value for LOOP
|
||||
};
|
||||
} src1;
|
||||
|
||||
static union SRC2
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
u32 end_offset;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_reg_index : 6;
|
||||
u32 fp16 : 1;
|
||||
u32 swizzle_x : 2;
|
||||
u32 swizzle_y : 2;
|
||||
u32 swizzle_z : 2;
|
||||
u32 swizzle_w : 2;
|
||||
u32 neg : 1;
|
||||
u32 abs : 1;
|
||||
u32 addr_reg : 11;
|
||||
u32 use_index_reg : 1;
|
||||
u32 perspective_corr : 1;
|
||||
};
|
||||
} src2;
|
||||
|
||||
static const char* rsx_fp_input_attr_regs[] =
|
||||
{
|
||||
"WPOS", "COL0", "COL1", "FOGC", "TEX0",
|
||||
"TEX1", "TEX2", "TEX3", "TEX4", "TEX5",
|
||||
"TEX6", "TEX7", "TEX8", "TEX9", "SSA"
|
||||
};
|
||||
|
||||
static const std::string rsx_fp_op_names[] =
|
||||
{
|
||||
"NOP", "MOV", "MUL", "ADD", "MAD", "DP3", "DP4",
|
||||
"DST", "MIN", "MAX", "SLT", "SGE", "SLE", "SGT",
|
||||
"SNE", "SEQ", "FRC", "FLR", "KIL", "PK4", "UP4",
|
||||
"DDX", "DDY", "TEX", "TXP", "TXD", "RCP", "RSQ",
|
||||
"EX2", "LG2", "LIT", "LRP", "STR", "SFL", "COS",
|
||||
"SIN", "PK2", "UP2", "POW", "PKB", "UPB", "PK16",
|
||||
"UP16", "BEM", "PKG", "UPG", "DP2A", "TXL", "NULL",
|
||||
"TXB", "NULL", "TEXBEM", "TXPBEM", "BEMLUM", "REFL", "TIMESWTEX",
|
||||
"DP2", "NRM", "DIV", "DIVSQ", "LIF", "FENCT", "FENCB",
|
||||
"NULL", "BRK", "CAL", "IFE", "LOOP", "REP", "RET"
|
||||
};
|
||||
|
||||
struct RSXFragmentProgram
|
||||
{
|
||||
u32 size;
|
||||
|
@ -1,5 +1,195 @@
|
||||
#pragma once
|
||||
|
||||
enum sca_opcode
|
||||
{
|
||||
RSX_SCA_OPCODE_NOP = 0x00,
|
||||
RSX_SCA_OPCODE_MOV = 0x01,
|
||||
RSX_SCA_OPCODE_RCP = 0x02,
|
||||
RSX_SCA_OPCODE_RCC = 0x03,
|
||||
RSX_SCA_OPCODE_RSQ = 0x04,
|
||||
RSX_SCA_OPCODE_EXP = 0x05,
|
||||
RSX_SCA_OPCODE_LOG = 0x06,
|
||||
RSX_SCA_OPCODE_LIT = 0x07,
|
||||
RSX_SCA_OPCODE_BRA = 0x08,
|
||||
RSX_SCA_OPCODE_BRI = 0x09,
|
||||
RSX_SCA_OPCODE_CAL = 0x0a,
|
||||
RSX_SCA_OPCODE_CLI = 0x0b,
|
||||
RSX_SCA_OPCODE_RET = 0x0c,
|
||||
RSX_SCA_OPCODE_LG2 = 0x0d,
|
||||
RSX_SCA_OPCODE_EX2 = 0x0e,
|
||||
RSX_SCA_OPCODE_SIN = 0x0f,
|
||||
RSX_SCA_OPCODE_COS = 0x10,
|
||||
RSX_SCA_OPCODE_BRB = 0x11,
|
||||
RSX_SCA_OPCODE_CLB = 0x12,
|
||||
RSX_SCA_OPCODE_PSH = 0x13,
|
||||
RSX_SCA_OPCODE_POP = 0x14
|
||||
};
|
||||
|
||||
enum vec_opcode
|
||||
{
|
||||
RSX_VEC_OPCODE_NOP = 0x00,
|
||||
RSX_VEC_OPCODE_MOV = 0x01,
|
||||
RSX_VEC_OPCODE_MUL = 0x02,
|
||||
RSX_VEC_OPCODE_ADD = 0x03,
|
||||
RSX_VEC_OPCODE_MAD = 0x04,
|
||||
RSX_VEC_OPCODE_DP3 = 0x05,
|
||||
RSX_VEC_OPCODE_DPH = 0x06,
|
||||
RSX_VEC_OPCODE_DP4 = 0x07,
|
||||
RSX_VEC_OPCODE_DST = 0x08,
|
||||
RSX_VEC_OPCODE_MIN = 0x09,
|
||||
RSX_VEC_OPCODE_MAX = 0x0a,
|
||||
RSX_VEC_OPCODE_SLT = 0x0b,
|
||||
RSX_VEC_OPCODE_SGE = 0x0c,
|
||||
RSX_VEC_OPCODE_ARL = 0x0d,
|
||||
RSX_VEC_OPCODE_FRC = 0x0e,
|
||||
RSX_VEC_OPCODE_FLR = 0x0f,
|
||||
RSX_VEC_OPCODE_SEQ = 0x10,
|
||||
RSX_VEC_OPCODE_SFL = 0x11,
|
||||
RSX_VEC_OPCODE_SGT = 0x12,
|
||||
RSX_VEC_OPCODE_SLE = 0x13,
|
||||
RSX_VEC_OPCODE_SNE = 0x14,
|
||||
RSX_VEC_OPCODE_STR = 0x15,
|
||||
RSX_VEC_OPCODE_SSG = 0x16,
|
||||
RSX_VEC_OPCODE_TEX = 0x19
|
||||
};
|
||||
|
||||
static union D0
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 addr_swz : 2;
|
||||
u32 mask_w : 2;
|
||||
u32 mask_z : 2;
|
||||
u32 mask_y : 2;
|
||||
u32 mask_x : 2;
|
||||
u32 cond : 3;
|
||||
u32 cond_test_enable : 1;
|
||||
u32 cond_update_enable_0 : 1;
|
||||
u32 dst_tmp : 6;
|
||||
u32 src0_abs : 1;
|
||||
u32 src1_abs : 1;
|
||||
u32 src2_abs : 1;
|
||||
u32 addr_reg_sel_1 : 1;
|
||||
u32 cond_reg_sel_1 : 1;
|
||||
u32 staturate : 1;
|
||||
u32 index_input : 1;
|
||||
u32 : 1;
|
||||
u32 cond_update_enable_1 : 1;
|
||||
u32 vec_result : 1;
|
||||
u32 : 1;
|
||||
};
|
||||
} d0;
|
||||
|
||||
static union D1
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src0h : 8;
|
||||
u32 input_src : 4;
|
||||
u32 const_src : 10;
|
||||
u32 vec_opcode : 5;
|
||||
u32 sca_opcode : 5;
|
||||
};
|
||||
} d1;
|
||||
|
||||
static union D2
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src2h : 6;
|
||||
u32 src1 : 17;
|
||||
u32 src0l : 9;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 iaddrh : 6;
|
||||
u32 : 26;
|
||||
};
|
||||
} d2;
|
||||
|
||||
static union D3
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 end : 1;
|
||||
u32 index_const : 1;
|
||||
u32 dst : 5;
|
||||
u32 sca_dst_tmp : 6;
|
||||
u32 vec_writemask_w : 1;
|
||||
u32 vec_writemask_z : 1;
|
||||
u32 vec_writemask_y : 1;
|
||||
u32 vec_writemask_x : 1;
|
||||
u32 sca_writemask_w : 1;
|
||||
u32 sca_writemask_z : 1;
|
||||
u32 sca_writemask_y : 1;
|
||||
u32 sca_writemask_x : 1;
|
||||
u32 src2l : 11;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 : 29;
|
||||
u32 iaddrl : 3;
|
||||
};
|
||||
} d3;
|
||||
|
||||
static union SRC
|
||||
{
|
||||
union
|
||||
{
|
||||
u32 HEX;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src0l : 9;
|
||||
u32 src0h : 8;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src1 : 17;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 src2l : 11;
|
||||
u32 src2h : 6;
|
||||
};
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_src : 6;
|
||||
u32 swz_w : 2;
|
||||
u32 swz_z : 2;
|
||||
u32 swz_y : 2;
|
||||
u32 swz_x : 2;
|
||||
u32 neg : 1;
|
||||
};
|
||||
} src[3];
|
||||
|
||||
static const std::string rsx_vp_sca_op_names[] =
|
||||
{
|
||||
"NOP", "MOV", "RCP", "RCC", "RSQ", "EXP", "LOG",
|
||||
"LIT", "BRA", "BRI", "CAL", "CLI", "RET", "LG2",
|
||||
"EX2", "SIN", "COS", "BRB", "CLB", "PSH", "POP"
|
||||
};
|
||||
|
||||
static const std::string rsx_vp_vec_op_names[] =
|
||||
{
|
||||
"NOP", "MOV", "MUL", "ADD", "MAD", "DP3", "DPH", "DP4",
|
||||
"DST", "MIN", "MAX", "SLT", "SGE", "ARL", "FRC", "FLR",
|
||||
"SEQ", "SFL", "SGT", "SLE", "SNE", "STR", "SSG", "TEX"
|
||||
};
|
||||
|
||||
struct RSXVertexProgram
|
||||
{
|
||||
std::vector<u32> data;
|
||||
|
58
rpcs3/Gui/CgDisasm.cpp
Normal file
58
rpcs3/Gui/CgDisasm.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "stdafx_gui.h"
|
||||
|
||||
#include "CgDisasm.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/RSX/CgBinaryProgram.h"
|
||||
|
||||
BEGIN_EVENT_TABLE(CgDisasm, wxFrame)
|
||||
EVT_SIZE(CgDisasm::OnSize)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
CgDisasm::CgDisasm(wxWindow* parent)
|
||||
: wxFrame(parent, wxID_ANY, "Cg Disasm", wxDefaultPosition, wxSize(640, 480))
|
||||
{
|
||||
wxMenuBar* menubar = new wxMenuBar();
|
||||
|
||||
wxMenu* menu_general = new wxMenu();
|
||||
menubar->Append(menu_general, "&Open");
|
||||
menu_general->Append(id_open_file, "Open &Cg binary program");
|
||||
|
||||
wxNotebook* nb_cg = new wxNotebook(this, wxID_ANY);
|
||||
wxPanel* p_cg_disasm = new wxPanel(nb_cg, wxID_ANY);
|
||||
wxPanel* p_glsl_shader = new wxPanel(nb_cg, wxID_ANY);
|
||||
|
||||
nb_cg->AddPage(p_cg_disasm, wxT("ASM"));
|
||||
nb_cg->AddPage(p_glsl_shader, wxT("GLSL"));
|
||||
|
||||
m_disasm_text = new wxTextCtrl(p_cg_disasm, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(620, 395), wxTE_MULTILINE | wxNO_BORDER | wxTE_READONLY | wxTE_RICH2);
|
||||
m_glsl_text = new wxTextCtrl(p_glsl_shader, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(620, 395), wxTE_MULTILINE | wxNO_BORDER | wxTE_READONLY | wxTE_RICH2);
|
||||
|
||||
SetMenuBar(menubar);
|
||||
|
||||
Bind(wxEVT_MENU, &CgDisasm::OpenCg, this, id_open_file);
|
||||
}
|
||||
|
||||
void CgDisasm::OpenCg(wxCommandEvent& event)
|
||||
{
|
||||
wxFileDialog ctrl(this, L"Select Cg program object", wxEmptyString, wxEmptyString,
|
||||
"Cg program objects (*.fpo;*.vpo)|*.fpo;*.vpo"
|
||||
"|All files (*.*)|*.*",
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
|
||||
if (ctrl.ShowModal() == wxID_CANCEL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CgBinaryDisasm disasm(fmt::ToUTF8(ctrl.GetPath()));
|
||||
disasm.BuildShaderBody();
|
||||
*m_disasm_text << disasm.GetArbShader();
|
||||
*m_glsl_text << disasm.GetGlslShader();
|
||||
}
|
||||
|
||||
void CgDisasm::OnSize(wxSizeEvent& event)
|
||||
{
|
||||
m_disasm_text->SetSize(GetSize().x - 20, GetSize().y - 85);
|
||||
m_glsl_text->SetSize(GetSize().x - 20, GetSize().y - 85);
|
||||
event.Skip();
|
||||
}
|
22
rpcs3/Gui/CgDisasm.h
Normal file
22
rpcs3/Gui/CgDisasm.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
enum CgDisasmIds
|
||||
{
|
||||
id_open_file
|
||||
};
|
||||
|
||||
class CgDisasm : public wxFrame
|
||||
{
|
||||
private:
|
||||
wxTextCtrl* m_disasm_text;
|
||||
wxTextCtrl* m_glsl_text;
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
public:
|
||||
CgDisasm(wxWindow* parent);
|
||||
|
||||
void OpenCg(wxCommandEvent& event);
|
||||
virtual void OnSize(wxSizeEvent& event);
|
||||
};
|
@ -22,6 +22,7 @@
|
||||
#include "Gui/RSXDebugger.h"
|
||||
#include "Gui/MemoryStringSearcher.h"
|
||||
#include "Gui/LLEModulesManager.h"
|
||||
#include "Gui/CgDisasm.h"
|
||||
|
||||
#include <wx/dynlib.h>
|
||||
|
||||
@ -53,8 +54,9 @@ enum IDs
|
||||
id_tools_memory_viewer,
|
||||
id_tools_rsx_debugger,
|
||||
id_tools_string_search,
|
||||
id_tools_cg_disasm,
|
||||
id_help_about,
|
||||
id_update_dbg,
|
||||
id_update_dbg
|
||||
};
|
||||
|
||||
wxString GetPaneName()
|
||||
@ -111,6 +113,7 @@ MainFrame::MainFrame()
|
||||
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);
|
||||
menu_tools->Append(id_tools_cg_disasm, "&Cg Disasm")->Enable();
|
||||
|
||||
wxMenu* menu_help = new wxMenu();
|
||||
menubar->Append(menu_help, "&Help");
|
||||
@ -151,6 +154,7 @@ MainFrame::MainFrame()
|
||||
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::OpenCgDisasm, this, id_tools_cg_disasm);
|
||||
|
||||
Bind(wxEVT_MENU, &MainFrame::AboutDialogHandler, this, id_help_about);
|
||||
|
||||
@ -722,6 +726,11 @@ void MainFrame::OpenStringSearch(wxCommandEvent& WXUNUSED(event))
|
||||
(new MemoryStringSearcher(this)) -> Show();
|
||||
}
|
||||
|
||||
void MainFrame::OpenCgDisasm(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
(new CgDisasm(this))->Show();
|
||||
}
|
||||
|
||||
void MainFrame::AboutDialogHandler(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
AboutDialog(this).ShowModal();
|
||||
|
@ -46,7 +46,7 @@ private:
|
||||
void OpenMemoryViewer(wxCommandEvent& evt);
|
||||
void OpenRSXDebugger(wxCommandEvent& evt);
|
||||
void OpenStringSearch(wxCommandEvent& evt);
|
||||
void OpenFnIdGenerator(wxCommandEvent& evt);
|
||||
void OpenCgDisasm(wxCommandEvent& evt);
|
||||
void AboutDialogHandler(wxCommandEvent& event);
|
||||
void UpdateUI(wxCommandEvent& event);
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
|
@ -37,6 +37,7 @@
|
||||
<ClCompile Include="..\Utilities\SSemaphore.cpp" />
|
||||
<ClCompile Include="..\Utilities\StrFmt.cpp" />
|
||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||
<ClCompile Include="Emu\RSX\CgBinaryFragmentProgram.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellSpursSpu.cpp" />
|
||||
<ClCompile Include="Crypto\aes.cpp" />
|
||||
<ClCompile Include="Crypto\ec.cpp" />
|
||||
@ -409,6 +410,7 @@
|
||||
<ClInclude Include="Emu\Memory\Memory.h" />
|
||||
<ClInclude Include="Emu\Memory\MemoryBlock.h" />
|
||||
<ClInclude Include="Emu\Memory\atomic_type.h" />
|
||||
<ClInclude Include="Emu\RSX\CgBinaryProgram.h" />
|
||||
<ClInclude Include="Emu\RSX\GCM.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\GLBuffers.h" />
|
||||
<ClInclude Include="Emu\RSX\GL\GLFragmentProgram.h" />
|
||||
|
@ -854,6 +854,9 @@
|
||||
<ClCompile Include="Emu\ARMv7\Modules\psv_cond.cpp">
|
||||
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\CgBinaryFragmentProgram.cpp">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
@ -1519,5 +1522,8 @@
|
||||
<ClInclude Include="Emu\ARMv7\Modules\psv_cond.h">
|
||||
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\CgBinaryProgram.h">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
160
rpcs3/rpcs3.cpp
160
rpcs3/rpcs3.cpp
@ -43,163 +43,6 @@ Rpcs3App* TheApp;
|
||||
|
||||
std::string simplify_path(const std::string& path, bool is_dir);
|
||||
|
||||
typedef be_t<uint> CGprofile;
|
||||
typedef int CGbool;
|
||||
typedef be_t<uint> CGresource;
|
||||
typedef be_t<uint> CGenum;
|
||||
typedef be_t<uint> CGtype;
|
||||
|
||||
typedef be_t<unsigned int> 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<unsigned int> ucodeCount; // occurances
|
||||
be_t<unsigned int> 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<int> resIndex; // cgGetParameterResourceIndex()
|
||||
CgBinaryStringOffset name; // cgGetParameterName()
|
||||
CgBinaryFloatOffset defaultValue; // default constant value
|
||||
CgBinaryEmbeddedConstantOffset embeddedConst; // embedded constant information
|
||||
CgBinaryStringOffset semantic; // cgGetParameterSemantic()
|
||||
CGenum direction; // cgGetParameterDirection()
|
||||
be_t<int> paramno; // 0..n: cgGetParameterIndex() -1: globals
|
||||
CGbool isReferenced; // cgIsParameterReferenced()
|
||||
CGbool isShared; // cgIsParameterShared()
|
||||
};
|
||||
|
||||
// attributes needed for vshaders
|
||||
struct CgBinaryVertexProgram
|
||||
{
|
||||
be_t<unsigned int> instructionCount; // #instructions
|
||||
be_t<unsigned int> instructionSlot; // load address (indexed reads!)
|
||||
be_t<unsigned int> registerCount; // R registers count
|
||||
be_t<unsigned int> attributeInputMask; // attributes vs reads from
|
||||
be_t<unsigned int> attributeOutputMask; // attributes vs writes (uses SET_VERTEX_ATTRIB_OUTPUT_MASK bits)
|
||||
be_t<unsigned int> 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<unsigned int> instructionCount; // #instructions
|
||||
be_t<unsigned int> attributeInputMask; // attributes fp reads (uses SET_VERTEX_ATTRIB_OUTPUT_MASK bits)
|
||||
be_t<unsigned int> partialTexType; // texid 0..15 use two bits each marking whether the texture format requires partial load: see CgBinaryPartialTexType
|
||||
be_t<unsigned short> texCoordsInputMask; // tex coords used by frag prog. (tex<n> is bit n)
|
||||
be_t<unsigned short> texCoords2D; // tex coords that are 2d (tex<n> is bit n)
|
||||
be_t<unsigned short> texCoordsCentroid; // tex coords that are centroid (tex<n> 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<unsigned int> binaryFormatRevision;
|
||||
|
||||
// total size of this struct including profile and totalSize field!
|
||||
be_t<unsigned int> totalSize;
|
||||
|
||||
// parameter usually queried using cgGet[First/Next]LeafParameter
|
||||
be_t<unsigned int> parameterCount;
|
||||
CgBinaryParameterOffset parameterArray;
|
||||
|
||||
// depending on profile points to a CgBinaryVertexProgram or CgBinaryFragmentProgram struct
|
||||
CgBinaryOffset program;
|
||||
|
||||
// raw ucode data
|
||||
be_t<unsigned int> 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<CgBinaryProgram>(ptr);
|
||||
LOG_ERROR(GENERAL, "%d - 0x%x", (u32)prog.profile, (u32)prog.binaryFormatRevision);
|
||||
|
||||
std::string shader;
|
||||
GLParamArray param_array;
|
||||
u32 size;
|
||||
|
||||
if (prog.profile == 7004)
|
||||
{
|
||||
CgBinaryFragmentProgram& fprog = vm::get_ref<CgBinaryFragmentProgram>(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<CgBinaryVertexProgram>(ptr + prog.program);
|
||||
|
||||
std::vector<u32> data;
|
||||
be_t<u32>* vdata = vm::get_ptr<be_t<u32>>(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()
|
||||
{
|
||||
static const wxCmdLineEntryDesc desc[]
|
||||
@ -314,9 +157,6 @@ bool Rpcs3App::OnInit()
|
||||
|
||||
OnArguments(parser);
|
||||
|
||||
//compile_shader("compile_shader0.spo");
|
||||
//compile_shader("compile_shader1.spo");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,7 @@
|
||||
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp" />
|
||||
<ClCompile Include="Emu\Io\XInput\XInputPadHandler.cpp" />
|
||||
<ClCompile Include="Gui\AutoPauseManager.cpp" />
|
||||
<ClCompile Include="Gui\CgDisasm.cpp" />
|
||||
<ClCompile Include="Gui\CompilerELF.cpp" />
|
||||
<ClCompile Include="Gui\ConLogFrame.cpp" />
|
||||
<ClCompile Include="Gui\Debugger.cpp" />
|
||||
@ -205,6 +206,7 @@
|
||||
<ClInclude Include="Emu\Io\XInput\XInputPadHandler.h" />
|
||||
<ClInclude Include="Gui\AboutDialog.h" />
|
||||
<ClInclude Include="Gui\AutoPauseManager.h" />
|
||||
<ClInclude Include="Gui\CgDisasm.h" />
|
||||
<ClInclude Include="Gui\CompilerELF.h" />
|
||||
<ClInclude Include="Gui\ConLogFrame.h" />
|
||||
<ClInclude Include="Gui\Debugger.h" />
|
||||
|
@ -96,6 +96,9 @@
|
||||
<ClCompile Include="Gui\MemoryStringSearcher.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Gui\CgDisasm.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
@ -194,8 +197,8 @@
|
||||
<ClInclude Include="Gui\LLEModulesManager.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="git-version.h">
|
||||
<ClInclude Include="Gui\CgDisasm.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user