Index: oup/current/DataAccess/Access_OniArchive.pas
===================================================================
--- oup/current/DataAccess/Access_OniArchive.pas	(revision 207)
+++ oup/current/DataAccess/Access_OniArchive.pas	(revision 209)
@@ -16,7 +16,8 @@
     FRawOpened:          Boolean;
     FSepOpened:          Boolean;
+    procedure SetUnloadWhenUnused(doit: Boolean);
   protected
   public
-    property UnloadWhenUnused: Boolean Read FUnloadWhenUnused Write FUnloadWhenUnused;
+    property UnloadWhenUnused: Boolean Read FUnloadWhenUnused Write SetUnloadWhenUnused;
 
     constructor Create(DatFilename: String; ConnectionID: Integer; var Msg: TStatusMessages); override;
@@ -161,4 +162,51 @@
   FChangeRights := [CR_EditDat, CR_EditRaw, CR_AppendRaw];
 end;
+
+
+
+
+procedure TAccess_OniArchive.SetUnloadWhenUnused(doit: Boolean);
+begin
+  FUnloadWhenUnused := doit;
+  if FUnloadWhenUnused then
+  begin
+    if FDatOpened then
+    begin
+      FDatOpened := False;
+      Fdat_file.Free;
+    end;
+    if FRawOpened then
+    begin
+      FRawOpened := False;
+      Fraw_file.Free;
+    end;
+    if FSepOpened then
+    begin
+      FSepOpened := False;
+      Fsep_file.Free;
+    end;
+  end
+  else
+  begin
+    if not FDatOpened then
+    begin
+      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
+      FDatOpened := True;
+    end;
+    if not FRawOpened then
+    begin
+      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
+        fmOpenReadWrite);
+      FRawOpened := True;
+    end;
+    if (not FSepOpened) and (FDataOS <> DOS_WIN) then
+    begin
+      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
+        fmOpenReadWrite);
+      FSepOpened := True;
+    end;
+  end;
+end;
+
 
 
Index: oup/current/FileClasses/TXMP.pas
===================================================================
--- oup/current/FileClasses/TXMP.pas	(revision 207)
+++ oup/current/FileClasses/TXMP.pas	(revision 209)
@@ -4,5 +4,5 @@
 
 uses
-  TypeDefs, _FileTypes, _DataTypes;
+  _FileTypes;
 
 type
@@ -17,19 +17,7 @@
 
 uses
-  ConnectionManager, Math, Classes;
+  ConnectionManager, Math, Classes, TypeDefs, _DataTypes;
 
-{ TFile_SNDD }
-
-procedure TFile_TXMP.InitDatLinks;
-begin
-  SetLength(FDatLinks, 2);
-  FDatLinks[0].SrcOffset := $94;
-  FDatLinks[0].DestID := -1;
-  FDatLinks[0].PosDestExts := '*';
-  FDatLinks[1].SrcOffset := $98;
-  FDatLinks[1].DestID := -1;
-  FDatLinks[1].PosDestExts := 'TXMP';
-end;
-
+{ TFile_TXMP }
 
 procedure TFile_TXMP.InitDataFields;
@@ -119,4 +107,16 @@
 
 
+procedure TFile_TXMP.InitDatLinks;
+begin
+  SetLength(FDatLinks, 2);
+  FDatLinks[0].SrcOffset := $94;
+  FDatLinks[0].DestID := GetDatLinkValue(FFile, $94);
+  FDatLinks[0].PosDestExts := '*';
+  FDatLinks[1].SrcOffset := $98;
+  FDatLinks[1].DestID := GetDatLinkValue(FFile, $98);
+  FDatLinks[1].PosDestExts := 'TXMP';
+end;
+
+
 procedure TFile_TXMP.InitRawList;
 var
