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("Face Input Error: {0}")]
20 FaceInputError(#[from] face_input::FaceInputError),
21 #[error("DPad Input Error: {0}")]
23 DPadInputError(#[from] dpad_input::DPadInputError),
24 #[error("Stick Input Error: {0}")]
26 StickInputError(#[from] stick_input::StickInputError),
27}
28
29pub struct InputData {
40 raw_data: Vec<u8>,
42 face_input_count: u16,
44 stick_input_count: u16,
46 dpad_input_count: u16,
48 face_inputs: Vec<FaceInput>,
50 stick_inputs: Vec<StickInput>,
52 dpad_inputs: Vec<DPadInput>,
54}
55
56impl InputData {
57 pub fn new(input_data: &[u8]) -> Result<Self, InputDataError> {
69 if input_data.len() < 0x08 {
70 return Err(InputDataError::InputDataLengthTooShort);
71 }
72
73 let mut raw_data = Vec::from(input_data);
74
75 let input_data = if input_data[4..8] == [0x59, 0x61, 0x7A, 0x31] {
76 yaz1_decompress(&input_data[4..]).unwrap()
78 } else {
79 raw_data.resize(0x2774, 0x00);
80 Vec::from(input_data)
81 };
82
83 let face_input_count = u16::from_be_bytes([input_data[0], input_data[1]]);
84 let stick_input_count = u16::from_be_bytes([input_data[2], input_data[3]]);
85 let dpad_input_count = u16::from_be_bytes([input_data[4], input_data[5]]);
86 let mut current_byte = 8;
89 let mut face_inputs: Vec<FaceInput> = Vec::with_capacity(face_input_count as usize);
90 while current_byte < 8 + face_input_count * 2 {
91 let idx = current_byte as usize;
92 let input = &input_data[idx..idx + 2];
93 face_inputs.push(FaceInput::try_from(input)?);
94 current_byte += 2;
95 }
96
97 current_byte = 8 + face_input_count * 2;
98 let mut stick_inputs: Vec<StickInput> = Vec::with_capacity(stick_input_count as usize);
99 while current_byte < 8 + (face_input_count + stick_input_count) * 2 {
100 let idx = current_byte as usize;
101 let input = &input_data[idx..idx + 2];
102 stick_inputs.push(StickInput::try_from(input)?);
103 current_byte += 2;
104 }
105
106 current_byte = 8 + (face_input_count + stick_input_count) * 2;
107 let mut dpad_inputs: Vec<DPadInput> = Vec::with_capacity(dpad_input_count as usize);
108 while current_byte < 8 + (face_input_count + stick_input_count + dpad_input_count) * 2 {
109 let idx = current_byte as usize;
110 let input = &input_data[idx..idx + 2];
111 dpad_inputs.push(DPadInput::try_from(input)?);
112 current_byte += 2;
113 }
114
115 for index in (0..face_inputs.len() - 1).rev() {
118 if face_inputs[index] == face_inputs[index + 1] {
119 let f1 = face_inputs[index].frame_duration();
120 let f2 = face_inputs[index + 1].frame_duration();
121 face_inputs[index].set_frame_duration(f1 + f2);
122 face_inputs.remove(index + 1);
123 }
124 }
125
126 for index in (0..stick_inputs.len() - 1).rev() {
127 if stick_inputs[index] == stick_inputs[index + 1] {
128 let f1 = stick_inputs[index].frame_duration();
129 let f2 = stick_inputs[index + 1].frame_duration();
130 stick_inputs[index].set_frame_duration(f1 + f2);
131 stick_inputs.remove(index + 1);
132 }
133 }
134
135 Ok(Self {
136 raw_data,
137 face_input_count,
138 stick_input_count,
139 dpad_input_count,
140 face_inputs,
141 stick_inputs,
142 dpad_inputs,
143 })
144 }
145
146 pub fn inputs(&self) -> Vec<Input> {
153 let mut result = Vec::new();
154
155 let mut face_idx = 0;
157 let mut stick_idx = 0;
158 let mut dpad_idx = 0;
159
160 let mut face_offset = 0u32;
162 let mut stick_offset = 0u32;
163 let mut dpad_offset = 0u32;
164
165 while face_idx < self.face_inputs.len()
167 || stick_idx < self.stick_inputs.len()
168 || dpad_idx < self.dpad_inputs.len()
169 {
170 let face = self.face_inputs.get(face_idx);
172 let stick = self.stick_inputs.get(stick_idx);
173 let dpad = self.dpad_inputs.get(dpad_idx);
174
175 let face_remaining = face
177 .map(|f| f.frame_duration() - face_offset)
178 .unwrap_or(u32::MAX);
179 let stick_remaining = stick
180 .map(|s| s.frame_duration() - stick_offset)
181 .unwrap_or(u32::MAX);
182 let dpad_remaining = dpad
183 .map(|d| d.frame_duration() - dpad_offset)
184 .unwrap_or(u32::MAX);
185
186 let duration = face_remaining.min(stick_remaining).min(dpad_remaining);
188
189 if duration == u32::MAX {
190 break;
192 }
193
194 let combined = Input::new(
196 face.map(|f| f.buttons().clone()).unwrap_or_default(),
197 stick.map(|s| s.x()).unwrap_or(0),
198 stick.map(|s| s.y()).unwrap_or(0),
199 dpad.map(|d| d.button()).unwrap_or(DPadButton::None),
200 duration,
201 );
202 result.push(combined);
203
204 face_offset += duration;
206 stick_offset += duration;
207 dpad_offset += duration;
208
209 if let Some(face) = face
210 && face_offset >= face.frame_duration()
211 {
212 face_idx += 1;
213 face_offset = 0;
214 }
215 if let Some(stick) = stick
216 && stick_offset >= stick.frame_duration()
217 {
218 stick_idx += 1;
219 stick_offset = 0;
220 }
221 if let Some(dpad) = dpad
222 && dpad_offset >= dpad.frame_duration()
223 {
224 dpad_idx += 1;
225 dpad_offset = 0;
226 }
227 }
228
229 result
230 }
231
232 pub fn contains_illegal_brake_or_drift_inputs(&self) -> bool {
238 for (idx, input) in self.face_inputs().iter().enumerate() {
239 let current_buttons = input.buttons();
240 if current_buttons.contains(&FaceButton::Drift)
241 && !current_buttons.contains(&FaceButton::Brake)
242 {
243 return true;
245 } else if idx > 0 {
246 let previous_buttons = self.face_inputs()[idx - 1].buttons();
247 if current_buttons.contains(&FaceButton::Brake)
248 && current_buttons.contains(&FaceButton::Accelerator)
249 && !current_buttons.contains(&FaceButton::Drift)
250 && previous_buttons.contains(&FaceButton::Accelerator)
251 && !previous_buttons.contains(&FaceButton::Brake)
252 {
253 return true;
255 }
256 }
257 }
258 false
259 }
260
261 pub fn is_compressed(&self) -> bool {
263 self.raw_data[4..8] == [0x59, 0x61, 0x7A, 0x31]
264 }
265
266 pub(crate) fn compress(&mut self) {
270 if !self.is_compressed() {
271 self.raw_data = yaz1_compress(&self.raw_data);
272 }
273 }
274
275 pub(crate) fn decompress(&mut self) {
279 if self.is_compressed() {
280 self.raw_data = yaz1_decompress(&self.raw_data[4..]).unwrap();
281 }
282 }
283
284 pub fn raw_data(&self) -> &[u8] {
286 &self.raw_data
287 }
288
289 pub fn contains_illegal_stick_inputs(&self, controller: Controller) -> bool {
297 const ILLEGAL_STICK_INPUTS: [[i8; 2]; 44] = [
299 [-7, 7],
301 [-7, 6],
302 [-7, 5],
303 [-7, -7],
304 [-7, -6],
305 [-7, -5],
306 [-6, 7],
307 [-6, 6],
308 [-6, -7],
309 [-6, -6],
310 [-5, 7],
311 [-5, -7],
312 [7, 7],
313 [7, 6],
314 [7, 5],
315 [7, -7],
316 [7, -6],
317 [7, -5],
318 [6, 7],
319 [6, 6],
320 [6, -7],
321 [6, -6],
322 [5, 7],
323 [5, -7],
324 [-7, 4],
326 [-6, 5],
327 [-5, 6],
328 [-4, 7],
329 [-3, 7],
330 [3, 7],
331 [4, 7],
332 [4, 6],
333 [4, -7],
334 [5, 6],
335 [5, 5],
336 [5, -6],
337 [6, 5],
338 [6, 4],
339 [6, -5],
340 [7, 4],
341 [7, 3],
342 [7, 2],
343 [7, -3],
344 [7, -4],
345 ];
346
347 let illegal_stick_inputs = match controller {
348 Controller::Nunchuk => &ILLEGAL_STICK_INPUTS[..24],
349 Controller::Classic | Controller::Gamecube => &ILLEGAL_STICK_INPUTS,
350 Controller::WiiWheel => {
351 return false;
352 }
353 };
354
355 for current_stick_input in self.stick_inputs().iter() {
356 for illegal_stick_input in illegal_stick_inputs.iter() {
357 if current_stick_input == illegal_stick_input {
358 return true;
359 }
360 }
361 }
362
363 false
364 }
365
366 pub fn face_inputs(&self) -> &[FaceInput] {
368 &self.face_inputs
369 }
370
371 pub fn stick_inputs(&self) -> &[StickInput] {
373 &self.stick_inputs
374 }
375
376 pub fn dpad_inputs(&self) -> &[DPadInput] {
378 &self.dpad_inputs
379 }
380
381 pub fn face_input_count(&self) -> u16 {
383 self.face_input_count
384 }
385
386 pub fn stick_input_count(&self) -> u16 {
388 self.stick_input_count
389 }
390
391 pub fn dpad_input_count(&self) -> u16 {
393 self.dpad_input_count
394 }
395}
396
397pub(crate) fn yaz1_decompress(data: &[u8]) -> Option<Vec<u8>> {
408 if data.len() < 16 || &data[0..4] != b"Yaz1" {
410 return None;
411 }
412
413 let uncompressed_size = u32::from_be_bytes([data[4], data[5], data[6], data[7]]) as usize;
414
415 let mut result = Vec::with_capacity(uncompressed_size);
416
417 let decompressed = decompress_block(
418 data,
419 16, uncompressed_size,
421 );
422
423 if let Some(mut dec) = decompressed {
424 result.append(&mut dec);
425 }
426
427 if result.len() == uncompressed_size {
428 result.resize(0x2774, 0);
429 Some(result)
430 } else {
431 None
432 }
433}
434
435fn decompress_block(src: &[u8], offset: usize, uncompressed_size: usize) -> Option<Vec<u8>> {
440 let mut dst = Vec::with_capacity(uncompressed_size);
441 let mut src_pos = offset;
442
443 let mut valid_bit_count = 0; let mut curr_code_byte = 0u8;
445
446 while dst.len() < uncompressed_size {
447 if valid_bit_count == 0 {
449 if src_pos >= src.len() {
450 return None;
451 }
452 curr_code_byte = src[src_pos];
453 src_pos += 1;
454 valid_bit_count = 8;
455 }
456
457 if (curr_code_byte & 0x80) != 0 {
458 if src_pos >= src.len() {
460 return None;
461 }
462 dst.push(src[src_pos]);
463 src_pos += 1;
464 } else {
465 if src_pos + 1 >= src.len() {
467 return None;
468 }
469
470 let byte1 = src[src_pos];
471 src_pos += 1;
472 let byte2 = src[src_pos];
473 src_pos += 1;
474
475 let dist = (((byte1 & 0xF) as usize) << 8) | (byte2 as usize);
476 let copy_source = dst.len().wrapping_sub(dist + 1);
477
478 let mut num_bytes = (byte1 >> 4) as usize;
479 if num_bytes == 0 {
480 if src_pos >= src.len() {
481 return None;
482 }
483 num_bytes = src[src_pos] as usize + 0x12;
484 src_pos += 1;
485 } else {
486 num_bytes += 2;
487 }
488
489 for i in 0..num_bytes {
491 if copy_source + i >= dst.len() {
492 return None;
493 }
494 let byte = dst[copy_source + i];
495 dst.push(byte);
496 }
497 }
498
499 curr_code_byte <<= 1;
501 valid_bit_count -= 1;
502 }
503
504 Some(dst)
505}
506
507pub(crate) fn yaz1_compress(src: &[u8]) -> Vec<u8> {
516 let mut trailing_bytes_to_remove = 0usize;
518 for idx in (0..src.len()).rev() {
519 if src[idx] == 0 {
520 trailing_bytes_to_remove += 1;
521 } else {
522 break;
523 }
524 }
525
526 let src = &src[0..src.len() - trailing_bytes_to_remove];
527
528 let mut dst = Vec::new();
529 let src_size = src.len();
530 let mut src_pos = 0;
531 let mut prev_flag = false;
532 let mut prev_num_bytes = 0;
533 let mut prev_match_pos = 0;
534
535 let mut code_byte = 0u8;
536 let mut valid_bit_count = 0;
537 let mut chunk = Vec::with_capacity(24); while src_pos < src_size {
540 let (num_bytes, match_pos) = nintendo_encode(
541 src,
542 src_size,
543 src_pos,
544 &mut prev_flag,
545 &mut prev_num_bytes,
546 &mut prev_match_pos,
547 );
548
549 if num_bytes < 3 {
550 chunk.push(src[src_pos]);
552 src_pos += 1;
553 code_byte |= 0x80 >> valid_bit_count;
555 } else {
556 let dist = src_pos - match_pos - 1;
558
559 if num_bytes >= 0x12 {
560 let byte1 = (dist >> 8) as u8;
562 let byte2 = (dist & 0xff) as u8;
563 chunk.push(byte1);
564 chunk.push(byte2);
565
566 let num_bytes = num_bytes.min(0xff + 0x12);
568 let byte3 = (num_bytes - 0x12) as u8;
569 chunk.push(byte3);
570 } else {
571 let byte1 = (((num_bytes - 2) << 4) | (dist >> 8)) as u8;
573 let byte2 = (dist & 0xff) as u8;
574 chunk.push(byte1);
575 chunk.push(byte2);
576 }
577 src_pos += num_bytes;
578 }
579
580 valid_bit_count += 1;
581
582 if valid_bit_count == 8 {
584 dst.push(code_byte);
585 dst.extend_from_slice(&chunk);
586
587 code_byte = 0;
588 valid_bit_count = 0;
589 chunk.clear();
590 }
591 }
592
593 if valid_bit_count > 0 {
595 dst.push(code_byte);
596 dst.extend_from_slice(&chunk);
597 }
598
599 let mut compressed_data = Vec::new();
600
601 compressed_data.extend_from_slice(&((dst.len() + 8) as u32).to_be_bytes()); compressed_data.extend_from_slice(b"Yaz1");
604 compressed_data.extend_from_slice(&(src_size as u32).to_be_bytes());
605 compressed_data.extend_from_slice(&[0u8; 8]); compressed_data.extend_from_slice(&dst);
607 compressed_data
608}
609
610fn nintendo_encode(
617 src: &[u8],
618 size: usize,
619 pos: usize,
620 prev_flag: &mut bool,
621 prev_num_bytes: &mut usize,
622 prev_match_pos: &mut usize,
623) -> (usize, usize) {
624 if *prev_flag {
626 *prev_flag = false;
627 return (*prev_num_bytes, *prev_match_pos);
628 }
629
630 *prev_flag = false;
631 let (num_bytes, match_pos) = simple_encode(src, size, pos);
632
633 if num_bytes >= 3 {
635 let (num_bytes1, match_pos1) = simple_encode(src, size, pos + 1);
636 *prev_num_bytes = num_bytes1;
637 *prev_match_pos = match_pos1;
638
639 if num_bytes1 >= num_bytes + 2 {
641 *prev_flag = true;
642 return (1, match_pos);
643 }
644 }
645
646 (num_bytes, match_pos)
647}
648
649fn simple_encode(src: &[u8], size: usize, pos: usize) -> (usize, usize) {
656 let mut start_pos = pos as i32 - 0x1000;
657 let mut num_bytes = 1;
658 let mut match_pos = 0;
659
660 if start_pos < 0 {
661 start_pos = 0;
662 }
663 let start_pos = start_pos as usize;
664
665 for i in start_pos..pos {
666 let mut j = 0;
667 while j < size - pos {
669 if src[i + j] != src[j + pos] {
670 break;
671 }
672 j += 1;
673 }
674
675 if j > num_bytes {
676 num_bytes = j;
677 match_pos = i;
678 }
679 }
680
681 if num_bytes == 2 {
682 num_bytes = 1;
683 }
684
685 (num_bytes, match_pos)
686}