重新支持repack ESC-ARC bin

这里lzw FakeCompress来自marcussacana的EscudeEditor
*不用lzw压缩也没事,问题出在文件顺序上
This commit is contained in:
Chenx221 2024-10-27 11:59:46 +08:00
parent 390a4614b3
commit 3adf8c207a
Signed by: chenx221
GPG Key ID: D7A9EC07024C3021
6 changed files with 594 additions and 322 deletions

View 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;
}
}
}
}

View 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);
}
}
}

View File

@ -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 EscudeTools.Garbro;
using System.Drawing;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
@ -54,6 +58,10 @@ namespace EscudeTools
if (item == null) if (item == null)
return false; return false;
pItem = item; 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; isLoaded = true;
pFile = path; pFile = path;
@ -121,7 +129,7 @@ namespace EscudeTools
return null; return null;
Decrypt(ref index); Decrypt(ref index);
int index_offset = 0; 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) for (uint i = 0; i < m_count; ++i)
{ {
int filename_offset = (int)Utils.ToUInt32(index, index_offset); int filename_offset = (int)Utils.ToUInt32(index, index_offset);
@ -170,7 +178,7 @@ namespace EscudeTools
if (!Directory.Exists(output)) if (!Directory.Exists(output))
Directory.CreateDirectory(output); Directory.CreateDirectory(output);
var lzwManifest = new List<LzwEntry>(); 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 FileStream inputStream = new(pFile, FileMode.Open, FileAccess.Read);
using BinaryReader br = new(inputStream); using BinaryReader br = new(inputStream);
foreach (Entry entry in pItem) foreach (Entry entry in pItem)
@ -207,11 +215,11 @@ namespace EscudeTools
if (lzwManifest.Count > 0) if (lzwManifest.Count > 0)
{ {
//using (FileStream fs = File.Create(jsonPath)) using (FileStream fs = File.Create(jsonPath))
//{ {
// byte[] jsonBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(lzwManifest)); byte[] jsonBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(lzwManifest));
// fs.Write(jsonBytes, 0, jsonBytes.Length); fs.Write(jsonBytes, 0, jsonBytes.Length);
//} }
LzwDecode(lzwManifest, output); LzwDecode(lzwManifest, output);
}; };
@ -316,10 +324,10 @@ namespace EscudeTools
{ {
if (useCustomKey) if (useCustomKey)
LoadKey(customKeyProviderPath); LoadKey(customKeyProviderPath);
GeneratePItem(path); ReadPItem(path);
//if(File.Exists(Path.Combine(path, "lzwManifest.json"))) List<LzwEntry> lzwManifest = [];
// return false; if (File.Exists(Path.Combine(path, "lzwManifest.json")))
//Q:为什么不支持LZW打包 //A:因为我实在不想研究lzw算法欢迎PR lzwManifest = JsonSerializer.Deserialize<List<LzwEntry>>(File.ReadAllText(Path.Combine(path, "lzwManifest.json"))) ?? [];
m_seed = isLoaded ? LoadedKey : 2210579460; m_seed = isLoaded ? LoadedKey : 2210579460;
string outputPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileName(path) + ".bin"); string outputPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileName(path) + ".bin");
using (FileStream fs = new(outputPath, FileMode.Create)) using (FileStream fs = new(outputPath, FileMode.Create))
@ -343,8 +351,12 @@ namespace EscudeTools
Array.Copy(strbytes, result, lengthToCopy); Array.Copy(strbytes, result, lengthToCopy);
bw.Write(result); bw.Write(result);
bw.Write(storeOffset); bw.Write(storeOffset);
bw.Write(pItem[i].Size); uint size = pItem[i].Size;
storeOffset += 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 else
@ -361,10 +373,13 @@ namespace EscudeTools
indexOffset += 4; indexOffset += 4;
BitConverter.GetBytes(storeOffset).CopyTo(index, indexOffset); BitConverter.GetBytes(storeOffset).CopyTo(index, indexOffset);
indexOffset += 4; 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; indexOffset += 4;
filenameOffset += (uint)pItem[i].Name.Length + 1; filenameOffset += (uint)pItem[i].Name.Length + 1;
storeOffset += pItem[i].Size; storeOffset += size;
} }
Decrypt(ref index); Decrypt(ref index);
bw.Write(index); bw.Write(index);
@ -378,30 +393,73 @@ namespace EscudeTools
} }
foreach (Entry entry in pItem) foreach (Entry entry in pItem)
{ {
byte[] data = File.ReadAllBytes(Path.Combine(path, entry.Name)); byte[] data;
bw.Write(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; return true;
} }
private void GeneratePItem(string path) private void ReadPItem(string path)
{ {
pItem.Clear(); pItem.Clear();
var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories) //反序列化path上级的json文件
.Where(file => !file.EndsWith("lzwManifest.json", StringComparison.OrdinalIgnoreCase)) string jsonPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path) + ".json");
.ToArray(); if (File.Exists(jsonPath))
foreach (var file in files) pItem = JsonSerializer.Deserialize<List<Entry>>(File.ReadAllText(jsonPath)) ?? [];
{ else
var relativePath = Path.GetRelativePath(path, file); throw new Exception("No json file found.");
var fileInfo = new FileInfo(file); for (int i = 0; i < pItem.Count; i++)
pItem.Add(new Entry {
{ pItem[i].Size = (uint)new FileInfo(Path.Combine(path, pItem[i].Name)).Length;
Name = relativePath, }
Size = (uint)fileInfo.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; 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();
}
}
} }
} }

