/// <summary> /// Obtains a stream which can be used to read and write a cache file's meta in realtime. /// The stream will be set up such that offsets in the stream correspond to meta pointers in the cache file. /// </summary> /// <param name="cacheFile">The cache file to get a stream for.</param> /// <param name="tag">The tag to get a stream for.</param> /// <returns>The stream if it was opened successfully, or null otherwise.</returns> public IStream GetMetaStream(ICacheFile cacheFile, ITag tag) { Process gameProcess = FindGameProcess(); if (gameProcess == null) return null; var gameMemory = new ProcessMemoryStream(gameProcess); var mapInfo = new H2VistaMapPointerReader(gameMemory); long metaAddress; if (cacheFile.Type != CacheFileType.Shared) { metaAddress = mapInfo.CurrentMetaAddress; // The map isn't shared, so make sure the map names match if (mapInfo.MapName != cacheFile.InternalName) { gameMemory.Close(); return null; } } else { metaAddress = mapInfo.SharedMetaAddress; // Make sure the shared and current map pointers are different, // or that the current map is the shared map if (mapInfo.MapType != CacheFileType.Shared && mapInfo.CurrentMetaAddress == mapInfo.SharedMetaAddress) { gameMemory.Close(); return null; } } var metaStream = new OffsetStream(gameMemory, metaAddress - cacheFile.MetaArea.BasePointer); return new EndianStream(metaStream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian); }
/// <summary> /// Obtains a stream which can be used to read and write a cache file's meta in realtime. /// The stream will be set up such that offsets in the stream correspond to meta pointers in the cache file. /// </summary> /// <param name="cacheFile">The cache file to get a stream for.</param> /// <param name="tag">The tag to get a stream for.</param> /// <returns> /// The stream if it was opened successfully, or null otherwise. /// </returns> public IStream GetMetaStream(ICacheFile cacheFile, ITag tag) { // Open a handle to the game process var gameProcess = FindGameProcess(); if (gameProcess == null) return null; var memoryStream = new ProcessMemoryStream(gameProcess); var exeBase = (uint)memoryStream.BaseProcess.MainModule.BaseAddress - 0x400000; var tagAddress = GetTagAddress(new EndianReader(memoryStream, Endian.LittleEndian), tag.Index.Index, exeBase); if (tagAddress == 0) { memoryStream.Close(); return null; } var offsetStream = new OffsetStream(memoryStream, tagAddress - tag.HeaderLocation.AsOffset()); return new EndianStream(offsetStream, Endian.LittleEndian); }