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
        Result := ExportHandlers[i].Handler(ConnectionID, FileID, filename);
end;




function ExportSNDD(ConnectionID, FileID: Integer; filename: String): Integer;
type
  TDatData = packed record
    {0x00}
    _fileid:         Integer;
    level:           Integer;
    FormatSize:      Integer;
    AudioFormat:     Word;
    NumChannels:     Word;
    {0x10}
    SampleRate:      Integer;
    ByteRate:        Integer;
    BlockAlign:      Word;
    BitsPerSample:   Word;
    {0x1C}
    SizeExtHeader:   Word;
    SamplesPerBlock: Word;
    NumCoefficients: Word;
    Coefficients:    array[0..6] of Integer;
    {0x3E}
    Duration:        Word;
    {0x40}
    RawSize:         Integer;
    RawPos:          Integer;
  end;
var
  filestream: TFileStream;
  DatData:     TDatData;
  i: Integer;

  //Wave Header Stuff
  ASCII_RIFF:   LongWord; //"RIFF"
  WAVE_Len:     Integer;
  ASCII_WAVE:   LongWord; //"WAVE"
  ASCII_FMT:    LongWord; //"fmt "
  WAVE_FMT_Len: Integer;
  ASCII_DATA:   LongWord; //"data"
  WAVE_DataLen:  Integer;
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: Integer;
  link: Integer;
  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.WriteToFile(filename+'.dds');
  img.WriteToFile(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.
