1use super::delphi::*;
2use super::twister::*;
3use super::types::*;
4use crate::ext::io::*;
5use crate::scripts::base::*;
6use crate::types::*;
7use crate::utils::encoding::*;
8use crate::utils::mmx::*;
9use anyhow::Result;
10use pelite::FileMap;
11use pelite::pe32::{Pe, PeFile};
12use std::io::{Read, Seek, SeekFrom, Write};
13use std::path::{Path, PathBuf};
14
15pub trait Hasher {
16 fn update(&mut self, data: &[u8]) -> Result<()>;
17 fn finalize(&mut self) -> Result<u32>;
18}
19
20pub trait Encryption: std::fmt::Debug {
21 fn is_unicode(&self) -> bool {
22 false
23 }
24 fn compute_hash(&self, _data: &[u8]) -> Result<u32> {
25 Ok(0)
26 }
27 fn create_hash(&self) -> Result<Box<dyn Hasher>> {
28 Err(anyhow::anyhow!("Hasher not implemented"))
29 }
30 fn decrypt_name(&self, name: &mut [u8], hash: i32, encoding: Encoding) -> Result<String>;
31 fn decrypt_entry<'a>(
32 &self,
33 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
34 entry: &QlieEntry,
35 ) -> Result<Box<dyn ReadDebug + Send + Sync + 'a>>;
36 fn index_has_hash(&self) -> bool {
37 true
38 }
39}
40
41pub fn create_encryption(
42 major: u8,
43 minor: u8,
44 game_key: Option<Vec<u8>>,
45) -> Result<Box<dyn Encryption + Send + Sync>> {
46 match (major, minor) {
47 (3, 1) => Ok(Box::new(Encryption31::new())),
48 (3, 0) => Ok(Box::new(Encryption30::new(game_key))),
49 (2, 0) => Ok(Box::new(Encryption20::new())),
50 (1, 0) => Ok(Box::new(Encryption10::new())),
51 _ => Err(anyhow::anyhow!(
52 "Unsupported encryption version: {}.{}",
53 major,
54 minor
55 )),
56 }
57}
58
59pub fn decompress<'a>(
60 data: Box<dyn ReadDebug + Send + Sync + 'a>,
61) -> Result<Box<dyn ReadDebug + Send + Sync + 'a>> {
62 Ok(Box::new(Decompressor::new(data)?))
63}
64
65pub fn decrypt(data: &mut [u8], key: u32) -> Result<()> {
66 let length = data.len();
67 if length < 8 {
68 return Ok(());
70 }
71 let mut data = MemWriterRef::new(data);
72 const C1: u64 = 0xA73C5F9D;
73 const C2: u64 = 0xCE24F523;
74 const C3: u64 = 0xFEC9753E;
75 let mut v5 = mmx_punpckldq2(C1);
76 const V7: u64 = mmx_punpckldq2(C2);
77 let mut v9 = mmx_punpckldq2(((length as u32).wrapping_add(key) as u64) ^ C3);
78 for _ in 0..length / 8 {
79 let d = data.peek_u64()?;
80 v5 = mmx_p_add_d(v5, V7) ^ v9;
81 v9 = d ^ v5;
82 data.write_u64(v9)?;
83 }
84 Ok(())
85}
86
87pub fn encrypt(data: &mut [u8], key: u32) -> Result<()> {
88 let length = data.len();
89 if length < 8 {
90 return Ok(());
92 }
93 let mut data = MemWriterRef::new(data);
94 const C1: u64 = 0xA73C5F9D;
95 const C2: u64 = 0xCE24F523;
96 const C3: u64 = 0xFEC9753E;
97 let mut v5 = mmx_punpckldq2(C1);
98 const V7: u64 = mmx_punpckldq2(C2);
99 let mut v9 = mmx_punpckldq2(((length as u32).wrapping_add(key) as u64) ^ C3);
100 for _ in 0..length / 8 {
101 let mut d = data.peek_u64()?;
102 v5 = mmx_p_add_d(v5, V7) ^ v9;
103 v9 = d;
104 d ^= v5;
105 data.write_u64(d)?;
106 }
107 Ok(())
108}
109
110pub fn get_common_key(data: &[u8]) -> Result<Vec<u8>> {
111 let mut reader = MemReaderRef::new(data);
112 let mut key = vec![0u8; 0x400];
113 let mut writer = MemWriterRef::new(&mut key);
114 for i in 0..0x100i32 {
115 let temp = if (i % 3) != 0 {
116 (i + 7) * -(i + 3)
117 } else {
118 (i + 7) * (i + 3)
119 };
120 writer.write_u32_at(i as u64 * 4, temp as u32)?;
121 }
122 let mut v1 = (reader.peek_u8_at(49)? % 0x49) as i32 + 0x80;
123 let v2 = (reader.peek_u8_at(79)? % 7) as i32 + 7;
124 let data_len = data.len() as i32;
125 for i in 0..0x400 {
126 v1 = (v1.wrapping_add(v2)) % data_len;
127 key[i] ^= reader.peek_u8_at(v1 as u64)?;
128 }
129 Ok(key)
131}
132
133#[derive(Debug)]
134pub struct Encryption31 {}
135
136impl Encryption31 {
137 pub fn new() -> Self {
138 Self {}
139 }
140
141 fn create_table(length: usize, mut value: u32, is_v1: bool) -> Result<Vec<u8>> {
142 let mut table = Vec::with_capacity(length);
143 let key: u32 = if is_v1 { 0x8DF21431 } else { 0x8A77F473 };
144 for _ in 0..length {
145 let t = (key as u64).wrapping_mul((value as u64) ^ (key as u64));
146 value = ((t >> 32) + t) as u32;
147 table.push(value);
148 }
149 let mut mem = MemWriter::with_capacity(length * 4);
150 for i in table {
151 mem.write_u32(i)?;
152 }
153 Ok(mem.into_inner())
154 }
155
156 pub fn compute_name_hash(&self, name: &[u16]) -> Result<u32> {
157 let mut v2 = 0u32;
158 let mut v3 = name.len() as u32;
159 let mut v4 = 1u32;
160 if v3 > 0 {
161 loop {
162 let n = (name[(v4 - 1) as usize] as u32) << (v4 & 7);
163 v2 = v2.wrapping_add(n) & 0x3FFFFFFF;
164 v4 += 1;
165 v3 -= 1;
166 if v3 == 0 {
167 break;
168 }
169 }
170 }
171 Ok(v2)
172 }
173
174 pub fn encrypt_name(&self, name: &mut [u8], hash: i32) -> Result<()> {
175 if name.len() % 2 != 0 {
176 return Err(anyhow::anyhow!(
177 "Invalid name length for Unicode encryption"
178 ));
179 }
180 let char_len = name.len() / 2;
181 let cl = char_len as i32;
182 let temp = (cl.wrapping_mul(cl) ^ cl ^ 0x3e13 ^ (hash >> 16) ^ hash) & 0xFFFF;
183 let mut key = temp;
184 for i in 0..char_len {
185 key = temp
186 .wrapping_add(i as i32)
187 .wrapping_add(key.wrapping_mul(8));
188 name[i * 2] ^= key as u8;
189 name[i * 2 + 1] ^= (key >> 8) as u8;
190 }
191 Ok(())
192 }
193}
194
195impl Encryption for Encryption31 {
196 fn is_unicode(&self) -> bool {
197 true
198 }
199 fn compute_hash(&self, data: &[u8]) -> Result<u32> {
200 let mut hasher = Encryption31Hasher::new();
201 hasher.update(data)?;
202 Ok(hasher.finalize()?)
203 }
204 fn create_hash(&self) -> Result<Box<dyn Hasher>> {
205 Ok(Box::new(Encryption31Hasher::new()))
206 }
207 fn decrypt_name(&self, name: &mut [u8], hash: i32, _encoding: Encoding) -> Result<String> {
208 if name.len() % 2 != 0 {
209 return Err(anyhow::anyhow!(
210 "Invalid name length for Unicode decryption"
211 ));
212 }
213 let char_len = name.len() / 2;
214 let cl = char_len as i32;
215 let temp = (cl.wrapping_mul(cl) ^ cl ^ 0x3e13 ^ (hash >> 16) ^ hash) & 0xFFFF;
216 let mut key = temp;
217 for i in 0..char_len {
218 key = temp
219 .wrapping_add(i as i32)
220 .wrapping_add(key.wrapping_mul(8));
221 name[i * 2] ^= key as u8;
222 name[i * 2 + 1] ^= (key >> 8) as u8;
223 }
224 Ok(decode_to_string(Encoding::Utf16LE, &name, true)?)
225 }
226 fn decrypt_entry<'a>(
227 &self,
228 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
229 entry: &QlieEntry,
230 ) -> Result<Box<dyn ReadDebug + Send + Sync + 'a>> {
231 match entry.is_encrypted {
232 0 => Ok(Box::new(stream)),
234 1 => Ok(Box::new(Encryption31DecryptV1::new(
235 stream,
236 entry.size,
237 entry.name.clone(),
238 entry.key,
239 )?)),
240 2 => Ok(Box::new(Encryption31DecryptV2::new(
241 stream,
242 entry.size,
243 entry.name.clone(),
244 entry.key,
245 entry
246 .common_key
247 .clone()
248 .ok_or(anyhow::anyhow!("Missing common key"))?,
249 )?)),
250 _ => Err(anyhow::anyhow!(
251 "Unsupported encryption flag: {}",
252 entry.is_encrypted
253 )),
254 }
255 }
256}
257
258pub struct Encryption31Hasher {
259 hash: u64,
260 key: u64,
261 buffer: [u8; 8],
262 buffer_len: usize,
263}
264
265impl Encryption31Hasher {
266 pub fn new() -> Self {
267 Self {
268 hash: 0,
269 key: 0,
270 buffer: [0; 8],
271 buffer_len: 0,
272 }
273 }
274
275 fn update_internal(&mut self, data: u64) {
276 const C: u64 = mmx_punpckldq2(0xA35793A7);
277 self.hash = mmx_p_add_w(self.hash, C);
278 let temp = mmx_p_add_w(self.key, self.hash ^ data);
279 self.key = mmx_p_sll_d(temp, 3) | mmx_p_srl_d(temp, 0x1d);
280 }
281}
282
283impl Hasher for Encryption31Hasher {
284 fn update(&mut self, data: &[u8]) -> Result<()> {
285 let mut used = 0;
286 if self.buffer_len > 0 {
287 let to_copy = (8 - self.buffer_len).min(data.len());
288 self.buffer[self.buffer_len..self.buffer_len + to_copy]
289 .copy_from_slice(&data[..to_copy]);
290 self.buffer_len += to_copy;
291 used += to_copy;
292 }
293 if self.buffer_len == 8 {
294 let v = u64::from_le_bytes(self.buffer);
295 self.update_internal(v);
296 self.buffer_len = 0;
297 }
298 let round = (data.len() - used) / 8;
299 let mut reader = MemReaderRef::new(&data[used..]);
300 for _ in 0..round {
301 let v = reader.read_u64()?;
302 self.update_internal(v);
303 used += 8;
304 }
305 let remaining = data.len() - used;
306 if remaining > 0 {
307 self.buffer[..remaining].copy_from_slice(&data[used..]);
308 self.buffer_len = remaining;
309 }
310 Ok(())
311 }
312
313 fn finalize(&mut self) -> Result<u32> {
314 let p1 = ((self.key as i16) as i32).wrapping_mul(((self.key >> 32) as i16) as i32);
315 let p2 = (((self.key >> 16) as i16) as i32).wrapping_mul(((self.key >> 48) as i16) as i32);
316 Ok((p1.wrapping_add(p2)) as u32)
317 }
318}
319
320#[derive(Debug)]
321struct Encryption31DecryptV1<'a> {
322 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
323 table: MemReader,
324 v4: u32,
325 v6: u64,
326}
327
328impl<'a> Encryption31DecryptV1<'a> {
329 pub fn new(
330 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
331 size: u32,
332 name: String,
333 key: u32,
334 ) -> Result<AlignedReader<8, Self>> {
335 let mut v1 = 0x85F532u32;
336 let mut v2 = 0x33F641u32;
337 for (i, n) in name.encode_utf16().enumerate() {
338 v1 = v1.wrapping_add((n as u32) << (i & 7));
339 v2 ^= v1;
340 }
341 v2 = v2.wrapping_add(
342 key ^ ((7 * (size & 0xFFFFFF))
343 .wrapping_add(size)
344 .wrapping_add(v1)
345 .wrapping_add(v1 ^ size ^ 0x8F32DC)),
346 );
347 v2 = 9 * (v2 & 0xFFFFFF);
348 let table = MemReader::new(Encryption31::create_table(0x40, v2, true)?);
349 let v4 = 8 * (table.cpeek_u32_at(52)? & 0xF);
350 let v6 = table.cpeek_u64_at(24)?;
351 let inner = Self {
352 stream,
353 table,
354 v4,
355 v6,
356 };
357 Ok(AlignedReader::new(inner))
358 }
359}
360
361impl<'a> Read for Encryption31DecryptV1<'a> {
362 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
363 let readed = self.stream.read_most(buf)?;
364 let round = readed / 8;
365 let mut writer = MemWriterRef::new(buf);
366 for _ in 0..round {
367 let d = writer.peek_u64()?;
368 let temp = self.table.cpeek_u64_at(self.v4 as u64)?;
369 let v7 = mmx_p_add_d(self.v6 ^ temp, temp);
370 let v8 = d ^ v7;
371 writer.write_u64(v8)?;
372 self.v6 = mmx_p_add_w(mmx_p_sll_d(mmx_p_add_b(v7, v8) ^ v8, 1), v8);
373 self.v4 = (self.v4 + 8) & 0x7F;
374 }
375 Ok(readed)
376 }
377}
378
379#[derive(Debug)]
380pub struct Encryption31EncryptV1<T: Write> {
381 stream: T,
382 table: MemReader,
383 v4: u32,
384 v6: u64,
385}
386
387impl<T: Write> Encryption31EncryptV1<T> {
388 pub fn new(stream: T, size: u32, name: String, key: u32) -> Result<AlignedWriter<8, Self>> {
389 let mut v1 = 0x85F532u32;
390 let mut v2 = 0x33F641u32;
391 for (i, n) in name.encode_utf16().enumerate() {
392 v1 = v1.wrapping_add((n as u32) << (i & 7));
393 v2 ^= v1;
394 }
395 v2 = v2.wrapping_add(
396 key ^ ((7 * (size & 0xFFFFFF))
397 .wrapping_add(size)
398 .wrapping_add(v1)
399 .wrapping_add(v1 ^ size ^ 0x8F32DC)),
400 );
401 v2 = 9 * (v2 & 0xFFFFFF);
402 let table = MemReader::new(Encryption31::create_table(0x40, v2, true)?);
403 let v4 = 8 * (table.cpeek_u32_at(52)? & 0xF);
404 let v6 = table.cpeek_u64_at(24)?;
405 let inner = Self {
406 stream,
407 table,
408 v4,
409 v6,
410 };
411 Ok(AlignedWriter::new(inner))
412 }
413}
414
415impl<T: Write> Write for Encryption31EncryptV1<T> {
416 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
417 let round = buf.len() / 8;
418 let mut reader = MemReaderRef::new(buf);
419 for _ in 0..round {
420 let d = reader.read_u64()?;
421 let temp = self.table.cpeek_u64_at(self.v4 as u64)?;
422 let v7 = mmx_p_add_d(self.v6 ^ temp, temp);
423 let v8 = d ^ v7;
424 self.stream.write_u64(v8)?;
425 self.v6 = mmx_p_add_w(mmx_p_sll_d(mmx_p_add_b(v7, d) ^ d, 1), d);
426 self.v4 = (self.v4 + 8) & 0x7F;
427 }
428 let remain = buf.len() % 8;
429 if remain > 0 {
430 self.stream.write_all(&buf[buf.len() - remain..])?;
431 }
432 Ok(buf.len())
433 }
434
435 fn flush(&mut self) -> std::io::Result<()> {
436 self.stream.flush()
437 }
438}
439
440#[derive(Debug)]
441struct Encryption31DecryptV2<'a> {
442 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
443 table: MemReader,
444 v4: u32,
445 v6: u64,
446 common_key: MemReader,
447}
448
449impl<'a> Encryption31DecryptV2<'a> {
450 pub fn new(
451 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
452 size: u32,
453 name: String,
454 key: u32,
455 common_key: Vec<u8>,
456 ) -> Result<AlignedReader<8, Self>> {
457 let mut v1 = 0x86F7E2u32;
458 let mut v2 = 0x4437F1u32;
459 for (i, n) in name.encode_utf16().enumerate() {
460 v1 = v1.wrapping_add((n as u32) << (i & 7));
461 v2 ^= v1;
462 }
463 v2 = v2.wrapping_add(
464 key ^ ((13 * (size & 0xFFFFFF))
465 .wrapping_add(size)
466 .wrapping_add(v1)
467 .wrapping_add(v1 ^ size ^ 0x56E213)),
468 );
469 v2 = 13 * (v2 & 0xFFFFFF);
470 let table = MemReader::new(Encryption31::create_table(0x40, v2, false)?);
471 let v4 = 8 * (table.cpeek_u32_at(32)? & 0xD);
472 let v6 = table.cpeek_u64_at(24)?;
473 let inner = Self {
474 stream,
475 table,
476 v4,
477 v6,
478 common_key: MemReader::new(common_key),
479 };
480 Ok(AlignedReader::new(inner))
481 }
482}
483
484impl<'a> Read for Encryption31DecryptV2<'a> {
485 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
486 let readed = self.stream.read_most(buf)?;
487 let round = readed / 8;
488 let mut writer = MemWriterRef::new(buf);
489 for _ in 0..round {
490 let d = writer.peek_u64()?;
491 let temp_index1 = ((self.v4 & 0xF) * 8) as u64;
492 let temp_index2 = ((self.v4 & 0x7F) * 8) as u64;
493 let temp = self.table.cpeek_u64_at(temp_index1)?
494 ^ self.common_key.cpeek_u64_at(temp_index2)?;
495 let v7 = mmx_p_add_d(self.v6 ^ temp, temp);
496 let v8 = d ^ v7;
497 writer.write_u64(v8)?;
498 self.v6 = mmx_p_add_w(mmx_p_sll_d(mmx_p_add_b(v7, v8) ^ v8, 1), v8);
499 self.v4 = (self.v4 + 1) & 0x7F;
500 }
501 Ok(readed)
502 }
503}
504
505#[derive(Debug)]
506pub struct Encryption31EncryptV2<T: Write> {
507 stream: T,
508 table: MemReader,
509 v4: u32,
510 v6: u64,
511 common_key: MemReader,
512}
513
514impl<T: Write> Encryption31EncryptV2<T> {
515 pub fn new(
516 stream: T,
517 size: u32,
518 name: String,
519 key: u32,
520 common_key: Vec<u8>,
521 ) -> Result<AlignedWriter<8, Self>> {
522 let mut v1 = 0x86F7E2u32;
523 let mut v2 = 0x4437F1u32;
524 for (i, n) in name.encode_utf16().enumerate() {
525 v1 = v1.wrapping_add((n as u32) << (i & 7));
526 v2 ^= v1;
527 }
528 v2 = v2.wrapping_add(
529 key ^ ((13 * (size & 0xFFFFFF))
530 .wrapping_add(size)
531 .wrapping_add(v1)
532 .wrapping_add(v1 ^ size ^ 0x56E213)),
533 );
534 v2 = 13 * (v2 & 0xFFFFFF);
535 let table = MemReader::new(Encryption31::create_table(0x40, v2, false)?);
536 let v4 = 8 * (table.cpeek_u32_at(32)? & 0xD);
537 let v6 = table.cpeek_u64_at(24)?;
538 let inner = Self {
539 stream,
540 table,
541 v4,
542 v6,
543 common_key: MemReader::new(common_key),
544 };
545 Ok(AlignedWriter::new(inner))
546 }
547}
548
549impl<T: Write> Write for Encryption31EncryptV2<T> {
550 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
551 let round = buf.len() / 8;
552 let mut reader = MemReaderRef::new(buf);
553 for _ in 0..round {
554 let d = reader.read_u64()?;
555 let temp_index1 = ((self.v4 & 0xF) * 8) as u64;
556 let temp_index2 = ((self.v4 & 0x7F) * 8) as u64;
557 let temp = self.table.cpeek_u64_at(temp_index1)?
558 ^ self.common_key.cpeek_u64_at(temp_index2)?;
559 let v7 = mmx_p_add_d(self.v6 ^ temp, temp);
560 let v8 = d ^ v7;
561 self.stream.write_u64(v8)?;
562 self.v6 = mmx_p_add_w(mmx_p_sll_d(mmx_p_add_b(v7, d) ^ d, 1), d);
563 self.v4 = (self.v4 + 1) & 0x7F;
564 }
565 let remain = buf.len() % 8;
566 if remain > 0 {
567 self.stream.write_all(&buf[buf.len() - remain..])?;
568 }
569 Ok(buf.len())
570 }
571
572 fn flush(&mut self) -> std::io::Result<()> {
573 self.stream.flush()
574 }
575}
576
577#[derive(Debug)]
578pub struct Decompressor<'a> {
579 stream: Box<dyn ReadDebug + Send + Sync + 'a>,
580 is_16bit: bool,
581 temp: Vec<u8>,
582 buf: Vec<u8>,
583 buf_pos: usize,
584}
585
586impl<'a> Decompressor<'a> {
587 pub fn new(mut stream: Box<dyn ReadDebug + Send + Sync + 'a>) -> Result<Self> {
588 let sign = stream.read_u32()?;
589 if sign != 0xFF435031 {
590 return Err(anyhow::anyhow!("Invalid compression signature"));
591 }
592 let is_16bit = stream.read_u32()? & 1 != 0;
593 let _unpacked_size = stream.read_u32()?;
594 let temp = vec![0u8; 0x1000];
595 Ok(Self {
596 stream,
597 is_16bit,
598 temp,
599 buf: Vec::new(),
600 buf_pos: 0,
601 })
602 }
603
604 fn next_block(&mut self) -> Result<()> {
605 self.buf.clear();
606 self.buf_pos = 0;
607 let mut buf = [0u8; 1];
608 let readed = self.stream.read(&mut buf)?;
609 if readed == 0 {
610 return Ok(());
611 }
612 let mut buf_used = false;
613 let mut table = [[0u8; 2]; 0x100];
614 let mut i = 0u32;
615 while i < 0x100 {
616 let mut c = if !buf_used {
617 buf_used = true;
618 buf[0] as u32
619 } else {
620 self.stream.read_u8()? as u32
621 };
622 if c > 127 {
623 c -= 127;
624 while c > 0 {
625 table[i as usize][0] = i as u8;
626 c -= 1;
627 i += 1;
628 }
629 }
630 c += 1;
631 while c > 0 && i < 0x100 {
632 table[i as usize][0] = self.stream.read_u8()?;
633 if i as u8 != table[i as usize][0] {
634 table[i as usize][1] = self.stream.read_u8()?;
635 }
636 c -= 1;
637 i += 1;
638 }
639 }
640 let mut block_size = if self.is_16bit {
641 self.stream.read_u16()? as usize
642 } else {
643 self.stream.read_u32()? as usize
644 };
645 let mut temp_length = 0usize;
646 while block_size > 0 || temp_length > 0 {
647 let c = if temp_length > 0 {
648 temp_length -= 1;
649 self.temp[temp_length]
650 } else {
651 block_size -= 1;
652 self.stream.read_u8()?
653 };
654 if c == table[c as usize][0] {
655 self.buf.push(c);
656 } else {
657 self.temp[temp_length] = table[c as usize][1];
658 temp_length += 1;
659 self.temp[temp_length] = table[c as usize][0];
660 temp_length += 1;
661 }
662 }
663 Ok(())
664 }
665}
666
667impl<'a> Read for Decompressor<'a> {
668 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
669 let mut used = 0;
670 while used < buf.len() {
671 if self.buf_pos >= self.buf.len() {
672 self.next_block()
673 .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
674 if self.buf.is_empty() {
675 break;
676 }
677 }
678 let to_copy = (self.buf.len() - self.buf_pos).min(buf.len() - used);
679 buf[used..used + to_copy]
680 .copy_from_slice(&self.buf[self.buf_pos..self.buf_pos + to_copy]);
681 self.buf_pos += to_copy;
682 used += to_copy;
683 }
684 Ok(used)
685 }
686}
687
688pub struct Compressor<W: Write + Seek> {
689 stream: W,
690 buffer: Vec<u8>,
691 total_unpacked_size: u32,
692 is_finished: bool,
693}
694
695impl<W: Write + Seek> Compressor<W> {
696 pub fn new(mut stream: W) -> Result<Self> {
697 stream.write_u32(0xFF435031)?;
698 stream.write_u32(0)?;
699 stream.write_u32(0)?;
700 Ok(Self {
701 stream,
702 buffer: Vec::new(),
703 total_unpacked_size: 0,
704 is_finished: false,
705 })
706 }
707
708 pub fn finish(&mut self) -> Result<()> {
709 if self.is_finished {
710 return Ok(());
711 }
712 if !self.buffer.is_empty() {
713 self.flush_block()?;
714 }
715 let pos = self.stream.stream_position()?;
716 self.stream.seek(SeekFrom::Start(8))?;
717 self.stream.write_u32(self.total_unpacked_size)?;
718 self.stream.seek(SeekFrom::Start(pos))?;
719 self.is_finished = true;
720 Ok(())
721 }
722
723 fn flush_block(&mut self) -> Result<()> {
724 if self.buffer.is_empty() {
725 return Ok(());
726 }
727 let (table, data) = compress_algo(&self.buffer);
728
729 write_table(&mut self.stream, &table)?;
731
732 self.stream.write_u32(data.len() as u32)?;
734 self.stream.write_all(&data)?;
735
736 self.total_unpacked_size += self.buffer.len() as u32;
737 self.buffer.clear();
738 Ok(())
739 }
740}
741
742impl<W: Write + Seek> Write for Compressor<W> {
743 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
744 let mut pos = 0;
745 while pos < buf.len() {
746 let space = 0x10000 - self.buffer.len();
747 let copy = space.min(buf.len() - pos);
748 self.buffer.extend_from_slice(&buf[pos..pos + copy]);
749 pos += copy;
750 if self.buffer.len() >= 0x10000 {
751 self.flush_block()
752 .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
753 }
754 }
755 Ok(buf.len())
756 }
757
758 fn flush(&mut self) -> std::io::Result<()> {
759 self.stream.flush()
760 }
761}
762
763impl<W: Write + Seek> Drop for Compressor<W> {
764 fn drop(&mut self) {
765 let _ = self.finish();
766 }
767}
768
769fn write_table<W: Write>(writer: &mut W, table: &[[u8; 2]; 256]) -> Result<()> {
770 let mut i = 0;
771 while i < 256 {
772 let mut n_identities = 0;
774 let mut j = i;
775 while j < 256 && table[j][0] == j as u8 {
776 n_identities += 1;
777 j += 1;
778 }
779
780 if n_identities > 0 {
781 let k = n_identities.min(128);
782 if i + k == 256 {
783 writer.write_u8(127 + k as u8)?;
784 i += k;
785 } else {
786 writer.write_u8(127 + k as u8)?;
787 i += k;
788 writer.write_u8(table[i][0])?;
790 if table[i][0] != i as u8 {
791 writer.write_u8(table[i][1])?;
792 }
793 i += 1;
794 }
795 } else {
796 let mut count = 0;
797 let mut j = i;
798 while j < 256 && count < 128 {
799 if j + 1 < 256 && table[j][0] == j as u8 && table[j + 1][0] == (j + 1) as u8 {
800 break;
801 }
802 count += 1;
803 j += 1;
804 }
805
806 writer.write_u8((count - 1) as u8)?;
807 for k in 0..count {
808 let curr = i + k;
809 writer.write_u8(table[curr][0])?;
810 if table[curr][0] != curr as u8 {
811 writer.write_u8(table[curr][1])?;
812 }
813 }
814 i += count;
815 }
816 }
817 Ok(())
818}
819
820fn compress_algo(input: &[u8]) -> ([[u8; 2]; 256], Vec<u8>) {
821 let mut tokens = input.to_vec();
822 let mut table = [[0u8; 2]; 256];
823 for i in 0..256 {
824 table[i][0] = i as u8;
825 }
826
827 let max_iterations = 256;
828 for _ in 0..max_iterations {
829 let mut pair_counts = vec![0u32; 65536];
830 let mut max_pair_idx = 0;
831 let mut max_pair_count = 0;
832
833 if tokens.len() < 2 {
834 break;
835 }
836
837 for i in 0..tokens.len() - 1 {
838 let pair = ((tokens[i] as usize) << 8) | (tokens[i + 1] as usize);
839 pair_counts[pair] += 1;
840 if pair_counts[pair] > max_pair_count {
841 max_pair_count = pair_counts[pair];
842 max_pair_idx = pair;
843 }
844 }
845
846 if max_pair_count < 2 {
848 break;
849 }
850
851 let is_used = get_used_tokens(&tokens, &table);
852 let mut unused = None;
853 for i in 0..256 {
854 if !is_used[i] {
855 unused = Some(i as u8);
856 break;
857 }
858 }
859
860 if let Some(token) = unused {
861 let left = (max_pair_idx >> 8) as u8;
862 let right = (max_pair_idx & 0xFF) as u8;
863
864 table[token as usize] = [left, right];
865
866 let mut new_tokens = Vec::with_capacity(tokens.len());
867 let mut i = 0;
868 while i < tokens.len() {
869 if i + 1 < tokens.len() && tokens[i] == left && tokens[i + 1] == right {
870 new_tokens.push(token);
871 i += 2;
872 } else {
873 new_tokens.push(tokens[i]);
874 i += 1;
875 }
876 }
877 tokens = new_tokens;
878 } else {
879 break;
880 }
881 }
882 (table, tokens)
883}
884
885fn get_used_tokens(tokens: &[u8], table: &[[u8; 2]; 256]) -> [bool; 256] {
886 let mut used = [false; 256];
887 let mut stack = Vec::with_capacity(256);
888
889 for &t in tokens {
891 if !used[t as usize] {
892 used[t as usize] = true;
893 stack.push(t);
894 }
895 }
896
897 while let Some(t) = stack.pop() {
899 let t_idx = t as usize;
902 if table[t_idx][0] != t {
903 let l = table[t_idx][0];
904 let r = table[t_idx][1];
905
906 if !used[l as usize] {
907 used[l as usize] = true;
908 stack.push(l);
909 }
910 if !used[r as usize] {
911 used[r as usize] = true;
912 stack.push(r);
913 }
914 }
915 }
916 used
917}
918
919pub fn compress(data: &[u8]) -> Result<Vec<u8>> {
920 let mut cursor = std::io::Cursor::new(Vec::new());
921 {
922 let mut compressor = Compressor::new(&mut cursor)?;
923 compressor.write_all(data)?;
924 compressor.finish()?;
925 }
926 Ok(cursor.into_inner())
927}
928
929const KEY_DIR: [&'static str; 4] = [".", "..", "../DLL", "DLL"];
930
931pub fn find_game_key(filename: &str) -> Result<Option<Vec<u8>>> {
932 let path = PathBuf::from(filename);
933 if !path.is_file() {
934 return Ok(None);
935 }
936 if let Some(pdir) = path.parent() {
937 for dir in KEY_DIR {
938 let key_path = pdir.join(dir).join("key.fkey");
939 if key_path.is_file() {
940 eprintln!("Found res key file: {}", key_path.display());
941 return Ok(Some(std::fs::read(key_path)?));
942 }
943 }
944 let exe_dir = pdir.join("..");
945 if exe_dir.is_dir() {
946 for entry in std::fs::read_dir(exe_dir)? {
947 let entry = entry?;
948 if entry.file_type()?.is_file() {
949 if let Some(ext) = entry.path().extension() {
950 if ext.eq_ignore_ascii_case("exe") {
951 if let Ok(key) = get_game_key_from_exe(&entry.path()) {
952 eprintln!(
953 "Found res key in executable: {}",
954 entry.path().display()
955 );
956 return Ok(Some(key));
957 }
958 }
959 }
960 }
961 }
962 }
963 }
964 Ok(None)
965}
966
967pub fn get_game_key_from_exe<S: AsRef<Path> + ?Sized>(exe_path: &S) -> Result<Vec<u8>> {
968 let path = exe_path.as_ref();
969 let file_map = FileMap::open(path)?;
970 let file = PeFile::from_bytes(&file_map)?;
971 let resources = file.resources()?;
972 Ok(resources
973 .find_resource(&["#10".into(), "RESKEY".into()])?
974 .to_vec())
975}
976
977pub fn find_key_data(filename: &str) -> Result<Option<Vec<u8>>> {
978 let path = PathBuf::from(filename);
979 if !path.is_file() {
980 return Ok(None);
981 }
982 if let Some(pdir) = path.parent() {
983 let exe_dir = pdir.join("..");
984 if exe_dir.is_dir() {
985 for entry in std::fs::read_dir(exe_dir)? {
986 let entry = entry?;
987 if entry.file_type()?.is_file() {
988 if let Some(ext) = entry.path().extension() {
989 if ext.eq_ignore_ascii_case("exe") {
990 if let Ok(key) = get_key_data_from_exe(&entry.path()) {
991 eprintln!(
992 "Found key data in executable: {}",
993 entry.path().display()
994 );
995 return Ok(Some(key));
996 }
997 }
998 }
999 }
1000 }
1001 }
1002 }
1003 Ok(None)
1004}
1005
1006pub fn get_key_data_from_exe<S: AsRef<Path> + ?Sized>(exe_path: &S) -> Result<Vec<u8>> {
1007 let path = exe_path.as_ref();
1008 let file_map = FileMap::open(path)?;
1009 let file = PeFile::from_bytes(&file_map)?;
1010 let resources = file.resources()?;
1011 let key_data = resources.find_resource(&["#10".into(), "TFORM1".into()])?;
1012 let mut reader = MemReaderRef::new(&key_data);
1013 let form = deser_delphi(&mut reader)?;
1014 let image = form
1015 .contents
1016 .iter()
1017 .find(|s| s.name == "IconKeyImage")
1018 .ok_or(anyhow::anyhow!("IconKeyImage not found in form"))?;
1019 let picture_data = image
1020 .properties
1021 .get("Picture.Data")
1022 .ok_or(anyhow::anyhow!("Picture.Data not found in IconKeyImage"))?
1023 .as_bytes()
1024 .ok_or(anyhow::anyhow!("Picture.Data is not bytes"))?;
1025 let mut reader = MemReaderRef::new(picture_data);
1026 let mut sig = [0u8; 6];
1027 reader.read_exact(&mut sig)?;
1028 if &sig != b"\x05TIcon" {
1029 return Err(anyhow::anyhow!("Invalid TIcon signature"));
1030 }
1031 Ok(reader.read_exact_vec(0x100)?)
1032}
1033
1034#[derive(Debug)]
1035pub struct Encryption30 {
1036 key: Option<Vec<u8>>,
1037}
1038
1039impl Encryption30 {
1040 pub fn new(game_key: Option<Vec<u8>>) -> Self {
1041 Self { key: game_key }
1042 }
1043}
1044
1045impl Encryption for Encryption30 {
1046 fn decrypt_name(&self, name: &mut [u8], hash: i32, encoding: Encoding) -> Result<String> {
1047 let key = (hash ^ 0x3E) + name.len() as i32;
1048 for i in 1..=name.len() {
1049 name[i - 1] ^= ((key ^ i as i32).wrapping_add(i as i32)) as u8;
1050 }
1051 Ok(decode_to_string(encoding, name, true)?)
1052 }
1053
1054 fn create_hash(&self) -> Result<Box<dyn Hasher>> {
1055 Ok(Box::new(Encryption30Hasher::new()))
1056 }
1057
1058 fn compute_hash(&self, data: &[u8]) -> Result<u32> {
1059 let mut hasher = Encryption30Hasher::new();
1060 hasher.update(data)?;
1061 hasher.finalize()
1062 }
1063
1064 fn decrypt_entry<'a>(
1065 &self,
1066 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
1067 entry: &QlieEntry,
1068 ) -> Result<Box<dyn ReadDebug + Send + Sync + 'a>> {
1069 if entry.is_encrypted == 0 {
1070 return Ok(Box::new(stream));
1071 }
1072 if self.key.is_none() || entry.common_key.is_none() {
1073 return Ok(Box::new(Decrypter::new(stream, entry.key, entry.size)));
1074 }
1075 return Ok(Box::new(Encryption30Decrypt::new(
1076 stream,
1077 &entry.raw_name,
1078 entry.common_key.as_ref().unwrap(),
1079 entry.size,
1080 entry.key,
1081 self.key.as_ref().unwrap(),
1082 )));
1083 }
1084}
1085
1086#[derive(Debug)]
1087pub struct Encryption30Hasher {
1088 hash: u64,
1089 key: u64,
1090 buffer: [u8; 8],
1091 buffer_len: usize,
1092}
1093
1094impl Encryption30Hasher {
1095 pub fn new() -> Self {
1096 Self {
1097 hash: 0,
1098 key: 0,
1099 buffer: [0; 8],
1100 buffer_len: 0,
1101 }
1102 }
1103
1104 fn update_internal(&mut self, data: u64) {
1105 const C: u64 = mmx_punpckldq2(0x03070307);
1106 self.hash = mmx_p_add_w(self.hash, C);
1107 self.key = mmx_p_add_w(self.key, self.hash ^ data);
1108 }
1109}
1110
1111impl Hasher for Encryption30Hasher {
1112 fn update(&mut self, data: &[u8]) -> Result<()> {
1113 let mut used = 0;
1114 if self.buffer_len > 0 {
1115 let to_copy = (8 - self.buffer_len).min(data.len());
1116 self.buffer[self.buffer_len..self.buffer_len + to_copy]
1117 .copy_from_slice(&data[..to_copy]);
1118 self.buffer_len += to_copy;
1119 used += to_copy;
1120 }
1121 if self.buffer_len == 8 {
1122 let v = u64::from_le_bytes(self.buffer);
1123 self.update_internal(v);
1124 self.buffer_len = 0;
1125 }
1126 let round = (data.len() - used) / 8;
1127 let mut reader = MemReaderRef::new(&data[used..]);
1128 for _ in 0..round {
1129 let v = reader.read_u64()?;
1130 self.update_internal(v);
1131 used += 8;
1132 }
1133 let remaining = data.len() - used;
1134 if remaining > 0 {
1135 self.buffer[..remaining].copy_from_slice(&data[used..]);
1136 self.buffer_len = remaining;
1137 }
1138 Ok(())
1139 }
1140
1141 fn finalize(&mut self) -> Result<u32> {
1142 let key = self.key ^ (self.key >> 32);
1143 Ok(key as u32)
1144 }
1145}
1146
1147#[derive(Debug)]
1148pub struct Decrypter<'a> {
1149 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
1150 v5: u64,
1151 v9: u64,
1152}
1153
1154impl<'a> Decrypter<'a> {
1155 pub fn new(
1156 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
1157 key: u32,
1158 length: u32,
1159 ) -> AlignedReader<8, Self> {
1160 const C1: u64 = 0xA73C5F9D;
1161 const C3: u64 = 0xFEC9753E;
1162 const V5_INIT: u64 = mmx_punpckldq2(C1);
1163 let v9 = mmx_punpckldq2((length.wrapping_add(key) as u64) ^ C3);
1164 AlignedReader::new(Self {
1165 stream,
1166 v5: V5_INIT,
1167 v9,
1168 })
1169 }
1170}
1171
1172impl<'a> Read for Decrypter<'a> {
1173 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1174 let readed = self.stream.read_most(buf)?;
1175 let round = readed / 8;
1176 let mut writer = MemWriterRef::new(buf);
1177 const C2: u64 = 0xCE24F523;
1178 const V7: u64 = mmx_punpckldq2(C2);
1179 for _ in 0..round {
1180 let d = writer.peek_u64()?;
1181 self.v5 = mmx_p_add_d(self.v5, V7) ^ self.v9;
1182 self.v9 = d ^ self.v5;
1183 writer.write_u64(self.v9)?;
1184 }
1185 Ok(readed)
1186 }
1187}
1188
1189#[derive(Debug)]
1190struct Encryption30Decrypt<'a> {
1191 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
1192 table: [u64; 0x10],
1193 hash64: u64,
1194 t: usize,
1195}
1196
1197impl<'a> Encryption30Decrypt<'a> {
1198 pub fn new<'b>(
1199 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
1200 raw_name: &'b [u8],
1201 common_key: &'b [u8],
1202 size: u32,
1203 key: u32,
1204 game_key: &'b [u8],
1205 ) -> AlignedReader<8, Self> {
1206 let mut hash = 0x85F532u32;
1207 let mut seed = 0x33F641u32;
1208 for (i, n) in raw_name.iter().enumerate() {
1209 hash = hash.wrapping_add(((i & 0xFF) as u32) * (*n as u32));
1210 seed ^= hash;
1211 }
1212 seed = seed.wrapping_add(
1213 key ^ ((7 * (size & 0xFFFFFF))
1214 .wrapping_add(size)
1215 .wrapping_add(hash)
1216 .wrapping_add(hash ^ size ^ 0x8F32DC)),
1217 );
1218 seed = 9 * (seed & 0xFFFFFF);
1219 seed ^= 0x453A;
1220 let mut mt = MersenneTwister::new(seed);
1221 if !common_key.is_empty() {
1222 mt.xor_state(common_key);
1223 }
1224 if !game_key.is_empty() {
1225 mt.xor_state(game_key);
1226 }
1227 let mut table = [0u64; 0x10];
1228 for i in 0..0x10 {
1229 table[i] = mt.rand64();
1230 }
1231 for _ in 0..9 {
1232 mt.rand();
1233 }
1234 let hash64 = mt.rand64();
1235 let t = mt.rand() as usize & 0xF;
1236 AlignedReader::new(Self {
1237 stream,
1238 table,
1239 hash64,
1240 t,
1241 })
1242 }
1243}
1244
1245impl<'a> Read for Encryption30Decrypt<'a> {
1246 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1247 let readed = self.stream.read_most(buf)?;
1248 let round = readed / 8;
1249 let mut writer = MemWriterRef::new(buf);
1250 for _ in 0..round {
1251 let data64 = writer.peek_u64()?;
1252 self.hash64 = mmx_p_add_d(self.hash64 ^ self.table[self.t], self.table[self.t]);
1253 let d = data64 ^ self.hash64;
1254 writer.write_u64(d)?;
1255 self.hash64 = mmx_p_add_b(self.hash64, d) ^ d;
1256 self.hash64 = mmx_p_add_w(mmx_p_sll_d(self.hash64, 1), d);
1257 self.t = (self.t + 1) & 0xF;
1258 }
1259 Ok(readed)
1260 }
1261}
1262
1263#[derive(Debug)]
1264pub struct Encryption10 {}
1265
1266impl Encryption10 {
1267 pub fn new() -> Self {
1268 Self {}
1269 }
1270}
1271
1272impl Encryption for Encryption10 {
1273 fn decrypt_name(&self, name: &mut [u8], _hash: i32, encoding: Encoding) -> Result<String> {
1274 const KEY: u32 = 0xC4 ^ 0x3E;
1275 for (i, b) in name.iter_mut().enumerate() {
1276 let i = (i + 1) as u32;
1277 *b ^= ((KEY ^ i).wrapping_add(i)) as u8;
1278 }
1279 decode_to_string(encoding, name, true)
1280 }
1281
1282 fn decrypt_entry<'a>(
1283 &self,
1284 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
1285 entry: &QlieEntry,
1286 ) -> Result<Box<dyn ReadDebug + Send + Sync + 'a>> {
1287 if entry.is_encrypted == 0 {
1288 return Ok(Box::new(stream));
1289 }
1290 Ok(Box::new(Encryption10Decrypt::new(stream, 0)))
1291 }
1292
1293 fn index_has_hash(&self) -> bool {
1294 false
1295 }
1296}
1297
1298#[derive(Debug)]
1299pub struct Encryption20 {
1300 index_has_hash: bool,
1301}
1302
1303impl Encryption20 {
1304 pub fn new() -> Self {
1305 Self {
1306 index_has_hash: true,
1307 }
1308 }
1309
1310 pub fn new_no_hash() -> Self {
1311 Self {
1312 index_has_hash: false,
1313 }
1314 }
1315}
1316
1317impl Encryption for Encryption20 {
1318 fn decrypt_name(&self, name: &mut [u8], _hash: i32, encoding: Encoding) -> Result<String> {
1319 let key = (0xC4u32 ^ 0x3E).wrapping_add(name.len() as u32);
1320 for (i, b) in name.iter_mut().enumerate() {
1321 let i = (i + 1) as u32;
1322 *b ^= ((key ^ i).wrapping_add(i)) as u8;
1323 }
1324 decode_to_string(encoding, name, true)
1325 }
1326
1327 fn decrypt_entry<'a>(
1328 &self,
1329 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
1330 entry: &QlieEntry,
1331 ) -> Result<Box<dyn ReadDebug + Send + Sync + 'a>> {
1332 if entry.is_encrypted == 0 {
1333 return Ok(Box::new(stream));
1334 }
1335 Ok(Box::new(Decrypter::new(stream, 0, entry.size)))
1336 }
1337
1338 fn index_has_hash(&self) -> bool {
1339 self.index_has_hash
1340 }
1341}
1342
1343#[derive(Debug)]
1344struct Encryption10Decrypt<'a> {
1345 stream: Box<dyn ReadSeek + Send + Sync + 'a>,
1346 v5: u64,
1347 v9: u64,
1348}
1349
1350impl<'a> Encryption10Decrypt<'a> {
1351 pub fn new(stream: Box<dyn ReadSeek + Send + Sync + 'a>, key: u32) -> AlignedReader<8, Self> {
1352 const C1: u64 = 0xA73C5F9D;
1353 const C3: u64 = 0xFEC9753E;
1354 const V5_INIT: u64 = mmx_punpckldq2(C1);
1355 let v9 = mmx_punpckldq2((key as u64) ^ C3);
1356 AlignedReader::new(Self {
1357 stream,
1358 v5: V5_INIT,
1359 v9,
1360 })
1361 }
1362}
1363
1364impl<'a> Read for Encryption10Decrypt<'a> {
1365 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1366 let readed = self.stream.read_most(buf)?;
1367 let round = readed / 8;
1368 let mut writer = MemWriterRef::new(buf);
1369 const C2: u64 = 0xCE24F523;
1370 const V7: u64 = mmx_punpckldq2(C2);
1371 for _ in 0..round {
1372 let d = writer.peek_u64()?;
1373 self.v5 = mmx_p_add_d(self.v5, V7) ^ self.v9;
1374 self.v9 = d ^ self.v5;
1375 writer.write_u64(self.v9)?;
1376 }
1377 Ok(readed)
1378 }
1379}
1380
1381#[test]
1382fn test_compress_decompress() -> Result<()> {
1383 let data = b"The quick brown fox jumps over the lazy dog.".repeat(100);
1384 println!("Original size: {}", data.len());
1385 let compressed = compress(&data)?;
1386 println!("Compressed size: {}", compressed.len());
1387 let mut decompressed = decompress(Box::new(MemReaderRef::new(&compressed)))?;
1388 let mut output = Vec::new();
1389 decompressed.read_to_end(&mut output)?;
1390 assert_eq!(data.as_slice(), output.as_slice());
1391 Ok(())
1392}