1use crate::crc32::crc32;
7
8use super::byte_search;
9
10pub const VM_MEMSIZE: usize = 0x40000;
12pub const VM_MEMMASK: u32 = (VM_MEMSIZE - 1) as u32;
13
14pub const MAX_UNPACK_CHANNELS: usize = 1024;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum StandardFilter {
20 None,
21 E8,
23 E8E9,
25 Itanium,
27 Delta,
29 Rgb,
31 Audio,
33}
34
35struct FilterSignature {
37 length: u32,
38 crc: u32,
39 filter_type: StandardFilter,
40}
41
42const FILTER_SIGNATURES: &[FilterSignature] = &[
43 FilterSignature {
44 length: 53,
45 crc: 0xad576887,
46 filter_type: StandardFilter::E8,
47 },
48 FilterSignature {
49 length: 57,
50 crc: 0x3cd7e57e,
51 filter_type: StandardFilter::E8E9,
52 },
53 FilterSignature {
54 length: 120,
55 crc: 0x3769893f,
56 filter_type: StandardFilter::Itanium,
57 },
58 FilterSignature {
59 length: 29,
60 crc: 0x0e06077d,
61 filter_type: StandardFilter::Delta,
62 },
63 FilterSignature {
64 length: 149,
65 crc: 0x1c2c5dc8,
66 filter_type: StandardFilter::Rgb,
67 },
68 FilterSignature {
69 length: 216,
70 crc: 0xbc85e701,
71 filter_type: StandardFilter::Audio,
72 },
73];
74
75#[derive(Debug, Clone)]
77pub struct PreparedFilter {
78 pub filter_type: StandardFilter,
79 pub init_r: [u32; 7],
81 pub block_start: u64,
83 pub block_length: u32,
85 pub window_mask: u32,
87}
88
89#[derive(Debug, Clone)]
91pub struct StoredFilter {
92 pub filter_type: StandardFilter,
93}
94
95pub struct RarVM {
97 mem: Vec<u8>,
99 filters: Vec<StoredFilter>,
101 stack: Vec<PreparedFilter>,
103 last_filter: usize,
105 old_lengths: Vec<u32>,
107}
108
109impl RarVM {
110 pub fn new() -> Self {
111 Self {
112 mem: vec![0u8; VM_MEMSIZE + 4],
113 filters: Vec::new(),
114 stack: Vec::new(),
115 last_filter: 0,
116 old_lengths: Vec::new(),
117 }
118 }
119
120 pub fn reset(&mut self) {
122 self.filters.clear();
123 self.stack.clear();
124 self.last_filter = 0;
125 self.old_lengths.clear();
126 }
127
128 fn identify_filter(code: &[u8]) -> StandardFilter {
130 if code.is_empty() {
131 return StandardFilter::None;
132 }
133
134 let mut xor_sum: u8 = 0;
136 for &b in &code[1..] {
137 xor_sum ^= b;
138 }
139 #[cfg(test)]
140 let checksum_ok = xor_sum == code[0];
141
142 if xor_sum != code[0] {
143 #[cfg(test)]
144 eprintln!(
145 " identify_filter: XOR checksum FAILED (expected 0x{:02x}, got 0x{:02x})",
146 code[0], xor_sum
147 );
148 return StandardFilter::None;
149 }
150
151 let code_crc = crc32(code);
153 let code_len = code.len() as u32;
154
155 #[cfg(test)]
156 eprintln!(
157 " identify_filter: len={}, crc=0x{:08x}, checksum={}",
158 code_len, code_crc, checksum_ok
159 );
160
161 for sig in FILTER_SIGNATURES {
162 if sig.crc == code_crc && sig.length == code_len {
163 #[cfg(test)]
164 eprintln!(" identified: {:?}", sig.filter_type);
165 return sig.filter_type;
166 }
167 }
168
169 #[cfg(test)]
170 eprintln!(" identified: None (no matching signature)");
171
172 StandardFilter::None
173 }
174
175 fn read_data(data: &[u8], bit_pos: &mut usize) -> u32 {
177 let bits_available = (data.len() * 8).saturating_sub(*bit_pos);
180 if bits_available < 2 {
181 #[cfg(test)]
182 eprintln!(
183 " read_data: EOF at bit_pos={}, data.len={}",
184 *bit_pos,
185 data.len()
186 );
187 return 0;
188 }
189
190 let byte_pos = *bit_pos / 8;
192 let bit_off = *bit_pos % 8;
193
194 let mut val: u32 = 0;
196 if byte_pos < data.len() {
197 val |= (data[byte_pos] as u32) << 16;
198 }
199 if byte_pos + 1 < data.len() {
200 val |= (data[byte_pos + 1] as u32) << 8;
201 }
202 if byte_pos + 2 < data.len() {
203 val |= data[byte_pos + 2] as u32;
204 }
205 val >>= 8 - bit_off;
206 val &= 0xffff;
207
208 #[cfg(test)]
209 if *bit_pos < 100 {
210 eprintln!(" read_data at bit {}: bytes[{}..{}]=[{:02x},{:02x},{:02x}], bit_off={}, val=0x{:04x}",
211 *bit_pos, byte_pos, byte_pos+3,
212 data.get(byte_pos).copied().unwrap_or(0),
213 data.get(byte_pos+1).copied().unwrap_or(0),
214 data.get(byte_pos+2).copied().unwrap_or(0),
215 bit_off, val);
216 }
217
218 match val & 0xc000 {
219 0 => {
220 *bit_pos += 6;
221 (val >> 10) & 0xf
222 }
223 0x4000 => {
224 if (val & 0x3c00) == 0 {
225 *bit_pos += 14;
226 0xffffff00 | ((val >> 2) & 0xff)
227 } else {
228 *bit_pos += 10;
229 (val >> 6) & 0xff
230 }
231 }
232 0x8000 => {
233 *bit_pos += 2;
235 let byte_pos = *bit_pos / 8;
237 let bit_off = *bit_pos % 8;
238
239 let mut raw: u32 = 0;
240 if byte_pos < data.len() {
241 raw |= (data[byte_pos] as u32) << 16;
242 }
243 if byte_pos + 1 < data.len() {
244 raw |= (data[byte_pos + 1] as u32) << 8;
245 }
246 if byte_pos + 2 < data.len() {
247 raw |= data[byte_pos + 2] as u32;
248 }
249 raw >>= 8 - bit_off;
250
251 *bit_pos += 16;
252 raw & 0xffff
253 }
254 _ => {
255 *bit_pos += 2;
257 let byte_pos = *bit_pos / 8;
259 let bit_off = *bit_pos % 8;
260
261 let mut raw1: u32 = 0;
262 if byte_pos < data.len() {
263 raw1 |= (data[byte_pos] as u32) << 16;
264 }
265 if byte_pos + 1 < data.len() {
266 raw1 |= (data[byte_pos + 1] as u32) << 8;
267 }
268 if byte_pos + 2 < data.len() {
269 raw1 |= data[byte_pos + 2] as u32;
270 }
271 raw1 >>= 8 - bit_off;
272 let high16 = raw1 & 0xffff;
273
274 *bit_pos += 16;
275
276 let byte_pos = *bit_pos / 8;
278 let bit_off = *bit_pos % 8;
279
280 let mut raw2: u32 = 0;
281 if byte_pos < data.len() {
282 raw2 |= (data[byte_pos] as u32) << 16;
283 }
284 if byte_pos + 1 < data.len() {
285 raw2 |= (data[byte_pos + 1] as u32) << 8;
286 }
287 if byte_pos + 2 < data.len() {
288 raw2 |= data[byte_pos + 2] as u32;
289 }
290 raw2 >>= 8 - bit_off;
291 let low16 = raw2 & 0xffff;
292
293 *bit_pos += 16;
294 (high16 << 16) | low16
295 }
296 }
297 }
298
299 pub fn add_code(
303 &mut self,
304 first_byte: u8,
305 code: &[u8],
306 total_written: u64,
307 window_mask: u32,
308 ) -> bool {
309 let mut bit_pos = 0;
310
311 #[cfg(test)]
312 eprintln!(
313 " add_code: first_byte=0x{:02x}, code.len={}",
314 first_byte,
315 code.len()
316 );
317
318 let filt_pos = if (first_byte & 0x80) != 0 {
320 let pos = Self::read_data(code, &mut bit_pos);
321 if pos == 0 {
322 self.filters.clear();
324 self.old_lengths.clear();
325 }
326 pos.saturating_sub(1) as usize
327 } else {
328 self.last_filter
329 };
330
331 if filt_pos > self.filters.len() || filt_pos > 1024 {
332 return false;
333 }
334
335 self.last_filter = filt_pos;
336 let new_filter = filt_pos == self.filters.len();
337
338 let mut block_start = Self::read_data(code, &mut bit_pos);
340 if (first_byte & 0x40) != 0 {
341 block_start = block_start.wrapping_add(258);
342 }
343
344 let block_length = if (first_byte & 0x20) != 0 {
346 let len = Self::read_data(code, &mut bit_pos);
347 #[cfg(test)]
348 eprintln!(" block_length read from code: {}", len);
349 if filt_pos < self.old_lengths.len() {
350 self.old_lengths[filt_pos] = len;
351 } else if new_filter {
352 }
354 len
355 } else if filt_pos < self.old_lengths.len() {
356 #[cfg(test)]
357 eprintln!(
358 " block_length from old_lengths[{}]: {}",
359 filt_pos, self.old_lengths[filt_pos]
360 );
361 self.old_lengths[filt_pos]
362 } else {
363 #[cfg(test)]
364 eprintln!(
365 " block_length: 0 (filt_pos {} >= old_lengths.len {})",
366 filt_pos,
367 self.old_lengths.len()
368 );
369 0
370 };
371
372 let absolute_block_start = total_written + block_start as u64;
375
376 let mut init_r = [0u32; 7];
378 init_r[3] = VM_MEMSIZE as u32;
379 init_r[4] = block_length;
380 init_r[5] = 0; init_r[6] = (absolute_block_start & 0xFFFFFFFF) as u32; if (first_byte & 0x10) != 0 {
384 let byte_pos = bit_pos / 8;
386 let bit_off = bit_pos % 8;
387
388 let mut val: u32 = 0;
390 if byte_pos < code.len() {
391 val |= (code[byte_pos] as u32) << 16;
392 }
393 if byte_pos + 1 < code.len() {
394 val |= (code[byte_pos + 1] as u32) << 8;
395 }
396 if byte_pos + 2 < code.len() {
397 val |= code[byte_pos + 2] as u32;
398 }
399 val >>= 8 - bit_off;
400 let init_mask = ((val >> 9) & 0x7f) as u8;
401 bit_pos += 7;
402
403 #[cfg(test)]
404 eprintln!(" init_mask=0x{:02x} at bit {}", init_mask, bit_pos - 7);
405
406 for i in 0..7 {
407 if (init_mask & (1 << i)) != 0 {
408 init_r[i] = Self::read_data(code, &mut bit_pos);
409 #[cfg(test)]
410 eprintln!(" init_r[{}]={}", i, init_r[i]);
411 }
412 }
413 }
414
415 let filter_type = if new_filter {
417 let vm_code_size = Self::read_data(code, &mut bit_pos) as usize;
419 #[cfg(test)]
420 eprintln!(
421 " new_filter: vm_code_size={}, bit_pos={}, code.len={}",
422 vm_code_size,
423 bit_pos,
424 code.len()
425 );
426
427 if vm_code_size == 0 || vm_code_size >= 0x10000 {
428 return false;
429 }
430
431 let mut vm_code = vec![0u8; vm_code_size];
433 for i in 0..vm_code_size {
434 if bit_pos + 8 > code.len() * 8 {
435 return false;
436 }
437 let byte_idx = bit_pos / 8;
439 let bit_off = bit_pos % 8;
440
441 let mut val: u32 = 0;
442 if byte_idx < code.len() {
443 val |= (code[byte_idx] as u32) << 16;
444 }
445 if byte_idx + 1 < code.len() {
446 val |= (code[byte_idx + 1] as u32) << 8;
447 }
448 if byte_idx + 2 < code.len() {
449 val |= code[byte_idx + 2] as u32;
450 }
451 val >>= 8 - bit_off;
452 vm_code[i] = ((val >> 8) & 0xff) as u8;
453 bit_pos += 8;
454 }
455
456 #[cfg(test)]
457 eprintln!(
458 " vm_code first 4 bytes: {:02x} {:02x} {:02x} {:02x}",
459 vm_code.get(0).copied().unwrap_or(0),
460 vm_code.get(1).copied().unwrap_or(0),
461 vm_code.get(2).copied().unwrap_or(0),
462 vm_code.get(3).copied().unwrap_or(0)
463 );
464
465 Self::identify_filter(&vm_code)
466 } else if filt_pos < self.filters.len() {
467 self.filters[filt_pos].filter_type
468 } else {
469 StandardFilter::None
470 };
471
472 if new_filter {
473 self.filters.push(StoredFilter { filter_type });
474 self.old_lengths.push(block_length);
475 }
476
477 #[cfg(test)]
478 eprintln!(
479 " filter: type={:?}, block_start={} (raw {}+total_written {}), len={}",
480 filter_type, absolute_block_start, block_start, total_written, block_length
481 );
482
483 let filter = PreparedFilter {
484 filter_type,
485 init_r,
486 block_start: absolute_block_start as u64,
487 block_length,
488 window_mask,
489 };
490
491 self.stack.push(filter);
492 true
493 }
494
495 pub fn has_pending_filters(&self) -> bool {
497 !self.stack.is_empty()
498 }
499
500 pub fn find_ready_filter(&self, total_written: u64) -> Option<(usize, u64)> {
503 let mut earliest_idx = None;
504 let mut earliest_start = u64::MAX;
505
506 for (idx, filter) in self.stack.iter().enumerate() {
507 let block_length = (filter.block_length & VM_MEMMASK) as u64;
508 let block_end = filter.block_start + block_length;
509
510 if block_end <= total_written && filter.block_start < earliest_start {
512 #[cfg(test)]
513 if filter.block_start < 1600000 && filter.block_start > 1400000 {
514 eprintln!(" find_ready_filter: found candidate idx={}, start={}, end={}, total_written={}",
515 idx, filter.block_start, block_end, total_written);
516 }
517 earliest_start = filter.block_start;
518 earliest_idx = Some(idx);
519 }
520 }
521
522 earliest_idx.map(|idx| (idx, earliest_start))
523 }
524
525 pub fn next_filter_pos(&self) -> Option<u64> {
527 self.stack.first().map(|f| f.block_start)
528 }
529
530 pub fn next_filter_end(&self) -> Option<u64> {
532 self.stack
533 .iter()
534 .map(|f| f.block_start + (f.block_length & VM_MEMMASK) as u64)
535 .min()
536 }
537
538 pub fn peek_filter(&self) -> Option<&PreparedFilter> {
540 self.stack.first()
541 }
542
543 pub fn execute_filter_at_index(
550 &mut self,
551 filter_idx: usize,
552 window: &[u8],
553 window_mask: usize,
554 total_written: u64,
555 ) -> Option<(u64, &[u8])> {
556 if filter_idx >= self.stack.len() {
557 return None;
558 }
559
560 let filter = self.stack.remove(filter_idx);
562 let block_start = filter.block_start;
563 let block_length = (filter.block_length & VM_MEMMASK) as usize;
564 let block_end = block_start + block_length as u64;
565
566 #[cfg(test)]
567 eprintln!(
568 "EXECUTE filter {:?}: start={}, len={}, total_written={}",
569 filter.filter_type, block_start, block_length, total_written
570 );
571 #[cfg(not(test))]
572 let _ = total_written;
573
574 let copy_len = block_length.min(VM_MEMSIZE);
576 let window_start = (block_start as usize) & window_mask;
577
578 if window_start + copy_len <= window.len() {
580 self.mem[..copy_len].copy_from_slice(&window[window_start..window_start + copy_len]);
581 } else {
582 let first_part = window.len() - window_start;
584 self.mem[..first_part].copy_from_slice(&window[window_start..]);
585 self.mem[first_part..copy_len].copy_from_slice(&window[..copy_len - first_part]);
586 }
587
588 #[cfg(test)]
589 {
590 if block_start == 46592 {
591 eprintln!(
593 " WINDOW at filter start: window[46592..46608] = {:02x?}",
594 (46592..46608)
595 .map(|p| window[p & window_mask])
596 .collect::<Vec<_>>()
597 );
598 eprintln!(" INPUT to filter: mem[0..16] = {:02x?}", &self.mem[0..16]);
600 eprintln!(
601 " INPUT to filter: mem[9456..9472] = {:02x?}",
602 &self.mem[9456..9472]
603 );
604 }
605 }
606
607 #[cfg(test)]
608 {
609 eprintln!(" init_r: {:?}", filter.init_r);
610 }
611
612 let (filtered_data_offset, filtered_size) = self.execute_filter(&filter, block_length);
614
615 #[cfg(test)]
616 eprintln!(
617 " result: filtered_data_offset={}, filtered_size={}",
618 filtered_data_offset, filtered_size
619 );
620
621 let output_size = filtered_size.max(block_length);
624 let data = if filtered_size > 0 && filtered_size <= output_size {
625 &self.mem[filtered_data_offset..filtered_data_offset + filtered_size]
626 } else {
627 &self.mem[0..block_length]
629 };
630
631 Some((block_end, data))
632 }
633
634 pub fn execute_filters(
638 &mut self,
639 buffer: &mut [u8],
640 _write_pos: u64,
641 ) -> Option<(usize, usize)> {
642 if self.stack.is_empty() {
643 return None;
644 }
645
646 let filter = &self.stack[0];
647 let block_start = filter.block_start as usize;
648 let block_length = (filter.block_length & VM_MEMMASK) as usize;
649
650 if block_start + block_length > buffer.len() {
652 return None;
653 }
654
655 let filter = self.stack.remove(0);
657
658 #[cfg(test)]
659 eprintln!(
660 "EXECUTE filter {:?}: start={}, len={}, buffer.len={}",
661 filter.filter_type,
662 block_start,
663 block_length,
664 buffer.len()
665 );
666
667 let copy_len = block_length.min(VM_MEMSIZE);
669 self.mem[..copy_len].copy_from_slice(&buffer[block_start..block_start + copy_len]);
670
671 #[cfg(test)]
672 {
673 eprintln!(" init_r: {:?}", filter.init_r);
674 if block_start <= 4096 && block_start + block_length > 4096 {
675 let _offset = 4096 - block_start;
676 eprintln!(
677 " BEFORE buffer[4096..4104]: {:02x?}",
678 &buffer[4096..4104.min(buffer.len())]
679 );
680 }
681 }
682
683 let (filtered_data, filtered_size) = self.execute_filter(&filter, block_length);
685
686 #[cfg(test)]
687 eprintln!(
688 " result: filtered_data={}, filtered_size={}",
689 filtered_data, filtered_size
690 );
691
692 if filtered_size > 0 && filtered_size <= block_length {
693 buffer[block_start..block_start + filtered_size]
695 .copy_from_slice(&self.mem[filtered_data..filtered_data + filtered_size]);
696
697 #[cfg(test)]
698 if block_start <= 4096 && block_start + block_length > 4096 {
699 eprintln!(
700 " AFTER buffer[4096..4104]: {:02x?}",
701 &buffer[4096..4104.min(buffer.len())]
702 );
703 }
704 }
705
706 Some((block_start, filtered_size.max(block_length)))
707 }
708
709 fn execute_filter(&mut self, filter: &PreparedFilter, data_size: usize) -> (usize, usize) {
711 let r = filter.init_r;
712
713 match filter.filter_type {
714 StandardFilter::None => (0, data_size),
715 StandardFilter::E8 | StandardFilter::E8E9 => self.filter_e8e9(
716 r[4] as usize,
717 r[6],
718 filter.filter_type == StandardFilter::E8E9,
719 ),
720 StandardFilter::Itanium => self.filter_itanium(r[4] as usize, r[6]),
721 StandardFilter::Delta => self.filter_delta(r[4] as usize, r[0] as usize),
722 StandardFilter::Rgb => self.filter_rgb(r[4] as usize, r[0] as usize, r[1] as usize),
723 StandardFilter::Audio => self.filter_audio(r[4] as usize, r[0] as usize),
724 }
725 }
726
727 fn filter_e8e9(
729 &mut self,
730 data_size: usize,
731 file_offset: u32,
732 include_e9: bool,
733 ) -> (usize, usize) {
734 if !(4..=VM_MEMSIZE).contains(&data_size) {
735 return (0, 0);
736 }
737
738 const FILE_SIZE: u32 = 0x1000000;
739
740 let search_end = data_size - 4;
742 let mut cur_pos: usize = 0;
743
744 while cur_pos < search_end {
745 let found = if include_e9 {
746 byte_search::find_byte2(&self.mem[cur_pos..search_end], 0xe8, 0xe9)
747 } else {
748 byte_search::find_byte(&self.mem[cur_pos..search_end], 0xe8)
749 };
750 if let Some(offset) = found {
751 cur_pos += offset;
752 let addr_pos = cur_pos + 1;
753 let offset_val = addr_pos as u32 + file_offset;
754 let addr = u32::from_le_bytes([
755 self.mem[addr_pos],
756 self.mem[addr_pos + 1],
757 self.mem[addr_pos + 2],
758 self.mem[addr_pos + 3],
759 ]);
760 Self::transform_e8e9_addr(
761 &mut self.mem[addr_pos..addr_pos + 4],
762 addr,
763 offset_val,
764 FILE_SIZE,
765 );
766 cur_pos = addr_pos + 4;
767 } else {
768 break;
769 }
770 }
771
772 (0, data_size)
773 }
774
775 #[inline(always)]
777 fn transform_e8e9_addr(dest: &mut [u8], addr: u32, offset: u32, file_size: u32) {
778 if (addr & 0x80000000) != 0 {
779 if (addr.wrapping_add(offset) & 0x80000000) == 0 {
781 let new_addr = addr.wrapping_add(file_size);
782 dest.copy_from_slice(&new_addr.to_le_bytes());
783 }
784 } else {
785 if (addr.wrapping_sub(file_size) & 0x80000000) != 0 {
787 let new_addr = addr.wrapping_sub(offset);
788 dest.copy_from_slice(&new_addr.to_le_bytes());
789 }
790 }
791 }
792
793 fn filter_itanium(&mut self, data_size: usize, file_offset: u32) -> (usize, usize) {
795 if !(21..=VM_MEMSIZE).contains(&data_size) {
796 return (0, 0);
797 }
798
799 static MASKS: [u8; 16] = [4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0];
800
801 let mut cur_pos: usize = 0;
802 let mut file_off = file_offset >> 4;
803
804 while cur_pos < data_size - 21 {
805 let byte_val = (self.mem[cur_pos] & 0x1f) as i32 - 0x10;
806 if byte_val >= 0 {
807 let cmd_mask = MASKS[byte_val as usize];
808 if cmd_mask != 0 {
809 for i in 0..=2 {
810 if (cmd_mask & (1 << i)) != 0 {
811 let start_pos = i * 41 + 5;
812 let op_type = self.itanium_get_bits(cur_pos, start_pos + 37, 4);
813 if op_type == 5 {
814 let offset = self.itanium_get_bits(cur_pos, start_pos + 13, 20);
815 self.itanium_set_bits(
816 cur_pos,
817 (offset.wrapping_sub(file_off)) & 0xfffff,
818 start_pos + 13,
819 20,
820 );
821 }
822 }
823 }
824 }
825 }
826 cur_pos += 16;
827 file_off = file_off.wrapping_add(1);
828 }
829
830 (0, data_size)
831 }
832
833 fn itanium_get_bits(&self, base: usize, bit_pos: usize, bit_count: usize) -> u32 {
834 let in_addr = base + bit_pos / 8;
835 let in_bit = bit_pos & 7;
836
837 let mut bit_field: u32 = 0;
838 if in_addr < self.mem.len() {
839 bit_field |= self.mem[in_addr] as u32;
840 }
841 if in_addr + 1 < self.mem.len() {
842 bit_field |= (self.mem[in_addr + 1] as u32) << 8;
843 }
844 if in_addr + 2 < self.mem.len() {
845 bit_field |= (self.mem[in_addr + 2] as u32) << 16;
846 }
847 if in_addr + 3 < self.mem.len() {
848 bit_field |= (self.mem[in_addr + 3] as u32) << 24;
849 }
850
851 bit_field >>= in_bit;
852 bit_field & (0xffffffff >> (32 - bit_count))
853 }
854
855 fn itanium_set_bits(&mut self, base: usize, bit_field: u32, bit_pos: usize, bit_count: usize) {
856 let in_addr = base + bit_pos / 8;
857 let in_bit = bit_pos & 7;
858
859 let and_mask = !(((1u32 << bit_count) - 1) << in_bit);
860 let bit_field = bit_field << in_bit;
861
862 for i in 0..4 {
863 if in_addr + i < self.mem.len() {
864 self.mem[in_addr + i] &= (and_mask >> (i * 8)) as u8;
865 self.mem[in_addr + i] |= (bit_field >> (i * 8)) as u8;
866 }
867 }
868 }
869
870 fn filter_delta(&mut self, data_size: usize, channels: usize) -> (usize, usize) {
872 if data_size > VM_MEMSIZE / 2 || channels > MAX_UNPACK_CHANNELS || channels == 0 {
873 return (0, 0);
874 }
875
876 let border = data_size * 2;
877 let mut src_pos = 0;
878
879 for cur_channel in 0..channels {
880 let mut prev_byte: u8 = 0;
881 let mut dest_pos = data_size + cur_channel;
882 while dest_pos < border {
883 prev_byte = prev_byte.wrapping_sub(self.mem[src_pos]);
884 self.mem[dest_pos] = prev_byte;
885 src_pos += 1;
886 dest_pos += channels;
887 }
888 }
889
890 (data_size, data_size)
891 }
892
893 fn filter_rgb(&mut self, data_size: usize, width: usize, pos_r: usize) -> (usize, usize) {
895 let width = width.saturating_sub(3);
896 if !(3..=VM_MEMSIZE / 2).contains(&data_size) || width > data_size || pos_r > 2 {
897 return (0, 0);
898 }
899
900 const CHANNELS: usize = 3;
901 let mut src_idx = 0;
902
903 for cur_channel in 0..CHANNELS {
904 let mut prev_byte: u32 = 0;
905
906 let mut i = cur_channel;
907 while i < data_size {
908 let predicted = if i >= width + 3 {
909 let upper_idx = data_size + i - width;
910 let upper_byte = self.mem[upper_idx] as u32;
911 let upper_left_byte = self.mem[upper_idx - 3] as u32;
912
913 let mut pred = prev_byte
914 .wrapping_add(upper_byte)
915 .wrapping_sub(upper_left_byte);
916 let pa = (pred as i32 - prev_byte as i32).unsigned_abs();
917 let pb = (pred as i32 - upper_byte as i32).unsigned_abs();
918 let pc = (pred as i32 - upper_left_byte as i32).unsigned_abs();
919
920 if pa <= pb && pa <= pc {
921 pred = prev_byte;
922 } else if pb <= pc {
923 pred = upper_byte;
924 } else {
925 pred = upper_left_byte;
926 }
927 pred
928 } else {
929 prev_byte
930 };
931
932 prev_byte = predicted.wrapping_sub(self.mem[src_idx] as u32) & 0xff;
933 self.mem[data_size + i] = prev_byte as u8;
934 src_idx += 1;
935 i += CHANNELS;
936 }
937 }
938
939 let border = data_size - 2;
941 let mut i = pos_r;
942 while i < border {
943 let g = self.mem[data_size + i + 1];
944 self.mem[data_size + i] = self.mem[data_size + i].wrapping_add(g);
945 self.mem[data_size + i + 2] = self.mem[data_size + i + 2].wrapping_add(g);
946 i += 3;
947 }
948
949 (data_size, data_size)
950 }
951
952 fn filter_audio(&mut self, data_size: usize, channels: usize) -> (usize, usize) {
954 if data_size > VM_MEMSIZE / 2 || channels > 128 || channels == 0 {
955 return (0, 0);
956 }
957
958 let mut src_idx = 0;
959
960 for cur_channel in 0..channels {
961 let mut prev_byte: u32 = 0;
962 let mut prev_delta: i32 = 0;
963 let mut dif = [0u32; 7];
964 let mut d1: i32 = 0;
965 let mut d2: i32 = 0;
966 let mut k1: i32 = 0;
967 let mut k2: i32 = 0;
968 let mut k3: i32 = 0;
969
970 let mut i = cur_channel;
971 let mut byte_count = 0u32;
972 while i < data_size {
973 let d3 = d2;
974 d2 = prev_delta - d1;
975 d1 = prev_delta;
976
977 let predicted = (8i32 * prev_byte as i32 + k1 * d1 + k2 * d2 + k3 * d3) >> 3;
978 let predicted = (predicted as u32) & 0xff;
979
980 let cur_byte = self.mem[src_idx] as u32;
981 src_idx += 1;
982
983 let result = predicted.wrapping_sub(cur_byte) & 0xff;
984 self.mem[data_size + i] = result as u8;
985 prev_delta = (result.wrapping_sub(prev_byte) & 0xff) as u8 as i8 as i32;
988 prev_byte = result;
989
990 let d = ((cur_byte as i8) as i32) << 3;
991
992 dif[0] = dif[0].wrapping_add(d.unsigned_abs());
993 dif[1] = dif[1].wrapping_add((d - d1).unsigned_abs());
994 dif[2] = dif[2].wrapping_add((d + d1).unsigned_abs());
995 dif[3] = dif[3].wrapping_add((d - d2).unsigned_abs());
996 dif[4] = dif[4].wrapping_add((d + d2).unsigned_abs());
997 dif[5] = dif[5].wrapping_add((d - d3).unsigned_abs());
998 dif[6] = dif[6].wrapping_add((d + d3).unsigned_abs());
999
1000 if (byte_count & 0x1f) == 0 {
1001 let mut min_dif = dif[0];
1002 let mut num_min_dif = 0;
1003 dif[0] = 0;
1004
1005 for j in 1..7 {
1006 if dif[j] < min_dif {
1007 min_dif = dif[j];
1008 num_min_dif = j;
1009 }
1010 dif[j] = 0;
1011 }
1012
1013 match num_min_dif {
1014 1 => {
1015 if k1 >= -16 {
1016 k1 -= 1;
1017 }
1018 }
1019 2 => {
1020 if k1 < 16 {
1021 k1 += 1;
1022 }
1023 }
1024 3 => {
1025 if k2 >= -16 {
1026 k2 -= 1;
1027 }
1028 }
1029 4 => {
1030 if k2 < 16 {
1031 k2 += 1;
1032 }
1033 }
1034 5 => {
1035 if k3 >= -16 {
1036 k3 -= 1;
1037 }
1038 }
1039 6 => {
1040 if k3 < 16 {
1041 k3 += 1;
1042 }
1043 }
1044 _ => {}
1045 }
1046 }
1047
1048 i += channels;
1049 byte_count += 1;
1050 }
1051 }
1052
1053 (data_size, data_size)
1054 }
1055}
1056
1057impl Default for RarVM {
1058 fn default() -> Self {
1059 Self::new()
1060 }
1061}
1062
1063#[cfg(test)]
1064mod tests {
1065 use super::*;
1066
1067 #[test]
1068 fn test_filter_identification() {
1069 assert_eq!(RarVM::identify_filter(&[]), StandardFilter::None);
1071 }
1072
1073 #[test]
1074 fn test_delta_filter() {
1075 let mut vm = RarVM::new();
1076
1077 vm.mem[0] = 10;
1079 vm.mem[1] = 20;
1080 vm.mem[2] = 30;
1081 vm.mem[3] = 5;
1082 vm.mem[4] = 10;
1083 vm.mem[5] = 15;
1084
1085 let (offset, size) = vm.filter_delta(6, 3);
1086 assert_eq!(offset, 6);
1087 assert_eq!(size, 6);
1088 }
1089
1090 #[test]
1091 fn test_e8_filter() {
1092 let mut vm = RarVM::new();
1093
1094 vm.mem[0] = 0xe8;
1096 vm.mem[1] = 0x00;
1097 vm.mem[2] = 0x00;
1098 vm.mem[3] = 0x10;
1099 vm.mem[4] = 0x00;
1100
1101 let (offset, size) = vm.filter_e8e9(5, 0, false);
1102 assert_eq!(offset, 0);
1103 assert_eq!(size, 5);
1104 }
1105}