;/////////////////////////////////////////////////// ; ; DIR. Вывод списка файлов и папок ; ;/////////////////////////////////////////////////// cmd_dir: push de ;;;; [ ] поддержка параметров ; зануляем все параметры на старте xor a ld (read_disk_info.full),a ; выполняем/настраиваем все найденные параметры в строке ld hl,cmd_dir_options LD C,256-3 ;!HARDCODE длина строки с командой .parse: call RUN_OPTION jr nc,.skip jp (hl) ; .skip: ld c,Dss.CurDisk ; узнать тек. диск RST ToDSS ADD A,"A" ld (root_path),a ; номер диска SUB "A" call read_disk_info ; прочитать метку и серийный номер диска ; pop de ld hl,0 ld (D88DC),hl ld (D88DE),hl ld (D88E0),hl ld (dir_number),hl ex de,hl ld a,(hl) or a jr nz,1F ; задана маска имен ld hl,mask_fname ; "*.*" ;ld de,T9186 ; буфер 1: ld de,work_buffer1 ; 80 ld c,Dss.GSwitch ; выделить параметр ком-строки RST ToDSS ; [ ] 1/10/23 ld hl,work_buffer1 ; имя файла ld de,work_buffer1 ; 80 буфер ld a,#37 ; атрибут (все, кроме метки тома) ld bc,0*256 + Dss.F_First ; f_first (формат 11) RST ToDSS JR C,.dir_empty ;R14 CALL .Print_Header ; цикл вывода списка файлов/папок .loop: ld hl,work_buffer1 ; 80 ld de,33 add hl,de call A88E2 ld ix,work_buffer1 ; 80 ld a,(ix+32) ; атрибут тек. записи and FAT_ATTR.DIRECTORY ; папка ? jr z,.calc_size ; нет ; считаем папки ; не считаем папкой служебные "." и ".." ld d,(ix+33) ld e,(ix+34) ld hl,-('..') add hl,de ld a,h or l jr z,.next ld hl,-('. ') add hl,de ld a,h or l jr z,.next ; увеличиваем счётчик папок ld hl,(dir_number) inc hl ld (dir_number),hl jr .next ;;R14 .dir_empty: push af CALL .Print_Header pop af CALL print_err_message jr .print ;;R14 ; прибавить размер тек. файла .calc_size: ld hl,(D88DC) inc hl ld (D88DC),hl ld e,(ix+30) ld d,(ix+31) ld hl,(D88E0) exx ld e,(ix+28) ld d,(ix+29) ld hl,(D88DE) add hl,de exx adc hl,de exx ld (D88DE),hl exx ld (D88E0),hl .next: ld de,work_buffer1 ; 80 буфер ld c,Dss.F_Next ; поиск след. RST ToDSS jr nc,.loop ; назад в цикл, если не конец списка ; Десятичный вывод .print: ld hl,(D88DC) ld ix,PRM1 ; буфер call A8964 ld hl,(D88DE) ; мл. разряд exx ld hl,(D88E0) ; ст. разряд exx call A8A8F ; десятичный 32-х разрядный вывод ld hl,T8B37 ; "0" ld a,(hl) cp " " jr nz,.not_zero ld a,"0" ld (hl),a .not_zero: ld de,T8B46 ; "0 000 000 000" ld hl,T8B2E ; "0000000000" ld a,(hl) ldi cp " " jr z,$+4 ld a,"," ; разд. разрядов ld (de),a inc de ldi ldi ld a,(hl) ldi cp " " jr z,$+4 ld a,"," ; разд. разрядов ld (de),a inc de ldi ldi ld a,(hl) ldi cp " " jr z,$+4 ld a,"," ; разд. разрядов ld (de),a inc de ldi ldi ldi ; [ ] вывод количества папок ; [ ] вывод общего количества свободного места ld hl,T8B46 ; "0 000 000 000" ld de,PRM2 ; куда call ncopy_string ; скопир. строку (с нулем), макс.15 симв. ; ;!TEST ;ld hl,(dir_number) ;ld de,PRM3 ;call hex2dec_ascii_16bit.n10000 ; Десятичный вывод ld hl,(dir_number) ld ix,PRM3 ; буфер call A8964 ;xor a ;ld (de),a ; ld de,MAIN_MSG.DIR_2 ; индекс " %1 file(s) %2 bytes" jp MESSAGE ; вывести строку .Print_Header: ; %1 ld a,(screen_path) ; диск ld hl,PRM1 ld (hl),a inc hl ld (hl),":" inc hl ld (hl),0 ; %2 ld hl,serial_string ; строка серийного номера диска ld de,PRM2 ; куда call ncopy_string ; скопир. строку (с нулем) ; %3 ld hl,screen_path ld de,PRM3 ; 16 буфер CALL copy_string ; скопир. строку (с нулем) ; ld de,MAIN_MSG.DIR_1 ; индекс "Volume in drive %1..." ;!HARDCODE номер строки MSG0 JP MESSAGE ; вывести строку ; ; Подготовить строку списка файлов/папок A88E2: ld bc,8 ld de,PRM1 ; буфер ldir xor a ld (de),a ld de,PRM2 ; куда ldi ldi ldi ld (de),a ld ix,work_buffer1 call A89A4 ; вывести в буфер имя файла и его размер (у папки ) call A89FA ; вывести в буфер дату файла/папки call A8A19 ; вывести в буфер время файла/папки ld de,MAIN_MSG.DIR_3 ; индекс "%1 %2 %3 %4 %5" jp MESSAGE ; вывод строки ; Вывести в буфер имя файла и его размер (у папки ) A89A4: ld a,(ix+32) ld hl,T8B38 ; " " and 10h ; папка ? jr nz,A89F4 ; да ld l,(ix+28) ; мл. разряд ld h,(ix+29) exx ld l,(ix+30) ; ст. разряд ld h,(ix+31) exx push ix call A8A8F ; десятичный 32-х разрядный вывод ld hl,T8B37 ld a,(hl) cp " " jr nz,A89CD ld a,"0" ld (hl),a A89CD: ld de,T8B46 ; "0 000 000 000" ld hl,T8B2E ; "0000000000" ldi ld a," " ld (de),a inc de ldi ldi ldi ld (de),a inc de ldi ldi ldi ld (de),a inc de ldi ldi ldi ld hl,T8B46 ; "0 000 000 000" pop ix A89F4: ld de,PRM3 ; 16 буфер jp ncopy_string ; скопир. строку (с нулем), макс.15 симв. ; Скопировать в буфер дату файла/папки A89FA: ld b,(ix+25) ld c,(ix+24) ld hl,T8B46 ; "0 000 000 000" call A8A53 ; вывод в буфер даты ld (hl),0 ld hl,T8B46 ; "0 000 000 000" ld de,PRM4 ; 16 куда ld a,(hl) cp "0" jr nz,$+4 ld (hl)," " jp ncopy_string ; скопир. строку (с нулем), макс.15 симв. ; Скопировать в буфер время файла/папки A8A19: ld b,(ix+22) ld c,(ix+23) ld hl,T8B46 ; "0 000 000 000" call A8A38 ; скопир. в буфер время файла/папки ld (hl),0 ld hl,T8B46 ; "0 000 000 000" ld de,PRM5 ; 80 буфер строки ld a,(hl) cp "0" jr nz,$+4 ld (hl)," " jp ncopy_string ; скопир. строку (с нулем), макс.15 симв. ; в буфер время файла/папки A8A38: srl c rr b srl c rr b srl c rr b srl b srl b ld a,c call A8A7E ld (hl),":" ; раздел. времени inc hl ld a,b jr A8A7E ; в буфер дату файла/папки A8A53: ld a,c and 1Fh push bc call A8A7E ld (hl),"." ; раздел. даты inc hl pop bc ld a,c srl b rla rla rla rla and 0Fh call A8A7E ld (hl),"." ; раздел. даты inc hl ld a,b add a,80 cp 100 jr c,A8A7E A8A75: sub 100 cp 100 jr nc,A8A75 A8A7E: ld c,2Fh inc c sub 10 jr nc,$-3 add a,10 add a,"0" ld (hl),c inc hl ld (hl),a inc hl ret ;!TODO перетащить в procedures/math.asm ; Десятичный 32-х разрядный вывод A8A8F: ld ix,T8B2E ; "0000000000" exx ld de,3B9Ah exx ld de,0CA00h call A8B15 ; 1,000,000,000 exx ld de,05F5h exx ld de,0E100h call A8B15 ; 100,000,000...999,999,999 exx ld de,98h exx ld de,9680h call A8B15 ; 10,000,000...99,999,999 exx ld de,0Fh exx ld de,4240h call A8B15 ; 1,000,000...9,999,999 exx ld de,1 exx ld de,86A0h call A8B15 ; 100,000...999,999 exx ld de,0 exx ld de,10000 call A8B15 ; 10,000...99,999 exx ld de,0 exx ld de,1000 call A8B15 ; 1,000...9,999 exx ld de,0 exx ld de,100 call A8B15 ; 100..999 exx ld de,0 exx ld de,10 call A8B15 ; 10..99 ld a,l add a,"0" ld (ix+0),a inc ix ld hl,T8B2E ; "0000000000" ld de,2030h ; " ","0" A8B04: ld a,(hl) cp e jr nz,A8B0D ld (hl),d inc hl jr A8B04 ; A8B0D: ld hl,T8B37 ; "0" ld a,(hl) cp d ret nz ld (hl),e ret A8B15: xor a A8B16: inc a sbc hl,de exx sbc hl,de exx jp nc,A8B16 add hl,de exx adc hl,de exx dec a add a,"0" ld (ix+0),a inc ix ret ; D88DC: dw 0 D88DE: dw 0 D88E0: dw 0 dir_number: dw 0 ; T8B2E: db "000000000" T8B37: db "0" T8B38: db " ",0 T8B46: db "0 000 000 000",0 db 0 ; ; [ ] теперь не лезет напрямую, делает через новый параметр функции DskInfo ; иная логика получения метки тома - сначала ищется в корневой директории, ; если там нет, то берётся из BPB read_disk_info: OR #80 LD HL,work_buffer .full+1: LD B,0 LD C,Dss.DskInfo RST ToDSS ; Файловая система ; Серийный номер диска ; Метка диска в BPB ; parse LD D,0 LD HL,work_buffer ; тут в HL длина поля "Файловая система" LD E,(HL) ADD HL,DE INC HL ; длина поля "Серийный номер диска" LD A,(HL) LD E,A ADD HL,DE INC HL PUSH HL ; указатель на длину поля "Метка диска" CP 4 ;!HARDCODE длина поля серийного номера JR NZ,unknown_serial DEC HL ; старшее слово серийника LD D,(HL) DEC HL LD E,(HL) DEC HL PUSH HL EX DE,HL ld de,serial_string ; xxxx-xxxx call hex16 POP HL ; ld a,"-" ld (de),a INC DE ; младшее слово серийника LD A,(HL) DEC HL LD L,(HL) LD H,A call hex16 ; ; Метка диска ; ld a,(disk) ; номер диска ; cp 2 ; меньше "C:" ? ; jr nc,get_inf_data1 ; метка в BPB .get_label: ; ищем метку в корне ФС раздела ; уст. корень диска ld hl,root_path ; "x:\",0 ld c,Dss.ChDir RST ToDSS ; поиск метки ld hl,mask_fname ; "*.*" имя метки ld de,work_buffer1 ; куда ld a,FAT_ATTR.VOLUME_ID ; атрибут метки тома ld bc,0*256 + Dss.F_First ; f_first, формат 11 RST ToDSS push af call restore_path ; восст. тек. путь pop af ;jr c,no_volume_label ; метки нет дирректории ld hl,work_buffer1+33 ; начало метки в буфере f_first jr nc,volume_label ; метка в корневом каталоге ; берём метку из BPB ; тут в HL длина поля "Метка диска" POP hl LD A,(HL) INC HL AND A jr z,.no_volume_label ; да PUSH HL LD B,A LD A,' ' ; .loop: CP (HL) JR NZ,.good_label INC HL DJNZ .loop POP HL ; снимаем лишнее ; нет метки .no_volume_label: ; %4 ld hl,volume_string_no ; строка ld de,PRM4 ; куда call ncopy_string ; скопир. строку (с нулем) XOR A LD (PRM5),A ret .good_label: POP HL PUSH HL ; лишнее ;!FIXIT сделать через аргументы %1-%9 ; есть метка volume_label: pop DE ; лишнее ; %5 ld de,PRM5 ld bc,11 ;!HARDCODE длина метки ldir xor a ld (de),a ; %4 ld hl,volume_string_yes ; строка ld de,PRM4 ; куда call ncopy_string ; скопир. строку (с нулем) ret ; ; если не удалось прочитать серийный номер диска или формат неизвестен unknown_serial: ; серийный номер диска - неизвестен ;!HARDCODE ниже LD HL,serial_string LD A,'?' LD B,serial_string.Size .loop: LD (HL),A INC HL DJNZ .loop LD HL,serial_string+4 LD (HL),'-' ;POP HL ; лишнее JP read_disk_info.get_label ; ; маска файлов mask_fname: db "*.*",0 ; корень диска root_path: db 'X:\',0 ; Серийный номер диска serial_string: db "xxxx-xxxx" .Size equ $-serial_string db 0 ; закрывашка volume_string_no: db "has no label",0 volume_string_yes: db "has label",0 ; cmd_dir_options: ; [ ] параметр /F - вывод количества свободного места на диске (тормозит, поэтому параметром) DB 'f' : DW cmd_dir_freeSpace .Size EQU ($-cmd_dir_options)/3 .paramLength equ 3 ; ; cmd_dir_freeSpace: PUSH DE PUSH BC ; затираем найденый ключ ld A,'/' ex de,hl ld bc,4 CPDR inc hl ld (hl),' ' inc hl ld (hl),' ' ; ставим опцию для API DSS DskInfo ld a,1 ld (read_disk_info.full),a ; выводим строку о расчёте свободного места так, чтоб она затёрлась LD DE,MAIN_MSG.CALCULATING CALL MESSAGE ; возвращаемся в цикл POP BC POP DE jp cmd_dir.parse ;