Exemplo n.º 1
0
        private void WriteSsbh(SsbhFile file, bool isLastWrite)
        {
            foreach (var prop in file.GetType().GetProperties())
            {
                // Some more matl hacks.
                if (ParseTag.ShouldSkipProperty(prop))
                {
                    continue;
                }

                // Check for types that use offsets.
                if (prop.PropertyType == typeof(string))
                {
                    // TODO: Is this check necessary?
                    if (prop.GetValue(file) == null)
                    {
                        // Write placeholder relative offset.
                        Write(0L);
                        continue;
                    }
                    objectWriteQueue.Enqueue(new ObjectWriteInfo(prop.GetValue(file), (uint)Position));
                    // Write placeholder relative offset.
                    Write(0L);
                }
                else if (prop.PropertyType.IsArray)
                {
                    var array = (prop.GetValue(file) as Array);
                    if (array.Length > 0)
                    {
                        objectWriteQueue.Enqueue(new ObjectWriteInfo(array, (uint)Position));
                    }
                    else
                    {
                        objectWriteQueue.Enqueue(new ObjectWriteInfo(array));
                    }

                    // Write placeholder relative offset.
                    Write(0L);
                    Write((long)array.Length);
                }
                else if (prop.PropertyType == typeof(SsbhOffset))
                {
                    // HACK: for materials
                    var dataObject = file.GetType().GetProperty("DataObject").GetValue(file);
                    var matEntry   = new MaterialEntry(dataObject);
                    objectWriteQueue.Enqueue(new ObjectWriteInfo(matEntry, (uint)Position));
                    // Write placeholder relative offset.
                    Write(0L);
                }
                else
                {
                    WriteProperty(prop.GetValue(file), isLastWrite);
                }
            }
        }
Exemplo n.º 2
0
        public void WriteSsbhFile(SsbhFile file)
        {
            // The header is 16-byte aligned.
            Write(new char[] { 'H', 'B', 'S', 'S' });
            // TODO: This value is always present.
            Write(0x40);
            Pad(0x10);

            // write file contents
            AddSsbhFile(file);
            // TODO: padding?
            //exporter.Pad(0x4);
        }
Exemplo n.º 3
0
        private bool Skip(SsbhFile file, PropertyInfo prop)
        {
            object[] attrs = prop.GetCustomAttributes(true);
            bool     skip  = false;

            foreach (object attr in attrs)
            {
                if (attr is ParseTag tag)
                {
                    if (tag.Ignore)
                    {
                        return(true);
                    }
                }
            }
            return(skip);
        }
Exemplo n.º 4
0
        public static void WriteSsbhFile(string fileName, SsbhFile file, bool writeHeader = true)
        {
            using (SsbhExporter exporter = new SsbhExporter(new FileStream(fileName, FileMode.Create)))
            {
                // write ssbh header
                if (writeHeader)
                {
                    exporter.Write(new char[] { 'H', 'B', 'S', 'S' });
                    exporter.Write(0x40);
                    exporter.Pad(0x10);
                }

                // write file contents
                exporter.AddSsbhFile(file);
                exporter.Pad(4);
            }
        }
Exemplo n.º 5
0
        public static void WriteSsbhFile(string fileName, SsbhFile file, bool writeHeader = true)
        {
            using (SsbhExporter exporter = new SsbhExporter(new FileStream(fileName, FileMode.Create)))
            {
                // write ssbh header
                if (writeHeader)
                {
                    // The header is 16-byte aligned.
                    exporter.Write(new char[] { 'H', 'B', 'S', 'S' });
                    // TODO: This value is always present.
                    exporter.Write(0x40);
                    exporter.Pad(0x10);
                }

                // write file contents
                exporter.AddSsbhFile(file);
                exporter.Pad(4);
            }
        }
