;[BEGIN] ;//MODULE: FAT ;//CREATE: 19-05-1998 AUTHOR: Denis Parinov ;//UPDATE: 24-10-1999 DNS Restore module ;--------------------------------------------------------------- ;Rev Date Name Description ;--------------------------------------------------------------- ;RX01 10-02-1999 DNS UPGRADE FAT CASH ;--------------------------------------------------------------- ;----------------------------------------------------------------------; ; Поиск записи каталога в списке каталога ; ; вход: a = атрибут записи ; выход: de = индекс записи в списке каталога ; (HANDBUF) = file's direcory record ; CF - каталог не найден SEARCH: .Dir: LD A,FAT_ATTR.DIRECTORY CALL SEARCH.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 ;[x] 9/11/23 оптимизация для индекса записи в списке каталога (возможно понадобится вернуть) ; EXX ; LD DE,0 ; EXX ; .loop: LD A,(IX+00) OR A JR Z,.error_file_not_found CP #E5 ;!HARDCODE #E5 - запись в директории свободна, так как файл/директория были удалены JR Z,.next_record LD A,(IX+11) AND C JR NZ,.next_record 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 ;[x] 9/11/23 оптимизация для индекса записи в списке каталога (возможно понадобится вернуть) EXX ; LD D,XH ; LD E,XL PUSH IX EXX ; LD HL,HANDBUF EX DE,HL LD BC,HANDBUF.SIZE LDIR ;[x] 9/11/23 оптимизация для индекса записи в списке каталога (возможно понадобится удалить) POP DE ; EX AF,AF' OUT (SLOT3),A EX AF,AF' AND A RET .next_record: ;[x] 9/11/23 оптимизация для индекса записи в списке каталога (возможно понадобится вернуть) ; EXX ; INC DE ; EXX ; LD DE,#0020 ;!HARDCODE ADD IX,DE JR NC,.loop .error_too_many_files: ;POP AF EX AF,AF' OUT (SLOT3),A LD A,DSS_Error.sys.TOO_MANY_FILES_IN_DIR SCF RET ; .error_file_not_found: ;POP AF 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,#0020 ;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 FINDDIR: SET_PAGE_X DIRPAGE ; PUSH AF LD IX,DIRPAGE.buffer .big_loop: LD A,(IX + _sFAT_DIRECTORY_RECORD.NAME) OR A JR Z,.error CP #E5 JR Z,.next_step LD A,(IX + _sFAT_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 + _sFAT_DIRECTORY_RECORD.NAME) CP "." JP NZ,.ADDSPEC LD A,(IX + _sFAT_DIRECTORY_RECORD.NAME + 1) CP "." JP NZ,.IT_DIR LD HL,WorkDirectory LD D,H LD E,L INC HL LD BC,WorkDirectory.DEPTH XOR A CPIR JP PO,.error ;[x] 20/11/23 проверка на выход за границы DEC HL ;R009 DEC HL LD BC,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,#0020 ;!HARDCODE 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,WorkDirectory+1 LD BC,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 + _sFAT_DIRECTORY_RECORD.FIRST_CLUSTER_L) LD D,(IX + _sFAT_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 ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ; Прочитать список каталога LOADDIR: XOR A LD H,A LD L,A LD IX,0 LD B,A ; от начала файла CALL MOVE_FP SET_PAGE_X DIRPAGE AND A PUSH AF ;!TEST no ldir ; очистить кеш каталога ; LD HL,#C000 ; LD DE,#C001 ; LD BC,#3FFF ; LD (HL),L ; LDIR ; LD A,(FatBuffer.DRIVE) ; номер диска LD (IY+_sFM.DRIVE),A ; сохр. в дескриптор ; номер первого кластера ; [ ] fat32 LD A,(IY+_sFM.FS_REC.FIRST_CLUSTER_L) OR (IY+_sFM.FS_REC.FIRST_CLUSTER_L+1) JP Z,.LROTDIR ; root ?? ; LD HL,DIRPAGE.buffer ; куда LD DE,#4000 ; сколько XOR A ; дескриптор CALL READ ; чтение из файла LD (SAVEDIR.DIRSIZE),DE ; число прочит. байтов POP AF OUT (SLOT3),A RET .LROTDIR: LD HL,(FatBuffer.DIR_FRH) ; ст. разряд LD IX,(FatBuffer.DIR_FRL) ; номер лог. сектора LD A,(FatBuffer.DIR_S_S) LD B,32 ; !HARDCODE 16384/(sector 512). размер root-каталога CP B JR NC,.RTD1 LD B,A ; число секторов .RTD1: LD A,(FatBuffer.DRIVE) ; номер диска LD DE,DIRPAGE.buffer ; буфер LD C,Dss.DRV.Read ; чтение секторов RST ToDSS.DRV POP AF OUT (SLOT3),A RET ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ; скопировать запись в список диска (каталога) ; и сбросить кеш каталога на диск WRT_HND: SET_PAGE_X DIRPAGE EX AF,AF' ; ;LD IX,DIRPAGE.buffer LD HL,DIRPAGE.buffer ;TEST 9/11/23 ; EXX ; LD DE,0 ; EXX ; LD BC,#0020 .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 ; 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,(FatBuffer.B_P_C) ADD HL,BC LD (SAVEDIR.DIRSIZE),HL AND A JP SAVEDIR ;----------------------------------------------------------------------; ;!TODO FAT procedures ;----------------------------------------------------------------------; ; Сбросить кеш каталога на диск. ; вход: iy=структура дескриптора SAVEDIR: XOR A LD HL,0 LD IX,0 LD B,0 CALL MOVE_FP ; SET_PAGE_X DIRPAGE PUSH AF ; LD A,(FatBuffer.DRIVE) LD (IY+_sFM.DRIVE),A ;[ ] fat32 LD D,(IY+_sFM.FS_REC.FIRST_CLUSTER_L) LD E,(IY+_sFM.FS_REC.FIRST_CLUSTER_L+1) LD A,D OR E JP Z,.SROTDIR LD HL,DIRPAGE.buffer ; размер списка каталога size_cash_directory ;!FIXIT если она нужна, то проверить на баги (например, размер дирректории меньше при открытии и больше после правок) .DIRSIZE+1: LD DE,0 XOR A CALL WRITE POP AF OUT (SLOT3),A AND A RET .SROTDIR: LD HL,(FatBuffer.DIR_FRH) LD IX,(FatBuffer.DIR_FRL) LD A,(FatBuffer.DIR_S_S) LD B,32 ;!HARDCODE SUB B JR NC,.RTD1S ADD A,B LD B,A .RTD1S: LD A,(FatBuffer.DRIVE) LD DE,DIRPAGE.buffer LD C,Dss.DRV.Write RST ToDSS.DRV POP AF OUT (SLOT3),A AND A RET ;----------------------------------------------------------------------; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ; не используется ; TESTDSK: ;????? возможно, что тут логичнее, чем в начале OPENDSK, если будет работать Dss.DRV.Open ; LD A,(FatBuffer.DRIVE) ; LD C,Dss.DRV.MediaCheck ; RST ToDSS.DRV ; OR A ; RET Z ; рег. D - номер диска RD_BPB: LD C,SLOT3 IN B,(C) PUSH BC IN A,(SLOT0) OUT (SLOT3),A LD A,(FatBuffer.DRIVE) ;R08 ;LD DE,BOOT+#C000 LD DE,CORE_BUFFERS.SECBUF+#C000 ;R08 LD C,Dss.DRV.GetBPB RST ToDSS.DRV POP BC OUT (C),B JP C,DOS_X_Error.Not_ready //PUSH IY ; пока без индексного, но может пригодиться LD DE,#AA55 ; сигнатура ;R05 LD HL,(CORE_BUFFERS.SECBUF+_sBOOT_SECTOR.MBR_SIGNATURE) ;R08 ;R07 ;R05 AND A SBC HL,DE JP NZ,DOS_X_Error.UnknownBPB ;R08 LD HL,CORE_BUFFERS.SECBUF LD DE,CORE_BUFFERS.BootSector LD BC,_sBOOT_SECTOR_PARAMS ; size LDIR ; //LD IY,BootSector ; пока без индексного, но может пригодиться //LD A,(IY+_sBOOT_SECTOR_PARAMS.DRIVE_TYPE) LD A,(CORE_BUFFERS.BootSector.DRIVE_TYPE) CP #F0 JP C,DOS_X_Error.UnknownBPB ;!TEST ;LD HL,0 ; calc. first sector FAT ;LD E,(IY+_sBOOT_SECTOR_PARAMS.RESERVED_SECTORS) ;Reserve sec ;LD D,(IY+_sBOOT_SECTOR_PARAMS.RESERVED_SECTORS+1) ;ADD HL,DE //LD L,(IY+_sBOOT_SECTOR_PARAMS.RESERVED_SECTORS) ;Reserve sec //LD H,(IY+_sBOOT_SECTOR_PARAMS.RESERVED_SECTORS+1) LD HL,(CORE_BUFFERS.BootSector.RESERVED_SECTORS) ; ; LD E,(IY+_sBOOT_SECTOR_PARAMS.HIDDEN) ;Hidden sec ; LD D,(IY+_sBOOT_SECTOR_PARAMS.HIDDEN+1) ; ADD HL,DE ;LD (FatBuffer.FAT_FRM),HL ; first sector FAT LD (FatBuffer.FAT1_XX),HL ; first sector FAT #1 LD (FatBuffer.FAT2_XX),HL //LD E,(IY+_sBOOT_SECTOR_PARAMS.S_P_F) ; sectors in FAT //LD D,(IY+_sBOOT_SECTOR_PARAMS.S_P_F+1) LD DE,(CORE_BUFFERS.BootSector.S_P_F) LD A,(CORE_BUFFERS.BootSector.FAT_NUM) ; amount FATs CP 1 JR Z,.loop1 DEC A ADD HL,DE LD (FatBuffer.FAT2_XX),HL ;C_DATA1 .loop1: ADD HL,DE DEC A JR NZ,.loop1 LD (FatBuffer.DIR_FRL),HL ; first sector DIR ; CF = ? мало ли AND A ; CF = 0 //LD C,(IY+_sBOOT_SECTOR_PARAMS.B_P_S) ; Size sectors //LD B,(IY+_sBOOT_SECTOR_PARAMS.B_P_S+1) LD BC,(CORE_BUFFERS.BootSector.B_P_S) ; RL C ; RL B ; RL C ; RL B ; RL C ; RL B ; LD C,B ; LD B,0 ; BC - File handels in sectors ; LD A,C ;;;; LD A,B ; RL C RLA ; RL C RLA ; RL C RLA ; LD C,A LD B,0 ; BC - File handels in sectors ;;;; LD (FatBuffer.F_P_S),A //LD E,(IY+_sBOOT_SECTOR_PARAMS.F_P_DIR) ; Number file handel //LD D,(IY+_sBOOT_SECTOR_PARAMS.F_P_DIR+1) LD DE,(CORE_BUFFERS.BootSector.F_P_DIR) EX DE,HL DEC HL XOR A ;NEXTAD2 .loop2: INC A JP Z,DOS_X_Error.UnknownBPB SBC HL,BC JR NC,.loop2 EX DE,HL LD C,A ; A - sectors in DIR LD B,0 LD (FatBuffer.DIR_S_S),A ADD HL,BC ; Start DATA area LD (FatBuffer.DAT_FRL),HL ;!TODO не используются значения вычисляемые и сохраняемые в FatBuffer //////////////////////////////////////////////////////////////////////// ;IF COMPILE_UNUSED_CODE ;LD HL,0 ;LD H,B ; тут в B ноль должен быть ;LD L,B ;LD C,(IY+_sBOOT_SECTOR_PARAMS.B_P_S) ; Size sector ;LD B,(IY+_sBOOT_SECTOR_PARAMS.B_P_S+1) //LD L,(IY+_sBOOT_SECTOR_PARAMS.B_P_S) ; Size sector //LD H,(IY+_sBOOT_SECTOR_PARAMS.B_P_S+1) LD HL,(CORE_BUFFERS.BootSector.B_P_S) ; Size sector LD A,(CORE_BUFFERS.BootSector.S_P_C) ;!TODO FATcacheSize ;NEXTAD3 ; .loop3: ADD HL,BC ; calc. cluster size ; DEC A ; JR NZ,.loop3 XOR 1 ; calc. cluster size JR Z,.loop3.end RRA .loop3: ADD HL,HL RRA JP NC,.loop3 .loop3.end: ; LD (FatBuffer.CLU_LEN),HL 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 (FatBuffer.C_P_B),A ; A - Clusters per bank (16k) ;ENDIF //////////////////////////////////////////////////////////////////////// ;!TODO detect fat type by clusters! ;[ ] fat32 reset fat32 variables LD HL,0 LD (FatBuffer.ENDCLUS_HIGH),HL LD (FAT_Max_Cluster_H),HL ; LD HL,CORE_BUFFERS.BootSector.ID_FAT ;!!!!! а если IY используется для переменного BootSector, то будет бага LD DE,FatBuffer.MSG LD B,3 ;R_BPBL1 .loop5: LD A,(DE) CP (HL) JP NZ,.IBM_DOS INC HL INC DE DJNZ .loop5 ;FID .loop6: LD A,(HL) INC HL CP ' ' JR Z,.loop6 ; CP '1' IF _FAT32_ENABLE JP Z,.fat1x ;[ ] fat32 CP '2' JP NZ,DOS_X_Error.UnknownBPB LD A,#46 ; #46-#26 = 32 fat type LD HL,#0FFF LD (FatBuffer.ENDCLUS_HIGH),HL LD (FAT_Max_Cluster_H),HL LD H,#FF JR .BPB_FAT ; ELSE JP NZ,DOS_X_Error.UnknownBPB ENDIF ; .fat1x: LD A,(HL) CP '6' ; FAT16 LD HL,#FFFF JR Z,.BPB_FAT CP '2' ; FAT12 JP NZ,DOS_X_Error.UnknownBPB LD HL,#0FFF .BPB_FAT: SUB #26 ; A-#26 = fat type (12, 16, 32) LD (FatBuffer.FAT_TYPE),A LD (FatBuffer.ENDCLUS_LOW),HL ;!TODO не используются значения вычисляемые и сохраняемые в FatBuffer //////////////////////////////////////////////////////////////////////// ;IF COMPILE_UNUSED_CODE LD HL,0 //LD C,(IY+_sBOOT_SECTOR_PARAMS.S_P_T) ; Sector per track //LD B,(IY+_sBOOT_SECTOR_PARAMS.S_P_T+1) LD BC,(CORE_BUFFERS.BootSector.S_P_T) ; Sector per track LD A,(CORE_BUFFERS.BootSector.HEADS) ;!!!!! а если IY используется для переменного BootSector, то будет бага .BPB_L1: ; calc. sector per cylinder ADD HL,BC DEC A JR NZ,.BPB_L1 LD (FatBuffer.S_X_H),HL ;ENDIF //////////////////////////////////////////////////////////////////////// LD DE,(FatBuffer.DAT_FRL) ; LD E,(IY+_sBOOT_SECTOR_PARAMS.HIDDEN) ;Hidden sec ; LD D,(IY+_sBOOT_SECTOR_PARAMS.HIDDEN+1) ; AND A ; SBC HL,DE ; EX DE,HL //LD L,(IY+_sBOOT_SECTOR_PARAMS.S_P_D) //LD H,(IY+_sBOOT_SECTOR_PARAMS.S_P_D+1) LD HL,(CORE_BUFFERS.BootSector.S_P_D) LD A,H OR L JP NZ,.HDDSMAL ; //LD L,(IY+_sBOOT_SECTOR_PARAMS.BPB_BIG_TOTAL_SECTORS) //LD H,(IY+_sBOOT_SECTOR_PARAMS.BPB_BIG_TOTAL_SECTORS+1) LD HL,(CORE_BUFFERS.BootSector.BPB_BIG_TOTAL_SECTORS_L) //LD C,(IY+_sBOOT_SECTOR_PARAMS.BPB_BIG_TOTAL_SECTORS+2) //LD B,(IY+_sBOOT_SECTOR_PARAMS.BPB_BIG_TOTAL_SECTORS+3) LD BC,(CORE_BUFFERS.BootSector.BPB_BIG_TOTAL_SECTORS_H) AND A SBC HL,DE JP NC,.HDDBIG DEC BC JP .HDDBIG .HDDSMAL: ;AND A ;тут CF полюбас сброшен должен быть SBC HL,DE LD BC,0 .HDDBIG: LD A,(CORE_BUFFERS.BootSector.S_P_C) ;!!!!! а если IY используется для переменного BootSector, то будет бага SCF .S4C01: RRA JR C,.S4C02 RR B RR C RR H RR L JP .S4C01 .S4C02: INC HL LD (FAT_Max_Cluster_L),HL //POP IY XOR A LD H,A LD L,A LD (FatCache.Block),HL LD (FatCache.Update),A SET_PAGE_X FATPAGE PUSH AF XOR A CALL READ_FAT_TABLE POP AF OUT (SLOT3),A CALL R_CLUST XOR A RET ;!TODO detect fat type by clusters! .IBM_DOS: LD A,(CORE_BUFFERS.BootSector.DRIVE_TYPE) CP #F0 JR C,DOS_X_Error.UnknownBPB ; ID ram-диска - #FA CP #F8 ; !FIXIT не обязательно если винт, то не FAT12 LD A,'6' LD HL,#FFFF JP Z,.BPB_FAT ; LD A,'2' LD HL,#0FFF JP .BPB_FAT ; DOS_X_Error: .UnknownBPB: //POP IY LD A,DSS_Error.sys.UNKNOWN_FORMAT SCF RET .Not_ready: LD A,DSS_Error.sys.NOT_READY ; CF = 1 RET ; ; ;!TODO к буферам! FatBuffer: .MSG: DB 'FAT' .READ_PG: DB #00 ;!TODO не используются некоторые значения, но задумка неплохая))) .BLOCK: DB #00 .DIR_CLU_L: DW #0000 .DIR_CLU_H: DW #0000 ; fat32 .DRIVE: DB #FF .FAT_FRM: .FAT1_XX: DW #0000 ; MSD_FAT_SEC first sector FAT .FAT2_XX: DW #0000 .DIR_FRH: DW #0000 ; MSD_CAT_SEC first sector DIR ; !TODO ограничение в 32 Гига ;!FIXIT не используется .DIR_FRL: DW #0000 ; MSD_CAT_SEC first sector DIR .F_P_S: DB #00 ; число файловых записей в секторе .DIR_S_S: DB #00 ; DIR_SEC_SIZE .DAT_FRL: DW #0000 ; MSD_DAT_SEC low .DAT_FRH: DW #0000 ; MSD_DAT_SEC high ; !TODO ограничение в 32 Гига ;!FIXIT не используется .CLU_LEN: .B_P_C: DW #0000 ; CLUSTER_LEN .C_P_B: DB #00 ; A - Clusters per bank (16k) (число кластеров на блок ОЗУ) ; ????? это используется? .FAT_TYPE: DB #00 ; TYPE FAT (12 - 12bit, 16 - 16bit, 32 - 32bit) ;!TODO fat32 .S_X_H: DW #0000 ; количество секторов на цилиндре ; ????? это используется? .ENDCLUS_LOW: DW #FFFF .ENDCLUS_HIGH: DW #FFFF ; !TODO for fat32 ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ; INCLUDE "FAT12_16.ASM" IF _FAT32_ENABLE INCLUDE "FAT32.ASM" ENDIF ;