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); }
protected D2Unit GetPlayer() { if (player == null) { IntPtr playerAddress = reader.ReadAddress32(memory.Address.PlayerUnit, AddressingMode.Relative); player = reader.Read <D2Unit>(playerAddress); } return(player); }
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); }
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)); }
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); } } }
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)); }