/////////////////////////////////////
//                                 //
// (c) Alex 'Shirson' Nevskiy 2006 //
//                                 //
//  Shirson's Compressed Data unit //
//                                 //
/////////////////////////////////////

unit _scd;
interface
uses Classes,zlib,Windows,SysUtils,graphics;

type
  TFiledata=record
    Name:string[40];
    FullName:string;
    Pos:int64;
    Size:int64;
  end;

  TAFiledata=array of TFiledata;

  var
    DataStream:TMemoryStream;
    Datalist:TAFileData;
    TempDir:string;

procedure GetSCD(Name:String);
procedure GetData(Name:String; var ms:TMemoryStream); overload;
procedure GetData(Name:String; var tb:TBitMap); overload;
function  GetData(Name:String; var Pnt:Pointer):integer; overload;

function GetFile(Name:String):string;
procedure clearfile(Name:String);

implementation

//------------------------------------------------------------------------------
procedure GetSCD(Name:String);
var a:integer;
    l:word;
    inbuff, outbuff:pointer;
//    tsl:tstringlist;
begin
//tsl:=tstringlist.Create;
SetLength(TempDir, MAX_PATH);
GetTempPath(MAX_PATH, PChar(TempDir));
SetLength(TempDir, StrLen(PChar(TempDir)));
DataStream:=TMemoryStream.Create;
setlength(Datalist,0);
DataStream.LoadFromFile(name);
DataStream.Seek(-2,soFromEnd);
DataStream.Read(l,2);
DataStream.Position:=0;
DataStream.Size:=DataStream.Size-2;
getmem(inbuff,DataStream.Size);
DataStream.Read(inbuff^,DataStream.Size);
DecompressBuf(inbuff,DataStream.Size,0,outbuff,a);
DataStream.Clear;
DataStream.Write(outbuff^,a);
DataStream.Seek(-56*l,soFromEnd);
Setlength(Datalist,l);
for a:=0 to l-1 do
  begin
    DataStream.Read(Datalist[a].Name,40);
    DataStream.Read(Datalist[a].Pos,8);
    DataStream.Read(Datalist[a].Size,8);
//    tsl.Add(inttostr(a)+': '+Datalist[a].FullName+' '+Datalist[a].Name+' '+inttostr(Datalist[a].Size)+' '+inttostr(Datalist[a].pos));
  end;
//tsl.SaveToFile('test');
end;

//------------------------------------------------------------------------------
procedure GetData(Name:String; var ms:TMemoryStream); overload;
var a:integer;
    f:boolean;
    s:string;
begin
s:=lowercase(Name);
f:=false;
a:=0;
while (a<=high(DataList)) and (not f) do
  if Datalist[a].Name=s then f:=true else inc(a);
if not f then
  begin
    messagebox(0,pchar('No '+Name+' resource!'),pchar('!!!'),MB_OK+MB_ICONWARNING);
    halt(0);
  end;
DataStream.Position:=DataList[a].Pos;
ms.Clear;
ms.CopyFrom(DataStream,Datalist[a].Size);
ms.Position:=0;
end;

//------------------------------------------------------------------------------
procedure GetData(Name:String; var tb:TBitMap); overload;
var a:integer;
    f:boolean;
    ms:Tmemorystream;
    s:string;
begin
s:=lowercase(Name);
f:=false;
a:=0;
ms:=Tmemorystream.Create;
while (a<=high(DataList)) and (not f) do
  if Datalist[a].Name=s then f:=true else inc(a);
if not f then
  begin
    messagebox(0,pchar('No '+s+' resource!'),pchar('!!!'),MB_OK+MB_ICONWARNING);
    halt(0);
  end;
DataStream.Position:=DataList[a].Pos;
ms.Clear;
ms.CopyFrom(DataStream,Datalist[a].Size);
ms.Position:=0;
tb.loadfromstream(ms);
end;

//------------------------------------------------------------------------------
function GetFile(Name:String):string;
var a:integer;
    f:boolean;
    ms:TMemoryStream;
begin
ms:=TMemoryStream.Create;
f:=false;
a:=0;
while (a<high(DataList)) and (not f) do
  if Datalist[a].Name=Name then f:=true else inc(a);
DataStream.Position:=DataList[a].Pos;
ms.Clear;
ms.CopyFrom(DataStream,Datalist[a].Size);
ms.Position:=0;
result:=tempdir+name;
ms.SaveToFile(result);
ms.Free;
end;

//------------------------------------------------------------------------------

function GetData(Name:String; var Pnt:Pointer):integer; overload;
var a:integer;
    f:boolean;
    s:string;
begin
s:=lowercase(Name);
f:=false;
a:=0;
while (a<=high(DataList)) and (not f) do
  if Datalist[a].Name=s then f:=true else inc(a);
if not f then
  begin
    messagebox(0,pchar('No '+s+' resource!'),pchar('!!!'),MB_OK+MB_ICONWARNING);
    halt(0);
  end;
result:=Datalist[a].Size;
DataStream.Position:=DataList[a].Pos;
getmem(pnt,result);
DataStream.Read(Pnt^,result);

end;

//------------------------------------------------------------------------------
procedure clearfile(Name:String);
begin
deletefile(pchar(tempdir+name));
end;

//------------------------------------------------------------------------------
end.
