-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfurqLoader.pas
100 lines (86 loc) · 2.21 KB
/
furqLoader.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
unit furqLoader;
interface
uses
Classes,
SysUtils
;
function FURQLoadQS1(aStream: TStream): string;
function FURQLoadQS2(aStream: TStream): string;
function FURQLoadQST(aStream: TStream): string;
type
EFURQLoadError = class(Exception);
implementation
uses
//JclMath,
furqDecoders;
type
TQS2Header = packed record
rSignature: array[0..3] of Char;
rVersion : Longword;
rLength : Longword;
rCRC32 : Longword;
end;
const
sUnexpectedEndOfStream = 'Íåîæèäàííûé êîíåö äàííûõ';
sCorruptedData = 'Èñïîð÷åííûå äàííûå';
function FURQLoadQS2(aStream: TStream): string;
var
l_B: Byte;
l_Header: TQS2Header;
l_BFLength: Longword;
l_P1, l_P2: Pointer;
l_Mod: Integer;
l_CRC: Longword;
begin
Result := '';
// èùåì íóëåâîé áàéò (òàì âíà÷àëå çàãëóøêà)
l_B := 255;
while (l_B <> 0) do
begin
if aStream.Read(l_B, 1) <> 1 then
raise EFURQLoadError.Create(sUnexpectedEndOfStream);
end;
// ÷èòàåì çàãîëîâîê
if aStream.Read(l_Header, SizeOf(TQS2Header)) <> SizeOf(TQS2Header) then
raise EFURQLoadError.Create(sUnexpectedEndOfStream);
// ïðîâåðÿåì ñèãíàòóðó
if PChar(@l_Header) <> 'QS2' then
raise EFURQLoadError.Create(sCorruptedData);
l_BFLength := l_Header.rLength;
l_Mod := l_Header.rLength mod 8;
if l_Mod <> 0 then
l_BFLength := l_BFLength + 8 - l_Mod;
// ÷èòàåì äàííûå è ðàñøèôðîâûâàåì
l_P1 := GetMemory(l_BFLength);
l_P2 := GetMemory(l_BFLength);
try
if aStream.Read(l_P1^, l_BFLength) <> l_BFLength then
raise EFURQLoadError.Create(sUnexpectedEndOfStream);
BFDecode(l_P1, l_BFLength, l_P2);
QS2Decode(l_P2, l_Header.rLength, l_P1);
{ TODO : Ïðîâåðêà CRC32 }
l_CRC := Crc32(l_P1, l_Header.rLength);
if l_CRC <> l_Header.rCRC32 then
raise EFURQLoadError.Create(sCorruptedData);
SetLength(Result, l_Header.rLength);
Move(l_P1^, Result[1], l_Header.rLength);
finally
FreeMemory(l_P1);
FreeMemory(l_P2);
end;
end;
function FURQLoadQS1(aStream: TStream): string;
begin
Result := FURQLoadQST(aStream);
QS1Decode(Pointer(Result), Length(Result));
end;
function FURQLoadQST(aStream: TStream): string;
var
l_Len: Cardinal;
begin
Result := '';
l_Len := aStream.Size - aStream.Position;
SetLength(Result, l_Len);
aStream.Read(Pointer(Result)^, l_Len);
end;
end.