/// <summary> /// 解压到路径。 /// </summary> /// <param name="InFile">文件路径</param> /// <param name="OutDirectory">解压路径</param> public static void Unpack(string InFile, string OutDirectory) { using (FileStream pak = File.OpenRead(InFile)) { if (PakUtils.CheckMagic(pak, "GsPack4 abc")) { if (OutDirectory == null || OutDirectory.Length == 0) { OutDirectory = Path.GetFileName(InFile); } Directory.CreateDirectory(OutDirectory); Pak_Header pak_header = PakUtils.ToStruct <Pak_Header>(pak); pak.Seek(pak_header.index_offset, SeekOrigin.Begin); byte[] pak_compress = new byte[pak_header.index_length]; pak.Read(pak_compress, 0, pak_compress.Length); byte[] pak_decompress = PakUtils.LZSS.Decompress(pak_compress); Pak_Entry[] pak_entries = PakUtils.ToStructArray <Pak_Entry>(pak_decompress); for (int i = 0; i < pak_entries.Length; i++) { Pak_Entry pak_entry = pak_entries[i]; pak.Seek(pak_header.data_offset, SeekOrigin.Begin); pak.Seek(pak_entry.offset, SeekOrigin.Current); byte[] data = new byte[pak_entry.length]; pak.Read(data, 0, (int)pak_entry.length); using (MemoryStream data_stream = new MemoryStream(data)) { if (PakUtils.CheckMagic(data_stream, "Scw4.x")) { UnpackScw4(OutDirectory, pak_entry, data_stream); } else { // TODO 处理图片文件 } } } } else { throw new PakException.MagicMissMatching(Path.GetFileName(InFile)); } } }
private static void UnpackScw4(string OutDirectory, Pak_Entry pak_entry, MemoryStream data_stream) { //解压缩 Scw_Header scw4_header = PakUtils.ToStruct <Scw_Header>(data_stream); byte[] scw_compress = new byte[scw4_header.comprlen]; data_stream.Read(scw_compress, 0, scw_compress.Length); if (scw4_header.is_compr == -1) { for (int i = 0; i < scw_compress.Length; i++) { scw_compress[i] ^= Convert.ToByte(i & 0xFF); } } byte[] scw_decompress = PakUtils.LZSS.Decompress(scw_compress); using (MemoryStream decompress_stream = new MemoryStream(scw_decompress)) { string directory = Path.Combine(OutDirectory, pak_entry.name); Directory.CreateDirectory(directory); int size = Marshal.SizeOf(typeof(Scw4_Entry)); byte[] instruction_table = new byte[scw4_header.instruction_table_entries * size]; decompress_stream.Read(instruction_table, 0, instruction_table.Length); File.WriteAllBytes(Path.Combine(directory, "instruction_table.bin"), instruction_table); Scw4_Entry[] instruction_entries = PakUtils.ToStructArray <Scw4_Entry>(instruction_table); byte[] script_table = new byte[scw4_header.string_table_entries * size]; decompress_stream.Read(script_table, 0, script_table.Length); Scw4_Entry[] script_entries = PakUtils.ToStructArray <Scw4_Entry>(script_table); byte[] method_table = new byte[scw4_header.unknown_table_entries * size]; decompress_stream.Read(method_table, 0, method_table.Length); File.WriteAllBytes(Path.Combine(directory, "method_table.bin"), method_table); Scw4_Entry[] method_entries = PakUtils.ToStructArray <Scw4_Entry>(method_table); using (BinaryWriter writer = new BinaryWriter(File.Open(Path.Combine(directory, "instruction.bin"), FileMode.Create))) { foreach (Scw4_Entry scw_entry in instruction_entries) { byte[] data = new byte[scw_entry.length]; decompress_stream.Read(data, 0, data.Length); writer.Write(data); } } using (StreamWriter writer = new StreamWriter(Path.Combine(OutDirectory, pak_entry.name + ".txt"), false, Encoding.GetEncoding("GB2312"))) //using (StreamWriter writer = new StreamWriter(Path.Combine(directory, "script.txt"), false, Encoding.GetEncoding("GB2312"))) { foreach (Scw4_Entry scw_entry in script_entries) { byte[] data = new byte[scw_entry.length]; decompress_stream.Read(data, 0, data.Length); string text = Encoding.GetEncoding("Shift_JIS").GetString(data); writer.WriteLine($":{text}"); writer.WriteLine($":{text}"); writer.WriteLine(); } } using (BinaryWriter writer = new BinaryWriter(File.Open(Path.Combine(directory, "method.bin"), FileMode.Create))) { long length = decompress_stream.Length - decompress_stream.Position; byte[] data = new byte[length]; decompress_stream.Read(data, 0, data.Length); writer.Write(data); } } }