示例#1
0
        public SkillReader(ProcessMemoryReader reader, GameMemoryTable memory)
        {
            this.reader = reader;

            globals      = reader.Read <D2GlobalData>(reader.ReadAddress32(memory.Address.GlobalData, AddressingMode.Relative));
            stringReader = new StringLookupTable(reader, memory.Address);
        }
示例#2
0
        protected D2Unit GetPlayer()
        {
            if (player == null)
            {
                IntPtr playerAddress = reader.ReadAddress32(memory.Address.PlayerUnit, AddressingMode.Relative);
                player = reader.Read <D2Unit>(playerAddress);
            }

            return(player);
        }
示例#3
0
        public D2Unit GetPlayer()
        {
            if (player == null && (long)memory.Address.PlayerUnit > 0)
            {
                IntPtr playerAddress = reader.ReadAddress32(memory.Address.PlayerUnit, AddressingMode.Relative);
                player = reader.Read <D2Unit>(playerAddress);
            }

            return(player);
        }
示例#4
0
        public D2Inventory GetPlayerInventory()
        {
            var playerAddress = processReader.ReadAddress32(memory.Address.PlayerUnit, AddressingMode.Relative);

            if (playerAddress == IntPtr.Zero)
            {
                return(null);
            }

            var playerUnit = processReader.Read <D2Unit>(playerAddress);

            if (playerUnit == null)
            {
                return(null);
            }

            return(processReader.Read <D2Inventory>(playerUnit.pInventory.Address));
        }
示例#5
0
        public ItemReader(ProcessMemoryReader reader, D2MemoryTable memory) : base(reader, memory)
        {
            cachedItemData     = new Dictionary <IntPtr, D2ItemData>();
            cachedDescriptions = new Dictionary <int, D2ItemDescription>();

            globals          = reader.Read <D2GlobalData>(reader.ReadAddress32(memory.Address.GlobalData, AddressingMode.Relative));
            lowQualityTable  = reader.Read <D2SafeArray>(memory.Address.LowQualityItems, AddressingMode.Relative);
            descriptionTable = reader.Read <D2SafeArray>(memory.Address.ItemDescriptions, AddressingMode.Relative);
            magicModifiers   = reader.Read <ModifierTable>(memory.Address.MagicModifierTable, AddressingMode.Relative);
            rareModifiers    = reader.Read <ModifierTable>(memory.Address.RareModifierTable, AddressingMode.Relative);
            if (globals != null)
            {
                opNestings = reader.ReadArray <ushort>(globals.OpStatNesting, (int)globals.OpStatNestingCount);

                if (ItemStatCost == null && !globals.ItemStatCost.IsNull)
                {
                    ItemStatCost = reader.ReadArray <D2ItemStatCost>(globals.ItemStatCost, (int)globals.ItemStatCostCount);
                }
            }
        }
示例#6
0
        private string LookupStringTable(ushort identifier)
        {
            StringTable strTable = GetStringTableByIdentifier(identifier);

            identifier -= strTable.identifierOffset;

            IntPtr indexerTable = reader.ReadAddress32(strTable.indexTable, AddressingMode.Relative);

            if (indexerTable == IntPtr.Zero)
            {
                return(null);
            }

            IntPtr addressTable = reader.ReadAddress32(strTable.addressTable, AddressingMode.Relative);

            if (addressTable == IntPtr.Zero)
            {
                return(null);
            }

            /*
             *  Info by [qhris].
             *
             *  Unicode strings are stored contiguous in a big buffer. To access this buffer
             *  the address table is used. The address table maps an address index to a string
             *  in the contiguous buffer.
             *
             *  Note that all strings end with a null terminator and string length does not seem to
             *  be stored anywhere.
             *
             *  To get the address index, the string identifier (unsigned short) is looked up in the
             *  item info table, along with a few checks to validate.
             */
            var tableInfo = reader.Read <D2StringTableInfo>(indexerTable);

            // We use the identifier 0x1F4 for invalid identifiers.
            // because this is also what happens in D2Lang.dll
            if (identifier >= tableInfo.IdentifierCount)
            {
                identifier = 0x01F4;
            }

            // Right after the string info table (in memory) lies the identifier -> address index
            // mapping array.
            IntPtr stringDataRegion = indexerTable + Marshal.SizeOf <D2StringTableInfo>();
            Func <ushort, IntPtr> GetAddressIndexLocation = (index) => stringDataRegion + index * sizeof(ushort);

            // Read address index; must be in valid range.
            ushort addressTableIndex = reader.ReadUInt16(GetAddressIndexLocation(identifier));

            if (addressTableIndex >= tableInfo.AddressTableSize)
            {
                return(null);
            }

            // Get the address containing string information.
            IntPtr stringInfoBlock   = GetAddressIndexLocation(tableInfo.IdentifierCount);
            IntPtr stringInfoAddress = stringInfoBlock + addressTableIndex * Marshal.SizeOf <D2StringInfo>();

            // Make sure it's in range.
            IntPtr endTest = indexerTable + tableInfo.DataBlockSize;

            if ((long)stringInfoAddress >= (long)endTest)
            {
                return(null);
            }

            // Check if the string has been loaded into the address table.
            D2StringInfo stringInfo = reader.Read <D2StringInfo>(stringInfoAddress);

            if (!stringInfo.IsLoadedUnicode)
            {
                return(null);
            }

            // If we get a null string address, just ignore it.
            IntPtr stringAddress = reader.ReadAddress32(addressTable + addressTableIndex * sizeof(uint));

            if (stringAddress == IntPtr.Zero)
            {
                return(null);
            }

            // A maximum of 0x4000 sized buffer **should** be enough to read all strings, bump if too low.
            return(reader.GetNullTerminatedString(stringAddress, 0x100, 0x4000, Encoding.Unicode, AddressingMode.Absolute));
        }