static void Main(string[] args) { Console.WriteLine("FreeMote PSB Converter"); Console.WriteLine("by Ulysses, [email protected]"); FreeMount.Init(); Console.WriteLine($"{FreeMount.PluginsCount} Plugins Loaded."); Console.WriteLine(); var app = new CommandLineApplication(); app.OptionsComparison = StringComparison.OrdinalIgnoreCase; //help app.HelpOption(); app.ExtendedHelpText = PrintHelp(); //options var optKey = app.Option <uint>("-k|--key <KEY>", "PSB key (uint, dec)", CommandOptionType.SingleValue); var optNewKey = app.Option <uint>("-nk|--new-key <KEY>", "New PSB key for transfer (uint, dec)", CommandOptionType.SingleValue); //args var argPath = app.Argument("Files", "File paths", multipleValues: true); //command: pixel app.Command("pixel", pixelCmd => { //help pixelCmd.Description = "Convert pixel colors of extracted images (RGBA BMP/PNG)"; pixelCmd.HelpOption(); pixelCmd.ExtendedHelpText = @" Example: EmtConvert pixel -m Switch02 sample.png "; //options var optMethod = pixelCmd.Option <PsbImageConvertMethod>("-m|--method <METHOD>", "Set convert method", CommandOptionType.SingleValue); //args var argPaths = pixelCmd.Argument("Image", "Image Paths", true); pixelCmd.OnExecute(() => { if (!optMethod.HasValue()) { Console.WriteLine("Convert Method is not specified!"); return; } foreach (var path in argPaths.Values) { if (string.IsNullOrWhiteSpace(path) || !File.Exists(path)) { continue; } int width = 0; int height = 0; PixelFormat pixelFormat = PixelFormat.Format32bppArgb; try { var img = Image.FromFile(path); width = img.Width; height = img.Height; pixelFormat = img.PixelFormat; } catch (Exception e) { Console.WriteLine(e); continue; } var bts = RL.GetPixelBytesFromImageFile(path); switch (optMethod.ParsedValue) { case PsbImageConvertMethod.Switch02: RL.Switch_0_2(ref bts); break; case PsbImageConvertMethod.ROR: RL.Rgba2Argb(ref bts); break; case PsbImageConvertMethod.ROL: RL.Rgba2Argb(ref bts, true); break; case PsbImageConvertMethod.RGBA428: bts = RL.Rgba428(bts); break; case PsbImageConvertMethod.RGBA2L8Grayscale: bts = RL.Rgba2L8(bts); bts = RL.ReadL8(bts, height, width); break; case PsbImageConvertMethod.Untile: bts = PostProcessing.UntileTexture(bts, width, height, pixelFormat); break; case PsbImageConvertMethod.Unswizzle: bts = PostProcessing.UnswizzleTexture(bts, width, height, pixelFormat); break; case PsbImageConvertMethod.Tile: bts = PostProcessing.TileTexture(bts, width, height, pixelFormat); break; case PsbImageConvertMethod.Swizzle: bts = PostProcessing.SwizzleTexture(bts, width, height, pixelFormat); break; default: continue; } RL.ConvertToImageFile(bts, Path.ChangeExtension(path, ".converted.png"), height, width, PsbImageFormat.png); } }); }); //command: pack app.Command("pack", packCmd => { //help packCmd.Description = "Pack/Unpack PSBs to/from shell (FreeMote.Plugins required)"; packCmd.HelpOption(); packCmd.ExtendedHelpText = @" Example: EmtConvert pack -s LZ4 sample.psb "; //options var optType = packCmd.Option("-s|--shell <SHELL>", "Set shell type. No need to specify if unpack", CommandOptionType.SingleValue); //args var argPsbPaths = packCmd.Argument("PSB", "MDF/PSB Paths", true); packCmd.OnExecute(() => { string type = optType.HasValue() ? optType.Value() : null; foreach (var s in argPsbPaths.Values) { if (File.Exists(s)) { ShellConvert(s, type); } } }); }); //command: print app.Command("print", printCmd => { //help printCmd.Description = "Print an EMT PSB (for its initial state, don't expect it working)"; printCmd.HelpOption(); printCmd.ExtendedHelpText = @" Example: EmtConvert print -w 4096 -h 4096 sample.psb "; //options var optWidth = printCmd.Option <int>("-w|--width <INT>", "Set width. Default=-1 (auto)", CommandOptionType.SingleValue); var optHeight = printCmd.Option <int>("-h|--height <INT>", "Set height. Default=-1 (auto)", CommandOptionType.SingleValue); //args var argPsbPaths = printCmd.Argument("PSB", "MDF/PSB Paths", true); printCmd.OnExecute(() => { int width = optWidth.HasValue() ? optWidth.ParsedValue : -1; int height = optHeight.HasValue() ? optHeight.ParsedValue : -1; foreach (var s in argPsbPaths.Values) { if (File.Exists(s)) { Draw(s, width, height); } } }); }); //mdf app.Command("mdf", mdfCmd => { //help mdfCmd.Description = "Pack/Unpack MT19937 encrypted MDF (FreeMote.Plugins required)"; mdfCmd.HelpOption(); mdfCmd.ExtendedHelpText = @" Example: EmtConvert mdf -k 1234567890ab -l 131 sample.psb EmtConvert mdf -s 1234567890absample.psb -l 131 sample.psb Hint: To pack a pure MDF, use `EmtConvert pack -s MDF <MDF file>` "; //options //var optMdfPack = mdfCmd.Option("-p|--pack", // "Pack (Encrypt) a PSB to MT19937 MDF", // CommandOptionType.NoValue); var optMdfSeed = mdfCmd.Option("-s|--seed <SEED>", "Set complete seed (Key+FileName)", CommandOptionType.SingleValue); var optMdfKey = mdfCmd.Option("-k|--key <KEY>", "Set key (Infer file name from path)", CommandOptionType.SingleValue); var optMdfKeyLen = mdfCmd.Option <uint>("-l|--length <LEN>", "Set key length (not required if decrypt all bytes)", CommandOptionType.SingleValue); //args var argPsbPaths = mdfCmd.Argument("PSB", "PSB Paths", true); mdfCmd.OnExecute(() => { string key = optMdfKey.HasValue() ? optMdfKey.Value() : null; string seed = optMdfSeed.HasValue() ? optMdfSeed.Value() : null; if (string.IsNullOrEmpty(key) && string.IsNullOrEmpty(seed)) { //throw new ArgumentNullException(nameof(key), "No key or seed specified."); Console.WriteLine("No key or seed specified. Packing to pure MDF."); foreach (var s in argPsbPaths.Values) { if (File.Exists(s)) { ShellConvert(s, "MDF"); } } return; } Dictionary <string, object> context = new Dictionary <string, object>(); uint?keyLen = optMdfKeyLen.HasValue() ? optMdfKeyLen.ParsedValue : (uint?)null; if (keyLen.HasValue) { context[Context_MdfKeyLength] = keyLen; } foreach (var s in argPsbPaths.Values) { if (File.Exists(s)) { var fileName = Path.GetFileName(s); string finalSeed = seed; if (key != null) { finalSeed = key + fileName; } context[Context_MdfKey] = finalSeed; ShellConvert(s, "MDF", context); } } }); }); app.OnExecute(() => { uint?key = optKey.HasValue() ? optKey.ParsedValue : (uint?)null; uint?newKey = optNewKey.HasValue() ? optNewKey.ParsedValue : (uint?)null; foreach (var s in argPath.Values) { if (File.Exists(s)) { if (key != null && newKey != null) //Transfer { File.WriteAllBytes(Path.ChangeExtension(s, ".converted.psb"), PsbFile.Transfer(key.Value, newKey.Value, File.ReadAllBytes(s))); } else { Convert(key, s); } } } }); if (args.Length == 0) { app.ShowHelp(); Console.WriteLine("Convert all PSBs in current directory:"); AskForKey(); AskForNewKey(); DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory); uint count = 0; foreach (var file in di.EnumerateFiles("*.psb")) { if (NewKey != null) { try { File.WriteAllBytes(Path.ChangeExtension(file.FullName, ".converted.psb"), PsbFile.Transfer(Key.Value, NewKey.Value, File.ReadAllBytes(file.FullName))); count++; } catch (Exception e) { Console.WriteLine("Error: This file is not valid."); Console.WriteLine(e); } } else { if (Convert(Key, file.FullName)) { count++; } } } Console.WriteLine($"Completed! {count} files processed in total."); Console.WriteLine("Press ENTER to exit..."); Console.ReadLine(); return; } app.Execute(args); Console.WriteLine("Done."); }
static void Main(string[] args) { Console.WriteLine("FreeMote PSB Converter"); Console.WriteLine("by Ulysses, [email protected]"); FreeMount.Init(); Console.WriteLine($"{FreeMount.PluginsCount} Plugins Loaded."); Console.WriteLine(); var app = new CommandLineApplication(); app.OptionsComparison = StringComparison.OrdinalIgnoreCase; //help app.HelpOption(); app.ExtendedHelpText = PrintHelp(); //options var optKey = app.Option <uint>("-k|--key <KEY>", "PSB key (uint, dec)", CommandOptionType.SingleValue); var optNewKey = app.Option <uint>("-nk|--new-key <KEY>", "New PSB key for transfer (uint, dec)", CommandOptionType.SingleValue); //args var argPath = app.Argument("Files", "File paths", multipleValues: true); //command: pack app.Command("pack", packCmd => { //help packCmd.Description = "Pack/Unpack PSBs to/from shell (FreeMote.Plugins required)"; packCmd.HelpOption(); packCmd.ExtendedHelpText = @" Example: EmtConvert pack -s LZ4 sample.psb "; //options var optType = packCmd.Option("-s|--shell <SHELL>", "Set shell type. No need to specify if unpack", CommandOptionType.SingleValue); //args var argPsbPaths = packCmd.Argument("PSB", "MDF/PSB Paths", true); packCmd.OnExecute(() => { string type = optType.HasValue() ? optType.Value() : null; foreach (var s in argPsbPaths.Values) { if (File.Exists(s)) { ShellConvert(s, type); } } }); }); //command: print app.Command("print", printCmd => { //help printCmd.Description = "Print an EMT PSB (for its initial state, don't expect it working)"; printCmd.HelpOption(); printCmd.ExtendedHelpText = @" Example: EmtConvert print -w 4096 -h 4096 sample.psb "; //options var optWidth = printCmd.Option <int>("-w|--width <INT>", "Set width. Default=-1 (auto)", CommandOptionType.SingleValue); var optHeight = printCmd.Option <int>("-h|--height <INT>", "Set height. Default=-1 (auto)", CommandOptionType.SingleValue); //args var argPsbPaths = printCmd.Argument("PSB", "MDF/PSB Paths", true); printCmd.OnExecute(() => { int width = optWidth.HasValue() ? optWidth.ParsedValue : -1; int height = optHeight.HasValue() ? optHeight.ParsedValue : -1; foreach (var s in argPsbPaths.Values) { if (File.Exists(s)) { Draw(s, width, height); } } }); }); //mdf app.Command("mdf", mdfCmd => { //help mdfCmd.Description = "Pack/Unpack MT19937 encrypted MDF (FreeMote.Plugins required)"; mdfCmd.HelpOption(); mdfCmd.ExtendedHelpText = @" Example: EmtConvert mdf -k 1234567890ab -l 131 sample.psb EmtConvert mdf -s 1234567890absample.psb -l 131 sample.psb Hint: To pack a normal MDF, use `EmtConvert pack -s MDF <MDF file>` "; //options //var optMdfPack = mdfCmd.Option("-p|--pack", // "Pack (Encrypt) a PSB to MT19937 MDF", // CommandOptionType.NoValue); var optMdfSeed = mdfCmd.Option("-s|--seed <SEED>", "Set complete seed (Key+FileName)", CommandOptionType.SingleValue); var optMdfKey = mdfCmd.Option("-k|--key <KEY>", "Set key (Infer file name from path)", CommandOptionType.SingleValue); var optMdfKeyLen = mdfCmd.Option <uint>("-l|--length <LEN>", "Set key length (not required if decrypt all bytes)", CommandOptionType.SingleValue); //args var argPsbPaths = mdfCmd.Argument("PSB", "PSB Paths", true); mdfCmd.OnExecute(() => { string key = optMdfKey.HasValue() ? optMdfKey.Value() : null; string seed = optMdfSeed.HasValue() ? optMdfSeed.Value() : null; if (string.IsNullOrEmpty(key) && string.IsNullOrEmpty(seed)) { throw new ArgumentNullException(nameof(key), "No key or seed specified."); } uint?keyLen = optMdfKeyLen.HasValue() ? optMdfKeyLen.ParsedValue : (uint?)null; Dictionary <string, object> context = new Dictionary <string, object>(); if (keyLen.HasValue) { context["MdfKeyLength"] = keyLen; } foreach (var s in argPsbPaths.Values) { if (File.Exists(s)) { var fileName = Path.GetFileName(s); string finalSeed = seed; if (key != null) { finalSeed = key + fileName; } context["MdfKey"] = finalSeed; ShellConvert(s, "MDF", context); } } }); }); app.OnExecute(() => { uint?key = optKey.HasValue() ? optKey.ParsedValue : (uint?)null; uint?newKey = optNewKey.HasValue() ? optNewKey.ParsedValue : (uint?)null; foreach (var s in argPath.Values) { if (File.Exists(s)) { if (key != null && newKey != null) //Transfer { File.WriteAllBytes(Path.ChangeExtension(s, ".converted.psb"), PsbFile.Transfer(key.Value, newKey.Value, File.ReadAllBytes(s))); } else { Convert(key, s); } } } }); if (args.Length == 0) { app.ShowHelp(); Console.WriteLine("Convert all PSBs in current directory:"); AskForKey(); AskForNewKey(); DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory); uint count = 0; foreach (var file in di.EnumerateFiles("*.psb")) { if (NewKey != null) { try { File.WriteAllBytes(Path.ChangeExtension(file.FullName, ".converted.psb"), PsbFile.Transfer(Key.Value, NewKey.Value, File.ReadAllBytes(file.FullName))); count++; } catch (Exception e) { Console.WriteLine("Error: This file is not valid."); Console.WriteLine(e); } } else { if (Convert(Key, file.FullName)) { count++; } } } Console.WriteLine($"Completed! {count} files processed in total."); Console.WriteLine("Press ENTER to exit..."); Console.ReadLine(); return; } app.Execute(args); Console.WriteLine("Done."); }
static void Main(string[] args) { Console.WriteLine("FreeMote PSB Converter"); Console.WriteLine("by Ulysses, [email protected]"); Console.WriteLine(); if (args.Length >= 3) { if (!File.Exists(args[0])) { Console.WriteLine("File not exists."); return; } uint key; if (!uint.TryParse(args[1], out key)) { Console.WriteLine("Key is not valid."); return; } Key = key; if (!uint.TryParse(args[2], out key)) { Console.WriteLine("New key is not valid."); return; } NewKey = key; byte[] bytes = File.ReadAllBytes(args[0]); File.WriteAllBytes(args[0] + ".converted", PsbFile.Transfer(Key.Value, NewKey.Value, bytes)); } else if (args.Length == 2) { if (!File.Exists(args[0])) { Console.WriteLine("File not exists."); return; } uint key; if (!uint.TryParse(args[1], out key)) { Console.WriteLine("Key is not valid."); return; } Key = key; Convert(Key, args[0]); } else if (args.Length == 1) { if (!File.Exists(args[0])) { PrintHelp(); return; } AskForKey(); Convert(Key, args[0]); } else { PrintHelp(); AskForKey(); AskForNewKey(); DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory); uint count = 0; foreach (var file in di.EnumerateFiles("*.psb")) { if (NewKey != null) { try { File.WriteAllBytes(file.FullName + ".converted", PsbFile.Transfer(Key.Value, NewKey.Value, File.ReadAllBytes(file.FullName))); count++; } catch (Exception e) { Console.WriteLine("Error: This file is not valid."); Console.WriteLine(e); } } else { if (Convert(Key, file.FullName)) { count++; } } } Console.WriteLine($"Completed! {count} files processed in total."); Console.WriteLine("Press ENTER to exit..."); Console.ReadLine(); } }