diff --git a/MarathonData.md b/MarathonData.md index 6629e40..cec50a9 100644 --- a/MarathonData.md +++ b/MarathonData.md @@ -369,7 +369,9 @@ main menu, and physics files. Here is a listing of all chunks used within them: | Name | Description | | ---- | ----------- | +| `Minf` | Static Map Info structure | | `PNTS` | Array of Points | +| `EPNT` | Array of Endpoints | | `LINS` | Array of Lines | | `SIDS` | Array of Sides | | `POLY` | Array of Polygons | @@ -377,11 +379,9 @@ main menu, and physics files. Here is a listing of all chunks used within them: | `NOTE` | Not analyzed (annotations) | | `OBJS` | Array of Objects | | `påth` | Not analyzed (å is $8C) (guardpaths) | -| `Minf` | Static Map Info structure | | `plac` | Not analyzed (item placement) | | `door` | No test data (extra door data) | -| `plat` | No test data (platform static data) | -| `EPNT` | Array of Endpoints | +| `PLAT` | No test data (platform static data) | | `medi` | Media (liquids) | | `ambi` | Not analyzed (ambient sounds) | | `bonk` | Not analyzed (random sounds) | @@ -554,17 +554,17 @@ If `WadVersion` is greater than or equal to `VerDir`: ### Light Function ### -Light Function is 14 bytes. A light function specification. +Light Function is 14 bytes. | Name | Type | Offset | | ---- | ---- | ------ | -| `Index` | `u16` | `0` | +| `Type` | `u16` | `0` | | `Period` | `u16` | `2` | | `DeltaPeriod` | `u16` | `4` | -| `ValueHi` | `u16` | `6` | -| `ValueLo` | `u16` | `8` | -| `DeltaValueHi` | `u16` | `10` | -| `DeltaValueLo` | `u16` | `12` | +| `Value` | `u16` | `6` | +| `DeltaValue` | `u16` | `10` | + +- `Type` is a Light Function enumeration. ### Side Texture ### @@ -703,7 +703,7 @@ shape and automatically split them.) | `OrigCei` | `struct` | `112` | | `Media` | `u16` | `116` | | `MediaLight` | `u16` | `118` | -| `Sound` | `u16` | `120` | +| `SoundIndices` | `u16` | `120` | | `SoundAmbient` | `u16` | `122` | | `SoundRandom` | `u16` | `124` | @@ -712,8 +712,9 @@ shape and automatically split them.) - `Area` is the power-of-two area of the polygon. - `ObjectFst` must be `65535`. - `Center` is a Point structure. -- `OrigFlr` is a Point structure. -- `OrigCei` is a Point structure. +- `OrigFlr` is a Point structure for the texture offset of the floor. +- `OrigCei` is a Point structure for the texture offset of the ceiling. +- `Media` is an Object ID. - `SoundAmbient` is an Object ID. - `SoundRandom` is an Object ID. @@ -734,6 +735,11 @@ Light is 100 bytes. | `InactMid` | `struct` | `76` | | `Tag` | `u16` | `90` | +- `Type` is a Light Type enumeration. +- `Flags` is a Light Flags bit field. +- `ActivPri`, `ActivSec` and `ActivMid` are Light Function structures. +- `InactPri`, `InactSec` and `InactMid` are Light Function structures. + ### Object ### Object is 16 bytes. @@ -1398,9 +1404,9 @@ Marathon 2 itself acknowledges how redundant this enumeration is. | Name | Value | Description | | ---- | ----- | ----------- | -| TODO | `0` | Normal light | -| TODO | `1` | Strobe light | -| TODO | `2` | Media light | +| `Normal` | `0` | Normal light | +| `Strobe` | `1` | Strobe light | +| `Media` | `2` | Media light | ### Wad Version ### @@ -1488,6 +1494,20 @@ fall off at 10 world units unobstructed. full volume for twice the distance as a normal sound, and fall off at 15 units unobstructed. +### Light Function ### + +| Name | Value | +| ---- | ----- | +| `Constant` | `0` | +| `Linear` | `1` | +| `Smooth` | `2` | +| `Flicker` | `3` | + +- `Constant` maintains the final intensity for `Period`. +- `Linear` transitions between the initial and final intensities over `Period`. +- `Smooth` does a sine transition in the same fashion as `Linear`. +- `Flicker` flickers between a random smoothed intensity and the final one. + # FLAGS ####################################################################### ### Endpoint Flags ### @@ -1619,8 +1639,9 @@ gravity. | Name | Bit | | ---- | --- | -| TODO | `0` | -| `Stateless` | `1` | +| `InitActive` | `0` | +| `SlaveValue` | `1` | +| `Stateless` | `2` | ### Entry Point Flags ### diff --git a/src/main.rs b/src/main.rs index d1ae5a3..8923108 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,6 +53,7 @@ fn dump_chunk(opt: &Options, cid: Ident, cnk: &[u8], eid: u16) -> ResultS<()> b"LINS" => make_yaml(opt, &rd_array(cnk, map::read_lins)?)?, b"SIDS" => make_yaml(opt, &rd_array(cnk, map::read_sids)?)?, b"POLY" => make_yaml(opt, &rd_array(cnk, map::read_poly)?)?, + b"LITE" => make_yaml(opt, &rd_array(cnk, map::read_lite)?)?, b"term" => make_yaml(opt, &rd_array(cnk, trm::read_term)?)?, _ => (), } diff --git a/src/marathon/map.rs b/src/marathon/map.rs index d6f5b54..745fa30 100644 --- a/src/marathon/map.rs +++ b/src/marathon/map.rs @@ -25,6 +25,22 @@ pub fn read_minf(b: &[u8]) -> ResultS 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! { @@ -119,7 +135,6 @@ 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]; @@ -131,14 +146,13 @@ pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)> 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]; + med_ind = u16[116]; + med_ctl = u16[118]; + snd_ind = 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)?; @@ -146,12 +160,36 @@ pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)> 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, 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)) + 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)] @@ -164,59 +202,83 @@ pub struct Point #[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, + 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 { - offs: Point, - tex_id: ObjID, + pub offs: Point, + pub 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, + 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 { - 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, + 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)] @@ -314,6 +376,16 @@ bitflags! { } } +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 @@ -352,6 +424,27 @@ c_enum! { } } +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