Skip to content

Commit 693c669

Browse files
committed
Fix mod loader for TR8 and add simplified MultiFileSystem
1 parent 46b51eb commit 693c669

File tree

6 files changed

+158
-41
lines changed

6 files changed

+158
-41
lines changed

Hooking.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ Hooking::Hooking()
6565
MH_CreateHook((void*)ADDR(0x467310, 0x4642F0), MakePeHandle, nullptr);
6666
#endif
6767

68+
#if TR8
69+
MultiFileSystem_Add = reinterpret_cast<void(__thiscall*)(void*, cdc::FileSystem*, bool, bool)>(0x472C50);
70+
#endif
71+
6872
Game::Initialize();
6973

7074
MH_EnableHook(MH_ALL_HOOKS);
@@ -123,7 +127,7 @@ void(__cdecl* org_Font__Flush)();
123127
cdc::FileSystem* GetFS()
124128
{
125129
#ifndef TR8
126-
static cdc::FileSystem* pFS = CreateHookFileSystem(*(cdc::FileSystem**)ARCHIVEFS, *(cdc::FileSystem**)DISKFS);
130+
static cdc::FileSystem* pFS = CreateMultiFileSystem(*(cdc::FileSystem**)ARCHIVEFS, *(cdc::FileSystem**)DISKFS);
127131

128132
return pFS;
129133
#else
@@ -132,6 +136,21 @@ cdc::FileSystem* GetFS()
132136
#endif
133137
}
134138

139+
bool(__cdecl* orgInitPatchArchive)(const char* name);
140+
void(__thiscall* MultiFileSystem_Add)(void* _this, cdc::FileSystem* filesystem, bool unk, bool insertFirst);
141+
142+
bool InitPatchArchive(const char* name)
143+
{
144+
// init the orginal patch archive, let the game add it to the multi filesystem
145+
auto ret = orgInitPatchArchive(name);
146+
147+
// create the hook filesystem and add it front to the multi filesystem
148+
auto pFS = CreateHookFileSystem(*(cdc::FileSystem**)DISKFS);
149+
MultiFileSystem_Add(GetFS(), pFS, false, true);
150+
151+
return ret;
152+
}
153+
135154
#if TRAE || (TR7 && RETAIL_VERSION)
136155
void __cdecl EVENT_DisplayString(char* str, int time)
137156
{

Hooking.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,8 @@ uint8_t __declspec(noinline)* GetAddress(uint8_t* ptr, uint8_t offset, uint8_t i
6969
void DrawQuads(int flags, int tpage, DRAWVERTEX* verts, int numquads);
7070

7171
extern int(__cdecl* G2EmulationInstanceQueryAnimation)(Instance* instance, int section);
72+
73+
bool InitPatchArchive(const char* name);
74+
75+
extern bool(__cdecl* orgInitPatchArchive)(const char* name);
76+
extern void(__thiscall* MultiFileSystem_Add)(void* _this, cdc::FileSystem* filesystem, bool unk, bool insertFirst);

dllmain.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ BOOL WINAPI hGetVersionExA(LPSTARTUPINFOA lpStartupInfo)
1414
#elif TR7
1515
MH_CreateHook((void*)ADDR(0x45F420, 0x45C700), GetFS, nullptr);
1616
#endif
17+
1718
MH_EnableHook(GetFS);
1819

1920
Hooking::GetInstance(); // Will call the ctor
@@ -49,6 +50,9 @@ DWORD WINAPI Hook(LPVOID lpParam)
4950
MH_CreateHookApi(L"Kernel32", "GetStartupInfoA", hGetVersionExA, reinterpret_cast<void**>(&dGetVersionExA));
5051
MH_EnableHook(MH_ALL_HOOKS);
5152
#else
53+
MH_CreateHook((void*)0x478930, InitPatchArchive, (void**)&orgInitPatchArchive);
54+
MH_EnableHook(InitPatchArchive);
55+
5256
Hooking::GetInstance(); // Will call the ctor
5357
#endif
5458

game/filesystem.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ namespace cdc
4343
};
4444
}
4545

46+
cdc::FileSystem* CreateHookFileSystem(cdc::FileSystem* pDiskFS);
47+
cdc::FileSystem* CreateMultiFileSystem(cdc::FileSystem* pFS, cdc::FileSystem* pDiskFS);
48+
4649
#define g_pDiskFS VAR_U_(DISKFS, cdc::MSFileSystem*)
4750
#define g_pFS VAR_U_(ARCHIVEFS, cdc::FileSystem*)
4851

