Estex-DSS/DSS/FS/FAT/FAT_X.asm
Anatoliy Belyanskiy b515b2429f FAT_X done
2024-04-01 02:49:38 +10:00

1236 lines
27 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.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; FAT 12-16-32
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;[BEGIN]
;//MODULE: FAT_X
;//CREATE: 19-05-1998 AUTHOR: Denis Parinov
;//UPDATE: 24-10-1999 DNS Restore module
;---------------------------------------------------------------
;Rev Date Name Description
;---------------------------------------------------------------
;RY01 16-11-1999 DNS ERROR READING FAT CHAIN
;RX01 10-02-1999 DNS UPGRADE FAT CASH
;---------------------------------------------------------------
; [x] fat32 ;!TEST
; “áâ ­®¢¨âì ­ ç «ì­ë© ª« áâ¥à ¤«ï ç⥭¨ï
R_CLUST: LD HL,#0001
LD (G_CLUST.low),HL
DEC L
LD (G_CLUST.high),HL
RET
;
; [x] fat32 ;!TEST
; ­ ©â¨ ¯¥à¢ë© ᢮¡®¤­ë© ª« áâ¥à ;!TODO ¯à®¢¥à¨âì ¯¥à¥¡®à ª« áâ¥à®¢
; ¢ë室: HL - ¬« ¤è¨© ­®¬¥à ᢮¡®¤­®£® ª« áâ¥à 
; HL' - áâ à訩 ­®¬¥à ᢮¡®¤­®£® ª« áâ¥à 
G_CLUST: ;
.low+1: LD HL,#0001
.loop: INC HL ; ­®¬¥à ª« áâ¥à 
LD A,L
OR H
; [x] fat32
EXX
.high+1: LD HL,#0000
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
LD (G_CLUST.low),HL
EXX
LD (G_CLUST.high),HL
EXX
RET
;
; [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
;
AND A
RET
;RX01
; [x] fat32 ;!TEST
; ¢å®¤: hl = ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à  ¤«ï áà ¢­¥­¨ï á FAT_Max_Cluster
; hl' = áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ¤«ï áà ¢­¥­¨ï á FAT_Max_Cluster (⮫쪮 ¤«ï fat32)
CHECK_CLUSTER_IS_SMALLER:
LD A,(FatBuffer.FAT_TYPE)
XOR FAT_TYPE.x32
JR NZ,.low ; Z=0 ¯à®¢¥à塞 ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
; ¯à®¢¥à塞 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
EXX
EX DE,HL
LD HL,(FatBuffer.MaxClusterHigh)
; CF = 0
SBC HL,DE
EX DE,HL
EXX
LD A,DSS_Error.sys.DISK_FULL
;RET C
RET NZ ; ¥á«¨ FatBuffer.MaxClusterHigh - hl' != 0, â® ª« áâ¥à ª®à४â­ë©
; ¯à®¢¥à塞 ¬« ¤è¥ á«®¢® ­®¬¥à  ª« áâ¥à 
.low: EX DE,HL
LD HL,(FatBuffer.MaxClusterLow)
; CF = 0
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,(FatBuffer.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
RET
;
; [x] fat32 ;!TEST
;------------------------------------------------------------------------------------------------
; ‡ ¯¨á âì ¢ ª¥è FAT-  ­®¬¥à ª« áâ¥à 
; ¢å®¤: hl = ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à  ¢ ª®â®àë© § ¯¨á âì
; hl' = áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ¢ ª®â®àë© § ¯¨á âì (⮫쪮 ¤«ï fat32)
; .Custom:
; de = ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à  ª®â®à®¥ ¢¯¨á âì
; de' = áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ª®â®à®¥ ¢¯¨á âì (⮫쪮 ¤«ï fat32)
; ¢ë室: HL':HL â ª¨¥ ¦¥ ª ª ¨ ­  ¢å®¤¥
; .Custom:
; HL':HL ¨ DE':DE â ª¨¥ ¦¥ ª ª ¨ ­  ¢å®¤¥
;------------------------------------------------------------------------------------------------
WRITE_TO_FAT: LD DE,(FatBuffer.ENDCLUS_LOW) ; ­®¬¥à ª« áâ¥à 
EXX
LD DE,(FatBuffer.ENDCLUS_HIGH) ; ­®¬¥à ª« áâ¥à 
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
PUSH AF
PUSH DE ; ¬« ¤è¨© ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
; [x] 2/12/23 FAT ­¥ ¢á¥£¤  ¬®£ § ¯¨á âìáï ­  HDD
;LD A,1
;LD (FatBuffer.CacheUpdated),A
;
LD A,(FatBuffer.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: POP AF ; ¢®ááâ. ¯®àâ
POP HL
OUT (SLOT3),A
; [x] 2/12/23 FAT ­¥ ¢á¥£¤  ¬®£ § ¯¨á âìáï ­  HDD
XOR A
INC A
LD (FatBuffer.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 ; áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à  ¢ ª®â®àë© § ¯¨á âì
EXX
POP DE ; áâ à訩 ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
POP BC ; ¬« ¤è¨© ­®¬¥à ª« áâ¥à  ª®â®àë© ¢¯¨á âì
; á®åà. ¢ ª¥è¥ FAT-  ­®¬¥à ª« áâ¥à 
LD (HL),C
INC HL
LD (HL),B
INC HL
LD (HL),E
INC HL
LD (HL),D
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,(FatBuffer.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,(FatBuffer.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,(FatBuffer.CacheUpdated)
OR A
CALL NZ,WRITE_FAT_TABLE.Start
POP DE
;
EX DE,HL
LD (FatBuffer.CacheBlock),HL
;
CALL GET_SECTOR_OF_FAT
;
; BC:HL - ­®¬¥à «®£.ᥪâ®à 
LD DE,(FatBuffer.FAT1_SEC_L)
ADD HL,DE
EX DE,HL
LD XH,D
LD XL,E
LD HL,(FatBuffer.FAT1_SEC_H)
; JR NC,.no_inc
; INC HL
.no_inc: ADC HL,BC
; HL:IX - SECTOR FAT FOR READING
LD A,(FatBuffer.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,(FatBuffer.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: LD HL,(FatBuffer.CacheBlock)
;FAT_BLOCK * Sectors_in_Block = SECTOR_OF_FAT
CALL GET_SECTOR_OF_FAT
; B=0, C:HL - ᬥ饭¨¥ ¢ ᥪâ®à å ¢­ãâਠ⠡«¨æë FAT ­  ­ ç «® ¡«®ª 
; [x] fat32 ;!FIXIT
LD (.save_hl),HL
;LD B,H
;LD C,L
;
LD DE,FAT_CACHE.Sectors_32
LD A,(FatBuffer.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
;
; C:HL ᬥ饭¨¥ ¢ ᥪâ®à å ¢­ãâਠ⠡«¨æë FAT ­  ª®­¥æ ¡«®ª 
;
.no_inc: ; ª®­¥æ ¡«®ª  ¢ë室¨â §  ¯à¥¤¥«ë â ¡«¨æë?
LD B,E ; MAX ç¨á«® ᥪâ®à®¢ ¤«ï ç⥭¨ï ¢ ªíè
LD A,(FatBuffer.SectorsPerFAT_H)
LD (.sub_A),A
;LD DE,(CORE_BUFFERS.BootSector.SectorsPerFAT16) ; ᥪâ®à®¢ ­  FAT
LD DE,(FatBuffer.SectorsPerFAT_L)
AND A
LD A,C
SBC HL,DE
.sub_A+1: SBC A,0
JR C,.WALLFAT ; F=1: ­¥ ¢ë室¨â
OR A
JR 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: ;
.save_hl+1: LD HL,0
;LD H,B
;LD L,C
;PUSH HL
;
; B = ç¨á«® ᥪâ®à®¢
LD IX,(FatBuffer.FAT1_SEC_H)
LD DE,(FatBuffer.FAT1_SEC_L)
;LD B,A
;LD C,Dss.DRV.Write ; § ¯¨áì ᥪâ®à®¢
PUSH BC
;
; á®å࠭塞 ¯¥à¢ãî ª®¯¨î FAT. ‚室 IX:DE - ­ ç «® â ¡«¨æë FAT
; C:HL - ᬥ饭¨¥ ¢­ãâਠ⠡«¨æë
; B - ª®«¨ç¥á⢮ ᥪâ®à®¢
CALL .SAVE_FAT_XX
; [x] ¥á«¨ ¢á¥£® ®¤­  â ¡«¨æ  FAT, â® ¯®¢â®à­®© § ¯¨á¨ ­¥ ¯à®¨á室¨â 13/03/2024
POP BC ; B = ç¨á«® ᥪâ®à®¢, C = áâ à訩 ¡ ©â ᬥ饭¨ï ¢ ᥪâ®à å
LD HL,(FatBuffer.FAT1_SEC_H)
LD DE,(FatBuffer.FAT2_SEC_H)
AND A
SBC HL,DE
JR NZ,.not_one_FAT
LD HL,(FatBuffer.FAT2_SEC_L)
LD DE,(FatBuffer.FAT1_SEC_L)
; CF = 0
SBC HL,DE
JR Z,.only_one_FAT
;
; á®å࠭塞 ¢â®àãî ª®¯¨î FAT
.not_one_FAT: LD IX,(FatBuffer.FAT2_SEC_H)
LD DE,(FatBuffer.FAT2_SEC_L)
LD HL,(.save_hl)
CALL .SAVE_FAT_XX
AND A ;!TODO ­¥â ª®­âà®«ï ®è¨¡®ª
.only_one_FAT: ;
.ERR: LD A,0
LD (FatBuffer.CacheUpdated),A
RET
; ‚室: IX:DE - ­ ç «® â ¡«¨æë FAT ¢ ᥪâ®à å
; C:HL - ᬥ饭¨¥ ¢ â ¡«¨æ¥ ¢ ᥪâ®à å
; B - ª®«¨ç¥á⢮ ᥪâ®à®¢
.SAVE_FAT_XX: ADD HL,DE
;EX DE,HL
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 H,0
; LD L,C
LD XH,D
LD XL,E
; HL:IX - ᬥ饭¨¥ ¢­ãâਠࠧ¤¥«  ­  ­ ç «® ­ã¦­®£® ¡«®ª  FAT
LD DE,FATPAGE.cache ; ®âªã¤ 
LD A,(FatBuffer.DRIVE) ; ­®¬¥à ¤¨áª 
LD C,Dss.DRV.Write
JP ToDSS.DRV
;-----------------------------------------------------------------------
;
;[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_32 ; 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 ; [ç] fat32 á®å࠭塞 ­  á«ãç ©, ¥á«¨ READ_FAT_TABLE ¨á¯®àâ¨â
AND A
;
EXX
EX DE,HL
LD HL,(FatBuffer.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)
; [ ] fat32 ¯®¬¥­ï«áï ¢å®¤ ¢ ¯à®æ¥¤ãàã READ_FAT_TABLE. <20> ­ìè¥ ­®¬¥à ¡«®ª  ¢ ॣ. A ¯¥à¥¤ ¢ «áï
; LD BC,(FatBuffer.CacheBlock) ; BC - BLOCK FAT IN CASH
; CP C
LD DE,(FatBuffer.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,(FatBuffer.CacheBlock) ; BC - BLOCK FAT IN CASH
; CP C
LD DE,(FatBuffer.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
;NSECTOR:
; in: HL':HL - CLUSTER
; out: HL:IX - SECTOR
CLUSTER_TO_SECTOR:
EXX
PUSH HL
EXX
POP DE
; DE:HL - cluster
DEC HL
DEC HL
LD A,(CORE_BUFFERS.BootSector.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,(FatBuffer.FirstDataSector_L)
; [x] fat32
;XOR A
;
ADD IX,DE
; [x] fat32
LD DE,(FatBuffer.FirstDataSector_H)
;LD D,A
;LD E,A
;
ADC HL,DE
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.BootSector.SectorsPerCluster) ;SECTORS PER CLUSTER
LD C,A
PUSH BC ; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï, C - SectorsPerCluster
; HL:DE / A => DE:BC, H=0, L - ®áâ â®ª
CALL DIV_for_SPC
PUSH HL ; ®áâ â®ª DIV_for_SPC
; [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_for_SPC
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_for_SPC
CALL CLUSTER_TO_SECTOR
POP DE ; D = 0, E = ®áâ â®ª DIV_for_SPC
ADD IX,DE
JR NC,.skip2
INC HL
.skip2: LD DE,(READ.PointerOnBuffer)
LD A,(FatBuffer.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.BootSector.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.BootSector.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,(FatBuffer.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.BootSector.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 ;!TEST
; 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.BootSector.SectorsPerCluster) ;SECTORS PER CLUSTER
LD C,A
PUSH BC ; B - ª®«¨ç¥á⢮ ᥪâ®à®¢ ¤«ï ç⥭¨ï, C - SectorsPerCluster
; HL:DE / A => DE:BC, H=0, L - ®áâ â®ª
CALL DIV_for_SPC
PUSH HL ; ®áâ â®ª DIV_for_SPC
;[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
; 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 ; [x] 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
;
CALL WRITE_TO_FAT
;!TEST ;!TODO 2/12/23 ; [ ] ¡ £ á ¨§¡ëâ®ç­®© § ¯¨áìî WRITE_FAT_TABLE?
;PUSH HL
;CALL WRITE_FAT_TABLE ; ¯®¤ª«. ¡ ­ªã ª¥è  FAT ¨ § ¯¨á âì ¥£® ­  ¤¨áª
;POP HL
;
POP DE ; ¬« ¤è¥¥ á«®¢® ­®¬¥à  ª« áâ¥à 
POP BC ; [x] fat32 áâ à襥 á«®¢® ­®¬¥à  ª« áâ¥à 
;
INC B
INC D ; [x] 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 ; [x] ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (áâ à襥 á«®¢®)
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 ; [x] ®á⠢襥áï ᬥ饭¨¥ ¢ ä ©«¥ ¢ ª« áâ¥à å (áâ à襥 á«®¢®)
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_for_SPC
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_for_SPC
CALL CLUSTER_TO_SECTOR
POP DE ; D = 0, E = ®áâ â®ª DIV_for_SPC
ADD IX,DE
JR NC,.skip2
INC HL
; DOUBLE 1
.skip2: LD DE,(READ.PointerOnBuffer)
LD A,(FatBuffer.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.BootSector.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.BootSector.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,(FatBuffer.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.BootSector.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
////////////////////////////////////////////////////////////////////////
;!TODO fat32
;=======================================================================
;BPB
;LD (FatBuffer.FAT2_SEC_L),HL
;LD (FatBuffer.RootDirFirstSector_L),HL ; first sector DIR
;BPB32
;LD HL,(CORE_BUFFERS.BootSector+#2C) ;fat32 <20>¥à¢ë© ª« áâ¥à ª®à­¥¢®£® ª â «®£  (®¡ëç­® 2) 4 ¡ ©â 
;FAT Max Cluster
;LD (FatBuffer.MaxClusterLow),HL
;=======================================================================
;//MODULE: FAT_X
;[END]