Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="gr"></param>
        /// <param name="gr2"></param>
        /// <param name="sb"></param>
        /// <param name="swe"></param>
        /// <returns></returns>
        public static bool ParseInitialSpellsOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            sb.AppendLine("Packet offset " + gr.BaseStream.Position.ToString("X2"));
            sb.AppendLine("Opcode SMSG_INITIAL_SPELLS (0x012A)");

            byte unk1 = gr2.ReadByte();

            sb.AppendLine("unk byte " + unk1);

            ushort spells_count = gr2.ReadUInt16();

            sb.AppendLine("Spells count " + spells_count);
            for (ushort i = 0; i < spells_count; i++)
            {
                ushort spellid = gr2.ReadUInt16();
                ushort slotid  = gr2.ReadUInt16();
                sb.AppendLine("Spell ID " + spellid + ", slot " + slotid.ToString("X2"));
            }

            ushort cooldowns_count = gr2.ReadUInt16();

            sb.AppendLine("Cooldowns count " + cooldowns_count);
            for (ushort i = 0; i < cooldowns_count; i++)
            {
                ushort spellid       = gr2.ReadUInt16();
                ushort itemid        = gr2.ReadUInt16();
                ushort spellcategory = gr2.ReadUInt16();
                uint   cooldown1     = gr2.ReadUInt32();
                uint   cooldown2     = gr2.ReadUInt32();
                sb.AppendLine("Spell Cooldown: spell id " + spellid + ", itemid " + itemid + ", spellcategory " + spellcategory + ", cooldown1 " + cooldown1 + ", cooldown2 " + cooldown2);
            }
            return(true);
        }
Пример #2
0
        /// <summary>
        /// Builds a 4-color color table for a DXT1-compressed 4x4 block of texels and then decodes the texels.
        /// </summary>
        /// <remarks>See https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC1 </remarks>
        static Color32[] DecodeDXT1TexelBlock(GenericReader r, bool containsAlpha)
        {
            // Create the color table.
            var colorTable = new Color[4];

            colorTable[0] = r.ReadUInt16().B565ToColor();
            colorTable[1] = r.ReadUInt16().B565ToColor();
            if (!containsAlpha)
            {
                colorTable[2] = Color.Lerp(colorTable[0], colorTable[1], 1.0f / 3);
                colorTable[3] = Color.Lerp(colorTable[0], colorTable[1], 2.0f / 3);
            }
            else
            {
                colorTable[2] = Color.Lerp(colorTable[0], colorTable[1], 1.0f / 2);
                colorTable[3] = new Color(0, 0, 0, 0);
            }
            // Calculate pixel colors.
            return(DecodeDXT1TexelBlock(r, colorTable));
        }
Пример #3
0
        /// <summary>
        /// Decodes a DXT3-compressed 4x4 block of texels.
        /// </summary>
        /// <remarks>See https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC2 </remarks>
        static Color32[] DecodeDXT3TexelBlock(GenericReader r)
        {
            // Read compressed pixel alphas.
            var compressedAlphas = new byte[16];

            for (var rowIndex = 0; rowIndex < 4; rowIndex++)
            {
                var compressedAlphaRow = r.ReadUInt16();
                for (var columnIndex = 0; columnIndex < 4; columnIndex++)
                {
                    // Each compressed alpha is 4 bits.
                    compressedAlphas[(4 * rowIndex) + columnIndex] = (byte)((compressedAlphaRow >> (columnIndex * 4)) & 0xF);
                }
            }
            // Calculate pixel alphas.
            var alphas = new byte[16];

            for (var i = 0; i < 16; i++)
            {
                var alphaPercent = (float)compressedAlphas[i] / 15;
                alphas[i] = (byte)Mathf.RoundToInt(alphaPercent * 255);
            }
            // Create the color table.
            var colorTable = new Color[4];

            colorTable[0] = r.ReadUInt16().B565ToColor();
            colorTable[1] = r.ReadUInt16().B565ToColor();
            colorTable[2] = Color.Lerp(colorTable[0], colorTable[1], 1.0f / 3);
            colorTable[3] = Color.Lerp(colorTable[0], colorTable[1], 2.0f / 3);
            // Calculate pixel colors.
            var colors = DecodeDXT1TexelBlock(r, colorTable);

            for (var i = 0; i < 16; i++)
            {
                colors[i].a = alphas[i];
            }
            return(colors);
        }
