STFS->Stfs.

Fixes #309.
This commit is contained in:
Ben Vanik 2015-06-29 10:38:51 -07:00
parent cc08e9019a
commit c9f4d00da3
7 changed files with 83 additions and 83 deletions

View File

@ -256,7 +256,7 @@ X_STATUS Emulator::LaunchStfsContainer(std::wstring path) {
auto mount_path = "\\Device\\Cdrom0"; auto mount_path = "\\Device\\Cdrom0";
// Register the container in the virtual filesystem. // Register the container in the virtual filesystem.
auto device = std::make_unique<vfs::STFSContainerDevice>(mount_path, path); auto device = std::make_unique<vfs::StfsContainerDevice>(mount_path, path);
if (!device->Initialize()) { if (!device->Initialize()) {
XELOGE("Unable to mount STFS container"); XELOGE("Unable to mount STFS container");
return X_STATUS_NO_SUCH_FILE; return X_STATUS_NO_SUCH_FILE;

View File

@ -25,13 +25,13 @@ namespace vfs {
((uint32_t)xe::load<uint8_t>((p) + 1) << 8) | \ ((uint32_t)xe::load<uint8_t>((p) + 1) << 8) | \
(uint32_t)xe::load<uint8_t>((p) + 0)) (uint32_t)xe::load<uint8_t>((p) + 0))
STFSContainerDevice::STFSContainerDevice(const std::string& mount_path, StfsContainerDevice::StfsContainerDevice(const std::string& mount_path,
const std::wstring& local_path) const std::wstring& local_path)
: Device(mount_path), local_path_(local_path) {} : Device(mount_path), local_path_(local_path) {}
STFSContainerDevice::~STFSContainerDevice() = default; StfsContainerDevice::~StfsContainerDevice() = default;
bool STFSContainerDevice::Initialize() { bool StfsContainerDevice::Initialize() {
if (filesystem::IsFolder(local_path_)) { if (filesystem::IsFolder(local_path_)) {
// Was given a folder. Try to find the file in // Was given a folder. Try to find the file in
// local_path\TITLE_ID\000D0000\HASH_OF_42_CHARS // local_path\TITLE_ID\000D0000\HASH_OF_42_CHARS
@ -99,15 +99,15 @@ bool STFSContainerDevice::Initialize() {
return true; return true;
} }
STFSContainerDevice::Error STFSContainerDevice::ReadHeaderAndVerify( StfsContainerDevice::Error StfsContainerDevice::ReadHeaderAndVerify(
const uint8_t* map_ptr) { const uint8_t* map_ptr) {
// Check signature. // Check signature.
if (memcmp(map_ptr, "LIVE", 4) == 0) { if (memcmp(map_ptr, "LIVE", 4) == 0) {
package_type_ = StfsPackageType::STFS_PACKAGE_LIVE; package_type_ = StfsPackageType::kLive;
} else if (memcmp(map_ptr, "PIRS", 4) == 0) { } else if (memcmp(map_ptr, "PIRS", 4) == 0) {
package_type_ = StfsPackageType::STFS_PACKAGE_PIRS; package_type_ = StfsPackageType::kPirs;
} else if (memcmp(map_ptr, "CON", 3) == 0) { } else if (memcmp(map_ptr, "CON", 3) == 0) {
package_type_ = StfsPackageType::STFS_PACKAGE_CON; package_type_ = StfsPackageType::kCon;
} else { } else {
// Unexpected format. // Unexpected format.
return Error::kErrorFileMismatch; return Error::kErrorFileMismatch;
@ -127,14 +127,14 @@ STFSContainerDevice::Error STFSContainerDevice::ReadHeaderAndVerify(
return Error::kSuccess; return Error::kSuccess;
} }
STFSContainerDevice::Error STFSContainerDevice::ReadAllEntries( StfsContainerDevice::Error StfsContainerDevice::ReadAllEntries(
const uint8_t* map_ptr) { const uint8_t* map_ptr) {
auto root_entry = new STFSContainerEntry(this, nullptr, "", mmap_.get()); auto root_entry = new StfsContainerEntry(this, nullptr, "", mmap_.get());
root_entry->attributes_ = kFileAttributeDirectory; root_entry->attributes_ = kFileAttributeDirectory;
root_entry_ = std::unique_ptr<Entry>(root_entry); root_entry_ = std::unique_ptr<Entry>(root_entry);
std::vector<STFSContainerEntry*> all_entries; std::vector<StfsContainerEntry*> all_entries;
// Load all listings. // Load all listings.
auto& volume_descriptor = header_.volume_descriptor; auto& volume_descriptor = header_.volume_descriptor;
@ -157,14 +157,14 @@ STFSContainerDevice::Error STFSContainerDevice::ReadAllEntries(
uint32_t access_timestamp = xe::load_and_swap<uint32_t>(p + 0x3C); uint32_t access_timestamp = xe::load_and_swap<uint32_t>(p + 0x3C);
p += 0x40; p += 0x40;
STFSContainerEntry* parent_entry = nullptr; StfsContainerEntry* parent_entry = nullptr;
if (path_indicator == 0xFFFF) { if (path_indicator == 0xFFFF) {
parent_entry = root_entry; parent_entry = root_entry;
} else { } else {
parent_entry = all_entries[path_indicator]; parent_entry = all_entries[path_indicator];
} }
auto entry = new STFSContainerEntry( auto entry = new StfsContainerEntry(
this, parent_entry, this, parent_entry,
std::string((char*)filename, filename_length_flags & 0x3F), std::string((char*)filename, filename_length_flags & 0x3F),
mmap_.get()); mmap_.get());
@ -222,7 +222,7 @@ STFSContainerDevice::Error STFSContainerDevice::ReadAllEntries(
return Error::kSuccess; return Error::kSuccess;
} }
size_t STFSContainerDevice::BlockToOffset(uint32_t block) { size_t StfsContainerDevice::BlockToOffset(uint32_t block) {
if (block >= 0xFFFFFF) { if (block >= 0xFFFFFF) {
return -1; return -1;
} else { } else {
@ -230,7 +230,7 @@ size_t STFSContainerDevice::BlockToOffset(uint32_t block) {
} }
} }
uint32_t STFSContainerDevice::ComputeBlockNumber(uint32_t block_index) { uint32_t StfsContainerDevice::ComputeBlockNumber(uint32_t block_index) {
uint32_t block_shift = 0; uint32_t block_shift = 0;
if (((header_.header_size + 0x0FFF) & 0xB000) == 0xB000) { if (((header_.header_size + 0x0FFF) & 0xB000) == 0xB000) {
block_shift = 1; block_shift = 1;
@ -243,19 +243,19 @@ uint32_t STFSContainerDevice::ComputeBlockNumber(uint32_t block_index) {
} }
uint32_t base = (block_index + 0xAA) / 0xAA; uint32_t base = (block_index + 0xAA) / 0xAA;
if (package_type_ == StfsPackageType::STFS_PACKAGE_CON) { if (package_type_ == StfsPackageType::kCon) {
base <<= block_shift; base <<= block_shift;
} }
uint32_t block = base + block_index; uint32_t block = base + block_index;
if (block_index >= 0xAA) { if (block_index >= 0xAA) {
base = (block_index + 0x70E4) / 0x70E4; base = (block_index + 0x70E4) / 0x70E4;
if (package_type_ == StfsPackageType::STFS_PACKAGE_CON) { if (package_type_ == StfsPackageType::kCon) {
base <<= block_shift; base <<= block_shift;
} }
block += base; block += base;
if (block_index >= 0x70E4) { if (block_index >= 0x70E4) {
base = (block_index + 0x4AF768) / 0x4AF768; base = (block_index + 0x4AF768) / 0x4AF768;
if (package_type_ == StfsPackageType::STFS_PACKAGE_CON) { if (package_type_ == StfsPackageType::kCon) {
base <<= block_shift; base <<= block_shift;
} }
block += base; block += base;
@ -264,7 +264,7 @@ uint32_t STFSContainerDevice::ComputeBlockNumber(uint32_t block_index) {
return block; return block;
} }
STFSContainerDevice::BlockHash STFSContainerDevice::GetBlockHash( StfsContainerDevice::BlockHash StfsContainerDevice::GetBlockHash(
const uint8_t* map_ptr, uint32_t block_index, uint32_t table_offset) { const uint8_t* map_ptr, uint32_t block_index, uint32_t table_offset) {
static const uint32_t table_spacing[] = { static const uint32_t table_spacing[] = {
0xAB, 0x718F, 0xAB, 0x718F,
@ -310,7 +310,7 @@ bool StfsHeader::Read(const uint8_t* p) {
std::memcpy(license_entries, p + 0x22C, 0x100); std::memcpy(license_entries, p + 0x22C, 0x100);
std::memcpy(header_hash, p + 0x32C, 0x14); std::memcpy(header_hash, p + 0x32C, 0x14);
header_size = xe::load_and_swap<uint32_t>(p + 0x340); header_size = xe::load_and_swap<uint32_t>(p + 0x340);
content_type = (STFSContentType)xe::load_and_swap<uint32_t>(p + 0x344); content_type = (StfsContentType)xe::load_and_swap<uint32_t>(p + 0x344);
metadata_version = xe::load_and_swap<uint32_t>(p + 0x348); metadata_version = xe::load_and_swap<uint32_t>(p + 0x348);
if (metadata_version > 1) { if (metadata_version > 1) {
// This is a variant of thumbnail data/etc. // This is a variant of thumbnail data/etc.
@ -332,7 +332,7 @@ bool StfsHeader::Read(const uint8_t* p) {
data_file_count = xe::load_and_swap<uint32_t>(p + 0x39D); data_file_count = xe::load_and_swap<uint32_t>(p + 0x39D);
data_file_combined_size = xe::load_and_swap<uint64_t>(p + 0x3A1); data_file_combined_size = xe::load_and_swap<uint64_t>(p + 0x3A1);
descriptor_type = (StfsDescriptorType)xe::load_and_swap<uint8_t>(p + 0x3A9); descriptor_type = (StfsDescriptorType)xe::load_and_swap<uint8_t>(p + 0x3A9);
if (descriptor_type != StfsDescriptorType::STFS_DESCRIPTOR_STFS) { if (descriptor_type != StfsDescriptorType::kStfs) {
XELOGE("STFS descriptor format not supported: %d", descriptor_type); XELOGE("STFS descriptor format not supported: %d", descriptor_type);
return false; return false;
} }

View File

@ -22,53 +22,53 @@ namespace vfs {
// http://www.free60.org/STFS // http://www.free60.org/STFS
enum class StfsPackageType { enum class StfsPackageType {
STFS_PACKAGE_CON, kCon,
STFS_PACKAGE_PIRS, kPirs,
STFS_PACKAGE_LIVE, kLive,
}; };
enum STFSContentType : uint32_t { enum class StfsContentType : uint32_t {
STFS_CONTENT_ARCADE_TITLE = 0x000D0000, kArcadeTitle = 0x000D0000,
STFS_CONTENT_AVATAR_ITEM = 0x00009000, kAvatarItem = 0x00009000,
STFS_CONTENT_CACHE_FILE = 0x00040000, kCacheFile = 0x00040000,
STFS_CONTENT_COMMUNITY_GAME = 0x02000000, kCommunityGame = 0x02000000,
STFS_CONTENT_GAME_DEMO = 0x00080000, kGameDemo = 0x00080000,
STFS_CONTENT_GAMER_PICTURE = 0x00020000, kGamerPictuer = 0x00020000,
STFS_CONTENT_GAME_TITLE = 0x000A0000, kGameTitle = 0x000A0000,
STFS_CONTENT_GAME_TRAILER = 0x000C0000, kGameTrailer = 0x000C0000,
STFS_CONTENT_GAME_VIDEO = 0x00400000, kGameVideo = 0x00400000,
STFS_CONTENT_INSTALLED_GAME = 0x00004000, kInstalledGame = 0x00004000,
STFS_CONTENT_INSTALLER = 0x000B0000, kInstaller = 0x000B0000,
STFS_CONTENT_IPTV_PAUSE_BUFFER = 0x00002000, kIptvPauseBuffer = 0x00002000,
STFS_CONTENT_LICENSE_STORE = 0x000F0000, kLicenseStore = 0x000F0000,
STFS_CONTENT_MARKETPLACE_CONTENT = 0x00000002, kMarketplaceContent = 0x00000002,
STFS_CONTENT_MOVIE = 0x00100000, kMovie = 0x00100000,
STFS_CONTENT_MUSIC_VIDEO = 0x00300000, kMusicVideo = 0x00300000,
STFS_CONTENT_PODCAST_VIDEO = 0x00500000, kPodcastVideo = 0x00500000,
STFS_CONTENT_PROFILE = 0x00010000, kProfile = 0x00010000,
STFS_CONTENT_PUBLISHER = 0x00000003, kPublisher = 0x00000003,
STFS_CONTENT_SAVED_GAME = 0x00000001, kSavedGame = 0x00000001,
STFS_CONTENT_STORAGE_DOWNLOAD = 0x00050000, kStorageDownload = 0x00050000,
STFS_CONTENT_THEME = 0x00030000, kTheme = 0x00030000,
STFS_CONTENT_TV = 0x00200000, kTV = 0x00200000,
STFS_CONTENT_VIDEO = 0x00090000, kVideo = 0x00090000,
STFS_CONTENT_VIRAL_VIDEO = 0x00600000, kViralVideo = 0x00600000,
STFS_CONTENT_XBOX_DOWNLOAD = 0x00070000, kXboxDownload = 0x00070000,
STFS_CONTENT_XBOX_ORIGINAL_GAME = 0x00005000, kXboxOriginalGame = 0x00005000,
STFS_CONTENT_XBOX_SAVED_GAME = 0x00060000, kXboxSavedGame = 0x00060000,
STFS_CONTENT_XBOX_360_TITLE = 0x00001000, kXbox360Title = 0x00001000,
STFS_CONTENT_XBOX_TITLE = 0x00005000, kXboxTitle = 0x00005000,
STFS_CONTENT_XNA = 0x000E0000, kXNA = 0x000E0000,
}; };
enum class StfsPlatform : uint8_t { enum class StfsPlatform : uint8_t {
STFS_PLATFORM_XBOX_360 = 0x02, kXbox360 = 0x02,
STFS_PLATFORM_PC = 0x04, kPc = 0x04,
}; };
enum class StfsDescriptorType : uint32_t { enum class StfsDescriptorType : uint32_t {
STFS_DESCRIPTOR_STFS = 0, kStfs = 0,
STFS_DESCRIPTOR_SVOD = 1, kSvod = 1,
}; };
struct StfsVolumeDescriptor { struct StfsVolumeDescriptor {
@ -91,7 +91,7 @@ class StfsHeader {
uint8_t license_entries[0x100]; uint8_t license_entries[0x100];
uint8_t header_hash[0x14]; uint8_t header_hash[0x14];
uint32_t header_size; uint32_t header_size;
STFSContentType content_type; StfsContentType content_type;
uint32_t metadata_version; uint32_t metadata_version;
uint64_t content_size; uint64_t content_size;
uint32_t media_id; uint32_t media_id;
@ -121,11 +121,11 @@ class StfsHeader {
uint8_t title_thumbnail_image[0x4000]; uint8_t title_thumbnail_image[0x4000];
}; };
class STFSContainerDevice : public Device { class StfsContainerDevice : public Device {
public: public:
STFSContainerDevice(const std::string& mount_path, StfsContainerDevice(const std::string& mount_path,
const std::wstring& local_path); const std::wstring& local_path);
~STFSContainerDevice() override; ~StfsContainerDevice() override;
bool Initialize() override; bool Initialize() override;

View File

@ -15,20 +15,20 @@
namespace xe { namespace xe {
namespace vfs { namespace vfs {
STFSContainerEntry::STFSContainerEntry(Device* device, Entry* parent, StfsContainerEntry::StfsContainerEntry(Device* device, Entry* parent,
std::string path, MappedMemory* mmap) std::string path, MappedMemory* mmap)
: Entry(device, parent, path), : Entry(device, parent, path),
mmap_(mmap), mmap_(mmap),
data_offset_(0), data_offset_(0),
data_size_(0) {} data_size_(0) {}
STFSContainerEntry::~STFSContainerEntry() = default; StfsContainerEntry::~StfsContainerEntry() = default;
X_STATUS STFSContainerEntry::Open(KernelState* kernel_state, X_STATUS StfsContainerEntry::Open(KernelState* kernel_state,
uint32_t desired_access, uint32_t desired_access,
object_ref<XFile>* out_file) { object_ref<XFile>* out_file) {
*out_file = object_ref<XFile>( *out_file = object_ref<XFile>(
new STFSContainerFile(kernel_state, desired_access, this)); new StfsContainerFile(kernel_state, desired_access, this));
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
} }

View File

@ -19,13 +19,13 @@
namespace xe { namespace xe {
namespace vfs { namespace vfs {
class STFSContainerDevice; class StfsContainerDevice;
class STFSContainerEntry : public Entry { class StfsContainerEntry : public Entry {
public: public:
STFSContainerEntry(Device* device, Entry* parent, std::string path, StfsContainerEntry(Device* device, Entry* parent, std::string path,
MappedMemory* mmap); MappedMemory* mmap);
~STFSContainerEntry() override; ~StfsContainerEntry() override;
MappedMemory* mmap() const { return mmap_; } MappedMemory* mmap() const { return mmap_; }
size_t data_offset() const { return data_offset_; } size_t data_offset() const { return data_offset_; }
@ -41,7 +41,7 @@ class STFSContainerEntry : public Entry {
const std::vector<BlockRecord>& block_list() const { return block_list_; } const std::vector<BlockRecord>& block_list() const { return block_list_; }
private: private:
friend class STFSContainerDevice; friend class StfsContainerDevice;
MappedMemory* mmap_; MappedMemory* mmap_;
size_t data_offset_; size_t data_offset_;

View File

@ -16,14 +16,14 @@
namespace xe { namespace xe {
namespace vfs { namespace vfs {
STFSContainerFile::STFSContainerFile(KernelState* kernel_state, StfsContainerFile::StfsContainerFile(KernelState* kernel_state,
uint32_t file_access, uint32_t file_access,
STFSContainerEntry* entry) StfsContainerEntry* entry)
: XFile(kernel_state, file_access, entry), entry_(entry) {} : XFile(kernel_state, file_access, entry), entry_(entry) {}
STFSContainerFile::~STFSContainerFile() = default; StfsContainerFile::~StfsContainerFile() = default;
X_STATUS STFSContainerFile::ReadSync(void* buffer, size_t buffer_length, X_STATUS StfsContainerFile::ReadSync(void* buffer, size_t buffer_length,
size_t byte_offset, size_t byte_offset,
size_t* out_bytes_read) { size_t* out_bytes_read) {
if (byte_offset >= entry_->size()) { if (byte_offset >= entry_->size()) {

View File

@ -15,20 +15,20 @@
namespace xe { namespace xe {
namespace vfs { namespace vfs {
class STFSContainerEntry; class StfsContainerEntry;
class STFSContainerFile : public XFile { class StfsContainerFile : public XFile {
public: public:
STFSContainerFile(KernelState* kernel_state, uint32_t file_access, StfsContainerFile(KernelState* kernel_state, uint32_t file_access,
STFSContainerEntry* entry); StfsContainerEntry* entry);
~STFSContainerFile() override; ~StfsContainerFile() override;
protected: protected:
X_STATUS ReadSync(void* buffer, size_t buffer_length, size_t byte_offset, X_STATUS ReadSync(void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_read) override; size_t* out_bytes_read) override;
private: private:
STFSContainerEntry* entry_; StfsContainerEntry* entry_;
}; };
} // namespace vfs } // namespace vfs