Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 588 → Rev 589

/programs/fs/kfar/trunk/kfar_arc/7z.inc
0,0 → 1,3138
; Loading of 7z archives was ported from 7z sources (file 7zip\Archive\7z\7zIn.cpp).
; The version 7-Zip 4.42 was used.
; 7-Zip is copyright (C) 1999-2006 Igor Pavlov.
; Assembler version as KFar plugin has been written by diamond, 2007.
 
virtual at 0
file_in_7z:
.fullname dd ? ; pointer to cp866 string
.name dd ?
.namelen dd ?
.bIsDirectory db ?
.bPseudoFolder db ?
rb 2
.parent dd ? ; pointer to parent directory record
.subfolders dd ? ; head of L2-list of subfolders [for folders]
.subfolders.end dd ?
.subfiles dd ? ; head of L2-list of files [for folders]
.subfiles.end dd ?
.NumSubItems dd ?
.next dd ? ; next item of list of subfolders or files
.prev dd ? ; previous item of list of subfolders or files
.attr dd ?
.FileCRC dd ?
.startPos dq ?
.CreationTime dq ?
.LastAccessTime dq ?
.LastWriteTime dq ?
.UnPackSize dq ?
.folder dd ?
.folder_index dd ?
.folderStart dq ?
.bAttrDefined db ?
.bStartPosDefined db ?
.bCRCDefined db ?
.bCreationTimeDefined db ?
.bLastAccessTimeDefined db ?
.bLastWriteTimeDefined db ?
.bHasStream db ?
.bAnti db ?
.stamp dd ?
.size = $
end virtual
 
virtual at 0
handle_7z:
.type dd ?
.root.subfolders dd ?
.root.subfolders.end dd ?
.root.subfiles dd ?
.root.subfiles.end dd ?
.root.NumSubItems dd ?
.curdir dd ?
.NumFiles dd ?
.names_buf dd ?
.host dd ?
.host_datetime rd 6
; streams info
.numPackStreams dd ?
.packSizes dd ?
.numFolders dd ?
.unpackCRCsDefined dd ?
.unpackCRCs dd ?
.folders dd ?
.last_folder dd ?
.last_pos dq ?
.last_context dd ?
.last_main_stream dd ?
.password_len dd ? ; -1 if no password defined; in characters
.password rw password_maxlen
.basesize = $
; .size = .basesize + .NumFiles * file_in_7z.size
end virtual
 
iglobal
align 4
empty_7z_handle:
dd type_7z
dd 0,0,0,0,0,0
endg
 
kEnd = 0
kHeader = 1
kArchiveProperties = 2
kAdditionalStreamsInfo = 3
kMainStreamsInfo = 4
kFilesInfo = 5
kPackInfo = 6
kUnPackInfo = 7
kSubStreamsInfo = 8
kSize = 9
kCRC = 10
kFolder = 11
kCodersUnPackSize = 12
kNumUnPackStream = 13
kEmptyStream = 14
kEmptyFile = 15
kAnti = 16
kName = 17
kCreationTime = 18
kLastAccessTime = 19
kLastWriteTime = 20
kWinAttributes = 21
kComment = 22
kEncodedHeader = 23
kStartPos = 24
 
_7z.ReadByte:
cmp edi, [bufend]
jae return.err
mov al, [edi]
inc edi
ret
_7z.ReadWord:
add edi, 2
cmp edi, [bufend]
ja return.err
mov ax, [edi-2]
ret
_7z.ReadDword:
add edi, 4
cmp edi, [bufend]
ja return.err
mov eax, [edi-4]
ret
 
_7z.SkipSize:
test edx, edx
jnz return.err
add edi, eax
jc return.err
cmp edi, [bufend]
ja return.err
ret
 
_7z.ReadNumber:
xor eax, eax
push eax
push eax
call _7z.ReadByte
push ecx
xor ecx, ecx
@@:
add al, al
jnc @f
inc ecx
jmp @b
@@:
shr eax, cl
shr eax, 1
jz @f
mov [esp+4+ecx], al
@@:
jecxz .ret
push edx
xor edx, edx
@@:
call _7z.ReadByte
mov [esp+8+edx], al
inc edx
loop @b
pop edx
.ret:
pop ecx
pop eax
pop edx
ret
 
_7z.ReadNum:
push edx
call _7z.ReadNumber
test edx, edx
jnz return.err
test eax, eax
js return.err
pop edx
ret
 
open_7z:
; CInArchive::ReadDatabase()
cmp byte [esi+6], 0 ; major version must be 0
; minor version does not be checked ([byte +7]=2 for now)
jz @f
xor eax, eax
ret
@@:
and [hOut], 0
and [_7z.FreeSubStreams], 0
and [_7z.tmpVector], 0
push esi
add esi, 12
mov ecx, 20
call crc
pop esi
cmp eax, [esi+8]
jnz .header_crc_error
cmp dword [esi+24], 0
jnz .header_error
mov edi, buffer
mov ecx, [esi+20]
mov [bufsize], ecx
test ecx, ecx
jnz .notempty
mov eax, empty_7z_handle
push ebp
call [close]
ret
.notempty:
cmp ecx, 1024
jbe @f
call [pgalloc]
test eax, eax
jz .reterr
mov edi, eax
@@:
mov [bufptr], edi
lea eax, [edi+ecx]
mov [bufend], eax
mov eax, [esi+12]
mov edx, [esi+16]
add eax, 20h ; end of main header
adc edx, 0
push edx
push eax
push 0
push ebp
call [seek]
push ecx
push edi
push ebp
call [read]
cmp eax, ecx
jnz .header_error
push esi
mov esi, edi
call crc
pop esi
cmp eax, [esi+28]
jz .header_ok
.header_crc_error:
.header_error:
push ContinueBtn
push 1
push HeaderError_ptr
push 1
call [SayErr]
.clear:
mov ecx, [_7z.tmpVector]
jecxz @f
call [pgfree]
@@:
mov ecx, [hOut]
jecxz @f
call _7z.CloseHandle
@@:
mov ebx, [_7z.dataVectorSize]
test ebx, ebx
jz @f
call _7z.ReadAndDecodePackedStreams.free2
@@:
mov ecx, [_7z.FreeSubStreams]
jecxz @f
call [pgfree]
@@:
mov ecx, [bufptr]
cmp ecx, buffer
jz .reterr
call [pgfree]
.reterr:
or eax, -1
ret
.header_ok:
mov [_esp], esp
mov [inStream], ebp
.loop:
mov [error_proc], .header_error
mov [clear_proc], .clear
and [_7z.dataVectorSize], 0
call _7z.ReadNum
cmp eax, kHeader
jz .found_header
cmp eax, kEncodedHeader
jnz .header_error
call _7z.ReadAndDecodePackedStreams
cmp [_7z.StreamsInfo.numFolders], 0
jz .free_empty
cmp [_7z.StreamsInfo.numFolders], 1
jnz return.err
mov ecx, [bufptr]
cmp ecx, buffer
jz @f
call [pgfree]
@@:
mov edi, [_7z.unpbuf+4]
mov [bufptr], edi
mov ecx, [_7z.unpbuf]
add ecx, edi
mov [bufend], ecx
mov [error_proc], .header_error
mov [clear_proc], .clear
and [_7z.dataVectorSize], 0
call _7z.ReadNum
cmp eax, kHeader
jz .found_header
jmp return.err
.free_empty:
mov ecx, [bufptr]
cmp ecx, buffer
jz @f
call [pgfree]
@@:
push [inStream]
call [close]
mov eax, empty_7z_handle
ret
.found_header:
call _7z.ReadNum
cmp eax, kArchiveProperties
jnz .no_archive_props
@@:
call _7z.ReadNum
test eax, eax
jz @f
call _7z.SkipData
jmp @b
@@:
call _7z.ReadNum
.no_archive_props:
cmp eax, kAdditionalStreamsInfo
jnz .no_additional_streams
call _7z.ReadAndDecodePackedStreams
mov eax, [_7z.unpacked]
mov [_7z.dataVector], eax
mov eax, [_7z.StreamsInfo.numFolders]
mov [_7z.dataVectorSize], eax
mov [error_proc], .header_error
mov [clear_proc], .clear
call _7z.ReadNum
.no_additional_streams:
cmp eax, kMainStreamsInfo
jnz return.err
call _7z.ReadStreamsInfo
call _7z.ReadNum
test eax, eax
jnz .notempty2
.empty2:
mov ebx, [_7z.dataVectorSize]
test ebx, ebx
jz @f
call _7z.ReadAndDecodePackedStreams.free2
@@:
mov ecx, [_7z.FreeSubStreams]
jecxz @f
call [pgfree]
@@:
mov ecx, [bufptr]
cmp ecx, buffer
jz @f
call [pgfree]
@@:
push [inStream]
call [close]
mov eax, empty_7z_handle
ret
.notempty2:
cmp eax, kFilesInfo
jnz return.err
call _7z.ReadNum
test eax, eax
jz .empty2
mov ebx, eax ; number of files in archive
imul ecx, ebx, file_in_7z.size
add ecx, handle_7z.basesize
mov [hOut.allocated], ecx
call [pgalloc]
test eax, eax
jz return.clear
mov [hOut], eax
mov [eax+handle_7z.type], type_7z
mov [eax+handle_7z.NumFiles], ebx
push edi
lea edi, [eax+handle_7z.numPackStreams]
mov esi, _7z.StreamsInfo
mov ecx, 6
rep movsd
or [eax+handle_7z.password_len], -1
or [eax+handle_7z.last_folder], -1
mov [eax+handle_7z.last_context], ecx
mov [eax+handle_7z.names_buf], ecx
mov [eax+handle_7z.host], ecx
cmp [bPasswordDefined], cl
jz @f
mov ecx, [password_size]
mov [eax+handle_7z.password_len], ecx
lea edi, [eax+handle_7z.password]
mov esi, password_unicode
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
@@:
lea edi, [eax+handle_7z.basesize]
imul ecx, ebx, file_in_7z.size/4
xor eax, eax
rep stosd
pop edi
mov eax, [_7z.StreamsInfo.SubStreamsSizes]
mov [_7z.FreeSubStreams], eax
mov [error_proc], .header_error
mov [clear_proc], .clear
mov ecx, ebx
shl ecx, 2
call [pgalloc]
test eax, eax
jz return.clear
push edi
mov edi, eax
mov [_7z.tmpVector], eax
add eax, ebx
mov [_7z.emptyStreams], eax
add eax, ebx
mov [_7z.emptyFiles], eax
add eax, ebx
mov [_7z.antiFiles], eax
mov ecx, ebx
xor eax, eax
rep stosd
pop edi
mov [_7z.numEmptyStreams], eax
.parse_header:
call _7z.ReadNum
test eax, eax
jz .parse_header_done
mov ecx, eax ; ecx = type
call _7z.ReadNum ; eax = size
cmp ecx, kName
jz .parse_names
cmp ecx, kWinAttributes
jz .parse_winAttr
cmp ecx, kStartPos
jz .parse_startPos
cmp ecx, kEmptyStream
jz .parse_emptyStream
cmp ecx, kEmptyFile
jz .parse_emptyFile
cmp ecx, kAnti
jz .parse_anti
cmp ecx, kCreationTime
jz .parse_time
cmp ecx, kLastWriteTime
jz .parse_time
cmp ecx, kLastAccessTime
jz .parse_time
xor edx, edx
call _7z.SkipSize
jmp .parse_header
.parse_names:
push eax
call _7z.SwitchStream
pop eax
jz @f
mov eax, [bufend]
sub eax, edi
@@:
shr eax, 1 ; size of ANSI string is a half of size of UNICODE string
mov ecx, eax
call [pgalloc]
test eax, eax
jz return.clear
mov ebp, eax
mov esi, [hOut]
mov [esi+handle_7z.names_buf], eax
add eax, ecx
push eax ; remember limit
mov ecx, ebx
add esi, handle_7z.basesize + file_in_7z.fullname
mov [bWasWarning], 0
.parse_names_loop:
mov [esi], ebp
add esi, file_in_7z.size
.parse_names_loop_int:
cmp ebp, [esp]
jae return.err
call _7z.ReadWord
; UNICODE char -> cp866 char
cmp ax, 0x80
jb .id
cmp ax, 0x401
jz .yo1
cmp ax, 0x451
jz .yo2
cmp ax, 0x410
jb .unk
cmp ax, 0x440
jb .rus1
cmp ax, 0x450
jb .rus2
.unk:
cmp [bWasWarning], 0
jnz @f
push ContinueBtn
push 1
push aEncodingProblem_str_ptr
push 3
push aEncodingProblem
call [Message]
inc [bWasWarning]
@@:
mov al, '_'
jmp .id
.yo1:
mov al, 'ð'
jmp .id
.yo2:
mov al, 'ñ'
jmp .id
.rus1:
; 0x410-0x43F -> 0x80-0xAF
add al, 0x70
jmp .id
.rus2:
; 0x440-0x44F -> 0xE0-0xEF
add al, 0xA0
.id:
mov [ebp], al
inc ebp
test al, al
jnz .parse_names_loop_int
loop .parse_names_loop
pop eax
call _7z.UnswitchStream
jmp .parse_header
.parse_winAttr:
mov edx, [_7z.tmpVector]
push ebx
mov ecx, ebx
mov ebx, edx
call _7z.ReadBoolVector2
pop ebx
call _7z.SwitchStream
mov esi, [hOut]
add esi, handle_7z.basesize
mov ecx, ebx
.winAttrLoop:
mov al, [edx]
inc edx
mov [esi+file_in_7z.bAttrDefined], al
test al, al
jz @f
call _7z.ReadDword
mov [esi+file_in_7z.attr], eax
@@:
add esi, file_in_7z.size
loop .winAttrLoop
call _7z.UnswitchStream
jmp .parse_header
.parse_startPos:
mov edx, [_7z.tmpVector]
push ebx
mov ecx, ebx
mov ebx, edx
call _7z.ReadBoolVector2
pop ebx
call _7z.SwitchStream
mov esi, [hOut]
add esi, handle_7z.basesize
mov ecx, ebx
.startPosLoop:
mov al, [edx]
inc edx
mov [esi+file_in_7z.bStartPosDefined], al
test al, al
jz @f
call _7z.ReadDword
mov dword [esi+file_in_7z.startPos], eax
call _7z.ReadDword
mov dword [esi+file_in_7z.startPos+4], eax
@@:
add esi, file_in_7z.size
loop .startPosLoop
call _7z.UnswitchStream
jmp .parse_header
.parse_emptyStream:
mov edx, [_7z.emptyStreams]
push ebx
mov ecx, ebx
mov ebx, edx
call _7z.ReadBoolVector
pop ebx
and [_7z.numEmptyStreams], 0
mov ecx, ebx
.emptyStrLoop:
cmp byte [edx], 0
jz @f
inc [_7z.numEmptyStreams]
@@:
inc edx
loop .emptyStrLoop
jmp .parse_header
.parse_emptyFile:
push ebx
mov ecx, [_7z.numEmptyStreams]
mov ebx, [_7z.emptyFiles]
call _7z.ReadBoolVector
pop ebx
jmp .parse_header
.parse_anti:
push ebx
mov ecx, [_7z.numEmptyStreams]
mov ebx, [_7z.antiFiles]
call _7z.ReadBoolVector
pop ebx
jmp .parse_header
.parse_time:
push ecx
push ebx
mov ecx, ebx
mov ebx, [_7z.tmpVector]
call _7z.ReadBoolVector2
pop ebx
call _7z.SwitchStream
mov esi, [hOut]
add esi, handle_7z.basesize
xor ecx, ecx
.timeLoop:
mov eax, [_7z.tmpVector]
mov al, [eax+ecx]
pop edx
push edx
mov [esi + file_in_7z.bCreationTimeDefined + edx - kCreationTime], al
test al, al
jz @f
call _7z.ReadDword
push eax
call _7z.ReadDword
mov edx, eax
pop eax
push edi
mov edi, [esp+4]
lea edi, [esi + file_in_7z.CreationTime + (edi-kCreationTime)*8]
call ntfs_datetime_to_bdfe
pop edi
@@:
add esi, file_in_7z.size
inc ecx
cmp ecx, ebx
jb .timeLoop
call _7z.UnswitchStream
pop eax
jmp .parse_header
.parse_header_done:
xor ecx, ecx ; index in emptyFiles
xor edx, edx ; index in subStreams
xor ebp, ebp ; index in files
mov esi, [hOut]
add esi, handle_7z.basesize
.filesLoop:
mov eax, [_7z.emptyStreams]
mov al, [eax+ebp]
xor al, 1
mov [esi+file_in_7z.bHasStream], al
jz .nostream
mov [esi+file_in_7z.bIsDirectory], 0
mov [esi+file_in_7z.bAnti], 0
mov eax, [_7z.StreamsInfo.SubStreamsSizes]
push dword [eax+edx*8]
pop dword [esi+file_in_7z.UnPackSize]
push dword [eax+edx*8+4]
pop dword [esi+file_in_7z.UnPackSize+4]
mov eax, [_7z.StreamsInfo.SubStreamsCRCsDefined]
mov al, [eax+edx]
mov [esi+file_in_7z.bCRCDefined], al
test al, al
jz @f
mov eax, [_7z.StreamsInfo.SubStreamsCRCs]
mov eax, [eax+edx*4]
mov [esi+file_in_7z.FileCRC], eax
@@:
inc edx
jmp .filesCont
.nostream:
mov eax, [_7z.emptyFiles]
cmp byte [eax+ecx], 0
setz [esi+file_in_7z.bIsDirectory]
mov eax, [_7z.antiFiles]
cmp byte [eax+ecx], 0
setnz [esi+file_in_7z.bAnti]
and dword [esi+file_in_7z.UnPackSize], 0
and dword [esi+file_in_7z.UnPackSize+4], 0
mov [esi+file_in_7z.bCRCDefined], 0
inc ecx
.filesCont:
inc ebp
add esi, file_in_7z.size
dec ebx
jnz .filesLoop
mov ecx, [_7z.tmpVector]
call [pgfree]
and [_7z.tmpVector], 0
mov ebx, [_7z.dataVectorSize]
test ebx, ebx
jz @f
call _7z.ReadAndDecodePackedStreams.free2
and [_7z.dataVectorSize], 0
@@:
mov ecx, [_7z.FreeSubStreams]
jecxz @f
call [pgfree]
and [_7z.FreeSubStreams], 0
@@:
mov ecx, [bufptr]
cmp ecx, buffer
jz @f
call [pgfree]
mov [bufptr], buffer
@@:
xor esi, esi ; index of folder
mov edi, [hOut]
mov ebx, [edi+handle_7z.NumFiles]
add edi, handle_7z.basesize ; pointer to fileinfo
push 0 ; start index of packed stream for folder
.getfoldersloop0:
xor edx, edx ; index in folder
push edx edx ; position in folder
.getfoldersloop:
dec ebx
js .getfoldersdone
cmp [edi+file_in_7z.bHasStream], 0
jnz @f
test edx, edx
jz .nofolder
@@:
test edx, edx
jnz .notfirst
; skip empty folders
@@:
mov eax, [hOut]
cmp esi, [eax+handle_7z.numFolders]
jae return.err
mov eax, [eax+handle_7z.folders]
mov eax, [eax+esi*4]
cmp edx, [eax+_7z.StreamsInfo.numUnPackStreams]
jb @f
inc esi
jmp @b
@@:
.notfirst:
mov [edi+file_in_7z.folder], esi
mov [edi+file_in_7z.folder_index], edx
mov eax, [esp]
mov dword [edi+file_in_7z.folderStart], eax
mov eax, [esp+4]
mov dword [edi+file_in_7z.folderStart+4], eax
mov ecx, dword [edi+file_in_7z.UnPackSize]
add [esp], ecx
mov ecx, dword [edi+file_in_7z.UnPackSize+4]
adc [esp+4], ecx
add edi, file_in_7z.size
inc edx
mov eax, [hOut]
mov eax, [eax+handle_7z.folders]
mov eax, [eax+esi*4]
cmp edx, [eax+_7z.StreamsInfo.numUnPackStreams]
jb .getfoldersloop
inc esi
pop edx edx
jmp .getfoldersloop0
.nofolder:
push -1
pop eax
mov [edi+file_in_7z.folder], eax
mov [edi+file_in_7z.folder_index], eax
mov dword [edi+file_in_7z.folderStart], eax
mov dword [edi+file_in_7z.folderStart+4], eax
add edi, file_in_7z.size
jmp .getfoldersloop
.getfoldersdone:
pop eax eax eax
mov ebp, [hOut]
mov esi, [ebp+handle_7z.folders]
xor ebx, ebx
cmp ebx, [ebp+handle_7z.numFolders]
jae .getoffsdone
.getoffsloop:
lodsd
test ebx, ebx
jnz .getoffs2
mov edx, dword [_7z.StreamsInfo.dataOffset]
mov dword [eax+_7z.StreamsInfo.packOffset], edx
mov edx, dword [_7z.StreamsInfo.dataOffset+4]
mov dword [eax+_7z.StreamsInfo.packOffset+4], edx
jmp .getoffscont
.getoffs2:
mov ecx, [esi-8]
mov edx, dword [ecx+_7z.StreamsInfo.packOffset]
mov dword [eax+_7z.StreamsInfo.packOffset], edx
mov edx, dword [ecx+_7z.StreamsInfo.packOffset+4]
mov dword [eax+_7z.StreamsInfo.packOffset+4], edx
mov edi, [ecx+_7z.StreamsInfo.startPackedStream]
mov ecx, [ecx+_7z.StreamsInfo.numPackedStreams]
push ecx
add ecx, edi
cmp ecx, [ebp+handle_7z.numPackStreams]
ja return.err
pop ecx
shl edi, 3
add edi, [ebp+handle_7z.packSizes]
@@:
dec ecx
js @f
mov edx, [edi]
add dword [eax+_7z.StreamsInfo.packOffset], edx
mov edx, [edi+4]
adc dword [eax+_7z.StreamsInfo.packOffset+4], edx
add edi, 8
jmp @b
@@:
.getoffscont:
inc ebx
cmp ebx, [ebp+handle_7z.numFolders]
jb .getoffsloop
.getoffsdone:
mov edx, [hOut]
mov ebx, [edx+handle_7z.NumFiles]
lea edi, [edx+handle_7z.root.subfolders]
add edx, handle_7z.basesize
push file_in_7z.size
call init_file_links
mov eax, [hOut]
and [eax+handle_7z.curdir], 0 ; set root directory
mov esi, [inStream]
mov [eax+handle_7z.host], esi
lea edi, [eax+handle_7z.host_datetime]
mov esi, [esp+16]
add esi, 8
mov ecx, 6
rep movsd
ret
 
