/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 |