Skip to content

Commit e727d19

Browse files
committed
[BAD DESIGN] added IFP loader. It works properly, but the design is horrible. We'll need to properly rewrite it according to MTA's coding guidelines. Also, there is no function for unloading IFP, so yeah there are memory leaks. Dynamic memory allocation is used for sequeneces and key frames only, so freeing this memory is important.
1 parent 556bcec commit e727d19

File tree

9 files changed

+2239
-4
lines changed

9 files changed

+2239
-4
lines changed

Client/mods/deathmatch/logic/CClientIFP.cpp

Lines changed: 1142 additions & 2 deletions
Large diffs are not rendered by default.

Client/mods/deathmatch/logic/CClientIFP.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,55 @@
44
#define __CCLIENTIFP_H
55

66
#include "CClientEntity.h"
7+
#include "IFP/IFPLoader.h"
8+
#include <algorithm>
79

8-
class CClientIFP: public CClientEntity
10+
class CClientIFP: public CClientEntity, FileLoader
911
{
1012
public:
1113
CClientIFP ( class CClientManager* pManager, ElementID ID );
1214
~CClientIFP ( void );
1315

1416
virtual eClientEntityType GetType ( void ) const { return CCLIENTIFP; }
1517

16-
bool LoadIFP ( const char* szFilePath, const char* szBlockName );
18+
bool LoadIFP ( const char* szFilePath, SString strBlockName );
1719
void UnloadIFP ( void );
1820

21+
bool LoadIFPFile(const char * FilePath);
22+
void ReadIFPVersion1();
23+
void ReadIFPVersion2( bool anp3);
24+
25+
std::string convertStringToMapKey(char * String);
26+
IFP_FrameType getFrameTypeFromFourCC(char * FourCC);
27+
size_t GetSizeOfCompressedFrame ( IFP_FrameType FrameType );
28+
29+
void ReadKrtsFramesAsCompressed ( BYTE * pKeyFrames, int32_t TotalFrames );
30+
void ReadKrt0FramesAsCompressed ( BYTE * pKeyFrames, int32_t TotalFrames );
31+
void ReadKr00FramesAsCompressed ( BYTE * pKeyFrames, int32_t TotalFrames );
32+
33+
// Remove this ugly function and use ReadKr00FramesAsCompressed instead
34+
void ReadKr00FramesAsCompressed ( BYTE * pKeyFrames, int32_t TotalFrames, int32_t BoneID );
35+
36+
void insertAnimDummySequence(bool anp3, _CAnimBlendHierarchy * pAnimHierarchy, size_t SequenceIndex);
37+
int32_t getBoneIDFromName(std::string const& BoneName);
38+
std::string getCorrectBoneNameFromName(std::string const& BoneName);
39+
std::string getCorrectBoneNameFromID(int32_t & BoneID);
40+
size_t getCorrectBoneIndexFromID(int32_t & BoneID);
41+
1942
// Sorta a hack that these are required by CClientEntity...
2043
void Unlink ( void ) {};
2144
void GetPosition ( CVector& vecPosition ) const {};
2245
void SetPosition ( const CVector& vecPosition ) {};
2346

47+
48+
private:
49+
SString m_strBlockName;
50+
bool isVersion1;
51+
IFPHeaderV2 HeaderV2;
52+
std::vector <_CAnimBlendHierarchy> AnimationHierarchies;
53+
std::vector <_CAnimBlendSequence> AnimationSequences;
54+
unsigned char * KeyFramesArray;
55+
2456
};
2557

