DEADSOFTWARE

fixed wadeditor; added nosound mode; fixed codepage problems; fixed pointers; cleanup
[d2df-editor.git] / src / shared / BinEditor.pas
1 Unit BinEditor;
3 Interface
5 Uses
6 SysUtils;
8 Type
9 EBinSizeError = Class (Exception);
11 TBinMemoryWriter = Class (TObject)
12 Private
13 FSize: Cardinal;
14 FData: Pointer;
15 FPosition: Cardinal;
17 Procedure WriteVar(Var x; varSize: Cardinal);
18 Procedure ExtendMemory(addLen: Cardinal);
20 Public
21 Constructor Create(aSize: Cardinal);
22 Destructor Destroy(); Override;
23 Procedure WriteByte(Var x: Byte);
24 Procedure WriteWord(Var x: Word);
25 Procedure WriteDWORD(Var x: DWORD);
26 Procedure WriteShortInt(Var x: ShortInt);
27 Procedure WriteSmallInt(Var x: SmallInt);
28 Procedure WriteInt(Var x: Integer);
29 Procedure WriteSingle(Var x: Single);
30 Procedure WriteBoolean(Var x: Boolean);
31 Procedure WriteString(Var x: String; aMaxLen: Byte = 255);
32 Procedure WriteMemory(Var x: Pointer; memSize: Cardinal);
33 Procedure Fill(aLen: Cardinal; aFillSym: Byte);
34 Procedure SaveToFile(Var aFile: File);
35 Procedure SaveToMemory(Var aMem: TBinMemoryWriter);
36 End;
38 TBinMemoryReader = Class (TObject)
39 Private
40 FSize: Cardinal;
41 FData: Pointer;
42 FPosition: Cardinal;
44 Procedure ReadVar(Var x; varSize: Cardinal);
46 Public
47 Constructor Create();
48 Destructor Destroy(); Override;
49 Procedure ReadByte(Var x: Byte);
50 Procedure ReadWord(Var x: Word);
51 Procedure ReadDWORD(Var x: DWORD);
52 Procedure ReadShortInt(Var x: ShortInt);
53 Procedure ReadSmallInt(Var x: SmallInt);
54 Procedure ReadInt(Var x: Integer);
55 Procedure ReadSingle(Var x: Single);
56 Procedure ReadBoolean(Var x: Boolean);
57 Procedure ReadString(Var x: String);
58 Procedure ReadMemory(Var x: Pointer; Var memSize: Cardinal);
59 Procedure Skip(aLen: Cardinal);
60 Procedure LoadFromFile(Var aFile: File);
61 Procedure LoadFromMemory(Var aMem: TBinMemoryReader);
62 End;
64 TBinFileWriter = Class (TObject)
65 Private
66 FHandle: File;
67 FOpened: Boolean;
69 Public
70 Constructor Create();
71 Destructor Destroy(); Override;
72 Procedure OpenFile(Const aFileName: String;
73 aFileSig: Cardinal;
74 aFileVer: Byte;
75 aOverWrite: Boolean = True);
76 Procedure Close();
77 Procedure WriteMemory(Var aMemory: TBinMemoryWriter);
78 End;
80 TBinFileReader = Class (TObject)
81 Private
82 FHandle: File;
83 FOpened: Boolean;
85 Public
86 Constructor Create();
87 Destructor Destroy(); Override;
88 Function OpenFile(Const aFileName: String;
89 aFileSig: Cardinal;
90 aFileVer: Byte): Boolean;
91 Procedure Close();
92 Procedure ReadMemory(Var aMemory: TBinMemoryReader);
93 End;
95 procedure FillMemory(Dest: Pointer; Len: Cardinal; Ch: Byte);
96 procedure CopyMemory(Dest: Pointer; Src: Pointer; Len: Cardinal);
97 procedure ZeroMemory(Dest: Pointer; Len: Cardinal);
99 Implementation
101 Uses
102 Math, e_log, utils;
104 Const
105 MAX_BIN_SIZE = 4 * 1024 * 1024; // 4 MB
107 procedure CopyMemory(Dest: Pointer; Src: Pointer; Len: Cardinal);
108 begin
109 Move(Src^, Dest^, Len);
110 end;
112 procedure FillMemory(Dest: Pointer; Len: Cardinal; Ch: Byte);
113 begin
114 FillChar(Dest^, Len, Ch);
115 end;
117 procedure ZeroMemory(Dest: Pointer; Len: Cardinal);
118 begin
119 FillChar(Dest^, Len, 0);
120 end;
122 { T B i n M e m o r y W r i t e r : }
124 Constructor TBinMemoryWriter.Create(aSize: Cardinal);
125 begin
126 if aSize <= 0 then
127 FSize := 1
128 else
129 FSize := aSize;
130 if FSize > MAX_BIN_SIZE then
131 FSize := MAX_BIN_SIZE;
133 GetMem(FData, FSize);
134 FPosition := 0;
135 end;
137 Destructor TBinMemoryWriter.Destroy();
138 begin
139 if FData <> nil then
140 begin
141 FreeMem(FData);
142 FData := nil;
143 end;
145 Inherited;
146 end;
148 Procedure TBinMemoryWriter.WriteVar(Var x; varSize: Cardinal);
149 begin
150 if (FPosition + varSize) > FSize then
151 ExtendMemory(varSize);
153 CopyMemory(Pointer(PtrUInt(FData) + FPosition),
154 @x, varSize);
155 FPosition := FPosition + varSize;
156 end;
158 Procedure TBinMemoryWriter.ExtendMemory(addLen: Cardinal);
159 var
160 tmp: Pointer;
162 begin
163 while ((FPosition + addLen) > FSize) and
164 (FSize <= MAX_BIN_SIZE) do
165 FSize := FSize * 2;
167 if FSize > MAX_BIN_SIZE then
168 begin
169 raise EBinSizeError.Create('TBinMemoryWriter.ExtendMemory: Tried to allocete more than 4 MB');
170 Exit;
171 end;
173 GetMem(tmp, FSize);
175 if FPosition > 0 then
176 CopyMemory(tmp, FData, FPosition);
178 FreeMem(FData);
179 FData := tmp;
181 e_WriteLog('Save Memory Extended: '+IntToStr(FSize), MSG_NOTIFY);
182 end;
184 Procedure TBinMemoryWriter.WriteByte(Var x: Byte);
185 begin
186 WriteVar(x, SizeOf(Byte));
187 end;
189 Procedure TBinMemoryWriter.WriteWord(Var x: Word);
190 begin
191 WriteVar(x, SizeOf(Word));
192 end;
194 Procedure TBinMemoryWriter.WriteDWORD(Var x: DWORD);
195 begin
196 WriteVar(x, SizeOf(DWORD));
197 end;
199 Procedure TBinMemoryWriter.WriteShortInt(Var x: ShortInt);
200 begin
201 WriteVar(x, SizeOf(ShortInt));
202 end;
204 Procedure TBinMemoryWriter.WriteSmallInt(Var x: SmallInt);
205 begin
206 WriteVar(x, SizeOf(SmallInt));
207 end;
209 Procedure TBinMemoryWriter.WriteInt(Var x: Integer);
210 begin
211 WriteVar(x, SizeOf(Integer));
212 end;
214 Procedure TBinMemoryWriter.WriteSingle(Var x: Single);
215 begin
216 WriteVar(x, SizeOf(Single));
217 end;
219 Procedure TBinMemoryWriter.WriteBoolean(Var x: Boolean);
220 var
221 y: Byte;
223 begin
224 if x then
225 y := 1
226 else
227 y := 0;
229 WriteVar(y, SizeOf(Byte));
230 end;
232 Procedure TBinMemoryWriter.WriteString(Var x: String; aMaxLen: Byte = 255);
233 var
234 len: Byte;
236 begin
237 len := Min(Length(x), aMaxLen);
239 if (FPosition + SizeOf(Byte) + len) > FSize then
240 ExtendMemory(SizeOf(Byte) + len);
242 // Äëèíà ñòðîêè:
243 CopyMemory(Pointer(PtrUInt(FData) + FPosition),
244 @len, SizeOf(Byte));
245 FPosition := FPosition + SizeOf(Byte);
246 // Ñòðîêà:
247 if len > 0 then
248 begin
249 CopyMemory(Pointer(PtrUInt(FData) + FPosition),
250 @x[1], len);
251 FPosition := FPosition + len;
252 end;
253 end;
255 Procedure TBinMemoryWriter.WriteMemory(Var x: Pointer; memSize: Cardinal);
256 begin
257 if (FPosition + SizeOf(Cardinal) + memSize) > FSize then
258 ExtendMemory(SizeOf(Cardinal) + memSize);
260 // Äëèíà áëîêà ïàìÿòè:
261 CopyMemory(Pointer(PtrUInt(FData) + FPosition),
262 @memSize, SizeOf(Cardinal));
263 FPosition := FPosition + SizeOf(Cardinal);
264 // Áëîê ïàìÿòè:
265 if memSize > 0 then
266 begin
267 CopyMemory(Pointer(PtrUInt(FData) + FPosition),
268 x, memSize);
269 FPosition := FPosition + memSize;
270 end;
271 end;
273 Procedure TBinMemoryWriter.Fill(aLen: Cardinal; aFillSym: Byte);
274 begin
275 if (FPosition + aLen) > FSize then
276 ExtendMemory(aLen);
278 if aLen > 0 then
279 begin
280 FillMemory(Pointer(PtrUInt(FData) + FPosition),
281 aLen, aFillSym);
282 FPosition := FPosition + aLen;
283 end;
284 end;
286 Procedure TBinMemoryWriter.SaveToFile(Var aFile: File);
287 var
288 nw: Cardinal;
290 begin
291 // Ðàçìåð áëîêà:
292 BlockWrite(aFile, FPosition, SizeOf(Cardinal), nw);
293 if nw <> SizeOf(Cardinal) then
294 begin
295 raise EInOutError.Create('TBinMemoryWriter.SaveToFile: Writing Length');
296 end
297 else
298 begin
299 // Äàííûå áëîêà:
300 BlockWrite(aFile, FData^, FPosition, nw);
301 if nw <> FPosition then
302 begin
303 raise EInOutError.Create('TBinMemoryWriter.SaveToFile: Writing Data');
304 end
305 end;
306 end;
308 Procedure TBinMemoryWriter.SaveToMemory(Var aMem: TBinMemoryWriter);
309 begin
310 if aMem <> nil then
311 begin
312 aMem.WriteMemory(FData, FPosition);
313 end;
314 end;
316 { T B i n M e m o r y R e a d e r : }
318 Constructor TBinMemoryReader.Create();
319 begin
320 FSize := 0;
321 FData := nil;
322 FPosition := 1;
323 end;
325 Destructor TBinMemoryReader.Destroy();
326 begin
327 if FData <> nil then
328 begin
329 FreeMem(FData);
330 FData := nil;
331 end;
333 Inherited;
334 end;
336 Procedure TBinMemoryReader.ReadVar(Var x; varSize: Cardinal);
337 begin
338 if (FPosition + varSize) <= FSize then
339 begin
340 CopyMemory(@x,
341 Pointer(PtrUInt(FData) + FPosition),
342 varSize);
343 FPosition := FPosition + varSize;
344 end
345 else
346 raise EBinSizeError.Create('TBinMemoryReader.ReadVar: End of Memory');
347 end;
349 Procedure TBinMemoryReader.ReadByte(Var x: Byte);
350 begin
351 ReadVar(x, SizeOf(Byte));
352 end;
354 Procedure TBinMemoryReader.ReadWord(Var x: Word);
355 begin
356 ReadVar(x, SizeOf(Word));
357 end;
359 Procedure TBinMemoryReader.ReadDWORD(Var x: DWORD);
360 begin
361 ReadVar(x, SizeOf(DWORD));
362 end;
364 Procedure TBinMemoryReader.ReadShortInt(Var x: ShortInt);
365 begin
366 ReadVar(x, SizeOf(ShortInt));
367 end;
369 Procedure TBinMemoryReader.ReadSmallInt(Var x: SmallInt);
370 begin
371 ReadVar(x, SizeOf(SmallInt));
372 end;
374 Procedure TBinMemoryReader.ReadInt(Var x: Integer);
375 begin
376 ReadVar(x, SizeOf(Integer));
377 end;
379 Procedure TBinMemoryReader.ReadSingle(Var x: Single);
380 begin
381 ReadVar(x, SizeOf(Single));
382 end;
384 Procedure TBinMemoryReader.ReadBoolean(Var x: Boolean);
385 var
386 y: Byte;
388 begin
389 ReadVar(y, SizeOf(Byte));
391 if y > 0 then
392 x := True
393 else
394 x := False;
395 end;
397 Procedure TBinMemoryReader.ReadString(Var x: String);
398 var
399 len: Byte;
401 begin
402 if (FPosition + SizeOf(Byte)) <= FSize then
403 begin
404 // Äëèíà ñòðîêè:
405 CopyMemory(@len,
406 Pointer(PtrUInt(FData) + FPosition),
407 SizeOf(Byte));
409 if (FPosition + SizeOf(Byte) + len) <= FSize then
410 begin
411 FPosition := FPosition + SizeOf(Byte);
412 // Ñòðîêà:
413 SetLength(x, len);
414 if len > 0 then
415 begin
416 CopyMemory(@x[1],
417 Pointer(PtrUInt(FData) + FPosition),
418 len);
419 FPosition := FPosition + len;
420 end
421 else
422 x := '';
423 end
424 else
425 raise EBinSizeError.Create('TBinMemoryReader.ReadString: Too Long String');
426 end
427 else
428 raise EBinSizeError.Create('TBinMemoryReader.ReadString: End of Memory');
429 end;
431 Procedure TBinMemoryReader.ReadMemory(Var x: Pointer; Var memSize: Cardinal);
432 begin
433 if (FPosition + SizeOf(Cardinal)) <= FSize then
434 begin
435 // Äëèíà áëîêà ïàìÿòè:
436 CopyMemory(@memSize,
437 Pointer(PtrUInt(FData) + FPosition),
438 SizeOf(Cardinal));
440 if (FPosition + SizeOf(Cardinal) + memSize) <= FSize then
441 begin
442 FPosition := FPosition + SizeOf(Cardinal);
443 // Áëîê ïàìÿòè:
444 if memSize > 0 then
445 begin
446 GetMem(x, memSize);
447 CopyMemory(x,
448 Pointer(PtrUInt(FData) + FPosition),
449 memSize);
450 FPosition := FPosition + memSize;
451 end
452 else
453 x := nil;
454 end
455 else
456 raise EBinSizeError.Create('TBinMemoryReader.ReadMemory: Too Long Memory');
457 end
458 else
459 raise EBinSizeError.Create('TBinMemoryReader.ReadMemory: End of Memory');
460 end;
462 Procedure TBinMemoryReader.Skip(aLen: Cardinal);
463 begin
464 if (FPosition + aLen) <= FSize then
465 begin
466 FPosition := FPosition + aLen;
467 end
468 else
469 raise EBinSizeError.Create('TBinMemoryReader.Skip: End of Memory');
470 end;
472 Procedure TBinMemoryReader.LoadFromFile(Var aFile: File);
473 var
474 nr: Cardinal;
475 aSize: Cardinal;
477 begin
478 if FData <> nil then
479 FreeMem(FData);
481 // Ðàçìåð áëîêà:
482 BlockRead(aFile, aSize, SizeOf(Cardinal), nr);
483 if nr <> SizeOf(Cardinal) then
484 begin
485 raise EInOutError.Create('TBinMemoryReader.LoadFromFile: Reading Length');
486 end
487 else
488 begin
489 FSize := aSize;
490 GetMem(FData, FSize);
491 FPosition := 0;
492 // Äàííûå áëîêà:
493 BlockRead(aFile, FData^, FSize, nr);
494 if nr <> FSize then
495 begin
496 raise EInOutError.Create('TBinMemoryReader.LoadFromFile: Reading Data');
497 end
498 end;
499 end;
501 Procedure TBinMemoryReader.LoadFromMemory(Var aMem: TBinMemoryReader);
502 begin
503 if FData <> nil then
504 FreeMem(FData);
506 if aMem <> nil then
507 begin
508 aMem.ReadMemory(FData, FSize);
509 FPosition := 0;
510 end;
511 end;
513 { T B i n F i l e W r i t e r : }
515 Constructor TBinFileWriter.Create();
516 begin
517 FOpened := False;
518 end;
520 Destructor TBinFileWriter.Destroy();
521 begin
522 Close();
524 Inherited;
525 end;
527 Procedure TBinFileWriter.OpenFile(Const aFileName: String;
528 aFileSig: Cardinal;
529 aFileVer: Byte;
530 aOverWrite: Boolean = True);
531 var
532 nw: Integer;
534 begin
535 Close();
537 if (not FileExists(aFileName)) or (aOverWrite) then
538 begin
539 AssignFile(FHandle, findFileCIStr(aFileName));
540 ReWrite(FHandle, 1);
542 // Ñèãíàòóðà:
543 BlockWrite(FHandle, aFileSig, SizeOf(Cardinal), nw);
544 if nw <> SizeOf(Cardinal) then
545 begin
546 raise EInOutError.Create('TBinFileWriter.OpenFile: Writing File Signature');
547 end
548 else
549 begin
550 // Âåðñèÿ:
551 BlockWrite(FHandle, aFileVer, SizeOf(Byte), nw);
552 if nw <> SizeOf(Byte) then
553 begin
554 raise EInOutError.Create('TBinFileWriter.OpenFile: Writing File Version');
555 end
556 else
557 begin
558 FOpened := True;
559 end;
560 end;
561 end;
562 end;
564 Procedure TBinFileWriter.Close();
565 begin
566 if FOpened then
567 begin
568 System.Close(FHandle);
569 FOpened := False;
570 end;
571 end;
573 Procedure TBinFileWriter.WriteMemory(Var aMemory: TBinMemoryWriter);
574 begin
575 if (FOpened) and (aMemory <> nil) then
576 begin
577 aMemory.SaveToFile(FHandle);
578 end;
579 end;
581 { T B i n F i l e R e a d e r : }
583 Constructor TBinFileReader.Create();
584 begin
585 FOpened := False;
586 end;
588 Destructor TBinFileReader.Destroy();
589 begin
590 Close();
592 Inherited;
593 end;
595 Function TBinFileReader.OpenFile(Const aFileName: String;
596 aFileSig: Cardinal;
597 aFileVer: Byte): Boolean;
598 var
599 nr: Integer;
600 sig: Cardinal;
601 ver: Byte;
603 begin
604 Result := False;
606 Close();
608 if FileExists(aFileName) then
609 begin
610 AssignFile(FHandle, findFileCIStr(aFileName));
611 ReSet(FHandle, 1);
613 // Ñèãíàòóðà:
614 BlockRead(FHandle, sig, SizeOf(Cardinal), nr);
615 if (nr <> SizeOf(Cardinal)) then
616 begin
617 raise EInOutError.Create('TBinFileReader.OpenFile: Reading File Signature');
618 end
619 else
620 if (sig <> aFileSig) then
621 begin
622 raise EInOutError.Create('TBinFileReader.OpenFile: Wrong File Signature');
623 end
624 else
625 begin
626 // Âåðñèÿ:
627 BlockRead(FHandle, ver, SizeOf(Byte), nr);
628 if (nr <> SizeOf(Byte)) then
629 begin
630 raise EInOutError.Create('TBinFileReader.OpenFile: Reading File Version');
631 end
632 else
633 if (ver <> aFileVer) then
634 begin
635 raise EInOutError.Create('TBinFileReader.OpenFile: Wrong File Version');
636 end
637 else
638 begin
639 FOpened := True;
640 Result := True;
641 end;
642 end;
643 end;
644 end;
646 Procedure TBinFileReader.Close();
647 begin
648 if FOpened then
649 begin
650 System.Close(FHandle);
651 FOpened := False;
652 end;
653 end;
655 Procedure TBinFileReader.ReadMemory(Var aMemory: TBinMemoryReader);
656 begin
657 if (FOpened) and (aMemory <> nil) then
658 begin
659 aMemory.LoadFromFile(FHandle);
660 end;
661 end;
664 End.