Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 67 additions & 41 deletions ps2xRecomp/src/lib/ps2_recompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2120,62 +2120,67 @@ namespace ps2recomp
uint32_t start = function.start;
uint32_t end = function.end;

for (uint32_t address = start; address < end; address += 4)
auto decodeInstructionAt = [&](uint32_t address) -> Instruction
{
try
{
if (!m_elfParser->isValidAddress(address))
{
{
std::ostringstream msg;
msg << "Invalid address 0x" << std::hex << address << " (truncating decode)";
m_reporter.warningAt("decode", function.name, address, msg.str());
}
truncated = true;
break;
}

uint32_t rawInstruction = m_elfParser->readWord(address);
const uint32_t originalInstruction = rawInstruction;
uint32_t rawInstruction = m_elfParser->readWord(address);
const uint32_t originalInstruction = rawInstruction;

auto patchIt = m_config.patches.find(address);
if (patchIt != m_config.patches.end())
auto patchIt = m_config.patches.find(address);
if (patchIt != m_config.patches.end())
{
const PatchClass patchClass = classifyPatchedInstruction(originalInstruction);
if (shouldApplyConfiguredPatch(patchClass, m_config))
{
const PatchClass patchClass = classifyPatchedInstruction(originalInstruction);
if (shouldApplyConfiguredPatch(patchClass, m_config))
try
{
try
rawInstruction = std::stoul(patchIt->second, nullptr, 0);
{
rawInstruction = std::stoul(patchIt->second, nullptr, 0);
{
std::ostringstream msg;
msg << "Applied patch at 0x" << std::hex << address;
m_reporter.info("patch", msg.str());
}
std::ostringstream msg;
msg << "Applied patch at 0x" << std::hex << address;
m_reporter.info("patch", msg.str());
}
catch (const std::exception &e)
}
catch (const std::exception &e)
{
{
{
std::ostringstream msg;
msg << "Invalid patch value at 0x" << std::hex << address
<< " (" << patchIt->second << "): " << e.what()
<< ". Using original instruction.";
m_reporter.warningAt("patch", function.name, address, msg.str());
}
std::ostringstream msg;
msg << "Invalid patch value at 0x" << std::hex << address
<< " (" << patchIt->second << "): " << e.what()
<< ". Using original instruction.";
m_reporter.warningAt("patch", function.name, address, msg.str());
}
}
}
}

Instruction inst = m_decoder->decodeInstruction(address, rawInstruction, !m_config.lowMemoryMode);

auto mmioIt = m_config.mmioByInstructionAddress.find(address);
if (mmioIt != m_config.mmioByInstructionAddress.end())
{
inst.isMmio = true;
inst.mmioAddress = mmioIt->second;
}

Instruction inst = m_decoder->decodeInstruction(address, rawInstruction, !m_config.lowMemoryMode);
return inst;
};

auto mmioIt = m_config.mmioByInstructionAddress.find(address);
if (mmioIt != m_config.mmioByInstructionAddress.end())
for (uint32_t address = start; address < end; address += 4)
{
try
{
if (!m_elfParser->isValidAddress(address))
{
inst.isMmio = true;
inst.mmioAddress = mmioIt->second;
{
std::ostringstream msg;
msg << "Invalid address 0x" << std::hex << address << " (truncating decode)";
m_reporter.warningAt("decode", function.name, address, msg.str());
}
truncated = true;
break;
}

instructions.push_back(inst);
instructions.push_back(decodeInstructionAt(address));
}
catch (const std::exception &e)
{
Expand Down Expand Up @@ -2204,6 +2209,27 @@ namespace ps2recomp
function.end = instructions.back().address + 4;
}

// When another function starts at the final branch's delay slot, decode the real slot past
// function.end so the branch runs it instead of a synthetic NOP.
const bool delaySlotPastEnd = !truncated && instructions.back().hasDelaySlot &&
instructions.back().address + 4u == function.end &&
m_elfParser->isValidAddress(function.end);
if (delaySlotPastEnd)
{
try
{
instructions.push_back(decodeInstructionAt(function.end));
}
catch (const std::exception &e)
{
{
std::ostringstream msg;
msg << "Error decoding delay slot past function end: " << e.what() << " (using NOP)";
m_reporter.warningAt("decode", function.name, function.end, msg.str());
}
}
}

m_decodedFunctions.insert_or_assign(function.start, std::move(instructions));

return true;
Expand Down
Loading