예제 #1
0
        /// <summary>
        /// Gets an image from a bitmap tag.
        /// </summary>
        /// <param name="Cache">The CacheFile containing the bitmap tag.</param>
        /// <param name="bitm">The bitmap tag.</param>
        /// <param name="Index">The index of the BitmapData chunk to use.</param>
        /// <param name="Alpha">Whether to include the alpha channel in the image.</param>
        /// <returns>The image from the bitmap tag as a Bitmap.</returns>
        public static Bitmap GetBitmapByTag(CacheBase Cache, bitmap bitm, int Index, PixelFormat PF)
        {
            try
            {
                var submap = bitm.Bitmaps[Index];

                byte[] raw;
                if (Cache.Version <= DefinitionSet.Halo2Vista)
                {
                    raw = Cache.GetRawFromID(submap.PixelsOffset, submap.RawSize);
                }
                else
                {
                    if (bitm.RawChunkBs.Count > 0)
                    {
                        int    rawID  = bitm.RawChunkBs[submap.InterleavedIndex].RawID;
                        byte[] buffer = Cache.GetRawFromID(rawID);
                        raw = new byte[submap.RawSize];
                        Array.Copy(buffer, submap.Index2 * submap.RawSize, raw, 0, submap.RawSize);
                    }
                    else
                    {
                        int rawID = bitm.RawChunkAs[Index].RawID;
                        raw = Cache.GetRawFromID(rawID, submap.RawSize);
                    }
                }

                int vHeight = submap.VirtualHeight;
                int vWidth  = submap.VirtualWidth;

                if (submap.Type == TextureType.CubeMap)
                {
                    return(DXTDecoder.DecodeCubeMap(raw, submap, PF, Cache.Version));
                }

                raw = DXTDecoder.DecodeBitmap(raw, submap, Cache.Version);

                Bitmap     bitmap2          = new Bitmap(submap.Width, submap.Height, PF);
                Rectangle  rect             = new Rectangle(0, 0, submap.Width, submap.Height);
                BitmapData bitmapdata       = bitmap2.LockBits(rect, ImageLockMode.WriteOnly, PF);
                byte[]     destinationArray = new byte[(submap.Width * submap.Height) * 4];

                for (int j = 0; j < submap.Height; j++)
                {
                    Array.Copy(raw, j * vWidth * 4, destinationArray, j * submap.Width * 4, submap.Width * 4);
                }

                Marshal.Copy(destinationArray, 0, bitmapdata.Scan0, destinationArray.Length);
                bitmap2.UnlockBits(bitmapdata);

                return(bitmap2);
            }
            catch
            {
                return(null);
            }
        }
예제 #2
0
        public static void SaveBink(string Filename, CacheBase Cache, CacheBase.IndexItem Tag)
        {
            var bik = DefinitionsManager.bink(Cache, Tag);
            var raw = Cache.GetRawFromID(bik.RawID);

            if (!Filename.EndsWith(".bik"))
            {
                Filename += ".bik";
            }

            if (!Directory.GetParent(Filename).Exists)
            {
                Directory.GetParent(Filename).Create();
            }

            var fs = new FileStream(Filename, FileMode.Create, FileAccess.Write);
            var bw = new BinaryWriter(fs);

            for (int i = 0; i < (raw.Length); i += 4)
            {
                Array.Reverse(raw, i, 4);
            }

            bw.Write(raw);

            bw.Close();
            bw.Dispose();
        }
