using System; using System.Collections.Generic; using System.IO; using System.Text; using dq8chr2glb.Container; using dq8chr2glb.Converter; using dq8chr2glb.Converter.GLTF; using dq8chr2glb.Core.InfoCfg; using dq8chr2glb.Core.MDSFormat; using dq8chr2glb.Core.MOTFormat; using dq8chr2glb.Logger; using SixLabors.ImageSharp; using Texture = dq8chr2glb.TM2Format.Texture; namespace dq8chr2glb; public class ChrFile { public bool Extract; public bool Convert; public bool TextFormat; public void Process(string inputPath, string outputPath) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); var ctx = new Context(); ctx.InputPath = inputPath; ctx.ModelName = Path.GetFileNameWithoutExtension(ctx.InputPath); ctx.OutputPath = Path.Combine(outputPath, ctx.ModelName); var chrData = File.ReadAllBytes(ctx.InputPath); var container = Container.ChrFile.FromBytes(chrData); EnsurePath(ctx.OutputPath); foreach (var file in container) { PrintTask(file); switch (file.Extension) { case FileExtension.CFG: ProcessConfig(file); break; case FileExtension.TEXT: ProcessTextFile(file); break; case FileExtension.TM2: ProcessTextures(file); break; case FileExtension.MDS: ProcessMDSFile(file); break; case FileExtension.MOT: ProcessMOTFile(file); break; default: ProcessRawFile(file); break; } } if (Convert) { foreach (var converter in Context.Current.MdsConverters) { converter.Save(ctx.OutputPath, TextFormat); } } foreach (var err in Context.Current.Errors) { Log.Line($"{err.Name}, {err.Text}", LogLevel.Error); if (err.Exception != null) { Log.Error(err.Exception); } } foreach (var err in Context.Current.Messages) { Log.Line($"{err.Name}, {err.Text}"); } } private void PrintTask(IncludedFile file) { var spaces = 30 - file.Name.Length; if (spaces <= 0) { spaces = 1; } var spacer = new string('.', spaces); Log.Line($" Process: {file.Name + spacer} {file.Data.Length} bytes"); } private void EnsurePath(string path) { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } } private void ProcessMOTFile(IncludedFile file) { if (Extract) { ProcessRawFile(file); } if (Convert) { foreach (var converter in Context.Current.MdsConverters) { var motImporter = new Importer(); var animation = motImporter.Import(file.Data); converter.AddAnimation(animation, Context.Current.InfoCfg); } } } private void ProcessMDSFile(IncludedFile file) { if (Extract) { ProcessRawFile(file); } var mdsScene = Reader.Read(file.Data, file.Name); if (mdsScene == null) { Context.Current.Errors.Add(new Error(file.Name, "mdsScene is empty!")); return; } if (Convert) { var converter = new MDSConverter(file.Name); var rootName = Path.GetFileNameWithoutExtension(file.Name); converter.Convert(mdsScene, Context.Current.Textures, rootName); Context.Current.MdsConverters.Add(converter); } } private void ProcessConfig(IncludedFile file) { if (Extract) { var isSecond = Context.Current.InfoCfg != null; if (isSecond) { file.Name = file.Name.Replace(".cfg", "_2.cfg"); } ProcessTextFile(file); } var data = Encoding.GetEncoding("shift_jis").GetString(file.Data).TrimEnd('\0'); var configFile = new ConfigFile(data); var info = configFile.ReadConfig(); if (Context.Current.InfoCfg == null) { Context.Current.InfoCfg = info; } } private void ProcessTextFile(IncludedFile file) { try { var root = Path.GetDirectoryName(file.Name); var fileName = Path.GetFileName(file.Name); var outputPath = Path.Combine(Context.Current.OutputPath, root); var text = Encoding.GetEncoding("shift_jis").GetString(file.Data).TrimEnd('\0'); if (string.IsNullOrEmpty(text)) { Context.Current.Errors.Add(new Error(file.Name, "Text data is empty!")); return; } if (Extract) { EnsurePath(outputPath); File.WriteAllText(Path.Combine(outputPath, fileName), text); } } catch (Exception e) { Context.Current.Errors.Add(new Error(file.Name, "Error while process text file", e)); } } private void ProcessRawFile(IncludedFile file) { try { var root = Path.GetDirectoryName(file.Name); var fileName = Path.GetFileName(file.Name); var outputPath = Path.Combine(Context.Current.OutputPath, root); if (Extract) { EnsurePath(outputPath); File.WriteAllBytes(Path.Combine(outputPath, fileName), file.Data); } } catch (Exception e) { Context.Current.Errors.Add(new Error(file.Name, $"File extraction failed", e)); } } private void ProcessTextures(IncludedFile file) { var root = Path.GetDirectoryName(file.Name); var fileName = Path.GetFileNameWithoutExtension(file.Name); var outputPath = Path.Combine(Context.Current.OutputPath, root); var image = TM2Format.TM2Format.GetImage(file, fileName); if (Extract && image != null && image.Data != null) { EnsurePath(outputPath); image.Data.SaveAsPng(Path.Combine(outputPath, fileName + ".png")); } Context.Current.Textures.Add(image); } }