VolumeDirectory: Sort the FST

We can't rely on the OS returning files and directories
in a deterministic order, so we should sort them on our own
if we want VolumeDirectory to work for movies and netplay.
This commit is contained in:
JosJuice 2016-12-25 22:35:38 +01:00
parent 09c6148aba
commit a502f069e8
2 changed files with 32 additions and 28 deletions

View File

@ -363,10 +363,7 @@ void CVolumeDirectory::BuildFST()
// write root entry // write root entry
WriteEntryData(fstOffset, DIRECTORY_ENTRY, 0, 0, totalEntries); WriteEntryData(fstOffset, DIRECTORY_ENTRY, 0, 0, totalEntries);
for (auto& entry : rootEntry.children) WriteDirectory(rootEntry, fstOffset, nameOffset, curDataAddress, rootOffset);
{
WriteEntry(entry, fstOffset, nameOffset, curDataAddress, rootOffset);
}
// overflow check // overflow check
_dbg_assert_(DVDINTERFACE, nameOffset == m_totalNameSize); _dbg_assert_(DVDINTERFACE, nameOffset == m_totalNameSize);
@ -443,34 +440,41 @@ void CVolumeDirectory::WriteEntryName(u32& nameOffset, const std::string& name)
nameOffset += (u32)(name.length() + 1); nameOffset += (u32)(name.length() + 1);
} }
void CVolumeDirectory::WriteEntry(const File::FSTEntry& entry, u32& fstOffset, u32& nameOffset, void CVolumeDirectory::WriteDirectory(const File::FSTEntry& parent_entry, u32& fstOffset,
u64& dataOffset, u32 parentEntryNum) u32& nameOffset, u64& dataOffset, u32 parentEntryNum)
{ {
if (entry.isDirectory) std::vector<File::FSTEntry> sorted_entries = parent_entry.children;
{
u32 myOffset = fstOffset;
u32 myEntryNum = myOffset / ENTRY_SIZE;
WriteEntryData(fstOffset, DIRECTORY_ENTRY, nameOffset, parentEntryNum,
myEntryNum + entry.size + 1);
WriteEntryName(nameOffset, entry.virtualName);
for (const auto& child : entry.children) std::sort(sorted_entries.begin(), sorted_entries.end(),
[](const File::FSTEntry& one, const File::FSTEntry& two) {
return one.virtualName < two.virtualName;
});
for (const File::FSTEntry& entry : sorted_entries)
{
if (entry.isDirectory)
{ {
WriteEntry(child, fstOffset, nameOffset, dataOffset, myEntryNum); u32 myOffset = fstOffset;
u32 myEntryNum = myOffset / ENTRY_SIZE;
WriteEntryData(fstOffset, DIRECTORY_ENTRY, nameOffset, parentEntryNum,
myEntryNum + entry.size + 1);
WriteEntryName(nameOffset, entry.virtualName);
WriteDirectory(entry, fstOffset, nameOffset, dataOffset, myEntryNum);
} }
} else
else {
{ // put entry in FST
// put entry in FST WriteEntryData(fstOffset, FILE_ENTRY, nameOffset, dataOffset, entry.size);
WriteEntryData(fstOffset, FILE_ENTRY, nameOffset, dataOffset, entry.size); WriteEntryName(nameOffset, entry.virtualName);
WriteEntryName(nameOffset, entry.virtualName);
// write entry to virtual disk // write entry to virtual disk
_dbg_assert_(DVDINTERFACE, m_virtualDisk.find(dataOffset) == m_virtualDisk.end()); _dbg_assert_(DVDINTERFACE, m_virtualDisk.find(dataOffset) == m_virtualDisk.end());
m_virtualDisk.emplace(dataOffset, entry.physicalName); m_virtualDisk.emplace(dataOffset, entry.physicalName);
// 4 byte aligned // 4 byte aligned
dataOffset = Common::AlignUp(dataOffset + std::max<u64>(entry.size, 1ull), 0x8000ull); dataOffset = Common::AlignUp(dataOffset + std::max<u64>(entry.size, 1ull), 0x8000ull);
}
} }
} }

View File

@ -85,8 +85,8 @@ private:
// FST creation // FST creation
void WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u64 length); void WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u64 length);
void WriteEntryName(u32& nameOffset, const std::string& name); void WriteEntryName(u32& nameOffset, const std::string& name);
void WriteEntry(const File::FSTEntry& entry, u32& fstOffset, u32& nameOffset, u64& dataOffset, void WriteDirectory(const File::FSTEntry& parent_entry, u32& fstOffset, u32& nameOffset,
u32 parentEntryNum); u64& dataOffset, u32 parentEntryNum);
// returns number of entries found in _Directory // returns number of entries found in _Directory
u64 AddDirectoryEntries(const std::string& _Directory, File::FSTEntry& parentEntry); u64 AddDirectoryEntries(const std::string& _Directory, File::FSTEntry& parentEntry);