示例#1
0
        /// <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, if you need to use it outside FreeMote</param>
        /// <param name="spec">PSB Platform</param>
        /// <returns></returns>
        public static byte[] Compile(string inputJson, string inputResJson, string baseDir = null, ushort?version = null, uint?cryptKey = null,
                                     PsbSpec?spec = null)
        {
            //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;
                    }

                    if (resx.ExternalTextures)
                    {
                        Console.WriteLine("[INFO] External Texture mode ON, no resource will be compiled.");
                    }
                    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
            return(cryptKey != null?PsbFile.EncodeToBytes(cryptKey.Value, bytes, EncodeMode.Encrypt, EncodePosition.Auto) : bytes);
        }
示例#2
0
        public void TestWin2Krkr2Win()
        {
            var resPath  = Path.Combine(Environment.CurrentDirectory, @"..\..\Res");
            var pathGood = Path.Combine(resPath, "goodstr.freemote.psb");
            var psb      = new PSB(pathGood);

            psb.SwitchSpec(PsbSpec.krkr, PsbSpec.krkr.DefaultPixelFormat());
            psb.Merge();
            psb.SwitchSpec(PsbSpec.win, PsbSpec.win.DefaultPixelFormat());
            psb.Merge();
            psb.BuildToFile("convert2.psb");
        }
示例#3
0
        /// <summary>
        /// Convert a PSB to External Texture PSB.
        /// </summary>
        /// <param name="inputPath"></param>
        /// <param name="outputUnlinkedPsb">output unlinked PSB if you need</param>
        /// <param name="order"></param>
        /// <param name="format"></param>
        public static void UnlinkToFile(string inputPath, bool outputUnlinkedPsb = true, PsbLinkOrderBy order = PsbLinkOrderBy.Name, PsbImageFormat format = PsbImageFormat.Png)
        {
            if (!File.Exists(inputPath))
            {
                return;
            }

            var name    = Path.GetFileNameWithoutExtension(inputPath);
            var dirPath = Path.Combine(Path.GetDirectoryName(inputPath), name);

            if (File.Exists(dirPath))
            {
                name    += "-resources";
                dirPath += "-resources";
            }

            if (!Directory.Exists(dirPath)) //ensure there is no file with same name!
            {
                Directory.CreateDirectory(dirPath);
            }

            var psb  = new PSB(inputPath);
            var texs = psb.Unlink();

            if (outputUnlinkedPsb)
            {
                psb.Merge();
                var psbSavePath = Path.ChangeExtension(inputPath, ".unlinked.psb");
                File.WriteAllBytes(psbSavePath, psb.Build());
            }

            var texExt    = format == PsbImageFormat.Bmp ? ".bmp" :".png";
            var texFormat = format == PsbImageFormat.Bmp ? ImageFormat.Bmp : ImageFormat.Png;

            switch (order)
            {
            case PsbLinkOrderBy.Convention:
                foreach (var tex in texs)
                {
                    tex.Save(Path.Combine(dirPath, tex.Tag + texExt), texFormat);
                }
                break;

            case PsbLinkOrderBy.Name:
                foreach (var tex in texs)
                {
                    tex.Save(Path.Combine(dirPath, $"{name}_{tex.Tag}{texExt}"), texFormat);
                }
                break;

            case PsbLinkOrderBy.Order:
                for (var i = 0; i < texs.Count; i++)
                {
                    var tex = texs[i];
                    tex.Save(Path.Combine(dirPath, $"{i}{texExt}"), texFormat);
                }
                break;
            }
        }
示例#4
0
        public void TestConvertWin2Krkr()
        {
            var resPath = Path.Combine(Environment.CurrentDirectory, @"..\..\Res");

            //var path = Path.Combine(resPath, "e-mote38_win-pure.psb.json");
            var path = Path.Combine(resPath, "e-mote38_win-pure.psb");
            //var path = Path.Combine(resPath, "dx_e-mote3.0ショコラパジャマa-pure.psb.json");
            //PSB psb = PsbCompiler.LoadPsbFromJsonFile(path);
            PSB psb = new PSB(path);

            psb.SwitchSpec(PsbSpec.krkr);
            //Common2KrkrConverter converter = new Common2KrkrConverter();
            //converter.Convert(psb);
            psb.Merge();
            File.WriteAllBytes("emote_test_front.psb", psb.Build());
            File.WriteAllText("emote_test_front.json", PsbDecompiler.Decompile(psb));
            psb.SwitchSpec(PsbSpec.win);
            psb.Merge();
            File.WriteAllBytes("emote_2x.psb", psb.Build());
        }
示例#5
0
        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());
        }
示例#6
0
        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());
        }
示例#7
0
        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));
        }
示例#8
0
        public void TestInline()
        {
            var resPath = Path.Combine(Environment.CurrentDirectory, @"..\..\Res");
            var path    = Path.Combine(resPath, "2001010400_00_mid.pure.psb");
            var texPath = Path.Combine(resPath, "2001010400_00_mid_tex000.png");
            PSB psb     = new PSB(path);

            psb.Link(new List <string> {
                texPath
            }, order: PsbLinkOrderBy.Order);
            psb.Merge();
            File.WriteAllBytes("inline.psb", psb.Build());
            PSB p2 = new PSB("inline.psb");
        }
