use crate::{durandal::{bin::*, err::*, fixed::*, text::mac_roman_conv}, marathon::xfer::TransferMode}; use bitflags::bitflags; use serde::Serialize; 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]; missi_flags = u16[6]; envir_flags = u16[8]; level_name = mac_roman_conv[18..84] nt; entry_flags = u32[84]; } let missi_flags = flag_ok!(MsnFlags, missi_flags)?; let envir_flags = flag_ok!(EnvFlags, envir_flags)?; let entry_flags = flag_ok!(EntFlags, entry_flags)?; Ok(Minf{env_code, physi_id, music_id, missi_flags, envir_flags, entry_flags, level_name}) } 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 = OptU16[4]; } Ok(SideTex{offs, tex_id}) } pub fn read_point(b: &[u8]) -> ResultS { read_data! { 4, BE in b => x = Unit[0]; y = Unit[2]; } Ok(Point{x, 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 = OptU16[12]; side_bk = OptU16[14]; poly_fr = OptU16[16]; poly_bk = OptU16[18]; } let flags = flag_ok!(LineFlags, flags)?; 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 = Fixed[48]; } let flags = flag_ok!(SideFlags, flags)?; 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)?; 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 = OptU16[40]; tex_cei = OptU16[42]; hei_flr = Unit[44]; hei_cei = Unit[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 = OptU16[116]; med_ctl = u16[118]; snd_ind = u16[120]; snd_amb = OptU16[122]; snd_rnd = OptU16[124]; } let xfr_flr = TransferMode::from_repr(xfr_flr)?; let xfr_cei = TransferMode::from_repr(xfr_cei)?; let ptype = PolyType::from_repr(ptype)?; 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 = flag_ok!(LightFlags, flags)?; 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)) } pub fn read_objs(b: &[u8]) -> ResultS<(Object, usize)> { read_data! { 16, BE in b => group = u16[0]; index = u16[2]; angle = Angle[4]; poly = u16[6]; pos_x = Unit[8]; pos_y = Unit[10]; pos_z = Unit[12]; flags = u16[14]; } let bias = flags & 0xF0_00; let flags = flags & 0x0F_FF; let bias = bias >> 12; let flags = flag_ok!(ObjectFlags, flags)?; Ok((Object{group, index, angle, poly, pos_x, pos_y, pos_z, flags, bias}, 16)) } pub fn read_plac(b: &[u8]) -> ResultS<(ObjectFreq, usize)> { read_data! { 12, BE in b => flags = u16[0]; cnt_ini = u16[2]; cnt_min = u16[4]; cnt_max = u16[6]; cnt_rnd = u16[8]; chance = u16[10]; } let rnd_loc = flags != 0; Ok((ObjectFreq{rnd_loc, cnt_ini, cnt_min, cnt_max, cnt_rnd, chance}, 12)) } pub fn read_ambi(b: &[u8]) -> ResultS<(SoundAmbi, usize)> { read_data! { 16, BE in b => index = u16[2]; volume = u16[4]; } Ok((SoundAmbi{index, volume}, 16)) } pub fn read_bonk(b: &[u8]) -> ResultS<(SoundRand, usize)> { read_data! { 32, BE in b => flags = u16[0]; index = u16[2]; vol_nrm = u16[4]; vol_dta = u16[6]; prd_nrm = u16[8]; prd_dta = u16[10]; yaw_nrm = Angle[12]; yaw_dta = Angle[14]; pit_nrm = Fixed[16]; pit_dta = Fixed[20]; } let no_dir = flags != 0; Ok((SoundRand{no_dir, index, vol_nrm, vol_dta, prd_nrm, prd_dta, yaw_nrm, yaw_dta, pit_nrm, pit_dta}, 32)) } pub fn read_medi(b: &[u8]) -> ResultS<(Media, usize)> { read_data! { 32, BE in b => mtype = u16[0]; flags = u16[2]; control = u16[4]; dir = Angle[6]; mag = Unit[8]; hei_lo = Unit[10]; hei_hi = Unit[12]; orig = read_point[14..18]; hei_nrm = Unit[18]; min_lt = Fixed[20]; texture = OptU16[24]; xfer = u16[26]; } let mtype = MediaType::from_repr(mtype)?; let xfer = TransferMode::from_repr(xfer)?; let flr_obs = flags != 0; Ok((Media{mtype, flr_obs, control, dir, mag, hei_lo, hei_hi, orig, hei_nrm, min_lt, texture, xfer}, 32)) } pub fn read_plat(b: &[u8]) -> ResultS<(Platform, usize)> { read_data! { 32, BE in b => ptype = u16[0]; speed = u16[2]; delay = u16[4]; hei_max = Unit[6]; hei_min = Unit[8]; flags = u32[10]; index = u16[14]; tag = u16[16]; } let flags = flag_ok!(PlatformFlags, flags)?; Ok((Platform{ptype, speed, delay, hei_min, hei_max, flags, index, tag}, 32)) } #[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: OptU16, pub side_bk: OptU16, pub poly_fr: OptU16, pub poly_bk: OptU16, } #[derive(Debug, Serialize)] pub struct SideTex { pub offs: Point, pub tex_id: OptU16, } #[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: OptU16, pub tex_cei: OptU16, 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: OptU16, pub med_ctl: u16, pub snd_ind: u16, pub snd_amb: OptU16, pub snd_rnd: OptU16, } #[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, Serialize)] pub struct Object { pub group: u16, pub index: u16, pub angle: Angle, pub poly: u16, pub pos_x: Unit, pub pos_y: Unit, pub pos_z: Unit, pub flags: ObjectFlags, pub bias: u16, } #[derive(Debug, Serialize)] pub struct ObjectFreq { pub rnd_loc: bool, pub cnt_ini: u16, pub cnt_min: u16, pub cnt_max: u16, pub cnt_rnd: u16, pub chance: u16, } #[derive(Debug, Serialize)] pub struct SoundAmbi { pub index: u16, pub volume: u16, } #[derive(Debug, Serialize)] pub struct SoundRand { pub no_dir: bool, pub index: u16, pub vol_nrm: u16, pub vol_dta: u16, pub prd_nrm: u16, pub prd_dta: u16, pub yaw_nrm: Angle, pub yaw_dta: Angle, pub pit_nrm: Fixed, pub pit_dta: Fixed, } #[derive(Debug, Serialize)] pub struct Media { pub mtype: MediaType, pub flr_obs: bool, pub control: u16, pub dir: Angle, pub mag: Unit, pub hei_lo: Unit, pub hei_hi: Unit, pub orig: Point, pub hei_nrm: Unit, pub min_lt: Fixed, pub texture: OptU16, pub xfer: TransferMode, } #[derive(Debug, Serialize)] pub struct Platform { pub ptype: u16, pub speed: u16, pub delay: u16, pub hei_min: Unit, pub hei_max: Unit, pub flags: PlatformFlags, pub index: u16, pub tag: u16, } #[derive(Debug, PartialEq, Serialize)] pub struct Minf { pub env_code: u16, pub physi_id: u16, pub music_id: u16, pub missi_flags: MsnFlags, pub envir_flags: EnvFlags, pub entry_flags: EntFlags, pub level_name: 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; } } bitflags! { #[derive(Serialize)] pub struct ObjectFlags: u16 { const Invisible = 1; const Ceiling = 1 << 1; const Blind = 1 << 2; const Deaf = 1 << 3; const Floating = 1 << 4; const NetOnly = 1 << 5; } } bitflags! { #[derive(Serialize)] pub struct PlatformFlags: u32 { const InitActive = 1; const InitExtended = 1 << 1; const StopAtEachLevel = 1 << 2; const StopAtInitLevel = 1 << 3; const StartAdjOnStop = 1 << 4; const ExtendsFloorToCeil = 1 << 5; const ComesFromFloor = 1 << 6; const ComesFromCeil = 1 << 7; const CausesDamage = 1 << 8; const NoActivateParent = 1 << 9; const ActivatesOnce = 1 << 10; const ActivatesLight = 1 << 11; const DeactivatesLight = 1 << 12; const PlayerControls = 1 << 13; const MonsterControls = 1 << 14; const ReverseOnObstruct = 1 << 15; const NoExtDeactivation = 1 << 16; const UsePolygonHeights = 1 << 17; const DelayedActivation = 1 << 18; const StartAdjOnStart = 1 << 19; const StopAdjOnStart = 1 << 20; const StopAdjOnStop = 1 << 21; const Slow = 1 << 22; const StartAtEachLevel = 1 << 23; const Locked = 1 << 24; const Secret = 1 << 25; const Door = 1 << 26; } } 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, } } c_enum! { #[derive(Debug, Serialize)] pub enum MediaType: u16 { 0 => Water, 1 => Lava, 2 => Goo, 3 => Sewage, } } impl std::fmt::Debug for Point { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "({}, {})", self.x, self.y) } } // EOF