;[BEGIN] ;//MODULE: DOS_FM ;//CREATE: 19-05-1998 AUTHOR: Denis Parinov ;//UPDATE: 24-10-1999 DNS Restore module ;--------------------------------------------------------------- ;Rev Date Name Description ;--------------------------------------------------------------- ;R01 16-11-1999 DNS ERROR READING FAT CHAIN ;--------------------------------------------------------------- ;FMS DB FMCOUNT ;ACCESS MODE: ; 00 - READ/WRITE ; 01 - READ ; 02 - WRITE ;FM_BUF: ;File Manipulator (FM) ; BYTE '. ' ;+00 NAME ; BYTE ' ' ;+08 EXT ; BYTE #10 ;+11 ATTRIBUT ; BYTE 0 ;+12 RESERVED; !TODO следующий кластер для чтения ; BYTE 0 ;+13 RESERVED; !TODO следующий кластер для записи ; BLOCK 8,0 ;+14 RESERVED ; WORD #0000 ;+22 TIME ; WORD #0000 ;+24 DATE ; WORD #0000 ;+26 START CLUSTER ; DWORD #0000 ;+28 SIZE FILE ; DWORD #0000 ;+32 FILE POSITION (FP) ; WORD #0000 ;+36 DIRECTORY CLUSTER ; WORD #0000 ;+38 HANDLE NUMBER ; BYTE #00 ;+40 DRIVE OR CURRENT ; BYTE #00 ;+41 ACCESS MODE ; BYTE #00 ;+42 TASK ; BYTE #00 ;+43 EMPTY /* ;!TEST FM_BUF: _sFM .Size EQU _sFM BLOCK (FMCOUNT-1)*FM_BUF.Size, 0 */ ; на выходе без ошибок IY указывает на файловый манипулятор MACRO _mFM_FIND CP FMCOUNT+1 JR NC,ABS_FM PUSH DE LD IY,FM_BUF LD DE,FM_BUF.Size AND A JR Z,.endLoop .loop: ADD IY,DE DEC A JR NZ,.loop .endLoop: POP DE ; A=0 OR (IY) ;+00 NAME ENDM SET_FM: _mFM_FIND LD A,0 ;!HARDCODE номер ошибки RET NZ ABS_FM LD A,DSS_Error.sys.INVALID_HANDLE SCF RET RES_FM: _mFM_FIND LD A,5 EXX SCF RET Z XOR A LD (IY+0),A RET GET_FM: LD B,FMCOUNT LD C,#FF LD IY,FM_BUF-FM_BUF.Size LD DE,FM_BUF.Size .loop: ADD IY,DE INC C LD A,(IY+0) OR A RET Z DJNZ .loop LD A,DSS_Error.sys.NO_HANDLES SCF RET ; HL:IX - OFFSET POINTER ; A - FILE MANIPULATOR MOVE_FP CALL SET_FM RET C INC B DEC B JR Z,.F_start DEC B JR Z,.F_current DEC B JR Z,.B_end LD A,DSS_Error.sys.INVALID_FUNCTION SCF RET ;from Start File .F_start: ; B=0 LD C,B LD D,B LD E,B JP .DO ;from End File .B_end: LD C,(IY+_sFM.F_SIZE) LD B,(IY+_sFM.F_SIZE+1) LD E,(IY+_sFM.F_SIZE+2) LD D,(IY+_sFM.F_SIZE+3) JP .DO ;from Current Position .F_current: LD C,(IY+_sFM.F_POSITION) LD B,(IY+_sFM.F_POSITION+1) LD E,(IY+_sFM.F_POSITION+2) LD D,(IY+_sFM.F_POSITION+3) .DO: ADD IX,BC ADC HL,DE LD D,XH LD E,XL LD (IY+_sFM.F_POSITION),E LD (IY+_sFM.F_POSITION+1),D LD (IY+_sFM.F_POSITION+2),L LD (IY+_sFM.F_POSITION+3),H XOR A RET ;FP COMPARE ; CY - FILE POINTER > SIZE ; NC - FILE POINTER < SIZE MOVE_CP: LD L,(IY+_sFM.F_SIZE) LD H,(IY+_sFM.F_SIZE+1) LD E,(IY+_sFM.F_POSITION) LD D,(IY+_sFM.F_POSITION+1) AND A SBC HL,DE LD L,(IY+_sFM.F_SIZE+2) LD H,(IY+_sFM.F_SIZE+3) LD E,(IY+_sFM.F_POSITION+2) LD D,(IY+_sFM.F_POSITION+3) SBC HL,DE RET ;-------------------- ECL2: ;!TEST SAVE CLUSTER AFTER READ POP BC ; POP BC POP DE AND A RET BLOKRD0 POP BC POP DE SCF RET ;READ SECTORS OF FILE ;HL:DE - FP (in sectors) ; B - Amount sectors BLOK_RD: PUSH BC LD (READMEM),IX LD A,(BootSector.S_P_C) ;SECTORS PER CLUSTER LD C,A LD B,0 ;HL:DE / BC => DE:IX HL-OSTATOK CALL DIV32 ;!FIXIT заменить вызов HLDE/BC на HLDE/C ;!FIXIT далее заточка на то, что в DE всегда 0 - раздел не больше 2Gb LD B,XH LD C,XL PUSH HL ;RESIDUE LD L,(IY+_sFM.ST_CLUSTER) ;START CLUSTER LD H,(IY+_sFM.ST_CLUSTER+1) LD A,H OR L ;!TEST SAVE CLUSTER AFTER READ ;JR NZ,BLOKRD2 PUSH BC JR NZ,.testFunc ; JP ECL2 ;R01 JR BLOKRD0 .testFunc: ;!TEST SAVE CLUSTER AFTER READ LD E,(IY+_sFM.KnownCluster_L) LD D,(IY+_sFM.KnownCluster_H) LD A,D OR E JR Z,BLOKRD2 PUSH DE PUSH HL PUSH BC LD E,(IY+_sFM.KnownOffset_L) LD D,(IY+_sFM.KnownOffset_H) LD A,D OR E JR Z,.noOptimization_1 POP HL AND A SBC HL,DE JR C,.noOptimization_2 LD C,L LD B,H POP HL POP DE EX DE,HL JP BLOKRD2 ; .noOptimization_1: POP BC .noOptimization_2: POP HL POP DE JP BLOKRD2 BLOKRD1: PUSH BC CALL R_F_FAT POP BC JR C,ECL2 ;R01 EX DE,HL DEC BC BLOKRD2: LD A,B ; ВС - смещение внутри файла в кластерах OR C JR NZ,BLOKRD1 ;!TEST SAVE CLUSTER AFTER READ LD (IY+_sFM.KnownCluster_L),L LD (IY+_sFM.KnownCluster_H),H POP BC LD (IY+_sFM.KnownOffset_L),C LD (IY+_sFM.KnownOffset_H),B ; POP DE POP BC LD A,(BootSector.S_P_C) SUB E LD C,A ;\ CP B ; \ JR C,BLOKRD3 ;SIZE > RESIDUE CLUSTER ; \ LD C,B ;SIZE < CLUSTER ;->-|--> ; !TODO разобраться BLOKRD3 LD A,B ; / SUB C ; / LD B,A ;/ PUSH HL PUSH BC PUSH DE CALL NSECTOR POP DE ADD IX,DE JR NC,BLOKRD4 INC HL BLOKRD4 LD DE,(READMEM) LD A,(FatBuffer.DRIVE) LD B,C LD C,Dss.DRV.Read RST ToDSS.DRV JP C,BLOKRD0 POP BC LD HL,(READMEM) LD DE,(BootSector.B_P_S) BLOKRD5 ADD HL,DE DEC C JR NZ,BLOKRD5 LD (READMEM),HL POP DE LD A,B OR A RET Z BLOKRD6 LD HL,BootSector.S_P_C LD A,B SUB (HL) LD B,A LD C,(HL) JR NC,BLOKRD7 LD B,0 ADD A,(HL) ;0 AND CF LD C,A OR A ;CLEAR CF RET Z BLOKRD7 EX DE,HL PUSH BC CALL R_F_FAT POP BC JP C,ECL1 ;R01? EX DE,HL PUSH HL PUSH BC CALL NSECTOR LD DE,(READMEM) LD A,(FatBuffer.DRIVE) LD B,C LD C,Dss.DRV.Read RST ToDSS.DRV JP C,BLOKRD0 POP BC LD HL,(READMEM) LD DE,(BootSector.B_P_S) BLOKRD8 ADD HL,DE DEC C JR NZ,BLOKRD8 LD (READMEM),HL POP DE JR BLOKRD6 ECL1 AND A RET ;-------------------- BLOKWRC: POP BC ;!TEST SAVE CLUSTER AFTER WRITE POP BC ; BLOKWR0 POP BC POP DE SCF RET ;WRITE SECTORS OF FILE ;HL:DE - FP (in sectors) ; B - Amount sectors BLOK_WR PUSH BC LD (READMEM),IX LD A,(BootSector.S_P_C) ;SECTORS PER CLUSTER LD C,A LD B,0 ;HL:DE / BC => DE:IX HL-OSTATOK CALL DIV32 LD B,XH LD C,XL PUSH HL ;RESIDUE LD L,(IY+_sFM.ST_CLUSTER) ;START CLUSTER LD H,(IY+_sFM.ST_CLUSTER+1) LD A,H OR L ;!TEST SAVE CLUSTER AFTER WRITE ;JR NZ,BLOKWR2 PUSH BC JR NZ,.testFunc ; PUSH BC CALL G_CLUST JR C,BLOKWRC LD (IY+_sFM.ST_CLUSTER),L LD (IY+_sFM.ST_CLUSTER+1),H LD DE,(FatBuffer.ENDCLUS) CALL W_T_FAT PUSH HL CALL WR_FAT POP HL POP BC JP BLOKWR2 .testFunc: ;!TEST SAVE CLUSTER AFTER WRITE LD E,(IY+_sFM.KnownCluster_L) LD D,(IY+_sFM.KnownCluster_H) LD A,D OR E JR Z,BLOKWR2 PUSH DE PUSH HL PUSH BC LD E,(IY+_sFM.KnownOffset_L) LD D,(IY+_sFM.KnownOffset_H) LD A,D OR E JR Z,.noOptimization_1 POP HL AND A SBC HL,DE JR C,.noOptimization_2 LD C,L LD B,H POP HL POP DE EX DE,HL JP BLOKWR2 ; .noOptimization_1: POP BC .noOptimization_2: POP HL POP DE JP BLOKWR2 BLOKWR1 PUSH BC CALL R_F_FAT JR NC,BLOKWRB PUSH HL CALL INC_FAT POP HL JR C,BLOKWRC CALL R_F_FAT BLOKWRB POP BC EX DE,HL DEC BC BLOKWR2 LD A,B OR C JR NZ,BLOKWR1 ;!TEST SAVE CLUSTER AFTER WRITE LD (IY+_sFM.KnownCluster_L),L LD (IY+_sFM.KnownCluster_H),H POP BC LD (IY+_sFM.KnownOffset_L),C LD (IY+_sFM.KnownOffset_H),B ; POP DE POP BC LD A,(BootSector.S_P_C) SUB E LD C,A CP B JR C,BLOKWR3 ;SIZE > RESIDUE CLUSTER LD C,B ;SIZE < CLUSTER BLOKWR3 LD A,B SUB C LD B,A PUSH HL PUSH BC PUSH DE CALL NSECTOR POP DE ADD IX,DE JR NC,BLOKWR4 INC HL BLOKWR4 LD DE,(READMEM) LD A,(FatBuffer.DRIVE) LD B,C LD C,Dss.DRV.Write RST ToDSS.DRV JP C,BLOKWR0 POP BC LD HL,(READMEM) LD DE,(BootSector.B_P_S) BLOKWR5 ADD HL,DE DEC C JR NZ,BLOKWR5 LD (READMEM),HL POP DE LD A,B OR A RET Z BLOKWR6 LD HL,BootSector.S_P_C LD A,B SUB (HL) LD B,A LD C,(HL) JR NC,BLOKWR7 LD B,0 ADD A,(HL) ;0 AND CF LD C,A OR A ;CLEAR CF RET Z BLOKWR7 EX DE,HL PUSH BC CALL R_F_FAT JR NC,BLOKWR9 PUSH HL CALL INC_FAT POP HL JR C,BLOKWRA CALL R_F_FAT BLOKWR9 POP BC EX DE,HL PUSH HL PUSH BC CALL NSECTOR LD DE,(READMEM) LD A,(FatBuffer.DRIVE) LD B,C LD C,Dss.DRV.Write RST ToDSS.DRV JP C,BLOKWR0 POP BC LD HL,(READMEM) LD DE,(BootSector.B_P_S) BLOKWR8 ADD HL,DE DEC C JR NZ,BLOKWR8 LD (READMEM),HL POP DE JR BLOKWR6 BLOKWRA POP BC LD A,DSS_Error.sys.DISK_FULL SCF RET TSTSIZE XOR A LD (READCOD),A LD L,(IY+32) ;FP LOW _sFM.F_POSITION LD H,(IY+33) ADD HL,DE EXX LD DE,0 LD L,(IY+34) ;FP HIGH LD H,(IY+35) ADC HL,DE EXX ;HL':HL - NEW FP LD C,(IY+28) ; _sFM.F_SIZE LD B,(IY+29) ;SIZE LOW AND A SBC HL,BC EXX LD C,(IY+30) ;SIZE HIGH LD B,(IY+31) SBC HL,BC EXX RET C ;OK READ ALL EX DE,HL SBC HL,DE ;VERY BIG EX DE,HL LD A,#FF LD (READCOD),A RET ; HL - ADDRESS ; DE - SIZE ; A - FM READ: LD (R_POINT),HL LD (S_POINT),HL CALL SET_FM RET C CALL TSTSIZE LD A,D OR E JP Z,NOREAD ;!FIXIT можно перенести в начало процедуры PUSH DE LD A,(IY+_sFM.DRIVE) CALL OPENDSK ; JP C,RPERR1 ;Расчёт смещения в секторах LD C,(IY+_sFM.F_POSITION) LD E,(IY+_sFM.F_POSITION+1) LD A,E AND #01 LD B,A LD D,(IY+_sFM.F_POSITION+2) LD L,(IY+_sFM.F_POSITION+3) LD H,0 OR A RR L RR D RR E ;HL:DE FP (in sectors) ;BC FP residue (in bytes) ; LD A,B OR C JP NZ,ROV1 ROV4: POP BC PUSH BC SRL B JR Z,ROV2 LD (SECTORH),HL LD (SECTORL),DE LD IX,(R_POINT) CALL BLOK_RD JP C,RPERR1 LD DE,(R_POINT) READMEM+1: LD HL,0 // LD HL,(READMEM) AND A SBC HL,DE LD C,H LD B,0 ADD HL,DE LD (R_POINT),HL SRL C SECTORL+1: LD HL,0 // LD HL,(SECTORL) ADD HL,BC EX DE,HL SECTORH+1: LD HL,0 // LD HL,(SECTORH) LD C,B ADC HL,BC ROV2: POP BC LD A,B AND #01 LD B,A OR C JP Z,ROV6 PUSH BC LD IX,BUFFER+#C000 LD B,1 IN A,(SLOT3) PUSH AF IN A,(SLOT0) OUT (SLOT3),A CALL BLOK_RD POP BC LD C,SLOT3 OUT (C),B JP C,RPERR1 LD HL,BUFFER LD DE,(R_POINT) POP BC LDIR LD (R_POINT),DE ROV6: S_POINT+1: LD HL,0 LD DE,(R_POINT) EX DE,HL AND A SBC HL,DE PUSH HL EX DE,HL LD XH,D LD XL,E LD HL,0 CALL MOVE_FP.F_current POP DE NOREAD: READCOD+1: LD A,0 OR A RET ROV1: PUSH BC PUSH HL PUSH DE LD IX,BUFFER+#C000 LD B,1 IN A,(SLOT3) PUSH AF IN A,(SLOT0) OUT (SLOT3),A CALL BLOK_RD POP BC LD C,SLOT3 OUT (C),B POP HL JP C,RPERR3 LD BC,1 ADD HL,BC EX DE,HL POP HL LD C,B ADC HL,BC EXX POP DE LD HL,512 AND A SBC HL,DE LD B,H LD C,L POP HL AND A SBC HL,BC JR NC,ROV3 ADD HL,BC LD B,H LD C,L LD HL,0 ROV3: PUSH HL LD HL,BUFFER ADD HL,DE LD DE,(R_POINT) LDIR LD (R_POINT),DE EXX JP ROV4 RPERR3: POP HL RPERR2: POP HL RPERR1: POP BC SCF RET PWERR3: POP HL PWERR2: POP HL PWERR1: POP BC SCF RET RD_ONLY: POP DE LD A,DSS_Error.sys.READONLY SCF RET ; HL - ADDRESS ; DE - SIZE ; A - FM WRITE: LD (R_POINT),HL LD (S_POINT),HL PUSH DE CALL SET_FM JP C,PWERR1 LD A,(IY+_sFM.ACCESS_MODE) AND #01 JR NZ,RD_ONLY SET 7,(IY+_sFM.ACCESS_MODE) SET 5,(IY+_sFM.ATTRIBUT) LD A,(IY+_sFM.DRIVE) CALL OPENDSK JP C,PWERR1 LD C,(IY+_sFM.F_POSITION) LD A,(IY+_sFM.F_POSITION+1) LD E,A AND #01 LD B,A LD D,(IY+_sFM.F_POSITION+2) LD L,(IY+_sFM.F_POSITION+3) LD H,0 OR A RR L RR D RR E ; HL:DE - FP (in sectors) ; BC - FP residue (in bytes) LD A,B OR C JP NZ,WOV1 WOV4: POP BC PUSH BC SRL B JR Z,WOV2 PUSH HL PUSH DE PUSH BC R_POINT+2: LD IX,0 // LD IX,(R_POINT) CALL BLOK_WR POP BC JP C,PWERR3 LD C,B LD HL,(R_POINT) LD DE,#0200 WOV5: ADD HL,DE DJNZ WOV5 LD (R_POINT),HL LD B,0 POP HL ADD HL,BC EX DE,HL POP HL LD C,B ADC HL,BC WOV2: POP BC LD A,B AND #01 LD B,A OR C JP Z,WOV6 PUSH HL PUSH DE PUSH BC LD IX,BUFFER+#C000 LD B,1 IN A,(SLOT3) PUSH AF IN A,(SLOT0) OUT (SLOT3),A CALL BLOK_RD POP BC LD C,SLOT3 OUT (C),B LD DE,BUFFER LD HL,(R_POINT) POP BC JP C,PWERR2 LDIR LD (R_POINT),HL POP DE POP HL LD IX,BUFFER+#C000 LD B,1 IN A,(SLOT3) PUSH AF IN A,(SLOT0) OUT (SLOT3),A CALL BLOK_WR POP BC LD C,SLOT3 OUT (C),B RET C WOV6: LD DE,(S_POINT) LD HL,(R_POINT) AND A SBC HL,DE PUSH HL EX DE,HL LD XH,D LD XL,E LD HL,0 CALL MOVE_FP.F_current CALL MOVE_CP POP DE RET NC LD L,(IY+32) LD H,(IY+33) LD C,(IY+34) LD B,(IY+35) LD (IY+28),L LD (IY+29),H LD (IY+30),C LD (IY+31),B AND A RET WOV1: PUSH BC PUSH HL PUSH DE LD IX,BUFFER+#C000 LD B,1 IN A,(SLOT3) PUSH AF IN A,(SLOT0) OUT (SLOT3),A CALL BLOK_RD POP BC LD C,SLOT3 OUT (C),B POP DE POP HL EXX POP DE JP C,PWERR1 LD HL,512 AND A SBC HL,DE LD B,H LD C,L POP HL AND A SBC HL,BC JR NC,WOV3 ADD HL,BC LD B,H LD C,L LD HL,0 WOV3: PUSH HL LD HL,BUFFER ADD HL,DE LD DE,(R_POINT) EX DE,HL LDIR LD (R_POINT),HL EXX PUSH HL PUSH DE LD IX,BUFFER+#C000 LD B,1 IN A,(SLOT3) PUSH AF IN A,(SLOT0) OUT (SLOT3),A CALL BLOK_WR POP BC LD C,SLOT3 OUT (C),B POP HL JP C,PWERR2 LD BC,1 ADD HL,BC EX DE,HL POP HL LD C,B ADC HL,BC JP WOV4 ; HL - CLUSTER ; HL:IX - SECTOR NSECTOR: DEC HL DEC HL EX DE,HL LD A,(BootSector.S_P_C) LD B,A LD HL,0 LD IX,0 ADD_DE1: ADD IX,DE JR NC,ADD_DE2 INC HL ADD_DE2: DJNZ ADD_DE1 LD DE,(FatBuffer.DAT_FRM) ADD IX,DE LD DE,#0000 ADC HL,DE RET ; HL:DE / BC => DE:IX HL-OSTATOK DIV32: LD XH,D LD XL,E EX DE,HL LD HL,0 LD A,#20 DIV001: ADD IX,IX EX DE,HL ADC HL,HL EX DE,HL ADC HL,HL SBC HL,BC JR NC,DIV002 ADD HL,BC DEC A JR NZ,DIV001 RET DIV002: INC IX DEC A JR NZ,DIV001 RET //READCOD DB #00 //READMEM DW #0000 //SECTORH DW 0 //SECTORL DW 0 //R_POINT DW 0 //S_POINT DW 0 ;//MODULE: DOS_FM ;[END]