DEADSOFTWARE

de670694b81fe44207506b355c7351b3921ea86c
[d2df-sdl.git] / src / shared / WADEDITOR.pas
1 unit WADEDITOR;
3 {$DEFINE SFS_DWFAD_DEBUG}
5 interface
7 uses
8 sfs, xstreams;
11 type
12 SArray = array of ShortString;
14 TWADEditor_1 = class(TObject)
15 private
16 fFileName: string; // empty: not opened
17 fIter: TSFSFileList;
19 function getIsOpen (): Boolean;
21 public
22 constructor Create();
23 destructor Destroy(); override;
25 procedure FreeWAD();
27 function ReadFile (FileName: string): Boolean;
28 function ReadMemory (Data: Pointer; Len: LongWord): Boolean;
29 function GetResource (Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
30 function GetResourcesList (Section: string): SArray;
32 property isOpen: Boolean read getIsOpen;
33 end;
35 {
36 const
37 DFWAD_NOERROR = 0;
38 DFWAD_ERROR_WADNOTFOUND = -1;
39 DFWAD_ERROR_CANTOPENWAD = -2;
40 DFWAD_ERROR_RESOURCENOTFOUND = -3;
41 DFWAD_ERROR_FILENOTWAD = -4;
42 DFWAD_ERROR_WADNOTLOADED = -5;
43 DFWAD_ERROR_READRESOURCE = -6;
44 DFWAD_ERROR_READWAD = -7;
45 DFWAD_ERROR_WRONGVERSION = -8;
46 }
49 procedure g_ProcessResourceStr (ResourceStr: String; var FileName, SectionName, ResourceName: String); overload;
50 procedure g_ProcessResourceStr (ResourceStr: String; FileName, SectionName, ResourceName: PString); overload;
53 implementation
55 uses
56 SysUtils, Classes, BinEditor, e_log, g_options;
59 procedure g_ProcessResourceStr (ResourceStr: String; var FileName, SectionName, ResourceName: String);
60 var
61 a, i: Integer;
63 begin
64 //e_WriteLog(Format('g_ProcessResourceStr0: [%s]', [ResourceStr]), MSG_NOTIFY);
65 for i := Length(ResourceStr) downto 1 do
66 if ResourceStr[i] = ':' then
67 Break;
69 FileName := Copy(ResourceStr, 1, i-1);
71 for a := i+1 to Length(ResourceStr) do
72 if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break;
74 ResourceName := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a));
75 SectionName := Copy(ResourceStr, i+1, Length(ResourceStr)-Length(ResourceName)-Length(FileName)-2);
76 end;
79 procedure g_ProcessResourceStr (ResourceStr: AnsiString; FileName, SectionName, ResourceName: PAnsiString);
80 var
81 a, i, l1, l2: Integer;
83 begin
84 //e_WriteLog(Format('g_ProcessResourceStr1: [%s]', [ResourceStr]), MSG_NOTIFY);
85 for i := Length(ResourceStr) downto 1 do
86 if ResourceStr[i] = ':' then
87 Break;
89 if FileName <> nil then
90 begin
91 FileName^ := Copy(ResourceStr, 1, i-1);
92 l1 := Length(FileName^);
93 end
94 else
95 l1 := 0;
97 for a := i+1 to Length(ResourceStr) do
98 if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break;
100 if ResourceName <> nil then
101 begin
102 ResourceName^ := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a));
103 l2 := Length(ResourceName^);
104 end
105 else
106 l2 := 0;
108 if SectionName <> nil then
109 SectionName^ := Copy(ResourceStr, i+1, Length(ResourceStr)-l2-l1-2);
110 end;
113 { TWADEditor_1 }
114 constructor TWADEditor_1.Create();
115 begin
116 fFileName := '';
117 end;
120 destructor TWADEditor_1.Destroy();
121 begin
122 FreeWAD();
123 inherited;
124 end;
127 function TWADEditor_1.getIsOpen (): Boolean;
128 begin
129 result := (fFileName <> '');
130 end;
133 procedure TWADEditor_1.FreeWAD();
134 begin
135 if fIter <> nil then FreeAndNil(fIter);
136 //if fFileName <> '' then e_WriteLog(Format('TWADEditor_1.ReadFile: [%s] closed', [fFileName]), MSG_NOTIFY);
137 fFileName := '';
138 end;
141 function removeExt (s: string): string;
142 var
143 i: Integer;
144 begin
145 i := length(s)+1;
146 while (i > 1) and (s[i-1] <> '.') and (s[i-1] <> '/') do Dec(i);
147 if (i > 1) and (s[i-1] = '.') then
148 begin
149 //writeln('[', s, '] -> [', Copy(s, 1, i-2), ']');
150 s := Copy(s, 1, i-2);
151 end;
152 result := s;
153 end;
155 function TWADEditor_1.GetResource (Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
156 var
157 f: Integer;
158 fi: TSFSFileInfo;
159 fs: TStream;
160 //fn: string;
161 begin
162 Result := False;
163 if not isOpen or (fIter = nil) then Exit;
164 if length(Resource) = 0 then Exit; // just in case
165 if (length(Section) <> 0) and (Section[length(Section)] <> '/') then Section := Section+'/';
166 // backwards, due to possible similar names and such
167 for f := fIter.Count-1 downto 0 do
168 begin
169 fi := fIter.Files[f];
170 if fi = nil then continue;
171 //e_WriteLog(Format('DFWAD: searching for [%s : %s] in [%s]; current is [%s : %s] (%d, %d)', [Section, Resource, fFileName, fi.path, fi.name, SFSStrEqu(fi.path, Section), SFSStrEqu(fi.name, Resource)]), MSG_NOTIFY);
172 if {SFSStrEqu}SFSDFPathEqu(fi.path, Section) and SFSStrEqu(removeExt(fi.name), Resource) then
173 begin
174 // i found her!
175 //fn := fFileName+'::'+fi.path+fi.name;
176 //fs := SFSFileOpen(fn);
177 try
178 fs := fIter.volume.OpenFileByIndex(f);
179 except
180 fs := nil;
181 end;
182 if fs = nil then
183 begin
184 e_WriteLog(Format('DFWAD: can''t open file [%s%s] in [%s]', [Section, Resource, fFileName]), MSG_WARNING);
185 break;
186 end;
187 Len := Integer(fs.size);
188 GetMem(pData, Len);
189 fs.ReadBuffer(pData^, Len);
190 fs.Free;
191 result := true;
192 {$IFDEF SFS_DWFAD_DEBUG}
193 if gSFSDebug then
194 e_WriteLog(Format('DFWAD: file [%s%s] FOUND in [%s]; size is %d bytes', [Section, Resource, fFileName, Len]), MSG_NOTIFY);
195 {$ENDIF}
196 exit;
197 end;
198 end;
199 e_WriteLog(Format('DFWAD: file [%s%s] not found in [%s]', [Section, Resource, fFileName]), MSG_WARNING);
200 end;
203 function TWADEditor_1.GetResourcesList (Section: string): SArray;
204 var
205 f: Integer;
206 fi: TSFSFileInfo;
207 begin
208 Result := nil;
209 if not isOpen or (fIter = nil) then Exit;
210 if (length(Section) <> 0) and (Section[length(Section)] <> '/') then Section := Section+'/';
211 for f := 0 to fIter.Count-1 do
212 begin
213 fi := fIter.Files[f];
214 if fi = nil then continue;
215 if length(fi.name) = 0 then continue;
216 if {SFSStrEqu}SFSDFPathEqu(fi.path, Section) then
217 begin
218 SetLength(result, Length(result)+1);
219 result[high(result)] := removeExt(fi.name);
220 end;
221 end;
222 end;
225 function TWADEditor_1.ReadFile (FileName: string): Boolean;
226 var
227 rfn: string;
228 //f: Integer;
229 //fi: TSFSFileInfo;
230 begin
231 Result := False;
232 //e_WriteLog(Format('TWADEditor_1.ReadFile: [%s]', [FileName]), MSG_NOTIFY);
233 FreeWAD();
234 rfn := FileName;
235 if not FileExists(rfn) then
236 begin
237 //if length(rfn) >= 4 then e_WriteLog(Format('XXXX TWADEditor_1.ReadFile: [%s] [%s]', [Copy(rfn, length(rfn)-3, 4), Copy(rfn, 1, length(rfn)-4)]), MSG_NOTIFY);
238 if (length(rfn) >= 4) and SFSStrEqu(Copy(rfn, length(rfn)-3, 4), '.wad') then
239 begin
240 rfn := Copy(rfn, 1, length(rfn)-4);
241 if FileExists(rfn+'.pk3') then rfn := rfn+'.pk3'
242 else if FileExists(rfn+'.zip') then rfn := rfn+'.zip'
243 else rfn := FileName;
244 {.$IFDEF SFS_DWFAD_DEBUG}
245 if gSFSDebug then
246 if FileExists(rfn) then e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
247 {.$ENDIF}
248 end;
249 end;
250 if not FileExists(rfn) then exit;
251 {$IFDEF SFS_DWFAD_DEBUG}
252 if gSFSDebug then
253 e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
254 {$ENDIF}
255 // cache this wad
256 SFSAddDataFile(rfn);
257 fIter := SFSFileList(rfn);
258 if fIter = nil then Exit;
259 fFileName := rfn;
260 {$IFDEF SFS_DWFAD_DEBUG}
261 if gSFSDebug then
262 e_WriteLog(Format('TWADEditor_1.ReadFile: [%s] opened', [fFileName]), MSG_NOTIFY);
263 {$ENDIF}
265 for f := 0 to fIter.Count-1 do
266 begin
267 fi := fIter.Files[f];
268 if fi = nil then continue;
269 e_WriteLog(Format('[%s]: [%s : %s] %u', [fFileName, fi.path, fi.name, fi.size]), MSG_NOTIFY);
270 end;
272 Result := True;
273 end;
276 var
277 uniqueCounter: Integer = 0;
279 function TWADEditor_1.ReadMemory (Data: Pointer; Len: LongWord): Boolean;
280 var
281 fn: string;
282 st: TStream = nil;
283 //f: Integer;
284 //fi: TSFSFileInfo;
285 begin
286 Result := False;
287 FreeWAD();
288 if (Data = nil) or (Len = 0) then
289 begin
290 e_WriteLog('TWADEditor_1.ReadMemory: EMPTY SUBWAD!', MSG_WARNING);
291 Exit;
292 end;
294 fn := Format(' -- memwad %d -- ', [uniqueCounter]);
295 Inc(uniqueCounter);
296 {$IFDEF SFS_DWFAD_DEBUG}
297 e_WriteLog(Format('TWADEditor_1.ReadMemory: [%s]', [fn]), MSG_NOTIFY);
298 {$ENDIF}
300 try
301 st := TSFSMemoryStreamRO.Create(Data, Len);
302 if not SFSAddSubDataFile(fn, st) then
303 begin
304 st.Free;
305 Exit;
306 end;
307 except
308 st.Free;
309 Exit;
310 end;
312 fIter := SFSFileList(fn);
313 if fIter = nil then Exit;
315 fFileName := fn;
316 {$IFDEF SFS_DWFAD_DEBUG}
317 e_WriteLog(Format('TWADEditor_1.ReadMemory: [%s] opened', [fFileName]), MSG_NOTIFY);
318 {$ENDIF}
321 for f := 0 to fIter.Count-1 do
322 begin
323 fi := fIter.Files[f];
324 if fi = nil then continue;
325 st := fIter.volume.OpenFileByIndex(f);
326 if st = nil then
327 begin
328 e_WriteLog(Format('[%s]: [%s : %s] CAN''T OPEN', [fFileName, fi.path, fi.name]), MSG_NOTIFY);
329 end
330 else
331 begin
332 e_WriteLog(Format('[%s]: [%s : %s] %u', [fFileName, fi.path, fi.name, st.size]), MSG_NOTIFY);
333 st.Free;
334 end;
335 end;
336 //fIter.volume.OpenFileByIndex(0);
339 Result := True;
340 end;
343 begin
344 sfsDiskDirs := '<exedir>/data'; //FIXME
345 end.