Index: oup/current/FileClasses/_FileManager.pas
===================================================================
--- oup/current/FileClasses/_FileManager.pas	(revision 209)
+++ oup/current/FileClasses/_FileManager.pas	(revision 209)
@@ -0,0 +1,81 @@
+unit _FileManager;
+interface
+
+uses _FileTypes, TXMP;
+
+type
+  TFileType = class of TFile;
+  TFileDesc = record
+    ext: String;
+    ftype: TFileType;
+  end;
+
+const
+  FileDescs: array[0..0] of TFileDesc = (
+    (ext: 'TXMP'; ftype: TFile_TXMP)
+  );
+
+type
+  TFileManager = class
+    protected
+      FFiles: array of TFile;
+      FConnectionID: Integer;
+      function GetFileCount: Integer;
+      function GetFileById(Id: Integer): TFile;
+    public
+      constructor Create(ConnectionID: Integer);
+
+      property FileCount: Integer read GetFileCount;
+      property FileById[Id: Integer]: TFile read GetFileById;
+  end;
+
+implementation
+
+uses
+  Classes, ConnectionManager, Access_OniArchive, TypeDefs, Dialogs, SysUtils, StrUtils;
+
+{ TFileManager }
+
+constructor TFileManager.Create(ConnectionID: Integer);
+var
+  files: TStrings;
+  i: Integer;
+  typei: Integer;
+  fid: Integer;
+begin
+  FConnectionID := ConnectionID;
+  if ConManager.Connection[ConnectionID] is TAccess_OniArchive then
+    TAccess_OniArchive(ConManager.Connection[ConnectionID]).UnloadWhenUnused := False;
+  files := TStringList.Create;
+  files := ConManager.Connection[ConnectionID].GetFilesList('', '', False, ST_IDAsc);
+  if files.Count > 0 then
+  begin
+    for i := 0 to files.Count - 1 do
+    begin
+      for typei := 0 to High(FileDescs) do
+      begin
+        if Pos('.' + FileDescs[typei].ext, files.Strings[i]) = Length(files.Strings[i]) - 4 then
+        begin
+          SetLength(FFiles, Length(FFiles) + 1);
+          fid := StrToInt(MidStr(files.Strings[i], 1, 5));
+          FFiles[High(FFiles)] := TFileType(FileDescs[typei].ftype).Create(FConnectionID, fid);
+        end;
+      end;
+    end;
+  end;
+  files.Free;
+  if ConManager.Connection[ConnectionID] is TAccess_OniArchive then
+    TAccess_OniArchive(ConManager.Connection[ConnectionID]).UnloadWhenUnused := True;
+end;
+
+function TFileManager.GetFileById(Id: Integer): TFile;
+begin
+  Result := FFiles[Id];
+end;
+
+function TFileManager.GetFileCount: Integer;
+begin
+  Result := Length(FFiles);
+end;
+
+end.
Index: oup/current/FileClasses/_FileTypes.pas
===================================================================
--- oup/current/FileClasses/_FileTypes.pas	(revision 207)
+++ oup/current/FileClasses/_FileTypes.pas	(revision 209)
@@ -12,4 +12,5 @@
       FConnectionID: Integer;
       FFileID: Integer;
+      FFileName: String;
       FFile: TMemoryStream;
 
@@ -34,4 +35,5 @@
       property FileStream: TMemoryStream read FFile;
       property FileID: Integer read FFileID;
+      property FileName: String read FFileName;
       property ConnectionID: Integer read FConnectionID;
 
@@ -50,4 +52,8 @@
 
 
+function GetDatLinkValue(stream: TStream; offset: Integer): Integer;
+
+
+
 implementation
 
@@ -63,5 +69,5 @@
   FConnectionID := ConnectionID;
   FFileID := FileID;
-  FFile := nil;
+  FFileName := ConManager.Connection[ConnectionID].GetFileInfo(FileID).Name;
 
   FFile := TMemoryStream.Create;
@@ -71,12 +77,4 @@
   InitDataFields();
   InitRawList();
-
-  if FDataFields.FieldCount > 0 then
-  begin
-    for i := 0 to FDataFields.FieldCount - 1 do
-    begin
-      ShowMessage(FDataFields.FieldByIndex[i].ValueAsString);
-    end;
-  end;
 
   FFile.Free;
