Feature/vu fixes (#55)

* fix: added missing header include for gcc

* fix: small thread fix on syscalls
fix: fix incorrect VU translations (they was using wrong register)

* feat: added authoritative system for function extraction, this will prevent functions overlap when we have debug symbols
This commit is contained in:
Ranieri
2026-02-16 23:00:35 -03:00
committed by GitHub
parent 4961710407
commit aa76cdbbf7
5 changed files with 592 additions and 190 deletions
+95 -1
View File
@@ -493,6 +493,72 @@ namespace ps2recomp
std::unordered_map<uint32_t, size_t> indexByStart;
indexByStart.reserve(functions.capacity());
// Symbol table sizes are authoritative wwhen exist
std::unordered_map<uint32_t, uint32_t> authoritativeEndByStart;
authoritativeEndByStart.reserve(m_symbols.size());
for (const auto &symbol : m_symbols)
{
if (!symbol.isFunction || symbol.isImported || symbol.size == 0)
{
continue;
}
const uint32_t symbolEnd = symbol.address + symbol.size;
auto inserted = authoritativeEndByStart.emplace(symbol.address, symbolEnd);
if (!inserted.second && symbolEnd > inserted.first->second)
{
inserted.first->second = symbolEnd;
}
}
// Named debug/map functions with explicit bounds are authoritative too.
for (const auto &extra : m_extraFunctions)
{
if (extra.start == 0 || extra.end <= extra.start || extra.name.empty() || IsAutoGeneratedName(extra.name))
{
continue;
}
auto inserted = authoritativeEndByStart.emplace(extra.start, extra.end);
if (!inserted.second && extra.end > inserted.first->second)
{
inserted.first->second = extra.end;
}
}
std::vector<std::pair<uint32_t, uint32_t>> authoritativeRanges;
authoritativeRanges.reserve(authoritativeEndByStart.size());
for (const auto &entry : authoritativeEndByStart)
{
authoritativeRanges.emplace_back(entry.first, entry.second);
}
std::sort(authoritativeRanges.begin(), authoritativeRanges.end(),
[](const std::pair<uint32_t, uint32_t> &a, const std::pair<uint32_t, uint32_t> &b)
{ return a.first < b.first; });
auto isInsideAuthoritativeRange = [&](uint32_t startAddress)
{
if (authoritativeRanges.empty())
{
return false;
}
auto it = std::upper_bound(
authoritativeRanges.begin(),
authoritativeRanges.end(),
startAddress,
[](uint32_t value, const std::pair<uint32_t, uint32_t> &range)
{ return value < range.first; });
if (it == authoritativeRanges.begin())
{
return false;
}
--it;
return startAddress > it->first && startAddress < it->second;
};
auto addOrMerge = [&](const Function &newFunction)
{
if (newFunction.start == 0)
@@ -500,11 +566,27 @@ namespace ps2recomp
return;
}
const bool insideAuthoritativeRange = isInsideAuthoritativeRange(newFunction.start);
const bool hasOwnAuthoritativeRange = authoritativeEndByStart.contains(newFunction.start);
const bool hasAutoName = newFunction.name.empty() || IsAutoGeneratedName(newFunction.name);
if (insideAuthoritativeRange && (!hasOwnAuthoritativeRange || hasAutoName))
{
return;
}
auto it = indexByStart.find(newFunction.start);
if (it == indexByStart.end())
{
indexByStart.emplace(newFunction.start, functions.size());
functions.push_back(newFunction);
Function &insertedFunction = functions.back();
auto authoritativeIt = authoritativeEndByStart.find(insertedFunction.start);
if (authoritativeIt != authoritativeEndByStart.end())
{
insertedFunction.end = authoritativeIt->second;
}
return;
}
@@ -518,7 +600,12 @@ namespace ps2recomp
}
}
if (newFunction.end > existing.end)
auto authoritativeIt = authoritativeEndByStart.find(existing.start);
if (authoritativeIt != authoritativeEndByStart.end())
{
existing.end = authoritativeIt->second;
}
else if (newFunction.end > existing.end)
{
existing.end = newFunction.end;
}
@@ -557,6 +644,13 @@ namespace ps2recomp
{
Function &func = functions[index];
auto authoritativeIt = authoritativeEndByStart.find(func.start);
if (authoritativeIt != authoritativeEndByStart.end())
{
func.end = authoritativeIt->second;
continue;
}
if (func.end > func.start)
{
continue;