Exemplo n.º 1
0
    public static void HandleDataBlock(byte[] data, int index, Stream stream)
    {
        switch (data[0])
        {
        case 0x4E:             // N
            stream.Write(data, 1, data.Length - 1);
            break;

        case 0x5A:             // Z
            Casc.CopyTo(BLTE_Decompress(data), stream);
            break;

        case 0x45:     // E (encrypted)
            byte[] decrypted = BLTE.Decrypt(data, index);
            if (decrypted == null)
            {
                break;
            }
            HandleDataBlock(decrypted, index, stream);
            break;

        default:
            Debug.Log("Error: BLTE_ExtractData - Unknown byte at switch case : " + data[0]);                 //might need return
            break;
        }
    }
Exemplo n.º 2
0
    public static void Load(string mapName, Vector2 coords)
    {
        string          dataPath             = @"world\maptextures\" + mapName + @"\" + mapName + "_" + coords.x + "_" + coords.y + ".blp";
        MapTextureBlock mapTextureBlock      = new MapTextureBlock();
        Texture2Ddata   texture2Ddata        = new Texture2Ddata();
        string          extractedTexturePath = Casc.GetFile(dataPath);

        using (Stream stream = File.Open(extractedTexturePath, FileMode.Open))
        {
            BLP     blp  = new BLP();
            byte[]  data = blp.GetUncompressed(stream, true);
            BLPinfo info = blp.Info();
            texture2Ddata.hasMipmaps    = info.hasMipmaps;
            texture2Ddata.height        = info.height;
            texture2Ddata.width         = info.width;
            texture2Ddata.textureFormat = info.textureFormat;
            texture2Ddata.TextureData   = data;
            mapTextureBlock.dataPath    = dataPath;
            mapTextureBlock.mapName     = mapName;
            mapTextureBlock.coords      = coords;
            mapTextureBlock.data        = texture2Ddata;
            if (ADT.working)
            {
                MapTextureDataQueue.Enqueue(mapTextureBlock);
            }
            MapTextureThreadRunning = false;
        }
    }
Exemplo n.º 3
0
    ////////////////////
    #region Map List Methods

    // Get a List of Maps from the ADT Maps Directory //
    public void GetMapList(string mapPath)
    {
        string[] list = Casc.GetFolderListFromFolder(mapPath);

        ExtractedMapList = new List <string>();
        ExtractedMapList.AddRange(list);
    }
Exemplo n.º 4
0
    private static void ParseM2_Root(string dataPath, M2Data m2Data, M2Texture m2Tex)
    {
        StreamTools s    = new StreamTools();
        string      path = Casc.GetFile(dataPath);

        byte[] M2MainData     = File.ReadAllBytes(path);
        long   streamPosition = 0;

        using (MemoryStream ms = new MemoryStream(M2MainData))
        {
            while (streamPosition < ms.Length)
            {
                ms.Position = streamPosition;
                int chunkID   = s.ReadLong(ms);
                int chunkSize = s.ReadLong(ms);

                streamPosition = ms.Position + chunkSize;

                switch (chunkID)
                {
                case (int)ChunkID.M2ChunkID.MD21:
                    ReadMD21(ms, m2Data, m2Tex);
                    break;

                default:
                    SkipUnknownChunk(ms, chunkID, chunkSize);
                    break;
                }
            }
        };
    }
Exemplo n.º 5
0
 public static void Load_hTextures()
 {
     if (ADTTexData.textureBlockData.MTXP)
     {
         ADTTexData.textureBlockData.terrainHTextures = new Dictionary <string, ADTTexData.Texture2Ddata>();
         foreach (string texturePath in ADTTexData.textureBlockData.terrainTexturePaths)
         {
             string noExtension   = Path.GetFileNameWithoutExtension(texturePath);
             string directoryPath = Path.GetDirectoryName(texturePath);
             string hTexturePath  = directoryPath + @"\" + noExtension + "_h" + ".blp";
             if (Casc.FileExists(hTexturePath))
             {
                 string  extractedPath = Casc.GetFile(hTexturePath);
                 Stream  stream        = File.Open(extractedPath, FileMode.Open);
                 BLP     blp           = new BLP();
                 byte[]  data          = blp.GetUncompressed(stream, true);
                 BLPinfo info          = blp.Info();
                 ADTTexData.Texture2Ddata texture2Ddata = new ADTTexData.Texture2Ddata();
                 texture2Ddata.hasMipmaps = info.hasMipmaps;
                 texture2Ddata.width      = info.width;
                 texture2Ddata.height     = info.height;
                 if (info.width != info.height) // Unity doesn't support nonsquare mipmaps // sigh
                 {
                     texture2Ddata.hasMipmaps = false;
                 }
                 texture2Ddata.textureFormat = info.textureFormat;
                 texture2Ddata.TextureData   = data;
                 ADTTexData.textureBlockData.terrainHTextures.Add(texturePath, texture2Ddata);
                 stream.Close();
                 stream = null;
             }
         }
     }
 }
