Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
632 diamond 1
; Deflate and Deflate64 decoders for *.zip and *.7z archives.
2
; Written by diamond in 2007.
3
 
4
deflate_decoder:
5
virtual at 0
6
.outStream      rb      streamInfo.size
7
.inStream       dd      ?
8
.bDeflate64     db      ?
9
.dl             db      ?
10
.bLast          db      ?
11
                rb      1
12
.outEnd         dd      ?
13
.inLen          dd      ?
14
.inPtr          dd      ?
15
.continue       dd      ?
16
.blockLen       dd      ?
17
.lit_len        rb      19
18
                rb      1
19
.lengths        rb      288+32
20
.huff_bl        rd      18*2
21
.huff_dist      rd      31*2
22
.huff_lit       rd      287*2
23
.size = $
24
end virtual
25
 
26
.fillBuf:
27
        mov     ebp, eax
28
        jecxz   .nodata
29
        add     ecx, edi
30
        mov     [ebp+.outEnd], ecx
31
        mov     esi, [ebp+.inPtr]
32
        mov     dl, [ebp+.dl]
33
        jmp     [ebp+.continue]
34
.nodata:
35
        popad
36
        ret
37
.block_loop_done:
38
        mov     [ebp+.inPtr], esi
39
        mov     [ebp+.dl], dl
40
        mov     [ebp+.continue], .block_loop
41
        popad
42
        ret
43
.start:
44
        xor     edx, edx
45
        mov     [ebp+.inLen], edx
46
        mov     [ebp+.bLast], dl
47
.block_loop:
48
        cmp     edi, [ebp+.outEnd]
49
        jae     .block_loop_done
50
        cmp     [ebp+.bLast], 0
51
        jnz     return.err
52
        call    .get_bit
53
        setc    [ebp+.bLast]
54
        call    .get_bit
55
        jc      .test_block_fh
56
        call    .get_bit
57
        jc      .block_dh
58
.block_stored:  ; Stored
59
        xor     edx, edx
60
        xor     eax, eax
61
        call    .get_word
62
        mov     ecx, eax
63
        call    .get_word
64
        not     ax
65
        cmp     eax, ecx
66
        jnz     return.err
67
        mov     [ebp+.blockLen], ecx
68
.continue_stored:
69
        mov     ecx, [ebp+.blockLen]
70
        mov     eax, [ebp+.outEnd]
71
        sub     eax, edi
72
        cmp     eax, ecx
73
        jae     @f
74
        mov     ecx, eax
75
@@:
76
        sub     [ebp+.blockLen], ecx
77
.bs_loop:
78
        mov     eax, [ebp+.inLen]
79
        test    eax, eax
80
        jnz     @f
81
        call    .refill
82
        mov     eax, [ebp+.inLen]
83
        inc     eax
84
        mov     [ebp+.inLen], eax
85
@@:
86
        push    ecx
87
        sub     ecx, eax
88
        sbb     eax, eax
89
        and     ecx, eax
90
        add     ecx, [ebp+.inLen]
91
        sub     [ebp+.inLen], ecx
92
        sub     [esp], ecx
93
        rep     movsb
94
        pop     ecx
95
        jnz     .bs_loop
96
        cmp     [ebp+.blockLen], ecx
97
        jz      .block_loop
98
        mov     [ebp+.inPtr], esi
99
        mov     [ebp+.dl], dl
100
        mov     [ebp+.continue], .continue_stored
101
        popad
102
        ret
103
.test_block_fh:
104
        call    .get_bit
105
        jc      return.err
106
.block_fh:      ; Fixed Huffman
107
        push    edi
108
        lea     edi, [ebp+.huff_dist]
109
        lea     eax, [edi+8]
110
        xor     ecx, ecx
111
        mov     cl, 30
112
@@:
113
        stosd
114
        add     eax, 8
115
        loop    @b
116
        xor     eax, eax
117
        mov     cl, 32
118
@@:
119
        stosd
120
        inc     eax
121
        loop    @b
122
        lea     eax, [edi+8]
123
        mov     cl, 126
124
@@:
125
        stosd
126
        add     eax, 8
127
        loop    @b
128
        push    eax
129
        mov     eax, 256
130
        mov     cl, 24
131
@@:
132
        stosd
133
        inc     eax
134
        loop    @b
