use crate::{durandal::{bin::*, err::*, fixed::*, text::mac_roman_conv}, marathon::xfer::TransferMode}; use bitflags::bitflags; use serde::Serialize; use std::fmt; pub fn read_minf(b: &[u8]) -> ResultS { read_data! { 88, BE in b => env_code = u16[0]; physi_id = u16[2]; music_id = u16[4]; msn_flag = u16[6]; env_flag = u16[8]; levelnam = mac_roman_conv[18..84] nt; ent_flag = u32[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}) } pub fn read_sidetex(b: &[u8]) -> ResultS { read_data! { 6, BE in b => offs = read_point[0..4]; tex_id = u16[4]; } let tex_id = ObjID::from_repr(tex_id); Ok(SideTex{offs, tex_id}) } pub fn read_point(b: &[u8]) -> ResultS { read_data! { 4, BE in b => x = u16[0]; y = u16[2]; } Ok(Point{x: Unit::from_bits(x), y: Unit::from_bits(y)}) } pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)> { read_data! { 16, BE in b => pnt = read_point[6..10]; } Ok((pnt, 16)) } pub fn read_pnts(b: &[u8]) -> ResultS<(Point, usize)> { Ok((read_point(b)?, 4)) } pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)> { read_data! { 32, BE in b => pnt_beg = u16[0]; pnt_end = u16[2]; flags = u16[4]; side_fr = u16[12]; side_bk = u16[14]; poly_fr = u16[16]; poly_bk = u16[18]; } let flags = ok!(LineFlags::from_bits(flags), "bad LineFlags")?; let side_fr = ObjID::from_repr(side_fr); let side_bk = ObjID::from_repr(side_bk); let poly_fr = ObjID::from_repr(poly_fr); let poly_bk = ObjID::from_repr(poly_bk); Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32)) } pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)> { read_data! { 64, BE in b => stype = u16[0]; flags = u16[2]; tex_pri = read_sidetex[4..10]; tex_sec = read_sidetex[10..16]; tex_tra = read_sidetex[16..22]; paneltyp = u16[38]; paneldat = i16[40]; xfer_pri = u16[42]; xfer_sec = u16[44]; xfer_tra = u16[46]; shade = u32[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 stype = SideType::from_repr(stype)?; let shade = Fixed::from_bits(shade); Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat, xfer_pri, xfer_sec, xfer_tra, shade}, 64)) } pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)> { read_data! { 128, BE in b => ptype = u16[0]; flags = u16[2]; pdata = i16[4]; tex_flr = u16[40]; tex_cei = u16[42]; hei_flr = u16[44]; hei_cei = u16[46]; lit_flr = u16[48]; lit_cei = u16[50]; xfr_flr = u16[64]; xfr_cei = u16[66]; ori_flr = read_point[108..112]; ori_cei = read_point[112..116]; media = u16[116]; media_l = u16[118]; sound = u16[120]; snd_amb = u16[122]; snd_rnd = u16[124]; } let flags = ok!(PolyFlags::from_bits(flags), "bad PolyFlags")?; let xfr_flr = TransferMode::from_repr(xfr_flr)?; let xfr_cei = TransferMode::from_repr(xfr_cei)?; let ptype = PolyType::from_repr(ptype)?; let tex_flr = ObjID::from_repr(tex_flr); let tex_cei = ObjID::from_repr(tex_cei); let snd_amb = ObjID::from_repr(snd_amb); let snd_rnd = ObjID::from_repr(snd_rnd); let hei_flr = Unit::from_bits(hei_flr); let hei_cei = Unit::from_bits(hei_cei); Ok((Polygon{ptype, flags, pdata, tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr, xfr_cei, ori_flr, ori_cei, media, media_l, sound, snd_amb, snd_rnd}, 128)) } #[derive(Clone, PartialEq, Serialize)] pub struct Point { pub x: Unit, pub y: Unit, } #[derive(Debug, Serialize)] pub struct Line { flags: LineFlags, pnt_beg: u16, pnt_end: u16, side_fr: ObjID, side_bk: ObjID, poly_fr: ObjID, poly_bk: ObjID, } #[derive(Debug, Serialize)] pub struct SideTex { offs: Point, tex_id: ObjID, } #[derive(Debug, Serialize)] pub struct Side { stype: SideType, flags: SideFlags, tex_pri: SideTex, tex_sec: SideTex, tex_tra: SideTex, paneltyp: u16, paneldat: i16, xfer_pri: TransferMode, xfer_sec: TransferMode, xfer_tra: TransferMode, shade: Fixed, } #[derive(Debug, Serialize)] pub struct Polygon { ptype: PolyType, flags: PolyFlags, pdata: i16, tex_flr: ObjID, tex_cei: ObjID, hei_flr: Unit, hei_cei: Unit, lit_flr: u16, lit_cei: u16, xfr_flr: TransferMode, xfr_cei: TransferMode, ori_flr: Point, ori_cei: Point, media: u16, media_l: u16, sound: u16, snd_amb: ObjID, snd_rnd: ObjID, } #[derive(Debug, PartialEq, Serialize)] pub struct Minf { pub env_code: u16, pub physi_id: u16, pub music_id: u16, pub msn_flag: MsnFlags, pub env_flag: EnvFlags, pub ent_flag: EntFlags, pub levelnam: String, } bitflags! { #[derive(Serialize)] pub struct LineFlags: u16 { const TransSide = 1 << 9; const ElevVar = 1 << 10; const Elevation = 1 << 11; const Landscape = 1 << 12; const Transparent = 1 << 13; const Solid = 1 << 14; } } bitflags! { #[derive(Serialize)] pub struct SideFlags: u16 { const Status = 1; const Panel = 1 << 1; const Repair = 1 << 2; const ItemUse = 1 << 3; const Lighted = 1 << 4; const CanDestroy = 1 << 5; const HitOnly = 1 << 6; const ItemOpt = 1 << 7; } } bitflags! { #[derive(Serialize)] pub struct EnvFlags: u16 { const Vacuum = 1; const Magnetic = 1 << 1; const Rebellion = 1 << 2; const LowGrav = 1 << 3; const M1Glue = 1 << 4; const LavaFloor = 1 << 5; const Rebellion2 = 1 << 6; const Music = 1 << 7; const TermPause = 1 << 8; const M1Monster = 1 << 9; const M1Weps = 1 << 10; const NetPlay = 1 << 13; const Solo = 1 << 14; } } bitflags! { #[derive(Serialize)] pub struct EntFlags: u32 { const Solo = 1; const CoOp = 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! { #[derive(Serialize)] pub struct MsnFlags: u16 { const Extermination = 1; const Exploration = 1 << 1; const Retrieval = 1 << 2; const Repair = 1 << 3; const Rescue = 1 << 4; } } bitflags! { #[derive(Serialize)] pub struct PolyFlags: u16 { const Detached = 1 << 14; } } c_enum! { #[derive(Debug, Serialize)] pub enum SideType: u16 { 0 => Full, 1 => High, 2 => Low, 3 => Composite, 4 => Split, } } c_enum! { #[derive(Debug, Serialize)] pub enum PolyType: u16 { 0 => Normal, 1 => ImpassItem, 2 => ImpassMons, 3 => Hill, 4 => Base, 5 => Platform, 6 => TrigLightOn, 7 => TrigPlatOn, 8 => TrigLightOff, 9 => TrigPlatOff, 10 => Teleporter, 11 => ZoneBorder, 12 => Goal, 13 => TrigMonsVis, 14 => TrigMonsInv, 15 => TrigMonsDual, 16 => TrigItems, 17 => MustExplore, 18 => AutoExit, } } impl fmt::Debug for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({}, {})", self.x, self.y) } } // EOF