rpfm_lib/files/sound_bank/
mod.rs1use getset::*;
28use serde_derive::{Serialize, Deserialize};
29
30use crate::binary::{ReadBytes, WriteBytes};
31use crate::error::{Result, RLibError};
32use crate::files::{Decodeable, EncodeableExtraData, Encodeable};
33use crate::utils::check_size_mismatch;
34
35use self::sections::bkhd::BKHD;
36use self::sections::hirc::HIRC;
37
38use super::DecodeableExtraData;
39
40pub const EXTENSION: &str = ".bnk";
42
43const FNV_NO: &str = "none"; const FNV_BNK: &str = "bank";
46const FNV_LNG: &str = "language";
47const FNV_EVT: &str = "event";
48const FNV_BUS: &str = "bus";
49const FNV_SFX: &str = "sfx";
50const FNV_TRG: &str = "trigger";
51const FNV_GME: &str = "rtpc/game-variable";
52const FNV_VAR: &str = "variable"; const FNV_VAL: &str = "value"; const FNV_UNK: &str = "???";
55
56const FNV_ORDER: [&str; 10] = [
57 FNV_BNK, FNV_LNG, FNV_EVT, FNV_BUS, FNV_SFX, FNV_TRG, FNV_GME, FNV_VAR, FNV_VAL, FNV_UNK
58];
59
60const FNV_ORDER_JOIN: [&str; 3] = [
61 FNV_BNK, FNV_LNG, FNV_BUS
62];
63
64const SIGNATURE_AKBK: &str = "AKBK"; const SIGNATURE_BKHD: &str = "BKHD"; const SIGNATURE_HIRC: &str = "HIRC"; const SIGNATURE_DATA: &str = "DATA"; const SIGNATURE_FXPR: &str = "FXPR"; const SIGNATURE_ENVS: &str = "ENVS"; const SIGNATURE_STID: &str = "STID"; const SIGNATURE_STMG: &str = "STMG"; const SIGNATURE_DIDX: &str = "DIDX"; const SIGNATURE_PLAT: &str = "PLAT"; const SIGNATURE_INIT: &str = "INIT"; mod common;
78mod sections;
79
80#[cfg(test)] mod test_soundbank;
81
82#[derive(Default, PartialEq, Clone, Debug, Getters, MutGetters, Setters, Serialize, Deserialize)]
94#[getset(get = "pub", get_mut = "pub", set = "pub")]
95pub struct SoundBank {
96 sections: Vec<Section>,
98}
99
100#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
106pub enum Section {
107 BKHD(BKHD),
109 HIRC(HIRC),
111}
112
113impl Decodeable for SoundBank {
118
119 fn decode<R: ReadBytes>(data: &mut R, _extra_data: &Option<DecodeableExtraData>) -> Result<Self> {
120 let mut decoded = Self::default();
121 let data_len = data.len()?;
122
123 while let Ok(section_signature) = data.read_string_u8(4) {
124 let section_size = data.read_u32()? as u64;
125 dbg!(§ion_signature);
129 dbg!(§ion_size);
130 decoded.sections.push(match &*section_signature {
131 SIGNATURE_AKBK => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_AKBK.to_string())),
132
133 SIGNATURE_BKHD => Section::BKHD(BKHD::read(data, section_size as usize)?),
135 SIGNATURE_HIRC => {
136 let header = match decoded.sections.first() {
137 Some(Section::BKHD(section)) => section,
138 _ => return Err(RLibError::SoundBankBKHDNotFound),
139 };
140
141 Section::HIRC(HIRC::read(data, *header.version())?)
142 },
143 SIGNATURE_DATA => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_DATA.to_string())),
144 SIGNATURE_FXPR => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_FXPR.to_string())),
145 SIGNATURE_ENVS => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_ENVS.to_string())),
146 SIGNATURE_STID => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_STID.to_string())),
147 SIGNATURE_STMG => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_STMG.to_string())),
148 SIGNATURE_DIDX => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_DIDX.to_string())),
149 SIGNATURE_PLAT => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_PLAT.to_string())),
150 SIGNATURE_INIT => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_INIT.to_string())),
151 _ => return Err(RLibError::SoundBankUnsupportedSectionFound(section_signature)),
152 });
153 }
154
155 check_size_mismatch(data.stream_position()? as usize, data_len as usize)?;
156
157 Ok(decoded)
158 }
159}
160
161impl Encodeable for SoundBank {
162
163 fn encode<W: WriteBytes>(&mut self, buffer: &mut W, _extra_data: &Option<EncodeableExtraData>) -> Result<()> {
164 let header = match self.sections.first() {
165 Some(Section::BKHD(section)) => section,
166 _ => return Err(RLibError::SoundBankBKHDNotFound),
167 };
168
169 for section in self.sections() {
170 match section {
171 Section::BKHD(data) => data.write(buffer)?,
172 Section::HIRC(data) => data.write(buffer, *header.version())?,
173 }
174 }
175
176 Ok(())
177 }
178}