5 -----------------------------------
6 WADEDITOR.PAS ÂÅÐÑÈß ÎÒ 26.08.08
8 Ïîääåðæêà âàäîâ âåðñèè 1
9 -----------------------------------
13 -----------------------------------
14 WADSTRUCT.PAS ÂÅÐÑÈß ÎÒ 24.09.06
16 Ïîääåðæêà âàäîâ âåðñèè 1
17 -----------------------------------
19 Ñòðóêòóðà DFWAD-ôàéëà âåðñèè 1:
20 ------------------------------------------
21 SIGNATURE | Byte[5] | 'DFWAD'
23 HEADER | TWADHeaderRec_1 |
24 RESRECORD1 | TResourceTableRec_1 |
25 ... | ................... |
26 RESRECORDN | TResourceTableRec_1 |
28 ------------------------------------------
34 SArray
= array of ShortString;
35 Char16
= packed array[0..15] of Char;
37 TWADHeaderRec_1
= packed record
41 TResourceTableRec_1
= packed record
47 TWADEditor_1
= class(TObject
)
50 FResTable
: packed array of TResourceTableRec_1
;
51 FHeader
: TWADHeaderRec_1
;
58 function LastErrorString(): string;
59 function GetResName(ResName
: string): Char16
;
62 destructor Destroy(); override;
64 function ReadFile(FileName
: string): Boolean;
65 function ReadMemory(Data
: Pointer; Len
: LongWord): Boolean;
66 procedure CreateImage();
67 function AddResource(Data
: Pointer; Len
: LongWord; Name
: string;
68 Section
: string): Boolean; overload
;
69 function AddResource(FileName
, Name
, Section
: string): Boolean; overload
;
70 function AddAlias(Res
, Alias
: string): Boolean;
71 procedure AddSection(Name
: string);
72 procedure RemoveResource(Section
, Resource
: string);
73 procedure SaveTo(FileName
: string);
74 function HaveResource(Section
, Resource
: string): Boolean;
75 function HaveSection(Section
: string): Boolean;
76 function GetResource(Section
, Resource
: string; var pData
: Pointer;
77 var Len
: Integer): Boolean;
78 function GetSectionList(): SArray
;
79 function GetResourcesList(Section
: string): SArray
;
81 property GetLastError
: Integer read FLastError
;
82 property GetLastErrorStr
: string read LastErrorString
;
83 property GetResourcesCount
: Word read FHeader
.RecordsCount
;
84 property GetVersion
: Byte read FVersion
;
88 DFWAD_SIGNATURE
= 'DFWAD';
93 DFWAD_ERROR_WADNOTFOUND
= -1;
94 DFWAD_ERROR_CANTOPENWAD
= -2;
95 DFWAD_ERROR_RESOURCENOTFOUND
= -3;
96 DFWAD_ERROR_FILENOTWAD
= -4;
97 DFWAD_ERROR_WADNOTLOADED
= -5;
98 DFWAD_ERROR_READRESOURCE
= -6;
99 DFWAD_ERROR_READWAD
= -7;
100 DFWAD_ERROR_WRONGVERSION
= -8;
103 procedure g_ProcessResourceStr(ResourceStr
: String; var FileName
,
104 SectionName
, ResourceName
: String); overload
;
105 procedure g_ProcessResourceStr(ResourceStr
: String; FileName
,
106 SectionName
, ResourceName
: PString); overload
;
111 SysUtils
, BinEditor
, ZLib
;
114 DFWAD_OPENED_NONE
= 0;
115 DFWAD_OPENED_FILE
= 1;
116 DFWAD_OPENED_MEMORY
= 2;
118 procedure DecompressBuf(const InBuf
: Pointer; InBytes
: Integer;
119 OutEstimate
: Integer; out OutBuf
: Pointer; out OutBytes
: Integer);
125 FillChar(strm
, sizeof(strm
), 0);
126 BufInc
:= (InBytes
+ 255) and not 255;
127 if OutEstimate
= 0 then
130 OutBytes
:= OutEstimate
;
131 GetMem(OutBuf
, OutBytes
);
133 strm
.next_in
:= InBuf
;
134 strm
.avail_in
:= InBytes
;
135 strm
.next_out
:= OutBuf
;
136 strm
.avail_out
:= OutBytes
;
137 inflateInit_(strm
, zlib_version
, sizeof(strm
));
139 while inflate(strm
, Z_FINISH
) <> Z_STREAM_END
do
142 Inc(OutBytes
, BufInc
);
143 ReallocMem(OutBuf
, OutBytes
);
144 strm
.next_out
:= PByteF(PChar(OutBuf
) + (PChar(strm
.next_out
) - PChar(P
)));
145 strm
.avail_out
:= BufInc
;
150 ReallocMem(OutBuf
, strm
.total_out
);
151 OutBytes
:= strm
.total_out
;
158 procedure g_ProcessResourceStr(ResourceStr
: String; var FileName
,
159 SectionName
, ResourceName
: String);
164 for i
:= Length(ResourceStr
) downto 1 do
165 if ResourceStr
[i
] = ':' then
168 FileName
:= Copy(ResourceStr
, 1, i
-1);
170 for a
:= i
+1 to Length(ResourceStr
) do
171 if (ResourceStr
[a
] = '\') or (ResourceStr
[a
] = '/') then Break
;
173 ResourceName
:= Copy(ResourceStr
, a
+1, Length(ResourceStr
)-Abs(a
));
174 SectionName
:= Copy(ResourceStr
, i
+1, Length(ResourceStr
)-Length(ResourceName
)-Length(FileName
)-2);
177 procedure g_ProcessResourceStr(ResourceStr
: AnsiString; FileName
,
178 SectionName
, ResourceName
: PAnsiString);
180 a
, i
, l1
, l2
: Integer;
183 for i
:= Length(ResourceStr
) downto 1 do
184 if ResourceStr
[i
] = ':' then
187 if FileName
<> nil then
189 FileName
^ := Copy(ResourceStr
, 1, i
-1);
190 l1
:= Length(FileName
^);
195 for a
:= i
+1 to Length(ResourceStr
) do
196 if (ResourceStr
[a
] = '\') or (ResourceStr
[a
] = '/') then Break
;
198 if ResourceName
<> nil then
200 ResourceName
^ := Copy(ResourceStr
, a
+1, Length(ResourceStr
)-Abs(a
));
201 l2
:= Length(ResourceName
^);
206 if SectionName
<> nil then
207 SectionName
^ := Copy(ResourceStr
, i
+1, Length(ResourceStr
)-l2
-l1
-2);
212 function TWADEditor_1
.AddResource(Data
: Pointer; Len
: LongWord; Name
: string;
213 Section
: string): Boolean;
215 ResCompressed
: Pointer;
216 ResCompressedSize
: Integer;
221 SetLength(FResTable
, Length(FResTable
)+1);
225 if Length(FResTable
) > 1 then
226 for a
:= High(FResTable
) downto 1 do
227 FResTable
[a
] := FResTable
[a
-1];
233 Section
:= AnsiUpperCase(Section
);
236 for a
:= 0 to High(FResTable
) do
237 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
239 for b
:= High(FResTable
) downto a
+2 do
240 FResTable
[b
] := FResTable
[b
-1];
248 SetLength(FResTable
, Length(FResTable
)-1);
254 ResCompressed
:= nil;
255 ResCompressedSize
:= 0;
256 Compress(Data
, @Len
, ResCompressed
, ResCompressedSize
);
257 if ResCompressed
= nil then Exit
;
259 if FResData
= nil then FResData
:= AllocMem(ResCompressedSize
)
260 else ReallocMem(FResData
, FDataSize
+Cardinal(ResCompressedSize
));
262 FDataSize
:= FDataSize
+LongWord(ResCompressedSize
);
264 CopyMemory(Pointer(PChar(FResData
)+FDataSize
-PChar(ResCompressedSize
)),
265 ResCompressed
, ResCompressedSize
);
266 FreeMemory(ResCompressed
);
268 Inc(FHeader
.RecordsCount
);
272 ResourceName
:= GetResName(Name
);
274 Length
:= ResCompressedSize
;
277 FOffset
:= FOffset
+Cardinal(ResCompressedSize
);
282 function TWADEditor_1
.AddAlias(Res
, Alias
: string): Boolean;
289 if FResTable
= nil then Exit
;
292 ares
:= GetResName(Alias
);
293 for a
:= 0 to High(FResTable
) do
294 if FResTable
[a
].ResourceName
= Res
then
302 Inc(FHeader
.RecordsCount
);
304 SetLength(FResTable
, Length(FResTable
)+1);
306 with FResTable
[High(FResTable
)] do
308 ResourceName
:= ares
;
309 Address
:= FResTable
[b
].Address
;
310 Length
:= FResTable
[b
].Length
;
316 function TWADEditor_1
.AddResource(FileName
, Name
, Section
: string): Boolean;
318 ResCompressed
: Pointer;
319 ResCompressedSize
: Integer;
321 TempResource
: Pointer;
322 OriginalSize
: Integer;
327 AssignFile(ResourceFile
, FileName
);
330 Reset(ResourceFile
, 1);
332 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
336 OriginalSize
:= FileSize(ResourceFile
);
337 GetMem(TempResource
, OriginalSize
);
340 BlockRead(ResourceFile
, TempResource
^, OriginalSize
);
342 FLastError
:= DFWAD_ERROR_READWAD
;
343 FreeMemory(TempResource
);
344 CloseFile(ResourceFile
);
348 CloseFile(ResourceFile
);
350 ResCompressed
:= nil;
351 ResCompressedSize
:= 0;
352 Compress(TempResource
, @OriginalSize
, ResCompressed
, ResCompressedSize
);
353 FreeMemory(TempResource
);
354 if ResCompressed
= nil then Exit
;
356 SetLength(FResTable
, Length(FResTable
)+1);
360 if Length(FResTable
) > 1 then
361 for a
:= High(FResTable
) downto 1 do
362 FResTable
[a
] := FResTable
[a
-1];
368 Section
:= AnsiUpperCase(Section
);
371 for a
:= 0 to High(FResTable
) do
372 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
374 for b
:= High(FResTable
) downto a
+2 do
375 FResTable
[b
] := FResTable
[b
-1];
383 FreeMemory(ResCompressed
);
384 SetLength(FResTable
, Length(FResTable
)-1);
391 if FResData
= nil then FResData
:= AllocMem(ResCompressedSize
)
392 else ReallocMem(FResData
, FDataSize
+Cardinal(ResCompressedSize
));
394 FDataSize
:= FDataSize
+LongWord(ResCompressedSize
);
395 CopyMemory(Pointer(PChar(FResData
)+FDataSize
-PChar(ResCompressedSize
)),
396 ResCompressed
, ResCompressedSize
);
397 FreeMemory(ResCompressed
);
399 Inc(FHeader
.RecordsCount
);
403 ResourceName
:= GetResName(Name
);
405 Length
:= ResCompressedSize
;
408 FOffset
:= FOffset
+Cardinal(ResCompressedSize
);
413 procedure TWADEditor_1
.AddSection(Name
: string);
415 if Name
= '' then Exit
;
417 Inc(FHeader
.RecordsCount
);
419 SetLength(FResTable
, Length(FResTable
)+1);
420 with FResTable
[High(FResTable
)] do
422 ResourceName
:= GetResName(Name
);
423 Address
:= $00000000;
428 constructor TWADEditor_1
.Create();
434 FHeader
.RecordsCount
:= 0;
436 FWADOpened
:= DFWAD_OPENED_NONE
;
437 FLastError
:= DFWAD_NOERROR
;
438 FVersion
:= DFWAD_VERSION
;
441 procedure TWADEditor_1
.CreateImage();
446 if FWADOpened
= DFWAD_OPENED_NONE
then
448 FLastError
:= DFWAD_ERROR_WADNOTLOADED
;
452 if FWADOpened
= DFWAD_OPENED_MEMORY
then Exit
;
454 if FResData
<> nil then FreeMem(FResData
);
457 AssignFile(WADFile
, FFileName
);
460 b
:= 6+SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
);
462 FDataSize
:= LongWord(FileSize(WADFile
))-b
;
464 GetMem(FResData
, FDataSize
);
467 BlockRead(WADFile
, FResData
^, FDataSize
);
471 FOffset
:= FDataSize
;
473 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
478 FLastError
:= DFWAD_NOERROR
;
481 destructor TWADEditor_1
.Destroy();
488 procedure TWADEditor_1
.FreeWAD();
490 if FResData
<> nil then FreeMem(FResData
);
494 FHeader
.RecordsCount
:= 0;
496 FWADOpened
:= DFWAD_OPENED_NONE
;
497 FLastError
:= DFWAD_NOERROR
;
498 FVersion
:= DFWAD_VERSION
;
501 function TWADEditor_1
.GetResName(ResName
: string): Char16
;
503 ZeroMemory(@Result
[0], 16);
504 if ResName
= '' then Exit
;
506 ResName
:= Trim(UpperCase(ResName
));
507 if Length(ResName
) > 16 then SetLength(ResName
, 16);
509 CopyMemory(@Result
[0], @ResName
[1], Length(ResName
));
512 function TWADEditor_1
.HaveResource(Section
, Resource
: string): Boolean;
515 CurrentSection
: string;
519 if FResTable
= nil then Exit
;
521 CurrentSection
:= '';
522 Section
:= AnsiUpperCase(Section
);
523 Resource
:= AnsiUpperCase(Resource
);
525 for a
:= 0 to High(FResTable
) do
527 if FResTable
[a
].Length
= 0 then
529 CurrentSection
:= FResTable
[a
].ResourceName
;
533 if (FResTable
[a
].ResourceName
= Resource
) and
534 (CurrentSection
= Section
) then
542 function TWADEditor_1
.HaveSection(Section
: string): Boolean;
548 if FResTable
= nil then Exit
;
555 Section
:= AnsiUpperCase(Section
);
557 for a
:= 0 to High(FResTable
) do
558 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
565 function TWADEditor_1
.GetResource(Section
, Resource
: string;
566 var pData
: Pointer; var Len
: Integer): Boolean;
571 CurrentSection
: string;
577 CurrentSection
:= '';
579 if FWADOpened
= DFWAD_OPENED_NONE
then
581 FLastError
:= DFWAD_ERROR_WADNOTLOADED
;
585 Section
:= UpperCase(Section
);
586 Resource
:= UpperCase(Resource
);
589 for a
:= 0 to High(FResTable
) do
591 if FResTable
[a
].Length
= 0 then
593 CurrentSection
:= FResTable
[a
].ResourceName
;
597 if (FResTable
[a
].ResourceName
= Resource
) and
598 (CurrentSection
= Section
) then
607 FLastError
:= DFWAD_ERROR_RESOURCENOTFOUND
;
611 if FWADOpened
= DFWAD_OPENED_FILE
then
614 AssignFile(WADFile
, FFileName
);
617 Seek(WADFile
, FResTable
[i
].Address
+6+
618 LongWord(SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
619 TempData
:= GetMemory(FResTable
[i
].Length
);
620 BlockRead(WADFile
, TempData
^, FResTable
[i
].Length
);
621 DecompressBuf(TempData
, FResTable
[i
].Length
, 0, pData
, OutBytes
);
628 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
635 TempData
:= GetMemory(FResTable
[i
].Length
);
636 CopyMemory(TempData
, Pointer(LongWord(FResData
)+FResTable
[i
].Address
+6+
637 LongWord(SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
))),
638 FResTable
[i
].Length
);
639 DecompressBuf(TempData
, FResTable
[i
].Length
, 0, pData
, OutBytes
);
645 FLastError
:= DFWAD_NOERROR
;
649 function TWADEditor_1
.GetResourcesList(Section
: string): SArray
;
652 CurrentSection
: Char16
;
656 if FResTable
= nil then Exit
;
657 if Length(Section
) > 16 then Exit
;
659 CurrentSection
:= '';
661 for a
:= 0 to High(FResTable
) do
663 if FResTable
[a
].Length
= 0 then
665 CurrentSection
:= FResTable
[a
].ResourceName
;
669 if CurrentSection
= Section
then
671 SetLength(Result
, Length(Result
)+1);
672 Result
[High(Result
)] := FResTable
[a
].ResourceName
;
677 function TWADEditor_1
.GetSectionList(): SArray
;
683 if FResTable
= nil then Exit
;
685 if FResTable
[0].Length
<> 0 then
687 SetLength(Result
, 1);
691 for i
:= 0 to High(FResTable
) do
692 if FResTable
[i
].Length
= 0 then
694 SetLength(Result
, Length(Result
)+1);
695 Result
[High(Result
)] := FResTable
[i
].ResourceName
;
699 function TWADEditor_1
.LastErrorString(): string;
702 DFWAD_NOERROR
: Result
:= '';
703 DFWAD_ERROR_WADNOTFOUND
: Result
:= 'DFWAD file not found';
704 DFWAD_ERROR_CANTOPENWAD
: Result
:= 'Can''t open DFWAD file';
705 DFWAD_ERROR_RESOURCENOTFOUND
: Result
:= 'Resource not found';
706 DFWAD_ERROR_FILENOTWAD
: Result
:= 'File is not DFWAD';
707 DFWAD_ERROR_WADNOTLOADED
: Result
:= 'DFWAD file is not loaded';
708 DFWAD_ERROR_READRESOURCE
: Result
:= 'Read resource error';
709 DFWAD_ERROR_READWAD
: Result
:= 'Read DFWAD error';
710 else Result
:= 'Unknown DFWAD error';
714 function TWADEditor_1
.ReadFile(FileName
: string): Boolean;
717 Signature
: array[0..4] of Char;
724 if not FileExists(FileName
) then
726 FLastError
:= DFWAD_ERROR_WADNOTFOUND
;
730 FFileName
:= FileName
;
732 AssignFile(WADFile
, FFileName
);
737 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
742 BlockRead(WADFile
, Signature
, 5);
743 if Signature
<> DFWAD_SIGNATURE
then
745 FLastError
:= DFWAD_ERROR_FILENOTWAD
;
750 BlockRead(WADFile
, FVersion
, 1);
751 if FVersion
<> DFWAD_VERSION
then
753 FLastError
:= DFWAD_ERROR_WRONGVERSION
;
758 BlockRead(WADFile
, FHeader
, SizeOf(TWADHeaderRec_1
));
759 SetLength(FResTable
, FHeader
.RecordsCount
);
760 if FResTable
<> nil then
762 BlockRead(WADFile
, FResTable
[0], SizeOf(TResourceTableRec_1
)*FHeader
.RecordsCount
);
764 for a
:= 0 to High(FResTable
) do
765 if FResTable
[a
].Length
<> 0 then
766 FResTable
[a
].Address
:= FResTable
[a
].Address
-6-(LongWord(SizeOf(TWADHeaderRec_1
)+
767 SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
772 FLastError
:= DFWAD_ERROR_READWAD
;
777 FWADOpened
:= DFWAD_OPENED_FILE
;
778 FLastError
:= DFWAD_NOERROR
;
782 function TWADEditor_1
.ReadMemory(Data
: Pointer; Len
: LongWord): Boolean;
784 Signature
: array[0..4] of Char;
791 CopyMemory(@Signature
[0], Data
, 5);
792 if Signature
<> DFWAD_SIGNATURE
then
794 FLastError
:= DFWAD_ERROR_FILENOTWAD
;
798 CopyMemory(@FVersion
, Pointer(LongWord(Data
)+5), 1);
799 if FVersion
<> DFWAD_VERSION
then
801 FLastError
:= DFWAD_ERROR_WRONGVERSION
;
805 CopyMemory(@FHeader
, Pointer(LongWord(Data
)+6), SizeOf(TWADHeaderRec_1
));
807 SetLength(FResTable
, FHeader
.RecordsCount
);
808 if FResTable
<> nil then
810 CopyMemory(@FResTable
[0], Pointer(LongWord(Data
)+6+SizeOf(TWADHeaderRec_1
)),
811 SizeOf(TResourceTableRec_1
)*FHeader
.RecordsCount
);
813 for a
:= 0 to High(FResTable
) do
814 if FResTable
[a
].Length
<> 0 then
815 FResTable
[a
].Address
:= FResTable
[a
].Address
-6-(LongWord(SizeOf(TWADHeaderRec_1
)+
816 SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
819 GetMem(FResData
, Len
);
820 CopyMemory(FResData
, Data
, Len
);
822 FWADOpened
:= DFWAD_OPENED_MEMORY
;
823 FLastError
:= DFWAD_NOERROR
;
828 procedure TWADEditor_1
.RemoveResource(Section
, Resource
: string);
831 CurrentSection
: Char16
;
834 if FResTable
= nil then Exit
;
839 CurrentSection
:= '';
841 for a
:= 0 to High(FResTable
) do
843 if FResTable
[a
].Length
= 0 then
845 CurrentSection
:= FResTable
[a
].ResourceName
;
849 if (FResTable
[a
].ResourceName
= Resource
) and
850 (CurrentSection
= Section
) then
853 b
:= FResTable
[a
].Length
;
854 c
:= FResTable
[a
].Address
;
861 for a
:= i
to High(FResTable
)-1 do
862 FResTable
[a
] := FResTable
[a
+1];
864 SetLength(FResTable
, Length(FResTable
)-1);
867 for a
:= 0 to High(FResTable
) do
868 if (FResTable
[a
].Length
<> 0) and (FResTable
[a
].Address
> c
) then
870 FResTable
[a
].Address
:= FResTable
[a
].Address
-b
;
871 d
:= d
+FResTable
[a
].Length
;
874 CopyMemory(Pointer(LongWord(FResData
)+c
), Pointer(LongWord(FResData
)+c
+b
), d
);
876 FDataSize
:= FDataSize
-b
;
877 FOffset
:= FOffset
-b
;
878 ReallocMem(FResData
, FDataSize
);
880 FHeader
.RecordsCount
:= FHeader
.RecordsCount
-1;
883 procedure TWADEditor_1
.SaveTo(FileName
: string);
888 Header
: TWADHeaderRec_1
;
891 sign
:= DFWAD_SIGNATURE
;
892 ver
:= DFWAD_VERSION
;
894 Header
.RecordsCount
:= Length(FResTable
);
896 if FResTable
<> nil then
897 for i
:= 0 to High(FResTable
) do
898 if FResTable
[i
].Length
<> 0 then
899 FResTable
[i
].Address
:= FResTable
[i
].Address
+6+SizeOf(TWADHeaderRec_1
)+
900 SizeOf(TResourceTableRec_1
)*Header
.RecordsCount
;
902 AssignFile(WADFile
, FileName
);
904 BlockWrite(WADFile
, sign
[1], 5);
905 BlockWrite(WADFile
, ver
, 1);
906 BlockWrite(WADFile
, Header
, SizeOf(TWADHeaderRec_1
));
907 if FResTable
<> nil then BlockWrite(WADFile
, FResTable
[0],
908 SizeOf(TResourceTableRec_1
)*Header
.RecordsCount
);
909 if FResData
<> nil then BlockWrite(WADFile
, FResData
^, FDataSize
);