public void Serialize(Stream output)
        {
            if (this.Version == 1)
            {
                throw new NotSupportedException();
            }
            else if (this.Version == 2)
            {
                throw new NotSupportedException();
            }
            else if (this.Version == 3)
            {
                output.WriteString("ERF V3.0", Encoding.Unicode);

                var strings = new List<string>();
                foreach (var entry in this.Entries)
                {
                    if (entry.Name != null &&
                        strings.Contains(entry.Name) == false)
                    {
                        strings.Add(entry.Name);
                    }
                }
                strings.Sort();

                var stringOffsets = new Dictionary<string, uint>();
                var stringTable = new MemoryStream();

                foreach (var str in strings)
                {
                    stringOffsets[str] = (uint)stringTable.Length;
                    stringTable.WriteStringZ(str, Encoding.UTF8);
                }
                stringTable.SetLength(stringTable.Length.Align(16));
                stringTable.Position = 0;

                output.WriteValueU32((uint)stringTable.Length);
                output.WriteValueS32(this.Entries.Count);

                if (this.Encryption != EncryptionScheme.None ||
                    this.Compression != CompressionScheme.None)
                {
                    throw new NotSupportedException();
                }

                uint flags = 0;
                flags |= ((uint)this.Encryption) << 4;
                flags |= ((uint)this.Compression) << 29;
                output.WriteValueU32(flags);

                output.WriteValueU32(this.ContentId);
                if (this.PasswordDigest == null)
                {
                    output.Write(new byte[16], 0, 16);
                }
                else
                {
                    output.Write(this.PasswordDigest, 0, 16);
                }

                output.WriteFromStream(stringTable, stringTable.Length, 0x00100000);

                foreach (var entry in this.Entries)
                {
                    if (entry.Name != null)
                    {
                        entry.CalculateHashes();
                        output.WriteValueU32(stringOffsets[entry.Name]);
                    }
                    else
                    {
                        output.WriteValueU32(0xFFFFFFFF);
                    }

                    output.WriteValueU64(entry.NameHash);
                    output.WriteValueU32(entry.TypeHash);
                    output.WriteValueU32((uint)entry.Offset);
                    output.WriteValueU32(entry.CompressedSize);
                    output.WriteValueU32(entry.UncompressedSize);
                }
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
Example #2
0
        public string saveToFile(bool fileOverwrite = true)
        {
            bChanged = false;

            string finalTocFile = fileOverwrite ? tocFilePath : tocFilePath + ".tmp";
            using (FileStream newFileStream = File.Create(finalTocFile))
            {
                newFileStream.WriteValueU32(0x3AB70C13);
                newFileStream.WriteValueS32(0x0);
                newFileStream.WriteValueS32(chunkList.Count);

                int chunkOffset = 12;
                int fileOffset = 12 + (chunkList.Count * 8);

                string lastFile = chunkList.Last(x => (x.fileList != null) && x.fileList.Count(/*y => y.exist*/) != 0).fileList.Last(/*z => z.exist*/).filePath;

                //foreach (chunk element in chunkList)
                for(int i = 0; i < chunkList.Count; i++)
                {
                    chunk element = chunkList[i];
                    newFileStream.Seek(chunkOffset, SeekOrigin.Begin);

                    if (element.countNextFiles == 0)// || element.fileList.Count(x => x.exist) == 0)
                    {
                        newFileStream.WriteValueS64(0x0);
                        chunkOffset = (int)newFileStream.Position;
                    }
                    else
                    {
                        newFileStream.WriteValueS32(fileOffset - chunkOffset);
                        newFileStream.WriteValueS32(element.fileList.Count/*(x => x.exist)*/);
                        chunkOffset = (int)newFileStream.Position;

                        newFileStream.Seek(fileOffset, SeekOrigin.Begin);
                        //foreach (fileStruct fileElement in element.fileList.Where(x => x.exist))
                        for(int j = 0; j < element.fileList.Count; j++)
                        {
                            fileStruct fileElement = element.fileList[j];

                            //if (!fileElement.exist)
                            //    continue;
                            MemoryStream buffer = new MemoryStream(fileElement.blockSize);
                            {
                                if (fileElement.filePath == lastFile)
                                    buffer.WriteValueS16(0x0);
                                else
                                    buffer.WriteValueS16(fileElement.blockSize);
                                buffer.WriteValueS16(fileElement.flag);
                                buffer.WriteValueS32(fileElement.fileSize);
                                buffer.WriteBytes(fileElement.sha1);
                                buffer.WriteStringZ(fileElement.filePath);
                                byte[] byteBuff = new byte[fileElement.blockSize];
                                buffer.ToArray().CopyTo(byteBuff, 0);
                                newFileStream.WriteBytes(byteBuff);
                            }
                            //newFileStream.Seek(fileOffset, SeekOrigin.Begin);
                        }
                        fileOffset = (int)newFileStream.Position;
                    }
                }
            }

            return finalTocFile;
        }
Example #3
0
        public Stream Serialize()
        {
            MemoryStream data = new MemoryStream();
            uint sectionCount = (uint)this.Sections.Count;
            Stream[] resolvers = new MemoryStream[sectionCount]; // for serialized resolvers

            uint unknown04_size = 0;
            uint unknown08_size = 0;

            // Write DRM Header
            data.WriteValueU32(this.Version, this.Endianness);
            data.WriteValueU32(0); // skip for now
            data.WriteValueU32(0); // skip for now
            data.WriteValueU32(0); // unknown0C
            data.WriteValueU32(0); // unknown10
            data.WriteValueU32(sectionCount, this.Endianness);

            // Write DRM Section Headers
            for (int i = 0; i < sectionCount; i++)
            {
                DRM.Section section = this.Sections[i];

                // Serialize resolvers to get length, data will be used later
                uint resolverLen;
                if (section.Resolver != null)
                {
                    resolvers[i] = section.Resolver.Serialize(this.Endianness);
                    resolverLen = (uint)resolvers[i].Length;
                }
                else
                {
                    resolvers[i] = null;
                    resolverLen = 0;
                }

                data.WriteValueU32((uint)section.Data.Length, this.Endianness);
                data.WriteValueU8((byte)section.Type);
                data.WriteValueU8(section.Unknown05);
                data.WriteValueU16(section.Unknown06, this.Endianness);
                data.WriteValueU32((uint)section.Flags | (resolverLen << 8), this.Endianness);
                data.WriteValueU32(section.Id, this.Endianness);
                data.WriteValueU32(section.Unknown10, this.Endianness);
            }

            // Write Unknown08s
            for (int i = 0; i < Unknown08s.Count; i++)
            {
                unknown08_size += ((uint)Unknown08s[i].Length + 1);
                data.WriteStringZ(Unknown08s[i]);
            }

            // Write Unknown04s
            for (int i = 0; i < Unknown04s.Count; i++)
            {
                unknown04_size += ((uint)Unknown04s[i].Length + 1);
                data.WriteStringZ(Unknown04s[i]);
            }

            // Write DRM Section Data
            for (int i = 0; i < sectionCount; i++)
            {
                if (resolvers[i] != null)
                {
                    data.WriteFromStream(resolvers[i], resolvers[i].Length);
                }
                data.WriteFromStream(this.Sections[i].Data, this.Sections[i].Data.Length);
                this.Sections[i].Data.Position = 0;
            }

            // Go back and write unknowns length
            data.Seek(4, SeekOrigin.Begin);
            data.WriteValueU32(unknown04_size);
            data.WriteValueU32(unknown08_size);

            data.Position = 0;
            return data;
        }