1use crate::header::controller::Controller;
2use crate::input_data::dpad_input::{DPadButton, DPadInput};
3use crate::input_data::face_input::{FaceButton, FaceInput};
4use crate::input_data::input::Input;
5use crate::input_data::stick_input::StickInput;
6
7pub mod dpad_input;
8pub mod face_input;
9pub mod input;
10pub mod stick_input;
11
12#[derive(thiserror::Error, Debug)]
14pub enum InputDataError {
15 #[error("Input data length is too short")]
17 InputDataLengthTooShort,
18 #[error("Input data is malformed")]
20 InputDataMalformed,
21 #[error("Face Input Error: {0}")]
23 FaceInputError(#[from] face_input::FaceInputError),
24 #[error("DPad Input Error: {0}")]
26 DPadInputError(#[from] dpad_input::DPadInputError),
27 #[error("Stick Input Error: {0}")]
29 StickInputError(#[from] stick_input::StickInputError),
30}
31
32pub struct InputData {
43 raw_data: Vec<u8>,
45 face_input_count: u16,
47 stick_input_count: u16,
49 dpad_input_count: u16,
51 face_inputs: Vec<FaceInput>,
53 stick_inputs: Vec<StickInput>,
55 dpad_inputs: Vec<DPadInput>,
57}
58
59impl InputData {
60 pub fn new(input_data: &[u8]) -> Result<Self, InputDataError> {
72 if input_data.len() < 0x08 {
73 return Err(InputDataError::InputDataLengthTooShort);
74 }
75
76 let mut raw_data = Vec::from(input_data);
77
78 let input_data = if input_data[4..8] == [0x59, 0x61, 0x7A, 0x31] {
79 yaz1_decompress(&input_data[4..]).unwrap()
81 } else {
82 raw_data.resize(0x2774, 0x00);
83 Vec::from(input_data)
84 };
85
86 let face_input_count = u16::from_be_bytes([input_data[0], input_data[1]]);
87 let stick_input_count = u16::from_be_bytes([input_data[2], input_data[3]]);
88 let dpad_input_count = u16::from_be_bytes([input_data[4], input_data[5]]);
89 if (input_data.len() as u64)
92 < ((face_input_count as u64 + stick_input_count as u64 + dpad_input_count as u64) * 2)
93 + 8
94 {
95 return Err(InputDataError::InputDataMalformed);
96 }
97
98 let mut current_byte = 8;
99 let mut face_inputs: Vec<FaceInput> = Vec::with_capacity(face_input_count as usize);
100 while current_byte < 8 + face_input_count * 2 {
101 let idx = current_byte as usize;
102 let input = &input_data[idx..idx + 2];
103 face_inputs.push(FaceInput::try_from(input)?);
104 current_byte += 2;
105 }
106
107 current_byte = 8 + face_input_count * 2;
108 let mut stick_inputs: Vec<StickInput> = Vec::with_capacity(stick_input_count as usize);
109 while current_byte < 8 + (face_input_count + stick_input_count) * 2 {
110 let idx = current_byte as usize;
111 let input = &input_data[idx..idx + 2];
112 stick_inputs.push(StickInput::try_from(input)?);
113 current_byte += 2;
114 }
115
116 current_byte = 8 + (face_input_count + stick_input_count) * 2;
117 let mut dpad_inputs: Vec<DPadInput> = Vec::with_capacity(dpad_input_count as usize);
118 while current_byte < 8 + (face_input_count + stick_input_count + dpad_input_count) * 2 {
119 let idx = current_byte as usize;
120 let input = &input_data[idx..idx + 2];
121 dpad_inputs.push(DPadInput::try_from(input)?);
122 current_byte += 2;
123 }
124
125 for index in (0..face_inputs.len() - 1).rev() {
128 if face_inputs[index] == face_inputs[index + 1] {
129 let f1 = face_inputs[index].frame_duration();
130 let f2 = face_inputs[index + 1].frame_duration();
131 face_inputs[index].set_frame_duration(f1 + f2);
132 face_inputs.remove(index + 1);
133 }
134 }
135
136 for index in (0..stick_inputs.len() - 1).rev() {
137 if stick_inputs[index] == stick_inputs[index + 1] {
138 let f1 = stick_inputs[index].frame_duration();
139 let f2 = stick_inputs[index + 1].frame_duration();
140 stick_inputs[index].set_frame_duration(f1 + f2);
141 stick_inputs.remove(index + 1);
142 }
143 }
144
145 Ok(Self {
146 raw_data,
147 face_input_count,
148 stick_input_count,
149 dpad_input_count,
150 face_inputs,
151 stick_inputs,
152 dpad_inputs,
153 })
154 }
155
156 pub fn inputs(&self) -> Vec<Input> {
163 let mut result = Vec::new();
164
165 let mut face_idx = 0;
167 let mut stick_idx = 0;
168 let mut dpad_idx = 0;
169
170 let mut face_offset = 0u32;
172 let mut stick_offset = 0u32;
173 let mut dpad_offset = 0u32;
174
175 while face_idx < self.face_inputs.len()
177 || stick_idx < self.stick_inputs.len()
178 || dpad_idx < self.dpad_inputs.len()
179 {
180 let face = self.face_inputs.get(face_idx);
182 let stick = self.stick_inputs.get(stick_idx);
183 let dpad = self.dpad_inputs.get(dpad_idx);
184
185 let face_remaining = face
187 .map(|f| f.frame_duration() - face_offset)
188 .unwrap_or(u32::MAX);
189 let stick_remaining = stick
190 .map(|s| s.frame_duration() - stick_offset)
191 .unwrap_or(u32::MAX);
192 let dpad_remaining = dpad
193 .map(|d| d.frame_duration() - dpad_offset)
194 .unwrap_or(u32::MAX);
195
196 let duration = face_remaining.min(stick_remaining).min(dpad_remaining);
198
199 if duration == u32::MAX {
200 break;
202 }
203
204 let combined = Input::new(
206 face.map(|f| f.buttons().clone()).unwrap_or_default(),
207 stick.map(|s| s.x()).unwrap_or(0),
208 stick.map(|s| s.y()).unwrap_or(0),
209 dpad.map(|d| d.button()).unwrap_or(DPadButton::None),
210 duration,
211 );
212 result.push(combined);
213
214 face_offset += duration;
216 stick_offset += duration;
217 dpad_offset += duration;
218
219 if let Some(face) = face
220 && face_offset >= face.frame_duration()
221 {
222 face_idx += 1;
223 face_offset = 0;
224 }
225 if let Some(stick) = stick
226 && stick_offset >= stick.frame_duration()
227 {
228 stick_idx += 1;
229 stick_offset = 0;
230 }
231 if let Some(dpad) = dpad
232 && dpad_offset >= dpad.frame_duration()
233 {
234 dpad_idx += 1;
235 dpad_offset = 0;
236 }
237 }
238
239 result
240 }
241
242 pub fn contains_illegal_brake_or_drift_inputs(&self) -> bool {
248 for (idx, input) in self.face_inputs().iter().enumerate() {
249 let current_buttons = input.buttons();
250 if current_buttons.contains(&FaceButton::Drift)
251 && !current_buttons.contains(&FaceButton::Brake)
252 {
253 return true;
255 } else if idx > 0 {
256 let previous_buttons = self.face_inputs()[idx - 1].buttons();
257 if current_buttons.contains(&FaceButton::Brake)
258 && current_buttons.contains(&FaceButton::Accelerator)
259 && !current_buttons.contains(&FaceButton::Drift)
260 && previous_buttons.contains(&FaceButton::Accelerator)
261 && !previous_buttons.contains(&FaceButton::Brake)
262 {
263 return true;
265 }
266 }
267 }
268 false
269 }
270
271 pub fn is_compressed(&self) -> bool {
273 self.raw_data[4..8] == [0x59, 0x61, 0x7A, 0x31]
274 }
275
276 pub(crate) fn compress(&mut self) {
280 if !self.is_compressed() {
281 self.raw_data = yaz1_compress(&self.raw_data);
282 }
283 }
284
285 pub(crate) fn decompress(&mut self) {
289 if self.is_compressed() {
290 self.raw_data = yaz1_decompress(&self.raw_data[4..]).unwrap();
291 }
292 }
293
294 pub fn raw_data(&self) -> &[u8] {
296 &self.raw_data
297 }
298
299 pub fn contains_illegal_stick_inputs(&self, controller: Controller) -> bool {
307 const ILLEGAL_STICK_INPUTS: [[i8; 2]; 44] = [
309 [-7, 7],
311 [-7, 6],
312 [-7, 5],
313 [-7, -7],
314 [-7, -6],
315 [-7, -5],
316 [-6, 7],
317 [-6, 6],
318 [-6, -7],
319 [-6, -6],
320 [-5, 7],
321 [-5, -7],
322 [7, 7],
323 [7, 6],
324 [7, 5],
325 [7, -7],
326 [7, -6],
327 [7, -5],
328 [6, 7],
329 [6, 6],
330 [6, -7],
331 [6, -6],
332 [5, 7],
333 [5, -7],
334 [-7, 4],
336 [-6, 5],
337 [-5, 6],
338 [-4, 7],
339 [-3, 7],
340 [3, 7],
341 [4, 7],
342 [4, 6],
343 [4, -7],
344 [5, 6],
345 [5, 5],
346 [5, -6],
347 [6, 5],
348 [6, 4],
349 [6, -5],
350 [7, 4],
351 [7, 3],
352 [7, 2],
353 [7, -3],
354 [7, -4],
355 ];
356
357 let illegal_stick_inputs = match controller {
358 Controller::Nunchuk => &ILLEGAL_STICK_INPUTS[..24],
359 Controller::Classic | Controller::Gamecube => &ILLEGAL_STICK_INPUTS,
360 Controller::WiiWheel => {
361 return false;
362 }
363 };
364
365 for current_stick_input in self.stick_inputs().iter() {
366 for illegal_stick_input in illegal_stick_inputs.iter() {
367 if current_stick_input == illegal_stick_input {
368 return true;
369 }
370 }
371 }
372
373 false
374 }
375
376 pub fn face_inputs(&self) -> &[FaceInput] {
378 &self.face_inputs
379 }
380
381 pub fn stick_inputs(&self) -> &[StickInput] {
383 &self.stick_inputs
384 }
385
386 pub fn dpad_inputs(&self) -> &[DPadInput] {
388 &self.dpad_inputs
389 }
390
391 pub fn face_input_count(&self) -> u16 {
393 self.face_input_count
394 }
395
396 pub fn stick_input_count(&self) -> u16 {
398 self.stick_input_count
399 }
400
401 pub fn dpad_input_count(&self) -> u16 {
403 self.dpad_input_count
404 }
405}
406
407pub(crate) fn yaz1_decompress(data: &[u8]) -> Option<Vec<u8>> {
418 if data.len() < 16 || &data[0..4] != b"Yaz1" {
420 return None;
421 }
422
423 let uncompressed_size = u32::from_be_bytes([data[4], data[5], data[6], data[7]]) as usize;
424
425 let mut result = Vec::with_capacity(uncompressed_size);
426
427 let decompressed = decompress_block(
428 data,
429 16, uncompressed_size,
431 );
432
433 if let Some(mut dec) = decompressed {
434 result.append(&mut dec);
435 }
436
437 if result.len() == uncompressed_size {
438 result.resize(0x2774, 0);
439 Some(result)
440 } else {
441 None
442 }
443}
444
445fn decompress_block(src: &[u8], offset: usize, uncompressed_size: usize) -> Option<Vec<u8>> {
450 let mut dst = Vec::with_capacity(uncompressed_size);
451 let mut src_pos = offset;
452
453 let mut valid_bit_count = 0; let mut curr_code_byte = 0u8;
455
456 while dst.len() < uncompressed_size {
457 if valid_bit_count == 0 {
459 if src_pos >= src.len() {
460 return None;
461 }
462 curr_code_byte = src[src_pos];
463 src_pos += 1;
464 valid_bit_count = 8;
465 }
466
467 if (curr_code_byte & 0x80) != 0 {
468 if src_pos >= src.len() {
470 return None;
471 }
472 dst.push(src[src_pos]);
473 src_pos += 1;
474 } else {
475 if src_pos + 1 >= src.len() {
477 return None;
478 }
479
480 let byte1 = src[src_pos];
481 src_pos += 1;
482 let byte2 = src[src_pos];
483 src_pos += 1;
484
485 let dist = (((byte1 & 0xF) as usize) << 8) | (byte2 as usize);
486 let copy_source = dst.len().wrapping_sub(dist + 1);
487
488 let mut num_bytes = (byte1 >> 4) as usize;
489 if num_bytes == 0 {
490 if src_pos >= src.len() {
491 return None;
492 }
493 num_bytes = src[src_pos] as usize + 0x12;
494 src_pos += 1;
495 } else {
496 num_bytes += 2;
497 }
498
499 for i in 0..num_bytes {
501 if copy_source + i >= dst.len() {
502 return None;
503 }
504 let byte = dst[copy_source + i];
505 dst.push(byte);
506 }
507 }
508
509 curr_code_byte <<= 1;
511 valid_bit_count -= 1;
512 }
513
514 Some(dst)
515}
516
517pub(crate) fn yaz1_compress(src: &[u8]) -> Vec<u8> {
526 let mut trailing_bytes_to_remove = 0usize;
528 for idx in (0..src.len()).rev() {
529 if src[idx] == 0 {
530 trailing_bytes_to_remove += 1;
531 } else {
532 break;
533 }
534 }
535
536 let src = &src[0..src.len() - trailing_bytes_to_remove];
537
538 let mut dst = Vec::new();
539 let src_size = src.len();
540 let mut src_pos = 0;
541 let mut prev_flag = false;
542 let mut prev_num_bytes = 0;
543 let mut prev_match_pos = 0;
544
545 let mut code_byte = 0u8;
546 let mut valid_bit_count = 0;
547 let mut chunk = Vec::with_capacity(24); while src_pos < src_size {
550 let (num_bytes, match_pos) = nintendo_encode(
551 src,
552 src_size,
553 src_pos,
554 &mut prev_flag,
555 &mut prev_num_bytes,
556 &mut prev_match_pos,
557 );
558
559 if num_bytes < 3 {
560 chunk.push(src[src_pos]);
562 src_pos += 1;
563 code_byte |= 0x80 >> valid_bit_count;
565 } else {
566 let dist = src_pos - match_pos - 1;
568
569 if num_bytes >= 0x12 {
570 let byte1 = (dist >> 8) as u8;
572 let byte2 = (dist & 0xff) as u8;
573 chunk.push(byte1);
574 chunk.push(byte2);
575
576 let num_bytes = num_bytes.min(0xff + 0x12);
578 let byte3 = (num_bytes - 0x12) as u8;
579 chunk.push(byte3);
580 } else {
581 let byte1 = (((num_bytes - 2) << 4) | (dist >> 8)) as u8;
583 let byte2 = (dist & 0xff) as u8;
584 chunk.push(byte1);
585 chunk.push(byte2);
586 }
587 src_pos += num_bytes;
588 }
589
590 valid_bit_count += 1;
591
592 if valid_bit_count == 8 {
594 dst.push(code_byte);
595 dst.extend_from_slice(&chunk);
596
597 code_byte = 0;
598 valid_bit_count = 0;
599 chunk.clear();
600 }
601 }
602
603 if valid_bit_count > 0 {
605 dst.push(code_byte);
606 dst.extend_from_slice(&chunk);
607 }
608
609 let mut compressed_data = Vec::new();
610
611 compressed_data.extend_from_slice(&((dst.len() + 8) as u32).to_be_bytes()); compressed_data.extend_from_slice(b"Yaz1");
614 compressed_data.extend_from_slice(&(src_size as u32).to_be_bytes());
615 compressed_data.extend_from_slice(&[0u8; 8]); compressed_data.extend_from_slice(&dst);
617 compressed_data
618}
619
620fn nintendo_encode(
627 src: &[u8],
628 size: usize,
629 pos: usize,
630 prev_flag: &mut bool,
631 prev_num_bytes: &mut usize,
632 prev_match_pos: &mut usize,
633) -> (usize, usize) {
634 if *prev_flag {
636 *prev_flag = false;
637 return (*prev_num_bytes, *prev_match_pos);
638 }
639
640 *prev_flag = false;
641 let (num_bytes, match_pos) = simple_encode(src, size, pos);
642
643 if num_bytes >= 3 {
645 let (num_bytes1, match_pos1) = simple_encode(src, size, pos + 1);
646 *prev_num_bytes = num_bytes1;
647 *prev_match_pos = match_pos1;
648
649 if num_bytes1 >= num_bytes + 2 {
651 *prev_flag = true;
652 return (1, match_pos);
653 }
654 }
655
656 (num_bytes, match_pos)
657}
658
659fn simple_encode(src: &[u8], size: usize, pos: usize) -> (usize, usize) {
666 let mut start_pos = pos as i32 - 0x1000;
667 let mut num_bytes = 1;
668 let mut match_pos = 0;
669
670 if start_pos < 0 {
671 start_pos = 0;
672 }
673 let start_pos = start_pos as usize;
674
675 for i in start_pos..pos {
676 let mut j = 0;
677 while j < size - pos {
679 if src[i + j] != src[j + pos] {
680 break;
681 }
682 j += 1;
683 }
684
685 if j > num_bytes {
686 num_bytes = j;
687 match_pos = i;
688 }
689 }
690
691 if num_bytes == 2 {
692 num_bytes = 1;
693 }
694
695 (num_bytes, match_pos)
696}