/// <summary>
        /// Loads a .mod file from given file and returns a nullable boolean (True, null, False).
        /// </summary>
        /// <param name="file">.mod file to load.</param>
        /// <param name="modCount">REF: Total number of jobs loaded.</param>
        /// <param name="progbar">ProgressBar to increment/change during method.</param>
        /// <param name="ExternalCall">If true, certain functions are disabled/automated.</param>
        /// <returns>True if update is to be done automatically, false if not, and null if user requests to stop loading .mod.</returns>
        public static bool? LoadDotMod(string file, ref int modCount, ToolStripProgressBar progbar, bool ExternalCall)
        {
            bool AutoUpdate = false;

            // KFreon: Load from file
            using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                // KFreon: Attempt to get version
                fs.Seek(0, SeekOrigin.Begin);
                int versionLength = fs.ReadValueS32();
                long countOffset = fs.Seek(0, SeekOrigin.Current);  // Just in case
                string version = "";
                int count = -1;
                string ExecutingVersion = null;
                bool validVersion = false;
                if (versionLength > 20)     // KFreon: Version is definitely wrong
                    ExecutingVersion = "";
                else
                {
                    // KFreon: Do version checking
                    for (int i = 0; i < versionLength; i++)
                        version += (char)fs.ReadByte();

                    // KFreon: Get Executing Version and check validity of read .mod version
                    string vers;
                    ExecutingVersion = GetVersion(version, out vers, out validVersion);
                    version = vers;

                    count = fs.ReadValueS32();

                    // KFreon: Check if update required
                    if (version != ExecutingVersion)
                    {
                        if (ExternalCall)
                            AutoUpdate = true;
                    }
                    else   // KFreon: Reset to null to signify success
                        ExecutingVersion = null;
                }

                
                // KFreon: Ask what to do about version
                if (ExecutingVersion != null) //&& !ExternalCall) // Heff: do we want to suppress this for external calls? should they always autoupdate?
                {                                                 // Seems better to keep it the current way, so that users get prompted if they load old .mods.
                    DialogResult dr = MessageBox.Show(Path.GetFileName(file) + " is old and unsupported by this version of ME3Explorer." + Environment.NewLine + "Click Yes to update .mod now, No to continue loading .mod, or Cancel to stop loading .mod", "Ancient .mod detected.", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                    if (dr == System.Windows.Forms.DialogResult.Cancel)
                        return null;
                    else if (dr == System.Windows.Forms.DialogResult.Yes)
                        AutoUpdate = true;
                }
                /*else if (ExecutingVersion != null) // Heff: could use this for always updating if its an external call:
                    AutoUpdate = true;*/

                // KFreon: Reset stream position if necessary
                if (!validVersion)
                {
                    count = versionLength;
                    fs.Seek(countOffset, SeekOrigin.Begin);
                }

                // KFreon: Increment progress bar
                if (progbar != null)
                    progbar.GetCurrentParent().Invoke(new Action(() =>
                    {
                        progbar.Value = 0;
                        progbar.Maximum = count;
                    }));

                // KFreon: Read Data
                DebugOutput.PrintLn("Found " + count + " Jobs", true);
                modCount += count;
                for (int i = 0; i < count; i++)
                {
                    // KFreon: Read name
                    ModMaker.ModJob md = new ModMaker.ModJob();
                    int len = fs.ReadValueS32();
                    md.Name = "";
                    for (int j = 0; j < len; j++)
                        md.Name += (char)fs.ReadByte();

                    // KFreon: Read script
                    len = fs.ReadValueS32();
                    md.Script = "";
                    for (int j = 0; j < len; j++)
                        md.Script += (char)fs.ReadByte();

                    // KFreon: Read data
                    len = fs.ReadValueS32();
                    byte[] buff = fs.ReadBytes(len);
                    md.data = buff;
                    ModMaker.JobList.Add(md);
                    DebugOutput.PrintLn("Add Job \"" + md.Name + "\"", true);

                    if (progbar != null)
                        progbar.GetCurrentParent().Invoke(new Action(() => progbar.Increment(1)));
                }
            }
            return AutoUpdate;
        }
