|
10 | 10 | *****************************************************************************/ |
11 | 11 |
|
12 | 12 | #include "StdInc.h" |
| 13 | +#include "../Client/game_sa/CDirectorySA.h" |
13 | 14 |
|
14 | 15 | DWORD FUNC_CStreamingInfoAddToList = 0x407480; |
15 | 16 | DWORD FUNC_CStreamingConvertBufferToObject = 0x40C6B0; |
@@ -54,49 +55,6 @@ void CMultiplayerSA::SetFastClothesLoading(EFastClothesLoading fastClothesLoadin |
54 | 55 | ms_PlayerImgCachePtr = NULL; |
55 | 56 | } |
56 | 57 |
|
57 | | -// |
58 | | -// Skip loading the directory data from player.img if it has already been loaded. |
59 | | -// Speeds up clothes a bit, but is only part of a solution - The actual files from inside player.img are still loaded each time |
60 | | -// |
61 | | -bool _cdecl IsPlayerImgDirLoaded() |
62 | | -{ |
63 | | - // When player.img dir is loaded, it looks this this: |
64 | | - // 0x00BC12C0 00bbcdc8 00000226 |
65 | | - DWORD* ptr1 = (DWORD*)0x00BC12C0; |
66 | | - if (ptr1[0] == 0x00BBCDC8 && ptr1[1] == 0x0000226) |
67 | | - { |
68 | | - return true; |
69 | | - } |
70 | | - return false; |
71 | | -} |
72 | | - |
73 | | -// Hook info |
74 | | -#define HOOKPOS_LoadingPlayerImgDir 0x5A69E3 |
75 | | -#define HOOKSIZE_LoadingPlayerImgDir 5 |
76 | | -DWORD RETURN_LoadingPlayerImgDirA = 0x5A69E8; |
77 | | -DWORD RETURN_LoadingPlayerImgDirB = 0x5A6A06; |
78 | | -void _declspec(naked) HOOK_LoadingPlayerImgDir() |
79 | | -{ |
80 | | - // hook from 005A69E3 5 bytes |
81 | | - _asm |
82 | | - { |
83 | | - pushad |
84 | | - call IsPlayerImgDirLoaded |
85 | | - cmp al, 0 |
86 | | - jnz skip |
87 | | - popad |
88 | | - |
89 | | - // Standard code to load img directory |
90 | | - push 0BBCDC8h |
91 | | - jmp RETURN_LoadingPlayerImgDirA |
92 | | - |
93 | | - // Skip loading img directory |
94 | | -skip: |
95 | | - popad |
96 | | - jmp RETURN_LoadingPlayerImgDirB |
97 | | - } |
98 | | -} |
99 | | - |
100 | 58 | //////////////////////////////////////////////// |
101 | 59 | // |
102 | 60 | // Hook CStreaming::RequestFile |
@@ -252,13 +210,89 @@ void _declspec(naked) HOOK_CStreamingLoadRequestedModels() |
252 | 210 | } |
253 | 211 | } |
254 | 212 |
|
| 213 | +// |
| 214 | +// Skip loading the directory data from player.img if it has already been loaded. |
| 215 | +// Speeds up clothes a bit, but is only part of a solution - The actual files from inside player.img are still loaded each time |
| 216 | +// |
| 217 | + |
| 218 | +uint32_t g_pPlayerImgEntries = 0xBBCDC8; |
| 219 | +uint16_t g_nPlayerImgSize = 0x226; |
| 220 | + |
| 221 | +bool _cdecl IsPlayerImgDirLoaded() |
| 222 | +{ |
| 223 | + // When player.img dir is loaded, it looks this this: |
| 224 | + // 0x00BC12C0 00bbcdc8 00000226 |
| 225 | + DWORD* ptr1 = (DWORD*)0xBC12C0; |
| 226 | + if (ptr1[0] == g_pPlayerImgEntries && ptr1[1] == g_nPlayerImgSize) |
| 227 | + { |
| 228 | + return true; |
| 229 | + } |
| 230 | + return false; |
| 231 | +} |
| 232 | + |
| 233 | +// Hook info |
| 234 | +#define HOOKSIZE_LoadingPlayerImgDir 5 |
| 235 | +#define HOOKPOS_LoadingPlayerImgDir 0x5A69E3 // 005A69D6 -> CClothesBuilder::CreateSkinnedClump -> playerImgEntries |
| 236 | +DWORD RETURN_LoadingPlayerImgDirA = 0x5A69E8; // push 00000226 { 550 } |
| 237 | +DWORD RETURN_LoadingPlayerImgDirB = 0x5A6A06; // return of CreateSkinnedClump function |
| 238 | + |
| 239 | +void _declspec(naked) HOOK_LoadingPlayerImgDir() |
| 240 | +{ |
| 241 | + // hook from 005A69E3 5 bytes |
| 242 | + _asm |
| 243 | + { |
| 244 | + pushad |
| 245 | + call IsPlayerImgDirLoaded |
| 246 | + cmp al, 0 |
| 247 | + jnz skip |
| 248 | + popad |
| 249 | + |
| 250 | + // Standard code to load img directory |
| 251 | + mov eax, g_pPlayerImgEntries |
| 252 | + push eax |
| 253 | + jmp RETURN_LoadingPlayerImgDirA |
| 254 | + |
| 255 | + // Skip loading img directory |
| 256 | +skip: |
| 257 | + popad |
| 258 | + jmp RETURN_LoadingPlayerImgDirB |
| 259 | + } |
| 260 | +} |
| 261 | + |
| 262 | +////////////////////////////////////////////////////////////////////////////////////////// |
| 263 | +// |
| 264 | +// Setup clothing directory size |
| 265 | +// |
| 266 | +////////////////////////////////////////////////////////////////////////////////////////// |
| 267 | +bool _cdecl SetClothingDirectorySize(int iCapacity) |
| 268 | +{ |
| 269 | + DirectoryInfoSA* clothesDirectory = (DirectoryInfoSA*)malloc(sizeof(DirectoryInfoSA) * iCapacity); |
| 270 | + |
| 271 | + if (clothesDirectory) |
| 272 | + { |
| 273 | + // CClothesBuilder::LoadCdDirectory(void) |
| 274 | + MemPut<uint32_t>(0x5A4190 + 1, reinterpret_cast<uint32_t>(clothesDirectory)); // push offset _playerImgEntries; headers |
| 275 | + MemPut<uint16_t>(0x5A4195 + 1, iCapacity); // push 550 ; count |
| 276 | + MemPut<uint16_t>(0x5A69E8 + 1, iCapacity); // push 550 ; count |
| 277 | + |
| 278 | + g_pPlayerImgEntries = reinterpret_cast<uint32_t>(clothesDirectory); |
| 279 | + g_nPlayerImgSize = iCapacity; |
| 280 | + |
| 281 | + return true; |
| 282 | + } |
| 283 | + |
| 284 | + return false; |
| 285 | +} |
| 286 | + |
255 | 287 | ////////////////////////////////////////////////////////////////////////////////////////// |
256 | 288 | // |
257 | 289 | // Setup hooks for ClothesSpeedUp |
258 | 290 | // |
259 | 291 | ////////////////////////////////////////////////////////////////////////////////////////// |
260 | 292 | void CMultiplayerSA::InitHooks_ClothesSpeedUp() |
261 | 293 | { |
| 294 | + SetClothingDirectorySize(2050); |
| 295 | + |
262 | 296 | EZHookInstall(CStreamingLoadRequestedModels); |
263 | 297 | EZHookInstall(LoadingPlayerImgDir); |
264 | 298 | EZHookInstall(CallCStreamingInfoAddToList); |
|
0 commit comments