Subversion Repositories Kolibri OS

Rev

Rev 893 | 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.         ja      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.         jz      .done1
  286.         push    ecx
  287.         cmp     ecx, eax
  288.         jb      @f
  289.         mov     ecx, eax
  290. @@:
  291.         sub     [esp], ecx
  292.         rep     movsb
  293.         pop     ecx
  294.         jz      .repmovsb1
  295. .done1:
  296.         pop     [ebp+.inPtr]
  297.         mov     [ebp+.state], ebx
  298.         mov     [ebp+.ecx], ecx
  299.         mov     [ebp+.continue], .restart_repmovsb
  300.         popad
  301.         ret
  302. .repmovsb0:
  303.         mov     edx, [ebp+.dictSize]
  304. ;       cmp     edx, [ebp+streamInfo.bufSize]
  305. ;       jnz     return.err
  306.         add     esi, edx
  307.         push    ecx
  308.         cmp     ecx, eax
  309.         jb      @f
  310.         mov     ecx, eax
  311. @@:
  312.         mov     eax, [ebp+.outEnd]
  313.         sub     eax, edi
  314.         jz      .done2
  315.         cmp     ecx, eax
  316.         jb      @f
  317.         mov     ecx, eax
  318. @@:
  319.         sub     [esp], ecx
  320.         rep     movsb
  321.         pop     ecx
  322.         jnz     .repmovsbr
  323. .repmovsb1:
  324.         pop     esi
  325.         mov     al, [edi-1]
  326.         mov     [ebp+.previousByte], al
  327.         jmp     .main_loop
  328. .done2:
  329.         pop     ecx
  330.         jmp     .done1
  331. .main_loop_done:
  332.         mov     [ebp+.state], ebx
  333.         mov     [ebp+.continue], .main_loop
  334.         mov     [ebp+.inPtr], esi
  335.         popad
  336.         ret
  337. .restart_repmovsb:
  338.         mov     ecx, [ebp+.ecx]
  339.         jmp     .repmovsbz
  340.  
  341. .RangeDecoderBitDecode:
  342. ; in: eax->prob
  343. ; out: CF=bit; destroys eax
  344.         push    edx
  345.         mov     edx, [ebp+.range]
  346.         shr     edx, .kNumBitModelTotalBits
  347.         imul    edx, [eax]
  348.         cmp     [ebp+.code], edx
  349.         jae     .ae
  350.         mov     [ebp+.range], edx
  351.         mov     edx, .kBitModelTotal
  352.         sub     edx, [eax]
  353.         shr     edx, .kNumMoveBits
  354.         add     [eax], edx
  355.         clc
  356. .n:
  357.         lahf
  358.         cmp     [ebp+.range], .kTopValue
  359.         jae     @f
  360.         shl     [ebp+.range], 8
  361.         shl     [ebp+.code], 8
  362.         sub     [ebp+.inLen], 1
  363.         js      .refill1
  364. .refilled1:
  365.         lodsb
  366.         mov     byte [ebp+.code], al
  367. @@:
  368.         sahf
  369.         pop     edx
  370.         ret
  371. .ae:
  372.         sub     [ebp+.range], edx
  373.         sub     [ebp+.code], edx
  374.         mov     edx, [eax]
  375.         shr     edx, .kNumMoveBits
  376.         sub     [eax], edx
  377.         stc
  378.         jmp     .n
  379.  
  380. .refill1:
  381.         push    eax
  382.         call    .refill
  383.         pop     eax
  384.         jmp     .refilled1
  385.  
  386. .refill:
  387.         mov     eax, [ebp+.inStream]
  388.         cmp     dword [eax+streamInfo.fullSize+4], 0
  389.         jnz     @f
  390.         cmp     dword [eax+streamInfo.fullSize], 0
  391.         jz      return.err
  392. @@:
  393.         call    fillBuf
  394.         mov     esi, [eax+streamInfo.bufPtr]
  395.         mov     eax, [eax+streamInfo.bufDataLen]
  396.         dec     eax
  397.         js      return.err
  398.         mov     [ebp+.inLen], eax
  399.         ret
  400.  
  401. .refill2:
  402.         call    .refill
  403.         jmp     .refilled2
  404.  
  405. .RangeDecoderDecodeDirectBits:
  406. ; in: ecx=numTotalBits
  407. ; out: eax=result; destroys edx
  408.         xor     eax, eax
  409. .l:
  410.         shr     [ebp+.range], 1
  411.         shl     eax, 1
  412.         mov     edx, [ebp+.code]
  413.         sub     edx, [ebp+.range]
  414.         jb      @f
  415.         mov     [ebp+.code], edx
  416.         or      eax, 1
  417. @@:
  418.         cmp     [ebp+.range], .kTopValue
  419.         jae     @f
  420.         shl     [ebp+.range], 8
  421.         shl     [ebp+.code], 8
  422.         push    eax
  423.         dec     [ebp+.inLen]
  424.         js      .refill2
  425. .refilled2:
  426.         lodsb
  427.         mov     byte [ebp+.code], al
  428.         pop     eax
  429. @@:
  430.         loop    .l
  431.         ret
  432.  
  433. .LzmaLiteralDecode:
  434. ; in: eax->probs
  435. ; out: al=byte; destroys edx
  436.         push    ecx
  437.         mov     ecx, 1
  438. @@:
  439.         push    eax
  440.         lea     eax, [eax+ecx*4]
  441.         call    .RangeDecoderBitDecode
  442.         pop     eax
  443.         adc     cl, cl
  444.         jnc     @b
  445. .LzmaLiteralDecode.ret:
  446.         mov     al, cl
  447.         pop     ecx
  448.         ret
  449. .LzmaLiteralDecodeMatch:
  450. ; in: eax->probs, dl=matchByte
  451. ; out: al=byte; destroys edx
  452.         push    ecx
  453.         mov     ecx, 1
  454. .LzmaLiteralDecodeMatch.1:
  455.         add     dl, dl
  456.         setc    ch
  457.         push    eax
  458.         lea     eax, [eax+ecx*4+0x100*4]
  459.         call    .RangeDecoderBitDecode
  460.         pop     eax
  461.         adc     cl, cl
  462.         jc      .LzmaLiteralDecode.ret
  463.         xor     ch, cl
  464.         test    ch, 1
  465.         mov     ch, 0
  466.         jnz     @b
  467.         jmp     .LzmaLiteralDecodeMatch.1
  468.  
  469. .LzmaLenDecode:
  470. ; in: eax->prob, edx=posState
  471. ; out: ecx=len
  472.         push    eax
  473.         add     eax, .LenChoice*4
  474.         call    .RangeDecoderBitDecode
  475.         pop     eax
  476.         jnc     .0
  477.         push    eax
  478.         add     eax, .LenChoice2*4
  479.         call    .RangeDecoderBitDecode
  480.         pop     eax
  481.         jc      @f
  482.         mov     ecx, .kLenNumMidBits
  483.         shl     edx, cl
  484.         lea     eax, [eax + .LenMid*4 + edx*4]
  485.         call    .RangeDecoderBitTreeDecode
  486.         add     ecx, .kLenNumLowSymbols
  487.         ret
  488. @@:
  489.         add     eax, .LenHigh*4
  490.         mov     ecx, .kLenNumHighBits
  491.         call    .RangeDecoderBitTreeDecode
  492.         add     ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
  493.         ret
  494. .0:
  495.         mov     ecx, .kLenNumLowBits
  496.         shl     edx, cl
  497.         lea     eax, [eax + .LenLow*4 + edx*4]
  498. .RangeDecoderBitTreeDecode:
  499. ; in: eax->probs,ecx=numLevels
  500. ; out: ecx=length; destroys edx
  501.         push    ebx
  502.         mov     edx, 1
  503.         mov     ebx, edx
  504. @@:
  505.         push    eax
  506.         lea     eax, [eax+edx*4]
  507.         call    .RangeDecoderBitDecode
  508.         pop     eax
  509.         adc     dl, dl
  510.         add     bl, bl
  511.         loop    @b
  512.         sub     dl, bl
  513.         pop     ebx
  514.         mov     ecx, edx
  515.         ret
  516. .RangeDecoderReverseBitTreeDecode:
  517. ; in: eax->probs,ecx=numLevels
  518. ; out: ecx=length; destroys edx
  519.         push    ebx ecx
  520.         mov     edx, 1
  521.         xor     ebx, ebx
  522. @@:
  523.         push    eax
  524.         lea     eax, [eax+edx*4]
  525.         call    .RangeDecoderBitDecode
  526.         lahf
  527.         adc     edx, edx
  528.         sahf
  529.         rcr     ebx, 1
  530.         pop     eax
  531.         loop    @b
  532.         pop     ecx
  533.         rol     ebx, cl
  534.         mov     ecx, ebx
  535.         pop     ebx
  536.         ret
  537.  
  538. ; LZMA parameters:
  539. ;       db      lc + 9 * (lp + 5 * pb)
  540. ;       dd      dictionarySize
  541.  
  542. lzma_get_buf_size:
  543.         cmp     dword [esi-4], 5
  544.         jb      return.err
  545.         push    ecx
  546.         lodsb
  547.         aam     9
  548.         mov     cl, al
  549.         mov     al, ah
  550.         aam     5
  551.         add     cl, al
  552.         mov     eax, LZMA_LIT_SIZE
  553.         shl     eax, cl
  554.         lea     eax, [lzma_decoder.basesize+eax*4]
  555.         pop     ecx
  556.         mov     edx, [esi]
  557.         ret
  558.  
  559. lzma_init_decoder:
  560.         lodsb
  561.         aam     9
  562.         mov     [ebp+lzma_decoder.lc], al
  563.         mov     al, ah
  564.         aam     5
  565.         mov     [ebp+lzma_decoder.lp], al
  566.         mov     [ebp+lzma_decoder.pb], ah
  567.         cmp     ah, lzma_decoder.kNumPosBitsMax
  568.         ja      return.err
  569.         mov     cl, ah
  570.         lodsd
  571.         mov     [ebp+lzma_decoder.dictSize], eax
  572.         push    1
  573.         pop     eax
  574.         shl     eax, cl
  575.         dec     eax
  576.         mov     [ebp+lzma_decoder.posStateMask], eax
  577.         mov     cl, [ebp+lzma_decoder.lp]
  578.         push    1
  579.         pop     eax
  580.         shl     eax, cl
  581.         dec     eax
  582.         mov     [ebp+lzma_decoder.literalPosMask], eax
  583.         mov     [ebp+streamInfo.fillBuf], lzma_decoder.fillBuf
  584.         mov     [ebp+lzma_decoder.continue], lzma_decoder.start
  585.         xor     eax, eax
  586.         mov     [ebp+lzma_decoder.previousByte], al
  587.         mov     [ebp+lzma_decoder.state], eax
  588.         inc     eax
  589.         lea     edi, [ebp+lzma_decoder.rep0]
  590.         stosd
  591.         stosd
  592.         stosd
  593.         mov     eax, LZMA_LIT_SIZE
  594.         mov     cl, [ebp+lzma_decoder.lc]
  595.         add     cl, [ebp+lzma_decoder.lp]
  596.         shl     eax, cl
  597.         lea     ecx, [eax+lzma_decoder.Literal]
  598.         mov     eax, lzma_decoder.kBitModelTotal/2
  599.         lea     edi, [ebp+lzma_decoder.p]
  600.         rep     stosd
  601.         ret
  602.