Пример #1
0
        private void UnpackSongs(IEnumerable <string> sourceFileNames, string destPath, bool decode = false, bool overwrite = false)
        {
            ToggleUIControls(false);
            errorsFound = new StringBuilder();
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            Stopwatch sw = new Stopwatch();

            sw.Restart();

            foreach (string sourceFileName in sourceFileNames)
            {
                Application.DoEvents();
                GlobalExtension.ShowProgress(String.Format("Unpacking '{0}'", Path.GetFileName(sourceFileName)), 10);

                try
                {
                    Platform platform = sourceFileName.GetPlatform();
                    Packer.Unpack(sourceFileName, destPath, decode, overwrite, platform);
                }
                catch (Exception ex)
                {
                    errorsFound.AppendLine(String.Format("Error unpacking file '{0}': {1}", Path.GetFileName(sourceFileName), ex.Message));
                }
            }

            sw.Stop();
            GlobalExtension.ShowProgress("Finished unpacking archive (elapsed time): " + sw.Elapsed, 100);
            PromptComplete(destPath, false, errorsFound.ToString());
            GlobalExtension.Dispose();
            ToggleUIControls(true);
        }
Пример #2
0
        public List <string> ExtractEntryNames()
        {
            var sw = new Stopwatch();

            sw.Restart();
            var    entryNames = new List <string>();
            var    step       = Math.Round(1.0 / (_archive.TOC.Count + 2) * 100, 3);
            double progress   = 0;

            GlobalExtension.ShowProgress("Inflating Entries ...");


            // this iterates through all entries in archive
            foreach (var entry in _archive.TOC)
            {
                // do something interesting with the entry
                entryNames.Add(entry.Name);
                // needed to free memory (prevent crashing)
                if (entry.Data != null)
                {
                    entry.Data.Dispose();
                }

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

            GlobalExtension.UpdateProgress.Value = 100;
            return(entryNames);
        }
        public string PackSong(string srcPath, string destPath)
        {
            ToggleUIControls(false);
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            GlobalExtension.ShowProgress("Packing archive ...", 30);
            Application.DoEvents();
            var errMsg      = String.Empty;
            var archivePath = String.Empty;

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Restart();
                var srcPlatform = srcPath.GetPlatform();
                archivePath = Packer.Pack(srcPath, destPath, srcPlatform, UpdateSng, UpdateManifest);
                sw.Stop();
                GlobalExtension.ShowProgress("Finished packing archive (elapsed time): " + sw.Elapsed, 100);
            }
            catch (Exception ex)
            {
                errMsg = String.Format("{0}\n{1}", ex.Message, ex.InnerException);
            }

            if (!ConfigGlobals.IsUnitTest)
            {
                PromptComplete(destPath, true, errMsg);
            }

            GlobalExtension.Dispose();
            ToggleUIControls(true);

            return(archivePath);
        }
Пример #4
0
        public ManifestHeader2014 <AttributesHeader2014> ExtractHsanManifest()
        {
            var sw = new Stopwatch();

            sw.Restart();
            // every song and song pack contain only one hsan file
            var hsanEntry = _archive.TOC.FirstOrDefault(x => x.Name.StartsWith("manifests/songs") && x.Name.EndsWith(".hsan"));

            if (hsanEntry == null)
            {
                throw new Exception("Could not find valid hsan manifest in archive.");
            }

            var hsanData = new ManifestHeader2014 <AttributesHeader2014>(new Platform(GamePlatform.Pc, GameVersion.RS2014));

            _archive.InflateEntry(hsanEntry);
            var ms = new MemoryStream();

            using (var reader = new StreamReader(ms, new UTF8Encoding(), false, 65536)) //4Kb is default alloc size for windows .. 64Kb is default PSARC alloc
            {
                hsanEntry.Data.Position = 0;
                hsanEntry.Data.CopyTo(ms);
                ms.Position = 0;
                var jsonObj = JObject.Parse(reader.ReadToEnd());
                hsanData = JsonConvert.DeserializeObject <ManifestHeader2014 <AttributesHeader2014> >(jsonObj.ToString());
            }

            sw.Stop();
            GlobalExtension.ShowProgress(String.Format("{0} parsing hsan manifest entry took: {1} (msec)", Path.GetFileName(_filePath), sw.ElapsedMilliseconds));
            return(hsanData);
        }
Пример #5
0
        public string PackSong(string srcPath, string destPath)
        {
            ToggleUIControls(false);
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            GlobalExtension.ShowProgress("Packing archive ...", 30);
            Application.DoEvents();
            var errMsg      = String.Empty;
            var archivePath = String.Empty;

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Restart();
                archivePath = Packer.Pack(srcPath, destPath, updateSng: UpdateSng, updateManifest: UpdateManifest);
                sw.Stop();
                GlobalExtension.ShowProgress("Finished packing archive (elapsed time): " + sw.Elapsed, 100);
            }
            catch (Exception ex)
            {
                errMsg = String.Format("{0}\n{1}", ex.Message, ex.InnerException) + Environment.NewLine + Environment.NewLine +
                         "Confirm GamePlatform and GameVersion are set correctly for desired destination in GeneraConfig";
            }

            if (!GlobalsLib.IsUnitTest)
            {
                PromptComplete(destPath, true, errMsg);
            }

            GlobalExtension.Dispose();
            ToggleUIControls(true);

            return(archivePath);
        }
        private void btnPackSongPack_Click(object sender, EventArgs e)
        {
            string sourcePath;
            string saveFileName;

            using (var fbd = new VistaFolderBrowserDialog())
            {
                fbd.Description = "Select the Song Pack folder";
                fbd.SelectedPath = savePath;

                if (fbd.ShowDialog() != DialogResult.OK)
                    return;

                sourcePath = fbd.SelectedPath;
            }

            saveFileName = Path.GetFileName(sourcePath);

            //using (var sfd = new SaveFileDialog())
            //{
            //    sfd.FileName = Path.GetFileName(sourcePath);

            //    if (sfd.ShowDialog() != DialogResult.OK)
            //        return;

            //    saveFileName = sfd.FileName;
            //}

            GlobalExtension.UpdateProgress = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            GlobalExtension.ShowProgress("Packing archive ...");
            Application.DoEvents();

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Restart();

                var songPackDir = AggregateGraph2014.DoLikeSongPack(sourcePath, txtAppId.Text);
                var destFilePath = Path.Combine(Path.GetDirectoryName(sourcePath), String.Format("{0}_p.psarc", Path.GetFileName(sourcePath)));
                Packer.Pack(songPackDir, destFilePath, fixShowlights: false, predefinedPlatform: new Platform(GamePlatform.Pc, GameVersion.RS2014));

                // clean up now (song pack folder)
                //if (Directory.Exists(songPackDir))
                //    DirectoryExtension.SafeDelete(songPackDir);

                sw.Stop();
                GlobalExtension.ShowProgress("Finished packing archive (elapsed time): " + sw.Elapsed, 100);
                MessageBox.Show("Packing is complete.", MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format("{0}\n{1}\n{2}", "Packing error!", ex.Message, ex.InnerException), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            // prevents possible cross threading
            GlobalExtension.Dispose();
        }
Пример #7
0
        private void btnPack_Click(object sender, EventArgs e)
        {
            var srcPath      = String.Empty;
            var destFileName = String.Empty;

            using (var fbd = new VistaFolderBrowserDialog())
            {
                fbd.SelectedPath = destPath;
                fbd.Description  = "Select CDLC artifacts folder.";

                if (fbd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                srcPath = destPath = fbd.SelectedPath;
            }

            destFileName = RecycleFolderName(srcPath);

            using (var sfd = new SaveFileDialog())
            {
                sfd.Title    = "Select a new CDLC destination file name or use the system generated default.";
                sfd.FileName = destFileName;

                if (sfd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                destFileName = sfd.FileName;
            }

            ToggleUIControls(false);
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            GlobalExtension.ShowProgress("Packing archive ...", 30);
            Application.DoEvents();
            var errMsg = String.Empty;

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Restart();
                var packagePlatform = srcPath.GetPlatform();
                Packer.Pack(srcPath, destFileName, UpdateSng, packagePlatform, UpdateManifest);
                sw.Stop();
                GlobalExtension.ShowProgress("Finished packing archive (elapsed time): " + sw.Elapsed, 100);
            }
            catch (Exception ex)
            {
                errMsg = String.Format("{0}\n{1}", ex.Message, ex.InnerException);
            }

            PromptComplete(destFileName, true, errMsg);
            GlobalExtension.Dispose();
            ToggleUIControls(true);
        }
Пример #8
0
        private static void ExtractPSARC(string filename, string savePath, Stream inputStream, Platform platform, bool isExternalFile = true)
        {
            string psarcFilename = Path.GetFileNameWithoutExtension(filename);

            if (isExternalFile)
            {
                psarcFilename += String.Format("_{0}", platform.platform);
            }

            var destpath = Path.Combine(savePath, psarcFilename);

            if (Directory.Exists(destpath) && isExternalFile)
            {
                DirectoryExtension.SafeDelete(destpath);
            }

            var psarc = new PSARC.PSARC();

            psarc.Read(inputStream, true);

            var    step     = Math.Round(1.0 / (psarc.TOC.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Inflating Entries ...");

            foreach (var entry in psarc.TOC)
            {
                // custom InflateEntries
                // var debugMe = "Check the TOC";
                var fullfilename = Path.Combine(destpath, entry.Name);

                if (Path.GetExtension(entry.Name).ToLower() == ".psarc")
                {
                    psarc.InflateEntry(entry);
                    ExtractPSARC(fullfilename, destpath, entry.Data, platform, false);
                }
                else
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(fullfilename));
                    psarc.InflateEntry(entry, fullfilename);
                    if (entry.Data != null)
                    {
                        entry.Data.Dispose(); //Close();
                    }
                }

                if (!String.IsNullOrEmpty(psarc.ErrMSG))
                {
                    throw new InvalidDataException(psarc.ErrMSG);
                }

                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
            }
            // GlobalExtension.HideProgress();
        }
Пример #9
0
        private void btnPackSongPack_Click(object sender, EventArgs e)
        {
            var srcPath = String.Empty;
            var errMsg  = String.Empty;

            using (var fbd = new VistaFolderBrowserDialog())
            {
                fbd.Description  = "Select the Song Pack folder created in Step #1.";
                fbd.SelectedPath = destPath;

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

                srcPath = fbd.SelectedPath;
            }

            ToggleUIControls(false);
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            GlobalExtension.ShowProgress("Packing archive ...", 30);
            Application.DoEvents();

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Restart();

                var songPackDir = AggregateGraph2014.DoLikeSongPack(srcPath, txtAppId.Text);
                destPath = Path.Combine(Path.GetDirectoryName(srcPath), String.Format("{0}_songpack_p.psarc", Path.GetFileName(srcPath)));
                // PC Only for now can't mix platform packages
                Packer.Pack(songPackDir, destPath, predefinedPlatform: new Platform(GamePlatform.Pc, GameVersion.RS2014));

                // clean up now (song pack folder)
                if (Directory.Exists(songPackDir))
                {
                    DirectoryExtension.SafeDelete(songPackDir);
                }

                sw.Stop();
                GlobalExtension.ShowProgress("Finished packing archive (elapsed time): " + sw.Elapsed, 100);
            }
            catch (Exception ex)
            {
                errMsg  = String.Format("{0}\n{1}", ex.Message, ex.InnerException);
                errMsg += Environment.NewLine + "Make sure there aren't any non-PC CDLC in the SongPacks folder.";
            }

            PromptComplete(destPath, true, errMsg);
            GlobalExtension.Dispose();
            ToggleUIControls(true);
        }
        // this method will work for Song Packs too!
        public IEnumerable <Manifest2014 <Attributes2014> > ExtractJsonManifests()
        {
            var sw = new Stopwatch();

            sw.Restart();

            // every song contains gamesxblock but may not contain showlights.xml
            var xblockEntries = _archive.TOC.Where(x => x.Name.StartsWith("gamexblocks/nsongs") && x.Name.EndsWith(".xblock")).ToList();

            if (!xblockEntries.Any())
            {
                throw new Exception("Could not find valid xblock file in archive.");
            }

            var jsonData = new List <Manifest2014 <Attributes2014> >();

            // this foreach loop addresses song packs otherwise it is only done one time
            foreach (var xblockEntry in xblockEntries)
            {
                // CAREFUL with use of Contains and Replace to avoid creating duplicates
                var strippedName = xblockEntry.Name.Replace(".xblock", "").Replace("gamexblocks/nsongs", "");
                if (strippedName.Contains("_fcp_dlc"))
                {
                    strippedName = strippedName.Replace("fcp_dlc", "");
                }

                var jsonEntries = _archive.TOC.Where(x => x.Name.StartsWith("manifests/songs") &&
                                                     x.Name.EndsWith(".json") && x.Name.Contains(strippedName)).OrderBy(x => x.Name).ToList();

                // looping through song multiple times gathering each arrangement
                foreach (var jsonEntry in jsonEntries)
                {
                    var dataObj = new Manifest2014 <Attributes2014>();

                    _archive.InflateEntry(jsonEntry);
                    jsonEntry.Data.Position = 0;
                    var ms = new MemoryStream();
                    using (var reader = new StreamReader(ms, new UTF8Encoding(), false, 65536)) //4Kb is default alloc size for windows .. 64Kb is default PSARC alloc
                    {
                        jsonEntry.Data.Position = 0;
                        jsonEntry.Data.CopyTo(ms);
                        ms.Position = 0;
                        var jsonObj = JObject.Parse(reader.ReadToEnd());
                        dataObj = JsonConvert.DeserializeObject <Manifest2014 <Attributes2014> >(jsonObj.ToString());
                    }

                    jsonData.Add(dataObj);
                }
            }

            sw.Stop();
            GlobalExtension.ShowProgress(String.Format("{0} parsing json manifest entries took: {1} (msec)", Path.GetFileName(_filePath), sw.ElapsedMilliseconds));
            return(jsonData);
        }
        private void packButton_Click(object sender, EventArgs e)
        {
            string sourcePath;
            string saveFileName;

            using (var fbd = new VistaFolderBrowserDialog())
            {
                if (fbd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                sourcePath = fbd.SelectedPath;
            }

            using (var sfd = new SaveFileDialog())
            {
                if (sfd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                saveFileName = sfd.FileName;
            }

            GlobalExtension.UpdateProgress        = this.updateProgress;
            GlobalExtension.CurrentOperationLabel = this.currentOperationLabel;
            Thread.Sleep(100); // give Globals a chance to initialize
            GlobalExtension.ShowProgress("Packing archive ...");

            Application.DoEvents();

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Restart();
                Packer.Pack(sourcePath, saveFileName, updateSng);
                sw.Stop();
                GlobalExtension.ShowProgress("Finished packing archive (elapsed time): " + sw.Elapsed, 100);
                MessageBox.Show("Packing is complete.", MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format("{0}\n{1}\n{2}", "Packing error!", ex.Message, ex.InnerException), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            // prevents possible cross threading
            GlobalExtension.Dispose();
        }
Пример #12
0
        public string PackSong(string srcPath, string destPath)
        {
            ToggleUIControls(false);
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            GlobalExtension.ShowProgress("Packing archive ...", 30);
            Application.DoEvents();
            var errMsg      = String.Empty;
            var archivePath = String.Empty;

            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Restart();
                archivePath = Packer.Pack(srcPath, destPath, updateSng: UpdateSng, updateManifest: UpdateManifest);
                sw.Stop();
                GlobalExtension.ShowProgress("Finished packing archive (elapsed time): " + sw.Elapsed, 100);
            }
            catch (OutOfMemoryException ex)
            {
                errMsg = String.Format("{0}\n{1}", ex.Message, ex.InnerException) + Environment.NewLine +
                         "Toolkit is not capable of repacking some large system artifact files.   " + Environment.NewLine +
                         "Defragging the hard drive and clearing the 'pagefile.sys' may help.";
            }
            catch (Exception ex)
            {
                errMsg = String.Format("{0}\n{1}", ex.Message, ex.InnerException) + Environment.NewLine +
                         "Confirm GamePlatform and GameVersion are set correctly for" + Environment.NewLine +
                         "the desired destination in the toolkit Configuration settings.";
            }

            if (!GlobalsLib.IsUnitTest)
            {
                PromptComplete(destPath, true, errMsg);
            }

            GlobalExtension.Dispose();
            ToggleUIControls(true);

            return(archivePath);
        }
        private void UnpackSongs(IEnumerable<string> sourceFileNames, string destPath, bool decode = false, bool extract = false)
        {
            ToggleUIControls(false);
            errorsFound = new StringBuilder();
            GlobalExtension.UpdateProgress = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize
            Stopwatch sw = new Stopwatch();
            sw.Restart();

            foreach (string sourceFileName in sourceFileNames)
            {
                Application.DoEvents();
                Platform platform = Packer.GetPlatform(sourceFileName);
                GlobalExtension.ShowProgress(String.Format("Unpacking '{0}'", Path.GetFileName(sourceFileName)));
                lblCurrentOperation.Refresh();
                
                try
                {
                    Packer.Unpack(sourceFileName, destPath, decode, extract);
                }
                catch (Exception ex)
                {
                    errorsFound.AppendLine(String.Format("Error unpacking file '{0}': {1}", Path.GetFileName(sourceFileName), ex.Message));
                }
            }

            sw.Stop();
            GlobalExtension.ShowProgress("Finished unpacking archive (elapsed time): " + sw.Elapsed, 100);

            if (errorsFound.Length > 0)
                MessageBox.Show("Unpacking is complete with errors. See below: " + Environment.NewLine + Environment.NewLine + errorsFound.ToString(), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            else
                MessageBox.Show("Unpacking is complete.", MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Information);

            // prevents possible cross threading
            GlobalExtension.Dispose();
            ToggleUIControls(true);
        }
Пример #14
0
        // ===================== FOR FUTURE ====================

        public Bitmap ExtractAlbumArt(bool extractTaggerOrg)
        {
            Bitmap imageData = null;
            var    sw        = new Stopwatch();

            sw.Restart();

            //Func<Entry, bool> entryLINQ;
            //if (extractTaggerOrg)
            //    entryLINQ = entry => entry.Name == "tagger.org";
            //else
            //    entryLINQ = x => x.Name.Contains("256.dds");

            //var albumArtEntry = _archive.TOC.FirstOrDefault(entryLINQ);
            //if (albumArtEntry == null && extractTaggerOrg)
            //    RSTKTools.GlobalExtension.ShowProgress("Could not find tagger.org entry in archive.");

            //if (albumArtEntry != null)
            //{
            //    _archive.InflateEntry(albumArtEntry);
            //    var ms = new MemoryStream();
            //    using (var reader = new StreamReader(ms, new UTF8Encoding(), false, 65536)) //4Kb is default alloc size for windows .. 64Kb is default PSARC alloc
            //    {
            //        albumArtEntry.Data.Position = 0;
            //        albumArtEntry.Data.CopyTo(ms);
            //        ms.Position = 0;

            //        var b = ImageExtensions.DDStoBitmap(ms);
            //        if (b != null)
            //            imageData = b;
            //    }
            //}

            sw.Stop();
            GlobalExtension.ShowProgress(String.Format("{0} parsing albumart entry took: {1} (msec)", Path.GetFileName(_filePath), sw.ElapsedMilliseconds));
            return(imageData);
        }
Пример #15
0
        /// <summary>
        /// Writes to the inputStream
        /// <para>Default 'seek' is true, flushes and seeks to the end of stream after write is finished</para>
        /// <para>Eliminates the need for coding output.Flush() followed by output.Seek(0, SeekOrigin.Begin)</para>
        /// </summary>
        /// <param name="inputStream"></param>
        /// <param name="encrypt"></param>
        /// <param name="seek"></param>
        public void Write(Stream inputStream, bool encrypt = false, bool seek = true)
        {
            _header.ArchiveFlags = encrypt ? 4U : 0U;
            _header.TOCEntrySize = 30U;

            // track artifacts
            WriteManifest();

            //Pack entries
            List <uint> zLengths;
            Dictionary <Entry, byte[]> zStreams;

            DeflateEntries(out zStreams, out zLengths);

            //Build zLengths
            _writer = new BigEndianBinaryWriter(inputStream);
            _header.TotalTOCSize = (uint)(32 + _toc.Count * _header.TOCEntrySize + zLengths.Count * bNum);
            _toc[0].Offset       = _header.TotalTOCSize;

            for (int i = 1; i < _toc.Count; i++)
            {
                _toc[i].Offset = _toc[i - 1].Offset + (ulong)(zStreams[_toc[i - 1]].Length);
            }

            //Write Header
            _writer.Write(_header.MagicNumber);
            _writer.Write(_header.VersionNumber);
            _writer.Write(_header.CompressionMethod);
            _writer.Write(_header.TotalTOCSize);
            _writer.Write(_header.TOCEntrySize);
            _writer.Write(_toc.Count);
            _writer.Write(_header.BlockSizeAlloc);
            _writer.Write(_header.ArchiveFlags);

            var    step     = Math.Round(1D / (this.TOC.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Writing tocData ...");

            //Write Table of contents
            foreach (Entry entry in _toc)
            {
                entry.UpdateNameMD5();
                _writer.Write(entry.MD5);
                _writer.Write(entry.zIndexBegin);
                _writer.WriteUInt40((ulong)entry.Data.Length);
                _writer.WriteUInt40(entry.Offset);

                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Console.WriteLine("Writing tocData: " + entry.Id);
            }

            foreach (uint zLen in zLengths)
            {
                switch (bNum)
                {
                case 2:     //16bit
                    _writer.Write((ushort)zLen);
                    break;

                case 3:     //24bit
                    _writer.WriteUInt24(zLen);
                    break;

                case 4:     //32bit
                    _writer.Write(zLen);
                    break;
                }
            }

            zLengths = null;
            progress = 0;
            GlobalExtension.ShowProgress("Writing zData ...");

            // Write zData
            foreach (Entry entry in _toc)
            {
                // skip NamesBlock.bin
                //if (current.Name == "NamesBlock.bin")
                //    continue;

                //try
                //{
                // use chunk write method to avoid OOM Exceptions
                var z   = zStreams[entry];
                var len = z.Length;
                if (len > _header.BlockSizeAlloc)
                {
                    using (var msInput = new MemoryStreamExtension(z))
                        using (var msExt = new MemoryStreamExtension())
                            using (var _writer2 = new BigEndianBinaryWriter(msExt))
                            {
                                int bytesRead;
                                int totalBytesRead = 0;
                                var buffer         = new byte[_header.BlockSizeAlloc];
                                while ((bytesRead = msInput.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    totalBytesRead += bytesRead;
                                    if (totalBytesRead > len)
                                    {
                                        bytesRead = len - (totalBytesRead - bytesRead);
                                    }

                                    using (var msOutput = new MemoryStreamExtension())
                                    {
                                        msOutput.Write(buffer, 0, bytesRead);
                                        _writer2.Write(msOutput.ToArray());
                                    }
                                }

                                _writer.Write(msExt.ToArray());
                            }
                }
                else
                {
                    _writer.Write(zStreams[entry]);
                }

                if (entry.Data != null)
                {
                    entry.Data.Close();
                }
                //}
                //catch (Exception ex)
                //{
                //    Console.WriteLine("<ERROR> _writer.Write: " + ex.Message);
                //    _writer.Flush();
                //    _writer.Dispose();
                //    break;
                //}

                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Console.WriteLine("Writing zData: " + entry.Id);
            }

            zStreams = null;

            if (encrypt) // Encrypt TOC
            {
                using (var outputStream = new MemoryStreamExtension())
                    using (var encStream = new MemoryStreamExtension())
                    {
                        inputStream.Position = 32L;
                        RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, _header.TotalTOCSize);
                        inputStream.Position = 0L;

                        // quick copy header from input stream
                        var buffer = new byte[32];
                        encStream.Write(buffer, 0, inputStream.Read(buffer, 0, buffer.Length));
                        encStream.Position = 32; //sanity check ofc
                        inputStream.Flush();

                        int tocSize = (int)_header.TotalTOCSize - 32;
                        int decSize = 0;
                        buffer = new byte[1024 * 16]; // more efficient use of memory

                        var ndx = 0;                  // for debugging
                        step     = Math.Round(1D / (((double)tocSize / buffer.Length) + 2) * 100, 3);
                        progress = 0;
                        GlobalExtension.ShowProgress("Writing encryptedData ...");

                        int bytesRead;
                        while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            decSize += bytesRead;
                            if (decSize > tocSize)
                            {
                                bytesRead = tocSize - (decSize - bytesRead);
                            }

                            encStream.Write(buffer, 0, bytesRead);

                            progress += step;
                            GlobalExtension.UpdateProgress.Value = (int)progress;
                            Console.WriteLine("Writing encryptedData: " + ndx++);
                        }

                        inputStream.Position = 0;
                        encStream.Position   = 0;
                        encStream.CopyTo(inputStream, (int)_header.BlockSizeAlloc);
                    }
            }

            if (seek)
            {
                inputStream.Flush();
                inputStream.Seek(0, SeekOrigin.Begin);
            }

            //GlobalExtension.HideProgress();
        }
Пример #16
0
        // old slower static method
        public static List <Entry> ExtractAudioEntry(string archiveName, string audioName, string previewName)
        {
            bool result = false;

            if (String.IsNullOrEmpty(audioName))
            {
                return(null); // false;
            }
            GlobalExtension.ShowProgress("Extracting Audio ...");
            List <Entry> wems;

            using (var archive = new PSARC(true))
                using (var stream = File.OpenRead(archiveName))
                {
                    archive.Read(stream, true);
                    wems = archive.TOC.Where(entry => entry.Name.StartsWith("audio/windows") && entry.Name.EndsWith(".wem")).ToList();

                    if (wems.Count > 1)
                    {
                        wems.Sort((e1, e2) =>
                        {
                            if (e1.Length < e2.Length)
                            {
                                return(1);
                            }
                            if (e1.Length > e2.Length)
                            {
                                return(-1);
                            }
                            return(0);
                        });
                    }

                    if (wems.Count > 0)
                    {
                        var top = wems[0]; // wem audio with internal TOC path
                        archive.InflateEntry(top);
                        top.Data.Position = 0;
                        using (var FS = File.Create(audioName))
                        {
                            WwiseToOgg w2o = new WwiseToOgg(top.Data, FS);
                            result = w2o.ConvertToOgg();
                        }
                    }

                    if (!String.IsNullOrEmpty(previewName) && result && wems.Count > 0)
                    {
                        var bottom = wems.Last();
                        archive.InflateEntry(bottom);
                        bottom.Data.Position = 0;
                        using (var FS = File.Create(previewName))
                        {
                            WwiseToOgg w2o = new WwiseToOgg(bottom.Data, FS);
                            result = w2o.ConvertToOgg();
                        }
                    }
                }

            // confirmed this output is same as old exe converter method both are 44KHz VBR
            if (!result)
            {
                return(null);
            }

            return(wems);
        }
Пример #17
0
        private void unpackButton_Click(object sender, EventArgs e)
        {
            string[] sourceFileNames;
            savePath = String.Empty;

            using (var ofd = new OpenFileDialog())
            {
                ofd.Filter      = "All Files (*.*)|*.*";
                ofd.Multiselect = true;
                if (ofd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                sourceFileNames = ofd.FileNames;
            }

            using (var fbd = new VistaFolderBrowserDialog())
            {
                fbd.SelectedPath = Path.GetDirectoryName(sourceFileNames[0]) + Path.DirectorySeparatorChar;
                if (fbd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                savePath = fbd.SelectedPath;
            }

            // commented out bWorker aspects to test GlobalExtension ProgressBar function
            //if (!bwUnpack.IsBusy && sourceFileNames.Length > 0)
            //{
            //    updateProgress.Value = 0;
            //    updateProgress.Visible = true;
            //    currentOperationLabel.Visible = true;
            unpackButton.Enabled = false;
            //    bwUnpack.RunWorkerAsync(sourceFileNames);
            //}
            //}

            //private void Unpack(object sender, DoWorkEventArgs e)
            //{
            //    var sourceFileNames = e.Argument as string[];
            errorsFound = new StringBuilder();
            //var step = (int)Math.Round(1.0 / sourceFileNames.Length * 100, 0);
            //int progress = 0;

            GlobalExtension.UpdateProgress        = this.updateProgress;
            GlobalExtension.CurrentOperationLabel = this.currentOperationLabel;
            Thread.Sleep(100); // give Globals a chance to initialize

            foreach (string sourceFileName in sourceFileNames)
            {
                Application.DoEvents();
                Platform platform = Packer.GetPlatform(sourceFileName);
                // bwUnpack.ReportProgress(progress, String.Format("Unpacking '{0}'", Path.GetFileName(sourceFileName)));

                GlobalExtension.ShowProgress(String.Format("Unpacking '{0}'", Path.GetFileName(sourceFileName)));

                // remove this exception handler for testing
                try
                {
                    Stopwatch sw = new Stopwatch();
                    sw.Restart();
                    Packer.Unpack(sourceFileName, savePath, decodeAudio, extractSongXml);
                    sw.Stop();
                    GlobalExtension.ShowProgress("Finished unpacking archive (elapsed time): " + sw.Elapsed, 100);
                }
                catch (Exception ex)
                {
                    errorsFound.AppendLine(String.Format("Error unpacking file '{0}': {1}", Path.GetFileName(sourceFileName), ex.Message));
                }

                // progress += step;
                // bwUnpack.ReportProgress(progress);
            }
            //  bwUnpack.ReportProgress(100);
            //  e.Result = "unpack";

            // add this message while bWorker is commented out
            if (errorsFound.Length <= 0)
            {
                MessageBox.Show("Unpacking is complete.", MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("Unpacking is complete with errors. See below: " + Environment.NewLine + Environment.NewLine + errorsFound.ToString(), MESSAGEBOX_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            unpackButton.Enabled = true;
            // prevents possible cross threading
            GlobalExtension.Dispose();
        }
        /// <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);
        }
Пример #19
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;
            }

            var fixLowBass = ConfigRepository.Instance().GetBoolean("creator_fixlowbass");

            ToggleUIControls(false);
            errorsFound = new StringBuilder();
            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();

                string unpackedDir;
                try
                {
                    unpackedDir = Packer.Unpack(srcPath, tmpPath, overwriteSongXml: true, predefinedPlatform: packagePlatform);
                }
                catch (Exception ex)
                {
                    errorsFound.AppendLine(String.Format("Error trying unpack file '{0}': {1}", Path.GetFileName(srcPath), ex.Message));
                    continue;
                }

                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, false);

                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 != 220.0)
                        {
                            if (!TuningFrequency.ApplyBassFix(arr, fixLowBass))
                            {
                                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
                        {
                            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.");
                    }
                }

                // 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 (!GeneralExtensions.IsInDesignMode)
                {
                    DirectoryExtension.SafeDelete(unpackedDir);
                }
            }

            sw.Stop();
            GlobalExtension.ShowProgress("Finished applying low bass tuning fix (elapsed time): " + sw.Elapsed, 100);
            if (String.IsNullOrEmpty(destPath))
            {
                destPath = srcPaths[0];
            }

            PromptComplete(destPath, errMsg: errorsFound.ToString());
            GlobalExtension.Dispose();
            ToggleUIControls(true);
        }
Пример #20
0
        private void UnpackSongs(IEnumerable <string> sourceFileNames, string destPath, bool decode = false, bool overwrite = false)
        {
            ToggleUIControls(false);
            errorsFound = new StringBuilder();
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize

            var       structured = ConfigRepository.Instance().GetBoolean("creator_structured");
            var       step       = (int)Math.Floor(100.0 / (sourceFileNames.Count() * 2)); // Math.Floor prevents roundup errors
            int       progress   = 0;
            Stopwatch sw         = new Stopwatch();

            sw.Restart();

            foreach (string sourceFileName in sourceFileNames)
            {
                Application.DoEvents();
                progress += step;
                GlobalExtension.ShowProgress(String.Format("Unpacking: '{0}'", Path.GetFileName(sourceFileName)), progress);

                try
                {
                    Platform platform    = sourceFileName.GetPlatform();
                    var      unpackedDir = Packer.Unpack(sourceFileName, destPath, decode, overwrite, platform);

                    // added a bulk process to create template xml files here so unpacked folders may be loaded quickly in CDLC Creator if desired
                    progress += step;
                    GlobalExtension.ShowProgress(String.Format("Creating Template XML file for: '{0}'", Path.GetFileName(sourceFileName)), progress);
                    using (var packageCreator = new DLCPackageCreator.DLCPackageCreator())
                    {
                        DLCPackageData info = null;
                        if (platform.version == GameVersion.RS2014)
                        {
                            info = DLCPackageData.LoadFromFolder(unpackedDir, platform, platform, true, true);
                        }
                        else
                        {
                            info = DLCPackageData.RS1LoadFromFolder(unpackedDir, platform, false);
                        }

                        info.GameVersion = platform.version;

                        switch (platform.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;
                        }

                        packageCreator.FillPackageCreatorForm(info, unpackedDir);
                        // fix descrepancies
                        packageCreator.CurrentGameVersion = platform.version;
                        //packageCreator.SelectComboAppId(info.AppId);
                        packageCreator.AppId = info.AppId;
                        // save template xml file except when SongPack
                        if (!sourceFileName.Contains("_sp_") && !sourceFileName.Contains("_songpack_"))
                        {
                            packageCreator.SaveTemplateFile(unpackedDir, false);
                        }
                    }
                }
                catch (Exception ex)
                {
                    errorsFound.AppendLine(String.Format("Error unpacking file: '{0}' ... {1}", Path.GetFileName(sourceFileName), ex.Message));
                }
            }

            sw.Stop();
            GlobalExtension.ShowProgress("Finished unpacking archive (elapsed time): " + sw.Elapsed, 100);
            PromptComplete(destPath, false, errorsFound.ToString());
            GlobalExtension.Dispose();
            ToggleUIControls(true);
        }
Пример #21
0
        static void Main(string[] args)
        {
            // make the logger available globally in application
            GlobalsConfig.Log = LogManager.GetCurrentClassLogger();
            // TODO: figure out way for native mac\linux OS
            var logPath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "_RSToolkit_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log");

            // verify external apps in 'tools' and 'ddc' directory
            ExternalApps.VerifyExternalApps(); // throws necessary exception if missing

            // workaround fix for Win10 NET4.6 compatiblity issue
            var updaterVersion = "Null";

            try
            {
                updaterVersion = ToolkitVersion.RSTKUpdaterVersion();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message + "\n\n" + e.ToString());
                /* DO NOTHING */
            }

            var assembly = Assembly.LoadFile(typeof(RocksmithToolkitLib.ToolkitVersion).Assembly.Location);
            var assemblyConfiguration = assembly.GetCustomAttributes(typeof(AssemblyConfigurationAttribute), false).Cast <AssemblyConfigurationAttribute>().FirstOrDefault().Configuration.ToString() ?? "";
            var dtuLib = DateTime.Parse(assemblyConfiguration, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);

            GlobalsConfig.Log.Info(//OSVersion on unix will return it's Kernel version, urgh.
                String.Format(" - RocksmithToolkitGUI: v{0}\r\n ", ToolkitVersion.RSTKGuiVersion) +
                String.Format(" - RocksmithToolkitLib: v{0} [{1}]\r\n ", ToolkitVersion.RSTKLibVersion(), dtuLib) +
                String.Format(" - RocksmithToolkitUpdater: v{0}\r\n ", updaterVersion) +
                String.Format(" - Dynamic Difficulty Creator: v{0}\r\n ", FileVersionInfo.GetVersionInfo(Path.Combine(ExternalApps.TOOLKIT_ROOT, ExternalApps.APP_DDC)).ProductVersion) +
                String.Format(" - OS: {0} ({1} bit)\r\n ", Environment.OSVersion, Environment.Is64BitOperatingSystem ? "64" : "32") +
                String.Format(" - .NET Framework Runtime: v{0}\r\n ", Environment.Version) +
                String.Format(" - CultureInfo: ({0}) \r\n ", CultureInfo.CurrentCulture.ToString()) +
                String.Format(" - Current Local DateTime: [{0}]\r\n ", DateTime.Now.ToString()) +
                String.Format(" - Current UTC DateTime: [{0}]\r\n ", DateTime.UtcNow.ToString()) +
                String.Format(" - JIT: {0}\r\n ", JitVersionInfo.GetJitVersion()) +
                String.Format(" - WINE_INSTALLED: {0}\r\n ", GeneralExtension.IsWine()) +
                String.Format(" - MacOSX: {0} ", Environment.OSVersion.Platform == PlatformID.MacOSX)
                );

            if (!Environment.Version.ToString().Contains("4.0.30319") &&
                ConfigRepository.Instance().GetBoolean("general_firstrun"))
            {
                var envMsg = "The toolkit runs best with .NET 4.0.30319 installed." + Environment.NewLine +
                             "You are currently running .NET " + Environment.Version.ToString() + Environment.NewLine +
                             "Install the correct version if you experinece problems running the toolkit.   " + Environment.NewLine + Environment.NewLine +
                             "Click 'Yes' to download and install the correct version now from:" + Environment.NewLine +
                             "https://www.microsoft.com/en-us/download/confirmation.aspx?id=17718";

                if (MessageBox.Show(envMsg, "Incorrect .NET Version ...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                {
                    Process.Start("https://www.microsoft.com/en-us/download/confirmation.aspx?id=17718");
                    Thread.Sleep(500);
                    Process.Start("https://www.howtogeek.com/118869/how-to-easily-install-previous-versions-of-the-.net-framework-in-windows-8");

                    // Kill current toolkit process now that download process is started
                    Environment.Exit(0);
                }
            }

            // use custom event handlers
            if (!GeneralExtension.IsInDesignMode)
            {
                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                AppDomain.CurrentDomain.UnhandledException += (s, e) =>
                {
                    var exception = e.ExceptionObject as Exception;
                    GlobalsConfig.Log.Error(" - Unhandled.Exception:\n\nSource: {0}\nTarget: {1}\n{2}", exception.Source, exception.TargetSite, exception.ToString());

                    if (MessageBox.Show(String.Format("Unhandled.Exception:\n\n{0}\nPlease send us the {1} file if you need help.  Open log file now?",
                                                      exception.Message.ToString(), Path.GetFileName(logPath)),
                                        "Please Read This Important Message Completely ...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                    {
                        Process.Start(logPath);
                    }

                    GlobalExtension.HideProgress();
                };

                // UI thread exceptions handling.
                Application.ThreadException += (s, e) =>
                {
                    var exception    = e.Exception;
                    var packerErrMsg = RocksmithToolkitLib.DLCPackage.Packer.ErrMsg.ToString();

                    if (String.IsNullOrEmpty(packerErrMsg))
                    {
                        GlobalsConfig.Log.Error(" - Application.ThreadException\n\nSource: {0}\nTarget: {1}\n{2}", exception.Source, exception.TargetSite, exception.ToString());
                    }
                    else
                    {
                        GlobalsConfig.Log.Error(" - Application.ThreadException\n\nSource: {0}\nTarget: {1}\n{2}\n\nPacker.ThreadException (Corrupt CDLC): {3}", exception.Source, exception.TargetSite, exception.ToString(), packerErrMsg.Trim());
                    }

                    if (exception.Message != null && exception.Message.Contains("expired"))
                    {
                        MessageBox.Show(String.Format("Activation.ThreadException:\n\n{0}", exception.Message),
                                        "Please Read This Important Message Completely ...", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        Application.Exit();
                    }
                    else
                    {
                        var exMessage = String.IsNullOrEmpty(packerErrMsg) ? exception.Message : String.Format("{0}\nPacker.ThreadException (Corrupt CDLC):\n{1}\n", exception.Message, packerErrMsg.Trim());
                        if (MessageBox.Show(String.Format("Application.ThreadException:\n\n{0}\n\nPlease send us the {1} file if you need help.  Open log file now?", exMessage, Path.GetFileName(logPath)),
                                            "Please Read This Important Message Completely ...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                        {
                            Process.Start(logPath);
                        }
                    }

                    GlobalExtension.HideProgress();
                };
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm(args));
        }
        public List <string> UnpackSongs(IEnumerable <string> srcPaths, string destPath)
        {
            ToggleUIControls(false);
            errorsFound = new StringBuilder();
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize

            var       unpackedDirs = new List <string>();
            var       structured   = ConfigRepository.Instance().GetBoolean("creator_structured");
            var       step         = (int)Math.Floor(100.0 / (srcPaths.Count() * 2)); // Math.Floor prevents roundup errors
            int       progress     = 0;
            Stopwatch sw           = new Stopwatch();

            sw.Restart();

            foreach (string srcPath in srcPaths)
            {
                Application.DoEvents();
                progress += step;
                GlobalExtension.ShowProgress(String.Format("Unpacking: '{0}'", Path.GetFileName(srcPath)), progress);

                try
                {
                    Platform srcPlatform = srcPath.GetPlatform();
                    var      unpackedDir = Packer.Unpack(srcPath, destPath, srcPlatform, DecodeAudio, OverwriteSongXml);

                    // added a bulk process to create template xml files here so unpacked folders may be loaded quickly in CDLC Creator if desired
                    progress += step;
                    GlobalExtension.ShowProgress(String.Format("Creating Template XML file for: '{0}'", Path.GetFileName(srcPath)), progress);
                    using (var packageCreator = new DLCPackageCreator.DLCPackageCreator())
                    {
                        DLCPackageData info = null;
                        if (srcPlatform.version == GameVersion.RS2014)
                        {
                            info = DLCPackageData.LoadFromFolder(unpackedDir, srcPlatform, srcPlatform, true, true);
                        }
                        else
                        {
                            info = DLCPackageData.RS1LoadFromFolder(unpackedDir, srcPlatform, false);
                        }

                        info.GameVersion = srcPlatform.version;

                        switch (srcPlatform.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;
                        }

                        // save template xml file (except SongPacks)
                        if (ConfigRepository.Instance().GetBoolean("creator_autosavetemplate") &&
                            !srcPath.Contains("_sp_") && !srcPath.Contains("_songpack_"))
                        {
                            packageCreator.FillPackageCreatorForm(info, unpackedDir);
                            // fix descrepancies
                            packageCreator.CurrentGameVersion = srcPlatform.version;
                            // console files do not have an AppId
                            if (!srcPlatform.IsConsole)
                            {
                                packageCreator.AppId = info.AppId;
                            }

                            packageCreator.SaveTemplateFile(unpackedDir, false);
                        }
                    }

                    unpackedDirs.Add(unpackedDir);
                }
                catch (Exception ex)
                {
                    // ignore any 'Index out of range' exceptions
                    if (!ex.Message.StartsWith("Index"))
                    {
                        errorsFound.AppendLine(String.Format("<ERROR> Unpacking file: '{0}' ... {1}", Path.GetFileName(srcPath), ex.Message));
                    }
                }
            }

            sw.Stop();
            GlobalExtension.ShowProgress("Finished unpacking archive (elapsed time): " + sw.Elapsed, 100);

            if (!ConfigGlobals.IsUnitTest)
            {
                PromptComplete(destPath, false, errorsFound.ToString());
            }

            GlobalExtension.Dispose();
            ToggleUIControls(true);

            return(unpackedDirs);
        }
Пример #23
0
        public List <string> UnpackSongs(IEnumerable <string> srcPaths, string destPath)
        {
            ToggleUIControls(false);
            Packer.ErrMsg = new StringBuilder();
            errorsFound   = new StringBuilder();
            GlobalExtension.UpdateProgress        = this.pbUpdateProgress;
            GlobalExtension.CurrentOperationLabel = this.lblCurrentOperation;
            Thread.Sleep(100); // give Globals a chance to initialize

            var       unpackedDirs = new List <string>();
            var       structured   = ConfigRepository.Instance().GetBoolean("creator_structured");
            var       step         = (int)Math.Floor(100.0 / (srcPaths.Count() * 2)); // Math.Floor prevents roundup errors
            int       progress     = 0;
            Stopwatch sw           = new Stopwatch();

            sw.Restart();

            foreach (string srcPath in srcPaths)
            {
                Application.DoEvents();
                progress += step;
                GlobalExtension.ShowProgress(String.Format("Unpacking: '{0}'", Path.GetFileName(srcPath)), progress);
                Platform srcPlatform = srcPath.GetPlatform();
                var      unpackedDir = String.Empty;

                try
                {
                    unpackedDir = Packer.Unpack(srcPath, destPath, srcPlatform, DecodeAudio, OverwriteSongXml);
                    unpackedDirs.Add(unpackedDir);
                }
                catch (Exception ex)
                {
                    errorsFound.AppendLine(String.Format("<ERROR> Unpacking file: {0}{1}{2}", Path.GetFileName(srcPath), Environment.NewLine, ex.Message));
                    continue;
                }

                // added bulk process to create template xml files here so unpacked folders may be loaded quickly in CDLC Creator if desired
                if (ConfigRepository.Instance().GetBoolean("creator_autosavetemplate")) // && !srcPath.Contains("_sp_") && !srcPath.Contains("_songpack_"))
                {
                    try
                    {
                        var isSongPack = Directory.EnumerateFiles(unpackedDir, "*.wem", SearchOption.AllDirectories).Count() > 2;
                        if (isSongPack)
                        {
                            throw new Exception("<ERROR> Found too many *.wem files for template to" + Environment.NewLine +
                                                "process and load.  Uncheck the Autosave Template" + Environment.NewLine +
                                                "checkbox in General Config to prevent this exception." + Environment.NewLine);
                        }

                        //var isODLC = !Directory.EnumerateFiles(unpackedDir, "toolkit.version", SearchOption.AllDirectories).Any();
                        //if (isODLC)
                        //    throw new Exception("Uncheck 'Autosave Templates' in 'General Config' to avoid this error.");

                        if (srcPlatform.platform == GamePlatform.None)
                        {
                            throw new Exception("Could not determine GamePlatform.");
                        }

                        progress += step;
                        GlobalExtension.ShowProgress(String.Format("Creating Template XML file for: '{0}'", Path.GetFileName(srcPath)), progress);

                        using (var packageCreator = new DLCPackageCreator.DLCPackageCreator())
                        {
                            DLCPackageData info = null;
                            if (srcPlatform.version == GameVersion.RS2014)
                            {
                                info = DLCPackageData.LoadFromFolder(unpackedDir, srcPlatform, srcPlatform, true, true);
                            }
                            else
                            {
                                info = DLCPackageData.RS1LoadFromFolder(unpackedDir, srcPlatform, false);
                            }

                            info.GameVersion = srcPlatform.version;

                            switch (srcPlatform.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;
                            }

                            packageCreator.FillPackageCreatorForm(info, unpackedDir);
                            // fix descrepancies
                            packageCreator.CurrentGameVersion = srcPlatform.version;
                            // console files do not have an AppId
                            if (!srcPlatform.IsConsole)
                            {
                                packageCreator.AppId = info.AppId;
                            }

                            packageCreator.SaveTemplateFile(unpackedDir, false);
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex.Message.Contains("Object reference"))
                        {
                            errorsFound.AppendLine(String.Format("Could not create Template XML file for:{0}{1}", Environment.NewLine, Path.GetFileName(srcPath) + new string(' ', 5)));
                        }
                        else
                        {
                            errorsFound.AppendLine(String.Format("Could not create Template XML file for:{0}{1}{0}{0}{2}", Environment.NewLine, Path.GetFileName(srcPath) + new string(' ', 5), ex.Message));
                        }
                    }
                }
            }

            sw.Stop();
            GlobalExtension.ShowProgress("Finished unpacking archive (elapsed time): " + sw.Elapsed, 100);

            // insert any Packer error messages
            if (!String.IsNullOrEmpty(Packer.ErrMsg.ToString()))
            {
                errorsFound.Insert(0, Packer.ErrMsg.ToString());
            }

            if (!GlobalsLib.IsUnitTest)
            {
                PromptComplete(destPath, false, errorsFound.ToString());
            }

            GlobalExtension.Dispose();
            ToggleUIControls(true);

            return(unpackedDirs);
        }
        /// <summary>
        /// Packs Entries to zStream
        /// </summary>
        /// <param name="entryDeflatedData">zStreams</param>
        /// <param name="zLengths">zBlocksSizeList</param>
        private void DeflateEntries(out Dictionary <Entry, byte[]> entryDeflatedData, out List <uint> zLengths)
        {
            // TODO: This produces perfect results for song archives (original vs repacked)
            // there are slight differences in the binary of large archives (original vs repacked).  WHY?
            //
            entryDeflatedData = new Dictionary <Entry, byte[]>();
            uint blockSize = _header.BlockSizeAlloc;

            zLengths = new List <uint>();

            var    ndx      = 0; // for debugging
            var    step     = Math.Round(1.0 / (_toc.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Deflating Entries ...");

            foreach (Entry entry in _toc)
            {
                var zList = new List <Tuple <byte[], int> >();
                entry.zIndexBegin = (uint)zLengths.Count;
                entry.Data.Seek(0, SeekOrigin.Begin);

                while (entry.Data.Position < entry.Data.Length)
                {
                    var array_i      = new byte[blockSize];
                    var array_o      = new byte[blockSize * 2];
                    var memoryStream = new MemoryStream(array_o);

                    int plain_len  = entry.Data.Read(array_i, 0, array_i.Length);
                    int packed_len = (int)RijndaelEncryptor.Zip(array_i, memoryStream, plain_len, false);

                    if (packed_len >= plain_len)
                    {// If packed data "worse" than plain (i.e. already packed) z = 0
                        zList.Add(new Tuple <byte[], int>(array_i, plain_len));
                    }
                    else
                    {     // If packed data is good
                        if (packed_len < (blockSize - 1))
                        { // If packed data fits maximum packed block size z = packed_len
                            zList.Add(new Tuple <byte[], int>(array_o, packed_len));
                        }
                        else
                        {// Write plain. z = 0
                            zList.Add(new Tuple <byte[], int>(array_i, plain_len));
                        }
                    }
                }

                int zSisesSum = 0;
                foreach (var zSize in zList)
                {
                    zSisesSum += zSize.Item2;
                    zLengths.Add((uint)zSize.Item2);
                }

                var array3        = new byte[zSisesSum];
                var memoryStream2 = new MemoryStream(array3);
                foreach (var entryblock in zList)
                {
                    memoryStream2.Write(entryblock.Item1, 0, entryblock.Item2);
                }

                entryDeflatedData.Add(entry, array3);
                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Console.WriteLine("Deflating: " + ndx++);
            }
        }
        public void Write(Stream inputStream, bool encrypt = false, bool seek = true)
        {
            _header.ArchiveFlags = encrypt ? 4U : 0U;
            _header.TOCEntrySize = 30U;
            WriteManifest();
            //Pack entries
            List <uint> zLengths;
            Dictionary <Entry, byte[]> zStreams;

            DeflateEntries(out zStreams, out zLengths);
            //Build zLengths
            _writer = new BigEndianBinaryWriter(inputStream);
            _header.TotalTOCSize = (uint)(32 + _toc.Count * _header.TOCEntrySize + zLengths.Count * bNum);
            _toc[0].Offset       = _header.TotalTOCSize;
            for (int i = 1; i < _toc.Count; i++)
            {
                _toc[i].Offset = _toc[i - 1].Offset + (ulong)(zStreams[_toc[i - 1]].Length);
            }
            //Write Header
            _writer.Write(_header.MagicNumber);
            _writer.Write(_header.VersionNumber);
            _writer.Write(_header.CompressionMethod);
            _writer.Write(_header.TotalTOCSize);
            _writer.Write(_header.TOCEntrySize);
            _writer.Write(_toc.Count);
            _writer.Write(_header.BlockSizeAlloc);
            _writer.Write(_header.ArchiveFlags);
            //Write Table of contents
            foreach (Entry current in _toc)
            {
                current.UpdateNameMD5();
                _writer.Write(current.MD5);
                _writer.Write(current.zIndexBegin);
                _writer.WriteUInt40((ulong)current.Data.Length);//current.Length
                _writer.WriteUInt40(current.Offset);
            }
            foreach (uint zLen in zLengths)
            {
                switch (bNum)
                {
                case 2:    //16bit
                    _writer.Write((ushort)zLen);
                    break;

                case 3:    //24bit
                    _writer.WriteUInt24(zLen);
                    break;

                case 4:    //32bit
                    _writer.Write(zLen);
                    break;
                }
            }
            zLengths = null;

            // Write zData
            var    ndx      = 0; // for debugging
            var    step     = Math.Round(1D / (this.TOC.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Writing Zipped Data ...");

            foreach (Entry current in _toc)
            {
                _writer.Write(zStreams[current]);
                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Console.WriteLine("Zipped: " + ndx++);
                current.Data.Close();
            }
            zStreams = null;

            if (encrypt) // Encrypt TOC
            {
                using (var outputStream = new MemoryStreamExtension())
                {
                    var encStream = new MemoryStreamExtension();
                    inputStream.Position = 32L;
                    RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, _header.TotalTOCSize);
                    inputStream.Position = 0L;

                    // quick copy header from input stream
                    var buffer = new byte[32];
                    encStream.Write(buffer, 0, inputStream.Read(buffer, 0, buffer.Length));
                    encStream.Position = 32; //sanity check ofc
                    inputStream.Flush();

                    int tocSize = (int)_header.TotalTOCSize - 32;
                    int decSize = 0;
                    buffer = new byte[1024 * 16]; // more efficient use of memory

                    ndx      = 0;                 // for debugging
                    step     = Math.Round(1D / (((double)tocSize / buffer.Length) + 2) * 100, 3);
                    progress = 0;
                    GlobalExtension.ShowProgress("Writing Encrypted Data ...");

                    int bytesRead;
                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > tocSize)
                        {
                            bytesRead = tocSize - (decSize - bytesRead);
                        }

                        encStream.Write(buffer, 0, bytesRead);

                        progress += step;
                        GlobalExtension.UpdateProgress.Value = (int)progress;
                        Console.WriteLine("Encrypted: " + ndx++);
                    }

                    inputStream.Position = 0;
                    encStream.Position   = 0;
                    encStream.CopyTo(inputStream, (int)_header.BlockSizeAlloc);
                }
            }
            if (seek) // May be redundant
            {
                inputStream.Flush();
                inputStream.Position = 0;
            }
            //GlobalExtension.HideProgress();
        }
Пример #26
0
        public void Write(Stream inputStream, bool encrypt)
        {
            // TODO: This produces perfect results for song archives (original vs repacked)
            // there are slight differences in the binary of large archives (original vs repacked).  WHY?
            //
            this.header.archiveFlags = encrypt ? 4U : 0U;
            this.header.TOCEntrySize = 30;
            this.WriteManifest();
            //Pack entries
            Dictionary <Entry, byte[]> zStreams; List <uint> zLengths;

            DeflateEntries(out zStreams, out zLengths);
            //Build zLengths
            _writer = new BigEndianBinaryWriter(inputStream);
            this.header.TotalTOCSize = (uint)(32 + this.TOC.Count * this.header.TOCEntrySize + zLengths.Count * bNum);
            this.TOC[0].Offset       = (ulong)this.header.TotalTOCSize;
            for (int i = 1; i < this.TOC.Count; i++)
            {
                this.TOC[i].Offset = this.TOC[i - 1].Offset + (ulong)(zStreams[this.TOC[i - 1]].Length);
            }
            //Write Header
            _writer.Write(this.header.MagicNumber);
            _writer.Write(this.header.VersionNumber);
            _writer.Write(this.header.CompressionMethod);
            _writer.Write(this.header.TotalTOCSize);
            _writer.Write(this.header.TOCEntrySize);
            _writer.Write(this.TOC.Count);
            _writer.Write(this.header.blockSizeAlloc);
            _writer.Write(this.header.archiveFlags);
            //Write Table of contents
            foreach (Entry current in this.TOC)
            {
                current.UpdateNameMD5();
                _writer.Write((current.Id == 0) ? new byte[16] : current.MD5);
                _writer.Write(current.zIndexBegin);
                _writer.WriteUInt40((ulong)current.Data.Length);
                _writer.WriteUInt40(current.Offset);
            }
            foreach (uint zLen in zLengths)
            {
                switch (bNum)
                {
                case 2:
                    _writer.Write((ushort)zLen);
                    break;

                case 3:
                    _writer.WriteUInt24(zLen);
                    break;

                case 4:
                    _writer.Write(zLen);
                    break;
                }
            }

            // Write zData
            var    ndx      = 0; // for debugging
            var    step     = Math.Round(1.0 / (this.TOC.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Writing Zipped Data ...");

            foreach (Entry current in this.TOC)
            {
                _writer.Write(zStreams[current]);
                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Debug.WriteLine("Zipped: " + ndx++);
                current.Data.Close();
            }

            if (encrypt) // Encrypt TOC
            {
                using (var outputStream = new MemoryStreamExtension())
                {
                    var encStream = new MemoryStreamExtension();
                    inputStream.Seek(32, SeekOrigin.Begin);
                    RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, this.header.TotalTOCSize);
                    inputStream.Seek(0, SeekOrigin.Begin);

                    int bytesRead;
                    var buffer = new byte[32];
                    bytesRead = inputStream.Read(buffer, 0, buffer.Length);
                    inputStream.Flush();
                    // quick copy header from input stream
                    encStream.Write(buffer, 0, bytesRead);
                    encStream.Seek(32, SeekOrigin.Begin);

                    int tocSize = (int)this.header.TotalTOCSize - 32;
                    int decSize = 0;
                    buffer = new byte[1024 * 16]; // more effecient use of memory

                    ndx      = 0;                 // for debuging
                    step     = Math.Round(1.0 / ((tocSize / buffer.Length) + 2) * 100, 3);
                    progress = 0;
                    GlobalExtension.ShowProgress("Writing Encrypted Data ...");

                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > tocSize)
                        {
                            bytesRead = tocSize - (decSize - bytesRead);
                        }

                        encStream.Write(buffer, 0, bytesRead);

                        progress += step;
                        GlobalExtension.UpdateProgress.Value = (int)progress;
                        Debug.WriteLine("Encrypted: " + ndx++);
                    }

                    inputStream.Seek(0, SeekOrigin.Begin);
                    encStream.Seek(0, SeekOrigin.Begin);
                    encStream.CopyTo(inputStream, (int)this.header.blockSizeAlloc);
                }
            }

            inputStream.Flush();
            GlobalExtension.HideProgress();
        }