DEADSOFTWARE

typo in mapcvt: microseconds -> milliseconds
[d2df-sdl.git] / src / sheditor / WADEDITOR_full.pas
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$MODE DELPHI}
17 unit WADEDITOR_full;
19 {
20 -----------------------------------
21 WADEDITOR.PAS ÂÅÐÑÈß ÎÒ 26.08.08
23 Ïîääåðæêà âàäîâ âåðñèè 1
24 -----------------------------------
25 }
27 {
28 -----------------------------------
29 WADSTRUCT.PAS ÂÅÐÑÈß ÎÒ 24.09.06
31 Ïîääåðæêà âàäîâ âåðñèè 1
32 -----------------------------------
34 Ñòðóêòóðà DFWAD-ôàéëà âåðñèè 1:
35 ------------------------------------------
36 SIGNATURE | Byte[5] | 'DFWAD'
37 VERSION | Byte | $01
38 HEADER | TWADHeaderRec_1 |
39 RESRECORD1 | TResourceTableRec_1 |
40 ... | ................... |
41 RESRECORDN | TResourceTableRec_1 |
42 DATA | RAW |
43 ------------------------------------------
44 }
46 interface
48 type
49 SArray = array of ShortString;
50 Char16 = packed array[0..15] of Char;
52 TWADHeaderRec_1 = packed record
53 RecordsCount: Word;
54 end;
56 TResourceTableRec_1 = packed record
57 ResourceName: Char16;
58 Address: LongWord;
59 Length: LongWord;
60 end;
62 TWADEditor_1 = class(TObject)
63 private
64 FResData: Pointer;
65 FResTable: packed array of TResourceTableRec_1;
66 FHeader: TWADHeaderRec_1;
67 FDataSize: LongWord;
68 FOffset: LongWord;
69 FFileName: string;
70 FWADOpened: Byte;
71 FLastError: Integer;
72 FVersion: Byte;
73 function LastErrorString(): string;
74 function GetResName(ResName: string): Char16;
75 public
76 constructor Create();
77 destructor Destroy(); override;
78 procedure FreeWAD();
79 function ReadFile(FileName: string): Boolean;
80 function ReadMemory(Data: Pointer; Len: LongWord): Boolean;
81 procedure CreateImage();
82 function AddResource(Data: Pointer; Len: LongWord; Name: string;
83 Section: string): Boolean; overload;
84 function AddResource(FileName, Name, Section: string): Boolean; overload;
85 function AddAlias(Res, Alias: string): Boolean;
86 procedure AddSection(Name: string);
87 procedure RemoveResource(Section, Resource: string);
88 procedure SaveTo(FileName: string);
89 function HaveResource(Section, Resource: string): Boolean;
90 function HaveSection(Section: string): Boolean;
91 function GetResource(Section, Resource: string; var pData: Pointer;
92 var Len: Integer): Boolean;
93 function GetSectionList(): SArray;
94 function GetResourcesList(Section: string): SArray;
96 property GetLastError: Integer read FLastError;
97 property GetLastErrorStr: string read LastErrorString;
98 property GetResourcesCount: Word read FHeader.RecordsCount;
99 property GetVersion: Byte read FVersion;
100 end;
102 const
103 DFWAD_SIGNATURE = 'DFWAD';
104 DFWAD_VERSION = $01;
106 const
107 DFWAD_NOERROR = 0;
108 DFWAD_ERROR_WADNOTFOUND = -1;
109 DFWAD_ERROR_CANTOPENWAD = -2;
110 DFWAD_ERROR_RESOURCENOTFOUND = -3;
111 DFWAD_ERROR_FILENOTWAD = -4;
112 DFWAD_ERROR_WADNOTLOADED = -5;
113 DFWAD_ERROR_READRESOURCE = -6;
114 DFWAD_ERROR_READWAD = -7;
115 DFWAD_ERROR_WRONGVERSION = -8;
118 procedure g_ProcessResourceStr(ResourceStr: String; var FileName,
119 SectionName, ResourceName: String); overload;
120 procedure g_ProcessResourceStr(ResourceStr: String; FileName,
121 SectionName, ResourceName: PString); overload;
123 implementation
125 uses
126 SysUtils, BinEditor, ZLib;
128 const
129 DFWAD_OPENED_NONE = 0;
130 DFWAD_OPENED_FILE = 1;
131 DFWAD_OPENED_MEMORY = 2;
133 procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
134 OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
135 var
136 strm: TZStreamRec;
137 P: Pointer;
138 BufInc: Integer;
139 begin
140 FillChar(strm, sizeof(strm), 0);
141 BufInc := (InBytes + 255) and not 255;
142 if OutEstimate = 0 then
143 OutBytes := BufInc
144 else
145 OutBytes := OutEstimate;
146 GetMem(OutBuf, OutBytes);
147 try
148 strm.next_in := InBuf;
149 strm.avail_in := InBytes;
150 strm.next_out := OutBuf;
151 strm.avail_out := OutBytes;
152 inflateInit_(strm, zlib_version, sizeof(strm));
153 try
154 while inflate(strm, Z_FINISH) <> Z_STREAM_END do
155 begin
156 P := OutBuf;
157 Inc(OutBytes, BufInc);
158 ReallocMem(OutBuf, OutBytes);
159 strm.next_out := PByteF(PChar(OutBuf) + (PChar(strm.next_out) - PChar(P)));
160 strm.avail_out := BufInc;
161 end;
162 finally
163 inflateEnd(strm);
164 end;
165 ReallocMem(OutBuf, strm.total_out);
166 OutBytes := strm.total_out;
167 except
168 FreeMem(OutBuf);
169 raise
170 end;
171 end;
173 procedure g_ProcessResourceStr(ResourceStr: String; var FileName,
174 SectionName, ResourceName: String);
175 var
176 a, i: Integer;
178 begin
179 for i := Length(ResourceStr) downto 1 do
180 if ResourceStr[i] = ':' then
181 Break;
183 FileName := Copy(ResourceStr, 1, i-1);
185 for a := i+1 to Length(ResourceStr) do
186 if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break;
188 ResourceName := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a));
189 SectionName := Copy(ResourceStr, i+1, Length(ResourceStr)-Length(ResourceName)-Length(FileName)-2);
190 end;
192 procedure g_ProcessResourceStr(ResourceStr: AnsiString; FileName,
193 SectionName, ResourceName: PAnsiString);
194 var
195 a, i, l1, l2: Integer;
197 begin
198 for i := Length(ResourceStr) downto 1 do
199 if ResourceStr[i] = ':' then
200 Break;
202 if FileName <> nil then
203 begin
204 FileName^ := Copy(ResourceStr, 1, i-1);
205 l1 := Length(FileName^);
206 end
207 else
208 l1 := 0;
210 for a := i+1 to Length(ResourceStr) do
211 if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break;
213 if ResourceName <> nil then
214 begin
215 ResourceName^ := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a));
216 l2 := Length(ResourceName^);
217 end
218 else
219 l2 := 0;
221 if SectionName <> nil then
222 SectionName^ := Copy(ResourceStr, i+1, Length(ResourceStr)-l2-l1-2);
223 end;
225 { TWADEditor_1 }
227 function TWADEditor_1.AddResource(Data: Pointer; Len: LongWord; Name: string;
228 Section: string): Boolean;
229 var
230 ResCompressed: Pointer;
231 ResCompressedSize: Integer;
232 a, b: Integer;
233 begin
234 Result := False;
236 SetLength(FResTable, Length(FResTable)+1);
238 if Section = '' then
239 begin
240 if Length(FResTable) > 1 then
241 for a := High(FResTable) downto 1 do
242 FResTable[a] := FResTable[a-1];
244 a := 0;
245 end
246 else
247 begin
248 Section := AnsiUpperCase(Section);
249 b := -1;
251 for a := 0 to High(FResTable) do
252 if (FResTable[a].Length = 0) and (FResTable[a].ResourceName = Section) then
253 begin
254 for b := High(FResTable) downto a+2 do
255 FResTable[b] := FResTable[b-1];
257 b := a+1;
258 Break;
259 end;
261 if b = -1 then
262 begin
263 SetLength(FResTable, Length(FResTable)-1);
264 Exit;
265 end;
266 a := b;
267 end;
269 ResCompressed := nil;
270 ResCompressedSize := 0;
271 Compress(Data, @Len, ResCompressed, ResCompressedSize);
272 if ResCompressed = nil then Exit;
274 if FResData = nil then FResData := AllocMem(ResCompressedSize)
275 else ReallocMem(FResData, FDataSize+Cardinal(ResCompressedSize));
277 FDataSize := FDataSize+LongWord(ResCompressedSize);
279 CopyMemory(Pointer(PChar(FResData)+FDataSize-PChar(ResCompressedSize)),
280 ResCompressed, ResCompressedSize);
281 FreeMemory(ResCompressed);
283 Inc(FHeader.RecordsCount);
285 with FResTable[a] do
286 begin
287 ResourceName := GetResName(Name);
288 Address := FOffset;
289 Length := ResCompressedSize;
290 end;
292 FOffset := FOffset+Cardinal(ResCompressedSize);
294 Result := True;
295 end;
297 function TWADEditor_1.AddAlias(Res, Alias: string): Boolean;
298 var
299 a, b: Integer;
300 ares: Char16;
301 begin
302 Result := False;
304 if FResTable = nil then Exit;
306 b := -1;
307 ares := GetResName(Alias);
308 for a := 0 to High(FResTable) do
309 if FResTable[a].ResourceName = Res then
310 begin
311 b := a;
312 Break;
313 end;
315 if b = -1 then Exit;
317 Inc(FHeader.RecordsCount);
319 SetLength(FResTable, Length(FResTable)+1);
321 with FResTable[High(FResTable)] do
322 begin
323 ResourceName := ares;
324 Address := FResTable[b].Address;
325 Length := FResTable[b].Length;
326 end;
328 Result := True;
329 end;
331 function TWADEditor_1.AddResource(FileName, Name, Section: string): Boolean;
332 var
333 ResCompressed: Pointer;
334 ResCompressedSize: Integer;
335 ResourceFile: File;
336 TempResource: Pointer;
337 OriginalSize: Integer;
338 a, b: Integer;
339 begin
340 Result := False;
342 AssignFile(ResourceFile, FileName);
344 try
345 Reset(ResourceFile, 1);
346 except
347 FLastError := DFWAD_ERROR_CANTOPENWAD;
348 Exit;
349 end;
351 OriginalSize := FileSize(ResourceFile);
352 GetMem(TempResource, OriginalSize);
354 try
355 BlockRead(ResourceFile, TempResource^, OriginalSize);
356 except
357 FLastError := DFWAD_ERROR_READWAD;
358 FreeMemory(TempResource);
359 CloseFile(ResourceFile);
360 Exit;
361 end;
363 CloseFile(ResourceFile);
365 ResCompressed := nil;
366 ResCompressedSize := 0;
367 Compress(TempResource, @OriginalSize, ResCompressed, ResCompressedSize);
368 FreeMemory(TempResource);
369 if ResCompressed = nil then Exit;
371 SetLength(FResTable, Length(FResTable)+1);
373 if Section = '' then
374 begin
375 if Length(FResTable) > 1 then
376 for a := High(FResTable) downto 1 do
377 FResTable[a] := FResTable[a-1];
379 a := 0;
380 end
381 else
382 begin
383 Section := AnsiUpperCase(Section);
384 b := -1;
386 for a := 0 to High(FResTable) do
387 if (FResTable[a].Length = 0) and (FResTable[a].ResourceName = Section) then
388 begin
389 for b := High(FResTable) downto a+2 do
390 FResTable[b] := FResTable[b-1];
392 b := a+1;
393 Break;
394 end;
396 if b = -1 then
397 begin
398 FreeMemory(ResCompressed);
399 SetLength(FResTable, Length(FResTable)-1);
400 Exit;
401 end;
403 a := b;
404 end;
406 if FResData = nil then FResData := AllocMem(ResCompressedSize)
407 else ReallocMem(FResData, FDataSize+Cardinal(ResCompressedSize));
409 FDataSize := FDataSize+LongWord(ResCompressedSize);
410 CopyMemory(Pointer(PChar(FResData)+FDataSize-PChar(ResCompressedSize)),
411 ResCompressed, ResCompressedSize);
412 FreeMemory(ResCompressed);
414 Inc(FHeader.RecordsCount);
416 with FResTable[a] do
417 begin
418 ResourceName := GetResName(Name);
419 Address := FOffset;
420 Length := ResCompressedSize;
421 end;
423 FOffset := FOffset+Cardinal(ResCompressedSize);
425 Result := True;
426 end;
428 procedure TWADEditor_1.AddSection(Name: string);
429 begin
430 if Name = '' then Exit;
432 Inc(FHeader.RecordsCount);
434 SetLength(FResTable, Length(FResTable)+1);
435 with FResTable[High(FResTable)] do
436 begin
437 ResourceName := GetResName(Name);
438 Address := $00000000;
439 Length := $00000000;
440 end;
441 end;
443 constructor TWADEditor_1.Create();
444 begin
445 FResData := nil;
446 FResTable := nil;
447 FDataSize := 0;
448 FOffset := 0;
449 FHeader.RecordsCount := 0;
450 FFileName := '';
451 FWADOpened := DFWAD_OPENED_NONE;
452 FLastError := DFWAD_NOERROR;
453 FVersion := DFWAD_VERSION;
454 end;
456 procedure TWADEditor_1.CreateImage();
457 var
458 WADFile: File;
459 b: LongWord;
460 begin
461 if FWADOpened = DFWAD_OPENED_NONE then
462 begin
463 FLastError := DFWAD_ERROR_WADNOTLOADED;
464 Exit;
465 end;
467 if FWADOpened = DFWAD_OPENED_MEMORY then Exit;
469 if FResData <> nil then FreeMem(FResData);
471 try
472 AssignFile(WADFile, FFileName);
473 Reset(WADFile, 1);
475 b := 6+SizeOf(TWADHeaderRec_1)+SizeOf(TResourceTableRec_1)*Length(FResTable);
477 FDataSize := LongWord(FileSize(WADFile))-b;
479 GetMem(FResData, FDataSize);
481 Seek(WADFile, b);
482 BlockRead(WADFile, FResData^, FDataSize);
484 CloseFile(WADFile);
486 FOffset := FDataSize;
487 except
488 FLastError := DFWAD_ERROR_CANTOPENWAD;
489 CloseFile(WADFile);
490 Exit;
491 end;
493 FLastError := DFWAD_NOERROR;
494 end;
496 destructor TWADEditor_1.Destroy();
497 begin
498 FreeWAD();
500 inherited;
501 end;
503 procedure TWADEditor_1.FreeWAD();
504 begin
505 if FResData <> nil then FreeMem(FResData);
506 FResTable := nil;
507 FDataSize := 0;
508 FOffset := 0;
509 FHeader.RecordsCount := 0;
510 FFileName := '';
511 FWADOpened := DFWAD_OPENED_NONE;
512 FLastError := DFWAD_NOERROR;
513 FVersion := DFWAD_VERSION;
514 end;
516 function TWADEditor_1.GetResName(ResName: string): Char16;
517 begin
518 ZeroMemory(@Result[0], 16);
519 if ResName = '' then Exit;
521 ResName := Trim(UpperCase(ResName));
522 if Length(ResName) > 16 then SetLength(ResName, 16);
524 CopyMemory(@Result[0], @ResName[1], Length(ResName));
525 end;
527 function TWADEditor_1.HaveResource(Section, Resource: string): Boolean;
528 var
529 a: Integer;
530 CurrentSection: string;
531 begin
532 Result := False;
534 if FResTable = nil then Exit;
536 CurrentSection := '';
537 Section := AnsiUpperCase(Section);
538 Resource := AnsiUpperCase(Resource);
540 for a := 0 to High(FResTable) do
541 begin
542 if FResTable[a].Length = 0 then
543 begin
544 CurrentSection := FResTable[a].ResourceName;
545 Continue;
546 end;
548 if (FResTable[a].ResourceName = Resource) and
549 (CurrentSection = Section) then
550 begin
551 Result := True;
552 Break;
553 end;
554 end;
555 end;
557 function TWADEditor_1.HaveSection(Section: string): Boolean;
558 var
559 a: Integer;
560 begin
561 Result := False;
563 if FResTable = nil then Exit;
564 if Section = '' then
565 begin
566 Result := True;
567 Exit;
568 end;
570 Section := AnsiUpperCase(Section);
572 for a := 0 to High(FResTable) do
573 if (FResTable[a].Length = 0) and (FResTable[a].ResourceName = Section) then
574 begin
575 Result := True;
576 Exit;
577 end;
578 end;
580 function TWADEditor_1.GetResource(Section, Resource: string;
581 var pData: Pointer; var Len: Integer): Boolean;
582 var
583 a: LongWord;
584 i: Integer;
585 WADFile: File;
586 CurrentSection: string;
587 TempData: Pointer;
588 OutBytes: Integer;
589 begin
590 Result := False;
592 CurrentSection := '';
594 if FWADOpened = DFWAD_OPENED_NONE then
595 begin
596 FLastError := DFWAD_ERROR_WADNOTLOADED;
597 Exit;
598 end;
600 Section := UpperCase(Section);
601 Resource := UpperCase(Resource);
603 i := -1;
604 for a := 0 to High(FResTable) do
605 begin
606 if FResTable[a].Length = 0 then
607 begin
608 CurrentSection := FResTable[a].ResourceName;
609 Continue;
610 end;
612 if (FResTable[a].ResourceName = Resource) and
613 (CurrentSection = Section) then
614 begin
615 i := a;
616 Break;
617 end;
618 end;
620 if i = -1 then
621 begin
622 FLastError := DFWAD_ERROR_RESOURCENOTFOUND;
623 Exit;
624 end;
626 if FWADOpened = DFWAD_OPENED_FILE then
627 begin
628 try
629 AssignFile(WADFile, FFileName);
630 Reset(WADFile, 1);
632 Seek(WADFile, FResTable[i].Address+6+
633 LongWord(SizeOf(TWADHeaderRec_1)+SizeOf(TResourceTableRec_1)*Length(FResTable)));
634 TempData := GetMemory(FResTable[i].Length);
635 BlockRead(WADFile, TempData^, FResTable[i].Length);
636 DecompressBuf(TempData, FResTable[i].Length, 0, pData, OutBytes);
637 FreeMem(TempData);
639 Len := OutBytes;
641 CloseFile(WADFile);
642 except
643 FLastError := DFWAD_ERROR_CANTOPENWAD;
644 CloseFile(WADFile);
645 Exit;
646 end;
647 end
648 else
649 begin
650 TempData := GetMemory(FResTable[i].Length);
651 CopyMemory(TempData, Pointer(NativeUInt(FResData)+FResTable[i].Address+6+
652 LongWord(SizeOf(TWADHeaderRec_1)+SizeOf(TResourceTableRec_1)*Length(FResTable))),
653 FResTable[i].Length);
654 DecompressBuf(TempData, FResTable[i].Length, 0, pData, OutBytes);
655 FreeMem(TempData);
657 Len := OutBytes;
658 end;
660 FLastError := DFWAD_NOERROR;
661 Result := True;
662 end;
664 function TWADEditor_1.GetResourcesList(Section: string): SArray;
665 var
666 a: Integer;
667 CurrentSection: Char16;
668 begin
669 Result := nil;
671 if FResTable = nil then Exit;
672 if Length(Section) > 16 then Exit;
674 CurrentSection := '';
676 for a := 0 to High(FResTable) do
677 begin
678 if FResTable[a].Length = 0 then
679 begin
680 CurrentSection := FResTable[a].ResourceName;
681 Continue;
682 end;
684 if CurrentSection = Section then
685 begin
686 SetLength(Result, Length(Result)+1);
687 Result[High(Result)] := FResTable[a].ResourceName;
688 end;
689 end;
690 end;
692 function TWADEditor_1.GetSectionList(): SArray;
693 var
694 i: DWORD;
695 begin
696 Result := nil;
698 if FResTable = nil then Exit;
700 if FResTable[0].Length <> 0 then
701 begin
702 SetLength(Result, 1);
703 Result[0] := '';
704 end;
706 for i := 0 to High(FResTable) do
707 if FResTable[i].Length = 0 then
708 begin
709 SetLength(Result, Length(Result)+1);
710 Result[High(Result)] := FResTable[i].ResourceName;
711 end;
712 end;
714 function TWADEditor_1.LastErrorString(): string;
715 begin
716 case FLastError of
717 DFWAD_NOERROR: Result := '';
718 DFWAD_ERROR_WADNOTFOUND: Result := 'DFWAD file not found';
719 DFWAD_ERROR_CANTOPENWAD: Result := 'Can''t open DFWAD file';
720 DFWAD_ERROR_RESOURCENOTFOUND: Result := 'Resource not found';
721 DFWAD_ERROR_FILENOTWAD: Result := 'File is not DFWAD';
722 DFWAD_ERROR_WADNOTLOADED: Result := 'DFWAD file is not loaded';
723 DFWAD_ERROR_READRESOURCE: Result := 'Read resource error';
724 DFWAD_ERROR_READWAD: Result := 'Read DFWAD error';
725 else Result := 'Unknown DFWAD error';
726 end;
727 end;
729 function TWADEditor_1.ReadFile(FileName: string): Boolean;
730 var
731 WADFile: File;
732 Signature: array[0..4] of Char;
733 a: Integer;
734 begin
735 FreeWAD();
737 Result := False;
739 if not FileExists(FileName) then
740 begin
741 FLastError := DFWAD_ERROR_WADNOTFOUND;
742 Exit;
743 end;
745 FFileName := FileName;
747 AssignFile(WADFile, FFileName);
749 try
750 Reset(WADFile, 1);
751 except
752 FLastError := DFWAD_ERROR_CANTOPENWAD;
753 Exit;
754 end;
756 try
757 BlockRead(WADFile, Signature, 5);
758 if Signature <> DFWAD_SIGNATURE then
759 begin
760 FLastError := DFWAD_ERROR_FILENOTWAD;
761 CloseFile(WADFile);
762 Exit;
763 end;
765 BlockRead(WADFile, FVersion, 1);
766 if FVersion <> DFWAD_VERSION then
767 begin
768 FLastError := DFWAD_ERROR_WRONGVERSION;
769 CloseFile(WADFile);
770 Exit;
771 end;
773 BlockRead(WADFile, FHeader, SizeOf(TWADHeaderRec_1));
774 SetLength(FResTable, FHeader.RecordsCount);
775 if FResTable <> nil then
776 begin
777 BlockRead(WADFile, FResTable[0], SizeOf(TResourceTableRec_1)*FHeader.RecordsCount);
779 for a := 0 to High(FResTable) do
780 if FResTable[a].Length <> 0 then
781 FResTable[a].Address := FResTable[a].Address-6-(LongWord(SizeOf(TWADHeaderRec_1)+
782 SizeOf(TResourceTableRec_1)*Length(FResTable)));
783 end;
785 CloseFile(WADFile);
786 except
787 FLastError := DFWAD_ERROR_READWAD;
788 CloseFile(WADFile);
789 Exit;
790 end;
792 FWADOpened := DFWAD_OPENED_FILE;
793 FLastError := DFWAD_NOERROR;
794 Result := True;
795 end;
797 function TWADEditor_1.ReadMemory(Data: Pointer; Len: LongWord): Boolean;
798 var
799 Signature: array[0..4] of Char;
800 a: Integer;
801 begin
802 FreeWAD();
804 Result := False;
806 CopyMemory(@Signature[0], Data, 5);
807 if Signature <> DFWAD_SIGNATURE then
808 begin
809 FLastError := DFWAD_ERROR_FILENOTWAD;
810 Exit;
811 end;
813 CopyMemory(@FVersion, Pointer(NativeUInt(Data)+5), 1);
814 if FVersion <> DFWAD_VERSION then
815 begin
816 FLastError := DFWAD_ERROR_WRONGVERSION;
817 Exit;
818 end;
820 CopyMemory(@FHeader, Pointer(NativeUInt(Data)+6), SizeOf(TWADHeaderRec_1));
822 SetLength(FResTable, FHeader.RecordsCount);
823 if FResTable <> nil then
824 begin
825 CopyMemory(@FResTable[0], Pointer(NativeUInt(Data)+6+SizeOf(TWADHeaderRec_1)),
826 SizeOf(TResourceTableRec_1)*FHeader.RecordsCount);
828 for a := 0 to High(FResTable) do
829 if FResTable[a].Length <> 0 then
830 FResTable[a].Address := FResTable[a].Address-6-(LongWord(SizeOf(TWADHeaderRec_1)+
831 SizeOf(TResourceTableRec_1)*Length(FResTable)));
832 end;
834 GetMem(FResData, Len);
835 CopyMemory(FResData, Data, Len);
837 FWADOpened := DFWAD_OPENED_MEMORY;
838 FLastError := DFWAD_NOERROR;
840 Result := True;
841 end;
843 procedure TWADEditor_1.RemoveResource(Section, Resource: string);
844 var
845 a, i: Integer;
846 CurrentSection: Char16;
847 b, c, d: LongWord;
848 begin
849 if FResTable = nil then Exit;
851 i := -1;
852 b := 0;
853 c := 0;
854 CurrentSection := '';
856 for a := 0 to High(FResTable) do
857 begin
858 if FResTable[a].Length = 0 then
859 begin
860 CurrentSection := FResTable[a].ResourceName;
861 Continue;
862 end;
864 if (FResTable[a].ResourceName = Resource) and
865 (CurrentSection = Section) then
866 begin
867 i := a;
868 b := FResTable[a].Length;
869 c := FResTable[a].Address;
870 Break;
871 end;
872 end;
874 if i = -1 then Exit;
876 for a := i to High(FResTable)-1 do
877 FResTable[a] := FResTable[a+1];
879 SetLength(FResTable, Length(FResTable)-1);
881 d := 0;
882 for a := 0 to High(FResTable) do
883 if (FResTable[a].Length <> 0) and (FResTable[a].Address > c) then
884 begin
885 FResTable[a].Address := FResTable[a].Address-b;
886 d := d+FResTable[a].Length;
887 end;
889 CopyMemory(Pointer(LongWord(FResData)+c), Pointer(LongWord(FResData)+c+b), d);
891 FDataSize := FDataSize-b;
892 FOffset := FOffset-b;
893 ReallocMem(FResData, FDataSize);
895 FHeader.RecordsCount := FHeader.RecordsCount-1;
896 end;
898 procedure TWADEditor_1.SaveTo(FileName: string);
899 var
900 WADFile: File;
901 sign: string;
902 ver: Byte;
903 Header: TWADHeaderRec_1;
904 i: Integer;
905 begin
906 sign := DFWAD_SIGNATURE;
907 ver := DFWAD_VERSION;
909 Header.RecordsCount := Length(FResTable);
911 if FResTable <> nil then
912 for i := 0 to High(FResTable) do
913 if FResTable[i].Length <> 0 then
914 FResTable[i].Address := FResTable[i].Address+6+SizeOf(TWADHeaderRec_1)+
915 SizeOf(TResourceTableRec_1)*Header.RecordsCount;
917 AssignFile(WADFile, FileName);
918 Rewrite(WADFile, 1);
919 BlockWrite(WADFile, sign[1], 5);
920 BlockWrite(WADFile, ver, 1);
921 BlockWrite(WADFile, Header, SizeOf(TWADHeaderRec_1));
922 if FResTable <> nil then BlockWrite(WADFile, FResTable[0],
923 SizeOf(TResourceTableRec_1)*Header.RecordsCount);
924 if FResData <> nil then BlockWrite(WADFile, FResData^, FDataSize);
925 CloseFile(WADFile);
926 end;
928 end.