Beispiel #1
0
        private static void Pack2014(string sourcePath, string saveFileName, Platform platform, bool updateSng, bool updateManifest, bool fixShowlights = true)
        {
            using (var psarc = new PSARC.PSARC())
                using (var psarcStream = new MemoryStreamExtension())
                {
                    if (updateSng)
                    {
                        UpdateSng2014(sourcePath, platform, fixShowlights: fixShowlights);
                    }
                    if (updateManifest)
                    {
                        UpdateManifest2014(sourcePath, platform);
                    }

                    WalkThroughDirectory("", sourcePath, (a, b) =>
                    {
                        var fileStream = File.OpenRead(b);
                        psarc.AddEntry(a, fileStream);
                    });

                    psarc.Write(psarcStream, !platform.IsConsole);
                    psarcStream.Flush();
                    psarcStream.Seek(0, SeekOrigin.Begin);

                    if (Path.GetExtension(saveFileName) != ".psarc")
                    {
                        saveFileName += ".psarc";
                    }

                    using (var outputFileStream = File.Create(saveFileName))
                        psarcStream.CopyTo(outputFileStream);
                }
        }
Beispiel #2
0
        public void Write(Stream psarc, bool encrypt)
        {
            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(psarc);
            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
            foreach (Entry current in this.TOC)
            {
                _writer.Write(zStreams[current]);
                current.Data.Close();
            }
            if (encrypt)
            {// Encrypt TOC
                var encStream = new MemoryStreamExtension();
                using (var outputStream = new MemoryStreamExtension())
                {
                    int bytesRead;
                    int decSize = 0;
                    var buffer  = new byte[30000];
                    int tocSize = (int)this.header.TotalTOCSize - 32;

                    psarc.Seek(32, SeekOrigin.Begin);
                    RijndaelEncryptor.EncryptPSARC(psarc, outputStream, this.header.TotalTOCSize);

                    psarc.Seek(0, SeekOrigin.Begin);
                    while ((bytesRead = psarc.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        encStream.Write(buffer, 0, bytesRead);
                    }

                    outputStream.Seek(0, SeekOrigin.Begin);
                    encStream.Seek(32, SeekOrigin.Begin);
                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > tocSize)
                        {
                            bytesRead = tocSize - (decSize - bytesRead);
                        }
                        encStream.Write(buffer, 0, bytesRead);
                    }
                }

                psarc.Seek(0, SeekOrigin.Begin);
                encStream.Seek(0, SeekOrigin.Begin);
                encStream.CopyTo(psarc, (int)this.header.blockSizeAlloc);
            }
            psarc.Flush();
        }
Beispiel #3
0
        public void Write(Stream str, bool encrypt)
        {
            if (encrypt)
            {
                this.header.archiveFlags = 4;
            }
            this.header.TOCEntrySize = 30;
            this.UpdateManifest();
            Dictionary <Entry, byte[]> dictionary;
            List <uint> list;

            this.deflateEntries(out dictionary, out list, this.header.blockSize);
            byte b   = 1;
            uint num = 256;

            do
            {
                num *= 256;
                b   += 1;
            }while (num < this.header.blockSize);
            BigEndianBinaryWriter bigEndianBinaryWriter = new BigEndianBinaryWriter(str);

            this.header.TotalTOCSize = (uint)(32 + this.header.TOCEntrySize * (this.Entries.Count) + ((int)b * list.Count));
            this.Entries[0].Offset   = (ulong)this.header.TotalTOCSize;
            for (int i = 1; i < this.Entries.Count; i++)
            {
                this.Entries[i].Offset = this.Entries[i - 1].Offset + (ulong)(dictionary[this.Entries[i - 1]].Length);
            }
            bigEndianBinaryWriter.Write(this.header.MagicNumber);
            bigEndianBinaryWriter.Write(this.header.VersionNumber);
            bigEndianBinaryWriter.Write(this.header.CompressionMethod);
            bigEndianBinaryWriter.Write(this.header.TotalTOCSize);
            bigEndianBinaryWriter.Write(this.header.TOCEntrySize);
            bigEndianBinaryWriter.Write(this.Entries.Count);
            bigEndianBinaryWriter.Write(this.header.blockSize);
            bigEndianBinaryWriter.Write(this.header.archiveFlags);
            foreach (Entry current in this.Entries)
            {
                current.UpdateNameMD5();
                bigEndianBinaryWriter.Write((current.id == 0) ? new byte[16] : current.MD5);
                bigEndianBinaryWriter.Write(current.zIndex);
                bigEndianBinaryWriter.WriteUInt40((ulong)current.Data.Length);
                bigEndianBinaryWriter.WriteUInt40(current.Offset);
            }
            foreach (uint current2 in list)
            {
                switch (b)
                {
                case 2:
                    bigEndianBinaryWriter.Write((ushort)current2);
                    break;

                case 3:
                    bigEndianBinaryWriter.WriteUInt24(current2);
                    break;

                case 4:
                    bigEndianBinaryWriter.Write(current2);
                    break;
                }
            }
            foreach (Entry current in this.Entries)
            {
                bigEndianBinaryWriter.Write(dictionary[current]);
            }

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

                    int    bytesRead;
                    byte[] buffer = new byte[30000];

                    str.Seek(0, SeekOrigin.Begin);
                    while ((bytesRead = str.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        encStream.Write(buffer, 0, bytesRead);
                    }
                    int decMax  = (int)this.header.TotalTOCSize - 32;
                    int decSize = 0;
                    outputStream.Seek(0, SeekOrigin.Begin);
                    encStream.Seek(32, SeekOrigin.Begin);
                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > decMax)
                        {
                            bytesRead = decMax - (decSize - bytesRead);
                        }
                        encStream.Write(buffer, 0, bytesRead);
                    }
                }

                str.Seek(0, SeekOrigin.Begin);
                encStream.Seek(0, SeekOrigin.Begin);
                encStream.CopyTo(str);
            }

            str.Flush();
        }
        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();
        }