11//!A decrypter implementation for rpgm-archive-decrypter. Not intended for use in other applications; but can be.
22
3+ use arrayvec:: ArrayVec ;
34#[ cfg( feature = "rayon" ) ]
45use rayon:: prelude:: * ;
56#[ cfg( feature = "rayon" ) ]
@@ -23,12 +24,10 @@ enum SeekFrom {
2324
2425impl std:: fmt:: Display for Engine {
2526 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
26- let variant_name: & str = match self {
27- Engine :: Older => "XP/VX" ,
28- Engine :: VXAce => "VXAce" ,
29- } ;
30-
31- write ! ( f, "{}" , variant_name)
27+ match self {
28+ Engine :: Older => write ! ( f, "XP/VX" ) ,
29+ Engine :: VXAce => write ! ( f, "VXAce" ) ,
30+ }
3231 }
3332}
3433
@@ -44,22 +43,26 @@ impl VecWalker {
4443 VecWalker { data, pos : 0 , len }
4544 }
4645
46+ #[ inline]
4747 pub fn advance ( & mut self , bytes : usize ) -> & [ u8 ] {
4848 self . pos += bytes;
4949 & self . data [ self . pos - bytes..self . pos ]
5050 }
5151
52- pub fn read_chunk ( & mut self ) -> [ u8 ; 4 ] {
52+ #[ inline]
53+ pub fn read_i32 ( & mut self ) -> i32 {
5354 let chunk: & [ u8 ] = self . advance ( 4 ) ;
54- unsafe { * ( chunk. as_ptr ( ) as * const [ u8 ; 4 ] ) }
55+ i32 :: from_le_bytes ( unsafe { * ( chunk. as_ptr ( ) as * const [ u8 ; 4 ] ) } )
5556 }
5657
58+ #[ inline]
5759 pub fn read_byte ( & mut self ) -> u8 {
5860 self . pos += 1 ;
5961 self . data [ self . pos - 1 ]
6062 }
6163
62- pub fn seek ( & mut self , offset : usize , seek_from : SeekFrom ) {
64+ #[ inline]
65+ pub const fn seek ( & mut self , offset : usize , seek_from : SeekFrom ) {
6366 self . pos = match seek_from {
6467 SeekFrom :: Start => offset,
6568 SeekFrom :: Current => self . pos + offset,
@@ -77,20 +80,24 @@ struct Archive {
7780pub struct Decrypter {
7881 walker : UnsafeCell < VecWalker > ,
7982 key : u32 ,
83+ key_bytes : [ u8 ; 4 ] ,
8084 engine : Engine ,
8185}
8286
8387impl Decrypter {
8488 /// Creates a new decrypter for specified archive binary data.
8589 pub fn new ( bytes : Vec < u8 > ) -> Self {
90+ let key: u32 = 0xDEADCAFE ;
8691 Self {
8792 walker : UnsafeCell :: new ( VecWalker :: new ( bytes) ) ,
88- key : 0xDEADCAFE ,
93+ key,
94+ key_bytes : key. to_le_bytes ( ) ,
8995 engine : Engine :: Older ,
9096 }
9197 }
9298
9399 /// Extracts archive to `output_path`. Does nothing if extracted files already exist and `force` is set to `false`.
100+ #[ inline]
94101 pub fn extract < P : AsRef < Path > > ( & mut self , output_path : P , force : bool ) -> Result < ( ) , & str > {
95102 let walker: & mut VecWalker = unsafe { & mut * self . walker . get ( ) } ;
96103
@@ -105,21 +112,19 @@ impl Decrypter {
105112 walker. read_byte ( )
106113 } ;
107114
108- self . engine = if version == 1 {
109- Engine :: Older
110- } else if version == 3 {
111- Engine :: VXAce
112- } else {
113- return Err ( "Unknown archive game engine. Archive is possibly corrupted." ) ;
115+ self . engine = match version {
116+ 1 => Engine :: Older ,
117+ 3 => Engine :: VXAce ,
118+ _ => return Err ( "Unknown archive game engine. Archive is possibly corrupted." ) ,
114119 } ;
115120
116- let archives: Vec < Archive > = self . read_archive ( ) ;
121+ let archives: ArrayVec < Archive , 2048 > = self . read_archive ( ) ;
117122
118123 #[ cfg( feature = "rayon" ) ]
119124 let arc: Arc < Mutex < & mut VecWalker > > = Arc :: new ( Mutex :: new ( walker) ) ;
120125
121126 #[ cfg( feature = "rayon" ) ]
122- let archives = archives. into_par_iter ( ) ;
127+ let archives = archives. into_iter ( ) . par_bridge ( ) ;
123128
124129 #[ cfg( not( feature = "rayon" ) ) ]
125130 let archives = archives. into_iter ( ) ;
@@ -156,6 +161,13 @@ impl Decrypter {
156161 Ok ( ( ) )
157162 }
158163
164+ #[ inline]
165+ fn update_key ( & mut self , new_key : u32 ) {
166+ self . key = new_key;
167+ self . key_bytes = new_key. to_le_bytes ( ) ;
168+ }
169+
170+ #[ inline]
159171 fn decrypt_archive ( data : & [ u8 ] , mut key : u32 ) -> Vec < u8 > {
160172 let mut decrypted: Vec < u8 > = Vec :: with_capacity ( data. len ( ) ) ;
161173
@@ -176,89 +188,85 @@ impl Decrypter {
176188 decrypted
177189 }
178190
191+ #[ inline]
179192 fn decrypt_integer ( & mut self , value : i32 ) -> i32 {
180193 let result: i32 = value ^ self . key as i32 ;
181194
182195 if self . engine == Engine :: Older {
183- self . key = self . key . wrapping_mul ( 7 ) . wrapping_add ( 3 ) ;
196+ self . update_key ( self . key . wrapping_mul ( 7 ) . wrapping_add ( 3 ) ) ;
184197 }
185198
186199 result
187200 }
188201
202+ #[ inline]
189203 fn decrypt_filename ( & mut self , filename : & [ u8 ] ) -> String {
190204 let mut decrypted: Vec < u8 > = Vec :: with_capacity ( filename. len ( ) ) ;
191205
192206 if self . engine == Engine :: VXAce {
193- let key_bytes: [ u8 ; 4 ] = self . key . to_le_bytes ( ) ;
194207 let mut j: usize = 0 ;
195208
196209 for item in filename {
197210 if j == 4 {
198211 j = 0 ;
199212 }
200213
201- decrypted. push ( item ^ key_bytes[ j] ) ;
214+ decrypted. push ( item ^ self . key_bytes [ j] ) ;
202215 j += 1 ;
203216 }
204217 } else {
205218 for item in filename {
206- decrypted. push ( item ^ ( self . key & 0xff ) as u8 ) ;
207- self . key = self . key . wrapping_mul ( 7 ) . wrapping_add ( 3 ) ;
219+ decrypted. push ( item ^ self . key as u8 ) ;
220+ self . update_key ( self . key . wrapping_mul ( 7 ) . wrapping_add ( 3 ) ) ;
208221 }
209222 }
210223
224+ //? probably non-utf8 support?
211225 String :: from_utf8 ( decrypted) . unwrap ( )
212226 }
213227
214- fn read_archive ( & mut self ) -> Vec < Archive > {
228+ #[ inline]
229+ fn read_archive ( & mut self ) -> ArrayVec < Archive , 2048 > {
215230 let walker: & mut VecWalker = unsafe { & mut * self . walker . get ( ) } ;
216231
217232 if self . engine == Engine :: VXAce {
218233 // 0xDEADCAFE key is not ever used and overwritten.
219- self . key = u32:: from_le_bytes ( walker. read_chunk ( ) )
220- . wrapping_mul ( 9 )
221- . wrapping_add ( 3 ) ;
234+ self . update_key ( ( walker. read_i32 ( ) as u32 ) . wrapping_mul ( 9 ) . wrapping_add ( 3 ) ) ;
222235 }
223236
224- let mut archives: Vec < Archive > = Vec :: with_capacity ( 1024 ) ;
237+ let mut archives: ArrayVec < Archive , 2048 > = ArrayVec :: new ( ) ;
225238
226239 loop {
227- let ( filename, size, offset, key) = if self . engine == Engine :: VXAce {
228- let offset: usize =
229- self . decrypt_integer ( i32:: from_le_bytes ( walker. read_chunk ( ) ) ) as usize ;
230-
231- let size: i32 = self . decrypt_integer ( i32:: from_le_bytes ( walker. read_chunk ( ) ) ) ;
232-
233- let key: u32 = self . decrypt_integer ( i32:: from_le_bytes ( walker. read_chunk ( ) ) ) as u32 ;
234-
235- let length: i32 = self . decrypt_integer ( i32:: from_le_bytes ( walker. read_chunk ( ) ) ) ;
236-
237- if offset == 0 {
238- break ;
240+ let ( filename, size, offset, key) = match self . engine {
241+ Engine :: VXAce => {
242+ let offset: usize = self . decrypt_integer ( walker. read_i32 ( ) ) as usize ;
243+ let size: i32 = self . decrypt_integer ( walker. read_i32 ( ) ) ;
244+ let key: u32 = self . decrypt_integer ( walker. read_i32 ( ) ) as u32 ;
245+ let length: i32 = self . decrypt_integer ( walker. read_i32 ( ) ) ;
246+
247+ if offset == 0 {
248+ break ;
249+ }
250+
251+ let filename: String = self . decrypt_filename ( walker. advance ( length as usize ) ) ;
252+ ( filename, size, offset, key)
239253 }
254+ Engine :: Older => {
255+ let length: i32 = self . decrypt_integer ( walker. read_i32 ( ) ) ;
256+ let filename: String = self . decrypt_filename ( walker. advance ( length as usize ) ) ;
257+ let size: i32 = self . decrypt_integer ( walker. read_i32 ( ) ) ;
240258
241- let filename: String = self . decrypt_filename ( walker. advance ( length as usize ) ) ;
242-
243- ( filename, size, offset, key)
244- } else {
245- let length: i32 = self . decrypt_integer ( i32:: from_le_bytes ( walker. read_chunk ( ) ) ) ;
246-
247- let filename: String = self . decrypt_filename ( walker. advance ( length as usize ) ) ;
259+ let offset: usize = walker. pos ;
260+ let key: u32 = self . key ;
248261
249- let size : i32 = self . decrypt_integer ( i32 :: from_le_bytes ( walker . read_chunk ( ) ) ) ;
262+ walker . seek ( size as usize , SeekFrom :: Current ) ;
250263
251- let offset: usize = walker. pos ;
264+ if walker. pos == walker. len {
265+ break ;
266+ }
252267
253- let key: u32 = self . key ;
254-
255- walker. seek ( size as usize , SeekFrom :: Current ) ;
256-
257- if walker. pos == walker. len {
258- break ;
268+ ( filename, size, offset, key)
259269 }
260-
261- ( filename, size, offset, key)
262270 } ;
263271
264272 archives. push ( Archive {
0 commit comments