diff --git a/include/PICA/shader.hpp b/include/PICA/shader.hpp index f282da72..bad37d2e 100644 --- a/include/PICA/shader.hpp +++ b/include/PICA/shader.hpp @@ -16,6 +16,7 @@ namespace ShaderOpcodes { DP3 = 0x01, DP4 = 0x02, MUL = 0x08, + MAX = 0x0C, MIN = 0x0D, RSQ = 0x0F, MOVA = 0x12, @@ -93,6 +94,7 @@ class PICAShader { void ifu(u32 instruction); void loop(u32 instruction); void mad(u32 instruction); + void max(u32 instruction); void min(u32 instruction); void mov(u32 instruction); void mova(u32 instruction); diff --git a/src/core/PICA/shader_interpreter.cpp b/src/core/PICA/shader_interpreter.cpp index 3931f033..ec656937 100644 --- a/src/core/PICA/shader_interpreter.cpp +++ b/src/core/PICA/shader_interpreter.cpp @@ -24,6 +24,7 @@ void PICAShader::run() { case ShaderOpcodes::IFC: ifc(instruction); break; case ShaderOpcodes::IFU: ifu(instruction); break; case ShaderOpcodes::LOOP: loop(instruction); break; + case ShaderOpcodes::MAX: max(instruction); break; case ShaderOpcodes::MIN: min(instruction); break; case ShaderOpcodes::MOV: mov(instruction); break; case ShaderOpcodes::MOVA: mova(instruction); break; @@ -169,6 +170,28 @@ void PICAShader::mul(u32 instruction) { } } +void PICAShader::max(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] MAX: 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::min(u32 instruction) { const u32 operandDescriptor = operandDescriptors[instruction & 0x7f]; const u32 src1 = (instruction >> 12) & 0x7f;