135
        pop     eax
136
        mov     cl, 104
137
@@:
138
        stosd
139
        add     eax, 8
140
        loop    @b
141
        push    eax
142
        xor     eax, eax
143
        mov     cl, 144
144
@@:
145
        stosd
146
        inc     eax
147
        loop    @b
148
        mov     eax, 280
149
        mov     cl, 8
150
@@:
151
        stosd
152
        inc     eax
153
        loop    @b
154
        pop     eax
155
        mov     cl, 56
156
@@:
157
        stosd
158
        add     eax, 8
159
        loop    @b
160
        mov     eax, 144
161
        mov     cl, 112
162
@@:
163
        stosd
164
        inc     eax
165
        loop    @b
166
        jmp     .block_h_start
167
.block_dh:      ; Dynamic Huffman
168
        xor     ecx, ecx
169
        mov     cl, 5
170
        push    edi
171
        lea     edi, [ebp+.lit_len]
172
        push    edi
173
        xor     eax, eax
174
        rep     stosd
175
        pop     edi
176
        mov     cl, 5
177
        call    .get_bits
178
        push    eax
179
        mov     cl, 5
180
        call    .get_bits
181
        push    eax
182
        mov     cl, 4
183
        call    .get_bits
184
        lea     ecx, [eax+4]
185
        mov     ebx, deflate.CodeLengthOrder
186
iglobal
187
deflate.CodeLengthOrder:
188
        db      16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
189
endg
190
@@:
191
        push    ecx
192
        mov     cl, 3
193
        call    .get_bits
194
        mov     cl, [ebx]
195
        inc     ebx
196
        mov     [edi+ecx], al
197
        pop     ecx
198
        loop    @b
199
        lea     ebx, [ebp+.huff_bl]
200
        mov     cl, 19
201
        push    18*8
202
        call    .construct_huffman_tree
203
        mov     ecx, [esp]
204
        add     ecx, [esp+4]
205
        add     ecx, 258
206
        lea     edi, [ebp+.lengths]
207
.dhl:
208
        lea     ebx, [ebp+.huff_bl]
209
        call    .get_huffman_code
210
        cmp     eax, 16
211
        jae     .dh_special
212
        stosb
213
        loop    .dhl
214
        jmp     .dhd
215
.dh_special:
216
        push    ecx
217
        sub     eax, 16
218
        jnz     .dh_norep
219
        push    2
220
        pop     ecx
221
        call    .get_bits
222
        pop     ecx
223
        add     eax, 3
224
        sub     ecx, eax
225
        jb      return.err
226
@@:
227
        mov     bl, [edi-1]
228
        mov     [edi], bl
229
        inc     edi
230
        dec     eax
231
        jnz     @b
232
        test    ecx, ecx
233
        jnz     .dhl
234
        jmp     .dhd
235
.dh_norep:
236
        dec     eax
237
        jz      .dh_0
238
        dec     eax
239
        jnz     return.err
240
        push    7
241
        pop     ecx
242
        call    .get_bits
243
        add     eax, 11
244
        jmp     @f
245
.dh_0:
246
        push    3
247
        pop     ecx
248
        call    .get_bits
249
        add     eax, 3
250
@@:
251
        pop     ecx
252
        sub     ecx, eax
253
        jb      return.err
254
        push    ecx
255
        mov     ecx, eax
256
        xor     eax, eax
257
        rep     stosb
258
        pop     ecx
259
        test    ecx, ecx
260
        jnz     .dhl
261
.dhd:
262
        pop     ecx
263
        inc     ecx
264
        lea     ebx, [ebp+.huff_dist]
265
        pop     edi
266
        push    edi
267
        lea     edi, [edi+ebp+.lengths+257]
268
        push    31*8
269
        call    .construct_huffman_tree
270
        pop     ecx
271
        add     ecx, 257
272
        lea     ebx, [ebp+.huff_lit]
273
        lea     edi, [ebp+.lengths]
274
        push    287*8
275
        call    .construct_huffman_tree
276
.block_h_start: ; Huffman
277
        pop     edi
278
.block_h:
279
        lea     ebx, [ebp+.huff_lit]
280
        call    .get_huffman_code
281
        sub     eax, 256
282
        jnc     .not_char
283
        stosb
284
.bhc:
285
        cmp     edi, [ebp+.outEnd]