2658
#endif
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <StdInc.h>
2+
#include "wrapper.h"
3+
4+
h_CAnimBlendHierarchy_Constructor OLD__CAnimBlendHierarchy_Constructor = (h_CAnimBlendHierarchy_Constructor)0x4CF270;
5+
6+
void _CAnimBlendHierarchy_Constructor ( _CAnimBlendHierarchy * pAnimHierarchy )
7+
{
8+
int pThis = (int)pAnimHierarchy;
9+
10+
11+
*(DWORD *)(pThis + 4) = 0;
12+
*(WORD *)(pThis + 8) = 0;
13+
*(BYTE *)(pThis + 10) = 0;
14+
*(BYTE *)(pThis + 11) = 0;
15+
*(DWORD *)(pThis + 12) = -1;
16+
*(DWORD *)(pThis + 16) = 0;
17+
*(DWORD *)(pThis + 20) = 0;
18+
19+
}
20+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <StdInc.h>
2+
#include "wrapper.h"
3+
4+
h_CAnimBlendSequence_Constructor OLD__CAnimBlendSequence_Constructor = (h_CAnimBlendSequence_Constructor)0x4D0C10;
5+
h_CAnimBlendSequence_Deconstructor OLD__CAnimBlendSequence_Deconstructor = (h_CAnimBlendSequence_Deconstructor)0x4D0C30;
6+
7+
void _CAnimBlendSequence_Constructor (_CAnimBlendSequence * pSequence)
8+
{
9+
WORD * pThis = (WORD *)pSequence;
10+
11+
pThis[2] = 0;
12+
pThis[3] = 0;
13+
*((DWORD *)pThis + 2) = 0;
14+
*pThis = -1;
15+
}
16+
17+
/*
18+
// The keyframes will not be freed if the deconstructor is not there, but
19+
// it would be better to put the frames in a vector container for better control.
20+
// I prefer to not use the deconstructor, so I guess we don't need to uncomment this
21+
22+
_CAnimBlendSequence::~_CAnimBlendSequence()
23+
{
24+
OLD__CAnimBlendSequence_Deconstructor();
25+
}
26+
*/
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#pragma once
2+
#ifndef FILELOADER_H
3+
#define FILELOADER_H
4+
5+
#include <Windows.h>
6+
#include <iostream>
7+
#include <fstream>
8+
9+
class FileLoader
10+
{
11+
private:
12+
13+
const char * FilePath;
14+
FILE * FilePointer;
15+
char * FileDataBuffer;
16+
UINT FileLength = 0;
17+
UINT BytesReadFromBuffer = 0;
18+
19+
void setLoaderFilePath(const char * FileToRead)
20+
{
21+
FilePath = FileToRead;
22+
}
23+
24+
BOOL getFileHandle(void)
25+
{
26+
errno_t FileOpen = fopen_s(&FilePointer, FilePath, "rb");
27+
28+
if (FileOpen != 0)
29+
{
30+
std::cout << "Failed to open file";
31+
return FALSE;
32+
}
33+
34+
return TRUE;
35+
}
36+
37+
BOOL getFileLength(void)
38+
{
39+
if (!FilePointer)
40+
return FALSE;
41+
42+
if (fseek(FilePointer, 0, SEEK_END) != 0)
43+
{
44+
std::cout << "Failed to set cursor to end of file." << std::endl;
45+
return FALSE;
46+
}
47+
48+
FileLength = ftell(FilePointer);
49+
if (FileLength == -1L)
50+
{
51+
std::cout << "Failed to get length of file (ftell)" << std::endl;
52+
return FALSE;
53+
}
54+
55+
rewind(FilePointer);
56+
57+
return TRUE;
58+
}
59+
60+
void AllocateBufferMemory(void)
61+
{
62+
if (!FilePointer)
63+
return;
64+
65+
FileDataBuffer = new char[FileLength + 1];
66+
}
67+
68+
BOOL loadToMemory(void)
69+
{
70+
if (!FilePointer)
71+
return FALSE;
72+
73+
UINT ReadSize = fread(FileDataBuffer, sizeof(char), FileLength, FilePointer);
74+
75+
if (ReadSize != FileLength)
76+
{
77+
std::cout << "loadToMemory Failed. ReadSize != FileLength";
78+
return FALSE;
79+
}
80+
81+
return TRUE;
82+
}
83+
84+
85+
public:
86+
87+
~FileLoader(void)
88+
{
89+
unloadFile ();
90+
}
91+
92+
FileLoader(void)
93+
{
94+
95+
}
96+
97+
BOOL createLoader(const char * FileToRead)
98+
{
99+
setLoaderFilePath(FileToRead);
100+
101+
if (!getFileHandle() || !getFileLength())
102+
return FALSE;
103+
104+
AllocateBufferMemory();
105+
106+
FileDataBuffer[FileLength] = '\0';
107+
108+
return TRUE;
109+
}
110+
111+
BOOL loadFile(void)
112+
{
113+
if (!loadToMemory())
114+
return FALSE;
115+
116+
std::cout << "Length: " << FileLength << std::endl;
117+
return TRUE;
118+
}
119+
120+
// This function does not unload IFP data, to unload IFP call unloadIFP function
121+
void unloadFile(void)
122+
{
123+
if (FileDataBuffer != nullptr)
124+
{
125+
delete[] FileDataBuffer;
126+
fclose(FilePointer);
127+
128+
FileDataBuffer = nullptr;
129+
}
130+
}
131+
132+
void PrintReadOffset(void)
133+
{
134+
std::cout << "Bytes read from buffer: " << BytesReadFromBuffer << std::endl;
135+
}
136+
137+
138+
template < class T >
139+
void readBuffer ( T * Destination )
140+
{
141+
const UINT ReadOffset = BytesReadFromBuffer;
142+
BytesReadFromBuffer += sizeof ( T );
143+
144+
*Destination = *reinterpret_cast < T * > (FileDataBuffer + ReadOffset);
145+
146+
}
147+
148+
void readBytes(void * Destination, const UINT BytesToRead)
149+
{
150+
const UINT ReadOffset = BytesReadFromBuffer;
151+
BytesReadFromBuffer += BytesToRead;
152+
153+
memcpy(Destination, FileDataBuffer + ReadOffset, BytesToRead);
154+
}
155+
156+
std::string readString(UINT StringSizeInBytes)
157+
{
158+
std::string String;
159+
160+
String.resize(StringSizeInBytes);
161+
162+
for (UINT i = 0; i < StringSizeInBytes; i++)
163+
{
164+
const UINT ReadOffset = BytesReadFromBuffer;
165+
166+
String[i] = FileDataBuffer[ReadOffset];
167+
BytesReadFromBuffer++;
168+
}
169+
return String;
170+
}
171+
172+
void readCString (char * Destination, const UINT BytesToRead)
173+
{
174+
const UINT ReadOffset = BytesReadFromBuffer;
175+
BytesReadFromBuffer += BytesToRead;
176+
177+
memcpy(Destination, FileDataBuffer + ReadOffset, BytesToRead);
178+
179+
*(Destination + (BytesToRead - 1)) = '\0';
180+
}
181+
182+
void skipBytes(UINT TotalBytesToSkip)
183+
{
184+
BytesReadFromBuffer += TotalBytesToSkip;
185+
}
186+
};
187+
188+
#endif

0 commit comments

Comments
 (0)