示例#1
0
        //Write the nodes out to a file

        public bool Save(string filename, int version, ref string error)
        {
            foreach (var node in Root.IterateAll())
            {
                if (node.Children == null && node.Data == null)
                {
                    error = string.Format("{0} is empty. Can't write UTF", GetUtfPath(node));
                    return(false);
                }
            }
            if (version == 0)
            {
                return(SaveV1(filename, ref error));
            }
            else
            {
                return(SaveV2(filename, ref error));
            }
        }
示例#2
0
        //Write the nodes out to a file
        public bool Save(string filename, ref string error)
        {
            //Check for invalid UTF
            foreach (var node in Root.IterateAll())
            {
                if (node.Children == null && node.Data == null)
                {
                    error = string.Format("{0} is empty. Can't write UTF", GetUtfPath(node));
                    return(false);
                }
            }
            Dictionary <string, int>   stringOffsets = new Dictionary <string, int>();
            Dictionary <LUtfNode, int> dataOffsets   = new Dictionary <LUtfNode, int>();
            List <string> strings = new List <string>();

            using (var writer = new BinaryWriter(File.Create(filename)))
            {
                int currentDataOffset       = 0;
                int bytesSaved              = 0;
                List <SmallData> smallDatas = new List <SmallData>();
                foreach (var node in Root.IterateAll())
                {
                    if (!strings.Contains(node.Name))
                    {
                        strings.Add(node.Name);
                    }
                    if (node.Data != null)
                    {
                        int dataAlloc = node.Data.Length + 3 & ~3;
                        node.Write = true;
                        //De-duplicate data up to 64 bytes
                        if (node.Data.Length <= 64)
                        {
                            var small = new SmallData(node.Data);
                            int idx   = -1;
                            for (int i = 0; i < smallDatas.Count; i++)
                            {
                                if (smallDatas[i].Match(ref small))
                                {
                                    idx = i;
                                    break;
                                }
                            }
                            if (idx == -1)
                            {
                                small.Offset = currentDataOffset;
                                smallDatas.Add(small);
                                dataOffsets.Add(node, currentDataOffset);
                                currentDataOffset += dataAlloc;
                            }
                            else
                            {
                                node.Write  = false;
                                bytesSaved += smallDatas[idx].Length;
                                dataOffsets.Add(node, smallDatas[idx].Offset);
                            }
                        }
                        else
                        {
                            dataOffsets.Add(node, currentDataOffset);
                            currentDataOffset += dataAlloc;
                        }
                    }
                }
                LibreLancer.FLLog.Info("UTF", "Bytes Saved: " + bytesSaved);
                byte[] stringBlock;
                using (var mem = new MemoryStream())
                {
                    foreach (var str in strings)
                    {
                        stringOffsets.Add(str, (int)mem.Position);
                        var strx = str;
                        if (strx == "/")
                        {
                            strx = "\\";
                        }
                        var strb = Encoding.ASCII.GetBytes(strx);
                        mem.Write(strb, 0, strb.Length);
                        mem.WriteByte(0);                         //null terminate
                    }
                    strings     = null;
                    stringBlock = mem.ToArray();
                }

                byte[] nodeBlock;
                using (var mem = new MemoryStream())
                {
                    WriteNode(Root, new BinaryWriter(mem), stringOffsets, dataOffsets, true);
                    nodeBlock = mem.ToArray();
                }

                int strAlloc = stringBlock.Length + 3 & ~3;
                /*write signature*/
                writer.Write((byte)'U');
                writer.Write((byte)'T');
                writer.Write((byte)'F');
                writer.Write((byte)' ');
                writer.Write(LibreLancer.Utf.UtfFile.FILE_VERSION);
                writer.Write((int)56);                    //nodeBlockOffset
                writer.Write((int)nodeBlock.Length);      //nodeBlockLength
                writer.Write((int)0);                     //unused entry offset
                writer.Write((int)44);                    //entry Size - Not accurate but FL expects it to be 44
                writer.Write((int)56 + nodeBlock.Length); //stringBlockOffset
                writer.Write((int)strAlloc);              //namesAllocatedSize
                writer.Write((int)stringBlock.Length);    //namesUsedSize
                var dataBlockDesc = writer.BaseStream.Position;
                writer.Write((int)(56 + nodeBlock.Length + strAlloc));
                writer.Write((int)0);                    //unused
                writer.Write((int)0);                    //unused
                writer.Write((ulong)125596224000000000); //Fake filetime
                writer.Write(nodeBlock);
                writer.Write(stringBlock);
                for (int i = 0; i < (strAlloc - stringBlock.Length); i++)
                {
                    writer.Write((byte)0);
                }
                stringBlock = null;
                nodeBlock   = null;
                //write out data block
                foreach (var node in Root.IterateAll())
                {
                    if (node.Write && node.Data != null)
                    {
                        writer.Write(node.Data);
                        int dataAlloc = node.Data.Length + 3 & ~3;
                        for (int i = 0; i < (dataAlloc - node.Data.Length); i++)
                        {
                            writer.Write((byte)0);
                        }
                    }
                }
            }
            return(true);
        }