234 lines
6.5 KiB
C#
234 lines
6.5 KiB
C#
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);
|
|
}
|
|
}
|