Index: oup/current/Global/DatLinks.pas
===================================================================
--- oup/current/Global/DatLinks.pas	(revision 122)
+++ oup/current/Global/DatLinks.pas	(revision 122)
@@ -0,0 +1,1327 @@
+unit DatLinks;
+interface
+uses TypeDefs, DataAccess;
+
+type
+  THandler = function(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+  TDatLinkHandler = record
+    Ext:     String[4];
+    Handler: THandler;
+  end;
+  TDatLinkHandlers = array of TDatLinkHandler;
+
+  TDatLinks = class
+    private
+      FDatLinkHandlers: TDatLinkHandlers;
+    public
+      property RawListHandlers: TDatLinkHandlers read FDatLinkHandlers;
+      procedure InsertDatLinkHandler(ext: String; handler: THandler);
+      function GetDatLinks(ConnectionID, FileID: Integer): TDatLinkList;
+      function GetDatLink(ConnectionID, FileID, DatOffset: Integer): TDatLink;
+  end;
+
+
+var
+  DatLinksManager: TDatLinks;
+
+
+implementation
+uses
+  ConnectionManager, Classes, SysUtils;
+
+
+
+function AISA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1E, 2, @packages);
+  SetLength(Result, packages * 2);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i*2 + 0].SrcOffset := $20 + i * 352 + $28;
+      Result[i*2 + 0].DestID := -1;
+      Result[i*2 + 0].PosDestExts := 'ONCC';
+
+      Result[i*2 + 1].SrcOffset := $20 + i * 352 + $150;
+      Result[i*2 + 1].DestID := -1;
+      Result[i*2 + 1].PosDestExts := 'ONWC';
+    end;
+  end;
+end;
+
+
+
+function AKEV(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..16] of String[4] =
+      ('PNTA', 'PLEA', 'TXCA', 'AGQG', 'AGQR', 'AGQC', 'AGDB', 'TXMA', 'AKVA',
+      'AKBA', 'IDXA', 'IDXA', 'AKBP', 'ABNA', 'AKOT', 'AKAA', 'AKDA');
+var
+  i: Integer;
+begin
+  SetLength(Result, 17);
+  for i := 0 to 16 do
+  begin
+    Result[i].SrcOffset := $8 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function AKOT(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..4] of String[4] =
+      ('OTIT', 'OTLF', 'QTNA', 'IDXA', 'IDXA');
+var
+  i: Integer;
+begin
+  SetLength(Result, 5);
+  for i := 0 to 4 do
+  begin
+    Result[i].SrcOffset := $8 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function CBPI(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 57);
+  for i := 0 to 56 do
+  begin
+    Result[i].SrcOffset := $8 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := 'Impt';
+  end;
+end;
+
+
+
+function CBPM(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 19);
+  for i := 0 to 18 do
+  begin
+    Result[i].SrcOffset := $8 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := 'Mtrl';
+  end;
+end;
+
+
+
+function CONS(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..1] of String[4] =
+      ('OFGA', 'M3GM');
+var
+  i: Integer;
+begin
+  SetLength(Result, 2);
+  for i := 0 to 1 do
+  begin
+    Result[i].SrcOffset := $24 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function CRSA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*1100 + $A0;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'ONCC';
+    end;
+  end;
+end;
+
+
+
+function DOOR(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..2] of String[4] =
+      ('OFGA', 'OFGA', 'OBAN');
+var
+  i: Integer;
+begin
+  SetLength(Result, 3);
+  for i := 0 to 2 do
+  begin
+    Result[i].SrcOffset := $8 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function DPge(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..0] of String[4] =
+      ('IGPG');
+var
+  i: Integer;
+begin
+  SetLength(Result, 1);
+  for i := 0 to 0 do
+  begin
+    Result[i].SrcOffset := $40 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function FILM(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..1] of String[4] =
+      ('TRAM', 'TRAM');
+var
+  i: Integer;
+begin
+  SetLength(Result, 2);
+  for i := 0 to 1 do
+  begin
+    Result[i].SrcOffset := $28 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function FXLR(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..1] of String[4] =
+      ('TXMP', 'M3GM');
+var
+  i: Integer;
+begin
+  SetLength(Result, 2);
+  for i := 0 to 1 do
+  begin
+    Result[i].SrcOffset := $0C + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function GMAN(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'M3GM';
+    end;
+  end;
+end;
+
+
+
+function HPge(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..0] of String[4] =
+      ('IGPG');
+var
+  i: Integer;
+begin
+  SetLength(Result, 1);
+  for i := 0 to 0 do
+  begin
+    Result[i].SrcOffset := $0C + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function IGHH(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..1] of String[4] =
+      ('TXMP', 'TXMP');
+var
+  i: Integer;
+begin
+  SetLength(Result, 2);
+  for i := 0 to 1 do
+  begin
+    Result[i].SrcOffset := $24 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function IGPA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'IGPG';
+    end;
+  end;
+end;
+
+
+
+function IGPG(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..3] of String[4] =
+      ('TSFF', '*', 'IGSA', 'IGSA');
+var
+  i: Integer;
+begin
+  SetLength(Result, 4);
+  Result[0].SrcOffset := $8;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := types[0];
+
+  for i := 1 to 3 do
+  begin
+    Result[i].SrcOffset := $14 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function IGSA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'IGSt';
+    end;
+  end;
+end;
+
+
+
+function IGSt(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..0] of String[4] =
+      ('TSFF');
+var
+  i: Integer;
+begin
+  SetLength(Result, 1);
+  for i := 0 to 0 do
+  begin
+    Result[i].SrcOffset := $8 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function Impt(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..0] of String[4] =
+      ('*');
+var
+  i: Integer;
+begin
+  SetLength(Result, 1);
+  for i := 0 to 0 do
+  begin
+    Result[i].SrcOffset := $10 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function IPge(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..0] of String[4] =
+      ('IGPG');
+var
+  i: Integer;
+begin
+  SetLength(Result, 1);
+  for i := 0 to 0 do
+  begin
+    Result[i].SrcOffset := $0C + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function KeyI(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 10);
+  for i := 0 to 9 do
+  begin
+    Result[i].SrcOffset := $08 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := 'TXMP';
+  end;
+end;
+
+
+
+function M3GA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'M3GM';
+    end;
+  end;
+end;
+
+
+
+function M3GM(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..7] of String[4] =
+      ('PNTA', 'VCRA', 'VCRA', 'TXCA', 'IDXA', 'IDXA', 'TXMP', '*');
+var
+  i: Integer;
+begin
+  SetLength(Result, 8);
+  for i := 0 to 7 do
+  begin
+    Result[i].SrcOffset := $0C + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function Mtrl(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..0] of String[4] =
+      ('*');
+var
+  i: Integer;
+begin
+  SetLength(Result, 1);
+  for i := 0 to 0 do
+  begin
+    Result[i].SrcOffset := $10 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function OBDC(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1E, 2, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*$18 + 4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'OBAN';
+    end;
+  end;
+end;
+
+
+
+function OBOA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1E, 2, @packages);
+  SetLength(Result, packages * 3);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i*3 + 0].SrcOffset := $20 + i*240 + 0;
+      Result[i*3 + 0].DestID := -1;
+      Result[i*3 + 0].PosDestExts := 'M3GA';
+
+      Result[i*3 + 0].SrcOffset := $20 + i*240 + 4;
+      Result[i*3 + 0].DestID := -1;
+      Result[i*3 + 1].PosDestExts := 'OBAN';
+
+      Result[i*3 + 0].SrcOffset := $20 + i*240 + 8;
+      Result[i*3 + 0].DestID := -1;
+      Result[i*3 + 2].PosDestExts := 'ENVP';
+    end;
+  end;
+end;
+
+
+
+function OFGA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages * 2 + 1);
+
+  Result[0].SrcOffset := $18;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := 'ENVP';
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[1 + i*2 + 0].SrcOffset := $20 + i*12 + 4;
+      Result[1 + i*2 + 0].DestID := -1;
+      Result[1 + i*2 + 0].PosDestExts := 'M3GM';
+
+      Result[1 + i*2 + 1].SrcOffset := $20 + i*12 + 8;
+      Result[1 + i*2 + 1].DestID := -1;
+      Result[1 + i*2 + 1].PosDestExts := 'OBLS';
+    end;
+  end;
+end;
+
+
+
+function ONCC(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 10);
+  i := 0;
+  Result[i].SrcOffset := $28;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+  Inc(i);
+  Result[i].SrcOffset := $434;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'ONCV';
+  Inc(i);
+  Result[i].SrcOffset := $438;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'ONCP';
+  Inc(i);
+  Result[i].SrcOffset := $43C;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'ONIA';
+  Inc(i);
+  Result[i].SrcOffset := $C3C;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TRBS';
+  Inc(i);
+  Result[i].SrcOffset := $C40;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TRMA';
+  Inc(i);
+  Result[i].SrcOffset := $C44;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'CBPM';
+  Inc(i);
+  Result[i].SrcOffset := $C48;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'CBPI';
+  Inc(i);
+  Result[i].SrcOffset := $C88;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TRAC';
+  Inc(i);
+  Result[i].SrcOffset := $C8C;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TRSC';
+end;
+
+
+
+function ONCV(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+begin
+  SetLength(Result, 1);
+  Result[0].SrcOffset := $8;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := '*';
+end;
+
+
+
+function ONLV(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..12] of String[4] =
+      ('AKEV', 'OBOA', 'ONMA', 'ONFA', 'ONTA', 'ONSK', 'AISA', 'AITR',
+       'ONSA', 'OBDC', 'ONOA', 'ENVP', 'CRSA');
+var
+  i: Integer;
+begin
+  SetLength(Result, 13);
+  for i := 0 to 5 do
+  begin
+    Result[i].SrcOffset := $48 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+  for i := 0 to 5 do
+  begin
+    Result[i+6].SrcOffset := $64 + i*4;
+    Result[i+6].DestID := -1;
+    Result[i+6].PosDestExts := types[i+6];
+  end;
+  Result[12].SrcOffset := $300;
+  Result[12].DestID := -1;
+  Result[12].PosDestExts := types[12];
+end;
+
+
+
+function ONOA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*8 + 4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'IDXA';
+    end;
+  end;
+end;
+
+
+
+function ONSK(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 20);
+  for i := 0 to 19 do
+  begin
+    Result[i].SrcOffset := $08 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := 'TXMP';
+  end;
+end;
+
+
+
+function ONVL(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'ONCV';
+    end;
+  end;
+end;
+
+
+
+function ONWC(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 9);
+  i := 0;
+  Result[i].SrcOffset := $28;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+  Inc(i);
+  Result[i].SrcOffset := $34;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+  Inc(i);
+  Result[i].SrcOffset := $40;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+  Inc(i);
+  Result[i].SrcOffset := $54;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+  Inc(i);
+  Result[i].SrcOffset := $58;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+  Inc(i);
+  Result[i].SrcOffset := $5C;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+  Inc(i);
+  Result[i].SrcOffset := $60;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'M3GM';
+  Inc(i);
+  Result[i].SrcOffset := $6FC;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+  Inc(i);
+  Result[i].SrcOffset := $700;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'TXMP';
+end;
+
+
+
+function OPge(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+begin
+  SetLength(Result, 1);
+  Result[0].SrcOffset := $0C;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := 'IGPA';
+end;
+
+
+
+function PSpc(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+begin
+  SetLength(Result, 1);
+  Result[0].SrcOffset := $50;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := '*';
+end;
+
+
+
+function PSpL(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*8 + 4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := '*';
+    end;
+  end;
+end;
+
+
+
+function PSUI(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 44);
+  for i := 0 to 43 do
+  begin
+    Result[i].SrcOffset := $08 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := 'PSpc';
+  end;
+end;
+
+
+
+function StNA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1E, 2, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'TStr';
+    end;
+  end;
+end;
+
+
+
+function TMRA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := '*';
+    end;
+  end;
+end;
+
+
+
+function TRAC(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1E, 2, @packages);
+  SetLength(Result, packages + 1);
+  Result[0].SrcOffset := $18;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := 'TRAC';
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i+1].SrcOffset := $20 + i*12 + 8;
+      Result[i+1].DestID := -1;
+      Result[i+1].PosDestExts := 'TRAM';
+    end;
+  end;
+end;
+
+
+
+function TRAM(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 2);
+  for i := 0 to 1 do
+  begin
+    Result[i].SrcOffset := $40 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := 'TRAM';
+  end;
+end;
+
+
+
+function TRAS(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+begin
+  SetLength(Result, 1);
+  Result[0].SrcOffset := $08;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := 'TRAM';
+end;
+
+
+
+function TRBS(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 5);
+  for i := 0 to 4 do
+  begin
+    Result[i].SrcOffset := $08 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := 'TRCM';
+  end;
+end;
+
+
+
+function TRCM(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..2] of String[4] =
+      ('TRGA', 'TRTA', 'TRIA');
+var
+  i: Integer;
+begin
+  SetLength(Result, 3);
+  for i := 0 to 2 do
+  begin
+    Result[i].SrcOffset := $5C + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+end;
+
+
+
+function TRGA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1E, 2, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'M3GM';
+    end;
+  end;
+end;
+
+
+
+function TRGE(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+begin
+  SetLength(Result, 1);
+  Result[0].SrcOffset := $20;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := 'M3GM';
+end;
+
+
+
+function TRIG(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+const
+  types: array[0..3] of String[4] =
+      ('M3GM', 'OBLS', 'TRGE', 'OBAN');
+var
+  i: Integer;
+begin
+  SetLength(Result, 4);
+  for i := 0 to 1 do
+  begin
+    Result[i].SrcOffset := $18 + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := types[i];
+  end;
+  for i := 0 to 1 do
+  begin
+    Result[i+2].SrcOffset := $24 + i*4;
+    Result[i+2].DestID := -1;
+    Result[i+2].PosDestExts := types[i+2];
+  end;
+end;
+
+
+
+function TRMA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1E, 2, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'TXMP';
+    end;
+  end;
+end;
+
+
+
+function TRSC(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1E, 2, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'TRAS';
+    end;
+  end;
+end;
+
+
+
+function TSFF(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages + 1);
+
+  Result[0].SrcOffset := $18;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := 'TSFL';
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i+1].SrcOffset := $20 + i*4;
+      Result[i+1].DestID := -1;
+      Result[i+1].PosDestExts := 'TSFT';
+    end;
+  end;
+end;
+
+
+
+function TSFT(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 256);
+  for i := 0 to 255 do
+  begin
+    Result[i].SrcOffset := $1C + i*4;
+    Result[i].DestID := -1;
+    Result[i].PosDestExts := 'TSGA';
+  end;
+end;
+
+
+
+function TURR(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+begin
+  SetLength(Result, 4);
+  i := 0;
+  Result[i].SrcOffset := $60;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'M3GM';
+  Inc(i);
+  Result[i].SrcOffset := $64;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'OBLS';
+  Inc(i);
+  Result[i].SrcOffset := $6C;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'M3GM';
+  Inc(i);
+  Result[i].SrcOffset := $74;
+  Result[i].DestID := -1;
+  Result[i].PosDestExts := 'M3GM';
+end;
+
+
+
+function TXAN(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'TXMP';
+    end;
+  end;
+end;
+
+
+
+function TXMA(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'TXMP';
+    end;
+  end;
+end;
+
+
+
+function TXMB(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'TXMP';
+    end;
+  end;
+end;
+
+
+
+function TXMP(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+begin
+  SetLength(Result, 2);
+  Result[0].SrcOffset := $94;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := '*';
+  Result[1].SrcOffset := $98;
+  Result[1].DestID := -1;
+  Result[1].PosDestExts := 'TXMP';
+end;
+
+
+
+function TxtC(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+begin
+  SetLength(Result, 1);
+  Result[0].SrcOffset := $08;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := 'IGPA';
+end;
+
+
+
+function WMCL(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*8 + 4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := '*';
+    end;
+  end;
+end;
+
+
+
+function WMDD(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $11C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $120 + i*292 + $134;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'TSFF';
+    end;
+  end;
+end;
+
+
+
+function WMMB(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+var
+  packages: Integer;
+  i: Integer;
+begin
+  packages := 0;
+  Connection.LoadDatFilePart(fileid, $1C, 4, @packages);
+  SetLength(Result, packages);
+  if packages > 0 then
+  begin
+    for i := 0 to packages - 1 do
+    begin
+      Result[i].SrcOffset := $20 + i*4;
+      Result[i].DestID := -1;
+      Result[i].PosDestExts := 'WMM_';
+    end;
+  end;
+end;
+
+
+
+function WPge(Connection: TDataAccess; FileID: Integer): TDatLinkList;
+begin
+  SetLength(Result, 2);
+  Result[0].SrcOffset := $08;
+  Result[0].DestID := -1;
+  Result[0].PosDestExts := 'ONWC';
+  Result[1].SrcOffset := $0C;
+  Result[1].DestID := -1;
+  Result[1].PosDestExts := 'IGPG';
+end;
+
+
+
+
+
+
+
+function TDatLinks.GetDatLink(ConnectionID, FileID, DatOffset: Integer): TDatLink;
+var
+  i: Integer;
+  DatLinks: TDatLinkList;
+begin
+  DatLinks           := GetDatLinks(ConnectionID, FileID);
+  Result.SrcOffset   := -1;
+  Result.DestID      := -1;
+  Result.PosDestExts := '';
+  if Length(DatLinks) > 0 then
+  begin
+    for i := 0 to High(DatLinks) do
+    begin
+      if DatLinks[i].SrcOffset = DatOffset then
+      begin
+        Result.SrcOffset := DatOffset;
+        Result.DestID := DatLinks[i].DestID;
+        Result.PosDestExts := DatLinks[i].PosDestExts;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+
+function TDatLinks.GetDatLinks(ConnectionID, FileID: Integer): TDatLinkList;
+var
+  i: Integer;
+  fileinfo: TFileInfo;
+begin
+  SetLength(Result, 0);
+  fileinfo := ConManager.Connection[ConnectionID].GetFileInfo(FileID);
+  for i := 0 to High(FDatLinkHandlers) do
+    if UpperCase(FDatLinkHandlers[i].Ext) = UpperCase(fileinfo.extension) then
+    begin
+      Result := FDatLinkHandlers[i].Handler(ConManager.Connection[ConnectionID], FileID);
+      Break;
+    end;
+end;
+
+procedure TDatLinks.InsertDatLinkHandler(ext: String; handler: THandler);
+begin
+  SetLength(FDatLinkHandlers, Length(FDatLinkHandlers) + 1);
+  FDatLinkHandlers[High(FDatLinkHandlers)].Ext := ext;
+  FDatLinkHandlers[High(FDatLinkHandlers)].handler := handler;
+end;
+
+
+
+
+initialization
+  DatLinksManager := TDatLinks.Create;
+  DatLinksManager.InsertDatLinkHandler('AISA', AISA);
+  DatLinksManager.InsertDatLinkHandler('AKEV', AKEV);
+  DatLinksManager.InsertDatLinkHandler('AKOT', AKOT);
+  DatLinksManager.InsertDatLinkHandler('CBPI', AISA);
+  DatLinksManager.InsertDatLinkHandler('CBPM', AKEV);
+  DatLinksManager.InsertDatLinkHandler('CONS', AKOT);
+  DatLinksManager.InsertDatLinkHandler('CRSA', AISA);
+  DatLinksManager.InsertDatLinkHandler('DOOR', AKEV);
+  DatLinksManager.InsertDatLinkHandler('DPge', AKOT);
+  DatLinksManager.InsertDatLinkHandler('FILM', AISA);
+  DatLinksManager.InsertDatLinkHandler('FXLR', AKEV);
+  DatLinksManager.InsertDatLinkHandler('GMAN', AKOT);
+  DatLinksManager.InsertDatLinkHandler('HPge', AISA);
+  DatLinksManager.InsertDatLinkHandler('IGHH', AKEV);
+  DatLinksManager.InsertDatLinkHandler('IGPA', AKOT);
+end.
Index: oup/current/Global/OniImgClass.pas
===================================================================
--- oup/current/Global/OniImgClass.pas	(revision 121)
+++ oup/current/Global/OniImgClass.pas	(revision 122)
@@ -611,5 +611,5 @@
       x    := x div 2;
       y    := y div 2;
-      size := (size + x * y * bpp) div 8;
+      size := size + (x * y * bpp) div 8;
     until (x = 1) or (y = 1);
   end;
Index: oup/current/Global/RawList.pas
===================================================================
--- oup/current/Global/RawList.pas	(revision 121)
+++ oup/current/Global/RawList.pas	(revision 122)
@@ -341,5 +341,5 @@
       x    := x div 2;
       y    := y div 2;
-      datasize := (datasize + x * y * bpp) div 8;
+      datasize := datasize + (x * y * bpp) div 8;
     until (x = 1) or (y = 1);
   end;
