Example #1
0
        public LocResFile(BinaryReader reader)
        {
            FGuid MagicNumber = default;

            if (reader.BaseStream.Length >= Marshal.SizeOf <FGuid>())
            {
                MagicNumber = new FGuid(reader);
            }

            LocResVersion VersionNumber = LocResVersion.LEGACY;

            if (MagicNumber == LocResMagic)
            {
                VersionNumber = (LocResVersion)reader.ReadByte();
            }
            else
            {
                // Legacy LocRes files lack the magic number, assume that's what we're dealing with, and seek back to the start of the file
                reader.BaseStream.Seek(0, SeekOrigin.Begin);
            }

            if (VersionNumber > LocResVersion.LATEST)
            {
                throw new IOException($"LocRes file is too new to be loaded! (File Version: {(byte)VersionNumber}, Loader Version: {(byte)LocMetaVersion.LATEST})");
            }

            // Read the localized string array
            FTextLocalizationResourceString[] LocalizedStringArray = new FTextLocalizationResourceString[0];
            if (VersionNumber >= LocResVersion.COMPACT)
            {
                long LocalizedStringArrayOffset = -1; // INDEX_NONE
                LocalizedStringArrayOffset = reader.ReadInt64();

                if (LocalizedStringArrayOffset != -1)
                {
                    if (VersionNumber >= LocResVersion.OPTIMIZED)
                    {
                        long CurrentFileOffset = reader.BaseStream.Position;
                        reader.BaseStream.Seek(LocalizedStringArrayOffset, SeekOrigin.Begin);
                        LocalizedStringArray = reader.ReadTArray(() => new FTextLocalizationResourceString(reader));
                        reader.BaseStream.Seek(CurrentFileOffset, SeekOrigin.Begin);
                    }
                    else
                    {
                        string[] TmpLocalizedStringArray;

                        long CurrentFileOffset = reader.BaseStream.Position;
                        reader.BaseStream.Seek(LocalizedStringArrayOffset, SeekOrigin.Begin);
                        TmpLocalizedStringArray = reader.ReadTArray(() => CleanString(AssetReader.read_string(reader)));
                        reader.BaseStream.Seek(CurrentFileOffset, SeekOrigin.Begin);

                        LocalizedStringArray = new FTextLocalizationResourceString[TmpLocalizedStringArray.Length];
                        for (int i = 0; i < TmpLocalizedStringArray.Length; i++)
                        {
                            LocalizedStringArray[i] = new FTextLocalizationResourceString()
                            {
                                String = TmpLocalizedStringArray[i], RefCount = -1
                            };
                        }
                    }
                }
            }

            // Read entries count
            if (VersionNumber >= LocResVersion.OPTIMIZED)
            {
                uint EntriesCount = reader.ReadUInt32();
                // No need for initializer
                // Link: https://github.com/EpicGames/UnrealEngine/blob/7d9919ac7bfd80b7483012eab342cb427d60e8c9/Engine/Source/Runtime/Core/Private/Internationalization/TextLocalizationResource.cpp#L266
            }

            // Read namespace count
            uint NamespaceCount = reader.ReadUInt32();

            for (uint i = 0; i < NamespaceCount; i++)
            {
                // Read namespace
                FTextKey Namespace;
                if (VersionNumber >= LocResVersion.OPTIMIZED)
                {
                    Namespace = new FTextKey(reader);
                }
                else
                {
                    Namespace = new FTextKey(CleanString(AssetReader.read_string(reader)));
                }

                var Entries = new Dictionary <string, string>();

                // Read key count
                uint KeyCount = reader.ReadUInt32();

                for (uint j = 0; j < KeyCount; j++)
                {
                    // Read key
                    FTextKey Key;
                    if (VersionNumber >= LocResVersion.OPTIMIZED)
                    {
                        Key = new FTextKey(reader);
                    }
                    else
                    {
                        Key = new FTextKey(CleanString(AssetReader.read_string(reader)));
                    }

                    FEntry NewEntry;
                    NewEntry.SourceStringHash = reader.ReadUInt32();

                    if (VersionNumber >= LocResVersion.COMPACT)
                    {
                        int LocalizedStringIndex = reader.ReadInt32();

                        if (LocalizedStringArray.Length > LocalizedStringIndex)
                        {
                            // Steal the string if possible
                            FTextLocalizationResourceString LocalizedString = LocalizedStringArray[LocalizedStringIndex];
                            if (LocalizedString.RefCount == 1)
                            {
                                NewEntry.LocalizedString = LocalizedString.String;
                                LocalizedString.RefCount--;
                            }
                            else
                            {
                                NewEntry.LocalizedString = LocalizedString.String;
                                if (LocalizedString.RefCount != -1)
                                {
                                    LocalizedString.RefCount--;
                                }
                            }
                        }
                        else
                        {
                            throw new IOException($"LocRes has an invalid localized string index for namespace '{Namespace}' and key '{Key}'. This entry will have no translation.");
                        }
                    }
                    else
                    {
                        NewEntry.LocalizedString = CleanString(AssetReader.read_string(reader));
                    }

                    Entries.Add(Key.String, NewEntry.LocalizedString);
                }
                this.Entries.Add(Namespace.String, Entries);
            }
        }