Example #2
0
        private void MoveCaches(string cookedPath, string NewCache)
        {
            //Fix the GUID
            using (FileStream newCache = new FileStream(Path.Combine(cookedPath, NewCache), FileMode.Open, FileAccess.Read))
            {
                SaltPropertyReader.Property GUIDProp = properties["TFCFileGuid"];

                for (int i = 0; i < 4; i++)
                {
                    SaltPropertyReader.PropertyValue tempVal = GUIDProp.Value.Array[i];
                    tempVal.IntValue = newCache.ReadValueS32();
                    GUIDProp.Value.Array[i] = tempVal;
                }
            }

            //Move across any existing textures
            using (FileStream oldCache = new FileStream(FullArcPath, FileMode.Open, FileAccess.Read))
            {
                using (FileStream newCache = new FileStream(Path.Combine(cookedPath, NewCache), FileMode.Append, FileAccess.Write))
                {
                    for (int i = 0; i < privateimgList.Count; i++)
                    {
                        ImageInfo img = privateimgList[i];

                        switch (img.storageType)
                        {
                            case storage.arcCpr:
                                byte[] buff = new byte[img.cprSize];
                                oldCache.Seek(img.offset, SeekOrigin.Begin);
                                Buffer.BlockCopy(oldCache.ReadBytes(img.cprSize), 0, buff, 0, img.cprSize);
                                img.offset = (int)newCache.Position;
                                newCache.WriteBytes(buff);
                                break;
                            case storage.arcUnc:
                                buff = new byte[img.uncSize];
                                oldCache.Seek(img.offset, SeekOrigin.Begin);
                                Buffer.BlockCopy(oldCache.ReadBytes(img.cprSize), 0, buff, 0, img.cprSize);
                                img.offset = (int)newCache.Position;
                                newCache.WriteBytes(buff);
                                break;
                            case storage.pccSto:
                                break;
                            case storage.empty:
                                break;
                            default:
                                throw new NotImplementedException("Storage type not supported yet");
                        }
                        privateimgList[i] = img;
                    }
                }
            }
        }
        public void clean()
        {
            using (FileStream tocStream = new FileStream(tocFilePath, FileMode.Open, FileAccess.ReadWrite), newTocStream = File.Create(tocFilePath + ".tmp"))
            {
                tocStream.Seek(0, SeekOrigin.Begin);
                byte[] buffer = tocStream.ReadBytes(8);
                newTocStream.WriteBytes(buffer);
                int count = tocStream.ReadValueS32();

                newTocStream.Seek(12, SeekOrigin.Begin);
                int newCount = 0;
                for (int i = 0; i < count; i++)
                {
                    int offset = tocStream.ReadValueS32();
                    int nextFiles = tocStream.ReadValueS32();
                    //if (offset != 0)
                    {
                        newCount++;
                        newTocStream.WriteValueS32(offset);
                        newTocStream.WriteValueS32(nextFiles);
                    }
                }
                //MessageBox.Show("pos: " + newTocStream.Position);
                newTocStream.Seek(8, SeekOrigin.Begin);
                newTocStream.WriteValueS32(newCount);

                int newDataOffset = 12 + (newCount * 8);

                //newTocStream.Seek(12 + (newCount * 8), SeekOrigin.Begin);
                //newTocStream.Seek(12, SeekOrigin.Begin);

                int oldDataOffset = 12 + (count * 8);
                int oldChunkOffset = 16;
                int newChunkOffset = 12;
                for (int i = 0; i < count; i++)
                {
                    //MessageBox.Show("pos: " + newTocStream.Length);
                    tocStream.Seek(oldChunkOffset, SeekOrigin.Begin);
                    oldChunkOffset += 8;
                    int numOfNextFiles = tocStream.ReadValueS32();
                    //oldChunkOffset += 4;
                    //MessageBox.Show("numofnextfiles: " + numOfNextFiles + " at pos: 0x" + oldChunkOffset.ToString("X4"));

                    /*if (numOfNextFiles == 0)
                    {
                        //newChunkOffset -= 4;
                        newTocStream.Seek(newChunkOffset, SeekOrigin.Begin);
                        continue;
                    }*/

                    //newChunkOffset += 4;
                    newTocStream.Seek(newChunkOffset, SeekOrigin.Begin);
                    if(numOfNextFiles == 0)
                        newTocStream.WriteValueS32(0);
                    else
                        newTocStream.WriteValueS32((int)newTocStream.Length - newChunkOffset);
                    newTocStream.WriteValueS32(numOfNextFiles);
                    newChunkOffset = (int)newTocStream.Position;
                    newTocStream.Seek(0, SeekOrigin.End);

                    for (int j = 0; j < numOfNextFiles; j++)
                    {
                        short size;
                        tocStream.Seek(oldDataOffset, SeekOrigin.Begin);
                        size = tocStream.ReadValueS16();
                        tocStream.Seek(oldDataOffset, SeekOrigin.Begin);
                        oldDataOffset += size;
                        buffer = tocStream.ReadBytes(size);
                        newTocStream.Seek(newDataOffset, SeekOrigin.Begin);
                        newTocStream.WriteBytes(buffer);
                        newDataOffset = (int)newTocStream.Position;
                    }
                }
            }
        }