[VFS] Add StfsHashEntry struct to view hash entry flags in more detail
+ small adds to StfsHeader
This commit is contained in:
parent
7eb5fa230a
commit
c3551636e1
|
@ -542,16 +542,16 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
|||
if (entry->attributes() & X_FILE_ATTRIBUTE_NORMAL) {
|
||||
uint32_t block_index = start_block_index;
|
||||
size_t remaining_size = file_size;
|
||||
uint32_t info = 0x80;
|
||||
while (remaining_size && block_index) {
|
||||
assert_true(block_index != 0xffffff);
|
||||
|
||||
size_t block_size =
|
||||
std::min(static_cast<size_t>(0x1000), remaining_size);
|
||||
size_t offset = STFSDataBlockToOffset(block_index);
|
||||
entry->block_list_.push_back({0, offset, block_size});
|
||||
remaining_size -= block_size;
|
||||
auto block_hash = STFSGetLevel0HashEntry(data, block_index);
|
||||
block_index = block_hash.next_block_index;
|
||||
info = block_hash.info;
|
||||
block_index = block_hash.level0_next_block();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,7 +559,7 @@ StfsContainerDevice::Error StfsContainerDevice::ReadSTFS() {
|
|||
}
|
||||
|
||||
auto block_hash = STFSGetLevel0HashEntry(data, table_block_index);
|
||||
table_block_index = block_hash.next_block_index;
|
||||
table_block_index = block_hash.level0_next_block();
|
||||
}
|
||||
|
||||
if (all_entries.size() > 0) {
|
||||
|
@ -634,7 +634,7 @@ size_t StfsContainerDevice::STFSDataBlockToBackingHashBlockOffset(
|
|||
STFSDataBlockToBackingHashBlock(block, level));
|
||||
}
|
||||
|
||||
StfsContainerDevice::BlockHash StfsContainerDevice::STFSGetLevelNHashEntry(
|
||||
StfsHashEntry StfsContainerDevice::STFSGetLevelNHashEntry(
|
||||
const uint8_t* map_ptr, uint32_t block_index, uint32_t level,
|
||||
bool secondary_block) {
|
||||
uint32_t record = block_index;
|
||||
|
@ -652,13 +652,11 @@ StfsContainerDevice::BlockHash StfsContainerDevice::STFSGetLevelNHashEntry(
|
|||
|
||||
const uint8_t* hash_data = map_ptr + hash_offset;
|
||||
|
||||
const uint8_t* record_data = hash_data + record * 0x18;
|
||||
uint32_t info = xe::load_and_swap<uint8_t>(record_data + 0x14);
|
||||
uint32_t next_block_index = load_uint24_be(record_data + 0x15);
|
||||
return {next_block_index, info};
|
||||
auto* entry = (StfsHashEntry*)(hash_data + record * 0x18);
|
||||
return *entry;
|
||||
}
|
||||
|
||||
StfsContainerDevice::BlockHash StfsContainerDevice::STFSGetLevel0HashEntry(
|
||||
StfsHashEntry StfsContainerDevice::STFSGetLevel0HashEntry(
|
||||
const uint8_t* map_ptr, uint32_t block_index) {
|
||||
bool use_secondary_block = false;
|
||||
// Use secondary block for root table if RootActiveIndex flag is set
|
||||
|
@ -679,7 +677,7 @@ StfsContainerDevice::BlockHash StfsContainerDevice::STFSGetLevel0HashEntry(
|
|||
auto l2_entry =
|
||||
STFSGetLevelNHashEntry(map_ptr, block_index, 2, use_secondary_block);
|
||||
use_secondary_block = false;
|
||||
if (l2_entry.info & 0x40) { // ActiveIndex flag
|
||||
if (l2_entry.levelN_activeindex()) {
|
||||
use_secondary_block = true;
|
||||
}
|
||||
}
|
||||
|
@ -689,7 +687,7 @@ StfsContainerDevice::BlockHash StfsContainerDevice::STFSGetLevel0HashEntry(
|
|||
auto l1_entry =
|
||||
STFSGetLevelNHashEntry(map_ptr, block_index, 1, use_secondary_block);
|
||||
use_secondary_block = false;
|
||||
if (l1_entry.info & 0x40) { // ActiveIndex flag
|
||||
if (l1_entry.levelN_activeindex()) {
|
||||
use_secondary_block = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,26 @@ struct StfsVolumeDescriptor {
|
|||
};
|
||||
static_assert_size(StfsVolumeDescriptor, 0x24);
|
||||
|
||||
struct StfsHashEntry {
|
||||
uint8_t sha1[0x14];
|
||||
|
||||
uint8_t info0; // usually contains flags
|
||||
|
||||
uint8_t info1;
|
||||
uint8_t info2;
|
||||
uint8_t info3;
|
||||
|
||||
// If this is a level0 entry, this points to the next block in the chain
|
||||
uint32_t level0_next_block() { return info3 | (info2 << 8) | (info1 << 16); }
|
||||
|
||||
// If this is level 1 or 2, this says whether the hash table this entry refers
|
||||
// to is using the secondary block or not
|
||||
bool levelN_activeindex() { return info0 & 0x40; }
|
||||
|
||||
bool levelN_writeable() { return info0 & 0x80; }
|
||||
};
|
||||
static_assert_size(StfsHashEntry, 0x18);
|
||||
|
||||
/* SVOD */
|
||||
struct SvodDeviceDescriptor {
|
||||
uint8_t descriptor_length;
|
||||
|
@ -385,13 +405,16 @@ struct StfsHeader {
|
|||
XContentInstaller installer;
|
||||
uint8_t padding[0x2F2];
|
||||
|
||||
bool has_installer() {
|
||||
return header.header_size == 0xAD0E && installer.type != 0;
|
||||
}
|
||||
|
||||
void set_defaults() {
|
||||
memset(this, 0, sizeof(StfsHeader));
|
||||
|
||||
header.magic = xe::vfs::XContentPackageType::kPackageTypeCon;
|
||||
header.licenses[0].licensee_id =
|
||||
-1; // X360 gamesaves seem to set licenses like this
|
||||
header.header_size = 0x971A;
|
||||
header.licenses[0].licensee_id = -1; // gamesaves set licenses like this ?
|
||||
header.header_size = 0x971A; // no installer section in header
|
||||
|
||||
metadata.metadata_version = 2;
|
||||
memcpy(metadata.console_id, "XENIA", 5);
|
||||
|
@ -441,11 +464,6 @@ class StfsContainerDevice : public Device {
|
|||
kSingleFile = 0x4,
|
||||
};
|
||||
|
||||
struct BlockHash {
|
||||
uint32_t next_block_index;
|
||||
uint32_t info;
|
||||
};
|
||||
|
||||
const uint32_t kSTFSDataBlocksPerHashLevel[3] = {0xAA, 0x70E4, 0x4AF768};
|
||||
|
||||
uint32_t ReadMagic(const std::wstring& path);
|
||||
|
@ -469,12 +487,12 @@ class StfsContainerDevice : public Device {
|
|||
size_t STFSDataBlockToBackingHashBlockOffset(uint64_t block,
|
||||
uint32_t level = 0);
|
||||
|
||||
BlockHash STFSGetLevelNHashEntry(const uint8_t* map_ptr, uint32_t block_index,
|
||||
uint32_t level,
|
||||
bool secondary_block = false);
|
||||
StfsHashEntry STFSGetLevelNHashEntry(const uint8_t* map_ptr,
|
||||
uint32_t block_index, uint32_t level,
|
||||
bool secondary_block = false);
|
||||
|
||||
BlockHash STFSGetLevel0HashEntry(const uint8_t* map_ptr,
|
||||
uint32_t block_index);
|
||||
StfsHashEntry STFSGetLevel0HashEntry(const uint8_t* map_ptr,
|
||||
uint32_t block_index);
|
||||
|
||||
std::wstring local_path_;
|
||||
std::map<size_t, std::unique_ptr<MappedMemory>> mmap_;
|
||||
|
|
Loading…
Reference in New Issue