286
        jb      .block_h
287
        mov     [ebp+.inPtr], esi
288
        mov     [ebp+.dl], dl
289
        mov     [ebp+.continue], .block_h
290
        popad
291
        ret
292
.not_char:
293
        jz      .block_loop
294
        cmp     eax, 285-256
295
        ja      return.err
296
        jz      .h_max
297
iglobal
298
deflate.LengthCodesStart:
299
        db      3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59
300
        db      67,83,99,115,131,163,195,227
301
deflate.LengthCodesExtra:
302
        db      0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5
303
endg
304
        movzx   ebx, byte [deflate.LengthCodesStart+eax-1]
305
        movzx   ecx, byte [deflate.LengthCodesExtra+eax-1]
306
        call    .get_bits
307
        add     ebx, eax
308
.length_known:
309
        push    ebx
310
        lea     ebx, [ebp+.huff_dist]
311
        call    .get_huffman_code
312
        cmp     eax, 32
313
        jae     return.err
314
iglobal
315
align 4
316
deflate.DistCodesStart:
317
        dd      1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537
318
        dd      2049,3073,4097,6145,8193,12289,16385,24577,32769,49153
319
deflate.DistCodesExtra:
320
        db      0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
321
endg
322
        mov     ebx, [deflate.DistCodesStart+eax*4]
323
        movzx   ecx, byte [deflate.DistCodesExtra+eax]
324
        call    .get_bits
325
        add     ebx, eax
326
        pop     ecx
327
; ecx=length, ebx=distance
328
.repmovsbz:
329
        push    esi
330
.repmovsbr:
331
        mov     esi, edi
332
        sub     esi, ebx
333
        mov     eax, [ebp+streamInfo.bufPtr]
334
        sub     eax, esi
335
        ja      .repmovsb0
336
        mov     eax, [ebp+.outEnd]
337
        sub     eax, edi
338
        push    ecx
339
        cmp     ecx, eax
340
        jb      @f
341
        mov     ecx, eax
342
@@:
343
        sub     [esp], ecx
344
        rep     movsb
345
        pop     ecx
346
        jz      .repmovsb1
347
.repmovsbc:
348
        pop     [ebp+.inPtr]
349
        mov     [ebp+.blockLen], ecx
350
        mov     dword [ebp+.lit_len], ebx
351
        mov     [ebp+.dl], dl
352
        mov     [ebp+.continue], .restart_repmovsb
353
        popad
354
        ret
355
.repmovsb0:
356
        add     esi, 0x10000
357
        push    ecx
358
        cmp     ecx, eax
359
        jb      @f
360
        mov     ecx, eax
361
@@:
362
        mov     eax, [ebp+.outEnd]
363
        sub     eax, edi
364
        cmp     ecx, eax
365
        jb      @f
366
        mov     ecx, eax
367
@@:
368
        sub     [esp], ecx
369
        rep     movsb
370
        pop     ecx
371
        jz      .repmovsb1
372
        cmp     edi, [ebp+.outEnd]
373
        jb      .repmovsbr
374
        jmp     .repmovsbc
375
.repmovsb1:
376
        pop     esi
377
        jmp     .bhc
378
.restart_repmovsb:
379
        mov     ecx, [ebp+.blockLen]
380
        mov     ebx, dword [ebp+.lit_len]
381
        jmp     .repmovsbz
382
.h_max:
383
        mov     ebx, 258
384
        xor     ecx, ecx
385
        cmp     [ebp+.bDeflate64], cl
386
        jz      .length_known
387
        mov     cl, 16
388
        call    .get_bits
389
        lea     ebx, [eax+3]
390
        jmp     .length_known
391
 
392
align 16
393
.get_bit:
394
        shr     dl, 1
395
        jnz     .ret
396
        sub     [ebp+.inLen], 1
397
        js      .gb_refill
398
@@:
399
        mov     dl, [esi]
400
        sub     esi, -1
401
        rcr     dl, 1
402
.ret:
403
        ret
404
.gb_refill:
405
        call    .refill
406
        jmp     @b
407
 
408
.refill:
409
        push    eax
410
        mov     eax, [ebp+.inStream]
411
        call    fillBuf
412
        mov     esi, [eax+streamInfo.bufPtr]
413
        mov     eax, [eax+streamInfo.bufDataLen]
