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