_7z.CloseHandle:
mov esi, ecx
push [esi+handle_7z.host]
call [close]
mov ecx, [esi+handle_7z.packSizes]
call [pgfree]
mov ecx, [esi+handle_7z.folders]
call [pgfree]
mov ecx, [esi+handle_7z.names_buf]
call [pgfree]
mov ecx, [esi+handle_7z.last_context]
jecxz @f
call [pgfree]
@@:
mov ecx, esi
call [pgfree]
ret
 
close_7z:
mov ecx, [esp+4]
cmp ecx, empty_7z_handle
jz @f
call _7z.CloseHandle
@@:
ret 4
 
uglobal
align 4
_7z.unpacked dd ?
_7z.unpbuf rd 2*8
_7z.CurInStream dd ?
_7z.dataVector dd ?
_7z.dataVectorSize dd ?
_7z.FreeSubStreams dd ?
_7z.tmpVector dd ?
_7z.emptyStreams dd ?
_7z.numEmptyStreams dd ?
_7z.emptyFiles dd ?
_7z.antiFiles dd ?
endg
 
_7z.ReadAndDecodePackedStreams:
call _7z.ReadStreamsInfo
mov ecx, [_7z.StreamsInfo.numFolders]
test ecx, ecx
jz .ret2
push ecx
mov ecx, [_7z.StreamsInfo.SubStreamsSizes]
jecxz @f
call [pgfree]
and [_7z.StreamsInfo.SubStreamsSizes], 0
@@:
pop ecx
mov eax, _7z.unpbuf
cmp ecx, 8
jbe .1
shl ecx, 3
call [pgalloc]
test eax, eax
jz return.clear
mov esi, eax
@@:
and dword [esi], 0
add esi, 4
sub ecx, 4
jnz @b
.1:
mov [_7z.unpacked], eax
mov esi, eax
xor ecx, ecx
mov [_7z.CurInStream], ecx
mov [error_proc], .error
mov [clear_proc], .clear
.loop:
mov eax, [_7z.StreamsInfo.folders]
mov ebx, [eax+ecx*4]
call _7z.GetUnPackSize
test edx, edx
jnz return.err
test eax, eax
js return.err
push ecx
mov [esi], eax
mov [_7z.decode.outBufferSize], eax
mov ecx, eax
call [pgalloc]
test eax, eax
jz return.err
mov [esi+4], eax
mov [_7z.decode.outBufferPtr], eax
push esi
call _7z.decode
pop esi
pop ecx
push ecx
mov eax, [_7z.StreamsInfo.unpackCRCsDefined]
cmp byte [eax+ecx], 0
jz @f
push esi
mov ecx, [esi]
mov esi, [esi+4]
call crc
pop esi
pop ecx
push ecx
mov edx, [_7z.StreamsInfo.unpackCRCs]
cmp [edx+ecx*4], eax
jnz return.err
@@:
add esi, 8
pop ecx
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb .loop
.ret:
mov ecx, [_7z.StreamsInfo.folders]
call [pgfree]
mov [error_proc], .error2
mov [clear_proc], .clear2
.ret2:
mov ecx, [_7z.StreamsInfo.packSizes]
call [pgfree]
ret
 
.error:
call .free
jmp _7z.ReadStreamsInfo.error
.clear:
call .free
jmp _7z.ReadStreamsInfo.clear
.error2:
call .free
jmp open_7z.header_error
.clear2:
call .free
jmp open_7z.clear
.free:
mov ebx, [_7z.StreamsInfo.numFolders]
.free2:
dec ebx
js @f
mov ecx, [_7z.unpacked]
mov ecx, [ecx+ebx*8+4]
call [pgfree]
jmp .free2
@@:
mov ecx, [_7z.unpacked]
cmp ecx, _7z.unpbuf
jz @f
call [pgfree]
@@:
ret
 
_7z.GetUnPackSize:
xor edx, edx
mov eax, [ebx+_7z.StreamsInfo.numOutStreams]
test eax, eax
jz .ret
.scan:
dec eax
js return.err
push ecx
mov ecx, [ebx+_7z.StreamsInfo.numBindPairs]
mov edx, [ebx+_7z.StreamsInfo.bindPairs]
@@:
add edx, 8
dec ecx
js .found
cmp [edx-4], eax
jnz @b
pop ecx
jmp .scan
.found:
mov [ebx+_7z.StreamsInfo.mainOutStream], eax
mov ecx, [ebx+_7z.StreamsInfo.unpackSizes]
mov edx, [ecx+eax*8+4]
mov eax, [ecx+eax*8]
pop ecx
.ret:
ret
 
uglobal
align 4
_7z.StreamsInfo:
.numPackStreams dd ?
.packSizes dd ? ; 8 bytes per item
.numFolders dd ?
.unpackCRCsDefined dd ?
.unpackCRCs dd ?
.folders dd ?
.folders.size dd ?
.folders.alloc dd ?
.dataOffset dq ?
.packCRCsDefined dd ? ; 1 byte per item
.packCRCs dd ? ; 4 bytes per item
virtual at 0
.numCoders dd ?
.bindPairs dd ?
.numBindPairs dd ?
.packedStreams dd ?
.numPackedStreams dd ?
.startPackedStream dd ?
.numOutStreams dd ?
.unpackSizes dd ?
.mainOutStream dd ?
.numUnPackStreams dd ?
.packOffset dq ?
.fsz = $
end virtual
.numSubStreams dd ?
.SubStreamsSizes dd ?
.SubStreamsCRCsDefined dd ?
.SubStreamsCRCs dd ?
.tmpSubStreamsCRCsDefined dd ?
.tmpSubStreamsCRCs dd ?
endg
 
_7z.SkipData:
call _7z.ReadNumber
call _7z.SkipSize
ret
 
_7z.WaitAttribute:
call _7z.ReadNumber
cmp eax, ecx
jz @f
test eax, eax
jz return.err
call _7z.SkipData
jmp _7z.WaitAttribute
@@:
ret
 
_7z.ReadBoolVector2:
; in: ebx->vector, ecx=size
call _7z.ReadByte
test al, al
jz _7z.ReadBoolVector
push ebx ecx
jecxz .ret
@@:
mov byte [ebx], 1
inc ebx
loop @b
.ret:
pop ecx ebx
ret
 
_7z.ReadBoolVector:
push ebx ecx
jecxz .ret
xor eax, eax
.1:
add al, al
jnz @f
call _7z.ReadByte
stc
adc al, al
@@:
setc byte [ebx]
inc ebx
loop .1
.ret:
pop ecx ebx
ret
 
_7z.ReadHashDigests:
; in: ebx->bool vector, esi->crc, ecx=size
call _7z.ReadBoolVector2
jecxz .ret
.1:
xor eax, eax
cmp byte [ebx], al
jz @f
call _7z.ReadDword
@@:
mov [esi], eax
add esi, 4
inc ebx
loop .1
.ret:
ret
 
uglobal
_7z.saved_edi dd ?
_7z.saved_edi_end dd ?
endg
 
_7z.SwitchStream:
mov eax, [bufend]
mov [_7z.saved_edi_end], eax
call _7z.ReadByte
test al, al
jnz @f
ret
@@:
call _7z.ReadNum
mov [_7z.saved_edi], edi
cmp eax, [_7z.dataVectorSize]
jae return.err
shl eax, 3
add eax, [_7z.dataVector]
mov edi, [eax+4]
mov eax, [eax]
add eax, edi
mov [bufend], eax
ret
 
_7z.UnswitchStream:
mov eax, [_7z.saved_edi_end]
cmp eax, [bufend]
jnz @f
ret
@@:
mov [bufend], eax
mov edi, [_7z.saved_edi]
@@:
ret
 
; 6 ¯à®£à ¬¬¨á⮢ ¯ëâ «¨áì ª®¤ ¯®­ïâì,
; Ž¤¨­ ¨§ ­¨å á®èñ« á 㬠, ¨ ¨å ®áâ «®áì 5.
 
_7z.ReadStreamsInfo:
xor eax, eax
mov [_7z.StreamsInfo.numPackStreams], eax
mov [_7z.StreamsInfo.packSizes], eax
mov [_7z.StreamsInfo.numFolders], eax
mov [_7z.StreamsInfo.folders], eax
mov [_7z.StreamsInfo.numSubStreams], eax
mov [_7z.StreamsInfo.SubStreamsSizes], eax
mov [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], eax
mov [error_proc], .error
mov [clear_proc], .clear
.mainloop:
call _7z.ReadNum
test eax, eax
jz @b
cmp eax, kSubStreamsInfo
jz .SubStreamsInfo
cmp eax, kUnPackInfo
jz .UnpackInfo
cmp eax, kPackInfo
jnz return.err
 
.PackInfo:
cmp [_7z.StreamsInfo.numPackStreams], 0
jnz return.err
call _7z.ReadNumber
add eax, 0x20
adc edx, 0
mov dword [_7z.StreamsInfo.dataOffset], eax
mov dword [_7z.StreamsInfo.dataOffset+4], edx
call _7z.ReadNum
mov [_7z.StreamsInfo.numPackStreams], eax
mov ecx, kSize
call _7z.WaitAttribute
mov ecx, [_7z.StreamsInfo.numPackStreams]
imul ecx, 8+1+4
jecxz .nostreams1
call [pgalloc]
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.packSizes], eax
mov ecx, [_7z.StreamsInfo.numPackStreams]
push eax
lea eax, [eax+ecx*8]
mov [_7z.StreamsInfo.packCRCsDefined], eax
mov ebx, eax
add eax, ecx
mov [_7z.StreamsInfo.packCRCs], eax
@@:
mov byte [ebx], 0
inc ebx
loop @b
pop eax
.nostreams1:
mov ecx, [_7z.StreamsInfo.numPackStreams]
jecxz .noloop1
mov esi, eax
@@:
call _7z.ReadNumber
mov [esi], eax
mov [esi+4], edx
add esi, 8
loop @b
.noloop1:
call _7z.ReadNum
test eax, eax
jz .mainloop
cmp eax, kCRC
jz .packInfo.crc
call _7z.SkipData
jmp .noloop1
.packInfo.crc:
mov esi, [_7z.StreamsInfo.packCRCs]
mov ebx, [_7z.StreamsInfo.packCRCsDefined]
mov ecx, [_7z.StreamsInfo.numPackStreams]
call _7z.ReadHashDigests
jmp .noloop1
 