414
        dec     eax
415
        js      return.err
416
        mov     [ebp+.inLen], eax
417
        pop     eax
418
        ret
419
 
420
.get_bits:
421
        push    ebx
422
        mov     ebx, ecx
423
        xor     eax, eax
424
        jecxz   .gbr
425
@@:
426
        call    .get_bit
427
        rcr     eax, 1
428
        loop    @b
429
        mov     cl, 32
430
        sub     cl, bl
431
        shr     eax, cl
432
.gbr:
433
        pop     ebx
434
        ret
435
 
436
.get_word:
437
        sub     [ebp+.inLen], 1
438
        jns     @f
439
        call    .refill
440
@@:
441
        lodsb
442
        sub     [ebp+.inLen], 1
443
        jns     @f
444
        call    .refill
445
@@:
446
        mov     ah, [esi]
447
        inc     esi
448
        ret
449
 
450
.construct_huffman_tree:
451
; edi->bit lengths array, ecx=number of items, ebx->tree root, [esp+4]=size of tree
452
        add     [esp+4], ebx
453
        push    edx esi
454
        xor     eax, eax
455
        xor     edx, edx
456
        mov     dword [ebx], eax
457
        mov     dword [ebx+4], eax
458
.cht1:
459
        cmp     al, [edi+edx]
460
        ja      @f
461
        mov     al, [edi+edx]
462
@@:
463
        inc     edx
464
        cmp     edx, ecx
465
        jb      .cht1
466
        test    eax, eax
467
        jz      .chtd
468
        push    ecx     ; remember number of items
469
        push    eax     ; remember maximum length
470
        lea     eax, [ebx+8]
471
        xor     edx, edx
472
        inc     edx
473
        push    2
474
        pop     ecx
475
.cht2:
476
        push    eax
477
        xor     eax, eax
478
.cht3:
479
        cmp     dl, [edi+eax]
480
        jnz     @f
481
        dec     ecx
482
        js      return.err
483
        cmp     ebx, [esp+24]
484
        jae     return.err
485
        mov     [ebx], eax
486
        add     ebx, 4
487
@@:
488
        inc     eax
489
        cmp     eax, [esp+8]
490
        jnz     .cht3
491
        pop     eax
492
        jecxz   .cht4
493
        push    ecx
494
.cht5:
495
        cmp     eax, [esp+24]
496
        jb      @f
497
        or      eax, -1
498
@@:
499
        cmp     ebx, [esp+24]
500
        jae     return.err
501
        mov     [ebx], eax
502
        add     ebx, 4
503
        cmp     eax, -1
504
        jz      @f
505
        add     eax, 8
506
@@:
507
        loop    .cht5
508
        pop     ecx
509
        add     ecx, ecx
510
.cht4:
511
        inc     edx
512
        cmp     edx, [esp]
513
        jbe     .cht2
514
        pop     eax
515
        pop     eax
516
        jecxz   .chtd
517
        or      eax, -1
518
@@:
519
        cmp     ebx, [esp+12]
520
        jae     .chtd
521
        mov     [ebx], eax
522
        add     ebx, 4
523
        loop    @b
524
.chtd:
525
        pop     esi edx
526
        ret     4
527
 
528
.get_huffman_code:
529
; ebx->tree root
530
        xor     eax, eax
531
        cmp     dword [ebx+4], eax
532
        jz      .ghcret
533
@@:
534
        call    .get_bit
535
        setc    al
536
        mov     ebx, [ebx+4*eax]
537
        cmp     ebx, -1
538
        jz      @f
539
        cmp     ebx, 0x1000
540
        jae     @b
541
@@:
542
        mov     eax, ebx
543
.ghcret:
544
        ret
545
 
546
deflate_get_buf_size:
547
        mov     eax, deflate_decoder.size
548
        mov     edx, 0x10000
549
        ret
550
 
551
deflate_init_decoder:
552
        mov     [ebp+deflate_decoder.bDeflate64], 0
553
        jmp     @f
554
 
555
deflate64_init_decoder:
556
        mov     [ebp+deflate_decoder.bDeflate64], 1
557
@@:
558
        mov     [ebp+streamInfo.fillBuf], deflate_decoder.fillBuf
559
        mov     [ebp+deflate_decoder.continue], deflate_decoder.start
560
        ret