(WarOpener): ignore duplicate file names.

(HuffmanReader): refactoring.
This commit is contained in:
morkt 2016-09-07 20:32:17 +04:00
parent 1139034b2f
commit d8531398d9

View File

@ -123,6 +123,7 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒
{ {
byte[] name_buf = new byte[decoder.EntryNameSize]; byte[] name_buf = new byte[decoder.EntryNameSize];
var dir = new List<Entry> (); var dir = new List<Entry> ();
var unique_names = new HashSet<string>();
while (name_buf.Length == header.Read (name_buf, 0, name_buf.Length)) while (name_buf.Length == header.Read (name_buf, 0, name_buf.Length))
{ {
var name = Binary.GetCString (name_buf, 0, name_buf.Length); var name = Binary.GetCString (name_buf, 0, name_buf.Length);
@ -135,7 +136,7 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒
entry.IsPacked = entry.Size != entry.UnpackedSize; entry.IsPacked = entry.Size != entry.UnpackedSize;
entry.FileTime = header.ReadInt64(); entry.FileTime = header.ReadInt64();
entry.Flags = header.ReadUInt32(); entry.Flags = header.ReadUInt32();
if (0 != name.Length) if (0 != name.Length && unique_names.Add (name))
dir.Add (entry); dir.Add (entry);
} }
if (0 == dir.Count) if (0 == dir.Count)
@ -427,8 +428,7 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒
byte[] m_src; byte[] m_src;
byte[] m_dst; byte[] m_dst;
uint[] lhs = new uint[511]; ushort[,] m_tree = new ushort[2,511];
uint[] rhs = new uint[511];
int m_origin; int m_origin;
int m_total; int m_total;
@ -436,7 +436,7 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒
int m_remaining; int m_remaining;
int m_curbits; int m_curbits;
uint m_cache; uint m_cache;
uint m_curindex; ushort m_curindex;
public HuffmanReader (byte[] src, int index, int length, byte[] dst) public HuffmanReader (byte[] src, int index, int length, byte[] dst)
{ {
@ -456,31 +456,21 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒
m_remaining = m_total; m_remaining = m_total;
m_curbits = 0; m_curbits = 0;
m_curindex = 256; m_curindex = 256;
uint index = CreateTree(); ushort root = CreateTree();
for (int i = 0; i < m_dst.Length; ++i) for (int i = 0; i < m_dst.Length; ++i)
{ {
uint idx = index; ushort symbol = root;
while (idx >= 256) while (symbol >= 256)
{ {
if (--m_curbits < 0) symbol = m_tree[GetBits(1), symbol];
{
m_curbits = 31;
m_cache = ReadUInt32();
}
if (0 != ((m_cache >> m_curbits) & 1))
idx = rhs[idx];
else
idx = lhs[idx];
} }
m_dst[i] = (byte)idx; m_dst[i] = (byte)symbol;
} }
return m_dst; return m_dst;
} }
uint ReadUInt32 () uint ReadUInt32 ()
{ {
if (0 == m_remaining)
throw new InvalidFormatException ("Unexpected end of file");
uint v; uint v;
if (m_remaining >= 4) if (m_remaining >= 4)
{ {
@ -488,7 +478,7 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒
m_input_pos += 4; m_input_pos += 4;
m_remaining -= 4; m_remaining -= 4;
} }
else else if (m_remaining > 0)
{ {
v = m_src[m_input_pos++]; v = m_src[m_input_pos++];
int shift = 8; int shift = 8;
@ -498,6 +488,8 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒
shift += 8; shift += 8;
} }
} }
else
throw new InvalidFormatException ("Unexpected end of file");
return v; return v;
} }
@ -506,41 +498,26 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒
uint ret_val = 0; uint ret_val = 0;
if (req_bits > m_curbits) if (req_bits > m_curbits)
{ {
do req_bits -= m_curbits;
{ ret_val |= (m_cache & ((1u << m_curbits) - 1u)) << req_bits;
req_bits -= m_curbits; m_cache = ReadUInt32();
ret_val |= (m_cache & ((1u << m_curbits) - 1u)) << req_bits; m_curbits = 32;
m_cache = ReadUInt32();
m_curbits = 32;
}
while (req_bits > 32);
} }
m_curbits -= req_bits; m_curbits -= req_bits;
return ret_val | ((1u << req_bits) - 1u) & (m_cache >> m_curbits); return ret_val | ((1u << req_bits) - 1u) & (m_cache >> m_curbits);
} }
uint CreateTree () ushort CreateTree ()
{ {
uint not_leaf; ushort i;
if (0 != GetBits (1))
if (m_curbits-- < 1)
{
m_curbits = 31;
m_cache = ReadUInt32();
not_leaf = m_cache >> 31;
}
else
not_leaf = (m_cache >> m_curbits) & 1;
uint i;
if (0 != not_leaf)
{ {
i = m_curindex++; i = m_curindex++;
lhs[i] = CreateTree(); m_tree[0,i] = CreateTree();
rhs[i] = CreateTree(); m_tree[1,i] = CreateTree();
} }
else else
i = GetBits (8); i = (ushort)GetBits (8);
return i; return i;
} }
} }