Exemplo n.º 6
0
        public bool TryParse(out SsbhFile file)
        {
            file = null;
            if (FileSize < 4)
            {
                return(false);
            }

            string fileMagic = new string(ReadChars(4));

            Seek(Position - 4);
            if (fileMagic.Equals("HBSS"))
            {
                Seek(0x10);
                fileMagic = new string(ReadChars(4));
                Seek(0x10);
            }

            if (parseMethodByMagic.ContainsKey(fileMagic))
            {
                file = parseMethodByMagic[fileMagic](this);
                return(true);
            }

            // The type is not known, so do a very slow check to find it.
            foreach (var type in issbhTypes)
            {
                if (type.GetCustomAttributes(typeof(SsbhFileAttribute), true).FirstOrDefault() is SsbhFileAttribute attr)
                {
                    if (attr.Magic.Equals(fileMagic))
                    {
                        MethodInfo parseMethod = typeof(SsbhParser).GetMethod("Parse");
                        parseMethod = parseMethod.MakeGenericMethod(type);

                        file = (SsbhFile)parseMethod.Invoke(this, null);
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 7
0
        private void AddSsbhFile(SsbhFile file)
        {
            objectWriteQueue.Enqueue(new ObjectWriteInfo(file));

            while (objectWriteQueue.Count > 0)
            {
                var writeInfo = objectWriteQueue.Dequeue();
                if (writeInfo.Data == null)
                {
                    continue;
                }

                // 8-byte alignment for arrays and matl data objects.
                if (writeInfo.Data is Array || (writeInfo.Data is MaterialEntry entry && entry.Object is MatlAttribute.MatlString))
                {
                    Pad(0x8);
                }

                // 4-byte alignment for strings.
                if (writeInfo.Data is string)
                {
                    Pad(0x4);
                }

                // Fill in the temporary relative offset with the correct value.
                if (writeInfo.RelativeOffsetStartPosition.HasValue)
                {
                    WriteRelativeOffset(writeInfo);
                }

                var isLastWrite = objectWriteQueue.Count == 0;
                if (writeInfo.Data is Array array)
                {
                    WriteArray(array, isLastWrite);
                }
                else
                {
                    WriteProperty(writeInfo.Data, isLastWrite);
                }
            }
        }
Exemplo n.º 8
0
        private void AddSsbhFile(SsbhFile file)
        {
            objectQueue.AddFirst(file);
            while (objectQueue.Count > 0)
            {
                var obj = objectQueue.First();
                objectQueue.RemoveFirst();
                if (obj == null)
                {
                    continue;
                }

                // I guess?
                if (obj is Array || obj is MaterialEntry entry && entry.Object is Formats.Materials.MatlAttribute.MatlString)
                {
                    Pad(0x8);
                }

                // not sure if 4 or 8
                if (obj is string)
                {
                    Pad(0x4);
                }

                if (objectOffset.ContainsValue(obj))
                {
                    long key = objectOffset.FirstOrDefault(x => x.Value == obj).Key;
                    if (key != 0)
                    {
                        long temp = Position;
                        BaseStream.Position = key;
                        WriteProperty(temp - key);
                        BaseStream.Position = temp;
                        objectOffset.Remove((uint)key);
                    }
                }

                if (obj is Array array)
                {
                    if (array.GetType() == typeof(byte[]))
                    {
                        foreach (byte o in array)
                        {
                            Write(o);
                        }
                    }
                    else
                    {
                        LinkedList <object> objectQueueTemp = objectQueue;
                        objectQueue = new LinkedList <object>();
                        foreach (object o in array)
                        {
                            WriteProperty(o);
                        }
                        foreach (object o in objectQueueTemp)
                        {
                            objectQueue.AddLast(o);
                        }
                    }
                }
                else
                {
                    WriteProperty(obj);
                }
            }
        }
Exemplo n.º 9
0
        private void WriteSsbhFile(SsbhFile file)
        {
            foreach (var prop in file.GetType().GetProperties())
            {
                if (Skip(file, prop))
                {
                    continue;
                }

                if (prop.PropertyType == typeof(string))
                {
                    if (prop.GetValue(file) == null)
                    {
                        Write((long)0);
                        continue;
                    }
                    objectQueue.AddLast(prop.GetValue(file));
                    objectOffset.Add((uint)Position, prop.GetValue(file));
                    Write((long)0);
                }
                else if (prop.PropertyType.IsArray)
                {
                    var  array  = (prop.GetValue(file) as Array);
                    bool inline = false;
                    if (prop.GetCustomAttribute(typeof(ParseTag)) != null)
                    {
                        inline = ((ParseTag)prop.GetCustomAttribute(typeof(ParseTag))).InLine;
                    }

                    if (!inline)
                    {
                        if (array.Length > 0)
                        {
                            objectOffset.Add((uint)Position, array);
                        }
                        objectQueue.AddLast(array);
                        Write((long)0);
                        Write((long)array.Length);
                    }
                    else
                    {
                        // inline array
                        foreach (object o in array)
                        {
                            WriteProperty(o);
                        }
                    }
                }
                else if (prop.PropertyType == typeof(SsbhOffset))
                {
                    // HACK: for materials
                    var dataObject = file.GetType().GetProperty("DataObject").GetValue(file);
                    var matentry   = new MaterialEntry(dataObject);
                    objectOffset.Add((uint)Position, matentry);
                    objectQueue.AddLast(matentry);
                    Write((long)0);
                }
                else
                {
                    WriteProperty(prop.GetValue(file));
                }
            }


            // TODO: Post Write is only used for materials.
            file.PostWrite(this);
        }