Added vertex program decompiler draft

This commit is contained in:
DHrpcs3
2015-12-20 02:10:11 +02:00
parent 7a98f70db4
commit 6b988b54f5
6 changed files with 134 additions and 38 deletions

View File

@@ -8,6 +8,8 @@ namespace rsx
template<typename Language>
struct decompiler_base : shader_code::clike_builder<Language>
{
writer_t writer;
enum class compare_function
{
less,
@@ -65,5 +67,24 @@ namespace rsx
return vector_compare_function(function, a, b);
}
writer_t comment(const std::string& lines)
{
writer_t result;
result += "//" + lines + "\n";
return result;
}
writer_t warning(const std::string& lines)
{
return comment("WARNING: " + lines);
}
writer_t unimplemented(const std::string& lines)
{
return comment("TODO: " + lines);
}
};
}

View File

@@ -200,7 +200,6 @@ namespace rsx
instruction_t instruction;
context_t context;
writer_t writer;
expression_from<float_point_t<4>> src(int index, bool is_swizzle_as_dst = false)
{
@@ -527,25 +526,6 @@ namespace rsx
return set_dst(expression_from<float_point_t<4>>{ arg_string, std::string("xyzw"), is_single, 4 }, flags);
}
writer_t comment(const std::string& lines)
{
writer_t result;
result += "//" + lines + "\n";
return result;
}
writer_t warning(const std::string& lines)
{
return comment("WARNING: " + lines);
}
writer_t unimplemented(const std::string& lines)
{
return comment("TODO: " + lines);
}
expression_base_t decode_instruction()
{
switch (instruction.data.dst.opcode | (instruction.data.src1.opcode_is_branch << 6))

View File

@@ -1,9 +1,90 @@
#include "rsx_decompiler.h"
#include <glsl_language.h>
#include "rsx_decompiler_base.h"
namespace rsx
{
namespace vertex_program
{
class decompiler : public decompiler_base<shader_code::glsl_language>
{
struct context_t
{
decompiled_program program;
};
public:
struct instruction_t
{
ucode_instr data;
static u32 swap_endianess(u32 data)
{
return
((data >> 24) & 0x000000ff) |
((data >> 8) & 0x0000ff00) |
((data << 8) & 0x00ff0000) |
((data << 24) & 0xff000000);
}
instruction_t unpack()
{
instruction_t result;
result.data.d0._u32 = swap_endianess(data.d0._u32);
result.data.d1._u32 = swap_endianess(data.d1._u32);
result.data.d2._u32 = swap_endianess(data.d2._u32);
result.data.d3._u32 = swap_endianess(data.d3._u32);
return result;
}
};
static_assert(sizeof(instruction_t) == 16, "Bad instruction_t implementation");
instruction_t instruction;
context_t context;
decompiled_program decompile(std::size_t offset, instruction_t *instructions)
{
for (std::size_t i = offset; i < 512; ++i, writer.next())
{
instruction = instructions[i].unpack();
if (instruction.data.d1.sca_opcode == sca_opcode::nop && instruction.data.d1.vec_opcode == vec_opcode::nop)
{
writer += comment("NOP");
}
else
{
if (instruction.data.d1.sca_opcode != sca_opcode::nop)
{
writer += comment(sca_op_names[(int)instruction.data.d1.sca_opcode]);
}
if (instruction.data.d1.vec_opcode != vec_opcode::nop)
{
writer += comment(vec_op_names[(int)instruction.data.d1.vec_opcode]);
}
}
if (instruction.data.d3.end)
break;
}
context.program.entry_function = "func0";
context.program.code = "void func0()\n{\n" + writer.build() + "}\n";
return context.program;
}
};
template<typename Language>
decompiled_program decompile(std::size_t offset, ucode_instr *instructions)
{
return decompiler{}.decompile(offset, (decompiler::instruction_t*)instructions);
}
decompiled_program decompile(std::size_t offset, ucode_instr* instructions, decompile_language lang)
{
decompiled_program result;
@@ -11,7 +92,7 @@ namespace rsx
switch (lang)
{
case decompile_language::glsl:
//result = ...;
result = decompile<shader_code::glsl_language>(offset, instructions);
result.code_language = decompile_language::glsl;
break;

View File

@@ -4,19 +4,19 @@ namespace rsx
{
namespace vertex_program
{
const std::string rsx_vp_sca_op_names[0x20] =
const std::string sca_op_names[0x20] =
{
"NOP", "MOV", "RCP", "RCC", "RSQ", "EXP", "LOG",
"LIT", "BRA", "BRI", "CAL", "CLI", "RET", "LG2",
"EX2", "SIN", "COS", "BRB", "CLB", "PSH", "POP"
};
const std::string rsx_vp_vec_op_names[0x20] =
const std::string vec_op_names[0x20] =
{
"NOP", "MOV", "MUL", "ADD", "MAD", "DP3", "DPH", "DP4",
"DST", "MIN", "MAX", "SLT", "SGE", "ARL", "FRC", "FLR",
"SEQ", "SFL", "SGT", "SLE", "SNE", "STR", "SSG", nullptr,
nullptr, "TXL"
"SEQ", "SFL", "SGT", "SLE", "SNE", "STR", "SSG", {},
{}, "TXL"
};
}
}

View File

@@ -62,7 +62,7 @@ namespace rsx
union D0
{
u32 HEX;
u32 _u32;
struct
{
@@ -91,7 +91,7 @@ namespace rsx
union D1
{
u32 HEX;
u32 _u32;
struct
{
@@ -105,7 +105,7 @@ namespace rsx
union D2
{
u32 HEX;
u32 _u32;
struct
{
@@ -122,7 +122,7 @@ namespace rsx
union D3
{
u32 HEX;
u32 _u32;
struct
{
@@ -151,7 +151,7 @@ namespace rsx
{
union
{
u32 HEX;
u32 _u32;
struct
{
@@ -191,7 +191,7 @@ namespace rsx
D3 d3;
};
extern const std::string rsx_vp_sca_op_names[0x20];
extern const std::string rsx_vp_vec_op_names[0x20];
extern const std::string sca_op_names[0x20];
extern const std::string vec_op_names[0x20];
}
}

View File

@@ -260,7 +260,7 @@ void test(const std::string &shader)
enum
{
GL_FRAGMENT_SHADER = 35632,
GL_SHADER_SOURCE_LENGTH = 35720,
GL_INFO_LOG_LENGTH = 35716,
GL_COMPILE_STATUS = 35713,
};
@@ -283,10 +283,9 @@ void test(const std::string &shader)
if (param == 0)
{
std::cout << "compilation failed." << std::endl;
glGetShaderiv(fragmentShader, GL_SHADER_SOURCE_LENGTH, &param);
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &param);
std::vector<char> buffer(param + 1);
glGetShaderInfoLog(fragmentShader, param, &param, buffer.data());
std::cout << buffer.data();
@@ -312,6 +311,7 @@ void print_info(const rsx::decompiled_program& program)
std::cout << "[COMPLETE CODE]" << std::endl;
std::cout << complete_program.code;
std::cout.flush();
#ifdef _DEBUG
test(complete_program.code);
#endif
@@ -319,13 +319,27 @@ void print_info(const rsx::decompiled_program& program)
int main(int argc, char** argv)
{
extract_objects_from_elf(argv[1], "tmp.vp.cg", { "_binary_vp_shader_vpo_start", "_binary_vp_shader_vpo_end" });
extract_objects_from_elf(argv[1], "tmp.fp.cg", { "_binary_fp_shader_fpo_start", "_binary_fp_shader_fpo_end" });
extract_ucode("tmp.fp.cg", "tmp.fp.ucode");
extract_ucode("tmp.vp.cg", "tmp.vp.ucode");
std::vector<char> file = load_file("tmp.fp.ucode");
rsx::decompiled_program program;
rsx::fragment_program::ucode_instr *instructions = (rsx::fragment_program::ucode_instr *)file.data();
rsx::decompiled_program program = rsx::fragment_program::decompile(0, instructions, rsx::decompile_language::glsl);
if (0)
{
std::vector<char> file = load_file("tmp.fp.ucode");
rsx::fragment_program::ucode_instr *instructions = (rsx::fragment_program::ucode_instr *)file.data();
program = rsx::fragment_program::decompile(0, instructions, rsx::decompile_language::glsl);
}
else
{
std::vector<char> file = load_file("tmp.vp.ucode");
rsx::vertex_program::ucode_instr *instructions = (rsx::vertex_program::ucode_instr *)file.data();
program = rsx::vertex_program::decompile(0, instructions, rsx::decompile_language::glsl);
}
print_info(program);
/*