; PPMD decoder, ported from C++ sources of 7-Zip (c) Igor Pavlov ; C++ code is based on Dmitry Shkarin's PPMdH code uglobal ppmd_decoder.NS2Indx rb 256 ppmd_decoder.NS2BSIndx rb 256 ppmd_decoder.HB2Flag rb 256 ppmd_decoder.Indx2Units rb ppmd_decoder.N_INDEXES ppmd_decoder.Units2Indx rb 128 endg iglobal label ppmd_decoder.InitBinEsc word dw 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051 ppmd_decoder.ExpEscape db 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 endg init_ppmd: ; NS2Indx table mov edi, ppmd_decoder.NS2Indx xor eax, eax stosb inc eax stosb inc eax stosb mov edx, 3-256 @@: lea ecx, [eax-1] inc eax add edx, ecx jc @f rep stosb jmp @b @@: sub ecx, edx rep stosb ; NS2BSIndx table xor eax, eax stosb add al, 2 stosb add al, 2 mov cl, 9 rep stosb add al, 2 mov cl, 256-11 rep stosb ; HB2Flag table mov cl, 0x40/4 xor eax, eax rep stosd mov al, 8 mov cl, 0x100-0x40 rep stosb ; Indx2Units table mov eax, 0x04030201 stosd mov eax, 0x0C0A0806 stosd mov eax, 0x1815120F stosd mov al, 0x1C @@: stosb add al, 4 cmp al, 0x80 jbe @b ; Units2Indx table xor eax, eax xor edx, edx inc edx xor ecx, ecx @@: cmp [ppmd_decoder.Indx2Units+eax], dl adc al, 0 stosb inc edx cmp dl, 0x80 jbe @b ret ppmd_decoder: virtual at 0 ; base is standard structure .outStream rb streamInfo.size .inStream dd ? ; RangeDecoder data .inLen dd ? .inPtr dd ? .code dd ? .range dd ? .outSize dd ? ; number of bytes rest for output ; PPMD data .order db ? .GlueCount db ? .bInited db ? rb 1 .usedMemorySize dd ? ; CSubAllocator constants .N1 = 4 .N2 = 4 .N3 = 4 .N4 = (128+3-1*.N1-2*.N2-3*.N3)/4 .UNIT_SIZE = 12 .N_INDEXES = .N1+.N2+.N3+.N4 .kExtraSize = .UNIT_SIZE*3 .kMaxMemBlockSize = 0xFFFFFFFF - .kExtraSize ; CSubAllocator data .HeapStart dd ? .LoUnit dd ? .HiUnit dd ? .pText dd ? .UnitsStart dd ? .FreeList rd .N_INDEXES ; Context constants .INT_BITS = 7 .PERIOD_BITS = 7 .TOT_BITS = .INT_BITS + .PERIOD_BITS .INTERVAL = 1 shl .INT_BITS .BIN_SCALE = 1 shl .TOT_BITS .MAX_FREQ = 124 .kMaxOrderCompress = 32 .MAX_O = 255 ; CDecodeInfo (inherits from CInfo) data ; SEE2_CONTEXT is 4 bytes long .SEE2Cont rd 25*16 .DummySEE2Cont dd ? .MinContext dd ? .MaxContext dd ? .FoundState dd ? ; found next state transition .NumMasked dd ? .InitEsc dd ? .OrderFall dd ? .RunLength dd ? .InitRL dd ? .CharMask rb 256 .EscCount db ? .PrintCount db ? .PrevSuccess db ? .HiBitsFlag db ? .BinSumm rw 128*64 .basesize = $ .Base: ; rb .kExtraSize + [.usedMemorySize] end virtual .init: mov eax, [eax+.inStream] call fillBuf mov esi, [eax+streamInfo.bufPtr] mov eax, [eax+streamInfo.bufDataLen] sub eax, 5 jb return.err mov [ebp+.inLen], eax inc esi lodsd mov [ebp+.inPtr], esi bswap eax mov [ebp+.code], eax or [ebp+.range], -1 mov [ebp+.bInited], 1 call .StartModelRare mov eax, ebp jmp .mainloop .fillBuf: mov ebp, eax mov [eax+.outSize], ecx cmp [eax+.bInited], 0 jz .init .mainloop: sub [ebp+.outSize], 1 js .mainloopdone ; cmp edi, 0xde070+0x18 ; jnz @f ; int3 ;@@: call .DecodeSymbol jmp .mainloop .mainloopdone: popad ret .GetBinSumm: ; CInfo::GetBinSumm(ebx=rs, ecx=numStates) movzx eax, [ebp+.PrevSuccess] movzx edx, [.NS2BSIndx+ecx-1] add eax, edx mov edx, [ebp+.FoundState] movzx edx, byte [edx] movzx edx, [.HB2Flag+edx] mov [ebp+.HiBitsFlag], dl add eax, edx movzx edx, byte [ebx] movzx edx, [.HB2Flag+edx] lea eax, [eax+edx*2] mov edx, [ebp+.RunLength] shr edx, 26 and edx, 0x20 add eax, edx movzx edx, byte [ebx+1] shl edx, 6 add eax, edx lea ecx, [ebp+.BinSumm+eax*2-2*64] ret .StartModelRare: ; CInfo::StartModelRare(.order) mov [ebp+.EscCount], 1 mov [ebp+.PrintCount], 1 ; N.B. ; 1. Original code has some handling of [.order]<2, but this handling is incorrect ; and causes exception (access violation). ; 2. 7-Zip never generates archives with [.order]<2 due to input preprocessing ; (for PPMd method in switch -mo= archiver checks that 2 <= n <= 32). ; 3. If manually created archive says [.order]<2, the exception will be generated ; in StartModelRare, but it will be handled in Code() resulting in "data error". cmp [ebp+.order], 2 jb return.err mov byte [ebp+.DummySEE2Cont+2], .PERIOD_BITS .RestartModelRare: ; CInfo::RestartModelRare(void) push edi lea edi, [ebp+.CharMask] xor eax, eax push 0x40 pop ecx rep stosd ; CSubAllocator::InitSubAllocator start mov [ebp+.GlueCount], al lea edi, [ebp+.FreeList] mov cl, .N_INDEXES rep stosd mov ebx, [ebp+.HeapStart] mov [ebp+.pText], ebx add ebx, [ebp+.usedMemorySize] mov [ebp+.HiUnit], ebx mov eax, [ebp+.usedMemorySize] xor edx, edx mov cl, 8*.UNIT_SIZE div ecx imul eax, 7*.UNIT_SIZE sub ebx, eax mov [ebp+.LoUnit], ebx mov [ebp+.UnitsStart], ebx ; CSubAllocator::InitSubAllocator end pop edi movzx eax, [ebp+.order] cmp al, 12 jb @f mov al, 12 @@: neg eax dec eax mov [ebp+.InitRL], eax mov [ebp+.RunLength], eax call .AllocContext mov [ebp+.MinContext], eax mov [ebp+.MaxContext], eax and dword [eax+8], 0 mov esi, eax movzx edx, [ebp+.order] mov [ebp+.OrderFall], edx mov dword [eax], 257*10000h+256 mov ecx, 256/2 call .AllocUnits mov [ebp+.FoundState], eax mov [esi+4], eax push edi mov edi, eax xor eax, eax mov [ebp+.PrevSuccess], al @@: stosb mov byte [edi], 1 and dword [edi+1], 0 add edi, 5 inc al jnz @b lea edi, [ebp+.BinSumm] push 2 pop ecx .rmr1: mov esi, .InitBinEsc @@: lodsw xor edx, edx div ecx sub eax, .BIN_SCALE neg eax mov [edi+2*8], ax mov [edi+2*16], ax mov [edi+2*24], ax mov [edi+2*32], ax mov [edi+2*40], ax mov [edi+2*48], ax mov [edi+2*56], ax stosw cmp esi, .InitBinEsc+2*8 jb @b add edi, 128-16 inc ecx cmp ecx, 128+2 jb .rmr1 lea edi, [ebp+.SEE2Cont] mov eax, (10 shl (.PERIOD_BITS-4)) + ((.PERIOD_BITS-4) shl 16) + (4 shl 24) push 25 pop edx @@: push 16 pop ecx rep stosd add ax, 5 shl (.PERIOD_BITS-4) dec edx jnz @b pop edi ret .CreateSuccessors: ; CInfo::CreateSuccessors(bool al=skip,STATE* esi=p1) push ebx edi mov ebx, [ebp+.MinContext] ; ebx=pc mov ecx, [ebp+.FoundState] mov ecx, [ecx+2] ; ecx=UpBranch sub esp, .MAX_O*4 ; esp=ps mov edi, esp ; edi=pps test al, al jnz @f mov eax, [ebp+.FoundState] stosd cmp dword [ebx+8], 0 jz .csnoloop @@: test esi, esi jz .csloopstart mov edx, esi ; edx=p mov ebx, [ebx+8] jmp .csloopentry .csloopstart: mov ebx, [ebx+8] lea edx, [ebx+2] cmp word [ebx], 1 jz .csloopentry mov edx, [ebx+4] mov eax, [ebp+.FoundState] sub edx, 6 mov al, [eax] @@: add edx, 6 cmp al, [edx] jnz @b .csloopentry: cmp ecx, [edx+2] jz @f mov ebx, [edx+2] jmp .csnoloop @@: mov [edi], edx add edi, 4 cmp dword [ebx+8], 0 jnz .csloopstart .csnoloop: cmp edi, esp jz .csr push eax push eax mov al, [ecx] mov [esp], al add ecx, 1 mov [esp+2], ecx mov ah, [ebx+3] cmp word [ebx], 1 jz .cs2 mov edx, [ebx+4] sub edx, 6 @@: add edx, 6 cmp [edx], al jnz @b movzx edx, byte [edx+1] sub edx, 1 ; edx=cf movzx ecx, word [ebx+2] movzx eax, word [ebx] sub ecx, eax sub ecx, edx ; ecx=s0 lea eax, [edx+edx] cmp eax, ecx ja .cs0 lea eax, [edx*5] cmp eax, ecx seta ah jmp .cs1 .cs0: lea eax, [eax+ecx*2] lea eax, [eax+ecx-1] add ecx, ecx xor edx, edx div ecx mov ah, al .cs1: add ah, 1 .cs2: mov [esp+1], ah sub edi, 8 .cs3: ; PPM_CONTEXT::createChild(this=ebx,pStats=[edi+4],FirstState=esp) begin call .AllocContext test eax, eax jz .csr0 mov word [eax], 1 mov dx, [esp] mov [eax+2], dx mov edx, [esp+2] mov [eax+4], edx mov [eax+8], ebx mov edx, [edi+4] mov [edx+2], eax ; PPM_CONTEXT::createChild end mov ebx, eax sub edi, 4 cmp edi, esp jnz .cs3 pop eax eax .csr: mov eax, ebx @@: add esp, .MAX_O*4 pop edi ebx ret .csr0: pop eax eax xor eax, eax jmp @b ; CInfo::UpdateModel(void) .UpdateModel: mov ebx, [ebp+.FoundState] xor esi, esi ; esi=p movzx eax, word [ebx] mov ebx, [ebx+2] ; ebx=fs.Successor push eax cmp ah, .MAX_FREQ/4 jae .um2 mov eax, [ebp+.MinContext] mov eax, [eax+8] test eax, eax jz .um2 cmp word [eax], 1 jz .um1 push eax mov esi, [eax+4] mov al, [esp+4] cmp al, [esi] jz .um0 @@: add esi, 6 cmp al, [esi] jnz @b mov al, [esi+1] cmp al, [esi-6+1] jb @f mov eax, [esi] xchg [esi-6], eax mov [esi], eax mov ax, [esi+4] xchg [esi-6+4], ax mov [esi+4], ax sub esi, 6 @@: .um0: pop eax cmp byte [esi+1], .MAX_FREQ-9 jae @f add byte [esi+1], 2 add word [eax+2], 2 @@: jmp .um2 .um1: lea esi, [eax+2] cmp byte [esi+1], 32 adc byte [esi+1], 0 .um2: cmp [ebp+.OrderFall], 0 jnz .um3 pop eax mov al, 1 call .CreateSuccessors mov [ebp+.MinContext], eax mov [ebp+.MaxContext], eax mov edx, [ebp+.FoundState] mov [edx+2], eax test eax, eax jz .RestartModel ret .um3: mov edx, [ebp+.pText] mov al, [esp] mov [edx], al add edx, 1 ; edx=Successor mov [ebp+.pText], edx cmp edx, [ebp+.UnitsStart] jae .RestartModelPop test ebx, ebx jz .um4 cmp ebx, [ebp+.pText] ja @f push edx xor eax, eax call .CreateSuccessors pop edx mov ebx, eax test eax, eax jz .RestartModelPop @@: sub [ebp+.OrderFall], 1 jnz @f mov edx, ebx xor ecx, ecx mov eax, [ebp+.MinContext] cmp eax, [ebp+.MaxContext] setnz cl sub [ebp+.pText], ecx @@: jmp .um5 .um4: mov eax, [ebp+.FoundState] mov [eax+2], edx mov ebx, [ebp+.MinContext] .um5: mov eax, [ebp+.MinContext] movzx ecx, word [eax] ; ecx=ns movzx eax, word [eax+2] sub eax, ecx push eax movzx eax, byte [esp+5] sub eax, 1 sub [esp], eax ; [esp]=s0 mov esi, [ebp+.MaxContext] ; ebx=pc cmp esi, [ebp+.MinContext] jz .um12 .um6: movzx eax, word [esi] cmp eax, 1 jz .um8 push eax shr eax, 1 jc .um7 push esi mov esi, [esi+4] call .ExpandUnits pop esi mov [esi+4], eax test eax, eax jz .RestartModelPop3 .um7: pop eax add eax, eax cmp eax, ecx adc word [esi+2], 0 add eax, eax cmp eax, ecx ja @f lea eax, [eax+eax+1] cmp word [esi+2], ax ja @f add word [esi+2], 2 @@: push edx jmp .um9 .um8: push edx ecx mov ecx, 1 call .AllocUnits pop ecx test eax, eax jz .RestartModelPop3 mov dx, [esi+2] mov [eax], dx mov edx, [esi+4] mov [eax+2], edx mov [esi+4], eax movzx edx, byte [eax+1] add edx, edx cmp edx, (.MAX_FREQ/4-1)*2 jb @f mov edx, .MAX_FREQ-4 @@: mov [eax+1], dl add edx, [ebp+.InitEsc] cmp ecx, 4 sbb edx, -1 mov [esi+2], dx .um9: movzx edx, word [esi+2] mov eax, [esp+4] push ecx lea ecx, [eax+edx] ; ecx=sf add edx, 6 movzx eax, byte [esp+13] add eax, eax imul eax, edx ; eax=cf lea edx, [ecx*3] add edx, edx cmp eax, edx jae .um10 mov edx, 1 cmp ecx, eax adc edx, 0 shl ecx, 2 add eax, 1 cmp ecx, eax adc edx, 0 add word [esi+2], 3 jmp .um11 .um10: lea ecx, [ecx*3] lea edx, [ecx*3] add eax, 1 push 4 cmp edx, eax adc dword [esp], 0 add edx, ecx cmp edx, eax adc dword [esp], 0 add edx, ecx cmp edx, eax adc dword [esp], 0 pop edx add [esi+2], dx .um11: movzx eax, word [esi] lea eax, [eax*3] add eax, eax add eax, [esi+4] mov ecx, [esp+4] mov [eax+2], ecx mov cl, [esp+12] mov [eax], cl mov [eax+1], dl add word [esi], 1 pop ecx edx mov esi, [esi+8] cmp esi, [ebp+.MinContext] jnz .um6 .um12: pop eax pop eax mov [ebp+.MinContext], ebx mov [ebp+.MaxContext], ebx ret .RestartModelPop3: pop eax pop eax .RestartModelPop: pop eax .RestartModel: call .RestartModelRare mov [ebp+.EscCount], 0 mov [ebp+.PrintCount], 0xFF ret .rescale: mov esi, [ebp+.MinContext] movzx ecx, word [esi] push ecx ; [esp]=OldNS sub ecx, 1 mov ebx, [ebp+.FoundState] cmp ebx, [esi+4] jz .r1 .r0: mov ax, [ebx] xchg [ebx-6], ax mov [ebx], ax mov eax, [ebx+2] xchg [ebx-6+2], eax mov [ebx+2], eax sub ebx, 6 cmp ebx, [esi+4] jnz .r0 .r1: add byte [ebx+1], 4 add word [esi+2], 4 movzx eax, byte [ebx+1] movzx edx, word [esi+2] sub edx, eax ; edx=EscFreq cmp [ebp+.OrderFall], 1 sbb eax, -1 shr eax, 1 mov [ebx+1], al mov [esi+2], ax .r2: add ebx, 6 movzx eax, byte [ebx+1] sub edx, eax cmp [ebp+.OrderFall], 1 sbb eax, -1 shr eax, 1 mov [ebx+1], al add [esi+2], ax cmp al, [ebx-6+1] jbe .r3 push ecx push ebx push dword [ebx] push word [ebx+4] @@: mov ecx, [ebx-6] mov [ebx], ecx mov cx, [ebx-6+4] mov [ebx+4], cx sub ebx, 6 cmp ebx, [esi+4] jz @f cmp al, [ebx-6+1] ja @b @@: pop word [ebx+4] pop dword [ebx] pop ebx pop ecx .r3: sub ecx, 1 jnz .r2 cmp byte [ebx+1], 0 jnz .r4 @@: add ecx, 1 sub ebx, 6 cmp byte [ebx+1], 0 jz @b add edx, ecx sub word [esi], cx cmp word [esi], 1 jnz .r4 pop ebx mov eax, [esi+4] movzx ecx, word [eax+4] push ecx push dword [eax] movzx eax, byte [eax+1] @@: add eax, 1 shr eax, 1 shr edx, 1 cmp edx, 1 ja @b mov [esp+1], al add ebx, 1 shr ebx, 1 mov eax, [esi+4] call .FreeUnits lea ebx, [esi+2] mov [ebp+.FoundState], ebx pop dword [ebx] pop eax mov [ebx+4], ax ret .r4: add edx, 1 shr edx, 1 add [esi+2], dx pop ebx add ebx, 1 shr ebx, 1 movzx ecx, word [esi] add ecx, 1 shr ecx, 1 cmp ebx, ecx jz @f mov eax, [esi+4] call .ShrinkUnits mov [esi+4], eax @@: mov eax, [esi+4] mov [ebp+.FoundState], eax ret .DecodeSymbol: ; CDecodeInfo::DecodeSymbol mov esi, [ebp+.MinContext] cmp word [esi], 1 jz .binsymbol ; CDecodeInfo::DecodeSymbol1 start mov ebx, [esi+4] ; state movzx ecx, word [esi+2] mov eax, [ebp+.range] xor edx, edx div ecx mov [ebp+.range], eax mov ecx, eax mov eax, [ebp+.code] xor edx, edx div ecx movzx edx, byte [ebx+1] cmp eax, edx jae .ds0 push edx add edx, edx cmp dx, [esi+2] pop edx seta [ebp+.PrevSuccess] movzx eax, [ebp+.PrevSuccess] add [ebp+.RunLength], eax xor eax, eax call .RangeDecoder.Decode mov [ebp+.FoundState], ebx add edx, 4 mov [ebx+1], dl add word [esi+2], 4 cmp edx, .MAX_FREQ jbe @f call .rescale @@: jmp .dscmn .ds0: mov [ebp+.PrevSuccess], 0 movzx ecx, word [esi] sub ecx, 1 push eax .ds1: add ebx, 6 movzx eax, byte [ebx+1] add edx, eax cmp edx, [esp] ja .ds2 sub ecx, 1 jnz .ds1 pop eax mov eax, [ebp+.FoundState] movzx eax, byte [eax] mov al, [.HB2Flag+eax] mov [ebp+.HiBitsFlag], al mov eax, edx movzx edx, word [esi+2] sub edx, eax call .RangeDecoder.Decode mov al, [ebp+.EscCount] movzx edx, byte [ebx] mov [ebp+.CharMask+edx], al movzx ecx, word [esi] mov [ebp+.NumMasked], ecx sub ecx, 1 @@: sub ebx, 6 movzx edx, byte [ebx] mov [ebp+.CharMask+edx], al sub ecx, 1 jnz @b mov [ebp+.FoundState], ecx jmp .dscmn .ds2: pop eax mov eax, edx movzx edx, byte [ebx+1] sub eax, edx call .RangeDecoder.Decode .update1: mov [ebp+.FoundState], ebx add byte [ebx+1], 4 add word [esi+2], 4 mov al, [ebx+1] cmp al, [ebx-6+1] jbe @f mov eax, [ebx] xchg eax, [ebx-6] mov [ebx], eax mov ax, [ebx+4] xchg ax, [ebx-6+4] mov [ebx+4], ax sub ebx, 6 mov [ebp+.FoundState], ebx cmp byte [ebx+1], .MAX_FREQ jbe @f call .rescale @@: jmp .dscmn ; CDecodeInfo::DecodeSymbol1 end .binsymbol: ; CDecodeInfo::DecodeBinSymbol start lea ebx, [esi+2] mov ecx, [esi+8] movzx ecx, word [ecx] call .GetBinSumm movzx eax, word [ecx] call .RangeDecoder.DecodeBit jc .ds3 mov [ebp+.FoundState], ebx cmp byte [ebx+1], 128 adc byte [ebx+1], 0 movzx eax, word [ecx] add eax, 1 shl (.PERIOD_BITS-2) shr eax, .PERIOD_BITS sub eax, .INTERVAL sub [ecx], ax mov [ebp+.PrevSuccess], 1 add [ebp+.RunLength], 1 jmp .dscmn .ds3: movzx eax, word [ecx] add eax, 1 shl (.PERIOD_BITS-2) shr eax, .PERIOD_BITS sub [ecx], ax movzx eax, word [ecx] shr eax, 10 movzx eax, [.ExpEscape+eax] mov [ebp+.InitEsc], eax mov [ebp+.NumMasked], 1 mov al, [ebp+.EscCount] movzx edx, byte [ebx] mov [ebp+.CharMask+edx], al mov [ebp+.PrevSuccess], 0 and [ebp+.FoundState], 0 ; CDecodeInfo::DecodeBinSymbol end .dscmn: cmp [ebp+.FoundState], 0 jnz .dsfnd .ds4: add [ebp+.OrderFall], 1 mov eax, [ebp+.MinContext] mov eax, [eax+8] test eax, eax jz return.err ; no end-of-stream mark mov [ebp+.MinContext], eax movzx ecx, word [eax] sub ecx, [ebp+.NumMasked] jz .ds4 ; CDecodeInfo::DecodeSymbol2 start call .makeEscFreq2 push eax mov ebx, [esi+4] sub ebx, 6 sub esp, 256*4 mov esi, esp xor eax, eax push eax @@: add ebx, 6 mov al, [ebx] mov al, [ebp+.CharMask+eax] cmp al, [ebp+.EscCount] jz @b mov al, [ebx+1] add [esp], eax mov [esi], ebx add esi, 4 sub ecx, 1 jnz @b add edx, [esp] mov ecx, edx mov eax, [ebp+.range] xor edx, edx div ecx mov [ebp+.range], eax mov eax, [ebp+.code] xor edx, edx div [ebp+.range] cmp eax, [esp] jae .ds5 pop ecx mov esi, esp xor ecx, ecx @@: mov ebx, [esi] add esi, 4 movzx edx, byte [ebx+1] add ecx, edx cmp eax, ecx jae @b mov eax, ecx movzx edx, byte [ebx+1] sub eax, edx call .RangeDecoder.Decode add esp, 256*4 pop eax mov cl, [eax+2] cmp cl, .PERIOD_BITS jae @f sub byte [eax+3], 1 jnz @f shl word [eax], 1 mov dl, 3 shl dl, cl mov [eax+3], dl add byte [eax+2], 1 @@: .update2: mov [ebp+.FoundState], ebx add byte [ebx+1], 4 mov esi, [ebp+.MinContext] add word [esi+2], 4 cmp byte [ebx+1], .MAX_FREQ jbe @f call .rescale @@: add [ebp+.EscCount], 1 mov eax, [ebp+.InitRL] mov [ebp+.RunLength], eax jmp .dsfnd .ds5: pop eax mov edx, ecx sub edx, eax call .RangeDecoder.Decode mov eax, [ebp+.MinContext] movzx eax, word [eax] mov ebx, eax sub ebx, [ebp+.NumMasked] mov [ebp+.NumMasked], eax mov esi, esp mov al, [ebp+.EscCount] @@: mov edx, [esi] add esi, 4 movzx edx, byte [edx] mov [ebp+.CharMask+edx], al sub ebx, 1 jnz @b add esp, 256*4 pop eax add word [eax], cx ; CDecodeInfo::DecodeSymbol2 end cmp [ebp+.FoundState], 0 jz .ds4 .dsfnd: mov eax, [ebp+.FoundState] mov al, [eax] stosb .NextContext: ; CInfo::NextContext(void) mov ebx, [ebp+.FoundState] mov ebx, [ebx+2] cmp [ebp+.OrderFall], 0 jnz .nc0 cmp ebx, [ebp+.pText] jbe .nc0 mov [ebp+.MinContext], ebx mov [ebp+.MaxContext], ebx ret .nc0: call .UpdateModel cmp [ebp+.EscCount], 0 jz @f ret @@: mov [ebp+.EscCount], 1 push edi lea edi, [ebp+.CharMask] mov ecx, 256/4 xor eax, eax rep stosd pop edi ret .makeEscFreq2: ; CInfo::makeEscFreq2(ecx=Diff)->{eax->SEE2_CONTEXT,edx=scale} mov esi, [ebp+.MinContext] cmp word [esi], 256 jz .mef0 movzx edx, [.NS2Indx+ecx-1] shl edx, 4 mov eax, [esi+8] movzx eax, word [eax] sub ax, [esi] cmp ecx, eax adc edx, 0 movzx eax, word [esi] push edx lea edx, [eax*9] lea edx, [edx+eax*2] movzx eax, word [esi+2] cmp eax, edx pop edx setc al movzx eax, al lea edx, [edx+eax*2] cmp ecx, [ebp+.NumMasked] setc al lea edx, [edx+eax*4] add dl, [ebp+.HiBitsFlag] lea eax, [ebp+edx*4+.SEE2Cont] movzx edx, word [eax] push ecx mov cl, [eax+2] shr edx, cl sub [eax], dx pop ecx cmp edx, 1 adc edx, 0 ret .mef0: lea eax, [ebp+.DummySEE2Cont] mov edx, 1 ret .RangeDecoder.DecodeBit: ; CRangeDecoder::DecodeBit(eax=size0,numTotalBits=.TOT_BITS) mov edx, [ebp+.range] shr edx, .TOT_BITS imul eax, edx cmp [ebp+.code], eax jae .rddb mov [ebp+.range], eax call .RangeDecoder.Normalize clc ret .rddb: sub [ebp+.code], eax sub [ebp+.range], eax call .RangeDecoder.Normalize stc ret .RangeDecoder.Decode: imul eax, [ebp+.range] sub [ebp+.code], eax mov eax, [ebp+.range] imul eax, edx mov [ebp+.range], eax .RangeDecoder.Normalize: cmp byte [ebp+.range+3], 0 jz @f ret @@: sub [ebp+.inLen], 1 js .refill .filled: shl [ebp+.range], 8 shl [ebp+.code], 8 mov eax, [ebp+.inPtr] add [ebp+.inPtr], 1 mov al, [eax] mov byte [ebp+.code], al jmp .RangeDecoder.Normalize .refill: mov eax, [ebp+.inStream] call fillBuf push [eax+streamInfo.bufPtr] pop [ebp+.inPtr] mov eax, [eax+streamInfo.bufDataLen] sub eax, 1 js return.err mov [ebp+.inLen], eax jmp .filled .GlueFreeBlocks: ; CSubAllocator::GlueFreeBlocks, called from AllocUnitsRare push eax mov [ebp+.GlueCount], 255 mov edx, [ebp+.HeapStart] add edx, [ebp+.usedMemorySize] ; we need add extra MEM_BLK with Stamp=0 and word [edx], 0 add edx, .UNIT_SIZE mov eax, [ebp+.LoUnit] cmp eax, [ebp+.HiUnit] jz @f mov byte [eax], 0 @@: mov [edx+4], edx mov [edx+8], edx push ecx xor ecx, ecx .gfb1: mov eax, [ebp+ecx*4+.FreeList] test eax, eax jz .gfb2 push dword [eax] pop dword [ebp+ecx*4+.FreeList] mov [eax+8], edx push edx mov edx, [edx+4] mov [eax+4], edx mov [edx+8], eax or word [eax], 0xFFFF movzx edx, [.Indx2Units+ecx] mov [eax+2], dx pop edx mov [edx+4], eax jmp .gfb1 .gfb2: inc ecx cmp ecx, .N_INDEXES jb .gfb1 mov ecx, edx .gfb3: mov ecx, [ecx+4] cmp ecx, edx jz .gfb5 .gfb4: movzx eax, word [ecx+2] lea eax, [eax*3] lea eax, [ecx+eax*4] cmp word [eax], 0xFFFF jnz .gfb3 push eax mov ax, [eax+2] add ax, [ecx+2] pop eax jc .gfb3 push edx mov edx, [eax+4] push dword [eax+8] pop dword [edx+8] mov edx, [eax+8] push dword [eax+4] pop dword [edx+4] pop edx mov ax, [eax+2] add [ecx+2], ax jmp .gfb4 .gfb5: mov ecx, [edx+4] cmp ecx, edx jz .gfb8 mov eax, [ecx+4] mov [eax+8], edx mov [edx+4], eax movzx eax, word [ecx+2] push edx .gfb6: sub eax, 128 jbe .gfb7 mov edx, ecx xchg edx, [ebp+.FreeList+(.N_INDEXES-1)*4] mov [ecx], edx add ecx, 128*.UNIT_SIZE jmp .gfb6 .gfb7: add eax, 128 movzx edx, [.Units2Indx+eax-1] cmp [.Indx2Units+edx], al jz @f dec edx push edx movzx edx, [.Indx2Units+edx] sub eax, edx lea eax, [ebp+.FreeList+(eax-1)*4] lea edx, [edx*3] lea edx, [ecx+edx*4] push dword [eax] pop dword [edx] mov [eax], edx pop edx @@: mov eax, ecx xchg eax, [ebp+.FreeList+edx*4] mov [ecx], eax pop edx jmp .gfb5 .gfb8: pop ecx pop eax mov edx, [ebp+.FreeList+eax*4] test edx, edx jz .aur.cont push edx mov edx, [edx] mov [ebp+.FreeList+eax*4], edx pop eax ret .AllocContext: ; CSubAllocator::AllocContext mov eax, [ebp+.HiUnit] cmp eax, [ebp+.LoUnit] jz @f sub eax, .UNIT_SIZE mov [ebp+.HiUnit], eax ret @@: mov eax, [ebp+.FreeList] test eax, eax jz @f mov edx, [eax] mov [ebp+.FreeList], edx ret @@: xor eax, eax jmp .AllocUnitsRare .AllocUnits: ; CSubAllocator::AllocUnits(ecx) movzx ecx, [.Units2Indx+ecx-1] mov eax, [ebp+.FreeList+ecx*4] test eax, eax jz @f mov edx, [eax] mov [ebp+.FreeList+ecx*4], edx ret @@: mov eax, [ebp+.LoUnit] movzx edx, [.Indx2Units+ecx] lea edx, [edx*3] lea eax, [eax+edx*4] cmp eax, [ebp+.HiUnit] ja @f xchg eax, [ebp+.LoUnit] ret @@: mov eax, ecx .AllocUnitsRare: ; CSubAllocator::AllocUnitsRare(eax) cmp [ebp+.GlueCount], 0 jz .GlueFreeBlocks .aur.cont: push eax .aur1: inc eax cmp eax, .N_INDEXES jz .aur3 mov edx, [ebp+.FreeList+eax*4] test edx, edx jz .aur1 push edx mov edx, [edx] mov [ebp+.FreeList+eax*4], edx call .SplitBlock pop eax pop edx ret .aur3: dec [ebp+.GlueCount] pop eax movzx eax, [.Indx2Units+eax] lea edx, [eax*3] shl edx, 2 mov eax, [ebp+.UnitsStart] sub eax, [ebp+.pText] cmp eax, edx jbe .aur4 mov eax, [ebp+.UnitsStart] sub eax, edx mov [ebp+.UnitsStart], eax ret .aur4: xor eax, eax ret .SplitBlock: ; CSubAllocator::SplitBlock(pv=[esp+4],oldIndx=eax,newIndx=[esp+8]) push eax mov edx, [esp+12] movzx eax, [.Indx2Units+eax] movzx edx, [.Indx2Units+edx] sub eax, edx lea edx, [edx*3] push ecx mov ecx, [esp+12] lea ecx, [ecx+edx*4] movzx edx, [.Units2Indx+eax-1] cmp [.Indx2Units+edx], al jz .aur2 push dword [ebp+.FreeList+(edx-1)*4] pop dword [ecx] mov [ebp+.FreeList+(edx-1)*4], ecx movzx edx, [.Indx2Units+edx-1] sub eax, edx lea edx, [edx*3] lea ecx, [ecx+edx*4] .aur2: movzx eax, [.Units2Indx+eax-1] push dword [ebp+.FreeList+eax*4] pop dword [ecx] mov [ebp+.FreeList+eax*4], ecx pop ecx pop eax ret .ExpandUnits: ; CSubAllocator::ExpandUnits(void* oldPtr=esi, int oldNU=eax) push edx movzx edx, [.Units2Indx + eax - 1] cmp dl, [.Units2Indx + eax] jnz @f pop edx mov eax, esi ret @@: push eax ecx edx lea ecx, [eax+1] call .AllocUnits pop edx test eax, eax jz @f push esi edi mov edi, eax mov ecx, [esp+8+4] lea ecx, [ecx*3] rep movsd pop edi esi mov ecx, [ebp+.FreeList+edx*4] mov [esi], ecx mov [ebp+.FreeList+edx*4], esi @@: pop ecx add esp, 4 pop edx ret .ShrinkUnits: ; CSubAllocator::ShrinkUnits(void* oldPtr=eax, int oldNU=ebx, int newNU=ecx) push ecx movzx ebx, [.Units2Indx+ebx-1] movzx ecx, [.Units2Indx+ecx-1] cmp ebx, ecx jnz @f pop ecx ret @@: mov edx, [ebp+.FreeList+ecx*4] test edx, edx jz @f push dword [edx] pop [ebp+.FreeList+ecx*4] pop ecx push esi edi mov esi, eax mov edi, edx lea ecx, [ecx*3] rep movsd pop edi esi mov ecx, [ebp+.FreeList+ebx*4] mov [eax], ecx mov [ebp+.FreeList+ebx*4], eax mov eax, edx ret @@: push ecx push eax mov eax, ebx call .SplitBlock pop eax pop ecx pop ecx ret .FreeUnits: ; CSubAllocator::FreeUnits(void* ptr=eax, int oldNU=ebx) movzx ebx, [.Units2Indx+ebx-1] push [ebp+.FreeList+ebx*4] pop dword [eax] mov [ebp+.FreeList+ebx*4], eax ret ppmd_get_buf_size: cmp dword [esi-4], 5 jb return.err lodsb lodsd cmp eax, ppmd_decoder.kMaxMemBlockSize ja return.err add eax, ppmd_decoder.basesize + ppmd_decoder.kExtraSize mov edx, 0x4000 ret ppmd_init_decoder: mov [ebp+ppmd_decoder.bInited], 0 ; CDecoder::SetDecoderProperties2 lodsb mov [ebp+ppmd_decoder.order], al lodsd mov [ebp+ppmd_decoder.usedMemorySize], eax ; CSubAllocator::CSubAllocator xor eax, eax mov [ebp+ppmd_decoder.GlueCount], al lea edi, [ebp+ppmd_decoder.LoUnit] mov ecx, (ppmd_decoder.SEE2Cont - ppmd_decoder.LoUnit)/4 rep stosd ; CSubAllocator::StartSubAllocator lea eax, [ebp+ppmd_decoder.Base+ppmd_decoder.UNIT_SIZE] mov [ebp+ppmd_decoder.HeapStart], eax mov [ebp+streamInfo.fillBuf], ppmd_decoder.fillBuf ret