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