summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO/FileSystemGCWii.cpp
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2015-07-29 16:42:29 +0200
committerJosJuice <josjuice@gmail.com>2017-06-13 22:38:31 +0200
commit07d3a39aeb06204e13cfdf1d5f7dbe4f3aa66f89 (patch)
tree5cb05fd42f2f5da5319d32a73cd2856ad5d18b61 /Source/Core/DiscIO/FileSystemGCWii.cpp
parent5021b4a567fad9a258f2b0fc397912f499e4cb1d (diff)
Filesystem: Replace file info's full path with name
Some callers (i.e. ISOProperties) don't want the full path, so giving them it is unnecessary. Those that do want it can use GetPathFromFSTOffset. Not storing full paths everywhere also saves a small bit of RAM and is necessary for a later commit. The code isn't especially pretty right now (callers need to use FST offsets...) but it'll become better later.
Diffstat (limited to 'Source/Core/DiscIO/FileSystemGCWii.cpp')
-rw-r--r--Source/Core/DiscIO/FileSystemGCWii.cpp112
1 files changed, 60 insertions, 52 deletions
diff --git a/Source/Core/DiscIO/FileSystemGCWii.cpp b/Source/Core/DiscIO/FileSystemGCWii.cpp
index 32f93f5eb6..fc0e40f055 100644
--- a/Source/Core/DiscIO/FileSystemGCWii.cpp
+++ b/Source/Core/DiscIO/FileSystemGCWii.cpp
@@ -22,8 +22,8 @@
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(u64 name_offset, u64 offset, u64 file_size, std::string name)
+ : m_NameOffset(name_offset), m_Offset(offset), m_FileSize(file_size), m_Name(name)
{
}
@@ -55,23 +55,64 @@ u64 FileSystemGCWii::GetFileSize(const std::string& _rFullPath)
return 0;
}
-std::string FileSystemGCWii::GetFileName(u64 _Address)
+std::string FileSystemGCWii::GetPath(u64 _Address)
{
if (!m_Initialized)
InitFileSystem();
- for (auto& fileInfo : m_FileInfoVector)
+ for (size_t i = 0; i < m_FileInfoVector.size(); ++i)
{
- if ((fileInfo.GetOffset() <= _Address) &&
- ((fileInfo.GetOffset() + fileInfo.GetSize()) > _Address))
+ const FileInfoGCWii& file_info = m_FileInfoVector[i];
+ if ((file_info.GetOffset() <= _Address) &&
+ ((file_info.GetOffset() + file_info.GetSize()) > _Address))
{
- return fileInfo.m_FullPath;
+ return GetPathFromFSTOffset(i);
}
}
return "";
}
+std::string FileSystemGCWii::GetPathFromFSTOffset(size_t file_info_offset)
+{
+ if (!m_Initialized)
+ InitFileSystem();
+
+ // Root entry doesn't have a name
+ if (file_info_offset == 0)
+ return "";
+
+ const FileInfoGCWii& file_info = m_FileInfoVector[file_info_offset];
+ if (file_info.IsDirectory())
+ {
+ // The offset of the parent directory is stored in the current directory.
+
+ if (file_info.GetOffset() >= file_info_offset)
+ {
+ // The offset of the parent directory is supposed to be smaller than
+ // the current offset. If an FST is malformed and breaks that rule,
+ // there's a risk that parent directory pointers form a loop.
+ // To avoid stack overflows, this method returns.
+ ERROR_LOG(DISCIO, "Invalid parent offset in file system");
+ return "";
+ }
+ return GetPathFromFSTOffset(file_info.GetOffset()) + file_info.GetName() + "/";
+ }
+ else
+ {
+ // The parent directory can be found by searching backwards
+ // for a directory that contains this file.
+
+ size_t parent_offset = file_info_offset - 1;
+ while (!(m_FileInfoVector[parent_offset].IsDirectory() &&
+ m_FileInfoVector[parent_offset].GetSize() > file_info_offset))
+ {
+ parent_offset--;
+ }
+ return GetPathFromFSTOffset(parent_offset) + file_info.GetName();
+ }
+}
+
u64 FileSystemGCWii::ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize,
u64 _OffsetInFile)
{
@@ -248,10 +289,10 @@ const FileInfoGCWii* FileSystemGCWii::FindFileInfo(const std::string& _rFullPath
if (!m_Initialized)
InitFileSystem();
- for (auto& fileInfo : m_FileInfoVector)
+ for (size_t i = 0; i < m_FileInfoVector.size(); ++i)
{
- if (!strcasecmp(fileInfo.m_FullPath.c_str(), _rFullPath.c_str()))
- return &fileInfo;
+ if (!strcasecmp(GetPathFromFSTOffset(i).c_str(), _rFullPath.c_str()))
+ return &m_FileInfoVector[i];
}
return nullptr;
@@ -290,7 +331,7 @@ void FileSystemGCWii::InitFileSystem()
if (!root_name_offset || !root_offset || !root_size)
return;
FileInfoGCWii root(*root_name_offset, static_cast<u64>(*root_offset) << m_offset_shift,
- *root_size);
+ *root_size, "");
if (!root.IsDirectory())
return;
@@ -309,53 +350,20 @@ void FileSystemGCWii::InitFileSystem()
if (m_FileInfoVector.size())
PanicAlert("Wtf?");
- u64 NameTableOffset = FSTOffset;
+ u64 NameTableOffset = FSTOffset + (root.GetSize() * 0xC);
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);
- const std::optional<u32> offset = m_rVolume->ReadSwapped<u32>(read_offset + 0x4, m_partition);
- const std::optional<u32> size = m_rVolume->ReadSwapped<u32>(read_offset + 0x8, m_partition);
- m_FileInfoVector.emplace_back(name_offset.value_or(0),
- static_cast<u64>(offset.value_or(0)) << m_offset_shift,
- size.value_or(0));
- NameTableOffset += 0xC;
+ const u32 name_offset = m_rVolume->ReadSwapped<u32>(read_offset, m_partition).value_or(0);
+ const u32 offset = m_rVolume->ReadSwapped<u32>(read_offset + 0x4, m_partition).value_or(0);
+ const u32 size = m_rVolume->ReadSwapped<u32>(read_offset + 0x8, m_partition).value_or(0);
+ const std::string name = GetStringFromOffset(NameTableOffset + (name_offset & 0xFFFFFF));
+ m_FileInfoVector.emplace_back(
+ name_offset, static_cast<u64>(offset) << (m_offset_shift * !(name_offset & 0xFF000000)),
+ size, name);
}
-
- BuildFilenames(1, m_FileInfoVector.size(), "", NameTableOffset);
-}
-
-size_t FileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex,
- const std::string& _szDirectory, u64 _NameTableOffset)
-{
- size_t CurrentIndex = _FirstIndex;
-
- while (CurrentIndex < _LastIndex)
- {
- 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();
- rFileInfo.m_FullPath.reserve(_szDirectory.size() + offset_str.size());
-
- rFileInfo.m_FullPath.append(_szDirectory.data(), _szDirectory.size())
- .append(offset_str.data(), offset_str.size())
- .append("/", size_t(is_dir));
-
- if (!is_dir)
- {
- ++CurrentIndex;
- continue;
- }
-
- // check next index
- CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t)rFileInfo.GetSize(),
- rFileInfo.m_FullPath, _NameTableOffset);
- }
-
- return CurrentIndex;
}
} // namespace