예제 #1
0
        /// <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);
            }
        }
예제 #2
0
        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);
        }