Index: oup/current/FileClasses/SUBT.pas
===================================================================
--- oup/current/FileClasses/SUBT.pas	(revision 238)
+++ oup/current/FileClasses/SUBT.pas	(revision 240)
@@ -4,8 +4,14 @@
 
 uses
-  _FileTypes;
+  _FileTypes, Grids, StdCtrls, ExtCtrls;
 
 type
   TFile_SUBT = class(TFile)
+      procedure SetOpened(Opened: Boolean); override;
+    private
+      grid: TStringGrid;
+      panel: TPanel;
+      save: TButton;
+      procedure saveclick(Sender: TObject); 
     public
       procedure InitDataFields; override;
@@ -16,42 +22,143 @@
 
 uses
-  ConnectionManager, Math, Classes, TypeDefs, _DataTypes, Forms, StdCtrls, Grids;
+  ConnectionManager, Math, Classes, TypeDefs, _DataTypes, Forms,
+  Controls;
 
 procedure TFile_SUBT.InitDataFields;
-var
-  tempi: Integer;
 begin
   inherited;
-  FDataFields := TBlock.Create(Self, nil, 0, 'Base', '', nil);
+  FDataFields := TBlock.Create(Self, nil, 'Base', '', []);
   with FDataFields do
   begin
-    AddField(TFileID, $00, 'FileID', '', nil);
+    AddField(TFileID, 'FileID', '', []);
+    AddField(TLevelID, 'LevelID', '', []);
+    AddField(TUnused, 'Unused data', '', [16]);
 
-    AddField(TLevelID, $04, 'LevelID', '', nil);
+    AddField(TRawLink, 'Raw Address', '', []);
 
-    tempi := 16;
-    AddField(TUnused, $08, 'Unused data', '', @tempi);
-
-    AddField(TRawLink, $18, 'Raw Address', '', nil);
-
-    tempi := 4;
-    with AddField(TArray, $1C, 'SUBT offsets array', '', @tempi) do
+    with TArray(AddField(TArray, 'SUBT offsets array', '', [4])) do
     begin
-      tempi := 4;
-      AddField(TInt, $00, 'Offset', '', @tempi);
+      AddField(TInt, 'Offset', '', [4]);
+      SetCount;
     end;
   end;
+  FDataFields.Update(0, -1);
+
   FFileStream.Free;
   FFileStream := nil;
 end;
 
-
 procedure TFile_SUBT.InitEditor;
-var
-  grid: TStringGrid;
 begin
   FEditor := TFrame.Create(nil);
   grid := TStringGrid.Create(FEditor);
+  grid.Align := alClient;
+  grid.DefaultRowHeight := 18;
+  grid.DefaultColWidth := 100;
+  grid.ColCount := 2;
+  grid.RowCount := 4;
+  grid.FixedRows := 1;
+  grid.FixedCols := 0;
+  grid.ColWidths[0] := 80;
+  grid.ColWidths[1] := 200;
+  grid.Cells[0, 0] := 'Name';
+  grid.Cells[1, 0] := 'Content';
+  grid.Options := [goColSizing,goEditing,
+      goVertLine,goHorzLine,goFixedVertLine,goFixedHorzLine];
   grid.Parent := FEditor;