예제 #3
0
        public scenario_structure_bsp(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;

            Reader.SeekTo(Address);

            #region sldt/lbsp ID
            //lbsp's sections address will be used instead of the one in sbsp
            int sectCount = 0, sectionAddress = 0, bbCount = 0, bbAddr = 0;
            foreach (var item in Cache.IndexItems)
            {
                if (item.ClassCode == "scnr")
                {
                    Reader.SeekTo(item.Offset + 160);
                    int cnt = Reader.ReadInt32();
                    int ptr = Reader.ReadInt32() - Cache.Magic;

                    int bspIndex = 0;

                    for (int i = 0; i < cnt; i++)
                    {
                        Reader.SeekTo(ptr + 336 * i + 12);
                        if (Cache.IndexItems.GetItemByID(Reader.ReadInt32()).Offset == Address)
                        {
                            bspIndex = i;
                            break;
                        }
                    }

                    Reader.SeekTo(item.Offset + 1896 + 12);
                    int sldtID      = Reader.ReadInt32();
                    int sldtAddress = Cache.IndexItems.GetItemByID(sldtID).Offset;

                    Reader.SeekTo(sldtAddress + 4);
                    cnt = Reader.ReadInt32();
                    ptr = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(ptr + 32 * bspIndex + 12);
                    int lbspID      = Reader.ReadInt32();
                    int lbspAddress = Cache.IndexItems.GetItemByID(lbspID).Offset;

                    Reader.SeekTo(lbspAddress + 320); //320, 512, 692
                    sectCount      = Reader.ReadInt32();
                    sectionAddress = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(lbspAddress + 344); //344, 536, 716
                    bbCount = Reader.ReadInt32();
                    bbAddr  = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(lbspAddress + 464); //464, 656, 836
                    geomRawID = Reader.ReadInt32();
                    break;
                }
            }
            #endregion

            Reader.SeekTo(Address + 268);
            XBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());
            YBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());
            ZBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());

            #region Clusters Block
            Reader.SeekTo(Address + 340);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < 1; i++)
            {
                Clusters.Add(new Cluster(Cache, iOffset + 140 * i));
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 352);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new Halo4Retail.render_model.Shader(Cache, iOffset + 44 * i));
            }
            #endregion

            #region GeometryInstances Block
            Reader.SeekTo(Address + 640);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 4 * i));
            }

            #region Load Fixup Data
            Reader.SeekTo(Address + 1364);
            int id    = Reader.ReadInt32();
            var entry = Cache.zone.RawEntries[id & 0xFFFF];
            var er    = new EndianReader(new MemoryStream(Cache.GetRawFromID(id)), EndianFormat.BigEndian);
            int addr  = entry.Fixups[entry.Fixups.Count - 10].Offset;

            for (int i = 0; i < GeomInstances.Count; i++)
            {
                er.SeekTo(addr + 148 * i);
                var geom = GeomInstances[i];

                geom.TransformScale = er.ReadSingle();

                geom.TransformMatrix.m11 = er.ReadSingle();
                geom.TransformMatrix.m12 = er.ReadSingle();
                geom.TransformMatrix.m13 = er.ReadSingle();

                geom.TransformMatrix.m21 = er.ReadSingle();
                geom.TransformMatrix.m22 = er.ReadSingle();
                geom.TransformMatrix.m23 = er.ReadSingle();

                geom.TransformMatrix.m31 = er.ReadSingle();
                geom.TransformMatrix.m32 = er.ReadSingle();
                geom.TransformMatrix.m33 = er.ReadSingle();

                geom.TransformMatrix.m41 = er.ReadSingle();
                geom.TransformMatrix.m42 = er.ReadSingle();
                geom.TransformMatrix.m43 = er.ReadSingle();

                er.ReadUInt16();
                er.ReadUInt16();
                er.ReadInt32();
                er.ReadUInt16();
                geom.SectionIndex = er.ReadUInt16();
            }
            er.Close();
            er.Dispose();
            #endregion
            #endregion

            Reader.SeekTo(Address + 844);
            RawID1 = Reader.ReadInt32();

            Reader.SeekTo(Address + 1048);
            RawID2 = Reader.ReadInt32();

            #region ModelSections Block
            Reader.SeekTo(Address + 1144);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            if (sectionAddress == -Cache.Magic)
            {
                sectionAddress = iOffset;                                 //null address in lbsp
            }
            for (int i = 0; i < sectCount; i++)
            {
                ModelSections.Add(new Halo4Retail.render_model.ModelSection(Cache, sectionAddress + 112 * i));
            }
            #endregion

            #region Bounding Boxes Block
            Reader.SeekTo(Address + 1168);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < bbCount; i++)
            {
                BoundingBoxes.Add(new Halo4Retail.render_model.BoundingBox(Cache, bbAddr + 52 * i));
            }
            #endregion

            Reader.SeekTo(Address + 1288);
            RawID3 = Reader.ReadInt32();
        }
