public byte[] ToArray(uint pccExportDataOffset, ME3PCCObject pcc)
        {
            using (MemoryStream tempStream = new MemoryStream())
            {
                tempStream.WriteBytes(headerData);

                // Whilst testing get rid of this
                // Heff: Seems like the shadowmap was the best solution in most cases,
                // adding an exception for known problematic animated textures for now.
                // (See popup in tpftools)
                if (properties.ContainsKey("LODGroup"))
                    properties["LODGroup"].Value.String2 = "TEXTUREGROUP_Shadowmap";
                else
                {
                    tempStream.WriteValueS64(pcc.addName2("LODGroup"));
                    tempStream.WriteValueS64(pcc.addName2("ByteProperty"));
                    tempStream.WriteValueS64(8);
                    tempStream.WriteValueS64(pcc.addName2("TextureGroup"));
                    tempStream.WriteValueS64(pcc.addName2("TEXTUREGROUP_Shadowmap"));
                }

                foreach (KeyValuePair<string, SaltPropertyReader.Property> kvp in properties)
                {
                    SaltPropertyReader.Property prop = kvp.Value;

                    if (prop.Name == "UnpackMin")
                    {
                        for (int i = 0; i < UnpackNum; i++)
                        {
                            tempStream.WriteValueS64(pcc.addName2(prop.Name));
                            tempStream.WriteValueS64(pcc.addName2(prop.TypeVal.ToString()));
                            tempStream.WriteValueS32(prop.Size);
                            tempStream.WriteValueS32(i);
                            tempStream.WriteValueF32(prop.Value.FloatValue);
                        }
                        continue;
                    }

                    tempStream.WriteValueS64(pcc.addName2(prop.Name));

                    if (prop.Name == "None")
                        continue;

                    tempStream.WriteValueS64(pcc.addName2(prop.TypeVal.ToString()));
                    tempStream.WriteValueS64(prop.Size);

                    switch (prop.TypeVal)
                    {
                        case SaltPropertyReader.Type.FloatProperty:
                            tempStream.WriteValueF32(prop.Value.FloatValue);
                            break;
                        case SaltPropertyReader.Type.IntProperty:
                            tempStream.WriteValueS32(prop.Value.IntValue);
                            break;
                        case SaltPropertyReader.Type.NameProperty:
                            tempStream.WriteValueS64(pcc.addName2(prop.Value.StringValue));
                            // Heff: Modified to handle name references.
                            //var nameIndex = pcc.addName2(prop.Value.StringValue);
                            //tempStream.WriteValueS32(nameIndex);
                            //tempStream.WriteValueS32(prop.Value.NameValue.count);
                            break;
                        case SaltPropertyReader.Type.ByteProperty:
                            tempStream.WriteValueS64(pcc.addName2(prop.Value.StringValue));
                            tempStream.WriteValueS64(pcc.addName2(prop.Value.String2));
                            // Heff: Modified to handle name references.
                            //var valueIndex = pcc.addName2(prop.Value.String2);
                            //tempStream.WriteValueS32(valueIndex);
                            //tempStream.WriteValueS32(prop.Value.NameValue.count);

                            //tempStream.WriteValueS32(pcc.addName2(prop.Value.String2));
                            //byte[] footer = new byte[4];
                            //Buffer.BlockCopy(prop.raw, prop.raw.Length - 4, footer, 0, 4);
                            //tempStream.WriteBytes(footer);
                            break;
                        case SaltPropertyReader.Type.BoolProperty:
                            tempStream.WriteValueBoolean(prop.Value.Boolereno);
                            break;
                        case SaltPropertyReader.Type.StructProperty:
                            tempStream.WriteValueS64(pcc.addName2(prop.Value.StringValue));
                            for (int i = 0; i < prop.Size; i++)
                                tempStream.WriteByte((byte)prop.Value.Array[i].IntValue);
                            break;
                        default:
                            throw new NotImplementedException("Property type: " + prop.TypeVal + ", not yet implemented. TELL ME ABOUT THIS!");
                    }
                }

                //Remove empty textures
                List<ImageInfo> tempList = new List<ImageInfo>();
                foreach (ImageInfo imgInfo in privateimgList)
                {
                    if (imgInfo.storageType != storage.empty)
                        tempList.Add(imgInfo);
                }
                privateimgList = tempList;
                numMipMaps = (uint)privateimgList.Count;

                tempStream.WriteValueU32(numMipMaps);
                foreach (ImageInfo imgInfo in privateimgList)
                {
                    tempStream.WriteValueS32((int)imgInfo.storageType);
                    tempStream.WriteValueS32(imgInfo.uncSize);
                    tempStream.WriteValueS32(imgInfo.cprSize);
                    if (imgInfo.storageType == storage.pccSto)
                    {
                        tempStream.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset));
                        tempStream.Write(imageData, imgInfo.offset, imgInfo.uncSize);
                    }
                    else
                        tempStream.WriteValueS32(imgInfo.offset);
                    tempStream.WriteValueU32(imgInfo.imgSize.width);
                    tempStream.WriteValueU32(imgInfo.imgSize.height);
                }
                //// Texture2D footer, 24 bytes size - changed to 20
                //tempStream.Write(imageData, imageData.Length - 20, 20);
                tempStream.WriteBytes(footerData);
                return tempStream.ToArray();
            }

            #region Unused Code
            /*
            bool lodExists = false;
            foreach (KeyValuePair<string, PropertyReader.Property> kvp in properties)
            {
                PropertyReader.Property property = kvp.Value;
                if (kvp.Key == "LODGroup")
                {
                    lodExists = true;
                    break;
                }
            }

            MemoryStream buffer = new MemoryStream();
            buffer.Write(headerData, 0, headerData.Length);

            if (lodExists)
            {
                // extracting values from LODGroup Property
                PropertyReader.Property LODGroup = properties["LODGroup"];
                string textureGroupName = pcc.Names[LODGroup.Value.IntValue];
                bool nameExists = false;
                string newTextureGroupName = "TEXTUREGROUP_Shadowmap";
                if (String.Compare(newTextureGroupName, textureGroupName) != 0)
                {
                    textureGroupName = newTextureGroupName;
                    if (!pcc.Names.Exists(name => name == newTextureGroupName))
                        pcc.Names.Add(newTextureGroupName);
                    using (MemoryStream rawStream = new MemoryStream(LODGroup.raw))
                    {
                        rawStream.Seek(32, SeekOrigin.Begin);
                        rawStream.WriteValueS32(pcc.Names.FindIndex(name => name == newTextureGroupName));
                        rawStream.WriteValueS32(0);
                        properties["LODGroup"].raw = rawStream.ToArray();
                    }
                }
                else
                    nameExists = true;
                //MemoryStream buffer = new MemoryStream();
                //buffer.Write(headerData, 0, headerData.Length);
                foreach (KeyValuePair<string, PropertyReader.Property> kvp in properties)
                {
                    PropertyReader.Property property = kvp.Value;

                    if (kvp.Key == "LODBias")
                        continue;
                    if (kvp.Key == "InternalFormatLODBias")
                        continue;
                    if (kvp.Key == "LODGroup" && nameExists == false)
                    {
                        int name;
                        if (!nameExists)
                            name = pcc.Names.Count - 1;                 //Warranty Voiders Name redirect hack^^
                        else
                            name = LODGroup.Value.IntValue;
                        ME3_HR_Patch.Helper.BitConverter.IsLittleEndian = true;
                        byte[] buff = ME3_HR_Patch.Helper.BitConverter.GetBytes(name);
                        for (int i = 0; i < 4; i++)
                            property.raw[i + 24] = buff[i];
                    }
                    buffer.Write(property.raw, 0, property.raw.Length);
                    if (kvp.Key == "UnpackMin")
                    {
                        buffer.Write(property.raw, 0, property.raw.Length);
                        buffer.Write(property.raw, 0, property.raw.Length);
                    }
                }
            }
            else
            {
                //MemoryStream buffer = new MemoryStream();
                //buffer.Write(headerData, 0, headerData.Length);
                int lodID = pcc.findName("LODGroup");
                if (lodID == -1)
                {
                    pcc.addName("LODGroup");
                    lodID = pcc.Names.Count - 1;
                }
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes(lodID));
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0));
                lodID = pcc.findName("ByteProperty");
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes(lodID));
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0));
                //Write an int
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)8));
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0));

                lodID = pcc.findName("TextureGroup");
                if (lodID == -1)
                {
                    pcc.addName("TextureGroup");
                    lodID = pcc.Names.Count - 1;
                }
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes(lodID));
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0));

                lodID = pcc.findName("TEXTUREGROUP_Shadowmap");
                if (lodID == -1)
                {
                    pcc.addName("TEXTUREGROUP_Shadowmap");
                    lodID = pcc.Names.Count - 1;
                }
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes(lodID));
                buffer.WriteBytes(ME3_HR_Patch.Helper.BitConverter.GetBytes((int)0));

                foreach (KeyValuePair<string, PropertyReader.Property> kvp in properties)
                {
                    PropertyReader.Property property = kvp.Value;

                    if (kvp.Key == "LODBias")
                        continue;
                    if (kvp.Key == "InternalFormatLODBias")
                        continue;
                    if (kvp.Key == "LODGroup")
                    {
                        int name = pcc.Names.Count - 1;                 //Warranty Voiders Name redirect hack^^
                        ME3_HR_Patch.Helper.BitConverter.IsLittleEndian = true;
                        byte[] buff = ME3_HR_Patch.Helper.BitConverter.GetBytes(name);
                        for (int i = 0; i < 4; i++)
                            property.raw[i + 24] = buff[i];
                    }
                    buffer.Write(property.raw, 0, property.raw.Length);
                    if (kvp.Key == "UnpackMin")
                    {
                        buffer.Write(property.raw, 0, property.raw.Length);
                        buffer.Write(property.raw, 0, property.raw.Length);
                    }
                }
            }

            buffer.WriteValueU32(numMipMaps);
            foreach (ImageInfo imgInfo in imgList)
            {
                buffer.WriteValueS32((int)imgInfo.storageType);
                buffer.WriteValueS32(imgInfo.uncSize);
                buffer.WriteValueS32(imgInfo.cprSize);
                if (imgInfo.storageType == storage.pccSto)
                {
                    buffer.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset));
                    buffer.Write(imageData, imgInfo.offset, imgInfo.uncSize);
                }
                else
                    buffer.WriteValueS32(imgInfo.offset);
                buffer.WriteValueU32(imgInfo.imgSize.width);
                buffer.WriteValueU32(imgInfo.imgSize.height);
            }
            // Texture2D footer, 24 bytes size
            buffer.Write(imageData, imageData.Length - 24, 24);
            byte[] rawData = buffer.ToArray();
            return rawData;
            */
            #endregion
        }
        public void CopyImgList(ME3SaltTexture2D inTex, ME3PCCObject pcc)
        {
            imageData = inTex.imageData;
            privateimgList = inTex.privateimgList;
            numMipMaps = inTex.numMipMaps;

            //Copy Properties
            byte[] buff;
            using (MemoryStream tempMem = new MemoryStream())
            {
                tempMem.WriteBytes(headerData);
                for (int i = 0; i < inTex.properties.Count; i++)
                {
                    SaltPropertyReader.Property prop = inTex.properties.ElementAt(i).Value;

                    if (prop.Name == "UnpackMin")
                    {
                        for (int j = 0; j < inTex.UnpackNum; j++)
                        {
                            tempMem.WriteValueS64(pcc.addName2(prop.Name));
                            tempMem.WriteValueS64(pcc.addName2(prop.TypeVal.ToString()));
                            tempMem.WriteValueS32(prop.Size);
                            tempMem.WriteValueS32(j);
                            tempMem.WriteValueF32(prop.Value.FloatValue);
                        }
                        continue;
                    }

                    tempMem.WriteValueS64(pcc.addName2(prop.Name));

                    if (prop.Name == "None")
                        continue;


                    tempMem.WriteValueS64(pcc.addName2(prop.TypeVal.ToString()));
                    tempMem.WriteValueS64(prop.Size);

                    switch (prop.TypeVal)
                    {
                        case SaltPropertyReader.Type.FloatProperty:
                            tempMem.WriteValueF32(prop.Value.FloatValue);
                            break;
                        case SaltPropertyReader.Type.IntProperty:
                            tempMem.WriteValueS32(prop.Value.IntValue);
                            break;
                        case SaltPropertyReader.Type.NameProperty:
                            tempMem.WriteValueS64(pcc.addName2(prop.Value.StringValue));
                            // Heff: Modified to handle name references.
                            //var index = pcc.addName2(prop.Value.StringValue);
                            //tempMem.WriteValueS32(index);
                            //tempMem.WriteValueS32(prop.Value.NameValue.count);
                            break;
                        case SaltPropertyReader.Type.ByteProperty:
                            tempMem.WriteValueS64(pcc.addName2(prop.Value.StringValue));
                            tempMem.WriteValueS32(pcc.addName2(prop.Value.String2));
                            byte[] footer = new byte[4];
                            Buffer.BlockCopy(prop.raw, prop.raw.Length - 4, footer, 0, 4);
                            tempMem.WriteBytes(footer);
                            break;
                        case SaltPropertyReader.Type.BoolProperty:
                            tempMem.WriteValueBoolean(prop.Value.Boolereno);
                            break;
                        case SaltPropertyReader.Type.StructProperty:
                            tempMem.WriteValueS64(pcc.addName2(prop.Value.StringValue));
                            for (int k = 0; k < prop.Size; k++)
                                tempMem.WriteByte((byte)prop.Value.Array[k].IntValue);
                            break;
                        default:
                            throw new NotImplementedException("Property type: " + prop.TypeVal + ", not yet implemented. TELL ME ABOUT THIS!");
                    }
                }
                buff = tempMem.ToArray();
            }

            properties = new Dictionary<string, SaltPropertyReader.Property>();

            List<SaltPropertyReader.Property> tempProperties = SaltPropertyReader.ReadProp(pcc, buff, headerData.Length);
            for (int i = 0; i < tempProperties.Count; i++)
            {
                SaltPropertyReader.Property property = tempProperties[i];
                if (property.Name == "UnpackMin")
                    UnpackNum++;

                if (!properties.ContainsKey(property.Name))
                    properties.Add(property.Name, property);

                switch (property.Name)
                {
                    case "Format":
                        texFormat = Textures.Methods.ParseFormat(pcc.Names[property.Value.IntValue].Substring(3));
                        break;
                    case "TextureFileCacheName": arcName = property.Value.NameValue.Name; break;
                    case "LODGroup": LODGroup = property.Value.NameValue.Name; break;
                    case "None": dataOffset = (uint)(property.offsetval + property.Size); break;
                }
            }

            // if "None" property isn't found throws an exception
            if (dataOffset == 0)
                throw new Exception("\"None\" property not found");
        }
