1 (* Copyright (C) DooM 2D:Forever Developers
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.
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.
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/>.
16 {$INCLUDE a_modes.inc}
25 EBinSizeError
= class(Exception
);
27 TBinMemoryWriter
= class
33 procedure WriteVar (var x
; varSize
: LongWord);
34 procedure ExtendMemory (addLen
: LongWord);
37 constructor Create (aSize
: LongWord);
38 destructor Destroy (); override;
40 procedure WriteByte (x
: Byte);
41 procedure WriteWord (x
: Word);
42 procedure WriteDWORD (x
: LongWord);
43 procedure WriteShortInt (x
: ShortInt);
44 procedure WriteSmallInt (x
: SmallInt);
45 procedure WriteInt (x
: LongInt);
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
: LongWord);
50 procedure Fill (aLen
: LongWord; aFillSym
: Byte);
51 procedure SaveToFile (st
: TStream
);
52 procedure SaveToMemory (aMem
: TBinMemoryWriter
);
55 TBinMemoryReader
= class
61 procedure ReadVar (var x
; varSize
: LongWord);
64 constructor Create ();
65 destructor Destroy (); override;
66 procedure ReadByte (var x
: Byte);
67 procedure ReadWord (var x
: Word);
68 procedure ReadDWORD (var x
: LongWord);
69 procedure ReadShortInt (var x
: ShortInt);
70 procedure ReadSmallInt (var x
: SmallInt);
71 procedure ReadInt (var x
: LongInt);
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
: LongWord);
76 procedure Skip (aLen
: LongWord);
77 procedure LoadFromFile (st
: TStream
);
78 procedure LoadFromMemory (aMem
: TBinMemoryReader
);
81 TBinFileWriter
= class
86 constructor Create ();
87 destructor Destroy (); override;
88 procedure OpenFile (const aFileName
: AnsiString; aFileSig
: LongWord;
89 aFileVer
: Byte; aOverWrite
: Boolean=true);
91 procedure WriteMemory (aMemory
: TBinMemoryWriter
);
94 TBinFileReader
= class
99 constructor Create ();
100 destructor Destroy (); override;
101 function OpenFile (const aFileName
: AnsiString; aFileSig
: LongWord; aFileVer
: Byte): Boolean;
103 procedure ReadMemory (aMemory
: TBinMemoryReader
);
106 procedure FillMemory (Dest
: Pointer; Len
: LongWord; Ch
: Byte); inline;
107 procedure CopyMemory (Dest
: Pointer; Src
: Pointer; Len
: LongWord); inline;
108 procedure ZeroMemory (Dest
: Pointer; Len
: LongWord); inline;
117 MAX_BIN_SIZE
= 42*1024*1024; // 42 MB
120 procedure CopyMemory (Dest
: Pointer; Src
: Pointer; Len
: LongWord); inline;
122 Move(Src
^, Dest
^, Len
);
125 procedure FillMemory (Dest
: Pointer; Len
: LongWord; Ch
: Byte); inline;
127 FillChar(Dest
^, Len
, Ch
);
130 procedure ZeroMemory (Dest
: Pointer; Len
: LongWord); inline;
132 FillChar(Dest
^, Len
, 0);
136 { T B i n M e m o r y W r i t e r : }
138 constructor TBinMemoryWriter
.Create (aSize
: LongWord);
140 if (aSize
<= 0) then FSize
:= 1 else FSize
:= aSize
;
141 if (FSize
> MAX_BIN_SIZE
) then FSize
:= MAX_BIN_SIZE
;
142 GetMem(FData
, FSize
);
146 destructor TBinMemoryWriter
.Destroy ();
148 if (FData
<> nil) then
156 procedure TBinMemoryWriter
.WriteVar (var x
; varSize
: LongWord);
158 if (varSize
> 0) then
160 if (FPosition
+varSize
> FSize
) then ExtendMemory(varSize
);
161 CopyMemory(Pointer(PtrUInt(FData
)+FPosition
), @x
, varSize
);
162 FPosition
:= FPosition
+varSize
;
166 procedure TBinMemoryWriter
.ExtendMemory (addLen
: LongWord);
170 while (FPosition
+addLen
> FSize
) and (FSize
<= MAX_BIN_SIZE
) do FSize
:= FSize
*2;
172 if (FSize
> MAX_BIN_SIZE
) then raise EBinSizeError
.Create('TBinMemoryWriter.ExtendMemory: Tried to allocete more than 42 MB');
176 if (FPosition
> 0) then CopyMemory(tmp
, FData
, FPosition
);
181 e_WriteLog('Save Memory Extended: '+IntToStr(FSize
), MSG_NOTIFY
);
184 procedure TBinMemoryWriter
.WriteByte (x
: Byte); begin WriteVar(x
, sizeof(Byte)); end;
185 procedure TBinMemoryWriter
.WriteWord (x
: Word); begin WriteVar(x
, sizeof(Word)); end;
186 procedure TBinMemoryWriter
.WriteDWORD (x
: LongWord); begin WriteVar(x
, sizeof(LongWord)); end;
187 procedure TBinMemoryWriter
.WriteShortInt (x
: ShortInt); begin WriteVar(x
, sizeof(ShortInt)); end;
188 procedure TBinMemoryWriter
.WriteSmallInt (x
: SmallInt); begin WriteVar(x
, sizeof(SmallInt)); end;
189 procedure TBinMemoryWriter
.WriteInt (x
: LongInt); begin WriteVar(x
, sizeof(LongInt)); end;
190 procedure TBinMemoryWriter
.WriteSingle (x
: Single); begin WriteVar(x
, sizeof(Single)); end;
192 procedure TBinMemoryWriter
.WriteBoolean (x
: Boolean);
196 if x
then y
:= 1 else y
:= 0;
197 WriteVar(y
, sizeof(Byte));
200 procedure TBinMemoryWriter
.WriteString (const x
: AnsiString; aMaxLen
: Word=65535);
204 if (Length(x
) > aMaxLen
) then len
:= aMaxLen
else len
:= Word(Length(x
));
206 if (FPosition
+sizeof(Byte)+len
) > FSize
then ExtendMemory(sizeof(Byte)+len
);
209 CopyMemory(Pointer(PtrUInt(FData
)+FPosition
), @len
, sizeof(len
));
210 FPosition
:= FPosition
+sizeof(len
);
214 CopyMemory(Pointer(PtrUInt(FData
) + FPosition
), @x
[1], len
);
215 FPosition
:= FPosition
+len
;
219 procedure TBinMemoryWriter
.WriteMemory (x
: Pointer; memSize
: LongWord);
221 if (FPosition
+sizeof(LongWord)+memSize
) > FSize
then ExtendMemory(sizeof(LongWord)+memSize
);
222 // Äëèíà áëîêà ïàìÿòè
223 CopyMemory(Pointer(PtrUInt(FData
)+FPosition
), @memSize
, sizeof(LongWord));
224 FPosition
:= FPosition
+sizeof(LongWord);
226 if (memSize
> 0) then
228 CopyMemory(Pointer(PtrUInt(FData
)+FPosition
), x
, memSize
);
229 FPosition
:= FPosition
+memSize
;
233 procedure TBinMemoryWriter
.Fill (aLen
: LongWord; aFillSym
: Byte);
235 if (FPosition
+aLen
> FSize
) then ExtendMemory(aLen
);
238 FillMemory(Pointer(PtrUInt(FData
) + FPosition
), aLen
, aFillSym
);
239 FPosition
:= FPosition
+aLen
;
243 procedure TBinMemoryWriter
.SaveToFile (st
: TStream
);
246 utils
.writeInt(st
, LongWord(FPosition
));
248 if (FPosition
> 0) then st
.WriteBuffer(FData
^, FPosition
);
251 procedure TBinMemoryWriter
.SaveToMemory (aMem
: TBinMemoryWriter
);
253 if (aMem
<> nil) then aMem
.WriteMemory(FData
, FPosition
);
257 { T B i n M e m o r y R e a d e r : }
259 constructor TBinMemoryReader
.Create ();
266 destructor TBinMemoryReader
.Destroy ();
268 if (FData
<> nil) then
276 procedure TBinMemoryReader
.ReadVar (var x
; varSize
: LongWord);
278 if (varSize
= 0) then exit
;
279 if (FPosition
+varSize
> FSize
) then raise EBinSizeError
.Create('TBinMemoryReader.ReadVar: End of Memory');
280 CopyMemory(@x
, Pointer(PtrUInt(FData
) + FPosition
), varSize
);
281 FPosition
:= FPosition
+varSize
;
284 procedure TBinMemoryReader
.ReadByte (var x
: Byte); begin ReadVar(x
, sizeof(Byte)); end;
285 procedure TBinMemoryReader
.ReadWord (var x
: Word); begin ReadVar(x
, sizeof(Word)); end;
286 procedure TBinMemoryReader
.ReadDWORD (var x
: LongWord); begin ReadVar(x
, sizeof(LongWord)); end;
287 procedure TBinMemoryReader
.ReadShortInt (var x
: ShortInt); begin ReadVar(x
, sizeof(ShortInt)); end;
288 procedure TBinMemoryReader
.ReadSmallInt (var x
: SmallInt); begin ReadVar(x
, sizeof(SmallInt)); end;
289 procedure TBinMemoryReader
.ReadInt (var x
: LongInt); begin ReadVar(x
, sizeof(LongInt)); end;
290 procedure TBinMemoryReader
.ReadSingle (var x
: Single); begin ReadVar(x
, sizeof(Single)); end;
292 procedure TBinMemoryReader
.ReadBoolean (var x
: Boolean);
296 ReadVar(y
, sizeof(Byte));
300 procedure TBinMemoryReader
.ReadString (var x
: AnsiString);
304 if (FPosition
+sizeof(len
)) <= FSize
then
307 CopyMemory(@len
, Pointer(PtrUInt(FData
)+FPosition
), sizeof(len
));
308 if (FPosition
+sizeof(len
)+len
<= FSize
) then
310 FPosition
:= FPosition
+sizeof(len
);
316 CopyMemory(@x
[1], Pointer(PtrUInt(FData
) + FPosition
), len
);
317 FPosition
:= FPosition
+len
;
326 raise EBinSizeError
.Create('TBinMemoryReader.ReadString: Too Long AnsiString');
331 raise EBinSizeError
.Create('TBinMemoryReader.ReadString: End of Memory');
335 procedure TBinMemoryReader
.ReadMemory (var x
: Pointer; var memSize
: LongWord);
337 if (FPosition
+sizeof(LongWord) > FSize
) then raise EBinSizeError
.Create('TBinMemoryReader.ReadMemory: End of Memory');
338 // Äëèíà áëîêà ïàìÿòè
339 CopyMemory(@memSize
, Pointer(PtrUInt(FData
)+FPosition
), sizeof(LongWord));
340 if (FPosition
+sizeof(LongWord)+memSize
> FSize
) then raise EBinSizeError
.Create('TBinMemoryReader.ReadMemory: Too Long Memory');
341 FPosition
:= FPosition
+sizeof(LongWord);
343 if (memSize
> 0) then
346 CopyMemory(x
, Pointer(PtrUInt(FData
)+FPosition
), memSize
);
347 FPosition
+= memSize
;
355 procedure TBinMemoryReader
.Skip(aLen
: LongWord);
357 if (FPosition
+aLen
> FSize
) then raise EBinSizeError
.Create('TBinMemoryReader.Skip: End of Memory');
361 procedure TBinMemoryReader
.LoadFromFile (st
: TStream
);
365 if (FData
<> nil) then begin FreeMem(FData
); FData
:= nil; end;
367 aSize
:= utils
.readLongWord(st
);
369 GetMem(FData
, FSize
);
372 if (aSize
<> 0) then st
.ReadBuffer(FData
^, FSize
);
376 procedure TBinMemoryReader
.LoadFromMemory (aMem
: TBinMemoryReader
);
378 if (FData
<> nil) then begin FreeMem(FData
); FData
:= nil; end;
379 if (aMem
<> nil) then
381 aMem
.ReadMemory(FData
, FSize
);
387 { T B i n F i l e W r i t e r : }
389 constructor TBinFileWriter
.Create ();
394 destructor TBinFileWriter
.Destroy ();
400 procedure TBinFileWriter
.OpenFile (const aFileName
: AnsiString; aFileSig
: LongWord;
401 aFileVer
: Byte; aOverWrite
: Boolean=true);
404 if (not FileExists(aFileName
)) or aOverWrite
then
407 FHandle
:= createDiskFile(aFileName
);
409 utils
.writeInt(FHandle
, LongWord(aFileSig
));
411 utils
.writeInt(FHandle
, Byte(aFileVer
));
420 procedure TBinFileWriter
.Close();
422 if (FHandle
<> nil) then
429 procedure TBinFileWriter
.WriteMemory (aMemory
: TBinMemoryWriter
);
431 if (FHandle
<> nil) and (aMemory
<> nil) then aMemory
.SaveToFile(FHandle
);
435 { T B i n F i l e R e a d e r : }
437 constructor TBinFileReader
.Create ();
442 destructor TBinFileReader
.Destroy ();
448 function TBinFileReader
.OpenFile (const aFileName
: AnsiString; aFileSig
: LongWord; aFileVer
: Byte): Boolean;
457 if FileExists(aFileName
) then
459 FHandle
:= openDiskFileRO(aFileName
);
462 sig
:= utils
.readLongWord(FHandle
);
463 if (sig
<> aFileSig
) then raise EInOutError
.Create('TBinFileReader.OpenFile: Wrong File Signature');
465 ver
:= utils
.readByte(FHandle
);
466 if (ver
<> aFileVer
) then raise EInOutError
.Create('TBinFileReader.OpenFile: Wrong File Version');
476 procedure TBinFileReader
.Close ();
478 if (FHandle
<> nil) then
485 procedure TBinFileReader
.ReadMemory (aMemory
: TBinMemoryReader
);
487 if (FHandle
<> nil) and (aMemory
<> nil) then aMemory
.LoadFromFile(FHandle
);