pedump 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: binary
3
+ require 'pedump/loader'
4
+ require 'pedump/cli'
5
+
6
+ module PEdump::Unpacker; end
7
+
8
+ class PEdump::Unpacker::UPX
9
+ def self.unpack src_fname, dst_fname, log = ''
10
+ log << `upx -dqq #{src_fname} -o #{dst_fname} 2>&1`
11
+ $?.success?
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ class PEdump
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 5
5
+ PATCH = 2
6
+ BUILD = nil
7
+
8
+ STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
9
+ end
10
+ end
@@ -0,0 +1,171 @@
1
+ class PEdump
2
+ class VS_VERSIONINFO < IOStruct.new( 'v3a32v',
3
+ :wLength,
4
+ :wValueLength,
5
+ :wType,
6
+ :szKey, # The Unicode string L"VS_VERSION_INFO".
7
+ :Padding1,
8
+ # manual:
9
+ :Value, # VS_FIXEDFILEINFO
10
+ :Padding2,
11
+ :Children
12
+ )
13
+ def self.read f, size = SIZE
14
+ super.tap do |vi|
15
+ vi.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
16
+ vi.Padding1 = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
17
+ vi.Value = VS_FIXEDFILEINFO.read(f,vi.wValueLength)
18
+ # As many zero words as necessary to align the Children member on a 32-bit boundary.
19
+ # These bytes are not included in wValueLength. This member is optional.
20
+ vi.Padding2 = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
21
+ vi.Children = [] # An array of zero or one StringFileInfo structures,
22
+ # and zero or one VarFileInfo structures
23
+
24
+ 2.times do
25
+ pos = f.tell
26
+ f.seek(pos+6) # seek 6 bytes forward
27
+ t = f.read(6)
28
+ f.seek(pos) # return back
29
+ case t
30
+ when "V\x00a\x00r\x00"
31
+ vi.Children << VarFileInfo.read(f)
32
+ when "S\x00t\x00r\x00"
33
+ vi.Children << StringFileInfo.read(f)
34
+ else
35
+ PEdump.logger.warn "[?] invalid VS_VERSIONINFO child type #{t.inspect}"
36
+ break
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ class VS_FIXEDFILEINFO < IOStruct.new( 'V13',
44
+ :dwSignature,
45
+ :dwStrucVersion,
46
+ :dwFileVersionMS,
47
+ :dwFileVersionLS,
48
+ :dwProductVersionMS,
49
+ :dwProductVersionLS,
50
+ :dwFileFlagsMask,
51
+ :dwFileFlags,
52
+ :dwFileOS,
53
+ :dwFileType,
54
+ :dwFileSubtype,
55
+ :dwFileDateMS,
56
+ :dwFileDateLS,
57
+ # manual:
58
+ :valid
59
+ )
60
+ def self.read f, size = SIZE
61
+ super.tap do |ffi|
62
+ ffi.valid = (ffi.dwSignature == 0xFEEF04BD)
63
+ end
64
+ end
65
+ end
66
+
67
+ class StringFileInfo < IOStruct.new( 'v3a30',
68
+ :wLength,
69
+ :wValueLength, # always 0
70
+ :wType, # 1 => text data, 0 => binary data
71
+ :szKey, # The Unicode string L"StringFileInfo"
72
+ :Padding, # As many zero words as necessary to align the Children member on a 32-bit boundary
73
+ :Children # An array of one or more StringTable structures
74
+ )
75
+ def self.read f, size = SIZE
76
+ pos0 = f.tell
77
+ super.tap do |x|
78
+ x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
79
+ x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
80
+ x.Children = []
81
+ while !f.eof? && f.tell < pos0+x.wLength
82
+ x.Children << StringTable.read(f)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ class StringTable < IOStruct.new( 'v3a16v',
89
+ :wLength, # The length, in bytes, of this StringTable structure,
90
+ # including all structures indicated by the Children member.
91
+ :wValueLength, # always 0
92
+ :wType, # 1 => text data, 0 => binary data
93
+ :szKey, # An 8-digit hexadecimal number stored as a Unicode string
94
+ :Padding, # As many zero words as necessary to align the Children member on a 32-bit boundary
95
+ :Children # An array of one or more String structures.
96
+ )
97
+ def self.read f, size = SIZE
98
+ pos0 = f.tell
99
+ super.tap do |x|
100
+ x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
101
+ x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
102
+ x.Children = []
103
+ while !f.eof? && f.tell < pos0+x.wLength
104
+ x.Children << VersionString.read(f)
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ class VersionString < IOStruct.new( 'v3',
111
+ :wLength, # The length, in bytes, of this String structure.
112
+ :wValueLength, # The size, in words, of the Value member
113
+ :wType, # 1 => text data, 0 => binary data
114
+ :szKey, # An arbitrary Unicode string
115
+ :Padding, # As many zero words as necessary to align the Value member on a 32-bit boundary
116
+ :Value # A zero-terminated string. See the szKey member description for more information
117
+ )
118
+ def self.read f, size = SIZE
119
+ pos = f.tell
120
+ super.tap do |x|
121
+ x.szKey = ''
122
+ x.szKey << f.read(2) until x.szKey[-2..-1] == "\x00\x00" || f.eof?
123
+ x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
124
+
125
+ value_len = [x.wValueLength*2, x.wLength - (f.tell-pos)].min
126
+ value_len = 0 if value_len < 0
127
+
128
+ x.Value = f.read(value_len)
129
+ if f.tell%4 > 0
130
+ f.read(4-f.tell%4) # undoc padding?
131
+ end
132
+ x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000+$/,'') rescue nil
133
+ x.Value.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000+$/,'') rescue nil
134
+ end
135
+ end
136
+ end
137
+
138
+ class VarFileInfo < IOStruct.new( 'v3a24v',
139
+ :wLength,
140
+ :wValueLength, # always 0
141
+ :wType, # 1 => text data, 0 => binary data
142
+ :szKey, # The Unicode string L"VarFileInfo"
143
+ :Padding, # As many zero words as necessary to align the Children member on a 32-bit boundary
144
+ :Children # Typically contains a list of languages that the application or DLL supports
145
+ )
146
+ def self.read f, size = SIZE
147
+ super.tap do |x|
148
+ x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
149
+ x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
150
+ x.Children = Var.read(f)
151
+ end
152
+ end
153
+ end
154
+
155
+ class Var < IOStruct.new( 'v3a24',
156
+ :wLength,
157
+ :wValueLength, # The length, in bytes, of the Value member
158
+ :wType, # 1 => text data, 0 => binary data
159
+ :szKey, # The Unicode string L"Translation"
160
+ :Padding, # As many zero words as necessary to align the Children member on a 32-bit boundary
161
+ :Value # An array of one or more values that are language and code page identifier pairs
162
+ )
163
+ def self.read f, size = SIZE
164
+ super.tap do |x|
165
+ x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
166
+ x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
167
+ x.Value = f.read(x.wValueLength).unpack('v*')
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,3 @@
1
+ all: aspack_unlzx
2
+ aspack_unlzx:
3
+ gcc aspack_unlzx.c -o aspack_unlzx
@@ -0,0 +1,92 @@
1
+ #include <stdlib.h>
2
+ #include <stdio.h>
3
+ #include <strings.h> // for bzero()
4
+
5
+ #include "lzxdec.c"
6
+
7
+ // based on ASPack Unpacker v1.00 by Dr.Golova (thx! :)
8
+
9
+ /* error codes for unpacker thread */
10
+ #define ERR_OK (0)
11
+ #define ERR_NO_FILE (1)
12
+ #define ERR_FILE_OPEN (2)
13
+ #define ERR_NO_MEM (3)
14
+ #define ERR_CANT_MAP (4)
15
+ #define ERR_FILE_CREATE (5)
16
+ #define ERR_FILE_WRITE (6)
17
+ #define ERR_COPY_OVL (7)
18
+ #define ERR_CORRUPT (8)
19
+ #define ERR_UNKNOWN (9)
20
+ #define ERR_SKIPPED (10)
21
+ #define ERR_UNPACK (11)
22
+ #define ERR_FAILED (12)
23
+
24
+
25
+ void write_result(void*buf, int size){
26
+ fwrite(buf,1,size,stdout);
27
+ }
28
+
29
+ int unpack(BYTE*packed_data, size_t packed_size, size_t unpacked_size){
30
+ LZX_CONTEXT LZX;
31
+ BYTE* unpacked_data = NULL;
32
+ size_t decoded_size;
33
+
34
+ bzero(&LZX, sizeof(LZX));
35
+
36
+ if ( NULL == (unpacked_data = calloc(1, unpacked_size + 300)) ){
37
+ perror("no mem");
38
+ return(ERR_NO_MEM);
39
+ }
40
+
41
+ decoded_size = DecodeLZX(&LZX, packed_data, unpacked_data, packed_size, unpacked_size);
42
+ if ( decoded_size < 0 || decoded_size < unpacked_size ) {
43
+ free(unpacked_data);
44
+ fprintf(stderr,"ERR_UNPACK\n");
45
+ return(ERR_UNPACK);
46
+ }
47
+
48
+ write_result(unpacked_data, decoded_size);
49
+ free(unpacked_data);
50
+ return 0;
51
+ }
52
+
53
+ int main(int argc, char*argv[]){
54
+ size_t packed_size, unpacked_size;
55
+ BYTE* packed_data = NULL;
56
+ int r;
57
+
58
+ if(argc != 3){
59
+ fprintf(stderr, "ASPack unLZX\n");
60
+ fprintf(stderr, "usage: %s <packed_size> <unpacked_size>\n", argv[0]);
61
+ fprintf(stderr, "(data is read from stdin and written to stdout)\n", argv[0]);
62
+ return 1;
63
+ }
64
+
65
+ sscanf(argv[1],"%zu",&packed_size);
66
+ if( packed_size < 1 || packed_size > 0x10000000 ){ // 256 Mb max
67
+ fprintf(stderr, "invalid packed_size: %zu\n", packed_size);
68
+ return 1;
69
+ }
70
+
71
+ sscanf(argv[2],"%zu",&unpacked_size);
72
+ if( unpacked_size < 1 || unpacked_size > 0x10000000 ){ // 256 Mb max
73
+ fprintf(stderr, "invalid unpacked_size: %zu\n", unpacked_size);
74
+ return 1;
75
+ }
76
+
77
+ /* alloc buffer */
78
+ if ( NULL == (packed_data = calloc(1, packed_size + 300)) ){
79
+ perror("no mem");
80
+ return(ERR_NO_MEM);
81
+ }
82
+
83
+ if( packed_size != fread(packed_data, 1, packed_size, stdin)){
84
+ free(packed_data);
85
+ perror("read");
86
+ return(ERR_NO_FILE);
87
+ }
88
+
89
+ r = unpack(packed_data, packed_size, unpacked_size);
90
+ free(packed_data);
91
+ return r;
92
+ }
@@ -0,0 +1,479 @@
1
+ //#include <windows.h>
2
+
3
+ typedef unsigned char BYTE;
4
+ typedef int INT;
5
+ typedef unsigned int UINT;
6
+ typedef unsigned long DWORD;
7
+ typedef int BOOL;
8
+
9
+ #define FALSE 0
10
+ #define TRUE 1
11
+
12
+ #include "lzxdec.h"
13
+
14
+ /* #define LZX_DEBUG_LOG */
15
+
16
+ #if defined _DEBUG && defined LZX_DEBUG_LOG
17
+ # include <stdio.h>
18
+ static FILE* FDebLog = NULL;
19
+ #endif
20
+
21
+ /* ##### *** COMMON FUNCTIONS *** ########################################## */
22
+
23
+ /* memset local redefinition */
24
+ static void lzx_memset(void* dst, int val, unsigned int count)
25
+ {
26
+ while( count-- )
27
+ {
28
+ *(char*)(dst) = val;
29
+ dst = (char*)(dst) + 1;
30
+ }
31
+ }
32
+
33
+ /* memcpy local redefinition */
34
+ static void lzx_memcpy(void* dst, void* src, unsigned int count)
35
+ {
36
+ while( count-- )
37
+ {
38
+ *(char*)(dst) = *(char*)(src);
39
+ dst = (char*)(dst) + 1;
40
+ src = (char*)(src) + 1;
41
+ }
42
+ }
43
+
44
+ /* ##### *** BIT READER FUNCTIONS *** ###################################### */
45
+
46
+ /* init bit reader */
47
+ #define BITRDR_INIT(BitRdr, RawSrc, RawLen) { \
48
+ (BitRdr)->SrcData = (RawSrc); \
49
+ (BitRdr)->SrcSize = (RawLen); \
50
+ (BitRdr)->CurOffs = 0; \
51
+ (BitRdr)->BitBuff = 0; \
52
+ (BitRdr)->BitFree = 32; \
53
+ }
54
+
55
+ /* read input byte (can be rewritten for file io) */
56
+ #define BITRDR_GETBYTE(BitRdr, RetVal) { \
57
+ if ( (BitRdr)->CurOffs < (BitRdr)->SrcSize ) \
58
+ RetVal = (BitRdr)->SrcData[(BitRdr)->CurOffs++]; \
59
+ else \
60
+ return(-1); /* error */ \
61
+ }
62
+
63
+ /* remove number of bits from bit buffer */
64
+ #define BITRDR_DROPBITS(BitRdr, BitNum) { \
65
+ (BitRdr)->BitFree += (BitNum); \
66
+ }
67
+
68
+ /* extract integer from bit buffer */
69
+ #define BITRDR_GETINT(BitRdr, RetVal) { \
70
+ DWORD BitBuff = (BitRdr)->BitBuff; \
71
+ UINT BitFree = (BitRdr)->BitFree; \
72
+ UINT UVal; \
73
+ while( BitFree >= 8 ) { \
74
+ BITRDR_GETBYTE(BitRdr, UVal); \
75
+ BitBuff = (BitBuff << 8) | UVal; \
76
+ BitFree -= 8; \
77
+ } \
78
+ RetVal = (BitBuff >> (8 - BitFree)) & 0x00ffffff; \
79
+ (BitRdr)->BitFree = BitFree; \
80
+ (BitRdr)->BitBuff = BitBuff; \
81
+ }
82
+
83
+ /* read number of bits from bit buffer */
84
+ #define BITRDR_GETBITS(BitRdr, BitNum, RetVal) { \
85
+ DWORD BitBuff = (BitRdr)->BitBuff; \
86
+ UINT BitFree = (BitRdr)->BitFree; \
87
+ UINT UVal; \
88
+ while( BitFree >= 8 ) { \
89
+ BITRDR_GETBYTE(BitRdr, UVal); \
90
+ BitBuff = (BitBuff << 8) | UVal; \
91
+ BitFree -= 8; \
92
+ } \
93
+ RetVal = (BitBuff >> (8 - BitFree)); \
94
+ RetVal = (RetVal & 0x00ffffff) >> (24 - (BitNum)); \
95
+ (BitRdr)->BitFree = (BitFree + (BitNum)); \
96
+ (BitRdr)->BitBuff = BitBuff; \
97
+ }
98
+
99
+ /* ##### *** SLIDING WINDOW DICTIONARY FUNCTIONS *** ####################### */
100
+
101
+ /* init swd context */
102
+ #define SWD_INIT(Wnd, Mem, Len) { \
103
+ (Wnd)->Window = (Mem); \
104
+ (Wnd)->WndLen = (Len); \
105
+ (Wnd)->CurOfs = 0; \
106
+ }
107
+
108
+ /* put byte to dictionary */
109
+ #define SWD_PUTBYTE(Wnd, DVal) { \
110
+ if ( (Wnd)->CurOfs < (Wnd)->WndLen ) \
111
+ (Wnd)->Window[(Wnd)->CurOfs++] = (BYTE)(DVal); \
112
+ else \
113
+ return(-1); /* error */ \
114
+ }
115
+
116
+ /* copy lz phrase in window */
117
+ #define SWD_DELTACOPY(Wnd, DOfs, DLen) { \
118
+ BYTE* WndPtr; \
119
+ if ( (Wnd)->CurOfs < (DOfs) ) \
120
+ return(-1); /* error */ \
121
+ if ( (Wnd)->CurOfs + (DLen) > (Wnd)->WndLen ) \
122
+ return(-1); /* error */ \
123
+ WndPtr = (Wnd)->Window + (Wnd)->CurOfs; \
124
+ lzx_memcpy(WndPtr, WndPtr - (DOfs), (DLen)); \
125
+ (Wnd)->CurOfs += (DLen); \
126
+ }
127
+
128
+ /* ##### *** HUFFMAN DECODERS FUNCTIONS *** ################################ */
129
+
130
+ /* init huffman decoder, return next table address */
131
+ static BYTE* LzxHuf_Init(LZX_HUFF* Huf, LZX_BITRDR* BitRdr, UINT SymNum,
132
+ BYTE* HufTbl)
133
+ {
134
+ Huf->BitRdr = BitRdr;
135
+ Huf->SymNum = SymNum;
136
+ Huf->Symbol = (UINT*)(HufTbl);
137
+ HufTbl += (SymNum * sizeof(Huf->Symbol[0]));
138
+ Huf->Length = HufTbl;
139
+ HufTbl += (256 * sizeof(Huf->Length[0]));
140
+ return(HufTbl);
141
+ }
142
+
143
+ /* decode one huffman symbol */
144
+ static INT LzxHuf_DecodeSymbol(LZX_HUFF* Huf)
145
+ {
146
+ UINT HVal, BNum, IOfs;
147
+
148
+ BITRDR_GETINT(Huf->BitRdr, HVal);
149
+ HVal &= 0x00fffe00;
150
+
151
+ if ( HVal < Huf->SymLim[8] )
152
+ BNum = Huf->Length[HVal >> 16];
153
+ else if ( HVal < Huf->SymLim[10] )
154
+ BNum = (HVal < Huf->SymLim[9]) ? (9) : (10);
155
+ else if ( HVal < Huf->SymLim[11] )
156
+ BNum = 11;
157
+ else if ( HVal < Huf->SymLim[12] )
158
+ BNum = 12;
159
+ else if ( HVal < Huf->SymLim[13] )
160
+ BNum = 13;
161
+ else
162
+ BNum = (HVal < Huf->SymLim[14]) ? (14) : (15);
163
+
164
+ BITRDR_DROPBITS(Huf->BitRdr, BNum);
165
+ IOfs = (HVal - Huf->SymLim[BNum-1]) >> (24 - BNum);
166
+ return(Huf->Symbol[Huf->SymIdx[BNum] + IOfs]);
167
+ }
168
+
169
+ /* construct huffman tables */
170
+ static INT LzxHuf_HufTblBuild(LZX_HUFF* Huf, BYTE* CodeLen)
171
+ {
172
+ UINT LenCnt[16];
173
+ UINT CurIdx[16];
174
+ UINT SymIdx, I;
175
+ UINT Lim, Idx;
176
+ UINT Ofs;
177
+
178
+ for ( I = 0; I < 16; I++ )
179
+ LenCnt[I] = 0;
180
+ for ( SymIdx = 0; SymIdx < Huf->SymNum; SymIdx++ )
181
+ LenCnt[CodeLen[SymIdx]]++;
182
+
183
+ #ifdef LZX_DEBUG_LOG
184
+ if ( NULL == FDebLog )
185
+ FDebLog = fopen("lzxdeb.log", "wt");
186
+ #endif
187
+
188
+ LenCnt[0] = 0;
189
+ CurIdx[0] = 0;
190
+ Huf->SymIdx[0] = 0;
191
+ Huf->SymLim[0] = 0;
192
+ Lim = 0;
193
+ Idx = 0;
194
+
195
+ for ( I = 1; I < 16; I++ )
196
+ {
197
+ Lim += (LenCnt[I] << (24 - I));
198
+ if ( Lim > 0x1000000 )
199
+ return(-1); /* overrun */
200
+
201
+ Huf->SymLim[I] = Lim;
202
+ Huf->SymIdx[I] = Huf->SymIdx[I-1] + LenCnt[I-1];
203
+ CurIdx[I] = Huf->SymIdx[I];
204
+
205
+ if ( I <= 8 )
206
+ {
207
+ Ofs = (Huf->SymLim[I] >> 16);
208
+ lzx_memset(&Huf->Length[Idx], I, Ofs - Idx);
209
+ Idx = Ofs;
210
+ }
211
+ }
212
+
213
+ if ( Lim != 0x1000000 )
214
+ return(-1); /* not full set */
215
+
216
+ #ifdef LZX_DEBUG_LOG
217
+ fprintf(FDebLog, "Huf->SymNum == %u\n", Huf->SymNum);
218
+ fprintf(FDebLog, "Huf->SymIdx == ");
219
+ for ( I = 0; I < 16; I++ )
220
+ fprintf(FDebLog, "%u ", Huf->SymIdx[I]);
221
+ fprintf(FDebLog, "\n");
222
+ fprintf(FDebLog, "Huf->SymLim == ");
223
+ for ( I = 0; I < 16; I++ )
224
+ fprintf(FDebLog, "%u ", Huf->SymLim[I]);
225
+ fprintf(FDebLog, "\n");
226
+ fflush(FDebLog);
227
+ #endif
228
+
229
+ for ( SymIdx = 0; SymIdx < Huf->SymNum; SymIdx++ )
230
+ {
231
+ if ( CodeLen[SymIdx] )
232
+ {
233
+ #ifdef LZX_DEBUG_LOG
234
+ fprintf(FDebLog, "%u\n", SymIdx);
235
+ fflush(FDebLog);
236
+ #endif
237
+ Huf->Symbol[CurIdx[CodeLen[SymIdx]]++] = SymIdx;
238
+ }
239
+ }
240
+
241
+ return(0); /* all ok */
242
+ }
243
+
244
+ /* ##### *** LZX DECODER FUNCTIONS *** ##################################### */
245
+
246
+ /* basic lzx tables */
247
+ static const UINT LzxTblLenBits[28] = {
248
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
249
+ 5, 5, 5, 5
250
+ };
251
+ static const UINT LzxTblLenBase[28] = {
252
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32,
253
+ 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224
254
+ };
255
+ static const UINT LzxTblOfsBits[58] = {
256
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
257
+ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
258
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18,
259
+ 18, 18, 18, 18
260
+ };
261
+ static const UINT LzxTblOfsBase[58] = {
262
+ 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000006,
263
+ 0x00000008, 0x0000000C, 0x00000010, 0x00000018, 0x00000020, 0x00000030,
264
+ 0x00000040, 0x00000060, 0x00000080, 0x000000C0, 0x00000100, 0x00000180,
265
+ 0x00000200, 0x00000300, 0x00000400, 0x00000600, 0x00000800, 0x00000C00,
266
+ 0x00001000, 0x00001800, 0x00002000, 0x00003000, 0x00004000, 0x00006000,
267
+ 0x00008000, 0x0000C000, 0x00010000, 0x00018000, 0x00020000, 0x00030000,
268
+ 0x00040000, 0x00060000, 0x00080000, 0x000A0000, 0x000C0000, 0x000E0000,
269
+ 0x00100000, 0x00120000, 0x00140000, 0x00160000, 0x00180000, 0x001A0000,
270
+ 0x001C0000, 0x001E0000, 0x00200000, 0x00240000, 0x00280000, 0x002C0000,
271
+ 0x00300000, 0x00340000, 0x00380000, 0x003C0000
272
+ };
273
+
274
+ /* ------------------------------------------------------------------------- */
275
+
276
+ /* build lzx tables */
277
+ static INT Lzx_LzxTblBuild(LZX_CONTEXT* Ctx)
278
+ {
279
+ BYTE* Heap;
280
+ BYTE LenTbl[19];
281
+ BYTE HufSym[757];
282
+ UINT Val, I, Sym;
283
+ INT ISym;
284
+
285
+ Heap = Ctx->LstMem;
286
+ BITRDR_GETBITS(&Ctx->BitRdr, 1, Val);
287
+ if ( !Val ) lzx_memset(Heap, 0, 757);
288
+
289
+ for ( I = 0; I < 19; I++ )
290
+ {
291
+ BITRDR_GETBITS(&Ctx->BitRdr, 4, Val);
292
+ LenTbl[I] = (BYTE)(Val);
293
+ }
294
+
295
+ if ( LzxHuf_HufTblBuild(&Ctx->HufSpec, LenTbl) )
296
+ return(-1); /* error */
297
+
298
+ I = 0;
299
+ while ( I < 757 )
300
+ {
301
+ if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufSpec)) == -1 )
302
+ return(-1); /* error */
303
+
304
+ if ( (Sym = (UINT)(ISym)) < 16 )
305
+ {
306
+ HufSym[I] = (BYTE)((Heap[I] + Sym) & 15); I++;
307
+ continue;
308
+ }
309
+
310
+ if ( Sym == 16 )
311
+ {
312
+ BITRDR_GETBITS(&Ctx->BitRdr, 2, Val); Val += 3;
313
+ while ( Val > 0 && I < 757 )
314
+ {
315
+ HufSym[I] = HufSym[I-1];
316
+ Val--; I++;
317
+ }
318
+ continue;
319
+ }
320
+
321
+ if ( Sym == 17 )
322
+ {
323
+ BITRDR_GETBITS(&Ctx->BitRdr, 3, Val);
324
+ Val += 3;
325
+ }
326
+ else
327
+ {
328
+ BITRDR_GETBITS(&Ctx->BitRdr, 7, Val);
329
+ Val += 11;
330
+ }
331
+
332
+ while ( Val > 0 && I < 757 )
333
+ {
334
+ HufSym[I] = 0;
335
+ Val--; I++;
336
+ }
337
+ }
338
+
339
+ if ( LzxHuf_HufTblBuild(&Ctx->HufBase, &HufSym[0]) )
340
+ return(-1);
341
+ if ( LzxHuf_HufTblBuild(&Ctx->HufLens, &HufSym[721]) )
342
+ return(-1);
343
+ if ( LzxHuf_HufTblBuild(&Ctx->HufOffs, &HufSym[749]) )
344
+ return(-1);
345
+
346
+ Ctx->HasOffs = FALSE;
347
+ for ( I = 0; I < 8; I++ )
348
+ {
349
+ if ( HufSym[749+I] != 3 )
350
+ {
351
+ Ctx->HasOffs = TRUE;
352
+ break;
353
+ }
354
+ }
355
+
356
+ lzx_memcpy(Heap, &HufSym[0], 757);
357
+ return(0); /* all ok */
358
+ }
359
+
360
+ /* ------------------------------------------------------------------------- */
361
+
362
+ INT DecodeLZX(LZX_CONTEXT* Ctx, BYTE* Src, BYTE* Dst, UINT PSize, UINT USize)
363
+ {
364
+ UINT Written;
365
+ UINT Symbol;
366
+ BYTE* HufMem;
367
+ UINT Ofs;
368
+ UINT Len;
369
+ UINT Num;
370
+ UINT Val;
371
+ INT ISym;
372
+
373
+ /* check params */
374
+ if ( !Ctx || !Src || !Dst || !USize )
375
+ return(-1); /* invalid param */
376
+
377
+ /* init lzx context */
378
+ BITRDR_INIT(&Ctx->BitRdr, Src, PSize);
379
+ SWD_INIT(&Ctx->Window, Dst, USize);
380
+ Ctx->HasOffs = FALSE;
381
+ Ctx->LstOfs[0] = 0;
382
+ Ctx->LstOfs[1] = 0;
383
+ Ctx->LstOfs[2] = 0;
384
+
385
+ /* init huffman coders */
386
+ HufMem = &Ctx->HufTbl[0];
387
+ HufMem = LzxHuf_Init(&Ctx->HufBase, &Ctx->BitRdr, 721, HufMem);
388
+ HufMem = LzxHuf_Init(&Ctx->HufLens, &Ctx->BitRdr, 28, HufMem);
389
+ HufMem = LzxHuf_Init(&Ctx->HufOffs, &Ctx->BitRdr, 8, HufMem);
390
+ HufMem = LzxHuf_Init(&Ctx->HufSpec, &Ctx->BitRdr, 19, HufMem);
391
+ lzx_memset(Ctx->LstMem = HufMem, 0, 757);
392
+
393
+ /* build lzx tables */
394
+ if ( Lzx_LzxTblBuild(Ctx) )
395
+ return(-1);
396
+
397
+ /* decode */
398
+ Written = 0;
399
+ while ( Written < USize )
400
+ {
401
+ if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufBase)) == -1 )
402
+ return(-1);
403
+
404
+ if ( (Symbol = (UINT)(ISym)) < 256 )
405
+ {
406
+ /* literal */
407
+ SWD_PUTBYTE(&Ctx->Window, Symbol);
408
+ Written++;
409
+ continue;
410
+ }
411
+
412
+ if ( Symbol < 720 )
413
+ {
414
+ /* phrase */
415
+ Symbol -= 256;
416
+ Ofs = (Symbol >> 3);
417
+ Len = (Symbol & 7) + 2;
418
+
419
+ if ( Len == 9 )
420
+ {
421
+ if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufLens)) == -1 )
422
+ return(-1);
423
+
424
+ Symbol = (UINT)(ISym);
425
+ Num = LzxTblLenBits[Symbol];
426
+ BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
427
+ Len += (Val + LzxTblLenBase[Symbol]);
428
+ }
429
+
430
+ Num = LzxTblOfsBits[Ofs];
431
+ Ofs = LzxTblOfsBase[Ofs];
432
+
433
+ if ( Num < 3 || !Ctx->HasOffs )
434
+ {
435
+ BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
436
+ Ofs += Val;
437
+ }
438
+ else
439
+ {
440
+ Num -= 3;
441
+ BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
442
+ if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufOffs)) == -1 )
443
+ return(-1);
444
+ Ofs += ((UINT)(ISym) + (Val << 3));
445
+ }
446
+
447
+ if ( Ofs < 3 )
448
+ {
449
+ /* use saved last offset */
450
+ Ofs = Ctx->LstOfs[Num = Ofs];
451
+ if ( Num )
452
+ {
453
+ Ctx->LstOfs[Num] = Ctx->LstOfs[0];
454
+ Ctx->LstOfs[0] = Ofs;
455
+ }
456
+ }
457
+ else
458
+ {
459
+ /* update last offset */
460
+ Ctx->LstOfs[2] = Ctx->LstOfs[1];
461
+ Ctx->LstOfs[1] = Ctx->LstOfs[0];
462
+ Ctx->LstOfs[0] = (Ofs -= 3);
463
+ }
464
+
465
+ /* copy phrase */
466
+ SWD_DELTACOPY(&Ctx->Window, Ofs+1, Len);
467
+ Written += Len;
468
+ continue;
469
+ }
470
+
471
+ /* update trees */
472
+ if ( Lzx_LzxTblBuild(Ctx) )
473
+ return(-1);
474
+ }
475
+
476
+ return(Written); /* all ok */
477
+ }
478
+
479
+ /* ------------------------------------------------------------------------- */