fixed missing DLC, macOS crash, crashes when editing photos
This commit is contained in:
parent
4329f6d049
commit
5d932d1cc8
4 changed files with 37 additions and 14 deletions
|
|
@ -77,7 +77,7 @@ class StfsContainerDevice : public Device {
|
|||
if (header_.metadata.volume_type == XContentVolumeType::kStfs) {
|
||||
return header_.metadata.volume_descriptor.stfs.total_block_count * kBlockSize;
|
||||
}
|
||||
return files_total_size_ - rex::round_up(header_.header.header_size, kBlockSize);
|
||||
return files_total_size_ - StfsBaseOffset();
|
||||
}
|
||||
return files_total_size_ - sizeof(StfsHeader);
|
||||
}
|
||||
|
|
@ -116,6 +116,7 @@ class StfsContainerDevice : public Device {
|
|||
void BlockToOffsetSVOD(size_t sector, size_t* address, size_t* file_index);
|
||||
|
||||
Error ReadSTFS();
|
||||
size_t StfsBaseOffset() const;
|
||||
size_t BlockToOffsetSTFS(uint64_t block_index) const;
|
||||
uint32_t BlockToHashBlockNumberSTFS(uint32_t block_index, uint32_t hash_level) const;
|
||||
size_t BlockToHashBlockOffsetSTFS(uint32_t block_index, uint32_t hash_level) const;
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ extern PPCFuncMapping {{ project }}_PPCFuncMappings[];
|
|||
// Memory Access
|
||||
//=============================================================================
|
||||
|
||||
#if REX_PLATFORM_WIN32
|
||||
#if REX_PLATFORM_WIN32 || (REX_PLATFORM_MAC && REX_ARCH_ARM64)
|
||||
#define REX_PHYS_HOST_OFFSET(addr) (((u32)(addr) >= 0xE0000000u) ? 0x1000u : 0u)
|
||||
#else
|
||||
#define REX_PHYS_HOST_OFFSET(addr) 0u
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if REX_PLATFORM_WIN32
|
||||
#if REX_PLATFORM_WIN32 || (REX_PLATFORM_MAC && REX_ARCH_ARM64)
|
||||
#define REX_PHYS_HOST_OFFSET(addr) (((u32)(addr) >= 0xE0000000u) ? 0x1000u : 0u)
|
||||
#else
|
||||
#define REX_PHYS_HOST_OFFSET(addr) 0u
|
||||
|
|
|
|||
|
|
@ -568,15 +568,20 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
|||
break;
|
||||
}
|
||||
|
||||
std::string name(reinterpret_cast<const char*>(dir_entry.name),
|
||||
dir_entry.flags.name_length & 0x3F);
|
||||
StfsContainerEntry* parent_entry = nullptr;
|
||||
if (dir_entry.directory_index == 0xFFFF) {
|
||||
parent_entry = root_entry;
|
||||
} else {
|
||||
if (dir_entry.directory_index >= all_entries.size()) {
|
||||
REXFS_ERROR("STFS directory entry {} has invalid parent index {}", name,
|
||||
dir_entry.directory_index.get());
|
||||
return Error::kErrorDamagedFile;
|
||||
}
|
||||
parent_entry = all_entries[dir_entry.directory_index];
|
||||
}
|
||||
|
||||
std::string name(reinterpret_cast<const char*>(dir_entry.name),
|
||||
dir_entry.flags.name_length & 0x3F);
|
||||
auto entry = StfsContainerEntry::Create(this, parent_entry, name, &files_);
|
||||
|
||||
if (dir_entry.flags.directory) {
|
||||
|
|
@ -609,27 +614,32 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
|||
entry->block_list_.push_back({0, offset, block_size});
|
||||
remaining_size -= block_size;
|
||||
auto block_hash = GetBlockHash(block_index);
|
||||
if (!block_hash) {
|
||||
REXFS_ERROR("STFS failed to read block hash for entry {} block {}", name,
|
||||
block_index);
|
||||
return Error::kErrorReadError;
|
||||
}
|
||||
block_index = block_hash->level0_next_block();
|
||||
}
|
||||
|
||||
if (remaining_size) {
|
||||
// Loop above must have exited prematurely, bad hash tables?
|
||||
REXFS_WARN(
|
||||
REXFS_ERROR(
|
||||
"STFS file {} only found {} bytes for file, expected {} ({} "
|
||||
"bytes missing)",
|
||||
name, dir_entry.length.get() - remaining_size, dir_entry.length.get(),
|
||||
remaining_size);
|
||||
assert_always();
|
||||
return Error::kErrorDamagedFile;
|
||||
}
|
||||
|
||||
// Check that the number of blocks retrieved from hash entries matches
|
||||
// the block count read from the file entry
|
||||
if (entry->block_list_.size() != dir_entry.allocated_data_blocks()) {
|
||||
REXFS_WARN(
|
||||
REXFS_ERROR(
|
||||
"STFS failed to read correct block-chain for entry {}, read {} "
|
||||
"blocks, expected {}",
|
||||
entry->name_, entry->block_list_.size(), dir_entry.allocated_data_blocks());
|
||||
assert_always();
|
||||
return Error::kErrorDamagedFile;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -637,6 +647,10 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
|||
}
|
||||
|
||||
auto block_hash = GetBlockHash(table_block_index);
|
||||
if (!block_hash) {
|
||||
REXFS_ERROR("STFS failed to read file table block hash for block {}", table_block_index);
|
||||
return Error::kErrorReadError;
|
||||
}
|
||||
table_block_index = block_hash->level0_next_block();
|
||||
if (table_block_index == kEndOfChain) {
|
||||
break;
|
||||
|
|
@ -644,14 +658,22 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
|||
}
|
||||
|
||||
if (n + 1 != descriptor.file_table_block_count) {
|
||||
REXFS_WARN("STFS read {} file table blocks, but STFS headers expected {}!", n + 1,
|
||||
descriptor.file_table_block_count);
|
||||
assert_always();
|
||||
REXFS_ERROR("STFS read {} file table blocks, but STFS headers expected {}!", n + 1,
|
||||
descriptor.file_table_block_count);
|
||||
return Error::kErrorDamagedFile;
|
||||
}
|
||||
|
||||
return Error::kSuccess;
|
||||
}
|
||||
|
||||
size_t StfsContainerDevice::StfsBaseOffset() const {
|
||||
// STFS packages with CON headers can report a metadata header size that
|
||||
// rounds to 0xA000, but the hash tables still begin at the standard 0xB000
|
||||
// backing offset. Using the smaller value makes the directory reader consume
|
||||
// hash bytes as file-table entries.
|
||||
return std::max<size_t>(0xB000, rex::round_up(header_.header.header_size, kBlockSize));
|
||||
}
|
||||
|
||||
size_t StfsContainerDevice::BlockToOffsetSTFS(uint64_t block_index) const {
|
||||
// For every level there is a hash table
|
||||
// Level 0: hash table of next 170 blocks
|
||||
|
|
@ -669,7 +691,7 @@ size_t StfsContainerDevice::BlockToOffsetSTFS(uint64_t block_index) const {
|
|||
base *= kBlocksPerHashLevel[0];
|
||||
}
|
||||
|
||||
return rex::round_up(header_.header.header_size, kBlockSize) + (block << 12);
|
||||
return StfsBaseOffset() + (block << 12);
|
||||
}
|
||||
|
||||
uint32_t StfsContainerDevice::BlockToHashBlockNumberSTFS(uint32_t block_index,
|
||||
|
|
@ -706,7 +728,7 @@ uint32_t StfsContainerDevice::BlockToHashBlockNumberSTFS(uint32_t block_index,
|
|||
size_t StfsContainerDevice::BlockToHashBlockOffsetSTFS(uint32_t block_index,
|
||||
uint32_t hash_level) const {
|
||||
uint64_t block = BlockToHashBlockNumberSTFS(block_index, hash_level);
|
||||
return rex::round_up(header_.header.header_size, kBlockSize) + (block << 12);
|
||||
return StfsBaseOffset() + (block << 12);
|
||||
}
|
||||
|
||||
const StfsHashEntry* StfsContainerDevice::GetBlockHash(uint32_t block_index) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue