diff --git a/include/PICA/shader.hpp b/include/PICA/shader.hpp index c5af3443..2978192e 100644 --- a/include/PICA/shader.hpp +++ b/include/PICA/shader.hpp @@ -12,6 +12,7 @@ enum class ShaderType { namespace ShaderOpcodes { enum : u32 { + ADD = 0x00, DP4 = 0x02, MOV = 0x13, END = 0x22 @@ -37,6 +38,7 @@ class PICAShader { vec4f& getDest(u32 dest); // Shader opcodes + void add(u32 instruction); void dp4(u32 instruction); void mov(u32 instruction); diff --git a/src/core/PICA/shader_interpreter.cpp b/src/core/PICA/shader_interpreter.cpp index b213b1ed..0aae6da6 100644 --- a/src/core/PICA/shader_interpreter.cpp +++ b/src/core/PICA/shader_interpreter.cpp @@ -8,6 +8,7 @@ void PICAShader::run() { const u32 opcode = instruction >> 26; // Top 6 bits are the opcode switch (opcode) { + case ShaderOpcodes::ADD: add(instruction); break; case ShaderOpcodes::DP4: dp4(instruction); break; case ShaderOpcodes::END: return; // Stop running shader case ShaderOpcodes::MOV: mov(instruction); break; @@ -36,6 +37,27 @@ PICAShader::vec4f& PICAShader::getDest(u32 dest) { Helpers::panic("[PICA] Unimplemented dest: %X", dest); } +void PICAShader::add(u32 instruction) { + const u32 operandDescriptor = operandDescriptors[instruction & 0x7f]; + const u32 src1 = (instruction >> 12) & 0x7f; + const u32 src2 = (instruction >> 7) & 0x1f; // src2 coming first because PICA moment + const u32 idx = (instruction >> 19) & 3; + const u32 dest = (instruction >> 21) & 0x1f; + + if (idx) Helpers::panic("[PICA] ADD: idx != 0"); + vec4f srcVec1 = getSourceSwizzled<1>(src1, operandDescriptor); + vec4f srcVec2 = getSourceSwizzled<2>(src2, operandDescriptor); + + vec4f& destVector = getDest(dest); + + u32 componentMask = operandDescriptor & 0xf; + for (int i = 0; i < 4; i++) { + if (componentMask & (1 << i)) { + destVector[3 - i] = srcVec1[3 - i] + srcVec2[3 - 1]; + } + } +} + void PICAShader::mov(u32 instruction) { const u32 operandDescriptor = operandDescriptors[instruction & 0x7f]; const u32 src = (instruction >> 12) & 0x7f; @@ -46,7 +68,6 @@ void PICAShader::mov(u32 instruction) { vec4f srcVector = getSourceSwizzled<1>(src, operandDescriptor); vec4f& destVector = getDest(dest); - // Destination component mask. Tells us which lanes of the destination register will be written to u32 componentMask = operandDescriptor & 0xf; for (int i = 0; i < 4; i++) { if (componentMask & (1 << i)) { @@ -69,7 +90,6 @@ void PICAShader::dp4(u32 instruction) { vec4f& destVector = getDest(dest); f24 dot = srcVec1[0] * srcVec2[0] + srcVec1[1] * srcVec2[1] + srcVec1[2] * srcVec2[2] + srcVec1[3] * srcVec2[3]; - // Destination component mask. Tells us which lanes of the destination register will be written to u32 componentMask = operandDescriptor & 0xf; for (int i = 0; i < 4; i++) { if (componentMask & (1 << i)) {