use getset::*;
use serde_derive::{Serialize, Deserialize};
use crate::binary::{ReadBytes, WriteBytes};
use crate::error::{Result, RLibError};
use crate::files::{Decodeable, EncodeableExtraData, Encodeable};
use crate::utils::check_size_mismatch;
use self::sections::bkhd::BKHD;
use self::sections::hirc::HIRC;
use super::DecodeableExtraData;
pub const EXTENSION: &str = ".bnk";
const FNV_NO: &str = "none";const FNV_BNK: &str = "bank";
const FNV_LNG: &str = "language";
const FNV_EVT: &str = "event";
const FNV_BUS: &str = "bus";
const FNV_SFX: &str = "sfx";
const FNV_TRG: &str = "trigger";
const FNV_GME: &str = "rtpc/game-variable";
const FNV_VAR: &str = "variable";const FNV_VAL: &str = "value";const FNV_UNK: &str = "???";
const FNV_ORDER: [&str; 10] = [
FNV_BNK, FNV_LNG, FNV_EVT, FNV_BUS, FNV_SFX, FNV_TRG, FNV_GME, FNV_VAR, FNV_VAL, FNV_UNK
];
const FNV_ORDER_JOIN: [&str; 3] = [
FNV_BNK, FNV_LNG, FNV_BUS
];
const 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;
mod sections;
#[cfg(test)] mod test_soundbank;
#[derive(Default, PartialEq, Clone, Debug, Getters, MutGetters, Setters, Serialize, Deserialize)]
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub struct SoundBank {
sections: Vec<Section>,
}
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum Section {
BKHD(BKHD),
HIRC(HIRC),
}
impl Decodeable for SoundBank {
fn decode<R: ReadBytes>(data: &mut R, _extra_data: &Option<DecodeableExtraData>) -> Result<Self> {
let mut decoded = Self::default();
let data_len = data.len()?;
while let Ok(section_signature) = data.read_string_u8(4) {
let section_size = data.read_u32()? as u64;
dbg!(§ion_signature);
dbg!(§ion_size);
decoded.sections.push(match &*section_signature {
SIGNATURE_AKBK => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_AKBK.to_string())),
SIGNATURE_BKHD => Section::BKHD(BKHD::read(data, section_size as usize)?),
SIGNATURE_HIRC => {
let header = match decoded.sections.first() {
Some(Section::BKHD(section)) => section,
_ => return Err(RLibError::SoundBankBKHDNotFound),
};
Section::HIRC(HIRC::read(data, *header.version())?)
},
SIGNATURE_DATA => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_DATA.to_string())),
SIGNATURE_FXPR => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_FXPR.to_string())),
SIGNATURE_ENVS => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_ENVS.to_string())),
SIGNATURE_STID => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_STID.to_string())),
SIGNATURE_STMG => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_STMG.to_string())),
SIGNATURE_DIDX => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_DIDX.to_string())),
SIGNATURE_PLAT => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_PLAT.to_string())),
SIGNATURE_INIT => return Err(RLibError::SoundBankUnsupportedSectionFound(SIGNATURE_INIT.to_string())),
_ => return Err(RLibError::SoundBankUnsupportedSectionFound(section_signature)),
});
}
check_size_mismatch(data.stream_position()? as usize, data_len as usize)?;
Ok(decoded)
}
}
impl Encodeable for SoundBank {
fn encode<W: WriteBytes>(&mut self, buffer: &mut W, _extra_data: &Option<EncodeableExtraData>) -> Result<()> {
let header = match self.sections.first() {
Some(Section::BKHD(section)) => section,
_ => return Err(RLibError::SoundBankBKHDNotFound),
};
for section in self.sections() {
match section {
Section::BKHD(data) => data.write(buffer)?,
Section::HIRC(data) => data.write(buffer, *header.version())?,
}
}
Ok(())
}
}