Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
2f738a1a71 | |||
c9c1919fdd | |||
1b23f31f78 | |||
5ca0fe2e9a | |||
17550bb6b1 | |||
89d9a1d76b | |||
7ebf4beda1 | |||
15d8c8c775 | |||
c7c17002dd | |||
ea52c2128b | |||
3adf8c207a |
@ -3,18 +3,24 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.11.35312.102
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EscudeTools", "EscudeTools\EscudeTools.csproj", "{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EscudeTools", "EscudeTools\EscudeTools.csproj", "{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}.Debug|x64.Build.0 = Debug|x64
|
||||
{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}.Release|x64.ActiveCfg = Release|x64
|
||||
{3DD9B6A4-5DD0-43FA-92EF-33DED4622A2B}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -170,7 +170,7 @@ namespace EscudeTools
|
||||
// Add columns to the create table query
|
||||
foreach (var column in sheet.col)
|
||||
{
|
||||
createTableQuery.Append($"{column.name} {Utils.GetSQLiteColumnType(column.type, column.size)}, ");
|
||||
createTableQuery.Append($"{column.name} {Utils.GetSQLiteColumnType(column.type)}, ");
|
||||
}
|
||||
|
||||
createTableQuery.Remove(createTableQuery.Length - 2, 2); // Remove the last comma and space
|
||||
|
@ -3,23 +3,6 @@ namespace EscudeTools
|
||||
{
|
||||
public static class Define
|
||||
{
|
||||
public static readonly string[] ProcNames =
|
||||
[
|
||||
"proc_end", "proc_call", "proc_argv", "proc_argc", "proc_typeof", "proc_int", "proc_float", "proc_abs",
|
||||
"proc_rand", "proc_min", "proc_max", "proc_rgb", "proc_refer", "proc_credit", "proc_log_new", "proc_log_out",
|
||||
"proc_title", "proc_auto_save", "proc_is_pass", "proc_event", "proc_scene", "proc_open_name", "proc_notice",
|
||||
"proc_log_img", "proc_msg_opt", "proc_cf", "proc_cv", "proc_vt", "proc_frame", "proc_text", "proc_vals",
|
||||
"proc_clear", "proc_gap", "proc_menu_opt", "proc_menu", "proc_wait", "proc_lsf_init", "proc_lsf_set",
|
||||
"proc_lsf_get", "proc_lsf_break", "proc_dt", "proc_ps", "proc_cg", "proc_cg_org", "proc_cg_set", "proc_cg_get",
|
||||
"proc_cg_em", "proc_cg_clr", "proc_cg_disp", "proc_path", "proc_tween", "proc_trans", "proc_mot_set",
|
||||
"proc_mot_get", "proc_quake", "proc_flash", "proc_flt", "proc_ptcl", "proc_sync", "proc_auto_kill", "proc_movie",
|
||||
"proc_bgm_play", "proc_bgm_stop", "proc_bgm_vol", "proc_bgm_fx", "proc_amb_play", "proc_amb_stop", "proc_amb_vol",
|
||||
"proc_amb_fx", "proc_se_play", "proc_se_stop", "proc_se_wait", "proc_se_vol", "proc_se_fx", "proc_voc_play",
|
||||
"proc_voc_stop", "proc_voc_wait", "proc_voc_vol", "proc_voc_fx", "proc_bgv_play", "proc_bgv_stop", "proc_bgv_vol",
|
||||
"proc_bgv_fx", "proc_set_param", "proc_get_param", "proc_jump", "proc_date", "proc_flow", "proc_diary",
|
||||
"proc_unlock", "proc_section", "proc_omake"
|
||||
];
|
||||
// 说句实话,我觉得这些定义可能会发生变化
|
||||
public const byte INST_POP = 1;
|
||||
public const byte INST_POP_N = 2;
|
||||
public const byte INST_POP_RET = 3;
|
||||
@ -241,7 +224,9 @@ namespace EscudeTools
|
||||
return $"File line number";
|
||||
case INST_PROC:
|
||||
uint index = BitConverter.ToUInt32(c.Parameter);
|
||||
return $"Execute built-in function: {ProcNames[index]} {SetExtStr(c, sf)}";
|
||||
//if(index>= ProcNames.Length)
|
||||
// return $"Execute unknown built-in function";
|
||||
return $"Execute built-in function {index}";
|
||||
case INST_TEXT:
|
||||
messIndex++;
|
||||
return (sm == null) ? "意外的指令,此表无Mess" : sm.DataString[messIndex - 1];
|
||||
@ -261,581 +246,5 @@ namespace EscudeTools
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string SetExtStr(Command c, ScriptFile sf)
|
||||
{
|
||||
switch (BitConverter.ToUInt32(c.Parameter))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
//(0 = 标题 / -1 = 游戏结束,保留数据 / 1以上 = 通关,保留数据)
|
||||
string[] ps = ["结束代码"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "脚本结束";
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
string[] ps = ["脚本编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "调用文件";
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
string[] ps = ["参数索引"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取函数帧的参数";
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
string[] ps = ["参数数量"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取函数帧的参数数量";
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
string[] ps = ["值"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取变量的类型";
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
string[] ps = ["值"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "转换为整数";
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
string[] ps = ["值"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "转换为浮点数";
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
string[] ps = ["值"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "绝对值";
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
string[] ps = ["可变长度参数"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取随机数";
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
string[] ps = ["可变长度参数"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取最小值";
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
string[] ps = ["可变长度参数"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取最大值";
|
||||
}
|
||||
case 11:
|
||||
{
|
||||
string[] ps = ["R", "G", "B", "A"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "将RGB值转换为颜色代码";
|
||||
}
|
||||
case 12:
|
||||
{
|
||||
string[] ps = ["索引", "可变长度参数"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "引用转换";
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
string[] ps = ["编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "员工名单滚动";
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
string[] ps = ["文件名"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "新建日志";
|
||||
}
|
||||
case 15:
|
||||
{
|
||||
string[] ps = ["文件名", "输出值..."];
|
||||
SetExtStr1(ps, sf);
|
||||
return "输出日志";
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
string[] ps = ["标题字符串"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置场景标题";
|
||||
}
|
||||
case 17:
|
||||
{
|
||||
return "自动保存";
|
||||
}
|
||||
case 18:
|
||||
{
|
||||
string[] ps = ["脚本编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取脚本通过标志";
|
||||
}
|
||||
case 19:
|
||||
{
|
||||
string[] ps = ["CG编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置CG欣赏标志";
|
||||
}
|
||||
case 20:
|
||||
{
|
||||
string[] ps = ["脚本编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置场景回想标志";
|
||||
}
|
||||
case 21:
|
||||
{
|
||||
string[] ps = ["名称编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "打开名称";
|
||||
}
|
||||
case 22:
|
||||
{
|
||||
string[] ps = ["文本", "显示时间", "强制标志"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "显示通知文本";
|
||||
}
|
||||
case 23:
|
||||
{
|
||||
string[] ps = ["角色ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置日志中的角色图像";
|
||||
}
|
||||
case 24:
|
||||
{
|
||||
string[] ps = ["文本控制ID", "设置标志"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "文本控制标志的设置";
|
||||
}
|
||||
case 25:
|
||||
{
|
||||
string[] ps = ["图像ID", "表情ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "表情指定";
|
||||
}
|
||||
case 26:
|
||||
{
|
||||
string[] ps = ["声音编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "声音指定";
|
||||
}
|
||||
case 27:
|
||||
{
|
||||
string[] ps = ["时间", "音轨"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "声音的播放时间等待";
|
||||
}
|
||||
case 28:
|
||||
{
|
||||
string[] ps = ["框架编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "文本框架的更改";
|
||||
}
|
||||
case 29:
|
||||
{
|
||||
//显示标志 (0 = 隐藏 / 1 = 显示)
|
||||
//显示时间 (1 / 1000毫秒)
|
||||
string[] ps = ["显示标志", "显示时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "文本框架的显示/隐藏";
|
||||
}
|
||||
case 30:
|
||||
{
|
||||
string[] ps = ["可变长参数"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "文本引用值的设置";
|
||||
}
|
||||
case 31:
|
||||
{
|
||||
string[] ps = ["时间(1/1000 ms)"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "文本消息的消去";
|
||||
}
|
||||
case 32:
|
||||
{
|
||||
string[] ps = ["x间隔", "y间隔"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "文本间距的设置";
|
||||
}
|
||||
case 33:
|
||||
{
|
||||
string[] ps = ["选择允许标志"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "菜单选项的设置";
|
||||
}
|
||||
case 34:
|
||||
{
|
||||
string[] ps = ["随机显示标志", "流程分支标志"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "菜单选择";
|
||||
}
|
||||
case 35:
|
||||
{
|
||||
string[] ps = ["延迟时间 (以毫秒为单位)", "点击取消标志"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "延迟处理";
|
||||
}
|
||||
case 36:
|
||||
{
|
||||
string[] ps = ["角色ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "初始化LSF部件";
|
||||
}
|
||||
case 37:
|
||||
{
|
||||
string[] ps = ["角色ID", "部件状态..."];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置LSF部件状态";
|
||||
}
|
||||
case 38:
|
||||
{
|
||||
string[] ps = ["角色ID", "部件ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取LSF部件状态";
|
||||
}
|
||||
case 39:
|
||||
{
|
||||
string[] ps = ["角色ID", "部件ID..."];
|
||||
SetExtStr1(ps, sf);
|
||||
return "LSF部件破坏效果";
|
||||
}
|
||||
case 40:
|
||||
{
|
||||
string[] ps = ["相对值"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "相对指定显示对象属性";
|
||||
}
|
||||
case 41:
|
||||
{
|
||||
string[] ps = ["显示对象..."];
|
||||
SetExtStr1(ps, sf);
|
||||
return "指定显示对象列表";
|
||||
}
|
||||
case 42:
|
||||
{
|
||||
string[] ps = ["显示对象", "图像ID", "表情ID", "分辨率等级", "滤镜ID", "Z", "X", "Y", "水平缩放率", "垂直缩放率", "旋转角度", "不透明度"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置显示对象";
|
||||
}
|
||||
case 43:
|
||||
{
|
||||
string[] ps = ["显示对象", "X", "Y"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置显示对象的原点坐标";
|
||||
}
|
||||
case 44:
|
||||
{
|
||||
string[] ps = ["显示对象", "属性ID", "属性值"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置显示对象的属性值";
|
||||
}
|
||||
case 45:
|
||||
{
|
||||
string[] ps = ["显示对象", "属性ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取显示对象的属性值";
|
||||
}
|
||||
case 46:
|
||||
{
|
||||
string[] ps = ["显示对象", "效果编号", "部位ID", "相对于部位的X坐标", "相对于部位的Y坐标", "显示顺序"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置情感效果";
|
||||
}
|
||||
case 47:
|
||||
{
|
||||
string[] ps = ["显示对象列表"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "删除显示对象";
|
||||
}
|
||||
case 48:
|
||||
{
|
||||
string[] ps = ["效果编号", "显示时间 (ms)", "时间曲线", "翻转规则图像标志", "逆向播放标志", "颜色"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "更新屏幕";
|
||||
}
|
||||
case 49:
|
||||
{
|
||||
string[] ps = ["显示对象", "时间", "X", "Y", "水平缩放率", "垂直缩放率", "旋转角度", "不透明度"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置插值";
|
||||
}
|
||||
case 50:
|
||||
{
|
||||
string[] ps = ["显示对象", "插值动画ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "插值动画";
|
||||
}
|
||||
case 51:
|
||||
{
|
||||
return "插值";
|
||||
}
|
||||
case 52:
|
||||
{
|
||||
string[] ps = ["显示对象", "变量编号", "值"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置MOT的变量";
|
||||
}
|
||||
case 53:
|
||||
{
|
||||
string[] ps = ["显示对象", "变量编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取MOT的变量";
|
||||
}
|
||||
case 54:
|
||||
{
|
||||
string[] ps = ["显示对象", "X轴震动像素数", "Y轴震动像素数", "效果时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "屏幕震动";
|
||||
}
|
||||
case 55:
|
||||
{
|
||||
string[] ps = ["闪光颜色", "闪光次数"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "闪光效果";
|
||||
}
|
||||
case 56:
|
||||
{
|
||||
string[] ps = ["滤镜ID", "模式", "颜色", "水平模糊", "垂直模糊"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置颜色滤镜";
|
||||
}
|
||||
case 57:
|
||||
{
|
||||
string[] ps = ["效果编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置特殊效果";
|
||||
}
|
||||
case 58:
|
||||
{
|
||||
string[] ps = ["效果标志", "取消标志"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "屏幕效果等待";
|
||||
}
|
||||
case 59:
|
||||
{
|
||||
string[] ps = ["显示对象", "自动消失标志"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置自动消失标志";
|
||||
}
|
||||
case 60:
|
||||
{
|
||||
string[] ps = ["视频编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "播放视频";
|
||||
}
|
||||
case 61:
|
||||
{
|
||||
string[] ps = ["BGM编号", "淡入时间", "音量", "播放开始时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "播放BGM";
|
||||
}
|
||||
case 62:
|
||||
{
|
||||
string[] ps = ["淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "停止BGM";
|
||||
}
|
||||
case 63:
|
||||
{
|
||||
string[] ps = ["音量值", "淡入淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置BGM音量";
|
||||
}
|
||||
case 64:
|
||||
{
|
||||
string[] ps = ["效果编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置BGM效果";
|
||||
}
|
||||
case 65:
|
||||
{
|
||||
string[] ps = ["环境音编号", "淡入时间", "音量", "播放开始时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "播放环境音";
|
||||
}
|
||||
case 66:
|
||||
{
|
||||
string[] ps = ["淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "停止环境音";
|
||||
}
|
||||
case 67:
|
||||
{
|
||||
string[] ps = ["音量值", "淡入淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置环境音音量";
|
||||
}
|
||||
case 68:
|
||||
{
|
||||
string[] ps = ["效果编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置环境音效果";
|
||||
}
|
||||
case 69:
|
||||
{
|
||||
string[] ps = ["轨道", "音效编号", "循环标志", "淡入时间", "音量", "播放开始时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "播放音效";
|
||||
}
|
||||
case 70:
|
||||
{
|
||||
string[] ps = ["轨道", "淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "停止音效";
|
||||
}
|
||||
case 71:
|
||||
{
|
||||
string[] ps = ["轨道"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "音效等待";
|
||||
}
|
||||
case 72:
|
||||
{
|
||||
string[] ps = ["轨道", "音量值", "淡入淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置音效音量";
|
||||
}
|
||||
case 73:
|
||||
{
|
||||
string[] ps = ["效果编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置音效效果";
|
||||
}
|
||||
case 74:
|
||||
{
|
||||
string[] ps = ["轨道", "语音编号", "淡入时间", "音量", "播放开始时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "播放角色语音";
|
||||
}
|
||||
case 75:
|
||||
{
|
||||
string[] ps = ["轨道", "淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "停止角色语音";
|
||||
}
|
||||
case 76:
|
||||
{
|
||||
string[] ps = ["轨道"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "角色语音等待";
|
||||
}
|
||||
case 77:
|
||||
{
|
||||
string[] ps = ["轨道", "音量值", "淡入淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置角色语音音量";
|
||||
}
|
||||
case 78:
|
||||
{
|
||||
string[] ps = ["效果编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置角色语音效果";
|
||||
}
|
||||
case 79:
|
||||
{
|
||||
string[] ps = ["轨道", "语音编号", "淡入时间", "音量", "播放开始时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "播放BGV";
|
||||
}
|
||||
case 80:
|
||||
{
|
||||
string[] ps = ["轨道", "淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "停止BGV";
|
||||
}
|
||||
case 81:
|
||||
{
|
||||
string[] ps = ["轨道", "音量值", "淡入淡出时间"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置BGV音量";
|
||||
}
|
||||
case 82:
|
||||
{
|
||||
string[] ps = ["效果编号"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置BGV效果";
|
||||
}
|
||||
case 83:
|
||||
{
|
||||
string[] ps = ["类别ID", "参数ID", "参数值"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置参数";
|
||||
}
|
||||
case 84:
|
||||
{
|
||||
string[] ps = ["类别ID", "参数ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "获取参数";
|
||||
}
|
||||
case 85:
|
||||
{
|
||||
string[] ps = ["脚本ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "文件跳转";
|
||||
}
|
||||
case 86:
|
||||
{
|
||||
string[] ps = ["经过天数"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "更新日期";
|
||||
}
|
||||
case 87:
|
||||
{
|
||||
string[] ps = ["脚本ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "更新并显示流程图";
|
||||
}
|
||||
case 88:
|
||||
{
|
||||
string[] ps = ["日记ID", "附加标志", "等待标志"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "更新并显示日记";
|
||||
}
|
||||
case 89:
|
||||
{
|
||||
string[] ps = ["脚本ID", "父脚本ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "解锁区块";
|
||||
}
|
||||
case 90:
|
||||
{
|
||||
string[] ps = ["章节ID"];
|
||||
SetExtStr1(ps, sf);
|
||||
return "设置章节";
|
||||
}
|
||||
case 91:
|
||||
{
|
||||
return "附加内容";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static void SetExtStr1(string[] ps, ScriptFile sf)
|
||||
{
|
||||
int i = sf.Commands.Count - 2;
|
||||
sf.Commands[i + 1].IsProcSet = true;
|
||||
for (int k = 0; k < ps.Length; k++)
|
||||
{
|
||||
if (sf.Commands[i].IsProcSet || sf.Commands[i].Instruction < 4 || sf.Commands[i].Instruction > 10)
|
||||
{
|
||||
k--;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
sf.Commands[i].Helper += $": {ps[k]}";
|
||||
sf.Commands[i].IsProcSet = true;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
71
EscudeTools/EscudeEditor/BinWriter.cs
Normal file
71
EscudeTools/EscudeEditor/BinWriter.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using EscudeEditor;
|
||||
|
||||
namespace EscudeTools.EscudeEditor
|
||||
{
|
||||
internal class BitWriter : Stream
|
||||
{
|
||||
Stream Base;
|
||||
int Buffer = 0;
|
||||
int BufferedBits = 0;
|
||||
internal BitWriter(Stream Output)
|
||||
{
|
||||
Base = Output;
|
||||
}
|
||||
public override bool CanRead => false;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => true;
|
||||
|
||||
public override long Length => Base.Length;
|
||||
|
||||
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
Base.WriteByte((byte)(Buffer & 0xFF));
|
||||
Buffer = 0;
|
||||
BufferedBits = 0;
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void PutBits(byte Byte)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
PutBit(Byte.GetBit(i));
|
||||
}
|
||||
public void PutBit(bool Bit)
|
||||
{
|
||||
Buffer <<= 1;
|
||||
Buffer |= (byte)(Bit ? 1 : 0);
|
||||
BufferedBits++;
|
||||
|
||||
if (BufferedBits == 8)
|
||||
{
|
||||
Base.WriteByte((byte)(Buffer & 0xFF));
|
||||
BufferedBits -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
78
EscudeTools/EscudeEditor/Extensions.cs
Normal file
78
EscudeTools/EscudeEditor/Extensions.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace EscudeEditor {
|
||||
internal static class Extensions {
|
||||
|
||||
public static string GetString(this byte[] Binary, uint At, uint Len) {
|
||||
EncodingProvider provider = CodePagesEncodingProvider.Instance;
|
||||
Encoding? shiftJis = provider.GetEncoding("shift-jis");
|
||||
byte[] Buffer = new byte[Len];
|
||||
for (int i = 0; i < Len; i++) {
|
||||
Buffer[i] = Binary[i + At];
|
||||
}
|
||||
|
||||
return shiftJis.GetString(Buffer);
|
||||
}
|
||||
public static uint GetUInt32(this byte[] Binary, uint Position) {
|
||||
byte[] Buffer = new byte[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
Buffer[i] = Binary[i+Position];
|
||||
|
||||
return BitConverter.ToUInt32(Buffer, 0);
|
||||
}
|
||||
|
||||
public static void WriteTo(this uint Value, byte[] Binary, uint At) {
|
||||
BitConverter.GetBytes(Value).CopyTo(Binary, At);
|
||||
}
|
||||
|
||||
public static bool GetBit(this byte Byte, int Bit) {
|
||||
return (Byte & (1 << (7 - Bit))) != 0;
|
||||
}
|
||||
|
||||
public static byte[] ToArray(this Stream Stream) {
|
||||
Stream.Seek(0,0);
|
||||
|
||||
byte[] Data = new byte[Stream.Length];
|
||||
Stream.Read(Data, 0, Data.Length);
|
||||
|
||||
return Data;
|
||||
}
|
||||
|
||||
public static void WriteString(this Stream Stream, string String) {
|
||||
EncodingProvider provider = CodePagesEncodingProvider.Instance;
|
||||
Encoding? shiftJis = provider.GetEncoding("shift-jis");
|
||||
byte[] Buffer = shiftJis.GetBytes(String);
|
||||
|
||||
Stream.Write(Buffer, 0, Buffer.Length);
|
||||
}
|
||||
public static void WriteCString(this Stream Stream, string String) {
|
||||
Stream.WriteString(String);
|
||||
Stream.WriteByte(0x00);
|
||||
}
|
||||
public static string PeekCString(this Stream Stream, uint At) {
|
||||
long Pos = Stream.Position;
|
||||
List<byte> Buffer = new List<byte>();
|
||||
|
||||
Stream.Position = At;
|
||||
int b = 0;
|
||||
while ((b = Stream.ReadByte()) >= 1)
|
||||
Buffer.Add((byte)b);
|
||||
Stream.Position = Pos;
|
||||
|
||||
return Encoding.GetEncoding(932).GetString(Buffer.ToArray());
|
||||
}
|
||||
public static uint PeekUInt32(this Stream Stream, uint At) {
|
||||
long Pos = Stream.Position;
|
||||
byte[] Buffer = new byte[4];
|
||||
Stream.Position = At;
|
||||
Stream.Read(Buffer, 0, Buffer.Length);
|
||||
Stream.Position = Pos;
|
||||
|
||||
return Buffer.GetUInt32(0);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,23 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -4,9 +4,126 @@ namespace EscudeTools
|
||||
{
|
||||
public class ImageManager
|
||||
{
|
||||
public static void ImgPreProcessNew(List<StTable> stts, Face[] faces, LsfManager lm, string outputDir)
|
||||
{
|
||||
var parallelOptions = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = 6 // 设置最大并行线程数
|
||||
};
|
||||
|
||||
Parallel.ForEach(stts, parallelOptions, stt =>
|
||||
//foreach (StTable stt in stts)
|
||||
{
|
||||
if (stt.order == 0) //仅提取鉴赏中有的ST
|
||||
return;
|
||||
//continue;
|
||||
string targetFilename = Path.Combine(outputDir, stt.name); //最后保存可用的文件名
|
||||
LsfData? lsfData = lm.FindLsfDataByName(stt.file);
|
||||
if (lsfData == null)
|
||||
{
|
||||
Console.WriteLine($"警告,未找到与{stt.file}对应的lsf数据");
|
||||
return;
|
||||
}
|
||||
List<int> pendingList = [];
|
||||
List<string> pendingListFn = [];
|
||||
foreach (string o in stt.option)
|
||||
{
|
||||
List<int> t = TableManagercs.ParseOptions(lsfData, o);
|
||||
if (t.Count == 0)
|
||||
continue;
|
||||
pendingList.AddRange(t);
|
||||
foreach (int i in t)
|
||||
{
|
||||
pendingListFn.Add(lsfData.lli[i].nameStr);
|
||||
}
|
||||
}
|
||||
//pendingList = TableManagercs.OrderLayer(pendingList, pendingListFn);
|
||||
int n = 0;
|
||||
foreach (string o in faces[(int)stt.face].faceOptions)
|
||||
{
|
||||
List<int> pendingListCopy = new(pendingList);
|
||||
List<string> pendingListFnCopy = new(pendingListFn);
|
||||
List<int> t = TableManagercs.ParseOptions(lsfData, o);
|
||||
if (t.Count == 0)
|
||||
continue;
|
||||
foreach (int i in t)
|
||||
{
|
||||
pendingListFnCopy.Add(lsfData.lli[i].nameStr);
|
||||
}
|
||||
pendingListCopy.AddRange(t);
|
||||
pendingListCopy = TableManagercs.OrderLayer(pendingListCopy, pendingListFnCopy);
|
||||
if (!ImageManager.Process(lsfData, [.. pendingListCopy], targetFilename + $"_{n}.png"))
|
||||
throw new Exception("Process Fail");
|
||||
else
|
||||
Console.WriteLine($"Export {stt.name}_{n} Success");
|
||||
n++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void ImgPreProcessOld(List<StTable> stts, LsfManager lm, string outputDir)
|
||||
{
|
||||
var parallelOptions = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = 6 // 设置最大并行线程数
|
||||
};
|
||||
|
||||
Parallel.ForEach(stts, parallelOptions, stt =>
|
||||
//foreach (var stt in stts)
|
||||
{
|
||||
if (stt.order == 0) //仅提取鉴赏中有的ST
|
||||
return;
|
||||
string targetFilename = Path.Combine(outputDir, stt.name);
|
||||
LsfData? lsfData = lm.FindLsfDataByName(stt.file);
|
||||
if (lsfData == null)
|
||||
{
|
||||
Console.WriteLine($"警告,未找到与{stt.file}对应的lsf数据");
|
||||
return;
|
||||
}
|
||||
List<int> faceAvailList = [];
|
||||
List<string> faceAvailNameList = [];
|
||||
for (int i = 0; i < lsfData.lli.Length; i++)
|
||||
{
|
||||
if (lsfData.lli[i].index == 1)
|
||||
{
|
||||
faceAvailList.Add(i);
|
||||
faceAvailNameList.Add(lsfData.lli[i].nameStr);
|
||||
}
|
||||
|
||||
}
|
||||
List<int> pendingList = [];
|
||||
List<string> pendingListFn = [];
|
||||
foreach (string o in stt.option)
|
||||
{
|
||||
List<int> t = TableManagercs.ParseOptions(lsfData, o);
|
||||
if (t.Count == 0)
|
||||
continue;
|
||||
pendingList.AddRange(t);
|
||||
foreach (int i in t)
|
||||
{
|
||||
pendingListFn.Add(lsfData.lli[i].nameStr);
|
||||
}
|
||||
}
|
||||
//pendingList = TableManagercs.OrderLayer(pendingList, pendingListFn);
|
||||
int n = 0;
|
||||
for (int k = 0; k < faceAvailList.Count; k++)
|
||||
{
|
||||
List<int> que = new(pendingList);
|
||||
List<string> queStr = new(pendingListFn);
|
||||
que.Add(faceAvailList[k]);
|
||||
queStr.Add(faceAvailNameList[k]);
|
||||
que = TableManagercs.OrderLayer(que, queStr);
|
||||
if (!ImageManager.Process(lsfData, [.. que], targetFilename + $"_{n}.png"))
|
||||
throw new Exception("Process Fail");
|
||||
else
|
||||
Console.WriteLine($"Export {stt.name}_{n} Success");
|
||||
n++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static bool Process(LsfData ld, int[] n, string target)
|
||||
{
|
||||
//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++)
|
||||
@ -19,9 +136,9 @@ namespace EscudeTools
|
||||
if (mode == 3)
|
||||
{
|
||||
overlayImage.Composite(baseImage, -1 * offsetX, -1 * offsetY, CompositeOperator.DstIn);
|
||||
baseImage.Composite(overlayImage, offsetX, offsetY, CompositeOperator.Multiply);//原先就一条这个,发现处理透明时会有问题
|
||||
baseImage.Composite(overlayImage, offsetX, offsetY, CompositeOperator.Multiply);//应该能解决透明度问题了
|
||||
}
|
||||
else if (mode == 10)
|
||||
else if (mode == 10) //目前还没遇到过?
|
||||
{
|
||||
baseImage.Composite(overlayImage, offsetX, offsetY, CompositeOperator.Plus);
|
||||
}
|
||||
@ -34,10 +151,6 @@ namespace EscudeTools
|
||||
return true;
|
||||
}
|
||||
|
||||
//上面足够给Ev、St用了
|
||||
//public static bool StProcess()
|
||||
//{
|
||||
// throw new NotImplementedException();
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -114,9 +114,8 @@ namespace EscudeTools
|
||||
{
|
||||
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 Dictionary<string, LsfData> lsfDataLookup = [];
|
||||
|
||||
private bool preFetchInfo;
|
||||
|
||||
@ -158,7 +157,7 @@ namespace EscudeTools
|
||||
return lsfData; // 如果未找到,则返回 null
|
||||
}
|
||||
|
||||
private LsfFileHeader LoadLsfHeader(string path)
|
||||
private static LsfFileHeader LoadLsfHeader(string path)
|
||||
{
|
||||
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||
if (fs.Length < 0x1C)
|
||||
|
@ -1,5 +1,9 @@
|
||||
//这里的提取代码参考(Ctrl+C, Ctrl+V)了Garbro中关于ESCUDE BIN封包的实现
|
||||
//这里的部分Unpack代码参考了Garbro中关于ESCUDE BIN封包的实现
|
||||
//这里的部分Pack代码参考了marcussacana/EscudeEditor中的假压缩实现
|
||||
using EscudeEditor;
|
||||
using EscudeTools.EscudeEditor;
|
||||
using EscudeTools.Garbro;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
@ -54,6 +58,10 @@ namespace EscudeTools
|
||||
if (item == null)
|
||||
return false;
|
||||
pItem = item;
|
||||
|
||||
if (!Directory.Exists(Path.Combine(Path.GetDirectoryName(path), "output")))
|
||||
Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(path), "output"));
|
||||
File.WriteAllText(Path.Combine(Path.GetDirectoryName(path), "output", Path.GetFileNameWithoutExtension(path) + ".json"), JsonSerializer.Serialize(pItem));
|
||||
}
|
||||
isLoaded = true;
|
||||
pFile = path;
|
||||
@ -121,7 +129,7 @@ namespace EscudeTools
|
||||
return null;
|
||||
Decrypt(ref index);
|
||||
int index_offset = 0;
|
||||
var dir = new List<Entry>((int)m_count);
|
||||
List<Entry> dir = new((int)m_count);
|
||||
for (uint i = 0; i < m_count; ++i)
|
||||
{
|
||||
int filename_offset = (int)Utils.ToUInt32(index, index_offset);
|
||||
@ -170,7 +178,7 @@ namespace EscudeTools
|
||||
if (!Directory.Exists(output))
|
||||
Directory.CreateDirectory(output);
|
||||
var lzwManifest = new List<LzwEntry>();
|
||||
//string jsonPath = Path.Combine(output, "lzwManifest.json");
|
||||
string jsonPath = Path.Combine(output, "lzwManifest.json");
|
||||
using FileStream inputStream = new(pFile, FileMode.Open, FileAccess.Read);
|
||||
using BinaryReader br = new(inputStream);
|
||||
foreach (Entry entry in pItem)
|
||||
@ -207,18 +215,18 @@ namespace EscudeTools
|
||||
|
||||
if (lzwManifest.Count > 0)
|
||||
{
|
||||
//using (FileStream fs = File.Create(jsonPath))
|
||||
//{
|
||||
// byte[] jsonBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(lzwManifest));
|
||||
// fs.Write(jsonBytes, 0, jsonBytes.Length);
|
||||
//}
|
||||
using (FileStream fs = File.Create(jsonPath))
|
||||
{
|
||||
byte[] jsonBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(lzwManifest));
|
||||
fs.Write(jsonBytes, 0, jsonBytes.Length);
|
||||
}
|
||||
LzwDecode(lzwManifest, output);
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void LzwDecode(List<LzwEntry> lzwManifest, string output)
|
||||
private static void LzwDecode(List<LzwEntry> lzwManifest, string output)
|
||||
{
|
||||
foreach (var i in lzwManifest)
|
||||
{
|
||||
@ -236,19 +244,13 @@ namespace EscudeTools
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class LzwDecoder : IDisposable
|
||||
internal sealed class LzwDecoder(Stream input, int unpacked_size) : IDisposable
|
||||
{
|
||||
private MsbBitStream m_input;
|
||||
private byte[] m_output;
|
||||
private MsbBitStream m_input = new(input, true);
|
||||
private byte[] m_output = new byte[unpacked_size];
|
||||
|
||||
public byte[] Output { get { return m_output; } }
|
||||
|
||||
public LzwDecoder(Stream input, int unpacked_size)
|
||||
{
|
||||
m_input = new MsbBitStream(input, true);
|
||||
m_output = new byte[unpacked_size];
|
||||
}
|
||||
|
||||
public void Unpack()
|
||||
{
|
||||
int dst = 0;
|
||||
@ -312,19 +314,18 @@ namespace EscudeTools
|
||||
#endregion
|
||||
}
|
||||
|
||||
public bool Repack(string path, int version, bool useCustomKey = false, string customKeyProviderPath = "") //目前支持v2v1
|
||||
public bool Repack(string path, int version, string customKeyProviderPath = "") //目前支持v2v1
|
||||
{
|
||||
if (useCustomKey)
|
||||
if (customKeyProviderPath!="")
|
||||
LoadKey(customKeyProviderPath);
|
||||
GeneratePItem(path);
|
||||
//if(File.Exists(Path.Combine(path, "lzwManifest.json")))
|
||||
// return false;
|
||||
//Q:为什么不支持LZW打包 //A:因为我实在不想研究lzw算法,欢迎PR
|
||||
ReadPItem(path);
|
||||
List<LzwEntry> lzwManifest = [];
|
||||
if (File.Exists(Path.Combine(path, "lzwManifest.json")))
|
||||
lzwManifest = JsonSerializer.Deserialize<List<LzwEntry>>(File.ReadAllText(Path.Combine(path, "lzwManifest.json"))) ?? [];
|
||||
m_seed = isLoaded ? LoadedKey : 2210579460;
|
||||
string outputPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileName(path) + ".bin");
|
||||
using (FileStream fs = new(outputPath, FileMode.Create))
|
||||
using (BinaryWriter bw = new(fs))
|
||||
{
|
||||
using FileStream fs = new(outputPath, FileMode.Create);
|
||||
using BinaryWriter bw = new(fs);
|
||||
bw.Write(fileSignature);
|
||||
bw.Write(supportPackVersion[version - 1]);
|
||||
bw.Write(m_seed);
|
||||
@ -343,8 +344,12 @@ namespace EscudeTools
|
||||
Array.Copy(strbytes, result, lengthToCopy);
|
||||
bw.Write(result);
|
||||
bw.Write(storeOffset);
|
||||
bw.Write(pItem[i].Size);
|
||||
storeOffset += pItem[i].Size;
|
||||
uint size = pItem[i].Size;
|
||||
if (Utils.SearchLzwEntryList(lzwManifest, pItem[i].Name) != -1)
|
||||
size = (uint)FakeCompress(File.ReadAllBytes(Path.Combine(path, pItem[i].Name))).Length;
|
||||
bw.Write(size);
|
||||
storeOffset += size;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -361,10 +366,13 @@ namespace EscudeTools
|
||||
indexOffset += 4;
|
||||
BitConverter.GetBytes(storeOffset).CopyTo(index, indexOffset);
|
||||
indexOffset += 4;
|
||||
BitConverter.GetBytes(pItem[i].Size).CopyTo(index, indexOffset);
|
||||
uint size = pItem[i].Size;
|
||||
if (Utils.SearchLzwEntryList(lzwManifest, pItem[i].Name) != -1)
|
||||
size = (uint)FakeCompress(File.ReadAllBytes(Path.Combine(path, pItem[i].Name))).Length;
|
||||
BitConverter.GetBytes(size).CopyTo(index, indexOffset);
|
||||
indexOffset += 4;
|
||||
filenameOffset += (uint)pItem[i].Name.Length + 1;
|
||||
storeOffset += pItem[i].Size;
|
||||
storeOffset += size;
|
||||
}
|
||||
Decrypt(ref index);
|
||||
bw.Write(index);
|
||||
@ -378,30 +386,70 @@ namespace EscudeTools
|
||||
}
|
||||
foreach (Entry entry in pItem)
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(Path.Combine(path, entry.Name));
|
||||
byte[] data;
|
||||
if (Utils.SearchLzwEntryList(lzwManifest, entry.Name) != -1)
|
||||
data = FakeCompress(File.ReadAllBytes(Path.Combine(path, entry.Name)));
|
||||
else
|
||||
data = File.ReadAllBytes(Path.Combine(path, entry.Name));
|
||||
|
||||
bw.Write(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void GeneratePItem(string path)
|
||||
private void ReadPItem(string path)
|
||||
{
|
||||
pItem.Clear();
|
||||
var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories)
|
||||
.Where(file => !file.EndsWith("lzwManifest.json", StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
foreach (var file in files)
|
||||
//反序列化path上级的json文件
|
||||
string jsonPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path) + ".json");
|
||||
if (File.Exists(jsonPath))
|
||||
pItem = JsonSerializer.Deserialize<List<Entry>>(File.ReadAllText(jsonPath)) ?? [];
|
||||
else
|
||||
throw new Exception("No json file found.");
|
||||
for (int i = 0; i < pItem.Count; i++)
|
||||
{
|
||||
var relativePath = Path.GetRelativePath(path, file);
|
||||
var fileInfo = new FileInfo(file);
|
||||
pItem.Add(new Entry
|
||||
{
|
||||
Name = relativePath,
|
||||
Size = (uint)fileInfo.Length
|
||||
});
|
||||
pItem[i].Size = (uint)new FileInfo(Path.Combine(path, pItem[i].Name)).Length;
|
||||
}
|
||||
//var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories)
|
||||
// .Where(file => !file.EndsWith("lzwManifest.json", StringComparison.OrdinalIgnoreCase))
|
||||
// .ToArray();
|
||||
//foreach (var file in files)
|
||||
//{
|
||||
// var relativePath = Path.GetRelativePath(path, file);
|
||||
// var fileInfo = new FileInfo(file);
|
||||
// pItem.Add(new Entry
|
||||
// {
|
||||
// Name = relativePath,
|
||||
// Size = (uint)fileInfo.Length
|
||||
// });
|
||||
//}
|
||||
m_count = (uint)pItem.Count;
|
||||
}
|
||||
|
||||
//不压其实也没事
|
||||
public static byte[] FakeCompress(byte[] Data)
|
||||
{
|
||||
using MemoryStream Stream = new();
|
||||
byte[] Buffer = new byte[4];
|
||||
((uint)Utils.Reverse((uint)Data.Length)).WriteTo(Buffer, 0);
|
||||
Stream.WriteCString("acp");
|
||||
Stream.Write(Buffer, 0, Buffer.Length);
|
||||
|
||||
BitWriter Writer = new(Stream);
|
||||
for (int i = 0; i < Data.Length; i++)
|
||||
{
|
||||
if (i > 0 && (i % 0x4000) == 0)
|
||||
{
|
||||
Writer.PutBit(true);
|
||||
Writer.PutBits(2);
|
||||
}
|
||||
Writer.PutBit(false);
|
||||
Writer.PutBits(Data[i]);
|
||||
}
|
||||
Writer.PutBit(true);
|
||||
Writer.PutBits(0);
|
||||
Writer.Flush();
|
||||
return Stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using System.Data;
|
||||
|
||||
namespace EscudeTools
|
||||
{
|
||||
@ -6,17 +7,286 @@ namespace EscudeTools
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
//批量处理EV/ST
|
||||
if (Directory.Exists(args[0]) && File.Exists(args[1]))
|
||||
//if (File.Exists(args[0]))
|
||||
if (args.Length == 1)
|
||||
switch (args[0])
|
||||
{
|
||||
string graphicsDBPath = args[1];
|
||||
case "-h":
|
||||
PrintHelp();
|
||||
break;
|
||||
default:
|
||||
InvalidArgument();
|
||||
break;
|
||||
}
|
||||
else if (args.Length == 2)
|
||||
switch (args[0])
|
||||
{
|
||||
case "-u":
|
||||
UnpackEscArc(args[1]);
|
||||
break;
|
||||
case "-r":
|
||||
RepackEscArc(args[1]);
|
||||
break;
|
||||
case "-d":
|
||||
UnpackMdb(args[1]);
|
||||
break;
|
||||
case "-f":
|
||||
RepackMdb(args[1]);
|
||||
break;
|
||||
//case "-s1": 这是一个坏主意
|
||||
// StProcessS1(args[1]);
|
||||
// break;
|
||||
default:
|
||||
InvalidArgument();
|
||||
break;
|
||||
}
|
||||
else if (args.Length == 3)
|
||||
switch (args[0])
|
||||
{
|
||||
case "-c":
|
||||
EvProcess(args[1], args[2]);
|
||||
break;
|
||||
case "-s":
|
||||
StProcess(args[1], args[2]);
|
||||
break;
|
||||
}
|
||||
else if (args.Length == 4)
|
||||
{
|
||||
switch (args[0])
|
||||
{
|
||||
case "-r":
|
||||
if (args[2] == "-c")
|
||||
RepackEscArc(args[1], args[3]);
|
||||
else
|
||||
InvalidArgument();
|
||||
break;
|
||||
case "-v":
|
||||
if (args[2] == "-t")
|
||||
UnpackScript(args[1], args[3]);
|
||||
else
|
||||
InvalidArgument();
|
||||
break;
|
||||
case "-e":
|
||||
if (args[2] == "-t")
|
||||
switch (args[3])
|
||||
{
|
||||
case "0":
|
||||
RepackScript0(args[1]);
|
||||
break;
|
||||
case "1":
|
||||
RepackScript1(args[1]);
|
||||
break;
|
||||
case "2":
|
||||
RepackScript2(args[1]);
|
||||
break;
|
||||
default:
|
||||
InvalidArgument();
|
||||
break;
|
||||
}
|
||||
else
|
||||
InvalidArgument();
|
||||
break;
|
||||
default:
|
||||
InvalidArgument();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (args.Length == 5)
|
||||
switch (args[0])
|
||||
{
|
||||
case "-e":
|
||||
bool b;
|
||||
if (!bool.TryParse(args[4], out b))
|
||||
{
|
||||
InvalidArgument();
|
||||
break;
|
||||
}
|
||||
if (args[2] == "-t")
|
||||
switch (args[3])
|
||||
{
|
||||
case "0":
|
||||
RepackScript0(args[1], b);
|
||||
break;
|
||||
case "1":
|
||||
RepackScript1(args[1], b);
|
||||
break;
|
||||
default:
|
||||
InvalidArgument();
|
||||
break;
|
||||
}
|
||||
else
|
||||
InvalidArgument();
|
||||
break;
|
||||
default:
|
||||
InvalidArgument();
|
||||
break;
|
||||
}
|
||||
else
|
||||
InvalidArgument();
|
||||
Console.WriteLine("Press any key to exit.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
private static void StProcess(string v1, string v2)
|
||||
{
|
||||
if (Directory.Exists(v1) && File.Exists(v2))
|
||||
{
|
||||
string graphicsDBPath = v2;
|
||||
using SqliteConnection connection = new($"Data Source={graphicsDBPath};");
|
||||
connection.Open();
|
||||
List<string> tableNames = [];
|
||||
string[] foundTN = new string[3];
|
||||
string[] foundTN = new string[2];
|
||||
List<int> tableIds = [];
|
||||
bool found1 = false, found2 = false, found3 = false;
|
||||
bool found2 = false, found3 = 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;
|
||||
found2 = true;
|
||||
}
|
||||
else if (tableName.StartsWith("表情"))
|
||||
{
|
||||
foundTN[1] = tableName;
|
||||
found3 = true;
|
||||
}
|
||||
tableNames.Add(tableName);
|
||||
tableIds.Add(id++);
|
||||
}
|
||||
}
|
||||
if (!(found2 && found3)) //这里的代码未经测试
|
||||
{
|
||||
for (int i = 0; i < tableNames.Count; i++)
|
||||
Console.WriteLine($"{tableIds[i]}: {tableNames[i]}");
|
||||
if (!found2)
|
||||
{
|
||||
Console.WriteLine("自动识别失败,请选择存放立绘信息的数据表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 (!found3)
|
||||
{
|
||||
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<StTable> stts = [];
|
||||
Face[] faces = new Face[32];
|
||||
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[0]};", connection))
|
||||
{
|
||||
using var reader = command.ExecuteReader();
|
||||
int fieldCount = reader.FieldCount;
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
|
||||
continue;
|
||||
stts.Add(new StTable
|
||||
{
|
||||
name = reader["ID_44"].ToString() ?? "",
|
||||
file = reader["ファイル_44"].ToString() ?? "",
|
||||
option = (reader["オプション_44"].ToString() ?? "").Split(' '),
|
||||
//coverd = (uint)reader.GetInt32(3),
|
||||
//filter = (uint)reader.GetInt32(4),
|
||||
face = (uint)(fieldCount == 9 ? 0 : reader.GetInt32("表情_14")),
|
||||
//id = (uint)reader.GetInt32(6),
|
||||
//loc = (uint)reader.GetInt32(7),
|
||||
order = reader.GetInt32("CG鑑賞_14"),
|
||||
//link = (uint)reader.GetInt32(9)
|
||||
});
|
||||
}
|
||||
}
|
||||
List<string> fa = [];
|
||||
bool legacyMode = false;
|
||||
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[1]};", connection))
|
||||
{
|
||||
using var reader = command.ExecuteReader();
|
||||
int fieldCount = reader.FieldCount;
|
||||
if (fieldCount <= 2)
|
||||
legacyMode = true;
|
||||
while (reader.Read() && !legacyMode)
|
||||
{
|
||||
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
|
||||
continue;
|
||||
for (int i = 0; i < faces.Length; i++)
|
||||
{
|
||||
if (faces[i] == null)
|
||||
faces[i] = new Face();
|
||||
if (reader.GetInt32(2 + i) == 1)
|
||||
faces[i].faceOptions.Add(reader.GetString(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
string[] files = Directory.GetFiles(v1, "*.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");
|
||||
}
|
||||
}
|
||||
connection.Close();
|
||||
string outputDir = Path.Combine(Path.GetDirectoryName(v1), "Output");
|
||||
if (!Directory.Exists(outputDir))
|
||||
Directory.CreateDirectory(outputDir);
|
||||
if (legacyMode)
|
||||
ImageManager.ImgPreProcessOld(stts, lm, outputDir);
|
||||
else
|
||||
ImageManager.ImgPreProcessNew(stts, faces, lm, outputDir);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void EvProcess(string v1, string v2)
|
||||
{
|
||||
if (Directory.Exists(v1) && File.Exists(v2))
|
||||
{
|
||||
string graphicsDBPath = v2;
|
||||
using SqliteConnection connection = new($"Data Source={graphicsDBPath};");
|
||||
connection.Open();
|
||||
List<string> tableNames = [];
|
||||
string[] foundTN = new string[1];
|
||||
List<int> tableIds = [];
|
||||
bool found1 = false;
|
||||
using (var command = new SqliteCommand("SELECT name FROM sqlite_master WHERE type='table';", connection))
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
@ -29,21 +299,11 @@ namespace EscudeTools
|
||||
foundTN[0] = tableName;
|
||||
found1 = true;
|
||||
}
|
||||
else if (tableName.StartsWith("立ち"))
|
||||
{
|
||||
foundTN[1] = tableName;
|
||||
found2 = true;
|
||||
}
|
||||
else if (tableName.StartsWith("表情"))
|
||||
{
|
||||
foundTN[2] = tableName;
|
||||
found3 = true;
|
||||
}
|
||||
tableNames.Add(tableName);
|
||||
tableIds.Add(id++);
|
||||
}
|
||||
}
|
||||
if (!(found1 && found2 && found3)) //这里的代码未经测试
|
||||
if (!found1) //这里的代码未经测试
|
||||
{
|
||||
for (int i = 0; i < tableNames.Count; i++)
|
||||
Console.WriteLine($"{tableIds[i]}: {tableNames[i]}");
|
||||
@ -69,55 +329,8 @@ namespace EscudeTools
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!found3)
|
||||
{
|
||||
Console.WriteLine("自动识别失败,请选择存放表情信息的数据表ID: ");
|
||||
string? input = Console.ReadLine();
|
||||
if (int.TryParse(input, out int userInputId))
|
||||
{
|
||||
if (userInputId >= 0 && userInputId < tableIds.Count)
|
||||
{
|
||||
foundTN[2] = 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 = [];
|
||||
Face[] faces = new Face[32];
|
||||
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[0]};", connection))
|
||||
{
|
||||
using var reader = command.ExecuteReader();
|
||||
@ -127,59 +340,21 @@ namespace EscudeTools
|
||||
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),
|
||||
name = reader["ID_44"].ToString() ?? "",
|
||||
file = reader["ファイル_44"].ToString() ?? "",
|
||||
option = (reader["オプション_44"].ToString() ?? "").Split(' '),
|
||||
//coverd = (uint)reader.GetInt32(3),
|
||||
//filter = (uint)reader.GetInt32(4),
|
||||
//color = (uint)reader.GetInt32(5),
|
||||
id = (uint)reader.GetInt32(5),
|
||||
loc = (uint)reader.GetInt32(6),
|
||||
order = reader.GetInt32(7),
|
||||
link = (uint)reader.GetInt32(8)
|
||||
//id = (uint)reader.GetInt32(6),
|
||||
//loc = (uint)reader.GetInt32(7),
|
||||
order = reader.GetInt32("CG鑑賞_14"),
|
||||
//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),
|
||||
// face = (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[2]};", connection))
|
||||
//{
|
||||
// using var reader = command.ExecuteReader();
|
||||
// while (reader.Read())
|
||||
// {
|
||||
// if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
|
||||
// continue;
|
||||
// for (int i = 0; i < faces.Length; i++)
|
||||
// {
|
||||
// if (faces[i] == null)
|
||||
// faces[i] = new Face();
|
||||
// if (reader.GetInt32(2 + i) == 1)
|
||||
// faces[i].faceOptions.Add(reader.GetString(1));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
string[] files = Directory.GetFiles(args[0], "*.lsf", SearchOption.AllDirectories);
|
||||
string[] files = Directory.GetFiles(v1, "*.lsf", SearchOption.AllDirectories);
|
||||
LsfManager lm = new();
|
||||
foreach (string file in files)
|
||||
{
|
||||
@ -191,7 +366,7 @@ namespace EscudeTools
|
||||
}
|
||||
}
|
||||
connection.Close();
|
||||
string outputDir = Path.Combine(Path.GetDirectoryName(args[0]), "Output");
|
||||
string outputDir = Path.Combine(Path.GetDirectoryName(v1), "Output");
|
||||
if (!Directory.Exists(outputDir))
|
||||
Directory.CreateDirectory(outputDir);
|
||||
var parallelOptions = new ParallelOptions
|
||||
@ -199,46 +374,6 @@ namespace EscudeTools
|
||||
MaxDegreeOfParallelism = 6 // 设置最大并行线程数
|
||||
};
|
||||
|
||||
// //ST //表情还要另取?
|
||||
// Parallel.ForEach(stts, parallelOptions, stt =>
|
||||
// //foreach (StTable stt in stts)
|
||||
// {
|
||||
// if (stt.order == 0) //仅提取鉴赏中有的ST
|
||||
// return;
|
||||
// //continue;
|
||||
// string targetFilename = Path.Combine(outputDir, stt.name); //最后保存可用的文件名
|
||||
// LsfData? lsfData = lm.FindLsfDataByName(stt.file) ?? throw new Exception($"错误,未找到与{stt.file}对应的lsf数据");
|
||||
// List<int> pendingList = [];
|
||||
// List<string> pendingListFn = [];
|
||||
// foreach (string o in stt.option)
|
||||
// {
|
||||
// List<int> t = TableManagercs.ParseOptions(lsfData, o);
|
||||
// if (t.Count == 0)
|
||||
// continue;
|
||||
// pendingList.AddRange(t);
|
||||
// foreach (int i in t)
|
||||
// {
|
||||
// pendingListFn.Add(lsfData.lli[i].nameStr);
|
||||
// }
|
||||
// }
|
||||
// pendingList = TableManagercs.OrderLayer(pendingList, pendingListFn);
|
||||
// int n = 0;
|
||||
// foreach (string o in faces[(int)stt.face].faceOptions)
|
||||
// {
|
||||
// List<int> pendingListCopy = new(pendingList);
|
||||
// List<int> t = TableManagercs.ParseOptions(lsfData, o);
|
||||
// if (t.Count == 0)
|
||||
// continue;
|
||||
// pendingListCopy.AddRange(t);
|
||||
// if (!ImageManager.Process(lsfData, [.. pendingListCopy], targetFilename + $"_{n++}.png"))
|
||||
// throw new Exception("Process Fail");
|
||||
// else
|
||||
// Console.WriteLine($"Export {stt.name}_{n - 1} Success");
|
||||
// }
|
||||
// });
|
||||
////}
|
||||
|
||||
//EV
|
||||
Parallel.ForEach(evts, parallelOptions, evt =>
|
||||
//foreach (EvTable evt in evts)
|
||||
{
|
||||
@ -270,233 +405,242 @@ namespace EscudeTools
|
||||
});
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// 批量读取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");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
////不支持script data打包,因为这几个封包,游戏强制lzw压缩读取
|
||||
////而我没写出lzw压缩代码
|
||||
////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))
|
||||
// Console.WriteLine("Repack Package Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Repack Package Failed");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
////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;
|
||||
|
||||
////repack sqlite to bin
|
||||
//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");
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
//导出db_*.bin
|
||||
if (Directory.Exists(args[0]))
|
||||
private static void RepackScript2(string v)
|
||||
{
|
||||
string[] files = Directory.GetFiles(args[0], "db_*.bin");
|
||||
//TEXT
|
||||
if (File.Exists(v))
|
||||
ScriptManager.Repackv3(v);
|
||||
else
|
||||
Console.WriteLine("Invalid Path");
|
||||
}
|
||||
|
||||
private static void RepackScript1(string v)
|
||||
{
|
||||
RepackScript1(v, true);
|
||||
}
|
||||
|
||||
private static void RepackScript0(string v)
|
||||
{
|
||||
RepackScript0(v, true);
|
||||
}
|
||||
|
||||
private static void RepackScript1(string v1, bool v2)
|
||||
{
|
||||
//MESS
|
||||
if (File.Exists(v1))
|
||||
ScriptManager.Repackv2(v1, v2);
|
||||
else
|
||||
Console.WriteLine("Invalid Path");
|
||||
}
|
||||
|
||||
private static void RepackScript0(string v1, bool v2)
|
||||
{
|
||||
//FULL
|
||||
if (File.Exists(v1))
|
||||
ScriptManager.Repackv1(v1, v2);
|
||||
else
|
||||
Console.WriteLine("Invalid Path");
|
||||
}
|
||||
|
||||
private static void UnpackScript(string v1, string v2)
|
||||
{
|
||||
//Batch Unpack Script(Full, Text, Mess)
|
||||
if (Directory.Exists(v1))
|
||||
{
|
||||
string[] files = Directory.GetFiles(v1, "*.bin");
|
||||
foreach (string file in files)
|
||||
{
|
||||
ScriptManager smr = new();
|
||||
if (smr.LoadScriptFile(file))
|
||||
{
|
||||
Console.WriteLine($"Load {file} Success");
|
||||
switch (v2)
|
||||
{
|
||||
case "0":
|
||||
if (smr.ExportDatabase(Path.GetDirectoryName(v1)))
|
||||
Console.WriteLine("Export Script Success");
|
||||
else
|
||||
Console.WriteLine("Export Script Failed");
|
||||
break;
|
||||
case "1":
|
||||
if (smr.ExportMessDatabase(Path.GetDirectoryName(v1)))
|
||||
Console.WriteLine("Export Mess Success");
|
||||
else
|
||||
Console.WriteLine("Export Mess Failed");
|
||||
break;
|
||||
case "2":
|
||||
if (smr.ExportTextDatabase(Path.GetDirectoryName(v1)))
|
||||
Console.WriteLine("Export Text Success");
|
||||
else
|
||||
Console.WriteLine("Export Text Failed");
|
||||
break;
|
||||
default:
|
||||
InvalidArgument();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
Console.WriteLine($"Load {file} Failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RepackMdb(string v)
|
||||
{
|
||||
//repack sqlite to bin
|
||||
if (Directory.Exists(v))
|
||||
{
|
||||
string[] files = Directory.GetFiles(v, "*.db");
|
||||
foreach (string file in files)
|
||||
{
|
||||
DatabaseManager.ExportMDB(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Invalid Path");
|
||||
}
|
||||
|
||||
private static void UnpackMdb(string v)
|
||||
{
|
||||
//导出db_*.bin
|
||||
if (Directory.Exists(v))
|
||||
{
|
||||
string[] files = Directory.GetFiles(v, "*.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])))
|
||||
if (dm.ExportDatabase(Path.GetDirectoryName(v)))
|
||||
Console.WriteLine("Export Database Success");
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Export Database Failed");
|
||||
return;
|
||||
}
|
||||
else
|
||||
Console.WriteLine($"Load {file} Failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Invalid Path");
|
||||
}
|
||||
|
||||
private static void RepackEscArc(string v, string v1)
|
||||
{
|
||||
//Batch Repack ESC-ARC Package
|
||||
if (Directory.Exists(v) && (v1 == "" || File.Exists(v1)))
|
||||
{
|
||||
string[] directories = Directory.GetDirectories(v);
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
PackManager pm = new();
|
||||
//string providerFilePath = Path.Combine(args[1], Path.GetFileName(directory) + ".bin");
|
||||
if (pm.Repack(directory, 2, v1))
|
||||
Console.WriteLine("Repack Package Success");
|
||||
else
|
||||
Console.WriteLine("Repack Package Failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Invalid Path");
|
||||
}
|
||||
|
||||
private static void RepackEscArc(string v)
|
||||
{
|
||||
RepackEscArc(v, "");
|
||||
}
|
||||
|
||||
private static void UnpackEscArc(string v)
|
||||
{
|
||||
//Batch Unpack ESC-ARC Package
|
||||
if (Directory.Exists(v))
|
||||
{
|
||||
string[] files = Directory.GetFiles(v, "*.bin");
|
||||
PackManager pm = new();
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (pm.Load(file))
|
||||
{
|
||||
Console.WriteLine($"Load {file} Success");
|
||||
if (pm.Extract())
|
||||
Console.WriteLine("Extract Package Success");
|
||||
else
|
||||
Console.WriteLine("Extract Package Failed");
|
||||
}
|
||||
else
|
||||
Console.WriteLine($"Load {file} Failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Invalid Path");
|
||||
}
|
||||
|
||||
private static void InvalidArgument()
|
||||
{
|
||||
Console.WriteLine("Invalid arguments. Use -h for help.");
|
||||
}
|
||||
|
||||
public static void PrintHelp()
|
||||
{
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine("EscudeTools.exe -u <path>");
|
||||
Console.WriteLine("-u: unpack ESC-ARC bin");
|
||||
Console.WriteLine("Unpacks all ESC-ARC bin files in the specified directory path.");
|
||||
Console.WriteLine("Unpacked contents will be saved in the 'output' directory.");
|
||||
Console.WriteLine("*.json files include package information; do not delete them (use for repack).");
|
||||
Console.WriteLine("lzwManifest.json file contains LZW file information; delete it if you want to repack the package without LZW compression.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("EscudeTools.exe -r (-c) <path>");
|
||||
Console.WriteLine("-r: repack ESC-ARC bin");
|
||||
Console.WriteLine("-r -c: repack ESC-ARC bin & use a custom key from an existing ESC-ARC bin.");
|
||||
Console.WriteLine("Repacks all directories in the specified directory path to ESC-ARC bin.");
|
||||
Console.WriteLine("Accepts an optional -c flag to use a custom key from an existing ESC-ARC bin.");
|
||||
Console.WriteLine("Default key is ... (check it in the source code).");
|
||||
Console.WriteLine("For notes about JSON files in the output directory, please refer to unpack usage.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("EscudeTools.exe -v <path> -t <type>");
|
||||
Console.WriteLine("-v -t: unpack script bin, type");
|
||||
Console.WriteLine("Unpacks all script bin files in the specified directory path to SQLite database.");
|
||||
Console.WriteLine("Ignore the 001 files; the program will read them if needed.");
|
||||
Console.WriteLine("Must specify the type of script bin file to unpack.");
|
||||
Console.WriteLine("Accepts the following types: 0, 1, 2.");
|
||||
Console.WriteLine("Type 0(unstable): Full; this creates script.db containing all .bin and .001 information.");
|
||||
Console.WriteLine("Type 2: Exports only the text from bin; this creates script_text.db and many .dat files (non-text data).");
|
||||
Console.WriteLine("Type 1: Exports only the text from 001; this creates script_sm.db containing all .001 information.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("EscudeTools.exe -e <path> -t <type>");
|
||||
Console.WriteLine("-e -t: repack script bin, type");
|
||||
Console.WriteLine("Repacks all SQLite database files in the specified directory path to script bin.");
|
||||
Console.WriteLine("Must specify the type of script bin file to repack.");
|
||||
Console.WriteLine("Accepts the following types: 0, 1, 2.");
|
||||
Console.WriteLine("Type 0: Full; this generates .bin and .001 files.");
|
||||
Console.WriteLine("Type 2: This generates .bin files.");
|
||||
Console.WriteLine("Type 1: This generates .001 files.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("EscudeTools.exe -d <path>");
|
||||
Console.WriteLine("-d: unpack db_*.bin to SQLite");
|
||||
Console.WriteLine("Exports all db_*.bin files in the path to individual SQLite databases.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("EscudeTools.exe -f <path>");
|
||||
Console.WriteLine("-f: repack SQLite to db_*.bin");
|
||||
Console.WriteLine("Restores all SQLite databases in the path to db_*.bin files.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("EscudeTools.exe -c <EvPath> <db_graphics.db Path>");
|
||||
Console.WriteLine("-c: compose EV image");
|
||||
Console.WriteLine("Provide a set of EV images of the same size and the db_graphics.db to compose the images.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("EscudeTools.exe -s <StPath> <db_graphics.db Path>");
|
||||
Console.WriteLine("-s: compose ST image");
|
||||
Console.WriteLine("Provide a set of ST images of the same size and the db_graphics.db to compose the images.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("EscudeTools.exe -h");
|
||||
Console.WriteLine("-h: print help info");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 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");
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"profiles": {
|
||||
"EscudeTools": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "G:\\x221.local\\lab3\\Haison\\output\\ev\\1\r\n\"G:\\x221.local\\lab3\\Haison\\output\\ev\\db_graphics.db\""
|
||||
"commandLineArgs": "-v\r\n\"G:\\x221.local\\[231027][1231724][エスクード] 戦巫<センナギ> ―穢れた契りと神ころも― DL版 (files)\\戦巫〈センナギ〉―穢れた契りと神ころも―\\1\\script\"\r\n-t\r\n0"
|
||||
}
|
||||
}
|
||||
}
|
@ -54,6 +54,8 @@ namespace EscudeTools
|
||||
}
|
||||
}
|
||||
}
|
||||
if (results.Count == 0)
|
||||
return [];
|
||||
List<int> tmp = [];
|
||||
List<string> tmpS = [];
|
||||
for (int i = 0; i < ld.lli.Length; i++)
|
||||
@ -87,9 +89,9 @@ namespace EscudeTools
|
||||
foreach (string item in layer_fn)
|
||||
{
|
||||
string[] parts = item.Split("_");
|
||||
if (parts.Length == 3)
|
||||
if (parts.Length >= 3)
|
||||
{
|
||||
if (int.TryParse(parts[2], out int number))
|
||||
if (int.TryParse(parts[^1], out int number))
|
||||
{
|
||||
order.Add(number);
|
||||
}
|
||||
|
@ -4,6 +4,34 @@ using System.Text;
|
||||
|
||||
namespace EscudeTools
|
||||
{
|
||||
public class Const
|
||||
{
|
||||
//Types
|
||||
public const string INT8 = "System.SByte";
|
||||
public const string UINT8 = "System.Byte";
|
||||
public const string INT16 = "System.Int16";
|
||||
public const string UINT16 = "System.UInt16";
|
||||
public const string INT32 = "System.Int32";
|
||||
public const string UINT32 = "System.UInt32";
|
||||
public const string DOUBLE = "System.Double";
|
||||
public const string FLOAT = "System.Single";
|
||||
public const string INT64 = "System.Int64";
|
||||
public const string UINT64 = "System.UInt64";
|
||||
public const string STRING = "System.String";
|
||||
public const string DELEGATE = "System.MulticastDelegate";
|
||||
public const string CHAR = "System.Char";
|
||||
|
||||
//Attributes
|
||||
public const string PSTRING = "PString";
|
||||
public const string CSTRING = "CString";
|
||||
public const string UCSTRING = "UCString";
|
||||
public const string FSTRING = "FString";
|
||||
public const string STRUCT = "StructField";
|
||||
public const string IGNORE = "Ignore";
|
||||
public const string FARRAY = "FArray";
|
||||
public const string PARRAY = "PArray";
|
||||
public const string RARRAY = "RArray";
|
||||
}
|
||||
public class Utils
|
||||
{
|
||||
public static string ReadStringFromTextData(byte[] sheet_text, int offset)
|
||||
@ -77,7 +105,7 @@ namespace EscudeTools
|
||||
stream.CopyTo(fileStream);
|
||||
}
|
||||
|
||||
public static string GetSQLiteColumnType(ushort type, uint size)
|
||||
public static string GetSQLiteColumnType(ushort type)
|
||||
{
|
||||
if (type == 1)
|
||||
return "INTEGER";
|
||||
@ -164,5 +192,38 @@ namespace EscudeTools
|
||||
Buffer.BlockCopy(data, src, data, dst, count);
|
||||
}
|
||||
}
|
||||
public static dynamic Reverse(dynamic Data)
|
||||
{
|
||||
byte[] Arr = BitConverter.GetBytes(Data);
|
||||
Array.Reverse(Arr, 0, Arr.Length);
|
||||
string type = Data.GetType().FullName;
|
||||
return type switch
|
||||
{
|
||||
Const.INT8 or Const.UINT8 => Data,
|
||||
Const.INT16 => BitConverter.ToInt16(Arr, 0),
|
||||
Const.UINT16 => BitConverter.ToUInt16(Arr, 0),
|
||||
Const.INT32 => BitConverter.ToInt32(Arr, 0),
|
||||
Const.UINT32 => BitConverter.ToUInt32(Arr, 0),
|
||||
Const.INT64 => BitConverter.ToInt64(Arr, 0),
|
||||
Const.UINT64 => BitConverter.ToUInt64(Arr, 0),
|
||||
Const.DOUBLE => BitConverter.ToDouble(Arr, 0),
|
||||
Const.FLOAT => BitConverter.ToSingle(Arr, 0),
|
||||
_ => throw new Exception("Unk Data Type."),
|
||||
};
|
||||
}
|
||||
public static void WriteTo(uint Value, byte[] Binary, uint At)
|
||||
{
|
||||
BitConverter.GetBytes(Value).CopyTo(Binary, At);
|
||||
}
|
||||
|
||||
public static int SearchLzwEntryList(List<LzwEntry> lle, string keyword)
|
||||
{
|
||||
foreach (LzwEntry le in lle)
|
||||
{
|
||||
if (le.Name == keyword)
|
||||
return lle.IndexOf(le);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
110
README.md
110
README.md
@ -1,3 +1,111 @@
|
||||
# EscudeTools
|
||||
|
||||
程序尚未彻底完工,lsf图像合成需要搭配本程序的另一功能——提取db_*.bin为sqlite 使用
|
||||
### 已测试
|
||||
|
||||
- 悠刻のファムファタル (解封包正常、EV ST合成正常)
|
||||
|
||||
- 戦巫〈センナギ〉―穢れた契りと神ころも―(解包正常,EV ST合成正常)
|
||||
|
||||
- 廃村少女 ~妖し惑ひの籠の郷~ (解封包正常,EV合成正常,ST未知)
|
||||
|
||||
### 使用说明:
|
||||
|
||||
**1. 解包 ESC-ARC bin 文件:**
|
||||
命令:`EscudeTools.exe -u <路径>`
|
||||
|
||||
- **-u**: 解包 ESC-ARC bin 文件
|
||||
- 解包指定目录中的所有 ESC-ARC bin 文件。
|
||||
- 解包后的内容将保存在 `output` 目录中。
|
||||
- `*.json` 文件包含包信息;请勿删除(用于重新封包)。
|
||||
- `lzwManifest.json` 文件包含 LZW 文件信息;如果您希望不使用 LZW 压缩重新封包,请删除此文件。
|
||||
|
||||
------
|
||||
|
||||
**2. 重新封包 ESC-ARC bin 文件:**
|
||||
命令:`EscudeTools.exe -r (-c) <路径>`
|
||||
|
||||
- **-r**: 重新封包 ESC-ARC bin 文件
|
||||
- **-r -c**: 重新封包 ESC-ARC bin 文件并使用现有的自定义密钥
|
||||
- 重新封包指定目录中的所有文件夹为 ESC-ARC bin 格式。
|
||||
- 可选的 **-c** 标志用于使用自定义密钥(来自现有 ESC-ARC bin)。
|
||||
- 默认密钥为 ...(请查看源代码)。
|
||||
- 有关输出目录中 JSON 文件的说明,请参考上一条。
|
||||
|
||||
------
|
||||
|
||||
**3. 解包脚本 bin 文件:**
|
||||
命令:`EscudeTools.exe -v <路径> -t <类型>`
|
||||
|
||||
- **-v -t**: 解包脚本 bin 文件及其类型
|
||||
- 解包指定目录中的所有脚本 bin 文件到 SQLite 数据库中。
|
||||
- 忽略 001 文件;程序将在需要时读取它们。
|
||||
- 必须指定要解包的类型。
|
||||
- 支持以下类型:0、1、2
|
||||
- **类型 0**: 完整,这会创建包含所有 .bin 和 .001 信息的 `script.db`。
|
||||
- **类型 1**: 只导出 bin 中的文本,这会创建 `script_text.db` 以及大量 .dat 文件(非文本的其他数据)。
|
||||
- **类型 2**: 只导出 001 中的文本,这会创建 `script_sm.db`,包含所有 .001 信息。
|
||||
|
||||
------
|
||||
|
||||
**4. 重新封包脚本 bin 文件:**
|
||||
命令:`EscudeTools.exe -e <路径> -t <类型>`
|
||||
|
||||
- **-e -t**: 重新封包脚本 bin 文件及其类型
|
||||
- 重新封包指定目录中的所有 SQLite 数据库文件为脚本 bin 文件。
|
||||
- 必须指定要解包的类型。
|
||||
- 支持以下类型:0、1、2
|
||||
- **类型 0**: 完整,这会生成 .bin 和 .001 文件。
|
||||
- **类型 1**: 这会生成 .001 文件。
|
||||
- **类型 2**: 这会生成 .bin 文件。
|
||||
|
||||
------
|
||||
|
||||
**5. 解包 db_\*.bin 文件:**
|
||||
命令:`EscudeTools.exe -d <路径>`
|
||||
|
||||
- **-d**: 解包 db_*.bin 文件到 SQLite
|
||||
- 将路径下所有的 db_*.bin 文件导出到单独的 SQLite 数据库中。
|
||||
|
||||
------
|
||||
|
||||
**6. 重新封包 SQLite 数据库:**
|
||||
命令:`EscudeTools.exe -f <路径>`
|
||||
|
||||
- **-f**: 重新封包 SQLite 到 db_*.bin
|
||||
- 将路径下所有的 SQLite 数据库恢复为 db_*.bin 文件。
|
||||
|
||||
------
|
||||
|
||||
**7. 合成 EV 图像:**
|
||||
命令:`EscudeTools.exe -c <EvPath> <db_graphics.db 路径>`
|
||||
|
||||
- **-c**: 合成 EV 图像
|
||||
- 提供一组相同尺寸的 EV 图像和 `db_graphics.db` 来合成图像。
|
||||
|
||||
------
|
||||
|
||||
**8. 合成 ST 图像:**
|
||||
命令:`EscudeTools.exe -s <StPath> <db_graphics.db 路径>`
|
||||
|
||||
- **-s**: 合成 ST 图像
|
||||
- 提供一组相同尺寸的 ST 图像和 `db_graphics.db` 来合成图像。
|
||||
|
||||
------
|
||||
|
||||
**9. 打印帮助信息:**
|
||||
命令:`EscudeTools.exe -h`
|
||||
|
||||
- **-h**: 打印帮助信息
|
||||
|
||||
### 额外说明
|
||||
|
||||
- 因为匹配规则的问题,程序会跳过类似data\game_list.bin的文件(即非```db_*.bin```)。临时解决方法是在文件名开头手动补一下```db_```。
|
||||
|
||||
- ↑ 最好请先检查一下文件头是不是```mdb\0```
|
||||
|
||||
- ST不支持合成是因为暂时没找到哪个表里有与角色对应的表情信息(除了悠刻のファムファタル),后续我会尝试修复这一问题
|
||||
|
||||
### 感谢
|
||||
|
||||
- https://github.com/morkt/GARbro ESC-ARC bin解包方法
|
||||
- https://github.com/marcussacana/EscudeEditor lzw编码方法
|
Loading…
Reference in New Issue
Block a user