Sfoglia il codice sorgente

Add ability to convert menu files

ghorsington 4 anni fa
parent
commit
51fc7cd9cc

+ 5 - 0
ArcToolkitCLI/ArcToolkitCLI.csproj

@@ -25,6 +25,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <LangVersion>8.0</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -64,10 +65,14 @@
     <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
       <HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
     </Reference>
+    <Reference Include="YamlDotNet, Version=6.0.0.0, Culture=neutral, PublicKeyToken=ec19458f3c15af5e, processorArchitecture=MSIL">
+      <HintPath>..\packages\YamlDotNet.6.1.2\lib\net45\YamlDotNet.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Commands\ConvertCommand.cs" />
     <Compile Include="Commands\Converters\IConverterCommand.cs" />
+    <Compile Include="Commands\Converters\MenuConverter.cs" />
     <Compile Include="Commands\Converters\NeiConverter.cs" />
     <Compile Include="Commands\Converters\TexConverter.cs" />
     <Compile Include="Commands\DecryptCommand.cs" />

+ 177 - 0
ArcToolkitCLI/Commands/Converters/MenuConverter.cs

@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using ArcToolkitCLI.Commands.Options;
+using ArcToolkitCLI.Util;
+using CommandLine;
+using YamlDotNet.Core;
+using YamlDotNet.Serialization;
+
+namespace ArcToolkitCLI.Commands.Converters
+{
+    [Verb("menu", HelpText = "Convert MENU files into YAML and back")]
+    public class MenuConverter : IConverterCommand, IInputOptions, IOutputOptions
+    {
+        private const string MENU_TAG = "CM3D2_MENU";
+
+        public int Run()
+        {
+            var files = Glob.EnumerateFiles(Input);
+            Directory.CreateDirectory(Output);
+
+            if (!files.Any())
+            {
+                Console.WriteLine("No files specified. Run `convert help tex` for help.");
+                return 0;
+            }
+
+            foreach (var file in files)
+            {
+                var result = 0;
+                switch (file.Extension.ToLowerInvariant())
+                {
+                    case ".menu":
+                        if ((result = MenuToYaml(file.FullName)) != 0)
+                            return result;
+                        break;
+                    case ".yaml":
+                        if ((result = YamlToMenu(file.FullName)) != 0)
+                            return result;
+                        break;
+                    default:
+                        Console.WriteLine($"File {file.FullName} is neither .png nor .tex file. Skipping...");
+                        break;
+                }
+            }
+
+            return 0;
+        }
+
+        public IEnumerable<string> Input { get; set; }
+        public string Output { get; set; }
+
+        private int YamlToMenu(string file)
+        {
+            var deserializer = new DeserializerBuilder().Build();
+
+            MenuFile data;
+            try
+            {
+                data = deserializer.Deserialize<MenuFile>(new StreamReader(file, Encoding.UTF8));
+            }
+            catch (YamlException e)
+            {
+                Console.WriteLine($"Failed to read YAML file because {e.Message}: {e.InnerException?.Message}");
+                return 1;
+            }
+
+            using var ms = new MemoryStream();
+            using var dataBw = new BinaryWriter(ms, Encoding.UTF8);
+            using var bw =
+                new BinaryWriter(File.Create(Path.Combine(Output, $"{Path.GetFileNameWithoutExtension(file)}.menu")),
+                                 Encoding.UTF8);
+
+            foreach (var dataMenuEntry in data.MenuEntries)
+            {
+                dataBw.Write((byte)(dataMenuEntry.Data.Count + 1));
+                dataBw.Write(dataMenuEntry.Key);
+                foreach (var s in dataMenuEntry.Data)
+                    dataBw.Write(s);
+            }
+
+            dataBw.Write((byte)0);
+
+            bw.Write(MENU_TAG);
+            bw.Write(data.Version);
+            bw.Write(data.Path);
+            bw.Write(data.Name);
+            bw.Write(data.Part);
+            bw.Write(data.Description);
+
+            var menuData = ms.ToArray();
+            bw.Write(menuData.Length);
+            bw.Write(menuData);
+
+            return 0;
+        }
+
+        private int MenuToYaml(string file)
+        {
+            using var br = new BinaryReader(File.OpenRead(file), Encoding.UTF8);
+            var tag = br.ReadString();
+            if (tag != MENU_TAG)
+            {
+                Console.WriteLine("Provided file is not a valid menu file!");
+                return 1;
+            }
+
+            var menuFile = new MenuFile
+            {
+                Version = br.ReadInt32(),
+                Path = br.ReadString(),
+                Name = br.ReadString(),
+                Part = br.ReadString(),
+                Description = br.ReadString(),
+                MenuEntries = new List<MenuEntry>()
+            };
+
+            br.ReadInt32();
+
+            while (true)
+            {
+                var n1 = br.ReadByte();
+                var strList = new List<string>();
+                if (n1 == 0)
+                    break;
+
+                for (var i = 0; i < n1; i++)
+                    strList.Add(br.ReadString());
+
+                if (strList.Count == 0)
+                    continue;
+
+                if (strList[0] == "end")
+                    break;
+
+                menuFile.MenuEntries.Add(new MenuEntry { Key = strList[0], Data = strList.Skip(1).ToList() });
+            }
+
+            var serializer = new SerializerBuilder().Build();
+            var yaml = serializer.Serialize(menuFile);
+            File.WriteAllText(Path.Combine(Output, $"{Path.GetFileNameWithoutExtension(file)}.yaml"), yaml);
+            return 0;
+        }
+
+        private class MenuEntry
+        {
+            [YamlMember(Alias = "key")]
+            public string Key { get; set; }
+
+            [YamlMember(Alias = "data")]
+            public List<string> Data { get; set; }
+        }
+
+        private class MenuFile
+        {
+            [YamlMember(Alias = "version")]
+            public int Version { get; set; }
+
+            [YamlMember(Alias = "path")]
+            public string Path { get; set; }
+
+            [YamlMember(Alias = "name")]
+            public string Name { get; set; }
+
+            [YamlMember(Alias = "part")]
+            public string Part { get; set; }
+
+            [YamlMember(Alias = "descriptions")]
+            public string Description { get; set; }
+
+            [YamlMember(Alias = "menu_entries")]
+            public List<MenuEntry> MenuEntries { get; set; }
+        }
+    }
+}

+ 1 - 1
ArcToolkitCLI/packages.config

@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-
 <packages>
   <package id="Glob" version="1.1.3" targetFramework="net461" />
   <package id="ILRepack" version="2.0.16" targetFramework="net461" />
@@ -9,4 +8,5 @@
   <package id="System.IO.FileSystem" version="4.3.0" targetFramework="net461" />
   <package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net461" />
   <package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
+  <package id="YamlDotNet" version="6.1.2" targetFramework="net461" />
 </packages>