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_lightfunc(b: &[u8]) -> ResultS { read_data! { 14, BE in b => ftype = u16[0]; prd_nrm = u16[2]; prd_dta = u16[4]; val_nrm = u16[6]; val_dta = u16[10]; } let ftype = LightFuncType::from_repr(ftype)?; Ok(LightFunc{ftype, prd_nrm, prd_dta, val_nrm, val_dta}) } 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]; 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]; med_ind = u16[116]; med_ctl = u16[118]; snd_ind = u16[120]; snd_amb = u16[122]; snd_rnd = u16[124]; } 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 med_ind = ObjID::from_repr(med_ind); let hei_flr = Unit::from_bits(hei_flr); let hei_cei = Unit::from_bits(hei_cei); Ok((Polygon{ptype, pdata, tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr, xfr_cei, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb, snd_rnd}, 128)) } pub fn read_lite(b: &[u8]) -> ResultS<(Light, usize)> { read_data! { 100, BE in b => ltype = u16[0]; flags = u16[2]; phase = i16[4]; act_pri = read_lightfunc[6..20]; act_sec = read_lightfunc[20..34]; act_mid = read_lightfunc[34..48]; ina_pri = read_lightfunc[48..62]; ina_sec = read_lightfunc[62..76]; ina_mid = read_lightfunc[76..90]; tag = u16[90]; } let flags = ok!(LightFlags::from_bits(flags), "bad LightFlags")?; let ltype = LightType::from_repr(ltype)?; Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec, ina_mid, tag}, 100)) } #[derive(Clone, PartialEq, Serialize)] pub struct Point { pub x: Unit, pub y: Unit, } #[derive(Debug, Serialize)] pub struct Line { pub flags: LineFlags, pub pnt_beg: u16, pub pnt_end: u16, pub side_fr: ObjID, pub side_bk: ObjID, pub poly_fr: ObjID, pub poly_bk: ObjID, } #[derive(Debug, Serialize)] pub struct SideTex { pub offs: Point, pub tex_id: ObjID, } #[derive(Debug, Serialize)] pub struct Side { pub stype: SideType, pub flags: SideFlags, pub tex_pri: SideTex, pub tex_sec: SideTex, pub tex_tra: SideTex, pub paneltyp: u16, pub paneldat: i16, pub xfer_pri: TransferMode, pub xfer_sec: TransferMode, pub xfer_tra: TransferMode, pub shade: Fixed, } #[derive(Debug, Serialize)] pub struct Polygon { pub ptype: PolyType, pub pdata: i16, pub tex_flr: ObjID, pub tex_cei: ObjID, pub hei_flr: Unit, pub hei_cei: Unit, pub lit_flr: u16, pub lit_cei: u16, pub xfr_flr: TransferMode, pub xfr_cei: TransferMode, pub ori_flr: Point, pub ori_cei: Point, pub med_ind: ObjID, pub med_ctl: u16, pub snd_ind: u16, pub snd_amb: ObjID, pub snd_rnd: ObjID, } #[derive(Debug, Serialize)] pub struct LightFunc { pub ftype: LightFuncType, pub prd_nrm: u16, pub prd_dta: u16, pub val_nrm: u16, pub val_dta: u16, } #[derive(Debug, Serialize)] pub struct Light { pub ltype: LightType, pub flags: LightFlags, pub phase: i16, pub act_pri: LightFunc, pub act_sec: LightFunc, pub act_mid: LightFunc, pub ina_pri: LightFunc, pub ina_sec: LightFunc, pub ina_mid: LightFunc, pub tag: u16, } #[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; } } bitflags! { #[derive(Serialize)] pub struct LightFlags: u16 { const InitActive = 1; const SlaveValue = 1 << 1; const Stateless = 1 << 2; } } 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, } } c_enum! { #[derive(Debug, Serialize)] pub enum LightFuncType: u16 { 0 => Constant, 1 => Linear, 2 => Smooth, 3 => Flicker, } } c_enum! { #[derive(Debug, Serialize)] pub enum LightType: u16 { 0 => Normal, 1 => Strobe, 2 => Media, } } impl fmt::Debug for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({}, {})", self.x, self.y) } } // EOF