예제 #4
0
        /// <summary>
        /// Saves an image from a bitmap tag to disk.
        /// </summary>
        /// <param name="Filename">The full path and filename to save to.</param>
        /// <param name="Cache">The CacheFile containing the bitmap tag.</param>
        /// <param name="Tag">The bitmap tag.</param>
        /// <param name="Index">The index of the BitmapData chunk to use.</param>
        /// <param name="Format">The format to save the image in.</param>
        /// <param name="Alpha">Whether to include the alpha channel in the image. Only applies when saving in TIF format.</param>
        public static void SaveImage(string Filename, CacheBase Cache, bitmap bitm, int Index, BitmapFormat Format, bool Alpha)
        {
            var submap = bitm.Bitmaps[Index];

            byte[] raw;

            if (Cache.Version <= DefinitionSet.Halo2Vista)
            {
                raw = Cache.GetRawFromID(submap.PixelsOffset, submap.RawSize);
            }
            else
            {
                if (bitm.RawChunkBs.Count > 0)
                {
                    int    rawID  = bitm.RawChunkBs[submap.InterleavedIndex].RawID;
                    byte[] buffer = Cache.GetRawFromID(rawID);
                    raw = new byte[submap.RawSize];
                    Array.Copy(buffer, submap.Index2 * submap.RawSize, raw, 0, submap.RawSize);
                }
                else
                {
                    int rawID = bitm.RawChunkAs[Index].RawID;
                    raw = Cache.GetRawFromID(rawID, submap.RawSize);
                }
            }

            int vHeight = submap.VirtualHeight;
            int vWidth  = submap.VirtualWidth;

            if (Format == BitmapFormat.TIF || Format == BitmapFormat.PNG)
            {
                string      ext     = (Format == BitmapFormat.TIF) ? ".tif" : ".png";
                int         pLength = (Format == BitmapFormat.TIF) ? 4 : 4;
                ImageFormat IF      = (Format == BitmapFormat.TIF) ? ImageFormat.Tiff : ImageFormat.Png;

                if (!Filename.EndsWith(ext))
                {
                    Filename += ext;
                }

                if (submap.Type == TextureType.CubeMap)
                {
                    var img = DXTDecoder.DecodeCubeMap(raw, submap, Alpha ? PixelFormat.Format32bppArgb : PixelFormat.Format32bppRgb, Cache.Version);
                    if (!Directory.GetParent(Filename).Exists)
                    {
                        Directory.GetParent(Filename).Create();
                    }
                    img.Save(Filename, ImageFormat.Tiff);
                    return;
                }

                raw = DXTDecoder.DecodeBitmap(raw, submap, Cache.Version);

                PixelFormat PF = (Alpha) ? PixelFormat.Format32bppArgb : PixelFormat.Format32bppRgb;

                Bitmap     bitmap2          = new Bitmap(submap.Width, submap.Height, PF);
                Rectangle  rect             = new Rectangle(0, 0, submap.Width, submap.Height);
                BitmapData bitmapdata       = bitmap2.LockBits(rect, ImageLockMode.WriteOnly, PF);
                byte[]     destinationArray = new byte[(submap.Width * submap.Height) * pLength];

                for (int j = 0; j < submap.Height; j++)
                {
                    Array.Copy(raw, j * vWidth * pLength, destinationArray, j * submap.Width * pLength, submap.Width * pLength);
                }

                Marshal.Copy(destinationArray, 0, bitmapdata.Scan0, destinationArray.Length);
                bitmap2.UnlockBits(bitmapdata);

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                bitmap2.Save(Filename, IF);
            }
            else if (Format == BitmapFormat.DDS)
            {
                if (!Filename.EndsWith(".dds"))
                {
                    Filename += ".dds";
                }

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                var fs = new FileStream(Filename, FileMode.Create, FileAccess.Write);
                var bw = new BinaryWriter(fs);

                if (submap.Flags.Values[3])
                {
                    raw = DXTDecoder.ConvertToLinearTexture(raw, vWidth, vHeight, submap.Format);
                }

                if (submap.Format != TextureFormat.A8R8G8B8)
                {
                    for (int i = 0; i < raw.Length; i += 2)
                    {
                        Array.Reverse(raw, i, 2);
                    }
                }
                else
                {
                    for (int i = 0; i < (raw.Length); i += 4)
                    {
                        Array.Reverse(raw, i, 4);
                    }
                }

                new DDS(submap).Write(bw);
                bw.Write(raw);

                bw.Close();
                bw.Dispose();
            }
            else if (Format == BitmapFormat.RAW)
            {
                if (!Filename.EndsWith(".bin"))
                {
                    Filename += ".bin";
                }

                if (!Directory.GetParent(Filename).Exists)
                {
                    Directory.GetParent(Filename).Create();
                }

                File.WriteAllBytes(Filename, raw);
            }
            else
            {
                throw new InvalidOperationException("Invalid BitmapFormat received.");
            }
        }
