6 -----------------------------------
7 WADEDITOR.PAS ВЕРСИЯ ОТ 26.08.08
9 Поддержка вадов версии 1
10 -----------------------------------
18 SArray
= array of ShortString;
20 TWADEditor_1
= class(TObject
)
23 FResTable
: packed array of TResourceTableRec_1
;
24 FHeader
: TWADHeaderRec_1
;
31 function LastErrorString(): string;
32 function GetResName(ResName
: string): Char16
;
35 destructor Destroy(); override;
37 function ReadFile(FileName
: string): Boolean;
38 function ReadMemory(Data
: Pointer; Len
: LongWord): Boolean;
39 procedure CreateImage();
40 function AddResource(Data
: Pointer; Len
: LongWord; Name
: string;
41 Section
: string): Boolean; overload
;
42 function AddResource(FileName
, Name
, Section
: string): Boolean; overload
;
43 function AddAlias(Res
, Alias
: string): Boolean;
44 procedure AddSection(Name
: string);
45 procedure RemoveResource(Section
, Resource
: string);
46 procedure SaveTo(FileName
: string);
47 function HaveResource(Section
, Resource
: string): Boolean;
48 function HaveSection(Section
: string): Boolean;
49 function GetResource(Section
, Resource
: string; var pData
: Pointer;
50 var Len
: Integer): Boolean;
51 function GetSectionList(): SArray
;
52 function GetResourcesList(Section
: string): SArray
;
54 property GetLastError
: Integer read FLastError
;
55 property GetLastErrorStr
: string read LastErrorString
;
56 property GetResourcesCount
: Word read FHeader
.RecordsCount
;
57 property GetVersion
: Byte read FVersion
;
62 DFWAD_ERROR_WADNOTFOUND
= -1;
63 DFWAD_ERROR_CANTOPENWAD
= -2;
64 DFWAD_ERROR_RESOURCENOTFOUND
= -3;
65 DFWAD_ERROR_FILENOTWAD
= -4;
66 DFWAD_ERROR_WADNOTLOADED
= -5;
67 DFWAD_ERROR_READRESOURCE
= -6;
68 DFWAD_ERROR_READWAD
= -7;
69 DFWAD_ERROR_WRONGVERSION
= -8;
72 procedure g_ProcessResourceStr(ResourceStr
: String; var FileName
,
73 SectionName
, ResourceName
: String); overload
;
74 procedure g_ProcessResourceStr(ResourceStr
: String; FileName
,
75 SectionName
, ResourceName
: PString); overload
;
80 SysUtils
, BinEditor
, ZLib
;
83 DFWAD_OPENED_NONE
= 0;
84 DFWAD_OPENED_FILE
= 1;
85 DFWAD_OPENED_MEMORY
= 2;
87 procedure DecompressBuf(const InBuf
: Pointer; InBytes
: Integer;
88 OutEstimate
: Integer; out OutBuf
: Pointer; out OutBytes
: Integer);
94 FillChar(strm
, sizeof(strm
), 0);
95 BufInc
:= (InBytes
+ 255) and not 255;
96 if OutEstimate
= 0 then
99 OutBytes
:= OutEstimate
;
100 GetMem(OutBuf
, OutBytes
);
102 strm
.next_in
:= InBuf
;
103 strm
.avail_in
:= InBytes
;
104 strm
.next_out
:= OutBuf
;
105 strm
.avail_out
:= OutBytes
;
106 inflateInit_(strm
, zlib_version
, sizeof(strm
));
108 while inflate(strm
, Z_FINISH
) <> Z_STREAM_END
do
111 Inc(OutBytes
, BufInc
);
112 ReallocMem(OutBuf
, OutBytes
);
113 strm
.next_out
:= PByteF(PChar(OutBuf
) + (PChar(strm
.next_out
) - PChar(P
)));
114 strm
.avail_out
:= BufInc
;
119 ReallocMem(OutBuf
, strm
.total_out
);
120 OutBytes
:= strm
.total_out
;
127 procedure g_ProcessResourceStr(ResourceStr
: String; var FileName
,
128 SectionName
, ResourceName
: String);
133 for i
:= Length(ResourceStr
) downto 1 do
134 if ResourceStr
[i
] = ':' then
137 FileName
:= Copy(ResourceStr
, 1, i
-1);
139 for a
:= i
+1 to Length(ResourceStr
) do
140 if (ResourceStr
[a
] = '\') or (ResourceStr
[a
] = '/') then Break
;
142 ResourceName
:= Copy(ResourceStr
, a
+1, Length(ResourceStr
)-Abs(a
));
143 SectionName
:= Copy(ResourceStr
, i
+1, Length(ResourceStr
)-Length(ResourceName
)-Length(FileName
)-2);
146 procedure g_ProcessResourceStr(ResourceStr
: AnsiString; FileName
,
147 SectionName
, ResourceName
: PAnsiString);
149 a
, i
, l1
, l2
: Integer;
152 for i
:= Length(ResourceStr
) downto 1 do
153 if ResourceStr
[i
] = ':' then
156 if FileName
<> nil then
158 FileName
^ := Copy(ResourceStr
, 1, i
-1);
159 l1
:= Length(FileName
^);
164 for a
:= i
+1 to Length(ResourceStr
) do
165 if (ResourceStr
[a
] = '\') or (ResourceStr
[a
] = '/') then Break
;
167 if ResourceName
<> nil then
169 ResourceName
^ := Copy(ResourceStr
, a
+1, Length(ResourceStr
)-Abs(a
));
170 l2
:= Length(ResourceName
^);
175 if SectionName
<> nil then
176 SectionName
^ := Copy(ResourceStr
, i
+1, Length(ResourceStr
)-l2
-l1
-2);
181 function TWADEditor_1
.AddResource(Data
: Pointer; Len
: LongWord; Name
: string;
182 Section
: string): Boolean;
184 ResCompressed
: Pointer;
185 ResCompressedSize
: Integer;
190 SetLength(FResTable
, Length(FResTable
)+1);
194 if Length(FResTable
) > 1 then
195 for a
:= High(FResTable
) downto 1 do
196 FResTable
[a
] := FResTable
[a
-1];
202 Section
:= AnsiUpperCase(Section
);
205 for a
:= 0 to High(FResTable
) do
206 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
208 for b
:= High(FResTable
) downto a
+2 do
209 FResTable
[b
] := FResTable
[b
-1];
217 SetLength(FResTable
, Length(FResTable
)-1);
223 ResCompressed
:= nil;
224 ResCompressedSize
:= 0;
225 Compress(Data
, @Len
, ResCompressed
, ResCompressedSize
);
226 if ResCompressed
= nil then Exit
;
228 if FResData
= nil then FResData
:= AllocMem(ResCompressedSize
)
229 else ReallocMem(FResData
, FDataSize
+Cardinal(ResCompressedSize
));
231 FDataSize
:= FDataSize
+LongWord(ResCompressedSize
);
233 CopyMemory(Pointer(PChar(FResData
)+FDataSize
-PChar(ResCompressedSize
)),
234 ResCompressed
, ResCompressedSize
);
235 FreeMemory(ResCompressed
);
237 Inc(FHeader
.RecordsCount
);
241 ResourceName
:= GetResName(Name
);
243 Length
:= ResCompressedSize
;
246 FOffset
:= FOffset
+Cardinal(ResCompressedSize
);
251 function TWADEditor_1
.AddAlias(Res
, Alias
: string): Boolean;
258 if FResTable
= nil then Exit
;
261 ares
:= GetResName(Alias
);
262 for a
:= 0 to High(FResTable
) do
263 if FResTable
[a
].ResourceName
= Res
then
271 Inc(FHeader
.RecordsCount
);
273 SetLength(FResTable
, Length(FResTable
)+1);
275 with FResTable
[High(FResTable
)] do
277 ResourceName
:= ares
;
278 Address
:= FResTable
[b
].Address
;
279 Length
:= FResTable
[b
].Length
;
285 function TWADEditor_1
.AddResource(FileName
, Name
, Section
: string): Boolean;
287 ResCompressed
: Pointer;
288 ResCompressedSize
: Integer;
290 TempResource
: Pointer;
291 OriginalSize
: Integer;
296 AssignFile(ResourceFile
, FileName
);
299 Reset(ResourceFile
, 1);
301 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
305 OriginalSize
:= FileSize(ResourceFile
);
306 GetMem(TempResource
, OriginalSize
);
309 BlockRead(ResourceFile
, TempResource
^, OriginalSize
);
311 FLastError
:= DFWAD_ERROR_READWAD
;
312 FreeMemory(TempResource
);
313 CloseFile(ResourceFile
);
317 CloseFile(ResourceFile
);
319 ResCompressed
:= nil;
320 ResCompressedSize
:= 0;
321 Compress(TempResource
, @OriginalSize
, ResCompressed
, ResCompressedSize
);
322 FreeMemory(TempResource
);
323 if ResCompressed
= nil then Exit
;
325 SetLength(FResTable
, Length(FResTable
)+1);
329 if Length(FResTable
) > 1 then
330 for a
:= High(FResTable
) downto 1 do
331 FResTable
[a
] := FResTable
[a
-1];
337 Section
:= AnsiUpperCase(Section
);
340 for a
:= 0 to High(FResTable
) do
341 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
343 for b
:= High(FResTable
) downto a
+2 do
344 FResTable
[b
] := FResTable
[b
-1];
352 FreeMemory(ResCompressed
);
353 SetLength(FResTable
, Length(FResTable
)-1);
360 if FResData
= nil then FResData
:= AllocMem(ResCompressedSize
)
361 else ReallocMem(FResData
, FDataSize
+Cardinal(ResCompressedSize
));
363 FDataSize
:= FDataSize
+LongWord(ResCompressedSize
);
364 CopyMemory(Pointer(PChar(FResData
)+FDataSize
-PChar(ResCompressedSize
)),
365 ResCompressed
, ResCompressedSize
);
366 FreeMemory(ResCompressed
);
368 Inc(FHeader
.RecordsCount
);
372 ResourceName
:= GetResName(Name
);
374 Length
:= ResCompressedSize
;
377 FOffset
:= FOffset
+Cardinal(ResCompressedSize
);
382 procedure TWADEditor_1
.AddSection(Name
: string);
384 if Name
= '' then Exit
;
386 Inc(FHeader
.RecordsCount
);
388 SetLength(FResTable
, Length(FResTable
)+1);
389 with FResTable
[High(FResTable
)] do
391 ResourceName
:= GetResName(Name
);
392 Address
:= $00000000;
397 constructor TWADEditor_1
.Create();
403 FHeader
.RecordsCount
:= 0;
405 FWADOpened
:= DFWAD_OPENED_NONE
;
406 FLastError
:= DFWAD_NOERROR
;
407 FVersion
:= DFWAD_VERSION
;
410 procedure TWADEditor_1
.CreateImage();
415 if FWADOpened
= DFWAD_OPENED_NONE
then
417 FLastError
:= DFWAD_ERROR_WADNOTLOADED
;
421 if FWADOpened
= DFWAD_OPENED_MEMORY
then Exit
;
423 if FResData
<> nil then FreeMem(FResData
);
426 AssignFile(WADFile
, FFileName
);
429 b
:= 6+SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
);
431 FDataSize
:= LongWord(FileSize(WADFile
))-b
;
433 GetMem(FResData
, FDataSize
);
436 BlockRead(WADFile
, FResData
^, FDataSize
);
440 FOffset
:= FDataSize
;
442 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
447 FLastError
:= DFWAD_NOERROR
;
450 destructor TWADEditor_1
.Destroy();
457 procedure TWADEditor_1
.FreeWAD();
459 if FResData
<> nil then FreeMem(FResData
);
463 FHeader
.RecordsCount
:= 0;
465 FWADOpened
:= DFWAD_OPENED_NONE
;
466 FLastError
:= DFWAD_NOERROR
;
467 FVersion
:= DFWAD_VERSION
;
470 function TWADEditor_1
.GetResName(ResName
: string): Char16
;
472 ZeroMemory(@Result
[0], 16);
473 if ResName
= '' then Exit
;
475 ResName
:= Trim(UpperCase(ResName
));
476 if Length(ResName
) > 16 then SetLength(ResName
, 16);
478 CopyMemory(@Result
[0], @ResName
[1], Length(ResName
));
481 function TWADEditor_1
.HaveResource(Section
, Resource
: string): Boolean;
484 CurrentSection
: string;
488 if FResTable
= nil then Exit
;
490 CurrentSection
:= '';
491 Section
:= AnsiUpperCase(Section
);
492 Resource
:= AnsiUpperCase(Resource
);
494 for a
:= 0 to High(FResTable
) do
496 if FResTable
[a
].Length
= 0 then
498 CurrentSection
:= FResTable
[a
].ResourceName
;
502 if (FResTable
[a
].ResourceName
= Resource
) and
503 (CurrentSection
= Section
) then
511 function TWADEditor_1
.HaveSection(Section
: string): Boolean;
517 if FResTable
= nil then Exit
;
524 Section
:= AnsiUpperCase(Section
);
526 for a
:= 0 to High(FResTable
) do
527 if (FResTable
[a
].Length
= 0) and (FResTable
[a
].ResourceName
= Section
) then
534 function TWADEditor_1
.GetResource(Section
, Resource
: string;
535 var pData
: Pointer; var Len
: Integer): Boolean;
540 CurrentSection
: string;
546 CurrentSection
:= '';
548 if FWADOpened
= DFWAD_OPENED_NONE
then
550 FLastError
:= DFWAD_ERROR_WADNOTLOADED
;
554 Section
:= UpperCase(Section
);
555 Resource
:= UpperCase(Resource
);
558 for a
:= 0 to High(FResTable
) do
560 if FResTable
[a
].Length
= 0 then
562 CurrentSection
:= FResTable
[a
].ResourceName
;
566 if (FResTable
[a
].ResourceName
= Resource
) and
567 (CurrentSection
= Section
) then
576 FLastError
:= DFWAD_ERROR_RESOURCENOTFOUND
;
580 if FWADOpened
= DFWAD_OPENED_FILE
then
583 AssignFile(WADFile
, FFileName
);
586 Seek(WADFile
, FResTable
[i
].Address
+6+
587 LongWord(SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
588 TempData
:= GetMemory(FResTable
[i
].Length
);
589 BlockRead(WADFile
, TempData
^, FResTable
[i
].Length
);
590 DecompressBuf(TempData
, FResTable
[i
].Length
, 0, pData
, OutBytes
);
597 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
604 TempData
:= GetMemory(FResTable
[i
].Length
);
605 CopyMemory(TempData
, Pointer(LongWord(FResData
)+FResTable
[i
].Address
+6+
606 LongWord(SizeOf(TWADHeaderRec_1
)+SizeOf(TResourceTableRec_1
)*Length(FResTable
))),
607 FResTable
[i
].Length
);
608 DecompressBuf(TempData
, FResTable
[i
].Length
, 0, pData
, OutBytes
);
614 FLastError
:= DFWAD_NOERROR
;
618 function TWADEditor_1
.GetResourcesList(Section
: string): SArray
;
621 CurrentSection
: Char16
;
625 if FResTable
= nil then Exit
;
626 if Length(Section
) > 16 then Exit
;
628 CurrentSection
:= '';
630 for a
:= 0 to High(FResTable
) do
632 if FResTable
[a
].Length
= 0 then
634 CurrentSection
:= FResTable
[a
].ResourceName
;
638 if CurrentSection
= Section
then
640 SetLength(Result
, Length(Result
)+1);
641 Result
[High(Result
)] := FResTable
[a
].ResourceName
;
646 function TWADEditor_1
.GetSectionList(): SArray
;
652 if FResTable
= nil then Exit
;
654 if FResTable
[0].Length
<> 0 then
656 SetLength(Result
, 1);
660 for i
:= 0 to High(FResTable
) do
661 if FResTable
[i
].Length
= 0 then
663 SetLength(Result
, Length(Result
)+1);
664 Result
[High(Result
)] := FResTable
[i
].ResourceName
;
668 function TWADEditor_1
.LastErrorString(): string;
671 DFWAD_NOERROR
: Result
:= '';
672 DFWAD_ERROR_WADNOTFOUND
: Result
:= 'DFWAD file not found';
673 DFWAD_ERROR_CANTOPENWAD
: Result
:= 'Can''t open DFWAD file';
674 DFWAD_ERROR_RESOURCENOTFOUND
: Result
:= 'Resource not found';
675 DFWAD_ERROR_FILENOTWAD
: Result
:= 'File is not DFWAD';
676 DFWAD_ERROR_WADNOTLOADED
: Result
:= 'DFWAD file is not loaded';
677 DFWAD_ERROR_READRESOURCE
: Result
:= 'Read resource error';
678 DFWAD_ERROR_READWAD
: Result
:= 'Read DFWAD error';
682 function TWADEditor_1
.ReadFile(FileName
: string): Boolean;
685 Signature
: array[0..4] of Char;
692 if not FileExists(FileName
) then
694 FLastError
:= DFWAD_ERROR_WADNOTFOUND
;
698 FFileName
:= FileName
;
700 AssignFile(WADFile
, FFileName
);
705 FLastError
:= DFWAD_ERROR_CANTOPENWAD
;
710 BlockRead(WADFile
, Signature
, 5);
711 if Signature
<> DFWAD_SIGNATURE
then
713 FLastError
:= DFWAD_ERROR_FILENOTWAD
;
718 BlockRead(WADFile
, FVersion
, 1);
719 if FVersion
<> DFWAD_VERSION
then
721 FLastError
:= DFWAD_ERROR_WRONGVERSION
;
726 BlockRead(WADFile
, FHeader
, SizeOf(TWADHeaderRec_1
));
727 SetLength(FResTable
, FHeader
.RecordsCount
);
728 if FResTable
<> nil then
730 BlockRead(WADFile
, FResTable
[0], SizeOf(TResourceTableRec_1
)*FHeader
.RecordsCount
);
732 for a
:= 0 to High(FResTable
) do
733 if FResTable
[a
].Length
<> 0 then
734 FResTable
[a
].Address
:= FResTable
[a
].Address
-6-(LongWord(SizeOf(TWADHeaderRec_1
)+
735 SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
740 FLastError
:= DFWAD_ERROR_READWAD
;
745 FWADOpened
:= DFWAD_OPENED_FILE
;
746 FLastError
:= DFWAD_NOERROR
;
750 function TWADEditor_1
.ReadMemory(Data
: Pointer; Len
: LongWord): Boolean;
752 Signature
: array[0..4] of Char;
759 CopyMemory(@Signature
[0], Data
, 5);
760 if Signature
<> DFWAD_SIGNATURE
then
762 FLastError
:= DFWAD_ERROR_FILENOTWAD
;
766 CopyMemory(@FVersion
, Pointer(LongWord(Data
)+5), 1);
767 if FVersion
<> DFWAD_VERSION
then
769 FLastError
:= DFWAD_ERROR_WRONGVERSION
;
773 CopyMemory(@FHeader
, Pointer(LongWord(Data
)+6), SizeOf(TWADHeaderRec_1
));
775 SetLength(FResTable
, FHeader
.RecordsCount
);
776 if FResTable
<> nil then
778 CopyMemory(@FResTable
[0], Pointer(LongWord(Data
)+6+SizeOf(TWADHeaderRec_1
)),
779 SizeOf(TResourceTableRec_1
)*FHeader
.RecordsCount
);
781 for a
:= 0 to High(FResTable
) do
782 if FResTable
[a
].Length
<> 0 then
783 FResTable
[a
].Address
:= FResTable
[a
].Address
-6-(LongWord(SizeOf(TWADHeaderRec_1
)+
784 SizeOf(TResourceTableRec_1
)*Length(FResTable
)));
787 GetMem(FResData
, Len
);
788 CopyMemory(FResData
, Data
, Len
);
790 FWADOpened
:= DFWAD_OPENED_MEMORY
;
791 FLastError
:= DFWAD_NOERROR
;
796 procedure TWADEditor_1
.RemoveResource(Section
, Resource
: string);
799 CurrentSection
: Char16
;
802 if FResTable
= nil then Exit
;
807 CurrentSection
:= '';
809 for a
:= 0 to High(FResTable
) do
811 if FResTable
[a
].Length
= 0 then
813 CurrentSection
:= FResTable
[a
].ResourceName
;
817 if (FResTable
[a
].ResourceName
= Resource
) and
818 (CurrentSection
= Section
) then
821 b
:= FResTable
[a
].Length
;
822 c
:= FResTable
[a
].Address
;
829 for a
:= i
to High(FResTable
)-1 do
830 FResTable
[a
] := FResTable
[a
+1];
832 SetLength(FResTable
, Length(FResTable
)-1);
835 for a
:= 0 to High(FResTable
) do
836 if (FResTable
[a
].Length
<> 0) and (FResTable
[a
].Address
> c
) then
838 FResTable
[a
].Address
:= FResTable
[a
].Address
-b
;
839 d
:= d
+FResTable
[a
].Length
;
842 CopyMemory(Pointer(LongWord(FResData
)+c
), Pointer(LongWord(FResData
)+c
+b
), d
);
844 FDataSize
:= FDataSize
-b
;
845 FOffset
:= FOffset
-b
;
846 ReallocMem(FResData
, FDataSize
);
848 FHeader
.RecordsCount
:= FHeader
.RecordsCount
-1;
851 procedure TWADEditor_1
.SaveTo(FileName
: string);
856 Header
: TWADHeaderRec_1
;
859 sign
:= DFWAD_SIGNATURE
;
860 ver
:= DFWAD_VERSION
;
862 Header
.RecordsCount
:= Length(FResTable
);
864 if FResTable
<> nil then
865 for i
:= 0 to High(FResTable
) do
866 if FResTable
[i
].Length
<> 0 then
867 FResTable
[i
].Address
:= FResTable
[i
].Address
+6+SizeOf(TWADHeaderRec_1
)+
868 SizeOf(TResourceTableRec_1
)*Header
.RecordsCount
;
870 AssignFile(WADFile
, FileName
);
872 BlockWrite(WADFile
, sign
[1], 5);
873 BlockWrite(WADFile
, ver
, 1);
874 BlockWrite(WADFile
, Header
, SizeOf(TWADHeaderRec_1
));
875 if FResTable
<> nil then BlockWrite(WADFile
, FResTable
[0],
876 SizeOf(TResourceTableRec_1
)*Header
.RecordsCount
);
877 if FResData
<> nil then BlockWrite(WADFile
, FResData
^, FDataSize
);