UNIT Unit10_leveldb;
INTERFACE
USES
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, StrUtils;

TYPE
  TForm10 = Class(TForm)
    group_progress: TGroupBox;
    progress: TProgressBar;
    lbl_progress: TLabel;
    btn_abortok: TButton;
    lbl_estimation: TLabel;
    PROCEDURE btn_abortokClick(Sender: TObject);
  PRIVATE
    PROCEDURE HandleFile(ext:String; fileid:LongWord; dir_dat2db:Boolean);
    PROCEDURE stop_convert;
  PUBLIC
    PROCEDURE CreateDatabase(FileName:String);
  END;


VAR
  Form10: TForm10;

IMPLEMENTATION
{$R *.dfm}
USES ABSMain, ABSDecUtil, Unit1_main, Unit2_functions, Unit3_data;
TYPE
  THandler=PROCEDURE(fileid:LongWord; dir_dat2db:Boolean);
  TConvertHandlers=RECORD
    Ext:String[4];
    needed:Boolean;
    Handler:THandler;
  END;
VAR
  ConvertHandlers:Array OF TConvertHandlers;
  loaded_filename:String;
  converting:Boolean=False;
  abort:Boolean=False;
  filestream:TFileStream;
  dat_stream:TMemoryStream;
  mem:TMemoryStream;
  DataBase:TABSDatabase;
  Query:TABSQuery;
  MimeCoder: TStringFormat_MIME64;

PROCEDURE TForm10.HandleFile;
  VAR
    i:Byte;
  BEGIN
    FOR i:=1 TO Length(ConvertHandlers) DO
      IF UpperCase(ConvertHandlers[i].Ext)=UpperCase(ext) THEN
        IF ConvertHandlers[i].needed THEN BEGIN
          ConvertHandlers[i].Handler(fileid, dir_dat2db);
          Break;
        END ELSE
          Break;
  END;

PROCEDURE TForm10.CreateDatabase(FileName:String);
  VAR
    i,j:LongWord;
    temps,temps2:String;
    data:Tdata;
    absolutebegintime,begintime:Double;
    step:Byte;
  CONST
    steps:Byte=4;
  PROCEDURE DoStep(stepname:String);
    BEGIN
      Inc(step);
      IF stepname<>'FIN' THEN
        group_progress.Caption:='Creating DB (Step '+IntToStr(step)+'/'+IntToStr(steps)+': '+stepname+')'
      ELSE
        group_progress.Caption:='Creating DB (FINISHED)';
    END;
  BEGIN
    Form10.Visible:=True;
    Form1.Visible:=False;
    step:=0;
    converting:=True;
    abort:=False;
    loaded_filename:=FileName;
    btn_abortok.Caption:='&Abort...';
    btn_abortok.Default:=False;

    absolutebegintime:=Time;

    DataBase:=TABSDatabase.Create(Self);
    DataBase.DatabaseName:='OLDB';
    DataBase.DatabaseFileName:=FileName;
    DataBase.CreateDatabase;

    DoStep('Creating tables');
    progress.Position:=0;
    lbl_progress.Caption:='';
    lbl_estimation.Caption:='Estimated finishing time: unknown';
    Application.ProcessMessages;

    Query:=TABSQuery.Create(Self);
    Query.DatabaseName:='OLDB';
    Query.SQL.Text:='CREATE TABLE globals  ( id AUTOINC PRIMARY KEY, name STRING(128), value STRING(128) );';
    Query.ExecSQL;
    Query.SQL.Text:='CREATE TABLE linkmap  ( id AUTOINC PRIMARY KEY, src_id INTEGER, src_link_offset INTEGER, target_id INTEGER );';
    Query.ExecSQL;
    Query.SQL.Text:='CREATE TABLE rawmap  ( id AUTOINC PRIMARY KEY, src_id INTEGER, src_link_offset INTEGER, size INTEGER, data BLOB BlobCompressionMode 9 BlobBlockSize 1024 BlobCompressionAlgorithm ZLib );';