+  panel := TPanel.Create(FEditor);
+  panel.Align := alBottom;
+  panel.Height := 30;
+  panel.Parent := FEditor;
+  save := TButton.Create(panel);
+  save.Top := 2;
+  save.Left := 2;
+  save.Width := 100;
+  save.Height := 26;
+  save.Caption := 'Save';
+  save.OnClick := saveclick;
+  save.Parent := panel;
+end;
+
+procedure TFile_SUBT.saveclick(Sender: TObject);
+var
+  i,j: Integer;
+  temps: String;
+  fs: TFileStream;
+  offset: Integer;
+begin
+  fs := TFileStream.Create('C:\Spiele\Oni\GameDataFolder\tests\messages_raw_recreated.hex', fmCreate);
+
+  i := grid.RowCount - 2;
+  FFileStream.Seek($1C, soFromBeginning);
+  FFileStream.Write(i, 4);
+  FFileStream.Size := $20 + i * 4; 
+  
+  for i := 0 to grid.RowCount - 2 do
+  begin
+    for j := 0 to 1 do
+    begin
+      if j = 0 then
+      begin
+        offset := fs.Size;
+        FFileStream.Seek($20 + i*4, soFromBeginning);
+        FFileStream.Write(offset, 4);
+      end;
+      temps := grid.Cells[j, i+1];
+      SetLength(temps, Length(temps)+1);
+      temps[Length(temps)] := #0;
+      fs.Write(temps[1], Length(temps));
+    end;
+  end;
+  fs.Free;
+  fs := TFileStream.Create('C:\Spiele\Oni\GameDataFolder\tests\messages_dat_recreated.hex', fmCreate);
+  ReCreateFile(fs);
+  fs.Free;
+end;
+
+
+procedure TFile_SUBT.SetOpened(Opened: Boolean);
+var
+  i,j: Integer;
+  offset: Integer;
+  temps: String;
+  pos: Integer;
+begin
+  inherited;
+  if Opened then
+  begin
+    CacheFile;
+    CacheRawFile($18);
+
+    FFileStream.Seek($1C, soFromBeginning);
+    FFileStream.Read(i, 4);
+
+    grid.RowCount := 1 + i;
+
+    for i := 0 to grid.RowCount - 2 do
+    begin
+      for j := 0 to 1 do
+      begin
+        if j = 0 then
+        begin
+          FFileStream.Seek($20 + i*4, soFromBeginning);
+          FFileStream.Read(offset, 4);
+          FRawCaches[0].Seek(offset, soFromBeginning);
+        end;
+        SetLength(temps, 200);
+        pos := 0;
+        repeat
+          Inc(pos);
+          FRawCaches[0].Read(temps[pos], 1);
+        until temps[pos] = #0;
+        SetLength(temps, pos - 1);
+        grid.Cells[j, i+1] := temps;
+      end;
+    end;
+
+  end else
+  begin
+    Exit;
+  end;
 end;
 
Index: oup/current/FileClasses/_DataTypes.pas
===================================================================
--- oup/current/FileClasses/_DataTypes.pas	(revision 238)
+++ oup/current/FileClasses/_DataTypes.pas	(revision 240)
@@ -28,4 +28,5 @@
 
       procedure Update(Offset, Length: Integer); virtual; abstract;
+      procedure WriteData(stream: TStream); virtual; abstract;
 
       property Offset: Integer read FOffset;
@@ -56,4 +57,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
       property FieldByOffset[Offset: Integer]: TDataField read GetFieldByOffset;
 
@@ -73,4 +75,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
   end;
 
@@ -85,4 +88,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
   end;
 
@@ -98,4 +102,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
   end;
 
@@ -110,4 +115,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
   end;
 
@@ -122,8 +128,17 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
-  end;
-
-
-  TLinkByID = class(TDataField)
+      procedure WriteData(stream: TStream); override;
+  end;
+
+
+  TDatLink = class(TDataField)
+    private
+      function GetTarget: TObject; virtual; abstract;
+    public
+      property TargetFile: TObject read GetTarget;
+  end;
+
+
+  TLinkByID = class(TDatLink)
       function GetChildCount: Integer; override;
       function GetChild(ID: Integer): TTreeElement; override;
@@ -132,4 +147,5 @@
       FPosExts: String;
       function GetValueAsString: String; override;
+      function GetTarget: TObject; override;
     public
       // ExtraArgs: Pointer auf String: Possible Exts
@@ -137,4 +153,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
   end;
 
@@ -149,4 +166,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
   end;
 
@@ -168,4 +186,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
 
       function AddField(fieldtype: TFieldType; Name, Description: String;
@@ -186,4 +205,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
   end;
 
@@ -197,4 +217,5 @@
           Name, Description: String; ExtraArgs: array of const); override;
       procedure Update(Offset, Length: Integer); override;
+      procedure WriteData(stream: TStream); override;
   end;
 
@@ -283,4 +304,16 @@
 end;
 
+procedure TString.WriteData(stream: TStream);
+var
+  temps: String;
+  i: Integer;
+begin
+  temps := FString;
+  SetLength(temps, FDataLength);
+  for i := Length(FString) + 1 to FDataLength do
+    temps[i] := #0;
+  stream.Write(temps[1], FDataLength);
+end;
+
 
 
@@ -307,4 +340,9 @@
   fstream.Seek(FOffset, soFromBeginning);
   fstream.Read(FInt, FDataLength);
+end;
+
+procedure TInt.WriteData(stream: TStream);
+begin
+  stream.Write(FInt, FDataLength);
 end;
 
@@ -418,4 +456,87 @@
 
 procedure TArray.Update(Offset, Length: Integer);
