(count);
+ for (int i = 0; i < count; ++i)
+ {
+ var name = file.View.ReadString (index_offset, 0x20);
+ index_offset += 0x20;
+ var entry = new SPackEntry
+ {
+ Name = name,
+ Offset = base_offset + file.View.ReadUInt32 (index_offset),
+ UnpackedSize = file.View.ReadUInt32 (index_offset+4),
+ Size = file.View.ReadUInt32 (index_offset+8),
+ Method = file.View.ReadByte (index_offset+12),
+ Crc = file.View.ReadUInt16 (index_offset+14),
+ };
+ if (!entry.CheckPlacement (file.MaxOffset))
+ return null;
+ if (name.EndsWith (".dat", StringComparison.InvariantCultureIgnoreCase))
+ entry.Type = "audio";
+ else
+ entry.Type = FormatCatalog.Instance.GetTypeFromName (name);
+ entry.IsPacked = entry.Method != 0;
+ dir.Add (entry);
+ index_offset += 0x18;
+ }
+ return new ArcFile (file, this, dir);
+ }
+
+ public override Stream OpenEntry (ArcFile arc, Entry entry)
+ {
+ var input = arc.File.CreateStream (entry.Offset, entry.Size);
+ var packed_entry = entry as SPackEntry;
+ if (null == packed_entry || !packed_entry.IsPacked)
+ return input;
+ if (1 == packed_entry.Method)
+ return new CryptoStream (input, new Kogado.NotTransform(), CryptoStreamMode.Read);
+ if (2 == packed_entry.Method)
+ {
+ using (var reader = new PackedReader (packed_entry, input))
+ {
+ reader.Unpack();
+ return new MemoryStream (reader.Data);
+ }
+ }
+ return input;
+ }
+ }
+
+ internal class PackedReader : IDisposable
+ {
+ BinaryReader m_input;
+ uint m_packed_size;
+ byte[] m_output;
+
+ public byte[] Data { get { return m_output; } }
+
+ public PackedReader (SPackEntry entry, Stream input)
+ {
+ m_input = new BinaryReader (input);
+ m_packed_size = entry.Size;
+ m_output = new byte[entry.UnpackedSize];
+ }
+
+ public byte[] Unpack ()
+ {
+ int dst = 0;
+ uint src = 0;
+ uint ctl = 0;
+ uint mask = 0;
+
+ while (dst < m_output.Length && src < m_packed_size)
+ {
+ if (0 == mask)
+ {
+ ctl = m_input.ReadUInt32();
+ src += 4;
+ mask = 0x80000000;
+ }
+ if (0 != (ctl & mask))
+ {
+ int copy_count, offset;
+
+ offset = m_input.ReadByte();
+ src++;
+ copy_count = offset >> 4;
+ offset &= 0x0f;
+ if (15 == copy_count)
+ {
+ copy_count = m_input.ReadUInt16();
+ src += 2;
+ }
+ else if (14 == copy_count)
+ {
+ copy_count = m_input.ReadByte();
+ src++;
+ }
+ else
+ copy_count++;
+
+ if (offset < 10)
+ offset++;
+ else
+ {
+ offset = ((offset - 10) << 8) | m_input.ReadByte();
+ src++;
+ }
+
+ if (dst + copy_count > m_output.Length)
+ copy_count = m_output.Length - dst;
+ Binary.CopyOverlapped (m_output, dst-offset, dst, copy_count);
+ dst += copy_count;
+ }
+ else
+ {
+ m_output[dst++] = m_input.ReadByte();
+ src++;
+ }
+ mask >>= 1;
+ }
+ return m_output;
+ }
+
+ #region IDisposable Members
+ bool disposed = false;
+
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ if (!disposed)
+ {
+ if (disposing)
+ {
+ m_input.Dispose();
+ }
+ disposed = true;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/supported.html b/supported.html
index 36e76f4b..e9584792 100644
--- a/supported.html
+++ b/supported.html
@@ -156,12 +156,21 @@ Rikorisu ~Lycoris Radiata~
*.mfg *.mfm *.mfs | ALPF | No | Silky's | Jokei Kazoku |
* | MFG_ MFGA MFGC | No |
*.pmp *.pmw | - | Yes | ScenePlayer | Nyuujoku Hitozuma Jogakuen |
-*.dat | GAMEDAT PACK GAMEDAT PAC2 | No | Pajamas Soft | Prism Heart |
+*.dat | GAMEDAT PACK GAMEDAT PAC2 | No | Pajamas Soft |
+Aneimo 2 ~Second Stage~
+Prism Heart
+ |
*.epa | EP | No |
*.arc | MAI | No | Matsuri Kikaku | Chikan Sharyou Nigousha |
*.ami *.cmp
| AM CM | No |
*.mgd *.mgs | MGD MGS | No | MEGU | Seduce |
*.agc | AGd | No |
+*.pak+*.idx | - | No | EAGLS |
+Oppai Baka
+Mainichi Shabutte Ii Desu ka?
+ |
+*.gr | - | No |
+*.dat | SPack | No | Goku-Fero | Inchuu Reiki Elenova |
[1] Non-encrypted only