OpenBarnyard
 
Loading...
Searching...
No Matches
TCompress_Compress.cpp
Go to the documentation of this file.
1#include "ToshiPCH.h"
2#include "TCompress.h"
3#include "BTECCompressor.h"
4
5//-----------------------------------------------------------------------------
6// Enables memory debugging.
7// Note: Should be the last include!
8//-----------------------------------------------------------------------------
10
12
14
15TINT TCompress::Write( TUINT32 length, TBYTE*& data, TFile* file )
16{
17 // 0068a830
18 TASSERT( length <= maxlength );
19
20 TINT writtenSize = 0;
21 TUINT32 dataSize = length;
22
23 length -= 1;
24
25 if ( length < BTECSizeFlag_BigSize )
26 {
27 // 6 bits value
28 LOWBYTE( length ) = length | BTECSizeFlag_NoOffset;
29 writtenSize += file->Write( &length, 1 );
30 }
31 else
32 {
33 // 14 bits value
34 auto len = length;
35 LOWBYTE( length ) = HIGHBYTE( length ) | ( BTECSizeFlag_NoOffset | BTECSizeFlag_BigSize );
36 BYTE1( length ) = len;
37 writtenSize += file->Write( &length, 2 );
38 }
39
40 writtenSize += file->Write( data, dataSize );
41 data += dataSize;
42
43 return writtenSize;
44}
45
46TINT TCompress::WriteOffset( TUINT32 length, TINT offset, TBYTE*& data, TFile* file )
47{
48 // 0068a8c0
49 TASSERT( length <= maxlength );
50 TASSERT( offset <= usemaxoffset );
51
52 TINT writtenSize = 0;
53 TUINT32 dataSize = length;
54
55 length -= 1;
56 offset -= 1;
57
58 if ( length < BTECSizeFlag_BigSize )
59 {
60 LOWBYTE( length ) = length;
61 writtenSize += file->Write( &length, 1 );
62 }
63 else
64 {
65 auto len = length;
66 LOWBYTE( length ) = HIGHBYTE( length ) | BTECSizeFlag_BigSize;
67 BYTE1( length ) = len;
68 writtenSize += file->Write( &length, 2 );
69 }
70
71 if ( offset <= BTECOffsetFlag_BigOffset )
72 {
73 LOWBYTE( offset ) = offset;
74 writtenSize += file->Write( &offset, 1 );
75 }
76 else
77 {
78 auto _offset = offset;
79 LOWBYTE( offset ) = HIGHBYTE( offset ) | BTECOffsetFlag_BigOffset;
80 BYTE1( offset ) = _offset;
81 writtenSize += file->Write( &offset, 2 );
82 }
83
84 data += dataSize;
85
86 return writtenSize;
87}
88
89TSIZE TCompress::Compress( TFile* file, TBYTE* buffer, TUINT32 size, TUINT32 unused, TBOOL isBigEndian )
90{
91 BTECCompressor compressor;
92
93 usemaxoffset = 0x8000;
94 compressor.Initialize( buffer, size, usemaxoffset, 3 );
95
96 TBYTE* bufferPos = buffer;
97 TBYTE* bufferEnd = buffer + size;
98
99 auto initialPos = file->Tell();
101
102 TSIZE compressedSize = 0;
103 TSIZE chunkSize = 0;
104 TBYTE* chunkStart = TNULL;
105
106 while ( bufferPos < bufferEnd )
107 {
108 TSIZE uncompressedLeft = TMath::Min<TSIZE>( size - ( bufferPos - buffer ), maxlength );
109
110 TBYTE* offset = TNULL;
111 TSIZE dataSize = 0;
112 TBOOL hasOffset = compressor.FUN_0068af10( bufferPos, uncompressedLeft, offset, dataSize );
113
114 if ( hasOffset == TFALSE || dataSize < 3 )
115 {
116 dataSize = 1;
117
118 // Check if we have to start a new chunk
119 if ( chunkStart == TNULL ) chunkStart = bufferPos;
120 chunkSize += 1;
121
122 if ( maxlength <= chunkSize )
123 {
124 // Write a chunk of data
125 compressedSize += TCompress::Write( chunkSize, chunkStart, file );
126 chunkStart = TNULL;
127 chunkSize = 0;
128 }
129
130 bufferPos += 1;
131 }
132 else
133 {
134 if ( chunkStart != TNULL )
135 {
136 // We found an offset but we have a not-written chunk of data so write it
137 compressedSize += TCompress::Write( chunkSize, chunkStart, file );
138 chunkStart = TNULL;
139 chunkSize = 0;
140 }
141
142 compressedSize += TCompress::WriteOffset( dataSize, bufferPos - offset, bufferPos, file );
143 }
144
145 compressor.FUN_0068ae40( dataSize );
146 }
147
148 if ( chunkStart != TNULL )
149 {
150 // We are out of the while loop but still have some chunk of data that should be written
151 compressedSize += TCompress::Write( chunkSize, chunkStart, file );
152 }
153
154 TCompress::Header btecHeader;
155 btecHeader.Magic = TFourCC( "BTEC" );
156 btecHeader.Version = TVERSION( 1, 2 );
157 btecHeader.CompressedSize = compressedSize;
158 btecHeader.Size = size;
159
160 if ( isBigEndian )
161 {
162 btecHeader.Magic = PARSEDWORD_BIG( btecHeader.Magic );
163 btecHeader.Version = PARSEDWORD_BIG( btecHeader.Version );
164 btecHeader.CompressedSize = PARSEDWORD_BIG( btecHeader.CompressedSize );
165 btecHeader.Size = PARSEDWORD_BIG( btecHeader.Size );
166 }
167
168 file->Seek( initialPos, TSEEK_SET );
169 file->Write( &btecHeader, TCompress::HEADER_SIZE_12 );
170 file->Seek( compressedSize, TSEEK_CUR );
171
172 return compressedSize;
173}
174
@ BTECSizeFlag_NoOffset
Definition TCompress.h:19
@ BTECSizeFlag_BigSize
Definition TCompress.h:18
@ BTECOffsetFlag_BigOffset
Definition TCompress.h:25
@ TSEEK_SET
Definition TFile.h:30
@ TSEEK_CUR
Definition TFile.h:31
#define TASSERT(X,...)
Definition Defines.h:138
#define TOSHI_NAMESPACE_START
Definition Defines.h:47
#define TVERSION(VER_MAJOR, VER_MINOR)
Definition Defines.h:14
#define TOSHI_NAMESPACE_END
Definition Defines.h:50
TFORCEINLINE constexpr TUINT32 TFourCC(const TCHAR str[4])
Definition Helpers.h:15
#define LOWBYTE(x)
Definition Typedefs.h:32
#define HIGHBYTE(x)
Definition Typedefs.h:35
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
bool TBOOL
Definition Typedefs.h:6
uint8_t TBYTE
Definition Typedefs.h:19
#define BYTE1(x)
Definition Typedefs.h:41
TFORCEINLINE const T & Min(const T &a, const T &b)
void FUN_0068ae40(size_t dataSize)
TBOOL FUN_0068af10(TBYTE *buffer, size_t bufferSize, TBYTE *&offset, size_t &dataSize)
void Initialize(TBYTE *buffer, size_t bufferSize, TINT maxoffset, TINT unk)
static constexpr TUINT32 HEADER_SIZE_12
Definition TCompress.h:46
static constexpr TINT maxlength
Definition TCompress.h:59
static size_t Compress(TFile *file, TBYTE *data, TUINT32 size, TUINT32 unused, TBOOL isBigEndian)
static TINT usemaxoffset
Definition TCompress.h:60
TVersion Version
Definition TCompress.h:39
TUINT32 CompressedSize
Definition TCompress.h:40
Definition TFile.h:128
virtual TBOOL Seek(TINT a_iOffset, TSEEK a_eOrigin=TSEEK_CUR)=0
Shifts current file cursor based on the specified offset and origin.
virtual TSIZE Tell()=0
virtual TSIZE Write(const void *a_pSrc, TSIZE a_uiSize)=0
Writes specified number of bytes to the file from the buffer.