1use std::fs::File;
4use std::io::{self, Read, Seek, SeekFrom, Write};
5
6pub use super::decoder::HcaInfo;
7use super::decoder::{ClHca, HcaError};
8
9#[derive(Debug, Clone, Default)]
11pub struct KeyTest {
12 pub key: u64,
13 pub subkey: u64,
14 pub start_offset: u32,
15 pub best_score: i32,
16 pub best_key: u64,
17}
18
19const HCA_KEY_SCORE_SCALE: i32 = 10;
21const HCA_KEY_MAX_SKIP_BLANKS: i32 = 1200;
22const HCA_KEY_MIN_TEST_FRAMES: i32 = 3;
23const HCA_KEY_MAX_TEST_FRAMES: i32 = 7;
24const HCA_KEY_MAX_FRAME_SCORE: i32 = 600;
25const HCA_KEY_MAX_TOTAL_SCORE: i32 = HCA_KEY_MAX_TEST_FRAMES * 50 * HCA_KEY_SCORE_SCALE;
26
27pub struct HcaDecoder<R: Read + Seek> {
29 reader: R,
30 info: HcaInfo,
31 handle: ClHca,
32 buf: Vec<u8>,
33 fbuf: Vec<f32>,
34 current_delay: i32,
35 current_block: u32,
36 owns_file: bool,
37}
38
39impl HcaDecoder<File> {
40 pub fn from_file(filename: &str) -> Result<Self, HcaDecoderError> {
42 let file = File::open(filename)?;
43 let mut decoder = HcaDecoder::from_reader(file)?;
44 decoder.owns_file = true;
45 Ok(decoder)
46 }
47}
48
49impl<R: Read + Seek> HcaDecoder<R> {
50 pub fn from_reader(mut reader: R) -> Result<Self, HcaDecoderError> {
52 let mut header_buf = [0u8; 8];
54 reader.read_exact(&mut header_buf)?;
55
56 let header_size = ClHca::is_hca_file(&header_buf).ok_or(HcaDecoderError::InvalidHeader)?;
57
58 if header_size > 0x1000 {
59 return Err(HcaDecoderError::InvalidHeader);
60 }
61
62 let mut full_header = vec![0u8; header_size];
64 reader.seek(SeekFrom::Start(0))?;
65 reader.read_exact(&mut full_header)?;
66
67 let mut handle = ClHca::new();
69 handle.decode_header(&full_header)?;
70
71 let info = handle.get_info()?;
72
73 let buf = vec![0u8; info.block_size as usize];
75 let fbuf = vec![0.0f32; info.channel_count as usize * info.samples_per_block];
76
77 let current_delay = info.encoder_delay as i32;
78
79 Ok(Self {
80 reader,
81 info,
82 handle,
83 buf,
84 fbuf,
85 current_delay,
86 current_block: 0,
87 owns_file: false,
88 })
89 }
90
91 pub fn reset(&mut self) {
93 self.handle.decode_reset();
94 self.current_block = 0;
95 self.current_delay = self.info.encoder_delay as i32;
96 }
97
98 pub fn info(&self) -> &HcaInfo {
100 &self.info
101 }
102
103 pub fn set_encryption_key(&mut self, keycode: u64, subkey: u64) {
105 let key = if subkey != 0 {
106 keycode.wrapping_mul((subkey << 16) | (!subkey as u16 as u64).wrapping_add(2))
107 } else {
108 keycode
109 };
110 self.handle.set_key(key);
111 }
112
113 fn read_packet(&mut self) -> Result<(), HcaDecoderError> {
115 if self.current_block >= self.info.block_count {
116 return Err(HcaDecoderError::Eof);
117 }
118
119 let offset =
120 self.info.header_size as u64 + self.current_block as u64 * self.info.block_size as u64;
121 self.reader.seek(SeekFrom::Start(offset))?;
122 self.reader.read_exact(&mut self.buf)?;
123
124 self.current_block += 1;
125 Ok(())
126 }
127
128 pub fn decode_frame(&mut self) -> Result<(&[f32], usize), HcaDecoderError> {
131 self.read_packet()?;
133
134 self.handle.decode_block(&mut self.buf)?;
136
137 self.handle.read_samples(&mut self.fbuf);
139
140 let samples = self.info.samples_per_block as i32;
141 let mut discard = 0;
142
143 if self.current_delay > 0 {
145 if self.current_delay >= samples {
146 self.current_delay -= samples;
147 return Ok((&[], 0));
148 }
149 discard = self.current_delay;
150 self.current_delay = 0;
151 }
152
153 let start_idx = discard as usize * self.info.channel_count as usize;
154 let num_samples = (samples - discard) as usize;
155 Ok((&self.fbuf[start_idx..], num_samples))
156 }
157
158 pub fn decode_all(&mut self) -> Result<Vec<f32>, HcaDecoderError> {
160 self.reset();
161
162 let channel_count = self.info.channel_count as usize;
163 let total_samples = self.info.block_count as usize * self.info.samples_per_block;
164 let mut all_samples = Vec::with_capacity(total_samples * channel_count);
165
166 loop {
167 match self.decode_frame() {
168 Ok((samples, num_samples)) => {
169 let samples_to_add = num_samples * channel_count;
170 all_samples.extend_from_slice(&samples[..samples_to_add]);
171 }
172 Err(HcaDecoderError::Eof) => break,
173 Err(e) => return Err(e),
174 }
175 }
176
177 Ok(all_samples)
178 }
179
180 pub fn seek(&mut self, sample_num: u32) {
182 let target_sample = sample_num + self.info.encoder_delay;
183 let loop_start_block = target_sample / self.info.samples_per_block as u32;
184 let loop_start_delay =
185 target_sample - (loop_start_block * self.info.samples_per_block as u32);
186
187 self.current_block = loop_start_block;
188 self.current_delay = loop_start_delay as i32;
189 }
190
191 pub fn test_key(&mut self, kt: &mut KeyTest) {
193 let score = self.test_hca_score(kt);
194
195 if score < 0 {
197 return;
198 }
199
200 if kt.best_score <= 0 || (score < kt.best_score && score > 0) {
202 kt.best_score = score;
203 kt.best_key = kt.key;
204 }
205 }
206
207 fn test_hca_score(&mut self, kt: &mut KeyTest) -> i32 {
209 let mut test_frames = 0;
210 let mut current_frame = 0u32;
211 let mut blank_frames = 0;
212 let mut total_score = 0;
213
214 let mut offset = kt.start_offset;
215 if offset == 0 {
216 offset = self.info.header_size;
217 }
218
219 self.set_encryption_key(kt.key, kt.subkey);
220
221 while test_frames < HCA_KEY_MAX_TEST_FRAMES && current_frame < self.info.block_count {
222 let (score, should_break, new_offset) =
223 self.test_single_frame(kt, offset, blank_frames);
224 offset = new_offset;
225
226 if should_break {
227 total_score = -1;
228 break;
229 }
230
231 if score < 0 {
232 break;
233 }
234
235 current_frame += 1;
236
237 if score == 0 && blank_frames < HCA_KEY_MAX_SKIP_BLANKS {
238 blank_frames += 1;
239 continue;
240 }
241
242 test_frames += 1;
243 total_score += scale_frame_score(score);
244
245 if total_score > HCA_KEY_MAX_TOTAL_SCORE {
246 break;
247 }
248 }
249
250 self.handle.decode_reset();
251 finalize_score(total_score, test_frames)
252 }
253
254 fn test_single_frame(
255 &mut self,
256 kt: &mut KeyTest,
257 offset: u32,
258 _blank_frames: i32,
259 ) -> (i32, bool, u32) {
260 if self.reader.seek(SeekFrom::Start(offset as u64)).is_err() {
261 return (-1, false, offset);
262 }
263
264 if self.reader.read_exact(&mut self.buf).is_err() {
265 return (-1, false, offset);
266 }
267
268 let score = self.handle.test_block(&mut self.buf);
269
270 if kt.start_offset == 0 && score != 0 {
272 kt.start_offset = offset;
273 }
274
275 let new_offset = offset + self.info.block_size;
276
277 if !(0..=HCA_KEY_MAX_FRAME_SCORE).contains(&score) {
278 return (0, true, new_offset);
279 }
280
281 (score, false, new_offset)
282 }
283
284 pub fn decode_to_wav<W: Write>(&mut self, w: &mut W) -> Result<(), HcaDecoderError> {
286 self.reset();
287
288 let total_samples = (self.info.block_count * self.info.samples_per_block as u32)
289 .saturating_sub(self.info.encoder_delay) as usize;
290 let total_pcm_bytes = total_samples * self.info.channel_count as usize * 2;
291
292 let mut header = [0u8; 44];
294 header[0..4].copy_from_slice(b"RIFF");
295 header[4..8].copy_from_slice(&((36 + total_pcm_bytes) as u32).to_le_bytes());
296 header[8..12].copy_from_slice(b"WAVE");
297 header[12..16].copy_from_slice(b"fmt ");
298 header[16..20].copy_from_slice(&16u32.to_le_bytes()); header[20..22].copy_from_slice(&1u16.to_le_bytes()); header[22..24].copy_from_slice(&(self.info.channel_count as u16).to_le_bytes());
301 header[24..28].copy_from_slice(&self.info.sampling_rate.to_le_bytes());
302 let byte_rate = self.info.sampling_rate * self.info.channel_count * 2;
303 header[28..32].copy_from_slice(&byte_rate.to_le_bytes());
304 let block_align = (self.info.channel_count * 2) as u16;
305 header[32..34].copy_from_slice(&block_align.to_le_bytes());
306 header[34..36].copy_from_slice(&16u16.to_le_bytes()); header[36..40].copy_from_slice(b"data");
308 header[40..44].copy_from_slice(&(total_pcm_bytes as u32).to_le_bytes());
309
310 w.write_all(&header)?;
311
312 let mut pcm_buf =
313 vec![0i16; self.info.samples_per_block * self.info.channel_count as usize];
314
315 loop {
316 match self.read_packet() {
317 Ok(()) => {}
318 Err(HcaDecoderError::Eof) => break,
319 Err(e) => return Err(e),
320 }
321
322 self.handle.decode_block(&mut self.buf)?;
323 self.handle.read_samples_16(&mut pcm_buf);
324
325 let samples = self.info.samples_per_block as i32;
326 let mut discard = 0;
327
328 if self.current_delay > 0 {
329 if self.current_delay >= samples {
330 self.current_delay -= samples;
331 continue;
332 }
333 discard = self.current_delay;
334 self.current_delay = 0;
335 }
336
337 let start = discard as usize * self.info.channel_count as usize;
338 let end = samples as usize * self.info.channel_count as usize;
339
340 if start >= end || end > pcm_buf.len() {
341 return Err(HcaDecoderError::InvalidSampleRange);
342 }
343
344 let mut data = vec![0u8; (end - start) * 2];
346 for (i, &sample) in pcm_buf[start..end].iter().enumerate() {
347 data[i * 2..i * 2 + 2].copy_from_slice(&sample.to_le_bytes());
348 }
349 w.write_all(&data)?;
350 }
351
352 Ok(())
353 }
354}
355
356fn scale_frame_score(score: i32) -> i32 {
357 match score {
358 1 => 1,
359 0 => 3 * HCA_KEY_SCORE_SCALE,
360 _ => score * HCA_KEY_SCORE_SCALE,
361 }
362}
363
364fn finalize_score(total_score: i32, test_frames: i32) -> i32 {
365 if test_frames > HCA_KEY_MIN_TEST_FRAMES && total_score > 0 && total_score <= test_frames {
367 return 1;
368 }
369 total_score
370}
371
372#[derive(Debug)]
374pub enum HcaDecoderError {
375 Io(io::Error),
376 Hca(HcaError),
377 InvalidHeader,
378 InvalidSampleRange,
379 Eof,
380}
381
382impl std::fmt::Display for HcaDecoderError {
383 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
384 match self {
385 Self::Io(e) => write!(f, "IO error: {}", e),
386 Self::Hca(e) => write!(f, "HCA error: {}", e),
387 Self::InvalidHeader => write!(f, "Invalid HCA header"),
388 Self::InvalidSampleRange => write!(f, "Invalid sample range"),
389 Self::Eof => write!(f, "End of file"),
390 }
391 }
392}
393
394impl std::error::Error for HcaDecoderError {}
395
396impl From<io::Error> for HcaDecoderError {
397 fn from(e: io::Error) -> Self {
398 Self::Io(e)
399 }
400}
401
402impl From<HcaError> for HcaDecoderError {
403 fn from(e: HcaError) -> Self {
404 Self::Hca(e)
405 }
406}
407
408#[cfg(test)]
409mod tests {
410 use super::*;
411
412 #[test]
413 fn test_scale_frame_score() {
414 assert_eq!(scale_frame_score(1), 1);
415 assert_eq!(scale_frame_score(0), 3 * HCA_KEY_SCORE_SCALE); assert_eq!(scale_frame_score(5), 5 * HCA_KEY_SCORE_SCALE); assert_eq!(scale_frame_score(-1), -1 * HCA_KEY_SCORE_SCALE); }
419
420 #[test]
421 fn test_finalize_score() {
422 assert_eq!(finalize_score(4, 5), 1); assert_eq!(finalize_score(2, 2), 2); assert_eq!(finalize_score(100, 5), 100);
428 assert_eq!(finalize_score(-1, 5), -1);
430 }
431
432 #[test]
433 fn test_key_test_default() {
434 let kt = KeyTest::default();
435 assert_eq!(kt.key, 0);
436 assert_eq!(kt.subkey, 0);
437 assert_eq!(kt.start_offset, 0);
438 assert_eq!(kt.best_score, 0);
439 assert_eq!(kt.best_key, 0);
440 }
441
442 #[test]
443 fn test_hca_decoder_error_display() {
444 let err = HcaDecoderError::InvalidHeader;
445 assert_eq!(format!("{}", err), "Invalid HCA header");
446
447 let err = HcaDecoderError::Eof;
448 assert_eq!(format!("{}", err), "End of file");
449
450 let err = HcaDecoderError::InvalidSampleRange;
451 assert_eq!(format!("{}", err), "Invalid sample range");
452 }
453}