//    Query.SQL.Text:='CREATE TABLE rawmap  ( id AUTOINC PRIMARY KEY, src_id INTEGER, src_link_offset INTEGER, size INTEGER, data BLOB BlobCompressionAlgorithm None );';
    Query.ExecSQL;
    Query.SQL.Text:='CREATE TABLE datfiles  ( id INTEGER PRIMARY KEY, extension CHAR(4), name STRING(128), contenttype INTEGER, size INTEGER, data BLOB BlobCompressionMode 9 BlobBlockSize 1024 BlobCompressionAlgorithm ZLib );';
//    Query.SQL.Text:='CREATE TABLE datfiles  ( id INTEGER PRIMARY KEY, extension CHAR(4), name STRING(128), contenttype INTEGER, size INTEGER, data BLOB BlobCompressionAlgorithm None );';
    Query.ExecSQL;
    Query.SQL.Text:='CREATE TABLE extlist  ( id AUTOINC PRIMARY KEY, ext CHAR(4), ident CHAR(16) );';
    Query.ExecSQL;

    Query.SQL.Text:='INSERT INTO globals (name,value) VALUES ("dbversion","'+dbversion+'");';
    Query.ExecSQL;
    SetLength(data,Length(dat_header.Ident));
    FOR i:=0 TO High(dat_header.Ident) DO data[i]:=dat_header.Ident[i];
    temps:=CreateHexString(data,True);
    Query.SQL.Text:='INSERT INTO globals (name,value) VALUES ("ident","'+temps+'");';
    Query.ExecSQL;
    data:=LoadDatFile(0);
    i:=data[7];
    i:=i DIV 2;
    Query.SQL.Text:='INSERT INTO globals (name,value) VALUES ("lvl","'+IntToStr(i)+'");';
    Query.ExecSQL;

    DoStep('Writing extensionslist');
    progress.Max:=dat_header.Extensions;
    Application.ProcessMessages;

    FOR i:=0 TO dat_header.Extensions-1 DO BEGIN
      SetLength(data,Length(dat_extensionsmap[i].Ident));
      FOR j:=0 TO High(dat_extensionsmap[i].Ident) DO data[j]:=dat_extensionsmap[i].Ident[j];
      temps:=CreateHexString(data,True);
      temps2:=dat_extensionsmap[i].Extension[3]+dat_extensionsmap[i].Extension[2]+dat_extensionsmap[i].Extension[1]+dat_extensionsmap[i].Extension[0];
      Query.SQL.Text:='INSERT INTO extlist (ext,ident) VALUES ("'+temps2+'","'+temps+'");';
      Query.ExecSQL;
      progress.Position:=i;
      lbl_progress.Caption:='Extensions done: '+IntToStr(i)+'/'+IntToStr(dat_header.Extensions);
      Application.ProcessMessages;
      IF abort THEN BEGIN
        stop_convert;
        Exit;
      END;
    END;
    lbl_progress.Caption:='';

    DoStep('Loading .dat into memory');
    Application.ProcessMessages;

    progress.Position:=0;
    lbl_progress.Caption:='Files done: '+IntToStr(0)+'/'+IntToStr(dat_header.Files);
    lbl_estimation.Caption:='Estimated finishing time: unknown';

    filestream:=TFileStream.Create(dat_filename, fmOpenRead);
    dat_stream:=TMemoryStream.Create;
    dat_stream.CopyFrom(filestream,0);
    dat_stream.Seek(0,soFromBeginning);
    filestream.Free;

    progress.Max:=dat_header.Files;
    begintime:=Time;
    DoStep('Writing .dat-fileslist');
    Application.ProcessMessages;

    Database.StartTransaction;
    FOR i:=0 TO dat_header.Files-1 DO BEGIN
      IF (dat_files[i].FileType AND $02)=0 THEN BEGIN
        dat_stream.Seek(dat_files[i].DatAddr,soFromBeginning);
        mimecoder:=TStringFormat_MIME64.Create;
        mem:=TMemoryStream.Create;
        mem.CopyFrom(dat_stream,dat_files[i].Size);
        Query.SQL.Text:='INSERT INTO datfiles (id,extension,name,contenttype,size,data) VALUES ('+IntToStr(i)+',"'+dat_files[i].Extension+'","'+dat_files[i].Name+'","'+IntToHex(dat_files[i].FileType,8)+'",'+IntToStr(dat_files[i].size)+',MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") );';
        Query.ExecSQL;
        mem.Free;
        mimecoder.Free;
        HandleFile(dat_files[i].Extension,i,True);
      END ELSE BEGIN
        Query.SQL.Text:='INSERT INTO datfiles (id,extension,name,contenttype,size) VALUES ('+IntToStr(i)+',"'+dat_files[i].Extension+'","'+dat_files[i].Name+'","'+IntToHex(dat_files[i].FileType,8)+'",0);';
        Query.ExecSQL;
      END;
      IF ( (i MOD 100)=0 ) AND (i>0) THEN BEGIN
        Database.Commit(False);
        Database.StartTransaction;
      END;
      IF ( (i MOD 25)=0 ) AND (i>=100) THEN
        lbl_estimation.Caption:='Estimated finishing time: '+TimeToStr((Time-begintime)/i*dat_header.Files+begintime);
      progress.Position:=i;
      lbl_progress.Caption:='Files done: '+IntToStr(i)+'/'+IntToStr(dat_header.Files);
      Application.ProcessMessages;
      IF abort THEN BEGIN
        stop_convert;
        Exit;
      END;
    END;
    Database.Commit(False);
    progress.Position:=dat_header.Files;
    lbl_progress.Caption:='Files done: '+IntToStr(dat_header.Files)+'/'+IntToStr(dat_header.Files);
    lbl_estimation.Caption:='FINISHED (duration: '+TimeToStr(Time-absolutebegintime)+')';

    DoStep('FIN');
    btn_abortok.Caption:='&OK';
    btn_abortok.Default:=True;

    loaded_filename:='';
    converting:=False;
    dat_stream.Free;

    database.Close;
    database.Free;
  END;

