Feature/agressive recompiler (#146)

* feat: added guestBranchKind enum to categorize branch types
feat: added missingFunctionPolicy enum to define behaviors for missing function scenarios
refactor: added handle guest branches and report missing functions
feat lookupFunction to utilize new dispatch logic and improve error handling for unregistered functions

* fix: fix test conflict

* feat: added debug sound driver logs

* feat: emmiter for return

* feat: added recompiler reporter
feat: added strict diagnostics flag for heavy debug calls

* feat: staticc table insted of hashmap for runtime

* feat: back file to ignore

* feat: explode code across helpers and classes

* feat: update codegen test
feat: better guest nop check

* feat: fix link problem on linux

* feat: fix Segmentation fault

* feat: added recompile replace for DMA and MMIO
feat: added a clean memory helpers
feat: use memory helpers across the project
feat: fix ucrt on msvc

* feat: undo messup merge
This commit is contained in:
Ranieri
2026-07-07 10:14:25 -03:00
committed by GitHub
parent 61621b8313
commit 52edf07657
24 changed files with 1756 additions and 70 deletions
+190
View File
@@ -55,6 +55,63 @@ namespace
return v;
}
struct PackedGifPacketTag
{
uint64_t lo = 0u;
uint64_t hi = 0u;
uint32_t payloadOffset = 0u;
uint32_t nloop = 0u;
uint32_t nreg = 0u;
uint8_t regs[16]{};
};
template <typename Visitor>
bool visitPackedGifPacket(const uint8_t *data, uint32_t sizeBytes, Visitor &&visitor)
{
uint32_t offset = 0u;
while (offset + 16u <= sizeBytes)
{
PackedGifPacketTag tag{};
tag.lo = loadLE64(data + offset);
tag.hi = loadLE64(data + offset + 8u);
const uint8_t flg = static_cast<uint8_t>((tag.lo >> 58u) & 0x3u);
if (flg != GIF_FMT_PACKED)
return false;
tag.nloop = static_cast<uint32_t>(tag.lo & 0x7FFFu);
tag.nreg = static_cast<uint32_t>((tag.lo >> 60u) & 0xFu);
if (tag.nreg == 0u)
tag.nreg = 16u;
const uint64_t payloadBytes64 =
static_cast<uint64_t>(tag.nloop) * static_cast<uint64_t>(tag.nreg) * 16ull;
if (payloadBytes64 > 0xFFFFFFFFull)
return false;
offset += 16u;
const uint32_t payloadBytes = static_cast<uint32_t>(payloadBytes64);
if (payloadBytes > sizeBytes - offset)
return false;
tag.payloadOffset = offset;
for (uint32_t i = 0u; i < tag.nreg; ++i)
tag.regs[i] = static_cast<uint8_t>((tag.hi >> (i * 4u)) & 0xFu);
if (!visitor(tag))
return false;
offset += payloadBytes;
}
return offset == sizeBytes;
}
bool validatePackedGifPacket(const uint8_t *data, uint32_t sizeBytes)
{
return visitPackedGifPacket(data, sizeBytes, [](const PackedGifPacketTag &) { return true; });
}
void decodeDisplaySize(uint64_t display64, uint32_t &outWidth, uint32_t &outHeight)
{
const uint32_t dx = static_cast<uint32_t>((display64 >> 0) & 0x0FFFu);
@@ -1221,6 +1278,9 @@ void GS::processGIFPacket(const uint8_t *data, uint32_t sizeBytes)
if (!data || sizeBytes < 16 || !m_vram)
return;
if (tryProcessNativeImageUploadPacket(data, sizeBytes))
return;
PS2_IF_AGRESSIVE_LOGS({
const uint32_t packetIndex = s_debugGifPacketCount.fetch_add(1, std::memory_order_relaxed);
if (packetIndex < 48u)
@@ -1311,6 +1371,136 @@ void GS::processGIFPacket(const uint8_t *data, uint32_t sizeBytes)
}
}
bool GS::processNativePackedGIFPacket(const uint8_t *data, uint32_t sizeBytes)
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!data || sizeBytes < 16u || !m_vram)
return false;
if (!validatePackedGifPacket(data, sizeBytes))
return false;
const bool processed = visitPackedGifPacket(data, sizeBytes, [&](const PackedGifPacketTag &tag)
{
m_curQ = 1.0f;
recordGifTagDebugEventUnlocked(sizeBytes, tag.nloop, GIF_FMT_PACKED, tag.nreg);
const bool pre = ((tag.lo >> 46u) & 1u) != 0u;
if (pre)
writeRegister(GS_REG_PRIM, (tag.lo >> 47u) & 0x7FFu);
uint32_t offset = tag.payloadOffset;
for (uint32_t loop = 0u; loop < tag.nloop; ++loop)
{
for (uint32_t r = 0u; r < tag.nreg; ++r)
{
const uint64_t lo = loadLE64(data + offset);
const uint64_t hi = loadLE64(data + offset + 8u);
offset += 16u;
writeRegisterPacked(tag.regs[r], lo, hi);
}
}
return true;
});
if (!processed)
return false;
++m_nativePackedGIFPacketCount;
return true;
}
void GS::uploadImageNative(uint64_t bitbltbuf,
uint64_t trxpos,
uint64_t trxreg,
uint64_t trxdir,
const uint8_t *data,
uint32_t sizeBytes)
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!data || sizeBytes == 0 || !m_vram)
return;
writeRegister(GS_REG_BITBLTBUF, bitbltbuf);
writeRegister(GS_REG_TRXPOS, trxpos);
writeRegister(GS_REG_TRXREG, trxreg);
writeRegister(GS_REG_TRXDIR, trxdir);
processImageData(data, sizeBytes);
++m_nativeImageUploadCount;
}
bool GS::tryProcessNativeImageUploadPacket(const uint8_t *data, uint32_t sizeBytes)
{
constexpr uint32_t kSetupRegisters = 4u;
constexpr uint32_t kPackedAdPayloadBytes = kSetupRegisters * 16u;
constexpr uint64_t kPackedAdDescriptor = 0x0Eull;
if (!data || sizeBytes < 16u + kPackedAdPayloadBytes + 16u)
return false;
const uint64_t setupTagLo = loadLE64(data);
const uint64_t setupTagHi = loadLE64(data + 8u);
const uint32_t setupNloop = static_cast<uint32_t>(setupTagLo & 0x7FFFu);
const uint8_t setupFlg = static_cast<uint8_t>((setupTagLo >> 58u) & 0x3u);
uint32_t setupNreg = static_cast<uint32_t>((setupTagLo >> 60u) & 0xFu);
if (setupNreg == 0u)
setupNreg = 16u;
if (setupNloop != kSetupRegisters ||
setupFlg != GIF_FMT_PACKED ||
setupNreg != 1u ||
(setupTagHi & 0xFull) != kPackedAdDescriptor)
{
return false;
}
uint64_t regs[kSetupRegisters] = {};
uint32_t offset = 16u;
constexpr uint8_t expectedRegs[kSetupRegisters] = {
GS_REG_BITBLTBUF,
GS_REG_TRXPOS,
GS_REG_TRXREG,
GS_REG_TRXDIR,
};
for (uint32_t i = 0; i < kSetupRegisters; ++i)
{
regs[i] = loadLE64(data + offset);
const uint64_t reg = loadLE64(data + offset + 8u);
if ((reg & 0xFFu) != expectedRegs[i])
return false;
offset += 16u;
}
const uint32_t trxdirMode = static_cast<uint32_t>(regs[3] & 0x3ull);
const uint32_t rrw = static_cast<uint32_t>(regs[2] & 0xFFFull);
const uint32_t rrh = static_cast<uint32_t>((regs[2] >> 32u) & 0xFFFull);
if (trxdirMode != 0u || rrw == 0u || rrh == 0u)
return false;
if (offset + 16u > sizeBytes)
return false;
const uint64_t imageTagLo = loadLE64(data + offset);
const uint8_t imageFlg = static_cast<uint8_t>((imageTagLo >> 58u) & 0x3u);
const uint32_t imageNloop = static_cast<uint32_t>(imageTagLo & 0x7FFFu);
if (imageFlg != GIF_FMT_IMAGE || imageNloop == 0u)
return false;
offset += 16u;
const uint64_t imageBytes64 = static_cast<uint64_t>(imageNloop) * 16ull;
if (imageBytes64 > 0xFFFFFFFFull)
return false;
const uint32_t imageBytes = static_cast<uint32_t>(imageBytes64);
if (offset + imageBytes != sizeBytes)
return false;
uploadImageNative(regs[0], regs[1], regs[2], regs[3], data + offset, imageBytes);
return true;
}
void GS::writeRegisterPacked(uint8_t regDesc, uint64_t lo, uint64_t hi)
{
switch (regDesc)