From f38fc2c4ccfccd0c56ff7520e5577960a765c16d Mon Sep 17 00:00:00 2001 From: Chenx221 Date: Tue, 22 Oct 2024 14:49:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=AF=BB=E5=8F=96lsf?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20mot=E7=9C=8B=E4=BA=86=E4=B8=8B=EF=BC=8C?= =?UTF-8?q?=E5=86=99=E5=88=B0=E4=B8=80=E5=8D=8A=E6=84=9F=E8=A7=89=E6=B2=A1?= =?UTF-8?q?=E6=84=8F=E4=B9=89=E5=B0=B1=E5=88=A0=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EscudeTools/ImageManager.cs | 192 ++++++++-- EscudeTools/Program.cs | 409 +++++++++++---------- EscudeTools/Properties/launchSettings.json | 2 +- 3 files changed, 384 insertions(+), 219 deletions(-) diff --git a/EscudeTools/ImageManager.cs b/EscudeTools/ImageManager.cs index cee7c59..19cb97d 100644 --- a/EscudeTools/ImageManager.cs +++ b/EscudeTools/ImageManager.cs @@ -1,39 +1,53 @@ -namespace EscudeTools +using ImageMagick; +using System.Text; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace EscudeTools { public class Image { - public byte[] filename = new byte[64]; // Image file name - public int page; // Image memory - public int back_page; // Back image memory + //public byte[] file = new byte[64]; // Image file name + //public int page; // Image memory + //public int back_page; // Back image memory + public uint width; // Width + public uint height; // Height + public uint depth; // Color depth + //public int id; // ID + public int reff; // Reference counter + //public bool cache; // Cache flag + public bool isFile; // Is it an image file + //public uint[] extra = new uint[8]; // Reserved + + public string fileStr; // 自己加的,用于保存文件名 + } + public class GInfo + { public int width; // Width public int height; // Height public int depth; // Color depth - public int id; // ID - public int reff; // Reference counter - public bool cache; // Cache flag - public bool isFile; // Is it an image file - public uint[] extra = new uint[8]; // Reserved - - public string filenameStr; // 自己加的,用于保存文件名 + public string pixel; // address of the pixel data + public uint pitch; + public string palette; } public class LsfImage { - public bool cache; // Cache flag + //public bool cache; // Cache flag public Image img; // Layer image } public class LsfData { - public byte[] path = new byte[64]; // LSF folder + //public byte[] path = new byte[64]; // LSF folder public LsfFileHeader lfh; // LSF file header - public LsfLayerInfo lli; // LSF layer information - public LsfImage layer; // LSF layer image + public LsfLayerInfo[] lli; // LSF layer information + public LsfImage[] layer; // LSF layer image public string pathStr; + public string lsfName; } public class LsfFileHeader { - public uint signature = 0x46534C; // Header signature (LSF) - public ushort revision; // Revision number (0x0001) + //public uint signature; // Header signature (LSF) 0x46534C + public ushort revision; // Revision number public ushort bg; // Background flag public ushort id; // ID public ushort layer_count; // Number of layers @@ -49,15 +63,22 @@ public Rect rect; // Layer position public int cx; // Center coordinates public int cy; // Center coordinates - public string index; // Position - public string state; // State - public string mode; // Drawing mode - public string opacity; // Opacity + public byte index; // Position + public byte state; // State + public byte mode; // Drawing mode + public byte opacity; // Opacity public uint fill; // Fill color public uint value; // Generic value public string nameStr; // 自己加的,用于保存文件名 public string textStr; // 自己加的,用于保存通用名 + public string indexStr; // Position str + public string stateStr; // State str + public string modeStr; // Drawing mode str + public string opacityStr; // Opacity str + + public bool skip = false; // 是否跳过 + } public class Rect { @@ -90,10 +111,133 @@ public string fileStr; public string optionStr; } + public class ImageManager { - private static Image image; - //Todo: Implement ImageManager - //Lots of methods and properties to implement + static readonly byte[] lsfFileSignature = [0x4C, 0x53, 0x46, 0x00]; + static readonly byte[] lsfLayerSkipSignature = [0x00, 0x75, 0x6C, 0x00]; //flowchat部分的lsf块 + static readonly byte[] motV1Signature = [0x6D, 0x6F, 0x74, 0x00]; // mot v1 file signature + static readonly byte[] motV2Signature = [0x4D, 0x4F, 0x54, 0x00]; // MOT v2 file signature + private static string WorkPath = string.Empty; + private LsfData lsfData = new(); + private List lsfDatas = []; + + private bool preFetchInfo; + + public bool LoadLsf(string path, bool preFI = false) + { + if (!File.Exists(path)) + return false; + preFetchInfo = preFI; + lsfData.pathStr = Path.GetDirectoryName(path); + lsfData.lsfName = Path.GetFileNameWithoutExtension(path); + lsfData.lfh = LoadLsfHeader(path); + lsfData.lli = LoadLsfLayerInfo(path); + lsfData.layer = new LsfImage[lsfData.lfh.layer_count]; + for (int i = 0; i < lsfData.lfh.layer_count; i++) + { + string imgPath = Path.Combine(lsfData.pathStr, lsfData.lli[i].nameStr + ".png"); + LsfImage li = new(); + if (!lsfData.lli[i].skip) + { + li.img = LoadLsfImage(imgPath); + lsfData.layer[i] = li; + } + } + lsfDatas.Add(lsfData); + lsfData = new(); + return true; + } + + private LsfFileHeader LoadLsfHeader(string path) + { + using var fs = new FileStream(path, FileMode.Open, FileAccess.Read); + if (fs.Length < 0x1C) + throw new Exception("Invalid LSF Header"); + using var br = new BinaryReader(fs); + byte[] head = br.ReadBytes(4); + if (!head.SequenceEqual(lsfFileSignature)) + throw new Exception("Invalid LSF file"); + LsfFileHeader lfh = new() + { + //lfh.signature = br.ReadUInt32(); //无用 + revision = br.ReadUInt16(), + bg = br.ReadUInt16(), + id = br.ReadUInt16(), + layer_count = br.ReadUInt16(), + width = br.ReadInt32(), + height = br.ReadInt32(), + bx = br.ReadInt32(), + by = br.ReadInt32() + }; + return lfh; + } + + private LsfLayerInfo[] LoadLsfLayerInfo(string path) + { + EncodingProvider provider = CodePagesEncodingProvider.Instance; + Encoding? shiftJis = provider.GetEncoding("shift-jis"); + using var fs = new FileStream(path, FileMode.Open, FileAccess.Read); + using var br = new BinaryReader(fs); + br.ReadBytes(0x1C); // Skip the header + long remainingBytes = br.BaseStream.Length - br.BaseStream.Position; + if (remainingBytes != lsfData.lfh.layer_count * 0xA4) + throw new Exception("Invalid LSF Layer Info"); + LsfLayerInfo[] llis = new LsfLayerInfo[lsfData.lfh.layer_count]; + for (int i = 0; i < lsfData.lfh.layer_count; i++) + { + LsfLayerInfo l = new() + { + name = br.ReadBytes(64), + text = br.ReadBytes(64), + rect = new Rect + { + left = br.ReadInt32(), + top = br.ReadInt32(), + right = br.ReadInt32(), + bottom = br.ReadInt32() + }, + cx = br.ReadInt32(), + cy = br.ReadInt32(), + index = br.ReadByte(), + state = br.ReadByte(), + mode = br.ReadByte(), + opacity = br.ReadByte(), + fill = br.ReadUInt32(), + value = br.ReadUInt32() + }; + if (l.name.Take(4).SequenceEqual(lsfLayerSkipSignature))//临时处理 + l.skip = true; + l.nameStr = shiftJis.GetString(l.name).TrimEnd('\0'); + l.textStr = shiftJis.GetString(l.text).TrimEnd('\0'); + l.indexStr = l.index.ToString().TrimEnd('\0'); + l.stateStr = l.state.ToString().TrimEnd('\0'); + l.modeStr = l.mode.ToString().TrimEnd('\0'); + l.opacityStr = l.opacity.ToString().TrimEnd('\0'); + llis[i] = l; + } + return llis; + } + + private Image LoadLsfImage(string imgPath) + { + if (!File.Exists(imgPath)) + throw new Exception("Image file not found");//一般文件都是存在的,不存在是因为这是特殊lsf + Image i = new() + { + fileStr = imgPath, + isFile = true, + reff = 1 + }; + if (preFetchInfo) + { + using var image = new MagickImage(imgPath); + i.width = image.Width; + i.height = image.Height; + i.depth = image.Depth; + } + return i; + } + } } diff --git a/EscudeTools/Program.cs b/EscudeTools/Program.cs index 8c296ba..14f37b2 100644 --- a/EscudeTools/Program.cs +++ b/EscudeTools/Program.cs @@ -4,202 +4,223 @@ { static void Main(string[] args) { - // NOTE - // 推荐使用DB Browser for SQLite (https://sqlitebrowser.org/) 查看、编辑导出的数据库文件 - // 这不是广告,这只是我在开发期间使用的工具 - - ////Batch Unpack ESC-ARC Package - //if (Directory.Exists(args[0])) - //{ - // string[] files = Directory.GetFiles(args[0], "*.bin"); - // PackManager pm = new(); - // foreach (string file in files) - // { - // if (pm.Load(file)) - // { - // Console.WriteLine($"Load {file} Success"); - // } - // else - // { - // Console.WriteLine($"Load {file} Failed"); - // } - - // if (pm.Extract()) - // Console.WriteLine("Extract Package Success"); - // else - // { - // Console.WriteLine("Extract Package Failed"); - // } - // } - //} - - ////Batch Repack ESC-ARC Package - //if (Directory.Exists(args[0]) && Directory.Exists(args[1])) - //{ - // string[] directories = Directory.GetDirectories(args[0]); - // foreach (string directory in directories) - // { - // PackManager pm = new(); - // string providerFilePath = Path.Combine(args[1], Path.GetFileName(directory) + ".bin"); - // if (pm.Repack(directory, 2,true, providerFilePath)) - // Console.WriteLine("Repack Package Success"); - // else - // { - // Console.WriteLine("Repack Package Failed"); - // return; - // } - // } - //} - - - ////Batch Unpack Script(Full, Text, Mess) - //if (Directory.Exists(args[0])) - //{ - // string[] files = Directory.GetFiles(args[0], "*.bin"); - // foreach (string file in files) - // { - // ScriptManager smr = new(); - // if (smr.LoadScriptFile(file)) - // { - // Console.WriteLine($"Load {file} Success"); - // } - // else - // { - // Console.WriteLine($"Load {file} Failed"); - // return; - // } - // if (smr.ExportDatabase(Path.GetDirectoryName(args[0]))) - // Console.WriteLine("Export Script Success"); - // else - // { - // Console.WriteLine("Export Script Failed"); - // return; - // } - // if (smr.ExportTextDatabase(Path.GetDirectoryName(args[0]))) - // Console.WriteLine("Export Text Success"); - // else - // { - // Console.WriteLine("Export Text Failed"); - // return; - // } - // if (smr.ExportMessDatabase(Path.GetDirectoryName(args[0]))) - // Console.WriteLine("Export Mess Success"); - // else - // { - // Console.WriteLine("Export Mess Failed"); - // return; - // } - // } - //} - - //Export Full Script - if (File.Exists(args[0])) //fail //lost 1 //something diff + if (Directory.Exists(args[0])) { - ScriptManager.Repackv1(args[0], true); + string[] files = Directory.GetFiles(args[0], "*.lsf", SearchOption.AllDirectories); + ImageManager im = new(); + foreach (string file in files) + { + if (im.LoadLsf(file)) + Console.WriteLine($"Load {file} Success"); + else + { + Console.WriteLine($"Load {file} Failed"); + } + } + Console.WriteLine("OK"); + + + + + + + // NOTE + // 推荐使用DB Browser for SQLite (https://sqlitebrowser.org/) 查看、编辑导出的数据库文件 + // 这不是广告,这只是我在开发期间使用的工具 + + ////Batch Unpack ESC-ARC Package + //if (Directory.Exists(args[0])) + //{ + // string[] files = Directory.GetFiles(args[0], "*.bin"); + // PackManager pm = new(); + // foreach (string file in files) + // { + // if (pm.Load(file)) + // { + // Console.WriteLine($"Load {file} Success"); + // } + // else + // { + // Console.WriteLine($"Load {file} Failed"); + // } + + // if (pm.Extract()) + // Console.WriteLine("Extract Package Success"); + // else + // { + // Console.WriteLine("Extract Package Failed"); + // } + // } + //} + + ////Batch Repack ESC-ARC Package + //if (Directory.Exists(args[0]) && Directory.Exists(args[1])) + //{ + // string[] directories = Directory.GetDirectories(args[0]); + // foreach (string directory in directories) + // { + // PackManager pm = new(); + // string providerFilePath = Path.Combine(args[1], Path.GetFileName(directory) + ".bin"); + // if (pm.Repack(directory, 2,true, providerFilePath)) + // Console.WriteLine("Repack Package Success"); + // else + // { + // Console.WriteLine("Repack Package Failed"); + // return; + // } + // } + //} + + + ////Batch Unpack Script(Full, Text, Mess) + //if (Directory.Exists(args[0])) + //{ + // string[] files = Directory.GetFiles(args[0], "*.bin"); + // foreach (string file in files) + // { + // ScriptManager smr = new(); + // if (smr.LoadScriptFile(file)) + // { + // Console.WriteLine($"Load {file} Success"); + // } + // else + // { + // Console.WriteLine($"Load {file} Failed"); + // return; + // } + // if (smr.ExportDatabase(Path.GetDirectoryName(args[0]))) + // Console.WriteLine("Export Script Success"); + // else + // { + // Console.WriteLine("Export Script Failed"); + // return; + // } + // if (smr.ExportTextDatabase(Path.GetDirectoryName(args[0]))) + // Console.WriteLine("Export Text Success"); + // else + // { + // Console.WriteLine("Export Text Failed"); + // return; + // } + // if (smr.ExportMessDatabase(Path.GetDirectoryName(args[0]))) + // Console.WriteLine("Export Mess Success"); + // else + // { + // Console.WriteLine("Export Mess Failed"); + // return; + // } + // } + //} + + ////Export Full Script + //if (File.Exists(args[0])) //fail //lost 1 //something diff + //{ + // ScriptManager.Repackv1(args[0], true); + //} + + ////Export ScriptMessage + //if (File.Exists(args[1])) //pass + //{ + // ScriptManager.Repackv2(args[1], true); + //} + + //////Export ScriptFile + //if (File.Exists(args[2])) //pass + //{ + // ScriptManager.Repackv3(args[2]); + //} + + + + //ScriptManager smr = new(); + //smr.LoadScriptFile(args[0]); //加载.bin文件 + //smr.ExportDatabase(Path.GetDirectoryName(args[0])); + //smr.ExportMessDatabase(Path.GetDirectoryName(args[0])); + //return; + + + //if (Directory.Exists(args[0])) + //{ + // string[] files = Directory.GetFiles(args[0], "*.db"); + + // foreach (string file in files) + // { + // DatabaseManager.ExportMDB(file); + + // } + //} + + //if (Directory.Exists(args[0])) + //{ + // string[] files = Directory.GetFiles(args[0], "*.bin"); + // DatabaseManager dm = new(); + // foreach (string file in files) + // { + // dm.LoadDatabase(file); + // if (dm.ExportDatabase(Path.GetDirectoryName(args[0]))) + // Console.WriteLine("Export Database Success"); + // } + + //} + + + //if (Directory.Exists(args[0])) + //{ + // string[] files = Directory.GetFiles(args[0], "db_*.bin"); + // DatabaseManager dm = new(); + // foreach (string file in files) + // { + // if (dm.LoadDatabase(file)) + // { + // Console.WriteLine($"Load {file} Success"); + // } + // else + // { + // Console.WriteLine($"Load {file} Failed"); + // return; + // } + + // if (dm.ExportDatabase(Path.GetDirectoryName(args[0]))) + // Console.WriteLine("Export Database Success"); + // else + // { + // Console.WriteLine("Export Database Failed"); + // return; + // } + + // } + + //} + + + // if (args.Length == 0 || args.Length > 2) + // { + // Console.WriteLine("Invalid arguments. Use -h for help."); + // return; + // } + + // switch (args[0]) + // { + // case "-h": + // case "-r": + // case "-d": + // case "-s": + // default: + // break; + // } + //} + //static void DisplayHelp() + //{ + // Console.WriteLine("Usage: EscudeTools.exe [-r ] [-d ] [-s ] [-h]"); + // Console.WriteLine("Options:"); + // Console.WriteLine(" Single lsf process"); + // Console.WriteLine(" -r Read single lsf file"); + // Console.WriteLine(" -d Process all lsf files in directory"); + // Console.WriteLine(" -s Same as "); + // Console.WriteLine(" -h Display help info"); + //} + } - - //Export ScriptMessage - if (File.Exists(args[1])) //pass - { - ScriptManager.Repackv2(args[1], true); - } - - ////Export ScriptFile - if (File.Exists(args[2])) //pass - { - ScriptManager.Repackv3(args[2]); - } - - - - //ScriptManager smr = new(); - //smr.LoadScriptFile(args[0]); //加载.bin文件 - //smr.ExportDatabase(Path.GetDirectoryName(args[0])); - //smr.ExportMessDatabase(Path.GetDirectoryName(args[0])); - //return; - - - //if (Directory.Exists(args[0])) - //{ - // string[] files = Directory.GetFiles(args[0], "*.db"); - - // foreach (string file in files) - // { - // DatabaseManager.ExportMDB(file); - - // } - //} - - //if (Directory.Exists(args[0])) - //{ - // string[] files = Directory.GetFiles(args[0], "*.bin"); - // DatabaseManager dm = new(); - // foreach (string file in files) - // { - // dm.LoadDatabase(file); - // if (dm.ExportDatabase(Path.GetDirectoryName(args[0]))) - // Console.WriteLine("Export Database Success"); - // } - - //} - - - //if (Directory.Exists(args[0])) - //{ - // string[] files = Directory.GetFiles(args[0], "db_*.bin"); - // DatabaseManager dm = new(); - // foreach (string file in files) - // { - // if (dm.LoadDatabase(file)) - // { - // Console.WriteLine($"Load {file} Success"); - // } - // else - // { - // Console.WriteLine($"Load {file} Failed"); - // return; - // } - - // if (dm.ExportDatabase(Path.GetDirectoryName(args[0]))) - // Console.WriteLine("Export Database Success"); - // else - // { - // Console.WriteLine("Export Database Failed"); - // return; - // } - - // } - - //} - - - // if (args.Length == 0 || args.Length > 2) - // { - // Console.WriteLine("Invalid arguments. Use -h for help."); - // return; - // } - - // switch (args[0]) - // { - // case "-h": - // case "-r": - // case "-d": - // case "-s": - // default: - // break; - // } - //} - //static void DisplayHelp() - //{ - // Console.WriteLine("Usage: EscudeTools.exe [-r ] [-d ] [-s ] [-h]"); - // Console.WriteLine("Options:"); - // Console.WriteLine(" Single lsf process"); - // Console.WriteLine(" -r Read single lsf file"); - // Console.WriteLine(" -d Process all lsf files in directory"); - // Console.WriteLine(" -s Same as "); - // Console.WriteLine(" -h Display help info"); - //} - } } } diff --git a/EscudeTools/Properties/launchSettings.json b/EscudeTools/Properties/launchSettings.json index f48662c..3a8b7b3 100644 --- a/EscudeTools/Properties/launchSettings.json +++ b/EscudeTools/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "EscudeTools": { "commandName": "Project", - "commandLineArgs": "\"G:\\x221.local\\lab\\test1\\type1\\script.db\"\r\n\"G:\\x221.local\\lab\\test1\\type2\\script_sm.db\"\r\n\"G:\\x221.local\\lab\\test1\\type3\\script_text.db\"" + "commandLineArgs": "G:\\x221.local\\lab2" } } } \ No newline at end of file