kolibrios/programs/fs/kfar/trunk/kfar_arc/7zbranch.inc
Evgeny Grechnikov (Diamond) 1d9fff9e92 KFar 0.4 + KFar_Arc 0.1
git-svn-id: svn://kolibrios.org@589 a494cfbc-eb01-0410-851d-a64ba20cac60
2007-07-26 12:45:49 +00:00

470 lines
13 KiB
PHP

; Branch filters for 7-Zip archives: BCJ and BCJ2.
; Ported from C++ sources of 7-Zip (c) Igor Pavlov.
virtual at 0
bcj_decoder:
.outStream rb streamInfo.size
.inStream dd ?
.inPtr dd ?
.inSize dd ?
.nowPos dd ? ; offset in stream
.prevPos dd ? ; pointer in buffer
.prevMask db ?
.numRest db ?
rw 1
.dwordRest dd ?
.tempSize dd ?
.tempDword dd ?
.size = $
end virtual
bcj_get_buf_size:
mov eax, bcj_decoder.size
mov edx, 0x4000
ret
bcj_init_decoder:
mov [ebp+streamInfo.fillBuf], bcj_fillBuf
xor edx, edx
mov [ebp+bcj_decoder.inPtr], edx
mov [ebp+bcj_decoder.inSize], edx
mov [ebp+bcj_decoder.prevPos], edx
mov [ebp+bcj_decoder.nowPos], edx
mov [ebp+bcj_decoder.numRest], dl
ret
bcj_fillBuf:
add [eax+bcj_decoder.nowPos], ecx
mov ebp, ecx ; save output size
mov esi, [eax+bcj_decoder.inPtr]
mov ebx, [eax+bcj_decoder.inStream]
mov ecx, [eax+bcj_decoder.inSize]
add esi, [ebx+streamInfo.bufPtr]
mov ebx, eax
cmp [eax+bcj_decoder.prevPos], 0
jz @f
add [eax+bcj_decoder.prevPos], edi
@@:
cmp [ebx+bcj_decoder.numRest], 0
jz .mainloop
sub ebp, 1
js .mainloopdone
dec [ebx+bcj_decoder.numRest]
mov eax, [ebx+bcj_decoder.dwordRest]
stosb
shr eax, 8
mov [ebx+bcj_decoder.dwordRest], eax
jmp @b
.mainloop:
sub ebp, 1
js .mainloopdone
sub ecx, 1
js .refill1
.filled1:
lodsb
.filled2:
stosb
cmp al, 0xE8
jz .filter
cmp al, 0xE9
jnz .mainloop
.filter:
and [ebx+bcj_decoder.tempSize], 0
sub ecx, 4
jb .nopos
js .nopos2
lodsd
push eax
.posok:
xor edx, edx
mov eax, edi
sub eax, [ebx+bcj_decoder.prevPos]
cmp eax, 5
ja .maskok
movzx edx, [ebx+bcj_decoder.prevMask]
@@:
and edx, 0x77
add edx, edx
sub eax, 1
jnz @b
.maskok:
mov [ebx+bcj_decoder.prevMask], dl
mov [ebx+bcj_decoder.prevPos], edi
mov al, [esp+3]
add al, 1
cmp al, 2
jae .miss
cmp dl, 0x20
jae .miss2
lea eax, [edx-1]
test eax, edx
jnz .miss2
pop eax
shr edx, 1
push ecx
mov cl, [bcj_kMaskToBitNumber+edx]
iglobal
bcj_kMaskToBitNumber db 24,16,8,8,0,0,0,0
endg
@@:
sub eax, [ebx+bcj_decoder.nowPos]
add eax, [ebx+streamInfo.bufDataLen]
sub eax, edi
sub eax, 4
add eax, [ebx+streamInfo.bufPtr]
cmp cl, 24
jz @f
push eax
shr eax, cl
add al, 1
cmp al, 2
pop eax
jae @f
mov edx, 0x100
shl edx, cl
sub edx, 1
xor eax, edx
jmp @b
@@:
pop ecx
shl eax, 7
sar eax, 7
sub ebp, 4
jb .finalize_dword
stosd
jmp .mainloop
.miss2:
or [ebx+bcj_decoder.prevMask], 10h
.miss:
or [ebx+bcj_decoder.prevMask], 1
cmp [ebx+bcj_decoder.tempSize], 0
jz @f
lea esi, [ebx+bcj_decoder.tempDword]
pop dword [esi]
mov ecx, [ebx+bcj_decoder.tempSize]
jmp .mainloop
@@:
pop eax
sub esi, 4
add ecx, 4
jmp .mainloop
.finalize_dword:
add ebp, 4
mov [ebx+bcj_decoder.numRest], 4
@@:
dec ebp
js .save_dword
stosb
dec [ebx+bcj_decoder.numRest]
shr eax, 8
jmp @b
.save_dword:
mov [ebx+bcj_decoder.dwordRest], eax
.mainloopdone:
mov eax, [ebx+bcj_decoder.prevPos]
test eax, eax
jz .noprev
sub eax, edi
mov [ebx+bcj_decoder.prevPos], eax
.noprev:
mov eax, [ebx+bcj_decoder.inStream]
sub esi, [eax+streamInfo.bufPtr]
mov [ebx+bcj_decoder.inPtr], esi
mov [ebx+bcj_decoder.inSize], ecx
popad
ret
.refill1:
cmp ecx, -1
jz .refill0
lodsb
cmp ecx, -4
jnz @f
mov ecx, [ebx+bcj_decoder.inStream]
mov esi, [ecx+streamInfo.bufPtr]
mov ecx, [ecx+streamInfo.bufDataLen]
@@:
jmp .filled2
.refill0:
mov eax, [ebx+bcj_decoder.inStream]
call fillBuf
mov esi, [eax+streamInfo.bufPtr]
mov ecx, [eax+streamInfo.bufDataLen]
sub ecx, 1
js return.err
jmp .filled1
.nopos:
mov eax, [ebx+bcj_decoder.inStream]
cmp dword [eax+streamInfo.fullSize+4], 0
jnz .hasdata
push ecx
add ecx, dword [eax+streamInfo.fullSize]
pop ecx
jc .hasdata
add ecx, 4
jmp .mainloop
.hasdata:
mov [ebx+bcj_decoder.tempSize], ecx
push 0
push edi
lea edi, [esp+4]
add ecx, 4
rep movsb
sub esi, ebx
sub esi, 1
cmp esi, bcj_decoder.tempDword+4
jbe @f
call fillBuf
@@:
mov esi, [eax+streamInfo.bufPtr]
mov ecx, [ebx+bcj_decoder.tempSize]
neg ecx
rep movsb
pop edi
mov ecx, [eax+streamInfo.bufDataLen]
add ecx, [ebx+bcj_decoder.tempSize]
cmp [ebx+bcj_decoder.tempSize], -4
jnz .posok
and [ebx+bcj_decoder.tempSize], 0
jmp .posok
.nopos2:
mov eax, [ebx+bcj_decoder.inStream]
add ecx, 4
jmp .hasdata
virtual at 0
bcj2_decoder:
.outStream rb streamInfo.size
.mainInStream dd ?
.callStream dd ?
.jumpStream dd ?
.rangeDecoder dd ?
.dwordRest dd ?
.prevByte db ?
.numRest db ?
.bInited db ?
rb 1
.inPtr dd ?
.inSize dd ?
.callPtr dd ?
.jumpPtr dd ?
.callSize dd ?
.jumpSize dd ?
.rangeDecPtr dd ?
.rangeDecSize dd ?
.nowPos dd ?
.range dd ?
.code dd ?
.statusE9Decoder dd ?
.statusJccDecoder dd ?
.statusE8Decoder rd 256
.size = $
end virtual
bcj2_get_buf_size:
mov eax, bcj2_decoder.size
mov edx, 0x4000
ret
bcj2_init_decoder:
mov [ebp+streamInfo.fillBuf], bcj2_fillBuf
mov eax, lzma_decoder.kBitModelTotal/2
mov ecx, 256+1+1
lea edi, [ebp+bcj2_decoder.statusE9Decoder]
rep stosd
mov dword [ebp+bcj2_decoder.prevByte], ecx
mov [ebp+bcj2_decoder.inSize], ecx
mov [ebp+bcj2_decoder.callSize], ecx
mov [ebp+bcj2_decoder.jumpSize], ecx
mov [ebp+bcj2_decoder.rangeDecSize], ecx
mov [ebp+bcj2_decoder.nowPos], ecx
ret
bcj2_fillBuf.init:
mov eax, [eax+bcj2_decoder.rangeDecoder]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
sub edx, 5
jb return.err
mov [ebp+bcj2_decoder.rangeDecSize], edx
mov edx, [eax+streamInfo.bufPtr]
add edx, 5
mov [ebp+bcj2_decoder.rangeDecPtr], edx
mov edx, [edx-4]
bswap edx
mov [ebp+bcj2_decoder.code], edx
or [ebp+bcj2_decoder.range], -1
mov [ebp+bcj2_decoder.bInited], 1
mov eax, ebp
jmp bcj2_fillBuf.inited
bcj2_fillBuf:
mov ebp, eax
cmp [eax+bcj2_decoder.bInited], 0
jz .init
.inited:
add [eax+bcj2_decoder.nowPos], ecx
mov esi, [eax+bcj2_decoder.inPtr]
@@:
cmp [ebp+bcj2_decoder.numRest], 0
jz .mainloop
sub ecx, 1
js .mainloopdone
dec [ebp+bcj2_decoder.numRest]
mov eax, [ebp+bcj2_decoder.dwordRest]
stosb
mov [ebp+bcj2_decoder.prevByte], al
shr eax, 8
mov [ebp+bcj2_decoder.dwordRest], eax
jmp @b
.mainloop:
sub ecx, 1
js .mainloopdone
sub [ebp+bcj2_decoder.inSize], 1
js .refill1
.filled1:
lodsb
stosb
cmp al, 0xE8
jz .e8
cmp al, 0xE9
jz .e9
cmp [ebp+bcj2_decoder.prevByte], 0xF
mov [ebp+bcj2_decoder.prevByte], al
jnz .mainloop
and al, 0xF0
cmp al, 0x80
jnz .mainloop
.jcc:
lea eax, [ebp+bcj2_decoder.statusJccDecoder]
call .RangeDecoderBitDecode
jnc .mainloop
jmp .getptrj
.e8:
movzx eax, al
xchg al, [ebp+bcj2_decoder.prevByte]
lea eax, [ebp+bcj2_decoder.statusE8Decoder+eax*4]
call .RangeDecoderBitDecode
jnc .mainloop
lea eax, [ebp+bcj2_decoder.callPtr]
jmp .getptr
.e9:
mov [ebp+bcj2_decoder.prevByte], al
lea eax, [ebp+bcj2_decoder.statusE9Decoder]
call .RangeDecoderBitDecode
jnc .mainloop
.getptrj:
lea eax, [ebp+bcj2_decoder.jumpPtr]
.getptr:
sub dword [eax+8], 4
js .refill2
.filled2:
add dword [eax], 4
mov eax, [eax]
mov eax, [eax-4]
bswap eax
sub eax, [ebp+bcj2_decoder.nowPos]
add eax, [ebp+streamInfo.bufDataLen]
sub eax, edi
sub eax, 4
add eax, [ebp+streamInfo.bufPtr]
sub ecx, 4
jb .finalize_dword
stosd
shr eax, 24
mov [ebp+bcj2_decoder.prevByte], al
jmp .mainloop
.finalize_dword:
add ecx, 4
mov [ebp+bcj2_decoder.numRest], 4
@@:
dec ecx
js .save_dword
stosb
dec [ebp+bcj2_decoder.numRest]
shr eax, 8
jmp @b
.save_dword:
mov [ebp+bcj2_decoder.dwordRest], eax
.mainloopdone:
mov [ebp+bcj2_decoder.inPtr], esi
popad
ret
.refill1:
mov eax, [ebp+bcj2_decoder.mainInStream]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
dec edx
js return.err
mov [ebp+bcj2_decoder.inSize], edx
mov esi, [eax+streamInfo.bufPtr]
jmp .filled1
.refill2:
push eax
mov eax, [eax-bcj2_decoder.callPtr+bcj2_decoder.callStream]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
sub edx, 4
js return.err
push [eax+streamInfo.bufPtr]
mov eax, [esp+4]
pop dword [eax]
pop eax
mov [eax+8], edx
jmp .filled2
.refill3:
push eax
mov eax, [ebp+bcj2_decoder.rangeDecoder]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
dec edx
js return.err
mov [ebp+bcj2_decoder.rangeDecSize], edx
mov edx, [eax+streamInfo.bufPtr]
mov [ebp+bcj2_decoder.rangeDecPtr], edx
pop eax
jmp .filled3
.RangeDecoderBitDecode:
; in: eax->prob
; out: CF=bit; destroys eax,edx
mov edx, [ebp+bcj2_decoder.range]
shr edx, lzma_decoder.kNumBitModelTotalBits
imul edx, [eax]
cmp [ebp+bcj2_decoder.code], edx
jae .ae
mov [ebp+bcj2_decoder.range], edx
mov edx, lzma_decoder.kBitModelTotal
sub edx, [eax]
shr edx, lzma_decoder.kNumMoveBits
add [eax], edx
clc
.n:
lahf
cmp [ebp+bcj2_decoder.range], lzma_decoder.kTopValue
jae @f
shl [ebp+bcj2_decoder.range], 8
shl [ebp+bcj2_decoder.code], 8
dec [ebp+bcj2_decoder.rangeDecSize]
js .refill3
.filled3:
mov edx, [ebp+bcj2_decoder.rangeDecPtr]
mov al, [edx]
add edx, 1
mov [ebp+bcj2_decoder.rangeDecPtr], edx
mov byte [ebp+bcj2_decoder.code], al
@@:
sahf
ret
.ae:
sub [ebp+bcj2_decoder.range], edx
sub [ebp+bcj2_decoder.code], edx
mov edx, [eax]
shr edx, lzma_decoder.kNumMoveBits
sub [eax], edx
stc
jmp .n