From 252d6b8edd003d752dff60de726cdac46e3906ae Mon Sep 17 00:00:00 2001 From: Marrub Date: Thu, 13 Dec 2018 04:08:02 -0500 Subject: [PATCH] add new loaders for map data --- src/main.rs | 23 +++- src/marathon/map.rs | 275 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 288 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4f8ac49..d0bddef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ +#[macro_use] pub mod durandal; pub mod marathon; -use crate::durandal::{err::*, image::Image, pict::load_pict}; +use crate::durandal::{chunk::*, err::*, image::Image, pict::load_pict}; use crate::marathon::{map, wad, term}; use memmap::Mmap; use std::{io, io::Write, fs, env}; @@ -44,6 +45,26 @@ fn main() -> ResultS<()> println!("entry {} has {:#?}", id, minf); } + if let Some(b) = ent.chunks.get(b"EPNT") { + let epnt = map::Endpoint::chunk(b)?; + println!("entry {} has EPNT {:#?}", id, epnt); + } + + if let Some(b) = ent.chunks.get(b"PNTS") { + let epnt = map::Point::chunk(b)?; + println!("entry {} has PNTS {:#?}", id, epnt); + } + + if let Some(b) = ent.chunks.get(b"LINS") { + let line = map::Line::chunk(b)?; + println!("entry {} has LINS {:#?}", id, line); + } + + if let Some(b) = ent.chunks.get(b"SIDS") { + let line = map::Side::chunk(b)?; + println!("entry {} has SIDS {:#?}", id, line); + } + if let Some(b) = ent.chunks.get(b"term") { let term = term::Terminal::chunk(b)?; println!("entry {} has term {:#?}", id, term); diff --git a/src/marathon/map.rs b/src/marathon/map.rs index 763cf69..5061f53 100644 --- a/src/marathon/map.rs +++ b/src/marathon/map.rs @@ -1,11 +1,103 @@ -use crate::durandal::{bin::*, err::*, text::mac_roman_conv}; +use bitflags::bitflags; +use crate::durandal::{bin::*, chunk::*, err::*, fx32::*, text::mac_roman_conv}; +use std::fmt; -impl Minf +impl Chunked for Point { - pub fn chunk(b: &[u8]) -> ResultS - { - if b.len() < 88 {return err_msg("not enough data for Minf")} + 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])?; + // xform = Point::read(&b[10..14])?; + 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)?; + 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 paneltyp = + if flags.contains(SideFlags::Panel) { + Some(PanelType::from_repr(paneltyp)?) + } else { + None + }; + 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)?; @@ -13,21 +105,186 @@ impl Minf 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: u16, +} + +#[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: Option, + 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: u16, - env_flag: u16, - ent_flag: u32, + 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; + } +} + +c_enum! { + #[derive(Debug)] + pub enum PanelType: u16 + { + 0 => Oxygen, + 1 => Shield, + 2 => Shield2x, + 3 => Shield3x, + 4 => Light, + 5 => Platform, + 6 => Tag, + 7 => PatternBuf, + 8 => Terminal, + } +} + +impl fmt::Debug for Point +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + write!(f, "({}, {})", self.x, self.y) + } +} + // EOF