Index: /oup/releases/0.33a/Code/DataStructures.pas
===================================================================
--- /oup/releases/0.33a/Code/DataStructures.pas	(revision 76)
+++ /oup/releases/0.33a/Code/DataStructures.pas	(revision 76)
@@ -0,0 +1,605 @@
+unit DataStructures;
+
+interface
+
+uses SysUtils, Classes, Data, Dialogs, StrUtils;
+
+type
+  Tstructure_entry = record
+    Name:     String;
+    offset:   LongWord;
+    datatype: Word;  // 1..4  : Integer[1..4] dec
+    // 5..8  : Integer[1..4] hex
+    // 9     : float
+    // 10    : bitset
+    // 11    : raw-addr
+    // 12    : dat-file-ID
+    // 13..16: Signed Integer[1..4]
+    // 17    : level-ID
+    // 100..300: dat-file-name[0..200]
+    // 1000..9999: Unused data[0-8999]
+    // 10000+: string[0+]
+    description: String;
+  end;
+
+  TStructDefSub = record
+    SubName: String;
+    SubDesc: String;
+    Entries: array of TStructure_entry;
+  end;
+
+  TStructDef = record
+    Data:   Boolean;
+    Global: array of TStructure_entry;
+    Subs:   array of TStructDefSub;
+  end;
+  THandler = function(fileid: LongWord): TRawList;
+
+  TRawListHandlers = record
+    Ext:     String[4];
+    needed:  Boolean;
+    Handler: THandler;
+  end;
+
+var
+  RawListHandlers: array of TRawListHandlers;
+  Raws: String;
+
+
+function LoadStructureDefinition(fileid: LongWord): TStructDef;
+function GetDataType(typeid: Word): String;
+function GetTypeDataLength(datatype: Word): Word;
+
+implementation
+
+uses Functions, OniDataClass, Forms, Template;
+
+
+
+
+function GetTypeDataLength(datatype: Word): Word;
+begin
+  case datatype of
+    1..4:
+      Result := datatype;
+    5..8:
+      Result := datatype - 4;
+    9:
+      Result := 4;
+    10:
+      Result := 1;
+    11:
+      Result := 4;
+    12:
+      Result := 4;
+    13..16:
+      Result := datatype - 12;
+    17:
+      Result := 4;
+    100..300:
+      Result := datatype - 100;
+    1000..9999:
+      Result := datatype - 1000;
+    10000..65535:
+      Result := datatype - 10000;
+  end;
+end;
+
+
+
+
+function GetDataType(typeid: Word): String;
+begin
+  case typeid of
+    1..4:
+      Result := 'Int' + IntToStr(typeid * 8);
+    5..8:
+      Result := 'Int' + IntToStr((typeid - 4) * 8);
+    9:
+      Result := 'Float';
+    10:
+      Result := 'BitSet';
+    11:
+      Result := 'Raw-Address';
+    12:
+      Result := '.dat-file-ID';
+    13..16:
+      Result := 'SignedInt' + IntToStr((typeid - 12) * 8);
+    17:
+      Result := 'LevelID';
+    100..300:
+      Result := '.dat-file-name(' + IntToStr(typeid - 100) + ')';
+    1000..9999:
+      Result := 'Unused(' + IntToStr(typeid - 1000) + ')';
+    10000..65535:
+      Result := 'String(' + IntToStr(typeid - 10000) + ')';
+  end;
+end;
+
+
+
+
+function AGDB(fileid: LongWord): TRawList;
+var
+  link:  LongWord;
+  links: LongWord;
+  i:     LongWord;
+begin
+  if not OniDataConnection.OSisMac then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $1C, 4, @links);
+    links := links * 2;
+    SetLength(Result, links);
+    for i := 0 to links - 1 do
+    begin
+      Result[i].src_offset := $20 + i * 4;
+      OniDataConnection.LoadDatFilePart(fileid, $20 + i * 4, 4, @link);
+      Result[i].raw_addr := link;
+      Result[i].raw_size := 0{????????????????????????????????};
+      Result[i].loc_sep  := False;
+    end;
+  end;
+end;
+
+
+
+
+function AKVA(fileid: LongWord): TRawList;
+var
+  link:  LongWord;
+  links: LongWord;
+  i:     LongWord;
+begin
+  if not OniDataConnection.OSisMac then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $1C, 4, @links);
+    SetLength(Result, links);
+    for i := 0 to links - 1 do
+    begin
+      Result[i].src_offset := $20 + i * $74 + $24;
+      OniDataConnection.LoadDatFilePart(fileid, $20 + i * $74 + $24, 4, @link);
+      Result[i].raw_addr := link;
+      OniDataConnection.LoadDatFilePart(fileid, $20 + i * $74 + $28, 4, @link);
+      Result[i].raw_size := link;
+      Result[i].loc_sep  := False;
+    end;
+  end;
+end;
+
+
+
+
+function BINA(fileid: LongWord): TRawList;
+var
+  link:     LongWord;
+  datasize: LongWord;
+begin
+  OniDataConnection.LoadDatFilePart(fileid, $0C, 4, @link);
+  OniDataConnection.LoadDatFilePart(fileid, $08, 4, @datasize);
+  SetLength(Result, 1);
+  Result[0].src_offset := $0C;
+  Result[0].raw_addr   := link;
+  Result[0].raw_size   := datasize;
+  Result[0].loc_sep    := OniDataConnection.OSisMac;
+end;
+
+
+
+
+function OSBD(fileid: LongWord): TRawList;
+var
+  link:     LongWord;
+  datasize: LongWord;
+begin
+  OniDataConnection.LoadDatFilePart(fileid, $08, 4, @datasize);
+  OniDataConnection.LoadDatFilePart(fileid, $0C, 4, @link);
+  SetLength(Result, 1);
+  Result[0].src_offset := $0C;
+  Result[0].raw_addr   := link;
+  Result[0].raw_size   := datasize;
+  Result[0].loc_sep    := OniDataConnection.OSisMac;
+end;
+
+
+
+
+function SNDD(fileid: LongWord): TRawList;
+var
+  link:     LongWord;
+  datasize: LongWord;
+begin
+  SetLength(Result, 1);
+  if not OniDataConnection.OSisMac then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $40, 4, @datasize);
+    OniDataConnection.LoadDatFilePart(fileid, $44, 4, @link);
+    Result[0].src_offset := $44;
+  end
+  else
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $10, 4, @datasize);
+    OniDataConnection.LoadDatFilePart(fileid, $14, 4, @link);
+    Result[0].src_offset := $14;
+  end;
+  Result[0].raw_addr := link;
+  Result[0].raw_size := datasize;
+  Result[0].loc_sep  := False;
+end;
+
+
+
+
+function SUBT(fileid: LongWord): TRawList;
+var
+  baselink, lastlink: LongWord;
+  links: LongWord;
+  j, k:  LongWord;
+  Data:  Tdata;
+begin
+  OniDataConnection.LoadDatFilePart(fileid, $18, 4, @baselink);
+  OniDataConnection.LoadDatFilePart(fileid, $1C, 4, @links);
+  if links > 0 then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $20 + (links - 1) * 4, 4, @lastlink);
+    SetLength(Data, lastlink + 1024);
+    TOniDataDat(OniDataConnection).LoadRawOffset(False,
+      baselink, lastlink + 1024, Data);
+    //      OniDataConnection.LoadRawFile(fileid,$1C,baselink,lastlink+1024,False,@data[0]);
+    k := 0;
+    for j := 0 to 1024 do
+    begin
+      if (Data[lastlink + j] = $00) or (j = 1024) then
+      begin
+        if j < 1024 then
+        begin
+          if k = 0 then
+          begin
+            k := 1;
+          end
+          else
+          begin
+            SetLength(Result, 1);
+            Result[0].src_offset := $18;
+            Result[0].raw_addr   := baselink;
+            Result[0].raw_size   := lastlink + j;
+            Break;
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+
+
+
+function TRAM(fileid: LongWord): TRawList;
+var
+  i:      Integer;
+  link:   LongWord;
+  frames: Word;
+  tempb:  Byte;
+  tempw:  Word;
+  templ:  LongWord;
+  Data:   Tdata;
+  offset: Word;
+  frame_count: Byte;
+begin
+  SetLength(Result, 13);
+  OniDataConnection.LoadDatFilePart(fileid, $16C, 2, @frames);
+  {y-pos}
+  OniDataConnection.LoadDatFilePart(fileid, $0C, 4, @link);
+  Result[0].src_offset := $0C;
+  Result[0].raw_addr   := link;
+  Result[0].raw_size   := frames * 4;
+  {x-z-pos}
+  OniDataConnection.LoadDatFilePart(fileid, $10, 4, @link);
+  Result[1].src_offset := $10;
+  Result[1].raw_addr   := link;
+  Result[1].raw_size   := frames * 8;
+  {attacks}
+  OniDataConnection.LoadDatFilePart(fileid, $182, 1, @tempb);
+  OniDataConnection.LoadDatFilePart(fileid, $14, 4, @link);
+  Result[2].src_offset := $14;
+  Result[2].raw_addr   := link;
+  Result[2].raw_size   := tempb * 32;
+  {damage}
+  OniDataConnection.LoadDatFilePart(fileid, $183, 1, @tempb);
+  OniDataConnection.LoadDatFilePart(fileid, $18, 4, @link);
+  Result[3].src_offset := $18;
+  Result[3].raw_addr   := link;
+  Result[3].raw_size   := tempb * 8;
+  {motionblur}
+  OniDataConnection.LoadDatFilePart(fileid, $184, 1, @tempb);
+  OniDataConnection.LoadDatFilePart(fileid, $1C, 4, @link);
+  Result[4].src_offset := $1C;
+  Result[4].raw_addr   := link;
+  Result[4].raw_size   := tempb * 8;
+  {shortcut}
+  OniDataConnection.LoadDatFilePart(fileid, $185, 1, @tempb);
+  OniDataConnection.LoadDatFilePart(fileid, $20, 4, @link);
+  Result[5].src_offset := $20;
+  Result[5].raw_addr   := link;
+  Result[5].raw_size   := tempb * 8;
+  {throw}
+  OniDataConnection.LoadDatFilePart(fileid, $24, 4, @link);
+  Result[6].src_offset := $24;
+  Result[6].raw_addr   := link;
+  if link > 0 then
+    Result[6].raw_size := 24
+  else
+    Result[6].raw_size := 0;
+  {footstep}
+  OniDataConnection.LoadDatFilePart(fileid, $186, 1, @tempb);
+  OniDataConnection.LoadDatFilePart(fileid, $28, 4, @link);
+  Result[7].src_offset := $28;
+  Result[7].raw_addr   := link;
+  Result[7].raw_size   := tempb * 4;
+  {particle}
+  OniDataConnection.LoadDatFilePart(fileid, $187, 1, @tempb);
+  OniDataConnection.LoadDatFilePart(fileid, $2C, 4, @link);
+  Result[8].src_offset := $2C;
+  Result[8].raw_addr   := link;
+  Result[8].raw_size   := tempb * 24;
+  {position}
+  OniDataConnection.LoadDatFilePart(fileid, $30, 4, @link);
+  Result[9].src_offset := $30;
+  Result[9].raw_addr   := link;
+  Result[9].raw_size   := frames * 8;
+  {particle}
+  OniDataConnection.LoadDatFilePart(fileid, $154, 2, @tempw);
+  OniDataConnection.LoadDatFilePart(fileid, $38, 4, @link);
+  Result[11].src_offset := $38;
+  Result[11].raw_addr   := link;
+  Result[11].raw_size   := tempw * 34;
+  {extent}
+  OniDataConnection.LoadDatFilePart(fileid, $138, 4, @templ);
+  OniDataConnection.LoadDatFilePart(fileid, $13C, 4, @link);
+  Result[12].src_offset := $13C;
+  Result[12].raw_addr   := link;
+  Result[12].raw_size   := templ * 12;
+
+  OniDataConnection.LoadDatFilePart(fileid, $34, 4, @link);
+  if link > 0 then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $160, 2, @tempw);
+    frame_count := 0;
+    i := 0;
+    SetLength(Data, $FFFF);
+    TOniDataDat(OniDataConnection).LoadRawOffset(False, link, $FFFF, Data);
+    offset := Data[$24] + Data[$25] * 256;
+    while (offset + i < Length(Data)) and (frame_count < frames - 1) do
+    begin
+      Inc(i, tempw);
+      frame_count := frame_count + Data[offset + i];
+      Inc(i);
+    end;
+    if offset + i < Length(Data) then
+    begin
+      Inc(i, tempw);
+      Result[10].raw_size := offset + i;
+    end
+    else
+    begin
+      Result[10].raw_size := 0;
+    end;
+  end;
+  Result[10].src_offset := $34;
+  Result[10].raw_addr   := link;
+end;
+
+
+
+
+function TXMP(fileid: LongWord): TRawList;
+var
+  link_pc:   LongWord;
+  link_mac:  LongWord;
+  x, y:      Word;
+  storetype: Byte;
+  datasize:  LongWord;
+begin
+  OniDataConnection.LoadDatFilePart(fileid, $8C, SizeOf(x), @x);
+  OniDataConnection.LoadDatFilePart(fileid, $8E, SizeOf(y), @y);
+  OniDataConnection.LoadDatFilePart(fileid, $90, SizeOf(storetype), @storetype);
+  OniDataConnection.LoadDatFilePart(fileid, $9C, 4, @link_pc);
+  OniDataConnection.LoadDatFilePart(fileid, $A0, 4, @link_mac);
+  case storetype of
+    0, 1, 2:
+      datasize := x * y * 2;
+    8:
+      datasize := x * y * 4;
+    9:
+      datasize := x * y div 2;
+  end;
+  SetLength(Result, 1);
+  if not OniDataConnection.OSisMac then
+  begin
+    Result[0].src_offset := $9C;
+    Result[0].raw_addr   := link_pc;
+  end
+  else
+  begin
+    Result[0].src_offset := $A0;
+    Result[0].raw_addr   := link_mac;
+  end;
+  Result[0].raw_size := datasize;
+  Result[0].loc_sep  := OniDataConnection.OSisMac;
+end;
+
+
+
+
+procedure InsertRawListHandler(ext: String; needed: Boolean; handler: THandler);
+begin
+  SetLength(RawListHandlers, Length(RawListHandlers) + 1);
+  RawListHandlers[High(RawListHandlers)].Ext := ext;
+  RawListHandlers[High(RawListHandlers)].needed := needed;
+  RawListHandlers[High(RawListHandlers)].handler := handler;
+  Raws := Raws + ext;
+  AddToolListEntry('rawedit', '', ext);
+end;
+
+
+
+
+function LoadStructureDefinition(fileid: LongWord): TStructDef;
+var
+  i:      LongWord;
+  current_type: Byte; //0: Global, 1: Undynamic, 2: Dynamic
+  current_base, current_package, current_package_size: LongWord;
+  packages: LongWord;
+  deffile: Text;
+  structentry: TStructure_Entry;
+  fields: TStringArray;
+  filename: String;
+  ext:    String[4];
+  temps:  String;
+  Data:   TData;
+begin
+  SetLength(Result.Global, 0);
+  SetLength(Result.Subs, 0);
+  Result.Data := False;
+  ext      := OniDataConnection.GetFileInfo(fileid).Extension;
+  filename := ExtractFilePath(Application.ExeName) + '\StructDefs\' + ext + '.txt';
+  if FileExists(filename) then
+  begin
+    Data := OniDataConnection.LoadDatFile(fileid);
+    AssignFile(deffile, filename);
+    Reset(deffile);
+    current_type := 0;
+    Result.Data  := True;
+    if not EOF(deffile) then
+    begin
+      ReadLn(deffile, temps);
+      while not EOF(deffile) do
+      begin
+        ReadLn(deffile, temps);
+        if (Length(temps) > 0) and (temps[1] <> '#') then
+        begin
+          if temps[1] = '*' then
+          begin
+            fields := Explode(temps, #9);
+            case Length(fields) of
+              1..2:
+              begin
+                current_type := 1;
+                current_base := 0;
+                SetLength(Result.Subs, Length(Result.Subs) + 1);
+                Result.Subs[High(Result.Subs)].SubName :=
+                  MidStr(fields[0], 2, Length(fields[0]) - 1);
+                if Length(fields) = 2 then
+                  Result.Subs[High(Result.Subs)].SubDesc := fields[1];
+              end;
+              3:
+              begin
+                current_type := 1;
+                current_base := HexToLong(fields[2]);
+                SetLength(Result.Subs, Length(Result.Subs) + 1);
+                Result.Subs[High(Result.Subs)].SubName :=
+                  MidStr(fields[0], 2, Length(fields[0]) - 1);
+                Result.Subs[High(Result.Subs)].SubDesc := fields[1];
+              end;
+              6:
+              begin
+                current_type    := 2;
+                current_base    := HexToLong(fields[2]);
+                current_package := 0;
+                current_package_size := StrToInt(fields[5]);
+                if fields[4][1] <> '$' then
+                begin
+                  case StrToInt(fields[4]) of
+                    1:
+                      packages := Data[HexToLong(fields[3])];
+                    2:
+                      packages := Data[HexToLong(fields[3])] + Data[HexToLong(fields[3]) + 1] * 256;
+                    4:
+                      packages := Data[HexToLong(fields[3])] + Data[HexToLong(fields[3]) + 1] *
+                        256 + Data[HexToLong(fields[3]) + 2] * 256 * 256 + Data[HexToLong(fields[3]) + 3] * 256 * 256 * 256;
+                  end;
+                end
+                else
+                begin
+                  packages := HexToLong(fields[4]);
+                end;
+                SetLength(Result.Subs, Length(Result.Subs) + packages);
+                for current_package := 0 to packages - 1 do
+                begin
+                  Result.Subs[High(Result.Subs) - packages +
+                    current_package + 1].SubName :=
+                    MidStr(fields[0], 2, Length(fields[0]) - 1) +
+                    '[' + IntToStr(current_package) + ']' + '#' +
+                    IntToHex(current_base + current_package * current_package_size, 8) +
+                    '#' + IntToHex(current_package_size, 8);
+                  Result.Subs[High(Result.Subs) - packages +
+                    current_package + 1].SubDesc :=
+                    fields[1];
+                end;
+              end;
+            end;
+          end
+          else
+          begin
+            fields := Explode(temps, #9);
+            if (Length(fields) = 3) or (Length(fields) = 4) then
+            begin
+              if not AppSettings.HideUnusedData or
+                ((StrToInt(fields[2]) < 1000) or (StrToInt(fields[2]) > 9999)) then
+              begin
+                structentry.Name     := fields[0];
+                structentry.datatype := StrToInt(fields[2]);
+                if Length(fields) = 4 then
+                  structentry.description := fields[3]
+                else
+                  structentry.description := '';
+                if current_type in [0, 1] then
+                begin
+                  structentry.offset := HexToLong(fields[1]) + current_base;
+                  if Length(Result.Subs) = 0 then
+                  begin
+                    SetLength(Result.Global, Length(Result.Global) + 1);
+                    Result.Global[High(Result.Global)] := structentry;
+                  end
+                  else
+                  begin
+                    SetLength(Result.Subs[High(Result.Subs)].Entries,
+                      Length(Result.Subs[High(Result.Subs)].Entries) + 1);
+                    Result.Subs[High(Result.Subs)].Entries[High(
+                      Result.Subs[High(Result.Subs)].Entries)] := structentry;
+                  end;
+                end
+                else
+                begin
+                  for current_package := 0 to packages - 1 do
+                  begin
+                    structentry.offset :=
+                      current_base + current_package * current_package_size + HexToLong(fields[1]);
+                    with Result.Subs[High(Result.Subs) - packages + current_package + 1] do
+                    begin
+                      SetLength(Entries, Length(Entries) + 1);
+                      Entries[High(Entries)] := structentry;
+                    end;
+                  end;
+                end;
+              end;
+            end;
+          end;
+        end;
+      end;
+    end;
+    CloseFile(deffile);
+  end;
+end;
+
+
+begin
+  Raws := '';
+  //  InsertRawListHandler('AGDB',True,AGDB);
+  InsertRawListHandler('AKVA', True, AKVA);
+  InsertRawListHandler('BINA', True, BINA);
+  InsertRawListHandler('OSBD', True, OSBD);
+  InsertRawListHandler('SNDD', True, SNDD);
+  InsertRawListHandler('SUBT', True, SUBT);
+  InsertRawListHandler('TRAM', True, TRAM);
+  InsertRawListHandler('TXMP', True, TXMP);
+end.
Index: /oup/releases/0.33a/Code/Exporters.pas
===================================================================
--- /oup/releases/0.33a/Code/Exporters.pas	(revision 76)
+++ /oup/releases/0.33a/Code/Exporters.pas	(revision 76)
@@ -0,0 +1,251 @@
+unit Exporters;
+
+interface
+
+uses Classes, Dialogs, StrUtils, SysUtils, Math, Data, OniImgClass;
+
+procedure ExportDatFile(fileid: LongWord; filename: String);
+procedure ExportRawFiles(fileid: LongWord; filename: String);
+procedure ExportRawFile(fileid: LongWord; dat_offset: LongWord; filename: String);
+function ExportConverted(fileid: LongWord; filename: String): Integer;
+
+function ExportSNDD(fileid: LongWord; filename: String): Integer;
+function ExportTRAC(fileid: LongWord; filename: String): Integer;
+function ExportTXAN(fileid: LongWord; filename: String): Integer;
+function ExportImage(fileid: LongWord; filename: String): Integer;
+
+var
+  ExportHandlers: array[1..3] of TExportHandlers = (
+//    (Ext:'ABNA'; needed:False),
+//    (Ext:'AGDB'; needed:False),
+    (Ext: 'SNDD'; needed: True; Handler: ExportSNDD),
+//    (Ext:'TRAC'; needed:True; Handler:ExportTRAC),
+//    (Ext:'TXAN'; needed:True; Handler:ExportTXAN),
+    (Ext:'TXMB'; needed:True; Handler:ExportImage),
+    (Ext:'TXMP'; needed:True; Handler:ExportImage)
+);
+
+
+
+implementation
+
+uses Functions, DataStructures, OniDataClass;
+
+
+
+procedure ExportDatFile(fileid: LongWord; filename: String);
+var
+  filestream: TFileStream;
+  Data: Tdata;
+begin
+  Data := OniDataConnection.LoadDatFile(fileid);
+  if FileExists(filename) then
+  begin
+    filestream := TFileStream.Create(filename, fmOpenReadWrite);
+    filestream.Seek(0, soFromEnd);
+  end
+  else
+  begin
+    filestream := TFileStream.Create(filename, fmCreate);
+  end;
+  filestream.Write(Data[0], Length(Data));
+  filestream.Free;
+end;
+
+
+procedure ExportRawFiles(fileid: LongWord; filename: String);
+var
+  i: Integer;
+  rawlist: TRawList;
+begin
+  rawlist := OniDataConnection.GetRawList(fileid);
+  if Length(rawlist) > 0 then
+    for i := 0 to High(rawlist) do
+      ExportRawFile(fileid, rawlist[i].src_offset, filename);
+end;
+
+procedure ExportRawFile(fileid: LongWord; dat_offset: LongWord; filename: String);
+var
+  filestream: TFileStream;
+  Data: Tdata;
+begin
+  SetLength(Data, OniDataConnection.GetRawInfo(fileid, dat_offset).raw_size);
+  OniDataConnection.LoadRawFile(fileid, dat_offset, @Data[0]);
+  if FileExists(filename + '.raw0x' + IntToHex(dat_offset, 8)) then
+  begin
+    filestream := TFileStream.Create(filename + '.raw0x' + IntToHex(
+      dat_offset, 8), fmOpenReadWrite);
+    filestream.Seek(0, soFromEnd);
+  end
+  else
+  begin
+    filestream := TFileStream.Create(filename + '.raw0x' + IntToHex(dat_offset, 8), fmCreate);
+  end;
+  filestream.Write(Data[0], Length(Data));
+  filestream.Free;
+end;
+
+function ExportConverted(fileid: LongWord; filename: String): Integer;
+var
+  i: Integer;
+  fileinfo: TFileInfo;
+begin
+  fileinfo := OniDataConnection.GetFileInfo(fileid);
+  if Length(ExportHandlers) > 0 then
+    for i := 0 to High(ExportHandlers) do
+      if ExportHandlers[i].Ext = fileinfo.Extension then
+        ExportHandlers[i].Handler(fileid, filename);
+end;
+
+
+
+
+function ExportSNDD;
+type
+  TDatData = packed record
+    {0x00}
+    _fileid:         LongWord;
+    level:           LongWord;
+    FormatSize:      LongWord;
+    AudioFormat:     Word;
+    NumChannels:     Word;
+    {0x10}
+    SampleRate:      LongWord;
+    ByteRate:        LongWord;
+    BlockAlign:      Word;
+    BitsPerSample:   Word;
+    {0x1C}
+    SizeExtHeader:   Word;
+    SamplesPerBlock: Word;
+    NumCoefficients: Word;
+    Coefficients:    array[0..6] of LongWord;
+    {0x3E}
+    Duration:        Word;
+    {0x40}
+    RawSize:         LongWord;
+    RawPos:          LongWord;
+  end;
+var
+  filestream: TFileStream;
+  DatData:     TDatData;
+  i: Integer;
+  Data: Tdata;
+
+  //Wave Header Stuff
+  ASCII_RIFF:   LongWord; //"RIFF"
+  WAVE_Len:     LongWord;
+  ASCII_WAVE:   LongWord; //"WAVE"
+  ASCII_FMT:    LongWord; //"fmt "
+  WAVE_FMT_Len: LongWord;
+  ASCII_DATA:   LongWord; //"data"
+  WAVE_DataLen:  LongWord;
+begin
+  Result := export_noerror;
+  OniDataConnection.LoadDatFilePart(fileid, 0, SizeOf(DatData), @DatData);
+  with DatData do
+  begin
+    //Initializing Header vars
+    ASCII_RIFF   := 1179011410; // 'RIFF'
+    WAVE_Len     := RAWSize + 70;
+    ASCII_WAVE   := 1163280727;  // 'WAVE'
+    ASCII_FMT    := 544501094;   // 'fmt '
+    WAVE_FMT_Len := 50;          // 50 bytes
+    ASCII_DATA   := 1635017060;  // 'data'
+    WAVE_DataLen := RAWSize;
+    SetLength(Data, RAWSize);
+    OniDataConnection.LoadRawFile(fileid, $44, Data);
+
+    //Now start packing this into a neat wave...
+    filestream := TFileStream.Create(filename + '.wav', fmCreate);
+    filestream.Write(ASCII_RIFF, SizeOf(ASCII_RIFF));
+    filestream.Write(WAVE_Len, SizeOf(WAVE_Len));
+    filestream.Write(ASCII_WAVE, SizeOf(ASCII_WAVE));
+    filestream.Write(ASCII_FMT, SizeOf(ASCII_FMT));
+    filestream.Write(WAVE_FMT_Len, SizeOf(WAVE_FMT_Len));
+    filestream.Write(AudioFormat, SizeOf(AudioFormat));
+    filestream.Write(NumChannels, SizeOf(NumChannels));
+    filestream.Write(Samplerate, SizeOf(Samplerate));
+    filestream.Write(ByteRate, SizeOf(ByteRate));
+    filestream.Write(BlockAlign, SizeOf(BlockAlign));
+    filestream.Write(BitsPerSample, SizeOf(BitsPerSample));
+    filestream.Write(SizeExtHeader, SizeOf(SizeExtHeader));
+    filestream.Write(SamplesPerBlock, SizeOf(SamplesPerBlock));
+    filestream.Write(NumCoefficients, SizeOf(NumCoefficients));
+    for i := 0 to High(Coefficients) do
+      filestream.Write(Coefficients[i], SizeOf(Coefficients[i]));
+    filestream.Write(ASCII_DATA, SizeOf(ASCII_DATA));
+    filestream.Write(WAVE_DataLen, SizeOf(WAVE_DataLen));
+    filestream.Write(Data[0], Length(Data));
+    filestream.Free;
+  end;
+end;
+
+
+
+
+function ExportTRAC;
+var
+  link: LongWord;
+  linkcount: Word;
+  i: LongWord;
+begin
+  Result := export_noerror;
+
+  OniDataConnection.LoadDatFilePart(fileid, $18, SizeOf(link), @link);
+  link := link div 256;
+
+  OniDataConnection.LoadDatFilePart(fileid, $1E, SizeOf(linkcount), @linkcount);
+  for i := 1 to linkcount do
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $20 + (i - 1) * 12 + 8, SizeOf(link), @link);
+    link := link div 256;
+  end;
+end;
+
+
+
+
+function ExportTXAN;
+var
+  loop_speed, unknown: Word;
+  linkcount: LongWord;
+  link: LongWord;
+  i: Byte;
+begin
+  Result := export_noerror;
+
+  OniDataConnection.LoadDatFilePart(fileid, $14, SizeOf(loop_speed), @loop_speed);
+  OniDataConnection.LoadDatFilePart(fileid, $16, SizeOf(unknown), @unknown);
+
+  OniDataConnection.LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
+  for i := 0 to linkcount - 1 do
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
+    link := link div 256;
+    if link = 0 then
+      link := fileid - 1;
+  end;
+end;
+
+
+
+
+function ExportImage;
+var
+  filestream: TFileStream;
+  img: TOniImage;
+  data: Tdata;
+begin
+  Result := export_noerror;
+
+  img := TOniImage.Create;
+  img.Load(fileid);
+  data := img.GetAsBMP;
+  img.Free;
+
+  filestream:=TFileStream.Create(filename+'.bmp',fmCreate);
+  filestream.Write(data[0],Length(data));
+  filestream.Free;
+end;
+
+end.
Index: /oup/releases/0.33a/Code/FolderBrowser.pas
===================================================================
--- /oup/releases/0.33a/Code/FolderBrowser.pas	(revision 76)
+++ /oup/releases/0.33a/Code/FolderBrowser.pas	(revision 76)
@@ -0,0 +1,549 @@
+// -----------------------------------------------------------------------------
+//
+// TFolderBrowser-Klasse
+// Copyright (c) 2003-2005 Delphi-Forum
+// Tino, Popov, Christian Stelzman (PL), Luckie, Aton, Mathias Simmack (msi)
+//
+// basiert auf den folgenden Beiträgen
+//   - http://www.delphi-forum.de/viewtopic.php?t=11240
+//   - http://www.delphi-forum.de/viewtopic.php?t=21471
+//   * http://www.delphi-forum.de/viewtopic.php?t=25302
+//   - http://www.delphi-forum.de/viewtopic.php?t=27010&start=0
+//
+// -----------------------------------------------------------------------------
+
+// -- Revision history ---------------------------------------------------------
+//
+//   * ursprüngliche Version von PL (s. Link #3)
+//   * Fehlerkorrekturen von Luckie
+//       - Result bei Callback ergänzt
+//       - Properties als private deklariert
+//       - Bugs in "Execute"-Methode behoben
+//   * Dateifilter in Callback-Funktion
+//       - Idee (Aton)
+//       - globale Stringvariable (msi)
+//       - TFolderBrowser-Klasse (PL)
+//   * Unterstützung für mehrere Filter ergänzt (msi)
+//   * Unterstützung für verschiedene Root-Ordner (msi)
+//   * Änderungen bei den Properties (msi)
+//       - "SelFolder" in "SelectedItem" umbenannt
+//       - "FNewFolder" als "NewFolderButton" verfügbar
+//       - "FShowFiles" als "ShowFiles" verfügbar
+//       - "FNoTT" als "NoTargetTranslation" verfügbar (XP-Flag)
+//   * Funktion zum Ermitteln von Verknüpfungszielen ergänzt (msi)
+//       - Ergänzung, um Umgebungsvariablen umzuwandeln
+//   * "InitFolder" (s. Create) umbenannt in "PreSelectedFolder" (PL)
+//   * "FNoTT" (NoTargetTranslation) standardmäßig auf TRUE gesetzt,
+//     damit alle Windows-Versionen, inkl. XP, gleich reagieren (msi)
+//   * "CoInitializeEx" (Execute & TranslateLink) geändert (msi)
+//   * "TranslateMsiLink" (PL, msi)
+//        - ermittelt Pfad/Programm aus MSI-Verknüpfungen (Office, Openoffice)
+//        - benötigt installierten MSI
+//
+// -----------------------------------------------------------------------------
+unit FolderBrowser;
+
+
+interface
+
+uses
+  ShlObj, ActiveX, Windows, Messages;
+
+type
+  TFolderBrowser = class
+  private
+    // alles private gemacht; geht niemanden was an,
+    // da nachträglicher Zugriff sinnlos (Luckie)
+    FHandle      : THandle;
+    FCaption     : string;
+    FShowFiles   : boolean;
+    FNewFolder   : boolean;
+    FStatusText  : boolean;
+    FNoTT        : boolean;
+    FInitFolder  : string;
+    FSelected    : string;
+    FTop,
+    FLeft        : integer;
+    FPosChanged  : boolean;
+
+    // mehrere Filter müssen durch #0 voneinander getrennt
+    // werden, bspw. '*.txt'#0'*.*htm*'#0'*.xml'
+    // der letzte Filter kann mit #0#0 enden, muss er aber
+    // nicht, weil die Funktion "CheckFilter" diese beiden
+    // Zeichen automatisch anhängt (Mathias)
+    FFilter      : string;
+    FRoot        : PItemIdList;
+    procedure FreeItemIDList(var pidl: pItemIDList);
+    procedure SetTopPosition(const Value: Integer);
+    procedure SetLeftPosition(const Value: Integer);
+  public
+    constructor Create(Handle: THandle; const Caption: string;
+      const PreSelectedFolder: string = ''; ShowFiles: Boolean = False;
+      NewFolder: Boolean = False);
+    destructor Destroy; override;
+    function SetDefaultRoot: boolean;
+    function SetRoot(const SpecialFolderId: integer): boolean; overload;
+    function SetRoot(const Path: string): boolean; overload;
+    function Execute: Boolean; overload;
+    function TranslateLink(const LnkFile: string): string;
+    function TranslateMsiLink(const LnkFile: string): string;
+    property SelectedItem: string read FSelected;
+    property Filter: string read FFilter write FFilter;
+    property NewFolderButton: boolean read FNewFolder write FNewFolder;
+    property ShowFiles: boolean read FShowFiles write FShowFiles;
+    property StatusText: boolean read FStatusText write FStatusText;
+    property NoTargetTranslation: boolean read FNoTT write FNoTT;
+    property Top: integer read FTop write SetTopPosition;
+    property Left: integer read FLeft write SetLeftPosition;
+  end;
+
+implementation
+
+
+//
+// erweiterte SHBrowseForFolder-Eigenschaften
+// (Deklaration ist notwendig, weil u.U. nicht in jeder Delphi-Version
+// bekannt und verfügbar)
+//
+const
+  BIF_NEWDIALOGSTYLE     = $0040;
+  BIF_USENEWUI           = BIF_NEWDIALOGSTYLE or BIF_EDITBOX;
+  BIF_BROWSEINCLUDEURLS  = $0080;
+  BIF_UAHINT             = $0100;
+  BIF_NONEWFOLDERBUTTON  = $0200;
+  BIF_NOTRANSLATETARGETS = $0400;
+  BIF_SHAREABLE          = $8000;
+
+  BFFM_IUNKNOWN          = 5;
+  BFFM_SETOKTEXT         = WM_USER + 105; // Unicode only
+  BFFM_SETEXPANDED       = WM_USER + 106; // Unicode only
+
+
+// -- helper functions ---------------------------------------------------------
+
+function fileexists(const FileName: string): boolean;
+var
+  Handle   : THandle;
+  FindData : TWin32FindData;
+begin
+  Handle   := FindFirstFile(pchar(FileName),FindData);
+  Result   := (Handle <> INVALID_HANDLE_VALUE);
+
+  if(Result) then FindClose(Handle);
+end;
+
+function CheckFilter(const Path, Filter: string): boolean;
+var
+  p      : pchar;
+begin
+  // Standardergebnis
+  Result := false;
+  if(Path = '') or (Filter = '') then exit;
+
+  // #0#0 an den Filter anhängen, damit später das Ende
+  // korrekt erkannt wird
+  p      := pchar(Filter + #0#0);
+  while(p[0] <> #0) do
+  begin
+    // Datei mit entsprechendem Filter wurde gefunden, ...
+    if(fileexists(Path + '\' + p)) then
+    begin
+    // ... Ergebnis auf TRUE setzen, und Schleife abbrechen
+      Result := true;
+      break;
+    end;
+
+    // ansonsten zum nächsten Filter
+    inc(p,lstrlen(p) + 1);
+  end;
+end;
+
+function SHGetIDListFromPath(const Path: string; out pidl: PItemIDList):
+  boolean;
+var
+  ppshf        : IShellFolder;
+  wpath        : array[0..MAX_PATH]of widechar;
+  pchEaten,
+  dwAttributes : Cardinal;
+begin
+  // Standardergebnis
+  Result       := false;
+
+  // IShellFolder-Handle holen
+  if(SHGetDesktopFolder(ppshf) = S_OK) then
+  try
+    if(StringToWideChar(Path,wpath,sizeof(wpath)) <> nil) then
+    begin
+      // Pfadname in "PItemIdList" umwandeln
+      ppshf.ParseDisplayName(0,nil,wpath,pchEaten,pidl,dwAttributes);
+      Result   := pidl <> nil;
+    end;
+  finally
+    ppshf      := nil;
+  end;
+end;
+
+//
+// "CreateComObject" (modifizierte Version; Mathias)
+//
+function CreateComObject(const ClassID: TGUID;
+  out OleResult : HRESULT): IUnknown;
+begin
+  OleResult := CoCreateInstance(ClassID,nil,CLSCTX_INPROC_SERVER or
+    CLSCTX_LOCAL_SERVER,IUnknown,Result);
+end;
+
+//
+// "ExpandEnvStr"
+//
+function ExpandEnvStr(const szInput: string): string;
+const
+  MAXSIZE = 32768;
+begin
+  SetLength(Result,MAXSIZE);
+  SetLength(Result,ExpandEnvironmentStrings(pchar(szInput),
+    @Result[1],length(Result)));
+end;
+
+
+
+// -----------------------------------------------------------------------------
+//
+// TFolderBrowser-Klasse
+//
+// -----------------------------------------------------------------------------
+
+function FolderCallback(wnd: HWND; uMsg: UINT; lp, lpData: LPARAM): LRESULT;
+  stdcall;
+var
+  path : array[0..MAX_PATH + 1]of char;
+  fb   : TFolderBrowser;
+begin
+  fb   := TFolderBrowser(lpData);
+
+  case uMsg of
+    // Dialog wurde initialisiert
+    BFFM_INITIALIZED:
+      begin
+        // Ordner auswählen, ...
+        if(fb.FInitFolder <> '') then
+          SendMessage(wnd,BFFM_SETSELECTION,WPARAM(true),
+          LPARAM(pchar(fb.FInitFolder)));
+
+        // ... & OK-Button deaktivieren, wenn Filter benutzt werden
+        SendMessage(wnd,BFFM_ENABLEOK,0,LPARAM(fb.FFilter = ''));
+        // oder anders gesagt: OK-Button aktivieren, wenn keine
+        // Filter benutzt werden. ;o)
+        // (Mathias)
+
+        // Dialog neu positionieren
+        if(fb.FPosChanged) then
+          SetWindowPos(wnd,0,fb.Left,fb.Top,0,0,SWP_NOSIZE or SWP_NOZORDER);
+      end;
+    BFFM_SELCHANGED:
+      if(PItemIdList(lp) <> nil) and (fb.FFilter <> '') then
+      begin
+        // den aktuellen Pfadnamen holen, ...
+        ZeroMemory(@path,sizeof(path));
+        if(SHGetPathFromIdList(PItemIdList(lp),path)) then
+        begin
+        // ... & anzeigen
+          SendMessage(wnd,BFFM_SETSTATUSTEXT,0,LPARAM(@path));
+
+        // gibt´s Dateien mit dem Filter?
+        // nur dann wird der OK-Button des Dialogs aktiviert
+          SendMessage(wnd,BFFM_ENABLEOK,0,LPARAM(CheckFilter(path,fb.FFilter)));
+        end;
+      end;
+  end;
+
+  Result := 0; // von Luckie hinzugefügt, hatte ich vergessen (oops)
+end;
+
+
+constructor TFolderBrowser.Create(Handle: THandle; const Caption: string;
+  const PreSelectedFolder: string = ''; ShowFiles: Boolean = False;
+  NewFolder: Boolean = False);
+begin
+  FHandle     := Handle;
+  FCaption    := Caption;
+  FInitFolder := PreSelectedFolder;
+  FShowFiles  := ShowFiles;
+  FNewFolder  := NewFolder;
+  FStatusText := true;
+  FNoTT       := true;
+  FFilter     := '';
+  FRoot       := nil;
+  FTop        := 0;
+  FLeft       := 0;
+  FPosChanged := false;
+end;
+
+destructor TFolderBrowser.Destroy;
+begin
+  // ggf. belegte "PItemIdList" freigeben
+  if(FRoot <> nil) then
+    self.FreeItemIdList(FRoot);
+
+  inherited Destroy;
+end;
+
+procedure TFolderBrowser.SetTopPosition(const Value: integer);
+begin
+  FPosChanged := true;
+  FTop        := Value;
+end;
+
+procedure TFolderBrowser.SetLeftPosition(const Value: integer);
+begin
+  FPosChanged := true;
+  FLeft       := Value;
+end;
+
+function TFolderBrowser.SetDefaultRoot: boolean;
+begin
+  // altes Objekt freigeben
+  if(FRoot <> nil) then
+    self.FreeItemIDList(FRoot);
+
+  // und alles zurücksetzen
+  FRoot  := nil;
+  Result := true;
+end;
+
+function TFolderBrowser.SetRoot(const SpecialFolderId: integer): boolean;
+begin
+  // altes Objekt freigeben
+  if(FRoot <> nil) then
+    self.FreeItemIDList(FRoot);
+
+  // SpecialFolderId kann eine der CSIDL_*-Konstanten sein,
+  //   CSIDL_DESKTOP
+  //   CSIDL_STARTMENU
+  //   CSIDL_PERSONAL
+  //   ...
+  // s. PSDK
+
+  // neuen Root setzen
+  Result := SHGetSpecialFolderLocation(FHandle,SpecialFolderId,FRoot) = S_OK;
+end;
+
+function TFolderBrowser.SetRoot(const Path: string): boolean;
+begin
+  // altes Objekt freigeben
+  if(FRoot <> nil) then
+    self.FreeItemIDList(FRoot);
+
+  // neuen Root setzen
+  Result := SHGetIDListFromPath(Path,FRoot);
+end;
+
+function TFolderBrowser.Execute: Boolean;
+var
+  hr           : HRESULT;
+  BrowseInfo   : TBrowseInfo;
+  pidlResult   : PItemIDList;
+  DisplayName,
+  Path         : array[0..MAX_PATH + 1]of char;
+begin
+  Result       := false;
+
+  hr           := CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
+  // Wenn die COM-Bibliothek noch nicht initialisiert ist,
+  // dann ist das Ergebnis S_OK; ist sie bereits initialisiert
+  // ist sie S_FALSE
+  if(hr = S_OK) or (hr = S_FALSE) then
+  try
+    // "BrowseInfo" mit Werten füllen
+    ZeroMemory(@BrowseInfo,sizeof(BrowseInfo));
+    BrowseInfo.hwndOwner      := FHandle;
+    BrowseInfo.pidlRoot       := FRoot;
+    BrowseInfo.pszDisplayName := @Displayname;
+    BrowseInfo.lpszTitle      := pchar(FCaption);
+    BrowseInfo.lpfn           := @FolderCallBack;
+
+    // TFolderBrowser-Klasse als Referenz für Callback-Funktion
+    // übergeben (PL)
+    BrowseInfo.lParam         := LPARAM(self);
+
+    // Flags
+    if(FStatusText) then
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_STATUSTEXT;
+
+
+    // BIF_USENEWUI sorgt dafür dass besagter Button immer angezeigt wird,
+    // egal, ob BIF_BROWSEINCLUDEFILES gesetzt wird oder nicht, daher
+    // rausgenommen (Luckie)
+    if(FShowFiles) then
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_BROWSEINCLUDEFILES;
+
+    // Button zum Erstellen neuer Ordner anzeigen? (Luckie, PL)
+    if(FNewFolder) then
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_NEWDIALOGSTYLE
+    else
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_NONEWFOLDERBUTTON;
+
+    // Windows XP sucht automatisch die Verknüpfungsziele von
+    // Shortcuts heraus; soll stattdessen aber der Name der
+    // Verknüpfung angezeigt werden, ist das Flag BIF_NOTRANSLATETARGETS
+    // erforderlich; Sinn macht es nur unter Windows XP
+    if(FNoTT) then
+      BrowseInfo.ulFlags      := BrowseInfo.ulFlags or BIF_NOTRANSLATETARGETS;
+    // für die älteren Windows-Versionen gibt es mit der Funktion
+    // "TranslateLink" (s. weiter unten) eine Entsprechung, um die
+    // Ziele von Shortcuts zu ermitteln (Mathias)
+
+
+    // Dialog aufrufen
+    pidlResult := SHBrowseForFolder(BrowseInfo);
+    if(pidlResult <> nil) then
+    begin
+      if(FSelected = '') then
+        if(SHGetPathFromIdList(pidlResult,Path)) and
+          (Path[0] <> #0) then
+        begin
+          FSelected := Path;
+          Result    := true;
+        end;
+
+      self.FreeItemIdList(pidlResult);
+    end;
+  finally
+    CoUninitialize;
+  end;
+end;
+
+function TFolderBrowser.TranslateLink(const LnkFile: string): string;
+var
+  link       : IShellLink;
+  hr         : HRESULT;
+  afile      : IPersistFile;
+  pwcLnkFile : array[0..MAX_PATH]of widechar;
+  szData     : array[0..MAX_PATH]of char;
+  FindData   : TWin32FindData;
+begin
+  // Standardergebnis
+  Result     := '';
+  link       := nil;
+  afile      := nil;
+
+  hr         := CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
+  if(hr = S_OK) or (hr = S_FALSE) then
+  try
+    // IShellLink-Interface erzeugen, ...
+    link   := CreateComObject(CLSID_ShellLink,hr) as IShellLink;
+    if(hr = S_OK) and (link <> nil) then
+    begin
+    // ... & Verknüpfung laden
+      StringToWideChar(LnkFile,pwcLnkFile,sizeof(pwcLnkFile));
+      afile := link as IPersistFile;
+
+      if(afile <> nil) and
+        (afile.Load(pwcLnkFile,STGM_READ) = S_OK) then
+      begin
+        ZeroMemory(@szData,sizeof(szData));
+
+    // Pfad + Dateiname ermitteln, ...
+        if(link.GetPath(szData,sizeof(szData),FindData,
+          SLGP_RAWPATH) = S_OK) then
+        begin
+          SetString(Result,szData,lstrlen(szData));
+    // ... & evtl. Umgebungsvariablen filtern
+          Result := ExpandEnvStr(Result);
+        end;
+      end;
+    end;
+  finally
+    if(afile <> nil) then afile := nil;
+    if(link <> nil) then link := nil;
+
+    CoUninitialize;
+  end;
+end;
+
+procedure TFolderBrowser.FreeItemIDList(var pidl: pItemIDList);
+var
+  ppMalloc : iMalloc;
+begin
+  if(SHGetMalloc(ppMalloc) = S_OK) then
+  try
+    ppMalloc.Free(pidl);
+    pidl     := nil;
+  finally
+    ppMalloc := nil;
+  end;
+end;
+
+
+const
+  MsiDllName                = 'msi.dll';
+
+  INSTALLSTATE_ABSENT       =  2;    // uninstalled
+  INSTALLSTATE_LOCAL        =  3;    // installed on local drive
+  INSTALLSTATE_SOURCE       =  4;    // run from source, CD or net
+  INSTALLSTATE_SOURCEABSENT = -4;    // run from source, source is unavailable
+  INSTALLSTATE_NOTUSED      = -7;    // component disabled
+  INSTALLSTATE_INVALIDARG   = -2;    // invalid function argument
+  INSTALLSTATE_UNKNOWN      = -1;    // unrecognized product or feature
+
+type
+  INSTALLSTATE              = LongInt;
+
+  TMsiGetShortcutTarget     = function(szShortcutTarget, szProductCode,
+    szFeatureId, szComponentCode: PAnsiChar): uint; stdcall;
+  TMsiGetComponentPath      = function(szProduct, szComponent: PAnsiChar;
+    lpPathBuf: PAnsiChar; pcchBuf: pdword): INSTALLSTATE; stdcall;
+var
+  MsiGetShortcutTarget      : TMsiGetShortcutTarget = nil;
+  MsiGetComponentPath       : TMsiGetComponentPath  = nil;
+  MsiDll                    : dword = 0;
+
+function TFolderBrowser.TranslateMsiLink(const LnkFile: string): string;
+var
+  ProductCode,
+  FeatureId,
+  ComponentCode : array[0..MAX_PATH]of char;
+  Path          : array[0..MAX_PATH]of char;
+  PathLen       : dword;
+begin
+  Result := '';
+  if(@MsiGetShortcutTarget = nil) or (@MsiGetComponentPath = nil) then exit;
+
+  ZeroMemory(@ProductCode, sizeof(ProductCode));
+  ZeroMemory(@FeatureId, sizeof(FeatureId));
+  ZeroMemory(@ComponentCode, sizeof(ComponentCode));
+
+  if(MsiGetShortcutTarget(PAnsiChar(LnkFile), ProductCode, FeatureId,
+    ComponentCode) = ERROR_SUCCESS) then
+  begin
+    ZeroMemory(@Path, sizeof(Path));
+    PathLen := sizeof(Path);
+
+    case MsiGetComponentPath(ProductCode, ComponentCode, Path, @PathLen) of
+      INSTALLSTATE_LOCAL,
+      INSTALLSTATE_SOURCE:
+        SetString(Result, Path, lstrlen(Path));
+    end;
+  end;
+end;
+
+
+initialization
+  MsiDll                     := GetModuleHandle(MsiDllName);
+  if(MsiDll = 0) then MsiDll := LoadLibrary(MsiDllName);
+
+  if(MsiDll <> 0) then
+  begin
+    MsiGetShortcutTarget     := GetProcAddress(MsiDll, 'MsiGetShortcutTargetA');
+    MsiGetComponentPath      := GetProcAddress(MsiDll, 'MsiGetComponentPathA');
+
+    if(@MsiGetShortcutTarget = nil) or
+      (@MsiGetComponentPath  = nil) then
+    begin
+      FreeLibrary(MsiDll);
+      MsiDll := 0;
+    end;
+  end;
+finalization
+  if(MsiDll <> 0) then FreeLibrary(MsiDll);
+end.
Index: /oup/releases/0.33a/Code/Functions.pas
===================================================================
--- /oup/releases/0.33a/Code/Functions.pas	(revision 76)
+++ /oup/releases/0.33a/Code/Functions.pas	(revision 76)
@@ -0,0 +1,362 @@
+unit Functions;
+
+interface
+
+uses Classes, Dialogs, SysUtils, StrUtils, Math, Data;
+
+function BoolToStr(bool: Boolean): String;
+function HexToLong(hex: String): LongWord;
+function Decode_Int(buffer: Tdata): LongWord;
+function Encode_Int(input: LongWord): Tdata;
+function Decode_Float(buffer: Tdata): Single;
+function Encode_Float(input: Single): Tdata;
+function DataToBin(Data: Tdata): String;
+function BinToInt(bin: String): Byte;
+
+function StringSmaller(string1, string2: String): Boolean;
+
+function FormatNumber(Value: LongWord; Width: Byte; leadingzeros: Char): String;
+function FormatFileSize(size: LongWord): String;
+function CreateHexString(Data: Tdata; HexOnly: Boolean): String;
+function DecodeHexString(hex: String): Tdata;
+function GetWinFileName(Name: String): String;
+function GetExtractPath: String;
+
+function Explode(_string: String; delimiter: Char): TStringArray;
+
+
+implementation
+
+uses Exporters, OniDataClass;
+
+type
+  TValueSwitcher = record
+    case IsFloat: Boolean of
+      True: (ValueFloat: Single);
+      False: (ValueInt: LongWord);
+  end;
+
+
+
+
+function BoolToStr(bool: Boolean): String;
+begin
+  if bool then
+    Result := 'true'
+  else
+    Result := 'false';
+end;
+
+
+
+
+function HexToLong(hex: String): LongWord;
+
+
+
+
+  function NormalizeHexString(var hex: String): Boolean;
+  var
+    i: Byte;
+  begin
+    if hex[1] = '$' then
+    begin
+      for i := 1 to Length(hex) - 1 do
+      begin
+        hex[i] := hex[i + 1];
+      end;
+      SetLength(hex, Length(hex) - 1);
+    end;
+    if (hex[1] = '0') and (UpCase(hex[2]) = 'X') then
+    begin
+      for i := 1 to Length(hex) - 2 do
+      begin
+        hex[i] := hex[i + 2];
+      end;
+      SetLength(hex, Length(hex) - 2);
+    end;
+    if Length(hex) = 0 then
+      Result := False
+    else
+      Result := True;
+  end;
+
+var
+  i: Byte;
+begin
+  if NormalizeHexString(hex) then
+  begin
+    hex    := UpperCase(hex);
+    Result := 0;
+    for i := 1 to Length(hex) do
+    begin
+      Result := Result shl 4;
+      case hex[i] of
+        '0'..'9':
+          Result := Result + Ord(hex[i]) - 48;
+        'A'..'F':
+          Result := Result + Ord(hex[i]) - 55;
+        else
+          Result := 0;
+          Exit;
+      end;
+    end;
+  end
+  else
+  begin
+    Result := 0;
+  end;
+end;
+
+
+
+
+function Decode_Int(buffer: Tdata): LongWord;
+begin
+  Result := buffer[0] + buffer[1] * 256 + buffer[2] * 256 * 256 + buffer[3] * 256 * 256 * 256;
+end;
+
+
+
+
+function Encode_Int(input: LongWord): Tdata;
+begin
+  SetLength(Result, 4);
+  Result[0] := input mod 256;
+  input     := input div 256;
+  Result[1] := input mod 256;
+  input     := input div 256;
+  Result[2] := input mod 256;
+  input     := input div 256;
+  Result[3] := input mod 256;
+end;
+
+
+
+
+function Decode_Float(buffer: Tdata): Single;
+var
+  _valueswitcher: TValueSwitcher;
+begin
+  _valueswitcher.ValueInt := Decode_Int(buffer);
+  Result := _valueswitcher.ValueFloat;
+  if IsNAN(Result) then
+    Result := 0.0;
+end;
+
+
+
+
+function Encode_Float(input: Single): Tdata;
+var
+  _valueswitcher: TValueSwitcher;
+begin
+  _valueswitcher.ValueFloat := input;
+  Result := Encode_Int(_valueswitcher.ValueInt);
+end;
+
+
+
+
+function DataToBin(Data: Tdata): String;
+var
+  i, j:     Byte;
+  singlebyte: Byte;
+  bytepart: String;
+begin
+  SetLength(bytepart, 8);
+  Result := '';
+  for i := 0 to High(Data) do
+  begin
+    singlebyte := Data[i];
+    for j := 7 downto 0 do
+    begin
+      bytepart[j + 1] := Char((singlebyte and $01) + 48);
+      singlebyte      := singlebyte shr 1;
+    end;
+    Result := Result + bytepart + ' ';
+  end;
+end;
+
+
+
+
+function BinToInt(bin: String): Byte;
+var
+  Add: Integer;
+  i:   Byte;
+begin
+  Result := 0;
+  if Length(bin) <> 8 then
+    Exit;
+  Add := 1;
+  for i := 8 downto 1 do
+  begin
+    if not (bin[i] in ['0', '1']) then
+      Exit;
+    if bin[i] = '1' then
+      Inc(Result, Add);
+    Add := Add shl 1;
+  end;
+end;
+
+
+
+
+function FormatNumber(Value: LongWord; Width: Byte; leadingzeros: Char): String;
+begin
+  Result := AnsiReplaceStr(Format('%' + IntToStr(Width) + 'u', [Value]), ' ', leadingzeros);
+end;
+
+
+
+
+function FormatFileSize(size: LongWord): String;
+var
+  floatformat: TFormatSettings;
+begin
+  floatformat.DecimalSeparator := '.';
+  if size >= 1000 * 1024 * 1024 then
+  begin
+    Result := FloatToStrF(size / 1024 / 1024 / 1024, ffFixed, 5, 1, floatformat) + ' GB';
+  end
+  else
+  begin
+    if size >= 1000 * 1024 then
+    begin
+      Result := FloatToStrF(size / 1024 / 1024, ffFixed, 5, 1, floatformat) + ' MB';
+    end
+    else
+    begin
+      if size >= 1000 then
+      begin
+        Result := FloatToStrF(size / 1024, ffFixed, 5, 1, floatformat) + ' KB';
+      end
+      else
+      begin
+        Result := IntToStr(size) + ' B';
+      end;
+    end;
+  end;
+end;
+
+
+
+
+function CreateHexString(Data: Tdata; HexOnly: Boolean): String;
+var
+  string_build, ascii_version: String;
+  i: LongWord;
+begin
+  string_build  := '';
+  ascii_version := '';
+  for i := 0 to High(Data) do
+  begin
+    if not HexOnly then
+      if (i mod 16) = 0 then
+        string_build := string_build + '0x' + IntToHex(i, 6) + '  ';
+    string_build := string_build + IntToHex(Data[i], 2);
+    if not HexOnly then
+    begin
+      if Data[i] >= 32 then
+        ascii_version := ascii_version + Chr(Data[i])
+      else
+        ascii_version := ascii_version + '.';
+      if ((i + 1) mod 2) = 0 then
+        string_build := string_build + #32;
+      if ((i + 1) mod 16) = 0 then
+      begin
+        string_build  := string_build + #32 + ascii_version + CrLf;
+        ascii_version := '';
+      end;
+    end;
+  end;
+  Result := string_build;
+end;
+
+
+
+
+function DecodeHexString(hex: String): Tdata;
+var
+  i: LongWord;
+begin
+  SetLength(Result, Length(hex) div 2);
+  for i := 0 to Length(Result) do
+  begin
+    Result[i] := 0;
+    case UpCase(hex[1 + i * 2]) of
+      '0'..'9':
+        Result[i] := (Ord(UpCase(hex[1 + i * 2])) - 48) * 16;
+      'A'..'F':
+        Result[i] := (Ord(UpCase(hex[1 + i * 2])) - 55) * 16;
+    end;
+    case UpCase(hex[1 + i * 2 + 1]) of
+      '0'..'9':
+        Result[i] := Result[i] + (Ord(UpCase(hex[1 + i * 2 + 1])) - 48);
+      'A'..'F':
+        Result[i] := Result[i] + (Ord(UpCase(hex[1 + i * 2 + 1])) - 55);
+    end;
+  end;
+end;
+
+
+
+
+function StringSmaller(string1, string2: String): Boolean;
+var
+  i:   Integer;
+  len: Integer;
+begin
+  len := Min(Length(string1), Length(string2));
+  for i := 1 to len do
+    if Ord(string1[i]) <> Ord(string2[i]) then
+    begin
+      Result := Ord(string1[i]) < Ord(string2[i]);
+      Exit;
+    end;
+  Result := Length(string1) < Length(string2);
+end;
+
+
+
+function Explode(_string: String; delimiter: Char): TStringArray;
+var
+  start, len: Word;
+begin
+  SetLength(Result, 0);
+  start := 1;
+  while PosEx(delimiter, _string, start) > 0 do
+  begin
+    len := PosEx(delimiter, _string, start) - start;
+    SetLength(Result, Length(Result) + 1);
+    Result[High(Result)] := MidStr(_string, start, len);
+    start := start + len + 1;
+  end;
+  SetLength(Result, Length(Result) + 1);
+  Result[High(Result)] := MidStr(_string, start, Length(_string) - start + 1);
+end;
+
+
+
+
+function GetWinFileName(Name: String): String;
+begin
+  Result := Name;
+  Result := AnsiReplaceStr(Result, '\', '__');
+  Result := AnsiReplaceStr(Result, '/', '__');
+  Result := AnsiReplaceStr(Result, '>', '__');
+  Result := AnsiReplaceStr(Result, '<', '__');
+end;
+
+
+
+
+function GetExtractPath: String;
+begin
+  Result := ExtractFilePath(OniDataConnection.FileName) + '\extracted_' +
+    ExtractFileName(OniDataConnection.Filename);
+end;
+
+
+end.
Index: /oup/releases/0.33a/Code/OniDataClass.pas
===================================================================
--- /oup/releases/0.33a/Code/OniDataClass.pas	(revision 76)
+++ /oup/releases/0.33a/Code/OniDataClass.pas	(revision 76)
@@ -0,0 +1,1422 @@
+unit OniDataClass;
+interface
+uses Data, DataStructures, Classes, SysUtils, StrUtils,
+  Dialogs, ABSDecUtil, ABSMain, DB, Windows;
+
+type
+  TOniData = class
+  private
+    FFileName:  String;
+    FLevelInfo: TLevelInfo;
+    FBackend:   Integer;
+    Fos_mac:    Boolean;
+  protected
+  public
+    property FileName: String Read FFileName Write FFileName;
+    property Backend: Integer Read FBackend Write FBackend;
+    property OSisMac: Boolean Read Fos_mac Write Fos_mac;
+    property LevelInfo: TLevelinfo Read FLevelInfo Write FLevelInfo;
+
+    constructor Create(filename: String; var Result: Boolean); virtual; abstract;
+    procedure Close; virtual; abstract;
+
+    function GetFileInfo(fileid: LongWord): TFileInfo; virtual; abstract;
+    function GetFilesList(ext: String; pattern: String;
+      NoEmptyFiles: Boolean; sort: TSortType): TStringArray; virtual; abstract;
+    function GetFilesCount: LongWord; virtual; abstract;
+    function GetExtensionsList: TStringArray; virtual; abstract;
+    function GetExtendedExtensionsList: TExtensionsMap; virtual; abstract;
+    function ExtractFileID(Name: String): Integer;
+    function GetFileIDByName(Name: String): Integer;
+
+    function LoadDatFile(fileid: LongWord): Tdata; virtual; abstract;
+    procedure UpdateDatFile(fileid: LongWord; Data: Tdata); virtual; abstract;
+    procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
+      virtual; abstract;
+    procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
+      virtual; abstract;
+
+    function GetRawList(fileid: LongWord): TRawList; virtual; abstract;
+    function GetRawInfo(fileid, dat_offset: LongWord): TRawInfo;
+    procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
+      virtual; abstract;
+    procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord; target: Pointer);
+      virtual; abstract;
+    procedure LoadRawFilePart(fileid, dat_offset: LongWord;
+      offset, size: LongWord; target: Pointer); virtual; abstract;
+    procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
+      offset, size: LongWord; target: Pointer); virtual; abstract;
+    function AppendRawFile(loc_sep: Boolean; size: LongWord; target: Pointer): LongWord;
+      virtual; abstract;//Returns new Address
+  published
+  end;
+
+  TOniDataDat = class(TOniData)
+  private
+    Fdat_file:     TFileStream;
+    Fraw_file:     TFileStream;
+    Fsep_file:     TFileStream;
+    Fdat_header:   THeader;
+    Fdat_filesmap: TFilesMap;
+    Fdat_files:    TFiles;
+    Fdat_namedfilesmap: TNamedFilesMap;
+    Fdat_extensionsmap: TExtensionsMap;
+    FUnloadWhenUnused: Boolean;
+    FDatOpened:    Boolean;
+    FRawOpened:    Boolean;
+    FSepOpened:    Boolean;
+  protected
+  public
+    property UnloadWhenUnused: Boolean Read FUnloadWhenUnused Write FUnloadWhenUnused;
+
+    constructor Create(DatFilename: String; var Result: Boolean); override;
+    procedure Close; override;
+
+    function GetFileInfo(fileid: LongWord): TFileInfo; override;
+    function GetFilesList(ext: String; pattern: String;
+      NoEmptyFiles: Boolean; sort: TSortType): TStringArray; override;
+    function GetFilesCount: LongWord; override;
+    function GetExtensionsList: TStringArray; override;
+    function GetExtendedExtensionsList: TExtensionsMap; override;
+
+    function LoadDatFile(fileid: LongWord): Tdata; override;
+    procedure UpdateDatFile(fileid: LongWord; Data: Tdata); override;
+    procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
+    procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
+
+    procedure LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord; target: Pointer);
+    function GetRawList(fileid: LongWord): TRawList; override;
+    procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer); override;
+    procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord;
+      target: Pointer); override;
+    procedure LoadRawFilePart(fileid, dat_offset: LongWord;
+      offset, size: LongWord; target: Pointer); override;
+    procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
+      offset, size: LongWord; target: Pointer); override;
+    function AppendRawFile(loc_sep: Boolean; size: LongWord; target: Pointer): LongWord;
+      override;//Returns new Address
+  published
+  end;
+
+  TOniDataADB = class(TOniData)
+  private
+    FDatabase: TABSDatabase;
+    FQuery:    TABSQuery;
+    Fdat_files:    TFiles;
+    Fdat_extensionsmap: TExtensionsMap;
+  protected
+  public
+    constructor Create(OLDBFilename: String; var Result: Boolean); override;
+    procedure Close; override;
+
+    procedure UpdateListCache;
+    //      function GetDatLinks(srcid:LongWord):TDatLinks;
+    function GetFileInfo(fileid: LongWord): TFileInfo; override;
+    function GetFilesList(ext: String; pattern: String;
+      NoEmptyFiles: Boolean; sort: TSortType): TStringArray; override;
+    function GetFilesCount: LongWord; override;
+    function GetExtensionsList: TStringArray; override;
+    function GetExtendedExtensionsList: TExtensionsMap; override;
+    function GetNamedFilesMap: TNamedFilesMap;
+
+    function LoadDatFile(fileid: LongWord): Tdata; override;
+    procedure UpdateDatFile(fileid: LongWord; Data: Tdata); override;
+    procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
+    procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
+
+    function GetRawList(fileid: LongWord): TRawList; override;
+    procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer); override;
+    procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord;
+      target: Pointer); override;
+    procedure LoadRawFilePart(fileid, dat_offset: LongWord;
+      offset, size: LongWord; target: Pointer); override;
+    procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
+      offset, size: LongWord; target: Pointer); override;
+  published
+  end;
+
+
+const
+  ODB_None = -1;
+  ODB_Dat  = 0;
+  ODB_ADB  = 1;
+
+var
+  OniDataConnection: TOniData;
+
+function CreateDataConnection(filename: String; backend: Integer): Boolean;
+procedure CloseDataConnection;
+
+
+
+
+implementation
+uses Functions;
+
+
+
+(*
+  Implementation of  TOniData
+*)
+
+function TOniData.GetFileIDByName(Name: String): Integer;
+var
+  files: TStringArray;
+  i:     Integer;
+begin
+  Result := -1;
+  files  := Self.GetFilesList('', Name, False, stIDAsc);
+  if Length(files) > 0 then
+    for i := 0 to High(files) do
+      if Pos(Name, files[i]) = Pos('-', files[i]) + 1 then
+      begin
+        //        if MidStr(files[i],Pos('-',files[i])+1,Length(files[i])-Pos('-',files[i])-5)=name then begin
+        Result := Self.ExtractFileID(files[i]);
+        Break;
+      end;
+end;
+
+
+
+
+function TOniData.ExtractFileID(Name: String): Integer;
+begin
+  if Name[5] = '-' then
+    Result := HexToLong(MidStr(Name, 1, 4))
+  else
+    Result := StrToInt(MidStr(Name, 1, 5));
+end;
+
+
+
+
+function TOniData.GetRawInfo(fileid, dat_offset: LongWord): TRawInfo;
+var
+  i: LongWord;
+  raw_list: TRawList;
+begin
+  raw_list      := Self.GetRawList(fileid);
+  Result.src_id := 0;
+  Result.src_offset := 0;
+  Result.raw_addr := 0;
+  Result.raw_size := 0;
+  for i := 0 to High(raw_list) do
+  begin
+    if raw_list[i].src_offset = dat_offset then
+    begin
+      Result.src_id     := fileid;
+      Result.src_offset := raw_list[i].src_offset;
+      Result.raw_addr   := raw_list[i].raw_addr;
+      Result.raw_size   := raw_list[i].raw_size;
+      Result.loc_sep    := raw_list[i].loc_sep;
+      Break;
+    end;
+  end;
+end;
+
+
+
+
+
+
+
+(*
+================================================================================
+                      Implementation of  TOniDataDat
+*)
+
+constructor TOniDataDat.Create(DatFilename: String; var Result: Boolean);
+const
+  header_ident1_pc: array[0..$13] of Byte =
+    ($1F, $27, $DC, $33, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
+    $14, $00, $10, $00, $08, $00);
+  header_ident1_mac: array[0..$13] of Byte =
+    ($61, $30, $C1, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
+    $14, $00, $10, $00, $08, $00);
+  header_ident1_macbeta: array[0..$13] of Byte =
+    ($81, $11, $8D, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
+    $14, $00, $10, $00, $08, $00);
+  header_ident2: array[0..$F] of Byte =
+    ($99, $CF, $40, $00, $90, $4F, $63, $00, $F4, $55, $5F, $00, $90, $4F, $63, $00);
+var
+  i: LongWord;
+  header_pc, header_mac: Boolean;
+begin
+  FUnloadWhenUnused := True;
+  FDatOpened := False;
+  FRawOpened := False;
+  if not FileExists(DatFilename) then
+  begin
+    ShowMessage('File doesn''t exist!!!');
+    Result := False;
+    Exit;
+  end;
+  FFileName := DatFilename;
+  Fdat_file := TFileStream.Create(FFileName, fmOpenRead);
+  Fdat_file.Read(Fdat_header, SizeOf(Fdat_header));
+  header_pc  := True;
+  header_mac := True;
+  for i := 0 to High(Fdat_header.Ident) do
+  begin
+    FLevelInfo.Ident[i] := Fdat_header.Ident[i];
+    if Fdat_header.Ident[i] <> header_ident1_pc[i] then
+      header_pc := False;
+    if Fdat_header.Ident[i] <> header_ident1_mac[i] then
+      header_mac := False;
+  end;
+  if not (header_pc xor header_mac) then
+  begin
+    Result := False;
+    Exit;
+  end
+  else
+  begin
+    if (header_pc and not header_mac) then
+      Fos_mac := False
+    else
+      Fos_mac := True;
+  end;
+  SetLength(Fdat_filesmap, Fdat_header.Files);
+  SetLength(Fdat_files, Fdat_header.Files);
+  for i := 0 to Fdat_header.Files - 1 do
+    Fdat_file.Read(Fdat_filesmap[i], SizeOf(Fdat_filesmap[i]));
+  for i := 0 to Fdat_header.Files - 1 do
+  begin
+    Fdat_files[i].ID := i;
+    Fdat_files[i].Extension := Fdat_filesmap[i].Extension;
+    Fdat_files[i].Extension := ReverseString(Fdat_files[i].Extension);
+    Fdat_files[i].Size      := Fdat_filesmap[i].FileSize;
+    Fdat_files[i].FileType  := Fdat_filesmap[i].FileType;
+    Fdat_files[i].DatAddr   := Fdat_filesmap[i].DataAddr - 8 + Fdat_header.DataAddr;
+    if (Fdat_filesmap[i].FileType and $01) = 0 then
+    begin
+      Fdat_file.Seek(Fdat_filesmap[i].NameAddr + Fdat_header.NamesAddr, soFromBeginning);
+      SetLength(Fdat_files[i].Name, 100);
+      Fdat_file.Read(Fdat_files[i].Name[1], 100);
+      Fdat_files[i].Name := MidStr(Fdat_files[i].Name, 1 + 4, Pos(
+        #0, Fdat_files[i].Name) - 1 - 4);
+    end
+    else
+    begin
+      Fdat_files[i].Name := '';
+    end;
+    Fdat_files[i].FileName    :=
+      FormatNumber(i, 5, '0') + '-' + Fdat_files[i].Name + '.' + Fdat_files[i].Extension;
+    Fdat_files[i].FileNameHex :=
+      IntToHex(i, 4) + '-' + Fdat_files[i].Name + '.' + Fdat_files[i].Extension;
+  end;
+  Fdat_file.Seek($40 + Fdat_header.Files * $14, soFromBeginning);
+  SetLength(Fdat_namedfilesmap, Fdat_header.NamedFiles);
+  for i := 0 to Fdat_header.NamedFiles - 1 do
+    Fdat_file.Read(Fdat_namedfilesmap[i], SizeOf(Fdat_namedfilesmap[i]));
+
+  Fdat_file.Seek($40 + Fdat_header.Files * $14 + Fdat_header.NamedFiles * $8, soFromBeginning);
+  SetLength(Fdat_extensionsmap, Fdat_header.Extensions);
+  for i := 0 to Fdat_header.Extensions - 1 do
+    Fdat_file.Read(Fdat_extensionsmap[i], SizeOf(Fdat_extensionsmap[i]));
+
+  Fdat_file.Seek(Fdat_files[0].DatAddr + 7, soFromBeginning);
+  Fdat_file.Read(FLevelInfo.LevelNumber, 1);
+  FLevelInfo.LevelNumber := FLevelInfo.LevelNumber div 2;
+
+  Fdat_file.Free;
+
+  Result   := True;
+  FBackend := ODB_Dat;
+end;
+
+
+
+
+procedure TOniDataDat.Close;
+begin
+  if not FUnloadWhenUnused and FDatOpened then
+    Fdat_file.Free;
+  if not FUnloadWhenUnused and FRawOpened then
+    Fraw_file.Free;
+  if not FUnloadWhenUnused and FSepOpened then
+    Fsep_file.Free;
+  Self.Free;
+end;
+
+
+
+
+function TOniDataDat.GetFileInfo(fileid: LongWord): TFileInfo;
+begin
+  if fileid < Self.GetFilesCount then
+    Result    := Fdat_files[fileid]
+  else
+    Result.ID := -1;
+end;
+
+
+
+
+function TOniDataDat.GetFilesList(ext: String; pattern: String;
+  NoEmptyFiles: Boolean; sort: TSortType): TStringArray;
+var
+  i: LongWord;
+  list: TStringList;
+  id, name, extension: String;
+  fields: TStrings;
+
+  procedure getfields;
+  begin
+     fields.CommaText := StringReplace(AnsiQuotedStr(list.Strings[i], '"'), ';', '","', [rfReplaceAll]);
+    if sort in [stIDAsc, stIDDesc] then
+    begin
+      id := fields.Strings[0];
+      name := fields.Strings[1];
+      extension := fields.Strings[2];
+    end;
+    if sort in [stNameAsc, stNameDesc] then
+    begin
+      id := fields.Strings[1];
+      name := fields.Strings[0];
+      extension := fields.Strings[2];
+    end;
+    if sort in [stExtAsc, stExtDesc] then
+    begin
+      id := fields.Strings[1];
+      name := fields.Strings[2];
+      extension := fields.Strings[0];
+    end;
+  end;
+
+begin
+  list := TStringList.Create;
+  list.Sorted := True;
+  for i := 0 to Fdat_header.Files - 1 do
+  begin
+    if ((Length(ext) = 0) or (Pos(Fdat_files[i].Extension, ext) > 0)) and
+      ((Length(pattern) = 0) or
+      (Pos(UpperCase(pattern), UpperCase(Fdat_files[i].Name)) > 0)) then
+    begin
+      if (NoEmptyFiles = False) or ((Fdat_files[i].FileType and $02) = 0) then
+      begin
+        if AppSettings.FilenumbersAsHex then
+          id := IntToHex(Fdat_files[i].ID, 4)
+        else
+          id := FormatNumber(Fdat_files[i].ID, 5, '0');
+        name := Fdat_files[i].Name;
+        extension := Fdat_files[i].Extension;
+
+        case sort of
+          stIDAsc, stIDDesc:     list.Add(id + ';' + name + ';' + extension);
+          stNameAsc, stNameDesc: list.Add(name + ';' + id + ';' + extension);
+          stExtAsc, stExtDesc:   list.Add(extension + ';' + id + ';' + name);
+        end;
+      end;
+    end;
+  end;
+  SetLength(Result, list.Count);
+  if Length(Result) > 0 then
+  begin
+    fields := TStringList.Create;
+    if sort in [stIDAsc, stNameAsc, stExtAsc] then
+      for i := 0 to list.Count - 1 do
+      begin
+        getfields;
+        Result[i] := id + '-' + name + '.' + extension;
+      end
+    else
+      for i := list.Count - 1 downto 0 do
+      begin
+        getfields;
+        Result[list.Count - i - 1] := id + '-' + name + '.' + extension;
+      end;
+    fields.Free;
+  end;
+  list.Free;
+end;
+
+
+
+
+function TOniDataDat.GetFilesCount: LongWord;
+begin
+  Result := Fdat_header.Files;
+end;
+
+
+
+
+function TOniDataDat.GetExtensionsList: TStringArray;
+var
+  i: LongWord;
+begin
+  SetLength(Result, Fdat_header.Extensions);
+  for i := 0 to Fdat_header.Extensions - 1 do
+  begin
+    with Fdat_extensionsmap[i] do
+    begin
+      Result[i] := Extension[3] + Extension[2] + Extension[1] + Extension[0] +
+        ' (' + IntToStr(ExtCount) + ')';
+    end;
+  end;
+end;
+
+
+
+
+function TOniDataDat.GetExtendedExtensionsList: TExtensionsMap;
+var
+  i: LongWord;
+begin
+  SetLength(Result, Fdat_header.Extensions);
+  for i := 0 to Fdat_header.Extensions - 1 do
+  begin
+    Result[i] := Fdat_extensionsmap[i];
+  end;
+end;
+
+
+
+
+function TOniDataDat.LoadDatFile(fileid: LongWord): Tdata;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    if FUnloadWhenUnused or not FDatOpened then
+      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
+    Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
+    SetLength(Result, Fdat_files[fileid].Size);
+    Fdat_file.Read(Result[0], Fdat_files[fileid].Size);
+    if UnloadWhenUnused then
+      Fdat_file.Free
+    else
+      FDatOpened := True;
+  end;
+end;
+
+
+
+
+procedure TOniDataDat.UpdateDatFile(fileid: LongWord; Data: Tdata);
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    if FUnloadWhenUnused or not FDatOpened then
+      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
+    Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
+    Fdat_file.Write(Data[0], Length(Data));
+    if UnloadWhenUnused then
+      Fdat_file.Free
+    else
+      FDatOpened := True;
+  end;
+end;
+
+
+
+
+procedure TOniDataDat.LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    if FUnloadWhenUnused or not FDatOpened then
+      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
+    Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
+    Fdat_file.Read(target^, size);
+    if UnloadWhenUnused then
+      Fdat_file.Free
+    else
+      FDatOpened := True;
+  end;
+end;
+
+
+
+
+procedure TOniDataDat.UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    if FUnloadWhenUnused or not FDatOpened then
+      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
+    Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
+    Fdat_file.Write(target^, size);
+    if UnloadWhenUnused then
+      Fdat_file.Free
+    else
+      FDatOpened := True;
+  end;
+end;
+
+
+
+
+function TOniDataDat.GetRawList(fileid: LongWord): TRawList;
+var
+  i: LongWord;
+begin
+  SetLength(Result, 0);
+  for i := 0 to High(RawListHandlers) do
+    if UpperCase(RawListHandlers[i].Ext) = UpperCase(Fdat_files[fileid].extension) then
+      if RawListHandlers[i].needed then
+      begin
+        Result := RawListHandlers[i].Handler(fileid);
+        Break;
+      end
+      else
+        Break;
+end;
+
+
+
+
+procedure TOniDataDat.LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord;
+  target: Pointer);
+begin
+  if not loc_sep then
+  begin
+    if FUnloadWhenUnused or not FRawOpened then
+      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
+        fmOpenReadWrite);
+    if raw_addr <= Fraw_file.Size then
+    begin
+      Fraw_file.Seek(raw_addr, soFromBeginning);
+      Fraw_file.Read(target^, size);
+    end;
+    if UnloadWhenUnused then
+      Fraw_file.Free
+    else
+      FRawOpened := True;
+  end
+  else
+  begin
+    if FUnloadWhenUnused or not FSepOpened then
+      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
+        fmOpenReadWrite);
+    if raw_addr <= Fsep_file.Size then
+    begin
+      Fsep_file.Seek(raw_addr, soFromBeginning);
+      Fsep_file.Read(target^, size);
+    end;
+    if UnloadWhenUnused then
+      Fsep_file.Free
+    else
+      FSepOpened := True;
+  end;
+end;
+
+
+
+
+procedure TOniDataDat.LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
+var
+  raw_info: TRawInfo;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    raw_info := Self.GetRawInfo(fileid, dat_offset);
+    if not raw_info.loc_sep then
+    begin
+      if FUnloadWhenUnused or not FRawOpened then
+        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
+          fmOpenReadWrite);
+      Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
+      Fraw_file.Read(target^, raw_info.raw_size);
+      if UnloadWhenUnused then
+        Fraw_file.Free
+      else
+        FRawOpened := True;
+    end
+    else
+    begin
+      if FUnloadWhenUnused or not FSepOpened then
+        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
+          fmOpenReadWrite);
+      Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
+      Fsep_file.Read(target^, raw_info.raw_size);
+      if UnloadWhenUnused then
+        Fsep_file.Free
+      else
+        FSepOpened := True;
+    end;
+  end;
+end;
+
+
+
+
+procedure TOniDataDat.UpdateRawFile(fileid, dat_offset: LongWord;
+  size: LongWord; target: Pointer);
+var
+  raw_info: TRawInfo;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    raw_info := Self.GetRawInfo(fileid, dat_offset);
+    if not raw_info.loc_sep then
+    begin
+      if FUnloadWhenUnused or not FRawOpened then
+        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
+          fmOpenReadWrite);
+      Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
+      Fraw_file.Write(target^, raw_info.raw_size);
+      if UnloadWhenUnused then
+        Fraw_file.Free
+      else
+        FRawOpened := True;
+    end
+    else
+    begin
+      if FUnloadWhenUnused or not FSepOpened then
+        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
+          fmOpenReadWrite);
+      Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
+      Fsep_file.Write(target^, raw_info.raw_size);
+      if UnloadWhenUnused then
+        Fsep_file.Free
+      else
+        FSepOpened := True;
+    end;
+  end;
+end;
+
+
+
+
+procedure TOniDataDat.LoadRawFilePart(fileid, dat_offset: LongWord;
+  offset, size: LongWord; target: Pointer);
+var
+  raw_info: TRawInfo;
+  Data:     Tdata;
+  mem:      TMemoryStream;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    raw_info := Self.GetRawInfo(fileid, dat_offset);
+    SetLength(Data, raw_info.raw_size);
+    Self.LoadRawFile(fileid, dat_offset, @Data[0]);
+    mem := TMemoryStream.Create;
+    mem.Write(Data[offset], size);
+    mem.Read(target^, size);
+    mem.Free;
+  end;
+end;
+
+
+
+
+procedure TOniDataDat.UpdateRawFilePart(fileid, dat_offset: LongWord;
+  offset, size: LongWord; target: Pointer);
+var
+  raw_info: TRawInfo;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    raw_info := Self.GetRawInfo(fileid, dat_offset);
+    if not raw_info.loc_sep then
+    begin
+      if FUnloadWhenUnused or not FRawOpened then
+        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
+          fmOpenReadWrite);
+      Fraw_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
+      Fraw_file.Write(target^, raw_info.raw_size);
+      if UnloadWhenUnused then
+        Fraw_file.Free
+      else
+        FRawOpened := True;
+    end
+    else
+    begin
+      if FUnloadWhenUnused or not FSepOpened then
+        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
+          fmOpenReadWrite);
+      Fsep_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
+      Fsep_file.Write(target^, raw_info.raw_size);
+      if UnloadWhenUnused then
+        Fsep_file.Free
+      else
+        FSepOpened := True;
+    end;
+  end;
+end;
+
+
+
+
+function TOniDataDat.AppendRawFile(loc_sep: Boolean; size: LongWord;
+  target: Pointer): LongWord; //Returns new Address
+begin
+  if not loc_sep then
+  begin
+    if FUnloadWhenUnused or not FRawOpened then
+      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
+        fmOpenReadWrite);
+    Result := Fraw_file.Size;
+    Fraw_file.Seek(0, soFromEnd);
+    Fraw_file.Write(target^, size);
+    if UnloadWhenUnused then
+      Fraw_file.Free
+    else
+      FRawOpened := True;
+  end
+  else
+  begin
+    if FUnloadWhenUnused or not FSepOpened then
+      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
+        fmOpenReadWrite);
+    Result := Fsep_file.Size;
+    Fsep_file.Seek(0, soFromEnd);
+    Fsep_file.Write(target^, size);
+    if UnloadWhenUnused then
+      Fsep_file.Free
+    else
+      FSepOpened := True;
+  end;
+end;
+
+
+
+
+
+
+
+
+
+
+
+(*
+================================================================================
+                     Implementation of  TOniDataADB
+*)
+
+constructor TOniDataADB.Create(OLDBFilename: String; var Result: Boolean);
+var
+  i, j:  Byte;
+  temps: String;
+begin
+  if not FileExists(OLDBFilename) then
+  begin
+    ShowMessage('File doesn''t exist!!!');
+    Result := False;
+    Exit;
+  end;
+  FFileName := OLDBFilename;
+  FDatabase := TABSDatabase.Create(nil);
+  FDatabase.DatabaseName := 'OLDBcon';
+  FDatabase.DatabaseFileName := OLDBFilename;
+  FDatabase.Open;
+  FQuery := TABSQuery.Create(FDatabase);
+  FQuery.DatabaseName := 'OLDBcon';
+  FQuery.SQL.Text := 'SELECT [name],[value] FROM globals ORDER BY [name] ASC';
+  FQuery.Open;
+  FQuery.First;
+  repeat
+    if FQuery.FieldByName('name').AsString = 'dbversion' then
+    begin
+      if FQuery.FieldByName('value').AsString <> DBversion then
+      begin
+        ShowMessage('Database-file ' + #13 + #10 +
+          '"' + OLDBFilename + '"' + #13 + #10 +
+          'has wrong version. (Required: ' + DBversion + '; found: ' +
+          FQuery.FieldByName('value').AsString + ')');
+        FQuery.Close;
+        Result := False;
+        Exit;
+      end;
+    end;
+    if FQuery.FieldByName('name').AsString = 'lvl' then
+    begin
+      FLevelInfo.LevelNumber := StrToInt(FQuery.FieldByName('value').AsString);
+    end;
+    if FQuery.FieldByName('name').AsString = 'ident' then
+    begin
+      temps := FQuery.FieldByName('value').AsString;
+      for i := 0 to High(FLevelInfo.Ident) do
+      begin
+        j := i * 2 + 1;
+        case temps[j] of
+          '0'..'9':
+            FLevelInfo.Ident[i] := Ord(temps[j]) - 48;
+          'A'..'F':
+            FLevelInfo.Ident[i] := Ord(temps[j]) - 55;
+        end;
+        FLevelInfo.Ident[i] := FLevelInfo.Ident[i] * 16;
+        case temps[j + 1] of
+          '0'..'9':
+            FLevelInfo.Ident[i] := FLevelInfo.Ident[i] + Ord(temps[j + 1]) - 48;
+          'A'..'F':
+            FLevelInfo.Ident[i] := FLevelInfo.Ident[i] + Ord(temps[j + 1]) - 55;
+        end;
+      end;
+    end;
+    if FQuery.FieldByName('name').AsString = 'ident' then
+    begin
+      temps   := FQuery.FieldByName('value').AsString;
+      Fos_mac := temps = 'MAC';
+    end;
+    FQuery.Next;
+  until FQuery.EOF;
+  FQuery.Close;
+
+  UpdateListCache;
+
+  Result   := True;
+  FBackend := ODB_ADB;
+end;
+
+
+
+
+procedure TOniDataADB.Close;
+begin
+  FDatabase.Close;
+  FDatabase.Free;
+  Self.Free;
+end;
+
+
+
+procedure TOniDataADB.UpdateListCache;
+var
+  i:     LongWord;
+  temps: String;
+begin
+  FQuery.SQL.Text := 'SELECT id,name,extension,[size],contenttype FROM datfiles ORDER BY id ASC;';
+  FQuery.Open;
+  if FQuery.RecordCount > 0 then
+  begin
+    FQuery.First;
+    SetLength(Fdat_files, FQuery.RecordCount);
+    i := 0;
+    repeat
+      Fdat_files[i].ID := FQuery.FieldByName('id').AsInteger;
+      Fdat_files[i].Name := FQuery.FieldByName('name').AsString;
+      Fdat_files[i].Extension := FQuery.FieldByName('extension').AsString;
+      Fdat_files[i].FileName := FormatNumber(Fdat_files[i].ID, 5, '0') + '-' +
+          Fdat_files[i].Name + '.' + Fdat_files[0].Extension;
+      Fdat_files[i].FileNameHex := IntToHex(Fdat_files[i].ID, 4) + '-' +
+          Fdat_files[i].Name + '.' + Fdat_files[0].Extension;
+      Fdat_files[i].Size := FQuery.FieldByName('size').AsInteger;
+      Fdat_files[i].FileType := HexToLong(FQuery.FieldByName('contenttype').AsString);
+      Fdat_files[i].DatAddr := 0;
+      Fdat_files[i].opened := False;
+      Inc(i);
+      FQuery.Next;
+    until FQuery.EOF;
+  end;
+  FQuery.Close;
+
+  SetLength(Fdat_extensionsmap, 0);
+  FQuery.SQL.Text :=
+    'SELECT extension,count(extension) AS x FROM datfiles GROUP BY extension ORDER BY extension ASC;';
+  FQuery.Open;
+  if FQuery.RecordCount > 0 then
+  begin
+    SetLength(Fdat_extensionsmap, FQuery.RecordCount);
+    i := 0;
+    repeat
+      temps := FQuery.FieldByName('extension').AsString[1];
+      Fdat_extensionsmap[i].Extension[3] := temps[1];
+      Fdat_extensionsmap[i].Extension[2] := temps[2];
+      Fdat_extensionsmap[i].Extension[1] := temps[3];
+      Fdat_extensionsmap[i].Extension[0] := temps[4];
+      Fdat_extensionsmap[i].ExtCount := FQuery.FieldByName('x').AsInteger;
+      Inc(i);
+      FQuery.Next;
+    until FQuery.EOF;
+  end;
+  FQuery.Close;
+end;
+
+
+function TOniDataADB.GetFileInfo(fileid: LongWord): TFileInfo;
+var
+  i: Integer;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    for i := 0 to High(Fdat_files) do
+      if Fdat_files[i].ID = fileid then
+        Break;
+    if i < Length(Fdat_files) then
+      Result := Fdat_files[i]
+    else
+      Result.ID := -1;
+  end
+  else
+  begin
+    Result.ID := -1;
+  end;
+end;
+
+
+
+
+function TOniDataADB.GetFilesList(ext: String; pattern: String;
+  NoEmptyFiles: Boolean; sort: TSortType): TStringArray;
+var
+  i: LongWord;
+  list: TStringList;
+  id, name, extension: String;
+  fields: TStrings;
+
+  procedure getfields;
+  begin
+     fields.CommaText := StringReplace(AnsiQuotedStr(list.Strings[i], '"'), ';', '","', [rfReplaceAll]);
+    if sort in [stIDAsc, stIDDesc] then
+    begin
+      id := fields.Strings[0];
+      name := fields.Strings[1];
+      extension := fields.Strings[2];
+    end;
+    if sort in [stNameAsc, stNameDesc] then
+    begin
+      id := fields.Strings[1];
+      name := fields.Strings[0];
+      extension := fields.Strings[2];
+    end;
+    if sort in [stExtAsc, stExtDesc] then
+    begin
+      id := fields.Strings[1];
+      name := fields.Strings[2];
+      extension := fields.Strings[0];
+    end;
+  end;
+
+begin
+  list := TStringList.Create;
+  list.Sorted := True;
+  for i := 0 to High(Fdat_files) do
+  begin
+    if ((Length(ext) = 0) or (Pos(Fdat_files[i].Extension, ext) > 0)) and
+      ((Length(pattern) = 0) or
+      (Pos(UpperCase(pattern), UpperCase(Fdat_files[i].Name)) > 0)) then
+    begin
+      if (NoEmptyFiles = False) or ((Fdat_files[i].FileType and $02) = 0) then
+      begin
+        if AppSettings.FilenumbersAsHex then
+          id := IntToHex(Fdat_files[i].ID, 4)
+        else
+          id := FormatNumber(Fdat_files[i].ID, 5, '0');
+        name := Fdat_files[i].Name;
+        extension := Fdat_files[i].Extension;
+
+        case sort of
+          stIDAsc, stIDDesc:     list.Add(id + ';' + name + ';' + extension);
+          stNameAsc, stNameDesc: list.Add(name + ';' + id + ';' + extension);
+          stExtAsc, stExtDesc:   list.Add(extension + ';' + id + ';' + name);
+        end;
+      end;
+    end;
+  end;
+  SetLength(Result, list.Count);
+  fields := TStringList.Create;
+  if sort in [stIDAsc, stNameAsc, stExtAsc] then
+    for i := 0 to list.Count - 1 do
+    begin
+      getfields;
+      Result[i] := id + '-' + name + '.' + extension;
+    end
+  else
+    for i := list.Count - 1 downto 0 do
+    begin
+      getfields;
+      Result[list.Count - i - 1] := id + '-' + name + '.' + extension;
+    end;
+  list.Free;
+  fields.Free;
+end;
+
+
+
+
+function TOniDataADB.GetFilesCount: LongWord;
+begin
+  Result := Length(Fdat_files);
+end;
+
+
+
+
+function TOniDataADB.GetExtensionsList: TStringArray;
+var
+  i: LongWord;
+begin
+  SetLength(Result, Length(Fdat_extensionsmap));
+  for i := 0 to High(Result) do
+  begin
+    with Fdat_extensionsmap[i] do
+    begin
+      Result[i] := Extension[3] + Extension[2] + Extension[1] + Extension[0] +
+        ' (' + IntToStr(ExtCount) + ')';
+    end;
+  end;
+end;
+
+
+
+
+function TOniDataADB.GetExtendedExtensionsList: TExtensionsMap;
+var
+  i, j:  LongWord;
+  temps: String;
+  Data:  Tdata;
+begin
+  SetLength(Result, 0);
+  FQuery.SQL.Text := 'SELECT ext,ident FROM extlist ORDER BY ext ASC;';
+  FQuery.Open;
+  if FQuery.RecordCount > 0 then
+  begin
+    SetLength(Result, FQuery.RecordCount);
+    i := 0;
+    repeat
+      temps := FQuery.FieldByName('ext').AsString;
+      for j := 0 to 3 do
+        Result[i].Extension[j] := temps[4 - j];
+      Data := DecodeHexString(FQuery.FieldByName('ident').AsString);
+      for j := 0 to 7 do
+        Result[i].Ident[j] := Data[j];
+      Inc(i);
+      FQuery.Next;
+    until FQuery.EOF;
+  end;
+  FQuery.Close;
+end;
+
+
+
+
+function TOniDataADB.GetNamedFilesMap: TNamedFilesMap;
+var
+  i:     LongWord;
+  temp:  Integer;
+  temps: String;
+  temparray: array of record
+    id: Integer;
+    fullname: String[50];
+  end;
+begin
+  SetLength(temparray, 0);
+  FQuery.SQL.Text :=
+    'SELECT id,(extension+name) AS xname FROM datfiles WHERE Length(name)>0 ORDER BY extension,name ASC;';
+  FQuery.Open;
+  if FQuery.RecordCount > 0 then
+  begin
+    repeat
+      temp  := FQuery.FieldByName('id').AsInteger;
+      temps := FQuery.FieldByName('xname').AsString;
+
+      SetLength(temparray, Length(temparray) + 1);
+      if Length(temparray) > 1 then
+      begin
+        for i := High(temparray) - 1 downto 0 do
+        begin
+          if StringSmaller(temps, temparray[i].fullname) then
+          begin
+            temparray[i + 1] := temparray[i];
+            if i = 0 then
+            begin
+              temparray[i].id := temp;
+              temparray[i].fullname := temps;
+            end;
+          end
+          else
+          begin
+            temparray[i + 1].id := temp;
+            temparray[i + 1].fullname := temps;
+            Break;
+          end;
+        end;
+      end
+      else
+      begin
+        temparray[0].id := temp;
+        temparray[0].fullname := temps;
+      end;
+      FQuery.Next;
+    until FQuery.EOF;
+  end;
+  FQuery.Close;
+  SetLength(Result, Length(temparray));
+  for i := 0 to High(temparray) do
+  begin
+    Result[i].FileNumber := temparray[i].id;
+    Result[i].blubb      := 0;
+  end;
+end;
+
+
+
+
+function TOniDataADB.LoadDatFile(fileid: LongWord): Tdata;
+var
+  mem: TStream;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    FQuery.SQL.Text := 'SELECT data FROM datfiles WHERE id=' + IntToStr(fileid) + ';';
+    FQuery.Open;
+    if FQuery.RecordCount > 0 then
+    begin
+      mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
+      SetLength(Result, mem.Size);
+      mem.Seek(0, soFromBeginning);
+      mem.Read(Result[0], mem.Size);
+      mem.Free;
+    end;
+    FQuery.Close;
+  end;
+end;
+
+
+
+
+procedure TOniDataADB.UpdateDatFile(fileid: LongWord; Data: Tdata);
+var
+  MimeCoder: TStringFormat_MIME64;
+  mem: TMemoryStream;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    mimecoder := TStringFormat_MIME64.Create;
+    mem := TMemoryStream.Create;
+    mem.Write(Data[0], Length(Data));
+    mem.Seek(0, soFromBeginning);
+    FQuery.SQL.Text := 'UPDATE datfiles SET data=MimeToBin("' +
+      MimeCoder.StrTo(mem.Memory, mem.Size) + '"), size=' + IntToStr(mem.Size) +
+      ' WHERE id=' + IntToStr(fileid) + ';';
+    FQuery.ExecSQL;
+    mem.Free;
+    mimecoder.Free;
+  end;
+  UpdateListCache;
+end;
+
+
+
+
+procedure TOniDataADB.LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
+var
+  mem: TStream;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    FQuery.SQL.Text := 'SELECT data FROM datfiles WHERE id=' + IntToStr(fileid) + ';';
+    FQuery.Open;
+    if FQuery.RecordCount > 0 then
+    begin
+      mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
+      mem.Seek(offset, soFromBeginning);
+      mem.Read(target^, size);
+      mem.Free;
+    end;
+    FQuery.Close;
+  end;
+end;
+
+
+
+
+procedure TOniDataADB.UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
+var
+  MimeCoder: TStringFormat_MIME64;
+  mem:  TMemoryStream;
+  Data: Tdata;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    Data := Self.LoadDatFile(fileid);
+    mimecoder := TStringFormat_MIME64.Create;
+    mem := TMemoryStream.Create;
+    mem.Write(Data[0], Length(Data));
+    mem.Seek(offset, soFromBeginning);
+    mem.Write(target^, size);
+    mem.Seek(0, soFromBeginning);
+    FQuery.SQL.Text := 'UPDATE datfiles SET data=MimeToBin("' +
+      MimeCoder.StrTo(mem.Memory, mem.Size) + '") WHERE id=' + IntToStr(fileid) + ';';
+    FQuery.ExecSQL;
+    mem.Free;
+    mimecoder.Free;
+  end;
+end;
+
+
+
+
+function TOniDataADB.GetRawList(fileid: LongWord): TRawList;
+var
+  i: LongWord;
+begin
+  SetLength(Result, 0);
+  FQuery.SQL.Text := 'SELECT [src_link_offset],[size],[sep] FROM rawmap WHERE [src_id]=' +
+    IntToStr(fileid) + ' ORDER BY src_link_offset ASC;';
+  FQuery.Open;
+  if FQuery.RecordCount > 0 then
+  begin
+    FQuery.First;
+    SetLength(Result, FQuery.RecordCount);
+    i := 0;
+    repeat
+      Result[i].src_id     := fileid;
+      Result[i].src_offset := FQuery.FieldByName('src_link_offset').AsInteger;
+      Result[i].raw_addr   := 0;
+      Result[i].raw_size   := FQuery.FieldByName('size').AsInteger;
+      Result[i].loc_sep    := FQuery.FieldByName('sep').AsBoolean;
+      Inc(i);
+      FQuery.Next;
+    until FQuery.EOF;
+  end;
+  FQuery.Close;
+end;
+
+
+
+
+procedure TOniDataADB.LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
+var
+  mem: TStream;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    FQuery.SQL.Text := 'SELECT data FROM rawmap WHERE (src_id=' +
+      IntToStr(fileid) + ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
+    FQuery.Open;
+    if FQuery.RecordCount > 0 then
+    begin
+      mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
+      mem.Seek(0, soFromBeginning);
+      mem.Read(target^, mem.size);
+      mem.Free;
+    end;
+    FQuery.Close;
+  end;
+end;
+
+
+
+
+procedure TOniDataADB.UpdateRawFile(fileid, dat_offset: LongWord;
+  size: LongWord; target: Pointer);
+var
+  MimeCoder: TStringFormat_MIME64;
+  mem: TMemoryStream;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    mimecoder := TStringFormat_MIME64.Create;
+    mem := TMemoryStream.Create;
+    mem.Write(target^, size);
+    mem.Seek(0, soFromBeginning);
+    FQuery.SQL.Text := 'UPDATE rawmap SET data=MimeToBin("' + MimeCoder.StrTo(
+      mem.Memory, mem.Size) + '") WHERE (src_id=' + IntToStr(fileid) +
+      ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
+    FQuery.ExecSQL;
+    mem.Free;
+    mimecoder.Free;
+  end;
+end;
+
+
+
+
+procedure TOniDataADB.LoadRawFilePart(fileid, dat_offset: LongWord;
+  offset, size: LongWord; target: Pointer);
+var
+  Data: Tdata;
+  mem:  TMemoryStream;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    SetLength(Data, Self.GetRawInfo(fileid, dat_offset).raw_size);
+    Self.LoadRawFile(fileid, dat_offset, @Data[0]);
+    mem := TMemoryStream.Create;
+    mem.Write(Data[offset], size);
+    mem.Read(target^, size);
+    mem.Free;
+  end;
+end;
+
+
+
+
+procedure TOniDataADB.UpdateRawFilePart(fileid, dat_offset: LongWord;
+  offset, size: LongWord; target: Pointer);
+var
+  MimeCoder: TStringFormat_MIME64;
+  mem:  TMemoryStream;
+  Data: Tdata;
+begin
+  if fileid < Self.GetFilesCount then
+  begin
+    SetLength(Data, Self.GetRawInfo(fileid, offset).raw_size);
+    Self.LoadRawFile(fileid, offset, @Data[0]);
+    mimecoder := TStringFormat_MIME64.Create;
+    mem := TMemoryStream.Create;
+    mem.Write(Data[0], Length(Data));
+    mem.Seek(offset, soFromBeginning);
+    mem.Write(target^, size);
+    mem.Seek(0, soFromBeginning);
+    FQuery.SQL.Text := 'UPDATE rawmap SET data=MimeToBin("' + MimeCoder.StrTo(
+      mem.Memory, mem.Size) + '") WHERE (src_id=' + IntToStr(fileid) +
+      ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
+    FQuery.ExecSQL;
+    mem.Free;
+    mimecoder.Free;
+  end;
+end;
+
+
+
+
+
+
+
+
+
+
+
+function CreateDataConnection(filename: String; backend: Integer): Boolean;
+var
+  answer: Boolean;
+begin
+  if Assigned(OniDataConnection) then
+  begin
+    OniDataConnection.Close;
+    OniDataConnection.Free;
+    OniDataConnection := nil;
+  end;
+  case backend of
+    ODB_Dat:
+      OniDataConnection := TOniDataDat.Create(filename, answer);
+    ODB_ADB:
+      OniDataConnection := TOniDataADB.Create(filename, answer);
+    else
+      ShowMessage('Unknown Backend');
+      Result := False;
+      Exit;
+  end;
+
+  if answer then
+  begin
+    //      ShowMessage('file loaded');
+    //      ShowMessage('Files: '+IntToStr(OniDataConnection.GetFilesCount));
+    Result := True;
+  end
+  else
+  begin
+    ShowMessage('File not loaded');
+    OniDataConnection.Close;
+    OniDataConnection.Free;
+    Result := False;
+  end;
+end;
+
+
+
+
+procedure CloseDataConnection;
+begin
+  if Assigned(OniDataConnection) then
+  begin
+    OniDataConnection.Close;
+    OniDataConnection := nil;
+  end;
+end;
+
+end.
Index: /oup/releases/0.33a/Code/OniImgClass.pas
===================================================================
--- /oup/releases/0.33a/Code/OniImgClass.pas	(revision 76)
+++ /oup/releases/0.33a/Code/OniImgClass.pas	(revision 76)
@@ -0,0 +1,827 @@
+unit OniImgClass;
+
+interface
+
+uses Math, Dialogs, Types, SysUtils, Classes, Data, OniDataClass;
+
+type
+  TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32);
+
+type
+  TOniImage = class
+  private
+    FLoaded:    Boolean;
+    FDataType:  TImgDataType;
+    FData:      Tdata;
+    FWidth, FHeight: Word;
+    FDepth:     Byte;
+    FStoreType: Byte;
+
+    function ResizeImage(oldx, oldy: LongWord; img: Tdata): Tdata;
+    procedure RevertImage;
+    procedure DecodeImage;
+    procedure DecompressImage;
+  protected
+  public
+    property Loaded: Boolean Read FLoaded Write FLoaded;
+    property DataType: TImgDataType Read FDataType Write FDataType;
+    property Width: Word Read FWidth Write FWidth;
+    property Height: Word Read FHeight Write FHeight;
+    property Depth: Byte Read FDepth Write FDepth;
+    property StoreType: Byte Read FStoreType Write FStoreType;
+    property Data: Tdata Read FData Write FData;
+
+    constructor Create;
+    function Load(fileid: LongWord): Boolean;
+    function LoadFromPSpc(fileid: LongWord): Boolean;
+    function LoadFromTXMP(fileid: LongWord): Boolean;
+    function LoadFromTXMB(fileid: LongWord): Boolean;
+    function GetImageDataSize(fading: Boolean): LongWord;
+
+    function GetAsData: Tdata;
+    function GetAs32bit: Tdata;
+    function GetAsBMP: Tdata;
+    function LoadFromBMP(filename: String): Boolean;
+    function WriteToBMP(filename: String): Boolean;
+    function GetMipMappedImage(var faded: Tdata): Boolean;
+  published
+  end;
+
+
+implementation
+
+uses Functions;
+
+
+
+
+constructor TOniImage.Create;
+begin
+  Self.FLoaded   := False;
+  Self.FDataType := [];
+  SetLength(Self.FData, 0);
+  Self.FWidth     := 0;
+  Self.FHeight    := 0;
+  Self.FDepth     := 0;
+  Self.FStoreType := 0;
+end;
+
+
+
+
+function TOniImage.ResizeImage(oldx, oldy: LongWord; img: Tdata): Tdata;
+var
+  i, j: LongWord;
+  col, row, row_orig: LongWord;
+begin
+  SetLength(Result, (oldx div 2) * (oldy div 2) * (Self.FDepth div 8));
+  row_orig := 0;
+  row      := 0;
+  col      := 0;
+  for i := 0 to (oldx * oldy) - 1 do
+  begin
+    if ((i mod oldx) = 0) and (i > 0) then
+    begin
+      Inc(row_orig);
+      if (row_orig mod 2) = 0 then
+      begin
+        Inc(row);
+        col := 0;
+      end;
+    end;
+    if (row_orig mod 2) = 0 then
+    begin
+      if (i mod 2) = 0 then
+      begin
+        for j := 0 to (Self.FDepth div 8) - 1 do
+          Result[((row * (oldx div 2)) + col) * (Self.FDepth div 8) + j] :=
+            img[(i * (Self.FDepth div 8)) + j];
+        Inc(col);
+      end;
+    end;
+  end;
+end;
+
+
+
+
+procedure TOniImage.RevertImage;
+var
+  x, y, i: LongWord;
+  tempd:   Tdata;
+begin
+  SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
+  for y := 0 to Self.FHeight - 1 do
+    for x := 0 to Self.FWidth - 1 do
+      for i := 0 to (Self.FDepth div 8) - 1 do
+        tempd[((Self.FWidth * (Self.FHeight - 1 - y) + x) * (Self.FDepth div 8)) + i] :=
+          Self.FData[(Self.FWidth * y + x) * (Self.FDepth div 8) + i];
+  for x := 0 to High(tempd) do
+    Self.FData[x] := tempd[x];
+  if DT_OniReverted in Self.FDataType then
+    Self.FDataType := Self.FDataType - [DT_OniReverted]
+  else
+    Self.FDataType := Self.FDataType + [DT_OniReverted];
+end;
+
+
+
+
+procedure TOniImage.DecodeImage;
+var
+  x, y:  LongWord;
+  tempd: Tdata;
+begin
+  if not (DT_Decoded32 in Self.FDataType) then
+  begin
+    SetLength(tempd, Self.FWidth * Self.FHeight * 4);
+    case Self.FStoreType of
+      0:
+      begin
+        for y := 0 to Self.FHeight - 1 do
+        begin
+          for x := 0 to Self.FWidth - 1 do
+          begin
+            tempd[((Self.FWidth * y + x) * 4) + 0] :=
+              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
+              $000F) / $000F * 255);
+            tempd[((Self.FWidth * y + x) * 4) + 1] :=
+              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
+              $00F0) / $00F0 * 255);
+            tempd[((Self.FWidth * y + x) * 4) + 2] :=
+              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
+              $0F00) / $0F00 * 255);
+            tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
+          end;
+        end;
+      end;
+      1, 2:
+      begin
+        for y := 0 to Self.FHeight - 1 do
+        begin
+          for x := 0 to Self.FWidth - 1 do
+          begin
+            tempd[((Self.FWidth * y + x) * 4) + 0] :=
+              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
+              $001F) / $001F * 255);
+            tempd[((Self.FWidth * y + x) * 4) + 1] :=
+              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
+              $03E0) / $03E0 * 255);
+            tempd[((Self.FWidth * y + x) * 4) + 2] :=
+              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
+              $7C00) / $7C00 * 255);
+            tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
+          end;
+        end;
+      end;
+      9:
+      begin
+        DecompressImage;
+      end;
+    end;
+    Self.FDepth := 32;
+    if (Self.FStoreType <> 9) and (Self.FStoreType <> 8) then
+    begin
+      SetLength(Self.FData, Length(tempd));
+      for x := 0 to High(tempd) do
+        Self.FData[x] := tempd[x];
+    end;
+    Self.FStoreType := 8;
+    if DT_Oni in Self.FDataType then
+      Self.FDataType := Self.FDataType - [DT_Oni];
+    Self.FDataType := Self.FDataType + [DT_Decoded32];
+  end;
+  if DT_OniReverted in Self.FDataType then
+    Self.RevertImage;
+end;
+
+
+
+
+procedure TOniImage.DecompressImage;
+type
+  Tcolor = record
+    RGBb: Byte;
+    RGBg: Byte;
+    RGBr: Byte;
+    RGBa: Byte;
+  end;
+var
+  i, j, x, y: LongWord;
+  color:      array[1..4] of Tcolor;
+  pixel:      array[1..16] of Byte;
+  tempd:      Tdata;
+begin
+  x := 0;
+  y := 0;
+  SetLength(tempd, Self.FWidth * Self.FHeight * 4);
+  for i := 0 to ((Self.FWidth * Self.FHeight) div 16) - 1 do
+  begin
+    Color[1].RGBb := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $001F) /
+      $001F * 255);
+    Color[1].RGBg := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $07E0) /
+      $07E0 * 255);
+    Color[1].RGBr := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $F800) /
+      $F800 * 255);
+    Color[1].RGBa := 255;
+    Color[2].RGBb := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $001F) /
+      $001F * 255);
+    Color[2].RGBg := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $07E0) /
+      $07E0 * 255);
+    Color[2].RGBr := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $F800) /
+      $F800 * 255);
+    Color[2].RGBa := 255;
+    Color[3].RGBb := Round(Color[1].RGBb / 3 * 2 + Color[2].RGBb / 3);
+    Color[3].RGBg := Round(Color[1].RGBg / 3 * 2 + Color[2].RGBg / 3);
+    Color[3].RGBr := Round(Color[1].RGBr / 3 * 2 + Color[2].RGBr / 3);
+    Color[3].RGBa := 255;
+    Color[4].RGBb := Round(Color[1].RGBb / 3 + Color[2].RGBb / 3 * 2);
+    Color[4].RGBg := Round(Color[1].RGBg / 3 + Color[2].RGBg / 3 * 2);
+    Color[4].RGBr := Round(Color[1].RGBr / 3 + Color[2].RGBr / 3 * 2);
+    Color[4].RGBa := 255;
+    Pixel[1]      := Round((Self.FData[(i * 8) + 4] and $C0) / $40 + 1);
+    Pixel[2]      := Round((Self.FData[(i * 8) + 4] and $30) / $10 + 1);
+    Pixel[3]      := Round((Self.FData[(i * 8) + 4] and $0C) / $04 + 1);
+    Pixel[4]      := Round((Self.FData[(i * 8) + 4] and $03) + 1);
+    Pixel[5]      := Round((Self.FData[(i * 8) + 5] and $C0) / $40 + 1);
+    Pixel[6]      := Round((Self.FData[(i * 8) + 5] and $30) / $10 + 1);
+    Pixel[7]      := Round((Self.FData[(i * 8) + 5] and $0C) / $04 + 1);
+    Pixel[8]      := Round((Self.FData[(i * 8) + 5] and $03) + 1);
+    Pixel[9]      := Round((Self.FData[(i * 8) + 6] and $C0) / $40 + 1);
+    Pixel[10]     := Round((Self.FData[(i * 8) + 6] and $30) / $10 + 1);
+    Pixel[11]     := Round((Self.FData[(i * 8) + 6] and $0C) / $04 + 1);
+    Pixel[12]     := Round((Self.FData[(i * 8) + 6] and $03) + 1);
+    Pixel[13]     := Round((Self.FData[(i * 8) + 7] and $C0) / $40 + 1);
+    Pixel[14]     := Round((Self.FData[(i * 8) + 7] and $30) / $10 + 1);
+    Pixel[15]     := Round((Self.FData[(i * 8) + 7] and $0C) / $04 + 1);
+    Pixel[16]     := Round((Self.FData[(i * 8) + 7] and $03) + 1);
+    for j := 0 to 3 do
+    begin
+      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[16 - j]].RGBb;
+      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[16 - j]].RGBg;
+      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[16 - j]].RGBr;
+      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 3] := 0;
+    end;
+    for j := 0 to 3 do
+    begin
+      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[12 - j]].RGBb;
+      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[12 - j]].RGBg;
+      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[12 - j]].RGBr;
+      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 3] := 0;
+    end;
+    for j := 0 to 3 do
+    begin
+      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[8 - j]].RGBb;
+      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[8 - j]].RGBg;
+      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[8 - j]].RGBr;
+      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 3] := 0;
+    end;
+    for j := 0 to 3 do
+    begin
+      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[4 - j]].RGBb;
+      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[4 - j]].RGBg;
+      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[4 - j]].RGBr;
+      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 3] := 0;
+    end;
+    x := x + 4;
+    if x = Self.FWidth then
+    begin
+      y := y + 4;
+      x := 0;
+    end;
+  end;
+  SetLength(Self.FData, Length(tempd));
+  for i := 0 to High(tempd) do
+    Self.FData[i] := tempd[i];
+  Self.FStoreType := 8;
+  Self.FDepth    := 32;
+  Self.FDataType := Self.FDataType - [DT_Oni] + [DT_Decoded32];
+end;
+
+
+
+
+
+function TOniImage.Load(fileid: LongWord): Boolean;
+var
+  FileInfo: TFileInfo;
+  ext:      String;
+begin
+  FileInfo := OniDataConnection.GetFileInfo(fileid);
+  if FileInfo.Extension = 'PSpc' then
+    Result := LoadFromPSpc(fileid)
+  else if FileInfo.Extension = 'TXMB' then
+    Result := LoadFromTXMB(fileid)
+  else if FileInfo.Extension = 'TXMP' then
+    Result := LoadFromTXMP(fileid)
+  else
+    Result := False;
+end;
+
+
+
+
+function TOniImage.LoadFromPSpc(fileid: LongWord): Boolean;
+type
+  TPoint = packed record
+    X, Y: Word;
+  end;
+
+  TPSpc = packed record
+    p1:   array[0..8] of TPoint;
+    p2:   array[0..8] of TPoint;
+    TXMP: LongWord;
+  end;
+
+  TPart = packed record
+    x_txmp, y_txmp: Word;
+    x_pspc, y_pspc: Word;
+    w, h:    Word;
+    imgdata: Tdata;
+    used:    Boolean;
+  end;
+const
+  PartMatch: array[0..8] of Byte = (0, 3, 6, 1, 4, 7, 2, 5, 8);
+var
+  x, y, pixel: Word;
+  i: Integer;
+
+  PSpc:     TPSpc;
+  txmpimg:  TOniImage;
+  txmpdata: Tdata;
+
+  parts:    array[0..8] of TPart;
+  part:     Byte;
+  cols:     array[0..2] of Word;
+  rows:     array[0..2] of Word;
+  col, row: Byte;
+begin
+  OniDataConnection.LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
+  PSpc.TXMP := PSpc.TXMP div 256;
+  if PSpc.TXMP = 0 then
+  begin
+    Result := False;
+    Exit;
+  end;
+  txmpimg := TOniImage.Create;
+  txmpimg.LoadFromTXMP(PSpc.TXMP);
+  txmpimg.DecodeImage;
+  txmpimg.WriteToBMP('C:\file.bmp');
+  txmpdata := txmpimg.GetAs32bit;
+{    ShowMessage(IntToStr(txmpimg.Width)+'x'+IntToStr(txmpimg.Height));
+    for i:=0 to High(txmpdata) do
+      txmpimg.Data[i]:=txmpdata[i];
+    txmpimg.WriteToBMP('D:\file2.bmp');
+}
+  with PSpc do
+  begin
+    for i := 0 to 2 do
+    begin
+      cols[i] := 0;
+      rows[i] := 0;
+    end;
+    for i := 0 to 8 do
+    begin
+      part := PartMatch[i];
+      col  := i div 3;
+      row  := i mod 3;
+      if (p2[i].X > 0) or (p2[i].Y > 0) then
+      begin
+        parts[part].x_txmp := p1[i].X - 1;
+        parts[part].y_txmp := p1[i].Y - 1;
+        parts[part].x_pspc := 0;
+        if col > 0 then
+          for x := 0 to col - 1 do
+            Inc(parts[part].x_pspc, cols[x]);
+        parts[part].y_pspc := 0;
+        if row > 0 then
+          for y := 0 to row - 1 do
+            Inc(parts[part].y_pspc, rows[y]);
+        parts[part].w := p2[i].X - p1[i].X + 1;
+        parts[part].h := p2[i].Y - p1[i].Y + 1;
+        parts[part].used := True;
+        cols[col] := parts[part].w;
+        rows[row] := parts[part].h;
+        SetLength(parts[part].imgdata, parts[part].w * parts[part].h * 4);
+        for y := 0 to parts[part].h - 1 do
+        begin
+          for x := 0 to parts[part].w - 1 do
+          begin
+            for pixel := 0 to 3 do
+            begin
+              parts[part].imgdata[(y * parts[part].w + x) * 4 + pixel] :=
+                txmpdata[((parts[part].y_txmp + y) * txmpimg.Width +
+                parts[part].x_txmp + x) * 4 + pixel];
+            end;
+          end;
+        end;
+      end
+      else
+      begin
+        parts[part].used := False;
+      end;
+    end;
+
+  end;
+
+  txmpimg.Free;
+  txmpimg := TOniImage.Create;
+  for i := 0 to 8 do
+  begin
+    if parts[i].used then
+    begin
+      SetLength(txmpimg.FData, Length(parts[i].imgdata));
+      for pixel := 0 to High(parts[i].imgdata) do
+        txmpimg.Data[pixel] := parts[i].imgdata[pixel];
+      txmpimg.Width := parts[i].w;
+      txmpimg.Height    := parts[i].h;
+      txmpimg.StoreType := 8;
+      txmpimg.DataType  := [DT_Decoded32];
+      txmpimg.Depth     := 32;
+      txmpimg.WriteToBMP('D:\' + IntToStr(i) + '.bmp');
+    end;
+  end;
+  txmpimg.Free;
+
+  Self.FWidth  := 0;
+  Self.FHeight := 0;
+  for i := 0 to 2 do
+  begin
+    Inc(Self.FWidth, cols[i]);
+    Inc(Self.FHeight, rows[i]);
+  end;
+  SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
+
+  //Combine data parts
+
+  Self.FDepth     := 32;
+  Self.FStoreType := 8;
+  Self.FDataType  := [DT_Decoded32];
+  //    Self.RevertImage;
+end;
+
+
+
+
+function TOniImage.LoadFromTXMP(fileid: LongWord): Boolean;
+var
+  img_addr: LongWord;
+begin
+  Result := True;
+  OniDataConnection.LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
+  OniDataConnection.LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
+  OniDataConnection.LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType),
+    @Self.FStoreType);
+  if not OniDataConnection.OSisMac then
+    OniDataConnection.LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
+  else
+    OniDataConnection.LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
+
+  case Self.FStoreType of
+    0, 1, 2:
+    begin
+      SetLength(Self.FData, Self.FWidth * Self.FHeight * 2);
+      Self.FDepth := 16;
+    end;
+    8:
+    begin
+      SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
+      Self.FDepth := 32;
+    end;
+    9:
+    begin
+      SetLength(Self.FData, Self.FWidth * Self.FHeight div 2);
+      Self.FDepth := 16;
+    end;
+    else
+      Result := False;
+      Exit;
+  end;
+
+  if not OniDataConnection.OSisMac then
+    OniDataConnection.LoadRawFile(fileid, $9C, @Self.FData[0])
+  else
+    OniDataConnection.LoadRawFile(fileid, $A0, @Self.FData[0]);
+
+  Self.FDataType := [DT_OniReverted, DT_Oni];
+end;
+
+
+
+
+function TOniImage.LoadFromTXMB(fileid: LongWord): Boolean;
+var
+  i, x, y, x2, y2, pixelid, imgid: LongWord;
+  rows, cols: Word;
+  linkcount: LongWord;
+  link: LongWord;
+  images_decoded: array of TOniImage;
+  x_start, y_start: LongWord;
+begin
+  OniDataConnection.LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
+  OniDataConnection.LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
+  OniDataConnection.LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
+  OniDataConnection.LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
+  OniDataConnection.LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
+  SetLength(images_decoded, linkcount);
+  for i := 0 to linkcount - 1 do
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
+    link := link div 256;
+    images_decoded[i] := TOniImage.Create;
+    images_decoded[i].LoadFromTXMP(link);
+    images_decoded[i].DecodeImage;
+    images_decoded[i].RevertImage;
+  end;
+  SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
+  for y := 0 to rows - 1 do
+  begin
+    for x := 0 to cols - 1 do
+    begin
+      imgid   := y * cols + x;
+      x_start := 0;
+      y_start := 0;
+      for i := 0 to x do
+        if i < x then
+          x_start := x_start + images_decoded[i].Width;
+      for i := 0 to y do
+        if i < y then
+          y_start := y_start + images_decoded[i].Height;
+      for y2 := 0 to images_decoded[imgid].Height - 1 do
+      begin
+        for x2 := 0 to images_decoded[imgid].Width - 1 do
+        begin
+          if ((x_start + x2) < Self.FWidth) and ((y_start + y2) < Self.FHeight) then
+          begin
+            pixelid := y_start * Self.FWidth + x_start + y2 * Self.FWidth + x2;
+            Self.FData[pixelid * 4 + 0] :=
+              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 0];
+            Self.FData[pixelid * 4 + 1] :=
+              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 1];
+            Self.FData[pixelid * 4 + 2] :=
+              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 2];
+            Self.FData[pixelid * 4 + 3] :=
+              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 3];
+          end;
+        end;
+      end;
+    end;
+  end;
+  for i := 0 to linkcount - 1 do
+    images_decoded[i].Free;
+  Self.FDepth     := 32;
+  Self.FStoreType := 8;
+  Self.FDataType  := [DT_Decoded32];
+  Self.RevertImage;
+end;
+
+
+
+
+function TOniImage.GetImageDataSize(fading: Boolean): LongWord;
+var
+  size: LongWord;
+  x, y: Word;
+  bpp:  Byte;
+begin
+  case Self.FStoreType of
+    9:
+      bpp := 8;
+    0, 1, 2:
+      bpp := 16;
+    8:
+      bpp := 32;
+    else
+      Result := 0;
+      Exit;
+  end;
+
+  x    := Self.FWidth;
+  y    := Self.FHeight;
+  size := x * y * bpp div 8;
+  if fading then
+  begin
+    repeat
+      x    := x div 2;
+      y    := y div 2;
+      size := size + x * y * bpp div 8;
+    until (x = 1) or (y = 1);
+  end;
+  Result := size;
+end;
+
+
+
+
+function TOniImage.GetAsData: Tdata;
+var
+  i:      Integer;
+  revert: Boolean;
+begin
+  //    if not (DT_Decoded32 in Self.FDataType) then
+  //      Self.DecodeImage;
+  if not (DT_OniReverted in Self.FDataType) then
+  begin
+    revert := True;
+    Self.RevertImage;
+  end
+  else
+    revert := False;
+  SetLength(Result, Length(Self.FData));
+  for i := 0 to High(Result) do
+    Result[i] := Self.FData[i];
+  if revert then
+    Self.RevertImage;
+end;
+
+
+
+
+function TOniImage.GetAs32bit: Tdata;
+var
+  i: Integer;
+begin
+  if not (DT_Decoded32 in Self.FDataType) then
+    Self.DecodeImage;
+  SetLength(Result, Length(Self.FData));
+  for i := 0 to High(Result) do
+    Result[i] := Self.FData[i];
+end;
+
+
+
+
+function TOniImage.GetAsBMP: Tdata;
+const
+  BMPheader: array[0..53] of Byte =
+    ($42, $4D, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
+    40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, $18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+var
+  i, x, y: LongWord;
+begin
+  if not (DT_Decoded32 in Self.FDataType) then
+    Self.DecodeImage;
+
+  SetLength(Result, Self.FWidth * Self.FHeight * 3 + 54);
+  for y := 0 to Self.FHeight - 1 do
+  begin
+    for x := 0 to Self.FWidth - 1 do
+    begin
+      Result[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
+      Result[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
+      Result[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
+    end;
+  end;
+
+  for i := 0 to High(BMPheader) do
+    Result[i] := BMPheader[i];
+  Result[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
+  Result[3]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
+  Result[4]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
+  Result[5]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
+  Result[18] := (Self.FWidth and $000000FF) div $1;
+  Result[19] := (Self.FWidth and $0000FF00) div $100;
+  Result[20] := (Self.FWidth and $00FF0000) div $10000;
+  Result[21] := (Self.FWidth and $FF000000) div $1000000;
+  Result[22] := (Self.FHeight and $000000FF) div $1;
+  Result[23] := (Self.FHeight and $0000FF00) div $100;
+  Result[24] := (Self.FHeight and $00FF0000) div $10000;
+  Result[25] := (Self.FHeight and $FF000000) div $1000000;
+  Result[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
+  Result[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
+  Result[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
+  Result[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
+end;
+
+
+
+
+function TOniImage.LoadFromBMP(filename: String): Boolean;
+var
+  filestream: TFileStream;
+  tempd:      Tdata;
+
+  x, y: LongWord;
+begin
+  filestream := TFileStream.Create(filename, fmOpenRead);
+  SetLength(tempd, filestream.Size);
+  filestream.Read(tempd[0], filestream.Size);
+  filestream.Free;
+
+  if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
+  begin
+    Result := False;
+    ShowMessage('Not a standard 24bit bitmap');
+    Exit;
+  end;
+  if not (tempd[10] = 54) then
+  begin
+    Result := False;
+    ShowMessage('Imagedata has to start at 0x54');
+    Exit;
+  end;
+  if not (tempd[14] = 40) then
+  begin
+    Result := False;
+    ShowMessage('Second bitmap header has to have 40 bytes');
+    Exit;
+  end;
+  if not (tempd[28] = 24) then
+  begin
+    Result := False;
+    ShowMessage('Bitmap has to have 24bits');
+    Exit;
+  end;
+  if not (tempd[30] = 0) then
+  begin
+    Result := False;
+    ShowMessage('Bitmap has to be uncompressed');
+    Exit;
+  end;
+
+  Self.FWidth     := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
+  Self.FHeight    := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
+  Self.FDepth     := 32;
+  Self.FStoreType := 8;
+
+  SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
+  for y := 0 to Self.FHeight - 1 do
+  begin
+    for x := 0 to Self.FWidth - 1 do
+    begin
+      Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
+      Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
+      Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
+      Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
+    end;
+  end;
+
+  Self.FDataType := [DT_Decoded32];
+end;
+
+
+
+
+function TOniImage.WriteToBMP(filename: String): Boolean;
+var
+  filestream: TFileStream;
+  tempd:      Tdata;
+begin
+  tempd      := Self.GetAsBMP;
+  filestream := TFileStream.Create(filename, fmCreate);
+  filestream.Write(tempd[0], Length(tempd));
+  filestream.Free;
+end;
+
+
+
+
+function TOniImage.GetMipMappedImage(var faded: Tdata): Boolean;
+var
+  i:      LongWord;
+  x, y:   Word;
+  fadelvldata: Tdata;
+  revert: Boolean;
+begin
+  Result := False;
+
+  //    if not (DT_Decoded32 in Self.FDataType) then
+  //      Self.DecodeImage;
+  if Self.FStoreType = 9 then
+    Self.DecompressImage;
+  if not (DT_OniReverted in Self.FDataType) then
+  begin
+    revert := True;
+    Self.RevertImage;
+  end
+  else
+    revert := False;
+
+  x := Self.FWidth;
+  y := Self.FHeight;
+  SetLength(faded, x * y * Self.FDepth div 8);
+  SetLength(fadelvldata, x * y * Self.FDepth div 8);
+  for i := 0 to Length(faded) - 1 do
+  begin
+    faded[i] := Self.FData[i];
+    fadelvldata[i] := Self.FData[i];
+  end;
+  repeat
+    fadelvldata := Self.ResizeImage(x, y, fadelvldata);
+    x := x div 2;
+    y := y div 2;
+    SetLength(faded, Length(faded) + x * y * Self.FDepth div 8);
+    for i := 0 to Length(fadelvldata) - 1 do
+      faded[Length(faded) - x * y * Self.FDepth div 8 + i] := fadelvldata[i];
+  until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1);
+  if (x > 1) and (y > 1) then
+    Exit;
+  Result := True;
+
+  if revert then
+    Self.RevertImage;
+end;
+
+
+end.
Index: /oup/releases/0.33a/Data.pas
===================================================================
--- /oup/releases/0.33a/Data.pas	(revision 76)
+++ /oup/releases/0.33a/Data.pas	(revision 76)
@@ -0,0 +1,141 @@
+unit Data;
+
+interface
+
+uses Classes, Graphics;
+
+const
+  Version: String   = 'v0.33a';
+  DBVersion: String = '0.3';
+  CrLf: String[2]   = #13 + #10;
+
+type
+  TData = array of Byte;
+
+  THeader = packed record
+    Ident:      array[0..$13] of Byte;
+    Files:      LongWord;
+    NamedFiles: LongWord;
+    Extensions: LongWord;
+    DataAddr:   LongWord;
+    DataSize:   LongWord;
+    NamesAddr:  LongWord;
+    NamesSize:  LongWord;
+    Ident2:     array[0..$F] of Byte;
+  end;
+  TFilesMap = array of packed record
+    Extension: array[0..$3] of Char;
+    DataAddr:  LongWord;
+    NameAddr:  LongWord;
+    FileSize:  LongWord;
+    FileType:  LongWord;
+  end;
+
+  TFileInfo = packed record
+    ID:      Integer;
+    FileName: String;
+    FileNameHex: String;
+    Extension: String[4];
+    Name:    String;
+    Size:    LongWord;
+    FileType: LongWord;
+    DatAddr: LongWord;
+    opened:  Boolean;
+  end;
+  TFiles = array of TFileInfo;
+
+  TNamedFilesMap = array of packed record
+    FileNumber: LongWord;
+    blubb:      LongWord;
+  end;
+  TExtensionsMap = array of packed record
+    Ident:     array[0..$7] of Byte;
+    Extension: array[0..$3] of Char;
+    ExtCount:  LongWord;
+  end;
+
+  TLevelInfo = record
+    Ident: array[0..$13] of Byte;
+    LevelNumber: Byte;
+  end;
+
+  TAppSettings = record
+    DatPath:     String[250];
+    ExtractPath: String[250];
+    FilenumbersAsHex: Boolean;
+    CharSet:     TFontCharSet;
+    HideUnusedData: Boolean;
+  end;
+
+  TExportHandlers = record
+    Ext:     String[4];
+    needed:  Boolean;
+    Handler: function(fileid: LongWord; filename: String): Integer;
+  end;
+
+  TStringArray = array of String;
+  TExtList     = array of record
+    Ext:   String;
+    Count: LongWord;
+  end;
+
+  TRawInfo = record
+    src_id:     LongWord;
+    src_offset: LongWord;
+    raw_addr:   LongWord;
+    raw_size:   LongWord;
+    loc_sep:    Boolean;
+  end;
+  TRawList = array of TRawInfo;
+
+  TDatLinks = array of record
+    Src_Offset: LongWord;
+    Target:     LongWord;
+  end;
+
+  TToolList = array of record
+    context: String;
+    name: String;
+    exts: String;
+  end;
+
+  TSortType = (stIDAsc, stIDDesc, stNameAsc, stNameDesc, stExtAsc, stExtDesc);
+
+var
+{
+  opened_state:Byte=0;
+  dat_filename:String='';
+  raw_filename:String='';
+  dat_os_mac:Boolean=False;
+  dat_header:Theader;
+  dat_filesmap:Tfilesmap;
+  dat_files:Tfiles;
+  dat_namedfilesmap:Tnamedfilesmap;
+  dat_extensionsmap:Textensionsmap;
+}
+  AppSettings:     TAppSettings;
+  AppSettingsFile: file of TAppSettings;
+{
+  database_level:LongWord;
+  database_ident:Array[0..$13] of Byte;
+}
+const
+{  header_ident1_pc:Array[0..$13] of Byte=
+      ($1F,$27,$DC,$33,$DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
+  header_ident1_mac:Array[0..$13] of Byte=
+      ($61,$30,$C1,$23,$DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
+  header_ident2:Array[0..$F] of Byte=
+      ($99,$CF,$40,$00,$90,$4F,$63,$00,$F4,$55,$5F,$00,$90,$4F,$63,$00);
+}
+  export_noerror: Integer = 0;
+  export_nohandler: Integer = 1;
+  export_handlererror: Integer = 2;
+  export_error: Integer = 3;
+{
+  opened_nothing:Byte=0;
+  opened_dat:Byte=1;
+  opened_db:Byte=2;
+}
+implementation
+
+end.
Index: /oup/releases/0.33a/FTypeReg.pas
===================================================================
--- /oup/releases/0.33a/FTypeReg.pas	(revision 76)
+++ /oup/releases/0.33a/FTypeReg.pas	(revision 76)
@@ -0,0 +1,625 @@
+// -----------------------------------------------------------------------------
+//
+// TFileTypeRegistration-Klasse (Win32-API)
+// Copyright (c) 2004 Mathias Simmack
+//
+// -----------------------------------------------------------------------------
+
+// -- Revision history ---------------------------------------------------------
+//
+//   * erste Version
+//
+// -----------------------------------------------------------------------------
+unit FTypeReg;
+
+interface
+
+uses
+  Windows, ShlObj, SysUtils;
+
+type
+  TFileTypeRegistration = class
+    FRegConnector : HKEY;
+    FExtension,
+    FInternalName : string;
+    FVerb         : string;
+  public
+    constructor Create;
+    destructor Destroy; override;
+    function RegisterType(const Extension, InternalName: string;
+      Description: string = ''; IconFile: string = '';
+      IconIndex: integer = -1): boolean;
+    function UnregisterExtension(const Extension: string): boolean;
+    function UnregisterType(const Extension: string): boolean;
+    procedure UpdateShell;
+    function AddHandler(const HandlerVerb, CommandLine: string;
+      HandlerDescription: string = ''): boolean; overload;
+    function DeleteHandler(const HandlerVerb: string): boolean;
+    function SetDefaultHandler: boolean; overload;
+    function SetDefaultHandler(const HandlerVerb: string): boolean; overload;
+    function GetInternalKey(const Extension: string): string;
+    function AddNewFileSupport(const Extension: string): boolean;
+    function RemoveNewFileSupport(const Extension: string): boolean;
+
+    property Extension: string read FExtension;
+    property InternalName: string read FInternalName;
+    property CurrentVerb: string read FVerb;
+  end;
+
+
+implementation
+
+(* *****************************************************************************
+
+  Beispiel #1: Einen neuen Dateityp registrieren
+  ----------------------------------------------
+
+  ftr := TFileTypeRegistration.Create;
+  if(ftr <> nil) then
+  try
+    // die Dateiendung ".foo" registrieren, der interne Schlüssel
+    // lautet "FooFile", eine Beschreibung und eine Symboldatei
+    // sind ebenfalls angegeben
+    if(ftr.RegisterType('.foo','FooFile','FOO Description',
+      'c:\folder\icon.ico')) then
+    begin
+      // fügt den Handler "open" hinzu und verknüpft ihn mit dem
+      // Programm "foo.exe"
+      ftr.AddHandler('open','"c:\folder\foo.exe" "%1"');
+
+      // setzt den zuletzt benutzten Handler ("open" in dem Fall)
+      // als Standard
+      ftr.SetDefaultHandler;
+    end;
+
+    if(ftr.RegisterType('.foo','ThisIsNotTheFOOKey')) then
+    // Das ist kein Fehler! Obwohl hier der interne Name
+    // "ThisIsNotTheFOOKey" verwendet wird, benutzt die Funktion
+    // intern den bereits vorhandenen Schlüssel "FooFile" (s. oben).
+    begin
+      // zwei neue Handler werden registriert, ...
+      ftr.AddHandler('print','"c:\folder\foo.exe" /p "%1"');
+      ftr.AddHandler('edit','notepad.exe "%1"');
+
+      // ... & dank der überladenen Funktion "SetDefaultHandler"
+      // kann diesmal auch "print" als Standardhandler gesetzt
+      // werden
+      ftr.SetDefaultHandler('print');
+    end;
+  finally
+    ftr.Free;
+  end;
+
+
+  Beispiel #2: Einen neuen Typ mit einem vorhandenen Schlüssel
+  verknüpfen
+  ------------------------------------------------------------
+
+  Das Beispiel registriert die Endung ".foo" auf die gleiche
+  Weise wie Textdateien (.txt). Es wird einfach der interne
+  Schlüsselname ermittelt und für die Endung ".foo" gesetzt
+
+  ftr := TFileTypeRegistration.Create;
+  if(ftr <> nil) then
+  try
+    strInternalTextFileKey := ftr.GetInternalKey('.txt');
+    if(strInternalTextFileKey <> '') then
+      ftr.RegisterType('.foo',strInternalTextFileKey);
+  finally
+    ftr.Free;
+  end;
+
+
+  Beispiel #3: Einen Handler entfernen
+  ------------------------------------
+
+  ftr := TFileTypeRegistration.Create;
+  if(ftr <> nil) then
+  try
+    // den internen Schlüsselnamen des Typs ".foo" ermitteln, ...
+    if(ftr.GetInternalKey('.foo') <> '') then
+    // ... wobei das Ergebnis in dem Fall unwichtig ist, weil
+    // intern auch die Eigenschaft "FInternalName" gesetzt
+    // wird
+    begin
+      // den "print"-Handler entfernen, ...
+      ftr.DeleteHandler('print');
+
+      // ... & den Standardhandler aktualisieren
+      ftr.SetDefaultHandler('open');
+    end;
+  finally
+    ftr.Free;
+  end;
+
+
+  Beispiel #4: Nur eine Dateiendung entfernen
+  -------------------------------------------
+
+  In diesem Fall wird lediglich die Endung ".foo" entfernt. Der
+  evtl. vorhandene interne Schlüssel bleibt bestehen. Das ist
+  für das Beispiel #2 nützlich, wenn die Endung ".foo" entfernt
+  werden soll, intern aber mit den Textdateien verlinkt ist, die
+  ja im Normalfall nicht entfernt werden dürfen/sollten.
+
+    ftr.UnregisterExtension('.foo');
+
+
+  Beispiel #5: Den kompletten Dateityp entfernen
+  ----------------------------------------------
+
+  Dieses Beispiel entfernt dagegen den kompletten Dateityp,
+  inkl. des evtl. vorhandenen internen Schlüssels (vgl. mit
+  Beispiel #4).
+
+    ftr.UnregisterType('.foo');
+
+  Bezogen auf Beispiel #2 wäre das die fatale Lösung, weil dadurch
+  zwar die Endung ".foo" deregistriert wird, gleichzeitig wird
+  aber auch der intern verwendete Schlüssel der Textdateien
+  gelöscht.
+
+  ALSO, VORSICHT!!!
+
+***************************************************************************** *)
+
+
+//
+// Admin-Rechte sind erforderlich (Funktion von NicoDE)
+//
+//{$INCLUDE IsAdmin.inc}
+function GetAdminSid: PSID;
+const
+  // bekannte SIDs ... (WinNT.h)
+  SECURITYNTAUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
+  // bekannte RIDs ... (WinNT.h)
+  SECURITYBUILTINDOMAINRID: DWORD = $00000020;
+  DOMAINALIASRIDADMINS: DWORD = $00000220;
+begin
+  Result := nil;
+  AllocateAndInitializeSid(SECURITYNTAUTHORITY, 2, SECURITYBUILTINDOMAINRID,
+    DOMAINALIASRIDADMINS, 0, 0, 0, 0, 0, 0, Result);
+end;
+
+function IsAdmin: LongBool;
+var
+  TokenHandle      : THandle;
+  ReturnLength     : DWORD;
+  TokenInformation : PTokenGroups;
+  AdminSid         : PSID;
+  Loop             : Integer;
+  wv               : TOSVersionInfo;
+begin
+  wv.dwOSVersionInfoSize := sizeof(TOSversionInfo);
+  GetVersionEx(wv);
+
+  Result := (wv.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS);
+
+  if(wv.dwPlatformId = VER_PLATFORM_WIN32_NT) then
+    begin
+      TokenHandle := 0;
+      if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, TokenHandle) then
+        try
+          ReturnLength := 0;
+          GetTokenInformation(TokenHandle, TokenGroups, nil, 0, ReturnLength);
+          TokenInformation := GetMemory(ReturnLength);
+          if Assigned(TokenInformation) then
+            try
+              if GetTokenInformation(TokenHandle, TokenGroups,
+                TokenInformation, ReturnLength, ReturnLength) then
+              begin
+                AdminSid := GetAdminSid;
+                for Loop := 0 to TokenInformation^.GroupCount - 1 do
+                  begin
+                    if EqualSid(TokenInformation^.Groups[Loop].Sid, AdminSid) then
+                      begin
+                        Result := True;
+                        break;
+                      end;
+                  end;
+                FreeSid(AdminSid);
+              end;
+            finally
+              FreeMemory(TokenInformation);
+            end;
+        finally
+          CloseHandle(TokenHandle);
+        end;
+    end;
+end;
+
+function WVersion: string;
+var
+  OSInfo: TOSVersionInfo;
+begin
+  Result := '3X';
+  OSInfo.dwOSVersionInfoSize := sizeof(TOSVERSIONINFO);
+  GetVersionEx(OSInfo);
+  case OSInfo.dwPlatformID of
+    VER_PLATFORM_WIN32S: begin
+        Result := '3X';
+        Exit;
+      end;
+    VER_PLATFORM_WIN32_WINDOWS: begin
+        Result := '9X';
+        Exit;
+      end;
+    VER_PLATFORM_WIN32_NT: begin
+        Result := 'NT';
+        Exit;
+      end;
+  end; //case
+end;
+
+
+// -----------------------------------------------------------------------------
+//
+// Registry
+//
+// -----------------------------------------------------------------------------
+
+function RegWriteSubKeyVal(const parent: HKEY; SubKeyName: string;
+  ValueName, Value: string): boolean;
+var
+  tmp    : HKEY;
+begin
+  Result := false;
+  if(parent = INVALID_HANDLE_VALUE) or
+    (SubKeyName = '') then exit;
+
+  if(RegCreateKeyEx(parent,pchar(SubKeyName),0,nil,0,KEY_READ or KEY_WRITE,
+    nil,tmp,nil) = ERROR_SUCCESS) then
+  try
+    Result := (RegSetValueEx(tmp,pchar(ValueName),0,REG_SZ,pchar(Value),
+      length(Value) + 1) = ERROR_SUCCESS);
+  finally
+    RegCloseKey(tmp);
+  end;
+end;
+
+function RegReadSubKeyStr(const parent: HKEY; SubKeyName: string;
+  ValueName: string): string;
+var
+  tmp     : HKEY;
+  lpData,
+  dwLen   : dword;
+begin
+  Result  := '';
+  if(parent = INVALID_HANDLE_VALUE) or
+    (SubKeyName = '') then exit;
+
+  if(RegOpenKeyEx(parent,pchar(SubKeyName),0,KEY_READ,
+    tmp) = ERROR_SUCCESS) then
+  try
+    lpData := REG_NONE;
+    dwLen  := 0;
+    if(RegQueryValueEx(tmp,pchar(ValueName),nil,@lpData,nil,
+         @dwLen) = ERROR_SUCCESS) and
+      (lpData in[REG_SZ,REG_EXPAND_SZ]) and
+      (dwLen > 0) then
+    begin
+      SetLength(Result,dwLen);
+
+      if(RegQueryValueEx(tmp,pchar(ValueName),nil,@lpData,
+           @Result[1],@dwLen) = ERROR_SUCCESS) then
+        SetLength(Result,dwLen - 1)
+      else
+        Result := '';
+    end;
+  finally
+    RegCloseKey(tmp);
+  end;
+end;
+
+function RegKeyExists(const parent: HKEY; KeyName: string): boolean;
+var
+  tmp    : HKEY;
+begin
+  Result := (RegOpenKeyEx(parent,pchar(KeyName),0,KEY_READ,tmp) =
+    ERROR_SUCCESS);
+  if(Result) then RegCloseKey(tmp);
+end;
+
+function RegDeleteWholeKey(parent: HKEY; KeyName: string): boolean;
+var
+  reg       : HKEY;
+  dwSubkeys : dword;
+  dwLen     : dword;
+  i         : integer;
+  buf       : array[0..MAX_PATH]of char;
+begin
+  if(RegOpenKeyEx(parent,pchar(KeyName),0,KEY_READ,reg) = ERROR_SUCCESS) then
+  try
+    if(RegQueryInfoKey(reg,nil,nil,nil,@dwSubKeys,nil,
+      nil,nil,nil,nil,nil,nil) = ERROR_SUCCESS) and
+      (dwSubKeys > 0) then
+    for i := 0 to dwSubKeys - 1 do begin
+      ZeroMemory(@buf,sizeof(buf));
+      dwLen   := MAX_PATH;
+
+      if(RegEnumKeyEx(reg,i,buf,dwLen,nil,nil,nil,nil) = ERROR_SUCCESS) and
+        (dwLen > 0) then
+      RegDeleteWholeKey(reg,buf);
+    end;
+  finally
+    RegCloseKey(reg);
+  end;
+
+  Result := (RegDeleteKey(parent,pchar(KeyName)) = ERROR_SUCCESS);
+end;
+
+
+// -----------------------------------------------------------------------------
+//
+// TFileTypeRegistration-Klasse
+//
+// -----------------------------------------------------------------------------
+
+constructor TFileTypeRegistration.Create;
+var
+  key: HKEY;
+  sub: PChar;
+begin
+  FExtension    := '';
+  FInternalName := '';
+  FVerb         := '';
+
+  // Zugriff auf die Registry, & HKEY_CLASSES_ROOT
+  // als Root setzen
+  if(WVersion='9X') or IsAdmin then begin
+    key:=HKEY_CLASSES_ROOT;
+    sub:=nil;
+  end else begin
+    key:=HKEY_CURRENT_USER;
+    sub:=PChar('SOFTWARE\Classes');
+  end;
+
+  if RegOpenKeyEx(key,sub,0,KEY_ALL_ACCESS, FRegConnector) <> ERROR_SUCCESS then
+    FRegConnector := INVALID_HANDLE_VALUE;
+end;
+
+destructor TFileTypeRegistration.Destroy;
+begin
+  if(FRegConnector <> INVALID_HANDLE_VALUE) then
+    RegCloseKey(FRegConnector);
+end;
+
+function TFileTypeRegistration.RegisterType(const Extension,
+  InternalName: string; Description: string = ''; IconFile: string = '';
+  IconIndex: integer = -1): boolean;
+var
+  strDummy : string;
+begin
+  // Standardergebnis
+  Result         := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // ist dieser Typ evtl. schon registriert?
+  strDummy := self.GetInternalKey(Extension);
+
+  // Nein. :o)
+  if(strDummy = '') then strDummy := InternalName;
+
+  // den Schlüssel mit der Dateiendung anlegen oder aktualisieren
+  Result := RegWriteSubKeyVal(FRegConnector,Extension,'',strDummy);
+  if(not Result) then exit;
+
+  // den internen Schlüssel öffnen
+  if(Result) then
+  begin
+    // Beschreibung anlegen
+    if(Description <> '') then
+      RegWriteSubKeyVal(FRegConnector,strDummy,'',Description);
+
+    // Symbol zuweisen (Datei muss existieren!)
+    if(IconFile <> '') and
+      (fileexists(IconFile)) then
+    begin
+      if(IconIndex <> -1) then
+        RegWriteSubKeyVal(FRegConnector,strDummy + '\DefaultIcon',
+          '',Format('%s,%d',[IconFile,IconIndex]))
+      else
+        RegWriteSubKeyVal(FRegConnector,strDummy + '\DefaultIcon',
+          '',IconFile);
+    end;
+  end;
+
+  // Systemsymbole aktualisieren
+  self.UpdateShell;
+
+  // Properties aktualisieren
+  if(Result) then
+  begin
+    FExtension    := Extension;
+    FInternalName := strDummy;
+  end;
+end;
+
+function TFileTypeRegistration.UnregisterExtension(const Extension: string):
+  boolean;
+begin
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // die Endung entfernen
+  Result := (RegKeyExists(FRegConnector,Extension)) and
+    (RegDeleteWholeKey(FRegConnector,Extension));
+
+  // Systemsymbole aktualisieren
+  self.UpdateShell;
+end;
+
+function TFileTypeRegistration.UnregisterType(const Extension: string):
+  boolean;
+var
+  strDummy : string;
+begin
+  Result   := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // den internen Namen der Endung ermitteln
+  strDummy := self.GetInternalKey(Extension);
+
+  // die Endung entfernen (s. "UnregisterExtension"), ...
+  Result   := (self.UnregisterExtension(Extension)) and
+  // ... & den internen Schlüssel löschen
+    (strDummy <> '') and
+    (RegKeyExists(FRegConnector,strDummy)) and
+    (RegDeleteWholeKey(FRegConnector,strDummy));
+
+  // Systemsymbole aktualisieren
+  self.UpdateShell;
+end;
+
+procedure TFileTypeRegistration.UpdateShell;
+begin
+  SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST,nil,nil);
+end;
+
+
+const
+  ShellKey = '%s\shell\%s';
+
+function TFileTypeRegistration.AddHandler(const HandlerVerb,
+  CommandLine: string; HandlerDescription: string = ''): boolean;
+begin
+  // Standardergebnis
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (FInternalName = '') or
+    (HandlerVerb = '') or
+    (CommandLine = '') then exit;
+
+  // der interne Schlüssel muss existieren
+  if(RegKeyExists(FRegConnector,FInternalName)) then
+  begin
+    // den Handler (= Verb) erzeugen
+    Result := RegWriteSubKeyVal(FRegConnector,
+      Format(ShellKey + '\command',[FInternalName,HandlerVerb]),
+      '',
+      CommandLine);
+
+    // ggf. Beschreibung für Handler setzen
+    if(HandlerDescription <> '') then
+      RegWriteSubKeyVal(FRegConnector,
+        Format(ShellKey,[FInternalName,HandlerVerb]),
+        '',
+        HandlerDescription);
+  end;
+
+  // interne Eigenschaft anpassen (für "SetDefaultHandler")
+  if(Result) then
+    FVerb := HandlerVerb;
+end;
+
+function TFileTypeRegistration.DeleteHandler(const HandlerVerb: string):
+  boolean;
+begin
+  // Standardergebnis
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (FInternalName = '') or
+    (HandlerVerb = '') then exit;
+
+  // Handlerschlüssel entfernen (sofern vorhanden)
+  Result :=
+    (RegKeyExists(FRegConnector,
+       Format(ShellKey,[FInternalName,HandlerVerb]))) and
+    (RegDeleteWholeKey(FRegConnector,
+       Format(ShellKey,[FInternalName,HandlerVerb])));
+end;
+
+function TFileTypeRegistration.SetDefaultHandler: boolean;
+begin
+  if(FInternalName <> '') and (FVerb <> '') then
+    Result := self.SetDefaultHandler(FVerb)
+  else
+    Result := false;
+end;
+
+function TFileTypeRegistration.SetDefaultHandler(const HandlerVerb: string):
+  boolean;
+begin
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (FInternalName = '') or
+    (HandlerVerb = '') then exit;
+
+  // interner Schlüssel muss existieren, ...
+  if(RegKeyExists(FRegConnector,FInternalName)) and
+  // ... & Handler muss existieren, ...
+    (RegKeyExists(FRegConnector,
+       Format(ShellKey,[FInternalName,HandlerVerb]))) then
+  begin
+  // ... dann den Handler als Standard eintragen
+    Result := RegWriteSubKeyVal(FRegConnector,FInternalName + '\shell',
+      '',HandlerVerb);
+  end;
+end;
+
+function TFileTypeRegistration.GetInternalKey(const Extension: string): string;
+begin
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // einen evtl. eingestellten internen Namen zurücksetzen
+  FInternalName   := '';
+
+  // den Schlüssel der Dateiendung öffnen, ...
+  if(RegKeyExists(FRegConnector,Extension)) then
+    FInternalName := RegReadSubKeyStr(FRegConnector,Extension,'');
+
+  // ... als Funktionsergebnis zurückliefern
+  if(not RegKeyExists(FRegConnector,FInternalName)) then
+    FInternalName := '';
+
+  Result := FInternalName;
+end;
+
+
+function TFileTypeRegistration.AddNewFileSupport(const Extension: string):
+  boolean;
+var
+  Description : string;
+begin
+  Result      := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // interne Beschreibung des Typs ermitteln
+  if(self.GetInternalKey(Extension) <> '') then
+    Description := RegReadSubKeyStr(FRegConnector,FInternalName,'')
+  else
+    Description := '';
+
+  // die Beschreibung darf keine Leerzeichen enthalten, weil sie
+  // als Referenz für den neuen Dateinamen verwendet wird, ...
+  if(pos(#32,Description) > 0) or
+  // ... & sie darf auch nicht leer sein
+    (Description = '') then exit;
+
+  Result := (RegKeyExists(FRegConnector,Extension)) and
+    (RegWriteSubKeyVal(FRegConnector,Extension + '\ShellNew','NullFile',''));
+end;
+
+function TFileTypeRegistration.RemoveNewFileSupport(const Extension: string):
+  boolean;
+begin
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  Result := (RegKeyExists(FRegConnector,Extension + '\ShellNew')) and
+    (RegDeleteWholeKey(FRegConnector,Extension + '\ShellNew'));
+end;
+
+end.
Index: /oup/releases/0.33a/Helper_LevelDB.dfm
===================================================================
--- /oup/releases/0.33a/Helper_LevelDB.dfm	(revision 76)
+++ /oup/releases/0.33a/Helper_LevelDB.dfm	(revision 76)
@@ -0,0 +1,61 @@
+object Form_LevelDB: TForm_LevelDB
+  Left = 0
+  Top = 0
+  BorderStyle = bsNone
+  Caption = 'Creating DB'
+  ClientHeight = 89
+  ClientWidth = 400
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poScreenCenter
+  PixelsPerInch = 96
+  TextHeight = 13
+  object group_progress: TGroupBox
+    Left = 0
+    Top = 0
+    Width = 400
+    Height = 89
+    Caption = 'Progress ...'
+    TabOrder = 0
+    object lbl_progress: TLabel
+      Left = 2
+      Top = 32
+      Width = 396
+      Height = 17
+      Align = alTop
+      AutoSize = False
+    end
+    object lbl_estimation: TLabel
+      Left = 2
+      Top = 49
+      Width = 396
+      Height = 17
+      Align = alTop
+      AutoSize = False
+      Caption = 'Estimated finishing time:'
+    end
+    object progress: TProgressBar
+      Left = 2
+      Top = 15
+      Width = 396
+      Height = 17
+      Align = alTop
+      Smooth = True
+      TabOrder = 0
+    end
+    object btn_abortok: TButton
+      Left = 3
+      Top = 64
+      Width = 60
+      Height = 22
+      Caption = 'Abort...'
+      TabOrder = 1
+      OnClick = btn_abortokClick
+    end
+  end
+end
Index: /oup/releases/0.33a/Helper_LevelDB.pas
===================================================================
--- /oup/releases/0.33a/Helper_LevelDB.pas	(revision 76)
+++ /oup/releases/0.33a/Helper_LevelDB.pas	(revision 76)
@@ -0,0 +1,1748 @@
+unit Helper_LevelDB;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, ComCtrls, StdCtrls, StrUtils;
+
+type
+  TForm_LevelDB = 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(Source, target: String);
+    procedure CreateLevel(Source, target: String);
+  end;
+
+
+var
+  Form_LevelDB: TForm_LevelDB;
+
+implementation
+
+{$R *.dfm}
+
+uses ABSMain, ABSDecUtil, Main, Functions, Data,
+  OniImgClass, DataStructures, OniDataClass;
+
+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;
+  DataBase:  TABSDatabase;
+  Query:     TABSQuery;
+  MimeCoder: TStringFormat_MIME64;
+
+var
+  DatHeader:   THeader;
+  FilesHeader: TFilesMap;
+  NamedFilesHeader: TNamedFilesMap;
+  ExtensionsHeader: TExtensionsMap;
+  Stream_Body, Stream_Names: TMemoryStream;
+  Stream_Dat, Stream_Raw, Stream_Sep: TFileStream;
+
+
+
+
+procedure TForm_LevelDB.CreateLevel(Source, target: String);
+var
+  files: LongWord;
+
+  i, j:     LongWord;
+  temps, temps2: String;
+  Data, rawdata: Tdata;
+  absolutebegintime, begintime: Double;
+  step:     Byte;
+  rawlist:  TRawList;
+  extlist:  TExtensionsMap;
+  fileinfo: TFileInfo;
+  datlinks: TDatLinks;
+  OniImage: TOniImage;
+  levelid:  LongWord;
+  timeformat: TFormatSettings;
+const
+  steps: Byte = 3;
+
+
+
+
+  procedure DoStep(stepname: String);
+  begin
+    Inc(step);
+    if stepname <> 'FIN' then
+      group_progress.Caption :=
+        'Creating Dat (Step ' + IntToStr(step) + '/' + IntToStr(steps) + ': ' + stepname + ')'
+    else
+      group_progress.Caption := 'Creating Dat (FINISHED)';
+  end;
+
+begin
+
+  //
+  // FILE EXISTS CHECK FÜR DAT/RAW/SEP!!!
+  //
+
+  timeformat.LongTimeFormat := 'hh:nn:ss';
+  timeformat.TimeSeparator := ':';
+
+  if not CreateDataConnection(Source, ODB_ADB) then
+  begin
+    ShowMessage('Could not connect to .oldb-file');
+    Exit;
+  end;
+  levelid  := OniDataConnection.LevelInfo.LevelNumber;
+  levelid  := (levelid * 2) * 256 * 256 * 256 + $01;
+  OniImage := TOniImage.Create;
+
+  absolutebegintime := Time;
+
+  Self.Visible := True;
+  Form_Main.Visible := False;
+  step  := 0;
+  converting := True;
+  abort := False;
+  btn_abortok.Caption := '&Abort...';
+  btn_abortok.Default := False;
+  absolutebegintime := Time;
+
+  Stream_Body  := TMemoryStream.Create;
+  Stream_Names := TMemoryStream.Create;
+  Stream_Dat   := TFileStream.Create(target, fmCreate);
+  Stream_Raw   := TFileStream.Create(AnsiReplaceStr(target, '.dat', '.raw'), fmCreate);
+  if OniDataConnection.OSisMac then
+    Stream_Sep := TFileStream.Create(AnsiReplaceStr(target, '.dat', '.sep'), fmCreate);
+
+  DoStep('Creating header');
+  progress.Position      := 0;
+  lbl_progress.Caption   := '';
+  lbl_estimation.Caption := 'Estimated finishing time: unknown';
+  Application.ProcessMessages;
+
+  NamedFilesHeader := TOniDataADB(OniDataConnection).GetNamedFilesMap;
+  extlist := OniDataConnection.GetExtendedExtensionsList;
+  for i := 0 to High(DatHeader.Ident) do
+    DatHeader.Ident[i] := OniDataConnection.LevelInfo.Ident[i];
+  DatHeader.Files := OniDataConnection.GetFilesCount;
+  DatHeader.NamedFiles := Length(NamedFilesHeader);
+  DatHeader.Extensions := Length(extlist);
+  DatHeader.DataAddr   := 0;
+  DatHeader.DataSize   := 0;
+  DatHeader.NamesAddr  := 0;
+  DatHeader.NamesSize  := 0;
+  for i := 0 to High(DatHeader.Ident2) do
+    DatHeader.Ident2[i] := 0;
+  SetLength(FilesHeader, DatHeader.Files);
+  SetLength(ExtensionsHeader, DatHeader.Extensions);
+
+  DoStep('Writing extensions-header');
+  progress.Max := Length(OniDataConnection.GetExtensionsList);
+  Application.ProcessMessages;
+
+  for i := 0 to High(ExtensionsHeader) do
+  begin
+    ExtensionsHeader[i].Ident     := extlist[i].Ident;
+    ExtensionsHeader[i].Extension := extlist[i].Extension;
+    SetLength(temps, 4);
+    for j := 0 to 3 do
+      temps[j + 1] := ExtensionsHeader[i].Extension[3 - j];
+    ExtensionsHeader[i].ExtCount :=
+      Length(OniDataConnection.GetFilesList(temps, '', False, stIDAsc));
+    progress.Position    := i + 1;
+    lbl_progress.Caption := 'Extensions done: ' + IntToStr(i + 1) + '/' +
+      IntToStr(Length(extlist));
+    Application.ProcessMessages;
+  end;
+
+  DoStep('Storing files-data');
+  progress.Position := 0;
+  progress.Max      := DatHeader.Files;
+  lbl_progress.Caption := '';
+  lbl_estimation.Caption := 'Estimated finishing time: unknown';
+  Application.ProcessMessages;
+
+  begintime := Time;
+  for i := 0 to DatHeader.Files - 1 do
+  begin
+    fileinfo := OniDataConnection.GetFileInfo(i);
+    for j := 0 to 3 do
+      FilesHeader[i].Extension[j] := fileinfo.Extension[4 - j];
+    if fileinfo.Size > 0 then
+    begin
+      //        DatLinks:=;
+      FilesHeader[i].DataAddr := Stream_Body.Size + 8;
+      Data    := OniDataConnection.LoadDatFile(i);
+      Data[4] := (levelid) and $FF;
+      Data[5] := (levelid shr 8) and $FF;
+      Data[6] := (levelid shr 16) and $FF;
+      Data[7] := (levelid shr 24) and $FF;
+
+      if (Pos(UpperCase(fileinfo.Extension), UpperCase(raws)) mod 4) = 1 then
+      begin
+        rawlist := OniDataConnection.GetRawList(i);
+        if Length(rawlist) > 0 then
+        begin
+          for j := 0 to High(rawlist) do
+          begin
+            if rawlist[j].raw_size > 0 then
+            begin
+              if (UpperCase(fileinfo.Extension) = 'TXMP') and
+                ((Data[$88] and $01) > 0) then
+              begin
+                OniImage.LoadFromTXMP(i);
+                OniImage.GetMipMappedImage(rawdata);
+                rawlist[j].raw_size := OniImage.GetImageDataSize(True);
+                Data[$90] := $08;
+                Data[$89] := 32;
+{                  if data[$90]<>OniImage.StoreType then begin
+                    data[$90]:=OniImage.StoreType;
+                    data[$89]:=(data[$89] and $CF) or $20;
+                  end;
+}                end
+              else
+              begin
+                SetLength(rawdata, rawlist[j].raw_size);
+                OniDataConnection.LoadRawFile(i, rawlist[j].src_offset, @rawdata[0]);
+              end;
+              //                data[$88]:=data[$88] and $FE;
+
+              if rawlist[j].loc_sep then
+              begin
+                rawlist[j].raw_addr := Stream_Sep.Size;
+                Stream_Sep.Write(rawdata[0], Length(rawdata));
+              end
+              else
+              begin
+                rawlist[j].raw_addr := Stream_Raw.Size;
+                Stream_Raw.Write(rawdata[0], Length(rawdata));
+              end;
+            end
+            else
+              rawlist[j].raw_addr := 0;
+            Data[rawlist[j].src_offset + 0] := (rawlist[j].raw_addr) and $FF;
+            Data[rawlist[j].src_offset + 1] := (rawlist[j].raw_addr shr 8) and $FF;
+            Data[rawlist[j].src_offset + 2] := (rawlist[j].raw_addr shr 16) and $FF;
+            Data[rawlist[j].src_offset + 3] := (rawlist[j].raw_addr shr 24) and $FF;
+          end;
+        end;
+      end;
+
+      Stream_Body.Write(Data[0], Length(Data));
+      //
+    end
+    else
+      FilesHeader[i].DataAddr := 0;
+    if Length(fileinfo.Name) > 0 then
+    begin
+      FilesHeader[i].NameAddr := Stream_Names.Size;
+      temps := fileinfo.Extension + fileinfo.Name + Chr(0);
+      Stream_Names.Write(temps[1], Length(temps));
+    end
+    else
+      FilesHeader[i].NameAddr := 0;
+    FilesHeader[i].FileSize := fileinfo.Size;
+    FilesHeader[i].FileType := fileinfo.FileType;
+
+    if ((i mod 10) = 0) and (i >= 100) then
+      lbl_estimation.Caption := 'Estimated time left: ' + TimeToStr(
+        (Time - begintime) / i * (progress.Max - i + 1) * 1.1 );
+    progress.Position := i + 1;
+    lbl_progress.Caption := 'Files done: ' + IntToStr(i + 1) + '/' + IntToStr(progress.Max);
+    Application.ProcessMessages;
+  end;
+
+  Stream_Dat.Write(DatHeader, SizeOf(DatHeader));
+  for i := 0 to High(FilesHeader) do
+    Stream_Dat.Write(FilesHeader[i], SizeOf(FilesHeader[i]));
+  for i := 0 to High(NamedFilesHeader) do
+    Stream_Dat.Write(NamedFilesHeader[i], SizeOf(NamedFilesHeader[i]));
+  for i := 0 to High(ExtensionsHeader) do
+    Stream_Dat.Write(ExtensionsHeader[i], SizeOf(ExtensionsHeader[i]));
+
+  DatHeader.DataSize  := Stream_Body.Size;
+  DatHeader.NamesSize := Stream_Names.Size;
+  DatHeader.DataAddr  := Stream_Dat.Size;
+  Stream_Body.Seek(0, soFromBeginning);
+  Stream_Dat.CopyFrom(Stream_Body, Stream_Body.Size);
+  DatHeader.NamesAddr := Stream_Dat.Size;
+  Stream_Names.Seek(0, soFromBeginning);
+  Stream_Dat.CopyFrom(Stream_Names, Stream_Names.Size);
+
+  Stream_Dat.Seek(0, soFromBeginning);
+  Stream_Dat.Write(DatHeader, SizeOf(DatHeader));
+
+  Stream_Dat.Free;
+  Stream_Body.Free;
+  Stream_Names.Free;
+  Stream_Raw.Free;
+  if OniDataConnection.OSisMac then
+    Stream_Sep.Free;
+
+  progress.Position      := progress.Max;
+  lbl_progress.Caption   := 'Files done: ' + IntToStr(progress.Max) + '/' +
+    IntToStr(progress.Max);
+  lbl_estimation.Caption := 'FINISHED (duration: ' + TimeToStr(Time - absolutebegintime, timeformat) + ')';
+
+  DoStep('FIN');
+  btn_abortok.Caption := '&OK';
+  btn_abortok.Default := True;
+
+  OniImage.Free;
+
+  converting := False;
+
+  CloseDataConnection;
+end;
+
+
+
+
+procedure TForm_LevelDB.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 TForm_LevelDB.CreateDatabase(Source, target: String);
+var
+  i, j:     LongWord;
+  temps, temps2: String;
+  Data:     Tdata;
+  absolutebegintime, begintime: Double;
+  step:     Byte;
+  rawlist:  TRawList;
+  extlist:  TExtensionsMap;
+  fileinfo: TFileInfo;
+  timeformat: TFormatSettings;
+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
+  if not CreateDataConnection(Source, ODB_Dat) then
+  begin
+    ShowMessage('Could not connect to .dat-file');
+    Exit;
+  end
+  else
+  begin
+    TOniDataDat(OniDataConnection).UnloadWhenUnused := False;
+  end;
+
+  Self.Visible := True;
+  Form_Main.Visible := False;
+  step  := 0;
+  converting := True;
+  abort := False;
+  btn_abortok.Caption := '&Abort...';
+  btn_abortok.Default := False;
+  loaded_filename := target;
+
+  absolutebegintime := Time;
+
+  DataBase := TABSDatabase.Create(Self);
+  DataBase.DatabaseName := 'OLDB';
+  DataBase.DatabaseFileName := target;
+  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, sep BOOLEAN, 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(OniDataConnection.LevelInfo.Ident));
+  for i := 0 to High(OniDataConnection.LevelInfo.Ident) do
+    Data[i] := OniDataConnection.LevelInfo.Ident[i];
+  temps := CreateHexString(Data, True);
+  Query.SQL.Text := 'INSERT INTO globals (name,value) VALUES ("ident","' + temps + '");';
+  Query.ExecSQL;
+  Query.SQL.Text := 'INSERT INTO globals (name,value) VALUES ("lvl","' +
+    IntToStr(OniDataConnection.LevelInfo.LevelNumber) + '");';
+  Query.ExecSQL;
+  if OniDataConnection.OSisMAC then
+    Query.SQL.Text := 'INSERT INTO globals (name,value) VALUES ("os","MAC");'
+  else
+    Query.SQL.Text := 'INSERT INTO globals (name,value) VALUES ("os","PC");';
+  Query.ExecSQL;
+
+  DoStep('Writing extensionslist');
+  progress.Max := Length(OniDataConnection.GetExtensionsList);
+  Application.ProcessMessages;
+
+  extlist := OniDataConnection.GetExtendedExtensionsList;
+  for i := 0 to High(extlist) do
+  begin
+    SetLength(Data, Length(extlist[i].Ident));
+    for j := 0 to High(extlist[i].Ident) do
+      Data[j] := extlist[i].Ident[j];
+    temps := CreateHexString(Data, True);
+    temps2 := extlist[i].Extension[3] + extlist[i].Extension[2] +
+      extlist[i].Extension[1] + extlist[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(Length(extlist));
+    Application.ProcessMessages;
+    if abort then
+    begin
+      stop_convert;
+      Exit;
+    end;
+  end;
+  lbl_progress.Caption := '';
+
+  progress.Position      := 0;
+  lbl_progress.Caption   := 'Files done: ' + IntToStr(0) + '/' + IntToStr(
+    OniDataConnection.GetFilesCount);
+  lbl_estimation.Caption := 'Estimated finishing time: unknown';
+
+  DoStep('Loading .dat into memory');
+  Application.ProcessMessages;
+
+  progress.Max := OniDataConnection.GetFilesCount;
+  begintime    := Time;
+  DoStep('Writing .dat-fileslist');
+  Application.ProcessMessages;
+
+  Database.StartTransaction;
+  for i := 0 to OniDataConnection.GetFilesCount - 1 do
+  begin
+    fileinfo := OniDataConnection.GetFileInfo(i);
+    if (fileinfo.FileType and $02) = 0 then
+    begin
+      mimecoder := TStringFormat_MIME64.Create;
+      Data      := OniDataConnection.LoadDatFile(i);
+      Query.SQL.Text :=
+        'INSERT INTO datfiles (id,extension,name,contenttype,size,data) VALUES (' +
+        IntToStr(i) + ',"' + fileinfo.Extension + '","' + fileinfo.Name + '","' + IntToHex(
+        fileinfo.FileType, 8) + '",' + IntToStr(fileinfo.Size) + ',MimeToBin("' +
+        MimeCoder.StrTo(@Data[0], Length(Data)) + '") );';
+      Query.ExecSQL;
+      mimecoder.Free;
+
+      rawlist := OniDataConnection.GetRawList(i);
+      if Length(rawlist) > 0 then
+      begin
+        for j := 0 to High(rawlist) do
+        begin
+          if rawlist[j].raw_size > 0 then
+          begin
+            SetLength(Data, rawlist[j].raw_size);
+            OniDataConnection.LoadRawFile(i, rawlist[j].src_offset, Data);
+            mimecoder      := TStringFormat_MIME64.Create;
+            Query.SQL.Text :=
+              'INSERT INTO rawmap (src_id,src_link_offset,sep,size,data) VALUES (' +
+              IntToStr(i) + ',' + IntToStr(rawlist[j].src_offset) + ',' + BoolToStr(
+              rawlist[j].loc_sep) + ',' + IntToStr(rawlist[j].raw_size) + ',MimeToBin("' +
+              MimeCoder.StrTo(@Data[0], rawlist[j].raw_size) + '") );';
+            Query.ExecSQL;
+            mimecoder.Free;
+          end
+          else
+          begin
+            Query.SQL.Text :=
+              'INSERT INTO rawmap (src_id,src_link_offset,sep,size) VALUES (' +
+              IntToStr(i) + ',' + IntToStr(rawlist[j].src_offset) + ',' + BoolToStr(rawlist[j].loc_sep) + ',0);';
+            Query.ExecSQL;
+          end;
+        end;
+      end;
+
+      HandleFile(fileinfo.Extension, i, True);
+    end
+    else
+    begin
+      Query.SQL.Text :=
+        'INSERT INTO datfiles (id,extension,name,contenttype,size) VALUES (' +
+        IntToStr(i) + ',"' + fileinfo.Extension + '","' + fileinfo.Name + '","' + IntToHex(
+        fileinfo.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 10) = 0) and (i >= 100) then
+      lbl_estimation.Caption := 'Estimated time left: ' + TimeToStr(
+        (Time - begintime) / i * (progress.Max - i + 1) * 1.1 );
+    progress.Position := i;
+    lbl_progress.Caption := 'Files done: ' + IntToStr(i) + '/' + IntToStr(progress.Max);
+    Application.ProcessMessages;
+    if abort then
+    begin
+      stop_convert;
+      Exit;
+    end;
+  end;
+  Database.Commit(False);
+  progress.Position      := progress.Max;
+  lbl_progress.Caption   := 'Files done: ' + IntToStr(progress.Max) + '/' +
+    IntToStr(progress.Max);
+
+  timeformat.LongTimeFormat := 'hh:nn:ss';
+  timeformat.TimeSeparator := ':';
+  lbl_estimation.Caption := 'FINISHED (duration: ' + TimeToStr(Time - absolutebegintime, timeformat) + ')';
+
+  DoStep('FIN');
+  btn_abortok.Caption := '&OK';
+  btn_abortok.Default := True;
+
+  converting := False;
+
+  database.Close;
+  database.Free;
+
+  CloseDataConnection;
+end;
+
+
+
+
+procedure TForm_LevelDB.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 TForm_LevelDB.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
+    Self.Visible := False;
+    Form_Main.Visible  := True;
+  end;
+end;
+
+
+
+
+procedure InsertDatLinkToDB(fileid: LongWord; offset: LongWord);
+var
+  link: LongWord;
+begin
+  OniDataConnection.LoadDatFilePart(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 AISA(fileid: LongWord; dir_dat2db: Boolean);
+var
+  packages: Word;
+  i: LongWord;
+begin
+  if dir_dat2db then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $1E, 2, @packages);
+    if packages > 0 then
+    begin
+      for i := 0 to packages - 1 do
+        InsertDatLinkToDB(fileid, $20 + i * $160 + $28);
+      for i := 0 to packages - 1 do
+        InsertDatLinkToDB(fileid, $20 + i * $160 + $150);
+    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 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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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 OBDC(fileid: LongWord; dir_dat2db: Boolean);
+var
+  packages: Word;
+  i: LongWord;
+begin
+  if dir_dat2db then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $1E, 2, @packages);
+    if packages > 0 then
+      for i := 0 to packages - 1 do
+        InsertDatLinkToDB(fileid, $20 + i * $18 + $4);
+  end
+  else
+  begin
+  end;
+end;
+
+
+
+
+procedure OBOA(fileid: LongWord; dir_dat2db: Boolean);
+var
+  packages: Word;
+  i: LongWord;
+begin
+  if dir_dat2db then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $1E, 2, @packages);
+    if packages > 0 then
+      for i := 0 to packages - 1 do
+      begin
+        InsertDatLinkToDB(fileid, $20 + i * 240 + $0);
+        InsertDatLinkToDB(fileid, $20 + i * 240 + $4);
+        InsertDatLinkToDB(fileid, $20 + i * 240 + $8);
+      end;
+  end
+  else
+  begin
+  end;
+end;
+
+
+
+
+procedure OFGA(fileid: LongWord; dir_dat2db: Boolean);
+var
+  packages: LongWord;
+  i: LongWord;
+begin
+  if dir_dat2db then
+  begin
+    OniDataConnection.LoadDatFilePart(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
+    InsertDatLinkToDB(fileid, $28);
+    InsertDatLinkToDB(fileid, $434);
+    InsertDatLinkToDB(fileid, $438);
+    InsertDatLinkToDB(fileid, $43C);
+    InsertDatLinkToDB(fileid, $C3C);
+    InsertDatLinkToDB(fileid, $C40);
+    InsertDatLinkToDB(fileid, $C44);
+    InsertDatLinkToDB(fileid, $C48);
+    InsertDatLinkToDB(fileid, $C88);
+    InsertDatLinkToDB(fileid, $C8C);
+  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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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, $40);
+    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, $0C);
+  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
+    OniDataConnection.LoadDatFilePart(fileid, $1C, 4, @packages);
+    if packages > 0 then
+      for i := 0 to packages - 1 do
+        InsertDatLinkToDB(fileid, $20 + i * 8 + $4);
+  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 STNA(fileid: LongWord; dir_dat2db: Boolean);
+var
+  packages: Word;
+  i: LongWord;
+begin
+  if dir_dat2db then
+  begin
+    OniDataConnection.LoadDatFilePart(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);
+    OniDataConnection.LoadDatFilePart(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);
+begin
+  if dir_dat2db then
+  begin
+    InsertDatLinkToDB(fileid, $40);
+    InsertDatLinkToDB(fileid, $44);
+  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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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
+    OniDataConnection.LoadDatFilePart(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);
+begin
+  if dir_dat2db then
+  begin
+    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);
+var
+  i: LongWord;
+  packages: LongWord;
+begin
+  if dir_dat2db then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $1C, 4, @packages);
+    if packages > 0 then
+      for i := 0 to packages - 1 do
+        InsertDatLinkToDB(fileid, $20 + i * 8 + $4);
+  end
+  else
+  begin
+  end;
+end;
+
+
+
+
+procedure WMDD(fileid: LongWord; dir_dat2db: Boolean);
+var
+  i: LongWord;
+  packages: LongWord;
+begin
+  if dir_dat2db then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $11C, 4, @packages);
+    if packages > 0 then
+      for i := 0 to packages - 1 do
+        InsertDatLinkToDB(fileid, $120 + i * $124 + $114);
+  end
+  else
+  begin
+  end;
+end;
+
+
+
+
+procedure WMMB(fileid: LongWord; dir_dat2db: Boolean);
+var
+  i: LongWord;
+  packages: LongWord;
+begin
+  if dir_dat2db then
+  begin
+    OniDataConnection.LoadDatFilePart(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', True, AISA);
+  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', False, nil);
+  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', True, OBDC);
+  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', False, nil);
+  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', False, nil);
+  InsertHandler('STNA', True, STNA);
+  InsertHandler('SUBT', False, nil);
+  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', True, WMDD);
+  InsertHandler('WMM_', False, nil);
+  InsertHandler('WMMB', True, WMMB);
+  InsertHandler('WPGE', True, WPGE);
+end.
Index: /oup/releases/0.33a/Helper_ValueEdit.dfm
===================================================================
--- /oup/releases/0.33a/Helper_ValueEdit.dfm	(revision 76)
+++ /oup/releases/0.33a/Helper_ValueEdit.dfm	(revision 76)
@@ -0,0 +1,123 @@
+object Form_ValueEdit: TForm_ValueEdit
+  Left = 0
+  Top = 0
+  BorderStyle = bsNone
+  BorderWidth = 1
+  Caption = 'Value Edit'
+  ClientHeight = 145
+  ClientWidth = 298
+  Color = clBtnFace
+  Constraints.MaxHeight = 147
+  Constraints.MaxWidth = 700
+  Constraints.MinHeight = 147
+  Constraints.MinWidth = 300
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poMainFormCenter
+  OnCreate = FormCreate
+  PixelsPerInch = 96
+  TextHeight = 13
+  object group: TGroupBox
+    Left = 0
+    Top = 0
+    Width = 298
+    Height = 145
+    Align = alClient
+    Caption = '---'
+    TabOrder = 0
+    DesignSize = (
+      298
+      145)
+    object lbl_current: TLabel
+      Left = 8
+      Top = 64
+      Width = 73
+      Height = 17
+      AutoSize = False
+      Caption = 'Current value:'
+    end
+    object lbl_new: TLabel
+      Left = 8
+      Top = 88
+      Width = 73
+      Height = 17
+      AutoSize = False
+      Caption = 'New value:'
+    end
+    object lbl_offset: TLabel
+      Left = 8
+      Top = 16
+      Width = 73
+      Height = 17
+      AutoSize = False
+      Caption = 'Offset:'
+    end
+    object lbl_datatype: TLabel
+      Left = 8
+      Top = 40
+      Width = 73
+      Height = 17
+      AutoSize = False
+      Caption = 'Datatype:'
+    end
+    object btn_ok: TButton
+      Left = 153
+      Top = 112
+      Width = 65
+      Height = 25
+      Anchors = [akTop, akRight]
+      Caption = 'OK'
+      Default = True
+      TabOrder = 0
+      OnClick = btn_okClick
+    end
+    object btn_cancel: TButton
+      Left = 225
+      Top = 112
+      Width = 65
+      Height = 25
+      Anchors = [akTop, akRight]
+      Cancel = True
+      Caption = 'Cancel'
+      TabOrder = 1
+      OnClick = btn_cancelClick
+    end
+    object edit_current: TEdit
+      Left = 88
+      Top = 64
+      Width = 203
+      Height = 18
+      Anchors = [akLeft, akTop, akRight]
+      AutoSize = False
+      Color = clInfoBk
+      ReadOnly = True
+      TabOrder = 2
+    end
+    object edit_offset: TEdit
+      Left = 87
+      Top = 16
+      Width = 203
+      Height = 18
+      Anchors = [akLeft, akTop, akRight]
+      AutoSize = False
+      Color = clInfoBk
+      ReadOnly = True
+      TabOrder = 3
+    end
+    object edit_datatype: TEdit
+      Left = 87
+      Top = 40
+      Width = 203
+      Height = 18
+      Anchors = [akLeft, akTop, akRight]
+      AutoSize = False
+      Color = clInfoBk
+      ReadOnly = True
+      TabOrder = 4
+    end
+  end
+end
Index: /oup/releases/0.33a/Helper_ValueEdit.pas
===================================================================
--- /oup/releases/0.33a/Helper_ValueEdit.pas	(revision 76)
+++ /oup/releases/0.33a/Helper_ValueEdit.pas	(revision 76)
@@ -0,0 +1,186 @@
+unit Helper_ValueEdit;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, CrossEdit, Math;
+
+type
+  TForm_ValueEdit = class(TForm)
+    group:      TGroupBox;
+    btn_ok:     TButton;
+    btn_cancel: TButton;
+    lbl_current: TLabel;
+    edit_current: TEdit;
+    lbl_new:    TLabel;
+    lbl_offset: TLabel;
+    lbl_datatype: TLabel;
+    edit_offset: TEdit;
+    edit_datatype: TEdit;
+    procedure btn_cancelClick(Sender: TObject);
+    procedure btn_okClick(Sender: TObject);
+    procedure MakeVarInput(objectname: String; offset: LongWord;
+      datatype: Word; current: String; caller: TObject);
+    procedure FormCreate(Sender: TObject);
+  private
+  public
+    edit_new:   TCrossEdit;
+  end;
+
+var
+  Form_ValueEdit: TForm_ValueEdit;
+
+
+implementation
+
+uses BinEdit, RawEdit, DataStructures, Main;
+
+{$R *.dfm}
+
+var
+  caller_win_dat: TForm_BinEdit;
+  caller_win_raw: TForm_RawEdit;
+  _datatype: Word;
+  _offset: LongWord;
+
+
+
+
+procedure TForm_ValueEdit.MakeVarInput(objectname: String; offset: LongWord;
+  datatype: Word; current: String; caller: TObject);
+begin
+  caller_win_dat := nil;
+  caller_win_raw := nil;
+  if Pos('rawedit', TComponent(caller).Name) > 0 then
+    caller_win_raw := TForm_RawEdit(caller)
+  else
+    caller_win_dat := TForm_BinEdit(caller);
+  Form_Main.Enabled := False;
+  Self.Visible := True;
+  group.Caption := 'Edit value';
+  _datatype := datatype;
+  _offset := offset;
+  if Length(objectname) > 0 then
+    group.Caption := group.Caption + ' for ' + objectname;
+  edit_offset.Text := '0x' + IntToHex(offset, 8);
+  edit_datatype.Text := GetDataType(datatype);
+  edit_current.Text := current;
+  edit_new.EditType := etString;
+  edit_new.Text := '';
+  edit_new.LimitCheck := False;
+  edit_new.MaxLength := 0;
+  edit_new.Max := 0;
+  edit_new.BorderStyle := bsSingle;
+  Self.Width := 300;
+  case datatype of
+    1..4:
+    begin
+      edit_new.EditType := etUnsignedInt;
+      edit_new.LimitCheck := True;
+      edit_new.Max := Int(Power(256, datatype)) - 1;
+    end;
+    5..8:
+    begin
+      edit_new.MaxLength := 2 * (datatype - 4);
+      edit_new.EditType  := etHex;
+    end;
+    9:
+    begin
+      edit_new.EditType   := etFloat;
+      edit_new.LimitCheck := False;
+    end;
+    10:
+    begin
+      edit_new.EditType   := etBinary;
+      edit_new.LimitCheck := False;
+      edit_new.MaxLength  := 8;
+    end;
+    13..16:
+    begin
+      Exit;
+      edit_new.EditType := etInteger;
+      edit_new.LimitCheck := True;
+      edit_new.Max := Int((Power(256, datatype - 13)) / 2) - 1;
+      edit_new.Min := 1 - Int((Power(256, datatype - 13)) / 2) - 1;
+    end;
+    10000..65535:
+    begin
+      edit_new.EditType := etString;
+      edit_new.LimitCheck := False;
+      edit_new.MaxLength := datatype - 10000;
+      Self.Width := 700;
+    end;
+  end;
+  edit_new.SetFocus;
+  edit_new.SelectAll;
+end;
+
+
+
+
+procedure TForm_ValueEdit.btn_okClick(Sender: TObject);
+begin
+  if not edit_new.NoValidValue then
+  begin
+    Form_Main.Enabled := True;
+    Self.Visible  := False;
+    if caller_win_dat = nil then
+      caller_win_raw.SetNewValue(_datatype, _offset, edit_new.Text)
+    else
+      caller_win_dat.SetNewValue(_datatype, _offset, edit_new.Text);
+  end;
+end;
+
+
+
+
+procedure TForm_ValueEdit.FormCreate(Sender: TObject);
+begin
+  edit_new := TCrossEdit.Create(Self);
+  with edit_new do
+  begin
+    Left := 88;
+    Top := 88;
+    Width := 203;
+    Height := 18;
+    Anchors := [akLeft, akTop, akRight];
+    AutoSize := False;
+    BorderStyle := bsNone;
+    Color := clWhite;
+    Font.Charset := DEFAULT_CHARSET;
+    Font.Color := clWindowText;
+    Font.Height := -11;
+    Font.Name := 'Tahoma';
+    Font.Style := [];
+    HideSelection := False;
+    ParentFont := False;
+    TabOrder := 5;
+    Text := '0000';
+    FocusAlignment := taLeftJustify;
+    NoFocusAlignment := taLeftJustify;
+    Precision := 15;
+    Decimals := 4;
+    FocusWidthInc := 0;
+    EditType := etHex;
+    NextDialogOnEnter := True;
+    DialogOnCursorKeys := True;
+    NextPriorStep := 1;
+    AutoFocus := False;
+    LimitCheck := True;
+    Max := 2147483647.000000000000000000;
+    FocusColor := clWhite;
+    NoFocusColor := clWhite;
+    ErrorColor := clRed;
+    StringCharSet := scFull;
+  end;
+  Self.InsertControl(edit_new);
+end;
+
+procedure TForm_ValueEdit.btn_cancelClick(Sender: TObject);
+begin
+  Form_Main.Enabled := True;
+  Self.Visible  := False;
+end;
+
+end.
Index: /oup/releases/0.33a/Main.dfm
===================================================================
--- /oup/releases/0.33a/Main.dfm	(revision 76)
+++ /oup/releases/0.33a/Main.dfm	(revision 76)
@@ -0,0 +1,911 @@
+object Form_Main: TForm_Main
+  Left = 0
+  Top = 0
+  HorzScrollBar.Visible = False
+  VertScrollBar.Visible = False
+  Caption = 'Form_Main'
+  ClientHeight = 571
+  ClientWidth = 577
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIForm
+  OldCreateOrder = False
+  WindowState = wsMaximized
+  OnClose = FormClose
+  OnCreate = FormCreate
+  OnResize = FormResize
+  PixelsPerInch = 96
+  TextHeight = 13
+  object statbar: TStatusBar
+    Left = 0
+    Top = 554
+    Width = 577
+    Height = 17
+    BiDiMode = bdLeftToRight
+    Panels = <
+      item
+        Text = 'Nothing loaded'
+        Width = 500
+      end
+      item
+        Text = 'Files: -'
+        Width = 90
+      end
+      item
+        Text = 'Extensions: -'
+        Width = 100
+      end>
+    ParentBiDiMode = False
+  end
+  object DockTop: TTBDock
+    Left = 0
+    Top = 0
+    Width = 577
+    Height = 75
+    object MainMenu: TTBToolbar
+      Left = 0
+      Top = 0
+      Caption = 'MainMenu'
+      CloseButton = False
+      DragHandleStyle = dhDouble
+      FullSize = True
+      Images = MenuImages
+      MenuBar = True
+      ProcessShortCuts = True
+      ShrinkMode = tbsmWrap
+      TabOrder = 0
+      object menu_main: TTBSubmenuItem
+        Caption = '&Main'
+        object menu_loadfile: TTBItem
+          Caption = '&Open .dat/.raw ...'
+          ImageIndex = 0
+          ShortCut = 16463
+          OnClick = menu_loadfileClick
+        end
+        object menu_loaddb: TTBItem
+          Caption = 'Open level-&db ...'
+          ImageIndex = 1
+          ShortCut = 16452
+          OnClick = menu_loaddbClick
+        end
+        object menu_sep1: TTBSeparatorItem
+        end
+        object menu_settings: TTBItem
+          Caption = 'Se&ttings...'
+          OnClick = menu_settingsClick
+        end
+        object menu_sep4: TTBSeparatorItem
+        end
+        object menu_exit: TTBItem
+          Caption = '&Exit'
+          OnClick = menu_exitClick
+        end
+      end
+      object menu_convert: TTBSubmenuItem
+        Caption = '&Convert'
+        object menu_createdb: TTBItem
+          Caption = 'Convert .dat/.raw to DB ...'
+          ImageIndex = 2
+          OnClick = menu_createdbClick
+        end
+        object menu_createlvl: TTBItem
+          Caption = 'Convert DB to .dat/.raw ...'
+          ImageIndex = 3
+          OnClick = menu_createlvlClick
+        end
+      end
+      object menu_tools: TTBSubmenuItem
+        Caption = '&Tools'
+        Enabled = False
+        object menu_preview: TTBItem
+          Caption = '&Preview window ...'
+          ImageIndex = 4
+          ShortCut = 16464
+          OnClick = menu_previewClick
+        end
+        object menu_binedit: TTBItem
+          Caption = '&Binary .dat editor ...'
+          ImageIndex = 5
+          ShortCut = 16450
+          OnClick = menu_bineditClick
+        end
+        object menu_rawedit: TTBItem
+          Caption = 'Binary .&raw editor ...'
+          ImageIndex = 6
+          ShortCut = 16466
+          OnClick = menu_raweditClick
+        end
+        object menu_txmpreplace: TTBItem
+          Caption = '&TXMP replacer ...'
+          ImageIndex = 7
+          ShortCut = 16468
+          OnClick = menu_txmpreplaceClick
+        end
+        object menu_extractor: TTBItem
+          Caption = 'File &extractor ...'
+          ImageIndex = 8
+          ShortCut = 16453
+          OnClick = menu_extractorClick
+        end
+        object menu_meta: TTBItem
+          Caption = '&Meta editor'
+          Enabled = False
+          ImageIndex = 11
+          ShortCut = 16461
+          OnClick = menu_metaClick
+        end
+        object menu_filecompare: TTBItem
+          Caption = '&File compare ...'
+          Enabled = False
+          ImageIndex = 10
+          ShortCut = 16454
+          OnClick = menu_filecompareClick
+        end
+        object menu_levelstructedit: TTBItem
+          Caption = 'Levelfile structure editor ...'
+          Enabled = False
+          ImageIndex = 12
+          ShortCut = 16460
+        end
+      end
+      object menu_windows: TTBSubmenuItem
+        Caption = '&Windows'
+        object menu_windows_cascade: TTBItem
+          Caption = 'Cascade'
+          OnClick = menu_windows_cascadeClick
+        end
+        object menu_windows_tilevert: TTBItem
+          Caption = 'Tile vertical'
+          OnClick = menu_windows_tilevertClick
+        end
+        object menu_windows_tile: TTBItem
+          Caption = 'Tile horizontal'
+          OnClick = menu_windows_tileClick
+        end
+        object menu_windows_closeall: TTBItem
+          Caption = '&Close all'
+          OnClick = menu_windows_closeallClick
+        end
+        object menu_sep3: TTBSeparatorItem
+        end
+        object menu_windows_next: TTBItem
+          Caption = 'Next window'
+          ShortCut = 16417
+          OnClick = menu_windows_nextClick
+        end
+        object menu_windows_previous: TTBItem
+          Caption = 'Previous window'
+          ShortCut = 16418
+          OnClick = menu_windows_previousClick
+        end
+        object menu_sep2: TTBSeparatorItem
+        end
+        object menu_view: TTBSubmenuItem
+          Caption = '&View'
+          object menu_view_toolbar: TTBItem
+            Caption = '&Toolbar'
+            Checked = True
+            OnClick = menu_view_toolbarClick
+          end
+          object menu_view_statusbar: TTBItem
+            Caption = '&Status bar'
+            Checked = True
+            OnClick = menu_view_statusbarClick
+          end
+          object menu_view_mdibar: TTBItem
+            Caption = '&Window list'
+            Checked = True
+            OnClick = menu_view_mdibarClick
+          end
+        end
+      end
+      object menu_About: TTBItem
+        Caption = '&About'
+        OnClick = menu_AboutClick
+      end
+    end
+    object Toolbar: TTBToolbar
+      Left = 0
+      Top = 23
+      Caption = 'Toolbar'
+      DragHandleStyle = dhDouble
+      Images = MenuImages
+      TabOrder = 1
+      OnDockChanged = ToolbarDockChanged
+      object tbOpen: TTBItem
+        Caption = 'Open .dat'
+        DisplayMode = nbdmImageAndText
+        ImageIndex = 0
+        OnClick = menu_loadfileClick
+      end
+      object tb_opendb: TTBItem
+        Caption = 'Open DB'
+        DisplayMode = nbdmImageAndText
+        ImageIndex = 1
+        OnClick = menu_loaddbClick
+      end
+      object tb_separator1: TTBSeparatorItem
+      end
+      object tb_dat2db: TTBItem
+        Caption = '.dat -> DB'
+        DisplayMode = nbdmImageAndText
+        ImageIndex = 2
+        OnClick = menu_createdbClick
+      end
+      object tb_db2dat: TTBItem
+        Caption = 'DB -> .dat'
+        DisplayMode = nbdmImageAndText
+        ImageIndex = 3
+        OnClick = menu_createlvlClick
+      end
+      object TBSeparatorItem1: TTBSeparatorItem
+      end
+      object tb_preview: TTBItem
+        Caption = 'Preview'
+        DisplayMode = nbdmImageAndText
+        Enabled = False
+        ImageIndex = 4
+        OnClick = menu_previewClick
+      end
+      object tb_datedit: TTBItem
+        Caption = 'DatEditor'
+        DisplayMode = nbdmImageAndText
+        Enabled = False
+        ImageIndex = 5
+        OnClick = menu_bineditClick
+      end
+      object tb_rawedit: TTBItem
+        Caption = 'RawEditor'
+        DisplayMode = nbdmImageAndText
+        Enabled = False
+        ImageIndex = 6
+        OnClick = menu_raweditClick
+      end
+      object tb_txmpreplacer: TTBItem
+        Caption = 'TXMP replacer'
+        DisplayMode = nbdmImageAndText
+        Enabled = False
+        ImageIndex = 7
+        OnClick = menu_txmpreplaceClick
+      end
+      object tb_extractor: TTBItem
+        Caption = 'File extractor'
+        DisplayMode = nbdmImageAndText
+        Enabled = False
+        ImageIndex = 8
+        OnClick = menu_extractorClick
+      end
+      object tb_meta: TTBItem
+        Caption = 'MetaEditor'
+        DisplayMode = nbdmImageAndText
+        Enabled = False
+        ImageIndex = 11
+        OnClick = menu_metaClick
+      end
+      object tb_compare: TTBItem
+        Caption = 'File compare'
+        DisplayMode = nbdmImageAndText
+        Enabled = False
+        ImageIndex = 10
+        OnClick = menu_filecompareClick
+      end
+      object tb_structure: TTBItem
+        Caption = 'Level structure'
+        DisplayMode = nbdmImageAndText
+        Enabled = False
+        ImageIndex = 12
+      end
+    end
+    object MDIToolbar: TTBToolbar
+      Left = 0
+      Top = 49
+      Caption = 'MDIToolbar'
+      DockableTo = [dpTop, dpBottom]
+      DockMode = dmCannotFloat
+      DockPos = 0
+      DockRow = 2
+      DragHandleStyle = dhDouble
+      TabOrder = 2
+      object TBControlItem1: TTBControlItem
+        Control = MDITab
+      end
+      object MDITab: TMDITab
+        Left = 0
+        Top = 0
+        Width = 300
+        Height = 22
+        Cursor = crHandPoint
+        About = 'MDI Tab Control 1.4 - Copyright '#169' 1999,2002 MichaL MutL'
+        Align = alTop
+        DragKind = dkDock
+        HotTrack = True
+        Images = MenuImages
+        OwnerDraw = True
+        Style = tsFlatButtons
+        OnDrawTab = MDITabDrawTab
+        ParentShowHint = False
+        ShowHint = True
+        ShowOnChange = True
+        TabOrder = 0
+        OnMouseUp = MDITabMouseUp
+      end
+    end
+  end
+  object DockLeft: TTBDock
+    Left = 0
+    Top = 75
+    Width = 9
+    Height = 470
+    Position = dpLeft
+  end
+  object DockRight: TTBDock
+    Left = 568
+    Top = 75
+    Width = 9
+    Height = 470
+    Position = dpRight
+  end
+  object DockBottom: TTBDock
+    Left = 0
+    Top = 545
+    Width = 577
+    Height = 9
+    Position = dpBottom
+  end
+  object opend: TOpenDialog
+    Filter = 
+      'Compatible level files|*.dat;*.oldb|Oni level (*.dat)|*.dat|OUP ' +
+      'level database (*.oldb)|*.oldb|Any (*.*)|*'
+    Options = [ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    Left = 32
+    Top = 64
+  end
+  object saved: TSaveDialog
+    Options = [ofOverwritePrompt, ofPathMustExist, ofEnableSizing]
+    Left = 32
+    Top = 88
+  end
+  object MenuImages: TImageList
+    Left = 168
+    Top = 112
+    Bitmap = {
+      494C01010D000E00040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      0000000000003600000028000000400000004000000001002000000000000040
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF000000FF000000FF
+      000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF
+      000000FF000000FF000000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF000000000000000000000000000000000000000000000000000000
+      0000FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF00000000000000000000000000000000000000000000000000FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF000000000000000000000000000000000000000000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF0000000000000000000000000000000000FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF000000
+      FF00FFFFFF00000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF0000FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+      FF00FFFFFF00FFFFFF0000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FF000000FF000000FF
+      000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF
+      000000FF000000FF000000FF0000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000FF000000FF000000FF000000
+      FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+      FF000000FF000000FF000000FF000000FF00000000000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000FF00000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000FF0000FFFF000000FF0000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FF
+      FF0000FFFF000000FF000000FF000000FF00000000000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000FF00000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FF
+      FF0000FFFF00000000000000FF0000000000000000000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF00000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000FF0000000000000000000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FF
+      FF0000000000000000000000FF00000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FF
+      FF0000000000000000000000FF000000000000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF00000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000FF000000000000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000
+      000000000000000000000000FF000000000000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000
+      000000000000000000000000FF000000000000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000FF000000FF0000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000FF000000FF000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF00000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000FF00000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000FF000000FF000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000FF000000FF000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF00000000000000
+      000000000000000000000000FF00000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000FF000000FF000000000000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000FF000000FF000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF00000000000000
+      000000000000000000000000FF00000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF00000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000FF00000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000FF0000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000FF0000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000FFFF000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000000000000000000000
+      000000000000000000000000FF00000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000FF0000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000FF0000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000FF0000FFFF000000FF0000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000FF000000FF000000
+      FF000000FF000000FF000000FF000000FF000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000FF0000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000FF0000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000FF000000FF000000FF000000
+      FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+      FF000000FF000000FF000000FF000000FF000000000008080800080808000808
+      0800080808001018180010101000080808001010100008080800080810001010
+      1000101010000808080008080800000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000FFFF0000FFFF0000FFFF0000FFFF000000000000000000000000000000
+      000000FFFF0000FFFF0000FFFF0000FFFF000000000000000000202018002920
+      18005252520039313100393131009C9C9C0039313100393131009C9C9C000000
+      0000292020002920180000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000FFFF0000000000000000000000
+      00000000000000C1C100009A9A00008585000085850000000000000000000000
+      00000000000000FFFF0000FFFF0000FFFF000000000000000000292018002920
+      20005252520039313100DEDEDE00A4A4A40039313100DEDEDE00A4A4A4000000
+      000029202000292020000000000000000000FF00000000000000FF0000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FF00000000000000FF0000000000FF00000000000000FF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000FF00000000000000FF0000FFFF0000FFFF00000000000000
+      0000000B0B000032320000707000007C7C00007C7C000070700000323200000B
+      0B00000000000000000000FFFF0000FFFF000000000000000000292018002920
+      20005252520039313100DEDEDE00A4A4A40039313100DEDEDE00A4A4A4000000
+      000029202000292020000000000000000000FF00000000000000FF000000FF00
+      0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+      FF000000FF000000FF00000000000000FF0000FFFF0000FFFF0000D9D9000016
+      16000060600000B1B10000E0E00000F9F90000F9F90000E0E00000B1B1000060
+      600000161600000000000000000000FFFF000000000000000000292029003129
+      2900525252003931310039313100A4A4A4003931310039313100A4A4A4000000
+      000031292900312929000000000000000000FF00000000000000FF0000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000FF000000FF00000000000000FF0000FFFF0000EDED00008C8C000070
+      700000D5D50000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000D5
+      D50000606000000B0B0000000000000000000000000000000000525252005252
+      5200525252005252520052525200525252005252520052525200525252005252
+      520052525200525252000000000000000000FF00000000000000FF0000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000FF000000FF00000000000000FF000000000000C2C2000067670000B1
+      B10000FFFF0000C9C90000414100002C2C00002C2C00002C2C0000EAEA0000FF
+      FF0000B1B1000032320000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000FF00000000000000FF000000FF00
+      0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+      FF000000FF000000FF00000000000000FF0000000000000000000070700000E0
+      E00000C0C000002D2D00002B2B000062620000373700002121000039390000C9
+      C90000E0E00000707000000000000000000000000000000000000000FF000000
+      FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+      FF000000FF000000FF000000000000000000FF00000000000000FF0000000000
+      000000000000000000000000000000000000000000000000000000000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      FF000000FF000000FF00000000000000FF0000000000000000000079790000F8
+      F80000929200003C3C0000C9C90000FFFF0000FFFF0000FFFF0000464600006A
+      6A0000F8F800007C7C00008585000000000000000000000000000000FF000000
+      FF000000FF000000000000000000000000000000000000000000000000000000
+      FF000000FF000000FF000000000000000000FF00000000000000FF0000000000
+      000000000000000000000000000000000000000000000000000000000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      FF000000FF000000FF00000000000000FF0000000000000000000079790000F8
+      F80000F4F40000F4F40000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FF
+      FF0000F8F800007C7C000085850000FFFF0000000000000000000000FF000000
+      FF000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000000000
+      00000000FF000000FF000000000000000000FF00000000000000FF000000FF00
+      0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+      FF000000FF000000FF00000000000000FF0000FFFF00000000000060600000E0
+      E00000FFFF0000424200002A2A0000FFFF0000FFFF00003B3B000052520000FF
+      FF0000E0E00000707000009A9A0000FFFF0000000000000000000000FF000000
+      000000000000FFFFFF00FFFFFF000000000000000000FFFFFF00FFFFFF000000
+      0000000000000000FF000000000000000000FF00000000000000FF0000000000
+      0000000000000000000000000000000000000000000000000000FF000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      00000000000000000000000000000000000000000000000000000000FF000000
+      FF000000FF000000FF00000000000000FF0000FFFF0000C2C2000032320000B1
+      B10000C9C900005858000045450000FFFF0000FFFF0000434300005E5E0000FF
+      FF0000B1B1000032320000C2C20000FFFF0000000000000000000000FF000000
+      0000FFFFFF00FFFFFF00000000006A00BD006A00BD0000000000FFFFFF00FFFF
+      FF00000000000000FF000000000000000000FF00000000000000FF0000000000
+      0000000000000000000000000000000000000000000000000000FF000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      00000000000000000000000000000000000000000000000000000000FF000000
+      FF000000FF000000FF00000000000000FF0000FFFF0000EDED00008C8C000060
+      600000D5D50000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000D5
+      D50000606000000B0B000000000000FFFF0000000000000000000000FF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000FF000000000000000000FF00000000000000FF000000FF00
+      0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+      FF000000FF000000FF00000000000000FF0000FFFF0000FFFF0000D9D900007F
+      7F000060600000B1B10000E0E00000F8F80000F8F80000E0E00000B1B1000070
+      70000016160000000000000000000000000000000000000000000000FF000000
+      FF00000000000000000000000000000000000000000000000000000000000000
+      00000000FF000000FF000000000000000000FF00000000000000FF0000000000
+      00000000000000000000000000000000000000000000FF000000FF000000FF00
+      0000FF000000FF00000000000000FF0000000000FF00000000000000FF000000
+      000000000000000000000000000000000000000000000000FF000000FF000000
+      FF000000FF000000FF00000000000000FF000000000000FFFF0000FFFF0000D9
+      D900008C8C00003232000060600000797900007979000070700000676700008C
+      8C0000D9D90000000000000000000000000000000000000000000000FF000000
+      FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
+      FF000000FF000000FF0000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000000FFFF0000FF
+      FF0000EDED0000C2C2000000000000000000000000000000000000C2C20000ED
+      ED0000FFFF0000FFFF0000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000000000000000000000FF
+      FF0000FFFF0000FFFF0000FFFF000000000000000000000000000000000000FF
+      FF0000FFFF0000FFFF0000FFFF00000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000FF000000FF000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000FF000000FF000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FF0000000000FF0000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000FF0000000000FF0000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000FF000000FF0000000000000000000000FF000000FF00000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000FF000000FF0000000000000000000000FF000000FF00000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000FF0000000000FF000000FF000000FF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000FF000000FF000000FF0000000000FF000000FF000000FF000000
+      00000000000000000000000000000000000000000000000000000000000000FF
+      000000FF00000000000000000000FF0000000000FF00000000000000000000FF
+      000000FF000000000000000000000000000000000000000000000000000000FF
+      000000FF000000000000000000000000000000000000000000000000000000FF
+      000000FF0000000000000000000000000000000000000000000000000000FF00
+      0000FF000000FF00000000000000000000000000000000000000000000000000
+      FF000000FF00000000000000000000000000000000000000000000000000FF00
+      0000FF000000FF000000FF000000FF0000000000FF000000FF000000FF000000
+      FF000000FF000000000000000000000000000000000000FF000000FF00000000
+      000000000000FF000000FF000000FF0000000000FF000000FF000000FF000000
+      00000000000000FF000000FF0000000000000000000000FF000000FF00000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000FF000000FF00000000000000000000FF000000FF000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      00000000FF000000FF000000FF000000000000000000FF000000FF0000000000
+      0000000000000000000000000000FF0000000000FF0000000000000000000000
+      0000000000000000FF000000FF00000000000000000000FF000000000000FF00
+      0000FF000000FF000000FF000000FF0000000000FF000000FF000000FF000000
+      FF000000FF000000000000FF0000000000000000000000FF0000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000FF00000000000000000000FF000000FF000000FF00
+      0000000000000000000000000000FF0000000000FF000000FF00000000000000
+      0000000000000000FF000000FF000000000000000000FF000000FF000000FF00
+      0000000000000000000000000000FF0000000000FF0000000000000000000000
+      00000000FF000000FF000000FF00000000000000000000FF000000000000FF00
+      0000FF000000FF000000FF000000FF0000000000FF000000FF000000FF000000
+      FF000000FF000000000000FF0000000000000000000000FF0000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000FF00000000000000000000FF000000FF000000FF00
+      00000000000000000000FF000000FF0000000000FF000000FF000000FF000000
+      0000000000000000FF000000FF000000000000000000FF000000FF0000000000
+      0000000000000000000000000000FF0000000000FF0000000000000000000000
+      0000000000000000FF000000FF00000000000000000000FF000000000000FF00
+      0000FF000000FF000000FF000000FF0000000000FF000000FF000000FF000000
+      FF000000FF000000000000FF0000000000000000000000FF0000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000FF00000000000000000000FF000000FF000000FF00
+      00000000000000000000FF000000FF0000000000FF000000FF000000FF000000
+      FF000000FF000000FF000000FF000000000000000000FF000000FF0000000000
+      000000000000FF00000000000000FF0000000000FF00000000000000FF000000
+      0000000000000000FF000000FF00000000000000000000FF000000000000FF00
+      0000FF000000FF000000FF00000000000000000000000000FF000000FF000000
+      FF000000FF000000000000FF0000000000000000000000FF0000000000000000
+      000000000000000000000000000000FFFF0000FFFF0000000000000000000000
+      0000000000000000000000FF00000000000000000000FF000000FF000000FF00
+      0000000000000000000000FFFF0000FFFF0000FFFF0000FFFF000000FF000000
+      FF000000FF000000FF000000FF000000000000000000FF000000FF0000000000
+      000000000000FF00000000FFFF0000FFFF0000FFFF0000FFFF000000FF000000
+      0000000000000000FF000000FF00000000000000000000FF000000000000FF00
+      0000FF0000000000000000000000000000000000000000000000000000000000
+      FF000000FF000000000000FF0000000000000000000000FF0000000000000000
+      00000000000000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000
+      0000000000000000000000FF00000000000000000000FF000000FF000000FF00
+      000000000000000000000000000000FFFF000000000000FFFF0000FFFF0000FF
+      FF000000FF000000FF000000FF000000000000000000FF000000FF0000000000
+      00000000000000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000
+      0000000000000000FF000000FF00000000000000000000FF0000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000FF0000000000000000000000FF00000000000000FF
+      FF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FF
+      FF0000FFFF000000000000FF00000000000000000000FF00000000FFFF0000FF
+      FF0000FFFF000000000000000000000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF0000FFFF000000FF000000000000000000FF000000FF0000000000
+      0000000000000000000000FFFF0000FFFF0000FFFF0000FFFF00000000000000
+      0000000000000000FF000000FF00000000000000000000FF000000FF00000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000FF000000FF0000000000000000000000FF000000FF00000000
+      00000000000000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000
+      00000000000000FF000000FF0000000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF0000FFFF0000000000000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF0000FFFF0000FFFF00000000000000000000FFFF0000FFFF0000FF
+      FF0000000000000000000000000000FFFF0000FFFF0000000000000000000000
+      000000FFFF0000FFFF0000FFFF000000000000000000000000000000000000FF
+      000000FF000000000000000000000000000000000000000000000000000000FF
+      000000FF000000000000000000000000000000000000000000000000000000FF
+      000000FF0000000000000000000000FFFF0000FFFF00000000000000000000FF
+      000000FF000000000000000000000000000000000000000000000000000000FF
+      FF0000FFFF000000000000000000000000000000000000FFFF0000FFFF0000FF
+      FF0000FFFF0000000000000000000000000000000000000000000000000000FF
+      FF0000FFFF00000000000000000000FFFF0000FFFF00000000000000000000FF
+      FF0000FFFF000000000000000000000000000000000000000000000000000000
+      00000000000000FF000000FF0000000000000000000000FF000000FF00000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000FF000000FF0000000000000000000000FF000000FF00000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000FF000000FF000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000FF000000FF000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000FFFF0000FFFF0000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000FFFF0000FFFF0000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000424D3E000000000000003E000000
+      2800000040000000400000000100010000000000000200000000000000000000
+      000000000000000000000000FFFFFF0000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000003FB03BF00FF000003FD037900FF0000
+      0200020100FF000003FD037F1F07000003FB03B91F07000003EF03E91F070000
+      03F703DF1F070000020303831F07000003F703DF1F07000003E803E81F070000
+      03B803B81F07000003D803781F070000020F02071F07000003D8037800FF0000
+      03B803B800FF000003F803F800FF00008001FFFFFFFF00008001A007A0070000
+      8001000200020000800100020002000080010002000200000000000200020000
+      0000000200020000800100020002000080010002000200008001000200020000
+      8001000200020000800100020002000080010002000200008001000200020000
+      8001A07FA07F00008001FFFFFFFF0000FE7FFE7FFE7FFE7FF81FF81FF81FF81F
+      E007E007E007E007800180018001800100000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000008001800180018001E007E007E007E007
+      F81FF81FF81FF81FFE7FFE7FFE7FFE7F00000000000000000000000000000000
+      000000000000}
+  end
+end
Index: /oup/releases/0.33a/Main.pas
===================================================================
--- /oup/releases/0.33a/Main.pas	(revision 76)
+++ /oup/releases/0.33a/Main.pas	(revision 76)
@@ -0,0 +1,640 @@
+unit Main;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, StrUtils, Clipbrd, ExtCtrls, ComCtrls, Menus, Grids,
+  MPHexEditor, ToolWin, ImgList, Tabs,
+  MDITab, TB2Item, TB2Dock, TB2Toolbar, TB2MDI,
+  Data, Functions, DataStructures, OniDataClass, Exporters,
+  Helper_LevelDB, Settings, Template,
+  BinEdit, Extractor, Preview, RawEdit, TxmpReplace;
+
+type
+  TForm_Main = class(TForm)
+    saved:      TSaveDialog;
+    opend:      TOpenDialog;
+    statbar:    TStatusBar;
+    MenuImages: TImageList;
+    DockTop:    TTBDock;
+    MainMenu:   TTBToolbar;
+    menu_main:  TTBSubmenuItem;
+    menu_loadfile: TTBItem;
+    menu_sep1:  TTBSeparatorItem;
+    menu_settings: TTBItem;
+    menu_sep4:  TTBSeparatorItem;
+    menu_exit:  TTBItem;
+    menu_convert: TTBSubmenuItem;
+    menu_createdb: TTBItem;
+    menu_createlvl: TTBItem;
+    menu_tools: TTBSubmenuItem;
+    menu_preview: TTBItem;
+    menu_binedit: TTBItem;
+    menu_rawedit: TTBItem;
+    menu_txmpreplace: TTBItem;
+    menu_extractor: TTBItem;
+    menu_filecompare: TTBItem;
+    menu_levelstructedit: TTBItem;
+    menu_windows: TTBSubmenuItem;
+    menu_windows_cascade: TTBItem;
+    menu_windows_tile: TTBItem;
+    menu_windows_closeall: TTBItem;
+    menu_sep3:  TTBSeparatorItem;
+    menu_windows_next: TTBItem;
+    menu_windows_previous: TTBItem;
+    menu_sep2:  TTBSeparatorItem;
+    menu_About: TTBItem;
+    Toolbar:    TTBToolbar;
+    tbOpen:     TTBItem;
+    DockLeft:   TTBDock;
+    DockRight:  TTBDock;
+    DockBottom: TTBDock;
+    MDIToolbar: TTBToolbar;
+    TBControlItem1: TTBControlItem;
+    MDITab:     TMDITab;
+    menu_view:  TTBSubmenuItem;
+    menu_view_mdibar: TTBItem;
+    menu_view_statusbar: TTBItem;
+    menu_view_toolbar: TTBItem;
+    tb_separator1: TTBSeparatorItem;
+    tb_preview: TTBItem;
+    tb_structure: TTBItem;
+    tb_compare: TTBItem;
+    tb_extractor: TTBItem;
+    tb_txmpreplacer: TTBItem;
+    tb_rawedit: TTBItem;
+    tb_datedit: TTBItem;
+    menu_windows_tilevert: TTBItem;
+    tb_meta: TTBItem;
+    menu_meta: TTBItem;
+    TBSeparatorItem1: TTBSeparatorItem;
+    tb_db2dat: TTBItem;
+    tb_dat2db: TTBItem;
+    menu_loaddb: TTBItem;
+    tb_opendb: TTBItem;
+    procedure LoadFile(typedb: Boolean);
+    function TryCloseAll: Boolean;
+    procedure menu_AboutClick(Sender: TObject);
+    procedure menu_settingsClick(Sender: TObject);
+    procedure menu_filecompareClick(Sender: TObject);
+    procedure menu_raweditClick(Sender: TObject);
+    procedure menu_createlvlClick(Sender: TObject);
+    procedure menu_extractorClick(Sender: TObject);
+    procedure menu_createdbClick(Sender: TObject);
+    procedure menu_windows_previousClick(Sender: TObject);
+    procedure menu_windows_nextClick(Sender: TObject);
+    procedure menu_windows_tileClick(Sender: TObject);
+    function open_child(window_context: String; fileid: Integer): TForm_ToolTemplate;
+    procedure menu_windows_closeallClick(Sender: TObject);
+    procedure menu_windows_cascadeClick(Sender: TObject);
+    procedure menu_bineditClick(Sender: TObject);
+    procedure menu_loadfileClick(Sender: TObject);
+    procedure menu_txmpreplaceClick(Sender: TObject);
+    procedure menu_exitClick(Sender: TObject);
+    procedure menu_previewClick(Sender: TObject);
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+    procedure FormResize(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+    procedure UpdateStatBar;
+    procedure menu_view_mdibarClick(Sender: TObject);
+    procedure menu_view_statusbarClick(Sender: TObject);
+    procedure menu_view_toolbarClick(Sender: TObject);
+    procedure MDITabDrawTab(Control: TCustomTabControl; TabIndex: Integer;
+      const Rect: TRect; Active: Boolean);
+    procedure ActivateTools(active: Boolean);
+    procedure MDITabMouseUp(Sender: TObject; Button: TMouseButton;
+      Shift: TShiftState; X, Y: Integer);
+    procedure menu_windows_tilevertClick(Sender: TObject);
+    procedure menu_metaClick(Sender: TObject);
+    procedure ToolbarDockChanged(Sender: TObject);
+    procedure menu_loaddbClick(Sender: TObject);
+  private
+  public
+  end;
+
+var
+  Form_Main: TForm_Main;
+
+implementation
+
+{$R *.dfm}
+
+
+
+procedure TForm_Main.FormCreate(Sender: TObject);
+begin
+  Self.Caption := 'Oni Un/Packer ' + version;
+  Self.FormResize(Self);
+
+  if FileExists(ExtractFilepath(Application.EXEname) + '\oniunpacker.ini') then
+  begin
+    AssignFile(AppSettingsFile, ExtractFilepath(Application.EXEname) +
+      '\oniunpacker.ini');
+    Reset(AppSettingsFile);
+    Read(AppSettingsFile, AppSettings);
+    CloseFile(AppSettingsFile);
+  end
+  else
+  begin
+    AppSettings.DatPath     := 'D:\Spiele\Oni\GameDataFolder';
+    AppSettings.ExtractPath := 'C:\Dokumente und Einstellungen\Administrator\Desktop';
+    AppSettings.FilenumbersAsHex := False;
+    AppSettings.CharSet     := DEFAULT_CHARSET;
+    AppSettings.HideUnusedData := False;
+  end;
+
+  if MidStr(ParamStr(1), 1, 3) = 'opf' then
+  begin
+    ShowMessage('Load OPF-File: ' + ParamStr(2));
+  end
+  else if MidStr(ParamStr(1), 1, 4) = 'oldb' then
+  begin
+    if not CreateDataConnection(ParamStr(2), ODB_ADB) then
+      ShowMessage('Error while loading the file:' + CrLf + ParamStr(
+        2) + CrLf + 'Perhaps not an OniUnPacker-LevelDatabase-file?');
+  end
+  else if MidStr(ParamStr(1), 1, 3) = 'dat' then
+  begin
+    if not CreateDataConnection(ParamStr(2), ODB_Dat) then
+      ShowMessage('Error while loading the file:' + CrLf + ParamStr(
+        2) + CrLf + 'Perhaps not an Oni-.dat-file?');
+  end;
+  UpdateStatBar;
+end;
+
+
+
+
+procedure TForm_Main.FormResize(Sender: TObject);
+const
+  MinWidth: Integer  = 750;
+  MinHeight: Integer = 500;
+begin
+  if Self.Width < MinWidth then
+    Self.Width := MinWidth;
+  if Self.Height < MinHeight then
+    Self.Height := MinHeight;
+  statbar.Panels.Items[0].Width := Self.Width - 200;
+  MDITab.Width := Self.Width - 20;
+end;
+
+
+
+
+procedure TForm_Main.MDITabDrawTab(Control: TCustomTabControl;
+  TabIndex: Integer; const Rect: TRect; Active: Boolean);
+var
+  x, y: Integer;
+  iconindex: Integer;
+  caption: String;
+begin
+  iconindex := TMDITab(Control).Glyphs[TabIndex];
+  caption := TMDITab(Control).Captions[TabIndex];
+  if active then
+  begin
+    Control.Canvas.Font.Style := Control.Canvas.Font.Style + [fsItalic];
+    y := Rect.Top + 1;
+  end else
+    y := Rect.Top;
+  if iconindex >= 0 then
+  begin
+    TMDITab(Control).Images.Draw(Control.Canvas, Rect.Left + 4, y, iconindex);
+    x := Rect.Left + 26;
+  end else
+    x := Rect.Left + 4;
+  Control.Canvas.TextOut(x, y + 2, caption);
+end;
+
+
+
+
+
+
+procedure TForm_Main.MDITabMouseUp(Sender: TObject; Button: TMouseButton;
+  Shift: TShiftState; X, Y: Integer);
+var
+  pt: TPoint;
+  index: Integer;
+begin
+  pt.X := X;
+  pt.Y := Y;
+  index := MDITab.GetTabAtPos(pt);
+  if (Button = mbRight) and (index >= 0) then
+    MDITab.MDIChildren[index].Close;
+end;
+
+procedure TForm_Main.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  AssignFile(AppSettingsFile, ExtractFilepath(Application.EXEname) + '\oniunpacker.ini');
+  if FileExists(ExtractFilepath(Application.EXEname) + '\oniunpacker.ini') then
+    Reset(AppSettingsFile)
+  else
+    Rewrite(AppSettingsFile);
+  Write(AppSettingsFile, AppSettings);
+  CloseFile(AppSettingsFile);
+  Action := caFree;
+end;
+
+
+
+procedure TForm_Main.ActivateTools(active: Boolean);
+begin
+  menu_tools.Enabled := active;
+  tb_preview.Enabled := active;
+  tb_datedit.Enabled := active;
+  tb_rawedit.Enabled := active;
+  tb_txmpreplacer.Enabled := active;
+  tb_extractor.Enabled := active;
+//  tb_compare.Enabled := active;
+//  tb_structure.Enabled := active;
+end;
+
+procedure TForm_Main.UpdateStatBar;
+begin
+  if Assigned(OniDataConnection) then
+  begin
+    Self.Caption      := 'Oni Un/Packer ' + version + ' (' + ExtractFileName(
+      OniDataConnection.FileName) + ')';
+    ActivateTools(True);
+    statbar.Panels.Items[1].Text := 'Files: ' + IntToStr(OniDataConnection.GetFilesCount);
+    statbar.Panels.Items[2].Text :=
+      'Extensions: ' + IntToStr(Length(OniDataConnection.GetExtensionsList));
+    case OniDataConnection.Backend of
+      ODB_Dat:
+        begin
+          statbar.Panels.Items[0].Text := '.dat loaded: ' + OniDataConnection.FileName;
+        end;
+      ODB_ADB:
+        begin
+          statbar.Panels.Items[0].Text := 'OLDB loaded: ' + OniDataConnection.FileName;
+        end;
+    else
+      Self.Caption      := 'Oni Un/Packer ' + version;
+      statbar.Panels.Items[0].Text := 'Nothing loaded';
+      statbar.Panels.Items[1].Text := 'Files: -';
+      statbar.Panels.Items[2].Text := 'Extensions: -';
+      ActivateTools(False);
+    end;
+  end
+  else
+  begin
+    Self.Caption      := 'Oni Un/Packer ' + version;
+    statbar.Panels.Items[0].Text := 'Nothing loaded';
+    statbar.Panels.Items[1].Text := 'Files: -';
+    statbar.Panels.Items[2].Text := 'Extensions: -';
+    ActivateTools(False);
+  end;
+end;
+
+
+
+
+procedure TForm_Main.ToolbarDockChanged(Sender: TObject);
+var
+  toolbar: TTBToolbar;
+  position: TTBDockPosition;
+  mode: TTBItemDisplayMode;
+  i: Integer;
+  isEnabled: Boolean;
+begin
+  toolbar := TTBToolbar(Sender);
+  if toolbar.Floating then
+    mode := nbdmImageAndText
+  else begin
+    position := toolbar.CurrentDock.Position;
+    if position in [dpLeft, dpRight] then
+      mode := nbdmDefault
+    else
+      mode := nbdmImageAndText;
+  end;
+  for i := 0 to toolbar.Items.Count - 1 do
+    toolbar.Items.Items[i].DisplayMode := mode;
+end;
+
+function TForm_Main.TryCloseAll: Boolean;
+begin
+  menu_windows_closeallClick(Self);
+  Application.ProcessMessages;
+  if MDITab.MDIChildCount = 0 then
+    Result := True
+  else
+    Result := False;
+end;
+
+
+
+procedure TForm_Main.LoadFile(typedb: Boolean);
+var
+  ext: String;
+begin
+  if TryCloseAll then
+  begin
+    CloseDataConnection;
+    opend.InitialDir := AppSettings.DatPath;
+    opend.Filter     := 'Compatible level files|*.dat;*.oldb|Oni level (*.dat)|*.dat|OUP level database (*.oldb)|*.oldb|Any (*.*)|*';
+    if typedb then
+      opend.FilterIndex := 3
+    else
+      opend.FilterIndex := 2;
+    if opend.Execute then
+    begin
+      ext := ExtractFileExt(opend.FileName);
+      if ext = '.dat' then
+      begin
+        if not CreateDataConnection(opend.FileName, ODB_Dat) then
+          ShowMessage('Error while loading the file:' + CrLf + opend.FileName +
+            CrLf + 'Perhaps not an Oni-.dat-file?');
+      end else if ext = '.oldb' then
+      begin
+        if not CreateDataConnection(opend.FileName, ODB_ADB) then
+          ShowMessage('Error while loading the file:' + CrLf + opend.FileName +
+            CrLf + 'Perhaps not an OniUnPacker-LevelDatabase-file?');
+      end else
+        ShowMessage('Incompatible file');
+      AppSettings.DatPath := ExtractFilepath(opend.FileName);
+    end;
+  end;
+  UpdateStatBar;
+end;
+
+
+ {#################################}
+ {##### Main-Menu-Handlers    #####}
+ {#################################}
+procedure TForm_Main.menu_loaddbClick(Sender: TObject);
+begin
+  LoadFile(True);
+end;
+
+procedure TForm_Main.menu_loadfileClick(Sender: TObject);
+begin
+  LoadFile(False);
+end;
+
+
+
+
+procedure TForm_Main.menu_settingsClick(Sender: TObject);
+begin
+  Form_Settings.Visible := True;
+  Self.Enabled   := False;
+end;
+
+
+
+
+procedure TForm_Main.menu_exitClick(Sender: TObject);
+begin
+  Self.Close;
+end;
+
+ {####################################}
+ {##### Converters-Menu-Handlers #####}
+ {####################################}
+procedure TForm_Main.menu_createdbClick(Sender: TObject);
+begin
+  if Assigned(OniDataConnection) then
+    if MessageBox(Self.Handle, PChar('You have currently opened a level-file. ' +
+          'Do you want to close it to continue?'), PChar('Close file?'),
+          MB_YESNO + MB_ICONQUESTION) = ID_NO then
+      Exit
+    else begin
+      if TryCloseAll then
+      begin
+        CloseDataConnection;
+        UpdateStatBar;
+      end else
+        Exit;
+    end;
+  opend.Filter     := 'Oni-Dat-Files|*.dat';
+  saved.Filter     := 'OUP-Level-DB (*.oldb)|*.oldb';
+  saved.DefaultExt := 'oldb';
+  if opend.Execute then
+    if saved.Execute then
+      Form_LevelDB.CreateDatabase(opend.FileName, saved.FileName);
+end;
+
+
+
+
+procedure TForm_Main.menu_createlvlClick(Sender: TObject);
+begin
+  if Assigned(OniDataConnection) then
+    if MessageBox(Self.Handle, PChar('You have currently opened a level-file. ' +
+          'Do you want to close it to continue?'), PChar('Close file?'),
+          MB_YESNO + MB_ICONQUESTION) = ID_NO then
+      Exit
+    else begin
+      if TryCloseAll then
+      begin
+        CloseDataConnection;
+        UpdateStatBar;
+      end else
+        Exit;
+    end;
+  opend.Filter     := 'OUP-Level-DB (*.oldb)|*.oldb';
+  saved.Filter     := 'Oni-Dat-Files|*.dat';
+  saved.DefaultExt := 'dat';
+  if opend.Execute then
+    if saved.Execute then
+      Form_LevelDB.CreateLevel(opend.FileName, saved.FileName);
+end;
+
+ {#################################}
+ {##### Tools-Menu-Handlers   #####}
+ {#################################}
+procedure TForm_Main.menu_previewClick(Sender: TObject);
+begin
+  open_child('preview', -1);
+end;
+
+
+procedure TForm_Main.menu_txmpreplaceClick(Sender: TObject);
+begin
+  open_child('txmpreplace', -1);
+end;
+
+
+procedure TForm_Main.menu_bineditClick(Sender: TObject);
+begin
+  open_child('binedit', -1);
+end;
+
+
+procedure TForm_Main.menu_raweditClick(Sender: TObject);
+begin
+  open_child('rawedit', -1);
+end;
+
+
+procedure TForm_Main.menu_extractorClick(Sender: TObject);
+begin
+  open_child('extractor', -1);
+end;
+
+
+procedure TForm_Main.menu_metaClick(Sender: TObject);
+begin
+  ShowMessage('TBD');
+end;
+
+
+procedure TForm_Main.menu_filecompareClick(Sender: TObject);
+begin
+  open_child('compare', -1);
+end;
+
+
+ {#################################}
+ {#####   View-Menu-Handlers  #####}
+ {#################################}
+procedure TForm_Main.menu_view_mdibarClick(Sender: TObject);
+begin
+  menu_view_mdibar.Checked := not menu_view_mdibar.Checked;
+  mditoolbar.Visible := menu_view_mdibar.Checked;
+end;
+
+
+
+
+procedure TForm_Main.menu_view_statusbarClick(Sender: TObject);
+begin
+  menu_view_statusbar.Checked := not menu_view_statusbar.Checked;
+  statbar.Visible := menu_view_statusbar.Checked;
+end;
+
+
+
+
+procedure TForm_Main.menu_view_toolbarClick(Sender: TObject);
+begin
+  menu_view_toolbar.Checked := not menu_view_toolbar.Checked;
+  Toolbar.Visible := menu_view_toolbar.Checked;
+end;
+
+
+
+ {#################################}
+ {#####  Window-Menu-Handlers #####}
+ {#################################}
+procedure TForm_Main.menu_windows_cascadeClick(Sender: TObject);
+begin
+  Self.Cascade;
+end;
+
+
+
+procedure TForm_Main.menu_windows_tileClick(Sender: TObject);
+begin
+  Self.TileMode := tbHorizontal;
+  Self.Tile;
+end;
+
+procedure TForm_Main.menu_windows_tilevertClick(Sender: TObject);
+begin
+  Self.TileMode := tbVertical;
+  Self.Tile;
+end;
+
+
+procedure TForm_Main.menu_windows_closeallClick(Sender: TObject);
+begin
+  MDITab.CloseAll;
+end;
+
+
+
+procedure TForm_Main.menu_windows_nextClick(Sender: TObject);
+begin
+  if MDIChildCount > 1 then
+    if MDITab.TabIndex = MDITab.MDIChildCount - 1 then
+      MDITab.MDIChildren[0].BringToFront
+    else
+      MDITab.MDIChildren[MDITab.TabIndex + 1].BringToFront;
+end;
+
+
+
+procedure TForm_Main.menu_windows_previousClick(Sender: TObject);
+begin
+  if MDIChildCount > 1 then
+    if MDITab.TabIndex = 0 then
+      MDITab.MDIChildren[MDITab.MDIChildCount - 1].BringToFront
+    else
+      MDITab.MDIChildren[MDITab.TabIndex - 1].BringToFront;
+end;
+
+
+
+
+
+
+procedure TForm_Main.menu_AboutClick(Sender: TObject);
+begin
+  ShowMessage('Will be implemented later ;)');
+end;
+
+
+
+
+function TForm_Main.open_child(window_context: String; fileid: Integer): TForm_ToolTemplate;
+var
+  toolform: TForm_ToolTemplate;
+  i:       Integer;
+  tag:     Integer;
+  iconindex: Integer;
+begin
+  Result := nil;
+
+  tag := 1;
+  if MDIChildCount > 0 then
+    for i := 0 to MDIChildCount - 1 do
+      if MDIChildren[i].Tag >= tag then
+        tag := MDIChildren[i].Tag + 1;
+
+  iconindex := -1;
+
+  if window_context = 'binedit' then
+  begin
+    toolform         := TForm_BinEdit.Create(Self);
+    toolform.Caption := 'Binary .dat-Editor ' + IntToStr(tag);
+    iconindex        := 5;
+  end;
+  if window_context = 'extractor' then
+  begin
+    toolform         := TForm_Extractor.Create(Self);
+    toolform.Caption := 'Extractor ' + IntToStr(tag);
+    iconindex        := 8;
+  end;
+  if window_context = 'preview' then
+  begin
+    toolform         := TForm_Preview.Create(Self);
+    toolform.Caption := 'Preview-Window ' + IntToStr(tag);
+    iconindex        := 4;
+  end;
+  if window_context = 'rawedit' then
+  begin
+    toolform         := TForm_RawEdit.Create(Self);
+    toolform.Caption := 'Binary .raw-Editor ' + IntToStr(tag);
+    iconindex        := 6;
+  end;
+  if window_context = 'txmpreplace' then
+  begin
+    toolform         := TForm_TxmpReplace.Create(Application);
+    toolform.Caption := 'TXMP Replacer ' + IntToStr(tag);
+    iconindex        := 7;
+  end;
+
+  if Assigned(toolform) then
+  begin
+    toolform.Name    := window_context + IntToStr(tag);
+    toolform.Tag     := tag;
+    MDITab.AddTab(TForm(toolform), iconindex);
+    if fileid > -1 then
+      toolform.SelectFileID(fileid);
+    Result := toolform;
+  end;
+end;
+
+end.
Index: /oup/releases/0.33a/OniUnPacker.bdsproj
===================================================================
--- /oup/releases/0.33a/OniUnPacker.bdsproj	(revision 76)
+++ /oup/releases/0.33a/OniUnPacker.bdsproj	(revision 76)
@@ -0,0 +1,182 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<BorlandProject>
+	<PersonalityInfo>
+		<Option>
+			<Option Name="Personality">Delphi.Personality</Option>
+			<Option Name="ProjectType"></Option>
+			<Option Name="Version">1.0</Option>
+			<Option Name="GUID">{5F594E8D-8185-4AC6-8191-2A0F26194CB4}</Option>
+		</Option>
+	</PersonalityInfo>
+	<Delphi.Personality>
+		<Source>
+			<Source Name="MainSource">OniUnPacker.dpr</Source>
+		</Source>
+		<FileVersion>
+			<FileVersion Name="Version">7.0</FileVersion>
+		</FileVersion>
+		<Compiler>
+			<Compiler Name="A">8</Compiler>
+			<Compiler Name="B">0</Compiler>
+			<Compiler Name="C">1</Compiler>
+			<Compiler Name="D">1</Compiler>
+			<Compiler Name="E">0</Compiler>
+			<Compiler Name="F">0</Compiler>
+			<Compiler Name="G">1</Compiler>
+			<Compiler Name="H">1</Compiler>
+			<Compiler Name="I">1</Compiler>
+			<Compiler Name="J">0</Compiler>
+			<Compiler Name="K">0</Compiler>
+			<Compiler Name="L">1</Compiler>
+			<Compiler Name="M">0</Compiler>
+			<Compiler Name="N">1</Compiler>
+			<Compiler Name="O">1</Compiler>
+			<Compiler Name="P">1</Compiler>
+			<Compiler Name="Q">0</Compiler>
+			<Compiler Name="R">0</Compiler>
+			<Compiler Name="S">0</Compiler>
+			<Compiler Name="T">0</Compiler>
+			<Compiler Name="U">0</Compiler>
+			<Compiler Name="V">1</Compiler>
+			<Compiler Name="W">0</Compiler>
+			<Compiler Name="X">1</Compiler>
+			<Compiler Name="Y">1</Compiler>
+			<Compiler Name="Z">1</Compiler>
+			<Compiler Name="ShowHints">True</Compiler>
+			<Compiler Name="ShowWarnings">True</Compiler>
+			<Compiler Name="UnitAliases">WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;</Compiler>
+			<Compiler Name="NamespacePrefix"></Compiler>
+			<Compiler Name="GenerateDocumentation">False</Compiler>
+			<Compiler Name="DefaultNamespace"></Compiler>
+			<Compiler Name="SymbolDeprecated">True</Compiler>
+			<Compiler Name="SymbolLibrary">True</Compiler>
+			<Compiler Name="SymbolPlatform">True</Compiler>
+			<Compiler Name="SymbolExperimental">True</Compiler>
+			<Compiler Name="UnitLibrary">True</Compiler>
+			<Compiler Name="UnitPlatform">True</Compiler>
+			<Compiler Name="UnitDeprecated">True</Compiler>
+			<Compiler Name="UnitExperimental">True</Compiler>
+			<Compiler Name="HResultCompat">True</Compiler>
+			<Compiler Name="HidingMember">True</Compiler>
+			<Compiler Name="HiddenVirtual">True</Compiler>
+			<Compiler Name="Garbage">True</Compiler>
+			<Compiler Name="BoundsError">True</Compiler>
+			<Compiler Name="ZeroNilCompat">True</Compiler>
+			<Compiler Name="StringConstTruncated">True</Compiler>
+			<Compiler Name="ForLoopVarVarPar">True</Compiler>
+			<Compiler Name="TypedConstVarPar">True</Compiler>
+			<Compiler Name="AsgToTypedConst">True</Compiler>
+			<Compiler Name="CaseLabelRange">True</Compiler>
+			<Compiler Name="ForVariable">True</Compiler>
+			<Compiler Name="ConstructingAbstract">True</Compiler>
+			<Compiler Name="ComparisonFalse">True</Compiler>
+			<Compiler Name="ComparisonTrue">True</Compiler>
+			<Compiler Name="ComparingSignedUnsigned">True</Compiler>
+			<Compiler Name="CombiningSignedUnsigned">True</Compiler>
+			<Compiler Name="UnsupportedConstruct">True</Compiler>
+			<Compiler Name="FileOpen">True</Compiler>
+			<Compiler Name="FileOpenUnitSrc">True</Compiler>
+			<Compiler Name="BadGlobalSymbol">True</Compiler>
+			<Compiler Name="DuplicateConstructorDestructor">True</Compiler>
+			<Compiler Name="InvalidDirective">True</Compiler>
+			<Compiler Name="PackageNoLink">True</Compiler>
+			<Compiler Name="PackageThreadVar">True</Compiler>
+			<Compiler Name="ImplicitImport">True</Compiler>
+			<Compiler Name="HPPEMITIgnored">True</Compiler>
+			<Compiler Name="NoRetVal">True</Compiler>
+			<Compiler Name="UseBeforeDef">True</Compiler>
+			<Compiler Name="ForLoopVarUndef">True</Compiler>
+			<Compiler Name="UnitNameMismatch">True</Compiler>
+			<Compiler Name="NoCFGFileFound">True</Compiler>
+			<Compiler Name="MessageDirective">True</Compiler>
+			<Compiler Name="ImplicitVariants">True</Compiler>
+			<Compiler Name="UnicodeToLocale">True</Compiler>
+			<Compiler Name="LocaleToUnicode">True</Compiler>
+			<Compiler Name="ImagebaseMultiple">True</Compiler>
+			<Compiler Name="SuspiciousTypecast">True</Compiler>
+			<Compiler Name="PrivatePropAccessor">True</Compiler>
+			<Compiler Name="UnsafeType">False</Compiler>
+			<Compiler Name="UnsafeCode">False</Compiler>
+			<Compiler Name="UnsafeCast">False</Compiler>
+			<Compiler Name="OptionTruncated">True</Compiler>
+			<Compiler Name="WideCharReduced">True</Compiler>
+			<Compiler Name="DuplicatesIgnored">True</Compiler>
+			<Compiler Name="UnitInitSeq">True</Compiler>
+			<Compiler Name="LocalPInvoke">True</Compiler>
+			<Compiler Name="CodePage"></Compiler>
+		</Compiler>
+		<Linker>
+			<Linker Name="MapFile">0</Linker>
+			<Linker Name="OutputObjs">0</Linker>
+			<Linker Name="ConsoleApp">1</Linker>
+			<Linker Name="DebugInfo">False</Linker>
+			<Linker Name="RemoteSymbols">False</Linker>
+			<Linker Name="GenerateDRC">False</Linker>
+			<Linker Name="MinStackSize">16384</Linker>
+			<Linker Name="MaxStackSize">1048576</Linker>
+			<Linker Name="ImageBase">4194304</Linker>
+			<Linker Name="ExeDescription"></Linker>
+			<Linker Name="GenerateHpps">False</Linker>
+		</Linker>
+		<Directories>
+			<Directories Name="OutputDir">exe</Directories>
+			<Directories Name="UnitOutputDir">dcu</Directories>
+			<Directories Name="PackageDLLOutputDir"></Directories>
+			<Directories Name="PackageDCPOutputDir"></Directories>
+			<Directories Name="SearchPath"></Directories>
+			<Directories Name="Packages">xmlrtl;rtl;vcl;vclie;inet;inetdbbde;inetdbxpress;vclx;IndySystem;IndyCore;dbrtl;dsnap;soaprtl;IndyProtocols;bdertl;vcldbx;vcldb;webdsnap;websnap;vclactnband;GridPackd2005;TWrapGrid;Package1;A406_R70;CoolTrayIcon_D6plus</Directories>
+			<Directories Name="Conditionals"></Directories>
+			<Directories Name="DebugSourceDirs"></Directories>
+			<Directories Name="UsePackages">False</Directories>
+		</Directories>
+		<Parameters>
+			<Parameters Name="RunParams"></Parameters>
+			<Parameters Name="HostApplication"></Parameters>
+			<Parameters Name="Launcher"></Parameters>
+			<Parameters Name="UseLauncher">False</Parameters>
+			<Parameters Name="DebugCWD"></Parameters>
+			<Parameters Name="RemoteHost"></Parameters>
+			<Parameters Name="RemotePath"></Parameters>
+			<Parameters Name="RemoteLauncher"></Parameters>
+			<Parameters Name="RemoteCWD"></Parameters>
+			<Parameters Name="RemoteDebug">False</Parameters>
+			<Parameters Name="Debug Symbols Search Path"></Parameters>
+			<Parameters Name="LoadAllSymbols">True</Parameters>
+			<Parameters Name="LoadUnspecifiedSymbols">False</Parameters>
+		</Parameters>
+		<VersionInfo>
+			<VersionInfo Name="IncludeVerInfo">False</VersionInfo>
+			<VersionInfo Name="AutoIncBuild">False</VersionInfo>
+			<VersionInfo Name="MajorVer">1</VersionInfo>
+			<VersionInfo Name="MinorVer">0</VersionInfo>
+			<VersionInfo Name="Release">0</VersionInfo>
+			<VersionInfo Name="Build">0</VersionInfo>
+			<VersionInfo Name="Debug">False</VersionInfo>
+			<VersionInfo Name="PreRelease">False</VersionInfo>
+			<VersionInfo Name="Special">False</VersionInfo>
+			<VersionInfo Name="Private">False</VersionInfo>
+			<VersionInfo Name="DLL">False</VersionInfo>
+			<VersionInfo Name="Locale">1031</VersionInfo>
+			<VersionInfo Name="CodePage">1252</VersionInfo>
+		</VersionInfo>
+		<VersionInfoKeys>
+			<VersionInfoKeys Name="CompanyName"></VersionInfoKeys>
+			<VersionInfoKeys Name="FileDescription"></VersionInfoKeys>
+			<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
+			<VersionInfoKeys Name="InternalName"></VersionInfoKeys>
+			<VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys>
+			<VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys>
+			<VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys>
+			<VersionInfoKeys Name="ProductName"></VersionInfoKeys>
+			<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
+			<VersionInfoKeys Name="Comments"></VersionInfoKeys>
+		</VersionInfoKeys>
+		<Language>
+			<Language Name="ActiveLang"></Language>
+			<Language Name="ProjectLang">$00000000</Language>
+			<Language Name="RootDir"></Language>
+		</Language>  <Excluded_Packages>
+      <Excluded_Packages Name="d:\programme\borland\bds\3.0\Bin\dbwebxprt.bpl">Borland Web Wizard Package</Excluded_Packages>
+    </Excluded_Packages>
+  </Delphi.Personality>
+</BorlandProject>
Index: /oup/releases/0.33a/OniUnPacker.cfg
===================================================================
--- /oup/releases/0.33a/OniUnPacker.cfg	(revision 76)
+++ /oup/releases/0.33a/OniUnPacker.cfg	(revision 76)
@@ -0,0 +1,40 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"exe"
+-N0"dcu"
+-LE"C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Borland Studio Projects\Bpl"
+-LN"C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Borland Studio Projects\Bpl"
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST
Index: /oup/releases/0.33a/OniUnPacker.dpr
===================================================================
--- /oup/releases/0.33a/OniUnPacker.dpr	(revision 76)
+++ /oup/releases/0.33a/OniUnPacker.dpr	(revision 76)
@@ -0,0 +1,35 @@
+program OniUnPacker;
+
+uses
+  Forms,
+  Main in 'Main.pas' {Form_Main},
+  Data in 'Data.pas',
+  Helper_LevelDB in 'Helper_LevelDB.pas' {Form_LevelDB},
+  Helper_ValueEdit in 'Helper_ValueEdit.pas' {Form_ValueEdit},
+  Settings in 'Settings.pas' {Form_Settings},
+  FTypeReg in 'FTypeReg.pas',
+  Functions in 'Code\Functions.pas',
+  Exporters in 'Code\Exporters.pas',
+  OniImgClass in 'Code\OniImgClass.pas',
+  DataStructures in 'Code\DataStructures.pas',
+  OniDataClass in 'Code\OniDataClass.pas',
+  Template in 'Tools\Template.pas' {Form_ToolTemplate},
+  Preview in 'Tools\Preview.pas' {Form_Preview},
+  BinEdit in 'Tools\BinEdit.pas' {Form_ToolTemplate2},
+  Extractor in 'Tools\Extractor.pas' {Form_ToolTemplate3},
+  RawEdit in 'Tools\RawEdit.pas' {Form_ToolTemplate4},
+  TxmpReplace in 'Tools\TxmpReplace.pas' {Form_ToolTemplate5},
+  FolderBrowser in 'Code\FolderBrowser.pas';
+
+{$R *.res}
+{$R ExtraIcos.res}
+
+begin
+  Application.Initialize;
+  Application.Title := 'Oni Un/Packer';
+  Application.CreateForm(TForm_Main, Form_Main);
+  Application.CreateForm(TForm_LevelDB, Form_LevelDB);
+  Application.CreateForm(TForm_ValueEdit, Form_ValueEdit);
+  Application.CreateForm(TForm_Settings, Form_Settings);
+  Application.Run;
+end.
Index: /oup/releases/0.33a/Settings.dfm
===================================================================
--- /oup/releases/0.33a/Settings.dfm	(revision 76)
+++ /oup/releases/0.33a/Settings.dfm	(revision 76)
@@ -0,0 +1,110 @@
+object Form_Settings: TForm_Settings
+  Left = 0
+  Top = 0
+  BorderStyle = bsToolWindow
+  Caption = 'Settings'
+  ClientHeight = 235
+  ClientWidth = 321
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poMainFormCenter
+  OnCloseQuery = FormCloseQuery
+  OnShow = FormShow
+  PixelsPerInch = 96
+  TextHeight = 13
+  object label_charset: TLabel
+    Left = 8
+    Top = 39
+    Width = 145
+    Height = 26
+    AutoSize = False
+    Caption = 'CharSet for displaying strings in ValueViewer/StructViewer:'
+    WordWrap = True
+  end
+  object check_filesashex: TCheckBox
+    Left = 8
+    Top = 8
+    Width = 145
+    Height = 17
+    Caption = 'Show filenumbers as Hex'
+    TabOrder = 0
+  end
+  object btn_ok: TButton
+    Left = 8
+    Top = 199
+    Width = 57
+    Height = 23
+    Caption = 'OK'
+    Default = True
+    TabOrder = 1
+    OnClick = btn_okClick
+  end
+  object btn_cancel: TButton
+    Left = 112
+    Top = 199
+    Width = 57
+    Height = 23
+    Cancel = True
+    Caption = 'Cancel'
+    TabOrder = 2
+    OnClick = btn_cancelClick
+  end
+  object combo_charset: TComboBox
+    Left = 160
+    Top = 40
+    Width = 156
+    Height = 21
+    Style = csDropDownList
+    ItemHeight = 13
+    ItemIndex = 0
+    TabOrder = 3
+    Text = 'default - 1'
+    Items.Strings = (
+      'default - 1'
+      'Arabic - 178'
+      'Baltic - 186'
+      'ChineseBig5 - 136'
+      'EastEurope - 238'
+      'Greek - 161'
+      'Russian - 204'
+      'Thai - 222'
+      'Turkish - 162')
+  end
+  object check_hideunused: TCheckBox
+    Left = 8
+    Top = 79
+    Width = 209
+    Height = 17
+    Caption = 'Hide "Unused" data in StructureViewer'
+    TabOrder = 4
+  end
+  object check_reg_dat: TCheckBox
+    Left = 8
+    Top = 118
+    Width = 180
+    Height = 17
+    Caption = 'Register .dat files with OUP'
+    TabOrder = 5
+  end
+  object check_reg_oldb: TCheckBox
+    Left = 8
+    Top = 141
+    Width = 180
+    Height = 17
+    Caption = 'Register .oldb files with OUP'
+    TabOrder = 6
+  end
+  object check_reg_opf: TCheckBox
+    Left = 8
+    Top = 164
+    Width = 180
+    Height = 17
+    Caption = 'Register .opf files with OUP'
+    TabOrder = 7
+  end
+end
Index: /oup/releases/0.33a/Settings.pas
===================================================================
--- /oup/releases/0.33a/Settings.pas	(revision 76)
+++ /oup/releases/0.33a/Settings.pas	(revision 76)
@@ -0,0 +1,203 @@
+unit Settings;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, StrUtils, Grids, Wrapgrid;
+
+type
+  TForm_Settings = class(TForm)
+    check_filesashex: TCheckBox;
+    btn_ok:     TButton;
+    btn_cancel: TButton;
+    label_charset: TLabel;
+    combo_charset: TComboBox;
+    check_hideunused: TCheckBox;
+    check_reg_dat: TCheckBox;
+    check_reg_oldb: TCheckBox;
+    check_reg_opf: TCheckBox;
+    procedure btn_cancelClick(Sender: TObject);
+    procedure btn_okClick(Sender: TObject);
+    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+    procedure FormShow(Sender: TObject);
+    function RegisterExtension(ext: String; iconindex: Integer; reg: Boolean): Integer;
+  private
+  public
+  end;
+
+var
+  Form_Settings: TForm_Settings;
+
+implementation
+
+{$R *.dfm}
+
+uses
+  Main, Data, FTypeReg;
+
+
+
+
+function ExtensionRegistered(ext: String; var RegisteredAs: String): Boolean;
+var
+  ftr: TFileTypeRegistration;
+begin
+  ftr := TFileTypeRegistration.Create;
+  if (ftr <> nil) then
+  begin
+    try
+      RegisteredAs := ftr.GetInternalKey(ext);
+      if RegisteredAs <> '' then
+        Result := True
+      else
+        Result := False;
+    finally
+      ftr.Free;
+    end;
+  end;
+end;
+
+
+
+
+function TForm_Settings.RegisterExtension(ext: String; iconindex: Integer; reg: Boolean): Integer;
+var
+  ftr:     TFileTypeRegistration;
+  temps:   String;
+  warnmsg: String;
+begin
+  Result := -1;
+  ftr := TFileTypeRegistration.Create;
+  if reg then
+  begin
+    if ExtensionRegistered(ext, temps) then
+      if not ftr.UnregisterExtension(ext) then
+        ShowMessage('Could not unregister ' + ext + '-files');
+    if ftr.RegisterType(ext, 'ONI' + ext, 'ONI ' + ext + '-file', Application.EXEname, iconindex) then
+    begin
+      ftr.AddHandler('open', '"' + Application.EXEname + '" ' + MidStr(
+        ext, 2, Length(ext) - 1) + ' "%1"');
+      ftr.SetDefaultHandler;
+    end;
+  end else begin
+    if ExtensionRegistered(ext, temps) then
+      if not ftr.UnregisterExtension(ext) then
+        ShowMessage('Could not unregister ' + ext + '-files');
+  end;
+  ftr.Free;
+end;
+
+
+
+
+procedure TForm_Settings.btn_cancelClick(Sender: TObject);
+begin
+  Self.Close;
+end;
+
+
+
+
+procedure TForm_Settings.btn_okClick(Sender: TObject);
+var
+  temps: String;
+begin
+  AppSettings.FilenumbersAsHex := check_filesashex.Checked;
+  AppSettings.CharSet := StrToInt(
+    MidStr(combo_charset.Items.Strings[combo_charset.ItemIndex], Pos(
+    ' ', combo_charset.Items.Strings[combo_charset.ItemIndex]) + 3, Length(
+    combo_charset.Items.Strings[combo_charset.ItemIndex]) - Pos(
+    ' ', combo_charset.Items.Strings[combo_charset.ItemIndex]) - 2));
+  AppSettings.HideUnusedData := check_hideunused.Checked;
+
+  if check_reg_dat.Checked then
+  begin
+    if ExtensionRegistered('.dat', temps) then
+    begin
+      if temps <> 'ONI.dat' then
+        if MessageBox(Self.Handle, PChar('.dat-files already registered to "' +
+              temps+'". Reregister?'), PChar('Reregister?'),
+              MB_YESNO + MB_ICONQUESTION) = ID_YES then
+          RegisterExtension('.dat', 2, True);
+    end else
+      RegisterExtension('.dat', 2, True);
+  end else
+    RegisterExtension('.dat', 2, False);
+
+  if check_reg_oldb.Checked then
+  begin
+    if ExtensionRegistered('.oldb', temps) then
+    begin
+      if temps <> 'ONI.oldb' then
+        if MessageBox(Self.Handle, PChar('.oldb-files already registered to "' +
+              temps+'". Reregister?'), PChar('Reregister?'),
+              MB_YESNO + MB_ICONQUESTION) = ID_YES then
+          RegisterExtension('.oldb', 1, True);
+    end else
+      RegisterExtension('.oldb', 1, True);
+  end else
+    RegisterExtension('.oldb', 1, False);
+
+  if check_reg_opf.Checked then
+  begin
+    if ExtensionRegistered('.opf', temps) then
+    begin
+      if temps <> 'ONI.opf' then
+        if MessageBox(Self.Handle, PChar('.opf-files already registered to "' +
+              temps+'". Reregister?'), PChar('Reregister?'),
+              MB_YESNO + MB_ICONQUESTION) = ID_YES then
+          RegisterExtension('.opf', 0, True);
+    end else
+      RegisterExtension('.opf', 0, True);
+  end else
+    RegisterExtension('.opf', 0, False);
+
+  Self.Close;
+end;
+
+
+
+
+procedure TForm_Settings.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+  CanClose      := False;
+  Self.Visible  := False;
+  Form_Main.Enabled := True;
+  Form_Main.SetFocus;
+end;
+
+
+
+
+procedure TForm_Settings.FormShow(Sender: TObject);
+var
+  temps: String;
+  i:     Byte;
+begin
+  if ExtensionRegistered('.dat', temps) then
+    check_reg_dat.Checked := temps = 'ONI.dat'
+  else
+    check_reg_dat.Checked := False;
+
+  if ExtensionRegistered('.oldb', temps) then
+    check_reg_oldb.Checked := temps = 'ONI.oldb'
+  else
+    check_reg_oldb.Checked := False;
+
+  if ExtensionRegistered('.opf', temps) then
+    check_reg_opf.Checked := temps = 'ONI.opf'
+  else
+    check_reg_opf.Checked := False;
+
+  check_filesashex.Checked := AppSettings.FilenumbersAsHex;
+  check_hideunused.Checked := AppSettings.HideUnusedData;
+
+  for i := 0 to combo_charset.Items.Count - 1 do
+    if StrToInt(MidStr(combo_charset.Items.Strings[i], Pos(
+      ' ', combo_charset.Items.Strings[i]) + 3, Length(combo_charset.Items.Strings[i]) -
+      Pos(' ', combo_charset.Items.Strings[i]) - 2)) = AppSettings.CharSet then
+      combo_charset.ItemIndex := i;
+end;
+
+end.
Index: /oup/releases/0.33a/Tools/BinEdit.dfm
===================================================================
--- /oup/releases/0.33a/Tools/BinEdit.dfm	(revision 76)
+++ /oup/releases/0.33a/Tools/BinEdit.dfm	(revision 76)
@@ -0,0 +1,225 @@
+inherited Form_BinEdit: TForm_BinEdit
+  Caption = 'BinEdit'
+  KeyPreview = True
+  OnCloseQuery = FormCloseQuery
+  OnKeyUp = FormKeyUp
+  ExplicitWidth = 500
+  ExplicitHeight = 450
+  PixelsPerInch = 96
+  TextHeight = 13
+  inherited content: TPanel
+    object Splitter2: TSplitter
+      Left = 0
+      Top = 209
+      Width = 283
+      Height = 9
+      Cursor = crVSplit
+      Align = alTop
+      AutoSnap = False
+      Beveled = True
+      MinSize = 40
+      ExplicitWidth = 425
+    end
+    object Splitter3: TSplitter
+      Left = 0
+      Top = 318
+      Width = 283
+      Height = 8
+      Cursor = crVSplit
+      Align = alBottom
+      AutoSnap = False
+      Beveled = True
+      MinSize = 40
+      ExplicitLeft = -9
+      ExplicitTop = 430
+      ExplicitWidth = 425
+    end
+    object hex: TMPHexEditor
+      Left = 0
+      Top = 0
+      Width = 283
+      Height = 209
+      Cursor = crIBeam
+      Align = alTop
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -16
+      Font.Name = 'Courier'
+      Font.Style = []
+      OnKeyUp = hexKeyUp
+      ParentFont = False
+      TabOrder = 0
+      BytesPerRow = 16
+      Translation = tkASCII
+      OffsetFormat = '6!10:0x|'
+      Colors.Background = clWindow
+      Colors.ChangedBackground = clWindow
+      Colors.ChangedText = clRed
+      Colors.CursorFrame = clNavy
+      Colors.Offset = clBlack
+      Colors.OddColumn = clBlue
+      Colors.EvenColumn = clNavy
+      Colors.CurrentOffsetBackground = clBtnShadow
+      Colors.OffsetBackGround = clBtnFace
+      Colors.CurrentOffset = clBtnHighlight
+      Colors.Grid = clBtnFace
+      Colors.NonFocusCursorFrame = clAqua
+      Colors.ActiveFieldBackground = clWindow
+      FocusFrame = True
+      NoSizeChange = True
+      AllowInsertMode = False
+      DrawGridLines = False
+      Version = 'May 23, 2005; '#169' markus stephany, vcl[at]mirkes[dot]de'
+      OnChange = hexChange
+      ShowPositionIfNotFocused = True
+      OnSelectionChanged = hexSelectionChanged
+    end
+    object value_viewer: TWrapGrid
+      Left = 0
+      Top = 218
+      Width = 283
+      Height = 100
+      Align = alClient
+      ColCount = 1
+      DefaultColWidth = 80
+      DefaultRowHeight = 18
+      FixedCols = 0
+      RowCount = 8
+      FixedRows = 0
+      Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goColSizing]
+      PopupMenu = value_viewer_context
+      TabOrder = 1
+      OnDblClick = value_viewerDblClick
+      OnMouseDown = value_viewerMouseDown
+    end
+    object VST: TVirtualStringTree
+      Left = 0
+      Top = 326
+      Width = 283
+      Height = 97
+      Align = alBottom
+      AnimationDuration = 0
+      AutoExpandDelay = 300
+      BiDiMode = bdLeftToRight
+      Colors.UnfocusedSelectionColor = clGradientActiveCaption
+      Colors.UnfocusedSelectionBorderColor = clGradientActiveCaption
+      Ctl3D = True
+      DragOperations = []
+      DrawSelectionMode = smBlendedRectangle
+      EditDelay = 200
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -11
+      Font.Name = 'Tahoma'
+      Font.Style = []
+      Header.AutoSizeIndex = 0
+      Header.Font.Charset = DEFAULT_CHARSET
+      Header.Font.Color = clWindowText
+      Header.Font.Height = -11
+      Header.Font.Name = 'Tahoma'
+      Header.Font.Style = []
+      Header.Options = [hoColumnResize, hoDblClickResize, hoDrag, hoVisible]
+      Header.PopupMenu = VTHPopup
+      Header.Style = hsFlatButtons
+      HintAnimation = hatNone
+      HintMode = hmTooltip
+      Indent = 14
+      ParentBiDiMode = False
+      ParentCtl3D = False
+      ParentFont = False
+      ParentShowHint = False
+      ShowHint = True
+      TabOrder = 2
+      TreeOptions.MiscOptions = [toAcceptOLEDrop, toCheckSupport, toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning]
+      TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toShowHorzGridLines, toShowRoot, toShowTreeLines, toShowVertGridLines, toUseBlendedImages]
+      TreeOptions.SelectionOptions = [toExtendedFocus, toFullRowSelect, toRightClickSelect]
+      OnDblClick = VSTDblClick
+      OnFocusChanged = VSTFocusChanged
+      OnGetText = VSTGetText
+      OnHeaderDragged = VSTHeaderDragged
+      Columns = <
+        item
+          MaxWidth = 300
+          MinWidth = 100
+          Options = [coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 0
+          Spacing = 20
+          Width = 150
+          WideText = 'Name'
+          WideHint = 'Name of the item.'
+        end
+        item
+          MaxWidth = 110
+          MinWidth = 80
+          Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 1
+          Spacing = 20
+          Width = 85
+          WideText = 'Offset'
+          WideHint = 'Offset of the data-item.'
+        end
+        item
+          MaxWidth = 110
+          MinWidth = 75
+          Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 2
+          Width = 75
+          WideText = 'Type'
+          WideHint = 'Data type of the item.'
+        end
+        item
+          MaxWidth = 250
+          MinWidth = 80
+          Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 3
+          Width = 100
+          WideText = 'Value'
+          WideHint = 'Value of the item.'
+        end
+        item
+          MaxWidth = 400
+          MinWidth = 80
+          Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 4
+          Width = 400
+          WideText = 'Description'
+        end>
+      WideDefaultText = ''
+    end
+  end
+  object value_viewer_context: TPopupMenu [3]
+    AutoHotkeys = maManual
+    OnPopup = value_viewer_contextPopup
+    Left = 280
+    Top = 232
+    object value_viewer_context_copy: TMenuItem
+      Caption = 'Copy to &clipboard'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasdec: TMenuItem
+      Caption = 'Copy to clipboard (as &dec)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasfloat: TMenuItem
+      Caption = 'Copy to clipboard (as &float)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasbitset: TMenuItem
+      Caption = 'Copy to clipboard (as &bitset)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasstring: TMenuItem
+      Caption = 'Copy to clipboard (as &string)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyashex: TMenuItem
+      Caption = 'Copy to clipboard (as &hex)'
+      OnClick = value_viewer_context_copyClick
+    end
+  end
+  object VTHPopup: TVTHeaderPopupMenu [4]
+    OnColumnChange = VTHPopupColumnChange
+    Left = 272
+    Top = 376
+  end
+end
Index: /oup/releases/0.33a/Tools/BinEdit.pas
===================================================================
--- /oup/releases/0.33a/Tools/BinEdit.pas	(revision 76)
+++ /oup/releases/0.33a/Tools/BinEdit.pas	(revision 76)
@@ -0,0 +1,983 @@
+unit BinEdit;
+interface
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, Template, StdCtrls, ExtCtrls, VirtualTrees, Grids, Wrapgrid,
+  MPHexEditor, VTHeaderPopup, Menus, StrUtils, Clipbrd,
+  Data, OniDataClass, Functions, DataStructures, Exporters, Buttons;
+
+type
+  TForm_BinEdit = class(TForm_ToolTemplate)
+    hex: TMPHexEditor;
+    Splitter2: TSplitter;
+    value_viewer: TWrapGrid;
+    VST: TVirtualStringTree;
+    Splitter3: TSplitter;
+    value_viewer_context: TPopupMenu;
+    value_viewer_context_copy: TMenuItem;
+    value_viewer_context_copyasdec: TMenuItem;
+    value_viewer_context_copyasfloat: TMenuItem;
+    value_viewer_context_copyasbitset: TMenuItem;
+    value_viewer_context_copyasstring: TMenuItem;
+    value_viewer_context_copyashex: TMenuItem;
+    VTHPopup: TVTHeaderPopupMenu;
+    procedure FormCreate(Sender: TObject);
+    procedure NewFile(fileinfo: TFileInfo);
+
+    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+
+    procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+    procedure hexSelectionChanged(Sender: TObject);
+    procedure hexChange(Sender: TObject);
+
+    procedure LoadDat(_fileid: LongWord);
+    function Save: Boolean;
+    function GetValue(datatype: Word; offset: LongWord): String;
+    procedure SetNewValue(datatype: Word; offset: LongWord; Value: String);
+
+    procedure WriteStructureInfos;
+    procedure ClearStructViewer;
+    procedure VSTDblClick(Sender: TObject);
+    procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
+      Column: TColumnIndex);
+    procedure VTHPopupColumnChange(const Sender: TBaseVirtualTree;
+      const Column: TColumnIndex; Visible: Boolean);
+    procedure VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
+      OldPosition: Integer);
+    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
+      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
+
+    procedure ClearValues;
+    procedure WriteValues;
+    procedure value_viewerDblClick(Sender: TObject);
+    procedure value_viewer_context_copyClick(Sender: TObject);
+    procedure value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
+      Shift: TShiftState; X, Y: Integer);
+    procedure value_viewer_contextPopup(Sender: TObject);
+  private
+    fileid: LongWord;
+  public
+  end;
+
+var
+  Form_BinEdit: TForm_BinEdit;
+
+implementation
+
+uses Helper_ValueEdit, Main, RawEdit;
+{$R *.dfm}
+
+type
+  PNodeData = ^TNodeData;
+
+  TNodeData = record
+    Caption:  String;
+    Offset:   LongInt;
+    DataType: Word;
+    Value:    String;
+    Description: String;
+  end;
+
+
+
+procedure TForm_BinEdit.FormCreate(Sender: TObject);
+begin
+  inherited;
+  Self.OnNewFileSelected := NewFile;
+
+  Self.Caption := '';
+  fileid     := 0;
+  VST.NodeDataSize := SizeOf(TNodeData);
+  value_viewer.ColCount := 2;
+  value_viewer.RowCount := 8;
+  value_viewer.FixedRows := 1;
+  value_viewer.Cells[0, 0] := 'Type';
+  value_viewer.Cells[1, 0] := 'Value';
+  value_viewer.Cells[0, 1] := '1 byte, unsigned';
+  value_viewer.Cells[0, 2] := '2 bytes, unsigned';
+  value_viewer.Cells[0, 3] := '4 bytes, unsigned';
+  value_viewer.Cells[0, 4] := 'Bitset';
+  value_viewer.Cells[0, 5] := 'Float';
+  value_viewer.Cells[0, 6] := 'String';
+  value_viewer.Cells[0, 7] := 'Selected length';
+//  value_viewer.ColWidths[0] := 100;
+//  value_viewer.ColWidths[1] := value_viewer.Width - 150;
+//  hex.Height := content.Height - 215;
+  //
+  value_viewer.Font.Charset := AppSettings.CharSet;
+  VST.Font.Charset := AppSettings.CharSet;
+  hex.Translation := tkAsIs;
+  hex.Font.Charset := AppSettings.CharSet;
+  //
+end;
+
+procedure TForm_BinEdit.NewFile(fileinfo: TFileInfo);
+begin
+  LoadDat(fileinfo.ID);
+end;
+
+
+
+
+function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
+  ARecord: TNodeData): PVirtualNode;
+var
+  Data: PNodeData;
+begin
+  Result := AVST.AddChild(ANode);
+  Data   := AVST.GetNodeData(Result);
+  AVST.ValidateNode(Result, False);
+  Data^ := ARecord;
+end;
+
+
+
+
+procedure TForm_BinEdit.LoadDat(_fileid: LongWord);
+var
+  mem:  TMemoryStream;
+  Data: Tdata;
+begin
+  if hex.Modified then
+  begin
+    if not Save then
+    begin
+      Self.SelectFileID(fileid);
+      Exit;
+    end;
+  end;
+  fileid := _fileid;
+  if OniDataConnection.ExtractFileID(
+        filelist.Items.Strings[filelist.ItemIndex]) <> fileid then
+    Self.SelectFileID(fileid);
+  Self.ClearStructViewer;
+  Data := OniDataConnection.LoadDatFile(fileid);
+  if Length(Data) > 0 then
+  begin
+    mem := TMemoryStream.Create;
+    mem.Write(Data[0], Length(Data));
+    mem.Seek(0, soFromBeginning);
+    hex.LoadFromStream(mem);
+    mem.Free;
+    WriteStructureInfos;
+  end
+  else
+  begin
+    ClearValues;
+    hex.DataSize := 0;
+  end;
+end;
+
+
+
+
+function IntToBin(Value: Byte): String;
+var
+  i: Byte;
+begin
+  Result := '';
+  for i := 7 downto 0 do
+  begin
+    Result := Result + IntToStr((Value shr i) and $01);
+  end;
+end;
+
+
+
+
+function TForm_BinEdit.GetValue(datatype: Word; offset: LongWord): String;
+var
+  Data: Tdata;
+  i:    Word;
+  floatformat: TFormatSettings;
+begin
+  floatformat.DecimalSeparator := '.';
+  case datatype of
+    1:
+      Result := IntToStr(hex.Data[offset]);
+    2:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
+    3:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
+    4:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
+        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
+    5:
+      Result := '0x' + IntToHex(hex.Data[offset], 2);
+    6:
+      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256, 4);
+    7:
+      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
+        hex.Data[offset + 2] * 256 * 256, 6);
+    8:
+      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
+        hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8);
+    9:
+    begin
+      SetLength(Data, 4);
+      Data[0] := hex.Data[offset];
+      Data[1] := hex.Data[offset + 1];
+      Data[2] := hex.Data[offset + 2];
+      Data[3] := hex.Data[offset + 3];
+      Result  := FloatToStr(Decode_Float(Data), floatformat);
+    end;
+    10:
+      Result := IntToBin(hex.Data[offset]);
+    11:
+      Result := '0x' + IntToHex(OniDataConnection.GetRawInfo(fileid, offset).raw_addr, 8);
+    12:
+      Result := FormatNumber(hex.Data[offset + 1] + hex.Data[offset + 2] * 256 +
+        hex.Data[offset + 3] * 256 * 256, 5, '0');
+    13:
+      Result := IntToStr(hex.Data[offset]);
+    14:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
+    15:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
+    16:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
+        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
+    17:
+      Result := IntToStr((hex.Data[offset + 3]) div 2);
+    100..300:
+    begin
+      Result := '';
+      for i := 1 to datatype - 100 do
+      begin
+        if hex.Data[offset + i - 1] >= 32 then
+          Result := Result + Chr(hex.Data[offset + i - 1])
+        else
+          Break;
+      end;
+    end;
+    1000..9999:
+    begin
+      Result := '';
+      for i := 1 to datatype - 1000 do
+      begin
+        if hex.Data[offset + i - 1] >= 32 then
+          Result := Result + Chr(hex.Data[offset + i - 1])
+        else
+          Result := Result + '.';
+      end;
+    end;
+    10000..65535:
+    begin
+      Result := '';
+      for i := 1 to datatype - 10000 do
+      begin
+        if hex.Data[offset + i - 1] >= 32 then
+          Result := Result + Chr(hex.Data[offset + i - 1])
+        else
+          Result := Result + '.';
+      end;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.WriteStructureInfos;
+var
+  i, j:    LongWord;
+  pdata:   PNodeData;
+  Data:    TNodeData;
+  node:    PVirtualNode;
+  structs: TStructDef;
+begin
+  VST.BeginUpdate;
+  if VST.RootNodeCount = 0 then
+  begin
+    structs := LoadStructureDefinition(fileid);
+    if structs.Data then
+    begin
+      if Length(structs.Global) > 0 then
+      begin
+        for i := 0 to High(structs.Global) do
+        begin
+          Data.Caption  := structs.Global[i].Name;
+          Data.Offset   := structs.Global[i].offset;
+          Data.DataType := structs.Global[i].datatype;
+          Data.Value    := GetValue(structs.Global[i].datatype, structs.Global[i].offset);
+          Data.Description := structs.Global[i].description;
+          AddVSTEntry(VST, nil, Data);
+        end;
+      end;
+      if Length(structs.Subs) > 0 then
+      begin
+        for i := 0 to High(structs.Subs) do
+        begin
+          with structs.Subs[i] do
+          begin
+            if Length(Entries) > 0 then
+            begin
+              if Pos('#', SubName) > 0 then
+              begin
+                Data.Offset  := HexToLong(MidStr(SubName, Pos('#', SubName) + 1, 8));
+                Data.Value   :=
+                  MidStr(SubName, PosEx('#', SubName, Pos('#', SubName) + 1) + 1, 8);
+                Data.Caption := MidStr(SubName, 1, Pos('#', SubName) - 1);
+                Data.Description := SubDesc;
+              end
+              else
+              begin
+                Data.Caption := SubName;
+                Data.Description := SubDesc;
+                Data.Offset := 0;
+                Data.Value := '';
+              end;
+              Data.DataType := 0;
+              node := AddVSTEntry(VST, nil, Data);
+              Data.Description := '';
+              for j := 0 to High(Entries) do
+              begin
+                Data.Caption  := Entries[j].Name;
+                Data.Offset   := Entries[j].offset;
+                Data.DataType := Entries[j].datatype;
+                Data.Value    := GetValue(Entries[j].datatype, Entries[j].offset);
+                Data.Description := Entries[j].description;
+                AddVSTEntry(VST, node, Data);
+              end;
+            end;
+          end;
+        end;
+      end;
+    end;
+    if VST.RootNodeCount > 0 then
+      VST.FocusedNode := VST.GetFirst;
+  end
+  else
+  begin
+    Node := VST.GetFirst;
+    while Assigned(Node) do
+    begin
+      pdata := VST.GetNodeData(Node);
+      if pdata.DataType > 0 then
+        pdata.Value := GetValue(pdata.Datatype, pdata.Offset);
+      Node := VST.GetNext(Node);
+    end;
+  end;
+  VST.EndUpdate;
+end;
+
+
+
+
+procedure TForm_BinEdit.ClearValues;
+var
+  i: Byte;
+begin
+  for i := 1 to value_viewer.RowCount - 1 do
+  begin
+    value_viewer.Cells[1, i] := '';
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.WriteValues;
+var
+  i, j:  Byte;
+  Data:  Tdata;
+  str:   String;
+  Value: LongWord;
+  floatformat: TFormatSettings;
+begin
+  floatformat.DecimalSeparator := '.';
+  for i := 1 to value_viewer.RowCount - 1 do
+  begin
+    if value_viewer.Cells[0, i] = '1 byte, unsigned' then
+    begin
+      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 1) > hex.DataSize) then
+      begin
+        Value := hex.Data[hex.SelStart];
+        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 2);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = '2 bytes, unsigned' then
+    begin
+      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 2) > hex.DataSize) then
+      begin
+        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
+        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 4);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = '4 bytes, unsigned' then
+    begin
+      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 4) > hex.DataSize) then
+      begin
+        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
+          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
+        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 8);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = 'Bitset' then
+    begin
+      if (hex.SelCount <= 8) then
+      begin
+        if hex.SelCount = 0 then
+        begin
+          SetLength(Data, 1);
+          Data[0] := hex.Data[hex.SelStart];
+        end
+        else
+        begin
+          SetLength(Data, hex.SelCount);
+          for j := 0 to hex.SelCount - 1 do
+            Data[j] := hex.Data[hex.SelStart + j];
+        end;
+        value_viewer.Cells[1, i] := DataToBin(Data);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = 'Float' then
+    begin
+      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 4) > hex.DataSize) then
+      begin
+        SetLength(Data, 4);
+        for j := 0 to 3 do
+          Data[j] := hex.Data[hex.SelStart + j];
+        value_viewer.Cells[1, i] := FloatToStr(Decode_Float(Data), floatformat);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = 'Selected length' then
+    begin
+      value_viewer.Cells[1, i] := IntToStr(hex.SelCount) + ' bytes';
+    end;
+    if value_viewer.Cells[0, i] = 'String' then
+    begin
+      j   := 0;
+      str := '';
+      if hex.SelCount = 0 then
+      begin
+        while (hex.Data[hex.SelStart + j] > 0) and ((hex.SelStart + j) < hex.DataSize) do
+        begin
+          if hex.Data[hex.selstart + j] >= 32 then
+            str := str + Char(hex.Data[hex.SelStart + j])
+          else
+            str := str + '.';
+          Inc(j);
+        end;
+      end
+      else
+      begin
+        for j := 0 to hex.SelCount - 1 do
+          if hex.Data[hex.selstart + j] >= 32 then
+            str := str + Char(hex.Data[hex.SelStart + j])
+          else if hex.Data[hex.selstart + j] > 0 then
+            str := str + '.'
+          else
+            Break;
+      end;
+      value_viewer.Cells[1, i] := str;
+    end;
+  end;
+end;
+
+
+
+
+function TForm_BinEdit.Save: Boolean;
+var
+  mem:  TMemoryStream;
+  Data: Tdata;
+  i:    LongWord;
+begin
+  case MessageBox(Self.Handle, PChar('Save changes to file ' +
+      OniDataConnection.GetFileInfo(fileid).FileName + '?'), PChar('Data changed...'),
+      MB_YESNOCANCEL) of
+    idYes:
+    begin
+      mem := TMemoryStream.Create;
+      hex.SaveToStream(mem);
+      mem.Seek(0, soFromBeginning);
+      SetLength(Data, mem.Size);
+      mem.Read(Data[0], mem.Size);
+      mem.Free;
+      OniDataConnection.UpdateDatFile(fileid, Data);
+      hex.Modified := False;
+      for i := 0 to hex.Datasize - 1 do
+        hex.ByteChanged[i] := False;
+      Result := True;
+    end;
+    idNo:
+      Result := True;
+    idCancel:
+    begin
+      Result := False;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+  if hex.Modified then
+  begin
+    if not Save then
+      CanClose := False;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.ClearStructViewer;
+begin
+  VST.Clear;
+end;
+
+
+
+
+
+
+procedure TForm_BinEdit.hexChange(Sender: TObject);
+begin
+  ClearValues;
+  if hex.DataSize > 0 then
+  begin
+    WriteStructureInfos;
+    WriteValues;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+//var
+//  temps: String;
+begin
+  if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+  begin
+    if hex.SelCount > 0 then
+    begin
+      if hex.InCharField then
+        Clipboard.AsText := hex.SelectionAsText
+      else
+        Clipboard.AsText := hex.SelectionAsHex;
+    end;
+  end;
+  if (Shift = [ssCtrl]) and (Key = Ord('V')) then
+  begin
+{      temps:=Clipboard.AsText;
+      IF hex.SelStart+Length(temps)>hex.DataSize THEN
+        SetLength(temps, hex.DataSize-hex.SelStart);
+      hex.Sel
+      hex.SelCount:=Length(temps);
+      hex.ReplaceSelection(temps,Length(temps));
+}    end;
+end;
+
+
+
+
+procedure TForm_BinEdit.hexSelectionChanged(Sender: TObject);
+var
+  selstart: Integer;
+  node:     PVirtualNode;
+  pdata:    PNodeData;
+begin
+  if hex.DataSize > 0 then
+  begin
+    WriteValues;
+    selstart := hex.SelStart;
+    if VST.RootNodeCount > 0 then
+    begin
+      Node := VST.GetFirst;
+      while Assigned(Node) do
+      begin
+        pdata := VST.GetNodeData(Node);
+        if pdata.DataType > 0 then
+        begin
+          if ((selstart - pdata.Offset) < GetTypeDataLength(pdata.DataType)) and
+            ((selstart - pdata.Offset) >= 0) then
+          begin
+            VST.FocusedNode    := Node;
+            VST.Selected[Node] := True;
+            Break;
+          end;
+        end;
+        Node := VST.GetNext(Node);
+      end;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.value_viewer_contextPopup(Sender: TObject);
+var
+  i: Byte;
+begin
+  for i := 0 to value_viewer_context.Items.Count - 1 do
+    value_viewer_context.Items.Items[i].Visible := False;
+  with value_viewer do
+  begin
+    if (Col = 1) and (Row > 0) and (Length(Cells[Col, Row]) > 0) then
+    begin
+      if Pos(' byte', Cells[0, Row]) = 2 then
+      begin
+        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
+        value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible := True;
+        value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible := True;
+      end;
+      if Pos('Float', Cells[0, Row]) = 1 then
+        value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible := True;
+      if Pos('Bitset', Cells[0, Row]) = 1 then
+        value_viewer_context.Items.Find(
+          'Copy to clipboard (as &bitset)').Visible := True;
+      if Pos('String', Cells[0, Row]) = 1 then
+        value_viewer_context.Items.Find(
+          'Copy to clipboard (as &string)').Visible := True;
+      if Pos('Selected length', Cells[0, Row]) = 1 then
+        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
+  Shift: TShiftState; X, Y: Integer);
+var
+  ACol, ARow: Integer;
+begin
+  if Button = mbRight then
+  begin
+    value_viewer.MouseToCell(x, y, ACol, ARow);
+    if ARow > 0 then
+    begin
+      value_viewer.Col := ACol;
+      value_viewer.Row := ARow;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.value_viewer_context_copyClick(Sender: TObject);
+var
+  Name:  String;
+  Value: LongWord;
+begin
+  Name := TMenuItem(Sender).Name;
+  if Pos('asstring', Name) > 0 then
+  begin
+    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
+  end
+  else if Pos('asfloat', Name) > 0 then
+  begin
+    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
+  end
+  else if Pos('asbitset', Name) > 0 then
+  begin
+    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
+  end
+  else if (Pos('ashex', Name) > 0) or (Pos('asdec', Name) > 0) then
+  begin
+    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
+    begin
+      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 1) > hex.DataSize) then
+        Value := hex.Data[hex.SelStart];
+    end;
+    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
+    begin
+      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 2) > hex.DataSize) then
+        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
+    end;
+    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
+    begin
+      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 4) > hex.DataSize) then
+        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
+          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
+    end;
+    if Pos('asdec', Name) > 0 then
+    begin
+      Clipboard.AsText := IntToStr(Value);
+    end
+    else
+    begin
+      if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
+        Clipboard.AsText := '0x' + IntToHex(Value, 2);
+      if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
+        Clipboard.AsText := '0x' + IntToHex(Value, 4);
+      if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
+        Clipboard.AsText := '0x' + IntToHex(Value, 8);
+    end;
+  end
+  else
+  begin
+    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.VSTDblClick(Sender: TObject);
+var
+  node: PVirtualNode;
+  nodedata: PNodeData;
+  form: TForm_ToolTemplate;
+begin
+  if VST.FocusedColumn = 3 then
+  begin
+    node     := VST.FocusedNode;
+    nodedata := VST.GetNodeData(node);
+
+    if not (nodedata.datatype in [11, 12]) and
+      ((nodedata.DataType < 100) or (nodedata.DataType > 300)) then
+    begin
+      Form_ValueEdit.MakeVarInput(nodedata.Caption, nodedata.offset,
+        nodedata.datatype, nodedata.Value, Self);
+    end
+    else
+    begin
+      if nodedata.DataType = 11 then
+      begin
+        if OniDataConnection.GetRawInfo(fileid, nodedata.offset).raw_size > 0 then
+          Form_Main.open_child('rawedit', fileid);
+      end;
+      if nodedata.DataType = 12 then
+      begin
+        if (StrToInt(nodedata.Value) < OniDataConnection.GetFilesCount) and
+          (StrToInt(nodedata.Value) > 0) and
+          (StrToInt(nodedata.Value) <> fileid) then
+        begin
+          if OniDataConnection.GetFileInfo(StrToInt(nodedata.Value)).Size > 0 then
+            Form_Main.open_child('binedit', StrToInt(nodedata.Value))
+          else
+            ShowMessage('Linked filed is a zero-byte-file');
+        end;
+      end;
+      if (nodedata.DataType >= 100) and (nodedata.DataType <= 300) then
+      begin
+        form := Form_Main.open_child('binedit', -1);
+        if Assigned(form) then
+          form.SetFileFilters(nodedata.Value, '', False);
+      end;
+    end;
+
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
+  Column: TColumnIndex);
+var
+  Data: PNodeData;
+begin
+  Data := VST.GetNodeData(node);
+  if Data.DataType > 0 then
+  begin
+    hex.SelStart := Data.Offset;
+    hex.SelEnd   := Data.Offset + GetTypeDataLength(Data.DataType) - 1;
+  end
+  else
+  begin
+    hex.SelStart := Data.Offset;
+    hex.SelEnd   := Data.Offset + HexToLong(Data.Value) - 1;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
+  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
+var
+  Data: PNodeData;
+begin
+  Data     := Sender.GetNodeData(Node);
+  CellText := '';
+  if TextType = ttNormal then
+  begin
+    case Column of
+      0:
+        CellText := Data.Caption;
+      1:
+        if Data.DataType > 0 then
+          CellText := '0x' + IntToHex(Data.Offset, 8)
+        else if Data.Offset > 0 then
+          CellText := '0x' + IntToHex(Data.Offset, 8);
+      2:
+        if Data.DataType > 0 then
+          CellText := GetDataType(Data.DataType);
+      3:
+        if Data.DataType > 0 then
+          CellText := Data.Value //GetValue(data.DataType, data.Offset)
+        else if Length(Data.Value) > 0 then
+          CellText := IntToStr(HexToLong(Data.Value)) + ' Bytes';
+      4:
+        CellText := Data.Description;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
+  OldPosition: Integer);
+begin
+  if Sender.Columns.Items[column].Position < 1 then
+    Sender.Columns.Items[column].Position := OldPosition;
+end;
+
+
+
+
+procedure TForm_BinEdit.VTHPopupColumnChange(const Sender: TBaseVirtualTree;
+  const Column: TColumnIndex; Visible: Boolean);
+begin
+  if column = 0 then
+    TVirtualStringTree(Sender).Header.Columns.Items[column].Options :=
+      TVirtualStringTree(Sender).Header.Columns.Items[column].Options + [coVisible];
+end;
+
+
+
+
+procedure TForm_BinEdit.SetNewValue(datatype: Word; offset: LongWord; Value: String);
+var
+  Data: Tdata;
+  value_int: LongWord;
+  value_float: Single;
+  i: Word;
+begin
+  case datatype of
+    1..4:
+    begin
+      value_int := StrToInt(Value);
+      SetLength(Data, datatype);
+      for i := 0 to datatype - 1 do
+      begin
+        Data[i]   := value_int mod 256;
+        value_int := value_int div 256;
+      end;
+    end;
+    5..8:
+    begin
+      value_int := StrToInt('$' + Value);
+      SetLength(Data, datatype - 4);
+      for i := 0 to datatype - 5 do
+      begin
+        Data[i]   := value_int mod 256;
+        value_int := value_int div 256;
+      end;
+    end;
+    9:
+    begin
+      value_float := StrToFloat(Value);
+      Data := Encode_Float(value_float);
+    end;
+    10:
+    begin
+      value_int := BinToInt(Value);
+      SetLength(Data, 1);
+      Data[0] := value_int;
+    end;
+    10000..65535:
+    begin
+      SetLength(Data, datatype - 10000);
+      for i := 1 to datatype - 10000 do
+      begin
+        if i <= Length(Value) then
+          Data[i - 1] := Ord(Value[i])
+        else
+          Data[i - 1] := 0;
+      end;
+    end;
+  end;
+  for i := 0 to High(Data) do
+  begin
+    if hex.Data[offset + i] <> Data[i] then
+      hex.ByteChanged[offset + i] := True;
+    hex.Data[offset + i] := Data[i];
+  end;
+  hex.Modified := True;
+  hexChange(Self);
+  hex.Repaint;
+end;
+
+
+
+
+procedure TForm_BinEdit.value_viewerDblClick(Sender: TObject);
+var
+  offset:     LongWord;
+  datatype:   Word;
+  objectname: String;
+  Value:      String;
+begin
+  if (value_viewer.Col = 1) and (Length(value_viewer.Cells[1, value_viewer.Row]) > 0) then
+  begin
+    offset := hex.SelStart;
+    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
+      datatype := 1;
+    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
+      datatype := 2;
+    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
+      datatype := 4;
+    if value_viewer.Cells[0, value_viewer.Row] = 'Bitset' then
+      datatype := 10;
+    if value_viewer.Cells[0, value_viewer.Row] = 'Float' then
+      datatype := 9;
+    if value_viewer.Cells[0, value_viewer.Row] = 'Selected length' then
+      Exit;
+    if value_viewer.Cells[0, value_viewer.Row] = 'String' then
+    begin
+      if hex.SelCount > 0 then
+        datatype := 10000 + hex.SelCount
+      else
+        datatype := 10000 + Length(value_viewer.Cells[1, value_viewer.Row]);
+    end;
+    objectname := '';
+    Value      := GetValue(datatype, offset);
+    Form_ValueEdit.MakeVarInput(objectname, offset, datatype, Value, Self);
+  end;
+end;
+
+
+
+
+procedure TForm_BinEdit.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+begin
+  if (Shift = [ssCtrl]) and (Key = 83) then
+    if hex.Modified then
+      if not Save then
+        Exit;
+end;
+
+
+begin
+  AddToolListEntry('binedit', 'Binary .dat-Editor', '');
+end.
Index: /oup/releases/0.33a/Tools/Extractor.dfm
===================================================================
--- /oup/releases/0.33a/Tools/Extractor.dfm	(revision 76)
+++ /oup/releases/0.33a/Tools/Extractor.dfm	(revision 76)
@@ -0,0 +1,213 @@
+inherited Form_Extractor: TForm_Extractor
+  Caption = 'Extractor'
+  ClientHeight = 491
+  ExplicitWidth = 500
+  ExplicitHeight = 518
+  PixelsPerInch = 96
+  TextHeight = 13
+  inherited Splitter1: TSplitter
+    Left = 483
+    Height = 491
+    Align = alRight
+    Visible = False
+    ExplicitLeft = 172
+    ExplicitTop = -8
+    ExplicitHeight = 423
+  end
+  inherited panel_files: TPanel
+    Width = 333
+    Height = 491
+    ExplicitWidth = 333
+    ExplicitHeight = 491
+    inherited filelist: TListBox
+      Width = 333
+      Height = 362
+      ExplicitWidth = 333
+      ExplicitHeight = 362
+    end
+    inherited panel_extension: TPanel
+      Width = 333
+      ExplicitWidth = 333
+      inherited combo_extension: TComboBox
+        Width = 325
+        ExplicitWidth = 325
+      end
+      inherited check_zerobyte: TCheckBox
+        Visible = False
+      end
+      inherited edit_filtername: TEdit
+        Width = 325
+        ExplicitWidth = 325
+      end
+    end
+  end
+  inherited content: TPanel
+    Left = 333
+    Width = 150
+    Height = 491
+    ExplicitLeft = 333
+    ExplicitWidth = 150
+    ExplicitHeight = 491
+    object group_extract: TGroupBox
+      AlignWithMargins = True
+      Left = 6
+      Top = 3
+      Width = 138
+      Height = 374
+      Margins.Left = 6
+      Margins.Right = 6
+      Align = alClient
+      Caption = '2. Select extract-method'
+      TabOrder = 0
+      DesignSize = (
+        138
+        374)
+      object label_export_sel: TLabel
+        Left = 7
+        Top = 18
+        Width = 62
+        Height = 20
+        AutoSize = False
+        Caption = 'Export ...'
+      end
+      object label_path: TLabel
+        Left = 7
+        Top = 136
+        Width = 30
+        Height = 18
+        AutoSize = False
+        Caption = 'Path:'
+      end
+      object check_dat: TCheckBox
+        Left = 7
+        Top = 75
+        Width = 121
+        Height = 18
+        Anchors = [akLeft, akTop, akRight]
+        Caption = 'Export .dat-entries'
+        Checked = True
+        State = cbChecked
+        TabOrder = 0
+      end
+      object check_raw: TCheckBox
+        Left = 7
+        Top = 94
+        Width = 121
+        Height = 18
+        Anchors = [akLeft, akTop, akRight]
+        Caption = 'Export .raw-entries'
+        TabOrder = 1
+      end
+      object check_convert: TCheckBox
+        Left = 7
+        Top = 112
+        Width = 121
+        Height = 18
+        Anchors = [akLeft, akTop, akRight]
+        Caption = 'Convert files'
+        TabOrder = 2
+      end
+      object radio_selected: TRadioButton
+        Left = 7
+        Top = 36
+        Width = 113
+        Height = 17
+        Caption = 'selected files'
+        Checked = True
+        TabOrder = 3
+        TabStop = True
+      end
+      object radio_all: TRadioButton
+        Left = 7
+        Top = 52
+        Width = 113
+        Height = 17
+        Caption = 'all files in list'
+        TabOrder = 4
+      end
+      object edit_path: TEdit
+        Left = 36
+        Top = 133
+        Width = 28
+        Height = 21
+        Anchors = [akLeft, akTop, akRight]
+        ReadOnly = True
+        TabOrder = 5
+        Text = 'C:\'
+        OnClick = btn_pathClick
+      end
+      object btn_path: TButton
+        Left = 70
+        Top = 133
+        Width = 62
+        Height = 21
+        Anchors = [akTop, akRight]
+        Caption = 'Select...'
+        TabOrder = 6
+        OnClick = btn_pathClick
+      end
+      object btn_export: TButton
+        Left = 7
+        Top = 180
+        Width = 75
+        Height = 25
+        Caption = 'Export!'
+        TabOrder = 7
+        OnClick = btn_exportClick
+      end
+    end
+    object group_progress: TGroupBox
+      AlignWithMargins = True
+      Left = 6
+      Top = 381
+      Width = 138
+      Height = 104
+      Margins.Left = 6
+      Margins.Top = 1
+      Margins.Right = 6
+      Margins.Bottom = 6
+      Align = alBottom
+      Caption = 'Progress ...'
+      TabOrder = 1
+      Visible = False
+      DesignSize = (
+        138
+        104)
+      object lbl_progress: TLabel
+        Left = 8
+        Top = 40
+        Width = 265
+        Height = 17
+        AutoSize = False
+        Caption = 'Files done: 0/0'
+      end
+      object lbl_estimated: TLabel
+        Left = 8
+        Top = 56
+        Width = 265
+        Height = 17
+        AutoSize = False
+        Caption = 'Estimated finishing time: 00:00:00'
+      end
+      object progress: TProgressBar
+        Left = 8
+        Top = 16
+        Width = 122
+        Height = 17
+        Anchors = [akLeft, akTop, akRight]
+        Smooth = True
+        TabOrder = 0
+      end
+      object btn_abort: TButton
+        Left = 8
+        Top = 72
+        Width = 97
+        Height = 23
+        Caption = 'Abort'
+        Enabled = False
+        TabOrder = 1
+        OnClick = btn_abortClick
+      end
+    end
+  end
+end
Index: /oup/releases/0.33a/Tools/Extractor.pas
===================================================================
--- /oup/releases/0.33a/Tools/Extractor.pas	(revision 76)
+++ /oup/releases/0.33a/Tools/Extractor.pas	(revision 76)
@@ -0,0 +1,134 @@
+unit Extractor;
+interface
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, Template, StdCtrls, ExtCtrls, ComCtrls, Menus, Buttons, StrUtils;
+
+type
+  TForm_Extractor = class(TForm_ToolTemplate)
+    group_extract: TGroupBox;
+    check_dat: TCheckBox;
+    check_raw: TCheckBox;
+    check_convert: TCheckBox;
+    radio_selected: TRadioButton;
+    label_export_sel: TLabel;
+    radio_all: TRadioButton;
+    label_path: TLabel;
+    edit_path: TEdit;
+    btn_path: TButton;
+    btn_export: TButton;
+    group_progress: TGroupBox;
+    lbl_progress: TLabel;
+    lbl_estimated: TLabel;
+    progress: TProgressBar;
+    btn_abort: TButton;
+    procedure FormCreate(Sender: TObject);
+    procedure btn_abortClick(Sender: TObject);
+    procedure btn_pathClick(Sender: TObject);
+    procedure btn_exportClick(Sender: TObject);
+  private
+  public
+  end;
+
+var
+  Form_Extractor: TForm_Extractor;
+
+implementation
+{$R *.dfm}
+uses Main, Functions, Data, OniDataClass, FolderBrowser, Exporters;
+
+
+procedure TForm_Extractor.FormCreate(Sender: TObject);
+begin
+  inherited;
+  Self.AllowMultiSelect := True;
+  edit_path.Text := AppSettings.ExtractPath;
+end;
+
+procedure TForm_Extractor.btn_abortClick(Sender: TObject);
+begin
+  ShowMessage('X');
+end;
+
+procedure TForm_Extractor.btn_pathClick(Sender: TObject);
+var
+  fb: TFolderBrowser;
+begin
+  inherited;
+
+  fb := TFolderBrowser.Create(Handle, 'Please select a folder where you want ' +
+        'the files to be stored...', edit_path.Text, False, True);
+  if fb.Execute then
+  begin
+    edit_path.Text := fb.SelectedItem;
+    AppSettings.ExtractPath := edit_path.Text;
+  end;
+  fb.Free;
+end;
+
+procedure TForm_Extractor.btn_exportClick(Sender: TObject);
+var
+  begintime: Double;
+  files:     LongWord;
+  i, done:   LongWord;
+  selonly:   Boolean;
+  fileid:    LongWord;
+  filename:  String;
+  path:      String;
+begin
+  inherited;
+  panel_files.Enabled := False;
+  group_extract.Enabled := False;
+  group_progress.Visible := True;
+
+  path := edit_path.Text;
+  if not EndsText('\', path) then
+    path := path + '\';
+
+  begintime := Time;
+  lbl_estimated.Caption := 'Estimated finishing time: unknown';
+  progress.Position := 0;
+
+  selonly := radio_selected.Checked;
+
+  if selonly then
+    files := filelist.SelCount
+  else
+    files := filelist.Count;
+
+  lbl_progress.Caption := 'Files done: 0/' + IntToStr(files);
+  progress.Max := files;
+  done  := 0;
+
+  for i := 0 to filelist.Count - 1 do
+  begin
+    if (selonly and filelist.Selected[i]) or not selonly then
+    begin
+      fileid := OniDataConnection.ExtractFileID(filelist.Items.Strings[i]);
+      filename := GetWinFilename(filelist.Items.Strings[i]);
+      if check_dat.Checked then
+        ExportDatFile(fileid, path + filename);
+      if check_raw.Checked then
+        ExportRawFiles(fileid, path + filename);
+      if check_convert.Checked then
+        ExportConverted(fileid, path + filename);
+      Inc(done);
+    end;
+    if ((done mod 10) = 0) and (done >= 50) then
+      lbl_estimated.Caption := 'Estimated finishing time: ' + TimeToStr(
+            (Time - begintime) / done * files + begintime);
+
+    progress.Position    := done;
+    lbl_progress.Caption := 'Files done: ' + IntToStr(done) + '/' + IntToStr(files);
+    Application.ProcessMessages;
+  end;
+
+  panel_files.Enabled := True;
+  group_extract.Enabled := True;
+  group_progress.Visible := False;
+end;
+
+
+begin
+  AddToolListEntry('extractor', 'Extractor', '');
+end.
Index: /oup/releases/0.33a/Tools/Preview.dfm
===================================================================
--- /oup/releases/0.33a/Tools/Preview.dfm	(revision 76)
+++ /oup/releases/0.33a/Tools/Preview.dfm	(revision 76)
@@ -0,0 +1,78 @@
+inherited Form_Preview: TForm_Preview
+  Caption = 'Preview'
+  PixelsPerInch = 96
+  TextHeight = 13
+  inherited content: TPanel
+    object lbl_notpossible: TLabel
+      Left = 16
+      Top = 56
+      Width = 97
+      Height = 65
+      AutoSize = False
+      Caption = 'No preview possible for this filetype'
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -16
+      Font.Name = 'Tahoma'
+      Font.Style = []
+      ParentFont = False
+      Visible = False
+      WordWrap = True
+    end
+    object img: TImage
+      Left = 0
+      Top = 20
+      Width = 283
+      Height = 403
+      Align = alClient
+      ExplicitWidth = 313
+      ExplicitHeight = 453
+    end
+    object panel_buttons: TPanel
+      Left = 0
+      Top = 0
+      Width = 283
+      Height = 20
+      Align = alTop
+      BevelOuter = bvNone
+      TabOrder = 0
+      Visible = False
+      OnResize = panel_buttonsResize
+      object btn_dec: TButton
+        Left = 0
+        Top = 0
+        Width = 20
+        Height = 20
+        Caption = '-'
+        Enabled = False
+        TabOrder = 0
+        OnClick = btn_decClick
+      end
+      object btn_startstop: TButton
+        Left = 21
+        Top = 0
+        Width = 80
+        Height = 20
+        Caption = 'Stop automatic'
+        TabOrder = 1
+        OnClick = btn_startstopClick
+      end
+      object btn_inc: TButton
+        Left = 102
+        Top = 0
+        Width = 20
+        Height = 20
+        Caption = '+'
+        Enabled = False
+        TabOrder = 2
+        OnClick = btn_incClick
+      end
+    end
+  end
+  object timer: TTimer [3]
+    Enabled = False
+    OnTimer = timerTimer
+    Left = 400
+    Top = 120
+  end
+end
Index: /oup/releases/0.33a/Tools/Preview.pas
===================================================================
--- /oup/releases/0.33a/Tools/Preview.pas	(revision 76)
+++ /oup/releases/0.33a/Tools/Preview.pas	(revision 76)
@@ -0,0 +1,209 @@
+unit Preview;
+interface
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, Template, ExtCtrls, Math, StrUtils,
+  OniDataClass, OniImgClass, Data, Menus, Buttons;
+
+type
+  TForm_Preview = class(TForm_ToolTemplate)
+    lbl_notpossible: TLabel;
+    panel_buttons: TPanel;
+    btn_dec: TButton;
+    btn_startstop: TButton;
+    btn_inc: TButton;
+    img: TImage;
+    timer: TTimer;
+    procedure FormCreate(Sender: TObject);
+    procedure NewFile(fileinfo: TFileInfo);
+
+    procedure PreviewImage;
+    procedure PreviewTXAN;
+    procedure btn_incClick(Sender: TObject);
+    procedure btn_decClick(Sender: TObject);
+    procedure btn_startstopClick(Sender: TObject);
+    procedure timerTimer(Sender: TObject);
+    procedure panel_buttonsResize(Sender: TObject);
+
+    procedure DrawImage(index: Integer);
+    procedure SetBitmapCount(Count: Integer);
+    procedure LoadImage(fileid, index: Integer);
+  private
+    bitmaps:   array of TBitmap;
+    actualimg: Byte;
+    _fileid:   LongWord;
+  public
+  end;
+
+var
+  Form_Preview: TForm_Preview;
+
+implementation
+{$R *.dfm}
+
+
+procedure TForm_Preview.FormCreate(Sender: TObject);
+begin
+  inherited;
+  Self.OnNewFileSelected := NewFile;
+end;
+
+
+procedure TForm_Preview.NewFile(fileinfo: TFileInfo);
+var
+  ext: String;
+begin
+  _fileid := fileinfo.ID;
+  lbl_notpossible.Visible := False;
+  Self.img.Visible := True;
+  Self.timer.Enabled := False;
+  Self.panel_buttons.Visible := False;
+  ext     := fileinfo.Extension;
+  if (ext = 'PSpc') or (ext = 'TXMB') or (ext = 'TXMP') then
+    PreviewImage
+  else if ext = 'TXAN' then
+    PreviewTXAN
+  else
+  begin
+    Self.lbl_notpossible.Visible := True;
+    Self.img.Visible := False;
+  end;
+end;
+
+
+procedure TForm_Preview.LoadImage(fileid, index: Integer);
+var
+  Data:      Tdata;
+  memstream: TMemoryStream;
+  OniImage:  TOniImage;
+
+begin
+  OniImage := TOniImage.Create;
+  OniImage.Load(fileid);
+  Data := OniImage.GetAsBMP;
+  OniImage.Free;
+
+  memstream := TMemoryStream.Create;
+  memstream.Write(Data[0], Length(Data));
+  memstream.Seek(0, soFromBeginning);
+  bitmaps[index].LoadFromStream(memstream);
+  memstream.Free;
+end;
+
+
+procedure TForm_Preview.DrawImage(index: Integer);
+begin
+  BitBlt(img.Canvas.Handle, 0, 0, img.Width, img.Height,
+    bitmaps[index].Canvas.Handle, 0, 0, WHITENESS);
+  BitBlt(img.Canvas.Handle, 0, 0, bitmaps[index].Width, bitmaps[index].Height,
+    bitmaps[index].Canvas.Handle, 0, 0, SRCCOPY);
+  img.Invalidate;
+end;
+
+
+procedure TForm_Preview.SetBitmapCount(Count: Integer);
+var
+  i: Integer;
+begin
+  if Length(bitmaps) > Count then
+  begin
+    for i := Count to High(bitmaps) do
+      bitmaps[i].Free;
+    SetLength(bitmaps, Count);
+  end;
+  if Length(bitmaps) < Count then
+  begin
+    i := Length(bitmaps);
+    SetLength(bitmaps, Count);
+    for i := i to High(bitmaps) do
+      bitmaps[i] := TBitmap.Create;
+  end;
+end;
+
+
+procedure TForm_Preview.PreviewImage;
+begin
+  SetBitmapCount(1);
+  LoadImage(_fileid, 0);
+  DrawImage(0);
+end;
+
+
+procedure TForm_Preview.PreviewTXAN;
+var
+  loop_speed: Word;
+  linkcount: LongWord;
+  link: LongWord;
+  i:    Byte;
+begin
+  OniDataConnection.LoadDatFilePart(_fileid, $14, SizeOf(loop_speed), @loop_speed);
+  OniDataConnection.LoadDatFilePart(_fileid, $1C, SizeOf(linkcount), @linkcount);
+  SetBitmapCount(linkcount);
+  for i := 0 to linkcount - 1 do
+  begin
+    OniDataConnection.LoadDatFilePart(_fileid, $20 + i * 4, SizeOf(link), @link);
+    link := link div 256;
+    if link = 0 then
+      link := _fileid - 1;
+    LoadImage(link, i);
+  end;
+  actualimg := 254;
+  Self.timer.Interval := Floor(loop_speed * (1 / 60) * 1000);
+  Self.timer.Enabled := False;
+  Self.btn_startstopClick(Self);
+  Self.panel_buttons.Visible := True;
+end;
+
+
+procedure TForm_Preview.timerTimer(Sender: TObject);
+begin
+  btn_incClick(Self);
+end;
+
+
+procedure TForm_Preview.btn_startstopClick(Sender: TObject);
+begin
+  Self.timer.Enabled   := not Self.timer.Enabled;
+  Self.btn_dec.Enabled := not Self.timer.Enabled;
+  Self.btn_inc.Enabled := not Self.timer.Enabled;
+  if Self.timer.Enabled then
+    Self.btn_startstop.Caption := 'Stop automatic'
+  else
+    Self.btn_startstop.Caption := 'Start automatic';
+end;
+
+
+procedure TForm_Preview.btn_decClick(Sender: TObject);
+begin
+  if actualimg > 0 then
+    Dec(actualimg)
+  else
+    actualimg := High(bitmaps);
+  Self.Caption := 'Preview ' + OniDataConnection.GetFileInfo(_fileid).FileName +
+    ' (' + IntToStr(actualimg + 1) + '/' + IntToStr(Length(bitmaps)) + ')';
+  DrawImage(actualimg);
+end;
+
+
+procedure TForm_Preview.btn_incClick(Sender: TObject);
+begin
+  if actualimg < High(bitmaps) then
+    Inc(actualimg)
+  else
+    actualimg := 0;
+  Self.Caption := 'Preview ' + OniDataConnection.GetFileInfo(_fileid).FileName +
+    ' (' + IntToStr(actualimg + 1) + '/' + IntToStr(Length(bitmaps)) + ')';
+  DrawImage(actualimg);
+end;
+
+
+procedure TForm_Preview.panel_buttonsResize(Sender: TObject);
+begin
+  btn_startstop.Width := panel_buttons.Width - 45;
+  btn_inc.Left := panel_buttons.Width - 23;
+end;
+
+
+begin
+  AddToolListEntry('preview', 'Preview-Window', '');
+end.
Index: /oup/releases/0.33a/Tools/RawEdit.dfm
===================================================================
--- /oup/releases/0.33a/Tools/RawEdit.dfm	(revision 76)
+++ /oup/releases/0.33a/Tools/RawEdit.dfm	(revision 76)
@@ -0,0 +1,199 @@
+inherited Form_RawEdit: TForm_RawEdit
+  Caption = 'RawEdit'
+  KeyPreview = True
+  OnCloseQuery = FormCloseQuery
+  OnKeyUp = FormKeyUp
+  ExplicitWidth = 500
+  ExplicitHeight = 450
+  PixelsPerInch = 96
+  TextHeight = 13
+  inherited panel_files: TPanel
+    object Splitter4: TSplitter [0]
+      Left = 0
+      Top = 205
+      Width = 200
+      Height = 8
+      Cursor = crVSplit
+      Align = alBottom
+      AutoSnap = False
+      Beveled = True
+      MinSize = 150
+      ExplicitLeft = 3
+      ExplicitTop = 89
+    end
+    inherited filelist: TListBox
+      Height = 76
+      ExplicitHeight = 76
+    end
+    object panel_imexport: TPanel
+      Left = 0
+      Top = 363
+      Width = 200
+      Height = 60
+      Align = alBottom
+      BevelOuter = bvNone
+      TabOrder = 3
+      DesignSize = (
+        200
+        60)
+      object btn_export: TButton
+        Left = 4
+        Top = 4
+        Width = 190
+        Height = 25
+        Anchors = [akLeft, akTop, akRight]
+        Caption = 'Export to file...'
+        TabOrder = 0
+        OnClick = btn_exportClick
+      end
+      object btn_import: TButton
+        Left = 4
+        Top = 32
+        Width = 190
+        Height = 25
+        Anchors = [akLeft, akTop, akRight]
+        Caption = 'Import from file...'
+        TabOrder = 1
+        OnClick = btn_importClick
+      end
+    end
+    object GroupBox1: TGroupBox
+      Left = 0
+      Top = 213
+      Width = 200
+      Height = 150
+      Align = alBottom
+      Caption = '2. Select .dat-link-offset'
+      TabOrder = 2
+      object list_offset: TListBox
+        Left = 2
+        Top = 15
+        Width = 196
+        Height = 133
+        Align = alClient
+        ItemHeight = 13
+        TabOrder = 0
+        OnClick = list_offsetClick
+      end
+    end
+  end
+  inherited content: TPanel
+    OnResize = panel_contentResize
+    object Splitter2: TSplitter
+      Left = 0
+      Top = 300
+      Width = 283
+      Height = 9
+      Cursor = crVSplit
+      Align = alTop
+      AutoSnap = False
+      Beveled = True
+      MinSize = 40
+      ExplicitTop = 414
+    end
+    object hex: TMPHexEditor
+      Left = 0
+      Top = 0
+      Width = 283
+      Height = 300
+      Cursor = crIBeam
+      Align = alTop
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -16
+      Font.Name = 'Courier'
+      Font.Style = []
+      OnKeyUp = hexKeyUp
+      ParentFont = False
+      TabOrder = 0
+      BytesPerRow = 16
+      Translation = tkAsIs
+      OffsetFormat = '6!10:0x|'
+      Colors.Background = clWindow
+      Colors.ChangedBackground = clWindow
+      Colors.ChangedText = clRed
+      Colors.CursorFrame = clNavy
+      Colors.Offset = clBlack
+      Colors.OddColumn = clBlue
+      Colors.EvenColumn = clNavy
+      Colors.CurrentOffsetBackground = clBtnShadow
+      Colors.OffsetBackGround = clBtnFace
+      Colors.CurrentOffset = clBtnHighlight
+      Colors.Grid = clBtnFace
+      Colors.NonFocusCursorFrame = clAqua
+      Colors.ActiveFieldBackground = clWindow
+      FocusFrame = True
+      NoSizeChange = True
+      AllowInsertMode = False
+      DrawGridLines = False
+      Version = 'May 23, 2005; '#169' markus stephany, vcl[at]mirkes[dot]de'
+      OnChange = hexChange
+      ShowPositionIfNotFocused = True
+      OnSelectionChanged = hexSelectionChanged
+    end
+    object value_viewer: TWrapGrid
+      Left = 0
+      Top = 309
+      Width = 283
+      Height = 114
+      Align = alClient
+      ColCount = 2
+      DefaultColWidth = 80
+      DefaultRowHeight = 18
+      FixedCols = 0
+      RowCount = 8
+      FixedRows = 0
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -11
+      Font.Name = 'Tahoma'
+      Font.Style = []
+      Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goColSizing]
+      ParentFont = False
+      PopupMenu = value_viewer_context
+      TabOrder = 1
+      OnDblClick = value_viewerDblClick
+      OnMouseDown = value_viewerMouseDown
+    end
+  end
+  object value_viewer_context: TPopupMenu [3]
+    AutoHotkeys = maManual
+    OnPopup = value_viewer_contextPopup
+    Left = 368
+    Top = 264
+    object value_viewer_context_copy: TMenuItem
+      Caption = 'Copy to &clipboard'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasdec: TMenuItem
+      Caption = 'Copy to clipboard (as &dec)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasfloat: TMenuItem
+      Caption = 'Copy to clipboard (as &float)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasbitset: TMenuItem
+      Caption = 'Copy to clipboard (as &bitset)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasstring: TMenuItem
+      Caption = 'Copy to clipboard (as &string)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyashex: TMenuItem
+      Caption = 'Copy to clipboard (as &hex)'
+      OnClick = value_viewer_context_copyClick
+    end
+  end
+  object opend: TOpenDialog [4]
+    Options = [ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    Left = 128
+    Top = 256
+  end
+  object saved: TSaveDialog [5]
+    Options = [ofOverwritePrompt, ofPathMustExist, ofEnableSizing]
+    Left = 128
+    Top = 280
+  end
+end
Index: /oup/releases/0.33a/Tools/RawEdit.pas
===================================================================
--- /oup/releases/0.33a/Tools/RawEdit.pas	(revision 76)
+++ /oup/releases/0.33a/Tools/RawEdit.pas	(revision 76)
@@ -0,0 +1,821 @@
+unit RawEdit;
+interface
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, Template, StdCtrls, ExtCtrls, Menus, Grids, Wrapgrid,
+  MPHexEditor, Clipbrd, StrUtils,
+  Data, Functions, DataStructures, Exporters, OniDataClass, Buttons;
+
+type
+  TForm_RawEdit = class(TForm_ToolTemplate)
+    Splitter4: TSplitter;
+    panel_imexport: TPanel;
+    btn_export: TButton;
+    btn_import: TButton;
+    GroupBox1: TGroupBox;
+    list_offset: TListBox;
+    hex: TMPHexEditor;
+    Splitter2: TSplitter;
+    value_viewer: TWrapGrid;
+    value_viewer_context: TPopupMenu;
+    value_viewer_context_copy: TMenuItem;
+    value_viewer_context_copyasdec: TMenuItem;
+    value_viewer_context_copyasfloat: TMenuItem;
+    value_viewer_context_copyasbitset: TMenuItem;
+    value_viewer_context_copyasstring: TMenuItem;
+    value_viewer_context_copyashex: TMenuItem;
+    opend: TOpenDialog;
+    saved: TSaveDialog;
+    procedure list_offsetClick(Sender: TObject);
+    procedure NewFile(fileinfo: TFileInfo);
+    procedure LoadRaw(raw_info: TRawInfo);
+    function Save: Boolean;
+
+    procedure btn_importClick(Sender: TObject);
+    procedure btn_exportClick(Sender: TObject);
+
+    procedure FormCreate(Sender: TObject);
+    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+
+    procedure panel_contentResize(Sender: TObject);
+
+    function GetValue(datatype: Word; offset: LongWord): String;
+    procedure ClearValues;
+    procedure WriteValues;
+    procedure SetNewValue(datatype: Word; offset: LongWord; Value: String);
+
+    procedure value_viewerDblClick(Sender: TObject);
+    procedure value_viewer_context_copyClick(Sender: TObject);
+    procedure value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
+      Shift: TShiftState; X, Y: Integer);
+    procedure value_viewer_contextPopup(Sender: TObject);
+
+    procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+    procedure hexSelectionChanged(Sender: TObject);
+    procedure hexChange(Sender: TObject);
+  private
+    fileid:     Integer;
+    dat_offset: LongWord;
+    fileid_opened, dat_offset_opened: LongWord;
+  public
+  end;
+
+var
+  Form_RawEdit: TForm_RawEdit;
+
+implementation
+{$R *.dfm}
+uses Main, Helper_ValueEdit;
+
+procedure TForm_RawEdit.NewFile(fileinfo: TFileInfo);
+var
+  offsets: TRawList;
+  i: Integer;
+begin
+  if hex.Modified then
+    if not Save then
+      Exit;
+  ClearValues;
+  hex.DataSize := 0;
+  fileid := fileinfo.ID;
+  list_offset.Enabled := False;
+  if fileinfo.size > 0 then
+  begin
+    offsets := OniDataConnection.GetRawList(fileid);
+    list_offset.Items.Clear;
+    if Length(offsets) > 0 then
+      for i := 0 to High(offsets) do
+        list_offset.Items.Add('0x' + IntToHex(offsets[i].src_offset, 8) +
+              ', ' + IntToStr(offsets[i].raw_size) + ' bytes');
+    list_offset.Enabled := True;
+  end;
+end;
+
+procedure TForm_RawEdit.LoadRaw(raw_info: TRawInfo);
+var
+  i:    LongWord;
+  Data: Tdata;
+begin
+  if hex.Modified then
+  begin
+    if not Save then
+    begin
+      Exit;
+    end;
+  end;
+  if list_offset.Count = 0 then
+  begin
+    for i := 0 to filelist.Count - 1 do
+    begin
+      if OniDataConnection.ExtractFileID(filelist.Items.Strings[i]) = raw_info.src_id then
+      begin
+        filelist.ItemIndex := i;
+        listClick(Self);
+        Break;
+      end;
+    end;
+    for i := 0 to list_offset.Count - 1 do
+    begin
+      if MidStr(list_offset.Items.Strings[i], 3, 8) = IntToHex(raw_info.src_offset, 8) then
+      begin
+        list_offset.ItemIndex := i;
+        Break;
+      end;
+    end;
+  end;
+  SetLength(Data, raw_info.raw_size);
+  OniDataConnection.LoadRawFile(raw_info.src_id, raw_info.src_offset, @Data[0]);
+  if Length(Data) > 0 then
+  begin
+    hex.DataSize := 0;
+    hex.DataSize := raw_info.raw_size;
+    for i := 0 to High(Data) do
+      hex.Data[i] := Data[i];
+    //WriteStructureInfos(GetStructureInfoId(GetFileInfo(fileid).Extension));
+    //      structs.Height:=structs.RowCount*20;
+    //      IF structs.Height>120 THEN structs.Height:=120;
+    hexSelectionChanged(Self);
+    fileid_opened     := raw_info.src_id;
+    dat_offset_opened := raw_info.src_offset;
+    hex.Modified      := False;
+  end
+  else
+  begin
+    ClearValues;
+    hex.DataSize := 0;
+  end;
+end;
+
+
+
+
+
+
+procedure TForm_RawEdit.list_offsetClick(Sender: TObject);
+begin
+  ClearValues;
+  dat_offset := StrToInt('$' + MidStr(
+    list_offset.Items.Strings[list_offset.ItemIndex], 3, 8));
+  LoadRaw(OniDataConnection.GetRawInfo(fileid, dat_offset));
+end;
+
+
+
+
+function IntToBin(Value: Byte): String;
+var
+  i: Byte;
+begin
+  Result := '';
+  for i := 7 downto 0 do
+  begin
+    Result := Result + IntToStr((Value shr i) and $01);
+  end;
+end;
+
+
+
+
+function TForm_RawEdit.GetValue(datatype: Word; offset: LongWord): String;
+var
+  Data: Tdata;
+  i:    Word;
+  floatformat: TFormatSettings;
+begin
+  floatformat.DecimalSeparator := '.';
+  case datatype of
+    1:
+      Result := IntToStr(hex.Data[offset]);
+    2:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256);
+    3:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256);
+    4:
+      Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] *
+        256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256);
+    5:
+      Result := '0x' + IntToHex(hex.Data[offset], 2);
+    6:
+      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256, 4);
+    7:
+      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
+        hex.Data[offset + 2] * 256 * 256, 6);
+    8:
+      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
+        hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8);
+    9:
+    begin
+      SetLength(Data, 4);
+      Data[0] := hex.Data[offset];
+      Data[1] := hex.Data[offset + 1];
+      Data[2] := hex.Data[offset + 2];
+      Data[3] := hex.Data[offset + 3];
+      Result  := FloatToStr(Decode_Float(Data), floatformat);
+    end;
+    10:
+      Result := IntToBin(hex.Data[offset]);
+    11:
+      Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 +
+        hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8);
+    10000..65535:
+    begin
+      Result := '';
+      for i := 1 to datatype - 10000 do
+      begin
+        if hex.Data[offset + i - 1] >= 32 then
+          Result := Result + Chr(hex.Data[offset + i - 1])
+        else
+          Result := Result + '.';
+      end;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.ClearValues;
+var
+  i: Byte;
+begin
+  for i := 1 to value_viewer.RowCount - 1 do
+  begin
+    value_viewer.Cells[1, i] := '';
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.WriteValues;
+var
+  i, j:  Byte;
+  Data:  Tdata;
+  str:   String;
+  Value: LongWord;
+  floatformat: TFormatSettings;
+begin
+  floatformat.DecimalSeparator := '.';
+  for i := 1 to value_viewer.RowCount - 1 do
+  begin
+    if value_viewer.Cells[0, i] = '1 byte, unsigned' then
+    begin
+      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 1) > hex.DataSize) then
+      begin
+        Value := hex.Data[hex.SelStart];
+        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 2);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = '2 bytes, unsigned' then
+    begin
+      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 2) > hex.DataSize) then
+      begin
+        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
+        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 4);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = '4 bytes, unsigned' then
+    begin
+      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 4) > hex.DataSize) then
+      begin
+        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
+          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
+        value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 8);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = 'Bitset' then
+    begin
+      if (hex.SelCount <= 8) then
+      begin
+        if hex.SelCount = 0 then
+        begin
+          SetLength(Data, 1);
+          Data[0] := hex.Data[hex.SelStart];
+        end
+        else
+        begin
+          SetLength(Data, hex.SelCount);
+          for j := 0 to hex.SelCount - 1 do
+            Data[j] := hex.Data[hex.SelStart + j];
+        end;
+        value_viewer.Cells[1, i] := DataToBin(Data);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = 'Float' then
+    begin
+      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 4) > hex.DataSize) then
+      begin
+        SetLength(Data, 4);
+        for j := 0 to 3 do
+          Data[j] := hex.Data[hex.SelStart + j];
+        value_viewer.Cells[1, i] := FloatToStr(Decode_Float(Data), floatformat);
+      end
+      else
+        value_viewer.Cells[1, i] := '';
+    end;
+    if value_viewer.Cells[0, i] = 'Selected length' then
+    begin
+      value_viewer.Cells[1, i] := IntToStr(hex.SelCount) + ' bytes';
+    end;
+    if value_viewer.Cells[0, i] = 'String' then
+    begin
+      j   := 0;
+      str := '';
+      if hex.SelCount = 0 then
+      begin
+        while (hex.Data[hex.SelStart + j] > 0) and ((hex.SelStart + j) < hex.DataSize) do
+        begin
+          if hex.Data[hex.selstart + j] >= 32 then
+            str := str + Char(hex.Data[hex.SelStart + j])
+          else
+            str := str + '.';
+          Inc(j);
+        end;
+      end
+      else
+      begin
+        for j := 0 to hex.SelCount - 1 do
+          if hex.Data[hex.selstart + j] >= 32 then
+            str := str + Char(hex.Data[hex.SelStart + j])
+          else if hex.Data[hex.selstart + j] > 0 then
+            str := str + '.'
+          else
+            Break;
+      end;
+      value_viewer.Cells[1, i] := str;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.FormCreate(Sender: TObject);
+var
+  i:     LongWord;
+  exts: String;
+begin
+  inherited;
+  Self.OnNewFileSelected := Self.NewFile;
+
+  exts := '';
+  if Length(RawListHandlers) > 0 then
+  begin
+    for i := 0 to High(RawListHandlers) do
+      if Length(exts) > 0 then
+        exts := exts + ',' + RawListHandlers[i].Ext
+      else
+        exts := RawListHandlers[i].Ext;
+  end;
+  Self.AllowedExts := exts;
+
+  Self.Caption := '';
+  fileid     := -1;
+
+{
+  value_viewer.ColCount := 2;
+  value_viewer.RowCount := 8;
+}
+  value_viewer.FixedRows := 1;
+  value_viewer.Cells[0, 0] := 'Type';
+  value_viewer.Cells[1, 0] := 'Value';
+  value_viewer.Cells[0, 1] := '1 byte, unsigned';
+  value_viewer.Cells[0, 2] := '2 bytes, unsigned';
+  value_viewer.Cells[0, 3] := '4 bytes, unsigned';
+  value_viewer.Cells[0, 4] := 'Bitset';
+  value_viewer.Cells[0, 5] := 'Float';
+  value_viewer.Cells[0, 6] := 'String';
+  value_viewer.Cells[0, 7] := 'Selected length';
+  value_viewer.ColWidths[0] := 100;
+  //
+  value_viewer.Font.Charset := AppSettings.CharSet;
+  //
+end;
+
+
+
+
+function TForm_RawEdit.Save: Boolean;
+var
+  mem:  TMemoryStream;
+  Data: Tdata;
+  i:    LongWord;
+begin
+  case MessageBox(Self.Handle, PChar('Save changes to .raw-part of file ' +
+      OniDataConnection.GetFileInfo(fileid).FileName + '?'), PChar('Data changed...'),
+      MB_YESNOCANCEL) of
+    idYes:
+    begin
+      mem := TMemoryStream.Create;
+      hex.SaveToStream(mem);
+      mem.Seek(0, soFromBeginning);
+      SetLength(Data, mem.Size);
+      mem.Read(Data[0], mem.Size);
+      mem.Free;
+      OniDataConnection.UpdateRawFile(fileid_opened, dat_offset_opened,
+        Length(Data), @Data[0]);
+      hex.Modified := False;
+      for i := 0 to hex.Datasize - 1 do
+        hex.ByteChanged[i] := False;
+      Result := True;
+    end;
+    idNo:
+      Result := True;
+    idCancel:
+    begin
+      Result := False;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+  if hex.Modified then
+  begin
+    if not Save then
+      CanClose := False;
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.panel_contentResize(Sender: TObject);
+begin
+  if fileid >= 0 then
+    value_viewer.ColWidths[1] := value_viewer.Width - value_viewer.ColWidths[0] - 50;
+end;
+
+
+
+
+procedure TForm_RawEdit.hexChange(Sender: TObject);
+begin
+  ClearValues;
+  if hex.DataSize > 0 then
+  begin
+{      WriteStructureInfos(GetStructureInfoId(GetFileInfo(fileid).Extension));
+      WriteValues;
+}    end;
+end;
+
+
+
+
+procedure TForm_RawEdit.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+//var
+//  temps: String;
+begin
+  if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+  begin
+    if hex.SelCount > 0 then
+    begin
+      if hex.InCharField then
+        Clipboard.AsText := hex.SelectionAsText
+      else
+        Clipboard.AsText := hex.SelectionAsHex;
+    end;
+  end;
+  if (Shift = [ssCtrl]) and (Key = Ord('V')) then
+  begin
+{      temps:=Clipboard.AsText;
+      IF hex.SelStart+Length(temps)>hex.DataSize THEN
+        SetLength(temps, hex.DataSize-hex.SelStart);
+      hex.Sel
+      hex.SelCount:=Length(temps);
+      hex.ReplaceSelection(temps,Length(temps));
+}    end;
+end;
+
+
+
+
+procedure TForm_RawEdit.hexSelectionChanged(Sender: TObject);
+//var
+//  selstart: Integer;
+//  i, j:     Word;
+begin
+{    FOR i:=1 TO structs.RowCount-1 DO BEGIN
+      FOR j:=0 TO structs.ColCount-1 DO BEGIN
+        structs.CellColors[j,i]:=clWhite;
+        structs.CellFontColors[j,i]:=clBlack;
+      END;
+    END;
+}    if hex.DataSize > 0 then
+  begin
+{      selstart:=hex.SelStart;
+      IF GetStructureInfoId(GetFileInfo(fileid).Extension)>=0 THEN BEGIN
+        WITH structure_infos[GetStructureInfoId(GetFileInfo(fileid).Extension)] DO BEGIN
+          FOR i:=0 TO High(entries) DO BEGIN
+            IF ((selstart-entries[i].offset)<GetTypeDataLength(entries[i].datatype)) AND ((selstart-entries[i].offset)>=0) THEN BEGIN
+              FOR j:=0 TO structs.ColCount-1 DO BEGIN
+                structs.CellColors[j,i+1]:=clBlue;
+                structs.CellFontColors[j,i+1]:=clWhite;
+              END;
+              structs.Row:=i+1;
+            END;
+          END;
+        END;
+      END;
+}      WriteValues;
+  end;
+end;
+
+
+
+
+
+procedure TForm_RawEdit.btn_exportClick(Sender: TObject);
+var
+  fs: TFileStream;
+begin
+  saved.Filter     := 'Files of matching extension (*.' + OniDataConnection.GetFileInfo(
+    fileid).Extension + ')|*.' + OniDataConnection.GetFileInfo(fileid).Extension +
+    '|All files|*.*';
+  saved.DefaultExt := OniDataConnection.GetFileInfo(fileid).Extension;
+  if saved.Execute then
+  begin
+    fs := TFileStream.Create(saved.FileName, fmCreate);
+    hex.SaveToStream(fs);
+    fs.Free;
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.btn_importClick(Sender: TObject);
+var
+//  Data: Tdata;
+  fs:   TFileStream;
+begin
+  opend.Filter := 'Files of matching extension (*.' + OniDataConnection.GetFileInfo(
+    fileid).Extension + ')|*.' + OniDataConnection.GetFileInfo(fileid).Extension +
+    '|All files|*.*';
+  if opend.Execute then
+  begin
+    fs := TFileStream.Create(opend.FileName, fmOpenRead);
+    if fs.Size <> hex.DataSize then
+    begin
+      ShowMessage('Can''t import ' + ExtractFilename(opend.FileName) +
+        ', file has to have same size as file in .dat.' + CrLf +
+        'Size of file in .dat: ' + FormatFileSize(hex.datasize) + CrLf +
+        'Size of chosen file: ' + FormatFileSize(fs.Size));
+    end
+    else
+    begin
+      hex.LoadFromStream(fs);
+      hex.Modified := True;
+    end;
+    fs.Free;
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.value_viewer_contextPopup(Sender: TObject);
+var
+  i: Byte;
+begin
+  for i := 0 to value_viewer_context.Items.Count - 1 do
+    value_viewer_context.Items.Items[i].Visible := False;
+  with value_viewer do
+  begin
+    if (Col = 1) and (Row > 0) and (Length(Cells[Col, Row]) > 0) then
+    begin
+      if Pos(' byte', Cells[0, Row]) = 2 then
+      begin
+        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
+        value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible := True;
+        value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible := True;
+      end;
+      if Pos('Float', Cells[0, Row]) = 1 then
+        value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible := True;
+      if Pos('Bitset', Cells[0, Row]) = 1 then
+        value_viewer_context.Items.Find(
+          'Copy to clipboard (as &bitset)').Visible := True;
+      if Pos('String', Cells[0, Row]) = 1 then
+        value_viewer_context.Items.Find(
+          'Copy to clipboard (as &string)').Visible := True;
+      if Pos('Selected length', Cells[0, Row]) = 1 then
+        value_viewer_context.Items.Find('Copy to &clipboard').Visible := True;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.value_viewerMouseDown(Sender: TObject; Button: TMouseButton;
+  Shift: TShiftState; X, Y: Integer);
+var
+  ACol, ARow: Integer;
+begin
+  if Button = mbRight then
+  begin
+    value_viewer.MouseToCell(x, y, ACol, ARow);
+    if ARow > 0 then
+    begin
+      value_viewer.Col := ACol;
+      value_viewer.Row := ARow;
+    end;
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.value_viewer_context_copyClick(Sender: TObject);
+var
+//  i:     Byte;
+  Name:  String;
+  Value: LongWord;
+begin
+  Name := TMenuItem(Sender).Name;
+  if Pos('asstring', Name) > 0 then
+  begin
+    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
+  end
+  else if Pos('asfloat', Name) > 0 then
+  begin
+    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
+  end
+  else if Pos('asbitset', Name) > 0 then
+  begin
+    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
+  end
+  else if (Pos('ashex', Name) > 0) or (Pos('asdec', Name) > 0) then
+  begin
+    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
+    begin
+      if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 1) > hex.DataSize) then
+        Value := hex.Data[hex.SelStart];
+    end;
+    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
+    begin
+      if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 2) > hex.DataSize) then
+        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256;
+    end;
+    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
+    begin
+      if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not
+        ((hex.SelStart + 4) > hex.DataSize) then
+        Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 +
+          hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256;
+    end;
+    if Pos('asdec', Name) > 0 then
+    begin
+      Clipboard.AsText := IntToStr(Value);
+    end
+    else
+    begin
+      if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
+        Clipboard.AsText := '0x' + IntToHex(Value, 2);
+      if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
+        Clipboard.AsText := '0x' + IntToHex(Value, 4);
+      if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
+        Clipboard.AsText := '0x' + IntToHex(Value, 8);
+    end;
+  end
+  else
+  begin
+    Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row];
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.SetNewValue(datatype: Word; offset: LongWord; Value: String);
+var
+  Data: Tdata;
+  value_int: LongWord;
+  value_float: Single;
+  i: Word;
+begin
+  case datatype of
+    1..4:
+    begin
+      value_int := StrToInt(Value);
+      SetLength(Data, datatype);
+      for i := 0 to datatype - 1 do
+      begin
+        Data[i]   := value_int mod 256;
+        value_int := value_int div 256;
+      end;
+    end;
+    5..8:
+    begin
+      value_int := StrToInt('$' + Value);
+      SetLength(Data, datatype - 4);
+      for i := 0 to datatype - 5 do
+      begin
+        Data[i]   := value_int mod 256;
+        value_int := value_int div 256;
+      end;
+    end;
+    9:
+    begin
+      value_float := StrToFloat(Value);
+      Data := Encode_Float(value_float);
+    end;
+    10:
+    begin
+      value_int := BinToInt(Value);
+      SetLength(Data, 1);
+      Data[0] := value_int;
+    end;
+    10000..65535:
+    begin
+      SetLength(Data, datatype - 10000);
+      for i := 1 to datatype - 10000 do
+      begin
+        if i <= Length(Value) then
+          Data[i - 1] := Ord(Value[i])
+        else
+          Data[i - 1] := 0;
+      end;
+    end;
+  end;
+  for i := 0 to High(Data) do
+  begin
+    if hex.Data[offset + i] <> Data[i] then
+      hex.ByteChanged[offset + i] := True;
+    hex.Data[offset + i] := Data[i];
+  end;
+  hex.Modified := True;
+  hexChange(Self);
+  hex.Repaint;
+end;
+
+
+
+
+procedure TForm_RawEdit.value_viewerDblClick(Sender: TObject);
+var
+  offset:     LongWord;
+  datatype:   Word;
+  objectname: String;
+  Value:      String;
+begin
+  if (value_viewer.Col = 1) and (Length(value_viewer.Cells[1, value_viewer.Row]) > 0) then
+  begin
+    offset := hex.SelStart;
+    if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then
+      datatype := 1;
+    if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then
+      datatype := 2;
+    if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then
+      datatype := 4;
+    if value_viewer.Cells[0, value_viewer.Row] = 'Bitset' then
+      datatype := 10;
+    if value_viewer.Cells[0, value_viewer.Row] = 'Float' then
+      datatype := 9;
+    if value_viewer.Cells[0, value_viewer.Row] = 'Selected length' then
+      Exit;
+    if value_viewer.Cells[0, value_viewer.Row] = 'String' then
+    begin
+      if hex.SelCount > 0 then
+        datatype := 10000 + hex.SelCount
+      else
+        datatype := 10000 + Length(value_viewer.Cells[1, value_viewer.Row]);
+    end;
+    objectname := '';
+    Value      := GetValue(datatype, offset);
+    Form_ValueEdit.MakeVarInput(objectname, offset, datatype, Value, Self);
+  end;
+end;
+
+
+
+
+procedure TForm_RawEdit.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+begin
+  if (Shift = [ssCtrl]) and (Key = 83) then
+    if hex.Modified then
+      if not Save then
+        Exit;
+end;
+
+begin
+  AddToolListEntry('rawedit', 'Binary .raw-Editor', '');
+end.
Index: /oup/releases/0.33a/Tools/Template.dfm
===================================================================
--- /oup/releases/0.33a/Tools/Template.dfm	(revision 76)
+++ /oup/releases/0.33a/Tools/Template.dfm	(revision 76)
@@ -0,0 +1,307 @@
+object Form_ToolTemplate: TForm_ToolTemplate
+  Left = 0
+  Top = 0
+  Caption = 'Template'
+  ClientHeight = 423
+  ClientWidth = 492
+  Color = clBtnFace
+  Constraints.MinHeight = 450
+  Constraints.MinWidth = 500
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIChild
+  OldCreateOrder = False
+  Visible = True
+  WindowState = wsMaximized
+  OnActivate = FormActivate
+  OnClose = FormClose
+  OnCreate = FormCreate
+  OnResize = FormResize
+  PixelsPerInch = 96
+  TextHeight = 13
+  object Splitter1: TSplitter
+    Left = 200
+    Top = 0
+    Width = 9
+    Height = 423
+    AutoSnap = False
+    Beveled = True
+    MinSize = 155
+    ExplicitHeight = 473
+  end
+  object panel_files: TPanel
+    Left = 0
+    Top = 0
+    Width = 200
+    Height = 423
+    Align = alLeft
+    BevelOuter = bvNone
+    TabOrder = 0
+    object filelist: TListBox
+      Left = 0
+      Top = 129
+      Width = 200
+      Height = 294
+      Align = alClient
+      ItemHeight = 13
+      PopupMenu = filepopup
+      TabOrder = 0
+      OnClick = listClick
+      OnMouseDown = listMouseDown
+    end
+    object panel_extension: TPanel
+      Left = 0
+      Top = 0
+      Width = 200
+      Height = 129
+      Align = alTop
+      BevelOuter = bvNone
+      TabOrder = 1
+      DesignSize = (
+        200
+        129)
+      object Label2: TLabel
+        Left = 100
+        Top = 105
+        Width = 17
+        Height = 18
+        AutoSize = False
+        Caption = '.'
+        Font.Charset = DEFAULT_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -13
+        Font.Name = 'Tahoma'
+        Font.Style = [fsBold]
+        ParentFont = False
+      end
+      object Label1: TLabel
+        Left = 47
+        Top = 105
+        Width = 17
+        Height = 18
+        AutoSize = False
+        Caption = '-'
+        Font.Charset = DEFAULT_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -13
+        Font.Name = 'Tahoma'
+        Font.Style = [fsBold]
+        ParentFont = False
+      end
+      object label_ext: TLabel
+        Left = 2
+        Top = 62
+        Width = 100
+        Height = 17
+        AutoSize = False
+        Caption = 'Filter by &extension:'
+        FocusControl = combo_extension
+      end
+      object btn_sort_id_asc: TSpeedButton
+        Left = 3
+        Top = 101
+        Width = 20
+        Height = 22
+        Hint = 'Sort files by id, ascending'
+        GroupIndex = 1
+        Down = True
+        Glyph.Data = {
+          F6000000424DF600000000000000760000002800000010000000100000000100
+          0400000000008000000000000000000000001000000000000000C0C0C0000000
+          9900990000000000000000000000000000000000000000000000000000000000
+          0000000000000000000000000000000000000000000000000000000000000000
+          0000000001100000300000001001000030000000000100033300000001110003
+          3300000010010033333000001001000030000000011000003000000000000000
+          3000000002200000300000002002000030000000200200003000000020020000
+          3000000020020000300000002002000030000000022000003000}
+        ParentShowHint = False
+        ShowHint = True
+        OnClick = btn_sortClick
+      end
+      object btn_sort_id_desc: TSpeedButton
+        Left = 23
+        Top = 101
+        Width = 20
+        Height = 22
+        Hint = 'Sort files by id, descending'
+        GroupIndex = 1
+        Glyph.Data = {
+          F6000000424DF600000000000000760000002800000010000000100000000100
+          0400000000008000000000000000000000001000000000000000C0C0C0000000
+          9900990000000000000000000000000000000000000000000000000000000000
+          0000000000000000000000000000000000000000000000000000000000000000
+          0000000002200000300000002002000030000000200200033300000020020003
+          3300000020020033333000002002000030000000022000003000000000000000
+          3000000001100000300000001001000030000000000100003000000001110000
+          3000000010010000300000001001000030000000011000003000}
+        ParentShowHint = False
+        ShowHint = True
+        OnClick = btn_sortClick
+      end
+      object btn_sort_name_asc: TSpeedButton
+        Left = 58
+        Top = 101
+        Width = 20
+        Height = 22
+        Hint = 'Sort files by name, ascending'
+        GroupIndex = 1
+        Glyph.Data = {
+          F6000000424DF600000000000000760000002800000010000000100000000100
+          0400000000008000000000000000000000001000000000000000C0C0C0000000
+          9900990000000000000000000000000000000000000000000000000000000000
+          0000000000000000000000000000000000000000000000000000000000000000
+          0000011111100000300001100010000030000011000000033300000110000003
+          3300000011000033333001000110000030000111111000003000000000000000
+          3000022202220000300000200020000030000022222000003000000202000000
+          3000000222000000300000002000000030000000200000003000}
+        ParentShowHint = False
+        ShowHint = True
+        OnClick = btn_sortClick
+      end
+      object btn_sort_name_desc: TSpeedButton
+        Left = 78
+        Top = 101
+        Width = 20
+        Height = 22
+        Hint = 'Sort files by name, descending'
+        GroupIndex = 1
+        Glyph.Data = {
+          F6000000424DF600000000000000760000002800000010000000100000000100
+          0400000000008000000000000000000000001000000000000000C0C0C0000000
+          9900990000000000000000000000000000000000000000000000000000000000
+          0000000000000000000000000000000000000000000000000000000000000000
+          0000022202220000300000200020000030000022222000033300000202000003
+          3300000222000033333000002000000030000000200000003000000000000000
+          3000011111100000300001100010000030000011000000003000000110000000
+          3000000011000000300001000110000030000111111000003000}
+        ParentShowHint = False
+        ShowHint = True
+        OnClick = btn_sortClick
+      end
+      object btn_sort_ext_asc: TSpeedButton
+        Left = 108
+        Top = 101
+        Width = 20
+        Height = 22
+        Hint = 'Sort files by extension, ascending'
+        GroupIndex = 1
+        Glyph.Data = {
+          F6000000424DF600000000000000760000002800000010000000100000000100
+          0400000000008000000000000000000000001000000000000000C0C0C0000000
+          9900990000000000000000000000000000000000000000000000000000000000
+          0000000000000000000000000000000000000000000000000000000000000000
+          0000011111100000300001100010000030000011000000033300000110000003
+          3300000011000033333001000110000030000111111000003000000000000000
+          3000022202220000300000200020000030000022222000003000000202000000
+          3000000222000000300000002000000030000000200000003000}
+        ParentShowHint = False
+        ShowHint = True
+        OnClick = btn_sortClick
+      end
+      object btn_sort_ext_desc: TSpeedButton
+        Left = 128
+        Top = 101
+        Width = 20
+        Height = 22
+        Hint = 'Sort files by extension, descending'
+        GroupIndex = 1
+        Glyph.Data = {
+          F6000000424DF600000000000000760000002800000010000000100000000100
+          0400000000008000000000000000000000001000000000000000C0C0C0000000
+          9900990000000000000000000000000000000000000000000000000000000000
+          0000000000000000000000000000000000000000000000000000000000000000
+          0000022202220000300000200020000030000022222000033300000202000003
+          3300000222000033333000002000000030000000200000003000000000000000
+          3000011111100000300001100010000030000011000000003000000110000000
+          3000000011000000300001000110000030000111111000003000}
+        ParentShowHint = False
+        ShowHint = True
+        OnClick = btn_sortClick
+      end
+      object combo_extension: TComboBox
+        Left = 2
+        Top = 76
+        Width = 192
+        Height = 21
+        Style = csDropDownList
+        Anchors = [akLeft, akTop, akRight]
+        DropDownCount = 12
+        Font.Charset = DEFAULT_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -11
+        Font.Name = 'Tahoma'
+        Font.Style = []
+        ItemHeight = 13
+        ParentFont = False
+        Sorted = True
+        TabOrder = 3
+        OnClick = combo_extensionClick
+      end
+      object check_zerobyte: TCheckBox
+        Left = 2
+        Top = 44
+        Width = 130
+        Height = 13
+        Caption = 'Show &zero-byte files'
+        TabOrder = 2
+        OnClick = check_zerobyteClick
+      end
+      object edit_filtername: TEdit
+        Left = 2
+        Top = 20
+        Width = 192
+        Height = 18
+        Anchors = [akLeft, akTop, akRight]
+        AutoSize = False
+        TabOrder = 1
+      end
+      object check_filtername: TCheckBox
+        Left = 2
+        Top = 5
+        Width = 130
+        Height = 15
+        Caption = 'Filter by file&name:'
+        TabOrder = 0
+        OnClick = check_filternameClick
+      end
+    end
+  end
+  object content: TPanel
+    Left = 209
+    Top = 0
+    Width = 283
+    Height = 423
+    Align = alClient
+    BevelOuter = bvNone
+    TabOrder = 1
+  end
+  object filepopup: TPopupMenu
+    OnPopup = filepopupPopup
+    Left = 72
+    Top = 216
+    object popup_separator: TMenuItem
+      Caption = '-'
+    end
+    object popup_import: TMenuItem
+      Caption = 'Import binary .dat-file'
+      OnClick = popup_importClick
+    end
+    object popup_export: TMenuItem
+      Caption = 'Export binary .dat-file'
+      OnClick = popup_exportClick
+    end
+  end
+  object importd: TOpenDialog
+    Options = [ofExtensionDifferent, ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    Left = 136
+    Top = 232
+  end
+  object exportd: TSaveDialog
+    Options = [ofHideReadOnly, ofExtensionDifferent, ofPathMustExist, ofEnableSizing]
+    Left = 144
+    Top = 256
+  end
+end
Index: /oup/releases/0.33a/Tools/Template.pas
===================================================================
--- /oup/releases/0.33a/Tools/Template.pas	(revision 76)
+++ /oup/releases/0.33a/Tools/Template.pas	(revision 76)
@@ -0,0 +1,428 @@
+unit Template;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, ExtCtrls, StdCtrls, StrUtils,
+  OniDataClass, Functions, Data, Menus, Buttons;
+
+type
+  TNewFileSelectedEvent = procedure(fileinfo: TFileInfo) of object;
+
+  TForm_ToolTemplate = class(TForm)
+    panel_files: TPanel;
+    filelist: TListBox;
+    panel_extension: TPanel;
+    label_ext: TLabel;
+    combo_extension: TComboBox;
+    check_zerobyte: TCheckBox;
+    edit_filtername: TEdit;
+    check_filtername: TCheckBox;
+    Splitter1: TSplitter;
+    content: TPanel;
+    filepopup: TPopupMenu;
+    popup_import: TMenuItem;
+    popup_export: TMenuItem;
+    popup_separator: TMenuItem;
+    importd: TOpenDialog;
+    exportd: TSaveDialog;
+    btn_sort_id_asc: TSpeedButton;
+    btn_sort_id_desc: TSpeedButton;
+    btn_sort_name_asc: TSpeedButton;
+    btn_sort_name_desc: TSpeedButton;
+    btn_sort_ext_asc: TSpeedButton;
+    btn_sort_ext_desc: TSpeedButton;
+    Label1: TLabel;
+    Label2: TLabel;
+    procedure RecreateList;
+    procedure LoadFileNames;
+    procedure SelectFileName(filename: String);
+    procedure SelectFileID(id: Integer);
+    procedure check_filternameClick(Sender: TObject);
+    procedure check_zerobyteClick(Sender: TObject);
+    procedure combo_extensionClick(Sender: TObject);
+    procedure listClick(Sender: TObject);
+    procedure listMouseDown(Sender: TObject; Button: TMouseButton;
+      Shift: TShiftState; X, Y: Integer);
+
+    procedure FormResize(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+    procedure popup_importClick(Sender: TObject);
+    procedure popup_exportClick(Sender: TObject);
+    procedure popup_opentool(Sender: TObject);
+    procedure filepopupPopup(Sender: TObject);
+    procedure btn_sortClick(Sender: TObject);
+    procedure FormActivate(Sender: TObject);
+  private
+    FSortBy: TSortType;
+    FOnNewFileSelected: TNewFileSelectedEvent;
+    FAllowedExts: String;
+    FAllowMultiSelect: Boolean;
+    procedure SetAllowedExts(exts: String);
+    procedure SetMultiSelect(allow: Boolean);
+  public
+    constructor Create(AOwner: TComponent); override;
+    procedure SetFileFilters(pattern, extension: String; zerobytes: Boolean);
+  published
+    property OnNewFileSelected: TNewFileSelectedEvent read FOnNewFileSelected write FOnNewFileSelected;
+    property AllowedExts: String read FAllowedExts write SetAllowedExts;
+    property AllowMultiSelect: Boolean read FAllowMultiSelect write SetMultiSelect;
+  end;
+
+var
+  ToolList: TToolList;
+procedure AddToolListEntry(context, name, exts: String);
+
+implementation
+{$R *.dfm}
+uses Main, Exporters;
+
+
+procedure TForm_ToolTemplate.RecreateList;
+var
+  i:    LongWord;
+  exts: TStringArray;
+begin
+  combo_extension.Items.Clear;
+  combo_extension.Items.Add('_All files_ (' +
+    IntToStr(OniDataConnection.GetFilesCount) + ')');
+  exts := OniDataConnection.GetExtensionsList;
+  for i := 0 to High(exts) do
+    if Length(FAllowedExts) > 0 then
+    begin
+      if Pos(MidStr(exts[i],1,4), FAllowedExts) > 0 then
+      begin
+        combo_extension.Items.Add(exts[i]);
+      end;
+    end else
+      combo_extension.Items.Add(exts[i]);
+  combo_extension.ItemIndex := 0;
+  combo_extensionClick(Self);
+end;
+
+
+
+
+procedure TForm_ToolTemplate.LoadFileNames;
+var
+  Extension: String;
+  no_zero_bytes: Boolean;
+  pattern: String;
+  files: TStringArray;
+  i: LongWord;
+begin
+  Extension := MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex], 1, 4);
+  no_zero_bytes := not check_zerobyte.Checked;
+  pattern := '';
+  if check_filtername.Checked then
+    pattern := edit_filtername.Text;
+  if Extension = '_All' then
+    if Length(FAllowedExts) > 0 then
+      Extension := FAllowedExts
+    else
+      Extension := '';
+
+  files := OniDataConnection.GetFilesList(extension, pattern, no_zero_bytes, FSortBy);
+
+  filelist.Visible := False;
+  filelist.Items.Clear;
+  if Length(files) > 0 then
+    for i := 0 to High(files) do
+      filelist.Items.Add(files[i]);
+  filelist.Visible := True;
+end;
+
+
+procedure TForm_ToolTemplate.popup_exportClick(Sender: TObject);
+var
+  id: Integer;
+  ext: String;
+begin
+  id := OniDataConnection.ExtractFileID(filelist.Items.Strings[filelist.ItemIndex]);
+  ext := RightStr(filelist.Items.Strings[filelist.ItemIndex], 4);
+  exportd.Filter := 'Files of matching extension (*.' + ext + ')|*.' + ext + '|All files|*.*';
+  exportd.DefaultExt := ext;
+  if exportd.Execute then
+    ExportDatFile(id, exportd.FileName);
+end;
+
+procedure TForm_ToolTemplate.popup_importClick(Sender: TObject);
+var
+  id: Integer;
+  finfo: TFileInfo;
+  fs: TFileStream;
+  data: TData;
+begin
+  id := OniDataConnection.ExtractFileID(filelist.Items.Strings[filelist.ItemIndex]);
+  finfo := OniDataConnection.GetFileInfo(id);
+
+  importd.Filter := 'Files of matching extension (*.' + finfo.Extension + ')|*.' +
+        finfo.Extension + '|All files|*.*';
+  if importd.Execute then
+  begin
+    fs := TFileStream.Create(importd.FileName, fmOpenRead);
+    if fs.Size <> finfo.Size then
+      ShowMessage('Can''t import ' + ExtractFilename(importd.FileName) +
+        ', file has to have same size as file in .dat.' + CrLf +
+        'Size of file in .dat: ' + FormatFileSize(finfo.Size) + CrLf +
+        'Size of chosen file: ' + FormatFileSize(fs.Size))
+    else begin
+      SetLength(data, fs.Size);
+      fs.Read(data[0], fs.Size);
+      OniDataConnection.UpdateDatFile(id, data);
+      Self.listClick(Self);
+    end;
+    fs.Free;
+  end;
+end;
+
+procedure TForm_ToolTemplate.popup_opentool(Sender: TObject);
+var
+  sender_name, context: String;
+  id: Integer;
+begin
+  sender_name := TComponent(Sender).Name;
+  id := OniDataConnection.ExtractFileID(filelist.Items.Strings[filelist.ItemIndex]);
+  context := MidStr(sender_name, Pos('_', sender_name) + 1, Length(sender_name) - Pos('_', sender_name));
+  Form_Main.open_child(context, id);
+end;
+
+procedure TForm_ToolTemplate.combo_extensionClick(Sender: TObject);
+begin
+  LoadFileNames;
+end;
+
+
+constructor TForm_ToolTemplate.Create(AOwner: TComponent);
+var
+  i: Integer;
+  item: TMenuItem;
+begin
+  inherited;
+  RecreateList;
+  if Length(ToolList) > 0 then
+  begin
+    for i := 0 to High(ToolList) do
+    begin
+      item := TMenuItem.Create(filepopup);
+      item.Name := 'popup_' + ToolList[i].context;
+      item.Caption := 'Open with ' + ToolList[i].name;
+      item.OnClick := Self.popup_opentool;
+      filepopup.Items.Insert(i, item);
+    end;
+  end;
+end;
+
+procedure TForm_ToolTemplate.filepopupPopup(Sender: TObject);
+var
+  ext: String;
+  i: Integer;
+begin
+  ext := RightStr(filelist.Items.Strings[filelist.ItemIndex], 4);
+  for i := 0 to High(ToolList) do
+  begin
+    filepopup.Items.Items[i].Enabled := True;
+    if Length(ToolList[i].exts) > 0 then
+      if Pos(ext, ToolList[i].exts) = 0 then
+        filepopup.Items.Items[i].Enabled := False;
+  end;
+end;
+
+procedure TForm_ToolTemplate.check_zerobyteClick(Sender: TObject);
+begin
+  LoadFileNames;
+end;
+
+procedure TForm_ToolTemplate.btn_sortClick(Sender: TObject);
+begin
+  if btn_sort_id_asc.Down then
+    FSortBy := stIDAsc
+  else if btn_sort_id_desc.Down then
+    FSortBy := stIDDesc
+  else if btn_sort_name_asc.Down then
+    FSortBy := stNameAsc
+  else if btn_sort_name_desc.Down then
+    FSortBy := stNameDesc
+  else if btn_sort_ext_asc.Down then
+    FSortBy := stExtAsc
+  else if btn_sort_ext_desc.Down then
+    FSortBy := stExtDesc;
+  LoadFileNames;
+end;
+
+procedure TForm_ToolTemplate.check_filternameClick(Sender: TObject);
+begin
+  edit_filtername.Enabled := not check_filtername.Checked;
+  LoadFileNames;
+end;
+
+procedure TForm_ToolTemplate.listClick(Sender: TObject);
+var
+  fileid: Integer;
+begin
+  if filelist.ItemIndex > -1 then
+  begin
+    fileid := OniDataConnection.ExtractFileID(
+          filelist.Items.Strings[filelist.ItemIndex]);
+    if Assigned(FOnNewFileSelected) then
+      FOnNewFileSelected(OniDataConnection.GetFileInfo(fileid));
+  end;
+end;
+
+procedure TForm_ToolTemplate.listMouseDown(Sender: TObject; Button: TMouseButton;
+  Shift: TShiftState; X, Y: Integer);
+var
+  pt: TPoint;
+begin
+  pt.X := x;
+  pt.Y := y;
+//  filelist.ItemIndex := filelist.ItemAtPos(pt, true);
+//  Self.listClick(Self);
+end;
+
+
+
+procedure TForm_ToolTemplate.SelectFileID(id: Integer);
+var
+  i: Integer;
+begin
+  filelist.ItemIndex := -1;
+  if filelist.Items.Count > 0 then
+    for i := 0 to filelist.Items.Count - 1 do
+      if OniDataConnection.ExtractFileID(filelist.Items.Strings[i]) = id then
+      begin
+        filelist.ItemIndex := i;
+        Break;
+      end;
+  Self.listClick(Self);
+end;
+
+procedure TForm_ToolTemplate.SelectFileName(filename: String);
+var
+  i: Integer;
+begin
+  filelist.ItemIndex := -1;
+  if filelist.Items.Count > 0 then
+    for i := 0 to filelist.Items.Count - 1 do
+      if filelist.Items.Strings[i] = filename then
+        filelist.ItemIndex := i;
+  Self.listClick(Self);
+end;
+
+procedure TForm_ToolTemplate.SetAllowedExts(exts: String);
+begin
+  FAllowedExts := exts;
+  RecreateList;
+end;
+
+procedure TForm_ToolTemplate.SetFileFilters(pattern, extension: String;
+  zerobytes: Boolean);
+var
+  i: Integer;
+begin
+  if Length(pattern) > 0 then
+    Self.edit_filtername.Text := pattern;
+  Self.check_filtername.Checked := Length(pattern) > 0;
+  if Length(extension) > 0 then
+  begin
+    for i := 0 to Self.combo_extension.Items.Count - 1 do
+      if Pos(extension, Self.combo_extension.Items.Strings[i]) > 0 then
+        Break;
+    if i < Self.combo_extension.Items.Count then
+      Self.combo_extension.ItemIndex := i
+    else
+      Self.combo_extension.ItemIndex := -1;
+  end;
+  Self.check_zerobyte.Checked := zerobytes;
+  Self.LoadFileNames;
+end;
+
+procedure TForm_ToolTemplate.SetMultiSelect(allow: Boolean);
+begin
+  FAllowMultiSelect := allow;
+  filelist.MultiSelect := allow;
+end;
+
+
+procedure TForm_ToolTemplate.FormResize(Sender: TObject);
+begin
+  if Self.Width < 300 then
+    Self.Width := 300;
+  if Self.Height < 200 then
+    Self.Height := 200;
+end;
+
+
+
+procedure TForm_ToolTemplate.FormCreate(Sender: TObject);
+begin
+  Self.Width  := 260;
+  Self.Height := 300;
+  FOnNewFileSelected := nil;
+  FAllowedExts := '';
+  FAllowMultiSelect := False;
+end;
+
+procedure TForm_ToolTemplate.FormActivate(Sender: TObject);
+begin
+  if edit_filtername.CanFocus then
+    edit_filtername.SetFocus
+  else
+    if content.CanFocus then
+      content.SetFocus;
+end;
+
+procedure TForm_ToolTemplate.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  Action := caFree;
+end;
+
+
+procedure AddToolListEntryExt(context, ext: String);
+var
+  i: Integer;
+begin
+  for i := 0 to High(ToolList) do
+    if ToolList[i].context = context then
+    begin
+      if Pos(ext, ToolList[i].exts) = 0 then
+      begin
+        if Length(ToolList[i].exts) = 0 then
+          ToolList[i].exts := ext
+        else
+          ToolList[i].exts := ToolList[i].exts + ',' + ext;
+      end;
+      Exit;
+    end;
+end;
+
+procedure AddToolListEntry(context, name, exts: String);
+var
+  i: Integer;
+begin
+  if Length(ToolList) > 0 then
+  begin
+    for i := 0 to High(ToolList) do
+      if ToolList[i].context = context then
+      begin
+        if (Length(ToolList[i].name) = 0) and (Length(name) > 0) then
+          ToolList[i].name := name;
+        if Length(exts) > 0 then
+          AddToolListEntryExt(context, exts);
+        Exit;
+      end;
+  end;
+  SetLength(ToolList, Length(ToolList) + 1);
+  for i := High(ToolList) downto 1 do
+    if ToolList[i - 1].name > name then
+      ToolList[i] := ToolList[i - 1]
+    else
+      Break;
+  ToolList[i].context := context;
+  ToolList[i].name := name;
+  ToolList[i].exts := exts;
+end;
+
+end.
Index: /oup/releases/0.33a/Tools/TxmpReplace.dfm
===================================================================
--- /oup/releases/0.33a/Tools/TxmpReplace.dfm	(revision 76)
+++ /oup/releases/0.33a/Tools/TxmpReplace.dfm	(revision 76)
@@ -0,0 +1,150 @@
+inherited Form_TxmpReplace: TForm_TxmpReplace
+  Caption = 'TxmpReplace'
+  PixelsPerInch = 96
+  TextHeight = 13
+  inherited Splitter1: TSplitter
+    Height = 344
+    ExplicitHeight = 344
+  end
+  inherited panel_files: TPanel
+    Height = 344
+    ExplicitHeight = 344
+    object image_txmppreview: TImage [0]
+      Left = 0
+      Top = 283
+      Width = 200
+      Height = 31
+      Align = alClient
+      ExplicitTop = 111
+      ExplicitHeight = 211
+    end
+    object splitter_txmp: TSplitter [1]
+      Left = 0
+      Top = 275
+      Width = 200
+      Height = 8
+      Cursor = crVSplit
+      Align = alTop
+      AutoSnap = False
+      Beveled = True
+      MinSize = 60
+      ExplicitLeft = -6
+      ExplicitTop = 314
+    end
+    inherited filelist: TListBox
+      Height = 146
+      Align = alTop
+      ExplicitHeight = 146
+    end
+    inherited panel_extension: TPanel
+      Visible = False
+    end
+    object panel_txmppreview: TPanel
+      Left = 0
+      Top = 314
+      Width = 200
+      Height = 30
+      Align = alBottom
+      BevelOuter = bvNone
+      TabOrder = 2
+      object btn_save: TButton
+        Left = 2
+        Top = 2
+        Width = 111
+        Height = 25
+        Caption = 'Save TXMP-Picture'
+        TabOrder = 0
+        OnClick = btn_saveClick
+      end
+    end
+  end
+  inherited content: TPanel
+    Height = 344
+    ExplicitHeight = 344
+    object group_bmpselect: TGroupBox
+      Left = 0
+      Top = 0
+      Width = 283
+      Height = 344
+      Align = alClient
+      Caption = '2. Open BMP to replace with'
+      Enabled = False
+      TabOrder = 0
+      object image_bmppreview: TImage
+        Left = 2
+        Top = 45
+        Width = 279
+        Height = 297
+        Align = alClient
+        ExplicitWidth = 182
+        ExplicitHeight = 302
+      end
+      object panel_load: TPanel
+        Left = 2
+        Top = 15
+        Width = 279
+        Height = 30
+        Align = alTop
+        BevelOuter = bvNone
+        TabOrder = 0
+        object btn_load: TButton
+          Left = 2
+          Top = 2
+          Width = 121
+          Height = 25
+          Caption = 'Load BMP ...'
+          TabOrder = 0
+          OnClick = btn_loadClick
+        end
+      end
+    end
+  end
+  object group_options: TGroupBox [3]
+    Left = 0
+    Top = 344
+    Width = 492
+    Height = 79
+    Align = alBottom
+    Caption = '3. Options && Replace'
+    Enabled = False
+    TabOrder = 2
+    object btn_replace: TButton
+      Left = 4
+      Top = 50
+      Width = 157
+      Height = 25
+      Caption = 'Replace'
+      TabOrder = 0
+      OnClick = btn_replaceClick
+    end
+    object check_transparency: TCheckBox
+      Left = 8
+      Top = 16
+      Width = 105
+      Height = 17
+      Caption = 'Transparency'
+      TabOrder = 1
+    end
+    object check_fading: TCheckBox
+      Left = 8
+      Top = 32
+      Width = 105
+      Height = 17
+      Caption = 'MIP Mapping'
+      TabOrder = 2
+    end
+  end
+  object opend: TOpenDialog [4]
+    Filter = '24bit Bitmap (*.bmp)|*.bmp'
+    Options = [ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    Left = 352
+    Top = 16
+  end
+  object saved: TSaveDialog [5]
+    DefaultExt = 'bmp'
+    Filter = 'Windows Bitmap (*.bmp)|*.bmp'
+    Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofEnableSizing]
+    Left = 104
+    Top = 320
+  end
+end
Index: /oup/releases/0.33a/Tools/TxmpReplace.pas
===================================================================
--- /oup/releases/0.33a/Tools/TxmpReplace.pas	(revision 76)
+++ /oup/releases/0.33a/Tools/TxmpReplace.pas	(revision 76)
@@ -0,0 +1,203 @@
+unit TxmpReplace;
+interface
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, Template, StdCtrls, ExtCtrls,
+  Functions, Data, OniImgClass, Menus, Buttons;
+
+type
+  TForm_TxmpReplace = class(TForm_ToolTemplate)
+    group_options: TGroupBox;
+    btn_replace: TButton;
+    check_transparency: TCheckBox;
+    check_fading: TCheckBox;
+    panel_txmppreview: TPanel;
+    btn_save: TButton;
+    image_txmppreview: TImage;
+    splitter_txmp: TSplitter;
+    group_bmpselect: TGroupBox;
+    image_bmppreview: TImage;
+    panel_load: TPanel;
+    btn_load: TButton;
+    opend: TOpenDialog;
+    saved: TSaveDialog;
+    procedure SelectFile(fileinfo: TFileInfo);
+    procedure FormCreate(Sender: TObject);
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+    procedure btn_saveClick(Sender: TObject);
+    procedure btn_loadClick(Sender: TObject);
+    procedure btn_replaceClick(Sender: TObject);
+  private
+    OniImage_Old: TOniImage;
+    OniImage_New: TOniImage;
+    old_size: Integer;
+    fileid: Integer;
+  public
+  end;
+
+var
+  Form_TxmpReplace: TForm_TxmpReplace;
+
+implementation
+{$R *.dfm}
+uses Main, OniDataClass;
+
+
+
+procedure TForm_TxmpReplace.SelectFile(fileinfo: TFileInfo);
+var
+  Data: Tdata;
+  mem:  TMemoryStream;
+  fadingbyte, depthbyte, storebyte: Byte;
+begin
+  fileid := fileinfo.ID;
+  OniDataConnection.LoadDatFilePart(fileid, $88, SizeOf(fadingbyte), @fadingbyte);
+  OniDataConnection.LoadDatFilePart(fileid, $89, SizeOf(depthbyte), @depthbyte);
+  OniDataConnection.LoadDatFilePart(fileid, $90, SizeOf(storebyte), @storebyte);
+  check_fading.Checked := (fadingbyte and $01) > 0;
+  check_transparency.Checked := (depthbyte and $04) > 0;
+
+  OniImage_Old.LoadFromTXMP(fileid);
+  old_size := OniImage_Old.GetImageDataSize((fadingbyte and $01) > 0);
+  Data := OniImage_Old.GetAsBMP;
+  mem  := TMemoryStream.Create;
+  mem.Write(Data[0], Length(Data));
+  mem.Seek(0, soFromBeginning);
+  image_txmppreview.Picture.Bitmap.LoadFromStream(mem);
+  mem.Free;
+
+  group_bmpselect.Enabled := True;
+end;
+
+
+procedure TForm_TxmpReplace.btn_loadClick(Sender: TObject);
+var
+  mem:   TMemoryStream;
+  tempd: Tdata;
+begin
+  if opend.Execute then
+  begin
+    OniImage_New.LoadFromBMP(opend.FileName);
+    tempd := OniImage_New.GetAsBMP;
+    mem   := TMemoryStream.Create;
+    mem.Write(tempd[0], Length(tempd));
+    mem.Seek(0, soFromBeginning);
+    image_bmppreview.Picture.Bitmap.LoadFromStream(mem);
+    mem.Free;
+    group_options.Enabled := True;
+  end;
+end;
+
+
+
+
+procedure TForm_TxmpReplace.btn_replaceClick(Sender: TObject);
+var
+  newsize: LongWord;
+  old_rawaddr, new_rawaddr: LongWord;
+  oldfading: Byte;
+  tempd:     Tdata;
+
+  datbyte: Word;
+begin
+  if filelist.ItemIndex >= 0 then
+  begin
+    OniDataConnection.LoadDatFilePart(fileid, $88, 1, @oldfading);
+    if OniDataConnection.OSisMac then
+      OniDataConnection.UpdateDatFilePart(fileid, $A0, 4, @old_rawaddr)
+    else
+      OniDataConnection.LoadDatFilePart(fileid, $9C, 4, @old_rawaddr);
+
+    if (OniImage_Old.Width <> OniImage_New.Width) or
+      (OniImage_Old.Height <> OniImage_New.Height) then
+    begin
+      if MessageBox(Self.Handle, PChar(
+        'Current image and new image have different size' + CrLf +
+        '(Current: ' + IntToStr(OniImage_Old.Width) +
+        'x' + IntToStr(OniImage_Old.Height) + ' - New: ' +
+        IntToStr(OniImage_New.Width) + 'x' + IntToStr(OniImage_New.Height) + ')' + CrLf +
+        'Replace anyways?'),
+        PChar(filelist.Items.Strings[filelist.ItemIndex]),
+        MB_YESNO) = idNo then
+        Exit;
+    end;
+
+    if check_fading.Checked then
+      if not OniImage_New.GetMipMappedImage(tempd) then
+        if MessageBox(Self.Handle,
+          PChar('Can not create a MipMapped-image (probably because of a wrong dimension).' +
+          #13 + #10 + 'Do you want to continue without MipMapping?'), PChar('Warning'),
+          MB_YESNO) = ID_YES then
+          check_fading.Checked := False
+        else
+          Exit;
+
+    if not check_fading.Checked then
+      tempd := OniImage_New.GetAsData;
+
+    newsize := OniImage_New.GetImageDataSize(check_fading.Checked);
+
+    if (newsize > old_size) and (OniDataConnection.Backend = ODB_Dat) then
+      new_rawaddr := OniDataConnection.AppendRawFile(
+        OniDataConnection.OSisMac, Length(tempd), tempd)
+    else
+    begin
+      new_rawaddr := old_rawaddr;
+      OniDataConnection.UpdateRawFile(fileid, $9C, Length(tempd), tempd);
+    end;
+
+    datbyte := $00;
+    if check_fading.Checked then
+      datbyte := datbyte or $01;
+    OniDataConnection.UpdateDatFilePart(fileid, $88, 1, @datbyte);
+    datbyte := $10;
+    if check_transparency.Checked then
+      datbyte := datbyte or $04;
+    OniDataConnection.UpdateDatFilePart(fileid, $89, 1, @datbyte);
+    OniDataConnection.UpdateDatFilePart(fileid, $8C, 2, @OniImage_New.Width);
+    OniDataConnection.UpdateDatFilePart(fileid, $8E, 2, @OniImage_New.Height);
+    datbyte := $08;
+    OniDataConnection.UpdateDatFilePart(fileid, $90, 1, @datbyte);
+    if OniDataConnection.OSisMac then
+      OniDataConnection.UpdateDatFilePart(fileid, $A0, 4, @new_rawaddr)
+    else
+      OniDataConnection.UpdateDatFilePart(fileid, $9C, 4, @new_rawaddr);
+
+    ShowMessage('TXMP-image replaced');
+  end;
+end;
+
+
+
+
+procedure TForm_TxmpReplace.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  OniImage_Old.Free;
+  OniImage_New.Free;
+  inherited;
+end;
+
+
+
+
+procedure TForm_TxmpReplace.FormCreate(Sender: TObject);
+begin
+  inherited;
+  OniImage_Old := TOniImage.Create;
+  OniImage_New := TOniImage.Create;
+  Self.AllowedExts := 'TXMP';
+  Self.OnNewFileSelected := SelectFile;
+end;
+
+
+
+
+procedure TForm_TxmpReplace.btn_saveClick(Sender: TObject);
+begin
+  if saved.Execute then
+    OniImage_Old.WriteToBMP(saved.FileName);
+end;
+
+begin
+  AddToolListEntry('txmpreplace', 'TXMP Replacer', 'TXMP');
+end.
Index: /oup/releases/0.33a/text/_irf_oni.onlv.vb
===================================================================
--- /oup/releases/0.33a/text/_irf_oni.onlv.vb	(revision 76)
+++ /oup/releases/0.33a/text/_irf_oni.onlv.vb	(revision 76)
@@ -0,0 +1,545 @@
+Public Type LWOPolygon
+  NumVe As Integer
+  P1 As Integer
+  P2 As Integer
+  P3 As Integer
+  Surfa As Integer
+End Type
+
+Public Type PolDef
+  P1 As Integer
+  P2 As Integer
+  P3 As Integer
+End Type
+
+'Texture Coordinate Entry
+Public Type TXCAentry
+  X As Single
+  Y As Single
+End Type
+
+'Texture Coordinate Lists
+Public Type TXCA            'Length
+  ID As Long                '4
+  Version As Long           '8
+  Filler(1 To 5) As Long    '28
+  NumEntries As Long        '32
+End Type
+
+'Level Data Reference List
+Public Type ONLV            'Length
+  ID As Long                '4
+  Version As Long           '8
+  LevelName As String * 64  '72
+  AKEVid As Long            '76
+  OBOAid As Long            '80
+  ONMAid As Long            '84
+  ONFAid As Long            '88
+  ONTAid As Long            '92
+  ONSKid As Long            '96
+  Unkn As Long              '100
+  AISAid As Long            '104
+  AITRid As Long            '108
+  ONSAid As Long            '112
+  OBDCid As Long            '116
+  ONOAid As Long            '120
+  Fill(1 To 161) As Long    '764
+  CRSAid As Long            '768
+End Type
+
+Public Type AGQG
+  ID As Long
+  unk(1 To 24) As Byte
+  NumEntries As Long
+End Type
+
+Public Type AGQGEntry
+  VertIndex(1 To 4) As Long
+  VertUVIndex(1 To 4) As Long
+  LData_1(1 To 4) As Byte
+  LData_2(1 To 4) As Byte
+  LData_3(1 To 4) As Byte
+  LData_4(1 To 4) As Byte
+  unk(1 To 2) As Long
+End Type
+
+Public Type AGQREntry
+  TexIndex As Integer
+  unk As Integer
+End Type
+
+Public Type TXMA
+   ID As Long
+   shit(1 To 24) As Byte
+   NumEntries As Long
+End Type
+
+Public Type TXMAEntry
+   TXMP_ID As Long
+End Type
+
+
+
+
+
+Public Sub CExportONLV(Optional FileName As String)
+Form1.StatusBar1.SimpleText = "Status: Extracting LEVEL....."
+Dim ID4 As Long
+Dim I As Long
+Dim L As Long
+Dim LwoP() As LWOPolygon
+Dim OniPol2() As PolDef
+Dim NP As Long
+Dim numb As Long
+
+Dim TXMA1 As TXMA
+Dim AGQR1 As TXMA
+Dim TXCA1 As TXCA
+Dim TXCA_E() As TXCAentry
+Dim TXMA_E() As TXMAEntry
+Dim AGQR_E() As AGQREntry
+Dim TexNames() As String
+
+If FileName = "" Then
+  Form1.CD.DialogTitle = "Unpack resource..."
+  Form1.CD.FileName = OniEntry(Curr).szTagName
+  Form1.CD.Filter = "LightWave (*.lwo)|*.lwo"
+  Form1.CD.Flags = &H2 + &H4
+  Form1.CD.ShowSave
+  FileName = Form1.CD.FileName
+  If FileName = "" Then Exit Sub
+End If
+
+DoEvents
+
+Open DatFile For Binary As #1
+  Get 1, OniEntry(Curr).rDataPosition, ONLV
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = ONLV.AKEVid Then
+      Get 1, OniEntry(I).rDataPosition, AKEV
+      Exit For
+    End If
+  Next I
+
+  'Find ID of PNTA
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.PNTAid Then
+       Get 1, OniEntry(I).rDataPosition, PNTA
+       ReDim PNTAentry(PNTA.NumEntries - 1)
+       Get 1, , PNTAentry
+       Exit For
+    End If
+  Next I
+
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.AGQGid Then
+       Get 1, OniEntry(I).rDataPosition, AGQG
+       ReDim AGQGEntry(AGQG.NumEntries - 1)
+       Get 1, , AGQGEntry
+       Exit For
+    End If
+  Next I
+
+  'TXCA
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.TXCAid Then
+       Get 1, OniEntry(I).rDataPosition, TXCA1
+       ReDim TXCA_E(TXCA1.NumEntries - 1)
+       Get 1, , TXCA_E
+       ReDim Preserve TXCA_E(PNTA.NumEntries - 1)
+       Exit For
+    End If
+  Next I
+
+  'TXMA
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.TXMAid Then
+       Get 1, OniEntry(I).rDataPosition, TXMA1
+       ReDim TXMA_E(TXMA1.NumEntries - 1)
+       Get 1, , TXMA_E
+       Exit For
+    End If
+  Next I
+
+  'AGQR
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.AGQRid Then
+       Get 1, OniEntry(I).rDataPosition, AGQR1
+       ReDim AGQR_E(AGQR1.NumEntries - 1)
+       Get 1, , AGQR_E
+       Exit For
+    End If
+  Next I
+
+  ReDim TexNames(TXMA1.NumEntries - 1)
+
+  For I = 0 To TXMA1.NumEntries - 1
+    For L = 0 To UBound(OniEntry) - 1
+      Get 1, OniEntry(L).rDataPosition, ID4
+      If ID4 = TXMA_E(I).TXMP_ID Then
+        TexNames(I) = OniEntry(L).szTagName + Ext
+        Exit For
+      End If
+    Next L
+  Next I
+
+Close
+'Ok
+' so we have: 3D points, Texture coordinates and list of polygons,
+' end reading, now convert data
+I = 0
+Open App.Path + "\lwo.tmp" For Binary As #11
+Form1.StatusBar1.SimpleText = "Status: Extracting LEVEL [Reading Polygons...]"
+Seek 11, 1
+
+'reading polygons.......
+
+NP = AGQG.NumEntries * 2
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+  Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  NP = NP - 2
+  Case Else
+    Select Case Mid$(GetPureFile(TexNames(AGQR_E(I).TexIndex)), 1, 5)
+     Case "_DOOR"
+       NP = NP - 2
+     Case Else
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(1))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(2))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(3))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(3))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(4))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(1))
+    End Select
+  End Select
+Next I
+
+
+
+ReDim OniPol2(NP - 1)
+ReDim LwoP(NP - 1)
+Get 11, 1, OniPol2
+
+For I = 0 To NP - 1
+  LwoP(I).NumVe = ISItoMSI(3)
+  LwoP(I).P1 = OniPol2(I).P1
+  LwoP(I).P2 = OniPol2(I).P2
+  LwoP(I).P3 = OniPol2(I).P3
+  LwoP(I).Surfa = ISItoMSI(1)
+Next I
+
+I = Empty
+
+Close
+
+On Error Resume Next
+  Kill App.Path + "\*.tmp"
+On Error GoTo 0
+
+Form1.StatusBar1.SimpleText = "Status: Extracting LEVEL [Writing...]"
+Form1.ProgressBar1.Max = PNTA.NumEntries
+Form1.ProgressBar1.Value = 0
+If LevelType = 5 Or LevelType = 10 Then
+  FileName = GetPureFile(FileName) + ".raw"
+End If
+
+For I = 0 To PNTA.NumEntries - 1
+   If PNTAentry(I).X > 2000000.1 Then PNTAentry(I).X = 0
+   If PNTAentry(I).Y > 2000000.1 Then PNTAentry(I).Y = 0
+   If PNTAentry(I).Z > 2000000.1 Then PNTAentry(I).Z = 0
+   If PNTAentry(I).X < -2000000.1 Then PNTAentry(I).X = 0
+   If PNTAentry(I).Y < -2000000.1 Then PNTAentry(I).Y = 0
+   If PNTAentry(I).Z < -2000000.1 Then PNTAentry(I).Z = 0
+Next I
+
+Select Case LevelType
+Case 1
+
+Open FileName For Binary As #1
+  Put 1, , "FORM"
+  Put 1, , ISLtoMSL(12 + (PNTA.NumEntries * 12) + 8 + 6 + 8 + (NP * 10))
+  Put 1, , "LWOBPNTS"
+  Put 1, , ISLtoMSL(PNTA.NumEntries * 12)
+  For I = 0 To PNTA.NumEntries - 1
+    Put 1, , SwapFloat(PNTAentry(I).X)
+    Put 1, , SwapFloat(PNTAentry(I).Y)
+    Put 1, , SwapFloat(PNTAentry(I).Z)
+    Form1.ProgressBar1.Value = I
+  Next I
+  Put 1, , "SRFS"
+  Put 1, , ISLtoMSL(6)
+  Put 1, , "Level"
+  Put 1, , CByte(0)
+  Put 1, , "POLS"
+  Put 1, , ISLtoMSL(NP * 10)
+  Put 1, , LwoP
+Close
+Case 6
+
+' Convert Oni level to RAW 3D Binary
+Open GetPureFile(FileName) + ".rwb" For Binary As #1
+For I = 0 To AGQG.NumEntries - 1
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Z
+Next I
+
+Close
+Case 7
+
+' B3D
+Open GetPureFile(FileName) + ".b3d" For Binary As #1
+Put 1, , "Big3DbyOleg"
+Put 1, , CLng(1067030938)
+Put 1, , "POINTS  "
+Put 1, , CLng(PNTA.NumEntries)
+For I = 0 To PNTA.NumEntries - 1
+  Put 1, , PNTAentry(I).X
+  Put 1, , PNTAentry(I).Y
+  Put 1, , PNTAentry(I).Z
+Next I
+
+Put 1, , "POLYGONS"
+Put 1, , CLng(NP * 2)
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+  Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+    'nothing
+  Case Else
+    Select Case Mid$(GetPureFile(TexNames(AGQR_E(I).TexIndex)), 1, 5)
+     Case "_DOOR"
+       'nothing
+     Case Else
+       Put 1, , CLng(3)
+       Put 1, , AGQGEntry(I).VertIndex(1)
+       Put 1, , AGQGEntry(I).VertIndex(2)
+       Put 1, , AGQGEntry(I).VertIndex(3)
+       Put 1, , CLng(0)
+       Put 1, , CLng(3)
+       Put 1, , AGQGEntry(I).VertIndex(3)
+       Put 1, , AGQGEntry(I).VertIndex(4)
+       Put 1, , AGQGEntry(I).VertIndex(1)
+       Put 1, , CLng(0)
+    End Select
+End Select
+Next I
+Put 1, , CLng(0)
+Close
+
+Case 8
+
+'Delete shit from the Oni level
+numb = AGQG.NumEntries
+   ReDim Preserve PNTAentry(PNTA.NumEntries + 3)
+   PNTAentry(PNTA.NumEntries + 0).X = -9
+   PNTAentry(PNTA.NumEntries + 0).Y = 0
+   PNTAentry(PNTA.NumEntries + 0).Z = -3
+   PNTAentry(PNTA.NumEntries + 1).X = -9
+   PNTAentry(PNTA.NumEntries + 1).Y = 0
+   PNTAentry(PNTA.NumEntries + 1).Z = 8
+   PNTAentry(PNTA.NumEntries + 2).X = 11
+   PNTAentry(PNTA.NumEntries + 2).Y = 0
+   PNTAentry(PNTA.NumEntries + 2).Z = -3
+   PNTAentry(PNTA.NumEntries + 3).X = 11
+   PNTAentry(PNTA.NumEntries + 3).Y = 0
+   PNTAentry(PNTA.NumEntries + 3).Z = 8
+
+   If Form1.mnuDelGarbage.Checked = True Then
+   For I = 0 To AGQG.NumEntries - 1
+     Select Case Mid$(GetPureFile(TexNames(AGQR_E(I).TexIndex)), 1, 5)
+     Case "_DOOR"
+        AGQGEntry(I).VertIndex(1) = PNTA.NumEntries + 0
+        AGQGEntry(I).VertIndex(2) = PNTA.NumEntries + 1
+        AGQGEntry(I).VertIndex(3) = PNTA.NumEntries + 2
+        AGQGEntry(I).VertIndex(4) = PNTA.NumEntries + 3
+        'numb = numb - 1
+     End Select
+   Next I
+   End If
+
+   For I = 0 To AGQG.NumEntries - 1
+     Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+     Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+        AGQGEntry(I).VertIndex(1) = PNTA.NumEntries + 0
+        AGQGEntry(I).VertIndex(2) = PNTA.NumEntries + 1
+        AGQGEntry(I).VertIndex(3) = PNTA.NumEntries + 2
+        AGQGEntry(I).VertIndex(4) = PNTA.NumEntries + 3
+        numb = numb - 1
+     End Select
+   Next I
+
+'B3D + materials
+Open GetPureFile(FileName) + ".b3d" For Binary As #1
+Put 1, , "Big3DbyOleg"
+Put 1, , CLng(1067030938)
+Put 1, , "POINTS  "
+Put 1, , CLng(numb * 4)
+
+For I = 0 To AGQG.NumEntries - 1
+  ' Begin polygon
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+ Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  'nothing
+ Case Else
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Z
+
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).Z
+
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Z
+
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).Z
+End Select
+  ' end polygon
+Next I
+
+Put 1, , "POLYGONS"
+Put 1, , CLng(numb * 2)
+L = 0
+ID4 = 0
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+ Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  'nothing
+ Case Else
+  Put 1, , CLng(3)
+  Put 1, , CLng(L)
+  Put 1, , CLng(L + 1)
+  Put 1, , CLng(L + 2)
+  Put 1, , CLng(ID4)
+  Put 1, , CLng(3)
+  Put 1, , CLng(L + 2)
+  Put 1, , CLng(L + 3)
+  Put 1, , CLng(L)
+  Put 1, , CLng(ID4)
+  ID4 = ID4 + 1
+  L = L + 4
+End Select
+Next I
+
+Put 1, , CLng(1)
+Put 1, , "TEX_UV  "
+Put 1, , CLng(numb * 4)
+L = 0
+
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+ Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  'nothing
+ Case Else
+  Put 1, , CLng(L)
+  L = L + 1
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(1)).X
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(1)).Y
+  Put 1, , CLng(L)
+  L = L + 1
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(2)).X
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(2)).Y
+  Put 1, , CLng(L)
+  L = L + 1
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(3)).X
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(3)).Y
+  Put 1, , CLng(L)
+  L = L + 1
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(4)).X
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(4)).Y
+End Select
+  'Put 1, , CSng((-TXCA_E(I).Y) + 1)
+Next I
+
+L = 0
+Put 1, , "MATERIAL"
+Put 1, , CLng(numb)
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+ Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  'nothing
+ Case Else
+  Put 1, , CLng(1)
+  Put 1, , CLng(L)
+  Put 1, , CLng(Len(TexNames(AGQR_E(I).TexIndex)))
+  Put 1, , TexNames(AGQR_E(I).TexIndex)
+  L = L + 1
+End Select
+Next I
+Close
+
+Open GetPureFile(FileName) + ".tlist" For Binary As #4
+  For I = 0 To AGQR1.NumEntries - 1
+  Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+  Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+   'nothing
+  Case Else
+    Put 4, , AGQR_E(I).TexIndex
+  End Select
+  Next I
+Close
+
+Open GetPureFile(FileName) + ".txt" For Output As #4
+  Print #4, CStr(TXMA1.NumEntries)
+  For I = 0 To TXMA1.NumEntries - 1
+    Print #4, CStr(GetPureFile(TexNames(I)))
+  Next I
+Close
+
+If Form1.mnuB3DLight.Checked = True Then
+Open GetPureFile(FileName) + ".ltcs" For Binary As #4
+  For I = 0 To AGQR1.NumEntries - 1
+  Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+  Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+   'nothing
+  Case Else
+    Put 4, , AGQGEntry(I).LData_1
+    Put 4, , AGQGEntry(I).LData_2
+    Put 4, , AGQGEntry(I).LData_3
+    Put 4, , AGQGEntry(I).LData_4
+  End Select
+  Next I
+Close
+End If
+End Select
+
+Form1.ProgressBar1.Value = 0
+Form1.ProgressBar1.Max = UBound(OniEntry)
+
+Form1.StatusBar1.SimpleText = "OK"
+'Dispose
+I = Empty
+NP = Empty
+Erase LwoP
+Erase PNTAentry
+Erase OniPol2
+Erase AGQGEntry
+Erase AGQR_E
+Erase TXMA_E
+Erase TXCA_E
+Erase TexNames
+End Sub
Index: /oup/releases/0.33a/text/blubb.txt
===================================================================
--- /oup/releases/0.33a/text/blubb.txt	(revision 76)
+++ /oup/releases/0.33a/text/blubb.txt	(revision 76)
@@ -0,0 +1,6 @@
+___FILEINDEX___.txt
+
+
+TXMP:
+MipMapping: Bit0=an/aus
+ColorDepth: Bit0=??AnimationPic??, Bit1=shade vertex, Bit2=transparency, Bit4=16bit, Bit5=32bit
Index: /oup/releases/0.33a/text/changelog.txt
===================================================================
--- /oup/releases/0.33a/text/changelog.txt	(revision 76)
+++ /oup/releases/0.33a/text/changelog.txt	(revision 76)
@@ -0,0 +1,114 @@
+OniUnPacker v0.32a
+------------------
++DB2Dat functionality enhanced (*can* be used but is not yet finished)
++PSpc Preview added (but not yet working cause of some weird bugs)
+
+OniUnPacker v0.32a
+------------------
++Raw-part "BodyPartAnimation data" of TRAMs
++Added basic DB2Dat functionality (SHOULD NOT BE USED YET!!!)
++CharSet selection (works for ValueViewer only right now)
+
+OniUnPacker v0.31a
+------------------
++Dat2DB function working
++Fixed a bug which appeared when multiple windows of the same class were opened at one time (eg 2*BinEdit)
+
+OniUnPacker v0.30a
+------------------
++Completely rewritten data-backend-connection-classes (Unit15_Classes.pas)
+
+OniUnPacker v0.29a
+------------------
++Little changes in StructureDefs
+
+OniUnPacker v0.29a
+------------------
++New StructureViewer
++New StructureTypes: 12=.dat-file-ID, 13..16=SignedInteger, 1000..9999=Unused data
++Dynamic Structures (look at TXAN-files or AISA-files for examples)
++File-type associations (.dat, .oldb, .opf) with OUP possible
++File IDs as Hex
+
+OniUnPacker v0.28a
+------------------
++StructureDefinitions as separate txt-files
++Minor bugfixes
++Ctrl+C for Hex-fields
+
+OniUnPacker v0.27a
+------------------
++Added MAC-file support
++Added StructureDefs for ONCCs / TRAMs (thanks to SSG)
+
+OniUnPacker v0.26a
+------------------
++Fixed some bugs again ;)
+
+OniUnPacker v0.25a
+------------------
++Fixed some bugs here and there ;)
++BinEdit/RawEdit: Added keycombo CTRL+S for saving current file
+
+OniUnPacker v0.24a
+------------------
++RawEdit. Open it by doubleclick on a Raw-Link in the StructureViewer of BinEdit or enter the FileID and the offset of the raw-link in the .dat-file manually
+
+OniUnPacker v0.23a
+------------------
++Added copy2clipboard functions to ValueViewer (rightclick)
++Enhanced FileList-filters
++Added ValueEditor to BinEdit -> StructViewer / ValueViewer (doubleclick on either value field of ValueViewer or StructViewer)
+
+OniUnPacker v0.22a
+------------------
++Replaced DB-Backend (much faster conversion of levels)
++Added ValueViewer to BinEdit (decodes selected area as different variable-types)
+
+OniUnPacker v0.21a
+------------------
++Extractor tool works almost completely (you can't select where the files are stored if you *don't* choose to put them all in one file. They are stored in the root of drive d:)
++Corrected string-display in the structure viewer of BinEdit (strings are now displayed as a hint of the value-box if you move the mouse over it)
+
+OniUnPacker v0.20a
+------------------
++? (Forgot what I added here ;) )
+
+OniUnPacker v0.19a
+------------------
++.dat/.raw -> OUP-Level-DB-Convert basics
++Extractor tool (not working yet :D )
+
+OniUnPacker v0.18a
+------------------
++Completely rewritten GUI
+
+OniUnPacker v0.17a
+------------------
++Binary-editor: Structure-viewer (only TXMP so far)
+
+OniUnPacker v0.16a
+------------------
++Replaced hex-view-box with a true hex-component
++Binary-editor for .dat-files
+
+OniUnPacker v0.15a
+------------------
++Extract menu
++Changed layout
+
+OniUnPacker v0.14a
+------------------
++Corrected image-decoder for 32bit images
++TXMP-Replace: 32bit option (for prevention from quality loss)
+
+OniUnPacker v0.13a
+------------------
++TXMP-Replace: Transparency option
++TXMP-Replace: Fading option
++TXMP-Replace: Overwrites old data if the new fits in that space (to keep the raw as small as possible)
+
+OniUnPacker v0.12a
+------------------
++TXMP-Replace function (Menu -> Tools -> TXMP Replacer)
++TXMB-Decoder (export with convert & preview)
Index: /oup/releases/0.33a/text/selects.txt
===================================================================
--- /oup/releases/0.33a/text/selects.txt	(revision 76)
+++ /oup/releases/0.33a/text/selects.txt	(revision 76)
@@ -0,0 +1,3 @@
+SELECT (datfiles.name || "." || datfiles.extension) AS name, count(src_id) AS x, src_id FROM linkmap LEFT JOIN datfiles ON datfiles.id=src_id GROUP BY src_id ORDER BY x DESC
+
+SELECT (datfiles.name || "." || datfiles.extension) AS name, count(src_id) AS x, src_id FROM rawmap LEFT JOIN datfiles ON datfiles.id=src_id GROUP BY src_id ORDER BY x DESC
Index: /oup/releases/0.33a/text/todo.txt
===================================================================
--- /oup/releases/0.33a/text/todo.txt	(revision 76)
+++ /oup/releases/0.33a/text/todo.txt	(revision 76)
@@ -0,0 +1,74 @@
+-Non32bit MipMapping (???)
+-32byte paddings
+
+-Compo: TBitSetEdit mit 8 CheckBoxes + Captions
+-ValueEdit: TBitSetEdit
+
+-StructViewer: TBitSetEdit?
+-Structs: Nach Paketen wieder Global?
+-Idents: Unterschied für Sep-Linked und SNDD
+-NamedLinks: Überprüfung auf 0 files? (level0.dat)
+-Links: Wenn level0 dann OUP mit level0 laden?
+
+-History:Geyser:14.04.06 15:11:45, 16.04.06 15:21:29
+-Patching: History Geyser 2006-04-30 - 04:07:00
+
+-RawParts: AGDB immer 32 bytes
+
+-Signed vs Unsigned
+
+-PNG statt/zusätzlich zu BMP
+
+-AppSettings: Erst initialisieren mit defaults, dann .ini lesen
+
+-Exporters (-> TOniImage etc)
+
+-Wiki etc: Links für benutzte Componenten
+-SourceCode docu (eg: http://www.time2help.com/)
+-ProgHelp
+-Localization (eg: http://dybdahl.dk/dxgettext/)
+-About
+
+-StructViewer: Strings bis 0x00, BitSets besser darstellen? (SSG: 18.04.06/10:52:58),
+  Dat-Link value="Not used" wenn not-used, SUBT-Packages: Value=0???,
+  file-ID-value dblclick=edit / anderes=follow,
+  "typed"-file-id-links?,
+  0 packages -> crash?
+
+-Dateityp-Name anzeigen (SUBT -> Subtitles etc)
+
+-IGSt: Bei DEAD: OUP hangs (ValueViewer:String?)
+
+-Bug bei SetNewValue mit String
+
+-Preview PSpc (!!!)
+-Preview: Models? 3D-Data?
+
+-Get files die bestimmten content haben (string etc)
+
+-Cursor Sanduhr bei Wartezeiten (db-access etc)
+
+-Exporter: Checkboxes für was man im einzelnen will (zb Checkbox "in eine Datei ja/nein")
+-Extrahier-Ordner-Option (mit Platzhalter für .dat-Name)
+-Extractor: Wohin?
+
+-Hex: Paste
+
+
+
+-SELECT [src_id],MIN(datfiles.[name]),SUM(rawmap.[size]) FROM rawmap INNER  JOIN datfiles ON datfiles.[id]=[src_id] GROUP BY [src_id] ORDER BY [src_id] ASC
+
+
+-BinEdit: Zusatzfunktionen wie: Suche, 
+
+-FileCompare: Ergebnis=Tabelle, jede Zeile eine differenz-addresse, spalten = werte an addr. für compared files
+
+-TXMP-Replace: MultiReplace
+
+-Move-Freischalter (Mindestlvl eingabe)
+
+-Löschen einer Datei auf die gelinkt wird: Liste der Links und sicherheitsfrage
+
+-STRG+C auf Dateilisten etc für kopieren des Namens
+
+-REPACKING: testen lvl0: 690-collisions.txmp einbauen, script: collisions-zeug