Exemplo n.º 6
0
    private static void ParseM2_Skin(string dataPath, M2Data m2Data)
    {
        // check how many skins files there are //
        string noExtension   = Path.GetFileNameWithoutExtension(dataPath);
        string directoryPath = Path.GetDirectoryName(dataPath);

        int skinCount = 0;

        for (int i = 0; i <= 20; i++)
        {
            string fileNumber = i.ToString("00");
            if (Casc.FileExists(directoryPath + @"\" + noExtension + fileNumber + ".skin"))
            {
                skinCount++;
            }
            else
            {
                break;
            }
        }

        if (skinCount > 0)
        {
            // Load only skin00 for now //
            string skinDataPath = directoryPath + @"\" + noExtension + "00" + ".skin";
            string skinPath     = Casc.GetFile(skinDataPath);
            byte[] M2SkinData   = File.ReadAllBytes(skinPath);

            using (MemoryStream ms = new MemoryStream(M2SkinData))
            {
                ParseSkin(ms, m2Data);
            }
        }
    }
Exemplo n.º 7
0
    // texture paths //
    public static void ReadMOTX(Stream WMOrootstream, int MOTXsize)
    {
        long currentPos = WMOrootstream.Position;

        while (WMOrootstream.Position < currentPos + MOTXsize)
        {
            int    position = (int)(WMOrootstream.Position - currentPos);
            string path     = ReadNullTerminatedString(WMOrootstream);
            if (path != "") //&& !wmoData.textureData.ContainsKey(path))
            {
                //Debug.Log(path);
                wmoData.texturePaths.Add(position, path);
                string        extractedPath = Casc.GetFile(path);
                Stream        stream        = File.Open(extractedPath, FileMode.Open);
                byte[]        data          = BLP.GetUncompressed(stream, true);
                BLPinfo       info          = BLP.Info();
                Texture2Ddata texture2Ddata = new Texture2Ddata();
                texture2Ddata.hasMipmaps = info.hasMipmaps;
                texture2Ddata.width      = info.width;
                texture2Ddata.height     = info.height;
                //if (info.width != info.height) // Unity doesn't support nonsquare mipmaps // sigh
                //    texture2Ddata.hasMipmaps = false;
                texture2Ddata.textureFormat = info.textureFormat;
                texture2Ddata.TextureData   = data;
                wmoData.textureData[path]   = texture2Ddata;
                stream.Close();
                stream = null;
            }
        }
    } // loaded
Exemplo n.º 8
0
    public static void Read(string fileName)
    {
        string dataPath = dbfilesclient + fileName;
        string path     = Casc.GetFile(dataPath);

        byte[] fileData = File.ReadAllBytes(path);

        // Check DB2 Version //

        // WDC //
        if (fileData[0] == Convert.ToByte('W') && fileData[1] == Convert.ToByte('D') && fileData[2] == Convert.ToByte('C'))
        {
            // WDC 1 //
            if (fileData[3] == Convert.ToByte('1'))
            {
                WDC1.Read(fileName, fileData);
            }
            // WDC 2 //
            if (fileData[3] == Convert.ToByte('2'))
            {
                WDC2.Read(fileName, fileData);
            }
        }

        // WDB //
        else
        {
            Debug.LogWarning("Warning: " + "DB2 Format not supported: " + fileData[0] + fileData[1] + fileData[2] + fileData[3] + fileName);
        }
    }
Exemplo n.º 9
0
    // Terrain Texture Parser //
    private static void ParseADT_Tex(string Path, string MapName, Vector2 coords)
    {
        StreamTools s          = new StreamTools();
        ADTTex      t          = new ADTTex();
        string      ADTtexPath = Path + MapName + "_" + coords.x + "_" + coords.y + "_tex0" + ".adt";
        string      path       = Casc.GetFile(ADTtexPath);

        byte[] ADTtexData = File.ReadAllBytes(path);

        int  MCNKchunkNumber = 0;
        long streamPosition  = 0;

        using (MemoryStream ms = new MemoryStream(ADTtexData))
        {
            while (streamPosition < ms.Length)
            {
                ms.Position = streamPosition;
                int chunkID   = s.ReadLong(ms);
                int chunkSize = s.ReadLong(ms);
                streamPosition = ms.Position + chunkSize;

                switch (chunkID)
                {
                case (int)ChunkID.ADT.MVER:
                    t.ReadMVER(ms);     // ADT file version
                    break;

                case (int)ChunkID.ADT.MAMP:
                    t.ReadMAMP(ms);     // Single value - texture size = 64
                    break;

                case (int)ChunkID.ADT.MTEX:
                    t.ReadMTEX(ms, chunkSize);     // Texture Paths
                    break;

                case (int)ChunkID.ADT.MCNK:
                {
                    t.ReadMCNKtex(ms, MapName, MCNKchunkNumber, chunkSize);         // Texture Data - 256chunks
                    MCNKchunkNumber++;
                }
                break;

                case (int)ChunkID.ADT.MTXF:
                    t.ReadMTXF(ms, chunkSize);     // Texture Paths
                    break;

                case (int)ChunkID.ADT.MTXP:
                    t.ReadMTXP(ms, chunkSize);     // Texture Paths
                    break;

                default:
                    t.SkipUnknownChunk(ms, chunkID, chunkSize);
                    break;
                }
            }
        }
        ADTtexData = null;
    }
Exemplo n.º 10
0
    // Terrain Mesh Parser //
    private static void ParseADT_Main(string Path, string MapName, Vector2 coords)  // MS version
    {
        StreamTools s           = new StreamTools();
        ADTRoot     r           = new ADTRoot();
        ChunkID     c           = new ChunkID();
        string      ADTmainPath = Path + MapName + "_" + coords.x + "_" + coords.y + ".adt";
        string      path        = Casc.GetFile(ADTmainPath);

        byte[] ADTmainData = File.ReadAllBytes(path);

        int  MCNKchunkNumber = 0;
        long streamPosition  = 0;

        using (MemoryStream ms = new MemoryStream(ADTmainData))
        {
            while (streamPosition < ms.Length)
            {
                ms.Position = streamPosition;
                int chunkID   = s.ReadLong(ms);
                int chunkSize = s.ReadLong(ms);
                streamPosition = ms.Position + chunkSize;

                switch (chunkID)
                {
                case (int)ChunkID.ADT.MVER:
                    r.ReadMVER(ms);     // ADT file version
                    break;

                case (int)ChunkID.ADT.MHDR:
                    r.ReadMHDR(ms);     // Offsets for specific chunks 0000 if chunks don't exist.
                    break;

                case (int)ChunkID.ADT.MH2O:
                    r.ReadMH2O(ms, chunkSize);     // Water Data
                    break;

                case (int)ChunkID.ADT.MCNK:
                {
                    r.ReadMCNK(ms, MCNKchunkNumber, chunkSize);         // Terrain Data - 256chunks
                    MCNKchunkNumber++;
                }
                break;

                case (int)ChunkID.ADT.MFBO:
                    r.ReadMFBO(ms);     // FlightBounds plane & Death plane
                    break;

                default:
                    r.SkipUnknownChunk(ms, chunkID, chunkSize);
                    break;
                }
            }
        }
        ADTmainData = null;
    }
Exemplo n.º 11
0
 public bool CheckForMinimaps(string path)
 {
     if (Casc.FolderExists(path))
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Exemplo n.º 12
0
 public bool CheckForADTs(string path)
 {
     string[] files = Casc.GetFileListFromFolder(path);
     foreach (string file in files)
     {
         if (Path.GetExtension(file).ToLower() == ".adt")
         {
             return(true);
         }
     }
     return(false);
 }
Exemplo n.º 13
0
    private static void CASCInitThread()
    {
        while (ThreadRunning)
        {
            CurrentDataVersion = Settings.Data[3];
            Working            = true;

            EncryptionKeys.ParseKeyFile(Settings.ApplicationPath + @"\ListFiles\keys1.txt"); /// will need more keys maybe ///

            Casc.ClearData();

            CurrentWorkerText = "Reading WoW Folder";
            Casc.ReadWoWFolder();                    // check for correct wow data path
            CurrentWorkerPercent = .05f;

            CurrentWorkerText = "Find Build Config";
            Casc.FindWoWBuildConfig();
            CurrentWorkerPercent = .10f;

            CurrentWorkerText = "Reading IDX files";
            Casc.ReadWoWIDXfiles();              // read the IDX files
            Debug.Log("LocalIndexData Size : " + IndexBlockParser.LocalIndexData.Count);
            CurrentWorkerPercent = .25f;

            CurrentWorkerText = "Loading Encoding File";
            Casc.LoadEncodingFile();                // Locate and extract encoding file from the data files using the MD5 found in build configuration file
            Debug.Log("Encoding File Size : " + Casc.EncodingData.Count);
            CurrentWorkerPercent = .40f;

            CurrentWorkerText = "Loading Root File";
            Casc.LoadWoWRootFile();
            Debug.Log("Root Data Size : " + Casc.MyRootData.Count);
            CurrentWorkerPercent = .55f;

            CurrentWorkerText = "Loading the Filelist";
            Casc.LoadFilelist();
            CurrentWorkerPercent = .75f;

            CurrentWorkerText = "Sorting the Filelist";
            Casc.LoadTreeData();
            CurrentWorkerPercent = .90f;

            Working_InitializationFinished = true;
            Initialized = true;
            TerrainImport.Initialized = false;
            CASCThread.Abort();
            CASCThread    = null;
            ThreadRunning = false;
        }
    }
Exemplo n.º 14
0
    // WDT files specify exactly which map tiles are present in a world, if any, and can also reference a "global" WMO.
    // They have a chunked file structure.

    public static void Load(string Path, string MapName)
    {
        string       WDTpath   = Path + MapName + ".wdt";
        Stream       WDTstream = Casc.GetFileStream(WDTpath);
        WDTflagsdata WDTflags  = new WDTflagsdata();

        ReadMVER(WDTstream);
        ReadMPHD(WDTstream, MapName, WDTflags);
        ReadMAIN(WDTstream, WDTflags);

        // wmo only worlds specific chunk parsing here :

        Flags.Add(MapName, WDTflags);
        WDTstream.Close();
        WDTstream = null;
    }
Exemplo n.º 15
0
    private void AssignMinimapTexture(GameObject MinimapObject, string minimapName)
    {
        string path          = @"world\minimaps\" + minimapName + @"\" + MinimapObject.name + ".blp";
        string extractedPath = Casc.GetFile(path);
        Stream stream        = File.Open(extractedPath, FileMode.Open);

        byte[]    data = BLP.GetUncompressed(stream, false);
        BLPinfo   info = BLP.Info();
        Texture2D tex  = new Texture2D(info.width, info.height, BLP.TxFormat(), false);

        tex.LoadRawTextureData(data);
        MinimapObject.GetComponent <RawImage>().texture = tex;
        MinimapObject.GetComponent <RawImage>().uvRect  = new Rect(0, 0, 1, -1);
        tex.Apply();
        stream.Close();
        BLP.Close();
    }
Exemplo n.º 16
0
    public void ReadMTEX(MemoryStream ADTtexstream, int MTEXsize)
    {
        if (ADTtexstream.Length == ADTtexstream.Position)
        {
            return;
        }

        // texture path strings, separated by 0
        string texturePath      = "";
        int    numberOfTextures = 0;

        for (int a = 0; a < MTEXsize; a++)
        {
            int b = ADTtexstream.ReadByte();
            if (b != 0)
            {
                var stringSymbol = System.Convert.ToChar(b);
                texturePath = texturePath + stringSymbol;
            }
            else if (b == 0)
            {
                ADTTexData.textureBlockData.terrainTexturePaths.Add(texturePath);
                string extractedPath = Casc.GetFile(texturePath);
                using (Stream stream = File.Open(extractedPath, FileMode.Open))
                {
                    BLP     blp  = new BLP();
                    byte[]  data = blp.GetUncompressed(stream, true);
                    BLPinfo info = blp.Info();
                    ADTTexData.Texture2Ddata texture2Ddata = new ADTTexData.Texture2Ddata();
                    texture2Ddata.hasMipmaps = info.hasMipmaps;
                    texture2Ddata.width      = info.width;
                    texture2Ddata.height     = info.height;
                    if (info.width != info.height) // Unity doesn't support nonsquare mipmaps // sigh
                    {
                        texture2Ddata.hasMipmaps = false;
                    }
                    texture2Ddata.textureFormat = info.textureFormat;
                    texture2Ddata.TextureData   = data;
                    ADTTexData.textureBlockData.terrainTextures.Add(texturePath, texture2Ddata);
                    texturePath = null;
                    numberOfTextures++;
                }
            }
        }
    }
Exemplo n.º 17
0
    public static void Initialize()
    {
        // Check existing DB2 files //

        foreach (string fileName in fileNames)
        {
            if (Casc.FileExists(dbfilesclient + fileName))
            {
                availableFiles.Add(fileName, true);
                Read(fileName);
            }
            else
            {
                availableFiles.Add(fileName, false);
                Debug.LogWarning("Warning: " + "Missing " + fileName);
            }
        }
    }
Exemplo n.º 18
0
    // WDT files specify exactly which map tiles are present in a world, if any, and can also reference a "global" WMO.
    // They have a chunked file structure.

    public static bool Load(string Path, string MapName)
    {
        string WDTpath = Path + MapName + ".wdt";

        using (Stream WDTstream = Casc.GetFileStream(WDTpath))
        {
            if (WDTstream != null)
            {
                WDTflagsdata WDTflags = new WDTflagsdata();
                ReadMVER(WDTstream);
                ReadMPHD(WDTstream, MapName, WDTflags);
                ReadMAIN(WDTstream, WDTflags);
                // wmo only worlds specific chunk parsing here :
                Flags.Add(MapName, WDTflags);
                return(true);
            }
            return(false);
        }
    }
Exemplo n.º 19
0
    // Request a minimap image from the parser //
    private static void RequestBlock(Minimap.MinimapRequest minimapRequest)
    {
        string mapName       = minimapRequest.mapName;
        string fileName      = "map" + minimapRequest.coords.x + "_" + minimapRequest.coords.y + ".blp";
        string path          = @"world\minimaps\" + mapName + @"\" + fileName;
        string extractedPath = Casc.GetFile(path);

        using (Stream stream = File.Open(extractedPath, FileMode.Open))
        {
            BLP     blp  = new BLP();
            byte[]  data = blp.GetUncompressed(stream, true);
            BLPinfo info = blp.Info();
            MinimapData.MinimapBlockData blockData = new MinimapData.MinimapBlockData();
            blockData.mapName         = mapName;
            blockData.coords          = minimapRequest.coords;
            blockData.textureInfo     = info;
            blockData.minimapByteData = data;

            MinimapData.MinimapDataQueue.Enqueue(blockData);
        }
    }
Exemplo n.º 20
0
    public void LoadMinimaps(string minimapPath, string mapName)
    {
        // reset global variables //
        ClearData();

        // update global list of minimap files : MinimapFileList //
        string[] FileList = Casc.GetFileListFromFolder(minimapPath);
        foreach (string file in FileList)
        {
            var fileName = Path.GetFileNameWithoutExtension(file);
            if (fileName.StartsWith("m"))
            {
                MinimapFileList.Add(fileName);
            }
        }

        // resize scroll area to encapsulate all minimap blocks //
        AdjustScrollableArea();

        // Create minimap block instances //
        map_name = mapName;
        GenerateMinimaps(mapName);
    }
Exemplo n.º 21
0
    // texture paths //
    public static void ReadMOTX(Stream WMOrootstream, int MOTXsize)
    {
        long currentPos = WMOrootstream.Position;

        while (WMOrootstream.Position < currentPos + MOTXsize)
        {
            int    position = (int)(WMOrootstream.Position - currentPos);
            string path     = ReadNullTerminatedString(WMOrootstream);
            if (path != "") //&& !wmoData.textureData.ContainsKey(path))
            {
                wmoData.texturePaths.Add(position, path);
                if (!LoadedBLPs.Contains(path))
                {
                    string extractedPath = Casc.GetFile(path);
                    if (File.Exists(extractedPath))
                    {
                        Stream        stream        = File.Open(extractedPath, FileMode.Open);
                        BLP           blp           = new BLP();
                        byte[]        data          = blp.GetUncompressed(stream, true);
                        BLPinfo       info          = blp.Info();
                        Texture2Ddata texture2Ddata = new Texture2Ddata();
                        texture2Ddata.hasMipmaps    = info.hasMipmaps;
                        texture2Ddata.width         = info.width;
                        texture2Ddata.height        = info.height;
                        texture2Ddata.textureFormat = info.textureFormat;
                        texture2Ddata.TextureData   = data;
                        wmoData.textureData[path]   = texture2Ddata;
                        stream.Close();
                        stream.Dispose();
                        stream = null;
                    }
                    LoadedBLPs.Add(path);
                }
            }
        }
    } // loaded
Exemplo n.º 22
0
    // Build an array of available minimaps and maps //
    public static void CompileMapList(string mapName)
    {
        MinimapData.dataExists.WDT = false;
        if (!WDT.Flags.ContainsKey(mapName))
        {
            MinimapData.dataExists.WDT = WDT.Load(@"world\maps\" + mapName + @"\", mapName);
        }
        else
        {
            MinimapData.dataExists.WDT = true;
        }
        MinimapData.dataExists.ADT     = Casc.FolderExists(@"world\maps\" + mapName);
        MinimapData.dataExists.Minimap = Casc.FolderExists(@"world\minimaps\" + mapName);
        // sort data //
        MinimapData.mapAvailability = new MinimapData.MapAvailability[64, 64];
        List <string> ADTs     = new List <string>();
        List <string> Minimaps = new List <string>();

        if (MinimapData.dataExists.ADT)
        {
            ADTs = Casc.GetFileListFromFolder(@"world\maps\" + mapName);
        }
        if (MinimapData.dataExists.Minimap)
        {
            Minimaps = Casc.GetFileListFromFolder(@"world\minimaps\" + mapName);
        }
        for (int x = 0; x < 64; x++)
        {
            for (int y = 0; y < 64; y++)
            {
                // WDT data //
                if (MinimapData.dataExists.WDT)
                {
                    MinimapData.mapAvailability[x, y].WDT = WDT.Flags[mapName].HasADT[x, y];
                }
                // ADT files //
                if (MinimapData.dataExists.ADT)
                {
                    if (ADTs.Contains(mapName + "_" + x + "_" + y + ".adt"))
                    {
                        MinimapData.mapAvailability[x, y].ADT = true;
                    }
                    else
                    {
                        MinimapData.mapAvailability[x, y].ADT = false;
                    }
                }
                // Minimap files //
                if (MinimapData.dataExists.Minimap)
                {
                    if (Minimaps.Contains("map" + x + "_" + y + ".blp"))
                    {
                        MinimapData.mapAvailability[x, y].Minimap = true;
                    }
                    else
                    {
                        MinimapData.mapAvailability[x, y].Minimap = false;
                    }
                }
            }
        }
    }
Exemplo n.º 23
0
    // Terrain Models Parser //
    public static void ParseADT_Obj(string Path, string MapName, Vector2 coords)
    {
        StreamTools s          = new StreamTools();
        ADTObj      o          = new ADTObj();
        string      ADTobjPath = Path + MapName + "_" + coords.x + "_" + coords.y + "_obj0" + ".adt";
        string      path       = Casc.GetFile(ADTobjPath);

        byte[] ADTobjData = File.ReadAllBytes(path);

        int  MCNKchunkNumber = 0;
        long streamPosition  = 0;

        using (MemoryStream ms = new MemoryStream(ADTobjData))
        {
            while (streamPosition < ms.Length)
            {
                ms.Position = streamPosition;
                int chunkID   = s.ReadLong(ms);
                int chunkSize = s.ReadLong(ms);
                streamPosition = ms.Position + chunkSize;

                switch (chunkID)
                {
                case (int)ChunkID.ADT.MVER:
                    o.ReadMVER(ms);     // ADT file version
                    break;

                case (int)ChunkID.ADT.MMDX:
                    o.ReadMMDX(ms, chunkSize);     // List of filenames for M2 models
                    break;

                case (int)ChunkID.ADT.MMID:
                    o.ReadMMID(ms, chunkSize);     // List of offsets of model filenames in the MMDX chunk.
                    break;

                case (int)ChunkID.ADT.MWMO:
                    o.ReadMWMO(ms, chunkSize);     // List of filenames for WMOs (world map objects) that appear in this map tile.
                    break;

                case (int)ChunkID.ADT.MWID:
                    o.ReadMWID(ms, chunkSize);     // List of offsets of WMO filenames in the MWMO chunk.
                    break;

                case (int)ChunkID.ADT.MDDF:
                    o.ReadMDDF(ms, chunkSize);     // Placement information for doodads (M2 models).
                    break;

                case (int)ChunkID.ADT.MODF:
                    o.ReadMODF(ms, chunkSize);     // Placement information for WMOs.
                    break;

                case (int)ChunkID.ADT.MCNK:
                {
                    o.ReadMCNKObj(ms, MapName, MCNKchunkNumber, chunkSize);         // 256chunks
                    MCNKchunkNumber++;
                }
                break;

                default:
                    SkipUnknownChunk(ms, chunkID, chunkSize);
                    break;
                }
            }
        }
        ADTobjData = null;
    }
Exemplo n.º 24
0
    public static void ReadMD21(MemoryStream ms, M2Data m2Data, M2Texture m2Tex)
    {
        long md20position = ms.Position;

        StreamTools s                               = new StreamTools();
        int         MD20                            = s.ReadLong(ms);    // "MD20". Legion uses a chunked file format starting with MD21.
        int         version                         = s.ReadLong(ms);
        M2Array     name                            = s.ReadM2Array(ms); // should be globally unique, used to reload by name in internal clients
        var         flags                           = s.ReadLong(ms);
        M2Array     global_loops                    = s.ReadM2Array(ms); // Timestamps used in global looping animations.
        M2Array     sequences                       = s.ReadM2Array(ms); // Information about the animations in the model.
        M2Array     sequences_lookups               = s.ReadM2Array(ms); // Mapping of sequence IDs to the entries in the Animation sequences block.
        M2Array     bones                           = s.ReadM2Array(ms); // MAX_BONES = 0x100 => Creature\SlimeGiant\GiantSlime.M2 has 312 bones(Wrath)
        M2Array     key_bone_lookup                 = s.ReadM2Array(ms); // Lookup table for key skeletal bones.
        M2Array     vertices                        = s.ReadM2Array(ms);
        int         num_skin_profiles               = s.ReadLong(ms);
        M2Array     colors                          = s.ReadM2Array(ms); // Color and alpha animations definitions.
        M2Array     textures                        = s.ReadM2Array(ms);
        M2Array     texture_weights                 = s.ReadM2Array(ms); // Transparency of textures.
        M2Array     texture_transforms              = s.ReadM2Array(ms);
        M2Array     replaceable_texture_lookup      = s.ReadM2Array(ms);
        M2Array     materials                       = s.ReadM2Array(ms); // Blending modes / render flags.
        M2Array     bone_lookup_table               = s.ReadM2Array(ms);
        M2Array     texture_lookup_table            = s.ReadM2Array(ms);
        M2Array     tex_unit_lookup_table           = s.ReadM2Array(ms); // ≥ Cata: unused
        M2Array     transparency_lookup_table       = s.ReadM2Array(ms);
        M2Array     texture_transforms_lookup_table = s.ReadM2Array(ms);

        m2Data.bounding_box = s.ReadBoundingBox(ms);                    // min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height
        float       bounding_sphere_radius  = s.ReadFloat(ms);          // detail doodad draw dist = clamp (bounding_sphere_radius * detailDoodadDensityFade * detailDoodadDist, …)
        BoundingBox collision_box           = s.ReadBoundingBox(ms);
        float       collision_sphere_radius = s.ReadFloat(ms);

        M2Array collision_triangles     = s.ReadM2Array(ms);
        M2Array collision_vertices      = s.ReadM2Array(ms);
        M2Array collision_normals       = s.ReadM2Array(ms);
        M2Array attachments             = s.ReadM2Array(ms);            // position of equipped weapons or effects
        M2Array attachment_lookup_table = s.ReadM2Array(ms);
        M2Array events              = s.ReadM2Array(ms);                // Used for playing sounds when dying and a lot else.
        M2Array lights              = s.ReadM2Array(ms);                // Lights are mainly used in loginscreens but in wands and some doodads too.
        M2Array cameras             = s.ReadM2Array(ms);                // The cameras are present in most models for having a model in the character tab.
        M2Array camera_lookup_table = s.ReadM2Array(ms);
        M2Array ribbon_emitters     = s.ReadM2Array(ms);                // Things swirling around. See the CoT-entrance for light-trails.
        M2Array particle_emitters   = s.ReadM2Array(ms);

        // Name //
        ms.Position = name.offset + md20position;
        for (int n = 0; n < name.size; n++)
        {
            m2Data.name += Convert.ToChar(ms.ReadByte());
        }


        // Bones //
        ms.Position = bones.offset + md20position;
        M2TrackBase[] translationM2track = new M2TrackBase[bones.size];
        M2TrackBase[] rotationM22track   = new M2TrackBase[bones.size];
        M2TrackBase[] scaleM22track      = new M2TrackBase[bones.size];
        for (int cb = 0; cb < bones.size; cb++)
        {
            M2CompBone m2CompBone = new M2CompBone();

            m2CompBone.key_bone_id      = s.ReadLong(ms);               // Back-reference to the key bone lookup table. -1 if this is no key bone.
            m2CompBone.flags            = s.ReadUint32(ms);
            m2CompBone.parent_bone      = s.ReadShort(ms);
            m2CompBone.submesh_id       = s.ReadUint16(ms);
            m2CompBone.uDistToFurthDesc = s.ReadUint16(ms);
            m2CompBone.uZRatioOfChain   = s.ReadUint16(ms);

            translationM2track[cb] = s.ReadM2Track(ms);
            rotationM22track[cb]   = s.ReadM2Track(ms);
            scaleM22track[cb]      = s.ReadM2Track(ms);

            Vector3 pivotRaw = new Vector3(s.ReadFloat(ms) / Settings.worldScale, s.ReadFloat(ms) / Settings.worldScale, s.ReadFloat(ms) / Settings.worldScale);
            m2CompBone.pivot = new Vector3(-pivotRaw.x, pivotRaw.z, -pivotRaw.y);

            m2Data.m2CompBone.Add(m2CompBone);
        }


        // Animations //
        int numberOfAnimations = 0;

        for (int ab = 0; ab < bones.size; ab++)
        {
            List <Animation_Vector3>    bone_position_animations = new List <Animation_Vector3>();
            List <Animation_Quaternion> bone_rotation_animations = new List <Animation_Quaternion>();
            List <Animation_Vector3>    bone_scale_animations    = new List <Animation_Vector3>();

            // Position //
            int numberOfPositionAnimations = translationM2track[ab].Timestamps.size;
            if (numberOfAnimations < numberOfPositionAnimations)
            {
                numberOfAnimations = numberOfPositionAnimations;
            }
            for (int at = 0; at < numberOfPositionAnimations; at++)
            {
                Animation         bone_animation = new Animation();
                Animation_Vector3 positions      = new Animation_Vector3();

                // Timestamps //
                List <int> timeStamps = new List <int>();
                ms.Position = translationM2track[ab].Timestamps.offset + md20position;
                M2Array m2AnimationOffset = s.ReadM2Array(ms);
                ms.Position = m2AnimationOffset.offset;
                for (int t = 0; t < m2AnimationOffset.size; t++)
                {
                    timeStamps.Add(s.ReadLong(ms));
                }
                positions.timeStamps = timeStamps;

                // Values //
                List <Vector3> values = new List <Vector3>();
                ms.Position = translationM2track[ab].Values.offset + md20position;
                M2Array m2AnimationValues = s.ReadM2Array(ms);
                ms.Position = m2AnimationValues.offset;
                for (int t = 0; t < m2AnimationValues.size; t++)
                {
                    Vector3 rawPosition = new Vector3(s.ReadFloat(ms) / Settings.worldScale, s.ReadFloat(ms) / Settings.worldScale, s.ReadFloat(ms) / Settings.worldScale);
                    values.Add(new Vector3(-rawPosition.x, rawPosition.z, -rawPosition.y));
                }
                positions.values = values;
                bone_position_animations.Add(positions);
            }


            // Rotation //
            int numberOfRotationAnimations = rotationM22track[ab].Timestamps.size;
            if (numberOfAnimations < numberOfRotationAnimations)
            {
                numberOfAnimations = numberOfRotationAnimations;
            }
            for (int ar = 0; ar < numberOfRotationAnimations; ar++)
            {
                Animation_Quaternion rotations = new Animation_Quaternion();

                // Timestamps //
                List <int> timeStamps = new List <int>();
                ms.Position = rotationM22track[ab].Timestamps.offset + md20position;
                M2Array m2AnimationOffset = s.ReadM2Array(ms);
                ms.Position = m2AnimationOffset.offset;
                for (int t = 0; t < m2AnimationOffset.size; t++)
                {
                    timeStamps.Add(s.ReadLong(ms));
                }
                rotations.timeStamps = timeStamps;

                // Values //
                List <Quaternion> values = new List <Quaternion>();
                ms.Position = rotationM22track[ab].Values.offset + md20position;
                M2Array m2AnimationValues = s.ReadM2Array(ms);
                ms.Position = m2AnimationValues.offset;
                for (int t = 0; t < m2AnimationValues.size; t++)
                {
                    Quaternion rawRotation = s.ReadQuaternion16(ms);
                    values.Add(new Quaternion(rawRotation.x, rawRotation.y, rawRotation.z, rawRotation.w));
                }
                rotations.values = values;
                bone_rotation_animations.Add(rotations);
            }

            // Scale //
            int numberOfScaleAnimations = scaleM22track[ab].Timestamps.size;
            if (numberOfAnimations < numberOfScaleAnimations)
            {
                numberOfAnimations = numberOfScaleAnimations;
            }
            for (int aS = 0; aS < numberOfScaleAnimations; aS++)
            {
                Animation_Vector3 scales = new Animation_Vector3();

                // Timestamps //
                List <int> timeStamps = new List <int>();
                ms.Position = scaleM22track[ab].Timestamps.offset + md20position;
                M2Array m2AnimationOffset = s.ReadM2Array(ms);
                ms.Position = m2AnimationOffset.offset;
                for (int t = 0; t < m2AnimationOffset.size; t++)
                {
                    timeStamps.Add(s.ReadLong(ms));
                }
                scales.timeStamps = timeStamps;

                // Values //
                List <Vector3> values = new List <Vector3>();
                ms.Position = scaleM22track[ab].Values.offset + md20position;
                M2Array m2AnimationValues = s.ReadM2Array(ms);
                ms.Position = m2AnimationValues.offset;
                for (int t = 0; t < m2AnimationValues.size; t++)
                {
                    Vector3 rawScale = new Vector3(s.ReadFloat(ms) / Settings.worldScale, s.ReadFloat(ms) / Settings.worldScale, s.ReadFloat(ms) / Settings.worldScale);
                    values.Add(new Vector3(-rawScale.x, rawScale.z, -rawScale.y));
                }
                scales.values = values;
                bone_scale_animations.Add(scales);
            }
            //Debug.Log(numberOfPositionAnimations + " " + numberOfRotationAnimations + " " + numberOfScaleAnimations);
            m2Data.position_animations.Add(bone_position_animations);
            m2Data.rotation_animations.Add(bone_rotation_animations);
            m2Data.scale_animations.Add(bone_scale_animations);
        }
        m2Data.numberOfAnimations = numberOfAnimations;

        // Bone Lookup Table //
        ms.Position = bone_lookup_table.offset + md20position;
        for (int blt = 0; blt < key_bone_lookup.size; blt++)
        {
            m2Data.bone_lookup_table.Add(s.ReadUint16(ms));
        }

        // Key-Bone Lookup //
        ms.Position = key_bone_lookup.offset + md20position;
        for (int kbl = 0; kbl < key_bone_lookup.size; kbl++)
        {
            m2Data.key_bone_lookup.Add(s.ReadShort(ms));
        }

        // Vertices //
        ms.Position     = vertices.offset + md20position;
        m2Data.meshData = new MeshData();
        for (int v = 0; v < vertices.size; v++)
        {
            Vector3 rawPosition = new Vector3(s.ReadFloat(ms) / Settings.worldScale, s.ReadFloat(ms) / Settings.worldScale, s.ReadFloat(ms) / Settings.worldScale);
            m2Data.meshData.pos.Add(new Vector3(-rawPosition.x, rawPosition.z, -rawPosition.y));
            m2Data.meshData.bone_weights.Add(new float[] { ms.ReadByte() / 255.0f, ms.ReadByte() / 255.0f, ms.ReadByte() / 255.0f, ms.ReadByte() / 255.0f });
            m2Data.meshData.bone_indices.Add(new int[] { ms.ReadByte(), ms.ReadByte(), ms.ReadByte(), ms.ReadByte() });
            //Debug.Log(m2Data.meshData.bone_indices[v][0] + " " + m2Data.meshData.bone_indices[v][1] + " " + m2Data.meshData.bone_indices[v][2] + " " + m2Data.meshData.bone_indices[v][3]);
            Vector3 rawnormal = new Vector3(s.ReadFloat(ms) * Settings.worldScale, s.ReadFloat(ms) * Settings.worldScale, s.ReadFloat(ms) * Settings.worldScale);
            m2Data.meshData.normal.Add(new Vector3(-rawnormal.x, rawnormal.z, -rawnormal.y));
            m2Data.meshData.tex_coords.Add(new Vector2(s.ReadFloat(ms), s.ReadFloat(ms)));
            m2Data.meshData.tex_coords2.Add(new Vector2(s.ReadFloat(ms), s.ReadFloat(ms)));
        }

        // Textures //
        ms.Position = textures.offset + md20position;
        for (int t = 0; t < textures.size; t++)
        {
            M2Texture m2Texture = new M2Texture();

            m2Texture.type  = s.ReadLong(ms);
            m2Texture.flags = s.ReadLong(ms);

            M2Array filename = s.ReadM2Array(ms);

            // seek to filename and read //
            long savePosition = ms.Position;
            ms.Position = filename.offset + md20position;
            string fileNameString = "";
            for (int n = 0; n < filename.size; n++)
            {
                fileNameString += Convert.ToChar(ms.ReadByte());
            }
            ms.Position = savePosition;

            string fileNameStringFix = fileNameString.TrimEnd(fileNameString[fileNameString.Length - 1]);
            m2Texture.filename = fileNameStringFix;

            Texture2Ddata texture2Ddata = new Texture2Ddata();

            if (fileNameStringFix.Length > 1)
            {
                if (!LoadedBLPs.Contains(fileNameStringFix))
                {
                    string  extractedPath = Casc.GetFile(fileNameStringFix);
                    Stream  stream        = File.Open(extractedPath, FileMode.Open);
                    BLP     blp           = new BLP();
                    byte[]  data          = blp.GetUncompressed(stream, true);
                    BLPinfo info          = blp.Info();
                    texture2Ddata.hasMipmaps    = info.hasMipmaps;
                    texture2Ddata.width         = info.width;
                    texture2Ddata.height        = info.height;
                    texture2Ddata.textureFormat = info.textureFormat;
                    texture2Ddata.TextureData   = data;
                    m2Texture.texture2Ddata     = texture2Ddata;
                    stream.Close();
                    stream.Dispose();
                    stream = null;
                    LoadedBLPs.Add(fileNameString);
                }
            }
            m2Data.m2Tex.Add(m2Texture);
        }

        // texture_lookup_table //
        ms.Position = texture_lookup_table.offset + md20position;
        for (int tl = 0; tl < texture_lookup_table.size; tl++)
        {
            m2Data.textureLookupTable.Add(s.ReadUint16(ms));
        }
    }
Exemplo n.º 25
0
    private static void ParseWMO_Root(string dataPath)
    {
        Stream WMOrootstream = Casc.GetFileStream(dataPath);

        long streamPosition = 0;

        while (streamPosition < WMOrootstream.Length)
        {
            WMOrootstream.Position = streamPosition;
            int chunkID   = ReadLong(WMOrootstream);
            int chunkSize = ReadLong(WMOrootstream);
            streamPosition = WMOrootstream.Position + chunkSize;

            switch (chunkID)
            {
            case (int)ChunkID.WMOChunkID.MVER:
                ReadMVER(WMOrootstream);     // root file version
                break;

            case (int)ChunkID.WMOChunkID.MOHD:
                ReadMOHD(WMOrootstream);     // root file header
                break;

            case (int)ChunkID.WMOChunkID.MOTX:
                ReadMOTX(WMOrootstream, chunkSize);     // texture paths
                break;

            case (int)ChunkID.WMOChunkID.MOMT:
                ReadMOMT(WMOrootstream, chunkSize);     // materials
                break;

            case (int)ChunkID.WMOChunkID.MOUV:
                ReadMOUV(WMOrootstream);     // texture animation // optional
                break;

            case (int)ChunkID.WMOChunkID.MOGN:
                ReadMOGN(WMOrootstream, chunkSize);     // list of group names
                break;

            case (int)ChunkID.WMOChunkID.MOGI:
                ReadMOGI(WMOrootstream);     // Group information for WMO groups
                break;

            case (int)ChunkID.WMOChunkID.MOSB:
                ReadMOSB(WMOrootstream, chunkSize);     // Skybox model filename
                break;

            case (int)ChunkID.WMOChunkID.MOPV:
                ReadMOPV(WMOrootstream, chunkSize);     // Portal vertices
                break;

            case (int)ChunkID.WMOChunkID.MOPT:
                ReadMOPT(WMOrootstream);     // Portal information
                break;

            case (int)ChunkID.WMOChunkID.MOPR:
                ReadMOPR(WMOrootstream, chunkSize);     // Portal references from groups
                break;

            case (int)ChunkID.WMOChunkID.MOVV:
                ReadMOVV(WMOrootstream, chunkSize);     // Visible block vertices
                break;

            case (int)ChunkID.WMOChunkID.MOVB:
                ReadMOVB(WMOrootstream, chunkSize);     // Visible block list
                break;

            case (int)ChunkID.WMOChunkID.MOLT:
                ReadMOLT(WMOrootstream);     // Lighting information.
                break;

            case (int)ChunkID.WMOChunkID.MODS:
                ReadMODS(WMOrootstream, chunkSize);     // This chunk defines doodad sets.
                break;

            case (int)ChunkID.WMOChunkID.MODN:
                ReadMODN(WMOrootstream, chunkSize);     //List of filenames for M2
                break;

            case (int)ChunkID.WMOChunkID.MODD:
                ReadMODD(WMOrootstream, chunkSize);     // Information for doodad instances.
                break;

            case (int)ChunkID.WMOChunkID.MFOG:
                ReadMFOG(WMOrootstream, chunkSize);     // Fog information.
                break;

            case (int)ChunkID.WMOChunkID.MCVP:
                ReadMCVP(WMOrootstream, chunkSize);     // Convex Volume Planes.
                break;

            case (int)ChunkID.WMOChunkID.GFID:
                ReadGFID(WMOrootstream, chunkSize);     // required when WMO is loaded from fileID
                break;

            default:
                SkipUnknownChunk(WMOrootstream, chunkID, chunkSize);
                break;
            }
        }
        WMOrootstream.Close();
        WMOrootstream = null;
    }
Exemplo n.º 26
0
    private static void ParseWMO_Groups(string dataPath)
    {
        wmoData.groupsData = new List <GroupData>(wmoData.Info.nGroups);

        string noExtension   = Path.GetFileNameWithoutExtension(dataPath);
        string directoryPath = Path.GetDirectoryName(dataPath);

        //for (int grp = 0; grp < 1; grp++)
        for (int grp = 0; grp < wmoData.Info.nGroups; grp++)
        {
            groupDataBuffer = new GroupData();

            string fileNumber = grp.ToString("000");
            string fullPath   = directoryPath + @"\" + noExtension + "_" + fileNumber + ".wmo";

            Stream WMOgroupstream = Casc.GetFileStream(fullPath);

            int MVER     = ReadLong(WMOgroupstream);
            int MVERsize = ReadLong(WMOgroupstream);
            ReadMVER(WMOgroupstream); // root file version
            int MOGP     = ReadLong(WMOgroupstream);
            int MOGPsize = ReadLong(WMOgroupstream);
            ReadMOGP(WMOgroupstream); // group header (contains the rest of the chunks)

            int  MOTVcount      = 0;
            int  MOCVcount      = 0;
            long streamPosition = WMOgroupstream.Position;
            while (streamPosition < WMOgroupstream.Length)
            {
                WMOgroupstream.Position = streamPosition;
                int chunkID   = ReadLong(WMOgroupstream);
                int chunkSize = ReadLong(WMOgroupstream);
                streamPosition = WMOgroupstream.Position + chunkSize;
                switch (chunkID)
                {
                case (int)ChunkID.WMOChunkID.MOPY:
                    ReadMOPY(WMOgroupstream, chunkSize);     // Material info for triangles
                    break;

                case (int)ChunkID.WMOChunkID.MOVI:
                    ReadMOVI(WMOgroupstream, chunkSize);     // Vertex indices for triangles
                    break;

                case (int)ChunkID.WMOChunkID.MOVT:
                    ReadMOVT(WMOgroupstream, chunkSize);     // Vertices chunk
                    break;

                case (int)ChunkID.WMOChunkID.MONR:
                    ReadMONR(WMOgroupstream, chunkSize);     // Normals chunk
                    break;

                case (int)ChunkID.WMOChunkID.MOTV:
                {
                    MOTVcount++;
                    if (MOTVcount == 1)
                    {
                        ReadMOTV(WMOgroupstream, chunkSize);         // Texture coordinates
                    }
                    else if (MOTVcount == 2)
                    {
                        ReadMOTV2(WMOgroupstream, chunkSize);
                    }
                    else if (MOTVcount == 3)
                    {
                        ReadMOTV3(WMOgroupstream, chunkSize);
                    }
                }
                break;

                case (int)ChunkID.WMOChunkID.MOBA:
                    ReadMOBA(WMOgroupstream, chunkSize);     // Render batches
                    break;

                case (int)ChunkID.WMOChunkID.MOCV:
                {
                    MOCVcount++;
                    if (MOCVcount == 1)
                    {
                        ReadMOCV(WMOgroupstream, chunkSize);
                    }
                    else if (MOCVcount == 2)
                    {
                        ReadMOCV2(WMOgroupstream, chunkSize);
                    }
                }
                break;

                default:
                    SkipUnknownChunk(WMOgroupstream, chunkID, chunkSize);
                    break;
                }
            }

            wmoData.groupsData.Add(groupDataBuffer);

            WMOgroupstream.Close();
            WMOgroupstream = null;
        }
    }
Exemplo n.º 27
0
    public static MemoryStream ExtractData(Stream stream, int size)
    {
        if (size < 8)
        {
            Debug.Log("Error : BLTE block too small");
            return(null);
        }
        BinaryReader reader  = new BinaryReader(stream, Encoding.ASCII);
        MD5          md5     = MD5.Create();
        MemoryStream Mstream = new MemoryStream(); // write to this one
        int          magic   = reader.ReadInt32(); // BLTE (raw)

        if (magic != 0x45544c42)
        {
            Debug.Log("Error: BLTE_ExtractData - Wrong BLTE Magic");
            return(null);
        }
        else
        {
            int frameHeaderSize = Casc.ReadInt32BE(reader);
            int chunkCount      = 0;
            int totalSize       = 0;
            if (frameHeaderSize == 0)
            {
                totalSize  = size - 8;
                chunkCount = 1;
            }
            else
            {
                byte unk1 = reader.ReadByte();             // byte
                if (unk1 != 0x0F)
                {
                    Debug.Log("Error: BLTE_ExtractData - unk1 != 0x0F");
                    return(null);
                }
                byte v1 = reader.ReadByte();
                byte v2 = reader.ReadByte();
                byte v3 = reader.ReadByte();
                chunkCount = v1 << 16 | v2 << 8 | v3 << 0;             // 3-byte
            }
            if (chunkCount < 0)
            {
                Debug.Log("Error: BLTE_ExtractData - Possible error ({0}) at offset: {1:X8}");
                return(null);
            }
            BLTEChunk[] chunks = new BLTEChunk[chunkCount];
            for (int i = 0; i < chunkCount; i++)
            {
                chunks[i] = new BLTEChunk();
                if (frameHeaderSize != 0)
                {
                    chunks[i].CompSize   = Casc.ReadInt32BE(reader);
                    chunks[i].DecompSize = Casc.ReadInt32BE(reader);
                    chunks[i].Hash       = reader.ReadBytes(16);
                }
                else
                {
                    chunks[i].CompSize   = totalSize;
                    chunks[i].DecompSize = totalSize - 1;
                    chunks[i].Hash       = null;
                }
            }
            for (int i1 = 0; i1 < chunkCount; i1++)
            {
                chunks[i1].Data = reader.ReadBytes(chunks[i1].CompSize);
                if (chunks[i1].Data.Length != chunks[i1].CompSize)
                {
                    Debug.Log("Error: BLTE_ExtractData - chunks[i1].data.Length != chunks[i1].compSize");                  //might need a return
                }
                if (frameHeaderSize != 0)
                {
                    byte[] hh = md5.ComputeHash(chunks[i1].Data);
                    if (!Casc.EqualsTo(hh, chunks[i1].Hash))
                    {
                        Debug.Log("Error: BLTE_ExtractData - MD5 missmatch!");                      //might need return
                    }
                }
                HandleDataBlock(chunks[i1].Data, i1, Mstream);
            }
        }
        Mstream.Position = 0;
        return(Mstream);
    }