+var
+  i: Integer;
+  field: TDataField;
+begin
+  if System.Length(FDataFields) > 0 then
+  begin
+    if Length > 0 then
+    begin
+      for i := 0 to High(FDataFields) do
+      begin
+        field := FDataFields[i];
+        if ((field.Offset < Offset) and (field.Offset + field.DataLength > Offset + Length)) or
+          ((field.Offset > Offset) and (field.Offset < Offset + Length)) or
+          ((field.Offset + field.DataLength > Offset) and (field.Offset+field.DataLength < Offset + Length)) then
+          field.Update(Offset, Length);
+      end;
+    end else begin
+      for i := 0 to High(FDataFields) do
+        FDataFields[i].Update(Offset, Length);
+    end;
+  end;
+end;
+
+procedure TArray.UpdateSize;
+var
+  i: Integer;
+begin
+  FDataLength := FCounterSize;
+  if Length(FDataFields) > 0 then
+    for i := 0 to High(FDataFields) do
+      FDataLength := FDataLength + FDataFields[i].DataLength;
+  FParentBlock.UpdateSize;
+end;
+
+procedure TArray.WriteData(stream: TStream);
+var
+  i: Integer;
+begin
+  if FCounterSize > 0 then
+    stream.Write(FBlockCount, FCounterSize);
+  if Length(FDataFields) > 0 then
+    for i := 0 to High(FDataFields) do
+      FDataFields[i].WriteData(stream);
+end;
+
+
+
+{ TBlock }
+
+function TBlock.AddField(fieldtype: TFieldType; Name,
+    Description: String; ExtraArgs: array of const): TDataField;
+begin
+  SetLength(FDataFields, Length(FDataFields) + 1);
+  FDataFields[High(FDataFields)] := TFieldType(fieldtype).Create(
+      FParentFile, Self, Name, Description, ExtraArgs);
+  Result := FDataFields[High(FDataFields)];
+  FDataLength := FDataLength + Result.DataLength;
+  if Assigned(FParentBlock) then
+    FParentBlock.UpdateSize;
+end;
+
+constructor TBlock.Create(ParentFile: TObject; ParentBlock: TContainer;
+    Name, Description: String; ExtraArgs: array of const);
+begin
+  inherited Create(ParentFile, ParentBlock, Name, Description, ExtraArgs);
+end;
+
+function TBlock.GetChild(ID: Integer): TTreeElement;
+begin
+  Result := FDataFields[ID];
+end;
+
+function TBlock.GetChildCount: Integer;
+begin
+  Result := Length(FDataFields);
+end;
+
+function TBlock.GetFieldByOffset(Offset: Integer): TDataField;
+begin
+  Exit;
+end;
+
+procedure TBlock.Update(Offset, Length: Integer);
 var
   i: Integer;
@@ -443,78 +564,4 @@
 end;
 
-procedure TArray.UpdateSize;
-var
-  i: Integer;
-begin
-  FDataLength := FCounterSize;
-  if Length(FDataFields) > 0 then
-    for i := 0 to High(FDataFields) do
-      FDataLength := FDataLength + FDataFields[i].DataLength;
-  FParentBlock.UpdateSize;
-end;
-
-
-
-{ TBlock }
-
-function TBlock.AddField(fieldtype: TFieldType; Name,
-    Description: String; ExtraArgs: array of const): TDataField;
-begin
-  SetLength(FDataFields, Length(FDataFields) + 1);
-  FDataFields[High(FDataFields)] := TFieldType(fieldtype).Create(
-      FParentFile, Self, Name, Description, ExtraArgs);
-  Result := FDataFields[High(FDataFields)];
-  FDataLength := FDataLength + Result.DataLength;
-  if Assigned(FParentBlock) then
-    FParentBlock.UpdateSize;
-end;
-
-constructor TBlock.Create(ParentFile: TObject; ParentBlock: TContainer;
-    Name, Description: String; ExtraArgs: array of const);
-begin
-  inherited Create(ParentFile, ParentBlock, Name, Description, ExtraArgs);
-end;
-
-function TBlock.GetChild(ID: Integer): TTreeElement;
-begin
-  Result := FDataFields[ID];
-end;
-
-function TBlock.GetChildCount: Integer;
-begin
-  Result := Length(FDataFields);
-end;
-
-function TBlock.GetFieldByOffset(Offset: Integer): TDataField;
-begin
-  Exit;
-end;
-
-procedure TBlock.Update(Offset, Length: Integer);
-var
-  i: Integer;
-  field: TDataField;
-begin
-  if System.Length(FDataFields) > 0 then
-  begin
-    if Length > 0 then
-    begin
-      for i := 0 to High(FDataFields) do
-      begin
-        field := FDataFields[i];
-        if ((field.Offset < Offset) and (field.Offset + field.DataLength > Offset + Length)) or
-          ((field.Offset > Offset) and (field.Offset < Offset + Length)) or
-          ((field.Offset + field.DataLength > Offset) and (field.Offset+field.DataLength < Offset + Length)) then
-          field.Update(Offset, Length);
-      end;
-    end else begin
-      for i := 0 to High(FDataFields) do
-      begin
-        FDataFields[i].Update(Offset, Length);
-      end;
-    end;
-  end;
-end;
-
 procedure TBlock.UpdateSize;
 var
