index b533664d29bb1c60e3ccf11da9131f8a97a123ea..30b3260bfa20cb88b4cec54af788addae9de8bbf 100644 (file)
--- a/src/shared/WADEDITOR.pas
+++ b/src/shared/WADEDITOR.pas
-unit WADEDITOR;
-
-{$MODE Delphi}
+{$INCLUDE ../shared/a_modes.inc}
-{
------------------------------------
-WADEDITOR.PAS ВЕРСИЯ ОТ 26.08.08
+unit WADEDITOR;
-Поддержка вадов версии 1
------------------------------------
-}
+// TWADEditor errors:
+// - Create = DFWAD_NOERROR
+// - FreeWAD = DFWAD_NOERROR
+// - ReadFile -> DFWAD_ERROR_WADNOTFOUND, DFWAD_ERROR_CANTOPENWAD, DFWAD_ERROR_FILENOTWAD, DFWAD_ERROR_WRONGVERSION, DFWAD_ERROR_READWAD, DFWAD_NOERROR
+// - ReadMemory -> DFWAD_ERROR_FILENOTWAD, DFWAD_ERROR_WRONGVERSION, DFWAD_NOERROR
+// - CreateImage -> DFWAD_ERROR_WADNOTLOADED, DFWAD_OPENED_MEMORY, DFWAD_ERROR_CANTOPENWAD, DFWAD_NOERROR
+// - AddResource (pointer)
+// - AddResource (filename) -> DFWAD_ERROR_CANTOPENWAD, DFWAD_ERROR_READWAD, DFWAD_NOERROR
+// - AddAlias
+// - AddSection
+// - RemoveResource
+// - SaveTo
+// - HaveResource
+// - HaveSection
+// - GetResource -> DFWAD_ERROR_WADNOTLOADED, DFWAD_ERROR_RESOURCENOTFOUND, DFWAD_ERROR_CANTOPENWAD, DFWAD_NOERROR
+// - GetSectionList
+// - GetResourcesList
interface
-uses WADSTRUCT;
-
-type
- SArray = array of ShortString;
-
- TWADEditor_1 = class(TObject)
- private
- FResData: Pointer;
- FResTable: packed array of TResourceTableRec_1;
- FHeader: TWADHeaderRec_1;
- FDataSize: LongWord;
- FOffset: LongWord;
- FFileName: string;
- FWADOpened: Byte;
- FLastError: Integer;
- FVersion: Byte;
- function LastErrorString(): string;
- function GetResName(ResName: string): Char16;
- public
- constructor Create();
- destructor Destroy(); override;
- procedure FreeWAD();
- function ReadFile(FileName: string): Boolean;
- function ReadMemory(Data: Pointer; Len: LongWord): Boolean;
- procedure CreateImage();
- function AddResource(Data: Pointer; Len: LongWord; Name: string;
- Section: string): Boolean; overload;
- function AddResource(FileName, Name, Section: string): Boolean; overload;
- function AddAlias(Res, Alias: string): Boolean;
- procedure AddSection(Name: string);
- procedure RemoveResource(Section, Resource: string);
- procedure SaveTo(FileName: string);
- function HaveResource(Section, Resource: string): Boolean;
- function HaveSection(Section: string): Boolean;
- function GetResource(Section, Resource: string; var pData: Pointer;
- var Len: Integer): Boolean;
- function GetSectionList(): SArray;
- function GetResourcesList(Section: string): SArray;
-
- property GetLastError: Integer read FLastError;
- property GetLastErrorStr: string read LastErrorString;
- property GetResourcesCount: Word read FHeader.RecordsCount;
- property GetVersion: Byte read FVersion;
- end;
-
-const
- DFWAD_NOERROR = 0;
- DFWAD_ERROR_WADNOTFOUND = -1;
- DFWAD_ERROR_CANTOPENWAD = -2;
- DFWAD_ERROR_RESOURCENOTFOUND = -3;
- DFWAD_ERROR_FILENOTWAD = -4;
- DFWAD_ERROR_WADNOTLOADED = -5;
- DFWAD_ERROR_READRESOURCE = -6;
- DFWAD_ERROR_READWAD = -7;
- DFWAD_ERROR_WRONGVERSION = -8;
-
-
- procedure g_ProcessResourceStr(ResourceStr: String; var FileName,
- SectionName, ResourceName: String); overload;
- procedure g_ProcessResourceStr(ResourceStr: String; FileName,
- SectionName, ResourceName: PString); overload;
+ uses Classes;
+
+ const
+ DFWAD_NOERROR = 0;
+ DFWAD_ERROR_WADNOTFOUND = -1;
+ DFWAD_ERROR_CANTOPENWAD = -2;
+ DFWAD_ERROR_RESOURCENOTFOUND = -3;
+ DFWAD_ERROR_FILENOTWAD = -4;
+ DFWAD_ERROR_WADNOTLOADED = -5;
+ DFWAD_ERROR_READRESOURCE = -6;
+ DFWAD_ERROR_READWAD = -7;
+ DFWAD_ERROR_WRONGVERSION = -8;
+
+ type
+ SArray = array of ShortString;
+
+ TWADEditor = class abstract(TObject)
+ public
+ function ReadFile(FileName: string): Boolean;
+
+ function ReadFile2(FileName: string): Boolean; virtual; abstract;
+ function ReadMemory(Data: Pointer; Len: LongWord): Boolean; virtual; abstract;
+ procedure FreeWAD(); virtual; abstract;
+ procedure CreateImage(); virtual; abstract;
+ function AddResource(Data: Pointer; Len: LongWord; Name: string; Section: string): Boolean; virtual; abstract; overload;
+ function AddResource(FileName, Name, Section: string): Boolean; overload; virtual; abstract;
+ function AddAlias(Res, Alias: string): Boolean; virtual; abstract;
+ procedure AddSection(Name: string); virtual; abstract;
+ procedure RemoveResource(Section, Resource: string); virtual; abstract;
+ procedure SaveTo(FileName: string); virtual; abstract;
+ function HaveResource(Section, Resource: string): Boolean; virtual; abstract;
+ function HaveSection(Section: string): Boolean; virtual; abstract;
+ function GetResource(Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean; virtual; abstract;
+ function GetSectionList(): SArray; virtual; abstract;
+ function GetResourcesList(Section: string): SArray; virtual; abstract;
+
+ function GetLastError: Integer; virtual; abstract;
+ function GetLastErrorStr: String; virtual; abstract;
+ function GetResourcesCount: Word; virtual; abstract;
+ function GetVersion: Byte; virtual; abstract;
+ end;
-implementation
+ TWADEditorClass = class of TWADEditor;
-uses
- SysUtils, BinEditor, ZLib;
-
-const
- DFWAD_OPENED_NONE = 0;
- DFWAD_OPENED_FILE = 1;
- DFWAD_OPENED_MEMORY = 2;
-
-procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
- OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
-var
- strm: TZStreamRec;
- P: Pointer;
- BufInc: Integer;
-begin
- FillChar(strm, sizeof(strm), 0);
- BufInc := (InBytes + 255) and not 255;
- if OutEstimate = 0 then
- OutBytes := BufInc
- else
- OutBytes := OutEstimate;
- GetMem(OutBuf, OutBytes);
- try
- strm.next_in := InBuf;
- strm.avail_in := InBytes;
- strm.next_out := OutBuf;
- strm.avail_out := OutBytes;
- inflateInit_(strm, zlib_version, sizeof(strm));
- try
- while inflate(strm, Z_FINISH) <> Z_STREAM_END do
- begin
- P := OutBuf;
- Inc(OutBytes, BufInc);
- ReallocMem(OutBuf, OutBytes);
- strm.next_out := PByteF(PChar(OutBuf) + (PChar(strm.next_out) - PChar(P)));
- strm.avail_out := BufInc;
- end;
- finally
- inflateEnd(strm);
+ TWADEditorMapping = class sealed(TObject)
+ private
+ FName: String;
+ FWADEditorClass: TWADEditorClass;
+ public
+ constructor CreateEx(const name: String; const eclass: TWADEditorClass);
+ property Name: String read FName;
+ property WADEditorClass: TWADEditorClass read FWADEditorClass;
end;
- ReallocMem(OutBuf, strm.total_out);
- OutBytes := strm.total_out;
- except
- FreeMem(OutBuf);
- raise
- end;
-end;
-procedure g_ProcessResourceStr(ResourceStr: String; var FileName,
- SectionName, ResourceName: String);
-var
- a, i: Integer;
+ TWADEditorFactory = class sealed(TObject)
+ private
+ FMappings: TStringList;
+ FDefault: TWADEditorClass;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ procedure RegisterEditor(const name: String; const eclass: TWADEditorClass);
+ procedure SetDefaultEditor(const name: String);
+ function CreateEditor(const name: String): TWADEditor;
+ function CreateDefaultEditor(): TWADEditor;
+ function OpenFile(FileName: String): TWADEditor;
+ function OpenMemory(Data: Pointer; Len: Integer): TWADEditor;
+ procedure GetRegistredEditors(var list: TStringList);
+ end;
-begin
- for i := Length(ResourceStr) downto 1 do
- if ResourceStr[i] = ':' then
- Break;
+ // TWADEditor_1 deprecated
+ TWADEditor_1 = class sealed(TObject)
+ private
+ FBase: TWADEditor;
+ public
+ constructor Create();
+ destructor Destroy(); override;
+ procedure FreeWAD();
+ function ReadFile(FileName: string): Boolean;
+ function ReadMemory(Data: Pointer; Len: LongWord): Boolean;
+ procedure CreateImage();
+ function AddResource(Data: Pointer; Len: LongWord; Name: string; Section: string): Boolean; overload;
+ function AddResource(FileName, Name, Section: string): Boolean; overload;
+ function AddAlias(Res, Alias: string): Boolean;
+ procedure AddSection(Name: string);
+ procedure RemoveResource(Section, Resource: string);
+ procedure SaveTo(FileName: string);
+ function HaveResource(Section, Resource: string): Boolean;
+ function HaveSection(Section: string): Boolean;
+ function GetResource(Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
+ function GetSectionList(): SArray;
+ function GetResourcesList(Section: string): SArray;
+
+ function GetLastError: Integer;
+ function GetLastErrorStr: String;
+ function GetResourcesCount: Word;
+ function GetVersion: Byte;
+ end;
- FileName := Copy(ResourceStr, 1, i-1);
+ procedure g_ProcessResourceStr(ResourceStr: String; var FileName, SectionName, ResourceName: String); overload;
+ procedure g_ProcessResourceStr(ResourceStr: String; FileName, SectionName, ResourceName: PString); overload;
- for a := i+1 to Length(ResourceStr) do
- if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break;
+ function gWADEditorFactory: TWADEditorFactory;
- ResourceName := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a));
- SectionName := Copy(ResourceStr, i+1, Length(ResourceStr)-Length(ResourceName)-Length(FileName)-2);
-end;
+implementation
-procedure g_ProcessResourceStr(ResourceStr: AnsiString; FileName,
- SectionName, ResourceName: PAnsiString);
-var
- a, i, l1, l2: Integer;
+ uses SysUtils, Math, utils;
-begin
- for i := Length(ResourceStr) downto 1 do
- if ResourceStr[i] = ':' then
- Break;
+ var
+ uWADEditorFactory: TWADEditorFactory;
- if FileName <> nil then
- begin
- FileName^ := Copy(ResourceStr, 1, i-1);
- l1 := Length(FileName^);
- end
- else
- l1 := 0;
+ // EBNF:
+ // Resource = [Archive ":"] [{slash} Section {slash}slash] Name.
+ // slash = "/" | "\".
+ procedure g_ProcessResourceStr(ResourceStr: String; var FileName, SectionName, ResourceName: String);
+ begin
+ g_ProcessResourceStr(ResourceStr, @FileName, @SectionName, @ResourceName);
+ end;
+
+ procedure g_ProcessResourceStr(ResourceStr: AnsiString; FileName, SectionName, ResourceName: PAnsiString);
+ var i, j: Integer; sn: AnsiString;
+ begin
+ i := Max(1, LastDelimiter(':', ResourceStr));
- for a := i+1 to Length(ResourceStr) do
- if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break;
+ if FileName <> nil then
+ FileName^ := LeftStr(ResourceStr, i - 1);
- if ResourceName <> nil then
+ if (SectionName <> nil) or (ResourceName <> nil) then
begin
- ResourceName^ := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a));
- l2 := Length(ResourceName^);
- end
- else
- l2 := 0;
+ for i := i to High(ResourceStr) do
+ if ResourceStr[i] in ['\', '/', ':'] = False then
+ break;
+ sn := Copy(ResourceStr, i);
- if SectionName <> nil then
- SectionName^ := Copy(ResourceStr, i+1, Length(ResourceStr)-l2-l1-2);
-end;
+ j := LastDelimiter('/\', sn);
+ if ResourceName <> nil then
+ ResourceName^ := Copy(sn, j + 1);
-{ TWADEditor_1 }
+ if SectionName <> nil then
+ begin
+ for j := j downto 0 do
+ if (j > 0) and (sn[j] in ['\', '/'] = False) then
+ break;
+ if SectionName <> nil then
+ SectionName^ := LeftStr(sn, j);
+ end;
+ end;
+ end;
-function TWADEditor_1.AddResource(Data: Pointer; Len: LongWord; Name: string;
- Section: string): Boolean;
-var
- ResCompressed: Pointer;
- ResCompressedSize: Integer;
- a, b: Integer;
-begin
- Result := False;
+{ TWADEditor }
- SetLength(FResTable, Length(FResTable)+1);
+ function TWADEditor.ReadFile(FileName: String): Boolean;
+ var fname: String;
+ begin
+ fname := findFileCIStr(FileName);
+ Result := ReadFile2(fname);
+ end;
- if Section = '' then
- begin
- if Length(FResTable) > 1 then
- for a := High(FResTable) downto 1 do
- FResTable[a] := FResTable[a-1];
+{ TWADEditorMapping }
- a := 0;
- end
- else
- begin
- Section := AnsiUpperCase(Section);
- b := -1;
+ constructor TWADEditorMapping.CreateEx(const name: String; const eclass: TWADEditorClass);
+ begin
+ Create;
+ FName := name;
+ FWADEditorClass := eclass;
+ end;
- for a := 0 to High(FResTable) do
- if (FResTable[a].Length = 0) and (FResTable[a].ResourceName = Section) then
- begin
- for b := High(FResTable) downto a+2 do
- FResTable[b] := FResTable[b-1];
+{ TWADEditorFactory }
- b := a+1;
- Break;
- end;
-
- if b = -1 then
- begin
- SetLength(FResTable, Length(FResTable)-1);
- Exit;
- end;
- a := b;
- end;
-
- ResCompressed := nil;
- ResCompressedSize := 0;
- Compress(Data, @Len, ResCompressed, ResCompressedSize);
- if ResCompressed = nil then Exit;
-
- if FResData = nil then FResData := AllocMem(ResCompressedSize)
- else ReallocMem(FResData, FDataSize+Cardinal(ResCompressedSize));
-
- FDataSize := FDataSize+LongWord(ResCompressedSize);
-
- CopyMemory(Pointer(PChar(FResData)+FDataSize-PChar(ResCompressedSize)),
- ResCompressed, ResCompressedSize);
- FreeMemory(ResCompressed);
-
- Inc(FHeader.RecordsCount);
-
- with FResTable[a] do
- begin
- ResourceName := GetResName(Name);
- Address := FOffset;
- Length := ResCompressedSize;
- end;
-
- FOffset := FOffset+Cardinal(ResCompressedSize);
-
- Result := True;
-end;
-
-function TWADEditor_1.AddAlias(Res, Alias: string): Boolean;
-var
- a, b: Integer;
- ares: Char16;
-begin
- Result := False;
-
- if FResTable = nil then Exit;
-
- b := -1;
- ares := GetResName(Alias);
- for a := 0 to High(FResTable) do
- if FResTable[a].ResourceName = Res then
- begin
- b := a;
- Break;
- end;
-
- if b = -1 then Exit;
+ constructor TWADEditorFactory.Create;
+ begin
+ FMappings := TStringList.Create();
+ FDefault := nil;
+ end;
- Inc(FHeader.RecordsCount);
-
- SetLength(FResTable, Length(FResTable)+1);
-
- with FResTable[High(FResTable)] do
- begin
- ResourceName := ares;
- Address := FResTable[b].Address;
- Length := FResTable[b].Length;
- end;
-
- Result := True;
-end;
-
-function TWADEditor_1.AddResource(FileName, Name, Section: string): Boolean;
-var
- ResCompressed: Pointer;
- ResCompressedSize: Integer;
- ResourceFile: File;
- TempResource: Pointer;
- OriginalSize: Integer;
- a, b: Integer;
-begin
- Result := False;
-
- AssignFile(ResourceFile, FileName);
+ destructor TWADEditorFactory.Destroy;
+ var i: Integer;
+ begin
+ for i := 0 to FMappings.Count - 1 do
+ FMappings.Objects[i].Free();
+ FMappings.Free();
+ FDefault := nil;
+ end;
- try
- Reset(ResourceFile, 1);
- except
- FLastError := DFWAD_ERROR_CANTOPENWAD;
- Exit;
- end;
-
- OriginalSize := FileSize(ResourceFile);
- GetMem(TempResource, OriginalSize);
-
- try
- BlockRead(ResourceFile, TempResource^, OriginalSize);
- except
- FLastError := DFWAD_ERROR_READWAD;
- FreeMemory(TempResource);
- CloseFile(ResourceFile);
- Exit;
- end;
-
- CloseFile(ResourceFile);
-
- ResCompressed := nil;
- ResCompressedSize := 0;
- Compress(TempResource, @OriginalSize, ResCompressed, ResCompressedSize);
- FreeMemory(TempResource);
- if ResCompressed = nil then Exit;
-
- SetLength(FResTable, Length(FResTable)+1);
-
- if Section = '' then
- begin
- if Length(FResTable) > 1 then
- for a := High(FResTable) downto 1 do
- FResTable[a] := FResTable[a-1];
-
- a := 0;
- end
- else
- begin
- Section := AnsiUpperCase(Section);
- b := -1;
-
- for a := 0 to High(FResTable) do
- if (FResTable[a].Length = 0) and (FResTable[a].ResourceName = Section) then
- begin
- for b := High(FResTable) downto a+2 do
- FResTable[b] := FResTable[b-1];
-
- b := a+1;
- Break;
- end;
-
- if b = -1 then
- begin
- FreeMemory(ResCompressed);
- SetLength(FResTable, Length(FResTable)-1);
- Exit;
- end;
-
- a := b;
- end;
-
- if FResData = nil then FResData := AllocMem(ResCompressedSize)
- else ReallocMem(FResData, FDataSize+Cardinal(ResCompressedSize));
-
- FDataSize := FDataSize+LongWord(ResCompressedSize);
- CopyMemory(Pointer(PChar(FResData)+FDataSize-PChar(ResCompressedSize)),
- ResCompressed, ResCompressedSize);
- FreeMemory(ResCompressed);
-
- Inc(FHeader.RecordsCount);
-
- with FResTable[a] do
- begin
- ResourceName := GetResName(Name);
- Address := FOffset;
- Length := ResCompressedSize;
- end;
-
- FOffset := FOffset+Cardinal(ResCompressedSize);
-
- Result := True;
-end;
-
-procedure TWADEditor_1.AddSection(Name: string);
-begin
- if Name = '' then Exit;
-
- Inc(FHeader.RecordsCount);
-
- SetLength(FResTable, Length(FResTable)+1);
- with FResTable[High(FResTable)] do
- begin
- ResourceName := GetResName(Name);
- Address := $00000000;
- Length := $00000000;
- end;
-end;
-
-constructor TWADEditor_1.Create();
-begin
- FResData := nil;
- FResTable := nil;
- FDataSize := 0;
- FOffset := 0;
- FHeader.RecordsCount := 0;
- FFileName := '';
- FWADOpened := DFWAD_OPENED_NONE;
- FLastError := DFWAD_NOERROR;
- FVersion := DFWAD_VERSION;
-end;
-
-procedure TWADEditor_1.CreateImage();
-var
- WADFile: File;
- b: LongWord;
-begin
- if FWADOpened = DFWAD_OPENED_NONE then
- begin
- FLastError := DFWAD_ERROR_WADNOTLOADED;
- Exit;
- end;
-
- if FWADOpened = DFWAD_OPENED_MEMORY then Exit;
-
- if FResData <> nil then FreeMem(FResData);
-
- try
- AssignFile(WADFile, FFileName);
- Reset(WADFile, 1);
-
- b := 6+SizeOf(TWADHeaderRec_1)+SizeOf(TResourceTableRec_1)*Length(FResTable);
-
- FDataSize := LongWord(FileSize(WADFile))-b;
-
- GetMem(FResData, FDataSize);
-
- Seek(WADFile, b);
- BlockRead(WADFile, FResData^, FDataSize);
-
- CloseFile(WADFile);
-
- FOffset := FDataSize;
- except
- FLastError := DFWAD_ERROR_CANTOPENWAD;
- CloseFile(WADFile);
- Exit;
- end;
-
- FLastError := DFWAD_NOERROR;
-end;
-
-destructor TWADEditor_1.Destroy();
-begin
- FreeWAD();
-
- inherited;
-end;
-
-procedure TWADEditor_1.FreeWAD();
-begin
- if FResData <> nil then FreeMem(FResData);
- FResTable := nil;
- FDataSize := 0;
- FOffset := 0;
- FHeader.RecordsCount := 0;
- FFileName := '';
- FWADOpened := DFWAD_OPENED_NONE;
- FLastError := DFWAD_NOERROR;
- FVersion := DFWAD_VERSION;
-end;
-
-function TWADEditor_1.GetResName(ResName: string): Char16;
-begin
- ZeroMemory(@Result[0], 16);
- if ResName = '' then Exit;
-
- ResName := Trim(UpperCase(ResName));
- if Length(ResName) > 16 then SetLength(ResName, 16);
-
- CopyMemory(@Result[0], @ResName[1], Length(ResName));
-end;
-
-function TWADEditor_1.HaveResource(Section, Resource: string): Boolean;
-var
- a: Integer;
- CurrentSection: string;
-begin
- Result := False;
-
- if FResTable = nil then Exit;
-
- CurrentSection := '';
- Section := AnsiUpperCase(Section);
- Resource := AnsiUpperCase(Resource);
-
- for a := 0 to High(FResTable) do
- begin
- if FResTable[a].Length = 0 then
- begin
- CurrentSection := FResTable[a].ResourceName;
- Continue;
- end;
-
- if (FResTable[a].ResourceName = Resource) and
- (CurrentSection = Section) then
- begin
- Result := True;
- Break;
- end;
- end;
-end;
-
-function TWADEditor_1.HaveSection(Section: string): Boolean;
-var
- a: Integer;
-begin
- Result := False;
-
- if FResTable = nil then Exit;
- if Section = '' then
- begin
- Result := True;
- Exit;
- end;
-
- Section := AnsiUpperCase(Section);
-
- for a := 0 to High(FResTable) do
- if (FResTable[a].Length = 0) and (FResTable[a].ResourceName = Section) then
- begin
- Result := True;
- Exit;
- end;
-end;
-
-function TWADEditor_1.GetResource(Section, Resource: string;
- var pData: Pointer; var Len: Integer): Boolean;
-var
- a: LongWord;
- i: Integer;
- WADFile: File;
- CurrentSection: string;
- TempData: Pointer;
- OutBytes: Integer;
-begin
- Result := False;
+ procedure TWADEditorFactory.RegisterEditor(const name: String; const eclass: TWADEditorClass);
+ begin
+ if FMappings.IndexOf(UpperCase(name)) <> -1 then
+ raise Exception.Create('Registering a duplicate WAD Editor name <' + name + '>');
+ if FDefault = nil then
+ FDefault := eclass;
+ FMappings.AddObject(UpperCase(name), TWADEditorMapping.CreateEx(name, eclass));
+ end;
- CurrentSection := '';
-
- if FWADOpened = DFWAD_OPENED_NONE then
- begin
- FLastError := DFWAD_ERROR_WADNOTLOADED;
- Exit;
- end;
+ procedure TWADEditorFactory.SetDefaultEditor(const name: String);
+ var i: Integer;
+ begin
+ i := FMappings.IndexOf(UpperCase(name));
+ if i = -1 then
+ raise Exception.Create('No WAD Editor was registred by the name <' + name + '>');
+ FDefault := TWADEditorMapping(FMappings.Objects[i]).WADEditorClass;
+ end;
- Section := UpperCase(Section);
- Resource := UpperCase(Resource);
-
- i := -1;
- for a := 0 to High(FResTable) do
- begin
- if FResTable[a].Length = 0 then
- begin
- CurrentSection := FResTable[a].ResourceName;
- Continue;
+ function TWADEditorFactory.CreateEditor(const name: String): TWADEditor;
+ var i: Integer;
+ begin
+ if name = '' then
+ begin
+ Result := CreateDefaultEditor();
+ end
+ else
+ begin
+ i := FMappings.IndexOf(UpperCase(name));
+ if i = -1 then
+ raise Exception.Create('No WAD Editor was registred by the name <' + name + '>');
+ Result := TWADEditorMapping(FMappings.Objects[i]).WADEditorClass.Create();
+ end;
end;
- if (FResTable[a].ResourceName = Resource) and
- (CurrentSection = Section) then
+ function TWADEditorFactory.CreateDefaultEditor(): TWADEditor;
begin
- i := a;
- Break;
+ if FDefault = nil then
+ raise Exception.Create('No default WAD Editor was registred');
+ Result := FDefault.Create();
end;
- end;
- if i = -1 then
- begin
- FLastError := DFWAD_ERROR_RESOURCENOTFOUND;
- Exit;
- end;
-
- if FWADOpened = DFWAD_OPENED_FILE then
- begin
- try
- AssignFile(WADFile, FFileName);
- Reset(WADFile, 1);
-
- Seek(WADFile, FResTable[i].Address+6+
- LongWord(SizeOf(TWADHeaderRec_1)+SizeOf(TResourceTableRec_1)*Length(FResTable)));
- TempData := GetMemory(FResTable[i].Length);
- BlockRead(WADFile, TempData^, FResTable[i].Length);
- DecompressBuf(TempData, FResTable[i].Length, 0, pData, OutBytes);
- FreeMem(TempData);
-
- Len := OutBytes;
-
- CloseFile(WADFile);
- except
- FLastError := DFWAD_ERROR_CANTOPENWAD;
- CloseFile(WADFile);
- Exit;
- end;
- end
- else
- begin
- TempData := GetMemory(FResTable[i].Length);
- CopyMemory(TempData, Pointer(LongWord(FResData)+FResTable[i].Address+6+
- LongWord(SizeOf(TWADHeaderRec_1)+SizeOf(TResourceTableRec_1)*Length(FResTable))),
- FResTable[i].Length);
- DecompressBuf(TempData, FResTable[i].Length, 0, pData, OutBytes);
- FreeMem(TempData);
-
- Len := OutBytes;
- end;
-
- FLastError := DFWAD_NOERROR;
- Result := True;
-end;
-
-function TWADEditor_1.GetResourcesList(Section: string): SArray;
-var
- a: Integer;
- CurrentSection: Char16;
-begin
- Result := nil;
-
- if FResTable = nil then Exit;
- if Length(Section) > 16 then Exit;
-
- CurrentSection := '';
-
- for a := 0 to High(FResTable) do
- begin
- if FResTable[a].Length = 0 then
- begin
- CurrentSection := FResTable[a].ResourceName;
- Continue;
- end;
+ function TWADEditorFactory.OpenFile(FileName: String): TWADEditor;
+ var i: Integer; tmp: TWADEditor; fname: String;
+ begin
+ Result := nil;
+ if FMappings <> nil then
+ begin
+ fname := findFileCIStr(FileName);
+ for i := 0 to FMappings.Count - 1 do
+ begin
+ tmp := gWADEditorFactory.CreateEditor(FMappings[i]);
+ if tmp.ReadFile2(fname) then
+ begin
+ Result := tmp;
+ break;
+ end;
+ FreeAndNil(tmp);
+ end;
+ end;
+ end;
- if CurrentSection = Section then
+ function TWADEditorFactory.OpenMemory(Data: Pointer; Len: Integer): TWADEditor;
+ var i: Integer; tmp: TWADEditor;
begin
- SetLength(Result, Length(Result)+1);
- Result[High(Result)] := FResTable[a].ResourceName;
+ Result := nil;
+ if FMappings <> nil then
+ begin
+ for i := 0 to FMappings.Count - 1 do
+ begin
+ tmp := gWADEditorFactory.CreateEditor(FMappings[i]);
+ if tmp.ReadMemory(Data, Len) then
+ begin
+ Result := tmp;
+ break;
+ end;
+ FreeAndNil(tmp);
+ end;
+ end;
+ end;
+
+ procedure TWADEditorFactory.GetRegistredEditors(var list: TStringList);
+ var i: Integer;
+ begin
+ list.Clear();
+ for i := 0 to FMappings.Count - 1 do
+ list.Add(TWADEditorMapping(FMappings.Objects[i]).Name);
end;
- end;
-end;
-function TWADEditor_1.GetSectionList(): SArray;
-var
- i: DWORD;
-begin
- Result := nil;
+ function gWADEditorFactory: TWADEditorFactory;
+ begin
+ if not Assigned(uWADEditorFactory) then
+ uWADEditorFactory := TWADEditorFactory.Create();
+ Result := uWADEditorFactory;
+ end;
- if FResTable = nil then Exit;
+{ TWADEditor_1 }
- if FResTable[0].Length <> 0 then
- begin
- SetLength(Result, 1);
- Result[0] := '';
- end;
+ constructor TWADEditor_1.Create();
+ begin
+ FBase := gWADEditorFactory.CreateDefaultEditor();
+ end;
- for i := 0 to High(FResTable) do
- if FResTable[i].Length = 0 then
- begin
- SetLength(Result, Length(Result)+1);
- Result[High(Result)] := FResTable[i].ResourceName;
- end;
-end;
-
-function TWADEditor_1.LastErrorString(): string;
-begin
- case FLastError of
- DFWAD_NOERROR: Result := '';
- DFWAD_ERROR_WADNOTFOUND: Result := 'DFWAD file not found';
- DFWAD_ERROR_CANTOPENWAD: Result := 'Can''t open DFWAD file';
- DFWAD_ERROR_RESOURCENOTFOUND: Result := 'Resource not found';
- DFWAD_ERROR_FILENOTWAD: Result := 'File is not DFWAD';
- DFWAD_ERROR_WADNOTLOADED: Result := 'DFWAD file is not loaded';
- DFWAD_ERROR_READRESOURCE: Result := 'Read resource error';
- DFWAD_ERROR_READWAD: Result := 'Read DFWAD error';
- end;
-end;
-
-function TWADEditor_1.ReadFile(FileName: string): Boolean;
-var
- WADFile: File;
- Signature: array[0..4] of Char;
- a: Integer;
-begin
- FreeWAD();
-
- Result := False;
-
- if not FileExists(FileName) then
- begin
- FLastError := DFWAD_ERROR_WADNOTFOUND;
- Exit;
- end;
-
- FFileName := FileName;
-
- AssignFile(WADFile, FFileName);
-
- try
- Reset(WADFile, 1);
- except
- FLastError := DFWAD_ERROR_CANTOPENWAD;
- Exit;
- end;
-
- try
- BlockRead(WADFile, Signature, 5);
- if Signature <> DFWAD_SIGNATURE then
- begin
- FLastError := DFWAD_ERROR_FILENOTWAD;
- CloseFile(WADFile);
- Exit;
+ destructor TWADEditor_1.Destroy();
+ begin
+ if FBase <> nil then
+ FBase.Free();
+ inherited;
end;
- BlockRead(WADFile, FVersion, 1);
- if FVersion <> DFWAD_VERSION then
+ procedure TWADEditor_1.CreateImage();
begin
- FLastError := DFWAD_ERROR_WRONGVERSION;
- CloseFile(WADFile);
- Exit;
+ FBase.CreateImage();
end;
- BlockRead(WADFile, FHeader, SizeOf(TWADHeaderRec_1));
- SetLength(FResTable, FHeader.RecordsCount);
- if FResTable <> nil then
+ procedure TWADEditor_1.FreeWAD();
begin
- BlockRead(WADFile, FResTable[0], SizeOf(TResourceTableRec_1)*FHeader.RecordsCount);
+ FBase.FreeWAD();
+ end;
- for a := 0 to High(FResTable) do
- if FResTable[a].Length <> 0 then
- FResTable[a].Address := FResTable[a].Address-6-(LongWord(SizeOf(TWADHeaderRec_1)+
- SizeOf(TResourceTableRec_1)*Length(FResTable)));
+ function TWADEditor_1.ReadFile(FileName: String): Boolean;
+ var tmp: TWADEditor;
+ begin
+ Result := FBase.ReadFile(FileName);
+ if Result = False then
+ begin
+ tmp := gWADEditorFactory.OpenFile(FileName);
+ if tmp <> nil then
+ begin
+ FreeAndNil(FBase);
+ FBase := tmp;
+ Result := True;
+ end;
+ end;
end;
- CloseFile(WADFile);
- except
- FLastError := DFWAD_ERROR_READWAD;
- CloseFile(WADFile);
- Exit;
- end;
+ function TWADEditor_1.ReadMemory(Data: Pointer; Len: LongWord): Boolean;
+ var tmp: TWADEditor;
+ begin
+ Result := FBase.ReadMemory(Data, Len);
+ if Result = False then
+ begin
+ tmp := gWADEditorFactory.OpenMemory(Data, Len);
+ if tmp <> nil then
+ begin
+ FreeAndNil(FBase);
+ FBase := tmp;
+ Result := True;
+ end;
+ end;
+ end;
- FWADOpened := DFWAD_OPENED_FILE;
- FLastError := DFWAD_NOERROR;
- Result := True;
-end;
+ procedure TWADEditor_1.SaveTo(FileName: string);
+ var fname: AnsiString;
+ begin
+ fname := findFileCIStr(FileName);
+ FBase.SaveTo(fname);
+ end;
-function TWADEditor_1.ReadMemory(Data: Pointer; Len: LongWord): Boolean;
-var
- Signature: array[0..4] of Char;
- a: Integer;
-begin
- FreeWAD();
+ function TWADEditor_1.AddAlias(Res, Alias: string): Boolean;
+ begin
+ Result := FBase.AddAlias(Res, Alias);
+ end;
- Result := False;
+ function TWADEditor_1.AddResource(Data: Pointer; Len: LongWord; Name: string; Section: string): Boolean;
+ begin
+ Result := FBase.AddResource(Data, Len, Name, Section);
+ end;
- CopyMemory(@Signature[0], Data, 5);
- if Signature <> DFWAD_SIGNATURE then
- begin
- FLastError := DFWAD_ERROR_FILENOTWAD;
- Exit;
- end;
+ function TWADEditor_1.AddResource(FileName, Name, Section: string): Boolean;
+ var fname: AnsiString;
+ begin
+ fname := findFileCIStr(FileName);
+ Result := FBase.AddResource(fname, Name, Section);
+ end;
- CopyMemory(@FVersion, Pointer(LongWord(Data)+5), 1);
- if FVersion <> DFWAD_VERSION then
- begin
- FLastError := DFWAD_ERROR_WRONGVERSION;
- Exit;
- end;
-
- CopyMemory(@FHeader, Pointer(LongWord(Data)+6), SizeOf(TWADHeaderRec_1));
-
- SetLength(FResTable, FHeader.RecordsCount);
- if FResTable <> nil then
- begin
- CopyMemory(@FResTable[0], Pointer(LongWord(Data)+6+SizeOf(TWADHeaderRec_1)),
- SizeOf(TResourceTableRec_1)*FHeader.RecordsCount);
+ procedure TWADEditor_1.AddSection(Name: string);
+ begin
+ FBase.AddSection(Name);
+ end;
- for a := 0 to High(FResTable) do
- if FResTable[a].Length <> 0 then
- FResTable[a].Address := FResTable[a].Address-6-(LongWord(SizeOf(TWADHeaderRec_1)+
- SizeOf(TResourceTableRec_1)*Length(FResTable)));
- end;
+ function TWADEditor_1.GetSectionList(): SArray;
+ begin
+ Result := FBase.GetSectionList();
+ end;
- GetMem(FResData, Len);
- CopyMemory(FResData, Data, Len);
+ function TWADEditor_1.HaveSection(Section: string): Boolean;
+ begin
+ Result := FBase.HaveSection(Section);
+ end;
- FWADOpened := DFWAD_OPENED_MEMORY;
- FLastError := DFWAD_NOERROR;
+ function TWADEditor_1.GetResourcesList(Section: string): SArray;
+ begin
+ Result := FBase.GetResourcesList(Section);
+ end;
- Result := True;
-end;
+ function TWADEditor_1.HaveResource(Section, Resource: string): Boolean;
+ begin
+ Result := FBase.HaveResource(Section, Resource);
+ end;
-procedure TWADEditor_1.RemoveResource(Section, Resource: string);
-var
- a, i: Integer;
- CurrentSection: Char16;
- b, c, d: LongWord;
-begin
- if FResTable = nil then Exit;
+ function TWADEditor_1.GetResource(Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
+ begin
+ Result := FBase.GetResource(Section, Resource, pData, Len);
+ end;
- i := -1;
- b := 0;
- c := 0;
- CurrentSection := '';
+ procedure TWADEditor_1.RemoveResource(Section, Resource: string);
+ begin
+ FBase.RemoveResource(Section, Resource);
+ end;
- for a := 0 to High(FResTable) do
- begin
- if FResTable[a].Length = 0 then
+ function TWADEditor_1.GetLastError: Integer;
begin
- CurrentSection := FResTable[a].ResourceName;
- Continue;
+ Result := FBase.GetLastError();
end;
- if (FResTable[a].ResourceName = Resource) and
- (CurrentSection = Section) then
+ function TWADEditor_1.GetLastErrorStr: String;
begin
- i := a;
- b := FResTable[a].Length;
- c := FResTable[a].Address;
- Break;
+ Result := FBase.GetLastErrorStr();
end;
- end;
-
- if i = -1 then Exit;
-
- for a := i to High(FResTable)-1 do
- FResTable[a] := FResTable[a+1];
-
- SetLength(FResTable, Length(FResTable)-1);
-
- d := 0;
- for a := 0 to High(FResTable) do
- if (FResTable[a].Length <> 0) and (FResTable[a].Address > c) then
- begin
- FResTable[a].Address := FResTable[a].Address-b;
- d := d+FResTable[a].Length;
- end;
-
- CopyMemory(Pointer(LongWord(FResData)+c), Pointer(LongWord(FResData)+c+b), d);
-
- FDataSize := FDataSize-b;
- FOffset := FOffset-b;
- ReallocMem(FResData, FDataSize);
-
- FHeader.RecordsCount := FHeader.RecordsCount-1;
-end;
-
-procedure TWADEditor_1.SaveTo(FileName: string);
-var
- WADFile: File;
- sign: string;
- ver: Byte;
- Header: TWADHeaderRec_1;
- i: Integer;
-begin
- sign := DFWAD_SIGNATURE;
- ver := DFWAD_VERSION;
-
- Header.RecordsCount := Length(FResTable);
- if FResTable <> nil then
- for i := 0 to High(FResTable) do
- if FResTable[i].Length <> 0 then
- FResTable[i].Address := FResTable[i].Address+6+SizeOf(TWADHeaderRec_1)+
- SizeOf(TResourceTableRec_1)*Header.RecordsCount;
+ function TWADEditor_1.GetResourcesCount: Word;
+ begin
+ Result := FBase.GetResourcesCount();
+ end;
- AssignFile(WADFile, FileName);
- Rewrite(WADFile, 1);
- BlockWrite(WADFile, sign[1], 5);
- BlockWrite(WADFile, ver, 1);
- BlockWrite(WADFile, Header, SizeOf(TWADHeaderRec_1));
- if FResTable <> nil then BlockWrite(WADFile, FResTable[0],
- SizeOf(TResourceTableRec_1)*Header.RecordsCount);
- if FResData <> nil then BlockWrite(WADFile, FResData^, FDataSize);
- CloseFile(WADFile);
-end;
+ function TWADEditor_1.GetVersion: Byte;
+ begin
+ Result := FBase.GetVersion;
+ end;
+finalization
+ FreeAndNil(uWADEditorFactory);
end.