4 -----------------------------------
5 WADEDITOR.PAS ÂÅÐÑÈß ÎÒ 26.08.08
7 Ïîääåðæêà âàäîâ âåðñèè 1
8 -----------------------------------
12 -----------------------------------
13 WADSTRUCT.PAS ÂÅÐÑÈß ÎÒ 24.09.06
15 Ïîääåðæêà âàäîâ âåðñèè 1
16 -----------------------------------
18 Ñòðóêòóðà DFWAD-ôàéëà âåðñèè 1:
19 ------------------------------------------
20 SIGNATURE | Byte[5] | 'DFWAD'
22 HEADER | TWADHeaderRec_1 |
23 RESRECORD1 | TResourceTableRec_1 |
24 ... | ................... |
25 RESRECORDN | TResourceTableRec_1 |
27 ------------------------------------------
33 SArray
= array of ShortString;
34 Char16
= packed array[0..15] of Char;
36 TWADHeaderRec_1
= packed record
40 TResourceTableRec_1
= packed record
46 TWADEditor_1
= class(TObject
)
49 FResTable
: packed array of TResourceTableRec_1
;
50 FHeader
: TWADHeaderRec_1
;
57 function LastErrorString(): string;
58 function GetResName(ResName
: string): Char16
;
61 destructor Destroy(); override;
63 function ReadFile(FileName
: string): Boolean;
64 function ReadMemory(Data
: Pointer; Len
: LongWord): Boolean;
65 procedure CreateImage();
66 function AddResource(Data
: Pointer; Len
: LongWord; Name
: string;
67 Section
: string): Boolean; overload
;
68 function AddResource(FileName
, Name
, Section
: string): Boolean; overload
;
69 function AddAlias(Res
, Alias
: string): Boolean;
70 procedure AddSection(Name
: string);
71 procedure RemoveResource(Section
, Resource
: string);
72 procedure SaveTo(FileName
: string);
73 function HaveResource(Section
, Resource
: string): Boolean;
74 function HaveSection(Section
: string): Boolean;
75 function GetResource(Section
, Resource
: string; var pData
: Pointer;
76 var Len
: Integer): Boolean;
77 function GetSectionList(): SArray
;
78 function GetResourcesList(Section
: string): SArray
;
80 property GetLastError
: Integer read FLastError
;
81 property GetLastErrorStr
: string read LastErrorString
;
82 property GetResourcesCount
: Word read FHeader
.RecordsCount
;
83 property GetVersion
: Byte read FVersion
;
87 DFWAD_SIGNATURE
= 'DFWAD';
92 DFWAD_ERROR_WADNOTFOUND
= -1;
93 DFWAD_ERROR_CANTOPENWAD
= -2;
94 DFWAD_ERROR_RESOURCENOTFOUND
= -3;
95 DFWAD_ERROR_FILENOTWAD
= -4;
96 DFWAD_ERROR_WADNOTLOADED
= -5;
97 DFWAD_ERROR_READRESOURCE
= -6;
98 DFWAD_ERROR_READWAD
= -7;
99 DFWAD_ERROR_WRONGVERSION
= -8;
102 procedure g_ProcessResourceStr(ResourceStr
: String; var FileName
,
103 SectionName
, ResourceName
: String); overload
;
104 procedure g_ProcessResourceStr(ResourceStr
: String; FileName
,
105 SectionName
, ResourceName
: PString); overload
;
110 SysUtils
, BinEditor
, ZLib
;
113 DFWAD_OPENED_NONE
= 0;
114 DFWAD_OPENED_FILE
= 1;
115 DFWAD_OPENED_MEMORY
= 2;
117 procedure DecompressBuf(const InBuf
: Pointer; InBytes
: Integer;
118 OutEstimate
: Integer; out OutBuf
: Pointer; out OutBytes
: Integer);
124 FillChar(strm
, sizeof(strm
), 0);
125 BufInc
:= (InBytes
+ 255) and not 255;
126 if OutEstimate
= 0 then
129 OutBytes
:= OutEstimate
;
130 GetMem(OutBuf
, OutBytes
);
132 strm
.next_in
:= InBuf
;
133 strm
.avail_in
:= InBytes
;
134 strm
.next_out
:= OutBuf
;
135 strm
.avail_out
:= OutBytes
;
136 inflateInit_(strm
, zlib_version
, sizeof(strm
));
138 while inflate(strm
, Z_FINISH
) <> Z_STREAM_END
do
141 Inc(OutBytes
, BufInc
);
142 ReallocMem(OutBuf
, OutBytes
);
143 strm
.next_out
:= PByteF(PChar(OutBuf
) + (PChar(strm
.next_out
) - PChar(P
)));
144 strm
.avail_out
:= BufInc
;
149 ReallocMem(OutBuf
, strm
.total_out
);
150 OutBytes
:= strm
.total_out
;
157 procedure g_ProcessResourceStr(ResourceStr
: String; var FileName
,
158 SectionName
, ResourceName
: String);
163 for i
:= Length(ResourceStr
) downto 1 do
164 if ResourceStr
[i
] = ':' then
167 FileName
:= Copy(ResourceStr
, 1, i
-1);
169 for a
:= i
+1 to Length(ResourceStr
) do
170 if (ResourceStr
[a
] = '\') or (ResourceStr
[a
] = '/') then Break
;
172 ResourceName
:= Copy(ResourceStr
, a
+1, Length(ResourceStr
)-Abs(a
));
173 SectionName
:= Copy(ResourceStr
, i
+1, Length(ResourceStr
)-Length(ResourceName
)-Length(FileName
)-2);
176 procedure g_ProcessResourceStr(ResourceStr
: AnsiString; FileName
,
177 SectionName
, ResourceName
: PAnsiString);
179 a
, i
, l1
, l2
: Integer;
182 for i
:= Length(ResourceStr
) downto 1 do
183 if ResourceStr
[i
] = ':' then
186 if FileName
<> nil then
188 FileName
^ := Copy(ResourceStr
, 1, i
-1);
189 l1
:= Length(FileName
^);
194 for a
:= i
+1 to Length(ResourceStr
) do
195 if (ResourceStr
[a
] = '\') or (ResourceStr
[a
] = '/') then Break
;
197 if ResourceName
<> nil then
199 ResourceName
^ := Copy(ResourceStr
, a
+1, Length(ResourceStr
)-Abs(a
));
200 l2
:= Length(ResourceName
^);
205 if SectionName
<> nil then
206 SectionName
^ := Copy(ResourceStr
, i
+1, Length(ResourceStr
)-l2
-l1
-2);
211 function TWADEditor_1
.AddResource(Data
: Pointer; Len
: LongWord; Name
: string;
212 Section
: string): Boolean;
214 ResCompressed
: Pointer;
215 ResCompressedSize
: Integer;
220 SetLength(FResTable
, Length(FResTable
)+1);
224 if Length(FResTable
) > 1 then
225 for a
:= High(FResTable
) downto 1 do
226 FResTable
[a
] := FResTable
[a
-1];
232 Section
:= AnsiUpperCase(Section
);
235 for a
:= 0 to High(FResTable
) do
236 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
238 for b
:= High(FResTable
) downto a
+2 do
239 FResTable
[b
] := FResTable
[b
-1];
247 SetLength(FResTable
, Length(FResTable
)-1);
253 ResCompressed
:= nil;
254 ResCompressedSize
:= 0;
255 Compress(Data
, @Len
, ResCompressed
, ResCompressedSize
);
256 if ResCompressed
= nil then Exit
;
258 if FResData
= nil then FResData
:= AllocMem(ResCompressedSize
)
259 else ReallocMem(FResData
, FDataSize
+Cardinal(ResCompressedSize
));
261 FDataSize
:= FDataSize
+LongWord(ResCompressedSize
);
263 CopyMemory(Pointer(PChar(FResData
)+FDataSize
-PChar(ResCompressedSize
)),
264 ResCompressed
, ResCompressedSize
);
265 FreeMemory(ResCompressed
);
267 Inc(FHeader
.RecordsCount
);
271 ResourceName
:= GetResName(Name
);
273 Length
:= ResCompressedSize
;
276 FOffset
:= FOffset
+Cardinal(ResCompressedSize
);
281 function TWADEditor_1
.AddAlias(Res
, Alias
: string): Boolean;
288 if FResTable
= nil then Exit
;
291 ares
:= GetResName(Alias
);
292 for a
:= 0 to High(FResTable
) do
293 if FResTable
[a
].ResourceName
= Res
then
301 Inc(FHeader
.RecordsCount
);
303 SetLength(FResTable
, Length(FResTable
)+1);
305 with FResTable
[High(FResTable
)] do
307 ResourceName
:= ares
;
308 Address
:= FResTable
[b
].Address
;
309 Length
:= FResTable
[b
].Length
;
315 function TWADEditor_1
.AddResource(FileName
, Name
, Section
: string): Boolean;
317 ResCompressed
: Pointer;
318 ResCompressedSize
: Integer;
320 TempResource
: Pointer;
321 OriginalSize
: Integer;
326 AssignFile(ResourceFile
, FileName
);
329 Reset(ResourceFile
, 1);
331 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
335 OriginalSize
:= FileSize(ResourceFile
);
336 GetMem(TempResource
, OriginalSize
);
339 BlockRead(ResourceFile
, TempResource
^, OriginalSize
);
341 FLastError
:= DFWAD_ERROR_READWAD
;
342 FreeMemory(TempResource
);
343 CloseFile(ResourceFile
);
347 CloseFile(ResourceFile
);
349 ResCompressed
:= nil;
350 ResCompressedSize
:= 0;
351 Compress(TempResource
, @OriginalSize
, ResCompressed
, ResCompressedSize
);
352 FreeMemory(TempResource
);
353 if ResCompressed
= nil then Exit
;
355 SetLength(FResTable
, Length(FResTable
)+1);
359 if Length(FResTable
) > 1 then
360 for a
:= High(FResTable
) downto 1 do
361 FResTable
[a
] := FResTable
[a
-1];
367 Section
:= AnsiUpperCase(Section
);
370 for a
:= 0 to High(FResTable
) do
371 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
373 for b
:= High(FResTable
) downto a
+2 do
374 FResTable
[b
] := FResTable
[b
-1];
382 FreeMemory(ResCompressed
);
383 SetLength(FResTable
, Length(FResTable
)-1);
390 if FResData
= nil then FResData
:= AllocMem(ResCompressedSize
)
391 else ReallocMem(FResData
, FDataSize
+Cardinal(ResCompressedSize
));
393 FDataSize
:= FDataSize
+LongWord(ResCompressedSize
);
394 CopyMemory(Pointer(PChar(FResData
)+FDataSize
-PChar(ResCompressedSize
)),
395 ResCompressed
, ResCompressedSize
);
396 FreeMemory(ResCompressed
);
398 Inc(FHeader
.RecordsCount
);
402 ResourceName
:= GetResName(Name
);
404 Length
:= ResCompressedSize
;
407 FOffset
:= FOffset
+Cardinal(ResCompressedSize
);
412 procedure TWADEditor_1
.AddSection(Name
: string);
414 if Name
= '' then Exit
;
416 Inc(FHeader
.RecordsCount
);
418 SetLength(FResTable
, Length(FResTable
)+1);
419 with FResTable
[High(FResTable
)] do
421 ResourceName
:= GetResName(Name
);
422 Address
:= $00000000;
427 constructor TWADEditor_1
.Create();
433 FHeader
.RecordsCount
:= 0;
435 FWADOpened
:= DFWAD_OPENED_NONE
;
436 FLastError
:= DFWAD_NOERROR
;
437 FVersion
:= DFWAD_VERSION
;
440 procedure TWADEditor_1
.CreateImage();
445 if FWADOpened
= DFWAD_OPENED_NONE
then
447 FLastError
:= DFWAD_ERROR_WADNOTLOADED
;
451 if FWADOpened
= DFWAD_OPENED_MEMORY
then Exit
;
453 if FResData
<> nil then FreeMem(FResData
);
456 AssignFile(WADFile
, FFileName
);
459 b
:= 6+SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
);
461 FDataSize
:= LongWord(FileSize(WADFile
))-b
;
463 GetMem(FResData
, FDataSize
);
466 BlockRead(WADFile
, FResData
^, FDataSize
);
470 FOffset
:= FDataSize
;
472 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
477 FLastError
:= DFWAD_NOERROR
;
480 destructor TWADEditor_1
.Destroy();
487 procedure TWADEditor_1
.FreeWAD();
489 if FResData
<> nil then FreeMem(FResData
);
493 FHeader
.RecordsCount
:= 0;
495 FWADOpened
:= DFWAD_OPENED_NONE
;
496 FLastError
:= DFWAD_NOERROR
;
497 FVersion
:= DFWAD_VERSION
;
500 function TWADEditor_1
.GetResName(ResName
: string): Char16
;
502 ZeroMemory(@Result
[0], 16);
503 if ResName
= '' then Exit
;
505 ResName
:= Trim(UpperCase(ResName
));
506 if Length(ResName
) > 16 then SetLength(ResName
, 16);
508 CopyMemory(@Result
[0], @ResName
[1], Length(ResName
));
511 function TWADEditor_1
.HaveResource(Section
, Resource
: string): Boolean;
514 CurrentSection
: string;
518 if FResTable
= nil then Exit
;
520 CurrentSection
:= '';
521 Section
:= AnsiUpperCase(Section
);
522 Resource
:= AnsiUpperCase(Resource
);
524 for a
:= 0 to High(FResTable
) do
526 if FResTable
[a
].Length
= 0 then
528 CurrentSection
:= FResTable
[a
].ResourceName
;
532 if (FResTable
[a
].ResourceName
= Resource
) and
533 (CurrentSection
= Section
) then
541 function TWADEditor_1
.HaveSection(Section
: string): Boolean;
547 if FResTable
= nil then Exit
;
554 Section
:= AnsiUpperCase(Section
);
556 for a
:= 0 to High(FResTable
) do
557 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
564 function TWADEditor_1
.GetResource(Section
, Resource
: string;
565 var pData
: Pointer; var Len
: Integer): Boolean;
570 CurrentSection
: string;
576 CurrentSection
:= '';
578 if FWADOpened
= DFWAD_OPENED_NONE
then
580 FLastError
:= DFWAD_ERROR_WADNOTLOADED
;
584 Section
:= UpperCase(Section
);
585 Resource
:= UpperCase(Resource
);
588 for a
:= 0 to High(FResTable
) do
590 if FResTable
[a
].Length
= 0 then
592 CurrentSection
:= FResTable
[a
].ResourceName
;
596 if (FResTable
[a
].ResourceName
= Resource
) and
597 (CurrentSection
= Section
) then
606 FLastError
:= DFWAD_ERROR_RESOURCENOTFOUND
;
610 if FWADOpened
= DFWAD_OPENED_FILE
then
613 AssignFile(WADFile
, FFileName
);
616 Seek(WADFile
, FResTable
[i
].Address
+6+
617 LongWord(SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
618 TempData
:= GetMemory(FResTable
[i
].Length
);
619 BlockRead(WADFile
, TempData
^, FResTable
[i
].Length
);
620 DecompressBuf(TempData
, FResTable
[i
].Length
, 0, pData
, OutBytes
);
627 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
634 TempData
:= GetMemory(FResTable
[i
].Length
);
635 CopyMemory(TempData
, Pointer(LongWord(FResData
)+FResTable
[i
].Address
+6+
636 LongWord(SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
))),
637 FResTable
[i
].Length
);
638 DecompressBuf(TempData
, FResTable
[i
].Length
, 0, pData
, OutBytes
);
644 FLastError
:= DFWAD_NOERROR
;
648 function TWADEditor_1
.GetResourcesList(Section
: string): SArray
;
651 CurrentSection
: Char16
;
655 if FResTable
= nil then Exit
;
656 if Length(Section
) > 16 then Exit
;
658 CurrentSection
:= '';
660 for a
:= 0 to High(FResTable
) do
662 if FResTable
[a
].Length
= 0 then
664 CurrentSection
:= FResTable
[a
].ResourceName
;
668 if CurrentSection
= Section
then
670 SetLength(Result
, Length(Result
)+1);
671 Result
[High(Result
)] := FResTable
[a
].ResourceName
;
676 function TWADEditor_1
.GetSectionList(): SArray
;
682 if FResTable
= nil then Exit
;
684 if FResTable
[0].Length
<> 0 then
686 SetLength(Result
, 1);
690 for i
:= 0 to High(FResTable
) do
691 if FResTable
[i
].Length
= 0 then
693 SetLength(Result
, Length(Result
)+1);
694 Result
[High(Result
)] := FResTable
[i
].ResourceName
;
698 function TWADEditor_1
.LastErrorString(): string;
701 DFWAD_NOERROR
: Result
:= '';
702 DFWAD_ERROR_WADNOTFOUND
: Result
:= 'DFWAD file not found';
703 DFWAD_ERROR_CANTOPENWAD
: Result
:= 'Can''t open DFWAD file';
704 DFWAD_ERROR_RESOURCENOTFOUND
: Result
:= 'Resource not found';
705 DFWAD_ERROR_FILENOTWAD
: Result
:= 'File is not DFWAD';
706 DFWAD_ERROR_WADNOTLOADED
: Result
:= 'DFWAD file is not loaded';
707 DFWAD_ERROR_READRESOURCE
: Result
:= 'Read resource error';
708 DFWAD_ERROR_READWAD
: Result
:= 'Read DFWAD error';
709 else Result
:= 'Unknown DFWAD error';
713 function TWADEditor_1
.ReadFile(FileName
: string): Boolean;
716 Signature
: array[0..4] of Char;
723 if not FileExists(FileName
) then
725 FLastError
:= DFWAD_ERROR_WADNOTFOUND
;
729 FFileName
:= FileName
;
731 AssignFile(WADFile
, FFileName
);
736 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
741 BlockRead(WADFile
, Signature
, 5);
742 if Signature
<> DFWAD_SIGNATURE
then
744 FLastError
:= DFWAD_ERROR_FILENOTWAD
;
749 BlockRead(WADFile
, FVersion
, 1);
750 if FVersion
<> DFWAD_VERSION
then
752 FLastError
:= DFWAD_ERROR_WRONGVERSION
;
757 BlockRead(WADFile
, FHeader
, SizeOf(TWADHeaderRec_1
));
758 SetLength(FResTable
, FHeader
.RecordsCount
);
759 if FResTable
<> nil then
761 BlockRead(WADFile
, FResTable
[0], SizeOf(TResourceTableRec_1
)*FHeader
.RecordsCount
);
763 for a
:= 0 to High(FResTable
) do
764 if FResTable
[a
].Length
<> 0 then
765 FResTable
[a
].Address
:= FResTable
[a
].Address
-6-(LongWord(SizeOf(TWADHeaderRec_1
)+
766 SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
771 FLastError
:= DFWAD_ERROR_READWAD
;
776 FWADOpened
:= DFWAD_OPENED_FILE
;
777 FLastError
:= DFWAD_NOERROR
;
781 function TWADEditor_1
.ReadMemory(Data
: Pointer; Len
: LongWord): Boolean;
783 Signature
: array[0..4] of Char;
790 CopyMemory(@Signature
[0], Data
, 5);
791 if Signature
<> DFWAD_SIGNATURE
then
793 FLastError
:= DFWAD_ERROR_FILENOTWAD
;
797 CopyMemory(@FVersion
, Pointer(LongWord(Data
)+5), 1);
798 if FVersion
<> DFWAD_VERSION
then
800 FLastError
:= DFWAD_ERROR_WRONGVERSION
;
804 CopyMemory(@FHeader
, Pointer(LongWord(Data
)+6), SizeOf(TWADHeaderRec_1
));
806 SetLength(FResTable
, FHeader
.RecordsCount
);
807 if FResTable
<> nil then
809 CopyMemory(@FResTable
[0], Pointer(LongWord(Data
)+6+SizeOf(TWADHeaderRec_1
)),
810 SizeOf(TResourceTableRec_1
)*FHeader
.RecordsCount
);
812 for a
:= 0 to High(FResTable
) do
813 if FResTable
[a
].Length
<> 0 then
814 FResTable
[a
].Address
:= FResTable
[a
].Address
-6-(LongWord(SizeOf(TWADHeaderRec_1
)+
815 SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
818 GetMem(FResData
, Len
);
819 CopyMemory(FResData
, Data
, Len
);
821 FWADOpened
:= DFWAD_OPENED_MEMORY
;
822 FLastError
:= DFWAD_NOERROR
;
827 procedure TWADEditor_1
.RemoveResource(Section
, Resource
: string);
830 CurrentSection
: Char16
;
833 if FResTable
= nil then Exit
;
838 CurrentSection
:= '';
840 for a
:= 0 to High(FResTable
) do
842 if FResTable
[a
].Length
= 0 then
844 CurrentSection
:= FResTable
[a
].ResourceName
;
848 if (FResTable
[a
].ResourceName
= Resource
) and
849 (CurrentSection
= Section
) then
852 b
:= FResTable
[a
].Length
;
853 c
:= FResTable
[a
].Address
;
860 for a
:= i
to High(FResTable
)-1 do
861 FResTable
[a
] := FResTable
[a
+1];
863 SetLength(FResTable
, Length(FResTable
)-1);
866 for a
:= 0 to High(FResTable
) do
867 if (FResTable
[a
].Length
<> 0) and (FResTable
[a
].Address
> c
) then
869 FResTable
[a
].Address
:= FResTable
[a
].Address
-b
;
870 d
:= d
+FResTable
[a
].Length
;
873 CopyMemory(Pointer(LongWord(FResData
)+c
), Pointer(LongWord(FResData
)+c
+b
), d
);
875 FDataSize
:= FDataSize
-b
;
876 FOffset
:= FOffset
-b
;
877 ReallocMem(FResData
, FDataSize
);
879 FHeader
.RecordsCount
:= FHeader
.RecordsCount
-1;
882 procedure TWADEditor_1
.SaveTo(FileName
: string);
887 Header
: TWADHeaderRec_1
;
890 sign
:= DFWAD_SIGNATURE
;
891 ver
:= DFWAD_VERSION
;
893 Header
.RecordsCount
:= Length(FResTable
);
895 if FResTable
<> nil then
896 for i
:= 0 to High(FResTable
) do
897 if FResTable
[i
].Length
<> 0 then
898 FResTable
[i
].Address
:= FResTable
[i
].Address
+6+SizeOf(TWADHeaderRec_1
)+
899 SizeOf(TResourceTableRec_1
)*Header
.RecordsCount
;
901 AssignFile(WADFile
, FileName
);
903 BlockWrite(WADFile
, sign
[1], 5);
904 BlockWrite(WADFile
, ver
, 1);
905 BlockWrite(WADFile
, Header
, SizeOf(TWADHeaderRec_1
));
906 if FResTable
<> nil then BlockWrite(WADFile
, FResTable
[0],
907 SizeOf(TResourceTableRec_1
)*Header
.RecordsCount
);
908 if FResData
<> nil then BlockWrite(WADFile
, FResData
^, FDataSize
);