Compare commits

...

4 Commits

Author SHA1 Message Date
an daebfd2da6 maraiah: fix tests and move code to root 2019-06-22 00:55:08 -04:00
an bfb91792ec maraiah: rewrite how maps work 2019-06-21 21:34:10 -04:00
an be8d72df7d data: dang it bungie 2019-06-21 21:07:16 -04:00
an 91d171c8a6 maraiah: fix invisible dependencies in macros 2019-06-19 06:55:56 -04:00
128 changed files with 2903 additions and 601 deletions

View File

@ -14,10 +14,10 @@ publish = false
serde_obj = ["serde"] serde_obj = ["serde"]
[workspace] [workspace]
members = ["source/leela", "source/tycho"] members = ["leela", "tycho"]
[dependencies] [dependencies]
bitflags = "1.0" bitflags = "1.1"
failure = {version = "0.1", features = ["std"]} failure = {version = "0.1", features = ["std"]}
serde = {version = "1.0", features = ["derive"], optional = true} serde = {version = "1.0", features = ["derive"], optional = true}
memchr = "2.0" memchr = "2.0"
@ -31,4 +31,4 @@ lto = true
[lib] [lib]
name = "maraiah" name = "maraiah"
path = "source/lib.rs" path = "maraiah/lib.rs"

View File

@ -926,8 +926,9 @@ Random Sound is 32 bytes.
### Media Data ### ### Media Data ###
Media Data is 32 bytes. "Media" refers to liquids, presumably because of the Media Data is 32 bytes. "Media" refers to liquids, presumably because of the
plural of the definition of "medium," a "middle place or degree," as in, it's a plural of the definition of "medium," a "material which waves pass through," in
part of the map in the middle of a wall. this case liquid. (This is likely the case of whoever programmed this system
learning physics before rendering, or conflating the two.)
| Name | Type | Offset | | Name | Type | Offset |
| ---- | ---- | ------ | | ---- | ---- | ------ |

14
leela/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "maraiah-leela"
version = "0.0.0"
edition = "2018"
[dependencies]
clap = "2"
maraiah = {path = "..", features = ["serde_obj"]}
serde = "1.0"
serde_yaml = "0.8"
[[bin]]
name = "leela"
path = "main.rs"

View File

@ -1,13 +1,13 @@
#![allow(clippy::unit_arg)] #![allow(clippy::unit_arg)]
use maraiah::{err::*, file::*, image::*, sound::*, use maraiah::{err::*, file::*, image::*, machdr, map, shp, snd, sound::*};
machdr, map, ppm, shp, snd, tga, wav};
use std::{collections::HashSet, fs, io, slice::from_ref}; use std::{collections::HashSet, fs, io, slice::from_ref};
fn open(path: &str) -> ResultS<memmap::Mmap> /*
fn open(path: &str) -> ResultS<io::BufReader>
{ {
let fp = fs::File::open(path)?; let fp = fs::File::open(path)?;
Ok(unsafe {memmap::Mmap::map(&fp)?}) Ok(io::BufReader::new(fp))
} }
fn file_read<T, F>(path: &str, f: F) -> ResultS<T> fn file_read<T, F>(path: &str, f: F) -> ResultS<T>
@ -22,14 +22,15 @@ fn file_read<T, F>(path: &str, f: F) -> ResultS<T>
fn exists(path: String) -> Result<(), String> fn exists(path: String) -> Result<(), String>
{ {
match std::fs::metadata(path) { match std::fs::metadata(path) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(e) => Err(e.to_string()), Err(e) => Err(e.to_string()),
} }
} }
fn each_value<F>(opt: &clap::ArgMatches<'_>, fn each_value<F>(opt: &clap::ArgMatches<'_>,
name: &str, name: &str,
mut f: F) -> ResultS<()> mut f: F)
-> ResultS<()>
where F: FnMut(&str) -> ResultS<()> where F: FnMut(&str) -> ResultS<()>
{ {
if let Some(values) = opt.values_of(name) { if let Some(values) = opt.values_of(name) {
@ -91,43 +92,60 @@ fn sub_info_c(opt: &clap::ArgMatches<'_>) -> ResultS<()>
Ok(()) Ok(())
} }
*/
fn main() -> ResultS<()> fn main() -> ResultS<()>
{ {
use std::io::prelude::*;
let inp = include_bytes!("../tests/data/map/Test.in");
let mut rd = std::io::BufReader::new(&inp[..]);
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
let ed = map::data::read_all(mp.head(), &en).unwrap();
write!(&mut std::fs::File::create("dicks.txt").unwrap(), "{:#?}", ed);
/*
use clap::clap_app; use clap::clap_app;
let sub_data = let sub_data = clap_app! {
clap_app!(@subcommand data => @subcommand data =>
(about: "Dumps data into a discrete folder/YAML format")); (about: "Dumps data into a discrete folder/YAML format")
};
let sub_dump = let sub_dump = clap_app! {
clap_app!(@subcommand dump => @subcommand dump =>
(about: "Dumps particular parts of data") (about: "Dumps particular parts of data")
(@arg chunks: -c --chunks [name]... "Dumps named chunks from an entry") (@arg chunks: -c --chunks [name]... "Dumps named chunks from an entry")
(@group files => (@group files =>
(@attributes +required +multiple) (@attributes +required +multiple)
(@arg map: -m --map [file]... {exists} "Loads Map files") (@arg map: -m --map [file]... {exists} "Loads Map files")
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files") (@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))); (@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
};
let sub_info = let sub_info = clap_app! {
clap_app!(@subcommand info => @subcommand info =>
(about: "Outputs debug info") (about: "Outputs debug info")
(@group files => (@group files =>
(@attributes +required +multiple) (@attributes +required +multiple)
(@arg map: -m --map [file]... {exists} "Loads Map files") (@arg map: -m --map [file]... {exists} "Loads Map files")
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files") (@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))); (@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
};
let opt = let opt = clap_app! {
clap_app!((env!("CARGO_PKG_NAME")) => (env!("CARGO_PKG_NAME")) =>
(version: env!("CARGO_PKG_VERSION")) (version: maraiah::meta::version())
(author: env!("CARGO_PKG_AUTHORS")) (author: maraiah::meta::authors().replace(':', ", "))
(about: env!("CARGO_PKG_DESCRIPTION")) (about: maraiah::meta::description())
(setting: clap::AppSettings::SubcommandRequiredElseHelp) (setting: clap::AppSettings::SubcommandRequiredElseHelp)
(subcommand: sub_data) (subcommand: sub_data)
(subcommand: sub_dump) (subcommand: sub_dump)
(subcommand: sub_info)); (subcommand: sub_info)
};
let opt = opt.get_matches(); let opt = opt.get_matches();
@ -137,6 +155,7 @@ fn main() -> ResultS<()>
("info", Some(opt)) => sub_info_c(opt)?, ("info", Some(opt)) => sub_info_c(opt)?,
_ => unreachable!(), _ => unreachable!(),
} }
*/
Ok(()) Ok(())
} }

View File

