From 18c930c1b209eb24edd4081ce31804821902ae48 Mon Sep 17 00:00:00 2001 From: emoose Date: Sun, 5 Jan 2020 20:18:14 +0000 Subject: [PATCH] [VFS] Port new BlockToOffsetSTFS algo from stfs-headers https://github.com/emoose/xenia/commit/65ca664fdb5dc75d8585a2ca8f19f2f13b676e74 This should give better compatibility with CON packages - ie. profiles taken from actual consoles should hopefully extract properly without errors, now there's shouldn't be any need for extracting them with Velocity/Horizon first. --- .../vfs/devices/stfs_container_device.cc | 35 ++++++++++++++++++- src/xenia/vfs/devices/stfs_container_device.h | 3 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/xenia/vfs/devices/stfs_container_device.cc b/src/xenia/vfs/devices/stfs_container_device.cc index 8b180e91d..29e069df5 100644 --- a/src/xenia/vfs/devices/stfs_container_device.cc +++ b/src/xenia/vfs/devices/stfs_container_device.cc @@ -591,10 +591,43 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() { } } - return Error::kSuccess; + if (all_entries.size() > 0) { + return Error::kSuccess; + } + + // Failed to load any entries, try with old algo if we haven't already + if (!use_old_algorithm_) { + use_old_algorithm_ = true; + return ReadSTFS(); + } + + // Tried with old algo and still no entries... return failure + return Error::kErrorReadError; } size_t StfsContainerDevice::BlockToOffsetSTFS(uint64_t block_index) { + if (use_old_algorithm_) { + return BlockToOffsetSTFS_Old(block_index); + } + + uint32_t num_tables = 1; // num hashtables per block? or maybe backingblocks? + if (((header_.header_size + 0xFFF) & 0xB000) == 0xB000 || + (header_.stfs_volume_descriptor.flags & 0x1) == 0x0) { + num_tables++; + } + + uint64_t dataBlock = block_index + num_tables * ((block_index + 0xAA) / 0xAA); + if (block_index >= 170) { + dataBlock += num_tables * ((block_index + 0x70E4) / 0x70E4); + if (block_index >= 28900) { + dataBlock += num_tables * ((block_index + 0x4AF768) / 0x4AF768); + } + } + + return xe::round_up(header_.header_size, 0x1000) + (dataBlock * 0x1000); +} + +size_t StfsContainerDevice::BlockToOffsetSTFS_Old(uint64_t block_index) { uint64_t block; uint32_t block_shift = 0; if (((header_.header_size + 0x0FFF) & 0xB000) == 0xB000 || diff --git a/src/xenia/vfs/devices/stfs_container_device.h b/src/xenia/vfs/devices/stfs_container_device.h index e77674a3a..658844f84 100644 --- a/src/xenia/vfs/devices/stfs_container_device.h +++ b/src/xenia/vfs/devices/stfs_container_device.h @@ -217,6 +217,7 @@ class StfsContainerDevice : public Device { Error ReadSTFS(); size_t BlockToOffsetSTFS(uint64_t block); + size_t BlockToOffsetSTFS_Old(uint64_t block); BlockHash GetBlockHash(const uint8_t* map_ptr, uint32_t block_index, uint32_t table_offset); @@ -231,6 +232,8 @@ class StfsContainerDevice : public Device { StfsPackageType package_type_; StfsHeader header_; uint32_t table_size_shift_; + + bool use_old_algorithm_ = false; }; } // namespace vfs