/// <summary> /// Read the Texture MCNK from the texture ADT. /// </summary> public static void ReadTexMCNK(BinaryReader reader, uint mcnkSize, ADTModel model) { var startPosition = reader.BaseStream.Position; var texMcnk = new TexMCNKChunk(); while (reader.BaseStream.Position < startPosition + mcnkSize) { var chunkId = (Chunks)reader.ReadUInt32(); var chunkSize = reader.ReadUInt32(); switch (chunkId) { case Chunks.MCLY: // Texture Layers. ReadMCLY(reader, chunkSize, texMcnk); break; case Chunks.MCAL: // Alpha Layers. ReadMCAL(reader, texMcnk, model.WdtFileDataId, chunkSize); break; default: reader.Skip(chunkSize); break; } } model.TexMCNKs.Add(texMcnk); }
/// <summary> /// Read texture data from MCLY. /// </summary> public static void ReadMCLY(BinaryReader reader, uint chunkSize, TexMCNKChunk chunk) { var layerCount = chunkSize / 16; chunk.LayerCount = layerCount; chunk.TextureIds = new uint[layerCount]; chunk.LayerOffsetInMCAL = new uint[layerCount]; chunk.AlphaMapCompressed = new bool[layerCount]; for (var i = 0; i < layerCount; ++i) { chunk.TextureIds[i] = reader.ReadUInt32(); var bitArray = new byte[4]; reader.Read(bitArray, 0, 4); var flags = new BitArray(bitArray); chunk.AlphaMapCompressed[i] = flags[9]; chunk.LayerOffsetInMCAL[i] = reader.ReadUInt32(); var effectId = reader.ReadUInt32(); } }
/// <summary> /// Read Alpha Layers from MCAL. /// </summary> public static void ReadMCAL(BinaryReader reader, TexMCNKChunk chunk, uint wdtFileDataId, uint chunkSize) { var mphd = WDTData.MPHDs[wdtFileDataId]; var mcal = new MCAL[chunk.LayerCount]; mcal[0] = new MCAL { Layer = new byte[64 * 64] }; Parallel.For(0, 64 * 64, i => { mcal[0].Layer[i] = 255; }); var readOffset = 0; for (var i = 1; i < chunk.LayerCount; ++i) { if (chunk.LayerOffsetInMCAL[i] != readOffset) { Debug.LogError("Mismatch: layer boefre required more/less bytes than expected"); } if (chunk.AlphaMapCompressed[i]) { mcal[i] = new MCAL { Layer = new byte[64 * 64] }; var inOffset = 0; var outOffset = 0; while (outOffset < 4096) { var info = reader.ReadByte(); ++inOffset; var mode = (uint)(info & 0x80) >> 7; var count = (uint)(info & 0x7F); if (mode != 0) { var val = reader.ReadByte(); ++inOffset; while (count-- > 0 && outOffset < 4096) { mcal[i].Layer[outOffset] = val; ++outOffset; } } else { while (count-- > 0 && outOffset < 4096) { var val = reader.ReadByte(); ++inOffset; mcal[i].Layer[outOffset] = val; ++outOffset; } } } readOffset += inOffset; if (outOffset != 4096) { Debug.LogError($"OutOffset is not 4096! {outOffset}"); } } else if (mphd.Flags.HasFlag(MPHDFlags.AdtHasBigAlpha) || mphd.Flags.HasFlag(MPHDFlags.AdtHasHeightTexturing)) { mcal[i] = new MCAL { Layer = reader.ReadBytes(4096) }; readOffset += 4096; } else { mcal[i] = new MCAL { Layer = new byte[64 * 64] }; var mcalData = reader.ReadBytes(2048); readOffset += 2048; for (var j = 0; j < 2048; ++j) { mcal[i].Layer[2 * j + 0] = (byte)(((mcalData[j] & 0x0F) >> 0) * 17); mcal[i].Layer[2 * j + 1] = (byte)(((mcalData[j] & 0xF0) >> 4) * 17); } } } if (readOffset != chunkSize) { throw new Exception($"ReadOffset is not 4096! {readOffset}"); } chunk.AlphaLayers = mcal; }