@ -6,98 +6,133 @@ use std::{convert::{TryFrom, TryInto}, fmt, num::NonZeroU16};
#[doc(hidden)] #[doc(hidden)]
#[macro_export] #[macro_export]
macro_rules! rd_impl { macro_rules! rd_impl {
// worker - creates let statement // worker, creates let statement for 16 bit numbers
(W $b:expr, $pth:path, $nam:ident, $n:expr) => { (W $b:expr, $pth:path, $nam:ident, $n:expr) => {
let $nam = $pth([$b[$n], $b[$n + 1]]); let $nam = $pth([$b[$n], $b[$n + 1]]);
}; };
// worker, creates let statement for 32 bit numbers
(D $b:expr, $pth:path, $nam:ident, $n:expr) => { (D $b:expr, $pth:path, $nam:ident, $n:expr) => {
let $nam = $pth([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]); let $nam = $pth([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]);
}; };
// big endian // big endian, u16
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => { (BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
$crate::rd_impl!(W $b, u16::from_be_bytes, $nam, $n + $at); $crate::rd_impl!(W $b, u16::from_be_bytes, $nam, $n + $at);
}; };
// big endian, i16
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => { (BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
$crate::rd_impl!(W $b, i16::from_be_bytes, $nam, $n + $at); $crate::rd_impl!(W $b, i16::from_be_bytes, $nam, $n + $at);
}; };
// big endian, u32
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => { (BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
$crate::rd_impl!(D $b, u32::from_be_bytes, $nam, $n + $at); $crate::rd_impl!(D $b, u32::from_be_bytes, $nam, $n + $at);
}; };
// big endian, i32
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => { (BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
$crate::rd_impl!(D $b, i32::from_be_bytes, $nam, $n + $at); $crate::rd_impl!(D $b, i32::from_be_bytes, $nam, $n + $at);
}; };
// little endian // little endian, u16
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => { (LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
$crate::rd_impl!(W $b, u16::from_le_bytes, $nam, $n + $at); $crate::rd_impl!(W $b, u16::from_le_bytes, $nam, $n + $at);
}; };
// little endian, i16
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => { (LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
$crate::rd_impl!(W $b, i16::from_le_bytes, $nam, $n + $at); $crate::rd_impl!(W $b, i16::from_le_bytes, $nam, $n + $at);
}; };
// little endian, u32
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => { (LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
$crate::rd_impl!(D $b, u32::from_le_bytes, $nam, $n + $at); $crate::rd_impl!(D $b, u32::from_le_bytes, $nam, $n + $at);
}; };
// little endian, i32
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => { (LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
$crate::rd_impl!(D $b, i32::from_le_bytes, $nam, $n + $at); $crate::rd_impl!(D $b, i32::from_le_bytes, $nam, $n + $at);
}; };
// either endianness // either endianness, Angle
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Angle) => { ($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Angle) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16); $crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = Angle::from_bits($nam); let $nam = $crate::fixed::Angle::from_bits($nam);
}; };
// either endianness, Fixed
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Fixed) => { ($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Fixed) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u32); $crate::rd_impl!($e, $b, $at, $n; $nam, u32);
let $nam = Fixed::from_bits($nam); let $nam = $crate::fixed::Fixed::from_bits($nam);
}; };
// either endianness, Unit
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Unit) => { ($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Unit) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16); $crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = Unit::from_bits($nam); let $nam = $crate::fixed::Unit::from_bits($nam);
}; };
// either endianness, OptU16
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, OptU16) => { ($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, OptU16) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16); $crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = OptU16::from($nam); let $nam = $crate::bin::OptU16::from($nam);
}; };
// either endianness, u16 -> usize
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u16) => { ($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u16) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16); $crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = usize::from($nam); let $nam = usize::from($nam);
}; };
// either endianness, u32 -> usize
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u32) => { ($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u32) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u32); $crate::rd_impl!($e, $b, $at, $n; $nam, u32);
let $nam = usize_from_u32($nam); let $nam = $crate::bin::usize_from_u32($nam);
}; };
// either endianness, enum type with TryFrom
($e:ident, $b:expr, $at:expr, $n:expr; ($e:ident, $b:expr, $at:expr, $n:expr;
$nam:ident, enum, $et:ident$(::$etc:ident)*, $t:ident $nam:ident, enum, $et:ident$(::$etc:ident)*, $t:ident) => {
) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, $t); $crate::rd_impl!($e, $b, $at, $n; $nam, $t);
let $nam = $et$(::$etc)*::try_from($nam)?; let $nam: $et$(::$etc)* = std::convert::TryFrom::try_from($nam)?;
}; };
// either endianness, bitflag type
($e:ident, $b:expr, $at:expr, $n:expr; ($e:ident, $b:expr, $at:expr, $n:expr;
$nam:ident, flag, $ft:ident$(::$ftc:ident)*, $t:ident $nam:ident, flag, $ft:ident$(::$ftc:ident)*, $t:ident) => {
) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, $t); $crate::rd_impl!($e, $b, $at, $n; $nam, $t);
let $nam = flag_ok!($ft$(::$ftc)*, $nam)?; let $nam = flag_ok!($ft$(::$ftc)*, $nam)?;
}; };
// no endianness // no endianness, u8
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, u8) => { ($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, u8) => {
let $nam = $b[$n + $at]; let $nam = $b[$n + $at];
}; };
// no endianness, i8
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, i8) => { ($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, i8) => {
let $nam = $b[$n + $at] as i8; let $nam = $b[$n + $at] as i8;
}; };
// no endianness, [u8]
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, u8) => { ($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, u8) => {
let $nam = &$b[$n + $at..$n + $at + $rn]; let $nam = &$b[$n + $at..$n + $at + $rn];
}; };
// no endianness, Ident
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Ident) => { ($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Ident) => {
$crate::rd_impl!(D $b, Ident, $nam, $n + $at); $crate::rd_impl!(D $b, Ident, $nam, $n + $at);
}; };
// no endianness, fn([u8]) -> T
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; ($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr;
$nam:ident, no_try, $f:expr $nam:ident, no_try, $f:expr) => {
) => {
let $nam = $f(&$b[$n + $at..$n + $at + $rn]); let $nam = $f(&$b[$n + $at..$n + $at + $rn]);
}; };
// no endianness, fn([u8]) -> Result<T>
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, $f:expr) => { ($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, $f:expr) => {
let $nam = $f(&$b[$n + $at..$n + $at + $rn])?; let $nam = $f(&$b[$n + $at..$n + $at + $rn])?;
}; };
@ -524,7 +559,7 @@ impl OptU16
} }
} }
impl fmt::Debug for OptU16 impl fmt::Display for OptU16
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{ {
@ -535,6 +570,17 @@ impl fmt::Debug for OptU16
} }
} }
impl fmt::Debug for OptU16
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self.get() {
None => write!(f, "OptU16::none()"),
Some(n) => write!(f, "OptU16::from({})", n),
}
}
}
impl PartialEq<[u8; 4]> for Ident impl PartialEq<[u8; 4]> for Ident
{ {
#[inline] #[inline]

View File

@ -16,7 +16,6 @@
/// use std::convert::TryFrom; /// use std::convert::TryFrom;
/// ///
/// c_enum! { /// c_enum! {
/// #[derive(Debug)]
/// enum MyEnum: u16 /// enum MyEnum: u16
/// { /// {
/// Zero = 0, /// Zero = 0,
@ -43,7 +42,7 @@ macro_rules! c_enum
} }
) => { ) => {
$(#[$outer])* $(#[$outer])*
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)] #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr($ti)] #[repr($ti)]
$vi enum $t $vi enum $t
{ {
@ -74,7 +73,6 @@ mod test
use std::convert::TryFrom; use std::convert::TryFrom;
c_enum! { c_enum! {
#[derive(Debug)]
enum TestEnum: u16 enum TestEnum: u16
{ {
Zero = 0, Zero = 0,

View File

@ -8,7 +8,7 @@ macro_rules! ok {
($v:expr, $msg:expr) => { ($v:expr, $msg:expr) => {
match $v { match $v {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(err_msg($msg)), None => Err($crate::err::err_msg($msg)),
} }
}; };
} }
@ -17,14 +17,14 @@ macro_rules! flag_ok {
($t:ident$(::$tc:ident)*, $v:expr) => { ($t:ident$(::$tc:ident)*, $v:expr) => {
match $t$(::$tc)*::from_bits($v) { match $t$(::$tc)*::from_bits($v) {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(err_msg(concat!("bad ", stringify!($t)))), None => Err($crate::err::err_msg(concat!("bad ", stringify!($t)))),
} }
}; };
} }
macro_rules! bail { macro_rules! bail {
($e:expr) => { ($e:expr) => {
return Err(err_msg($e)); return Err($crate::err::err_msg($e));
}; };
} }

View File

@ -588,7 +588,9 @@ macro_rules! define_fixed_types {
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{ {
fmt::Display::fmt(self, f) write!(f,
concat!(stringify!($t), "::from_bits({})"),
self.to_bits())
} }
} }
)*}; )*};

View File

@ -1,7 +1,6 @@
//! QuickDraw PICT `PixMap` headers. //! QuickDraw PICT `PixMap` headers.
use crate::{bin::*, err::*, image::*}; use crate::{bin::*, err::*, image::*};
use std::convert::TryFrom;
/// Reads a `PixMap` header. /// Reads a `PixMap` header.
pub fn read<'a>(b: &'a [u8], pub fn read<'a>(b: &'a [u8],

39
maraiah/map.rs Normal file
View File

@ -0,0 +1,39 @@
//! Marathon Map format handling.
pub mod ambi;
pub mod attk;
pub mod bonk;
pub mod damg;
pub mod data;
pub mod entr;
pub mod epnt;
pub mod fxpx;
pub mod head;
pub mod iidx;
pub mod lins;
pub mod lite;
pub mod ltfn;
pub mod medi;
pub mod minf;
pub mod mnpx;
pub mod name;
pub mod note;
pub mod objs;
pub mod plac;
pub mod plat;
pub mod pnts;
pub mod poly;
pub mod prpx;
pub mod pxpx;
pub mod sids;
pub mod stex;
pub mod term;
pub mod trig;
pub mod trmf;
pub mod trmg;
pub mod wppx;
/// The number of game ticks per second.
pub const TICKS_PER_SECOND: u16 = 30;
// EOF

View File

