Ejemplo n.º 1
0
        public CPKData(string filePath)
        {
            FilePath = filePath;
            CPK      = new CPK(new Tools());
            CPK.ReadCPK(filePath, Encoding);
            Tables = new List <CPKTable>();
            BinaryReader     binaryReader = new BinaryReader(File.OpenRead(filePath));
            List <FileEntry> list         = CPK.FileTable.OrderBy((FileEntry x) => x.FileOffset).ToList();
            int  i    = 0;
            bool flag = Tools.CheckListRedundant(list);

            for (; i < list.Count; i++)
            {
                if (list[i].FileType != null)
                {
                    Nums++;
                    CPKTable cPKTable = new CPKTable();
                    if (list[i].ID == null)
                    {
                        cPKTable.id = -1;
                    }
                    else
                    {
                        cPKTable.id = Convert.ToInt32(list[i].ID);
                    }
                    if (cPKTable.id >= 0 && flag)
                    {
                        cPKTable.FileName = ((list[i].DirName != null) ? string.Concat(list[i].DirName, "/") : "") + $"[{cPKTable.id.ToString()}]" + list[i].FileName;
                    }
                    else
                    {
                        cPKTable.FileName = ((list[i].DirName != null) ? string.Concat(list[i].DirName, "/") : "") + list[i].FileName;
                    }
                    cPKTable.LocalName   = list[i].FileName.ToString();
                    cPKTable.FileOffset  = Convert.ToUInt64(list[i].FileOffset);
                    cPKTable.FileSize    = Convert.ToInt32(list[i].FileSize);
                    cPKTable.ExtractSize = Convert.ToInt32(list[i].ExtractSize);
                    cPKTable.FileType    = list[i].FileType;
                    if (list[i].FileType == "FILE")
                    {
                        cPKTable.Pt = (float)Math.Round((float)cPKTable.FileSize / (float)cPKTable.ExtractSize, 2) * 100f;
                    }
                    else
                    {
                        cPKTable.Pt = 100f;
                    }
                    Tables.Add(cPKTable);
                }
            }
            binaryReader.Close();
        }
Ejemplo n.º 2
0
        // Taken from CriPakTools - see adknowledgements
        private void ReplaceCPKFiles(string sourceCPK, string targetCPK, Dictionary <string, string> batchFileList)
        {
            CPK cpk = new CPK(new Tools());

            cpk.ReadCPK(sourceCPK, ActiveEncodings.currentEncoding);

            BinaryReader oldFile      = new BinaryReader(File.OpenRead(sourceCPK));
            bool         bUseCompress = false; // this could cause problems later if access to compressed files is needed

            FileInfo fi = new FileInfo(sourceCPK);

            string outputName = targetCPK;

            BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName));

            List <FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList();

            Tools tool = new Tools();

            for (int i = 0; i < entries.Count; i++)
            {
                if (entries[i].FileType != "CONTENT")
                {
                    if (entries[i].FileType == "FILE")
                    {
                        // I'm too lazy to figure out how to update the ContextOffset position so this works :)
                        if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset)
                        {
                            ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position;
                            for (ulong z = 0; z < padLength; z++)
                            {
                                newCPK.Write((byte)0);
                            }
                        }
                    }

                    string currentName = ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName;

                    if (!currentName.Contains("/"))
                    {
                        currentName = "/" + currentName;
                    }

                    if (!batchFileList.Keys.Contains(currentName.ToString()))
                    //如果不在表中,复制原始数据
                    {
                        oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin);

                        entries[i].FileOffset = (ulong)newCPK.BaseStream.Position;

                        if (entries[i].FileName.ToString() == "ETOC_HDR")
                        {
                            cpk.EtocOffset = entries[i].FileOffset;
                            Console.WriteLine("Fix ETOC_OFFSET to {0:x8}", cpk.EtocOffset);
                        }

                        cpk.UpdateFileEntry(entries[i]);

                        byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString()));
                        newCPK.Write(chunk);

                        if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1)
                        {
                            long cur_pos = newCPK.BaseStream.Position;
                            for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++)
                            {
                                newCPK.Write((byte)0);
                            }
                        }
                    }
                    else
                    {
                        string replace_with = batchFileList[currentName.ToString()];
                        //Got patch file name
                        Console.WriteLine("Patching: {0}", currentName.ToString());

                        byte[] newbie = File.ReadAllBytes(replace_with);
                        entries[i].FileOffset = (ulong)newCPK.BaseStream.Position;
                        int o_ext_size = Int32.Parse((entries[i].ExtractSize).ToString());
                        int o_com_size = Int32.Parse((entries[i].FileSize).ToString());
                        if ((o_com_size < o_ext_size) && entries[i].FileType == "FILE" && bUseCompress == true)
                        {
                            // is compressed
                            Console.Write("Compressing data:{0:x8}", newbie.Length);

                            byte[] dest_comp = cpk.CompressCRILAYLA(newbie);

                            entries[i].FileSize    = Convert.ChangeType(dest_comp.Length, entries[i].FileSizeType);
                            entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
                            cpk.UpdateFileEntry(entries[i]);
                            newCPK.Write(dest_comp);
                            Console.Write(">> {0:x8}\r\n", dest_comp.Length);
                        }

                        else
                        {
                            Console.Write("Storing data:{0:x8}\r\n", newbie.Length);
                            entries[i].FileSize    = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
                            entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
                            cpk.UpdateFileEntry(entries[i]);
                            newCPK.Write(newbie);
                        }


                        if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1)
                        {
                            long cur_pos = newCPK.BaseStream.Position;
                            for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++)
                            {
                                newCPK.Write((byte)0);
                            }
                        }
                    }
                }
                else
                {
                    // Content is special.... just update the position
                    cpk.UpdateFileEntry(entries[i]);
                }
            }

            cpk.WriteCPK(newCPK);
            cpk.WriteITOC(newCPK);
            cpk.WriteTOC(newCPK);
            cpk.WriteETOC(newCPK, cpk.EtocOffset);
            cpk.WriteGTOC(newCPK);

            newCPK.Close();
            oldFile.Close();
        }
Ejemplo n.º 3
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);
        }