Skip to content

Commit

Permalink
Add proper multi file system
Browse files Browse the repository at this point in the history
  • Loading branch information
TheIndra55 committed Mar 9, 2025
1 parent 1e465da commit 5c6a431
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 39 deletions.
95 changes: 66 additions & 29 deletions src/file/MultiFileSystem.cpp
Original file line number Diff line number Diff line change
@@ -1,73 +1,110 @@
#include "MultiFileSystem.h"

MultiFileSystem::MultiFileSystem(cdc::FileSystem* pFS, cdc::FileSystem* pHookFS)
#include "Hook.h"
#include "modules/Log.h"

MultiFileSystem::MultiFileSystem() : m_fileSystems()
{
m_pFS = pFS;
m_pHookFS = pHookFS;
}

// Gets the best file system for a file simply by checking the hook file system first
cdc::FileSystem* MultiFileSystem::GetBestFileSystem(const char* fileName)
void MultiFileSystem::Add(cdc::FileSystem* fileSystem)
{
// First check the hook file system, else fall back to default filesystem
if (m_pHookFS->FileExists(fileName))
m_fileSystems.push_back(fileSystem);

#ifdef _DEBUG
Hook::GetInstance().GetModule<Log>()->WriteLine("Mounted new file system %p, now at %d", fileSystem, m_fileSystems.size());
#endif
}

void MultiFileSystem::Remove(cdc::FileSystem* fileSystem)
{
auto it = std::find(m_fileSystems.begin(), m_fileSystems.end(), fileSystem);

if (it != m_fileSystems.end())
{
return m_pHookFS;
m_fileSystems.erase(it);
}

return m_pFS;
}

cdc::FileRequest* MultiFileSystem::RequestRead(cdc::FileReceiver* receiver, const char* fileName, unsigned int startOffset)
cdc::FileSystem* MultiFileSystem::GetBestFileSystem(const char* fileName) const noexcept
{
auto pFS = GetBestFileSystem(fileName);
for (auto fileSystem : m_fileSystems)
{
if (fileSystem->FileExists(fileName))
{
return fileSystem;
}
}

return pFS->RequestRead(receiver, fileName, startOffset);
return nullptr;
}

cdc::File* MultiFileSystem::OpenFile(char const* fileName)
cdc::FileRequest* MultiFileSystem::RequestRead(cdc::FileReceiver* receiver, const char* fileName, unsigned int startOffset)
{
auto pFS = GetBestFileSystem(fileName);
return GetBestFileSystem(fileName)->RequestRead(receiver, fileName, startOffset);
}

return pFS->OpenFile(fileName);
cdc::File* MultiFileSystem::OpenFile(const char* fileName)
{
return GetBestFileSystem(fileName)->OpenFile(fileName);
}

bool MultiFileSystem::FileExists(char const* fileName)
unsigned int MultiFileSystem::GetFileSize(const char* fileName)
{
return m_pFS->FileExists(fileName) || m_pHookFS->FileExists(fileName);
return GetBestFileSystem(fileName)->GetFileSize(fileName);
}

unsigned int MultiFileSystem::GetFileSize(char const* fileName)
bool MultiFileSystem::FileExists(const char* fileName)
{
auto pFS = GetBestFileSystem(fileName);
for (auto fileSystem : m_fileSystems)
{
if (fileSystem->FileExists(fileName))
{
return true;
}
}

return pFS->GetFileSize(fileName);
return false;
}

void MultiFileSystem::SetSpecialisationMask(unsigned int specMask)
{
m_pFS->SetSpecialisationMask(specMask);
m_pHookFS->SetSpecialisationMask(specMask);
for (auto fileSystem : m_fileSystems)
{
fileSystem->SetSpecialisationMask(specMask);
}
}

unsigned int MultiFileSystem::GetSpecialisationMask()
{
return m_pFS->GetSpecialisationMask();
return m_fileSystems.empty() ? 0xFFFFFFFF : m_fileSystems[0]->GetSpecialisationMask();
}

// These only need to call the default file system, both will end at the same place

cdc::FileSystem::Status MultiFileSystem::GetStatus()
{
return m_pFS->GetStatus();
for (auto fileSystem : m_fileSystems)
{
if (fileSystem->GetStatus() == BUSY)
{
return BUSY;
}
}

return IDLE;
}

void MultiFileSystem::Update()
{
m_pFS->Update();
for (auto fileSystem : m_fileSystems)
{
fileSystem->Update();
}
}

void MultiFileSystem::Synchronize()
{
m_pFS->Synchronize();
for (auto fileSystem : m_fileSystems)
{
fileSystem->Synchronize();
}
}
18 changes: 9 additions & 9 deletions src/file/MultiFileSystem.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
#pragma once

#include <vector>

#include "cdc/file/FileSystem.h"

// Simplified version for cdc::MultiFileSystem since it does not exist in Legend and Anniversary
// The real MultiFileSystem can dynamically add and re-order systems
//
// This just checks the hook file system first and else falls back to the
// original file system
class MultiFileSystem : public cdc::FileSystem
{
private:
cdc::FileSystem* m_pFS;
cdc::FileSystem* m_pHookFS;
std::vector<cdc::FileSystem*> m_fileSystems;

cdc::FileSystem* GetBestFileSystem(const char* fileName) const noexcept;

cdc::FileSystem* GetBestFileSystem(const char* fileName);
public:
MultiFileSystem(cdc::FileSystem* pFS, cdc::FileSystem* pHookFS);
MultiFileSystem();

void Add(cdc::FileSystem* fileSystem);
void Remove(cdc::FileSystem* fileSystem);

cdc::FileRequest* RequestRead(cdc::FileReceiver* receiver, const char* fileName, unsigned int startOffset);
cdc::File* OpenFile(const char* fileName);
Expand Down
6 changes: 5 additions & 1 deletion src/modules/ModLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ static void InitArchive()

// Create our hook file system and multi file system
auto fileSystem = CreateHookFileSystem();
auto multiFileSystem = new MultiFileSystem(GetFS(), fileSystem);
auto multiFileSystem = new MultiFileSystem();

// Add the hook and original file system
multiFileSystem->Add(fileSystem);
multiFileSystem->Add(GetFS());

// Overwrite the original file system with ours
*(cdc::FileSystem**)GET_ADDRESS(0x10E58BC, 0x83888C, 0x9CE278) = multiFileSystem;
Expand Down

0 comments on commit 5c6a431

Please sign in to comment.