;[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 ;--------------------------------------------------------------- ;----------------------------------------------------------------------; ; Поиск записи каталога в списке каталога ; ; вход: 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 ; оптимизация для индекса записи в списке каталога. ; Понадобится вернуть для перебора каталога > #4000 байт ; EXX ; LD DE,0 ; EXX ; .loop: LD A,(IX+_sFAT_DIRECTORY_RECORD.NAME) OR A JR Z,.error_file_not_found CP #E5 ;!HARDCODE #E5 - запись в директории свободна, так как файл/директория были удалены JR Z,.next_record LD A,(IX+_sFAT_DIRECTORY_RECORD.ATTRIBUT) 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 ;!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: ;!TEST 9/11/23 record index ; EXX ; INC DE ; EXX ; LD DE,#0020 ;!HARDCODE 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,#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 ; [x] fat32 ;!TEST ; выход: IY:DE - cluster number 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_H) LD D,(IX + _sFAT_DIRECTORY_RECORD.FIRST_CLUSTER_H+1) LD YH,D LD YL,E 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 ;----------------------------------------------------------------------; CHECK_ZERO_CLUSTER: EX DE,HL LD HL,(CORE_BUFFERS.FM_BUF + _sFM.FS_REC.FIRST_CLUSTER_L) ;R005 LD A,L OR H LD HL,(CORE_BUFFERS.FM_BUF + _sFM.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: ; fat32 EX DE,HL LD HL,(CORE_BUFFERS.FatBuffer.RootDirStartCluster_L) LD (CORE_BUFFERS.FM_BUF + _sFM.FS_REC.FIRST_CLUSTER_L),HL LD HL,(CORE_BUFFERS.FatBuffer.RootDirStartCluster_H) LD (CORE_BUFFERS.FM_BUF + _sFM.FS_REC.FIRST_CLUSTER_H),HL EX DE,HL CALL LOADDIR ; CF=0 LD HL,WorkDirectory LD (HL),'\' INC HL LD (HL),#00 ;AND A RET ; .SUBDIR: CP "." JR NZ,.SUBDIR2 ; fat32 CALL CHECK_ZERO_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 + _sFM.FS_REC.FIRST_CLUSTER_L),HL ; fat32 LD (CORE_BUFFERS.FM_BUF + _sFM.FS_REC.FIRST_CLUSTER_H),IY ; fat32 LD HL,#4000 ;!HARDCODE LD (CORE_BUFFERS.FM_BUF + _sFM.FS_REC.F_SIZE),HL ;EX DE,HL JP LOADDIR ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ; Прочитать список каталога ; [x] fat32 ;!TEST LOADDIR: ;!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 ; PUSH AF ; ;!TEST no ldir ; ; очистить кеш каталога ; ; LD HL,#C000 ; ; LD DE,#C001 ; ; LD BC,#3FFF ; ; LD (HL),L ; ; LDIR ; ; ; LD A,(CORE_BUFFERS.FatBuffer.DRIVE) ; номер диска ; LD (IY+_sFM.DRIVE),A ; сохр. в дескриптор ; ; номер первого кластера ; ; [x] fat32 ; LD A,(CORE_BUFFERS.FatBuffer.FAT_TYPE) ; XOR 32 ; JR Z,.read_dir ; ;!FIXIT переделать на работу без IY ; LD A,(IY+_sFM.FS_REC.FIRST_CLUSTER_L) ; OR (IY+_sFM.FS_REC.FIRST_CLUSTER_L+1) CALL LOAD_SAVE_DIR_PREPARE PUSH AF EX AF,AF' JR Z,.LoadRootDir .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.FatBuffer.RootDirFirstSector_H) ; ст. разряд LD IX,(CORE_BUFFERS.FatBuffer.RootDirFirstSector_L) ; номер лог. сектора LD A,(CORE_BUFFERS.FatBuffer.DirSizeInSectors) LD B,32 ; !HARDCODE sector size 512. 16384/(sector 512). размер root-каталога CP B JR NC,.RTD1 LD B,A ; число секторов .RTD1: LD A,(CORE_BUFFERS.FatBuffer.DRIVE) ; номер диска LD DE,DIRPAGE.buffer ; буфер LD C,Dss.DRV.Read ; чтение секторов RST ToDSS.DRV POP AF OUT (SLOT3),A RET ;----------------------------------------------------------------------; 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.FatBuffer.DRIVE) LD (IY+_sFM.DRIVE),A ; [x] fat32 LD A,(CORE_BUFFERS.FatBuffer.FAT_TYPE) CP FAT_TYPE.x32 - 1 JR NC,.exit ;!FIXIT переделать на работу без IY LD A,(IY+_sFM.FS_REC.FIRST_CLUSTER_L) OR (IY+_sFM.FS_REC.FIRST_CLUSTER_L+1) .exit: EX AF,AF' RET ;!TODO FAT procedures ;----------------------------------------------------------------------; ; Сбросить кеш каталога на диск. ; вход: iy=структура дескриптора ; [x] fat32 ;!TEST SAVEDIR: ;!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 ; PUSH AF ; ; ; LD A,(CORE_BUFFERS.FatBuffer.DRIVE) ; LD (IY+_sFM.DRIVE),A ; ; [x] fat32 ; LD A,(CORE_BUFFERS.FatBuffer.FAT_TYPE) ; XOR 32 ; JR Z,.save_dir ; ;!FIXIT переделать на работу без IY ; LD A,(IY+_sFM.FS_REC.FIRST_CLUSTER_L) ; OR (IY+_sFM.FS_REC.FIRST_CLUSTER_L+1) CALL LOAD_SAVE_DIR_PREPARE PUSH AF EX AF,AF' JR Z,.SaveRootDir .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.FatBuffer.RootDirFirstSector_H) LD IX,(CORE_BUFFERS.FatBuffer.RootDirFirstSector_L) LD A,(CORE_BUFFERS.FatBuffer.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.FatBuffer.DRIVE) LD DE,DIRPAGE.buffer LD C,Dss.DRV.Write RST ToDSS.DRV POP AF OUT (SLOT3),A RET ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ; скопировать запись в список диска (каталога) de ix iy ; и сбросить кеш каталога на диск ; вход: (HANDBUF) - запись каталога WRT_HND: SET_PAGE_X DIRPAGE EX AF,AF' ; ;LD IX,DIRPAGE.buffer LD HL,DIRPAGE.buffer ;!TEST 9/11/23 record index ; 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 ;!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.FatBuffer.BytesPerCluster) ADD HL,BC LD (SAVEDIR.DIRSIZE),HL AND A JP SAVEDIR ;----------------------------------------------------------------------; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ; не используется ; TESTDSK: ;????? возможно, что тут логичнее, чем в начале OPENDSK, если будет работать Dss.DRV.Open ; LD A,(CORE_BUFFERS.FatBuffer.DRIVE) ; LD C,Dss.DRV.MediaCheck ; RST ToDSS.DRV ; OR A ; RET Z ; рег. A - номер диска ; [ ] fat32 RD_BPB: LD C,SLOT3 IN B,(C) PUSH BC IN A,(SLOT0) OUT (SLOT3),A LD A,(CORE_BUFFERS.FatBuffer.DRIVE) 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 ; 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 ; [x] fat32 ; LD HL,CORE_BUFFERS.SECBUF ; LD DE,CORE_BUFFERS.BootSector ; LD BC,_sBOOT_SECTOR_PARAMS_FAT32 ; size ; LDIR ; LD A,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.DRIVE_TYPE) CP #F0 JP C,DOS_X_Error.UnknownBPB ; ;!TODO проверить по метке раздела, что это FAT, потом определять какой FAT ; LD HL,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.BytesPerSector) LD (CORE_BUFFERS.FatBuffer.BytesPerSector),HL LD A,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.SectorsPerCluster) LD (CORE_BUFFERS.FatBuffer.SectorsPerCluster),A LD HL,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.BPB_SERIAL_NUMBER) LD (CORE_BUFFERS.FatBuffer.BPB_SERIAL_NUMBER),HL LD HL,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.BPB_SERIAL_NUMBER+2) LD (CORE_BUFFERS.FatBuffer.BPB_SERIAL_NUMBER+2),HL ; calc. first sector FAT LD HL,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.RESERVED_SECTORS) ; ; LD E,(IY+_sBOOT_SECTOR_PARAMS.HIDDEN) ;Hidden sec ; LD D,(IY+_sBOOT_SECTOR_PARAMS.HIDDEN+1) ; ADD HL,DE ; ;!FIXIT для fat32 втыкать сюда сектора активной таблицы LD (CORE_BUFFERS.FatBuffer.FAT1_SEC_L),HL ; low word first sector FAT #1 LD (CORE_BUFFERS.FatBuffer.FAT2_SEC_L),HL ; low word first sector FAT #2 ;[ ] fat32 XOR A LD B,A LD C,A LD (CORE_BUFFERS.FatBuffer.FAT1_SEC_H),BC ; high word first sector FAT #1 ; [ ] fat32 LD (CORE_BUFFERS.FatBuffer.FAT2_SEC_H),BC ; high word first sector FAT #1 ; [ ] fat32 LD (CORE_BUFFERS.FatBuffer.RootDirStartCluster_L),BC ; [ ] fat32 LD (CORE_BUFFERS.FatBuffer.RootDirStartCluster_H),BC ; [ ] fat32 LD (CORE_BUFFERS.FatBuffer.END_CHAIN_CLUSTER_H),BC ; [ ] fat32 reset variables LD (CORE_BUFFERS.FatBuffer.MaxClusterHigh),BC ; [ ] fat32 reset variables LD (CORE_BUFFERS.FatBuffer.SectorsPerFAT_H),A ; [ ] fat32 ; ; LD DE,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.SectorsPerFAT16) LD A,E OR D JR NZ,.skip_high ; LD BC,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS_FAT32.SectorsPerFAT32+4) LD A,C LD (CORE_BUFFERS.FatBuffer.SectorsPerFAT_H),A LD DE,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS_FAT32.SectorsPerFAT32) .skip_high: LD (CORE_BUFFERS.FatBuffer.SectorsPerFAT_L),DE ; LD A,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.Number_of_FATs) ; amount FATs CP 1 JR Z,.one_FAT DEC A ADD HL,DE LD (CORE_BUFFERS.FatBuffer.FAT2_SEC_L),HL JR NC,.no_inc_BC INC BC .no_inc_BC: LD (CORE_BUFFERS.FatBuffer.FAT2_SEC_H),BC .one_FAT: ;C_DATA1 .loop1: ADD HL,DE JR NC,.loop1_1 INC BC .loop1_1: DEC A JR NZ,.loop1 ; LD (CORE_BUFFERS.FatBuffer.RootDirFirstSector_L),HL ; first sector DIR LD BC,(CORE_BUFFERS.FatBuffer.BytesPerSector) LD A,B AND A ; RL C RLA RL C RLA RL C RLA ; LD C,A LD B,0 ; BC - File handels in sectors ;;;; IF COMPILE_UNUSED_CODE LD (CORE_BUFFERS.FatBuffer.FilesPerSector),A ENDIF ; EX DE,HL LD HL,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.FilesInRootDIR) ; 0 for fat32 DEC HL ; [ ]fat32 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 (CORE_BUFFERS.FatBuffer.DirSizeInSectors),A ADD HL,BC ; Start DATA area LD (CORE_BUFFERS.FatBuffer.FirstDataSector_L),HL ; B = 0 ; LD HL,(CORE_BUFFERS.FatBuffer.BytesPerSector) LD A,(CORE_BUFFERS.FatBuffer.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.FatBuffer.BytesPerCluster),HL ; IF COMPILE_UNUSED_CODE 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.FatBuffer.ClustersPerBank),A ; A - Clusters per bank (16k) ENDIF //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// ; LD HL,CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.ID_FAT ;!!!!! а если IY используется для переменного BootSector, то будет бага ; LD DE,FAT_STRING ; 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' ; JP Z,.fat1x ; CP '3' ; JP NZ,DOS_X_Error.UnknownBPB ; LD A,#52 ; #52-#20 = #32 fat type ; LD HL,#0FFF ; LD (CORE_BUFFERS.FatBuffer.END_CHAIN_CLUSTER_H),HL ; LD (CORE_BUFFERS.FatBuffer.MaxClusterHigh),HL ; [ ] fat32 ;!FIXIT ; LD H,L ; JR .BPB_FAT ; ; ; .fat1x: LD A,(HL) ; CP '2' ; FAT16 ; LD HL,#0FFF ; JR Z,.BPB_FAT ; CP '6' ; FAT12 ; JP NZ,DOS_X_Error.UnknownBPB ; LD H,L ; .BPB_FAT: SUB #20 ; A-#20 = fat type (#12, #16, #32) ; LD (CORE_BUFFERS.FatBuffer.FAT_TYPE),A ; LD (CORE_BUFFERS.FatBuffer.END_CHAIN_CLUSTER_L),HL ;!TODO не используется значение вычисляемое и сохраняемое в FatBuffer //////////////////////////////////////////////////////////////////////// ; LD HL,0 ; LD BC,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.SectorsPerTrack) ; Sector per track ; LD A,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.HEADS) ; .BPB_L1: ; calc. sector per cylinder ; ADD HL,BC ; DEC A ; JR NZ,.BPB_L1 ; LD (CORE_BUFFERS.FatBuffer.S_X_H),HL //////////////////////////////////////////////////////////////////////// ; [ ] fat32 LD HL,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.SectorsPerDrive) LD DE,(CORE_BUFFERS.FatBuffer.FirstDataSector_L) LD A,H OR L JP NZ,.HDDSMAL ; LD HL,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.BPB_BIG_TOTAL_SECTORS_L) LD BC,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.BPB_BIG_TOTAL_SECTORS_H) PUSH BC ; Total Sectors high PUSH HL ; Total Sectors low AND A SBC HL,DE 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: LD A,(CORE_BUFFERS.FatBuffer.SectorsPerCluster) SCF .loop7: RRA JR C,.loop7_exit RR B RR C RR H RR L JP .loop7 ; .loop7_exit: INC HL LD (CORE_BUFFERS.FatBuffer.MaxClusterLow),HL ; XOR A LD H,A LD L,A LD (CORE_BUFFERS.FatBuffer.CacheBlock),HL LD (CORE_BUFFERS.FatBuffer.CacheUpdated),A ; A = 0 LD HL,(CORE_BUFFERS.FatBuffer.SectorsPerFAT_H) LD H,A EX DE,HL LD HL,(CORE_BUFFERS.FatBuffer.SectorsPerFAT_L) ; DE:HL = SectorsPerFAT ; LD A,(CORE_BUFFERS.SECBUF + _sBOOT_SECTOR_PARAMS.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.FatBuffer.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.SECBUF + _sBOOT_SECTOR_PARAMS.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.FatBuffer.SectorsPerCluster) ; HL:DE / A => DE:BC, H=0, L - остаток CALL DIV_for_SPC ; выясняем разрядность FAT LD A,D OR E JR NZ,.its_FAT32 ; LD HL,4084 SBC HL,BC JR NC,.its_FAT12 ; LD HL,65525 SBC HL,BC JR C,.its_FAT32 ; ; It's FAT16 LD A,FAT_TYPE.x16 LD HL,#FFFF JR .BPB_FAT ; .its_FAT12: LD HL,#0FFF LD A,FAT_TYPE.x12 JR .BPB_FAT ; .its_FAT32: LD A,FAT_TYPE.x32 LD HL,#0FFF LD (CORE_BUFFERS.FatBuffer.END_CHAIN_CLUSTER_H),HL LD (CORE_BUFFERS.FatBuffer.MaxClusterHigh),HL ; [ ] fat32 ;!FIXIT LD H,L ; .BPB_FAT: LD (CORE_BUFFERS.FatBuffer.FAT_TYPE),A LD (CORE_BUFFERS.FatBuffer.END_CHAIN_CLUSTER_L),HL ; SET_PAGE_X FATPAGE PUSH AF ; [ ] fat32 ; XOR A ; HL = 0 ; EX DE,HL ; LD DE,0 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.SECBUF + _sBOOT_SECTOR_PARAMS.DRIVE_TYPE) CP #F0 JR C,DOS_X_Error.UnknownBPB ; ID ram-диска - #FA CP #F8 ; !FIXIT fat. не обязательно если винт, то не FAT12 LD A,'2' LD HL,#0FFF JP NZ,.BPB_FAT ; LD A,'6' LD H,L JP .BPB_FAT ; 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 к буферам! /* FatBuffer: ;.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 ; количество секторов на цилиндре ; ????? это используется? ; */ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////