コード例 #1
0
        /// <summary>
        /// Fixes missing and updates showlights to current standards
        /// </summary>
        private static void UpdateShowlights(string songDirectory, Platform targetPlatform)
        {
            bool hasShowlights = true;
            // TODO: provide some pb feedback for long process
            var info              = DLCPackageData.LoadFromFolder(songDirectory, targetPlatform);
            var showlightsArr     = info.Arrangements.Where(x => x.ArrangementType == ArrangementType.ShowLight).FirstOrDefault();
            var showlightFilePath = showlightsArr.SongXml.File;

            if (String.IsNullOrEmpty(showlightFilePath))
            {
                var xmlFilePath = info.Arrangements[0].SongXml.File;
                var xmlName     = Path.GetFileNameWithoutExtension(xmlFilePath);
                showlightFilePath = Path.Combine(Path.GetDirectoryName(xmlFilePath), xmlName.Split('_')[0] + "_showlights.xml");
                hasShowlights     = false;
            }

            // Generate Showlights
            var showlight = new Showlights();

            showlight.CreateShowlights(info);
            // need at least two showlight elements to be valid
            if (showlight.ShowlightList.Count > 1)
            {
                var showlightStream = new MemoryStream();
                showlight.Serialize(showlightStream);

                using (FileStream file = new FileStream(showlightFilePath, FileMode.Create, FileAccess.Write))
                    showlightStream.WriteTo(file);

                // write xml comments
                Song2014.WriteXmlComments(showlightFilePath);
            }
            else
            {
                // insufficient showlight changes may crash game
                throw new InvalidOperationException("Detected insufficient showlight changes: " + showlight.ShowlightList.Count);
            }

            if (!hasShowlights)
            {
                UpdateAggegrateGraph(songDirectory, targetPlatform, info);
            }
        }
コード例 #2
0
        // TODO: apply before generate, like metronome arrangements does
        // only for RS2014
        public static bool ApplyBassFix(Arrangement arr)
        {
            if (arr.TuningPitch.Equals(220.0))
            {
                // MessageBox.Show("This song is already at 220Hz pitch (bass fixed applied already?)", MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return(false);
            }
            var      songFile = arr.SongXml.File;
            var      comments = Song2014.ReadXmlComments(songFile);
            Song2014 songXml  = Song2014.LoadFromFile(songFile);

            // Force 220Hz
            arr.TuningPitch    = 220.0;
            songXml.CentOffset = "-1200.0";
            // Octave up for each string
            Int16[] strings = arr.TuningStrings.ToArray();
            for (int s = 0; s < strings.Length; s++)
            {
                if (strings[s] < 0)
                {
                    strings[s] += 12;
                }
            }

            //Detect tuning
            var tuning = TuningDefinitionRepository.Instance.Detect(new TuningStrings(strings), GameVersion.RS2014, true);

            arr.Tuning        = tuning.UIName = tuning.Name = String.Format("{0} Fixed", tuning.Name);// bastartd bass hack, huh?
            arr.TuningStrings = songXml.Tuning = tuning.Tuning;
            TuningDefinitionRepository.Instance.Save(true);

            File.Delete(songFile);
            using (var stream = File.OpenWrite(songFile))
            {
                songXml.Serialize(stream, true);
            }
            Song2014.WriteXmlComments(songFile, comments, false);

            return(true);
        }