@@ -171,3 +169,15 @@
 end;
 
+
+
+function GetDatLinkValue(stream: TStream; offset: Integer): Integer;
+begin
+  stream.Seek(Offset, soFromBeginning);
+  stream.Read(Result, 4);
+  if Result > 0 then
+    Result := Result div 256
+  else
+    Result := -1;
+end;
+
 end.
Index: oup/current/Global/RawList.pas
===================================================================
--- oup/current/Global/RawList.pas	(revision 207)
+++ oup/current/Global/RawList.pas	(revision 209)
@@ -200,16 +200,10 @@
   Result[0].SrcOffset := $0C;
   Result[0].RawAddr   := link;
-  if link > 0 then
-    Result[0].RawSize := frames * 4
-  else
-    Result[0].RawSize := 0;
+  Result[0].RawSize := frames * 4;
   {y-pos}
   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, 4, @link);
   Result[1].SrcOffset := $10;
   Result[1].RawAddr   := link;
-  if link > 0 then
-    Result[1].RawSize := frames * 8
-  else
-    Result[1].RawSize := 0;
+  Result[1].RawSize := frames * 8;
   {attacks}
   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $182, 1, @tempb);
@@ -240,8 +234,5 @@
   Result[6].SrcOffset := $24;
   Result[6].RawAddr   := link;
-  if link > 0 then
-    Result[6].RawSize := 24
-  else
-    Result[6].RawSize := 0;
+  Result[6].RawSize := 24;
   {footstep}
   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $186, 1, @tempb);
@@ -410,4 +401,8 @@
       Break;
     end;
+  if Length(Result) > 0 then
+    for i := 0 to High(Result) do
+      if Result[i].RawAddr = 0 then
+        Result[i].RawSize := 0;
 end;
 
Index: oup/current/Main.dfm
===================================================================
--- oup/current/Main.dfm	(revision 207)
+++ oup/current/Main.dfm	(revision 209)
@@ -6,5 +6,5 @@
   Caption = 'Form_Main'
   ClientHeight = 571
-  ClientWidth = 742
+  ClientWidth = 842
   Color = clBtnFace
   Constraints.MinHeight = 500
@@ -26,5 +26,5 @@
     Left = 0
     Top = 554
-    Width = 742
+    Width = 842
     Height = 17
     BiDiMode = bdLeftToRight
@@ -43,10 +43,12 @@
       end>
     ParentBiDiMode = False
+    ExplicitWidth = 742
   end
   object DockTop: TTBDock
     Left = 0
     Top = 0
-    Width = 742
+    Width = 842
     Height = 75
+    ExplicitWidth = 742
     object MainMenu: TTBToolbar
       Left = 0
@@ -135,5 +137,4 @@
         object menu_meta: TTBItem
           Caption = '&Meta editor'
-          Enabled = False
           ImageIndex = 11
           ShortCut = 16461
@@ -353,16 +354,18 @@
   end
   object DockRight: TTBDock
-    Left = 733
+    Left = 833
     Top = 75
     Width = 9
     Height = 470
     Position = dpRight
+    ExplicitLeft = 733
   end
   object DockBottom: TTBDock
     Left = 0
     Top = 545
-    Width = 742
+    Width = 842
     Height = 9
     Position = dpBottom
+    ExplicitWidth = 742
   end
   object opend: TOpenDialog
Index: oup/current/Main.pas
===================================================================
--- oup/current/Main.pas	(revision 207)
+++ oup/current/Main.pas	(revision 209)
@@ -136,5 +136,5 @@
 
 uses
-  LevelDB;
+  LevelDB, MetaEditor;
 
 {$R *.dfm}
@@ -415,4 +415,5 @@
   tb_txmpreplacer.Enabled := active;
   tb_extractor.Enabled := active;
+  tb_meta.Enabled := active;
 //  tb_compare.Enabled := active;
 //  tb_structure.Enabled := active;
