use crate::{durandal::{bin::*, chunk::*, err::*, fx32::*, text::mac_roman_conv}, marathon::xfer::TransferMode}; use bitflags::bitflags; use serde::Serialize; use std::fmt; impl Chunked for Point { const SIZE_CHUNK: usize = 4; fn read(b: &[u8]) -> ResultS { let x = c_i16b(b, 0)?; let y = c_i16b(b, 2)?; Ok(Point{x, y}) } } impl Chunked for Endpoint { const SIZE_CHUNK: usize = 16; fn read(b: &[u8]) -> ResultS { let flags = c_u16b(b, 0)?; let adj_hi = c_i16b(b, 2)?; let adj_lo = c_i16b(b, 4)?; let pos = Point::read(c_data(b, 6..10)?)?; let support = c_u16b(b, 14)?; let flags = ok!(EndpFlags::from_bits(flags), "bad EndpFlags")?; Ok(Endpoint{flags, adj_hi, adj_lo, pos, support}) } } impl Chunked for Line { const SIZE_CHUNK: usize = 32; fn read(b: &[u8]) -> ResultS { let epnt_f = c_u16b(b, 0)?; let epnt_b = c_u16b(b, 2)?; let flags = c_u16b(b, 4)?; let length = c_i16b(b, 6)?; let adj_hi = c_i16b(b, 8)?; let adj_lo = c_i16b(b, 10)?; let side_f = c_u16b(b, 12)?; let side_b = c_u16b(b, 14)?; let poly_f = c_u16b(b, 16)?; let poly_b = c_u16b(b, 18)?; let flags = ok!(LineFlags::from_bits(flags), "bad LineFlags")?; Ok(Line{flags, length, adj_hi, adj_lo, epnt_f, epnt_b, side_f, side_b, poly_f, poly_b}) } } impl SideTex { fn read(b: &[u8]) -> ResultS { let offs = Point::read(c_data(b, 0..4)?)?; let tex_id = c_u16b(b, 4)?; let tex_id = ObjID::from_repr(tex_id); Ok(SideTex{offs, tex_id}) } } impl Chunked for Side { const SIZE_CHUNK: usize = 64; fn read(b: &[u8]) -> ResultS { let stype = c_u16b(b, 0)?; let flags = c_u16b(b, 2)?; let tex_pri = SideTex::read(c_data(b, 4..10)?)?; let tex_sec = SideTex::read(c_data(b, 10..16)?)?; let tex_tra = SideTex::read(c_data(b, 16..22)?)?; let ex_tleft = Point::read(c_data(b, 22..26)?)?; let ex_trigh = Point::read(c_data(b, 26..30)?)?; let ex_bleft = Point::read(c_data(b, 30..34)?)?; let ex_brigh = Point::read(c_data(b, 34..38)?)?; let paneltyp = c_u16b(b, 38)?; let paneldat = c_i16b(b, 40)?; let xfer_pri = c_u16b(b, 42)?; let xfer_sec = c_u16b(b, 44)?; let xfer_tra = c_u16b(b, 46)?; let shade = c_u32b(b, 48)?; let flags = ok!(SideFlags::from_bits(flags), "bad SideFlags")?; let xfer_pri = TransferMode::from_repr(xfer_pri)?; let xfer_sec = TransferMode::from_repr(xfer_sec)?; let xfer_tra = TransferMode::from_repr(xfer_tra)?; let shade = Fx32::from_bits(shade); Ok(Side{stype, flags, tex_pri, tex_sec, tex_tra, ex_tleft, ex_trigh, ex_bleft, ex_brigh, paneltyp, paneldat, xfer_pri, xfer_sec, xfer_tra, shade}) } } impl Chunker for Minf { fn chunk(b: &[u8]) -> ResultS { let env_code = c_u16b(b, 0)?; let physi_id = c_u16b(b, 2)?; let music_id = c_u16b(b, 4)?; let msn_flag = c_u16b(b, 6)?; let env_flag = c_u16b(b, 8)?; let levelnam = mac_roman_conv(c_data(b, 18..84)?); let ent_flag = c_u32b(b, 84)?; let msn_flag = ok!(MsnFlags::from_bits(msn_flag), "bad MsnFlags")?; let env_flag = ok!(EnvFlags::from_bits(env_flag), "bad EnvFlags")?; let ent_flag = ok!(EntFlags::from_bits(ent_flag), "bad EntFlags")?; Ok(Minf{env_code, physi_id, music_id, msn_flag, env_flag, ent_flag, levelnam}) } } type Unit = i16; #[derive(Serialize)] pub struct Point { x: Unit, y: Unit, } #[derive(Debug, Serialize)] pub struct Endpoint { flags: EndpFlags, adj_hi: Unit, adj_lo: Unit, pos: Point, support: u16, } #[derive(Debug, Serialize)] pub struct Line { flags: LineFlags, length: Unit, adj_hi: Unit, adj_lo: Unit, epnt_f: u16, epnt_b: u16, side_f: u16, side_b: u16, poly_f: u16, poly_b: u16, } #[derive(Debug, Serialize)] pub struct SideTex { offs: Point, tex_id: ObjID, } #[derive(Debug, Serialize)] pub struct Side { stype: u16, flags: SideFlags, tex_pri: SideTex, tex_sec: SideTex, tex_tra: SideTex, ex_tleft: Point, ex_trigh: Point, ex_bleft: Point, ex_brigh: Point, paneltyp: u16, paneldat: i16, xfer_pri: TransferMode, xfer_sec: TransferMode, xfer_tra: TransferMode, shade: Fx32, } #[derive(Debug, Serialize)] pub struct Minf { env_code: u16, physi_id: u16, music_id: u16, msn_flag: MsnFlags, env_flag: EnvFlags, ent_flag: EntFlags, levelnam: String, } bitflags! { #[derive(Serialize)] pub struct EndpFlags: u16 { const Solid = 0x00_01; const SameHeight = 0x00_02; const Transparent = 0x00_04; } } bitflags! { #[derive(Serialize)] pub struct LineFlags: u16 { const TransSide = 0x02_00; const ElevVar = 0x04_00; const Elevation = 0x08_00; const Landscape = 0x10_00; const Transparent = 0x20_00; const Solid = 0x40_00; } } bitflags! { #[derive(Serialize)] pub struct SideFlags: u16 { const Status = 0x00_01; const Panel = 0x00_02; const Repair = 0x00_04; const ItemUse = 0x00_08; const Lighted = 0x00_10; const CanDestroy = 0x00_20; const HitOnly = 0x00_40; const ItemOpt = 0x00_80; } } bitflags! { #[derive(Serialize)] pub struct EnvFlags: u16 { const Vacuum = 0x00_01; const Magnetic = 0x00_02; const Rebellion = 0x00_04; const LowGrav = 0x00_08; const M1Glue = 0x00_10; const LavaFloor = 0x00_20; const Rebellion2 = 0x00_40; const Music = 0x00_80; const TermPause = 0x01_00; const M1Monster = 0x02_00; const M1Weps = 0x04_00; const NetPlay = 0x20_00; const Solo = 0x40_00; } } bitflags! { #[derive(Serialize)] pub struct EntFlags: u32 { const Solo = 0x00_01; const CoOp = 0x00_02; const Carnage = 0x00_04; const KTMWTB = 0x00_08; const KOTH = 0x00_10; const Defense = 0x00_20; const Rugby = 0x00_40; const CTF = 0x00_80; } } bitflags! { #[derive(Serialize)] pub struct MsnFlags: u16 { const Extermination = 0x00_01; const Exploration = 0x00_02; const Retrieval = 0x00_04; const Repair = 0x00_08; const Rescue = 0x00_10; } } impl fmt::Debug for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({}, {})", self.x, self.y) } } // EOF