/// <summary> /// Iterate recursively through a given directory and its subdirectories and fill the provided list with information on all files contained within /// </summary> /// <param name="leadingPath">The directory to start from</param> /// <param name="subPath">Used to keep track of the current subdirectory that is being iterated though (usually set to "" initially)</param> /// <param name="fileList">The file list which should be populated</param> private bool PopulateFileList(string leadingPath, string subPath, List <FileLocationMeta> fileList) { if (fileListPopulateFailed) // try to quit as fast as possible if there has been an exception { return(false); } string currentAbsolutePath = Path.Combine(leadingPath, subPath); try { var subdirectories = Directory.GetDirectories(currentAbsolutePath); foreach (var subdirectory in subdirectories) { string dirWithoutPath = Path.GetFileName(subdirectory); string newSubPath = Path.Combine(subPath, dirWithoutPath); PopulateFileList(leadingPath, newSubPath, fileList); } var currentDirectoryFiles = Directory.GetFiles(currentAbsolutePath); foreach (var file in currentDirectoryFiles) { string filenameWithoutPath = Path.GetFileName(file); FileLocationMeta newFileData = new FileLocationMeta(); newFileData.leadingPath = leadingPath; newFileData.subPath = subPath; newFileData.fileName = filenameWithoutPath; fileList.Add(newFileData); } return(true); } catch (Exception e) { if (fileListPopulateFailed) // don't bother showing more than one exception message { fileListPopulateFailed = true; string errorMessage = string.Format("There was an error while looking for files in {0}.\r\n\r\n{1}", currentAbsolutePath, e.Message); MessageBox.Show(errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } return(false); } }
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); }