Пример #4
0
        public readonly uint AnimationTimerRelated; // Animation timer value

        public SiMaterial(GenericReader r)
        {
            TextureId             = r.ReadUInt16();
            Flags                 = r.ReadUInt16();
            SubtextureCount       = r.ReadUInt16();
            Flags2                = r.ReadUInt16();
            FirstFaceId           = r.ReadUInt16();
            FaceCount             = r.ReadUInt16();
            DefaultAlpha          = r.ReadByte();
            ModifiedAlpha         = r.ReadByte();
            AnimationStart        = r.ReadByte();
            AnimationEnd          = r.ReadByte();
            CurFrame              = r.ReadByte();
            AnimationSpeed        = r.ReadByte();
            AnimationType         = r.ReadByte();
            PlaybackDirection     = r.ReadByte();
            AnimationTimerRelated = r.ReadUInt32();
        }
Пример #5
0
        /// <summary>
        /// Packet header parser.
        /// </summary>
        /// <param name="gr">Main stream reader.</param>
        /// <param name="sw">Data stream writer.</param>
        /// <param name="swe">Error logger writer.</param>
        /// <param name="data">Data logger writer.</param>
        /// <param name="hex">HEX logger writer.</param>
        /// <returns>Successful</returns>
        private static bool ParseHeader(GenericReader gr, StreamWriter sw, StreamWriter swe, StreamWriter data, StreamWriter hex)
        {
            StringBuilder sb = new StringBuilder();

            int datasize = gr.ReadInt32();

            //sb.AppendLine("Packet offset " + (gr.BaseStream.Position - 4).ToString("X2"));

            //sb.AppendLine("Packet number: " + packet);

            //sb.AppendLine("Data size " + datasize);

            byte[]        temp = gr.ReadBytes(datasize);
            MemoryStream  ms   = new MemoryStream(temp);
            GenericReader gr2  = new GenericReader(ms);

            uint    id        = 0;
            uint    sess_id   = 0;
            string  time      = "";
            byte    direction = 0; // 0-CMSG, 1-SMSG
            OpCodes opcode    = OpCodes.MSG_NULL_ACTION;

            id        = gr2.ReadUInt32();
            sess_id   = gr2.ReadUInt32();
            time      = gr2.ReadStringNull();
            direction = gr2.ReadByte();
            opcode    = (OpCodes)gr2.ReadUInt16();

            long cur_pos = gr2.BaseStream.Position;

            HexLike(gr2, hex, id, sess_id, time, direction, opcode);

            gr2.BaseStream.Position = cur_pos;

            switch (opcode)
            {
            /*case OpCodes.SMSG_MONSTER_MOVE:
             *  OpcodeParser.ParseMonsterMoveOpcode(gr, gr2, sb, swe, direction);
             *  break;*/
            /*case OpCodes.SMSG_INITIAL_SPELLS:
             *  OpcodeParser.ParseInitialSpellsOpcode(gr, gr2, sb, swe, direction);
             *  break;
             * case OpCodes.SMSG_AUCTION_LIST_RESULT:
             *  OpcodeParser.ParseAuctionListResultOpcode(gr, gr2, sb, swe, direction);
             *  break;*/
            /*case OpCodes.SMSG_PARTY_MEMBER_STATS:
             * case OpCodes.SMSG_PARTY_MEMBER_STATS_FULL:
             *  OpcodeParser.ParsePartyMemberStatsOpcode(gr, gr2, sb, swe, direction);
             *  break;*/
            case OpCodes.SMSG_UPDATE_OBJECT:
            case OpCodes.SMSG_COMPRESSED_UPDATE_OBJECT:
                if (opcode == OpCodes.SMSG_COMPRESSED_UPDATE_OBJECT)
                {
                    gr2 = A9.Decompress(gr2);
                    gr2.BaseStream.Position = 0;
                    hex.WriteLine("Decompressed SMSG_COMPRESSED_UPDATE_OBJECT:");
                    HexLike(gr2, hex, id, sess_id, time, direction, OpCodes.SMSG_UPDATE_OBJECT);
                    gr2.BaseStream.Position = 0;
                }
                A9.ParseUpdatePacket(gr, gr2, sb, swe);
                break;

                /*case OpCodes.SMSG_SPELLNONMELEEDAMAGELOG:
                 *  OpcodeParser.ParseSpellNonMeleeDamageLogOpcode(gr, gr2, sb, swe, direction);
                 *  break;
                 * case OpCodes.SMSG_SPELLLOGEXECUTE:
                 *  OpcodeParser.ParseSpellLogExecuteOpcode(gr, gr2, sb, swe, direction);
                 *  break;*/
                /*case OpCodes.SMSG_LOGIN_SETTIMESPEED:
                 *  OpcodeParser.ParseLoginSetTimeSpeedOpcode(gr, gr2, sb, swe, direction);
                 *  break;
                 * case OpCodes.SMSG_TRAINER_LIST:
                 *  OpcodeParser.ParseTrainerListOpcode(gr, gr2, sb, swe, direction);
                 *  break;
                 * case OpCodes.SMSG_ATTACKERSTATEUPDATE:
                 *  OpcodeParser.ParseAttackerStateUpdateOpcode(gr, gr2, sb, swe, direction);
                 *  break;
                 * case OpCodes.MSG_CORPSE_QUERY:
                 *  OpcodeParser.ParseCorpseQueryOpcode(gr, gr2, sb, swe, direction);
                 *  break;
                 * case OpCodes.SMSG_LOGIN_VERIFY_WORLD:
                 *  OpcodeParser.ParseLoginVerifyWorldOpcode(gr, gr2, sb, swe, direction);
                 *  break;
                 * default:    // unhandled opcode
                 *  return false;*/
            }

            if (sb.ToString().Length != 0)
            {
                sw.WriteLine(sb.ToString());
            }

            ms.Close();
            gr2.Close();

            return(true);
        }
Пример #6
0
        /// <summary>
        /// Decodes a DXT5-compressed 4x4 block of texels.
        /// </summary>
        /// <remarks>See https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC3 </remarks>
        static Color32[] DecodeDXT5TexelBlock(GenericReader r)
        {
            // Create the alpha table.
            var alphaTable = new float[8];

            alphaTable[0] = r.ReadByte();
            alphaTable[1] = r.ReadByte();
            if (alphaTable[0] > alphaTable[1])
            {
                for (var i = 0; i < 6; i++)
                {
                    alphaTable[2 + i] = Mathf.Lerp(alphaTable[0], alphaTable[1], (float)(1 + i) / 7);
                }
            }
            else
            {
                for (var i = 0; i < 4; i++)
                {
                    alphaTable[2 + i] = Mathf.Lerp(alphaTable[0], alphaTable[1], (float)(1 + i) / 5);
                }
                alphaTable[6] = 0;
                alphaTable[7] = 255;
            }

            // Read pixel alpha indices.
            var alphaIndices        = new uint[16];
            var alphaIndexBytesRow0 = new byte[3];

            r.Read(alphaIndexBytesRow0, 0, alphaIndexBytesRow0.Length); Array.Reverse(alphaIndexBytesRow0); // Take care of little-endianness.
            var alphaIndexBytesRow1 = new byte[3];

            r.Read(alphaIndexBytesRow1, 0, alphaIndexBytesRow1.Length); Array.Reverse(alphaIndexBytesRow1); // Take care of little-endianness.
            const uint bitsPerAlphaIndex = 3U;

            alphaIndices[0]  = (uint)Utils.GetBits(21, bitsPerAlphaIndex, alphaIndexBytesRow0);
            alphaIndices[1]  = (uint)Utils.GetBits(18, bitsPerAlphaIndex, alphaIndexBytesRow0);
            alphaIndices[2]  = (uint)Utils.GetBits(15, bitsPerAlphaIndex, alphaIndexBytesRow0);
            alphaIndices[3]  = (uint)Utils.GetBits(12, bitsPerAlphaIndex, alphaIndexBytesRow0);
            alphaIndices[4]  = (uint)Utils.GetBits(9, bitsPerAlphaIndex, alphaIndexBytesRow0);
            alphaIndices[5]  = (uint)Utils.GetBits(6, bitsPerAlphaIndex, alphaIndexBytesRow0);
            alphaIndices[6]  = (uint)Utils.GetBits(3, bitsPerAlphaIndex, alphaIndexBytesRow0);
            alphaIndices[7]  = (uint)Utils.GetBits(0, bitsPerAlphaIndex, alphaIndexBytesRow0);
            alphaIndices[8]  = (uint)Utils.GetBits(21, bitsPerAlphaIndex, alphaIndexBytesRow1);
            alphaIndices[9]  = (uint)Utils.GetBits(18, bitsPerAlphaIndex, alphaIndexBytesRow1);
            alphaIndices[10] = (uint)Utils.GetBits(15, bitsPerAlphaIndex, alphaIndexBytesRow1);
            alphaIndices[11] = (uint)Utils.GetBits(12, bitsPerAlphaIndex, alphaIndexBytesRow1);
            alphaIndices[12] = (uint)Utils.GetBits(9, bitsPerAlphaIndex, alphaIndexBytesRow1);
            alphaIndices[13] = (uint)Utils.GetBits(6, bitsPerAlphaIndex, alphaIndexBytesRow1);
            alphaIndices[14] = (uint)Utils.GetBits(3, bitsPerAlphaIndex, alphaIndexBytesRow1);
            alphaIndices[15] = (uint)Utils.GetBits(0, bitsPerAlphaIndex, alphaIndexBytesRow1);
            // Create the color table.
            var colorTable = new Color[4];

            colorTable[0] = r.ReadUInt16().B565ToColor();
            colorTable[1] = r.ReadUInt16().B565ToColor();
            colorTable[2] = Color.Lerp(colorTable[0], colorTable[1], 1.0f / 3);
            colorTable[3] = Color.Lerp(colorTable[0], colorTable[1], 2.0f / 3);
            // Calculate pixel colors.
            var colors = DecodeDXT1TexelBlock(r, colorTable);

            for (var i = 0; i < 16; i++)
            {
                colors[i].a = (byte)Mathf.Round(alphaTable[alphaIndices[i]]);
            }
            return(colors);
        }
Пример #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="gr"></param>
        /// <param name="gr2"></param>
        /// <param name="sb"></param>
        /// <param name="swe"></param>
        /// <returns></returns>
        public static bool ParsePartyMemberStatsOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            sb.AppendLine("Packet offset " + gr.BaseStream.Position.ToString("X2"));
            sb.AppendLine("Opcode SMSG_PARTY_MEMBER_STATS (0x007E)");

            byte MAX_AURAS = 56;

            ulong guid = gr2.ReadPackedGuid();

            sb.AppendLine("GUID " + guid.ToString("X16"));

            GroupUpdateFlags flags = (GroupUpdateFlags)gr2.ReadUInt32();

            sb.AppendLine("Flags " + flags);

            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_ONLINE) != 0)
            {
                GroupMemberOnlineStatus online = (GroupMemberOnlineStatus)gr2.ReadUInt16(); // flag
                sb.AppendLine("Online state " + online);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_CUR_HP) != 0)
            {
                ushort hp = gr2.ReadUInt16();
                sb.AppendLine("Cur. health " + hp);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_MAX_HP) != 0)
            {
                ushort maxhp = gr2.ReadUInt16();
                sb.AppendLine("Max health " + maxhp);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_POWER_TYPE) != 0)
            {
                Powers power = (Powers)gr2.ReadByte();
                sb.AppendLine("Power type " + power);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_CUR_POWER) != 0)
            {
                ushort curpower = gr2.ReadUInt16();
                sb.AppendLine("Cur. power " + curpower);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_MAX_POWER) != 0)
            {
                ushort maxpower = gr2.ReadUInt16();
                sb.AppendLine("Max power " + maxpower);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_LEVEL) != 0)
            {
                ushort level = gr2.ReadUInt16();
                sb.AppendLine("Level " + level);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_ZONE) != 0)
            {
                ushort zone = gr2.ReadUInt16();
                sb.AppendLine("Zone " + zone);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_POSITION) != 0)
            {
                short x = gr2.ReadInt16();
                short y = gr2.ReadInt16();
                sb.AppendLine("Position: " + x + ", " + y);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_AURAS) != 0)
            {
                ulong mask = gr2.ReadUInt64();
                sb.AppendLine("Auras mask " + mask.ToString("X16"));

                BitArray bitArr = new BitArray(BitConverter.GetBytes(mask));

                for (int i = 0; i < bitArr.Length; i++)
                {
                    if (i >= MAX_AURAS) // we can have only 56 auras
                    {
                        break;
                    }

                    if (bitArr[i])
                    {
                        ushort spellid = gr2.ReadUInt16();
                        sb.AppendLine("Aura " + i.ToString() + ": " + spellid.ToString());
                        byte unk = gr2.ReadByte();
                        sb.AppendLine("Aura unk " + i.ToString() + ": " + unk.ToString());
                    }
                }
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_GUID) != 0)
            {
                ulong petguid = gr2.ReadUInt64();
                sb.AppendLine("Pet guid " + petguid.ToString("X16"));
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_NAME) != 0)
            {
                string name = gr2.ReadStringNull();
                sb.AppendLine("Pet name " + name);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_MODEL_ID) != 0)
            {
                ushort modelid = gr2.ReadUInt16();
                sb.AppendLine("Pet model id " + modelid);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_CUR_HP) != 0)
            {
                ushort pethp = gr2.ReadUInt16();
                sb.AppendLine("Pet cur. HP " + pethp);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_MAX_HP) != 0)
            {
                ushort petmaxhp = gr2.ReadUInt16();
                sb.AppendLine("Pet max HP " + petmaxhp);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_POWER_TYPE) != 0)
            {
                Powers power = (Powers)gr2.ReadByte();
                sb.AppendLine("Pet power type " + power);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_CUR_POWER) != 0)
            {
                ushort petpower = gr2.ReadUInt16();
                sb.AppendLine("Pet cur. power " + petpower);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_MAX_POWER) != 0)
            {
                ushort petmaxpower = gr2.ReadUInt16();
                sb.AppendLine("Pet max power " + petmaxpower);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_AURAS) != 0)
            {
                ulong mask = gr2.ReadUInt64();
                sb.AppendLine("Pet auras mask " + mask.ToString("X16"));

                BitArray bitArr = new BitArray(BitConverter.GetBytes(mask));
                for (int i = 0; i < bitArr.Length; i++)
                {
                    if (i >= MAX_AURAS) // we can have only 56 auras
                    {
                        break;
                    }

                    if (bitArr[i])
                    {
                        ushort spellid = gr2.ReadUInt16();
                        sb.AppendLine("Pet aura " + i.ToString() + ": " + spellid.ToString());
                        byte unk = gr2.ReadByte();
                        sb.AppendLine("Pet aura unk " + i.ToString() + ": " + unk.ToString());
                    }
                    i++;
                }
            }

            if (gr2.BaseStream.Position == gr2.BaseStream.Length)
            {
                sb.AppendLine("parsed: ok...");
            }
            else
            {
                sb.AppendLine("parsed: error...");
            }

            return(true);
        }
