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.
This commit is contained in:
p33k-a-b00 2026-04-11 21:36:13 -04:00
parent 391478b307
commit 8ddd5f21b6

View File

@ -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;