2727using System . Collections . Generic ;
2828using System . ComponentModel . Composition ;
2929using System . IO ;
30- using GameRes . Utility ;
3130using GameRes . Compression ;
31+ using System . Text ;
32+ using System . Linq ;
33+ using System . Text . RegularExpressions ;
3234
3335namespace 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 ;
0 commit comments