@@ -529,4 +576,12 @@
 end;
 
+procedure TBlock.WriteData(stream: TStream);
+var
+  i: Integer;
+begin
+  if Length(FDataFields) > 0 then
+    for i := 0 to High(FDataFields) do
+      FDataFields[i].WriteData(stream);
+end;
 
 
@@ -554,4 +609,12 @@
   fstream.Read(FLevelID, 4);
   FLevelID := FLevelID div 256 div 256 div 256 div 2;
+end;
+
+procedure TLevelID.WriteData(stream: TStream);
+var
+  tempi: Integer;
+begin
+  tempi := FLevelID * 256 * 256 * 256 * 2 + 1;
+  stream.Write(tempi, 4);
 end;
 
@@ -586,4 +649,15 @@
 end;
 
+procedure TFileID.WriteData(stream: TStream);
+var
+  tempi: Integer;
+begin
+  if FFileID >= 0 then
+    tempi := FFileID * 256 + 1
+  else
+    tempi := 0;
+  stream.Write(tempi, 4);
+end;
+
 
 
@@ -616,4 +690,12 @@
   else
     Result := 0;
+end;
+
+function TLinkByID.GetTarget: TObject;
+begin
+  if FFileID > 0 then
+    Result := ConManager.Connection[FConnectionID].MetaData.FileById[FFileID]
+  else
+    Result := nil;
 end;
 
@@ -639,4 +721,15 @@
 end;
 
+procedure TLinkByID.WriteData(stream: TStream);
+var
+  tempi: Integer;
+begin
+  if FFileID >= 0 then
+    tempi := FFileID * 256 + 1
+  else
+    tempi := 0;
+  stream.Write(tempi, 4);
+end;
+
 
 
@@ -667,4 +760,9 @@
 end;
 
+procedure TRawLink.WriteData(stream: TStream);
+begin
+  stream.Write(FRawAddress, 4);
+end;
+
 
 
@@ -686,4 +784,14 @@
 begin
   Exit;
+end;
+
+procedure TUnused.WriteData(stream: TStream);
+var
+  i: Integer;
+  tempb: Byte;
+begin
+  tempb := 0;
+  for i := 1 to FDataLength do
+    stream.Write(tempb, 1);
 end;
 
@@ -732,4 +840,9 @@
 end;
 
+procedure TBitSet.WriteData(stream: TStream);
+begin
+  stream.Write(FBits, FDataLength);
+end;
+
 
 
@@ -758,4 +871,9 @@
 end;
 
+procedure TFloat.WriteData(stream: TStream);
+begin
+  stream.Write(FFloat, 4);
+end;
+
 
 end.
Index: oup/current/FileClasses/_FileTypes.pas
===================================================================
--- oup/current/FileClasses/_FileTypes.pas	(revision 238)
+++ oup/current/FileClasses/_FileTypes.pas	(revision 240)
@@ -4,5 +4,5 @@
 
 uses
-  TypeDefs, _DataTypes, _TreeElement, Classes, Forms;
+  TypeDefs, _TreeElement, Classes, Forms, _DataTypes;
 
 
@@ -15,4 +15,5 @@
       FFileInfo: TFileInfo;
       FFileStream: TMemoryStream;
+      FRawCaches: array of TMemoryStream;
 
       FCached: Boolean;
@@ -24,6 +25,8 @@
       FOpened: Boolean;
 
+      function GetEditor: TFrame;
       function GetFieldByOffset(Offset: Integer): TDataField;
-  published
+      procedure SetOpened(Opened: Boolean); virtual;
+    published
     public
       constructor Create(ConnectionID, FileID: Integer); virtual;
@@ -33,13 +36,17 @@
       procedure InitEditor; virtual;
 
+      procedure ReCreateFile(fs: TStream);
+
+      procedure CacheFile;
+      procedure CacheRawFile(Offset: Integer);
+
       property FileStream: TMemoryStream read FFileStream;
       property FileInfo: TFileInfo read FFileInfo;
-      property ConnectionID: Integer read FConnectionID;
 
       property Cached: Boolean read FCached;
       property Changed: Boolean read FChanged write FChanged;
 
