Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ; PPMD decoder, ported from C++ sources of 7-Zip (c) Igor Pavlov
  2. ; C++ code is based on Dmitry Shkarin's PPMdH code
  3. uglobal
  4. ppmd_decoder.NS2Indx    rb      256
  5. ppmd_decoder.NS2BSIndx  rb      256
  6. ppmd_decoder.HB2Flag    rb      256
  7. ppmd_decoder.Indx2Units rb      ppmd_decoder.N_INDEXES
  8. ppmd_decoder.Units2Indx rb      128
  9. endg
  10.  
  11. iglobal
  12. label ppmd_decoder.InitBinEsc word
  13.         dw      0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051
  14. ppmd_decoder.ExpEscape db 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2
  15. endg
  16.  
  17. init_ppmd:
  18. ; NS2Indx table
  19.         mov     edi, ppmd_decoder.NS2Indx
  20.         xor     eax, eax
  21.         stosb
  22.         inc     eax
  23.         stosb
  24.         inc     eax
  25.         stosb
  26.         mov     edx, 3-256
  27. @@:
  28.         lea     ecx, [eax-1]
  29.         inc     eax
  30.         add     edx, ecx
  31.         jc      @f
  32.         rep     stosb
  33.         jmp     @b
  34. @@:
  35.         sub     ecx, edx
  36.         rep     stosb
  37. ; NS2BSIndx table
  38.         xor     eax, eax
  39.         stosb
  40.         add     al, 2
  41.         stosb
  42.         add     al, 2
  43.         mov     cl, 9
  44.         rep     stosb
  45.         add     al, 2
  46.         mov     cl, 256-11
  47.         rep     stosb
  48. ; HB2Flag table
  49.         mov     cl, 0x40/4
  50.         xor     eax, eax
  51.         rep     stosd
  52.         mov     al, 8
  53.         mov     cl, 0x100-0x40
  54.         rep     stosb
  55. ; Indx2Units table
  56.         mov     eax, 0x04030201
  57.         stosd
  58.         mov     eax, 0x0C0A0806
  59.         stosd
  60.         mov     eax, 0x1815120F
  61.         stosd
  62.         mov     al, 0x1C
  63. @@:
  64.         stosb
  65.         add     al, 4
  66.         cmp     al, 0x80
  67.         jbe     @b
  68. ; Units2Indx table
  69.         xor     eax, eax
  70.         xor     edx, edx
  71.         inc     edx
  72.         xor     ecx, ecx
  73. @@:
  74.         cmp     [ppmd_decoder.Indx2Units+eax], dl
  75.         adc     al, 0
  76.         stosb
  77.         inc     edx
  78.         cmp     dl, 0x80
  79.         jbe     @b
  80.         ret
  81.  
  82. ppmd_decoder:
  83. virtual at 0
  84. ; base is standard structure
  85. .outStream      rb      streamInfo.size
  86. .inStream       dd      ?
  87.  
  88. ; RangeDecoder data
  89. .inLen          dd      ?
  90. .inPtr          dd      ?
  91. .code           dd      ?
  92. .range          dd      ?
  93.  
  94. .outSize        dd      ?       ; number of bytes rest for output
  95.  
  96. ; PPMD data
  97. .order          db      ?
  98. .GlueCount      db      ?
  99. .bInited        db      ?
  100.                 rb      1
  101. .usedMemorySize dd      ?
  102.  
  103. ; CSubAllocator constants
  104. .N1 = 4
  105. .N2 = 4
  106. .N3 = 4
  107. .N4 = (128+3-1*.N1-2*.N2-3*.N3)/4
  108. .UNIT_SIZE = 12
  109. .N_INDEXES = .N1+.N2+.N3+.N4
  110. .kExtraSize = .UNIT_SIZE*3
  111. .kMaxMemBlockSize = 0xFFFFFFFF - .kExtraSize
  112.  
  113. ; CSubAllocator data
  114. .HeapStart      dd      ?
  115. .LoUnit         dd      ?
  116. .HiUnit         dd      ?
  117. .pText          dd      ?
  118. .UnitsStart     dd      ?
  119. .FreeList       rd      .N_INDEXES
  120.  
  121. ; Context constants
  122. .INT_BITS = 7
  123. .PERIOD_BITS = 7
  124. .TOT_BITS = .INT_BITS + .PERIOD_BITS
  125. .INTERVAL = 1 shl .INT_BITS
  126. .BIN_SCALE = 1 shl .TOT_BITS
  127. .MAX_FREQ = 124
  128.  
  129. .kMaxOrderCompress = 32
  130. .MAX_O = 255
  131.  
  132. ; CDecodeInfo (inherits from CInfo) data
  133. ; SEE2_CONTEXT is 4 bytes long
  134. .SEE2Cont       rd      25*16
  135. .DummySEE2Cont  dd      ?
  136. .MinContext     dd      ?
  137. .MaxContext     dd      ?
  138. .FoundState     dd      ?       ; found next state transition
  139. .NumMasked      dd      ?
  140. .InitEsc        dd      ?
  141. .OrderFall      dd      ?
  142. .RunLength      dd      ?
  143. .InitRL         dd      ?
  144. .CharMask       rb      256
  145. .EscCount       db      ?
  146. .PrintCount     db      ?
  147. .PrevSuccess    db      ?
  148. .HiBitsFlag     db      ?
  149. .BinSumm        rw      128*64
  150.  
  151. .basesize = $
  152. .Base:
  153. ;               rb      .kExtraSize + [.usedMemorySize]
  154. end virtual
  155.  
  156. .init:
  157.         mov     eax, [eax+.inStream]
  158.         call    fillBuf
  159.         mov     esi, [eax+streamInfo.bufPtr]
  160.         mov     eax, [eax+streamInfo.bufDataLen]
  161.         sub     eax, 5
  162.         jb      return.err
  163.         mov     [ebp+.inLen], eax
  164.         inc     esi
  165.         lodsd
  166.         mov     [ebp+.inPtr], esi
  167.         bswap   eax
  168.         mov     [ebp+.code], eax
  169.         or      [ebp+.range], -1
  170.         mov     [ebp+.bInited], 1
  171.         call    .StartModelRare
  172.         mov     eax, ebp
  173.         jmp     .mainloop
  174.  
  175. .fillBuf:
  176.         mov     ebp, eax
  177.         mov     [eax+.outSize], ecx
  178.         cmp     [eax+.bInited], 0
  179.         jz      .init
  180. .mainloop:
  181.         sub     [ebp+.outSize], 1
  182.         js      .mainloopdone
  183. ;        cmp     edi, 0xde070+0x18
  184. ;        jnz     @f
  185. ;        int3
  186. ;@@:
  187.         call    .DecodeSymbol
  188.         jmp     .mainloop
  189. .mainloopdone:
  190.         popad
  191.         ret
  192.  
  193. .GetBinSumm:
  194. ; CInfo::GetBinSumm(ebx=rs, ecx=numStates)
  195.         movzx   eax, [ebp+.PrevSuccess]
  196.         movzx   edx, [.NS2BSIndx+ecx-1]
  197.         add     eax, edx
  198.         mov     edx, [ebp+.FoundState]
  199.         movzx   edx, byte [edx]
  200.         movzx   edx, [.HB2Flag+edx]
  201.         mov     [ebp+.HiBitsFlag], dl
  202.         add     eax, edx
  203.         movzx   edx, byte [ebx]
  204.         movzx   edx, [.HB2Flag+edx]
  205.         lea     eax, [eax+edx*2]
  206.         mov     edx, [ebp+.RunLength]
  207.         shr     edx, 26
  208.         and     edx, 0x20
  209.         add     eax, edx
  210.         movzx   edx, byte [ebx+1]
  211.         shl     edx, 6
  212.         add     eax, edx
  213.         lea     ecx, [ebp+.BinSumm+eax*2-2*64]
  214.         ret
  215.  
  216. .StartModelRare:
  217. ; CInfo::StartModelRare(.order)
  218.         mov     [ebp+.EscCount], 1
  219.         mov     [ebp+.PrintCount], 1
  220. ; N.B.
  221. ; 1. Original code has some handling of [.order]<2, but this handling is incorrect
  222. ;    and causes exception (access violation).
  223. ; 2. 7-Zip never generates archives with [.order]<2 due to input preprocessing
  224. ;    (for PPMd method in switch -mo=<n> archiver checks that 2 <= n <= 32).
  225. ; 3. If manually created archive says [.order]<2, the exception will be generated
  226. ;    in StartModelRare, but it will be handled in Code() resulting in "data error".
  227.         cmp     [ebp+.order], 2
  228.         jb      return.err
  229.         mov     byte [ebp+.DummySEE2Cont+2], .PERIOD_BITS
  230.  
  231. .RestartModelRare:
  232. ; CInfo::RestartModelRare(void)
  233.         push    edi
  234.         lea     edi, [ebp+.CharMask]
  235.         xor     eax, eax
  236.         push    0x40
  237.         pop     ecx
  238.         rep     stosd
  239. ; CSubAllocator::InitSubAllocator start
  240.         mov     [ebp+.GlueCount], al
  241.         lea     edi, [ebp+.FreeList]
  242.         mov     cl, .N_INDEXES
  243.         rep     stosd
  244.         mov     ebx, [ebp+.HeapStart]
  245.         mov     [ebp+.pText], ebx
  246.         add     ebx, [ebp+.usedMemorySize]
  247.         mov     [ebp+.HiUnit], ebx
  248.         mov     eax, [ebp+.usedMemorySize]
  249.         xor     edx, edx
  250.         mov     cl, 8*.UNIT_SIZE
  251.         div     ecx
  252.         imul    eax, 7*.UNIT_SIZE
  253.         sub     ebx, eax
  254.         mov     [ebp+.LoUnit], ebx
  255.         mov     [ebp+.UnitsStart], ebx
  256. ; CSubAllocator::InitSubAllocator end
  257.         pop     edi
  258.         movzx   eax, [ebp+.order]
  259.         cmp     al, 12
  260.         jb      @f
  261.         mov     al, 12
  262. @@:
  263.         neg     eax
  264.         dec     eax
  265.         mov     [ebp+.InitRL], eax
  266.         mov     [ebp+.RunLength], eax
  267.         call    .AllocContext
  268.         mov     [ebp+.MinContext], eax
  269.         mov     [ebp+.MaxContext], eax
  270.         and     dword [eax+8], 0
  271.         mov     esi, eax
  272.         movzx   edx, [ebp+.order]
  273.         mov     [ebp+.OrderFall], edx
  274.         mov     dword [eax], 257*10000h+256
  275.         mov     ecx, 256/2
  276.         call    .AllocUnits
  277.         mov     [ebp+.FoundState], eax
  278.         mov     [esi+4], eax
  279.         push    edi
  280.         mov     edi, eax
  281.         xor     eax, eax
  282.         mov     [ebp+.PrevSuccess], al
  283. @@:
  284.         stosb
  285.         mov     byte [edi], 1
  286.         and     dword [edi+1], 0
  287.         add     edi, 5
  288.         inc     al
  289.         jnz     @b
  290.         lea     edi, [ebp+.BinSumm]
  291.         push    2
  292.         pop     ecx
  293. .rmr1:
  294.         mov     esi, .InitBinEsc
  295. @@:
  296.         lodsw
  297.         xor     edx, edx
  298.         div     ecx
  299.         sub     eax, .BIN_SCALE
  300.         neg     eax
  301.         mov     [edi+2*8], ax
  302.         mov     [edi+2*16], ax
  303.         mov     [edi+2*24], ax
  304.         mov     [edi+2*32], ax
  305.         mov     [edi+2*40], ax
  306.         mov     [edi+2*48], ax
  307.         mov     [edi+2*56], ax
  308.         stosw
  309.         cmp     esi, .InitBinEsc+2*8
  310.         jb      @b
  311.         add     edi, 128-16
  312.         inc     ecx
  313.         cmp     ecx, 128+2
  314.         jb      .rmr1
  315.         lea     edi, [ebp+.SEE2Cont]
  316.         mov     eax, (10 shl (.PERIOD_BITS-4)) + ((.PERIOD_BITS-4) shl 16) + (4 shl 24)
  317.         push    25
  318.         pop     edx
  319. @@:
  320.         push    16
  321.         pop     ecx
  322.         rep     stosd
  323.         add     ax, 5 shl (.PERIOD_BITS-4)
  324.         dec     edx
  325.         jnz     @b
  326.         pop     edi
  327.         ret
  328.  
  329. .CreateSuccessors:
  330. ; CInfo::CreateSuccessors(bool al=skip,STATE* esi=p1)
  331.         push    ebx edi
  332.         mov     ebx, [ebp+.MinContext]  ; ebx=pc
  333.         mov     ecx, [ebp+.FoundState]
  334.         mov     ecx, [ecx+2]            ; ecx=UpBranch
  335.         sub     esp, .MAX_O*4           ; esp=ps
  336.         mov     edi, esp                ; edi=pps
  337.         test    al, al
  338.         jnz     @f
  339.         mov     eax, [ebp+.FoundState]
  340.         stosd
  341.         cmp     dword [ebx+8], 0
  342.         jz      .csnoloop
  343. @@:
  344.         test    esi, esi
  345.         jz      .csloopstart
  346.         mov     edx, esi                ; edx=p
  347.         mov     ebx, [ebx+8]
  348.         jmp     .csloopentry
  349. .csloopstart:
  350.         mov     ebx, [ebx+8]
  351.         lea     edx, [ebx+2]
  352.         cmp     word [ebx], 1
  353.         jz      .csloopentry
  354.         mov     edx, [ebx+4]
  355.         mov     eax, [ebp+.FoundState]
  356.         sub     edx, 6
  357.         mov     al, [eax]
  358. @@:
  359.         add     edx, 6
  360.         cmp     al, [edx]
  361.         jnz     @b
  362. .csloopentry:
  363.         cmp     ecx, [edx+2]
  364.         jz      @f
  365.         mov     ebx, [edx+2]
  366.         jmp     .csnoloop
  367. @@:
  368.         mov     [edi], edx
  369.         add     edi, 4
  370.         cmp     dword [ebx+8], 0
  371.         jnz     .csloopstart
  372. .csnoloop:
  373.         cmp     edi, esp
  374.         jz      .csr
  375.         push    eax
  376.         push    eax
  377.         mov     al, [ecx]
  378.         mov     [esp], al
  379.         add     ecx, 1
  380.         mov     [esp+2], ecx
  381.         mov     ah, [ebx+3]
  382.         cmp     word [ebx], 1
  383.         jz      .cs2
  384.         mov     edx, [ebx+4]
  385.         sub     edx, 6
  386. @@:
  387.         add     edx, 6
  388.         cmp     [edx], al
  389.         jnz     @b
  390.         movzx   edx, byte [edx+1]
  391.         sub     edx, 1          ; edx=cf
  392.         movzx   ecx, word [ebx+2]
  393.         movzx   eax, word [ebx]
  394.         sub     ecx, eax
  395.         sub     ecx, edx        ; ecx=s0
  396.         lea     eax, [edx+edx]
  397.         cmp     eax, ecx
  398.         ja      .cs0
  399.         lea     eax, [edx*5]
  400.         cmp     eax, ecx
  401.         seta    ah
  402.         jmp     .cs1
  403. .cs0:
  404.         lea     eax, [eax+ecx*2]
  405.         lea     eax, [eax+ecx-1]
  406.         add     ecx, ecx
  407.         xor     edx, edx
  408.         div     ecx
  409.         mov     ah, al
  410. .cs1:
  411.         add     ah, 1
  412. .cs2:
  413.         mov     [esp+1], ah
  414.         sub     edi, 8
  415. .cs3:
  416. ; PPM_CONTEXT::createChild(this=ebx,pStats=[edi+4],FirstState=esp) begin
  417.         call    .AllocContext
  418.         test    eax, eax
  419.         jz      .csr0
  420.         mov     word [eax], 1
  421.         mov     dx, [esp]
  422.         mov     [eax+2], dx
  423.         mov     edx, [esp+2]
  424.         mov     [eax+4], edx
  425.         mov     [eax+8], ebx
  426.         mov     edx, [edi+4]
  427.         mov     [edx+2], eax
  428. ; PPM_CONTEXT::createChild end
  429.         mov     ebx, eax
  430.         sub     edi, 4
  431.         cmp     edi, esp
  432.         jnz     .cs3
  433.         pop     eax eax
  434. .csr:
  435.         mov     eax, ebx
  436. @@:
  437.         add     esp, .MAX_O*4
  438.         pop     edi ebx
  439.         ret
  440. .csr0:
  441.         pop     eax eax
  442.         xor     eax, eax
  443.         jmp     @b
  444.  
  445. ; CInfo::UpdateModel(void)
  446. .UpdateModel:
  447.         mov     ebx, [ebp+.FoundState]
  448.         xor     esi, esi                ; esi=p
  449.         movzx   eax, word [ebx]
  450.         mov     ebx, [ebx+2]            ; ebx=fs.Successor
  451.         push    eax
  452.         cmp     ah, .MAX_FREQ/4
  453.         jae     .um2
  454.         mov     eax, [ebp+.MinContext]
  455.         mov     eax, [eax+8]
  456.         test    eax, eax
  457.         jz      .um2
  458.         cmp     word [eax], 1
  459.         jz      .um1
  460.         push    eax
  461.         mov     esi, [eax+4]
  462.         mov     al, [esp+4]
  463.         cmp     al, [esi]
  464.         jz      .um0
  465. @@:
  466.         add     esi, 6
  467.         cmp     al, [esi]
  468.         jnz     @b
  469.         mov     al, [esi+1]
  470.         cmp     al, [esi-6+1]
  471.         jb      @f
  472.         mov     eax, [esi]
  473.         xchg    [esi-6], eax
  474.         mov     [esi], eax
  475.         mov     ax, [esi+4]
  476.         xchg    [esi-6+4], ax
  477.         mov     [esi+4], ax
  478.         sub     esi, 6
  479. @@:
  480. .um0:
  481.         pop     eax
  482.         cmp     byte [esi+1], .MAX_FREQ-9
  483.         jae     @f
  484.         add     byte [esi+1], 2
  485.         add     word [eax+2], 2
  486. @@:
  487.         jmp     .um2
  488. .um1:
  489.         lea     esi, [eax+2]
  490.         cmp     byte [esi+1], 32
  491.         adc     byte [esi+1], 0
  492. .um2:
  493.         cmp     [ebp+.OrderFall], 0
  494.         jnz     .um3
  495.         pop     eax
  496.         mov     al, 1
  497.         call    .CreateSuccessors
  498.         mov     [ebp+.MinContext], eax
  499.         mov     [ebp+.MaxContext], eax
  500.         mov     edx, [ebp+.FoundState]
  501.         mov     [edx+2], eax
  502.         test    eax, eax
  503.         jz      .RestartModel
  504.         ret
  505. .um3:
  506.         mov     edx, [ebp+.pText]
  507.         mov     al, [esp]
  508.         mov     [edx], al
  509.         add     edx, 1          ; edx=Successor
  510.         mov     [ebp+.pText], edx
  511.         cmp     edx, [ebp+.UnitsStart]
  512.         jae     .RestartModelPop
  513.         test    ebx, ebx
  514.         jz      .um4
  515.         cmp     ebx, [ebp+.pText]
  516.         ja      @f
  517.         push    edx
  518.         xor     eax, eax
  519.         call    .CreateSuccessors
  520.         pop     edx
  521.         mov     ebx, eax
  522.         test    eax, eax
  523.         jz      .RestartModelPop
  524. @@:
  525.         sub     [ebp+.OrderFall], 1
  526.         jnz     @f
  527.         mov     edx, ebx
  528.         xor     ecx, ecx
  529.         mov     eax, [ebp+.MinContext]
  530.         cmp     eax, [ebp+.MaxContext]
  531.         setnz   cl
  532.         sub     [ebp+.pText], ecx
  533. @@:
  534.         jmp     .um5
  535. .um4:
  536.         mov     eax, [ebp+.FoundState]
  537.         mov     [eax+2], edx
  538.         mov     ebx, [ebp+.MinContext]
  539. .um5:
  540.         mov     eax, [ebp+.MinContext]
  541.         movzx   ecx, word [eax] ; ecx=ns
  542.         movzx   eax, word [eax+2]
  543.         sub     eax, ecx
  544.         push    eax
  545.         movzx   eax, byte [esp+5]
  546.         sub     eax, 1
  547.         sub     [esp], eax      ; [esp]=s0
  548.         mov     esi, [ebp+.MaxContext]  ; ebx=pc
  549.         cmp     esi, [ebp+.MinContext]
  550.         jz      .um12
  551. .um6:
  552.         movzx   eax, word [esi]
  553.         cmp     eax, 1
  554.         jz      .um8
  555.         push    eax
  556.         shr     eax, 1
  557.         jc      .um7
  558.         push    esi
  559.         mov     esi, [esi+4]
  560.         call    .ExpandUnits
  561.         pop     esi
  562.         mov     [esi+4], eax
  563.         test    eax, eax
  564.         jz      .RestartModelPop3
  565. .um7:
  566.         pop     eax
  567.         add     eax, eax
  568.         cmp     eax, ecx
  569.         adc     word [esi+2], 0
  570.         add     eax, eax
  571.         cmp     eax, ecx
  572.         ja      @f
  573.         lea     eax, [eax+eax+1]
  574.         cmp     word [esi+2], ax
  575.         ja      @f
  576.         add     word [esi+2], 2
  577. @@:
  578.         push    edx
  579.         jmp     .um9
  580. .um8:
  581.         push    edx ecx
  582.         mov     ecx, 1
  583.         call    .AllocUnits
  584.         pop     ecx
  585.         test    eax, eax
  586.         jz      .RestartModelPop3
  587.         mov     dx, [esi+2]
  588.         mov     [eax], dx
  589.         mov     edx, [esi+4]
  590.         mov     [eax+2], edx
  591.         mov     [esi+4], eax
  592.         movzx   edx, byte [eax+1]
  593.         add     edx, edx
  594.         cmp     edx, (.MAX_FREQ/4-1)*2
  595.         jb      @f
  596.         mov     edx, .MAX_FREQ-4
  597. @@:
  598.         mov     [eax+1], dl
  599.         add     edx, [ebp+.InitEsc]
  600.         cmp     ecx, 4
  601.         sbb     edx, -1
  602.         mov     [esi+2], dx
  603. .um9:
  604.         movzx   edx, word [esi+2]
  605.         mov     eax, [esp+4]
  606.         push    ecx
  607.         lea     ecx, [eax+edx]  ; ecx=sf
  608.         add     edx, 6
  609.         movzx   eax, byte [esp+13]
  610.         add     eax, eax
  611.         imul    eax, edx        ; eax=cf
  612.         lea     edx, [ecx*3]
  613.         add     edx, edx
  614.         cmp     eax, edx
  615.         jae     .um10
  616.         mov     edx, 1
  617.         cmp     ecx, eax
  618.         adc     edx, 0
  619.         shl     ecx, 2
  620.         add     eax, 1
  621.         cmp     ecx, eax
  622.         adc     edx, 0
  623.         add     word [esi+2], 3
  624.         jmp     .um11
  625. .um10:
  626.         lea     ecx, [ecx*3]
  627.         lea     edx, [ecx*3]
  628.         add     eax, 1
  629.         push    4
  630.         cmp     edx, eax
  631.         adc     dword [esp], 0
  632.         add     edx, ecx
  633.         cmp     edx, eax
  634.         adc     dword [esp], 0
  635.         add     edx, ecx
  636.         cmp     edx, eax
  637.         adc     dword [esp], 0
  638.         pop     edx
  639.         add     [esi+2], dx
  640. .um11:
  641.         movzx   eax, word [esi]
  642.         lea     eax, [eax*3]
  643.         add     eax, eax
  644.         add     eax, [esi+4]
  645.         mov     ecx, [esp+4]
  646.         mov     [eax+2], ecx
  647.         mov     cl, [esp+12]
  648.         mov     [eax], cl
  649.         mov     [eax+1], dl
  650.         add     word [esi], 1
  651.         pop     ecx edx
  652.         mov     esi, [esi+8]
  653.         cmp     esi, [ebp+.MinContext]
  654.         jnz     .um6
  655. .um12:
  656.         pop     eax
  657.         pop     eax
  658.         mov     [ebp+.MinContext], ebx
  659.         mov     [ebp+.MaxContext], ebx
  660.         ret
  661. .RestartModelPop3:
  662.         pop     eax
  663.         pop     eax
  664. .RestartModelPop:
  665.         pop     eax
  666. .RestartModel:
  667.         call    .RestartModelRare
  668.         mov     [ebp+.EscCount], 0
  669.         mov     [ebp+.PrintCount], 0xFF
  670.         ret
  671.  
  672. .rescale:
  673.         mov     esi, [ebp+.MinContext]
  674.         movzx   ecx, word [esi]
  675.         push    ecx     ; [esp]=OldNS
  676.         sub     ecx, 1
  677.         mov     ebx, [ebp+.FoundState]
  678.         cmp     ebx, [esi+4]
  679.         jz      .r1
  680. .r0:
  681.         mov     ax, [ebx]
  682.         xchg    [ebx-6], ax
  683.         mov     [ebx], ax
  684.         mov     eax, [ebx+2]
  685.         xchg    [ebx-6+2], eax
  686.         mov     [ebx+2], eax
  687.         sub     ebx, 6
  688.         cmp     ebx, [esi+4]
  689.         jnz     .r0
  690. .r1:
  691.         add     byte [ebx+1], 4
  692.         add     word [esi+2], 4
  693.         movzx   eax, byte [ebx+1]
  694.         movzx   edx, word [esi+2]
  695.         sub     edx, eax        ; edx=EscFreq
  696.         cmp     [ebp+.OrderFall], 1
  697.         sbb     eax, -1
  698.         shr     eax, 1
  699.         mov     [ebx+1], al
  700.         mov     [esi+2], ax
  701. .r2:
  702.         add     ebx, 6
  703.         movzx   eax, byte [ebx+1]
  704.         sub     edx, eax
  705.         cmp     [ebp+.OrderFall], 1
  706.         sbb     eax, -1
  707.         shr     eax, 1
  708.         mov     [ebx+1], al
  709.         add     [esi+2], ax
  710.         cmp     al, [ebx-6+1]
  711.         jbe     .r3
  712.         push    ecx
  713.         push    ebx
  714.         push    dword [ebx]
  715.         push    word [ebx+4]
  716. @@:
  717.         mov     ecx, [ebx-6]
  718.         mov     [ebx], ecx
  719.         mov     cx, [ebx-6+4]
  720.         mov     [ebx+4], cx
  721.         sub     ebx, 6
  722.         cmp     ebx, [esi+4]
  723.         jz      @f
  724.         cmp     al, [ebx-6+1]
  725.         ja      @b
  726. @@:
  727.         pop     word [ebx+4]
  728.         pop     dword [ebx]
  729.         pop     ebx
  730.         pop     ecx
  731. .r3:
  732.         sub     ecx, 1
  733.         jnz     .r2
  734.         cmp     byte [ebx+1], 0
  735.         jnz     .r4
  736. @@:
  737.         add     ecx, 1
  738.         sub     ebx, 6
  739.         cmp     byte [ebx+1], 0
  740.         jz      @b
  741.         add     edx, ecx
  742.         sub     word [esi], cx
  743.         cmp     word [esi], 1
  744.         jnz     .r4
  745.         pop     ebx
  746.         mov     eax, [esi+4]
  747.         movzx   ecx, word [eax+4]
  748.         push    ecx
  749.         push    dword [eax]
  750.         movzx   eax, byte [eax+1]
  751. @@:
  752.         add     eax, 1
  753.         shr     eax, 1
  754.         shr     edx, 1
  755.         cmp     edx, 1
  756.         ja      @b
  757.         mov     [esp+1], al
  758.         add     ebx, 1
  759.         shr     ebx, 1
  760.         mov     eax, [esi+4]
  761.         call    .FreeUnits
  762.         lea     ebx, [esi+2]
  763.         mov     [ebp+.FoundState], ebx
  764.         pop     dword [ebx]
  765.         pop     eax
  766.         mov     [ebx+4], ax
  767.         ret
  768. .r4:
  769.         add     edx, 1
  770.         shr     edx, 1
  771.         add     [esi+2], dx
  772.         pop     ebx
  773.         add     ebx, 1
  774.         shr     ebx, 1
  775.         movzx   ecx, word [esi]
  776.         add     ecx, 1
  777.         shr     ecx, 1
  778.         cmp     ebx, ecx
  779.         jz      @f
  780.         mov     eax, [esi+4]
  781.         call    .ShrinkUnits
  782.         mov     [esi+4], eax
  783. @@:
  784.         mov     eax, [esi+4]
  785.         mov     [ebp+.FoundState], eax
  786.         ret
  787.  
  788. .DecodeSymbol:
  789. ; CDecodeInfo::DecodeSymbol
  790.         mov     esi, [ebp+.MinContext]
  791.         cmp     word [esi], 1
  792.         jz      .binsymbol
  793. ; CDecodeInfo::DecodeSymbol1 start
  794.         mov     ebx, [esi+4]    ; state
  795.         movzx   ecx, word [esi+2]
  796.         mov     eax, [ebp+.range]
  797.         xor     edx, edx
  798.         div     ecx
  799.         mov     [ebp+.range], eax
  800.         mov     ecx, eax
  801.         mov     eax, [ebp+.code]
  802.         xor     edx, edx
  803.         div     ecx
  804.         movzx   edx, byte [ebx+1]
  805.         cmp     eax, edx
  806.         jae     .ds0
  807.         push    edx
  808.         add     edx, edx
  809.         cmp     dx, [esi+2]
  810.         pop     edx
  811.         seta    [ebp+.PrevSuccess]
  812.         movzx   eax, [ebp+.PrevSuccess]
  813.         add     [ebp+.RunLength], eax
  814.         xor     eax, eax
  815.         call    .RangeDecoder.Decode
  816.         mov     [ebp+.FoundState], ebx
  817.         add     edx, 4
  818.         mov     [ebx+1], dl
  819.         add     word [esi+2], 4
  820.         cmp     edx, .MAX_FREQ
  821.         jbe     @f
  822.         call    .rescale
  823. @@:
  824.         jmp     .dscmn
  825. .ds0:
  826.         mov     [ebp+.PrevSuccess], 0
  827.         movzx   ecx, word [esi]
  828.         sub     ecx, 1
  829.         push    eax
  830. .ds1:
  831.         add     ebx, 6
  832.         movzx   eax, byte [ebx+1]
  833.         add     edx, eax
  834.         cmp     edx, [esp]
  835.         ja      .ds2
  836.         sub     ecx, 1
  837.         jnz     .ds1
  838.         pop     eax
  839.         mov     eax, [ebp+.FoundState]
  840.         movzx   eax, byte [eax]
  841.         mov     al, [.HB2Flag+eax]
  842.         mov     [ebp+.HiBitsFlag], al
  843.         mov     eax, edx
  844.         movzx   edx, word [esi+2]
  845.         sub     edx, eax
  846.         call    .RangeDecoder.Decode
  847.         mov     al, [ebp+.EscCount]
  848.         movzx   edx, byte [ebx]
  849.         mov     [ebp+.CharMask+edx], al
  850.         movzx   ecx, word [esi]
  851.         mov     [ebp+.NumMasked], ecx
  852.         sub     ecx, 1
  853. @@:
  854.         sub     ebx, 6
  855.         movzx   edx, byte [ebx]
  856.         mov     [ebp+.CharMask+edx], al
  857.         sub     ecx, 1
  858.         jnz     @b
  859.         mov     [ebp+.FoundState], ecx
  860.         jmp     .dscmn
  861. .ds2:
  862.         pop     eax
  863.         mov     eax, edx
  864.         movzx   edx, byte [ebx+1]
  865.         sub     eax, edx
  866.         call    .RangeDecoder.Decode
  867. .update1:
  868.         mov     [ebp+.FoundState], ebx
  869.         add     byte [ebx+1], 4
  870.         add     word [esi+2], 4
  871.         mov     al, [ebx+1]
  872.         cmp     al, [ebx-6+1]
  873.         jbe     @f
  874.         mov     eax, [ebx]
  875.         xchg    eax, [ebx-6]
  876.         mov     [ebx], eax
  877.         mov     ax, [ebx+4]
  878.         xchg    ax, [ebx-6+4]
  879.         mov     [ebx+4], ax
  880.         sub     ebx, 6
  881.         mov     [ebp+.FoundState], ebx
  882.         cmp     byte [ebx+1], .MAX_FREQ
  883.         jbe     @f
  884.         call    .rescale
  885. @@:
  886.         jmp     .dscmn
  887. ; CDecodeInfo::DecodeSymbol1 end
  888. .binsymbol:
  889. ; CDecodeInfo::DecodeBinSymbol start
  890.         lea     ebx, [esi+2]
  891.         mov     ecx, [esi+8]
  892.         movzx   ecx, word [ecx]
  893.         call    .GetBinSumm
  894.         movzx   eax, word [ecx]
  895.         call    .RangeDecoder.DecodeBit
  896.         jc      .ds3
  897.         mov     [ebp+.FoundState], ebx
  898.         cmp     byte [ebx+1], 128
  899.         adc     byte [ebx+1], 0
  900.         movzx   eax, word [ecx]
  901.         add     eax, 1 shl (.PERIOD_BITS-2)
  902.         shr     eax, .PERIOD_BITS
  903.         sub     eax, .INTERVAL
  904.         sub     [ecx], ax
  905.         mov     [ebp+.PrevSuccess], 1
  906.         add     [ebp+.RunLength], 1
  907.         jmp     .dscmn
  908. .ds3:
  909.         movzx   eax, word [ecx]
  910.         add     eax, 1 shl (.PERIOD_BITS-2)
  911.         shr     eax, .PERIOD_BITS
  912.         sub     [ecx], ax
  913.         movzx   eax, word [ecx]
  914.         shr     eax, 10
  915.         movzx   eax, [.ExpEscape+eax]
  916.         mov     [ebp+.InitEsc], eax
  917.         mov     [ebp+.NumMasked], 1
  918.         mov     al, [ebp+.EscCount]
  919.         movzx   edx, byte [ebx]
  920.         mov     [ebp+.CharMask+edx], al
  921.         mov     [ebp+.PrevSuccess], 0
  922.         and     [ebp+.FoundState], 0
  923. ; CDecodeInfo::DecodeBinSymbol end
  924. .dscmn:
  925.         cmp     [ebp+.FoundState], 0
  926.         jnz     .dsfnd
  927. .ds4:
  928.         add     [ebp+.OrderFall], 1
  929.         mov     eax, [ebp+.MinContext]
  930.         mov     eax, [eax+8]
  931.         test    eax, eax
  932.         jz      return.err      ; no end-of-stream mark
  933.         mov     [ebp+.MinContext], eax
  934.         movzx   ecx, word [eax]
  935.         sub     ecx, [ebp+.NumMasked]
  936.         jz      .ds4
  937. ; CDecodeInfo::DecodeSymbol2 start
  938.         call    .makeEscFreq2
  939.         push    eax
  940.         mov     ebx, [esi+4]
  941.         sub     ebx, 6
  942.         sub     esp, 256*4
  943.         mov     esi, esp
  944.         xor     eax, eax
  945.         push    eax
  946. @@:
  947.         add     ebx, 6
  948.         mov     al, [ebx]
  949.         mov     al, [ebp+.CharMask+eax]
  950.         cmp     al, [ebp+.EscCount]
  951.         jz      @b
  952.         mov     al, [ebx+1]
  953.         add     [esp], eax
  954.         mov     [esi], ebx
  955.         add     esi, 4
  956.         sub     ecx, 1
  957.         jnz     @b
  958.         add     edx, [esp]
  959.         mov     ecx, edx
  960.         mov     eax, [ebp+.range]
  961.         xor     edx, edx
  962.         div     ecx
  963.         mov     [ebp+.range], eax
  964.         mov     eax, [ebp+.code]
  965.         xor     edx, edx
  966.         div     [ebp+.range]
  967.         cmp     eax, [esp]
  968.         jae     .ds5
  969.         pop     ecx
  970.         mov     esi, esp
  971.         xor     ecx, ecx
  972. @@:
  973.         mov     ebx, [esi]
  974.         add     esi, 4
  975.         movzx   edx, byte [ebx+1]
  976.         add     ecx, edx
  977.         cmp     eax, ecx
  978.         jae     @b
  979.         mov     eax, ecx
  980.         movzx   edx, byte [ebx+1]
  981.         sub     eax, edx
  982.         call    .RangeDecoder.Decode
  983.         add     esp, 256*4
  984.         pop     eax
  985.         mov     cl, [eax+2]
  986.         cmp     cl, .PERIOD_BITS
  987.         jae     @f
  988.         sub     byte [eax+3], 1
  989.         jnz     @f
  990.         shl     word [eax], 1
  991.         mov     dl, 3
  992.         shl     dl, cl
  993.         mov     [eax+3], dl
  994.         add     byte [eax+2], 1
  995. @@:
  996. .update2:
  997.         mov     [ebp+.FoundState], ebx
  998.         add     byte [ebx+1], 4
  999.         mov     esi, [ebp+.MinContext]
  1000.         add     word [esi+2], 4
  1001.         cmp     byte [ebx+1], .MAX_FREQ
  1002.         jbe     @f
  1003.         call    .rescale
  1004. @@:
  1005.         add     [ebp+.EscCount], 1
  1006.         mov     eax, [ebp+.InitRL]
  1007.         mov     [ebp+.RunLength], eax
  1008.         jmp     .dsfnd
  1009. .ds5:
  1010.         pop     eax
  1011.         mov     edx, ecx
  1012.         sub     edx, eax
  1013.         call    .RangeDecoder.Decode
  1014.         mov     eax, [ebp+.MinContext]
  1015.         movzx   eax, word [eax]
  1016.         mov     ebx, eax
  1017.         sub     ebx, [ebp+.NumMasked]
  1018.         mov     [ebp+.NumMasked], eax
  1019.         mov     esi, esp
  1020.         mov     al, [ebp+.EscCount]
  1021. @@:
  1022.         mov     edx, [esi]
  1023.         add     esi, 4
  1024.         movzx   edx, byte [edx]
  1025.         mov     [ebp+.CharMask+edx], al
  1026.         sub     ebx, 1
  1027.         jnz     @b
  1028.         add     esp, 256*4
  1029.         pop     eax
  1030.         add     word [eax], cx
  1031. ; CDecodeInfo::DecodeSymbol2 end
  1032.         cmp     [ebp+.FoundState], 0
  1033.         jz      .ds4
  1034. .dsfnd:
  1035.         mov     eax, [ebp+.FoundState]
  1036.         mov     al, [eax]
  1037.         stosb
  1038.  
  1039. .NextContext:
  1040. ; CInfo::NextContext(void)
  1041.         mov     ebx, [ebp+.FoundState]
  1042.         mov     ebx, [ebx+2]
  1043.         cmp     [ebp+.OrderFall], 0
  1044.         jnz     .nc0
  1045.         cmp     ebx, [ebp+.pText]
  1046.         jbe     .nc0
  1047.         mov     [ebp+.MinContext], ebx
  1048.         mov     [ebp+.MaxContext], ebx
  1049.         ret
  1050. .nc0:
  1051.         call    .UpdateModel
  1052.         cmp     [ebp+.EscCount], 0
  1053.         jz      @f
  1054.         ret
  1055. @@:
  1056.         mov     [ebp+.EscCount], 1
  1057.         push    edi
  1058.         lea     edi, [ebp+.CharMask]
  1059.         mov     ecx, 256/4
  1060.         xor     eax, eax
  1061.         rep     stosd
  1062.         pop     edi
  1063.         ret
  1064.  
  1065. .makeEscFreq2:
  1066. ; CInfo::makeEscFreq2(ecx=Diff)->{eax->SEE2_CONTEXT,edx=scale}
  1067.         mov     esi, [ebp+.MinContext]
  1068.         cmp     word [esi], 256
  1069.         jz      .mef0
  1070.         movzx   edx, [.NS2Indx+ecx-1]
  1071.         shl     edx, 4
  1072.         mov     eax, [esi+8]
  1073.         movzx   eax, word [eax]
  1074.         sub     ax, [esi]
  1075.         cmp     ecx, eax
  1076.         adc     edx, 0
  1077.         movzx   eax, word [esi]
  1078.         push    edx
  1079.         lea     edx, [eax*9]
  1080.         lea     edx, [edx+eax*2]
  1081.         movzx   eax, word [esi+2]
  1082.         cmp     eax, edx
  1083.         pop     edx
  1084.         setc    al
  1085.         movzx   eax, al
  1086.         lea     edx, [edx+eax*2]
  1087.         cmp     ecx, [ebp+.NumMasked]
  1088.         setc    al
  1089.         lea     edx, [edx+eax*4]
  1090.         add     dl, [ebp+.HiBitsFlag]
  1091.         lea     eax, [ebp+edx*4+.SEE2Cont]
  1092.         movzx   edx, word [eax]
  1093.         push    ecx
  1094.         mov     cl, [eax+2]
  1095.         shr     edx, cl
  1096.         sub     [eax], dx
  1097.         pop     ecx
  1098.         cmp     edx, 1
  1099.         adc     edx, 0
  1100.         ret
  1101. .mef0:
  1102.         lea     eax, [ebp+.DummySEE2Cont]
  1103.         mov     edx, 1
  1104.         ret
  1105.  
  1106. .RangeDecoder.DecodeBit:
  1107. ; CRangeDecoder::DecodeBit(eax=size0,numTotalBits=.TOT_BITS)
  1108.         mov     edx, [ebp+.range]
  1109.         shr     edx, .TOT_BITS
  1110.         imul    eax, edx
  1111.         cmp     [ebp+.code], eax
  1112.         jae     .rddb
  1113.         mov     [ebp+.range], eax
  1114.         call    .RangeDecoder.Normalize
  1115.         clc
  1116.         ret
  1117. .rddb:
  1118.         sub     [ebp+.code], eax
  1119.         sub     [ebp+.range], eax
  1120.         call    .RangeDecoder.Normalize
  1121.         stc
  1122.         ret
  1123.  
  1124. .RangeDecoder.Decode:
  1125.         imul    eax, [ebp+.range]
  1126.         sub     [ebp+.code], eax
  1127.         mov     eax, [ebp+.range]
  1128.         imul    eax, edx
  1129.         mov     [ebp+.range], eax
  1130. .RangeDecoder.Normalize:
  1131.         cmp     byte [ebp+.range+3], 0
  1132.         jz      @f
  1133.         ret
  1134. @@:
  1135.         sub     [ebp+.inLen], 1
  1136.         js      .refill
  1137. .filled:
  1138.         shl     [ebp+.range], 8
  1139.         shl     [ebp+.code], 8
  1140.         mov     eax, [ebp+.inPtr]
  1141.         add     [ebp+.inPtr], 1
  1142.         mov     al, [eax]
  1143.         mov     byte [ebp+.code], al
  1144.         jmp     .RangeDecoder.Normalize
  1145. .refill:
  1146.         mov     eax, [ebp+.inStream]
  1147.         call    fillBuf
  1148.         push    [eax+streamInfo.bufPtr]
  1149.         pop     [ebp+.inPtr]
  1150.         mov     eax, [eax+streamInfo.bufDataLen]
  1151.         sub     eax, 1
  1152.         js      return.err
  1153.         mov     [ebp+.inLen], eax
  1154.         jmp     .filled
  1155.  
  1156. .GlueFreeBlocks:
  1157. ; CSubAllocator::GlueFreeBlocks, called from AllocUnitsRare
  1158.         push    eax
  1159.         mov     [ebp+.GlueCount], 255
  1160.         mov     edx, [ebp+.HeapStart]
  1161.         add     edx, [ebp+.usedMemorySize]
  1162.         ; we need add extra MEM_BLK with Stamp=0
  1163.         and     word [edx], 0
  1164.         add     edx, .UNIT_SIZE
  1165.         mov     eax, [ebp+.LoUnit]
  1166.         cmp     eax, [ebp+.HiUnit]
  1167.         jz      @f
  1168.         mov     byte [eax], 0
  1169. @@:
  1170.         mov     [edx+4], edx
  1171.         mov     [edx+8], edx
  1172.         push    ecx
  1173.         xor     ecx, ecx
  1174. .gfb1:
  1175.         mov     eax, [ebp+ecx*4+.FreeList]
  1176.         test    eax, eax
  1177.         jz      .gfb2
  1178.         push    dword [eax]
  1179.         pop     dword [ebp+ecx*4+.FreeList]
  1180.         mov     [eax+8], edx
  1181.         push    edx
  1182.         mov     edx, [edx+4]
  1183.         mov     [eax+4], edx
  1184.         mov     [edx+8], eax
  1185.         or      word [eax], 0xFFFF
  1186.         movzx   edx, [.Indx2Units+ecx]
  1187.         mov     [eax+2], dx
  1188.         pop     edx
  1189.         mov     [edx+4], eax
  1190.         jmp     .gfb1
  1191. .gfb2:
  1192.         inc     ecx
  1193.         cmp     ecx, .N_INDEXES
  1194.         jb      .gfb1
  1195.         mov     ecx, edx
  1196. .gfb3:
  1197.         mov     ecx, [ecx+4]
  1198.         cmp     ecx, edx
  1199.         jz      .gfb5
  1200. .gfb4:
  1201.         movzx   eax, word [ecx+2]
  1202.         lea     eax, [eax*3]
  1203.         lea     eax, [ecx+eax*4]
  1204.         cmp     word [eax], 0xFFFF
  1205.         jnz     .gfb3
  1206.         push    eax
  1207.         mov     ax, [eax+2]
  1208.         add     ax, [ecx+2]
  1209.         pop     eax
  1210.         jc      .gfb3
  1211.         push    edx
  1212.         mov     edx, [eax+4]
  1213.         push    dword [eax+8]
  1214.         pop     dword [edx+8]
  1215.         mov     edx, [eax+8]
  1216.         push    dword [eax+4]
  1217.         pop     dword [edx+4]
  1218.         pop     edx
  1219.         mov     ax, [eax+2]
  1220.         add     [ecx+2], ax
  1221.         jmp     .gfb4
  1222. .gfb5:
  1223.         mov     ecx, [edx+4]
  1224.         cmp     ecx, edx
  1225.         jz      .gfb8
  1226.         mov     eax, [ecx+4]
  1227.         mov     [eax+8], edx
  1228.         mov     [edx+4], eax
  1229.         movzx   eax, word [ecx+2]
  1230.         push    edx
  1231. .gfb6:
  1232.         sub     eax, 128
  1233.         jbe     .gfb7
  1234.         mov     edx, ecx
  1235.         xchg    edx, [ebp+.FreeList+(.N_INDEXES-1)*4]
  1236.         mov     [ecx], edx
  1237.         add     ecx, 128*.UNIT_SIZE
  1238.         jmp     .gfb6
  1239. .gfb7:
  1240.         add     eax, 128
  1241.         movzx   edx, [.Units2Indx+eax-1]
  1242.         cmp     [.Indx2Units+edx], al
  1243.         jz      @f
  1244.         dec     edx
  1245.         push    edx
  1246.         movzx   edx, [.Indx2Units+edx]
  1247.         sub     eax, edx
  1248.         lea     eax, [ebp+.FreeList+(eax-1)*4]
  1249.         lea     edx, [edx*3]
  1250.         lea     edx, [ecx+edx*4]
  1251.         push    dword [eax]
  1252.         pop     dword [edx]
  1253.         mov     [eax], edx
  1254.         pop     edx
  1255. @@:
  1256.         mov     eax, ecx
  1257.         xchg    eax, [ebp+.FreeList+edx*4]
  1258.         mov     [ecx], eax
  1259.         pop     edx
  1260.         jmp     .gfb5
  1261. .gfb8:
  1262.         pop     ecx
  1263.         pop     eax
  1264.         mov     edx, [ebp+.FreeList+eax*4]
  1265.         test    edx, edx
  1266.         jz      .aur.cont
  1267.         push    edx
  1268.         mov     edx, [edx]
  1269.         mov     [ebp+.FreeList+eax*4], edx
  1270.         pop     eax
  1271.         ret
  1272.  
  1273. .AllocContext:
  1274. ; CSubAllocator::AllocContext
  1275.         mov     eax, [ebp+.HiUnit]
  1276.         cmp     eax, [ebp+.LoUnit]
  1277.         jz      @f
  1278.         sub     eax, .UNIT_SIZE
  1279.         mov     [ebp+.HiUnit], eax
  1280.         ret
  1281. @@:
  1282.         mov     eax, [ebp+.FreeList]
  1283.         test    eax, eax
  1284.         jz      @f
  1285.         mov     edx, [eax]
  1286.         mov     [ebp+.FreeList], edx
  1287.         ret
  1288. @@:
  1289.         xor     eax, eax
  1290.         jmp     .AllocUnitsRare
  1291.  
  1292. .AllocUnits:
  1293. ; CSubAllocator::AllocUnits(ecx)
  1294.         movzx   ecx, [.Units2Indx+ecx-1]
  1295.         mov     eax, [ebp+.FreeList+ecx*4]
  1296.         test    eax, eax
  1297.         jz      @f
  1298.         mov     edx, [eax]
  1299.         mov     [ebp+.FreeList+ecx*4], edx
  1300.         ret
  1301. @@:
  1302.         mov     eax, [ebp+.LoUnit]
  1303.         movzx   edx, [.Indx2Units+ecx]
  1304.         lea     edx, [edx*3]
  1305.         lea     eax, [eax+edx*4]
  1306.         cmp     eax, [ebp+.HiUnit]
  1307.         ja      @f
  1308.         xchg    eax, [ebp+.LoUnit]
  1309.         ret
  1310. @@:
  1311.         mov     eax, ecx
  1312.  
  1313. .AllocUnitsRare:
  1314. ; CSubAllocator::AllocUnitsRare(eax)
  1315.         cmp     [ebp+.GlueCount], 0
  1316.         jz      .GlueFreeBlocks
  1317. .aur.cont:
  1318.         push    eax
  1319. .aur1:
  1320.         inc     eax
  1321.         cmp     eax, .N_INDEXES
  1322.         jz      .aur3
  1323.         mov     edx, [ebp+.FreeList+eax*4]
  1324.         test    edx, edx
  1325.         jz      .aur1
  1326.         push    edx
  1327.         mov     edx, [edx]
  1328.         mov     [ebp+.FreeList+eax*4], edx
  1329.         call    .SplitBlock
  1330.         pop     eax
  1331.         pop     edx
  1332.         ret
  1333. .aur3:
  1334.         dec     [ebp+.GlueCount]
  1335.         pop     eax
  1336.         movzx   eax, [.Indx2Units+eax]
  1337.         lea     edx, [eax*3]
  1338.         shl     edx, 2
  1339.         mov     eax, [ebp+.UnitsStart]
  1340.         sub     eax, [ebp+.pText]
  1341.         cmp     eax, edx
  1342.         jbe     .aur4
  1343.         mov     eax, [ebp+.UnitsStart]
  1344.         sub     eax, edx
  1345.         mov     [ebp+.UnitsStart], eax
  1346.         ret
  1347. .aur4:
  1348.         xor     eax, eax
  1349.         ret
  1350.  
  1351. .SplitBlock:
  1352. ; CSubAllocator::SplitBlock(pv=[esp+4],oldIndx=eax,newIndx=[esp+8])
  1353.         push    eax
  1354.         mov     edx, [esp+12]
  1355.         movzx   eax, [.Indx2Units+eax]
  1356.         movzx   edx, [.Indx2Units+edx]
  1357.         sub     eax, edx
  1358.         lea     edx, [edx*3]
  1359.         push    ecx
  1360.         mov     ecx, [esp+12]
  1361.         lea     ecx, [ecx+edx*4]
  1362.         movzx   edx, [.Units2Indx+eax-1]
  1363.         cmp     [.Indx2Units+edx], al
  1364.         jz      .aur2
  1365.         push    dword [ebp+.FreeList+(edx-1)*4]
  1366.         pop     dword [ecx]
  1367.         mov     [ebp+.FreeList+(edx-1)*4], ecx
  1368.         movzx   edx, [.Indx2Units+edx-1]
  1369.         sub     eax, edx
  1370.         lea     edx, [edx*3]
  1371.         lea     ecx, [ecx+edx*4]
  1372. .aur2:
  1373.         movzx   eax, [.Units2Indx+eax-1]
  1374.         push    dword [ebp+.FreeList+eax*4]
  1375.         pop     dword [ecx]
  1376.         mov     [ebp+.FreeList+eax*4], ecx
  1377.         pop     ecx
  1378.         pop     eax
  1379.         ret
  1380.  
  1381. .ExpandUnits:
  1382. ; CSubAllocator::ExpandUnits(void* oldPtr=esi, int oldNU=eax)
  1383.         push    edx
  1384.         movzx   edx, [.Units2Indx + eax - 1]
  1385.         cmp     dl, [.Units2Indx + eax]
  1386.         jnz     @f
  1387.         pop     edx
  1388.         mov     eax, esi
  1389.         ret
  1390. @@:
  1391.         push    eax ecx edx
  1392.         lea     ecx, [eax+1]
  1393.         call    .AllocUnits
  1394.         pop     edx
  1395.         test    eax, eax
  1396.         jz      @f
  1397.         push    esi edi
  1398.         mov     edi, eax
  1399.         mov     ecx, [esp+8+4]
  1400.         lea     ecx, [ecx*3]
  1401.         rep     movsd
  1402.         pop     edi esi
  1403.         mov     ecx, [ebp+.FreeList+edx*4]
  1404.         mov     [esi], ecx
  1405.         mov     [ebp+.FreeList+edx*4], esi
  1406. @@:
  1407.         pop     ecx
  1408.         add     esp, 4
  1409.         pop     edx
  1410.         ret
  1411.  
  1412. .ShrinkUnits:
  1413. ; CSubAllocator::ShrinkUnits(void* oldPtr=eax, int oldNU=ebx, int newNU=ecx)
  1414.         push    ecx
  1415.         movzx   ebx, [.Units2Indx+ebx-1]
  1416.         movzx   ecx, [.Units2Indx+ecx-1]
  1417.         cmp     ebx, ecx
  1418.         jnz     @f
  1419.         pop     ecx
  1420.         ret
  1421. @@:
  1422.         mov     edx, [ebp+.FreeList+ecx*4]
  1423.         test    edx, edx
  1424.         jz      @f
  1425.         push    dword [edx]
  1426.         pop     [ebp+.FreeList+ecx*4]
  1427.         pop     ecx
  1428.         push    esi edi
  1429.         mov     esi, eax
  1430.         mov     edi, edx
  1431.         lea     ecx, [ecx*3]
  1432.         rep     movsd
  1433.         pop     edi esi
  1434.         mov     ecx, [ebp+.FreeList+ebx*4]
  1435.         mov     [eax], ecx
  1436.         mov     [ebp+.FreeList+ebx*4], eax
  1437.         mov     eax, edx
  1438.         ret
  1439. @@:
  1440.         push    ecx
  1441.         push    eax
  1442.         mov     eax, ebx
  1443.         call    .SplitBlock
  1444.         pop     eax
  1445.         pop     ecx
  1446.         pop     ecx
  1447.         ret
  1448.  
  1449. .FreeUnits:
  1450. ; CSubAllocator::FreeUnits(void* ptr=eax, int oldNU=ebx)
  1451.         movzx   ebx, [.Units2Indx+ebx-1]
  1452.         push    [ebp+.FreeList+ebx*4]
  1453.         pop     dword [eax]
  1454.         mov     [ebp+.FreeList+ebx*4], eax
  1455.         ret
  1456.  
  1457. ppmd_get_buf_size:
  1458.         cmp     dword [esi-4], 5
  1459.         jb      return.err
  1460.         lodsb
  1461.         lodsd
  1462.         cmp     eax, ppmd_decoder.kMaxMemBlockSize
  1463.         ja      return.err
  1464.         add     eax, ppmd_decoder.basesize + ppmd_decoder.kExtraSize
  1465.         mov     edx, 0x4000
  1466.         ret
  1467.  
  1468. ppmd_init_decoder:
  1469.         mov     [ebp+ppmd_decoder.bInited], 0
  1470. ; CDecoder::SetDecoderProperties2
  1471.         lodsb
  1472.         mov     [ebp+ppmd_decoder.order], al
  1473.         lodsd
  1474.         mov     [ebp+ppmd_decoder.usedMemorySize], eax
  1475. ; CSubAllocator::CSubAllocator
  1476.         xor     eax, eax
  1477.         mov     [ebp+ppmd_decoder.GlueCount], al
  1478.         lea     edi, [ebp+ppmd_decoder.LoUnit]
  1479.         mov     ecx, (ppmd_decoder.SEE2Cont - ppmd_decoder.LoUnit)/4
  1480.         rep     stosd
  1481. ; CSubAllocator::StartSubAllocator
  1482.         lea     eax, [ebp+ppmd_decoder.Base+ppmd_decoder.UNIT_SIZE]
  1483.         mov     [ebp+ppmd_decoder.HeapStart], eax
  1484.         mov     [ebp+streamInfo.fillBuf], ppmd_decoder.fillBuf
  1485.         ret
  1486.