private void ExtractISO(PbpDiscEntry disc, string path, ExtractOptions extractInfo, CancellationToken cancellationToken) { try { disc.ProgressEvent += ProgressEvent; if (!ContinueIfFileExists(extractInfo, path)) { return; } Notify?.Invoke(PopstationEventEnum.Info, $"Writing {path}..."); Notify?.Invoke(PopstationEventEnum.GetIsoSize, disc.IsoSize); Notify?.Invoke(PopstationEventEnum.ExtractStart, disc.Index); var cueFilename = Path.GetFileNameWithoutExtension(path) + ".cue"; var dirPath = Path.GetDirectoryName(path); var cuePath = Path.Combine(dirPath, cueFilename); TempFiles.Add(path); TempFiles.Add(cuePath); using (var isoStream = new FileStream(path, FileMode.Create, FileAccess.Write)) { disc.CopyTo(isoStream, cancellationToken); } if (cancellationToken.IsCancellationRequested) { return; } TempFiles.Remove(path); if (!extractInfo.CreateCuesheet) { return; } var cueFile = TOCHelper.TOCtoCUE(disc.TOC, Path.GetFileName(path)); CueFileWriter.Write(cueFile, cuePath); TempFiles.Remove(cuePath); Notify?.Invoke(PopstationEventEnum.ExtractComplete, null); } finally { disc.ProgressEvent -= ProgressEvent; } }
private static CueFile TOCtoCUE(List <TOCEntry> tocEntries, string dataPath) { var cueFile = new CueFileEntry() { FileName = dataPath, Tracks = new List <CueTrack>(), FileType = "BINARY" }; var audioLeadin = new IndexPosition { Seconds = 2 }; foreach (var track in tocEntries) { var position = new IndexPosition { Minutes = track.Minutes, Seconds = track.Seconds, Frames = track.Frames, }; var indexes = new List <CueIndex>(); if (track.TrackType == TrackTypeEnum.Audio) { indexes.Add(new CueIndex() { Number = 0, Position = position - audioLeadin, }); } indexes.Add(new CueIndex() { Number = 1, Position = position, }); var cueTrack = new CueTrack() { DataType = TOCHelper.GetDataType(track.TrackType), Indexes = indexes, Number = track.TrackNo }; cueFile.Tracks.Add(cueTrack); } return(new CueFile(new[] { cueFile })); }
public static byte[] GetTOCData(this CueFile cue, uint isosize) { var tracks = cue.FileEntries.SelectMany(cf => cf.Tracks).ToList(); byte[] tocData = new byte[0xA * (tracks.Count + 3)]; var trackBuffer = new byte[0xA]; var frames = isosize / 2352; var position = TOCHelper.PositionFromFrames(frames); var ctr = 0; trackBuffer[0] = (byte)TOCHelper.GetTrackType(tracks.First().DataType); trackBuffer[1] = 0x00; trackBuffer[2] = 0xA0; trackBuffer[3] = 0x00; trackBuffer[4] = 0x00; trackBuffer[5] = 0x00; trackBuffer[6] = 0x00; trackBuffer[7] = TOCHelper.ToBinaryDecimal(tracks.First().Number); trackBuffer[8] = TOCHelper.ToBinaryDecimal(0x20); trackBuffer[9] = 0x00; Array.Copy(trackBuffer, 0, tocData, ctr, 0xA); ctr += 0xA; trackBuffer[0] = (byte)TOCHelper.GetTrackType(tracks.Last().DataType); trackBuffer[2] = 0xA1; trackBuffer[7] = TOCHelper.ToBinaryDecimal(tracks.Last().Number); trackBuffer[8] = 0x00; Array.Copy(trackBuffer, 0, tocData, ctr, 0xA); ctr += 0xA; trackBuffer[0] = 0x01; trackBuffer[2] = 0xA2; trackBuffer[7] = TOCHelper.ToBinaryDecimal(position.Minutes); trackBuffer[8] = TOCHelper.ToBinaryDecimal(position.Seconds); trackBuffer[9] = TOCHelper.ToBinaryDecimal(position.Frames); Array.Copy(trackBuffer, 0, tocData, ctr, 0xA); ctr += 0xA; foreach (var track in tracks) { trackBuffer[0] = (byte)TOCHelper.GetTrackType(track.DataType); trackBuffer[1] = 0x00; trackBuffer[2] = TOCHelper.ToBinaryDecimal(track.Number); var pos = track.Indexes.First(idx => idx.Number == 1).Position; trackBuffer[3] = TOCHelper.ToBinaryDecimal(pos.Minutes); trackBuffer[4] = TOCHelper.ToBinaryDecimal(pos.Seconds); trackBuffer[5] = TOCHelper.ToBinaryDecimal(pos.Frames); trackBuffer[6] = 0x00; pos = pos + (2 * 75); // add 2 seconds for lead in (75 frames / second) trackBuffer[7] = TOCHelper.ToBinaryDecimal(pos.Minutes); trackBuffer[8] = TOCHelper.ToBinaryDecimal(pos.Seconds); trackBuffer[9] = TOCHelper.ToBinaryDecimal(pos.Frames); Array.Copy(trackBuffer, 0, tocData, ctr, 0xA); ctr += 0xA; } //0x00 1 byte Track type - 0x41 = data track, 0x01 = audio track //0x01 1 byte Always null //0x02 1 byte The track number in "binary decimal" //0x03 3 bytes The absolute track start address in "binary decimal" - first byte is minutes, second is seconds, third is frames //0x06 1 byte Always null //0x07 3 bytes The "relative" track address -same as before, and uses MM: SS: FF format return(tocData); }
static MergedBin MergeBins(string file, CueFile cueFilex, string tempPath) { var mergedBin = new MergedBin(); mergedBin.CueFile = new CueFile(); var cueFilePath = Path.GetDirectoryName(file); long currentFrame = 0; var mergedFilename = Path.GetFileNameWithoutExtension(file) + " - MERGED.bin"; mergedBin.Path = Path.Combine(tempPath, mergedFilename); var mcueFile = new CueFileEntry() { FileName = mergedFilename, FileType = "BINARY", Tracks = new List <CueTrack>() }; mergedBin.CueFile.FileEntries.Add(mcueFile); using (var joinedFile = new FileStream(mergedBin.Path, FileMode.Create)) { foreach (var cueFileEntry in cueFilex.FileEntries) { var binPath = cueFileEntry.FileName; if (Path.GetDirectoryName(binPath) == "" || Path.GetDirectoryName(binPath).StartsWith("..") || Path.GetDirectoryName(binPath).StartsWith(".")) { binPath = Path.Combine(cueFilePath, cueFileEntry.FileName); } using (var srcStream = new FileStream(binPath, FileMode.Open)) { srcStream.CopyTo(joinedFile); foreach (var item in cueFileEntry.Tracks) { var indexes = new List <CueIndex>(); foreach (var idx in item.Indexes) { var newIndex = new CueIndex { Number = idx.Number, Position = idx.Position + TOCHelper.PositionFromFrames(currentFrame) }; indexes.Add(newIndex); } var newTrack = new CueTrack() { DataType = item.DataType, Number = item.Number, Indexes = indexes }; mcueFile.Tracks.Add(newTrack); } var frames = srcStream.Length / 2352; currentFrame += frames; } } } return(mergedBin); }