Subversion Repositories Kolibri OS

Rev

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