コード例 #1
0
ファイル: Files_nd.cs プロジェクト: loafbrad/NaturalDocs
        /* Function: Load
         * Loads <Files.nd> and returns whether it was successful.  If it wasn't it will still return valid objects, they will just
         * be empty.
         */
        public bool Load(Path filename, out IDObjects.Manager <File> files)
        {
            files = new IDObjects.Manager <File>(Config.Manager.KeySettingsForPaths, false);

            BinaryFile binaryFile = new BinaryFile();
            bool       result     = true;

            try
            {
                // We'll continue to handle 2.0 files in 2.0.2 since it's easy enough
                if (binaryFile.OpenForReading(filename, "2.0") == false)
                {
                    result = false;
                }
                else
                {
                    // [Int32: ID]
                    // [String: Path]
                    // [Byte: Type]
                    // [Int64: Last Modification in Ticks or 0]
                    // (if image)
                    //    [UInt32: Width in Pixels or 0 if unknown]
                    //    [UInt32: Height in Pixels or 0 if unknown]
                    // ...
                    // [Int32: 0]

                    int      id;
                    Path     path;
                    FileType type;
                    DateTime lastModification;
                    File     file;
                    uint     width, height;

                    for (;;)
                    {
                        id = binaryFile.ReadInt32();

                        if (id == 0)
                        {
                            break;
                        }

                        path             = binaryFile.ReadString();
                        type             = (FileType)binaryFile.ReadByte();
                        lastModification = new DateTime(binaryFile.ReadInt64());

                        if (type == FileType.Image)
                        {
                            if (binaryFile.Version < "2.0.2")
                            {
                                width  = 0;
                                height = 0;
                            }
                            else
                            {
                                width  = binaryFile.ReadUInt32();
                                height = binaryFile.ReadUInt32();
                            }

                            if (width == 0 || height == 0)
                            {
                                // If this file is from a different version of Natural Docs, no matter which one, reset the last modification
                                // time so they'll be reparsed and take another stab at getting the dimensions
                                if (binaryFile.Version != Engine.Instance.Version)
                                {
                                    lastModification = new DateTime(0);
                                }

                                file = new ImageFile(path, lastModification);
                            }
                            else
                            {
                                file = new ImageFile(path, lastModification, width, height);
                            }
                        }
                        else
                        {
                            file = new File(path, type, lastModification);
                        }

                        file.ID = id;
                        files.Add(file);
                    }
                }
            }
            catch
            {
                result = false;
            }
            finally
            {
                binaryFile.Close();
            }

            if (result == false)
            {
                files.Clear();
            }

            return(result);
        }
