public void TestConvertCommon2Win() { var resPath = Path.Combine(Environment.CurrentDirectory, @"..\..\Res"); var path = Path.Combine(resPath, "akira_guide-pure.psb"); //PSB psb = PsbCompiler.LoadPsbFromJsonFile(path); PSB psb = new PSB(path); psb.SwitchSpec(PsbSpec.win); psb.Merge(); File.WriteAllBytes("emote_common2win.psb", psb.Build()); }
public void TestConvertWin2Ems() { var resPath = Path.Combine(Environment.CurrentDirectory, @"..\..\Res"); var path = Path.Combine(resPath, "ca01_s_body_2.psz.psb-pure.psb"); //PSB psb = PsbCompiler.LoadPsbFromJsonFile(path); PSB psb = new PSB(path); psb.SwitchSpec(PsbSpec.ems); psb.Merge(); File.WriteAllBytes("emote_win2ems.psb", psb.Build()); }
public void TestConvertKrkr2Win() { var resPath = Path.Combine(Environment.CurrentDirectory, @"..\..\Res"); //var path = Path.Combine(resPath, "澄怜a_裸.psb-pure.psb"); var path = Path.Combine(resPath, "澄怜a_裸.psb-pure.psb.json"); //var path = Path.Combine(resPath, "e-mote38_KRKR-pure.psb.json"); //var path = Path.Combine(resPath, "e-mote38_KRKR-pure.psb"); PSB psb = PsbCompiler.LoadPsbFromJsonFile(path); //PSB psb = new PSB(path); psb.SwitchSpec(PsbSpec.win); psb.Merge(); File.WriteAllBytes("emote_krkr2win.psb", psb.Build()); File.WriteAllText("emote_krkr2win.json", PsbDecompiler.Decompile(psb)); RL.ConvertToImageFile(psb.Resources.First().Data, "tex-in-psb.png", 4096, 4096, PsbImageFormat.Png, PsbPixelFormat.WinRGBA8); }
private static void Port(string s, PsbSpec portSpec) { var name = Path.GetFileNameWithoutExtension(s); var ext = Path.GetExtension(s); Console.WriteLine($"Converting {name} to {portSpec} platform..."); PSB psb = new PSB(s); if (psb.Platform == portSpec) { Console.WriteLine("Already at the same platform, Skip."); } else { psb.SwitchSpec(portSpec); psb.Merge(); File.WriteAllBytes(Path.ChangeExtension(s, $".{portSpec}.psb"), psb.Build()); Console.WriteLine($"Convert {name} succeed."); } }
public void TestGraft() { var resPath = Path.Combine(Environment.CurrentDirectory, @"..\..\Res"); //var path = Path.Combine(resPath, "澄怜a_裸.psb-pure.psb.json"); var path = Path.Combine(resPath, "e-mote38_KRKR-pure.psb.json"); var path2 = Path.Combine(resPath, "e-mote38_win-pure.psb.json"); PSB psbKrkr = PsbCompiler.LoadPsbFromJsonFile(path); PSB psbWin = PsbCompiler.LoadPsbFromJsonFile(path2); psbWin.SwitchSpec(PsbSpec.krkr); //var metadata = (PsbDictionary)psbWin.Objects["metadata"]; //metadata["attrcomp"] = psbKrkr.Objects["metadata"].Children("attrcomp"); psbWin.Merge(); ////Graft var resKrkr = psbKrkr.CollectResources(false); var resWin = psbWin.CollectResources(false); var headWin = resWin.FirstOrDefault(r => r.Height == 186 && r.Width == 122); var headKrkr = resKrkr.FirstOrDefault(r => r.Height == 186 && r.Width == 122); if (headWin != null && headKrkr != null) { headWin.Resource.Data = headKrkr.Resource.Data; } //foreach (var resourceMetadata in resWin) //{ // var sameRes = resKrkr.FirstOrDefault(r => r.Height == resourceMetadata.Height && r.Width == resourceMetadata.Width); // if (sameRes != null) // { // Console.WriteLine($"{sameRes} {sameRes.Width}x{sameRes.Height} found."); // resourceMetadata.Resource.Data = sameRes.Resource.Data; // } //} psbWin.Merge(); File.WriteAllBytes("emote_win2krkr.psb", psbWin.Build()); //File.WriteAllText("emote_krkr2win.json", PsbDecompiler.Decompile(psb2)); }
/// <summary> /// Load PSB From Json file /// </summary> /// <param name="inputPath">Json file path</param> /// <param name="inputResPath">Resource Json file</param> /// <param name="version">PSB version</param> /// <returns></returns> public static PSB LoadPsbFromJsonFile(string inputPath, string inputResPath = null, ushort?version = null) { if (string.IsNullOrEmpty(inputPath)) { throw new FileNotFoundException("Can not find input json file."); } if (string.IsNullOrEmpty(inputResPath) || !File.Exists(inputResPath)) { inputResPath = Path.ChangeExtension(inputPath, ".resx.json"); if (!File.Exists(inputResPath)) { inputResPath = Path.ChangeExtension(inputPath, ".res.json"); } } string inputResJson = null; string baseDir = Path.GetDirectoryName(inputPath); if (File.Exists(inputResPath)) { inputResJson = File.ReadAllText(inputResPath); baseDir = Path.GetDirectoryName(inputPath); } //Parse PSB psb = Parse(File.ReadAllText(inputPath), version ?? 3); //Link if (!string.IsNullOrWhiteSpace(inputResJson)) { if (inputResJson.Trim().StartsWith("{")) //resx.json { PsbResourceJson resx = JsonConvert.DeserializeObject <PsbResourceJson>(inputResJson); if (resx.PsbType != null) { psb.Type = resx.PsbType.Value; } if (resx.PsbVersion != null && version == null) { psb.Header.Version = resx.PsbVersion.Value; } if (resx.ExternalTextures) { Console.WriteLine("[INFO] External Texture mode ON, no resource will be compiled."); } else { psb.Link(resx, baseDir); } if (resx.Platform != null) { psb.SwitchSpec(resx.Platform.Value, resx.Platform.Value.DefaultPixelFormat()); } } else { List <string> resources = JsonConvert.DeserializeObject <List <string> >(inputResJson); psb.Link(resources, baseDir); } } if (version != null) { psb.Header.Version = version.Value; } psb.Merge(); return(psb); }
static void Main(string[] args) { Console.WriteLine("FreeMote MMO Decompiler (Preview)"); Console.WriteLine("by Ulysses, [email protected]"); FreeMount.Init(); Console.WriteLine(); Console.WriteLine("This is a preview version. If it crashes, send the PSB to me."); Console.WriteLine("All output files from this tool should follow [CC BY-NC-SA 4.0] license. Agree this license by pressing Enter:"); Console.ReadLine(); if (args.Length < 1 || !File.Exists(args[0])) { return; } PSB psb = null; try { psb = new PSB(args[0]); } catch (Exception e) { Console.WriteLine("Input PSB is invalid."); } if (psb != null) { psb.FixMotionMetadata(); //Fix for partial exported PSB if (psb.Platform != PsbSpec.krkr) { if (psb.Platform == PsbSpec.common || psb.Platform == PsbSpec.win) { psb.SwitchSpec(PsbSpec.krkr); psb.Merge(); } else { Console.WriteLine( $"EmtMake do not support {psb.Platform} PSB. Please use pure krkr PSB."); goto END; } } #if !DEBUG try #endif { MmoBuilder builder = new MmoBuilder(); var output = builder.Build(psb); output.Merge(); File.WriteAllBytes(Path.ChangeExtension(args[0], ".FreeMote.mmo"), output.Build()); } #if !DEBUG catch (Exception e) { Console.WriteLine(e); } #endif } END: Console.WriteLine("Done."); Console.ReadLine(); }
/// <summary> /// Compile Json to PSB /// </summary> /// <param name="inputJson">Json text</param> /// <param name="inputResJson">Resource Json text</param> /// <param name="baseDir">If resource Json uses relative paths (usually it does), specify the base dir</param> /// <param name="version">PSB version</param> /// <param name="cryptKey">CryptKey, use null for pure PSB</param> /// <param name="spec">PSB Platform</param> /// <param name="keepShell">If true, try to compress PSB to shell type (MDF/LZ4 etc.) specified in resx.json; otherwise just output PSB</param> /// <returns></returns> public static byte[] Compile(string inputJson, string inputResJson, string baseDir = null, ushort?version = null, uint?cryptKey = null, PsbSpec?spec = null, bool keepShell = true) { var context = FreeMount.CreateContext(); //Parse PSB psb = Parse(inputJson, version ?? 3); //Link if (!string.IsNullOrWhiteSpace(inputResJson)) { if (inputResJson.Trim().StartsWith("{")) //resx.json { PsbResourceJson resx = JsonConvert.DeserializeObject <PsbResourceJson>(inputResJson); if (resx.PsbType != null) { psb.Type = resx.PsbType.Value; } if (resx.PsbVersion != null && version == null) { psb.Header.Version = resx.PsbVersion.Value; } if (resx.Platform != null && spec == null) { spec = resx.Platform; } if (resx.CryptKey != null & cryptKey == null) { cryptKey = resx.CryptKey; } context = FreeMount.CreateContext(resx.Context); if (resx.HasExtraResources) { PsbResHelper.LinkExtraResources(psb, context, resx.ExtraResources, resx.ExtraFlattenArrays, baseDir); } if (resx.ExternalTextures) { #if DEBUG Console.WriteLine("[INFO] External Texture mode ON, no resource will be compiled."); #endif } else { psb.Link(resx, baseDir); } } else { List <string> resources = JsonConvert.DeserializeObject <List <string> >(inputResJson); psb.Link(resources, baseDir); } } //Build psb.Merge(); if (spec != null && spec != psb.Platform) { psb.SwitchSpec(spec.Value, spec.Value.DefaultPixelFormat()); psb.Merge(); } var bytes = psb.Build(); //Convert if (cryptKey != null) { bytes = PsbFile.EncodeToBytes(cryptKey.Value, bytes, EncodeMode.Encrypt, EncodePosition.Auto); } if (context.HasShell && keepShell) { using var outStream = context.PackToShell(new MemoryStream(bytes)); bytes = outStream.ToArray(); } return(bytes); }