.UnpackInfo:
cmp [_7z.StreamsInfo.folders], 0
jnz return.err
mov ecx, kFolder
call _7z.WaitAttribute
call _7z.ReadNum
mov ecx, eax
mov [_7z.StreamsInfo.numFolders], eax
call _7z.SwitchStream
test ecx, ecx
jz .nofolders
push ecx
mov ecx, 0x1000
and [_7z.StreamsInfo.folders.size], 0
mov [_7z.StreamsInfo.folders.alloc], ecx
call [pgalloc]
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.folders], eax
pop ecx
lea ecx, [ecx*9]
call .folders_alloc
xor ecx, ecx
.folderloop:
mov eax, [_7z.StreamsInfo.folders]
push [_7z.StreamsInfo.folders.size]
pop dword [eax+ecx*4]
push ebp
mov [_ebp], ebp
push ecx
mov ecx, _7z.StreamsInfo.fsz
call .folders_alloc
mov ebp, eax
add ebp, [_7z.StreamsInfo.folders]
call _7z.ReadNum
mov [ebp+_7z.StreamsInfo.numCoders], eax
test eax, eax
jz return.err
mov ecx, eax
push ecx
shl ecx, 2
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
pop ecx
add eax, [_7z.StreamsInfo.folders]
@@:
and dword [eax], 0
add eax, 4
loop @b
push 0 ; numOutStreams
push 0 ; numInStreams
; [folders] = array of pointers to coders info
; Format of coder info:
; dd NextCoder
; db MethodID.IDSize
; times IDSize db MethodID.ID
; dd NumInStreams
; dd NumOutStreams
; dd PropSize
; times PropSize db Properties
xor esi, esi
.coders_loop:
call _7z.ReadByte
mov dl, al
and eax, 0xF
lea ecx, [eax+17]
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
push eax
mov ecx, [_7z.StreamsInfo.folders]
lea ebx, [ebp+esi*4+_7z.StreamsInfo.fsz]
@@:
cmp dword [ebx], 0
jz @f
mov ebx, [ebx]
add ebx, ecx
jmp @b
@@:
mov [ebx], eax
pop ebx
add ebx, ecx
and dword [ebx], 0
add ebx, 4
mov ecx, edx
and ecx, 0xF
mov byte [ebx], cl
inc ebx
jecxz .2
@@:
call _7z.ReadByte
mov byte [ebx], al
inc ebx
loop @b
.2:
test dl, 10h
jnz .coder_multiple_streams
mov dword [ebx], 1
mov dword [ebx+4], 1
inc dword [esp]
inc dword [esp+4]
jmp @f
.coder_multiple_streams:
call _7z.ReadNum
mov [ebx], eax
add dword [esp], eax
call _7z.ReadNum
mov [ebx+4], eax
add dword [esp+4], eax
; all currently defined 7z coders have 1 unpacked stream
; moreover, all reasonable coders have 1 unpacked stream
; so assume 1 output stream for unpacker - this simplifies decoding procedure
cmp eax, 1
jnz return.err
@@:
and dword [ebx+8], 0
add ebx, 12
test dl, 20h
jz .coder_no_properties
call _7z.ReadNum
test eax, eax
jz .coder_no_properties
mov [ebx-4], eax
mov ecx, eax
sub ebx, [_7z.StreamsInfo.folders]
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
add ebx, [_7z.StreamsInfo.folders]
@@:
call _7z.ReadByte
mov [ebx], al
inc ebx
loop @b
.coder_no_properties:
test dl, dl
js .coders_loop
inc esi
cmp esi, [ebp+_7z.StreamsInfo.numCoders]
jb .coders_loop
mov [ebp+_7z.StreamsInfo.numUnPackStreams], 1
mov eax, [esp+4]
dec eax
js return.err
mov [ebp+_7z.StreamsInfo.numBindPairs], eax
push eax
mov ecx, eax
shl ecx, 3
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
mov [ebp+_7z.StreamsInfo.bindPairs], eax
pop ecx
jecxz .noloop3
mov esi, eax
add esi, [_7z.StreamsInfo.folders]
@@:
call _7z.ReadNum
mov [esi], eax
cmp eax, [esp]
jae return.err
call _7z.ReadNum
mov [esi+4], eax
cmp eax, [esp+4]
jae return.err
add esi, 8
loop @b
.noloop3:
pop eax ; numInStreams
pop edx ; numOutStreams
mov [ebp+_7z.StreamsInfo.numOutStreams], edx
sub eax, edx
js return.err
inc eax
mov [ebp+_7z.StreamsInfo.numPackedStreams], eax
mov ecx, eax
push eax
shl ecx, 2
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
mov [ebp+_7z.StreamsInfo.packedStreams], eax
pop ecx
mov esi, eax
add esi, [_7z.StreamsInfo.folders]
cmp ecx, 1
jnz .multiplePackedStreams
mov ebx, [ebp+_7z.StreamsInfo.bindPairs]
add ebx, [_7z.StreamsInfo.folders]
push edx
xor ecx, ecx
.3:
push ebx
mov edx, [ebp+_7z.StreamsInfo.numBindPairs]
@@:
dec edx
js .5
cmp dword [ebx], ecx
jz .4
add ebx, 8
jmp @b
.4:
pop ebx
inc ecx
jmp .3
.5:
pop ebx
pop edx
mov [esi], ecx
jmp .commonPackedStreams
.multiplePackedStreams:
call _7z.ReadNum
mov [esi], eax
add esi, 4
loop .multiplePackedStreams
.commonPackedStreams:
mov ecx, edx
shl ecx, 3
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
mov [ebp+_7z.StreamsInfo.unpackSizes], eax
pop ecx
xor edx, edx
jecxz @f
mov eax, [_7z.StreamsInfo.folders]
mov eax, [eax+(ecx-1)*4]
add eax, [_7z.StreamsInfo.folders]
mov edx, [eax+_7z.StreamsInfo.numPackedStreams]
add edx, [eax+_7z.StreamsInfo.startPackedStream]
@@:
mov [ebp+_7z.StreamsInfo.startPackedStream], edx
pop ebp
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb .folderloop
.nofolders:
call _7z.UnswitchStream
mov ecx, kCodersUnPackSize
call _7z.WaitAttribute
xor ecx, ecx
.6:
cmp ecx, [_7z.StreamsInfo.numFolders]
jae .7
mov eax, [_7z.StreamsInfo.folders]
push ebp
mov ebp, [eax+ecx*4]
add ebp, eax
mov esi, [ebp+_7z.StreamsInfo.numOutStreams]
mov ebp, [ebp+_7z.StreamsInfo.unpackSizes]
add ebp, [_7z.StreamsInfo.folders]
@@:
call _7z.ReadNumber
mov dword [ebp], eax
mov dword [ebp+4], edx
add ebp, 8
dec esi
jnz @b
pop ebp
inc ecx
jmp .6
.7:
; convert all relative addresses to pointers
xor ecx, ecx
mov edx, [_7z.StreamsInfo.folders]
.8:
cmp ecx, [_7z.StreamsInfo.numFolders]
jae .9
lea eax, [edx+ecx*4]
add [eax], edx
mov eax, [eax]
add [eax+_7z.StreamsInfo.bindPairs], edx
add [eax+_7z.StreamsInfo.packedStreams], edx
add [eax+_7z.StreamsInfo.unpackSizes], edx
mov ebx, [eax+_7z.StreamsInfo.numCoders]
add eax, _7z.StreamsInfo.fsz
inc ecx
.11:
dec ebx
js .8
push eax
@@:
cmp dword [eax], 0
jz @f
add [eax], edx
mov eax, [eax]
jmp @b
@@:
pop eax
add eax, 4
jmp .11
.9:
; done
mov eax, [_7z.StreamsInfo.numFolders]
lea edx, [edx+eax*4]
mov [_7z.StreamsInfo.unpackCRCsDefined], edx
add edx, eax
mov [_7z.StreamsInfo.unpackCRCs], edx
@@:
call _7z.ReadNum
test eax, eax
jz .mainloop
cmp eax, kCRC
jz .unpackInfo.crc
call _7z.SkipData
jmp @b
.unpackInfo.crc:
mov esi, [_7z.StreamsInfo.unpackCRCs]
mov ebx, [_7z.StreamsInfo.unpackCRCsDefined]
mov ecx, [_7z.StreamsInfo.numFolders]
call _7z.ReadHashDigests
jmp @b
 
.SubStreamsInfo:
cmp [_7z.StreamsInfo.numFolders], 0
jz return.err
cmp [_7z.StreamsInfo.numSubStreams], 0
jnz return.err
mov ebx, [_7z.StreamsInfo.folders]
.ssloop1:
call _7z.ReadNum
cmp eax, kNumUnPackStream
jz .NumUnPackStream
cmp eax, kCRC
jz .break1
cmp eax, kSize
jz .break1
test eax, eax
jz .break1
call _7z.SkipData
jmp .ssloop1
.NumUnPackStream:
xor ecx, ecx
@@:
call _7z.ReadNum
mov edx, [ebx+ecx*4]
mov [edx+_7z.StreamsInfo.numUnPackStreams], eax
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb @b
jmp .ssloop1
.break1:
; calculate number of substreams and number of defined digests
xor ecx, ecx
xor ebp, ebp
push 0
push eax
xor eax, eax
.ssloop2:
mov edx, [ebx+ecx*4]
mov edx, [edx+_7z.StreamsInfo.numUnPackStreams]
cmp edx, 1
jz @f
inc ebp
@@:
add eax, edx
jc return.err
cmp edx, 1
jnz @f
push eax
mov eax, [_7z.StreamsInfo.unpackCRCsDefined]
cmp byte [eax+ecx], 0
pop eax
jz @f
xor edx, edx
@@:
add [esp+4], edx
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb .ssloop2
mov [_7z.StreamsInfo.numSubStreams], eax
imul ecx, eax, 4+8+1
jecxz .noss1
push eax
call [pgalloc]
pop ecx
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.SubStreamsSizes], eax
lea eax, [eax+ecx*8]
mov [_7z.StreamsInfo.SubStreamsCRCsDefined], eax
add eax, ecx
mov [_7z.StreamsInfo.SubStreamsCRCs], eax
@@:
dec eax
mov byte [eax], 0
loop @b
.noss1:
mov ecx, [esp+4]
jecxz @f
imul ecx, 4+1
call [pgalloc]
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], eax
add eax, [esp+4]
mov [_7z.StreamsInfo.tmpSubStreamsCRCs], eax
@@:
test ebp, ebp
jz @f
cmp dword [esp], kSize
jnz return.err
@@:
xor ecx, ecx
mov ebp, [_7z.StreamsInfo.SubStreamsSizes]
.ssloop3:
mov ebx, [_7z.StreamsInfo.folders]
mov ebx, [ebx+ecx*4]
mov eax, [ebx+_7z.StreamsInfo.numUnPackStreams]
dec eax
js .sscont3
push 0
push 0
@@:
dec eax
js @f
push eax
call _7z.ReadNumber
mov [ebp], eax
mov [ebp+4], edx
add ebp, 8
add [esp+4], eax
adc [esp+8], edx
jc return.err
pop eax
jmp @b
@@:
call _7z.GetUnPackSize
sub eax, [esp]
sbb edx, [esp+4]
jc return.err
mov [ebp], eax
mov [ebp+4], edx
add ebp, 8
add esp, 8
.sscont3:
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb .ssloop3
pop eax
cmp eax, kSize
jnz @f
call _7z.ReadNum
@@:
cmp eax, kCRC
jz .sscrc
test eax, eax
jz .ssend
call _7z.SkipData
.ssloop4:
call _7z.ReadNum
jmp @b
.sscrc:
pop ecx
push ecx
mov ebx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCs]
call _7z.ReadHashDigests
xor ecx, ecx ; index in out
xor edx, edx ; index in tmp
push -1
pop ebx ; index in folders
.ssloop5:
inc ebx
cmp ebx, [_7z.StreamsInfo.numFolders]
jae .ssloop4
mov eax, [_7z.StreamsInfo.folders]
mov ebp, [eax+ebx*4]
mov ebp, [ebp+_7z.StreamsInfo.numUnPackStreams]
cmp ebp, 1
jnz @f
mov eax, [_7z.StreamsInfo.unpackCRCsDefined]
cmp byte [eax+ebx], 0
jz @f
mov esi, [_7z.StreamsInfo.SubStreamsCRCsDefined]
mov byte [esi+ecx], 1
mov esi, [_7z.StreamsInfo.unpackCRCs]
mov eax, [esi+ebx*4]
mov esi, [_7z.StreamsInfo.SubStreamsCRCs]
mov [esi+ecx*4], eax
inc ecx
jmp .ssloop5
@@:
dec ebp
js .ssloop5
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
mov al, [esi+edx]
mov esi, [_7z.StreamsInfo.SubStreamsCRCsDefined]
mov [esi+ecx], al
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCs]
mov eax, [esi+edx*4]
mov esi, [_7z.StreamsInfo.SubStreamsCRCs]
mov [esi+ecx*4], eax
inc edx
inc ecx
jmp @b
.ssend:
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
call [pgfree]
and [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], 0
pop ecx
jmp .mainloop
 
.folders_alloc:
push ecx
add ecx, [_7z.StreamsInfo.folders.size]
sub ecx, [_7z.StreamsInfo.folders.alloc]
jbe @f
push edx
or ecx, 0xFFF
inc ecx
add ecx, [_7z.StreamsInfo.folders.alloc]
mov [_7z.StreamsInfo.folders.alloc], ecx
mov edx, [_7z.StreamsInfo.folders]
call [pgrealloc]
pop edx
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.folders], eax
@@:
pop ecx
mov eax, [_7z.StreamsInfo.folders.size]
add [_7z.StreamsInfo.folders.size], ecx
ret
 
.error:
mov ecx, [_7z.StreamsInfo.packSizes]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.folders]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.SubStreamsSizes]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
jecxz @f
call [pgfree]
@@:
jmp open_7z.header_error
.clear:
mov ecx, [_7z.StreamsInfo.packSizes]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.folders]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.SubStreamsSizes]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
jecxz @f
call [pgfree]
@@:
jmp open_7z.clear
 
uglobal
align 4
_7z.decode.mainbuf dd ?
_7z.decode.pStreams dd ?
_7z.decode.pStreams_def rd 8
_7z.decode.outBufferSize dd ?
_7z.decode.outBufferPtr dd ?
_7z.decode.outBufferRead dd ?
endg
 
virtual at 0
streamInfo:
.fullSize dq ?
.fillBuf dd ? ; procedure which fills the buffer
.bufSize dd ?
.bufDataLen dd ?
.bufPtr dd ?
.size = $
end virtual
 
_7z.decode:
; in: ebx->folder, outBufferSize, outBufferPtr
; N.B. We assume that every coder has 1 output (unpacked) stream.
and [.mainbuf], 0
mov [.pStreams], .pStreams_def
mov [error_proc], .error
mov [clear_proc], .clear
call .init
and [.outBufferRead], 0
@@:
push edi
mov eax, [ebx+_7z.StreamsInfo.mainOutStream]
mov esi, [.pStreams]
mov eax, [esi+eax*4]
call fillBuf
mov ecx, [eax+streamInfo.bufSize]
mov esi, [eax+streamInfo.bufPtr]
mov edi, [.outBufferPtr]
add edi, [.outBufferRead]
add [.outBufferRead], ecx
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
pop edi
mov eax, [.outBufferRead]
cmp eax, [.outBufferSize]
jb @b
mov ecx, [.pStreams]
cmp ecx, .pStreams_def
jz @f
call [pgfree]
@@:
mov ecx, [.mainbuf]
jecxz @f
call [pgfree]
@@:
mov [error_proc], _7z.ReadAndDecodePackedStreams.error
mov [clear_proc], _7z.ReadAndDecodePackedStreams.clear
ret
 
.error:
mov ecx, [.pStreams]
cmp ecx, .pStreams_def
jz @f
call [pgfree]
@@:
mov ecx, [.mainbuf]
jecxz @f
call [pgfree]
@@:
jmp _7z.ReadAndDecodePackedStreams.error
.clear:
mov ecx, [.pStreams]
cmp ecx, .pStreams_def
jz @f
call [pgfree]
@@:
mov ecx, [.mainbuf]
jecxz @f
call [pgfree]
@@:
jmp _7z.ReadAndDecodePackedStreams.clear
 
.init:
; We use stack to keep some information on streams,
; to avoid stack overflow we limit possible number of coders.
; Anyway, in real life maximum number of coders is 5
; (password protection filter + BCJ2 filter + 3 LZMA coders),
; from command line user can define more coders, but
; archive with, say, 32 coders is most likely bogus.
cmp [ebx+_7z.StreamsInfo.numCoders], 128
ja return.err
; allocate space for streams info array
mov eax, .pStreams_def
mov ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
add ecx, [ebx+_7z.StreamsInfo.numCoders]
cmp ecx, 8
jbe @f
shl ecx, 2
call [pgalloc]
test eax, eax
jz return.clear
@@:
mov [.pStreams], eax
; calculate size of buffers required for decoders
xor ecx, ecx
push ecx
mov ebp, [ebx+_7z.StreamsInfo.unpackSizes]
.calcbufsz:
; LZMA decoder: method ID = [size=03] 03 01 01, NumInStreams = NumOutStreams = 1
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
call _7z.GetCoder
jnc .known_id
.unknown_method_id:
movzx esi, byte [eax+4]
lea ecx, [eax+5]
mov ebx, aUnknownMethod.z
@@:
dec esi
js @f
mov byte [ebx], ' '
inc ebx
mov al, [ecx]
push eax
shr al, 4
cmp al, 10
sbb al, 69h
das
mov [ebx], al
inc ebx
pop eax
and al, 0xF
cmp al, 10
sbb al, 69h
das
mov [ebx], al
inc ebx
inc ecx
jmp @b
@@:
mov byte [ebx], 0
push ContinueBtn
push 1
push aUnknownMethod_ptr
push 1
call [SayErr]
jmp return.clear
iglobal
if lang eq ru
aUnknownMethod db '¥¨§¢¥áâ­ë© ¬¥â®¤:'
else
aUnknownMethod db 'Unknown method:'
end if
.z:
times 16*3+1 db 0
aUnknownMethod_ptr dd aUnknownMethod
endg
.known_id:
movzx esi, byte [eax+4]
lea esi, [esi+eax+17]
call [_7z.GetBufSizeTable+edx*4]
add eax, 3
and al, not 3
add [esp], eax
jc .nomem
cmp dword [ebp+4], 0
jnz @f
cmp dword [ebp], edx
jae @f
mov edx, [ebp]
@@:
add edx, 0xF
and edx, not 0xF
add [esp], edx
jc .nomem
add ebp, 8
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numCoders]
jb .calcbufsz
; add 4 pages for each of not binded input streams
mov ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
shl ecx, 14
add [esp], ecx
;; calculate free RAM
; call [getfreemem]
; sub eax, 64 ; keep at least 64 Kb of free RAM
; jbe .nomem
; pop ecx
; push ecx
; add ecx, 0x3FF
; shr ecx, 10
; cmp eax, ecx
; jae .memok
jmp .memok
.nomem:
push ContinueBtn
push 1
push aNoFreeRam_ptr
push 1
call [SayErr]
jmp return.clear
.memok:
; allocate streamInfos
pop ecx
call [pgalloc]
test eax, eax
jz return.clear
mov [.mainbuf], eax
; initialize streamInfos for decoders
xor ecx, ecx
mov ebp, [ebx+_7z.StreamsInfo.unpackSizes]
mov edx, [.pStreams]
.init1:
mov [edx], eax
add edx, 4
push edx
push dword [ebp]
pop dword [eax]
push dword [ebp+4]
pop dword [eax+4]
and dword [eax+streamInfo.size], 0
push eax
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
call _7z.GetCoder
movzx esi, byte [eax+4]
lea esi, [esi+eax+17]
call [_7z.GetBufSizeTable+edx*4]
pop esi
push esi
add eax, 3
and al, not 3
add [esp], eax
pop [esi+streamInfo.bufPtr]
push [esi+streamInfo.bufPtr]
cmp dword [ebp+4], 0
jnz @f
cmp dword [ebp], edx
jae @f
mov edx, [ebp]
@@:
add edx, 0xF
and edx, not 0xF
mov [esi+streamInfo.bufSize], edx
and [esi+streamInfo.bufDataLen], 0
pop eax
add eax, edx
pop edx
add ebp, 8
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numCoders]
jb .init1
; initialize streamInfos for input streams
xor ecx, ecx
@@:
mov [edx], eax
add edx, 4
mov esi, [_7z.CurInStream]
inc [_7z.CurInStream]
shl esi, 3
add esi, [_7z.StreamsInfo.packSizes]
push dword [esi]
pop dword [eax]
push dword [esi+4]
pop dword [eax+4]
mov [eax+streamInfo.fillBuf], fillBufFromInStream
lea esi, [eax+streamInfo.size+8]
mov [eax+streamInfo.bufPtr], esi
mov [eax+streamInfo.bufSize], 0x4000 - streamInfo.size - 8
and [eax+streamInfo.bufDataLen], 0
mov esi, dword [_7z.StreamsInfo.dataOffset]
mov dword [eax+streamInfo.size], esi
mov esi, dword [_7z.StreamsInfo.dataOffset+4]
mov dword [eax+streamInfo.size+4], esi
mov esi, [eax]
add dword [_7z.StreamsInfo.dataOffset], esi
mov esi, [eax+4]
adc dword [_7z.StreamsInfo.dataOffset+4], esi
add eax, 0x4000
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
jb @b
; initialize links between streams
push -1
mov edx, [ebx+_7z.StreamsInfo.mainOutStream]
xor ecx, ecx
.init_links:
mov eax, [ebx+_7z.StreamsInfo.fsz+edx*4]
movzx esi, byte [eax+4]
cmp ecx, [eax+esi+5]
jb @f
pop ecx
cmp ecx, -1
jz .inited_links
pop edx
jmp .init_links
@@:
push edx
push ecx
@@:
dec edx
js @f
mov eax, [ebx+_7z.StreamsInfo.fsz+edx*4]
movzx esi, byte [eax+4]
add ecx, [eax+esi+5]
jmp @b
@@:
mov esi, [ebx+_7z.StreamsInfo.bindPairs]
mov edx, [ebx+_7z.StreamsInfo.numBindPairs]
@@:
add esi, 8
dec edx
js .link_to_in
cmp ecx, [esi-8]
jnz @b
pop ecx
pop edx
mov eax, [.pStreams]
mov eax, [eax+edx*4]
lea eax, [eax+streamInfo.size+ecx*4]
push edx
inc ecx
push ecx
mov edx, [esi-4]
mov ecx, [.pStreams]
mov ecx, [ecx+edx*4]
mov [eax], ecx
cmp dword [ecx+streamInfo.size], 0
jnz return.err
xor ecx, ecx
jmp .init_links
.link_to_in:
mov esi, [ebx+_7z.StreamsInfo.packedStreams]
mov edx, [ebx+_7z.StreamsInfo.numPackedStreams]
@@:
dec edx
js return.err
cmp ecx, [esi+edx*4]
jnz @b
add edx, [ebx+_7z.StreamsInfo.numCoders]
mov esi, [.pStreams]
mov eax, [esi+edx*4]
pop ecx
pop edx
mov esi, [esi+edx*4]
mov [esi+streamInfo.size+ecx*4], eax
inc ecx
jmp .init_links
.inited_links:
; initialize all decoders
; bool zzz_init_decoder(stream_info* ebp, esi->params, [esi-4]=params_size);
xor ecx, ecx
.init_decoders:
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
call _7z.GetCoder
movzx esi, byte [eax+4]
mov ebp, [.pStreams]
mov ebp, [ebp+ecx*4]
cmp dword [esi+eax], 0
jz @f
cmp dword [ebp+streamInfo.size], 0
jz return.err
@@:
lea esi, [esi+eax+17]
push ebx ecx edi
xor ebx, ebx
call [_7z.InitTable+edx*4]
pop edi ecx ebx
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numCoders]
jb .init_decoders
ret
 
