Estex-DSS/DSS/FS/FAT.asm
Tolik ec139d5761 SHELL: fixed bug in read_disk_info with .full
CORE: добавлены дополнительные проверки ФС раздела в FAT_BPB
2025-05-25 01:03:36 +10:00

2780 lines
62 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.

;[BEGIN]
;//MODULE: FAT
;//CREATE: 19-05-1998 AUTHOR: Denis Parinov
;//UPDATE: 24-10-1999 DNS Restore module
;---------------------------------------------------------------
;Rev Date Name Description
;---------------------------------------------------------------
;R08 14-11-2002 DNS IMPROVE BPB-FUNCTION
;R07 17-12-1999 DNS BUG FIX SIGNATURE #55AA AT 510 OFFSET
;RY01 16-11-1999 DNS ERROR READING FAT CHAIN
;RX01 10-02-1999 DNS UPGRADE FAT CASH
;---------------------------------------------------------------
; [ ] RST_FS
;----------------------------------------------------------------------;
FAT_MODULE_START EQU $
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
;
; [ ] 㤠«¥­¨¥ § ¯¨á¨ LFN
;
; ¢å®¤: IX = ⥪ãé ï § ¯¨áì ¢ áâà ­¨æ¥ á ª â «®£®¬ FAT ¤«ï ª®â®à®©
; ­ ¤® 㤠«¨âì § ¯¨á¨ LFS
DELETE_LFN_RECORDS:
PUSH IX
LD A,XH
AND #C0
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
;
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
;----------------------------------------------------------------------;
; <20>®¨áª § ¯¨á¨ ª â «®£  ¢ ᯨ᪥ ª â «®£ 
;
; ¢å®¤: a =  âਡãâ § ¯¨á¨
; ¢ë室: de = ¨­¤¥ªá § ¯¨á¨ ¢ ᯨ᪥ ª â «®£ 
; (HANDBUF) = file's direcory 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
LD C,A
LD IX,DIRPAGE.buffer
;!TEST 9/11/23 record index
; ®¯â¨¬¨§ æ¨ï ¤«ï ¨­¤¥ªá  § ¯¨á¨ ¢ ᯨ᪥ ª â «®£ .
; <09>®­ ¤®¡¨âáï ¢¥à­ãâì ¤«ï ¯¥à¥¡®à  ª â «®£  > #4000 ¡ ©â
; EXX
; LD DE,0
; EXX
;
.loop: LD A,(IX+FAT_DIRECTORY_RECORD.NAME)
OR A
JR Z,.error_file_not_found
CP #E5 ;!HARDCODE #E5 - § ¯¨áì ¢ ¤¨à¥ªâ®à¨¨ ᢮¡®¤­ , â ª ª ª ä ©«/¤¨à¥ªâ®à¨ï ¡ë«¨ 㤠«¥­ë
JR Z,.next_record
LD A,(IX+FAT_DIRECTORY_RECORD.ATTRIBUT)
LD D,A
AND C
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,MASKARE
LD D,XH
LD E,XL
LD B,11
EX DE,HL
.loop_compare: LD A,(DE)
CP '?'
JR Z,.next_char
CP (HL)
JR NZ,.next_record
;
.next_char: INC HL
INC DE
DJNZ .loop_compare
;
LD D,XH
LD E,XL
;!TEST 9/11/23 record index
; EXX
; PUSH DE
; EXX
PUSH IX
;
LD HL,HANDBUF
EX DE,HL
LD BC,HANDBUF.SIZE
LDIR
;!TEST 9/11/23 record index
POP DE
;
EX AF,AF'
OUT (SLOT3),A
EX AF,AF'
AND A
RET
;
.next_record: LD DE,FAT_DIRECTORY_RECORD
;!TEST 9/11/23 record index
; EXX
; INC DE
; EXX
;
ADD IX,DE
JR NC,.loop
.error_too_many_files:
EX AF,AF'
OUT (SLOT3),A
LD A,DSS_Error.sys.TOO_MANY_FILES_IN_DIR
SCF
RET
;
.error_file_not_found:
EX AF,AF'
OUT (SLOT3),A
LD A,DSS_Error.sys.FILE_NOT_FOUND
SCF
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
;
;----------------------------------------------------------------------;
; FIND "MASKAREA" IN DIRECTORY
; [x] fat32 ;!TEST
; ¢ë室: IY:DE - cluster number
FINDDIR:
SET_PAGE_X DIRPAGE
;
PUSH AF
LD IX,DIRPAGE.buffer
.big_loop:
LD A,(IX + FAT_DIRECTORY_RECORD.NAME)
OR A
JR Z,.error
CP #E5
JR Z,.next_step
LD A,(IX + FAT_DIRECTORY_RECORD.ATTRIBUT)
AND FAT_ATTR.DIRECTORY
JR Z,.next_step
LD HL,MASKARE
LD D,XH
LD E,XL
EX DE,HL
LD B,11 ;!HARDCODE
.loop: LD A,(DE)
CP "?"
JR Z,.compared
CP (HL)
JR NZ,.next_step
.compared:
INC HL
INC DE
DJNZ .loop
;
LD A,(IX + FAT_DIRECTORY_RECORD.NAME)
CP "."
JP NZ,.ADDSPEC
LD A,(IX + FAT_DIRECTORY_RECORD.NAME + 1)
CP "."
JP NZ,.IT_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 .IT_DIR
;
.next_step:
LD BC,FAT_DIRECTORY_RECORD
ADD IX,BC
JR NC,.big_loop
;
.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
;
; LD BC,256*8 + ' ' ;!HARDCODE
; .MM1: LD A,(DE)
; INC DE
; CP C
; JR Z,.MM2
; LD (HL),A
; INC HL
; .MM2 DJNZ .MM1 ;x42-40 50-55
; LD A,(DE)
; INC DE
; CP C
; JR Z,.MM3
; LD (HL),"."
; INC HL
; LD (HL),A
; INC HL
; LD A,(DE)
; INC DE
; CP C
; JR Z,.MM3
; LD (HL),A
; INC HL
; LD A,(DE)
; CP C
; JR Z,.MM3
; LD (HL),A
; .MM2_5: INC HL
; .MM3: LD (HL),0
; ; JP IT_DIR
;
.IT_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
LD (HL),0
;INC HL
RET
;----------------------------------------------------------------------;
CHECK_ROOT_CLUSTER:
EX DE,HL
LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L) ;R005
LD A,L
OR H
LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H)
OR L
OR H
EX DE,HL
RET
;----------------------------------------------------------------------;
; ¢å®¤: HL - ¨¬ï ¤¨à¥ªâ®à¨¨
; [x] fat32 ;!TEST
OPENDIR: LD IY,CORE_BUFFERS.FM_BUF
LD A,(HL)
OR A
JR NZ,.SUBDIR
;
.REROOT: LD DE,0 ; !FIXIT ; [ ] CDFS - ¡à âì ¯¥à¢ë© ª« áâ¥à ¨§ ¯¥à¥¬¥­­®©
LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),DE
LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),DE
CALL LOADDIR
; CF=0
LD HL,CORE_BUFFERS.WorkDirectory
LD (HL),'\'
INC HL
LD (HL),#00
;AND A
RET
;
.SUBDIR: CP "."
JR NZ,.SUBDIR2
; fat32
CALL CHECK_ROOT_CLUSTER
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,MASKARE
LD DE,MASKARE+1
LD BC,10 ;!HARDCODE
LD (HL),' '
LDIR
EXX
LD DE,MASKARE
.loop: LDI
LD A,(HL)
OR A
JR NZ,.loop
JR .SUBDIR3
;
.SUBDIR2: CALL MASK.name
RET C
; fat32
.SUBDIR3: CALL FINDDIR
RET C
EX DE,HL
LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL ; fat32
LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),IY ; fat32
LD HL,#4000 ;!HARDCODE
LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),HL
;-------------; EX DE,HL
; JP LOADDIR
; <20>à®ç¨â âì ᯨ᮪ ª â «®£ 
; [x] fat32 ;!TEST
LOADDIR: ;!TODO optimize
CALL LOAD_SAVE_DIR_PREPARE
PUSH AF
EX AF,AF'
JR NZ,.read_dir
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x32
JR NZ,.LoadRootDir
; fat32
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
;LD HL,(CORE_BUFFERS.FS_Buffer.BytesPerCluster) ; !FIXIT ¢ëç¨â뢠âì ¯®«­®áâìî ª â «®£
LD HL,#4000 ; à §¬¥à ¤¨à¥ªâ®à¨¨ ;!HARDCODE
LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),HL
;
.read_dir: LD HL,DIRPAGE.buffer ; ªã¤ 
LD DE,#4000 ; ᪮«ìª®
XOR A ; ¤¥áªà¨¯â®à
CALL READ ; ç⥭¨¥ ¨§ ä ©« 
LD (SAVEDIR.DIRSIZE),DE ; ç¨á«® ¯à®ç¨â. ¡ ©â®¢
POP AF
OUT (SLOT3),A
RET
;
.LoadRootDir: 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-ª â «®£ 
CP B
JR NC,.RTD1
LD B,A ; ç¨á«® ᥪâ®à®¢
.RTD1: PUSH AF ; 21/04/2025 fix ¬ãá®à ¢ áâà ­¨æ¥ ª â «®£ , ¥á«¨ ª â «®£ ¬¥­ìè¥ áâà ­¨æë
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) ; ­®¬¥à ¤¨áª 
LD DE,DIRPAGE.buffer ; ¡ãä¥à
LD C,Dss.DRV.Read ; ç⥭¨¥ ᥪâ®à®¢
RST ToDSS.DRV
; !FIXIT ­¥â ¯à®¢¥àª¨ ­  ®è¨¡ªã
; 21/04/2025 fix ¬ãá®à ¢ áâà ­¨æ¥ ª â «®£ , ¥á«¨ ª â «®£ ¬¥­ìè¥ áâà ­¨æë
POP AF
JR NC,.exit
XOR A
LD (DE),A
;
.exit: POP AF
OUT (SLOT3),A
RET
;----------------------------------------------------------------------;
;!TODO FAT procedures
;----------------------------------------------------------------------;
LOAD_SAVE_DIR_PREPARE:
;!TODO optimize
XOR A ; FILE MANIPULATOR = 0
LD H,A
LD L,A
LD IX,0
LD B,A ; ®â ­ ç «  ä ©« 
CALL MOVE_FP
;
SET_PAGE_X DIRPAGE
AND A
EX AF,AF'
;
LD A,(CORE_BUFFERS.FS_Buffer.DRIVE)
LD (IY+_sFM.DRIVE),A
;!FIXIT ¯¥à¥¤¥« âì ­  à ¡®âã ¡¥§ IY
LD A,(IY+_sFM.FS_REC.FIRST_CLUSTER_L)
OR (IY+_sFM.FS_REC.FIRST_CLUSTER_L+1)
OR (IY+_sFM.FS_REC.FIRST_CLUSTER_H)
OR (IY+_sFM.FS_REC.FIRST_CLUSTER_H+1)
;
EX AF,AF'
RET
;----------------------------------------------------------------------;
; ᪮¯¨à®¢ âì § ¯¨áì ¢ ᯨ᮪ ¤¨áª  (ª â «®£ ) de ix iy
; ¨ á¡à®á¨âì ª¥è ª â «®£  ­  ¤¨áª
; ¢å®¤: (HANDBUF) - § ¯¨áì ª â «®£ 
WRT_HND:
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,HANDBUF
LD BC,HANDBUF.SIZE
LDIR
EX AF,AF'
OUT (SLOT3),A
LD HL,DIRPAGE.buffer
LD BC,(SAVEDIR.DIRSIZE)
DEC BC
ADD HL,BC
AND A
SBC HL,DE
JR NC,SAVEDIR
LD HL,(SAVEDIR.DIRSIZE)
LD BC,(CORE_BUFFERS.FS_Buffer.BytesPerCluster)
ADD HL,BC
LD (SAVEDIR.DIRSIZE),HL
AND A
;JP SAVEDIR
;----------------------------------------------------------------------;
; ‘¡à®á¨âì ª¥è ª â «®£  ­  ¤¨áª.
; ¢å®¤: iy=áâàãªâãà  ¤¥áªà¨¯â®à 
; [x] fat32 ;!TEST
SAVEDIR: ;!TODO optimize
CALL LOAD_SAVE_DIR_PREPARE
PUSH AF
EX AF,AF'
JR NZ,.save_dir
;
LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE)
CP FAT_TYPE.x32
JR NZ,.SaveRootDir
; fat32
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
;
.save_dir: LD HL,DIRPAGE.buffer
; à §¬¥à ᯨ᪠ ª â «®£  size_cash_directory
;!FIXIT ¥á«¨ ®­  ­ã¦­ , â® ¯à®¢¥à¨âì ­  ¡ £¨ (­ ¯à¨¬¥à, à §¬¥à ¤¨à४â®à¨¨ ¬¥­ìè¥ ¯à¨ ®âªàë⨨ ¨ ¡®«ìè¥ ¯®á«¥ ¯à ¢®ª)
; ª®£¤  ¡ã¤¥â ç⥭¨¥ ªã᪠¬¨ ª â «®£  ¢ ªíè, âãâ ¥éñ áçñâ稪 ¯à¨ªàãâ¨âì
.DIRSIZE+1: LD DE,0
XOR A
CALL WRITE
POP AF
OUT (SLOT3),A
RET
;
.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
;----------------------------------------------------------------------;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; [x] fat32
; 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
;
; ;R08 ; [x] fat32
; LD HL,CORE_BUFFERS.SECTOR_BUFFER
; LD DE,CORE_BUFFERS.BootSector
; LD BC,_sBOOT_SECTOR_PARAMS_FAT32 ; size
; LDIR
;
FAT_BPB: LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.DRIVE_TYPE)
CP #F0
JP C,RD_BPB.UnknownBPB
;
XOR A
LD (.UsesVarsFAT32),A
;
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
;[ ] fat32
XOR A
LD B,A
LD C,A
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.SectorsPerFAT_H),A ; [ ] fat32
;LD (CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_H),BC ; [ ] fat32 reset variables
;
;
EXX
LD H,A
LD L,A
LD D,A
LD E,A
EXX
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
;
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
.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 DIR
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
EX DE,HL
LD HL,(CORE_BUFFERS.FS_Buffer.SectorsPerFAT_L)
; DE:HL = SectorsPerFAT
;
LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.Number_of_FATs)
LD B,A
DEC A
JR Z,.loop_mul_end
; .Number_of_FATs * .SectorsPerFAT
.loop_mul: ADD HL,HL
EX DE,HL
ADC HL,HL
EX DE,HL
DJNZ .loop_mul
.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
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
JR Z,.first_FAT_active
LD B,A
;
.fat_calc_loop: ADD HL,DE
EXX
ADC HL,DE
EXX
DJNZ .fat_calc_loop
;
.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
;
; DOS_X_Error:
; .UnknownBPB: LD A,DSS_Error.sys.UNKNOWN_FORMAT
; SCF
; RET
;
; .Not_ready: LD A,DSS_Error.sys.NOT_READY
; ; CF = 1
; RET
;
;
;!TODO ª ¡ãä¥à ¬!
/*
FS_Buffer:
;.MSG: DB 'FAT'
.DRIVE: DB #FF
.FAT_TYPE: DB #00 ; TYPE FAT (12 - 12bit, 16 - 16bit, 32 - 32bit) ; [x] fat32
.CacheBlock: DW #00
.CacheUpdated: DB #00
;.SectorsPerBank: DB #00
.RootDirStartCluster_L: DW #0000
.RootDirStartCluster_H: DW #0000 ; [ ] fat32
.FAT1_SEC_L: DW #0000 ; MSD_FAT_SEC first sector FAT (FAT_FRM)
.FAT1_SEC_H: DW #0000 ; [ ] fat32
.FAT2_SEC_L: DW #0000
.FAT2_SEC_H: DW #0000 ; [ ] fat32
.SectorsPerFAT_L DW #0000
.SectorsPerFAT_H DB #00
.RootDirFirstSector_L: DW #0000 ; MSD_CAT_SEC first sector DIR
.RootDirFirstSector_H: DW #0000 ; MSD_CAT_SEC first sector DIR ; !TODO ®£à ­¨ç¥­¨¥ ¢ 32 ƒ¨£  ;!FIXIT ­¥ ¨á¯®«ì§ã¥âáï
.DirSizeInSectors: DB #00 ; DIR_SEC_SIZE
.FirstDataSector_L: DW #0000 ; MSD_DAT_SEC low
.FirstDataSector_H: DW #0000 ; MSD_DAT_SEC high ; [ ] fat32 ¡ë«® ®£à ­¨ç¥­¨¥ ¢ 32 ƒ¨£ 
.BytesPerCluster: DW #0000 ; CLUSTER_LEN
.END_CHAIN_CLUSTER_L: DW #FFFF
.END_CHAIN_CLUSTER_H: DW #0FFF ; [ ] fat3
.MaxClusterLow: DW #0000 ; ¬ ªá. ç¨á«® ª« áâ¥à®¢ (¡¥§ á«ã¦.)
.MaxClusterHigh: DW #0000 ; ¬ ªá. ç¨á«® ª« áâ¥à®¢ (¡¥§ á«ã¦.)
;
.BytesPerSector DW #0000
.SectorsPerCluster DB #00
.BPB_SERIAL_NUMBER DW 0,0
.BPB_LABEL BLOCK 11,' ' ; 11 ¤«ï FAT, 31 ¤«ï CDFS
IF COMPILE_UNUSED_CODE
.FilesPerSector: DB #00 ; ç¨á«® ä ©«®¢ëå § ¯¨á¥© ¢ ᥪâ®à¥
.ClustersPerBank: DB #00 ; A - Clusters per bank (16k) (ç¨á«® ª« áâ¥à®¢ ­  ¡«®ª އ“) ; ????? íâ® ¨á¯®«ì§ã¥âáï?
ENDIF
;.READ_PG: DB #00 ;!TODO ­¥ ¨á¯®«ì§ãîâáï ­¥ª®â®àë¥ §­ ç¥­¨ï, ­® § ¤ã¬ª  ­¥¯«®å ï)))
;.S_X_H: DW #0000 ; ª®«¨ç¥á⢮ ᥪâ®à®¢ ­  樫¨­¤à¥ ; ????? íâ® ¨á¯®«ì§ã¥âáï?
;
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ;
; FAT_X 12-16-32
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ;
; “¤ «ï¥â § ¯¨áì ¢ ª â «®£¥ ¨ ®á¢®¡®¦¤ ¥â § ­ïâãî æ¥¯®çªã ª« áâ¥à®¢
; ‚室: IX - 㪠§ â¥«ì ­  㤠«ï¥¬ãî § ¯¨áì ¢ DIRPAGE
;!TODO record index. ¢®§¬®¦­®, çâ® ¬®¦¥â á«®¬ âìáï, ¥á«¨ ¡®«ìè¥ áâà ­¨æë
DELETE_REC_FAT: SET_PAGE_X DIRPAGE
EX AF,AF'
CALL DELETE_LFN_RECORDS ; [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'
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
JP SAVEDIR ; á¡à®á¨âì ª¥è ª â «®£  ­  ¤¨áª
; “áâ ­®¢¨âì ¯¥à¢ë¬ ¨§¢¥áâ­ë¬ ª« áâ¥à®¬ ¤«ï ¯®¨áª  ᢮¡®¤­®£®.
; “áâ ­®¢¨âáï ⮫쪮 ¥á«¨ ¬¥­ìè¥ ¯à¥¤ë¤ã饣®
; ‚室: 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
;
; [x] fat32 ;!TEST
; ­ ©â¨ ¯¥à¢ë© ᢮¡®¤­ë© ª« áâ¥à ;!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
; ;
;
; [x] fat32 ;!TEST
; <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-  ­®¬¥à ª« áâ¥à 
;!TEST ;!TODO 2/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
;RX01
; [x] fat32 ;!TEST
; ¢å®¤: 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
;
;
;[x] fat32 ;!TEST
;------------------------------------------------------------------------------------------------
; <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
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
;
; [x] fat32 ;!TEST
;
; !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: ; [x] fat32 ;!TEST
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
;;;;;;;;;
; [x] fat32 ;!TEST
;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
;;;;;;;;;
; [x] fat32 ;!TEST
;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
; [x] fat32 ;!TEST
; <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
;-----------------------------------------------------------------------
;
;[x] fat32 ;!TEST
;¢å®¤: 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
;-----------------------------------------------------------------------
;[x] fat32 ;!TEST
;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
////////////////////////////////////////////////////////////////////////
; [x] fat32 ;!TEST
; 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
; [x] GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE
PUSH BC ; ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
PUSH DE ; [x] fat32 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
;
; 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 Low
; LD H,(IY+_sFM.FS_REC.FIRST_CLUSTER_L+1)
; OR L
; OR H
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
;;;;
;
;[x] 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
;-----------------------------------------------------------------------
; [x] fat32
; ¢å®¤: IY - FM
; ¢ë室: 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
; [x] fat32
; WRITE SECTORS OF FILE
; ¢å®¤: HL:DE - FP (in sectors)
; IX - data in RAM
; IY - FM
; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï § ¯¨á¨
BLOK_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 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
;
; 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
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
;LD A,DSS_Error.sys.WRITE_ERROR
;SCF
RET
;
.ErrorFull: POP BC
LD A,DSS_Error.sys.DISK_FULL
;SCF
RET
;
;[x] fat32
;[x] 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
;[x] fat32
;[x] 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
////////////////////////////////////////////////////////////////////////
;----------------------------------------------------------------------;
; ‚室: 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
;----------------------------------------------------------------------;
;----------------------------------------------------------------------;
;<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
;----------------------------------------------------------------------;
FAT_MODULE_SIZE EQU $-FAT_MODULE_START
;//MODULE: FAT
;[END]