parent
cc08e9019a
commit
c9f4d00da3
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue