Given a DBC file, used by a game, contains records, infos about ingame usable Spells. :) (like ID, name, damage, etc etc...)
To be more complex, the string data is stored in a block after the records. String data in records contain an offset to the string, (so its not really a string)
I have a struct for DBC file, that looks like this:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct SpellEntry
    {
        private const int MAX_EFFECT_INDEX = 3;
        public uint ID;
        public uint Category;
        public uint Dispel;
        public uint Mechanic;
        public uint Attributes;
        public uint AttributesEx;
        public uint AttributesEx2;
        public uint AttributesEx3;
        public uint AttributesEx4;
        public uint AttributesEx5;
        public uint AttributesEx6;
        public uint AttributesEx7;
        public uint Stances;
        public uint unk_320_2;
        public uint StancesNot;
        public uint unk_320_3;
        public uint Targets;
        public uint TargetCreatureType;
        public uint RequiresSpellFocus;
        public uint FacingCasterFlags;
        public uint CasterAuraState;
        public uint TargetAuraState;
        public uint CasterAuraStateNot;
        public uint TargetAuraStateNot;
        public uint casterAuraSpell;
        public uint targetAuraSpell;
        public uint excludeCasterAuraSpell;
        public uint excludeTargetAuraSpell;
        public uint CastingTimeIndex;
        public uint RecoveryTime;
        public uint CategoryRecoveryTime;
        public uint InterruptFlags;
        public uint AuraInterruptFlags;
        public uint ChannelInterruptFlags;
        public uint procFlags;
        public uint procChance;
        public uint procCharges;
        public uint maxLevel;
        public uint baseLevel;
        public uint spellLevel;
        public uint DurationIndex;
        public uint powerType;
        public uint manaCost;
        public uint manaCostPerlevel;
        public uint manaPerSecond;
        public uint manaPerSecondPerLevel;
        public uint rangeIndex;
        public float speed;
        public uint modalNextSpell;
        public uint StackAmount;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
        public uint[] Totem;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I4)]
        public int[] Reagent;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.U4)]
        public uint[] ReagentCount;
        public int EquippedItemClass;
        public int EquippedItemSubClassMask;
        public int EquippedItemInventoryTypeMask;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] Effect;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
        public int[] EffectDieSides;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
        public int[] EffectBaseDice;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
        public float[] EffectDicePerLevel;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
        public float[] EffectRealPointsPerLevel;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
        public int[] EffectBasePoints;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectMechanic;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectImplicitTargetA;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectImplicitTargetB;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectRadiusIndex;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectApplyAuraName;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectAmplitude;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
        public float[] EffectMultipleValue;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectChainTarget;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectItemType;
        //[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
        //public int[] EffectMiscValue;
        //[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
        //public int[] EffectMiscValueB;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
        public uint[] EffectTriggerSpell;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
        public float[] EffectPointsPerComboPoint;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX)]
        public Flag96[] EffectSpellClassMask;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
        public uint[] SpellVisual;
        public uint SpellIconID;
        public uint activeIconID;
        public uint spellPriority;
        [MarshalAs(UnmanagedType.LPStr)]
        public string SpellName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string Rank;
        [MarshalAs(UnmanagedType.LPStr)]
        public string Description;
        [MarshalAs(UnmanagedType.LPStr)]
        public string ToolTip;
        public uint ManaCostPercentage;
        public uint StartRecoveryCategory;
        public uint StartRecoveryTime;
        public uint MaxTargetLevel;
        public uint SpellFamilyName;
        public Flag96 SpellFamilyFlags;
        public uint MaxAffectedTargets;
        public uint DmgClass;
        public uint PreventionType;
        public uint StanceBarOrder;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
        public float[] DmgMultiplier;
        public uint MinFactionId;
        public uint MinReputation;
        public uint RequiredAuraVision;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
        public uint[] TotemCategory;
        public int AreaGroupId;
        public int SchoolMask;
        public uint runeCostID;
        public uint spellMissileID;
        public uint PowerDisplayId;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.R4)]
        public float[] unk_320_4;
        public uint spellDescriptionVariableID;
        public uint SpellDifficultyId;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct Flag96
    {
        public uint DwA;
        public uint DwB;
        public uint DwC;
        public override string ToString()
        {
            return string.Format("DwA: {0} - DwB: {1} - DwC: {2}", DwA, DwB, DwC);
        }
    }
So, what I'm trying to do is marshaling bytes to this struct with the following code:
                byte[] buff = new byte[Marshal.SizeOf(typeof(Spell.SpellEntry))];
                binReader.BaseStream.Seek(DBCFile.HEADER_SIZE + (index * 4 * 234), SeekOrigin.Begin);
                var bytes = binReader.ReadBytes(buff.Length);  
                var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                var obj = (Spell.SpellEntry)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(Spell.SpellEntry));
                handle.Free();
Which gives me an AccessViolationException on the Marshal.PtrToStructure line. I suspect my struct is invalid, somehow, could you correct me, or give a hint? What's interesting that when I debug in the IDE, it looks like its reads the structure correctly, but gives this exception... weird.
I also tryed reading into struct one by one, like
                    spell[index].ID = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
                    spell[index].Category = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
                    spell[index].Dispel = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
                    spell[index].Mechanic = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
which is working 100% good for me, but its looks lame, and its really long in the code. Marshaling looks more pro :) So, whats your opinion, Is marshaling faster than reading one by one, if yes, how should I fix it? THanks
 
     
    