diff --git a/include/PICA/shader.hpp b/include/PICA/shader.hpp index 0ad4ca51..2b4e012d 100644 --- a/include/PICA/shader.hpp +++ b/include/PICA/shader.hpp @@ -16,8 +16,10 @@ namespace ShaderOpcodes { DP3 = 0x01, DP4 = 0x02, MUL = 0x08, + MIN = 0x0D, MOVA = 0x12, MOV = 0x13, + NOP = 0x21, END = 0x22, IFC = 0x28, LOOP = 0x29, @@ -75,6 +77,7 @@ class PICAShader { void dp4(u32 instruction); void ifc(u32 instruction); void loop(u32 instruction); + void min(u32 instruction); void mov(u32 instruction); void mova(u32 instruction); void mul(u32 instruction); diff --git a/src/core/PICA/shader_interpreter.cpp b/src/core/PICA/shader_interpreter.cpp index d4ad08ac..bb47d2a9 100644 --- a/src/core/PICA/shader_interpreter.cpp +++ b/src/core/PICA/shader_interpreter.cpp @@ -19,9 +19,11 @@ void PICAShader::run() { case ShaderOpcodes::END: return; // Stop running shader case ShaderOpcodes::IFC: ifc(instruction); break; case ShaderOpcodes::LOOP: loop(instruction); break; + case ShaderOpcodes::MIN: min(instruction); break; case ShaderOpcodes::MOV: mov(instruction); break; case ShaderOpcodes::MOVA: mova(instruction); break; case ShaderOpcodes::MUL: mul(instruction); break; + case ShaderOpcodes::NOP: break; // Do nothing default:Helpers::panic("Unimplemented PICA instruction %08X (Opcode = %02X)", instruction, opcode); } @@ -147,6 +149,28 @@ void PICAShader::mul(u32 instruction) { } } +void PICAShader::min(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] MIN: 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)) { + const auto mininum = srcVec1[3 - i] < srcVec2[3 - i] ? srcVec1[3 - i] : srcVec2[3 - i]; + destVector[3 - i] = mininum; + } + } +} + void PICAShader::mov(u32 instruction) { const u32 operandDescriptor = operandDescriptors[instruction & 0x7f]; u32 src = (instruction >> 12) & 0x7f;