Latte: Add support for shader instructions MIN_UINT and MAX_UINT

Seen in the eShop version of Fatal Frame
Also made some warnings less spammy since this game seems to trigger it a lot
This commit is contained in:
Exzap 2024-11-16 13:45:33 +01:00
parent 2065ac5f63
commit c3e29fb619
6 changed files with 20 additions and 10 deletions

View File

@ -370,6 +370,8 @@ bool LatteDecompiler_IsALUTransInstruction(bool isOP3, uint32 opcode)
opcode == ALU_OP2_INST_LSHR_INT || opcode == ALU_OP2_INST_LSHR_INT ||
opcode == ALU_OP2_INST_MAX_INT || opcode == ALU_OP2_INST_MAX_INT ||
opcode == ALU_OP2_INST_MIN_INT || opcode == ALU_OP2_INST_MIN_INT ||
opcode == ALU_OP2_INST_MAX_UINT ||
opcode == ALU_OP2_INST_MIN_UINT ||
opcode == ALU_OP2_INST_MOVA_FLOOR || opcode == ALU_OP2_INST_MOVA_FLOOR ||
opcode == ALU_OP2_INST_MOVA_INT || opcode == ALU_OP2_INST_MOVA_INT ||
opcode == ALU_OP2_INST_SETE_DX10 || opcode == ALU_OP2_INST_SETE_DX10 ||

View File

@ -140,6 +140,8 @@ bool _isIntegerInstruction(const LatteDecompilerALUInstruction& aluInstruction)
case ALU_OP2_INST_SUB_INT: case ALU_OP2_INST_SUB_INT:
case ALU_OP2_INST_MAX_INT: case ALU_OP2_INST_MAX_INT:
case ALU_OP2_INST_MIN_INT: case ALU_OP2_INST_MIN_INT:
case ALU_OP2_INST_MAX_UINT:
case ALU_OP2_INST_MIN_UINT:
case ALU_OP2_INST_SETE_INT: case ALU_OP2_INST_SETE_INT:
case ALU_OP2_INST_SETGT_INT: case ALU_OP2_INST_SETGT_INT:
case ALU_OP2_INST_SETGE_INT: case ALU_OP2_INST_SETGE_INT:

View File

@ -1415,19 +1415,23 @@ void _emitALUOP2InstructionCode(LatteDecompilerShaderContext* shaderContext, Lat
} }
else if( aluInstruction->opcode == ALU_OP2_INST_ADD_INT ) else if( aluInstruction->opcode == ALU_OP2_INST_ADD_INT )
_emitALUOperationBinary<LATTE_DECOMPILER_DTYPE_SIGNED_INT>(shaderContext, aluInstruction, " + "); _emitALUOperationBinary<LATTE_DECOMPILER_DTYPE_SIGNED_INT>(shaderContext, aluInstruction, " + ");
else if( aluInstruction->opcode == ALU_OP2_INST_MAX_INT || aluInstruction->opcode == ALU_OP2_INST_MIN_INT ) else if( aluInstruction->opcode == ALU_OP2_INST_MAX_INT || aluInstruction->opcode == ALU_OP2_INST_MIN_INT ||
aluInstruction->opcode == ALU_OP2_INST_MAX_UINT || aluInstruction->opcode == ALU_OP2_INST_MIN_UINT)
{ {
// not verified // not verified
bool isUnsigned = aluInstruction->opcode == ALU_OP2_INST_MAX_UINT || aluInstruction->opcode == ALU_OP2_INST_MIN_UINT;
auto opType = isUnsigned ? LATTE_DECOMPILER_DTYPE_UNSIGNED_INT : LATTE_DECOMPILER_DTYPE_SIGNED_INT;
_emitInstructionOutputVariableName(shaderContext, aluInstruction); _emitInstructionOutputVariableName(shaderContext, aluInstruction);
if( aluInstruction->opcode == ALU_OP2_INST_MAX_INT ) src->add(" = ");
src->add(" = max("); _emitTypeConversionPrefix(shaderContext, opType, outputType);
if( aluInstruction->opcode == ALU_OP2_INST_MAX_INT || aluInstruction->opcode == ALU_OP2_INST_MAX_UINT )
src->add("max(");
else else
src->add(" = min("); src->add("min(");
_emitTypeConversionPrefix(shaderContext, LATTE_DECOMPILER_DTYPE_SIGNED_INT, outputType); _emitOperandInputCode(shaderContext, aluInstruction, 0, opType);
_emitOperandInputCode(shaderContext, aluInstruction, 0, LATTE_DECOMPILER_DTYPE_SIGNED_INT);
src->add(", "); src->add(", ");
_emitOperandInputCode(shaderContext, aluInstruction, 1, LATTE_DECOMPILER_DTYPE_SIGNED_INT); _emitOperandInputCode(shaderContext, aluInstruction, 1, opType);
_emitTypeConversionSuffix(shaderContext, LATTE_DECOMPILER_DTYPE_SIGNED_INT, outputType); _emitTypeConversionSuffix(shaderContext, opType, outputType);
src->add(");" _CRLF); src->add(");" _CRLF);
} }
else if( aluInstruction->opcode == ALU_OP2_INST_SUB_INT ) else if( aluInstruction->opcode == ALU_OP2_INST_SUB_INT )

View File

@ -60,6 +60,8 @@
#define ALU_OP2_INST_SUB_INT (0x035) // integer instruction #define ALU_OP2_INST_SUB_INT (0x035) // integer instruction
#define ALU_OP2_INST_MAX_INT (0x036) // integer instruction #define ALU_OP2_INST_MAX_INT (0x036) // integer instruction
#define ALU_OP2_INST_MIN_INT (0x037) // integer instruction #define ALU_OP2_INST_MIN_INT (0x037) // integer instruction
#define ALU_OP2_INST_MAX_UINT (0x038) // integer instruction
#define ALU_OP2_INST_MIN_UINT (0x039) // integer instruction
#define ALU_OP2_INST_SETE_INT (0x03A) // integer instruction #define ALU_OP2_INST_SETE_INT (0x03A) // integer instruction
#define ALU_OP2_INST_SETGT_INT (0x03B) // integer instruction #define ALU_OP2_INST_SETGT_INT (0x03B) // integer instruction
#define ALU_OP2_INST_SETGE_INT (0x03C) // integer instruction #define ALU_OP2_INST_SETGE_INT (0x03C) // integer instruction

View File

@ -421,7 +421,7 @@ namespace GX2
{ {
if(aluRegisterOffset&0x8000) if(aluRegisterOffset&0x8000)
{ {
cemuLog_logDebug(LogType::Force, "_GX2SubmitUniformReg(): Unhandled loop const special case or invalid offset"); cemuLog_logDebugOnce(LogType::Force, "_GX2SubmitUniformReg(): Unhandled loop const special case or invalid offset");
return; return;
} }
if((aluRegisterOffset+sizeInU32s) > 0x400) if((aluRegisterOffset+sizeInU32s) > 0x400)

View File

@ -408,7 +408,7 @@ bool VPADController::push_rumble(uint8* pattern, uint8 length)
std::scoped_lock lock(m_rumble_mutex); std::scoped_lock lock(m_rumble_mutex);
if (m_rumble_queue.size() >= 5) if (m_rumble_queue.size() >= 5)
{ {
cemuLog_logDebug(LogType::Force, "too many cmds"); cemuLog_logDebugOnce(LogType::Force, "VPADControlMotor(): Pattern too long");
return false; return false;
} }