DEADSOFTWARE

some more exoma code
[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 {$INCLUDE a_modes.inc}
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;
40 Procedure WriteByte (x: Byte);
41 Procedure WriteWord (x: Word);
42 Procedure WriteDWORD (x: DWORD);
43 Procedure WriteShortInt (x: ShortInt);
44 Procedure WriteSmallInt (x: SmallInt);
45 Procedure WriteInt (x: Integer);
46 Procedure WriteSingle (x: Single);
47 Procedure WriteBoolean (x: Boolean);
48 Procedure WriteString (const x: AnsiString; aMaxLen: Word=65535);
49 Procedure WriteMemory (x: Pointer; memSize: Cardinal);
50 Procedure Fill (aLen: Cardinal; aFillSym: Byte);
51 Procedure SaveToFile (Var aFile: File);
52 Procedure SaveToMemory (Var aMem: TBinMemoryWriter);
53 End;
55 TBinMemoryReader = Class (TObject)
56 Private
57 FSize: Cardinal;
58 FData: Pointer;
59 FPosition: Cardinal;
61 Procedure ReadVar(Var x; varSize: Cardinal);
63 Public
64 Constructor Create();
65 Destructor Destroy(); Override;
66 Procedure ReadByte(Var x: Byte);
67 Procedure ReadWord(Var x: Word);
68 Procedure ReadDWORD(Var x: DWORD);
69 Procedure ReadShortInt(Var x: ShortInt);
70 Procedure ReadSmallInt(Var x: SmallInt);
71 Procedure ReadInt(Var x: Integer);
72 Procedure ReadSingle(Var x: Single);
73 Procedure ReadBoolean(Var x: Boolean);
74 Procedure ReadString(Var x: AnsiString);
75 Procedure ReadMemory(Var x: Pointer; Var memSize: Cardinal);
76 Procedure Skip(aLen: Cardinal);
77 Procedure LoadFromFile(Var aFile: File);
78 Procedure LoadFromMemory(Var aMem: TBinMemoryReader);
79 End;
81 TBinFileWriter = Class (TObject)
82 Private
83 FHandle: File;
84 FOpened: Boolean;
86 Public
87 Constructor Create();
88 Destructor Destroy(); Override;
89 Procedure OpenFile(Const aFileName: String;
90 aFileSig: Cardinal;
91 aFileVer: Byte;
92 aOverWrite: Boolean = True);
93 Procedure Close();
94 Procedure WriteMemory(Var aMemory: TBinMemoryWriter);
95 End;
97 TBinFileReader = Class (TObject)
98 Private
99 FHandle: File;
100 FOpened: Boolean;
102 Public
103 Constructor Create();
104 Destructor Destroy(); Override;
105 Function OpenFile(Const aFileName: String;
106 aFileSig: Cardinal;
107 aFileVer: Byte): Boolean;
108 Procedure Close();
109 Procedure ReadMemory(Var aMemory: TBinMemoryReader);
110 End;
112 procedure FillMemory(Dest: Pointer; Len: Cardinal; Ch: Byte);
113 procedure CopyMemory(Dest: Pointer; Src: Pointer; Len: Cardinal);
114 procedure ZeroMemory(Dest: Pointer; Len: Cardinal);
116 Implementation
118 Uses
119 Math, e_log;
121 Const
122 MAX_BIN_SIZE = 4 * 1024 * 1024; // 4 MB
124 procedure CopyMemory(Dest: Pointer; Src: Pointer; Len: Cardinal);
125 begin
126 Move(Src^, Dest^, Len);
127 end;
129 procedure FillMemory(Dest: Pointer; Len: Cardinal; Ch: Byte);
130 begin
131 FillChar(Dest^, Len, Ch);
132 end;
134 procedure ZeroMemory(Dest: Pointer; Len: Cardinal);
135 begin
136 FillChar(Dest^, Len, 0);
137 end;
139 { T B i n M e m o r y W r i t e r : }
141 Constructor TBinMemoryWriter.Create(aSize: Cardinal);
142 begin
143 if aSize <= 0 then
144 FSize := 1
145 else
146 FSize := aSize;
147 if FSize > MAX_BIN_SIZE then
148 FSize := MAX_BIN_SIZE;
150 GetMem(FData, FSize);
151 FPosition := 0;
152 end;
154 Destructor TBinMemoryWriter.Destroy();
155 begin
156 if FData <> nil then
157 begin
158 FreeMem(FData);
159 FData := nil;
160 end;
162 Inherited;
163 end;
165 Procedure TBinMemoryWriter.WriteVar (var x; varSize: Cardinal);
166 begin
167 if (FPosition+varSize > FSize) then ExtendMemory(varSize);
168 CopyMemory(Pointer(PtrUInt(FData)+FPosition), @x, varSize);
169 FPosition := FPosition+varSize;
170 end;
172 Procedure TBinMemoryWriter.ExtendMemory(addLen: Cardinal);
173 var
174 tmp: Pointer;
176 begin
177 while ((FPosition + addLen) > FSize) and
178 (FSize <= MAX_BIN_SIZE) do
179 FSize := FSize * 2;
181 if FSize > MAX_BIN_SIZE then
182 begin
183 raise EBinSizeError.Create('TBinMemoryWriter.ExtendMemory: Tried to allocete more than 4 MB');
184 Exit;
185 end;
187 GetMem(tmp, FSize);
189 if FPosition > 0 then
190 CopyMemory(tmp, FData, FPosition);
192 FreeMem(FData);
193 FData := tmp;
195 e_WriteLog('Save Memory Extended: '+IntToStr(FSize), MSG_NOTIFY);
196 end;
198 Procedure TBinMemoryWriter.WriteByte (x: Byte);
199 begin
200 WriteVar(x, SizeOf(Byte));
201 end;
203 Procedure TBinMemoryWriter.WriteWord (x: Word);
204 begin
205 WriteVar(x, SizeOf(Word));
206 end;
208 Procedure TBinMemoryWriter.WriteDWORD (x: DWORD);
209 begin
210 WriteVar(x, SizeOf(DWORD));
211 end;
213 Procedure TBinMemoryWriter.WriteShortInt (x: ShortInt);
214 begin
215 WriteVar(x, SizeOf(ShortInt));
216 end;
218 Procedure TBinMemoryWriter.WriteSmallInt (x: SmallInt);
219 begin
220 WriteVar(x, SizeOf(SmallInt));
221 end;
223 Procedure TBinMemoryWriter.WriteInt (x: Integer);
224 begin
225 WriteVar(x, SizeOf(Integer));
226 end;
228 Procedure TBinMemoryWriter.WriteSingle (x: Single);
229 begin
230 WriteVar(x, SizeOf(Single));
231 end;
233 Procedure TBinMemoryWriter.WriteBoolean (x: Boolean);
234 var
235 y: Byte;
236 begin
237 if x then y := 1 else y := 0;
238 WriteVar(y, SizeOf(Byte));
239 end;
241 Procedure TBinMemoryWriter.WriteString (const x: AnsiString; aMaxLen: Word=65535);
242 var
243 len: Word;
244 begin
245 if (Length(x) > aMaxLen) then len := aMaxLen else len := Word(Length(x));
247 if (FPosition+SizeOf(Byte)+len) > FSize then ExtendMemory(SizeOf(Byte)+len);
249 // Äëèíà ñòðîêè:
250 CopyMemory(Pointer(NativeUInt(FData)+FPosition), @len, SizeOf(len));
251 FPosition := FPosition+SizeOf(len);
252 // Ñòðîêà:
253 if (len > 0) then
254 begin
255 CopyMemory(Pointer(NativeUInt(FData) + FPosition), @x[1], len);
256 FPosition := FPosition+len;
257 end;
258 end;
260 Procedure TBinMemoryWriter.WriteMemory (x: Pointer; memSize: Cardinal);
261 begin
262 if (FPosition+SizeOf(Cardinal)+memSize) > FSize then ExtendMemory(SizeOf(Cardinal)+memSize);
263 // Äëèíà áëîêà ïàìÿòè
264 CopyMemory(Pointer(PtrUInt(FData)+FPosition), @memSize, SizeOf(Cardinal));
265 FPosition := FPosition+SizeOf(Cardinal);
266 // Áëîê ïàìÿòè
267 if (memSize > 0) then
268 begin
269 CopyMemory(Pointer(PtrUInt(FData)+FPosition), x, memSize);
270 FPosition := FPosition+memSize;
271 end;
272 end;
274 Procedure TBinMemoryWriter.Fill (aLen: Cardinal; aFillSym: Byte);
275 begin
276 if (FPosition+aLen > FSize) then ExtendMemory(aLen);
277 if (aLen > 0) then
278 begin
279 FillMemory(Pointer(PtrUInt(FData) + FPosition), aLen, aFillSym);
280 FPosition := FPosition+aLen;
281 end;
282 end;
284 Procedure TBinMemoryWriter.SaveToFile(Var aFile: File);
285 var
286 nw: Cardinal;
288 begin
289 // Ðàçìåð áëîêà:
290 BlockWrite(aFile, FPosition, SizeOf(Cardinal), nw);
291 if nw <> SizeOf(Cardinal) then
292 begin
293 raise EInOutError.Create('TBinMemoryWriter.SaveToFile: Writing Length');
294 end
295 else
296 begin
297 // Äàííûå áëîêà:
298 BlockWrite(aFile, FData^, FPosition, nw);
299 if nw <> FPosition then
300 begin
301 raise EInOutError.Create('TBinMemoryWriter.SaveToFile: Writing Data');
302 end
303 end;
304 end;
306 Procedure TBinMemoryWriter.SaveToMemory(Var aMem: TBinMemoryWriter);
307 begin
308 if aMem <> nil then
309 begin
310 aMem.WriteMemory(FData, FPosition);
311 end;
312 end;
314 { T B i n M e m o r y R e a d e r : }
316 Constructor TBinMemoryReader.Create();
317 begin
318 FSize := 0;
319 FData := nil;
320 FPosition := 1;
321 end;
323 Destructor TBinMemoryReader.Destroy();
324 begin
325 if FData <> nil then
326 begin
327 FreeMem(FData);
328 FData := nil;
329 end;
331 Inherited;
332 end;
334 Procedure TBinMemoryReader.ReadVar(Var x; varSize: Cardinal);
335 begin
336 if (FPosition + varSize) <= FSize then
337 begin
338 CopyMemory(@x,
339 Pointer(NativeUInt(FData) + FPosition),
340 varSize);
341 FPosition := FPosition + varSize;
342 end
343 else
344 raise EBinSizeError.Create('TBinMemoryReader.ReadVar: End of Memory');
345 end;
347 Procedure TBinMemoryReader.ReadByte(Var x: Byte);
348 begin
349 ReadVar(x, SizeOf(Byte));
350 end;
352 Procedure TBinMemoryReader.ReadWord(Var x: Word);
353 begin
354 ReadVar(x, SizeOf(Word));
355 end;
357 Procedure TBinMemoryReader.ReadDWORD(Var x: DWORD);
358 begin
359 ReadVar(x, SizeOf(DWORD));
360 end;
362 Procedure TBinMemoryReader.ReadShortInt(Var x: ShortInt);
363 begin
364 ReadVar(x, SizeOf(ShortInt));
365 end;
367 Procedure TBinMemoryReader.ReadSmallInt(Var x: SmallInt);
368 begin
369 ReadVar(x, SizeOf(SmallInt));
370 end;
372 Procedure TBinMemoryReader.ReadInt(Var x: Integer);
373 begin
374 ReadVar(x, SizeOf(Integer));
375 end;
377 Procedure TBinMemoryReader.ReadSingle(Var x: Single);
378 begin
379 ReadVar(x, SizeOf(Single));
380 end;
382 Procedure TBinMemoryReader.ReadBoolean(Var x: Boolean);
383 var
384 y: Byte;
386 begin
387 ReadVar(y, SizeOf(Byte));
389 if y > 0 then
390 x := True
391 else
392 x := False;
393 end;
395 Procedure TBinMemoryReader.ReadString (Var x: AnsiString);
396 var
397 len: Word;
398 begin
399 if (FPosition+SizeOf(len)) <= FSize then
400 begin
401 // Äëèíà ñòðîêè:
402 CopyMemory(@len, Pointer(NativeUInt(FData)+FPosition), SizeOf(len));
403 if (FPosition+SizeOf(len)+len <= FSize) then
404 begin
405 FPosition := FPosition+SizeOf(len);
406 // Ñòðîêà:
407 UniqueString(x);
408 SetLength(x, len);
409 if (len > 0) then
410 begin
411 CopyMemory(@x[1], Pointer(NativeUInt(FData) + FPosition), len);
412 FPosition := FPosition+len;
413 end
414 else
415 begin
416 x := '';
417 end;
418 end
419 else
420 begin
421 raise EBinSizeError.Create('TBinMemoryReader.ReadString: Too Long String');
422 end;
423 end
424 else
425 begin
426 raise EBinSizeError.Create('TBinMemoryReader.ReadString: End of Memory');
427 end;
428 end;
430 Procedure TBinMemoryReader.ReadMemory(Var x: Pointer; Var memSize: Cardinal);
431 begin
432 if (FPosition + SizeOf(Cardinal)) <= FSize then
433 begin
434 // Äëèíà áëîêà ïàìÿòè:
435 CopyMemory(@memSize,
436 Pointer(NativeUInt(FData) + FPosition),
437 SizeOf(Cardinal));
439 if (FPosition + SizeOf(Cardinal) + memSize) <= FSize then
440 begin
441 FPosition := FPosition + SizeOf(Cardinal);
442 // Áëîê ïàìÿòè:
443 if memSize > 0 then
444 begin
445 GetMem(x, memSize);
446 CopyMemory(x,
447 Pointer(NativeUInt(FData) + FPosition),
448 memSize);
449 FPosition := FPosition + memSize;
450 end
451 else
452 x := nil;
453 end
454 else
455 raise EBinSizeError.Create('TBinMemoryReader.ReadMemory: Too Long Memory');
456 end
457 else
458 raise EBinSizeError.Create('TBinMemoryReader.ReadMemory: End of Memory');
459 end;
461 Procedure TBinMemoryReader.Skip(aLen: Cardinal);
462 begin
463 if (FPosition + aLen) <= FSize then
464 begin
465 FPosition := FPosition + aLen;
466 end
467 else
468 raise EBinSizeError.Create('TBinMemoryReader.Skip: End of Memory');
469 end;
471 Procedure TBinMemoryReader.LoadFromFile(Var aFile: File);
472 var
473 nr: Cardinal;
474 aSize: Cardinal;
476 begin
477 if FData <> nil then
478 FreeMem(FData);
480 // Ðàçìåð áëîêà:
481 BlockRead(aFile, aSize, SizeOf(Cardinal), nr);
482 if nr <> SizeOf(Cardinal) then
483 begin
484 raise EInOutError.Create('TBinMemoryReader.LoadFromFile: Reading Length');
485 end
486 else
487 begin
488 FSize := aSize;
489 GetMem(FData, FSize);
490 FPosition := 0;
491 // Äàííûå áëîêà:
492 BlockRead(aFile, FData^, FSize, nr);
493 if nr <> FSize then
494 begin
495 raise EInOutError.Create('TBinMemoryReader.LoadFromFile: Reading Data');
496 end
497 end;
498 end;
500 Procedure TBinMemoryReader.LoadFromMemory(Var aMem: TBinMemoryReader);
501 begin
502 if FData <> nil then
503 FreeMem(FData);
505 if aMem <> nil then
506 begin
507 aMem.ReadMemory(FData, FSize);
508 FPosition := 0;
509 end;
510 end;
512 { T B i n F i l e W r i t e r : }
514 Constructor TBinFileWriter.Create();
515 begin
516 FOpened := False;
517 end;
519 Destructor TBinFileWriter.Destroy();
520 begin
521 Close();
523 Inherited;
524 end;
526 Procedure TBinFileWriter.OpenFile(Const aFileName: String;
527 aFileSig: Cardinal;
528 aFileVer: Byte;
529 aOverWrite: Boolean = True);
530 var
531 nw: Integer;
533 begin
534 Close();
536 if (not FileExists(aFileName)) or (aOverWrite) then
537 begin
538 AssignFile(FHandle, aFileName);
539 ReWrite(FHandle, 1);
541 // Ñèãíàòóðà:
542 BlockWrite(FHandle, aFileSig, SizeOf(Cardinal), nw);
543 if nw <> SizeOf(Cardinal) then
544 begin
545 raise EInOutError.Create('TBinFileWriter.OpenFile: Writing File Signature');
546 end
547 else
548 begin
549 // Âåðñèÿ:
550 BlockWrite(FHandle, aFileVer, SizeOf(Byte), nw);
551 if nw <> SizeOf(Byte) then
552 begin
553 raise EInOutError.Create('TBinFileWriter.OpenFile: Writing File Version');
554 end
555 else
556 begin
557 FOpened := True;
558 end;
559 end;
560 end;
561 end;
563 Procedure TBinFileWriter.Close();
564 begin
565 if FOpened then
566 begin
567 System.Close(FHandle);
568 FOpened := False;
569 end;
570 end;
572 Procedure TBinFileWriter.WriteMemory(Var aMemory: TBinMemoryWriter);
573 begin
574 if (FOpened) and (aMemory <> nil) then
575 begin
576 aMemory.SaveToFile(FHandle);
577 end;
578 end;
580 { T B i n F i l e R e a d e r : }
582 Constructor TBinFileReader.Create();
583 begin
584 FOpened := False;
585 end;
587 Destructor TBinFileReader.Destroy();
588 begin
589 Close();
591 Inherited;
592 end;
594 Function TBinFileReader.OpenFile(Const aFileName: String;
595 aFileSig: Cardinal;
596 aFileVer: Byte): Boolean;
597 var
598 nr: Integer;
599 sig: Cardinal;
600 ver: Byte;
602 begin
603 Result := False;
605 Close();
607 if FileExists(aFileName) then
608 begin
609 AssignFile(FHandle, aFileName);
610 ReSet(FHandle, 1);
612 // Ñèãíàòóðà:
613 BlockRead(FHandle, sig, SizeOf(Cardinal), nr);
614 if (nr <> SizeOf(Cardinal)) then
615 begin
616 raise EInOutError.Create('TBinFileReader.OpenFile: Reading File Signature');
617 end
618 else
619 if (sig <> aFileSig) then
620 begin
621 raise EInOutError.Create('TBinFileReader.OpenFile: Wrong File Signature');
622 end
623 else
624 begin
625 // Âåðñèÿ:
626 BlockRead(FHandle, ver, SizeOf(Byte), nr);
627 if (nr <> SizeOf(Byte)) then
628 begin
629 raise EInOutError.Create('TBinFileReader.OpenFile: Reading File Version');
630 end
631 else
632 if (ver <> aFileVer) then
633 begin
634 raise EInOutError.Create('TBinFileReader.OpenFile: Wrong File Version');
635 end
636 else
637 begin
638 FOpened := True;
639 Result := True;
640 end;
641 end;
642 end;
643 end;
645 Procedure TBinFileReader.Close();
646 begin
647 if FOpened then
648 begin
649 System.Close(FHandle);
650 FOpened := False;
651 end;
652 end;
654 Procedure TBinFileReader.ReadMemory(Var aMemory: TBinMemoryReader);
655 begin
656 if (FOpened) and (aMemory <> nil) then
657 begin
658 aMemory.LoadFromFile(FHandle);
659 end;
660 end;
663 End.