Example #3
0
        public byte[] ThisToArray(uint pccExportDataOffset, ME2PCCObject pcc)
        {
            MemoryStream buffer = new MemoryStream();
            buffer.Write(headerData, 0, headerData.Length);

            if (properties.ContainsKey("LODGroup"))
            {
                properties["LODGroup"].Value.StringValue = "TEXTUREGROUP_LightAndShadowMap";
                properties["LODGroup"].Value.String2 = pcc.Names[0];
            }
            else
            {
                buffer.WriteValueS64(pcc.AddName("LODGroup"));
                buffer.WriteValueS64(pcc.AddName("ByteProperty"));
                buffer.WriteValueS64(8);
                buffer.WriteValueS64(pcc.AddName("TEXTUREGROUP_LightAndShadowMap"));
            }

            int count = 0;
            foreach (KeyValuePair<string, SaltPropertyReader.Property> kvp in properties)
            {
                SaltPropertyReader.Property prop = kvp.Value;

                if (prop.Name == "UnpackMin")
                {
                    for (int j = 0; j < UnpackNum; j++)
                    {
                        buffer.WriteValueS64(pcc.AddName(prop.Name));
                        buffer.WriteValueS64(pcc.AddName(prop.TypeVal.ToString()));
                        buffer.WriteValueS32(prop.Size);
                        buffer.WriteValueS32(j);
                        buffer.WriteValueF32(prop.Value.FloatValue, Endian.Little);
                    }
                    continue;
                }

                buffer.WriteValueS64(pcc.AddName(prop.Name));
                if (prop.Name == "None")
                {
                    for (int j = 0; j < 12; j++)
                        buffer.WriteByte(0);
                }
                else
                {
                    buffer.WriteValueS64(pcc.AddName(prop.TypeVal.ToString()));
                    buffer.WriteValueS64(prop.Size);

                    switch (prop.TypeVal)
                    {
                        case SaltPropertyReader.Type.IntProperty:
                            buffer.WriteValueS32(prop.Value.IntValue);
                            break;
                        case SaltPropertyReader.Type.BoolProperty:
                            buffer.WriteValueS32(prop.Value.IntValue);
                            break;
                        case SaltPropertyReader.Type.NameProperty:
                            buffer.WriteValueS64(pcc.AddName(prop.Value.StringValue));
                            // Heff: Modified to handle name references.
                            //var index = pcc.AddName(prop.Value.StringValue);
                            //buffer.WriteValueS32(index);
                            //buffer.WriteValueS32(prop.Value.NameValue.count);
                            break;
                        case SaltPropertyReader.Type.StrProperty:
                            buffer.WriteValueS32(prop.Value.StringValue.Length + 1);
                            foreach (char c in prop.Value.StringValue)
                                buffer.WriteByte((byte)c);
                            buffer.WriteByte(0);
                            break;
                        case SaltPropertyReader.Type.StructProperty:
                            string strVal = prop.Value.StringValue;
                                if (prop.Name.ToLowerInvariant().Contains("guid"))
                                    strVal = "Guid";

                            buffer.WriteValueS64(pcc.AddName(strVal));
                            foreach (SaltPropertyReader.PropertyValue value in prop.Value.Array)
                                buffer.WriteValueS32(value.IntValue);
                            break;
                        case SaltPropertyReader.Type.ByteProperty:
                            buffer.WriteValueS32(pcc.AddName(prop.Value.StringValue));
                            buffer.WriteValueS32(pcc.AddName(prop.Value.String2));
                            break;
                        case SaltPropertyReader.Type.FloatProperty:
                            buffer.WriteValueF32(prop.Value.FloatValue, Endian.Little);
                            break;
                        default:
                            throw new FormatException("unknown property");
                    }
                }

            }

            buffer.WriteValueS32((int)buffer.Position + (int)pccExportDataOffset);

            //Remove empty textures
            List<ImageInfo> tempList = new List<ImageInfo>();
            foreach (ImageInfo imgInfo in privateimgList)
            {
                if (imgInfo.storageType != storage.empty)
                    tempList.Add(imgInfo);
            }
            privateimgList = tempList;
            numMipMaps = (uint)privateimgList.Count;

            buffer.WriteValueU32(numMipMaps);
            foreach (ImageInfo imgInfo in privateimgList)
            {
                buffer.WriteValueS32((int)imgInfo.storageType);
                buffer.WriteValueS32(imgInfo.uncSize);
                buffer.WriteValueS32(imgInfo.cprSize);
                if (imgInfo.storageType == storage.pccSto)
                {
                    buffer.WriteValueS32((int)(buffer.Position + pccExportDataOffset));
                    buffer.Write(imageData, imgInfo.offset, imgInfo.uncSize);
                }
                else
                    buffer.WriteValueS32(imgInfo.offset);
                if (imgInfo.imgSize.width < 4)
                    buffer.WriteValueU32(4);
                else
                    buffer.WriteValueU32(imgInfo.imgSize.width);
                if (imgInfo.imgSize.height < 4)
                    buffer.WriteValueU32(4);
                else
                    buffer.WriteValueU32(imgInfo.imgSize.height);
            }
            buffer.WriteBytes(footerData);
            return buffer.ToArray();
        }
