Compare commits
4 Commits
92aea23e04
...
daebfd2da6
Author | SHA1 | Date |
---|---|---|
an | daebfd2da6 | |
an | bfb91792ec | |
an | be8d72df7d | |
an | 91d171c8a6 |
|
@ -14,10 +14,10 @@ publish = false
|
|||
serde_obj = ["serde"]
|
||||
|
||||
[workspace]
|
||||
members = ["source/leela", "source/tycho"]
|
||||
members = ["leela", "tycho"]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
bitflags = "1.1"
|
||||
failure = {version = "0.1", features = ["std"]}
|
||||
serde = {version = "1.0", features = ["derive"], optional = true}
|
||||
memchr = "2.0"
|
||||
|
@ -31,4 +31,4 @@ lto = true
|
|||
|
||||
[lib]
|
||||
name = "maraiah"
|
||||
path = "source/lib.rs"
|
||||
path = "maraiah/lib.rs"
|
||||
|
|
|
@ -926,8 +926,9 @@ Random Sound is 32 bytes.
|
|||
### Media Data ###
|
||||
|
||||
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
|
||||
part of the map in the middle of a wall.
|
||||
plural of the definition of "medium," a "material which waves pass through," in
|
||||
this case liquid. (This is likely the case of whoever programmed this system
|
||||
learning physics before rendering, or conflating the two.)
|
||||
|
||||
| Name | Type | Offset |
|
||||
| ---- | ---- | ------ |
|
||||
|
|
|
@ -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"
|
|
@ -1,13 +1,13 @@
|
|||
#![allow(clippy::unit_arg)]
|
||||
|
||||
use maraiah::{err::*, file::*, image::*, sound::*,
|
||||
machdr, map, ppm, shp, snd, tga, wav};
|
||||
use maraiah::{err::*, file::*, image::*, machdr, map, shp, snd, sound::*};
|
||||
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)?;
|
||||
Ok(unsafe {memmap::Mmap::map(&fp)?})
|
||||
Ok(io::BufReader::new(fp))
|
||||
}
|
||||
|
||||
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>
|
||||
{
|
||||
match std::fs::metadata(path) {
|
||||
Ok(_) => Ok(()),
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn each_value<F>(opt: &clap::ArgMatches<'_>,
|
||||
name: &str,
|
||||
mut f: F) -> ResultS<()>
|
||||
mut f: F)
|
||||
-> ResultS<()>
|
||||
where F: FnMut(&str) -> ResultS<()>
|
||||
{
|
||||
if let Some(values) = opt.values_of(name) {
|
||||
|
@ -91,43 +92,60 @@ fn sub_info_c(opt: &clap::ArgMatches<'_>) -> ResultS<()>
|
|||
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
let sub_data =
|
||||
clap_app!(@subcommand data =>
|
||||
(about: "Dumps data into a discrete folder/YAML format"));
|
||||
let sub_data = clap_app! {
|
||||
@subcommand data =>
|
||||
(about: "Dumps data into a discrete folder/YAML format")
|
||||
};
|
||||
|
||||
let sub_dump =
|
||||
clap_app!(@subcommand dump =>
|
||||
let sub_dump = clap_app! {
|
||||
@subcommand dump =>
|
||||
(about: "Dumps particular parts of data")
|
||||
(@arg chunks: -c --chunks [name]... "Dumps named chunks from an entry")
|
||||
(@group files =>
|
||||
(@attributes +required +multiple)
|
||||
(@arg map: -m --map [file]... {exists} "Loads Map files")
|
||||
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
|
||||
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files")));
|
||||
(@attributes +required +multiple)
|
||||
(@arg map: -m --map [file]... {exists} "Loads Map files")
|
||||
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
|
||||
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
|
||||
};
|
||||
|
||||
let sub_info =
|
||||
clap_app!(@subcommand info =>
|
||||
let sub_info = clap_app! {
|
||||
@subcommand info =>
|
||||
(about: "Outputs debug info")
|
||||
(@group files =>
|
||||
(@attributes +required +multiple)
|
||||
(@arg map: -m --map [file]... {exists} "Loads Map files")
|
||||
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
|
||||
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files")));
|
||||
(@attributes +required +multiple)
|
||||
(@arg map: -m --map [file]... {exists} "Loads Map files")
|
||||
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
|
||||
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
|
||||
};
|
||||
|
||||
let opt =
|
||||
clap_app!((env!("CARGO_PKG_NAME")) =>
|
||||
(version: env!("CARGO_PKG_VERSION"))
|
||||
(author: env!("CARGO_PKG_AUTHORS"))
|
||||
(about: env!("CARGO_PKG_DESCRIPTION"))
|
||||
let opt = clap_app! {
|
||||
(env!("CARGO_PKG_NAME")) =>
|
||||
(version: maraiah::meta::version())
|
||||
(author: maraiah::meta::authors().replace(':', ", "))
|
||||
(about: maraiah::meta::description())
|
||||
(setting: clap::AppSettings::SubcommandRequiredElseHelp)
|
||||
(subcommand: sub_data)
|
||||
(subcommand: sub_dump)
|
||||
(subcommand: sub_info));
|
||||
(subcommand: sub_info)
|
||||
};
|
||||
|
||||
let opt = opt.get_matches();
|
||||
|
||||
|
@ -137,6 +155,7 @@ fn main() -> ResultS<()>
|
|||
("info", Some(opt)) => sub_info_c(opt)?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
*/
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -6,98 +6,133 @@ use std::{convert::{TryFrom, TryInto}, fmt, num::NonZeroU16};
|
|||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$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) => {
|
||||
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
||||
let $nam = usize::from($nam);
|
||||
};
|
||||
|
||||
// either endianness, u32 -> usize
|
||||
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, 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;
|
||||
$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);
|
||||
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;
|
||||
$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);
|
||||
let $nam = flag_ok!($ft$(::$ftc)*, $nam)?;
|
||||
};
|
||||
|
||||
// no endianness
|
||||
// no endianness, u8
|
||||
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, u8) => {
|
||||
let $nam = $b[$n + $at];
|
||||
};
|
||||
|
||||
// no endianness, i8
|
||||
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, i8) => {
|
||||
let $nam = $b[$n + $at] as i8;
|
||||
};
|
||||
|
||||
// no endianness, [u8]
|
||||
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, u8) => {
|
||||
let $nam = &$b[$n + $at..$n + $at + $rn];
|
||||
};
|
||||
|
||||
// no endianness, Ident
|
||||
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Ident) => {
|
||||
$crate::rd_impl!(D $b, Ident, $nam, $n + $at);
|
||||
};
|
||||
|
||||
// no endianness, fn([u8]) -> T
|
||||
($_: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]);
|
||||
};
|
||||
|
||||
// no endianness, fn([u8]) -> Result<T>
|
||||
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, $f:expr) => {
|
||||
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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
#[inline]
|
|
@ -16,7 +16,6 @@
|
|||
/// use std::convert::TryFrom;
|
||||
///
|
||||
/// c_enum! {
|
||||
/// #[derive(Debug)]
|
||||
/// enum MyEnum: u16
|
||||
/// {
|
||||
/// Zero = 0,
|
||||
|
@ -43,7 +42,7 @@ macro_rules! c_enum
|
|||
}
|
||||
) => {
|
||||
$(#[$outer])*
|
||||
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
|
||||
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
#[repr($ti)]
|
||||
$vi enum $t
|
||||
{
|
||||
|
@ -74,7 +73,6 @@ mod test
|
|||
use std::convert::TryFrom;
|
||||
|
||||
c_enum! {
|
||||
#[derive(Debug)]
|
||||
enum TestEnum: u16
|
||||
{
|
||||
Zero = 0,
|
|
@ -8,7 +8,7 @@ macro_rules! ok {
|
|||
($v:expr, $msg:expr) => {
|
||||
match $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) => {
|
||||
match $t$(::$tc)*::from_bits($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 {
|
||||
($e:expr) => {
|
||||
return Err(err_msg($e));
|
||||
return Err($crate::err::err_msg($e));
|
||||
};
|
||||
}
|
||||
|
|
@ -588,7 +588,9 @@ macro_rules! define_fixed_types {
|
|||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
fmt::Display::fmt(self, f)
|
||||
write!(f,
|
||||
concat!(stringify!($t), "::from_bits({})"),
|
||||
self.to_bits())
|
||||
}
|
||||
}
|
||||
)*};
|
|
@ -1,7 +1,6 @@
|
|||
//! QuickDraw PICT `PixMap` headers.
|
||||
|
||||
use crate::{bin::*, err::*, image::*};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a `PixMap` header.
|
||||
pub fn read<'a>(b: &'a [u8],
|
|
@ -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
|
|
@ -17,7 +17,7 @@ pub fn read(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
|
|||
|
||||
/// An ambient sound definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct SoundAmbi
|
||||
{
|
||||
pub index: u16,
|
|
@ -27,7 +27,7 @@ pub fn read(b: &[u8]) -> ResultS<(SoundRand, usize)>
|
|||
|
||||
/// A randomly played sound definition.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct SoundRand
|
||||
{
|
||||
pub flags: SoundRandFlags,
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
use crate::{err::*, fixed::Fixed};
|
||||
use bitflags::bitflags;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a `Damage` object.
|
||||
pub fn read(b: &[u8]) -> ResultS<Damage>
|
||||
|
@ -76,7 +75,6 @@ bitflags! {
|
|||
c_enum! {
|
||||
/// A named type of damage taken by something.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum DamageType: u16
|
||||
{
|
||||
Explosion = 0,
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -23,7 +23,7 @@ pub fn read(b: &[u8]) -> ResultS<(Line, usize)>
|
|||
|
||||
/// A line segment.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Line
|
||||
{
|
||||
pub flags: LineFlags,
|
|
@ -3,7 +3,6 @@
|
|||
use super::{ltfn, TICKS_PER_SECOND};
|
||||
use crate::{err::*, fixed::Fixed};
|
||||
use bitflags::bitflags;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a `LITE` chunk.
|
||||
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.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Light
|
||||
{
|
||||
pub ltype: LightType,
|
||||
|
@ -102,7 +101,6 @@ bitflags! {
|
|||
c_enum! {
|
||||
/// The type of a `Light`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum LightType: u16
|
||||
{
|
||||
Normal = 0,
|
|
@ -1,7 +1,6 @@
|
|||
//! `LightFunc` type.
|
||||
|
||||
use crate::{err::*, fixed::Fixed};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a `LightFunc` object.
|
||||
pub fn read(b: &[u8]) -> ResultS<LightFunc>
|
||||
|
@ -33,7 +32,7 @@ pub fn write(v: &LightFunc) -> Vec<u8>
|
|||
|
||||
/// A light function.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct LightFunc
|
||||
{
|
||||
pub ftype: LightFuncType,
|
||||
|
@ -46,7 +45,6 @@ pub struct LightFunc
|
|||
c_enum! {
|
||||
/// The type of function for a `LightFunc`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum LightFuncType: u16
|
||||
{
|
||||
Constant = 0,
|
|
@ -6,7 +6,6 @@ use crate::{bin::OptU16,
|
|||
fixed::{Angle, Fixed, Unit},
|
||||
xfer::TransferMode};
|
||||
use bitflags::bitflags;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a `medi` chunk.
|
||||
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.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Media
|
||||
{
|
||||
pub mtype: MediaType,
|
||||
|
@ -54,7 +53,6 @@ pub struct Media
|
|||
c_enum! {
|
||||
/// The liquid type of a `Media`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum MediaType: u16
|
||||
{
|
||||
Water = 0,
|
|
@ -11,10 +11,10 @@ pub fn read(b: &[u8]) -> ResultS<Info>
|
|||
let texture_id = u16[0];
|
||||
let physics_id = u16[2];
|
||||
let skypict_id = u16[4];
|
||||
let miss_flags = u16[6] flag MsnFlags;
|
||||
let envi_flags = u16[8] flag EnvFlags;
|
||||
let miss_flags = u16[6] flag MissionFlags;
|
||||
let envi_flags = u16[8] flag EnvironmentFlags;
|
||||
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 mut entr_flags = if minf.entr_flags.is_empty() {
|
||||
EntFlags::SOLO
|
||||
EntryFlags::SOLO
|
||||
} else {
|
||||
minf.entr_flags
|
||||
};
|
||||
|
||||
if entr_flags.intersects(EntFlags::SOLO | EntFlags::CARNAGE) {
|
||||
entr_flags.insert(EntFlags::CO_OP)
|
||||
if entr_flags.intersects(EntryFlags::SOLO | EntryFlags::CARNAGE) {
|
||||
entr_flags.insert(EntryFlags::CO_OP)
|
||||
}
|
||||
|
||||
Ok(Info{entr_flags, ..minf})
|
||||
|
@ -61,9 +61,9 @@ impl Default for Info
|
|||
Self{texture_id: 0,
|
||||
physics_id: 1,
|
||||
skypict_id: 0,
|
||||
miss_flags: MsnFlags::empty(),
|
||||
envi_flags: EnvFlags::empty(),
|
||||
entr_flags: EntFlags::SOLO,
|
||||
miss_flags: MissionFlags::empty(),
|
||||
envi_flags: EnvironmentFlags::empty(),
|
||||
entr_flags: EntryFlags::SOLO,
|
||||
level_name: "Map".to_string()}
|
||||
}
|
||||
}
|
||||
|
@ -76,16 +76,16 @@ pub struct Info
|
|||
pub texture_id: u16,
|
||||
pub physics_id: u16,
|
||||
pub skypict_id: u16,
|
||||
pub miss_flags: MsnFlags,
|
||||
pub envi_flags: EnvFlags,
|
||||
pub entr_flags: EntFlags,
|
||||
pub miss_flags: MissionFlags,
|
||||
pub envi_flags: EnvironmentFlags,
|
||||
pub entr_flags: EntryFlags,
|
||||
pub level_name: String,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Static environment flags.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct EnvFlags: u16
|
||||
pub struct EnvironmentFlags: u16
|
||||
{
|
||||
const VACUUM = 1;
|
||||
const MAGNETIC = 1 << 1;
|
||||
|
@ -104,7 +104,7 @@ bitflags! {
|
|||
bitflags! {
|
||||
/// Static entry point flags.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct EntFlags: u32
|
||||
pub struct EntryFlags: u32
|
||||
{
|
||||
const SOLO = 1;
|
||||
const CO_OP = 1 << 1;
|
||||
|
@ -120,7 +120,7 @@ bitflags! {
|
|||
bitflags! {
|
||||
/// Static mission flags.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct MsnFlags: u16
|
||||
pub struct MissionFlags: u16
|
||||
{
|
||||
const EXTERMINATION = 1;
|
||||
const EXPLORATION = 1 << 1;
|
|
@ -19,7 +19,7 @@ pub fn read(b: &[u8]) -> ResultS<(Note, usize)>
|
|||
|
||||
/// Overhead map annotations.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Note
|
||||
{
|
||||
pub pos: pnts::Point,
|
|
@ -29,7 +29,7 @@ pub fn read(b: &[u8]) -> ResultS<(Object, usize)>
|
|||
|
||||
/// An object in the world.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Object
|
||||
{
|
||||
pub group: u16,
|
|
@ -22,7 +22,7 @@ pub fn read(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
|
|||
|
||||
/// The difficulty definition for various object types.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ObjectFreq
|
||||
{
|
||||
pub flags: ObjectFreqFlags,
|
|
@ -24,7 +24,7 @@ pub fn read(b: &[u8]) -> ResultS<(Platform, usize)>
|
|||
|
||||
/// Extra information for polygons with platforms.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Platform
|
||||
{
|
||||
pub ptype: u16,
|
|
@ -3,7 +3,6 @@
|
|||
use super::pnts;
|
||||
use crate::{bin::OptU16, err::*, fixed::Unit, xfer::TransferMode};
|
||||
use bitflags::bitflags;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a polygon for either M1 or M2.
|
||||
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 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,
|
||||
snd_rnd, ..poly}, 128))
|
||||
|
@ -60,81 +59,81 @@ pub fn read_old(b: &[u8]) -> ResultS<(Polygon, usize)>
|
|||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
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>
|
||||
{
|
||||
match n {
|
||||
0 => Ok(PolyType::Normal),
|
||||
1 => Ok(PolyType::ImpassItem),
|
||||
2 => Ok(PolyType::ImpassMons),
|
||||
3 => Ok(PolyType::Hill),
|
||||
4 => Ok(PolyType::Base),
|
||||
5 => Ok(PolyType::Platform(pdata)),
|
||||
6 => Ok(PolyType::TrigLightOn(pdata)),
|
||||
7 => Ok(PolyType::TrigPlatOn(pdata)),
|
||||
8 => Ok(PolyType::TrigLightOff(pdata)),
|
||||
9 => Ok(PolyType::TrigPlatOff(pdata)),
|
||||
10 => Ok(PolyType::Teleporter(pdata)),
|
||||
11 => Ok(PolyType::ZoneBorder),
|
||||
12 => Ok(PolyType::Goal),
|
||||
13 => Ok(PolyType::TrigMonsVis),
|
||||
14 => Ok(PolyType::TrigMonsInv),
|
||||
15 => Ok(PolyType::TrigMonsDual),
|
||||
16 => Ok(PolyType::TrigItems),
|
||||
17 => Ok(PolyType::MustExplore),
|
||||
18 => Ok(PolyType::AutoExit),
|
||||
19 => Ok(PolyType::OuchMinor),
|
||||
20 => Ok(PolyType::OuchMajor),
|
||||
21 => Ok(PolyType::Glue),
|
||||
22 => Ok(PolyType::GlueTrigger(pdata)),
|
||||
23 => Ok(PolyType::GlueSuper),
|
||||
0 => Ok(PolygonType::Normal),
|
||||
1 => Ok(PolygonType::ImpassItem),
|
||||
2 => Ok(PolygonType::ImpassMons),
|
||||
3 => Ok(PolygonType::Hill),
|
||||
4 => Ok(PolygonType::Base),
|
||||
5 => Ok(PolygonType::Platform(pdata)),
|
||||
6 => Ok(PolygonType::TrigLightOn(pdata)),
|
||||
7 => Ok(PolygonType::TrigPlatOn(pdata)),
|
||||
8 => Ok(PolygonType::TrigLightOff(pdata)),
|
||||
9 => Ok(PolygonType::TrigPlatOff(pdata)),
|
||||
10 => Ok(PolygonType::Teleporter(pdata)),
|
||||
11 => Ok(PolygonType::ZoneBorder),
|
||||
12 => Ok(PolygonType::Goal),
|
||||
13 => Ok(PolygonType::TrigMonsVis),
|
||||
14 => Ok(PolygonType::TrigMonsInv),
|
||||
15 => Ok(PolygonType::TrigMonsDual),
|
||||
16 => Ok(PolygonType::TrigItems),
|
||||
17 => Ok(PolygonType::MustExplore),
|
||||
18 => Ok(PolygonType::AutoExit),
|
||||
19 => Ok(PolygonType::OuchMinor),
|
||||
20 => Ok(PolygonType::OuchMajor),
|
||||
21 => Ok(PolygonType::Glue),
|
||||
22 => Ok(PolygonType::GlueTrigger(pdata)),
|
||||
23 => Ok(PolygonType::GlueSuper),
|
||||
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>
|
||||
{
|
||||
match n {
|
||||
0 => Ok(PolyType::Normal),
|
||||
1 => Ok(PolyType::ImpassItem),
|
||||
2 => Ok(PolyType::ImpassMons),
|
||||
3 => Ok(PolyType::OuchMinor),
|
||||
4 => Ok(PolyType::OuchMajor),
|
||||
5 => Ok(PolyType::Platform(pdata)),
|
||||
6 => Ok(PolyType::TrigLightOn(pdata)),
|
||||
7 => Ok(PolyType::TrigPlatOn(pdata)),
|
||||
8 => Ok(PolyType::TrigLightOff(pdata)),
|
||||
9 => Ok(PolyType::TrigPlatOff(pdata)),
|
||||
10 => Ok(PolyType::Teleporter(pdata)),
|
||||
11 => Ok(PolyType::Glue),
|
||||
12 => Ok(PolyType::GlueTrigger(pdata)),
|
||||
13 => Ok(PolyType::GlueSuper),
|
||||
14 => Ok(PolyType::MustExplore),
|
||||
15 => Ok(PolyType::AutoExit),
|
||||
0 => Ok(PolygonType::Normal),
|
||||
1 => Ok(PolygonType::ImpassItem),
|
||||
2 => Ok(PolygonType::ImpassMons),
|
||||
3 => Ok(PolygonType::OuchMinor),
|
||||
4 => Ok(PolygonType::OuchMajor),
|
||||
5 => Ok(PolygonType::Platform(pdata)),
|
||||
6 => Ok(PolygonType::TrigLightOn(pdata)),
|
||||
7 => Ok(PolygonType::TrigPlatOn(pdata)),
|
||||
8 => Ok(PolygonType::TrigLightOff(pdata)),
|
||||
9 => Ok(PolygonType::TrigPlatOff(pdata)),
|
||||
10 => Ok(PolygonType::Teleporter(pdata)),
|
||||
11 => Ok(PolygonType::Glue),
|
||||
12 => Ok(PolygonType::GlueTrigger(pdata)),
|
||||
13 => Ok(PolygonType::GlueSuper),
|
||||
14 => Ok(PolygonType::MustExplore),
|
||||
15 => Ok(PolygonType::AutoExit),
|
||||
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.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Default, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Polygon
|
||||
{
|
||||
pub ptype: PolyType,
|
||||
pub ptype: PolygonType,
|
||||
pub tex_flr: OptU16,
|
||||
pub tex_cei: OptU16,
|
||||
pub hei_flr: Unit,
|
||||
|
@ -154,8 +153,8 @@ pub struct Polygon
|
|||
|
||||
/// The action type of a `Polygon`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum PolyType
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum PolygonType
|
||||
{
|
||||
Normal,
|
||||
ImpassItem,
|
||||
|
@ -186,7 +185,7 @@ pub enum PolyType
|
|||
bitflags! {
|
||||
/// Flags for `Polygon`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
pub struct PolyFlags: u16
|
||||
pub struct PolygonFlags: u16
|
||||
{
|
||||
const DETACHED = 1 << 14;
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
use super::stex;
|
||||
use crate::{bin::OptU16, err::*, fixed::Fixed, xfer::TransferMode};
|
||||
use bitflags::bitflags;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a `SIDS` chunk.
|
||||
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.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Side
|
||||
{
|
||||
pub stype: SideType,
|
||||
|
@ -76,7 +75,6 @@ bitflags! {
|
|||
c_enum! {
|
||||
/// The texture type of a `Side`.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum SideType: u16
|
||||
{
|
||||
Full = 0,
|
|
@ -27,7 +27,7 @@ pub fn write(v: &SideTex) -> Vec<u8>
|
|||
|
||||
/// The texture of a side segment.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct SideTex
|
||||
{
|
||||
pub offs: pnts::Point,
|
|
@ -1,7 +1,6 @@
|
|||
//! `Monster` type.
|
||||
|
||||
use crate::{bin::OptU16, err::*, fixed::Unit};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a `Trigger` object.
|
||||
pub fn read(b: &[u8]) -> ResultS<Trigger>
|
||||
|
@ -62,7 +61,6 @@ pub struct Trigger
|
|||
c_enum! {
|
||||
/// A bullet shell casing emitted by a weapon.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum CasingType: u16
|
||||
{
|
||||
Rifle = 0,
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
use crate::{bin::OptU16, err::*, fixed::Fixed};
|
||||
use bitflags::bitflags;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use super::trig;
|
||||
|
||||
|
@ -100,7 +99,6 @@ bitflags! {
|
|||
c_enum! {
|
||||
/// The type of functionality a weapon provides.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum WeaponType: u16
|
||||
{
|
||||
Melee = 0,
|
|
@ -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
|
|
@ -1,8 +1,7 @@
|
|||
//! 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 std::convert::TryFrom;
|
||||
|
||||
/// Reads a `Collection`.
|
||||
pub fn read(b: &[u8]) -> ResultS<Collection>
|
||||
|
@ -58,7 +57,6 @@ pub struct Collection
|
|||
c_enum! {
|
||||
/// The type of a collection.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum CollectionType: u16
|
||||
{
|
||||
Unused = 0,
|
|
@ -3,7 +3,6 @@
|
|||
use crate::{bin::OptU16, err::*,
|
||||
text::{mac_roman_conv, pascal_str},
|
||||
xfer::TransferMode};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Reads a `Sequence`.
|
||||
pub fn read(b: &[u8]) -> ResultS<Sequence>
|
||||
|
@ -72,7 +71,6 @@ pub struct Sequence
|
|||
c_enum! {
|
||||
/// The type of or number of views for a sequence.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum ViewType: u16
|
||||
{
|
||||
Anim = 1,
|
|
@ -1,7 +1,6 @@
|
|||
//! Sounds format definition type.
|
||||
|
||||
use crate::{bin::{u32b, usize_from_u32}, err::*, fixed::*, sound::Sound16};
|
||||
use std::convert::TryFrom;
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// Reads a sound definition.
|
||||
|
@ -90,7 +89,6 @@ bitflags! {
|
|||
c_enum! {
|
||||
/// The type of volume this sound has.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum Volume: u16
|
||||
{
|
||||
Quiet = 0,
|
|
@ -1,6 +1,6 @@
|
|||
//! Sounds file audio type.
|
||||
|
||||
use crate::{bin::usize_from_u32, err::*, sound::Sound16};
|
||||
use crate::{err::*, sound::Sound16};
|
||||
|
||||
/// Reads a sound.
|
||||
pub fn read(b: &[u8]) -> ResultS<Sound16>
|
|
@ -8,7 +8,6 @@ impl Default for TransferMode
|
|||
c_enum! {
|
||||
/// A rendering style for many things.
|
||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub enum TransferMode: u16
|
||||
{
|
||||
Normal = 0,
|
|
@ -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"
|
107
source/map.rs
107
source/map.rs
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Binary file not shown.
|
@ -2,8 +2,8 @@ map::minf::Info{
|
|||
texture_id: 0,
|
||||
physics_id: 1,
|
||||
skypict_id: 1,
|
||||
miss_flags: map::minf::MsnFlags::REPAIR,
|
||||
envi_flags: map::minf::EnvFlags::empty(),
|
||||
entr_flags: map::minf::EntFlags::SOLO | map::minf::EntFlags::CO_OP,
|
||||
miss_flags: map::minf::MissionFlags::REPAIR,
|
||||
envi_flags: map::minf::EnvironmentFlags::empty(),
|
||||
entr_flags: map::minf::EntryFlags::SOLO | map::minf::EntryFlags::CO_OP,
|
||||
level_name: "Waterloo Waterpark".to_owned()
|
||||
}
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -36,7 +36,7 @@ fn defl_alice_2()
|
|||
fn defl_shapes()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
70
tests/map.rs
70
tests/map.rs
|
@ -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]
|
||||
fn map_must_not_process()
|
||||
{
|
||||
for inp in &RANDOM {
|
||||
map::minf::read(inp).err().unwrap();
|
||||
map::minf::read_old(inp).err().unwrap();
|
||||
bin::rd_array(inp, map::fxpx::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_old).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::objs::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_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_old).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::lite::read_old).err().unwrap();
|
||||
bin::rd_array(inp, map::poly::read_old).err().unwrap();
|
||||
bin::rd_array(inp, map::sids::read_old).err().unwrap();
|
||||
bin::rd_array(inp, map::wppx::read).err().unwrap();
|
||||
map::minf::read(inp).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::iidx::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));
|
||||
}
|
||||
}
|
||||
|
||||
#[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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use maraiah::{image::{Color8, pict}};
|
||||
use maraiah::image::{pict, Color8};
|
||||
|
||||
include!("data/rand.rs");
|
||||
|
||||
|
|
|
@ -5,12 +5,11 @@ edition = "2018"
|
|||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
maraiah = {path = "../.."}
|
||||
memmap = "0.7"
|
||||
maraiah = {path = ".."}
|
||||
|
||||
[build-dependencies]
|
||||
cmake = "0.1"
|
||||
maraiah = {path = "../.."}
|
||||
maraiah = {path = ".."}
|
||||
rust_qt_binding_generator = "0.3"
|
||||
|
||||
[[bin]]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue