;[BEGIN] ;//MODULE: DOS5 ;//CREATE: 19-05-1998 AUTHOR: Denis Parinov ;//UPDATE: 24-10-1999 DNS Restore module ;------------------------------------------------------------- ;Rev Date Name Description ;------------------------------------------------------------- ;R11 17-04-2023 BAO Временный костыль для недопускания переполнения буфера пути каталога ;R10 15-04-2023 BAO ;????? FIXED BUG WITH CHANGE DISK WITHOUT CHANGE PATH ;!FIXIT пока в виде заплатки полунеработающей ;R09 13-04-2023 BAO FIX BUG WITH PARSING DIRECTORY BUFFER ;R08 15-04-2003 DNS SAVE AND RESTORE CUR-PATH MACROS ;R07 06-02-2003 DNS FIX BUG IN MASK ROUTINE, IT ALLOW NAMES WHICH BEGAN ; FROM "." ".NAM" ;R06 29-01-2003 DNS FIX BUG WITH SET FILE DATE AND TIME ;R05 26-11-2002 DNS FIX ERROR IN CHDIR, DON'T ALLOWED "." FOR ROOT ;R04 19-11-2002 DNS DON'T ALLOW DIR & LABEL ATTR FOR FILES ;R03 19-11-2002 DNS ADD RESET OF VOLUME LABEL ATTRIBUT ;R02 19-11-2002 DNS FIX GET/SET ATTRIBUTES ;R01 16-12-1999 DNS Y2K fix ;------------------------------------------------------------- ; INPUT: HL - "C:\DIR1\DIR2\filename.ext",#00 ; A - ATTRIB ; B - MODE ; B = 0 GET ATTRIB ; B = 1 SET ATTRIB ; OUTPUT: A - ATTRIB ATTRIB: _mSavePath INC B DEC B JP Z,RATTRIB DEC B JP Z,WATTRIB LD A,DSS_Error.sys.INVALID_FUNCTION SCF RET RATTRIB XOR A CALL OPENATR ;R02 RET C LD B,(IY+_sFM.ATTRIBUT) PUSH BC CALL CLOSE POP BC RET C LD A,B AND A RET WATTRIB PUSH AF XOR A CALL OPENATR ;R02 POP BC RET C SET 7,(IY+_sFM.ACCESS_MODE) RES 3,B ;CLEAR LABEL ATTR ;R03 ;!HARDCODE attribute bit LD (IY+_sFM.ATTRIBUT),B PUSH BC CALL CLOSE POP BC RET C LD A,B AND A RET ; INPUT: HL - "C:\DIR1\DIR2\filename.ext",#00 ; OUTPUT: A - FM CREATE: _mSavePath AND #E7 ;R04 %76A00SHR = !FAT_ATTR LD (ACCESS),A LD (PATH0),HL CALL GETWORD RET C LD HL,TMPNAME LD DE,MASKARE CALL MASK RET C CALL SEARCH JR C,CREAT ;NO FILE, CREAT NEW. CALL DELFILE ;FILE EXIST RECREAT JP CREAT ; INPUT: HL - "C:\DIR1\DIR2\filename.ext",#00 ; OUTPUT: A - FM CREAT_N: _mSavePath AND #E7 ;R04 %76A00SHR = !FAT_ATTR LD (ACCESS),A LD (PATH0),HL CALL GETWORD RET C LD HL,TMPNAME LD DE,MASKARE CALL MASK RET C CALL SEARCH LD A,DSS_Error.sys.FILE_EXISTS CCF RET C CREAT LD HL,MASKARE LD DE,HANDBUF LD BC,11 LDIR EX DE,HL LD A,(ACCESS) LD (HL),A INC HL LD BC,#0A00 FIHND LD (HL),C INC HL DJNZ FIHND PUSH HL CALL SYSTIME CALL MK_TIME POP HL LD (HL),E INC HL LD (HL),D INC HL LD (HL),C INC HL LD (HL),B INC HL LD BC,#0600 FIHND1 LD (HL),C INC HL DJNZ FIHND1 CALL WRT_HND CALL SAVEDIR LD HL,(PATH0) XOR A JP OPEN ;R08 ; INPUT: HL - "filename.ext",#00 without simbols * ? DELETE: LD DE,MASKARE CALL MASK RET C LD HL,MASKARE LD BC,11 LD A,"?" CPIR LD A,DSS_Error.sys.INVALID_NAME SCF RET Z CALL LOADDIR CALL SEARCH RET C ; пометить запись как "удаленная" DELFILE: SET_PAGE_X DIRPAGE LD (IX+_sFM.NAME),#E5 ; признак удаления файла LD E,(IX+_sFM.ST_CLUSTER) ; № первого кластера LD D,(IX+_sFM.ST_CLUSTER+1) OUT (SLOT3),A LD A,E OR D JP Z,SAVEDIR ; сбросить кеш каталога на диск DEL01 EX DE,HL ; hl=номер кластера CALL R_F_FAT ; прочитать из кеша FAT-а номер след. кластера PUSH DE ; номер след. кластера PUSH AF LD DE,#0000 ; номер кластера CALL W_T_FAT ; записать в кеш FAT-а номер кластера POP AF POP DE JP NC,DEL01 CALL WR_FAT JP SAVEDIR ; сбросить кеш каталога на диск ////////////////////////////////////////////////////////////////////// ; Функция #10. Переименование файла. ; Глобальные символы * и ? в именах файлов не допускаются. ; ; вход: HL - указатель на старое имя файла ; DE - указатель на новое имя файла ; выход: A - код ошибки, если CF=1 ; ; INPUT: HL - "old_name.ext",#00 without simbols * ? ; DE - "new_name.ext",#00 without simbols * ? ////////////////////////////////////////////////////////////////////// RENAME: PUSH DE LD DE,MASKARE CALL MASK POP DE RET C LD HL,MASKARE LD BC,11 LD A,"?" CPIR LD A,DSS_Error.sys.INVALID_NAME SCF RET Z PUSH DE CALL LOADDIR ; прочитать список каталога ;LD A,#33 LD A,FAT_ATTR.NoSYSnoVolID CALL ASEARCH ; поиск записи в списке диска POP HL RET C LD DE,MASKARE CALL MASK RET C LD HL,MASKARE LD BC,11 LD A,"?" CPIR LD A,DSS_Error.sys.INVALID_NAME SCF RET Z PUSH IX LD A,FAT_ATTR.NoSYSnoVolID CALL ASEARCH ; поиск записи в списке диска POP IX LD A,DSS_Error.sys.FILE_EXISTS CCF RET C SET_PAGE_X DIRPAGE LD HL,MASKARE LD D,XH LD E,XL LD BC,11 LDIR OUT (SLOT3),A JP SAVEDIR ;R02 OPENATR: LD (ACCESS),A ; раб. ячейка (здесь атрибут записи) CALL GETWORD ; тест на допуст. имя и настр. на диск RET C LD HL,TMPNAME LD DE,MASKARE CALL MASK RET C LD A,FAT_ATTR.NoVolID CALL ASEARCH JR NC,OPENAT ; на поиск своб. дескриптора ; запись не найдена RET ;R02 ////////////////////////////////////////////////////////////////////// ; Функция #11. Открытие файла. ; ; вход: HL - указатель на имя файла ; A - режим доступа: ; A=0 чтение/запись ; A=1 чтение ; A=2 запись ; выход: A - дескриптор файла, если CF=0 ; код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// OPEN_FN: _mSavePath OPEN: ;R08 LD (ACCESS),A CALL GETWORD RET C LD HL,TMPNAME LD DE,MASKARE CALL MASK RET C OPENEXE: CALL SEARCH RET C OPENAT: ;R02 CALL GET_FM RET C LD A,C EX AF,AF' EXX LD (IY+_sFM.HANDLE),E LD (IY+_sFM.HANDLE+1),D EXX LD D,YH LD E,YL LD HL,HANDBUF LD BC,HANDBUF.SIZE LDIR LD A,(ACCESS) LD (IY+_sFM.ACCESS_MODE),A LD A,(TASK) LD (IY+_sFM.TASK_NUM),A XOR A LD (IY+_sFM.F_POSITION),A LD (IY+_sFM.F_POSITION+1),A LD (IY+_sFM.F_POSITION+2),A LD (IY+_sFM.F_POSITION+3),A LD A,(FatBuffer.DRIVE) LD (IY+_sFM.DRIVE),A LD HL,FM_BUF+_sFM.ST_CLUSTER LD E,(HL) INC HL LD D,(HL) LD (IY+_sFM.DIR_CLUSTER),E LD (IY+_sFM.DIR_CLUSTER+1),D EX AF,AF' AND A RET CLOSE_FN: _mSavePath CLOSE: ;R08 LD (ACCESS),A CALL SET_FM RET C LD A,(TASK) CP (IY+_sFM.TASK_NUM) LD A,DSS_Error.sys.ACCESS_DENIED SCF RET NZ BIT 7,(IY+_sFM.ACCESS_MODE) JR Z,NOTMODF LD D,(IY+_sFM.DIR_CLUSTER) LD E,(IY+_sFM.DIR_CLUSTER+1) PUSH DE XOR A CALL SET_FM POP DE LD (IY+_sFM.DIR_CLUSTER),D LD (IY+_sFM.DIR_CLUSTER+1),E CALL LOADDIR LD A,(ACCESS) CALL SET_FM LD HL,DIR LD DE,#0020 LD C,(IY+_sFM.HANDLE) LD B,(IY+_sFM.HANDLE+1) JR CLOSE2 CLOSE1: ADD HL,DE DEC BC CLOSE2: LD A,B OR C JR NZ,CLOSE1 LD D,YH LD E,YL EX DE,HL PUSH HL SET_PAGE_X DIRPAGE POP HL LD BC,#0020 LDIR OUT (SLOT3),A CALL SAVEDIR NOTMODF: LD A,(ACCESS) CALL RES_FM RET PATH0: DW #0000 ACCESS: DB #00 HANDBUF: BLOCK HANDBUF.SIZE,0 WRT_HND: SET_PAGE_X DIRPAGE PUSH AF LD IX,DIR EXX LD DE,0 EXX WRT_HN1: LD A,(IX+00) OR A JR Z,WRT_HN2 CP #E5 JR Z,WRT_HN2 LD BC,#0020 ADD IX,BC JR NC,WRT_HN1 POP AF OUT (SLOT3),A LD A,DSS_Error.sys.ROOT_OVERFLOW SCF RET WRT_HN2: LD D,XH LD E,XL LD HL,HANDBUF LD BC,HANDBUF.SIZE LDIR POP AF OUT (SLOT3),A LD HL,DIR LD BC,(DIRSIZE) DEC BC ADD HL,BC AND A SBC HL,DE RET NC LD HL,(DIRSIZE) LD BC,(FatBuffer.B_P_C) ADD HL,BC LD (DIRSIZE),HL AND A RET DOSNAME: INC B DEC B JP Z,GETNAME DEC B JP Z,MASK LD A,DSS_Error.sys.INVALID_FUNCTION SCF RET ; HL - 11 bytes filename "FILENAMEEXT" ; DE - DOS filename "FILENAME.EXT",0 GETNAME: LD BC,#08FF GETN1: LD A,(HL) CP " " JR NZ,GETN3 GETN2: INC HL DJNZ GETN2 JR GETN4 GETN3: LDI DJNZ GETN1 GETN4: LD A,(HL) CP " " LD A,"." JR NZ,GETN5 LD A,#00 GETN5: LD (DE),A INC DE RET Z LD B,#03 GETN6: LD A,(HL) CP " " RET Z LDI XOR A LD (DE),A DJNZ GETN6 RET DTABUF: DW #0000 CURHND: DW #0000 NO_NEXT: DB #00 .YES EQU 0 .NO EQU #FF FNDMODE: DB #00 F_FIRST: LD (ACCESS),A LD (DTABUF),DE LD A,B LD (FNDMODE),A PUSH HL CALL LOADDIR POP HL CALL GETWORD RET C LD HL,TMPNAME LD DE,MASKARE CALL MASK RET C LD A,(ACCESS) CALL ASEARCH RET C LD HL,MASKARE LD DE,(DTABUF) LD BC,11 ;!HARDCODE LDIR LD A,(ACCESS) LD (DE),A FIND_S: INC DE LD BC,#0020 ADD IX,BC LD (CURHND),IX LD HL,HANDBUF+12 LD BC,HANDBUF.SIZE-12 ;????? метку вместо числа? LDIR LD A,(HANDBUF+11) LD (DE),A INC DE LD HL,HANDBUF LD A,(FNDMODE) OR A JR NZ,FIND_M2 LD BC,11 ;!HARDCODE LDIR LD A,NO_NEXT.NO LD (NO_NEXT),A XOR A RET FIND_M2: CALL GETNAME LD A,NO_NEXT.NO LD (NO_NEXT),A XOR A RET F_NEXT: LD A,(NO_NEXT) OR A LD A,DSS_Error.sys.INVALID_ACCESS SCF RET Z LD (DTABUF),DE EX DE,HL LD DE,MASKARE LD BC,11 ;!HARDCODE LDIR XOR A LD (NO_NEXT),A LD A,(HL) PUSH HL CALL NSEARCH POP DE RET C JP FIND_S NSEARCH: EX AF,AF' SET_PAGE_X DIRPAGE PUSH AF EX AF,AF' CPL LD C,A EXX LD DE,0 EXX LD IX,(CURHND) LD A,XH OR XL JR Z,SEARCH3.error JP SEARCH1 ;------------------------------------------------- ; Поиск записи каталога в списке каталога ; ; вход: a=атрибут записи ; выход: de'=индекс записи в списке каталога ; CF - каталог не найден ;------------------------------------------------- DSEARCH: LD A,FAT_ATTR.DIRECTORY CALL ASEARCH RET NC LD A,DSS_Error.sys.PATH_NOT_FOUND RET SEARCH: LD A,FAT_ATTR.NoDIRnoVolID ASEARCH: EX AF,AF' ; 76ADLSHR SET_PAGE_X DIRPAGE PUSH AF EX AF,AF' CPL LD C,A LD IX,DIR EXX LD DE,0 EXX SEARCH1: LD A,(IX+00) OR A JR Z,SEARCH4 CP #E5 ;!HARDCODE #E5 - запись в директории свободна, так как файл/директория были удалены JR Z,SEARCH3 LD A,(IX+11) AND C JR NZ,SEARCH3 LD HL,MASKARE LD D,XH LD E,XL LD B,11 EX DE,HL SEARCH2: LD A,(DE) CP '?' JR Z,SEARCH5 CP (HL) JR NZ,SEARCH3 SEARCH5: INC HL INC DE DJNZ SEARCH2 LD D,XH LD E,XL LD HL,HANDBUF EX DE,HL LD BC,HANDBUF.SIZE LDIR POP AF OUT (SLOT3),A AND A RET SEARCH3: EXX INC DE EXX LD DE,#0020 ;!HARDCODE ADD IX,DE JR NC,SEARCH1 .error: POP AF OUT (SLOT3),A LD A,DSS_Error.sys.TOO_MANY_FILES_IN_DIR SCF RET SEARCH4: POP AF OUT (SLOT3),A LD A,DSS_Error.sys.FILE_NOT_FOUND SCF RET ;------------------------------------------------- ; Тест на допустимое имя и настроиться на диск. ; вход: hl=строка имени ;------------------------------------------------- GETWORD: LD DE,TMPNAME LD BC,#0DFF .loop: LD A,(HL) INC HL CP '\' JR Z,.DIR_NAME CP ':' JR Z,.DRV_NAME LD (DE),A INC DE CP ' '+1 CCF RET NC DJNZ .loop LD A,DSS_Error.sys.INVALID_NAME SCF RET .DIR_NAME: XOR A LD (DE),A PUSH HL LD HL,TMPNAME CALL OPENDIR POP HL JR NC,GETWORD RET .DRV_NAME: LD A,(TMPNAME) CP 'a' JR C,.next CP '{' JR NC,.next SUB #20 .next: SUB 'A' PUSH HL ;!TEST CHNDISK OPENDSK ;CALL OPENDSK CALL CHNDISK ; POP HL JP NC,GETWORD RET ; Буфер имени 8.3 формата TMPNAME: DZ ' ' ; 12 пробелов и 0 ;!TODO сделать для каждого драйва запоминание текущей дирректории, пока тут заглушка ; RestoreDIR: CHNDISK: ;!TEST ;CALL OPENDSK CALL OPENDSK.force ; ;????? R10 RET C ;LD HL,DIRSPEC+1 LD HL,DIRSPEC LD (HL),0 PUSH AF CALL OPENDIR POP BC RET C LD A,B RET /* RET C PUSH AF CALL LOADDIR POP AF */ RET ; ;????? R10 OPENDSK: ;!TEST DRV.Open обход LD C,A LD A,(FatBuffer.DRIVE) CP C JR Z,.exit LD A,C ; .force: PUSH AF LD C,Dss.DRV.Open RST ToDSS.DRV POP BC JP C,.error LD A,B LD (FatBuffer.DRIVE),A CALL RD_BPB RET C .exit: LD A,(LDRIVE) AND A RET .error: CP DSS_Error.sys.INVALID_DRIVE SCF RET Z LD A,DSS_Error.sys.NOT_READY RET ; OPENDIR: XOR A CALL SET_FM LD A,(HL) OR A JP NZ,SUBDIR REROOT1: LD DE,0 LD (IY+_sFM.ST_CLUSTER),E LD (IY+_sFM.ST_CLUSTER+1),D CALL LOADDIR LD HL,DIRSPEC LD (HL),'\' INC HL LD (HL),#00 AND A RET SUBDIR: CP "." JR NZ,SUBDIR2 LD A,(IY+_sFM.ST_CLUSTER) ;R05 ;!FIXIT можно переделать на прямые ссылки без IY OR (IY+_sFM.ST_CLUSTER+1) ;R05 ;!FIXIT можно переделать на прямые ссылки без IY JR NZ,SUDI1 ;R05 INC HL ;R05 LD A,(HL) ;R05 OR A ;R05 DEC HL ;R05 JR Z,REROOT1 ;R05 SUDI1: EXX LD HL,MASKARE LD DE,MASKARE+1 LD BC,10 ;!HARDCODE LD (HL),' ' LDIR EXX LD DE,MASKARE SUBDIR0: LDI LD A,(HL) OR A JR NZ,SUBDIR0 JR SUBDIR3 SUBDIR2: LD DE,MASKARE CALL MASK RET C SUBDIR3: CALL FINDDIR RET C LD (IY+_sFM.ST_CLUSTER),E LD (IY+_sFM.ST_CLUSTER+1),D LD DE,#4000 LD (IY+_sFM.F_SIZE),E LD (IY+_sFM.F_SIZE+1),D CALL LOADDIR AND A RET ; FIND "MASKAREA" IN DIRECTORY FINDDIR: SET_PAGE_X DIRPAGE PUSH AF LD IX,DIR .F_01: LD A,(IX+00) OR A JR Z,.error CP #E5 JR Z,.F_03 LD A,(IX+11) AND #10 JR Z,.F_03 LD HL,MASKARE LD D,XH LD E,XL EX DE,HL LD B,11 .loop: LD A,(DE) CP "?" JR Z,.F_05 CP (HL) JR NZ,.F_03 .F_05: INC HL INC DE DJNZ .loop LD A,(IX+0) CP "." JP NZ,ADDSPEC LD A,(IX+1) CP "." JP NZ,IT_DIR LD HL,DIRSPEC LD D,H LD E,L INC HL LD BC,DIRSPEC.DEPTH XOR A CPIR ;!FIXIT нет проверки на завершение по BC=0 DEC HL ;R09 ;[x] исправлен баг с парсингом буфера каталога DEC HL LD BC,DIRSPEC.DEPTH LD A,'\' CPDR INC HL AND A EX DE,HL SBC HL,DE EX DE,HL ; JR NZ,ROTZ JR NZ,MM3 JP MM2_5 ; INC HL ; ROTZ LD (HL),0 ; JP IT_DIR ; IT_DIR LD E,(IX+_sFM.ST_CLUSTER) ; LD D,(IX+_sFM.ST_CLUSTER+1) ; POP AF ; OUT (SLOT3),A ; AND A ; RET .F_03: LD BC,#0020 ADD IX,BC JR NC,.F_01 .error: POP AF OUT (SLOT3),A LD A,DSS_Error.sys.PATH_NOT_FOUND SCF RET ADDSPEC LD E,XL LD D,XH LD HL,DIRSPEC+1 LD BC,DIRSPEC.DEPTH-1 XOR A CPIR ;!FIXIT нет проверки на завершение по BC=0 DEC HL DEC HL LD A,'\' ; #5C CP (HL) INC HL JR Z,ADDSPE0 LD (HL),A INC HL ADDSPE0: ;R11 LD A,B AND A JR NZ,MM1 LD A,C CP 8 JR C,FINDDIR.error ;R11 LD BC,#0820 MM1 LD A,(DE) INC DE CP C JR Z,MM2 LD (HL),A ;!FIXIT вот тут может вылезать за пределы буфера при длинном пути и грохать код и данные. R11 времено лечит костылём INC HL MM2 DJNZ MM1 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: LD E,(IX+_sFM.ST_CLUSTER) LD D,(IX+_sFM.ST_CLUSTER+1) POP AF OUT (SLOT3),A AND A RET ////////////////////////////////////////////////////////////////////// ; Функция #1E. Информация о текущем каталоге. ; ; вход: HL - буфер в памяти 256 байт ; выход: A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// CURRDIR: EX DE,HL LD HL,DIRSPEC CURDIR1 LD A,(HL) OR A LDI JR NZ,CURDIR1 RET ;------------------------------------------------- ; Прочитать список каталога ;------------------------------------------------- LOADDIR: XOR A LD H,A LD L,A LD IX,0 LD B,A ; от начала файла CALL MOVE_FP SET_PAGE_X DIRPAGE 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 ; сохр. в дескриптор LD D,(IY+_sFM.ST_CLUSTER) ; de=номер первого кластера LD E,(IY+_sFM.ST_CLUSTER+1) LD A,D OR E JP Z,LROTDIR ; root ?? LD HL,DIR ; куда LD DE,#4000 ; сколько XOR A ; дескриптор CALL READ ; чтение из файла LD (DIRSIZE),DE ; число прочит. байтов POP AF OUT (SLOT3),A AND A RET LROTDIR LD HL,(FatBuffer.DIR_FRH) ; ст. разряд LD IX,(FatBuffer.DIR_FRL) ; номер лог. сектора LD A,(FatBuffer.DIR_S_S) LD B,32 ; !HARDCODE размер root-каталога SUB B JR NC,RTD1 ADD A,B LD B,A ; число секторов RTD1 LD A,(FatBuffer.DRIVE) ; номер диска LD DE,DIR ; буфер LD C,Dss.DRV.Read ; чтение секторов RST ToDSS.DRV POP AF OUT (SLOT3),A AND A RET ;------------------------------------------------- ; Сбросить кеш каталога на диск. ; вход: 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 LD D,(IY+_sFM.ST_CLUSTER) LD E,(IY+_sFM.ST_CLUSTER+1) LD A,D OR E JP Z,SROTDIR LD HL,DIR LD DE,(DIRSIZE) 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 SUB B JR NC,RTD1S ADD A,B LD B,A RTD1S LD A,(FatBuffer.DRIVE) LD DE,DIR LD C,Dss.DRV.Write RST ToDSS.DRV POP AF OUT (SLOT3),A AND A RET DIRSIZE: WORD 0 ; размер списка каталога size_cash_directory ;!TEST ;BANK: ; LD C,A ; LD B,0 ; LD HL,BANKTBL ; ADD HL,BC ; IN A,(SLOT3) ; LD C,SLOT3 ; OUTI ; RET ; ; Массив лог. номеров банок расширения ДОС BANKTBL: BLOCK USING_MEMPAGES+1,#FF ;!TODO ;G_HAND1 POP IX ; POP HL ; POP DE ; RET ;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 ;HANDTA BLOCK 32,0 MASKARE: BLOCK 8,0 ; имя файла BLOCK 3,0 ; расш. BLOCK 21,0 ; 11+21=32 ;------------------------------------------------- ; Преобразовать имя 8.3 -> 11 формат ; вход: hl = 8.3 имя ; de = буфер имени 11 симв. формата ; при ошибке CF - недоп. имя ; ; HL - MASK "file*.t??" ; DE - 11 bytes filename ; RET: C=2 FILE WITHOUT EXTENTION ; C=1 FILE WITH EXTENTION ;------------------------------------------------- MASK: PUSH HL PUSH DE LD H,D LD L,E INC DE LD (HL),' ' LD BC,10 ;!HARDCODE = size (FileName + Extension - 1) LDIR POP DE POP HL LD A,(HL) CP '.' ;R07 SCF ;R07 JR Z,.MASKB ;R07 CP ' '+1 .MASKB: LD A,DSS_Error.sys.INVALID_NAME RET C LD BC,#0902 ; B - счетчик MASK1: LD A,(HL) CP ' '+1 CCF RET NC CP '"' JR Z,MASK_ERR CP '*' JR Z,MASK3 CP '+' JR Z,MASK_ERR CP ',' JR Z,MASK_ERR CP '.' JR Z,MASK5 CP '/' JR Z,MASK_ERR CP ':' JR Z,MASK_ERR CP ';' JR Z,MASK_ERR CP '<' JR Z,MASK_ERR CP '=' JR Z,MASK_ERR CP '>' JR Z,MASK_ERR CP '[' JR Z,MASK_ERR CP '\' JR Z,MASK_ERR CP ']' JR Z,MASK_ERR CP '|' JR Z,MASK_ERR ; CP 'a' ;????? ; JR C,MASK2 ; CP '{' ; JR NC,MASK2 ; SUB #20 CALL UPPER ; a..z -> A..Z MASK2 LD (DE),A INC HL INC DE DJNZ MASK1 MASK_ERR: LD A,DSS_Error.sys.INVALID_NAME SCF RET MASK3: LD A,'?' INC HL DJNZ MASK6 LD A,DSS_Error.sys.INVALID_NAME SCF RET MASK6: LD (DE),A INC DE DJNZ MASK6 LD B,1 JR MASK1 MASK5: LD A,' ' INC HL DJNZ MASK4 LD B,4 DEC C JP NZ,MASK1 LD A,DSS_Error.sys.INVALID_NAME SCF RET MASK4: LD (DE),A INC DE DJNZ MASK4 LD B,4 DEC C JP NZ,MASK1 LD A,DSS_Error.sys.INVALID_NAME SCF RET ; a..z -> A..Z UPPER: CP 'a' RET C CP '{' JR NC,MDUPPER SUB #20 NOUPPER RET MDUPPER CP 'а' ; русская буква а, код #A0 JR C,NOUPPER CP 'п' ; русская буква п, код #B0 JR NC,BGUPPER SUB #20 RET BGUPPER CP 'р' ; русская буква р, код #E0 JR C,NOUPPER CP 'Ё' ; русская буква Ё, код #F0 JR NC,HGUPPER SUB #50 RET HGUPPER CP 'ё' ; русская буква ё, код #F1 RET NZ DEC A RET ////////////////////////////////////////////////////////////////////// ; Функция #21. Текущая дата и время. ; ; вход: нет ; выход: D - день ; E - месяц ; IX - год ; H - час ; L - минуты ; B - секунды ; C - день недели ////////////////////////////////////////////////////////////////////// SYSTIME LD C,BIOS.CMOS_TEST RST ToBIOS JP C,NOCMOS LD D,7 ;DAY CALL RCMOS PUSH AF LD D,8 ;MONTH CALL RCMOS POP DE LD E,A PUSH DE LD D,4 ;HOUR CALL RCMOS PUSH AF LD D,2 ;MINUTE CALL RCMOS POP DE LD E,A PUSH DE LD D,0 ;SECOND CALL RCMOS PUSH AF LD D,6 ;WEEK DAY LD C,BIOS.CMOS_RD RST ToBIOS POP DE LD E,A PUSH DE LD D,9 ;YEAR CALL RCMOS ;READ AND CONVERT TO DECIMAL PUSH AF LD D,#32 ;CENTURY LD C,BIOS.CMOS_RD RST ToBIOS LD XH,A POP AF CP 80 ;R01, TEST DECIMAL FIX PUSH AF JR C,XXIAGE LD A,#19 CP XH JR Z,GOODAGE JR BADAGE XXIAGE LD A,#20 CP XH JR Z,GOODAGE BADAGE PUSH AF LD D,#32 ;CENTURY LD C,BIOS.CMOS_WR RST ToBIOS POP AF LD XH,A GOODAGE POP AF LD XL,A LD A,XH CALL BCD2HEX LD L,A LD H,0 LD C,L LD B,H LD XH,B ADD HL,HL ADD HL,HL ADD HL,BC ADD HL,HL ;*10 LD B,H LD C,L ADD HL,HL ADD HL,HL ADD HL,BC ADD HL,HL ;*10(100) EX DE,HL ADD IX,DE POP BC POP HL POP DE AND A RET ; Чтение регистров CMOS ; вход: d=номер регистра RCMOS LD C,BIOS.CMOS_RD RST ToBIOS ; INPUT : A - BCD ; OUTPUT: A - HEX BCD2HEX LD E,A RRCA RRCA RRCA RRCA AND #0F LD D,A ADD A,A ADD A,A ADD A,D ADD A,A LD D,A LD A,E AND #0F ADD A,D RET NOCMOS LD DE,(NC_DAY) ;DAY/MONTH LD HL,(NC_HOUR) ;HOUR/MINUTE LD BC,(NC_SEC) ;SECOND/WEEKDAY LD IX,(NC_YEAR) ;YEAR AND A RET ; !FIXIT новый биос выставляет время, если с ним что-то не так. NOCMOS2 LD C,0 LD (NC_DAY),DE ;DAY/MONTH LD (NC_HOUR),HL ;HOUR/MINUTE LD (NC_SEC),BC ;SECOND/WEEKDAY LD (NC_YEAR),IX ;YEAR AND A RET ////////////////////////////////////////////////////////////////////// ; Функция #22. Установить текущую дату и время. ; ; вход: D - день ; E - месяц ; IX - год ; H - час ; L - минуты ; B - секунды ; выход: A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETTIME PUSH IX PUSH BC PUSH HL PUSH DE LD C,BIOS.CMOS_TEST RST ToBIOS JP C,NOCMOS2 POP AF PUSH AF LD D,7 ;DAY CALL WCMOS POP BC LD A,C LD D,8 ;MONTH CALL WCMOS POP AF PUSH AF LD D,4 ;HOUR CALL WCMOS POP BC LD A,C LD D,2 ;MINUTE CALL WCMOS POP AF PUSH AF LD D,0 ;SECOND CALL WCMOS POP BC LD A,C LD D,6 ;WEEK DAY LD C,BIOS.CMOS_WR RST ToBIOS POP HL XOR A LD DE,100 YR INC A SBC HL,DE JR NC,YR ADD HL,DE DEC A PUSH HL LD D,#32 ;CENTURY CALL WCMOS POP BC LD A,C LD D,9 ;YEAR CALL WCMOS AND A RET ;!FIXIT переделать по доке на Даллас и заись в ячейки часов ; Запись регистров CMOS ; вход: d=номер регистра WCMOS CALL HEX2BCD LD C,BIOS.CMOS_WR RST ToBIOS RET ; INPUT : A - HEX ; OUTPUT: A - BCD HEX2BCD LD BC,#0AFF H2B INC C SUB B JR NC,H2B ADD A,B LD B,A LD A,C RLCA RLCA RLCA RLCA AND #F0 OR B RET ; Дата по-умолчанию NC_DAY DW DAY*256+MONTH ;DAY/MONTH NC_HOUR DW #0000 ;HOUR/MINUTE NC_SEC DW #0001 ;SECOND/WEEKDAY NC_YEAR DW YEAR ;YEAR ////////////////////////////////////////////////////////////////////// ; Функция #17. Информация о дате и времени файла. ; ; вход: A - дескриптор файла ; выход: D - день ; E - месяц ; IX - год ; H - час ; L - минуты ; B - секунды ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// GET_D_T CALL SET_FM RET C ; время/дату из структуры дескр. LD E,(IY+_sFM.TIME) ; время LD D,(IY+_sFM.TIME+1) ; LD C,(IY+_sFM.DATE) ; дата LD B,(IY+_sFM.DATE+1) ; CALL RMKTIME ; раскодировать время/дату AND A RET ////////////////////////////////////////////////////////////////////// ; Функция #18. Изменение даты и времени файла. ; ; вход: A - дескриптор файла ; D - день ; E - месяц ; IX - год ; H - час ; L - минуты ; B - секунды ; выход: A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// PUT_D_T PUSH AF CALL MK_TIME ; закодировать время/дату POP AF ; дескриптор PUSH DE PUSH BC CALL SET_FM POP BC POP DE RET C LD (IY+_sFM.TIME),E LD (IY+_sFM.TIME+1),D LD (IY+_sFM.DATE),C LD (IY+_sFM.DATE+1),B SET 7,(IY+_sFM.ACCESS_MODE) ;R06 ; уст. признак изменения файла AND A RET ;------------------------------------------------- ; Закодировать время/дату ; вход: de - день/месяц ; hl - часы/минуты ; b - секунды ; ix - год ; выход: de - время ; bc - месяц/день ; ix - год ; ;INPUT: D - DAY; E - MONTH ; H - HOUR; L - MINUTE ; B - SECOND (0...59) ; IX- YEAR (0...65535) ;OUTPUT: DE - hhhhhmmmmmmsssss h - hour, m - min, s - sec/2 ; BC - yyyyyyymmmmddddd y - year, m - month, d - day ; (1980-2108) ;------------------------------------------------- MK_TIME LD A,L RLCA RLCA SLA A RL H SLA A RL H SLA A RL H SRL B OR B LD L,A LD BC,#F844 ;(-1980) ADD IX,BC LD A,E RLCA RLCA RLCA RLCA AND #F0 LD B,XL SLA A RL B OR D LD C,A EX DE,HL AND A RET ;------------------------------------------------- ; Раскодировать время/дату ; вход: de - время ; bc - месяц/день ; ix - год ; выход: de - день/месяц ; hl - часы/минуты ; b - секунды ; ix - год ; ;INPUT: DE - hhhhhmmmmmmsssss h - hour, m - min, s - sec/2 ; BC - yyyyyyymmmmddddd y - year, m - month, d - day ; (1980-2108) ;OUTPUT: D - DAY; E - MONTH ; H - HOUR; L - MINUTE ; B - SECOND (0...59) ; IX- YEAR (0...65535) ;------------------------------------------------- RMKTIME EX DE,HL LD A,C AND #1F LD D,A SRL B RR C LD A,C RRCA RRCA RRCA RRCA AND #0F LD E,A LD C,B LD B,0 LD IX,1980 ADD IX,BC LD A,L AND #1F ADD A,A LD B,A SRL H RR L SRL H RR L SRL H RR L SRL L SRL L AND A RET ////////////////////////////////////////////////////////////////////// ; Функция #1D. Смена текущего каталога. ; Меняет текущий каталог и текущий диск, если он указан в файловой ; спецификации. Если путь начинается с "\" - это означает путь от ; корневого каталога, иначе от текущего. ; ; вход: HL - указатель на имя каталога ; выход: нет ; ; INPUT: HL - "C:\DIR\DIR\DIR_NAME[\]",0 ////////////////////////////////////////////////////////////////////// CHDIR: CALL GETWORD ; тест на допуст. имя и настр. на диск RET C LD HL,TMPNAME LD A,(HL) OR A CALL NZ,OPENDIR RET ////////////////////////////////////////////////////////////////////// ; Функция #1B. Создание каталога. ; ; вход: HL - указатель на имя каталога ; выход: A - код ошибки, если CF=1 ; ; INPUT: HL - "C:\DIR\DIR\DIR_NAME",0 ////////////////////////////////////////////////////////////////////// MKDIR: _mSavePath CALL GETWORD ; тест на допуст. имя и настр. на диск RET C LD HL,TMPNAME ; 8.3 имя LD DE,MASKARE ; буфер имени 11 симв. формата CALL MASK ; преобр. имя 8.3 -> 11 формат RET C CALL LOADDIR ; прочитать список каталога CALL DSEARCH ; поиск записи каталога в списке диска LD A,DSS_Error.sys.DIR_EXISTS CCF RET C ; каталог найден CALL G_CLUST RET C PUSH HL LD DE,(FatBuffer.ENDCLUS) ; номер кластера CALL W_T_FAT ; записать в кеш FAT-а номер кластера CALL WR_FAT ; подкл. банку кеша FAT и записать его на диск LD HL,MASKARE LD DE,HANDBUF LD BC,11 LDIR EX DE,HL LD A,#10 ; атрибут записи каталога LD (HL),A INC HL LD BC,#0A00 ; b=счетчик .loop1: LD (HL),C INC HL DJNZ .loop1 PUSH HL CALL SYSTIME ; узнать тек. дату и время CALL MK_TIME ; закодировать время/дату POP HL LD (HL),E ; de=время INC HL LD (HL),D INC HL LD (HL),C ; день INC HL LD (HL),B ; месяц INC HL POP DE PUSH DE LD (HL),E INC HL LD (HL),D INC HL LD BC,#0400 ; b=счетчик .loop2: LD (HL),C INC HL DJNZ .loop2 CALL WRT_HND ; скопир. новую запись в список диска (каталога) CALL SAVEDIR ; сбросить кеш каталога на диск LD HL,SECBUF ; буфер LD (HL),"." ; запись тек. каталога LD BC,10*256 + ' ' ; b=счетчик, c=пробел .loop3: INC HL LD (HL),C DJNZ .loop3 INC HL LD DE,HANDBUF+11 ; ячейка атрибутов файла EX DE,HL LD BC,21 LDIR EX DE,HL LD (HL),"." ; запись родит. каталога INC HL LD (HL),"." LD BC,9*256 + ' ' ; b=счетчик, c=пробел MKD03 INC HL LD (HL),C DJNZ MKD03 INC HL IF OLD_SET_BANK PUSH HL ENDIF SET_PAGE_X DIRPAGE IF OLD_SET_BANK POP HL ENDIF PUSH AF LD A,(DIR) CP "." LD DE,DIR+11 ; атрибуты записи JP Z,MKD04 LD IX,HANDBUF XOR A LD (IX+_sFM.ST_CLUSTER),A LD (IX+_sFM.ST_CLUSTER+1),A LD DE,HANDBUF+11 ; ячейка атрибутов файла MKD04 EX DE,HL LD BC,HANDBUF.SIZE-11 LDIR POP AF OUT (SLOT3),A EX DE,HL LD D,H LD E,L INC DE LD (HL),0 LD BC,512-65 LDIR ;!FIXIT нужно ли так много грохать? POP HL CALL NSECTOR LD A,(BootSector.S_P_C) ; секторов на кластер MKD12 PUSH AF PUSH HL ; ст. разряд PUSH IX ; номер лог. сектора IN A,(SLOT3) PUSH AF IN A,(SLOT0) OUT (SLOT3),A ; LD A,(FatBuffer.DRIVE) LD DE,SECBUF+#C000 LD BC,1*256 + Dss.DRV.Write RST ToDSS.DRV ; POP AF OUT (SLOT3),A LD HL,SECBUF LD DE,SECBUF+1 LD BC,511 LD (HL),0 LDIR ;!FIXIT нужно ли так много грохать? POP IX POP HL INC IX LD A,XH OR XL JR NZ,MKD11 INC HL MKD11 POP AF DEC A JR NZ,MKD12 AND A RET ////////////////////////////////////////////////////////////////////// ; Функция #1C. Удаление каталога. ; Можно удалить только пустой каталог. ; ; вход: HL - указатель на имя каталога ; выход: A - код ошибки, если CF=1 ; ; INPUT: HL - "C:\DIR\DIR\DIR_NAME",0 ////////////////////////////////////////////////////////////////////// RMDIR: _mSavePath CALL GETWORD RET C LD HL,TMPNAME LD DE,MASKARE CALL MASK RET C LD HL,MASKARE LD BC,11 LD A,"?" CPIR LD A,DSS_Error.sys.INVALID_NAME SCF RET Z CALL LOADDIR CALL DSEARCH RET C LD HL,(HANDBUF+_sFM.ST_CLUSTER) PUSH IX RMD17 PUSH HL CALL NSECTOR LD A,(BootSector.S_P_C) RMD12 PUSH AF PUSH HL PUSH IX IN A,(SLOT3) PUSH AF IN A,(SLOT0) OUT (SLOT3),A LD DE,SECBUF+#C000 LD BC,1*256 + Dss.DRV.Read LD A,(FatBuffer.DRIVE) RST ToDSS.DRV POP AF OUT (SLOT3),A LD B,16 LD HL,SECBUF RMD10 LD A,(HL) OR A JP Z,RMD15 ;DIR EMPTY CP "." JR Z,RMD14 CP #E5 ;!HARDCODE байт удаления файла JR Z,RMD14 LD DE,11 ;!HARDCODE смещ. до байта атрибутов ADD HL,DE LD A,(HL) SBC HL,DE ;BIT 3,A AND %0000'1000 JP Z,RMD16 ;DIR NOT EMPTY RMD14 LD DE,#0020 ADD HL,DE DJNZ RMD10 POP IX POP HL INC IX LD A,XH OR XL JR NZ,RMD11 INC HL RMD11 POP AF DEC A JR NZ,RMD12 POP HL ; номер кластера CALL R_F_FAT ; прочитать из кеша FAT-а номер след. кластера EX DE,HL ; hl=номер след. кластера JR NC,RMD17 ; не конец цепочки RMD18 POP IX JP DELFILE ; пометить запись как "удаленная" RMD15 POP IX POP HL POP AF POP HL JR RMD18 RMD16 POP IX POP HL POP AF POP HL POP IX LD A,DSS_Error.sys.DIR_NOT_EMPTY SCF RET ;//MODULE: DOS5 ;[END]