OpenBarnyard
 
Loading...
Searching...
No Matches
TCompress_Decompress.cpp
Go to the documentation of this file.
1#include "ToshiPCH.h"
2#include "TCompress.h"
3
4//-----------------------------------------------------------------------------
5// Enables memory debugging.
6// Note: Should be the last include!
7//-----------------------------------------------------------------------------
9
11
12// $Barnyard: FUNCTION 006dc4f0
13uintptr_t TCompress::Decompress( TFile* file, TCompress::Header* header, TBYTE* buffer, TUINT32 bufferSize )
14{
16
17 if ( header->Magic != TFourCC( "BTEC" ) )
19 if ( header->Version != TVERSION( 1, 2 ) && header->Version != TVERSION( 1, 3 ) )
21 if ( header->Size > bufferSize )
23
24 TBYTE* pBufferPos = buffer;
25 TUINT32 compressedLeft = header->CompressedSize;
26
27 while ( compressedLeft > 0 )
28 {
29 TUINT32 chunkSize;
30 TBOOL noOffset;
31 TINT offset;
32
33 compressedLeft -= GetCommand( file, noOffset, chunkSize, offset );
34
35 if ( !noOffset )
36 {
37 // The data is already unpacked so just copy it
38 TBYTE* unpackedData = pBufferPos - offset;
39
40 while ( chunkSize > 0 )
41 {
42 *( pBufferPos++ ) = *( unpackedData++ );
43 chunkSize--;
44 }
45 }
46 else
47 {
48 // The data wasn't previously unpacked, read it from file
49 TSIZE readedCount = file->Read( pBufferPos, chunkSize );
50 pBufferPos += readedCount;
51 compressedLeft -= readedCount;
52 }
53 }
54
55 if ( header->Version == TVERSION( 1, 3 ) )
56 {
57 pBufferPos = buffer;
58 for ( TSIZE i = 0; i < header->Size; i++, pBufferPos++ )
59 {
60 *pBufferPos ^= header->XorValue;
61 }
62 }
63
64 uintptr_t sizeDecompressed = pBufferPos - buffer;
65 TASSERT( sizeDecompressed == header->Size, "Wrong decompressed size" );
66
67 return sizeDecompressed;
68}
69
70// $Barnyard: FUNCTION 006dc220
71int8_t TCompress::GetHeader( TFile* file, TCompress::Header& btecHeader )
72{
74 TUINT32 savedPos = file->Tell();
75 TSIZE readedSize = file->Read( &btecHeader, headerSize );
76
77 if ( ms_bIsBigEndian )
78 {
79 btecHeader.Size = CONVERTENDIANESS( Endianess_Big, btecHeader.Size );
80 btecHeader.CompressedSize = CONVERTENDIANESS( Endianess_Big, btecHeader.CompressedSize );
81 btecHeader.Magic = CONVERTENDIANESS( Endianess_Big, btecHeader.Magic );
82 btecHeader.Version = CONVERTENDIANESS( Endianess_Big, btecHeader.Version.Value );
83 }
84
85 if ( btecHeader.Version == TVERSION( 1, 3 ) )
86 {
87 readedSize += file->Read( &btecHeader.XorValue, sizeof( TCompress::Header::XorValue ) );
88 headerSize += sizeof( TCompress::Header::XorValue );
89
90 if ( ms_bIsBigEndian )
91 {
92 btecHeader.XorValue = CONVERTENDIANESS( Endianess_Big, btecHeader.XorValue );
93 }
94 }
95
96 if ( readedSize != headerSize )
97 {
98 file->Seek( savedPos, TSEEK_SET );
100 }
101
102 if ( btecHeader.Magic != TFourCC( "BTEC" ) )
103 {
104 file->Seek( savedPos, TSEEK_SET );
106 }
107
108 return TCOMPRESS_ERROR_OK;
109}
110
111// With the help of Revel8n approach
112// Could use some code cleanup
113// $Barnyard: FUNCTION 006dc340
114TINT TCompress::GetCommand( TFile* file, TBOOL& noOffset, TUINT32& size, TINT& offset )
115{
116 TINT read_count = file->Read( &size, 1 );
117 TBOOL isBigSize = size & BTECSizeFlag_BigSize;
118 noOffset = size & BTECSizeFlag_NoOffset;
119 offset = -1;
120
121 // by default size is 6 bits long
122 size &= BTECSizeFlag_SizeMask;
123
124 if ( isBigSize )
125 {
126 // now the size is 14 bits long
127 uint8_t secondByte;
128 read_count += file->Read( &secondByte, 1 );
129 size = ( size << 8 ) | secondByte;
130 }
131
132 if ( !noOffset )
133 {
134 // by default offset is 7 bits long
135 read_count += file->Read( &offset, 1 );
136 TBOOL bigOffset = offset & BTECOffsetFlag_BigOffset;
138
139 if ( bigOffset )
140 {
141 // now the offset is 15 bits long
142 uint8_t secondByte;
143 read_count += file->Read( &secondByte, 1 );
144 offset = ( offset << 8 ) | secondByte;
145 }
146 }
147
148 size += 1;
149 offset += 1;
150
151 return read_count;
152}
153
@ TCOMPRESS_ERROR_WRONG_MAGIC
Definition TCompress.h:10
@ TCOMPRESS_ERROR_WRONG_HEADERSIZE
Definition TCompress.h:13
@ TCOMPRESS_ERROR_WRONG_SIZE
Definition TCompress.h:12
@ TCOMPRESS_ERROR_OK
Definition TCompress.h:9
@ TCOMPRESS_ERROR_WRONG_VERSION
Definition TCompress.h:11
@ BTECSizeFlag_NoOffset
Definition TCompress.h:19
@ BTECSizeFlag_BigSize
Definition TCompress.h:18
@ BTECSizeFlag_SizeMask
Definition TCompress.h:20
@ BTECOffsetFlag_BigOffset
Definition TCompress.h:25
@ BTECOffsetFlag_OffsetMask
Definition TCompress.h:26
@ TSEEK_SET
Definition TFile.h:30
#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
@ Endianess_Big
Definition Endianness.h:9
TFORCEINLINE constexpr TUINT32 TFourCC(const TCHAR str[4])
Definition Helpers.h:15
#define TPROFILER_SCOPE()
Definition Profiler.h:17
size_t TSIZE
Definition Typedefs.h:9
uint32_t TUINT32
Definition Typedefs.h:13
int TINT
Definition Typedefs.h:7
bool TBOOL
Definition Typedefs.h:6
uint8_t TBYTE
Definition Typedefs.h:19
static TINT GetCommand(TFile *file, TBOOL &hasOffset, TUINT32 &size, TINT &offset)
static TBOOL ms_bIsBigEndian
Definition TCompress.h:52
static constexpr TUINT32 HEADER_SIZE_12
Definition TCompress.h:46
static uintptr_t Decompress(TFile *file, TCompress::Header *header, TBYTE *buffer, TUINT32 bufferSize)
static int8_t GetHeader(TFile *file, TCompress::Header &btecHeader)
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 Read(void *a_pDst, TSIZE a_uiSize)=0
Reads specified number of bytes from the file into the buffer.
TUINT32 Value
Definition TVersion.h:8