/// <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; }
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; } } } }