Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 588 → Rev 589

/programs/fs/kfar/trunk/kfar_arc/ppmd.inc
0,0 → 1,1485
; 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=<n> 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