From e5ae29b27ec4f6db17a21890a6bc4f4021232495 Mon Sep 17 00:00:00 2001 From: patchzyy <64382339+patchzyy@users.noreply.github.com> Date: Mon, 24 Aug 2026 11:30:11 +0200 Subject: [PATCH] Create egg_decomp.cpp --- runtime/src/hle/egg_decomp.cpp | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 runtime/src/hle/egg_decomp.cpp diff --git a/runtime/src/hle/egg_decomp.cpp b/runtime/src/hle/egg_decomp.cpp new file mode 100644 index 0000000..d1d2200 --- /dev/null +++ b/runtime/src/hle/egg_decomp.cpp @@ -0,0 +1,61 @@ +#include "hle_stubs.h" + +#include +#include "memory.h" +#include "runtime_log.h" + +// Native because a crafted Yaz0 run writes past the caller's buffer +// (github.com/vabold/szsHaxx) +// https://github.com/vabold/Kinoko/blob/main/source/egg/core/Decomp.cc + +extern "C" uint32_t EGG_Decomp_decodeSZS_80218c2c(uint32_t src, uint32_t dst) +{ + const uint32_t expandSize = (static_cast(MemoryInline::FlatRead8(src + 4)) << 24) | + (static_cast(MemoryInline::FlatRead8(src + 5)) << 16) | + (static_cast(MemoryInline::FlatRead8(src + 6)) << 8) | + static_cast(MemoryInline::FlatRead8(src + 7)); + + uint32_t srcIdx = 16; + uint32_t dstIdx = 0; + uint32_t mask = 0; + uint32_t flags = 0; + + while (static_cast(dstIdx) < static_cast(expandSize)) { + if (mask == 0) { + flags = MemoryInline::FlatRead8(src + srcIdx++); + mask = 0x80; + } + + if ((flags & mask) != 0) { + MemoryInline::FlatWrite8(dst + dstIdx++, MemoryInline::FlatRead8(src + srcIdx++)); + } else { + const uint32_t high = MemoryInline::FlatRead8(src + srcIdx); + const uint32_t low = MemoryInline::FlatRead8(src + srcIdx + 1); + srcIdx += 2; + + const uint32_t rep = (high << 8) | low; + uint32_t copyIdx = dstIdx - (rep & 0xFFF) - 1; + uint32_t count = rep >> 12; + count = count != 0 + ? count + 2 + : static_cast(MemoryInline::FlatRead8(src + srcIdx++)) + 18; + + for (uint32_t i = 0; i < count; ++i) { + if (dstIdx >= expandSize) { + RT_LOG(RT_TAG_HLE) << "decodeSZS: malformed stream from 0x" << std::hex << src + << std::dec << ", stopped after " << dstIdx << " of " + << expandSize << " bytes" << std::endl; + return expandSize; + } + MemoryInline::FlatWrite8(dst + dstIdx++, MemoryInline::FlatRead8(dst + copyIdx++)); + } + } + + mask >>= 1; + } + + return expandSize; +} + +PPC_NATIVE_OVERRIDE(80218C2C, EGG_Decomp_decodeSZS_80218c2c, uint32_t, + (uint32_t src, uint32_t dst), (src, dst));