Example #4
0
        public void CopyImgList(Texture2D inTex, PCCObject pcc, bool norender = false)
        {
            List<ImageInfo> tempList = new List<ImageInfo>();
            MemoryStream tempData = new MemoryStream();
            SaltLZOHelper lzo = new SaltLZOHelper();
            numMipMaps = inTex.numMipMaps;

            // forced norenderfix
            // norender = true;

            int type = -1;
            if (!norender)
            {
                if (imgList.Exists(img => img.storageType == storage.arcCpr) && imgList.Count > 1)
                    type = 1;
                else if (imgList.Exists(img => img.storageType == storage.pccCpr))
                    type = 2;
                else if (imgList.Exists(img => img.storageType == storage.pccSto) || imgList.Count == 1)
                    type = 3;
            }
            else
                type = 3;

            switch (type)
            {
                case 1:
                    for (int i = 0; i < inTex.imgList.Count; i++)
                    {
                        try
                        {
                            ImageInfo newImg = new ImageInfo();
                            ImageInfo replaceImg = inTex.imgList[i];
                            Texture2D.storage replaceType = imgList.Find(img => img.imgSize == replaceImg.imgSize).storageType;

                            int j = 0;
                            while (replaceType == storage.empty)
                            {
                                j++;
                                replaceType = imgList[imgList.FindIndex(img => img.imgSize == replaceImg.imgSize) + j].storageType;
                            }

                            if (replaceType == storage.arcCpr || !imgList.Exists(img => img.imgSize == replaceImg.imgSize))
                            {
                                newImg.storageType = storage.arcCpr;
                                newImg.uncSize = replaceImg.uncSize;
                                newImg.cprSize = replaceImg.cprSize;
                                newImg.imgSize = replaceImg.imgSize;
                                newImg.offset = (int)(replaceImg.offset + inTex.pccOffset + inTex.dataOffset);
                            }
                            else
                            {
                                newImg.storageType = storage.pccSto;
                                newImg.uncSize = replaceImg.uncSize;
                                newImg.cprSize = replaceImg.uncSize;
                                newImg.imgSize = replaceImg.imgSize;
                                newImg.offset = (int)(tempData.Position);
                                using (MemoryStream tempStream = new MemoryStream(inTex.imageData))
                                {
                                    tempData.WriteBytes(lzo.DecompressTex(tempStream, replaceImg.offset, replaceImg.uncSize, replaceImg.cprSize));
                                }
                            }
                            tempList.Add(newImg);
                        }
                        catch
                        {
                            ImageInfo replaceImg = inTex.imgList[i];
                            if (!imgList.Exists(img => img.imgSize == replaceImg.imgSize))
                                throw new Exception("An error occurred during imglist copying and no suitable replacement was found");
                            ImageInfo newImg = imgList.Find(img => img.imgSize == replaceImg.imgSize);
                            if (newImg.storageType != storage.pccCpr && newImg.storageType != storage.pccSto)
                                throw new Exception("An error occurred during imglist copying and no suitable replacement was found");
                            int temppos = newImg.offset;
                            newImg.offset = (int)tempData.Position;
                            tempData.Write(imageData, temppos, newImg.cprSize);
                            tempList.Add(newImg);
                        }
                    }
                    break;
                case 2:
                    for (int i = 0; i < inTex.imgList.Count; i++)
                    {
                        ImageInfo newImg = new ImageInfo();
                        ImageInfo replaceImg = inTex.imgList[i];
                        newImg.storageType = storage.pccCpr;
                        newImg.uncSize = replaceImg.uncSize;
                        newImg.cprSize = replaceImg.cprSize;
                        newImg.imgSize = replaceImg.imgSize;
                        newImg.offset = (int)(tempData.Position);
                        byte[] buffer = new byte[newImg.cprSize];
                        Buffer.BlockCopy(inTex.imageData, replaceImg.offset, buffer, 0, buffer.Length);
                        tempData.WriteBytes(buffer);
                        tempList.Add(newImg);
                    }
                    break;
                case 3:
                    for (int i = 0; i < inTex.imgList.Count; i++)
                    {
                        ImageInfo newImg = new ImageInfo();
                        ImageInfo replaceImg = inTex.imgList[i];
                        newImg.storageType = storage.pccSto;
                        newImg.uncSize = replaceImg.uncSize;
                        newImg.cprSize = replaceImg.uncSize;
                        newImg.imgSize = replaceImg.imgSize;
                        newImg.offset = (int)(tempData.Position);
                        if (replaceImg.storageType == storage.pccCpr)
                        {
                            using (MemoryStream tempStream = new MemoryStream(inTex.imageData))
                            {
                                tempData.WriteBytes(lzo.DecompressTex(tempStream, replaceImg.offset, replaceImg.uncSize, replaceImg.cprSize));
                            }
                        }
                        else if (replaceImg.storageType == storage.pccSto)
                        {
                            byte[] buffer = new byte[newImg.cprSize];
                            Buffer.BlockCopy(inTex.imageData, replaceImg.offset, buffer, 0, buffer.Length);
                            tempData.WriteBytes(buffer);
                        }
                        else
                            throw new NotImplementedException("Copying from non package stored texture no available");
                        tempList.Add(newImg);
                    }
                    break;
                default:
                    throw new NotImplementedException();
            }

            for (int i = 0; i < tempList.Count; i++)
            {
                ImageInfo tempinfo = tempList[i];
                if (inTex.imgList[i].storageType == storage.empty)
                    tempinfo.storageType = storage.empty;
                tempList[i] = tempinfo;
            }

            imgList = tempList;
            imageData = tempData.ToArray();
            tempData.Close();

            byte[] buff;
            //Copy properties
            using (MemoryStream tempMem = new MemoryStream())
            {
                tempMem.WriteBytes(headerData);
                for (int i = 0; i < inTex.properties.Count; i++)
                {
                    SaltPropertyReader.Property prop = inTex.properties.ElementAt(i).Value;

                    if (prop.Name == "UnpackMin")
                    {
                        for (int j = 0; j < inTex.UnpackNum; j++)
                        {
                            tempMem.WriteValueS64(pcc.AddName(prop.Name));
                            tempMem.WriteValueS64(pcc.AddName(prop.TypeVal.ToString()));
                            tempMem.WriteValueS32(prop.Size);
                            tempMem.WriteValueS32(j);
                            tempMem.WriteValueF32(prop.Value.FloatValue, Endian.Little);
                        }
                        continue;
                    }

                    tempMem.WriteValueS64(pcc.AddName(prop.Name));
                    if (prop.Name == "None")
                    {
                        for (int j = 0; j < 12; j++)
                            tempMem.WriteByte(0);
                    }
                    else
                    {
                        tempMem.WriteValueS64(pcc.AddName(prop.TypeVal.ToString()));
                        tempMem.WriteValueS64(prop.Size);

                        switch (prop.TypeVal)
                        {
                            case SaltPropertyReader.Type.IntProperty:
                                tempMem.WriteValueS32(prop.Value.IntValue);
                                break;
                            case SaltPropertyReader.Type.BoolProperty:
                                tempMem.Seek(-4, SeekOrigin.Current);
                                tempMem.WriteValueS32(prop.Value.IntValue);
                                tempMem.Seek(4, SeekOrigin.Current);
                                break;
                            case SaltPropertyReader.Type.NameProperty:
                                tempMem.WriteValueS64(pcc.AddName(prop.Value.StringValue));
                                break;
                            case SaltPropertyReader.Type.StrProperty:
                                tempMem.WriteValueS32(prop.Value.StringValue.Length + 1);
                                foreach (char c in prop.Value.StringValue)
                                    tempMem.WriteByte((byte)c);
                                tempMem.WriteByte(0);
                                break;
                            case SaltPropertyReader.Type.StructProperty:
                                tempMem.WriteValueS64(pcc.AddName(prop.Value.StringValue));
                                foreach (SaltPropertyReader.PropertyValue value in prop.Value.Array)
                                    tempMem.WriteValueS32(value.IntValue);
                                break;
                            case SaltPropertyReader.Type.ByteProperty:
                                tempMem.WriteValueS32(pcc.AddName(prop.Value.StringValue));
                                tempMem.WriteValueS32(prop.Value.IntValue);
                                break;
                            case SaltPropertyReader.Type.FloatProperty:
                                tempMem.WriteValueF32(prop.Value.FloatValue, Endian.Little);
                                break;
                            default:
                                throw new FormatException("unknown property");
                        }
                    }
                }
                buff = tempMem.ToArray();
            }

            int propertiesOffset = SaltPropertyReader.detectStart(pcc, buff);
            headerData = new byte[propertiesOffset];
            Buffer.BlockCopy(buff, 0, headerData, 0, propertiesOffset);
            properties = new Dictionary<string, SaltPropertyReader.Property>();
            List<SaltPropertyReader.Property> tempProperties = SaltPropertyReader.getPropList(pcc, buff);
            UnpackNum = 0;
            for (int i = 0; i < tempProperties.Count; i++)
            {
                SaltPropertyReader.Property property = tempProperties[i];
                if (property.Name == "UnpackMin")
                    UnpackNum++;

                if (!properties.ContainsKey(property.Name))
                    properties.Add(property.Name, property);

                switch (property.Name)
                {
                    case "Format": texFormat = property.Value.StringValue; break;
                    case "LODGroup": LODGroup = property.Value.StringValue; break;
                    case "CompressionSettings": Compression = property.Value.StringValue; break;
                    case "None": dataOffset = (uint)(property.offsetval + property.Size); break;
                }
            }

            // if "None" property isn't found throws an exception
            if (dataOffset == 0)
                throw new Exception("\"None\" property not found");
        }
