diff --git a/programs/develop/libraries/sorter/sort.asm b/programs/develop/libraries/sorter/sort.asm new file mode 100644 index 0000000000..85609ac7fd --- /dev/null +++ b/programs/develop/libraries/sorter/sort.asm @@ -0,0 +1,677 @@ +format MS COFF +public EXPORTS +section '.flat' code readable align 16 +; void __stdcall START(dword state); +DLL_ENTRY equ 1 +DLL_EXIT equ -1 +START: + cmp dword [esp+4], DLL_ENTRY + jnz .ret + push edi + mov edi, tolower_table + push 'A' + pop ecx + xor eax, eax +@@: + stosb + inc eax + loop @b + add al, 0x20 + mov cl, 'Z'-'A'+1 +@@: + stosb + inc eax + loop @b + sub al, 0x20 + mov cl, 'Ђ'-'Z'-1 +@@: + stosb + inc eax + loop @b + add al, 0x20 + mov cl, 'ђ'-'Ђ' +@@: + stosb + inc eax + loop @b + add al, 0x30 + mov cl, 'џ'-'ђ'+1 +@@: + stosb + inc eax + loop @b + sub al, 0x50 + mov cl, 256-'џ'-1 +@@: + stosb + inc eax + loop @b + mov byte [edi-256+'р'], 'с' + pop edi +.ret: + ret 4 + +; enum sort_mode +; { SORT_BY_NAME = 0, SORT_BY_NAME_REV = 1, +; SORT_BY_EXT = 2, SORT_BY_EXT_REV = 3, +; SORT_BY_MODIFIED = 4, SORT_BY_MODIFIED_REV = 5, +; SORT_BY_SIZE = 6, SORT_BY_SIZE_REV = 7, +; SORT_BY_CREATED = 10, SORT_BY_CREATED_REV = 11, +; SORT_BY_ACCESSED = 12, SORT_BY_ACCESSED_REV = 13 }; +; int __stdcall sort_dir(BDFE* folder_data, unsigned num_folder_entries, sort_mode mode); +; return: 0 = ok, 1 = error +sort_dir: + cmp dword [esp+12], num_compare_fns + jae .error + push ebx + mov eax, ptr_table + 0x1FFF + mov edx, ptr_table + and eax, not 0xFFF + mov ecx, [esp+4+8] ; num_folder_entries + sub eax, edx + shl ecx, 3 + jz .done + cmp eax, ecx + jae .memok + push 68 + pop eax + push 12 + pop ebx + int 0x40 + test eax, eax + jz .error2 + mov edx, eax +.memok: + shr ecx, 3 + mov eax, edx + mov ebx, [esp+4+4] ; folder_data + push ecx +.init_ptr: + mov [eax], ebx + mov [eax+4], eax + add eax, 8 + add ebx, 304 + sub ecx, 1 + jnz .init_ptr + pop ecx + mov ebx, [esp+4+12] ; mode + mov ebx, [compare_fns+ebx*4] + test ebx, ebx + jz .done_free + push esi edi ecx + call sort + pop ecx + mov ebx, edx + sub esp, 304 +.moveloop: + mov esi, [ebx] + test esi, esi + jz .movenext + cmp [ebx+4], ebx + jz .movenext + mov esi, [ebx] + mov edi, esp + push ecx + mov ecx, 304/4 + rep movsd + mov edi, [ebx] + mov eax, [ebx+4] +.z: + mov esi, [eax] + mov dword [eax], 0 + push esi + mov ecx, 304/4 + rep movsd + pop edi + mov eax, [eax+4] + cmp eax, ebx + jnz .z + lea esi, [esp+4] + mov ecx, 304/4 + rep movsd + pop ecx +.movenext: + add ebx, 8 + sub ecx, 1 + jnz .moveloop + add esp, 304 + pop edi esi +.done_free: + cmp edx, ptr_table + jz .done + push 68 + pop eax + push 13 + pop ebx + mov ecx, edx + int 0x40 +.done: + pop ebx + xor eax, eax + ret 12 +.error2: + pop ebx +.error: + push 1 + pop eax + ret 12 + +; ‘®авЁа®ўЄ  qword'®ў ў Є®«ЁзҐб⢥ ecx Ї®  ¤аҐбг edx, дг­ЄжЁп ба ў­Ґ­Ёп ў ebx +; ђ §аги Ґв eax, ecx, esi, edi +sort: +; jecxz .done ; checked by caller + mov eax, ecx +@@: + push eax + call .restore + pop eax + sub eax, 1 + jnz @b +@@: + cmp ecx, 1 + jz .done + mov esi, 1 + mov edi, ecx + call .exchange + dec ecx + mov eax, 1 + call .restore + jmp @b +.done: + ret + +.exchange: + push eax ecx + mov eax, [edx+esi*8-8] + mov ecx, [edx+edi*8-8] + mov [edx+esi*8-8], ecx + mov [edx+edi*8-8], eax + mov eax, [edx+esi*8-4] + mov ecx, [edx+edi*8-4] + mov [edx+esi*8-4], ecx + mov [edx+edi*8-4], eax + pop ecx eax + ret + +.restore: + lea esi, [eax+eax] + cmp esi, ecx + ja .doner + push esi + mov esi, [edx+esi*8-8] + mov edi, [edx+eax*8-8] + call ebx + pop esi + ja .need_xchg + cmp esi, ecx + jae .doner + push esi + mov esi, [edx+esi*8] + mov edi, [edx+eax*8-8] + call ebx + pop esi + jbe .doner +.need_xchg: + cmp esi, ecx + jz .do_xchg + push esi + mov edi, [edx+esi*8-8] + mov esi, [edx+esi*8] + call ebx + pop esi + sbb esi, -1 +.do_xchg: + mov edi, eax + call .exchange + mov eax, esi + jmp .restore +.doner: + ret + +compare_name: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + add esi, 40 + add edi, 40 + jmp strcmpi +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_name_rev: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + add esi, 40 + add edi, 40 + xchg esi, edi + jmp strcmpi +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +strcmpi: + push eax +@@: + lodsb + call match_symbol + jnz .ret + inc edi + test al, al + jnz @b +.ret: + pop eax + ret + +compare_ext: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + add esi, 40 + add edi, 40 + push esi edi + call seek_ext + xchg esi, edi + call seek_ext + xchg esi, edi + call strcmpi + jnz .ret + pop edi esi + jmp strcmpi +.ret: + pop edi esi + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_ext_rev: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + add esi, 40 + add edi, 40 + push esi edi + call seek_ext + xchg esi, edi + call seek_ext + call strcmpi + jnz .ret + pop edi esi + xchg esi, edi + jmp strcmpi +.ret: + pop edi esi + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +seek_ext: + push eax + xor eax, eax +.l: + inc esi + cmp byte [esi-1], '.' + jnz @f + mov eax, esi +@@: + cmp byte [esi-1], 0 + jnz .l + test eax, eax + jnz @f + lea eax, [esi-1] +@@: + mov esi, eax + pop eax + ret + +compare_modified: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + push edi + mov edi, [edi+28] + cmp edi, [esi+28] + pop edi + jnz @f + push edi + mov edi, [edi+24] + cmp edi, [esi+24] + pop edi + jnz @f + add esi, 40 + add edi, 40 + jmp strcmpi +@@: + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_modified_rev: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + push esi + mov esi, [esi+28] + cmp esi, [edi+28] + pop esi + jnz @f + push esi + mov esi, [esi+24] + cmp esi, [edi+24] + pop esi + jnz @f + add esi, 40 + add edi, 40 + xchg esi, edi + jmp strcmpi +@@: + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_size: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + push edi + mov edi, [edi+36] + cmp edi, [esi+36] + pop edi + jnz @f + push edi + mov edi, [edi+32] + cmp edi, [esi+32] + pop edi + jnz @f + add esi, 40 + add edi, 40 + jmp strcmpi +@@: + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_size_rev: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + push esi + mov esi, [esi+36] + cmp esi, [edi+36] + pop esi + jnz @f + push esi + mov esi, [esi+32] + cmp esi, [edi+32] + pop esi + jnz @f + add esi, 40 + add edi, 40 + xchg esi, edi + jmp strcmpi +@@: + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_unordered: + cmp esi, edi + ret +compare_unordered_rev: + cmp edi, esi + ret + +compare_created: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + push edi + mov edi, [edi+12] + cmp edi, [esi+12] + pop edi + jnz @f + push edi + mov edi, [edi+8] + cmp edi, [esi+8] + pop edi + jnz @f + add esi, 40 + add edi, 40 + jmp strcmpi +@@: + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_created_rev: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + push esi + mov esi, [esi+12] + cmp esi, [edi+12] + pop esi + jnz @f + push esi + mov esi, [esi+8] + cmp esi, [edi+8] + pop esi + jnz @f + add esi, 40 + add edi, 40 + xchg esi, edi + jmp strcmpi +@@: + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_accessed: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + push edi + mov edi, [edi+20] + cmp edi, [esi+20] + pop edi + jnz @f + push edi + mov edi, [edi+16] + cmp edi, [esi+16] + pop edi + jnz @f + add esi, 40 + add edi, 40 + jmp strcmpi +@@: + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +compare_accessed_rev: + test byte [esi], 10h + jnz .1dir + test byte [edi], 10h + jnz .greater +.eq1: + push esi + mov esi, [esi+20] + cmp esi, [edi+20] + pop esi + jnz @f + push esi + mov esi, [esi+16] + cmp esi, [edi+16] + pop esi + jnz @f + add esi, 40 + add edi, 40 + xchg esi, edi + jmp strcmpi +@@: + ret +.greater: + test esi, esi + ret +.1dir: + test byte [edi], 10h + jnz .eq1 +.less: + xor edi, edi + stc + ret + +match_symbol: +; in: al,[edi]=symbols +; out: flags as 'cmp al,[edi]' + push eax ecx + movzx ecx, al + mov al, [tolower_table+ecx] + movzx ecx, byte [edi] + cmp al, [tolower_table+ecx] + pop ecx eax + ret + +align 4 +compare_fns dd compare_name + dd compare_name_rev + dd compare_ext + dd compare_ext_rev + dd compare_modified + dd compare_modified_rev + dd compare_size + dd compare_size_rev +; dd compare_unordered +; dd compare_unordered_rev + dd 0 + dd 0 + dd compare_created + dd compare_created_rev + dd compare_accessed + dd compare_accessed_rev +num_compare_fns = ($ - compare_fns) / 4 + +EXPORTS: + dd szStart, START + dd szVersion, 0x00010001 + dd szSortDir, sort_dir + dd szStrcmpi, strcmpi + dd 0 +szStart db 'START',0 +szVersion db 'version',0 +szSortDir db 'SortDir',0 +szStrcmpi db 'strcmpi',0 + +section '.data' data readable writable align 16 +tolower_table rb 256 +; ptr_table must be last variable +ptr_table rb 0x1000 diff --git a/programs/develop/libraries/sorter/sort.txt b/programs/develop/libraries/sorter/sort.txt new file mode 100644 index 0000000000..33f4d6a3fd --- /dev/null +++ b/programs/develop/libraries/sorter/sort.txt @@ -0,0 +1,16 @@ +При загрузке библиотеки нужно вызывать функцию START с параметром DLL_ENTRY = 1. +Рабочая процедура для сортировки папки экспортируется как SortDir и принимает +три параметра, указатель на массив блоков с информацией для файла +(стандартные элементы по 304 байта в формате функции 70), число таких блоков +и тип сортировки: 0=имя,2=расширение,4=время последней модификации,6=размер, +10=время создания,12=время последнего доступа,1,3,5,7,11,13 - сортировка +по соответствующему параметру в обратном порядке. +Например, для сортировки по расширению данных папки, только что прочитанных +функцией 70 в буфер dirdata, можно сделать так: + push 2 ; режим сортировки + push dword [dirdata+4] ; число файлов + ; можно писать push ebx, если + ; дело происходит непосредственно после int 0x40 + push dirdata+32 ; данные файлов + call [SortDir] +; теперь данные в dirdata отсортированы