Subversion Repositories Kolibri OS

Rev

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

  1. ; LZMA decoder for *.7z archives.
  2. ; Based on C decoder in LZMA SDK (c) Igor Pavlov.
  3. ; Portions by Diamond, 2006, 2007.
  4. lzma_decoder:
  5. virtual at 0
  6. .outStream      rb      streamInfo.size
  7. .inStream       dd      ?
  8.  
  9. ; RangeDecoder data
  10. .inLen          dd      ?
  11. .inPtr          dd      ?
  12. .code           dd      ?
  13. .range          dd      ?
  14.  
  15. ; parameters
  16. .pb             db      ?       ; pos state bits (0 - 4)
  17. .lp             db      ?       ; literal pos state bits (0 - 4)
  18. .lc             db      ?       ; literal context bits (0 - 8)
  19. .previousByte   db      ?
  20. .posStateMask   dd      ?       ; (1 shl .pb)-1
  21. .literalPosMask dd      ?       ; (1 shl .lp)-1
  22.  
  23. ; constants
  24. .kNumPosBitsMax =       4
  25. .kNumPosStatesMax =     (1 shl .kNumPosBitsMax)
  26.  
  27. .kLenNumLowBits         =       3
  28. .kLenNumLowSymbols      =       (1 shl .kLenNumLowBits)
  29. .kLenNumMidBits         =       3
  30. .kLenNumMidSymbols      =       (1 shl .kLenNumMidBits)
  31. .kLenNumHighBits        =       8
  32. .kLenNumHighSymbols     =       (1 shl .kLenNumHighBits)
  33.  
  34. .LenChoice      =       0
  35. .LenChoice2     =       1
  36. .LenLow         =       2
  37. .LenMid         =       (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits))
  38. .LenHigh        =       (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits))
  39. .kNumLenProbs   =       (.LenHigh + .kLenNumHighSymbols)
  40.  
  41. .kNumStates     =       12
  42. .kNumLitStates  =       7
  43. .kStartPosModelIndex =  4
  44. .kEndPosModelIndex =    14
  45. .kNumFullDistances =    (1 shl (.kEndPosModelIndex/2))
  46. .kNumPosSlotBits =      6
  47. .kNumLenToPosStates =   4
  48. .kNumAlignBits  =       4
  49. .kAlignTableSize =      (1 shl .kNumAlignBits)
  50. .kMatchMinLen   =       2
  51.  
  52. .IsMatch        =       0
  53. .IsRep          =       (.IsMatch + (.kNumStates shl .kNumPosBitsMax))
  54. .IsRepG0        =       (.IsRep + .kNumStates)
  55. .IsRepG1        =       (.IsRepG0 + .kNumStates)
  56. .IsRepG2        =       (.IsRepG1 + .kNumStates)
  57. .IsRep0Long     =       (.IsRepG2 + .kNumStates)
  58. .PosSlot        =       (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax))
  59. .SpecPos        =       (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits))
  60. .Align_         =       (.SpecPos + .kNumFullDistances - .kEndPosModelIndex)
  61. .Lencoder       =       (.Align_ + .kAlignTableSize)
  62. .RepLencoder    =       (.Lencoder + .kNumLenProbs)
  63. .Literal        =       (.RepLencoder + .kNumLenProbs)
  64.  
  65. LZMA_BASE_SIZE  =       1846    ; must be ==Literal
  66. LZMA_LIT_SIZE   =       768
  67.  
  68. .kNumTopBits    =       24
  69. .kTopValue      =       (1 shl .kNumTopBits)
  70.  
  71. .kNumBitModelTotalBits =        11
  72. .kBitModelTotal =       (1 shl .kNumBitModelTotalBits)
  73. .kNumMoveBits   =       5
  74.  
  75. ; variables
  76. .continue       dd      ?
  77. .ecx            dd      ?
  78. .outEnd         dd      ?
  79. .dictSize       dd      ?
  80. .state          dd      ?
  81. .rep0           dd      ?
  82. .rep1           dd      ?
  83. .rep2           dd      ?
  84. .rep3           dd      ?
  85. .p              rd      LZMA_BASE_SIZE
  86. .basesize = $
  87. ;               rd      LZMA_LIT_SIZE shl (.lc+.lp)
  88. end virtual
  89.  
  90. .fillBuf:
  91.         mov     ebp, eax
  92.         mov     ebx, [ebp+.state]
  93.         jecxz   .nodata
  94.         add     ecx, edi
  95.         mov     [ebp+.outEnd], ecx
  96.         mov     esi, [ebp+.inPtr]
  97.         jmp     [ebp+.continue]
  98. .nodata:
  99.         popad
  100.         ret
  101. .start:
  102.         mov     eax, [ebp+.inStream]
  103.         call    fillBuf
  104.         mov     esi, [eax+streamInfo.bufPtr]
  105.         mov     eax, [eax+streamInfo.bufDataLen]
  106.         sub     eax, 5
  107.         jb      return.err
  108.         mov     [ebp+.inLen], eax
  109.         inc     esi
  110.         lodsd
  111.         bswap   eax
  112.         mov     [ebp+.code], eax
  113.         or      [ebp+.range], -1
  114. .main_loop:
  115.         cmp     edi, [ebp+.outEnd]
  116.         jae     .main_loop_done
  117.         mov     edx, edi
  118.         and     edx, [ebp+.posStateMask]
  119.         mov     eax, ebx
  120.         shl     eax, .kNumPosBitsMax
  121.         add     eax, edx
  122.         lea     eax, [ebp + .p + .IsMatch*4 + eax*4]
  123.         call    .RangeDecoderBitDecode
  124.         jc      .1
  125.         movzx   eax, [ebp+.previousByte]
  126.         mov     ah, dl
  127.         and     ah, byte [ebp+.literalPosMask]
  128.         mov     cl, 8
  129.         sub     cl, [ebp+.lc]
  130.         shr     eax, cl
  131.         imul    eax, LZMA_LIT_SIZE*4
  132.         lea     eax, [ebp + eax + .p+.Literal*4]
  133.         cmp     ebx, .kNumLitStates
  134.         jb      .literal
  135.         mov     edx, edi
  136.         sub     edx, [ebp+.rep0]
  137.         jc      .before_buf
  138.         cmp     edx, [ebp+streamInfo.bufPtr]
  139.         jb      .before_buf
  140. @@:
  141.         mov     dl, [edx]
  142.         call    .LzmaLiteralDecodeMatch
  143.         jmp     .got_byte
  144. .before_buf:
  145.         add     edx, [ebp+streamInfo.bufSize]
  146.         cmp     edx, [ebp+streamInfo.bufPtr]
  147.         jb      return.err
  148.         jmp     @b
  149. .literal:
  150.         call    .LzmaLiteralDecode
  151. .got_byte:
  152.         mov     [ebp+.previousByte], al
  153.         stosb
  154.         mov     al, bl
  155.         cmp     bl, 4
  156.         jb      @f
  157.         mov     al, 3
  158.         cmp     bl, 10
  159.         jb      @f
  160.         mov     al, 6
  161. @@:     sub     bl, al
  162.         jmp     .main_loop
  163. .1:
  164.         lea     eax, [ebp + .p + .IsRep*4 + ebx*4]
  165.         call    .RangeDecoderBitDecode
  166.         jnc     .10
  167.         lea     eax, [ebp + .p + .IsRepG0*4 + ebx*4]
  168.         call    .RangeDecoderBitDecode
  169.         jc      .111
  170.         mov     eax, ebx
  171.         shl     eax, .kNumPosBitsMax
  172.         add     eax, edx
  173.         lea     eax, [ebp + .p + .IsRep0Long*4 + eax*4]
  174.         call    .RangeDecoderBitDecode
  175.         jc      .1101
  176.         cmp     bl, 7
  177.         setae   bl
  178.         lea     ebx, [9 + ebx + ebx]
  179.         mov     edx, edi
  180.         sub     edx, [ebp+.rep0]
  181.         jc      @f
  182.         cmp     edx, [ebp+streamInfo.bufPtr]
  183.         jae     .copy_byte
  184. @@:
  185.         add     edx, [ebp+streamInfo.bufSize]
  186.         cmp     edx, [ebp+streamInfo.bufPtr]
  187.         jb      return.err
  188. .copy_byte:
  189.         mov     al, [edx]
  190.         stosb
  191.         mov     [ebp+.previousByte], al
  192.         jmp     .main_loop
  193. .111:
  194.         lea     eax, [ebp + .p + .IsRepG1*4 + ebx*4]
  195.         call    .RangeDecoderBitDecode
  196.         mov     eax, [ebp+.rep1]
  197.         jnc     .l3
  198. .l1:
  199.         lea     eax, [ebp + .p + .IsRepG2*4 + ebx*4]
  200.         call    .RangeDecoderBitDecode
  201.         mov     eax, [ebp+.rep2]
  202.         jnc     .l2
  203.         xchg    [ebp+.rep3], eax
  204. .l2:
  205.         push    [ebp+.rep1]
  206.         pop     [ebp+.rep2]
  207. .l3:
  208.         xchg    eax, [ebp+.rep0]
  209.         mov     [ebp+.rep1], eax
  210. .1101:
  211.         lea     eax, [ebp + .p + .RepLencoder*4]
  212.         call    .LzmaLenDecode
  213.         cmp     bl, 7
  214.         setc    bl
  215.         adc     bl, bl
  216.         xor     bl, 3
  217.         add     bl, 8
  218.         jmp     .repmovsb
  219. .10:
  220.         mov     eax, [ebp+.rep0]
  221.         xchg    eax, [ebp+.rep1]
  222.         xchg    eax, [ebp+.rep2]
  223.         xchg    eax, [ebp+.rep3]
  224.         cmp     bl, 7
  225.         setc    bl
  226.         adc     bl, bl
  227.         xor     bl, 3
  228.         add     bl, 7
  229.         lea     eax, [ebp + .p + .Lencoder*4]
  230.         call    .LzmaLenDecode
  231.         mov     eax, .kNumLenToPosStates-1
  232.         cmp     eax, ecx
  233.         jb      @f
  234.         mov     eax, ecx
  235. @@:
  236.         push    ecx
  237.         mov     ecx, .kNumPosSlotBits
  238.         shl     eax, cl
  239.         lea     eax, [ebp + .p+.PosSlot*4 + eax*4]
  240.         call    .RangeDecoderBitTreeDecode
  241.         mov     [ebp+.rep0], ecx
  242.         cmp     ecx, .kStartPosModelIndex
  243.         jb      .l6
  244.         push    ecx
  245.         mov     eax, ecx
  246.         and     eax, 1
  247.         shr     ecx, 1
  248.         or      eax, 2
  249.         dec     ecx
  250.         shl     eax, cl
  251.         mov     [ebp+.rep0], eax
  252.         pop     edx
  253.         cmp     edx, .kEndPosModelIndex
  254.         jae     .l5
  255.         sub     eax, edx
  256.         lea     eax, [ebp + .p + (.SpecPos - 1)*4 + eax*4]
  257.         call    .RangeDecoderReverseBitTreeDecode
  258.         add     [ebp+.rep0], ecx
  259.         jmp     .l6
  260. .l5:
  261.         sub     ecx, .kNumAlignBits
  262.         call    .RangeDecoderDecodeDirectBits
  263.         mov     ecx, .kNumAlignBits
  264.         shl     eax, cl
  265.         add     [ebp+.rep0], eax
  266.         lea     eax, [ebp+.p+.Align_*4]
  267.         call    .RangeDecoderReverseBitTreeDecode
  268.         add     [ebp+.rep0], ecx
  269. .l6:
  270.         pop     ecx
  271.         inc     [ebp+.rep0]
  272.         jz      .main_loop_done
  273. .repmovsb:
  274.         add     ecx, .kMatchMinLen
  275. .repmovsbz:
  276.         push    esi
  277. .repmovsbr:
  278.         mov     eax, [ebp+.rep0]
  279.         cmp     eax, [ebp+.dictSize]
  280.         ja      return.err
  281.         mov     esi, edi
  282.         sub     esi, eax
  283.         jc      .repmovsb0a
  284.         mov     eax, [ebp+streamInfo.bufPtr]
  285.         sub     eax, esi
  286.         ja      .repmovsb0
  287.         mov     eax, [ebp+.outEnd]
  288.         sub     eax, edi
  289.         jz      .done1
  290.         push    ecx
  291.         cmp     ecx, eax
  292.         jb      @f
  293.         mov     ecx, eax
  294. @@:
  295.         sub     [esp], ecx
  296.         rep     movsb
  297.         pop     ecx
  298.         jz      .repmovsb1
  299. .done1:
  300.         pop     [ebp+.inPtr]
  301.         mov     [ebp+.state], ebx
  302.         mov     [ebp+.ecx], ecx
  303.         mov     [ebp+.continue], .restart_repmovsb
  304.         popad
  305.         ret
  306. .repmovsb0a:
  307.         mov     eax, [ebp+streamInfo.bufPtr]
  308.         sub     eax, esi
  309. .repmovsb0:
  310.         mov     edx, [ebp+.dictSize]
  311. ;       cmp     edx, [ebp+streamInfo.bufSize]
  312. ;       jnz     return.err
  313.         add     esi, edx
  314.         push    ecx
  315.         cmp     ecx, eax
  316.         jb      @f
  317.         mov     ecx, eax
  318. @@:
  319.         mov     eax, [ebp+.outEnd]
  320.         sub     eax, edi
  321.         jz      .done2
  322.         cmp     ecx, eax
  323.         jb      @f
  324.         mov     ecx, eax
  325. @@:
  326.         sub     [esp], ecx
  327.         rep     movsb
  328.         pop     ecx
  329.         jnz     .repmovsbr
  330. .repmovsb1:
  331.         pop     esi
  332.         mov     al, [edi-1]
  333.         mov     [ebp+.previousByte], al
  334.         jmp     .main_loop
  335. .done2:
  336.         pop     ecx
  337.         jmp     .done1
  338. .main_loop_done:
  339.         mov     [ebp+.state], ebx
  340.         mov     [ebp+.continue], .main_loop
  341.         mov     [ebp+.inPtr], esi
  342.         popad
  343.         ret
  344. .restart_repmovsb:
  345.         mov     ecx, [ebp+.ecx]
  346.         jmp     .repmovsbz
  347.  
  348. .RangeDecoderBitDecode:
  349. ; in: eax->prob
  350. ; out: CF=bit; destroys eax
  351.         push    edx
  352.         mov     edx, [ebp+.range]
  353.         shr     edx, .kNumBitModelTotalBits
  354.         imul    edx, [eax]
  355.         cmp     [ebp+.code], edx
  356.         jae     .ae
  357.         mov     [ebp+.range], edx
  358.         mov     edx, .kBitModelTotal
  359.         sub     edx, [eax]
  360.         shr     edx, .kNumMoveBits
  361.         add     [eax], edx
  362.         clc
  363. .n:
  364.         lahf
  365.         cmp     [ebp+.range], .kTopValue
  366.         jae     @f
  367.         shl     [ebp+.range], 8
  368.         shl     [ebp+.code], 8
  369.         sub     [ebp+.inLen], 1
  370.         js      .refill1
  371. .refilled1:
  372.         lodsb
  373.         mov     byte [ebp+.code], al
  374. @@:
  375.         sahf
  376.         pop     edx
  377.         ret
  378. .ae:
  379.         sub     [ebp+.range], edx
  380.         sub     [ebp+.code], edx
  381.         mov     edx, [eax]
  382.         shr     edx, .kNumMoveBits
  383.         sub     [eax], edx
  384.         stc
  385.         jmp     .n
  386.  
  387. .refill1:
  388.         push    eax
  389.         call    .refill
  390.         pop     eax
  391.         jmp     .refilled1
  392.  
  393. .refill:
  394.         mov     eax, [ebp+.inStream]
  395.         cmp     dword [eax+streamInfo.fullSize+4], 0
  396.         jnz     @f
  397.         cmp     dword [eax+streamInfo.fullSize], 0
  398.         jz      return.err
  399. @@:
  400.         call    fillBuf
  401.         mov     esi, [eax+streamInfo.bufPtr]
  402.         mov     eax, [eax+streamInfo.bufDataLen]
  403.         dec     eax
  404.         js      return.err
  405.         mov     [ebp+.inLen], eax
  406.         ret
  407.  
  408. .refill2:
  409.         call    .refill
  410.         jmp     .refilled2
  411.  
  412. .RangeDecoderDecodeDirectBits:
  413. ; in: ecx=numTotalBits
  414. ; out: eax=result; destroys edx
  415.         xor     eax, eax
  416. .l:
  417.         shr     [ebp+.range], 1
  418.         shl     eax, 1
  419.         mov     edx, [ebp+.code]
  420.         sub     edx, [ebp+.range]
  421.         jb      @f
  422.         mov     [ebp+.code], edx
  423.         or      eax, 1
  424. @@:
  425.         cmp     [ebp+.range], .kTopValue
  426.         jae     @f
  427.         shl     [ebp+.range], 8
  428.         shl     [ebp+.code], 8
  429.         push    eax
  430.         dec     [ebp+.inLen]
  431.         js      .refill2
  432. .refilled2:
  433.         lodsb
  434.         mov     byte [ebp+.code], al
  435.         pop     eax
  436. @@:
  437.         loop    .l
  438.         ret
  439.  
  440. .LzmaLiteralDecode:
  441. ; in: eax->probs
  442. ; out: al=byte; destroys edx
  443.         push    ecx
  444.         mov     ecx, 1
  445. @@:
  446.         push    eax
  447.         lea     eax, [eax+ecx*4]
  448.         call    .RangeDecoderBitDecode
  449.         pop     eax
  450.         adc     cl, cl
  451.         jnc     @b
  452. .LzmaLiteralDecode.ret:
  453.         mov     al, cl
  454.         pop     ecx
  455.         ret
  456. .LzmaLiteralDecodeMatch:
  457. ; in: eax->probs, dl=matchByte
  458. ; out: al=byte; destroys edx
  459.         push    ecx
  460.         mov     ecx, 1
  461. .LzmaLiteralDecodeMatch.1:
  462.         add     dl, dl
  463.         setc    ch
  464.         push    eax
  465.         lea     eax, [eax+ecx*4+0x100*4]
  466.         call    .RangeDecoderBitDecode
  467.         pop     eax
  468.         adc     cl, cl
  469.         jc      .LzmaLiteralDecode.ret
  470.         xor     ch, cl
  471.         test    ch, 1
  472.         mov     ch, 0
  473.         jnz     @b
  474.         jmp     .LzmaLiteralDecodeMatch.1
  475.  
  476. .LzmaLenDecode:
  477. ; in: eax->prob, edx=posState
  478. ; out: ecx=len
  479.         push    eax
  480.         add     eax, .LenChoice*4
  481.         call    .RangeDecoderBitDecode
  482.         pop     eax
  483.         jnc     .0
  484.         push    eax
  485.         add     eax, .LenChoice2*4
  486.         call    .RangeDecoderBitDecode
  487.         pop     eax
  488.         jc      @f
  489.         mov     ecx, .kLenNumMidBits
  490.         shl     edx, cl
  491.         lea     eax, [eax + .LenMid*4 + edx*4]
  492.         call    .RangeDecoderBitTreeDecode
  493.         add     ecx, .kLenNumLowSymbols
  494.         ret
  495. @@:
  496.         add     eax, .LenHigh*4
  497.         mov     ecx, .kLenNumHighBits
  498.         call    .RangeDecoderBitTreeDecode
  499.         add     ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
  500.         ret
  501. .0:
  502.         mov     ecx, .kLenNumLowBits
  503.         shl     edx, cl
  504.         lea     eax, [eax + .LenLow*4 + edx*4]
  505. .RangeDecoderBitTreeDecode:
  506. ; in: eax->probs,ecx=numLevels
  507. ; out: ecx=length; destroys edx
  508.         push    ebx
  509.         mov     edx, 1
  510.         mov     ebx, edx
  511. @@:
  512.         push    eax
  513.         lea     eax, [eax+edx*4]
  514.         call    .RangeDecoderBitDecode
  515.         pop     eax
  516.         adc     dl, dl
  517.         add     bl, bl
  518.         loop    @b
  519.         sub     dl, bl
  520.         pop     ebx
  521.         mov     ecx, edx
  522.         ret
  523. .RangeDecoderReverseBitTreeDecode:
  524. ; in: eax->probs,ecx=numLevels
  525. ; out: ecx=length; destroys edx
  526.         push    ebx ecx
  527.         mov     edx, 1
  528.         xor     ebx, ebx
  529. @@:
  530.         push    eax
  531.         lea     eax, [eax+edx*4]
  532.         call    .RangeDecoderBitDecode
  533.         lahf
  534.         adc     edx, edx
  535.         sahf
  536.         rcr     ebx, 1
  537.         pop     eax
  538.         loop    @b
  539.         pop     ecx
  540.         rol     ebx, cl
  541.         mov     ecx, ebx
  542.         pop     ebx
  543.         ret
  544.  
  545. ; LZMA parameters:
  546. ;       db      lc + 9 * (lp + 5 * pb)
  547. ;       dd      dictionarySize
  548.  
  549. lzma_get_buf_size:
  550.         cmp     dword [esi-4], 5
  551.         jb      return.err
  552.         push    ecx
  553.         lodsb
  554.         aam     9
  555.         mov     cl, al
  556.         mov     al, ah
  557.         aam     5
  558.         add     cl, al
  559.         mov     eax, LZMA_LIT_SIZE
  560.         shl     eax, cl
  561.         lea     eax, [lzma_decoder.basesize+eax*4]
  562.         pop     ecx
  563.         mov     edx, [esi]
  564.         ret
  565.  
  566. lzma_init_decoder:
  567.         lodsb
  568.         aam     9
  569.         mov     [ebp+lzma_decoder.lc], al
  570.         mov     al, ah
  571.         aam     5
  572.         mov     [ebp+lzma_decoder.lp], al
  573.         mov     [ebp+lzma_decoder.pb], ah
  574.         cmp     ah, lzma_decoder.kNumPosBitsMax
  575.         ja      return.err
  576.         mov     cl, ah
  577.         lodsd
  578.         mov     [ebp+lzma_decoder.dictSize], eax
  579.         push    1
  580.         pop     eax
  581.         shl     eax, cl
  582.         dec     eax
  583.         mov     [ebp+lzma_decoder.posStateMask], eax
  584.         mov     cl, [ebp+lzma_decoder.lp]
  585.         push    1
  586.         pop     eax
  587.         shl     eax, cl
  588.         dec     eax
  589.         mov     [ebp+lzma_decoder.literalPosMask], eax
  590.         mov     [ebp+streamInfo.fillBuf], lzma_decoder.fillBuf
  591.         mov     [ebp+lzma_decoder.continue], lzma_decoder.start
  592.         xor     eax, eax
  593.         mov     [ebp+lzma_decoder.previousByte], al
  594.         mov     [ebp+lzma_decoder.state], eax
  595.         inc     eax
  596.         lea     edi, [ebp+lzma_decoder.rep0]
  597.         stosd
  598.         stosd
  599.         stosd
  600.         mov     eax, LZMA_LIT_SIZE
  601.         mov     cl, [ebp+lzma_decoder.lc]
  602.         add     cl, [ebp+lzma_decoder.lp]
  603.         shl     eax, cl
  604.         lea     ecx, [eax+lzma_decoder.Literal]
  605.         mov     eax, lzma_decoder.kBitModelTotal/2
  606.         lea     edi, [ebp+lzma_decoder.p]
  607.         rep     stosd
  608.         ret
  609.