; LAST UPDATE: 13.10.2022 savelij
COM_FAT EX AF,AF'
CALL P5_READ_BYTE
LD A,(NEXTBYTERST8)
PUSH IX
PUSH IY
LD IYL,EXTERNAL
JR ICOM_FAT1
;ОБЩАЯ ТОЧКА ВХОДА ДЛЯ РАБОТЫ С FAT
ICOM_FAT EX AF,AF'
EX (SP),HL
LD A,(HL)
INC HL
EX (SP),HL
PUSH IX
PUSH IY
LD IYL,INTERNAL
ICOM_FAT1 LD (ERORDRV),SP
PUSH HL
LD HL,EXITDRV
EX (SP),HL
PUSH HL
LD HL,TABLFAT
ADD A,A
ADD A,L
LD L,A
LD A,H
ADC A,0
LD H,A
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
EX AF,AF'
EX (SP),HL
RET
ERR_DRV LD SP,(ERORDRV)
EXITDRV POP IY
POP IX
RET
TABLFAT DW INIT_FATVARS ; инициализация переменных FAT
DW READ_DIR ; получение описателя файла
DW ENTER_DIR ; вход/выход в дир
DW GET_PATH ; получение текущего пути
DW GET_LONGNAME ; получение длинного имени файла
DW FIND_NAME ; поиск по имени
DW FIND_FILEITEM ; поиск всех описателей с выдачей номеров найденного
DW SET_MASK_EXT ; установка маски расширений для поиска
DW OPEN_FILE ; открытие файла
DW READ_FILE ; последовательное чтение файла
DW INIT_TEKDIR ; создание таблицы кластеров текущей директории
DW POS_FILES ; работа с текущей позицией
DW ROOTDIR ; выход в корневую директорию
ROOTDIR PUSH IY
LD IYL,INTERNAL
LD A,(SETDVOL)
LD D,A
LD L,A
LD H,0
ADD HL,HL
ADD HL,HL
ADD HL,HL
LD BC,BUF_TABLVOL + 2
ADD HL,BC
LD A,(HL)
LD HL,BUF_TABLVOL
CALL INIT_FATVARS
LD DE,(CurrentDIRCluster)
LD BC,(CurrentDIRCluster + 2)
CALL INIT_TEKDIR
POP IY
RET
; инициализация переменных FAT
; На входе:
; HL = адрес таблицы найденых разделов
; DE = D - номер выбранного раздела, E - количество найденных разделов
; A = тип раздела если найден MBR
; На выходе:
; BCDE = номер кластера корневой директории
; A = тип раздела если MBR не найден
INIT_FATVARS PUSH HL
LD HL,0xFFFF
LD (NumSec2Buf + 2),HL
LD (FATType),A
LD E,D
LD D,0
EX DE,HL
POP DE
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,DE
INC HL
INC HL
INC HL
CALL LOADZP
LD (StartSecVol),DE
LD (StartSecVol + 2),BC ; номер первого сектора раздела
CALL LOADLST
CALL VALID_BOOTSEC
AND A
JR Z,RDFAT07
SCF
RET
RDFAT07 LD A,(BUF_512 + _BPB_SecPerClus)
LD (SecPerClus),A
LD HL,(BUF_512 + _BPB_RsvdSecCnt)
ADD HL,DE
LD (NumSecFAT1),HL
LD HL,0
ADC HL,BC
LD (NumSecFAT1 + 2),HL
LD HL,0
LD DE,(BUF_512 + _BPB_FATSz16)
LD A,D
OR E
JR NZ,RDFAT01 ; если не FAT12/16 (_BPB_FATSz16 == 0)
LD DE,(BUF_512 + _BPB_FATSz32)
LD HL,(BUF_512 + _BPB_FATSz32 + 2) ; то берем из смещения +36
RDFAT01 LD (FATSize),DE
LD (FATSize + 2),HL ; число секторов на FAT таблицу
LD HL,0
LD DE,(BUF_512 + _BPB_TotSec16)
LD A,D
OR E
JR NZ,.L1 ; если не FAT12/16 (BPB_TOTSEC16=0)
LD DE,(BUF_512 + _BPB_TotSec32)
LD HL,(BUF_512 + _BPB_TotSec32+2)
; то берем из смещения +32
.L1 LD (NumsSectorsVol + 2),HL
LD (NumsSectorsVol),DE ; к-во секторов на диске/разделе
; вычисляем ROOTDIRSECTORS
LD DE,(BUF_512 + _BPB_RootEntCnt)
LD BC,0
LD A,D
OR E
JR Z,RDFAT03
LD A,0x10
CALL BCDE_A
; это реализована формула
; ROOTDIRSECTORS = ((BPB_ROOTENTCNT * 32) + (BPB_BYTSPERSEC - 1)) / BPB_BYTSPERSEC
; в HL ROOTDIRSECTORS. если FAT32, то HL = 0 всегда
RDFAT03 PUSH DE ; ROOTDIRSECTORS
LD HL,NumSecFAT1
CALL LOADZP
LD A,(BUF_512 + _BPB_NumFATs)
LD (NumFATs),A
DEC A
JR Z,.L1
LD HL,FATSize
CALL BCDEHLP
LD (NumSecFAT2),DE
LD (NumSecFAT2 + 2),BC
.L1 LD HL,FATSize
CALL BCDEHLP
LD (NumSecRootDir),DE
LD (NumSecRootDir + 2),BC
POP HL
; добавляем размер ROOTDIR
ADD HL,DE
EX DE,HL
LD HL,0
ADC HL,BC
LD B,H
LD C,L
LD (FirstSecData),DE
LD (FirstSecData + 2),BC
LD HL,NumsSectorsVol
CALL BCDEHLM
LD A,(SecPerClus)
CALL BCDE_A
LD (NumsClustersVol),DE
LD (NumsClustersVol + 2),BC
LD A,(FATType)
CP 0xFF
JR NZ,.L4
; определение типа FAT при отсуствии MBR
LD HL,(BUF_512 + _BPB_FATSz16)
LD A,H
OR L
LD A,2
JR Z,.L2
LD DE,(FATSize - 1)
LD BC,(FATSize + 1)
LD E,0 ; BCDE = количество секторов * 0x100
LD HL,NumsClustersVol ; количество кластеров на FAT
CALL HLBCDEM ; количество кластеров - (количество секторов * 0x100)
LD A,D
OR C
OR B
LD A,1 ; FAT16
JR Z,.L2 ; FAT16 если флаг Z=0
XOR A ; иначе FAT12
.L2 LD (FATType),A
; для FAT12/16 ROOT кластер = 0
; для FAT32 берем по смещению +44
; На выходе: BCDE - СЕКТОР ROOTDIR КЛАСТЕР
.L4 XOR A
LD (TEK_LEV),A
LD (BUF_PATH),A
CALL INIT_PATH
LD A,(FATType)
PUSH AF
AND A
LD DE,0
LD B,D
LD C,E
JR Z,.L3 ; FAT12-NONE
DEC A
JR Z,.L3 ; FAT16
LD DE,(BUF_512 + _BPB_RootClus)
LD BC,(BUF_512 + _BPB_RootClus + 2) ; FAT32
.L3 LD (CurrentDIRCluster),DE
LD (CurrentDIRCluster + 2),BC ; номер текущего кластера
LD (RootDIRCluster),DE
LD (RootDIRCluster + 2),BC ; номер корневого кластера
POP AF
RET
; проверка 0 сектора раздела
VALID_BOOTSEC LD HL,(BUF_512 + _BPB_BytsPerSec)
LD A,H
SUB 2
OR L
JR NZ,VALID_BOOTSEC1
LD HL,(BUF_512 + _BPB_SecPerClus)
OR L
JR Z,VALID_BOOTSEC1
NEG
AND L
CP L
JR NZ,VALID_BOOTSEC1
LD A,(BUF_512 + _BPB_NumFATs)
DEC A
CP 7
JR NC,VALID_BOOTSEC1
XOR A
RET
VALID_BOOTSEC1 OR IXH
RET
; формирование таблицы кластеров DIR
; и поиск первой "легальной" записи в DIR
INIRTSC PUSH AF
LD HL,0xFFFF
LD (NumSec2Buf + 2),HL
LD HL,BUF_TDIRCLS
LD DE,(CurrentDIRCluster)
LD BC,(CurrentDIRCluster + 2)
CALL SAVEZP
LD A,D
OR E
OR B
OR C
JR Z,LASTCLS
NEXTCLS PUSH HL
CALL RDFATZP
CALL LST_CLS
POP HL
JR C,LASTCLS
CALL SAVEZP
JR NEXTCLS
LASTCLS LD BC,0xFFFF
CALL SAVEZP
CALL POSTF02
POP AF
RET
; чтение следующего номера кластера
RDFATZP LD A,(FATType)
AND A
JR Z,RDFATS0
DEC A
JR Z,RDFATS1
EX DE,HL
ADD HL,HL
EX DE,HL
LD HL,0
ADC HL,BC
ADD HL,BC ; HLDE = BCDE * 2
LD A,E
LD E,D
LD D,L
LD C,H
LD B,0
CALL RDFATS2
INC HL
LD C,(HL)
INC HL
LD B,(HL)
RET
RDFATS1 LD BC,0
LD A,E
LD E,D
LD D,C
RDFATS2 PUSH AF
PUSH BC
LD HL,NumSecFAT1
CALL BCDEHLP
CALL LOADLST
POP BC
POP AF
LD E,A
LD D,0
ADD HL,DE
ADD HL,DE
LD E,(HL)
INC HL
LD D,(HL)
RET
RDFATS0 LD H,D
LD L,E
ADD HL,HL
ADD HL,DE
SRL H
RR L
LD A,E
LD E,H
LD D,0
LD B,D
LD C,D
SRL E
PUSH AF
PUSH HL
LD DE,(NumSecFAT1)
LD BC,(NumSecFAT1 + 2)
CALL LOADLST
POP BC
LD A,B
AND 1
LD B,A
ADD HL,BC
LD B,(HL)
INC HL
LD A,H
CP HIGH (BUF_512)+2
JR NZ,RDFATS4
PUSH BC
LD BC,0
INC DE
CALL LOADLST
POP BC
RDFATS4 POP AF
LD D,(HL)
LD E,B
LD BC,0
RRA
JR NC,RDFATS3
REPT 4
SRL D
RR E
ENDM
RDFATS3 LD A,D
AND 0x0F
LD D,A
RET
; вычисление номера реального сектора
; На входе: BCDE = номер кластера FAT
; На выходе: BCDE = номер сектора
REALSEC LD A,B
OR C
OR D
OR E
JR NZ,REALSE1
LD DE,(NumSecRootDir)
LD BC,(NumSecRootDir + 2)
RET
REALSE1 LD HL,0xFFFE
EX DE,HL
ADD HL,DE
EX DE,HL
INC HL
ADC HL,BC ; номер кластера-2
LD A,(SecPerClus)
JR REALSE2
REALSE3 SLA E
RL D
RL L
RL H
REALSE2 RRCA
JR NC,REALSE3 ; умножили на размер кластера
LD B,H
LD C,L
LD HL,FirstSecData
JP BCDEHLP ; прибавили смещение от начала раздела
; сохраняем сектор загруженный в буфер
LSTSAVE LD DE,(NumSec2Buf)
LD BC,(NumSec2Buf + 2)
LD HL,BUF_512
LD A,1
CALL TO_DRV
DB _DEV_WRITE
AND A
JP NZ,ERR_DRV
RET
; загружаем сектор в буфер
LOADLST CALL CPNUMSC
JR NZ,LOADLS1
LD HL,BUF_512
RET
LOADLS1 LD (NumSec2Buf),DE
LD (NumSec2Buf + 2),BC
LD HL,BUF_512
PUSH HL
LD A,1
CALL TO_DRV
DB _DEV_READ
AND A
JP NZ,ERR_DRV
POP HL
RET
; проверка на номер уже загруженный сектор
CPNUMSC LD HL,NumSec2Buf
LD A,(HL)
INC HL
CP E
RET NZ
LD A,(HL)
INC HL
CP D
RET NZ
LD A,(HL)
INC HL
CP C
RET NZ
LD A,(HL)
CP B
RET
; проверка на последний кластер
LST_CLS LD A,(FATType) ; взяли тип FAT
AND A
JR NZ,LST_CL1
LD HL,0x0FF7 ; для FAT12
SBC HL,DE
RET
LST_CL1 DEC A
JR NZ,LST_CL2
LD HL,0xFFF7 ; для FAT16
SBC HL,DE
RET
LST_CL2 LD HL,0x0FFF
SBC HL,BC
RET NZ
LD HL,0xFFF7
SBC HL,DE
RET
; получить описатель текущего файла
READ_DIR LD A,IYL
AND A
JR NZ,GETFZA3
PUSH IY
LD IYL,INTERNAL
PUSH HL
LD HL,(RREG_C)
LD (TEK_ZAP),HL
LD HL,GETFZA4
EX (SP),HL
GETFZA3 LD BC,(TEK_ZAP) ; текущий номер описателя
LD A,B
OR C
JR Z,GETRZAP ; если номер =0, то предыдущий номер не проверяем
PUSH BC ; сохранили текущий номер
DEC BC ; нужно проверить предыдущий номер
CALL GETRZAP ; проверяем
POP BC ; вернули текущий номер
LD E,A ; из предыдущего описателя нужен только флаговый байт
GETRZAP PUSH DE
CALL RDDIRSC ; читаем сектор с текущим номером
POP DE ; вернули регистр E
INC A
LD A,E ; вернули наличие/отсуствие длинного имени
RET Z ; выходим если вылетели за пределы существующей диры
EX AF,AF'
GETFZA1 LD A,C
AND 0x0F ; получили номер описателя в загруженном секторе диры
LD E,A
LD D,0
EX DE,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,DE ; вычислили адрес выбранного описателя
LD DE,0x0B
LD A,(HL) ; взяли флаговый байт текущего описателя
EX DE,HL
ADD HL,DE
LD L,(HL) ; взяли первый байт имени
LD H,A ; положили флаговый байт этого описателя
EX DE,HL
CALL CP_TWOT ; проверка на наличие в имени ".."
LD D,0 ; будем входить в директорию
JR NZ,GETFZA2
LD D,0x80 ; будем выходить в предыдущую директорию
GETFZA2 EX AF,AF'
CP 0x0F ; проверяем флаговый байт предыдущего описателя
LD A,E ; взяли флаговый байт текущего описателя
LD E,D ; выставили направление движения в дирах
RET NZ
INC E ; установка наличия длинного имени
RET
GETFZA4 PUSH AF
PUSH HL
PUSH DE
LD DE,CPU6
ADD HL,DE
LD DE,(RREG_L)
LD BC,0x20
CALL LDIR_BYTES
POP DE
POP HL
POP AF
POP IY
RET
; чтение сектора DIR по номеру BC
; На выходе: A = 0xFF - выход за пределы DIR
RDDIRSC PUSH BC
LD D,B
LD E,C
LD BC,0
LD A,0x10
CALL BCDE_A
LD A,E
PUSH AF
LD A,(SecPerClus)
PUSH AF
CALL BCDE_A
LD HL,BUF_TDIRCLS
EX DE,HL
ADD HL,HL
ADD HL,HL
ADD HL,DE
CALL LOADZP
BIT 7,B
JR Z,RDDIRS3
POP BC
POP BC
POP BC
XOR A
DEC A
RET
RDDIRS3 CALL REALSEC
POP AF
DEC A
LD L,A
POP AF
AND L
LD L,A
LD H,0
ADD HL,DE
EX DE,HL
LD HL,0
ADC HL,BC
LD B,H
LD C,L
CALL LOADLST
POP BC
XOR A
RET
; проверка на 1 точку
CP_ONET LD A,(HL)
CP "."
RET NZ
INC HL
LD A,(HL)
DEC HL
CP " "
RET NZ
XOR A
RET
; проверка на 2 точки
CP_TWOT LD A,(HL)
CP "."
RET NZ
INC HL
LD A,(HL)
DEC HL
CP "."
RET NZ
XOR A
RET
EPOS_FILES LD HL,(TEK_ZAP)
LD (RREG_C),HL
RET
POS_FILES LD D,A
LD A,IYL
LD IYL,INTERNAL
AND A
LD A,D
JR NZ,POSITFILE1
LD HL,EPOS_FILES
PUSH HL
LD A,(RREG_A)
LD BC,(RREG_C)
POSITFILE1 CP LOW ((ENDTPOS - TPOSITF) / 2)
RET NC
ADD A,A
LD DE,TPOSITF
LD L,A
LD H,0
ADD HL,DE
LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
JP (HL)
TPOSITF DW POSTF00 ; сохранение текущей позиции файла
DW POSTF01 ; восстановление текущей позиции файла
DW POSTF02 ; сброс текущей позиции в 0 и поиск первой "легальной" записи
DW POSTF03 ; перемотать на "B" файлов назад
DW POSTF04 ; перемотать на "B" файлов вперед
DW POSTF05 ; подсчет количества "легальных" записей
DW POSTF06 ; установить номер "легальной" записи из "BC"
DW POSTF07 ; вернуть в "BC" текущий номер "легальной" записи
ENDTPOS
; сохранение текущей позиции файла
POSTF00 LD HL,(TEK_ZAP)
LD (SAVEZAP),HL
RET
; восстановление текущей позиции файла
POSTF01 LD HL,(SAVEZAP)
LD (TEK_ZAP),HL
RET
; перемотать на "B" файлов назад
POSTF03 LD A,B
AND A
RET Z
.L1 PUSH BC
CALL PRVLEGZ
POP BC
DJNZ .L1
RET
; перемотать на "B" файлов вперед
POSTF04 LD A,B
AND A
RET Z
.L1 PUSH BC
CALL NXTLEGZ
POP BC
DJNZ .L1
RET
; подсчет количества "легальных" записей
POSTF05 LD BC,0
PUSH BC
EXX
POP BC
EXX
CALL RDDIRSC
LD DE,_DIR_StructSize
.L4 LD A,(HL)
CP "."
JR NZ,.L5
INC HL
LD A,(HL)
DEC HL
CP "."
JR Z,.L5
INC BC
ADD HL,DE
JR .L4
.L1 INC BC
ADD HL,DE
.L5 LD A,H
CP HIGH (BUF_512) + 2
JR NZ,.L2
CALL RDDIRSC
LD D,0
AND A
JR Z,.L2
CALL .L3
DEC A
RET
.L2 LD E,_DIR_Attr
ADD HL,DE
LD A,(HL)
AND A
SBC HL,DE
LD E,_DIR_StructSize
CP 0x0F ; длинное имя?
JR Z,.L1
CP 8 ; имя раздела?
JR Z,.L1
LD A,(HL)
CP 0xE5 ; удаленный файл?
JR Z,.L1
AND A
JR Z,.L3
EXX
INC BC
EXX
JR .L1
.L3 LD D,B
LD E,C
EXX
PUSH BC
EXX
POP BC
XOR A
RET
; установить номер "легальной" записи из "BC"
POSTF06 LD (TEK_ZAP),BC
RET
; вернуть в "BC" текущий номер "легальной" записи
POSTF07 LD BC,(TEK_ZAP)
RET
CPTEKZP CALL RDDIRSC
RET M
LD A,C
AND 0x0F
LD L,A
LD H,0
LD DE,BUF_512
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,DE
LD DE,0x0B
ADD HL,DE
LD A,(HL)
SBC HL,DE
LD E,(HL)
AND A
RET
; сброс текущей позиции в 0 и поиск первой "легальной" записи
POSTF02 LD BC,0
LD (TEK_ZAP),BC
CALL RDDIRSC
CALL CP_ONET
JR Z,NXTLEG1
LD A,(HL)
AND A
RET Z
JR NXTLEG1+1
NXTLEGZ LD BC,(TEK_ZAP)
NXTLEG1 INC BC
CALL CPTEKZP
CP 0xFF
RET Z
CP 0x0F
JR Z,NXTLEG1
CP 8
JR Z,NXTLEG1
LD A,E
AND A
RET Z
CP 0xE5
JR Z,NXTLEG1
LD (TEK_ZAP),BC
RET
PRVLEGZ LD BC,(TEK_ZAP)
CALL CPTEKZP
CALL CP_TWOT
RET Z
PRVLEG1 DEC BC
CALL CPTEKZP
CP 0x0F
JR Z,PRVLEG1
CP 8
JR Z,PRVLEG1
LD A,E
CP 0xE5
JR Z,PRVLEG1
LD (TEK_ZAP),BC
RET
SAVEZP LD (HL),E
INC HL
LD (HL),D
INC HL
LD (HL),C
INC HL
LD (HL),B
INC HL
RET
LOADZP LD E,(HL)
INC HL
LD D,(HL)
INC HL
LD C,(HL)
INC HL
LD B,(HL)
INC HL
RET
BCDE200 LD E,D
LD D,C
LD C,B
LD B,0
LD A,2
JR BCDE_A
; BCDE >> A = BCDE
BCDE_A1 SRL B
RR C
RR D
RR E
BCDE_A RRCA
JR NC,BCDE_A1
RET
; BCDE - (ADR) = BCDE
HLBCDEM LD A,E
SUB (HL)
INC HL
LD E,A
LD A,D
SBC A,(HL)
INC HL
LD D,A
LD A,C
SBC A,(HL)
INC HL
LD C,A
LD A,B
SBC A,(HL)
LD B,A
RET
; (ADR) - BCDE = BCDE
BCDEHLM LD A,(HL)
INC HL
SUB E
LD E,A
LD A,(HL)
INC HL
SBC A,D
LD D,A
LD A,(HL)
INC HL
SBC A,C
LD C,A
LD A,(HL)
SBC A,B
LD B,A
RET
; (ADR) + BCDE = BCDE
BCDEHLP LD A,(HL)
INC HL
ADD A,E
LD E,A
LD A,(HL)
INC HL
ADC A,D
LD D,A
LD A,(HL)
INC HL
ADC A,C
LD C,A
LD A,(HL)
ADC A,B
LD B,A
RET
; HLDE + BC = HLDE
HLDEPBC EX DE,HL
ADD HL,BC
EX DE,HL
LD BC,0
ADC HL,BC
RET
INIT_PATH
EVOPORT WIN_P5,RAM_MOUNTER
LD A,(SETDVOL)
LD D,A
ADD A,HIGH (TEK_BUFPATH + CPU5) + 4
LD H,A
LD L,0
LD A,"E"
ADD A,D
LD (HL),A
INC L
LD (HL),":"
INC L
LD (HL),"/"
INC L
LD (HL),0
INC L
LD A,L
LD L,0xFF
LD (HL),A
RET
RENEW_PATH
EVOPORT WIN_P5,RAM_MOUNTER
BIT 7,E
JR NZ,MINUS_PATH
; добавление директории к текущему пути (вход в директорию)
EX DE,HL
LD A,(SETDVOL)
ADD A,HIGH (TEK_BUFPATH + CPU5) + 4
LD H,A
LD L,0xFF
LD L,(HL)
EX DE,HL
DEC DE
LD BC,8
LDIR
LD B,8
RENEWPATH3 DEC DE
LD A,(DE)
INC DE
CP " "
JR NZ,RENEWPATH2
DEC DE
DJNZ RENEWPATH3
RENEWPATH2 LD A,(HL)
CP " "
JR Z,RENEWPATH4
LD A,"."
LD (DE),A
INC DE
LD BC,3
LDIR
LD B,3
RENEWPATH5 DEC DE
LD A,(DE)
INC DE
CP " "
JR NZ,RENEWPATH4
DEC DE
DJNZ RENEWPATH5
RENEWPATH4 EX DE,HL
LD (HL),"/"
INC L
LD (HL),0
INC L
LD A,L
LD L,0xFF
LD (HL),A
RET
; укорочение текущего пути (выход в предыдущую директорию)
MINUS_PATH LD A,(SETDVOL)
ADD A,HIGH (TEK_BUFPATH + CPU5) + 4
LD H,A
LD L,0xFF
LD L,(HL)
DEC L
DEC L
MINUS_PATH1 DEC L
LD A,(HL)
CP "/"
JR NZ,MINUS_PATH1
INC L
LD (HL),0
INC L
LD A,L
LD L,0xFF
LD (HL),A
RET
; получение текущего пути
GET_PATH
EVOPORT WIN_P5,RAM_MOUNTER
LD A,IYL
AND A
JR NZ,GETPATH1
LD A,(SETDVOL)
LD D,A
ADD A,HIGH (TEK_BUFPATH+CPU5)+4
LD H,A
LD L,0xFF
LD A,(HL)
LD DE,BUF_256
LD BC,0x100
LD L,C
LDIR
LD C,A ; BC=сколько байт переносить в адрес по запросу
LD A,HIGH (CPU6) - 1
ADD A,D
LD H,A
LD DE,(RREG_L) ; куда переносить путь
JP LDIR_BYTES
GETPATH1 PUSH HL
PUSH HL
LD A,(SETDVOL)
LD D,A
ADD A,HIGH (TEK_BUFPATH + CPU5) + 4
LD H,A
LD L,0xFF
LD A,(HL)
POP DE
LD BC,0x100
LD L,C
LDIR
POP HL
RET
; отдача короткого имени файла, если длинное отсуствует
NO_LNG POP DE
LD BC,8
LDIR
EX DE,HL
NO_LNG2 DEC HL
LD A,(HL)
CP " "
JR Z,NO_LNG2
INC HL
LD A,(DE)
EX DE,HL
CP " "
JR Z,NO_LNG1
EX DE,HL
LD (HL),"."
INC HL
EX DE,HL
LDI
LDI
LDI
NO_LNG1 EX DE,HL
LD (HL),0
LD A,L
LD (RREG_A),A
POP HL
RET
GETLNG8 POP IY
LD DE,CPU6
ADD HL,DE
LD DE,(RREG_L)
LD BC,0x100
JP LDIR_BYTES
; отдача длинного имени файла
GET_LONGNAME LD A,IYL
AND A
JR NZ,GETLNG9
PUSH IY
LD IYL,INTERNAL
LD HL,GETLNG8
PUSH HL
LD HL,BUF_256
GETLNG9 PUSH HL
PUSH HL
CALL READ_DIR
BIT 0,E
JR Z,NO_LNG
EXX
LD C,0
EXX
GETLNG2 DEC BC
CALL GETRZAP
LD A,(HL)
INC HL
EXX
BIT 6,C
POP HL
JR NZ,GETLNGE + 1
LD C,A
EXX
LD A,5
CALL GETLNG1
AND A
JR Z,GETLNGE
INC HL
INC HL
INC HL
LD A,6
CALL GETLNG1
AND A
JR Z,GETLNGE
INC HL
INC HL
LD A,2
CALL GETLNG1
AND A
JR Z,GETLNGE
EXX
PUSH HL
EXX
JR GETLNG2
GETLNGE EXX
LD (HL),0
LD A,L
LD (RREG_A),A
EXX
POP HL
RET
GETLNG1 EXX
LD B,A
EXX
LD D,(HL)
INC HL
LD E,(HL)
INC HL
LD A,D
OR E
RET Z
LD A,E
AND A
JR NZ,GETLNG3
LD A,D
CP 0x80
JR C,GETLNG5
LD D,0x5F
JR GETLNG5
GETLNG3 CP 4
LD A,0x5F
JR NZ,GETLNG5
LD A,D
LD E,0xEF
LD D,0x5F
CP 1
JR Z,GETLNG4
LD E,0xA0
CP 0x51
JR Z,GETLNG4
SUB 0x10
LD E,0x80
JR NC,GETLNG6
LD A,D
JR GETLNG5
GETLNG6 CP 0x30
JR C,GETLNG4
LD E,0xB0
CP 0x40
JR C,GETLNG4
LD A,D
JR GETLNG5
GETLNG4 ADD A,E
GETLNG5 EXX
LD (HL),A
INC HL
DEC B
EXX
RET Z
JR GETLNG1 + 3
;401,410-44F,451
; на входе: DE = список расширений
; HL = адрес описателя файла
; на выходе: A = номер расширения
CP_EXT LD C,0
CPETR2 LD A,(DE)
AND A
JR Z,CPETR1
INC C
PUSH DE
PUSH HL
CALL COMPARF
POP HL
POP DE
LD A,C
RET Z
INC DE
INC DE
INC DE
JR CPETR2
CPETR1 DEC A
RET
COMPARF PUSH DE
LD DE,8
ADD HL,DE
POP DE
COMPARF1 LD A,(DE)
CP (HL)
RET NZ
INC HL
INC DE
LD A,(DE)
CP (HL)
RET NZ
INC HL
INC DE
LD A,(DE)
CP (HL)
RET
FIND_FILEITEM PUSH IY
LD IYL,INTERNAL
CALL INIRTSC
EVOPORT WIN_P3,RAM_TEMP2
LD HL,CPU3
LD DE,CPU3+1
LD BC,0x3FFF
LD (HL),L
LDIR
LD HL,0
LD (KOLFIND),HL ; найденных файлов
LD HL,CPU3
LD (ADR_SKLAD),HL ; адрес складирования
LD HL,CPU3+0x1000
LD (ADR_SKLAD_NAME),HL ; адрес складирования первого символа имени найденного и его флага
LD BC,0xFFFF
EXX
LD BC,0
LD A,(TEK_LVL)
AND A
EXX
JR NZ,FINDF2
LD A,(FATType)
CP 2
JR NC,FINDF2
EXX
LD BC,(ROOTZAP)
EXX
FINDF2 INC BC
CALL RDDIRSC
LD A,C
AND 0x0F
REPT 4
ADD A,A
ENDM
LD E,A
LD D,0
EX DE,HL
ADD HL,HL
ADD HL,DE
EXX
DEC BC
LD A,B
OR C
EXX
JR Z,FINDF3
LD A,(HL)
AND A
JR Z,FINDF3
CP "."
JR NZ,FINDF21
INC HL
LD A,(HL)
DEC HL
CP " "
JR Z,FINDF2
FINDF21 CP 0xE5 ; если удалено
JR Z,FINDF2 ; то переходим на следующий описатель
LD DE,0x0B ; нужен флаговый байт описателя
ADD HL,DE ; получили адрес флагового байта
LD A,(HL) ; взяли флаговый байт
SBC HL,DE
CP 0x0F
JR Z,FINDF2
AND 0x10 ; проверка это файл или дира
JR NZ,FINDF1
LD A,(EXT4FOUND)
AND A
PUSH DE
LD DE,EXT4FOUND
PUSH BC
CALL NZ,CP_EXT
POP BC
POP DE
JR NZ,FINDF4
FINDF1 EX DE,HL
ADD HL,DE
LD A,(HL)
EX AF,AF'
LD HL,(ADR_SKLAD) ; для диры проверять больше не надо
LD (HL),C
INC HL
LD (HL),B ; положили номер диры в табличку
INC HL
LD (ADR_SKLAD),HL
LD HL,(KOLFIND)
INC HL ; +1 найденных файлов
LD (KOLFIND),HL
LD HL,(ADR_SKLAD_NAME)
EX AF,AF'
LD (HL),A
INC HL
LD A,(DE)
LD (HL),A
INC HL
LD (ADR_SKLAD_NAME),HL
FINDF4 LD A,(ADR_SKLAD + 1)
CP HIGH (CPU3) + 0x10
JR C,FINDF2 ; не более 2048 диров/файлов в текущей директории
FINDF3 LD HL,(KOLFIND)
POP IY
LD A,IYL
AND A
JR NZ,FINDF5
LD A,RAM_TEMP2
LD (RREG_A),A
LD (RREG_C),HL
FINDF5 LD (KOL_FOUNDED),HL
LD B,H
LD C,L
XOR A
RET
SET_MASK_EXT LD A,(RREG_A)
AND A
JR NZ,SET_MASK_EXT1
LD (EXT4FOUND),A
RET
SET_MASK_EXT1 LD HL,(RREG_L)
LD DE,BUF_256 - CPU6
LD BC,0x10 * 3 + 1
CALL LDIR_BYTES
LD HL,BUF_256
LD DE,EXT4FOUND
LD BC,0x10FF
SET_MASK_EXT2 LD A,(HL)
AND A
JR Z,SET_MASK_EXT3
LDI
LDI
LDI
DJNZ SET_MASK_EXT2
SET_MASK_EXT3 XOR A
LD (DE),A
RET
LD_FILE6 PUSH AF
POP HL
LD (RREG_F),HL
LD_FILE8 EXX
LD (SAVE_IY),DE ; IY
EXX
RET
; IXL - L - количество секторов для загрузки
; IXH - H - размер кластера
; IYL - E -
; IYH - D - смещение в кластере
READ_FILE EX AF,AF'
LD A,IYL
DEC A
JR Z,LD_FILE00
LD IYL,INT4EXT
LD HL,LD_FILE6
PUSH HL
LD HL,(RREG_L) ; адрес загрузки
EXX
LD DE,(SAVE_IY) ; смещение в кластере
LD A,(SecPerClus)
LD H,A ; количество секторов в кластере
LD A,(RREG_A)
LD L,A ; количество секторов для загрузки
EXX
JR LD_FILE0
LD_FILE00 EXX
LD DE,(SAVE_IY) ; смещение в кластере
LD HL,LD_FILE8
PUSH HL
LD A,(SecPerClus) ; КОЛИЧЕСТВО СЕКТОРОВ В КЛАСТЕРЕ
LD H,A
EX AF,AF'
LD L,A ; количество секторов для загрузки
EXX
; IXL - L - количество секторов для загрузки
; IXH - H - размер кластера
; IYL - E -
; IYH - D - смещение в кластере
LD_FILE0 LD DE,(AFILCLS)
LD BC,(AFILCLS+2) ; текущий номер кластера
PUSH BC
PUSH DE
PUSH HL
CALL REALSEC ; перевели номер кластера в номер сектора
EXX
LD A,D ; IYH
EXX
LD L,A
LD H,0
ADD HL,DE
EX DE,HL
JR NC,LD_FILE1
INC BC ; BCDE=номер сектора откуда грузить
LD_FILE1 EXX
LD A,L ; IXL
CP H ; IXH
JP C,LD_FILE2
LD A,H ; IXH
LD_FILE2 ADD A,D ; IYH
CP H ; IXH
LD A,L ; IXL
JP C,LD_FILE5
LD A,H ; IXH
SUB D ; IYH
LD_FILE5 LD E,A ; IYL,A ; сколько секторов сейчас грузим
EXX
POP HL ; восстановили адрес загрузки
; LD IYL,INT4EXT
CALL TO_DRV
DB _DEV_READ
LD A,IYL
DEC A
JR Z,LD_FILE7
LD (RREG_L),HL
LD_FILE7 POP DE
POP BC ; восстановили номер кластера
EXX
LD A,D ; IYH
ADD A,E ; IYL
CP H ; IXH
JP C,LD_FILE3
SUB H ; IXH
LD_FILE3 LD D,A ; IYH,A
EXX
JP C,LD_FILE4
PUSH HL ; сохранили адрес загрузки
PUSH IY
LD IYL,INTERNAL
CALL RDFATZP ; прочитали номер следующего кластера
POP IY
LD (AFILCLS),DE
LD (AFILCLS + 2),BC
CALL LST_CLS ; проверили, а может это последний кластер?
POP HL ; восстановили адрес загрузки
RET C ; если последний, выходим
LD_FILE4 EXX
LD A,L ; IXL
SUB E ; IYL
EXX
RET Z
EXX
LD L,A ; IXL,A
EXX
JP NZ,LD_FILE0
RET
OPEN_FILE LD A,IYL
AND A
JR NZ,OPENFILE1
LD HL,EOPEN_FILE
PUSH HL
OPENFILE1 PUSH IY
LD IYL,INTERNAL
CALL READ_DIR
LD DE,FILE_SRC
LD BC,_DIR_StructSize
PUSH DE
LDIR
LD HL,0
LD A,(FATType)
CP 2
JR C,OPENFILE2 ; если это не FAT32 то старшие 16 бит обнуляем
LD HL,(FILE_SRC + _DIR_FstClusHI)
OPENFILE2 LD (AFILCLS + 2),HL
LD HL,(FILE_SRC + _DIR_FstClusLO)
LD (AFILCLS),HL
LD HL,(TEK_ZAP)
LD (NUM_FILE_SRC),HL
XOR A
LD H,A
LD L,A
LD (SAVE_IY),HL
POP HL
POP IY
RET
EOPEN_FILE PUSH AF
POP HL
LD (RREG_F),HL
RET
EFINDNAME LD HL,(TEK_ZAP)
LD (RREG_C),HL
PUSH AF
POP HL
LD (RREG_F),HL
RET
FIND_NAME LD A,IYL
AND A
JR NZ,FINDNAME01
PUSH HL
LD HL,(RREG_L)
LD DE,BUF_256 - CPU6
LD BC,0x10
CALL LDIR_BYTES
LD HL,EFINDNAME
EX (SP),HL
FINDNAME01 PUSH IY
LD IYL,INTERNAL
LD HL,BUF_256
LD DE,FB_EXT
LD BC,0x8FF
LD A,(HL)
CP "."
JR NZ,FINDNAME02
LDI
LDI
LD B,6
FINDNAME02 LD A,(HL)
CP "!"
JR C,FINDNAME03
CP "."
JR Z,FINDNAME12
LDI
DJNZ FINDNAME02
LD A,(HL)
CP "!"
JR C,FINDNAME06
INC HL
JR FINDNAME06
FINDNAME12 INC HL
FINDNAME03 LD A," "
FINDNAME05 LD (DE),A
INC DE
DJNZ FINDNAME05
FINDNAME06 LD B,3
FINDNAME08 LD A,(HL)
CP "!"
JR C,FINDNAME07
LDI
DJNZ FINDNAME08
CALL POSTF02
JR FINDNAME11
FINDNAME07 LD A," "
FINDNAME09 LD (DE),A
INC DE
DJNZ FINDNAME09
CALL POSTF02
JR FINDNAME11
FINDNAME10 CALL NXTLEGZ
FINDNAME11 PUSH HL
CALL CMP_NAME
POP HL
JR Z,FINDNAME13
LD A,(HL)
AND A
JR NZ,FINDNAME10
SCF
FINDNAME13 POP IY
RET
CMP_NAME LD DE,FB_EXT
ICMP_NAME LD B,0x0B
CMP_NAME_B LD A,(DE)
CP "a"
JR C,CMPNAME01
CP "{"
JR NC,CMPNAME01
AND %11011111
CMPNAME01 CP (HL)
RET NZ
INC DE
INC HL
DJNZ CMP_NAME_B
XOR A
RET
; вхождение в dir
ENTER_DIR LD IYL,INTERNAL
CALL READ_DIR
PUSH AF
PUSH DE
PUSH HL
CALL RENEW_PATH
POP HL
POP DE
POP AF
BIT 4,A
EX AF,AF'
LD A,E
EX AF,AF'
LD E,A
LD D,(HL)
RET Z
EXX
EX AF,AF'
BIT 7,A
JR Z,ENT_DI2
LD HL,TEK_LEV
LD A,(HL)
AND A
EXX
RET Z
EXX
DEC A
LD (HL),A
ADD A,A
LD H,HIGH (BUF_DIRCEP + CPU6)
LD L,A
LD A,(HL)
INC L
LD H,(HL)
LD L,A
JR ENT_DI1
ENT_DI2 LD HL,TEK_LEV
LD A,(HL)
INC A
CP 0x10
EXX
RET Z
EXX
LD (HL),A
DEC A
ADD A,A
LD H,HIGH (BUF_DIRCEP + CPU6)
LD L,A
LD BC,(TEK_ZAP)
LD (HL),C
INC L
LD (HL),B
ENT_DI1 EXX
PUSH DE
LD DE,_DIR_FstClusHI
ADD HL,DE
LD C,(HL)
INC HL
LD B,(HL)
LD E,5
ADD HL,DE
LD E,(HL)
INC HL
LD D,(HL)
LD A,B
OR C
OR D
OR E
JR NZ,ENT_DI0
LD DE,(RootDIRCluster)
LD BC,(RootDIRCluster + 2)
ENT_DI0 LD (CurrentDIRCluster),DE
LD (CurrentDIRCluster + 2),BC
POP DE
INIT_TEKDIR PUSH DE
PUSH IY
LD IYL,INTERNAL
CALL INIRTSC
POP IY
POP DE
RET