;///////////////////////////////////////////////////
;
; 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
;