DEADSOFTWARE

Fix access violation on x86_64
[d2df-sdl.git] / src / shared / BinEditor.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 BinEditor;
19 Interface
21 Uses
22 SysUtils;
24 Type
25 EBinSizeError = Class (Exception);
27 TBinMemoryWriter = Class (TObject)
28 Private
29 FSize: Cardinal;
30 FData: Pointer;
31 FPosition: Cardinal;
33 Procedure WriteVar(Var x; varSize: Cardinal);
34 Procedure ExtendMemory(addLen: Cardinal);
36 Public
37 Constructor Create(aSize: Cardinal);
38 Destructor Destroy(); Override;
39 Procedure WriteByte(Var x: Byte);
40 Procedure WriteWord(Var x: Word);
41 Procedure WriteDWORD(Var x: DWORD);
42 Procedure WriteShortInt(Var x: ShortInt);
43 Procedure WriteSmallInt(Var x: SmallInt);
44 Procedure WriteInt(Var x: Integer);
45 Procedure WriteSingle(Var x: Single);
46 Procedure WriteBoolean(Var x: Boolean);
47 Procedure WriteString(Var x: String; aMaxLen: Byte = 255);
48 Procedure WriteMemory(Var x: Pointer; memSize: Cardinal);
49 Procedure Fill(aLen: Cardinal; aFillSym: Byte);
50 Procedure SaveToFile(Var aFile: File);
51 Procedure SaveToMemory(Var aMem: TBinMemoryWriter);
52 End;
54 TBinMemoryReader = Class (TObject)
55 Private
56 FSize: Cardinal;
57 FData: Pointer;
58 FPosition: Cardinal;
60 Procedure ReadVar(Var x; varSize: Cardinal);
62 Public
63 Constructor Create();
64 Destructor Destroy(); Override;
65 Procedure ReadByte(Var x: Byte);
66 Procedure ReadWord(Var x: Word);
67 Procedure ReadDWORD(Var x: DWORD);
68 Procedure ReadShortInt(Var x: ShortInt);
69 Procedure ReadSmallInt(Var x: SmallInt);
70 Procedure ReadInt(Var x: Integer);
71 Procedure ReadSingle(Var x: Single);
72 Procedure ReadBoolean(Var x: Boolean);
73 Procedure ReadString(Var x: String);
74 Procedure ReadMemory(Var x: Pointer; Var memSize: Cardinal);
75 Procedure Skip(aLen: Cardinal);
76 Procedure LoadFromFile(Var aFile: File);
77 Procedure LoadFromMemory(Var aMem: TBinMemoryReader);
78 End;
80 TBinFileWriter = Class (TObject)
81 Private
82 FHandle: File;
83 FOpened: Boolean;
85 Public
86 Constructor Create();
87 Destructor Destroy(); Override;
88 Procedure OpenFile(Const aFileName: String;
89 aFileSig: Cardinal;
90 aFileVer: Byte;
91 aOverWrite: Boolean = True);
92 Procedure Close();
93 Procedure WriteMemory(Var aMemory: TBinMemoryWriter);
94 End;
96 TBinFileReader = Class (TObject)
97 Private
98 FHandle: File;
99 FOpened: Boolean;
101 Public
102 Constructor Create();
103 Destructor Destroy(); Override;
104 Function OpenFile(Const aFileName: String;
105 aFileSig: Cardinal;
106 aFileVer: Byte): Boolean;
107 Procedure Close();
108 Procedure ReadMemory(Var aMemory: TBinMemoryReader);
109 End;
111 procedure FillMemory(Dest: Pointer; Len: Cardinal; Ch: Byte);
112 procedure CopyMemory(Dest: Pointer; Src: Pointer; Len: Cardinal);
113 procedure ZeroMemory(Dest: Pointer; Len: Cardinal);
115 Implementation
117 Uses
118 Math, e_log;
120 Const
121 MAX_BIN_SIZE = 4 * 1024 * 1024; // 4 MB
123 procedure CopyMemory(Dest: Pointer; Src: Pointer; Len: Cardinal);
124 begin
125 Move(Src^, Dest^, Len);
126 end;
128 procedure FillMemory(Dest: Pointer; Len: Cardinal; Ch: Byte);
129 begin
130 FillChar(Dest^, Len, Ch);
131 end;
133 procedure ZeroMemory(Dest: Pointer; Len: Cardinal);
134 begin
135 FillChar(Dest^, Len, 0);
136 end;
138 { T B i n M e m o r y W r i t e r : }
140 Constructor TBinMemoryWriter.Create(aSize: Cardinal);
141 begin
142 if aSize <= 0 then
143 FSize := 1
144 else
145 FSize := aSize;
146 if FSize > MAX_BIN_SIZE then
147 FSize := MAX_BIN_SIZE;
149 GetMem(FData, FSize);
150 FPosition := 0;
151 end;
153 Destructor TBinMemoryWriter.Destroy();
154 begin
155 if FData <> nil then
156 begin
157 FreeMem(FData);
158 FData := nil;
159 end;
161 Inherited;
162 end;
164 Procedure TBinMemoryWriter.WriteVar(Var x; varSize: Cardinal);
165 begin
166 if (FPosition + varSize) > FSize then
167 ExtendMemory(varSize);
169 CopyMemory(Pointer(NativeInt(FData) + FPosition),
170 @x, varSize);
171 FPosition := FPosition + varSize;
172 end;
174 Procedure TBinMemoryWriter.ExtendMemory(addLen: Cardinal);
175 var
176 tmp: Pointer;
178 begin
179 while ((FPosition + addLen) > FSize) and
180 (FSize <= MAX_BIN_SIZE) do
181 FSize := FSize * 2;
183 if FSize > MAX_BIN_SIZE then
184 begin
185 raise EBinSizeError.Create('TBinMemoryWriter.ExtendMemory: Tried to allocete more than 4 MB');
186 Exit;
187 end;
189 GetMem(tmp, FSize);
191 if FPosition > 0 then
192 CopyMemory(tmp, FData, FPosition);
194 FreeMem(FData);
195 FData := tmp;
197 e_WriteLog('Save Memory Extended: '+IntToStr(FSize), MSG_NOTIFY);
198 end;
200 Procedure TBinMemoryWriter.WriteByte(Var x: Byte);
201 begin
202 WriteVar(x, SizeOf(Byte));
203 end;
205 Procedure TBinMemoryWriter.WriteWord(Var x: Word);
206 begin
207 WriteVar(x, SizeOf(Word));
208 end;
210 Procedure TBinMemoryWriter.WriteDWORD(Var x: DWORD);
211 begin
212 WriteVar(x, SizeOf(DWORD));
213 end;
215 Procedure TBinMemoryWriter.WriteShortInt(Var x: ShortInt);
216 begin
217 WriteVar(x, SizeOf(ShortInt));
218 end;
220 Procedure TBinMemoryWriter.WriteSmallInt(Var x: SmallInt);
221 begin
222 WriteVar(x, SizeOf(SmallInt));
223 end;
225 Procedure TBinMemoryWriter.WriteInt(Var x: Integer);
226 begin
227 WriteVar(x, SizeOf(Integer));
228 end;
230 Procedure TBinMemoryWriter.WriteSingle(Var x: Single);
231 begin
232 WriteVar(x, SizeOf(Single));
233 end;
235 Procedure TBinMemoryWriter.WriteBoolean(Var x: Boolean);
236 var
237 y: Byte;
239 begin
240 if x then
241 y := 1
242 else
243 y := 0;
245 WriteVar(y, SizeOf(Byte));
246 end;
248 Procedure TBinMemoryWriter.WriteString(Var x: String; aMaxLen: Byte = 255);
249 var
250 len: Byte;
252 begin
253 len := Min(Length(x), aMaxLen);
255 if (FPosition + SizeOf(Byte) + len) > FSize then
256 ExtendMemory(SizeOf(Byte) + len);
258 // Äëèíà ñòðîêè:
259 CopyMemory(Pointer(NativeInt(FData) + FPosition),
260 @len, SizeOf(Byte));
261 FPosition := FPosition + SizeOf(Byte);
262 // Ñòðîêà:
263 if len > 0 then
264 begin
265 CopyMemory(Pointer(NativeInt(FData) + FPosition),
266 @x[1], len);
267 FPosition := FPosition + len;
268 end;
269 end;
271 Procedure TBinMemoryWriter.WriteMemory(Var x: Pointer; memSize: Cardinal);
272 begin
273 if (FPosition + SizeOf(Cardinal) + memSize) > FSize then
274 ExtendMemory(SizeOf(Cardinal) + memSize);
276 // Äëèíà áëîêà ïàìÿòè:
277 CopyMemory(Pointer(NativeInt(FData) + FPosition),
278 @memSize, SizeOf(Cardinal));
279 FPosition := FPosition + SizeOf(Cardinal);
280 // Áëîê ïàìÿòè:
281 if memSize > 0 then
282 begin
283 CopyMemory(Pointer(NativeInt(FData) + FPosition),
284 x, memSize);
285 FPosition := FPosition + memSize;
286 end;
287 end;
289 Procedure TBinMemoryWriter.Fill(aLen: Cardinal; aFillSym: Byte);
290 begin
291 if (FPosition + aLen) > FSize then
292 ExtendMemory(aLen);
294 if aLen > 0 then
295 begin
296 FillMemory(Pointer(NativeInt(FData) + FPosition),
297 aLen, aFillSym);
298 FPosition := FPosition + aLen;
299 end;
300 end;
302 Procedure TBinMemoryWriter.SaveToFile(Var aFile: File);
303 var
304 nw: Cardinal;
306 begin
307 // Ðàçìåð áëîêà:
308 BlockWrite(aFile, FPosition, SizeOf(Cardinal), nw);
309 if nw <> SizeOf(Cardinal) then
310 begin
311 raise EInOutError.Create('TBinMemoryWriter.SaveToFile: Writing Length');
312 end
313 else
314 begin
315 // Äàííûå áëîêà:
316 BlockWrite(aFile, FData^, FPosition, nw);
317 if nw <> FPosition then
318 begin
319 raise EInOutError.Create('TBinMemoryWriter.SaveToFile: Writing Data');
320 end
321 end;
322 end;
324 Procedure TBinMemoryWriter.SaveToMemory(Var aMem: TBinMemoryWriter);
325 begin
326 if aMem <> nil then
327 begin
328 aMem.WriteMemory(FData, FPosition);
329 end;
330 end;
332 { T B i n M e m o r y R e a d e r : }
334 Constructor TBinMemoryReader.Create();
335 begin
336 FSize := 0;
337 FData := nil;
338 FPosition := 1;
339 end;
341 Destructor TBinMemoryReader.Destroy();
342 begin
343 if FData <> nil then
344 begin
345 FreeMem(FData);
346 FData := nil;
347 end;
349 Inherited;
350 end;
352 Procedure TBinMemoryReader.ReadVar(Var x; varSize: Cardinal);
353 begin
354 if (FPosition + varSize) <= FSize then
355 begin
356 CopyMemory(@x,
357 Pointer(NativeInt(FData) + FPosition),
358 varSize);
359 FPosition := FPosition + varSize;
360 end
361 else
362 raise EBinSizeError.Create('TBinMemoryReader.ReadVar: End of Memory');
363 end;
365 Procedure TBinMemoryReader.ReadByte(Var x: Byte);
366 begin
367 ReadVar(x, SizeOf(Byte));
368 end;
370 Procedure TBinMemoryReader.ReadWord(Var x: Word);
371 begin
372 ReadVar(x, SizeOf(Word));
373 end;
375 Procedure TBinMemoryReader.ReadDWORD(Var x: DWORD);
376 begin
377 ReadVar(x, SizeOf(DWORD));
378 end;
380 Procedure TBinMemoryReader.ReadShortInt(Var x: ShortInt);
381 begin
382 ReadVar(x, SizeOf(ShortInt));
383 end;
385 Procedure TBinMemoryReader.ReadSmallInt(Var x: SmallInt);
386 begin
387 ReadVar(x, SizeOf(SmallInt));
388 end;
390 Procedure TBinMemoryReader.ReadInt(Var x: Integer);
391 begin
392 ReadVar(x, SizeOf(Integer));
393 end;
395 Procedure TBinMemoryReader.ReadSingle(Var x: Single);
396 begin
397 ReadVar(x, SizeOf(Single));
398 end;
400 Procedure TBinMemoryReader.ReadBoolean(Var x: Boolean);
401 var
402 y: Byte;
404 begin
405 ReadVar(y, SizeOf(Byte));
407 if y > 0 then
408 x := True
409 else
410 x := False;
411 end;
413 Procedure TBinMemoryReader.ReadString(Var x: String);
414 var
415 len: Byte;
417 begin
418 if (FPosition + SizeOf(Byte)) <= FSize then
419 begin
420 // Äëèíà ñòðîêè:
421 CopyMemory(@len,
422 Pointer(NativeInt(FData) + FPosition),
423 SizeOf(Byte));
425 if (FPosition + SizeOf(Byte) + len) <= FSize then
426 begin
427 FPosition := FPosition + SizeOf(Byte);
428 // Ñòðîêà:
429 SetLength(x, len);
430 if len > 0 then
431 begin
432 CopyMemory(@x[1],
433 Pointer(NativeInt(FData) + FPosition),
434 len);
435 FPosition := FPosition + len;
436 end
437 else
438 x := '';
439 end
440 else
441 raise EBinSizeError.Create('TBinMemoryReader.ReadString: Too Long String');
442 end
443 else
444 raise EBinSizeError.Create('TBinMemoryReader.ReadString: End of Memory');
445 end;
447 Procedure TBinMemoryReader.ReadMemory(Var x: Pointer; Var memSize: Cardinal);
448 begin
449 if (FPosition + SizeOf(Cardinal)) <= FSize then
450 begin
451 // Äëèíà áëîêà ïàìÿòè:
452 CopyMemory(@memSize,
453 Pointer((FData) + FPosition),
454 SizeOf(Cardinal));
456 if (FPosition + SizeOf(Cardinal) + memSize) <= FSize then
457 begin
458 FPosition := FPosition + SizeOf(Cardinal);
459 // Áëîê ïàìÿòè:
460 if memSize > 0 then
461 begin
462 GetMem(x, memSize);
463 CopyMemory(x,
464 Pointer(NativeInt(FData) + FPosition),
465 memSize);
466 FPosition := FPosition + memSize;
467 end
468 else
469 x := nil;
470 end
471 else
472 raise EBinSizeError.Create('TBinMemoryReader.ReadMemory: Too Long Memory');
473 end
474 else
475 raise EBinSizeError.Create('TBinMemoryReader.ReadMemory: End of Memory');
476 end;
478 Procedure TBinMemoryReader.Skip(aLen: Cardinal);
479 begin
480 if (FPosition + aLen) <= FSize then
481 begin
482 FPosition := FPosition + aLen;
483 end
484 else
485 raise EBinSizeError.Create('TBinMemoryReader.Skip: End of Memory');
486 end;
488 Procedure TBinMemoryReader.LoadFromFile(Var aFile: File);
489 var
490 nr: Cardinal;
491 aSize: Cardinal;
493 begin
494 if FData <> nil then
495 FreeMem(FData);
497 // Ðàçìåð áëîêà:
498 BlockRead(aFile, aSize, SizeOf(Cardinal), nr);
499 if nr <> SizeOf(Cardinal) then
500 begin
501 raise EInOutError.Create('TBinMemoryReader.LoadFromFile: Reading Length');
502 end
503 else
504 begin
505 FSize := aSize;
506 GetMem(FData, FSize);
507 FPosition := 0;
508 // Äàííûå áëîêà:
509 BlockRead(aFile, FData^, FSize, nr);
510 if nr <> FSize then
511 begin
512 raise EInOutError.Create('TBinMemoryReader.LoadFromFile: Reading Data');
513 end
514 end;
515 end;
517 Procedure TBinMemoryReader.LoadFromMemory(Var aMem: TBinMemoryReader);
518 begin
519 if FData <> nil then
520 FreeMem(FData);
522 if aMem <> nil then
523 begin
524 aMem.ReadMemory(FData, FSize);
525 FPosition := 0;
526 end;
527 end;
529 { T B i n F i l e W r i t e r : }
531 Constructor TBinFileWriter.Create();
532 begin
533 FOpened := False;
534 end;
536 Destructor TBinFileWriter.Destroy();
537 begin
538 Close();
540 Inherited;
541 end;
543 Procedure TBinFileWriter.OpenFile(Const aFileName: String;
544 aFileSig: Cardinal;
545 aFileVer: Byte;
546 aOverWrite: Boolean = True);
547 var
548 nw: Integer;
550 begin
551 Close();
553 if (not FileExists(aFileName)) or (aOverWrite) then
554 begin
555 AssignFile(FHandle, aFileName);
556 ReWrite(FHandle, 1);
558 // Ñèãíàòóðà:
559 BlockWrite(FHandle, aFileSig, SizeOf(Cardinal), nw);
560 if nw <> SizeOf(Cardinal) then
561 begin
562 raise EInOutError.Create('TBinFileWriter.OpenFile: Writing File Signature');
563 end
564 else
565 begin
566 // Âåðñèÿ:
567 BlockWrite(FHandle, aFileVer, SizeOf(Byte), nw);
568 if nw <> SizeOf(Byte) then
569 begin
570 raise EInOutError.Create('TBinFileWriter.OpenFile: Writing File Version');
571 end
572 else
573 begin
574 FOpened := True;
575 end;
576 end;
577 end;
578 end;
580 Procedure TBinFileWriter.Close();
581 begin
582 if FOpened then
583 begin
584 System.Close(FHandle);
585 FOpened := False;
586 end;
587 end;
589 Procedure TBinFileWriter.WriteMemory(Var aMemory: TBinMemoryWriter);
590 begin
591 if (FOpened) and (aMemory <> nil) then
592 begin
593 aMemory.SaveToFile(FHandle);
594 end;
595 end;
597 { T B i n F i l e R e a d e r : }
599 Constructor TBinFileReader.Create();
600 begin
601 FOpened := False;
602 end;
604 Destructor TBinFileReader.Destroy();
605 begin
606 Close();
608 Inherited;
609 end;
611 Function TBinFileReader.OpenFile(Const aFileName: String;
612 aFileSig: Cardinal;
613 aFileVer: Byte): Boolean;
614 var
615 nr: Integer;
616 sig: Cardinal;
617 ver: Byte;
619 begin
620 Result := False;
622 Close();
624 if FileExists(aFileName) then
625 begin
626 AssignFile(FHandle, aFileName);
627 ReSet(FHandle, 1);
629 // Ñèãíàòóðà:
630 BlockRead(FHandle, sig, SizeOf(Cardinal), nr);
631 if (nr <> SizeOf(Cardinal)) then
632 begin
633 raise EInOutError.Create('TBinFileReader.OpenFile: Reading File Signature');
634 end
635 else
636 if (sig <> aFileSig) then
637 begin
638 raise EInOutError.Create('TBinFileReader.OpenFile: Wrong File Signature');
639 end
640 else
641 begin
642 // Âåðñèÿ:
643 BlockRead(FHandle, ver, SizeOf(Byte), nr);
644 if (nr <> SizeOf(Byte)) then
645 begin
646 raise EInOutError.Create('TBinFileReader.OpenFile: Reading File Version');
647 end
648 else
649 if (ver <> aFileVer) then
650 begin
651 raise EInOutError.Create('TBinFileReader.OpenFile: Wrong File Version');
652 end
653 else
654 begin
655 FOpened := True;
656 Result := True;
657 end;
658 end;
659 end;
660 end;
662 Procedure TBinFileReader.Close();
663 begin
664 if FOpened then
665 begin
666 System.Close(FHandle);
667 FOpened := False;
668 end;
669 end;
671 Procedure TBinFileReader.ReadMemory(Var aMemory: TBinMemoryReader);
672 begin
673 if (FOpened) and (aMemory <> nil) then
674 begin
675 aMemory.LoadFromFile(FHandle);
676 end;
677 end;
680 End.