49-
cdc::FileSystem* GetFS();
50-
cdc::FileSystem* CreateHookFileSystem(cdc::FileSystem* pFS, cdc::FileSystem* pDiskFS);
52+
cdc::FileSystem* GetFS();

game/hookfilesystem.cpp

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,27 @@
77
// so we don't need to include <Windows.h>
88
#define _MAX_PATH 260
99

10+
// the HookFileSystem will look for a file in the mods folder and rewrite the path
11+
// for the disk filesystem to open, allowing it to load files without a bigfile
12+
1013
class HookFileSystem : public cdc::FileSystem
1114
{
1215
private:
13-
cdc::FileSystem* m_pFS;
1416
cdc::FileSystem* m_pDiskFS;
1517

1618
unsigned int m_specMask;
1719

1820
public:
19-
HookFileSystem(cdc::FileSystem* pFS, cdc::FileSystem* pDiskFS)
21+
HookFileSystem(cdc::FileSystem* pDiskFS)
2022
{
21-
m_pFS = pFS;
2223
m_pDiskFS = pDiskFS;
2324
m_specMask = 1;
2425
}
2526

26-
cdc::FileSystem* GetBestFileSystem(const char* fileName, char** outFilename)
27+
// finds a file in the mods folder and rewrites path to it
28+
bool FindFile(const char* fileName, char* path)
2729
{
28-
// suffix pc-w to mods folder
29-
char path[_MAX_PATH];
30-
strcpy_s(path, fileName);
30+
strcpy_s(path, _MAX_PATH, fileName);
3131

3232
for (char* p = path; *p; ++p) *p = tolower(*p);
3333

@@ -38,7 +38,7 @@ class HookFileSystem : public cdc::FileSystem
3838
}
3939

4040
// rewrite root to mods folder
41-
if (strncmp(path, "\\", 1) == 0)
41+
if (strncmp(path, "\\", 1) == 0)
4242
{
4343
// move string 4 bytes
4444
memmove(path + 4, path, sizeof(path) - 4);
@@ -51,101 +51,97 @@ class HookFileSystem : public cdc::FileSystem
5151

5252
if (m_pDiskFS->FileExists(specPath))
5353
{
54-
*outFilename = specPath;
55-
return m_pDiskFS;
54+
strcpy_s(path, _MAX_PATH, specPath);
55+
56+
return true;
5657
}
5758

5859
// check if file exists on disk, if so return the diskFS
5960
if (m_pDiskFS->FileExists(path))
6061
{
61-
*outFilename = path;
62-
return m_pDiskFS;
62+
return true;
6363
}
6464

65-
*outFilename = (char*)fileName;
66-
return m_pFS;
65+
return false;
6766
}
6867

6968
virtual void* RequestRead(void* receiver, const char* fileName, unsigned int startOffset)
7069
{
71-
char* path;
72-
auto pFS = GetBestFileSystem(fileName, &path);
70+
char path[_MAX_PATH];
71+
FindFile(fileName, path);
7372

74-
return pFS->RequestRead(receiver, path, startOffset);
73+
return m_pDiskFS->RequestRead(receiver, path, startOffset);
7574
}
7675

7776
virtual void* OpenFile(char const* fileName)
7877
{
79-
char* path;
80-
auto pFS = GetBestFileSystem(fileName, &path);
78+
char path[_MAX_PATH];
79+
FindFile(fileName, path);
8180

82-
return pFS->OpenFile(path);
81+
return m_pDiskFS->OpenFile(path);
8382
}
8483

8584
virtual bool FileExists(char const* fileName)
8685
{
87-
char* path;
88-
auto pFS = GetBestFileSystem(fileName, &path);
89-
90-
return pFS->FileExists(path);
86+
char path[_MAX_PATH];
87+
return FindFile(fileName, path);
9188
}
9289

9390
virtual unsigned int GetFileSize(char const* fileName)
9491
{
95-
char* path;
96-
auto pFS = GetBestFileSystem(fileName, &path);
92+
char path[_MAX_PATH];
93+
FindFile(fileName, path);
9794

98-
return pFS->GetFileSize(path);
95+
return m_pDiskFS->GetFileSize(path);
9996
}
10097

10198
virtual void SetSpecialisationMask(unsigned int specMask)
10299
{
103-
m_pFS->SetSpecialisationMask(specMask);
100+
m_pDiskFS->SetSpecialisationMask(specMask);
104101

105102
// unset next generation bit and set our spec mask
106103
m_specMask = specMask & ~0x80000000;
107104
}
108105

109106
virtual unsigned int GetSpecialisationMask()
110107
{
111-
return m_pFS->GetSpecialisationMask();
108+
return 0;
112109
}
113110

114-
// these below don't need to call diskFS, the archive filesystem will do so
115111
virtual int GetStatus()
116112
{
117-
return m_pFS->GetStatus();
113+
return m_pDiskFS->GetStatus();
118114
}
119115

120116
virtual void Update()
121117
{
122-
m_pFS->Update();
118+
m_pDiskFS->Update();
123119
}
124120

125121
virtual void Synchronize()
126122
{
127-
m_pFS->Synchronize();
123+
m_pDiskFS->Synchronize();
128124
}
129125

130126
#if TR8
131127
virtual void Suspend()
132128
{
133-
m_pFS->Suspend();
129+
m_pDiskFS->Suspend();
134130
}
135131

136132
virtual bool Resume()
137133
{
138-
return m_pFS->Resume();
134+
return m_pDiskFS->Resume();
139135
}
140136

141137
virtual bool IsSuspended()
142138
{
143-
return m_pFS->IsSuspended();
139+
return m_pDiskFS->IsSuspended();
144140
}
145141
#endif
146142
};
147143