예제 #5
0
        public scenario_structure_bsp(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;
            Reader.SeekTo(Address);

            #region sldt/lbsp ID
            //lbsp's sections address will be used instead of the one in sbsp
            int sectCount = 0, sectionAddress = 0, bbCount = 0, bbAddr = 0;
            foreach (var item in Cache.IndexItems)
            {
                if (item.ClassCode == "scnr")
                {
                    Reader.SeekTo(item.Offset + 160);
                    int cnt = Reader.ReadInt32();
                    int ptr = Reader.ReadInt32() - Cache.Magic;

                    int bspIndex = 0;

                    for (int i = 0; i < cnt; i++)
                    {
                        Reader.SeekTo(ptr + 336 * i + 12);
                        if (Cache.IndexItems.GetItemByID(Reader.ReadInt32()).Offset == Address)
                        {
                            bspIndex = i;
                            break;
                        }
                    }

                    Reader.SeekTo(item.Offset + 1896 + 12);
                    int sldtID = Reader.ReadInt32();
                    int sldtAddress = Cache.IndexItems.GetItemByID(sldtID).Offset;

                    Reader.SeekTo(sldtAddress + 4);
                    cnt = Reader.ReadInt32();
                    ptr = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(ptr + 32 * bspIndex + 12);
                    int lbspID = Reader.ReadInt32();
                    int lbspAddress = Cache.IndexItems.GetItemByID(lbspID).Offset;

                    Reader.SeekTo(lbspAddress + 320); //320, 512, 692
                    sectCount = Reader.ReadInt32();
                    sectionAddress = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(lbspAddress + 344); //344, 536, 716
                    bbCount = Reader.ReadInt32();
                    bbAddr = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(lbspAddress + 464); //464, 656, 836
                    geomRawID = Reader.ReadInt32();
                    break;
                }
            }
            #endregion

            Reader.SeekTo(Address + 268);
            XBounds = new Range<float>(Reader.ReadSingle(), Reader.ReadSingle());
            YBounds = new Range<float>(Reader.ReadSingle(), Reader.ReadSingle());
            ZBounds = new Range<float>(Reader.ReadSingle(), Reader.ReadSingle());

            #region Clusters Block
            Reader.SeekTo(Address + 340);
            int iCount = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < 1; i++)
                Clusters.Add(new Cluster(Cache, iOffset + 140 * i));
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 352);
            iCount = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
                Shaders.Add(new Halo4Retail.render_model.Shader(Cache, iOffset + 44 * i));
            #endregion

            #region GeometryInstances Block
            Reader.SeekTo(Address + 640);
            iCount = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
                GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 4 * i));

            #region Load Fixup Data
            Reader.SeekTo(Address + 1364);
            int id = Reader.ReadInt32();
            var entry = Cache.zone.RawEntries[id & 0xFFFF];
            var er = new EndianReader(new MemoryStream(Cache.GetRawFromID(id)), EndianFormat.Big);
            int addr = entry.Fixups[entry.Fixups.Count - 10].Offset;

            for (int i = 0; i < GeomInstances.Count; i++)
            {
                er.SeekTo(addr + 148 * i);
                var geom = GeomInstances[i];

                geom.TransformScale = er.ReadSingle();

                geom.TransformMatrix = Matrix4x3.Read(er);

                er.ReadUInt16();
                er.ReadUInt16();
                er.ReadInt32();
                er.ReadUInt16();
                geom.SectionIndex = er.ReadUInt16();
            }
            er.Close();
            er.Dispose();
            #endregion
            #endregion

            Reader.SeekTo(Address + 844);
            RawID1 = Reader.ReadInt32();

            Reader.SeekTo(Address + 1048);
            RawID2 = Reader.ReadInt32();

            #region ModelSections Block
            Reader.SeekTo(Address + 1144);
            iCount = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            if (sectionAddress == -Cache.Magic) sectionAddress = iOffset; //null address in lbsp
            for (int i = 0; i < sectCount; i++)
                ModelSections.Add(new Halo4Retail.render_model.ModelSection(Cache, sectionAddress + 112 * i));
            #endregion

            #region Bounding Boxes Block
            Reader.SeekTo(Address + 1168);
            iCount = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < bbCount; i++)
                BoundingBoxes.Add(new Halo4Retail.render_model.BoundingBox(Cache, bbAddr + 52 * i));
            #endregion

            Reader.SeekTo(Address + 1288);
            RawID3 = Reader.ReadInt32();
        }