;/////////////////////////////////////////////////// ; ; DIR. Вывод списка файлов и папок ; ;/////////////////////////////////////////////////// cmd_dir: push de ;;;; [ ] поддержка параметров ; зануляем все параметры на старте xor a ld (read_disk_info.full),a ld (.key_p),a ; выполняем/настраиваем все найденные параметры в строке LD C,256-3 ;!HARDCODE длина строки с командой .parse: ld hl,cmd_dir_options call RUN_OPTION jr nc,.end_opt jp (hl) .end_opt: ; выводим строку о расчёте свободного места так, чтоб она затёрлась ld a,(read_disk_info.full) and a jr z,.skip LD DE,MAIN_MSG.CALCULATING CALL MESSAGE .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 de,work_buffer1 ; 80 ld c,Dss.GSwitch ; выделить параметр ком-строки RST ToDSS ; ld a,(work_buffer1) or a jr nz,1F ; задана маска имен ; ld hl,mask_fname ; "*.*" ld de,work_buffer1 call copy_string ; [ ] 1/10/23 1: 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 ; LD A,32-5 ; количество строк до ожидания клавиши (с вычетом заголовка) ;!HARDCODE PUSH AF ; цикл вывода списка файлов/папок .loop: POP AF .key_p+1: and #ff dec a jr nz,.skip_wait ld de,MAIN_MSG.PAUSE call MESSAGE ; вывести строку ld c,Dss.WaitKey rst ToDSS dec d jr nz,.skip_esc xor a ld (.key_p),a ; отменяем ESC .skip_esc: ld a,32-1 .skip_wait: PUSH AF ; ld hl,work_buffer1+33 ; 80 ;push af ;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 jp nc,.loop ; назад в цикл, если не конец списка ; pop af ; баланс стека ; Десятичный вывод .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,1F ; ld a,"," ; разд. разрядов ; 1: ld (de),a ; inc de ; ldi ; ldi ; ld a,(hl) ; ldi ; cp " " ; jr z,1F ; ld a,"," ; разд. разрядов ; 1: ld (de),a ; inc de ; ldi ; ldi ; ld a,(hl) ; ldi ; cp " " ; jr z,1F ; ld a,"," ; разд. разрядов ; 1: ld (de),a ; inc de ; ldi ; ldi ; ldi ; ret CALL Size2Char ;;;;;;;;;;;;; ; ; [ ] вывод количества папок ; [ ] вывод общего количества свободного места 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 A,(read_disk_info.full) ;OR A ;ld hl,has_not_full_info ;JR Z,.skip_full_space ; ld hl,(free_space) ; мл. разряд exx ld hl,(free_space+2) ; ст. разряд exx CALL Size2Char ld hl,T8B46 ; "0 000 000 000" ; ;.skip_full_space: ld de,PRM4 ; куда call ncopy_string ; скопир. строку (с нулем), макс.15 симв. ; ; ld de,MAIN_MSG.DIR_2 ; индекс " %1 file(s) %2 bytes" CALL MESSAGE ; вывести строку ld a,(read_disk_info.full) and a ld de,MAIN_MSG.DIR_4 ; jp nz,MESSAGE ld de,MAIN_MSG.CRLF ; jp MESSAGE .Print_Header: ; %1 ld hl,PRM1 ld a,'"' ld (hl),a inc hl ld a,(screen_path) ; диск ld (hl),a inc hl ld a,'"' ld (hl),a inc hl ;ld (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..." 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 free_space: dword 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 EX AF,AF' LD A,(.full) OR A JR Z,.no_full_space_option ; ; (DE*A)*BC ;PUSH HL ; общее кол-во кластеров ;PUSH DE ; свободных кластеров PUSH BC ; размер сектора в байтах EX AF,AF' LD C,A ; A - размер кластера в секторах CALL Mult16X8 ; A:HL = DE*A ; EX DE,HL LD H,0 LD L,A POP BC CALL Mult32 LD (free_space+2),HL EX DE,HL LD (free_space),HL ; ; .no_full_space_option: ; 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 ; лишнее ; есть метка 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 ; has_not_full_info: ; db ' (?)',0 ; cmd_dir_options: ; [ ] параметр /F - вывод количества свободного места на диске (тормозит, поэтому параметром) DB 'f' : DW cmd_dir_freeSpace DB 'p' : DW cmd_dir_pause .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 ; cmd_dir_pause: ld a,#ff ld (cmd_dir.key_p),a jp cmd_dir.parse /////////////////////////////////////////////////////////////////////////////////////// Size2Char: 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,1F ld a,"," ; разд. разрядов 1: ld (de),a inc de ldi ldi ld a,(hl) ldi cp " " jr z,1F ld a,"," ; разд. разрядов 1: ld (de),a inc de ldi ldi ld a,(hl) ldi cp " " jr z,1F ld a,"," ; разд. разрядов 1: ld (de),a inc de ldi ldi ldi ret /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// ;----------------------------------------------------------------------; ;Процедура умножения (16*8bit) ;На вход: DE*C ;На выход:A+HL-результат Mult16X8: SUB A LD L,A LD H,A CP C RET Z OR D OR E RET Z LD A,C LD C,#00 LD B,#08 Mlt16x8: ADD HL,HL RLA JR NC,1F ADD HL,DE ADC A,C 1: DJNZ Mlt16x8 RET ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ;Процедура умножения (32bit) ;На вход: HL+DE*BC ;На выход:HL+DE-результат Mult32: PUSH IX LD IX,#0000 LD A,#20 EX DE,HL mul32b: ADD IX,IX ADC HL,HL RL E RL D JR NC,noadd1 ADD IX,BC JR NC,noadd1 INC HL noadd1: DEC A JR NZ,mul32b LD E,LX LD D,HX POP IX RET ;----------------------------------------------------------------------; ///////////////////////////////////////////////////////////////////////////////////////