BinCueReader.pas
上传用户:wanyu_2000
上传日期:2021-02-21
资源大小:527k
文件大小:19k
源码类别:

DVD

开发平台:

Delphi

  1. {-----------------------------------------------------------------------------
  2.  Unit Name: BinCueReader
  3.  Author:    Dancemammal
  4.  Purpose:   Read and extract tracks from BIN / CUE files
  5.  History:   First Release
  6. -----------------------------------------------------------------------------}
  7. unit BinCueReader;
  8. interface
  9. Uses Classes,Windows,sysutils,StrUtils;
  10. Const
  11.       MODE_UNKNOWN = 0;
  12.       MODE_AUDIO = 1;
  13.       MODE_MODE1 = 2;
  14.       MODE_MODE2 = 3;
  15.       MODE_MODE2_FORM1 = 4;
  16.       MODE_MODE2_FORM2 = 5;
  17.       MODE_MODE1_2048 = 6;
  18.       MODE_MODE2_2048 = 7;
  19.       CUE_OK               = 0;
  20.       CUE_CUEMISSING       = 1;
  21.       CUE_BINMISSING       = 2;
  22.       CUE_CUEFILEEXPECTED  = 3;
  23.       CUE_BINFILEEXPECTED  = 4;
  24.       CUE_BINARYEXPECTED   = 5;
  25.       CUE_TRACKEXPECTED    = 6;
  26.       CUE_TRACKNUMEXPECTED = 7;
  27.       CUE_INDEXEXPECTED    = 8;
  28.       CUE_INDEXNUMEXPECTED = 9;
  29.       CUE_INDEXMSFEXPECTED = 10;
  30.       CUE_UNKNOWN_ERROR    = 11;
  31.       PostLeadInGapTime    = 150;
  32. type
  33.   TWaveHeader = record
  34.     { RIFF file header }
  35.     RIFFHeader   : array[1..4] of Char; { Must be "RIFF" }
  36.     FileSize     : Integer; { Must be "RealFileSize - 8" }
  37.     WAVEHeader   : array[1..4] of Char; { Must be "WAVE" }
  38.     { Format information }
  39.     FormatHeader : array[1..4] of Char; { Must be "fmt " }
  40.     FormatSize   : DWord; { Must be 16 (decimal) }
  41.     FormatCode   : Word; { Must be 1 }
  42.     ChannelNumber: Word; { Number of channels }
  43.     SampleRate   : DWord; { Sample rate (hz) }
  44.     BytesPerSecond: DWord; { Bytes per second }
  45.     BytesPerSample: Word; { Bytes per Sample }
  46.     BitsPerSample : Word; { Bits per sample }
  47.     ExtraFormatBytes: Word;
  48.     { Data area }
  49.     DataHeader    : array[1..4] of Char; { Must be "data" }
  50.     DataSize      : DWord; { Data size }
  51.   end;
  52. Type
  53.  TATIPCue = Packed Record
  54.     CTL_ADR   : Byte;   // control field
  55.     TNO       : Byte;   // track number
  56.     Index     : Byte;   // Index number
  57.     DataForm  : Byte;   // data form ??
  58.     SCMS      : Byte;   // Serial Copy Managment system
  59.     Min       : Byte;
  60.     Sec       : Byte;
  61.     Frame     : Byte;
  62.   end;
  63. Type
  64.   TATIPCueList = Packed Record
  65.        Cues : Array[0..98] of TATIPCue;
  66.        Count : Integer;
  67.        BurnMode : Integer;
  68.    end;
  69. Type
  70.    TIndex = Packed Record
  71.       LBA      : Integer;
  72.       ATIP     : Integer;
  73.       IndexNum : Integer;
  74.     end;
  75. Type
  76.  TTrack = Packed Record
  77.      Mode       : Integer;
  78.      ModeDesc   : String[30];
  79.      FileType   : String[20];
  80.      FileName   : String[255];
  81.      FileSize   : LongInt;
  82.      PreGap     : Integer;
  83.      PreATIP    : Integer;
  84.      Index      : Array[0..98] of TIndex;
  85.      FirstIndex : Integer;
  86.      IndexCount : Integer;
  87.      TrackNumber : Integer;
  88.    end;
  89. Type
  90.   TTrackList = Packed Record
  91.      Tracks : Array[0..98] of TTrack;
  92.      Count : Integer;
  93.    end;
  94. TExtractProgress = procedure(PercentDone: Integer; Cancel : Boolean) of object;
  95. Type
  96.     TBinCueReader = Class
  97.     Private
  98.        CurrentTrack : Integer;
  99.        CurrentFileType : String;
  100.        CurrentIndexCount : Integer;
  101.        CueBuilderIndex : Integer;
  102.        FCueFileName : String;
  103.        FBinFileName : String;
  104.        FExtractProcess : TExtractProgress;
  105.        FBinTracks : TTrackList;
  106.        FCUEList : Tstringlist;
  107.        FTitle : String;
  108.        FPerformer : String;
  109.        FSongWriter : String;
  110.        FCatalog : String;
  111.        FATIPCounter : Integer;
  112.        FATIPCueList : TATIPCueList;
  113.        FCuePath     : String;
  114.        Function GetATIPCueList : TATIPCueList;
  115.        Function TrackModeToString(TrackMode : Integer): String;
  116.        Function StrToMode(TrackVal : String): Integer;
  117.        Function Parse(CueLine : String) : Integer;
  118.        Procedure AddPostLeadInGap;
  119.        Procedure SetupLeadIn;
  120.        Procedure SetupLeadOut;
  121.        Procedure CheckPreGap(Track : TTrack);
  122.        Procedure AddTrackToCUE(Track : TTrack);
  123.        Function BinLength(FileName : String):Integer;
  124.        Function WavLength(FileName : String):Integer;
  125.     Public
  126.       Function ExtractTrack(TrackNo : Integer; ToFileName : String ) : Boolean;
  127.       Function TrackMode(TrackNo : Integer): Integer;
  128.       Function OpenCueFile(FileName : String) : Integer;
  129.       Procedure SaveATIPCueToFile(FileName : String);
  130.       Constructor Create;
  131.       Destructor Destroy; override;
  132.     Published
  133.       property OnExtractProcess: TExtractProgress read FExtractProcess write FExtractProcess;
  134.       property CueFileName: String read FCueFileName write FCueFileName;
  135.       property BinFileName: String read FBinFileName write FBinFileName;
  136.       Property BinTrackList : TTrackList Read FBinTracks;
  137.       Property ATIPCueList : TATIPCueList Read GetATIPCueList;
  138.       property Title : String read FTitle write FTitle;
  139.       property Performer : String read FPerformer write FPerformer;
  140.       property SongWriter : String read FSongWriter write FSongWriter;
  141.       property Catalog : String read FCatalog write FCatalog;
  142.    end;
  143. implementation
  144. uses covertfuncs,ReadWave;
  145. function HMSFtoLBA(const  AMinute, ASecond, AFrame: Byte): LongWord;
  146. begin
  147.    Result := (AMinute * 60 * 75) + (ASecond * 75) + AFrame;
  148. end;
  149. Function StrToLBA(HSF : String) : LongWord;
  150. var
  151.     AMinute, ASecond, AFrame :Byte;
  152.    TempStr,Coded : String;
  153. begin
  154.    Coded := HSF;
  155.    TempStr := copy(Coded,0,pos(':',Coded)-1);
  156.    AMinute := strtoint(TempStr);
  157.    delete(Coded,1,pos(':',Coded));
  158.    TempStr := copy(Coded,0,pos(':',Coded)-1);
  159.    ASecond := strtoint(TempStr);
  160.    delete(Coded,1,pos(':',Coded));
  161.    TempStr := copy(Coded,0,99);
  162.    AFrame := strtoint(TempStr);
  163.    Result := HMSFtoLBA(AMinute,ASecond,AFrame);
  164. end;
  165. Constructor TBinCueReader.Create;
  166. begin
  167.     FCUEList := Tstringlist.create;
  168.     FATIPCounter := 0;
  169. end;
  170. Destructor TBinCueReader.Destroy;
  171. begin
  172.    FCUEList.Clear;
  173.    FCUEList.Free;
  174. end;
  175. Function TBinCueReader.StrToMode(TrackVal : String): Integer;
  176. begin
  177.       Result := MODE_UNKNOWN;
  178.       If TrackVal = 'AUDIO' then Result := MODE_AUDIO;
  179.       If TrackVal = 'MODE1/2352' then Result := MODE_MODE1;
  180.       If TrackVal = 'MODE2/2352' then Result := MODE_MODE2;
  181.       If TrackVal = 'MODE2FORM1/2352' then Result := MODE_MODE2_FORM1;
  182.       If TrackVal = 'MODE2FORM2/2352' then Result := MODE_MODE2_FORM2;
  183.       If TrackVal = 'MODE1/2048' then Result := MODE_MODE1_2048;
  184.       If TrackVal = 'MODE2/2048' then Result := MODE_MODE2_2048;
  185. End;
  186. Function TBinCueReader.TrackModeToString(TrackMode : Integer): String;
  187. begin
  188.      Result := 'MODE UNKNOWN';
  189.      Case TrackMode of
  190.         1 : Result := 'AUDIO';
  191.         2 : Result := 'MODE1 / 2352';
  192.         3 : Result := 'MODE2 / 2352';
  193.         4 : Result := 'MODE2 FORM1 / 2352';
  194.         5 : Result := 'MODE2 FORM2 / 2352';
  195.         6 : Result := 'MODE1 / 2048';
  196.         7 : Result := 'MODE2 / 2048';
  197.      end;
  198. end;
  199. Function TBinCueReader.TrackMode(TrackNo : Integer):Integer;
  200. begin
  201.     Result := FBinTracks.Tracks[TrackNo -1].Mode;
  202. end;
  203. Function TBinCueReader.WavLength(FileName : String):Integer;
  204. var
  205.   Header: PWaveInformation;
  206.   Count : LongInt;
  207.   Secs, Mins, Frames : Integer;
  208. begin
  209.   Result := 0;
  210.   Header := GetWaveInformationFromFile(FileName);
  211.   Count := round(Header^.Length);
  212.   Dispose(Header);
  213.   Result := Count;
  214. end;
  215. Function TBinCueReader.BinLength(FileName : String):Integer;
  216. begin
  217.   Result := 0;
  218.   with TFileStream.Create(FileName, fmOpenRead) do
  219.     try
  220.      Result := Size;
  221.     finally
  222.       Free;
  223.     end;
  224. end;
  225. {
  226. FILE "VIDEOC~1.BIN" BINARY
  227. TRACK 01 MODE2/2352
  228. INDEX 01 00:00:00
  229. TRACK 02 MODE2/2352
  230. INDEX 00 00:04:00
  231. INDEX 01 00:06:00
  232. TRACK 03 MODE2/2352
  233. INDEX 00 00:37:52
  234. INDEX 01 00:39:52
  235. TITLE "Enter title (disc or track)"
  236. PERFORMER "Enter Performer (disc or track)"
  237. SONGWRITER "Enter Songwriter (disc or track)"
  238. CATALOG 1234567890123
  239. FILE "C:TRACK1.WAV" WAVE
  240.   TRACK 01 AUDIO
  241.     PREGAP 00:02:00
  242.     INDEX 01 00:00:00
  243. FILE "C:TRACK2.WAV" WAVE
  244.   TRACK 02 AUDIO
  245.     PREGAP 00:02:00
  246.     INDEX 01 00:00:00
  247. }
  248. Function TBinCueReader.Parse(CueLine : String) : Integer;
  249. var
  250.    Filename,Filetype : String;
  251.    TrackNo, TrackType, IndexNo, TrackSecs : String;
  252.    TempCopy,Line : String;
  253.    IndexInt, TrackLength : Integer;
  254. begin
  255.    Result := 0;
  256.    Line := Trim(CueLine);
  257.    TempCopy := Copy(Line,0,Pos(' ',Line)-1);  // get KeyWord (FILE, TRACK, INDEX etc)
  258.    Delete(Line,1,Pos(' ',Line));
  259.    if (TempCopy = 'FILE') then //FILE "VIDEOC~1.BIN" BINARY
  260.     begin
  261.         Delete(Line,1,Pos('"',Line));
  262.         Filename := Copy(Line,0,pos('"',Line)-1); // filename
  263.         FileName := AnsiReplaceStr(FileName,'"','');
  264.         Delete(Line,1,Pos('"',Line));
  265.         Filetype := Copy(Line,0,100);
  266.         FBinFileName := trim(FileName);
  267.         CurrentFileType := trim(Filetype);
  268.         exit;
  269.     end;
  270.    if (TempCopy = 'TITLE') then //TITLE "Enter title (disc or track)"
  271.     begin
  272.         Filename := Copy(Line,0,99); // title
  273.         FileName := AnsiReplaceStr(FileName,'"','');
  274.         FTitle := trim(FileName);
  275.         exit;
  276.     end;
  277.    if (TempCopy = 'PERFORMER') then //PERFORMER "Enter Performer (disc or track)"
  278.     begin
  279.         Filename := Copy(Line,0,99); // title
  280.         FileName := AnsiReplaceStr(FileName,'"','');
  281.         FPerformer := trim(FileName);
  282.         exit;
  283.     end;
  284.    if (TempCopy = 'SONGWRITER') then //SONGWRITER "Enter Songwriter (disc or track)"
  285.     begin
  286.         Filename := Copy(Line,0,99); // title
  287.         FileName := AnsiReplaceStr(FileName,'"','');
  288.         FSongWriter := trim(FileName);
  289.         exit;
  290.     end;
  291.    if (TempCopy = 'CATALOG') then //CATALOG 1234567890123
  292.     begin
  293.         Filename := Copy(Line,0,99); // title
  294.         FCatalog := trim(FileName);
  295.         exit;
  296.     end;
  297.    if (TempCopy = 'TRACK') then //TRACK 01 MODE2/2352
  298.     begin
  299.         TrackNo := Copy(Line,0,pos(' ',Line)-1); // Track no
  300.         Delete(Line,1,Pos(' ',Line));
  301.         TrackType := Copy(Line,0,100);
  302.         
  303.         if (CurrentTrack > 0) then
  304.             inc(FATIPCounter,FBinTracks.Tracks[CurrentTrack -1].FileSize); // add on length of last file ?
  305.         CurrentTrack := strtoint(TrackNo);
  306.         FBinTracks.Tracks[CurrentTrack -1].FileName := FBinFileName;
  307.         FBinTracks.Tracks[CurrentTrack -1].Mode := StrToMode(trim(TrackType));
  308.         FBinTracks.Tracks[CurrentTrack -1].ModeDesc := TrackModeToString(StrToMode(trim(TrackType)));
  309.         FBinTracks.Tracks[CurrentTrack -1].FirstIndex := -1;
  310.         FBinTracks.Tracks[CurrentTrack -1].PreGap := 0;
  311.         FBinTracks.Tracks[CurrentTrack -1].TrackNumber := CurrentTrack;
  312.         if CurrentFileType = 'WAVE' then
  313.         begin
  314.           TrackLength := WavLength(FBinFileName);
  315.           FBinTracks.Tracks[CurrentTrack -1].FileSize := TrackLength;
  316.         end
  317.           else
  318.            if CurrentFileType = 'BINARY' then
  319.            begin
  320.              TrackLength := BinLength(FBinFileName);
  321.              FBinTracks.Tracks[CurrentTrack -1].FileSize := TrackLength;
  322.            end;
  323.         CurrentIndexCount := 0;
  324.         Exit;
  325.     end;
  326.    if (TempCopy = 'PREGAP') then //PREGAP 00:02:00
  327.     begin
  328.         TrackSecs := Copy(Line,0,100); //00:02:00
  329.         FBinTracks.Tracks[CurrentTrack -1].PreGap := StrToLBA(TrackSecs);
  330.         inc(FATIPCounter,FBinTracks.Tracks[CurrentTrack -1].PreGap);
  331.         FBinTracks.Tracks[CurrentTrack -1].PreATIP := FATIPCounter;
  332.         Exit;
  333.     end;
  334.    if (TempCopy = 'INDEX') then //INDEX 00 00:00:00  INDEX 01 03:28:42
  335.     begin
  336.         IndexNo := Copy(Line,0,pos(' ',Line)-1); // Index no
  337.         IndexInt := strtoint(IndexNo);
  338.         Delete(Line,1,Pos(' ',Line));
  339.         TrackSecs := Copy(Line,0,100);
  340.         if (FBinTracks.Tracks[CurrentTrack -1].FirstIndex = -1) then
  341.                     FBinTracks.Tracks[CurrentTrack -1].FirstIndex := IndexInt;
  342.         FBinTracks.Tracks[CurrentTrack -1].Index[IndexInt].LBA := StrToLBA(TrackSecs);
  343.         inc(FATIPCounter,FBinTracks.Tracks[CurrentTrack -1].Index[IndexInt].LBA);
  344.         FBinTracks.Tracks[CurrentTrack -1].Index[IndexInt].ATIP := FATIPCounter;
  345.         FBinTracks.Tracks[CurrentTrack -1].Index[IndexInt].IndexNum := IndexInt;
  346.         FBinTracks.Tracks[CurrentTrack -1].IndexCount := (CurrentIndexCount + 1);
  347.         inc(CurrentIndexCount);
  348.         FBinTracks.Tracks[CurrentTrack -1].FileType := CurrentFileType;
  349.         Exit;
  350.     end;
  351. end;
  352. Function TBinCueReader.OpenCueFile(FileName : String) : Integer;
  353. var
  354.      Count : Integer;
  355.      BufString : String;
  356. begin
  357.     Result := CUE_OK;
  358.     if not fileexists(Filename) then
  359.     begin
  360.         Result := CUE_CUEMISSING;
  361.         exit;
  362.     end;
  363.     CurrentTrack := 0;
  364.     CurrentIndexCount := 0;
  365.     FATIPCounter := 150;
  366.     FCUEList.LoadFromFile(Filename);
  367.     FCuePath := ExtractFilePath(FileName);
  368.     for Count := 0 to FCUEList.Count -1 do
  369.     begin
  370.       BufString := FCUEList.Strings[Count];
  371.       Result := Parse(Trim(BufString));
  372.     end;
  373.     inc(FATIPCounter,FBinTracks.Tracks[CurrentTrack -1].FileSize); // add on length of last file for lead out
  374.     FBinTracks.Count := CurrentTrack;
  375. end;
  376. Function TBinCueReader.ExtractTrack(TrackNo : Integer; ToFileName : String ) : Boolean;
  377. Const
  378.     ChunkSize = 65535;
  379. var
  380.     lngStart, lngEnd, Counter : Integer; //start and end offset
  381.     BinFileStream, OUTFileStream : TFileStream;      //  file Streams
  382.     StreamBuf : PChar;          //read buffer
  383.     blnCancel : Boolean;
  384.     BytesWritten : Integer;
  385. Begin
  386.     Result := True;
  387.     BytesWritten := 0;
  388.     StreamBuf := '';
  389.     blnCancel := False;
  390.     BinFileStream := TFileStream.Create(FBinFileName, fmOpenRead);
  391.      //Get Start LBA
  392.     with FBinTracks.Tracks[TrackNo -1] do
  393.        if FirstIndex = 0 then
  394.             lngStart := Index[1].LBA * 2352
  395.            else
  396.              lngStart := index[0].LBA * 2352;
  397.      //get the LBA of the next track
  398.     If TrackNo = FBinTracks.Count Then
  399.         lngEnd := (BinFileStream.Size - lngStart)
  400.     Else
  401.         lngEnd := FBinTracks.Tracks[TrackNo].index[0].LBA * 2352;
  402.     // Setup seek pos and output file
  403.     BinFileStream.Seek((lngStart + 1), soFromBeginning);
  404.     OUTFileStream := TFileStream.Create(ToFileName, fmOpenRead);
  405.     // extract data
  406.    While (BytesWritten < (lngEnd - lngStart)) do
  407.    begin
  408.         If (ChunkSize + BinFileStream.Position > lngEnd) Then
  409.             Counter := (lngEnd - BinFileStream.Position)
  410.             else
  411.               Counter := ChunkSize;
  412.        BytesWritten := BytesWritten + BinFileStream.Read(StreamBuf^,Counter);
  413.        OUTFileStream.Write(StreamBuf^,Counter);
  414.        if Assigned(FExtractProcess) then FExtractProcess(BytesWritten div ((lngEnd - lngStart) div 100), blnCancel);
  415.        If blnCancel Then Exit;
  416.    end;
  417.     OUTFileStream.free;
  418.     BinFileStream.free;
  419.     Result := True;
  420. End;
  421. // add cue line for 2 second gap (150 lba) after lead in
  422. Procedure TBinCueReader.AddPostLeadInGap;
  423. begin
  424.    FATIPCueList.Cues[CueBuilderIndex].CTL_ADR := $01;
  425.    FATIPCueList.Cues[CueBuilderIndex].TNO := $01;
  426.    FATIPCueList.Cues[CueBuilderIndex].Index := $00;
  427.    FATIPCueList.Cues[CueBuilderIndex].DataForm := $01;
  428.    FATIPCueList.Cues[CueBuilderIndex].SCMS := $00;
  429.    FATIPCueList.Cues[CueBuilderIndex].Min := $00;
  430.    FATIPCueList.Cues[CueBuilderIndex].Sec := $00;
  431.    FATIPCueList.Cues[CueBuilderIndex].Frame := $00;
  432.    inc(CueBuilderIndex);
  433. end;
  434. // set up first CUE as disk lead in
  435. Procedure TBinCueReader.SetupLeadIn;
  436. begin
  437.    FATIPCueList.Cues[0].CTL_ADR := $01;
  438.    FATIPCueList.Cues[0].TNO := $00;
  439.    FATIPCueList.Cues[0].Index := $00;
  440.    FATIPCueList.Cues[0].DataForm := $01;
  441.    FATIPCueList.Cues[0].SCMS := $00;
  442.    FATIPCueList.Cues[0].Min := $00;
  443.    FATIPCueList.Cues[0].Sec := $00;
  444.    FATIPCueList.Cues[0].Frame := $00;
  445.    CueBuilderIndex := 1;
  446.    AddPostLeadInGap;
  447. end;
  448. // set up Last CUE as disk lead out
  449. Procedure TBinCueReader.SetupLeadOut;
  450. var
  451.   Min, Sec, Frm : Integer;
  452. begin
  453.    LBA2MSF(FATIPCounter,  Min, Sec, Frm);
  454.    FATIPCueList.Cues[CueBuilderIndex].CTL_ADR := $01;
  455.    FATIPCueList.Cues[CueBuilderIndex].TNO := $AA;
  456.    FATIPCueList.Cues[CueBuilderIndex].Index := $01;
  457.    FATIPCueList.Cues[CueBuilderIndex].DataForm := $01;
  458.    FATIPCueList.Cues[CueBuilderIndex].SCMS := $00;
  459.    FATIPCueList.Cues[CueBuilderIndex].Min := Min; 
  460.    FATIPCueList.Cues[CueBuilderIndex].Sec := Sec;
  461.    FATIPCueList.Cues[CueBuilderIndex].Frame := Frm;
  462.    FATIPCueList.Count := CueBuilderIndex;
  463. end;
  464. Procedure TBinCueReader.CheckPreGap(Track : TTrack);
  465. var
  466.   Min, Sec, Frm : Integer;
  467. begin
  468.    if (Track.PreGap <> 0) then
  469.    begin
  470.         LBA2MSF(Track.PreATIP,  Min, Sec, Frm);
  471.         FATIPCueList.Cues[CueBuilderIndex].CTL_ADR := $41;
  472.         FATIPCueList.Cues[CueBuilderIndex].TNO := Track.TrackNumber;
  473.         FATIPCueList.Cues[CueBuilderIndex].Index := $00;
  474.         FATIPCueList.Cues[CueBuilderIndex].DataForm := $10;
  475.         FATIPCueList.Cues[CueBuilderIndex].SCMS := $00;
  476.         FATIPCueList.Cues[CueBuilderIndex].Min := Min; 
  477.         FATIPCueList.Cues[CueBuilderIndex].Sec := Sec;
  478.         FATIPCueList.Cues[CueBuilderIndex].Frame := Frm;
  479.         inc(CueBuilderIndex);
  480.    end;
  481. end;
  482. Procedure TBinCueReader.AddTrackToCUE(Track : TTrack);
  483. Var
  484.     IndexCnt : Integer;
  485.     Min, Sec, Frm : Integer;
  486. begin
  487.    CheckPreGap(Track);
  488.    FATIPCueList.BurnMode := Track.Mode;
  489.    for IndexCnt := Track.FirstIndex to Track.IndexCount do
  490.    begin
  491.       LBA2MSF(Track.Index[IndexCnt].ATIP,  Min, Sec, Frm);
  492.       FATIPCueList.Cues[CueBuilderIndex].CTL_ADR := $41;     // can copy and is trc index
  493.       FATIPCueList.Cues[CueBuilderIndex].TNO := Track.TrackNumber;
  494.       FATIPCueList.Cues[CueBuilderIndex].Index := Track.Index[IndexCnt].IndexNum;
  495.       FATIPCueList.Cues[CueBuilderIndex].DataForm := $C0;
  496.       FATIPCueList.Cues[CueBuilderIndex].SCMS := $00;
  497.       FATIPCueList.Cues[CueBuilderIndex].Min := Min;
  498.       FATIPCueList.Cues[CueBuilderIndex].Sec := Sec;
  499.       FATIPCueList.Cues[CueBuilderIndex].Frame := Frm;
  500.       inc(CueBuilderIndex);
  501.    end;
  502. end;
  503. Procedure TBinCueReader.SaveATIPCueToFile(FileName : String);
  504. var
  505.   Index : Integer;
  506.   CueFile : TStringlist;
  507.   Temp : String;
  508. begin
  509.    CueFile := TStringlist.create;
  510.    GetATIPCueList;
  511.    CueFile.Add('|  Count  |  CTL/ADR  |  TRK No  |  Index  | Data Form |  SCMS  |  MIN  |  SEC  |  Frame  |');
  512.    CueFile.add('-------------------------------------------------------------------------------------------');
  513.    for Index := 0 to 98 do
  514.    begin
  515.      Temp :=     '|   '+Inttostr(Index)+'    ';
  516.      Temp :=Temp+'|    '+InttoHex(FATIPCueList.Cues[index].CTL_ADR,2)+'     ';
  517.      Temp :=Temp+'|   '+InttoHex(FATIPCueList.Cues[index].TNO,2)+'   ';
  518.      Temp :=Temp+'|   '+InttoHex(FATIPCueList.Cues[index].Index,2)+'   ';
  519.      Temp :=Temp+'|    '+InttoHex(FATIPCueList.Cues[index].DataForm,2)+'     ';
  520.      Temp :=Temp+'|   '+InttoHex(FATIPCueList.Cues[index].SCMS,2)+'   ';
  521.      Temp :=Temp+'|   '+Inttostr(FATIPCueList.Cues[index].Min)+'   ';
  522.      Temp :=Temp+'|   '+Inttostr(FATIPCueList.Cues[index].Sec)+'   ';
  523.      Temp :=Temp+'|   '+Inttostr(FATIPCueList.Cues[index].Frame)+'   ';
  524.      CueFile.add(Temp);
  525.    end;
  526.    CueFile.SaveToFile(Filename);
  527. end;
  528. Function TBinCueReader.GetATIPCueList : TATIPCueList;
  529. var
  530.    Index : Integer;
  531. begin
  532.     CueBuilderIndex := 0;
  533.     SetupLeadIn;
  534.     for Index := 0 to BinTrackList.Count -1 do
  535.           AddTrackToCUE(BinTrackList.Tracks[Index]);
  536.    SetupLeadOut;
  537.    result := FATIPCueList;
  538. end;
  539. end.
  540.