@@ -13,8 +13,197 @@ class YAY0 : SlidingWindowAlgorithm
13
13
14
14
public override byte [ ] compress ( byte [ ] file , int offset )
15
15
{
16
- throw new NotImplementedException ( ) ;
16
+ List < byte > layoutBits = new List < byte > ( ) ;
17
+ List < byte > dictionary = new List < byte > ( ) ;
18
+
19
+ List < byte > uncompressedData = new List < byte > ( ) ;
20
+ List < int [ ] > compressedData = new List < int [ ] > ( ) ;
21
+
22
+ int maxDictionarySize = 4096 ;
23
+ int maxMatchLength = 255 + 0x12 ;
24
+ int minMatchLength = 3 ;
25
+ int decompressedSize = 0 ;
26
+
27
+ for ( int i = 0 ; i < file . Length ; i ++ )
28
+ {
29
+ if ( dictionary . Contains ( file [ i ] ) )
30
+ {
31
+ //check for best match
32
+ int [ ] matches = findAllMatches ( ref dictionary , file [ i ] ) ;
33
+ int [ ] bestMatch = findLargestMatch ( ref dictionary , matches , ref file , i , maxMatchLength ) ;
34
+
35
+ if ( bestMatch [ 1 ] >= minMatchLength )
36
+ {
37
+ //add to compressedData
38
+ layoutBits . Add ( 0 ) ;
39
+ bestMatch [ 0 ] = dictionary . Count - bestMatch [ 0 ] ; //sets offset in relation to end of dictionary
40
+
41
+ for ( int j = 0 ; j < bestMatch [ 1 ] ; j ++ )
42
+ {
43
+ dictionary . Add ( file [ i + j ] ) ;
44
+ }
45
+
46
+ i = i + bestMatch [ 1 ] - 1 ;
47
+
48
+ compressedData . Add ( bestMatch ) ;
49
+ decompressedSize += bestMatch [ 1 ] ;
50
+ }
51
+ else
52
+ {
53
+ //add to uncompressed data
54
+ layoutBits . Add ( 1 ) ;
55
+ uncompressedData . Add ( file [ i ] ) ;
56
+ dictionary . Add ( file [ i ] ) ;
57
+ decompressedSize ++ ;
58
+ }
59
+ }
60
+ else
61
+ {
62
+ //uncompressed data
63
+ layoutBits . Add ( 1 ) ;
64
+ uncompressedData . Add ( file [ i ] ) ;
65
+ dictionary . Add ( file [ i ] ) ;
66
+ decompressedSize ++ ;
67
+ }
68
+
69
+ if ( dictionary . Count > maxDictionarySize )
70
+ {
71
+ int overflow = dictionary . Count - maxDictionarySize ;
72
+ dictionary . RemoveRange ( 0 , overflow ) ;
73
+ }
74
+ }
75
+
76
+ return buildYAY0CompressedBlock ( ref layoutBits , ref uncompressedData , ref compressedData , decompressedSize , offset ) ;
17
77
}
78
+
79
+ public byte [ ] buildYAY0CompressedBlock ( ref List < byte > layoutBits , ref List < byte > uncompressedData , ref List < int [ ] > offsetLengthPairs , int decompressedSize , int offset )
80
+ {
81
+ List < byte > finalYAY0Block = new List < byte > ( ) ;
82
+ List < byte > layoutBytes = new List < byte > ( ) ;
83
+ List < byte > compressedDataBytes = new List < byte > ( ) ;
84
+ List < byte > extendedLengthBytes = new List < byte > ( ) ;
85
+
86
+ int compressedOffset = 16 + offset ; //header size
87
+ int uncompressedOffset ;
88
+
89
+ //add Yay0 magic number
90
+ finalYAY0Block . AddRange ( Encoding . ASCII . GetBytes ( "Yay0" ) ) ;
91
+
92
+ //add decompressed data size
93
+ byte [ ] decompressedSizeArray = BitConverter . GetBytes ( decompressedSize ) ;
94
+ Array . Reverse ( decompressedSizeArray ) ;
95
+ finalYAY0Block . AddRange ( decompressedSizeArray ) ;
96
+
97
+ //assemble layout bytes
98
+ while ( layoutBits . Count > 0 )
99
+ {
100
+ while ( layoutBits . Count < 8 )
101
+ {
102
+ layoutBits . Add ( 0 ) ;
103
+ }
104
+
105
+ string layoutBitsString = layoutBits [ 0 ] . ToString ( ) + layoutBits [ 1 ] . ToString ( ) + layoutBits [ 2 ] . ToString ( ) + layoutBits [ 3 ] . ToString ( )
106
+ + layoutBits [ 4 ] . ToString ( ) + layoutBits [ 5 ] . ToString ( ) + layoutBits [ 6 ] . ToString ( ) + layoutBits [ 7 ] . ToString ( ) ;
107
+
108
+ byte [ ] layoutByteArray = new byte [ 1 ] ;
109
+ layoutByteArray [ 0 ] = Convert . ToByte ( layoutBitsString , 2 ) ;
110
+ layoutBytes . Add ( layoutByteArray [ 0 ] ) ;
111
+ layoutBits . RemoveRange ( 0 , ( layoutBits . Count < 8 ) ? layoutBits . Count : 8 ) ;
112
+
113
+ }
114
+
115
+ //assemble offsetLength shorts
116
+ foreach ( int [ ] offsetLengthPair in offsetLengthPairs )
117
+ {
118
+ //if < 18, set 4 bits -2 as matchLength
119
+ //if >= 18, set matchLength == 0, write length to new byte - 0x12
120
+
121
+ int adjustedOffset = offsetLengthPair [ 0 ] ;
122
+ int adjustedLength = ( offsetLengthPair [ 1 ] >= 18 ) ? 0 : offsetLengthPair [ 1 ] - 2 ; //vital, 4 bit range is 0-15. Number must be at least 3 (if 2, when -2 is done, it will think it is 3 byte format), -2 is how it can store up to 17 without an extra byte because +2 will be added on decompression
123
+
124
+ int compressedInt = ( ( adjustedLength << 12 ) | adjustedOffset - 1 ) ;
125
+
126
+ byte [ ] compressed2Byte = new byte [ 2 ] ;
127
+ compressed2Byte [ 0 ] = ( byte ) ( compressedInt & 0XFF ) ;
128
+ compressed2Byte [ 1 ] = ( byte ) ( ( compressedInt >> 8 ) & 0xFF ) ;
129
+
130
+ compressedDataBytes . Add ( compressed2Byte [ 1 ] ) ;
131
+ compressedDataBytes . Add ( compressed2Byte [ 0 ] ) ;
132
+
133
+ if ( adjustedLength == 0 )
134
+ {
135
+ extendedLengthBytes . Add ( ( byte ) ( offsetLengthPair [ 1 ] - 18 ) ) ;
136
+ }
137
+ }
138
+
139
+ //pad layout bits if needed
140
+ while ( layoutBytes . Count % 4 != 0 )
141
+ {
142
+ layoutBytes . Add ( 0 ) ;
143
+ }
144
+
145
+ compressedOffset += layoutBytes . Count ;
146
+
147
+ //add final compresseed offset
148
+ byte [ ] compressedOffsetArray = BitConverter . GetBytes ( compressedOffset ) ;
149
+ Array . Reverse ( compressedOffsetArray ) ;
150
+ finalYAY0Block . AddRange ( compressedOffsetArray ) ;
151
+
152
+ //add final uncompressed offset
153
+ uncompressedOffset = compressedOffset + compressedDataBytes . Count ;
154
+ byte [ ] uncompressedOffsetArray = BitConverter . GetBytes ( uncompressedOffset ) ;
155
+ Array . Reverse ( uncompressedOffsetArray ) ;
156
+ finalYAY0Block . AddRange ( uncompressedOffsetArray ) ;
157
+
158
+ //add layout bits
159
+ foreach ( byte layoutByte in layoutBytes ) //add layout bytes to file
160
+ {
161
+ finalYAY0Block . Add ( layoutByte ) ;
162
+ }
163
+
164
+ //add compressed data
165
+ foreach ( byte compressedByte in compressedDataBytes ) //add compressed bytes to file
166
+ {
167
+ finalYAY0Block . Add ( compressedByte ) ;
168
+ }
169
+
170
+ //non-compressed/additional-length bytes
171
+ {
172
+ for ( int i = 0 ; i < layoutBytes . Count ; i ++ )
173
+ {
174
+ BitArray arrayOfBits = new BitArray ( new byte [ 1 ] { layoutBytes [ i ] } ) ;
175
+
176
+ for ( int j = 7 ; j > - 1 && finalYAY0Block . Count < decompressedSize ; j -- )
177
+ {
178
+ if ( arrayOfBits [ j ] == true )
179
+ {
180
+ finalYAY0Block . Add ( uncompressedData [ 0 ] ) ;
181
+ uncompressedData . RemoveAt ( 0 ) ;
182
+ }
183
+ else
184
+ {
185
+ if ( compressedDataBytes . Count > 0 )
186
+ {
187
+ int length = compressedDataBytes [ 0 ] >> 4 ;
188
+ compressedDataBytes . RemoveRange ( 0 , 2 ) ;
189
+
190
+ if ( length == 0 )
191
+ {
192
+ finalYAY0Block . Add ( extendedLengthBytes [ 0 ] ) ;
193
+ extendedLengthBytes . RemoveAt ( 0 ) ;
194
+ }
195
+
196
+
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }
202
+
203
+ return finalYAY0Block . ToArray ( ) ;
204
+ }
205
+
206
+
18
207
public override byte [ ] decompress ( BinaryReader br , int offset , FileStream inputFile )
19
208
{
20
209
List < byte > newFile = new List < byte > ( ) ;
0 commit comments