Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  561.