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) {
|
if (header_.metadata.volume_type == XContentVolumeType::kStfs) {
|
||||||
return header_.metadata.volume_descriptor.stfs.total_block_count * kBlockSize;
|
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);
|
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);
|
void BlockToOffsetSVOD(size_t sector, size_t* address, size_t* file_index);
|
||||||
|
|
||||||
Error ReadSTFS();
|
Error ReadSTFS();
|
||||||
|
size_t StfsBaseOffset() const;
|
||||||
size_t BlockToOffsetSTFS(uint64_t block_index) const;
|
size_t BlockToOffsetSTFS(uint64_t block_index) const;
|
||||||
uint32_t BlockToHashBlockNumberSTFS(uint32_t block_index, uint32_t hash_level) 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;
|
size_t BlockToHashBlockOffsetSTFS(uint32_t block_index, uint32_t hash_level) const;
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ extern PPCFuncMapping {{ project }}_PPCFuncMappings[];
|
||||||
// Memory Access
|
// 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)
|
#define REX_PHYS_HOST_OFFSET(addr) (((u32)(addr) >= 0xE0000000u) ? 0x1000u : 0u)
|
||||||
#else
|
#else
|
||||||
#define REX_PHYS_HOST_OFFSET(addr) 0u
|
#define REX_PHYS_HOST_OFFSET(addr) 0u
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
#endif
|
#endif
|
||||||
#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)
|
#define REX_PHYS_HOST_OFFSET(addr) (((u32)(addr) >= 0xE0000000u) ? 0x1000u : 0u)
|
||||||
#else
|
#else
|
||||||
#define REX_PHYS_HOST_OFFSET(addr) 0u
|
#define REX_PHYS_HOST_OFFSET(addr) 0u
|
||||||
|
|
|
||||||
|
|
@ -568,15 +568,20 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string name(reinterpret_cast<const char*>(dir_entry.name),
|
||||||
|
dir_entry.flags.name_length & 0x3F);
|
||||||
StfsContainerEntry* parent_entry = nullptr;
|
StfsContainerEntry* parent_entry = nullptr;
|
||||||
if (dir_entry.directory_index == 0xFFFF) {
|
if (dir_entry.directory_index == 0xFFFF) {
|
||||||
parent_entry = root_entry;
|
parent_entry = root_entry;
|
||||||
} else {
|
} 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];
|
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_);
|
auto entry = StfsContainerEntry::Create(this, parent_entry, name, &files_);
|
||||||
|
|
||||||
if (dir_entry.flags.directory) {
|
if (dir_entry.flags.directory) {
|
||||||
|
|
@ -609,27 +614,32 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
||||||
entry->block_list_.push_back({0, offset, block_size});
|
entry->block_list_.push_back({0, offset, block_size});
|
||||||
remaining_size -= block_size;
|
remaining_size -= block_size;
|
||||||
auto block_hash = GetBlockHash(block_index);
|
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();
|
block_index = block_hash->level0_next_block();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remaining_size) {
|
if (remaining_size) {
|
||||||
// Loop above must have exited prematurely, bad hash tables?
|
// Loop above must have exited prematurely, bad hash tables?
|
||||||
REXFS_WARN(
|
REXFS_ERROR(
|
||||||
"STFS file {} only found {} bytes for file, expected {} ({} "
|
"STFS file {} only found {} bytes for file, expected {} ({} "
|
||||||
"bytes missing)",
|
"bytes missing)",
|
||||||
name, dir_entry.length.get() - remaining_size, dir_entry.length.get(),
|
name, dir_entry.length.get() - remaining_size, dir_entry.length.get(),
|
||||||
remaining_size);
|
remaining_size);
|
||||||
assert_always();
|
return Error::kErrorDamagedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the number of blocks retrieved from hash entries matches
|
// Check that the number of blocks retrieved from hash entries matches
|
||||||
// the block count read from the file entry
|
// the block count read from the file entry
|
||||||
if (entry->block_list_.size() != dir_entry.allocated_data_blocks()) {
|
if (entry->block_list_.size() != dir_entry.allocated_data_blocks()) {
|
||||||
REXFS_WARN(
|
REXFS_ERROR(
|
||||||
"STFS failed to read correct block-chain for entry {}, read {} "
|
"STFS failed to read correct block-chain for entry {}, read {} "
|
||||||
"blocks, expected {}",
|
"blocks, expected {}",
|
||||||
entry->name_, entry->block_list_.size(), dir_entry.allocated_data_blocks());
|
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);
|
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();
|
table_block_index = block_hash->level0_next_block();
|
||||||
if (table_block_index == kEndOfChain) {
|
if (table_block_index == kEndOfChain) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -644,14 +658,22 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n + 1 != descriptor.file_table_block_count) {
|
if (n + 1 != descriptor.file_table_block_count) {
|
||||||
REXFS_WARN("STFS read {} file table blocks, but STFS headers expected {}!", n + 1,
|
REXFS_ERROR("STFS read {} file table blocks, but STFS headers expected {}!", n + 1,
|
||||||
descriptor.file_table_block_count);
|
descriptor.file_table_block_count);
|
||||||
assert_always();
|
return Error::kErrorDamagedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Error::kSuccess;
|
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 {
|
size_t StfsContainerDevice::BlockToOffsetSTFS(uint64_t block_index) const {
|
||||||
// For every level there is a hash table
|
// For every level there is a hash table
|
||||||
// Level 0: hash table of next 170 blocks
|
// Level 0: hash table of next 170 blocks
|
||||||
|
|
@ -669,7 +691,7 @@ size_t StfsContainerDevice::BlockToOffsetSTFS(uint64_t block_index) const {
|
||||||
base *= kBlocksPerHashLevel[0];
|
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,
|
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,
|
size_t StfsContainerDevice::BlockToHashBlockOffsetSTFS(uint32_t block_index,
|
||||||
uint32_t hash_level) const {
|
uint32_t hash_level) const {
|
||||||
uint64_t block = BlockToHashBlockNumberSTFS(block_index, hash_level);
|
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) {
|
const StfsHashEntry* StfsContainerDevice::GetBlockHash(uint32_t block_index) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue