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); }
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); }
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); }
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(); }
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); }
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(); }
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(); }
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); }
// ===================== 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); }
/// <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(); }
// 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); }
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); }
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); }
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); }
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); }
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); }
/// <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(); }
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(); }