fillBuf:
and [eax+streamInfo.bufDataLen], 0
fillBufNozero:
pushad
mov edx, [eax+streamInfo.bufSize]
sub edx, [eax+streamInfo.bufDataLen]
cmp dword [eax+streamInfo.fullSize+4], 0
jnz .full
mov ecx, dword [eax+streamInfo.fullSize]
cmp ecx, edx
jbe @f
.full:
mov ecx, edx
@@:
sub dword [eax+streamInfo.fullSize], ecx
sbb dword [eax+streamInfo.fullSize+4], 0
mov edi, [eax+streamInfo.bufPtr]
add edi, [eax+streamInfo.bufDataLen]
add [eax+streamInfo.bufDataLen], ecx
jmp [eax+streamInfo.fillBuf]
 
fillBufFromInStream:
push eax
push dword [eax+streamInfo.size+4]
push dword [eax+streamInfo.size]
push 0
push [inStream]
call [seek]
pop eax
push eax
push ecx
push edi
push [inStream]
call [read]
cmp eax, ecx
pop eax
jnz .error
add dword [eax+streamInfo.size], ecx
adc dword [eax+streamInfo.size+4], 0
popad
ret
.error:
push ContinueBtn
push 1
push aReadError_ptr
push 1
call [SayErr]
jmp return.clear
 
_7z.GetCoder:
; in: eax->coder
; out: edx = coder type
xor edx, edx
; Copy decoder: method ID = [size=01] 00, NumInStreams = NumOutStreams = 1
cmp word [eax+4], 0x0001
jnz @f
cmp dword [eax+6], 1
jz .ret
@@:
inc edx
; LZMA decoder: method ID = [size=03] 03 01 01, NumInStreams = NumOutStreams = 1
cmp dword [eax+4], 0x01010303
jnz @f
cmp dword [eax+8], 1
jz .ret
@@:
inc edx
; PPMD decoder: method ID = [size=03] 03 04 01, NumInStreams = NumOutStreams = 1
cmp dword [eax+4], 0x01040303
jnz @f
cmp dword [eax+8], 1
jz .ret
@@:
inc edx
; BCJ filter: method ID = [size=04] 03 03 01 03, NumInStreams = NumOutStreams = 1
cmp byte [eax+4], 4
jnz @f
cmp dword [eax+5], 0x03010303
jnz @f
cmp dword [eax+9], 1
jz .ret
@@:
inc edx
; BCJ2 filter: method ID = [size=04] 03 03 01 1B, NumInStreams = 4, NumOutStreams = 1
cmp byte [eax+4], 4
jnz @f
cmp dword [eax+5], 0x1B010303
jnz @f
cmp dword [eax+9], 4
jz .ret
@@:
inc edx
; 7z-AES cryptor: method ID = [size=04] 06 F1 07 01, NumInStreams = NumOutStreams = 1
cmp byte [eax+4], 4
jnz @f
cmp dword [eax+5], 0x0107F106
jnz @f
cmp dword [eax+9], 1
jz .ret
@@:
stc
.ret:
ret
 
iglobal
align 4
label _7z.GetBufSizeTable dword
dd copy_get_buf_size
dd lzma_get_buf_size
dd ppmd_get_buf_size
dd bcj_get_buf_size
dd bcj2_get_buf_size
dd aes7z_get_buf_size
label _7z.InitTable dword
dd copy_init_decoder
dd lzma_init_decoder
dd ppmd_init_decoder
dd bcj_init_decoder
dd bcj2_init_decoder
dd aes7z_init_decoder
endg
 
copy_get_buf_size:
mov eax, streamInfo.size+8
mov edx, 0x10000
ret
 
copy_init_decoder:
mov [ebp+streamInfo.fillBuf], copy_fillBuf
and dword [ebp+streamInfo.size+4], 0
ret
 
copy_fillBuf:
push eax
mov esi, [eax+streamInfo.size+4]
mov eax, [eax+streamInfo.size]
.redo:
push ecx
mov edx, [eax+streamInfo.bufDataLen]
sub edx, esi
cmp ecx, edx
jb @f
mov ecx, edx
@@:
sub [esp], ecx
add esi, [eax+streamInfo.bufPtr]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
pop ecx
jecxz .done
cmp dword [eax+streamInfo.fullSize+4], 0
jnz @f
cmp dword [eax+streamInfo.fullSize], ecx
jb return.err
@@:
call fillBuf
xor esi, esi
jmp .redo
.done:
sub esi, [eax+streamInfo.bufPtr]
pop eax
mov [eax+streamInfo.size+4], esi
popad
ret
 
; int __stdcall ReadFolder([esp+4] = HANDLE hPlugin,
; [esp+8] = unsigned dirinfo_start, [esp+12] = unsigned dirinfo_size,
; [esp+16] = void* dirdata);
ReadFolder_7z:
; init header
mov edi, [esp+16]
mov ecx, 32/4
xor eax, eax
rep stosd
mov byte [edi-32], 1 ; version
mov ebp, [esp+4]
; get current directory
lea ebx, [ebp+handle_7z.root.subfolders]
cmp [ebp+handle_7z.curdir], 0
jz @f
mov ebx, [ebp+handle_7z.curdir]
add ebx, file_in_7z.subfolders
@@:
mov ecx, [ebx+16]
mov [edi-24], ecx ; number of files
; edi points to BDFE
push 6 ; assume EOF
pop eax
sub ecx, [esp+8]
ja @f
and dword [edi-28], 0 ; number of files read
ret 10h
@@:
cmp ecx, [esp+12]
jb @f
mov ecx, [esp+12]
xor eax, eax ; OK
@@:
mov [edi-28], ecx
push eax
; copy files data
test ecx, ecx
jz .done
; seek to required item
mov eax, [esp+8+4]
mov esi, [ebx]
.0:
test esi, esi
jnz .1
mov esi, [ebx+8]
.1:
add esi, ebp
dec eax
js .2
mov esi, [esi+file_in_7z.next]
jmp .0
.2:
.copy:
cmp [esi+file_in_7z.bPseudoFolder], 0
jnz .pseudo
xor eax, eax
cmp [esi+file_in_7z.bAttrDefined], 0
jz @f
mov eax, [esi+file_in_7z.attr]
@@:
stosd
xor eax, eax
stosd
push esi ecx
add esi, file_in_7z.CreationTime
mov ecx, 8
rep movsd
pop ecx esi
mov edx, [esi+file_in_7z.name]
push edi
@@:
mov al, [edx]
inc edx
stosb
test al, al
jnz @b
pop edi
.cont:
add edi, 264
mov esi, [esi+file_in_7z.next]
test esi, esi
jnz @f
mov esi, [ebx+8]
@@:
add esi, ebp
loop .copy
jmp .done
.pseudo:
push 0x10 ; attributes: folder
pop eax
stosd
xor eax, eax
stosd
push ecx esi
lea esi, [ebp+handle_7z.host_datetime]
mov ecx, 6
rep movsd
pop esi
stosd
stosd
push edi esi
mov ecx, [esi+file_in_7z.namelen]
mov esi, [esi+file_in_7z.name]
rep movsb
mov byte [edi], 0
pop esi edi ecx
jmp .cont
.done:
pop eax
ret 10h
 
; bool __stdcall SetFolder([esp+4] = HANDLE hPlugin,
; [esp+8] = const char* relative_path, [esp+12] = const char* absolute_path);
SetFolder_7z:
mov ebp, [esp+4]
mov edx, [ebp+handle_7z.curdir]
mov esi, [esp+8]
cmp dword [esi], '..'
jz .toparent
xor ecx, ecx
@@:
inc ecx
cmp byte [esi+ecx], 0
jnz @b
mov ebx, [ebp+handle_7z.root.subfolders]
test edx, edx
jz .scan
mov ebx, [edx+file_in_7z.subfolders]
.scan:
test ebx, ebx
jz .err
add ebx, ebp
cmp [ebx+file_in_7z.namelen], ecx
jnz .cont
push ecx esi
mov edi, [ebx+file_in_7z.name]
repz cmpsb
pop esi ecx
jz .set
.cont:
mov ebx, [ebx+file_in_7z.next]
jmp .scan
.toparent:
test edx, edx
jz .err
mov ebx, [edx+file_in_7z.parent]
test ebx, ebx
jz @f
add ebx, ebp
@@:
.set:
mov [ebp+handle_7z.curdir], ebx
mov al, 1
ret 12
.err:
xor eax, eax
ret 12
 
; ebp=hPlugin, eax->item, edi->info
getattr_7z:
cmp [eax+file_in_7z.bPseudoFolder], 0
jnz .pseudo
lea esi, [eax+file_in_7z.attr]
movsd
xor eax, eax
stosd
add esi, -(file_in_7z.attr+4) + file_in_7z.CreationTime
mov ecx, 8
rep movsd
ret
.pseudo:
mov esi, [eax+file_in_7z.name]
mov ecx, [eax+file_in_7z.namelen]
push 0x10 ; attributes: folder
pop eax
stosd
xor eax, eax
stosd
push ecx esi
lea esi, [ebp+handle_7z.host_datetime]
push 6
pop ecx
rep movsd
pop esi ecx
stosd
stosd
rep movsb
mov byte [edi], 0
ret
 
virtual at 0
file_handle_7z:
.type dd ?
.context dd ?
.pos dq ?
.base dd ? ; handle of archive
.item dd ? ; pointer to file_in_7z
.mainStream dd ? ; (pointer in context)
.bError db ?
rb 3
.size = $
end virtual
 
iglobal
align 4
handle_table_7z dd handle_table_7z,handle_table_7z
endg
 
; ebp=hPlugin, eax->item, edi=mode
open_file_7z:
cmp [eax+file_in_7z.bHasStream], 0
jnz @f
mov eax, empty_7z_handle
ret
@@:
mov ecx, [ebp+handle_7z.password_len]
inc ecx
setnz [bPasswordDefined]
jz @f
dec ecx
lea esi, [ebp+handle_7z.password]
push edi
mov edi, password_unicode
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
pop edi
@@:
mov [hOut], ecx
mov [_7z.decode.mainbuf], ecx
mov ecx, [ebp+handle_7z.host]
mov [inStream], ecx
mov [_7z.decode.pStreams], _7z.decode.pStreams_def
push eax
mov [_esp], esp
mov [_ebp], ebp
mov [error_proc], .error
mov [clear_proc], .clear
mov ebx, [ebp+handle_7z.folders]
mov ecx, [eax+file_in_7z.folder]
cmp [ebp+handle_7z.last_folder], ecx
jnz .nolast
mov edx, dword [eax+file_in_7z.folderStart]
sub edx, dword [ebp+handle_7z.last_pos]
mov esi, dword [eax+file_in_7z.folderStart+4]
sbb esi, dword [ebp+handle_7z.last_pos+4]
jb .nolast
xor ecx, ecx
xchg ecx, [ebp+handle_7z.last_context]
mov [_7z.decode.mainbuf], ecx
mov eax, [ebp+handle_7z.last_main_stream]
mov dword [eax+streamInfo.fullSize], edx
mov dword [eax+streamInfo.fullSize+4], esi
or [ebp+handle_7z.last_folder], -1
pop esi
push esi
jmp .commonl
.nolast:
mov ebx, [ebx+ecx*4]
mov eax, [ebx+_7z.StreamsInfo.startPackedStream]
mov [_7z.CurInStream], eax
mov eax, dword [ebx+_7z.StreamsInfo.packOffset]
mov dword [_7z.StreamsInfo.dataOffset], eax
mov eax, dword [ebx+_7z.StreamsInfo.packOffset+4]
mov dword [_7z.StreamsInfo.dataOffset+4], eax
mov eax, [ebp+handle_7z.packSizes]
mov [_7z.StreamsInfo.packSizes], eax
push ebp
call _7z.decode.init
pop ebp
mov eax, [ebx+_7z.StreamsInfo.mainOutStream]
mov esi, [_7z.decode.pStreams]
mov eax, [esi+eax*4]
pop esi
push esi
mov ecx, dword [esi+file_in_7z.folderStart]
mov dword [eax+streamInfo.fullSize], ecx
mov ecx, dword [esi+file_in_7z.folderStart+4]
mov dword [eax+streamInfo.fullSize+4], ecx
.commonl:
call skip_7z
mov ecx, dword [esi+file_in_7z.UnPackSize]
mov dword [eax+streamInfo.fullSize], ecx
mov edx, dword [esi+file_in_7z.UnPackSize+4]
mov dword [eax+streamInfo.fullSize+4], edx
test edx, edx
jnz .nomemstream
if defined LIMIT_FOR_MEM_STREAM
cmp ecx, LIMIT_FOR_MEM_STREAM
ja .nomemstream
end if
push eax ecx
add ecx, 0x3FF
shr ecx, 10 ; get size in Kb
call [getfreemem]
shr eax, 2
cmp ecx, eax
pop ecx eax
ja .nomemstream
; create memory stream and unpack to memory
push eax ecx
add ecx, mem_stream.buf
call [pgalloc]
test eax, eax
jz return.clear
mov edi, eax
pop ecx
push edi
mov [hOut], eax
xor eax, eax ; type_mem_stream
stosd ; mem_stream.type
mov eax, ecx
stosd ; mem_stream.size
xor eax, eax
stosd ; mem_stream.pos
mov eax, [esp+4]
push esi
push ecx edi
call read_7z_to_buf
pop esi ecx
mov ebx, [esp+12]
cmp [ebx+file_in_7z.bCRCDefined], 0
jz @f
call crc
cmp eax, [ebx+file_in_7z.FileCRC]
jnz return.err
@@:
pop esi
xor ecx, ecx
xchg ecx, [_7z.decode.mainbuf]
xchg ecx, [ebp+handle_7z.last_context]
jecxz @f
call [pgfree]
@@:
and [hOut], 0
mov eax, [esi+file_in_7z.folder]
mov [ebp+handle_7z.last_folder], eax
mov eax, [esp+4]
mov [ebp+handle_7z.last_main_stream], eax
mov ecx, dword [esi+file_in_7z.UnPackSize]
add ecx, dword [esi+file_in_7z.folderStart]
mov dword [ebp+handle_7z.last_pos], ecx
mov ecx, dword [esi+file_in_7z.UnPackSize+4]
adc ecx, dword [esi+file_in_7z.folderStart+4]
mov dword [ebp+handle_7z.last_pos+4], ecx
call .done
pop eax edi ecx
ret
.nomemstream:
mov edi, eax
push esi
mov esi, handle_table_7z
push file_handle_7z.size
pop ecx
call alloc_handle
pop esi
test eax, eax
jz .clear
mov [eax+file_handle_7z.type], type_7z
xor edx, edx
mov dword [eax+file_handle_7z.pos], edx
mov dword [eax+file_handle_7z.pos+4], edx
mov [eax+file_handle_7z.bError], dl
xchg edx, [_7z.decode.mainbuf]
mov [eax+file_handle_7z.context], edx
mov [eax+file_handle_7z.mainStream], edi
mov [eax+file_handle_7z.base], ebp
mov [eax+file_handle_7z.item], esi
push eax
call .done
pop eax ecx
ret
 
.done:
cmp [bPasswordDefined], 0
jz @f
mov ecx, [password_size]
mov [ebp+handle_7z.password_len], ecx
mov esi, password_unicode
lea edi, [ebp+handle_7z.password]
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
@@:
jmp .clear
 
