public void Run() { input += "\\"; String header = input + "HEADER.data"; FileInfo fileInfo; String searchedName; using (FileStream fs = new FileStream(header, FileMode.Open, FileAccess.Read)) using (BinaryReader headerStream = new BinaryReader(fs)) { this.StatusText = "Reading structure..."; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); CPTRStruct cptrData = new CPTRStruct(); DPTRStruct ptrData = new DPTRStruct(headerStream); PKRStruct[] table = ptrData.Files; this.TotalFiles = (int)table.Length; this.CurrentProgress = 0; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); int pkrOffset = 16; byte[] compressedContainer; byte[] ending = { 0, 0, 255, 255 }; byte[] bytes; bytes = PKRStruct.Magic; this.SaveData(ref bytes, outputPkr); bytes = new byte[12]; this.SaveData(ref bytes, outputPkr); bytes = null; for (int i = 0; i < table.Length; ++i) { this.CurrentProgress = i; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); if (ptrData.Filenames.ElementAtOrDefault(table[i].NameID) != null) { this.StatusText = "Importing: " + ptrData.Filenames[table[i].NameID]; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); searchedName = input + ptrData.Filenames[table[i].NameID]; fileInfo = new FileInfo(searchedName); if (fileInfo.Extension.Equals(".lanb") && new FileInfo(searchedName + ".txt").Exists) { this.StatusText = "Converting text data from: " + searchedName + ".txt"; this.ImportLanb(fileInfo.FullName, searchedName + ".txt"); } else if (fileInfo.Name.Equals("48.dat") && new FileInfo(searchedName + ".xml").Exists) { this.StatusText = "Converting font map from: " + searchedName + ".txt"; this.ImportFontMap(fileInfo.FullName, searchedName + ".xml"); } compressedContainer = this.GetFileData(searchedName); table[i].Offset = pkrOffset; table[i].CompressedSize = compressedContainer.Length; table[i].DecompressedSize = (int)fileInfo.Length; this.SaveData(ref compressedContainer, outputPkr); if (table[i].CompressedSize != table[i].DecompressedSize) { this.SaveData(ref ending, outputPkr); } pkrOffset += table[i].CompressedSize; compressedContainer = null; } } // Create new ptr this.StatusText = "Creating new PTR file"; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); using (FileStream ptrStream = new FileStream(outputPtr, FileMode.Append, FileAccess.Write)) using (BinaryWriter ptrWriter = new BinaryWriter(ptrStream)) { ptrWriter.Write(ptrData.FilesCount); ptrWriter.Write(ptrData.Unknown2); ptrWriter.Write(ptrData.Unknown3); ptrWriter.Write(ptrData.Unknown4); ptrWriter.Write(ptrData.Unknown5); for (int i = 0; i < ptrData.UnknownDataset1.Length; ++i) { ptrWriter.Write(ptrData.UnknownDataset1[i]); } for (int i = 0; i < ptrData.UnknownDataset2.Length; ++i) { ptrWriter.Write(ptrData.UnknownDataset2[i]); } ptrWriter.Write(ptrData.NamesLength); ptrWriter.Write(ptrData.NamesCount); ptrWriter.Write(Encoding.UTF8.GetBytes(String.Join("\0", ptrData.Filenames))); for (int i = 0; i < table.Length; ++i) { ptrWriter.Write(table[i].NameID); ptrWriter.Write(table[i].Offset); ptrWriter.Write(table[i].CompressedSize); ptrWriter.Write(table[i].DecompressedSize); } ptrWriter.Write(ptrData.Someshit); } // new PKR hash this.StatusText = "Calculate new PKR hash"; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); byte[] PkrHashData = new byte[0x8000]; using (FileStream pkrfs = new FileStream(outputPkr, FileMode.Open, FileAccess.Read)) using (BinaryReader pkrbr = new BinaryReader(pkrfs)) { pkrbr.BaseStream.Seek(16, SeekOrigin.Begin); PkrHashData = pkrbr.ReadBytes(PkrHashData.Length); } byte[] MD5PkrHash = this.MD5hash(PkrHashData); int MD5FinalPkr = 0; for (int i = 0; i < MD5PkrHash.Length; i += 4) { MD5FinalPkr = MD5FinalPkr ^ BitConverter.ToInt32(MD5PkrHash.Skip(i).Take(4).ToArray(), 0); } // new PTR hash this.StatusText = "Calculate new PTR hash"; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); byte[] MD5PtrHash = this.MD5hash(File.ReadAllBytes(outputPtr)); int MD5FinalPtr = 0; for (int i = 0; i < MD5PtrHash.Length; i += 4) { MD5FinalPtr = MD5FinalPtr ^ BitConverter.ToInt32(MD5PtrHash.Skip(i).Take(4).ToArray(), 0); } cptrData.DecompressedSize = cptrData.CryptSize((int)(new FileInfo(outputPtr).Length)); cptrData.PkrChecksum = MD5FinalPkr; cptrData.PtrChecksum = MD5FinalPtr; byte[] compressedPTR = this.Compress(outputPtr); using (FileStream compressedFS = new FileStream(outputPtr, FileMode.Create, FileAccess.Write)) using (BinaryWriter cPTR = new BinaryWriter(compressedFS)) { cPTR.Write(cptrData.DecompressedSize); cPTR.Write(cptrData.Version); cPTR.Write(cptrData.PkrChecksum); cPTR.Write(cptrData.PtrChecksum); cPTR.Write(compressedPTR); cPTR.Write(ending); } compressedPTR = null; GC.Collect(); GC.WaitForPendingFinalizers(); this.StatusText = "Done"; this.CurrentProgress = this.TotalFiles; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); } }
public void Run() { output += "\\"; String header = output + "HEADER.data"; FileInfo file = new FileInfo(output); Directory.CreateDirectory(file.DirectoryName); using (FileStream fs = new FileStream(input, FileMode.Open, FileAccess.Read)) using (BinaryReader data = new BinaryReader(fs)) { this.StatusText = "Getting PTR structure..."; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); CPTRStruct cptr = new CPTRStruct(data); byte[] compessedData = data.ReadBytes((int)(data.BaseStream.Length - 0x10)); byte[] decompressedPTRData = this.DecompressData(ref compessedData); using (BufferedStream stream = new BufferedStream(new FileStream(header, FileMode.Create, FileAccess.Write))) { stream.Write(decompressedPTRData, 0, decompressedPTRData.Length); } using (BinaryReader ptrData = new BinaryReader(new FileStream(header, FileMode.Open, FileAccess.Read))) { DPTRStruct ptr = new DPTRStruct(ptrData); PKRStruct[] table = ptr.Files; this.TotalFiles = (int)ptr.FilesCount; this.CurrentProgress = 0; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); using (FileStream pkrFS = new FileStream(pkrFile, FileMode.Open, FileAccess.Read)) using (BinaryReader pkr = new BinaryReader(pkrFS)) { byte[] pkrData; string outputFile; FileInfo extractedFile; for (int i = 0; i < ptr.FilesCount; ++i) { this.CurrentProgress = i; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); pkr.BaseStream.Seek(table[i].Offset, SeekOrigin.Begin); if (ptr.Filenames.ElementAtOrDefault(table[i].NameID) != null) { this.StatusText = "Extracting: " + ptr.Filenames[table[i].NameID]; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); outputFile = output + ptr.Filenames[table[i].NameID]; pkrData = pkr.ReadBytes(table[i].CompressedSize); if (table[i].CompressedSize != table[i].DecompressedSize) { pkrData = this.DecompressData(ref pkrData); } extractedFile = new FileInfo(outputFile); this.SaveData(ref pkrData, outputFile); pkrData = null; // File extension is lanb -> convert it. if (extractedFile.Extension.Equals(".lanb")) { this.StatusText = "Converting text file: " + ptr.Filenames[table[i].NameID]; using (FileStream lanbFS = new FileStream(outputFile, FileMode.Open, FileAccess.Read)) using (BinaryReader lanbReader = new BinaryReader(lanbFS)) { LABNStruct lanbData = new LABNStruct(lanbReader); using (StreamWriter lanbWriter = new StreamWriter(outputFile + ".txt")) { for (int j = 0; j < lanbData.StringCount; ++j) { lanbWriter.WriteLine(lanbData.RowsName[j]); lanbWriter.WriteLine(lanbData.RowsText[j]); } } } } // File name is 48.dat -> convert to xml map. (some games 64_df.dat) else if (extractedFile.Name.Equals("48.dat")) { this.StatusText = "Converting font map: " + ptr.Filenames[table[i].NameID]; using (FileStream idfFS = new FileStream(outputFile, FileMode.Open, FileAccess.Read)) using (BinaryReader idfReader = new BinaryReader(idfFS)) { IDFStruct idfData = new IDFStruct(idfReader); IDFCharStruct[] charsData = idfData.CharsData; using (StreamWriter lanbWriter = new StreamWriter(outputFile + ".xml")) { lanbWriter.WriteLine("<GeneralData " + "chars=\"" + idfData.CharsCount + "\" param1=\"" + idfData.Unknown1 + "\" param2=\"" + idfData.Unknown2 + "\" param3=\"" + idfData.Unknown3 + "\" />" ); for (int j = 0; j < charsData.Length; ++j) { lanbWriter.WriteLine("<Char " + "id=\"" + charsData[j].CharID + "\" x=\"" + charsData[j].LeftTopX + "\" y=\"" + charsData[j].LeftTopY + "\" width=\"" + charsData[j].Width + "\" height=\"" + charsData[j].Height + "\" bearingX=\"" + charsData[j].BearingX + "\" bearingY=\"" + charsData[j].BearingY + "\" advanceX=\"" + charsData[j].AdvanceX + "\" advanceY=\"" + charsData[j].AdvanceY + "\" />" ); } } } } } } } } } GC.Collect(); GC.WaitForPendingFinalizers(); this.StatusText = "Done"; this.CurrentProgress = this.TotalFiles; OnProgressUpdate?.Invoke(this.CurrentProgress, this.TotalFiles, this.StatusText); }