148-
cdc::FileSystem* CreateHookFileSystem(cdc::FileSystem* pFS, cdc::FileSystem* pDiskFS)
144+
cdc::FileSystem* CreateHookFileSystem(cdc::FileSystem* pDiskFS)
149145
{
150-
return new HookFileSystem(pFS, pDiskFS);
146+
return new HookFileSystem(pDiskFS);
151147
}

game/multifilesystem.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#include "filesystem.hpp"
2+
3+
// very simplified version of cdc::MultiFileSystem since it does not exist in Legend and Anniversary
4+
// the real MultiFileSystem can dynamically add and re-order filesystems
5+
6+
class MultiFileSystem : public cdc::FileSystem
7+
{
8+
private:
9+
cdc::FileSystem* m_pFS;
10+
cdc::FileSystem* m_pHookFS;
11+
12+
public:
13+
MultiFileSystem(cdc::FileSystem* pFS, cdc::FileSystem* pHookFS)
14+
{
15+
m_pFS = pFS;
16+
m_pHookFS = pHookFS;
17+
}
18+
19+
cdc::FileSystem* GetBestFileSystem(const char* fileName)
20+
{
21+
// first check hook filesystem, else fall back to default filesystem
22+
if (m_pHookFS->FileExists(fileName))
23+
{
24+
return m_pHookFS;
25+
}
26+
27+
return m_pFS;
28+
}
29+
30+
virtual void* RequestRead(void* receiver, const char* fileName, unsigned int startOffset)
31+
{
32+
auto pFS = GetBestFileSystem(fileName);
33+
34+
return pFS->RequestRead(receiver, fileName, startOffset);
35+
}
36+
37+
virtual void* OpenFile(char const* fileName)
38+
{
39+
auto pFS = GetBestFileSystem(fileName);
40+
41+
return pFS->OpenFile(fileName);
42+
}
43+
44+
virtual bool FileExists(char const* fileName)
45+
{
46+
return m_pFS->FileExists(fileName) || m_pHookFS->FileExists(fileName);
47+
}
48+
49+
virtual unsigned int GetFileSize(char const* fileName)
50+
{
51+
auto pFS = GetBestFileSystem(fileName);
52+
53+
return pFS->GetFileSize(fileName);
54+
}
55+
56+
virtual void SetSpecialisationMask(unsigned int specMask)
57+
{
58+
m_pFS->SetSpecialisationMask(specMask);
59+
m_pHookFS->SetSpecialisationMask(specMask);
60+
}
61+
62+
virtual unsigned int GetSpecialisationMask()
63+
{
64+
return m_pFS->GetSpecialisationMask();
65+
}
66+
67+
// only need to call the default filesystem, both will end at the same place
68+
virtual int GetStatus()
69+
{
70+
return m_pFS->GetStatus();
71+
}
72+
73+
virtual void Update()
74+
{
75+
m_pFS->Update();
76+
}
77+
78+
virtual void Synchronize()
79+
{
80+
m_pFS->Synchronize();
81+
}
82+
};
83+
84+
#ifndef TR8
85+
cdc::FileSystem* CreateMultiFileSystem(cdc::FileSystem* pFS, cdc::FileSystem* pDiskFS)
86+
{
87+
auto pHookFS = CreateHookFileSystem(pDiskFS);
88+
89+
return new MultiFileSystem(pFS, pHookFS);
90+
}
91+
#endif

0 commit comments

Comments
 (0)