diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index bf66680122e9..3b8e64309705 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -16,6 +16,7 @@ #include "Core/System.h" #include "Core/HLE/sceCtrl.h" #include "Core/MIPS/JitCommon/JitCommon.h" +#include "GPU/Common/PostShader.h" #ifdef _WIN32 #include "util/text/utf8.h" @@ -421,6 +422,8 @@ enum class CheatOp { CopyBytesFrom, Vibration, VibrationFromMemory, + PostShader, + PostShaderFromMemory, Delay, Assert, @@ -475,6 +478,15 @@ struct CheatOperation { uint8_t vibrLTime; uint8_t vibrRTime; } vibrationValues; + struct { + union { + float f; + uint32_t u; + } value; + uint8_t shader; + uint8_t uniform; + uint8_t format; + } PostShaderUniform; }; }; @@ -620,6 +632,23 @@ CheatOperation CWCheatEngine::InterpretNextCwCheat(const CheatCode &cheat, size_ case 0x1: // 0x1 reads value for gamepad vibration from memory addr = line1.part2; return { CheatOp::VibrationFromMemory, addr }; + case 0x2: // 0x2 sets postprocessing shader uniform + { + CheatOperation op = { CheatOp::PostShader }; + op.PostShaderUniform.uniform = line1.part1 & 0x000000FF; + op.PostShaderUniform.shader = (line1.part1 >> 16) & 0x000000FF; + op.PostShaderUniform.value.u = line1.part2; + return op; + } + case 0x3: // 0x3 sets postprocessing shader uniform from memory + { + addr = line1.part2; + CheatOperation op = { CheatOp::PostShaderFromMemory, addr }; + op.PostShaderUniform.uniform = line1.part1 & 0x000000FF; + op.PostShaderUniform.format = (line1.part1 >> 8) & 0x000000FF; + op.PostShaderUniform.shader = (line1.part1 >> 16) & 0x000000FF; + return op; + } // Place for other PPSSPP specific cheats default: return { CheatOp::Invalid }; @@ -919,6 +948,47 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat, } break; + case CheatOp::PostShader: + { + auto shaderChain = GetPostShaderChain(g_Config.sPostShaderName); + if (op.PostShaderUniform.shader < shaderChain.size()) { + std::string shaderName = shaderChain[op.PostShaderUniform.shader]->section; + if (shaderName != "Off") + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = op.PostShaderUniform.value.f; + } + } + break; + + case CheatOp::PostShaderFromMemory: + { + auto shaderChain = GetPostShaderChain(g_Config.sPostShaderName); + if (Memory::IsValidAddress(op.addr) && op.PostShaderUniform.shader < shaderChain.size()) { + union { + float f; + uint32_t u; + } value; + value.u = Memory::Read_U32(op.addr); + std::string shaderName = shaderChain[op.PostShaderUniform.shader]->section; + if (shaderName != "Off") { + switch (op.PostShaderUniform.format) { + case 0: + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u & 0x000000FF; + break; + case 1: + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u & 0x0000FFFF; + break; + case 2: + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u; + break; + case 3: + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.f; + break; + } + } + } + } + break; + case CheatOp::Delay: // TODO: Not supported. break;