Example #2
0
        public LocResReader(BinaryReader reader)
        {
            var MagicNumber = new FGuid(reader);

            var VersionNumber = Version.LEGACY;

            if (MagicNumber == Magic)
            {
                VersionNumber = (Version)reader.ReadByte();
            }
            else
            {
                // Legacy LocRes files lack the magic number, assume that's what we're dealing with, and seek back to the start of the file
                reader.BaseStream.Seek(0, SeekOrigin.Begin);
            }

            if (VersionNumber > Version.LATEST)
            {
                throw new IOException($"LocRes file is too new to be loaded! (File Version: {(byte)VersionNumber}, Loader Version: {(byte)LocMetaReader.Version.LATEST})");
            }

            // Read the localized string array
            FTextLocalizationResourceString[] LocalizedStringArray = Array.Empty <FTextLocalizationResourceString>();
            if (VersionNumber >= Version.COMPACT)
            {
                long LocalizedStringArrayOffset = -1; // INDEX_NONE
                LocalizedStringArrayOffset = reader.ReadInt64();

                if (LocalizedStringArrayOffset != -1)
                {
                    if (VersionNumber >= Version.OPTIMIZED)
                    {
                        long CurrentFileOffset = reader.BaseStream.Position;
                        reader.BaseStream.Seek(LocalizedStringArrayOffset, SeekOrigin.Begin);
                        LocalizedStringArray = reader.ReadTArray(() => new FTextLocalizationResourceString(reader));
                        reader.BaseStream.Seek(CurrentFileOffset, SeekOrigin.Begin);
                    }
                    else
                    {
                        string[] TmpLocalizedStringArray;

                        long CurrentFileOffset = reader.BaseStream.Position;
                        reader.BaseStream.Seek(LocalizedStringArrayOffset, SeekOrigin.Begin);
                        TmpLocalizedStringArray = reader.ReadTArray(() => reader.ReadFString());
                        reader.BaseStream.Seek(CurrentFileOffset, SeekOrigin.Begin);

                        LocalizedStringArray = new FTextLocalizationResourceString[TmpLocalizedStringArray.Length];
                        for (int i = 0; i < TmpLocalizedStringArray.Length; i++)
                        {
                            LocalizedStringArray[i] = new FTextLocalizationResourceString(TmpLocalizedStringArray[i], -1);
                        }
                    }
                }
            }

            // Read entries count
            if (VersionNumber >= Version.OPTIMIZED)
            {
                uint EntriesCount = reader.ReadUInt32();
                // No need for initializer
                // Link: https://github.com/EpicGames/UnrealEngine/blob/7d9919ac7bfd80b7483012eab342cb427d60e8c9/Engine/Source/Runtime/Core/Private/Internationalization/TextLocalizationResource.cpp#L266
            }

            // Read namespace count
            uint NamespaceCount = reader.ReadUInt32();

            for (uint i = 0; i < NamespaceCount; i++)
            {
                // Read namespace
                if (VersionNumber >= Version.OPTIMIZED)
                {
                    reader.ReadUInt32(); // StrHash
                }
                var Namespace = reader.ReadFString();

                var Entries = new Dictionary <string, string>();

                // Read key count
                uint KeyCount = reader.ReadUInt32();

                for (uint j = 0; j < KeyCount; j++)
                {
                    // Read key
                    if (VersionNumber >= Version.OPTIMIZED)
                    {
                        reader.ReadUInt32(); // StrHash
                    }
                    var Key = reader.ReadFString();

                    reader.ReadUInt32(); // SourceStringHash

                    string EntryLocalizedString;
                    if (VersionNumber >= Version.COMPACT)
                    {
                        int LocalizedStringIndex = reader.ReadInt32();

                        if (LocalizedStringArray.Length > LocalizedStringIndex)
                        {
                            // Steal the string if possible
                            ref var LocalizedString = ref LocalizedStringArray[LocalizedStringIndex];
                            if (LocalizedString.RefCount == 1)
                            {
                                EntryLocalizedString = LocalizedString.String;
                                LocalizedString.RefCount--;
                            }
                            else
                            {
                                EntryLocalizedString = LocalizedString.String;
                                if (LocalizedString.RefCount != -1)
                                {
                                    LocalizedString.RefCount--;
                                }
                            }
                        }
                        else
                        {
                            throw new IOException($"LocRes has an invalid localized string index for namespace '{Namespace}' and key '{Key}'. This entry will have no translation.");
                        }
                    }
Example #3
0
        public LocResReader(BinaryReader reader)
        {
            var MagicNumber = new FGuid(reader);

            var VersionNumber = Version.Legacy;

            if (MagicNumber == Magic)
            {
                VersionNumber = (Version)reader.ReadByte();
            }
            else
            {
                // Legacy LocRes files lack the magic number, assume that's what we're dealing with, and seek back to the start of the file
                reader.BaseStream.Seek(0, SeekOrigin.Begin);
            }

            if (VersionNumber > Version.Latest)
            {
                throw new IOException($"LocRes file is too new to be loaded! (File Version: {(byte)VersionNumber}, Loader Version: {(byte)LocMetaReader.Version.LATEST})");
            }

            // Read the localized string array
            FTextLocalizationResourceString[] LocalizedStringArray = Array.Empty <FTextLocalizationResourceString>();
            if (VersionNumber >= Version.Compact)
            {
                long LocalizedStringArrayOffset = -1; // INDEX_NONE
                LocalizedStringArrayOffset = reader.ReadInt64();

                if (LocalizedStringArrayOffset != -1)
                {
                    long CurrentFileOffset = reader.BaseStream.Position;
                    reader.BaseStream.Seek(LocalizedStringArrayOffset, SeekOrigin.Begin);

                    if (VersionNumber >= Version.Optimized_CRC32)
                    {
                        LocalizedStringArray = reader.ReadTArray(() => new FTextLocalizationResourceString(reader));
                        reader.BaseStream.Seek(CurrentFileOffset, SeekOrigin.Begin);
                    }
                    else
                    {
                        string[] TmpLocalizedStringArray;
                        TmpLocalizedStringArray = reader.ReadTArray(() => reader.ReadFString());
                        reader.BaseStream.Seek(CurrentFileOffset, SeekOrigin.Begin);

                        LocalizedStringArray = new FTextLocalizationResourceString[TmpLocalizedStringArray.Length];
                        for (int i = 0; i < TmpLocalizedStringArray.Length; i++)
                        {
                            LocalizedStringArray[i] = new FTextLocalizationResourceString(TmpLocalizedStringArray[i], -1);
                        }
                    }
                }
            }

            if (VersionNumber >= Version.Optimized_CRC32)
            {
                reader.ReadUInt32(); // EntriesCount
            }
            // Read namespace count
            uint NamespaceCount = reader.ReadUInt32();

            for (uint i = 0; i < NamespaceCount; i++)
            {
                if (VersionNumber >= Version.Optimized_CRC32)
                {
                    reader.ReadUInt32(); // StrHash
                }
                string Namespace = reader.ReadFString();
                uint   KeyCount  = reader.ReadUInt32();
                Dictionary <string, string> Entries = new Dictionary <string, string>((int)KeyCount);
                for (uint j = 0; j < KeyCount; j++)
                {
                    // Read key
                    if (VersionNumber >= Version.Optimized_CRC32)
                    {
                        reader.ReadUInt32(); // StrHash
                    }
                    string Key = reader.ReadFString();
                    reader.ReadUInt32(); // SourceStringHash

                    string EntryLocalizedString;
                    if (VersionNumber >= Version.Compact)
                    {
                        int LocalizedStringIndex = reader.ReadInt32();

                        if (LocalizedStringArray.Length > LocalizedStringIndex)
                        {
                            // Steal the string if possible
                            ref var LocalizedString = ref LocalizedStringArray[LocalizedStringIndex];
                            if (LocalizedString.RefCount == 1)
                            {
                                EntryLocalizedString = LocalizedString.String;
                                LocalizedString.RefCount--;
                            }
                            else
                            {
                                EntryLocalizedString = LocalizedString.String;
                                if (LocalizedString.RefCount != -1)
                                {
                                    LocalizedString.RefCount--;
                                }
                            }
                        }
                        else
                        {
                            throw new IOException($"LocRes has an invalid localized string index for namespace '{Namespace}' and key '{Key}'. This entry will have no translation.");
                        }
                    }