@@ -605,6 +606,31 @@
 
 procedure TForm_Main.menu_metaClick(Sender: TObject);
-begin
-  ShowMessage('TBD');
+var
+  toolform:    TForm_Meta;
+  i:           Integer;
+  tag:         Integer;
+  iconindex:   Integer;
+begin
+  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;
+
+  toolform := nil;
+
+  toolform         := TForm_Meta.Create(Self);
+  toolform.Caption := 'MetaEditor' + ' ' + IntToStr(tag) + '       ';
+  iconindex        := 11;
+
+  if Assigned(toolform) then
+  begin
+    toolform.Name    := 'meta' + IntToStr(tag);
+    toolform.Tag     := tag;
+    MDITab.AddTab(TForm(toolform), iconindex);
+    toolform.Caption := AnsiReplaceStr(toolform.Caption, '       ', '');
+  end;
 end;
 
Index: oup/current/OniUnPacker.bdsproj
===================================================================
--- oup/current/OniUnPacker.bdsproj	(revision 207)
+++ oup/current/OniUnPacker.bdsproj	(revision 209)
@@ -176,9 +176,5 @@
 			<Language Name="ProjectLang">$00000000</Language>
 			<Language Name="RootDir"></Language>
-		</Language>  
-    
-    
-    
-    <Excluded_Packages>
+		</Language>  <Excluded_Packages>
       <Excluded_Packages Name="d:\programme\borland\bds\3.0\Bin\dbwebxprt.bpl">Borland Web Wizard Package</Excluded_Packages>
     </Excluded_Packages>
Index: oup/current/OniUnPacker.dpr
===================================================================
--- oup/current/OniUnPacker.dpr	(revision 207)
+++ oup/current/OniUnPacker.dpr	(revision 209)
@@ -32,5 +32,7 @@
   LevelDB in 'Helper\LevelDB.pas' {Form_LevelDB},
   Img_DDSTypes in 'Global\Img_DDSTypes.pas',
-  TXMP in 'FileClasses\TXMP.pas';
+  TXMP in 'FileClasses\TXMP.pas',
+  MetaEditor in 'Tools\MetaEditor.pas' {Form_Meta},
+  _FileManager in 'FileClasses\_FileManager.pas';
 
 {$R *.res}
