DEADSOFTWARE

sfs system now works!
[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;
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 TWADEditor_1.GetResource (Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
142 var
143 f: Integer;
144 fi: TSFSFileInfo;
145 fs: TStream;
146 //fn: string;
147 begin
148 Result := False;
149 if not isOpen or (fIter = nil) then Exit;
150 if (length(Section) <> 0) and (Section[length(Section)] <> '/') then Section := Section+'/';
151 for f := 0 to fIter.Count-1 do
152 begin
153 fi := fIter.Files[f];
154 if fi = nil then continue;
155 //e_WriteLog(Format('DFWAD: searching for [%s : %s] in [%s]; current is [%s : %s] (%d, %d)', [Section, Resource, fFileName, fi.path, fi.name, SFSStrComp(fi.path, Section), SFSStrComp(fi.name, Resource)]), MSG_NOTIFY);
156 if (SFSStrComp(fi.path, Section) = 0) and (SFSStrComp(fi.name, Resource) = 0) then
157 begin
158 // i found her!
159 //fn := fFileName+'::'+fi.path+fi.name;
160 //fs := SFSFileOpen(fn);
161 try
162 fs := fIter.volume.OpenFileByIndex(f);
163 except
164 fs := nil;
165 end;
166 if fs = nil then
167 begin
168 e_WriteLog(Format('DFWAD: can''t open file [%s%s] in [%s]', [Section, Resource, fFileName]), MSG_WARNING);
169 break;
170 end;
171 Len := Integer(fs.size);
172 GetMem(pData, Len);
173 fs.ReadBuffer(pData^, Len);
174 fs.Free;
175 result := true;
176 {$IFDEF SFS_DWFAD_DEBUG}
177 e_WriteLog(Format('DFWAD: file [%s%s] FOUND in [%s]; size is %d bytes', [Section, Resource, fFileName, Len]), MSG_NOTIFY);
178 {$ENDIF}
179 exit;
180 end;
181 end;
182 e_WriteLog(Format('DFWAD: file [%s%s] not found in [%s]', [Section, Resource, fFileName]), MSG_WARNING);
183 end;
186 function TWADEditor_1.GetResourcesList (Section: string): SArray;
187 var
188 f: Integer;
189 fi: TSFSFileInfo;
190 begin
191 Result := nil;
192 if not isOpen or (fIter = nil) then Exit;
193 if (length(Section) <> 0) and (Section[length(Section)] <> '/') then Section := Section+'/';
194 for f := 0 to fIter.Count-1 do
195 begin
196 fi := fIter.Files[f];
197 if fi = nil then continue;
198 if SFSStrComp(fi.path, Section) = 0 then
199 begin
200 SetLength(result, Length(result)+1);
201 result[high(result)] := fi.name;
202 end;
203 end;
204 end;
207 function TWADEditor_1.ReadFile (FileName: string): Boolean;
208 var
209 rfn: string;
210 begin
211 Result := False;
212 //e_WriteLog(Format('TWADEditor_1.ReadFile: [%s]', [FileName]), MSG_NOTIFY);
213 FreeWAD();
214 rfn := FileName;
215 if not FileExists(rfn) then
216 begin
217 //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);
218 if (length(rfn) >= 4) and (SFSStrComp(Copy(rfn, length(rfn)-3, 4), '.wad') = 0) then
219 begin
220 rfn := Copy(rfn, 1, length(rfn)-4);
221 if FileExists(rfn+'.pk3') then rfn := rfn+'.pk3'
222 else if FileExists(rfn+'.zip') then rfn := rfn+'.zip'
223 else rfn := FileName;
224 {.$IFDEF SFS_DWFAD_DEBUG}
225 if FileExists(rfn) then e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
226 {.$ENDIF}
227 end;
228 end;
229 if not FileExists(rfn) then exit;
230 {$IFDEF SFS_DWFAD_DEBUG}
231 e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
232 {$ENDIF}
233 // cache this wad
234 SFSAddDataFile(rfn);
235 fIter := SFSFileList(rfn);
236 if fIter = nil then Exit;
237 fFileName := rfn;
238 {$IFDEF SFS_DWFAD_DEBUG}
239 e_WriteLog(Format('TWADEditor_1.ReadFile: [%s] opened', [fFileName]), MSG_NOTIFY);
240 {$ENDIF}
241 Result := True;
242 end;
245 var
246 uniqueCounter: Integer = 0;
248 function TWADEditor_1.ReadMemory (Data: Pointer; Len: LongWord): Boolean;
249 var
250 Signature: array[0..4] of Char;
251 fn: string;
252 st: TStream = nil;
253 //f: Integer;
254 //fi: TSFSFileInfo;
255 begin
256 Result := False;
257 FreeWAD();
258 if (Data = nil) or (Len = 0) then
259 begin
260 e_WriteLog('TWADEditor_1.ReadMemory: EMPTY SUBWAD!', MSG_WARNING);
261 Exit;
262 end;
264 fn := Format(' -- memwad %d -- ', [uniqueCounter]);
265 Inc(uniqueCounter);
266 {$IFDEF SFS_DWFAD_DEBUG}
267 e_WriteLog(Format('TWADEditor_1.ReadMemory: [%s]', [fn]), MSG_NOTIFY);
268 {$ENDIF}
270 try
271 st := TSFSMemoryStreamRO.Create(Data, Len);
272 if not SFSAddSubDataFile(fn, st) then
273 begin
274 st.Free;
275 Exit;
276 end;
277 except
278 st.Free;
279 Exit;
280 end;
282 fIter := SFSFileList(fn);
283 if fIter = nil then Exit;
285 fFileName := fn;
286 {$IFDEF SFS_DWFAD_DEBUG}
287 e_WriteLog(Format('TWADEditor_1.ReadMemory: [%s] opened', [fFileName]), MSG_NOTIFY);
288 {$ENDIF}
291 for f := 0 to fIter.Count-1 do
292 begin
293 fi := fIter.Files[f];
294 if fi = nil then continue;
295 st := fIter.volume.OpenFileByIndex(f);
296 if st = nil then
297 begin
298 e_WriteLog(Format('[%s]: [%s : %s] CAN''T OPEN', [fFileName, fi.path, fi.name]), MSG_NOTIFY);
299 end
300 else
301 begin
302 e_WriteLog(Format('[%s]: [%s : %s] %u', [fFileName, fi.path, fi.name, st.size]), MSG_NOTIFY);
303 st.Free;
304 end;
305 end;
306 //fIter.volume.OpenFileByIndex(0);
309 Result := True;
310 end;
313 begin
314 sfsDiskDirs := '<exedir>/data'; //FIXME
315 end.