use crate::durandal::{bin::*, chunk::*, err::*, fx32::*, text::mac_roman_conv}; use bitflags::bitflags; use std::fmt; impl Chunked for Point { const SIZE_CHUNK: usize = 4; fn read(b: &[u8]) -> ResultS { let x = b.c_i16b(0)?; let y = b.c_i16b(2)?; Ok(Point{x, y}) } } impl Chunked for Endpoint { const SIZE_CHUNK: usize = 16; fn read(b: &[u8]) -> ResultS { let flags = b.c_u16b(0)?; let adj_hi = b.c_i16b(2)?; let adj_lo = b.c_i16b(4)?; let pos = Point::read(&b[6..10])?; let support = b.c_u16b(14)?; let flags = EndpointFlags::from_bits_truncate(flags); 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 = b.c_u16b(0)?; let epnt_b = b.c_u16b(2)?; let flags = b.c_u16b(4)?; let length = b.c_i16b(6)?; let adj_hi = b.c_i16b(8)?; let adj_lo = b.c_i16b(10)?; let side_f = b.c_u16b(12)?; let side_b = b.c_u16b(14)?; let poly_f = b.c_u16b(16)?; let poly_b = b.c_u16b(18)?; let flags = LineFlags::from_bits_truncate(flags); Ok(Line{flags, length, adj_hi, adj_lo, epnt_f, epnt_b, side_f, side_b, poly_f, poly_b}) } } fn read_side_tex(b: &[u8]) -> ResultS { let offs = Point::read(&b[0..4])?; let tex_id = b.c_u16b(4)?; let tex_id = if tex_id == 65535 {None} else {Some(tex_id)}; Ok(SideTex{offs, tex_id}) } impl Chunked for Side { const SIZE_CHUNK: usize = 64; fn read(b: &[u8]) -> ResultS { let stype = b.c_u16b(0)?; let flags = b.c_u16b(2)?; let tex_pri = read_side_tex(&b[4..10])?; let tex_sec = read_side_tex(&b[10..16])?; let tex_tra = read_side_tex(&b[16..22])?; let ex_tleft = Point::read(&b[22..26])?; let ex_trigh = Point::read(&b[26..30])?; let ex_bleft = Point::read(&b[30..34])?; let ex_brigh = Point::read(&b[34..38])?; let paneltyp = b.c_u16b(38)?; let paneldat = b.c_i16b(40)?; let xfer_pri = b.c_u16b(42)?; let xfer_sec = b.c_u16b(44)?; let xfer_tra = b.c_u16b(46)?; let shade = b.c_u32b(48)?; let flags = SideFlags::from_bits_truncate(flags); 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 = b.c_u16b(0)?; let physi_id = b.c_u16b(2)?; let music_id = b.c_u16b(4)?; let msn_flag = b.c_u16b(6)?; let env_flag = b.c_u16b(8)?; let levelnam = mac_roman_conv(&b[18..84]); let ent_flag = b.c_u32b(84)?; let msn_flag = MsnFlags::from_bits_truncate(msn_flag); let env_flag = EnvFlags::from_bits_truncate(env_flag); let ent_flag = EntFlags::from_bits_truncate(ent_flag); Ok(Minf{env_code, physi_id, music_id, msn_flag, env_flag, ent_flag, levelnam}) } } type Unit = i16; pub struct Point { x: Unit, y: Unit, } #[derive(Debug)] pub struct Endpoint { flags: EndpointFlags, adj_hi: Unit, adj_lo: Unit, pos: Point, support: u16, } #[derive(Debug)] 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)] pub struct SideTex { offs: Point, tex_id: Option, } #[derive(Debug)] 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: u16, xfer_sec: u16, xfer_tra: u16, shade: Fx32, } #[derive(Debug)] pub struct Minf { env_code: u16, physi_id: u16, music_id: u16, msn_flag: MsnFlags, env_flag: EnvFlags, ent_flag: EntFlags, levelnam: String, } bitflags! { pub struct EndpointFlags: u16 { const Solid = 0x00_01; const SameHeight = 0x00_02; const Transparent = 0x00_04; } } bitflags! { 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! { 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! { 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! { 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! { 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