示例#9
0
        public void TestConvertCommon2Krkr()
        {
            var resPath = Path.Combine(Environment.CurrentDirectory, @"..\..\Res");

            var path = Path.Combine(resPath, "akira_guide-pure.psb.json");
            PSB psb  = PsbCompiler.LoadPsbFromJsonFile(path);

            Common2KrkrConverter converter = new Common2KrkrConverter();

            converter.Convert(psb);
            psb.Merge();
            File.WriteAllBytes("emote_test_front.psb", psb.Build());
            File.WriteAllText("emote_test_front.json", PsbDecompiler.Decompile(psb));
        }
示例#10
0
        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);
        }
示例#11
0
        /// <summary>
        /// Convert a PSB to External Texture PSB.
        /// </summary>
        /// <param name="inputPath"></param>
        /// <param name="outputUnlinkedPsb">output unlinked PSB; otherwise only output textures</param>
        /// <param name="order"></param>
        /// <param name="format"></param>
        /// <returns>The unlinked PSB path</returns>
        public static string UnlinkToFile(string inputPath, bool outputUnlinkedPsb = true, PsbLinkOrderBy order = PsbLinkOrderBy.Name, PsbImageFormat format = PsbImageFormat.png)
        {
            if (!File.Exists(inputPath))
            {
                return(null);
            }

            var name        = Path.GetFileNameWithoutExtension(inputPath);
            var dirPath     = Path.Combine(Path.GetDirectoryName(inputPath), name);
            var psbSavePath = inputPath;

            if (File.Exists(dirPath))
            {
                name    += "-resources";
                dirPath += "-resources";
            }

            if (!Directory.Exists(dirPath)) //ensure there is no file with same name!
            {
                Directory.CreateDirectory(dirPath);
            }

            var context = FreeMount.CreateContext();

            context.ImageFormat = format;
            var psb = new PSB(inputPath);

            if (psb.TypeHandler is BaseImageType imageType)
            {
                imageType.UnlinkToFile(psb, context, name, dirPath, outputUnlinkedPsb, order);
            }

            psb.TypeHandler.UnlinkToFile(psb, context, name, dirPath, outputUnlinkedPsb, order);

            if (outputUnlinkedPsb)
            {
                psb.Merge();
                psbSavePath = Path.ChangeExtension(inputPath, ".unlinked.psb"); //unlink only works with motion.psb so no need for ext rename
                File.WriteAllBytes(psbSavePath, psb.Build());
            }

            return(psbSavePath);
        }
示例#12
0
        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.");
            }
        }
示例#13
0
        public void TestGraft2()
        {
            var resPath  = Path.Combine(Environment.CurrentDirectory, @"..\..\Res");
            var pathGood = Path.Combine(resPath, "goodstr.freemote.psb");
            var pathBad  = Path.Combine(resPath, "goodStr.psb");

            var psbGood = new PSB(pathGood);
            var psbBad  = new PSB(pathBad);

            dynamic texGood = (PsbDictionary)psbGood.Objects["source"].Children("tex");
            dynamic texBad  = (PsbDictionary)psbBad.Objects["source"].Children("tex#000");
            var     badIcon = texBad["icon"];

            PsbDictionary newIcon = new PsbDictionary();

            foreach (var part in texGood["icon"])
            {
                var content = part.Value;
                var bi      = ((PsbDictionary)badIcon).FirstOrDefault(i =>
                                                                      ((PsbNumber)i.Value.Children("width")).AsInt == content["width"].AsInt &&
                                                                      ((PsbNumber)i.Value.Children("height")).AsInt == content["height"].AsInt &&
                                                                      ((PsbNumber)i.Value.Children("originX")).AsFloat == content["originX"].AsFloat &&
                                                                      ((PsbNumber)i.Value.Children("originY")).AsFloat == content["originY"].AsFloat);

                if (bi.Key != null)
                {
                    newIcon[bi.Key] = content;
                }
            }

            texGood["icon"] = newIcon;

            dynamic badSource = psbBad.Objects["source"];

            badSource["tex#000"] = texGood;

            psbBad.Merge();
            psbBad.BuildToFile("graft.psb");
        }
示例#14
0
        private static void Link(string psbPath, List <string> texPaths, PsbLinkOrderBy order)
        {
            if (!File.Exists(psbPath))
            {
                return;
            }

            var name = Path.GetFileNameWithoutExtension(psbPath);
            var ext  = Path.GetExtension(psbPath);

            try
            {
                List <string> texs = new List <string>();
                foreach (var texPath in texPaths)
                {
                    if (File.Exists(texPath))
                    {
                        texs.Add(texPath);
                    }
                    else if (Directory.Exists(texPath))
                    {
                        texs.AddRange(Directory.EnumerateFiles(texPath));
                    }
                }

                PSB psb = new PSB(psbPath);
                psb.Link(texs, order: order, isExternal: true);
                psb.Merge();
                File.WriteAllBytes(Path.ChangeExtension(psbPath, "linked" + ext), psb.Build());
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            Console.WriteLine($"Link {name} succeed.");
        }
示例#15
0
        /// <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);
        }
示例#16
0
        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();
        }
示例#17
0
        /// <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);
        }