Moar instructions

This commit is contained in:
wheremyfoodat 2024-07-28 16:06:38 +03:00
parent 9ee1c3964a
commit 6c738e821d
3 changed files with 97 additions and 17 deletions

View file

@ -1,10 +1,12 @@
#pragma once
#include <fmt/format.h>
#include <map>
#include <set>
#include <string>
#include <tuple>
#include <map>
#include <vector>
#include <utility>
#include <vector>
#include "PICA/shader.hpp"
#include "PICA/shader_gen_types.hpp"
@ -42,9 +44,9 @@ namespace PICA::ShaderGen {
explicit Function(u32 start, u32 end) : start(start), end(end) {}
bool operator<(const Function& other) const { return AddressRange(start, end) < AddressRange(other.start, other.end); }
std::string getIdentifier() const { return "func_" + std::to_string(start) + "_to_" + std::to_string(end); }
std::string getForwardDecl() const { return "void " + getIdentifier() + "();\n"; }
std::string getCallStatement() const { return getIdentifier() + "()"; }
std::string getIdentifier() const { return fmt::format("fn_{}_{}", start, end); }
std::string getForwardDecl() const { return fmt::format("void fn_{}_{}();\n", start, end); }
std::string getCallStatement() const { return fmt::format("fn_{}_{}()", start, end); }
};
std::set<Function> functions{};

View file

@ -85,7 +85,6 @@ ExitMode ControlFlow::analyzeFunction(const PICAShader& shader, u32 start, u32 e
}
case ShaderOpcodes::IFU:
case ShaderOpcodes::IFC: {
Helpers::panic("IFC/IFU");
const u32 num = instruction & 0xff;
const u32 dest = getBits<10, 12>(instruction);
@ -122,7 +121,29 @@ ExitMode ControlFlow::analyzeFunction(const PICAShader& shader, u32 start, u32 e
}
break;
}
case ShaderOpcodes::CALL: Helpers::panic("Unimplemented control flow operation (CALL)"); break;
case ShaderOpcodes::CALL: {
const u32 num = instruction & 0xff;
const u32 dest = getBits<10, 12>(instruction);
const Function* calledFunction = addFunction(shader, dest, dest + num);
// Check if analysis of the branch taken func failed and return unknown if it did
if (analysisFailed) {
it->second = ExitMode::Unknown;
return it->second;
}
if (calledFunction->exitMode == ExitMode::AlwaysEnd) {
it->second = ExitMode::AlwaysEnd;
return it->second;
}
// Exit mode of the remainder of this function, after we return from the callee
ExitMode postCallExitMode = analyzeFunction(shader, pc + 1, end, labels);
ExitMode exitMode = exitSeries(postCallExitMode, calledFunction->exitMode);
it->second = exitMode;
return exitMode;
}
case ShaderOpcodes::CALLC: Helpers::panic("Unimplemented control flow operation (CALLC)"); break;
case ShaderOpcodes::CALLU: Helpers::panic("Unimplemented control flow operation (CALLU)"); break;
case ShaderOpcodes::LOOP: Helpers::panic("Unimplemented control flow operation (LOOP)"); break;
@ -464,14 +485,71 @@ void ShaderDecompiler::compileInstruction(u32& pc, bool& finished) {
const uint refY = getBit<24>(instruction);
const uint refX = getBit<25>(instruction);
const char* condition = getCondition(condOp, refX, refY);
decompiledShader += fmt::format("if ({}) {{ pc = {}u; break; }}", condition, dest);
break;
}
case ShaderOpcodes::IFU:
case ShaderOpcodes::IFC: {
const u32 num = instruction & 0xff;
const u32 dest = getBits<10, 12>(instruction);
const Function* conditionalFunc = findFunction(AddressRange(pc + 1, dest));
if (opcode == ShaderOpcodes::IFC) {
const u32 condOp = getBits<22, 2>(instruction);
const uint refY = getBit<24>(instruction);
const uint refX = getBit<25>(instruction);
const char* condition = getCondition(condOp, refX, refY);
decompiledShader += fmt::format("if ({}) {{", condition);
} else {
const u32 bit = getBits<22, 4>(instruction); // Bit of the bool uniform to check
const u32 mask = 1u << bit;
decompiledShader += fmt::format("if ((uniform_bool & {}u) != 0u) {{", mask);
}
callFunction(*conditionalFunc);
decompiledShader += "}\n";
pc = dest;
if (num > 0) {
const Function* elseFunc = findFunction(AddressRange(dest, dest + num));
pc = dest + num;
decompiledShader += "else { ";
callFunction(*elseFunc);
decompiledShader += "}\n";
if (conditionalFunc->exitMode == ExitMode::AlwaysEnd && elseFunc->exitMode == ExitMode::AlwaysEnd) {
finished = true;
return;
}
}
return;
}
case ShaderOpcodes::CALL: {
const u32 num = instruction & 0xff;
const u32 dest = getBits<10, 12>(instruction);
const Function* calledFunc = findFunction(AddressRange(dest, dest + num));
callFunction(*calledFunc);
if (opcode == ShaderOpcodes::CALL && calledFunc->exitMode == ExitMode::AlwaysEnd) {
finished = true;
return;
}
break;
}
case ShaderOpcodes::END:
decompiledShader += "return;\n";
finished = true;
return;
case ShaderOpcodes::NOP: break;
default: Helpers::panic("GLSL recompiler: Unknown opcode: %X", opcode); break;
}
}

View file

@ -717,15 +717,15 @@ std::string FragmentGenerator::getVertexShaderAccelerated(const std::string& pic
std::string semantics = fmt::format(
R"(
vec4 a_coords = vec4({}, {}, {}, {});
vec4 a_quaternion = vec4({}, {}, {}, {});
vec4 a_vertexColour = vec4({}, {}, {}, {});
vec2 a_texcoord0 = vec2({}, {});
float a_texcoord0_w = {};
vec2 a_texcoord1 = vec2({}, {});
vec2 a_texcoord2 = vec2({}, {});
vec3 a_view = vec3({}, {}, {});
)",
vec4 a_coords = vec4({}, {}, {}, {});
vec4 a_quaternion = vec4({}, {}, {}, {});
vec4 a_vertexColour = vec4({}, {}, {}, {});
vec2 a_texcoord0 = vec2({}, {});
float a_texcoord0_w = {};
vec2 a_texcoord1 = vec2({}, {});
vec2 a_texcoord2 = vec2({}, {});
vec3 a_view = vec3({}, {}, {});
)",
getSemanticName(0), getSemanticName(1), getSemanticName(2), getSemanticName(3), getSemanticName(4), getSemanticName(5), getSemanticName(6),
getSemanticName(7), getSemanticName(8), getSemanticName(9), getSemanticName(10), getSemanticName(11), getSemanticName(12),
getSemanticName(13), getSemanticName(16), getSemanticName(14), getSemanticName(15), getSemanticName(22), getSemanticName(23),