;/////////////////////////////////////////////////// ; ; DIR. Вывод списка файлов и папок ;/////////////////////////////////////////////////// cmd_dir: push de ;;;; [ ] поддержка параметров ; зануляем все параметры на старте xor a ld (Buffers.work.buffer2),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 ECHO_MESSAGE ; 23/05/24 .skip: ;LD C,Dss.CurDisk ; узнать тек. диск ;RST ToDSS ;CALL read_disk_info ; прочитать метку и серийный номер диска ; pop de xor a ld h,a ld l,a ld (FILES),hl ld (dir_number),hl ld (S_LOW),hl ld (S_MED),hl ld (S_HIGH),a ; ex de,hl ld de,Buffers.work.buffer1 ld c,Dss.GSwitch ; выделить параметр ком-строки RST ToDSS ; ld a,(Buffers.work.buffer1) or a ;jr nz,.SkipMask ; задана маска имён jr z,.NoSkipMask ; не задана маска имён ld hl,Buffers.work.buffer1 ld bc,Dss.EX_Path.GET_ALL rst ToDSS ; and %00001100 ; имя диска и путь jr z,.SkipMask ; ld hl,Buffers.work.buffer2+2 ld c,Dss.CurDir rst ToDSS ld c,Dss.CurDisk rst ToDSS add a,"A" ld (Buffers.work.buffer2),a ld a,":" ld (Buffers.work.buffer2+1),a ; xor a ld hl,Buffers.work.buffer1 ld bc,256 cpir ;!FIXIT проверка на ошибку по флагу P/V dec hl ex de,hl ld hl,256-1 and a sbc hl,bc ld b,h ld c,l ld a,'\' ; ex de,hl cpdr ;!FIXIT проверка на ошибку по флагу P/V inc hl ld (hl),0 inc hl ld de,Buffers.bat_params.PRM1 call ncopy_string ; сохраняем маску файла ; ld hl,Buffers.work.buffer1 ld c,Dss.ChDir rst ToDSS jr nc,.no_error ; cp DSS_Error.sys.MEDIA_CHANGED jp nz,print_err_message call print_err_message ; ld hl,Buffers.work.buffer1 ld c,Dss.ChDir rst ToDSS jp c,print_err_message .no_error: ; ld hl,Buffers.bat_params.PRM1 ld de,Buffers.work.free call ncopy_string ; восстанавливаем маску файла ; ld a,(Buffers.bat_params.PRM1) or a jr nz,.SkipMask ; ; добавление маски .NoSkipMask: ld hl,mask_fname ; "*.*" ld de,Buffers.work.free call copy_string ; 23/05/24 .SkipMask: LD C,Dss.CurDisk ; узнать тек. диск RST ToDSS CALL read_disk_info ; прочитать метку и серийный номер диска JR NC,.NeXt ; CALL print_err_message SCF RET ; .NeXt: CALL Print_Header ; [ ] 01/10/23 ld hl,Buffers.work.free ; имя файла ld de,Buffers.work.buffer1 ; 80 буфер ld a,FAT_ATTR.NoVolID ; атрибут (все, кроме метки тома) ld bc,Dss.F_First.FATname ; f_first (формат 11) RST ToDSS JR C,.Dir_Empty ;R14 ; 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.DIRPAUSE call ECHO_MESSAGE ; вывести строку ld c,Dss.WaitKey rst ToDSS PUSH DE ld de,MAIN_MSG.CLSLINE call ECHO_MESSAGE POP DE dec d ld de,MAIN_MSG.DIR_ESCAPE jp z,ECHO_MESSAGE ; закончить по ESC ;jr nz,.skip_esc ;xor a ;ld (.key_p),a ; отменяем ESC .skip_esc: ld a,32-1 .skip_wait: PUSH AF ld hl,Buffers.work.buffer1+33 ; 80 ;push af ;ld de,33 ;add hl,de call PRNNAME ; ld ix,Buffers.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,(FILES) inc hl ld (FILES),hl ld e,(ix+FAT_DIRECTORY_RECORD.F_SIZE+2) ld d,(ix+FAT_DIRECTORY_RECORD.F_SIZE+3) ld hl,(S_MED) ld a,(S_HIGH) exx ld e,(ix+FAT_DIRECTORY_RECORD.F_SIZE) ld d,(ix+FAT_DIRECTORY_RECORD.F_SIZE+1) ld hl,(S_LOW) add hl,de ld (S_LOW),hl exx adc hl,de ld (S_MED),hl ;exx adc a,0 ld (S_HIGH),a ;exx .next: ld de,Buffers.work.buffer1 ; 80 буфер ld c,Dss.F_Next ; поиск след. RST ToDSS jp nc,.loop ; назад в цикл, если не конец списка pop af ; баланс стека ; Десятичный вывод .print: ld hl,(FILES) ld ix,Buffers.bat_params.PRM3; количество файлов call PDIGIT ; ld a,(S_HIGH) ld hl,(S_MED) ; ст. разряд exx ld hl,(S_LOW) ; мл. разряд ;exx ; ;CALL PRINT_DWORD CALL PRINT_5BYTES ; ; [x] вывод количества папок ; [x] вывод общего количества свободного места ld hl,SIZE_BUFFER.high ; "000 000 000 000" ld de,Buffers.bat_params.PRM1; + PRM2. размер файлов в каталоге ld bc,SIZE_BUFFER.bytes call ncopy_string.start ; скопир. строку (с нулем), макс. SIZE_BUFFER.bytes симв. ; ; Десятичный вывод ld hl,(dir_number) ld ix,Buffers.bat_params.PRM4; кол-во каталогов в каталоге call PDIGIT ; full capacity ld a,(full_space_high) ld hl,(full_space_medium) ; ст. разряд exx ld hl,(full_space_low) ; мл. разряд CALL PRN_DISK_SIZE ; ; ld de,MAIN_MSG.DIR_2 ; индекс " %1 file(s), %2 bytes, %3 Dir(s)" CALL ECHO_MESSAGE ; вывести строку ; ; [ ] 23/05/2024 ld hl,Buffers.work.buffer2 ld c,Dss.ChDir ld a,(hl) or a call nz,ToDSS ; ld a,(read_disk_info.LastDskInfoIsFull) and a RET Z ; ; free space ld a,(free_space_high) ld hl,(free_space_medium) ; ст. разряд exx ld hl,(free_space_low) ; мл. разряд ; CALL PRN_DISK_SIZE ; ld de,MAIN_MSG.DIR_4 ; индекс " %6 bytes free" jp ECHO_MESSAGE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PRN_DISK_SIZE: call PRINT_5BYTES ld hl,SIZE_BUFFER.high ; "000 000 000 000" ld de,Buffers.bat_params.PRM5; and PRM6. куда ld bc,SIZE_BUFFER.bytes jp ncopy_string.start ; скопир. строку (с нулем), макс. SIZE_BUFFER.bytes симв. ; Print_Header: ; %1 ld hl,Buffers.bat_params.PRM1 ld a,'"' ld (hl),a inc hl push hl ; ld c,Dss.CurDisk rst ToDSS add a,"A" ; pop hl ld (hl),a inc hl ld a,'"' ld (hl),a inc hl ;ld (hl),":" ld (hl),0 ; %2 ld hl,serial_string ; строка серийного номера диска ld de,Buffers.bat_params.PRM2; куда call ncopy_string ; скопир. строку (с нулем) ; %3..5 ;push hl ld hl,Buffers.work.free + 256 + 128 ; 128 - на всякий случай ld c,Dss.CurDir rst ToDSS ld hl,Buffers.bat_params.PRM3 ld a,(Buffers.bat_params.PRM1 + 1) ld (hl),a inc hl ld (hl),':' ; ld hl,Buffers.bat_params.PRM3 +2 ld de,Buffers.bat_params.PRM3 +2 + 1 ld (hl),0 ld bc,16+16+16-1-2 ldir ; ld hl,Buffers.work.free + 256 + 128; сист. путь ld de,Buffers.bat_params.PRM3 + 2 ;+PRM4..5. 2 + 48 байтов буфер call make_short_path ld de,MAIN_MSG.DIR_1 ; индекс "Volume in drive %1..." JP ECHO_MESSAGE ; вывести строку ; ; Подготовить строку списка файлов/папок PRNNAME: dec hl ld a,(hl) and FAT_ATTR.DIRECTORY call z,.set_small inc hl ; ld bc,8 ld de,Buffers.bat_params.PRM1 ldir xor a ld (de),a ld de,Buffers.bat_params.PRM2; куда ldi ldi ldi ld (de),a ld ix,Buffers.work.buffer1 call PRNSIZE ; вывести в буфер имя файла и его размер (у папки ) call PRNDATE ; вывести в буфер дату файла/папки call PRNTIME ; вывести в буфер время файла/папки ld de,MAIN_MSG.DIR_3 ; индекс "%1 %2 %3 %4 %5" jp ECHO_MESSAGE ; вывод строки ; .set_small: ld d,h ld e,l ld b,11 ;!HARDCODE длина имени DOS .loop: inc hl ld a,(hl) cp 'A' jr c,.next cp 'Z'+1 jr c,.letter ; cp 'А' ;#80 jr c,.next cp 'Я'+1 ;#9F + 1 jr nc,.next ; .letter: or %0010'0000 ld (hl),a .next: djnz .loop ex de,hl ret ; Вывести в буфер имя файла и его размер (у папки ) PRNSIZE: ld a,(ix+32) ld hl,DIRIDD ; " " and FAT_ATTR.DIRECTORY ; папка ? jr nz,.PRZ ; да ld l,(ix+FAT_DIRECTORY_RECORD.F_SIZE) ; мл. разряд ld h,(ix+FAT_DIRECTORY_RECORD.F_SIZE+1) exx ld l,(ix+FAT_DIRECTORY_RECORD.F_SIZE+2) ; ст. разряд ld h,(ix+FAT_DIRECTORY_RECORD.F_SIZE+3) exx push ix call MAKE_LN ; десятичный 32-х разрядный вывод .not_zero: ld de,SIZE_BUFFER.low ; "0 000 000 000" ld hl,L32BIT_ ; "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,SIZE_BUFFER.low ; "0 000 000 000" pop ix .PRZ: ld de,Buffers.bat_params.PRM3; 16 буфер jp ncopy_string ; скопир. строку (с нулем), макс.15 симв. ; Скопировать в буфер дату файла/папки PRNDATE: ld c,(ix+FAT_DIRECTORY_RECORD.DATE) ld b,(ix+FAT_DIRECTORY_RECORD.DATE+1) ld hl,SIZE_BUFFER.low ; "0 000 000 000" call MAKE_DATE ; вывод в буфер даты ld (hl),0 ld hl,SIZE_BUFFER.low ; "0 000 000 000" ld de,Buffers.bat_params.PRM4; 16 куда jp ncopy_string ; скопир. строку (с нулем), макс.15 симв. ; Скопировать в буфер время файла/папки PRNTIME: ld b,(ix+22) ld c,(ix+23) ld hl,SIZE_BUFFER.low ; "0 000 000 000" call MAKE_TIME ; скопир. в буфер время файла/папки ld (hl),0 ld hl,SIZE_BUFFER.low ; "0 000 000 000" ld de,Buffers.bat_params.PRM5; 80 буфер строки jp ncopy_string ; скопир. строку (с нулем), макс.15 симв. ; в буфер время файла/папки MAKE_TIME: srl c rr b srl c rr b srl c rr b srl b srl b ld a,c call toNumber ld (hl),":" ; раздел. времени inc hl ld a,b jr toNumber ; в буфер дату файла/папки MAKE_DATE: ld a,c and #1F push bc call toNumber ld (hl),"." ; раздел. даты inc hl pop bc ld a,c srl b rla rla rla rla and #0F call toNumber ld (hl),"." ; раздел. даты inc hl ld a,b add a,80 cp 100 jr c,toNumber .loop: sub 100 cp 100 jr nc,.loop ; toNumber: ld c,#2F .loop: inc c sub 10 jr nc,.loop add a,10 add a,"0" ld (hl),c inc hl ld (hl),a inc hl ret ; ;!TODO перетащить в procedures/math.asm ; Десятичный 32-х разрядный вывод ; HL':HL - число для перевода ; !FIXIT можно объеденить с PDIGIT MAKE_LN: ld ix,L32BIT_ ; "0000000000" exx ld de,#3B9A exx ld de,#CA00 ; DE':DE = 1,000,000,000 call GET_DIG .skip_1: exx ld de,#05F5 exx ld de,#E100 ; DE':DE = 100,000,000 call GET_DIG ; 100,000,000...999,999,999 exx ld de,#98 exx ld de,#9680 ; DE':DE = 10,000,000 call GET_DIG ; 10,000,000...99,999,999 exx ld de,#0F exx ld de,#4240 ; DE':DE = 1,000,000 call GET_DIG ; 1,000,000...9,999,999 exx ld de,#01 exx ld de,#86A0 ; DE':DE = 100,000 call GET_DIG ; 100,000...999,999 exx ld de,#00 exx ld de,#2710 ; DE':DE = 10,000 call GET_DIG ; 10,000...99,999 exx ld de,#00 exx ld de,#03E8 ; DE':DE = 1,000 call GET_DIG ; 1,000...9,999 exx ld de,#00 exx ld de,#64 ; DE':DE = 100 call GET_DIG ; 100..999 exx ld de,#00 exx ld de,#0A ; DE':DE = 10 call GET_DIG ; 10..99 ld a,l add a,"0" ld (ix+0),a inc ix ret ; GET_DIG: ld a,"0"-1 AND A .loop: inc a sbc hl,de exx sbc hl,de exx jp nc,.loop ; add hl,de exx adc hl,de exx ;dec a cp "0" jr nz,.putChar ld b,a ld a,(ix-1) cp " " jr z,.putChar ld a,b ; .putChar: ld (ix+0),a inc ix ret ; FILES: WORD 0 S_LOW: WORD 0 S_MED: WORD 0 S_HIGH: BYTE 0 dir_number: WORD 0 ; full_space_low: WORD 0 full_space_medium: WORD 0 full_space_high: BYTE 0 ; ; !TODO может обойтись одним буфером 00 вместо двух? L40BIT: db " " ; маркер для ix-1 .Str: db " " ; 00 L32BIT_: db " " ; 000000000 .end: db "0" ; DIRIDD: db " ",0 ; SIZE_BUFFER: db " " ; маркер для ix-1 .high db " " ; "00" .low: db " ",0,0 ; "0 000 000 000",0,0 .bytes equ SIZE_BUFFER - $ ; ;---------------; SlashMaskFname: db '\' ; ; маска файлов mask_fname: db "*.*",0 ;---------------; cmd_dir_options:; [x] параметр /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: ; ставим опцию для API DSS DskInfo ld a,1 ld (read_disk_info.full),a jp cmd_dir.parse ; cmd_dir_pause: ld a,#ff ld (cmd_dir.key_p),a jp cmd_dir.parse /////////////////////////////////////////////////////////////////////////////////////// GET_BIG_DIG: ld b,"0"-1 and a .loop: inc b sbc hl,de exx sbc hl,de exx sbc a,c jp nc,.loop ; add hl,de ; exx adc hl,de exx adc a,c ; ex af,af' ;dec b ld a,b cp "0" jr nz,.putChar ld a,(ix-1) cp " " jr z,.putChar ld a,b ; .putChar: ld (ix+0),a ex af,af' inc ix ret ; stop ; A:HL':HL - число для перевода PRINT_5BYTES: ld ix,L40BIT.Str ; "00" ld c,#17 exx ld de,#4876 exx ld de,#E800 ; C:DE':DE = 100,000,000,000 call GET_BIG_DIG ; ld c,#02 exx ld de,#540B exx ld de,#E400 ; C:DE':DE = 10,000,000,000 CALL GET_BIG_DIG ; ld c,#00 exx ld de,#3B9A exx ld de,#CA00 ; C:DE':DE = 1,000,000,000 CALL GET_BIG_DIG ; ; DE':DE = 100,000,000 CALL MAKE_LN.skip_1 ld de,SIZE_BUFFER.high ; "0 000 000 000" ld hl,L40BIT.Str ; "0000000000" 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 ld a,(hl) ldi cp " " jr z,1F ld a,"," ; разд. разрядов 1: ld (de),a inc de ldi ldi ldi scf ret /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// ;----------------------------------------------------------------------; ;Процедура умножения (16*8bit) ;На вход: DE * C ;На выход:A:HL = результат IFUSED Mult32 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 .loop: ADD HL,HL RLA JR NC,.next ADD HL,DE ADC A,C .next: DJNZ .loop RET ENDIF ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ;Процедура умножения (32bit) ;На вход: HL:DE * BC ;На выход:HL:DE = результат IFUSED Mult32 Mult32: PUSH IX LD IX,#0000 LD A,#20 EX DE,HL .loop: ADD IX,IX ADC HL,HL RL E RL D JR NC,.no_add ADD IX,BC JR NC,no_add INC HL .no_add: DEC A JR NZ,.loop LD E,LX LD D,HX POP IX RET ENDIF ;----------------------------------------------------------------------; ;INPUT : DE * BC ;OUTPUT: HL:DE IFUSED Mult32 Mult_16x16: LD IX,0 LD HL,0 ; LD A,B OR C JR Z,.exit ; .loop: SRL B RR C JP NC,.no_add ADD IX,DE JR NC,.no_add INC HL ; .no_add: LD A,B OR C JR Z,.exit ; SLA E RL D RL L RL H JP .loop ; .exit: LD D,XH LD E,XL RET ENDIF ///////////////////////////////////////////////////////////////////////////////////////