DEADSOFTWARE

sfs now removing extensions from files
[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 for f := 0 to fIter.Count-1 do
167 begin
168 fi := fIter.Files[f];
169 if fi = nil then continue;
170 //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);
171 if {SFSStrEqu}SFSDFPathEqu(fi.path, Section) and SFSStrEqu(removeExt(fi.name), Resource) then
172 begin
173 // i found her!
174 //fn := fFileName+'::'+fi.path+fi.name;
175 //fs := SFSFileOpen(fn);
176 try
177 fs := fIter.volume.OpenFileByIndex(f);
178 except
179 fs := nil;
180 end;
181 if fs = nil then
182 begin
183 e_WriteLog(Format('DFWAD: can''t open file [%s%s] in [%s]', [Section, Resource, fFileName]), MSG_WARNING);
184 break;
185 end;
186 Len := Integer(fs.size);
187 GetMem(pData, Len);
188 fs.ReadBuffer(pData^, Len);
189 fs.Free;
190 result := true;
191 {$IFDEF SFS_DWFAD_DEBUG}
192 if gSFSDebug then
193 e_WriteLog(Format('DFWAD: file [%s%s] FOUND in [%s]; size is %d bytes', [Section, Resource, fFileName, Len]), MSG_NOTIFY);
194 {$ENDIF}
195 exit;
196 end;
197 end;
198 e_WriteLog(Format('DFWAD: file [%s%s] not found in [%s]', [Section, Resource, fFileName]), MSG_WARNING);
199 end;
202 function TWADEditor_1.GetResourcesList (Section: string): SArray;
203 var
204 f: Integer;
205 fi: TSFSFileInfo;
206 begin
207 Result := nil;
208 if not isOpen or (fIter = nil) then Exit;
209 if (length(Section) <> 0) and (Section[length(Section)] <> '/') then Section := Section+'/';
210 for f := 0 to fIter.Count-1 do
211 begin
212 fi := fIter.Files[f];
213 if fi = nil then continue;
214 if length(fi.name) = 0 then continue;
215 if {SFSStrEqu}SFSDFPathEqu(fi.path, Section) then
216 begin
217 SetLength(result, Length(result)+1);
218 result[high(result)] := removeExt(fi.name);
219 end;
220 end;
221 end;
224 function TWADEditor_1.ReadFile (FileName: string): Boolean;
225 var
226 rfn: string;
227 //f: Integer;
228 //fi: TSFSFileInfo;
229 begin
230 Result := False;
231 //e_WriteLog(Format('TWADEditor_1.ReadFile: [%s]', [FileName]), MSG_NOTIFY);
232 FreeWAD();
233 rfn := FileName;
234 if not FileExists(rfn) then
235 begin
236 //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);
237 if (length(rfn) >= 4) and SFSStrEqu(Copy(rfn, length(rfn)-3, 4), '.wad') then
238 begin
239 rfn := Copy(rfn, 1, length(rfn)-4);
240 if FileExists(rfn+'.pk3') then rfn := rfn+'.pk3'
241 //else if FileExists(rfn+'.zip') then rfn := rfn+'.zip'
242 else rfn := FileName;
243 {.$IFDEF SFS_DWFAD_DEBUG}
244 if gSFSDebug then
245 if FileExists(rfn) then e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
246 {.$ENDIF}
247 end;
248 end;
249 if not FileExists(rfn) then exit;
250 {$IFDEF SFS_DWFAD_DEBUG}
251 if gSFSDebug then
252 e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
253 {$ENDIF}
254 // cache this wad
255 SFSAddDataFile(rfn);
256 fIter := SFSFileList(rfn);
257 if fIter = nil then Exit;
258 fFileName := rfn;
259 {$IFDEF SFS_DWFAD_DEBUG}
260 if gSFSDebug then
261 e_WriteLog(Format('TWADEditor_1.ReadFile: [%s] opened', [fFileName]), MSG_NOTIFY);
262 {$ENDIF}
264 for f := 0 to fIter.Count-1 do
265 begin
266 fi := fIter.Files[f];
267 if fi = nil then continue;
268 e_WriteLog(Format('[%s]: [%s : %s] %u', [fFileName, fi.path, fi.name, fi.size]), MSG_NOTIFY);
269 end;
271 Result := True;
272 end;
275 var
276 uniqueCounter: Integer = 0;
278 function TWADEditor_1.ReadMemory (Data: Pointer; Len: LongWord): Boolean;
279 var
280 fn: string;
281 st: TStream = nil;
282 //f: Integer;
283 //fi: TSFSFileInfo;
284 begin
285 Result := False;
286 FreeWAD();
287 if (Data = nil) or (Len = 0) then
288 begin
289 e_WriteLog('TWADEditor_1.ReadMemory: EMPTY SUBWAD!', MSG_WARNING);
290 Exit;
291 end;
293 fn := Format(' -- memwad %d -- ', [uniqueCounter]);
294 Inc(uniqueCounter);
295 {$IFDEF SFS_DWFAD_DEBUG}
296 e_WriteLog(Format('TWADEditor_1.ReadMemory: [%s]', [fn]), MSG_NOTIFY);
297 {$ENDIF}
299 try
300 st := TSFSMemoryStreamRO.Create(Data, Len);
301 if not SFSAddSubDataFile(fn, st) then
302 begin
303 st.Free;
304 Exit;
305 end;
306 except
307 st.Free;
308 Exit;
309 end;
311 fIter := SFSFileList(fn);
312 if fIter = nil then Exit;
314 fFileName := fn;
315 {$IFDEF SFS_DWFAD_DEBUG}
316 e_WriteLog(Format('TWADEditor_1.ReadMemory: [%s] opened', [fFileName]), MSG_NOTIFY);
317 {$ENDIF}
320 for f := 0 to fIter.Count-1 do
321 begin
322 fi := fIter.Files[f];
323 if fi = nil then continue;
324 st := fIter.volume.OpenFileByIndex(f);
325 if st = nil then
326 begin
327 e_WriteLog(Format('[%s]: [%s : %s] CAN''T OPEN', [fFileName, fi.path, fi.name]), MSG_NOTIFY);
328 end
329 else
330 begin
331 e_WriteLog(Format('[%s]: [%s : %s] %u', [fFileName, fi.path, fi.name, st.size]), MSG_NOTIFY);
332 st.Free;
333 end;
334 end;
335 //fIter.volume.OpenFileByIndex(0);
338 Result := True;
339 end;
342 begin
343 sfsDiskDirs := '<exedir>/data'; //FIXME
344 end.