Skip to content

Commit 5915546

Browse files
authored
Merge pull request #46 from MkfsSion/ageengine
ArcFormats: Support S5IC archieve
2 parents 3120d94 + ca196d8 commit 5915546

2 files changed

Lines changed: 89 additions & 21 deletions

File tree

ArcFormats/Eushully/ArcALF.cs

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
using System.Collections.Generic;
2828
using System.ComponentModel.Composition;
2929
using System.IO;
30-
using GameRes.Utility;
3130
using GameRes.Compression;
31+
using System.Text;
32+
using System.Linq;
33+
using System.Text.RegularExpressions;
3234

3335
namespace GameRes.Formats.Eushully
3436
{
@@ -63,15 +65,64 @@ public override ArcFile TryOpen (ArcView file)
6365
return null;
6466
}
6567

68+
static internal string GetAAIName(string alf_name)
69+
{
70+
const string pattern = @"^(APPEND(?:[0-9]+)?)(?:_[0-9]+)?\.ALF$";
71+
var match = Regex.Match(alf_name, pattern);
72+
if (match.Success)
73+
return match.Groups[1].Value;
74+
return alf_name;
75+
}
76+
6677
internal IEnumerable<string> GetIndexNames (string alf_name)
6778
{
79+
yield return "sys5ini.bin";
6880
yield return "sys4ini.bin";
6981
yield return "sys3ini.bin";
70-
yield return Path.ChangeExtension (alf_name, "AAI");
82+
yield return Path.ChangeExtension (GetAAIName(alf_name), "AAI");
7183
}
7284

7385
Tuple<string, Dictionary<string, List<Entry>>> LastAccessedIndex;
7486

