支持EV图像合成

This commit is contained in:
Chenx221 2024-10-24 23:08:32 +08:00
parent f38fc2c4cc
commit a6f10be546
Signed by: chenx221
GPG Key ID: D7A9EC07024C3021
6 changed files with 729 additions and 432 deletions

View File

@ -1,243 +1,30 @@
using ImageMagick;
using System.Text;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace EscudeTools
{
public class Image
{
//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 string pixel; // address of the pixel data
public uint pitch;
public string palette;
}
public class LsfImage
{
//public bool cache; // Cache flag
public Image img; // Layer image
}
public class LsfData
{
//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 string pathStr;
public string lsfName;
}
public class LsfFileHeader
{
//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
public int width; // Width in pixels
public int height; // Height in pixels
public int bx; // Base coordinates
public int by; // Base coordinates
}
public class LsfLayerInfo
{
public byte[] name = new byte[64]; // File name
public byte[] text = new byte[64]; // Generic string
public Rect rect; // Layer position
public int cx; // Center coordinates
public int cy; // Center coordinates
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
{
public int left; // Top-left corner X coordinate of the rectangle
public int top; // Top-left corner Y coordinate of the rectangle
public int right; // Bottom-right corner X coordinate of the rectangle
public int bottom; // Bottom-right corner Y coordinate of the rectangle
}
public class CgInfo
{
public int kind; // Image category
public int index; // Image index
public int x; // Coordinates
public int y; // Coordinates
public int scale; // Scale factor
public bool loop; // Loop flag
public byte[] name = new byte[64]; // Registered name
public byte[] file = new byte[64]; // File name
public byte[] option = new byte[128]; // Options
public uint coverd; // White-out ID
public uint filter; // Filter
public uint color; // Color
public uint id; // Image identification ID
public uint loc; // Coordinate list
public uint spot; // Coordinate index
public int order; // CG viewing display order
public uint link; // Related CG
public string nameStr;
public string fileStr;
public string optionStr;
}
public class ImageManager
{
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<LsfData> lsfDatas = [];
private bool preFetchInfo;
public bool LoadLsf(string path, bool preFI = false)
public static bool EvProcess(LsfData ld, int[] n, string target)
{
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++)
//get base size
int height = ld.lfh.height, width = ld.lfh.width;
using var baseImage = new MagickImage(MagickColors.Transparent, (uint)width, (uint)height);
for (int i = 0; i < n.Length; 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;
}
string imgPath = ld.layer[n[i]].img.fileStr;
using var overlayImage = new MagickImage(imgPath);
int offsetX = ld.lli[n[i]].rect.left;
int offsetY = ld.lli[n[i]].rect.top;
int mode = ld.lli[n[i]].mode;
baseImage.Composite(overlayImage, offsetX, offsetY, (mode == 3) ? CompositeOperator.Multiply : ((mode == 10) ? CompositeOperator.Plus : CompositeOperator.Over));
}
lsfDatas.Add(lsfData);
lsfData = new();
baseImage.Write(target);
return true;
}
private LsfFileHeader LoadLsfHeader(string path)
public static bool STProcess()
{
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;
throw new NotImplementedException();
}
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;
}
}
}

244
EscudeTools/LsfManager.cs Normal file
View File

@ -0,0 +1,244 @@
using ImageMagick;
using System.Text;
namespace EscudeTools
{
public class Image
{
//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 string pixel; // address of the pixel data
public uint pitch;
public string palette;
}
public class LsfImage
{
//public bool cache; // Cache flag
public Image img; // Layer image
}
public class LsfData
{
//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 string pathStr;
public string lsfName;
}
public class LsfFileHeader
{
//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
public int width; // Width in pixels
public int height; // Height in pixels
public int bx; // Base coordinates
public int by; // Base coordinates
}
public class LsfLayerInfo
{
public byte[] name = new byte[64]; // File name
public byte[] text = new byte[64]; // Generic string
public Rect rect; // Layer position
public int cx; // Center coordinates
public int cy; // Center coordinates
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
{
public int left; // Top-left corner X coordinate of the rectangle
public int top; // Top-left corner Y coordinate of the rectangle
public int right; // Bottom-right corner X coordinate of the rectangle
public int bottom; // Bottom-right corner Y coordinate of the rectangle
}
public class CgInfo
{
public int kind; // Image category
public int index; // Image index
public int x; // Coordinates
public int y; // Coordinates
public int scale; // Scale factor
public bool loop; // Loop flag
public byte[] name = new byte[64]; // Registered name
public byte[] file = new byte[64]; // File name
public byte[] option = new byte[128]; // Options
public uint coverd; // White-out ID
public uint filter; // Filter
public uint color; // Color
public uint id; // Image identification ID
public uint loc; // Coordinate list
public uint spot; // Coordinate index
public int order; // CG viewing display order
public uint link; // Related CG
public string nameStr;
public string fileStr;
public string optionStr;
}
public class LsfManager
{
static readonly byte[] lsfFileSignature = [0x4C, 0x53, 0x46, 0x00];
static readonly byte[] lsfLayerSkipSignature = [0x00, 0x75, 0x6C, 0x00]; //flowchat部分的lsf块
private static string WorkPath = string.Empty;
private LsfData lsfData = new();
private Dictionary<string, LsfData> lsfDataLookup = new();
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).ToLower();
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;
}
}
lsfDataLookup[lsfData.lsfName] = lsfData;
lsfData = new();
return true;
}
public LsfData? FindLsfDataByName(string name)
{
lsfDataLookup.TryGetValue(name.ToLower(), out var lsfData);
return lsfData; // 如果未找到,则返回 null
}
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

