diff --git a/src/xenia/kernel/fs/device.cc b/src/xenia/kernel/fs/device.cc index 9bc191b27..f4c32a000 100644 --- a/src/xenia/kernel/fs/device.cc +++ b/src/xenia/kernel/fs/device.cc @@ -9,10 +9,14 @@ #include -using namespace xe; -using namespace xe::kernel; -using namespace xe::kernel::fs; +namespace xe { +namespace kernel { +namespace fs { Device::Device(const std::string& path) : path_(path) {} Device::~Device() = default; + +} // namespace fs +} // namespace kernel +} // namespace xe diff --git a/src/xenia/kernel/fs/device.h b/src/xenia/kernel/fs/device.h index 81d409761..af24004da 100644 --- a/src/xenia/kernel/fs/device.h +++ b/src/xenia/kernel/fs/device.h @@ -12,9 +12,7 @@ #include -#include #include - #include namespace xe { diff --git a/src/xenia/kernel/fs/devices/stfs_container_entry.cc b/src/xenia/kernel/fs/devices/stfs_container_entry.cc index 1af716c67..e738d2607 100644 --- a/src/xenia/kernel/fs/devices/stfs_container_entry.cc +++ b/src/xenia/kernel/fs/devices/stfs_container_entry.cc @@ -65,7 +65,7 @@ X_STATUS STFSContainerEntry::QueryDirectory( auto end = (uint8_t*)out_info + length; - auto entry = *stfs_entry_iterator_; + auto entry = stfs_entry_iterator_->get(); auto entry_name = entry->name; if (((uint8_t*)&out_info->file_name[0]) + entry_name.size() > end) { diff --git a/src/xenia/kernel/fs/devices/stfs_container_entry.h b/src/xenia/kernel/fs/devices/stfs_container_entry.h index 8858a3441..aead9c014 100644 --- a/src/xenia/kernel/fs/devices/stfs_container_entry.h +++ b/src/xenia/kernel/fs/devices/stfs_container_entry.h @@ -46,7 +46,7 @@ public: private: xe_mmap_ref mmap_; STFSEntry* stfs_entry_; - std::vector::iterator stfs_entry_iterator_; + std::vector>::iterator stfs_entry_iterator_; }; diff --git a/src/xenia/kernel/fs/entry.cc b/src/xenia/kernel/fs/entry.cc index 30b18d74b..448207229 100644 --- a/src/xenia/kernel/fs/entry.cc +++ b/src/xenia/kernel/fs/entry.cc @@ -10,9 +10,9 @@ #include #include -using namespace xe; -using namespace xe::kernel; -using namespace xe::kernel::fs; +namespace xe { +namespace kernel { +namespace fs { MemoryMapping::MemoryMapping(uint8_t* address, size_t length) : address_(address), length_(length) {} @@ -28,3 +28,7 @@ Entry::Entry(Type type, Device* device, const std::string& path) } Entry::~Entry() = default; + +} // namespace fs +} // namespace kernel +} // namespace xe diff --git a/src/xenia/kernel/fs/entry.h b/src/xenia/kernel/fs/entry.h index 1f5b09d1a..f0cb428d3 100644 --- a/src/xenia/kernel/fs/entry.h +++ b/src/xenia/kernel/fs/entry.h @@ -12,19 +12,19 @@ #include -#include #include - #include - -XEDECLARECLASS2(xe, kernel, KernelState); -XEDECLARECLASS2(xe, kernel, XFile); -XEDECLARECLASS2(xe, kernel, XFileInfo); -XEDECLARECLASS2(xe, kernel, XDirectoryInfo); -XEDECLARECLASS2(xe, kernel, XVolumeInfo); -XEDECLARECLASS2(xe, kernel, XFileSystemAttributeInfo); - +namespace xe { +namespace kernel { +class KernelState; +class XFile; +class XFileInfo; +class XFileSystemAttributeInfo; +class XDirectoryInfo; +class XVolumeInfo; +} // namespace kernel +} // namespace xe namespace xe { namespace kernel { @@ -32,23 +32,21 @@ namespace fs { class Device; - class MemoryMapping { -public: + public: MemoryMapping(uint8_t* address, size_t length); virtual ~MemoryMapping(); uint8_t* address() const { return address_; } size_t length() const { return length_; } -private: - uint8_t* address_; - size_t length_; + private: + uint8_t* address_; + size_t length_; }; - class Entry { -public: + public: enum Type { kTypeFile, kTypeDirectory, @@ -64,32 +62,29 @@ public: const std::string& name() const { return name_; } virtual X_STATUS QueryInfo(XFileInfo* out_info) = 0; - virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, - size_t length, const char* file_name, bool restart) = 0; + virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length, + const char* file_name, bool restart) = 0; virtual bool can_map() { return false; } - virtual MemoryMapping* CreateMemoryMapping( - xe_file_mode file_mode, const size_t offset, const size_t length) { + virtual MemoryMapping* CreateMemoryMapping(xe_file_mode file_mode, + const size_t offset, + const size_t length) { return NULL; } - virtual X_STATUS Open( - KernelState* kernel_state, - uint32_t desired_access, bool async, - XFile** out_file) = 0; + virtual X_STATUS Open(KernelState* kernel_state, uint32_t desired_access, + bool async, XFile** out_file) = 0; -private: - Type type_; - Device* device_; + private: + Type type_; + Device* device_; std::string path_; std::string absolute_path_; std::string name_; }; - } // namespace fs } // namespace kernel } // namespace xe - #endif // XENIA_KERNEL_FS_ENTRY_H_ diff --git a/src/xenia/kernel/fs/filesystem.cc b/src/xenia/kernel/fs/filesystem.cc index 26cc4b35d..0b9054359 100644 --- a/src/xenia/kernel/fs/filesystem.cc +++ b/src/xenia/kernel/fs/filesystem.cc @@ -14,14 +14,11 @@ #include #include +namespace xe { +namespace kernel { +namespace fs { -using namespace xe; -using namespace xe::kernel; -using namespace xe::kernel::fs; - - -FileSystem::FileSystem() { -} +FileSystem::FileSystem() {} FileSystem::~FileSystem() { // Delete all devices. @@ -106,14 +103,14 @@ int FileSystem::RegisterDevice(const std::string& path, Device* device) { return 0; } -int FileSystem::RegisterHostPathDevice( - const std::string& path, const std::wstring& local_path) { +int FileSystem::RegisterHostPathDevice(const std::string& path, + const std::wstring& local_path) { Device* device = new HostPathDevice(path, local_path); return RegisterDevice(path, device); } -int FileSystem::RegisterDiscImageDevice( - const std::string& path, const std::wstring& local_path) { +int FileSystem::RegisterDiscImageDevice(const std::string& path, + const std::wstring& local_path) { DiscImageDevice* device = new DiscImageDevice(path, local_path); if (device->Init()) { return 1; @@ -121,8 +118,8 @@ int FileSystem::RegisterDiscImageDevice( return RegisterDevice(path, device); } -int FileSystem::RegisterSTFSContainerDevice( - const std::string& path, const std::wstring& local_path) { +int FileSystem::RegisterSTFSContainerDevice(const std::string& path, + const std::wstring& local_path) { STFSContainerDevice* device = new STFSContainerDevice(path, local_path); if (device->Init()) { return 1; @@ -178,3 +175,7 @@ Entry* FileSystem::ResolvePath(const std::string& path) { XELOGE("ResolvePath(%s) failed - no root found", path.c_str()); return NULL; } + +} // namespace fs +} // namespace kernel +} // namespace xe diff --git a/src/xenia/kernel/fs/gdfx.cc b/src/xenia/kernel/fs/gdfx.cc index 9f275ff33..7f70a26b7 100644 --- a/src/xenia/kernel/fs/gdfx.cc +++ b/src/xenia/kernel/fs/gdfx.cc @@ -13,21 +13,14 @@ #include -using namespace xe; -using namespace xe::kernel; -using namespace xe::kernel::fs; +namespace xe { +namespace kernel { +namespace fs { +const size_t kXESectorSize = 2048; -namespace { - -#define kXESectorSize 2048 - -} - - -GDFXEntry::GDFXEntry() : - attributes(X_FILE_ATTRIBUTE_NONE), offset(0), size(0) { -} +GDFXEntry::GDFXEntry() + : attributes(X_FILE_ATTRIBUTE_NONE), offset(0), size(0) {} GDFXEntry::~GDFXEntry() { for (std::vector::iterator it = children.begin(); @@ -57,7 +50,6 @@ void GDFXEntry::Dump(int indent) { } } - GDFX::GDFX(xe_mmap_ref mmap) { mmap_ = xe_mmap_retain(mmap); @@ -70,28 +62,26 @@ GDFX::~GDFX() { xe_mmap_release(mmap_); } -GDFXEntry* GDFX::root_entry() { - return root_entry_; -} +GDFXEntry* GDFX::root_entry() { return root_entry_; } GDFX::Error GDFX::Load() { - Error result = kErrorOutOfMemory; - ParseState state; xe_zero_struct(&state, sizeof(state)); - state.ptr = (uint8_t*)xe_mmap_get_addr(mmap_); - state.size = xe_mmap_get_length(mmap_); + state.ptr = (uint8_t*)xe_mmap_get_addr(mmap_); + state.size = xe_mmap_get_length(mmap_); - result = Verify(state); - XEEXPECTZERO(result); + auto result = Verify(state); + if (result != kSuccess) { + return result; + } result = ReadAllEntries(state, state.ptr + state.root_offset); - XEEXPECTZERO(result); + if (result != kSuccess) { + return result; + } - result = kSuccess; -XECLEANUP: - return result; + return kSuccess; } void GDFX::Dump() { @@ -103,7 +93,7 @@ void GDFX::Dump() { GDFX::Error GDFX::Verify(ParseState& state) { // Find sector 32 of the game partition - try at a few points. const static size_t likely_offsets[] = { - 0x00000000, 0x0000FB20, 0x00020600, 0x0FD90000, + 0x00000000, 0x0000FB20, 0x00020600, 0x0FD90000, }; bool magic_found = false; for (size_t n = 0; n < poly::countof(likely_offsets); n++) { @@ -124,10 +114,9 @@ GDFX::Error GDFX::Verify(ParseState& state) { } uint8_t* fs_ptr = state.ptr + state.game_offset + (32 * kXESectorSize); state.root_sector = poly::load(fs_ptr + 20); - state.root_size = poly::load(fs_ptr + 24); + state.root_size = poly::load(fs_ptr + 24); state.root_offset = state.game_offset + (state.root_sector * kXESectorSize); - if (state.root_size < 13 || - state.root_size > 32 * 1024 * 1024) { + if (state.root_size < 13 || state.root_size > 32 * 1024 * 1024) { return kErrorDamagedFile; } @@ -143,8 +132,8 @@ GDFX::Error GDFX::ReadAllEntries(ParseState& state, const uint8_t* root_buffer) { root_entry_ = new GDFXEntry(); root_entry_->offset = 0; - root_entry_->size = 0; - root_entry_->name = ""; + root_entry_->size = 0; + root_entry_->name = ""; root_entry_->attributes = X_FILE_ATTRIBUTE_DIRECTORY; if (!ReadEntry(state, root_buffer, 0, root_entry_)) { @@ -158,13 +147,13 @@ bool GDFX::ReadEntry(ParseState& state, const uint8_t* buffer, uint16_t entry_ordinal, GDFXEntry* parent) { const uint8_t* p = buffer + (entry_ordinal * 4); - uint16_t node_l = poly::load(p + 0); - uint16_t node_r = poly::load(p + 2); - size_t sector = poly::load(p + 4); - size_t length = poly::load(p + 8); - uint8_t attributes = poly::load(p + 12); - uint8_t name_length = poly::load(p + 13); - char* name = (char*)(p + 14); + uint16_t node_l = poly::load(p + 0); + uint16_t node_r = poly::load(p + 2); + size_t sector = poly::load(p + 4); + size_t length = poly::load(p + 8); + uint8_t attributes = poly::load(p + 12); + uint8_t name_length = poly::load(p + 13); + char* name = (char*)(p + 14); if (node_l && !ReadEntry(state, buffer, node_l, parent)) { return false; @@ -181,7 +170,7 @@ bool GDFX::ReadEntry(ParseState& state, const uint8_t* buffer, if (attributes & X_FILE_ATTRIBUTE_DIRECTORY) { // Folder. entry->offset = 0; - entry->size = 0; + entry->size = 0; if (length) { // Not a leaf - read in children. if (state.size < state.game_offset + (sector * kXESectorSize)) { @@ -198,7 +187,7 @@ bool GDFX::ReadEntry(ParseState& state, const uint8_t* buffer, } else { // File. entry->offset = state.game_offset + (sector * kXESectorSize); - entry->size = length; + entry->size = length; } // Read next file in the list. @@ -208,3 +197,7 @@ bool GDFX::ReadEntry(ParseState& state, const uint8_t* buffer, return true; } + +} // namespace fs +} // namespace kernel +} // namespace xe diff --git a/src/xenia/kernel/fs/gdfx.h b/src/xenia/kernel/fs/gdfx.h index b6727044f..28e6d159d 100644 --- a/src/xenia/kernel/fs/gdfx.h +++ b/src/xenia/kernel/fs/gdfx.h @@ -10,25 +10,20 @@ #ifndef XENIA_KERNEL_FS_GDFX_H_ #define XENIA_KERNEL_FS_GDFX_H_ -#include -#include - #include +#include #include #include - namespace xe { namespace kernel { namespace fs { - class GDFX; - class GDFXEntry { -public: + public: GDFXEntry(); ~GDFXEntry(); @@ -36,23 +31,22 @@ public: void Dump(int indent); - std::string name; + std::string name; X_FILE_ATTRIBUTES attributes; - size_t offset; - size_t size; + size_t offset; + size_t size; std::vector children; }; - class GDFX { -public: + public: enum Error { - kSuccess = 0, - kErrorOutOfMemory = -1, - kErrorReadError = -10, - kErrorFileMismatch = -30, - kErrorDamagedFile = -31, + kSuccess = 0, + kErrorOutOfMemory = -1, + kErrorReadError = -10, + kErrorFileMismatch = -30, + kErrorDamagedFile = -31, }; GDFX(xe_mmap_ref mmap); @@ -63,17 +57,22 @@ public: Error Load(); void Dump(); -private: + private: typedef struct { - uint8_t* ptr; + uint8_t* ptr; - size_t size; // Size (bytes) of total image + // Size (bytes) of total image. + size_t size; - size_t game_offset; // Offset (bytes) of game partition + // Offset (bytes) of game partition. + size_t game_offset; - size_t root_sector; // Offset (sector) of root - size_t root_offset; // Offset (bytes) of root - size_t root_size; // Size (bytes) of root + // Offset (sector) of root. + size_t root_sector; + // Offset (bytes) of root. + size_t root_offset; + // Size (bytes) of root. + size_t root_size; } ParseState; Error Verify(ParseState& state); @@ -84,13 +83,11 @@ private: xe_mmap_ref mmap_; - GDFXEntry* root_entry_; + GDFXEntry* root_entry_; }; - } // namespace fs } // namespace kernel } // namespace xe - #endif // XENIA_KERNEL_FS_GDFX_H_ diff --git a/src/xenia/kernel/fs/stfs.cc b/src/xenia/kernel/fs/stfs.cc index a72c6e57b..6faa76f1b 100644 --- a/src/xenia/kernel/fs/stfs.cc +++ b/src/xenia/kernel/fs/stfs.cc @@ -13,63 +13,62 @@ #include -using namespace xe; -using namespace xe::kernel; -using namespace xe::kernel::fs; +namespace xe { +namespace kernel { +namespace fs { -#define XEGETUINT24BE(p) \ - (((uint32_t)poly::load_and_swap((p) + 0) << 16) | \ - ((uint32_t)poly::load_and_swap((p) + 1) << 8) | \ - (uint32_t)poly::load_and_swap((p) + 2)) -#define XEGETUINT24LE(p) \ - (((uint32_t)poly::load((p) + 2) << 16) | \ - ((uint32_t)poly::load((p) + 1) << 8) | \ - (uint32_t)poly::load((p) + 0)) +#define XEGETUINT24BE(p) \ + (((uint32_t)poly::load_and_swap((p)+0) << 16) | \ + ((uint32_t)poly::load_and_swap((p)+1) << 8) | \ + (uint32_t)poly::load_and_swap((p)+2)) +#define XEGETUINT24LE(p) \ + (((uint32_t)poly::load((p)+2) << 16) | \ + ((uint32_t)poly::load((p)+1) << 8) | \ + (uint32_t)poly::load((p)+0)) bool STFSVolumeDescriptor::Read(const uint8_t* p) { - descriptor_size = poly::load_and_swap(p + 0x00); + descriptor_size = poly::load_and_swap(p + 0x00); if (descriptor_size != 0x24) { XELOGE("STFS volume descriptor size mismatch, expected 0x24 but got 0x%X", descriptor_size); return false; } - reserved = poly::load_and_swap(p + 0x01); - block_separation = poly::load_and_swap(p + 0x02); - file_table_block_count = poly::load_and_swap(p + 0x03); - file_table_block_number = XEGETUINT24BE(p + 0x05); + reserved = poly::load_and_swap(p + 0x01); + block_separation = poly::load_and_swap(p + 0x02); + file_table_block_count = poly::load_and_swap(p + 0x03); + file_table_block_number = XEGETUINT24BE(p + 0x05); xe_copy_struct(top_hash_table_hash, p + 0x08, 0x14); - total_allocated_block_count = poly::load_and_swap(p + 0x1C); + total_allocated_block_count = poly::load_and_swap(p + 0x1C); total_unallocated_block_count = poly::load_and_swap(p + 0x20); return true; }; - bool STFSHeader::Read(const uint8_t* p) { xe_copy_struct(license_entries, p + 0x22C, 0x100); xe_copy_struct(header_hash, p + 0x32C, 0x14); - header_size = poly::load_and_swap(p + 0x340); - content_type = (STFSContentType)poly::load_and_swap(p + 0x344); - metadata_version = poly::load_and_swap(p + 0x348); + header_size = poly::load_and_swap(p + 0x340); + content_type = (STFSContentType)poly::load_and_swap(p + 0x344); + metadata_version = poly::load_and_swap(p + 0x348); if (metadata_version > 1) { // This is a variant of thumbnail data/etc. // Can just ignore it for now (until we parse thumbnails). XELOGW("STFSContainer doesn't support version %d yet", metadata_version); } - content_size = poly::load_and_swap(p + 0x34C); - media_id = poly::load_and_swap(p + 0x354); - version = poly::load_and_swap(p + 0x358); - base_version = poly::load_and_swap(p + 0x35C); - title_id = poly::load_and_swap(p + 0x360); - platform = (STFSPlatform)poly::load_and_swap(p + 0x364); - executable_type = poly::load_and_swap(p + 0x365); - disc_number = poly::load_and_swap(p + 0x366); - disc_in_set = poly::load_and_swap(p + 0x367); - save_game_id = poly::load_and_swap(p + 0x368); + content_size = poly::load_and_swap(p + 0x34C); + media_id = poly::load_and_swap(p + 0x354); + version = poly::load_and_swap(p + 0x358); + base_version = poly::load_and_swap(p + 0x35C); + title_id = poly::load_and_swap(p + 0x360); + platform = (STFSPlatform)poly::load_and_swap(p + 0x364); + executable_type = poly::load_and_swap(p + 0x365); + disc_number = poly::load_and_swap(p + 0x366); + disc_in_set = poly::load_and_swap(p + 0x367); + save_game_id = poly::load_and_swap(p + 0x368); xe_copy_struct(console_id, p + 0x36C, 0x5); xe_copy_struct(profile_id, p + 0x371, 0x8); - data_file_count = poly::load_and_swap(p + 0x39D); - data_file_combined_size = poly::load_and_swap(p + 0x3A1); - descriptor_type = (STFSDescriptorType)poly::load_and_swap(p + 0x3A9); + data_file_count = poly::load_and_swap(p + 0x39D); + data_file_combined_size = poly::load_and_swap(p + 0x3A1); + descriptor_type = (STFSDescriptorType)poly::load_and_swap(p + 0x3A9); if (descriptor_type != STFS_DESCRIPTOR_STFS) { XELOGE("STFS descriptor format not supported: %d", descriptor_type); return false; @@ -86,76 +85,61 @@ bool STFSHeader::Read(const uint8_t* p) { publisher_name[n] = poly::load_and_swap(p + 0x1611 + n * 2); title_name[n] = poly::load_and_swap(p + 0x1691 + n * 2); } - transfer_flags = poly::load_and_swap(p + 0x1711); - thumbnail_image_size = poly::load_and_swap(p + 0x1712); - title_thumbnail_image_size = poly::load_and_swap(p + 0x1716); + transfer_flags = poly::load_and_swap(p + 0x1711); + thumbnail_image_size = poly::load_and_swap(p + 0x1712); + title_thumbnail_image_size = poly::load_and_swap(p + 0x1716); xe_copy_struct(thumbnail_image, p + 0x171A, 0x4000); xe_copy_struct(title_thumbnail_image, p + 0x571A, 0x4000); return true; } -STFSEntry::STFSEntry() : - attributes(X_FILE_ATTRIBUTE_NONE), offset(0), size(0), - update_timestamp(0), access_timestamp(0) { -} - -STFSEntry::~STFSEntry() { - for (auto it = children.begin(); it != children.end(); ++it) { - delete *it; - } -} +STFSEntry::STFSEntry() + : attributes(X_FILE_ATTRIBUTE_NONE), + offset(0), + size(0), + update_timestamp(0), + access_timestamp(0) {} STFSEntry* STFSEntry::GetChild(const char* name) { // TODO(benvanik): a faster search - for (auto it = children.begin(); it != children.end(); ++it) { - STFSEntry* entry = *it; + for (const auto& entry : children) { if (strcasecmp(entry->name.c_str(), name) == 0) { - return entry; + return entry.get(); } } - return NULL; + return nullptr; } void STFSEntry::Dump(int indent) { printf("%s%s\n", std::string(indent, ' ').c_str(), name.c_str()); - for (auto it = children.begin(); it != children.end(); ++it) { - STFSEntry* entry = *it; + for (const auto& entry : children) { entry->Dump(indent + 2); } } - STFS::STFS(xe_mmap_ref mmap) { mmap_ = xe_mmap_retain(mmap); - - root_entry_ = NULL; } STFS::~STFS() { - delete root_entry_; - xe_mmap_release(mmap_); } -STFSEntry* STFS::root_entry() { - return root_entry_; -} - STFS::Error STFS::Load() { - Error result = kErrorOutOfMemory; - uint8_t* map_ptr = (uint8_t*)xe_mmap_get_addr(mmap_); - size_t map_size = xe_mmap_get_length(mmap_); + size_t map_size = xe_mmap_get_length(mmap_); - result = ReadHeaderAndVerify(map_ptr); - XEEXPECTZERO(result); + auto result = ReadHeaderAndVerify(map_ptr); + if (result != kSuccess) { + return result; + } result = ReadAllEntries(map_ptr); - XEEXPECTZERO(result); + if (result != kSuccess) { + return result; + } - result = kSuccess; -XECLEANUP: - return result; + return kSuccess; } void STFS::Dump() { @@ -192,10 +176,7 @@ STFS::Error STFS::ReadHeaderAndVerify(const uint8_t* map_ptr) { } STFS::Error STFS::ReadAllEntries(const uint8_t* map_ptr) { - root_entry_ = new STFSEntry(); - root_entry_->offset = 0; - root_entry_->size = 0; - root_entry_->name = ""; + root_entry_.reset(new STFSEntry()); root_entry_->attributes = X_FILE_ATTRIBUTE_DIRECTORY; std::vector entries; @@ -207,21 +188,21 @@ STFS::Error STFS::ReadAllEntries(const uint8_t* map_ptr) { const uint8_t* p = map_ptr + BlockToOffset(ComputeBlockNumber(table_block_index)); for (size_t m = 0; m < 0x1000 / 0x40; m++) { - const uint8_t* filename = p; // 0x28b + const uint8_t* filename = p; // 0x28b if (filename[0] == 0) { // Done. break; } - uint8_t filename_length_flags = poly::load_and_swap(p + 0x28); - uint32_t allocated_block_count = XEGETUINT24LE(p + 0x29); - uint32_t start_block_index = XEGETUINT24LE(p + 0x2F); - uint16_t path_indicator = poly::load_and_swap(p + 0x32); - uint32_t file_size = poly::load_and_swap(p + 0x34); - uint32_t update_timestamp = poly::load_and_swap(p + 0x38); - uint32_t access_timestamp = poly::load_and_swap(p + 0x3C); + uint8_t filename_length_flags = poly::load_and_swap(p + 0x28); + uint32_t allocated_block_count = XEGETUINT24LE(p + 0x29); + uint32_t start_block_index = XEGETUINT24LE(p + 0x2F); + uint16_t path_indicator = poly::load_and_swap(p + 0x32); + uint32_t file_size = poly::load_and_swap(p + 0x34); + uint32_t update_timestamp = poly::load_and_swap(p + 0x38); + uint32_t access_timestamp = poly::load_and_swap(p + 0x3C); p += 0x40; - STFSEntry* entry = new STFSEntry(); + auto entry = std::make_unique(); entry->name = std::string((char*)filename, filename_length_flags & 0x3F); entry->name.append(1, '\0'); // bit 0x40 = consecutive blocks (not fragmented?) @@ -229,23 +210,12 @@ STFS::Error STFS::ReadAllEntries(const uint8_t* map_ptr) { entry->attributes = X_FILE_ATTRIBUTE_DIRECTORY; } else { entry->attributes = X_FILE_ATTRIBUTE_NORMAL; - entry->offset = BlockToOffset(ComputeBlockNumber(start_block_index)); - entry->size = file_size; + entry->offset = BlockToOffset(ComputeBlockNumber(start_block_index)); + entry->size = file_size; } entry->update_timestamp = update_timestamp; entry->access_timestamp = access_timestamp; - entries.push_back(entry); - - const uint8_t* p = map_ptr + entry->offset; - - if (path_indicator == 0xFFFF) { - // Root entry. - root_entry_->children.push_back(entry); - } else { - // Lookup and add. - auto parent = entries[path_indicator]; - parent->children.push_back(entry); - } + entries.push_back(entry.get()); // Fill in all block records. // It's easier to do this now and just look them up later, at the cost @@ -255,12 +225,10 @@ STFS::Error STFS::ReadAllEntries(const uint8_t* map_ptr) { uint32_t block_index = start_block_index; size_t remaining_size = file_size; uint32_t info = 0x80; - while (remaining_size && - block_index && - info >= 0x80) { + while (remaining_size && block_index && info >= 0x80) { size_t block_size = std::min(0x1000ull, remaining_size); size_t offset = BlockToOffset(ComputeBlockNumber(block_index)); - entry->block_list.push_back({ offset, block_size }); + entry->block_list.push_back({offset, block_size}); remaining_size -= block_size; auto block_hash = GetBlockHash(map_ptr, block_index, 0); if (table_size_shift_ && block_hash.info < 0x80) { @@ -270,6 +238,15 @@ STFS::Error STFS::ReadAllEntries(const uint8_t* map_ptr) { info = block_hash.info; } } + + if (path_indicator == 0xFFFF) { + // Root entry. + root_entry_->children.push_back(std::move(entry)); + } else { + // Lookup and add. + auto parent = entries[path_indicator]; + parent->children.push_back(std::move(entry)); + } } auto block_hash = GetBlockHash(map_ptr, table_block_index, 0); @@ -327,12 +304,14 @@ uint32_t STFS::ComputeBlockNumber(uint32_t block_index) { return block; } -STFS::BlockHash_t STFS::GetBlockHash( - const uint8_t* map_ptr, - uint32_t block_index, uint32_t table_offset) { +STFS::BlockHash_t STFS::GetBlockHash(const uint8_t* map_ptr, + uint32_t block_index, + uint32_t table_offset) { static const uint32_t table_spacing[] = { - 0xAB, 0x718F, 0xFE7DA, // The distance in blocks between tables - 0xAC, 0x723A, 0xFD00B, // For when tables are 1 block and when they are 2 blocks + 0xAB, 0x718F, + 0xFE7DA, // The distance in blocks between tables + 0xAC, 0x723A, + 0xFD00B, // For when tables are 1 block and when they are 2 blocks }; uint32_t record = block_index % 0xAA; uint32_t table_index = @@ -343,10 +322,14 @@ STFS::BlockHash_t STFS::GetBlockHash( table_index += 1 << table_size_shift_; } } - //table_index += table_offset - (1 << table_size_shift_); + // table_index += table_offset - (1 << table_size_shift_); const uint8_t* hash_data = map_ptr + BlockToOffset(table_index); const uint8_t* record_data = hash_data + record * 0x18; uint32_t info = poly::load_and_swap(record_data + 0x14); uint32_t next_block_index = XEGETUINT24BE(record_data + 0x15); - return{ next_block_index, info }; + return {next_block_index, info}; } + +} // namespace fs +} // namespace kernel +} // namespace xe diff --git a/src/xenia/kernel/fs/stfs.h b/src/xenia/kernel/fs/stfs.h index 2355b4c12..da3e82627 100644 --- a/src/xenia/kernel/fs/stfs.h +++ b/src/xenia/kernel/fs/stfs.h @@ -10,23 +10,19 @@ #ifndef XENIA_KERNEL_FS_STFS_H_ #define XENIA_KERNEL_FS_STFS_H_ -#include -#include - +#include #include +#include #include #include - namespace xe { namespace kernel { namespace fs { - class STFS; - // http://www.free60.org/STFS enum STFSPackageType { @@ -36,120 +32,116 @@ enum STFSPackageType { }; enum STFSContentType : uint32_t { - STFS_CONTENT_ARCADE_TITLE = 0x000D0000, - STFS_CONTENT_AVATAR_ITEM = 0x00009000, - STFS_CONTENT_CACHE_FILE = 0x00040000, - STFS_CONTENT_COMMUNITY_GAME = 0x02000000, - STFS_CONTENT_GAME_DEMO = 0x00080000, - STFS_CONTENT_GAMER_PICTURE = 0x00020000, - STFS_CONTENT_GAME_TITLE = 0x000A0000, - STFS_CONTENT_GAME_TRAILER = 0x000C0000, - STFS_CONTENT_GAME_VIDEO = 0x00400000, - STFS_CONTENT_INSTALLED_GAME = 0x00004000, - STFS_CONTENT_INSTALLER = 0x000B0000, - STFS_CONTENT_IPTV_PAUSE_BUFFER = 0x00002000, - STFS_CONTENT_LICENSE_STORE = 0x000F0000, - STFS_CONTENT_MARKETPLACE_CONTENT = 0x00000002, - STFS_CONTENT_MOVIE = 0x00100000, - STFS_CONTENT_MUSIC_VIDEO = 0x00300000, - STFS_CONTENT_PODCAST_VIDEO = 0x00500000, - STFS_CONTENT_PROFILE = 0x00010000, - STFS_CONTENT_PUBLISHER = 0x00000003, - STFS_CONTENT_SAVED_GAME = 0x00000001, - STFS_CONTENT_STORAGE_DOWNLOAD = 0x00050000, - STFS_CONTENT_THEME = 0x00030000, - STFS_CONTENT_TV = 0x00200000, - STFS_CONTENT_VIDEO = 0x00090000, - STFS_CONTENT_VIRAL_VIDEO = 0x00600000, - STFS_CONTENT_XBOX_DOWNLOAD = 0x00070000, - STFS_CONTENT_XBOX_ORIGINAL_GAME = 0x00005000, - STFS_CONTENT_XBOX_SAVED_GAME = 0x00060000, - STFS_CONTENT_XBOX_360_TITLE = 0x00001000, - STFS_CONTENT_XBOX_TITLE = 0x00005000, - STFS_CONTENT_XNA = 0x000E0000, + STFS_CONTENT_ARCADE_TITLE = 0x000D0000, + STFS_CONTENT_AVATAR_ITEM = 0x00009000, + STFS_CONTENT_CACHE_FILE = 0x00040000, + STFS_CONTENT_COMMUNITY_GAME = 0x02000000, + STFS_CONTENT_GAME_DEMO = 0x00080000, + STFS_CONTENT_GAMER_PICTURE = 0x00020000, + STFS_CONTENT_GAME_TITLE = 0x000A0000, + STFS_CONTENT_GAME_TRAILER = 0x000C0000, + STFS_CONTENT_GAME_VIDEO = 0x00400000, + STFS_CONTENT_INSTALLED_GAME = 0x00004000, + STFS_CONTENT_INSTALLER = 0x000B0000, + STFS_CONTENT_IPTV_PAUSE_BUFFER = 0x00002000, + STFS_CONTENT_LICENSE_STORE = 0x000F0000, + STFS_CONTENT_MARKETPLACE_CONTENT = 0x00000002, + STFS_CONTENT_MOVIE = 0x00100000, + STFS_CONTENT_MUSIC_VIDEO = 0x00300000, + STFS_CONTENT_PODCAST_VIDEO = 0x00500000, + STFS_CONTENT_PROFILE = 0x00010000, + STFS_CONTENT_PUBLISHER = 0x00000003, + STFS_CONTENT_SAVED_GAME = 0x00000001, + STFS_CONTENT_STORAGE_DOWNLOAD = 0x00050000, + STFS_CONTENT_THEME = 0x00030000, + STFS_CONTENT_TV = 0x00200000, + STFS_CONTENT_VIDEO = 0x00090000, + STFS_CONTENT_VIRAL_VIDEO = 0x00600000, + STFS_CONTENT_XBOX_DOWNLOAD = 0x00070000, + STFS_CONTENT_XBOX_ORIGINAL_GAME = 0x00005000, + STFS_CONTENT_XBOX_SAVED_GAME = 0x00060000, + STFS_CONTENT_XBOX_360_TITLE = 0x00001000, + STFS_CONTENT_XBOX_TITLE = 0x00005000, + STFS_CONTENT_XNA = 0x000E0000, }; enum STFSPlatform : uint8_t { - STFS_PLATFORM_XBOX_360 = 0x02, - STFS_PLATFORM_PC = 0x04, + STFS_PLATFORM_XBOX_360 = 0x02, + STFS_PLATFORM_PC = 0x04, }; enum STFSDescriptorType : uint32_t { - STFS_DESCRIPTOR_STFS = 0, - STFS_DESCRIPTOR_SVOD = 1, + STFS_DESCRIPTOR_STFS = 0, + STFS_DESCRIPTOR_SVOD = 1, }; - class STFSVolumeDescriptor { -public: + public: bool Read(const uint8_t* p); - uint8_t descriptor_size; - uint8_t reserved; - uint8_t block_separation; - uint16_t file_table_block_count; - uint32_t file_table_block_number; - uint8_t top_hash_table_hash[0x14]; - uint32_t total_allocated_block_count; - uint32_t total_unallocated_block_count; + uint8_t descriptor_size; + uint8_t reserved; + uint8_t block_separation; + uint16_t file_table_block_count; + uint32_t file_table_block_number; + uint8_t top_hash_table_hash[0x14]; + uint32_t total_allocated_block_count; + uint32_t total_unallocated_block_count; }; - class STFSHeader { -public: + public: bool Read(const uint8_t* p); - uint8_t license_entries[0x100]; - uint8_t header_hash[0x14]; - uint32_t header_size; + uint8_t license_entries[0x100]; + uint8_t header_hash[0x14]; + uint32_t header_size; STFSContentType content_type; - uint32_t metadata_version; - uint64_t content_size; - uint32_t media_id; - uint32_t version; - uint32_t base_version; - uint32_t title_id; - STFSPlatform platform; - uint8_t executable_type; - uint8_t disc_number; - uint8_t disc_in_set; - uint32_t save_game_id; - uint8_t console_id[0x5]; - uint8_t profile_id[0x8]; + uint32_t metadata_version; + uint64_t content_size; + uint32_t media_id; + uint32_t version; + uint32_t base_version; + uint32_t title_id; + STFSPlatform platform; + uint8_t executable_type; + uint8_t disc_number; + uint8_t disc_in_set; + uint32_t save_game_id; + uint8_t console_id[0x5]; + uint8_t profile_id[0x8]; STFSVolumeDescriptor volume_descriptor; - uint32_t data_file_count; - uint64_t data_file_combined_size; + uint32_t data_file_count; + uint64_t data_file_combined_size; STFSDescriptorType descriptor_type; - uint8_t device_id[0x14]; - wchar_t display_names[0x900 / 2]; - wchar_t display_descs[0x900 / 2]; - wchar_t publisher_name[0x80 / 2]; - wchar_t title_name[0x80 / 2]; - uint8_t transfer_flags; - uint32_t thumbnail_image_size; - uint32_t title_thumbnail_image_size; - uint8_t thumbnail_image[0x4000]; - uint8_t title_thumbnail_image[0x4000]; + uint8_t device_id[0x14]; + wchar_t display_names[0x900 / 2]; + wchar_t display_descs[0x900 / 2]; + wchar_t publisher_name[0x80 / 2]; + wchar_t title_name[0x80 / 2]; + uint8_t transfer_flags; + uint32_t thumbnail_image_size; + uint32_t title_thumbnail_image_size; + uint8_t thumbnail_image[0x4000]; + uint8_t title_thumbnail_image[0x4000]; }; - class STFSEntry { -public: + public: STFSEntry(); - ~STFSEntry(); STFSEntry* GetChild(const char* name); void Dump(int indent); - std::string name; + std::string name; X_FILE_ATTRIBUTES attributes; - size_t offset; - size_t size; - uint32_t update_timestamp; - uint32_t access_timestamp; + size_t offset; + size_t size; + uint32_t update_timestamp; + uint32_t access_timestamp; - std::vector children; + std::vector> children; typedef struct { size_t offset; @@ -158,27 +150,26 @@ public: std::vector block_list; }; - class STFS { -public: + public: enum Error { - kSuccess = 0, - kErrorOutOfMemory = -1, - kErrorReadError = -10, - kErrorFileMismatch = -30, - kErrorDamagedFile = -31, + kSuccess = 0, + kErrorOutOfMemory = -1, + kErrorReadError = -10, + kErrorFileMismatch = -30, + kErrorDamagedFile = -31, }; STFS(xe_mmap_ref mmap); virtual ~STFS(); const STFSHeader* header() const { return &header_; } - STFSEntry* root_entry(); + STFSEntry* root_entry() const { return root_entry_.get(); } Error Load(); void Dump(); -private: + private: Error ReadHeaderAndVerify(const uint8_t* map_ptr); Error ReadAllEntries(const uint8_t* map_ptr); size_t BlockToOffset(uint32_t block); @@ -188,21 +179,19 @@ private: uint32_t next_block_index; uint32_t info; } BlockHash_t; - BlockHash_t GetBlockHash(const uint8_t* map_ptr, - uint32_t block_index, uint32_t table_offset); + BlockHash_t GetBlockHash(const uint8_t* map_ptr, uint32_t block_index, + uint32_t table_offset); xe_mmap_ref mmap_; STFSPackageType package_type_; - STFSHeader header_; - uint32_t table_size_shift_; - STFSEntry* root_entry_; + STFSHeader header_; + uint32_t table_size_shift_; + std::unique_ptr root_entry_; }; - } // namespace fs } // namespace kernel } // namespace xe - #endif // XENIA_KERNEL_FS_STFS_H_