Exemplo n.º 1
0
        public void TestLoadFromFile()
        {
            foreach (var unpackedDir in TestSettings.Instance.UnpackedDirs)
            {
                var platform = unpackedDir.GetPlatform();
                if (platform.version == GameVersion.RS2012)
                {
                    // NOTE: when unit test is finished, double click the test result to see this message
                    Debug.WriteLine("---------------------------------");
                    Debug.WriteLine("TestLoadFromFile skipped RS1 file: " + unpackedDir);
                    Debug.WriteLine("---------------------------------");
                    continue;
                }

                var sngPaths = Directory.EnumerateFiles(unpackedDir, "*.sng", SearchOption.AllDirectories).ToList();
                foreach (var sngPath in sngPaths)
                {
                    var song = Sng2014File.LoadFromFile(sngPath, platform);
                    if (song == null)
                    {
                        Assert.Fail("LoadFromFile Failed: " + Path.GetFileName(unpackedDir));
                    }

                    if (!song.Arrangements.Arrangements.Any())
                    {
                        Assert.Fail("LoadFromFile Arrangements Failed: " + Path.GetFileName(unpackedDir));
                    }
                }
            }
        }
Exemplo n.º 2
0
        private static void UpdateSng2014(string songDirectory, Platform targetPlatform)
        {
            var xmlFiles  = Directory.EnumerateFiles(Path.Combine(songDirectory, "songs", "arr"), "*_*.xml", SearchOption.AllDirectories).ToList();
            var sngFolder = Path.Combine(songDirectory, "songs", "bin", targetPlatform.GetPathName()[1]); //-3 or more times re-calculation

            foreach (var xmlFile in xmlFiles)
            {
                if (File.Exists(xmlFile))
                {
                    var  xmlName      = Path.GetFileNameWithoutExtension(xmlFile);
                    bool noShowlights = true;

                    //Update Showlights
                    if (xmlName.ToLower().Contains("_showlights"))
                    {
                        updateShl(xmlFile);
                    }
                    else
                    {
                        var sngFile = Path.Combine(sngFolder, xmlName + ".sng");
                        var arrType = ArrangementType.Guitar;
                        if (Path.GetFileName(xmlFile).ToLower().Contains("vocal"))
                        {
                            arrType = ArrangementType.Vocal;
                        }

                        // Handle custom fonts
                        string fontSng = null;
                        if (arrType == ArrangementType.Vocal)
                        {
                            var vocSng = Sng2014File.LoadFromFile(sngFile, TryGetPlatformByEndName(songDirectory));
                            if (vocSng.IsCustomFont())
                            {
                                vocSng.WriteChartData((fontSng = Path.GetTempFileName()), new Platform(GamePlatform.Pc, GameVersion.None));
                            }
                        }

                        using (var fs = new FileStream(sngFile, FileMode.Create))
                        {
                            var sng = Sng2014File.ConvertXML(xmlFile, arrType, fontSng);
                            sng.WriteSng(fs, targetPlatform);
                        }

                        noShowlights &= !xmlFiles.Any(x => Path.GetFileName(x).Contains(xmlName.Split('_')[0].ToLower() + "_showlights"));
                        //Create Showlights
                        if (noShowlights && arrType != ArrangementType.Vocal)
                        {
                            var shlName = Path.Combine(Path.GetDirectoryName(xmlFile), xmlName.Split('_')[0] + "_showlights.xml");
                            var shl     = new RocksmithToolkitLib.DLCPackage.Showlight.Showlights();
                            if (shl.PopShList(shl.FixShowlights(shl.Genegate(xmlFile).ShowlightList)))
                            {
                                shl.Count = shl.ShowlightList.Count;
                                using (var fs = new FileStream(shlName, FileMode.Create))
                                    shl.Serialize(fs);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 3
0
        internal ArrangementData ExtractArrangementData(Attributes2014 attr)
        {
            string sngFilePath = $"songs/bin/generic/{attr.SongXml.Substring(20)}.sng";
            var    entry       = _archive.TOC.Where(x => x.Name.Equals(sngFilePath)).FirstOrDefault();

            if (entry == null)
            {
                throw new Exception($"Could not find arrangement sng {_filePath}/{sngFilePath}");
            }

            ArrangementData data = null;

            _archive.InflateEntry(entry);
            entry.Data.Position = 0;

            var sng = Sng2014File.ReadSng(entry.Data, new RocksmithToolkitLib.Platform(RocksmithToolkitLib.GamePlatform.Pc, RocksmithToolkitLib.GameVersion.RS2014));

            if (sng == null)
            {
                throw new Exception($"Could not read sng {_filePath}{sngFilePath}");
            }

            data = new ArrangementData(sng);

            entry.Dispose();

            return(data);
        }
        public static GlyphDefinitions LoadFromSng(Sng2014File sng)
        {
            var glyphs = new List <GlyphDefinition>(sng.SymbolsDefinition.Count);

            foreach (var glyph in sng.SymbolsDefinition.SymbolDefinitions)
            {
                glyphs.Add(new GlyphDefinition()
                {
                    Symbol = glyph.Text.ToNullTerminatedUTF8(),

                    InnerXMin = glyph.Rect_Inner.xMin,
                    InnerXMax = glyph.Rect_Inner.xMax,
                    InnerYMin = glyph.Rect_Inner.yMin,
                    InnerYMax = glyph.Rect_Inner.yMax,

                    OuterXMin = glyph.Rect_Outter.xMin,
                    OuterXMax = glyph.Rect_Outter.xMax,
                    OuterYMin = glyph.Rect_Outter.yMin,
                    OuterYMax = glyph.Rect_Outter.yMax
                });
            }

            return(new GlyphDefinitions
            {
                TextureHeight = sng.SymbolsTexture.SymbolsTextures[0].Height,
                TextureWidth = sng.SymbolsTexture.SymbolsTextures[0].Width,
                Glyphs = glyphs
            });
        }
Exemplo n.º 5
0
        public TrackDetail GetTrackDetail(string songKey, string arrangmentName)
        {
            var sngEntry  = _psarc.Entries.FirstOrDefault(x => x.Name == @"songs/bin/generic/" + songKey + "_" + arrangmentName + ".sng");
            var jsonEntry = _psarc.Entries.FirstOrDefault(x => x.Name.StartsWith(@"manifests/songs") && x.Name.EndsWith("/" + songKey + "_" + arrangmentName + ".json"));

            if (sngEntry == null || jsonEntry == null)
            {
                return(null);
            }

            Attributes2014 att;

            using (var wrappedStream = new NonClosingStreamWrapper(jsonEntry.Data))
            {
                using (var reader = new StreamReader(wrappedStream))
                {
                    var manifest = JsonConvert.DeserializeObject <Manifest2014 <Attributes2014> >(reader.ReadToEnd());
                    att = manifest.Entries.ToArray()[0].Value.ToArray()[0].Value;
                }
            }

            Sng2014File sngFile;

            using (var wrappedStream = new NonClosingStreamWrapper(sngEntry.Data))
            {
                var platform = _archiveFile.GetPlatform();
                sngFile = Sng2014File.ReadSng(wrappedStream, platform);
            }
            var sngObject = new Song2014(sngFile, att);

            return(new TrackDetail()
            {
                RockSmithSong = sngObject
            });
        }
        private void convertSngXmlButton_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(ConverterSngXmlFile))
            {
                MessageBox.Show(String.Format("File not found: {0}: ", ConverterSngXmlFile), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Error);
                sngXmlTB.Focus();
                return;
            }

            if (sng2xmlRadio.Checked)
            {
                if (String.IsNullOrEmpty(ConverterManifestFile))
                {
                    MessageBox.Show("No manifest file was entered. The song xml file will be generated without song informations like song title, album, artist, tone names, etc.", MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                Attributes2014 att = null;
                if (ConverterArrangementType != ArrangementType.Vocal && !String.IsNullOrEmpty(ConverterManifestFile))
                {
                    att = Manifest2014 <Attributes2014> .LoadFromFile(ConverterManifestFile).Entries.ToArray()[0].Value.ToArray()[0].Value;
                }

                var sng = Sng2014File.LoadFromFile(ConverterSngXmlFile, ConverterPlatform);

                var outputFile = Path.Combine(Path.GetDirectoryName(ConverterSngXmlFile), String.Format("{0}.xml", Path.GetFileNameWithoutExtension(ConverterSngXmlFile)));
                using (FileStream outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite))
                {
                    dynamic xml = null;

                    if (ConverterArrangementType == ArrangementType.Vocal)
                    {
                        xml = new Vocals(sng);
                    }
                    else
                    {
                        xml = new Song2014(sng, att ?? null);
                    }

                    xml.Serialize(outputStream);

                    MessageBox.Show(String.Format("XML file was generated! {0}It was saved on same location of sng file specified.", Environment.NewLine), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else if (xml2sngRadio.Checked)
            {
                var outputFile = Path.Combine(Path.GetDirectoryName(ConverterSngXmlFile), String.Format("{0}.sng", Path.GetFileNameWithoutExtension(ConverterSngXmlFile)));

                using (FileStream outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite)) {
                    Sng2014File sng = Sng2014File.ConvertXML(ConverterSngXmlFile, ConverterArrangementType);
                    sng.WriteSng(outputStream, ConverterPlatform);
                }

                MessageBox.Show(String.Format("SNG file was generated! {0}It was saved on same location of xml file specified.", Environment.NewLine), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Exemplo n.º 7
0
        private void packUnpackButton_Click(object sender, EventArgs e)
        {
            IList <string> sourceFileNames;

            using (var ofd = new OpenFileDialog()) {
                ofd.Multiselect = true;
                if (ofd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                sourceFileNames = ofd.FileNames;
            }

            StringBuilder errorsFound = new StringBuilder();
            var           message     = (unpackRadio.Checked) ? "decrypted" : "encrypted";

            foreach (string sourceFileName in sourceFileNames)
            {
                Application.DoEvents();

                try {
                    var outputFile = Path.Combine(Path.GetDirectoryName(sourceFileName), String.Format("{0}_{1}.sng", Path.GetFileNameWithoutExtension(sourceFileName), message));

                    // Pack/Unpack SNG
                    using (FileStream inputStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read))
                        using (FileStream outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite)) {
                            if (packRadio.Checked)
                            {
                                Sng2014File.PackSng(inputStream, outputStream, PackerPlatform);
                            }
                            else if (unpackRadio.Checked)
                            {
                                Sng2014File.UnpackSng(inputStream, outputStream, PackerPlatform);
                            }
                        }
                } catch (FileNotFoundException ex) {
                    errorsFound.AppendLine(ex.Message);
                } catch (DirectoryNotFoundException ex) {
                    errorsFound.AppendLine(ex.Message);
                } catch (Exception ex) {
                    errorsFound.AppendLine(ex.Message);
                }
            }

            if (errorsFound.Length <= 0)
            {
                MessageBox.Show(String.Format("File(s) was {0}.", message), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show(String.Format("File(s) was {0} with errors. See below: {0}{1}", errorsFound.ToString(), Environment.NewLine, errorsFound.ToString()), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
Exemplo n.º 8
0
        private static void UpdateSng2014(string songDirectory, Platform platform)
        {
            var xmlFiles  = Directory.GetFiles(Path.Combine(songDirectory, "songs", "arr"), "*_*.xml", SearchOption.AllDirectories);
            var sngFolder = Path.Combine(songDirectory, "songs", "bin", platform.GetPathName()[1]); //-3 or more times re-calculation

            foreach (var xmlFile in xmlFiles)
            {
                if (File.Exists(xmlFile))
                {
                    var  xmlName      = Path.GetFileNameWithoutExtension(xmlFile);
                    bool noShowlights = true;

                    //Update Showlights
                    if (xmlName.ToLower().Contains("_showlights"))
                    {
                        updateShl(xmlFile);
                    }
                    else
                    {
                        var sngFile = Path.Combine(sngFolder, xmlName + ".sng");
                        var arrType = ArrangementType.Guitar;

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

                        using (FileStream fs = new FileStream(sngFile, FileMode.Create)) {
                            Sng2014File sng = Sng2014File.ConvertXML(xmlFile, arrType);
                            sng.WriteSng(fs, platform);
                        }

                        if (xmlFiles.Any(x => Path.GetFileName(x).Contains(xmlName.Split('_')[0].ToLower() + "_showlights")))
                        {
                            noShowlights = false;
                        }
                        //Create Showlights
                        if (noShowlights && arrType != ArrangementType.Vocal)
                        {
                            var shlName = Path.Combine(Path.GetDirectoryName(xmlFile), xmlName.Split('_')[0] + "_showlights.xml");
                            var shl     = new RocksmithToolkitLib.DLCPackage.Showlight.Showlights();
                            if (shl.PopShList(shl.FixShowlights(shl.Genegate(xmlFile).ShowlightList)))
                            {
                                shl.Count = shl.ShowlightList.Count;
                                using (var fs = new FileStream(shlName, FileMode.Create))
                                    shl.Serialize(fs);
                                noShowlights = false;
                            }
                        }
                    }
                }
            }
        }
        public static void PopFontPath(this Sng2014File vox, string dlcname)
        {
            var path = String.Format("assets/ui/lyrics/{0}/lyrics_{0}.dds", dlcname);

            if (vox.Vocals != null)
            {
                if (vox.Vocals.Count > 0 && vox.SymbolsTexture.Count > 0)
                {
                    Sng2014FileWriter.readString(path, vox.SymbolsTexture.SymbolsTextures[0].Font);
                    vox.SymbolsTexture.SymbolsTextures[0].FontpathLength = path.Length;
                }
            }
        }
Exemplo n.º 10
0
 public Vocals(Sng2014File sngData)
 {
     Vocal = new Vocal[sngData.Vocals.Count];
     for (var i = 0; i < sngData.Vocals.Count; i++)
     {
         var v = new Vocal();
         v.Time   = sngData.Vocals.Vocals[i].Time;
         v.Note   = sngData.Vocals.Vocals[i].Note;
         v.Length = sngData.Vocals.Vocals[i].Length;
         v.Lyric  = sngData.Vocals.Vocals[i].Lyric.ToNullTerminatedAscii();
         Vocal[i] = v;
     }
 }
Exemplo n.º 11
0
        /// <summary>
        /// Extract a particular arrangement of a song from the archive
        /// and return the corresponding Song2014 object.
        /// </summary>
        /// <param name="identifier">Identifier of the song to load.</param>
        /// <param name="arrangement">The arrangement to use.</param>
        /// <returns>A Song2014 object containing the arrangement.</returns>
        public Song2014 GetArrangement(string identifier, string arrangement)
        {
            // In order to instantiate a Rocksmith Song2014 object, we need both
            // the binary .sng file and the attributes contained in the corresponding
            // .json manifest.
            Console.WriteLine(" Opening arrangement {1} for song id {0}...", identifier, arrangement);
            Platform platform = new Platform(GamePlatform.Pc, GameVersion.RS2014);
            var      jsonFile = archive.Entries.FirstOrDefault(x => x.Name.StartsWith("manifests/songs") &&
                                                               x.Name.EndsWith("/" + identifier + "_" + arrangement + ".json"));
            var sngFile = archive.Entries.FirstOrDefault(x => x.Name == "songs/bin/generic/" +
                                                         identifier + "_" + arrangement + ".sng");

            if (sngFile == null)
            {
                // this might be a Mac archive, try with Mac path
                sngFile = archive.Entries.FirstOrDefault(x => x.Name == "songs/bin/macos/" +
                                                         identifier + "_" + arrangement + ".sng");
                platform.platform = GamePlatform.Mac;
            }
            if (sngFile == null || jsonFile == null)
            {
                if (sngFile == null)
                {
                    Console.WriteLine("sngFile is null.");
                }
                if (jsonFile == null)
                {
                    Console.WriteLine("jsonFile is null.");
                }
                return(null);
            }

            // read out attributes from .json manifest
            Attributes2014 attr;

            using (var reader = new StreamReader(jsonFile.Data.OpenStream()))
            {
                var manifest = JsonConvert.DeserializeObject <Manifest2014 <Attributes2014> >(
                    reader.ReadToEnd());
                if (manifest == null)
                {
                    return(null);
                }
                attr = manifest.Entries.ToArray()[0].Value.ToArray()[0].Value;
            }

            // get contents of .sng file
            Sng2014File sng = Sng2014File.ReadSng(sngFile.Data.OpenStream(), platform);

            return(new Song2014(sng, attr));
        }
        public static void WriteToSng(Sng2014File sng, string glyphDefinitionsPath)
        {
            GlyphDefinitions glyphDefs;

            using (var reader = new StreamReader(glyphDefinitionsPath))
            {
                glyphDefs = new XmlStreamingDeserializer <GlyphDefinitions>(reader).Deserialize();
            }

            sng.SymbolsTexture.SymbolsTextures[0].Width  = glyphDefs.TextureWidth;
            sng.SymbolsTexture.SymbolsTextures[0].Height = glyphDefs.TextureHeight;

            var symbolDefs = new List <SymbolDefinition>(glyphDefs.Glyphs.Count);

            foreach (var glyph in glyphDefs.Glyphs)
            {
                if (Encoding.UTF8.GetByteCount(glyph.Symbol) > 12)
                {
                    throw new Exception(String.Format("The following symbol does not fit into 12 bytes when encoded in UTF-8: {0}", glyph.Symbol));
                }

                var sDef = new SymbolDefinition
                {
                    Rect_Inner = new Rect
                    {
                        xMax = glyph.InnerXMax,
                        xMin = glyph.InnerXMin,
                        yMax = glyph.InnerYMax,
                        yMin = glyph.InnerYMin
                    },
                    Rect_Outter = new Rect
                    {
                        xMax = glyph.OuterXMax,
                        xMin = glyph.OuterXMin,
                        yMax = glyph.OuterYMax,
                        yMin = glyph.OuterYMin
                    }
                };
                Encoding.UTF8.GetBytes(glyph.Symbol).CopyTo(sDef.Text, 0);

                symbolDefs.Add(sDef);
            }

            sng.SymbolsDefinition = new SymbolDefinitionSection
            {
                Count             = symbolDefs.Count,
                SymbolDefinitions = symbolDefs.ToArray()
            };
        }
Exemplo n.º 13
0
        /// <summary>
        /// Extract a particular arrangement of a song from the archive
        /// and return the corresponding Song2014 object.
        /// </summary>
        /// <param name="identifier">Identifier (short title, aka key) of the song to load.</param>
        /// <param name="arrangement">The arrangement (lead, rythum, bass) to use.</param>
        /// <returns>A Song2014 object containing the arrangement.</returns>
        public Song2014 GetArrangement(string identifier, string arrangement)
        {
            // In order to instantiate a Rocksmith Song2014 object, we need both
            // the binary .sng file and the attributes contained in the corresponding
            // .json manifest.
            Console.WriteLine("GetArrangement called with identifier [{0}], arrangement {{{1}}}", identifier,
                              arrangement);
            var sngFile = archive.Entries.FirstOrDefault(x => x.Name == "songs/bin/generic/" +
                                                         identifier + "_" + arrangement + ".sng");
            var jsonFile = archive.Entries.FirstOrDefault(x => x.Name.StartsWith("manifests/songs") &&
                                                          x.Name.EndsWith("/" + identifier + "_" + arrangement +
                                                                          ".json"));

            if (sngFile == null || jsonFile == null)
            {
                if (sngFile == null)
                {
                    Console.WriteLine("sngFile is null.");
                }
                if (jsonFile == null)
                {
                    Console.WriteLine("jsonFile is null.");
                }
                return(null);
            }

            // read out attributes from .json manifest
            Attributes2014 attr;

            using (var ms = new MemoryStream())
                using (var reader = new StreamReader(ms, new UTF8Encoding(), false, 1024))
                {
                    jsonFile.Data.CopyTo(ms);
                    ms.Position = 0;
                    var manifest = JsonConvert.DeserializeObject <Manifest2014 <Attributes2014> >(
                        reader.ReadToEnd());
                    if (manifest == null)
                    {
                        return(null);
                    }
                    attr = manifest.Entries.ToArray()[0].Value.ToArray()[0].Value;
                }

            // get contents of .sng file
            Sng2014File sng = Sng2014File.ReadSng(sngFile.Data, platform);

            return(new Song2014(sng, attr));
        }
Exemplo n.º 14
0
        public ArrangementData(Sng2014File sng)
        {
            Measures = new List <Measure>();

            if (sng.BPMs.Count > 0)
            {
                Measures.Add(new Measure(sng.BPMs.BPMs[0]));

                for (int i = 0; i < sng.BPMs.BPMs.Length; ++i)
                {
                    var bpm = sng.BPMs.BPMs[i];

                    if (bpm.Measure != Measures.Last().Number)
                    {
                        Measures.Add(new Measure(bpm));
                    }
                }
            }
        }
        private static void UpdateSng2014(string songDirectory, Platform targetPlatform)
        {
            var xmlFiles  = Directory.EnumerateFiles(Path.Combine(songDirectory, "songs", "arr"), "*_*.xml", SearchOption.AllDirectories).ToList();
            var sngFolder = Path.Combine(songDirectory, "songs", "bin", targetPlatform.GetPathName()[1].ToLower()); //-3 or more times re-calculation

            foreach (var xmlFile in xmlFiles)
            {
                if (File.Exists(xmlFile))
                {
                    var xmlName = Path.GetFileNameWithoutExtension(xmlFile);
                    if (xmlName.ToLower().Contains("_showlights"))
                    {
                        continue;
                    }

                    var sngFile = Path.Combine(sngFolder, xmlName + ".sng");
                    var arrType = ArrangementType.Guitar;

                    if (xmlName.ToLower().Contains("vocal"))
                    {
                        arrType = ArrangementType.Vocal;
                    }

                    // TODO: Handle vocals custom font
                    string fontSng = null;
                    if (arrType == ArrangementType.Vocal)
                    {
                        //var vocSng = Sng2014File.LoadFromFile(sngFile, GetPlatform(songDirectory));
                        //if (vocSng.IsCustomFont())
                        //{
                        //    vocSng.WriteChartData((fontSng = Path.GetTempFileName()), new Platform(GamePlatform.Pc, GameVersion.None));
                        //}
                    }

                    using (var fs = new FileStream(sngFile, FileMode.Create))
                    {
                        var sng = Sng2014File.ConvertXML(xmlFile, arrType, fontSng);
                        sng.WriteSng(fs, targetPlatform);
                    }
                }
            }
        }
Exemplo n.º 16
0
        public static void Main(string[] args)
        {
            var xmlfile = args[0];
            var sngfile = args[1];

            using (FileStream fs = new FileStream(sngfile, FileMode.Create)) {
                // parse from XML
                Sng2014File sng = Sng2014File.ConvertSong(xmlfile);

                // write raw SNG data for diffing and inspection
                var raw = new FileStream(sngfile + ".raw", FileMode.Create);
                EndianBitConverter conv = EndianBitConverter.Little;
                EndianBinaryWriter w    = new EndianBinaryWriter(conv, raw);
                sng.Write(w);

                // write fully packed SNG
                Platform platform = new Platform(GamePlatform.Pc, GameVersion.RS2014);
                sng.writeSng(fs, platform);
            }
        }
Exemplo n.º 17
0
        public Vocals(Sng2014File sngData, bool validateLyrics = false)
        {
            Vocal = new Vocal[sngData.Vocals.Count];
            for (var i = 0; i < sngData.Vocals.Count; i++)
            {
                var v = new Vocal();
                v.Time   = sngData.Vocals.Vocals[i].Time;
                v.Note   = sngData.Vocals.Vocals[i].Note;
                v.Length = sngData.Vocals.Vocals[i].Length;
                v.Lyric  = sngData.Vocals.Vocals[i].Lyric.ToNullTerminatedUTF8();

                if (validateLyrics)
                {
                    v.Lyric = v.Lyric.GetValidLyric();
                }

                Vocal[i] = v;
            }
            Count = Vocal.Length;
        }
Exemplo n.º 18
0
        /// <summary>
        /// Loads required DLC info from folder.
        /// </summary>
        /// <returns>The DLCPackageData info.</returns>
        /// <param name="unpackedDir">Unpacked dir.</param>
        /// <param name="targetPlatform">Target platform.</param>
        /// <param name = "sourcePlatform"></param>
        /// <param name="ignoreMultitoneEx">Ignore multitone exceptions</param>
        public static DLCPackageData LoadFromFolder(string unpackedDir, Platform targetPlatform, Platform sourcePlatform = null, bool ignoreMultitoneEx = false)
        {
            var data = new DLCPackageData();

            data.GameVersion   = GameVersion.RS2014;
            data.SignatureType = PackageMagic.CON;
            if (sourcePlatform == null)
            {
                sourcePlatform = unpackedDir.GetPlatform();
            }

            //Arrangements / Tones
            data.Arrangements = new List <Arrangement>();
            data.TonesRS2014  = new List <Tone2014>();

            //Load files
            var jsonFiles = Directory.EnumerateFiles(unpackedDir, "*.json", SearchOption.AllDirectories).ToArray();

            foreach (var json in jsonFiles)
            {
                var attr = Manifest2014 <Attributes2014> .LoadFromFile(json).Entries.ToArray()[0].Value.ToArray()[0].Value;

                var xmlName = attr.SongXml.Split(':')[3];
                var xmlFile = Directory.EnumerateFiles(unpackedDir, xmlName + ".xml", SearchOption.AllDirectories).FirstOrDefault();

                if (attr.Phrases != null)
                {
                    if (data.SongInfo == null)
                    {
                        // Fill Package Data
                        data.Name          = attr.DLCKey;
                        data.Volume        = (attr.SongVolume == 0 ? -12 : attr.SongVolume); //FIXME: too low song volume issue, revert to -6 to fix.
                        data.PreviewVolume = (attr.PreviewVolume ?? data.Volume);

                        // Fill SongInfo
                        data.SongInfo = new SongInfo
                        {
                            SongDisplayName     = attr.SongName,
                            SongDisplayNameSort = attr.SongNameSort,
                            Album        = attr.AlbumName,
                            AlbumSort    = attr.AlbumNameSort,
                            SongYear     = attr.SongYear ?? 0,
                            Artist       = attr.ArtistName,
                            ArtistSort   = attr.ArtistNameSort,
                            AverageTempo = (int)attr.SongAverageTempo
                        };
                    }

                    // Adding Arrangement
                    data.Arrangements.Add(new Arrangement(attr, xmlFile, ignoreMultitoneEx));

                    // make a list of tone names used in arrangements
                    var toneNames = new List <string>();
                    foreach (var arr in data.Arrangements)
                    {
                        if (!String.IsNullOrEmpty(arr.ToneA))
                        {
                            toneNames.Add(arr.ToneA);
                        }
                        if (!String.IsNullOrEmpty(arr.ToneB))
                        {
                            toneNames.Add(arr.ToneB);
                        }
                        if (!String.IsNullOrEmpty(arr.ToneC))
                        {
                            toneNames.Add(arr.ToneC);
                        }
                        if (!String.IsNullOrEmpty(arr.ToneD))
                        {
                            toneNames.Add(arr.ToneD);
                        }
                        if (!String.IsNullOrEmpty(arr.ToneBase))
                        {
                            toneNames.Add(arr.ToneBase);
                        }
                    }

                    // Adding Tones
                    foreach (var jsonTone in attr.Tones)
                    {
                        if (jsonTone == null)
                        {
                            continue;
                        }
                        var key = jsonTone.Key;
                        if (data.TonesRS2014.All(t => t.Key != key))
                        {
                            // fix tones names that do not have the correct alphacase for cross matching
                            if (attr.Tone_Base.ToLower() == jsonTone.Name.ToLower() && attr.Tone_Base != jsonTone.Name)
                            {
                                jsonTone.Name = attr.Tone_Base;
                            }
                            if (attr.Tone_A != null && attr.Tone_A.ToLower() == jsonTone.Name.ToLower() && attr.Tone_A != jsonTone.Name)
                            {
                                jsonTone.Name = attr.Tone_A;
                            }
                            if (attr.Tone_B != null && attr.Tone_B.ToLower() == jsonTone.Name.ToLower() && attr.Tone_B != jsonTone.Name)
                            {
                                jsonTone.Name = attr.Tone_B;
                            }
                            if (attr.Tone_C != null && attr.Tone_C.ToLower() == jsonTone.Name.ToLower() && attr.Tone_C != jsonTone.Name)
                            {
                                jsonTone.Name = attr.Tone_C;
                            }
                            if (attr.Tone_D != null && attr.Tone_D.ToLower() == jsonTone.Name.ToLower() && attr.Tone_D != jsonTone.Name)
                            {
                                jsonTone.Name = attr.Tone_D;
                            }

                            // this is part of multitone exception handling auto convert to single tone arrangment
                            // make data.TonesRS2014 consistent with data.Arragment.Tones (toneNames)
                            if (toneNames.Contains(jsonTone.Name))
                            {
                                data.TonesRS2014.Add(jsonTone);
                            }
                        }
                    }
                }
                else if (xmlFile.ToLower().Contains("_vocals"))
                {
                    var voc = new Arrangement
                    {
                        Name            = attr.JapaneseVocal == true ? ArrangementName.JVocals : ArrangementName.Vocals,
                        ArrangementType = ArrangementType.Vocal,
                        ScrollSpeed     = 20,
                        SongXml         = new SongXML {
                            File = xmlFile
                        },
                        SongFile = new SongFile {
                            File = ""
                        },
                        CustomFont = attr.JapaneseVocal == true
                    };

                    // Get symbols stuff from _vocals.xml
                    var fontSng = Path.Combine(unpackedDir, xmlName + ".sng");
                    var vocSng  = Sng2014FileWriter.ReadVocals(xmlFile);

                    if (vocSng.IsCustomFont())
                    {
                        voc.CustomFont = true;
                        voc.FontSng    = fontSng;
                        vocSng.WriteChartData(fontSng, new Platform(GamePlatform.Pc, GameVersion.None));
                    }

                    voc.Sng2014 = Sng2014File.ConvertXML(xmlFile, ArrangementType.Vocal, voc.FontSng);

                    // Adding Arrangement
                    data.Arrangements.Add(voc);
                }
            }

            //ShowLights XML
            var xmlShowLights = Directory.EnumerateFiles(unpackedDir, "*_showlights.xml", SearchOption.AllDirectories).FirstOrDefault();

            if (!String.IsNullOrEmpty(xmlShowLights))
            {
                var shl = new Arrangement
                {
                    ArrangementType = ArrangementType.ShowLight,
                    Name            = ArrangementName.ShowLights,
                    SongXml         = new SongXML {
                        File = xmlShowLights
                    },
                    SongFile = new SongFile {
                        File = ""
                    }
                };

                // Adding ShowLights
                data.Arrangements.Add(shl);
                data.Showlights = true;
            }

            //Get DDS Files
            var ddsFiles = Directory.EnumerateFiles(unpackedDir, "album_*.dds", SearchOption.AllDirectories).ToArray();

            if (ddsFiles.Any())
            {
                var ddsFilesC = new List <DDSConvertedFile>();
                foreach (var file in ddsFiles)
                {
                    switch (Path.GetFileNameWithoutExtension(file).Split('_')[2])
                    {
                    case "256":
                        data.AlbumArtPath = file;
                        ddsFilesC.Add(new DDSConvertedFile()
                        {
                            sizeX = 256, sizeY = 256, sourceFile = file, destinationFile = file.CopyToTempFile(".dds")
                        });
                        break;

                    case "128":
                        ddsFilesC.Add(new DDSConvertedFile()
                        {
                            sizeX = 128, sizeY = 128, sourceFile = file, destinationFile = file.CopyToTempFile(".dds")
                        });
                        break;

                    case "64":
                        ddsFilesC.Add(new DDSConvertedFile()
                        {
                            sizeX = 64, sizeY = 64, sourceFile = file, destinationFile = file.CopyToTempFile(".dds")
                        });
                        break;
                    }
                }
                data.ArtFiles = ddsFilesC;
            }

            // Lyric Art
            var lyricArt = Directory.EnumerateFiles(unpackedDir, "lyrics_*.dds", SearchOption.AllDirectories).ToArray();

            if (lyricArt.Any())
            {
                data.LyricArtPath = lyricArt.FirstOrDefault();
            }

            //Get other files
            //Audio files
            var targetAudioFiles = new List <string>();
            var sourceAudioFiles = Directory.EnumerateFiles(unpackedDir, "*.wem", SearchOption.AllDirectories).ToArray();

            foreach (var file in sourceAudioFiles)
            {
                var newFile = Path.Combine(Path.GetDirectoryName(file), String.Format("{0}_fixed{1}", Path.GetFileNameWithoutExtension(file), Path.GetExtension(file)));
                if (targetPlatform.IsConsole != (sourcePlatform = file.GetAudioPlatform()).IsConsole)
                {
                    OggFile.ConvertAudioPlatform(file, newFile);
                    targetAudioFiles.Add(newFile);
                }
                else
                {
                    targetAudioFiles.Add(file);
                }
            }

            if (!targetAudioFiles.Any())
            {
                throw new InvalidDataException("Audio files not found.");
            }

            string audioPath = null, audioPreviewPath = null;
            var    a = new FileInfo(targetAudioFiles[0]);

            if (targetAudioFiles.Count == 2)
            {
                var b = new FileInfo(targetAudioFiles[1]);

                if (a.Length > b.Length)
                {
                    audioPath        = a.FullName;
                    audioPreviewPath = b.FullName;
                }
                else
                {
                    audioPath        = b.FullName;
                    audioPreviewPath = a.FullName;
                }
            }
            else
            {
                audioPath = a.FullName;
            }

            data.OggPath = audioPath;

            //Make Audio preview with expected name when rebuild
            if (!String.IsNullOrEmpty(audioPreviewPath))
            {
                var newPreviewFileName = Path.Combine(Path.GetDirectoryName(audioPath), String.Format("{0}_preview{1}", Path.GetFileNameWithoutExtension(audioPath), Path.GetExtension(audioPath)));
                File.Move(audioPreviewPath, newPreviewFileName);
                data.OggPreviewPath = newPreviewFileName;
            }

            //AppID
            var appidFile = Directory.EnumerateFiles(unpackedDir, "*.appid", SearchOption.AllDirectories).FirstOrDefault();

            if (appidFile != null)
            {
                data.AppId = File.ReadAllText(appidFile);
            }

            // Package Info
            var versionFile = Directory.EnumerateFiles(unpackedDir, "toolkit.version", SearchOption.AllDirectories).FirstOrDefault();

            if (versionFile != null)
            {
                var tkInfo = GeneralExtensions.ReadToolkitInfo(versionFile);
                data.PackageVersion = tkInfo.PackageVersion;
                data.PackageComment = tkInfo.PackageComment;
            }
            else
            {
                data.PackageVersion = "1";
                data.PackageComment = "";
            }

            return(data);
        }
        /// <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);
        }
Exemplo n.º 20
0
        static int Main(string[] args)
        {
            var arguments = DefaultArguments();
            var options   = GetOptions(arguments);

            try {
                options.Parse(args);

                if (arguments.ShowHelp)
                {
                    options.WriteOptionDescriptions(Console.Out);
                    return(0);
                }

                if (!arguments.Pack && !arguments.Unpack && !arguments.Sng2Xml && !arguments.Xml2Sng)
                {
                    ShowHelpfulError("Must especify a primary command as 'pack', 'unpack', 'sng2xml' or 'xml2sng'.");
                    return(1);
                }

                if (arguments.Input == null && arguments.Input.Length <= 0)
                {
                    ShowHelpfulError("Must specify at least one input file.");
                    return(1);
                }

                if (arguments.Sng2Xml && arguments.Manifest == null && arguments.Manifest.Length <= 0)
                {
                    Console.WriteLine("No manifest file was entered. The song xml file will be generated without song informations like song title, album, artist, tone names, etc.");
                }

                var srcFiles = new List <string>();
                foreach (var name in arguments.Input)
                {
                    if (name.IsDirectory())
                    {
                        srcFiles.AddRange(Directory.EnumerateFiles(Path.GetFullPath(name), "*.sng", SearchOption.AllDirectories));
                    }

                    if (File.Exists(name))
                    {
                        srcFiles.Add(name);
                    }
                }

                var errorCount = 0;
                var indexCount = 0;
                foreach (string inputFile in srcFiles)
                {
                    if (!File.Exists(inputFile))
                    {
                        Console.WriteLine(String.Format("File '{0}' doesn't exists.", inputFile));
                        continue;
                    }

                    if (arguments.Unpack || arguments.Sng2Xml)
                    {
                        if (Path.GetExtension(inputFile) != ".sng")
                        {
                            Console.WriteLine(String.Format("File '{0}' is not support. \nOnly *.sng are supported on this command.", inputFile));
                            continue;
                        }
                    }

                    if (arguments.Pack || arguments.Unpack)
                    {
                        var outputFile = Path.Combine(Path.GetDirectoryName(inputFile), String.Format("{0}_{1}.sng", Path.GetFileNameWithoutExtension(inputFile), (arguments.Unpack) ? "decrypted" : "encrypted"));

                        using (FileStream inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
                            using (FileStream outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite)) {
                                if (arguments.Pack)
                                {
                                    Sng2014File.PackSng(inputStream, outputStream, new Platform(arguments.Platform, GameVersion.RS2014));
                                }
                                else if (arguments.Unpack)
                                {
                                    Sng2014File.UnpackSng(inputStream, outputStream, new Platform(arguments.Platform, GameVersion.RS2014));
                                }
                            }
                    }
                    else if (arguments.Sng2Xml)
                    {
                        Attributes2014 att = null;
                        if (arguments.ArrangementType != ArrangementType.Vocal && arguments.Manifest != null && arguments.Manifest.Length > indexCount)
                        {
                            att = Manifest2014 <Attributes2014> .LoadFromFile(arguments.Manifest[indexCount]).Entries.ToArray()[0].Value.ToArray()[0].Value;
                        }

                        var sng = Sng2014File.LoadFromFile(inputFile, new Platform(arguments.Platform, GameVersion.RS2014));

                        var outputFile = Path.Combine(Path.GetDirectoryName(inputFile), String.Format("{0}.xml", Path.GetFileNameWithoutExtension(inputFile)));
                        using (FileStream outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite))
                        {
                            dynamic xml = null;

                            if (arguments.ArrangementType == ArrangementType.Vocal)
                            {
                                xml = new Vocals(sng);
                            }
                            else
                            {
                                xml = new Song2014(sng, att ?? null);
                            }

                            xml.Serialize(outputStream);
                        }
                    }
                    else if (arguments.Xml2Sng)
                    {
                        var outputFile = Path.Combine(Path.GetDirectoryName(inputFile), String.Format("{0}.sng", Path.GetFileNameWithoutExtension(inputFile)));

                        using (FileStream outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite)) {
                            Sng2014File sng = Sng2014File.ConvertXML(inputFile, arguments.ArrangementType);
                            sng.WriteSng(outputStream, new Platform(arguments.Platform, GameVersion.RS2014));
                        }
                    }
                }

                if (errorCount == 0)
                {
                    Console.WriteLine("Process successfully completed!");
                }
                else if (errorCount > 0 && errorCount < srcFiles.Count)
                {
                    Console.WriteLine("Process completed with errors!");
                }
                else
                {
                    Console.WriteLine("An error occurred!");
                }
            } catch (OptionException ex) {
                ShowHelpfulError(ex.Message);
                return(1);
            }

            return(0);
        }
Exemplo n.º 21
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="extractSongXml">If set to <c>true</c> extract song xml from sng.</param>
        /// <param name="overwriteSongXml">If set to <c>true</c> overwrite existing song xml with produced.</param>
        /// <param name="predefinedPlatform">Predefined source platform.</param>
        public static string Unpack(string sourceFileName, string savePath, bool decodeAudio = false, bool extractSongXml = false, bool overwriteSongXml = true, 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);
            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 :(");
            }

            if (platform.platform == GamePlatform.PS3)
            {
                fnameWithoutExt = fnameWithoutExt.Substring(0, fnameWithoutExt.LastIndexOf("."));
            }

            // DECODE AUDIO
            if (decodeAudio)
            {
                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());
                }
            }

            // EXTRACT XML FROM SNG
            if (extractSongXml && platform.version == GameVersion.RS2014)
            {
                var sngFiles = Directory.EnumerateFiles(unpackedDir, "*.sng", SearchOption.AllDirectories);

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

                    if (File.Exists(xmlOutput) && !overwriteSongXml)
                    {
                        continue;
                    }

                    var arrType = ArrangementType.Guitar;
                    if (Path.GetFileName(xmlOutput).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 (jsonFiles.Any() && !String.IsNullOrEmpty(jsonFiles))
                        {
                            att = Manifest2014 <Attributes2014> .LoadFromFile(jsonFiles).Entries.ToArray()[0].Value.ToArray()[0].Value;
                        }
                    }

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

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

                        xmlContent.Serialize(outputStream);
                    }
                }
            }

            return(unpackedDir);
        }