$Revision: 514 $ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; void __stdcall unpack(void* packed_data, void* unpacked_data); unpack: pushad mov esi, [esp+32+4] mov edi, [esp+32+8] mov eax, [esi+8] and al, 0xC0 cmp al, 0xC0 jz .failed mov eax, [esi+8] push eax add esi, 12 and al, not 0xC0 dec eax jz .lzma .failed: pop eax popad ret 8 .lzma: call .lzma_unpack .common: pop eax test al, 0x80 jnz .ctr1 test al, 0x40 jz .ok lodsd mov ecx, eax jecxz .ok mov dl, [esi] mov esi, [esp+32+8] .c1: lodsb sub al, 0E8h cmp al, 1 ja .c1 cmp byte [esi], dl jnz .c1 lodsd ; "bswap eax" is not supported on i386 shr ax, 8 ror eax, 16 xchg al, ah sub eax, esi add eax, [esp+32+8] mov [esi-4], eax loop .c1 .ok: popad ret 8 .ctr1: lodsd mov ecx, eax jecxz .ok mov dl, [esi] mov esi, [esp+32+8] .c2: lodsb @@: cmp al, 0xF jnz .f lodsb cmp al, 80h jb @b cmp al, 90h jb @f .f: sub al, 0E8h cmp al, 1 ja .c2 @@: cmp byte [esi], dl jnz .c2 lodsd shr ax, 8 ror eax, 16 xchg al, ah sub eax, esi add eax, [esp+32+8] mov [esi-4], eax loop .c2 jmp .ok .lzma_unpack: .pb = 2 ; pos state bits .lp = 0 ; literal pos state bits .lc = 3 ; literal context bits .posStateMask = ((1 shl .pb)-1) .literalPosMask = ((1 shl .lp)-1) .kNumPosBitsMax = 4 .kNumPosStatesMax = (1 shl .kNumPosBitsMax) .kLenNumLowBits = 3 .kLenNumLowSymbols = (1 shl .kLenNumLowBits) .kLenNumMidBits = 3 .kLenNumMidSymbols = (1 shl .kLenNumMidBits) .kLenNumHighBits = 8 .kLenNumHighSymbols = (1 shl .kLenNumHighBits) .LenChoice = 0 .LenChoice2 = 1 .LenLow = 2 .LenMid = (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits)) .LenHigh = (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits)) .kNumLenProbs = (.LenHigh + .kLenNumHighSymbols) .kNumStates = 12 .kNumLitStates = 7 .kStartPosModelIndex = 4 .kEndPosModelIndex = 14 .kNumFullDistances = (1 shl (.kEndPosModelIndex/2)) .kNumPosSlotBits = 6 .kNumLenToPosStates = 4 .kNumAlignBits = 4 .kAlignTableSize = (1 shl .kNumAlignBits) .kMatchMinLen = 2 .IsMatch = 0 .IsRep = (.IsMatch + (.kNumStates shl .kNumPosBitsMax)) .IsRepG0 = (.IsRep + .kNumStates) .IsRepG1 = (.IsRepG0 + .kNumStates) .IsRepG2 = (.IsRepG1 + .kNumStates) .IsRep0Long = (.IsRepG2 + .kNumStates) .PosSlot = (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax)) .SpecPos = (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits)) .Align_ = (.SpecPos + .kNumFullDistances - .kEndPosModelIndex) .Lencoder = (.Align_ + .kAlignTableSize) .RepLencoder = (.Lencoder + .kNumLenProbs) .Literal = (.RepLencoder + .kNumLenProbs) .LZMA_BASE_SIZE = 1846 ; must be ==Literal .LZMA_LIT_SIZE = 768 .kNumTopBits = 24 .kTopValue = (1 shl .kNumTopBits) .kNumBitModelTotalBits = 11 .kBitModelTotal = (1 shl .kNumBitModelTotalBits) .kNumMoveBits = 5 push edi ; int state=0; xor ebx, ebx mov [.previousByte], bl ; unsigned rep0=1,rep1=1,rep2=1,rep3=1; mov eax, 1 mov edi, .rep0 stosd stosd stosd stosd ; int len=0; ; result=0; mov ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp)) mov eax, .kBitModelTotal/2 mov edi, .p rep stosd ; RangeDecoderInit ; rd->ExtraBytes = 0 ; rd->Buffer = stream ; rd->BufferLim = stream+bufferSize ; rd->Range = 0xFFFFFFFF pop edi mov ebp, [esi-8] ; dest_length add ebp, edi ; ebp = destination limit lodsd ; rd->code_ = eax mov [.code_], eax or [.range], -1 .main_loop: cmp edi, ebp jae .main_loop_done mov edx, edi and edx, .posStateMask mov eax, ebx shl eax, .kNumPosBitsMax+2 lea eax, [.p + .IsMatch*4 + eax + edx*4] call .RangeDecoderBitDecode jc .1 movzx eax, [.previousByte] if .literalPosMask mov ah, dl and ah, .literalPosMask end if shr eax, 8-.lc imul eax, .LZMA_LIT_SIZE*4 add eax, .p+.Literal*4 cmp ebx, .kNumLitStates jb .literal xor edx, edx sub edx, [.rep0] mov dl, [edi + edx] call .LzmaLiteralDecodeMatch jmp @f .literal: call .LzmaLiteralDecode @@: mov [.previousByte], al stosb mov al, bl cmp bl, 4 jb @f mov al, 3 cmp bl, 10 jb @f mov al, 6 @@: sub bl, al jmp .main_loop .1: lea eax, [.p + .IsRep*4 + ebx*4] call .RangeDecoderBitDecode jnc .10 lea eax, [.p + .IsRepG0*4 + ebx*4] call .RangeDecoderBitDecode jc .111 mov eax, ebx shl eax, .kNumPosBitsMax+2 lea eax, [.p + .IsRep0Long*4 + eax + edx*4] call .RangeDecoderBitDecode jc .1101 cmp bl, 7 setae bl lea ebx, [9 + ebx + ebx] xor edx, edx sub edx, [.rep0] mov al, [edi + edx] stosb mov [.previousByte], al jmp .main_loop .111: lea eax, [.p + .IsRepG1*4 + ebx*4] call .RangeDecoderBitDecode mov eax, [.rep1] jnc .l3 .l1: lea eax, [.p + .IsRepG2*4 + ebx*4] call .RangeDecoderBitDecode mov eax, [.rep2] jnc .l2 xchg [.rep3], eax .l2: push [.rep1] pop [.rep2] .l3: xchg eax, [.rep0] mov [.rep1], eax .1101: mov eax, .p + .RepLencoder*4 call .LzmaLenDecode cmp bl, 7 setc bl adc bl, bl xor bl, 3 add bl, 8 jmp .repmovsb .10: mov eax, [.rep0] xchg eax, [.rep1] xchg eax, [.rep2] xchg eax, [.rep3] cmp bl, 7 setc bl adc bl, bl xor bl, 3 add bl, 7 mov eax, .p + .Lencoder*4 call .LzmaLenDecode mov eax, .kNumLenToPosStates-1 cmp eax, ecx jb @f mov eax, ecx @@: push ecx mov ecx, .kNumPosSlotBits shl eax, cl shl eax, 2 add eax, .p+.PosSlot*4 call .RangeDecoderBitTreeDecode mov [.rep0], ecx cmp ecx, .kStartPosModelIndex jb .l6 push ecx mov eax, ecx and eax, 1 shr ecx, 1 or eax, 2 dec ecx shl eax, cl mov [.rep0], eax pop edx cmp edx, .kEndPosModelIndex jae .l5 sub eax, edx shl eax, 2 add eax, .p + (.SpecPos - 1)*4 call .RangeDecoderReverseBitTreeDecode add [.rep0], ecx jmp .l6 .l5: sub ecx, .kNumAlignBits call .RangeDecoderDecodeDirectBits mov ecx, .kNumAlignBits shl eax, cl add [.rep0], eax mov eax, .p+.Align_*4 call .RangeDecoderReverseBitTreeDecode add [.rep0], ecx .l6: pop ecx inc [.rep0] jz .main_loop_done .repmovsb: add ecx, .kMatchMinLen push esi mov esi, edi sub esi, [.rep0] rep movsb pop esi mov al, [edi-1] mov [.previousByte], al jmp .main_loop .main_loop_done: ret .RangeDecoderBitDecode: ; in: eax->prob ; out: CF=bit; destroys eax push edx mov edx, [.range] shr edx, .kNumBitModelTotalBits imul edx, [eax] cmp [.code_], edx jae .ae mov [.range], edx mov edx, .kBitModelTotal sub edx, [eax] shr edx, .kNumMoveBits add [eax], edx clc .n: lahf cmp [.range], .kTopValue jae @f shl [.range], 8 shl [.code_], 8 lodsb mov byte [.code_], al @@: sahf pop edx ret .ae: sub [.range], edx sub [.code_], edx mov edx, [eax] shr edx, .kNumMoveBits sub [eax], edx stc jmp .n .RangeDecoderDecodeDirectBits: ; in: ecx=numTotalBits ; out: eax=result; destroys edx xor eax, eax .l: shr [.range], 1 shl eax, 1 mov edx, [.code_] sub edx, [.range] jb @f mov [.code_], edx or eax, 1 @@: cmp [.range], .kTopValue jae @f shl [.range], 8 shl [.code_], 8 push eax lodsb mov byte [.code_], al pop eax @@: loop .l ret .LzmaLiteralDecode: ; in: eax->probs ; out: al=byte; destroys edx push ecx mov ecx, 1 @@: push eax lea eax, [eax+ecx*4] call .RangeDecoderBitDecode pop eax adc cl, cl jnc @b .LzmaLiteralDecode.ret: mov al, cl pop ecx ret .LzmaLiteralDecodeMatch: ; in: eax->probs, dl=matchByte ; out: al=byte; destroys edx push ecx mov ecx, 1 .LzmaLiteralDecodeMatch.1: add dl, dl setc ch push eax lea eax, [eax+ecx*4+0x100*4] call .RangeDecoderBitDecode pop eax adc cl, cl jc .LzmaLiteralDecode.ret xor ch, cl test ch, 1 mov ch, 0 jnz @b jmp .LzmaLiteralDecodeMatch.1 .LzmaLenDecode: ; in: eax->prob, edx=posState ; out: ecx=len push eax add eax, .LenChoice*4 call .RangeDecoderBitDecode pop eax jnc .0 push eax add eax, .LenChoice2*4 call .RangeDecoderBitDecode pop eax jc @f mov ecx, .kLenNumMidBits shl edx, cl lea eax, [eax + .LenMid*4 + edx*4] call .RangeDecoderBitTreeDecode add ecx, .kLenNumLowSymbols ret @@: add eax, .LenHigh*4 mov ecx, .kLenNumHighBits call .RangeDecoderBitTreeDecode add ecx, .kLenNumLowSymbols + .kLenNumMidSymbols ret .0: mov ecx, .kLenNumLowBits shl edx, cl lea eax, [eax + .LenLow*4 + edx*4] .RangeDecoderBitTreeDecode: ; in: eax->probs,ecx=numLevels ; out: ecx=length; destroys edx push ebx mov edx, 1 mov ebx, edx @@: push eax lea eax, [eax+edx*4] call .RangeDecoderBitDecode pop eax adc dl, dl add bl, bl loop @b sub dl, bl pop ebx mov ecx, edx ret .RangeDecoderReverseBitTreeDecode: ; in: eax->probs,ecx=numLevels ; out: ecx=length; destroys edx push ebx ecx mov edx, 1 xor ebx, ebx @@: push eax lea eax, [eax+edx*4] call .RangeDecoderBitDecode lahf adc edx, edx sahf rcr ebx, 1 pop eax loop @b pop ecx rol ebx, cl mov ecx, ebx pop ebx ret uglobal align 4 unpack.p rd unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp)) unpack.code_ dd ? unpack.range dd ? unpack.rep0 dd ? unpack.rep1 dd ? unpack.rep2 dd ? unpack.rep3 dd ? unpack.previousByte db ? endg