mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 11:54:13 +08:00
implemented Entis archives decryption.
This commit is contained in:
parent
6fa4b53299
commit
d2eb1bbf8f
@ -1,4 +1,4 @@
|
|||||||
//! \file ArcNOA.cs
|
//! \file ArcNOA.cs
|
||||||
//! \date Thu Apr 23 15:57:17 2015
|
//! \date Thu Apr 23 15:57:17 2015
|
||||||
//! \brief Entis GLS engine archives implementation.
|
//! \brief Entis GLS engine archives implementation.
|
||||||
//
|
//
|
||||||
@ -26,11 +26,21 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using GameRes.Formats.Properties;
|
||||||
|
using GameRes.Formats.Strings;
|
||||||
using GameRes.Utility;
|
using GameRes.Utility;
|
||||||
|
|
||||||
namespace GameRes.Formats.Entis
|
namespace GameRes.Formats.Entis
|
||||||
{
|
{
|
||||||
|
internal class NoaOptions : ResourceOptions
|
||||||
|
{
|
||||||
|
public string Scheme { get; set; }
|
||||||
|
public string PassPhrase { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
internal class NoaEntry : Entry
|
internal class NoaEntry : Entry
|
||||||
{
|
{
|
||||||
public byte[] Extra;
|
public byte[] Extra;
|
||||||
@ -38,6 +48,17 @@ namespace GameRes.Formats.Entis
|
|||||||
public uint Attr;
|
public uint Attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class NoaArchive : ArcFile
|
||||||
|
{
|
||||||
|
public string Password;
|
||||||
|
|
||||||
|
public NoaArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, string password = null)
|
||||||
|
: base (arc, impl, dir)
|
||||||
|
{
|
||||||
|
Password = password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Export(typeof(ArchiveFormat))]
|
[Export(typeof(ArchiveFormat))]
|
||||||
public class NoaOpener : ArchiveFormat
|
public class NoaOpener : ArchiveFormat
|
||||||
{
|
{
|
||||||
@ -47,6 +68,28 @@ namespace GameRes.Formats.Entis
|
|||||||
public override bool IsHierarchic { get { return false; } }
|
public override bool IsHierarchic { get { return false; } }
|
||||||
public override bool CanCreate { get { return false; } }
|
public override bool CanCreate { get { return false; } }
|
||||||
|
|
||||||
|
public NoaOpener ()
|
||||||
|
{
|
||||||
|
Extensions = new string[] { "noa", "dat" };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly Dictionary<string, Dictionary<string, string>> KnownKeys =
|
||||||
|
new Dictionary<string, Dictionary<string, string>> {
|
||||||
|
{ arcStrings.NOAIgnoreEncryption, new Dictionary<string, string>() },
|
||||||
|
{ "Yatohime Zankikou", new Dictionary<string, string> {
|
||||||
|
{ "data1.noa", "arcdatapass" },
|
||||||
|
{ "data6.noa", "cfe7231hf9qccda" },
|
||||||
|
{ "data7.noa", "ceiuvw86680efq0hHDUHF673j" } } },
|
||||||
|
{ "You! Apron Chakuyou", new Dictionary<string, string> {
|
||||||
|
{ "containerb.noa", "7DQ1Xm7ZahIv1ZwlFgyMTMryKC6OP9V6cAgL64WD5JLyvmeEyqTSA5rUbRigOtebnnK4MuOptwsbOf4K8UBDH4kpAUOQgB71Qr1qxtHGxQl8KZKj6WIYWpPh0G3JOJat" } } },
|
||||||
|
{ "Do S Ane to Boku no Hounyou Kankei", new Dictionary<string, string> {
|
||||||
|
{ "d02.dat", "vwerc7s65r21bnfu" },
|
||||||
|
{ "d03.dat", "ctfvgbhnj67y8u" } } },
|
||||||
|
{ "Innyuu Famiresu", new Dictionary<string, string> {
|
||||||
|
{ "d01.dat", "vdiu$43AfUCfh9aksf" },
|
||||||
|
{ "d03.dat", "gaivnwq7365e021gf" } } },
|
||||||
|
};
|
||||||
|
|
||||||
public override ArcFile TryOpen (ArcView file)
|
public override ArcFile TryOpen (ArcView file)
|
||||||
{
|
{
|
||||||
if (!file.View.AsciiEqual (0, "Entis\x1a"))
|
if (!file.View.AsciiEqual (0, "Entis\x1a"))
|
||||||
@ -57,7 +100,27 @@ namespace GameRes.Formats.Entis
|
|||||||
var reader = new IndexReader (file);
|
var reader = new IndexReader (file);
|
||||||
if (!reader.ParseDirEntry (0x40, ""))
|
if (!reader.ParseDirEntry (0x40, ""))
|
||||||
return null;
|
return null;
|
||||||
return new ArcFile (file, this, reader.Dir);
|
if (!reader.HasEncrypted)
|
||||||
|
return new ArcFile (file, this, reader.Dir);
|
||||||
|
|
||||||
|
var options = Query<NoaOptions> (arcStrings.ArcEncryptedNotice);
|
||||||
|
string password = null;
|
||||||
|
if (!string.IsNullOrEmpty (options.PassPhrase))
|
||||||
|
{
|
||||||
|
password = options.PassPhrase;
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty (options.Scheme))
|
||||||
|
{
|
||||||
|
Dictionary<string, string> filemap;
|
||||||
|
if (KnownKeys.TryGetValue (options.Scheme, out filemap))
|
||||||
|
{
|
||||||
|
var filename = Path.GetFileName (file.Name).ToLowerInvariant();
|
||||||
|
filemap.TryGetValue (filename, out password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty (password))
|
||||||
|
return new ArcFile (file, this, reader.Dir);
|
||||||
|
return new NoaArchive (file, this, reader.Dir, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||||
@ -66,28 +129,84 @@ namespace GameRes.Formats.Entis
|
|||||||
if (null == nent || !arc.File.View.AsciiEqual (entry.Offset, "filedata"))
|
if (null == nent || !arc.File.View.AsciiEqual (entry.Offset, "filedata"))
|
||||||
return arc.File.CreateStream (entry.Offset, entry.Size);
|
return arc.File.CreateStream (entry.Offset, entry.Size);
|
||||||
ulong size = arc.File.View.ReadUInt64 (entry.Offset+8);
|
ulong size = arc.File.View.ReadUInt64 (entry.Offset+8);
|
||||||
if (size > uint.MaxValue)
|
if (size > int.MaxValue)
|
||||||
throw new FileSizeException();
|
throw new FileSizeException();
|
||||||
if (0 == nent.Encryption)
|
if (0 == size)
|
||||||
return arc.File.CreateStream (entry.Offset+0x10, (uint)size);
|
return Stream.Null;
|
||||||
if (0x40000000 != nent.Encryption)
|
|
||||||
|
var input = arc.File.CreateStream (entry.Offset+0x10, (uint)size);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
System.Diagnostics.Trace.WriteLine (string.Format ("{0}: unknown encryption scheme 0x{1:x8}",
|
var narc = arc as NoaArchive;
|
||||||
nent.Name, nent.Encryption));
|
if (0 == nent.Encryption || size < 4 || null == narc || null == narc.Password)
|
||||||
return arc.File.CreateStream (entry.Offset+0x10, (uint)size);
|
return input;
|
||||||
|
if (0x40000000 != nent.Encryption)
|
||||||
|
{
|
||||||
|
Trace.WriteLine (string.Format ("{0}: unknown encryption scheme 0x{1:x8}",
|
||||||
|
nent.Name, nent.Encryption));
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
uint nTotalBytes = (uint)(size - 4);
|
||||||
|
var pBSHF = new BSHFDecodeContext (0x10000);
|
||||||
|
pBSHF.AttachInputFile (input);
|
||||||
|
pBSHF.PrepareToDecodeBSHFCode (narc.Password);
|
||||||
|
|
||||||
|
byte[] buf = new byte[nTotalBytes];
|
||||||
|
uint decoded = pBSHF.DecodeBSHFCodeBytes (buf, nTotalBytes);
|
||||||
|
if (decoded < nTotalBytes)
|
||||||
|
throw new EndOfStreamException ("Unexpected end of encrypted stream");
|
||||||
|
/*
|
||||||
|
byte[] bufCRC = new byte[4];
|
||||||
|
int iCRC = 0;
|
||||||
|
for (int i = 0; i < buf.Length; ++i)
|
||||||
|
{
|
||||||
|
bufCRC[iCRC] ^= buf[i];
|
||||||
|
iCRC = (iCRC + 1) & 0x03;
|
||||||
|
}
|
||||||
|
uint orgCRC = arc.File.View.ReadUInt32 (entry.Offset+0x10+nTotalBytes);
|
||||||
|
uint crc = LittleEndian.ToUInt32 (bufCRC, 0);
|
||||||
|
if (orgCRC != crc)
|
||||||
|
{
|
||||||
|
Trace.WriteLine (string.Format ("{0}: CRC mismatch", nent.Name));
|
||||||
|
input.Position = 0;
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
input.Dispose();
|
||||||
|
return new MemoryStream (buf);
|
||||||
}
|
}
|
||||||
return arc.File.CreateStream (entry.Offset+0x10, (uint)size);
|
catch
|
||||||
|
{
|
||||||
|
input.Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ResourceOptions GetDefaultOptions ()
|
||||||
|
{
|
||||||
|
return new NoaOptions {
|
||||||
|
Scheme = Settings.Default.NOAScheme,
|
||||||
|
PassPhrase = Settings.Default.NOAPassPhrase,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object GetAccessWidget ()
|
||||||
|
{
|
||||||
|
return new GUI.WidgetNOA();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class IndexReader
|
internal class IndexReader
|
||||||
{
|
{
|
||||||
ArcView m_file;
|
ArcView m_file;
|
||||||
List<Entry> m_dir = new List<Entry>();
|
List<Entry> m_dir = new List<Entry>();
|
||||||
|
bool m_found_encrypted = false;
|
||||||
|
|
||||||
const char PathSeparatorChar = '/';
|
const char PathSeparatorChar = '/';
|
||||||
|
|
||||||
public List<Entry> Dir { get { return m_dir; } }
|
public List<Entry> Dir { get { return m_dir; } }
|
||||||
|
|
||||||
|
public bool HasEncrypted { get { return m_found_encrypted; } }
|
||||||
|
|
||||||
public IndexReader (ArcView file)
|
public IndexReader (ArcView file)
|
||||||
{
|
{
|
||||||
m_file = file;
|
m_file = file;
|
||||||
@ -113,14 +232,20 @@ namespace GameRes.Formats.Entis
|
|||||||
var entry = new NoaEntry();
|
var entry = new NoaEntry();
|
||||||
entry.Size = m_file.View.ReadUInt32 (dir_offset);
|
entry.Size = m_file.View.ReadUInt32 (dir_offset);
|
||||||
dir_offset += 8;
|
dir_offset += 8;
|
||||||
|
|
||||||
entry.Attr = m_file.View.ReadUInt32 (dir_offset);
|
entry.Attr = m_file.View.ReadUInt32 (dir_offset);
|
||||||
dir_offset += 4;
|
dir_offset += 4;
|
||||||
|
|
||||||
entry.Encryption = m_file.View.ReadUInt32 (dir_offset);
|
entry.Encryption = m_file.View.ReadUInt32 (dir_offset);
|
||||||
|
if (0 != entry.Encryption)
|
||||||
|
m_found_encrypted = true;
|
||||||
dir_offset += 4;
|
dir_offset += 4;
|
||||||
|
|
||||||
entry.Offset = base_offset + m_file.View.ReadInt64 (dir_offset);
|
entry.Offset = base_offset + m_file.View.ReadInt64 (dir_offset);
|
||||||
if (!entry.CheckPlacement (m_file.MaxOffset))
|
if (!entry.CheckPlacement (m_file.MaxOffset))
|
||||||
return false;
|
return false;
|
||||||
dir_offset += 0x10;
|
dir_offset += 0x10;
|
||||||
|
|
||||||
uint extra_length = m_file.View.ReadUInt32 (dir_offset);
|
uint extra_length = m_file.View.ReadUInt32 (dir_offset);
|
||||||
dir_offset += 4;
|
dir_offset += 4;
|
||||||
if (extra_length > 0 && 0 == (entry.Attr & 0x70))
|
if (extra_length > 0 && 0 == (entry.Attr & 0x70))
|
||||||
@ -132,12 +257,15 @@ namespace GameRes.Formats.Entis
|
|||||||
dir_offset += extra_length;
|
dir_offset += extra_length;
|
||||||
uint name_length = m_file.View.ReadUInt32 (dir_offset);
|
uint name_length = m_file.View.ReadUInt32 (dir_offset);
|
||||||
dir_offset += 4;
|
dir_offset += 4;
|
||||||
|
|
||||||
string name = m_file.View.ReadString (dir_offset, name_length);
|
string name = m_file.View.ReadString (dir_offset, name_length);
|
||||||
dir_offset += name_length;
|
dir_offset += name_length;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty (cur_dir))
|
if (string.IsNullOrEmpty (cur_dir))
|
||||||
entry.Name = name;
|
entry.Name = name;
|
||||||
else
|
else
|
||||||
entry.Name = cur_dir + PathSeparatorChar + name;
|
entry.Name = cur_dir + PathSeparatorChar + name;
|
||||||
|
entry.Type = FormatCatalog.Instance.GetTypeFromName (name);
|
||||||
if (0x10 == entry.Attr)
|
if (0x10 == entry.Attr)
|
||||||
{
|
{
|
||||||
if (!ParseDirEntry (entry.Offset+0x10, entry.Name))
|
if (!ParseDirEntry (entry.Offset+0x10, entry.Name))
|
||||||
@ -156,4 +284,245 @@ namespace GameRes.Formats.Entis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal abstract class ERISADecodeContext
|
||||||
|
{
|
||||||
|
protected int m_nIntBufCount;
|
||||||
|
protected uint m_dwIntBuffer;
|
||||||
|
protected uint m_nBufferingSize;
|
||||||
|
protected uint m_nBufCount;
|
||||||
|
protected byte[] m_ptrBuffer;
|
||||||
|
protected int m_ptrNextBuf;
|
||||||
|
|
||||||
|
protected Stream m_pFile;
|
||||||
|
protected bool m_nFlagEOF;
|
||||||
|
|
||||||
|
public ERISADecodeContext (uint nBufferingSize)
|
||||||
|
{
|
||||||
|
m_nIntBufCount = 0;
|
||||||
|
m_nBufferingSize = (nBufferingSize + 0x03) & ~0x03u;
|
||||||
|
m_nBufCount = 0;
|
||||||
|
m_ptrBuffer = new byte[nBufferingSize];
|
||||||
|
m_pFile = null;
|
||||||
|
m_nFlagEOF = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool EofFlag { get { return m_nFlagEOF; } } // GetEOFFlag
|
||||||
|
|
||||||
|
public void AttachInputFile (Stream file)
|
||||||
|
{
|
||||||
|
m_pFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint ReadNextData (byte[] ptrBuffer, uint nBytes)
|
||||||
|
{
|
||||||
|
if (m_pFile != null)
|
||||||
|
{
|
||||||
|
uint read = (uint)m_pFile.Read (ptrBuffer, 0, (int)nBytes);
|
||||||
|
m_nFlagEOF = read != nBytes;
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ApplicationException ("Uninitialized ERISA encryption context");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract uint DecodeBytes (Array ptrDst, uint nCount);
|
||||||
|
|
||||||
|
protected bool PrefetchBuffer()
|
||||||
|
{
|
||||||
|
if (0 == m_nIntBufCount)
|
||||||
|
{
|
||||||
|
if (0 == m_nBufCount)
|
||||||
|
{
|
||||||
|
m_ptrNextBuf = 0; // m_ptrBuffer;
|
||||||
|
m_nBufCount = ReadNextData (m_ptrBuffer, m_nBufferingSize);
|
||||||
|
if (0 == m_nBufCount)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (0 != (m_nBufCount & 0x03))
|
||||||
|
{
|
||||||
|
uint i = m_nBufCount;
|
||||||
|
m_nBufCount += 4 - (m_nBufCount & 0x03);
|
||||||
|
while (i < m_nBufCount)
|
||||||
|
m_ptrBuffer[i ++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_nIntBufCount = 32;
|
||||||
|
m_dwIntBuffer =
|
||||||
|
((uint)m_ptrBuffer[m_ptrNextBuf] << 24) | ((uint)m_ptrBuffer[m_ptrNextBuf+1] << 16)
|
||||||
|
| ((uint)m_ptrBuffer[m_ptrNextBuf+2] << 8) | (uint)m_ptrBuffer[m_ptrNextBuf+3];
|
||||||
|
m_ptrNextBuf += 4;
|
||||||
|
m_nBufCount -= 4;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FlushBuffer ()
|
||||||
|
{
|
||||||
|
m_nIntBufCount = 0;
|
||||||
|
m_nBufCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetABit ()
|
||||||
|
{
|
||||||
|
if (!PrefetchBuffer())
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int nValue = ((int)m_dwIntBuffer) >> 31;
|
||||||
|
--m_nIntBufCount;
|
||||||
|
m_dwIntBuffer <<= 1;
|
||||||
|
return nValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint GetNBits (int n)
|
||||||
|
{
|
||||||
|
uint nCode = 0;
|
||||||
|
while (n != 0)
|
||||||
|
{
|
||||||
|
if (!PrefetchBuffer())
|
||||||
|
break;
|
||||||
|
|
||||||
|
int nCopyBits = Math.Min (n, m_nIntBufCount);
|
||||||
|
nCode = (nCode << nCopyBits) | (m_dwIntBuffer >> (32 - nCopyBits));
|
||||||
|
n -= nCopyBits;
|
||||||
|
m_nIntBufCount -= nCopyBits;
|
||||||
|
m_dwIntBuffer <<= nCopyBits;
|
||||||
|
}
|
||||||
|
return nCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class BSHFDecodeContext : ERISADecodeContext
|
||||||
|
{
|
||||||
|
ERIBshfBuffer m_pBshfBuf;
|
||||||
|
uint m_dwBufPos;
|
||||||
|
|
||||||
|
public BSHFDecodeContext (uint nBufferingSize) : base (nBufferingSize)
|
||||||
|
{
|
||||||
|
m_pBshfBuf = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrepareToDecodeBSHFCode (string pszPassword)
|
||||||
|
{
|
||||||
|
if (null == m_pBshfBuf)
|
||||||
|
{
|
||||||
|
m_pBshfBuf = new ERIBshfBuffer();
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty (pszPassword))
|
||||||
|
{
|
||||||
|
pszPassword = " ";
|
||||||
|
}
|
||||||
|
int char_count = Encoding.ASCII.GetByteCount (pszPassword);
|
||||||
|
int length = Math.Max (char_count, 32);
|
||||||
|
var pass_bytes = new byte[length];
|
||||||
|
char_count = Encoding.ASCII.GetBytes (pszPassword, 0, pszPassword.Length, pass_bytes, 0);
|
||||||
|
if (char_count < 32)
|
||||||
|
{
|
||||||
|
pass_bytes[char_count++] = 0x1b;
|
||||||
|
for (int i = char_count; i < 32; ++i)
|
||||||
|
{
|
||||||
|
pass_bytes[i] = (byte)(pass_bytes[i % char_count] + pass_bytes[i - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_pBshfBuf.m_strPassword = pass_bytes;
|
||||||
|
m_pBshfBuf.m_dwPassOffset = 0;
|
||||||
|
m_dwBufPos = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override uint DecodeBytes (Array ptrDst, uint nCount)
|
||||||
|
{
|
||||||
|
return DecodeBSHFCodeBytes (ptrDst as byte[], nCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint DecodeBSHFCodeBytes (byte[] ptrDst, uint nCount)
|
||||||
|
{
|
||||||
|
uint nDecoded = 0;
|
||||||
|
while (nDecoded < nCount)
|
||||||
|
{
|
||||||
|
if (m_dwBufPos >= 32)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 32; ++i)
|
||||||
|
{
|
||||||
|
if (0 == m_nBufCount)
|
||||||
|
{
|
||||||
|
m_ptrNextBuf = 0;
|
||||||
|
m_nBufCount = ReadNextData (m_ptrBuffer, m_nBufferingSize);
|
||||||
|
if (0 == m_nBufCount)
|
||||||
|
{
|
||||||
|
return nDecoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_pBshfBuf.m_srcBSHF[i] = m_ptrBuffer[m_ptrNextBuf++];
|
||||||
|
m_nBufCount--;
|
||||||
|
}
|
||||||
|
m_pBshfBuf.DecodeBuffer();
|
||||||
|
m_dwBufPos = 0;
|
||||||
|
}
|
||||||
|
ptrDst[nDecoded++] = m_pBshfBuf.m_bufBSHF[m_dwBufPos++];
|
||||||
|
}
|
||||||
|
return nDecoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ERIBshfBuffer
|
||||||
|
{
|
||||||
|
public byte[] m_strPassword;
|
||||||
|
public uint m_dwPassOffset = 0;
|
||||||
|
public byte[] m_bufBSHF = new byte[32];
|
||||||
|
public byte[] m_srcBSHF = new byte[32];
|
||||||
|
public byte[] m_maskBSHF = new byte[32];
|
||||||
|
|
||||||
|
public void DecodeBuffer ()
|
||||||
|
{
|
||||||
|
int nPassLen = m_strPassword.Length;
|
||||||
|
if ((int)m_dwPassOffset >= nPassLen)
|
||||||
|
{
|
||||||
|
m_dwPassOffset = 0;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 32; ++i)
|
||||||
|
{
|
||||||
|
m_bufBSHF[i] = 0;
|
||||||
|
m_maskBSHF[i] = 0;
|
||||||
|
}
|
||||||
|
int iPos = (int) m_dwPassOffset++;
|
||||||
|
int iBit = 0;
|
||||||
|
for (int i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
iBit = (iBit + m_strPassword[iPos++]) & 0xFF;
|
||||||
|
if (iPos >= nPassLen)
|
||||||
|
{
|
||||||
|
iPos = 0;
|
||||||
|
}
|
||||||
|
int iOffset = (iBit >> 3);
|
||||||
|
int iMask = (0x80 >> (iBit & 0x07));
|
||||||
|
while (0xFF == m_maskBSHF[iOffset])
|
||||||
|
{
|
||||||
|
iBit = (iBit + 8) & 0xFF;
|
||||||
|
iOffset = (iBit >> 3);
|
||||||
|
}
|
||||||
|
while (0 != (m_maskBSHF[iOffset] & iMask))
|
||||||
|
{
|
||||||
|
iBit ++;
|
||||||
|
iMask >>= 1;
|
||||||
|
if (0 == iMask)
|
||||||
|
{
|
||||||
|
iBit = (iBit + 8) & 0xFF;
|
||||||
|
iOffset = (iBit >> 3);
|
||||||
|
iMask = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.Assert (iMask != 0);
|
||||||
|
m_maskBSHF[iOffset] |= (byte) iMask;
|
||||||
|
|
||||||
|
if (0 != (m_srcBSHF[(i >> 3)] & (0x80 >> (i & 0x07))))
|
||||||
|
{
|
||||||
|
m_bufBSHF[iOffset] |= (byte)iMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
24
ArcFormats/Properties/Settings.Designer.cs
generated
24
ArcFormats/Properties/Settings.Designer.cs
generated
@ -297,5 +297,29 @@ namespace GameRes.Formats.Properties {
|
|||||||
this["LPKScheme"] = value;
|
this["LPKScheme"] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||||
|
public string NOAScheme {
|
||||||
|
get {
|
||||||
|
return ((string)(this["NOAScheme"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["NOAScheme"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||||
|
public string NOAPassPhrase {
|
||||||
|
get {
|
||||||
|
return ((string)(this["NOAPassPhrase"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["NOAPassPhrase"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,5 +71,11 @@
|
|||||||
<Setting Name="LPKScheme" Type="System.String" Scope="User">
|
<Setting Name="LPKScheme" Type="System.String" Scope="User">
|
||||||
<Value Profile="(Default)">Default</Value>
|
<Value Profile="(Default)">Default</Value>
|
||||||
</Setting>
|
</Setting>
|
||||||
|
<Setting Name="NOAScheme" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)" />
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="NOAPassPhrase" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)" />
|
||||||
|
</Setting>
|
||||||
</Settings>
|
</Settings>
|
||||||
</SettingsFile>
|
</SettingsFile>
|
11
ArcFormats/Strings/arcStrings.Designer.cs
generated
11
ArcFormats/Strings/arcStrings.Designer.cs
generated
@ -1,7 +1,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.18444
|
// Runtime Version:4.0.30319.34209
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@ -387,6 +387,15 @@ namespace GameRes.Formats.Strings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Ignore encryption.
|
||||||
|
/// </summary>
|
||||||
|
public static string NOAIgnoreEncryption {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("NOAIgnoreEncryption", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Compress contents.
|
/// Looks up a localized string similar to Compress contents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -315,4 +315,7 @@ predefined encryption scheme.</value>
|
|||||||
<value>Archive directory is encrypted.
|
<value>Archive directory is encrypted.
|
||||||
Enter archive encryption key.</value>
|
Enter archive encryption key.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="NOAIgnoreEncryption" xml:space="preserve">
|
||||||
|
<value>Ignore encryption</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -210,6 +210,9 @@
|
|||||||
<data name="MsgWritingIndex" xml:space="preserve">
|
<data name="MsgWritingIndex" xml:space="preserve">
|
||||||
<value>Записывается оглавление...</value>
|
<value>Записывается оглавление...</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="NOAIgnoreEncryption" xml:space="preserve">
|
||||||
|
<value>Игнорировать шифрование</value>
|
||||||
|
</data>
|
||||||
<data name="NPACompressContents" xml:space="preserve">
|
<data name="NPACompressContents" xml:space="preserve">
|
||||||
<value>Сжать содержимое</value>
|
<value>Сжать содержимое</value>
|
||||||
</data>
|
</data>
|
||||||
|
10
ArcFormats/WidgetNOA.xaml
Normal file
10
ArcFormats/WidgetNOA.xaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<Grid x:Class="GameRes.Formats.GUI.WidgetNOA"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:entis="clr-namespace:GameRes.Formats.Entis"
|
||||||
|
xmlns:p="clr-namespace:GameRes.Formats.Properties"
|
||||||
|
MaxWidth="300">
|
||||||
|
<ComboBox Name="Scheme" ItemsSource="{Binding Source={x:Static entis:NoaOpener.KnownKeys}, Path=Keys, Mode=OneWay}"
|
||||||
|
SelectedValue="{Binding Source={x:Static p:Settings.Default}, Path=NOAScheme, Mode=TwoWay}"
|
||||||
|
Width="200"/>
|
||||||
|
</Grid>
|
18
ArcFormats/WidgetNOA.xaml.cs
Normal file
18
ArcFormats/WidgetNOA.xaml.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace GameRes.Formats.GUI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for WidgetNOA.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class WidgetNOA : Grid
|
||||||
|
{
|
||||||
|
public WidgetNOA ()
|
||||||
|
{
|
||||||
|
InitializeComponent ();
|
||||||
|
// select first scheme as default
|
||||||
|
if (-1 == Scheme.SelectedIndex)
|
||||||
|
Scheme.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -73,6 +73,12 @@
|
|||||||
<setting name="LPKScheme" serializeAs="String">
|
<setting name="LPKScheme" serializeAs="String">
|
||||||
<value>Default</value>
|
<value>Default</value>
|
||||||
</setting>
|
</setting>
|
||||||
|
<setting name="NOAScheme" serializeAs="String">
|
||||||
|
<value />
|
||||||
|
</setting>
|
||||||
|
<setting name="NOAPassPhrase" serializeAs="String">
|
||||||
|
<value />
|
||||||
|
</setting>
|
||||||
</GameRes.Formats.Properties.Settings>
|
</GameRes.Formats.Properties.Settings>
|
||||||
</userSettings>
|
</userSettings>
|
||||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
|
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user