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 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(); }
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 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: _writer.Write((ushort)zLen); break; case 3: _writer.WriteUInt24(zLen); break; case 4: _writer.Write(zLen); break; } } zLengths = null; // 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 _toc) { _writer.Write(zStreams[current]); progress += step; GlobalExtension.UpdateProgress.Value = (int)progress; Debug.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; //sainty check ofc inputStream.Flush(); int tocSize = (int)_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 ..."); 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; Debug.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(); }