mirror of
https://github.com/RPCS3/rsx_program_decompiler.git
synced 2026-01-31 01:25:19 +01:00
Added vertex program decompiler draft
This commit is contained in:
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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, ¶m);
|
||||
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, ¶m);
|
||||
|
||||
std::vector<char> buffer(param + 1);
|
||||
|
||||
glGetShaderInfoLog(fragmentShader, param, ¶m, 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);
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user