-      property Editor: TFrame read FEditor;
-      property Opened: Boolean read FOpened write FOpened;
+      property Editor: TFrame read GetEditor;
+      property Opened: Boolean read FOpened write SetOpened;
 
       property FieldByOffset[Offset: Integer]: TDataField read GetFieldByOffset;
@@ -58,8 +65,49 @@
 { TFileType }
 
+procedure TFile.CacheFile;
+begin
+  if not Assigned(FFileStream) then
+  begin
+    FFileStream := TMemoryStream.Create;
+    ConManager.Connection[FConnectionID].LoadDatFile(FFileInfo.ID, TStream(FFileStream));
+  end;
+end;
+
+
+procedure TFile.CacheRawFile(Offset: Integer);
+var
+  rawlist: TRawDataList;
+  i: Integer;
+begin
+  rawlist := ConManager.Connection[ConnectionID].GetRawList(FFileInfo.ID);
+  if Length(rawlist) > 0 then
+  begin
+    for i := 0 to High(rawlist) do
+    begin
+      if rawlist[i].SrcOffset = Offset then
+      begin
+        if not Assigned(FRawCaches[i]) then
+        begin
+          FRawCaches[i] := TMemoryStream.Create;
+          ConManager.Connection[ConnectionID].LoadRawFile(FFileInfo.ID, Offset, TStream(FRawCaches[i]));
+        end;
+      end;
+    end;
+  end;
+end;
+
+
+procedure TFile.SetOpened(Opened: Boolean);
+begin
+  FOpened := Opened;
+end;
+
+
 constructor TFile.Create(ConnectionID, FileID: Integer);
 begin
   FConnectionID := ConnectionID;
   FFileInfo := ConManager.Connection[ConnectionID].GetFileInfo(FileID);
+
+  SetLength(FRawCaches, Length(ConManager.Connection[ConnectionID].GetRawList(FileID)));
 
   FCached := False;
@@ -107,4 +155,12 @@
 
 
+function TFile.GetEditor: TFrame;
+begin
+  if not Assigned(FEditor) then
+    InitEditor;
+  Result := FEditor;
+end;
+
+
 procedure TFile.InitDataFields;
 begin
@@ -122,3 +178,25 @@
 
 
+//*********************************************************
+//*********************************************************
+//*********************************************************
+procedure TFile.ReCreateFile(fs: TStream);
+const
+  temp0: array[0..31] of Byte =
+    ($AD,$DE,$AD,$DE,$AD,$DE,$AD,$DE,
+     $AD,$DE,$AD,$DE,$AD,$DE,$AD,$DE,
+     $AD,$DE,$AD,$DE,$AD,$DE,$AD,$DE,
+     $AD,$DE,$AD,$DE,$AD,$DE,$AD,$DE);
+var
+  count: Integer;
+begin
+  FDataFields.WriteData(fs);
+  count := fs.Size mod 32;
+  if count > 0 then
+    fs.Write(temp0[count], 32 - count);
+end;
+//*********************************************************
+//*********************************************************
+//*********************************************************
+
 end.
Index: oup/current/FileClasses/_MetaTypes.pas
===================================================================
--- oup/current/FileClasses/_MetaTypes.pas	(revision 238)
+++ oup/current/FileClasses/_MetaTypes.pas	(revision 240)
@@ -5,5 +5,5 @@
 uses
   _FileTypes, _EmptyFile, _Unlinked, _DataTypes, _Extensions, _TreeElement,
-  AKVA, TXAN, TXMP;
+  AKVA, SUBT, TXAN, TXMP;
 //  ABNA, AGDB, AGQC, AGQG, AGQM, AGQR, AISA, AITR, AIWA, AKAA, AKBA, AKBP, AKDA,
 //  AKEV, AKOT, AKVA, BINA, CBPI, CBPM, CONS, CRSA, DOOR, DPge, EDIA, ENVP, FILM,
@@ -24,4 +24,5 @@
   TExtensions = _Extensions.TExtensions;
   TDataField = _DataTypes.TDataField;
+  TDatLink = _DataTypes.TDatLink;
 
   TFileClass = class of TFile;
@@ -32,6 +33,7 @@
 
 const
-  FileDescs: array[0..2] of TFileDesc = (
+  FileDescs: array[0..3] of TFileDesc = (
     (ext: 'AKVA'; ftype: TFile_AKVA),
+    (ext: 'SUBT'; ftype: TFile_SUBT),
     (ext: 'TXAN'; ftype: TFile_TXAN),
     (ext: 'TXMP'; ftype: TFile_TXMP)
