mirror of
https://github.com/crskycode/GARbro.git
synced 2026-07-08 01:30:18 +08:00
fixed NPK creation. (#30)
This commit is contained in:
@@ -101,7 +101,7 @@ namespace GameRes.Formats.NitroPlus
|
|||||||
int count = file.View.ReadInt32 (0x18);
|
int count = file.View.ReadInt32 (0x18);
|
||||||
if (!IsSaneCount (count))
|
if (!IsSaneCount (count))
|
||||||
return null;
|
return null;
|
||||||
var key = QueryEncryption();
|
var key = QueryEncryption (file.Name);
|
||||||
if (null == key)
|
if (null == key)
|
||||||
return null;
|
return null;
|
||||||
var aes = Aes.Create();
|
var aes = Aes.Create();
|
||||||
@@ -213,10 +213,18 @@ namespace GameRes.Formats.NitroPlus
|
|||||||
return new GUI.WidgetNPK();
|
return new GUI.WidgetNPK();
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] QueryEncryption ()
|
byte[] QueryEncryption (string arc_name)
|
||||||
{
|
{
|
||||||
var options = Query<Npk2Options> (arcStrings.ArcEncryptedNotice);
|
byte[] key = null;
|
||||||
return options.Key;
|
var title = FormatCatalog.Instance.LookupGame (arc_name);
|
||||||
|
if (!string.IsNullOrEmpty (title))
|
||||||
|
key = GetKey (title);
|
||||||
|
if (null == key)
|
||||||
|
{
|
||||||
|
var options = Query<Npk2Options> (arcStrings.ArcEncryptedNotice);
|
||||||
|
key = options.Key;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] GetKey (string title)
|
byte[] GetKey (string title)
|
||||||
@@ -230,6 +238,7 @@ namespace GameRes.Formats.NitroPlus
|
|||||||
class NpkStoredEntry : PackedEntry
|
class NpkStoredEntry : PackedEntry
|
||||||
{
|
{
|
||||||
public byte[] RawName;
|
public byte[] RawName;
|
||||||
|
public byte[] CheckSum;
|
||||||
public int SegmentCount;
|
public int SegmentCount;
|
||||||
public uint AlignedSize;
|
public uint AlignedSize;
|
||||||
}
|
}
|
||||||
@@ -249,7 +258,7 @@ namespace GameRes.Formats.NitroPlus
|
|||||||
var npk_entry = new NpkStoredEntry
|
var npk_entry = new NpkStoredEntry
|
||||||
{
|
{
|
||||||
Name = entry.Name,
|
Name = entry.Name,
|
||||||
RawName = enc.GetBytes (entry.Name),
|
RawName = enc.GetBytes (entry.Name.Replace ('\\', '/')),
|
||||||
SegmentCount = 0 == entry.Size ? 0 : 1,
|
SegmentCount = 0 == entry.Size ? 0 : 1,
|
||||||
};
|
};
|
||||||
dir.Add (npk_entry);
|
dir.Add (npk_entry);
|
||||||
@@ -287,16 +296,15 @@ namespace GameRes.Formats.NitroPlus
|
|||||||
using (var index_stream = new CryptoStream (proxy, encryptor, CryptoStreamMode.Write))
|
using (var index_stream = new CryptoStream (proxy, encryptor, CryptoStreamMode.Write))
|
||||||
using (var index = new BinaryWriter (index_stream))
|
using (var index = new BinaryWriter (index_stream))
|
||||||
{
|
{
|
||||||
var fill = new byte[0x20];
|
|
||||||
if (null != callback)
|
if (null != callback)
|
||||||
callback (callback_count++, null, arcStrings.MsgWritingIndex);
|
callback (callback_count++, null, arcStrings.MsgWritingIndex);
|
||||||
foreach (var entry in dir)
|
foreach (var entry in dir)
|
||||||
{
|
{
|
||||||
index.Write ((byte)0);
|
index.Write ((byte)1); // 0 -> segmentation enabled, 1 -> no segmentation
|
||||||
index.Write ((short)entry.RawName.Length);
|
index.Write ((short)entry.RawName.Length);
|
||||||
index.Write (entry.RawName);
|
index.Write (entry.RawName);
|
||||||
index.Write (entry.UnpackedSize);
|
index.Write (entry.UnpackedSize);
|
||||||
index.Write (fill);
|
index.Write (entry.CheckSum);
|
||||||
index.Write (entry.SegmentCount);
|
index.Write (entry.SegmentCount);
|
||||||
if (entry.SegmentCount > 0)
|
if (entry.SegmentCount > 0)
|
||||||
{
|
{
|
||||||
@@ -329,6 +337,7 @@ namespace GameRes.Formats.NitroPlus
|
|||||||
entry.UnpackedSize = (uint)file.Length;
|
entry.UnpackedSize = (uint)file.Length;
|
||||||
if (entry.Size > 0)
|
if (entry.Size > 0)
|
||||||
{
|
{
|
||||||
|
using (var sha256 = SHA256.Create())
|
||||||
using (var proxy = new ProxyStream (archive, true))
|
using (var proxy = new ProxyStream (archive, true))
|
||||||
{
|
{
|
||||||
var encryptor = aes.CreateEncryptor();
|
var encryptor = aes.CreateEncryptor();
|
||||||
@@ -337,11 +346,21 @@ namespace GameRes.Formats.NitroPlus
|
|||||||
output = measure;
|
output = measure;
|
||||||
if (ShouldCompress (entry.Name))
|
if (ShouldCompress (entry.Name))
|
||||||
output = new DeflateStream (output, CompressionLevel.Optimal);
|
output = new DeflateStream (output, CompressionLevel.Optimal);
|
||||||
|
var checksum = new CryptoStream (output, sha256, CryptoStreamMode.Write);
|
||||||
|
output = checksum;
|
||||||
using (output)
|
using (output)
|
||||||
|
{
|
||||||
file.CopyTo (output);
|
file.CopyTo (output);
|
||||||
|
checksum.FlushFinalBlock();
|
||||||
|
entry.CheckSum = sha256.Hash;
|
||||||
|
}
|
||||||
entry.Size = (uint)measure.Count;
|
entry.Size = (uint)measure.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry.CheckSum = EmptyFileHash;
|
||||||
|
}
|
||||||
entry.AlignedSize = (uint)(archive.Position - entry.Offset);
|
entry.AlignedSize = (uint)(archive.Position - entry.Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,6 +371,14 @@ namespace GameRes.Formats.NitroPlus
|
|||||||
filename.EndsWith (".ogg", StringComparison.InvariantCultureIgnoreCase) ||
|
filename.EndsWith (".ogg", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
filename.EndsWith (".mpg", StringComparison.InvariantCultureIgnoreCase));
|
filename.EndsWith (".mpg", StringComparison.InvariantCultureIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static readonly byte[] EmptyFileHash = GetDefaultHash();
|
||||||
|
|
||||||
|
static byte[] GetDefaultHash ()
|
||||||
|
{
|
||||||
|
using (var sha256 = SHA256.Create())
|
||||||
|
return sha256.ComputeHash (new byte[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class NpkStream : Stream
|
internal class NpkStream : Stream
|
||||||
|
|||||||
Reference in New Issue
Block a user