コード例 #2
0
ファイル: NICNT.cs プロジェクト: perivar/PresetConverter
        static readonly byte[] NKS_NICNT_TOC = new byte[] { 0x2F, 0x5C, 0x20, 0x4E, 0x49, 0x20, 0x46, 0x43, 0x20, 0x54, 0x4F, 0x43, 0x20, 0x20, 0x2F, 0x5C }; // /\ NI FC TOC  /\

        public static void Unpack(string inputFilePath, string outputDirectoryPath, bool doList, bool doVerbose)
        {
            using (BinaryFile bf = new BinaryFile(inputFilePath, BinaryFile.ByteOrder.LittleEndian, false))
            {
                var header = bf.ReadBytes(16);
                if (header.SequenceEqual(NKS_NICNT_MTD)) // 2F 5C 20 4E 49 20 46 43 20 4D 54 44 20 20 2F 5C   /\ NI FC MTD  /\
                {
                    bf.Seek(66, SeekOrigin.Begin);
                    string version = bf.ReadString(66, Encoding.Unicode).TrimEnd('\0');
                    Log.Information("Version: " + version);

                    string outputFileName = Path.GetFileNameWithoutExtension(inputFilePath);
                    if (!doList)
                    {
                        IOUtils.CreateDirectoryIfNotExist(Path.Combine(outputDirectoryPath, outputFileName));
                    }

                    // Save version in ContentVersion.txt
                    if (!doList)
                    {
                        IOUtils.WriteTextToFile(Path.Combine(outputDirectoryPath, outputFileName, "ContentVersion.txt"), version);
                    }

                    int unknown1 = bf.ReadInt32();
                    if (doVerbose)
                    {
                        Log.Debug("Unknown1: " + unknown1);
                    }

                    bf.Seek(144, SeekOrigin.Begin);

                    int startOffset = bf.ReadInt32();
                    Log.Information("Start Offset: " + startOffset);

                    int unknown3 = bf.ReadInt32();
                    if (doVerbose)
                    {
                        Log.Debug("Unknown3: " + unknown3);
                    }

                    bf.Seek(256, SeekOrigin.Begin);

                    string productHintsXml = bf.ReadStringNull();
                    Log.Information(string.Format("Read ProductHints Xml with length {0} characters.", productHintsXml.Length));
                    if (doVerbose)
                    {
                        Log.Debug("ProductHints Xml:\n" + productHintsXml);
                    }

                    // Save productHints as xml
                    if (!doList)
                    {
                        IOUtils.WriteTextToFile(Path.Combine(outputDirectoryPath, outputFileName, outputFileName + ".xml"), productHintsXml);
                    }

                    // get the product hints as an object
                    var productHints = ProductHintsFactory.ReadFromString(productHintsXml);
                    if (productHints != null && productHints.Product.Icon != null && productHints.Product.Icon.ImageBytes != null)
                    {
                        ProductHintsFactory.UpdateImageFromImageBytes(productHints);

                        var image       = productHints.Product.Icon.Image;
                        var imageFormat = productHints.Product.Icon.ImageFormat;
                        if (image != null && imageFormat != null)
                        {
                            Log.Information(string.Format("Found Icon in ProductHints Xml in {0} format. (Dimensions: {1} x {2}, Width: {1} pixels, Height: {2} pixels, Bit depth: {3} bpp)", imageFormat.Name, image.Width, image.Height, image.PixelType.BitsPerPixel));

                            // save icon to file
                            if (!doList)
                            {
                                var iconFileName = outputFileName + " Icon." + imageFormat.Name.ToLower();
                                var iconFilePath = Path.Combine(outputDirectoryPath, outputFileName, iconFileName);

                                if (doVerbose)
                                {
                                    Log.Debug("Saving Icon to: " + iconFilePath);
                                }

                                // save using ImageSharp
                                // var imageEncoder = image.GetConfiguration().ImageFormatsManager.FindEncoder(imageFormat);
                                // image.Save(iconFilePath, imageEncoder);

                                // save using image bytes
                                BinaryFile.ByteArrayToFile(iconFilePath, productHints.Product.Icon.ImageBytes);
                            }
                        }
                    }

                    bf.Seek(startOffset + 256, SeekOrigin.Begin);
                    var header2 = bf.ReadBytes(16);
                    if (header2.SequenceEqual(NKS_NICNT_MTD)) // 2F 5C 20 4E 49 20 46 43 20 4D 54 44 20 20 2F 5C   /\ NI FC MTD  /\
                    {
                        bf.ReadBytes(116);

                        long unknown4 = bf.ReadInt64();
                        if (doVerbose)
                        {
                            Log.Debug("Unknown4: " + unknown4);
                        }

                        bf.ReadBytes(4);

                        long unknown5 = bf.ReadInt64();
                        if (doVerbose)
                        {
                            Log.Debug("Unknown5: " + unknown5);
                        }

                        bf.ReadBytes(104);

                        long unknown6 = bf.ReadInt64();
                        if (doVerbose)
                        {
                            Log.Debug("Unknown6: " + unknown6);
                        }

                        var delimiter1 = bf.ReadBytes(8);
                        if (doVerbose)
                        {
                            Log.Debug("Delimiter1: " + StringUtils.ByteArrayToHexString(delimiter1));            // F0 F0 F0 F0 F0 F0 F0 F0
                        }
                        if (!delimiter1.SequenceEqual(new byte[] { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0 }))
                        {
                            Log.Error("Delimiter1 not as expected 'F0 F0 F0 F0 F0 F0 F0 F0' but got " + StringUtils.ToHexAndAsciiString(delimiter1));
                        }

                        long totalResourceCount = bf.ReadInt64();
                        Log.Information("Total Resource Count: " + totalResourceCount);

                        long totalResourceLength = bf.ReadInt64();
                        Log.Information("Total Resource Byte Length: " + totalResourceLength);

                        var resourceList = new List <NICNTResource>();
                        var header3      = bf.ReadBytes(16);
                        if (header3.SequenceEqual(NKS_NICNT_TOC)) // 2F 5C 20 4E 49 20 46 43 20 54 4F 43 20 20 2F 5C  /\ NI FC TOC  /\
                        {
                            bf.ReadBytes(600);

                            long lastEndIndex = 0;
                            for (int i = 0; i < totalResourceCount; i++)
                            {
                                var resource = new NICNTResource();

                                Log.Information("-------- Index: " + bf.Position + " --------");

                                long resCounter = bf.ReadInt64();
                                Log.Information("Resource Counter: " + resCounter);
                                resource.Count = resCounter;

                                bf.ReadBytes(16);

                                string resName = bf.ReadString(600, Encoding.Unicode).TrimEnd('\0');
                                Log.Information("Resource Name: " + resName);
                                resource.Name = resName;

                                long resUnknown = bf.ReadInt64();
                                if (doVerbose)
                                {
                                    Log.Debug("Resource Unknown: " + resUnknown);
                                }

                                long resEndIndex = bf.ReadInt64();
                                Log.Information("Resource End Index: " + resEndIndex);
                                resource.EndIndex = resEndIndex;

                                // store calculated length
                                if (lastEndIndex > 0)
                                {
                                    resource.Length = resEndIndex - lastEndIndex;
                                }
                                else
                                {
                                    // for the very first entry the end index is the same as the byte length
                                    resource.Length = resEndIndex;
                                }
                                Log.Information("Calculated Resource Byte Length: " + resource.Length);

                                lastEndIndex = resEndIndex;
                                resourceList.Add(resource);
                            }
                            Log.Information("-------- Index: " + bf.Position + " --------");

                            var delimiter2 = bf.ReadBytes(8);
                            if (doVerbose)
                            {
                                Log.Debug("Delimiter2: " + StringUtils.ByteArrayToHexString(delimiter2));            // F1 F1 F1 F1 F1 F1 F1 F1
                            }
                            if (!delimiter2.SequenceEqual(new byte[] { 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1 }))
                            {
                                Log.Error("Delimiter2 not as expected 'F1 F1 F1 F1 F1 F1 F1 F1' but got " + StringUtils.ToHexAndAsciiString(delimiter2));
                            }

                            long unknown13 = bf.ReadInt64();
                            if (doVerbose)
                            {
                                Log.Debug("Unknown13: " + unknown13);
                            }

                            long unknown14 = bf.ReadInt64();
                            if (doVerbose)
                            {
                                Log.Debug("Unknown14: " + unknown14);
                            }

                            var header4 = bf.ReadBytes(16);
                            if (header4.SequenceEqual(NKS_NICNT_TOC)) // 2F 5C 20 4E 49 20 46 43 20 54 4F 43 20 20 2F 5C  /\ NI FC TOC  /\
                            {
                                bf.ReadBytes(592);

                                if (!doList)
                                {
                                    IOUtils.CreateDirectoryIfNotExist(Path.Combine(outputDirectoryPath, outputFileName, "Resources"));
                                }

                                foreach (var res in resourceList)
                                {
                                    // convert the unix filename to a windows supported filename
                                    string escapedFileName = FromUnixFileNames(res.Name);

                                    // and add the counter in front
                                    string escapedFileNameWithNumber = string.Format("{0:D3}{1}", res.Count, escapedFileName);

                                    Log.Information(String.Format("Resource '{0}' @ position {1} [{2} bytes]", escapedFileNameWithNumber, bf.Position, res.Length));

                                    res.Data = bf.ReadBytes((int)res.Length);

                                    // if not only listing, save files
                                    if (!doList)
                                    {
                                        string     outputFilePath = Path.Combine(outputDirectoryPath, outputFileName, "Resources", escapedFileNameWithNumber);
                                        BinaryFile outBinaryFile  = new BinaryFile(outputFilePath, BinaryFile.ByteOrder.LittleEndian, true);

                                        outBinaryFile.Write(res.Data);
                                        outBinaryFile.Close();
                                    }
                                }
                            }
                            else
                            {
                                Log.Error(inputFilePath + ": Header4 not as expected '/\\ NI FC TOC  /\\' but got " + StringUtils.ToHexAndAsciiString(header4));
                            }
                        }
                        else
                        {
                            Log.Error(inputFilePath + ": Header3 not as expected '/\\ NI FC TOC  /\\' but got " + StringUtils.ToHexAndAsciiString(header3));
                        }
                    }
                    else
                    {
                        Log.Error(inputFilePath + ": Header2 not as expected '/\\ NI FC MTD  /\\' but got " + StringUtils.ToHexAndAsciiString(header2));
                    }
                }
                else
                {
                    Log.Error(inputFilePath + ": Header not as expected '/\\ NI FC MTD  /\\' but got " + StringUtils.ToHexAndAsciiString(header));
                }
            }
        }