87+
88+
internal class AGEArchiveInfo
89+
{
90+
public readonly byte[] signature;
91+
public readonly int offset;
92+
public readonly bool isNameUnicode;
93+
public readonly bool isLZSSCompressed;
94+
95+
public AGEArchiveInfo(byte[] Signature, int Offset, bool IsNameUnicode, bool IsLZSSCompressed)
96+
{
97+
signature = Signature;
98+
offset = Offset;
99+
isNameUnicode = IsNameUnicode;
100+
isLZSSCompressed = IsLZSSCompressed;
101+
}
102+
}
103+
104+
static AGEArchiveInfo[] infos =
105+
{
106+
new AGEArchiveInfo(Encoding.ASCII.GetBytes("S3IN"), 0x12C, false, false),
107+
new AGEArchiveInfo(Encoding.ASCII.GetBytes("S3IC"), 0x134, false, true),
108+
new AGEArchiveInfo(Encoding.ASCII.GetBytes("S3AC"), 0x114, false, true),
109+
new AGEArchiveInfo(Encoding.ASCII.GetBytes("S4IC"), 0x134, false, true),
110+
new AGEArchiveInfo(Encoding.ASCII.GetBytes("S4AC"), 0x114, false, true),
111+
new AGEArchiveInfo(Encoding.Unicode.GetBytes("S5IC"), 0x224, true, true),
112+
new AGEArchiveInfo(Encoding.Unicode.GetBytes("S5AC"), 0x21C, true, true)
113+
};
114+
115+
static internal AGEArchiveInfo GetAGEArcInfo(ArcView view)
116+
{
117+
byte[] sig = view.View.ReadBytes(0, 8);
118+
var siglow = sig.Take(4);
119+
var res = infos.Where(i => Enumerable.SequenceEqual(i.signature, siglow));
120+
if (res.Any()) return res.First();
121+
res = infos.Where(i => Enumerable.SequenceEqual(i.signature, sig));
122+
if (res.Any()) return res.First();
123+
return null;
124+
}
125+
75126
List<Entry> ReadIndex (string ini_file, string arc_name)
76127
{
77128
if (null == LastAccessedIndex
@@ -81,24 +132,21 @@ List<Entry> ReadIndex (string ini_file, string arc_name)
81132
using (var ini = VFS.OpenView (ini_file))
82133
{
83134
IBinaryStream index;
84-
bool is_append = ini.View.AsciiEqual (0, "S4AC");
85-
if (is_append || ini.View.AsciiEqual (0, "S4IC") || ini.View.AsciiEqual (0, "S3IC"))
135+
136+
AGEArchiveInfo info = GetAGEArcInfo (ini);
137+
if (info == null) return null;
138+
139+
if (info.isLZSSCompressed)
86140
{
87-
uint offset = is_append ? 0x114u : 0x134u;
88-
uint packed_size = ini.View.ReadUInt32 (offset);
89-
var packed = ini.CreateStream (offset+4, packed_size);
90-
var unpacked = new LzssStream (packed);
91-
index = new BinaryStream (unpacked, ini_file);
141+
index = new BinaryStream(new LzssStream(ini.CreateStream(info.offset + 4, (uint)ini.View.ReadInt32(info.offset))), ini_file);
92142
}
93-
else if (ini.View.AsciiEqual (0, "S3IN"))
143+
else
94144
{
95-
index = ini.CreateStream (0x12C);
145+
index = ini.CreateStream(info.offset);
96146
}
97-
else
98-
return null;
99147
using (index)
100148
{
101-
var file_table = ReadSysIni (index);
149+
var file_table = ReadSysIni (index, info);
102150
if (null == file_table)
103151
return null;
104152
LastAccessedIndex = Tuple.Create (ini_file, file_table);
@@ -110,7 +158,7 @@ List<Entry> ReadIndex (string ini_file, string arc_name)
110158
return dir;
111159
}
112160

113-
internal Dictionary<string, List<Entry>> ReadSysIni (IBinaryStream index)
161+
internal Dictionary<string, List<Entry>> ReadSysIni (IBinaryStream index, AGEArchiveInfo info)
114162
{
115163
int arc_count = index.ReadInt32();
116164
if (!IsSaneCount (arc_count))
@@ -119,17 +167,19 @@ internal Dictionary<string, List<Entry>> ReadSysIni (IBinaryStream index)
119167
var arc_list = new List<Entry>[arc_count];
120168
for (int i = 0; i < arc_count; ++i)
121169
{
122-
var name = index.ReadCString (0x100);
170+
string name = info.isNameUnicode ? index.ReadCString(0x200, Encoding.Unicode) : index.ReadCString(0x100);
171+
123172
var file_list = new List<Entry>();
124173
file_table.Add (name, file_list);
125174
arc_list[i] = file_list;
126175
}
127176
int file_count = index.ReadInt32();
128177
if (!IsSaneCount (file_count))
129178
return null;
179+
130180
for (int i = 0; i < file_count; ++i)
131181
{
132-
var name = index.ReadCString (0x40);
182+
string name = info.isNameUnicode ? index.ReadCString(0x80, Encoding.Unicode) : index.ReadCString(0x40);
133183
int arc_id = index.ReadInt32();
134184
if (arc_id < 0 || arc_id >= arc_list.Length)
135185
return null;

GameRes/BinaryStream.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,27 @@ public static IBinaryStream FromStream (Stream input, string filename)
170170
return bin;
171171
}
172172

173+
internal int FindEoS(int start, int length, Encoding enc)
174+
{
175+
int eos_pos = -1;
176+
if (enc.IsUtf16())
177+
{
178+
for (int i = start + 1; i < start + length; i += 2)
179+
{
180+
if (m_buffer[i - 1] == 0 && m_buffer[i] == 0)
181+
{
182+
eos_pos = i - 1;
183+
break;
184+
}
185+
}
186+
}
187+
else
188+
{
189+
eos_pos = Array.IndexOf<byte>(m_buffer, 0, start, length);
190+
}
191+
return eos_pos;
192+
}
193+
173194
uint ReadSignature ()
174195
{
175196
if (m_header_size >= 4)
@@ -307,10 +328,7 @@ public string ReadCString (int length)
307328
public string ReadCString (int length, Encoding enc)
308329
{
309330
length = FillBuffer (length);
310-
int i;
311-
for (i = 0; i < length; ++i)
312-
if (0 == m_buffer[m_buffer_pos+i])
313-
break;
331+
int i = FindEoS(m_buffer_pos, length, enc) - m_buffer_pos;
314332
string s = enc.GetString (m_buffer, m_buffer_pos, i);
315333
m_buffer_pos += length;
316334
return s;

0 commit comments

Comments
 (0)