PROCEDURE TForm10.stop_convert;
  BEGIN
    btn_abortok.Caption:='&Close';
    btn_abortok.Default:=True;
    converting:=False;
    lbl_estimation.Caption:='ABORTED';
    group_progress.Caption:='Creating DB (ABORTED)';
    DataBase.Close;
    IF MessageBox(Self.Handle, PChar('Delete the unfinished DB-file?'), PChar('Delete file?'), MB_YESNO)=IDYES THEN BEGIN
      DeleteFile(loaded_filename);
    END;
  END;

PROCEDURE TForm10.btn_abortokClick(Sender: TObject);
  BEGIN
    IF converting THEN BEGIN
      IF MessageBox(Self.Handle, PChar('Do you really want to cancel the convert-progress?'), PChar('Warning: Converting'), MB_YESNO)=IDYES THEN
        abort:=True;
    END ELSE BEGIN
      Form10.Visible:=False;
      Form1.Visible:=True;
    END;
  END;


PROCEDURE LoadFilePart(fileid,offset,size:LongWord; target:Pointer);
  BEGIN
    dat_stream.Seek(dat_files[fileid].DatAddr+offset,soFromBeginning);
    dat_stream.Read(target^,size);
  END;

PROCEDURE InsertDatLinkToDB(fileid:LongWord; offset:LongWord);
  VAR
    link:LongWord;
  BEGIN
    LoadFilePart(fileid,offset,4,@link);
    IF link=0 THEN
      link:=$FFFFFFFF
    ELSE
      link:=link DIV 256;
    Query.SQL.Text:='INSERT INTO linkmap (src_id,src_link_offset,target_id) VALUES ('+IntToStr(fileid)+','+IntToStr(offset)+','+IntToStr(link)+');';
    Query.ExecSQL;
  END;