@ -1,226 +1,408 @@
namespace EscudeTools
using Microsoft.Data.Sqlite;
namespace EscudeTools
{
internal class Program
{
static void Main(string[] args)
{
if (Directory.Exists(args[0]))
if (Directory.Exists(args[0]) && File.Exists(args[1]))
//if (File.Exists(args[0]))
{
string graphicsDBPath = args[1];
using SqliteConnection connection = new($"Data Source={graphicsDBPath};");
connection.Open();
List<string> tableNames = [];
string[] foundTN = new string[2];
List<int> tableIds = [];
bool found1 = false, found2 = false;
using (var command = new SqliteCommand("SELECT name FROM sqlite_master WHERE type='table';", connection))
using (var reader = command.ExecuteReader())
{
int id = 0;
while (reader.Read())
{
string tableName = reader.GetString(0);
if (tableName.StartsWith("イベント"))
{
foundTN[0] = tableName;
found1 = true;
}
else if (tableName.StartsWith("立ち"))
{
foundTN[1] = tableName;
found2 = true;
}
tableNames.Add(tableName);
tableIds.Add(id++);
}
}
if (!(found1 && found2))
{
for (int i = 0; i < tableNames.Count; i++)
Console.WriteLine($"{tableIds[i]}: {tableNames[i]}");
if (!found1)
{
Console.WriteLine("自动识别失败请选择存放CG信息的数据表ID: ");
string? input = Console.ReadLine();
if (int.TryParse(input, out int userInputId))
{
if (userInputId >= 0 && userInputId < tableIds.Count)
{
foundTN[0] = tableNames[userInputId];
}
else
{
Console.WriteLine("Invalid ID.");
return;
}
}
else
{
Console.WriteLine("Invalid input. Please enter a valid number.");
return;
}
}
if (!found2)
{
Console.WriteLine("自动识别失败请选择存放立绘信息的数据表ID: ");
string? input = Console.ReadLine();
if (int.TryParse(input, out int userInputId))
{
if (userInputId >= 0 && userInputId < tableIds.Count)
{
foundTN[1] = tableNames[userInputId];
}
else
{
Console.WriteLine("Invalid ID.");
return;
}
}
else
{
Console.WriteLine("Invalid input. Please enter a valid number.");
return;
}
}
}
List<EvTable> evts = [];
List<StTable> stts = [];
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[0]};", connection))
{
using var reader = command.ExecuteReader();
while (reader.Read())
{
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
continue;
evts.Add(new EvTable
{
name = reader.GetString(0),
file = reader.GetString(1),
option = reader.GetString(2).Split(' '),
coverd = (uint)reader.GetInt32(3),
filter = (uint)reader.GetInt32(4),
color = (uint)reader.GetInt32(5),
id = (uint)reader.GetInt32(6),
loc = (uint)reader.GetInt32(7),
order = reader.GetInt32(8),
link = (uint)reader.GetInt32(9)
});
}
}
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[1]};", connection))
{
using var reader = command.ExecuteReader();
while (reader.Read())
{
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
continue;
stts.Add(new StTable
{
name = reader.GetString(0),
file = reader.GetString(1),
option = reader.GetString(2).Split(' '),
coverd = (uint)reader.GetInt32(3),
filter = (uint)reader.GetInt32(4),
color = (uint)reader.GetInt32(5),
id = (uint)reader.GetInt32(6),
loc = (uint)reader.GetInt32(7),
order = reader.GetInt32(8),
link = (uint)reader.GetInt32(9)
});
}
}
string[] files = Directory.GetFiles(args[0], "*.lsf", SearchOption.AllDirectories);
ImageManager im = new();
LsfManager lm = new();
foreach (string file in files)
{
if (im.LoadLsf(file))
if (lm.LoadLsf(file, true))
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");
// }
// }
connection.Close();
string outputDir = Path.Combine(Path.GetDirectoryName(args[0]), "Output");
if (!Directory.Exists(outputDir))
Directory.CreateDirectory(outputDir);
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = 6 // 设置最大并行线程数
};
Parallel.ForEach(evts, parallelOptions, evt =>
//foreach (EvTable evt in evts)
{
if (evt.order == 0) //仅提取鉴赏中有的CG
return;
//continue;
string targetFilename = Path.Combine(outputDir, evt.name + ".png"); //最后保存可用的文件名(这里还没有后缀)
LsfData lsfData = lm.FindLsfDataByName(evt.file) ?? throw new Exception("Something Wrong");
List<int> pendingList = [];
foreach (string o in evt.option)
{
int t = TableManagercs.ParseOptions(lsfData, o);
if (t == -1)
continue;
pendingList.Add(t);
}
if (pendingList[0] != 0)
pendingList.Insert(0, 0);
if (!ImageManager.EvProcess(lsfData, [.. pendingList], targetFilename))
throw new Exception("Process Fail");
else
Console.WriteLine($"Export {evt.name} Success");
});
//}
////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 <filepath>] [-d <directory>] [-s <filepath>] [-h]");
// Console.WriteLine("Options:");
// Console.WriteLine(" <filepath> Single lsf process");
// Console.WriteLine(" -r <filepath> Read single lsf file");
// Console.WriteLine(" -d <directory> Process all lsf files in directory");
// Console.WriteLine(" -s <filepath> Same as <filepath>");
// Console.WriteLine(" -h Display help info");
//}
}
//// 批量读取lsf文件
//if (Directory.Exists(args[0]))
//{
// string[] files = Directory.GetFiles(args[0], "*.lsf", SearchOption.AllDirectories);
// LsfManager lm = new();
// foreach (string file in files)
// {
// if (lm.LoadLsf(file, true))
// 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 <filepath>] [-d <directory>] [-s <filepath>] [-h]");
// Console.WriteLine("Options:");
// Console.WriteLine(" <filepath> Single lsf process");
// Console.WriteLine(" -r <filepath> Read single lsf file");
// Console.WriteLine(" -d <directory> Process all lsf files in directory");
// Console.WriteLine(" -s <filepath> Same as <filepath>");
// Console.WriteLine(" -h Display help info");
//}
}
}
}

