diff --git a/DSS/API/Delete.asm b/DSS/API/Delete.asm index eb991bb..d5802d9 100644 --- a/DSS/API/Delete.asm +++ b/DSS/API/Delete.asm @@ -19,7 +19,7 @@ DEL_FN: ; Current Dir 15/10/23 CALL CHECK_NAME RET Z ; - CALL LOADDIR ; [ ] big dir + CALL LOADDIR ; [ ] big dir ; !FIXIT дублирует действие из SetPath_GetName? CALL SEARCH.File RET C JP DELETE_REC_FAT ; пометить запись как "удаленная" diff --git a/DSS/API/Rename.asm b/DSS/API/Rename.asm index 33e703d..748eceb 100644 --- a/DSS/API/Rename.asm +++ b/DSS/API/Rename.asm @@ -35,7 +35,9 @@ RENAME: ; Current Dir 15/10/23 RET Z ; PUSH DE - CALL LOADDIR ; [ ] big dir ; прочитать список каталога + ; !FIXIT дублирует действие и директория уже загружена? + CALL LOADDIR ; [ ] big dir ; прочитать список каталога + ; LD A,FAT_ATTR.NoSYSnoVolID CALL SEARCH.Custom ; поиск записи "old_name.ext" в списке диска POP HL diff --git a/DSS/API/RmDir.asm b/DSS/API/RmDir.asm index 4228525..07ac362 100644 --- a/DSS/API/RmDir.asm +++ b/DSS/API/RmDir.asm @@ -32,7 +32,7 @@ RMDIR: ; Current Dir 15/10/23 CALL CHECK_NAME RET Z ; - CALL LOADDIR ; [ ] big dir + CALL LOADDIR ; [ ] big dir ; !FIXIT дублирует действие из SetPath_GetName? CALL SEARCH.Dir RET C ; fat32 ; [ ] CDFS diff --git a/DSS/DOS_FS.ASM b/DSS/DOS_FS.ASM index b3bda7c..a3a0717 100644 --- a/DSS/DOS_FS.ASM +++ b/DSS/DOS_FS.ASM @@ -36,9 +36,10 @@ GetName: LD BC,#08FF ;!HARDCODE ;----------------------------------------------------------------------; ; old GETWORD -; Тест на допустимое имя и настроиться на диск. +; Тест на допустимое имя и настройка на диск. ; вход: hl=строка имени ; выход: (TMPNAME) +; !FIXIT оптимизировать обращения к этой функции, а то могут быть дублирующие вызовы подряд SetPath_GetName: INC HL LD A,(HL) diff --git a/DSS/FS/FAT.asm b/DSS/FS/FAT.asm index 70ac624..ca904b1 100644 --- a/DSS/FS/FAT.asm +++ b/DSS/FS/FAT.asm @@ -1,10 +1,21 @@ ; [ ] RST_FS ;----------------------------------------------------------------------; -;███████████████████████████████████████████████████████████████████████████████████████████████████████; ; MODULE FAT_FS MODULE_START EQU $ +;███████████████████████████████████████████████████████████████████████; +;███████████████████████████████████████████████████████████████████████; + + + +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; +; Служебные FAT +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; + +;----------------------------------------------------------------------; SET_FSInfo: LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE) CP FAT_TYPE.x32 RET NZ @@ -81,842 +92,12 @@ RW_SECTOR: IN A,(SLOT3) OUT (SLOT3),A EX AF,AF' RET -; - -; [ ] удаление записи LFN -; -; вход: IX = указатель на текущую запись в странице с каталогом FAT для которой -; надо удалить записи LFS -; [ ] big dir -DELETE_LFN_RECORDS: - PUSH IX - LD A,XH - AND #C0 - DEC A - ;SUB 1 - LD C,A - ; В регистре C маска для определения выхода за пределы страницы - ; -.find_LFN: LD DE, -(FAT_DIRECTORY_RECORD) - LD A,FAT_ATTR.LFS_Entry - ; -.loop: ADD IX,DE - LD A,XH - CP C - JR Z,.beyond_boundaries ; [ ] big dir тут надо подгружать предыдущий DIR_BLOCK - ; - 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 -;----------------------------------------------------------------------; - - -; Поиск записи каталога в списке каталога -; -; вход: 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 - ;!TEST 9/11/23 record index - EXX - LD DE,0 - EXX - ; -.loop_big: LD IX,DIRPAGE.buffer -.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,CORE_BUFFERS.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 ; record index - ; EXX - ;PUSH IX - ; - LD HL,CORE_BUFFERS.HANDBUF - EX DE,HL - LD BC,CORE_BUFFERS.HANDBUF.SIZE - LDIR - ; record index - ;POP DE - POP AF - ;EX AF,AF' - OUT (SLOT3),A - ;EX AF,AF' - AND A - EXX ; record index - RET - ; -.next_record: ;!TEST 9/11/23 record index - EXX - INC DE - EXX - ; - LD DE,FAT_DIRECTORY_RECORD - ADD IX,DE - JR NC,.loop -.error_too_many_files: - ; [ ] big dir - LD A,(F_FIRST.FNDMODE) ;!FIXIT big dir - неправильно использовать это, надо новую переменную - RLA - JR C,.readDirNext - ; - ;EX AF,AF' - POP AF - OUT (SLOT3),A - LD A,DSS_Error.sys.TOO_MANY_FILES_IN_DIR - SCF - RET - ; -.error_file_not_found: - ;EX AF,AF' - POP AF - OUT (SLOT3),A - LD A,DSS_Error.sys.FILE_NOT_FOUND - SCF - RET - ; -; SLOT3 = DIRPAGE -; CF=1 -; A' = страница до вызова функции -; !FIXIT root dir in LOADDIR -; !FIXIT если в кэш были изменения? -.readDirNext: SBC A,A ; ZF=0 - IN A,(SLOT3) - LD B,A - EX AF,AF' - PUSH HL - PUSH BC - EXX - PUSH DE ; record index - ; - CALL LOADDIR.next - ; - POP DE - EXX - POP BC - POP HL - LD A,B - OUT (SLOT3),A - JR NC,.loop_big - JR .error_file_not_found -;----------------------------------------------------------------------; - -; -;!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 -; выход: 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,CORE_BUFFERS.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,.ITs_DIR - LD HL,CORE_BUFFERS.WorkDirectory - LD D,H - LD E,L - INC HL - LD BC,CORE_BUFFERS.WorkDirectory.DEPTH - XOR A - CPIR - JP PO,.error ;[x] 20/11/23 проверка на выход за границы - DEC HL ;R009 - DEC HL - LD BC,CORE_BUFFERS.WorkDirectory.DEPTH - LD A,'\' - CPDR - INC HL - EX DE,HL - ; CF = 0 - SBC HL,DE - EX DE,HL - JR NZ,.MM3 - INC HL -.MM3: LD (HL),0 - JP .ITs_DIR - ; -.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 - ; -.ITs_DIR: ; fat32 - LD E,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H) - LD D,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H+1) - LD YH,D - LD YL,E - LD E,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L) - LD D,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L+1) - POP AF - OUT (SLOT3),A - AND A - RET - ; -.CHECK_SLASH: XOR A - CPIR - ;[x] 20/11/23 проверка на выход за границы - SCF - RET PO - ; - DEC HL - DEC HL - LD A,'\' ; #5C - CP (HL) - INC HL - RET Z - LD (HL),A - INC HL - XOR A ; сброс CF заодно - LD (HL),A - RET -;----------------------------------------------------------------------; - - -;----------------------------------------------------------------------; -; Вход: IY - указатель на начало файлового манипулятора -CHECK_ROOT_CLUSTER: - LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE) - CP FAT_TYPE.x32 - JR NZ,CHECK_FIRST_CLUSTER - ; - LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L) - LD BC,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L) - SBC HL,BC - RET NZ - ; - LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H) - LD BC,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H) - SBC HL,BC - RET -;----------------------------------------------------------------------; - - -;----------------------------------------------------------------------; -; SET_FAT_ROOT_DIR_CLUSTER: -; EX DE,HL -; LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L) -; LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL -; LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H) -; LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),HL -; EX DE,HL -; RET -;----------------------------------------------------------------------; - - -;----------------------------------------------------------------------- -; вход: IY - указатель на начало файлового манипулятора -; выход: HL':HL - first cluster -; ZF = 0 если первого кластера нет -CHECK_FIRST_CLUSTER: - EXX - LD L,(IY+_sFM.FS_REC.FIRST_CLUSTER_H) ; START CLUSTER High - LD H,(IY+_sFM.FS_REC.FIRST_CLUSTER_H+1) - LD A,L - OR H - EXX - LD L,(IY+_sFM.FS_REC.FIRST_CLUSTER_L) ; START CLUSTER - LD H,(IY+_sFM.FS_REC.FIRST_CLUSTER_L+1) - OR L - OR H - RET -;----------------------------------------------------------------------- - - -;----------------------------------------------------------------------; -; вход: HL - имя директории -OPENDIR: LD IY,CORE_BUFFERS.FM_BUF - LD A,(HL) - OR A - JR NZ,.SUBDIR - ; -.REROOT: EX DE,HL - LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L) - LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL - LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H) - LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),HL - EX DE,HL -.reroot: CALL LOADDIR ; [ ] big dir - ; CF=0 - LD HL,CORE_BUFFERS.WorkDirectory - LD (HL),'\' - INC HL - LD (HL),#00 - ;AND A - RET - ; -.SUBDIR: CP "." - JR NZ,.SUBDIR2 - ; fat32 - ; !TEST 04/01/2026 - EX DE,HL - CALL CHECK_ROOT_CLUSTER - ;CALL CHECK_FIRST_CLUSTER - EX DE,HL - ; - JR NZ,.no_root ;R005 - ; "cd ." or "cd .." - ;R005 - INC HL - LD A,(HL) - OR A - DEC HL - JR Z,.reroot - ; -.no_root: EXX - LD HL,CORE_BUFFERS.MASKARE - LD DE,CORE_BUFFERS.MASKARE+1 - LD BC,10 ;!HARDCODE - LD (HL),' ' - LDIR - EXX - LD DE,CORE_BUFFERS.MASKARE -.loop: LDI - LD A,(HL) - OR A - JR NZ,.loop - JR .SUBDIR3 - ; -.SUBDIR2: 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 - ; [ ] big dir - ; ... - ; - ;LD HL,#4000 ;!HARDCODE - ;LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),HL -;-------------; EX DE,HL -; JP LOADDIR - -; Прочитать список каталога -; вход (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L), (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H) -LOADDIR: ;!TODO optimize - LD HL,0 -.Custom: CALL LOAD_SAVE_DIR_PREPARE -.next: PUSH AF - EX AF,AF' - ;JR NZ,.read_dir ; root dir or not - ; root dir - ;LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE) - ;CP FAT_TYPE.x32 - JR Z,.LoadRootDir - CALL LOAD_SAVE_DIR_PREPARE.CalcDirSize - ; 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,DIRPAGE.size ; размер директории ;!HARDCODE - ; LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),HL - ; -.read_dir: LD HL,DIRPAGE.buffer ; куда - LD DE,DIRPAGE.size ; сколько - XOR A ; дескриптор - CALL READ ; чтение из файла - EX AF,AF' - LD (SAVEDIR.DIRSIZE),DE ; число прочит. байтов - POP AF - OUT (SLOT3),A - EX AF,AF' - 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-каталога ; [ ] sector size 512 - CP B - JR NC,.RTD1 - ; - LD B,A ; число секторов -.RTD1: LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) ; номер диска - LD DE,DIRPAGE.buffer ; буфер - LD C,Dss.DRV.Read ; чтение секторов - RST ToDSS.DRV - ; !FIXIT нет проверки на ошибку - ; 21/04/2025 fix мусор в странице каталога, если каталог меньше страницы - BIT 7,D - JR Z,.exit - XOR A - LD (DE),A - ; -.exit: POP AF - OUT (SLOT3),A - RET ;----------------------------------------------------------------------; -; [ ] доделать передачу ID записи директории и загрузки по ней нужного куска в кэш -;!TODO FAT procedures ;----------------------------------------------------------------------; -; Вход: -; HL - ID записи, который должен попасть в КЭШ -; Выход: A - Страница, которая была в SLOT3 до вызова -; ZF' - RootDir FAT12-16 -LOAD_SAVE_DIR_PREPARE: - ; [ ] Вход: HL - ID записи, который должен попасть в КЭШ - ; [ ] Выход: HLIX - смещение в файле каталога на нужный блок по #4000 байтов - ; HLIX = (HL*32) & #1FC000 смещение на нужный блок по #4000 байтов - XOR A - LD XL,A - LD E,A - LD A,H - LD H,E - AND #FE - RRA - RR E - LD (CORE_BUFFERS.FS_Buffer.DIR_BLOCK),A - RRA - RR E - RRA - RR E - LD XH,E - LD L,A - ; ; - ; - 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.FS_Buffer.DRIVE) - LD (CORE_BUFFERS.FM_BUF.DRIVE),A - ;;;;;;;; - XOR A - ;LD D,#40 - ;LD E,A - LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L) - EXX - ;LD D,A - ;LD E,A - LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H) - OR H - OR L - EXX - OR H - OR L - ;;;;;;;; - ;PUSH AF - ;CALL NZ,.CalcDirSize - ; - ; LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),DE - ; EXX - ; LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE + 2),DE - ;POP AF - EX AF,AF' - POP AF - RET - ; -.CalcDirSize: ; calc dir size in clusters - LD DE,0 - ;LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L) - ;EXX - ; LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H) -.loop: ; ; - ;EXX - INC DE ; Надеемся тут на то, что спецификация выполняется и переполнения не будет - PUSH DE - CALL READ_FROM_FAT - EX DE,HL - POP DE - EXX - EX DE,HL - EXX - JR NC,.loop - ; - ; DE - размер директории в кластерах - ;!FIXIT можно оптимизнуть кол-во сдвигов - ;0001 0000 0000 0000 max кол-во кластеров - ; пример - ;0000 0000 0000 0111 Clusters - ; 0100 0000 SectorsPerCluster - ;0000 0010 0000 0000 BytesPerSector - ; D' E' D E - ;0000 0000 0000 0011 1000 0000 0000 0000 - ; - LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster) - LD BC,(CORE_BUFFERS.FS_Buffer.BytesPerSector) - ; DE':DE - кол-во кластеров - ; A - размер кластера в секторах - ; BC - размер сектора в байтах - ; --> DE*BC*A = DE':DE для ответа хватит, походу, 4х регистров - EXX - LD DE,0 - EXX - SRL B - RR C - RRCA - JR C,.loop2 - ; -.loop1: ; - SLA E - RL D - EXX - RL E - RL D - ;RL C - EXX - ; - RRCA - JR NC,.loop1 - ; -.loop2: ; - SLA E - RL D - EXX - RL E - RL D - ;RL C - EXX - ; - SRL B - RR C - JR NC,.loop2 - ; <-- DE*BC*A = DE':DE - LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),DE - EXX - LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE + 2),DE - RET - -/* 4 3 2 1 - #FFFF<<5 = #1FFFE0 = 0000 0000 0001 1111 1111 1111 1110 0000 - - #FFFF номер записи - #1FFFE0 смещение на запись в файле директории - #1FFFE0 & #1FC000 смещение на нужный блок по #4000 байтов - #1FFFE0 & #3FFF Адрес нужной позиции в кэш - (#1FFFE0 & #1FC000)<<2 двигаем байт 2 и 3 чтоб получить номер блока -*/ -;----------------------------------------------------------------------; - - - -; [ ] big dir -; скопировать запись в список диска (каталога) de ix iy -; и сбросить кеш каталога на диск -; вход: (HANDBUF) - запись каталога -; выход: DE - record index -WRITE_DIR_HANDLE: - SET_PAGE_X DIRPAGE - EX AF,AF' - LD HL,DIRPAGE.buffer - ;!TEST 9/11/23 record index - EXX - LD DE,0 - EXX - ; - LD BC,FAT_DIRECTORY_RECORD -.loop: ;LD A,(IX+00) - LD A,(HL) - OR A - JR Z,.WRT_HN2 - CP #E5 - JR Z,.WRT_HN2 - ;ADD IX,BC - ADD HL,BC - JR NC,.loop ;!FIXIT количество записей каталога = страница - ; - EX AF,AF' - OUT (SLOT3),A - LD A,DSS_Error.sys.ROOT_OVERFLOW - SCF - RET - ; -.WRT_HN2: ;LD D,XH - ;LD E,XL - EX DE,HL - LD HL,CORE_BUFFERS.HANDBUF - LD BC,CORE_BUFFERS.HANDBUF.SIZE - LDIR - EX AF,AF' - OUT (SLOT3),A - ; проверяем, увеличился ли размер данных директории - LD HL,DIRPAGE.buffer - LD BC,(SAVEDIR.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 -.SAVEDIR: EXX - PUSH DE - EXX - ; [ ] big dir передавать откуда и сколько байтов изменилось в кэш, чтоб не писать на диск лишнего - CALL SAVEDIR - POP DE - RET -;----------------------------------------------------------------------; - ASSERT 0 "TODO! GET_ADDR_IN_DIR_CACHE" -;!TODO -; .DIRSIZE помешает если в кэш будет другая страница? -; LOAD_SAVE_DIR_PREPARE возможно не нужен, нужно только установить правильное смещение в FM -; Может вообще переделать её под работу с КЭШ - -; Сбросить кеш каталога на диск. -; вход: iy=структура дескриптора -; [ ] big dir получать откуда и сколько байтов изменилось в кэш, чтоб не писать на диск лишнего -SAVEDIR: ;!TODO optimize - CALL LOAD_SAVE_DIR_PREPARE - PUSH AF - EX AF,AF' - ;JR NZ,.save_dir - JR Z,.SaveRootDir - ; - ;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 - ; - ; FAT12-16 -.SaveRootDir: LD HL,(CORE_BUFFERS.FS_Buffer.RootDirFirstSector_H) ;!TODO возможно, хватит LD HL,0 - LD IX,(CORE_BUFFERS.FS_Buffer.RootDirFirstSector_L) - LD A,(CORE_BUFFERS.FS_Buffer.DirSizeInSectors) - LD B,32 ;!HARDCODE sector size 512, Root Dir max size in sectors - SUB B - JR NC,.RTD1S - ADD A,B - LD B,A -.RTD1S: LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) - LD DE,DIRPAGE.buffer - LD C,Dss.DRV.Write - RST ToDSS.DRV - POP AF - OUT (SLOT3),A - RET -;----------------------------------------------------------------------; - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -; [x] fat32 -; RD_BPB: CALL READ_BPB +; RD_BPB: CALL READ_BPB ; RET C ; ; ; LD DE,#AA55 ; сигнатура ;R05 @@ -927,12 +108,6 @@ SAVEDIR: ;!TODO optimize ; 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 @@ -940,16 +115,15 @@ FAT_BPB: LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.DRIVE_TYPE) XOR A LD (.UsesVarsFAT32),A ; - ;EXX - LD H,A - LD L,A - LD D,A - LD E,A + LD H,A + LD L,A + LD D,A + LD E,A EXX - ;[ ] fat32 + ; fat32 LD B,A LD C,A - LD (CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H),A ; [ ] fat32 + LD (CORE_BUFFERS.FS_Buffer.SectorsPerFAT_H),A ; fat32 ; LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.BytesPerSector) LD (CORE_BUFFERS.FS_Buffer.BytesPerSector),HL @@ -957,14 +131,18 @@ FAT_BPB: LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.DRIVE_TYPE) 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 - LD (CORE_BUFFERS.FS_Buffer.FAT1_SEC_H),BC ; high word first sector FAT #1 ; [ ] fat32 - LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_H),BC ; high word first sector FAT #1 ; [ ] fat32 - LD (CORE_BUFFERS.FS_Buffer.RootDirFirstSector_H),BC - ;LD (CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_H),BC ; [ ] fat32 reset variables + LD (CORE_BUFFERS.FS_Buffer.FAT1_SEC_L),HL ; low word first sector FAT #1 + LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_L),HL ; low word first sector FAT #2 ; + ; BC = 0 + ; fat32 + LD (CORE_BUFFERS.FS_Buffer.FAT1_SEC_H),BC ; high word first sector FAT #1 ; fat32 + LD (CORE_BUFFERS.FS_Buffer.FAT2_SEC_H),BC ; high word first sector FAT #1 ; fat32 + LD (CORE_BUFFERS.FS_Buffer.RootDirFirstSector_H),BC + ;LD (CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_H),BC ; fat32 reset variables + ; зануляем параметры директории для первого обращения + ; LD (CORE_BUFFERS.FM_BUF.FIRST_CLUSTER_L),BC + ; LD (CORE_BUFFERS.FM_BUF.FIRST_CLUSTER_H),BC ; LD DE,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.SectorsPerFAT16) LD A,E @@ -1077,7 +255,7 @@ FAT_BPB: LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.DRIVE_TYPE) ;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 @@ -1097,8 +275,8 @@ FAT_BPB: LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.DRIVE_TYPE) ; DEC A ; JR NZ,.BPB_L1 ; LD (CORE_BUFFERS.FS_Buffer.S_X_H),HL -//////////////////////////////////////////////////////////////////////// - ; [ ] fat32 +////////////////////////////////////////////////////////////////// + ; fat32 LD HL,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.SectorsPerDrive) LD A,H OR L @@ -1366,8 +544,11 @@ FAT_BPB: LD A,(CORE_BUFFERS.SECTOR_BUFFER + BOOT_SECTOR.DRIVE_TYPE) RET ; .UsesVarsFAT32: DB 0 -;;;;;;;; +;----------------------------------------------------------------------; + + +;----------------------------------------------------------------------; ; --> BC:HL - Sector ; <-- BC:HL - Cluster SectorToCluster: @@ -1383,8 +564,11 @@ SectorToCluster: RR H RR L JP .loop -; +;----------------------------------------------------------------------; + + +;----------------------------------------------------------------------; ; HL:HL' - first FAT sector ; DE:DE' - sectors per one FAT ; A - number of FATs (counts from 0) @@ -1395,141 +579,11 @@ ALL_SECTORS_PER_FATs: EXX DJNZ ALL_SECTORS_PER_FATs RET - -; 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 - указатель на номер записи в каталоге -; Выход: HL - смещение в SLOT3 на запись в каталоге -GET_ADDR_IN_DIR_CACHE: - LD A,3 - PUSH IX - POP HL - RR H - ; - RR L - RRA - RR L - RRA - RR L - RRA - LD H,L - LD L,A - LD A,H - OR #C0 - LD H,A - RET - - -; Удаляет запись в каталоге и освобождает занятую цепочку кластеров -; Вход: IX - указатель на удаляемую запись в DIRPAGE -; в КЭШ директории должна быть загружена часть с нужной записью -;!TODO record index. возможно, что может сломаться, если больше страницы -DELETE_REC_FAT: SET_PAGE_X DIRPAGE - EX AF,AF' - ;CALL DELETE_LFN_RECORDS ; [ ] big dir ; [x] удаление записи LFN - LD (IX + FAT_DIRECTORY_RECORD.NAME),#E5 ; признак удаления файла - ; fat32 - LD L,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H) ; № первого кластера - LD H,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H+1) - LD A,L - OR H - EXX - LD L,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L) ; № первого кластера - LD H,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L+1) - OR L - OR H - ; - EX AF,AF' - OUT (SLOT3),A - EX AF,AF' - ; [ ] big dir передавать откуда и сколько байтов изменилось в кэш, чтоб не писать на диск лишнего - JP Z,SAVEDIR ; сбросить кеш каталога на диск - ; если размер файла не ноль -.loop: ;EX DE,HL ; hl=номер кластера - ;EXX - ; EX DE,HL - ;EXX - CALL READ_FROM_FAT ; прочитать из кеша FAT-а номер след. кластера - EXX - PUSH DE ; номер след. кластера - PUSH AF - LD DE,#0000 ; номер кластера - EXX - PUSH DE - ; - CALL SET_NEW_FREE_CLUSTER - ; - LD DE,#0000 ; номер кластера - CALL WRITE_TO_FAT.Custom ; записать в кеш FAT-а номер кластера - POP HL - EXX - POP AF - POP HL - ;EX DE,HL - EXX - ;EX DE,HL - JP NC,.loop - CALL WRITE_FAT_TABLE - ; [ ] big dir передавать откуда и сколько байтов изменилось в кэш, чтоб не писать на диск лишнего - JP SAVEDIR ; сбросить кеш каталога на диск - +;----------------------------------------------------------------------; ; Установить первым известным кластером для поиска свободного. ; Установится только если меньше предыдущего ; Вход: HL':HL - cluster @@ -1568,7 +622,11 @@ SET_NEW_FREE_CLUSTER: ; LD (CORE_BUFFERS.FS_Buffer.RESET_FSINFO),A ; RET -; +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; ; найти первый свободный кластер ;!TODO проверить перебор кластеров ; выход: HL - младший номер свободного кластера ; HL' - старший номер свободного кластера @@ -1606,7 +664,11 @@ G_CLUST: ; INC A LD (CORE_BUFFERS.FS_Buffer.UPD_FSINFO),A RET +;----------------------------------------------------------------------; + + +;----------------------------------------------------------------------; ; Вход: A - уменьшить (0) или увеличить (!0) число свободных кластеров SET_NEW_FREE_CLUSTERS: EX AF,AF @@ -1661,8 +723,11 @@ SET_NEW_FREE_CLUSTERS: EXX JP .set_new ; ; +;----------------------------------------------------------------------; -; + + +;----------------------------------------------------------------------; ; Прикрепить к последнему кластеру цепочки новый пустой кластер ; Вход: HL':HL - номер кластера к которому прикрепить пустой ; Выход: HL':HL - номер кластера к которому прикрепился пустой @@ -1711,9 +776,11 @@ INC_FAT: PUSH HL ; тек XOR A ; уменьшить CALL SET_NEW_FREE_CLUSTERS ; [ ] free clusters for FSInfo RET +;----------------------------------------------------------------------; +;----------------------------------------------------------------------; ; вход: hl = младшее слово номера кластера для сравнения с FAT_Max_Cluster ; hl' = старшее слово номера кластера для сравнения с FAT_Max_Cluster (только для fat32) CHECK_CLUSTER_IS_SMALLER: @@ -1738,9 +805,11 @@ CHECK_CLUSTER_IS_SMALLER: EX DE,HL LD A,DSS_Error.sys.DISK_FULL RET -; +;----------------------------------------------------------------------; -; + + +;----------------------------------------------------------------------; ;------------------------------------------------------------------------------------------------ ; Прочитать из кеша FAT-а номер след. кластера ; вход: hl - номер кластера (младшее слово) @@ -1762,7 +831,9 @@ READ_FROM_FAT: CALL CHECK_CLUSTER_IS_SMALLER 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) ; прочитать номер кластера @@ -1793,10 +864,12 @@ READ_FROM_FAT: CALL CHECK_CLUSTER_IS_SMALLER LD D,(HL) LD HL,SERVICE_SECTORS.FAT12 JR NC,.Correct_2 + ; .Correct_1: LD A,E - AND #F0 + ;AND #F0 DUP 4 ; вправо на 4 битa - RR D + ;RR D + SRL D RRA EDUP LD E,A @@ -1845,8 +918,11 @@ READ_FROM_FAT: CALL CHECK_CLUSTER_IS_SMALLER POP HL LD A,0 RET -; +;----------------------------------------------------------------------; + + +;----------------------------------------------------------------------; ; Вход: HL - Номер первой ячейки кластера в блоке фата ; Портить только HL и A SET_FAT32_CACHE_BLOCK_CHANGED_REGION: @@ -1871,8 +947,11 @@ SET_FAT32_CACHE_BLOCK_CHANGED_REGION: OR H LD (CORE_BUFFERS.FS_Buffer.CacheUpdated),A RET +;----------------------------------------------------------------------; -; + + +;----------------------------------------------------------------------; ; !TODO optimize ; при записи в кэш значения отмечать через OR в ячейке FS_Buffer.SectorOfCacheBlock ; бит соответствующий куску в странице кэша, который был изменён и потом скидывать на диск @@ -2005,10 +1084,11 @@ WRITE_TO_FAT: LD DE,(CORE_BUFFERS.FS_Buffer.END_CHAIN_CLUSTER_L) ; OR B LD (HL),A JR .exit -;;;;;;;;; +;----------------------------------------------------------------------; +;----------------------------------------------------------------------; ;FAT_BLOCK * Sectors_in_Block = SECTOR_OF_FAT ; in: HL - Cache block ; out: C:HL - logical number @@ -2044,9 +1124,11 @@ GET_SECTOR_OF_FAT: ; RET NC ; INC C ; RET -;;;;;;;;; +;----------------------------------------------------------------------; + +;----------------------------------------------------------------------; ;RE_FAT: ;RX01 ; Прочитать в кеш ХХ секторов FAT-а @@ -2084,9 +1166,11 @@ READ_FAT_TABLE: PUSH HL RST ToDSS.DRV POP HL RET +;----------------------------------------------------------------------; +;----------------------------------------------------------------------; ; Подключить банку кеша FAT и записать его на диск WRITE_FAT_TABLE: SET_PAGE_X FATPAGE @@ -2293,9 +1377,11 @@ WRITE_FAT_TABLE: POP DE POP AF RET +;----------------------------------------------------------------------; -;----------------------------------------------------------------------- + +;----------------------------------------------------------------------; ;вход: HL':HL - номер кластера ;выход: HL - адрес нужной ячейки в странице FATPAGE GET_FAT32_CELL: ; двигаем влево HL':H @@ -2333,7 +1419,11 @@ GET_FAT32_CELL: ; LD DE,FATPAGE.cache ; начало кеша FAT-а ADD HL,DE ; на ячейку FAT RET -;----------------------------------------------------------------------- +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; ;вход: HL - номер кластера ;выход: HL - адрес нужной ячейки в странице FATPAGE GET_FAT16_CELL: LD A,H @@ -2361,7 +1451,11 @@ GET_FAT16_CELL: LD A,H LD DE,FATPAGE.cache ; начало кеша FAT-а ADD HL,DE ; на ячейку FAT RET -;----------------------------------------------------------------------- +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; ;вход: HL - номер кластера ;выход: HL - адрес нужной ячейки в странице FATPAGE ; CF - чётный/нечётный адрес кластера @@ -2406,9 +1500,11 @@ GET_FAT12_CELL: LD D,H ADD HL,DE POP AF RET -;----------------------------------------------------------------------- +;----------------------------------------------------------------------; + +;----------------------------------------------------------------------; ;CLUSTER_TO_SECTOR: ; in: HL':HL - CLUSTER ; out: HL:IX - SECTOR @@ -2455,8 +1551,11 @@ CLUSTER_TO_SECTOR: POP BC RET -//////////////////////////////////////////////////////////////////////// +;----------------------------------------------------------------------; + + +;----------------------------------------------------------------------; ; READ SECTORS OF FILE ; вход: HL:DE - FP (in sectors) ; IY - FM @@ -2621,10 +1720,11 @@ BLOCK_READ: LD (READ.PointerOnBuffer),IX ; .ECL1: AND A RET -;----------------------------------------------------------------------- +;----------------------------------------------------------------------; -;----------------------------------------------------------------------- + +;----------------------------------------------------------------------; ; WRITE SECTORS OF FILE ; вход: HL:DE - FP (in sectors) ; IX - data in RAM @@ -2832,10 +1932,12 @@ BLOCK_WRITE: LD (READ.PointerOnBuffer),IX LD A,DSS_Error.sys.DISK_FULL ;SCF RET +;----------------------------------------------------------------------; -; -;[x] fat32 -;[x] GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE + + +;----------------------------------------------------------------------; +; GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE ; Вход: DE - смещение в файле в кластерах (старшее слово) ; BC - смещение в файле в кластерах (младшее слово) ; HL - первый кластер файла (младшее слово) @@ -2903,9 +2005,12 @@ GetSavedCluster: INC B INC D RET +;----------------------------------------------------------------------; -;[x] fat32 -;[x] GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE + + +;----------------------------------------------------------------------; +; GET/SAVE CLUSTER NUMBER BEFORE/AFTER READ/WRITE SaveGotCluster: LD A,C OR B OR E @@ -2927,7 +2032,949 @@ SaveGotCluster: LD A,C LD A,1 LD (IY+_sFM.OptimizedClusters),A RET -//////////////////////////////////////////////////////////////////////// +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +;Расчёт смещения в секторах ;!HARDCODE sector size +GET_OFFSET_IN_SECTORS: + LD H,0 ;!HARDCODE max file size = 8 gb + LD E,(IY+_sFM.F_POSITION+1) + LD D,(IY+_sFM.F_POSITION+2) + LD L,(IY+_sFM.F_POSITION+3) + LD A,E + AND #01 + LD B,A + LD C,(IY+_sFM.F_POSITION) + RR L + RR D + RR E + ;HL:DE FP (in sectors) + ;BC FP residue (in bytes) + OR C + RET +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; 26/06/2024 {64 kb cluster} read only 64kb cluster ; !TODO cluster 64kb +CHECK_64kb_CLUSTER: + LD HL,(CORE_BUFFERS.FS_Buffer.BytesPerCluster) + ; CF=0 + ADC HL,HL + LD A,DSS_Error.sys.WRITE_PROTECT + RET NZ + CCF + RET +;----------------------------------------------------------------------; + + + + + +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; +; Директории/Файлы +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; + +;----------------------------------------------------------------------; +; [ ] удаление записи LFN +; +; вход: IX = указатель на текущую запись в странице с каталогом FAT для которой +; надо удалить записи LFS +; [ ] big dir +DELETE_LFN_RECORDS: + PUSH IX + LD A,XH + AND #C0 + DEC A + ;SUB 1 + LD C,A + ; В регистре C маска для определения выхода за пределы страницы + ; +.find_LFN: LD DE, -(FAT_DIRECTORY_RECORD) + LD A,FAT_ATTR.LFS_Entry + ; +.loop: ADD IX,DE + LD A,XH + CP C + JR Z,.beyond_boundaries ; [ ] big dir тут надо подгружать предыдущий DirBlock + ; + LD A,FAT_ATTR.LFS_Entry + CP (IX+FAT_DIRECTORY_RECORD.ATTRIBUT) + JR NZ,.exit + LD (IX+FAT_DIRECTORY_RECORD.NAME),#E5 + JR .loop + ; +.exit: AND A +.beyond_boundaries: ; !TODO подгрузка другой части каталога. пока заглушка + POP IX + RET +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; Поиск записи каталога в списке каталога +; вход: 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 + ;!TEST 9/11/23 record index + EXX + LD DE,0 + EXX + ; +.loop_big: LD IX,DIRPAGE.buffer +.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,CORE_BUFFERS.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 ; record index + ; EXX + ;PUSH IX + ; + LD HL,CORE_BUFFERS.HANDBUF + EX DE,HL + LD BC,CORE_BUFFERS.HANDBUF.SIZE + LDIR + ; record index + ;POP DE + POP AF + ;EX AF,AF' + OUT (SLOT3),A + ;EX AF,AF' + AND A + EXX ; record index + RET + ; +.next_record: ;!TEST 9/11/23 record index + EXX + INC DE + EXX + ; +.inc_rec_num: LD DE,FAT_DIRECTORY_RECORD + ADD IX,DE + JR NC,.loop + ; +.error_too_many_files: + ; [ ] big dir + LD A,(F_FIRST.FNDMODE) ;!FIXIT big dir - неправильно использовать это, надо новую переменную + RLA + JR NC,.ErrorTooManyFiles + ; +; CF=1 +; !FIXIT root dir in LOADDIR +; !FIXIT если в кэш были изменения? +.readDirNext: PUSH BC + EXX + PUSH DE ; record index + EX DE,HL + CALL LOADDIR.next + POP DE + EXX + POP BC + JR NC,.loop_big ; !FIXIT там нет CF на выходе + ; +.error_file_not_found: + POP AF + OUT (SLOT3),A + LD A,DSS_Error.sys.FILE_NOT_FOUND + SCF + RET + ; +.ErrorTooManyFiles: + POP AF + OUT (SLOT3),A + LD A,DSS_Error.sys.TOO_MANY_FILES_IN_DIR + SCF + RET + ; + +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; FIND "MASKAREA" IN DIRECTORY +; выход: 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,CORE_BUFFERS.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,.ITs_DIR + ; + LD HL,CORE_BUFFERS.WorkDirectory + LD D,H + LD E,L + INC HL + LD BC,CORE_BUFFERS.WorkDirectory.DEPTH + XOR A + CPIR + JP PO,.error ;[x] 20/11/23 проверка на выход за границы + ; + DEC HL ;R009 + DEC HL + LD BC,CORE_BUFFERS.WorkDirectory.DEPTH + LD A,'\' + CPDR + INC HL + EX DE,HL + ; CF = 0 + SBC HL,DE + EX DE,HL + JR NZ,.MM3 + ; + INC HL +.MM3: LD (HL),0 + JP .ITs_DIR + ; +.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 + ; +.ITs_DIR: ; fat32 + LD E,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H) + LD D,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H+1) + LD YH,D + LD YL,E + LD E,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L) + LD D,(IX + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L+1) + POP AF + OUT (SLOT3),A + AND A + RET + ; +.CHECK_SLASH: XOR A + CPIR + ;[x] 20/11/23 проверка на выход за границы + SCF + RET PO + ; + DEC HL + DEC HL + LD A,'\' ; #5C + CP (HL) + INC HL + RET Z + ; + LD (HL),A + INC HL + XOR A ; сброс CF заодно + LD (HL),A + RET +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; Вход: IY - указатель на начало файлового манипулятора +CHECK_ROOT_CLUSTER: + LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE) + CP FAT_TYPE.x32 + JR NZ,CHECK_FIRST_CLUSTER + ; + LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L) + LD BC,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L) + SBC HL,BC + RET NZ + ; + LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H) + LD BC,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H) + SBC HL,BC + RET +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; вход: IY - указатель на начало файлового манипулятора +; выход: HL':HL - first cluster +; ZF = 0 если первого кластера нет +CHECK_FIRST_CLUSTER: + EXX + LD L,(IY+_sFM.FS_REC.FIRST_CLUSTER_H) ; START CLUSTER High + LD H,(IY+_sFM.FS_REC.FIRST_CLUSTER_H+1) + LD A,L + OR H + EXX + LD L,(IY+_sFM.FS_REC.FIRST_CLUSTER_L) ; START CLUSTER + LD H,(IY+_sFM.FS_REC.FIRST_CLUSTER_L+1) + OR L + OR H + RET +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; вход: HL - имя директории +OPENDIR: ; init + ;EX DE,HL + ;XOR A + ;LD H,A + ;LD L,A + ;LD (CORE_BUFFERS.FS_Buffer.DirBlockDrive),A + ;LD (CORE_BUFFERS.FS_Buffer.DirBlockStartCluster_L),HL + ;LD (CORE_BUFFERS.FS_Buffer.DirBlockStartCluster_H),HL + ;IF DIR_BLOCK_CACHE_OPTIMIZE + ; LD (CORE_BUFFERS.FS_Buffer.DIR_BLOCK_CHANGES),HL + ; LD (CORE_BUFFERS.FS_Buffer.DIR_BLOCK_CHANGES + 2),HL + ;ENDIF + ;EX DE,HL + ; + LD IY,CORE_BUFFERS.FM_BUF + LD A,(HL) + OR A + JR NZ,.SUBDIR + ; REROOT + EX DE,HL + LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L) + LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL + LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H) + LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),HL + EX DE,HL +.reroot: CALL LOADDIR ; [ ] big dir + ; CF=0 + LD HL,CORE_BUFFERS.WorkDirectory + LD (HL),'\' + INC HL + LD (HL),#00 + ;AND A + RET + ; +.SUBDIR: CP "." + JR NZ,.SUBDIR2 + ; fat32 + ; !TEST 04/01/2026 + ;EX DE,HL + CALL CHECK_ROOT_CLUSTER + ;CALL CHECK_FIRST_CLUSTER + EX DE,HL + ; + JR NZ,.no_root ;R005 + ; "cd ." or "cd .." + ;R005 + INC HL + LD A,(HL) + OR A + DEC HL + JR Z,.reroot + ; +.no_root: EXX + LD HL,CORE_BUFFERS.MASKARE + LD DE,CORE_BUFFERS.MASKARE+1 + LD BC,10 ;!HARDCODE + LD (HL),' ' + LDIR + EXX + LD DE,CORE_BUFFERS.MASKARE +.loop: LDI + LD A,(HL) + OR A + JR NZ,.loop + JR .SUBDIR3 + ; +.SUBDIR2: ;EX DE,HL + CALL MASK.name + RET C + ; fat32 +.SUBDIR3: CALL FINDDIR + RET C + ; + EX DE,HL + LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL ; fat32 + LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),IY ; fat32 + ; [ ] big dir + ; ... + ; + ;LD HL,#4000 ;!HARDCODE + ;LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),HL +;-------------; EX DE,HL +; JP LOADDIR +;----------------------------------------------------------------------; +; Прочитать список каталога +; вход (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L), (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H) +LOADDIR: ;!TODO optimize + LD HL,0 ; ID записи, который должен попасть в КЭШ +.Custom: AND A ; в LOAD_SAVE_DIR_PREPARE посчитается размер каталога директории +.next: CALL LOAD_SAVE_DIR_PREPARE + PUSH AF + EX AF,AF' + ;JR NZ,.read_dir ; root dir or not + ; root dir + ;LD A,(CORE_BUFFERS.FS_Buffer.FAT_TYPE) + ;CP FAT_TYPE.x32 + JR Z,.LoadRootDir + ;CALL LOAD_SAVE_DIR_PREPARE.CalcDirSize + ; 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,DIRPAGE.size ; размер директории ;!HARDCODE + ; LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),HL + ; +.read_dir: LD HL,DIRPAGE.buffer ; куда + LD DE,DIRPAGE.size ; сколько + XOR A ; дескриптор + CALL READ ; чтение из файла + EX AF,AF' + LD (SAVEDIR.DirBlkSize),DE ; число прочит. байтов + POP AF + OUT (SLOT3),A + EX AF,AF' + RET C + ; если DE = 0 + ; (A == FF) & (DE == 0) - в прошлый раз прочитали до конца + ; + LD A,D + OR E + RET NZ + ; читаем с начала + CALL LOADDIR + SCF + 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-каталога ; [ ] sector size 512 + CP B + JR NC,.RTD1 + ; + LD B,A ; число секторов +.RTD1: LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) ; номер диска + LD DE,DIRPAGE.buffer ; буфер + LD C,Dss.DRV.Read ; чтение секторов + RST ToDSS.DRV + ; !FIXIT нет проверки на ошибку + ; 21/04/2025 fix мусор в странице каталога, если каталог меньше страницы + BIT 7,D + JR Z,.exit + XOR A + LD (DE),A + ; +.exit: POP AF + OUT (SLOT3),A + RET +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; [ ] доделать передачу ID записи директории и загрузки по ней нужного куска в кэш +;!TODO FAT procedures +;----------------------------------------------------------------------; +; Вход: HL - ID записи, который должен попасть в КЭШ +; CF - не считать размер каталога директории (при первом открытии) +; Выход: A - Страница, которая была в SLOT3 до вызова +; ZF' - RootDir FAT12-16 +LOAD_SAVE_DIR_PREPARE: + PUSH AF + ; [ ] Вход: HL - ID записи, который должен попасть в КЭШ + ; [ ] Выход: HLIX - смещение в файле каталога на нужный блок по #4000 байтов + ; HLIX = (HL*32) & #1FC000 смещение на нужный блок по #4000 байтов + XOR A + LD XL,A + LD E,A + LD A,H + LD H,E + AND #FE + RRA + RR E + LD (CORE_BUFFERS.FS_Buffer.DirBlock),A + RRA + RR E + RRA + RR E + LD XH,E + LD L,A + ; ; + ; + XOR A ; FILE MANIPULATOR = 0 + LD B,A ; от начала файла + CALL MOVE_FP + + SET_PAGE_X DIRPAGE + POP DE + AND A + PUSH AF + ; + LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) + LD (CORE_BUFFERS.FM_BUF.DRIVE),A + ;;;;;;;; + XOR A + LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L) + EXX + LD HL,(CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H) + OR H + OR L + EXX + OR H + OR L + ;;;;;;;; + JR Z,.exit + ; + PUSH AF + SRL E + CALL NC,.CalcDirSize + POP AF +.exit: EX AF,AF' + POP AF + RET + ; +.CalcDirSize: ; check dir cache + ;LD A,(CORE_BUFFERS.FS_Buffer.DirBlockDrive) + ;LD E,A + ;LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) + ;LD (CORE_BUFFERS.FM_BUF.DRIVE),A + ;RET Z + ;; + ;CP E + ;JR NZ,.goCalc + ;; + ;EX DE,HL + ;LD HL,(CORE_BUFFERS.FS_Buffer.DirBlockStartCluster_L) + ;SBC HL,DE + ;EX DE,HL + ;JR NZ,.goCalc + ;; + ;EXX + ; EX DE,HL + ; LD HL,(CORE_BUFFERS.FS_Buffer.DirBlockStartCluster_H) + ; SBC HL,DE + ; EX DE,HL + ;EXX + ;RET Z + ; + ; calc dir size in clusters +.goCalc: LD DE,0 +.loop: INC DE ; Надеемся тут на то, что спецификация выполняется и переполнения не будет + PUSH DE + CALL READ_FROM_FAT + EX DE,HL + POP DE + EXX + EX DE,HL + EXX + JR NC,.loop + ; + ; DE - размер директории в кластерах + ;!FIXIT можно оптимизнуть кол-во сдвигов + ;0001 0000 0000 0000 max кол-во кластеров + ; пример + ;0000 0000 0000 0111 Clusters + ; 0100 0000 SectorsPerCluster + ;0000 0010 0000 0000 BytesPerSector + ; D' E' D E + ;0000 0000 0000 0011 1000 0000 0000 0000 + ; + LD A,(CORE_BUFFERS.FS_Buffer.SectorsPerCluster) + LD BC,(CORE_BUFFERS.FS_Buffer.BytesPerSector) + ; DE':DE - кол-во кластеров + ; A - размер кластера в секторах + ; BC - размер сектора в байтах + ; --> DE*BC*A = DE':DE для ответа хватит, походу, 4х регистров + EXX + LD DE,0 + EXX + SRL B + RR C + RRCA + JR C,.loop2 + ; +.loop1: ; + SLA E + RL D + EXX + RL E + RL D + ;RL C + EXX + ; + RRCA + JR NC,.loop1 + ; +.loop2: ; + SLA E + RL D + EXX + RL E + RL D + ;RL C + EXX + ; + SRL B + RR C + JR NC,.loop2 + ; <-- DE*BC*A = DE':DE + LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE),DE + EXX + LD (CORE_BUFFERS.FM_BUF.FS_REC.F_SIZE + 2),DE + RET + +/* 4 3 2 1 + #FFFF<<5 = #1FFFE0 = 0000 0000 0001 1111 1111 1111 1110 0000 + + #FFFF номер записи + #1FFFE0 смещение на запись в файле директории + #1FFFE0 & #1FC000 смещение на нужный блок по #4000 байтов + #1FFFE0 & #3FFF Адрес нужной позиции в кэш + (#1FFFE0 & #1FC000)<<2 двигаем байт 2 и 3 чтоб получить номер блока +*/ +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; + ASSERT 0, "TODO! GET_ADDR_IN_DIR_CACHE" +;!TODO +; .DIRSIZE помешает если в кэш будет другая страница? +; LOAD_SAVE_DIR_PREPARE возможно не нужен, нужно только установить правильное смещение в FM +; Может вообще переделать её под работу с КЭШ + +; Сбросить кеш каталога на диск. +; вход: iy=структура дескриптора +; [ ] big dir получать откуда и сколько байтов изменилось в кэш, чтоб не писать на диск лишнего +SAVEDIR: ;!TODO optimize + CALL LOAD_SAVE_DIR_PREPARE + PUSH AF + EX AF,AF' + ;JR NZ,.save_dir + JR Z,.SaveRootDir + ; + ;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 если она нужна, то проверить на баги (например, размер дирректории меньше при открытии и больше после правок) + ; когда будет чтение кусками каталога в кэш, тут ещё счётчик прикрутить +.DirBlkSize+1: LD DE,0 + XOR A + CALL WRITE + POP AF + OUT (SLOT3),A + RET + ; + ; FAT12-16 +.SaveRootDir: LD HL,(CORE_BUFFERS.FS_Buffer.RootDirFirstSector_H) ;!TODO возможно, хватит LD HL,0 + LD IX,(CORE_BUFFERS.FS_Buffer.RootDirFirstSector_L) + LD A,(CORE_BUFFERS.FS_Buffer.DirSizeInSectors) + LD B,32 ;!HARDCODE sector size 512, Root Dir max size in sectors + SUB B + JR NC,.RTD1S + ADD A,B + LD B,A +.RTD1S: LD A,(CORE_BUFFERS.FS_Buffer.DRIVE) + LD DE,DIRPAGE.buffer + LD C,Dss.DRV.Write + RST ToDSS.DRV + POP AF + OUT (SLOT3),A + RET +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; [ ] big dir +; скопировать запись в список диска (каталога) de ix iy +; и сбросить кеш каталога на диск +; вход: (HANDBUF) - запись каталога +; выход: DE - record index +WRITE_DIR_HANDLE: + SET_PAGE_X DIRPAGE + EX AF,AF' + LD HL,DIRPAGE.buffer + ;!TEST 9/11/23 record index + EXX + LD DE,0 + EXX + ; + LD BC,FAT_DIRECTORY_RECORD +.loop: ;LD A,(IX+00) + LD A,(HL) + OR A + JR Z,.WRT_HN2 + CP #E5 + JR Z,.WRT_HN2 + ;ADD IX,BC + ADD HL,BC + JR NC,.loop ;!FIXIT количество записей каталога = страница + ; + EX AF,AF' + OUT (SLOT3),A + LD A,DSS_Error.sys.ROOT_OVERFLOW + SCF + RET + ; +.WRT_HN2: ;LD D,XH + ;LD E,XL + EX DE,HL + LD HL,CORE_BUFFERS.HANDBUF + LD BC,CORE_BUFFERS.HANDBUF.SIZE + LDIR + EX AF,AF' + OUT (SLOT3),A + ; проверяем, увеличился ли размер данных директории + LD HL,DIRPAGE.buffer + LD BC,(SAVEDIR.DirBlkSize) + DEC BC + ADD HL,BC + AND A + SBC HL,DE + JR NC,.SAVEDIR + ; + ; размер данных директории увеличился + LD HL,(SAVEDIR.DirBlkSize) + LD BC,(CORE_BUFFERS.FS_Buffer.BytesPerCluster) + ADD HL,BC + LD (SAVEDIR.DirBlkSize),HL + AND A +.SAVEDIR: EXX + PUSH DE + EXX + ; [ ] big dir передавать откуда и сколько байтов изменилось в кэш, чтоб не писать на диск лишнего + CALL SAVEDIR + POP DE + RET +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; + IFUSED GET_ADDR_IN_DIR_CACHE +; Вход: IX - указатель на номер записи в каталоге +; Выход: HL - смещение в SLOT3 на запись в каталоге +GET_ADDR_IN_DIR_CACHE: + LD A,3 + PUSH IX + POP HL + RR H + ; + RR L + RRA + RR L + RRA + RR L + RRA + LD H,L + LD L,A + LD A,H + OR #C0 + LD H,A + RET + ENDIF +;----------------------------------------------------------------------; + + + +;----------------------------------------------------------------------; +; Удаляет запись в каталоге и освобождает занятую цепочку кластеров +; Вход: IX - указатель на удаляемую запись в DIRPAGE +; в КЭШ директории должна быть загружена часть с нужной записью +;!TODO record index. возможно, что может сломаться, если больше страницы +DELETE_REC_FAT: SET_PAGE_X DIRPAGE + EX AF,AF' + ;CALL DELETE_LFN_RECORDS ; [ ] big dir ; [x] удаление записи LFN + LD (IX + FAT_DIRECTORY_RECORD.NAME),#E5 ; признак удаления файла + ; fat32 + LD L,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H) ; № первого кластера + LD H,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H+1) + LD A,L + OR H + EXX + LD L,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L) ; № первого кластера + LD H,(IX+FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L+1) + OR L + OR H + ; + EX AF,AF' + OUT (SLOT3),A + EX AF,AF' + ; [ ] big dir передавать откуда и сколько байтов изменилось в кэш, чтоб не писать на диск лишнего + JP Z,SAVEDIR ; сбросить кеш каталога на диск + ; если размер файла не ноль +.loop: ;EX DE,HL ; hl=номер кластера + ;EXX + ; EX DE,HL + ;EXX + CALL READ_FROM_FAT ; прочитать из кеша FAT-а номер след. кластера + EXX + PUSH DE ; номер след. кластера + PUSH AF + LD DE,#0000 ; номер кластера + EXX + PUSH DE + ; + CALL SET_NEW_FREE_CLUSTER + ; + LD DE,#0000 ; номер кластера + CALL WRITE_TO_FAT.Custom ; записать в кеш FAT-а номер кластера + POP HL + EXX + POP AF + POP HL + ;EX DE,HL + EXX + ;EX DE,HL + JP NC,.loop + CALL WRITE_FAT_TABLE + ; [ ] big dir передавать откуда и сколько байтов изменилось в кэш, чтоб не писать на диск лишнего + JP SAVEDIR ; сбросить кеш каталога на диск +;----------------------------------------------------------------------; + + ;----------------------------------------------------------------------; ; Вход: HL - адрес куда писать @@ -2952,42 +2999,6 @@ WRITE_DATE_TIME_TO_DIRECTORY_RECORD: ;----------------------------------------------------------------------; -;----------------------------------------------------------------------; -;Расчёт смещения в секторах ;!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 -;----------------------------------------------------------------------; - - -;----------------------------------------------------------------------; -; [x] 26/06/2024 {64 kb cluster} read only 64kb cluster ; !TODO cluster 64kb -CHECK_64kb_CLUSTER: - LD HL,(CORE_BUFFERS.FS_Buffer.BytesPerCluster) - ; CF=0 - ADC HL,HL - LD A,DSS_Error.sys.WRITE_PROTECT - RET NZ - CCF - RET - ; -;----------------------------------------------------------------------; - - ;----------------------------------------------------------------------; ; Преобразовать имя 8.3 -> 11 формат ; вход: hl = 8.3 имя @@ -3092,6 +3103,87 @@ MASK: LD HL,CORE_BUFFERS.TMPNAME ;----------------------------------------------------------------------; + +;----------------------------------------------------------------------; +; SET_FAT_ROOT_DIR_CLUSTER: +; EX DE,HL +; LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_L) +; LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_L),HL +; LD HL,(CORE_BUFFERS.FS_Buffer.RootDirStartCluster_H) +; LD (CORE_BUFFERS.FM_BUF.FS_REC.FIRST_CLUSTER_H),HL +; EX DE,HL +; RET +;----------------------------------------------------------------------; + + + + + +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; +;??? +;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; + +;----------------------------------------------------------------------; +;!TODO ? +;GHANDLE: +; PUSH DE +; PUSH HL +; PUSH IX +; CALL TESTDSK +; JP C,G_HAND1 +; CALL LOADDIR +; POP DE +; LD HL,DIR +; LD BC,FAT_DIRECTORY_RECORD +;G_HAND2: +; LD A,D +; OR E +; JP Z,G_HAND3 +; ADD HL,BC +; DEC DE +; JP G_HAND2 +;G_HAND3: +; EXX +; POP DE +; EXX +;G_HAND4: +; EX DE,HL +; LD A,DIRPAGE +; CALL BANK +; EX DE,HL +; LD DE,HANDTA +; +; DUP 32 +; LDI +; EDUP +; +; EXX +; OUT (SLOT3),A +; LD HL,HANDTA +; +; DUP 32 +; LDI +; EDUP +; +; EXX +; POP BC +; DEC BC +; LD A,B +; OR C +; RET Z +; PUSH BC +; JP G_HAND4 +;G_HAND1 POP IX +; POP HL +; POP DE +; RET +;HANDTA BLOCK 32,0 +;----------------------------------------------------------------------; + + + + MODULE_SIZE EQU $ - MODULE_START ; ENDMODULE -;███████████████████████████████████████████████████████████████████████████████████████████████████████; \ No newline at end of file +;███████████████████████████████████████████████████████████████████████; +;███████████████████████████████████████████████████████████████████████; \ No newline at end of file diff --git a/DSS/Structures.inc b/DSS/Structures.inc index 8cafc5a..8f15682 100644 --- a/DSS/Structures.inc +++ b/DSS/Structures.inc @@ -111,8 +111,14 @@ .UPD_FSINFO: BYTE 0 .FREE_CLUSTERS_COUNT_L: WORD #FFFF .FREE_CLUSTERS_COUNT_H: WORD #FFFF -.DIR_BLOCK BYTE #00 ; [ ] big dir. какой блок директории загружен в кэш директорий DIRPAGE -.DIR_BLOCK_CHANGES DWORD #00000000 ; [ ] big dir. какие из кусков в блоке кэш DIRPAGE изменились до сохранения +; For directory cache +.DirBlock BYTE #00 ; [ ] big dir. какой блок директории загружен в кэш директорий DIRPAGE +;.DirBlockDrive BYTE #00 +;.DirBlockStartCluster_L WORD #0000 +;.DirBlockStartCluster_H WORD #0000 +; IF DIR_BLOCK_CACHE_OPTIMIZE +;.DIR_BLOCK_CHANGES DWORD #00000000 ; [ ] big dir. какие из кусков в блоке кэш DIRPAGE изменились до сохранения +; ENDIF ;.FilesPerSector: BYTE #00 ; число файловых записей в секторе ;.ClustersPerBank: BYTE #00 ; A - Clusters per bank (16k) (число кластеров на блок ОЗУ) ;.READ_PG: BYTE #00 ;!TODO не используются некоторые значения, но задумка неплохая))) diff --git a/DSS/ToDo.txt b/DSS/ToDo.txt index 0145585..ef779ef 100644 --- a/DSS/ToDo.txt +++ b/DSS/ToDo.txt @@ -1,10 +1,11 @@ По полным директориям. +;[x] LOADDIR после READ выходить с CF, если прочитано 0 ;[ ] Переделать WRITE_DIR_HANDLE для работы с любой записью в каталоге (сейчас ищет первую пустую, чтоб записать в неё) ;[ ] Все изменения в записях каталога делать в буфере CORE_BUFFERS.HANDBUF и сохранять через WRITE_DIR_HANDLE -;[ ] Переменная DIR_BLOCK показывающая какой блок директории в кэш. +;[x] Переменная DirBlock показывающая какой блок директории в кэш. ;[ ] Переменная DIR_BLOCK_CHANGED показывающая какой из кусков в блоке кэш изменился до сохранения. Как в FAT. ;[ ] Процедуры меняющие данные в кэш директории должны менять DIR_BLOCK_CHANGED. -;[ ] Передавать в LOADDIR нужный блок для загрузки в кэш (или номер нужной записи каталога). +;[x] Передавать в LOADDIR нужный блок для загрузки в кэш (или номер нужной записи каталога). ;[ ] Передавать в SAVEDIR нужный блок для записи из кэш (или номер нужной записи каталога). ;[ ] LOAD_SAVE_DIR_PREPARE походу, переделать к херам вместе с LOADDIR и SAVEDIR diff --git a/DSS/defines.inc b/DSS/defines.inc index 3514add..377602f 100644 --- a/DSS/defines.inc +++ b/DSS/defines.inc @@ -7,6 +7,7 @@ DEFINE TEST_FEATURE 0 DEFINE MINIMUM_EXE_VERSION 1 DEFINE COMPILE_UNUSED_CODE 0 + DEFINE DIR_BLOCK_CACHE_OPTIMIZE 0 ; !TODO ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░; diff --git a/TMP_CODE.ASM b/TMP_CODE.ASM index 9c287be..91d1c93 100644 --- a/TMP_CODE.ASM +++ b/TMP_CODE.ASM @@ -436,7 +436,7 @@ LOAD_SAVE_DIR_PREPARE: AND #FE RRA RR E - LD (CORE_BUFFERS.FS_Buffer.DIR_BLOCK),A + LD (CORE_BUFFERS.FS_Buffer.DirBlock),A RRA RR E RRA