From 8ddd5f21b6bd7bef1655f929e43f4a017f75d5b8 Mon Sep 17 00:00:00 2001 From: p33k-a-b00 <43139100+p33k-a-b00@users.noreply.github.com> Date: Sat, 11 Apr 2026 21:36:13 -0400 Subject: [PATCH] FSC: Retry WUA lookup with percent-encoded '@' Some WUA packers percent-encode reserved characters in entry names, so '@bg0010.arc' ends up stored as '%40bg0010.arc'. ZArchive's LookUp is byte-literal, so the initial query misses and FSOpenFile returns -6. Fixes Twilight Princess HD, whose DVD thread (mDoDvdThd_mountArchive_c) uses '@'-prefixed archive names for Forest Temple room backgrounds. Without the retry, the cage room (bg0010) fails to mount and the player is softlocked on the monkey puzzle. --- src/Cafe/Filesystem/fscDeviceWua.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Cafe/Filesystem/fscDeviceWua.cpp b/src/Cafe/Filesystem/fscDeviceWua.cpp index f9014bdb..ac15646c 100644 --- a/src/Cafe/Filesystem/fscDeviceWua.cpp +++ b/src/Cafe/Filesystem/fscDeviceWua.cpp @@ -125,6 +125,23 @@ class fscDeviceWUAC : public fscDeviceC cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to WUA is not supported ZArchiveNodeHandle fileHandle = archive->LookUp(path, true, true); + if (fileHandle == ZARCHIVE_INVALID_NODE && path.find('@') != std::string_view::npos) + { + // Some WUA packers percent-encode '@' in entry names (stored as "%40"), + // so a byte-literal LookUp for "@bg0010.arc" misses "%40bg0010.arc". + // Retry with '@' percent-encoded. Affects Twilight Princess HD, whose + // DVD thread uses '@'-prefixed archive names for Forest Temple rooms. + std::string retryPath; + retryPath.reserve(path.size() + 16); + for (char c : path) + { + if (c == '@') + retryPath += "%40"; + else + retryPath += c; + } + fileHandle = archive->LookUp(retryPath, true, true); + } if (fileHandle == ZARCHIVE_INVALID_NODE) { *fscStatus = FSC_STATUS_FILE_NOT_FOUND;