View File

@ -6,270 +6,270 @@ namespace EscudeTools
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
//批量处理EV/ST ////批量处理EV/ST
if (Directory.Exists(args[0]) && File.Exists(args[1])) //if (Directory.Exists(args[0]) && File.Exists(args[1]))
//if (File.Exists(args[0])) ////if (File.Exists(args[0]))
{ //{
string graphicsDBPath = args[1]; // string graphicsDBPath = args[1];
using SqliteConnection connection = new($"Data Source={graphicsDBPath};"); // using SqliteConnection connection = new($"Data Source={graphicsDBPath};");
connection.Open(); // connection.Open();
List<string> tableNames = []; // List<string> tableNames = [];
string[] foundTN = new string[3]; // string[] foundTN = new string[3];
List<int> tableIds = []; // List<int> tableIds = [];
bool found1 = false, found2 = false, found3 = false; // bool found1 = false, found2 = false, found3 = false;
using (var command = new SqliteCommand("SELECT name FROM sqlite_master WHERE type='table';", connection)) // using (var command = new SqliteCommand("SELECT name FROM sqlite_master WHERE type='table';", connection))
using (var reader = command.ExecuteReader()) // using (var reader = command.ExecuteReader())
{ // {
int id = 0; // int id = 0;
while (reader.Read()) // while (reader.Read())
{ // {
string tableName = reader.GetString(0); // string tableName = reader.GetString(0);
if (tableName.StartsWith("イベント")) // if (tableName.StartsWith("イベント"))
{ // {
foundTN[0] = tableName; // foundTN[0] = tableName;
found1 = true; // found1 = true;
} // }
else if (tableName.StartsWith("立ち")) // else if (tableName.StartsWith("立ち"))
{ // {
foundTN[1] = tableName; // foundTN[1] = tableName;
found2 = true; // found2 = true;
} // }
else if (tableName.StartsWith("表情")) // else if (tableName.StartsWith("表情"))
{ // {
foundTN[2] = tableName; // foundTN[2] = tableName;
found3 = true; // found3 = true;
} // }
tableNames.Add(tableName); // tableNames.Add(tableName);
tableIds.Add(id++); // tableIds.Add(id++);
} // }
} // }
if (!(found1 && found2 && found3)) //这里的代码未经测试 // if (!(found1 && found2 && found3)) //这里的代码未经测试
{ // {
for (int i = 0; i < tableNames.Count; i++) // for (int i = 0; i < tableNames.Count; i++)
Console.WriteLine($"{tableIds[i]}: {tableNames[i]}"); // Console.WriteLine($"{tableIds[i]}: {tableNames[i]}");
if (!found1) // if (!found1)
{ // {
Console.WriteLine("自动识别失败请选择存放CG信息的数据表ID: "); // Console.WriteLine("自动识别失败请选择存放CG信息的数据表ID: ");
string? input = Console.ReadLine(); // string? input = Console.ReadLine();
if (int.TryParse(input, out int userInputId)) // if (int.TryParse(input, out int userInputId))
{ // {
if (userInputId >= 0 && userInputId < tableIds.Count) // if (userInputId >= 0 && userInputId < tableIds.Count)
{ // {
foundTN[0] = tableNames[userInputId]; // foundTN[0] = tableNames[userInputId];
} // }
else // else
{ // {
Console.WriteLine("Invalid ID."); // Console.WriteLine("Invalid ID.");
return; // return;
} // }
} // }
else // else
{ // {
Console.WriteLine("Invalid input. Please enter a valid number."); // Console.WriteLine("Invalid input. Please enter a valid number.");
return; // return;
} // }
} // }
if (!found2) // if (!found2)
{ // {
Console.WriteLine("自动识别失败请选择存放立绘信息的数据表ID: "); // Console.WriteLine("自动识别失败请选择存放立绘信息的数据表ID: ");
string? input = Console.ReadLine(); // string? input = Console.ReadLine();
if (int.TryParse(input, out int userInputId)) // if (int.TryParse(input, out int userInputId))
{ // {
if (userInputId >= 0 && userInputId < tableIds.Count) // if (userInputId >= 0 && userInputId < tableIds.Count)
{ // {
foundTN[1] = tableNames[userInputId]; // foundTN[1] = tableNames[userInputId];
} // }
else // else
{ // {
Console.WriteLine("Invalid ID."); // Console.WriteLine("Invalid ID.");
return; // return;
} // }
} // }
else // else
{ // {
Console.WriteLine("Invalid input. Please enter a valid number."); // Console.WriteLine("Invalid input. Please enter a valid number.");
return; // return;
} // }
} // }
if (!found3) // if (!found3)
{ // {
Console.WriteLine("自动识别失败请选择存放表情信息的数据表ID: "); // Console.WriteLine("自动识别失败请选择存放表情信息的数据表ID: ");
string? input = Console.ReadLine(); // string? input = Console.ReadLine();
if (int.TryParse(input, out int userInputId)) // if (int.TryParse(input, out int userInputId))
{ // {
if (userInputId >= 0 && userInputId < tableIds.Count) // if (userInputId >= 0 && userInputId < tableIds.Count)
{ // {
foundTN[2] = tableNames[userInputId]; // foundTN[2] = tableNames[userInputId];
} // }
else // else
{ // {
Console.WriteLine("Invalid ID."); // Console.WriteLine("Invalid ID.");
return; // return;
} // }
} // }
else // else
{ // {
Console.WriteLine("Invalid input. Please enter a valid number."); // Console.WriteLine("Invalid input. Please enter a valid number.");
return; // return;
} // }
} // }
} // }
List<EvTable> evts = []; // List<EvTable> evts = [];
List<StTable> stts = []; // List<StTable> stts = [];
Face[] faces = new Face[32]; // Face[] faces = new Face[32];
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[0]};", connection)) // using (var command = new SqliteCommand($"SELECT * FROM {foundTN[0]};", connection))
{ // {
using var reader = command.ExecuteReader(); // using var reader = command.ExecuteReader();
while (reader.Read()) // while (reader.Read())
{ // {
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0))) // if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
continue; // continue;
evts.Add(new EvTable // evts.Add(new EvTable
{ // {
name = reader.GetString(0), // name = reader.GetString(0),
file = reader.GetString(1), // file = reader.GetString(1),
option = reader.GetString(2).Split(' '), // option = reader.GetString(2).Split(' '),
coverd = (uint)reader.GetInt32(3), // coverd = (uint)reader.GetInt32(3),
filter = (uint)reader.GetInt32(4), // filter = (uint)reader.GetInt32(4),
color = (uint)reader.GetInt32(5), // color = (uint)reader.GetInt32(5),
id = (uint)reader.GetInt32(6), // id = (uint)reader.GetInt32(6),
loc = (uint)reader.GetInt32(7), // loc = (uint)reader.GetInt32(7),
order = reader.GetInt32(8), // order = reader.GetInt32(8),
link = (uint)reader.GetInt32(9) // link = (uint)reader.GetInt32(9)
}); // });
} // }
} // }
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[1]};", connection)) // using (var command = new SqliteCommand($"SELECT * FROM {foundTN[1]};", connection))
{ // {
using var reader = command.ExecuteReader(); // using var reader = command.ExecuteReader();
while (reader.Read()) // while (reader.Read())
{ // {
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0))) // if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
continue; // continue;
stts.Add(new StTable // stts.Add(new StTable
{ // {
name = reader.GetString(0), // name = reader.GetString(0),
file = reader.GetString(1), // file = reader.GetString(1),
option = reader.GetString(2).Split(' '), // option = reader.GetString(2).Split(' '),
coverd = (uint)reader.GetInt32(3), // coverd = (uint)reader.GetInt32(3),
filter = (uint)reader.GetInt32(4), // filter = (uint)reader.GetInt32(4),
face = (uint)reader.GetInt32(5), // face = (uint)reader.GetInt32(5),
id = (uint)reader.GetInt32(6), // id = (uint)reader.GetInt32(6),
loc = (uint)reader.GetInt32(7), // loc = (uint)reader.GetInt32(7),
order = reader.GetInt32(8), // order = reader.GetInt32(8),
link = (uint)reader.GetInt32(9) // link = (uint)reader.GetInt32(9)
}); // });
} // }
} // }
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[2]};", connection)) // using (var command = new SqliteCommand($"SELECT * FROM {foundTN[2]};", connection))
{ // {
using var reader = command.ExecuteReader(); // using var reader = command.ExecuteReader();
while (reader.Read()) // while (reader.Read())
{ // {
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0))) // if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
continue; // continue;
for (int i = 0; i < faces.Length; i++) // for (int i = 0; i < faces.Length; i++)
{ // {
if (faces[i] == null) // if (faces[i] == null)
faces[i] = new Face(); // faces[i] = new Face();
if (reader.GetInt32(2 + i) == 1) // if (reader.GetInt32(2 + i) == 1)
faces[i].faceOptions.Add(reader.GetString(1)); // faces[i].faceOptions.Add(reader.GetString(1));
} // }
} // }
} // }
string[] files = Directory.GetFiles(args[0], "*.lsf", SearchOption.AllDirectories); // string[] files = Directory.GetFiles(args[0], "*.lsf", SearchOption.AllDirectories);
LsfManager lm = new(); // LsfManager lm = new();
foreach (string file in files) // foreach (string file in files)
{ // {
if (lm.LoadLsf(file, true)) // if (lm.LoadLsf(file, true))
Console.WriteLine($"Load {file} Success"); // Console.WriteLine($"Load {file} Success");
else // else
{ // {
Console.WriteLine($"Load {file} Failed"); // Console.WriteLine($"Load {file} Failed");
} // }
} // }
connection.Close(); // connection.Close();
string outputDir = Path.Combine(Path.GetDirectoryName(args[0]), "Output"); // string outputDir = Path.Combine(Path.GetDirectoryName(args[0]), "Output");
if (!Directory.Exists(outputDir)) // if (!Directory.Exists(outputDir))
Directory.CreateDirectory(outputDir); // Directory.CreateDirectory(outputDir);
var parallelOptions = new ParallelOptions // var parallelOptions = new ParallelOptions
{ // {
MaxDegreeOfParallelism = 6 // 设置最大并行线程数 // MaxDegreeOfParallelism = 6 // 设置最大并行线程数
}; // };
// //ST //表情还要另取? // // //ST //表情还要另取?
// Parallel.ForEach(stts, parallelOptions, stt => // // Parallel.ForEach(stts, parallelOptions, stt =>
// //foreach (StTable stt in stts) // // //foreach (StTable stt in stts)
// { // // {
// if (stt.order == 0) //仅提取鉴赏中有的ST // // if (stt.order == 0) //仅提取鉴赏中有的ST
// return; // // return;
// //continue; // // //continue;
// string targetFilename = Path.Combine(outputDir, stt.name); //最后保存可用的文件名 // // string targetFilename = Path.Combine(outputDir, stt.name); //最后保存可用的文件名
// LsfData? lsfData = lm.FindLsfDataByName(stt.file) ?? throw new Exception($"错误,未找到与{stt.file}对应的lsf数据"); // // LsfData? lsfData = lm.FindLsfDataByName(stt.file) ?? throw new Exception($"错误,未找到与{stt.file}对应的lsf数据");
// List<int> pendingList = []; // // List<int> pendingList = [];
// List<string> pendingListFn = []; // // List<string> pendingListFn = [];
// foreach (string o in stt.option) // // foreach (string o in stt.option)
// { // // {
// List<int> t = TableManagercs.ParseOptions(lsfData, o); // // List<int> t = TableManagercs.ParseOptions(lsfData, o);
// if (t.Count == 0) // // if (t.Count == 0)
// continue; // // continue;
// pendingList.AddRange(t); // // pendingList.AddRange(t);
// foreach (int i in t) // // foreach (int i in t)
// { // // {
// pendingListFn.Add(lsfData.lli[i].nameStr); // // pendingListFn.Add(lsfData.lli[i].nameStr);
// } // // }
// } // // }
// pendingList = TableManagercs.OrderLayer(pendingList, pendingListFn); // // pendingList = TableManagercs.OrderLayer(pendingList, pendingListFn);
// int n = 0; // // int n = 0;
// foreach (string o in faces[(int)stt.face].faceOptions) // // foreach (string o in faces[(int)stt.face].faceOptions)
// { // // {
// List<int> pendingListCopy = new(pendingList); // // List<int> pendingListCopy = new(pendingList);
// List<int> t = TableManagercs.ParseOptions(lsfData, o); // // List<int> t = TableManagercs.ParseOptions(lsfData, o);
// if (t.Count == 0) // // if (t.Count == 0)
// continue; // // continue;
// pendingListCopy.AddRange(t); // // pendingListCopy.AddRange(t);
// if (!ImageManager.Process(lsfData, [.. pendingListCopy], targetFilename + $"_{n++}.png")) // // if (!ImageManager.Process(lsfData, [.. pendingListCopy], targetFilename + $"_{n++}.png"))
// throw new Exception("Process Fail"); // // throw new Exception("Process Fail");
// else // // else
// Console.WriteLine($"Export {stt.name}_{n - 1} Success"); // // Console.WriteLine($"Export {stt.name}_{n - 1} Success");
// } // // }
// }); // // });
////} // ////}
//EV // //EV
Parallel.ForEach(evts, parallelOptions, evt => // Parallel.ForEach(evts, parallelOptions, evt =>
//foreach (EvTable evt in evts) // //foreach (EvTable evt in evts)
{ //{
if (evt.order == 0) //仅提取鉴赏中有的CG // if (evt.order == 0) //仅提取鉴赏中有的CG
return; // return;
//continue; // //continue;
string targetFilename = Path.Combine(outputDir, evt.name + ".png"); //最后保存可用的文件名 // string targetFilename = Path.Combine(outputDir, evt.name + ".png"); //最后保存可用的文件名
LsfData lsfData = lm.FindLsfDataByName(evt.file) ?? throw new Exception("Something Wrong"); // LsfData lsfData = lm.FindLsfDataByName(evt.file) ?? throw new Exception("Something Wrong");
List<int> pendingList = []; // List<int> pendingList = [];
List<string> pendingListFn = []; // List<string> pendingListFn = [];
foreach (string o in evt.option) // foreach (string o in evt.option)
{ // {
List<int> t = TableManagercs.ParseOptions(lsfData, o); // List<int> t = TableManagercs.ParseOptions(lsfData, o);
if (t.Count == 0) // if (t.Count == 0)
continue; // continue;
pendingList.AddRange(t); // pendingList.AddRange(t);
foreach (int i in t) // foreach (int i in t)
{ // {
pendingListFn.Add(lsfData.lli[i].nameStr); // pendingListFn.Add(lsfData.lli[i].nameStr);
} // }
} // }
pendingList = TableManagercs.OrderLayer(pendingList, pendingListFn); // pendingList = TableManagercs.OrderLayer(pendingList, pendingListFn);
if (pendingList[0] != 0) // if (pendingList[0] != 0)
pendingList.Insert(0, 0); // pendingList.Insert(0, 0);
if (!ImageManager.Process(lsfData, [.. pendingList], targetFilename)) // if (!ImageManager.Process(lsfData, [.. pendingList], targetFilename))
throw new Exception("Process Fail"); // throw new Exception("Process Fail");
else // else
Console.WriteLine($"Export {evt.name} Success"); // Console.WriteLine($"Export {evt.name} Success");
}); //});
//} // //}
} //}
@ -313,39 +313,32 @@ namespace EscudeTools
// if (pm.Load(file)) // if (pm.Load(file))
// { // {
// Console.WriteLine($"Load {file} Success"); // Console.WriteLine($"Load {file} Success");
// if (pm.Extract())
// Console.WriteLine("Extract Package Success");
// else
// Console.WriteLine("Extract Package Failed");
// } // }
// else // else
// {
// Console.WriteLine($"Load {file} Failed"); // Console.WriteLine($"Load {file} Failed");
// }
// if (pm.Extract())
// Console.WriteLine("Extract Package Success");
// else
// {
// Console.WriteLine("Extract Package Failed");
// }
// } // }
//} //}
////不支持script data打包因为这几个封包游戏强制lzw压缩读取 //Batch Repack ESC-ARC Package
////而我没写出lzw压缩代码 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)
// string[] directories = Directory.GetDirectories(args[0]); {
// foreach (string directory in directories) PackManager pm = new();
// { //string providerFilePath = Path.Combine(args[1], Path.GetFileName(directory) + ".bin");
// PackManager pm = new(); if (pm.Repack(directory, 2, true))
// //string providerFilePath = Path.Combine(args[1], Path.GetFileName(directory) + ".bin"); Console.WriteLine("Repack Package Success");
// if (pm.Repack(directory, 2, true)) else
// Console.WriteLine("Repack Package Success"); {
// else Console.WriteLine("Repack Package Failed");
// { }
// Console.WriteLine("Repack Package Failed"); }
// } }
// }
//}
////Batch Unpack Script(Full, Text, Mess) ////Batch Unpack Script(Full, Text, Mess)

View File

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

View File

@ -4,6 +4,34 @@ using System.Text;
namespace EscudeTools 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 class Utils
{ {
public static string ReadStringFromTextData(byte[] sheet_text, int offset) public static string ReadStringFromTextData(byte[] sheet_text, int offset)
@ -164,5 +192,49 @@ namespace EscudeTools
Buffer.BlockCopy(data, src, data, dst, count); 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;
switch (type)
{
case Const.INT8:
case Const.UINT8:
return Data;
case Const.INT16:
return BitConverter.ToInt16(Arr, 0);
case Const.UINT16:
return BitConverter.ToUInt16(Arr, 0);
case Const.INT32:
return BitConverter.ToInt32(Arr, 0);
case Const.UINT32:
return BitConverter.ToUInt32(Arr, 0);
case Const.INT64:
return BitConverter.ToInt64(Arr, 0);
case Const.UINT64:
return BitConverter.ToUInt64(Arr, 0);
case Const.DOUBLE:
return BitConverter.ToDouble(Arr, 0);
case Const.FLOAT:
return BitConverter.ToSingle(Arr, 0);
default:
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;
}
} }
} }