///======================================================================== /// Static Method : FindCourseNameOffsets /// /// <summary> /// Find the locations in the CD image of all the course names. /// /// This only finds course names that are coded into the MMCD class. /// </summary> /// <param name="xiCDImage"></param> /// <returns></returns> ///======================================================================== private static int FindCourseNameOffsets(FileInfo xiCDImage) { CDImage lCDImage = new CDImage(xiCDImage); foreach (MMCD.Course lCourse in MMCD.Courses) { if (lCourse.CourseName == "") { continue; } byte[] lBytes = Encoding.ASCII.GetBytes(lCourse.CourseNameWithLineBreaks); long lIndex = 0; bool lFound = false; while ((lIndex = lCDImage.Find(lBytes, lIndex)) > 0) { WriteLine("{0}: {1}", lCourse.FileName, lIndex++, lCourse.CourseName); lFound = true; } if (!lFound) { WriteLine("{0}: Not found", lCourse.FileName, lCourse.CourseName); } } return 0; }
///======================================================================== /// Method : publishToolStripMenuItem_Click /// /// <summary> /// The Publish operation /// </summary> /// <param name="sender"></param> /// <param name="e"></param> ///======================================================================== private void publishToolStripMenuItem_Click(object sender, EventArgs e) { PublishForm lForm = new PublishForm(this); if (RootChunk is VersionList) { //===================================================================== // Use the properties saved on the VersionList as defaults //===================================================================== VersionList lVersionList = (VersionList)RootChunk; if (lVersionList.CDFilename != null && lVersionList.CDFilename != "") { lForm.CourseDropDown.SelectedItem = MMCD.Courses.Find(new Predicate<MMCD.Course>( delegate (MMCD.Course xiCourse) { return xiCourse.FileName == lVersionList.CDFilename; })); } if (lVersionList.BinaryFilename != null && lVersionList.BinaryFilename != "") { lForm.BinaryFileTextBox.Text = lVersionList.BinaryFilename; } if (lVersionList.CourseName != null && lVersionList.CourseName != "") { lForm.NameTextBox.Text = lVersionList.CourseName; } } if (lForm.ShowDialog() == DialogResult.OK) { FileInfo lBinaryFile = new FileInfo(lForm.BinaryFileTextBox.Text); //===================================================================== // If we want to keep backups, make one now //===================================================================== if (lForm.BackupsCheckBox.Checked && lBinaryFile.Exists) { string lBackupExtension = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.bak"); string lBackupPath = Path.Combine(Path.GetDirectoryName(lForm.BinaryFileTextBox.Text), "Backups"); if (!Directory.Exists(lBackupPath)) { Directory.CreateDirectory(lBackupPath); } string lBackupFile = Path.Combine(lBackupPath, Path.GetFileNameWithoutExtension(lForm.BinaryFileTextBox.Text) + "." + lBackupExtension); lBinaryFile.CopyTo(lBackupFile); //=================================================================== // Remove any outdated backups //=================================================================== FileInfo[] lAllBackups = Array.ConvertAll<string, FileInfo>(Directory.GetFiles(lBackupPath, Path.GetFileNameWithoutExtension(lForm.BinaryFileTextBox.Text) + ".*.bak"), new Converter<string, FileInfo>(delegate(string xiFilename) { return new FileInfo(xiFilename); })); Utils.ArrayStableSort(lAllBackups, x => x.CreationTime); for (int ii = (int)lForm.BackupCountUpDown.Value; ii < lAllBackups.Length; ii++) { lAllBackups[ii].Delete(); } } //===================================================================== // Save the binary file //===================================================================== using (FileStream lFileStream = lBinaryFile.Create()) { CurrentLevel.Serialise(lFileStream); } if (lForm.UpdateCDImageCheckBox.Checked) { //=================================================================== // Update the CD image //=================================================================== FileInfo lCDFile = new FileInfo(lForm.CDImageTextBox.Text); CDImage lImage = new CDImage(lCDFile); MMCD.Course lCourse = (MMCD.Course)lForm.CourseDropDown.SelectedItem; byte[] lBinaryData = new byte[lCourse.CDLength]; lBinaryFile.Refresh(); if (lBinaryFile.Length != lCourse.CDLength) { MessageBox.Show("File is the wrong length! It will be padded with zeros or truncated to fit on the CD.", "Publish Course", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } using (FileStream lFileStream = lBinaryFile.OpenRead()) { lFileStream.Read(lBinaryData, 0, (int)Math.Min(lBinaryData.Length, lBinaryFile.Length)); } lImage.Replace(lBinaryData, lCourse.CDOffset); lImage.WriteFile(lCDFile); byte[] lCourseNameForCD = Encoding.ASCII.GetBytes(lCourse.GetCDCourseName(lForm.NameTextBox.Text)); foreach (long lNameOffset in lCourse.NameOffsets) { lImage.Replace(lCourseNameForCD, lNameOffset); lImage.WriteFile(lCDFile); } } if (RootChunk is VersionList) { //=================================================================== // Update the properties saved on the VersionList //=================================================================== VersionList lVersionList = (VersionList)RootChunk; lVersionList.BinaryFilename = lForm.BinaryFileTextBox.Text; if (lForm.UpdateCDImageCheckBox.Checked) { lVersionList.CDFilename = ((MMCD.Course)lForm.CourseDropDown.SelectedItem).FileName; lVersionList.CourseName = lForm.NameTextBox.Text; } //=================================================================== // Save the VersionList //=================================================================== if (mCurrentFile != null) { SaveInternal(mCurrentFileMode, mCurrentFile); } } } }
///======================================================================== /// Static Method : FindCDOffsets /// /// <summary> /// Find the offsets in the CD image of all the courses in the given /// directory (and subdirectories). /// </summary> /// <param name="xiCDImage"></param> /// <param name="xiRootDir"></param> /// <returns></returns> ///======================================================================== private static int FindCDOffsets(FileInfo xiCDImage, DirectoryInfo xiRootDir) { CDImage lCDImage = new CDImage(xiCDImage); //======================================================================= // Find all the levels //======================================================================= Regex lLevelNameRegex = new Regex("[A-Z]+\\\\[A-Z]+[0-9]\\.DAT$", RegexOptions.IgnoreCase); foreach (FileInfo lFile in xiRootDir.GetFiles("*.DAT", SearchOption.AllDirectories)) { //===================================================================== // Read the entire level into memory //===================================================================== byte[] lLevelBytes = new byte[lFile.Length]; using (FileStream lFileStream = lFile.OpenRead()) { lFileStream.Read(lLevelBytes, 0, lLevelBytes.Length); } //===================================================================== // Find the level in the CD image and output //===================================================================== long lIndex = lCDImage.Find(lLevelBytes, 0); if (lIndex > -1) { WriteLine("{0}: {1}", lFile.Name, lIndex); } else { WriteLine("{0}: Not found", lFile.Name); } } return 0; }
private void newToolStripMenuItem_Click(object sender, EventArgs e) { NewForm lForm = new NewForm(this); if (lForm.ShowDialog() == DialogResult.OK) { //===================================================================== // Load the file from the CD image //===================================================================== CDImage lCDImage = new CDImage(new FileInfo(lForm.CDImageTextBox.Text)); MMCD.Course lCourse = (MMCD.Course)lForm.CourseDropDown.SelectedItem; byte[] lLevelBinary = lCDImage.Extract(lCourse.CDOffset, lCourse.CDLength); MemoryStream lLevelStream = new MemoryStream(lLevelBinary); Level lNewLevel = new Level(lLevelStream); //===================================================================== // Check that the whole file has been read //===================================================================== if (lLevelStream.Length != lLevelStream.Position) { throw new DeserialisationException(string.Format("Deserialisation terminated early at byte {0} of {1}", lLevelStream.Position, lLevelStream.Length)); } //===================================================================== // Create a new VersionList based on this level, and set it up //===================================================================== VersionList lVersionList = new VersionList(lNewLevel, lCourse.CourseName, lCourse.FileName); RootChunk = lVersionList; mCurrentFile = null; } }