public MCNK(char[] magic, byte[] size, byte[] content) : base(magic, size) { using (BinaryReader reader = new BinaryReader(new MemoryStream(content))) { #region read MCNKhead mcHeader.Flags = reader.ReadUInt32(); mcHeader.IndexX = reader.ReadUInt32(); mcHeader.IndexY = reader.ReadUInt32(); mcHeader.NLayers = reader.ReadUInt32(); mcHeader.NDoodadRefs = reader.ReadUInt32(); offset offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCVT = offset; offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCNR = offset; offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCLY = offset; offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCRF = offset; offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCAL = offset; mcHeader.SizeAlpha = reader.ReadUInt32(); offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCSH = offset; mcHeader.SizeShadow = reader.ReadUInt32(); mcHeader.Areaid = reader.ReadUInt32(); mcHeader.NMapObjRefs = reader.ReadUInt32(); mcHeader.Holes = reader.ReadUInt32(); mcHeader.GroundEffectsMap = new byte[16]; for (int x = 0; x < 16; x++) { mcHeader.GroundEffectsMap[x] = reader.ReadByte(); } mcHeader.PredTex = reader.ReadUInt32(); mcHeader.NoEffectDoodad = reader.ReadUInt32(); offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCSE = offset; mcHeader.NSndEmitters = reader.ReadUInt32(); offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCLQ = offset; mcHeader.SizeLiquid = reader.ReadUInt32(); mcHeader.Pos = new float[3]; mcHeader.Pos[0] = reader.ReadSingle(); mcHeader.Pos[1] = reader.ReadSingle(); mcHeader.Pos[2] = reader.ReadSingle(); offset = new offset(); offset.address = reader.ReadUInt32(); mcHeader.OfsMCCV = offset; mcHeader.Props = reader.ReadUInt32(); mcHeader.EffectId = reader.ReadUInt32(); #endregion while (reader.BaseStream.Position < reader.BaseStream.Length) { byte[] ChunkMagic = reader.ReadBytes(4); byte[] ChunkSize = reader.ReadBytes(4); byte[] ChunkContent = reader.ReadBytes(BitConverter.ToInt32(ChunkSize, 0)); string ChunkMagicString = ADT.MagicBytesToString(ChunkMagic); switch (ChunkMagicString) { case "MCVT": mcvt = new MCVT(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent); break; case "MCCV": mccv = new MCCV(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent); break; case "MCNR": mcnr = new MCNR(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent, reader.ReadBytes(13)); break; case "MCLY": mcly = new MCLY(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent); break; case "MCRF": mcrf = new MCRF(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent); break; case "MCAL": mcal = new MCAL(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent); break; case "MCSE": mcse = new MCSE(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent); break; case "MCSH": mcsh = new MCSH(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent); break; case "MCLQ": mclq = new MCLQ(ADT.MagicBytesToChars(ChunkMagic), ChunkSize, ChunkContent); break; } //Logger.log(ChunkMagicString, Logger.Direction.LEVEL2, ChunkContent.Length.ToString() + " byte"); } } //Logger.log("---", Logger.Direction.LEVEL2); }
//----------------------------------------------------------------------------------------------------------------- public void GenerateAlphaMaps(ADT adtfile, int GenerationMode) { if (GenerationMode == 0 || GenerationMode == 1) //MODE 0 & 1 (256 RGB ALPHAS, ONE PER CHUNK) { //---------------------------------------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////////////////////////////////// ///ALPHA MAPS TEST //////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------- var valuesR = new MCAL().layer; var valuesG = new MCAL().layer; var valuesB = new MCAL().layer; for (uint c = 0; c < adtfile.chunks.Count(); c++) { if (adtfile.texChunks[c].alphaLayer != null) { var bmp = new Bitmap(64, 64); //Assign the channels... switch (adtfile.texChunks[c].layers.Count()) { case 2: valuesR = adtfile.texChunks[c].alphaLayer[1].layer; break; case 3: valuesR = adtfile.texChunks[c].alphaLayer[1].layer; valuesG = adtfile.texChunks[c].alphaLayer[2].layer; break; case 4: valuesR = adtfile.texChunks[c].alphaLayer[1].layer; valuesG = adtfile.texChunks[c].alphaLayer[2].layer; valuesB = adtfile.texChunks[c].alphaLayer[3].layer; break; default: //Don't do anything break; } if (GenerationMode == 0) { // 64x64 ALPHAS: for (int x = 0; x < 64; x++) { for (int y = 0; y < 64; y++) { Color color; switch (adtfile.texChunks[c].layers.Count()) { case 2: color = Color.FromArgb(255, valuesR[x * 64 + y], 0, 0); break; case 3: color = Color.FromArgb(255, valuesR[x * 64 + y], valuesG[x * 64 + y], 0); break; case 4: color = Color.FromArgb(255, valuesR[x * 64 + y], valuesG[x * 64 + y], valuesB[x * 64 + y]); break; default: color = Color.FromArgb(255, 0, 0, 0); break; } bmp.SetPixel(x, y, color); } } } if (GenerationMode == 1) { // 63x63 ALPHAS: (Last column/row = previous one) for (int x = 0; x < 63; x++) { for (int y = 0; y < 63; y++) { Color color; switch (adtfile.texChunks[c].layers.Count()) { case 2: color = Color.FromArgb(255, valuesR[x * 64 + y], 0, 0); break; case 3: color = Color.FromArgb(255, valuesR[x * 64 + y], valuesG[x * 64 + y], 0); break; case 4: color = Color.FromArgb(255, valuesR[x * 64 + y], valuesG[x * 64 + y], valuesB[x * 64 + y]); break; default: color = Color.FromArgb(255, 0, 0, 0); break; } bmp.SetPixel(x, y, color); if (y == 62) { bmp.SetPixel(x, y + 1, color); } if (x == 62) { bmp.SetPixel(x + 1, y, color); } if (x == 62 && y == 62) { bmp.SetPixel(x + 1, y + 1, color); } } } } //---------------------------------------------------------------------------------------------------------- //Fix bmp orientation: //---------------------------------------------------------------------------------------------------------- bmp.RotateFlip(RotateFlipType.Rotate270FlipY); //---------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------- //Store the generated map in the array //---------------------------------------------------------------------------------------------------------- AlphaLayers.Add(bmp); //---------------------------------------------------------------------------------------------------------- } else //Create and add an empty BMP if Null { var bmp = new Bitmap(64, 64); AlphaLayers.Add(bmp); } } //---------------------------------------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////////////////////////////////// ///ALPHA MAPS TEST END //////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------- } if (GenerationMode == 2 || GenerationMode == 3) //MODE 2 & 3 (A BLACK&WHITE ALPHA FOR EACH LAYER (ROUGHLY ~768 ALPHAS)) { //---------------------------------------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////////////////////////////////// ///ALPHA MAPS TEST //////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------- for (uint c = 0; c < adtfile.chunks.Count(); c++) { var chunk = adtfile.chunks[c]; for (int li = 0; li < adtfile.texChunks[c].layers.Count(); li++) { if (adtfile.texChunks[c].alphaLayer != null) { var values = adtfile.texChunks[c].alphaLayer[li].layer; var bmp = new System.Drawing.Bitmap(64, 64); { if (GenerationMode == 2) { // 64x64 ALPHAS: for (int x = 0; x < 64; x++) { for (int y = 0; y < 64; y++) { Color color; if (Managers.ConfigurationManager.ADTAlphaUseA) { color = System.Drawing.Color.FromArgb(values[x * 64 + y], values[x * 64 + y], values[x * 64 + y], values[x * 64 + y]); } else { color = System.Drawing.Color.FromArgb(255, values[x * 64 + y], values[x * 64 + y], values[x * 64 + y]); } bmp.SetPixel(x, y, color); } } } if (GenerationMode == 3) { // 63x63 ALPHAS: (Last column/row = previous one) for (int x = 0; x < 63; x++) { for (int y = 0; y < 63; y++) { Color color; if (Managers.ConfigurationManager.ADTAlphaUseA) { color = System.Drawing.Color.FromArgb(values[x * 64 + y], values[x * 64 + y], values[x * 64 + y], values[x * 64 + y]); } else { color = System.Drawing.Color.FromArgb(255, values[x * 64 + y], values[x * 64 + y], values[x * 64 + y]); } bmp.SetPixel(x, y, color); if (y == 62) { bmp.SetPixel(x, y + 1, color); } if (x == 62) { bmp.SetPixel(x + 1, y, color); } if (x == 62 && y == 62) { bmp.SetPixel(x + 1, y + 1, color); } } } } } //---------------------------------------------------------------------------------------------------------- //Store the layer textures //---------------------------------------------------------------------------------------------------------- var AlphaLayerName = adtfile.textures.filenames[adtfile.texChunks[c].layers[li].textureId].ToLower(); AlphaLayersNames.Add(c + ";" + li + ";" + Path.GetFileNameWithoutExtension(AlphaLayerName)); //---------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------- //Fix bmp orientation: //---------------------------------------------------------------------------------------------------------- bmp.RotateFlip(RotateFlipType.Rotate270FlipY); //---------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------- //Store the generated map in the array //---------------------------------------------------------------------------------------------------------- AlphaLayers.Add(bmp); //---------------------------------------------------------------------------------------------------------- } } } //---------------------------------------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////////////////////////////////// ///ALPHA MAPS TEST END //////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------- } #region Splatmaps (1024x1024) if (GenerationMode == 4) { //Adapted from Selzier's code [https://github.com/Selzier/wow.export.unity/blob/master/src/js/3D/exporters/ADTExporter.js] //---------------------------------------------------------------------------------------------------------- //Generate the splatmap json //---------------------------------------------------------------------------------------------------------- #region Splatmap JSON string materialJSON = "{\"chunkData\":{"; // New JSON file to save material data for (uint c = 0; c < adtfile.chunks.Count(); c++) { materialJSON += "\"" + c + "\":["; for (int li = 0; li < adtfile.texChunks[c].layers.Count(); li++) { string AlphaLayerName = adtfile.textures.filenames[adtfile.texChunks[c].layers[li].textureId].ToLower(); if (Managers.ConfigurationManager.ADTPreserveTextureStruct) { AlphaLayerName = AlphaLayerName.Replace("\\", "\\\\").Replace(".blp", ""); //Remove extension and modify the path to use "\\" instead of "\" } else { AlphaLayerName = Path.GetFileNameWithoutExtension(AlphaLayerName); // Get only the filename } //Layer scale float LayerScale = 4; if (adtfile.texParams != null && adtfile.texParams.Count() >= adtfile.texChunks[c].layers[li].textureId) { LayerScale = (float)Math.Pow(2, (adtfile.texParams[adtfile.texChunks[c].layers[li].textureId].flags & 0xF0) >> 4); } materialJSON += "{\"id\":\"" + AlphaLayerName + "\",\"scale\":\"" + LayerScale + "\"},"; } materialJSON = materialJSON.Substring(0, materialJSON.Length - 1); // Remove tailing comma materialJSON += "],"; // Close the subchunk array } materialJSON = materialJSON.Substring(0, materialJSON.Length - 1); // Remove tailing comma string fullJSON = materialJSON + "},\"splatmapData\":{"; // Create JSON data to include splatmap data materialJSON += "}}"; // Close the JSON data JObject matJSON = JObject.Parse(materialJSON); if (adtfile.textures.filenames.Length == 0) { fullJSON += "\"id0\":\"null\","; } else { for (int q = 0; q < adtfile.textures.filenames.Length; q++) { string textureFile = adtfile.textures.filenames[q].ToLower(); if (Managers.ConfigurationManager.ADTPreserveTextureStruct) { textureFile = textureFile.Replace("\\", "\\\\").Replace(".blp", ""); //Remove extension and modify the path to use "\\" instead of "\" } else { textureFile = Path.GetFileNameWithoutExtension(textureFile); } fullJSON += "\"id" + q + "\":\"" + textureFile + "\","; } } fullJSON = fullJSON.Substring(0, fullJSON.Length - 1); // remove tailing comma fullJSON += "}}"; // Close the JSON data SplatmapJSON = fullJSON; #endregion //---------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------- //Generate the actual splatmaps //---------------------------------------------------------------------------------------------------------- #region Splatmap Bitmap string[] materialIDs = adtfile.textures.filenames; for (int i = 0; i < materialIDs.Length; i++) { if (Managers.ConfigurationManager.ADTPreserveTextureStruct) { materialIDs[i] = materialIDs[i].ToLower().Replace(".blp", ""); //Remove extension for the files } else { materialIDs[i] = Path.GetFileNameWithoutExtension(materialIDs[i].ToLower()); } } int imageCount = IntCeil(materialIDs.Length, 4); //---------------------------------------------------------------------------------------------------------- //Structure for this abomination: //---------------------------------------------------------------------------------------------------------- //>A int array for every map we need that contains: //>A int array for each channel (4 in total A R G B) that contains: //>A 2D array for each pixel (1024x1024) int[][][,] pixelData = new int[imageCount][][, ]; for (int p = 0; p < pixelData.Length; p++) { pixelData[p] = new int[4][, ]; for (int i = 0; i < 4; i++) { pixelData[p][i] = new int[1024, 1024]; } } //---------------------------------------------------------------------------------------------------------- // Now before we draw each sub-chunk to PNG, we need to check it's texture list in json. // Based on what order the textures are for that sub-chunk, we may need to draw RGBA in a different order than 0,1,2,3 //Chunk offset int xOff = 0; int yOff = 0; //Loop for all the 256 texChunks for (int chunkIndex = 0; chunkIndex < 256; chunkIndex++) { TexMCNK texChunk = adtfile.texChunks[chunkIndex]; MCAL[] alphaLayers = texChunk.alphaLayer; MCLY[] textureLayers = texChunk.layers; // If there is no texture data just skip it if (textureLayers.Length > 0) { // X,Y Loop through the texChunk (data is stored as 64x64) for (int x = 0; x < 64; x++) { for (int y = 0; y < 64; y++) { int alphaIndex = x * 64 + y; int numberTextureLayers = matJSON["chunkData"][chunkIndex.ToString()].Count(); for (int k = 0; k < numberTextureLayers; k++) { // k = 1, random materialID. This could be any RGBA, RGBA color! int currentIndex = 0; string currentID = (string)matJSON["chunkData"][chunkIndex.ToString()][k]["id"]; //Probably not a good idea to use a string though (check back on >7xx support) for (int l = 0; l < materialIDs.Length; l++) { if (materialIDs[l] == currentID) { currentIndex = l; } } int texIndex = currentIndex; // Calculate image index, 1 PNG image for each 4 textures. index 0 includes base texture on channel 0 int imageIndex = IntFloor(texIndex, 4); // 0-3 RGBA. If imageIndex=0 this should not be 0 because that is basetexture int channelIndex = texIndex % 4; // 'vec3 blendTex' from the adt.fragment shader var blendTexs = new int[3]; if (alphaLayers != null) //Those layers can be null { switch (alphaLayers.Length) { case 2: blendTexs[0] = alphaLayers[1].layer[alphaIndex]; break; case 3: blendTexs[0] = alphaLayers[1].layer[alphaIndex]; blendTexs[1] = alphaLayers[2].layer[alphaIndex]; break; case 4: blendTexs[0] = alphaLayers[1].layer[alphaIndex]; blendTexs[1] = alphaLayers[2].layer[alphaIndex]; blendTexs[2] = alphaLayers[3].layer[alphaIndex]; break; default: break; } } // 'vec4 layer_weights' from the adt.fragment shader var sumBlendTex = 0; for (int b = 0; b < blendTexs.Length; b++) { sumBlendTex += blendTexs[b]; } sumBlendTex = Clamp(sumBlendTex, 0, 255); int[] layerWeights = new int[4]; layerWeights[0] = 255 - sumBlendTex; layerWeights[1] = blendTexs[0]; layerWeights[2] = blendTexs[1]; layerWeights[3] = blendTexs[2]; // Write the actual pixel data if (k == 0) { pixelData[imageIndex][channelIndex][x + xOff, y + yOff] = layerWeights[0]; } else { pixelData[imageIndex][channelIndex][x + xOff, y + yOff] = layerWeights[k]; } } } } } //---------------------------------------------------------------------------------------------------------- //Change the offset //---------------------------------------------------------------------------------------------------------- if (yOff + 64 > 960) { yOff = 0; if (xOff + 64 <= 960) { xOff += 64; } } else { yOff += 64; } //---------------------------------------------------------------------------------------------------------- } //---------------------------------------------------------------------------------------------------------- //Generate the bitmaps //---------------------------------------------------------------------------------------------------------- for (int t = 0; t < imageCount; t++) { Bitmap bmp = new Bitmap(1024, 1024); for (int x = 0; x < 1024; x++) { for (int y = 0; y < 1024; y++) { Color currentColor = Color.FromArgb( ZeroClamp(pixelData[t][3][x, y]), //A ZeroClamp(pixelData[t][0][x, y]), //R ZeroClamp(pixelData[t][1][x, y]), //G ZeroClamp(pixelData[t][2][x, y]) //B ); bmp.SetPixel(x, y, currentColor); } } //---------------------------------------------------------------------------------------------------------- //Fix bmp orientation: //---------------------------------------------------------------------------------------------------------- bmp.RotateFlip(RotateFlipType.Rotate270FlipY); //---------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------- //Store the generated map in the list //---------------------------------------------------------------------------------------------------------- AlphaLayers.Add(bmp); //---------------------------------------------------------------------------------------------------------- } //---------------------------------------------------------------------------------------------------------- #endregion //---------------------------------------------------------------------------------------------------------- } #endregion }
public override byte[] GetChunkBytes() { using (var stream = new MemoryStream()) { using (var writer = new BinaryWriter(stream)) { writer.Write((uint)Flags); writer.WriteVector2UInt(Index); writer.Write(Layers); writer.Write(NumberDoodadRefs); var positionOffsetMCVT = BaseStream.Position; writer.Write(0); var positionOffsetMCNR = BaseStream.Position; writer.Write(0); var positionOffsetMCLY = BaseStream.Position; writer.Write(0); var positionOffsetMCRF = BaseStream.Position; writer.Write(0); var positionOffsetMCAL = BaseStream.Position; writer.Write(0); writer.Write(SizeShadow); var positionOffsetMCSH = BaseStream.Position; writer.Write(0); writer.Write(SizeShadow); writer.Write(AreaId); writer.Write(NumberMapObjectRefs); writer.Write(Holes); writer.Write(HolesPadding); for (int i = 0; i < 16; i++) { writer.Write(ReallyLowQualityTextureingMap[i]); } writer.Write(PredTex); writer.Write(NumberEffectDoodads); var positionOffsetMCSE = BaseStream.Position; writer.Write(0); writer.Write(NumberSoundEmitters); var positionOffsetMCLQ = BaseStream.Position; writer.Write(0); writer.Write(SizeLiquid); writer.WriteVector3Float(Position); var positionOffsetMCCV = BaseStream.Position; writer.Write(0); writer.Write(Unused1); writer.Write(Unused2); // Subchunks var positionMCVT = BaseStream.Position; BaseStream.Position = positionOffsetMCVT; writer.Write(positionMCVT); BaseStream.Position = positionMCVT; writer.Write(MCVT.GetChunkHeaderBytes()); writer.Write(MCVT.GetChunkBytes()); var positionMCNR = BaseStream.Position; BaseStream.Position = positionOffsetMCNR; writer.Write(positionMCNR); BaseStream.Position = positionMCNR; writer.Write(MCNR.GetChunkHeaderBytes()); writer.Write(MCNR.GetChunkBytes()); var positionMCLY = BaseStream.Position; BaseStream.Position = positionOffsetMCLY; writer.Write(positionMCLY); BaseStream.Position = positionMCLY; writer.Write(MCLY.GetChunkHeaderBytes()); writer.Write(MCLY.GetChunkBytes()); var positionMCRF = BaseStream.Position; BaseStream.Position = positionOffsetMCRF; writer.Write(positionMCRF); BaseStream.Position = positionMCRF; writer.Write(MCRF.GetChunkHeaderBytes()); writer.Write(MCRF.GetChunkBytes()); // if WDT var positionMCAL = BaseStream.Position; BaseStream.Position = positionOffsetMCAL; writer.Write(positionMCAL); BaseStream.Position = positionMCAL; writer.Write(MCAL.GetChunkHeaderBytes()); writer.Write(MCAL.GetChunkBytes()); if (SizeShadow > 8 && Flags.HasFlag(MCNKFlags.HasMCSH)) { var positionMCSH = BaseStream.Position; BaseStream.Position = positionOffsetMCSH; writer.Write(positionMCSH); BaseStream.Position = positionMCSH; writer.Write(MCSH.GetChunkHeaderBytes()); writer.Write(MCSH.GetChunkBytes()); } if (NumberSoundEmitters > 0) { var positionMCSE = BaseStream.Position; BaseStream.Position = positionOffsetMCSE; writer.Write(positionMCSE); BaseStream.Position = positionMCSE; writer.Write(MCSE.GetChunkHeaderBytes()); writer.Write(MCSE.GetChunkBytes()); } if (SizeLiquid > 0) { var positionMCLQ = BaseStream.Position; BaseStream.Position = positionOffsetMCLQ; writer.Write(positionMCLQ); BaseStream.Position = positionMCLQ; writer.Write(MCLQ.GetChunkHeaderBytes()); writer.Write(MCLQ.GetChunkBytes()); } var positionMCCV = BaseStream.Position; BaseStream.Position = positionOffsetMCCV; writer.Write(positionMCCV); BaseStream.Position = positionMCCV; writer.Write(MCCV.GetChunkHeaderBytes()); writer.Write(MCCV.GetChunkBytes()); } return(stream.ToArray()); } }
private MCAL[] ReadMCALSubChunk(uint size, BinaryReader bin, TexMCNK mapchunk) { var mcal = new MCAL[mapchunk.layers.Length]; mcal[0].layer = new byte[64 * 64]; for (int i = 0; i < 64 * 64; i++) { mcal[0].layer[i] = 255; } uint read_offset = 0; for (int layer = 1; layer < mapchunk.layers.Length; ++layer) { // we assume that we have read as many bytes as this next layer's mcal offset. we then read depending on encoding if (mapchunk.layers[layer].offsetInMCAL != read_offset) { throw new Exception("mismatch: layer before required more / less bytes than expected"); } if (mapchunk.layers[layer].flags.HasFlag(mclyFlags.Flag_0x200)) // Compressed { //Console.WriteLine("Compressed"); // first layer is always fully opaque -> you can let that out // array of 3 x array of 64*64 chars: unpacked alpha values mcal[layer].layer = new byte[64 * 64]; // sorry, I have no god damn idea about c# // *x = value at x. x = pointer to data. ++x = advance pointer a byte uint in_offset = 0; uint out_offset = 0; while (out_offset < 4096) { byte info = bin.ReadByte(); ++in_offset; uint mode = (uint)(info & 0x80) >> 7; // 0 = copy, 1 = fill uint count = (uint)(info & 0x7f); // do mode operation count times if (mode != 0) { byte val = bin.ReadByte(); ++in_offset; while (count-- > 0 && out_offset < 4096) { mcal[layer].layer[out_offset] = val; ++out_offset; } } else // mode == 1 { while (count-- > 0 && out_offset < 4096) { var val = bin.ReadByte(); ++in_offset; mcal[layer].layer[out_offset] = val; ++out_offset; } } } read_offset += in_offset; if (out_offset != 4096) { throw new Exception("we somehow overshoot. this should not be the case, except for broken adts"); } } else if (wdt.mphd.flags.HasFlag(Structs.WDT.mphdFlags.Flag_0x4) || wdt.mphd.flags.HasFlag(Structs.WDT.mphdFlags.Flag_0x80)) // Uncompressed (4096) { //Console.WriteLine("Uncompressed (4096)"); mcal[layer].layer = bin.ReadBytes(4096); read_offset += 4096; } else // Uncompressed (2048) { //Console.WriteLine("Uncompressed (2048)"); mcal[layer].layer = new byte[64 * 64]; var mcal_data = bin.ReadBytes(2048); read_offset += 2048; for (int i = 0; i < 2048; ++i) { // maybe nibbles swapped mcal[layer].layer[2 * i + 0] = (byte)(((mcal_data[i] & 0x0F) >> 0) * 17); mcal[layer].layer[2 * i + 1] = (byte)(((mcal_data[i] & 0xF0) >> 4) * 17); } } } if (read_offset != size) { throw new Exception("Haven't finished reading chunk but should be"); } return(mcal); }
public MCNK(byte[] chunkBytes, WDT.WDT wdt) : base(chunkBytes) { Flags = (MCNKFlags)ReadUInt32(); Index = this.ReadVector2UInt(); Layers = ReadUInt32(); NumberDoodadRefs = ReadUInt32(); OffsetMCVT = ReadUInt32(); OffsetMCNR = ReadUInt32(); OffsetMCLY = ReadUInt32(); OffsetMCRF = ReadUInt32(); OffsetMCAL = ReadUInt32(); SizeAlpha = ReadUInt32(); OffsetMCSH = ReadUInt32(); SizeShadow = ReadUInt32(); AreaId = ReadUInt32(); NumberMapObjectRefs = ReadUInt32(); Holes = ReadUInt16(); HolesPadding = ReadUInt16(); // Maybe change this to two longs like in https://bitbucket.org/mugadr_m/kotlin-wow/src/378f3fdec7fff325f52560fc2cce64c946cf57ab/editor/src/main/kotlin/ch/cromon/wow/io/files/map/wotlk/MapChunk.kt?at=master&fileviewer=file-view-default#MapChunk.kt-37 for (int i = 0; i < 16; i++) { ReallyLowQualityTextureingMap[i] = ReadByte(); } PredTex = ReadUInt32(); NumberEffectDoodads = ReadUInt32(); OffsetMCSE = ReadUInt32(); NumberSoundEmitters = ReadUInt32(); OffsetMCLQ = ReadUInt32(); SizeLiquid = ReadUInt32(); Position = this.ReadVector3Float(); OffsetMCCV = ReadUInt32(); Unused1 = ReadUInt32(); Unused2 = ReadUInt32(); if (OffsetMCVT > 0) { BaseStream.Position = OffsetMCVT; MCVT = new MCVT(ReadBytes((int)MCVT.ChunkSize)); } if (OffsetMCNR > 0) { BaseStream.Position = OffsetMCNR; MCNR = new MCNR(ReadBytes((int)MCNR.ChunkSize)); } if (OffsetMCLY > 0) { BaseStream.Position = OffsetMCLY; MCLY = new MCLY(ReadBytes((int)MCLY.ChunkSize)); } if (OffsetMCRF > 0) { BaseStream.Position = OffsetMCRF; MCRF = new MCRF(ReadBytes((int)MCRF.ChunkSize), this); } // TODO: && No WDT file? if (OffsetMCAL > 0 && wdt != null) { BaseStream.Position = OffsetMCAL; MCAL = new MCAL(ReadBytes((int)MCAL.ChunkSize), this, wdt); } if (OffsetMCSH > 0 && SizeShadow > 8 && Flags.HasFlag(MCNKFlags.HasMCSH)) { BaseStream.Position = OffsetMCSH; MCSH = new MCSH(ReadBytes((int)MCSH.ChunkSize)); } if (OffsetMCSE > 0 && NumberSoundEmitters > 0) { BaseStream.Position = OffsetMCSE; MCSE = new MCSE(ReadBytes((int)MCSE.ChunkSize), this); } if (OffsetMCLQ > 0 && SizeLiquid > 0) { BaseStream.Position = OffsetMCLQ; MCLQ = new MCLQ(ReadBytes((int)MCLQ.ChunkSize), this); } if (OffsetMCCV > 0) { BaseStream.Position = OffsetMCCV; MCCV = new MCCV(ReadBytes((int)MCCV.ChunkSize)); } Close(); }