Skip to content

Commit ca16a78

Browse files
committed
Forgot BIG_File.pas !
1 parent 61029e6 commit ca16a78

File tree

1 file changed

+361
-0
lines changed

1 file changed

+361
-0
lines changed

src/BIG_File.pas

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
unit BIG_File;
2+
3+
interface
4+
5+
uses
6+
BasicDataTypes, SysUtils, Classes, Dialogs;
7+
8+
const
9+
C_BIG4 = $34474942;
10+
C_BIGF = $46474942;
11+
12+
type
13+
TBIGFileUnit = record
14+
Offset : uint32;
15+
Size : uint32;
16+
Filename : string;
17+
FileWritten : Boolean;
18+
Index : integer;
19+
end;
20+
21+
TBIGPackage = class
22+
private
23+
ValidFile : boolean;
24+
Filename : string;
25+
BIGType : uint32;
26+
Size : uint32;
27+
Files : array of TBIGFileUnit;
28+
// Constructors and Destructors
29+
procedure Reset;
30+
// I/O
31+
function InvertInteger(_i: uint32): uint32;
32+
function InvertInteger16(_i: uint16): uint16;
33+
procedure DecompressData(var _Input,_OutPut: puint8);
34+
public
35+
// Constructors and Destructors
36+
constructor Create;
37+
// I/O
38+
procedure LoadFile(const _Filename : string);
39+
// Gets
40+
function GetNumFiles : uint32;
41+
function GetFileInfo (_ID : int32): TBIGFileUnit;
42+
function GetFileContents( _ID : int32; var _Data : TStream; var _DataSize : uint32) : Boolean;
43+
function IsValid : boolean;
44+
// Sets
45+
end;
46+
47+
implementation
48+
49+
// Constructors and Destructors
50+
constructor TBIGPackage.Create;
51+
begin
52+
Reset;
53+
end;
54+
55+
procedure TBIGPackage.Reset;
56+
begin
57+
ValidFile := false;
58+
SetLength(Files,0);
59+
end;
60+
61+
procedure TBIGPackage.LoadFile(const _Filename : string);
62+
var
63+
MyFile : TStream;
64+
FileSize: uint32;
65+
PData, PCurrentData: pint8;
66+
HeaderSize,NumFiles,i : uint32;
67+
begin
68+
Reset;
69+
if FileExists(_Filename) then
70+
begin
71+
Filename := copy(_Filename,1,Length(_Filename));
72+
MyFile := TFileStream.Create(_Filename, fmOpenRead); // Open file
73+
74+
// Store the whole file in the memory
75+
FileSize := MyFile.Size;
76+
if Filesize > 0 then
77+
begin
78+
Getmem(PData, 4);
79+
MyFile.Read(PData^, 4);
80+
PCurrentData := PData;
81+
// MyFile.Free;
82+
83+
// Let's start reading the file here.
84+
BIGType := uint32(puint32(PCurrentData)^);
85+
inc(PCurrentData,4);
86+
if (BIGType = C_BIG4) or (BIGType = C_BIGF) then
87+
begin
88+
// 0.4 Beta Change. This reduces memory load.
89+
FreeMem(PData);
90+
Getmem(PData, 16);
91+
PCurrentData := PData;
92+
MyFile.Read(PData^, 12);
93+
// Old code resumes...
94+
Size := InvertInteger(uint32(puint32(PCurrentData)^));
95+
inc(PCurrentData,4);
96+
NumFiles := InvertInteger(uint32(puint32(PCurrentData)^));
97+
inc(PCurrentData,4);
98+
// 0.4 code again. Now we get the header size
99+
HeaderSize := InvertInteger(uint32(puint32(PCurrentData)^)) - 16;
100+
inc(PCurrentData,4);
101+
FreeMem(PData);
102+
GetMem(PData,HeaderSize);
103+
PCurrentData := PData;
104+
MyFile.Read(PData^, HeaderSize);
105+
MyFile.Free;
106+
// Here we resume the old code.
107+
SetLength(Files,NumFiles);
108+
// Let's read each file
109+
for i := 0 to High(Files) do
110+
begin
111+
Files[i].Offset := InvertInteger(uint32(puint32(PCurrentData)^));
112+
inc(PCurrentData,4);
113+
Files[i].Size := InvertInteger(uint32(puint32(PCurrentData)^));
114+
inc(PCurrentData,4);
115+
// Now we need to read the filename.
116+
while (PCurrentData^ <> 0) do
117+
begin
118+
Files[i].Filename := Files[i].Filename + char(PCurrentData^);
119+
inc(PCurrentData,1);
120+
end;
121+
inc(PCurrentData,1);
122+
Files[i].FileWritten := true;
123+
end;
124+
ValidFile := true;
125+
end
126+
else
127+
MyFile.Free;
128+
FreeMem(PData);
129+
end;
130+
end;
131+
end;
132+
133+
function TBIGPackage.InvertInteger(_i: uint32): uint32;
134+
begin
135+
Result := (_i and $ff) shl 24;
136+
_i := _i shr 8;
137+
Result := Result + ((_i and $ff) shl 16);
138+
_i := _i shr 8;
139+
Result := Result + ((_i and $ff) shl 8);
140+
_i := _i shr 8;
141+
Result := Result + _i;
142+
end;
143+
144+
function TBIGPackage.InvertInteger16(_i: uint16): uint16;
145+
begin
146+
Result := (_i and $ff) shl 8;
147+
_i := _i shr 8;
148+
Result := Result + _i;
149+
end;
150+
151+
// Gets
152+
function TBIGPackage.GetNumFiles: uint32;
153+
begin
154+
Result := High(Files)+1;
155+
end;
156+
157+
function TBIGPackage.GetFileInfo (_ID : int32): TBIGFileUnit;
158+
begin
159+
if _ID <= High(Files) then
160+
begin
161+
Result := Files[_ID];
162+
end
163+
else
164+
Result := Files[0];
165+
end;
166+
167+
function TBIGPackage.GetFileContents( _ID : int32; var _Data : TStream; var _DataSize : uint32) : Boolean;
168+
var
169+
MyFile : TStream;
170+
FileSize: uint32;
171+
PData,iPData,PCData: puint8;
172+
FileWord : uint16;
173+
CompressedSize : uint32;
174+
begin
175+
Result := false;
176+
if ValidFile and (_ID <= High(Files)) then
177+
begin
178+
MyFile := TFileStream.Create(Filename, fmOpenRead); // Open file
179+
180+
// Store the whole file in the memory
181+
FileSize := MyFile.Size;
182+
if Filesize > 0 then
183+
begin
184+
Getmem(PData, Files[_ID].Size);
185+
MyFile.Seek(Files[_ID].Offset,soFromBeginning);
186+
MyFile.Read(PData^, Files[_ID].Size);
187+
MyFile.Free;
188+
189+
// Now, we create the contents and copy the interesting part.
190+
iPData := PData;
191+
_Data := TMemoryStream.Create;
192+
FileWord := InvertInteger16(uint16(puint16(iPData)^));
193+
if (FileWord and $3EFF) = $10FB then
194+
begin
195+
inc(iPData,2);
196+
if (FileWord and $8000) = 0 then
197+
begin
198+
CompressedSize := iPData^ shl 16;
199+
inc(iPData);
200+
CompressedSize := CompressedSize or (iPData^ shl 8);
201+
inc(iPData);
202+
CompressedSize := CompressedSize or iPData^;
203+
inc(iPData);
204+
if (FileWord and $100) > 0 then
205+
inc(iPData,3);
206+
end
207+
else
208+
begin
209+
CompressedSize := InvertInteger(uint32(puint32(iPData)^));
210+
if (FileWord and $100) > 0 then
211+
inc(iPData,4);
212+
inc(iPData,4);
213+
end;
214+
GetMem(PCData,CompressedSize);
215+
DecompressData(iPData,PCData);
216+
_Data.Write(PCData^,CompressedSize);
217+
FreeMem(PCData);
218+
_DataSize := CompressedSize;
219+
end
220+
else
221+
begin
222+
_Data.Write(iPData^,Files[_ID].Size);
223+
_DataSize := Files[_ID].Size;
224+
end;
225+
FreeMem(PData);
226+
end;
227+
end;
228+
end;
229+
230+
// RefPack decompression function written by jonwil.
231+
// Conversion from C to Delphi by Banshee.
232+
procedure TBIGPackage.DecompressData(var _Input,_Output : puint8);
233+
var
234+
CurrInput,CurrOutput : puint8;
235+
Flags : uint32;
236+
code,code2,code3,code4 : uint8;
237+
count : uint32;
238+
TempBuffer : puint8;
239+
i : uint32;
240+
begin
241+
flags := 0;
242+
code := 0;
243+
code2 := 0;
244+
count := 0;
245+
code3 := 0;
246+
code4 := 0;
247+
CurrInput := _Input;
248+
CurrOutput := _Output;
249+
while (true) do
250+
begin
251+
code := CurrInput^;
252+
inc(CurrInput);
253+
if (code and $80) = 0 then
254+
begin
255+
code2 := CurrInput^;
256+
inc(CurrInput);
257+
count := code and 3;
258+
for i := 1 to count do
259+
begin
260+
CurrOutput^ := CurrInput^;
261+
inc(CurrOutput);
262+
inc(CurrInput);
263+
end;
264+
TempBuffer := Puint8((Cardinal(CurrOutput) - 1) - (code2 + (code and $60) * 8));
265+
count := ((code and $1C) div 4) + 2;
266+
for i := 0 to count do
267+
begin
268+
try
269+
CurrOutput^ := TempBuffer^;
270+
except
271+
ShowMessage(IntToStr(Cardinal(TempBuffer)));
272+
exit;
273+
end;
274+
inc(CurrOutput);
275+
inc(TempBuffer);
276+
end;
277+
end
278+
else if (code and $40) = 0 then
279+
begin
280+
code2 := CurrInput^;
281+
inc(CurrInput);
282+
code3 := CurrInput^;
283+
inc(CurrInput);
284+
count := code2 shr 6;
285+
for i := 1 to count do
286+
begin
287+
CurrOutput^ := CurrInput^;
288+
inc(CurrOutput);
289+
inc(CurrInput);
290+
end;
291+
TempBuffer :=PuInt8((Cardinal(CurrOutput) - 1) - (((code2 and $3F) shl 8) + code3));
292+
count := (code and $3F) + 3;
293+
for i := 0 to count do
294+
begin
295+
CurrOutput^ := TempBuffer^;
296+
inc(CurrOutput);
297+
inc(TempBuffer);
298+
end;
299+
end
300+
else if (code and $20) = 0 then
301+
begin
302+
code2 := CurrInput^;
303+
inc(CurrInput);
304+
code3 := CurrInput^;
305+
inc(CurrInput);
306+
code4 := CurrInput^;
307+
inc(CurrInput);
308+
count := code and 3;
309+
for i := 1 to count do
310+
begin
311+
CurrOutput^ := CurrInput^;
312+
inc(CurrOutput);
313+
inc(CurrInput);
314+
end;
315+
TempBuffer := PuInt8((Cardinal(CurrOutput) - 1) - ((((code and $10) shr 4) shl $10) + (code2 shl 8) + code3));
316+
count := (((code and $0C) shr 2) shl 8) + code4 + 4;
317+
for i := 0 to count do
318+
begin
319+
try
320+
CurrOutput^ := TempBuffer^;
321+
except
322+
ShowMessage(IntToStr(Cardinal(TempBuffer)));
323+
exit;
324+
end;
325+
inc(CurrOutput);
326+
inc(TempBuffer);
327+
end;
328+
end
329+
else
330+
begin
331+
count := ((code and $1F) * 4) + 4;
332+
if (count <= $70) then
333+
begin
334+
for i := 1 to count do
335+
begin
336+
CurrOutput^ := CurrInput^;
337+
inc(CurrOutput);
338+
inc(CurrInput);
339+
end;
340+
end
341+
else
342+
begin
343+
count := code and 3;
344+
for i := 1 to count do
345+
begin
346+
CurrOutput^ := CurrInput^;
347+
inc(CurrOutput);
348+
inc(CurrInput);
349+
end;
350+
exit;
351+
end;
352+
end;
353+
end;
354+
end;
355+
356+
function TBIGPackage.IsValid : boolean;
357+
begin
358+
Result := ValidFile;
359+
end;
360+
361+
end.

0 commit comments

Comments
 (0)