コード例 #3
0
        private int ApplyPackageDD(string srcPath, int phraseLen, bool removeSus, string rampPath, string cfgPath, out string consoleOutput, bool overWrite = false, bool keepLog = false)
        {
            int            result = 0; // Ends normally with no error
            DLCPackageData packageData;

            consoleOutput = String.Empty;

            try
            {
                using (var psarcOld = new PsarcPackager())
                    packageData = psarcOld.ReadPackage(srcPath);
            }
            catch (Exception ex)
            {
                consoleOutput = "Error Reading : " + srcPath + Environment.NewLine + ex.Message;
                return(-1); // Read Error
            }

            // Update arrangement song info
            foreach (Arrangement arr in packageData.Arrangements)
            {
                if (chkGenArrIds.Checked)
                {
                    // generate new AggregateGraph
                    arr.SongFile = new RocksmithToolkitLib.DLCPackage.AggregateGraph.SongFile()
                    {
                        File = ""
                    };

                    // generate new Arrangement IDs
                    arr.Id       = IdGenerator.Guid();
                    arr.MasterId = RandomGenerator.NextInt();
                }

                // skip vocal and showlight arrangements
                if (arr.ArrangementType == ArrangementType.Vocal || arr.ArrangementType == ArrangementType.ShowLight)
                {
                    continue;
                }

                // validate (QC) RS2014 packageData
                if (packageData.GameVersion == GameVersion.RS2014)
                {
                    // validate existing SongInfo
                    var songXml = Song2014.LoadFromFile(arr.SongXml.File);
                    songXml.ArtistName     = packageData.SongInfo.Artist.GetValidAtaSpaceName();
                    songXml.Title          = packageData.SongInfo.SongDisplayName.GetValidAtaSpaceName();
                    songXml.AlbumName      = packageData.SongInfo.Album.GetValidAtaSpaceName();
                    songXml.ArtistNameSort = packageData.SongInfo.ArtistSort.GetValidSortableName();
                    songXml.SongNameSort   = packageData.SongInfo.SongDisplayNameSort.GetValidSortableName();
                    songXml.AlbumNameSort  = packageData.SongInfo.AlbumSort.GetValidSortableName();
                    songXml.AverageTempo   = Convert.ToSingle(packageData.SongInfo.AverageTempo.ToString().GetValidTempo());
                    songXml.AlbumYear      = packageData.SongInfo.SongYear.ToString().GetValidYear();

                    // update packageData with validated SongInfo
                    packageData.SongInfo.Artist              = songXml.ArtistName;
                    packageData.SongInfo.SongDisplayName     = songXml.Title;
                    packageData.SongInfo.Album               = songXml.AlbumName;
                    packageData.SongInfo.ArtistSort          = songXml.ArtistNameSort;
                    packageData.SongInfo.SongDisplayNameSort = songXml.SongNameSort;
                    packageData.SongInfo.AlbumSort           = songXml.AlbumNameSort;
                    packageData.SongInfo.AverageTempo        = (int)songXml.AverageTempo;
                    packageData.SongInfo.SongYear            = Convert.ToInt32(songXml.AlbumYear);

                    // write updated xml arrangement
                    using (var stream = File.Open(arr.SongXml.File, FileMode.Create))
                        songXml.Serialize(stream, false);

                    // restore arrangment comments
                    Song2014.WriteXmlComments(arr.SongXml.File, arr.XmlComments);
                }

                // apply DD to xml arrangments... 0 = Ends normally with no error
                result = DDCreator.ApplyDD(arr.SongXml.File, phraseLen, removeSus, rampPath, cfgPath, out consoleOutput, true, keepLog);
                if (result == 0)      // Ends normally with no error
                {                     /* DO NOTHING */
                }
                else if (result == 1) // Ends with system error
                {
                    consoleOutput = "DDC System Error: " + Environment.NewLine +
                                    "Arrangment file: " + Path.GetFileName(arr.SongXml.File) + Environment.NewLine +
                                    "CDLC file: " + srcPath;
                    return(result);
                }
                else if (result == 2) // Ends with application error
                {
                    consoleOutput = "DDC Application Error: " + Environment.NewLine +
                                    "Arrangment file: " + Path.GetFileName(arr.SongXml.File) + Environment.NewLine +
                                    "CDLC file: " + srcPath;
                    return(result);
                }

                if (keepLog)
                {
                    var unpackedDir = Path.GetDirectoryName(Path.GetDirectoryName(arr.SongXml.File));
                    var logFiles    = Directory.EnumerateFiles(unpackedDir, "*.log", SearchOption.AllDirectories);
                    var clogDir     = Path.Combine(Path.GetDirectoryName(srcPath), "DDC_Log");
                    var plogDir     = Path.Combine(clogDir, Path.GetFileNameWithoutExtension(srcPath).StripPlatformEndName().Replace("_DD", "").Replace("_NDD", ""));

                    if (!Directory.Exists(clogDir))
                    {
                        Directory.CreateDirectory(clogDir);
                    }

                    IOExtension.DeleteDirectory(plogDir);
                    Directory.CreateDirectory(plogDir);

                    foreach (var logFile in logFiles)
                    {
                        File.Copy(logFile, Path.Combine(plogDir, Path.GetFileName(logFile)));
                    }
                }

                // put arrangment comments in correct order
                Song2014.WriteXmlComments(arr.SongXml.File);
            }

            if (chkGenArrIds.Checked)
            {
                // add comment to ToolkitInfo to identify CDLC
                var arrIdComment = packageData.ToolkitInfo.PackageComment;
                if (String.IsNullOrEmpty(arrIdComment))
                {
                    arrIdComment = TKI_ARRID;
                }
                else if (!arrIdComment.Contains(TKI_ARRID))
                {
                    arrIdComment = arrIdComment + " " + TKI_ARRID;
                }

                packageData.ToolkitInfo.PackageComment = arrIdComment;
            }

            // add comment to ToolkitInfo to identify CDLC
            var remasterComment = packageData.ToolkitInfo.PackageComment;

            if (String.IsNullOrEmpty(remasterComment))
            {
                remasterComment = TKI_REMASTER;
            }
            else if (!remasterComment.Contains(TKI_REMASTER))
            {
                remasterComment = remasterComment + " " + TKI_REMASTER;
            }

            packageData.ToolkitInfo.PackageComment = remasterComment;

            // add default package version if missing
            if (String.IsNullOrEmpty(packageData.ToolkitInfo.PackageVersion))
            {
                packageData.ToolkitInfo.PackageVersion = "1";
            }
            else
            {
                packageData.ToolkitInfo.PackageVersion = packageData.ToolkitInfo.PackageVersion.GetValidVersion();
            }

            // validate packageData (important)
            packageData.Name = packageData.Name.GetValidKey(); // DLC Key

            var destPath = srcPath;

            if (!overWrite)
            {
                destPath = GenerateDdcFilePath(srcPath);
            }

            try
            {
                // regenerates the archive with DDC changes and repairs
                using (var psarcNew = new PsarcPackager(true))
                    psarcNew.WritePackage(destPath, packageData, srcPath);
            }
            catch (Exception ex)
            {
                consoleOutput = "Error Writing: " + srcPath + Environment.NewLine + ex.Message;
                result        = -2; // Write Error
            }

            return(result);
        }