.error:
cmp [bPasswordDefined], 0
jz .realerror
push CancelPassBtn
push 2
push aArchiveDataErrorPass_ptr
push 1
call [SayErr]
cmp al, 1
jnz .clear
; user wants to re-enter password
call .clear
pop eax
jmp open_file_7z
.realerror:
push ContinueBtn
push 1
push aArchiveDataError_ptr
push 1
call [SayErr]
.clear:
mov ecx, [_7z.decode.pStreams]
cmp ecx, _7z.decode.pStreams_def
jz @f
call [pgfree]
@@:
mov ecx, [_7z.decode.mainbuf]
jecxz @f
call [pgfree]
@@:
mov ecx, [hOut]
jecxz @f
call [pgfree]
@@:
cmp esp, [_esp]
jnz @f
pop eax
@@:
xor eax, eax
ret
 
read_7z_to_buf:
mov esi, [eax+streamInfo.bufDataLen]
cmp esi, [eax+streamInfo.bufSize]
jnz @f
xor esi, esi
mov [eax+streamInfo.bufDataLen], esi
@@:
call fillBufNozero
mov ecx, [eax+streamInfo.bufDataLen]
sub ecx, esi
add esi, [eax+streamInfo.bufPtr]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
cmp dword [eax+streamInfo.fullSize], 0
jnz read_7z_to_buf
ret
 
skip_7z:
push edx
mov edx, [eax+streamInfo.bufDataLen]
cmp edx, [eax+streamInfo.bufSize]
jnz @f
and [eax+streamInfo.bufDataLen], 0
@@:
pop edx
call fillBufNozero
cmp dword [eax+streamInfo.fullSize], 0
jnz skip_7z
cmp dword [eax+streamInfo.fullSize+4], 0
jnz skip_7z
ret
 
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
read_7z:
mov eax, [ebx+file_handle_7z.mainStream]
test eax, eax
jz .ret ; empty stream - return 0 bytes read
cmp [ebx+file_handle_7z.bError], 0
jnz .reterr
mov ecx, [ebx+file_handle_7z.base]
mov ecx, [ecx+handle_7z.host]
mov [inStream], ecx
mov edi, [esp+8]
mov ecx, [esp+12]
mov dword [eax+streamInfo.fullSize], ecx
and dword [eax+streamInfo.fullSize+4], 0
jecxz .nodata
mov [_esp], esp
mov [_ebp], ebp
mov [error_proc], .error
mov [clear_proc], .clear ; should not be called
mov esi, [ebx+file_handle_7z.item]
mov edx, dword [esi+file_in_7z.UnPackSize]
mov esi, dword [esi+file_in_7z.UnPackSize+4]
sub edx, dword [ebx+file_handle_7z.pos]
sbb esi, dword [ebx+file_handle_7z.pos+4]
jnz .do
cmp edx, ecx
jae .do
mov dword [eax+streamInfo.fullSize], edx
.do:
call read_7z_to_buf
.nodata:
sub edi, [esp+8]
mov eax, edi
add dword [ebx+file_handle_7z.pos], eax
adc dword [ebx+file_handle_7z.pos+4], 0
.ret:
ret 12
 
.error:
.clear:
mov ebx, [esp+4]
mov [ebx+file_handle_7z.bError], 1
push ContinueBtn
push 1
push aArchiveDataError_ptr
push 1
call [SayErr]
.reterr:
or eax, -1
ret 12
 
; void __stdcall setpos(HANDLE hFile, __int64 pos);
setpos_7z:
cmp [ebx+file_handle_7z.context], 0
jz .ret
mov edi, [ebx+file_handle_7z.base]
mov ecx, [edi+handle_7z.host]
mov [inStream], ecx
mov [_esp], esp
mov [_ebp], ebp
mov [error_proc], read_7z.error
mov [clear_proc], read_7z.clear ; should not be called
cmp [ebx+file_handle_7z.bError], 0
jnz .backward ; if was error, force reinitialization
mov ecx, [esp+8]
mov edx, [esp+12]
sub ecx, dword [ebx+file_handle_7z.pos]
sbb edx, dword [ebx+file_handle_7z.pos+4]
jb .backward
; move forward - skip some data
mov eax, [ebx+file_handle_7z.mainStream]
mov dword [eax+streamInfo.fullSize], ecx
mov dword [eax+streamInfo.fullSize+4], edx
call skip_7z
add dword [ebx+file_handle_7z.pos], ecx
adc dword [ebx+file_handle_7z.pos], edx
.ret:
ret 12
.backward:
; move backward - reinitialize and skip start data
mov [ebx+file_handle_7z.bError], 0
mov ebp, [ebx+file_handle_7z.context]
mov eax, [ebx+file_handle_7z.item]
mov ebx, [edi+handle_7z.folders]
mov eax, [eax+file_in_7z.folder]
mov ebx, [ebx+eax*4]
; initialize streamInfos for decoders
xor ecx, ecx
mov esi, [ebx+_7z.StreamsInfo.unpackSizes]
@@:
lodsd
mov [ebp], eax
lodsd
mov [ebp+4], eax
and [ebp+streamInfo.bufDataLen], 0
push esi
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
call _7z.GetCoder
movzx esi, byte [eax+4]
lea esi, [esi+eax+17]
push ebx ecx edi
mov bl, 1
call [_7z.InitTable+edx*4]
pop edi ecx ebx esi
mov edx, [ebp+streamInfo.bufSize]
mov ebp, [ebp+streamInfo.bufPtr]
add ebp, edx
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numCoders]
jb @b
; initialize streamInfos for input streams
xor ecx, ecx
mov esi, [ebx+_7z.StreamsInfo.startPackedStream]
shl esi, 3
add esi, [edi+handle_7z.packSizes]
mov edi, dword [ebx+_7z.StreamsInfo.packOffset]
mov edx, dword [ebx+_7z.StreamsInfo.packOffset+4]
@@:
mov dword [ebp+streamInfo.size], edi
mov dword [ebp+streamInfo.size+4], edx
and [ebp+streamInfo.bufDataLen], 0
lodsd
add edi, eax
mov [ebp], eax
lodsd
adc edx, eax
mov [ebp+4], eax
add ebp, 0x4000
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
jb @b
mov ebx, [esp+4]
mov esi, [ebx+file_handle_7z.item]
mov eax, [ebx+file_handle_7z.mainStream]
mov ecx, dword [esi+file_in_7z.folderStart]
add ecx, [esp+8]
mov dword [eax+streamInfo.fullSize], ecx
mov ecx, dword [esi+file_in_7z.folderStart+4]
adc ecx, [esp+12]
mov dword [eax+streamInfo.fullSize+4], ecx
and dword [ebx+file_handle_7z.pos], 0
and dword [ebx+file_handle_7z.pos+4], 0
and [eax+streamInfo.bufDataLen], 0
call skip_7z
mov eax, [esp+8]
mov dword [ebx+file_handle_7z.pos], eax
mov eax, [esp+12]
mov dword [ebx+file_handle_7z.pos+4], eax
ret 12
 
close_file_7z:
mov ecx, [ebx+file_handle_7z.context]
jecxz .ret
cmp [ebx+file_handle_7z.bError], 0
jnz @f
push ebp
mov ebp, [ebx+file_handle_7z.base]
xchg ecx, [ebp+handle_7z.last_context]
mov eax, [ebx+file_handle_7z.item]
mov edx, [eax+file_in_7z.folder]
mov [ebp+handle_7z.last_folder], edx
mov edx, [ebx+file_handle_7z.mainStream]
mov [ebp+handle_7z.last_main_stream], edx
mov edx, dword [eax+file_in_7z.folderStart+4]
mov eax, dword [eax+file_in_7z.folderStart]
add eax, dword [ebx+file_handle_7z.pos]
adc edx, dword [ebx+file_handle_7z.pos+4]
mov dword [ebp+handle_7z.last_pos], eax
mov dword [ebp+handle_7z.last_pos+4], edx
pop ebp
@@:
jecxz @f
call [pgfree]
@@:
mov esi, ebx
call free_handle
.ret:
ret 4
 
iglobal
cur_stamp dd 0
endg
 
uglobal
tmp_bdfe rb 304
endg
 
GetFiles_7z:
mov ecx, [ebp+handle_7z.NumFiles]
test ecx, ecx
jz .ret
lea ebx, [ebp+handle_7z.basesize]
inc [cur_stamp]
.loop:
push ecx
mov esi, [ebx+file_in_7z.fullname]
mov edx, [ebp+handle_7z.curdir]
test edx, edx
jz .incur
mov eax, [cur_stamp]
mov [edx+file_in_7z.stamp], eax
mov edi, [edx+file_in_7z.fullname]
mov ecx, [edx+file_in_7z.namelen]
add ecx, [edx+file_in_7z.name]
sub ecx, edi
repz cmpsb
jnz .cont
.incur:
cmp byte [esi], '/'
jnz @f
inc esi
@@:
mov ecx, [esp+12] ; NumItems
mov edx, [esp+16] ; items
cmp ecx, -1
jz .ok
.check:
sub ecx, 1
js .cont
push esi
mov edi, [edx]
add edi, 40
@@:
lodsb
scasb
jnz @f
test al, al
jz .ok2
jmp @b
@@:
pop esi
cmp al, '/'
jnz @f
cmp byte [edi-1], 0
jz .ok
@@:
add edx, 4
jmp .check
.ok2:
pop esi
.ok:
; add all parents directories if needed
.parloope:
mov ecx, [ebx+file_in_7z.parent]
jecxz .pardone
add ecx, ebp
mov eax, [cur_stamp]
cmp [ecx+file_in_7z.stamp], eax
jz .pardone
.parloopi:
mov edx, ecx
mov ecx, [ecx+file_in_7z.parent]
jecxz @f
add ecx, ebp
cmp [ecx+file_in_7z.stamp], eax
jnz .parloopi
@@:
mov [edx+file_in_7z.stamp], eax
push esi
mov eax, edx
mov edi, tmp_bdfe
push edi
sub esi, [ebx+file_in_7z.fullname]
add esi, [edx+file_in_7z.fullname]
push esi
call getattr_7z
mov eax, [esp+16+20]
call eax
pop esi
test al, al
jz .forced_exit
jmp .parloope
.pardone:
cmp [ebx+file_in_7z.bIsDirectory], 0
jz .addfile
mov eax, [cur_stamp]
cmp [ebx+file_in_7z.stamp], eax
jz .cont
mov [ebx+file_in_7z.stamp], eax
push esi
mov eax, ebx
mov edi, tmp_bdfe
push edi
push esi
call getattr_7z
mov eax, [esp+16+20]
call eax
pop esi
test al, al
jz .forced_exit
jmp .cont
.addfile:
push ebx esi
push 11h
pop edi
mov eax, ebx
call open_file_7z
pop esi ebx
test eax, eax
jz .cont
push eax
push eax
mov edi, tmp_bdfe
push edi
push esi
mov eax, ebx
call getattr_7z
mov eax, [esp+20+16]
call eax
pop ecx
push eax
push ebx
push ecx
call myclose
pop ebx
pop eax
test al, al
jz .forced_exit
.cont:
add ebx, file_in_7z.size
pop ecx
dec ecx
jnz .loop
.ret:
ret 20
.forced_exit:
pop ecx
jmp .ret
/programs/fs/kfar/trunk/kfar_arc/7zaes.inc
0,0 → 1,216
; Password handling in 7-Zip: "7zAES" filter (SHA256 + AES256).
; Ported from C++ sources of 7-Zip (c) Igor Pavlov.
aes7z_decoder:
virtual at 0
.outStream rb streamInfo.size
.inStream dd ?
.inLen dd ?
.inPtr dd ?
.bufRest dd ?
; key data
.NumCyclesPower dd ?
.SaltSize dd ?
.Salt rb 16
; AES data
.iv rb 16
.Key rb 32
.nr dd ?
.KeyExpanded rb 32*15
.size = $
end virtual
 
.fillBuf:
mov esi, [eax+.inPtr]
mov ebp, eax
add edi, [eax+.bufRest]
sub ecx, [eax+.bufRest]
js .rest1
and [eax+.bufRest], 0
.mainloop:
test ecx, ecx
jz .done
sub [ebp+.inLen], 16
js .refill
.refilled:
push esi edi ecx
mov ebx, edi
lea edi, [ebp+.nr]
call aes_decode
pop ecx edi esi
mov eax, dword [ebp+.iv]
xor [edi], eax
lodsd
mov dword [ebp+.iv], eax
mov eax, dword [ebp+.iv+4]
xor [edi+4], eax
lodsd
mov dword [ebp+.iv+4], eax
mov eax, dword [ebp+.iv+8]
xor [edi+8], eax
lodsd
mov dword [ebp+.iv+8], eax
mov eax, dword [ebp+.iv+12]
xor [edi+12], eax
lodsd
mov dword [ebp+.iv+12], eax
add edi, 16
sub ecx, 16
jns .mainloop
.rest1:
neg ecx
mov [ebp+.bufRest], ecx
.done:
mov [ebp+.inPtr], esi
popad
ret
 
.refill:
mov edx, [ebp+.inLen]
add edx, 16
jnz .rest
js return.err
mov eax, [ebp+.inStream]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
test edx, edx
jz return.err
mov esi, [eax+streamInfo.bufPtr]
mov [ebp+.inLen], edx
sub [ebp+.inLen], 16
jns .refilled
.rest:
; ASSERT([eax+streamInfo.fullSize] == 0);
sub edx, ecx
jb return.err
add ecx, edx
rep movsb
mov [ebp+.bufRest], edx
jmp .done
 
aes7z_get_buf_size:
mov eax, aes7z_decoder.size
mov edx, 0x4000
ret
 
aes7z_init_decoder:
; zero all
xor eax, eax
mov [ebp+aes7z_decoder.inLen], eax
mov [ebp+aes7z_decoder.bufRest], eax
mov [ebp+aes7z_decoder.NumCyclesPower], eax
mov [ebp+aes7z_decoder.SaltSize], eax
lea edi, [ebp+aes7z_decoder.Salt]
push 8
pop ecx
rep stosd ; zero .Salt and .iv
mov [ebp+streamInfo.fillBuf], aes7z_decoder.fillBuf
; parse parameters
cmp dword [esi-4], eax
jz .parok ; no parameters - OK
lodsb
mov cl, al
and al, 0x3F
mov byte [ebp+aes7z_decoder.NumCyclesPower], al
test cl, 0xC0
jz .parok
test cl, 0x80
setnz byte [ebp+aes7z_decoder.SaltSize]
shr cl, 6
and ecx, 1
cmp dword [esi-1-4], 2
jb return.err
lodsb
mov dl, al
shr al, 4
add byte [ebp+aes7z_decoder.SaltSize], al
and edx, 0xF
add ecx, edx
lea edx, [ecx+2]
push ecx
mov ecx, [ebp+aes7z_decoder.SaltSize]
add edx, ecx
cmp dword [esi-2-4], edx
jb return.err
lea edi, [ebp+aes7z_decoder.Salt]
rep movsb
pop ecx
lea edi, [ebp+aes7z_decoder.iv]
rep movsb
.parok:
test bl, bl
jnz .ret ; if reinitializing - all calculations have been already done
call query_password
jz return.clear
;.CalculateDigest:
mov cl, byte [ebp+aes7z_decoder.NumCyclesPower]
cmp cl, 0x3F
jnz .sha
lea edi, [ebp+aes7z_decoder.Key]
mov ecx, [ebp+aes7z_decoder.SaltSize]
push 32
pop edx
sub edx, ecx
lea esi, [ebp+aes7z_decoder.Salt]
rep movsb
mov ecx, [password_size]
add ecx, ecx
cmp ecx, edx
jbe @f
mov ecx, edx
@@:
sub edx, ecx
mov esi, password_unicode
rep movsb
mov ecx, edx
xor eax, eax
rep stosb
jmp .setkey
.sha:
cmp cl, 32
jb .normal
push 1
shl dword [esp], cl
push 0
jmp @f
.normal:
push 0
push 1
shl dword [esp], cl
@@:
push 0
push 0
call sha256_init
.loop:
lea esi, [ebp+aes7z_decoder.Salt]
mov edx, [ebp+aes7z_decoder.SaltSize]
call sha256_update
mov esi, password_unicode
mov edx, [password_size]
add edx, edx
call sha256_update
mov esi, esp
push 8
pop edx
call sha256_update
mov esi, esp
dec esi
@@:
inc esi
inc byte [esi]
jz @b
sub dword [esp+8], 1
sbb dword [esp+12], 0
mov eax, [esp+8]
or eax, [esp+12]
jnz .loop
lea edi, [ebp+aes7z_decoder.Key]
call sha256_final
add esp, 16
.setkey:
lea esi, [ebp+aes7z_decoder.Key]
push 8
pop edx ; 7z uses 256-bit keys
lea edi, [ebp+aes7z_decoder.nr]
call aes_setkey
.ret:
ret
/programs/fs/kfar/trunk/kfar_arc/7zbranch.inc
0,0 → 1,469
; 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
/programs/fs/kfar/trunk/kfar_arc/aes.inc
0,0 → 1,274
; Implementation of AES crypto algorithm.
; Buffer size is 0x10 bytes (128 bits), key size is not fixed.
; Written by diamond in 2007.
uglobal
aes.pow_table rb 256 ; pow[a] = 3^a
aes.log_table rb 256 ; log[3^a] = a
aes.sbox rb 256 ; ShiftBytes(a)
aes.sbox_rev rb 256 ; ShiftBytes^{-1}(a)
aes.mctable rd 256 ; MixColumns(ShiftBytes(a,0,0,0))
aes.mcrtable rd 256 ; MixColumns^{-1}(a,0,0,0)
endg
 
