public static bool fixBadIndex(Database db)
        {
            uint numFixed = 0;
            if (db.dbpf.packageType == Detective.PackageTypes.corruptIndex)
            {
                // This means the index is off by 3.  We can just write the file out again
                numFixed++;
            }

            if (numFixed == 0)
            {
                return false;
            }
            else
            {
                db.Commit(true);
            }

            return true;
        }
        public static Stream getStream(string filename, int typeID, int groupID, long instanceID)
        {
            Stream matchChunk = null;

            if (String.IsNullOrEmpty(filename))
            {
                return(matchChunk);
            }

            // Open the package file and search
            Stream package = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);

            MadScience.Wrappers.Database db = new MadScience.Wrappers.Database(package, true);

            matchChunk = getStream(db, typeID, groupID, instanceID);

            package.Close();

            return(matchChunk);
        }
        public static bool fixRecursive(Database db)
        {
            uint numFixed = 0;

            // textBox1.Text += "Checking for corrupted TXTC entries... " + Environment.NewLine;
            for (int i = 0; i < db.dbpf.Entries.Count; i++)
            {
                DatabasePackedFile.Entry entry = db.dbpf.Entries[i];
                if ((entry.Key.typeId == 0x0) && (entry.Key.groupId == 0x0) && (entry.Key.instanceId == 0x0))
                {
                    // Check the first 4 bytes of the stream
                    Stream checkDbpf = db.GetResourceStream(entry.Key);
                    string magic = MadScience.StreamHelpers.ReadStringASCII(checkDbpf, 4);
                    if (magic == "DBPF" || magic == "DBBF") // DBPF & DBBF
                    {
                        db.DeleteResource(entry.Key);
                        numFixed++;
                    }
                    checkDbpf.Close();
                }

            }

            if (numFixed == 0)
            {
                //textBox1.Text += Environment.NewLine;
                //textBox1.Text += "This file appears OK!";
                return false;
            }
            else
            {
                //this.filesFixed++;
                //textBox1.Text += Environment.NewLine;
                //textBox1.Text += "This file had some corrupted TXTCs! They are now fixed.";
                //textBox1.Text += "Fixed " + filename + Environment.NewLine;
                //saveToolStripMenuItem.Enabled = true;
                db.Commit(true);
            }

            return true;
        }
        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveFileDialog1.FileName = Helpers.currentPackageFile;
            saveFileDialog1.Filter = "Sims 3 Packages|*.package|CASPart|*.caspart";
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {

                FileInfo f = new FileInfo(saveFileDialog1.FileName);

                if (f.Extension == ".package")
                {

                    Stream saveFile = File.Open(saveFileDialog1.FileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);

                    ulong instanceId;

                    using (SaveForm sf = new SaveForm("", "CTU_" + DateTime.Now.Ticks + "_" + MadScience.Helpers.sanitiseString(f.Name), loadedCasPart.instanceId))
                    {
                        sf.ShowDialog(this);

                        instanceId = sf.Instance;
                    }
                    Database db = new Database(saveFile, false);

                    saveToDBPF(db, instanceId, true);

                    db.Commit(true);

                    saveFile.Close();

                    this.filename = f.Name;
                    makeTitleBar();
                }
                if (f.Extension == ".caspart")
                {
                    Stream saveFile = File.Open(saveFileDialog1.FileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);

                    MemoryStream mem = new MemoryStream();
                    casPartFile casPF = new casPartFile();
                    casPF.Save(mem, casPartNew);
                    casPF = null;

                    saveFile.Write(mem.GetBuffer(), 0, (int)mem.Length);

                    saveFile.Close();

                }
            }
        }
        private Image extractCASThumbnail(string meshName)
        {
            //Console.WriteLine("Started " + meshName + " at " + DateTime.Now.ToString());

            Helpers.logMessageToFile("Attemping to extract thumbnail for " + meshName);

            Image tempImage = null;

            if (String.IsNullOrEmpty(sims3root))
            {
                sims3root = MadScience.Helpers.findSims3Root();
            }

            string thumbnailPackage = Helpers.getGameSubPath(@"\Thumbnails\CasThumbnails.package");
            Helpers.logMessageToFile(Path.Combine(sims3root, thumbnailPackage));
            if (sims3root != "" && File.Exists(Path.Combine(sims3root, thumbnailPackage)))
            {
                // Open CAS Thumbnails package
                Stream cast = File.Open(Path.Combine(sims3root, thumbnailPackage), FileMode.Open, FileAccess.Read, FileShare.Read);
                Database castdb = new Database(cast, true);

                ulong instanceid = MadScience.StringHelpers.HashFNV64(meshName);

                if (casThumbsKeyList.Count == 0)
                {
                    Helpers.logMessageToFile("Populating casThumbs entry lists from " + castdb._Entries.Count.ToString() + " entries");
                    foreach (MadScience.Wrappers.ResourceKey entry in castdb._Entries.Keys)
                    {
                        //DatabasePackedFile.Entry entry = castdb.dbpfEntries[i];
                        if (entry.groupId == 0x00000000 && entry.typeId == 0x626f60ce)
                        {
                            casThumbsKeyList.Add(entry.instanceId, entry);
                        }
                        if (entry.groupId == 0x00000001 && entry.typeId == 0x626f60ce)
                        {
                            casThumbsKeyList2.Add(entry.instanceId, entry);
                        }
                    }
                    Helpers.logMessageToFile("casThumbs now contains " + casThumbsKeyList.Count.ToString() + " entries");
                    Helpers.logMessageToFile("casThumbs2 now contains " + casThumbsKeyList2.Count.ToString() + " entries");
                }

                bool foundPic = false;
                ResourceKey temp = new ResourceKey();
                if (casThumbsKeyList.ContainsKey(instanceid))
                {
                    temp = casThumbsKeyList[instanceid];
                    foundPic = true;
                }
                else
                {
                    if (casThumbsKeyList2.ContainsKey(instanceid))
                    {
                        temp = casThumbsKeyList2[instanceid];
                        foundPic = true;
                    }
                }

                if (foundPic)
                {
                    tempImage = Image.FromStream(castdb.GetResourceStream(temp));
                    try
                    {
                        tempImage.Save(Path.Combine(Application.StartupPath, Path.Combine("cache", meshName + ".png")), System.Drawing.Imaging.ImageFormat.Png);
                    }
                    catch (Exception ex)
                    {
                    }

                }
                else
                {
                    Helpers.logMessageToFile("Couldn't find a match for " + meshName + " (0x" + instanceid.ToString("X16") + ")");
                }

                cast.Close();
                //dbpf = null;
                castdb = null;
            }
            else
            {
                Helpers.logMessageToFile(@"Can't find sims3root or Thumbnails\CasThumbnails.package");
            }

            //Console.WriteLine("Stopped " + meshName + " at " + DateTime.Now.ToString());

            return tempImage;
        }
        public static ResourceKey getKey(string filename, int typeID, int groupID, long instanceID)
        {
            ResourceKey matchChunk = new ResourceKey();


            if (String.IsNullOrEmpty(filename))
            {
                return(matchChunk);
            }

            // Open the package file and search
            Stream package = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);

            MadScience.Wrappers.Database db = new MadScience.Wrappers.Database(package, true);

            int searchType = 0;

            if (typeID != -1)
            {
                searchType += 1;
            }
            if (groupID != -1)
            {
                searchType += 2;
            }
            if (instanceID != -1)
            {
                searchType += 4;
            }

            bool foundMatch = false;

            foreach (MadScience.Wrappers.ResourceKey entry in db._Entries.Keys)
            {
                //ResourceKey key = db.Entries.Keys[i];
                //DatabasePackedFile.Entry entry = db.Entries.Keys[i];
                //DatabasePackedFile.Entry entry = db.dbpfEntries[i];
                //MadScience.Wrappers.ResourceKey entry = new MadScience.Wrappers.ResourceKey(keyString);

                switch (searchType)
                {
                case 7:
                    if (entry.typeId == typeID && entry.groupId == groupID && entry.instanceId == (ulong)instanceID)
                    {
                        //loadedCasPart = entry;
                        //matchChunk = db.GetResourceStream(entry);
                        matchChunk = entry;
                        foundMatch = true;
                    }
                    break;

                case 6:
                    if (entry.groupId == groupID && entry.instanceId == (ulong)instanceID)
                    {
                        //loadedCasPart = entry;
                        //matchChunk = db.GetResourceStream(entry);
                        matchChunk = entry;
                        foundMatch = true;
                    }
                    break;

                case 5:
                    if (entry.typeId == typeID && entry.instanceId == (ulong)instanceID)
                    {
                        //loadedCasPart = entry;
                        //matchChunk = db.GetResourceStream(entry);
                        matchChunk = entry;
                        foundMatch = true;
                    }
                    break;

                case 4:
                    if (entry.instanceId == (ulong)instanceID)
                    {
                        //loadedCasPart = entry;
                        //matchChunk = db.GetResourceStream(entry);
                        matchChunk = entry;
                        foundMatch = true;
                    }
                    break;

                case 3:
                    if (entry.typeId == typeID && entry.groupId == groupID)
                    {
                        //loadedCasPart = entry;
                        //matchChunk = db.GetResourceStream(entry);
                        matchChunk = entry;
                        foundMatch = true;
                    }
                    break;

                case 2:
                    if (entry.groupId == groupID)
                    {
                        //loadedCasPart = entry;
                        //matchChunk = db.GetResourceStream(entry);
                        matchChunk = entry;
                        foundMatch = true;
                    }
                    break;

                case 1:
                    if (entry.typeId == typeID)
                    {
                        //loadedCasPart = entry;
                        //matchChunk = db.GetResourceStream(entry);
                        matchChunk = entry;
                        foundMatch = true;
                    }
                    break;
                }
                if (foundMatch)
                {
                    break;
                }
            }
            package.Close();

            return(matchChunk);
        }
        public static ResourceKey getKey(string filename, int typeID, int groupID, long instanceID)
        {
            ResourceKey matchChunk = new ResourceKey();

            if (String.IsNullOrEmpty(filename)) { return matchChunk; }

            // Open the package file and search
            Stream package = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
            MadScience.Wrappers.Database db = new MadScience.Wrappers.Database(package, true);

            int searchType = 0;
            if (typeID != -1) { searchType += 1; }
            if (groupID != -1) { searchType += 2; }
            if (instanceID != -1) { searchType += 4; }

            bool foundMatch = false;

            foreach (MadScience.Wrappers.ResourceKey entry in db._Entries.Keys)
            {
                //ResourceKey key = db.Entries.Keys[i];
                //DatabasePackedFile.Entry entry = db.Entries.Keys[i];
                //DatabasePackedFile.Entry entry = db.dbpfEntries[i];
                //MadScience.Wrappers.ResourceKey entry = new MadScience.Wrappers.ResourceKey(keyString);

                switch (searchType)
                {
                    case 7:
                        if (entry.typeId == typeID && entry.groupId == groupID && entry.instanceId == (ulong)instanceID)
                        {
                            //loadedCasPart = entry;
                            //matchChunk = db.GetResourceStream(entry);
                            matchChunk = entry;
                            foundMatch = true;
                        }
                        break;
                    case 6:
                        if (entry.groupId == groupID && entry.instanceId == (ulong)instanceID)
                        {
                            //loadedCasPart = entry;
                            //matchChunk = db.GetResourceStream(entry);
                            matchChunk = entry;
                            foundMatch = true;
                        }
                        break;
                    case 5:
                        if (entry.typeId == typeID && entry.instanceId == (ulong)instanceID)
                        {
                            //loadedCasPart = entry;
                            //matchChunk = db.GetResourceStream(entry);
                            matchChunk = entry;
                            foundMatch = true;
                        }
                        break;
                    case 4:
                        if (entry.instanceId == (ulong)instanceID)
                        {
                            //loadedCasPart = entry;
                            //matchChunk = db.GetResourceStream(entry);
                            matchChunk = entry;
                            foundMatch = true;
                        }
                        break;
                    case 3:
                        if (entry.typeId == typeID && entry.groupId == groupID)
                        {
                            //loadedCasPart = entry;
                            //matchChunk = db.GetResourceStream(entry);
                            matchChunk = entry;
                            foundMatch = true;
                        }
                        break;
                    case 2:
                        if (entry.groupId == groupID)
                        {
                            //loadedCasPart = entry;
                            //matchChunk = db.GetResourceStream(entry);
                            matchChunk = entry;
                            foundMatch = true;
                        }
                        break;
                    case 1:
                        if (entry.typeId == typeID)
                        {
                            //loadedCasPart = entry;
                            //matchChunk = db.GetResourceStream(entry);
                            matchChunk = entry;
                            foundMatch = true;
                        }
                        break;
                }
                if (foundMatch)
                {
                    break;
                }

            }
            package.Close();

            return matchChunk;
        }