Пример #8
0
        void ReadMetadata()
        {
            // Open
            Magic = _r.ReadUInt32();
            if (Magic == F4_BSAHEADER_FILEID)
            {
                Version = _r.ReadUInt32();
                if (Version != F4_BSAHEADER_VERSION)
                {
                    throw new InvalidOperationException("BAD MAGIC");
                }
                // Read the header
                var header_Type            = _r.ReadASCIIString(4); // 08 GNRL=General, DX10=Textures
                var header_NumFiles        = _r.ReadUInt32();       // 0C
                var header_NameTableOffset = _r.ReadUInt64();       // 10 - relative to start of file
                // Create file metadatas
                _r.Position = (long)header_NameTableOffset;
                _files      = new FileMetadata[header_NumFiles];
                for (var i = 0; i < header_NumFiles; i++)
                {
                    var length = _r.ReadUInt16();
                    var path   = _r.ReadASCIIString(length).Replace('\\', '/');
                    _files[i] = new FileMetadata
                    {
                        Path     = path,
                        PathHash = Tes4HashFilePath(path),
                    };
                }
                if (header_Type == "GNRL") // General BA2 Format
                {
                    _r.Position = 16 + 8;  // sizeof(header) + 8
                    for (var i = 0; i < header_NumFiles; i++)
                    {
                        var info_NameHash     = _r.ReadUInt32();       // 00
                        var info_Ext          = _r.ReadASCIIString(4); // 04 - extension
                        var info_DirHash      = _r.ReadUInt32();       // 08
                        var info_Unk0C        = _r.ReadUInt32();       // 0C - flags? 00100100
                        var info_Offset       = _r.ReadUInt64();       // 10 - relative to start of file
                        var info_PackedSize   = _r.ReadUInt32();       // 18 - packed length (zlib)
                        var info_UnpackedSize = _r.ReadUInt32();       // 1C - unpacked length
                        var info_Unk20        = _r.ReadUInt32();       // 20 - BAADF00D
                        _files[i].PackedSize   = info_PackedSize;
                        _files[i].UnpackedSize = info_UnpackedSize;
                        _files[i].Offset       = (long)info_Offset;
                    }
                }
                else if (header_Type == "DX10") // Texture BA2 Format
                {
                    _r.Position = 16 + 8;       // sizeof(header) + 8
                    for (var i = 0; i < header_NumFiles; i++)
                    {
                        var fileMetadata         = _files[i];
                        var info_NameHash        = _r.ReadUInt32();       // 00
                        var info_Ext             = _r.ReadASCIIString(4); // 04
                        var info_DirHash         = _r.ReadUInt32();       // 08
                        var info_Unk0C           = _r.ReadByte();         // 0C
                        var info_NumChunks       = _r.ReadByte();         // 0D
                        var info_ChunkHeaderSize = _r.ReadUInt16();       // 0E - size of one chunk header
                        var info_Height          = _r.ReadUInt16();       // 10
                        var info_Width           = _r.ReadUInt16();       // 12
                        var info_NumMips         = _r.ReadByte();         // 14
                        var info_Format          = _r.ReadByte();         // 15 - DXGI_FORMAT
                        var info_Unk16           = _r.ReadUInt16();       // 16 - 0800
                        // read tex-chunks
                        var texChunks = new F4TexChunk[info_NumChunks];
                        for (var j = 0; j < info_NumChunks; j++)
                        {
                            texChunks[j] = new F4TexChunk
                            {
                                Offset       = _r.ReadUInt64(),   // 00
                                PackedSize   = _r.ReadUInt32(),   // 08
                                UnpackedSize = _r.ReadUInt32(),   // 0C
                                StartMip     = _r.ReadUInt16(),   // 10
                                EndMip       = _r.ReadUInt16(),   // 12
                                Unk14        = _r.ReadUInt32(),   // 14 - BAADFOOD
                            }
                        }
                        ;
                        var firstChunk = texChunks[0];
                        _files[i].PackedSize   = firstChunk.PackedSize;
                        _files[i].UnpackedSize = firstChunk.UnpackedSize;
                        _files[i].Offset       = (long)firstChunk.Offset;
                        fileMetadata.Tex       = new F4Tex
                        {
                            Height  = info_Height,
                            Width   = info_Width,
                            NumMips = info_NumMips,
                            Format  = (DXGIFormat)info_Format,
                            Unk16   = info_Unk16,
                            Chunks  = texChunks,
                        };
                    }
                }
            }
            else if (Magic == OB_BSAHEADER_FILEID)
            {
                Version = _r.ReadUInt32();
                if (Version != OB_BSAHEADER_VERSION && Version != F3_BSAHEADER_VERSION && Version != SSE_BSAHEADER_VERSION)
                {
                    throw new InvalidOperationException("BAD MAGIC");
                }
                // Read the header
                var header_FolderRecordOffset = _r.ReadUInt32(); // Offset of beginning of folder records
                var header_ArchiveFlags       = _r.ReadUInt32(); // Archive flags
                var header_FolderCount        = _r.ReadUInt32(); // Total number of folder records (OBBSAFolderInfo)
                var header_FileCount          = _r.ReadUInt32(); // Total number of file records (OBBSAFileInfo)
                var header_FolderNameLength   = _r.ReadUInt32(); // Total length of folder names
                var header_FileNameLength     = _r.ReadUInt32(); // Total length of file names
                var header_FileFlags          = _r.ReadUInt32(); // File flags

                // Calculate some useful values
                if ((header_ArchiveFlags & OB_BSAARCHIVE_PATHNAMES) == 0 || (header_ArchiveFlags & OB_BSAARCHIVE_FILENAMES) == 0)
                {
                    throw new InvalidOperationException("HEADER FLAGS");
                }
                _compressToggle = (header_ArchiveFlags & OB_BSAARCHIVE_COMPRESSFILES) != 0;
                if (Version == F3_BSAHEADER_VERSION || Version == SSE_BSAHEADER_VERSION)
                {
                    _hasNamePrefix = (header_ArchiveFlags & F3_BSAARCHIVE_PREFIXFULLFILENAMES) != 0;
                }
                var folderSize = Version != SSE_BSAHEADER_VERSION ? 16 : 24;

                // Create file metadatas
                _files = new FileMetadata[header_FileCount];
                var filenamesSectionStartPos = _r.Position = header_FolderRecordOffset + header_FolderNameLength + header_FolderCount * (folderSize + 1) + header_FileCount * 16;
                var buf = new List <byte>(64);
                for (var i = 0; i < header_FileCount; i++)
                {
                    buf.Clear();
                    byte curCharAsByte; while ((curCharAsByte = _r.ReadByte()) != 0)
                    {
                        buf.Add(curCharAsByte);
                    }
                    var path = Encoding.ASCII.GetString(buf.ToArray()).Replace('\\', '/');
                    _files[i] = new FileMetadata
                    {
                        Path = path,
                    };
                }
                if (_r.Position != filenamesSectionStartPos + header_FileNameLength)
                {
                    throw new InvalidOperationException("HEADER FILENAMES");
                }

                // read-all folders
                _r.Position = header_FolderRecordOffset;
                var foldersFiles = new uint[header_FolderCount];
                for (var i = 0; i < header_FolderCount; i++)
                {
                    var folder_Hash = _r.ReadUInt64();      // Hash of the folder name
                    var folder_FileCount = _r.ReadUInt32(); // Number of files in folder
                    var folder_Unk = 0U; var folder_Offset = 0UL;
                    if (Version == SSE_BSAHEADER_VERSION)
                    {
                        folder_Unk = _r.ReadUInt32(); folder_Offset = _r.ReadUInt64();
                    }
                    else
                    {
                        folder_Offset = _r.ReadUInt32();
                    }
                    foldersFiles[i] = folder_FileCount;
                }

                // add file
                var fileNameIndex = 0U;
                for (var i = 0; i < header_FolderCount; i++)
                {
                    var folder_name = _r.ReadASCIIString(_r.ReadByte(), ASCIIFormat.PossiblyNullTerminated).Replace('\\', '/'); // BSAReadSizedString
                    var folderFiles = foldersFiles[i];
                    for (var j = 0; j < folderFiles; j++)
                    {
                        var file_Hash      = _r.ReadUInt64(); // Hash of the filename
                        var file_SizeFlags = _r.ReadUInt32(); // Size of the data, possibly with OB_BSAFILE_FLAG_COMPRESS set
                        var file_Offset    = _r.ReadUInt32(); // Offset to raw file data
                        var fileMetadata   = _files[fileNameIndex++];
                        fileMetadata.SizeFlags = file_SizeFlags;
                        fileMetadata.Offset    = file_Offset;
                        fileMetadata.Path      = folder_name + "/" + fileMetadata.Path;
                        fileMetadata.PathHash  = Tes4HashFilePath(fileMetadata.Path);
                    }
                }
            }
            else if (Magic == MW_BSAHEADER_FILEID)
            {
                // Read the header
                var header_HashOffset = _r.ReadUInt32(); // Offset of hash table minus header size (12)
                var header_FileCount  = _r.ReadUInt32(); // Number of files in the archive

                // Calculate some useful values
                var headerSize             = _r.Position;
                var hashTablePosition      = headerSize + header_HashOffset;
                var fileDataSectionPostion = hashTablePosition + (8 * header_FileCount);

                // Create file metadatas
                _files = new FileMetadata[header_FileCount];
                for (var i = 0; i < header_FileCount; i++)
                {
                    _files[i] = new FileMetadata
                    {
                        // Read file sizes/offsets
                        SizeFlags = _r.ReadUInt32(),
                        Offset    = fileDataSectionPostion + _r.ReadUInt32(),
                    }
                }
                ;

                // Read filename offsets
                var filenameOffsets = new uint[header_FileCount]; // relative offset in filenames section
                for (var i = 0; i < header_FileCount; i++)
                {
                    filenameOffsets[i] = _r.ReadUInt32();
                }

                // Read filenames
                var filenamesSectionStartPos = _r.Position;
                var buf = new List <byte>(64);
                for (var i = 0; i < header_FileCount; i++)
                {
                    _r.Position = filenamesSectionStartPos + filenameOffsets[i];
                    buf.Clear();
                    byte curCharAsByte; while ((curCharAsByte = _r.ReadByte()) != 0)
                    {
                        buf.Add(curCharAsByte);
                    }
                    _files[i].Path = Encoding.ASCII.GetString(buf.ToArray()).Replace('\\', '/');
                }

                // Read filename hashes
                _r.Position = hashTablePosition;
                for (var i = 0; i < header_FileCount; i++)
                {
                    //_files[i].PathHash = _r.ReadUInt64();
                    _files[i].PathHash = Tes3HashFilePath(_files[i].Path);
                }
            }
            else
            {
                throw new InvalidOperationException("BAD MAGIC");
            }

            // Create the file metadata hash table
            _filesByHash = _files.ToLookup(x => x.PathHash);
        }

        ulong HashFilePath(string filePath)
        {
            if (Magic == MW_BSAHEADER_FILEID)
            {
                return(Tes3HashFilePath(filePath));
            }
            else
            {
                return(Tes4HashFilePath(filePath));
            }
        }
Пример #9
0
        private static void ReadAndDumpField(UpdateField uf, StringBuilder sb, GenericReader gr, UpdateTypes updatetype, StreamWriter data, WoWObject obj)
        {
            MemoryStream  ms  = new MemoryStream(gr.ReadBytes(4));
            GenericReader gr2 = new GenericReader(ms);

            if (updatetype == UpdateTypes.UPDATETYPE_CREATE_OBJECT || updatetype == UpdateTypes.UPDATETYPE_CREATE_OBJECT2)
            {
                obj.SetUInt32Value(uf.Identifier, gr2.ReadUInt32());
                gr2.BaseStream.Position -= 4;
            }

            switch (uf.Type)
            {
            // TODO: add data writing

            /*case 3:
             *  string val1 = gr.ReadSingle().ToString().Replace(",", ".");
             *  if (updatetype == UpdateTypes.UPDATETYPE_CREATE_OBJECT || updatetype == UpdateTypes.UPDATETYPE_CREATE_OBJECT2)
             *      data.WriteLine(uf.Name + " (" + uf.Identifier + "): " + val1);
             *  sb.AppendLine(uf.Name + " (" + index + "): " + val1);
             *  break;
             * default:
             *  uint val2 = gr.ReadUInt32();
             *  if (updatetype == UpdateTypes.UPDATETYPE_CREATE_OBJECT || updatetype == UpdateTypes.UPDATETYPE_CREATE_OBJECT2)
             *      data.WriteLine(uf.Name + " (" + uf.Identifier + "): " + val2);
             *  sb.AppendLine(uf.Name + " (" + uf.Identifier + "): " + val2);
             *  break;*/
            case 1:     // uint32
                sb.AppendLine(uf.Name + " (" + uf.Identifier + "): " + gr2.ReadUInt32().ToString("X8"));
                break;

            case 2:     // uint16+uint16
                ushort value1 = gr2.ReadUInt16();
                ushort value2 = gr2.ReadUInt16();

                sb.AppendLine(uf.Name + " (" + uf.Identifier + "): " + "first " + value1.ToString("X4") + ", second " + value2.ToString("X4"));
                if (uf.Name.StartsWith("PLAYER_SKILL_INFO_1_"))
                {
                    int num = uf.Identifier - 858;
                    if ((num % 3) == 0)
                    {
                        ushort skill = value1;
                        ushort flag  = value2;

                        string str = String.Format("skill {0}, flag {1}", skill, (ProfessionFlags)flag);
                        sb.AppendLine(str);
                    }
                    else if (((num - 1) % 3) == 0)
                    {
                        ushort minskill = value1;
                        ushort maxskill = value2;

                        string str = String.Format("minskill {0}, maxskill {1}", minskill, maxskill);
                        sb.AppendLine(str);
                    }
                    else
                    {
                        ushort minbonus = value1;
                        ushort maxbonus = value2;

                        string str = String.Format("minbonus {0}, maxbonus {1}", minbonus, maxbonus);
                        sb.AppendLine(str);
                    }
                }
                break;

            case 3:     // float
                sb.AppendLine(uf.Name + " (" + uf.Identifier + "): " + gr2.ReadSingle());
                //sb.AppendLine(uf.Name + " (" + uf.Identifier + "): " + gr.ReadSingle().ToString().Replace(",", "."));
                break;

            case 4:     // uint64 (can be only low part)
                sb.AppendLine(uf.Name + " (" + uf.Identifier + "): " + gr2.ReadUInt32().ToString("X8"));
                break;

            case 5:     // bytes
                uint value = gr2.ReadUInt32();
                sb.AppendLine(uf.Name + " (" + uf.Identifier + "): " + value.ToString("X8"));
                if (uf.Identifier == 36)     // UNIT_FIELD_BYTES_0
                {
                    byte[] bytes     = BitConverter.GetBytes(value);
                    Races  race      = (Races)bytes[0];
                    Class  class_    = (Class)bytes[1];
                    Gender gender    = (Gender)bytes[2];
                    Powers powertype = (Powers)bytes[3];

                    string str = String.Format("Race: {0}, class: {1}, gender: {2}, powertype: {3}", race, class_, gender, powertype);
                    sb.AppendLine(str);
                }
                break;

            default:
                sb.AppendLine(uf.Name + " (" + uf.Identifier + "): " + "unknown type " + gr2.ReadUInt32().ToString("X8"));
                break;
            }

            gr2.Close();
        }
Пример #10
0
        private uint ParsePacket(GenericReader gr, StreamWriter sw, StreamWriter swe, StreamWriter data)
        {
            StringBuilder sb = new StringBuilder();

            //MessageBox.Show(br.BaseStream.Position.ToString() + " " + br.BaseStream.Length.ToString());

            uint opcode = gr.ReadUInt16();
            if (opcode != 0x00A9)
            {
                return 2;
            }

            sb.AppendLine("Packet offset " + (gr.BaseStream.Position - 2).ToString("X2"));

            sb.AppendLine("Packet number: " + packet);

            sb.AppendLine("Opcode: " + opcode.ToString("X4"));

            uint count = gr.ReadUInt32();
            sb.AppendLine("Object count: " + count);

            uint unk = gr.ReadByte();
            sb.AppendLine("Unk: " + unk);

            for (uint i = 1; i < count+1; i++)
            {
                sb.AppendLine("Update block for object " + i + ":");
                sb.AppendLine("Block offset " + gr.BaseStream.Position.ToString("X2"));

                if (!ParseBlock(gr, sb, swe, data))
                {
                    sw.WriteLine(sb.ToString());
                    return 1;
                }
            }
            sw.WriteLine(sb.ToString());
            return 0;
        }