PROCEDURE InsertRawFileToDB(fileid:LongWord; src_offset,raw_addr,size:LongWord);
  VAR
    localmem:TMemoryStream;
//    temps:String;
  BEGIN
    IF size>0 THEN BEGIN
      localmem:=TMemoryStream.Create;
      filestream:=TFileStream.Create(raw_filename,fmOpenRead);
      filestream.Seek(raw_addr,soFromBeginning);
      localmem.CopyFrom(filestream,size);
      filestream.Free;
      mimecoder:=TStringFormat_MIME64.Create;
      Query.SQL.Text:='INSERT INTO rawmap (src_id,src_link_offset,size,data) VALUES ('+IntToStr(fileid)+','+IntToStr(src_offset)+','+IntToStr(size)+',MimeToBin("'+MimeCoder.StrTo(localmem.Memory, localmem.Size)+'") );';
      Query.ExecSQL;
      localmem.Free;
      mimecoder.Free;
    END ELSE BEGIN
      Query.SQL.Text:='INSERT INTO rawmap (src_id,src_link_offset,size) VALUES ('+IntToStr(fileid)+','+IntToStr(src_offset)+',0);';
      Query.ExecSQL;
    END;
{    IF (raw_addr MOD 32)>0 THEN BEGIN
      temps:='FileID='+FormatNumber(fileid,5,'0')+' - dat-Offset=0x'+IntToHex(src_offset,8)+' - raw-address=0x'+IntToHex(raw_addr,8)+#13+#10;
      filestream:=TFileStream.Create('D:\not32.txt',fmOpenReadWrite);
      filestream.Seek(0,soFromEnd);
      filestream.Write(temps[1],Length(temps));
      filestream.Free;
    END; }
  END;



PROCEDURE AGDB(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    link:LongWord;
    links:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@links);
      links:=links*2;
      FOR i:=0 TO links-1 DO BEGIN
        LoadFilePart(fileid,$20+i*4,4,@link);
        InsertRawFileToDB(fileid,$20+i*4,link,1(*????????????????????????????????*));
      END;
    END ELSE BEGIN
    END;
  END;
