1#![cfg_attr(not(feature = "std"), no_std)]
2#![warn(clippy::all, clippy::pedantic)]
3#![allow(clippy::needless_doctest_main)]
4#![allow(clippy::cast_possible_truncation)]
5#![allow(clippy::cast_possible_wrap)]
6#![allow(clippy::cast_sign_loss)]
7#![allow(clippy::deref_addrof)]
8#![allow(invalid_reference_casting)]
9#![doc = include_str!("../README.md")]
10
11use core::{
12 default::Default,
13 iter::{self, Iterator},
14};
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17use strum_macros::{Display, EnumIs};
18use thiserror::Error;
19
20fn memcpy(dst: &mut [u8], src: &[u8]) {
21 unsafe {
22 core::ptr::copy_nonoverlapping(
23 src.as_ptr(),
24 dst.as_mut_ptr(),
25 src.len(),
26 );
27 }
28}
29
30enum SeekFrom {
31 Start(u64),
32 Current(i64),
33}
34
35macro_rules! sizeof {
36 ($t:ty) => {{ core::mem::size_of::<$t>() }};
37}
38
39const ARCHIVE_HEADER: &[u8; 7] = b"RGSSAD\0";
40
41const OLDER_DECRYPTION_KEY: u32 = 0xDEAD_CAFE;
42const ENCRYPTION_KEY: u32 = 0;
43
44pub const XP_RGSSAD_EXT: &str = "rgssad";
45pub const VX_RGSS2A_EXT: &str = "rgss2a";
46pub const VXACE_RGSS3A_EXT: &str = "rgss3a";
47
48#[derive(Debug, Error)]
49#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
50pub enum ExtractError {
51 #[error(
52 "Invalid archive file header: {0:?}. Expected: RGSSADā ([82, 71, 83, 83, 65, 68, 0])"
53 )]
54 InvalidHeader([u8; 7]),
55 #[error(
56 "Invalid game engine byte: {0}. Expected `1` for XP/VX or `3` for VX Ace."
57 )]
58 InvalidEngine(u8),
59}
60
61#[derive(Debug, Display, EnumIs, Clone, Copy, PartialEq)]
62pub enum Engine {
63 #[strum(to_string = "XP/VX")]
64 Older = 1,
65 #[strum(to_string = "VXAce")]
66 VXAce = 3,
67}
68
69pub struct ArchiveEntry<'a> {
78 pub path: &'a [u8],
79 pub data: &'a [u8],
80}
81
82pub struct Decrypter<'a> {
84 engine: Engine,
85 key: u32,
86 key_bytes: [u8; sizeof!(u32)],
87
88 data: &'a mut [u8],
90 pos: usize,
91 len: usize,
92}
93
94impl<'a> Decrypter<'a> {
95 #[must_use]
97 pub fn new() -> Self {
98 Self {
99 engine: Engine::Older,
100 key: OLDER_DECRYPTION_KEY,
101 key_bytes: OLDER_DECRYPTION_KEY.to_le_bytes(),
102
103 data: &mut [],
104 pos: 0,
105 len: 0,
106 }
107 }
108
109 #[inline]
110 fn update_key(&mut self, new_key: u32) {
111 self.key = new_key;
112 self.key_bytes = new_key.to_le_bytes();
113 }
114
115 #[inline]
116 fn update_key_older(&mut self) {
117 self.update_key(self.key.wrapping_mul(7).wrapping_add(3));
118 }
119
120 #[inline]
121 fn update_key_vxace(&mut self) {
122 self.update_key(self.key.wrapping_mul(9).wrapping_add(3));
123 }
124
125 #[inline]
126 #[track_caller]
127 fn read_bytes(&mut self, count: usize) -> &[u8] {
128 self.pos += count;
129 &self.data[self.pos - count..self.pos]
130 }
131
132 #[inline]
133 fn read_u32(&mut self) -> u32 {
134 let chunk = self.read_bytes(sizeof!(u32));
135 u32::from_le_bytes(unsafe {
136 *chunk.as_ptr().cast::<[u8; sizeof!(u32)]>()
137 })
138 }
139
140 #[inline]
141 fn read_byte(&mut self) -> u8 {
142 self.pos += 1;
143 self.data[self.pos - 1]
144 }
145
146 #[inline]
147 fn seek_byte(&mut self, from: SeekFrom) {
148 self.pos = match from {
149 SeekFrom::Start(offset) => offset as usize,
150 SeekFrom::Current(offset) => self.pos + offset as usize,
151 };
152 }
153
154 #[inline]
155 fn xor_u32_vxace(&self, u32: u32) -> u32 {
157 u32 ^ self.key
158 }
159
160 #[inline]
161 fn xor_u32_older(&mut self, u32: u32) -> u32 {
163 let decrypted = u32 ^ self.key;
164
165 if self.engine.is_older() {
166 self.update_key_older();
167 }
168
169 decrypted
170 }
171
172 #[inline]
173 fn xor_path_vxace(&mut self, path_data: &mut [u8]) {
175 for (idx, byte) in
176 (unsafe { &*(path_data as *mut [u8]) }).iter().enumerate()
177 {
178 path_data[idx] = byte ^ self.key_bytes[idx % 4];
181 }
182 }
183
184 #[inline]
185 fn xor_path_older(&mut self, path_data: &mut [u8]) {
187 for (idx, byte) in
188 (unsafe { &*(path_data as *mut [u8]) }).iter().enumerate()
189 {
190 path_data[idx] = byte ^ self.key as u8;
191 self.update_key_older();
192 }
193 }
194
195 #[inline]
196 fn xor_data(mut key: u32, data: &mut [u8]) {
198 let mut key_bytes = key.to_le_bytes();
199 let mut key_byte_pos = 0;
200
201 for (idx, data_byte) in
203 (unsafe { &*(data as *mut [u8]) }).iter().enumerate()
204 {
205 if key_byte_pos == 4 {
206 key_byte_pos = 0;
207 key = key.wrapping_mul(7).wrapping_add(3);
208 key_bytes = key.to_le_bytes();
209 }
210
211 data[idx] = data_byte ^ key_bytes[key_byte_pos];
212 key_byte_pos += 1;
213 }
214 }
215
216 #[inline]
217 fn parse_header(&mut self) -> Result<(), ExtractError> {
218 let header = self.read_bytes(ARCHIVE_HEADER.len());
219
220 if header != ARCHIVE_HEADER {
221 return Err(ExtractError::InvalidHeader(unsafe {
222 *header.as_ptr().cast::<[u8; 7]>()
223 }));
224 }
225
226 let engine_type = self.read_byte();
227
228 self.engine = match engine_type {
229 1 => Engine::Older,
230 3 => Engine::VXAce,
231 _ => {
232 return Err(ExtractError::InvalidEngine(engine_type));
233 }
234 };
235
236 Ok(())
237 }
238
239 #[inline]
240 #[track_caller]
241 fn decrypt_entries(&'a mut self) -> impl Iterator<Item = ArchiveEntry<'a>> {
242 if self.engine.is_vx_ace() {
243 let key = self.read_u32();
245 self.update_key(key);
246 self.update_key_vxace();
247 }
248
249 iter::from_fn(move || {
250 let mut u32: u32;
251
252 if self.engine.is_vx_ace() {
253 u32 = self.read_u32();
254 let data_offset = self.xor_u32_vxace(u32) as u64;
255
256 if data_offset == 0 {
258 return None;
259 }
260
261 u32 = self.read_u32();
262 let data_size = self.xor_u32_vxace(u32) as usize;
263
264 u32 = self.read_u32();
265 let entry_key = self.xor_u32_vxace(u32);
266
267 u32 = self.read_u32();
268 let path_size = self.xor_u32_vxace(u32) as usize;
269
270 let path_data = unsafe {
271 &mut *(self.read_bytes(path_size) as *const [u8]
272 as *mut [u8])
273 };
274
275 self.xor_path_vxace(path_data);
276
277 let prev_pos = self.pos;
279
280 self.seek_byte(SeekFrom::Start(data_offset));
282
283 let entry_data = unsafe {
284 &mut *(self.read_bytes(data_size) as *const [u8]
285 as *mut [u8])
286 };
287 Self::xor_data(entry_key, entry_data);
288
289 let entry = ArchiveEntry {
290 path: path_data,
291 data: entry_data,
292 };
293
294 self.seek_byte(SeekFrom::Start(prev_pos as u64));
296
297 Some(entry)
298 } else {
299 if self.pos == self.len {
301 return None;
302 }
303
304 u32 = self.read_u32();
305 let path_size = self.xor_u32_older(u32) as usize;
306
307 let path_data = unsafe {
308 &mut *(self.read_bytes(path_size) as *const [u8]
309 as *mut [u8])
310 };
311
312 self.xor_path_older(path_data);
313
314 u32 = self.read_u32();
315 let data_size = self.xor_u32_older(u32) as usize;
316 let data_offset = self.pos as u64;
317 let entry_key = self.key;
318
319 self.seek_byte(SeekFrom::Current(data_size as i64));
321
322 let prev_pos = self.pos;
324
325 self.seek_byte(SeekFrom::Start(data_offset));
327
328 let entry_data = unsafe {
329 &mut *(self.read_bytes(data_size) as *const [u8]
330 as *mut [u8])
331 };
332 Self::xor_data(entry_key, entry_data);
333
334 let entry = ArchiveEntry {
335 path: path_data,
336 data: entry_data,
337 };
338
339 self.seek_byte(SeekFrom::Start(prev_pos as u64));
341
342 Some(entry)
343 }
344 })
345 }
346
347 fn encrypt_entries(
348 &mut self,
349 entries: &[ArchiveEntry],
350 archive_buffer: &mut [u8],
351 ) {
352 let mut offset = 8;
353
354 if self.engine.is_vx_ace() {
355 self.update_key(ENCRYPTION_KEY);
356
357 memcpy(&mut archive_buffer[offset..], &self.key_bytes);
358 offset += 4;
359
360 self.update_key_vxace();
361 }
362
363 if self.engine.is_vx_ace() {
364 for entry in entries {
366 memcpy(&mut archive_buffer[offset..], &0u32.to_le_bytes());
368 offset += 4;
369
370 let data_size = entry.data.len() as u32;
371 let encoded_data_size = self.xor_u32_vxace(data_size);
372 memcpy(
373 &mut archive_buffer[offset..],
374 &encoded_data_size.to_le_bytes(),
375 );
376 offset += 4;
377
378 memcpy(
380 &mut archive_buffer[offset..],
381 &ENCRYPTION_KEY.to_le_bytes(),
382 );
383 offset += 4;
384
385 let path_size = entry.path.len() as u32;
386 let encoded_path_size = self.xor_u32_vxace(path_size);
387 memcpy(
388 &mut archive_buffer[offset..],
389 &encoded_path_size.to_le_bytes(),
390 );
391 offset += 4;
392
393 memcpy(&mut archive_buffer[offset..], entry.path);
394 self.xor_path_vxace(&mut archive_buffer[offset..]);
395 offset += entry.path.len();
396 }
397
398 memcpy(&mut archive_buffer[offset..], &self.key.to_le_bytes());
400 offset += 4;
401
402 let mut placeholder_offset = 12;
403
404 for entry in entries {
406 let data_offset = offset as u32;
407 let encrypted_data_offset = self.xor_u32_vxace(data_offset);
408
409 archive_buffer[placeholder_offset..placeholder_offset + 4]
410 .copy_from_slice(&encrypted_data_offset.to_le_bytes());
411
412 placeholder_offset += 16 + entry.path.len();
413
414 memcpy(&mut archive_buffer[offset..], entry.data);
415 Self::xor_data(self.key, &mut archive_buffer[offset..]);
416 offset += entry.data.len();
417 }
418 } else {
419 for entry in entries {
420 let path_size = entry.path.len() as u32;
421
422 let encoded_path_size = self.xor_u32_older(path_size);
423 memcpy(
424 &mut archive_buffer[offset..],
425 &encoded_path_size.to_le_bytes(),
426 );
427
428 memcpy(&mut archive_buffer[offset..], entry.path);
429 offset += entry.path.len();
430
431 self.xor_path_older(&mut archive_buffer[offset..]);
432
433 let data_size = entry.data.len() as u32;
434 let encoded_data_size = self.xor_u32_older(data_size);
435 memcpy(
436 &mut archive_buffer[offset..],
437 &encoded_data_size.to_le_bytes(),
438 );
439 offset += 4;
440
441 memcpy(&mut archive_buffer[offset..], entry.data);
442 Self::xor_data(self.key, &mut archive_buffer[offset..]);
443 offset += entry.data.len();
444 }
445 }
446 }
447
448 fn reset(&mut self, data: &'a mut [u8]) {
449 self.len = data.len();
450 self.data = data;
451 self.pos = 0;
452
453 self.engine = Engine::Older;
454 self.key = OLDER_DECRYPTION_KEY;
455 self.key_bytes = OLDER_DECRYPTION_KEY.to_le_bytes();
456 }
457
458 #[inline]
493 pub fn decrypt(
494 &'a mut self,
495 archive_data: &'a mut [u8],
496 ) -> Result<impl Iterator<Item = ArchiveEntry<'a>>, ExtractError> {
497 self.reset(archive_data);
498 self.parse_header()?;
499 Ok(self.decrypt_entries())
500 }
501
502 pub fn encrypted_buffer_size(
515 archive_entries: &[ArchiveEntry],
516 engine: Engine,
517 ) -> usize {
518 let mut buf_size: usize = ARCHIVE_HEADER.len();
519
520 buf_size += 1;
522
523 if engine.is_vx_ace() {
524 buf_size += 4;
525 }
526
527 for entry in archive_entries {
528 if engine.is_vx_ace() {
529 buf_size += sizeof!(u32);
531
532 buf_size += sizeof!(u32);
534
535 buf_size += sizeof!(u32);
537
538 buf_size += sizeof!(u32);
540 } else {
541 buf_size += sizeof!(u32);
543
544 buf_size += sizeof!(u32);
546 }
547
548 buf_size += entry.data.len();
549 buf_size += entry.path.len();
550 }
551
552 if engine.is_vx_ace() {
553 buf_size += sizeof!(u32);
555
556 buf_size += sizeof!(u32) * 3;
558 }
559
560 buf_size
561 }
562
563 #[must_use]
591 #[inline]
592 pub fn encrypt(
593 &mut self,
594 archive_entries: &[ArchiveEntry],
595 engine: Engine,
596 archive_buffer: &mut [u8],
597 ) {
598 memcpy(archive_buffer, ARCHIVE_HEADER);
599 archive_buffer[7] = engine as u8;
600
601 self.engine = engine;
602 self.encrypt_entries(archive_entries, archive_buffer);
603 }
604}
605
606impl Default for Decrypter<'_> {
607 fn default() -> Self {
611 Self::new()
612 }
613}