DEADSOFTWARE

Maps can be saved to zip
[d2df-editor.git] / src / editor / g_resources.pas
1 unit g_resources;
3 interface
5 (**
6 g_ReadResource
7 Read whole file from wad
9 g_ReadSubResource
10 Read whole file from folded wad
12 g_DeleteResource
13 Delete file from wad, res = 0 when ok
15 g_AddResource
16 Add/overwrite file to wad, res = 0 when ok
17 **)
19 procedure g_ReadResource (wad, section, name: String; out data: PByte; out len: Integer);
20 procedure g_ReadSubResource (wad, section0, name0, section1, name1: String; out data: PByte; out len: Integer);
21 procedure g_DeleteResource (wad, section, name: String; out res: Integer);
22 procedure g_AddResource (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
24 implementation
26 uses sfs, xstreams, dfzip, utils, Classes, SysUtils, WADEDITOR;
28 procedure g_AddResourceToDFWAD (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
29 var f: TWADEditor_1;
30 begin
31 res := 1; (* error *)
32 f := TWADEditor_1.Create();
33 if not f.ReadFile(wad) then
34 begin
35 (* do nothing *)
36 end;
37 f.CreateImage;
38 f.RemoveResource(section, name);
39 f.AddResource(data, len, name, section);
40 f.SaveTo(wad);
41 f.Free;
42 res := 0
43 end;
45 procedure g_AddResourceToZip (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
46 var
47 i, n, len0: Integer;
48 data0: PByte;
49 list: TSFSFileList;
50 tmp, entry: String;
51 ts: TFileStream;
52 dir: array of TFileInfo;
54 procedure Add (name: String; data: PByte; len: Integer);
55 var ds: TSFSMemoryChunkStream;
56 begin
57 SetLength(dir, n + 1);
58 ds := TSFSMemoryChunkStream.Create(data, len, false);
59 dir[n] := dfzip.ZipOne(ts, name, ds);
60 ds.Free;
61 INC(n);
62 end;
64 begin
65 res := 1;
66 wad := ExpandFileName(wad);
67 list := SFSFileList(wad);
68 tmp := wad + '.tmp' + IntToStr(Random(100000));
69 ts := TFileStream.Create(tmp, fmCreate);
70 n := 0;
71 SetLength(dir, 0);
72 if list <> nil then
73 begin
74 for i := 0 to list.Count - 1 do
75 begin
76 if (list.Files[i].path <> section) or (list.Files[i].name <> section) then
77 begin
78 g_ReadResource(wad, list.Files[i].path, list.Files[i].name, data0, len0);
79 if list.Files[i].path = '' then
80 entry := list.Files[i].name
81 else
82 entry := list.Files[i].path + '/' + list.Files[i].name;
83 Add(entry, data0, len0);
84 FreeMem(data0)
85 end
86 end;
87 list.Destroy
88 end;
90 if section = '' then
91 entry := name
92 else
93 entry := section + '/' + name;
95 Add(entry, data, len);
96 dfzip.writeCentralDir(ts, dir);
97 ts.Free;
99 if FileExists(wad) then
100 ASSERT(RenameFile(wad, wad + '.bak'));
101 ASSERT(RenameFile(tmp, wad));
102 res := 0
103 end;
105 procedure g_AddResource (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
106 var ext: String;
107 begin
108 res := 2; (* unknown type *)
109 ext := LowerCase(SysUtils.ExtractFileExt(wad));
110 if ext = '.wad' then
111 g_AddResourceToDFWAD(wad, section, name, data, len, res)
112 else if (ext = '.pk3') or (ext = '.zip') or (ext = '.dfzip') then
113 g_AddResourceToZip(wad, section, name, data, len, res)
114 end;
116 procedure g_DeleteResourceFromDFWAD (wad, section, name: String; out res: Integer);
117 var f: TWADEditor_1;
118 begin
119 res := 1; (* error *)
120 f := TWADEditor_1.Create;
121 if not f.ReadFile(wad) then
122 begin
123 f.Free;
124 Exit
125 end;
126 f.CreateImage;
127 f.RemoveResource(section, name);
128 f.SaveTo(wad);
129 f.Free;
130 res := 0 (* ok *)
131 end;
133 procedure g_DeleteResourceFromZip (wad, section, name: String; out res: Integer);
134 begin
135 res := 1 (* not implemented *)
136 end;
138 procedure g_DeleteResource (wad, section, name: String; out res: Integer);
139 var ext: String;
140 begin
141 res := 2; (* unknown type *)
142 ext := LowerCase(SysUtils.ExtractFileExt(wad));
143 if ext = '.wad' then
144 g_DeleteResourceFromDFWAD(wad, section, name, res)
145 else if (ext = '.pk3') or (ext = '.zip') or (ext = '.dfzip') then
146 g_DeleteResourceFromZip(wad, section, name, res)
147 end;
149 procedure g_ReadResource (wad, section, name: String; out data: PByte; out len: Integer);
150 var
151 stream: TStream;
152 str: String;
153 i: Integer;
154 begin
155 section := utf2win(section);
156 name := utf2win(name);
157 data := nil;
158 len := 0;
159 if SFSAddDataFileTemp(wad, TRUE) then
160 begin
161 str := SFSGetLastVirtualName(section + '\' + name);
162 stream := SFSFileOpen(wad + '::' + str);
163 if stream <> nil then
164 begin
165 len := stream.Size;
166 GetMem(data, len);
167 //stream.ReadBuffer(data, len); (* leads to segfault *)
168 for i := 0 to len - 1 do
169 data[i] := stream.ReadByte();
170 stream.Destroy
171 end
172 end;
173 SFSGCCollect
174 end;
176 procedure g_ReadSubResource (wad, section0, name0, section1, name1: String; out data: PByte; out len: Integer);
177 var
178 stream0, stream1: TStream;
179 str0, str1: String;
180 i: Integer;
181 begin
182 data := nil;
183 len := 0;
184 if (wad = '') OR (section0 = '') OR (name0 = '') OR (section1 = '') OR (name1 = '') then Exit;
185 section0 := utf2win(section0);
186 name0 := utf2win(name0);
187 section1 := utf2win(section1);
188 name1 := utf2win(name1);
189 if SFSAddDataFileTemp(wad, TRUE) then
190 begin
191 str0 := SFSGetLastVirtualName(section0 + '\' + name0);
192 stream0 := SFSFileOpen(wad + '::' + str0);
193 if stream0 <> nil then
194 begin
195 if SFSAddSubDataFile(wad + '\' + str0, stream0, TRUE) then
196 begin
197 str1 := SFSGetLastVirtualName(section1 + '\' + name1);
198 stream1 := SFSFileOpen(wad + '\' + str0 + '::' + str1);
199 if stream1 <> nil then
200 begin
201 len := stream1.Size;
202 GetMem(data, len);
203 //stream1.ReadBuffer(data, len); (* leads to segfault *)
204 for i := 0 to len - 1 do
205 data[i] := stream1.ReadByte();
206 stream1.Destroy
207 end
208 end
209 end
210 else
211 begin
212 stream0.Destroy
213 end
214 end;
215 SFSGCCollect
216 end;
218 end.