PROCEDURE AKEV(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 16 DO InsertDatLinkToDB(fileid,$8+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE AKOT(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 4 DO InsertDatLinkToDB(fileid,$8+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE BINA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    link:LongWord;
    datasize:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$0C,4,@link);
      LoadFilePart(fileid,$08,4,@datasize);
      InsertRawFileToDB(fileid,$0C,link,datasize);
    END ELSE BEGIN
    END;
  END;
PROCEDURE CBPI(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 56 DO InsertDatLinkToDB(fileid,$8+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE CBPM(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 18 DO InsertDatLinkToDB(fileid,$8+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE CONS(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 1 DO InsertDatLinkToDB(fileid,$24+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE CRSA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    packages:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$14,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*1100+$A0);
    END ELSE BEGIN
    END;
  END;
PROCEDURE DOOR(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$08);
      InsertDatLinkToDB(fileid,$10);
    END ELSE BEGIN
    END;
  END;
PROCEDURE DPGE(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$40);
    END ELSE BEGIN
    END;
  END;
PROCEDURE HPGE(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$0C);
    END ELSE BEGIN
    END;
  END;
PROCEDURE IGHH(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$24);
      InsertDatLinkToDB(fileid,$28);
    END ELSE BEGIN
    END;
  END;
PROCEDURE IGPA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    links:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@links);
      IF links>0 THEN
        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE IGPG(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 1 DO InsertDatLinkToDB(fileid,$1C+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE IGSA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    links:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@links);
      IF links>0 THEN
        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE IMPT(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$10);
    END ELSE BEGIN
    END;
  END;
PROCEDURE IPGE(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$0C);
    END ELSE BEGIN
    END;
  END;
PROCEDURE KEYI(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 9 DO InsertDatLinkToDB(fileid,$08+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE M3GA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    links:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@links);
      IF links>0 THEN
        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE M3GM(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 6 DO InsertDatLinkToDB(fileid,$0C+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE MTRL(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$10);
    END ELSE BEGIN
    END;
  END;
PROCEDURE OBOA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    packages:Word;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1E,2,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*240);
    END ELSE BEGIN
    END;
  END;
PROCEDURE OFGA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    packages:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*12+$04);
    END ELSE BEGIN
    END;
  END;
PROCEDURE ONCC(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
    END ELSE BEGIN
    END;
  END;
PROCEDURE ONCV(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$08);
    END ELSE BEGIN
    END;
  END;
PROCEDURE ONLV(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 5 DO InsertDatLinkToDB(fileid,$48+i*4);
      FOR i:=0 TO 5 DO InsertDatLinkToDB(fileid,$64+i*4);
      InsertDatLinkToDB(fileid,$300);
    END ELSE BEGIN
    END;
  END;
PROCEDURE ONOA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    packages:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*8+$04);
    END ELSE BEGIN
    END;
  END;
PROCEDURE ONSK(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$08);
      InsertDatLinkToDB(fileid,$0C);
      InsertDatLinkToDB(fileid,$10);
      InsertDatLinkToDB(fileid,$14);
      InsertDatLinkToDB(fileid,$18);
      InsertDatLinkToDB(fileid,$20);
      InsertDatLinkToDB(fileid,$44);
    END ELSE BEGIN
    END;
  END;
PROCEDURE ONVL(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    packages:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE ONWC(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$28);
      InsertDatLinkToDB(fileid,$34);
      InsertDatLinkToDB(fileid,$54);
      InsertDatLinkToDB(fileid,$58);
      InsertDatLinkToDB(fileid,$5C);
      InsertDatLinkToDB(fileid,$60);
      InsertDatLinkToDB(fileid,$6FC);
      InsertDatLinkToDB(fileid,$700);
    END ELSE BEGIN
    END;
  END;
PROCEDURE OPGE(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$1C);
    END ELSE BEGIN
    END;
  END;
PROCEDURE OSBD(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    link:LongWord;
    datasize:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$08,4,@datasize);
      LoadFilePart(fileid,$0C,4,@link);
      InsertRawFileToDB(fileid,$0C,link,datasize);
    END ELSE BEGIN
    END;
  END;
PROCEDURE PSPC(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$50);
    END ELSE BEGIN
    END;
  END;
PROCEDURE PSPL(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    packages:LongWord;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$24+i*8);
    END ELSE BEGIN
    END;
  END;
PROCEDURE PSUI(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 43 DO InsertDatLinkToDB(fileid,$08+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE SNDD(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    link:LongWord;
    datasize:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$40,4,@datasize);
      LoadFilePart(fileid,$44,4,@link);
      InsertRawFileToDB(fileid,$44,link,datasize);
    END ELSE BEGIN
    END;
  END;
PROCEDURE SUBT(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    baselink,link:LongWord;
    links:LongWord;
    i,j,k:LongWord;
    data:Tdata;
    filestream:TFileStream;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$18,4,@baselink);
      LoadFilePart(fileid,$1C,4,@links);
      IF links>0 THEN BEGIN
        LoadFilePart(fileid,$20+(links-1)*4,4,@link);
        SetLength(data,1024);
        filestream:=TFileStream.Create(AnsiReplaceStr(dat_filename,'.dat','.raw'),fmOpenRead);
        filestream.Seek(baselink+link,soFromBeginning);
        filestream.Read(data[0],1024);
        filestream.Free;
        k:=0;
        FOR j:=0 TO 1024 DO BEGIN
          IF (data[j]=$00) OR (j=1024) THEN BEGIN
            IF j<1024 THEN BEGIN
              IF k=0 THEN BEGIN
                k:=1;
              END ELSE BEGIN
                InsertRawFileToDB(fileid,$1C,baselink,link+j);
                Break;
              END;
            END ELSE
              ShowMessage('Error: Didn''t find message-end-marker...');
          END;
        END;
      END;
    END ELSE BEGIN
    END;
  END;
PROCEDURE STNA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    packages:Word;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1E,2,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRAC(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    packages:Word;
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$18);
      LoadFilePart(fileid,$1E,2,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*12+8);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRAM(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:Byte;
    link:LongWord;
    frames:Word;
    tempb:Byte;
    tempw:Word;
    templ:LongWord;
    data:Tdata;
    offset:Word;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$16C,2,@frames);
      {y-pos}
      LoadFilePart(fileid,$0C,4,@link);
      InsertRawFileToDB(fileid,$0C,link,frames*4);
      {x-z-pos}
      LoadFilePart(fileid,$10,4,@link);
      InsertRawFileToDB(fileid,$10,link,frames*8);
      {attacks}
      LoadFilePart(fileid,$182,1,@tempb);
      LoadFilePart(fileid,$14,4,@link);
      InsertRawFileToDB(fileid,$14,link,tempb*32);
      {damage}
      LoadFilePart(fileid,$183,1,@tempb);
      LoadFilePart(fileid,$18,4,@link);
      InsertRawFileToDB(fileid,$18,link,tempb*8);
      {motionblur}
      LoadFilePart(fileid,$184,1,@tempb);
      LoadFilePart(fileid,$1C,4,@link);
      InsertRawFileToDB(fileid,$1C,link,tempb*8);
      {shortcut}
      LoadFilePart(fileid,$185,1,@tempb);
      LoadFilePart(fileid,$20,4,@link);
      InsertRawFileToDB(fileid,$20,link,tempb*8);
      {throw}
      LoadFilePart(fileid,$24,4,@link);
      InsertRawFileToDB(fileid,$24,link,24);
      {footstep}
      LoadFilePart(fileid,$186,1,@tempb);
      LoadFilePart(fileid,$28,4,@link);
      InsertRawFileToDB(fileid,$28,link,tempb*4);
      {particle}
      LoadFilePart(fileid,$187,1,@tempb);
      LoadFilePart(fileid,$2C,4,@link);
      InsertRawFileToDB(fileid,$2C,link,tempb*24);
      {position}
      LoadFilePart(fileid,$30,4,@link);
      InsertRawFileToDB(fileid,$30,link,frames*8);
      {particle}
      LoadFilePart(fileid,$154,2,@tempw);
      LoadFilePart(fileid,$38,4,@link);
      InsertRawFileToDB(fileid,$38,link,tempw*34);
      {extent}
      LoadFilePart(fileid,$138,1,@templ);
      LoadFilePart(fileid,$13C,4,@link);
      InsertRawFileToDB(fileid,$13C,link,templ*12);

      LoadFilePart(fileid,$34,4,@link);
      tempw:=0;
      IF link>0 THEN BEGIN
        {BODY ANIMATIONS PART DECODE!!!}
        SetLength(data,$FFFF);
        filestream:=TFileStream.Create(AnsiReplaceStr(dat_filename,'.dat','.raw'),fmOpenRead);
        filestream.Seek(link,soFromBeginning);
        filestream.Read(data[0],$FFFF);
        filestream.Free;
        offset:=data[24]+data[25]*255;
        {}
      END;
      InsertRawFileToDB(fileid,$34,link,tempw);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRAS(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$08);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRBS(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 4 DO InsertDatLinkToDB(fileid,$08+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRCM(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      FOR i:=0 TO 2 DO InsertDatLinkToDB(fileid,$5C+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRGA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
    packages:Word;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1E,2,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRGE(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$20);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRIG(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$18);
      InsertDatLinkToDB(fileid,$24);
      InsertDatLinkToDB(fileid,$28);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRMA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
    packages:Word;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1E,2,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TRSC(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
    packages:Word;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1E,2,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TSFF(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
    packages:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TSFT(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$1C);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TURR(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$60);
      InsertDatLinkToDB(fileid,$6C);
      InsertDatLinkToDB(fileid,$74);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TXAN(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
    packages:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TXMA(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
    packages:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TXMB(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
    packages:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TXMP(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    link:LongWord;
    x,y:Word;
    storetype:Byte;
    datasize:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$8C,SizeOf(x),@x);
      LoadFilePart(fileid,$8E,SizeOf(y),@y);
      LoadFilePart(fileid,$90,SizeOf(storetype),@storetype);
      LoadFilePart(fileid,$9C,4,@link);
      CASE storetype OF
        0,1,2: datasize:=x*y*2;
        8: datasize:=x*y*4;
        9: datasize:=x*y DIV 2;
      END;
      InsertRawFileToDB(fileid,$9C,link,datasize);
      InsertDatLinkToDB(fileid,$94);
      InsertDatLinkToDB(fileid,$98);
    END ELSE BEGIN
    END;
  END;
PROCEDURE TXTC(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$08);
    END ELSE BEGIN
    END;
  END;
PROCEDURE WMCL(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$24);
    END ELSE BEGIN
    END;
  END;
PROCEDURE WMMB(fileid:LongWord; dir_dat2db:Boolean);
  VAR
    i:LongWord;
    packages:LongWord;
  BEGIN
    IF dir_dat2db THEN BEGIN
      LoadFilePart(fileid,$1C,4,@packages);
      IF packages>0 THEN
        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
    END ELSE BEGIN
    END;
  END;
PROCEDURE WPGE(fileid:LongWord; dir_dat2db:Boolean);
  BEGIN
    IF dir_dat2db THEN BEGIN
      InsertDatLinkToDB(fileid,$08);
      InsertDatLinkToDB(fileid,$0C);
    END ELSE BEGIN
    END;
  END;

PROCEDURE InsertHandler(ext:String; needed:Boolean; handler:THandler);
  BEGIN
    SetLength(ConvertHandlers,Length(ConvertHandlers)+1);
    ConvertHandlers[High(ConvertHandlers)].Ext:=ext;
    ConvertHandlers[High(ConvertHandlers)].needed:=needed;
    ConvertHandlers[High(ConvertHandlers)].handler:=handler;
  END;

BEGIN
  InsertHandler('ABNA',False,NIL);
//  InsertHandler('AGDB',True,AGDB);
  InsertHandler('AGDB',False,NIL);
  InsertHandler('AGQC',False,NIL);
  InsertHandler('AGQG',False,NIL);
  InsertHandler('AGQR',False,NIL);
  InsertHandler('AISA',False,NIL);
  InsertHandler('AITR',False,NIL);
  InsertHandler('AKAA',False,NIL);
  InsertHandler('AKBA',False,NIL);
  InsertHandler('AKBP',False,NIL);
  InsertHandler('AKDA',False,NIL);
  InsertHandler('AKEV',True,AKEV);
  InsertHandler('AKOT',True,AKOT);
  InsertHandler('AKVA',False,NIL);
  InsertHandler('BINA',True,BINA);
  InsertHandler('CBPI',True,CBPI);
  InsertHandler('CBPM',True,CBPM);
  InsertHandler('CONS',True,CONS);
  InsertHandler('CRSA',True,CRSA);
  InsertHandler('DOOR',True,DOOR);
  InsertHandler('DPGE',True,DPGE);
  InsertHandler('ENVP',False,NIL);
  InsertHandler('FILM',False,NIL);
  InsertHandler('HPGE',True,HPGE);
  InsertHandler('IDXA',False,NIL);
  InsertHandler('IGHH',True,IGHH);
  InsertHandler('IGPA',True,IGPA);
  InsertHandler('IGPG',True,IGPG);
  InsertHandler('IGSA',True,IGSA);
  InsertHandler('IMPT',True,IMPT);
  InsertHandler('IPGE',True,IPGE);
  InsertHandler('KEYI',True,KEYI);
  InsertHandler('M3GA',True,M3GA);
  InsertHandler('M3GM',True,M3GM);
  InsertHandler('MTRL',True,MTRL);
  InsertHandler('OBAN',False,NIL);
  InsertHandler('OBDC',False,NIL);
  InsertHandler('OBOA',True,OBOA);
  InsertHandler('OFGA',True,OFGA);
  InsertHandler('ONCC',True,ONCC);
  InsertHandler('ONCP',False,NIL);
  InsertHandler('ONCV',True,ONCV);
  InsertHandler('ONFA',False,NIL);
  InsertHandler('ONGS',False,NIL);
  InsertHandler('ONIA',False,NIL);
  InsertHandler('ONLD',False,NIL);
  InsertHandler('ONLV',True,ONLV);
  InsertHandler('ONMA',False,NIL);
  InsertHandler('ONOA',True,ONOA);
  InsertHandler('ONSA',False,NIL);
  InsertHandler('ONSK',True,ONSK);
  InsertHandler('ONTA',False,NIL);
  InsertHandler('ONVL',True,ONVL);
  InsertHandler('ONWC',True,ONWC);
  InsertHandler('OPGE',True,OPGE);
  InsertHandler('OSBD',True,OSBD);
  InsertHandler('OTIT',False,NIL);
  InsertHandler('OTLF',False,NIL);
  InsertHandler('PLEA',False,NIL);
  InsertHandler('PNTA',False,NIL);
  InsertHandler('PSPC',True,PSPC);
  InsertHandler('PSPL',True,PSPL);
  InsertHandler('PSUI',True,PSUI);
  InsertHandler('QTNA',False,NIL);
  InsertHandler('SNDD',True,SNDD);
  InsertHandler('STNA',True,STNA);
  InsertHandler('SUBT',True,SUBT);
  InsertHandler('TRAC',True,TRAC);
  InsertHandler('TRAM',True,TRAM);
  InsertHandler('TRAS',True,TRAS);
  InsertHandler('TRBS',True,TRBS);
  InsertHandler('TRCM',True,TRCM);
  InsertHandler('TRGA',True,TRGA);
  InsertHandler('TRGE',True,TRGE);
  InsertHandler('TRIA',False,NIL);
  InsertHandler('TRIG',True,TRIG);
  InsertHandler('TRMA',True,TRMA);
  InsertHandler('TRSC',True,TRSC);
  InsertHandler('TRTA',False,NIL);
  InsertHandler('TSFF',True,TSFF);
  InsertHandler('TSFL',False,NIL);
  InsertHandler('TSFT',True,TSFT);
  InsertHandler('TSGA',False,NIL);
  InsertHandler('TSTR',False,NIL);
  InsertHandler('TURR',True,TURR);
  InsertHandler('TXAN',True,TXAN);
  InsertHandler('TXCA',False,NIL);
  InsertHandler('TXMA',True,TXMA);
  InsertHandler('TXMB',True,TXMB);
  InsertHandler('TXMP',True,TXMP);
  InsertHandler('TXTC',True,TXTC);
  InsertHandler('VCRA',False,NIL);
  InsertHandler('WMCL',True,WMCL);
  InsertHandler('WMDD',False,NIL);
  InsertHandler('WMM_',False,NIL);
  InsertHandler('WMMB',True,WMMB);
  InsertHandler('WPGE',True,WPGE);   
END.
