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