/// <summary> /// Save as pure MDF /// </summary> /// <param name="psb"></param> /// <param name="key"></param> /// <returns></returns> public static byte[] SaveAsMdf(this PSB psb, uint?key = null) { psb.Merge(); var bytes = psb.Build(); Adler32 adler = new Adler32(); uint checksum = 0; if (key == null) { adler.Update(bytes); checksum = (uint)adler.Checksum; } MemoryStream ms = new MemoryStream(bytes); using (MemoryStream fs = new MemoryStream()) { if (key != null) { MemoryStream nms = new MemoryStream((int)ms.Length); PsbFile.Encode(key.Value, EncodeMode.Encrypt, EncodePosition.Auto, ms, nms); ms.Dispose(); ms = nms; var pos = ms.Position; adler.Update(ms); checksum = (uint)adler.Checksum; ms.Position = pos; } BinaryWriter bw = new BinaryWriter(fs); bw.WriteStringZeroTrim(MdfFile.Signature); bw.Write((uint)ms.Length); //bw.Write(ZlibCompress.Compress(ms)); ZlibCompress.CompressToBinaryWriter(bw, ms); bw.WriteBE(checksum); ms.Dispose(); bw.Flush(); return(fs.ToArray()); } }
/// <summary> /// Save PSB as MDF file /// </summary> /// <param name="psb"></param> /// <param name="path"></param> /// <param name="key"></param> public static void SaveAsMdfFile(this PSB psb, string path, uint?key = null) { psb.Merge(); var bytes = psb.Build(); Adler32 checksumer = new Adler32(); uint checksum = 0; if (key == null) { checksumer.Update(bytes); checksum = (uint)checksumer.Checksum; } MemoryStream ms = new MemoryStream(bytes); using (Stream fs = new FileStream(path, FileMode.Create)) { if (key != null) { MemoryStream nms = new MemoryStream((int)ms.Length); PsbFile.Encode(key.Value, EncodeMode.Encrypt, EncodePosition.Auto, ms, nms); ms.Dispose(); ms = nms; var pos = ms.Position; checksumer.Update(ms); checksum = (uint)checksumer.Checksum; ms.Position = pos; } BinaryWriter bw = new BinaryWriter(fs); bw.WriteStringZeroTrim(MdfFile.Signature); bw.Write((uint)ms.Length); bw.Write(ZlibCompress.Compress(ms)); bw.WriteBE(checksum); ms.Dispose(); bw.Flush(); } }
/// <summary> /// Decompile Pure PSB as Json /// </summary> /// <param name="path"></param> /// <param name="psb"></param> /// <param name="context"></param> /// <param name="psbType"></param> /// <returns></returns> public static string Decompile(string path, out PSB psb, Dictionary <string, object> context = null, PsbType psbType = PsbType.PSB) { using var fs = File.OpenRead(path); var ctx = FreeMount.CreateContext(context); string type = null; Stream stream = fs; using var ms = ctx.OpenFromShell(fs, ref type); if (ms != null) { ctx.Context[Consts.Context_PsbShellType] = type; fs.Dispose(); stream = ms; } try { psb = new PSB(stream, false); } catch (PsbBadFormatException e) when(e.Reason == PsbBadFormatReason.Header || e.Reason == PsbBadFormatReason.Array || e.Reason == PsbBadFormatReason.Body) //maybe encrypted { stream.Position = 0; uint?key = null; if (ctx.Context.ContainsKey(Consts.Context_CryptKey)) { key = ctx.Context[Consts.Context_CryptKey] as uint?; } else { key = ctx.GetKey(stream); } stream.Position = 0; if (key != null) //try use key { try { using (var mms = new MemoryStream((int)stream.Length)) { PsbFile.Encode(key.Value, EncodeMode.Decrypt, EncodePosition.Auto, stream, mms); stream.Dispose(); psb = new PSB(mms); ctx.Context[Consts.Context_CryptKey] = key; } } catch { throw e; } } else //key = null { if (e.Reason == PsbBadFormatReason.Header || e.Reason == PsbBadFormatReason.Array) //now try Dullahan loading { psb = PSB.DullahanLoad(stream); } else { throw; } } } if (psbType != PsbType.PSB) { psb.Type = psbType; } return(Decompile(psb)); }
static bool Convert(uint?key, string path) { if (!File.Exists(path)) { Console.WriteLine($"File:{path} not exists."); return(false); } try { using (var fs = new FileStream(path, FileMode.Open)) { Stream stream = fs; string type = null; var ms = FreeMount.CreateContext().OpenFromShell(fs, ref type); bool hasShell = false; if (ms != null) { Console.WriteLine($"Shell type: {type}"); stream = ms; hasShell = true; } BinaryReader br = new BinaryReader(stream, Encoding.UTF8); if (!key.HasValue) { var k = FreeMount.CreateContext().GetKey(stream); if (k != null) { key = k; Console.WriteLine($"Using key: {key}"); } else if (hasShell) { File.WriteAllBytes(Path.ChangeExtension(path, ".decompressed.psb"), ms.ToArray()); return(true); } else { Console.WriteLine("No Key and No Shell."); return(false); } } var header = PsbHeader.Load(br); using (var outMs = new MemoryStream((int)stream.Length)) { if (header.Version > 2) { if (PsbFile.TestHeaderEncrypted(stream, header)) //Decrypt { //psb.EncodeToFile(key.Value, path + ".decrypted", EncodeMode.Decrypt); PsbFile.Encode(key.Value, EncodeMode.Decrypt, EncodePosition.Auto, stream, outMs); File.WriteAllBytes(Path.ChangeExtension(path, ".pure.psb"), outMs.ToArray()); } else { //psb.EncodeToFile(key.Value, path + ".encrypted", EncodeMode.Encrypt); PsbFile.Encode(key.Value, EncodeMode.Encrypt, EncodePosition.Auto, stream, outMs); File.WriteAllBytes(Path.ChangeExtension(path, ".encrypted.psb"), outMs.ToArray()); } } else { if (PsbFile.TestBodyEncrypted(br, header)) //Decrypt { PsbFile.Encode(key.Value, EncodeMode.Decrypt, EncodePosition.Auto, stream, outMs); File.WriteAllBytes(Path.ChangeExtension(path, ".pure.psb"), outMs.ToArray()); } else { PsbFile.Encode(key.Value, EncodeMode.Encrypt, EncodePosition.Auto, stream, outMs); File.WriteAllBytes(Path.ChangeExtension(path, ".encrypted.psb"), outMs.ToArray()); } } } } } catch (Exception e) { Console.WriteLine("Error: This file is not valid."); Console.WriteLine(e); return(false); } return(true); }