public BitmapInjectionForm(HaloMap.Map.Map Map, string Filename, ParsedBitmap ParsedBitm, int NumDDS) { InitializeComponent(); this.bitm = ParsedBitm; this.filename = Filename; this.map = Map; // Load the DDS info & picture loadDDSInfo(filename, this.bitm); // Get the filename variable from the path / filename combo string fname = filename.Substring(filename.LastIndexOf('\\') + 1); // Populate Bitmap Injection box with number of bitmaps in current selection for (int i = 0; i < NumDDS; i++) { lbInjectionBitmap.Items.Add("Bitmap #" + i.ToString()); } #region inject_Form this.Text = "Inject " + fname + " to..."; if (lbInjectionBitmap.Items.Count > 0) { lbInjectionBitmap.SelectedIndex = 0; } #endregion }
/// <summary> /// Initializes a new instance of the <see cref="BitmapControl"/> class. /// </summary> /// <param name="map">The map.</param> /// <remarks></remarks> public BitmapControl(Map map) { InitializeComponent(); this.map = map; map.OpenMap(MapTypes.Internal); pm = new ParsedBitmap(ref map.SelectedMeta, map); for (int x = 0; x < pm.Properties.Length; x++) { TreeNode tn = new TreeNode("Bitmap #" + x); tn.Tag = "BITMAP"; for (int i = 0; i < map.SelectedMeta.raw.rawChunks.Count; i++) { int count = pm.Properties[x].mipMapCount; BitmapRawDataChunk bmRaw = (BitmapRawDataChunk)map.SelectedMeta.raw.rawChunks[i]; if (bmRaw.inchunk == x) { TreeNode chunknode = new TreeNode("Chunk #" + bmRaw.num); chunknode.Tag = "CHUNK"; int chunkWidth = pm.Properties[x].width >> bmRaw.num; int mipcount = 0; while (chunkWidth > 1 && count > 0) { TreeNode mipnode = new TreeNode("Mipmap #" + (mipcount++)); mipnode.Tag = "MIPMAP"; chunknode.Nodes.Add(mipnode); chunkWidth >>= 1; count--; } tn.Nodes.Add(chunknode); } } treeView1.Nodes.Add(tn); } map.CloseMap(); DisplayBitmap(0, 0, 0); }
// Used for Injection Selection box /// <summary> /// The convert to bump map tool strip menu item_ click. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> /// <remarks></remarks> private void convertToBumpMapToolStripMenuItem_Click(object sender, EventArgs e) { if (saveBitmapDialog1.ShowDialog() == DialogResult.Cancel) { return; } Panel p = new Panel(); Renderer r = new Renderer(); r.CreateDevice(p); map.OpenMap(MapTypes.Internal); ParsedBitmap pm = new ParsedBitmap(ref map.SelectedMeta, map); Bitmap b = pm.FindChunkAndDecode(0, 0, 0, ref map.SelectedMeta, map, 0, 0); ShaderInfo s = new ShaderInfo(); s.BumpMapBitmap = b; map.CloseMap(); s.MakeTextures(ref r.device); TextureLoader.Save(saveBitmapDialog1.FileName, ImageFileFormat.Dds, s.NormalMap); }
public void loadDDSInfo(string filename, ParsedBitmap pb) { FileStream fs = new FileStream(filename, FileMode.Open); BinaryReader br = new BinaryReader(fs); dds.ReadStruct(ref br); // Determine Format Type ParsedBitmap.BitmapType bitmapType = ParsedBitmap.BitmapType.BITM_TYPE_2D; if (((int)DDS.DDSEnum.DDSCAPS2_VOLUME & dds.ddsd.ddsCaps.caps2) > 0) bitmapType = ParsedBitmap.BitmapType.BITM_TYPE_3D; else if (((int)DDS.DDSEnum.DDSCAPS2_CUBEMAP & dds.ddsd.ddsCaps.caps2) > 0) bitmapType = ParsedBitmap.BitmapType.BITM_TYPE_CUBEMAP; // Used to display external (file) bitmap to be injected int tempsize = dds.ddsd.width * dds.ddsd.height; switch (dds.ddsd.ddfPixelFormat.FourCC) { case "DXT1": tempsize /= 2; break; case "DXT2": case "DXT3": case "DXT4": case "DXT5": // tempsize /= 1; break; // for non-compressed default: tempsize *= dds.ddsd.ddfPixelFormat.RGBBitCount >> 3; break; } int widthPad = 0; if (dds.ddsd.width % 16 != 0) widthPad = 16 - dds.ddsd.width % 16; int byteStep = dds.ddsd.ddfPixelFormat.RGBBitCount / 8; /* int totalSize = tempsize + (dds.ddsd.height * widthPad * byteStep); if (bitmapType == ParsedBitmap.BitmapType.BITM_TYPE_CUBEMAP) totalSize *= 6; byte[] guh = new byte[totalSize]; */ byte[] guh = new byte[br.BaseStream.Length-br.BaseStream.Position]; // + (widthPad * dds.ddsd.height * byteStep)]; br.BaseStream.Read(guh, 0, guh.Length); // Determine DDS Format ParsedBitmap.BitmapFormat bmf = DDS.getBitmapFormat(dds); // G8B8 same as A8Y8 (found as A8Y8), but adjusted to 128 as center if (bmf == ParsedBitmap.BitmapFormat.BITM_FORMAT_A8Y8 && pb.Properties[0].formatname == ParsedBitmap.BitmapFormat.BITM_FORMAT_G8B8) { for (int ii = 0; ii < guh.Length; ii++) { guh[ii] += 128; } bmf = ParsedBitmap.BitmapFormat.BITM_FORMAT_G8B8; } pbSourceDDS.Image = ParsedBitmap.DecodeBitm( guh, dds.ddsd.height, dds.ddsd.width, dds.ddsd.depth, dds.ddsd.ddfPixelFormat.RGBBitCount, bitmapType, bmf, false, null, -1, -1); br.Close(); fs.Close(); #region Fill the source info box with the DDS information this.lbSourceDDS.Items.Add("Aspect : " + dds.ddsd.width + "x" + dds.ddsd.height); this.lbSourceDDS.Items.Add("w/ Pad : " + (dds.ddsd.width + widthPad) + "x" + dds.ddsd.height); int bpp = 32; string format = string.Empty; switch (dds.ddsd.ddfPixelFormat.FourCC) { case "DXT1": format = "DXT1"; break; case "DXT2": case "DXT3": format = "DXT2AND3"; break; case "DXT4": case "DXT5": format = "DXT4AND5"; break; default: bpp = dds.ddsd.ddfPixelFormat.RGBBitCount; int aCount = 0; int rCount = 0; int gCount = 0; int bCount = 0; for (int i = 0; i < bpp; i++) { // # of alpha bits if ((dds.ddsd.ddfPixelFormat.RGBAlphaBitMask & (1 << i)) != 0) { aCount++; } // # of red bits if ((dds.ddsd.ddfPixelFormat.RBitMask & (1 << i)) != 0) { rCount++; } // # of green bits if ((dds.ddsd.ddfPixelFormat.GBitMask & (1 << i)) != 0) { gCount++; } // # of blue bits if ((dds.ddsd.ddfPixelFormat.BBitMask & (1 << i)) != 0) { bCount++; } } if ((aCount > 0) && ((dds.ddsd.ddfPixelFormat.Flags & 0x03) > 0)) { format += "A" + aCount; } else if (bpp - (rCount + gCount + bCount) > 0) { format += "X" + (bpp - (rCount + gCount + bCount)); } if (rCount > 0) { format += "R" + rCount; } if (gCount > 0) { format += "G" + gCount; } if (bCount > 0) { format += "B" + bCount; } break; } lbSourceDDS.Items.Add("BPP : " + bpp); lbSourceDDS.Items.Add("Type : " + bitmapType.ToString().Substring(10)); lbSourceDDS.Items.Add("Format : " + format); // remove "BITMAP_FORMAT_" lbSourceDDS.Items.Add("# Mips : " + Math.Max(dds.ddsd.MipMapCount - 1, 0)); #endregion }
/// <summary> /// The h 2 shader info. /// </summary> /// <param name="TagIndex">The TagIndex.</param> /// <param name="map">The map.</param> /// <remarks></remarks> public void H2ShaderInfo(int TagIndex, Map map) { bool alreadyOpen = true; if (!(map.isOpen && map.openMapType == MapTypes.Internal)) { map.OpenMap(MapTypes.Internal); alreadyOpen = false; } this.TagIndex = TagIndex; if (this.TagIndex == -1) { return; } this.shaderName = map.FileNames.Name[this.TagIndex]; map.BR.BaseStream.Position = map.MetaInfo.Offset[this.TagIndex] + 4; int tempstem = map.Functions.ForMeta.FindMetaByID(map.BR.ReadInt32()); if (tempstem != -1) { if (map.FileNames.Name[tempstem].IndexOf("alphatest") != -1) { this.Alpha = AlphaType.AlphaTest; } else if (map.FileNames.Name[tempstem].IndexOf("alpha") != -1) { this.Alpha = AlphaType.AlphaBlend; } else if (map.FileNames.Name[tempstem].IndexOf("water") != -1) { this.Alpha = AlphaType.AlphaBlend; } else { this.Alpha = AlphaType.None; } } else { this.Alpha = AlphaType.None; } map.BR.BaseStream.Position = map.MetaInfo.Offset[this.TagIndex] + 12; int tempc2 = map.BR.ReadInt32(); int tempr2 = map.BR.ReadInt32() - map.SecondaryMagic; if (tempc2 != 0) { map.BR.BaseStream.Position = tempr2 + 4; int tempcrap = map.Functions.ForMeta.FindMetaByID(map.BR.ReadInt32()); if (tempcrap != -1) { Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(tempcrap, false); ParsedBitmap pm = new ParsedBitmap(ref tempmeta, map); this.MainBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); this.MainName = map.FileNames.Name[tempcrap]; this.levels = pm.Properties[0].mipMapCount; } } //map.OpenMap(MapTypes.Internal); map.BR.BaseStream.Position = map.MetaInfo.Offset[this.TagIndex] + 32; tempc2 = map.BR.ReadInt32(); tempr2 = map.BR.ReadInt32() - map.SecondaryMagic; map.BR.BaseStream.Position = tempr2 + 24; int fuckr = map.BR.ReadInt32(); if (fuckr != 0) { fuckr -= map.SecondaryMagic; map.BR.BaseStream.Position = fuckr; this.primarydetailuscale = map.BR.ReadSingle(); this.primarydetailvscale = map.BR.ReadSingle(); this.primarydetailwscale = map.BR.ReadSingle(); map.BR.ReadSingle(); this.secondarydetailuscale = map.BR.ReadSingle(); this.secondarydetailvscale = map.BR.ReadSingle(); this.secondarydetailwscale = map.BR.ReadSingle(); } map.BR.BaseStream.Position = tempr2 + 4; tempc2 = map.BR.ReadInt32(); tempr2 = map.BR.ReadInt32() - map.SecondaryMagic; /* for (int x = 0; x < tempc2; x++) { map.BR.BaseStream.Position = tempr2 + (x * 12); int tempcrap = map.Functions.Meta.FindMetaByID(map.BR.ReadInt32(), map); if (tempcrap == -1) { continue; } Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(tempcrap, map, false); Raw.ParsedBitmap pm = new Raw.ParsedBitmap(ref tempmeta, map); Bitmaps.Add(pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0)); BitmapNames.Add(map.FileNames.Name[tempcrap]); } */ // map.BR.BaseStream.Position = tempr + 20; // tempc2 = map.BR.ReadInt32(); // tempr2 = map.BR.ReadInt32() - map.SecondaryMagic; // tempc2 = tempc; // tempr2 = tempr; if (tempc2 != 0) { map.BR.BaseStream.Position = tempr2; int tempcrap = map.Functions.ForMeta.FindMetaByID(map.BR.ReadInt32()); if (tempcrap != -1) { int test = map.FileNames.Name[tempcrap].IndexOf("reflection_maps"); if (map.FileNames.Name[tempcrap].IndexOf("_bump") != -1) { Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(tempcrap, false); ParsedBitmap pm = new ParsedBitmap(ref tempmeta, map); // this.BumpMapBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); this.BumpMapName = map.FileNames.Name[tempcrap]; } else if (map.FileNames.Name[tempcrap].IndexOf("_cube_map") != -1) { Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(tempcrap, false); ParsedBitmap pm = new ParsedBitmap(ref tempmeta, map); // this.CubeMapBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); this.CubeMapName = map.FileNames.Name[tempcrap]; } else if (map.FileNames.Name[tempcrap].IndexOf("default_") == -1 && this.MainBitmap == null && test == -1) { Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(tempcrap, false); ParsedBitmap pm = new ParsedBitmap(ref tempmeta, map); // Try to load LOD2-MIP3 if that fails, load LOD2-MIP0, otherwise LOD0-MIP0 this.MainBitmap = pm.FindChunkAndDecode(0, 2, 3, ref tempmeta, map, 0, 0); if (this.MainBitmap == null) { this.MainBitmap = pm.FindChunkAndDecode(0, 2, 0, ref tempmeta, map, 0, 0); if (this.MainBitmap == null) this.MainBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); } this.MainName = map.FileNames.Name[tempcrap]; this.levels = pm.Properties[0].mipMapCount; } else if (test != -1) { map.BR.BaseStream.Position += 8; tempcrap = map.Functions.ForMeta.FindMetaByID(map.BR.ReadInt32()); Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(tempcrap, false); ParsedBitmap pm = new ParsedBitmap(ref tempmeta, map); // this.MainBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map); // this.MainName = map.FileNames.Name[tempcrap]; } } map.BR.BaseStream.Position = tempr2 + 24; tempcrap = map.Functions.ForMeta.FindMetaByID(map.BR.ReadInt32()); if (tempcrap != -1 && this.MainBitmap == null) { Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(tempcrap, false); ParsedBitmap pm = new ParsedBitmap(ref tempmeta, map); this.MainBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); this.MainName = map.FileNames.Name[tempcrap]; this.levels = pm.Properties[0].mipMapCount; } else if (this.MainBitmap == null) { map.BR.BaseStream.Position = tempr2 + 12; tempcrap = map.Functions.ForMeta.FindMetaByID(map.BR.ReadInt32()); if (tempcrap != -1) { Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(tempcrap, false); ParsedBitmap pm = new ParsedBitmap(ref tempmeta, map); this.MainBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); this.MainName = map.FileNames.Name[tempcrap]; this.levels = pm.Properties[0].mipMapCount; } } } if (!alreadyOpen) { map.CloseMap(); } }
public DDS(ParsedBitmap.BitmapInfo bmInfo, FileStream fs) { this.classType = classTypes.DDS; this.BitsPerPixel = bmInfo.bitsPerPixel; this.Width = bmInfo.width; this.Height = bmInfo.height; this.Depth = bmInfo.depth; this.Format = bmInfo.format; this.FormatName = bmInfo.formatname; this.Compressed = bmInfo.format.ToString().ToUpper().Contains("DXT"); this.Swizzle = bmInfo.swizzle; this.MipMapCount = bmInfo.mipMapCount; this.stream = fs; this.streamOffset = (int)fs.Position; this.streamSize = (int)fs.Length; }
/// <summary> /// The btn load image_ click. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> /// <remarks></remarks> private void btnLoadImage_Click(object sender, EventArgs e) { OpenFileDialog getImage = new OpenFileDialog(); getImage.InitialDirectory = Prefs.pathBitmapsFolder; getImage.DefaultExt = "dds"; getImage.Filter = "DDS & Map files|*.dds;*.map|DDS files (*.dds)|*.dds|Map Files (*.map)|*.map"; if (getImage.ShowDialog() == DialogResult.OK) { Prefs.pathBitmapsFolder = getImage.FileName.Substring(0, getImage.FileName.LastIndexOf('\\')); if (getImage.FileName.EndsWith("dds", StringComparison.OrdinalIgnoreCase)) { FileStream fs = new FileStream(getImage.FileName, FileMode.Open); BinaryReader br = new BinaryReader(fs); DDS.DDS_HEADER_STRUCTURE dds = new DDS.DDS_HEADER_STRUCTURE(); dds.ReadStruct(ref br); int tempsize = dds.ddsd.width * dds.ddsd.height; switch (dds.ddsd.ddfPixelFormat.FourCC) { case "DXT1": tempsize /= 2; break; case "DXT2": case "DXT3": case "DXT4": case "DXT5": // tempsize /= 1; break; // for non-compressed default: tempsize *= dds.ddsd.ddfPixelFormat.RGBBitCount >> 3; break; } int widthPad = 0; if (dds.ddsd.width % 16 != 0) widthPad = 16 - dds.ddsd.width % 16; int byteStep = dds.ddsd.ddfPixelFormat.RGBBitCount / 8; byte[] guh = new byte[tempsize + (dds.ddsd.height * widthPad * byteStep)]; if (widthPad == 0) { br.BaseStream.Read(guh, 0, guh.Length); } else { // Change data to include padding for (int h = 0; h < dds.ddsd.height; h++) { br.BaseStream.Read( guh, h * (dds.ddsd.width + widthPad) * byteStep, dds.ddsd.width * byteStep); } } br.Close(); fs.Close(); int tagNum = map.Functions.ForMeta.FindMetaByID( currentLevels[lbMapListing.SelectedIndex].Preview_Image_Ident); if (tagNum != -1) { map.SelectedMeta = Map.GetMetaFromTagIndex(tagNum, map, false, false); } #region Confirm 224x207 A8R8G8B8 file and save to CurrentLevel[].ScreenShot & Cur...[].ScreenShotRaw ParsedBitmap.BitmapFormat bmf = DDS.getBitmapFormat(dds); if ((bmf == ParsedBitmap.BitmapFormat.BITM_FORMAT_A8R8G8B8) && (dds.ddsd.width + widthPad == 224) && (dds.ddsd.height == 207)) { currentLevels[lbMapListing.SelectedIndex].screenShotRaw.MS.Position = 0; currentLevels[lbMapListing.SelectedIndex].screenShotRaw.MS.Write( guh, 0, (int)Math.Min(map.SelectedMeta.raw.rawChunks[0].MS.Length, guh.Length)); currentLevels[lbMapListing.SelectedIndex].screenShotRaw.size = (int)currentLevels[lbMapListing.SelectedIndex].screenShotRaw.MS.Length; currentLevels[lbMapListing.SelectedIndex].screenShot = ParsedBitmap.DecodeBitm( guh, dds.ddsd.height, dds.ddsd.width, dds.ddsd.depth, dds.ddsd.ddfPixelFormat.RGBBitCount, ParsedBitmap.BitmapType.BITM_TYPE_2D, bmf, false, null, -1, -1); pbMapBitmap.Image = currentLevels[lbMapListing.SelectedIndex].screenShot; } else { MessageBox.Show("Bitmap must be a 224x207 A8R8G8B8 file"); } #endregion } else if (getImage.FileName.EndsWith("map", StringComparison.OrdinalIgnoreCase)) { this.Enabled = false; Map tempmap = Map.LoadFromFile(getImage.FileName); this.Enabled = true; if (tempmap == null) { MessageBox.Show("Unable to load image from map: " + getImage.FileName); return; } // Load Map Picture as raw data (for transfer) and Bitmap (for display) tempmap.OpenMap(MapTypes.Internal); Meta m = MapForm.GetMapBitmapMeta(tempmap); ////////////////////////////////// // Backwash for example has no internal picture, so it errors. ////////////////////////////////// if (m != null) { currentLevels[lbMapListing.SelectedIndex].screenShotRaw = m.raw.rawChunks[0]; ParsedBitmap pm = new ParsedBitmap(ref m, tempmap); currentLevels[lbMapListing.SelectedIndex].screenShot = pm.FindChunkAndDecode( 0, 0, 0, ref m, tempmap, 0, 0); } else { // No map listing found } tempmap.CloseMap(); pbMapBitmap.Image = currentLevels[lbMapListing.SelectedIndex].screenShot; } } }
/// <summary> /// The decode dds. /// </summary> /// <param name="sourceBytes">The source bytes.</param> /// <param name="b2">The b 2.</param> /// <returns></returns> /// <remarks></remarks> public static Bitmap DecodeDDS(byte[] sourceBytes, ParsedBitmap.BitmapInfo b2) { //// //// Check type name and handle 2D, 3D & Cubemaps //// // b2.typename; //// byte[] poo = new byte[0]; IntPtr ptr = new IntPtr(); PixelFormat o = new PixelFormat(); int poolength; byte[] fu; DecodeDXT decode = new DecodeDXT(); int oldwidth = b2.width; if (b2.width % 16 != 0) b2.width = (ushort)(b2.width + (16 - (b2.width % 16))); int stride = b2.width; if (b2.swizzle) { sourceBytes = Swizzler.Swizzle(sourceBytes, b2.width, b2.height, b2.depth, b2.bitsPerPixel, true); } switch (b2.formatname) { #region DXT1 case (ParsedBitmap.BitmapFormat)14: if (b2.swizzle) { MessageBox.Show("Swizzled"); } sourceBytes = decode.DecodeDXT1(b2.height, b2.width, sourceBytes); stride *= 4; o = PixelFormat.Format32bppArgb; break; #endregion #region DXT2/3 case (ParsedBitmap.BitmapFormat)15: if (b2.swizzle) { MessageBox.Show("Swizzled"); } sourceBytes = decode.DecodeDXT23(b2.height, b2.width, sourceBytes); stride *= 4; o = PixelFormat.Format32bppArgb; break; #endregion #region DXT 4/5 case (ParsedBitmap.BitmapFormat)16: if (b2.swizzle) { MessageBox.Show("Swizzled"); } sourceBytes = decode.DecodeDXT45(b2.height, b2.width, sourceBytes); stride *= 4; o = PixelFormat.Format32bppArgb; break; #endregion #region A8R8G8B8 case (ParsedBitmap.BitmapFormat)11: stride *= 4; o = PixelFormat.Format32bppArgb; break; #endregion #region X8R8G8B8 case (ParsedBitmap.BitmapFormat)10: stride *= 4; o = PixelFormat.Format32bppArgb; break; #endregion #region // 16 bit \\ #region A4R4G4B4 case (ParsedBitmap.BitmapFormat)9: stride *= 4; o = PixelFormat.Format32bppArgb; poolength = sourceBytes.Length; fu = new byte[poolength * 2]; for (int e = 0; e < poolength / 2; e++) { int r = e * 2; fu[r * 2 + 0] = (byte)((sourceBytes[r + 1] & 0xFF) >> 0); // Blue fu[r * 2 + 1] = (byte)((sourceBytes[r + 0] & 0xFF) >> 0); // Green fu[r * 2 + 2] = (byte)((sourceBytes[r + 0] & 0xFF) >> 0); // Red fu[r * 2 + 3] = 255; // (byte)(((sourceBytes[r + 1] & 0xFF) >> 0)); // Alpha } sourceBytes = fu; break; #endregion #region G8B8 case (ParsedBitmap.BitmapFormat)22: stride *= 4; o = PixelFormat.Format32bppArgb; poolength = sourceBytes.Length; fu = new byte[poolength / 2 * 4]; // These are actually signed (+/-128), so convert to unsigned for (int e = 0; e < poolength / 2; e++) { int r = e * 2; fu[r * 2 + 0] = (byte)(sourceBytes[r + 1] + 128); // Blue fu[r * 2 + 1] = (byte)(sourceBytes[r + 1] + 128); // Green fu[r * 2 + 2] = (byte)(sourceBytes[r + 0] + 128); // Red fu[r * 2 + 3] = (byte)(sourceBytes[r + 0] + 128); // Alpha } sourceBytes = fu; break; #endregion #region A1R5G5B5 case (ParsedBitmap.BitmapFormat)8: stride *= 2; o = PixelFormat.Format16bppRgb555; break; #endregion #region R5G6B5 case (ParsedBitmap.BitmapFormat)6: stride *= 2; o = PixelFormat.Format16bppRgb565; break; #endregion #region A8Y8 case (ParsedBitmap.BitmapFormat)3: o = PixelFormat.Format32bppArgb; poolength = sourceBytes.Length; fu = new byte[poolength / 2 * 4]; for (int e = 0; e < poolength / 2; e++) { int r = e * 2; fu[r * 2 + 0] = sourceBytes[r + 1]; fu[r * 2 + 1] = sourceBytes[r + 1]; fu[r * 2 + 2] = sourceBytes[r + 1]; fu[r * 2 + 3] = sourceBytes[r + 0]; } sourceBytes = fu; stride *= 4; break; #endregion #endregion #region // 8 bit \\ #region P8 case ParsedBitmap.BitmapFormat.BITM_FORMAT_P8: o = PixelFormat.Format32bppArgb; poolength = sourceBytes.Length; fu = new byte[poolength * 4]; for (int e = 0; e < poolength; e++) { int r = e * 4; fu[r + 0] = sourceBytes[e]; fu[r + 1] = sourceBytes[e]; fu[r + 2] = sourceBytes[e]; fu[r + 3] = 255; } sourceBytes = fu; stride *= 4; break; #endregion #region A8 case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8: o = PixelFormat.Format32bppArgb; poolength = sourceBytes.Length; fu = new byte[poolength * 4]; for (int e = 0; e < poolength; e++) { int r = e * 4; fu[r + 0] = sourceBytes[e]; fu[r + 1] = sourceBytes[e]; fu[r + 2] = sourceBytes[e]; fu[r + 3] = 255; } sourceBytes = fu; stride *= 4; break; #endregion #region AY8 case ParsedBitmap.BitmapFormat.BITM_FORMAT_AY8: o = PixelFormat.Format32bppArgb; poolength = sourceBytes.Length; fu = new byte[poolength * 4]; for (int e = 0; e < poolength; e++) { int r = e * 4; /* fu[r + 0] = (byte)((sourceBytes[e] & 0x0F) * 255 / 15 + 128); fu[r + 1] = (byte)((sourceBytes[e] & 0x0F) * 255 / 15 + 128); fu[r + 2] = (byte)((sourceBytes[e] & 0x0F) * 255 / 15 + 128); */ fu[r + 0] = (byte)(((sourceBytes[e] & 0xF0) >> 4) * 255 / 15); fu[r + 1] = (byte)(((sourceBytes[e] & 0xF0) >> 4) * 255 / 15); fu[r + 2] = (byte)(((sourceBytes[e] & 0xF0) >> 4) * 255 / 15); fu[r + 3] = (byte)((sourceBytes[e] & 0x0F) * 255 / 15); /* fu[r + 0] = (byte)((sourceBytes[e] & 0x0F) * 255 / 15); fu[r + 1] = (byte)((sourceBytes[e] & 0x0F) * 255 / 15); fu[r + 2] = (byte)((sourceBytes[e] & 0x0F) * 255 / 15); fu[r + 3] = (byte)(((sourceBytes[e] & 0xF0) >> 3) * 255 / 15); if (sourceBytes[e] == 0) fu[r + 3] = 0; else fu[r + 3] = 255; */ } sourceBytes = fu; stride *= 4; break; #endregion #region Y8 case (ParsedBitmap.BitmapFormat)1: o = PixelFormat.Format32bppArgb; poolength = sourceBytes.Length; fu = new byte[poolength * 4]; for (int e = 0; e < poolength; e++) { int r = e * 4; fu[r + 0] = sourceBytes[e]; fu[r + 1] = sourceBytes[e]; fu[r + 2] = sourceBytes[e]; fu[r + 3] = 255; } sourceBytes = fu; stride *= 4; break; #endregion /* #region LightMap case ParsedBitmap.BitmapFormat.BITM_FORMAT_LIGHTMAP: o = PixelFormat.Format32bppArgb;// Format32bppArgb; poolength = sourceBytes.Length; fu = new byte[poolength * 4]; int bspnumber = ident; int paletteindex = -1; if (visualchunkindex < 0) { int wtf = 0 - (visualchunkindex + 1); paletteindex = map.BSP.sbsp[bspnumber].SceneryChunk_LightMap_Index[wtf]; } if (paletteindex == -1) for (int i = 0; i < map.BSP.sbsp[bspnumber].VisualChunk_Bitmap_Index.Length; i++) if (map.BSP.sbsp[bspnumber].VisualChunk_Bitmap_Index[i] == visualchunkindex) { paletteindex = map.BSP.sbsp[bspnumber].VisualChunk_LightMap_Index[visualchunkindex]; break; } if (paletteindex == -1) for (int i = 0; i < map.BSP.sbsp[bspnumber].SceneryChunk_Bitmap_Index.Length; i++) if (map.BSP.sbsp[bspnumber].SceneryChunk_Bitmap_Index[i] == visualchunkindex) { paletteindex = map.BSP.sbsp[bspnumber].SceneryChunk_LightMap_Index[i]; break; } if (paletteindex == 255) return null; for (int e = 0; e < poolength; e++) { int r = e * 4; fu[r + 0] = (byte)map.BSP.sbsp[bspnumber].LightMap_Palettes[paletteindex][sourceBytes[e]].r; fu[r + 1] = (byte)map.BSP.sbsp[bspnumber].LightMap_Palettes[paletteindex][sourceBytes[e]].g; fu[r + 2] = (byte)map.BSP.sbsp[bspnumber].LightMap_Palettes[paletteindex][sourceBytes[e]].b; fu[r + 3] = (byte)map.BSP.sbsp[bspnumber].LightMap_Palettes[paletteindex][sourceBytes[e]].a; } sourceBytes = fu; stride *= 4; break; #endregion */ #endregion default: return null; } Marshal.FreeHGlobal(ptr); ptr = Marshal.AllocHGlobal(sourceBytes.Length); RtlMoveMemory(ptr, sourceBytes, sourceBytes.Length); return new Bitmap(b2.width, b2.height, stride, o, ptr); }
////////////////////////////////////////////////////// // Generate the DDSCAPS2 chunk of the header ////////////////////////////////////////////////////// #region Public Methods /// <summary> /// The generate. /// </summary> /// <param name="b2">The b 2.</param> /// <remarks></remarks> public void generate(ref ParsedBitmap.BitmapInfo b2) { // DDS files should always include DDSCAPS_TEXTURE. If the file contains mipmaps, DDSCAPS_MIPMAP // should be set. For any DDS file with more than one main surface,such as a mipmaps, cubic // environment map, or volume texture, DDSCAPS_COMPLEX should also be set. caps1 += (int)DDSEnum.DDSCAPS_TEXTURE; if (b2.mipMapCount > 0) { caps1 += (int)DDSEnum.DDSCAPS_MIPMAP; } caps1 += (int)DDSEnum.DDSCAPS_COMPLEX; // For cubic environment maps, DDSCAPS2_CUBEMAP should be included as well as one or more faces of // the map (DDSCAPS2_CUBEMAP_POSITIVEX, DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, // DDSCAPS2_CUBEMAP_NEGATIVEY, DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ). For volume // textures, DDSCAPS2_VOLUME should be included. // ****************************************************************************** // This is where I stopped - this code needs to be added for cubemaps. // ****************************************************************************** caps2 = 0; if (b2.typename == ParsedBitmap.BitmapType.BITM_TYPE_3D) { caps2 += (int)DDSEnum.DDSCAPS2_VOLUME; } if (b2.typename == ParsedBitmap.BitmapType.BITM_TYPE_CUBEMAP) { caps2 += (int)DDSEnum.DDSCAPS2_CUBEMAP; caps2 += (int)DDSEnum.DDSCAPS2_CUBEMAP_NEGATIVEX; caps2 += (int)DDSEnum.DDSCAPS2_CUBEMAP_NEGATIVEY; caps2 += (int)DDSEnum.DDSCAPS2_CUBEMAP_NEGATIVEZ; caps2 += (int)DDSEnum.DDSCAPS2_CUBEMAP_POSITIVEX; caps2 += (int)DDSEnum.DDSCAPS2_CUBEMAP_POSITIVEY; caps2 += (int)DDSEnum.DDSCAPS2_CUBEMAP_POSITIVEZ; } }
public int size; // '32 #endregion ////////////////////////////////////////////////////// // Generate the DDPIXELFORMAT chunk of the header ////////////////////////////////////////////////////// #region Public Methods /// <summary> /// The generate. /// </summary> /// <param name="b2">The b 2.</param> /// <remarks></remarks> public void generate(ParsedBitmap.BitmapInfo b2) { // Size of structure. This member must be set to 32. size = 32; // Flags to indicate valid fields. Uncompressed formats will usually use DDPF_RGB to indicate // an RGB format, while compressed formats will use DDPF_FOURCC with a four-character code. // This is accomplished in the below structure. // This is the four-character code for compressed formats. dwFlags should include DDPF_FOURCC in // this case. For DXTn compression, this is set to "DXT1", "DXT2", "DXT3", "DXT4", or "DXT5". Flags = 0; switch ((int)b2.formatname) { case 0xE: FourCC = "DXT1"; Flags = Flags + (int)DDSEnum.DDPF_FOURCC; break; case 0xF: FourCC = "DXT3"; Flags = Flags + (int)DDSEnum.DDPF_FOURCC; break; case 0x10: FourCC = "DXT5"; Flags = Flags + (int)DDSEnum.DDPF_FOURCC; break; default: FourCC = "\0\0\0\0"; Flags = Flags + (int)DDSEnum.DDPF_RGB; break; } // For RGB formats, this is the total number of bits in the format. dwFlags should include DDPF_RGB // in this case. This value is usually 16, 24, or 32. For A8R8G8B8, this value would be 32. RGBBitCount = b2.bitsPerPixel; // For RGB formats dwFlags should include DDPF_ALPHAPIXELS if it contains an alpha channel. // For A8R8G8B8, this value would be 0xff000000. switch (b2.formatname) { case ParsedBitmap.BitmapFormat.BITM_FORMAT_A1R5G5B5: case ParsedBitmap.BitmapFormat.BITM_FORMAT_A4R4G4B4: case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8R8G8B8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_G8B8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8Y8: Flags = Flags + (int)DDSEnum.DDPF_ALPHAPIXELS; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_P8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_Y8: Flags = Flags + (int)DDSEnum.DDPF_ALPHA; Flags = Flags - (int)DDSEnum.DDPF_RGB; // These formats are ALPHA ONLY, no RGB break; } // For RGB formats, this contains the masks for the red, green, and blue channels. For A8R8G8B8, these // values would be 0x00ff0000, 0x0000ff00, and 0x000000ff respectively. switch (b2.formatname) { /* RGBAlphaBitMask = 0x0000; RBitMask = 0x00FF; GBitMask = 0xFF00; BBitMask = 0x0000; Flags = 0x00080000; // Unknown flag. Used for 2 color dds files by photoshop? break; */ case ParsedBitmap.BitmapFormat.BITM_FORMAT_G8B8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8Y8: RGBAlphaBitMask = 0xFF00; RBitMask = 0x00FF; GBitMask = 0x0000; BBitMask = 0x0000; Flags -= (int)DDSEnum.DDPF_RGB; // This format doesn't use RGB Flags += 0x00020000; // Unknown flag. Used for unsigned 16-bit dds files by photoshop? break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_AY8: RGBAlphaBitMask = 0x0000; RBitMask = 0x000F; GBitMask = 0x00F0; BBitMask = 0x0000; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_P8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_Y8: RGBAlphaBitMask = 0x00FF; RBitMask = 0x0000; GBitMask = 0x0000; BBitMask = 0x0000; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_R5G6B5: RGBAlphaBitMask = 0x0000; RBitMask = 0xF800; GBitMask = 0x07E0; BBitMask = 0x001F; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A1R5G5B5: RGBAlphaBitMask = 0x8000; RBitMask = 0x7C00; GBitMask = 0x03E0; BBitMask = 0x001F; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A4R4G4B4: RGBAlphaBitMask = 0xF000; RBitMask = 0x0F00; GBitMask = 0x00F0; BBitMask = 0x000F; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_X8R8G8B8: RGBAlphaBitMask = 0x00000000; RBitMask = 0x00FF0000; GBitMask = 0x0000FF00; BBitMask = 0x000000FF; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8R8G8B8: RGBAlphaBitMask = 0xFF000000; RBitMask = 0x00FF0000; GBitMask = 0x0000FF00; BBitMask = 0x000000FF; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_LIGHTMAP: RGBAlphaBitMask = 0x00000000; RBitMask = 0x000000FF; GBitMask = 0x000000FF; BBitMask = 0x000000FF; Flags -= (int)DDSEnum.DDPF_RGB; // This format doesn't use RGB Flags += 0x00020000; // Unknown flag. Used for unsigned 16-bit dds files by photoshop? break; default: RGBAlphaBitMask = 0x0; RBitMask = 0; GBitMask = 0; BBitMask = 0; break; } }
private void timer1_Tick(object sender, EventArgs e) { if (map.SelectedMeta.type != "bitm") { timer1.Stop(); return; } if (!showAnimatedBitmapsToolStripMenuItem.Checked) return; ParsedBitmap pm = new ParsedBitmap(ref map.SelectedMeta, map); // Show next frame of 3D images if (pm.Properties[0].typename == ParsedBitmap.BitmapType.BITM_TYPE_3D) #region 3D images { pictureBox1.Image.Dispose(); // For 3D images, bitmapCount = pm.Properties[0].depth + 1 because index 0 is an overview if (bitmapCount > pm.Properties[0].depth) bitmapCount = 1; Bitmap b = pm.FindChunkAndDecode(0, 0, 0, ref map.SelectedMeta, map, bitmapCount++, 0); pictureBox1.Image = b; return; } #endregion // For Sequenced images, show next sprite else #region 2D Sequenced Images { int sprites = 1; BinaryReader br = new BinaryReader(map.SelectedMeta.MS); br.BaseStream.Seek(60, SeekOrigin.Begin); int seqCount = br.ReadInt32(); int seqOffset = br.ReadInt32() - map.SelectedMeta.magic - map.SelectedMeta.offset; if (seqCount > 0) { // Allows the animated picture to cycle through different animations every 6 seconds int sequenceSelect = (DateTime.Now.Minute * 60 + DateTime.Now.Second) / 6 % seqCount; br.BaseStream.Seek(seqOffset + sequenceSelect * 60 + 32, SeekOrigin.Begin); int bitmIndex = br.ReadInt16(); // Always 0? int bitmCount = br.ReadInt16(); // Always 0? #if DEBUG if (bitmIndex + bitmCount > 0) { //MessageBox.Show("DEBUG ONLY: Found a Bitmap with Index or Count > 0"); } #endif br.BaseStream.Seek(seqOffset + sequenceSelect * 60 + 52, SeekOrigin.Begin); int sprCount = br.ReadInt32(); int sprOffset = br.ReadInt32() - map.SelectedMeta.magic - map.SelectedMeta.offset; if (sprCount != 0) { if (pictureBox1.Tag == null) pictureBox1.Tag = 0; int currentSprite = (int)pictureBox1.Tag; pictureBox1.Tag = currentSprite = (currentSprite + 1) % sprCount; // Each sprite record is 32 bytes in length, values start at offset 8 br.BaseStream.Seek(sprOffset + currentSprite * 32 + 8, SeekOrigin.Begin); // The following are ratios between 0 - 1) float Left = br.ReadSingle(); float Right = br.ReadSingle(); float Top = br.ReadSingle(); float Bottom = br.ReadSingle(); Bitmap b = pm.FindChunkAndDecode(bitmIndex, 0, 0, ref map.SelectedMeta, map, 0, 0); if (pictureBox1.Image != null) { ((IDisposable)pictureBox1.Image).Dispose(); pictureBox1.Image = null; } pictureBox1.Image = b.Clone( new RectangleF( Left * b.Width, Top * b.Height, (Right - Left) * b.Width, (Bottom - Top) * b.Height), b.PixelFormat); if (b.Tag != null) Marshal.FreeHGlobal((IntPtr)b.Tag); b.Dispose(); return; } } } #endregion // If it is neither, stop further image updates //timer1.Stop(); }
/// <summary> /// The load meta. /// </summary> /// <param name="tag">The tag.</param> /// <remarks></remarks> public void LoadMeta(int tag) { Meta meta = Map.GetMetaFromTagIndex(tag, map, scanbspwithifp.Checked, parsedCheckBox.Checked); map.SelectedMeta = meta; buttonInternalize.Visible = false; if (meta.type == "bitm") { // ;&&Map.HaloVersion!= Map.HaloVersionEnum.Halo1 ) ParsedBitmap pm = new ParsedBitmap(ref meta, map); Bitmap b = pm.FindChunkAndDecode(0, 0, 0, ref meta, map, 0, 0); // Raw.ParsedBitmap.BitmapInfo bmInfo = new Entity.Raw.ParsedBitmap.BitmapInfo(pm.Properties[0].formatname, pm.Properties[0].swizzle); // b = DDS_Convert.DecodeDDS( DDS_Convert.EncodeDDS(b, ref bmInfo), bmInfo ); pictureBox1.Image = b; pictureBox1.Tag = 0; statusbar.Text = pm.Properties[0].width.ToString().PadLeft(4) + " X " + pm.Properties[0].height.ToString().PadRight(4) + " " + ("(" + pm.Properties[0].typename.ToString().Remove(0, 10) + ") ").PadRight(10) + pm.Properties[0].formatname.ToString().Remove(0, 12).PadRight(10) + " - Swizzle:" + pm.Properties[0].swizzle + "- Location: " + meta.raw.rawChunks[0].rawLocation; if (meta.raw.rawChunks[0].rawLocation != MapTypes.Internal) { buttonInternalize.Visible = true; } timer1.Start(); } else { statusbar.Text = string.Empty; } // Main Form Offsets/Idents/etc metaOffsetBox.Text = "0x" + meta.offset.ToString("X8") + "\n" + meta.offset.ToString("N0") + " bytes"; metaSizeBox.Text = "0x" + meta.size.ToString("X4") + "\n" + meta.size.ToString("N0") + " bytes"; metaIdentBox.Text = meta.ident.ToString("X"); metaTypeBox.Text = meta.type; if (meta.raw != null) { int tempRawSize = 0; for (int i = 0; i < meta.raw.rawChunks.Count; i++) { tempRawSize += meta.raw.rawChunks[i].size; } metaRawBox.Text = "0x" + tempRawSize.ToString("X4") + "\n" + tempRawSize.ToString("N0") + " bytes"; } else metaRawBox.Text = "n/a"; switch (meta.type) { case "PRTM": rawDataDropDown.DropDown = prtmcontext; rawDataDropDown.Enabled = true; break; case "mode": case "mod2": rawDataDropDown.DropDown = ModelContextStrip; rawDataDropDown.Enabled = true; break; case "bitm": rawDataDropDown.DropDown = BitmapContextStrip; rawDataDropDown.Enabled = true; if (ltmpTools.Visible) { bitmapEditorToolStripMenuItem_Click(bitmapEditorToolStripMenuItem, null); } break; case "sbsp": rawDataDropDown.DropDown = BSPcontextMenu; rawDataDropDown.Enabled = true; break; case "coll": rawDataDropDown.DropDown = collContextMenu; rawDataDropDown.Enabled = true; break; default: rawDataDropDown.Enabled = false; break; } switch (getEditorMode()) { case EditorModes.HexViewer: hexView1.Reload(meta, map); hexView1.Setup(map.filePath); break; case EditorModes.MetaEditor1: if (map.SelectedMeta != null) { if (this.metaEditor1.selectedTagType == map.SelectedMeta.type) { this.metaEditor1.ReloadMetaForSameTagType(true); } else { this.metaEditor1.loadControls(map); } } break; case EditorModes.MetaEditor2: if (map.SelectedMeta != null) { if (wME == null || wME.IsDisposed) { wME = new entity.MetaEditor2.WinMetaEditor(this, map); wME.BackgroundColor = this.LibraryPanel.BackColor; wME.ForegroundColor = this.LibraryPanel.ForeColor; wME.TopLevel = false; this.MetaEditor2Panel.Controls.Add(wME); MetaEditor2Panel.BringToFront(); wME.FormBorderStyle = FormBorderStyle.None; wME.FormClosed += new FormClosedEventHandler(wME_FormClosed); } // If we are not switching from a different editor mode (on MetaEditor2) and // we already have the current tag loaded in the editor, then we can load a duplicate wME.addNewTab(map.SelectedMeta, getEditorMode() == EditorModes.MetaEditor2 && wME.tabs.Tabs.Count > 0 && wME.tabs.SelectedTab.Text == ("[" + map.SelectedMeta.type + "] " + map.SelectedMeta.name.Substring(map.SelectedMeta.name.LastIndexOf('\\') + 1))); wME.Dock = DockStyle.Fill; } break; case EditorModes.ReferenceEditor: formFuncs.AddReferencesToListView(meta, references, map.DisplayType); break; } if (selectedplugin != -1 && LibraryPanel.Visible) { if (plugins.Plugin[selectedplugin].tagtype == meta.type || plugins.Plugin[selectedplugin].tagtype == "!*.*") { plugins.Plugin[selectedplugin].Run(map, ref progressbar); } } UpdatePluginsMenu(); Prefs.Save(); AddToHistory(tag); }
/// <summary> /// The save bitmap tool strip menu item_ click. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> /// <remarks></remarks> private void saveBitmapToolStripMenuItem_Click(object sender, EventArgs e) { string[] s = map.SelectedMeta.name.Split('\\'); saveBitmapDialog1.FileName = s[s.Length - 1]; saveBitmapDialog1.InitialDirectory = Prefs.pathBitmapsFolder; if (saveBitmapDialog1.ShowDialog() == DialogResult.Cancel) { return; } Prefs.pathBitmapsFolder = saveBitmapDialog1.FileName.Substring( 0, saveBitmapDialog1.FileName.LastIndexOf('\\')); // for (int index = 0; index < Map.SelectedMeta.raw.rawChunks.Count; index++) // { switch (saveBitmapDialog1.FilterIndex) { // DDS case 1: // Split save name up into parts s = new string[3]; s[0] = saveBitmapDialog1.FileName.Substring(0, saveBitmapDialog1.FileName.LastIndexOf('\\') + 1); s[1] = saveBitmapDialog1.FileName.Substring( s[0].Length, saveBitmapDialog1.FileName.LastIndexOf('.') - s[0].Length); s[2] = saveBitmapDialog1.FileName.Substring(saveBitmapDialog1.FileName.LastIndexOf('.')); int numDDS = 1; for (int i = 0; i < map.SelectedMeta.items.Count; i++) { if (map.SelectedMeta.items[i].offset == 68) { numDDS = ((MetaScanner.XReflex)map.SelectedMeta.items[i]).chunkcount; break; } } // If there is more than 1 DDS images, make a directory to hold them if (numDDS > 1) { Directory.CreateDirectory(s[0] + s[1]); } ParsedBitmap bm = new ParsedBitmap(ref map.SelectedMeta, map); bool convert = false; /* if (MessageBox.Show("Do you wish to save in the original format?", "DDS Extraction", MessageBoxButtons.YesNo) == DialogResult.No) convert = true; */ List<extractionInfo> extractInfo = new List<extractionInfo>(); // # of DDS files (not raw chunks as some are mipmaps) for (int index = 0; index < numDDS; index++) { FileStream fs; // Create the file, either in the direcotry if multiple or the single file if (numDDS > 1) { fs = new FileStream( s[0] + s[1] + "\\" + s[1] + "_" + index.ToString().PadLeft(2, '0') + s[2], FileMode.Create); } else { fs = new FileStream(saveBitmapDialog1.FileName, FileMode.Create); } BinaryWriter br = new BinaryWriter(fs); ParsedBitmap.BitmapInfo chunkInfo = null; // Conversion section disabled ATM. Maybe add it later... if (convert) { // Create Form to choose Bitmap Format Form tf = new Form(); tf.ControlBox = false; tf.Size = new Size(250, 120); tf.Text = "DDS output format"; Label tl = new Label(); tl.AutoSize = true; tl.Location = new Point(10, 2); tl.Text = "Select output format:"; ComboBox tcb = new ComboBox(); tcb.DropDownStyle = ComboBoxStyle.DropDownList; tcb.Location = new Point(10, 20); tcb.Size = new Size(200, 20); DDS.DDSFileFormat ff = DDS.getDDSType(bm.Properties[index]); string[] sa = Enum.GetNames(typeof(DDS.DDSFileFormats)); foreach (string st in sa) { tcb.Items.Add(st.Replace('_', ' ')); if (ff.Format.ToString() == st) { tcb.SelectedIndex = tcb.Items.Count - 1; } } Button tb = new Button(); tb.Location = new Point(80, 50); tb.DialogResult = DialogResult.OK; tb.Text = "&Save"; tf.Controls.Add(tl); tf.Controls.Add(tcb); tf.Controls.Add(tb); tf.ShowDialog(); string n = Enum.GetName(typeof(DDS.H2DDSFormats), tcb.SelectedIndex); ParsedBitmap.BitmapInfo bi = new ParsedBitmap.BitmapInfo(ParsedBitmap.BitmapFormat.BITM_FORMAT_A8R8G8B8, false); // DDS_Convert.DecodeDDS(); chunkInfo = DDS.ExtractDDS(map.SelectedMeta, bm, ref br, index, bi); } else { chunkInfo = DDS.ExtractDDS(map.SelectedMeta, bm, ref br, index); } // This is used to tell user expected DDS format when reinjecting DDS.DDSFileFormat DDSFF = DDS.getDDSType(chunkInfo); for (int count = 0; count <= extractInfo.Count; count++) { if (count == extractInfo.Count) { extractInfo.Add( new extractionInfo( DDSFF.Description, fs.Name.Substring(fs.Name.LastIndexOf("\\") + 1))); break; } else if (extractInfo[count].name == DDSFF.Format.ToString()) { extractInfo[count].lists.Add(fs.Name.Substring(fs.Name.LastIndexOf("\\") + 1)); } } br.Close(); fs.Close(); } // string tempS = "When reinjecting, make sure the following files are saved as the type specified:\n\n"; int retCount = 0; string tempS = "The following files have been saved as the type specified:\n\n"; for (int i = 0; i < extractInfo.Count; i++) { for (int ii = 0; ii < extractInfo[i].lists.Count; ii++) { tempS += extractInfo[i].lists[ii].PadRight(50) + " " + extractInfo[i].name + "\n"; retCount++; } } int maxLength = Screen.PrimaryScreen.Bounds.Height / 20 - 4; while (retCount > maxLength) { int ret = 0; for (int cc = 0; cc < maxLength; cc++) { ret = tempS.IndexOf('\n', ret + 1); if (ret == -1) { break; } } if (ret == -1) { break; } MessageBox.Show(tempS.Substring(0, ret)); tempS = tempS.Substring(ret); retCount -= maxLength; } MessageBox.Show(tempS); break; // BMP case 2: pictureBox1.Image.Save(saveBitmapDialog1.FileName, ImageFormat.Bmp); break; // JPG case 3: pictureBox1.Image.Save(saveBitmapDialog1.FileName, ImageFormat.Jpeg); break; } // } }
/// <summary> /// The display map bitmap. /// </summary> /// <remarks></remarks> public void DisplayMapBitmap() { map.OpenMap(MapTypes.Internal); try { Meta m = GetMapBitmapMeta(map); if (m != null) { ParsedBitmap pm = new ParsedBitmap(ref m, map); //if (bitmMainPtr != IntPtr.Zero) //{ // Marshal.FreeHGlobal(bitmMainPtr); //} pictureBox1.Image = pm.FindChunkAndDecode(0, 0, 0, ref m, map, 0, 0); } } catch { // Who cares if we can't load the map bitmap due to a missing MainMenu.map? } finally { map.CloseMap(); } }
/// <summary> /// The inject bitmap tool strip menu item_ click. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> /// <remarks></remarks> private void injectBitmapToolStripMenuItem_Click(object sender, EventArgs e) { int numDDS = 1; for (int i = 0; i < map.SelectedMeta.items.Count; i++) { if (map.SelectedMeta.items[i].offset == 68) { numDDS = ((MetaScanner.XReflex)map.SelectedMeta.items[i]).chunkcount; break; } } bool injectAll = false; string pathName = string.Empty; if (map.SelectedMeta.raw.rawChunks[0].rawLocation != MapTypes.Internal) { DialogResult dr = MessageBox.Show( "This bitmap is located in the \"" + map.SelectedMeta.raw.rawChunks[0].rawLocation.ToString().ToLower() + ".map\" file.\n\nSelect 'YES' to inject to " + map.SelectedMeta.raw.rawChunks[0].rawLocation.ToString().ToLower() + ".map \nSelect 'NO' to internalize it first", "Confirm Injection to External Map", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2); if (dr == DialogResult.Cancel) { return; } else if (dr == DialogResult.No) { buttonInternalize_Click(null, null); } } if (numDDS > 1) { DialogResult result = MessageBox.Show( "Current Bitmap contains " + numDDS + " bitmap chunks.\n\nDo you wish to inject all bitmaps?", "Inject All Bitmaps?", MessageBoxButtons.YesNo); injectAll = result == DialogResult.Yes; } if (injectAll) { openBitmapDialog1.Title = "Select a file from the set to Inject"; } else { openBitmapDialog1.Title = "Select file to Inject"; } openBitmapDialog1.InitialDirectory = Prefs.pathBitmapsFolder; openBitmapDialog1.FileName = map.SelectedMeta.name.Substring(map.SelectedMeta.name.LastIndexOf('\\')+1) + ".dds"; if (openBitmapDialog1.ShowDialog() == DialogResult.Cancel) { return; } Prefs.pathBitmapsFolder = openBitmapDialog1.FileName.Substring( 0, openBitmapDialog1.FileName.LastIndexOf('\\')); switch (openBitmapDialog1.FilterIndex) { case 1: ParsedBitmap bm = new ParsedBitmap(ref map.SelectedMeta, map); FileStream fs; if (injectAll) { string[] s = new string[3]; // s[0] = path s[0] = openBitmapDialog1.FileName.Substring(0, openBitmapDialog1.FileName.LastIndexOf('\\') + 1); // s[1] = filename (without numbering, eg "ASDF_001" => "ASDF") s[1] = openBitmapDialog1.FileName.Substring( s[0].Length, openBitmapDialog1.FileName.LastIndexOf('.') - s[0].Length); int Length = s[1].Length - s[1].LastIndexOf('_'); s[1] = s[1].Remove(s[1].Length - Length); // s[2] = extension s[2] = openBitmapDialog1.FileName.Substring(openBitmapDialog1.FileName.LastIndexOf('.')); for (int count = 0; count < numDDS; count++) { fs = new FileStream( s[0] + s[1] + "_" + count.ToString().PadLeft(Length - 1, '0') + s[2], FileMode.Open); BinaryReader br = new BinaryReader(fs); DDS.InjectDDS(map.SelectedMeta, bm, ref br, count); br.Close(); fs.Close(); } } else { BitmapInjectionForm bif = new BitmapInjectionForm(map, openBitmapDialog1.FileName, bm, numDDS); bif.ShowDialog(); bif.Dispose(); } break; } // Refresh bitmap for (int i = 0; i < ltmpTools.Controls.Count; i++) { if (ltmpTools.Controls[i] is BitmapControl) { LoadMeta(map.SelectedMeta.TagIndex); BitmapControl bc = (BitmapControl)ltmpTools.Controls[i]; bc.RefreshDisplay(); break; } } }
/// <summary> /// The load lightmaps. /// </summary> /// <remarks></remarks> public void LoadLightmaps() { if (map.BSP.sbsp[this.BspNumber].LightMap_TagNumber == -1) { LightMapBitmap = new Bitmap[this.BSPRawDataMetaChunks.Length]; SceneryLightMapBitmap = new Bitmap[this.PermutationInfo.Length]; return; } map.OpenMap(MapTypes.Internal); Meta m = new Meta(map); m.ReadMetaFromMap(map.BSP.sbsp[this.BspNumber].LightMap_TagNumber, false); ParsedBitmap pb = new ParsedBitmap(ref m, map); LightMapBitmap = new Bitmap[this.BSPRawDataMetaChunks.Length]; for (int x = 0; x < this.BSPRawDataMetaChunks.Length; x++) { int visualchunk = map.BSP.sbsp[this.BspNumber].VisualChunk_Bitmap_Index[x]; if (visualchunk == -1) { LightMapBitmap[x] = null; continue; } LightMapBitmap[x] = pb.FindChunkAndDecode(visualchunk, 0, 0, ref m, m.Map, x, this.BspNumber); } SceneryLightMapBitmap = new Bitmap[this.PermutationInfo.Length]; for (int x = 0; x < this.PermutationInfo.Length; x++) { int visualchunk = map.BSP.sbsp[this.BspNumber].SceneryChunk_Bitmap_Index[x]; if (visualchunk == -1) { SceneryLightMapBitmap[x] = null; continue; } SceneryLightMapBitmap[x] = pb.FindChunkAndDecode( visualchunk, 0, 0, ref m, m.Map, -x - 1, this.BspNumber); } map.CloseMap(); }
/// <summary> /// The encode dds. /// </summary> /// <param name="bitm">The bitm.</param> /// <param name="b2">The b 2.</param> /// <returns></returns> /// <remarks></remarks> public static byte[] EncodeDDS(Bitmap bitm, ref ParsedBitmap.BitmapInfo b2) { //// //// Check type name and handle 2D, 3D & Cubemaps //// // b2.typename; //// // Get bitmap data into array BitmapData bmd = bitm.LockBits( new Rectangle(new Point(0, 0), bitm.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); IntPtr ptr = bmd.Scan0; b2.width = (ushort)bitm.Width; b2.height = (ushort)bitm.Height; b2.depth = 1; b2.mipMapCount = 0; b2.pixelOffset = 0; b2.tagtype = "mtib".ToCharArray(); b2.typename = ParsedBitmap.BitmapType.BITM_TYPE_2D; int stride = bmd.Stride; // Declare an array to hold the bytes of the bitmap. int bitmSize = stride * bitm.Height; byte[] bitmData = new byte[bitmSize]; Marshal.Copy(ptr, bitmData, 0, bitmSize); bitm.UnlockBits(bmd); byte[] fu; // Misc.DecodeDXT decode = new Entity.Misc.DecodeDXT(); switch (b2.formatname) { /* #region DXT1 case (ParsedBitmap.BitmapFormat)14: sourceBytes = decode.DecodeDXT1(bitm.Height, bitm.Width, sourceBytes); stride *= 4; o = PixelFormat.Format32bppArgb; break; #endregion #region DXT2/3 case (ParsedBitmap.BitmapFormat)15: sourceBytes = decode.DecodeDXT23(bitm.Height, bitm.Width, sourceBytes); stride *= 4; o = PixelFormat.Format32bppArgb; break; #endregion #region DXT 4/5 case (ParsedBitmap.BitmapFormat)16: sourceBytes = decode.DecodeDXT45(b2.height, bitm.Width, sourceBytes); stride *= 4; o = PixelFormat.Format32bppArgb; break; #endregion */ #region A8R8G8B8 case (ParsedBitmap.BitmapFormat)11: b2.bitsPerPixel = 32; break; #endregion #region Lightmaps case ParsedBitmap.BitmapFormat.BITM_FORMAT_LIGHTMAP: b2.bitsPerPixel = 32; break; #endregion #region X8R8G8B8 case (ParsedBitmap.BitmapFormat)10: b2.bitsPerPixel = 32; break; #endregion #region // 16 bit \\ #region A1R5G5B5 case ParsedBitmap.BitmapFormat.BITM_FORMAT_A1R5G5B5: b2.bitsPerPixel = 16; fu = new byte[bitmSize / 2]; for (int r = 0; r < fu.Length; r += 2) { ushort temp = 0; temp += (ushort)((bitmData[r * 2 + 0] * 0x1F / 255) << 0); // 5-bit Blue temp += (ushort)((bitmData[r * 2 + 1] * 0x1F / 255) << 5); // 5-bit Green temp += (ushort)((bitmData[r * 2 + 2] * 0x1F / 255) << 10); // 5-bit Red temp += (ushort)((bitmData[r * 2 + 3] / 255) << 15); // 1-bit Alpha fu[r + 0] = (byte)(temp & 0xFF); fu[r + 1] = (byte)((temp >> 8) & 0xFF); } bitmData = fu; stride /= 2; break; #endregion #region A4R4G4B4 case ParsedBitmap.BitmapFormat.BITM_FORMAT_A4R4G4B4: b2.bitsPerPixel = 16; fu = new byte[bitmSize / 2]; for (int r = 0; r < fu.Length; r += 2) { fu[r + 1] = (byte)((bitmData[r * 2 + 0] * 15 / 255) << 4); // Take blue channel and store as 4-bit B fu[r + 1] += (byte)(bitmData[r * 2 + 1] * 15 / 255); // Take green channel and store as 4-bit G fu[r + 0] = (byte)((bitmData[r * 2 + 2] * 15 / 255) << 4); // Take red channel and store as 4-bit R fu[r + 0] += (byte)(bitmData[r * 2 + 3] * 15 / 255); // Take alpha channel and store as 4-bit A } bitmData = fu; stride /= 2; break; #endregion #region A8Y8 case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8Y8: b2.bitsPerPixel = 16; fu = new byte[bitmSize / 2]; for (int r = 0; r < fu.Length; r += 2) { fu[r + 0] = bitmData[r * 2 + 3]; // Store Alpha channel as (sbyte) G8 fu[r + 1] = bitmData[r * 2 + 0]; // Store Blue channel as (sbyte) B8 } bitmData = fu; stride /= 2; break; #endregion #region G8B8 case (ParsedBitmap.BitmapFormat)22: b2.bitsPerPixel = 16; fu = new byte[bitmSize / 2]; for (int r = 0; r < fu.Length; r += 2) { fu[r + 0] = (byte)(bitmData[r * 2 + 1] + 128); // Store Green channel as (sbyte) G8 fu[r + 1] = (byte)(bitmData[r * 2 + 2] + 128); // Store Blue channel as (sbyte) B8 } bitmData = fu; stride /= 2; break; #endregion #region R5G6B5 case ParsedBitmap.BitmapFormat.BITM_FORMAT_R5G6B5: b2.bitsPerPixel = 16; fu = new byte[bitmSize / 2]; for (int r = 0; r < fu.Length; r += 2) { ushort temp = 0; temp += (ushort)(bitmData[r * 2 + 0] * 0x1F / 255); // 5-bit Red temp += (ushort)((bitmData[r * 2 + 1] * 0x3F / 255) << 5); // 5-bit Green temp += (ushort)((bitmData[r * 2 + 2] * 0x1F / 255) << 11); // 5-bit Blue fu[r + 0] = (byte)(temp & 0xFF); fu[r + 1] = (byte)((temp >> 8) & 0xFF); } bitmData = fu; stride /= 2; break; #endregion #endregion #region // 8 bit \\ #region AY8 case ParsedBitmap.BitmapFormat.BITM_FORMAT_AY8: b2.bitsPerPixel = 8; fu = new byte[bitmSize / 4]; for (int r = 0; r < fu.Length; r++) { fu[r] = (byte)((bitmData[r * 4 + 0] * 0x0F / 255) << 4); // Take red channel and store as 4-bit Y fu[r] += (byte)(bitmData[r * 4 + 3] * 0x0F / 255); // Take alpha channel and store as 4-bit A } bitmData = fu; stride /= 4; break; #endregion #region A8 case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8: b2.bitsPerPixel = 8; fu = new byte[bitmSize / 4]; for (int r = 0; r < fu.Length; r++) { fu[r] = bitmData[r * 4]; // Take red channel only and store as Y value } bitmData = fu; stride /= 4; break; #endregion #region P8 case ParsedBitmap.BitmapFormat.BITM_FORMAT_P8: b2.bitsPerPixel = 8; fu = new byte[bitmSize / 4]; for (int r = 0; r < fu.Length; r++) { fu[r] = bitmData[r * 4]; // Take red channel only and store as Y value } bitmData = fu; stride /= 4; break; #endregion #region Y8 case (ParsedBitmap.BitmapFormat)1: b2.bitsPerPixel = 8; fu = new byte[bitmSize / 4]; for (int r = 0; r < fu.Length; r++) { fu[r] = bitmData[r * 4]; // Take red channel only and store as Y value } bitmData = fu; stride /= 4; break; #endregion #endregion default: MessageBox.Show(b2.formatname.ToString()); break; } b2.type = (ushort)b2.typename; if (b2.swizzle) { bitmData = Swizzler.Swizzle(bitmData, bitm.Width, bitm.Height, b2.depth, b2.bitsPerPixel, false); } return bitmData; }
////////////////////////////////////////////////////// // Generate the DDSURFACEDESC2 chunk of the header ////////////////////////////////////////////////////// #region Public Methods /// <summary> /// The generate. /// </summary> /// <param name="b2">The b 2.</param> /// <remarks></remarks> public void generate(ref ParsedBitmap.BitmapInfo b2) { Reserved1 = new int[11]; // 'Size of structure. This member must be set to 124. size_of_structure = 124; flags = 0; // Flags to indicate valid fields. Always include DDSD_CAPS, DDSD_PIXELFORMAT, // DDSD_WIDTH, DDSD_HEIGHT and either DDSD_PITCH (for uncompressed) or DDSD_LINEARSIZE (for compressed). flags = flags + (int)DDSEnum.DDSD_CAPS; flags = flags + (int)DDSEnum.DDSD_PIXELFORMAT; flags = flags + (int)DDSEnum.DDSD_WIDTH; flags = flags + (int)DDSEnum.DDSD_HEIGHT; switch (b2.formatname) { case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT1: case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT2AND3: case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT4AND5: flags = flags + (int)DDSEnum.DDSD_LINEARSIZE; break; default: flags = flags + (int)DDSEnum.DDSD_PITCH; break; } // Height of the main image in pixels height = b2.height; // Width of the main image in pixels width = b2.width; int RGBBitCount = 0; switch (b2.formatname) { case ParsedBitmap.BitmapFormat.BITM_FORMAT_X8R8G8B8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8R8G8B8: RGBBitCount = 32; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A1R5G5B5: case ParsedBitmap.BitmapFormat.BITM_FORMAT_A4R4G4B4: case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8Y8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_G8B8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_R5G6B5: RGBBitCount = 16; break; // AY8 is same as Raw.ParsedBitmap.BitmapType.BITM_TYPE_CUBEMAP: case ParsedBitmap.BitmapFormat.BITM_FORMAT_LIGHTMAP: case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_P8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_Y8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_AY8: RGBBitCount = 8; break; } // For uncompressed formats, this is the number of bytes per scan line (DWORD aligned) for the main // image. dwFlags should include DDSD_PITCH in this case. For compressed formats, this is the (total) // number of bytes for the main image. dwFlags should be include DDSD_LINEARSIZE in this case. PitchOrLinearSize = width * (RGBBitCount / 8); // For volume textures, this is the depth of the volume. // dwFlags should include DDSD_DEPTH in this case. depth = b2.depth > 1 ? b2.depth : 0; // UPDATE: There are volume textures / 3D bitmaps if (depth > 0) { flags = flags + (int)DDSEnum.DDSD_DEPTH; } // For items with mipmap levels, this is the total number of levels in the mipmap // chain of the main image. dwFlags should include DDSD_MIPMAPCOUNT in this case MipMapCount = b2.mipMapCount; if (MipMapCount > 1) { flags = flags + (int)DDSEnum.DDSD_MIPMAPCOUNT; } // A 32-byte value that specifies the pixel format structure. ddfPixelFormat.generate(b2); // A 16-byte value that specifies the capabilities structure. ddsCaps.generate(ref b2); // End Sub }
/// <summary> /// The add map. /// </summary> /// <param name="filename">The filename.</param> /// <remarks></remarks> private void addMap(string filename) { if (currentLevels[currentLevels.Count - 1].mapID != -1) { MessageBox.Show("There are already " + currentLevels.Count + " maps! No more can be added."); return; } Map tempmap = Map.LoadFromFile(filename); if (tempmap == null) { MessageBox.Show("Unable to load MAP: " + filename); } // Set default gametype numbers gametypes gameTypes = new gametypes(); // Load SCNR tag for (int i = 0; i < tempmap.IndexHeader.metaCount; i++) { if (tempmap.MetaInfo.TagType[i] == "scnr") { tempmap.SelectedMeta = Map.GetMetaFromTagIndex(1, tempmap, false, false); break; } } Meta m = tempmap.SelectedMeta; BinaryReader br = new BinaryReader(m.MS); // Netgame flags, size 32 br.BaseStream.Position = 280; int netgameFlagsCount = br.ReadInt32(); int netgameFlagsOffset = br.ReadInt32() - m.offset - m.magic; for (int i = 0; i < netgameFlagsCount; i++) { // offset 16 is netgame type (0-1=CTF, 2-3=Assault, 4=Odball, 6=Race, 9=Headhunter, 10=Territories, 11-18=KOTH) br.BaseStream.Position = netgameFlagsOffset + i * 32 + 16; int gameType = br.ReadInt16(); int teamNum = br.ReadInt16(); // We only need to check CTF & Assault. For all else, it will default to 8 teams max if (gameType == 0 || gameType == 1) { gameTypes.gameTypes[(int)gametypes.gameTypesNames.CTF].Teams[teamNum] = true; } else if (gameType == 2 || gameType == 3) { gameTypes.gameTypes[(int)gametypes.gameTypesNames.Assault].Teams[teamNum] = true; } } // Start new MapID at 90 for MP, 101 for Campaign int newID = currentLevels[0].campaignNumber == -1 ? 90 : 201; for (int i = 0; i < currentLevels.Count; i++) { if (currentLevels[i].MapID == newID) { // increase MapID by 10 for MP, 100 for Campaign and restart search newID = currentLevels[i].MapID + (currentLevels[0].campaignNumber == -1 ? 10 : 100); i = -1; } } mapInfo newMap = new mapInfo(tempmap.MapHeader.mapName.Trim('\0'), tempmap.MapHeader.scenarioPath, newID); gameTypes.Save(newMap); // Load Map Picture as raw data (for transfer) and Bitmap (for display) tempmap.OpenMap(MapTypes.Internal); m = MapForm.GetMapBitmapMeta(tempmap); ////////////////////////////////// // Backwash for example has no internal picture, so it errors. ////////////////////////////////// if (m != null) { newMap.screenShotRaw = m.raw.rawChunks[0]; ParsedBitmap pm = new ParsedBitmap(ref m, tempmap); newMap.screenShot = pm.FindChunkAndDecode(0, 0, 0, ref m, tempmap, 0, 0); } else { newMap.screenShotRaw = new RawDataChunk(); newMap.screenShotRaw.MS = new MemoryStream(); newMap.screenShotRaw.pointerMetaOffset = 104; } tempmap.CloseMap(); // Save the current Map Bitmap Offset listing in case a map has been added, then removed, so we don't keep // adding new un-needed Raw Listings newMap.screenShotOffset = currentLevels[lbMapListing.Items.Count].screenShotOffset; // Insert the new map & remove the current listing to make sure that we keep the same # of maps total for // when we rewrite currentLevels[this.lbMapListing.Items.Count] = newMap; this.lbMapListing.Items.Add(newMap.Name); }
/// <summary> /// The generate. /// </summary> /// <param name="b2">The b 2.</param> /// <remarks></remarks> public void generate(ref ParsedBitmap.BitmapInfo b2) { magic = "DDS "; ddsd.generate(ref b2); }
/// <summary> /// The load bitmaps. /// </summary> /// <remarks></remarks> private void loadBitmaps() { Map thisMap = map; // Load Map Bitmap & RawChunk for Campaign for (int i = 0; i < campaignLevels.Count; i++) { int metaNum = map.Functions.ForMeta.FindMetaByID(campaignLevels[i].Preview_Image_Ident); if (metaNum != -1) { Meta m = Map.GetMetaFromTagIndex(metaNum, map, false, false); campaignLevels[i].screenShotRaw = m.raw.rawChunks[0]; campaignLevels[i].screenShotOffset = m.raw.rawChunks[0].offset; ParsedBitmap pm = new ParsedBitmap(ref m, map); campaignLevels[i].screenShot = pm.FindChunkAndDecode(0, 0, 0, ref m, map, 0, 0); } } // Load Map Bitmap & RawChunk for MP for (int i = 0; i < MPLevels.Count; i++) { int metaNum = map.Functions.ForMeta.FindMetaByID(MPLevels[i].Preview_Image_Ident); if (metaNum != -1) { Meta m = Map.GetMetaFromTagIndex(metaNum, map, false, false); MPLevels[i].screenShotRaw = m.raw.rawChunks[0]; MPLevels[i].screenShotOffset = m.raw.rawChunks[0].offset; ParsedBitmap pm = new ParsedBitmap(ref m, map); MPLevels[i].screenShot = pm.FindChunkAndDecode(0, 0, 0, ref m, map, 0, 0); } // Checks the offsets to see if they are shared. // Allows us to know if we need to internalize a new bitmap when adding maps for (int j = 0; j < i; j++) { if (MPLevels[i].screenShotOffset == MPLevels[j].screenShotOffset) { if (MPLevels[i].mapID != -1 && MPLevels[j].mapID == -1) { MPLevels[j].screenShotOriginal = false; } else if (MPLevels[i].mapID == -1 && MPLevels[j].mapID != -1) { MPLevels[i].screenShotOriginal = false; } else { MPLevels[i].screenShotOriginal = false; MPLevels[j].screenShotOriginal = false; } } } } }
/// <summary> /// Extracts Meta Data to a dds file. /// </summary> /// <param name="m">Bitmap Meta</param> /// <param name="pm">ParsedBitmap Data</param> /// <param name="bw">Binary Writer Stream</param> /// <param name="index">The index # of the ParsedBitmap Data</param> /// <returns>BitmapInfo containing the format of the extracted DDS</returns> /// <remarks></remarks> public static ParsedBitmap.BitmapInfo ExtractDDS(Meta m, ParsedBitmap pm, ref BinaryWriter bw, int index) { return ExtractDDS(m, pm, ref bw, index, pm.Properties[index]); }
/// <summary> /// The tree view 1_ after select. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> /// <remarks></remarks> private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { if (treeView1.SelectedNode.Level == 2) { currBitm = treeView1.SelectedNode.Parent.Parent.Index; currChunk = treeView1.SelectedNode.Parent.Index; currMipMap = treeView1.SelectedNode.Index; } else if (treeView1.SelectedNode.Level == 1) { currBitm = treeView1.SelectedNode.Parent.Index; currChunk = treeView1.SelectedNode.Index; currMipMap = 0; } else { currBitm = treeView1.SelectedNode.Index; currChunk = 0; currMipMap = 0; } DisplayBitmap(currBitm, currChunk, currMipMap); object o = ((Form)this.TopLevelControl).ActiveMdiChild; if (o is MapForm) { MapForm mf = (MapForm)o; Meta meta = map.SelectedMeta; ParsedBitmap pm = new ParsedBitmap(ref meta, map); Bitmap b = pm.FindChunkAndDecode(currBitm, currChunk, currMipMap, ref meta, map, 0, 0); mf.pictureBox = (Bitmap)pictureBox1.Image.Clone(); mf.statusBarText = (Math.Max(pm.Properties[currBitm].width >> currChunk >> currMipMap,1)).ToString().PadLeft(4) + " X " + (Math.Max(pm.Properties[currBitm].height >> currChunk >> currMipMap,1)).ToString().PadRight(4) + "X " + (Math.Max(pm.Properties[currBitm].depth >> currChunk >> currMipMap,1)).ToString().PadRight(4) + " " + ("(" + pm.Properties[currBitm].typename.ToString().Remove(0, 10) + ") ").PadRight(10) + pm.Properties[currBitm].formatname.ToString().Remove(0, 12).PadRight(10) + " - Swizzle:" + pm.Properties[0].swizzle + "- Location: " + meta.raw.rawChunks[0].rawLocation; } }
/// <summary> /// Extracts meta data to a dds stream. /// </summary> /// <param name="m">Bitmap Meta</param> /// <param name="pm">ParsedBitmap Data</param> /// <param name="bw">Binary Writer Stream</param> /// <param name="index">The index # of the ParsedBitmap Data</param> /// <param name="bi">BitmapInfo Data</param> /// <returns>BitmapInfo containing the format of the extracted DDS</returns> /// <remarks></remarks> public static ParsedBitmap.BitmapInfo ExtractDDS( Meta m, ParsedBitmap pm, ref BinaryWriter bw, int index, ParsedBitmap.BitmapInfo bi) { DDS_HEADER_STRUCTURE dds = new DDS_HEADER_STRUCTURE(); ParsedBitmap.BitmapInfo pmProp = pm.Properties[index]; dds.generate(ref pmProp); // Get our raw data from the Meta, LOD 0 of our selected index int tempNum = -1; for (int i = 0; i < m.raw.rawChunks.Count; i++) if (((BitmapRawDataChunk)m.raw.rawChunks[i]).inchunk == index) { tempNum = i; break; } if (tempNum == -1) return null; byte[] tempChunk = m.raw.rawChunks[tempNum].MS.ToArray(); //int bytesToWrite = 0; int inOffset = 0; // If the original size needs padding, then use it, but not otherwise bool useWidthPad = pmProp.width % 16 != 0 ? true : false; bw.BaseStream.SetLength(128); bw.BaseStream.Position = 0; for (int cubemap = 0; cubemap < (pmProp.typename == ParsedBitmap.BitmapType.BITM_TYPE_CUBEMAP ? 6 : 1); cubemap++) { inOffset = cubemap * (tempChunk.Length / 6); int outOffset = 0; int tWidth = pmProp.width; int tHeight = pmProp.height; int tDepth = pmProp.depth; int mipMapCount = 0; // Halo 2 only uses mipmaps down to 2x__, instead of 1x1 (could be 2x1, 2x2, 2x4, etc), // but is padded enough we should be able to get a 1x1 extracted from the padded data while (tWidth != 0 && tHeight != 0) { int mipSize; // Any compressed images must have each mimap at least 16 bytes (4x4 image) // This concerns mipmaps such as 2x4, 2x2, 1x1, etc switch (pmProp.formatname) { case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT1: mipSize = Math.Max(Math.Max(1, tWidth) * Math.Max(1, tHeight) * Math.Max(1, tDepth) * (pmProp.bitsPerPixel >> 3) / 8, 8); //mipSize = Math.Max(1, tWidth / 4) * Math.Max(1, tHeight / 4) * 8; if (dds.ddsd.PitchOrLinearSize == 0) dds.ddsd.PitchOrLinearSize = mipSize; //dds.ddsd.PitchOrLinearSize = Math.Max(1, ((tWidth + 3) / 4)) * 8; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT2AND3: case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT4AND5: mipSize = Math.Max(Math.Max(1, tWidth) * Math.Max(1, tHeight) * Math.Max(1, tDepth), 16) * (pmProp.bitsPerPixel >> 3) / 4; //mipSize = Math.Max(1, tWidth / 4) * Math.Max(1, tHeight / 4) * 16; if (dds.ddsd.PitchOrLinearSize == 0) dds.ddsd.PitchOrLinearSize = mipSize; break; default: mipSize = Math.Max(Math.Max(1, tWidth) * Math.Max(1, tHeight) * Math.Max(1, tDepth), 8) * (pmProp.bitsPerPixel >> 3); break; } #region Decode swizzled images if (pmProp.swizzle) { try { byte[] tempSwizzle = new byte[mipSize]; Array.Copy(tempChunk, inOffset + outOffset, tempSwizzle, 0, tempSwizzle.Length); tempSwizzle = Swizzler.Swizzle(tempSwizzle, tWidth, tHeight, tDepth > 1 ? tDepth : -1, pmProp.bitsPerPixel, true); Array.Copy(tempSwizzle, 0, tempChunk, inOffset + outOffset, tempSwizzle.Length); } catch { // We cannot generate all mipmaps, so just continue with the amount we have break; } } #endregion // H2 Bitmap Data is padded to a minimum of: // 1 BPP/DXT2/3/4/5 = 128 bytes // 2 BPP/DXT1 = 256 bytes // 4 BPP = 512 bytes // We need to remove the extra padding when // extracting to a DDS. DDS pads DXT1 to 8 bytes minimum & DXT2/3/4/5 to 16 bytes minimum // bytesToWrite is the width * height size. tempChunk2 will contain a stripped version #region Remove padding int widthPad = 0; //if (pmProp.typename != ParsedBitmap.BitmapType.BITM_TYPE_3D && tWidth % 16 != 0) if (useWidthPad && tWidth % 16 != 0) widthPad = 16 - tWidth % 16; if (!pmProp.formatname.ToString().Contains("DXT") && widthPad != 0) { //byte[] tempChunk2 = new byte[tWidth * tHeight * tDepth * byteStep]; byte[] tempChunk2 = new byte[mipSize]; try { // tempPadSize = Padded scanline length int tempPadSize = (tWidth + widthPad) * (pmProp.bitsPerPixel >> 3); int paddedSize = tHeight * tempPadSize; // Copy each line without the padding for (int d = 0; d < tDepth; d++) for (int h = 0; h < tHeight; h++) { Array.Copy( tempChunk, inOffset + outOffset + (d * paddedSize) + (h * tempPadSize), tempChunk2, (d * mipSize) + (h * tWidth * (pmProp.bitsPerPixel >> 3)), tWidth * (pmProp.bitsPerPixel >> 3)); } // Make a copy of the bytes beyond our current mipmap paddedSize *= tDepth; byte[] endBytes = new byte[tempChunk.Length - paddedSize - (inOffset + outOffset)]; Array.Copy(tempChunk, inOffset + outOffset + paddedSize, endBytes, 0, endBytes.Length); Array.Resize( ref tempChunk, inOffset + outOffset + tempChunk2.Length + endBytes.Length ); Array.Copy(tempChunk2, 0, tempChunk, inOffset + outOffset, tempChunk2.Length); Array.Copy(endBytes, 0, tempChunk, inOffset + outOffset + tempChunk2.Length, endBytes.Length); } catch { // We cannot generate all mipmaps, so just continue with the amount we have break; } } #endregion outOffset += mipSize; if ((pmProp.mipMapCount == 0) || (outOffset > tempChunk.Length)) break; tWidth >>= 1; tHeight >>= 1; tDepth = Math.Max(tDepth >> 1, 1); mipMapCount++; } // For exporting, use mipmaps right down to 1x1, instead of Halo's 2x2 dds.ddsd.MipMapCount = mipMapCount; // G8B8 is based on a 128 value for 0 and adds -/+, so adjust values to 128 if (pmProp.formatname == ParsedBitmap.BitmapFormat.BITM_FORMAT_G8B8) { for (int ii = 0; ii < tempChunk.Length; ii++) { tempChunk[ii] += 128; } } byte[] bChunk = new byte[outOffset]; Array.Copy(tempChunk, inOffset, bChunk, 0, Math.Min(outOffset, tempChunk.Length)); if (cubemap == 0) { dds.WriteStruct(ref bw); bw.BaseStream.Position = 128; } bw.Write(bChunk); } return pmProp; }
/// <summary> /// The ce shader info. /// </summary> /// <param name="TagIndex">The TagIndex.</param> /// <param name="map">The map.</param> /// <remarks></remarks> public void CEShaderInfo(int TagIndex, Map map) { this.TagIndex = TagIndex; if (this.TagIndex == -1) { return; } this.shaderName = map.FileNames.Name[this.TagIndex]; map.OpenMap(MapTypes.Internal); int mainid = 0; int primarydetail = -1; int secondarydetail = -1; int micro = -1; switch (map.MetaInfo.TagType[TagIndex]) { case "schi": map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 228; mainid = map.BR.ReadInt32(); break; case "soso": map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 176; mainid = map.BR.ReadInt32(); break; case "sgla": map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 356; mainid = map.BR.ReadInt32(); break; case "scex": map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 900; mainid = map.BR.ReadInt32(); break; case "senv": map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 148; mainid = map.BR.ReadInt32(); map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 180; this.primarydetailuscale = map.BR.ReadSingle(); this.primarydetailvscale = this.primarydetailuscale; this.primarydetailwscale = 1; map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 196; primarydetail = map.BR.ReadInt32(); map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 200; this.secondarydetailuscale = map.BR.ReadSingle(); this.secondarydetailvscale = this.secondarydetailuscale; this.secondarydetailwscale = 1; map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 216; secondarydetail = map.BR.ReadInt32(); map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 248; this.microdetailuscale = map.BR.ReadSingle(); this.microdetailvscale = this.secondarydetailuscale; this.microdetailwscale = 1; map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 264; micro = map.BR.ReadInt32(); map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 40; byte alphatest = map.BR.ReadByte(); int test = alphatest & 1; if (test != 0) { this.Alpha = AlphaType.AlphaTest; } break; case "swat": map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 88; mainid = map.BR.ReadInt32(); break; case "smet": map.BR.BaseStream.Position = map.MetaInfo.Offset[TagIndex] + 88; mainid = map.BR.ReadInt32(); break; } map.CloseMap(); mainid = map.Functions.ForMeta.FindMetaByID(mainid); primarydetail = map.Functions.ForMeta.FindMetaByID(primarydetail); secondarydetail = map.Functions.ForMeta.FindMetaByID(secondarydetail); micro = map.Functions.ForMeta.FindMetaByID(micro); if (mainid == -1) { return; } if (map.MetaInfo.external[mainid]) { map.OpenMap(MapTypes.Bitmaps); } else { map.OpenMap(MapTypes.Internal); } Meta tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(mainid, false); map.CloseMap(); ParsedBitmap pm = new ParsedBitmap(ref tempmeta, map); // Attempt to load LOD2, if that fails, load LOD0 try { this.MainBitmap = pm.FindChunkAndDecode(0, 2, 0, ref tempmeta, map, 0, 0); } catch { this.MainBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); } this.MainName = map.FileNames.Name[mainid]; if (primarydetail != -1) { if (map.MetaInfo.external[primarydetail]) { map.OpenMap(MapTypes.Bitmaps); } else { map.OpenMap(MapTypes.Internal); } tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(primarydetail, false); map.CloseMap(); pm = new ParsedBitmap(ref tempmeta, map); this.primarydetailBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); this.primarydetailName = map.FileNames.Name[primarydetail]; } if (secondarydetail != -1) { if (map.MetaInfo.external[secondarydetail]) { map.OpenMap(MapTypes.Bitmaps); } else { map.OpenMap(MapTypes.Internal); } tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(secondarydetail, false); map.CloseMap(); pm = new ParsedBitmap(ref tempmeta, map); this.secondarydetailBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); this.secondarydetailName = map.FileNames.Name[secondarydetail]; } if (micro != -1) { if (map.MetaInfo.external[micro]) { map.OpenMap(MapTypes.Bitmaps); } else { map.OpenMap(MapTypes.Internal); } tempmeta = new Meta(map); tempmeta.ReadMetaFromMap(micro, false); map.CloseMap(); pm = new ParsedBitmap(ref tempmeta, map); this.microdetailBitmap = pm.FindChunkAndDecode(0, 0, 0, ref tempmeta, map, 0, 0); this.microdetailName = map.FileNames.Name[micro]; } }
/// <summary> /// Injects a dds stream to Meta Data. /// </summary> /// <param name="m">Bitmap Meta</param> /// <param name="pm">ParsedBitmap Data</param> /// <param name="br">Binary Reader Stream</param> /// <param name="index">The index # of the ParsedBitmap Data</param> /// <remarks></remarks> public static void InjectDDS(Meta m, ParsedBitmap pm, ref BinaryReader br, int index) { InjectDDS(m, pm, ref br, index, pm.Properties[index]); }
/// <summary> /// Injects a dds stream to Meta Data. /// </summary> /// <param name="m">Bitmap Meta</param> /// <param name="pm">ParsedBitmap Data</param> /// <param name="br">Binary Reader Stream</param> /// <param name="index">The index # of the ParsedBitmap Data</param> /// <param name="bi">BitmapInfo Data</param> /// <remarks></remarks> public static void InjectDDS( Meta m, ParsedBitmap pm, ref BinaryReader br, int index, ParsedBitmap.BitmapInfo bi) { DDS_HEADER_STRUCTURE dds = new DDS_HEADER_STRUCTURE(); ParsedBitmap.BitmapInfo pmProp = pm.Properties[index]; // ' Read dds header dds.ReadStruct(ref br); // Check padded values as we can allow bitmaps of different size if they have the same padding int pmPropPaddedWidth = pmProp.width + (pmProp.width % 16 == 0 ? 0 : (16 - pmProp.width % 16)); int ddsPaddedWidth = dds.ddsd.width + (dds.ddsd.width % 16 == 0 ? 0 : (16 - dds.ddsd.width % 16)); if (ddsPaddedWidth != pmPropPaddedWidth || pmProp.height != dds.ddsd.height) { MessageBox.Show("ERROR (Bitmap #" + index + "): Images have different padded dimensions!"); return; } // Set new image width pmProp.width = (ushort)dds.ddsd.width; #region Discover if we are doing a bitmap, 3D or cubemap ParsedBitmap.BitmapType type = ParsedBitmap.BitmapType.BITM_TYPE_2D; if ((dds.ddsd.ddsCaps.caps2 & (int)DDSEnum.DDSCAPS2_VOLUME) > 0) type = ParsedBitmap.BitmapType.BITM_TYPE_3D; else if ((dds.ddsd.ddsCaps.caps2 & (int)DDSEnum.DDSCAPS2_CUBEMAP) > 0) type = ParsedBitmap.BitmapType.BITM_TYPE_CUBEMAP; #endregion // If they are different types if (pmProp.typename != type) { MessageBox.Show("ERROR: Images are different types!" + "\nInjected image = " + type + "\nInternal image = " + pmProp.typename); return; } if (bi.formatname.ToString().ToUpper().Contains("DXT")) bi.bitsPerPixel = 32; // Some programs don't save these values, so to be sure int rawsize = (int)br.BaseStream.Length - 128; br.BaseStream.Position = 128; byte[] bChunk = br.ReadBytes(rawsize); int cubemap = ((dds.ddsd.ddsCaps.caps2 & (int)DDSEnum.DDSCAPS2_CUBEMAP) > 0 ? 6 : 1); byte[][][] mipStreams = new byte[cubemap][][]; for (int i = 0; i < mipStreams.Length; i++) mipStreams[i] = new byte[Math.Max(dds.ddsd.MipMapCount, 1)][]; // 6 loops for cubemaps, 1 for all else for (int c = 0; c < cubemap; c++) { // the starting offset of each cubemap side int mipOffset = c * (bChunk.Length / cubemap); int inOffset = mipOffset; // Loop for each mipmap within each cube face (if it is a cubemap) for (int i = 0; i < mipStreams[c].Length; i++) { #region calculate width, height & stream length of mipmap // each mipmap is 1/2 width & height int tWidth = ddsPaddedWidth / (1 << i); int tHeight = dds.ddsd.height / (1 << i); // Contains the size of the current MipMap int mipStreamLength; switch (bi.formatname) { case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT1: mipStreamLength = Math.Max(1, tWidth / 4) * Math.Max(1, tHeight / 4) * 8; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT2AND3: case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT4AND5: mipStreamLength = Math.Max(1, tWidth / 4) * Math.Max(1, tHeight / 4) * 16; break; default: mipStreamLength = Math.Max(1, tWidth) * Math.Max(1, tHeight) * (dds.ddsd.ddfPixelFormat.RGBBitCount >> 3); break; } #endregion mipStreams[c][i] = new byte[mipStreamLength]; if (dds.ddsd.width == ddsPaddedWidth) Array.Copy(bChunk, mipOffset, mipStreams[c][i], 0, mipStreams[c][i].Length); else { int byteStep = (dds.ddsd.ddfPixelFormat.RGBBitCount >> 3); Array.Clear(mipStreams[c][i], 0, mipStreams[c][i].Length); // Copy each line, adding padding to the output for (int h = 0; h < (dds.ddsd.height); h++) { Array.Copy( bChunk, mipOffset + h * dds.ddsd.width * byteStep, mipStreams[c][i], h * ddsPaddedWidth * byteStep, dds.ddsd.width * byteStep); } } mipOffset += mipStreams[c][i].Length; } #region conversion routine // Temporary. Remove after conversion routine verified / corrected // Don't allow different BPP injections if ((pmProp.bitsPerPixel != bi.bitsPerPixel) || // Don't allow compressed types to be converted to ((pmProp.formatname != bi.formatname) && pmProp.formatname.ToString().Contains("DXT"))) { string tempInfo = "\nBPP: " + pmProp.bitsPerPixel.ToString() + ", " + bi.bitsPerPixel.ToString() + "\nDXT: " + pmProp.formatname.ToString() + ", " + bi.formatname.ToString() + " (DXT = " + pmProp.formatname.ToString().Contains("DXT") + ")"; MessageBox.Show("Incompatible format types\n Check Bits Per Pixel & Format type\n *NOTE* No conversions to any DXT (compressed) format supported!\n" + tempInfo); return; } // H2 pads to a 128 boundry (not cubemaps) if (cubemap <= 1 && mipOffset % 128 != 0) mipOffset += (128 - (mipOffset % 128)); /* if (pmProp.formatname != bi.formatname) { byte[] temp = new byte[mipStreamLength]; // Check if we are at the end of Data, such as less mipmaps injected than the original if (inOffset + mipStreamLength > bAll.Length) { return; } Array.Copy(bAll, inOffset, temp, 0, mipStreamLength); Bitmap ba = DDS_Convert.DecodeDDS(temp, bi); /***** This testes to make sure it was being decoded properly Form1 f = new Form1(); System.Windows.Forms.PictureBox p1 = new System.Windows.Forms.PictureBox(); p1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; p1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; p1.Location = new System.Drawing.Point(300, 10); p1.Size = new System.Drawing.Size(70, 70); p1.Image = ba; f.Controls.Add(p1); f.ShowDialog(); *******/ /*// We need to make sure that it doesn't swizzle it here as it does it later! bool tb = pmProp.swizzle; pmProp.swizzle = false; bChunk = DDS_Convert.EncodeDDS(ba, ref pmProp); pmProp.swizzle = tb; ba.Dispose(); bi.width = (ushort)(bi.width / 2); bi.height = (ushort)(bi.height / 2); tWidth = pmProp.width; tHeight = pmProp.height; pmProp.width = (ushort)origWidth; pmProp.height = (ushort)origHeight; } */ #endregion #region Add padding, byte changes, etc for (int mi = 0; mi < mipStreams[c].Length; mi++) { int mipWidth = pmProp.width >> mi; // We don't need to pad the saved data as we pad any data read in /* if (pmProp.width % 16 != 0) //if (mipWidth % 16 != 0) { int paddedWidth = 16 - (mipWidth % 16); int byteStep = pmProp.bitsPerPixel / 8; byte[] paddedChunk = new byte[(mipWidth + paddedWidth) * pmProp.height * byteStep]; Array.Clear(paddedChunk, 0, paddedChunk.Length); // Make sure all bytes are zero to start! // Copy each line, adding padding to the output for (int h = 0; h < (pmProp.height >> mi); h++) { Array.Copy( mipStreams[c][mi], h * mipWidth * byteStep, paddedChunk, h * (mipWidth + paddedWidth) * byteStep, mipWidth * byteStep); } mipStreams[c][mi] = paddedChunk; } */ // G8B8 is based on a 128 value for 0 and adds -/+, so adjust values to 128 if (pmProp.formatname == ParsedBitmap.BitmapFormat.BITM_FORMAT_G8B8) { for (int mii = 0; mii < mipStreams[c][mi].Length; mii++) { mipStreams[c][mi][mii] += 128; } } } #endregion int lodNumber = 0; // First one is the main pic, not mipmap for (int j = 0; j < m.raw.rawChunks.Count; j++) { // If the selected index is the desired index and the LOD # starts at the mipmap # if (((BitmapRawDataChunk)m.raw.rawChunks[j]).inchunk == index && ((BitmapRawDataChunk)m.raw.rawChunks[j]).num == lodNumber) { m.Map.OpenMap(m.raw.rawChunks[j].rawLocation, false); if (!m.Map.isOpen) { return; } // Recaculate the total length (may have changed from above with conversion code) int totalLength = 0; for (int temp = lodNumber; temp < mipStreams[c].Length; temp++) totalLength += mipStreams[c][temp].Length; // H2 pads to a 128 boundry for each Bpp (not on cubemaps) switch (pmProp.formatname) { case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT1: if (totalLength % (256) != 0) totalLength += 256 - (totalLength % (256)); break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT2AND3: case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT4AND5: if (totalLength % (128) != 0) totalLength += 128 - (totalLength % (128)); break; default: if (totalLength % (128 * pmProp.bitsPerPixel >> 3) != 0) totalLength += (128 * (pmProp.bitsPerPixel >> 3) - (totalLength % (128 * pmProp.bitsPerPixel >> 3))); break; } byte[] tempChunk = new byte[totalLength]; int outOffset = 0; for (int temp = lodNumber; temp < mipStreams[c].Length; temp++) { if (pmProp.swizzle) { Array.Copy( Swizzler.Swizzle( mipStreams[c][temp], dds.ddsd.width >> temp, dds.ddsd.height >> temp, -1, dds.ddsd.ddfPixelFormat.RGBBitCount, false), 0, tempChunk, outOffset, mipStreams[c][temp].Length); } else Array.Copy(mipStreams[c][temp], 0, tempChunk, outOffset, mipStreams[c][temp].Length); outOffset += mipStreams[c][temp].Length; } // Append onto existing data for cubemaps m.Map.BW.BaseStream.Position = m.raw.rawChunks[j].offset + totalLength * c; m.Map.BW.Write(tempChunk, 0, Math.Min(tempChunk.Length, m.raw.rawChunks[j].size - (totalLength * c))); if (c == cubemap - 1) { m.Map.OpenMap(MapTypes.Internal); if (((BitmapRawDataChunk)m.raw.rawChunks[j]).num == 0) { m.Map.BW.BaseStream.Position = m.offset + m.raw.rawChunks[j].pointerMetaOffset - 28; pm.Properties[index].Write(ref m.Map.BW); } m.Map.BW.BaseStream.Position = m.offset + m.raw.rawChunks[j].pointerMetaOffset + 24; m.Map.BW.Write(Math.Min(tempChunk.Length * cubemap, m.raw.rawChunks[j].size)); m.Map.CloseMap(); } lodNumber++; } } inOffset += mipOffset; } }
/// <summary> /// The get dds type. /// </summary> /// <param name="info">The info.</param> /// <returns></returns> /// <remarks></remarks> public static DDSFileFormat getDDSType(ParsedBitmap.BitmapInfo info) { string[] formatDescriptions = new[] { "DXT1 ARGB 4 bpp | 1 bit alpha", "DXT3 ARGB 8 bpp | explicit alpha", "DXT5 ARGB 8 bpp | interpolated alpha", "8 A 8 bpp | alpha", "8.8 AL 16 bpp | alpha/luminance", "4.4.4.4 RGB 16 bpp | unsigned", "1.5.5.5 ARGB 16 bpp | unsigned", "5.6.5 RGB 16 bpp | unsigned", "4.4 ARGB 16 bpp | unsigned", "X.8.8.8 XRGB 32 bpp | unsigned", "8.8.8.8 ARGB 32 bpp | unsigned", " | lightmap" }; DDSFileFormat ddsff = new DDSFileFormat(); string temp = "("; switch (info.typename) { case ParsedBitmap.BitmapType.BITM_TYPE_2D: ddsff.Type = DDSFileType._2D; temp += "2D"; break; case ParsedBitmap.BitmapType.BITM_TYPE_3D: ddsff.Type = DDSFileType._3D; temp += "3D"; break; case ParsedBitmap.BitmapType.BITM_TYPE_CUBEMAP: ddsff.Type = DDSFileType._CubeMap; temp += "CUBEMAP"; break; } temp += ") "; ddsff.BMFormat = info.formatname; switch (info.formatname) { case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT1: ddsff.Format = DDSFileFormats.DXT1; temp += formatDescriptions[0]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT2AND3: ddsff.Format = DDSFileFormats.DXT3; temp += formatDescriptions[1]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_DXT4AND5: ddsff.Format = DDSFileFormats.DXT5; temp += formatDescriptions[2]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_P8: case ParsedBitmap.BitmapFormat.BITM_FORMAT_Y8: ddsff.Format = DDSFileFormats.Alpha_8_bit; temp += formatDescriptions[3]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_G8B8: ddsff.Format = DDSFileFormats.AlphaLuminance_16_bit; temp += formatDescriptions[4]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A4R4G4B4: ddsff.Format = DDSFileFormats.A4R4G4B4_16_bit; temp += formatDescriptions[5]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A1R5G5B5: ddsff.Format = DDSFileFormats.A1R5G5B5_16_bit; temp += formatDescriptions[6]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_R5G6B5: ddsff.Format = DDSFileFormats.R5G6B5_16_bit; temp += formatDescriptions[7]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8Y8: ddsff.Format = DDSFileFormats.AlphaLuminance_16_bit; temp += formatDescriptions[8]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_AY8: ddsff.Format = DDSFileFormats.AlphaLuminance_16_bit; temp += formatDescriptions[8]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_X8R8G8B8: ddsff.Format = DDSFileFormats.X8R8G8B8_32_bit; temp += formatDescriptions[9]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_A8R8G8B8: ddsff.Format = DDSFileFormats.A8R8G8B8_32_bit; temp += formatDescriptions[10]; break; case ParsedBitmap.BitmapFormat.BITM_FORMAT_LIGHTMAP: ddsff.Format = DDSFileFormats.BITM_FORMAT_LIGHTMAP; temp += formatDescriptions[11]; break; } ddsff.Description = temp; return ddsff; // (temp + "\""); }
private void loadSkin() { animation = new List<animationData>(); bitmapBlocks = new List<bitmapData>(); textBlocks = new List<textBlockData>(); BinaryReader br = new BinaryReader(meta.MS); BinaryReader br2 = br; #region Animation Frames reflexive br2 = br; br.BaseStream.Position = 20; int animationCount = br.ReadInt32(); int animationOffset = br.ReadInt32() - map.SecondaryMagic; // Handles reflexives in other tags (pointers) int animationTag = map.Functions.ForMeta.FindMetaByOffset(animationOffset); if (animationCount > 0 && animationTag != meta.TagIndex) { Meta newMeta = Map.GetMetaFromTagIndex(animationTag, meta.Map, false, true); br2 = new BinaryReader(newMeta.MS); animationOffset -= newMeta.offset; } else animationOffset -= meta.offset; for (int list = 0; list < animationCount; list++) { animationData ad = new animationData(list, meta); ad.offset = animationOffset + list * 16; ad.Read(br2); this.animation.Add(ad); } #endregion #region Text blocks reflexive br2 = br; br.BaseStream.Position = 28; int textBlockCount = br.ReadInt32(); int textBlockOffset = br.ReadInt32() - map.SecondaryMagic; // Handles reflexives in other tags (pointers) int textBlockTag = map.Functions.ForMeta.FindMetaByOffset(textBlockOffset); if (textBlockCount > 0 && textBlockTag != meta.TagIndex) { Meta newMeta = Map.GetMetaFromTagIndex(textBlockTag, map, false, true); br2 = new BinaryReader(newMeta.MS); textBlockOffset -= newMeta.offset; } else textBlockOffset -= meta.offset; for (int list = 0; list < textBlockCount; list++) { textBlockData tbd = new textBlockData(list); tbd.offset = textBlockOffset + list * 44; tbd.Read(br2); this.textBlocks.Add(tbd); } #endregion #region Bitmap block reflexive br.BaseStream.Position = 36; int bitmapBlockCount = br.ReadInt32(); int bitmapBlockOffset = br.ReadInt32() - map.SecondaryMagic; // Handles reflexives in other tags (pointers) int bitmBlockTag = map.Functions.ForMeta.FindMetaByOffset(bitmapBlockOffset); if (bitmapBlockCount > 0 && bitmBlockTag != meta.TagIndex) { Meta newMeta = Map.GetMetaFromTagIndex(bitmBlockTag, map, false, true); br2 = new BinaryReader(newMeta.MS); bitmapBlockOffset -= newMeta.offset; } else bitmapBlockOffset -= meta.offset; // Always add 3 in case of using sub bitmaps for (int list = 0; list < bitmapBlockCount; list++) { bitmapData bd = new bitmapData(list); bd.offset = bitmapBlockOffset + list * 56; bd.Read(br2); int bitmID = map.Functions.ForMeta.FindMetaByID(bd.bitmIdent); if (bitmID != -1) { bd.meta = Map.GetMetaFromTagIndex(bitmID, map, false, false); ParsedBitmap pm = new ParsedBitmap(ref bd.meta, map); bd.link = pm.FindChunkAndDecode(0, 0, 0, ref bd.meta, map, 0, 0); this.bitmapBlocks.Add(bd); if (pm.Properties.Length > 1) { bd = (bitmapData)bd.Clone(); bd.link = pm.FindChunkAndDecode(1, 0, 0, ref bd.meta, map, 0, 0); } this.bitmapBlocks.Add(bd); if (pm.Properties.Length > 2) { bd = (bitmapData)bd.Clone(); bd.link = pm.FindChunkAndDecode(2, 0, 0, ref bd.meta, map, 0, 0); } this.bitmapBlocks.Add(bd); } } #endregion isLoaded = true; }
/// <summary> /// The convert ce to h 2 tool strip menu item_ click. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> /// <remarks></remarks> private void convertCEToH2ToolStripMenuItem_Click(object sender, EventArgs e) { string[] split = map.SelectedMeta.name.Split('\\'); string temp = split[split.Length - 1] + "." + map.SelectedMeta.type; temp = temp.Replace('<', '_'); temp = temp.Replace('>', '_'); saveMetaDialog.FileName = temp; if (saveMetaDialog.ShowDialog() == DialogResult.Cancel) { return; } switch (map.SelectedMeta.type) { case "bitm": ParsedBitmap pb = new ParsedBitmap(ref map.SelectedMeta, map); pb.ConvertCEtoH2ParsedBitmap(ref map.SelectedMeta, map); break; } map.SelectedMeta.SaveMetaToFile(saveMetaDialog.FileName, true); }