prs_rs/impls/decomp/
decompress.rs1use super::common::{read_byte, read_two_le, retrieve_control_bit};
2
3pub(crate) unsafe fn prs_decompress(mut source: *const u8, mut dest: *mut u8) -> usize {
4 let mut control_byte = read_byte(&mut source);
5 let mut current_bit_position = 0;
6 let mut file_size = 0;
7
8 loop {
9 if retrieve_control_bit(&mut control_byte, &mut current_bit_position, &mut source) == 1 {
11 *dest = read_byte(&mut source) as u8;
12 dest = dest.add(1);
13 file_size += 1;
14 continue;
15 }
16
17 if retrieve_control_bit(&mut control_byte, &mut current_bit_position, &mut source) == 1 {
19 if decode_long_copy(&mut source, &mut dest, &mut file_size) {
22 break;
23 }
24 } else {
25 decode_short_copy(
27 &mut control_byte,
28 &mut current_bit_position,
29 &mut source,
30 &mut dest,
31 &mut file_size,
32 );
33 }
34 }
35
36 file_size
37}
38
39#[inline]
40unsafe fn decode_long_copy(
41 source: &mut *const u8,
42 dest: &mut *mut u8,
43 file_size: &mut usize,
44) -> bool {
45 let ofs_bytes = read_two_le(source) as isize;
47 if ofs_bytes == 0 {
48 return true;
49 }
50
51 let offset = (ofs_bytes >> 3) | -0x2000;
54
55 let length = ofs_bytes as usize & 0b111;
59 let length = if length == 0 {
60 read_byte(source) + 1 } else {
62 length + 2 };
64
65 let dest_local = *dest; let src_addr = dest_local.wrapping_add(offset as usize);
67 for i in 0..length {
68 *dest_local.add(i) = *src_addr.add(i);
69 }
70
71 *dest = dest_local.add(length);
72 *file_size += length;
73 false
74}
75
76#[inline]
77unsafe fn decode_short_copy(
78 control_byte: &mut usize,
79 current_bit_position: &mut usize,
80 source: &mut *const u8,
81 dest: &mut *mut u8,
82 file_size: &mut usize,
83) {
84 let mut length = retrieve_control_bit(control_byte, current_bit_position, source) << 1;
86 length |= retrieve_control_bit(control_byte, current_bit_position, source);
87 length += 2;
88
89 let offset = read_byte(source) as isize | -0x100; let dest_local = *dest; let src_addr = dest_local.wrapping_add(offset as usize);
99 for i in 0..length {
100 *dest_local.add(i) = *src_addr.add(i);
101 }
102
103 *dest = dest_local.add(length);
104 *file_size += length;
105}