Example #8
0
        public static Image makePatternThumb(patternDetails pattern, Wrappers.Database db)
        {
            Image temp = null;

            if (pattern.type == "HSV")
            {
                DdsFileTypePlugin.DdsFile ddsP = new DdsFileTypePlugin.DdsFile();

                Colours.HSVColor channel1Color = new Colours.HSVColor();
                Colours.HSVColor channel2Color = new Colours.HSVColor();
                Colours.HSVColor channel3Color = new Colours.HSVColor();

                Colours.HSVColor backColor       = new Colours.HSVColor(Convert.ToDouble(pattern.HBg, CultureInfo.InvariantCulture) * 360, Convert.ToDouble(pattern.SBg, CultureInfo.InvariantCulture), Convert.ToDouble(pattern.VBg, CultureInfo.InvariantCulture));
                bool[]           channelsEnabled = new bool[3];

                if (pattern.ChannelEnabled[0] != null && pattern.ChannelEnabled[0].ToLower() == "true")
                {
                    channel1Color      = new Colours.HSVColor(Convert.ToDouble(pattern.H[0], CultureInfo.InvariantCulture) * 360, Convert.ToDouble(pattern.S[0], CultureInfo.InvariantCulture), Convert.ToDouble(pattern.V[0], CultureInfo.InvariantCulture));
                    channelsEnabled[0] = true;
                }
                if (pattern.ChannelEnabled[1] != null && pattern.ChannelEnabled[1].ToLower() == "true")
                {
                    channel2Color      = new Colours.HSVColor(Convert.ToDouble(pattern.H[1], CultureInfo.InvariantCulture) * 360, Convert.ToDouble(pattern.S[1], CultureInfo.InvariantCulture), Convert.ToDouble(pattern.V[1], CultureInfo.InvariantCulture));
                    channelsEnabled[1] = true;
                }
                if (pattern.ChannelEnabled[2] != null && pattern.ChannelEnabled[2].ToLower() == "true")
                {
                    channel3Color      = new Colours.HSVColor(Convert.ToDouble(pattern.H[2], CultureInfo.InvariantCulture) * 360, Convert.ToDouble(pattern.S[2], CultureInfo.InvariantCulture), Convert.ToDouble(pattern.V[2], CultureInfo.InvariantCulture));
                    channelsEnabled[2] = true;
                }
                if (isEmptyMask(pattern.rgbmask))
                {
                    if (db != null)
                    {
                        temp = Patterns.createHSVPattern(KeyUtils.findKey(new Wrappers.ResourceKey(pattern.BackgroundImage), 2, db), backColor);
                    }
                    else
                    {
                        temp = Patterns.createHSVPattern(KeyUtils.findKey(pattern.BackgroundImage), backColor);
                    }
                }
                else
                {
                    if (db != null)
                    {
                        temp = Patterns.createHSVPattern(KeyUtils.findKey(new Wrappers.ResourceKey(pattern.BackgroundImage), 2, db), KeyUtils.findKey(new Wrappers.ResourceKey(pattern.rgbmask), 2, db), backColor, KeyUtils.findKey(new MadScience.Wrappers.ResourceKey(makeKey(pattern.Channel[0])), 0, db), KeyUtils.findKey(new Wrappers.ResourceKey(makeKey(pattern.Channel[1])), 0, db), KeyUtils.findKey(new Wrappers.ResourceKey(makeKey(pattern.Channel[2])), 0, db), channel1Color, channel2Color, channel3Color, channelsEnabled);
                    }
                    else
                    {
                        temp = Patterns.createHSVPattern(KeyUtils.findKey(pattern.BackgroundImage), KeyUtils.findKey(pattern.rgbmask), backColor, KeyUtils.findKey(makeKey(pattern.Channel[0])), KeyUtils.findKey(makeKey(pattern.Channel[1])), KeyUtils.findKey(makeKey(pattern.Channel[2])), channel1Color, channel2Color, channel3Color, channelsEnabled);
                    }
                }
            }
            else if (pattern.type == "Coloured")
            {
                DdsFileTypePlugin.DdsFile ddsP = new DdsFileTypePlugin.DdsFile();
                Color bgColor = Colours.convertColour(pattern.ColorP[0], true);
                if (bgColor == Color.Empty)
                {
                    bgColor = Color.Black;
                }
                if (pattern.isCustom)
                {
                    // We need this in here becuase findKey only searches the game files and any local DDS files - it
                    // doesn't search custom packages
                    if (File.Exists(pattern.customFilename))
                    {
                        Stream patternThumb = KeyUtils.searchForKey(pattern.rgbmask, pattern.customFilename);
                        if (!StreamHelpers.isValidStream(patternThumb))
                        {
                            patternThumb = KeyUtils.searchForKey(pattern.BackgroundImage, pattern.customFilename);
                        }
                        if (StreamHelpers.isValidStream(patternThumb))
                        {
                            ddsP.Load(patternThumb);
                        }
                        patternThumb.Close();
                    }
                }
                else
                {
                    if (db != null)
                    {
                        ddsP.Load(KeyUtils.findKey(new Wrappers.ResourceKey(pattern.rgbmask), 2, db));
                    }
                    else
                    {
                        ddsP.Load(KeyUtils.findKey(pattern.rgbmask));
                    }
                }
                temp = ddsP.Image(bgColor, Colours.convertColour(pattern.ColorP[1], true), Colours.convertColour(pattern.ColorP[2], true), Colours.convertColour(pattern.ColorP[3], true), Colours.convertColour(pattern.ColorP[4], true));
            }
            else if (pattern.type == "solidColor")
            {
                temp = new Bitmap(256, 256);
                using (Graphics g = Graphics.FromImage(temp))
                {
                    g.FillRectangle(new SolidBrush(Colours.convertColour(pattern.Color)), 0, 0, 256, 256);
                }
            }


            return(temp);
        }
        private bool checkTXTCEntry(DatabasePackedFile.Entry entry, Database db)
        {
            if (entry.Key.typeId == 0x033A1435)
            {
                //textBox1.Text += "  " + entry.Key.ToString() + Environment.NewLine;
                // textBox1.Text += "    Checking for corrupted TGI offset... ";

                // Quick and dirty way
                Stream TXTC = db.GetResourceStream(entry.Key);
                // Read offset, first 4 bytes after ID
                StreamHelpers.ReadValueU32(TXTC);

                uint offset = StreamHelpers.ReadValueU32(TXTC);
                // textBox1.Text += offset.ToString() + "...";

                // Seek to this offset + 8 and read the number there.
                TXTC.Seek(offset + 8, SeekOrigin.Begin);

                uint numTGIs = StreamHelpers.ReadValueU8(TXTC);
                // textBox1.Text += numTGIs.ToString() + " TGIs... ";

                // Since each TGI is 16 bytes we can calculate how many bytes they are.
                uint tgiSize = numTGIs * 16;
                uint tgiOffsetEnd = offset + 8 + 1 + tgiSize;

                //textBox1.Text += "TGI block end is at " + tgiOffsetEnd.ToString() + "...";

                if (tgiOffsetEnd == TXTC.Length)
                {
                    TXTC = null;
                    return true;
                }
                else
                {
                    TXTC = null;
                    return false;
                }

            }

            return true;
        }
 public PackageType getType(Stream input)
 {
     Database db = new Database(input, true, false);
     return getType(db, false);
 }
 public static bool fixRecursive(Stream input, bool throwError)
 {
     Database db = new Database(input, true, throwError);
     return fixRecursive(db);
 }
 public static bool fixBadIndex(Stream input, bool throwError)
 {
     Database db = new Database(input, true, throwError);
     return fixBadIndex(db);
 }
        public static bool fixTXTR(Database db)
        {
            uint numFixed = 0;

            // textBox1.Text += "Checking for corrupted TXTC entries... " + Environment.NewLine;
            for (int i = 0; i < db.dbpf.Entries.Count; i++)
            {
                DatabasePackedFile.Entry entry = db.dbpf.Entries[i];
                if (entry.Key.typeId == 0x033A1435)
                {
                    //textBox1.Text += "  " + entry.Key.ToString() + Environment.NewLine;
                    // textBox1.Text += "    Checking for corrupted TGI offset... ";

                    // Quick and dirty way
                    Stream TXTC = db.GetResourceStream(entry.Key);
                    // Read offset, first 4 bytes after ID
                    StreamHelpers.ReadValueU32(TXTC);

                    uint offset = StreamHelpers.ReadValueU32(TXTC);
                    // textBox1.Text += offset.ToString() + "...";

                    // Seek to this offset + 8 and read the number there.
                    TXTC.Seek(offset + 8, SeekOrigin.Begin);

                    uint numTGIs = StreamHelpers.ReadValueU8(TXTC);
                    // textBox1.Text += numTGIs.ToString() + " TGIs... ";

                    // Since each TGI is 16 bytes we can calculate how many bytes they are.
                    uint tgiSize = numTGIs * 16;
                    uint tgiOffsetEnd = offset + 8 + 1 + tgiSize;

                    //textBox1.Text += "TGI block end is at " + tgiOffsetEnd.ToString() + "...";

                    if (tgiOffsetEnd == TXTC.Length)
                    {
                        return false;
                    }
                    else
                    {
                        // Try offset - 1
                        offset = offset - 1;

                        // Seek to this offset + 8 and read the number there.
                        TXTC.Seek(offset + 8, SeekOrigin.Begin);

                        numTGIs = StreamHelpers.ReadValueU8(TXTC);
                        // textBox1.Text += numTGIs.ToString() + " TGIs... ";

                        // Since each TGI is 16 bytes we can calculate how many bytes they are.
                        tgiSize = numTGIs * 16;
                        tgiOffsetEnd = offset + 8 + 1 + tgiSize;

                        //textBox1.Text += "TGI block end is at " + tgiOffsetEnd.ToString() + "...";

                        if (tgiOffsetEnd == TXTC.Length)
                        {
                            //   textBox1.Text += "Correct!";
                            // Offset it minus 1

                            TXTC.Seek(4, SeekOrigin.Begin);
                            StreamHelpers.WriteValueU32(TXTC, offset);

                            MemoryStream newTXTC = new MemoryStream();
                            StreamHelpers.CopyStream(TXTC, newTXTC, true);

                            db.SetResourceStream(entry.Key, newTXTC);

                            //    textBox1.Text += Environment.NewLine;
                            //     textBox1.Text += "The above resource has been fixed.";

                            numFixed++;

                            newTXTC.Close();
                        }
                        else
                        {
                            //   textBox1.Text += "Incorrect!";
                        }
                    }

                    // textBox1.Text += Environment.NewLine;

                    TXTC = null;
                }
            }

            if (numFixed == 0)
            {
                //textBox1.Text += Environment.NewLine;
                //textBox1.Text += "This file appears OK!";
                return false;
            }
            else
            {
                //this.filesFixed++;
                //textBox1.Text += Environment.NewLine;
                //textBox1.Text += "This file had some corrupted TXTCs! They are now fixed.";
                //textBox1.Text += "Fixed " + filename + Environment.NewLine;
                //saveToolStripMenuItem.Enabled = true;
                db.Commit(true);
            }

            return true;
        }
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //saveFileDialog1.FileName = "";
            //saveFileDialog1.Filter = "Sims 3 Packages|*.package|CASPart|*.caspart";
            if (Helpers.currentPackageFile != "")
            {

                FileInfo f = new FileInfo(Helpers.currentPackageFile);

                if (f.Extension == ".package")
                {

                    Stream saveFile = File.OpenRead(Helpers.currentPackageFile);
                    MemoryStream tempSave = new MemoryStream();
                    StreamHelpers.CopyStream(saveFile, tempSave, true);
                    saveFile.Close();

                    tempSave.Seek(0, SeekOrigin.Begin);

                    ulong instanceId = MadScience.StringHelpers.HashFNV64("CTU_" + DateTime.Now.Ticks + "_" + MadScience.Helpers.sanitiseString(f.Name));
                    //ulong instanceId = MadScience.StringHelpers.HashFNV64(casPartNew.meshName);
                    Database db = new Database(tempSave, true);

                    saveToDBPF(db, instanceId, false);

                    db.Commit(true);

                    saveFile = File.Open(Helpers.currentPackageFile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                    StreamHelpers.CopyStream(tempSave, saveFile, true);
                    saveFile.Close();

                    tempSave.Close();

                }
            }
        }
