index 6a5dbeedd227e3c8da2cc61bd07e6828342b6028..0e383c3a565d8317103f87a0170500f4945f7eff 100644 (file)
interface
(**
interface
(**
+ g_GetResourceSection
+ Parse path in form 'path/to/file.wad:some/section/resouce' to
+ wad = 'path/to/file.wa', section = 'some/section', name = 'resource'
+
+ g_DeleteFile
+ Delete file if it exists. Make backup if enabled.
+
g_ReadResource
Read whole file from wad
(data <> nil) and (len > 0) when ok
g_ReadResource
Read whole file from wad
(data <> nil) and (len > 0) when ok
res = 0 when ok
**)
res = 0 when ok
**)
+ (* Editor options *)
+ var
+ Compress: Boolean;
+ Backup: Boolean;
+
+ procedure g_GetResourceSection (path: String; out wad, section, name: String);
+ procedure g_DeleteFile(wad: String; backupPostfix: String = '.bak');
+
procedure g_ReadResource (wad, section, name: String; out data: PByte; out len: Integer);
procedure g_ReadSubResource (wad, section0, name0, section1, name1: String; out data: PByte; out len: Integer);
procedure g_DeleteResource (wad, section, name: String; out res: Integer);
procedure g_ReadResource (wad, section, name: String; out data: PByte; out len: Integer);
procedure g_ReadSubResource (wad, section0, name0, section1, name1: String; out data: PByte; out len: Integer);
procedure g_DeleteResource (wad, section, name: String; out res: Integer);
implementation
implementation
- uses sfs, xstreams, dfzip, utils, Classes, SysUtils, WADEDITOR;
+ uses sfs, xstreams, dfzip, utils, Classes, SysUtils, WADEDITOR, e_log;
+
+ function NoTrailing (path: String): String;
+ var i: Integer;
+ begin
+ i := Length(path);
+ while (i > 0) and ((path[i] = '/') or (path[i] = '\')) do dec(i);
+ result := Copy(path, 1, i)
+ end;
+
+ function g_CleanPath (path: String; sys: Boolean = False): String;
+ var i, len: Integer;
+ begin
+ i := 1;
+ result := '';
+ len := Length(path);
+ (* drop separators at the end *)
+ while (len > 1) and ((path[i] = '/') or (path[i] = '\')) do dec(len);
+ while i <= len do
+ begin
+ while (i <= len) and (path[i] <> '/') and (path[i] <> '\') do
+ begin
+ result := result + path[i];
+ inc(i)
+ end;
+ if i <= len then
+ if sys then
+ result := result + DirectorySeparator
+ else
+ result := result + '/';
+ inc(i);
+ while (i <= len) and ((path[i] = '/') or (path[i] = '\')) do inc(i)
+ end;
+ end;
+
+ procedure g_GetResourceSection (path: String; out wad, section, name: String);
+ var i, j, len: Integer;
+ begin
+ len := Length(path);
+ i := len;
+ while (i > 0) and (path[i] <> '/') and (path[i] <> '\') do dec(i);
+ name := Copy(path, i + 1, len);
+ j := i;
+ while (i > 0) and (path[i] <> ':') do dec(i);
+ section := Copy(path, i + 1, j - i - 1);
+ wad := Copy(path, 1, i - 1);
+ end;
+
+ procedure g_DeleteFile (wad: String; backupPostfix: String = '.bak');
+ var newwad: String;
+ begin
+ if Backup then
+ begin
+ if FileExists(wad) then
+ begin
+ newwad := wad + backupPostfix;
+ if FileExists(newwad) then
+ ASSERT(DeleteFile(newwad));
+ ASSERT(RenameFile(wad, newwad))
+ end
+ end
+ else
+ begin
+ if FileExists(wad) then
+ ASSERT(DeleteFile(wad))
+ end
+ end;
procedure g_AddResourceToDFWAD (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
var f: TWADEditor_1;
begin
res := 1; (* error *)
wad := utf2win(wad);
procedure g_AddResourceToDFWAD (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
var f: TWADEditor_1;
begin
res := 1; (* error *)
wad := utf2win(wad);
- section := utf2win(section);
+ section := utf2win(NoTrailing(section));
name := utf2win(name);
name := utf2win(name);
+ ASSERT(name <> '');
f := TWADEditor_1.Create();
if not f.ReadFile(wad) then
begin
f := TWADEditor_1.Create();
if not f.ReadFile(wad) then
begin
f.CreateImage;
f.RemoveResource(section, name);
f.AddResource(data, len, name, section);
f.CreateImage;
f.RemoveResource(section, name);
f.AddResource(data, len, name, section);
- if FileExists(wad) then
- ASSERT(RenameFile(wad, wad + '.bak'));
+ g_DeleteFile(wad);
f.SaveTo(wad);
f.Free;
res := 0
f.SaveTo(wad);
f.Free;
res := 0
i, n, len0: Integer;
data0: PByte;
list: TSFSFileList;
i, n, len0: Integer;
data0: PByte;
list: TSFSFileList;
- tmp, entry: String;
+ tmp, path: String;
ts: TFileStream;
dir: array of TFileInfo;
ts: TFileStream;
dir: array of TFileInfo;
var ds: TSFSMemoryChunkStream;
begin
SetLength(dir, n + 1);
var ds: TSFSMemoryChunkStream;
begin
SetLength(dir, n + 1);
- ds := TSFSMemoryChunkStream.Create(data, len, false);
- dir[n] := dfzip.ZipOne(ts, name, ds);
+ ds := TSFSMemoryChunkStream.Create(data, len, False);
+ dir[n] := dfzip.ZipOne(ts, name, ds, Compress);
ds.Free;
INC(n);
end;
ds.Free;
INC(n);
end;
begin
res := 1;
wad := ExpandFileName(wad);
begin
res := 1;
wad := ExpandFileName(wad);
- section := utf2win(section);
+ section := utf2win(NoTrailing(section));
name := utf2win(name);
name := utf2win(name);
+ ASSERT(name <> '');
list := SFSFileList(wad);
tmp := wad + '.tmp' + IntToStr(Random(100000));
ts := TFileStream.Create(tmp, fmCreate);
list := SFSFileList(wad);
tmp := wad + '.tmp' + IntToStr(Random(100000));
ts := TFileStream.Create(tmp, fmCreate);
begin
for i := 0 to list.Count - 1 do
begin
begin
for i := 0 to list.Count - 1 do
begin
- if (list.Files[i].path <> section) or (list.Files[i].name <> section) then
+ path := NoTrailing(list.Files[i].path);
+ if (path <> section) or (list.Files[i].name <> name) then
begin
begin
- g_ReadResource(wad, list.Files[i].path, list.Files[i].name, data0, len0);
- if list.Files[i].path = '' then
- entry := list.Files[i].name
+ g_ReadResource(wad, path, list.Files[i].name, data0, len0);
+ ASSERT(data0 <> nil);
+ if path = '' then
+ path := list.Files[i].name
else
else
- entry := list.Files[i].path + '/' + list.Files[i].name;
- Add(entry, data0, len0);
+ path := path + '/' + list.Files[i].name;
+ Add(path, data0, len0);
FreeMem(data0)
end
end;
FreeMem(data0)
end
end;
end;
if section = '' then
end;
if section = '' then
- entry := name
+ path := name
else
else
- entry := section + '/' + name;
+ path := section + '/' + name;
+ Add(path, data, len);
- Add(entry, data, len);
dfzip.writeCentralDir(ts, dir);
ts.Free;
dfzip.writeCentralDir(ts, dir);
ts.Free;
- if FileExists(wad) then
- ASSERT(RenameFile(wad, wad + '.bak'));
+ g_DeleteFile(wad);
ASSERT(RenameFile(tmp, wad));
res := 0
end;
ASSERT(RenameFile(tmp, wad));
res := 0
end;
procedure g_AddResource (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
var ext: String;
begin
procedure g_AddResource (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
var ext: String;
begin
+ ASSERT(name <> '');
res := 2; (* unknown type *)
ext := LowerCase(SysUtils.ExtractFileExt(wad));
res := 2; (* unknown type *)
ext := LowerCase(SysUtils.ExtractFileExt(wad));
+ e_WriteLog('g_AddResource "' + wad + '" "' + section + '" "' + name + '"', MSG_NOTIFY);
if ext = '.wad' then
g_AddResourceToDFWAD(wad, section, name, data, len, res)
if ext = '.wad' then
g_AddResourceToDFWAD(wad, section, name, data, len, res)
- else if (ext = '.pk3') or (ext = '.zip') or (ext = '.dfzip') then
+ else
g_AddResourceToZip(wad, section, name, data, len, res)
end;
procedure g_DeleteResourceFromDFWAD (wad, section, name: String; out res: Integer);
var f: TWADEditor_1;
begin
g_AddResourceToZip(wad, section, name, data, len, res)
end;
procedure g_DeleteResourceFromDFWAD (wad, section, name: String; out res: Integer);
var f: TWADEditor_1;
begin
+ ASSERT(name <> '');
res := 1; (* error *)
res := 1; (* error *)
- section := utf2win(section);
+ section := utf2win(NoTrailing(section));
name := utf2win(name);
f := TWADEditor_1.Create;
if not f.ReadFile(wad) then
name := utf2win(name);
f := TWADEditor_1.Create;
if not f.ReadFile(wad) then
end;
f.CreateImage;
f.RemoveResource(section, name);
end;
f.CreateImage;
f.RemoveResource(section, name);
+ g_DeleteFile(wad);
f.SaveTo(wad);
f.Free;
res := 0 (* ok *)
f.SaveTo(wad);
f.Free;
res := 0 (* ok *)
data0: PByte;
i, n, len0: Integer;
list: TSFSFileList;
data0: PByte;
i, n, len0: Integer;
list: TSFSFileList;
- tmp, entry: String;
+ tmp, path: String;
ts: TFileStream;
dir: array of TFileInfo;
ts: TFileStream;
dir: array of TFileInfo;
var ds: TSFSMemoryChunkStream;
begin
SetLength(dir, n + 1);
var ds: TSFSMemoryChunkStream;
begin
SetLength(dir, n + 1);
- ds := TSFSMemoryChunkStream.Create(data, len, false);
- dir[n] := dfzip.ZipOne(ts, name, ds);
+ ds := TSFSMemoryChunkStream.Create(data, len, False);
+ dir[n] := dfzip.ZipOne(ts, name, ds, Compress);
ds.Free;
INC(n);
end;
ds.Free;
INC(n);
end;
begin
res := 1;
wad := ExpandFileName(wad);
begin
res := 1;
wad := ExpandFileName(wad);
- section := utf2win(section);
+ section := utf2win(NoTrailing(section));
name := utf2win(name);
name := utf2win(name);
+ ASSERT(name <> '');
list := SFSFileList(wad);
tmp := wad + '.tmp' + IntToStr(Random(100000));
ts := TFileStream.Create(tmp, fmCreate);
list := SFSFileList(wad);
tmp := wad + '.tmp' + IntToStr(Random(100000));
ts := TFileStream.Create(tmp, fmCreate);
begin
for i := 0 to list.Count - 1 do
begin
begin
for i := 0 to list.Count - 1 do
begin
- if (list.Files[i].path <> section) or (list.Files[i].name <> section) then
+ path := NoTrailing(list.Files[i].path);
+ if (path <> section) or (list.Files[i].name <> name) then
begin
begin
- g_ReadResource(wad, list.Files[i].path, list.Files[i].name, data0, len0);
- if list.Files[i].path = '' then
- entry := list.Files[i].name
+ g_ReadResource(wad, path, list.Files[i].name, data0, len0);
+ ASSERT(data0 <> nil);
+ if path = '' then
+ path := list.Files[i].name
else
else
- entry := list.Files[i].path + '/' + list.Files[i].name;
- Add(entry, data0, len0);
+ path := path + '/' + list.Files[i].name;
+ Add(path, data0, len0);
FreeMem(data0)
end
end;
FreeMem(data0)
end
end;
dfzip.writeCentralDir(ts, dir);
ts.Free;
dfzip.writeCentralDir(ts, dir);
ts.Free;
- if FileExists(wad) then
- ASSERT(RenameFile(wad, wad + '.bak'));
+ g_DeleteFile(wad);
ASSERT(RenameFile(tmp, wad));
res := 0
end;
ASSERT(RenameFile(tmp, wad));
res := 0
end;
procedure g_DeleteResource (wad, section, name: String; out res: Integer);
var ext: String;
begin
procedure g_DeleteResource (wad, section, name: String; out res: Integer);
var ext: String;
begin
+ ASSERT(name <> '');
res := 2; (* unknown type *)
ext := LowerCase(SysUtils.ExtractFileExt(wad));
if ext = '.wad' then
g_DeleteResourceFromDFWAD(wad, section, name, res)
res := 2; (* unknown type *)
ext := LowerCase(SysUtils.ExtractFileExt(wad));
if ext = '.wad' then
g_DeleteResourceFromDFWAD(wad, section, name, res)
- else if (ext = '.pk3') or (ext = '.zip') or (ext = '.dfzip') then
+ else
g_DeleteResourceFromZip(wad, section, name, res)
end;
g_DeleteResourceFromZip(wad, section, name, res)
end;
var str: String; stream: TStream;
begin
res := 1;
var str: String; stream: TStream;
begin
res := 1;
- section := utf2win(section);
+ section := utf2win(NoTrailing(section));
name := utf2win(name);
name := utf2win(name);
+ ASSERT(name <> '');
if SFSAddDataFileTemp(wad, TRUE) then
begin
str := SFSGetLastVirtualName(section + '\' + name);
if SFSAddDataFileTemp(wad, TRUE) then
begin
str := SFSGetLastVirtualName(section + '\' + name);
procedure g_ReadResource (wad, section, name: String; out data: PByte; out len: Integer);
var stream: TStream; str: String; i: Integer;
begin
procedure g_ReadResource (wad, section, name: String; out data: PByte; out len: Integer);
var stream: TStream; str: String; i: Integer;
begin
- section := utf2win(section);
+ e_WriteLog('g_ReadResource: "' + wad + '" "' + section + '" "' + name + '"', MSG_NOTIFY);
+ section := utf2win(NoTrailing(section));
name := utf2win(name);
data := nil;
len := 0;
name := utf2win(name);
data := nil;
len := 0;
+ //ASSERT(name <> '');
+ if name = '' then Exit; (* SKY can be void *)
if SFSAddDataFileTemp(wad, TRUE) then
begin
if SFSAddDataFileTemp(wad, TRUE) then
begin
- str := SFSGetLastVirtualName(section + '\' + name);
+ str := SFSGetLastVirtualName(section + '/' + name);
stream := SFSFileOpen(wad + '::' + str);
if stream <> nil then
begin
len := stream.Size;
GetMem(data, len);
stream := SFSFileOpen(wad + '::' + str);
if stream <> nil then
begin
len := stream.Size;
GetMem(data, len);
+ ASSERT(data <> nil);
//stream.ReadBuffer(data, len); (* leads to segfault *)
for i := 0 to len - 1 do
data[i] := stream.ReadByte();
//stream.ReadBuffer(data, len); (* leads to segfault *)
for i := 0 to len - 1 do
data[i] := stream.ReadByte();
begin
data := nil;
len := 0;
begin
data := nil;
len := 0;
- if (wad = '') OR (section0 = '') OR (name0 = '') OR (section1 = '') OR (name1 = '') then Exit;
- section0 := utf2win(section0);
+ section0 := utf2win(NoTrailing(section0));
name0 := utf2win(name0);
name0 := utf2win(name0);
- section1 := utf2win(section1);
+ section1 := utf2win(NoTrailing(section1));
name1 := utf2win(name1);
name1 := utf2win(name1);
+ //ASSERT(name0 <> '');
+ //ASSERT(name1 <> '');
+ if (wad = '') OR (name0 = '') OR (name1 = '') then Exit; (* ??? *)
if SFSAddDataFileTemp(wad, TRUE) then
begin
str0 := SFSGetLastVirtualName(section0 + '\' + name0);
if SFSAddDataFileTemp(wad, TRUE) then
begin
str0 := SFSGetLastVirtualName(section0 + '\' + name0);
begin
len := stream1.Size;
GetMem(data, len);
begin
len := stream1.Size;
GetMem(data, len);
+ ASSERT(data <> nil);
//stream1.ReadBuffer(data, len); (* leads to segfault *)
for i := 0 to len - 1 do
data[i] := stream1.ReadByte();
//stream1.ReadBuffer(data, len); (* leads to segfault *)
for i := 0 to len - 1 do
data[i] := stream1.ReadByte();