コード例 #4
0
        private void btnFixLowBassTuning_Click(object sender, EventArgs e)
        {
            string[] srcPaths;
            bool     alreadyFixed;
            bool     hasBass;

            // GET PATH
            using (var ofd = new OpenFileDialog())
            {
                ofd.Title       = "Select the CDLC(s) which to apply Bass Tuning Fix";
                ofd.Filter      = "All Files (*.*)|*.*|Rocksmith 2014 PC|*_p.psarc|Rocksmith 2014 Mac|*_m.psarc|Rocksmith 2014 Xbox|*_xbox|Rocksmith 2014 PS3|*.edat";
                ofd.Multiselect = true;
                ofd.FileName    = destPath;

                if (ofd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                srcPaths = ofd.FileNames;
            }

            ToggleUIControls(false);
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            Stopwatch sw = new Stopwatch();

            sw.Restart();

            foreach (var srcPath in srcPaths)
            {
                // UNPACK
                var packagePlatform = srcPath.GetPlatform();
                var tmpPath         = Path.GetTempPath();
                Application.DoEvents();
                var unpackedDir = Packer.Unpack(srcPath, tmpPath, overwriteSongXml: true, predefinedPlatform: packagePlatform);
                destPath = Path.Combine(Path.GetDirectoryName(srcPaths[0]), Path.GetFileName(unpackedDir));

                GlobalExtension.ShowProgress(String.Format("Loading '{0}' ...", Path.GetFileName(srcPath)), 40);

                // Same name xbox issue fix
                //if (packagePlatform.platform == GamePlatform.XBox360)
                //    destPath = String.Format("{0}_{1}", destPath, GamePlatform.XBox360.ToString());

                DirectoryExtension.Move(unpackedDir, destPath, true);
                unpackedDir = destPath;

                // Low Bass Tuning Fix is for Rocksmith 2014 Only
                packagePlatform = new Platform(packagePlatform.platform, GameVersion.RS2014);
                // LOAD DATA
                var info = DLCPackageData.LoadFromFolder(unpackedDir, packagePlatform, packagePlatform);

                switch (packagePlatform.platform)
                {
                case GamePlatform.Pc:
                    info.Pc = true;
                    break;

                case GamePlatform.Mac:
                    info.Mac = true;
                    break;

                case GamePlatform.XBox360:
                    info.XBox360 = true;
                    break;

                case GamePlatform.PS3:
                    info.PS3 = true;
                    break;
                }

                //apply bass fix
                GlobalExtension.ShowProgress(String.Format("Applying Bass Tuning Fix '{0}' ...", Path.GetFileName(srcPath)), 60);
                alreadyFixed = false;
                hasBass      = false;

                for (int i = 0; i < info.Arrangements.Count; i++)
                {
                    Arrangement arr = info.Arrangements[i];
                    if (arr.ArrangementType == ArrangementType.Bass)
                    {
                        hasBass = true;

                        if (arr.TuningStrings.String0 < -4 && arr.TuningPitch == 440.0)
                        {
                            if (!TuningFrequency.ApplyBassFix(arr))
                            {
                                if (chkVerbose.Checked)
                                {
                                    MessageBox.Show(Path.GetFileName(srcPath) + "  " + Environment.NewLine + "bass arrangement is already at 220Hz pitch.  ", "Error ... Applying Low Bass Tuning Fix", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                }

                                alreadyFixed = true;
                            }
                            else
                            {
                                // write xml comments back to fixed bass arrangement
                                Song2014.WriteXmlComments(arr.SongXml.File, arr.XmlComments, customComment: " Low Bass Tuning Fixed ");
                            }
                        }
                        else
                        {
                            if (chkVerbose.Checked)
                            {
                                MessageBox.Show(Path.GetFileName(srcPath) + "  " + Environment.NewLine + "bass arrangement tuning does not need to be fixed.  ", "Error ... Applying Low Bass Tuning Fix", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }

                            alreadyFixed = true;
                        }
                    }
                }

                // don't repackage a song that is already fixed or doesn't have bass
                if (alreadyFixed || !hasBass)
                {
                    if (chkVerbose.Checked && !hasBass)
                    {
                        MessageBox.Show(Path.GetFileName(srcPath) + "  " + Environment.NewLine + "has no bass arrangement.  ", "Error ... Applying Low Bass Tuning Fix", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                    DirectoryExtension.SafeDelete(unpackedDir);
                    continue;
                }

                var ndx     = srcPath.LastIndexOf('_');
                var srcName = srcPath.Substring(0, ndx);
                var srcExt  = srcPath.Substring(ndx, srcPath.Length - ndx);

                if (!chkQuickBassFix.Checked)
                {
                    using (var ofd = new SaveFileDialog())
                    {
                        ofd.Title    = "Select a name for the Low Bass Tuning Fixed file.";
                        ofd.Filter   = "All Files (*.*)|*.*|Rocksmith 2014 PC|*_p.psarc|Rocksmith 2014 Mac|*_m.psarc|Rocksmith 2014 Xbox|*_xbox|Rocksmith 2014 PS3|*.edat";
                        ofd.FileName = String.Format("{0}_{1}_bassfix{2}", info.SongInfo.ArtistSort, info.SongInfo.SongDisplayNameSort, srcExt);

                        if (ofd.ShowDialog() != DialogResult.OK)
                        {
                            return;
                        }

                        destPath = ofd.FileName;
                    }
                }
                else
                {
                    destPath = String.Format("{0}_bassfix{1}", srcName, srcExt);
                }

                if (Path.GetFileName(destPath).Contains(" ") && info.PS3)
                {
                    if (!ConfigRepository.Instance().GetBoolean("creator_ps3pkgnamewarn"))
                    {
                        MessageBox.Show(String.Format("PS3 package name can't support space character due to encryption limitation. {0} Spaces will be automatic removed for your PS3 package name.", Environment.NewLine), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                    else
                    {
                        ConfigRepository.Instance()["creator_ps3pkgnamewarn"] = true.ToString();
                    }
                }

                if (chkDeleteSourceFile.Checked)
                {
                    try
                    {
                        File.Delete(srcPath);
                    }
                    catch (Exception ex)
                    {
                        Console.Write(ex.Message);
                        MessageBox.Show("Access rights required to delete source package, or an error occurred. Package still may exist. Try running as Administrator.");
                    }
                }

                // reuse existing showlights.xml or generates new one if none is found
                info.Showlights = true;
                // Generate Fixed Low Bass Tuning Package
                GlobalExtension.ShowProgress(String.Format("Repackaging '{0}' ...", Path.GetFileName(srcPath)), 80);
                // TODO consider user of regular packer here
                RocksmithToolkitLib.DLCPackage.DLCPackageCreator.Generate(destPath, info, packagePlatform);
#if !DEBUG
                DirectoryExtension.SafeDelete(unpackedDir);
#endif
            }

            sw.Stop();
            GlobalExtension.ShowProgress("Finished applying low bass tuning fix (elapsed time): " + sw.Elapsed, 100);
            PromptComplete(destPath);
            GlobalExtension.Dispose();
            ToggleUIControls(true);
        }
コード例 #5
0
        /// <summary>
        /// Fill Arrangement 2014 from json and xml.
        /// </summary>
        /// <param name="attr"></param>
        /// <param name="xmlSongFile"></param>
        /// <param name="fixMultiTone">If set to <c>true</c> fix low bass tuning </param>
        /// <param name="fixLowBass">If set to <c>true</c> fix multitone exceptions </param>
        public Arrangement(Attributes2014 attr, string xmlSongFile, bool fixMultiTone = false, bool fixLowBass = false)
        {
            var isDirty = false;
            var song    = Song2014.LoadFromFile(xmlSongFile);

            this.SongFile = new SongFile {
                File = ""
            };
            this.SongXml = new SongXML {
                File = xmlSongFile
            };

            //Properties
            Debug.Assert(attr.ArrangementType != null, "Missing information from manifest (ArrangementType)");
            SetArrType(attr.ArrangementType);

            this.ArrangementPropeties = attr.ArrangementProperties;
            this.ArrangementSort      = attr.ArrangementSort;
            this.Name            = (ArrangementName)Enum.Parse(typeof(ArrangementName), attr.ArrangementName);
            this.ScrollSpeed     = Convert.ToInt32(attr.DynamicVisualDensity.Last() * 10);
            this.PluckedType     = (PluckedType)attr.ArrangementProperties.BassPick;
            this.RouteMask       = (RouteMask)attr.ArrangementProperties.RouteMask;
            this.BonusArr        = attr.ArrangementProperties.BonusArr == 1;
            this.Metronome       = (Metronome)attr.ArrangementProperties.Metronome;
            this.ToneMultiplayer = attr.Tone_Multiplayer;
            this.Id       = Guid.Parse(attr.PersistentID);
            this.MasterId = attr.MasterID_RDV;

            // Save xml comments
            this.XmlComments = Song2014.ReadXmlComments(xmlSongFile);

            // Filter out showlights\vocals
            if (ArrangementType != ArrangementType.Guitar && ArrangementType != ArrangementType.Bass)
            {
                return;
            }

            // Tones
            if (attr.Tones == null) // RS2012
            {
                this.ToneBase = attr.Tone_Base;

                if (attr.Tone_A != null || attr.Tone_B != null || attr.Tone_C != null || attr.Tone_D != null)
                {
                    throw new DataException("RS2012 CDLC has extraneous tone data.");
                }
            }
            else // RS2014 or Converter RS2012
            {
                // TODO: optimize using common Arrangment.cs method
                // verify the xml Tone_ exists in tone.manifest.json
                foreach (var jsonTone in attr.Tones)
                {
                    if (jsonTone == null)
                    {
                        continue;
                    }

                    // fix for tone.id (may not be needed/used by game)
                    Int32 toneId = 0;

                    // cleanup the xml arrangement file too
                    if (jsonTone.Name.ToLower() == attr.Tone_Base.ToLower())
                    {
                        this.ToneBase = song.ToneBase = attr.Tone_Base;
                    }
                    if (attr.Tone_A != null && jsonTone.Name.ToLower() == attr.Tone_A.ToLower())
                    {
                        this.ToneA = song.ToneA = attr.Tone_A;
                    }
                    if (attr.Tone_B != null && jsonTone.Name.ToLower() == attr.Tone_B.ToLower())
                    {
                        this.ToneB = song.ToneB = attr.Tone_B;
                        toneId     = 1;
                    }
                    if (attr.Tone_C != null && jsonTone.Name.ToLower() == attr.Tone_C.ToLower())
                    {
                        this.ToneC = song.ToneC = attr.Tone_C;
                        toneId     = 2;
                    }
                    if (attr.Tone_D != null && jsonTone.Name.ToLower() == attr.Tone_D.ToLower())
                    {
                        this.ToneD = song.ToneD = attr.Tone_D;
                        toneId     = 3;
                    }

                    // update EOF tone name and set tone id
                    if (song.Tones != null)
                    {
                        foreach (var xmlTone in song.Tones)
                        {
                            // fix some old toolkit behavior
                            if (xmlTone.Name == "ToneA")
                            {
                                xmlTone.Name = attr.Tone_A;
                            }
                            if (xmlTone.Name == "ToneB")
                            {
                                xmlTone.Name = attr.Tone_B;
                            }
                            if (xmlTone.Name == "ToneC")
                            {
                                xmlTone.Name = attr.Tone_C;
                            }
                            if (xmlTone.Name == "ToneD")
                            {
                                xmlTone.Name = attr.Tone_D;
                            }

                            if (xmlTone.Name.ToLower() == jsonTone.Name.ToLower() || jsonTone.Name.ToLower().EndsWith(xmlTone.Name.ToLower())) //todo: SAMENAME tone fix?
                            {
                                xmlTone.Name = jsonTone.Name;
                                xmlTone.Id   = toneId;
                            }
                        }
                    }


                    // song.Tones => id, name, time to apply tone is missing when song.Tones == null
                    if (song.Tones == null && toneId > 0)
                    {
                        // convert the corrupt multitone to a single tone instead of throwing exception
                        if (fixMultiTone)
                        {
                            song.Tones = new SongTone2014[0]; // => song.Tones.Length == 0
                            isDirty    = true;
                        }
                        else
                        {
                            throw new InvalidDataException("Tone data is missing in CDLC and multitones will not change properly in game." + Environment.NewLine + "Please re-author XML arrangements in EOF and repair multitones name and time changes.");
                        }
                    }
                }

                // convert corrupt multitone to single tone and/or cleanup/repair old toolkit single tone
                // ToneA in single tone ODLC is null/empty
                if ((song.Tones == null || song.Tones.Length == 0) && !String.IsNullOrEmpty(song.ToneA))
                {
                    song.ToneA    = song.ToneB = song.ToneC = String.Empty;
                    song.ToneBase = attr.Tone_Base;
                    this.ToneBase = attr.Tone_Base;
                    this.ToneA    = this.ToneB = this.ToneC = String.Empty;
                    isDirty       = true;
                }

                // set to standard tuning if no tuning exists
                if (song.Tuning == null)
                {
                    song.Tuning = new TuningStrings {
                        String0 = 0, String1 = 0, String2 = 0, String3 = 0, String4 = 0, String5 = 0
                    };
                    isDirty = true;
                }

                this.TuningStrings = song.Tuning;

                // NOTE: any serializing coverts abridged xml to standard xml arrangement
                // so only serialize if necessary to fix errors
                if (isDirty)
                {
                    using (var stream = File.Open(xmlSongFile, FileMode.Create))
                        song.Serialize(stream, true);

                    // write comments back to xml now so they are available for debugging (used for Guitar and Bass)
                    Song2014.WriteXmlComments(xmlSongFile, XmlComments, writeNewVers: false);
                }

                // do a quick check/repair of low bass tuning, only for RS2014 bass arrangements
                if (fixLowBass && song.Version == "7" && this.ArrangementType == ArrangementType.Bass)
                {
                    if (attr.Tuning.String0 < -4 && attr.CentOffset != -1200.0)
                    {
                        if (TuningFrequency.ApplyBassFix(this, fixLowBass))
                        {
                            attr.CentOffset = -1200.0; // Force 220Hz
                            song.Tuning     = Song2014.LoadFromFile(xmlSongFile).Tuning;
                        }
                    }
                }
            }

            // Set Final Tuning
            DetectTuning(song);
            this.CapoFret = attr.CapoFret;
            if (attr.CentOffset != null)
            {
                this.TuningPitch = attr.CentOffset.Cents2Frequency();
            }
        }
コード例 #6
0
        // only for RS2014
        public static bool ApplyBassFix(Arrangement arr, bool saveTuningDefinition = false)
        {
            var debubMe = arr;

            // get the latest comments from the XML
            var xmlComments = Song2014.ReadXmlComments(arr.SongXml.File);
            var isBassFixed = xmlComments.Any(xComment => xComment.ToString().Contains("Low Bass Tuning Fixed")) || arr.TuningPitch.Equals(220.0);

            if (isBassFixed)
            {
                Debug.WriteLine("Low bass tuning may already be fixed: " + arr.SongXml.File);
                // return false;
            }

            // TODO: check guitar compatibility
            // Octave up for each string
            Int16[] strings = arr.TuningStrings.ToArray();
            for (int s = 0; s < strings.Length; s++)
            {
                if (strings[s] < 0)
                {
                    strings[s] += 12;
                }
            }

            // update XML arrangement
            Song2014 songXml = Song2014.LoadFromFile(arr.SongXml.File);

            songXml.CentOffset = "-1200.0"; // Force 220Hz
            songXml.Tuning     = new TuningStrings(strings);

            // bass tuning definition gets auto added/saved to repository
            if (saveTuningDefinition)
            {
                var tuningDef = TuningDefinitionRepository.Instance.Detect(songXml.Tuning, GameVersion.RS2014, false);

                if (!tuningDef.Name.Contains("Fixed"))
                {
                    var tuningUiName = String.Format("{0} Fixed", tuningDef.UIName);
                    var bassTuning   = new TuningDefinition
                    {
                        Custom      = true,
                        GameVersion = GameVersion.RS2014,
                        Name        = tuningUiName.Replace(" ", ""),
                        Tuning      = songXml.Tuning,
                        UIName      = tuningUiName
                    };

                    TuningDefinitionRepository.SaveUnique(bassTuning);
                }
            }

            using (var stream = File.Open(arr.SongXml.File, FileMode.Create))
                songXml.Serialize(stream, true);

            // write xml comments back to fixed bass arrangement
            if (!isBassFixed)
            {
                Song2014.WriteXmlComments(arr.SongXml.File, xmlComments, customComment: "Low Bass Tuning Fixed");
            }

            return(true);
        }
コード例 #7
0
        public Arrangement(Attributes2014 attr, string xmlSongFile)
        {
            var song = Song2014.LoadFromFile(xmlSongFile);

            this.SongFile      = new SongFile();
            this.SongFile.File = "";

            this.SongXml      = new SongXML();
            this.SongXml.File = xmlSongFile;
            //Tuning
            TuningDefinition tuning = null;

            switch ((ArrangementName)attr.ArrangementType)
            {
            case ArrangementName.Lead:
            case ArrangementName.Rhythm:
            case ArrangementName.Combo:
                this.ArrangementType = Sng.ArrangementType.Guitar;
                tuning = TuningDefinitionRepository.Instance().Select(song.Tuning, GameVersion.RS2014);
                break;

            case ArrangementName.Bass:
                this.ArrangementType = Sng.ArrangementType.Bass;
                // TODO: trying to fix bass tuning issue
                tuning = TuningDefinitionRepository.Instance().Select(song.Tuning, GameVersion.RS2014);
                // tuning = TuningDefinitionRepository.Instance().SelectForBass(song.Tuning, GameVersion.RS2014);
                break;

            case ArrangementName.Vocals:
                this.ArrangementType = Sng.ArrangementType.Vocal;
                break;
            }

            if (tuning == null)
            {
                tuning             = new TuningDefinition();
                tuning.UIName      = tuning.Name = tuning.NameFromStrings(song.Tuning, this.ArrangementType == Sng.ArrangementType.Bass);
                tuning.Custom      = true;
                tuning.GameVersion = GameVersion.RS2014;
                tuning.Tuning      = song.Tuning;
                TuningDefinitionRepository.Instance().Add(tuning, true);
            }

            this.Tuning        = tuning.UIName;
            this.TuningStrings = tuning.Tuning;
            this.CapoFret      = attr.CapoFret;
            if (attr.CentOffset != null)
            {
                this.TuningPitch = attr.CentOffset.Cents2Frequency();
            }
            //Properties
            this.ArrangementSort = attr.ArrangementSort;
            this.Name            = (ArrangementName)Enum.Parse(typeof(ArrangementName), attr.ArrangementName);
            this.ScrollSpeed     = Convert.ToInt32(attr.DynamicVisualDensity.Last() * 10);
            this.PluckedType     = (PluckedType)attr.ArrangementProperties.BassPick;
            this.RouteMask       = (RouteMask)attr.ArrangementProperties.RouteMask;
            this.BonusArr        = attr.ArrangementProperties.BonusArr == 1;
            this.Metronome       = (Metronome)attr.ArrangementProperties.Metronome;
            this.ToneMultiplayer = attr.Tone_Multiplayer;
            this.Id       = Guid.Parse(attr.PersistentID);
            this.MasterId = attr.MasterID_RDV;
            // save xml comments
            this.XmlComments = Song2014.ReadXmlComments(xmlSongFile);
            //Tones
            if (attr.Tones == null) // RS2012
            {
                this.ToneBase = attr.Tone_Base;

                if (attr.Tone_A != null || attr.Tone_B != null || attr.Tone_C != null || attr.Tone_D != null)
                {
                    throw new DataException("RS2012 CDLC has extraneous tone data.");
                }
            }
            else // RS2014 or Converter RS2012
            {
                // TODO: optimize using common Arrangment.cs method
                // verify the xml Tone_ exists in tone.manifest.json
                foreach (var jsonTone in attr.Tones)
                {
                    if (jsonTone == null)
                    {
                        continue;
                    }

                    // fix for tone.id (may not be needed/used by game)
                    Int32 toneId = 0;

                    // cleanup the xml arrangement file too
                    if (jsonTone.Name.ToLower() == attr.Tone_Base.ToLower())
                    {
                        this.ToneBase = song.ToneBase = attr.Tone_Base;
                    }
                    if (attr.Tone_A != null && jsonTone.Name.ToLower() == attr.Tone_A.ToLower())
                    {
                        this.ToneA = song.ToneA = attr.Tone_A;
                    }
                    if (attr.Tone_B != null && jsonTone.Name.ToLower() == attr.Tone_B.ToLower())
                    {
                        this.ToneB = song.ToneB = attr.Tone_B;
                        toneId     = 1;
                    }
                    if (attr.Tone_C != null && jsonTone.Name.ToLower() == attr.Tone_C.ToLower())
                    {
                        this.ToneC = song.ToneC = attr.Tone_C;
                        toneId     = 2;
                    }
                    if (attr.Tone_D != null && jsonTone.Name.ToLower() == attr.Tone_D.ToLower())
                    {
                        this.ToneD = song.ToneD = attr.Tone_D;
                        toneId     = 3;
                    }

                    // update EOF tone name and set tone id
                    if (song.Tones != null)
                    {
                        foreach (var xmlTone in song.Tones)
                        {
                            // fix some old toolkit behavior
                            if (xmlTone.Name == "ToneA")
                            {
                                xmlTone.Name = attr.Tone_A;
                            }
                            if (xmlTone.Name == "ToneB")
                            {
                                xmlTone.Name = attr.Tone_B;
                            }
                            if (xmlTone.Name == "ToneC")
                            {
                                xmlTone.Name = attr.Tone_C;
                            }
                            if (xmlTone.Name == "ToneD")
                            {
                                xmlTone.Name = attr.Tone_D;
                            }

                            if (xmlTone.Name.ToLower() == jsonTone.Name.ToLower() || jsonTone.Name.ToLower().Contains(xmlTone.Name.ToLower()))
                            {
                                xmlTone.Name = jsonTone.Name;
                                xmlTone.Id   = toneId;
                            }
                        }
                    }

                    if (song.Tones == null && toneId > 0)
                    {
                        throw new InvalidDataException("Custom tones were not set properly in EOF" + Environment.NewLine + "Please reauthor XML arrangement in EOF and fix custom tone consistency.");
                    }
                }

                // write changes to xml arrangement (w/o comments)
                using (var stream = File.Open(xmlSongFile, FileMode.Create))
                    song.Serialize(stream);

                // write comments back to xml now so they are available for debugging
                if (this.ArrangementType == ArrangementType.Guitar || this.ArrangementType == ArrangementType.Bass)
                {
                    Song2014.WriteXmlComments(xmlSongFile, this.XmlComments, false);
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Fill Arrangement 2014 from json and xml.
        /// </summary>
        /// <param name="attr"></param>
        /// <param name="xmlSongFile"></param>
        public Arrangement(Attributes2014 attr, string xmlSongFile)
        {
            var song = Song2014.LoadFromFile(xmlSongFile);

            this.SongFile = new SongFile {
                File = ""
            };
            this.SongXml = new SongXML {
                File = xmlSongFile
            };

            //Properties
            Debug.Assert(attr.ArrangementType != null, "Missing information from manifest (ArrangementType)");
            SetArrType(attr.ArrangementType);

            this.ArrangementPropeties = attr.ArrangementProperties;
            this.ArrangementSort      = attr.ArrangementSort;
            this.Name            = (ArrangementName)Enum.Parse(typeof(ArrangementName), attr.ArrangementName);
            this.ScrollSpeed     = Convert.ToInt32(attr.DynamicVisualDensity.Last() * 10);
            this.PluckedType     = (PluckedType)attr.ArrangementProperties.BassPick;
            this.RouteMask       = (RouteMask)attr.ArrangementProperties.RouteMask;
            this.BonusArr        = attr.ArrangementProperties.BonusArr == 1;
            this.Metronome       = (Metronome)attr.ArrangementProperties.Metronome;
            this.ToneMultiplayer = attr.Tone_Multiplayer;
            this.Id       = Guid.Parse(attr.PersistentID);
            this.MasterId = attr.MasterID_RDV;


            //Filter out showlights\vocals
            if (ArrangementType != ArrangementType.Guitar && ArrangementType != ArrangementType.Bass)
            {
                return;
            }

            //Tuning
            DetectTuning(song);
            this.CapoFret = attr.CapoFret;
            if (attr.CentOffset != null)
            {
                this.TuningPitch = attr.CentOffset.Cents2Frequency();
            }

            // save xml comments
            this.XmlComments = Song2014.ReadXmlComments(xmlSongFile);

            //Tones
            if (attr.Tones == null) // RS2012
            {
                this.ToneBase = attr.Tone_Base;

                if (attr.Tone_A != null || attr.Tone_B != null || attr.Tone_C != null || attr.Tone_D != null)
                {
                    throw new DataException("RS2012 CDLC has extraneous tone data.");
                }
            }
            else // RS2014 or Converter RS2012
            {
                // TODO: optimize using common Arrangment.cs method
                // verify the xml Tone_ exists in tone.manifest.json
                foreach (var jsonTone in attr.Tones)
                {
                    if (jsonTone == null)
                    {
                        continue;
                    }

                    // fix for tone.id (may not be needed/used by game)
                    Int32 toneId = 0;

                    // cleanup the xml arrangement file too
                    if (jsonTone.Name.ToLower() == attr.Tone_Base.ToLower())
                    {
                        this.ToneBase = song.ToneBase = attr.Tone_Base;
                    }
                    if (attr.Tone_A != null && jsonTone.Name.ToLower() == attr.Tone_A.ToLower())
                    {
                        this.ToneA = song.ToneA = attr.Tone_A;
                    }
                    if (attr.Tone_B != null && jsonTone.Name.ToLower() == attr.Tone_B.ToLower())
                    {
                        this.ToneB = song.ToneB = attr.Tone_B;
                        toneId     = 1;
                    }
                    if (attr.Tone_C != null && jsonTone.Name.ToLower() == attr.Tone_C.ToLower())
                    {
                        this.ToneC = song.ToneC = attr.Tone_C;
                        toneId     = 2;
                    }
                    if (attr.Tone_D != null && jsonTone.Name.ToLower() == attr.Tone_D.ToLower())
                    {
                        this.ToneD = song.ToneD = attr.Tone_D;
                        toneId     = 3;
                    }

                    // update EOF tone name and set tone id
                    if (song.Tones != null)
                    {
                        foreach (var xmlTone in song.Tones)
                        {
                            // fix some old toolkit behavior
                            if (xmlTone.Name == "ToneA")
                            {
                                xmlTone.Name = attr.Tone_A;
                            }
                            if (xmlTone.Name == "ToneB")
                            {
                                xmlTone.Name = attr.Tone_B;
                            }
                            if (xmlTone.Name == "ToneC")
                            {
                                xmlTone.Name = attr.Tone_C;
                            }
                            if (xmlTone.Name == "ToneD")
                            {
                                xmlTone.Name = attr.Tone_D;
                            }

                            if (xmlTone.Name.ToLower() == jsonTone.Name.ToLower() || jsonTone.Name.ToLower().EndsWith(xmlTone.Name.ToLower())) //todo: SAMENAME tone fix?
                            {
                                xmlTone.Name = jsonTone.Name;
                                xmlTone.Id   = toneId;
                            }
                        }
                    }

                    if (song.Tones == null && toneId > 0)
                    {
                        throw new InvalidDataException("Custom tones were not set properly in EOF" + Environment.NewLine + "Please re-author XML arrangement in EOF and fix custom tone consistency.");
                    }
                }

                // write changes to xml arrangement (w/o comments)
                using (var stream = File.Open(xmlSongFile, FileMode.Create))
                    song.Serialize(stream, true);

                // write comments back to xml now so they are available for debugging (used for Guitar and Bass)
                Song2014.WriteXmlComments(xmlSongFile, XmlComments, writeNewVers: false);
            }
        }
コード例 #9
0
        /// <summary>
        /// Unpack the specified File, returns unpacked dir.
        /// </summary>
        /// <param name="sourceFileName">Source file path.</param>
        /// <param name="savePath">Save path.</param>
        /// <param name="decodeAudio">If set to <c>true</c> decode audio.</param>
        /// <param name="overwriteSongXml">If set to <c>true</c> overwrite existing song (EOF) xml with SNG data</param>
        /// <param name="predefinedPlatform">Predefined source platform.</param>
        public static string Unpack(string sourceFileName, string savePath, bool decodeAudio = false, bool overwriteSongXml = false, Platform predefinedPlatform = null)
        {
            Platform platform = sourceFileName.GetPlatform();

            if (predefinedPlatform != null && predefinedPlatform.platform != GamePlatform.None && predefinedPlatform.version != GameVersion.None)
            {
                platform = predefinedPlatform;
            }
            var fnameWithoutExt = Path.GetFileNameWithoutExtension(sourceFileName);

            if (platform.platform == GamePlatform.PS3)
            {
                fnameWithoutExt = fnameWithoutExt.Substring(0, fnameWithoutExt.LastIndexOf("."));
            }
            var unpackedDir = Path.Combine(savePath, String.Format("{0}_{1}", fnameWithoutExt, platform.platform));

            if (Directory.Exists(unpackedDir))
            {
                DirectoryExtension.SafeDelete(unpackedDir);
            }

            var useCryptography = platform.version == GameVersion.RS2012; // Cryptography way is used only for PC in Rocksmith 1

            switch (platform.platform)
            {
            case GamePlatform.Pc:
            case GamePlatform.Mac:
                if (platform.version == GameVersion.RS2014)
                {
                    using (var inputStream = File.OpenRead(sourceFileName))
                        ExtractPSARC(sourceFileName, savePath, inputStream, platform);
                }
                else
                {
                    using (var inputFileStream = File.OpenRead(sourceFileName))
                        using (var inputStream = new MemoryStream())
                        {
                            if (useCryptography)
                            {
                                RijndaelEncryptor.DecryptFile(inputFileStream, inputStream, RijndaelEncryptor.DLCKey);
                            }
                            else
                            {
                                inputFileStream.CopyTo(inputStream);
                            }

                            ExtractPSARC(sourceFileName, savePath, inputStream, platform);
                        }
                }
                break;

            case GamePlatform.XBox360:
                UnpackXBox360Package(sourceFileName, savePath, platform);
                break;

            case GamePlatform.PS3:
                UnpackPS3Package(sourceFileName, savePath, platform);
                break;

            case GamePlatform.None:
                throw new InvalidOperationException("Platform not found :(");
            }

            // DECODE AUDIO
            if (decodeAudio)
            {
                GlobalExtension.ShowProgress("Decoding Audio ...", 50);
                var audioFiles = Directory.EnumerateFiles(unpackedDir, "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".ogg") || s.EndsWith(".wem"));
                foreach (var file in audioFiles)
                {
                    var outputAudioFileName = Path.Combine(Path.GetDirectoryName(file), String.Format("{0}_fixed{1}", Path.GetFileNameWithoutExtension(file), ".ogg"));
                    OggFile.Revorb(file, outputAudioFileName, Path.GetDirectoryName(Application.ExecutablePath), Path.GetExtension(file).GetWwiseVersion());
                }

                //GlobalExtension.HideProgress();
            }

            // for debugging
            //overwriteSongXml = false;

            // Extract XML from SNG and check it against the EOF XML (correct bass tuning from older toolkit/EOF xml files)
            if (platform.version == GameVersion.RS2014)
            {
                var    sngFiles = Directory.EnumerateFiles(unpackedDir, "*.sng", SearchOption.AllDirectories).ToList();
                var    step     = Math.Round(1.0 / (sngFiles.Count + 2) * 100, 3);
                double progress = 0;
                GlobalExtension.ShowProgress("Extracting XML from SNG ...");

                foreach (var sngFile in sngFiles)
                {
                    var xmlEofFile = Path.Combine(Path.GetDirectoryName(sngFile), String.Format("{0}.xml", Path.GetFileNameWithoutExtension(sngFile)));
                    xmlEofFile = xmlEofFile.Replace(String.Format("bin{0}{1}", Path.DirectorySeparatorChar, platform.GetPathName()[1].ToLower()), "arr");
                    var xmlSngFile = xmlEofFile.Replace(".xml", ".sng.xml");

                    var arrType = ArrangementType.Guitar;

                    if (Path.GetFileName(xmlSngFile).ToLower().Contains("vocal"))
                    {
                        arrType = ArrangementType.Vocal;
                    }

                    Attributes2014 att = null;
                    if (arrType != ArrangementType.Vocal)
                    {
                        var jsonFiles = Directory.EnumerateFiles(unpackedDir, String.Format("{0}.json", Path.GetFileNameWithoutExtension(sngFile)), SearchOption.AllDirectories).FirstOrDefault();
                        if (!String.IsNullOrEmpty(jsonFiles) && jsonFiles.Any())
                        {
                            att = Manifest2014 <Attributes2014> .LoadFromFile(jsonFiles).Entries.ToArray()[0].Value.ToArray()[0].Value;
                        }
                    }

                    var sngContent = Sng2014File.LoadFromFile(sngFile, platform);
                    using (var outputStream = new FileStream(xmlSngFile, FileMode.Create, FileAccess.ReadWrite))
                    {
                        dynamic xmlContent = null;

                        if (arrType == ArrangementType.Vocal)
                        {
                            xmlContent = new Vocals(sngContent);
                        }
                        else
                        {
                            xmlContent = new Song2014(sngContent, att);
                        }

                        xmlContent.Serialize(outputStream);
                    }

                    // correct old toolkit/EOF xml (tuning) issues ... sync with SNG data
                    if (File.Exists(xmlEofFile) &&
                        !overwriteSongXml && arrType != ArrangementType.Vocal)
                    {
                        var eofSong = Song2014.LoadFromFile(xmlEofFile);
                        var sngSong = Song2014.LoadFromFile(xmlSngFile);
                        if (eofSong.Tuning != sngSong.Tuning)
                        {
                            eofSong.Tuning = sngSong.Tuning;
                            var xmlComments = Song2014.ReadXmlComments(xmlEofFile);

                            using (var stream = File.Open(xmlEofFile, FileMode.Create))
                                eofSong.Serialize(stream, true);

                            Song2014.WriteXmlComments(xmlEofFile, xmlComments, customComment: "Synced with SNG file");
                        }

                        File.Delete(xmlSngFile);
                    }
                    else
                    {
                        if (arrType != ArrangementType.Vocal)
                        {
                            Song2014.WriteXmlComments(xmlSngFile, customComment: "Generated from SNG file");
                        }

                        File.Copy(xmlSngFile, xmlEofFile, true);
                        File.Delete(xmlSngFile);
                    }

                    progress += step;
                    GlobalExtension.UpdateProgress.Value = (int)progress;
                }

                //GlobalExtension.HideProgress();
            }
            return(unpackedDir);
        }
コード例 #10
0
        private static void RemasterSong(string srcFilePath)
        {
            try
            {
                // SNG's needs to be regenerated
                // ArrangmentIDs are stored in multiple place and all need to be updated
                // therefore we are going to unpack, apply repair, and repack
                ShowMessage(" - Extracting CDLC artifacts ...");
                DLCPackageData packageData;

                using (var psarcOld = new PsarcPackager())
                    packageData = psarcOld.ReadPackage(srcFilePath);

                // Update arrangement song info
                foreach (Arrangement arr in packageData.Arrangements)
                {
                    if (!optionPre)
                    {
                        // generate new AggregateGraph
                        arr.SongFile = new RocksmithToolkitLib.DLCPackage.AggregateGraph.SongFile {
                            File = ""
                        };

                        // generate new Arrangement IDs
                        arr.Id       = IdGenerator.Guid();
                        arr.MasterId = RandomGenerator.NextInt();
                    }

                    // skip vocal and showlight arrangements
                    if (arr.ArrangementType == ArrangementType.Vocal || arr.ArrangementType == ArrangementType.ShowLight)
                    {
                        continue;
                    }

                    // validate SongInfo
                    var songXml = Song2014.LoadFromFile(arr.SongXml.File);
                    songXml.AlbumYear      = packageData.SongInfo.SongYear.ToString().GetValidYear();
                    songXml.ArtistName     = packageData.SongInfo.Artist.GetValidAtaSpaceName();
                    songXml.Title          = packageData.SongInfo.SongDisplayName.GetValidAtaSpaceName();
                    songXml.AlbumName      = packageData.SongInfo.Album.GetValidAtaSpaceName();
                    songXml.ArtistNameSort = packageData.SongInfo.ArtistSort.GetValidSortableName();
                    songXml.SongNameSort   = packageData.SongInfo.SongDisplayNameSort.GetValidSortableName();
                    songXml.AlbumNameSort  = packageData.SongInfo.AlbumSort.GetValidSortableName();
                    songXml.AverageTempo   = Convert.ToSingle(packageData.SongInfo.AverageTempo.ToString().GetValidTempo());

                    // write updated xml arrangement
                    using (var stream = File.Open(arr.SongXml.File, FileMode.Create))
                        songXml.Serialize(stream, true);

                    // add comments back to xml arrangement
                    Song2014.WriteXmlComments(arr.SongXml.File, arr.XmlComments);
                }

                if (!optionPre)
                {
                    // add comment to ToolkitInfo to identify CDLC
                    var arrIdComment = packageData.PackageComment;
                    if (String.IsNullOrEmpty(arrIdComment))
                    {
                        arrIdComment = TKI_ARRID;
                    }
                    else if (!arrIdComment.Contains(TKI_ARRID))
                    {
                        arrIdComment = arrIdComment + " " + TKI_ARRID;
                    }

                    packageData.PackageComment = arrIdComment;
                }

                // add comment to ToolkitInfo to identify CDLC
                var remasterComment = packageData.PackageComment;
                if (String.IsNullOrEmpty(remasterComment))
                {
                    remasterComment = TKI_REMASTER;
                }
                else if (!remasterComment.Contains(TKI_REMASTER))
                {
                    remasterComment = remasterComment + " " + TKI_REMASTER;
                }

                packageData.PackageComment = remasterComment;

                // add default package version if missing
                if (String.IsNullOrEmpty(packageData.PackageVersion))
                {
                    packageData.PackageVersion = "1";
                }
                else
                {
                    packageData.PackageVersion = packageData.PackageVersion.GetValidVersion();
                }

                // validate packageData (important)
                packageData.Name = packageData.Name.GetValidKey(); // DLC Key
                ShowMessage(" - Repackaging remastered CDLC ...");

                // regenerates the SNG with the repair and repackages
                using (var psarcNew = new PsarcPackager(true))
                    psarcNew.WritePackage(srcFilePath, packageData);

                ShowMessage(" - Repair was sucessful ...");
            }
            catch (Exception ex)
            {
                ShowMessage(" - Repair failed ... " + SplitString(ex.Message, 55), MessageType.Warning);
                ShowMessage(" - See 'remastered_error.log' file ... ", MessageType.Warning);
                ShowMessage(srcFilePath + ", Corrupt File", MessageType.Error, postfixLine: true);

                // copy (org) to corrupt (cor), delete backup (org), delete original
                var properExt   = Path.GetExtension(srcFilePath);
                var orgFilePath = String.Format(@"{0}{1}{2}", Path.Combine(workDirectory, Path.GetFileNameWithoutExtension(srcFilePath)), orgExt, properExt).Trim();
                if (File.Exists(orgFilePath))
                {
                    var corFilePath = String.Format(@"{0}{1}{2}", Path.Combine(workDirectory, Path.GetFileNameWithoutExtension(srcFilePath)), corExt, properExt).Trim();
                    File.Copy(orgFilePath, corFilePath, true);
                    File.Delete(orgFilePath);
                    File.Delete(srcFilePath);
                }
            }
        }