ScriptFile(.bin)支持仅导出text
剩余部分以.bat形式存储
This commit is contained in:
parent
6516dbde44
commit
5d23d7d09f
@ -1,4 +1,4 @@
|
|||||||
//以下是垃圾代码,仅供参考
|
//以下是垃圾代码,闲人勿入
|
||||||
namespace EscudeTools
|
namespace EscudeTools
|
||||||
{
|
{
|
||||||
public static class Define
|
public static class Define
|
||||||
@ -19,7 +19,7 @@ namespace EscudeTools
|
|||||||
"proc_bgv_fx", "proc_set_param", "proc_get_param", "proc_jump", "proc_date", "proc_flow", "proc_diary",
|
"proc_bgv_fx", "proc_set_param", "proc_get_param", "proc_jump", "proc_date", "proc_flow", "proc_diary",
|
||||||
"proc_unlock", "proc_section", "proc_omake"
|
"proc_unlock", "proc_section", "proc_omake"
|
||||||
];
|
];
|
||||||
|
// 说句实话,我觉得这些定义可能会发生变化
|
||||||
public const byte INST_POP = 1;
|
public const byte INST_POP = 1;
|
||||||
public const byte INST_POP_N = 2;
|
public const byte INST_POP_N = 2;
|
||||||
public const byte INST_POP_RET = 3;
|
public const byte INST_POP_RET = 3;
|
||||||
@ -151,7 +151,7 @@ namespace EscudeTools
|
|||||||
|
|
||||||
case INST_POP_N:
|
case INST_POP_N:
|
||||||
{
|
{
|
||||||
Mark(sf, (uint)c.Parameter);
|
Mark(sf, BitConverter.ToUInt32(c.Parameter));
|
||||||
return $"Pop multiple values";
|
return $"Pop multiple values";
|
||||||
}
|
}
|
||||||
case INST_POP_RET:
|
case INST_POP_RET:
|
||||||
@ -163,7 +163,7 @@ namespace EscudeTools
|
|||||||
case INST_PUSH_RET:
|
case INST_PUSH_RET:
|
||||||
return $"Push the return value";
|
return $"Push the return value";
|
||||||
case INST_PUSH_TEXT:
|
case INST_PUSH_TEXT:
|
||||||
return $"Push a string: {sf.TextString[(uint)c.Parameter]}";
|
return $"Push a string: {sf.TextString[BitConverter.ToUInt32(c.Parameter)]}";
|
||||||
case INST_PUSH_MESS:
|
case INST_PUSH_MESS:
|
||||||
{
|
{
|
||||||
messIndex++;
|
messIndex++;
|
||||||
@ -186,7 +186,7 @@ namespace EscudeTools
|
|||||||
case INST_JMPZ:
|
case INST_JMPZ:
|
||||||
return $"Conditional jump";
|
return $"Conditional jump";
|
||||||
case INST_CALL:
|
case INST_CALL:
|
||||||
return $"Call function offset: {(uint)c.Parameter + 1}";
|
return $"Call function offset: {BitConverter.ToUInt32(c.Parameter) + 1}";
|
||||||
case INST_RET:
|
case INST_RET:
|
||||||
return $"Return";
|
return $"Return";
|
||||||
case INST_LOG_OR:
|
case INST_LOG_OR:
|
||||||
@ -240,7 +240,7 @@ namespace EscudeTools
|
|||||||
case INST_LINE:
|
case INST_LINE:
|
||||||
return $"File line number";
|
return $"File line number";
|
||||||
case INST_PROC:
|
case INST_PROC:
|
||||||
uint index = (uint)c.Parameter;
|
uint index = BitConverter.ToUInt32(c.Parameter);
|
||||||
return $"Execute built-in function: {ProcNames[index]} {SetExtStr(c, sf)}";
|
return $"Execute built-in function: {ProcNames[index]} {SetExtStr(c, sf)}";
|
||||||
case INST_TEXT:
|
case INST_TEXT:
|
||||||
messIndex++;
|
messIndex++;
|
||||||
@ -264,7 +264,7 @@ namespace EscudeTools
|
|||||||
|
|
||||||
private static string SetExtStr(Command c, ScriptFile sf)
|
private static string SetExtStr(Command c, ScriptFile sf)
|
||||||
{
|
{
|
||||||
switch ((uint)c.Parameter)
|
switch (BitConverter.ToUInt32(c.Parameter))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
|
@ -4,8 +4,11 @@
|
|||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
// NOTE
|
||||||
|
// 推荐使用DB Browser for SQLite (https://sqlitebrowser.org/) 查看、编辑导出的数据库文件
|
||||||
|
// 这不是广告,这只是我在开发期间使用的工具
|
||||||
|
|
||||||
////Batch Unpack
|
////Batch Unpack ESC-ARC Package
|
||||||
//if (Directory.Exists(args[0]))
|
//if (Directory.Exists(args[0]))
|
||||||
//{
|
//{
|
||||||
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
||||||
@ -30,64 +33,66 @@
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (Directory.Exists(args[0]) && Directory.Exists(args[1]))
|
////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[] directories = Directory.GetDirectories(args[0]);
|
string[] files = Directory.GetFiles(args[0], "*.bin");
|
||||||
foreach (string directory in directories)
|
foreach (string file in files)
|
||||||
{
|
{
|
||||||
PackManager pm = new();
|
ScriptManager smr = new();
|
||||||
string providerFilePath = Path.Combine(args[1], Path.GetFileName(directory) + ".bin");
|
if (smr.LoadScriptFile(file))
|
||||||
if (pm.Repack(directory, 2,true, providerFilePath))
|
{
|
||||||
Console.WriteLine("Export Database Success");
|
Console.WriteLine($"Load {file} Success");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Export Database Failed");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//if (Directory.Exists(args[0]))
|
|
||||||
//{
|
|
||||||
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
|
||||||
// foreach (string file in files)
|
|
||||||
// {
|
|
||||||
// ScriptManager smr = new();
|
|
||||||
// //目前不支持二次加载
|
|
||||||
// //Todo
|
|
||||||
// //修复
|
|
||||||
// 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 Database Success");
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// Console.WriteLine("Export Database Failed");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (smr.ExportMessDatabase(Path.GetDirectoryName(args[0])))
|
|
||||||
// Console.WriteLine("Export Mess Database Success");
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// Console.WriteLine("Export Mess Database Failed");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//ScriptManager smr = new();
|
//ScriptManager smr = new();
|
||||||
//smr.LoadScriptFile(args[0]); //加载.bin文件
|
//smr.LoadScriptFile(args[0]); //加载.bin文件
|
||||||
//smr.ExportDatabase(Path.GetDirectoryName(args[0]));
|
//smr.ExportDatabase(Path.GetDirectoryName(args[0]));
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"EscudeTools": {
|
"EscudeTools": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"commandLineArgs": "G:\\x221.local\\lab\\unpack_pack\\orgin\\output\r\nG:\\x221.local\\lab\\unpack_pack\\1"
|
"commandLineArgs": "G:\\x221.local\\lab\\test1\\script"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace EscudeTools
|
namespace EscudeTools
|
||||||
@ -32,7 +33,7 @@ namespace EscudeTools
|
|||||||
public uint Offset { get; set; }
|
public uint Offset { get; set; }
|
||||||
public byte Instruction { get; set; }
|
public byte Instruction { get; set; }
|
||||||
public string InstructionString { get; set; }
|
public string InstructionString { get; set; }
|
||||||
public Object Parameter { get; set; }
|
public byte[] Parameter { get; set; }
|
||||||
public String Helper { get; set; }
|
public String Helper { get; set; }
|
||||||
public bool IsProcSet { get; set; }
|
public bool IsProcSet { get; set; }
|
||||||
}
|
}
|
||||||
@ -46,7 +47,6 @@ namespace EscudeTools
|
|||||||
private string name = string.Empty;
|
private string name = string.Empty;
|
||||||
private ScriptFile sf;
|
private ScriptFile sf;
|
||||||
private int messIndex = 0;
|
private int messIndex = 0;
|
||||||
private bool enableCommandHelper = true;
|
|
||||||
|
|
||||||
public ScriptMessage GetSM()
|
public ScriptMessage GetSM()
|
||||||
{
|
{
|
||||||
@ -58,12 +58,6 @@ namespace EscudeTools
|
|||||||
return sf;
|
return sf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ToggleCommandHelper()
|
|
||||||
{
|
|
||||||
enableCommandHelper = !enableCommandHelper;
|
|
||||||
return enableCommandHelper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool LoadScriptFile(string path)
|
public bool LoadScriptFile(string path)
|
||||||
{
|
{
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
@ -106,19 +100,17 @@ namespace EscudeTools
|
|||||||
{
|
{
|
||||||
Instruction = sf.Code[i++],
|
Instruction = sf.Code[i++],
|
||||||
Offset = (uint)i,
|
Offset = (uint)i,
|
||||||
IsProcSet = false
|
IsProcSet = false,
|
||||||
};
|
};
|
||||||
if (enableCommandHelper)
|
c.InstructionString = Define.GetInstructionString(c.Instruction, out int paramNum);
|
||||||
|
if (paramNum > 0)
|
||||||
{
|
{
|
||||||
c.InstructionString = Define.GetInstructionString(c.Instruction, out int paramNum);
|
c.Parameter = new byte[paramNum*4];
|
||||||
for (int j = 0; j < paramNum; j++)
|
Buffer.BlockCopy(sf.Code, i, c.Parameter, 0, 4 * paramNum);
|
||||||
{
|
i += 4 * paramNum;
|
||||||
c.Parameter = Define.TyperHelper(c.Instruction, sf.Code, i);
|
|
||||||
i += 4;
|
|
||||||
}
|
|
||||||
if (sm != null)
|
|
||||||
c.Helper = Define.SetCommandStr(c, sf, sm, ref messIndex);
|
|
||||||
}
|
}
|
||||||
|
if (sm != null)
|
||||||
|
c.Helper = Define.SetCommandStr(c, sf, sm, ref messIndex);
|
||||||
sf.Commands.Add(c);
|
sf.Commands.Add(c);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -195,7 +187,8 @@ namespace EscudeTools
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ExportDatabase(string? storePath)
|
//此导出功能导出的sqlite数据库
|
||||||
|
public bool ExportDatabase(string storePath)
|
||||||
{
|
{
|
||||||
if (sf.Code == null)
|
if (sf.Code == null)
|
||||||
return false;
|
return false;
|
||||||
@ -208,7 +201,8 @@ namespace EscudeTools
|
|||||||
return SqliteProcess(sf, targetPath);
|
return SqliteProcess(sf, targetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ExportMessDatabase(string? storePath)
|
//从ScriptMessage中导出游戏文本
|
||||||
|
public bool ExportMessDatabase(string storePath)
|
||||||
{
|
{
|
||||||
if (sf == null)
|
if (sf == null)
|
||||||
return false;
|
return false;
|
||||||
@ -223,6 +217,37 @@ namespace EscudeTools
|
|||||||
return SqliteProcess(sm, targetPath);
|
return SqliteProcess(sm, targetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//从ScriptFile中导出Text部分,剩余指令部分导出至.dat文件,以便重新封包
|
||||||
|
public bool ExportTextDatabase(string storePath)
|
||||||
|
{
|
||||||
|
if (sf == null)
|
||||||
|
return false;
|
||||||
|
//分成两个文件,一个是放text的sqlite数据库,一个是放code的dat文件
|
||||||
|
|
||||||
|
//dat
|
||||||
|
string datPath = Path.Combine(storePath, name + ".dat");
|
||||||
|
if (File.Exists(datPath))
|
||||||
|
return false;
|
||||||
|
using FileStream fs = new(datPath, FileMode.Create);
|
||||||
|
using BinaryWriter bw = new(fs);
|
||||||
|
bw.Write(FileHeader);//文件头
|
||||||
|
bw.Write(sf.CodeSize);//代码区大小
|
||||||
|
bw.Write(sf.TextCount);//文本数量
|
||||||
|
byte[] empty4B = new byte[4];
|
||||||
|
bw.Write(empty4B);//文本大小(占位)
|
||||||
|
bw.Write(sf.MessCount);//消息数量
|
||||||
|
bw.Write(sf.Code);//代码区
|
||||||
|
|
||||||
|
//sqlite
|
||||||
|
storePath ??= Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException("Unable to determine the directory.");
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
return false;
|
||||||
|
string targetPath = Path.Combine(storePath, "script_text.db");
|
||||||
|
if (!File.Exists(targetPath))
|
||||||
|
Utils.ExtractEmbeddedDatabase(targetPath);
|
||||||
|
return SqliteProcess(sf.TextString, targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
private bool SqliteProcess(ScriptFile sf, string path)
|
private bool SqliteProcess(ScriptFile sf, string path)
|
||||||
{
|
{
|
||||||
using SqliteConnection connection = new($"Data Source={path};");
|
using SqliteConnection connection = new($"Data Source={path};");
|
||||||
@ -240,7 +265,7 @@ namespace EscudeTools
|
|||||||
Offset INTEGER,
|
Offset INTEGER,
|
||||||
Instruction INTEGER,
|
Instruction INTEGER,
|
||||||
InstructionString TEXT,
|
InstructionString TEXT,
|
||||||
Parameter TEXT,
|
Parameter BLOB,
|
||||||
Helper TEXT
|
Helper TEXT
|
||||||
);";
|
);";
|
||||||
using (var createTableCmd = new SqliteCommand(createTableQuery, connection))
|
using (var createTableCmd = new SqliteCommand(createTableQuery, connection))
|
||||||
@ -259,7 +284,9 @@ namespace EscudeTools
|
|||||||
insertCmd.Parameters.AddWithValue("@Offset", command.Offset);
|
insertCmd.Parameters.AddWithValue("@Offset", command.Offset);
|
||||||
insertCmd.Parameters.AddWithValue("@Instruction", command.Instruction);
|
insertCmd.Parameters.AddWithValue("@Instruction", command.Instruction);
|
||||||
insertCmd.Parameters.AddWithValue("@InstructionString", command.InstructionString);
|
insertCmd.Parameters.AddWithValue("@InstructionString", command.InstructionString);
|
||||||
insertCmd.Parameters.AddWithValue("@Parameter", command.Parameter ?? "");
|
insertCmd.Parameters.AddWithValue("@Parameter", (command.Parameter == null)
|
||||||
|
? DBNull.Value
|
||||||
|
: command.Parameter);
|
||||||
insertCmd.Parameters.AddWithValue("@Helper", command.Helper ?? "");
|
insertCmd.Parameters.AddWithValue("@Helper", command.Helper ?? "");
|
||||||
|
|
||||||
insertCmd.ExecuteNonQuery();
|
insertCmd.ExecuteNonQuery();
|
||||||
@ -305,5 +332,57 @@ namespace EscudeTools
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool SqliteProcess(string[] ts,string path)
|
||||||
|
{
|
||||||
|
using SqliteConnection connection = new($"Data Source={path};");
|
||||||
|
connection.Open();
|
||||||
|
|
||||||
|
string checkTableExistsQuery = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{name}';";
|
||||||
|
using (var checkTableCmd = new SqliteCommand(checkTableExistsQuery, connection))
|
||||||
|
{
|
||||||
|
var result = checkTableCmd.ExecuteScalar();
|
||||||
|
if (result != null) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string createTableQuery = $@"
|
||||||
|
CREATE TABLE {name} (
|
||||||
|
Text TEXT
|
||||||
|
);";
|
||||||
|
using (var createTableCmd = new SqliteCommand(createTableQuery, connection))
|
||||||
|
{
|
||||||
|
createTableCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
string insertQuery = $"INSERT INTO {name} (Text) VALUES (@Text);";
|
||||||
|
|
||||||
|
using var transaction = connection.BeginTransaction();
|
||||||
|
using var insertCmd = new SqliteCommand(insertQuery, connection, transaction);
|
||||||
|
|
||||||
|
foreach (var t in ts)
|
||||||
|
{
|
||||||
|
insertCmd.Parameters.Clear();
|
||||||
|
insertCmd.Parameters.AddWithValue("@Text", t ?? "");
|
||||||
|
insertCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.Commit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Repackv1()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Repackv2()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Repackv3()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user