7 Read whole file from wad
8 (data <> nil) and (len > 0) when ok
9 use FreeMem(data) when done
12 Read whole file from folded wad
13 (data <> nil) and (len > 0) when ok
14 use FreeMem(data) when done
21 Add/overwrite file to wad
25 Check that resource exists
29 procedure g_GetResourceSection (path
: String; out wad
, section
, name
: String);
31 procedure g_ReadResource (wad
, section
, name
: String; out data
: PByte; out len
: Integer);
32 procedure g_ReadSubResource (wad
, section0
, name0
, section1
, name1
: String; out data
: PByte; out len
: Integer);
33 procedure g_DeleteResource (wad
, section
, name
: String; out res
: Integer);
34 procedure g_AddResource (wad
, section
, name
: String; const data
: PByte; len
: Integer; out res
: Integer);
35 procedure g_ExistsResource (wad
, section
, name
: String; out res
: Integer);
39 uses sfs
, xstreams
, dfzip
, utils
, Classes
, SysUtils
, WADEDITOR
, e_log
;
41 function NoTrailing (path
: String): String;
45 while (i
> 0) and ((path
[i
] = '/') or (path
[i
] = '\')) do dec(i
);
46 result
:= Copy(path
, 1, i
)
49 function g_CleanPath (path
: String; sys
: Boolean = False): String;
55 (* drop separators at the end *)
56 while (len
> 1) and ((path
[i
] = '/') or (path
[i
] = '\')) do dec(len
);
59 while (i
<= len
) and (path
[i
] <> '/') and (path
[i
] <> '\') do
61 result
:= result
+ path
[i
];
66 result
:= result
+ DirectorySeparator
68 result
:= result
+ '/';
70 while (i
<= len
) and ((path
[i
] = '/') or (path
[i
] = '\')) do inc(i
)
74 procedure g_GetResourceSection (path
: String; out wad
, section
, name
: String);
75 var i
, j
, len
: Integer;
79 while (i
> 0) and (path
[i
] <> '/') and (path
[i
] <> '\') do dec(i
);
80 name
:= Copy(path
, i
+ 1, len
);
82 while (i
> 0) and (path
[i
] <> ':') do dec(i
);
83 section
:= Copy(path
, i
+ 1, j
- i
- 1);
84 wad
:= Copy(path
, 1, i
- 1);
87 procedure g_AddResourceToDFWAD (wad
, section
, name
: String; const data
: PByte; len
: Integer; out res
: Integer);
92 section
:= utf2win(NoTrailing(section
));
93 name
:= utf2win(name
);
95 f
:= TWADEditor_1
.Create();
96 if not f
.ReadFile(wad
) then
101 f
.RemoveResource(section
, name
);
102 f
.AddResource(data
, len
, name
, section
);
103 if FileExists(wad
) then
105 if FileExists(wad
+ '.bak') then
106 ASSERT(DeleteFile(wad
+ '.bak'));
107 ASSERT(RenameFile(wad
, wad
+ '.bak'))
114 procedure g_AddResourceToZip (wad
, section
, name
: String; const data
: PByte; len
: Integer; out res
: Integer);
121 dir
: array of TFileInfo
;
123 procedure Add (name
: String; data
: PByte; len
: Integer);
124 var ds
: TSFSMemoryChunkStream
;
126 SetLength(dir
, n
+ 1);
127 ds
:= TSFSMemoryChunkStream
.Create(data
, len
, false);
128 dir
[n
] := dfzip
.ZipOne(ts
, name
, ds
);
135 wad
:= ExpandFileName(wad
);
136 section
:= utf2win(NoTrailing(section
));
137 name
:= utf2win(name
);
139 list
:= SFSFileList(wad
);
140 tmp
:= wad
+ '.tmp' + IntToStr(Random(100000));
141 ts
:= TFileStream
.Create(tmp
, fmCreate
);
146 for i
:= 0 to list
.Count
- 1 do
148 path
:= NoTrailing(list
.Files
[i
].path
);
149 if (path
<> section
) or (list
.Files
[i
].name
<> section
) then
151 g_ReadResource(wad
, path
, list
.Files
[i
].name
, data0
, len0
);
152 ASSERT(data0
<> nil);
154 path
:= list
.Files
[i
].name
156 path
:= path
+ '/' + list
.Files
[i
].name
;
157 Add(path
, data0
, len0
);
167 path
:= section
+ '/' + name
;
168 Add(path
, data
, len
);
170 dfzip
.writeCentralDir(ts
, dir
);
173 if FileExists(wad
) then
175 if FileExists(wad
+ '.bak') then
176 ASSERT(DeleteFile(wad
+ '.bak'));
177 ASSERT(RenameFile(wad
, wad
+ '.bak'))
179 ASSERT(RenameFile(tmp
, wad
));
183 procedure g_AddResource (wad
, section
, name
: String; const data
: PByte; len
: Integer; out res
: Integer);
187 res
:= 2; (* unknown type *)
188 ext
:= LowerCase(SysUtils
.ExtractFileExt(wad
));
189 e_WriteLog('g_AddResource "' + wad
+ '" "' + section
+ '" "' + name
+ '"', MSG_NOTIFY
);
191 g_AddResourceToDFWAD(wad
, section
, name
, data
, len
, res
)
192 else if (ext
= '.pk3') or (ext
= '.zip') or (ext
= '.dfzip') then
193 g_AddResourceToZip(wad
, section
, name
, data
, len
, res
)
196 procedure g_DeleteResourceFromDFWAD (wad
, section
, name
: String; out res
: Integer);
200 res
:= 1; (* error *)
201 section
:= utf2win(NoTrailing(section
));
202 name
:= utf2win(name
);
203 f
:= TWADEditor_1
.Create
;
204 if not f
.ReadFile(wad
) then
210 f
.RemoveResource(section
, name
);
216 procedure g_DeleteResourceFromZip (wad
, section
, name
: String; out res
: Integer);
223 dir
: array of TFileInfo
;
225 procedure Add (name
: String; data
: PByte; len
: Integer);
226 var ds
: TSFSMemoryChunkStream
;
228 SetLength(dir
, n
+ 1);
229 ds
:= TSFSMemoryChunkStream
.Create(data
, len
, false);
230 dir
[n
] := dfzip
.ZipOne(ts
, name
, ds
);
237 wad
:= ExpandFileName(wad
);
238 section
:= utf2win(NoTrailing(section
));
239 name
:= utf2win(name
);
241 list
:= SFSFileList(wad
);
242 tmp
:= wad
+ '.tmp' + IntToStr(Random(100000));
243 ts
:= TFileStream
.Create(tmp
, fmCreate
);
248 for i
:= 0 to list
.Count
- 1 do
250 path
:= NoTrailing(list
.Files
[i
].path
);
251 if (path
<> section
) or (list
.Files
[i
].name
<> section
) then
253 g_ReadResource(wad
, path
, list
.Files
[i
].name
, data0
, len0
);
254 ASSERT(data0
<> nil);
256 path
:= list
.Files
[i
].name
258 path
:= path
+ '/' + list
.Files
[i
].name
;
259 Add(path
, data0
, len0
);
266 dfzip
.writeCentralDir(ts
, dir
);
269 if FileExists(wad
) then
271 if FileExists(wad
+ '.bak') then
272 ASSERT(DeleteFile(wad
+ '.bak'));
273 ASSERT(RenameFile(wad
, wad
+ '.bak'))
275 ASSERT(RenameFile(tmp
, wad
));
279 procedure g_DeleteResource (wad
, section
, name
: String; out res
: Integer);
283 res
:= 2; (* unknown type *)
284 ext
:= LowerCase(SysUtils
.ExtractFileExt(wad
));
286 g_DeleteResourceFromDFWAD(wad
, section
, name
, res
)
287 else if (ext
= '.dfz') or (ext
= '.pk3') or (ext
= '.zip') or (ext
= '.dfzip') then
288 g_DeleteResourceFromZip(wad
, section
, name
, res
)
291 procedure g_ExistsResource (wad
, section
, name
: String; out res
: Integer);
292 var str
: String; stream
: TStream
;
295 section
:= utf2win(NoTrailing(section
));
296 name
:= utf2win(name
);
298 if SFSAddDataFileTemp(wad
, TRUE) then
300 str
:= SFSGetLastVirtualName(section
+ '\' + name
);
301 stream
:= SFSFileOpen(wad
+ '::' + str
);
302 if stream
<> nil then
311 procedure g_ReadResource (wad
, section
, name
: String; out data
: PByte; out len
: Integer);
312 var stream
: TStream
; str
: String; i
: Integer;
314 e_WriteLog('g_ReadResource: "' + wad
+ '" "' + section
+ '" "' + name
+ '"', MSG_NOTIFY
);
315 section
:= utf2win(NoTrailing(section
));
316 name
:= utf2win(name
);
319 //ASSERT(name <> '');
320 if name
= '' then Exit
; (* SKY can be void *)
321 if SFSAddDataFileTemp(wad
, TRUE) then
323 str
:= SFSGetLastVirtualName(section
+ '/' + name
);
324 stream
:= SFSFileOpen(wad
+ '::' + str
);
325 if stream
<> nil then
330 //stream.ReadBuffer(data, len); (* leads to segfault *)
331 for i
:= 0 to len
- 1 do
332 data
[i
] := stream
.ReadByte();
339 procedure g_ReadSubResource (wad
, section0
, name0
, section1
, name1
: String; out data
: PByte; out len
: Integer);
340 var stream0
, stream1
: TStream
; str0
, str1
: String; i
: Integer;
344 section0
:= utf2win(NoTrailing(section0
));
345 name0
:= utf2win(name0
);
346 section1
:= utf2win(NoTrailing(section1
));
347 name1
:= utf2win(name1
);
348 //ASSERT(name0 <> '');
349 //ASSERT(name1 <> '');
350 if (wad
= '') OR (name0
= '') OR (name1
= '') then Exit
; (* ??? *)
351 if SFSAddDataFileTemp(wad
, TRUE) then
353 str0
:= SFSGetLastVirtualName(section0
+ '\' + name0
);
354 stream0
:= SFSFileOpen(wad
+ '::' + str0
);
355 if stream0
<> nil then
357 if SFSAddSubDataFile(wad
+ '\' + str0
, stream0
, TRUE) then
359 str1
:= SFSGetLastVirtualName(section1
+ '\' + name1
);
360 stream1
:= SFSFileOpen(wad
+ '\' + str0
+ '::' + str1
);
361 if stream1
<> nil then
366 //stream1.ReadBuffer(data, len); (* leads to segfault *)
367 for i
:= 0 to len
- 1 do
368 data
[i
] := stream1
.ReadByte();