Filesystem: Replace FileInfo struct with interface

GC/Wii filesystem internals shouldn't be exposed to other classes.
This change isn't especially useful by itself, but it opens up the
way for some neat stuff in the following commits.
This commit is contained in:
JosJuice 2015-07-28 16:56:25 +02:00
parent 95bc57cff3
commit 5021b4a567
6 changed files with 84 additions and 49 deletions

View File

@ -16,6 +16,8 @@
#include "Common/Logging/Log.h"
#include "DiscIO/DiscScrubber.h"
#include "DiscIO/Filesystem.h"
// TODO: eww
#include "DiscIO/FileSystemGCWii.h"
#include "DiscIO/Volume.h"
namespace DiscIO
@ -219,11 +221,11 @@ bool DiscScrubber::ParsePartitionData(const Partition& partition, PartitionHeade
MarkAsUsedE(partition_data_offset, header->fst_offset, header->fst_size);
// Go through the filesystem and mark entries as used
for (const FileInfo& file : filesystem->GetFileList())
for (const FileInfoGCWii& file : filesystem->GetFileList())
{
DEBUG_LOG(DISCIO, "%s", file.m_FullPath.empty() ? "/" : file.m_FullPath.c_str());
if (!file.IsDirectory())
MarkAsUsedE(partition_data_offset, file.m_Offset, file.m_FileSize);
MarkAsUsedE(partition_data_offset, file.GetOffset(), file.GetSize());
}
return true;

View File

@ -22,8 +22,17 @@
namespace DiscIO
{
FileInfoGCWii::FileInfoGCWii(u64 name_offset, u64 offset, u64 file_size)
: m_NameOffset(name_offset), m_Offset(offset), m_FileSize(file_size)
{
}
FileInfoGCWii::~FileInfoGCWii()
{
}
FileSystemGCWii::FileSystemGCWii(const Volume* _rVolume, const Partition& partition)
: FileSystem(_rVolume, partition), m_Initialized(false), m_Valid(false), m_offset_shift(0)
: FileSystem(_rVolume, partition), m_Initialized(false), m_Valid(false), m_offset_shift(0)
{
m_Valid = DetectFileSystem();
}
@ -38,10 +47,10 @@ u64 FileSystemGCWii::GetFileSize(const std::string& _rFullPath)
if (!m_Initialized)
InitFileSystem();
const FileInfo* pFileInfo = FindFileInfo(_rFullPath);
const FileInfoGCWii* pFileInfo = FindFileInfo(_rFullPath);
if (pFileInfo != nullptr && !pFileInfo->IsDirectory())
return pFileInfo->m_FileSize;
return pFileInfo->GetSize();
return 0;
}
@ -53,7 +62,8 @@ std::string FileSystemGCWii::GetFileName(u64 _Address)
for (auto& fileInfo : m_FileInfoVector)
{
if ((fileInfo.m_Offset <= _Address) && ((fileInfo.m_Offset + fileInfo.m_FileSize) > _Address))
if ((fileInfo.GetOffset() <= _Address) &&
((fileInfo.GetOffset() + fileInfo.GetSize()) > _Address))
{
return fileInfo.m_FullPath;
}
@ -68,21 +78,21 @@ u64 FileSystemGCWii::ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _
if (!m_Initialized)
InitFileSystem();
const FileInfo* pFileInfo = FindFileInfo(_rFullPath);
const FileInfoGCWii* pFileInfo = FindFileInfo(_rFullPath);
if (pFileInfo == nullptr)
return 0;
if (_OffsetInFile >= pFileInfo->m_FileSize)
if (_OffsetInFile >= pFileInfo->GetSize())
return 0;
u64 read_length = std::min(_MaxBufferSize, pFileInfo->m_FileSize - _OffsetInFile);
u64 read_length = std::min(_MaxBufferSize, pFileInfo->GetSize() - _OffsetInFile);
DEBUG_LOG(DISCIO, "Reading %" PRIx64 " bytes at %" PRIx64 " from file %s. Offset: %" PRIx64
" Size: %" PRIx64,
read_length, _OffsetInFile, _rFullPath.c_str(), pFileInfo->m_Offset,
pFileInfo->m_FileSize);
read_length, _OffsetInFile, _rFullPath.c_str(), pFileInfo->GetOffset(),
pFileInfo->GetSize());
m_rVolume->Read(pFileInfo->m_Offset + _OffsetInFile, read_length, _pBuffer, m_partition);
m_rVolume->Read(pFileInfo->GetOffset() + _OffsetInFile, read_length, _pBuffer, m_partition);
return read_length;
}
@ -91,13 +101,13 @@ bool FileSystemGCWii::ExportFile(const std::string& _rFullPath, const std::strin
if (!m_Initialized)
InitFileSystem();
const FileInfo* pFileInfo = FindFileInfo(_rFullPath);
const FileInfoGCWii* pFileInfo = FindFileInfo(_rFullPath);
if (!pFileInfo)
return false;
u64 remainingSize = pFileInfo->m_FileSize;
u64 fileOffset = pFileInfo->m_Offset;
u64 remainingSize = pFileInfo->GetSize();
u64 fileOffset = pFileInfo->GetOffset();
File::IOFile f(_rExportFilename, "wb");
if (!f)
@ -225,7 +235,7 @@ std::string FileSystemGCWii::GetStringFromOffset(u64 _Offset) const
return SHIFTJISToUTF8(data);
}
const std::vector<FileInfo>& FileSystemGCWii::GetFileList()
const std::vector<FileInfoGCWii>& FileSystemGCWii::GetFileList()
{
if (!m_Initialized)
InitFileSystem();
@ -233,7 +243,7 @@ const std::vector<FileInfo>& FileSystemGCWii::GetFileList()
return m_FileInfoVector;
}
const FileInfo* FileSystemGCWii::FindFileInfo(const std::string& _rFullPath)
const FileInfoGCWii* FileSystemGCWii::FindFileInfo(const std::string& _rFullPath)
{
if (!m_Initialized)
InitFileSystem();
@ -279,7 +289,8 @@ void FileSystemGCWii::InitFileSystem()
const std::optional<u32> root_size = m_rVolume->ReadSwapped<u32>(FSTOffset + 0x8, m_partition);
if (!root_name_offset || !root_offset || !root_size)
return;
FileInfo root = {*root_name_offset, static_cast<u64>(*root_offset) << m_offset_shift, *root_size};
FileInfoGCWii root(*root_name_offset, static_cast<u64>(*root_offset) << m_offset_shift,
*root_size);
if (!root.IsDirectory())
return;
@ -287,7 +298,7 @@ void FileSystemGCWii::InitFileSystem()
// 12 bytes (the size of a file entry) times 10 * 1024 * 1024 is 120 MiB,
// more than total RAM in a Wii. No file system should use anywhere near that much.
static const u32 ARBITRARY_FILE_SYSTEM_SIZE_LIMIT = 10 * 1024 * 1024;
if (root.m_FileSize > ARBITRARY_FILE_SYSTEM_SIZE_LIMIT)
if (root.GetSize() > ARBITRARY_FILE_SYSTEM_SIZE_LIMIT)
{
// Without this check, Dolphin can crash by trying to allocate too much
// memory when loading the file systems of certain malformed disc images.
@ -300,8 +311,8 @@ void FileSystemGCWii::InitFileSystem()
PanicAlert("Wtf?");
u64 NameTableOffset = FSTOffset;
m_FileInfoVector.reserve((size_t)root.m_FileSize);
for (u32 i = 0; i < root.m_FileSize; i++)
m_FileInfoVector.reserve((size_t)root.GetSize());
for (u32 i = 0; i < root.GetSize(); i++)
{
const u64 read_offset = FSTOffset + (i * 0xC);
const std::optional<u32> name_offset = m_rVolume->ReadSwapped<u32>(read_offset, m_partition);
@ -323,7 +334,7 @@ size_t FileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _L
while (CurrentIndex < _LastIndex)
{
FileInfo& rFileInfo = m_FileInfoVector[CurrentIndex];
FileInfoGCWii& rFileInfo = m_FileInfoVector[CurrentIndex];
u64 const uOffset = _NameTableOffset + (rFileInfo.m_NameOffset & 0xFFFFFF);
std::string const offset_str{GetStringFromOffset(uOffset)};
bool const is_dir = rFileInfo.IsDirectory();
@ -340,7 +351,7 @@ size_t FileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _L
}
// check next index
CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t)rFileInfo.m_FileSize,
CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t)rFileInfo.GetSize(),
rFileInfo.m_FullPath, _NameTableOffset);
}