View File

@ -2,7 +2,7 @@
"profiles": {
"EscudeTools": {
"commandName": "Project",
"commandLineArgs": "G:\\x221.local\\lab2"
"commandLineArgs": "G:\\x221.local\\lab2\\ev\\1\r\n\"G:\\x221.local\\lab2\\db_graphics.db\""
}
}
}

View File

@ -0,0 +1,84 @@
using System.Text.RegularExpressions;
namespace EscudeTools
{
public class EvTable
{
public string name;
public string file;
public string[] option;
public uint coverd;
public uint filter;
public uint color;
public uint id;
public uint loc;
public int order;
public uint link;
}
public class StTable
{
public string name;
public string file;
public string[] option;
public uint coverd;
public uint filter;
public uint color;
public uint id;
public uint loc;
public int order;
public uint link;
}
public class TableManagercs
{
public static int ParseOptions(LsfData ld, string input)
{
// 正则表达式匹配 p*:* 格式
Regex regex = new(@"p(\d+):(\d+)");
MatchCollection matches = regex.Matches(input);
List<int> results = [];
foreach (Match match in matches)
{
if (match.Groups.Count == 3)
{
if (int.TryParse(match.Groups[1].Value, out int firstNumber) &&
int.TryParse(match.Groups[2].Value, out int secondNumber))
{
results.Add(firstNumber);//index
results.Add(secondNumber);//state //可能要+1
}
}
}
for (int i = 0; i < ld.lli.Length; i++)
{
if (ld.lli[i].index == 0 && ld.lli[i].state == 0)
{
if (ld.lli[i].index == results[0] && ld.lli[i].state + 1 == results[1])
return i;
}
if (ld.lli[i].index == results[0] && ld.lli[i].state == results[1])
return i;
}
//一般可以忽略这个警告
Console.WriteLine($"[WARN] Found invalid index:state data {results[0]}:{results[1]} in {ld.lsfName}, may be a bug?");
return -1;
}
public static int ParseCharactor(string input)
{
// 使用正则表达式匹配格式 * _ *
Regex regex = new(@"^(\d+)_.*$");
var match = regex.Match(input);
if (match.Success && match.Groups.Count > 1)
{
if (int.TryParse(match.Groups[1].Value, out int result))
{
return result;
}
}
return 0;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 KiB