支持读取lsf文件

mot看了下,写到一半感觉没意义就删了
This commit is contained in:
Chenx221 2024-10-22 14:49:25 +08:00
parent be30d3751a
commit f38fc2c4cc
Signed by: chenx221
GPG Key ID: D7A9EC07024C3021
3 changed files with 384 additions and 219 deletions

View File

@ -1,39 +1,53 @@
namespace EscudeTools using ImageMagick;
using System.Text;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace EscudeTools
{ {
public class Image public class Image
{ {
public byte[] filename = new byte[64]; // Image file name //public byte[] file = new byte[64]; // Image file name
public int page; // Image memory //public int page; // Image memory
public int back_page; // Back 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 width; // Width
public int height; // Height public int height; // Height
public int depth; // Color depth public int depth; // Color depth
public int id; // ID public string pixel; // address of the pixel data
public int reff; // Reference counter public uint pitch;
public bool cache; // Cache flag public string palette;
public bool isFile; // Is it an image file
public uint[] extra = new uint[8]; // Reserved
public string filenameStr; // 自己加的,用于保存文件名
} }
public class LsfImage public class LsfImage
{ {
public bool cache; // Cache flag //public bool cache; // Cache flag
public Image img; // Layer image public Image img; // Layer image
} }
public class LsfData 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 LsfFileHeader lfh; // LSF file header
public LsfLayerInfo lli; // LSF layer information public LsfLayerInfo[] lli; // LSF layer information
public LsfImage layer; // LSF layer image public LsfImage[] layer; // LSF layer image
public string pathStr; public string pathStr;
public string lsfName;
} }
public class LsfFileHeader public class LsfFileHeader
{ {
public uint signature = 0x46534C; // Header signature (LSF) //public uint signature; // Header signature (LSF) 0x46534C
public ushort revision; // Revision number (0x0001) public ushort revision; // Revision number
public ushort bg; // Background flag public ushort bg; // Background flag
public ushort id; // ID public ushort id; // ID
public ushort layer_count; // Number of layers public ushort layer_count; // Number of layers
@ -49,15 +63,22 @@
public Rect rect; // Layer position public Rect rect; // Layer position
public int cx; // Center coordinates public int cx; // Center coordinates
public int cy; // Center coordinates public int cy; // Center coordinates
public string index; // Position public byte index; // Position
public string state; // State public byte state; // State
public string mode; // Drawing mode public byte mode; // Drawing mode
public string opacity; // Opacity public byte opacity; // Opacity
public uint fill; // Fill color public uint fill; // Fill color
public uint value; // Generic value public uint value; // Generic value
public string nameStr; // 自己加的,用于保存文件名 public string nameStr; // 自己加的,用于保存文件名
public string textStr; // 自己加的,用于保存通用名 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 public class Rect
{ {
@ -90,10 +111,133 @@
public string fileStr; public string fileStr;
public string optionStr; public string optionStr;
} }
public class ImageManager public class ImageManager
{ {
private static Image image; static readonly byte[] lsfFileSignature = [0x4C, 0x53, 0x46, 0x00];
//Todo: Implement ImageManager static readonly byte[] lsfLayerSkipSignature = [0x00, 0x75, 0x6C, 0x00]; //flowchat部分的lsf块
//Lots of methods and properties to implement 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<LsfData> 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;
}
} }
} }

View File

@ -4,6 +4,26 @@
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
if (Directory.Exists(args[0]))
{
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 // NOTE
// 推荐使用DB Browser for SQLite (https://sqlitebrowser.org/) 查看、编辑导出的数据库文件 // 推荐使用DB Browser for SQLite (https://sqlitebrowser.org/) 查看、编辑导出的数据库文件
// 这不是广告,这只是我在开发期间使用的工具 // 这不是广告,这只是我在开发期间使用的工具
@ -92,23 +112,23 @@
// } // }
//} //}
//Export Full Script ////Export Full Script
if (File.Exists(args[0])) //fail //lost 1 //something diff //if (File.Exists(args[0])) //fail //lost 1 //something diff
{ //{
ScriptManager.Repackv1(args[0], true); // ScriptManager.Repackv1(args[0], true);
} //}
//Export ScriptMessage ////Export ScriptMessage
if (File.Exists(args[1])) //pass //if (File.Exists(args[1])) //pass
{ //{
ScriptManager.Repackv2(args[1], true); // ScriptManager.Repackv2(args[1], true);
} //}
////Export ScriptFile //////Export ScriptFile
if (File.Exists(args[2])) //pass //if (File.Exists(args[2])) //pass
{ //{
ScriptManager.Repackv3(args[2]); // ScriptManager.Repackv3(args[2]);
} //}
@ -202,4 +222,5 @@
} }
} }
}
} }

View File

@ -2,7 +2,7 @@
"profiles": { "profiles": {
"EscudeTools": { "EscudeTools": {
"commandName": "Project", "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"
} }
} }
} }