Example #15
0
        public static Stream findKey(MadScience.Wrappers.ResourceKey resourceKey, int fullBuildNum, Wrappers.Database db)
        {
            List <MadScience.Wrappers.ResourceKey> resourceKeys = new List <MadScience.Wrappers.ResourceKey>();

            resourceKeys.Add(resourceKey);

            return(findKey(resourceKeys, fullBuildNum, db)[0]);
        }
        private void btnDumpFromFullbuild2_Click(object sender, EventArgs e)
        {
            // Go through the list of DDS files and dump them
            string s3root = MadScience.Helpers.findSims3Root();

            if (s3root != "")
            {

                bool hasShownDialog = false;

                toolStripProgressBar1.Visible = true;
                toolStripProgressBar1.Minimum = 0;
                toolStripProgressBar1.Value = 0;
                toolStripStatusLabel1.Text = "Searching for textures... please wait";
                statusStrip1.Refresh();

                Stream fbuild2 = File.Open(Path.Combine(s3root, Helpers.getGameSubPath("\\GameData\\Shared\\Packages\\FullBuild2.package")), FileMode.Open, FileAccess.Read, FileShare.Read);
                MadScience.Wrappers.Database db = new MadScience.Wrappers.Database(fbuild2, true);

                toolStripProgressBar1.Maximum = casPartSrc.tgi64list.Count;

                Dictionary<ulong, string> keyNames = new Dictionary<ulong, string>();
                long nowTicks = DateTime.Now.Ticks;
                Console.WriteLine("Started at: " + nowTicks);
                foreach (MadScience.Wrappers.ResourceKey entry in db._Entries.Keys)
                {
                    //DatabasePackedFile.Entry entry = db.dbpfEntries[i];
                    if (entry.typeId == (int)0x0166038C)
                    {
                        keyNames = Helpers.getKeyNames(db.GetResourceStream(entry));
                        break;
                    }
                }

                int numFound = 0;
                folderBrowserDialog1.SelectedPath = "";

                for (int j = 0; j < casPartSrc.tgi64list.Count; j++)
                {
                    toolStripProgressBar1.Value++;
                    //keyName tgi = new keyName((tgi64)casPartSrc.tgi64list[j]);
                    MadScience.Wrappers.ResourceKey tgi = casPartSrc.tgi64list[j];
                    if (tgi.typeId == (int)0x736884F1) // VPXY
                    {
                        // Find the meshes, then dump any textures the meshes reference too

                        // Use the VPXY to get the mesh lod
                        Stream vpxyStream = KeyUtils.findKey(tgi, 0);

                        //int numFound = 0;
                        //folderBrowserDialog1.SelectedPath = "";

                        if (vpxyStream != null)
                        {
                            VPXYFile vpxyFile = new VPXYFile(vpxyStream);
                            // Get the first VPXY internal link
                            if (vpxyFile.vpxy.linkEntries.Count >= 1 && vpxyFile.vpxy.linkEntries[0].tgiList.Count >= 1)
                            {
                                for (int i = 0; i < vpxyFile.vpxy.linkEntries[0].tgiList.Count; i++)
                                {
                                    //meshStreams.Add(KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[i], 0));
                                    //KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[i], 0);

                                    //ResourceKey entry = vpxyFile.vpxy.linkEntries[0].tgiList[i];

                                    Stream meshFile = KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[i], 0);

                                    SimGeomFile sgf = new SimGeomFile(meshFile);

                                    if (!hasShownDialog)
                                    {
                                        folderBrowserDialog1.Description = "Please select a folder to save the extracted textures to.";
                                        folderBrowserDialog1.ShowDialog();
                                        hasShownDialog = true;
                                    }
                                    if (folderBrowserDialog1.SelectedPath != "")
                                    {
                                        string extension = "";
                                        for (int k = 0; k < sgf.simgeom.keytable.keys.Count; k++)
                                        {
                                            ResourceKey entry = sgf.simgeom.keytable.keys[k];

                                            if (entry.typeId == 0x00B2D882)
                                            {
                                                extension = ".dds";

                                                string fileNameToSave = "";
                                                if (keyNames.ContainsKey(entry.instanceId))
                                                {
                                                    fileNameToSave = keyNames[entry.instanceId];
                                                    if (fileNameToSave.Contains("0x") == false) { fileNameToSave += "_0x" + entry.instanceId.ToString("X16"); }
                                                }
                                                else
                                                {
                                                    fileNameToSave = entry.typeId.ToString("X8") + "_" + entry.groupId.ToString("X8") + "_" + entry.instanceId.ToString("X16");
                                                }

                                                FileStream saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                                                StreamHelpers.CopyStream(KeyUtils.findKey(entry, 2, db), saveFile);
                                                saveFile.Close();
                                            }
                                        }
                                        //numFound++;
                                    }
                                    meshFile.Close();

                                    //output.Close();
                                }

                            }

                        }
                    }
                    if (tgi.typeId == (int)0x00B2D882) // DDS
                    {
                        //Stream textureStream = KeyUtils.searchForKey(tgi.ToString(), 2);
                        Stream textureStream = KeyUtils.findKey(tgi);
                        if (textureStream != null)
                        {
                            string fileNameToSave = "";
                            if (keyNames.ContainsKey(tgi.instanceId))
                            {
                                fileNameToSave = keyNames[tgi.instanceId];
                            }
                            else
                            {
                                fileNameToSave = tgi.typeId.ToString("X8") + "_" + tgi.groupId.ToString("X8") + "_" + tgi.instanceId.ToString("X16");
                            }

                            if (!hasShownDialog)
                            {
                                folderBrowserDialog1.Description = "Please select a folder to save the extracted textures to.";
                                folderBrowserDialog1.ShowDialog();
                                hasShownDialog = true;
                            }
                            if (folderBrowserDialog1.SelectedPath != "")
                            {

                                Stream output = db.GetResourceStream(tgi);
                                FileStream saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + ".dds"), FileMode.Create, FileAccess.Write);
                                StreamHelpers.CopyStream(output, saveFile);
                                saveFile.Close();
                                output.Close();
                                numFound++;
                            }

                        }
                    }
                }

                toolStripProgressBar1.Value = 0;
                toolStripStatusLabel1.Text = numFound + " textures found.";
                toolStripProgressBar1.Visible = false;
                statusStrip1.Refresh();

                fbuild2.Close();

            }
        }
        private void writeLocalResource(Database db, string keyName)
        {
            if (String.IsNullOrEmpty(keyName)) return;
            //if (!validateKey(keyName)) return;

            if (Helpers.localFiles.ContainsKey(keyName))
            {
                ResourceKey key = new ResourceKey(keyName);
                Stream newDDS = File.Open((string)Helpers.localFiles[keyName], FileMode.Open, FileAccess.Read, FileShare.Read);
                db.SetResourceStream(key, newDDS);
                newDDS.Close();
            }
        }
        public PackageType getType(Database db, bool loopAll)
        {
            // Do some quick sanity checks
            switch (db.dbpf.packageType)
            {
                case PackageTypes.genericPackage:
                    break;
                case PackageTypes.corruptBadDownload:
                case PackageTypes.corruptChaavik:
                case PackageTypes.corruptIndex:
                case PackageTypes.corruptPeggy:
                case PackageTypes.corruptNotADBPF:
                case PackageTypes.corruptTXTC:
                    this.isCorrupt = true;
                    this.pType.SubType = "";
                    this.pType.MainType = db.dbpf.packageType;
                    return this.pType;
                case PackageTypes.sims3Store:
                case PackageTypes.sims2Package:
                case PackageTypes.pngThumbnail:
                    this.pType.SubType = "";
                    this.pType.MainType = db.dbpf.packageType;
                    return this.pType;
            }

            rc.Clear();
            this.pType = new PackageType();

            //print(db.dbpf.Entries.Count + " entries found");
            for (int i = 0; i < db.dbpf.Entries.Count; i++)
            {
                DatabasePackedFile.Entry entry = db.dbpf.Entries[i];

                if ((entry.Key.typeId == (uint)ResourceTypes.NULL) && (entry.Key.groupId == (uint)ResourceTypes.NULL) && (entry.Key.instanceId == (uint)ResourceTypes.NULL))
                {
                    // Check the first 4 bytes of the stream
                    Stream checkDbpf = db.GetResourceStream(entry.Key);
                    string magic = MadScience.StreamHelpers.ReadStringASCII(checkDbpf, 4);
                    if (magic == "DBPF" || magic == "DBBF") // DBPF & DBBF
                    {
                        this.isCorrupt = true;
                        this.pType.MainType = PackageTypes.corruptRecursive;
                        this.pType.SubType = "This package contains another package inside it.";
                        if (!loopAll) return this.pType;
                    }
                    checkDbpf.Close();
                }

                if (entry.Key.typeId == (uint)ResourceTypes.TXTC)
                {
                    int isValid = checkValidEntry(entry, db);
                    if (isValid > 0)
                    {
                        if (isValid == 2)
                        {
                            this.isCorrupt = true;
                            this.pType.MainType = PackageTypes.corruptTXTC;
                            if (!loopAll) return this.pType;
                        }
                    }
                }

                if (entry.Key.typeId == (uint)ResourceTypes.PTRN)
                {
                    if (this.pType.MainType == PackageTypes.genericPackage) this.pType.MainType = PackageTypes.patternGeneric;
                    if (!loopAll) return this.pType;
                }

                if (Enum.IsDefined(typeof(ResourceTypes), entry.Key.typeId))
                {
                    if (rc.ContainsKey(Enum.GetName(typeof(ResourceTypes), entry.Key.typeId)))
                    {
                        rc[Enum.GetName(typeof(ResourceTypes), entry.Key.typeId)]++;
                    }
                    else
                    {
                        rc.Add(Enum.GetName(typeof(ResourceTypes), entry.Key.typeId), 1);
                    }
                }

            }

            //print("Done");

            if (rc.ContainsKey("WLOT") && rc.ContainsKey("UNKW1"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage) this.pType.MainType = PackageTypes.neighbourhood;
                this.isCorrupt = true;
                return this.pType;
            }

            if (rc.ContainsKey("WLTL") && rc.ContainsKey("ARY2"))
            {
                this.pType.MainType = PackageTypes.lot;
                return this.pType;
            }

            if (rc.ContainsKey("SIMO") && rc.ContainsKey("SIME") && rc.ContainsKey("SNAP") && rc.ContainsKey("SNAPL"))
            {
                this.pType.MainType = PackageTypes.sim;
                return this.pType;
            }

            //this.pType.MainType = PackageTypes.genericPackage;
            // Check Objects
            if (rc.ContainsKey("OBJD"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage) this.pType.MainType = PackageTypes.objectGeneric;
                Stream objStream = MadScience.Package.Search.getStream(db, 0x319E4F1D, -1, -1);
                if (StreamHelpers.isValidStream(objStream))
                {
                    OBJD objd = new OBJD(objStream);
                    this.pType.SubType = objd.ToString();
                    objd = null;

                }
                return this.pType;
            }
            if (rc.ContainsKey("S3SA"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage)	this.pType.MainType = PackageTypes.coremod;
            }

            if (rc.ContainsKey("CASP"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage) this.pType.MainType = PackageTypes.casPartGeneric;

                Stream casStream = MadScience.Package.Search.getStream(db, 0x034AEECB, -1, -1);
                if (StreamHelpers.isValidStream(casStream))
                {
                    casPartFile cFile = new casPartFile();
                    cFile.Load(casStream);

                    this.pType.SubType = cFile.clothingType();

                    switch (cFile.casType())
                    {
                        case "Hair":
                            this.pType.MainType = PackageTypes.casPartHair;
                            break;
                        case "Scalp":
                            break;
                        case "Face Overlay":
                            switch (cFile.clothingType())
                            {
                                case "Lipstick":
                                case "Eyeshadow":
                                case "Eyeliner":
                                case "Blush":
                                case "Makeup":
                                case "Mascara":
                                    this.pType.MainType = PackageTypes.casPartMakeup;
                                    break;
                                default:
                                    this.pType.MainType = PackageTypes.casPartFaceOverlay;
                                    break;
                            }
                            break;
                        case "Body":
                            this.pType.MainType = PackageTypes.casPartClothing;
                            this.pType.SubType = cFile.clothingCategory();

                            // Check the TYPE of clothing we have
                            switch (cFile.clothingType())
                            {
                                case "Body":
                                case "Top":
                                case "Bottom":
                                case "Shoes":
                                    // Check the age too
                                    // If we have Toddler OR Child OR Teen, plus other ages
                                    bool ageCorrupt = false;
                                    //if ((cFile.cFile.ageGender.baby || cFile.cFile.ageGender.toddler || cFile.cFile.ageGender.child || cFile.cFile.ageGender.teen) && (cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                                    //{
                                    //	ageCorrupt = true;
                                    //}
                                    // If we have Baby AND any other age...
                                    if (cFile.cFile.ageGender.baby && (cFile.cFile.ageGender.toddler || cFile.cFile.ageGender.child || cFile.cFile.ageGender.teen || cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                                    {
                                        ageCorrupt = true;
                                    }
                                    // If we have Toddler AND any other age...
                                    if (cFile.cFile.ageGender.toddler && (cFile.cFile.ageGender.child || cFile.cFile.ageGender.teen || cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                                    {
                                        ageCorrupt = true;
                                    }
                                    // If we have Child AND any other age
                                    if (cFile.cFile.ageGender.child && (cFile.cFile.ageGender.teen || cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                                    {
                                        ageCorrupt = true;
                                    }
                                    // If we have Teen AND any other age
                                    if (cFile.cFile.ageGender.teen && (cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                                    {
                                        ageCorrupt = true;
                                    }

                                    if (ageCorrupt)
                                    {
                                        this.isCorrupt = true;
                                        this.pType.MainType = PackageTypes.corruptBadAges;
                                        if (!loopAll) return this.pType;
                                    }
                                    break;
                                default:
                                    break;
                            }

                            break;
                        case "Accessory":
                            this.pType.MainType = PackageTypes.casPartAccessory;
                            break;
                    }
                    this.pType.SubType += " (" + cFile.ageGender() + ")";

                }
                return this.pType;
            }

            if (rc.ContainsKey("FBLN") && rc.ContainsKey("FACE") && rc.ContainsKey("BOND"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage) this.pType.MainType = PackageTypes.casSlider;
                return this.pType;
            }

            if (rc.ContainsKey("_IMG") && rc.Count == 1)
            {
                if (this.pType.MainType == PackageTypes.genericPackage) this.pType.MainType = PackageTypes.textureReplacement;
            }

            if (rc.Count == 1 && (rc.ContainsKey("_XML") || rc.ContainsKey("_XML2")))
            {
                if (this.pType.MainType == PackageTypes.genericPackage) this.pType.MainType = PackageTypes.xmltuningmod;
            }

            return this.pType;
        }
        private void saveToDBPF(Database db, ulong instanceId, bool newInstance)
        {
            ResourceKey rkey;

            MemoryStream mem = new MemoryStream();
            casPartFile casPF = new casPartFile();

            // Do we have new meshes?  If so, we need to do some pretty heft modifications. :)

            string meshName = txtMeshName.Text;

            NameMap namemap = new NameMap();
            ResourceKey namemapKey = new ResourceKey(0x0166038C, 0x00000000, instanceId);

            if (!String.IsNullOrEmpty(txtMeshLod1.Text) || !String.IsNullOrEmpty(txtMeshLod0.Text))
            {
                keyName bodyBlendFat = new keyName(0x062C8204, 0x0, meshName + "_fat");
                keyName bodyBlendFit = new keyName(0x062C8204, 0x0, meshName + "_fit");
                keyName bodyBlendThin = new keyName(0x062C8204, 0x0, meshName + "_thin");
                keyName bodyBlendSpecial = new keyName(0x062C8204, 0x0, meshName + "_special");

                namemap.entries.Add(bodyBlendFat.instanceId, bodyBlendFat.name);
                namemap.entries.Add(bodyBlendFit.instanceId, bodyBlendFit.name);
                namemap.entries.Add(bodyBlendThin.instanceId, bodyBlendThin.name);
                namemap.entries.Add(bodyBlendSpecial.instanceId, bodyBlendSpecial.name);

                Stream bodyBlendFatStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoFat].ToString(), 0);
                Stream bodyBlendFitStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoFit].ToString(), 0);
                Stream bodyBlendThinStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoThin].ToString(), 0);
                Stream bodyBlendSpecialStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoSpecial].ToString(), 0);

                // Load in the blend information
                FacialBlend bodyBlendFatFile = new FacialBlend(bodyBlendFatStream);
                bodyBlendFatFile.partName = meshName + "_fat";
                FacialBlend bodyBlendFitFile = new FacialBlend(bodyBlendFitStream);
                bodyBlendFitFile.partName = meshName + "_fit";
                FacialBlend bodyBlendThinFile = new FacialBlend(bodyBlendThinStream);
                bodyBlendThinFile.partName = meshName + "_thin";
                FacialBlend bodyBlendSpecialFile = new FacialBlend(bodyBlendSpecialStream);
                bodyBlendSpecialFile.partName = meshName + "_special";

                if (debugModeToolStripMenuItem.Checked)
                {
                    Stream bgeoStream = KeyUtils.findKey(bodyBlendFatFile.blendTgi, 0);
                    bgeoStream.Seek(0, SeekOrigin.Begin);
                    bodyBlendFatFile.blendTgi = new keyName(0x067CAA11, 0x0, meshName + "_fat").ToResourceKey();
                    db.SetResourceStream(bodyBlendFatFile.blendTgi, bgeoStream);

                    bgeoStream = KeyUtils.findKey(bodyBlendFitFile.blendTgi, 0);
                    bgeoStream.Seek(0, SeekOrigin.Begin);
                    bodyBlendFitFile.blendTgi = new keyName(0x067CAA11, 0x0, meshName + "_fit").ToResourceKey();
                    db.SetResourceStream(bodyBlendFitFile.blendTgi, bgeoStream);

                    bgeoStream = KeyUtils.findKey(bodyBlendThinFile.blendTgi, 0);
                    bgeoStream.Seek(0, SeekOrigin.Begin);
                    bodyBlendThinFile.blendTgi = new keyName(0x067CAA11, 0x0, meshName + "_thin").ToResourceKey();
                    db.SetResourceStream(bodyBlendThinFile.blendTgi, bgeoStream);

                    bgeoStream = KeyUtils.findKey(bodyBlendSpecialFile.blendTgi, 0);
                    bgeoStream.Seek(0, SeekOrigin.Begin);
                    bodyBlendSpecialFile.blendTgi = new keyName(0x067CAA11, 0x0, meshName + "_special").ToResourceKey();
                    db.SetResourceStream(bodyBlendSpecialFile.blendTgi, bgeoStream);

                }

                db.SetResourceStream(bodyBlendFit.ToResourceKey(), bodyBlendFitFile.Save());
                db.SetResourceStream(bodyBlendFat.ToResourceKey(), bodyBlendFatFile.Save());
                db.SetResourceStream(bodyBlendThin.ToResourceKey(), bodyBlendThinFile.Save());
                db.SetResourceStream(bodyBlendSpecial.ToResourceKey(), bodyBlendSpecialFile.Save());

                // Update the CAS part TGI links with the new VPXY
                casPartNew.tgi64list[casPartNew.tgiIndexBlendInfoFat] = bodyBlendFat.ToResourceKey();
                casPartNew.tgi64list[casPartNew.tgiIndexBlendInfoFit] = bodyBlendFit.ToResourceKey();
                casPartNew.tgi64list[casPartNew.tgiIndexBlendInfoThin] = bodyBlendThin.ToResourceKey();
                casPartNew.tgi64list[casPartNew.tgiIndexBlendInfoSpecial] = bodyBlendSpecial.ToResourceKey();

                keyName proxyFitKey = new keyName(0x736884F1, 0x00000001, meshName + "_fit");
                keyName proxyFatKey = new keyName(0x736884F1, 0x00000001, meshName + "_fat");
                keyName proxyThinKey = new keyName(0x736884F1, 0x00000001, meshName + "_thin");
                keyName proxySpecialKey = new keyName(0x736884F1, 0x00000001, meshName + "_special");

                Stream proxyFatStream = KeyUtils.findKey(new ResourceKey(0x736884F1, 0x00000001, casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoFat].instanceId), 0);
                Stream proxyFitStream = KeyUtils.findKey(new ResourceKey(0x736884F1, 0x00000001, casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoFit].instanceId), 0);
                Stream proxyThinStream = KeyUtils.findKey(new ResourceKey(0x736884F1, 0x00000001, casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoThin].instanceId), 0);
                Stream proxySpecialStream = KeyUtils.findKey(new ResourceKey(0x736884F1, 0x00000001, casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoSpecial].instanceId), 0);

                VPXYFile proxyFat = new VPXYFile(proxyFatStream);
                proxyFat.rcolHeader.internalChunks.Clear();
                proxyFat.rcolHeader.internalChunks.Add(proxyFatKey.ToResourceKey());
                VPXYFile proxyFit = new VPXYFile(proxyFitStream);
                proxyFit.rcolHeader.internalChunks.Clear();
                proxyFit.rcolHeader.internalChunks.Add(proxyFitKey.ToResourceKey());
                VPXYFile proxyThin = new VPXYFile(proxyThinStream);
                proxyThin.rcolHeader.internalChunks.Clear();
                proxyThin.rcolHeader.internalChunks.Add(proxyThinKey.ToResourceKey());
                VPXYFile proxySpecial = new VPXYFile(proxySpecialStream);
                proxySpecial.rcolHeader.internalChunks.Clear();
                proxySpecial.rcolHeader.internalChunks.Add(proxySpecialKey.ToResourceKey());

                db.SetResourceStream(proxyFatKey.ToResourceKey(), proxyFat.Save());
                db.SetResourceStream(proxyFitKey.ToResourceKey(), proxyFit.Save());
                db.SetResourceStream(proxyThinKey.ToResourceKey(), proxyThin.Save());
                db.SetResourceStream(proxySpecialKey.ToResourceKey(), proxySpecial.Save());

                uint customGroup = MadScience.StringHelpers.HashFNV24(meshName);
                keyName meshLod0 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod0"), meshName + "_lod0");
                keyName meshLod0_1 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod0_1"), meshName + "_lod0_1");
                keyName meshLod0_2 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod0_2"), meshName + "_lod0_2");
                keyName meshLod0_3 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod0_3"), meshName + "_lod0_3");

                keyName meshLod1 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod1"), meshName + "_lod1");
                keyName meshLod1_1 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod1_1"), meshName + "_lod1_1");
                keyName meshLod1_2 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod1_2"), meshName + "_lod1_2");
                keyName meshLod1_3 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod1_3"), meshName + "_lod1_3");
                keyName meshLod2 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod2"), meshName + "_lod2");
                keyName meshLod2_1 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod2_1"), meshName + "_lod2_1");
                keyName meshLod2_2 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod2_2"), meshName + "_lod2_2");

                keyName meshLod3 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod3"), meshName + "_lod3");
                keyName meshLod3_1 = new keyName(0x015A1849, customGroup, (ulong)MadScience.StringHelpers.HashFNV32(meshName + "_lod3_1"), meshName + "_lod3_1");

                keyName vpxyKey = new keyName(0x736884F1, 0x00000001, (ulong)customGroup);

                // Load in the VPXY - we need to modify it.
                //keyName oldVpxyKey = new keyName((tgi64)casPartSrc.tgi64list[casPartSrc.tgiIndexVPXY]);
                Stream vpxyStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexVPXY].ToString(), 0);
                if (StreamHelpers.isValidStream(vpxyStream))
                {

                    namemap.entries.Add(meshLod0.instanceId, meshName + "_lod0");
                    namemap.entries.Add(meshLod0_1.instanceId, meshName + "_lod0_1");
                    namemap.entries.Add(meshLod0_2.instanceId, meshName + "_lod0_2");
                    namemap.entries.Add(meshLod0_3.instanceId, meshName + "_lod0_3");
                    namemap.entries.Add(meshLod1.instanceId, meshName + "_lod1");
                    namemap.entries.Add(meshLod1_1.instanceId, meshName + "_lod1_1");
                    namemap.entries.Add(meshLod1_2.instanceId, meshName + "_lod1_2");
                    namemap.entries.Add(meshLod1_3.instanceId, meshName + "_lod1_3");
                    namemap.entries.Add(meshLod2.instanceId, meshName + "_lod2");
                    namemap.entries.Add(meshLod2_1.instanceId, meshName + "_lod2_1");
                    namemap.entries.Add(meshLod2_2.instanceId, meshName + "_lod2_2");
                    namemap.entries.Add(meshLod3.instanceId, meshName + "_lod3");
                    namemap.entries.Add(meshLod3_1.instanceId, meshName + "_lod3_1");
                    namemap.entries.Add(vpxyKey.instanceId, meshName);

                    //keyName proxyFit = new keyName(0x736884F1, 0x00000001, meshName + "_fit");
                    //keyName proxyFat = new keyName(0x736884F1, 0x00000001, meshName + "_fat");
                    //keyName proxyThin = new keyName(0x736884F1, 0x00000001, meshName + "_thin");
                    //keyName proxySpecial = new keyName(0x736884F1, 0x00000001, meshName + "_special");

                    VPXYFile vpxyfile = new VPXYFile(vpxyStream);
                    vpxyfile.rcolHeader.internalChunks.Clear();
                    vpxyfile.rcolHeader.internalChunks.Add(vpxyKey.ToResourceKey());

                    vpxyfile.vpxy.linkEntries.Clear();
                    if (!String.IsNullOrEmpty(txtMeshLod0.Text))
                    {
                        // LOD 0
                        VPXYEntry vpxyE = new VPXYEntry();
                        if (!String.IsNullOrEmpty(txtMeshLod0_1.Text)) vpxyE.tgiList.Add(meshLod0_1.ToResourceKey());
                        if (!String.IsNullOrEmpty(txtMeshLod0_2.Text)) vpxyE.tgiList.Add(meshLod0_2.ToResourceKey());
                        if (!String.IsNullOrEmpty(txtMeshLod0_3.Text)) vpxyE.tgiList.Add(meshLod0_3.ToResourceKey());
                        vpxyE.tgiList.Add(meshLod0.ToResourceKey());
                        vpxyfile.vpxy.linkEntries.Add(vpxyE);
                    }
                    if (!String.IsNullOrEmpty(txtMeshLod1.Text))
                    {
                        // LOD 1
                        VPXYEntry vpxyE = new VPXYEntry();
                        if (!String.IsNullOrEmpty(txtMeshLod1_1.Text)) vpxyE.tgiList.Add(meshLod1_1.ToResourceKey());
                        if (!String.IsNullOrEmpty(txtMeshLod1_2.Text)) vpxyE.tgiList.Add(meshLod1_2.ToResourceKey());
                        if (!String.IsNullOrEmpty(txtMeshLod1_3.Text)) vpxyE.tgiList.Add(meshLod1_3.ToResourceKey());
                        vpxyE.tgiList.Add(meshLod1.ToResourceKey());
                        vpxyfile.vpxy.linkEntries.Add(vpxyE);
                    }
                    if (!String.IsNullOrEmpty(txtMeshLod2.Text))
                    {
                        // LOD 2
                        VPXYEntry vpxyE = new VPXYEntry();
                        if (!String.IsNullOrEmpty(txtMeshLod2_1.Text)) vpxyE.tgiList.Add(meshLod2_1.ToResourceKey());
                        if (!String.IsNullOrEmpty(txtMeshLod2_2.Text)) vpxyE.tgiList.Add(meshLod2_2.ToResourceKey());
                        vpxyE.tgiList.Add(meshLod2.ToResourceKey());
                        vpxyfile.vpxy.linkEntries.Add(vpxyE);
                    }
                    if (!String.IsNullOrEmpty(txtMeshLod3.Text))
                    {
                        // LOD 2
                        VPXYEntry vpxyE = new VPXYEntry();
                        if (!String.IsNullOrEmpty(txtMeshLod3_1.Text)) vpxyE.tgiList.Add(meshLod3_1.ToResourceKey());
                        vpxyE.tgiList.Add(meshLod3.ToResourceKey());
                        vpxyfile.vpxy.linkEntries.Add(vpxyE);
                    }

                    vpxyfile.vpxy.keytable.keys.Clear();

                    // If a Hair or an Accessory then set the vpxy start to 0 else starts at 1
                    if (checkedListType.GetItemChecked(0) == true || checkedListType.GetItemChecked(4) == true)
                    {
                        vpxyfile.vpxy.numTypeZero = 0;
                    }
                    else
                    {
                        vpxyfile.vpxy.numTypeZero = 1;
                    }
                    vpxyStream = vpxyfile.Save();

                    //vpxyfile.rcolHeader.internalChunks[0] = proxyFit.ToResourceKey();
                    //Stream proxyFitFile = vpxyfile.Save();

                    //vpxyfile.rcolHeader.internalChunks[0] = proxyFat.ToResourceKey();
                    //Stream proxyFatFile = vpxyfile.Save();

                    //vpxyfile.rcolHeader.internalChunks[0] = proxyThin.ToResourceKey();
                    //Stream proxyThinFile = vpxyfile.Save();

                    //vpxyfile.rcolHeader.internalChunks[0] = proxySpecial.ToResourceKey();
                    //Stream proxySpecialFile = vpxyfile.Save();

                    db.SetResourceStream(vpxyKey.ToResourceKey(), vpxyStream);
                    //db.SetResourceStream(proxyFit.ToResourceKey(), proxyFitFile);
                    //db.SetResourceStream(proxyFat.ToResourceKey(), proxyFatFile);
                    //db.SetResourceStream(proxyThin.ToResourceKey(), proxyThinFile);
                    //db.SetResourceStream(proxySpecial.ToResourceKey(), proxySpecialFile);

                    // Update the CAS part TGI links with the new VPXY
                    casPartNew.tgi64list[casPartNew.tgiIndexVPXY] = vpxyKey.ToResourceKey();

                    keyName bumpMapKey = new keyName();

                    if (String.IsNullOrEmpty(txtOtherBumpMap.Text) == false)
                    {
                        bumpMapKey = new keyName(txtOtherBumpMap.Text, meshName + "_n");
                        //kNames.Add(bumpMapKey);
                        Stream bumpMapStream = File.OpenRead(txtOtherBumpMap.Text);
                        if (txtOtherBumpMap.Text != "" && !txtOtherBumpMap.Text.StartsWith("key:")) db.SetResourceStream(bumpMapKey.ToResourceKey(), bumpMapStream);
                        bumpMapStream.Close();
                    }

                    #region Import Mesh LODs
                    if (!String.IsNullOrEmpty(txtMeshLod0.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod0.ToResourceKey(), saveGeom(txtMeshLod0.Text, bumpMapKey.ToResourceKey()));
                    }
                    if (!String.IsNullOrEmpty(txtMeshLod0_1.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod0_1.ToResourceKey(), saveGeom(txtMeshLod0_1.Text, bumpMapKey.ToResourceKey()));
                    }
                    if (!String.IsNullOrEmpty(txtMeshLod0_2.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod0_2.ToResourceKey(), saveGeom(txtMeshLod0_2.Text, bumpMapKey.ToResourceKey()));
                    }
                    if (!String.IsNullOrEmpty(txtMeshLod0_3.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod0_3.ToResourceKey(), saveGeom(txtMeshLod0_3.Text, bumpMapKey.ToResourceKey()));
                    }

                    if (!String.IsNullOrEmpty(txtMeshLod1.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod1.ToResourceKey(), saveGeom(txtMeshLod1.Text, bumpMapKey.ToResourceKey()));
                    }

                    if (!String.IsNullOrEmpty(txtMeshLod1_1.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod1_1.ToResourceKey(), saveGeom(txtMeshLod1_1.Text, bumpMapKey.ToResourceKey()));
                    }

                    if (!String.IsNullOrEmpty(txtMeshLod1_2.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod1_2.ToResourceKey(), saveGeom(txtMeshLod1_2.Text, bumpMapKey.ToResourceKey()));
                    }

                    if (!String.IsNullOrEmpty(txtMeshLod1_3.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod1_3.ToResourceKey(), saveGeom(txtMeshLod1_3.Text, bumpMapKey.ToResourceKey()));
                    }

                    if (!String.IsNullOrEmpty(txtMeshLod2.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod2.ToResourceKey(), saveGeom(txtMeshLod2.Text, bumpMapKey.ToResourceKey()));
                    }
                    if (!String.IsNullOrEmpty(txtMeshLod2_1.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod2_1.ToResourceKey(), saveGeom(txtMeshLod2_1.Text, bumpMapKey.ToResourceKey()));
                    }

                    if (!String.IsNullOrEmpty(txtMeshLod2_2.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod2_2.ToResourceKey(), saveGeom(txtMeshLod2_2.Text, bumpMapKey.ToResourceKey()));
                    }

                    if (!String.IsNullOrEmpty(txtMeshLod3.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod3.ToResourceKey(), saveGeom(txtMeshLod3.Text, bumpMapKey.ToResourceKey()));
                    }
                    if (!String.IsNullOrEmpty(txtMeshLod3_1.Text.Trim()))
                    {
                        db.SetResourceStream(meshLod3_1.ToResourceKey(), saveGeom(txtMeshLod3_1.Text, bumpMapKey.ToResourceKey()));
                    }

                    #endregion
                }

            }

            db.SetResourceStream(namemapKey, namemap.Save());

            if (casPartNew != null)
            {
                casPF.Save(mem, casPartNew);
            }
            else
            {
                casPF.Save(mem, casPartSrc);
            }
            casPF = null;

            if (this.loadedCasPart.ToString() == "00000000:00000000:0000000000000000")
            {
                rkey = new ResourceKey((uint)0x034AEECB, (uint)0, instanceId, (uint)ResourceKeyOrder.ITG);
            }
            else
            {
                if (!newInstance)
                {
                    rkey = this.loadedCasPart;
                }
                else
                {
                    rkey = new ResourceKey((uint)0x034AEECB, (uint)0, instanceId, (uint)ResourceKeyOrder.ITG);
                }
            }
            db.SetResourceStream(rkey, mem);

            if (casPartNew != null)
            {
                // Go through a list of all the keys and see if they are "local"
                for (int i = 0; i < casPartNew.xmlChunk.Count; i++)
                {
                    xmlChunkDetails chunk = (xmlChunkDetails)casPartNew.xmlChunk[i];

                    for (int j = 0; j < 10; j++)
                    {
                        writeLocalResource(db, stencilPool[j].key);
                    }
                    writeLocalResource(db, chunk.Multiplier);
                    writeLocalResource(db, chunk.Overlay);
                    writeLocalResource(db, chunk.hair.RootColor);
                    writeLocalResource(db, chunk.hair.DiffuseColor);
                    writeLocalResource(db, chunk.hair.HighlightColor);
                    writeLocalResource(db, chunk.hair.TipColor);
                    writeLocalResource(db, chunk.hair.ScalpDiffuseMap);
                    writeLocalResource(db, chunk.hair.ScalpControlMap);
                    writeLocalResource(db, chunk.hair.ScalpSpecularMap);
                    writeLocalResource(db, chunk.hair.ScalpAO);
                    writeLocalResource(db, chunk.hair.FaceDiffuseMap);
                    writeLocalResource(db, chunk.hair.FaceControlMap);
                    writeLocalResource(db, chunk.hair.FaceSpecularMap);
                    writeLocalResource(db, chunk.hair.FaceAO);
                    writeLocalResource(db, chunk.Mask);
                    writeLocalResource(db, chunk.SkinSpecular);
                    writeLocalResource(db, chunk.SkinAmbient);
                    writeLocalResource(db, chunk.ClothingSpecular);
                    writeLocalResource(db, chunk.ClothingAmbient);
                    writeLocalResource(db, chunk.PartMask);
                    writeLocalResource(db, chunk.pattern[0].BackgroundImage);
                    writeLocalResource(db, chunk.pattern[1].BackgroundImage);
                    writeLocalResource(db, chunk.pattern[2].BackgroundImage);
                    writeLocalResource(db, chunk.pattern[3].BackgroundImage);
                    writeLocalResource(db, chunk.pattern[0].rgbmask);
                    writeLocalResource(db, chunk.pattern[1].rgbmask);
                    writeLocalResource(db, chunk.pattern[2].rgbmask);
                    writeLocalResource(db, chunk.pattern[3].rgbmask);
                    writeLocalResource(db, chunk.pattern[0].specmap);
                    writeLocalResource(db, chunk.pattern[1].specmap);
                    writeLocalResource(db, chunk.pattern[2].specmap);
                    writeLocalResource(db, chunk.pattern[3].specmap);
                    writeLocalResource(db, chunk.pattern[0].filename);
                    writeLocalResource(db, chunk.pattern[1].filename);
                    writeLocalResource(db, chunk.pattern[2].filename);
                    writeLocalResource(db, chunk.pattern[3].filename);
                    writeLocalResource(db, chunk.faceOverlay);
                    writeLocalResource(db, chunk.faceSpecular);
                    writeLocalResource(db, chunk.ControlMap);
                    writeLocalResource(db, chunk.DiffuseMap);

                    if (newPNGfiles.ContainsKey(i))
                    {
                        Stream newPNG = File.Open(newPNGfiles[i], FileMode.Open, FileAccess.Read, FileShare.Read);
                        uint thumbGroup = (uint)i;
                        if (useAlternativeToolStripMenuItem.Checked == true) thumbGroup++;

                        ResourceKey keyPNG = new ResourceKey(0x626F60CE, thumbGroup, instanceId, (uint)ResourceKeyOrder.ITG);
                        db.SetResourceStream(keyPNG, newPNG);
                        newPNG.Close();
                    }
                }
            }

            mem.Close();
        }
        private int checkValidEntry(DatabasePackedFile.Entry entry, Database db)
        {
            int validEntry = 0; // 0 = valid
            if (!checkTXTCEntry(entry, db))
            {
                validEntry = 2; // 2 = BlueLot TXTC
            }

            return validEntry;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.Description = "Please locate the directory where you want to save this package";
            folderBrowserDialog1.ShowDialog();

            //txtSliderName.Text = txtSliderName.Text;

            // Make the instance id
            ulong instanceid = MadScience.StringHelpers.HashFNV64(txtSliderName.Text);
            ulong instance32 = (ulong)MadScience.StringHelpers.HashFNV32(txtSliderName.Text);

            ulong instanceLeft = MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "Left");
            ulong instanceRight = MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "Right");

            // Keys
            ResourceKey nameMapKey = new ResourceKey(0x0166038C, 0, instanceid);
            ResourceKey stblKey = new ResourceKey(0x220557DA, 0, instance32);
            ResourceKey blendunitKey = new ResourceKey(0xB52F5055, 0, instanceid);

            ResourceKey facialblendLeft = new MadScience.Wrappers.ResourceKey(0x0358B08A, 0x0, instanceLeft);
            ResourceKey facialblendRight = new MadScience.Wrappers.ResourceKey(0x0358B08A, 0x0, instanceRight);

            ResourceKey blendGeomLeft = new ResourceKey(0x067CAA11, 0, instanceLeft);
            ResourceKey blendGeomRight = new ResourceKey(0x067CAA11, 0, instanceRight);

            ResourceKey vpxyRightMale = new ResourceKey(0x736884F1, 0x0, MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "RightMale"));
            ResourceKey vpxyLeftMale = new ResourceKey(0x736884F1, 0x0, MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "LeftMale"));
            ResourceKey boneDeltaRightMale = new ResourceKey(0x0355E0A6, 0, MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "RightMale"));
            ResourceKey boneDeltaLeftMale = new ResourceKey(0x0355E0A6, 0, MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "LeftMale"));
            ResourceKey vpxyRightFemale = new ResourceKey(0x736884F1, 0x0, MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "RightFemale"));
            ResourceKey vpxyLeftFemale = new ResourceKey(0x736884F1, 0x0, MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "LeftFemale"));
            ResourceKey boneDeltaRightFemale = new ResourceKey(0x0355E0A6, 0, MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "RightFemale"));
            ResourceKey boneDeltaLeftFemale = new ResourceKey(0x0355E0A6, 0, MadScience.StringHelpers.HashFNV64(txtSliderName.Text + "LeftFemale"));

            #region Name Map
            NameMap namemap = new NameMap();
            namemap.entries.Add(instanceid, txtSliderName.Text);
            namemap.entries.Add(instanceLeft, txtSliderName.Text + "Left");
            namemap.entries.Add(instanceRight, txtSliderName.Text + "Right");
            if (chkMFLink.Checked)
            {
                namemap.entries.Add(vpxyRightFemale.instanceId, txtSliderName.Text + "RightFemale");
                namemap.entries.Add(vpxyLeftFemale.instanceId, txtSliderName.Text + "LeftFemale");
            }
            else
            {
                if (chkMale.Checked)
                {
                    namemap.entries.Add(vpxyRightMale.instanceId, txtSliderName.Text + "RightMale");
                    namemap.entries.Add(vpxyLeftMale.instanceId, txtSliderName.Text + "LeftMale");
                }
                if (chkFemale.Checked)
                {
                    namemap.entries.Add(vpxyRightFemale.instanceId, txtSliderName.Text + "RightFemale");
                    namemap.entries.Add(vpxyLeftFemale.instanceId, txtSliderName.Text + "LeftFemale");
                }
            }
            Stream nameMapFile = namemap.Save();
            namemap = null;
            #endregion

            #region String Table
            // Start with the STBL
            STBL stbl = new STBL();
            stbl.Items.Add(new STBLEntry(instanceid, txtSliderString.Text));
            Stream stblFile = stbl.Save();
            stbl = null;
            #endregion

            #region BlendUnit
            // Now the BlendUnit (CAS Slider)
            BlendUnit blendunit = new BlendUnit();
            blendunit.localeHash = instanceid;
            blendunit.bidirectional = 1;
            blendunit.casPanelSubGroup = Convert.ToUInt32(txtSubgroup.Text);
            if (chkListCasPanelGroup.GetItemChecked(0) == true) blendunit.casPanelGroup = (uint)casPanelGroup.HeadAndEars;
            if (chkListCasPanelGroup.GetItemChecked(1) == true) blendunit.casPanelGroup = (uint)casPanelGroup.Mouth;
            if (chkListCasPanelGroup.GetItemChecked(2) == true) blendunit.casPanelGroup = (uint)casPanelGroup.Nose;
            if (chkListCasPanelGroup.GetItemChecked(3) == true) blendunit.casPanelGroup = (uint)casPanelGroup.Eyelash;
            if (chkListCasPanelGroup.GetItemChecked(4) == true) blendunit.casPanelGroup = (uint)casPanelGroup.Eyes;
            blendunit.blendLinks.Add(facialblendRight);
            blendunit.blendLinks.Add(facialblendLeft);

            Stream blendunitFile = blendunit.Save();
            blendunit = null;
            #endregion

            #region Facial Blends
            // Now the Facial Blends - need 2 of these, one per slider
            FacialBlend faceblend = new FacialBlend();
            faceblend.partName = txtSliderName.Text + "Left";
            faceblend.blendTgi = blendGeomLeft;
            faceblend.blendType = 2;
            faceblend.keytable.keys.Add(new ResourceKey());
            if (chkMFLink.Checked)
            {
                faceblend.keytable.keys.Add(vpxyLeftFemale);
                if (chkMale.Checked && chkFemale.Checked)
                {
                    faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Male, 1));
                    faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Female, 1));
                }
                else
                {
                    if (chkMale.Checked) { faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Male, 1)); }
                    if (chkFemale.Checked) { faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Female, 1)); }
                }
            }
            else
            {
                if (chkMale.Checked) { faceblend.keytable.keys.Add(vpxyLeftMale); }
                if (chkFemale.Checked) { faceblend.keytable.keys.Add(vpxyLeftFemale); }
                if (chkMale.Checked && chkFemale.Checked)
                {
                    faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Male, 1));
                    faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Female, 2));
                }
                else
                {
                    if (chkMale.Checked) { faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Male, 1)); }
                    if (chkFemale.Checked) { faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Female, 1)); }
                }
            }
            Stream faceBlendFileLeft = faceblend.Save();
            faceblend = null;

            faceblend = new FacialBlend();
            faceblend.partName = txtSliderName.Text + "Right";
            faceblend.blendTgi = blendGeomRight;
            faceblend.blendType = 2;
            faceblend.keytable.keys.Add(new ResourceKey());
            if (chkMFLink.Checked)
            {
                faceblend.keytable.keys.Add(vpxyRightFemale);
                if (chkMale.Checked && chkFemale.Checked)
                {
                    faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Male, 1));
                    faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Female, 1));
                }
                else
                {
                    if (chkMale.Checked) { faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Male, 1)); }
                    if (chkFemale.Checked) { faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Female, 1)); }
                }

            }
            else
            {
                if (chkMale.Checked) { faceblend.keytable.keys.Add(vpxyRightMale); }
                if (chkFemale.Checked) { faceblend.keytable.keys.Add(vpxyRightFemale); }
                if (chkMale.Checked && chkFemale.Checked)
                {
                    faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Male, 1));
                    faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Female, 2));
                }
                else
                {
                    if (chkMale.Checked) { faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Male, 1)); }
                    if (chkFemale.Checked) { faceblend.geomBoneEntries.Add(makeFBEntry((uint)AgeGenderFlags.Female, 1)); }
                }
            }
            Stream faceBlendFileRight = faceblend.Save();
            faceblend = null;
            #endregion

            #region Blend Geometry
            BlendGeom blendGeom = new BlendGeom();
            BlendGeomSection1 blendGeomS1 = new BlendGeomSection1();
            if (chkMale.Checked)
            {
                blendGeomS1.ageGenderFlags = (uint)AgeGenderFlags.Male + allFlags;
                blendGeomS1.regionFlags = getRegionFlag();
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeom.section1.Add(blendGeomS1);
            }
            if (chkFemale.Checked)
            {
                blendGeomS1 = new BlendGeomSection1();
                blendGeomS1.ageGenderFlags = (uint)AgeGenderFlags.Female + allFlags;
                blendGeomS1.regionFlags = getRegionFlag();
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeom.section1.Add(blendGeomS1);
            }
            Stream blendGeomFileLeft = blendGeom.Save();

            blendGeom = new BlendGeom();
            blendGeomS1 = new BlendGeomSection1();
            if (chkMale.Checked)
            {
                blendGeomS1.ageGenderFlags = (uint)AgeGenderFlags.Male + allFlags;
                blendGeomS1.regionFlags = getRegionFlag();
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeom.section1.Add(blendGeomS1);
            }
            if (chkFemale.Checked)
            {
                blendGeomS1 = new BlendGeomSection1();
                blendGeomS1.ageGenderFlags = (uint)AgeGenderFlags.Female + allFlags;
                blendGeomS1.regionFlags = getRegionFlag();
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeomS1.subentries.Add(new BlendGeomSection1SubEntry());
                blendGeom.section1.Add(blendGeomS1);
            }
            Stream blendGeomFileRight = blendGeom.Save();

            blendGeom = null;

            #endregion

            #region Proxys
            VPXYFile vpxy = new VPXYFile();
            VPXYEntry vpxyEntry = new VPXYEntry();
            Stream vpxyFileLeftMale = Stream.Null;
            Stream vpxyFileRightMale = Stream.Null;
            Stream vpxyFileLeftFemale = Stream.Null;
            Stream vpxyFileRightFemale = Stream.Null;
            if (chkMFLink.Checked)
            {
                if (chkFemale.Checked)
                {
                    // VPXY Female left
                    vpxy = new VPXYFile();
                    vpxy.rcolHeader.internalChunks.Add(vpxyLeftFemale);
                    vpxyEntry = new VPXYEntry();
                    vpxyEntry.tgiList.Add(boneDeltaLeftFemale);
                    vpxy.vpxy.linkEntries.Add(vpxyEntry);
                }
                vpxyFileLeftFemale = vpxy.Save();
                if (chkFemale.Checked)
                {
                    // VPXY Female Right
                    vpxy = new VPXYFile();
                    vpxy.rcolHeader.internalChunks.Add(vpxyRightFemale);
                    vpxyEntry = new VPXYEntry();
                    vpxyEntry.tgiList.Add(boneDeltaRightFemale);
                    vpxy.vpxy.linkEntries.Add(vpxyEntry);
                }
                vpxyFileRightFemale = vpxy.Save();

            }
            else
            {
                if (chkMale.Checked)
                {
                    //VPXY Male Left
                    vpxy.rcolHeader.internalChunks.Add(vpxyLeftMale);
                    vpxyEntry.tgiList.Add(boneDeltaLeftMale);
                    vpxy.vpxy.linkEntries.Add(vpxyEntry);
                }
                vpxyFileLeftMale = vpxy.Save();
                if (chkMale.Checked)
                {
                    //VPXY Male Right
                    vpxy = new VPXYFile();
                    vpxy.rcolHeader.internalChunks.Add(vpxyRightMale);
                    vpxyEntry = new VPXYEntry();
                    vpxyEntry.tgiList.Add(boneDeltaRightMale);
                    vpxy.vpxy.linkEntries.Add(vpxyEntry);
                }
                vpxyFileRightMale = vpxy.Save();
                if (chkFemale.Checked)
                {
                    // VPXY Female left
                    vpxy = new VPXYFile();
                    vpxy.rcolHeader.internalChunks.Add(vpxyLeftFemale);
                    vpxyEntry = new VPXYEntry();
                    vpxyEntry.tgiList.Add(boneDeltaLeftFemale);
                    vpxy.vpxy.linkEntries.Add(vpxyEntry);
                }
                vpxyFileLeftFemale = vpxy.Save();
                if (chkFemale.Checked)
                {
                    // VPXY Female Right
                    vpxy = new VPXYFile();
                    vpxy.rcolHeader.internalChunks.Add(vpxyRightFemale);
                    vpxyEntry = new VPXYEntry();
                    vpxyEntry.tgiList.Add(boneDeltaRightFemale);
                    vpxy.vpxy.linkEntries.Add(vpxyEntry);
                }
                vpxyFileRightFemale = vpxy.Save();

            }
            #endregion

            #region BoneDeltas
            BoneDeltaFile bonedeltaFile = new BoneDeltaFile();
            BoneDeltaEntry bdEntry = new BoneDeltaEntry();
            Stream bonedeltaLeftMaleFile;
            Stream bonedeltaRightMaleFile;
            Stream bonedeltaLeftFemaleFile ;
            Stream bonedeltaRightFemaleFile ;
            if (chkMFLink.Checked)
            {
                if (chkMale.Checked)
                {
                    bonedeltaFile.rcolHeader.internalChunks.Add(boneDeltaLeftFemale);
                    bdEntry.boneHash = 0x0F97B21B;
                    bdEntry.scale.x = -2f;
                    bdEntry.scale.y = -2f;
                    bdEntry.scale.z = -2f;
                    bonedeltaFile.bonedelta.entries.Add(bdEntry);
                }
                bonedeltaLeftMaleFile = bonedeltaFile.Save();
                if (chkMale.Checked)
                {
                    bonedeltaFile = new BoneDeltaFile();
                    bonedeltaFile.rcolHeader.internalChunks.Add(boneDeltaRightFemale);
                    bdEntry = new BoneDeltaEntry();
                    bdEntry.boneHash = 0x0F97B21B;
                    bdEntry.scale.x = 2f;
                    bdEntry.scale.y = 2f;
                    bdEntry.scale.z = 2f;
                    bonedeltaFile.bonedelta.entries.Add(bdEntry);
                }
                bonedeltaRightMaleFile = bonedeltaFile.Save();

                if (chkFemale.Checked)
                {
                    bonedeltaFile = new BoneDeltaFile();
                    bonedeltaFile.rcolHeader.internalChunks.Add(boneDeltaLeftFemale);
                    bdEntry = new BoneDeltaEntry();
                    bdEntry.boneHash = 0x0F97B21B;
                    bdEntry.scale.x = -2f;
                    bdEntry.scale.y = -2f;
                    bdEntry.scale.z = -2f;
                    bonedeltaFile.bonedelta.entries.Add(bdEntry);
                }
                bonedeltaLeftFemaleFile = bonedeltaFile.Save();

                if (chkFemale.Checked)
                {
                    bonedeltaFile = new BoneDeltaFile();
                    bonedeltaFile.rcolHeader.internalChunks.Add(boneDeltaRightFemale);
                    bdEntry = new BoneDeltaEntry();
                    bdEntry.boneHash = 0x0F97B21B;
                    bdEntry.scale.x = 2f;
                    bdEntry.scale.y = 2f;
                    bdEntry.scale.z = 2f;
                    bonedeltaFile.bonedelta.entries.Add(bdEntry);
                }
                bonedeltaRightFemaleFile = bonedeltaFile.Save();

            }
            else
            {
                if (chkMale.Checked)
                {
                    bonedeltaFile.rcolHeader.internalChunks.Add(boneDeltaLeftMale);
                    bdEntry.boneHash = 0x0F97B21B;
                    bdEntry.scale.x = -2f;
                    bdEntry.scale.y = -2f;
                    bdEntry.scale.z = -2f;
                    bonedeltaFile.bonedelta.entries.Add(bdEntry);
                }
                bonedeltaLeftMaleFile = bonedeltaFile.Save();
                if (chkMale.Checked)
                {
                    bonedeltaFile = new BoneDeltaFile();
                    bonedeltaFile.rcolHeader.internalChunks.Add(boneDeltaRightMale);
                    bdEntry = new BoneDeltaEntry();
                    bdEntry.boneHash = 0x0F97B21B;
                    bdEntry.scale.x = 2f;
                    bdEntry.scale.y = 2f;
                    bdEntry.scale.z = 2f;
                    bonedeltaFile.bonedelta.entries.Add(bdEntry);
                }
                bonedeltaRightMaleFile = bonedeltaFile.Save();

                if (chkFemale.Checked)
                {
                    bonedeltaFile = new BoneDeltaFile();
                    bonedeltaFile.rcolHeader.internalChunks.Add(boneDeltaLeftFemale);
                    bdEntry = new BoneDeltaEntry();
                    bdEntry.boneHash = 0x0F97B21B;
                    bdEntry.scale.x = -2f;
                    bdEntry.scale.y = -2f;
                    bdEntry.scale.z = -2f;
                    bonedeltaFile.bonedelta.entries.Add(bdEntry);
                }
                bonedeltaLeftFemaleFile = bonedeltaFile.Save();

                if (chkFemale.Checked)
                {
                    bonedeltaFile = new BoneDeltaFile();
                    bonedeltaFile.rcolHeader.internalChunks.Add(boneDeltaRightFemale);
                    bdEntry = new BoneDeltaEntry();
                    bdEntry.boneHash = 0x0F97B21B;
                    bdEntry.scale.x = 2f;
                    bdEntry.scale.y = 2f;
                    bdEntry.scale.z = 2f;
                    bonedeltaFile.bonedelta.entries.Add(bdEntry);
                }
                bonedeltaRightFemaleFile = bonedeltaFile.Save();
            }
            #endregion

            Stream packageFile = File.Create(folderBrowserDialog1.SelectedPath + "\\" + txtSliderName.Text + ".package");
            Database db = new Database(packageFile, false);

            for (int i = 0; i < 23; i++)
            {
                ulong actualKey = (ulong)(i * 72057594037927936) + instance32;
                db.SetResourceStream(new ResourceKey(0x220557DA, 0, actualKey), stblFile);
            }

            //db.SetResourceStream(stblKey, stblFile);
            db.SetResourceStream(nameMapKey, nameMapFile);
            db.SetResourceStream(blendunitKey, blendunitFile);
            db.SetResourceStream(blendGeomLeft, blendGeomFileLeft);
            db.SetResourceStream(blendGeomRight, blendGeomFileRight);
            db.SetResourceStream(facialblendLeft, faceBlendFileLeft);
            db.SetResourceStream(facialblendRight, faceBlendFileRight);

            if (chkMFLink.Checked)
            {
                db.SetResourceStream(vpxyLeftFemale, vpxyFileLeftFemale);
                db.SetResourceStream(vpxyRightFemale, vpxyFileRightFemale);
                db.SetResourceStream(boneDeltaLeftFemale, bonedeltaLeftFemaleFile);
                db.SetResourceStream(boneDeltaRightFemale, bonedeltaRightFemaleFile);
            }
            else
            {
                if (chkMale.Checked)
                {
                    db.SetResourceStream(vpxyLeftMale, vpxyFileLeftMale);
                    db.SetResourceStream(vpxyRightMale, vpxyFileRightMale);
                    db.SetResourceStream(boneDeltaLeftMale, bonedeltaLeftMaleFile);
                    db.SetResourceStream(boneDeltaRightMale, bonedeltaRightMaleFile);
                }
                if (chkFemale.Checked)
                {
                    db.SetResourceStream(vpxyLeftFemale, vpxyFileLeftFemale);
                    db.SetResourceStream(vpxyRightFemale, vpxyFileRightFemale);
                    db.SetResourceStream(boneDeltaLeftFemale, bonedeltaLeftFemaleFile);
                    db.SetResourceStream(boneDeltaRightFemale, bonedeltaRightFemaleFile);
                }
            }
            db.Commit(true);

            packageFile.Close();

            MessageBox.Show("Package saved");
        }
        public static Stream getStream(string filename, int typeID, int groupID, long instanceID)
        {
            Stream matchChunk = null;

            if (String.IsNullOrEmpty(filename)) { return matchChunk; }

            // Open the package file and search
            Stream package = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
            MadScience.Wrappers.Database db = new MadScience.Wrappers.Database(package, true);

            matchChunk = getStream(db, typeID, groupID, instanceID);

            package.Close();

            return matchChunk;
        }
        private void button9_Click(object sender, EventArgs e)
        {
            // Go through the list of DDS files and dump them
            string s3root = MadScience.Helpers.findSims3Root();

            if (s3root != "")
            {

                bool hasShownDialog = false;

                toolStripProgressBar1.Visible = true;
                toolStripProgressBar1.Minimum = 0;
                toolStripProgressBar1.Value = 0;
                toolStripStatusLabel1.Text = "Searching for meshes... please wait";
                statusStrip1.Refresh();

                Stream fbuild0 = File.Open(Path.Combine(s3root, Helpers.getGameSubPath("\\GameData\\Shared\\Packages\\FullBuild0.package")), FileMode.Open, FileAccess.Read, FileShare.Read);
                MadScience.Wrappers.Database db = new MadScience.Wrappers.Database(fbuild0, true);

                toolStripProgressBar1.Maximum = db._Entries.Count;

                Dictionary<ulong, string> keyNames = new Dictionary<ulong, string>();
                long nowTicks = DateTime.Now.Ticks;
                Console.WriteLine("Started at: " + nowTicks);
                foreach (MadScience.Wrappers.ResourceKey entry in db._Entries.Keys)
                {
                    //MadScience.Wrappers.ResourceKey entry = new MadScience.Wrappers.ResourceKey(keyString);
                    //DatabasePackedFile.Entry entry = db.dbpfEntries[i];
                    if (entry.typeId == (int)0x0166038C)
                    {
                        keyNames = Helpers.getKeyNames(db.GetResourceStream(entry));
                        break;
                    }
                }

                // Get the Mesh links for the first LOD
                //List<Stream> meshStreams = new List<Stream>();

                // Use the VPXY to get the mesh lod
                Stream vpxyStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexVPXY], 0);

                int numFound = 0;
                folderBrowserDialog1.SelectedPath = "";

                if (vpxyStream != null)
                {
                    VPXYFile vpxyFile = new VPXYFile(vpxyStream);
                    // Get the first VPXY internal link
                    if (vpxyFile.vpxy.linkEntries.Count >= 1) // && vpxyFile.vpxy.linkEntries[0].tgiList.Count >= 1)
                    {
                        for (int p = 0; p < vpxyFile.vpxy.linkEntries.Count; p++)
                        {
                            for (int i = 0; i < vpxyFile.vpxy.linkEntries[p].tgiList.Count; i++)
                            {
                                //meshStreams.Add(KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[i], 0));
                                //KeyUtils.findKey(vpxyFile.vpxy.linkEntries[0].tgiList[i], 0);

                                ResourceKey entry = vpxyFile.vpxy.linkEntries[p].tgiList[i];

                                string fileNameToSave = "";
                                if (keyNames.ContainsKey(entry.instanceId))
                                {
                                    fileNameToSave = keyNames[entry.instanceId];
                                    if (fileNameToSave.Contains("0x") == false) { fileNameToSave += "_0x" + entry.instanceId.ToString("X16"); }
                                }
                                else
                                {
                                    fileNameToSave = entry.typeId.ToString("X8") + "_" + entry.groupId.ToString("X8") + "_" + entry.instanceId.ToString("X16");
                                }

                                Stream output = KeyUtils.findKey(entry, 0);

                                if (!hasShownDialog)
                                {
                                    folderBrowserDialog1.Description = "Please select a folder to save the extracted meshes to.";
                                    folderBrowserDialog1.ShowDialog();
                                    hasShownDialog = true;
                                }
                                if (folderBrowserDialog1.SelectedPath != "")
                                {
                                    string extension = "";
                                    if (entry.typeId == 0x015A1849)
                                    {
                                        extension = ".simgeom";
                                    }

                                    FileStream saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                                    StreamHelpers.CopyStream(output, saveFile);
                                    saveFile.Close();
                                    numFound++;
                                }
                                output.Close();
                            }
                        }

                    }

                    if (numFound > 0)
                    {
                        string fileNameToSave2 = "";
                        ResourceKey entry = casPartSrc.tgi64list[casPartSrc.tgiIndexVPXY];
                        if (keyNames.ContainsKey(entry.instanceId))
                        {
                            fileNameToSave2 = keyNames[entry.instanceId];
                            if (fileNameToSave2.Contains("0x") == false) { fileNameToSave2 += "_0x" + entry.instanceId.ToString("X16"); }
                        }
                        else
                        {
                            fileNameToSave2 = entry.typeId.ToString("X8") + "_" + entry.groupId.ToString("X8") + "_" + entry.instanceId.ToString("X16");
                        }

                        FileStream saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave2) + ".vpxy", FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(vpxyStream, saveFile, true);
                        saveFile.Close();

                    }

                    vpxyStream.Close();

                }

                if (debugModeToolStripMenuItem.Checked)
                {
                    Stream bodyBlendFatStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoFat].ToString(), 0);
                    Stream bodyBlendFitStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoFit].ToString(), 0);
                    Stream bodyBlendThinStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoThin].ToString(), 0);
                    Stream bodyBlendSpecialStream = KeyUtils.findKey(casPartSrc.tgi64list[casPartSrc.tgiIndexBlendInfoSpecial].ToString(), 0);

                    if (!hasShownDialog)
                    {
                        folderBrowserDialog1.Description = "Please select a folder to save the extracted meshes to.";
                        folderBrowserDialog1.ShowDialog();
                        hasShownDialog = true;
                    }
                    if (folderBrowserDialog1.SelectedPath != "")
                    {
                        string extension = ".bodyblend";

                        string fileNameToSave = "";
                        fileNameToSave = txtMeshName.Text + "_fit";
                        FileStream saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(bodyBlendFitStream, saveFile);
                        saveFile.Close();

                        fileNameToSave = txtMeshName.Text + "_fat";
                        saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(bodyBlendFatStream, saveFile);
                        saveFile.Close();

                        fileNameToSave = txtMeshName.Text + "_thin";
                        saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(bodyBlendThinStream, saveFile);
                        saveFile.Close();

                        fileNameToSave = txtMeshName.Text + "_special";
                        saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(bodyBlendSpecialStream, saveFile);
                        saveFile.Close();

                        // Just grab the one BGEO for now
                        bodyBlendFatStream.Seek(0, SeekOrigin.Begin);
                        FacialBlend fblend = new FacialBlend(bodyBlendFatStream);
                        Stream bgeoStream = KeyUtils.findKey(fblend.blendTgi, 0);
                        bgeoStream.Seek(0, SeekOrigin.Begin);
                        extension = ".blendgeom";
                        fileNameToSave = txtMeshName.Text + "_fat";
                        saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(bgeoStream, saveFile);
                        saveFile.Close();

                        bodyBlendFitStream.Seek(0, SeekOrigin.Begin);
                        fblend = new FacialBlend(bodyBlendFitStream);
                        bgeoStream = KeyUtils.findKey(fblend.blendTgi, 0);
                        bgeoStream.Seek(0, SeekOrigin.Begin);
                        fileNameToSave = txtMeshName.Text + "_fit";
                        saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(bgeoStream, saveFile);
                        saveFile.Close();

                        bodyBlendThinStream.Seek(0, SeekOrigin.Begin);
                        fblend = new FacialBlend(bodyBlendThinStream);
                        bgeoStream = KeyUtils.findKey(fblend.blendTgi, 0);
                        bgeoStream.Seek(0, SeekOrigin.Begin);
                        extension = ".blendgeom";
                        fileNameToSave = txtMeshName.Text + "_thin";
                        saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(bgeoStream, saveFile);
                        saveFile.Close();

                        bodyBlendSpecialStream.Seek(0, SeekOrigin.Begin);
                        fblend = new FacialBlend(bodyBlendSpecialStream);
                        bgeoStream = KeyUtils.findKey(fblend.blendTgi, 0);
                        bgeoStream.Seek(0, SeekOrigin.Begin);
                        extension = ".blendgeom";
                        fileNameToSave = txtMeshName.Text + "_special";
                        saveFile = new FileStream(Path.Combine(folderBrowserDialog1.SelectedPath, fileNameToSave + extension), FileMode.Create, FileAccess.Write);
                        StreamHelpers.CopyStream(bgeoStream, saveFile);
                        saveFile.Close();

                        //numFound++;
                    }
                }
                toolStripProgressBar1.Value = 0;
                toolStripProgressBar1.Visible = false;
                toolStripStatusLabel1.Text = numFound.ToString() + " meshes found";
                statusStrip1.Refresh();

                fbuild0.Close();
            }
        }
        public static Stream getStream(Database db, int typeID, int groupID, long instanceID)
        {
            Stream matchChunk = null;

            int searchType = 0;
            if (typeID != -1) { searchType += 1; }
            if (groupID != -1) { searchType += 2; }
            if (instanceID != -1) { searchType += 4; }

            bool foundMatch = false;

            foreach (MadScience.Wrappers.ResourceKey entry in db._Entries.Keys)
            {
                //ResourceKey key = db.Entries.Keys[i];
                //DatabasePackedFile.Entry entry = db.Entries.Keys[i];
                //DatabasePackedFile.Entry entry = db.dbpfEntries[i];
                //MadScience.Wrappers.ResourceKey entry = new MadScience.Wrappers.ResourceKey(keyString);

                switch (searchType)
                {
                    case 7:
                        if (entry.typeId == typeID && entry.groupId == groupID && entry.instanceId == (ulong)instanceID)
                        {
                            //loadedCasPart = entry;
                            matchChunk = db.GetResourceStream(entry);
                            foundMatch = true;
                        }
                        break;
                    case 6:
                        if (entry.groupId == groupID && entry.instanceId == (ulong)instanceID)
                        {
                            //loadedCasPart = entry;
                            matchChunk = db.GetResourceStream(entry);
                            foundMatch = true;
                        }
                        break;
                    case 5:
                        if (entry.typeId == typeID && entry.instanceId == (ulong)instanceID)
                        {
                            //loadedCasPart = entry;
                            matchChunk = db.GetResourceStream(entry);
                            foundMatch = true;
                        }
                        break;
                    case 4:
                        if (entry.instanceId == (ulong)instanceID)
                        {
                            //loadedCasPart = entry;
                            matchChunk = db.GetResourceStream(entry);
                            foundMatch = true;
                        }
                        break;
                    case 3:
                        if (entry.typeId == typeID && entry.groupId == groupID)
                        {
                            //loadedCasPart = entry;
                            matchChunk = db.GetResourceStream(entry);
                            foundMatch = true;
                        }
                        break;
                    case 2:
                        if (entry.groupId == groupID)
                        {
                            //loadedCasPart = entry;
                            matchChunk = db.GetResourceStream(entry);
                            foundMatch = true;
                        }
                        break;
                    case 1:
                        if (entry.typeId == typeID)
                        {
                            //loadedCasPart = entry;
                            matchChunk = db.GetResourceStream(entry);
                            foundMatch = true;
                        }
                        break;
                }
                if (foundMatch)
                {
                    break;
                }

            }

            return matchChunk;
        }
        /*
        private string convertColour(Color color)
        {
            // Converts a colour dialog box colour into a 0 to 1 style colour
            float newR = color.R / 255f;
            float newG = color.G / 255f;
            float newB = color.B / 255f;

            // Alpha is always 1
            int alpha = 1;

            //CultureInfo englishCulture = new CultureInfo("");
            string red = String.Format(CultureInfo.InvariantCulture, "{0:0.0000000}", newR);
            string green = String.Format(CultureInfo.InvariantCulture, "{0:0.0000000}", newG);
            string blue = String.Format(CultureInfo.InvariantCulture, "{0:0.0000000}", newB);

            return red + "," + green + "," + blue + "," + alpha.ToString();

        }
        */
        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (validateFields() == false)
            {
                MessageBox.Show("You have a missing or invalid field!  Please double check everything and try again.");
                return;
            }

            // Save folders in registry
            RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Mad Scientist Productions\\" + Application.ProductName, true);
            key.SetValue("creatorName", txtCreatorName.Text);
            key.SetValue("creatorHomepage", txtCreatorHomepage.Text);
            key.Close();

            //saveFileDialog1.Filter = "Sims 3 Pack|*.Sims3Pack";
            saveFileDialog1.Filter = "Sims 3 Package|*.package|Sims 3 Pack|*.Sims3Pack";
            saveFileDialog1.Title = "Save Pattern As....";
            saveFileDialog1.FileName = "";
            saveFileDialog1.OverwritePrompt = true;
            if (saveFileDialog1.ShowDialog() == DialogResult.OK && !String.IsNullOrEmpty(saveFileDialog1.FileName))
            {

                // Check for .package on the end - if it exists, strip it
                string savePath = saveFileDialog1.FileName.Substring(0, saveFileDialog1.FileName.LastIndexOf(Path.DirectorySeparatorChar) + 1);

                string saveName = "";

                FileInfo f = new FileInfo(saveFileDialog1.FileName);
                saveName = saveFileDialog1.FileName.Substring(saveFileDialog1.FileName.LastIndexOf(Path.DirectorySeparatorChar) + 1).Replace(f.Extension, "");

                toggleEverything(false);

                label1.Visible = true;
                label1.Refresh();
                this.Refresh();

                // Construct name for XML
                string fName = MadScience.Helpers.sanitiseString(saveName);

                string pName = "DPP_" + MadScience.Helpers.sanitiseString(txtCreatorName.Text.Trim()) + "_" + fName + "_" + MadScience.Helpers.sanitiseString(dateTimePicker1.Value.ToString());

                ulong instanceId = MadScience.StringHelpers.HashFNV64(pName);
                ulong specInstanceId = MadScience.StringHelpers.HashFNV64(pName + "_spec");

                //uint groupId = 33554432;
                uint groupId = 0;

                int numChans = numChannels();

                StringBuilder sb = new StringBuilder();
                sb.AppendLine("<complate category=\"" + cmbCategory.Text + "\" type=\"fabric\" name=\"" + pName + "\" typeConverter=\"Medator.ComplateConvertor,Medator\" surfaceMaterial=\"" + cmbSurfaceMat.Text + "\" reskey=\"key:0333406c:" + groupId.ToString("X8").ToLower() + ":" + instanceId.ToString("X16").ToLower() + "\">");
                sb.AppendLine("  <GUID>" + System.Guid.NewGuid().ToString() + "</GUID>");
                sb.AppendLine("  <variables>");

                // Convert color boxes into 0 to 1 style colours
                if (numChans >= 1) { sb.AppendLine("    <param type=\"color\" name=\"Color 0\" default=\"" + MadScience.Colours.convertColour(lblPalette1.BackColor) + "\" uiEditor=\"Medator.Color4TypeEditor, Medator\" uiCategory=\"Colors\" />"); }
                if (numChans >= 2) { sb.AppendLine("    <param type=\"color\" name=\"Color 1\" default=\"" + MadScience.Colours.convertColour(lblPalette2.BackColor) + "\" uiEditor=\"Medator.Color4TypeEditor, Medator\" uiCategory=\"Colors\" />"); }
                if (numChans >= 3) { sb.AppendLine("    <param type=\"color\" name=\"Color 2\" default=\"" + MadScience.Colours.convertColour(lblPalette3.BackColor) + "\" uiEditor=\"Medator.Color4TypeEditor, Medator\" uiCategory=\"Colors\" />"); }
                if (numChans == 4) { sb.AppendLine("    <param type=\"color\" name=\"Color 3\" default=\"" + MadScience.Colours.convertColour(lblPalette4.BackColor) + "\" uiEditor=\"Medator.Color4TypeEditor, Medator\" uiCategory=\"Colors\" />"); }

                sb.AppendLine("    <param type=\"texture\" name=\"rgbmask\" uiVisible=\"false\" default=\"key:00b2d882:" + groupId.ToString("X8").ToLower() + ":" + instanceId.ToString("X16").ToLower() + "\" />");
                if (chkUseDefaultSpecular.Checked)
                {
                    sb.AppendLine("    <param type=\"texture\" name=\"specmap\" uiVisible=\"false\" default=\"($assetRoot)\\InGame\\GlobalTextures\\Objects\\defaultBlackSpecular.tga\" />");
                }
                else
                {
                    sb.AppendLine("    <param type=\"texture\" name=\"specmap\" uiVisible=\"false\" default=\"key:00b2d882:" + groupId.ToString("X8").ToLower() + ":" + specInstanceId.ToString("X16").ToLower() + "\" />");
                }
                sb.AppendLine("  </variables>");

                sb.AppendLine("  <texturePart>");
                sb.AppendLine("    <destination>");
                if (!chkAllowDecal.Checked)
                {
                    sb.AppendLine("      <step type=\"ColorFill\" color=\"" + MadScience.Colours.convertColour(lblBackgroundColour.BackColor) + "\" />");
                }
                // 2 lines per channel
                if (numChans >= 1)
                {
                    sb.AppendLine("      <step type=\"ChannelSelect\" texture=\"($rgbmask)\" select=\"1.0000,0.0000,0.0000,0.0000\" colorWrite=\"Alpha\" />");
                    sb.AppendLine("      <step type=\"ColorFill\" color=\"($Color 0)\" enableBlending=\"" + chkPalette1Blend.Checked.ToString().ToLower() + "\" srcBlend=\"DestAlpha\" dstBlend=\"InvDestAlpha\" sourceRect=\"0,0,1,1\" />");
                }
                if (numChans >= 2)
                {
                    sb.AppendLine("      <step type=\"ChannelSelect\" texture=\"($rgbmask)\" select=\"0.0000,1.0000,0.0000,0.0000\" colorWrite=\"Alpha\" />");
                    sb.AppendLine("      <step type=\"ColorFill\" color=\"($Color 1)\" enableBlending=\"" + chkPalette1Blend.Checked.ToString().ToLower() + "\" srcBlend=\"DestAlpha\" dstBlend=\"InvDestAlpha\" sourceRect=\"0,0,1,1\" />");
                }
                if (numChans >= 3)
                {
                    sb.AppendLine("      <step type=\"ChannelSelect\" texture=\"($rgbmask)\" select=\"0.0000,0.0000,1.0000,0.0000\" colorWrite=\"Alpha\" />");
                    sb.AppendLine("      <step type=\"ColorFill\" color=\"($Color 2)\" enableBlending=\"" + chkPalette1Blend.Checked.ToString().ToLower() + "\" srcBlend=\"DestAlpha\" dstBlend=\"InvDestAlpha\" sourceRect=\"0,0,1,1\" />");
                }
                if (numChans >= 4)
                {
                    sb.AppendLine("      <step type=\"ChannelSelect\" texture=\"($rgbmask)\" select=\"0.0000,0.0000,0.0000,1.0000\" colorWrite=\"Alpha\" />");
                    sb.AppendLine("      <step type=\"ColorFill\" color=\"($Color 3)\" enableBlending=\"" + chkPalette1Blend.Checked.ToString().ToLower() + "\" srcBlend=\"DestAlpha\" dstBlend=\"InvDestAlpha\" sourceRect=\"0,0,1,1\" />");
                }

                sb.AppendLine("      <step type=\"ChannelSelect\" texture=\"($specmap)\" select=\"1.0,0.0,0.0,0.0\" colorWrite=\"Alpha\" />");
                sb.AppendLine("    </destination>");
                sb.AppendLine("  </texturePart>");

                sb.AppendLine("  <localizedName key=\"Name:" + pName + "\" />");
                sb.AppendLine("  <contentType type=\"kCustomContent\" />");
                sb.AppendLine("  <localizedDescription key=\"Name:" + pName + "\" />");
                sb.AppendLine("</complate>");

                string xml033406c = sb.ToString();

                sb = null;
                sb = new StringBuilder();

                // Now for the d4d9fbe5 patternlist file
                sb.AppendLine("<patternlist>");
                sb.AppendLine("  <category name=\"" + cmbCategory.Text + "\">");
                sb.AppendLine("    <pattern reskey=\"key:0333406c:" + groupId.ToString("X8").ToLower() + ":" + instanceId.ToString("X16").ToLower() + "\" name=\"" + pName + "\" complexity=\"\" />");
                sb.AppendLine("  </category>");
                sb.AppendLine("</patternlist>");

                string xmld4d9fbe = sb.ToString();

                sb = null;
                sb = new StringBuilder();

                sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
                sb.Append("<manifest version=\"3\" packagetype=\"pattern\" packagesubtype=\"0x00000000\" paidcontent=\"false\">");
                sb.Append("<gameversion>0.0.0.11195</gameversion>");
                sb.Append("<packagedate>" + dateTimePicker1.Value.ToString() + "</packagedate>");
                sb.Append("<packageid>" + pName + "</packageid>");
                sb.Append("<packagetitle><![CDATA[" + txtPatternTitle.Text + "]]></packagetitle>");
                sb.Append("<packagedesc><![CDATA[" + txtPatternDesc.Text + "]]></packagedesc>");
                sb.Append("<assetversion>0</assetversion>");
                sb.Append("<mingamever>1.0.0.0</mingamever>");
                sb.Append("<thumbnail>2e75c765:" + groupId.ToString("X8").ToLower() + ":" + instanceId.ToString("X16").ToLower() + "</thumbnail>");
                sb.Append("<localizednames>");
                sb.Append("<localizedname language=\"en-US\"><![CDATA[" + txtPatternTitle.Text + "]]></localizedname>");
                sb.Append("</localizednames>");
                sb.Append("<localizeddescriptions>");
                sb.Append("<localizeddescription language=\"en-US\"><![CDATA[" + txtPatternDesc.Text + "]]></localizeddescription>");
                sb.Append("</localizeddescriptions>");
                sb.Append("<handler />");
                sb.Append("<dependencylist>");
                sb.Append("<packageid>0x050cffe800000000050cffe800000000</packageid>");
                sb.Append("<packageid>" + pName + "</packageid>");
                sb.Append("</dependencylist>");
                sb.Append("<keylist>");
                sb.Append("<reskey>1:0333406c:" + groupId.ToString("X8").ToLower() + ":" + instanceId.ToString("X16").ToLower() + "</reskey>");
                sb.Append("<reskey>1:00b2d882:" + groupId.ToString("X8").ToLower() + ":" + instanceId.ToString("X16").ToLower() + "</reskey>");
                sb.Append("<reskey>1:d4d9fbe5:" + groupId.ToString("X8").ToLower() + ":" + instanceId.ToString("X16").ToLower() + "</reskey>");
                sb.Append("<reskey>1:2e75c765:" + groupId.ToString("X8").ToLower() + ":" + instanceId.ToString("X16").ToLower() + "</reskey>");
                if (chkUseDefaultSpecular.Checked == false) { sb.Append("<reskey>1:00b2d882:" + groupId.ToString("X8").ToLower() + ":" + specInstanceId.ToString("X16").ToLower() + "</reskey>"); }
                sb.Append("</keylist>");
                sb.Append("<metatags>");
                sb.Append("<numofthumbs>1</numofthumbs>");
                sb.Append("<matcategory>" + cmbCategory.Text + "</matcategory>");
                sb.Append("</metatags>");
                sb.Append("</manifest>");

                string xml73e93eeb = sb.ToString();
                sb = null;

                sb = new StringBuilder();

                sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
                sb.Append("<communityCustomContentManifest>");
                sb.Append("<installTo>{CCROOT}/installTo>");
                sb.Append("<contentType>Pattern</contentType>");
                sb.Append("<creatorName><![CDATA[" + MadScience.Helpers.sanitiseString(txtCreatorName.Text.Trim()) + "]]></creatorName>");
                sb.Append("<homePage><![CDATA[" + txtCreatorHomepage.Text.Trim() + "]]></homePage>");
                sb.Append("<toolName>DelphysPatternCreator</toolName>");
                sb.Append("</communityCustomContentManifest>");

                string xmlCommunityCustomContentPackage = sb.ToString();
                sb = null;

                Stream output;
                if (f.Extension.ToLower() == ".package")
                {
                    output = File.Open(savePath + saveName + ".package", FileMode.Create, FileAccess.ReadWrite);
                }
                else
                {
                    output = new MemoryStream();
                }

                Database db = new Database(output, false);
                ResourceKey rkey;

                rkey = new ResourceKey((uint)0xDEADBEEF, (uint)0xDEADBEEF, (ulong)0xcafebabeb000b135);
                db.SetResource(rkey, Encoding.UTF8.GetBytes(xmlCommunityCustomContentPackage));

                // 0x73e93eeb
                rkey = new ResourceKey(1944665835, 0, (ulong)0);
                db.SetResource(rkey, Encoding.UTF8.GetBytes(xml73e93eeb));

                // 0x0333406
                rkey = new ResourceKey(53690476, groupId, instanceId);
                db.SetResource(rkey, Encoding.UTF8.GetBytes(xml033406c));

                // 0xd4d9fbe5
                rkey = new ResourceKey(3571055589, groupId, instanceId);
                db.SetResource(rkey, Encoding.UTF8.GetBytes(xmld4d9fbe));

                // 0x00B2D882
                Stream ddsImage = File.Open(txtSourceDDS.Text, FileMode.Open);
                rkey = new ResourceKey(11720834, groupId, instanceId);
                db.SetResourceStream(rkey, ddsImage);
                ddsImage.Close();

                if (chkUseDefaultSpecular.Checked == false)
                {
                    // 0x00B2D882
                    Stream ddsImageSpec = File.Open(lblSpecularCustom.Text, FileMode.Open);
                    rkey = new ResourceKey(11720834, groupId, specInstanceId);
                    db.SetResourceStream(rkey, ddsImageSpec);
                    ddsImageSpec.Close();

                }

                // PNG file
                MemoryStream pngFile = new MemoryStream();
                if (radioButton1.Checked)
                {
                    toggleColourPalettes(true, true, false, false, false);
                }
                if (radioButton2.Checked)
                {
                    toggleColourPalettes(true, true, true, false, false);
                }
                if (radioButton3.Checked)
                {
                    toggleColourPalettes(true, true, true, true, false);
                }
                if (radioButton4.Checked)
                {
                    toggleColourPalettes(true, true, true, true, true);
                }

                pictureBox1.Image.Save(pngFile, System.Drawing.Imaging.ImageFormat.Png);

                pngFile.Seek(0, SeekOrigin.Begin);
                rkey = new ResourceKey(0x2E75C765, groupId, instanceId);
                db.SetResourceStream(rkey, pngFile);

                db.Commit(true);

                //output.Close();

                //FileInfo fi = new FileInfo(saveFileDialog1.FileName);

                if (f.Extension.ToLower() == ".sims3pack")
                {

                    sb = new StringBuilder();
                    sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
                    sb.Append("<Sims3Package Type=\"pattern\" SubType=\"0x00000000\">");
                    sb.Append("<ArchiveVersion>1.4</ArchiveVersion>");
                    sb.Append("<CodeVersion>0.0.0.34</CodeVersion>");
                    sb.Append("<GameVersion>0.0.0.0</GameVersion>");
                    sb.Append("<PackageId>" + pName + "</PackageId>");
                    sb.Append("<Date>" + dateTimePicker1.Value.ToString() + "</Date>");
                    sb.Append("<AssetVersion>0</AssetVersion>");
                    sb.Append("<MinReqVersion>1.0.0.0</MinReqVersion>");
                    sb.Append("<DisplayName><![CDATA[" + txtPatternTitle.Text + "]]></DisplayName>");
                    sb.Append("<Description><![CDATA[" + txtPatternDesc.Text + "]]></Description>");
                    //sb.Append("<DisplayName>" + txtPatternTitle.Text + "</DisplayName>");
                    //sb.Append("<Description>" + txtPatternDesc.Text + "</Description>");
                    sb.Append("<Dependencies>");
                    sb.Append("<Dependency>0x050cffe800000000050cffe800000000</Dependency>");
                    //sb.Append("<Dependency>" + pName + "</Dependency>");
                    sb.Append("</Dependencies>");
                    sb.Append("<LocalizedNames>");
                    sb.Append("<LocalizedName Language=\"en-US\"><![CDATA[" + txtPatternTitle.Text + "]]></LocalizedName>");
                    sb.Append("</LocalizedNames>");
                    sb.Append("<LocalizedDescriptions>");
                    sb.Append("<LocalizedDescription Language=\"en-US\"><![CDATA[" + txtPatternDesc.Text + "]]></LocalizedDescription>");
                    sb.Append("</LocalizedDescriptions>");
                    sb.Append("<PackagedFile>");
                    sb.Append("<Name>" + pName + ".package</Name>");
                    sb.Append("<Length>" + output.Length + "</Length>");
                    sb.Append("<Offset>0</Offset>");
                    //sb.Append("    <Crc>317211BAD0B3E0F5</Crc>");
                    sb.Append("<Guid>" + pName + "</Guid>");
                    sb.Append("<ContentType>pattern</ContentType>");
                    sb.Append("<MetaTags />");
                    sb.Append("</PackagedFile>");
                    /*
                    sb.Append("    <metatags>");
                    sb.Append("      <numOfThumbs>1</numOfThumbs>");
                    sb.Append("      <matCategory>" + cmbCategory.Text + "</matCategory>");
                    sb.Append("    </metatags>");

                    */
                    /*
                    sb.Append("  <PackagedFile>");
                    sb.Append("    <Name>" + pName + ".png</Name>");
                    sb.Append("    <Length>" + pngFile.Length + "</Length>");
                    sb.Append("    <Offset>" + output.Length + "</Offset>");
                    //sb.Append("    <Crc>317211BAD0B3E0F5</Crc>");
                    sb.Append("    <Guid>" + pName + "png</Guid>");
                    sb.Append("    <ContentType>unknown</ContentType>");
                    sb.Append("    <metatags />");
                    sb.Append("  </PackagedFile>");
                    */
                    sb.Append("</Sims3Package>");

                    string s3p_xml = sb.ToString();
                    sb = null;

                    Stream sims3pack = File.Open(savePath + saveName + ".Sims3Pack", FileMode.Create, FileAccess.ReadWrite);

                    MadScience.StreamHelpers.WriteValueU32(sims3pack, 7);
                    MadScience.StreamHelpers.WriteStringASCII(sims3pack, "TS3Pack");
                    MadScience.StreamHelpers.WriteValueU16(sims3pack, 257);
                    MadScience.StreamHelpers.WriteValueU32(sims3pack, (uint)s3p_xml.Length);
                    MadScience.StreamHelpers.WriteStringUTF8(sims3pack, s3p_xml);

                    MadScience.StreamHelpers.CopyStream(output, sims3pack, true);
                    //ReadWriteStream(pngFile, sims3pack, true);

                    sims3pack.Close();

                }
                pngFile.Close();
                output.Close();

                toggleEverything(true);
                label1.Visible = false;

            }
        }