OpenBarnyard
 
Loading...
Searching...
No Matches
BTECCompressor.cpp
Go to the documentation of this file.
1#include "ToshiPCH.h"
2#include "BTECCompressor.h"
3
4//-----------------------------------------------------------------------------
5// Enables memory debugging.
6// Note: Should be the last include!
7//-----------------------------------------------------------------------------
9
11
13{
14 this->m_Buffer1 = TNULL;
15 this->m_DataEnd = TNULL;
16 this->m_Buffer2 = TNULL;
17 this->m_Buffer3 = TNULL;
18 this->m_SomeArray1 = TNULL;
19 this->m_Buckets = TNULL;
20 this->m_BucketCount = 0;
21}
22
24{
25 TFree( m_SomeArray1 );
26
27 for ( TSIZE i = 0; i < m_BucketCount; i++ )
28 {
29 for ( TSIZE k = 0; k < 256; k++ )
30 {
31 TFree( m_Buckets[ i ][ k ] );
32 }
33
34 TFree( m_Buckets[ i ] );
35 }
36
37 TFree( m_Buckets );
38}
39
40void BTECCompressor::Initialize( TBYTE* buffer, TSIZE bufferSize, TINT maxoffset, TINT unk )
41{
42 // 0068ac60 +++
43 m_DataEnd = buffer + bufferSize;
44 m_Buffer1 = buffer;
45 m_Buffer2 = buffer;
46 m_Buffer3 = buffer;
47 m_MaxOffset = maxoffset;
48 m_BucketCount = ( unk < 1 ) ? 0 : unk - 1;
49
50 m_Root1.Reset();
51 m_Root2.Reset();
52
53 TSIZE arraySize1 = m_BucketCount * maxoffset;
54 m_SomeArray1 = (Node*)TMemalign( arraySize1 * sizeof( Node ), 16 );
55
56 for ( TSIZE i = 0; i < arraySize1; i++ )
57 {
58 m_SomeArray1[ i ].m_Ptr1 = &m_Root1;
59 m_SomeArray1[ i ].m_Ptr2 = m_Root1.m_Ptr2;
60 m_SomeArray1[ i ].m_Ptr1->m_Ptr2 = &m_SomeArray1[ i ];
61 m_SomeArray1[ i ].m_Ptr2->m_Ptr1 = &m_SomeArray1[ i ];
62 }
63
64 TUtil::MemClear( m_Offsets, sizeof( m_Offsets ) );
65
66 m_Buckets = (Bucket*)TMemalign( m_BucketCount * sizeof( Bucket ), 16 );
67
68 for ( TSIZE i = 0; i < m_BucketCount; i++ )
69 {
70 m_Buckets[ i ] = (Bucket)TMemalign( 256 * sizeof( Node* ), 16 );
71
72 for ( TSIZE k = 0; k < 256; k++ )
73 {
74 Node* someNode = new Node();
75 someNode->m_Unk1 = someNode;
76 someNode->m_Unk2 = someNode;
77 m_Buckets[ i ][ k ] = someNode;
78 }
79 }
80}
81
83{
84 // 0068ae40
85 auto oldBuffer3 = m_Buffer3;
86 auto newBuffer3 = m_Buffer3 + dataSize;
87
88 if ( m_DataEnd <= newBuffer3 && newBuffer3 != m_DataEnd )
89 {
90 newBuffer3 = m_DataEnd;
91 }
92
93 m_Buffer3 = newBuffer3;
94
95 if ( m_MaxOffset < static_cast<uintptr_t>( m_Buffer3 - m_Buffer2 ) )
96 {
97 m_Buffer2 = m_Buffer3 - m_MaxOffset;
98
99 for ( TSIZE i = 0; i < 256; i++ )
100 {
101 if ( m_Offsets[ i ] < m_Buffer2 )
102 {
103 m_Offsets[ i ] = TNULL;
104 }
105 }
106
107 auto node = m_Root2.m_Ptr1;
108 while ( node != &m_Root2 )
109 {
110 if ( m_Buffer2 <= node->m_Unk3 ) break;
111 auto nextNode = node->m_Ptr1;
112
113 node->m_Unk1->m_Unk2 = node->m_Unk2;
114 node->m_Unk2->m_Unk1 = node->m_Unk1;
115 node->m_Unk1 = node;
116 node->m_Unk2 = node;
117 node->m_Ptr1->m_Ptr2 = node->m_Ptr2;
118 node->m_Ptr2->m_Ptr1 = node->m_Ptr1;
119 node->m_Ptr1 = &m_Root1;
120 node->m_Ptr2 = m_Root1.m_Ptr2;
121 m_Root1.m_Ptr2 = node;
122 node->m_Ptr2->m_Ptr1 = node;
123
124 node = nextNode;
125 }
126 }
127
128 while ( oldBuffer3 < m_Buffer3 )
129 {
130 AllocSubstring( oldBuffer3 );
131 oldBuffer3++;
132 }
133}
134
135TBOOL BTECCompressor::FUN_0068af10( TBYTE* buffer, TSIZE bufferSize, TBYTE*& offset, TSIZE& dataSize )
136{
137 // +++
138 offset = TNULL;
139 dataSize = 0;
140
141 if ( bufferSize < 1 || m_Offsets[ (TBYTE)*buffer ] == TNULL )
142 {
143 return TFALSE;
144 }
145
146 if ( m_BucketCount > 0 )
147 {
148 TSIZE size = 0;
149 Node* node1 = TNULL;
150 Node* node2 = TNULL;
151 Bucket bucket = TNULL;
152
153 for ( TSIZE i = 0; i < m_BucketCount; i++ )
154 {
155 TSIZE localSize = 2 << ( i % 32 );
156 if ( bufferSize < localSize ) break;
157
158 Node* localNode1;
159 Node* localNode2;
160 TBOOL bRes = FUN_0068b300( buffer, m_Buckets[ i ], localSize, localNode1, localNode2 );
161 if ( bRes == TFALSE ) break;
162
163 size = localSize;
164 node1 = localNode1;
165 node2 = localNode2;
166 bucket = m_Buckets[ i ];
167 }
168
169 if ( node1 != TNULL )
170 {
171 TSIZE someSize;
172
173 if ( bucket == m_Buckets[ m_BucketCount - 1 ] )
174 {
175 someSize = TMath::Min( bufferSize, static_cast<TSIZE>( m_DataEnd - node1->m_Unk3 ) );
176 }
177 else
178 {
179 someSize = TMath::Min( bufferSize, size * 2 - 1 );
180 }
181
182 if ( node1 == node2 )
183 {
184 return TTRUE;
185 }
186
187 while ( TTRUE )
188 {
189 size = 0;
190
191 while ( node1->m_Unk3[ size ] == buffer[ size ] )
192 {
193 if ( someSize <= size ) break;
194 size++;
195 }
196
197 if ( dataSize < size )
198 {
199 dataSize = size;
200 offset = node1->m_Unk3;
201
202 if ( someSize <= size )
203 {
204 return TTRUE;
205 }
206 }
207
208 node1 = node1->m_Unk1;
209
210 if ( node1 == node2 )
211 {
212 return TTRUE;
213 }
214 }
215 }
216 }
217
218 offset = m_Offsets[ (TBYTE)*buffer ];
219 dataSize = 1;
220
221 return TTRUE;
222}
223
225{
226 // 0068b180 +++
227 m_Offsets[ (TBYTE)*buffer ] = buffer;
228
229 for ( TSIZE i = 0; i < m_BucketCount; i++ )
230 {
231 TSIZE unknown = 2 << ( i % 32 );
232
233 if ( static_cast<uintptr_t>( m_DataEnd - buffer ) < unknown )
234 {
235 return;
236 }
237
238 auto node = m_Root1.m_Ptr1;
239 if ( node == &m_Root1 )
240 {
241 TERROR( "SlidingWindow::AllocSubstring: No free substrings!\n" );
242 TBREAK();
243 return;
244 }
245
246 node->m_Ptr1->m_Ptr2 = node->m_Ptr2;
247 node->m_Ptr2->m_Ptr1 = node->m_Ptr1;
248 node->m_Ptr1 = &m_Root2;
249 node->m_Ptr2 = m_Root2.m_Ptr2;
250 m_Root2.m_Ptr2 = node;
251 node->m_Ptr2->m_Ptr1 = node;
252 node->m_Unk4 = (void*)( m_DataEnd - buffer );
253 node->m_Unk3 = buffer;
254
255 TUINT32 hash = HashData( buffer, unknown );
256
257 auto hashedNode = m_Buckets[ i ][ hash % 256 ];
258 node->m_Unk1 = hashedNode;
259 node->m_Unk2 = hashedNode->m_Unk2;
260 hashedNode->m_Unk2 = node;
261 node->m_Unk2->m_Unk1 = node;
262 }
263}
264
265TBOOL BTECCompressor::FUN_0068b300( TBYTE* buffer, Bucket nodeBucket, TSIZE bufferSize, Node*& out1, Node*& out2 )
266{
267 auto hash = HashData( buffer, bufferSize );
268 auto hashedNode = nodeBucket[ hash % 256 ];
269
270 out2 = hashedNode;
271 hashedNode = hashedNode->m_Unk1;
272 out1 = hashedNode;
273
274 while ( hashedNode != out2 )
275 {
276 TINT difference = Toshi::TUtil::MemCompare( out1->m_Unk3, buffer, bufferSize );
277 if ( difference == 0 ) break;
278
279 hashedNode = hashedNode->m_Unk1;
280 out1 = hashedNode;
281 }
282
283 return out1 != out2;
284}
285
void * TMemalign(TSIZE a_uiAlignment, TSIZE a_uiSize, Toshi::TMemory::MemBlock *a_pMemBlock)
Allocates aligned memory from a specific memory block.
Definition TMemory.cpp:1020
void TFree(void *a_pMem)
Frees previously allocated memory.
Definition TMemory.cpp:1054
#define TERROR(...)
Definition Defines.h:153
#define TBREAK()
Definition Defines.h:64
#define TOSHI_NAMESPACE_START
Definition Defines.h:47
#define TOSHI_NAMESPACE_END
Definition Defines.h:50
size_t TSIZE
Definition Typedefs.h:9
#define TNULL
Definition Typedefs.h:23
uint32_t TUINT32
Definition Typedefs.h:13
int TINT
Definition Typedefs.h:7
#define TFALSE
Definition Typedefs.h:24
#define TTRUE
Definition Typedefs.h:25
bool TBOOL
Definition Typedefs.h:6
uint8_t TBYTE
Definition Typedefs.h:19
TFORCEINLINE const T & Min(const T &a, const T &b)
void AllocSubstring(TBYTE *buffer)
static TBOOL FUN_0068b300(TBYTE *buffer, Bucket nodeBucket, size_t bufferSize, Node *&out1, Node *&out2)
void FUN_0068ae40(size_t dataSize)
TBOOL FUN_0068af10(TBYTE *buffer, size_t bufferSize, TBYTE *&offset, size_t &dataSize)
static TUINT32 HashData(TBYTE *data, size_t size)
void Initialize(TBYTE *buffer, size_t bufferSize, TINT maxoffset, TINT unk)
static void MemClear(void *ptr, TSIZE size)
Definition TUtil.h:91