Index: oup/rewrite/Global/DatStructureLoader.pas
===================================================================
--- oup/rewrite/Global/DatStructureLoader.pas	(revision 97)
+++ oup/rewrite/Global/DatStructureLoader.pas	(revision 97)
@@ -0,0 +1,277 @@
+unit DatStructureLoader;
+
+interface
+
+type
+  TStructureEntry = record
+    Name:     String;
+    offset:   Integer;
+    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 TStructureEntry;
+  end;
+
+  TStructDef = record
+    Data:   Boolean;
+    Global: array of TStructureEntry;
+    Subs:   array of TStructDefSub;
+  end;
+
+
+function LoadStructureDefinition(ConnectionID, FileID: Integer): TStructDef;
+function GetDataType(TypeID: Word): String;
+function GetDataTypeLength(DataType: Word): Word;
+
+implementation
+
+uses
+  SysUtils, Classes, Functions, ConnectionManager, TypeDefs, Forms, StrUtils, Data;
+
+type
+  TStringArray = array of String;
+
+function GetDataTypeLength(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 Explode(_string: String; delimiter: Char): TStringArray;
+var
+  start, len: Word;
+begin
+  SetLength(Result, 0);
+  start := 1;
+  while PosEx(delimiter, _string, start) > 0 do
+  begin
+    SetLength(Result, Length(Result) + 1);
+    len := PosEx(delimiter, _string, start) - start;
+    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 LoadStructureDefinition(ConnectionID, FileID: Integer): TStructDef;
+var
+  i:      Integer;
+  current_type: Byte; //0: Global, 1: Undynamic, 2: Dynamic
+  current_base, current_package, current_package_size: Integer;
+  packages: Integer;
+  deffile: Text;
+  structentry: TStructureEntry;
+  fields: TStringArray;
+  filename: String;
+  ext:    String[4];
+  temps:  String;
+  Data:   TByteData;
+begin
+  SetLength(Result.Global, 0);
+  SetLength(Result.Subs, 0);
+  Result.Data := False;
+  ext      := ConManager.Connection[ConnectionID].GetFileInfo(fileid).Extension;
+  filename := ExtractFilePath(Application.ExeName) + '\StructDefs\' + ext + '.txt';
+  if FileExists(filename) then
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFile(FileID, Data);
+    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;
+
+
+end.
Index: oup/rewrite/Global/Exporters.pas
===================================================================
--- oup/rewrite/Global/Exporters.pas	(revision 97)
+++ oup/rewrite/Global/Exporters.pas	(revision 97)
@@ -0,0 +1,259 @@
+unit Exporters;
+
+interface
+
+procedure ExportDatFile(ConnectionID, FileID: Integer; filename: String);
+procedure ExportRawFiles(ConnectionID, FileID: Integer; filename: String);
+procedure ExportRawFile(ConnectionID, FileID, DatOffset: Integer; filename: String);
+function ExportConverted(ConnectionID, FileID: Integer; filename: String): Integer;
+
+
+implementation
+
+uses
+  Classes, SysUtils, TypeDefs, ConnectionManager, OniImgClass;
+
+type
+  TExportHandler = function(ConnectionID, FileID: Integer; filename: String): Integer;
+  TExportHandlers = record
+    Ext:     String[4];
+    needed:  Boolean;
+    Handler: TExportHandler;
+  end;
+
+var
+  ExportHandlers: array of TExportHandlers;
+
+
+procedure ExportDatFile(ConnectionID, FileID: Integer; filename: String);
+var
+  filestream: TFileStream;
+begin
+  if FileExists(filename) then
+  begin
+    // Overwrite???
+  end;
+  filestream := TFileStream.Create(filename, fmCreate);
+  ConManager.Connection[ConnectionID].LoadDatFile(FileID, TStream(filestream));
+  filestream.Free;
+end;
+
+
+procedure ExportRawFiles(ConnectionID, FileID: Integer; filename: String);
+var
+  i: Integer;
+  rawlist: TRawDataList;
+begin
+  rawlist := ConManager.Connection[ConnectionID].GetRawList(fileid);
+  if Length(rawlist) > 0 then
+    for i := 0 to High(rawlist) do
+      ExportRawFile(ConnectionID, FileID, rawlist[i].SrcOffset, filename);
+end;
+
+
+procedure ExportRawFile(ConnectionID, FileID, DatOffset: Integer; filename: String);
+var
+  filestream: TFileStream;
+begin
+  if FileExists(filename + '.raw0x' + IntToHex(DatOffset, 8)) then
+  begin
+    // Overwrite???
+  end;
+  filestream := TFileStream.Create(filename + '.raw0x' + IntToHex(DatOffset, 8), fmCreate);
+  ConManager.Connection[ConnectionID].LoadRawFile(FileID, DatOffset, TStream(filestream));
+  filestream.Free;
+end;
+
+function ExportConverted(ConnectionID, FileID: Integer; filename: String): Integer;
+var
+  i: Integer;
+  fileinfo: TFileInfo;
+begin
+  fileinfo := ConManager.Connection[ConnectionID].GetFileInfo(FileID);
+  if Length(ExportHandlers) > 0 then
+    for i := 0 to High(ExportHandlers) do
+      if ExportHandlers[i].Ext = fileinfo.Extension then
+        ExportHandlers[i].Handler(ConnectionID, FileID, filename);
+end;
+
+
+
+
+function ExportSNDD(ConnectionID, FileID: Integer; filename: String): Integer;
+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;
+
+  //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 := 0;
+  ConManager.Connection[ConnectionID].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;
+
+    if FileExists(filename+'.wav') then
+    begin
+      // Overwrite???
+    end;
+
+    //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));
+    ConManager.Connection[ConnectionID].LoadRawFile(FileID, $44, TStream(filestream));
+    filestream.Free;
+  end;
+end;
+
+
+
+
+function ExportTRAC(ConnectionID, FileID: Integer; filename: String): Integer;
+var
+  link: Integer;
+  linkcount: Word;
+  i: Integer;
+begin
+  Result := 0;
+
+  ConManager.Connection[ConnectionID].LoadDatFilePart(FileID, $18, SizeOf(link), @link);
+  link := link div 256;
+
+  ConManager.Connection[ConnectionID].LoadDatFilePart(FileID, $1E, SizeOf(linkcount), @linkcount);
+  for i := 1 to linkcount do
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFilePart(FileID, $20 + (i - 1) * 12 + 8, SizeOf(link), @link);
+    link := link div 256;
+  end;
+end;
+
+
+
+
+function ExportTXAN(ConnectionID, FileID: Integer; filename: String): Integer;
+var
+  loop_speed, unknown: Word;
+  linkcount: LongWord;
+  link: LongWord;
+  i: Byte;
+begin
+  Result := 0;
+
+  ConManager.Connection[ConnectionID].LoadDatFilePart(FileID, $14, SizeOf(loop_speed), @loop_speed);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(FileID, $16, SizeOf(unknown), @unknown);
+
+  ConManager.Connection[ConnectionID].LoadDatFilePart(FileID, $1C, SizeOf(linkcount), @linkcount);
+  for i := 0 to linkcount - 1 do
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFilePart(FileID, $20 + i * 4, SizeOf(link), @link);
+    link := link div 256;
+    if link = 0 then
+      link := fileid - 1;
+  end;
+end;
+
+
+
+
+function ExportImage(ConnectionID, FileID: Integer; filename: String): Integer;
+var
+  img: TOniImage;
+begin
+  Result := 0;
+
+  if FileExists(filename+'.bmp') then
+  begin
+    // Overwrite???
+  end;
+
+  img := TOniImage.Create;
+  img.Load(ConnectionID, FileID);
+  img.WriteToBMP(filename+'.bmp');
+  img.Free;
+end;
+
+
+
+procedure InsertExportHandler(ext: String; needed: Boolean; handler: TExportHandler);
+begin
+  SetLength(ExportHandlers, Length(ExportHandlers) + 1);
+  ExportHandlers[High(ExportHandlers)].Ext := ext;
+  ExportHandlers[High(ExportHandlers)].needed := needed;
+  ExportHandlers[High(ExportHandlers)].handler := handler;
+end;
+
+{
+  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)
+);
+}
+
+initialization
+//  InsertExportHandler('ABNA', False, ABNA);
+//  InsertExportHandler('AGDB', False, AGDB);
+  InsertExportHandler('SNDD', True, ExportSNDD);
+  InsertExportHandler('TXMB', True, ExportImage);
+  InsertExportHandler('TXMP', True, ExportImage);
+end.
Index: oup/rewrite/Global/Functions.pas
===================================================================
--- oup/rewrite/Global/Functions.pas	(revision 97)
+++ oup/rewrite/Global/Functions.pas	(revision 97)
@@ -0,0 +1,330 @@
+unit Functions;
+
+interface
+
+uses TypeDefs, Classes;
+
+function BoolToStr(bool: Boolean): String;
+function HexToLong(hex: String): LongWord;
+function Decode_Int(buffer: TByteData): LongWord;
+function Encode_Int(input: LongWord): TByteData;
+function Decode_Float(buffer: TByteData): Single;
+function Encode_Float(input: Single): TByteData;
+function DataToBin(Data: TByteData): 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: TByteData; HexOnly: Boolean): String;
+function DecodeHexString(hex: String): TByteData;
+function GetWinFileName(Name: String): String;
+//function GetExtractPath: String;
+
+function Explode(_string: String; delimiter: Char): TStrings;
+
+
+implementation
+
+uses SysUtils, Math, StrUtils;
+
+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
+    Result := True;
+    if hex[1] = '$' then
+    begin
+      for i := 1 to Length(hex) - 1 do
+        hex[i] := hex[i + 1];
+      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
+        hex[i] := hex[i + 2];
+      SetLength(hex, Length(hex) - 2);
+    end;
+    if Length(hex) = 0 then
+      Result := False;
+  end;
+
+begin
+  if NormalizeHexString(hex) then
+  begin
+    Result := StrToInt(hex);
+{
+    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: TByteData): LongWord;
+begin
+  Result := buffer[0] + buffer[1] * 256 + buffer[2] * 256 * 256 + buffer[3] * 256 * 256 * 256;
+end;
+
+
+
+
+function Encode_Int(input: LongWord): TByteData;
+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: TByteData): 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): TByteData;
+var
+  _valueswitcher: TValueSwitcher;
+begin
+  _valueswitcher.ValueFloat := input;
+  Result := Encode_Int(_valueswitcher.ValueInt);
+end;
+
+
+
+
+function DataToBin(Data: TByteData): 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
+    Result := FloatToStrF(size / 1024 / 1024 / 1024, ffFixed, 5, 1, floatformat) + ' GB'
+  else
+    if size >= 1000 * 1024 then
+      Result := FloatToStrF(size / 1024 / 1024, ffFixed, 5, 1, floatformat) + ' MB'
+    else
+      if size >= 1000 then
+        Result := FloatToStrF(size / 1024, ffFixed, 5, 1, floatformat) + ' KB'
+      else
+        Result := IntToStr(size) + ' B';
+end;
+
+
+
+
+function CreateHexString(Data: TByteData; 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): TByteData;
+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): TStrings;
+var
+  start, len: Word;
+begin
+  Result := TStringList.Create;
+  start := 1;
+  while PosEx(delimiter, _string, start) > 0 do
+  begin
+    len := PosEx(delimiter, _string, start) - start;
+    Result.Add(MidStr(_string, start, len));
+    start := start + len + 1;
+  end;
+  Result.Add(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;
+
+
+end.
Index: oup/rewrite/Global/OniImgClass.pas
===================================================================
--- oup/rewrite/Global/OniImgClass.pas	(revision 97)
+++ oup/rewrite/Global/OniImgClass.pas	(revision 97)
@@ -0,0 +1,833 @@
+unit OniImgClass;
+
+interface
+
+uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs;
+
+type
+  TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32);
+
+type
+  TOniImage = class
+  private
+    FLoaded:    Boolean;
+    FDataType:  TImgDataType;
+    FData:      TByteData;
+    FWidth, FHeight: Word;
+    FDepth:     Byte;
+    FStoreType: Byte;
+
+    function ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
+    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:      TByteData    Read FData      Write FData;
+
+    constructor Create;
+    function Load(ConnectionID, FileID: Integer): Boolean;
+    function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
+    function LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
+    function LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
+    function GetImageDataSize(fading: Boolean): Integer;
+
+    function GetAsData: TByteData;
+    function GetAs32bit: TByteData;
+    procedure GetAsBMP(var Target: TByteData); overload;
+    procedure GetAsBMP(var Target: TStream); overload;
+    function LoadFromBMP(filename: String): Boolean;
+    function WriteToBMP(filename: String): Boolean;
+    function GetMipMappedImage(var faded: TByteData): 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: Integer; img: TByteData): TByteData;
+var
+  i, j: Integer;
+  col, row, row_orig: Integer;
+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: Integer;
+  tempd:   TByteData;
+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:  Integer;
+  tempd: TByteData;
+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: Integer;
+  color:      array[1..4] of Tcolor;
+  pixel:      array[1..16] of Byte;
+  tempd:      TByteData;
+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(ConnectionID, FileID: Integer): Boolean;
+var
+  FileInfo: TFileInfo;
+  ext:      String;
+begin
+  FileInfo := ConManager.Connection[ConnectionID].GetFileInfo(fileid);
+  if FileInfo.Extension = 'PSpc' then
+    Result := LoadFromPSpc(ConnectionID, fileid)
+  else if FileInfo.Extension = 'TXMB' then
+    Result := LoadFromTXMB(ConnectionID, fileid)
+  else if FileInfo.Extension = 'TXMP' then
+    Result := LoadFromTXMP(ConnectionID, fileid)
+  else
+    Result := False;
+end;
+
+
+
+
+function TOniImage.LoadFromPSpc(ConnectionID, FileID: Integer): 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: Integer;
+  end;
+
+  TPart = packed record
+    x_txmp, y_txmp: Word;
+    x_pspc, y_pspc: Word;
+    w, h:    Word;
+    imgdata: TByteData;
+    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: TByteData;
+
+  parts:    array[0..8] of TPart;
+  part:     Byte;
+  cols:     array[0..2] of Word;
+  rows:     array[0..2] of Word;
+  col, row: Byte;
+begin
+  ConManager.Connection[ConnectionID].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(ConnectionID, 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('M:\' + 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(ConnectionID, FileID: Integer): Boolean;
+var
+  img_addr: Integer;
+begin
+  Result := True;
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType),
+    @Self.FStoreType);
+  if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
+    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
+  else
+    ConManager.Connection[ConnectionID].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 ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
+    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
+  else
+    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
+
+  Self.FDataType := [DT_OniReverted, DT_Oni];
+end;
+
+
+
+
+function TOniImage.LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
+var
+  i, x, y, x2, y2, pixelid, imgid: Integer;
+  rows, cols: Word;
+  linkcount: Integer;
+  link: Integer;
+  images_decoded: array of TOniImage;
+  x_start, y_start: Integer;
+begin
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
+  SetLength(images_decoded, linkcount);
+  for i := 0 to linkcount - 1 do
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
+    link := link div 256;
+    images_decoded[i] := TOniImage.Create;
+    images_decoded[i].LoadFromTXMP(ConnectionID, 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): Integer;
+var
+  size: Integer;
+  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: TByteData;
+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: TByteData;
+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;
+
+
+
+
+procedure TOniImage.GetAsBMP(var Target: TByteData);
+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: Integer;
+begin
+  if not (DT_Decoded32 in Self.FDataType) then
+    Self.DecodeImage;
+
+  SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54);
+  for y := 0 to Self.FHeight - 1 do
+  begin
+    for x := 0 to Self.FWidth - 1 do
+    begin
+      Target[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
+      Target[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
+      Target[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
+    end;
+  end;
+
+  for i := 0 to High(BMPheader) do
+    Target[i] := BMPheader[i];
+  Target[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
+  Target[3]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
+  Target[4]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
+  Target[5]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
+  Target[18] := (Self.FWidth and $000000FF) div $1;
+  Target[19] := (Self.FWidth and $0000FF00) div $100;
+  Target[20] := (Self.FWidth and $00FF0000) div $10000;
+  Target[21] := (Self.FWidth and $FF000000) div $1000000;
+  Target[22] := (Self.FHeight and $000000FF) div $1;
+  Target[23] := (Self.FHeight and $0000FF00) div $100;
+  Target[24] := (Self.FHeight and $00FF0000) div $10000;
+  Target[25] := (Self.FHeight and $FF000000) div $1000000;
+  Target[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
+  Target[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
+  Target[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
+  Target[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
+end;
+
+
+procedure TOniImage.GetAsBMP(var Target: TStream);
+var
+  data: TByteData;
+begin
+  GetAsBMP(data);
+  Target.Write(data[0], Length(data));
+end;
+
+
+function TOniImage.LoadFromBMP(filename: String): Boolean;
+var
+  filestream: TFileStream;
+  tempd:      TByteData;
+
+  x, y: Integer;
+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;
+begin
+  filestream := TFileStream.Create(filename, fmCreate);
+  GetAsBMP(TStream(filestream));
+  filestream.Free;
+end;
+
+
+
+
+function TOniImage.GetMipMappedImage(var faded: TByteData): Boolean;
+var
+  i:      Integer;
+  x, y:   Word;
+  fadelvldata: TByteData;
+  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/rewrite/Global/RawList.pas
===================================================================
--- oup/rewrite/Global/RawList.pas	(revision 97)
+++ oup/rewrite/Global/RawList.pas	(revision 97)
@@ -0,0 +1,414 @@
+unit RawList;
+
+interface
+
+uses TypeDefs, ConnectionManager;
+
+type
+  THandler = function(ConnectionID, FileID: Integer): TRawDataList;
+  TRawListHandlers = record
+    Ext:     String[4];
+    needed:  Boolean;
+    Handler: THandler;
+  end;
+
+  TRawLists = class
+    private
+      FRawListHandlers: TRawListHandlers;
+    public
+      procedure InsertRawListHandler(ext: String; needed: Boolean; handler: THandler);
+      function GetRawList(ConnectionID, FileID: Integer): TRawDataList;
+      function GetRawInfo(ConnectionID, FileID, DatOffset: Integer): TRawDataInfo;
+  end;
+
+
+var
+  RawLists: TRawLists;
+  
+
+implementation
+
+uses
+  Template;
+
+
+function AGDB(ConnectionID, FileID: Integer): TRawDataList;
+var
+  link:  Integer;
+  links: Integer;
+  i:     Integer;
+begin
+  if not connection.OSisMac then
+  begin
+    ConManager.Connection[ConnectionID].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;
+      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, 4, @link);
+      Result[i].raw_addr := link;
+      Result[i].raw_size := 32;
+      Result[i].loc_sep  := False;
+    end;
+  end;
+end;
+
+
+
+
+function AKVA(ConnectionID, FileID: Integer): TRawDataList;
+var
+  link:  Integer;
+  links: Integer;
+  i:     Integer;
+begin
+  if not connection.OSisMac then
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, 4, @links);
+    SetLength(Result, links);
+    for i := 0 to links - 1 do
+    begin
+      Result[i].src_offset := $20 + i * $74 + $24;
+      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * $74 + $24, 4, @link);
+      Result[i].raw_addr := link;
+      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * $74 + $28, 4, @link);
+      Result[i].raw_size := link;
+      Result[i].loc_sep  := False;
+    end;
+  end;
+end;
+
+
+
+
+function BINA(ConnectionID, FileID: Integer): TRawDataList;
+var
+  link:     Integer;
+  datasize: Integer;
+begin
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $0C, 4, @link);
+  ConManager.Connection[ConnectionID].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    := connection.OSisMac;
+end;
+
+
+
+
+function OSBD(ConnectionID, FileID: Integer): TRawDataList;
+var
+  link:     Integer;
+  datasize: Integer;
+begin
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, 4, @datasize);
+  ConManager.Connection[ConnectionID].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    := connection.OSisMac;
+end;
+
+
+
+
+function SNDD(ConnectionID, FileID: Integer): TRawDataList;
+var
+  link:     Integer;
+  datasize: Integer;
+begin
+  SetLength(Result, 1);
+  if not connection.OSisMac then
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $40, 4, @datasize);
+    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $44, 4, @link);
+    Result[0].src_offset := $44;
+  end
+  else
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, 4, @datasize);
+    ConManager.Connection[ConnectionID].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(ConnectionID, FileID: Integer): TRawDataList;
+var
+  baselink, lastlink: Integer;
+  links: Integer;
+  j, k:  Integer;
+  Data:  TByteData;
+begin
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, 4, @baselink);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, 4, @links);
+  if links > 0 then
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + (links - 1) * 4, 4, @lastlink);
+    SetLength(Data, lastlink + 1024);
+    TOniDataDat(connection).LoadRawOffset(False,
+      baselink, lastlink + 1024, Data);
+    //      connection.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(ConnectionID, FileID: Integer): TRawDataList;
+var
+  i:      Integer;
+  link:   Integer;
+  frames: Word;
+  tempb:  Byte;
+  tempw:  Word;
+  templ:  Integer;
+  Data:   TByteData;
+  offset: Word;
+  frame_count: Byte;
+begin
+  SetLength(Result, 13);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $16C, 2, @frames);
+  {y-pos}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $0C, 4, @link);
+  Result[0].src_offset := $0C;
+  Result[0].raw_addr   := link;
+  Result[0].raw_size   := frames * 4;
+  {x-z-pos}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, 4, @link);
+  Result[1].src_offset := $10;
+  Result[1].raw_addr   := link;
+  Result[1].raw_size   := frames * 8;
+  {attacks}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $182, 1, @tempb);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $14, 4, @link);
+  Result[2].src_offset := $14;
+  Result[2].raw_addr   := link;
+  Result[2].raw_size   := tempb * 32;
+  {damage}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $183, 1, @tempb);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, 4, @link);
+  Result[3].src_offset := $18;
+  Result[3].raw_addr   := link;
+  Result[3].raw_size   := tempb * 8;
+  {motionblur}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $184, 1, @tempb);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, 4, @link);
+  Result[4].src_offset := $1C;
+  Result[4].raw_addr   := link;
+  Result[4].raw_size   := tempb * 8;
+  {shortcut}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $185, 1, @tempb);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20, 4, @link);
+  Result[5].src_offset := $20;
+  Result[5].raw_addr   := link;
+  Result[5].raw_size   := tempb * 8;
+  {throw}
+  ConManager.Connection[ConnectionID].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}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $186, 1, @tempb);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $28, 4, @link);
+  Result[7].src_offset := $28;
+  Result[7].raw_addr   := link;
+  Result[7].raw_size   := tempb * 4;
+  {particle}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $187, 1, @tempb);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $2C, 4, @link);
+  Result[8].src_offset := $2C;
+  Result[8].raw_addr   := link;
+  Result[8].raw_size   := tempb * 24;
+  {position}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $30, 4, @link);
+  Result[9].src_offset := $30;
+  Result[9].raw_addr   := link;
+  Result[9].raw_size   := frames * 8;
+  {particle}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $154, 2, @tempw);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $38, 4, @link);
+  Result[11].src_offset := $38;
+  Result[11].raw_addr   := link;
+  Result[11].raw_size   := tempw * 34;
+  {extent}
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $138, 4, @templ);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $13C, 4, @link);
+  Result[12].src_offset := $13C;
+  Result[12].raw_addr   := link;
+  Result[12].raw_size   := templ * 12;
+
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $34, 4, @link);
+  if link > 0 then
+  begin
+    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $160, 2, @tempw);
+    frame_count := 0;
+    i := 0;
+    SetLength(Data, $FFFF);
+    TOniDataDat(connection).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(ConnectionID, FileID: Integer): TRawDataList;
+var
+  link_pc:   Integer;
+  link_mac:  Integer;
+  x, y:      Word;
+  storetype: Byte;
+  datasize:  Integer;
+begin
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(x), @x);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(y), @y);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(storetype), @storetype);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, 4, @link_pc);
+  ConManager.Connection[ConnectionID].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 connection.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  := connection.OSisMac;
+end;
+
+
+
+
+function TRawLists.GetRawInfo(ConnectionID, FileID,
+  DatOffset: Integer): TRawDataInfo;
+var
+  i: Integer;
+  RawList: TRawDataList;
+begin
+  RawList          := GetRawList(ConnectionID, FileID);
+  Result.SrcID     := -1;
+  Result.SrcOffset := -1;
+  Result.RawAddr   := -1;
+  Result.RawSize   := -1;
+  if Length(RawList) > 0 then
+  begin
+    for i := 0 to High(RawList) do
+    begin
+      if RawList[i].SrcOffset = DatOffset then
+      begin
+        Result.SrcID     := FileID;
+        Result.SrcOffset := RawList[i].SrcOffset;
+        Result.RawAddr   := RawList[i].RawAddr;
+        Result.RawSize   := RawList[i].RawSize;
+        Result.LocSep    := RawList[i].LocSep;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+
+function TRawLists.GetRawList(ConnectionID, FileID: Integer): TRawDataList;
+var
+  i: Integer;
+  fileinfo: TFileInfo;
+begin
+  SetLength(Result, 0);
+  fileinfo := ConManager.Connection[ConnectionID].GetFileInfo(FileID);
+  for i := 0 to High(FRawListHandlers) do
+    if UpperCase(FRawListHandlers[i].Ext) = UpperCase(fileinfo.extension) then
+    begin
+      if FRawListHandlers[i].needed then
+        Result := FRawListHandlers[i].Handler(ConnectionID, FileID);
+      Break;
+    end;
+end;
+
+procedure TRawLists.InsertRawListHandler(ext: String; needed: Boolean; handler: THandler);
+begin
+  SetLength(FRawListHandlers, Length(FRawListHandlers) + 1);
+  FRawListHandlers[High(FRawListHandlers)].Ext := ext;
+  FRawListHandlers[High(FRawListHandlers)].needed := needed;
+  FRawListHandlers[High(FRawListHandlers)].handler := handler;
+//  Raws := Raws + ext;
+  AddToolListEntry('rawedit', '', ext);
+end;
+
+
+
+
+initialization
+  RawLists := TRawLists.Create;
+  RawLists.InsertRawListHandler('AGDB',False,AGDB);
+  RawLists.InsertRawListHandler('AKVA', True, AKVA);
+  RawLists.InsertRawListHandler('BINA', True, BINA);
+  RawLists.InsertRawListHandler('OSBD', True, OSBD);
+  RawLists.InsertRawListHandler('SNDD', True, SNDD);
+  RawLists.InsertRawListHandler('SUBT', True, SUBT);
+  RawLists.InsertRawListHandler('TRAM', True, TRAM);
+  RawLists.InsertRawListHandler('TXMP', True, TXMP);
+end.
Index: oup/rewrite/Global/TypeDefs.pas
===================================================================
--- oup/rewrite/Global/TypeDefs.pas	(revision 93)
+++ oup/rewrite/Global/TypeDefs.pas	(revision 97)
@@ -3,8 +3,11 @@
 
 uses
-  Graphics;
+  Graphics, SysUtils;
 
 type
+  ENotImplemented = class(Exception);
+
   TDataBackend = (DB_ONI, DB_ADB);
+  TDataOS = (DOS_WIN, DOS_MAC);
 
   TChangeRights = set of (CR_EditDat, CR_EditRaw, CR_ResizeDat, CR_ResizeRaw);
@@ -51,5 +54,5 @@
   );
 
-  TByteArray = array of Byte; 
+  TByteData = array of Byte; 
 
   TAppSettings = record
@@ -79,4 +82,7 @@
 }
 
+const
+  CrLf: String[2] = #13#10;
+
 implementation
 
