private CPKBuildObject FilterCPKFile(FileLocationMeta file, string sourceDirectoryPath, string targetDirectoryPath) { var cpkFile = new CPK(new Tools()); // this function gets a bit confusings since file, cpkFile and embeddedFile are all thrown around - i will need to fix that var filePath = Path.Combine(sourceDirectoryPath, file.subPath, file.fileName); if (!cpkFile.ReadCPK(filePath, ActiveEncodings.currentEncoding)) { string errorMessage = string.Format("Unknown error while attempting to open {0}.", filePath); MessageBox.Show(errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // this could be replaced with a custom form that allows the user to skip all errors or a simple "errors while opening X files" after the files are done being read. though, the later option would require a small restructuring of the code. Environment.Exit(1); } int realFileCount = 0; foreach (var embeddedFile in cpkFile.FileTable) { if (embeddedFile.FileType.ToString() == "FILE") { realFileCount += 1; } } if (realFileCount == 0) { string errorMessage = string.Format("CPK file {0} was empty.", filePath); // i am not sure this should be a fatal error - i will attempt to come back to it once i have a more complete picture of how the build system works and thus have a better idea of how to handle such an eventuality MessageBox.Show(errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Environment.Exit(1); } CPKBuildObject cpkBuildInstructions = new CPKBuildObject(); string originalFileLocation = Path.Combine(ProjectFolder.extractedISODir, file.subPath, file.fileName); cpkBuildInstructions.SetOriginalFileLocation(originalFileLocation); string targetFileLocation = Path.Combine(ProjectFolder.repackedGameFilesDir, file.subPath, file.fileName); cpkBuildInstructions.SetTargetFileLocation(targetFileLocation); if (realFileCount > 1) // if there is more than one file in the CPK we move the files within it to their own directory { string newSubDir = Path.GetFileNameWithoutExtension(file.fileName); string newSubPath = Path.Combine(file.subPath, newSubDir); file.subPath = newSubPath; } foreach (var embeddedFile in cpkFile.FileTable) { var cpkMeta = new CPKEmbeddedFileMeta(); if (embeddedFile.FileType != "FILE") { continue; // skip headers etc. } if (FileParser.IsParseable(embeddedFile.FileName.ToString())) // use this to determine whether to unpack or not, not save location { file.switchPath = editableDirectory; } else { file.switchPath = rawDirectory; } string targetFileAbsolutePath = Path.Combine(targetDirectoryPath, ProjectFolder.unpackedGameFilesDir, file.subPath, embeddedFile.FileName.ToString()); DirectoryGuard.CheckDirectory(targetFileAbsolutePath); byte[] fileAsBytes = GrabCPKData(filePath, embeddedFile); if (DebugSettings.ATTEMPT_DECOMPRESSION) { if (fileAsBytes.Length >= 8) // 8 = length of "CRILAYLA" { byte[] crilaylaCheck = new byte[8]; Array.Copy(fileAsBytes, 0, crilaylaCheck, 0, 8); string crilaylaString = Encoding.ASCII.GetString(crilaylaCheck); if (crilaylaString == "CRILAYLA") { byte[] decompressedBytes = cpkFile.DecompressCRILAYLA(fileAsBytes, fileAsBytes.Length); fileAsBytes = decompressedBytes; } } } if (DebugSettings.ALLOW_FILE_WRITES) { FileStream fs = new FileStream(targetFileAbsolutePath, FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(fileAsBytes); bw.Close(); fs.Close(); } if (DebugSettings.COPY_UNPACKED_FILES) { string secondTargetPath = Path.Combine(targetDirectoryPath, ProjectFolder.reassembledGameFilesDir, file.subPath, embeddedFile.FileName.ToString()); DirectoryGuard.CheckDirectory(secondTargetPath); FileStream fs = new FileStream(secondTargetPath, FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(fileAsBytes); bw.Close(); fs.Close(); } string relativeFilePath = Path.Combine(file.subPath, embeddedFile.FileName.ToString()); uint fileID = (uint)embeddedFile.ID; cpkMeta.filePath = Path.Combine(ProjectFolder.reassembledGameFilesDir, relativeFilePath); cpkMeta.fileName = embeddedFile.FileName.ToString(); cpkMeta.checksumType = Checksum.MD5; cpkMeta.checksumValue = Checksums.GetMD5(fileAsBytes); cpkMeta.ID = fileID; cpkBuildInstructions.AddFile(fileID, cpkMeta); } cpkBuildInstructions.SerializeToDisk(Path.Combine(targetDirectoryPath, ProjectFolder.buildScriptsDir)); return(cpkBuildInstructions); }
public static void RebuildCPKs(object sender, EventArgs e) { BackgroundWorker worker = null; DoWorkEventArgs eventArgs = null; if (sender is BackgroundWorker) { worker = sender as BackgroundWorker; eventArgs = e as DoWorkEventArgs; } else { worker = null; } string buildDir = Path.Combine(rootDir, buildScriptsDir); if (!Directory.Exists(buildDir)) { string errorMessage = string.Format("Could not find build scripts directory at {0}.", buildDir); MessageBox.Show(errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); eventArgs.Result = false; } string[] fileList = Directory.GetFiles(buildDir); int counter = 0; foreach (var file in fileList) { counter++; if (worker != null) { double progress = ((double)counter / (double)fileList.Length) * 100; worker.ReportProgress((int)progress); Thread.Sleep(3); // these are aeshetic sleeps, there to make the progress bar grow steadily so the user doesn't think something might have went wrong } if (worker != null) { if (worker.WorkerSupportsCancellation && worker.CancellationPending) { eventArgs.Result = false; MessageBox.Show("Rebuild CPKs cancelled"); return; } } if (file.EndsWith(".cpk.yaml")) { if (file.EndsWith("movie-movie.cpk.yaml")) // doesn't work for some reason - manually blacklisting { continue; } CPKBuildObject cpk = new CPKBuildObject(); if (!cpk.BuildCPK(file)) { eventArgs.Result = false; } } } Thread.Sleep(1000); // this is another aesthetic sleep, ensuring the the progress bar does not disappear before the user can see it completing using (System.IO.StreamWriter logFile = new System.IO.StreamWriter(buildDir + Path.DirectorySeparatorChar + "build.log", true)) { CPKBuildObject.changedCPKs.ForEach(changedCPK => logFile.WriteLine(changedCPK)); } eventArgs.Result = true; }