Example #1
0
        public static TexEntry[] ReadEntries(byte[] fileData)
        {
            List<TexEntry> entries = new List<TexEntry>();

            var reader = new DataReader(fileData);

            // Unknown
            reader.ReadInt32();

            while (true)
            {
                var entry = new TexEntry();

                entry.CellOffset = reader.ReadInt32();
                entry.DirectoryOffset = reader.ReadInt32();
                entry.Size = reader.ReadInt32();

                if (entry.CellOffset < 0)
                    break;

                entries.Add(entry);
            }

            return entries.ToArray();
        }
Example #2
0
 private static string GetString(DataReader reader, int offset)
 {
     int tempOffset = reader.Offset;
     reader.SetOffset(offset);
     var value = reader.ReadZString();
     reader.SetOffset(tempOffset);
     return value;
 }
Example #3
0
 public void ReadEntries()
 {
     Entries.Clear();
     DataReader reader = new DataReader(FileData);
     Entry entry;
     while ((entry = readEntry(reader)) != null)
     {
         Entries.Add(entry);
     }
 }
Example #4
0
 Child readChild(DataReader reader)
 {
     int t = reader.ReadInt32();
     if (t == 0)
     {
         return null;
     }
     Child child = new Child();
     child.TextureOffset = t;
     child.VifOffset = reader.ReadInt32();
     child.VifLength = reader.ReadInt32();
     return child;
 }
Example #5
0
        public static List<ObjectData> Decode(byte[] data, int startOffset, int length)
        {
            var reader = new DataReader(data, startOffset, length);

            var count = reader.ReadInt16();
            var flags = reader.ReadInt16();
            var stringOffset = reader.ReadInt32();

            var objects = new List<ObjectData>(count);

            for (int i = 0; i < count; i++)
            {
                var obj = new ObjectData();

                int nameStringOffset = reader.ReadInt32();
                obj.Name = GetString(reader, stringOffset + nameStringOffset);
                short structSize = reader.ReadInt16(); // Size would be 20 if there isn't a stringoffsetarray, but usually 24 with an empty array
                obj.I6 = reader.ReadInt16();
                obj.Floats = new float[3];
                obj.Floats[0] = reader.ReadFloat();
                obj.Floats[1] = reader.ReadFloat();
                obj.Floats[2] = reader.ReadFloat();

                if (structSize > 20)
                {
                    var props = new List<string>();
                    for (int o =0; o < (structSize-20)/4; o++)
                    {
                        int propStringOffset = reader.ReadInt32();

                        if (propStringOffset == 0 && o == (structSize - 20) / 4 - 1)
                        {
                            // There is always a null at the end of the array
                            break;
                        }

                        props.Add(GetString(reader, stringOffset + propStringOffset));
                    }
                    obj.Properties = props;
                }

                objects.Add(obj);
            }

            return objects;
        }
Example #6
0
        public void ReadDirectory()
        {
            var reader = new DataReader(FileData, _startOffset, _dataLen);
            int numEntries = reader.ReadInt32();

            for (int entry = 0; entry < numEntries; ++entry) {
                if (EngineVersion.ReturnToArms == _engineVersion)
                {
                    int stringOffset = reader.ReadInt32();
                    int dataOffset = reader.ReadInt32();
                    int dataLength = reader.ReadInt32();

                    var tempOffset = reader.Offset;
                    reader.SetOffset(stringOffset);
                    var name = reader.ReadZString();
                    reader.SetOffset(tempOffset);

                    var info = new EntryInfo() { Name = name, StartOffset = dataOffset + _startOffset, Length = dataLength };
                    Directory[name] = info;
                }
                else
                {
                    int headerOffset = _startOffset + 4 + entry * 64;
                    String subfileName = DataUtil.GetString(FileData, headerOffset);

                    int subOffset = BitConverter.ToInt32(FileData, headerOffset + 56);
                    int subLen = BitConverter.ToInt32(FileData, headerOffset + 60);

                    var info = new EntryInfo()
                    {Name = subfileName, StartOffset = subOffset + _startOffset, Length = subLen};
                    Directory[subfileName] = info;
                }
            }
        }
