home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1998 July / pcx23_9807.iso / PC-XUSER / PC-XUSER.18 / TT / R4S_FDOS.INT < prev    next >
Encoding:
Text File  |  1998-06-14  |  46.6 KB  |  1,280 lines

  1. {*********************************************}
  2. {                                             }
  3. {   R4s File DOS Function Unit                }
  4. {   Copyright (c) 1996, 97 By Bérczi László   }
  5. {                                             }
  6. {*********************************************}
  7. {Last Edit: 1997 VI 1. 15:00}
  8. {R4s File DOS = R4s rewrited all the DOS File user function for making a
  9.  virtual disks. It means you have a disk image file and R4sFDOS makes a
  10.  virtual drive from it - under R4sFDOS -.}
  11. {$G+}
  12.  
  13. {Bugs:
  14.  - Critical error No mouse update (while Dump-ing disk, NO Handle Event)
  15.  - Just that ONE ... ^
  16. }
  17.  
  18. unit R4s_FDOS;
  19.  
  20. INTERFACE
  21. uses Objects, R4s_Symb, X_Stream;
  22.  
  23. type
  24.  
  25.   PChar13 = ^TChar13;
  26.   TChar13 = Array[1..13] of Char;
  27.  
  28.   PChar11 = ^TChar11;
  29.   TChar11 = Array[1..11] of Char;
  30.  
  31.   PChar8 = ^TChar8;
  32.   TChar8 = Array[1..8] of Char;
  33.  
  34.   PChar3 = ^TChar3;
  35.   TChar3 = Array[1..3] of Char;
  36.  
  37.   PFCB = ^TFCB;
  38.   TFCB = record {for DOS 5.0+}
  39.     DriveNumber   : Byte;
  40.     FileName      : TChar8;
  41.     FileExt       : TChar3;
  42.     CurrBlockNum  : Word; {current block number; each block is 128 Byte long}
  43.     LogicalRecSize: Word;
  44.     FileSize      : Longint;
  45.     FileDate,             {Date of last write}
  46.     FileTime      : Word; {Time of last write}
  47. {S+}SysFileEntry  : Byte; {EXT FUNCS} {number of system file table entry for file}
  48.     Attribute     : Byte; {bits 7,6 - SHARE.exe ... ; bits 5-0 device attribute word}
  49.     ExtraInfo     : Byte; {b7: RO attr from SFT; b6 archive attr from SFT
  50.                            b5-0: high number of sector number}
  51.     StartCluster  : Word; {starting cluster of file}
  52.     SectorNumber  : Word; {low word of sector number containing directory entry}
  53. {E+}DirEntrypSec  : Byte; {END EXT FUNCS} {number of directory entry within sector}
  54.     RecordInCurBlk: Byte; {record within current block 0-127}
  55.     RndAccRecNum  : Longint; {random access record number (if record size is > 64 bytes, high byte is omitted)}
  56.     R4sFCBsPos    : Byte;
  57.   end;
  58.  
  59.   PRFCB = ^TRFCB;
  60.   TRFCB = record {TRFCB: FCB for renaming}
  61.     DriveNumber: Byte;
  62.     OldFileName: TChar8;
  63.     OldFileExt : TChar3;
  64.     NillAreaLow: Array[1..5] of Char;
  65.     NewFileName: TChar8;
  66.     NewFileExt : TChar3;
  67.     NillAreaHi : Array[1..9] of Char;
  68.   end;
  69.  
  70.   PHandle = ^THandle;
  71.   THandle = record
  72.     Path    : String[80]; {temporary}
  73.     Entry   : TDirectoryEntry;        
  74.     Position: Longint; {in Byte from start of file}
  75.     PosZero : Boolean;
  76.     OwnerDIR: Word;    {Owner directory's cluster number}
  77.   end;
  78.  
  79.   {R4s_Symb includes these types}
  80. (*PDirectoryEntry = ^TDirectoryEntry;
  81.   TDirectoryEntry = record
  82.     FileName : TChar8;
  83.     Extension: TChar3;
  84.     Attribute: Byte;
  85.     Reserved : Array[1..10] of Byte;
  86.     Time,
  87.     Date,
  88.     ClusterNumber: Word;
  89.     FileSize     : Longint;
  90.   end;
  91.  
  92.   PDriveParameterBlock = ^TDriveParameterBlock;
  93.   TDriveParameterBlock = record
  94.     Drive             : Byte; {0: A, 1: B . . .}
  95.     UNWDeviceDriver   : Byte;
  96.     BytePerSector     : Word;
  97.     SectorPerCluster  : Byte;
  98.     SqrNSectorACluster: Byte;
  99.     BootSizeInSector  : Word;
  100.     FATNumber         : Byte;
  101.     MaxDirectories    : Word;
  102.     FirstDataSector   : Word;
  103.     MaxCluster        : Word;
  104.     SectorPerFAT      : Word;
  105.     FirstDIRsSector   : Word;
  106.     DeviceHeader      : PDeviceHeader;
  107.     MediaID           : Byte;
  108.     AccessByte        : Byte;
  109.     NextDPB           : PDriveParameterBlock;
  110.     FirstFreeCluster  : Word;
  111.     FreeClusterssNumb : Word
  112.   end;  {R4s_REM}
  113.  
  114.   PFileTime = ^TFileTime;
  115.   TFileTime = record
  116.     Hour,
  117.     Minute,
  118.     Second: Byte;
  119.   end;
  120.  
  121.   PFileDate = ^TFileDate;
  122.   TFileDate = record
  123.     Year : Word;
  124.     Month,
  125.     Day  : Byte;
  126.   end;
  127.  
  128.   PBootSecInforms = ^TBootSecInforms; {SizeOf(TBootSecInforms) = 62 Byte}
  129.   TBootSecInforms = record
  130.     JMP            : Array[1..3] of Byte;
  131.     OEMName        : Array[1..8] of Char;
  132.     Byte_Sector    : Word;
  133.     Sector_Cluster : Byte;
  134.     ReservedSecs   : Word;
  135.     FATCount       : Byte;    {FATCount * SectorInOneFAT          }
  136.     MaxRootEntries,           {(MaxRootEntries * 32) / Byte_Sector}
  137.     Total_Sector   : Word;    {DataStart = ReservedSecs + FATSize + RootSize}
  138.     MediaDescriptor: Byte;
  139.     SectorInOneFAT,
  140.     Sector_Track,
  141.     Head_Number,
  142.     Hidden_Sector  : Word;    {if partitions > 32M then It's the Lo Word    }
  143.     Hidden_SectorHi: Word;    {if partitions > 32M then used else not used  }
  144.     BIGTotal_Sector: Longint; {if (partitions > 32M) And (Total_Sector = 0) }
  145.     PhisicalDriveNo: Byte;    {   then used else not used                   }
  146.     InfoLevel      : Word;    {Must be 0 ???}
  147.     SerialNumber   : Longint; {In Hex (bin) }
  148.     VolumeLabel    : Array[1..11] of Char; {'NO NAME    ' if none present}
  149.     FileSystemType : Array[1..8] of Char;  {'FAT12   ' or 'FAT16   ' or 'FAT     ' (OS2)}
  150.     TempArray      : Array[1..1024-62] of Byte;
  151.   end;   
  152.   *)
  153.  
  154.   PFindFileDataType = ^TFindFileDataType;
  155.   TFindFileDataType = record    
  156.     DriveLetter      : Byte;
  157.     SearchTemp       : TChar11;
  158.     SearchAttribute  : Byte;
  159.     EnrtyCountwDIR   : Word;
  160.     OwnerDIRStartClus: Word;
  161.     OwnerDIRSector   : Longint;
  162.     {Reserved         : Array[1..4] of Char;}
  163.     FoundAttribute   : Byte;
  164.     FileTime,
  165.     FileDate         : Word;
  166.     FileSize         : Longint;
  167.     FileName         : TChar13; {ASCIIZ !!!}    
  168.   end;
  169.  
  170.   PNameBuffer = ^TNameBuffer;
  171.   TNameBuffer = Array[1..128] of Char;
  172.  
  173.   PDiskInfo_Serial = ^TDiskInfo_Serial;
  174.   TDiskInfo_Serial = record
  175.     InfoLevel     : Word; {Must be 0}
  176.     SerialNumber  : Longint;
  177.     VolumeLabel   : Array[1..11] of Char; {'NO NAME    ' if none present}
  178.     FileSystemType: Array[1..8] of Char;  {'FAT12   ' or 'FAT16   '}
  179.   end;
  180.  
  181.   PCurrentDIR = ^TCurrentDIR;
  182.   TCurrentDIR = record
  183.     Sector: Longint;
  184.     Path  : String;
  185.   end;
  186.  
  187.   PBuffer4k = ^TBuffer4k;
  188.   TBuffer4k = Array[1..4096] of Char;
  189.  
  190.   PBuffer = ^TBuffer;
  191.   TBuffer = Array[1..16384] of Char;
  192.  
  193.   PBuffer64k = ^TBuffer64k;
  194.   TBuffer64k = Array[1..65535] of Char;
  195.  
  196.   PBooleanArray = ^TBooleanArray;
  197.   TBooleanArray = Array[0..5760] of Boolean;
  198.  
  199.   PSector = ^TSector;
  200.   TSector = Array[1..4096] of Char; {Usually the Sector size is 512 Byte}
  201.  
  202.   PFileTime = ^TFileTime;
  203.   TFileTime = record
  204.     Hour,
  205.     Minute,
  206.     Second: Byte;
  207.   end;
  208.  
  209.   PFileDate = ^TFileDate;
  210.   TFileDate = record
  211.     Year : Word;
  212.     Month,
  213.     Day  : Byte;
  214.   end;
  215.  
  216.   PAbstractDrive = ^TAbstractDrive;
  217.   TAbstractDrive = Object(TObject)
  218.   public
  219.     LastStatus: Byte;
  220.     CF        : Boolean; {Carray Flag}
  221.     Drive     : Byte;
  222.     constructor Init(ADrive: Byte);
  223.     destructor  Done; virtual;
  224.     function  ResetDisk(ADrive: Byte): Byte; virtual; {Ret: Status} {1300}
  225.     function  GetStatusOfLastOperation(ADrive: Byte): Byte; virtual;  {Ret: Status} {1301}
  226.     function  ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector,
  227.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; virtual; {1302}
  228.     function  WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector,
  229.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean; virtual; {1303}
  230.     function  VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector,
  231.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean; virtual; {1304}
  232.     function  ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  233.                 var Status, ReadedSecCount: Byte): Boolean; virtual; {1301}
  234.     procedure GetDriveDatas(var AFATStart, AFATSize, ARootStart, ARootSize, ADataStart: Word; var AMaxEntryPerSec: Byte;
  235.                 var ABootInf: TBootSecInforms);
  236.     function  GetDriveNumber: Byte;
  237.   private
  238.     FATStart,
  239.     FATSize,
  240.     RootStart,
  241.     RootSize,
  242.     DataStart       : Word;
  243.     MaxEntryPerSec  : Byte;
  244.     BootInf         : TBootSecInforms; {The BootSector's informations}
  245.     UseXMSCache     : Boolean;
  246.     IsSectorIn,
  247.     IsSectorModified: PBooleanArray;
  248.     XMSCache        : PXMSStream;
  249.   end;
  250.  
  251.   PPhisicalDrive = ^TPhisicalDrive;
  252.   TPhisicalDrive = Object(TAbstractDrive)
  253.   public
  254.     constructor Init(ADrive: Byte);
  255.     destructor  Done; virtual;
  256.     function  ResetDisk(ADrive: Byte): Byte; virtual; {Ret: Status} {1300}    
  257.     function  ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  258.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; virtual; {1302}
  259.     function  WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  260.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean; virtual; {1303}
  261.     function  VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  262.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean; virtual; {1304}
  263.     function  ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  264.                 var Status, ReadedSecCount: Byte): Boolean; virtual; {1301}
  265.   end;
  266.  
  267.   PImageDrive = ^TImageDrive;
  268.   TImageDrive = Object(TAbstractDrive)
  269.   public
  270.     DriveStr : String[80];
  271.     ImageFile: File;
  272.     constructor Init(ADrive: String);
  273.     destructor  Done; virtual;
  274.     function  ResetDisk(ADrive: Byte): Byte; virtual; {Ret: Status} {1300}    
  275.     function  ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  276.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; virtual; {1302}
  277.     function  WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  278.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean; virtual; {1303}
  279.     function  VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  280.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean; virtual; {1304}
  281.     function  ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  282.                 var Status, ReadedSecCount: Byte): Boolean; virtual; {1301}
  283.     function  SetWriteProtect(On: Boolean): Boolean; virtual;
  284.   private
  285.     IsWriteProtected: Boolean;
  286.     function  GetBytePERSector: Word;
  287.   end;
  288.  
  289. (* PXMSImageDrive = ^TXMSImageDrive;
  290.   TXMSImageDrive = Object(TAbstractDrive)
  291.   public
  292.     DriveStr : String[80];
  293.     ImageFile: File;
  294.     constructor Init(ADrive: String);
  295.     destructor  Done; virtual;
  296.     function  ResetDisk(ADrive: Byte): Byte; virtual; {Ret: Status} {1300}
  297.     function  ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  298.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; virtual; {1302}
  299.     function  WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  300.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean; virtual; {1303}
  301.     function  VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  302.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean; virtual; {1304}
  303.     function  ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  304.                 var Status, ReadedSecCount: Byte): Boolean; virtual; {1301}
  305.     function  SetWriteProtect(On: Boolean): Boolean; virtual;
  306.   private
  307.     IsWriteProtected: Boolean;
  308.     function  GetBytePERSector: Word;
  309.   end;
  310. *)
  311.  
  312.   {MicroSoft offers handle-oriented file commands instead of FCB like !!!
  313.    So handle-oriented file commands is more reliable then FCB like.
  314.    /FCB oriented file command may mistakes/  - MicroSoft (MS-DOS)}
  315.  
  316.   PR4sFileDOS = ^TR4sFileDOS;
  317.   TR4sFileDOS = Object(TObject)
  318.   public {Original DOS functions}
  319. {R} constructor Init(ADriveObj: PAbstractDrive); {R means it's ready}
  320. {R} destructor  Done; virtual;
  321. {R} procedure SelectDefaultDrive(DriveImageFile: String); virtual;               {210E}
  322. {R} function  OpenFileByFCB(var FCB: TFCB): Boolean; virtual;  {UnOp}            {210F}
  323. {R} function  CloseFileByFCB(var FCB: TFCB): Boolean; virtual; {  Op}            {2110}
  324.     function  FindFirstByFCB(FCB: TFCB): Boolean; virtual; {UnOp}                {2111}
  325.     function  FindNextByFCB(FCB: TFCB): Boolean; virtual;  {UnOp}                {2112}
  326.     function  DeleteFileByFCB(FCB: TFCB): Boolean; virtual;{UnOp}                {2113}
  327. {R} function  SeqReadByFCB(var FCB: TFCB): Boolean;virtual;{Op,Return data in DTA 2114}
  328.     function  SeqWriteByFCB(FCB: TFCB): Boolean; virtual;  {Op,Expect data in DTA 2115}
  329.     function  CreateFileByFCB(FCB: TFCB): Boolean; virtual;{UnOp,overw. if exist  2116}
  330.     function  RenameFileByFCB(RFCB: TRFCB): Boolean; virtual;                    {2117}
  331. {R} function  GetCurrentDrive: String; virtual;                                  {2119}
  332. {R} procedure SetDTA(Address: Pointer); virtual;           {Disk Transfer Area    211A}
  333.     procedure GetAllocationInformationForDefDrive(var SecClus: Byte;    {211B}
  334.                 var ByteSec: Word; var TotClus: Word; var MediaID: Byte); virtual;
  335.   (*procedure GetAllocationInformationForSpecDrive(Drive: String; var SecClus: Byte;  {211C}
  336.               var ByteSec: Word; var TotClus: Word; var MediaID: Byte); virtual;*)
  337.     function  GetDPBForDefDrive: PDriveParameterBlock; virtual;                  {211F}
  338.     function  ReadRandomRecByFCB(FCB: TFCB): Boolean; virtual;   {Op,Return data in DTA 2121}
  339.     function  WriteRandomRecByFCB(FCB: TFCB): Boolean; virtual;  {Op,Except data in DTA 2122}
  340.     function  GetFileSizeByFCB(var FCB: TFCB): Boolean; virtual; {UnOp   2123}
  341.     procedure SetRandomRecNumbForFCB(var FCB: TFCB); virtual;    {Op     2124}
  342.     function  RandomBlockReadByFCB(var NumbRecToRead: Word; var FCB: TFCB): Boolean; virtual; {Op,Return data in DTA 2127}
  343.     function  RandomBlockWriteByFCB(var NumbRecToRead: Word; var FCB: TFCB): Boolean; virtual;{Op,Except data in DTA 2128}
  344.     function  PraseFileNameToFCB(var FCB: TFCB; Str: String; var UnPrasedPos: Byte): Boolean; virtual; {UnOp 2129}
  345. {R} function  GetDTA: Pointer; virtual; {212F}
  346.   (*function  GetDPBForSpecDrive(Drive: String): PDriveParameterBlock; virtual; {2132}*)
  347.     function  GetFreeDiskSpace(Drive: String; var SecClus, FreeClus, ByteClus, TotalClus: Word): Boolean; virtual; {2136}
  348.     function  MkDIR(Name: TASCIIZ): Boolean; virtual; {2139}
  349.     function  RmDIR(Name: TASCIIZ): Boolean; virtual; {213A}
  350. {R} function  ChDIR(Name: TASCIIZ): Boolean; virtual; {213B}
  351.     function  CreatFile(Name: TASCIIZ; Attributes: Word; var Handle: Word): Boolean; virtual; {213C}
  352. {R} function  OpenFile(Name: TASCIIZ; AccessMode: Byte; var Handle: Word): Boolean; virtual;  {213D}
  353. {R} function  CloseFile(Handle: Word): Boolean; virtual; {213E}
  354. {R?}function  ReadFromFile(Handle: Word; var ByteToRead: Word; var Buf; BufSize: Word): Boolean; virtual; {213F}
  355. {N} function  WriteToFile(Handle: Word; var ByteToWrite: Word; var Buf): Boolean; virtual; {2140}
  356.     function  DeleteFile(Name: String): Boolean; virtual; {2141}
  357. {R} function  SeekFile(Handle: Word; SeekType: Byte; var Pos: Longint): Boolean; virtual;  {2142}
  358. {R} function  GetFilePos(Handle: Word): Longint; {2142xx} {if Return = $FFFFFFFF then It means Error !}
  359. {*} function  GetFileAttributes(Name: String; var Attributes: Word): Boolean; virtual; {214300}
  360.     function  SetFileAttributes(Name: String; Attributes: Word): Boolean; virtual;     {214301}
  361.   (*function  GetDeviceInforms(Handle: Word; var Inform: Word): Boolean; virtual;      {214400}
  362.     function  SetDeviceInforms(Handle: Word; Inform: Word): Boolean; virtual;          {214401}*)
  363.     function  DuplicateFileHandle(Handle: Word; var NewHandle: Word): Boolean; virtual;  {2145}
  364. {?} function  DuplicateFileHandle2(Handle: Word; var NewHandle: Word): Boolean; virtual; {2146}
  365.     function  GetCurrentDIR(Drive: Byte; var ASCIIZPath: TASCIIZ): Boolean; virtual; {2147}
  366. {R} function  FindFirstFile(Name: TASCIIZ; Attribute: Byte): Boolean; virtual; {Return FF DataBlock in DTA  214E}
  367. {R} function  FindNextFile: Boolean; virtual; {EXCEPT previous FF DataBlock in DTA  214F}
  368.     function  RenameFile(OldName, NewName: TASCIIZ): Boolean; virtual; {2156}
  369. {R} function  GetFilesTimeAndDate(Handle: Word; var Time, Date: Word): Boolean; virtual; {215700}
  370.     function  SetFilesTimeAndDate(Handle: Word; Time, Date: Word): Boolean; virtual;     {215701}
  371.   (*function  GetExtAttributesForFile    {215702}
  372.     function  GetExtAttributesProperties {215703}
  373.     function  SetExtAttributes           {215704}*)
  374.     function  CreateTempFile(var Name: TASCIIZ {\ !}; Attribute: Word; var Handle: Word): Boolean; virtual; {215A}
  375.     function  CreateNewFile(var Name: TASCIIZ; Attribute: Word; var Handle: Word): Boolean; virtual;        {215B}
  376.     function  NameExpand(Name: TASCIIZ; var OutNameBuffer: TNameBuffer): Boolean; virtual; {Canonicalize filename or path 2160}
  377.     function  FlushFileDatas(Handle: Word): Boolean; virtual; {2168}
  378. {*} function  GetDiskSerialNumber(Disk: String; var DiskInfo: TDiskInfo_Serial): Boolean; virtual; {216900}
  379.     function  SetDiskSerialNumber(Disk: String; DiskInfo: TDiskInfo_Serial): Boolean; virtual;     {216901}
  380.     function  ComitFile(Handle: Word): Boolean; virtual; {216A}
  381. {}  function  ExtendedOpenOrCreateFile(Name: String; OpenMode, Flags: Byte; Attribute: Word; Action: Byte;
  382.                 var Handle: Word): Boolean; virtual; {216C00}
  383.    {function  AbsouluteDiskRead(Disk: String; SecToRead, StartSec: Word; var Buf ... {26..}
  384.   public {DOS Extensions}
  385.     function  GetFileSize(Handle: Word): Longint;
  386.   public {Helper methods for using DOS functions}
  387.     DTA  : Pointer;
  388.     Error: Byte;
  389.     procedure PrepareFCBForUsing(var FCB: TFCB; AFileName, AFileExt: String);
  390.     procedure TempFunc;
  391.   public {Temporary, check methods for out use}
  392.     function  GetHandle(Handle: Byte): PHandle;
  393.   private {Sub-methods for internal use of FDOS}
  394.     function  GetSectorOfDirectory(Name: TASCIIZ; var Sector: Longint; var Path: String): Boolean; virtual;
  395.   private
  396.     MyFCB     : TFCB;
  397.     TheDrive  : String;
  398.     DriveNum  : Byte;
  399.     DriveObj  : PAbstractDrive;
  400.     DriveImage: File;
  401.     CurDIR    : TCurrentDIR;
  402.     ASector   : TSector;
  403.     AEntry    : TDirectoryEntry;
  404.     FATStart,
  405.     FATSize,
  406.     RootStart,
  407.     RootSize,
  408.     DataStart     : Word;
  409.     MaxEntryPerSec: Byte;
  410.     BootInf       : TBootSecInforms; {The BootSector's informations}
  411.     FCBs          : Array[1..50] of PFCB;
  412.     Handles       : Array[6..55] of THandle;
  413.     IsUsedHandle  : Array[6..55] of Boolean;
  414.     FAT           : PBuffer; {64k;}
  415.     Is12bitFAT    : Boolean;
  416.     CRC_ASector,
  417.     SectorNumber  : Longint;
  418.   private {Internal converter, and other helper methods}
  419.     function  GetSectorPerByteInADriveImage(Drive: String): Word;
  420.     procedure ClearAllLocalVariable;
  421.     function  ReadLogicalSector(SecNb: Longint): Boolean;
  422.     function  ReadnLogigalSector(FromSector: Longint; var Count: Word; ToMem: Pointer): Boolean;
  423.     function  IsEntryASimpleFile(Entry: TDirectoryEntry): Boolean;
  424.     function  ConvertClusterNumberToLogicalSector(ClusNum: Word): Longint;
  425.     function  ConvertLogicalSectorToClusterNumber(LogSec: Longint): Word;
  426.     function  IsNULLEntry(const Entry: TDirectoryEntry): Boolean;
  427.     function  IsNULLTheEntry(Sector: TSector; Index: Word): Boolean;
  428.     function  IsFillWithEntry(Sector: TSector): Boolean;
  429.     function  IsUsedEntry(Sector: TSector; Index: Word): Boolean;
  430.     procedure CopyBufToBootInforms(var Buf; var ABootInf: TBootSecInforms);
  431.     procedure ConvertTimeWordToRecord(FileTimeW: Word; var FileTime: TFileTime);
  432.     procedure ConvertDateWordToRecord(FileDateW: Word; var FileDate: TFileDate);
  433.     procedure CopyBufToDirEntry(var Buf; Index: Byte; var _AEntry: TDirectoryEntry);
  434.     procedure GetBootInforms;
  435.     function  GetFirstFreeFCBsPos: Byte;
  436.     function  ReadFAT: Boolean;
  437.     function  HasDrive12bitFAT: Boolean;
  438.     function  Convert12BitFATToWord(FATBuf: Pointer; FATIndex: Word): Word;
  439.     procedure CopyASectorToDTA(var _ASector; Count: Word);
  440.     procedure BringDecedXByte(var Buf; SegBuf, OfsBuf, WithX: Word; SizeOfBuf: Integer);
  441.     procedure ConvertStringToChar13(S: String; var CArray: TChar13);
  442.     procedure ConvertStringToChar11(S: String; var CArray: TChar11);
  443.   end;
  444.  
  445. const
  446.  
  447.   SeekFrom_Start      = 0;
  448.   SeekFrom_CurFilePos = 1;
  449.   SeekFrom_End        = 2;
  450.  
  451.   Cluster12_FREE = $0000;
  452.   Cluster12_RES  = $0FF0; {RESERVED}
  453.   Cluster12_RES2 = $0FF1; {RESERVED}
  454.   Cluster12_RES3 = $0FF2; {RESERVED}
  455.   Cluster12_RES4 = $0FF3; {RESERVED}
  456.   Cluster12_RES5 = $0FF4; {RESERVED}
  457.   Cluster12_RES6 = $0FF5; {RESERVED}
  458.   Cluster12_RES7 = $0FF6; {RESERVED}
  459.   Cluster12_BAD  = $0FF7;
  460.   Cluster12_EOF  = $0FF8;
  461.   Cluster12_EOF2 = $0FF9;
  462.   Cluster12_EOF3 = $0FFA;
  463.   Cluster12_EOF4 = $0FFB;
  464.   Cluster12_EOF5 = $0FFC;
  465.   Cluster12_EOF6 = $0FFD;
  466.   Cluster12_EOF7 = $0FFE;
  467.   Cluster12_EOF8 = $0FFF;
  468.  
  469.   Cluster16_FREE = $0000;
  470.   Cluster16_RES  = $FFF0; {RESERVED}
  471.   Cluster16_RES2 = $FFF1; {RESERVED}
  472.   Cluster16_RES3 = $FFF2; {RESERVED}
  473.   Cluster16_RES4 = $FFF3; {RESERVED}
  474.   Cluster16_RES5 = $FFF4; {RESERVED}
  475.   Cluster16_RES6 = $FFF5; {RESERVED}
  476.   Cluster16_RES7 = $FFF6; {RESERVED}
  477.   Cluster16_BAD  = $FFF7;
  478.   Cluster16_EOF  = $FFF8;
  479.   Cluster16_EOF2 = $FFF9;
  480.   Cluster16_EOF3 = $FFFA;
  481.   Cluster16_EOF4 = $FFFB;
  482.   Cluster16_EOF5 = $FFFC;
  483.   Cluster16_EOF6 = $FFFD;
  484.   Cluster16_EOF7 = $FFFE;
  485.   Cluster16_EOF8 = $FFFF;
  486.  
  487.   {Original DOS Error}
  488.   R4sFDOS_NoError               = $00; {ConvertExtErrCodeToString}
  489.   R4sFDOS_FunctionNumberInvalid = $01;
  490.   R4sFDOS_FileNotFound          = $02;
  491.   R4sFDOS_PathNotFound          = $03;
  492.   R4sFDOS_TooManyOpenFiles      = $04;
  493.   R4sFDOS_AccessDenied          = $05;
  494.   R4sFDOS_InvalidHandle         = $06;
  495.   R4sFDOS_FormatInvalid         = $0B;
  496.   R4sFDOS_AccessCodeInvalid     = $0C;
  497.   R4sFDOS_DataInvalid           = $0D;
  498.   R4sFDOS_InvalidDrive          = $0F;
  499.   R4sFDOS_AttemptedToRemoveCurrentDirectory = $10;
  500.   R4sFDOS_NoMoreFiles           = $12;
  501.   R4sFDOS_DiskWrite_Protected   = $13;
  502.   R4sFDOS_UnknownUnit           = $14;
  503.   R4sFDOS_DriveNotReady         = $15;
  504.   R4sFDOS_UnknownCommand        = $16;
  505.   R4sFDOS_DataError_CRC         = $17;
  506.   R4sFDOS_BadRequestStructureLength = $18;
  507.   R4sFDOS_SeekError             = $19;
  508.   R4sFDOS_UnknownMediaType      = $1A;
  509.   R4sFDOS_SectorNotFound        = $1B;
  510.   R4sFDOS_WriteFault            = $1D;
  511.   R4sFDOS_ReadFault             = $1E;
  512.   R4sFDOS_GeneralFailure        = $1F;
  513.   R4sFDOS_SharingViolation      = $20;
  514.   R4sFDOS_LockViolation         = $21;
  515.   R4sFDOS_DiskChangeInvalid     = $22;
  516.   R4sFDOS_FCBUnavailable        = $23;
  517.   R4sFDOS_SharingBufferOverflow = $24;
  518.   R4sFDOS_InsufficientDiskSpace = $27;
  519.   R4sFDOS_FileExists            = $50;
  520.   R4sFDOS_CannotMakeDirectory   = $52;
  521.   {R4sFileDOS Enhanced Error Codes}
  522.   R4sFDOS_EOF                   = $53;
  523.   R4sFDOS_FATToBig              = $54;
  524.   R4sFDOS_Unknown               = $FF;
  525.  
  526.   NoAttr    = $00;
  527.   ReadOnly  = $01;
  528.   Hidden    = $02;
  529.   SysFile   = $04;
  530.   VolumeID  = $08;
  531.   Directory = $10;
  532.   Archive   = $20;
  533.   AnyFile   = $3F;
  534.  
  535. IMPLEMENTATION
  536. uses R4s_Init, DOS, CRC, R4s_Str, R4s_Conv, R4s_MEMF;
  537.  
  538. {TAbstractDrive}
  539. constructor TAbstractDrive.Init(ADrive: Byte);
  540. begin
  541.   {Inherited Init;} {OFF: Because it fill himself with 0}
  542. end;
  543.  
  544. destructor  TAbstractDrive.Done;
  545. begin
  546.   Abstract;
  547. end;
  548.  
  549. function  TAbstractDrive.ResetDisk(ADrive: Byte): Byte;
  550. begin
  551.   Abstract;
  552. end;
  553.  
  554. function  TAbstractDrive.GetStatusOfLastOperation(ADrive: Byte): Byte;
  555. begin
  556.   GetStatusOfLastOperation:=LastStatus;
  557. end;
  558.  
  559. function  TAbstractDrive.ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  560.                SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean;
  561. begin
  562.   Abstract;
  563. end;
  564.  
  565. function  TAbstractDrive.WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  566.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean;
  567. begin
  568.   Abstract;
  569. end;
  570.  
  571. function  TAbstractDrive.VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  572.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean;
  573. begin
  574.   Abstract;
  575. end;
  576.  
  577. function  TAbstractDrive.ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  578.             var Status, ReadedSecCount: Byte): Boolean;
  579. begin
  580.   Abstract;
  581. end;
  582.  
  583. procedure TAbstractDrive.GetDriveDatas(var AFATStart, AFATSize, ARootStart, ARootSize, ADataStart: Word; 
  584.               var AMaxEntryPerSec: Byte; var ABootInf: TBootSecInforms);
  585. begin
  586.   AFATStart:=FATStart;
  587.   AFATSize:=FATSize;
  588.   ARootStart:=RootStart;
  589.   ARootSize:=RootSize;
  590.   ADataStart:=DataStart;
  591.   AMaxEntryPerSec:=MaxEntryPerSec;
  592.   ABootInf:=BootInf;
  593. end;
  594.  
  595. function  TAbstractDrive.GetDriveNumber: Byte;
  596. begin
  597.   GetDriveNumber:=Drive;
  598. end;
  599.  
  600. {TPhisicalDrive}
  601. constructor TPhisicalDrive.Init(ADrive: Byte);
  602. var Status, Readed: Byte;
  603. begin
  604.   Inherited Init(ADrive);
  605.   Drive:=ADrive;
  606.   for Readed:=0 to 4 do if ResetDisk(Drive) = 0 then Break;
  607.   ReadSectorsIntoMemory(BootInf, Drive, 0, 0, 1, 2, Status, Readed);
  608.   with BootInf do
  609.   begin
  610.     FATStart:=ReservedSecs;
  611.     FATSize:=FATCount * SectorInOneFAT;
  612.     RootStart:=FATStart + FATSize;
  613.     RootSize:=(MaxRootEntries * 32) div Byte_Sector;
  614.     DataStart:=RootStart + RootSize;
  615.     MaxEntryPerSec:=(Sector_Cluster * Byte_Sector) div $20;  {20h = 32 = AEntry Size}
  616.  
  617.     if IsXMSDriverInstalled
  618.     then if Total_Sector * Byte_Sector < (GetTotalExtendedMemorySize* 1024)+(64*1024)
  619.          then UseXMSCache:=True
  620.          else UseXMSCache:=False
  621.     else UseXMSCache:=False;
  622.  
  623.   end;
  624.  
  625.   {
  626.     IsSectorIn,
  627.     IsSectorModified: PBooleanArray;
  628.     XMSCache        : PXMSStream;
  629.   }
  630. end;
  631.  
  632. destructor  TPhisicalDrive.Done;
  633. begin
  634. end;
  635.  
  636. function  TPhisicalDrive.ResetDisk(ADrive: Byte): Byte; Assembler;
  637. asm
  638.   xor  ah, ah
  639.   mov  dl, ADrive
  640.   and  al, 01111111b
  641.   int  13h
  642.   mov  al, ah
  643. end;
  644.  
  645. function  TPhisicalDrive.ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  646.             SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean; Assembler;
  647. asm
  648.   push es
  649.   push di
  650.  
  651.   cmp  SecCount, 00h
  652.   jne  @Cont
  653.   mov  ah, 0FFh
  654.   xor  al, al
  655.   jmp  @Error
  656.  
  657. @Cont:
  658.   mov  ax, Track  {CylNum -> ax (ah, al)}
  659.   shl  ah, 6      {xxxx xxBB -> BBxx xxxx}
  660.   mov  bl, Sector {SecNum -> bl}
  661.   shl  bl, 2      {xxBB BBBB -> BBBB BB00}
  662.   shr  bl, 2      {BBBB BB00 -> 00BB BBBB}
  663.   add  ah, bl     {ah -> ah felsô két bit  és  bl alsô 6 bit}
  664.   xchg al, ah     {ah, al között csere}
  665.   mov  cx, ax   
  666.  
  667.   mov  ah, 02h
  668.   mov  al, SecCount
  669.   mov  dh, Head
  670.   mov  dl, ADrive
  671.   les  bx, [Buf]
  672.   int  13h
  673.   jc   @Error
  674.  
  675.   les  di, Self
  676.   mov  Byte Ptr es:[di].TPhisicalDrive.LastStatus, ah
  677.   mov  Byte Ptr es:[di].TPhisicalDrive.CF, False
  678.   les  di, Status
  679.   mov  Byte Ptr es:[di], ah
  680.   les  di, ReadedSecCount
  681.   mov  Byte Ptr es:[di], al 
  682.  
  683.   mov  al, True
  684.   jmp  @Exit
  685.  
  686. @Error:
  687.   les  di, Self
  688.   mov  Byte Ptr es:[di].TPhisicalDrive.LastStatus, ah
  689.   mov  Byte Ptr es:[di].TPhisicalDrive.CF, True
  690.   les  di, Status
  691.   mov  Byte Ptr es:[di], ah
  692.   les  di, ReadedSecCount
  693.   mov  Byte Ptr es:[di], al 
  694.   mov  al, False
  695. @Exit:
  696.   pop  di
  697.   pop  es
  698. end;
  699.  
  700. function  TPhisicalDrive.WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  701.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean;
  702. begin
  703. end;
  704.  
  705. function  TPhisicalDrive.VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  706.                SecToVerify: Byte; var Status, SecVerified: Byte): Boolean;
  707. begin
  708. end;
  709.  
  710. function  TPhisicalDrive.ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  711.             var Status, ReadedSecCount: Byte): Boolean;
  712. var
  713.   Track : Word;
  714.   Sector,
  715.   Head : Byte;
  716. begin
  717.   Sector:=Byte(((StartSec) mod BootInf.Sector_Track)+1);
  718.   Track:=Word(((StartSec) div BootInf.Sector_Track) div BootInf.Head_Number);
  719.   if ADrive > $7F then Head:=Byte(((((StartSec) div BootInf.Sector_Track) mod BootInf.Head_Number))+1) {HDD}
  720.                   else Head:=Byte((((StartSec) div BootInf.Sector_Track) mod BootInf.Head_Number));    {FDD}
  721.   ReadLogicalSectorIntoMemory:=ReadSectorsIntoMemory(Buf, ADrive, Head, Track, 
  722.     Sector, SecCount, Status, ReadedSecCount);
  723. end;
  724.  
  725. {TImageDrive}
  726. constructor TImageDrive.Init(ADrive: String);
  727. var 
  728.   TempW: Word;
  729.   Status, Readed: Byte;
  730. begin
  731.   Inherited Init(0);
  732.   DriveStr:=ADrive;
  733.   Assign(ImageFile, DriveStr);
  734.   GetFAttr(ImageFile, TempW);
  735.   IsWriteProtected:=(TempW and ReadOnly) <> 0;
  736.   if (TempW and ReadOnly) <> 0 then FileMode:=0;
  737.   {$I-}
  738.   Reset(ImageFile, GetBytePERSector);
  739.   {$I+}
  740.   if IOResult <> 0 then RunError($5); {File Not Found!}
  741.   if (TempW and ReadOnly) <> 0 then FileMode:=2;
  742.  
  743.   Drive:=0;
  744.   ResetDisk(Drive);
  745.   ReadSectorsIntoMemory(BootInf, Drive, 0, 0, 1, 2, Status, Readed);
  746.   with BootInf do
  747.   begin
  748.     FATStart:=ReservedSecs;
  749.     FATSize:=FATCount * SectorInOneFAT;
  750.     RootStart:=FATStart + FATSize;
  751.     RootSize:=(MaxRootEntries * 32) div Byte_Sector;
  752.     DataStart:=RootStart + RootSize;
  753.     MaxEntryPerSec:=(Sector_Cluster * Byte_Sector) div $20;  {20h = 32 = AEntry Size}
  754.   end;                  
  755. end;
  756.  
  757. destructor  TImageDrive.Done;
  758. begin
  759.   Close(ImageFile);
  760. end;
  761.  
  762. function  TImageDrive.ResetDisk(ADrive: Byte): Byte;
  763. begin
  764.   Seek(ImageFile, 0);
  765.   if IOResult = 0 then ResetDisk:=0
  766.                   else ResetDisk:=$80;
  767. end;
  768.  
  769. function  TImageDrive.ReadSectorsIntoMemory(var Buf; ADrive, Head: Byte; Track: Word; 
  770.             Sector, SecCount: Byte; var Status, ReadedSecCount: Byte): Boolean;
  771. var LogicalSec: Longint;
  772. begin
  773.   LogicalSec:= Track * BootInf.Head_Number * BootInf.Sector_Track + Head * BootInf.Sector_Track + Sector - 1;
  774.   ReadSectorsIntoMemory:=ReadLogicalSectorIntoMemory(Buf, ADrive, LogicalSec, SecCount, Status, ReadedSecCount);
  775. end;
  776.  
  777. function  TImageDrive.WriteSectors(var Buf; ADrive, Head: Byte; Track: Word; Sector, 
  778.                SecToWrite: Byte; var Status, SecWrited: Byte): Boolean;
  779. var 
  780.   TempWord  : Word;
  781.   LogicalSec: Longint;
  782. begin
  783.   if IsWriteProtected 
  784.   then begin Status:=$03; SecWrited:=0; WriteSectors:=False; end
  785.   else begin
  786.          LogicalSec:= Track * BootInf.Head_Number * BootInf.Sector_Track + Head * BootInf.Sector_Track + Sector - 1;
  787.          Seek(ImageFile, LogicalSec);
  788.          BlockWrite(ImageFile, Buf, SecToWrite, TempWord);
  789.          if IOResult = 0 then Status:=0
  790.                          else Status:=$80;
  791.          SecWrited:=Byte(TempWord);  
  792.          WriteSectors:= IOResult = 0;
  793.        end;
  794. end;
  795.  
  796. function  TImageDrive.VerifySectors(var Buf; ADrive, Head: Byte; Track: Word; 
  797.             Sector, SecToVerify: Byte; var Status, SecVerified: Byte): Boolean;
  798. begin
  799.   VerifySectors:=ReadSectorsIntoMemory(Buf, ADrive, Head, Track, Sector, 
  800.     SecToVerify, Status, SecVerified);
  801. end;
  802.  
  803. function  TImageDrive.ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte;
  804.                 var Status, ReadedSecCount: Byte): Boolean;
  805. var TempWord: Word;
  806. begin
  807.   Seek(ImageFile, StartSec);
  808.   BlockRead(ImageFile, Buf, SecCount, TempWord);
  809.   if IOResult = 0 then Status:=0
  810.                   else Status:=$80;
  811.   ReadedSecCount:=Byte(TempWord);  
  812.   ReadLogicalSectorIntoMemory:= IOResult = 0;
  813. end;
  814.  
  815. function  TImageDrive.SetWriteProtect(On: Boolean): Boolean;
  816. var Attr: Word;
  817. begin
  818.   GetFAttr(ImageFile, Attr); 
  819.   if On then Attr:=Attr or ReadOnly
  820.         else Attr:=Attr and Not ReadOnly;
  821.   if IOResult = 0 then begin 
  822.                          SetFAttr(ImageFile, Attr);
  823.                          if IOResult = 0 then SetWriteProtect:=True
  824.                                          else SetWriteProtect:=False;
  825.                        end
  826.                   else SetWriteProtect:=False;
  827. end;
  828.  
  829. function  TImageDrive.GetBytePERSector: Word;
  830. var 
  831.   F   : File;
  832.   BInf: TBootSecInforms;
  833.   W   : Word;
  834. begin
  835.   Assign(F, DriveStr);
  836.   {$I-}
  837.   Reset(F, 1024);
  838.   if IOResult <> 0 then begin GetBytePERSector:=512; Exit; end; {Structureless!!!}
  839.   {$I+}
  840.   BlockRead(F, BInf, 1, W);
  841.   if W = 1 then GetBytePERSector:=BInf.Byte_Sector
  842.            else GetBytePERSector:=512;
  843.   Close(F);
  844. end;
  845.  
  846. {PUBLIC Original DOS functions}
  847. constructor TR4sFileDOS.Init(ADriveObj: PAbstractDrive);
  848. var Mem, Disk: Longint;
  849. begin
  850.   New(FAT);
  851.  
  852.   DriveObj:=ADriveObj;
  853.   DriveNum:=ADriveObj^.GetDriveNumber;
  854.  
  855.   SelectDefaultDrive(TheDrive);
  856.   if Error <> 0 then begin Error:=R4sFDOS_DriveNotReady; Fail; end;
  857.   Is12bitFAT:=HasDrive12bitFAT;
  858.   SetDTA(Ptr(PrefixSeg, $80));
  859. end;
  860.  
  861. destructor  TR4sFileDOS.Done;
  862. begin
  863.   ClearAllLocalVariable;
  864.   Dispose(FAT);
  865.   DriveObj^.Done;
  866.   Inherited Done;
  867. end;
  868.  
  869. procedure TR4sFileDOS.SelectDefaultDrive(DriveImageFile: String);
  870. var
  871.   TempW: Word;
  872.   TempB: Boolean;
  873. begin
  874. {  if ExistFile(DriveImageFile) then {Because of read before exists ?!!!}
  875. {  begin}
  876. (*    TheDrive:=DriveImageFile;
  877.     TempW:=GetSectorPerByteInADriveImage(TheDrive);
  878.     {$I-} Assign(DriveImage, TheDrive);
  879.     Reset(DriveImage, TempW);  {$I+}*)
  880.     ClearAllLocalVariable;
  881.     DriveObj^.GetDriveDatas(FATStart, FATSize, RootStart, RootSize, 
  882.                             DataStart, MaxEntryPerSec, BootInf);
  883.  
  884.     CurDIR.Sector:=RootStart; {ConvertClusterNumberToLogicalSector(8);}
  885.     CurDIR.Path:=':\';
  886.     if IOResult <> 0 then Error:=R4sFDOS_DriveNotReady
  887.                      else if Not ReadFAT then Error:=R4sFDOS_FATToBig;
  888.   {end                          else Error:=R4sFDOS_DriveNotReady;}
  889. end;
  890.  
  891. function  TR4sFileDOS.OpenFileByFCB(var FCB: TFCB): Boolean;
  892. var
  893.   TempB             : Byte;
  894.   TempW, Sector     : Word;
  895.   Found, End_It     : Boolean;
  896.   TempSec, TempEntry: Word;
  897. begin
  898.   Found:=False; End_It:=False;
  899.   for Sector:=CurDIR.Sector to BootInf.Total_Sector do
  900.   begin  
  901.     ReadLogicalSector(Longint(Sector));
  902.     for TempW:=0 to MaxEntryPerSec-1 do
  903.     begin
  904.       CopyBufToDirEntry(ASector, TempW, AEntry); {copy the TempW-th entry    }
  905.       if IsNULLEntry(AEntry) then                {from ASector to AEntry var.}
  906.                                   begin          {exit if no more}
  907.                                 End_It:=True;
  908.                                     Break;
  909.                                   end;
  910.  
  911.       if IsEntryASimpleFile(AEntry) and (AEntry.FileName <> '') and (AEntry.FileName[1] <> #0) then
  912.         if (AEntry.FileName = FCB.FileName) and (AEntry.Extension = FCB.FileExt)
  913.         then begin Found:=True; TempSec:=Sector; TempEntry:=TempW; Break; end;
  914.     end; {Next TempW}
  915.     if Found or End_It then Break;
  916.   end; {Next Sector}
  917.   if Found then
  918.   begin
  919.     with FCB do
  920.     begin
  921.       FileSize:=AEntry.FileSize;
  922.       FileTime:=AEntry.Time;
  923.       FileDate:=AEntry.Date;
  924.       StartCluster:=AEntry.ClusterNumber;
  925.       Attribute:=AEntry.Attribute;
  926.       DirEntrypSec:=TempW;
  927.       SectorNumber:=TempSec;
  928.     end;
  929.     TempB:=GetFirstFreeFCBsPos;
  930.     if TempB <> 255 then begin FCB.R4sFCBsPos:=TempB; FCBs[TempB]:=Addr(FCB) end
  931.                     else Error:=R4sFDOS_TooManyOpenFiles;
  932.   end      else OpenFileByFCB:=False;
  933. end;
  934.  
  935. function  TR4sFileDOS.CloseFileByFCB(var FCB: TFCB): Boolean;
  936. begin
  937.   FCBs[FCB.R4sFCBsPos]:=nil;
  938.   FillChar(FCB, SizeOf(FCB), 0);
  939.   CloseFileByFCB:=True;
  940. end;
  941.  
  942. function  TR4sFileDOS.FindFirstByFCB(FCB: TFCB): Boolean;
  943. begin
  944. end;
  945.  
  946. function  TR4sFileDOS.FindNextByFCB(FCB: TFCB): Boolean;
  947. begin
  948. end;
  949.  
  950. function  TR4sFileDOS.DeleteFileByFCB(FCB: TFCB): Boolean;
  951. begin
  952.   {σ = #229 & Fill FAT with 000h}
  953. end;
  954.  
  955. function  TR4sFileDOS.SeqReadByFCB(var FCB: TFCB): Boolean;
  956. var
  957.   Cluster, ReadCluster, TempW, ToCopy, i, ToX: Word;
  958.   W, W0, W1, W2, W3 : Word;
  959. begin
  960.   if (FCB.CurrBlockNum * 128) + (FCB.LogicalRecSize * FCB.RecordInCurBlk) < FCB.FileSize then
  961.   begin
  962.     ReadCluster:=FCB.StartCluster;
  963.     W0:=FCB.LogicalRecSize;
  964.     W1:=Word(FCB.RecordInCurBlk);
  965.     W2:=Word(BootInf.Byte_Sector);
  966.     W3:=Word(FCB.CurrBlockNum * 128);
  967.     ToX:=Word((Word((W0 * W1) div W2)) + W3);
  968.     for Cluster:=1 to ToX do
  969.       ReadCluster:=Convert12BitFATToWord(FAT, ReadCluster);
  970.     TempW:=ConvertClusterNumberToLogicalSector(ReadCluster);
  971.     if ReadLogicalSector(TempW) then
  972.     begin
  973.       if (FCB.LogicalRecSize mod BootInf.Byte_Sector) <> 0 then
  974.       begin
  975.         W:=(FCB.LogicalRecSize * FCB.RecordInCurBlk) mod BootInf.Byte_Sector;
  976.         MoveMemXByteToBuffer(DTA^, Seg(ASector), Ofs(ASector)+W, FCB.LogicalRecSize);
  977.       end                                                  else
  978.         CopyASectorToDTA(ASector, FCB.LogicalRecSize);
  979.       if FCB.RecordInCurBlk = 127 then begin
  980.                                          Inc(FCB.CurrBlockNum);
  981.                                          FCB.RecordInCurBlk:=0;
  982.                                        end
  983.                                   else Inc(FCB.RecordInCurBlk);
  984.     end                         else begin SeqReadByFCB:=False; Error:=R4sFDOS_DriveNotReady end;
  985.   end else begin SeqReadByFCB:=False; Error:=R4sFDOS_EOF; end;
  986. end;
  987.  
  988. function  TR4sFileDOS.SeqWriteByFCB(FCB: TFCB): Boolean;
  989. begin
  990. end;
  991.  
  992. function  TR4sFileDOS.CreateFileByFCB(FCB: TFCB): Boolean;
  993. begin
  994. end;
  995.  
  996. function  TR4sFileDOS.RenameFileByFCB(RFCB: TRFCB): Boolean;
  997. begin
  998. end;
  999.  
  1000. function  TR4sFileDOS.GetCurrentDrive: String;
  1001. begin
  1002.   GetCurrentDrive:=TheDrive;
  1003. end;
  1004.  
  1005. procedure TR4sFileDOS.SetDTA(Address: Pointer);
  1006. begin
  1007.   DTA:=Address;
  1008. end;
  1009.  
  1010. procedure TR4sFileDOS.GetAllocationInformationForDefDrive(var SecClus: Byte; var ByteSec: Word; var TotClus: Word;
  1011.             var MediaID: Byte);
  1012. begin
  1013. end;
  1014.  
  1015. function  TR4sFileDOS.GetDPBForDefDrive: PDriveParameterBlock;
  1016. begin
  1017. end;
  1018.  
  1019. function  TR4sFileDOS.ReadRandomRecByFCB(FCB: TFCB): Boolean;
  1020. begin
  1021. end;
  1022.  
  1023. function  TR4sFileDOS.WriteRandomRecByFCB(FCB: TFCB): Boolean;
  1024. begin
  1025. end;
  1026.  
  1027. function  TR4sFileDOS.GetFileSizeByFCB(var FCB: TFCB): Boolean;
  1028. begin
  1029. end;
  1030.  
  1031. procedure TR4sFileDOS.SetRandomRecNumbForFCB(var FCB: TFCB);
  1032. begin
  1033. end;
  1034.  
  1035. function  TR4sFileDOS.RandomBlockReadByFCB(var NumbRecToRead: Word; var FCB: TFCB): Boolean;
  1036. begin
  1037.  
  1038. end;
  1039.  
  1040. function  TR4sFileDOS.RandomBlockWriteByFCB(var NumbRecToRead: Word; var FCB: TFCB): Boolean;
  1041. begin
  1042. end;
  1043.  
  1044. function  TR4sFileDOS.PraseFileNameToFCB(var FCB: TFCB; Str: String; var UnPrasedPos: Byte): Boolean;
  1045. begin
  1046. end;
  1047.  
  1048. function  TR4sFileDOS.GetDTA: Pointer;
  1049. begin
  1050.   GetDTA:=DTA;
  1051. end;
  1052.  
  1053. function  TR4sFileDOS.GetFreeDiskSpace(Drive: String; var SecClus, FreeClus, ByteClus, TotalClus: Word): Boolean;
  1054. begin
  1055. end;
  1056.  
  1057. function  TR4sFileDOS.MkDIR(Name: TASCIIZ): Boolean;
  1058. begin
  1059. end;
  1060.  
  1061. function  TR4sFileDOS.RmDIR(Name: TASCIIZ): Boolean;
  1062. begin
  1063. end;
  1064.  
  1065. function  TR4sFileDOS.ChDIR(Name: TASCIIZ): Boolean;
  1066. var 
  1067.   Sector: Longint;
  1068.   Path  : String;
  1069. begin
  1070.   if GetSectorOfDirectory(Name, Sector, Path) {NEW construction: GetDIRsSector removed there}
  1071.   then begin
  1072.          ChDIR:=True;
  1073.          CurDIR.Sector:=Sector;
  1074.          CurDIR.Path:=Path;
  1075.        end
  1076.   else ChDIR:=False;
  1077. end;
  1078.  
  1079. function  TR4sFileDOS.CreatFile(Name: TASCIIZ; Attributes: Word; var Handle: Word): Boolean;
  1080. begin
  1081. end;
  1082.  
  1083. function  TR4sFileDOS.OpenFile(Name: TASCIIZ; AccessMode: Byte; var Handle: Word): Boolean;
  1084.  
  1085.    function  GetFirstFreeHandle: Word;
  1086.    var i: Word;
  1087.    begin
  1088.      for i:=6 to 55 do
  1089.        if Not IsUsedHandle[i] then begin GetFirstFreeHandle:=i; Break; end;
  1090.    end;                              
  1091.  
  1092. var 
  1093.   FFDataBlock: PFindFileDataType;
  1094.   NameS      : String;
  1095.  
  1096. begin {first handle 0006h; AccessMode = FileMode} 
  1097.   if FindFirstFile(Name, AnyFile and ((Not Directory) and (Not VolumeID)))
  1098.   then begin
  1099.          NameS:=ConvertASCIIZToString(Name); NameS:=UCaseString(UTrim(NameS)); FFDataBlock:=DTA;
  1100.          FFDataBlock:=DTA;
  1101.          if NameS[2] = ':' then Delete(NameS, 1, 2);
  1102.          repeat
  1103.            Delete(NameS, Length(NameS), 1);
  1104.          until NameS[Length(NameS)] = '\';
  1105.          if Length(NameS) > 2 then Delete(NameS, Length(NameS), 1);
  1106.          NameS:=Slasher(NameS) + FFDataBlock^.FileName;
  1107.          repeat
  1108.            Delete(NameS, Length(NameS), 1);
  1109.          until NameS[Length(NameS)] <> #0;
  1110.          Handle:=GetFirstFreeHandle;
  1111.          Handles[Handle].Path:=NameS;
  1112.          Handles[Handle].Entry:=AEntry;
  1113.          Handles[Handle].Position:=0;
  1114.          Handles[Handle].OwnerDIR:=FFDataBlock^.OwnerDIRStartClus;
  1115.          IsUsedHandle[Handle]:=True;
  1116.          OpenFile:=True;
  1117.        end
  1118.   else begin
  1119.          Handle:=0;
  1120.          OpenFile:=False;
  1121.        end;
  1122. end;
  1123.  
  1124. function  TR4sFileDOS.CloseFile(Handle: Word): Boolean;
  1125. begin
  1126.   if IsUsedHandle[Handle] 
  1127.   then begin
  1128.          IsUsedHandle[Handle]:=False;
  1129.          FillChar(Handles[Handle], SizeOf(Handles[Handle]), 0);
  1130.          CloseFile:=True;
  1131.        end
  1132.   else begin Error:=R4sFDOS_InvalidHandle; CloseFile:=False; end;
  1133. end;
  1134.  
  1135. function  TR4sFileDOS.ReadFromFile(Handle: Word; var ByteToRead: Word; var Buf; BufSize: Word): Boolean;
  1136. var
  1137.   i, PosInBuf, MustRead   : Word;
  1138.   OK, NotINC, NeedLocalBuf, ErrProc, WasPosZero: Boolean;
  1139.   ToBuf, TempP            : Pointer;
  1140.   LocalBuf                : PBuffer4k;
  1141.   PosDiv, PosMod, StartCluster, Cluster, MaxCluster, ClusToRead, Res, TempW: Word;  
  1142.     
  1143. begin  
  1144.   if IsUsedHandle[Handle] then
  1145.   begin
  1146.     ErrProc:=False;
  1147.     if BufSize < 4096 then NeedLocalBuf:=True
  1148.                       else NeedLocalBuf:=False;
  1149.     if BufSize < ByteToRead then begin ByteToRead:=BufSize; ErrProc:=True; end;
  1150.     if NeedLocalBuf then begin 
  1151.                            New(LocalBuf);
  1152.                            FillChar(LocalBuf^, SizeOf(LocalBuf^), 0); 
  1153.                            ToBuf:=LocalBuf;
  1154.                          end
  1155.                     else begin
  1156.                            FillChar(Buf, BufSize, 0);
  1157.                            ToBuf:=@Buf;
  1158.                          end;
  1159.     MustRead:=ByteToRead; WasPosZero:=False;
  1160.     if (Handles[Handle].Position <> 0) or Handles[Handle].PosZero then
  1161.     begin
  1162.       if Handles[Handle].PosZero then begin 
  1163.                                         Handles[Handle].PosZero:=False;
  1164.                                         WasPosZero:=True;
  1165.                                       end;
  1166.       PosDiv:=(Handles[Handle].Position + 1) div (BootInf.Byte_Sector * BootInf.Sector_Cluster);
  1167.       PosMod:=(Handles[Handle].Position + 1) mod (BootInf.Byte_Sector * BootInf.Sector_Cluster);
  1168.     end                              else begin PosDiv:=0; PosMod:=0; end;
  1169.     {PosDiv, and PosMod are Cluster "orianteted" variables}
  1170.     MaxCluster:=(Handles[Handle].Entry.FileSize div (BootInf.Byte_Sector * BootInf.Sector_Cluster));
  1171.     if Handles[Handle].Entry.FileSize mod (BootInf.Byte_Sector * BootInf.Sector_Cluster) <> 0 then Inc(MaxCluster);
  1172.  
  1173.     Cluster:=Handles[Handle].Entry.ClusterNumber;
  1174.     if PosDiv <> 0 then
  1175.       for i:=Handles[Handle].Entry.ClusterNumber to Handles[Handle].Entry.ClusterNumber+PosDiv-1 do
  1176.         Cluster:=GetIndexFromFAT(FAT, Cluster);
  1177.  
  1178.     {Cluster:=PosDiv + Handles[Handle].Entry.ClusterNumber;} {BAD !!! = 32 lastreaded + startoffile, it doesn't work with FAT}
  1179.     OK:=False; Res:=0;
  1180.     repeat
  1181.       ClusToRead:=0;
  1182.       StartCluster:=Cluster;
  1183.       repeat      
  1184.         Inc(ClusToRead);
  1185.         if GetIndexFromFAT(FAT, Cluster) >= Cluster12_EOF then Break;
  1186.         if Longint(ByteToRead) <= Longint( Longint(ClusToRead + Res) * 
  1187.           Longint(BootInf.Byte_Sector) * Longint(BootInf.Sector_Cluster) ) then 
  1188.             Break;
  1189.         NotINC:=False; 
  1190.         if GetIndexFromFAT(FAT, Cluster) = Cluster + 1 then Cluster:=GetIndexFromFAT(FAT, Cluster)
  1191.                                                              else NotINC:=True;
  1192.       until (GetIndexFromFAT(FAT, Cluster) <> Cluster + 1);
  1193.  
  1194.       TempW:=GetIndexFromFAT(FAT, Cluster);
  1195.       if ((TempW >= Cluster12_EOF) or (TempW <> Cluster + 1)) and (Not NotINC) 
  1196.       then Inc(ClusToRead)
  1197.       else NotINC:=False;
  1198.       Res:=Res + ClusToRead;
  1199.       ReadnLogigalSector(ConvertClusterNumberToLogicalSector(StartCluster), ClusToRead, ToBuf);
  1200.       ToBuf:=Ptr(Seg(ToBuf^), Ofs(ToBuf^) + Word(ClusToRead * BootInf.Byte_Sector * BootInf.Sector_Cluster));
  1201.       Cluster:=GetIndexFromFAT(FAT, Cluster);
  1202.     until Longint(ByteToRead) <= Longint( Longint(Res) * 
  1203.       Longint(BootInf.Byte_Sector) * Longint(BootInf.Sector_Cluster) );
  1204.     ByteToRead:=Res * Word(BootInf.Byte_Sector * BootInf.Sector_Cluster);
  1205.     if ByteToRead > MustRead then ByteToRead:=MustRead;    
  1206.     if PosMod <> 0 then
  1207.       if NeedLocalBuf 
  1208.       then BringDecedXByte(LocalBuf^, Seg(LocalBuf^), Ofs(LocalBuf^), Word(PosMod), SizeOf(LocalBuf^))
  1209.       else BringDecedXByte(Buf, Seg(Buf), Ofs(Buf), Word(PosMod), BufSize);
  1210.     if NeedLocalBuf then begin Move(LocalBuf^, Buf, ByteToRead); Dispose(LocalBuf); end;
  1211.     if (Handles[Handle].Position = 0) and (Not Handles[Handle].PosZero) then Handles[Handle].PosZero:=True;
  1212.     if (Handles[Handle].Position = 0) and (Not WasPosZero)
  1213.     then Handles[Handle].Position:=ByteToRead - 1
  1214.     else Handles[Handle].Position:=Handles[Handle].Position + ByteToRead;
  1215.     if ErrProc then ReadFromFile:=False
  1216.                else ReadFromFile:=True;
  1217.   end                     else 
  1218.   begin FillChar(Buf, ByteToRead, 0); ByteToRead:=0; ReadFromFile:=False; end;
  1219. end;
  1220.  
  1221. function  TR4sFileDOS.WriteToFile(Handle: Word; var ByteToWrite: Word; var Buf): Boolean;
  1222. begin
  1223. end;
  1224.  
  1225. function  TR4sFileDOS.DeleteFile(Name: String): Boolean;
  1226. begin
  1227. end;
  1228.  
  1229. {SeekType method code byte
  1230.     00h offset from beginning of file
  1231.     01h offset from present location
  1232.     02h offset from end of file}
  1233. function  TR4sFileDOS.SeekFile(Handle: Word; SeekType: Byte; var Pos: Longint): Boolean;
  1234. begin
  1235.   if IsUsedHandle[Handle] then
  1236.     case SeekType of
  1237.       $00: begin Handles[Handle].Position:=Pos; SeekFile:=True; end;
  1238.       $01: begin Handles[Handle].Position:=Handles[Handle].Position + Pos; SeekFile:=True; end;
  1239.       $02: begin Handles[Handle].Position:=Handles[Handle].Entry.FileSize - Abs(Pos); SeekFile:=True; end;
  1240.       else begin Handles[Handle].Position:=Pos; SeekFile:=True; end;
  1241.     end                   else begin Pos:=0; SeekFile:=False; end;
  1242. end;
  1243.  
  1244. function  TR4sFileDOS.GetFilePos(Handle: Word): Longint;
  1245. begin
  1246.   if IsUsedHandle[Handle] then GetFilePos:=Handles[Handle].Position
  1247.                           else GetFilePos:=$FFFFFFFF; {it means error !}
  1248. end;
  1249.  
  1250. function  TR4sFileDOS.GetFileAttributes(Name: String; var Attributes: Word): Boolean;
  1251. begin
  1252.   {Attributes:=0;
  1253.   Attributes:=Word(Handles[Handle].Entry.Attribute);}
  1254. end;
  1255.  
  1256. function  TR4sFileDOS.SetFileAttributes(Name: String; Attributes: Word): Boolean;
  1257. begin
  1258. end;
  1259.  
  1260. function  TR4sFileDOS.DuplicateFileHandle(Handle: Word; var NewHandle: Word): Boolean;
  1261. begin
  1262. end;
  1263.  
  1264. function  TR4sFileDOS.DuplicateFileHandle2(Handle: Word; var NewHandle: Word): Boolean;
  1265. begin
  1266. end;
  1267.  
  1268. function  TR4sFileDOS.GetCurrentDIR(Drive: Byte; var ASCIIZPath: TASCIIZ): Boolean;
  1269. begin
  1270. end;
  1271.  
  1272.         {További forráskód részletek azon becses Olvasónak akik ennyire
  1273.           érdeklôdnek a téma iránt a PC-XUSER@FREEMAIL.C3.HU-cimre írt
  1274.           meggyôzô levél után adatik meg.
  1275.          Ill. az R4sFDOS könyvtárban van egy ZIP, azt is meglehet nézni,
  1276.           igaz csak TPU.
  1277.                                                                       R4s}
  1278.  
  1279.  
  1280. END.