Index: oup/current/Tools/MetaEditor.dfm
===================================================================
--- oup/current/Tools/MetaEditor.dfm	(revision 209)
+++ oup/current/Tools/MetaEditor.dfm	(revision 209)
@@ -0,0 +1,53 @@
+object Form_Meta: TForm_Meta
+  Left = 0
+  Top = 0
+  Caption = 'Form_Meta'
+  ClientHeight = 293
+  ClientWidth = 426
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIChild
+  OldCreateOrder = False
+  Visible = True
+  WindowState = wsMaximized
+  OnClose = FormClose
+  OnCreate = FormCreate
+  DesignSize = (
+    426
+    293)
+  PixelsPerInch = 96
+  TextHeight = 13
+  object VST: TVirtualStringTree
+    Left = 8
+    Top = 8
+    Width = 389
+    Height = 265
+    Anchors = [akLeft, akTop, akRight, akBottom]
+    AnimationDuration = 0
+    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, hoDrag, hoVisible]
+    TabOrder = 0
+    TreeOptions.MiscOptions = [toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning]
+    TreeOptions.PaintOptions = [toShowDropmark, toShowRoot, toShowTreeLines, toThemeAware, toUseBlendedImages]
+    OnGetText = VSTGetText
+    Columns = <
+      item
+        Position = 0
+        Width = 150
+        WideText = 'Main'
+      end
+      item
+        Position = 1
+        WideText = 'Data'
+      end>
+  end
+end
Index: oup/current/Tools/MetaEditor.pas
===================================================================
--- oup/current/Tools/MetaEditor.pas	(revision 209)
+++ oup/current/Tools/MetaEditor.pas	(revision 209)
@@ -0,0 +1,200 @@
+unit MetaEditor;
+interface
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, VirtualTrees, _FileManager;
+
+type
+  TForm_Meta = class(TForm)
+    VST: TVirtualStringTree;
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+    procedure FormCreate(Sender: TObject);
+    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
+      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
+  private
+  public
+    FileManager: TFileManager;
+  end;
+
+var
+  Form_Meta: TForm_Meta;
+
+implementation
+uses
+  Data, _DataTypes, _FileTypes;
+{$R *.dfm}
+
+type
+  PNodeData = ^TNodeData;
+
+  TNodeData = record
+    Field: TObject;
+  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_Meta.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  FileManager.Free;
+  Action := caFree;
+end;
+
+
+procedure TForm_Meta.FormCreate(Sender: TObject);
+var
+  a,b,c: Int64;
+  i: Integer;
+  data: TNodeData;
+begin
+  VST.NodeDataSize := SizeOf(TNodeData);
+  VST.Font.Charset := AppSettings.CharSet;
+  VST.Clear;
+
+  QueryPerformanceFrequency(c);
+  QueryPerformanceCounter(a);
+  FileManager := TFileManager.Create(1);
+  QueryPerformanceCounter(b);
+  ShowMessage('Loading Done - ' + FloatToStr((b-a)/c) + 's');
+
+  for i := 0 to FileManager.FileCount - 1 do
+  begin
+    data.Field := FileManager.FileById[i];
+    AddVSTEntry(VST, nil, data);
+  end;
+end;
+
+
+
+procedure TForm_Meta.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: begin
+        if Data.Field is TFile then
+        begin
+          CellText := TFile(Data.Field).FileName;
+        end;
+      end;
+{      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(StrToInt(Data.Value)) + ' Bytes';
+      4:
+        CellText := Data.Description;
+}    end;
+  end;
+end;
+
+{
+
+procedure WriteStructureInfos;
+var
+  i, j:    Integer;
+  pdata:   PNodeData;
+  Data:    TNodeData;
+  node:    PVirtualNode;
+begin
+  VST.BeginUpdate;
+  if VST.RootNodeCount = 0 then
+  begin
+    structs := LoadStructureDefinition(ConID, 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  := StrToInt('$'+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;
+}
+end.
Index: oup/current/Tools/Preview.dfm
===================================================================
--- oup/current/Tools/Preview.dfm	(revision 207)
+++ oup/current/Tools/Preview.dfm	(revision 209)
@@ -27,9 +27,12 @@
     end
     object img: TImage
-      Left = 0
-      Top = 20
-      Width = 283
-      Height = 403
+      AlignWithMargins = True
+      Left = 3
+      Top = 23
+      Width = 277
+      Height = 397
       Align = alClient
+      ExplicitLeft = 0
+      ExplicitTop = 20
       ExplicitWidth = 313
       ExplicitHeight = 453
Index: oup/current/Tools/TxmpReplace.dfm
===================================================================
--- oup/current/Tools/TxmpReplace.dfm	(revision 207)
+++ oup/current/Tools/TxmpReplace.dfm	(revision 209)
@@ -84,9 +84,12 @@
       TabOrder = 0
       object image_bmppreview: TImage
-        Left = 2
-        Top = 45
-        Width = 279
-        Height = 297
+        AlignWithMargins = True
+        Left = 5
+        Top = 48
+        Width = 273
+        Height = 291
         Align = alClient
+        ExplicitLeft = 2
+        ExplicitTop = 45
         ExplicitWidth = 182
         ExplicitHeight = 302
Index: oup/current/Tools/TxmpReplace.pas
===================================================================
--- oup/current/Tools/TxmpReplace.pas	(revision 207)
+++ oup/current/Tools/TxmpReplace.pas	(revision 209)
@@ -234,7 +234,4 @@
   Self.OnNewFileSelected := SelectFile;
   opend.Filter := saved.Filter;
-
-  TXMP := TFile_TXMP.Create(ConnectionID, 8552);
-  TXMP.Free;
 end;
 