Example #7
0
 Entry readEntry(DataReader reader)
 {
     Child child1 = readChild(reader);
     if (child1 == null)
     {
         return null;
     }
     Entry entry = new Entry();
     entry.children[0] = child1;
     entry.children[1] = readChild(reader);
     entry.children[2] = readChild(reader);
     entry.children[3] = readChild(reader);
     return entry;
 }
        public WorldData Decode(EngineVersion engineVersion, WorldTexFile texFile, ILogger log, byte[] data, int startOffset, int length)
        {
            WorldData worldData = new WorldData();

            var reader = new DataReader(data, startOffset, length);

            int numElements = reader.ReadInt32();       // 0

            reader.Skip(12); // Skipping 3 ints

            int numCols = reader.ReadInt32();           // x10
            int numRows = reader.ReadInt32();           // x14

            reader.Skip(12); // Skipping 3 ints         // x18 x1c x20
            int elementArrayStart = reader.ReadInt32(); // x24

            reader.Skip(8); // Skipping 2 ints
            int off38Cols = reader.ReadInt32();
            int off38Rows = reader.ReadInt32();
            int off38 = reader.ReadInt32();

            reader.Skip(28);
            int texll = reader.ReadInt32();
            int texur = reader.ReadInt32();
            int texX0 = texll % 100;
            int texY0 = texll / 100;
            int texX1 = texur % 100;
            int texY1 = texur / 100;

            reader.Skip(4);
            int worldTexOffsetsOffset = reader.ReadInt32();
            worldData.textureChunkOffsets = readTextureChunkOffsets(engineVersion, data, startOffset + worldTexOffsetsOffset, texX0, texY0, texX1+1, texY1);
            worldData.worldElements = new List<WorldElement>(numElements);

            for (int elementIdx = 0; elementIdx < numElements; ++elementIdx)
            {
                var element = new WorldElement();

                if (EngineVersion.ReturnToArms == engineVersion)
                {
                    reader.SetOffset(elementArrayStart + elementIdx * 0x3C);
                }
                else // Default to Dark Allience version
                {
                    reader.SetOffset(elementArrayStart + elementIdx * 0x38);
                }

                int vifDataOffset = reader.ReadInt32();

                if (EngineVersion.DarkAlliance == engineVersion)
                {
                    int tex2 = reader.ReadInt32();
                    if (tex2 != 0) {
                        log.LogLine("Tex2=" + tex2);
                    }
                }

                int vifLen = reader.ReadInt32();
                log.LogLine("-----------");
                log.LogLine("vifdata: " + vifDataOffset + ", " + vifLen);

                float x1 = reader.ReadFloat();
                float y1 = reader.ReadFloat();
                float z1 = reader.ReadFloat();
                float x2 = reader.ReadFloat();
                float y2 = reader.ReadFloat();
                float z2 = reader.ReadFloat();

                element.boundingBox = new Rect3D(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);

                log.LogLine("Bounding Box: " + element.boundingBox.ToString());

                int textureNum = reader.ReadInt32() / 0x40;
                log.LogLine("Texture Num: " + textureNum);

                int texCellxy = reader.ReadInt16();
                int y = texCellxy / 100;
                int x = texCellxy % 100;

                if (EngineVersion.ReturnToArms == engineVersion)
                {
                    x += texX0;
                    y += texY0;
                }

                if (textureNum != 0)
                {
                    if (EngineVersion.ReturnToArms == engineVersion)
                    {
                        element.Texture = texFile.GetBitmapRTA(x, y, textureNum);
                    }
                    else
                    {
                        element.Texture = texFile.GetBitmap(worldData.textureChunkOffsets[y, x], textureNum);
                    }
                }

                if (element.Texture != null)
                {
                    log.LogLine("Found in texture chunk: " + x + ", " + y);
                }

                var vifLogger = new StringLogger();
                int texWidth = 100;
                int texHeight = 100;
                if (element.Texture != null)
                {
                    texWidth = element.Texture.PixelWidth;
                    texHeight = element.Texture.PixelHeight;
                }

                byte nregs = data[startOffset + vifDataOffset + 0x10];
                int vifStartOffset = (nregs + 2) * 0x10;
                element.VifDataOffset = startOffset + vifDataOffset + vifStartOffset;
                element.VifDataLength = vifLen*0x10 - vifStartOffset;
                element.model = decodeModel(engineVersion, vifLogger, data, startOffset + vifDataOffset + vifStartOffset, vifLen * 0x10 - vifStartOffset, texWidth, texHeight);

                if (EngineVersion.ReturnToArms == engineVersion)
                {
                    int unk = reader.ReadInt16();
                    log.LogLine("Unknown: " + unk);
                }

                int posx = reader.ReadInt16();
                int posy = reader.ReadInt16();
                int posz = reader.ReadInt16();

                log.LogLine("Position : " + posx + ", " + posy + ", " + posz);

                element.pos = new Vector3D(posx / 16.0, posy / 16.0, posz / 16.0);

                if (EngineVersion.ReturnToArms == engineVersion)
                {
                    // Just a guess, maybe wrong.
                    element.pos = new Vector3D(posx / 16.0, posz / 16.0, posy / 16.0);
                }

                // I don't think RTA uses this flags scheme. From the data it looks like there are
                // 2 shorts (or possibly floats) following.

                int flags = reader.ReadInt32();

                if ((flags & 0x01) == 0)
                {
                    log.LogLine("Flags   : " + HexUtil.formatHexUShort(flags & 0xFFFF));
                    element.cosAlpha = (flags >> 16) / 32767.0;
                    element.sinAlpha = reader.ReadInt16() / 32767.0;
                    log.LogLine("cos alpha : " + element.cosAlpha);
                    log.LogLine("sin alpha : " + element.sinAlpha);
                    log.LogLine("alpha(cos, sin): " + Math.Acos(element.cosAlpha) * 180.0 / Math.PI + ", " + Math.Asin(element.sinAlpha) * 180.0 / Math.PI);

                    element.usesRotFlags = false;
                }
                else
                {
                    reader.ReadInt16();     // not necessary but makes the code more obvious.
                    log.LogLine("Flags   : " + HexUtil.formatHex(flags));
                    element.xyzRotFlags = (flags >> 16) & 7;
                    element.usesRotFlags = true;
                    log.LogLine("Rot Flags   : " + element.xyzRotFlags);
                }

                element.negYaxis = (flags & 0x40) == 0x40;

                if (EngineVersion.ReturnToArms == engineVersion)
                {
                    flags = 0;
                    element.usesRotFlags = true;
                    log.LogLine("Forcing flags to 0 until we know the format better");
                }

                worldData.worldElements.Add(element);
            }

            return worldData;
        }