Feature/runtime review codegen fixes (#87)

* feat: small fixes on code gen

* feat: added code gen test

* feat: rename IOP

* fix: fix special case on JR
feat: added code generator test

* feat: ps2 logs now need special macros

* feat: a lot of regressions test
feat: use test to fix bugs on runtime
fix: fix incorrect instructions on code generator
feat: added missing decode on r5900 decoder
feat: added scissor on rasterizer

* feat: better ghidra plugin analyzer
fix: fix real bug on function finding on elf analyzer

* feat: some logs on GS
feat: added more syscalls stubs
feat: added more ps2 stubs

* feat: added missing stub
This commit is contained in:
Ranieri
2026-02-27 03:44:59 -03:00
committed by GitHub
parent 8d1f1c5672
commit 669114f3f6
51 changed files with 7912 additions and 382 deletions
+156 -8
View File
@@ -143,6 +143,69 @@ namespace
return nullptr;
}
bool HasAnyExecutableSection(const std::vector<ps2recomp::Section> &sections)
{
for (const auto &section : sections)
{
if (section.isCode)
{
return true;
}
}
return false;
}
const ps2recomp::Section *FindFunctionSectionByAddress(const std::vector<ps2recomp::Section> &sections, uint32_t address)
{
const ps2recomp::Section *codeSection = FindCodeSectionByAddress(sections, address);
if (codeSection)
{
return codeSection;
}
// Some malformed/stripped ELFs may not carry executable section flags.
if (!HasAnyExecutableSection(sections))
{
return FindSectionByAddress(sections, address);
}
return nullptr;
}
uint32_t ClampFunctionEndToSection(const ps2recomp::Section *section, uint32_t start, uint32_t requestedEnd)
{
if (!section)
{
return requestedEnd;
}
const uint64_t sectionEnd64 = static_cast<uint64_t>(section->address) + static_cast<uint64_t>(section->size);
const uint32_t sectionEnd = (sectionEnd64 > 0xFFFFFFFFull)
? 0xFFFFFFFFu
: static_cast<uint32_t>(sectionEnd64);
uint32_t end = requestedEnd;
if (end == 0 || end > sectionEnd)
{
end = sectionEnd;
}
if (end <= start)
{
const uint64_t minimumEnd64 = static_cast<uint64_t>(start) + 4ull;
if (minimumEnd64 <= sectionEnd64)
{
end = static_cast<uint32_t>(minimumEnd64);
}
else
{
end = sectionEnd;
}
}
return end;
}
std::string MakeAutoFunctionName(uint32_t address)
{
char buffer[32]{};
@@ -503,7 +566,22 @@ namespace ps2recomp
continue;
}
const uint32_t symbolEnd = symbol.address + symbol.size;
const Section *functionSection = FindFunctionSectionByAddress(m_sections, symbol.address);
if (!functionSection)
{
continue;
}
const uint64_t symbolEnd64 = static_cast<uint64_t>(symbol.address) + static_cast<uint64_t>(symbol.size);
uint32_t symbolEnd = (symbolEnd64 > 0xFFFFFFFFull)
? 0xFFFFFFFFu
: static_cast<uint32_t>(symbolEnd64);
symbolEnd = ClampFunctionEndToSection(functionSection, symbol.address, symbolEnd);
if (symbolEnd <= symbol.address)
{
continue;
}
auto inserted = authoritativeEndByStart.emplace(symbol.address, symbolEnd);
if (!inserted.second && symbolEnd > inserted.first->second)
{
@@ -519,10 +597,22 @@ namespace ps2recomp
continue;
}
auto inserted = authoritativeEndByStart.emplace(extra.start, extra.end);
if (!inserted.second && extra.end > inserted.first->second)
const Section *functionSection = FindFunctionSectionByAddress(m_sections, extra.start);
if (!functionSection)
{
inserted.first->second = extra.end;
continue;
}
const uint32_t clampedEnd = ClampFunctionEndToSection(functionSection, extra.start, extra.end);
if (clampedEnd <= extra.start)
{
continue;
}
auto inserted = authoritativeEndByStart.emplace(extra.start, clampedEnd);
if (!inserted.second && clampedEnd > inserted.first->second)
{
inserted.first->second = clampedEnd;
}
}
@@ -566,6 +656,11 @@ namespace ps2recomp
return;
}
if (!FindFunctionSectionByAddress(m_sections, newFunction.start))
{
return;
}
const bool insideAuthoritativeRange = isInsideAuthoritativeRange(newFunction.start);
const bool hasOwnAuthoritativeRange = authoritativeEndByStart.contains(newFunction.start);
const bool hasAutoName = newFunction.name.empty() || IsAutoGeneratedName(newFunction.name);
@@ -585,7 +680,10 @@ namespace ps2recomp
auto authoritativeIt = authoritativeEndByStart.find(insertedFunction.start);
if (authoritativeIt != authoritativeEndByStart.end())
{
insertedFunction.end = authoritativeIt->second;
insertedFunction.end = ClampFunctionEndToSection(
FindFunctionSectionByAddress(m_sections, insertedFunction.start),
insertedFunction.start,
authoritativeIt->second);
}
return;
}
@@ -603,7 +701,10 @@ namespace ps2recomp
auto authoritativeIt = authoritativeEndByStart.find(existing.start);
if (authoritativeIt != authoritativeEndByStart.end())
{
existing.end = authoritativeIt->second;
existing.end = ClampFunctionEndToSection(
FindFunctionSectionByAddress(m_sections, existing.start),
existing.start,
authoritativeIt->second);
}
else if (newFunction.end > existing.end)
{
@@ -620,10 +721,24 @@ namespace ps2recomp
{
continue;
}
if (!FindFunctionSectionByAddress(m_sections, symbol.address))
{
continue;
}
Function func;
func.name = symbol.name;
func.start = symbol.address;
func.end = (symbol.size > 0) ? (symbol.address + symbol.size) : 0;
if (symbol.size > 0)
{
const uint64_t end64 = static_cast<uint64_t>(symbol.address) + static_cast<uint64_t>(symbol.size);
func.end = (end64 > 0xFFFFFFFFull) ? 0xFFFFFFFFu : static_cast<uint32_t>(end64);
}
else
{
func.end = 0;
}
func.isRecompiled = false;
func.isStub = false;
func.isSkipped = false;
@@ -656,7 +771,7 @@ namespace ps2recomp
continue;
}
const Section *section = FindSectionByAddress(m_sections, func.start);
const Section *section = FindFunctionSectionByAddress(m_sections, func.start);
uint32_t sectionEnd = section ? (section->address + section->size) : (func.start + 4);
uint32_t nextStart = sectionEnd;
@@ -846,6 +961,8 @@ namespace ps2recomp
}
int count = 0;
int skippedNonExecutable = 0;
int skippedInvalidRange = 0;
while (std::getline(file, line))
{
if (line.empty())
@@ -867,6 +984,20 @@ namespace ps2recomp
uint32_t start = std::stoul(startStr, nullptr, 0);
uint32_t end = std::stoul(endStr, nullptr, 0);
const Section *section = FindFunctionSectionByAddress(m_sections, start);
if (!section)
{
++skippedNonExecutable;
continue;
}
end = ClampFunctionEndToSection(section, start, end);
if (end <= start)
{
++skippedInvalidRange;
continue;
}
Function func{};
func.name = name;
func.start = start;
@@ -887,6 +1018,16 @@ namespace ps2recomp
if (count > 0)
{
std::cout << "Loaded " << count << " functions from Ghidra map" << std::endl;
if (skippedNonExecutable > 0)
{
std::cout << "Ignored " << skippedNonExecutable
<< " Ghidra function(s) outside executable sections." << std::endl;
}
if (skippedInvalidRange > 0)
{
std::cout << "Ignored " << skippedInvalidRange
<< " Ghidra function(s) with invalid ranges after section clamping." << std::endl;
}
std::sort(m_extraFunctions.begin(), m_extraFunctions.end(),
[](const Function &a, const Function &b)
@@ -908,6 +1049,13 @@ namespace ps2recomp
return true;
}
if (skippedNonExecutable > 0 || skippedInvalidRange > 0)
{
std::cout << "Loaded 0 functions from Ghidra map after filtering ("
<< skippedNonExecutable << " non-executable, "
<< skippedInvalidRange << " invalid range)." << std::endl;
}
return false;
}