msg_tool\scripts\circus\audio/
pcm.rs

1//! Circus Audio File (.pcm)
2use crate::ext::io::*;
3use crate::scripts::base::*;
4use crate::types::*;
5use crate::utils::lossless_audio::*;
6use crate::utils::pcm::*;
7use crate::utils::struct_pack::*;
8use anyhow::Result;
9use int_enum::IntEnum;
10use msg_tool_macro::*;
11use overf::wrapping;
12use std::io::{Read, Seek, Write};
13
14#[derive(Debug)]
15/// Circus PCM Builder
16pub struct PcmBuilder {}
17
18impl PcmBuilder {
19    /// Creates a new instance of `PcmBuilder`.
20    pub fn new() -> Self {
21        Self {}
22    }
23}
24
25impl ScriptBuilder for PcmBuilder {
26    fn default_encoding(&self) -> Encoding {
27        Encoding::Utf8
28    }
29
30    fn build_script(
31        &self,
32        buf: Vec<u8>,
33        _filename: &str,
34        _encoding: Encoding,
35        _archive_encoding: Encoding,
36        config: &ExtraConfig,
37        _archive: Option<&Box<dyn Script>>,
38    ) -> Result<Box<dyn Script + Send + Sync>> {
39        Ok(Box::new(Pcm::new(MemReader::new(buf), config)?))
40    }
41
42    fn build_script_from_file(
43        &self,
44        filename: &str,
45        _encoding: Encoding,
46        _archive_encoding: Encoding,
47        config: &ExtraConfig,
48        _archive: Option<&Box<dyn Script>>,
49    ) -> Result<Box<dyn Script + Send + Sync>> {
50        let file = std::fs::File::open(filename)?;
51        let f = std::io::BufReader::new(file);
52        Ok(Box::new(Pcm::new(f, config)?))
53    }
54
55    fn build_script_from_reader<'a>(
56        &self,
57        reader: Box<dyn ReadSeek + Send + Sync + 'a>,
58        _filename: &str,
59        _encoding: Encoding,
60        _archive_encoding: Encoding,
61        config: &ExtraConfig,
62        _archive: Option<&Box<dyn Script>>,
63    ) -> Result<Box<dyn Script + Send + Sync + 'a>> {
64        Ok(Box::new(Pcm::new(reader, config)?))
65    }
66
67    fn extensions(&self) -> &'static [&'static str] {
68        &["pcm"]
69    }
70
71    fn script_type(&self) -> &'static ScriptType {
72        &ScriptType::CircusPcm
73    }
74
75    fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
76        if buf_len >= 4 && buf.starts_with(b"XPCM") {
77            Some(10)
78        } else {
79            None
80        }
81    }
82
83    fn is_audio(&self) -> bool {
84        true
85    }
86}
87
88#[derive(Debug, IntEnum)]
89#[repr(u32)]
90enum Mode {
91    Raw = 0,
92    Lzss = 1,
93    Adpcm = 2,
94    Zlib = 3,
95    Ogg = 5,
96}
97
98#[derive(Debug, StructPack, StructUnpack)]
99struct Header {
100    src_size: u32,
101    _mode: u32,
102    #[skip_pack_if(self.mode() != 5)]
103    #[skip_unpack_if((_mode & 0xFF) != 5)]
104    ogg_size: u32,
105    #[skip_pack_if(self.mode() == 5)]
106    #[skip_unpack_if((_mode & 0xFF) == 5)]
107    pcm: Option<PcmFormat>,
108}
109
110impl Header {
111    pub fn mode(&self) -> u32 {
112        self._mode & 0xFF
113    }
114
115    pub fn extra(&self) -> u32 {
116        (self._mode >> 8) & 0xFF
117    }
118}
119
120#[derive(Debug)]
121/// Circus PCM Script
122pub struct Pcm {
123    header: Header,
124    data: MemReader,
125    config: ExtraConfig,
126}
127
128impl Pcm {
129    /// Creates a new `Pcm` instance from a reader and configuration.
130    ///
131    /// * `reader` - The reader to read the PCM data from.
132    /// * `config` - Extra configuration options.
133    pub fn new<R: Read + Seek>(mut reader: R, config: &ExtraConfig) -> Result<Self> {
134        let mut magic = [0u8; 4];
135        reader.read_exact(&mut magic)?;
136        if &magic != b"XPCM" {
137            return Err(anyhow::anyhow!("Invalid PCM header magic: {:?}", magic));
138        }
139        let header = Header::unpack(&mut reader, false, Encoding::Utf8, &None)?;
140        let mode = Mode::try_from(header.mode())
141            .map_err(|_| anyhow::anyhow!("Unsupported PCM mode: {}", header.mode()))?;
142        let data = match mode {
143            Mode::Ogg => {
144                if header.ogg_size == 0 {
145                    return Err(anyhow::anyhow!("Invalid OGG size in PCM header"));
146                }
147                let mut data = vec![0u8; header.ogg_size as usize];
148                reader.read_exact(&mut data)?;
149                data
150            }
151            Mode::Raw => {
152                let mut data = vec![0u8; header.src_size as usize];
153                reader.read_exact(&mut data)?;
154                data
155            }
156            Mode::Adpcm => Self::decode_adpcm(&mut reader, header.src_size as usize)?,
157            _ => {
158                PcmDecoder::new(reader, header.src_size as usize, header.extra(), mode)?.unpack()?
159            }
160        };
161        Ok(Self {
162            header,
163            data: MemReader::new(data),
164            config: config.clone(),
165        })
166    }
167
168    fn decode_adpcm<R: Read + Seek>(mut input: R, pcm_size: usize) -> Result<Vec<u8>> {
169        let input_len = input.stream_length()? - input.stream_position()?;
170        let mut output = Vec::with_capacity(pcm_size);
171        let mut table = [0u32; 6];
172        let mut channel = 0;
173        let mut src = 0;
174        let mut dst = 0;
175        while src < input_len && dst < pcm_size as u32 {
176            let data = input.read_i8()?;
177            src += 1;
178            table[channel * 3] =
179                table[channel * 3].wrapping_add((data as u32) << (table[channel * 3 + 1] & 0xFF));
180            if data == 0 {
181                if table[channel * 3 + 1] != 0 {
182                    table[channel * 3 + 1] = table[channel * 3 + 1].wrapping_sub(1);
183                }
184            } else if data == 0x7F || data == -0x80 {
185                if table[channel * 3 + 1] != 8 {
186                    table[channel * 3 + 1] = table[channel * 3 + 1].wrapping_add(1);
187                }
188            }
189            output.push(table[channel * 3] as u8);
190            output.push((table[channel * 3] >> 8) as u8);
191            channel = 1 - channel;
192            dst += 2;
193        }
194        Ok(output)
195    }
196}
197
198impl Script for Pcm {
199    fn default_output_script_type(&self) -> OutputScriptType {
200        OutputScriptType::Custom
201    }
202
203    fn default_format_type(&self) -> FormatOptions {
204        FormatOptions::None
205    }
206
207    fn is_output_supported(&self, output: OutputScriptType) -> bool {
208        matches!(output, OutputScriptType::Custom)
209    }
210
211    fn custom_output_extension<'a>(&'a self) -> &'a str {
212        if self.header.mode() == 5 {
213            "ogg"
214        } else {
215            self.config.lossless_audio_fmt.as_ref()
216        }
217    }
218
219    fn custom_export(&self, filename: &std::path::Path, _encoding: Encoding) -> Result<()> {
220        let mut writer = std::fs::File::create(filename)?;
221        if self.header.mode() == 5 {
222            writer.write_all(&self.data.data)?;
223        } else {
224            let fmt = self
225                .header
226                .pcm
227                .as_ref()
228                .ok_or_else(|| anyhow::anyhow!("PCM format not found in header"))?;
229            write_audio(fmt, self.data.to_ref(), writer, &self.config)?;
230        }
231        Ok(())
232    }
233}
234
235const UNK_43A254: [u8; 320] = [
236    0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
237    0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
238    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
239    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
240    0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
241    0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
242    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
243    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
244    0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
245    0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
246    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
247    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
248    0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
249    0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
250    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
251    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
252    0x55, 0x05, 0x00, 0x00, 0x55, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xAA, 0x0A, 0x00, 0x00,
253    0xAA, 0x0A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
254    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
255    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
256];
257const DWORD_43A358: [i32; 2048] = [
258    0x1000, 0x0000, 0x0FFF, 0x0006, 0x0FFF, 0x000C, 0x0FFF, 0x0012, 0x0FFF, 0x0019, 0x0FFF, 0x001F,
259    0x0FFF, 0x0025, 0x0FFF, 0x002B, 0x0FFF, 0x0032, 0x0FFF, 0x0038, 0x0FFF, 0x003E, 0x0FFF, 0x0045,
260    0x0FFF, 0x004B, 0x0FFF, 0x0051, 0x0FFF, 0x0057, 0x0FFE, 0x005E, 0x0FFE, 0x0064, 0x0FFE, 0x006A,
261    0x0FFE, 0x0071, 0x0FFE, 0x0077, 0x0FFE, 0x007D, 0x0FFD, 0x0083, 0x0FFD, 0x008A, 0x0FFD, 0x0090,
262    0x0FFD, 0x0096, 0x0FFC, 0x009D, 0x0FFC, 0x00A3, 0x0FFC, 0x00A9, 0x0FFC, 0x00AF, 0x0FFB, 0x00B6,
263    0x0FFB, 0x00BC, 0x0FFB, 0x00C2, 0x0FFB, 0x00C8, 0x0FFA, 0x00CF, 0x0FFA, 0x00D5, 0x0FFA, 0x00DB,
264    0x0FF9, 0x00E2, 0x0FF9, 0x00E8, 0x0FF9, 0x00EE, 0x0FF8, 0x00F4, 0x0FF8, 0x00FB, 0x0FF7, 0x0101,
265    0x0FF7, 0x0107, 0x0FF7, 0x010D, 0x0FF6, 0x0114, 0x0FF6, 0x011A, 0x0FF5, 0x0120, 0x0FF5, 0x0127,
266    0x0FF4, 0x012D, 0x0FF4, 0x0133, 0x0FF3, 0x0139, 0x0FF3, 0x0140, 0x0FF2, 0x0146, 0x0FF2, 0x014C,
267    0x0FF1, 0x0152, 0x0FF1, 0x0159, 0x0FF0, 0x015F, 0x0FF0, 0x0165, 0x0FEF, 0x016B, 0x0FEF, 0x0172,
268    0x0FEE, 0x0178, 0x0FEE, 0x017E, 0x0FED, 0x0184, 0x0FEC, 0x018B, 0x0FEC, 0x0191, 0x0FEB, 0x0197,
269    0x0FEB, 0x019D, 0x0FEA, 0x01A4, 0x0FE9, 0x01AA, 0x0FE9, 0x01B0, 0x0FE8, 0x01B6, 0x0FE7, 0x01BD,
270    0x0FE7, 0x01C3, 0x0FE6, 0x01C9, 0x0FE5, 0x01CF, 0x0FE4, 0x01D6, 0x0FE4, 0x01DC, 0x0FE3, 0x01E2,
271    0x0FE2, 0x01E8, 0x0FE1, 0x01EF, 0x0FE1, 0x01F5, 0x0FE0, 0x01FB, 0x0FDF, 0x0201, 0x0FDE, 0x0208,
272    0x0FDE, 0x020E, 0x0FDD, 0x0214, 0x0FDC, 0x021A, 0x0FDB, 0x0221, 0x0FDA, 0x0227, 0x0FD9, 0x022D,
273    0x0FD9, 0x0233, 0x0FD8, 0x0239, 0x0FD7, 0x0240, 0x0FD6, 0x0246, 0x0FD5, 0x024C, 0x0FD4, 0x0252,
274    0x0FD3, 0x0259, 0x0FD2, 0x025F, 0x0FD1, 0x0265, 0x0FD0, 0x026B, 0x0FCF, 0x0271, 0x0FCE, 0x0278,
275    0x0FCD, 0x027E, 0x0FCC, 0x0284, 0x0FCB, 0x028A, 0x0FCA, 0x0290, 0x0FC9, 0x0297, 0x0FC8, 0x029D,
276    0x0FC7, 0x02A3, 0x0FC6, 0x02A9, 0x0FC5, 0x02AF, 0x0FC4, 0x02B6, 0x0FC3, 0x02BC, 0x0FC2, 0x02C2,
277    0x0FC1, 0x02C8, 0x0FC0, 0x02CE, 0x0FBF, 0x02D5, 0x0FBE, 0x02DB, 0x0FBD, 0x02E1, 0x0FBB, 0x02E7,
278    0x0FBA, 0x02ED, 0x0FB9, 0x02F3, 0x0FB8, 0x02FA, 0x0FB7, 0x0300, 0x0FB6, 0x0306, 0x0FB4, 0x030C,
279    0x0FB3, 0x0312, 0x0FB2, 0x0318, 0x0FB1, 0x031F, 0x0FB0, 0x0325, 0x0FAE, 0x032B, 0x0FAD, 0x0331,
280    0x0FAC, 0x0337, 0x0FAB, 0x033D, 0x0FA9, 0x0344, 0x0FA8, 0x034A, 0x0FA7, 0x0350, 0x0FA5, 0x0356,
281    0x0FA4, 0x035C, 0x0FA3, 0x0362, 0x0FA1, 0x0368, 0x0FA0, 0x036F, 0x0F9F, 0x0375, 0x0F9D, 0x037B,
282    0x0F9C, 0x0381, 0x0F9B, 0x0387, 0x0F99, 0x038D, 0x0F98, 0x0393, 0x0F96, 0x0399, 0x0F95, 0x03A0,
283    0x0F94, 0x03A6, 0x0F92, 0x03AC, 0x0F91, 0x03B2, 0x0F8F, 0x03B8, 0x0F8E, 0x03BE, 0x0F8C, 0x03C4,
284    0x0F8B, 0x03CA, 0x0F89, 0x03D0, 0x0F88, 0x03D7, 0x0F86, 0x03DD, 0x0F85, 0x03E3, 0x0F83, 0x03E9,
285    0x0F82, 0x03EF, 0x0F80, 0x03F5, 0x0F7F, 0x03FB, 0x0F7D, 0x0401, 0x0F7B, 0x0407, 0x0F7A, 0x040D,
286    0x0F78, 0x0413, 0x0F77, 0x041A, 0x0F75, 0x0420, 0x0F73, 0x0426, 0x0F72, 0x042C, 0x0F70, 0x0432,
287    0x0F6E, 0x0438, 0x0F6D, 0x043E, 0x0F6B, 0x0444, 0x0F69, 0x044A, 0x0F68, 0x0450, 0x0F66, 0x0456,
288    0x0F64, 0x045C, 0x0F63, 0x0462, 0x0F61, 0x0468, 0x0F5F, 0x046E, 0x0F5D, 0x0474, 0x0F5C, 0x047A,
289    0x0F5A, 0x0480, 0x0F58, 0x0486, 0x0F56, 0x048C, 0x0F55, 0x0492, 0x0F53, 0x0498, 0x0F51, 0x049E,
290    0x0F4F, 0x04A5, 0x0F4D, 0x04AB, 0x0F4B, 0x04B1, 0x0F4A, 0x04B7, 0x0F48, 0x04BD, 0x0F46, 0x04C3,
291    0x0F44, 0x04C9, 0x0F42, 0x04CF, 0x0F40, 0x04D5, 0x0F3E, 0x04DB, 0x0F3C, 0x04E0, 0x0F3B, 0x04E6,
292    0x0F39, 0x04EC, 0x0F37, 0x04F2, 0x0F35, 0x04F8, 0x0F33, 0x04FE, 0x0F31, 0x0504, 0x0F2F, 0x050A,
293    0x0F2D, 0x0510, 0x0F2B, 0x0516, 0x0F29, 0x051C, 0x0F27, 0x0522, 0x0F25, 0x0528, 0x0F23, 0x052E,
294    0x0F21, 0x0534, 0x0F1F, 0x053A, 0x0F1D, 0x0540, 0x0F1B, 0x0546, 0x0F18, 0x054C, 0x0F16, 0x0552,
295    0x0F14, 0x0558, 0x0F12, 0x055D, 0x0F10, 0x0563, 0x0F0E, 0x0569, 0x0F0C, 0x056F, 0x0F0A, 0x0575,
296    0x0F08, 0x057B, 0x0F05, 0x0581, 0x0F03, 0x0587, 0x0F01, 0x058D, 0x0EFF, 0x0593, 0x0EFD, 0x0599,
297    0x0EFA, 0x059E, 0x0EF8, 0x05A4, 0x0EF6, 0x05AA, 0x0EF4, 0x05B0, 0x0EF2, 0x05B6, 0x0EEF, 0x05BC,
298    0x0EED, 0x05C2, 0x0EEB, 0x05C7, 0x0EE8, 0x05CD, 0x0EE6, 0x05D3, 0x0EE4, 0x05D9, 0x0EE2, 0x05DF,
299    0x0EDF, 0x05E5, 0x0EDD, 0x05EB, 0x0EDB, 0x05F0, 0x0ED8, 0x05F6, 0x0ED6, 0x05FC, 0x0ED4, 0x0602,
300    0x0ED1, 0x0608, 0x0ECF, 0x060E, 0x0ECD, 0x0613, 0x0ECA, 0x0619, 0x0EC8, 0x061F, 0x0EC5, 0x0625,
301    0x0EC3, 0x062B, 0x0EC0, 0x0630, 0x0EBE, 0x0636, 0x0EBC, 0x063C, 0x0EB9, 0x0642, 0x0EB7, 0x0648,
302    0x0EB4, 0x064D, 0x0EB2, 0x0653, 0x0EAF, 0x0659, 0x0EAD, 0x065F, 0x0EAA, 0x0664, 0x0EA8, 0x066A,
303    0x0EA5, 0x0670, 0x0EA3, 0x0676, 0x0EA0, 0x067B, 0x0E9E, 0x0681, 0x0E9B, 0x0687, 0x0E98, 0x068D,
304    0x0E96, 0x0692, 0x0E93, 0x0698, 0x0E91, 0x069E, 0x0E8E, 0x06A3, 0x0E8B, 0x06A9, 0x0E89, 0x06AF,
305    0x0E86, 0x06B5, 0x0E84, 0x06BA, 0x0E81, 0x06C0, 0x0E7E, 0x06C6, 0x0E7C, 0x06CB, 0x0E79, 0x06D1,
306    0x0E76, 0x06D7, 0x0E74, 0x06DC, 0x0E71, 0x06E2, 0x0E6E, 0x06E8, 0x0E6B, 0x06ED, 0x0E69, 0x06F3,
307    0x0E66, 0x06F9, 0x0E63, 0x06FE, 0x0E60, 0x0704, 0x0E5E, 0x070A, 0x0E5B, 0x070F, 0x0E58, 0x0715,
308    0x0E55, 0x071B, 0x0E53, 0x0720, 0x0E50, 0x0726, 0x0E4D, 0x072B, 0x0E4A, 0x0731, 0x0E47, 0x0737,
309    0x0E44, 0x073C, 0x0E42, 0x0742, 0x0E3F, 0x0748, 0x0E3C, 0x074D, 0x0E39, 0x0753, 0x0E36, 0x0758,
310    0x0E33, 0x075E, 0x0E30, 0x0763, 0x0E2D, 0x0769, 0x0E2B, 0x076F, 0x0E28, 0x0774, 0x0E25, 0x077A,
311    0x0E22, 0x077F, 0x0E1F, 0x0785, 0x0E1C, 0x078A, 0x0E19, 0x0790, 0x0E16, 0x0795, 0x0E13, 0x079B,
312    0x0E10, 0x07A0, 0x0E0D, 0x07A6, 0x0E0A, 0x07AC, 0x0E07, 0x07B1, 0x0E04, 0x07B7, 0x0E01, 0x07BC,
313    0x0DFE, 0x07C2, 0x0DFB, 0x07C7, 0x0DF8, 0x07CD, 0x0DF5, 0x07D2, 0x0DF2, 0x07D7, 0x0DEE, 0x07DD,
314    0x0DEB, 0x07E2, 0x0DE8, 0x07E8, 0x0DE5, 0x07ED, 0x0DE2, 0x07F3, 0x0DDF, 0x07F8, 0x0DDC, 0x07FE,
315    0x0DD9, 0x0803, 0x0DD5, 0x0809, 0x0DD2, 0x080E, 0x0DCF, 0x0813, 0x0DCC, 0x0819, 0x0DC9, 0x081E,
316    0x0DC6, 0x0824, 0x0DC2, 0x0829, 0x0DBF, 0x082E, 0x0DBC, 0x0834, 0x0DB9, 0x0839, 0x0DB6, 0x083F,
317    0x0DB2, 0x0844, 0x0DAF, 0x0849, 0x0DAC, 0x084F, 0x0DA9, 0x0854, 0x0DA5, 0x085A, 0x0DA2, 0x085F,
318    0x0D9F, 0x0864, 0x0D9B, 0x086A, 0x0D98, 0x086F, 0x0D95, 0x0874, 0x0D91, 0x087A, 0x0D8E, 0x087F,
319    0x0D8B, 0x0884, 0x0D87, 0x088A, 0x0D84, 0x088F, 0x0D81, 0x0894, 0x0D7D, 0x0899, 0x0D7A, 0x089F,
320    0x0D77, 0x08A4, 0x0D73, 0x08A9, 0x0D70, 0x08AF, 0x0D6C, 0x08B4, 0x0D69, 0x08B9, 0x0D65, 0x08BE,
321    0x0D62, 0x08C4, 0x0D5F, 0x08C9, 0x0D5B, 0x08CE, 0x0D58, 0x08D3, 0x0D54, 0x08D9, 0x0D51, 0x08DE,
322    0x0D4D, 0x08E3, 0x0D4A, 0x08E8, 0x0D46, 0x08EE, 0x0D43, 0x08F3, 0x0D3F, 0x08F8, 0x0D3C, 0x08FD,
323    0x0D38, 0x0902, 0x0D35, 0x0908, 0x0D31, 0x090D, 0x0D2D, 0x0912, 0x0D2A, 0x0917, 0x0D26, 0x091C,
324    0x0D23, 0x0921, 0x0D1F, 0x0927, 0x0D1C, 0x092C, 0x0D18, 0x0931, 0x0D14, 0x0936, 0x0D11, 0x093B,
325    0x0D0D, 0x0940, 0x0D09, 0x0945, 0x0D06, 0x094B, 0x0D02, 0x0950, 0x0CFE, 0x0955, 0x0CFB, 0x095A,
326    0x0CF7, 0x095F, 0x0CF3, 0x0964, 0x0CF0, 0x0969, 0x0CEC, 0x096E, 0x0CE8, 0x0973, 0x0CE5, 0x0978,
327    0x0CE1, 0x097D, 0x0CDD, 0x0982, 0x0CD9, 0x0987, 0x0CD6, 0x098D, 0x0CD2, 0x0992, 0x0CCE, 0x0997,
328    0x0CCA, 0x099C, 0x0CC7, 0x09A1, 0x0CC3, 0x09A6, 0x0CBF, 0x09AB, 0x0CBB, 0x09B0, 0x0CB7, 0x09B5,
329    0x0CB4, 0x09BA, 0x0CB0, 0x09BF, 0x0CAC, 0x09C4, 0x0CA8, 0x09C9, 0x0CA4, 0x09CE, 0x0CA0, 0x09D3,
330    0x0C9D, 0x09D7, 0x0C99, 0x09DC, 0x0C95, 0x09E1, 0x0C91, 0x09E6, 0x0C8D, 0x09EB, 0x0C89, 0x09F0,
331    0x0C85, 0x09F5, 0x0C81, 0x09FA, 0x0C7D, 0x09FF, 0x0C79, 0x0A04, 0x0C76, 0x0A09, 0x0C72, 0x0A0E,
332    0x0C6E, 0x0A12, 0x0C6A, 0x0A17, 0x0C66, 0x0A1C, 0x0C62, 0x0A21, 0x0C5E, 0x0A26, 0x0C5A, 0x0A2B,
333    0x0C56, 0x0A30, 0x0C52, 0x0A35, 0x0C4E, 0x0A39, 0x0C4A, 0x0A3E, 0x0C46, 0x0A43, 0x0C42, 0x0A48,
334    0x0C3E, 0x0A4D, 0x0C3A, 0x0A51, 0x0C36, 0x0A56, 0x0C31, 0x0A5B, 0x0C2D, 0x0A60, 0x0C29, 0x0A65,
335    0x0C25, 0x0A69, 0x0C21, 0x0A6E, 0x0C1D, 0x0A73, 0x0C19, 0x0A78, 0x0C15, 0x0A7C, 0x0C11, 0x0A81,
336    0x0C0D, 0x0A86, 0x0C08, 0x0A8B, 0x0C04, 0x0A8F, 0x0C00, 0x0A94, 0x0BFC, 0x0A99, 0x0BF8, 0x0A9D,
337    0x0BF4, 0x0AA2, 0x0BEF, 0x0AA7, 0x0BEB, 0x0AAC, 0x0BE7, 0x0AB0, 0x0BE3, 0x0AB5, 0x0BDF, 0x0ABA,
338    0x0BDA, 0x0ABE, 0x0BD6, 0x0AC3, 0x0BD2, 0x0AC8, 0x0BCE, 0x0ACC, 0x0BCA, 0x0AD1, 0x0BC5, 0x0AD5,
339    0x0BC1, 0x0ADA, 0x0BBD, 0x0ADF, 0x0BB8, 0x0AE3, 0x0BB4, 0x0AE8, 0x0BB0, 0x0AEC, 0x0BAC, 0x0AF1,
340    0x0BA7, 0x0AF6, 0x0BA3, 0x0AFA, 0x0B9F, 0x0AFF, 0x0B9A, 0x0B03, 0x0B96, 0x0B08, 0x0B92, 0x0B0C,
341    0x0B8D, 0x0B11, 0x0B89, 0x0B15, 0x0B85, 0x0B1A, 0x0B80, 0x0B1F, 0x0B7C, 0x0B23, 0x0B78, 0x0B28,
342    0x0B73, 0x0B2C, 0x0B6F, 0x0B31, 0x0B6A, 0x0B35, 0x0B66, 0x0B3A, 0x0B62, 0x0B3E, 0x0B5D, 0x0B42,
343    0x0B59, 0x0B47, 0x0B54, 0x0B4B, 0x0B50, 0x0B50, 0x0B4B, 0x0B54, 0x0B47, 0x0B59, 0x0B42, 0x0B5D,
344    0x0B3E, 0x0B62, 0x0B3A, 0x0B66, 0x0B35, 0x0B6A, 0x0B31, 0x0B6F, 0x0B2C, 0x0B73, 0x0B28, 0x0B78,
345    0x0B23, 0x0B7C, 0x0B1F, 0x0B80, 0x0B1A, 0x0B85, 0x0B15, 0x0B89, 0x0B11, 0x0B8D, 0x0B0C, 0x0B92,
346    0x0B08, 0x0B96, 0x0B03, 0x0B9A, 0x0AFF, 0x0B9F, 0x0AFA, 0x0BA3, 0x0AF6, 0x0BA7, 0x0AF1, 0x0BAC,
347    0x0AEC, 0x0BB0, 0x0AE8, 0x0BB4, 0x0AE3, 0x0BB8, 0x0ADF, 0x0BBD, 0x0ADA, 0x0BC1, 0x0AD5, 0x0BC5,
348    0x0AD1, 0x0BCA, 0x0ACC, 0x0BCE, 0x0AC8, 0x0BD2, 0x0AC3, 0x0BD6, 0x0ABE, 0x0BDA, 0x0ABA, 0x0BDF,
349    0x0AB5, 0x0BE3, 0x0AB0, 0x0BE7, 0x0AAC, 0x0BEB, 0x0AA7, 0x0BEF, 0x0AA2, 0x0BF4, 0x0A9D, 0x0BF8,
350    0x0A99, 0x0BFC, 0x0A94, 0x0C00, 0x0A8F, 0x0C04, 0x0A8B, 0x0C08, 0x0A86, 0x0C0D, 0x0A81, 0x0C11,
351    0x0A7C, 0x0C15, 0x0A78, 0x0C19, 0x0A73, 0x0C1D, 0x0A6E, 0x0C21, 0x0A69, 0x0C25, 0x0A65, 0x0C29,
352    0x0A60, 0x0C2D, 0x0A5B, 0x0C31, 0x0A56, 0x0C36, 0x0A51, 0x0C3A, 0x0A4D, 0x0C3E, 0x0A48, 0x0C42,
353    0x0A43, 0x0C46, 0x0A3E, 0x0C4A, 0x0A39, 0x0C4E, 0x0A35, 0x0C52, 0x0A30, 0x0C56, 0x0A2B, 0x0C5A,
354    0x0A26, 0x0C5E, 0x0A21, 0x0C62, 0x0A1C, 0x0C66, 0x0A17, 0x0C6A, 0x0A12, 0x0C6E, 0x0A0E, 0x0C72,
355    0x0A09, 0x0C76, 0x0A04, 0x0C79, 0x09FF, 0x0C7D, 0x09FA, 0x0C81, 0x09F5, 0x0C85, 0x09F0, 0x0C89,
356    0x09EB, 0x0C8D, 0x09E6, 0x0C91, 0x09E1, 0x0C95, 0x09DC, 0x0C99, 0x09D7, 0x0C9D, 0x09D3, 0x0CA0,
357    0x09CE, 0x0CA4, 0x09C9, 0x0CA8, 0x09C4, 0x0CAC, 0x09BF, 0x0CB0, 0x09BA, 0x0CB4, 0x09B5, 0x0CB7,
358    0x09B0, 0x0CBB, 0x09AB, 0x0CBF, 0x09A6, 0x0CC3, 0x09A1, 0x0CC7, 0x099C, 0x0CCA, 0x0997, 0x0CCE,
359    0x0992, 0x0CD2, 0x098D, 0x0CD6, 0x0987, 0x0CD9, 0x0982, 0x0CDD, 0x097D, 0x0CE1, 0x0978, 0x0CE5,
360    0x0973, 0x0CE8, 0x096E, 0x0CEC, 0x0969, 0x0CF0, 0x0964, 0x0CF3, 0x095F, 0x0CF7, 0x095A, 0x0CFB,
361    0x0955, 0x0CFE, 0x0950, 0x0D02, 0x094B, 0x0D06, 0x0945, 0x0D09, 0x0940, 0x0D0D, 0x093B, 0x0D11,
362    0x0936, 0x0D14, 0x0931, 0x0D18, 0x092C, 0x0D1C, 0x0927, 0x0D1F, 0x0921, 0x0D23, 0x091C, 0x0D26,
363    0x0917, 0x0D2A, 0x0912, 0x0D2D, 0x090D, 0x0D31, 0x0908, 0x0D35, 0x0902, 0x0D38, 0x08FD, 0x0D3C,
364    0x08F8, 0x0D3F, 0x08F3, 0x0D43, 0x08EE, 0x0D46, 0x08E8, 0x0D4A, 0x08E3, 0x0D4D, 0x08DE, 0x0D51,
365    0x08D9, 0x0D54, 0x08D3, 0x0D58, 0x08CE, 0x0D5B, 0x08C9, 0x0D5F, 0x08C4, 0x0D62, 0x08BE, 0x0D65,
366    0x08B9, 0x0D69, 0x08B4, 0x0D6C, 0x08AF, 0x0D70, 0x08A9, 0x0D73, 0x08A4, 0x0D77, 0x089F, 0x0D7A,
367    0x0899, 0x0D7D, 0x0894, 0x0D81, 0x088F, 0x0D84, 0x088A, 0x0D87, 0x0884, 0x0D8B, 0x087F, 0x0D8E,
368    0x087A, 0x0D91, 0x0874, 0x0D95, 0x086F, 0x0D98, 0x086A, 0x0D9B, 0x0864, 0x0D9F, 0x085F, 0x0DA2,
369    0x085A, 0x0DA5, 0x0854, 0x0DA9, 0x084F, 0x0DAC, 0x0849, 0x0DAF, 0x0844, 0x0DB2, 0x083F, 0x0DB6,
370    0x0839, 0x0DB9, 0x0834, 0x0DBC, 0x082E, 0x0DBF, 0x0829, 0x0DC2, 0x0824, 0x0DC6, 0x081E, 0x0DC9,
371    0x0819, 0x0DCC, 0x0813, 0x0DCF, 0x080E, 0x0DD2, 0x0809, 0x0DD5, 0x0803, 0x0DD9, 0x07FE, 0x0DDC,
372    0x07F8, 0x0DDF, 0x07F3, 0x0DE2, 0x07ED, 0x0DE5, 0x07E8, 0x0DE8, 0x07E2, 0x0DEB, 0x07DD, 0x0DEE,
373    0x07D7, 0x0DF2, 0x07D2, 0x0DF5, 0x07CD, 0x0DF8, 0x07C7, 0x0DFB, 0x07C2, 0x0DFE, 0x07BC, 0x0E01,
374    0x07B7, 0x0E04, 0x07B1, 0x0E07, 0x07AC, 0x0E0A, 0x07A6, 0x0E0D, 0x07A0, 0x0E10, 0x079B, 0x0E13,
375    0x0795, 0x0E16, 0x0790, 0x0E19, 0x078A, 0x0E1C, 0x0785, 0x0E1F, 0x077F, 0x0E22, 0x077A, 0x0E25,
376    0x0774, 0x0E28, 0x076F, 0x0E2B, 0x0769, 0x0E2D, 0x0763, 0x0E30, 0x075E, 0x0E33, 0x0758, 0x0E36,
377    0x0753, 0x0E39, 0x074D, 0x0E3C, 0x0748, 0x0E3F, 0x0742, 0x0E42, 0x073C, 0x0E44, 0x0737, 0x0E47,
378    0x0731, 0x0E4A, 0x072B, 0x0E4D, 0x0726, 0x0E50, 0x0720, 0x0E53, 0x071B, 0x0E55, 0x0715, 0x0E58,
379    0x070F, 0x0E5B, 0x070A, 0x0E5E, 0x0704, 0x0E60, 0x06FE, 0x0E63, 0x06F9, 0x0E66, 0x06F3, 0x0E69,
380    0x06ED, 0x0E6B, 0x06E8, 0x0E6E, 0x06E2, 0x0E71, 0x06DC, 0x0E74, 0x06D7, 0x0E76, 0x06D1, 0x0E79,
381    0x06CB, 0x0E7C, 0x06C6, 0x0E7E, 0x06C0, 0x0E81, 0x06BA, 0x0E84, 0x06B5, 0x0E86, 0x06AF, 0x0E89,
382    0x06A9, 0x0E8B, 0x06A3, 0x0E8E, 0x069E, 0x0E91, 0x0698, 0x0E93, 0x0692, 0x0E96, 0x068D, 0x0E98,
383    0x0687, 0x0E9B, 0x0681, 0x0E9E, 0x067B, 0x0EA0, 0x0676, 0x0EA3, 0x0670, 0x0EA5, 0x066A, 0x0EA8,
384    0x0664, 0x0EAA, 0x065F, 0x0EAD, 0x0659, 0x0EAF, 0x0653, 0x0EB2, 0x064D, 0x0EB4, 0x0648, 0x0EB7,
385    0x0642, 0x0EB9, 0x063C, 0x0EBC, 0x0636, 0x0EBE, 0x0630, 0x0EC0, 0x062B, 0x0EC3, 0x0625, 0x0EC5,
386    0x061F, 0x0EC8, 0x0619, 0x0ECA, 0x0613, 0x0ECD, 0x060E, 0x0ECF, 0x0608, 0x0ED1, 0x0602, 0x0ED4,
387    0x05FC, 0x0ED6, 0x05F6, 0x0ED8, 0x05F0, 0x0EDB, 0x05EB, 0x0EDD, 0x05E5, 0x0EDF, 0x05DF, 0x0EE2,
388    0x05D9, 0x0EE4, 0x05D3, 0x0EE6, 0x05CD, 0x0EE8, 0x05C7, 0x0EEB, 0x05C2, 0x0EED, 0x05BC, 0x0EEF,
389    0x05B6, 0x0EF2, 0x05B0, 0x0EF4, 0x05AA, 0x0EF6, 0x05A4, 0x0EF8, 0x059E, 0x0EFA, 0x0599, 0x0EFD,
390    0x0593, 0x0EFF, 0x058D, 0x0F01, 0x0587, 0x0F03, 0x0581, 0x0F05, 0x057B, 0x0F08, 0x0575, 0x0F0A,
391    0x056F, 0x0F0C, 0x0569, 0x0F0E, 0x0563, 0x0F10, 0x055D, 0x0F12, 0x0558, 0x0F14, 0x0552, 0x0F16,
392    0x054C, 0x0F18, 0x0546, 0x0F1B, 0x0540, 0x0F1D, 0x053A, 0x0F1F, 0x0534, 0x0F21, 0x052E, 0x0F23,
393    0x0528, 0x0F25, 0x0522, 0x0F27, 0x051C, 0x0F29, 0x0516, 0x0F2B, 0x0510, 0x0F2D, 0x050A, 0x0F2F,
394    0x0504, 0x0F31, 0x04FE, 0x0F33, 0x04F8, 0x0F35, 0x04F2, 0x0F37, 0x04EC, 0x0F39, 0x04E6, 0x0F3B,
395    0x04E0, 0x0F3C, 0x04DB, 0x0F3E, 0x04D5, 0x0F40, 0x04CF, 0x0F42, 0x04C9, 0x0F44, 0x04C3, 0x0F46,
396    0x04BD, 0x0F48, 0x04B7, 0x0F4A, 0x04B1, 0x0F4B, 0x04AB, 0x0F4D, 0x04A5, 0x0F4F, 0x049E, 0x0F51,
397    0x0498, 0x0F53, 0x0492, 0x0F55, 0x048C, 0x0F56, 0x0486, 0x0F58, 0x0480, 0x0F5A, 0x047A, 0x0F5C,
398    0x0474, 0x0F5D, 0x046E, 0x0F5F, 0x0468, 0x0F61, 0x0462, 0x0F63, 0x045C, 0x0F64, 0x0456, 0x0F66,
399    0x0450, 0x0F68, 0x044A, 0x0F69, 0x0444, 0x0F6B, 0x043E, 0x0F6D, 0x0438, 0x0F6E, 0x0432, 0x0F70,
400    0x042C, 0x0F72, 0x0426, 0x0F73, 0x0420, 0x0F75, 0x041A, 0x0F77, 0x0413, 0x0F78, 0x040D, 0x0F7A,
401    0x0407, 0x0F7B, 0x0401, 0x0F7D, 0x03FB, 0x0F7F, 0x03F5, 0x0F80, 0x03EF, 0x0F82, 0x03E9, 0x0F83,
402    0x03E3, 0x0F85, 0x03DD, 0x0F86, 0x03D7, 0x0F88, 0x03D0, 0x0F89, 0x03CA, 0x0F8B, 0x03C4, 0x0F8C,
403    0x03BE, 0x0F8E, 0x03B8, 0x0F8F, 0x03B2, 0x0F91, 0x03AC, 0x0F92, 0x03A6, 0x0F94, 0x03A0, 0x0F95,
404    0x0399, 0x0F96, 0x0393, 0x0F98, 0x038D, 0x0F99, 0x0387, 0x0F9B, 0x0381, 0x0F9C, 0x037B, 0x0F9D,
405    0x0375, 0x0F9F, 0x036F, 0x0FA0, 0x0368, 0x0FA1, 0x0362, 0x0FA3, 0x035C, 0x0FA4, 0x0356, 0x0FA5,
406    0x0350, 0x0FA7, 0x034A, 0x0FA8, 0x0344, 0x0FA9, 0x033D, 0x0FAB, 0x0337, 0x0FAC, 0x0331, 0x0FAD,
407    0x032B, 0x0FAE, 0x0325, 0x0FB0, 0x031F, 0x0FB1, 0x0318, 0x0FB2, 0x0312, 0x0FB3, 0x030C, 0x0FB4,
408    0x0306, 0x0FB6, 0x0300, 0x0FB7, 0x02FA, 0x0FB8, 0x02F3, 0x0FB9, 0x02ED, 0x0FBA, 0x02E7, 0x0FBB,
409    0x02E1, 0x0FBD, 0x02DB, 0x0FBE, 0x02D5, 0x0FBF, 0x02CE, 0x0FC0, 0x02C8, 0x0FC1, 0x02C2, 0x0FC2,
410    0x02BC, 0x0FC3, 0x02B6, 0x0FC4, 0x02AF, 0x0FC5, 0x02A9, 0x0FC6, 0x02A3, 0x0FC7, 0x029D, 0x0FC8,
411    0x0297, 0x0FC9, 0x0290, 0x0FCA, 0x028A, 0x0FCB, 0x0284, 0x0FCC, 0x027E, 0x0FCD, 0x0278, 0x0FCE,
412    0x0271, 0x0FCF, 0x026B, 0x0FD0, 0x0265, 0x0FD1, 0x025F, 0x0FD2, 0x0259, 0x0FD3, 0x0252, 0x0FD4,
413    0x024C, 0x0FD5, 0x0246, 0x0FD6, 0x0240, 0x0FD7, 0x0239, 0x0FD8, 0x0233, 0x0FD9, 0x022D, 0x0FD9,
414    0x0227, 0x0FDA, 0x0221, 0x0FDB, 0x021A, 0x0FDC, 0x0214, 0x0FDD, 0x020E, 0x0FDE, 0x0208, 0x0FDE,
415    0x0201, 0x0FDF, 0x01FB, 0x0FE0, 0x01F5, 0x0FE1, 0x01EF, 0x0FE1, 0x01E8, 0x0FE2, 0x01E2, 0x0FE3,
416    0x01DC, 0x0FE4, 0x01D6, 0x0FE4, 0x01CF, 0x0FE5, 0x01C9, 0x0FE6, 0x01C3, 0x0FE7, 0x01BD, 0x0FE7,
417    0x01B6, 0x0FE8, 0x01B0, 0x0FE9, 0x01AA, 0x0FE9, 0x01A4, 0x0FEA, 0x019D, 0x0FEB, 0x0197, 0x0FEB,
418    0x0191, 0x0FEC, 0x018B, 0x0FEC, 0x0184, 0x0FED, 0x017E, 0x0FEE, 0x0178, 0x0FEE, 0x0172, 0x0FEF,
419    0x016B, 0x0FEF, 0x0165, 0x0FF0, 0x015F, 0x0FF0, 0x0159, 0x0FF1, 0x0152, 0x0FF1, 0x014C, 0x0FF2,
420    0x0146, 0x0FF2, 0x0140, 0x0FF3, 0x0139, 0x0FF3, 0x0133, 0x0FF4, 0x012D, 0x0FF4, 0x0127, 0x0FF5,
421    0x0120, 0x0FF5, 0x011A, 0x0FF6, 0x0114, 0x0FF6, 0x010D, 0x0FF7, 0x0107, 0x0FF7, 0x0101, 0x0FF7,
422    0x00FB, 0x0FF8, 0x00F4, 0x0FF8, 0x00EE, 0x0FF9, 0x00E8, 0x0FF9, 0x00E2, 0x0FF9, 0x00DB, 0x0FFA,
423    0x00D5, 0x0FFA, 0x00CF, 0x0FFA, 0x00C8, 0x0FFB, 0x00C2, 0x0FFB, 0x00BC, 0x0FFB, 0x00B6, 0x0FFB,
424    0x00AF, 0x0FFC, 0x00A9, 0x0FFC, 0x00A3, 0x0FFC, 0x009D, 0x0FFC, 0x0096, 0x0FFD, 0x0090, 0x0FFD,
425    0x008A, 0x0FFD, 0x0083, 0x0FFD, 0x007D, 0x0FFE, 0x0077, 0x0FFE, 0x0071, 0x0FFE, 0x006A, 0x0FFE,
426    0x0064, 0x0FFE, 0x005E, 0x0FFE, 0x0057, 0x0FFF, 0x0051, 0x0FFF, 0x004B, 0x0FFF, 0x0045, 0x0FFF,
427    0x003E, 0x0FFF, 0x0038, 0x0FFF, 0x0032, 0x0FFF, 0x002B, 0x0FFF, 0x0025, 0x0FFF, 0x001F, 0x0FFF,
428    0x0019, 0x0FFF, 0x0012, 0x0FFF, 0x000C, 0x0FFF, 0x0006, 0x0FFF,
429];
430
431lazy_static::lazy_static! {
432    static ref WORD_6A56C8: Vec<i16> = init_table();
433}
434
435fn init_table() -> Vec<i16> {
436    let mut table = Vec::with_capacity(0x10000);
437    let mut cx: i16 = 0;
438    let mut dx: i16 = 0;
439    for _ in 0..0x8000 {
440        table.push(dx);
441        wrapping! {
442            dx -= 1;
443            cx += 1;
444        }
445        table.push(cx);
446    }
447    table
448}
449
450struct PcmDecoder {
451    pcm_data: Vec<u8>,
452    encoded: MemReader,
453    pcm_size: usize,
454    extra: u32,
455    dword_43a214: Vec<i32>,
456    unk_6a16c8: Vec<u8>,
457    /// dword_6996C8
458    a2: Vec<i32>,
459    /// dword_69D6C8
460    a3: Vec<i32>,
461}
462
463impl PcmDecoder {
464    pub fn new<R: Read + Seek>(
465        mut input: R,
466        pcm_size: usize,
467        extra: u32,
468        mode: Mode,
469    ) -> Result<Self> {
470        if extra > 4 {
471            return Err(anyhow::anyhow!("Unsupported PCM extra: {}", extra));
472        }
473        let packed_size = input.read_u32()?;
474        let pcm_data = vec![0u8; pcm_size + 8192];
475        let encoded = match mode {
476            Mode::Lzss => {
477                let mut data = vec![0u8; packed_size as usize];
478                input.read_exact(&mut data)?;
479                Self::unpack_v1(&data)?
480            }
481            Mode::Zlib => {
482                let mut decoder = flate2::read::ZlibDecoder::new(input);
483                let mut data = Vec::new();
484                decoder.read_to_end(&mut data)?;
485                data
486            }
487            _ => return Err(anyhow::anyhow!("Unsupported PCM mode: {:?}", mode)),
488        };
489        Ok(Self {
490            pcm_data,
491            encoded: MemReader::new(encoded),
492            pcm_size,
493            extra,
494            dword_43a214: vec![0; 0x10],
495            unk_6a16c8: vec![0; 0x2000],
496            a2: vec![0; 0x1000],
497            a3: vec![0; 0x1000],
498        })
499    }
500
501    pub fn unpack(mut self) -> Result<Vec<u8>> {
502        let mut reader = MemReaderRef::new(&UNK_43A254);
503        reader.pos = self.extra as usize * 0x40;
504        for i in 0..0x10 {
505            self.dword_43a214[i] = reader.read_i32()?;
506        }
507        self.decode_v1()?;
508        self.pcm_data.truncate(self.pcm_size);
509        Ok(self.pcm_data)
510    }
511
512    fn decode_v1(&mut self) -> Result<()> {
513        let v14 = self.pcm_size / 2;
514        let mut v5 = 0;
515        let mut decoded = 0;
516        let mut dst_sizea = 0;
517        while dst_sizea < v14 {
518            self.sub_4121c0(v5)?;
519            v5 += 8192;
520            self.sub_411ab0(12);
521            let mut v6 = decoded;
522            let mut v7 = 0;
523            let mut v8 = 0;
524            let mut v9 = 32;
525            while v9 > -4064 {
526                if v7 + dst_sizea < v14 {
527                    let mut v11;
528                    if v9 > 0 && dst_sizea != 0 {
529                        let v10 = (v7 as i64).wrapping_mul(self.a2[v8] as u32 as i64)
530                            + (v9 as i64).wrapping_mul(i16::from_le_bytes([
531                                self.pcm_data[v6],
532                                self.pcm_data[v6 + 1],
533                            ]) as i64);
534                        v11 = (((v10 >> 32) & 0x1F) as i32 + v10 as i32) >> 5;
535                    } else {
536                        v11 = self.a2[v8];
537                    }
538                    if v11 > 32767 {
539                        v11 = 32767;
540                    } else if v11 < -32768 {
541                        v11 = -32768;
542                    }
543                    let data = (v11 as i16).to_le_bytes();
544                    self.pcm_data[v6] = data[0];
545                    self.pcm_data[v6 + 1] = data[1];
546                }
547                v7 += 1;
548                v6 += 2;
549                v8 += 1;
550                v9 -= 1;
551            }
552            decoded += 8128;
553            dst_sizea += 4064;
554        }
555        Ok(())
556    }
557
558    fn sub_4121c0(&mut self, a1: usize) -> Result<()> {
559        let mut v1 = a1;
560        let mut v5 = 1;
561        for _ in 0..0x1000 {
562            self.unk_6a16c8[v5] = self.encoded.cpeek_u8_at(v1 as u64)?;
563            v1 += 1;
564            v5 += 2;
565        }
566        v5 = 0;
567        for _ in 0..0x800 {
568            let v7 = self.encoded.cpeek_u8_at(v1 as u64 + 0x800)?;
569            let v8 = self.encoded.cpeek_u8_at(v1 as u64)?;
570            self.unk_6a16c8[v5] = (v7 >> 4) | (v8 & 0xF0);
571            self.unk_6a16c8[v5 + 2] = (v8 << 4) | (v7 & 0x0F);
572            v5 += 4;
573            v1 += 1;
574        }
575        let mut v9 = 0;
576        v5 = 0;
577        for v11_chunk in (0..32768).step_by(16) {
578            let result = self.dword_43a214[v11_chunk / 0x1000];
579            let i1 = u16::from_le_bytes([self.unk_6a16c8[v5], self.unk_6a16c8[v5 + 1]]) as usize;
580            let i2 =
581                u16::from_le_bytes([self.unk_6a16c8[v5 + 2], self.unk_6a16c8[v5 + 3]]) as usize;
582            self.a2[v9] = result.wrapping_mul(WORD_6A56C8[i1] as i32);
583            self.a3[v9] = result.wrapping_mul(WORD_6A56C8[i2] as i32);
584            v9 += 1;
585            v5 += 4;
586        }
587        for i in v9..4096 {
588            self.a2[i] = 0;
589            self.a3[i] = 0;
590        }
591        Ok(())
592    }
593
594    fn sub_411ab0(&mut self, a1: i32) {
595        let mut v4 = 1 << a1;
596        let mut v5 = 1;
597        let mut v68 = 1;
598        let mut v6 = 1 << a1;
599        let v79 = 1 << a1;
600        if a1 >= 3 {
601            let mut v7 = v4 >> 1;
602            let mut v59 = a1 - 2;
603            loop {
604                let v63 = v4;
605                let v82 = DWORD_43A358[v5 as usize * 2];
606                let v66 = v7;
607                let mut v8 = v7 >> 1;
608                let v62 = v7 >> 1;
609                let v80 = DWORD_43A358[1 + 2 * v5 as usize];
610                let mut v77 = 0;
611                if v6 > 0 {
612                    let mut v73 = 0;
613                    let mut v69 = v8;
614                    let mut v75 = v7;
615                    let v9 = v8 + 1;
616                    let v10 = v7 + v8;
617                    let mut v64 = v9;
618                    let mut v11 = 1;
619                    let mut v12 = v10 + 1;
620                    let mut v71 = v10;
621                    let mut v13 = v7 + 1;
622                    loop {
623                        let v14 = self.a2[v75 as usize];
624                        let v15 = self.a2[v73 as usize];
625                        let v16 = self.a3[v11 as usize - 1] - self.a3[v13 as usize - 1];
626                        self.a2[v73 as usize] += self.a2[v75 as usize];
627                        self.a3[v11 as usize - 1] += self.a3[v13 as usize - 1];
628                        self.a2[v75 as usize] = v15 - v14;
629                        self.a3[v13 as usize - 1] = v16;
630                        let v17 = self.a2[v13 as usize];
631                        let v18 = self.a2[v11 as usize] - v17;
632                        let v19 = self.a3[v11 as usize] - self.a3[v13 as usize];
633                        self.a2[v11 as usize] += v17;
634                        self.a3[v11 as usize] += self.a3[v13 as usize];
635                        self.a2[v13 as usize] = (((v18 as i64).wrapping_mul(v82 as i64) as u64
636                            >> 12)
637                            + ((v19 as i64).wrapping_mul(v80 as i64) as u64 >> 12))
638                            as i32;
639                        let pv = (v19 as i64).wrapping_mul(v82 as i64) as u64 >> 12;
640                        let nv = (v18 as i64).wrapping_mul(v80 as i64) as u64 >> 12;
641                        self.a3[v13 as usize] = pv.wrapping_sub(nv) as i32;
642                        let v20 = self.a2[v69 as usize] - self.a2[v71 as usize];
643                        let v21 = v64;
644                        let v22 = self.a3[v64 as usize - 1] - self.a3[v12 as usize - 1];
645                        self.a2[v69 as usize] += self.a2[v71 as usize];
646                        self.a3[v21 as usize - 1] += self.a3[v12 as usize - 1];
647                        self.a2[v71 as usize] = v22;
648                        self.a3[v12 as usize - 1] = -v20;
649                        let v23 = self.a2[v12 as usize];
650                        let v24 = self.a2[v64 as usize] - v23;
651                        let v25 = self.a3[v64 as usize] - self.a3[v12 as usize];
652                        self.a2[v21 as usize] += v23;
653                        self.a3[v21 as usize] += self.a3[v12 as usize];
654                        let pv = (v25 as i64).wrapping_mul(v82 as i64) as u64 >> 12;
655                        let nv = (v24 as i64).wrapping_mul(v80 as i64) as u64 >> 12;
656                        self.a2[v12 as usize] = pv.wrapping_sub(nv) as i32;
657                        self.a3[v12 as usize] = (-((((v24 as i64).wrapping_mul(v82 as i64) as u64
658                            >> 12)
659                            + ((v25 as i64).wrapping_mul(v80 as i64) as u64 >> 12))
660                            as i64)) as i32;
661                        v13 += v63;
662                        v75 += v63;
663                        v11 += v63;
664                        v73 += v63;
665                        v12 += v63;
666                        v71 += v63;
667                        v77 += v63;
668                        v69 += v63;
669                        v64 += v63;
670                        if v77 >= v79 {
671                            break;
672                        }
673                    }
674                    v8 = v62;
675                    v5 = v68;
676                    v7 = v66;
677                    v6 = 1 << a1;
678                }
679                if v8 > 2 {
680                    let mut v70 = 2;
681                    let mut v72 = v7 + 2;
682                    let mut v74 = v8 + 2;
683                    let mut v27 = 1 + 4 * v5;
684                    let mut v60 = v8 - 2;
685                    let mut v76 = v8 + 2 + v7;
686                    loop {
687                        let v83 = DWORD_43A358[v27 as usize - 1];
688                        let v81 = DWORD_43A358[v27 as usize];
689                        let mut v78 = 0;
690                        if v6 > 0 {
691                            let mut v28 = v70;
692                            let mut v29 = v72;
693                            let mut v65 = v74;
694                            let mut v85 = v76;
695                            loop {
696                                let v31 = self.a2[v29 as usize];
697                                let v32 = self.a2[v28 as usize] - v31;
698                                let v33 = self.a3[v28 as usize] - self.a3[v29 as usize];
699                                self.a2[v28 as usize] += v31;
700                                self.a3[v28 as usize] += self.a3[v29 as usize];
701                                self.a2[v29 as usize] =
702                                    (((v32 as i64).wrapping_mul(v83 as i64) as u64 >> 12)
703                                        + ((v33 as i64).wrapping_mul(v81 as i64) as u64 >> 12))
704                                        as i32;
705                                let pv = (v33 as i64).wrapping_mul(v83 as i64) as u64 >> 12;
706                                let nv = (v32 as i64).wrapping_mul(v81 as i64) as u64 >> 12;
707                                self.a3[v29 as usize] = pv.wrapping_sub(nv) as i32;
708                                let v34 = self.a2[v65 as usize] - self.a2[v85 as usize];
709                                let v35 = self.a3[v65 as usize] - self.a3[v85 as usize];
710                                self.a2[v65 as usize] += self.a2[v85 as usize];
711                                self.a3[v65 as usize] += self.a3[v85 as usize];
712                                let pv = (v35 as i64).wrapping_mul(v83 as i64) as u64 >> 12;
713                                let nv = (v34 as i64).wrapping_mul(v81 as i64) as u64 >> 12;
714                                self.a2[v85 as usize] = pv.wrapping_sub(nv) as i32;
715                                self.a3[v85 as usize] =
716                                    (-((((v34 as i64).wrapping_mul(v83 as i64) as u64 >> 12)
717                                        + ((v35 as i64).wrapping_mul(v81 as i64) as u64 >> 12))
718                                        as i64)) as i32;
719                                v29 += v63;
720                                v85 += v63;
721                                v28 += v63;
722                                v65 += v63;
723                                v78 += v63;
724                                if v78 >= v79 {
725                                    break;
726                                }
727                            }
728                            v5 = v68;
729                            v6 = 1 << a1;
730                        }
731                        v27 += 2 * v5;
732                        v70 += 1;
733                        v72 += 1;
734                        v74 += 1;
735                        v76 += 1;
736                        v60 -= 1;
737                        if v60 == 0 {
738                            break;
739                        }
740                    }
741                }
742                v68 = 2 * v5;
743                v59 -= 1;
744                if v59 == 0 {
745                    break;
746                }
747                v7 = v62;
748                v5 *= 2;
749                v4 = v66;
750            }
751        }
752        if !(a1 < 2 || v6 <= 0) {
753            let mut v37 = 1;
754            let mut v38 = 3;
755            let mut v88 = (v6 as u32 + 3) >> 2;
756            loop {
757                let v39 = self.a2[v37 as usize - 1];
758                let v40 = self.a2[v37 as usize + 1];
759                let v41 = self.a3[v38 as usize - 3] - self.a3[v38 as usize - 1];
760                self.a2[v37 as usize - 1] = v40 + v39;
761                v37 += 4;
762                self.a3[v38 as usize - 3] += self.a3[v38 as usize - 1];
763                self.a2[v37 as usize - 3] = v39 - v40;
764                self.a3[v38 as usize - 1] = v41;
765                let v42 = self.a2[v38 as usize];
766                let v43 = self.a3[v38 as usize - 2] - self.a3[v38 as usize];
767                v38 += 4;
768                let v44 = self.a2[v37 as usize - 4] - v42;
769                self.a2[v37 as usize - 4] += v42;
770                self.a3[v38 as usize - 6] += self.a3[v38 as usize - 4];
771                self.a2[v38 as usize - 4] = v43;
772                self.a3[v38 as usize - 4] = -v44;
773                v88 -= 1;
774                if v88 == 0 {
775                    break;
776                }
777            }
778            v6 = v79;
779        }
780        let mut v45 = 0;
781        if v6 > 0 {
782            let mut v47 = 1;
783            let mut v89 = (v79 as u32 + 1) >> 1;
784            loop {
785                let v48 = self.a2[v47 as usize];
786                let v49 = self.a3[v47 as usize - 1] - self.a3[v47 as usize];
787                let v50 = self.a2[v45 as usize] - v48;
788                v47 += 2;
789                self.a2[v45 as usize] += v48;
790                v45 += 2;
791                self.a3[v47 as usize - 3] += self.a3[v47 as usize - 2];
792                self.a2[v47 as usize - 2] = v50;
793                self.a3[v47 as usize - 2] = v49;
794                v89 -= 1;
795                if v89 == 0 {
796                    break;
797                }
798            }
799            v45 = 0;
800            v6 = v79;
801        }
802        let mut v51 = 0;
803        let mut result = v6 / 2;
804        let v67 = v6 / 2;
805        let mut v90 = 1;
806        if v6 - 1 > 1 {
807            let mut v54 = 1;
808            loop {
809                while result <= v51 {
810                    v51 -= result;
811                    result /= 2;
812                }
813                v51 += result;
814                if v90 < v51 {
815                    self.a2.swap((v45 + v51) as usize, v54 as usize);
816                    self.a3.swap(v51 as usize, v54 as usize);
817                }
818                v54 += 1;
819                v90 += 1;
820                if v90 >= v79 - 1 {
821                    break;
822                }
823                result = v67;
824            }
825            v6 = v79;
826        }
827        while v6 > 0 {
828            let eax = self.a2[v45] << 4;
829            let edx = if eax < 0 { 0x3FFF } else { 0 };
830            self.a2[v45] = eax.wrapping_add(edx) >> 14;
831            v45 += 1;
832            v6 -= 1;
833        }
834    }
835
836    fn unpack_v1(input: &[u8]) -> Result<Vec<u8>> {
837        let packed_size = input.len();
838        let mut flag = 0;
839        let mut src = 0;
840        let mut output = Vec::new();
841        while src < packed_size {
842            flag >>= 1;
843            if (flag & 0x100) == 0 {
844                flag = input[src] as u32 | 0xFF00;
845                src += 1;
846            }
847            if (flag & 1) != 0 {
848                output.push(input[src]);
849                src += 1;
850            } else {
851                if src >= packed_size {
852                    break;
853                }
854                let mut offset;
855                let count;
856                let ctl = input[src] as u32;
857                src += 1;
858                if ctl >= 0xc0 {
859                    offset = input[src] as usize | (((ctl & 3) << 8) as usize);
860                    src += 1;
861                    count = 4 + ((ctl >> 2) & 0xF) as usize;
862                } else if ctl & 0x80 != 0 {
863                    offset = (ctl & 0x1F) as usize;
864                    count = (2 + ((ctl >> 5) & 3)) as usize;
865                    if offset == 0 {
866                        offset = input[src] as usize;
867                        src += 1;
868                    }
869                } else if ctl == 0x7F {
870                    count = (2 + u16::from_le_bytes([input[src], input[src + 1]])) as usize;
871                    offset = u16::from_le_bytes([input[src + 2], input[src + 3]]) as usize;
872                    src += 4;
873                } else {
874                    offset = u16::from_le_bytes([input[src], input[src + 1]]) as usize;
875                    src += 2;
876                    count = (ctl + 4) as usize;
877                }
878                let dst = output.len();
879                let copy_src = dst - offset;
880                for i in 0..count {
881                    output.push(output[copy_src + i]);
882                }
883            }
884        }
885        Ok(output)
886    }
887}