/// <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);
        }