; ; Shell-Metzner алгоритм сортировки ; ;------------------------------------------------- ; Сортировка списка панели (вызов из оболочки) ; вход: c = буква сортировки (n/x/d/s/u) ;------------------------------------------------- sorting_list: call test_show_panels ; тест на режим вкл. панелей ret z ; выкл. ld hl,(all_files) ; число файлов и папок ld a,l or h ret z ld a,(format_mode) ; фомат акт. панели and form_trd ; trd/scl spectrum ret nz ld hl,(sort_type) ; тип сорт. акт. панели ld a,h xor 1 ; инверсия сортировки ld h,a ld a,l cp c ; новый = старому ? jr z,$+4 ; инверсия режима сортировки ld h,0 ; сбр. сортировку в "" ld l,c ld (sort_type),hl call sorting ; раздельный список указателей + сорт. списка jp A20FC ; обновить список ;----------------------------------------------------------- ; Создание раздельного списка указателей и сортировка ; списков папок и файлов. ; ; вход: de=кол-во записей списка ;----------------------------------------------------------- sorting:ld de,(all_files) ; число файлов и папок ld a,e or d ret z call make_array_pointer ; создать раздельный список указателей ld hl,sort_type+1 ld a,(hl) ; 00/01 / or a ld a,0D2h ; "jp nc,.." jr z,$+4 ld a,0DAh ; "jp c,.." ld (sort_mode),a ; / сортировка dec hl ld a,(hl) ; hl=sort_type cp "n" ; name jr z,sort_name cp "x" ; extension jr z,sort_ext cp "d" ; date jr z,sort_date cp "s" ; size jr z,sort_size jr unsorted_list ; создать общий список указателей ; Сортировка папок sort_folders: ld de,(all_folders) ; число папок в списке ld hl,(directory) ; начало списка указателей папок ld c,(hl) inc hl ld b,(hl) dec hl ld a,(bc) ;+0 имя файла cp "." ; ".." первая запись ? jr nz,$+5 ; нет dec de ; --число папок inc hl ; на след. указатель inc hl jp metzner_sort ; Ctrl+F3. Сортировка по имени sort_name: ld hl,cmp_names ; процедура сравнения sort__: ld (sort_func+1),hl call sort_folders ; сортировка папок ld hl,(all_files) ; число записей списка ld de,(all_folders) ; число папок списка and a sbc hl,de ex de,hl ; de=число файлов в списке ld hl,(directory+2) ; начало списка указателей файлов jp metzner_sort ; сортировка ; Ctrl+F4. Сортировка по расширению sort_ext: ld hl,cmp_extensions ; процедура сравнения jr sort__ ; Ctrl+F5. Сортировка по дате sort_date: ld hl,cmp_date ; процедура сравнения jr sort__ ; Ctrl+F6. Сортировка по размеру sort_size: ld hl,cmp_size ; процедура сравнения jr sort__ ; Ctrl+F7. Без сортировки. unsorted_list: ld a,(cash_left_dir) ; банка каталога акт. панели out (SLOT3),a ; подкл. страницу каталога ld iy,0C000h ; начало сканируемой папки ld hl,(directory) ; начало буфера списка адресов ld bc,32 ; ms-dos запись ld a,(format_mode) ; формат акт. панели and form_trd ; trd/scl spectrum jr z,$+5 unsorted_spec: ; <- переход из "make_array_pointer" ld bc,16 ; spec-запись ; создать общ. список указателей ld de,(all_files) ; число файлов и папок в списке unsorted_loop: db 0FDh ld a,l ld (hl),a inc hl db 0FDh ld a,h ld (hl),a inc hl add iy,bc ; на след. запись dec de ld a,e or d jp nz,unsorted_loop ret ;----------------------------------------------------------- ; Создание массива указателей на записи списка ; ; вход: de = кол-во записей списка ; выход: directory+2 - содержит начало списка файлов ; all_folders - содержит число папок в списке ; NZ - спек-список ;----------------------------------------------------------- make_array_pointer: ld iy,0C000h ; начало сканируемого каталога ld a,(cash_left_dir) ; банка каталога акт. панели out (SLOT3),a ; подкл. страницу каталога ld hl,(directory) ; начало списка указателей ld a,(format_mode) ; формат акт. панели and form_trd ; trd/scl spectrum jr z,make_msdos_list ; спек-список ld a,"u" ld (sort_type),a ; уст. режим "unsort" ld bc,0 ld (all_folders),bc ; число папок в списке ld (directory+2),hl ; начало списка файлов jr unsorted_spec ; создать общ. список указателей ; создать раздельный список указателей make_msdos_list: exx ld bc,32 ; ms-dos запись exx ; создать указатели на папки ld a,0CAh ; "jp z," call make_flist1__ ; создать список папок ld (all_folders),bc ; число папок в списке ld (directory+2),hl ; начало списка файлов ; создать указатели на файлы ld iy,0C000h ; начало сканируемого каталога ld de,(all_files) ; число файлов и папок ld a,0C2h ; "jp nz," ; make_flist1__: ld (make_flist_code),a ld bc,0 ; счетчик числа папок/файлов make_flist_loop: bit 4,(iy+11) ;+11 атрибут файла make_flist_code: jp z,make_flist_next db 0FDh ld a,l ld (hl),a inc hl db 0FDh ld a,h ld (hl),a inc hl inc bc ; ++число папок/файлов make_flist_next: exx add iy,bc ; на след. ms-dos запись exx dec de ld a,e or d jp nz,make_flist_loop ret ;------------------------------------------------- ; Сортировка списка. Shell-Metzner алгоритм. ; Работает с указателями на записи. ; ; вход: hl=адрес массива указателей ; de=кол-во записей в списке ;------------------------------------------------- metzner_sort: ld (sort_base+1),hl ; адрес массива ld (sort_count+1),de ; кол-во элементов (не изм.) ld (sort_count1),de ; (счетчик) ; разделить тек. число элементов на 2 sort_divide: db 21h ; ld hl,.. sort_count1: dw 0 ; тек. кол-во элементов / 2 and a ld a,h rra ld h,a ld a,l rra ld l,a ld a,l or h ret z ; все элементы отсортированы ld (sort_count1),hl ;6,3,1,0 тек. кол-во элементов / 2 ex de,hl sort_count: ld hl,0 ;12 (count) кол-во элементов and a sbc hl,de ; sreclen = sort_count - sort_count1 ld (sreclen+1),hl ;6,9,11 ld hl,1 ld (sortv1),hl ld (sstadr),hl dec l add hl,de add hl,de ld (sortv2),hl ;+42,+21,+0B смещ. до середины тек. массива ex de,hl sort_base: ld hl,0 ; начало массива ; sort_ndone: ld (sortv4),hl ; адрес след. записи 1-й половины массива  ld (sortv3),hl ex de,hl add hl,de ; смещ.до середины массива + адрес след. записи ex de,hl ; de=адрес след. записи 2-й половины массива  sort_compre: ld (srtptr2+1),de ld (srtptr1+1),hl ; разадресация de и hl ld a,(de) ld c,a inc de ld a,(de) ld d,a ld e,c ld a,(hl) inc hl ld h,(hl) ld l,a ld (srtptr3+1),hl ld (srtptr4+1),de ; sort_func: call cmp_extensions ; тек. п/п сортировки jp z,noswap_items ; элементы равны sort_mode: jp nc,noswap_items ; nc/c тип / сортировки ; обменять адреса указателей srtptr2:ld de,0 ; адрес записи 2-й половины списка srtptr1:ld hl,0 ; адрес записи 1-й половины списка ld a,(de) ld c,a ld a,(hl) ld (de),a ld (hl),c inc de inc hl ld a,(de) ld c,a ld a,(hl) ld (de),a ld (hl),c ; ld hl,(sort_count1) ;6,3,1 тек. кол-во элементов / 2 ld a,h cpl ld d,a ld a,l cpl ld e,a db 21h ; ld hl,.. sortv1: dw 0 add hl,de ;-7, -4, -2 jp nc,noswap_items inc hl ld (sortv1),hl ; порядк. номера записей db 11h ; ld de,.. sortv3: dw 0 ; тек. запись 1-й половины массива ld hl,(sortv2) ;+42,+21,+0B смещ. до середины тек. массива ld a,e sub l ld l,a ld a,d sbc a,h ld h,a ld (sortv3),hl ; адреса записей jp sort_compre ; сравнить элементы (de и hl) ; noswap_items: db 21h ; ld hl,.. sstadr: dw 0 ; от 1 inc hl ; ++incr ld (sstadr),hl ; ld (sortv1),hl ex de,hl sreclen:ld hl,0 ;6,9,11 (sreclen) длина элемента and a sbc hl,de ; cmp sreclen и incr jp c,sort_divide db 21h sortv4: dw 0 ; адрес след. записи 1-й половины массива inc hl ; на след. указатель inc hl db 11h ; ld de,.. sortv2: dw 0 ;+42,+21,+0B смещ. до середины тек. массива jp sort_ndone ;------------------------------------------------- ; Сравнить имена ; ; in: hl=адрес записи 1-й половины массива ; de=адрес записи 2-й половины массива ; out: z - равны ; nz - не равны ;------------------------------------------------- cmp_names: ld b,11 ; полное имя srtptr3:ld hl,0 srtptr4:ld de,0 cmp__: ld a,(de) ; 2-я половина массива cp "_" jp z,cmp1__ or 00100000b cp "Ё" ; 240 jp nz,cmp1__ inc a ; 241 = "ё" cmp1__: ld c,(hl) ; 1-я половина массива cp "_" jp z,cmp2__ set 5,c cp "Ё" ; 240 jp nz,cmp2__ inc c ; 241 = "ё" cmp2__: sub c ret nz ; элементы не равны inc hl inc de djnz cmp__ ret ;------------------------------------------------- ; Сравнить расширения ; ; in: hl=адрес записи 1-й половины массива ; de=адрес записи 2-й половины массива ; out: z - равны ; nz - не равны ;------------------------------------------------- cmp_extensions: ld bc,8 ; смещ. до элем. сравнения ex de,hl add hl,bc ; смещ. до ячеек сравнения ex de,hl add hl,bc ; смещ. до ячеек сравнения ld b,3 ; длина элем. сравнения ecmp__: ld a,(de) ; 2-я половина массива cp "_" jp z,ecmp1__ or 00100000b cp "Ё" ; 240 jp nz,ecmp1__ inc a ; 241 = "ё" ecmp1__:ld c,(hl) ; 1-я половина массива cp "_" jp z,ecmp2__ set 5,c cp "Ё" ; 240 jp nz,ecmp2__ inc c ; 241 = "ё" ecmp2__:sub c ret nz ; элементы не равны inc hl inc de djnz ecmp__ ; элементы совпадают ld b,8 ; длина элем. сравнения jp srtptr3 ; сравнить имена ;------------------------------------------------- ; Сравнить даты/размеры ; ; in: hl=адрес конца записи (1-я половина массива) ; de=адрес конца записи (2-я половина массива) ; out: z - равны ; nz - не равны ;------------------------------------------------- cmp_date: ld bc,25 ; смещ. на конец даты jp $+6 cmp_size: ld bc,31 ; смещ. на конец размера ex de,hl add hl,bc ; + смещ. до ячеек сравнения ex de,hl add hl,bc ; + смещ. до ячеек сравнения ld b,4 ; длина элем. сравнения ld a,(de) ; 2-я половина массива sub (hl) ; 1-я половина массива ret nz ; элементы не равны dec hl dec de djnz $-5 ; элементы совпадают jp cmp_names ; сравнить имена