Estex-DSS/DSS/FS/FAT.asm
Tolik ef258143e7 SEARCH_RECORD_IN_DIR_CACHE
допилить переключение страницы кэша при достижении конца директории (напоролись на ноль)
2026-01-13 22:11:46 +10:00

3164 lines
72 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; [ ] RST_FS
;----------------------------------------------------------------------;
; MODULE FAT_FS
MODULE_START EQU $
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ;
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ;
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
; ‘«ã¦¥¡­ë¥ FAT
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
;----------------------------------------------------------------------;
SET_FSInfo: LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x32
RET NZ
;
LD A,(CORE_BUFFERS.FS_Buffer.UPD_FSINFO)
OR A
RET Z
;
; „¥« ¥¬ FSInfo ᥪâ®à
; ç¨á⨬ ᥪâ®à
LD HL,CORE_BUFFERS.SECTOR_BUFFER
LD DE,CORE_BUFFERS.SECTOR_BUFFER+1
LD (HL),0
LD BC,512 - 1 ;!HARDCODE à §¬¥à ᥪâ®à 
LDIR
; LEAD_SIGNATURE
LD HL,#5252
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.LEAD_SIGNATURE),HL
LD HL,#4161
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.LEAD_SIGNATURE + 2),HL
; DATA_SIGNATURE
LD HL,#7272
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.DATA_SIGNATURE),HL
LD HL,#6141
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.DATA_SIGNATURE + 2),HL
; SECTOR_SIGNATURE
LD HL,#AA55
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.SECTOR_SIGNATURE),HL
; FREE_CLUSTERS_COUNT
LD HL,(CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_L)
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT),HL
LD HL,(CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_H)
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT+2),HL
; FIRST_FREE_CLUSTER
LD HL,(G_CLUST.low)
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER),HL
LD HL,(G_CLUST.high)
LD (CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER+2),HL
; <20>¨è¥¬ ¥£® ­  ¢¨­â
XOR A
LD (CORE_BUFFERS.FS_Buffer.UPD_FSINFO),A
JR WRITE_FSinfo
; ;
; <20>à®ç¨â âì BPB ¢ SECTOR_BUFFER
READ_BPB: LD C,Dss.DRV.GetBPB
JR RW_SECTOR
; ‡ ¯¨á âì FSinfo ¨§ SECTOR_BUFFER
WRITE_FSinfo: LD IX,(CORE_BUFFERS.FS_Buffer.FSINFO_Sector)
LD HL,0
;JR WRITE_SECTOR
;
; ‡ ¯¨á âì ᥪâ®à ¨§ SECTOR_BUFFER
; ‚室: HL:IX = Logical Block (sector)
WRITE_SECTOR: LD BC,1*256 + Dss.DRV.Write
JR RW_SECTOR
; <20>à®ç¨â âì FSinfo ¢ SECTOR_BUFFER
READ_FSinfo: LD IX,(CORE_BUFFERS.FS_Buffer.FSINFO_Sector)
LD HL,0
; <20>à®ç¨â âì ᥪâ®à ¢ SECTOR_BUFFER
; ‚室: HL:IX = Logical Block (sector)
READ_SECTOR: LD BC,1*256 + Dss.DRV.Read
;
RW_SECTOR: IN A,(SLOT3)
PUSH AF
IN A,(SLOT0)
OUT (SLOT3),A
;
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE)
LD DE,CORE_BUFFERS.SECTOR_BUFFER+#C000
RST ToDSS.DRV
EX AF,AF'
;
POP AF
OUT (SLOT3),A
EX AF,AF'
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; RD_BPB: CALL READ_BPB
; RET C
; ;
; LD DE,#AA55 ; ᨣ­ âãà  ;R05
; LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.MBR_SIGNATURE) ;R08 ;R07
; ;[ ] CDFS
; ;R05
; AND A
; SBC HL,DE
; JP NZ,DOS_X_Error.UnknownBPB
;
FAT_BPB: LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.DRIVE_TYPE)
CP #F0
JP C,RD_BPB.UnknownBPB
; PREPARE
XOR A
LD (.UsesVarsFAT32),A
;
LD H,A
LD L,A
LD D,A
LD E,A
EXX
; fat32
LD B,A
LD C,A
LD (CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H),A ; fat32
;
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.BytesPerSector)
LD (CORE_BUFFERS.FS_Buffer.BytesPerSector),HL
LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.SectorsPerCluster)
LD (CORE_BUFFERS.FS_Buffer.SectorsPerCluster),A
; calc. first sector FAT
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.RESERVED_SECTORS)
LD (CORE_BUFFERS.FS_Buffer.FAT1_SEC_L),HL ; low word first sector FAT #1
LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_L),HL ; low word first sector FAT #2
;
; BC = 0
; fat32
LD (CORE_BUFFERS.FS_Buffer.FAT1_SEC_H),BC ; high word first sector FAT #1 ; fat32
LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_H),BC ; high word first sector FAT #1 ; fat32
LD (CORE_BUFFERS.FS_Buffer.RootDirFirstSector_H),BC
;LD (CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_H),BC ; fat32 reset variables
; § ­ã«ï¥¬ ¯ à ¬¥âàë ¤¨à¥ªâ®à¨¨ ¤«ï ¯¥à¢®£® ®¡à é¥­¨ï
; LD (CORE_BUFFERS.FM_BUF.FIRST_CLUSTER_L),BC
; LD (CORE_BUFFERS.FM_BUF.FIRST_CLUSTER_H),BC
;
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.SectorsPerFAT16)
LD A,E
OR D
JR NZ,.skip_high
;
LD (.UsesVarsFAT32),A
EXX
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.SectorsPerFAT32 + 2)
LD A,E
EXX
;
LD (CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H),A
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.SectorsPerFAT32)
;
.skip_high: LD (CORE_BUFFERS.FS_Buffer.SectorsPerFAT_L),DE
LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.Number_of_FATs) ; amount FATs
LD (CORE_BUFFERS.FS_Buffer.Number_Of_FATs),A
CP 1
JR Z,.one_FAT
JP C,RD_BPB.UnknownBPB
DEC A
ADD HL,DE
LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_L),HL
EXX
ADC HL,DE
LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_H),HL
EXX
;JR NC,.no_inc_BC
;INC BC
.no_inc_BC:;LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_H),BC
.one_FAT: ;
.loop1: ADD HL,DE
;JR NC,.loop1_1
;INC BC
EXX
ADC HL,DE
EXX
.loop1_1: DEC A
JR NZ,.loop1
;
LD (CORE_BUFFERS.FS_Buffer.RootDirFirstSector_L),HL ; first sector DIR
EXX
; ¬®¦­® áà §ã âãâ § £­ âì áâ à訩 ¡ ©â, ¯®â®¬ã-çâ® ¤«  FAT32 á«¥¤ãî騩 à áçñâ - íâ® ¯à¨¡ ¢«¥­¨¥ ­ã«ï.
LD (CORE_BUFFERS.FS_Buffer.FirstDataSector_H),HL
EXX
;
LD BC,(CORE_BUFFERS.FS_Buffer.BytesPerSector)
LD A,B
AND A
; BytesPerSector/FAT_DIRECTORY_RECORD (32)
RL C
RLA
RL C
RLA
RL C
RLA
;
LD C,A
LD B,0 ; BC - File handels per sector
;;;;
IF COMPILE_UNUSED_CODE
LD (CORE_BUFFERS.FS_Buffer.FilesPerSector),A
ENDIF
;
EX DE,HL
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.FilesInRootDIR) ; 0 for fat32
; fat32
LD A,H
OR L
;JR Z,.skip_loop2
JR NZ,.filesRoot
;
INC A
LD (.UsesVarsFAT32),A
DEC A
JR .skip_loop2
;
.filesRoot: DEC HL
XOR A
;NEXTAD2
; FilesInRootDIR / FilesPerSector = sectors in RootDir
.loop2: INC A
JP Z,RD_BPB.UnknownBPB
SBC HL,BC
JR NC,.loop2
;
.skip_loop2: EX DE,HL
LD C,A ; A - sectors in RootDir
LD B,0
LD (CORE_BUFFERS.FS_Buffer.DirSizeInSectors),A
ADD HL,BC ; Start DATA area
LD (CORE_BUFFERS.FS_Buffer.FirstDataSector_L),HL
; B = 0
;
LD HL,(CORE_BUFFERS.FS_Buffer.BytesPerSector)
LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster)
;!TODO FATcacheSize
; calc. cluster size
XOR 1
JR Z,.loop3.end
RRA
.loop3: ADD HL,HL
RRA
JP NC,.loop3
.loop3.end: ;
LD (CORE_BUFFERS.FS_Buffer.BytesPerCluster),HL
;LD DE,#8001 ; ¯à®¢¥àª  ­  à §¬¥à ª« áâ¥à  ¡®«ìè¥ 32 ª¡ - ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ; !TODO
;AND A
;SBC HL,DE
;JP NC,DOS_X_Error.UnknownBPB ; [ ] fixed bug, thanks to @Romychs (Roman Boykov)
//////////////////////////////////////////////////////////////////
;!TODO ­¥ ¨á¯®«ì§ã¥âáï §­ ç¥­¨ï ¢ëç¨á«ï¥¬ë¥ ¨ á®åà ­ï¥¬ë¥ ¢ FS_Buffer
; EX DE,HL
; LD HL,#3FFF ;!HARDCODE ;!TODO FATcacheSize
; XOR A
; ;NEXTAD4 ;!FIXIT ®¯â¨¬¨§¨à®¢ âì ª®£¤  ¯®­ ¤®¡¨âáï
;.loop4: INC A
; JP Z,DOS_X_Error.UnknownBPB
; SBC HL,DE
; JR NC,.loop4
; LD (CORE_BUFFERS.FS_Buffer.ClustersPerBank),A ; A - Clusters per bank (16k)
;
; LD HL,0
; LD BC,(CORE_BUFFERS.SECTOR_BUFFER + _sBOOT_SECTOR_PARAMS.SectorsPerTrack) ; Sector per track
; LD A,(CORE_BUFFERS.SECTOR_BUFFER + _sBOOT_SECTOR_PARAMS.HEADS)
;.BPB_L1: ; calc. sector per cylinder
; ADD HL,BC
; DEC A
; JR NZ,.BPB_L1
; LD (CORE_BUFFERS.FS_Buffer.S_X_H),HL
//////////////////////////////////////////////////////////////////
; fat32
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.SectorsPerDrive)
LD A,H
OR L
LD DE,(CORE_BUFFERS.FS_Buffer.FirstDataSector_L)
JP NZ,.HDDSMAL
;
EXX
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.BPB_BIG_TOTAL_SECTORS_H)
PUSH HL ; Total Sectors high
LD DE,(CORE_BUFFERS.FS_Buffer.FirstDataSector_H)
EXX
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.BPB_BIG_TOTAL_SECTORS_L)
PUSH HL ; Total Sectors low
AND A
SBC HL,DE
EXX
SBC HL,DE
PUSH HL
EXX
POP BC
;JP NC,.HDDBIG
;DEC BC
JP .HDDBIG
;
.HDDSMAL: ; CF = 0
LD BC,0
PUSH BC ; Total Sectors high
PUSH HL ; Total Sectors low
SBC HL,DE
;
.HDDBIG: CALL SectorToCluster
;
.loop7_exit: INC HL
LD (CORE_BUFFERS.FS_Buffer.MaxClusterLow),HL
LD A,L
OR H
JR NZ,.no_inc_bc
INC BC
.no_inc_bc: LD (CORE_BUFFERS.FS_Buffer.MaxClusterHigh),BC
;
XOR A
LD H,A
LD L,A
LD (CORE_BUFFERS.FS_Buffer.CacheBlock),HL
LD (CORE_BUFFERS.FS_Buffer.CacheUpdated),A
; A = 0
LD HL,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H)
LD H,A
LD D,H
LD E,L
EXX
LD HL,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_L)
LD D,H
LD E,L
; HL':HL = SectorsPerFAT
; DE':DE = SectorsPerFAT
LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.Number_of_FATs)
DEC A
LD B,A
CALL NZ,ALL_SECTORS_PER_FATs
EXX
PUSH HL
EXX
POP DE
; DE:HL - sectors per FATs
.loop_mul_end: ; .DirSizeInSectors + .Number_of_FATs * .SectorsPerFAT
LD B,0
LD A,(CORE_BUFFERS.FS_Buffer.DirSizeInSectors)
LD C,A
ADD HL,BC
JR NC,.no_inc_DE
INC DE
.no_inc_DE: ; .RESERVED_SECTORS + .DirSizeInSectors + .Number_of_FATs * .SectorsPerFAT
LD BC,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.RESERVED_SECTORS)
ADD HL,BC
JR NC,.no_inc_de
INC DE
.no_inc_de: ; Total_Sectors - (.RESERVED_SECTORS + .DirSizeInSectors + .Number_of_FATs * .SectorsPerFAT)
AND A
LD B,D
LD C,E
POP DE ; Total Sectors low
EX DE,HL
SBC HL,DE
EX (SP),HL ; Total Sectors high
SBC HL,BC
POP DE ; Total Sectors low
; HL:DE = DataSec
;
LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster)
; HL:DE / A => DE:BC, H=0, L - ®áâ â®ª
CALL DIV_by_Shifts
; ¢ëïá­ï¥¬ à §à來®áâì FAT
LD A,D
OR E
JR NZ,.its_FAT32
;
LD HL,4084
SBC HL,BC
JR NC,.its_FAT12
;
LD HL,65524
SBC HL,BC
JR C,.its_FAT32
; It's FAT16
LD A,(.UsesVarsFAT32)
AND A
JP NZ,RD_BPB.UnknownBPB
;
LD HL,#FFFF
LD A,FAT_TYPE.x16
.set_vars: EXX
;!TODO áç¨â âì âãâ à §¬¥à root-¤¨à¥ªâ®à¨¨ ¢ ¡ ©â å ¨ åà ­¨âì ¢ FS_Buffer?
LD HL,0
LD (CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_H),HL
LD (CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L),HL
LD (CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H),HL
LD HL,CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.FAT.LABEL
EXX
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.FAT.SERIAL_NUMBER)
LD BC,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.FAT.SERIAL_NUMBER+2)
JR .SET_VARS
;
.its_FAT12: LD A,(.UsesVarsFAT32)
AND A
JP NZ,RD_BPB.UnknownBPB
;
LD HL,#0FFF
LD A,FAT_TYPE.x12
JR .set_vars
;
.its_FAT32: LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.MainFATnumber)
CP #80
JR C,.mirrored_FATs ;¥á«¨ ¢á¥ ª®¯¨¨ FAT ¨á¯®«ì§ãîâáï
; ¨á¯®«ì§ã¥âáï ⮫쪮 ®¤­  ª®¯¨ï FAT
LD HL,(CORE_BUFFERS.FS_Buffer.FAT1_SEC_H)
LD DE,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H)
LD D,0
EXX
LD HL,(CORE_BUFFERS.FS_Buffer.FAT1_SEC_L)
LD DE,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_L)
AND #0F
LD B,A
CALL NZ,ALL_SECTORS_PER_FATs
;
.first_FAT_active:
LD (CORE_BUFFERS.FS_Buffer.FAT1_SEC_L),HL
LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_L),HL
EXX
LD (CORE_BUFFERS.FS_Buffer.FAT1_SEC_H),HL
LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_H),HL
;
.mirrored_FATs: LD HL,CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.FAT32.LABEL
;
EXX
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.RootDirStartCluster)
LD (CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L),HL
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.RootDirStartCluster+2)
LD (CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H),DE
;
CALL CLUSTER_TO_SECTOR.no_prepare
LD (CORE_BUFFERS.FS_Buffer.RootDirFirstSector_L),IX
LD (CORE_BUFFERS.FS_Buffer.RootDirFirstSector_H),HL
;
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.FSINFO_Sector)
LD (CORE_BUFFERS.FS_Buffer.FSINFO_Sector),HL
;
LD A,FAT_TYPE.x32
LD HL,#0FFF
LD (CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_H),HL
LD H,L
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.FAT32.SERIAL_NUMBER)
LD BC,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.FAT32.SERIAL_NUMBER+2)
;
.SET_VARS: LD (CORE_BUFFERS.FS_Buffer.FAT_TYPE),A
LD (CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_L),HL
LD (CORE_BUFFERS.FS_Buffer.BPB_SERIAL_NUMBER),DE
LD (CORE_BUFFERS.FS_Buffer.BPB_SERIAL_NUMBER+2),BC
EXX
LD DE,CORE_BUFFERS.FS_Buffer.BPB_LABEL
LD BC,11 ;!HARDCODE
LDIR
;
SET_PAGE_X FATPAGE
PUSH AF
LD DE,0
CALL READ_FAT_TABLE
POP AF
OUT (SLOT3),A
;
; “áâ ­®¢¨âì ­ ç «ì­ë© ª« áâ¥à ¤«ï ç⥭¨ï
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x32
JR Z,.set_FSinfo
;
LD HL,#0001
LD (G_CLUST.low),HL
DEC L
LD (G_CLUST.high),HL
;
DEC HL
LD (CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_L),HL
LD (CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_H),HL
XOR A
RET
;
.set_FSinfo: CALL READ_FSinfo
; !FIXIT ¯à®¢¥àª  ­  ®è¨¡ªã
;
; ¯à®¢¥àª  ®¤­®© ¨§ á®â­¨ áà ­ëå ᨣ­ âãà
LD HL,(CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.DATA_SIGNATURE)
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.DATA_SIGNATURE + 2)
LD BC,#7272
SBC HL,BC
JR NZ,.error
EX DE,HL
LD DE,#6141
SBC HL,DE
JR NZ,.error
; FREE_CLUSTERS_COUNT
LD BC,(CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT)
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT+2)
; CF = 0
CALL .check_cluster
JR NC,.skip_FFFF
;
LD B,#FF
LD C,B
LD D,B
LD E,B
;
.skip_FFFF: LD (CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_L),BC
LD (CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_H),DE
;
; FIRST_FREE_CLUSTER
LD BC,(CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER)
LD DE,(CORE_BUFFERS.SECTOR_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER+2)
; CF = 0
CALL .check_cluster
JR C,.error
;
LD (G_CLUST.high),DE
LD (G_CLUST.low),BC
XOR A
.error: LD (CORE_BUFFERS.FS_Buffer.UPD_FSINFO),A
RET Z
;!TODO FREE_CLUSTERS_COUNT
;LD HL,#FFFF
;LD (CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_L),HL
;LD (CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_H),HL
;
XOR A
LD H,A
LD L,2
LD (G_CLUST.low),HL
LD L,H
LD (G_CLUST.high),HL
RET
;
;!TODO MaxCluster - ¬ ªá¨¬ «ì­® ¤®¯ãáâ¨¬ë© ¨«¨ ­  1 ¡®«ìè¥ ¬ ªá¨¬ «ì­® ¤®¯ãá⨬®£®?
.check_cluster: LD HL,(CORE_BUFFERS.FS_Buffer.MaxClusterLow)
SBC HL,BC
LD HL,(CORE_BUFFERS.FS_Buffer.MaxClusterHigh)
SBC HL,DE
RET
;
.UsesVarsFAT32: DB 0
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; --> BC:HL - Sector
; <-- BC:HL - Cluster
SectorToCluster:
LD A,B
AND #0F
LD B,A
LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster)
SCF
.loop: RRA
RET C
RR B
RR C
RR H
RR L
JP .loop
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; HL:HL' - first FAT sector
; DE:DE' - sectors per one FAT
; A - number of FATs (counts from 0)
ALL_SECTORS_PER_FATs:
ADD HL,DE
EXX
ADC HL,DE
EXX
DJNZ ALL_SECTORS_PER_FATs
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; “áâ ­®¢¨âì ¯¥à¢ë¬ ¨§¢¥áâ­ë¬ ª« áâ¥à®¬ ¤«ï ¯®¨áª  ᢮¡®¤­®£®.
; “áâ ­®¢¨âáï ⮫쪮 ¥á«¨ ¬¥­ìè¥ ¯à¥¤ë¤ã饣®
; ‚室: HL':HL - cluster
; ¯®àâ¨â DE, BC' ¨ A
; [x] à ­ìè¥ ¡ë« è ­á 㯥à¥âìáï ¢ "DISK FULL" ¥á«¨ G_CLUST 㪠§ë¢ « ­  ª« áâ¥à ¤ «ìè¥, 祬 ¤à㣮© ᢮¡®¤­ë©
; [ ] free clusters for FSInfo
SET_NEW_FREE_CLUSTER:
LD A,1 ; 㢥«¨ç¨âì
CALL SET_NEW_FREE_CLUSTERS ; [ ] free clusters for FSInfo
; CF=0
;
EX DE,HL
LD HL,(G_CLUST.low)
SBC HL,DE
EX DE,HL
;
EXX
LD B,D
LD C,E
EX DE,HL
LD HL,(G_CLUST.high)
SBC HL,DE
EX DE,HL
LD D,B
LD E,C
EXX
RET C
;
JR G_CLUST.set_new
; LD (G_CLUST.low),HL
; EXX
; LD (G_CLUST.high),HL
; EXX
; XOR A
; INC A
; LD (CORE_BUFFERS.FS_Buffer.RESET_FSINFO),A
; RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ­ ©â¨ ¯¥à¢ë© ᢮¡®¤­ë© ª« áâ¥à ;!TODO ¯à®¢¥à¨âì ¯¥à¥¡®à ª« áâ¥à®¢
; ¢ë室: HL - ¬« ¤è¨© ­®¬¥à ᢮¡®¤­®£® ª« áâ¥à 
; HL' - áâ à訩 ­®¬¥à ᢮¡®¤­®£® ª« áâ¥à 
G_CLUST: ;
.low+1: LD HL,#0001
EXX
.high+1: LD HL,#0000
EXX
.loop: INC HL ; ­®¬¥à ª« áâ¥à 
LD A,L
OR H
; [x] fat32
EXX
JR NZ,.no_inc
INC HL
.no_inc: EXX
;
CALL READ_FROM_FAT ; ¯à®ç¨â âì ¨§ ª¥è  FAT-  ­®¬¥à á«¥¤. ª« áâ¥à 
CP DSS_Error.sys.DISK_FULL
SCF
RET Z
;
EXX
LD A,D
OR E
EXX
OR D
OR E
JR NZ,.loop
.set_new: ; A = 0
LD (G_CLUST.low),HL
EXX
LD (G_CLUST.high),HL
EXX
INC A
LD (CORE_BUFFERS.FS_Buffer.UPD_FSINFO),A
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ‚室: A - 㬥­ìè¨âì (0) ¨«¨ 㢥«¨ç¨âì (!0) ç¨á«® ᢮¡®¤­ëå ª« áâ¥à®¢
SET_NEW_FREE_CLUSTERS:
EX AF,AF
PUSH HL
PUSH DE
EXX
PUSH HL
PUSH DE
LD HL,(CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_H)
LD A,H
AND L
EXX
LD HL,(CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_L)
AND H
AND L
INC A
EXX
JR Z,.no_change
EXX
;
EX AF,AF
OR A
JR Z,.dec_clusters
; inc clusters
INC HL
LD A,H
OR L
JR NZ,.set_new
EXX
INC HL
EXX
;
.set_new: LD A,1
LD (CORE_BUFFERS.FS_Buffer.UPD_FSINFO),A
;
LD (CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_L),HL
EXX
LD (CORE_BUFFERS.FS_Buffer.FREE_CLUSTERS_COUNT_H),HL
.no_change: POP DE
POP HL
EXX
POP DE
POP HL
RET
;
.dec_clusters: LD A,H
OR L
DEC HL
JR NZ,.set_new
EXX
DEC HL
EXX
JP .set_new
; ;
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; <20>ਪ९¨âì ª ¯®á«¥¤­¥¬ã ª« áâ¥àã æ¥¯®çª¨ ­®¢ë© ¯ãá⮩ ª« áâ¥à
; ‚室: HL':HL - ­®¬¥à ª« áâ¥à  ª ª®â®à®¬ã ¯à¨ªà¥¯¨âì ¯ãá⮩
; ‚ë室: HL':HL - ­®¬¥à ª« áâ¥à  ª ª®â®à®¬ã ¯à¨ªà¥¯¨«áï ¯ãá⮩
; DE':DE - ­®¬¥à ¯ãá⮣® ª« áâ¥à 
INC_FAT: PUSH HL ; ⥪ã騩 ª« áâ¥à
EXX
PUSH HL ; ⥪ã騩 ª« áâ¥à
EXX
;
CALL G_CLUST
;
EXX
POP DE ; ⥪ã騩 ª« áâ¥à
EXX
POP DE ; ⥪ã騩 ª« áâ¥à
RET C
; HL':HL - ᢮¡®¤­ë© ª« áâ¥à, DE':DE - ⥪ã騩 ª« áâ¥à
;
EX DE,HL
EXX
EX DE,HL
EXX
;
CALL WRITE_TO_FAT.Custom ; § ¯¨á âì ¢ ª¥è FAT-  ­®¬¥à ª« áâ¥à 
;!FIXIT <­¥â ª®­âà®«ï ®è¨¡ª¨>
;
PUSH HL
EX DE,HL
EXX
PUSH HL
EX DE,HL
EXX
;
CALL WRITE_TO_FAT ; § ¯¨á âì ¢ ª¥è FAT-  ­®¬¥à ª« áâ¥à 
; 02/12/23 ¡ £ á ¨§¡ëâ®ç­®© § ¯¨áìî WRITE_FAT_TABLE
;CALL WRITE_FAT_TABLE ; ¯®¤ª«. ¡ ­ªã ª¥è  FAT ¨ § ¯¨á âì ¥£® ­  ¤¨áª
;
EXX
POP DE
EX DE,HL
EXX
POP DE
EX DE,HL
;
; [ ] free clusters for FSInfo
XOR A ; 㬥­ìè¨âì
CALL SET_NEW_FREE_CLUSTERS ; [ ] free clusters for FSInfo
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ¢å®¤: hl = ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à  ¤«ï áà ¢­¥­¨ï á FAT_Max_Cluster
; hl' = áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ¤«ï áà ¢­¥­¨ï á FAT_Max_Cluster (⮫쪮 ¤«ï fat32)
CHECK_CLUSTER_IS_SMALLER:
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
XOR FAT_TYPE.x32
JR NZ,.low ; Z=0 ¯à®¢¥à塞 ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
; ¯à®¢¥à塞 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
EXX
EX DE,HL
LD HL,(CORE_BUFFERS.FS_Buffer.MaxClusterHigh)
; CF = 0
SBC HL,DE
EX DE,HL
EXX
LD A,DSS_Error.sys.DISK_FULL
RET C
RET NZ
; ¯à®¢¥à塞 ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
.low: EX DE,HL
LD HL,(CORE_BUFFERS.FS_Buffer.MaxClusterLow)
SBC HL,DE
EX DE,HL
LD A,DSS_Error.sys.DISK_FULL
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;------------------------------------------------------------------------------------------------
; <20>à®ç¨â âì ¨§ ª¥è  FAT-  ­®¬¥à á«¥¤. ª« áâ¥à 
; ¢å®¤: hl - ­®¬¥à ª« áâ¥à  (¬« ¤è¥¥ á«®¢®)
; hl' - ­®¬¥à ª« áâ¥à  (áâ à襥 á«®¢®. ⮫쪮 ¤«ï FAT32)
; ¢ë室: hl - ­®¬¥à ª« áâ¥à  (¬« ¤è¥¥ á«®¢®)
; hl' - ­®¬¥à ª« áâ¥à  (áâ à襥 á«®¢®)
; de - ­®¬¥à á«¥¤. ª« áâ¥à  (¬« ¤è¥¥ á«®¢®)
; de' - ­®¬¥à á«¥¤. ª« áâ¥à  (áâ à襥 á«®¢®)
; ¥á«¨ DE':DE = 0, â® ª« áâ¥à HL':HL ᢮¡®¤¥­
; CF - ª®­¥æ 楯®çª¨
;------------------------------------------------------------------------------------------------
READ_FROM_FAT: CALL CHECK_CLUSTER_IS_SMALLER
RET C
;
SET_PAGE_X FATPAGE
;
PUSH HL
PUSH AF
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x16
JR C,.FAT12
;
JR NZ,.FAT32
;
; fat16, ¯à®áâ® ç¨â âì á«¥¤. ­®¬¥à
.FAT16: CALL GET_FAT16_CELL
LD E,(HL) ; ¯à®ç¨â âì ­®¬¥à ª« áâ¥à 
INC HL
LD D,(HL)
;
LD HL,SERVICE_SECTORS.FAT16
.exit: POP AF
OUT (SLOT3),A
; ®¡­ã«ï¥¬ CF ¨ ãáâ ­ ¢«¨¢ ¥¬ ª®¤ ®è¨¡ª¨ = DssErr.sys.NO_ERROR
XOR A
; ¯à®¢¥àª  ­  á«ã¦. ª« áâ¥àë
SBC HL,DE
POP HL
;!FIXIT fat32 ¯¥à¥áâà å®¢ª 
EXX
LD H,A
LD L,A
LD D,A
LD E,A
EXX
RET
;
;
.FAT12: CALL GET_FAT12_CELL
LD E,(HL)
INC HL
LD D,(HL)
LD HL,SERVICE_SECTORS.FAT12
JR NC,.Correct_2
;
.Correct_1: LD A,E
;AND #F0
DUP 4 ; ¢¯à ¢® ­  4 ¡¨âa
;RR D
SRL D
RRA
EDUP
LD E,A
JR .exit
;
.Correct_2: LD A,D
AND #0F
LD D,A
JR .exit
;
.FAT32: EXX
PUSH HL
EXX
;
CALL GET_FAT32_CELL
; ¯à®ç¨â âì ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
LD E,(HL)
INC HL
LD D,(HL)
INC HL
; ¯à®ç¨â âì áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
LD A,(HL)
INC HL
EX AF,AF'
LD A,(HL)
EXX
AND #0F
LD D,A
EX AF,AF'
LD E,A
EXX
; ®¡­ã«ï¥¬ CF ¨ ãáâ ­ ¢«¨¢ ¥¬ ª®¤ ®è¨¡ª¨ = DssErr.sys.NO_ERROR
XOR A
; ¯à®¢¥àª  ­  á«ã¦. ª« áâ¥àë ¬« ¤è¥£® á«®¢  ª« áâ¥à 
LD HL,SERVICE_SECTORS.FAT32.Low
SBC HL,DE
; ¯à®¢¥àª  ­  á«ã¦. ª« áâ¥àë áâ à襣® á«®¢  ª« áâ¥à 
EXX
LD HL,SERVICE_SECTORS.FAT32.High
SBC HL,DE
POP HL
EXX
POP BC
LD A,B
OUT (SLOT3),A
POP HL
LD A,0
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ‚室: HL - <20>®¬¥à ¯¥à¢®© ï祩ª¨ ª« áâ¥à  ¢ ¡«®ª¥ ä â 
; <20>®àâ¨âì ⮫쪮 HL ¨ A
SET_FAT32_CACHE_BLOCK_CHANGED_REGION:
;DEC HL
;LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
;CP FAT_TYPE.x16 + 1
;JR C,.start
;DEC HL
;DEC HL
;
.start: LD A,H
AND #38
LD HL,#0108
JR Z,.set_region
;
.loop: SLA H
;AND A
SUB L
JR NZ,.loop
;
.set_region: LD A,(CORE_BUFFERS.FS_Buffer.CacheUpdated)
OR H
LD (CORE_BUFFERS.FS_Buffer.CacheUpdated),A
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; !TODO optimize
; ¯à¨ § ¯¨á¨ ¢ ªíè §­ ç¥­¨ï ®â¬¥ç âì ç¥à¥§ OR ¢ ï祩ª¥ FS_Buffer.SectorOfCacheBlock
; ¡¨â ᮮ⢥âáâ¢ãî騩 ªãáªã ¢ áâà ­¨æ¥ ªíè , ª®â®àë© ¡ë« ¨§¬¥­ñ­ ¨ ¯®â®¬ ᪨¤ë¢ âì ­  ¤¨áª
; ⮫쪮 ⥠ªã᪨, ª®â®àë¥ ¡ë«¨ ¨§¬¥­¥­ë.
; |--------------------|
; | bit | adresses |
; |-----|--------------|
; | 0 | #0000..#07FF |
; | 1 | #0800..#0FFF |
; | 2 | #1000..#17FF |
; | 3 | #1800..#1FFF |
; | 4 | #2000..#27FF |
; | 5 | #2800..#2FFF |
; | 6 | #3000..#37FF |
; | 7 | #3800..#3FFF |
; |--------------------|
;
;------------------------------------------------------------------------------------------------
; ‡ ¯¨á âì ¢ ª¥è FAT-  ­®¬¥à ª« áâ¥à 
; ¢å®¤: hl = ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à  ¢ ª®â®àë© § ¯¨á âì
; hl' = áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ¢ ª®â®àë© § ¯¨á âì (⮫쪮 ¤«ï fat32)
; .Custom:
; de = ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à  ª®â®à®¥ ¢¯¨á âì
; de' = áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ª®â®à®¥ ¢¯¨á âì (⮫쪮 ¤«ï fat32)
; ¢ë室: HL':HL â ª¨¥ ¦¥ ª ª ¨ ­  ¢å®¤¥
; .Custom:
; HL':HL ¨ DE':DE â ª¨¥ ¦¥ ª ª ¨ ­  ¢å®¤¥
;------------------------------------------------------------------------------------------------
WRITE_TO_FAT: LD DE,(CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_L) ; ­®¬¥à ª« áâ¥à 
EXX
LD DE,(CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_H) ; ­®¬¥à ª« áâ¥à 
EXX
.Custom: PUSH DE
EXX
PUSH DE
EXX
CALL CHECK_CLUSTER_IS_SMALLER
EXX
POP DE
EXX
POP DE
RET C
;
EXX
SET_PAGE_X FATPAGE
EXX
PUSH HL
AND A
PUSH AF
PUSH DE ; ¬« ¤è¨© ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
; [x] 2/12/23 FAT ­¥ ¢á¥£¤  ¬®£ § ¯¨á âìáï ­  HDD
;LD A,1
;LD (CORE_BUFFERS.FS_Buffer.CacheUpdated),A
;
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x16
JR C,.FAT12
JR NZ,.FAT32
;
.FAT16: CALL GET_FAT16_CELL
POP DE ; ¬« ¤è¨© ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
LD (HL),E ; á®åà. ¢ ª¥è¥ FAT- 
INC HL ; ­®¬¥à ª« áâ¥à 
LD (HL),D
.exit: ;
; [ ] ã᪮७¨¥ à ¡®âë á ªí襬 FAT
CALL SET_FAT32_CACHE_BLOCK_CHANGED_REGION
;
POP AF ; ¢®ááâ. ¯®àâ
POP HL
OUT (SLOT3),A
; [x] 2/12/23 FAT ­¥ ¢á¥£¤  ¬®£ § ¯¨á âìáï ­  HDD
;LD A,#FF
;LD (CORE_BUFFERS.FS_Buffer.CacheUpdated),A
;
; CF = 0
RET
;
.FAT12: ;!FIXIT ¯¥à¥¤¥« âì ­  ¯¥à¥¬¥­­ë¥ FAT_CACHE
CALL GET_FAT12_CELL
POP DE ; ¬« ¤è¨© ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
JR C,.Correct_1 ; ­®¬¥à ­¥çñâ­ë©
LD (HL),E
INC HL
LD A,(HL)
AND #F0
OR D
LD (HL),A
JR .exit
;
.Correct_1: ; ¢«¥¢® ­  4 ¡¨âa
PUSH DE
EX DE,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
EX DE,HL
;
LD A,(HL)
AND #0F
OR E
LD (HL),A ; á®åà. ¢ ª¥è¥ FAT- 
INC HL ; ­®¬¥à ª« áâ¥à 
LD (HL),D
POP DE
JR .exit
;
.FAT32: EXX
PUSH DE ; áâ à訩 ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
PUSH HL ; áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ¢ ª®â®àë© § ¯¨á âì
EXX
CALL GET_FAT32_CELL
EXX
POP HL ; áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ¢ ª®â®àë© § ¯¨á âì
POP DE
PUSH DE ; áâ à訩 ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
EXX
POP BC ; áâ à訩 ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
POP DE ; ¬« ¤è¨© ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
; á®åà. ¢ ª¥è¥ FAT-  ­®¬¥à ª« áâ¥à 
LD (HL),E
INC HL
LD (HL),D
INC HL
LD (HL),C
INC HL
LD A,(HL)
AND #F0
OR B
LD (HL),A
JR .exit
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;FAT_BLOCK * Sectors_in_Block = SECTOR_OF_FAT
; in: HL - Cache block
; out: C:HL - logical number
; B = 0
GET_SECTOR_OF_FAT:
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
LD B,FAT_CACHE.Degree_32 ;!FIXIT ᤥ« âì ç¥à¥§ ¯¥à¥¬¥­­ãî
XOR FAT_TYPE.x32
JR Z,.next
LD B,FAT_CACHE.Degree ;!FIXIT ᤥ« âì ç¥à¥§ ¯¥à¥¬¥­­ãî
XOR A
.next: LD C,A
;
.loop: ADD HL,HL ;x2
ADC A,C
DJNZ .loop
;
LD C,A
RET
; GET_SECTOR_OF_FAT:
; XOR A
; LD B,A
; LD C,A
; DUP FAT_CACHE.Degree ; 4
; ADD HL,HL ;x2
; ADC A,C
; EDUP
; LD C,A
; LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
; CP FAT_TYPE.x32
; RET NZ
; ADD HL,HL ;x2
; RET NC
; INC C
; RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;RE_FAT:
;RX01
; <20>à®ç¨â âì ¢ ª¥è •• ᥪâ®à®¢ FAT- 
; DE - NEW FAT BLOCK
READ_FAT_TABLE: PUSH HL
PUSH DE
LD A,(CORE_BUFFERS.FS_Buffer.CacheUpdated)
OR A
CALL NZ,WRITE_FAT_TABLE.Start
POP DE
;
EX DE,HL
LD (CORE_BUFFERS.FS_Buffer.CacheBlock),HL
;
CALL GET_SECTOR_OF_FAT
;
; BC:HL - ­®¬¥à «®£.ᥪâ®à 
LD DE,(CORE_BUFFERS.FS_Buffer.FAT1_SEC_L)
ADD HL,DE
EX DE,HL
LD XH,D
LD XL,E
LD HL,(CORE_BUFFERS.FS_Buffer.FAT1_SEC_H)
; JR NC,.no_inc
; INC HL
.no_inc: ADC HL,BC
; HL:IX - SECTOR FAT FOR READING
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
XOR FAT_TYPE.x32
LD BC,FAT_CACHE.Sectors_16 * 256 + Dss.DRV.Read ; ॣ B * FAT_CACHE.Sector_Size = CASH SIZE
JR NZ,.next
LD B,FAT_CACHE.Sectors_32 ; ॣ B * FAT_CACHE.Sector_Size = CASH SIZE
.next: LD DE,FATPAGE.cache ; ªã¤  ; DE - FAT ADDRESS
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) ; ­®¬¥à ¤¨áª 
RST ToDSS.DRV
POP HL
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; <20>®¤ª«îç¨âì ¡ ­ªã ª¥è  FAT ¨ § ¯¨á âì ¥£® ­  ¤¨áª
WRITE_FAT_TABLE:
SET_PAGE_X FATPAGE
PUSH AF
CALL .Start ;!TODO ­¥â ª®­âà®«ï ®è¨¡®ª
POP AF
OUT (SLOT3),A
RET
; ‡ ¯¨áì ª¥è  FAT-  ­  ¤¨áª
.Start: CALL SET_FSInfo
LD HL,(CORE_BUFFERS.FS_Buffer.CacheBlock)
;FAT_BLOCK * Sectors_in_Block = SECTOR_OF_FAT
CALL GET_SECTOR_OF_FAT
; B=0, C:HL - ᬥ饭¨¥ ¢ ᥪâ®à å ¢­ãâਠ⠡«¨æë FAT ­  ­ ç «® ¡«®ª 
LD (.pop_offset_HL),HL
LD DE,FAT_CACHE.Sectors_32
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x32
JR Z,.next
LD DE,FAT_CACHE.Sectors_16 ; !FIXIT ¡à âì íâ® §­ ç¥­¨¥ ¨§ ¯¥à¥¬¥­­®© ¢¥§¤¥
;
.next: ADD HL,DE ;+ SIZE CASH (16 SECTORS)
JR NC,.no_inc
INC C
.no_inc: ; C:HL ᬥ饭¨¥ ¢ ᥪâ®à å ¢­ãâਠ⠡«¨æë FAT ­  ª®­¥æ ¡«®ª 
;
; ª®­¥æ ¡«®ª  ¢ë室¨â §  ¯à¥¤¥«ë â ¡«¨æë?
LD B,E ; MAX ç¨á«® ᥪâ®à®¢ ¤«ï ç⥭¨ï ¢ ªíè
LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H)
LD (.sub_A),A
LD DE,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_L)
AND A
LD A,C
SBC HL,DE
.sub_A+1: SBC A,0
JR C,.WALLFAT ; F=1: ­¥ ¢ë室¨â
OR A
JP NZ,.ERR
;
EX DE,HL
; DE - ­  ᪮«ìª® ᥪâ®à®¢ ª®­¥æ ¡«®ª  ¢ë室¨â §  ¯à¥¤¥«ë â ¡«¨æë.
LD HL,FAT_CACHE.Sectors_16 ; !FIXIT ¡à âì íâ® §­ ç¥­¨¥ ¨§ ¯¥à¥¬¥­­®© ¢¥§¤¥
; CF = 0
SBC HL,DE
;SBC A,0
JR C,.ERR ;!TODO ¯à®¢¥à¨âì
LD B,L ; ç¨á«® ᥪâ®à®¢ ¤«ï ç⥭¨ï ¢ ªíè
.WALLFAT: ;
.pop_offset_HL+1:
LD HL,0
; B = ç¨á«® ᥪâ®à®¢
LD IX,(CORE_BUFFERS.FS_Buffer.FAT1_SEC_H)
LD DE,(CORE_BUFFERS.FS_Buffer.FAT1_SEC_L)
PUSH BC
; á®å࠭塞 ¯¥à¢ãî ª®¯¨î FAT. ‚室 IX:DE - ­ ç «® â ¡«¨æë FAT
; C:HL - ᬥ饭¨¥ ¢­ãâਠ⠡«¨æë
; B - ª®«¨ç¥á⢮ ᥪâ®à®¢
CALL .SAVE_FAT_XX
; [x] ¥á«¨ ¢á¥£® ®¤­  â ¡«¨æ  FAT, â® ¯®¢â®à­®© § ¯¨á¨ ­¥ ¯à®¨á室¨â 13/03/2024
POP BC ; B = ç¨á«® ᥪâ®à®¢, C = áâ à訩 ¡ ©â ᬥ饭¨ï ¢ ᥪâ®à å
LD HL,(CORE_BUFFERS.FS_Buffer.FAT1_SEC_H)
LD DE,(CORE_BUFFERS.FS_Buffer.FAT2_SEC_H)
AND A
SBC HL,DE
JR NZ,.not_one_FAT
LD HL,(CORE_BUFFERS.FS_Buffer.FAT2_SEC_L)
LD DE,(CORE_BUFFERS.FS_Buffer.FAT1_SEC_L)
; CF = 0
SBC HL,DE
JR Z,.only_one_FAT
;
.not_one_FAT: LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x32
JR NZ,.fat_num_2
;
LD A,(CORE_BUFFERS.FS_Buffer.Number_Of_FATs)
CP 2
JR Z,.fat_num_2
; á®å࠭塞 ¡®«ìè¥ ¤¢ãå ª®¯¨© FAT
LD HL,(CORE_BUFFERS.FS_Buffer.FAT2_SEC_H)
LD DE,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H)
LD D,0
EXX
LD HL,(CORE_BUFFERS.FS_Buffer.FAT2_SEC_L)
LD DE,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_L)
DEC A
.many_fat_loop: EXX
PUSH HL
PUSH HL
POP IX
EXX
PUSH HL
PUSH BC
EX DE,HL
LD HL,(.pop_offset_HL)
CALL .SAVE_FAT_XX
POP BC
POP HL
;
LD DE,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_L)
ADD HL,DE
EXX
LD DE,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H)
POP HL
ADC HL,DE
EXX
DEC A
JR NZ,.many_fat_loop
JR .norm_exit
;
; á®å࠭塞 ¢â®àãî ª®¯¨î FAT
.fat_num_2: LD IX,(CORE_BUFFERS.FS_Buffer.FAT2_SEC_H)
LD DE,(CORE_BUFFERS.FS_Buffer.FAT2_SEC_L)
LD HL,(.pop_offset_HL)
CALL .SAVE_FAT_XX
.norm_exit: AND A ;!TODO ­¥â ª®­âà®«ï ®è¨¡®ª
.only_one_FAT: ;
.ERR: LD A,0
LD (CORE_BUFFERS.FS_Buffer.CacheUpdated),A
RET
; ‚室: IX:DE - ­ ç «® â ¡«¨æë FAT ¢ ᥪâ®à å
; C:HL - ᬥ饭¨¥ ¢ â ¡«¨æ¥ ¢ ᥪâ®à å
; B - ª®«¨ç¥á⢮ ᥪâ®à®¢
.SAVE_FAT_XX: ADD HL,DE
JR NC,.no_inc_C
INC C
; ­®¬¥à «®£. ᥪâ®à 
.no_inc_C: LD D,0
LD E,C
ADD IX,DE
LD D,XH
LD E,XL
EX DE,HL
LD XH,D
LD XL,E
; HL:IX - ᬥ饭¨¥ ¢­ãâਠࠧ¤¥«  ­  ­ ç «® ­ã¦­®£® ¡«®ª  FAT
LD A,(CORE_BUFFERS.FS_Buffer.CacheUpdated)
CP #FF
JR NZ,.SAVE_NOT_ALL_BLOCK
;
LD DE,FATPAGE.cache ; ®âªã¤ 
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) ; ­®¬¥à ¤¨áª 
LD C,Dss.DRV.Write
JP ToDSS.DRV
;
.SAVE_NOT_ALL_BLOCK:
; A = CORE_BUFFERS.FS_Buffer.CacheUpdated
; HL:IX - ᬥ饭¨¥ ¢­ãâਠࠧ¤¥«  ­  ­ ç «® ­ã¦­®£® ¡«®ª  FAT
; B = ¬ ªá¨¬ «ì­®¥ ç¨á«® ¡«®ª®¢ ¤«ï § ¯¨á¨
EXX
LD HL,FATPAGE.cache
LD DE,#0800 ;!HARDCODE à §¬¥à ॣ¨®­  ¢ ¡«®ª¥ Š<>˜  FAT (¡ ©â®¢)
EXX
LD C,A
LD A,B
LD B,8 ;!HARDCODE ª®«¨ç¥á⢮ ॣ¨®­®¢ ¢ ¡«®ª¥ Š<>˜  FAT
LD DE,4 ;!HARDCODE à §¬¥à ॣ¨®­  ¢ ¡«®ª¥ Š<>˜  FAT (ᥪâ®à®¢)
; ç⮡ ­¥ ­ áà âì §  £à ­¨æë FAT
.region_loop: SUB A,E
JR NC,.good_blk
; ¬ ªá¨¬ «ì­® ¤®¯ãáâ¨¬ë© ¡«®ª ¤«ï § ¯¨á¨ ¬¥­ìè¥, 祬 å®ç¥âáï
ADD A,E
LD E,A
;
.good_blk: SRL C
CALL C,.SAVE_FAT_CACHE_REGION
EXX
ADD HL,DE
EXX
ADD IX,DE
JR NC,.no_inc_HL
INC HL
.no_inc_HL: DJNZ .region_loop
RET
; HL' - €¤à¥á ¢ áâà ­¨æ¥ Š<>˜ 
; HL:IX - ᬥ饭¨¥ ¢­ãâਠࠧ¤¥«  ­  ­ ç «® ­ã¦­®£® <20>…ƒˆŽ<CB86>€ ¡«®ª  FAT
.SAVE_FAT_CACHE_REGION:
PUSH AF
PUSH DE
PUSH BC
PUSH HL
PUSH IX
;
EXX
PUSH HL
PUSH HL
EXX
LD B,E ; ª®«-¢® ᥪâ®à®¢
POP DE ; €¤à¥á ¢ áâà ­¨æ¥ Š<>˜ 
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) ; ­®¬¥à ¤¨áª 
LD C,Dss.DRV.Write
RST ToDSS.DRV
; HL:IX = Sector + Sector counter
; DE = Address + (Sector counter * Size sector)
EXX
POP HL ;  ¤à¥á ¢ áâà ­¨æ¥ Š<>˜ 
LD DE,#0800 ;!HARDCODE à §¬¥à ॣ¨®­  ¢ ¡«®ª¥ Š<>˜  FAT (¡ ©â®¢)
EXX
;
POP IX
POP HL
POP BC
POP DE
POP AF
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;¢å®¤: HL':HL - ­®¬¥à ª« áâ¥à 
;¢ë室: HL -  ¤à¥á ­ã¦­®© ï祩ª¨ ¢ áâà ­¨æ¥ FATPAGE
GET_FAT32_CELL: ; ¤¢¨£ ¥¬ ¢«¥¢® HL':H
LD A,H
EXX
LD C,A
LD A,H
AND FAT_CACHE.Size_Mask_32 ; #0F
LD H,A
LD A,C
;
LD B,FAT_CACHE.Degree ; 4 ᤢ¨£ 
.loop_block: RLCA ; << H
RL L ; << L'
RL H ; << H'
DJNZ .loop_block
EXX
; ¨â®£¥ âãâ ¢ HL' ­®¬¥à ¡«®ª  FAT
;
; HL - FAT32 OFFSET (FROM CASH)
LD A,H
AND FAT_CACHE.Size_Mask_32 ; #0F
LD H,A
ADD HL,HL
ADD HL,HL
PUSH HL ; [x] fat32 á®å࠭塞 ­  á«ãç ©, ¥á«¨ READ_FAT_TABLE ¨á¯®àâ¨â
AND A
;
EXX
EX DE,HL
LD HL,(CORE_BUFFERS.FS_Buffer.CacheBlock) ; BC - BLOCK FAT IN CASH
SBC HL,DE
CALL NZ,READ_FAT_TABLE ; A != C - READ NEW BLOCK FAT
POP HL
LD DE,FATPAGE.cache ; ­ ç «® ª¥è  FAT- 
ADD HL,DE ; ­  ï祩ªã FAT
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;¢å®¤: HL - ­®¬¥à ª« áâ¥à 
;¢ë室: HL -  ¤à¥á ­ã¦­®© ï祩ª¨ ¢ áâà ­¨æ¥ FATPAGE
GET_FAT16_CELL: LD A,H
LD B,H
;AND #0F
AND FAT_CACHE.Size_Mask_16
LD H,A
LD A,B
; A=A/16 ; A - BLOCK FAT (1 BLOCK = 8192 BYTES)
DUP FAT_CACHE.Degree_16
RRCA
EDUP
;AND #0F
AND FAT_CACHE.Part_Mask_16
;
ADD HL,HL ; HL - FAT OFFSET (FROM CASH)
; [x] fat32 ¯®¬¥­ï«áï ¢å®¤ ¢ ¯à®æ¥¤ãàã READ_FAT_TABLE. <20> ­ìè¥ ­®¬¥à ¡«®ª  ¢ ॣ. A ¯¥à¥¤ ¢ «áï
; LD BC,(CORE_BUFFERS.FS_Buffer.CacheBlock) ; BC - BLOCK FAT IN CASH
; CP C
LD DE,(CORE_BUFFERS.FS_Buffer.CacheBlock) ; BC - BLOCK FAT IN CASH
CP E
LD E,A
;
CALL NZ,READ_FAT_TABLE ; A != C - READ NEW BLOCK FAT
LD DE,FATPAGE.cache ; ­ ç «® ª¥è  FAT- 
ADD HL,DE ; ­  ï祩ªã FAT
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;¢å®¤: HL - ­®¬¥à ª« áâ¥à 
;¢ë室: HL -  ¤à¥á ­ã¦­®© ï祩ª¨ ¢ áâà ­¨æ¥ FATPAGE
; CF - çñâ­ë©/­¥çñâ­ë©  ¤à¥á ª« áâ¥à 
GET_FAT12_CELL: LD D,H
LD E,L
SRL H
RR L ; ᤢ¨£ ¢¯à ¢® ç¥à¥§ CF
PUSH AF ; á®åà. ä« £
ADD HL,DE ; CLUSTER * 1.5
;
IF FAT_CACHE.Size_12 < #1800
;!FIXIT ®¯â¨¬¨§¨à®¢ âì
LD A,H
LD B,H
;
AND #1F
;AND FAT_CACHE.Size_Mask_16
;
LD H,A
LD A,B
;
RLCA
RLCA
RLCA
;DUP FAT_CACHE.Degree_16
; RRCA
;EDUP
AND #07
;AND FAT_CACHE.Part_Mask_16
;
; [ ] ¯®¬¥­ï«áï ¢å®¤ ¢ ¯à®æ¥¤ãàã READ_FAT_TABLE. <20> ­ìè¥ ­®¬¥à ¡«®ª  ¢ ॣ. A ¯¥à¥¤ ¢ «áï
; LD BC,(CORE_BUFFERS.FS_Buffer.CacheBlock) ; BC - BLOCK FAT IN CASH
; CP C
LD DE,(CORE_BUFFERS.FS_Buffer.CacheBlock) ; BC - BLOCK FAT IN CASH
CP E
LD E,A
;
CALL NZ,READ_FAT_TABLE ; ¯à®ç¨â âì ¢ ª¥è 16 ᥪâ®à®¢ FAT- 
ENDIF
;
LD DE,FATPAGE.cache
ADD HL,DE
POP AF
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;CLUSTER_TO_SECTOR:
; in: HL':HL - CLUSTER
; out: HL:IX - SECTOR
CLUSTER_TO_SECTOR:
EXX
PUSH HL
EXX
POP DE
; DE:HL - cluster
;
.no_prepare: PUSH BC
LD BC,-2
ADD HL,BC
JR C,.no_dec_de
DEC DE
.no_dec_de: ; cluster = cluster - 2
;
LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster)
XOR 1
JR Z,.skip
;
RRA
.loop: ADD HL,HL
RL E
RL D
;
RRA
JP NC,.loop
;
.skip: EX DE,HL
LD XL,E
LD XH,D
LD DE,(CORE_BUFFERS.FS_Buffer.FirstDataSector_L)
; [x] fat32
;XOR A
;
ADD IX,DE
; [x] fat32
LD DE,(CORE_BUFFERS.FS_Buffer.FirstDataSector_H)
;LD D,A
;LD E,A
;
ADC HL,DE
POP BC
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; READ SECTORS OF FILE
; ¢å®¤: HL:DE - FP (in sectors)
; IY - FM
; IX - buffer in RAM
; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï
BLOCK_READ: LD (READ.PointerOnBuffer),IX
LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster) ;SECTORS PER CLUSTER
LD C,A
PUSH BC ; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï, C - SectorsPerCluster
; HL:DE / A => DE:BC, H=0, L - ®áâ â®ª
CALL DIV_by_Shifts
PUSH HL ; ®áâ â®ª DIV_by_Shifts
; GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
PUSH BC ; ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
PUSH DE ; [x] fat32 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
;
CALL CHECK_FIRST_CLUSTER
JR Z,.fast_exit_4
CALL GetSavedCluster
;HL': HL - ¨§¢¥áâ­ë© ª« áâ¥à ä ©«  ¤«ï ®âáçñâ 
;DE : BC - ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (D=D+1, B=B+1)
;
PUSH DE ; [x] ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (áâ à襥 á«®¢®)
JR .enter_loop1
;
.fast_exit_5: POP DE
.fast_exit_4: ; [x] GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
POP DE ; [x] fat32 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
POP BC
;
POP BC
POP DE
AND A
RET
; [x] fat32
.loop1_big: PUSH BC
LD BC,0
.loop1_small: PUSH BC
CALL READ_FROM_FAT
POP BC
JR C,.fast_exit_5 ;RY01
EX DE,HL
EXX
EX DE,HL
EXX
.enter_loop1: INC B
DEC BC ; - ᬥ饭¨¥ ¢­ãâਠ䠩«  ¢ ª« áâ¥à å (¬« ¤è¥¥ á«®¢®)
DJNZ .loop1_small
POP BC ; [x] ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (áâ à襥 á«®¢®)
INC B
DEC BC
DJNZ .loop1_big
;;;;
;
; GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
POP DE ; [x] fat32 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
POP BC ; ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
CALL SaveGotCluster
;
POP DE ; D = 0, E = ®áâ â®ª DIV_by_Shifts
POP BC ; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï, C - SectorsPerCluster
; (SP) = (RET)
; à ¡®â  á ®áâ âª®¬ ®â ¤¥«¥­¨ï
LD A,C
SUB E
LD C,A
CP B ; (SectorsPerCluster - ®áâ â®ª) - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï
JR C,.skip1 ; SIZE > RESIDUE CLUSTER
LD C,B ; SIZE < CLUSTER
.skip1: LD A,B
SUB C
LD B,A
;
EXX
PUSH HL ; ­®¬¥à ª« áâ¥à  áâ àè ï ç áâì
EXX
PUSH HL ; ­®¬¥à ª« áâ¥à  ¬« ¤è ï ç áâì
PUSH BC ; B = ª®«¨ç¥á⢮ ᥪâ®à®¢ ­  ¤®ç¨âªã, C = (SectorsPerCluster - ®áâ â®ª) «¨¡® ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï
PUSH DE ; D = 0, E = ®áâ â®ª DIV_by_Shifts
CALL CLUSTER_TO_SECTOR
POP DE ; D = 0, E = ®áâ â®ª DIV_by_Shifts
ADD IX,DE
JR NC,.skip2
INC HL
.skip2: LD DE,(READ.PointerOnBuffer)
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE)
LD B,C
LD C,Dss.DRV.Read
RST ToDSS.DRV
;
JR C,.Error
POP BC ; B = ª®«¨ç¥á⢮ ᥪâ®à®¢ ­  ¤®ç¨âªã, C = (SectorsPerCluster - ®áâ â®ª) «¨¡® ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï
LD HL,(READ.PointerOnBuffer)
LD DE,(CORE_BUFFERS.FS_Buffer.BytesPerSector)
;!TEST
LD A,B
LD B,C
.loop2: ADD HL,DE
DJNZ .loop2
;
LD (READ.PointerOnBuffer),HL
POP DE ; ­®¬¥à ª« áâ¥à  ¬« ¤è ï ç áâì
EXX
POP HL ; ­®¬¥à ª« áâ¥à  áâ àè ï ç áâì
EXX
OR A
RET Z ; ª®«¨ç¥á⢮ ᥪâ®à®¢ ­  ¤®ç¨âªã = 0?
LD B,A
;
.loop4: LD HL,CORE_BUFFERS.FS_Buffer.SectorsPerCluster
LD A,B
SUB (HL)
LD B,A
LD C,(HL)
JR NC,.BLOKRD7
LD B,0
ADD A,(HL) ;0 AND CF
LD C,A
OR A ;CLEAR CF
RET Z
;
.BLOKRD7: EX DE,HL
PUSH BC
; HL':HL - ­®¬¥à ª« áâ¥à 
CALL READ_FROM_FAT
POP BC
JR C,.ECL1 ;RY01
;
EXX
EX DE,HL
PUSH HL ; ­®¬¥à á«¥¤. ª« áâ¥à  (áâ à襥 á«®¢®)
EXX
EX DE,HL
PUSH HL ; ­®¬¥à á«¥¤. ª« áâ¥à  (¬« ¤è¥¥ á«®¢®)
PUSH BC
CALL CLUSTER_TO_SECTOR
LD DE,(READ.PointerOnBuffer)
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE)
LD B,C
LD C,Dss.DRV.Read
RST ToDSS.DRV
JR C,.Error
;
POP BC
LD HL,(READ.PointerOnBuffer)
LD DE,(CORE_BUFFERS.FS_Buffer.BytesPerSector)
.loop3: ADD HL,DE
DEC C
JR NZ,.loop3
LD (READ.PointerOnBuffer),HL
POP DE ; ­®¬¥à á«¥¤. ª« áâ¥à  (¬« ¤è¥¥ á«®¢®)
EXX
POP HL ; ­®¬¥à á«¥¤. ª« áâ¥à  (áâ à襥 á«®¢®)
EXX
JP .loop4
;
.Error: POP BC
POP DE
POP HL
;SCF
RET
;
.ECL1: AND A
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; WRITE SECTORS OF FILE
; ¢å®¤: HL:DE - FP (in sectors)
; IX - data in RAM
; IY - FM
; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï § ¯¨á¨
BLOCK_WRITE: LD (READ.PointerOnBuffer),IX
LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster) ;SECTORS PER CLUSTER
LD C,A
PUSH BC ; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï, C - SectorsPerCluster
; HL:DE / A => DE:BC, H=0, L - ®áâ â®ª
CALL DIV_by_Shifts
PUSH HL ; ®áâ â®ª DIV_by_Shifts
;[x] GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
PUSH BC ; ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
PUSH DE ; fat32 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
;
CALL CHECK_FIRST_CLUSTER
JR NZ,.FindCluster
;
PUSH BC ; ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
PUSH DE ; fat32 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
; [x] fat32
CALL G_CLUST
JP C,.Error_6
;
LD (IY+_sFM.FS_REC.FIRST_CLUSTER_L),L
LD (IY+_sFM.FS_REC.FIRST_CLUSTER_L+1),H
; [x] fat32
EXX
LD (IY+_sFM.FS_REC.FIRST_CLUSTER_H),L ; START CLUSTER High
LD (IY+_sFM.FS_REC.FIRST_CLUSTER_H+1),H
EXX
;
XOR A
CALL SET_NEW_FREE_CLUSTERS
;
CALL WRITE_TO_FAT
; 02/12/23 ; [ ] ¡ £ á ¨§¡ëâ®ç­®© § ¯¨áìî WRITE_FAT_TABLE?
;PUSH HL
;CALL WRITE_FAT_TABLE ; ¯®¤ª«. ¡ ­ªã ª¥è  FAT ¨ § ¯¨á âì ¥£® ­  ¤¨áª
;POP HL
;
POP DE ; ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
POP BC ; fat32 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
;
INC B
INC D ; fat32
PUSH DE
JP .enter_loop
;[x] GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
.FindCluster: CALL GetSavedCluster
;HL': HL - ¨§¢¥áâ­ë© ª« áâ¥à ä ©«  ¤«ï ®âáçñâ 
;DE : BC - ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (D=D+1, B=B+1)
;
PUSH DE ; ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (áâ à襥 á«®¢®)
JP .enter_loop
;
; [x] fat32
.loop_big: PUSH BC
LD BC,0
.loop: PUSH BC
CALL READ_FROM_FAT
JR NC,.next
; end of chain - get new cluster
CALL INC_FAT
JP C,.Error_6
; [x] ¨§¡ëâ®ç­®¥ ®¡à é¥­¨¥ 01/04/2024
;CALL READ_FROM_FAT
;
.next: POP BC
EX DE,HL
EXX
EX DE,HL
EXX
.enter_loop: INC B
DEC BC
DJNZ .loop
POP BC ; ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (áâ à襥 á«®¢®)
INC B
DEC BC
DJNZ .loop_big
;;;;
;
;[x] GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
POP DE
POP BC
CALL SaveGotCluster
;
POP DE ; D = 0, E = ®áâ â®ª DIV_by_Shifts
POP BC ; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï, C - SectorsPerCluster
; (SP) = (RET)
;
LD A,C
SUB E
LD C,A
CP B ; (SectorsPerCluster - ®áâ â®ª) - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï
JR C,.skip1 ;SIZE > RESIDUE CLUSTER
LD C,B ;SIZE < CLUSTER
.skip1: LD A,B
SUB C
LD B,A
;
EXX
PUSH HL ; ­®¬¥à ª« áâ¥à  áâ àè ï ç áâì
EXX
PUSH HL ; ­®¬¥à ª« áâ¥à  ¬« ¤è ï ç áâì
PUSH BC ; B = ª®«¨ç¥á⢮ ᥪâ®à®¢ ­  ¤®ç¨âªã, C = (SectorsPerCluster - ®áâ â®ª) «¨¡® ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï
PUSH DE ; D = 0, E = ®áâ â®ª DIV_by_Shifts
CALL CLUSTER_TO_SECTOR
POP DE ; D = 0, E = ®áâ â®ª DIV_by_Shifts
ADD IX,DE
JR NC,.skip2
INC HL
; DOUBLE 1
.skip2: LD DE,(READ.PointerOnBuffer)
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE)
LD B,C
LD C,Dss.DRV.Write
RST ToDSS.DRV
;
LD A,DSS_Error.sys.WRITE_ERROR
JR C,.Error_3
POP BC
LD HL,(READ.PointerOnBuffer)
LD DE,(CORE_BUFFERS.FS_Buffer.BytesPerSector)
;
LD A,B
LD B,C
.loop2: ADD HL,DE
DJNZ .loop2
;
LD (READ.PointerOnBuffer),HL
POP DE ; ­®¬¥à ª« áâ¥à  ¬« ¤è ï ç áâì
EXX
POP HL ; ­®¬¥à ª« áâ¥à  áâ àè ï ç áâì
EXX
;
OR A
RET Z ; ª®«¨ç¥á⢮ ᥪâ®à®¢ ­  ¤®ç¨âªã = 0?
LD B,A
;
.big_loop: LD HL,CORE_BUFFERS.FS_Buffer.SectorsPerCluster
LD A,B
SUB (HL)
LD B,A
LD C,(HL)
JR NC,.WR7
LD B,0
ADD A,(HL) ;0 AND CF
LD C,A
OR A ;CLEAR CF
RET Z
;
.WR7: EX DE,HL
PUSH BC
; HL':HL - ­®¬¥à ª« áâ¥à 
CALL READ_FROM_FAT
JR NC,.WR9
CALL INC_FAT
JR C,.ErrorFull
; [x] ¨§¡ëâ®ç­®¥ ®¡à é¥­¨¥ 01/04/2024
;CALL READ_FROM_FAT
;
.WR9: POP BC
EXX
EX DE,HL
PUSH HL ; ­®¬¥à á«¥¤. ª« áâ¥à  (áâ à襥 á«®¢®)
EXX
EX DE,HL
PUSH HL ; ­®¬¥à á«¥¤. ª« áâ¥à  (¬« ¤è¥¥ á«®¢®)
PUSH BC
CALL CLUSTER_TO_SECTOR
; DOUBLE 1
LD DE,(READ.PointerOnBuffer)
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE)
LD B,C
LD C,Dss.DRV.Write
RST ToDSS.DRV
;
LD A,DSS_Error.sys.WRITE_ERROR
JR C,.Error_3
POP BC
LD HL,(READ.PointerOnBuffer)
LD DE,(CORE_BUFFERS.FS_Buffer.BytesPerSector)
.loop3: ADD HL,DE
DEC C
JR NZ,.loop3
LD (READ.PointerOnBuffer),HL
POP DE ; ­®¬¥à á«¥¤. ª« áâ¥à  (¬« ¤è¥¥ á«®¢®)
EXX
POP HL ; ­®¬¥à á«¥¤. ª« áâ¥à  (áâ à襥 á«®¢®)
EXX
JP .big_loop
;
.Error_6: POP BC
POP BC
POP BC
.Error_3: POP BC ;[x] GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
POP BC
POP DE
;SCF
RET
;
.ErrorFull: POP BC
LD A,DSS_Error.sys.DISK_FULL
;SCF
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
; ‚室: DE - ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (áâ à襥 á«®¢®)
; BC - ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (¬« ¤è¥¥ á«®¢®)
; HL - ¯¥à¢ë© ª« áâ¥à ä ©«  (¬« ¤è¥¥ á«®¢®)
; HL' - ¯¥à¢ë© ª« áâ¥à ä ©«  (áâ à襥 á«®¢®)
; ‚ë室: HL - ¨§¢¥áâ­ë© ª« áâ¥à ä ©«  ¤«ï ®âáçñâ  (¬« ¤è¥¥ á«®¢®)
; HL' - ¨§¢¥áâ­ë© ª« áâ¥à ä ©«  ¤«ï ®âáçñâ  (áâ à襥 á«®¢®)
; DE - ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (áâ à襥 á«®¢®, D=D+1)
; BC - ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (¬« ¤è¥¥ á«®¢®, B=B+1)
; ­¥ ¯®àâ¨â HL, HL' ¨ DE:BC ¥á«¨ ®¯â¨¬¨§ æ¨ï ­¥ áà ¡®â « 
GetSavedCluster:
XOR A
CP (IY+_sFM.OptimizedClusters)
JR Z,.noOptimization_0
;
PUSH DE
PUSH HL ; ¯¥à¢ë© ª« áâ¥à ä ©«  (¬« ¤è¥¥ á«®¢®)
; ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å
EX DE,HL
LD E,(IY+_sFM.KnownOffset_H)
LD D,(IY+_sFM.KnownOffset_H+1)
; ¯à®¢¥àª  áâ à襣® á«®¢ 
AND A
SBC HL,DE
JR C,.noOptimization_2
;
PUSH BC
EX DE,HL
LD H,B
LD L,C
LD C,(IY+_sFM.KnownOffset_L)
LD B,(IY+_sFM.KnownOffset_L+1)
; ¯à®¢¥àª  ¬« ¤è¥£® á«®¢ 
SBC HL,BC
LD BC,0
EX DE,HL
SBC HL,BC
JR C,.noOptimization_3
EX DE,HL
LD B,H
LD C,L
; DE:BC ­®¢®¥ ᬥ饭¨¥ ®â ¨§¢¥áâ­®£® ª« áâ¥à  ä ©«  (¢ ª« áâ¥à å)
;
LD L,(IY+_sFM.KnownCluster_L)
LD H,(IY+_sFM.KnownCluster_L+1)
EXX
LD L,(IY+_sFM.KnownCluster_H)
LD H,(IY+_sFM.KnownCluster_H+1)
EXX
; ¡ « ­á á⥪ 
POP AF
POP AF
POP AF
; ¤«ï 横«  DJNZ
INC B
INC D
RET
;
.noOptimization_3:
POP BC
.noOptimization_2:
POP HL
.noOptimization_1:
POP DE
.noOptimization_0:
INC B
INC D
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
SaveGotCluster: LD A,C
OR B
OR E
OR D
RET Z
;
LD (IY+_sFM.KnownOffset_L),C
LD (IY+_sFM.KnownOffset_L+1),B
LD (IY+_sFM.KnownOffset_H),E
LD (IY+_sFM.KnownOffset_H+1),D
;
LD (IY+_sFM.KnownCluster_L),L
LD (IY+_sFM.KnownCluster_L+1),H
EXX
LD (IY+_sFM.KnownCluster_H),L
LD (IY+_sFM.KnownCluster_H+1),H
EXX
;
LD A,1
LD (IY+_sFM.OptimizedClusters),A
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;<3B> áçñâ ᬥ饭¨ï ¢ ᥪâ®à å ;!HARDCODE sector size
GET_OFFSET_IN_SECTORS:
LD H,0 ;!HARDCODE max file size = 8 gb
LD E,(IY+_sFM.F_POSITION+1)
LD D,(IY+_sFM.F_POSITION+2)
LD L,(IY+_sFM.F_POSITION+3)
LD A,E
AND #01
LD B,A
LD C,(IY+_sFM.F_POSITION)
RR L
RR D
RR E
;HL:DE FP (in sectors)
;BC FP residue (in bytes)
OR C
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; 26/06/2024 {64 kb cluster} read only 64kb cluster ; !TODO cluster 64kb
CHECK_64kb_CLUSTER:
LD HL,(CORE_BUFFERS.FS_Buffer.BytesPerCluster)
; CF=0
ADC HL,HL
LD A,DSS_Error.sys.WRITE_PROTECT
RET NZ
CCF
RET
;----------------------------------------------------------------------;
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
; „¨à¥ªâ®à¨¨/” ©«ë
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
;----------------------------------------------------------------------;
; [ ] 㤠«¥­¨¥ § ¯¨á¨ LFN
;
; ¢å®¤: IX = 㪠§ â¥«ì ­  ⥪ãéãî § ¯¨áì ¢ áâà ­¨æ¥ á ª â «®£®¬ FAT ¤«ï ª®â®à®©
; ­ ¤® 㤠«¨âì § ¯¨á¨ LFS
; [ ] big dir
DELETE_LFN_RECORDS:
PUSH IX
LD A,XH
AND #C0
DEC A
;SUB 1
LD C,A
; ॣ¨áâॠC ¬ áª  ¤«ï ®¯à¥¤¥«¥­¨ï ¢ë室  §  ¯à¥¤¥«ë áâà ­¨æë
;
.find_LFN: LD DE, -(FAT_DIRECTORY_RECORD)
LD A,FAT_ATTR.LFS_Entry
;
.loop: ADD IX,DE
LD A,XH
CP C
JR Z,.beyond_boundaries ; [ ] big dir âãâ ­ ¤® ¯®¤£à㦠âì ¯à¥¤ë¤ã騩 DirBlock
;
LD A,FAT_ATTR.LFS_Entry
CP (IX+FAT_DIRECTORY_RECORD.ATTRIBUT)
JR NZ,.exit
LD (IX+FAT_DIRECTORY_RECORD.NAME),#E5
JR .loop
;
.exit: AND A
.beyond_boundaries: ; !TODO ¯®¤£à㧪  ¤à㣮© ç á⨠ª â «®£ . ¯®ª  § £«ã誠
POP IX
RET
;----------------------------------------------------------------------;
; [ ] big dir £à㧨âì âãâ ­ ç «ì­ãî áâà ­¨æã ¢ dir cache ¨«¨ ¯¥à¥¤ ¢ë§®¢®¬?
; [ ] big dir ¢á¥£¤  «¨ ¯à¨ ¢ë§®¢¥ ã ­ á ¯à ¢¨«ì­ë¥ (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L ¨ H) ¤«ï LOADDIR?
;----------------------------------------------------------------------;
; <20>®¨áª § ¯¨á¨ ª â «®£  ¢ ᯨ᪥ ª â «®£ 
; ¢å®¤: A =  âਡãâ § ¯¨á¨ (.Custom)
; (CORE_BUFFERS.MASKARE) - ¬ áª  ¤«ï ¯®¨áª 
; ¢ë室: DE - ¨­¤¥ªá § ¯¨á¨ ¢ ᯨ᪥ ª â «®£ 
; IX -  ¤à¥á ­ ©¤¥­®© § ¯¨á¨ ¢ SLOT3
; (HANDBUF) = file's directory record
; CF - ª â «®£ ­¥ ­ ©¤¥­
SEARCH:
.Dir: ;LD A,FAT_ATTR.DIRECTORY
LD A,FAT_ATTR.HiddenSysDir
CALL .Custom
RET NC
CP DSS_Error.sys.PATH_NOT_FOUND + 1
RET C
;
SCF
LD A,DSS_Error.sys.TOO_MANY_FILES_IN_DIR
RET
;
.File: LD A,FAT_ATTR.NoDIRnoVolID
.Custom: EX AF,AF' ; A = 76ADLSHR
SET_PAGE_X DIRPAGE
PUSH AF
EX AF,AF'
CPL
CALL SEARCH_RECORD_IN_DIR_CACHE
.for_F_NEXT: JR C,.error
;
LD D,XH
LD E,XL
LD HL,CORE_BUFFERS.HANDBUF
EX DE,HL
LD BC,CORE_BUFFERS.HANDBUF.SIZE
LDIR
POP AF
OUT (SLOT3),A
AND A
EXX ; record index
RET
;
.error: POP AF
OUT (SLOT3),A
LD A,DSS_Error.sys.FILE_NOT_FOUND
SCF
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
SEARCH_RECORD_IN_DIR_CACHE:
;CPL
LD C,A
LD A,(CORE_BUFFERS.FS_Buffer.DirBlock)
LD (.StartPage),A
SLA A
;!TEST 9/11/23 record index
EXX
LD D,A
LD E,0
EXX
;
.loop_big: LD IX,DIRPAGE.buffer
.loop: LD A,(IX + FAT_DIRECTORY_RECORD.NAME)
OR A
SCF
RET Z ; not found
;
CP #E5 ;!HARDCODE #E5 - § ¯¨áì ¢ ¤¨à¥ªâ®à¨¨ ᢮¡®¤­ , â ª ª ª ä ©«/¤¨à¥ªâ®à¨ï ¡ë«¨ 㤠«¥­ë
JR Z,.next_record
;
LD A,(IX + FAT_DIRECTORY_RECORD.ATTRIBUT)
LD D,A
AND C
.type+0: JR NZ,.next_record
;
LD A,C
INC A
JR NZ,.found_attr
; A=0
OR D
JR NZ,.next_record
;
.found_attr: LD HL,CORE_BUFFERS.MASKARE
LD D,XH
LD E,XL
LD B,11 ;!HARDCODE dos name not LFN
EX DE,HL
;
.loop_compare: LD A,(DE)
CP '?'
JR Z,.next_char
;
CP (HL)
;JR NZ,.next_record
JR Z,.next_char
;
.next_record: ;!TEST 9/11/23 record index
EXX
INC DE
EXX
;
LD DE,FAT_DIRECTORY_RECORD
ADD IX,DE
JR NC,.loop
;
; CF=1
; !FIXIT root dir in LOADDIR
; !FIXIT ¥á«¨ ¢ ªíè ¡ë«¨ ¨§¬¥­¥­¨ï?
.readDirNext: PUSH BC
EXX
PUSH DE ; record index
EX DE,HL
CALL LOADDIR.next
POP DE
EXX
POP BC
;JR NC,.loop_big ; !FIXIT ¬®¦¥â ¡ëâì ®è¨¡ª  ç⥭¨ï ¨«¨ ¯à¨ ZF - ª®­¥æ ¤¨à¥ªâ®à¨¨
;RET
RET C
;
; ¯®«­ë© ®¡å®¤ ª â «®£  ­ ç¨­ ï á § £à㦥­­®© áâà ­¨æë
LD A,(CORE_BUFFERS.FS_Buffer.DirBlock)
AND A
JR NZ,.toStartPage
;
EXX
LD DE,0
EXX
.toStartPage: ;
.StartPage+1: CP 0
JR NZ,.loop_big
;
SCF
RET
;
.next_char: INC HL
INC DE
DJNZ .loop_compare
; CF=0
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------; 20 28
; FIND "MASKAREA" IN DIRECTORY
; ¢ë室: IY:DE - cluster number
; [ ] big dir ¢á¥£¤  «¨ ¯à¨ ¢ë§®¢¥ ã ­ á ¯à ¢¨«ì­ë¥ (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L ¨ H) ¤«ï LOADDIR?
FINDDIR: SET_PAGE_X DIRPAGE
;
PUSH AF
;
;LD A,(CORE_BUFFERS.FS_Buffer.DirBlock)
;AND A
;CALL NZ,LOADDIR ;!FIXIT check error
;
LD A,#28 ; JR Z,...
LD (SEARCH_RECORD_IN_DIR_CACHE.type),A ; search directory
LD A,FAT_ATTR.DIRECTORY
CALL SEARCH_RECORD_IN_DIR_CACHE
EX AF,AF
LD A,#20 ; JR NZ,...
LD (SEARCH_RECORD_IN_DIR_CACHE.type),A ; search
EX AF,AF
JR C,.error
;
LD A,(IX + FAT_DIRECTORY_RECORD.NAME)
CP "."
JP NZ,.ADDSPEC
LD A,(IX + FAT_DIRECTORY_RECORD.NAME + 1)
CP "."
JP NZ,.ITs_DIR
;
LD HL,CORE_BUFFERS.WorkDirectory
LD D,H
LD E,L
INC HL
LD BC,CORE_BUFFERS.WorkDirectory.DEPTH
XOR A
CPIR
JP PO,.error ;[x] 20/11/23 ¯à®¢¥àª  ­  ¢ë室 §  £à ­¨æë
;
DEC HL ;R009
DEC HL
LD BC,CORE_BUFFERS.WorkDirectory.DEPTH
LD A,'\'
CPDR
INC HL
EX DE,HL
; CF = 0
SBC HL,DE
EX DE,HL
JR NZ,.MM3
;
INC HL
.MM3: LD (HL),0
JP .ITs_DIR
;
.error: POP AF
OUT (SLOT3),A
LD A,DSS_Error.sys.PATH_NOT_FOUND
SCF
RET
;
.ADDSPEC: LD HL,CORE_BUFFERS.WorkDirectory+1
LD BC,CORE_BUFFERS.WorkDirectory.DEPTH-1
CALL .CHECK_SLASH
JR C,.error
;R011
LD A,B
AND A
JR NZ,.nxt
LD A,C
CP 8+1+3 ;!HARDCODE ¨¬ï ª â «®£  + â®çª  + à áè¨à¥­¨¥
JR C,.error
.nxt: ;
LD E,XL
LD D,XH
; [x] ®¯â¨¬¨§ æ¨ï ¯® à §¬¥àã
EX DE,HL
CALL GetName
EX DE,HL
;
.ITs_DIR: ; fat32
LD E,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H)
LD D,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H+1)
LD YH,D
LD YL,E
LD E,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L)
LD D,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L+1)
POP AF
OUT (SLOT3),A
AND A
RET
;
.CHECK_SLASH: XOR A
CPIR
;[x] 20/11/23 ¯à®¢¥àª  ­  ¢ë室 §  £à ­¨æë
SCF
RET PO
;
DEC HL
DEC HL
LD A,'\' ; #5C
CP (HL)
INC HL
RET Z
;
LD (HL),A
INC HL
XOR A ; á¡à®á CF § ®¤­®
LD (HL),A
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ‚室: IY - 㪠§ â¥«ì ­  ­ ç «® ä ©«®¢®£® ¬ ­¨¯ã«ïâ®à 
CHECK_ROOT_CLUSTER:
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x32
JR NZ,CHECK_FIRST_CLUSTER
;
LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L)
LD BC,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L)
SBC HL,BC
RET NZ
;
LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H)
LD BC,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H)
SBC HL,BC
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ¢å®¤: IY - 㪠§ â¥«ì ­  ­ ç «® ä ©«®¢®£® ¬ ­¨¯ã«ïâ®à 
; ¢ë室: HL':HL - first cluster
; ZF = 0 ¥á«¨ ¯¥à¢®£® ª« áâ¥à  ­¥â
CHECK_FIRST_CLUSTER:
EXX
LD L,(IY+_sFM.FS_REC.FIRST_CLUSTER_H) ; START CLUSTER High
LD H,(IY+_sFM.FS_REC.FIRST_CLUSTER_H+1)
LD A,L
OR H
EXX
LD L,(IY+_sFM.FS_REC.FIRST_CLUSTER_L) ; START CLUSTER
LD H,(IY+_sFM.FS_REC.FIRST_CLUSTER_L+1)
OR L
OR H
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ¢å®¤: HL - ¨¬ï ¤¨à¥ªâ®à¨¨
OPENDIR: ; init
;EX DE,HL
;XOR A
;LD H,A
;LD L,A
;LD (CORE_BUFFERS.FS_Buffer.DirBlockDrive),A
;LD (CORE_BUFFERS.FS_Buffer.DirBlockStartCluster_L),HL
;LD (CORE_BUFFERS.FS_Buffer.DirBlockStartCluster_H),HL
;IF DIR_BLOCK_CACHE_OPTIMIZE
; LD (CORE_BUFFERS.FS_Buffer.DIR_BLOCK_CHANGES),HL
; LD (CORE_BUFFERS.FS_Buffer.DIR_BLOCK_CHANGES + 2),HL
;ENDIF
;EX DE,HL
;
LD IY,CORE_BUFFERS.FM_BUF
LD A,(HL)
OR A
JR NZ,.SUBDIR
; REROOT
EX DE,HL
LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L)
LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL
LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H)
LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),HL
EX DE,HL
.reroot: CALL LOADDIR ; [ ] big dir
; CF=0
LD HL,CORE_BUFFERS.WorkDirectory
LD (HL),'\'
INC HL
LD (HL),#00
;AND A
RET
;
.SUBDIR: CP "."
JR NZ,.SUBDIR2
; fat32
; !TEST 04/01/2026
EX DE,HL
CALL CHECK_ROOT_CLUSTER
;CALL CHECK_FIRST_CLUSTER
EX DE,HL
;
JR NZ,.no_root ;R005
; "cd ." or "cd .."
;R005
INC HL
LD A,(HL)
OR A
DEC HL
JR Z,.reroot
;
.no_root: EXX
LD HL,CORE_BUFFERS.MASKARE
LD DE,CORE_BUFFERS.MASKARE+1
LD BC,10 ;!HARDCODE
LD (HL),' '
LDIR
EXX
LD DE,CORE_BUFFERS.MASKARE
.loop: LDI
LD A,(HL)
OR A
JR NZ,.loop
JR .SUBDIR3
;
.SUBDIR2: ;EX DE,HL
CALL MASK.name
RET C
; fat32
.SUBDIR3: CALL FINDDIR
RET C
;
EX DE,HL
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x32
JR NZ,.setCluster
; [ ] big dir
LD A,H
OR L
OR YH
OR YL
JR NZ,.setCluster
; set root dir for fat32
LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L)
LD IY,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H)
.setCluster: LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL
LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),IY ; fat32
;
;-------------; JP LOADDIR
;----------------------------------------------------------------------;
;!TODO optimize
; <20>à®ç¨â âì ᯨ᮪ ª â «®£ 
; ‚室: (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L), (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H)
LOADDIR: LD HL,0 ;!FIXIT ¥á«¨ HL ¢ë©¤¥â §  à §¬¥àë ¤¨à¥ªâ®à¨¨ ¨ DirBlock ¡ã¤¥â ­¥ª®à४â­ë¬?
;[-------------]
; ‚室: HL - ID § ¯¨á¨, ª®â®àë© ¤®«¦¥­ ¯®¯ áâì ¢ Š<>˜
; (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L), (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H)
.Custom: AND A ; ¢ LOAD_SAVE_DIR_PREPARE ¯®áç¨â ¥âáï à §¬¥à ª â «®£  ¤¨à¥ªâ®à¨¨
;[-------------]
; ‚室: HL - ID § ¯¨á¨, ª®â®àë© ¤®«¦¥­ ¯®¯ áâì ¢ Š<>˜
; (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L), (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H)
; CF - ­¥ à ááç¨â뢠âì à §¬¥à ¤¨à¥ªâ®à¨¨
.next: CALL LOAD_SAVE_DIR_PREPARE
PUSH AF
EX AF,AF'
JR Z,.LoadRootDirFAT12_16
;
.read_dir: LD HL,DIRPAGE.buffer ; ªã¤ 
LD DE,DIRPAGE.size ; ᪮«ìª®
XOR A ; ¤¥áªà¨¯â®à
CALL READ ; ç⥭¨¥ ¨§ ä ©« 
EX AF,AF'
LD (SAVEDIR.DirBlkSize),DE ; ç¨á«® ¯à®ç¨â. ¡ ©â®¢
POP AF
OUT (SLOT3),A
EX AF,AF'
RET C
; ¥á«¨ DE = 0
; (A == FF) & (DE == 0) - ¢ ¯à®è«ë© à § ¯à®ç¨â «¨ ¤® ª®­æ 
;
LD A,D
OR E
RET NZ
; ç¨â ¥¬ á ­ ç « 
JR LOADDIR
; .no_more: LD A,#FF
; SCF
; RET
;
.LoadRootDirFAT12_16:
; [ ] big dir
LD A,(CORE_BUFFERS.FS_Buffer.DirBlock)
AND A
JR Z,.ok
;
XOR A
LD (CORE_BUFFERS.FS_Buffer.DirBlock),A
RET
;
;
.ok: LD HL,(CORE_BUFFERS.FS_Buffer.RootDirFirstSector_H);!TODO ¢®§¬®¦­®, 墠â¨â LD HL,0
LD IX,(CORE_BUFFERS.FS_Buffer.RootDirFirstSector_L); ­®¬¥à «®£. ᥪâ®à 
LD A,(CORE_BUFFERS.FS_Buffer.DirSizeInSectors)
LD B,32 ; !HARDCODE sector size 512. 16384/(sector 512). à §¬¥à root-ª â «®£  ; [ ] sector size 512
CP B
JR NC,.RTD1
;
LD B,A ; ç¨á«® ᥪâ®à®¢
.RTD1: LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) ; ­®¬¥à ¤¨áª 
LD DE,DIRPAGE.buffer ; ¡ãä¥à
LD C,Dss.DRV.Read ; ç⥭¨¥ ᥪâ®à®¢
RST ToDSS.DRV
; !FIXIT ­¥â ¯à®¢¥àª¨ ­  ®è¨¡ªã
; 21/04/2025 fix ¬ãá®à ¢ áâà ­¨æ¥ ª â «®£ , ¥á«¨ ª â «®£ ¬¥­ìè¥ áâà ­¨æë
BIT 7,D
JR Z,.exit
XOR A
LD (DE),A
;
.exit: POP AF
OUT (SLOT3),A
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ‚室: HL - ID § ¯¨á¨, ª®â®àë© ¤®«¦¥­ ¯®¯ áâì ¢ Š<>˜
; ‚ë室: HLIX - ᬥ饭¨¥ ¢ ä ©«¥ ª â «®£  ­  ­ã¦­ë© ¡«®ª ¯® #4000 ¡ ©â®¢
; A - <20>®¬¥à ¡«®ª  DirBlock
; GET_DIRCACHE_BLOCK_ADDR:
; ; HLIX = (HL*32) & #1FC000 ᬥ饭¨¥ ­  ­ã¦­ë© ¡«®ª ¯® #4000 ¡ ©â®¢
; XOR A
; LD XL,A
; LD E,A
; LD A,H
; LD H,E
; AND #FE
; RRA
; RR E
; LD D,A ; DirBlock
; RRA
; RR E
; RRA
; RR E
; LD XH,E
; LD L,A
; LD A,D
; RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; [ ] ¤®¤¥« âì ¯¥à¥¤ çã ID § ¯¨á¨ ¤¨à¥ªâ®à¨¨ ¨ § £à㧪¨ ¯® ­¥© ­ã¦­®£® ªã᪠ ¢ ªíè
;!TODO FAT procedures
;----------------------------------------------------------------------;
; ‚室: HL - ID § ¯¨á¨, ª®â®àë© ¤®«¦¥­ ¯®¯ áâì ¢ Š<>˜
; CF - ­¥ áç¨â âì à §¬¥à ª â «®£  ¤¨à¥ªâ®à¨¨ (¯à¨ ¯¥à¢®¬ ®âªàë⨨)
; ‚ë室: A - ‘âà ­¨æ , ª®â®à ï ¡ë«  ¢ SLOT3 ¤® ¢ë§®¢ 
; ZF' - RootDir FAT12-16
LOAD_SAVE_DIR_PREPARE:
PUSH AF
;CALL GET_DIRCACHE_BLOCK_ADDR
;LD (CORE_BUFFERS.FS_Buffer.DirBlock),A
; HLIX = (HL*32) & #1FC000 ᬥ饭¨¥ ­  ­ã¦­ë© ¡«®ª ¯® #4000 ¡ ©â®¢
XOR A
LD XL,A
LD E,A
LD A,H
LD H,E
AND #FE
RRA
RR E
LD (CORE_BUFFERS.FS_Buffer.DirBlock),A
RRA
RR E
RRA
RR E
LD XH,E
LD L,A
;
XOR A ; FILE MANIPULATOR = 0
LD B,A ; ®â ­ ç «  ä ©« 
CALL MOVE_FP
SET_PAGE_X DIRPAGE
POP DE
AND A
PUSH AF
;
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE)
LD (CORE_BUFFERS.FM_BUF.DRIVE),A
; check fat12-16 root dir
XOR A
LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L)
EXX
LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H)
OR H
OR L
EXX
OR H
OR L
JR Z,.exit
;
PUSH AF
SRL E
CALL NC,.CalcDirSize
POP AF
.exit: EX AF,AF'
POP AF
RET
;
; calc dir size in clusters
.CalcDirSize: LD DE,0
.loop: INC DE ; <20> ¤¥¥¬áï âãâ ­  â®, ç⮠ᯥæ¨ä¨ª æ¨ï ¢ë¯®«­ï¥âáï ¨ ¯¥à¥¯®«­¥­¨ï ­¥ ¡ã¤¥â
PUSH DE
CALL READ_FROM_FAT
EX DE,HL
POP DE
EXX
EX DE,HL
EXX
JR NC,.loop
;
; DE - à §¬¥à ¤¨à¥ªâ®à¨¨ ¢ ª« áâ¥à å
;!FIXIT ¬®¦­® ®¯â¨¬¨§­ãâì ª®«-¢® ᤢ¨£®¢
;0001 0000 0000 0000 max ª®«-¢® ª« áâ¥à®¢
; ¯à¨¬¥à
;0000 0000 0000 0111 Clusters
; 0100 0000 SectorsPerCluster
;0000 0010 0000 0000 BytesPerSector
; D' E' D E
;0000 0000 0000 0011 1000 0000 0000 0000
;
LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster)
LD BC,(CORE_BUFFERS.FS_Buffer.BytesPerSector)
; DE':DE - ª®«-¢® ª« áâ¥à®¢
; A - à §¬¥à ª« áâ¥à  ¢ ᥪâ®à å
; BC - à §¬¥à ᥪâ®à  ¢ ¡ ©â å
; --> DE*BC*A = DE':DE ¤«ï ®â¢¥â  墠â¨â, ¯®å®¤ã, 4å ॣ¨áâ஢
EXX
LD DE,0
EXX
SRL B
RR C
RRCA
JR C,.loop2
;
.loop1: SLA E
RL D
EXX
RL E
RL D
EXX
RRCA
JR NC,.loop1
;
.loop2: SLA E
RL D
EXX
RL E
RL D
EXX
;
SRL B
RR C
JR NC,.loop2
; <-- DE*BC*A = DE':DE
LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),DE
EXX
LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE + 2),DE
RET
/* ¯à¨¬¥à 4 3 2 1
#FFFF<<5 = #1FFFE0 = 0000 0000 0001 1111 1111 1111 1110 0000
#FFFF ­®¬¥à § ¯¨á¨
#1FFFE0 ᬥ饭¨¥ ­  § ¯¨áì ¢ ä ©«¥ ¤¨à¥ªâ®à¨¨
#1FFFE0 & #1FC000 ᬥ饭¨¥ ­  ­ã¦­ë© ¡«®ª ¯® #4000 ¡ ©â®¢
#1FFFE0 & #3FFF ¤à¥á ­ã¦­®© ¯®§¨æ¨¨ ¢ ªíè
(#1FFFE0 & #1FC000)<<2 ¤¢¨£ ¥¬ ¡ ©â 2 ¨ 3 ç⮡ ¯®«ãç¨âì ­®¬¥à ¡«®ª 
*/
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;!TODO optimize
;!TODO .DIRSIZE ¯®¬¥è ¥â ¥á«¨ ¢ ªíè ¡ã¤¥â ¤à㣠ï áâà ­¨æ ?
;!TODO LOAD_SAVE_DIR_PREPARE ¢®§¬®¦­® ­¥ ­ã¦¥­, ­ã¦­® ⮫쪮 ãáâ ­®¢¨âì ¯à ¢¨«ì­®¥ ᬥ饭¨¥ ¢ FM
;!TODO Œ®¦¥â ¢®®¡é¥ ¯¥à¥¤¥« âì ¥ñ ¯®¤ à ¡®âã á Š<>˜
;!TODO ; [ ] big dir ¯®«ãç âì ®âªã¤  ¨ ᪮«ìª® ¡ ©â®¢ ¨§¬¥­¨«®áì ¢ ªíè, ç⮡ ­¥ ¯¨á âì ­  ¤¨áª «¨è­¥£®
;
; ‘¡à®á¨âì ª¥è ª â «®£  ­  ¤¨áª.
; ¢å®¤: HL - ID § ¯¨á¨, ª®â®à ï ¨§¬¥­¨« áì ¢ Š<>˜
; ¢ ªíè ¤®«¦­  ¡ëâì ª®à४⭠ï áâà ­¨æ  ¤¨à¥ªâ®à¨¨, DirBlkSize ª®à४â­ë© ⮦¥
SAVEDIR: SCF ; ­¥ áç¨â âì à §¬¥à ¤¨à¥ªâ®à¨¨
CALL LOAD_SAVE_DIR_PREPARE
PUSH AF
EX AF,AF'
JR Z,.SaveRootDir
;
.save_dir: LD HL,DIRPAGE.buffer
; à §¬¥à ᯨ᪠ ª â «®£  size_cash_directory
;!FIXIT ¥á«¨ ®­  ­ã¦­ , â® ¯à®¢¥à¨âì ­  ¡ £¨ (­ ¯à¨¬¥à, à §¬¥à ¤¨à४â®à¨¨ ¬¥­ìè¥ ¯à¨ ®âªàë⨨ ¨ ¡®«ìè¥ ¯®á«¥ ¯à ¢®ª)
; ª®£¤  ¡ã¤¥â ç⥭¨¥ ªã᪠¬¨ ª â «®£  ¢ ªíè, âãâ ¥éñ áçñâ稪 ¯à¨ªàãâ¨âì
.DirBlkSize+1: LD DE,0
XOR A ; FM
CALL WRITE
POP AF
OUT (SLOT3),A
RET
;
; FAT12-16
.SaveRootDir: LD HL,(CORE_BUFFERS.FS_Buffer.RootDirFirstSector_H) ;!TODO ¢®§¬®¦­®, 墠â¨â LD HL,0
LD IX,(CORE_BUFFERS.FS_Buffer.RootDirFirstSector_L)
LD A,(CORE_BUFFERS.FS_Buffer.DirSizeInSectors)
LD B,32 ;!HARDCODE sector size 512, Root Dir max size in sectors
SUB B
JR NC,.RTD1S
;
ADD A,B
LD B,A
.RTD1S: LD A,(CORE_BUFFERS.FS_Buffer.DRIVE)
LD DE,DIRPAGE.buffer
LD C,Dss.DRV.Write
RST ToDSS.DRV
POP AF
OUT (SLOT3),A
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; [ ] big dir
; ᪮¯¨à®¢ âì § ¯¨áì ¢ ᯨ᮪ ¤¨áª  (ª â «®£ ) de ix iy
; ¨ á¡à®á¨âì ª¥è ª â «®£  ­  ¤¨áª
; ¢å®¤: (HANDBUF) - § ¯¨áì ª â «®£ 
; ¢ë室: DE - record index
WRITE_DIR_HANDLE:
SET_PAGE_X DIRPAGE
EX AF,AF'
LD HL,DIRPAGE.buffer
;!TEST 9/11/23 record index
EXX
LD DE,0
EXX
;
LD BC,FAT_DIRECTORY_RECORD
.loop: ;LD A,(IX+00)
LD A,(HL)
OR A
JR Z,.WRT_HN2
CP #E5
JR Z,.WRT_HN2
;ADD IX,BC
ADD HL,BC
JR NC,.loop ;!FIXIT ª®«¨ç¥á⢮ § ¯¨á¥© ª â «®£  = áâà ­¨æ 
;
EX AF,AF'
OUT (SLOT3),A
LD A,DSS_Error.sys.ROOT_OVERFLOW
SCF
RET
;
.WRT_HN2: ;LD D,XH
;LD E,XL
EX DE,HL
LD HL,CORE_BUFFERS.HANDBUF
LD BC,CORE_BUFFERS.HANDBUF.SIZE
LDIR
EX AF,AF'
OUT (SLOT3),A
; ¯à®¢¥à塞, 㢥«¨ç¨«áï «¨ à §¬¥à ¤ ­­ëå ¤¨à¥ªâ®à¨¨
LD HL,DIRPAGE.buffer
LD BC,(SAVEDIR.DirBlkSize)
DEC BC
ADD HL,BC
AND A
SBC HL,DE
JR NC,.SAVEDIR
;
; à §¬¥à ¤ ­­ëå ¤¨à¥ªâ®à¨¨ 㢥«¨ç¨«áï
LD HL,(SAVEDIR.DirBlkSize)
LD BC,(CORE_BUFFERS.FS_Buffer.BytesPerCluster)
ADD HL,BC
LD (SAVEDIR.DirBlkSize),HL
AND A
.SAVEDIR: EXX
PUSH DE
EXX
; [ ] big dir ¯¥à¥¤ ¢ âì ®âªã¤  ¨ ᪮«ìª® ¡ ©â®¢ ¨§¬¥­¨«®áì ¢ ªíè, ç⮡ ­¥ ¯¨á âì ­  ¤¨áª «¨è­¥£®
CALL SAVEDIR
POP DE
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
IFUSED GET_ADDR_IN_DIR_CACHE
; ‚室: IX - 㪠§ â¥«ì ­  ­®¬¥à § ¯¨á¨ ¢ ª â «®£¥
; ‚ë室: HL - ᬥ饭¨¥ ¢ SLOT3 ­  § ¯¨áì ¢ ª â «®£¥
GET_ADDR_IN_DIR_CACHE:
LD A,3
PUSH IX
POP HL
RR H
;
RR L
RRA
RR L
RRA
RR L
RRA
LD H,L
LD L,A
LD A,H
OR #C0
LD H,A
RET
ENDIF
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; “¤ «ï¥â § ¯¨áì ¢ ª â «®£¥ ¨ ®á¢®¡®¦¤ ¥â § ­ïâãî æ¥¯®çªã ª« áâ¥à®¢
; ‚室: IX - 㪠§ â¥«ì ­  㤠«ï¥¬ãî § ¯¨áì ¢ DIRPAGE
; ¢ Š<>˜ ¤¨à¥ªâ®à¨¨ ¤®«¦­  ¡ëâì § £à㦥­  ç áâì á ­ã¦­®© § ¯¨áìî
;!TODO record index. ¢®§¬®¦­®, çâ® ¬®¦¥â á«®¬ âìáï, ¥á«¨ ¡®«ìè¥ áâà ­¨æë
DELETE_REC_FAT: SET_PAGE_X DIRPAGE
EX AF,AF'
;CALL DELETE_LFN_RECORDS ; [ ] big dir ; [x] 㤠«¥­¨¥ § ¯¨á¨ LFN
LD (IX + FAT_DIRECTORY_RECORD.NAME),#E5 ; ¯à¨§­ ª 㤠«¥­¨ï ä ©« 
; fat32
LD L,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H) ; ü ¯¥à¢®£® ª« áâ¥à 
LD H,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H+1)
LD A,L
OR H
EXX
LD L,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L) ; ü ¯¥à¢®£® ª« áâ¥à 
LD H,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L+1)
OR L
OR H
;
EX AF,AF'
OUT (SLOT3),A
EX AF,AF'
; [ ] big dir ¯¥à¥¤ ¢ âì ®âªã¤  ¨ ᪮«ìª® ¡ ©â®¢ ¨§¬¥­¨«®áì ¢ ªíè, ç⮡ ­¥ ¯¨á âì ­  ¤¨áª «¨è­¥£®
JP Z,SAVEDIR ; á¡à®á¨âì ª¥è ª â «®£  ­  ¤¨áª
; ¥á«¨ à §¬¥à ä ©«  ­¥ ­®«ì
.loop: ;EX DE,HL ; hl=­®¬¥à ª« áâ¥à 
;EXX
; EX DE,HL
;EXX
CALL READ_FROM_FAT ; ¯à®ç¨â âì ¨§ ª¥è  FAT-  ­®¬¥à á«¥¤. ª« áâ¥à 
EXX
PUSH DE ; ­®¬¥à á«¥¤. ª« áâ¥à 
PUSH AF
LD DE,#0000 ; ­®¬¥à ª« áâ¥à 
EXX
PUSH DE
;
CALL SET_NEW_FREE_CLUSTER
;
LD DE,#0000 ; ­®¬¥à ª« áâ¥à 
CALL WRITE_TO_FAT.Custom ; § ¯¨á âì ¢ ª¥è FAT-  ­®¬¥à ª« áâ¥à 
POP HL
EXX
POP AF
POP HL
;EX DE,HL
EXX
;EX DE,HL
JP NC,.loop
CALL WRITE_FAT_TABLE
; [ ] big dir ¯¥à¥¤ ¢ âì ®âªã¤  ¨ ᪮«ìª® ¡ ©â®¢ ¨§¬¥­¨«®áì ¢ ªíè, ç⮡ ­¥ ¯¨á âì ­  ¤¨áª «¨è­¥£®
JP SAVEDIR ; á¡à®á¨âì ª¥è ª â «®£  ­  ¤¨áª
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; ‚室: HL -  ¤à¥á ªã¤  ¯¨á âì
; ‚ë室: HL -  ¤à¥á á«¥¤ãî騩 ¯®á«¥ § ¯¨á ­®£®
WRITE_DATE_TIME_TO_DIRECTORY_RECORD:
; [ ] VFAT date
PUSH HL
CALL SYSTIME ; ã§­ âì ⥪. ¤ âã ¨ ¢à¥¬ï
CALL MK_TIME ; § ª®¤¨à®¢ âì ¢à¥¬ï/¤ âã
POP HL
; FAT_DIRECTORY_RECORD.TIME
LD (HL),E ; de=¢à¥¬ï
INC HL
LD (HL),D
INC HL
; FAT_DIRECTORY_RECORD.DATE
LD (HL),C ; ¤¥­ì
INC HL
LD (HL),B ; ¬¥áïæ
INC HL
RET
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; <20>८¡à §®¢ âì ¨¬ï 8.3 -> 11 ä®à¬ â
; !FIXIT ­ ¯¨á âì ­®à¬ «ì­®¥ ®¯¨á ­¨¥ ¢å®¤ /¢ë室 
; ¢å®¤: hl = 8.3 ¨¬ï
; de = ¡ãä¥à ¨¬¥­¨ 11 ᨬ¢. ä®à¬ â 
; ¯à¨ ®è¨¡ª¥ CF - ­¥¤®¯. ¨¬ï
;
; HL - MASK "file*.t??"
; DE - 11 bytes filename
; RET: C=2 FILE WITHOUT EXTENTION
; C=1 FILE WITH EXTENTION
MASK: LD HL,CORE_BUFFERS.TMPNAME
;[-------------]
; ¢å®¤: hl = 8.3 ¨¬ï
.name: LD DE,CORE_BUFFERS.MASKARE
;[-------------]
; ¢å®¤: hl = 8.3 ¨¬ï
; de = ¡ãä¥à ¨¬¥­¨ 11 ᨬ¢. ä®à¬ â 
.custom: PUSH HL
PUSH DE
LD H,D
LD L,E
INC DE
LD (HL),' '
LD BC,10 ;!HARDCODE = size (FileName + Extension - 1)
LDIR
POP DE
POP HL
LD A,(HL)
CP '.' ;R007
SCF ;R007
JR Z,.MASKB ;R007
CP ' '+1
.MASKB: LD A,DSS_Error.sys.INVALID_NAME
RET C
LD BC,#0902 ; B - áç¥â稪
.MASK1: LD A,(HL)
CP ' '+1
CCF
RET NC
;
CP '*'
JR Z,.MASK3
CP '.'
JR Z,.MASK5
CP '"'
JR Z,.MASK_ERR
CP '+'
JR Z,.MASK_ERR
CP ','
JR Z,.MASK_ERR
CP '/'
JR Z,.MASK_ERR
CP ':'
JR Z,.MASK_ERR
CP ';'
JR Z,.MASK_ERR
CP '<'
JR Z,.MASK_ERR
CP '='
JR Z,.MASK_ERR
CP '>'
JR Z,.MASK_ERR
CP '['
JR Z,.MASK_ERR
CP '\'
JR Z,.MASK_ERR
CP ']'
JR Z,.MASK_ERR
CP '|'
JR Z,.MASK_ERR
CALL UPPER ; a..z -> A..Z
.MASK2: LD (DE),A
INC HL
INC DE
DJNZ .MASK1
;
.MASK_ERR: LD A,DSS_Error.sys.INVALID_NAME
SCF
RET
;
.MASK3: LD A,'?'
INC HL
DJNZ .MASK6
JR .MASK_ERR
;
.MASK6: LD (DE),A
INC DE
DJNZ .MASK6
LD B,1
JR .MASK1
;
.MASK5: LD A,' '
INC HL
DJNZ .MASK4
LD B,4
DEC C
JR NZ,.MASK1
JR .MASK_ERR
;
.MASK4: LD (DE),A
INC DE
DJNZ .MASK4
LD B,4
DEC C
JR NZ,.MASK1
JR .MASK_ERR
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
; SET_FAT_ROOT_DIR_CLUSTER:
; EX DE,HL
; LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L)
; LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL
; LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H)
; LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),HL
; EX DE,HL
; RET
;----------------------------------------------------------------------;
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
;???
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°;
;----------------------------------------------------------------------;
;!TODO ?
;GHANDLE:
; PUSH DE
; PUSH HL
; PUSH IX
; CALL TESTDSK
; JP C,G_HAND1
; CALL LOADDIR
; POP DE
; LD HL,DIR
; LD BC,FAT_DIRECTORY_RECORD
;G_HAND2:
; LD A,D
; OR E
; JP Z,G_HAND3
; ADD HL,BC
; DEC DE
; JP G_HAND2
;G_HAND3:
; EXX
; POP DE
; EXX
;G_HAND4:
; EX DE,HL
; LD A,DIRPAGE
; CALL BANK
; EX DE,HL
; LD DE,HANDTA
;
; DUP 32
; LDI
; EDUP
;
; EXX
; OUT (SLOT3),A
; LD HL,HANDTA
;
; DUP 32
; LDI
; EDUP
;
; EXX
; POP BC
; DEC BC
; LD A,B
; OR C
; RET Z
; PUSH BC
; JP G_HAND4
;G_HAND1 POP IX
; POP HL
; POP DE
; RET
;HANDTA BLOCK 32,0
;----------------------------------------------------------------------;
MODULE_SIZE EQU $ - MODULE_START
; ENDMODULE
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ;
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ;