Subversion Repositories Kolibri OS

Rev

Rev 920 | Go to most recent revision | 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.         xor     edx, edx
  136.         sub     edx, [ebp+.rep0]
  137.         mov     dl, [edi + edx]
  138.         call    .LzmaLiteralDecodeMatch
  139.         jmp     @f
  140. .literal:
  141.         call    .LzmaLiteralDecode
  142. @@:
  143.         mov     [ebp+.previousByte], al
  144.         stosb
  145.         mov     al, bl
  146.         cmp     bl, 4
  147.         jb      @f
  148.         mov     al, 3
  149.         cmp     bl, 10
  150.         jb      @f
  151.         mov     al, 6
  152. @@:     sub     bl, al
  153.         jmp     .main_loop
  154. .1:
  155.         lea     eax, [ebp + .p + .IsRep*4 + ebx*4]
  156.         call    .RangeDecoderBitDecode
  157.         jnc     .10
  158.         lea     eax, [ebp + .p + .IsRepG0*4 + ebx*4]
  159.         call    .RangeDecoderBitDecode
  160.         jc      .111
  161.         mov     eax, ebx
  162.         shl     eax, .kNumPosBitsMax
  163.         add     eax, edx
  164.         lea     eax, [ebp + .p + .IsRep0Long*4 + eax*4]
  165.         call    .RangeDecoderBitDecode
  166.         jc      .1101
  167.         cmp     bl, 7
  168.         setae   bl
  169.         lea     ebx, [9 + ebx + ebx]
  170.         xor     edx, edx
  171.         sub     edx, [ebp+.rep0]
  172.         mov     al, [edi + edx]
  173.         stosb
  174.         mov     [ebp+.previousByte], al
  175.         jmp     .main_loop
  176. .111:
  177.         lea     eax, [ebp + .p + .IsRepG1*4 + ebx*4]
  178.         call    .RangeDecoderBitDecode
  179.         mov     eax, [ebp+.rep1]
  180.         jnc     .l3
  181. .l1:
  182.         lea     eax, [ebp + .p + .IsRepG2*4 + ebx*4]
  183.         call    .RangeDecoderBitDecode
  184.         mov     eax, [ebp+.rep2]
  185.         jnc     .l2
  186.         xchg    [ebp+.rep3], eax
  187. .l2:
  188.         push    [ebp+.rep1]
  189.         pop     [ebp+.rep2]
  190. .l3:
  191.         xchg    eax, [ebp+.rep0]
  192.         mov     [ebp+.rep1], eax
  193. .1101:
  194.         lea     eax, [ebp + .p + .RepLencoder*4]
  195.         call    .LzmaLenDecode
  196.         cmp     bl, 7
  197.         setc    bl
  198.         adc     bl, bl
  199.         xor     bl, 3
  200.         add     bl, 8
  201.         jmp     .repmovsb
  202. .10:
  203.         mov     eax, [ebp+.rep0]
  204.         xchg    eax, [ebp+.rep1]
  205.         xchg    eax, [ebp+.rep2]
  206.         xchg    eax, [ebp+.rep3]
  207.         cmp     bl, 7
  208.         setc    bl
  209.         adc     bl, bl
  210.         xor     bl, 3
  211.         add     bl, 7
  212.         lea     eax, [ebp + .p + .Lencoder*4]
  213.         call    .LzmaLenDecode
  214.         mov     eax, .kNumLenToPosStates-1
  215.         cmp     eax, ecx
  216.         jb      @f
  217.         mov     eax, ecx
  218. @@:
  219.         push    ecx
  220.         mov     ecx, .kNumPosSlotBits
  221.         shl     eax, cl
  222.         lea     eax, [ebp + .p+.PosSlot*4 + eax*4]
  223.         call    .RangeDecoderBitTreeDecode
  224.         mov     [ebp+.rep0], ecx
  225.         cmp     ecx, .kStartPosModelIndex
  226.         jb      .l6
  227.         push    ecx
  228.         mov     eax, ecx
  229.         and     eax, 1
  230.         shr     ecx, 1
  231.         or      eax, 2
  232.         dec     ecx
  233.         shl     eax, cl
  234.         mov     [ebp+.rep0], eax
  235.         pop     edx
  236.         cmp     edx, .kEndPosModelIndex
  237.         jae     .l5
  238.         sub     eax, edx
  239.         lea     eax, [ebp + .p + (.SpecPos - 1)*4 + eax*4]
  240.         call    .RangeDecoderReverseBitTreeDecode
  241.         add     [ebp+.rep0], ecx
  242.         jmp     .l6
  243. .l5:
  244.         sub     ecx, .kNumAlignBits
  245.         call    .RangeDecoderDecodeDirectBits
  246.         mov     ecx, .kNumAlignBits
  247.         shl     eax, cl
  248.         add     [ebp+.rep0], eax
  249.         lea     eax, [ebp+.p+.Align_*4]
  250.         call    .RangeDecoderReverseBitTreeDecode
  251.         add     [ebp+.rep0], ecx
  252. .l6:
  253.         pop     ecx
  254.         inc     [ebp+.rep0]
  255.         jz      .main_loop_done
  256. .repmovsb:
  257.         add     ecx, .kMatchMinLen
  258. .repmovsbz:
  259.         push    esi
  260. .repmovsbr:
  261.         mov     eax, [ebp+.rep0]
  262.         cmp     eax, [ebp+.dictSize]
  263.         jae     return.err
  264.         mov     esi, edi
  265.         sub     esi, eax
  266.         mov     eax, [ebp+streamInfo.bufPtr]
  267.         sub     eax, esi
  268.         ja      .repmovsb0
  269.         mov     eax, [ebp+.outEnd]
  270.         sub     eax, edi
  271.         push    ecx
  272.         cmp     ecx, eax
  273.         jb      @f
  274.         mov     ecx, eax
  275. @@:
  276.         sub     [esp], ecx
  277.         rep     movsb
  278.         pop     ecx
  279.         jz      .repmovsb1
  280.         pop     [ebp+.inPtr]
  281.         mov     [ebp+.state], ebx
  282.         mov     [ebp+.ecx], ecx
  283.         mov     [ebp+.continue], .restart_repmovsb
  284.         popad
  285.         ret
  286. .repmovsb0:
  287.         mov     edx, [ebp+.dictSize]
  288.         cmp     edx, [ebp+streamInfo.bufSize]
  289.         jnz     return.err
  290.         add     esi, edx
  291.         push    ecx
  292.         cmp     ecx, eax
  293.         jb      @f
  294.         mov     ecx, eax
  295. @@:
  296.         mov     eax, [ebp+.outEnd]
  297.         sub     eax, edi
  298.         cmp     ecx, eax
  299.         jb      @f
  300.         mov     ecx, eax
  301. @@:
  302.         sub     [esp], ecx
  303.         rep     movsb
  304.         pop     ecx
  305.         jnz     .repmovsbr
  306. .repmovsb1:
  307.         pop     esi
  308.         mov     al, [edi-1]
  309.         mov     [ebp+.previousByte], al
  310.         jmp     .main_loop
  311. .main_loop_done:
  312.         mov     [ebp+.state], ebx
  313.         mov     [ebp+.continue], .main_loop
  314.         mov     [ebp+.inPtr], esi
  315.         popad
  316.         ret
  317. .restart_repmovsb:
  318.         mov     ecx, [ebp+.ecx]
  319.         jmp     .repmovsbz
  320.  
  321. .RangeDecoderBitDecode:
  322. ; in: eax->prob
  323. ; out: CF=bit; destroys eax
  324.         push    edx
  325.         mov     edx, [ebp+.range]
  326.         shr     edx, .kNumBitModelTotalBits
  327.         imul    edx, [eax]
  328.         cmp     [ebp+.code], edx
  329.         jae     .ae
  330.         mov     [ebp+.range], edx
  331.         mov     edx, .kBitModelTotal
  332.         sub     edx, [eax]
  333.         shr     edx, .kNumMoveBits
  334.         add     [eax], edx
  335.         clc
  336. .n:
  337.         lahf
  338.         cmp     [ebp+.range], .kTopValue
  339.         jae     @f
  340.         shl     [ebp+.range], 8
  341.         shl     [ebp+.code], 8
  342.         sub     [ebp+.inLen], 1
  343.         js      .refill1
  344. .refilled1:
  345.         lodsb
  346.         mov     byte [ebp+.code], al
  347. @@:
  348.         sahf
  349.         pop     edx
  350.         ret
  351. .ae:
  352.         sub     [ebp+.range], edx
  353.         sub     [ebp+.code], edx
  354.         mov     edx, [eax]
  355.         shr     edx, .kNumMoveBits
  356.         sub     [eax], edx
  357.         stc
  358.         jmp     .n
  359.  
  360. .refill1:
  361.         push    eax
  362.         call    .refill
  363.         pop     eax
  364.         jmp     .refilled1
  365.  
  366. .refill:
  367.         mov     eax, [ebp+.inStream]
  368.         cmp     dword [eax+streamInfo.fullSize+4], 0
  369.         jnz     @f
  370.         cmp     dword [eax+streamInfo.fullSize], 0
  371.         jz      return.err
  372. @@:
  373.         call    fillBuf
  374.         mov     esi, [eax+streamInfo.bufPtr]
  375.         mov     eax, [eax+streamInfo.bufDataLen]
  376.         dec     eax
  377.         js      return.err
  378.         mov     [ebp+.inLen], eax
  379.         ret
  380.  
  381. .refill2:
  382.         call    .refill
  383.         jmp     .refilled2
  384.  
  385. .RangeDecoderDecodeDirectBits:
  386. ; in: ecx=numTotalBits
  387. ; out: eax=result; destroys edx
  388.         xor     eax, eax
  389. .l:
  390.         shr     [ebp+.range], 1
  391.         shl     eax, 1
  392.         mov     edx, [ebp+.code]
  393.         sub     edx, [ebp+.range]
  394.         jb      @f
  395.         mov     [ebp+.code], edx
  396.         or      eax, 1
  397. @@:
  398.         cmp     [ebp+.range], .kTopValue
  399.         jae     @f
  400.         shl     [ebp+.range], 8
  401.         shl     [ebp+.code], 8
  402.         push    eax
  403.         dec     [ebp+.inLen]
  404.         js      .refill2
  405. .refilled2:
  406.         lodsb
  407.         mov     byte [ebp+.code], al
  408.         pop     eax
  409. @@:
  410.         loop    .l
  411.         ret
  412.  
  413. .LzmaLiteralDecode:
  414. ; in: eax->probs
  415. ; out: al=byte; destroys edx
  416.         push    ecx
  417.         mov     ecx, 1
  418. @@:
  419.         push    eax
  420.         lea     eax, [eax+ecx*4]
  421.         call    .RangeDecoderBitDecode
  422.         pop     eax
  423.         adc     cl, cl
  424.         jnc     @b
  425. .LzmaLiteralDecode.ret:
  426.         mov     al, cl
  427.         pop     ecx
  428.         ret
  429. .LzmaLiteralDecodeMatch:
  430. ; in: eax->probs, dl=matchByte
  431. ; out: al=byte; destroys edx
  432.         push    ecx
  433.         mov     ecx, 1
  434. .LzmaLiteralDecodeMatch.1:
  435.         add     dl, dl
  436.         setc    ch
  437.         push    eax
  438.         lea     eax, [eax+ecx*4+0x100*4]
  439.         call    .RangeDecoderBitDecode
  440.         pop     eax
  441.         adc     cl, cl
  442.         jc      .LzmaLiteralDecode.ret
  443.         xor     ch, cl
  444.         test    ch, 1
  445.         mov     ch, 0
  446.         jnz     @b
  447.         jmp     .LzmaLiteralDecodeMatch.1
  448.  
  449. .LzmaLenDecode:
  450. ; in: eax->prob, edx=posState
  451. ; out: ecx=len
  452.         push    eax
  453.         add     eax, .LenChoice*4
  454.         call    .RangeDecoderBitDecode
  455.         pop     eax
  456.         jnc     .0
  457.         push    eax
  458.         add     eax, .LenChoice2*4
  459.         call    .RangeDecoderBitDecode
  460.         pop     eax
  461.         jc      @f
  462.         mov     ecx, .kLenNumMidBits
  463.         shl     edx, cl
  464.         lea     eax, [eax + .LenMid*4 + edx*4]
  465.         call    .RangeDecoderBitTreeDecode
  466.         add     ecx, .kLenNumLowSymbols
  467.         ret
  468. @@:
  469.         add     eax, .LenHigh*4
  470.         mov     ecx, .kLenNumHighBits
  471.         call    .RangeDecoderBitTreeDecode
  472.         add     ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
  473.         ret
  474. .0:
  475.         mov     ecx, .kLenNumLowBits
  476.         shl     edx, cl
  477.         lea     eax, [eax + .LenLow*4 + edx*4]
  478. .RangeDecoderBitTreeDecode:
  479. ; in: eax->probs,ecx=numLevels
  480. ; out: ecx=length; destroys edx
  481.         push    ebx
  482.         mov     edx, 1
  483.         mov     ebx, edx
  484. @@:
  485.         push    eax
  486.         lea     eax, [eax+edx*4]
  487.         call    .RangeDecoderBitDecode
  488.         pop     eax
  489.         adc     dl, dl
  490.         add     bl, bl
  491.         loop    @b
  492.         sub     dl, bl
  493.         pop     ebx
  494.         mov     ecx, edx
  495.         ret
  496. .RangeDecoderReverseBitTreeDecode:
  497. ; in: eax->probs,ecx=numLevels
  498. ; out: ecx=length; destroys edx
  499.         push    ebx ecx
  500.         mov     edx, 1
  501.         xor     ebx, ebx
  502. @@:
  503.         push    eax
  504.         lea     eax, [eax+edx*4]
  505.         call    .RangeDecoderBitDecode
  506.         lahf
  507.         adc     edx, edx
  508.         sahf
  509.         rcr     ebx, 1
  510.         pop     eax
  511.         loop    @b
  512.         pop     ecx
  513.         rol     ebx, cl
  514.         mov     ecx, ebx
  515.         pop     ebx
  516.         ret
  517.  
  518. ; LZMA parameters:
  519. ;       db      lc + 9 * (lp + 5 * pb)
  520. ;       dd      dictionarySize
  521.  
  522. lzma_get_buf_size:
  523.         cmp     dword [esi-4], 5
  524.         jb      return.err
  525.         push    ecx
  526.         lodsb
  527.         aam     9
  528.         mov     cl, al
  529.         mov     al, ah
  530.         aam     5
  531.         add     cl, al
  532.         mov     eax, LZMA_LIT_SIZE
  533.         shl     eax, cl
  534.         lea     eax, [lzma_decoder.basesize+eax*4]
  535.         pop     ecx
  536.         mov     edx, [esi]
  537.         ret
  538.  
  539. lzma_init_decoder:
  540.         lodsb
  541.         aam     9
  542.         mov     [ebp+lzma_decoder.lc], al
  543.         mov     al, ah
  544.         aam     5
  545.         mov     [ebp+lzma_decoder.lp], al
  546.         mov     [ebp+lzma_decoder.pb], ah
  547.         cmp     ah, lzma_decoder.kNumPosBitsMax
  548.         ja      return.err
  549.         mov     cl, ah
  550.         lodsd
  551.         mov     [ebp+lzma_decoder.dictSize], eax
  552.         push    1
  553.         pop     eax
  554.         shl     eax, cl
  555.         dec     eax
  556.         mov     [ebp+lzma_decoder.posStateMask], eax
  557.         mov     cl, [ebp+lzma_decoder.lp]
  558.         push    1
  559.         pop     eax
  560.         shl     eax, cl
  561.         dec     eax
  562.         mov     [ebp+lzma_decoder.literalPosMask], eax
  563.         mov     [ebp+streamInfo.fillBuf], lzma_decoder.fillBuf
  564.         mov     [ebp+lzma_decoder.continue], lzma_decoder.start
  565.         xor     eax, eax
  566.         mov     [ebp+lzma_decoder.previousByte], al
  567.         mov     [ebp+lzma_decoder.state], eax
  568.         inc     eax
  569.         lea     edi, [ebp+lzma_decoder.rep0]
  570.         stosd
  571.         stosd
  572.         stosd
  573.         mov     eax, LZMA_LIT_SIZE
  574.         mov     cl, [ebp+lzma_decoder.lc]
  575.         add     cl, [ebp+lzma_decoder.lp]
  576.         shl     eax, cl
  577.         lea     ecx, [eax+lzma_decoder.Literal]
  578.         mov     eax, lzma_decoder.kBitModelTotal/2
  579.         lea     edi, [ebp+lzma_decoder.p]
  580.         rep     stosd
  581.         ret
  582.