init_aes:
; Byte values in SubBytes transform are interpreted as items of
; GF(2^8) \cong F_2[x]/(x^8+x^4+x^3+x+1)F_2[x].
; x+1 is primitive item in this field.
xor ebx, ebx
push 1
pop eax
.1:
mov [aes.pow_table+ebx], al
mov [aes.log_table+eax], bl
; Multiplication by x+1...
mov cl, al ; save value
; ...multiply by x with mod (x^8+x^4+x^3+x+1) = 0x11B...
add al, al
jnc @f
xor al, 0x1B
@@:
; ...and add operand
xor al, cl
inc bl
jnz .1
; generate table for SubBytes transform
mov [aes.sbox+0], 0x63
mov [aes.sbox_rev+0x63], bl
inc ebx
.2:
; calculate inverse in GF(2^8)
mov al, [aes.log_table+ebx]
xor al, 0xFF ; equivalent to "al = 0xFF - al"
mov cl, [aes.pow_table+eax]
; linear transform of byte as vector over F_2
mov al, cl
rol cl, 1
xor al, cl
rol cl, 1
xor al, cl
rol cl, 1
xor al, cl
rol cl, 1
xor al, cl
xor al, 0x63
mov [aes.sbox+ebx], al
mov [aes.sbox_rev+eax], bl
inc bl
jnz .2
; generate table for SubBytes + MixColumn transforms
.3:
mov al, [aes.sbox+ebx] ; SubBytes transform
mov cl, al
add cl, cl
jnc @f
xor cl, 0x1B
@@:
mov byte [aes.mctable+ebx*4], cl ; low byte of MixColumn(a,0,0,0)
mov byte [aes.mctable+ebx*4+1], al
mov byte [aes.mctable+ebx*4+2], al
xor cl, al
mov byte [aes.mctable+ebx*4+3], cl ; high byte of MixColumn(a,0,0,0)
inc bl
jnz .3
; generate table for reverse MixColumn transform
mov dword [aes.mcrtable+0], ebx
inc ebx
.4:
; log_table[9]=0xC7, log_table[0xB]=0x68, log_table[0xD]=0xEE, log_table[0xE]=0xDF
mov cl, [aes.log_table+ebx]
mov al, cl
add al, 0xDF
adc al, 0
mov al, [aes.pow_table+eax]
mov byte [aes.mcrtable+ebx*4], al
mov al, cl
add al, 0xC7
adc al, 0
mov al, [aes.pow_table+eax]
mov byte [aes.mcrtable+ebx*4+1], al
mov al, cl
add al, 0xEE
adc al, 0
mov al, [aes.pow_table+eax]
mov byte [aes.mcrtable+ebx*4+2], al
mov al, cl
add al, 0x68
adc al, 0
mov al, [aes.pow_table+eax]
mov byte [aes.mcrtable+ebx*4+3], al
inc bl
jnz .4
ret
 
aes_setkey:
; in: esi->key, edx=key size in dwords, edi->AES data struc
lea eax, [edx+6] ; calc number of rounds (buffer size=4)
stosd
shl eax, 4
lea ebx, [edi+eax+16]
mov ecx, edx
rep movsd
push ebx
mov bl, 1
.0:
push 4
pop ecx
@@:
movzx esi, byte [edi-5+ecx]
mov al, [aes.sbox+esi]
rol eax, 8
loop @b
ror eax, 16
mov esi, edx
neg esi
xor eax, [edi+esi*4]
xor al, bl
add bl, bl
jnc @f
xor bl, 0x1B
@@:
stosd
lea ecx, [edx-1]
.1:
cmp edi, [esp]
jz .ret
cmp edx, 8
jnz @f
cmp ecx, 4
jnz @f
push eax
movzx eax, al
mov al, [aes.sbox+eax]
mov [esp], al
mov al, byte [esp+1]
mov al, [aes.sbox+eax]
mov [esp+1], al
mov al, byte [esp+2]
mov al, [aes.sbox+eax]
mov [esp+2], al
mov al, byte [esp+3]
mov al, [aes.sbox+eax]
mov [esp+3], al
pop eax
@@:
xor eax, [edi+esi*4]
stosd
loop .1
cmp edi, [esp]
jnz .0
.ret:
pop eax
ret
 
aes_decode:
; in: esi->in, ebx->out, edi->AES state
push ebx ebp
push dword [esi+12]
push dword [esi+8]
push dword [esi+4]
push dword [esi]
mov esi, esp
; reverse final round
mov ebp, [edi] ; number of rounds
mov ecx, ebp
shl ecx, 4
lea edi, [edi+ecx+4] ; edi->last round key
; load buffer into registers
mov eax, [esi]
mov ebx, [esi+4]
mov ecx, [esi+8]
mov edx, [esi+12]
; (AddRoundKey)
xor eax, [edi]
xor ebx, [edi+4]
xor ecx, [edi+8]
xor edx, [edi+12]
; (ShiftRows)
.loop0:
xchg ch, dh
xchg bh, ch
xchg ah, bh
rol eax, 16
rol ebx, 16
rol ecx, 16
rol edx, 16
xchg al, cl
xchg bl, dl
xchg ah, bh
xchg bh, ch
xchg ch, dh
rol eax, 16
rol ebx, 16
rol ecx, 16
rol edx, 16
; (SubBytes)
mov [esi], eax
mov [esi+4], ebx
mov [esi+8], ecx
mov [esi+12], edx
mov ecx, 16
@@:
movzx eax, byte [esi]
mov al, [aes.sbox_rev+eax]
mov byte [esi], al
add esi, 1
sub ecx, 1
jnz @b
sub esi, 16
sub edi, 16
; reverse normal rounds
sub ebp, 1
jz .done
mov eax, [esi]
mov ebx, [esi+4]
mov ecx, [esi+8]
mov edx, [esi+12]
push esi edi
; (AddRoundKey)
xor eax, [edi]
xor ebx, [edi+4]
xor ecx, [edi+8]
xor edx, [edi+12]
; (MixColumns)
macro mix_reg reg {
movzx esi, reg#l
mov edi, [aes.mcrtable+esi*4]
movzx esi, reg#h
rol e#reg#x, 16
mov esi, [aes.mcrtable+esi*4]
rol esi, 8
xor edi, esi
movzx esi, reg#l
mov esi, [aes.mcrtable+esi*4]
rol esi, 16
xor edi, esi
movzx esi, reg#h
mov esi, [aes.mcrtable+esi*4]
ror esi, 8
xor edi, esi
mov e#reg#x, edi
}
mix_reg a
mix_reg b
mix_reg c
mix_reg d
purge mix_reg
pop edi esi
jmp .loop0
.done:
; (AddRoundKey)
mov esi, [esp+20]
pop eax
xor eax, [edi]
mov [esi], eax
pop eax
xor eax, [edi+4]
mov [esi+4], eax
pop eax
xor eax, [edi+8]
mov [esi+8], eax
pop eax
xor eax, [edi+12]
mov [esi+12], eax
pop ebp ebx
ret
/programs/fs/kfar/trunk/kfar_arc/crc.inc
0,0 → 1,32
init_crc_table:
xor edx, edx
mov edi, crc_table
.1:
mov ecx, 8
mov eax, edx
.2:
shr eax, 1
jnc @f
xor eax, 0xEDB88320
@@:
loop .2
stosd
inc dl
jnz .1
ret
 
crc:
; in: ecx=size, esi->buffer
; out: eax=crc
or eax, -1
jecxz .end
.loop:
movzx edx, al
xor dl, byte [esi]
inc esi
shr eax, 8
xor eax, [crc_table+edx*4]
loop .loop
.end:
xor eax, -1
ret
/programs/fs/kfar/trunk/kfar_arc/kfar_arc.asm
0,0 → 1,1075
;
; project name: KFar_Arc - plugin for KFar, which supports various archives
; target platform: KolibriOS
; compiler: FASM 1.67.14
; version: 0.1
; last update: 2007-07-11 (Jul 11, 2007)
; minimal KFar version: 0.4
; minimal kernel: no limit
;
; author: Diamond
; email: diamondz@land.ru
; web: http://diamondz.land.ru
;
 
; standard start of Kolibri dynamic library
format MS COFF
public EXPORTS
 
section '.flat' code readable align 16
 
; include auxiliary procedures
include 'kglobals.inc' ; iglobal/uglobal
include 'lang.inc' ; define language for localized strings
include 'crc.inc' ; CRC32 calculation
include 'sha256.inc' ; SHA-256 hash algorithm
include 'aes.inc' ; AES crypto algorithm
; include main code for archives loading
include '7z.inc' ; *.7z
include 'lzma.inc' ; LZMA-decoder for *.7z
include 'ppmd.inc' ; PPMD-decoder for *.7z
include '7zbranch.inc' ; branch filters for *.7z
include '7zaes.inc' ; AES cryptor for *.7z
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; Interface for KFar ;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
virtual at 0
kfar_info_struc:
.lStructSize dd ?
.kfar_ver dd ?
.open dd ?
.read dd ?
.write dd ?
.seek dd ?
.flush dd ?
.filesize dd ?
.close dd ?
.pgalloc dd ?
.pgrealloc dd ?
.pgfree dd ?
.getfreemem dd ?
.pgalloc2 dd ?
.pgrealloc2 dd ?
.pgfree2 dd ?
.menu dd ?
.menu_centered_in dd ?
.DialogBox dd ?
.SayErr dd ?
.Message dd ?
.cur_console_size dd ?
end virtual
 
; int __stdcall plugin_load(kfar_info* info);
; Initialization of plugin + Save used KFar functions.
plugin_load:
mov eax, [esp+4]
mov [kfar_info], eax
push [eax+kfar_info_struc.read]
pop [read]
push [eax+kfar_info_struc.seek]
pop [seek]
push [eax+kfar_info_struc.close]
pop [close]
lea esi, [eax+kfar_info_struc.DialogBox]
mov edi, DialogBox
movsd
movsd
movsd
movsd
lea esi, [eax+kfar_info_struc.pgalloc]
mov edi, pgalloc
movsd
movsd
movsd
movsd
call init_crc_table
call init_aes
call init_ppmd
xor eax, eax ; success
ret 4
 
; HANDLE __stdcall OpenFilePlugin(HANDLE basefile, const char* name,
; const void* attr, const void* data, int datasize);
; This function is called when user presses Enter (or Ctrl+PgDn) on file.
; Plugin tests whether given file is of supported type
; and if so, loads information and returns
; handle to be used in subsequent calls to ReadFolder, SetFolder and so on.
OpenFilePlugin:
mov [bPasswordDefined], 0
mov esi, [esp+16]
mov ebp, [esp+4]
; test for 7z archive
cmp dword [esp+20], 20h ; minimal size of 7z archive is 20h bytes
jb .no_7z
cmp word [esi], '7z' ; signature, part 1
jnz .no_7z
cmp dword [esi+2], 0x1C27AFBC ; signature, part 2
jnz .no_7z
call open_7z
ret 20
.no_7z:
xor eax, eax
ret 20
 
; Handle of plugin in kfar_arc is as follow:
virtual at 0
handle_common:
.type dd ?
.root.subfolders dd ?
.root.subfolders.end dd ?
.root.subfiles dd ?
.root.subfiles.end dd ?
.root.NumSubItems dd ?
; ... some plugin-specific data follows ...
end virtual
 
; and for each archive item there is one file info structure, which begins as follow:
virtual at 0
file_common:
.fullname dd ? ; pointer to cp866 string
.name dd ? ; name without path (end of .fullname)
.namelen dd ? ; strlen(.name)
.bIsDirectory db ?
.bPseudoFolder db ?
rb 2
.parent dd ? ; pointer to parent directory record
.subfolders dd ? ; head of L2-list of subfolders [for folders]
.subfolders.end dd ?
.subfiles dd ? ; head of L2-list of files [for folders]
.subfiles.end dd ?
.NumSubItems dd ?
.next dd ? ; next item in list of subfolders/files
.prev dd ? ; previous item in list of subfolders/files
end virtual
 
; void __stdcall ClosePlugin(HANDLE hPlugin);
; This function frees all resources allocated in OpenFilePlugin.
ClosePlugin:
mov eax, [esp+4] ; get hPlugin
mov eax, [eax] ; hPlugin is pointer to internal data structure
; first dword is archive type (type_xxx constants)
dec eax ; types start from 1
jmp dword [ClosePluginTable+eax*4]
 
; int __stdcall ReadFolder(HANDLE hPlugin,
; unsigned dirinfo_start, unsigned dirinfo_size, void* dirdata);
ReadFolder:
mov eax, [esp+4]
mov eax, [eax]
dec eax
jmp dword [ReadFolderTable+eax*4]
 
; bool __stdcall SetFolder(HANDLE hPlugin,
; const char* relative_path, const char* absolute_path);
SetFolder:
mov eax, [esp+4]
mov eax, [eax]
dec eax
jmp dword [SetFolderTable+eax*4]
 
; void __stdcall GetFiles(HANDLE hPlugin, int NumItems, void* items[],
; void* addfile, void* adddir);
; bool __stdcall addfile(const char* name, void* bdfe_info, HANDLE hFile);
; bool __stdcall adddir(const char* name, void* bdfe_info);
GetFiles:
mov ebp, [esp+4]
mov eax, [ebp]
dec eax
jmp dword [GetFilesTable+eax*4]
 
; void __stdcall GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo* info);
GetOpenPluginInfo:
mov eax, [esp+8] ; get info ptr
mov byte [eax], 3 ; flags: add non-existing '..' entry automatically
; use GetFiles for copying
ret 8
 
; int __stdcall getattr(HANDLE hPlugin, const char* filename, void* info);
mygetattr:
call lookup_file_name
test eax, eax
jz @f
mov edx, [ebp]
dec edx
mov edi, [esp+12] ; info ptr
call dword [getattrTable+edx*4]
xor eax, eax
ret 12
@@:
mov al, 5 ; ERROR_FILE_NOT_FOUND
ret 12
 
; HANDLE __stdcall open(HANDLE hPlugin, const char* filename, int mode);
myopen:
call lookup_file_name
test eax, eax
jz @f
mov edx, [ebp]
dec edx
mov edi, [esp+12] ; mode
call dword [openTable+edx*4]
@@:
ret 12
 
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
myread:
mov ebx, [esp+4]
mov eax, [ebx]
jmp dword [readTable+eax*4]
 
; void __stdcall setpos(HANDLE hFile, __int64 pos);
mysetpos:
mov ebx, [esp+4]
mov eax, [ebx]
jmp dword [setposTable+eax*4]
 
; void __stdcall close(HANDLE hFile);
myclose:
mov ebx, [esp+4]
mov eax, [ebx]
jmp dword [closeTable+eax*4]
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;; Auxiliary procedures ;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; return.err and return.clear are labels to jmp if something is invalid
; the caller must previously define [_esp], [_ebp] and [error_proc], [clear_proc]
return.err:
mov esp, [_esp]
mov ebp, [_ebp]
jmp [error_proc]
return.clear:
mov esp, [_esp]
mov ebp, [_ebp]
jmp [clear_proc]
 
; data for following routine
iglobal
align 4
_24 dd 24
_60 dd 60
_10000000 dd 10000000
days400year dd 365*400+100-4+1
days100year dd 365*100+25-1
days4year dd 365*4+1
days1year dd 365
months dd 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
months2 dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
_400 dd 400
_100 dd 100
endg
 
; Convert QWORD FILETIME to BDFE format.
ntfs_datetime_to_bdfe:
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
push eax
mov eax, edx
xor edx, edx
div [_10000000]
xchg eax, [esp]
div [_10000000]
pop edx
; edx:eax = number of seconds since January 1, 1601
push eax
mov eax, edx
xor edx, edx
div [_60]
xchg eax, [esp]
div [_60]
mov [edi], dl
pop edx
; edx:eax = number of minutes
div [_60]
mov [edi+1], dl
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
xor edx, edx
div [_24]
mov [edi+2], dl
mov [edi+3], byte 0
; eax = number of days since January 1, 1601
xor edx, edx
div [days400year]
imul eax, 400
add eax, 1601
mov [edi+6], ax
mov eax, edx
xor edx, edx
div [days100year]
cmp al, 4
jnz @f
dec eax
add edx, [days100year]
@@:
imul eax, 100
add [edi+6], ax
mov eax, edx
xor edx, edx
div [days4year]
shl eax, 2
add [edi+6], ax
mov eax, edx
xor edx, edx
div [days1year]
cmp al, 4
jnz @f
dec eax
add edx, [days1year]
@@:
add [edi+6], ax
push esi edx
mov esi, months
movzx eax, word [edi+6]
test al, 3
jnz .noleap
xor edx, edx
push eax
div [_400]
pop eax
test edx, edx
jz .leap
xor edx, edx
div [_100]
test edx, edx
jz .noleap
.leap:
mov esi, months2
.noleap:
pop edx
xor eax, eax
inc eax
@@:
sub edx, [esi]
jb @f
add esi, 4
inc eax
jmp @b
@@:
add edx, [esi]
pop esi
inc edx
mov [edi+4], dl
mov [edi+5], al
add edi, 8
ret
 
