//! `Minf` type. use crate::{durandal::err::*, marathon::text::*}; use bitflags::bitflags; /// Reads a `Minf` chunk. pub fn read(b: &[u8]) -> ResultS { read_data! { endian: BIG, buf: b, size: 88, start: 0, data { let texture_id = u16[0]; let physics_id = u16[2]; let skypict_id = u16[4]; let miss_flags = u16[6] flag MsnFlags; let envi_flags = u16[8] flag EnvFlags; let level_name = mac_roman_cstr[18; 66] no_try; let entr_flags = u32[84] flag EntFlags; } } Ok(Minf{texture_id, physics_id, skypict_id, miss_flags, envi_flags, entr_flags, level_name}) } /// Writes a `Minf` chunk. pub fn write(v: &Minf) -> Vec { let mut o = Vec::with_capacity(4); o.extend(&v.texture_id.to_be_bytes()); o.extend(&v.physics_id.to_be_bytes()); o.extend(&v.skypict_id.to_be_bytes()); o.extend(&v.miss_flags.bits().to_be_bytes()); o.extend(&v.envi_flags.bits().to_be_bytes()); o.extend(&pad_zero(to_mac_roman(&v.level_name), 66)); o.extend(&v.entr_flags.bits().to_be_bytes()); o } /// Reads an old `Minf` chunk. pub fn read_old(b: &[u8]) -> ResultS { let minf = read(b)?; let mut entr_flags = if minf.entr_flags.is_empty() { EntFlags::SOLO } else { minf.entr_flags }; if entr_flags.intersects(EntFlags::SOLO | EntFlags::CARNAGE) { entr_flags.insert(EntFlags::CO_OP) } Ok(Minf{entr_flags, ..minf}) } impl Default for Minf { fn default() -> Self { Self{texture_id: 0, physics_id: 1, skypict_id: 0, miss_flags: MsnFlags::empty(), envi_flags: EnvFlags::empty(), entr_flags: EntFlags::SOLO, level_name: "Map".to_string()} } } /// Static map information. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Clone, Debug, Eq, PartialEq)] pub struct Minf { pub texture_id: u16, pub physics_id: u16, pub skypict_id: u16, pub miss_flags: MsnFlags, pub envi_flags: EnvFlags, pub entr_flags: EntFlags, pub level_name: String, } bitflags! { /// Static environment flags. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] pub struct EnvFlags: u16 { const VACUUM = 1; const MAGNETIC = 1 << 1; const REBELLION = 1 << 2; const LOW_GRAV = 1 << 3; const M1_GLUE = 1 << 4; const LAVA_FLOOR = 1 << 5; const REBELLION2 = 1 << 6; const MUSIC = 1 << 7; const TERM_PAUSE = 1 << 8; const M1_MONSTER = 1 << 9; const M1_WEPS = 1 << 10; } } bitflags! { /// Static entry point flags. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] pub struct EntFlags: u32 { const SOLO = 1; const CO_OP = 1 << 1; const CARNAGE = 1 << 2; const KTMWTB = 1 << 3; const KOTH = 1 << 4; const DEFENSE = 1 << 5; const RUGBY = 1 << 6; const CTF = 1 << 7; } } bitflags! { /// Static mission flags. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] pub struct MsnFlags: u16 { const EXTERMINATION = 1; const EXPLORATION = 1 << 1; const RETRIEVAL = 1 << 2; const REPAIR = 1 << 3; const RESCUE = 1 << 4; } } // EOF