Subversion Repositories Kolibri OS

Rev

Rev 9029 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2022. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 9715 $
  9.  
  10.  
  11. ; @brief Unpack LZMA-compressed data. C-style declaration of the function.
  12. ;
  13. ; ```void __stdcall unpack(void *packed_data, void *unpacked_data);```
  14. ;
  15. ; @param packed_data Data to unpack
  16. ; @param unpacked_data Buffer to hold unpacked data
  17. ; @returns Nothing
  18. unpack:
  19.         pushad
  20.         mov     esi, [esp+32+4]
  21.         mov     edi, [esp+32+8]
  22.         mov     eax, [esi+8]
  23.         and     al, 0xC0
  24.         cmp     al, 0xC0
  25.         jz      .failed
  26.         mov     eax, [esi+8]
  27.         push    eax
  28.         add     esi, 12
  29.         and     al, not 0xC0
  30.         dec     al
  31.         jz      .lzma
  32. .failed:
  33.         pop     eax
  34.         popad
  35.         ret     8
  36. .lzma:
  37.         call    .lzma_unpack
  38. .common:
  39.         pop     eax
  40.         test    al, 0x80
  41.         jnz     .ctr1
  42.         test    al, 0x40
  43.         jz      .ok
  44.         lodsd
  45.         mov     ecx, eax
  46.         jecxz   .ok
  47.         mov     dl, [esi]
  48.         mov     esi, [esp+32+8]
  49. .c1:
  50.         lodsb
  51.         sub     al, 0E8h
  52.         cmp     al, 1
  53.         ja      .c1
  54.         cmp     byte [esi], dl
  55.         jnz     .c1
  56.         lodsd
  57. ; "bswap eax" is not supported on i386
  58.         shr     ax, 8
  59.         ror     eax, 16
  60.         xchg    al, ah
  61.         sub     eax, esi
  62.         add     eax, [esp+32+8]
  63.         mov     [esi-4], eax
  64.         loop    .c1
  65. .ok:
  66.         popad
  67.         ret     8
  68. .ctr1:
  69.         lodsd
  70.         mov     ecx, eax
  71.         jecxz   .ok
  72.         mov     dl, [esi]
  73.         mov     esi, [esp+32+8]
  74. .c2:
  75.         lodsb
  76. @@:
  77.         cmp     al, 0xF
  78.         jnz     .f
  79.         lodsb
  80.         cmp     al, 80h
  81.         jb      @b
  82.         cmp     al, 90h
  83.         jb      @f
  84. .f:
  85.         sub     al, 0E8h
  86.         cmp     al, 1
  87.         ja      .c2
  88. @@:
  89.         cmp     byte [esi], dl
  90.         jnz     .c2
  91.         lodsd
  92.         shr     ax, 8
  93.         ror     eax, 16
  94.         xchg    al, ah
  95.         sub     eax, esi
  96.         add     eax, [esp+32+8]
  97.         mov     [esi-4], eax
  98.         loop    .c2
  99.         jmp     .ok
  100.  
  101. .lzma_unpack:
  102.  
  103. .pb     =       2       ; pos state bits
  104. .lp     =       0       ; literal pos state bits
  105. .lc     =       3       ; literal context bits
  106. .posStateMask   =       ((1 shl .pb)-1)
  107. .literalPosMask =       ((1 shl .lp)-1)
  108.  
  109. .kNumPosBitsMax =       4
  110. .kNumPosStatesMax =     (1 shl .kNumPosBitsMax)
  111.  
  112. .kLenNumLowBits         =       3
  113. .kLenNumLowSymbols      =       (1 shl .kLenNumLowBits)
  114. .kLenNumMidBits         =       3
  115. .kLenNumMidSymbols      =       (1 shl .kLenNumMidBits)
  116. .kLenNumHighBits        =       8
  117. .kLenNumHighSymbols     =       (1 shl .kLenNumHighBits)
  118.  
  119. .LenChoice      =       0
  120. .LenChoice2     =       1
  121. .LenLow         =       2
  122. .LenMid         =       (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits))
  123. .LenHigh        =       (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits))
  124. .kNumLenProbs   =       (.LenHigh + .kLenNumHighSymbols)
  125.  
  126. .kNumStates     =       12
  127. .kNumLitStates  =       7
  128. .kStartPosModelIndex =  4
  129. .kEndPosModelIndex =    14
  130. .kNumFullDistances =    (1 shl (.kEndPosModelIndex/2))
  131. .kNumPosSlotBits =      6
  132. .kNumLenToPosStates =   4
  133. .kNumAlignBits  =       4
  134. .kAlignTableSize =      (1 shl .kNumAlignBits)
  135. .kMatchMinLen   =       2
  136.  
  137. .IsMatch        =       0
  138. .IsRep          =       (.IsMatch + (.kNumStates shl .kNumPosBitsMax))
  139. .IsRepG0        =       (.IsRep + .kNumStates)
  140. .IsRepG1        =       (.IsRepG0 + .kNumStates)
  141. .IsRepG2        =       (.IsRepG1 + .kNumStates)
  142. .IsRep0Long     =       (.IsRepG2 + .kNumStates)
  143. .PosSlot        =       (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax))
  144. .SpecPos        =       (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits))
  145. .Align_         =       (.SpecPos + .kNumFullDistances - .kEndPosModelIndex)
  146. .Lencoder       =       (.Align_ + .kAlignTableSize)
  147. .RepLencoder    =       (.Lencoder + .kNumLenProbs)
  148. .Literal        =       (.RepLencoder + .kNumLenProbs)
  149.  
  150. .LZMA_BASE_SIZE =       1846    ; must be ==Literal
  151. .LZMA_LIT_SIZE  =       768
  152.  
  153. .kNumTopBits    =       24
  154. .kTopValue      =       (1 shl .kNumTopBits)
  155.  
  156. .kNumBitModelTotalBits =        11
  157. .kBitModelTotal =       (1 shl .kNumBitModelTotalBits)
  158. .kNumMoveBits   =       5
  159.  
  160.         push    edi
  161. ; int state=0;
  162.         xor     ebx, ebx
  163.         mov     [.previousByte], bl
  164. ; unsigned rep0=1,rep1=1,rep2=1,rep3=1;
  165.         mov     eax, 1
  166.         mov     edi, .rep0
  167.         stosd
  168.         stosd
  169.         stosd
  170.         stosd
  171. ; int len=0;
  172. ; result=0;
  173.         mov     ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp))
  174.         mov     eax, .kBitModelTotal/2
  175.         mov     edi, [.p]
  176.         rep stosd
  177. ; RangeDecoderInit
  178. ; rd->ExtraBytes = 0
  179. ; rd->Buffer = stream
  180. ; rd->BufferLim = stream+bufferSize
  181. ; rd->Range = 0xFFFFFFFF
  182.         pop     edi
  183.         mov     ebp, [esi-8]    ; dest_length
  184.         add     ebp, edi        ; ebp = destination limit
  185.         lodsd
  186. ; rd->code_ = eax
  187.         mov     [.code_], eax
  188.         or      [.range], -1
  189. .main_loop:
  190.         cmp     edi, ebp
  191.         jae     .main_loop_done
  192.         mov     edx, edi
  193.         and     edx, .posStateMask
  194.         mov     eax, ebx
  195.         shl     eax, .kNumPosBitsMax+2
  196.         lea     eax, [.IsMatch*4 + eax + edx*4]
  197.         add     eax, [.p]
  198.         call    .RangeDecoderBitDecode
  199.         jc      .1
  200.         movzx   eax, [.previousByte]
  201. if .literalPosMask
  202.         mov     ah, dl
  203.         and     ah, .literalPosMask
  204. end if
  205.         shr     eax, 8-.lc
  206.         imul    eax, .LZMA_LIT_SIZE*4
  207.         add     eax, .Literal*4
  208.         add     eax, [.p]
  209.         cmp     ebx, .kNumLitStates
  210.         jb      .literal
  211.         xor     edx, edx
  212.         sub     edx, [.rep0]
  213.         mov     dl, [edi + edx]
  214.         call    .LzmaLiteralDecodeMatch
  215.         jmp     @f
  216. .literal:
  217.         call    .LzmaLiteralDecode
  218. @@:
  219.         mov     [.previousByte], al
  220.         stosb
  221.         mov     al, bl
  222.         cmp     bl, 4
  223.         jb      @f
  224.         mov     al, 3
  225.         cmp     bl, 10
  226.         jb      @f
  227.         mov     al, 6
  228. @@:
  229.         sub     bl, al
  230.         jmp     .main_loop
  231. .1:
  232.         lea     eax, [.IsRep*4 + ebx*4]
  233.         add     eax, [.p]
  234.         call    .RangeDecoderBitDecode
  235.         jnc     .10
  236.         lea     eax, [.IsRepG0*4 + ebx*4]
  237.         add     eax, [.p]
  238.         call    .RangeDecoderBitDecode
  239.         jc      .111
  240.         mov     eax, ebx
  241.         shl     eax, .kNumPosBitsMax+2
  242.         lea     eax, [.IsRep0Long*4 + eax + edx*4]
  243.         add     eax, [.p]
  244.         call    .RangeDecoderBitDecode
  245.         jc      .1101
  246.         cmp     bl, 7
  247.         setae   bl
  248.         lea     ebx, [9 + ebx + ebx]
  249.         xor     edx, edx
  250.         sub     edx, [.rep0]
  251.         mov     al, [edi + edx]
  252.         stosb
  253.         mov     [.previousByte], al
  254.         jmp     .main_loop
  255. .111:
  256.         lea     eax, [.IsRepG1*4 + ebx*4]
  257.         add     eax, [.p]
  258.         call    .RangeDecoderBitDecode
  259.         mov     eax, [.rep1]
  260.         jnc     .l3
  261. .l1:
  262.         lea     eax, [.IsRepG2*4 + ebx*4]
  263.         add     eax, [.p]
  264.         call    .RangeDecoderBitDecode
  265.         mov     eax, [.rep2]
  266.         jnc     .l2
  267.         xchg    [.rep3], eax
  268. .l2:
  269.         push    [.rep1]
  270.         pop     [.rep2]
  271. .l3:
  272.         xchg    eax, [.rep0]
  273.         mov     [.rep1], eax
  274. .1101:
  275.         mov     eax, .RepLencoder*4
  276.         add     eax, [.p]
  277.         call    .LzmaLenDecode
  278.         cmp     bl, 7
  279.         setc    bl
  280.         adc     bl, bl
  281.         xor     bl, 3
  282.         add     bl, 8
  283.         jmp     .repmovsb
  284. .10:
  285.         mov     eax, [.rep0]
  286.         xchg    eax, [.rep1]
  287.         xchg    eax, [.rep2]
  288.         xchg    eax, [.rep3]
  289.         cmp     bl, 7
  290.         setc    bl
  291.         adc     bl, bl
  292.         xor     bl, 3
  293.         add     bl, 7
  294.         mov     eax, .Lencoder*4
  295.         add     eax, [.p]
  296.         call    .LzmaLenDecode
  297.         mov     eax, .kNumLenToPosStates-1
  298.         cmp     eax, ecx
  299.         jb      @f
  300.         mov     eax, ecx
  301. @@:
  302.         push    ecx
  303.         mov     ecx, .kNumPosSlotBits
  304.         shl     eax, cl
  305.         shl     eax, 2
  306.         add     eax, .PosSlot*4
  307.         add     eax, [.p]
  308.         call    .RangeDecoderBitTreeDecode
  309.         mov     [.rep0], ecx
  310.         cmp     ecx, .kStartPosModelIndex
  311.         jb      .l6
  312.         push    ecx
  313.         mov     eax, ecx
  314.         and     eax, 1
  315.         shr     ecx, 1
  316.         or      eax, 2
  317.         dec     ecx
  318.         shl     eax, cl
  319.         mov     [.rep0], eax
  320.         pop     edx
  321.         cmp     edx, .kEndPosModelIndex
  322.         jae     .l5
  323.         sub     eax, edx
  324.         shl     eax, 2
  325.         add     eax, (.SpecPos - 1)*4
  326.         add     eax, [.p]
  327.         call    .RangeDecoderReverseBitTreeDecode
  328.         add     [.rep0], ecx
  329.         jmp     .l6
  330. .l5:
  331.         sub     ecx, .kNumAlignBits
  332.         call    .RangeDecoderDecodeDirectBits
  333.         mov     ecx, .kNumAlignBits
  334.         shl     eax, cl
  335.         add     [.rep0], eax
  336.         mov     eax, .Align_*4
  337.         add     eax, [.p]
  338.         call    .RangeDecoderReverseBitTreeDecode
  339.         add     [.rep0], ecx
  340. .l6:
  341.         pop     ecx
  342.         inc     [.rep0]
  343.         jz      .main_loop_done
  344. .repmovsb:
  345.         add     ecx, .kMatchMinLen
  346.         push    esi
  347.         mov     esi, edi
  348.         sub     esi, [.rep0]
  349.         rep movsb
  350.         pop     esi
  351.         mov     al, [edi-1]
  352.         mov     [.previousByte], al
  353.         jmp     .main_loop
  354. .main_loop_done:
  355.         ret
  356.  
  357. .RangeDecoderBitDecode:
  358. ; in: eax->prob
  359. ; out: CF=bit; destroys eax
  360.         push    edx
  361.         mov     edx, [.range]
  362.         shr     edx, .kNumBitModelTotalBits
  363.         imul    edx, [eax]
  364.         cmp     [.code_], edx
  365.         jae     .ae
  366.         mov     [.range], edx
  367.         mov     edx, .kBitModelTotal
  368.         sub     edx, [eax]
  369.         shr     edx, .kNumMoveBits
  370.         add     [eax], edx
  371.         clc
  372. .n:
  373.         lahf
  374.         cmp     [.range], .kTopValue
  375.         jae     @f
  376.         shl     [.range], 8
  377.         shl     [.code_], 8
  378.         lodsb
  379.         mov     byte [.code_], al
  380. @@:
  381.         sahf
  382.         pop     edx
  383.         ret
  384. .ae:
  385.         sub     [.range], edx
  386.         sub     [.code_], edx
  387.         mov     edx, [eax]
  388.         shr     edx, .kNumMoveBits
  389.         sub     [eax], edx
  390.         stc
  391.         jmp     .n
  392.  
  393. .RangeDecoderDecodeDirectBits:
  394. ; in: ecx=numTotalBits
  395. ; out: eax=result; destroys edx
  396.         xor     eax, eax
  397. .l:
  398.         shr     [.range], 1
  399.         shl     eax, 1
  400.         mov     edx, [.code_]
  401.         sub     edx, [.range]
  402.         jb      @f
  403.         mov     [.code_], edx
  404.         or      eax, 1
  405. @@:
  406.         cmp     [.range], .kTopValue
  407.         jae     @f
  408.         shl     [.range], 8
  409.         shl     [.code_], 8
  410.         push    eax
  411.         lodsb
  412.         mov     byte [.code_], al
  413.         pop     eax
  414. @@:
  415.         loop    .l
  416.         ret
  417.  
  418. .LzmaLiteralDecode:
  419. ; in: eax->probs
  420. ; out: al=byte; destroys edx
  421.         push    ecx
  422.         mov     ecx, 1
  423. @@:
  424.         push    eax
  425.         lea     eax, [eax+ecx*4]
  426.         call    .RangeDecoderBitDecode
  427.         pop     eax
  428.         adc     cl, cl
  429.         jnc     @b
  430. .LzmaLiteralDecode.ret:
  431.         mov     al, cl
  432.         pop     ecx
  433.         ret
  434. .LzmaLiteralDecodeMatch:
  435. ; in: eax->probs, dl=matchByte
  436. ; out: al=byte; destroys edx
  437.         push    ecx
  438.         mov     ecx, 1
  439. .LzmaLiteralDecodeMatch.1:
  440.         add     dl, dl
  441.         setc    ch
  442.         push    eax
  443.         lea     eax, [eax+ecx*4+0x100*4]
  444.         call    .RangeDecoderBitDecode
  445.         pop     eax
  446.         adc     cl, cl
  447.         jc      .LzmaLiteralDecode.ret
  448.         xor     ch, cl
  449.         test    ch, 1
  450.         mov     ch, 0
  451.         jnz     @b
  452.         jmp     .LzmaLiteralDecodeMatch.1
  453.  
  454. .LzmaLenDecode:
  455. ; in: eax->prob, edx=posState
  456. ; out: ecx=len
  457.         push    eax
  458.         add     eax, .LenChoice*4
  459.         call    .RangeDecoderBitDecode
  460.         pop     eax
  461.         jnc     .0
  462.         push    eax
  463.         add     eax, .LenChoice2*4
  464.         call    .RangeDecoderBitDecode
  465.         pop     eax
  466.         jc      @f
  467.         mov     ecx, .kLenNumMidBits
  468.         shl     edx, cl
  469.         lea     eax, [eax + .LenMid*4 + edx*4]
  470.         call    .RangeDecoderBitTreeDecode
  471.         add     ecx, .kLenNumLowSymbols
  472.         ret
  473. @@:
  474.         add     eax, .LenHigh*4
  475.         mov     ecx, .kLenNumHighBits
  476.         call    .RangeDecoderBitTreeDecode
  477.         add     ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
  478.         ret
  479. .0:
  480.         mov     ecx, .kLenNumLowBits
  481.         shl     edx, cl
  482.         lea     eax, [eax + .LenLow*4 + edx*4]
  483. .RangeDecoderBitTreeDecode:
  484. ; in: eax->probs,ecx=numLevels
  485. ; out: ecx=length; destroys edx
  486.         push    ebx
  487.         mov     edx, 1
  488.         mov     ebx, edx
  489. @@:
  490.         push    eax
  491.         lea     eax, [eax+edx*4]
  492.         call    .RangeDecoderBitDecode
  493.         pop     eax
  494.         adc     dl, dl
  495.         add     bl, bl
  496.         loop    @b
  497.         sub     dl, bl
  498.         pop     ebx
  499.         mov     ecx, edx
  500.         ret
  501. .RangeDecoderReverseBitTreeDecode:
  502. ; in: eax->probs,ecx=numLevels
  503. ; out: ecx=length; destroys edx
  504.         push    ebx ecx
  505.         mov     edx, 1
  506.         xor     ebx, ebx
  507. @@:
  508.         push    eax
  509.         lea     eax, [eax+edx*4]
  510.         call    .RangeDecoderBitDecode
  511.         lahf
  512.         adc     edx, edx
  513.         sahf
  514.         rcr     ebx, 1
  515.         pop     eax
  516.         loop    @b
  517.         pop     ecx
  518.         rol     ebx, cl
  519.         mov     ecx, ebx
  520.         pop     ebx
  521.         ret
  522.  
  523. uglobal
  524. align 4
  525. ;unpack.p       rd      unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp))
  526. unpack.p        dd      ?
  527. unpack.code_    dd      ?
  528. unpack.range    dd      ?
  529. unpack.rep0     dd      ?
  530. unpack.rep1     dd      ?
  531. unpack.rep2     dd      ?
  532. unpack.rep3     dd      ?
  533. unpack.previousByte db  ?
  534. endg
  535.