View File

@ -17,15 +17,32 @@ namespace DiscIO
class Volume;
struct Partition;
class FileInfoGCWii : public FileInfo
{
public:
FileInfoGCWii(u64 name_offset, u64 offset, u64 file_size);
~FileInfoGCWii() override;
u64 GetOffset() const override { return m_Offset; }
u64 GetSize() const override { return m_FileSize; }
bool IsDirectory() const override { return (m_NameOffset & 0xFF000000) != 0; }
// TODO: These shouldn't be public
std::string m_FullPath;
const u64 m_NameOffset = 0u;
private:
const u64 m_Offset = 0u;
const u64 m_FileSize = 0u;
};
class FileSystemGCWii : public FileSystem
{
public:
FileSystemGCWii(const Volume* _rVolume, const Partition& partition);
virtual ~FileSystemGCWii();
~FileSystemGCWii() override;
bool IsValid() const override { return m_Valid; }
u64 GetFileSize(const std::string& _rFullPath) override;
const std::vector<FileInfo>& GetFileList() override;
const std::vector<FileInfoGCWii>& GetFileList() override;
std::string GetFileName(u64 _Address) override;
u64 ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize,
u64 _OffsetInFile) override;
@ -39,10 +56,10 @@ private:
bool m_Initialized;
bool m_Valid;
u32 m_offset_shift;
std::vector<FileInfo> m_FileInfoVector;
std::vector<FileInfoGCWii> m_FileInfoVector;
std::string GetStringFromOffset(u64 _Offset) const;
const FileInfo* FindFileInfo(const std::string& _rFullPath);
const FileInfoGCWii* FindFileInfo(const std::string& _rFullPath);
bool DetectFileSystem();
void InitFileSystem();
size_t BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex,