; By given array of files information, initialize links between them
; ("[folder] contains [item]" relations).
; Information structure must be compatible with 'file_common'.
; Size of information structure is in [esp+4].
init_file_links:
; in: edx->file infos, ebx = number of files, [esp+4] = size,
; edi->{dd root.subfolders, dd root.subfolders.end,
; dd root.subfiles, dd root.subfiles.end, dd root.NumItems}
xor eax, eax
mov [.free], eax
push edi
stosd
stosd
stosd
stosd
stosd
pop edi
; Loop through all files
.mainloop:
dec ebx
js .mainloopdone
; Parse file name
; esi->current character in name
; dword [esp] = start of current component in file name
; ecx->{dd curdir.subfolders, dd curdir.subfolders.end,
; dd curdir.subfiles, dd curdir.subfiles.end}
mov esi, [edx+file_common.fullname]
mov ecx, edi
.parseloop:
push esi
.parsename:
lodsb
test al, al
jz @f
cmp al, '/'
jnz .parsename
@@:
; we have found next component of current name; look for it in current directory
sub esi, [esp]
dec esi ; esi = strlen(component)
cmp esi, 259
jbe @f
push ContinueBtn
push 1
push aNameTooLong_ptr
push 1
call [SayErr]
jmp return.clear
@@:
push ecx
mov eax, [ecx] ; eax->subfolders list
mov ecx, esi
.scansubfolders:
test eax, eax
jz .nofolder
add eax, [hOut]
cmp [eax+file_common.namelen], ecx
jnz .scancont
mov esi, [esp+4]
push ecx edi
mov edi, [eax+file_common.name]
repz cmpsb
pop edi ecx
jz .subfound
.scancont:
mov eax, [eax+file_common.next]
jmp .scansubfolders
.subfound:
; found subfolder, set it as current and continue parsing name
add [esp+4], ecx
pop ecx
lea ecx, [eax+file_common.subfolders]
pop esi
lodsb
test al, al
jnz .parseloop
; that was the last component of the name, and we have found subfolder
; so found subfolder is a virtual subfolder and must be replaced with current
; name
mov eax, [ecx-file_common.subfolders+file_common.namelen]
mov [edx+file_common.namelen], eax
sub esi, eax
dec esi
mov [edx+file_common.name], esi
sub edx, [hOut] ; convert pointer to relative
; replace item in L2-list
mov eax, [ecx-file_common.subfolders+file_common.prev]
test eax, eax
jnz .1
mov eax, [ecx-file_common.subfolders+file_common.parent]
sub eax, file_common.next - file_common.subfolders
jnc .1
lea eax, [edi-file_common.next]
jmp .2
.1:
add eax, [hOut]
.2:
mov [eax+file_common.next], edx
mov eax, [ecx-file_common.subfolders+file_common.next]
test eax, eax
jnz .3
mov eax, [ecx-file_common.subfolders+file_common.parent]
sub eax, file_common.prev - file_common.subfolders.end
jnc .3
lea eax, [edi-file_common.prev+4]
jmp .4
.3:
add eax, [hOut]
.4:
mov [eax+file_common.prev], edx
; correct parent links in childrens
mov eax, [ecx]
@@:
test eax, eax
jz @f
add eax, [hOut]
mov [eax+file_common.parent], edx
mov eax, [eax+file_common.next]
jmp @b
@@:
mov eax, [ecx+8]
@@:
test eax, eax
jz @f
add eax, [hOut]
mov [eax+file_common.parent], edx
mov eax, [eax+file_common.next]
jmp @b
@@:
add edx, [hOut]
; set children links
mov eax, [ecx]
mov [edx+file_common.subfolders], eax
mov eax, [ecx+4]
mov [edx+file_common.subfolders.end], eax
mov eax, [ecx+8]
mov [edx+file_common.subfiles], eax
mov eax, [ecx+12]
mov [edx+file_common.subfiles.end], eax
mov eax, [ecx+16]
mov [edx+file_common.NumSubItems], eax
; set prev/next links
mov eax, [ecx-file_common.subfolders+file_common.next]
mov [edx+file_common.next], eax
mov eax, [ecx-file_common.subfolders+file_common.prev]
mov [edx+file_common.prev], eax
; add old item to list of free items
uglobal
align 4
init_file_links.free dd ?
endg
sub ecx, file_common.subfolders
mov eax, [.free]
mov [ecx], eax
sub ecx, [hOut]
mov [.free], ecx
jmp .mainloopcont
.nofolder:
mov eax, edx
mov esi, [esp+4]
cmp byte [esi+ecx], 0
jz .newitem
; the current item is as 'dir1/item1' and 'dir1' has not been found
; allocate virtual subfolder 'dir1'
mov eax, [init_file_links.free]
test eax, eax
jz .realloc
add eax, [hOut]
push dword [eax]
pop [init_file_links.free]
jmp .allocated
.realloc:
; there is no free space, so reallocate [hOut] block
mov eax, [hOut]
sub [esp], eax ; make pointers relative
sub edx, eax
sub edi, eax
push ecx
mov ecx, [hOut.allocated]
add ecx, [esp+12+4]
mov [hOut.allocated], ecx
push ecx
and ecx, 0xFFF
cmp ecx, [esp+16+4]
pop ecx
ja @f
push edx
mov edx, eax
call [pgrealloc]
pop edx
test eax, eax
jnz @f
mov ecx, [hOut]
call [pgfree]
mov esp, [_esp]
or eax, -1
ret
@@:
pop ecx
mov [hOut], eax
add [esp], eax ; make pointers absolute
add edx, eax
add edi, eax
add eax, [hOut.allocated]
sub eax, [esp+8+4]
.allocated:
; eax -> new item
mov [eax+file_common.bIsDirectory], 1
mov [eax+file_common.bPseudoFolder], 1
.newitem:
mov [eax+file_common.namelen], ecx
pop ecx
pop esi
; ecx = parent item, eax = current item
mov [eax+file_common.name], esi
inc dword [ecx+16] ; new item in parent folder
push ecx
; add new item to end of L2-list
and [eax+file_common.next], 0
cmp [eax+file_common.bIsDirectory], 0
jnz @f
add ecx, 8
@@:
push eax
sub eax, [hOut]
cmp dword [ecx], 0
jnz @f
mov [ecx], eax
@@:
xchg eax, [ecx+4]
xchg eax, ecx
pop eax
mov [eax+file_common.prev], ecx
jecxz @f
add ecx, [hOut]
sub eax, [hOut]
mov [ecx+file_common.next], eax
add eax, [hOut]
@@:
pop ecx
; set parent link
and [eax+file_common.parent], 0
cmp ecx, edi
jz @f
sub ecx, file_common.subfolders
sub ecx, [hOut]
mov [eax+file_common.parent], ecx
@@:
; set current directory to current item
lea ecx, [eax+file_common.subfolders]
; if that was not last component, continue parse name
add esi, [eax+file_common.namelen]
lodsb
test al, al
jnz .parseloop
.mainloopcont:
; continue main loop
add edx, [esp+4]
jmp .mainloop
.mainloopdone:
; Loop done.
ret 4
 
; This subroutine is called by getattr and open.
; This subroutine looks for file name and returns NULL or pointer to file info record.
lookup_file_name:
mov ebp, [esp+8] ; hPlugin
mov esi, [esp+12] ; filename
lea edi, [ebp+handle_common.root.subfolders]
xor eax, eax
; KFar operates with absolute names, skip first '/'
cmp byte [esi], '/'
jnz .notfound
inc esi
.mainloop:
; get next component of name
push -1
pop ecx
@@:
inc ecx
cmp byte [esi+ecx], '/'
jz @f
cmp byte [esi+ecx], 0
jnz @b
@@:
; esi->component, ecx=length
; scan for required item in subfolders list
push -1
mov eax, [edi] ; .subfolders
.scan1:
test eax, eax
jz .notfound1
add eax, ebp
cmp [eax+file_common.namelen], ecx
jnz .cont1
push ecx esi edi
mov edi, [eax+file_common.name]
repz cmpsb
pop edi esi ecx
jz .found1
.cont1:
mov eax, [eax+file_common.next]
jmp .scan1
.notfound1:
pop edx
; if this is last component in file name, scan in subfiles list
cmp byte [esi+ecx], al
jnz .notfound
inc edx
jnz .notfound
mov eax, [edi+8] ; .subfiles
push edx
jmp .scan1
.found1:
pop edi
; item is found, go to next component
lea edi, [eax+file_common.subfolders]
lea esi, [esi+ecx+1]
cmp byte [esi-1], 0
jnz .mainloop
; this was the last component
.notfound:
ret
 
; Memory streams handling.
; Archive handlers create memory stream for small files:
; size of which is not greater than (free RAM size)/4 and
; not greater than following constant...
;LIMIT_FOR_MEM_STREAM = 2*1024*1024
; ...if it is defined. Now the definition is commented:
; if user has many physical memory, why not to use it?
 
virtual at 0
mem_stream:
.type dd ? ; type_mem_stream
.size dd ?
.pos dd ?
.buf:
end virtual
 
; unsigned __stdcall read(ebx = HANDLE hFile, void* buf, unsigned size);
read_mem_stream:
mov eax, [esp+12]
mov ecx, [ebx+mem_stream.size]
sub ecx, [ebx+mem_stream.pos]
jnc @f
xor ecx, ecx
@@:
cmp eax, ecx
jb @f
mov eax, ecx
@@:
mov ecx, eax
lea esi, [ebx+mem_stream.buf]
add esi, [ebx+mem_stream.pos]
add [ebx+mem_stream.pos], eax
mov edi, [esp+8]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
ret 12
 
; void __stdcall setpos(ebx = HANDLE hFile, __int64 pos);
setpos_mem_stream:
mov eax, [esp+8]
mov [ebx+mem_stream.pos], eax
ret 12
 
; void __stdcall close(ebx = HANDLE hFile);
close_mem_stream:
mov ecx, ebx
call [pgfree]
ret 4
 
; Allocate handle for file
; esi -> handle table, ecx = size of handle
alloc_handle:
; Handle table is L2-list of allocated pages.
; Scan for free entry
mov edx, esi
@@:
mov edx, [edx]
cmp edx, esi
jz .alloc_new
mov eax, [edx+8] ; head of L1-list of free entries
test eax, eax ; has free entry?
jz @b
; we have found allocated page with free entry; allocate entry and return
inc dword [edx+12] ; number of busy entries
push dword [eax]
pop dword [edx+8]
.ret:
ret
.alloc_new:
; no free pages; get new page and initialize
push ecx
mov ecx, 0x1000
call [pgalloc]
pop ecx
test eax, eax
jz .ret
; insert new page to start of L2-list
mov edx, [esi]
mov [eax], edx
mov [esi], eax
mov [eax+4], esi
mov [edx+4], eax
mov dword [eax+12], 1 ; 1 allocated entry
; initialize list of free entries
lea edx, [eax+16]
push edx ; save return value
add edx, ecx
mov [eax+8], edx
add eax, 0x1000
@@:
mov esi, edx
add edx, ecx
mov [esi], edx
cmp edx, eax
jb @b
and dword [esi], 0
pop eax
ret
 
; Free handle allocated in previous procedure
; esi = handle
free_handle:
mov ecx, esi
and ecx, not 0xFFF ; get page
; add entry to head of L1-list of free entries
mov eax, [ecx+8]
mov [esi], eax
mov [ecx+8], esi
dec dword [ecx+12] ; decrement number of allocated entries
jnz .ret
; delete page from common L2-list
mov eax, [ecx]
mov edx, [ecx+4]
mov [eax+4], edx
mov [edx], eax
; free page
call [pgfree]
.ret:
ret
 
; Ask user to enter password.
; Out: ZF set <=> user pressed Esc
; 'password_ansi', 'password_unicode', 'password_size' filled
query_password:
cmp [bPasswordDefined], 0
jnz .ret
mov edi, password_data
mov eax, password_maxlen
stosd ; maximum length
xor eax, eax
stosd ; start of visible part
stosd ; position of cursor
stosb ; initial state: empty string
mov eax, [cur_console_size]
mov eax, [eax] ; get current console width
sub eax, 12
mov edi, password_dlg
mov [edi+password_dlg.width-password_dlg], eax
dec eax
dec eax
mov [edi+password_dlg.width1-password_dlg], eax
mov [edi+password_dlg.width2-password_dlg], eax
push edi
call [DialogBox]
inc eax
jz .ret
; convert ANSI-cp866 to UNICODE string; also calculate 'password_size'
mov esi, password_ansi
mov edi, password_unicode
or [password_size], -1
.cvt:
inc [password_size]
lodsb
mov ah, 0
; 0x00-0x7F - trivial map
cmp al, 0x80
jb .symb
; 0x80-0xAF -> 0x410-0x43F
cmp al, 0xB0
jae @f
add ax, 0x410-0x80
jmp .symb
@@:
; 0xE0-0xEF -> 0x440-0x44F
cmp al, 0xE0
jb .unk
cmp al, 0xF0
jae @f
add ax, 0x440-0xE0
jmp .symb
@@:
; 0xF0 -> 0x401
; 0xF1 -> 0x451
cmp al, 'ð'
jz .yo1
cmp al, 'ñ'
jz .yo2
.unk:
mov al, '_'
jmp .symb
.yo1:
mov ax, 0x401
jmp .symb
.yo2:
mov ax, 0x451
.symb:
stosw
test al, al
jnz .cvt
inc [bPasswordDefined] ; clears ZF flag
.ret:
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;; Initialized data ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; export table
align 4
EXPORTS:
dd aVersion, 1
dd aPluginLoad, plugin_load
dd aOpenFilePlugin,OpenFilePlugin
dd aClosePlugin, ClosePlugin
dd aReadFolder, ReadFolder
dd aSetFolder, SetFolder
dd aGetFiles, GetFiles
dd aGetOpenPluginInfo, GetOpenPluginInfo
dd aGetattr, mygetattr
dd aOpen, myopen
dd aRead, myread
dd aSetpos, mysetpos
dd aClose, myclose
dd 0
 
; exported names
aVersion db 'version',0
aPluginLoad db 'plugin_load',0
aOpenFilePlugin db 'OpenFilePlugin',0
aClosePlugin db 'ClosePlugin',0
aReadFolder db 'ReadFolder',0
aSetFolder db 'SetFolder',0
aGetFiles db 'GetFiles',0
aGetOpenPluginInfo db 'GetOpenPluginInfo',0
aGetattr db 'getattr',0
aOpen db 'open',0
aRead db 'read',0
aSetpos db 'setpos',0
aClose db 'close',0
 
; common strings
if lang eq ru
aContinue db 'à®¤®«¦¨âì',0
aCancel db 'Žâ¬¥­ ',0
aHeaderError db 'Žè¨¡ª  ¢ § £®«®¢ª¥  à娢 ',0
aReadError db 'Žè¨¡ª  ç⥭¨ï',0
aNoFreeRam db '¥¤®áâ â®ç­® ᢮¡®¤­®© ®¯¥à â¨¢­®© ¯ ¬ïâ¨',0
aEncodingProblem db 'à®¡«¥¬  á ª®¤¨à®¢ª®©',0
aEncodingProblem_str db 'ˆ¬¥­  ­¥ª®â®àëå ä ©«®¢ ¢  à娢¥ ᮤ¥à¦ â ᨬ¢®«ë,',0
.2 db '­¥ ¯à¥¤áâ ¢¨¬ë¥ ¢ ª®¤¨à®¢ª¥ cp866.',0
.3 db 'â¨ ᨬ¢®«ë ¡ã¤ãâ § ¬¥­¥­ë ­  ¯®¤çñન¢ ­¨ï.',0
aEnterPassword db '‚¢¥¤¨â¥ ¯ à®«ì:',0
aEnterPasswordLen = $ - aEnterPassword - 1
aEnterPasswordTitle db '‚¢®¤ ¯ à®«ï',0
aArchiveDataError db 'Žè¨¡ª  ¢ ¤ ­­ëå  à娢 ',0
aArchiveDataErrorPass db 'Žè¨¡ª  ¢ ¤ ­­ëå  à娢  ¨«¨ ­¥¢¥à­ë© ¯ à®«ì',0
aChangePass db '‚¢¥á⨠¯ à®«ì',0
aNameTooLong db '‘«¨èª®¬ ¤«¨­­®¥ ¨¬ï',0
else
aContinue db 'Continue',0
aCancel db 'Cancel',0
aHeaderError db 'Invalid archive header',0
aReadError db 'Read error',0
aNoFreeRam db 'There is not enough of free RAM',0
aEncodingProblem db 'Encoding problem',0
aEncodingProblem_str db 'The names of some files in the archive contain',0
.2 db 'characters which can not be represented in cp866.',0
.3 db 'Such characters will be replaced to underscores.',0
aEnterPassword db 'Enter password:',0
aEnterPasswordLen = $ - aEnterPassword - 1
aEnterPasswordTitle db 'Get password',0
aArchiveDataError db 'Error in archive data',0
aArchiveDataErrorPass db 'Error in archive data or incorrect password',0
aChangePass db 'Enter password',0
aNameTooLong db 'Name is too long',0
end if
 
; kfar_arc supports [hmm... will support...] many archive types.
; OpenFilePlugin looks for supported archive signature and gives control
; to concrete handler if found.
; Other functions just determine type of opened archive and jumps to corresponding handler.
type_mem_stream = 0 ; memory stream - for file handles (returned from 'open')
type_7z = 1
 
; archive functions (types start from type_7z)
align 4
ClosePluginTable:
dd close_7z
ReadFolderTable:
dd ReadFolder_7z
SetFolderTable:
dd SetFolder_7z
GetFilesTable:
dd GetFiles_7z
getattrTable:
dd getattr_7z
openTable:
dd open_file_7z
 
; file functions (types start from type_mem_stream)
readTable:
dd read_mem_stream
dd read_7z
setposTable:
dd setpos_mem_stream
dd setpos_7z
closeTable:
dd close_mem_stream
dd close_file_7z
 
; pointers for SayErr and Message
ContinueBtn dd aContinue
HeaderError_ptr dd aHeaderError
aReadError_ptr dd aReadError
aNoFreeRam_ptr dd aNoFreeRam
aEncodingProblem_str_ptr:
dd aEncodingProblem_str
dd aEncodingProblem_str.2
dd aEncodingProblem_str.3
aNameTooLong_ptr dd aNameTooLong
aArchiveDataError_ptr dd aArchiveDataError
aArchiveDataErrorPass_ptr dd aArchiveDataErrorPass
CancelPassBtn dd aCancel
dd aChangePass
 
; "enter password" dialog for KFar
password_dlg:
dd 1 ; use standard dialog colors
dd -1 ; center window by x
dd -1 ; center window by y
.width dd ? ; width (will be filled according to current console width)
dd 2 ; height
dd 4, 2 ; border size
dd aEnterPasswordTitle ; title
dd ? ; colors (will be set by KFar)
dd 0, 0 ; reserved for DlgProc
dd 2 ; 2 controls
; the string "enter password"
dd 1 ; type: static
dd 1,0 ; upper-left position
.width1 dd ?,0 ; bottom-right position
dd aEnterPassword ; data
dd 0 ; flags
; editbox for password
dd 3 ; type: edit
dd 1,1 ; upper-left position
.width2 dd ?,0 ; bottom-right position
dd password_data ; data
dd 2Ch ; flags
 
