private void ReadWDL(string filename, Stream wdl) { var bin = new BinaryReader(wdl); BlizzHeader chunk; long position = 0; while (position < wdl.Length) { wdl.Position = position; chunk = new BlizzHeader(bin.ReadChars(4), bin.ReadUInt32()); chunk.Flip(); position = wdl.Position + chunk.Size; switch (chunk.ToString()) { case "MVER": ReadMVERChunk(bin); continue; case "MWMO": ReadMWMOChunk(bin, chunk); continue; case "MWID": case "MODF": case "MAOF": //contains MARE and MAHO subchunks case "MARE": case "MAOC": //New in WoD case "MAHO": continue; default: throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunk.ToString(), position.ToString(), filename)); } } }
private void ReadTEX(string filename, Stream tex) { var bin = new BinaryReader(tex); BlizzHeader chunk; long position = 0; while (position < tex.Length) { tex.Position = position; chunk = new BlizzHeader(bin.ReadChars(4), bin.ReadUInt32()); chunk.Flip(); position = tex.Position + chunk.Size; switch (chunk.ToString()) { case "TXVR": ReadTXVRChunk(bin); continue; case "TXFN": ReadTXFNChunk(bin, chunk); continue; case "TXBT": case "TXMD": continue; default: throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunk.ToString(), position.ToString(), filename)); } } }
public MCNK ReadMCNKChunk(BlizzHeader chunk, BinaryReader bin) { //256 of these chunks per file MCNK mapchunk = new MCNK(); mapchunk.header = bin.Read <MCNKheader>(); MemoryStream stream = new MemoryStream(bin.ReadBytes((int)chunk.Size - 128)); var subbin = new BinaryReader(stream); BlizzHeader subchunk; long subpos = 0; while (subpos < stream.Length) { subbin.BaseStream.Position = subpos; subchunk = new BlizzHeader(subbin.ReadChars(4), subbin.ReadUInt32()); subchunk.Flip(); subpos = stream.Position + subchunk.Size; switch (subchunk.ToString()) { case "MCVT": mapchunk.vertices = ReadMCVTSubChunk(subchunk, subbin); break; case "MCCV": mapchunk.vertexShading = ReadMCCVSubChunk(subchunk, subbin); break; case "MCNR": mapchunk.normals = ReadMCNRSubChunk(subchunk, subbin); break; case "MCSE": mapchunk.soundEmitters = ReadMCSESubChunk(subchunk, subbin); break; case "MCBB": mapchunk.blendBatches = ReadMCBBSubChunk(subchunk, subbin); break; case "MCLQ": case "MCLV": continue; default: throw new Exception(String.Format("Found unknown header at offset {1} \"{0}\" while we should've already read them all!", subchunk.ToString(), subpos.ToString())); } } return(mapchunk); }
public TexMCNK ReadTexMCNKChunk(BlizzHeader chunk, BinaryReader bin) { //256 of these chunks per file TexMCNK mapchunk = new TexMCNK(); MemoryStream stream = new MemoryStream(bin.ReadBytes((int)chunk.Size)); var subbin = new BinaryReader(stream); BlizzHeader subchunk; long subpos = 0; while (subpos < stream.Length) { subbin.BaseStream.Position = subpos; subchunk = new BlizzHeader(subbin.ReadChars(4), subbin.ReadUInt32()); subchunk.Flip(); subpos = stream.Position + subchunk.Size; switch (subchunk.ToString()) { case "MCLY": mapchunk.layers = ReadMCLYSubChunk(subchunk, subbin); break; case "MCAL": mapchunk.alphaLayer = ReadMCALSubChunk(subchunk, subbin, mapchunk); break; case "MCSH": case "MCMT": continue; default: throw new Exception(String.Format("Found unknown header at offset {1} \"{0}\" while we should've already read them all!", subchunk.ToString(), subpos.ToString())); } } return(mapchunk); }
private void ReadWMO(string filename, Stream wmo) { var bin = new BinaryReader(wmo); BlizzHeader chunk; long position = 0; while (position < wmo.Length) { wmo.Position = position; chunk = new BlizzHeader(bin.ReadChars(4), bin.ReadUInt32()); chunk.Flip(); position = wmo.Position + chunk.Size; switch (chunk.ToString()) { case "MVER": wmofile.version = bin.Read <MVER>(); if (wmofile.version.version != 17) { throw new Exception("Unsupported WMO version! (" + wmofile.version.version + ") (" + filename + ")"); } continue; case "MOTX": wmofile.textures = ReadMOTXChunk(chunk, bin); continue; case "MOHD": wmofile.header = ReadMOHDChunk(chunk, bin, filename); continue; case "MOGN": wmofile.groupNames = ReadMOGNChunk(chunk, bin, wmofile.header.nGroups); continue; case "MOGI": wmofile.groupInfo = ReadMOGIChunk(chunk, bin, wmofile.header.nGroups); continue; case "MOMT": wmofile.materials = ReadMOMTChunk(chunk, bin, wmofile.header.nMaterials); continue; case "MODN": wmofile.doodadNames = ReadMODNChunk(chunk, bin, wmofile.header.nModels); continue; case "MODD": wmofile.doodadDefinitions = ReadMODDChunk(chunk, bin); continue; case "MOGP": //ReadMOGPChunk(chunk, bin); //continue; case "MOSB": case "MOPV": case "MOPT": case "MOPR": case "MOVV": //Visible block vertices case "MOVB": //Visible block list case "MOLT": case "MODS": case "MFOG": case "MCVP": case "GFID": // Legion continue; default: throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunk.ToString(), position.ToString(), filename)); } } //open group files WMOGroupFile[] groupFiles = new WMOGroupFile[wmofile.header.nGroups]; for (int i = 0; i < wmofile.header.nGroups; i++) { string groupfilename = groupfilename = filename.Replace(".wmo", "_" + i.ToString().PadLeft(3, '0') + ".wmo"); if (_lod) { if (CASC.FileExists(groupfilename.Replace(".wmo", "_lod2.wmo"))) { groupfilename = groupfilename.Replace(".wmo", "_lod2.wmo"); Console.WriteLine("[LOD] Loading LOD 2 for group " + i); } else if (CASC.FileExists(groupfilename.Replace(".wmo", "_lod1.wmo"))) { groupfilename = groupfilename.Replace(".wmo", "_lod1.wmo"); Console.WriteLine("[LOD] Loading LOD 1 for group " + i); } else { Console.WriteLine("[LOD] No LOD " + i); } } if (!CASC.FileExists(groupfilename)) { new WoWFormatLib.Utils.MissingFile(groupfilename); return; } else { using (Stream wmoStream = CASC.OpenFile(groupfilename)) { groupFiles[i] = ReadWMOGroupFile(groupfilename, wmoStream); } } } wmofile.group = groupFiles; }
public MOGP ReadMOGPChunk(BlizzHeader chunk, BinaryReader bin) { MOGP mogp = new MOGP(); mogp.nameOffset = bin.ReadUInt32(); mogp.descriptiveNameOffset = bin.ReadUInt32(); mogp.flags = (MOGPFlags)bin.ReadUInt32(); mogp.boundingBox1 = bin.Read <Vector3>(); mogp.boundingBox2 = bin.Read <Vector3>(); mogp.ofsPortals = bin.ReadUInt16(); mogp.numPortals = bin.ReadUInt16(); mogp.numBatchesA = bin.ReadUInt16(); mogp.numBatchesB = bin.ReadUInt16(); mogp.numBatchesC = bin.ReadUInt32(); //mogp.fogIndices = bin.ReadBytes(4); bin.ReadBytes(4); mogp.liquidType = bin.ReadUInt32(); mogp.groupID = bin.ReadUInt32(); mogp.unk0 = bin.ReadUInt32(); mogp.unk1 = bin.ReadUInt32(); MemoryStream stream = new MemoryStream(bin.ReadBytes((int)chunk.Size)); var subbin = new BinaryReader(stream); BlizzHeader subchunk; long position = 0; int MOTVi = 0; if (mogp.flags.HasFlag(MOGPFlags.Flag_0x40000000)) { mogp.textureCoords = new MOTV[3][]; } else { mogp.textureCoords = new MOTV[2][]; } while (position < stream.Length) { stream.Position = position; subchunk = new BlizzHeader(subbin.ReadChars(4), subbin.ReadUInt32()); subchunk.Flip(); position = stream.Position + subchunk.Size; //Console.WriteLine(subchunk.ToString()); switch (subchunk.ToString()) { case "MOVI": //Vertex indices for triangles mogp.indices = ReadMOVIChunk(subchunk, subbin); //Console.WriteLine("Read " + mogp.indices.Length + " indices!"); break; case "MOVT": //Vertices chunk mogp.vertices = ReadMOVTChunk(subchunk, subbin); break; case "MOTV": //Texture coordinates mogp.textureCoords[MOTVi++] = ReadMOTVChunk(subchunk, subbin); break; case "MONR": //Normals mogp.normals = ReadMONRChunk(subchunk, subbin); break; case "MOBA": //Render batches mogp.renderBatches = ReadMOBAChunk(subchunk, subbin); break; case "MOPY": //Material info for triangles, two bytes per triangle. mogp.materialInfo = ReadMOPYChunk(subchunk, subbin); break; case "MOBS": //Unk case "MODR": //Doodad references case "MOBN": //Array of t_BSP_NODE case "MOBR": //Face indices case "MOLR": //Light references case "MOCV": //Vertex colors case "MDAL": //Unk (new in WoD?) case "MLIQ": //Liquids case "MOTA": //Unknown case "MOPL": //Unknown case "MOLP": //Unknown continue; default: throw new Exception(String.Format("Found unknown header at offset {1} \"{0}\" while we should've already read them all!", subchunk.ToString(), position.ToString())); } } //if(MOTVi == 0) { throw new Exception("Didn't parse any MOTV??"); } // antiportal groups have no motv return(mogp); }
private void ReadTexFile(string filename, Stream adtTexStream, ref BlizzHeader chunk) { var bin = new BinaryReader(adtTexStream); long position = 0; int MCNKi = 0; adtfile.texChunks = new TexMCNK[16 * 16]; while (position < adtTexStream.Length) { adtTexStream.Position = position; chunk = new BlizzHeader(bin.ReadChars(4), bin.ReadUInt32()); chunk.Flip(); position = adtTexStream.Position + chunk.Size; if (chunk.Is("MVER")) { if (bin.ReadUInt32() != 18) { throw new Exception("Unsupported ADT version!"); } continue; } if (chunk.Is("MAMP")) { continue; } if (chunk.Is("MTEX")) { adtfile.textures = ReadMTEXChunk(chunk, bin); continue; } if (chunk.Is("MCNK")) { adtfile.texChunks[MCNKi] = ReadTexMCNKChunk(chunk, bin); MCNKi++; continue; } if (chunk.Is("MTXP")) { continue; } throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunk.ToString(), position.ToString(), filename)); } }
private void ReadObjFile(string filename, Stream adtObjStream, ref BlizzHeader chunk) { var bin = new BinaryReader(adtObjStream); long position = 0; adtfile.objects = new Obj(); while (position < adtObjStream.Length) { adtObjStream.Position = position; chunk = new BlizzHeader(bin.ReadChars(4), bin.ReadUInt32()); chunk.Flip(); position = adtObjStream.Position + chunk.Size; if (chunk.Is("MVER")) { if (bin.ReadUInt32() != 18) { throw new Exception("Unsupported ADT version!"); } continue; } if (chunk.Is("MMDX")) { adtfile.objects.m2Names = ReadMMDXChunk(chunk, bin); continue; } if (chunk.Is("MMID")) { adtfile.objects.m2NameOffsets = ReadMMIDChunk(chunk, bin); continue; } if (chunk.Is("MWMO")) { adtfile.objects.wmoNames = ReadMWMOChunk(chunk, bin); continue; } if (chunk.Is("MWID")) { adtfile.objects.wmoNameOffsets = readMWIDChunk(chunk, bin); continue; } if (chunk.Is("MDDF")) { adtfile.objects.models = ReadMWIDChunk(chunk, bin); continue; } if (chunk.Is("MODF")) { adtfile.objects.worldModels = ReadMODFChunk(chunk, bin); continue; } if (chunk.Is("MCNK")) { continue; } // Only has MCRD and other useless things nobody cares about! throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunk.ToString(), position.ToString(), filename)); } }
public void LoadADT(string filename, bool loadSecondaryADTs = true, bool filenamesOnly = false, bool localFile = false) { m2Files = new List <string>(); wmoFiles = new List <string>(); blpFiles = new List <string>(); filename = Path.ChangeExtension(filename, ".adt"); if (!localFile) { if (!CASC.FileExists(filename)) { new WoWFormatLib.Utils.MissingFile(filename); return; } if (!CASC.FileExists(filename.Replace(".adt", "_obj0.adt"))) { new WoWFormatLib.Utils.MissingFile(filename.Replace(".adt", "_obj0.adt")); return; } if (!CASC.FileExists(filename.Replace(".adt", "_obj1.adt"))) { new WoWFormatLib.Utils.MissingFile(filename.Replace(".adt", "_obj1.adt")); return; } if (!CASC.FileExists(filename.Replace(".adt", "_tex0.adt"))) { new WoWFormatLib.Utils.MissingFile(filename.Replace(".adt", "_tex0.adt")); return; } if (!CASC.FileExists(filename.Replace(".adt", "_tex1.adt"))) { new WoWFormatLib.Utils.MissingFile(filename.Replace(".adt", "_tex1.adt")); return; } } else { if (!File.Exists(filename)) { throw new Exception("Missing file!"); } } Stream adt; if (!localFile) { var mapname = filename.Replace("world\\maps\\", "").Substring(0, filename.Replace("world\\maps\\", "").IndexOf("\\")); if (CASC.FileExists("world\\maps\\" + mapname + "\\" + mapname + ".wdt")) { var wdtr = new WDTReader(); wdtr.LoadWDT("world\\maps\\" + mapname + "\\" + mapname + ".wdt"); wdt = wdtr.wdtfile; } else { throw new Exception("WDT does not exist, need this for MCAL flags!"); } adt = CASC.OpenFile(filename); } else { adt = File.OpenRead(filename); } BlizzHeader chunk = null; if (filenamesOnly == false) { var bin = new BinaryReader(adt); long position = 0; int MCNKi = 0; adtfile.chunks = new MCNK[16 * 16]; while (position < adt.Length) { adt.Position = position; chunk = new BlizzHeader(bin.ReadChars(4), bin.ReadUInt32()); chunk.Flip(); position = adt.Position + chunk.Size; switch (chunk.ToString()) { case "MVER": uint version = bin.ReadUInt32(); if (version != 18) { throw new Exception("Unsupported ADT version!"); } else { adtfile.version = version; } continue; case "MCNK": adtfile.chunks[MCNKi] = ReadMCNKChunk(chunk, bin); MCNKi++; continue; case "MHDR": adtfile.header = ReadMHDRChunk(chunk, bin); continue; case "MH2O": case "MFBO": //model.blob stuff case "MBMH": case "MBBB": case "MBMI": case "MBNV": continue; default: throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunk.ToString(), position.ToString(), filename)); } } adt.Close(); } if (loadSecondaryADTs) { using (var adtobj0 = CASC.OpenFile(filename.Replace(".adt", "_obj0.adt"))) { ReadObjFile(filename, adtobj0, ref chunk); } using (var adttex0 = CASC.OpenFile(filename.Replace(".adt", "_tex0.adt"))) { ReadTexFile(filename, adttex0, ref chunk); } } }