View File

@ -9,6 +9,10 @@
namespace DiscIO
{
FileInfo::~FileInfo()
{
}
FileSystem::FileSystem(const Volume* _rVolume, const Partition& partition)
: m_rVolume(_rVolume), m_partition(partition)
{

View File

@ -14,22 +14,20 @@
namespace DiscIO
{
// TODO: eww
class FileInfoGCWii;
// file info of an FST entry
struct FileInfo
class FileInfo
{
u64 m_NameOffset = 0u;
u64 m_Offset = 0u;
u64 m_FileSize = 0u;
std::string m_FullPath;
public:
virtual ~FileInfo();
bool IsDirectory() const { return (m_NameOffset & 0xFF000000) != 0; }
FileInfo(u64 name_offset, u64 offset, u64 filesize)
: m_NameOffset(name_offset), m_Offset(offset), m_FileSize(filesize)
{
}
FileInfo(FileInfo const&) = default;
FileInfo() = default;
// Not guaranteed to return a meaningful value for directories
virtual u64 GetOffset() const = 0;
// Not guaranteed to return a meaningful value for directories
virtual u64 GetSize() const = 0;
virtual bool IsDirectory() const = 0;
};
class FileSystem
@ -39,7 +37,8 @@ public:
virtual ~FileSystem();
virtual bool IsValid() const = 0;
virtual const std::vector<FileInfo>& GetFileList() = 0;
// TODO: Should only return FileInfo, not FileInfoGCWii
virtual const std::vector<FileInfoGCWii>& GetFileList() = 0;
virtual u64 GetFileSize(const std::string& _rFullPath) = 0;
virtual u64 ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize,
u64 _OffsetInFile = 0) = 0;

View File

@ -23,6 +23,8 @@
#include "Common/Logging/Log.h"
#include "DiscIO/Enums.h"
#include "DiscIO/Filesystem.h"
// TODO: eww
#include "DiscIO/FileSystemGCWii.h"
#include "DiscIO/Volume.h"
#include "DolphinWX/ISOFile.h"
#include "DolphinWX/WxUtils.h"
@ -84,14 +86,14 @@ wxImageList* LoadIconBitmaps(const wxWindow* context)
}
size_t CreateDirectoryTree(wxTreeCtrl* tree_ctrl, wxTreeItemId parent,
const std::vector<DiscIO::FileInfo>& file_infos,
const std::vector<DiscIO::FileInfoGCWii>& file_infos,
const size_t first_index, const size_t last_index)
{
size_t current_index = first_index;
while (current_index < last_index)
{
const DiscIO::FileInfo& file_info = file_infos[current_index];
const DiscIO::FileInfoGCWii& file_info = file_infos[current_index];
std::string file_path = file_info.m_FullPath;
// Trim the trailing '/' if it exists.
@ -113,7 +115,7 @@ size_t CreateDirectoryTree(wxTreeCtrl* tree_ctrl, wxTreeItemId parent,
{
const wxTreeItemId item = tree_ctrl->AppendItem(parent, StrToWxStr(file_path), ICON_FOLDER);
current_index = CreateDirectoryTree(tree_ctrl, item, file_infos, current_index + 1,
static_cast<size_t>(file_info.m_FileSize));
static_cast<size_t>(file_info.GetSize()));
}
else
{
@ -126,12 +128,12 @@ size_t CreateDirectoryTree(wxTreeCtrl* tree_ctrl, wxTreeItemId parent,
}
size_t CreateDirectoryTree(wxTreeCtrl* tree_ctrl, wxTreeItemId parent,
const std::vector<DiscIO::FileInfo>& file_infos)
const std::vector<DiscIO::FileInfoGCWii>& file_infos)
{
if (file_infos.empty())
return 0;
return CreateDirectoryTree(tree_ctrl, parent, file_infos, 1, file_infos.at(0).m_FileSize);
return CreateDirectoryTree(tree_ctrl, parent, file_infos, 1, file_infos.at(0).GetSize());
}
WiiPartition* FindWiiPartition(wxTreeCtrl* tree_ctrl, const wxString& label)
@ -452,7 +454,7 @@ void FilesystemPanel::ExtractDirectories(const std::string& full_path,
const std::string& output_folder,
DiscIO::FileSystem* filesystem)
{
const std::vector<DiscIO::FileInfo>& fst = filesystem->GetFileList();
const std::vector<DiscIO::FileInfoGCWii>& fst = filesystem->GetFileList();
u32 index = 0;
u32 size = 0;
@ -473,7 +475,7 @@ void FilesystemPanel::ExtractDirectories(const std::string& full_path,
if (fst[index].m_FullPath == full_path)
{
INFO_LOG(DISCIO, "Found the directory at %u", index);
size = static_cast<u32>(fst[index].m_FileSize);
size = static_cast<u32>(fst[index].GetSize());
break;
}
}