Example #5
0
        public byte[] ToArray(int pccExportDataOffset, PCCObject pcc)
        {
            MemoryStream buffer = new MemoryStream();
            buffer.Write(headerData, 0, headerData.Length);

            if (properties.ContainsKey("LODGroup"))
            {
                properties["LODGroup"].Value.StringValue = "TEXTUREGROUP_LightAndShadowMap";
                //properties["LODGroup"].Value.IntValue = 1025;
            }
            else
            {
                buffer.WriteValueS64(pcc.AddName("LODGroup"));
                buffer.WriteValueS64(pcc.AddName("ByteProperty"));
                buffer.WriteValueS64(8);
                buffer.WriteValueS32(pcc.AddName("TEXTUREGROUP_LightAndShadowMap"));
                buffer.WriteValueS32(1025);
            }

            foreach (KeyValuePair<string, SaltPropertyReader.Property> kvp in properties)
            {
                SaltPropertyReader.Property prop = kvp.Value;

                if (prop.Name == "UnpackMin")
                {
                    for (int j = 0; j < UnpackNum; j++)
                    {
                        buffer.WriteValueS64(pcc.AddName(prop.Name));
                        buffer.WriteValueS64(pcc.AddName(prop.TypeVal.ToString()));
                        buffer.WriteValueS32(prop.Size);
                        buffer.WriteValueS32(j);
                        buffer.WriteValueF32(prop.Value.FloatValue, Endian.Little);
                    }
                    continue;
                }

                buffer.WriteValueS64(pcc.AddName(prop.Name));
                if (prop.Name == "None")
                {
                    for (int j = 0; j < 12; j++)
                        buffer.WriteByte(0);
                }
                else
                {
                    buffer.WriteValueS64(pcc.AddName(prop.TypeVal.ToString()));
                    buffer.WriteValueS64(prop.Size);

                    switch (prop.TypeVal)
                    {
                        case SaltPropertyReader.Type.IntProperty:
                            buffer.WriteValueS32(prop.Value.IntValue);
                            break;
                        case SaltPropertyReader.Type.BoolProperty:
                            buffer.Seek(-4, SeekOrigin.Current);
                            buffer.WriteValueS32(prop.Value.IntValue);
                            buffer.Seek(4, SeekOrigin.Current);
                            break;
                        case SaltPropertyReader.Type.NameProperty:
                            buffer.WriteValueS64(pcc.AddName(prop.Value.StringValue));
                            break;
                        case SaltPropertyReader.Type.StrProperty:
                            buffer.WriteValueS32(prop.Value.StringValue.Length + 1);
                            foreach (char c in prop.Value.StringValue)
                                buffer.WriteByte((byte)c);
                            buffer.WriteByte(0);
                            break;
                        case SaltPropertyReader.Type.StructProperty:
                            buffer.WriteValueS64(pcc.AddName(prop.Value.StringValue));
                            foreach (SaltPropertyReader.PropertyValue value in prop.Value.Array)
                                buffer.WriteValueS32(value.IntValue);
                            break;
                        case SaltPropertyReader.Type.ByteProperty:
                            buffer.WriteValueS32(pcc.AddName(prop.Value.StringValue));
                            buffer.WriteValueS32(prop.Value.IntValue);
                            break;
                        case SaltPropertyReader.Type.FloatProperty:
                            buffer.WriteValueF32(prop.Value.FloatValue, Endian.Little);
                            break;
                        default:
                            throw new FormatException("unknown property");
                    }
                }
            }

            buffer.WriteValueS32((int)(pccOffset + buffer.Position + 4));

            //Remove empty textures
            List<ImageInfo> tempList = new List<ImageInfo>();
            foreach (ImageInfo imgInfo in imgList)
            {
                if (imgInfo.storageType != storage.empty)
                    tempList.Add(imgInfo);
            }
            imgList = tempList;
            numMipMaps = (uint)imgList.Count;

            buffer.WriteValueU32(numMipMaps);

            foreach (ImageInfo imgInfo in imgList)
            {
                buffer.WriteValueS32((int)imgInfo.storageType);
                buffer.WriteValueS32(imgInfo.uncSize);
                buffer.WriteValueS32(imgInfo.cprSize);
                if (imgInfo.storageType == storage.pccSto)
                {
                    buffer.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset));
                    buffer.Write(imageData, imgInfo.offset, imgInfo.uncSize);
                }
                else if (imgInfo.storageType == storage.pccCpr)
                {
                    buffer.WriteValueS32((int)(imgInfo.offset + pccExportDataOffset + dataOffset));
                    buffer.Write(imageData, imgInfo.offset, imgInfo.cprSize);
                }
                else
                    buffer.WriteValueS32(imgInfo.offset);
                if (imgInfo.imgSize.width < 4)
                    buffer.WriteValueU32(4);
                else
                    buffer.WriteValueU32(imgInfo.imgSize.width);
                if (imgInfo.imgSize.height < 4)
                    buffer.WriteValueU32(4);
                else
                    buffer.WriteValueU32(imgInfo.imgSize.height);
            }
            buffer.WriteBytes(footerData);
            return buffer.ToArray();
        }
 public static void WriteStructPropVector(this Stream stream, IMEPackage pcc, string propName, float x, float y, float z)
 {
     MemoryStream m = new MemoryStream(12);
     m.WriteValueF32(x);
     m.WriteValueF32(y);
     m.WriteValueF32(z);
     stream.WriteStructProperty(pcc, propName, "Vector", m.ToArray());
 }