/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2023 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #ifndef XENIA_VFS_DEVICES_XCONTENT_CONTAINER_DEVICE_H_ #define XENIA_VFS_DEVICES_XCONTENT_CONTAINER_DEVICE_H_ #include #include #include #include "xenia/base/math.h" #include "xenia/kernel/util/xex2_info.h" #include "xenia/kernel/xam/content_manager.h" #include "xenia/vfs/device.h" #include "xenia/vfs/devices/stfs_xbox.h" namespace xe { namespace vfs { constexpr fourcc_t kLIVESignature = make_fourcc("LIVE"); constexpr fourcc_t kCONSignature = make_fourcc("CON "); constexpr fourcc_t kPIRSSignature = make_fourcc("PIRS"); class XContentContainerDevice : public Device { public: const static uint32_t kBlockSize = 0x1000; static std::unique_ptr CreateContentDevice( const std::string_view mount_path, const std::filesystem::path& host_path); ~XContentContainerDevice() override; bool Initialize(); const std::string& name() const override { return name_; } uint32_t attributes() const override { return 0; } uint32_t sectors_per_allocation_unit() const override { return 8; } uint32_t bytes_per_sector() const override { return 0x200; } size_t data_size() const { if (header_->content_header.header_size) { return files_total_size_ - xe::round_up(header_->content_header.header_size, kBlockSize); } return files_total_size_ - sizeof(XContentContainerHeader); } uint32_t title_id() const { return header_->content_metadata.execution_info.title_id; } uint32_t content_type() const { return (uint32_t)header_->content_metadata.content_type.get(); } kernel::xam::XCONTENT_AGGREGATE_DATA content_header() const; protected: XContentContainerDevice(const std::string_view mount_path, const std::filesystem::path& host_path); enum class Result { kSuccess = 0, kOutOfMemory = -1, kReadError = -10, kFileMismatch = -30, kDamagedFile = -31, kTooSmall = -32, }; virtual Result Read() = 0; // Load all host files. Usually STFS is only 1 file, meanwhile SVOD is usually // multiple file. virtual Result LoadHostFiles(FILE* header_file) = 0; // Initialize any container specific fields. virtual void SetupContainer(){}; Entry* ResolvePath(const std::string_view path); void CloseFiles(); void Dump(StringBuffer* string_buffer); Result ReadHeaderAndVerify(FILE* header_file); void SetName(std::string name) { name_ = name; } const std::string& GetName() const { return name_; } void SetFilesSize(uint64_t files_size) { files_total_size_ = files_size; } const uint64_t GetFilesSize() const { return files_total_size_; } const std::filesystem::path& GetHostPath() const { return host_path_; } const XContentContainerHeader* GetContainerHeader() const { return header_.get(); } std::string name_; std::filesystem::path host_path_; std::map files_; size_t files_total_size_; std::unique_ptr root_entry_; std::unique_ptr header_; private: static XContentContainerHeader* ReadContainerHeader(FILE* host_file); }; } // namespace vfs } // namespace xe #endif