X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fshared%2FWADEDITOR.pas;h=30b3260bfa20cb88b4cec54af788addae9de8bbf;hb=28a8176757c9c5ac298c8986a7b35a5ed7ccc5fd;hp=e68fd21bcdee1c7d63ced3b086fb58abf80cd09d;hpb=3dc2fe6b3d29cd54425db8f590e922f2dce50e99;p=d2df-editor.git diff --git a/src/shared/WADEDITOR.pas b/src/shared/WADEDITOR.pas index e68fd21..30b3260 100644 --- a/src/shared/WADEDITOR.pas +++ b/src/shared/WADEDITOR.pas @@ -1,919 +1,441 @@ -unit WADEDITOR; +{$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, utils, e_log; - -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 CompressBuf(const InBuf: Pointer; InBytes: Integer; - out OutBuf: Pointer; out OutBytes: Integer); -var - strm: TZStreamRec; - P: Pointer; -begin - FillChar(strm, sizeof(strm), 0); - OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255; - GetMem(OutBuf, OutBytes); - try - strm.next_in := InBuf; - strm.avail_in := InBytes; - strm.next_out := OutBuf; - strm.avail_out := OutBytes; - deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)); - try - while deflate(strm, Z_FINISH) <> Z_STREAM_END do - begin - P := OutBuf; - Inc(OutBytes, 256); - ReallocMem(OutBuf, OutBytes); - strm.next_out := PByteF(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); - strm.avail_out := 256; - end; - finally - deflateEnd(strm); + + 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; - 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; + // 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; -begin - for i := Length(ResourceStr) downto 1 do - if ResourceStr[i] = ':' then - Break; + procedure g_ProcessResourceStr(ResourceStr: String; var FileName, SectionName, ResourceName: String); overload; + procedure g_ProcessResourceStr(ResourceStr: String; FileName, SectionName, ResourceName: PString); overload; - FileName := Copy(ResourceStr, 1, i-1); + function gWADEditorFactory: TWADEditorFactory; - for a := i+1 to Length(ResourceStr) do - if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break; +implementation - ResourceName := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a)); - SectionName := Copy(ResourceStr, i+1, Length(ResourceStr)-Length(ResourceName)-Length(FileName)-2); -end; + uses SysUtils, Math, utils; -procedure g_ProcessResourceStr(ResourceStr: AnsiString; FileName, - SectionName, ResourceName: PAnsiString); -var - a, i, l1, l2: Integer; + var + uWADEditorFactory: TWADEditorFactory; -begin - for i := Length(ResourceStr) downto 1 do - if ResourceStr[i] = ':' then - Break; + // 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; - if FileName <> nil then - begin - FileName^ := Copy(ResourceStr, 1, i-1); - l1 := Length(FileName^); - end - else - l1 := 0; + 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; - - if SectionName <> nil then - SectionName^ := Copy(ResourceStr, i+1, Length(ResourceStr)-l2-l1-2); -end; + for i := i to High(ResourceStr) do + if ResourceStr[i] in ['\', '/', ':'] = False then + break; + sn := Copy(ResourceStr, i); -{ TWADEditor_1 } + j := LastDelimiter('/\', sn); + if ResourceName <> nil then + ResourceName^ := Copy(sn, j + 1); -function TWADEditor_1.AddResource(Data: Pointer; Len: LongWord; Name: string; - Section: string): Boolean; -var - ResCompressed: Pointer; - ResCompressedSize: Integer; - a, b: Integer; -begin - Result := False; + 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; - SetLength(FResTable, Length(FResTable)+1); +{ TWADEditor } - if Section = '' then - begin - if Length(FResTable) > 1 then - for a := High(FResTable) downto 1 do - FResTable[a] := FResTable[a-1]; + function TWADEditor.ReadFile(FileName: String): Boolean; + var fname: String; + begin + fname := findFileCIStr(FileName); + Result := ReadFile2(fname); + end; - 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]; +{ TWADEditorMapping } - b := a+1; - Break; - end; - - if b = -1 then - begin - SetLength(FResTable, Length(FResTable)-1); - Exit; - end; - a := b; - end; - - ResCompressed := nil; - ResCompressedSize := 0; - CompressBuf(Data, Len, ResCompressed, ResCompressedSize); - if ResCompressed = nil then Exit; - e_WriteLog('Fuck me (D)', MSG_NOTIFY); - - 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; - - 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, findFileCIStr(FileName)); - - 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; - CompressBuf(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, findFileCIStr(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; + constructor TWADEditorMapping.CreateEx(const name: String; const eclass: TWADEditorClass); + begin + Create; + FName := name; + FWADEditorClass := eclass; + end; - CurrentSection := ''; - - if FWADOpened = DFWAD_OPENED_NONE then - begin - FLastError := DFWAD_ERROR_WADNOTLOADED; - Exit; - end; +{ TWADEditorFactory } - 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; + constructor TWADEditorFactory.Create; + begin + FMappings := TStringList.Create(); + FDefault := nil; end; - if (FResTable[a].ResourceName = Resource) and - (CurrentSection = Section) then + destructor TWADEditorFactory.Destroy; + var i: Integer; begin - i := a; - Break; - end; - end; - - if i = -1 then - begin - FLastError := DFWAD_ERROR_RESOURCENOTFOUND; - Exit; - end; - - if FWADOpened = DFWAD_OPENED_FILE then - begin - try - AssignFile(WADFile, findFileCIStr(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(PtrUInt(FResData)+FResTable[i].Address+6+ - PtrUInt(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; + for i := 0 to FMappings.Count - 1 do + FMappings.Objects[i].Free(); + FMappings.Free(); + FDefault := nil; end; - if CurrentSection = Section then + procedure TWADEditorFactory.RegisterEditor(const name: String; const eclass: TWADEditorClass); begin - SetLength(Result, Length(Result)+1); - Result[High(Result)] := FResTable[a].ResourceName; + 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; - end; -end; - -function TWADEditor_1.GetSectionList(): SArray; -var - i: DWORD; -begin - Result := nil; - - if FResTable = nil then Exit; - - if FResTable[0].Length <> 0 then - begin - SetLength(Result, 1); - Result[0] := ''; - 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, findFileCIStr(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; - end; - - BlockRead(WADFile, FVersion, 1); - if FVersion <> DFWAD_VERSION then + procedure TWADEditorFactory.SetDefaultEditor(const name: String); + var i: Integer; begin - FLastError := DFWAD_ERROR_WRONGVERSION; - CloseFile(WADFile); - Exit; + 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; - BlockRead(WADFile, FHeader, SizeOf(TWADHeaderRec_1)); - SetLength(FResTable, FHeader.RecordsCount); - if FResTable <> nil then + function TWADEditorFactory.CreateEditor(const name: String): TWADEditor; + var i: Integer; begin - BlockRead(WADFile, FResTable[0], SizeOf(TResourceTableRec_1)*FHeader.RecordsCount); + 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; - 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 TWADEditorFactory.CreateDefaultEditor(): TWADEditor; + begin + if FDefault = nil then + raise Exception.Create('No default WAD Editor was registred'); + Result := FDefault.Create(); end; - CloseFile(WADFile); - except - FLastError := DFWAD_ERROR_READWAD; - CloseFile(WADFile); - Exit; - 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; - FWADOpened := DFWAD_OPENED_FILE; - FLastError := DFWAD_NOERROR; - Result := True; -end; + function TWADEditorFactory.OpenMemory(Data: Pointer; Len: Integer): TWADEditor; + var i: Integer; tmp: TWADEditor; + begin + 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; -function TWADEditor_1.ReadMemory(Data: Pointer; Len: LongWord): Boolean; -var - Signature: array[0..4] of Char; - a: Integer; -begin - FreeWAD(); + 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; - Result := False; + function gWADEditorFactory: TWADEditorFactory; + begin + if not Assigned(uWADEditorFactory) then + uWADEditorFactory := TWADEditorFactory.Create(); + Result := uWADEditorFactory; + end; - CopyMemory(@Signature[0], Data, 5); - if Signature <> DFWAD_SIGNATURE then - begin - FLastError := DFWAD_ERROR_FILENOTWAD; - Exit; - end; +{ TWADEditor_1 } - CopyMemory(@FVersion, Pointer(PtrUInt(Data)+5), 1); - if FVersion <> DFWAD_VERSION then - begin - FLastError := DFWAD_ERROR_WRONGVERSION; - Exit; - end; + constructor TWADEditor_1.Create(); + begin + FBase := gWADEditorFactory.CreateDefaultEditor(); + end; - CopyMemory(@FHeader, Pointer(PtrUInt(Data)+6), SizeOf(TWADHeaderRec_1)); + destructor TWADEditor_1.Destroy(); + begin + if FBase <> nil then + FBase.Free(); + inherited; + end; - SetLength(FResTable, FHeader.RecordsCount); - if FResTable <> nil then - begin - CopyMemory(@FResTable[0], Pointer(PtrUInt(Data)+6+SizeOf(TWADHeaderRec_1)), - SizeOf(TResourceTableRec_1)*FHeader.RecordsCount); + procedure TWADEditor_1.CreateImage(); + begin + FBase.CreateImage(); + 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; + procedure TWADEditor_1.FreeWAD(); + begin + FBase.FreeWAD(); + end; - GetMem(FResData, Len); - CopyMemory(FResData, Data, Len); + 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; - FWADOpened := DFWAD_OPENED_MEMORY; - FLastError := DFWAD_NOERROR; + 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; - Result := True; -end; + procedure TWADEditor_1.SaveTo(FileName: string); + var fname: AnsiString; + begin + fname := findFileCIStr(FileName); + FBase.SaveTo(fname); + 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.AddAlias(Res, Alias: string): Boolean; + begin + Result := FBase.AddAlias(Res, Alias); + end; - e_WriteLog('Fuck me (B) ' + Section + ' ' + Resource, MSG_NOTIFY); + function TWADEditor_1.AddResource(Data: Pointer; Len: LongWord; Name: string; Section: string): Boolean; + begin + Result := FBase.AddResource(Data, Len, Name, Section); + end; - i := -1; - b := 0; - c := 0; - CurrentSection := ''; + function TWADEditor_1.AddResource(FileName, Name, Section: string): Boolean; + var fname: AnsiString; + begin + fname := findFileCIStr(FileName); + Result := FBase.AddResource(fname, Name, Section); + end; - for a := 0 to High(FResTable) do - begin - if FResTable[a].Length = 0 then + procedure TWADEditor_1.AddSection(Name: string); begin - CurrentSection := FResTable[a].ResourceName; - Continue; + FBase.AddSection(Name); end; - if (FResTable[a].ResourceName = Resource) and - (CurrentSection = Section) then + function TWADEditor_1.GetSectionList(): SArray; begin - i := a; - b := FResTable[a].Length; - c := FResTable[a].Address; - Break; + Result := FBase.GetSectionList(); end; - end; - if i = -1 then Exit; + function TWADEditor_1.HaveSection(Section: string): Boolean; + begin + Result := FBase.HaveSection(Section); + end; - e_WriteLog('Fuck me (C) ' + Section + ' ' + Resource, MSG_NOTIFY); - - for a := i to High(FResTable)-1 do - FResTable[a] := FResTable[a+1]; + function TWADEditor_1.GetResourcesList(Section: string): SArray; + begin + Result := FBase.GetResourcesList(Section); + end; - 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; + function TWADEditor_1.HaveResource(Section, Resource: string): Boolean; + begin + Result := FBase.HaveResource(Section, Resource); end; - CopyMemory(Pointer(PtrUInt(FResData)+c), Pointer(PtrUInt(FResData)+c+b), d); - - FDataSize := FDataSize-b; - FOffset := FOffset-b; - ReallocMem(FResData, FDataSize); + function TWADEditor_1.GetResource(Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean; + begin + Result := FBase.GetResource(Section, Resource, pData, Len); + end; - FHeader.RecordsCount := FHeader.RecordsCount-1; -end; + procedure TWADEditor_1.RemoveResource(Section, Resource: string); + begin + FBase.RemoveResource(Section, Resource); + 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; + function TWADEditor_1.GetLastError: Integer; + begin + Result := FBase.GetLastError(); + end; - Header.RecordsCount := Length(FResTable); + function TWADEditor_1.GetLastErrorStr: String; + begin + Result := FBase.GetLastErrorStr(); + end; - 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.