IncludeIGlobals
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; Uninitialized data ;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
section '.udata' data readable writable align 16
kfar_info dd ?
crc_table rd 256
_esp dd ?
_ebp dd ?
bufsize dd ?
bufptr dd ?
bufend dd ?
buffer rb 1024
inStream dd ?
hOut dd ?
.allocated dd ?
 
error_proc dd ?
clear_proc dd ?
 
; import from kfar
read dd ?
seek dd ?
close dd ?
pgalloc dd ?
pgrealloc dd ?
pgfree dd ?
getfreemem dd ?
DialogBox dd ?
SayErr dd ?
Message dd ?
cur_console_size dd ?
 
; data for editbox in kfar dialog
password_maxlen = 512
password_data:
.maxlen dd ?
.pos dd ?
.start dd ?
password_ansi rb password_maxlen+1
bPasswordDefined db ?
 
; converted password
password_unicode rw password_maxlen+1
password_size dd ?
 
IncludeUGlobals
 
bWasWarning db ?
/programs/fs/kfar/trunk/kfar_arc/kglobals.inc
0,0 → 1,50
;------------------------------------------------------------------
; use "iglobal" for inserting initialized global data definitions.
;------------------------------------------------------------------
macro iglobal {
IGlobals equ IGlobals,
macro __IGlobalBlock { }
 
;-------------------------------------------------------------
; use 'uglobal' for inserting uninitialized global definitions.
; even when you define some data values, these variables
; will be stored as uninitialized data.
;-------------------------------------------------------------
macro uglobal {
UGlobals equ UGlobals,
macro __UGlobalBlock { }
 
endg fix } ; Use endg for ending iglobal and uglobal blocks.
 
macro IncludeIGlobals{
macro IGlobals dummy,[n] \{ __IGlobalBlock
purge __IGlobalBlock \}
match I, IGlobals \{ I \} }
 
 
macro IncludeUGlobals{
macro UGlobals dummy,[n] \{
\common
\local begin, size
begin = $
virtual at $
\forward
__UGlobalBlock
purge __UGlobalBlock
\common
size = $ - begin
end virtual
rb size
\}
match U, UGlobals \{ U \} }
 
macro IncludeAllGlobals {
IncludeIGlobals
IncludeUGlobals
}
iglobal
endg
 
uglobal
endg
/programs/fs/kfar/trunk/kfar_arc/lang.inc
0,0 → 1,0
lang fix ru
/programs/fs/kfar/trunk/kfar_arc/lzma.inc
0,0 → 1,581
; LZMA decoder for *.7z archives.
; Based on C decoder in LZMA SDK (c) Igor Pavlov.
; Portions by Diamond, 2006, 2007.
lzma_decoder:
virtual at 0
.outStream rb streamInfo.size
.inStream dd ?
 
; RangeDecoder data
.inLen dd ?
.inPtr dd ?
.code dd ?
.range dd ?
 
; parameters
.pb db ? ; pos state bits (0 - 4)
.lp db ? ; literal pos state bits (0 - 4)
.lc db ? ; literal context bits (0 - 8)
.previousByte db ?
.posStateMask dd ? ; (1 shl .pb)-1
.literalPosMask dd ? ; (1 shl .lp)-1
 
; constants
.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
 
; variables
.continue dd ?
.ecx dd ?
.outEnd dd ?
.dictSize dd ?
.state dd ?
.rep0 dd ?
.rep1 dd ?
.rep2 dd ?
.rep3 dd ?
.p rd LZMA_BASE_SIZE
.basesize = $
; rd LZMA_LIT_SIZE shl (.lc+.lp)
end virtual
 
.fillBuf:
mov ebp, eax
mov ebx, [ebp+.state]
jecxz .nodata
add ecx, edi
mov [ebp+.outEnd], ecx
mov esi, [ebp+.inPtr]
jmp [ebp+.continue]
.nodata:
popad
ret
.start:
mov eax, [ebp+.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
bswap eax
mov [ebp+.code], eax
or [ebp+.range], -1
.main_loop:
cmp edi, [ebp+.outEnd]
jae .main_loop_done
mov edx, edi
and edx, [ebp+.posStateMask]
mov eax, ebx
shl eax, .kNumPosBitsMax
add eax, edx
lea eax, [ebp + .p + .IsMatch*4 + eax*4]
call .RangeDecoderBitDecode
jc .1
movzx eax, [ebp+.previousByte]
mov ah, dl
and ah, byte [ebp+.literalPosMask]
mov cl, 8
sub cl, [ebp+.lc]
shr eax, cl
imul eax, LZMA_LIT_SIZE*4
lea eax, [ebp + eax + .p+.Literal*4]
cmp ebx, .kNumLitStates
jb .literal
xor edx, edx
sub edx, [ebp+.rep0]
mov dl, [edi + edx]
call .LzmaLiteralDecodeMatch
jmp @f
.literal:
call .LzmaLiteralDecode
@@:
mov [ebp+.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, [ebp + .p + .IsRep*4 + ebx*4]
call .RangeDecoderBitDecode
jnc .10
lea eax, [ebp + .p + .IsRepG0*4 + ebx*4]
call .RangeDecoderBitDecode
jc .111
mov eax, ebx
shl eax, .kNumPosBitsMax
add eax, edx
lea eax, [ebp + .p + .IsRep0Long*4 + eax*4]
call .RangeDecoderBitDecode
jc .1101
cmp bl, 7
setae bl
lea ebx, [9 + ebx + ebx]
xor edx, edx
sub edx, [ebp+.rep0]
mov al, [edi + edx]
stosb
mov [ebp+.previousByte], al
jmp .main_loop
.111:
lea eax, [ebp + .p + .IsRepG1*4 + ebx*4]
call .RangeDecoderBitDecode
mov eax, [ebp+.rep1]
jnc .l3
.l1:
lea eax, [ebp + .p + .IsRepG2*4 + ebx*4]
call .RangeDecoderBitDecode
mov eax, [ebp+.rep2]
jnc .l2
xchg [ebp+.rep3], eax
.l2:
push [ebp+.rep1]
pop [ebp+.rep2]
.l3:
xchg eax, [ebp+.rep0]
mov [ebp+.rep1], eax
.1101:
lea eax, [ebp + .p + .RepLencoder*4]
call .LzmaLenDecode
cmp bl, 7
setc bl
adc bl, bl
xor bl, 3
add bl, 8
jmp .repmovsb
.10:
mov eax, [ebp+.rep0]
xchg eax, [ebp+.rep1]
xchg eax, [ebp+.rep2]
xchg eax, [ebp+.rep3]
cmp bl, 7
setc bl
adc bl, bl
xor bl, 3
add bl, 7
lea eax, [ebp + .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
lea eax, [ebp + .p+.PosSlot*4 + eax*4]
call .RangeDecoderBitTreeDecode
mov [ebp+.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 [ebp+.rep0], eax
pop edx
cmp edx, .kEndPosModelIndex
jae .l5
sub eax, edx
lea eax, [ebp + .p + (.SpecPos - 1)*4 + eax*4]
call .RangeDecoderReverseBitTreeDecode
add [ebp+.rep0], ecx
jmp .l6
.l5:
sub ecx, .kNumAlignBits
call .RangeDecoderDecodeDirectBits
mov ecx, .kNumAlignBits
shl eax, cl
add [ebp+.rep0], eax
lea eax, [ebp+.p+.Align_*4]
call .RangeDecoderReverseBitTreeDecode
add [ebp+.rep0], ecx
.l6:
pop ecx
inc [ebp+.rep0]
jz .main_loop_done
.repmovsb:
add ecx, .kMatchMinLen
.repmovsbz:
push esi
.repmovsbr:
mov eax, [ebp+.rep0]
cmp eax, [ebp+.dictSize]
jae return.err
mov esi, edi
sub esi, eax
mov eax, [ebp+streamInfo.bufPtr]
sub eax, esi
ja .repmovsb0
mov eax, [ebp+.outEnd]
sub eax, edi
push ecx
cmp ecx, eax
jb @f
mov ecx, eax
@@:
sub [esp], ecx
rep movsb
pop ecx
jz .repmovsb1
pop [ebp+.inPtr]
mov [ebp+.state], ebx
mov [ebp+.ecx], ecx
mov [ebp+.continue], .restart_repmovsb
popad
ret
.repmovsb0:
mov edx, [ebp+.dictSize]
cmp edx, [ebp+streamInfo.bufSize]
jnz return.err
add esi, edx
push ecx
cmp ecx, eax
jb @f
mov ecx, eax
@@:
mov eax, [ebp+.outEnd]
sub eax, edi
cmp ecx, eax
jb @f
mov ecx, eax
@@:
sub [esp], ecx
rep movsb
pop ecx
jnz .repmovsbr
.repmovsb1:
pop esi
mov al, [edi-1]
mov [ebp+.previousByte], al
jmp .main_loop
.main_loop_done:
mov [ebp+.state], ebx
mov [ebp+.continue], .main_loop
mov [ebp+.inPtr], esi
popad
ret
.restart_repmovsb:
mov ecx, [ebp+.ecx]
jmp .repmovsbz
 
.RangeDecoderBitDecode:
; in: eax->prob
; out: CF=bit; destroys eax
push edx
mov edx, [ebp+.range]
shr edx, .kNumBitModelTotalBits
imul edx, [eax]
cmp [ebp+.code], edx
jae .ae
mov [ebp+.range], edx
mov edx, .kBitModelTotal
sub edx, [eax]
shr edx, .kNumMoveBits
add [eax], edx
clc
.n:
lahf
cmp [ebp+.range], .kTopValue
jae @f
shl [ebp+.range], 8
shl [ebp+.code], 8
sub [ebp+.inLen], 1
js .refill1
.refilled1:
lodsb
mov byte [ebp+.code], al
@@:
sahf
pop edx
ret
.ae:
sub [ebp+.range], edx
sub [ebp+.code], edx
mov edx, [eax]
shr edx, .kNumMoveBits
sub [eax], edx
stc
jmp .n
 
.refill1:
push eax
call .refill
pop eax
jmp .refilled1
 
.refill:
mov eax, [ebp+.inStream]
cmp dword [eax+streamInfo.fullSize+4], 0
jnz @f
cmp dword [eax+streamInfo.fullSize], 0
jz return.err
@@:
call fillBuf
mov esi, [eax+streamInfo.bufPtr]
mov eax, [eax+streamInfo.bufDataLen]
dec eax
js return.err
mov [ebp+.inLen], eax
ret
 
.refill2:
call .refill
jmp .refilled2
 
.RangeDecoderDecodeDirectBits:
; in: ecx=numTotalBits
; out: eax=result; destroys edx
xor eax, eax
.l:
shr [ebp+.range], 1
shl eax, 1
mov edx, [ebp+.code]
sub edx, [ebp+.range]
jb @f
mov [ebp+.code], edx
or eax, 1
@@:
cmp [ebp+.range], .kTopValue
jae @f
shl [ebp+.range], 8
shl [ebp+.code], 8
push eax
dec [ebp+.inLen]
js .refill2
.refilled2:
lodsb
mov byte [ebp+.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
 
; LZMA parameters:
; db lc + 9 * (lp + 5 * pb)
; dd dictionarySize
 
lzma_get_buf_size:
cmp dword [esi-4], 5
jb return.err
push ecx
lodsb
aam 9
mov cl, al
mov al, ah
aam 5
add cl, al
mov eax, LZMA_LIT_SIZE
shl eax, cl
lea eax, [lzma_decoder.basesize+eax*4]
pop ecx
mov edx, [esi]
ret
 
lzma_init_decoder:
lodsb
aam 9
mov [ebp+lzma_decoder.lc], al
mov al, ah
aam 5
mov [ebp+lzma_decoder.lp], al
mov [ebp+lzma_decoder.pb], ah
cmp ah, lzma_decoder.kNumPosBitsMax
ja return.err
mov cl, ah
lodsd
mov [ebp+lzma_decoder.dictSize], eax
push 1
pop eax
shl eax, cl
dec eax
mov [ebp+lzma_decoder.posStateMask], eax
mov cl, [ebp+lzma_decoder.lp]
push 1
pop eax
shl eax, cl
dec eax
mov [ebp+lzma_decoder.literalPosMask], eax
mov [ebp+streamInfo.fillBuf], lzma_decoder.fillBuf
mov [ebp+lzma_decoder.continue], lzma_decoder.start
xor eax, eax
mov [ebp+lzma_decoder.previousByte], al
mov [ebp+lzma_decoder.state], eax
inc eax
lea edi, [ebp+lzma_decoder.rep0]
stosd
stosd
stosd
mov eax, LZMA_LIT_SIZE
mov cl, [ebp+lzma_decoder.lc]
add cl, [ebp+lzma_decoder.lp]
shl eax, cl
lea ecx, [eax+lzma_decoder.Literal]
mov eax, lzma_decoder.kBitModelTotal/2
lea edi, [ebp+lzma_decoder.p]
rep stosd
ret
/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
/programs/fs/kfar/trunk/kfar_arc/sha256.inc
0,0 → 1,238
; Implementation of SHA-256 hash algorithm.
; Written by diamond in 2007.
 
iglobal
align 4
sha256_start_digest:
dd 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A
dd 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
sha256_const:
dd 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5
dd 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5
dd 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3
dd 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174
dd 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC
dd 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA
dd 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7
dd 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967
dd 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13
dd 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85
dd 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3
dd 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070
dd 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5
dd 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3
dd 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208
dd 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
endg
 
uglobal
align 4
sha256_buf rb 64
sha256_digest rd 8
sha256_count dd ?
sha256_size dq ?
endg
 
sha256_init:
mov edi, sha256_digest
mov esi, sha256_start_digest
push 8
pop ecx
rep movsd
xor eax, eax
stosd ; 0 bytes in buffer
stosd
stosd ; 0 bytes processed
ret
 
; Core of SHA-256: transform 64-byte 'sha256_buf' to updated 'sha256_digest'
sha256_transform:
mov esi, sha256_buf
mov edi, esi
rept 16
{
lodsd
bswap eax
stosd
}
push ebp
mov ebp, [esi+7*4]
mov edi, [esi+6*4]
push dword [esi+5*4]
push dword [esi+4*4]
push dword [esi+3*4]
push dword [esi+2*4]
push dword [esi+1*4]
push dword [esi+0*4]
xor ecx, ecx
.loop:
macro cmd1 cmd,a,b
{
if (b and 7) = 7
cmd a, ebp
else if (b and 7) = 6
cmd a, edi
else
cmd a, [esp+(b and 7)*4]
end if
}
macro cmd2 cmd,a,b
{
if (a and 7) = 7
cmd ebp, b
else if (a and 7) = 6
cmd edi, b
else
cmd [esp+(a and 7)*4], b
end if
}
rept 16 counter
{
cmd1 mov, eax, (5-counter)
ror eax, 6
mov edx, eax
ror eax, 5
xor edx, eax
ror eax, 14
xor edx, eax
cmd1 mov, eax, (6-counter)
cmd1 mov, esi, (7-counter)
xor eax, esi
cmd1 and, eax, (5-counter)
xor eax, esi
add edx, eax
add edx, [sha256_const+ecx+(counter-1)*4]
add edx, dword [sha256_buf+(counter-1)*4]
test ecx, ecx
jz @f
mov eax, dword [sha256_buf+((counter-3) and 15)*4]
mov esi, eax
ror eax, 17
shr esi, 10
xor esi, eax
ror eax, 2
xor esi, eax
add esi, dword [sha256_buf+((counter-8) and 15)*4]
mov eax, dword [sha256_buf+(counter and 15)*4]
mov ebx, eax
ror eax, 7
shr ebx, 3
xor ebx, eax
ror eax, 11
xor ebx, eax
add esi, ebx
add dword [sha256_buf+(counter-1)*4], esi
add edx, esi
@@:
cmd1 add, edx, (8-counter)
cmd2 mov, (8-counter), edx
cmd2 add, (4-counter), edx
cmd1 mov, ebx, (1-counter)
mov eax, ebx
cmd1 mov, edx, (2-counter)
mov esi, ebx
ror eax, 2
or esi, edx
and ebx, edx
cmd1 and, esi, (3-counter)
mov edx, eax
or esi, ebx
ror eax, 11
xor edx, eax
ror eax, 9
xor edx, eax
add esi, edx
cmd2 add, (8-counter), esi
}
purge cmd1,cmd2
add cl, 64
jnz .loop
mov esi, sha256_digest
pop eax
add [esi+0*4], eax
pop eax
add [esi+1*4], eax
pop eax
add [esi+2*4], eax
pop eax
add [esi+3*4], eax
pop eax
add [esi+4*4], eax
pop eax
add [esi+5*4], eax
add [esi+6*4], edi
add [esi+7*4], ebp
pop ebp
ret
 
sha256_update.transform:
push esi edx
call sha256_transform
pop edx esi
mov [sha256_count], ecx
 
sha256_update:
; in: esi->data, edx=size
mov eax, 64
sub eax, [sha256_count]
sub eax, edx
sbb ecx, ecx
and ecx, eax
add ecx, edx
sub edx, ecx
mov edi, sha256_buf
add edi, [sha256_count]
add [sha256_count], ecx
add dword [sha256_size], ecx
adc dword [sha256_size+4], 0
rep movsb
cmp edi, sha256_buf+64
jz .transform
.ret:
ret
 
sha256_final:
; out: edi->digest
push edi
mov eax, [sha256_count]
mov [sha256_buf+eax], 0x80
inc eax
cmp al, 64-8
jbe @f
lea edi, [sha256_buf+eax]
push 64
pop ecx
sub ecx, eax
xor eax, eax
rep stosb
push edx
call sha256_transform
pop edx
xor eax, eax
@@:
push 64-8
pop ecx
sub ecx, eax
lea edi, [sha256_buf+eax]
xor eax, eax
rep stosb
mov eax, dword [sha256_size]
mov edx, dword [sha256_size+4]
shld edx, eax, 3
shl eax, 3
bswap edx
bswap eax
xchg eax, edx
stosd
xchg eax, edx
stosd
call sha256_transform
mov esi, sha256_digest
mov cl, 8
pop edi
@@:
lodsd
bswap eax
stosd
loop @b
ret