@ -17,7 +17,7 @@ pub fn read(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
/// An ambient sound definition. /// An ambient sound definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct SoundAmbi pub struct SoundAmbi
{ {
pub index: u16, pub index: u16,

View File

@ -27,7 +27,7 @@ pub fn read(b: &[u8]) -> ResultS<(SoundRand, usize)>
/// A randomly played sound definition. /// A randomly played sound definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct SoundRand pub struct SoundRand
{ {
pub flags: SoundRandFlags, pub flags: SoundRandFlags,

View File

@ -2,7 +2,6 @@
use crate::{err::*, fixed::Fixed}; use crate::{err::*, fixed::Fixed};
use bitflags::bitflags; use bitflags::bitflags;
use std::convert::TryFrom;
/// Reads a `Damage` object. /// Reads a `Damage` object.
pub fn read(b: &[u8]) -> ResultS<Damage> pub fn read(b: &[u8]) -> ResultS<Damage>
@ -76,7 +75,6 @@ bitflags! {
c_enum! { c_enum! {
/// A named type of damage taken by something. /// A named type of damage taken by something.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum DamageType: u16 pub enum DamageType: u16
{ {
Explosion = 0, Explosion = 0,

114
maraiah/map/data.rs Normal file
View File

@ -0,0 +1,114 @@
//! Map file entry data.
use crate::{bin::*, err::*, image::{self, pict}, map};
use super::{entr, head};
use std::collections::BTreeMap;
/// Reads all chunks in an entry.
pub fn read(head: &head::Header, b: &[u8]) -> ResultS<EntryData>
{
let mut data = EntryData::default();
let old = head.old_data();
let rd_cminf = if old {map::minf::read_old} else {map::minf::read};
let rd_csids = if old {map::sids::read_old} else {map::sids::read};
let rd_cpoly = if old {map::poly::read_old} else {map::poly::read};
let rd_clite = if old {map::lite::read_old} else {map::lite::read};
let mut p = 0;
while p < b.len() {
read_data! {
endian: BIG, buf: b, size: head.size_chunk(), start: p, data {
let iden = Ident[0];
let size = u32[8] usize;
}
}
let beg = p + head.size_chunk();
let end = beg + size;
let buf = ok!(b.get(beg..end), "not enough data")?;
match &iden.0 {
b"EPNT" => data.epnt = Some(rd_array(buf, map::epnt::read)?),
b"FXpx" => data.fxpx = Some(rd_array(buf, map::fxpx::read)?),
b"LINS" => data.lins = Some(rd_array(buf, map::lins::read)?),
b"LITE" => data.lite = Some(rd_array(buf, rd_clite)?),
b"MNpx" => data.mnpx = Some(rd_array(buf, map::mnpx::read)?),
b"Minf" => data.minf = Some(rd_cminf(buf)?),
b"NAME" => data.name = Some(rd_array(buf, map::name::read)?),
b"NOTE" => data.note = Some(rd_array(buf, map::note::read)?),
b"OBJS" => data.objs = Some(rd_array(buf, map::objs::read)?),
b"PICT" => data.pict = Some(pict::read(buf)?),
b"PNTS" => data.pnts = Some(rd_array(buf, map::pnts::read)?),
b"POLY" => data.poly = Some(rd_array(buf, rd_cpoly)?),
b"PRpx" => data.prpx = Some(rd_array(buf, map::prpx::read)?),
b"PXpx" => data.pxpx = Some(rd_array(buf, map::pxpx::read)?),
b"SIDS" => data.sids = Some(rd_array(buf, rd_csids)?),
b"WPpx" => data.wppx = Some(rd_array(buf, map::wppx::read)?),
b"ambi" => data.ambi = Some(rd_array(buf, map::ambi::read)?),
b"bonk" => data.bonk = Some(rd_array(buf, map::bonk::read)?),
b"iidx" => data.iidx = Some(rd_array(buf, map::iidx::read)?),
b"medi" => data.medi = Some(rd_array(buf, map::medi::read)?),
b"plac" => data.plac = Some(rd_array(buf, map::plac::read)?),
b"plat" => data.plat = Some(rd_array(buf, map::plat::read)?),
b"term" => data.term = Some(rd_array(buf, map::term::read)?),
_ => data.unkn.push((iden, buf.to_vec())),
}
p = end;
}
Ok(data)
}
/// Reads all of the data from an entry map.
pub fn read_all(head: &head::Header,
map: &entr::EntryMap<'_>) -> ResultS<EntryDataMap>
{
let mut dmap = EntryDataMap::new();
for (&index, entry) in map {
dmap.insert(index, read(head, &entry.data)?);
}
Ok(dmap)
}
/// The loaded data of a Map file entry.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Default, Eq, PartialEq)]
pub struct EntryData
{
/** `EPNT` chunk data. */ pub epnt: Option<Vec<map::epnt::Endpoint>>,
/** `FXpx` chunk data. */ pub fxpx: Option<Vec<map::fxpx::Effect>>,
/** `LINS` chunk data. */ pub lins: Option<Vec<map::lins::Line>>,
/** `LITE` chunk data. */ pub lite: Option<Vec<map::lite::Light>>,
/** `MNpx` chunk data. */ pub mnpx: Option<Vec<map::mnpx::Monster>>,
/** `Minf` chunk data. */ pub minf: Option<map::minf::Info>,
/** `NAME` chunk data. */ pub name: Option<Vec<String>>,
/** `NOTE` chunk data. */ pub note: Option<Vec<map::note::Note>>,
/** `OBJS` chunk data. */ pub objs: Option<Vec<map::objs::Object>>,
/** `PICT` chunk data. */ pub pict: Option<image::Image8>,
/** `PNTS` chunk data. */ pub pnts: Option<Vec<map::pnts::Point>>,
/** `POLY` chunk data. */ pub poly: Option<Vec<map::poly::Polygon>>,
/** `PRpx` chunk data. */ pub prpx: Option<Vec<map::prpx::Projectile>>,
/** `PXpx` chunk data. */ pub pxpx: Option<Vec<map::pxpx::Physics>>,
/** `SIDS` chunk data. */ pub sids: Option<Vec<map::sids::Side>>,
/** `WPpx` chunk data. */ pub wppx: Option<Vec<map::wppx::Weapon>>,
/** `ambi` chunk data. */ pub ambi: Option<Vec<map::ambi::SoundAmbi>>,
/** `bonk` chunk data. */ pub bonk: Option<Vec<map::bonk::SoundRand>>,
/** `iidx` chunk data. */ pub iidx: Option<Vec<u16>>,
/** `medi` chunk data. */ pub medi: Option<Vec<map::medi::Media>>,
/** `plac` chunk data. */ pub plac: Option<Vec<map::plac::ObjectFreq>>,
/** `plat` chunk data. */ pub plat: Option<Vec<map::plat::Platform>>,
/** `term` chunk data. */ pub term: Option<Vec<map::term::Terminal>>,
pub unkn: Vec<(Ident, Vec<u8>)>,
}
/// A map of indexed entries.
pub type EntryDataMap = BTreeMap<u16, EntryData>;
// EOF

60
maraiah/map/entr.rs Normal file
View File

@ -0,0 +1,60 @@
//! Map file entry type.
use crate::err::*;
use super::head;
use std::collections::BTreeMap;
/// Read an entry from a Map file.
pub fn read(map: &head::Map, i: usize) -> ResultS<(u16, Entry<'_>)>
{
let size = map.head().size_entry();
read_data! {
endian: BIG, buf: map.dir(), size: size, start: size * i, data {
let offset = u32[0] usize;
let dsize = u32[4] usize;
let index = u16[8];
let app_data = u8[10; map.head().size_appl()];
}
}
let data = &map.data()[offset..offset + dsize];
let index = if map.head().old_wad() {i as u16} else {index};
Ok((index, Entry{data, app_data}))
}
/// Reads all entries in a Map file.
pub fn read_all(map: &head::Map) -> ResultS<EntryMap<'_>>
{
let mut entries = EntryMap::new();
for i in 0..map.num_ent() {
let (index, entry) = read(map, i)?;
if entries.contains_key(&index) {
bail!("entry index already exists");
}
entries.insert(index, entry);
}
Ok(entries)
}
/// An entry containing chunked data and application-specific data.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Entry<'a>
{
/// The data in this `Entry`.
pub data: &'a [u8],
/// The application specific data for this Entry.
pub app_data: &'a [u8],
}
/// A map of indexed entries.
pub type EntryMap<'a> = BTreeMap<u16, Entry<'a>>;
// EOF

147
maraiah/map/head.rs Normal file
View File

@ -0,0 +1,147 @@
//! Map file header.
use crate::{err::*, text::mac_roman_cstr};
use std::io::prelude::*;
/// Reads a Map file.
pub fn read(rd: &mut impl Read) -> ResultS<Map>
{
let mut data = Vec::new();
rd.read_to_end(&mut data)?;
read_data! {
endian: BIG, buf: &data, size: 128, start: 0, data {
let ver_wad = u16[0] enum Ver;
let ver_data = u16[2];
let name = mac_roman_cstr[4; 64] no_try;
let dir_ofs = u32[72] usize;
let num_ent = u16[76] usize;
let size_appl = u16[78] usize;
let size_wcnk = u16[80] usize;
let size_went = u16[82] usize;
}
}
let head = Header::new(size_appl, ver_data, ver_wad, Some(name));
if !head.old_wad() && head.size_entry_base() != size_went {
bail!("invalid entry size");
}
if !head.old_wad() && head.size_chunk() != size_wcnk {
bail!("invalid chunk size");
}
let map = Map{head, data, dir_ofs, num_ent};
if map.dir_end() > map.data.len() {
bail!("not enough data in map file");
}
Ok(map)
}
impl Header
{
/// Creates a new `Header`.
pub fn new(size_appl: usize,
ver_data: u16,
ver_wad: Ver,
name: Option<String>) -> Self
{
let name = name.unwrap_or(String::new());
Header{name, size_appl, ver_data, ver_wad}
}
/// Returns `true` if the data is in Marathon 1 format.
#[inline]
pub fn old_data(&self) -> bool {self.ver_data() == 0}
/// Returns `true` if the Map file is in Marathon 1 format.
#[inline]
pub fn old_wad(&self) -> bool {self.ver_wad() == Ver::Base}
/// The data version of this file.
#[inline]
pub const fn ver_data(&self) -> u16 {self.ver_data}
/// The format version of this file.
#[inline]
pub const fn ver_wad(&self) -> Ver {self.ver_wad}
/// The size of each `Entry`'s `appdata` field.
#[inline]
pub const fn size_appl(&self) -> usize {self.size_appl}
/// The size of each `Entry`'s data.
#[inline]
pub fn size_entry_base(&self) -> usize {if self.old_wad() {8} else {10}}
/// The size of each `Entry`.
#[inline]
pub fn size_entry(&self) -> usize {self.size_entry_base() + self.size_appl()}
/// The size of each chunk's header.
#[inline]
pub fn size_chunk(&self) -> usize {if self.old_wad() {12} else {16}}
}
impl Map
{
/// The header for this map.
pub fn head(&self) -> &Header {&self.head}
/// The data section of this map.
pub fn data(&self) -> &[u8] {&self.data[..]}
/// The directory section of this map.
pub fn dir(&self) -> &[u8] {&self.data[self.dir_beg()..self.dir_end()]}
/// The number of entries in the directory.
pub fn num_ent(&self) -> usize {self.num_ent}
fn dir_beg(&self) -> usize {self.dir_ofs}
fn dir_end(&self) -> usize
{
self.dir_ofs + self.head.size_entry() * self.num_ent
}
}
/// A Map header.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Header
{
/// The original name of this file.
pub name: String,
size_appl: usize,
ver_data: u16,
ver_wad: Ver,
}
/// A Map file.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Map
{
head: Header,
data: Vec<u8>,
dir_ofs: usize,
num_ent: usize,
}
c_enum! {
/// The version of a Map file.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum Ver: u16
{
Base = 0,
Dir = 1,
Over = 2,
Inf = 4,
}
}
// EOF

View File

@ -23,7 +23,7 @@ pub fn read(b: &[u8]) -> ResultS<(Line, usize)>
/// A line segment. /// A line segment.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Line pub struct Line
{ {
pub flags: LineFlags, pub flags: LineFlags,

View File

@ -3,7 +3,6 @@
use super::{ltfn, TICKS_PER_SECOND}; use super::{ltfn, TICKS_PER_SECOND};
use crate::{err::*, fixed::Fixed}; use crate::{err::*, fixed::Fixed};
use bitflags::bitflags; use bitflags::bitflags;
use std::convert::TryFrom;
/// Reads a `LITE` chunk. /// Reads a `LITE` chunk.
pub fn read(b: &[u8]) -> ResultS<(Light, usize)> pub fn read(b: &[u8]) -> ResultS<(Light, usize)>
@ -73,7 +72,7 @@ pub fn read_old(b: &[u8]) -> ResultS<(Light, usize)>
/// A dynamic polygon light. /// A dynamic polygon light.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Light pub struct Light
{ {
pub ltype: LightType, pub ltype: LightType,
@ -102,7 +101,6 @@ bitflags! {
c_enum! { c_enum! {
/// The type of a `Light`. /// The type of a `Light`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum LightType: u16 pub enum LightType: u16
{ {
Normal = 0, Normal = 0,

View File

@ -1,7 +1,6 @@
//! `LightFunc` type. //! `LightFunc` type.
use crate::{err::*, fixed::Fixed}; use crate::{err::*, fixed::Fixed};
use std::convert::TryFrom;
/// Reads a `LightFunc` object. /// Reads a `LightFunc` object.
pub fn read(b: &[u8]) -> ResultS<LightFunc> pub fn read(b: &[u8]) -> ResultS<LightFunc>
@ -33,7 +32,7 @@ pub fn write(v: &LightFunc) -> Vec<u8>
/// A light function. /// A light function.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct LightFunc pub struct LightFunc
{ {
pub ftype: LightFuncType, pub ftype: LightFuncType,
@ -46,7 +45,6 @@ pub struct LightFunc
c_enum! { c_enum! {
/// The type of function for a `LightFunc`. /// The type of function for a `LightFunc`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum LightFuncType: u16 pub enum LightFuncType: u16
{ {
Constant = 0, Constant = 0,

View File

@ -6,7 +6,6 @@ use crate::{bin::OptU16,
fixed::{Angle, Fixed, Unit}, fixed::{Angle, Fixed, Unit},
xfer::TransferMode}; xfer::TransferMode};
use bitflags::bitflags; use bitflags::bitflags;
use std::convert::TryFrom;
/// Reads a `medi` chunk. /// Reads a `medi` chunk.
pub fn read(b: &[u8]) -> ResultS<(Media, usize)> pub fn read(b: &[u8]) -> ResultS<(Media, usize)>
@ -34,7 +33,7 @@ pub fn read(b: &[u8]) -> ResultS<(Media, usize)>
/// A media, as in a part of a polygon which goes up the middle of the wall. /// A media, as in a part of a polygon which goes up the middle of the wall.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Media pub struct Media
{ {
pub mtype: MediaType, pub mtype: MediaType,
@ -54,7 +53,6 @@ pub struct Media
c_enum! { c_enum! {
/// The liquid type of a `Media`. /// The liquid type of a `Media`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum MediaType: u16 pub enum MediaType: u16
{ {
Water = 0, Water = 0,

View File

@ -11,10 +11,10 @@ pub fn read(b: &[u8]) -> ResultS<Info>
let texture_id = u16[0]; let texture_id = u16[0];
let physics_id = u16[2]; let physics_id = u16[2];
let skypict_id = u16[4]; let skypict_id = u16[4];
let miss_flags = u16[6] flag MsnFlags; let miss_flags = u16[6] flag MissionFlags;
let envi_flags = u16[8] flag EnvFlags; let envi_flags = u16[8] flag EnvironmentFlags;
let level_name = mac_roman_cstr[18; 66] no_try; let level_name = mac_roman_cstr[18; 66] no_try;
let entr_flags = u32[84] flag EntFlags; let entr_flags = u32[84] flag EntryFlags;
} }
} }
@ -42,13 +42,13 @@ pub fn read_old(b: &[u8]) -> ResultS<Info>
let minf = read(b)?; let minf = read(b)?;
let mut entr_flags = if minf.entr_flags.is_empty() { let mut entr_flags = if minf.entr_flags.is_empty() {
EntFlags::SOLO EntryFlags::SOLO
} else { } else {
minf.entr_flags minf.entr_flags
}; };
if entr_flags.intersects(EntFlags::SOLO | EntFlags::CARNAGE) { if entr_flags.intersects(EntryFlags::SOLO | EntryFlags::CARNAGE) {
entr_flags.insert(EntFlags::CO_OP) entr_flags.insert(EntryFlags::CO_OP)
} }
Ok(Info{entr_flags, ..minf}) Ok(Info{entr_flags, ..minf})
@ -61,9 +61,9 @@ impl Default for Info
Self{texture_id: 0, Self{texture_id: 0,
physics_id: 1, physics_id: 1,
skypict_id: 0, skypict_id: 0,
miss_flags: MsnFlags::empty(), miss_flags: MissionFlags::empty(),
envi_flags: EnvFlags::empty(), envi_flags: EnvironmentFlags::empty(),
entr_flags: EntFlags::SOLO, entr_flags: EntryFlags::SOLO,
level_name: "Map".to_string()} level_name: "Map".to_string()}
} }
} }
@ -76,16 +76,16 @@ pub struct Info
pub texture_id: u16, pub texture_id: u16,
pub physics_id: u16, pub physics_id: u16,
pub skypict_id: u16, pub skypict_id: u16,
pub miss_flags: MsnFlags, pub miss_flags: MissionFlags,
pub envi_flags: EnvFlags, pub envi_flags: EnvironmentFlags,
pub entr_flags: EntFlags, pub entr_flags: EntryFlags,
pub level_name: String, pub level_name: String,
} }
bitflags! { bitflags! {
/// Static environment flags. /// Static environment flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EnvFlags: u16 pub struct EnvironmentFlags: u16
{ {
const VACUUM = 1; const VACUUM = 1;
const MAGNETIC = 1 << 1; const MAGNETIC = 1 << 1;
@ -104,7 +104,7 @@ bitflags! {
bitflags! { bitflags! {
/// Static entry point flags. /// Static entry point flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EntFlags: u32 pub struct EntryFlags: u32
{ {
const SOLO = 1; const SOLO = 1;
const CO_OP = 1 << 1; const CO_OP = 1 << 1;
@ -120,7 +120,7 @@ bitflags! {
bitflags! { bitflags! {
/// Static mission flags. /// Static mission flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MsnFlags: u16 pub struct MissionFlags: u16
{ {
const EXTERMINATION = 1; const EXTERMINATION = 1;
const EXPLORATION = 1 << 1; const EXPLORATION = 1 << 1;

View File

@ -19,7 +19,7 @@ pub fn read(b: &[u8]) -> ResultS<(Note, usize)>
/// Overhead map annotations. /// Overhead map annotations.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Note pub struct Note
{ {
pub pos: pnts::Point, pub pos: pnts::Point,

View File

@ -29,7 +29,7 @@ pub fn read(b: &[u8]) -> ResultS<(Object, usize)>
/// An object in the world. /// An object in the world.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Object pub struct Object
{ {
pub group: u16, pub group: u16,

View File

@ -22,7 +22,7 @@ pub fn read(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
/// The difficulty definition for various object types. /// The difficulty definition for various object types.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct ObjectFreq pub struct ObjectFreq
{ {
pub flags: ObjectFreqFlags, pub flags: ObjectFreqFlags,

View File

@ -24,7 +24,7 @@ pub fn read(b: &[u8]) -> ResultS<(Platform, usize)>
/// Extra information for polygons with platforms. /// Extra information for polygons with platforms.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Platform pub struct Platform
{ {
pub ptype: u16, pub ptype: u16,

View File

@ -3,7 +3,6 @@
use super::pnts; use super::pnts;
use crate::{bin::OptU16, err::*, fixed::Unit, xfer::TransferMode}; use crate::{bin::OptU16, err::*, fixed::Unit, xfer::TransferMode};
use bitflags::bitflags; use bitflags::bitflags;
use std::convert::TryFrom;
/// Reads a polygon for either M1 or M2. /// Reads a polygon for either M1 or M2.
pub fn read_poly_inter(b: &[u8]) -> ResultS<Polygon> pub fn read_poly_inter(b: &[u8]) -> ResultS<Polygon>
@ -43,7 +42,7 @@ pub fn read(b: &[u8]) -> ResultS<(Polygon, usize)>
} }
let poly = read_poly_inter(b)?; let poly = read_poly_inter(b)?;
let ptype = PolyType::new(ptype, pdata)?; let ptype = PolygonType::new(ptype, pdata)?;
Ok((Polygon{ptype, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb, Ok((Polygon{ptype, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb,
snd_rnd, ..poly}, 128)) snd_rnd, ..poly}, 128))
@ -60,81 +59,81 @@ pub fn read_old(b: &[u8]) -> ResultS<(Polygon, usize)>
} }
let poly = read_poly_inter(b)?; let poly = read_poly_inter(b)?;
let ptype = PolyType::new_old(ptype, pdata)?; let ptype = PolygonType::new_old(ptype, pdata)?;
Ok((Polygon{ptype, ..poly}, 128)) Ok((Polygon{ptype, ..poly}, 128))
} }
impl PolyType impl PolygonType
{ {
/// Creates a `PolyType` from a `n`/`pdata` pair. /// Creates a `PolygonType` from a `n`/`pdata` pair.
pub fn new(n: u16, pdata: u16) -> Result<Self, ReprError> pub fn new(n: u16, pdata: u16) -> Result<Self, ReprError>
{ {
match n { match n {
0 => Ok(PolyType::Normal), 0 => Ok(PolygonType::Normal),
1 => Ok(PolyType::ImpassItem), 1 => Ok(PolygonType::ImpassItem),
2 => Ok(PolyType::ImpassMons), 2 => Ok(PolygonType::ImpassMons),
3 => Ok(PolyType::Hill), 3 => Ok(PolygonType::Hill),
4 => Ok(PolyType::Base), 4 => Ok(PolygonType::Base),
5 => Ok(PolyType::Platform(pdata)), 5 => Ok(PolygonType::Platform(pdata)),
6 => Ok(PolyType::TrigLightOn(pdata)), 6 => Ok(PolygonType::TrigLightOn(pdata)),
7 => Ok(PolyType::TrigPlatOn(pdata)), 7 => Ok(PolygonType::TrigPlatOn(pdata)),
8 => Ok(PolyType::TrigLightOff(pdata)), 8 => Ok(PolygonType::TrigLightOff(pdata)),
9 => Ok(PolyType::TrigPlatOff(pdata)), 9 => Ok(PolygonType::TrigPlatOff(pdata)),
10 => Ok(PolyType::Teleporter(pdata)), 10 => Ok(PolygonType::Teleporter(pdata)),
11 => Ok(PolyType::ZoneBorder), 11 => Ok(PolygonType::ZoneBorder),
12 => Ok(PolyType::Goal), 12 => Ok(PolygonType::Goal),
13 => Ok(PolyType::TrigMonsVis), 13 => Ok(PolygonType::TrigMonsVis),
14 => Ok(PolyType::TrigMonsInv), 14 => Ok(PolygonType::TrigMonsInv),
15 => Ok(PolyType::TrigMonsDual), 15 => Ok(PolygonType::TrigMonsDual),
16 => Ok(PolyType::TrigItems), 16 => Ok(PolygonType::TrigItems),
17 => Ok(PolyType::MustExplore), 17 => Ok(PolygonType::MustExplore),
18 => Ok(PolyType::AutoExit), 18 => Ok(PolygonType::AutoExit),
19 => Ok(PolyType::OuchMinor), 19 => Ok(PolygonType::OuchMinor),
20 => Ok(PolyType::OuchMajor), 20 => Ok(PolygonType::OuchMajor),
21 => Ok(PolyType::Glue), 21 => Ok(PolygonType::Glue),
22 => Ok(PolyType::GlueTrigger(pdata)), 22 => Ok(PolygonType::GlueTrigger(pdata)),
23 => Ok(PolyType::GlueSuper), 23 => Ok(PolygonType::GlueSuper),
n => Err(ReprError::new(n)), n => Err(ReprError::new(n)),
} }
} }
/// Creates a `PolyType` from a Marathon 1 compatible `n`/`pdata` pair. /// Creates a `PolygonType` from a Marathon 1 compatible `n`/`pdata` pair.
fn new_old(n: u16, pdata: u16) -> Result<Self, ReprError> fn new_old(n: u16, pdata: u16) -> Result<Self, ReprError>
{ {
match n { match n {
0 => Ok(PolyType::Normal), 0 => Ok(PolygonType::Normal),
1 => Ok(PolyType::ImpassItem), 1 => Ok(PolygonType::ImpassItem),
2 => Ok(PolyType::ImpassMons), 2 => Ok(PolygonType::ImpassMons),
3 => Ok(PolyType::OuchMinor), 3 => Ok(PolygonType::OuchMinor),
4 => Ok(PolyType::OuchMajor), 4 => Ok(PolygonType::OuchMajor),
5 => Ok(PolyType::Platform(pdata)), 5 => Ok(PolygonType::Platform(pdata)),
6 => Ok(PolyType::TrigLightOn(pdata)), 6 => Ok(PolygonType::TrigLightOn(pdata)),
7 => Ok(PolyType::TrigPlatOn(pdata)), 7 => Ok(PolygonType::TrigPlatOn(pdata)),
8 => Ok(PolyType::TrigLightOff(pdata)), 8 => Ok(PolygonType::TrigLightOff(pdata)),
9 => Ok(PolyType::TrigPlatOff(pdata)), 9 => Ok(PolygonType::TrigPlatOff(pdata)),
10 => Ok(PolyType::Teleporter(pdata)), 10 => Ok(PolygonType::Teleporter(pdata)),
11 => Ok(PolyType::Glue), 11 => Ok(PolygonType::Glue),
12 => Ok(PolyType::GlueTrigger(pdata)), 12 => Ok(PolygonType::GlueTrigger(pdata)),
13 => Ok(PolyType::GlueSuper), 13 => Ok(PolygonType::GlueSuper),
14 => Ok(PolyType::MustExplore), 14 => Ok(PolygonType::MustExplore),
15 => Ok(PolyType::AutoExit), 15 => Ok(PolygonType::AutoExit),
n => Err(ReprError::new(n)), n => Err(ReprError::new(n)),
} }
} }
} }
impl Default for PolyType impl Default for PolygonType
{ {
fn default() -> Self {PolyType::Normal} fn default() -> Self {PolygonType::Normal}
} }
/// A polygon segment. /// A polygon segment.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Polygon pub struct Polygon
{ {
pub ptype: PolyType, pub ptype: PolygonType,
pub tex_flr: OptU16, pub tex_flr: OptU16,
pub tex_cei: OptU16, pub tex_cei: OptU16,
pub hei_flr: Unit, pub hei_flr: Unit,
@ -154,8 +153,8 @@ pub struct Polygon
/// The action type of a `Polygon`. /// The action type of a `Polygon`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PolyType pub enum PolygonType
{ {
Normal, Normal,
ImpassItem, ImpassItem,
@ -186,7 +185,7 @@ pub enum PolyType
bitflags! { bitflags! {
/// Flags for `Polygon`. /// Flags for `Polygon`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct PolyFlags: u16 pub struct PolygonFlags: u16
{ {
const DETACHED = 1 << 14; const DETACHED = 1 << 14;
} }

View File

@ -3,7 +3,6 @@
use super::stex; use super::stex;
use crate::{bin::OptU16, err::*, fixed::Fixed, xfer::TransferMode}; use crate::{bin::OptU16, err::*, fixed::Fixed, xfer::TransferMode};
use bitflags::bitflags; use bitflags::bitflags;
use std::convert::TryFrom;
/// Reads a `SIDS` chunk. /// Reads a `SIDS` chunk.
pub fn read(b: &[u8]) -> ResultS<(Side, usize)> pub fn read(b: &[u8]) -> ResultS<(Side, usize)>
@ -41,7 +40,7 @@ pub fn read_old(b: &[u8]) -> ResultS<(Side, usize)>
/// One side of a line segment. /// One side of a line segment.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Side pub struct Side
{ {
pub stype: SideType, pub stype: SideType,
@ -76,7 +75,6 @@ bitflags! {
c_enum! { c_enum! {
/// The texture type of a `Side`. /// The texture type of a `Side`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum SideType: u16 pub enum SideType: u16
{ {
Full = 0, Full = 0,

View File

@ -27,7 +27,7 @@ pub fn write(v: &SideTex) -> Vec<u8>
/// The texture of a side segment. /// The texture of a side segment.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct SideTex pub struct SideTex
{ {
pub offs: pnts::Point, pub offs: pnts::Point,

View File

@ -1,7 +1,6 @@
//! `Monster` type. //! `Monster` type.
use crate::{bin::OptU16, err::*, fixed::Unit}; use crate::{bin::OptU16, err::*, fixed::Unit};
use std::convert::TryFrom;
/// Reads a `Trigger` object. /// Reads a `Trigger` object.
pub fn read(b: &[u8]) -> ResultS<Trigger> pub fn read(b: &[u8]) -> ResultS<Trigger>
@ -62,7 +61,6 @@ pub struct Trigger
c_enum! { c_enum! {
/// A bullet shell casing emitted by a weapon. /// A bullet shell casing emitted by a weapon.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum CasingType: u16 pub enum CasingType: u16
{ {
Rifle = 0, Rifle = 0,

View File

@ -2,7 +2,6 @@
use crate::{bin::OptU16, err::*, fixed::Fixed}; use crate::{bin::OptU16, err::*, fixed::Fixed};
use bitflags::bitflags; use bitflags::bitflags;
use std::convert::TryFrom;
use super::trig; use super::trig;
@ -100,7 +99,6 @@ bitflags! {
c_enum! { c_enum! {
/// The type of functionality a weapon provides. /// The type of functionality a weapon provides.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum WeaponType: u16 pub enum WeaponType: u16
{ {
Melee = 0, Melee = 0,

50
maraiah/meta.rs Normal file
View File

@ -0,0 +1,50 @@
//! Meta-information of this crate.
macro_rules! meta_str {
($($(#[$outer:meta])* $name:ident = $e:expr;)*) => {
$($(#[$outer])* pub const fn $name() -> &'static str {$e})*
pub mod ffi
{
$(
doc_comment! {
concat!("FFI variant of [`",
stringify!($name),
"`]\n\n[`",
stringify!($name),
"`]: ../fn.",
stringify!($name),
".html"),
pub const fn $name() -> crate::ffi::NT {c_str!($e)}
}
)*
}
}
}
meta_str!(
/// The authors of this crate, `:` separated.
authors = env!("CARGO_PKG_AUTHORS");
/// The description of this crate.
description = env!("CARGO_PKG_DESCRIPTION");
/// The home page of this crate.
homepage = env!("CARGO_PKG_HOMEPAGE");
/// The full license text of this crate.
license_text = include_str!("../LICENSE");
/// The name of this crate.
name = env!("CARGO_PKG_NAME");
/// The repository of this crate.
repository = env!("CARGO_PKG_REPOSITORY");
/// The full version of this crate.
version = env!("CARGO_PKG_VERSION");
/// The major version of this crate.
version_major = env!("CARGO_PKG_VERSION_MAJOR");
/// The minor version of this crate.
version_minor = env!("CARGO_PKG_VERSION_MINOR");
/// The patch version of this crate.
version_patch = env!("CARGO_PKG_VERSION_PATCH");
/// The pre-release version of this crate.
version_pre = env!("CARGO_PKG_VERSION_PRE");
);
// EOF

View File

@ -1,8 +1,7 @@
//! Shapes file collection type. //! Shapes file collection type.
use crate::{bin::{rd_ofstable, usize_from_u32}, err::*}; use crate::{bin::rd_ofstable, err::*};
use super::{bmap, clut, fram, sequ}; use super::{bmap, clut, fram, sequ};
use std::convert::TryFrom;
/// Reads a `Collection`. /// Reads a `Collection`.
pub fn read(b: &[u8]) -> ResultS<Collection> pub fn read(b: &[u8]) -> ResultS<Collection>
@ -58,7 +57,6 @@ pub struct Collection
c_enum! { c_enum! {
/// The type of a collection. /// The type of a collection.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum CollectionType: u16 pub enum CollectionType: u16
{ {
Unused = 0, Unused = 0,

View File

@ -3,7 +3,6 @@
use crate::{bin::OptU16, err::*, use crate::{bin::OptU16, err::*,
text::{mac_roman_conv, pascal_str}, text::{mac_roman_conv, pascal_str},
xfer::TransferMode}; xfer::TransferMode};
use std::convert::TryFrom;
/// Reads a `Sequence`. /// Reads a `Sequence`.
pub fn read(b: &[u8]) -> ResultS<Sequence> pub fn read(b: &[u8]) -> ResultS<Sequence>
@ -72,7 +71,6 @@ pub struct Sequence
c_enum! { c_enum! {
/// The type of or number of views for a sequence. /// The type of or number of views for a sequence.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum ViewType: u16 pub enum ViewType: u16
{ {
Anim = 1, Anim = 1,

View File

@ -1,7 +1,6 @@
//! Sounds format definition type. //! Sounds format definition type.
use crate::{bin::{u32b, usize_from_u32}, err::*, fixed::*, sound::Sound16}; use crate::{bin::{u32b, usize_from_u32}, err::*, fixed::*, sound::Sound16};
use std::convert::TryFrom;
use bitflags::bitflags; use bitflags::bitflags;
/// Reads a sound definition. /// Reads a sound definition.
@ -90,7 +89,6 @@ bitflags! {
c_enum! { c_enum! {
/// The type of volume this sound has. /// The type of volume this sound has.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum Volume: u16 pub enum Volume: u16
{ {
Quiet = 0, Quiet = 0,

View File

@ -1,6 +1,6 @@
//! Sounds file audio type. //! Sounds file audio type.
use crate::{bin::usize_from_u32, err::*, sound::Sound16}; use crate::{err::*, sound::Sound16};
/// Reads a sound. /// Reads a sound.
pub fn read(b: &[u8]) -> ResultS<Sound16> pub fn read(b: &[u8]) -> ResultS<Sound16>

View File

@ -8,7 +8,6 @@ impl Default for TransferMode
c_enum! { c_enum! {
/// A rendering style for many things. /// A rendering style for many things.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug)]
pub enum TransferMode: u16 pub enum TransferMode: u16
{ {
Normal = 0, Normal = 0,

View File

@ -1,17 +0,0 @@
[package]
name = "maraiah-leela"
version = "0.1.0"
authors = ["Alison Watson <marrub@greyserv.net>"]
description = "Maraiah testbed program."
edition = "2018"
[dependencies]
clap = "2"
maraiah = {path = "../..", features = ["serde_obj"]}
memmap = "0.7"
serde = "1.0"
serde_yaml = "0.8"
[[bin]]
name = "leela"
path = "main.rs"

View File

@ -1,107 +0,0 @@
//! Marathon Map format handling.
pub mod ambi;
pub mod attk;
pub mod bonk;
pub mod chnk;
pub mod damg;
pub mod entr;
pub mod epnt;
pub mod fxpx;
pub mod iidx;
pub mod lins;
pub mod lite;
pub mod ltfn;
pub mod medi;
pub mod minf;
pub mod mnpx;
pub mod name;
pub mod note;
pub mod objs;
pub mod plac;
pub mod plat;
pub mod pnts;
pub mod poly;
pub mod prpx;
pub mod pxpx;
pub mod sids;
pub mod stex;
pub mod term;
pub mod trig;
pub mod trmf;
pub mod trmg;
pub mod wppx;
use crate::{err::*, text::mac_roman_cstr};
use std::convert::TryFrom;
/// Reads a Map file.
pub fn read(b: &[u8]) -> ResultS<Wad>
{
read_data! {
endian: BIG, buf: b, size: 128, start: 0, data {
let ver_wad = u16[0] enum Ver;
let ver_dat = u16[2];
let name = mac_roman_cstr[4; 64] no_try;
let siz_app = u16[78] usize;
let siz_wcnk = u16[80] usize;
let siz_went = u16[82] usize;
}
}
let old_dat = ver_dat == 0;
let old_wad = match ver_wad {
Ver::Base => true,
_ => false,
};
let siz_ent = if old_wad {8 } else {10};
let siz_cnk = if old_wad {12} else {16};
if !old_wad && siz_ent != siz_went {
bail!("invalid entry size");
}
if !old_wad && siz_cnk != siz_wcnk {
bail!("invalid chunk size");
}
let entries = entr::read(b, old_wad, siz_app, siz_ent, siz_cnk)?;
Ok(Wad{name, siz_app, old_dat, entries})
}
/// A Map file containing entries.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Wad
{
/// The original name of this file.
pub name: String,
/// The size of each `Entry`'s `appdata` field.
pub siz_app: usize,
/// If the data is in Marathon 1 format.
pub old_dat: bool,
/// All of the entries in this `Wad`.
pub entries: entr::EntryMap,
}
c_enum! {
// The version of a `Wad`.
#[derive(Debug)]
enum Ver: u16
{
Base = 0,
Dir = 1,
Over = 2,
Inf = 4,
}
}
/// The number of game ticks per second.
pub const TICKS_PER_SECOND: u16 = 30;
// EOF

View File

@ -1,120 +0,0 @@
//! Wad file chunk type.
use crate::{bin::*, err::*, image::{self, pict}, map};
/// Reads all chunks in an entry.
pub fn read(b: &[u8], siz_cnk: usize) -> ResultS<Vec<ChunkData>>
{
let mut chunks = Vec::new();
let mut p = 0;
while p < b.len() {
read_data! {
endian: BIG, buf: b, size: siz_cnk, start: p, data {
let iden = Ident[0];
let size = u32[8] usize;
}
}
let beg = p + siz_cnk;
let end = beg + size;
let data = ok!(b.get(beg..end), "not enough data")?.to_vec();
chunks.push(ChunkData{iden, data});
p = end;
}
Ok(chunks)
}
/// Loads structured data from chunk data.
pub fn load(chunk_data: &[ChunkData], old: bool) -> ResultS<Vec<Chunk>>
{
let mut chunks = Vec::new();
let read_chunk_minf = if old {map::minf::read_old} else {map::minf::read};
let read_chunk_sids = if old {map::sids::read_old} else {map::sids::read};
let read_chunk_poly = if old {map::poly::read_old} else {map::poly::read};
let read_chunk_lite = if old {map::lite::read_old} else {map::lite::read};
for chunk in chunk_data.iter() {
let data = &chunk.data;
let chunk = match &chunk.iden.0 {
b"EPNT" => Chunk::Epnt(rd_array(data, map::epnt::read)?),
b"FXpx" => Chunk::Fxpx(rd_array(data, map::fxpx::read)?),
b"LINS" => Chunk::Lins(rd_array(data, map::lins::read)?),
b"LITE" => Chunk::Lite(rd_array(data, read_chunk_lite)?),
b"MNpx" => Chunk::Mnpx(rd_array(data, map::mnpx::read)?),
b"Minf" => Chunk::Minf(read_chunk_minf(data)?),
b"NAME" => Chunk::Name(rd_array(data, map::name::read)?),
b"NOTE" => Chunk::Note(rd_array(data, map::note::read)?),
b"OBJS" => Chunk::Objs(rd_array(data, map::objs::read)?),
b"PICT" => Chunk::Pict(pict::read(data)?),
b"PNTS" => Chunk::Pnts(rd_array(data, map::pnts::read)?),
b"POLY" => Chunk::Poly(rd_array(data, read_chunk_poly)?),
b"PRpx" => Chunk::Prpx(rd_array(data, map::prpx::read)?),
b"PXpx" => Chunk::Pxpx(rd_array(data, map::pxpx::read)?),
b"SIDS" => Chunk::Sids(rd_array(data, read_chunk_sids)?),
b"WPpx" => Chunk::Wppx(rd_array(data, map::wppx::read)?),
b"ambi" => Chunk::Ambi(rd_array(data, map::ambi::read)?),
b"bonk" => Chunk::Bonk(rd_array(data, map::bonk::read)?),
b"iidx" => Chunk::Iidx(rd_array(data, map::iidx::read)?),
b"medi" => Chunk::Medi(rd_array(data, map::medi::read)?),
b"plac" => Chunk::Plac(rd_array(data, map::plac::read)?),
b"plat" => Chunk::Plat(rd_array(data, map::plat::read)?),
b"term" => Chunk::Term(rd_array(data, map::term::read)?),
_ => Chunk::Data(chunk.clone()),
};
chunks.push(chunk);
}
Ok(chunks)
}
/// The data of a Chunk read from a file.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ChunkData
{
/// The name of the chunk.
pub iden: Ident,
/// The data.
pub data: Vec<u8>,
}
/// Any kind of chunk in an `Entry`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub enum Chunk
{
/** `EPNT` chunks. */ Epnt(Vec<map::epnt::Endpoint>),
/** `FXpx` chunks. */ Fxpx(Vec<map::fxpx::Effect>),
/** `LINS` chunks. */ Lins(Vec<map::lins::Line>),
/** `LITE` chunks. */ Lite(Vec<map::lite::Light>),
/** `MNpx` chunks. */ Mnpx(Vec<map::mnpx::Monster>),
/** `Minf` chunks. */ Minf(map::minf::Info),
/** `NAME` chunks. */ Name(Vec<String>),
/** `NOTE` chunks. */ Note(Vec<map::note::Note>),
/** `OBJS` chunks. */ Objs(Vec<map::objs::Object>),
/** `PICT` chunks. */ Pict(image::Image8),
/** `PNTS` chunks. */ Pnts(Vec<map::pnts::Point>),
/** `POLY` chunks. */ Poly(Vec<map::poly::Polygon>),
/** `PRpx` chunks. */ Prpx(Vec<map::prpx::Projectile>),
/** `PXpx` chunks. */ Pxpx(Vec<map::pxpx::Physics>),
/** `SIDS` chunks. */ Sids(Vec<map::sids::Side>),
/** `WPpx` chunks. */ Wppx(Vec<map::wppx::Weapon>),
/** `ambi` chunks. */ Ambi(Vec<map::ambi::SoundAmbi>),
/** `bonk` chunks. */ Bonk(Vec<map::bonk::SoundRand>),
/** `iidx` chunks. */ Iidx(Vec<u16>),
/** `medi` chunks. */ Medi(Vec<map::medi::Media>),
/** `plac` chunks. */ Plac(Vec<map::plac::ObjectFreq>),
/** `plat` chunks. */ Plat(Vec<map::plat::Platform>),
/** `term` chunks. */ Term(Vec<map::term::Terminal>),
/** Unknown chunk. */ Data(ChunkData),
}
// EOF

View File

@ -1,61 +0,0 @@
//! Wad file entry type.
use crate::{bin::usize_from_u32, err::*};
use super::chnk;
use std::collections::BTreeMap;
/// Reads all entries in a `Wad`.
pub fn read(b: &[u8],
old_wad: bool,
siz_app: usize,
siz_ent: usize,
siz_cnk: usize) -> ResultS<EntryMap>
{
read_data! {
endian: BIG, buf: b, size: 128, start: 0, data {
let dirofs = u32[72] usize;
let numents = u16[76] usize;
}
}
let mut entries = EntryMap::new();
let mut p = dirofs;
for i in 0..numents {
read_data! {
endian: BIG, buf: b, size: siz_ent, start: p, data {
let offset = u32[0] usize;
let size = u32[4] usize;
let index = u16[8];
}
}
let index = if old_wad {i as u16} else {index};
let chunks = chnk::read(&b[offset..offset + size], siz_cnk)?;
let appdata = b[p..p + siz_app].to_vec();
entries.insert(index, Entry{chunks, appdata});
p += siz_ent + siz_app;
}
Ok(entries)
}
/// An entry containing chunks and application-specific data.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Entry
{
/// All of the chunks in this `Entry`.
pub chunks: Vec<chnk::ChunkData>,
/// The application specific data for this Entry.
pub appdata: Vec<u8>,
}
/// A map of indexed entries.
pub type EntryMap = BTreeMap<u16, Entry>;
// EOF

View File

@ -1,51 +0,0 @@
//! Meta-information of this crate.
macro_rules! meta_str {
($($(#[$outer:meta])* $name:ident = $cname:ident = $e:expr;)*) => {
$(
$(#[$outer])* pub const $name: &'static str = $e;
)*
pub mod ffi
{
$(
doc_comment! {
concat!("FFI variant of [`",
stringify!($name),
"`]\n\n[`",
stringify!($name),
"`]: ../constant.",
stringify!($name),
".html"),
pub const $cname: crate::ffi::NT = c_str!($e);
}
)*
}
}
}
meta_str!(
/// The authors of this crate, `:` separated.
AUTHORS = AUTHORS_C = env!("CARGO_PKG_AUTHORS");
/// The description of this crate.
DESCRIPTION = DESCRIPTION_C = env!("CARGO_PKG_DESCRIPTION");
/// The home page of this crate.
HOMEPAGE = HOMEPAGE_C = env!("CARGO_PKG_HOMEPAGE");
/// The full license text of this crate.
LICENSE_TEXT = LICENSE_TEXT_C = include_str!("../LICENSE");
/// The name of this crate.
NAME = NAME_C = env!("CARGO_PKG_NAME");
/// The repository of this crate.
REPOSITORY = REPOSITORY_C = env!("CARGO_PKG_REPOSITORY");
/// The full version of this crate.
VERSION = VERSION_C = env!("CARGO_PKG_VERSION");
/// The major version of this crate.
VERSION_MAJOR = VERSION_MAJOR_C = env!("CARGO_PKG_VERSION_MAJOR");
/// The minor version of this crate.
VERSION_MINOR = VERSION_MINOR_C = env!("CARGO_PKG_VERSION_MINOR");
/// The patch version of this crate.
VERSION_PATCH = VERSION_PATCH_C = env!("CARGO_PKG_VERSION_PATCH");
/// The pre-release version of this crate.
VERSION_PRE = VERSION_PRE_C = env!("CARGO_PKG_VERSION_PRE");
);
// EOF

BIN
tests/data/m2/Map Normal file

Binary file not shown.

View File

@ -2,8 +2,8 @@ map::minf::Info{
texture_id: 0, texture_id: 0,
physics_id: 1, physics_id: 1,
skypict_id: 1, skypict_id: 1,
miss_flags: map::minf::MsnFlags::REPAIR, miss_flags: map::minf::MissionFlags::REPAIR,
envi_flags: map::minf::EnvFlags::empty(), envi_flags: map::minf::EnvironmentFlags::empty(),
entr_flags: map::minf::EntFlags::SOLO | map::minf::EntFlags::CO_OP, entr_flags: map::minf::EntryFlags::SOLO | map::minf::EntryFlags::CO_OP,
level_name: "Waterloo Waterpark".to_owned() level_name: "Waterloo Waterpark".to_owned()
} }

BIN
tests/data/map/testmap.in Normal file

Binary file not shown.

2185
tests/data/map/testmap.out Normal file

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ fn defl_alice_2()
fn defl_shapes() fn defl_shapes()
{ {
const INPUT: &[u8] = include_bytes!("data/defl/Shapes.in"); const INPUT: &[u8] = include_bytes!("data/defl/Shapes.in");
const OUTPUT: &[u8] = include_bytes!("data/defl/Shapes.out"); const OUTPUT: &[u8] = include_bytes!("data/m2/Shapes");
defl_gzip(INPUT, OUTPUT); defl_gzip(INPUT, OUTPUT);
} }

View File

@ -51,25 +51,65 @@ fn read_term_must_process()
} }
} }
#[test]
fn map_m2()
{
let inp = include_bytes!("data/m2/Map");
let mut rd = std::io::BufReader::new(&inp[..]);
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
assert!(map::data::read_all(mp.head(), &en).is_ok());
}
#[test]
#[ignore]
fn map_full_check()
{
use maraiah::{bin::OptU16,
map::{data::*, lins::*, lite::*, ltfn::*, minf::*, objs::*,
plac::*, pnts::*, poly::*},
xfer::TransferMode};
use std::collections::BTreeMap;
let inp = include_bytes!("data/map/testmap.in");
let mut rd = std::io::BufReader::new(&inp[..]);
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
let ed = map::data::read_all(mp.head(), &en).unwrap();
let mut out = BTreeMap::new();
out.insert(0, include!("data/map/testmap.out"));
assert_eq!(out, ed);
}
#[test] #[test]
fn map_must_not_process() fn map_must_not_process()
{ {
for inp in &RANDOM { for inp in &RANDOM {
map::minf::read(inp).err().unwrap(); bin::rd_array(inp, map::fxpx::read).err().unwrap();
map::minf::read_old(inp).err().unwrap();
bin::rd_array(inp, map::lins::read).err().unwrap(); bin::rd_array(inp, map::lins::read).err().unwrap();
bin::rd_array(inp, map::lite::read).err().unwrap(); bin::rd_array(inp, map::lite::read).err().unwrap();
bin::rd_array(inp, map::lite::read_old).err().unwrap();
bin::rd_array(inp, map::medi::read).err().unwrap(); bin::rd_array(inp, map::medi::read).err().unwrap();
bin::rd_array(inp, map::mnpx::read).err().unwrap();
bin::rd_array(inp, map::note::read).err().unwrap(); bin::rd_array(inp, map::note::read).err().unwrap();
bin::rd_array(inp, map::objs::read).err().unwrap(); bin::rd_array(inp, map::objs::read).err().unwrap();
bin::rd_array(inp, map::plat::read).err().unwrap(); bin::rd_array(inp, map::plat::read).err().unwrap();
bin::rd_array(inp, map::poly::read).err().unwrap(); bin::rd_array(inp, map::poly::read).err().unwrap();
bin::rd_array(inp, map::poly::read_old).err().unwrap();
bin::rd_array(inp, map::prpx::read).err().unwrap();
bin::rd_array(inp, map::sids::read).err().unwrap(); bin::rd_array(inp, map::sids::read).err().unwrap();
bin::rd_array(inp, map::sids::read_old).err().unwrap();
bin::rd_array(inp, map::term::read).err().unwrap(); bin::rd_array(inp, map::term::read).err().unwrap();
bin::rd_array(inp, map::trmg::read).err().unwrap(); bin::rd_array(inp, map::trmg::read).err().unwrap();
bin::rd_array(inp, map::lite::read_old).err().unwrap(); bin::rd_array(inp, map::wppx::read).err().unwrap();
bin::rd_array(inp, map::poly::read_old).err().unwrap(); map::minf::read(inp).err().unwrap();
bin::rd_array(inp, map::sids::read_old).err().unwrap(); map::minf::read_old(inp).err().unwrap();
} }
} }
@ -82,27 +122,9 @@ fn map_must_not_panic()
drop(bin::rd_array(inp, map::epnt::read)); drop(bin::rd_array(inp, map::epnt::read));
drop(bin::rd_array(inp, map::iidx::read)); drop(bin::rd_array(inp, map::iidx::read));
drop(bin::rd_array(inp, map::plac::read)); drop(bin::rd_array(inp, map::plac::read));
drop(bin::rd_array(inp, map::pxpx::read));
drop(bin::rd_array(inp, map::trmf::read)); drop(bin::rd_array(inp, map::trmf::read));
} }
} }
#[test]
fn phy_must_not_process()
{
for inp in &RANDOM {
bin::rd_array(inp, map::fxpx::read).err().unwrap();
bin::rd_array(inp, map::mnpx::read).err().unwrap();
bin::rd_array(inp, map::prpx::read).err().unwrap();
bin::rd_array(inp, map::wppx::read).err().unwrap();
}
}
#[test]
fn phy_must_not_panic()
{
for inp in &RANDOM {
drop(bin::rd_array(inp, map::pxpx::read));
}
}
// EOF // EOF

View File

@ -1,4 +1,4 @@
use maraiah::{image::{Color8, pict}}; use maraiah::image::{pict, Color8};
include!("data/rand.rs"); include!("data/rand.rs");

View File

@ -5,12 +5,11 @@ edition = "2018"
build = "build.rs" build = "build.rs"
[dependencies] [dependencies]
maraiah = {path = "../.."} maraiah = {path = ".."}
memmap = "0.7"
[build-dependencies] [build-dependencies]
cmake = "0.1" cmake = "0.1"
maraiah = {path = "../.."} maraiah = {path = ".."}
rust_qt_binding_generator = "0.3" rust_qt_binding_generator = "0.3"
[[bin]] [[bin]]

Some files were not shown because too many files have changed in this diff Show More