1 // Streaming R/O Virtual File System v0.2.0
2 // Copyright (C) XL A.S. Ketmar. All rights reserved
3 // See the file aplicense.txt for conditions of use.
5 // simple grouping files w/o packing:
6 // Quake I/II .PAK (PACK)
16 SysUtils
, Classes
, Contnrs
, sfs
;
20 TSFSPlainVolumeType
= (sfspvNone
, sfspvPAK
, sfspvSIN
);
22 TSFSPlainVolume
= class (TSFSVolume
)
24 fType
: TSFSPlainVolumeType
;
26 procedure ReadDirectory (); override;
29 function OpenFileByIndex (const index
: Integer): TStream
; override;
32 TSFSPlainVolumeFactory
= class (TSFSVolumeFactory
)
34 function IsMyVolumePrefix (const prefix
: AnsiString): Boolean; override;
35 function Produce (const prefix
, fileName
: AnsiString; st
: TStream
): TSFSVolume
; override;
36 procedure Recycle (vol
: TSFSVolume
); override;
47 procedure TSFSPlainVolume
.ReadDirectory ();
49 dsize
, dofs
, esz
: LongWord;
51 name
: packed array [0..120] of Char;
53 if (fType
<> sfspvPAK
) and (fType
<> sfspvSIN
) then raise ESFSError
.Create('invalid archive');
54 fFileStream
.Seek(4, soCurrent
); // skip signature
55 fFileStream
.ReadBuffer(dofs
, 4);
56 fFileStream
.ReadBuffer(dsize
, 4);
57 fFileStream
.Position
:= dofs
;
58 if fType
= sfspvPAK
then esz
:= 64 else esz
:= 128;
61 fi
:= TSFSFileInfo
.Create(self
);
62 FillChar(name
[0], length(name
), 0);
63 fFileStream
.ReadBuffer(name
[0], esz
-8);
64 fi
.fName
:= PChar(@name
[0]);
65 fFileStream
.ReadBuffer(fi
.fOfs
, 4);
66 fFileStream
.ReadBuffer(fi
.fSize
, 4);
71 function TSFSPlainVolume
.OpenFileByIndex (const index
: Integer): TStream
;
74 if fFiles
= nil then exit
;
75 if (index
< 0) or (index
>= fFiles
.Count
) or (fFiles
[index
] = nil) then exit
;
76 result
:= TSFSPartialStream
.Create(fFileStream
, TSFSFileInfo(fFiles
[index
]).fOfs
, TSFSFileInfo(fFiles
[index
]).fSize
, false);
80 { TSFSPlainVolumeFactory }
81 function TSFSPlainVolumeFactory
.IsMyVolumePrefix (const prefix
: AnsiString): Boolean;
84 StrEquCI1251(prefix
, 'pak') or
85 StrEquCI1251(prefix
, 'sin');
88 procedure TSFSPlainVolumeFactory
.Recycle (vol
: TSFSVolume
);
93 function TSFSPlainVolumeFactory
.Produce (const prefix
, fileName
: AnsiString; st
: TStream
): TSFSVolume
;
95 vt
: TSFSPlainVolumeType
;
96 sign
: packed array [0..3] of Char;
102 st
.ReadBuffer(sign
[0], 4);
103 st
.ReadBuffer(dofs
, 4);
104 st
.ReadBuffer(dsize
, 4);
105 st
.Seek(-12, soCurrent
);
106 if sign
= 'PACK' then
108 if (dsize
< 0) or (dofs
< 0) or (dofs
> st
.Size
) or (dofs
+dsize
> st
.Size
) or (dsize
mod 64 <> 0) then exit
;
111 else if sign
= 'SPAK' then
113 if (dsize
< 0) or (dofs
< 0) or (dofs
> st
.Size
) or (dofs
+dsize
> st
.Size
) or (dsize
mod 64 <> 0) then exit
;
117 result
:= TSFSPlainVolume
.Create(fileName
, st
);
118 TSFSPlainVolume(result
).fType
:= vt
;
120 result
.DoDirectoryRead();
129 pakf
: TSFSPlainVolumeFactory
;
131 pakf
:= TSFSPlainVolumeFactory
.Create();
132 SFSRegisterVolumeFactory(pakf
);
134 // SFSUnregisterVolumeFactory(pakf);