Merge branch 'master' into gui-branch

gui-branch
an 2019-03-18 16:31:45 -04:00
commit 708f2e106c
11 changed files with 802 additions and 756 deletions

View File

@ -5,75 +5,92 @@ use std::{fmt, num::NonZeroU16};
#[doc(hidden)] #[doc(hidden)]
#[macro_export] #[macro_export]
macro_rules! _durandal_read_impl { macro_rules! _rd_impl {
// big endian // big endian
(BE $b:expr; $nam:ident u16 $n:expr) => { (BIG $b:expr; $nam:ident u16 $n:expr; $at:expr) => {
_durandal_read_impl!($b; u16::from_be_bytes, $nam 2 $n); _rd_impl!($b; u16::from_be_bytes, $nam 2 $n + $at);
}; };
(BE $b:expr; $nam:ident i16 $n:expr) => { (BIG $b:expr; $nam:ident i16 $n:expr; $at:expr) => {
_durandal_read_impl!($b; i16::from_be_bytes, $nam 2 $n); _rd_impl!($b; i16::from_be_bytes, $nam 2 $n + $at);
}; };
(BE $b:expr; $nam:ident u32 $n:expr) => { (BIG $b:expr; $nam:ident u32 $n:expr; $at:expr) => {
_durandal_read_impl!($b; u32::from_be_bytes, $nam 4 $n); _rd_impl!($b; u32::from_be_bytes, $nam 4 $n + $at);
}; };
(BE $b:expr; $nam:ident i32 $n:expr) => { (BIG $b:expr; $nam:ident i32 $n:expr; $at:expr) => {
_durandal_read_impl!($b; i32::from_be_bytes, $nam 4 $n); _rd_impl!($b; i32::from_be_bytes, $nam 4 $n + $at);
}; };
// little endian (LITTLE $b:expr; $nam:ident u16 $n:expr; $at:expr) => {
(LE $b:expr; $nam:ident u16 $n:expr) => { _rd_impl!($b; u16::from_le_bytes, $nam 2 $n + $at);
_durandal_read_impl!($b; u16::from_le_bytes, $nam 2 $n);
}; };
(LE $b:expr; $nam:ident i16 $n:expr) => { (LITTLE $b:expr; $nam:ident i16 $n:expr; $at:expr) => {
_durandal_read_impl!($b; i16::from_le_bytes, $nam 2 $n); _rd_impl!($b; i16::from_le_bytes, $nam 2 $n + $at);
}; };
(LE $b:expr; $nam:ident u32 $n:expr) => { (LITTLE $b:expr; $nam:ident u32 $n:expr; $at:expr) => {
_durandal_read_impl!($b; u32::from_le_bytes, $nam 4 $n); _rd_impl!($b; u32::from_le_bytes, $nam 4 $n + $at);
}; };
(LE $b:expr; $nam:ident i32 $n:expr) => { (LITTLE $b:expr; $nam:ident i32 $n:expr; $at:expr) => {
_durandal_read_impl!($b; i32::from_le_bytes, $nam 4 $n); _rd_impl!($b; i32::from_le_bytes, $nam 4 $n + $at);
}; };
// either endianness // either endianness
($e:ident $b:expr; $nam:ident Angle $n:expr) => { ($e:ident $b:expr; $nam:ident Angle $n:expr; $at:expr) => {
_durandal_read_impl!($e $b; $nam u16 $n); _rd_impl!($e $b; $nam u16 $n; $at);
let $nam = Angle::from_bits($nam); let $nam = Angle::from_bits($nam);
}; };
($e:ident $b:expr; $nam:ident Fixed $n:expr) => { ($e:ident $b:expr; $nam:ident Fixed $n:expr; $at:expr) => {
_durandal_read_impl!($e $b; $nam u32 $n); _rd_impl!($e $b; $nam u32 $n; $at);
let $nam = Fixed::from_bits($nam); let $nam = Fixed::from_bits($nam);
}; };
($e:ident $b:expr; $nam:ident Unit $n:expr) => { ($e:ident $b:expr; $nam:ident Unit $n:expr; $at:expr) => {
_durandal_read_impl!($e $b; $nam u16 $n); _rd_impl!($e $b; $nam u16 $n; $at);
let $nam = Unit::from_bits($nam); let $nam = Unit::from_bits($nam);
}; };
($e:ident $b:expr; $nam:ident OptU16 $n:expr) => { ($e:ident $b:expr; $nam:ident OptU16 $n:expr; $at:expr) => {
_durandal_read_impl!($e $b; $nam u16 $n); _rd_impl!($e $b; $nam u16 $n; $at);
let $nam = OptU16::from_repr($nam); let $nam = OptU16::from($nam);
}; };
($e:ident $b:expr; $nam:ident usize u16 $n:expr) => { ($e:ident $b:expr; $nam:ident usize u16 $n:expr; $at:expr) => {
_durandal_read_impl!($e $b; $nam u16 $n); _rd_impl!($e $b; $nam u16 $n; $at);
let $nam = usize::from($nam); let $nam = usize::from($nam);
}; };
($e:ident $b:expr; $nam:ident usize u32 $n:expr) => { ($e:ident $b:expr; $nam:ident usize u32 $n:expr; $at:expr) => {
_durandal_read_impl!($e $b; $nam u32 $n); _rd_impl!($e $b; $nam u32 $n; $at);
let $nam = usize_from_u32($nam); let $nam = usize_from_u32($nam);
}; };
(
$e:ident $b:expr; $nam:ident enum $et:ident $t:ident $n:expr; $at:expr
) => {
_rd_impl!($e $b; $nam $t $n; $at);
let $nam = $et::try_from($nam)?;
};
(
$e:ident $b:expr; $nam:ident flag $ft:ident $t:ident $n:expr; $at:expr
) => {
_rd_impl!($e $b; $nam $t $n; $at);
let $nam = flag_ok!($ft, $nam)?;
};
// no endianness // no endianness
($_:ident $b:expr; $nam:ident u8 $n:expr) => {let $nam = $b[$n];}; ($_:ident $b:expr; $nam:ident u8 $n:expr; $at:expr) => {
($_:ident $b:expr; $nam:ident slice u8 $n:expr) => {let $nam = &$b[$n];}; let $nam = $b[$n + $at];
($_:ident $b:expr; $nam:ident i8 $n:expr) => {
let $nam = i8::from_ne_bytes([$b[$n]]);
}; };
($_:ident $b:expr; $nam:ident Ident $n:expr) => { ($_:ident $b:expr; $nam:ident i8 $n:expr; $at:expr) => {
let $nam = Ident([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]); let $nam = $b[$n + $at] as i8;
}; };
($_:ident $b:expr; $nam:ident $f:ident $n:expr) => { ($_:ident $b:expr; $nam:ident u8 $n:expr; $rn:expr; $at:expr) => {
let $nam = $f(&$b[$n])?; let $nam = &$b[$n + $at..$n + $at + $rn];
}; };
($_:ident $b:expr; $nam:ident no_try $f:ident $n:expr) => { ($_:ident $b:expr; $nam:ident Ident $n:expr; $at:expr) => {
let $nam = $f(&$b[$n]); _rd_impl!($b; Ident, $nam 4 $n + $at);
};
(
$_:ident $b:expr; $nam:ident no_try $f:ident $n:expr; $rn:expr; $at:expr
) => {
let $nam = $f(&$b[$n + $at..$n + $at + $rn]);
};
($_:ident $b:expr; $nam:ident $f:ident $n:expr; $rn:expr; $at:expr) => {
let $nam = $f(&$b[$n + $at..$n + $at + $rn])?;
}; };
// worker - creates let statement // worker - creates let statement
@ -89,23 +106,31 @@ macro_rules! _durandal_read_impl {
/// ///
/// # Syntax /// # Syntax
/// ///
/// First start by specifying the endianness, size and source using the syntax /// First start by specifying the basic information, using the syntax:
/// `endian, size in source =>` where: /// `endian: ENDIAN, buf: BUFFER, size: SIZE, start: START,` where:
/// ///
/// - `endian` is `BE` or `LE` for big- or little-endian respectively. /// - `ENDIAN` is `BIG` or `LITTLE` for big- or little-endian respectively.
/// - `size` is an expression specifying the last index that should be used by /// - `BUFFER` is a `u8` slice to read data from. This expression will be
/// this macro in `source`. /// evaluated many times, so be careful when specifying it.
/// - `source` is a `u8` slice to read data from. /// - `SIZE` is an expression specifying the last index that should be used by
/// this macro in `BUFFER`.
/// - `START` is an expression specifying the index to start at in `BUFFER`.
/// All indices and sizes will have this added to them.
/// ///
/// After the initializer line, all lines have the syntax /// Following that is a block with the syntax `data { ... }`. All lines within
/// `name = type[place] opts;` where: /// this block have the syntax `let NAME = TYPE[INDEX] OPTS;` where:
/// ///
/// - `name` is the binding to put the resulting data in. /// - `NAME` is the binding to put the resulting data in.
/// - `type` is one of: /// - `TYPE` is one of:
/// - `u8` or `i8`: one byte will be read at `place`. /// - `u8` or `i8`: one byte will be read at `INDEX`. If `INDEX` is a range,
/// - `u16` or `i16`: two bytes will be read at `place` with `from_*_bytes`. /// this will be a slice into `BUFFER` instead.
/// - `u32` or `i32`: four bytes will be read at `place` with `from_*_bytes`. /// - `u16` or `i16`: two bytes will be read at `INDEX` with `from_*_bytes`.
/// - `Ident`: four bytes will be read at `place` into an array, disregarding /// If `OPTS` is `usize`, this converts the resulting number to `usize` by
/// using `usize::from`.
/// - `u32` or `i32`: four bytes will be read at `INDEX` with `from_*_bytes`.
/// If `OPTS` is `usize`, this converts the resulting number to `usize` by
/// using `usize_from_u32`.
/// - `Ident`: four bytes will be read at `INDEX` into an array, disregarding
/// endianness, creating an `Ident` object. /// endianness, creating an `Ident` object.
/// - `Angle`: same as `u16`, but the result is passed to /// - `Angle`: same as `u16`, but the result is passed to
/// `fixed::Angle::from_bits`, resulting in a `fixed::Angle` object. /// `fixed::Angle::from_bits`, resulting in a `fixed::Angle` object.
@ -114,25 +139,21 @@ macro_rules! _durandal_read_impl {
/// - `Unit`: same as `u16`, but the result is passed to /// - `Unit`: same as `u16`, but the result is passed to
/// `fixed::Unit::from_bits`, resulting in a `fixed::Unit` object. /// `fixed::Unit::from_bits`, resulting in a `fixed::Unit` object.
/// - `OptU16`: same as `u16`, but the result is passed to /// - `OptU16`: same as `u16`, but the result is passed to
/// `OptU16::from_repr`, resulting in an `OptU16` object. /// `OptU16::from`, resulting in an `OptU16` object.
/// - The name of a function, which is passed `&source[place]` as its only /// - The name of a function, which is passed the index range as its only
/// argument. The function's result has the `?` operator applied to it. /// argument. The function's result has the `?` operator applied to it,
/// - `opts` may be one of: /// unless `OPTS` is `no_try`.
/// - `slice` when `type` is `u8`: `place` is a range specifying a `u8` slice /// - `OPT`, if not one of the things listed above, may be `enum TYPE` to apply
/// to be taken from `source`. /// an enumeration made by `c_enum!`, or `flag TYPE` to apply a bitfield made
/// - `usize` when `type` is `u16` or `u32`: converts the resulting integer to /// by `bitflags!`.
/// `usize` by `usize_to_u32` for `u32` or by `from` for `u16`. /// - `INDEX` is either an integer literal which must be representable as
/// - `no_try` when `type` is a function name: does not use the `?` operator /// `usize`, or a range with the syntax `INDEX; SIZE` denoting the beginning
/// on the resulting function call. /// and size of the range.
/// - Nothing at all.
/// - `place` is either an integer literal which must be representable as
/// `usize`, or a range, which may only be used when `type` is a function
/// name.
/// ///
/// # Panics /// # Panics
/// ///
/// This macro will not panic unless any index expression used exceeds or /// This macro will not panic unless any index expression used exceeds or
/// equals `size`. /// equals `SIZE + START`, or a function passed to it panics.
/// ///
/// # Examples /// # Examples
/// ///
@ -144,35 +165,37 @@ macro_rules! _durandal_read_impl {
/// let buffer = &[4, 0, 2, 0, 0, 0, 6]; /// let buffer = &[4, 0, 2, 0, 0, 0, 6];
/// ///
/// read_data! { /// read_data! {
/// 7, LE in buffer => /// endian: LITTLE, buf: buffer, size: 7, start: 0, data {
/// four = u16[0]; /// let four = u16[0];
/// two = u32[2]; /// let two = u32[2];
/// six = u8 [6]; /// let six = u8[6];
/// let byte = u8[2; 4];
/// }
/// } /// }
/// ///
/// assert_eq!(four, 4_u16); /// assert_eq!(four, 4_u16);
/// assert_eq!(two, 2_u32); /// assert_eq!(two, 2_u32);
/// assert_eq!(six, 6_u8); /// assert_eq!(six, 6_u8);
/// assert_eq!(byte, &[2, 0, 0, 0]);
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[macro_export] #[macro_export]
macro_rules! read_data { macro_rules! read_data {
( (
$sz:expr , $ty:ident in $b:expr => endian: $ty:ident, buf: $b:expr, size: $sz:expr, start: $at:expr, data {
$( $nam:ident = $t:ident [ $n:expr ] $( $ex:ident )* ; )* $(let $nam:ident = $t:ident[$n:expr $(; $rn:expr)?] $($ex:ident)*;)*
}
) => { ) => {
$crate::check_data!($sz, $b); $crate::check_data!($at + $sz, $b);
$($crate::_durandal_read_impl!($ty $b; $nam $($ex)* $t $n);)* $($crate::_rd_impl!($ty $b; $nam $($ex)* $t ($n); $(($rn);)? ($at));)*
}; };
} }
/// Checks if there is enough data in `b`. /// Checks if there is enough data in `b`.
#[macro_export] #[macro_export]
macro_rules! check_data { macro_rules! check_data {
( ($sz:expr, $b:expr) => {
$sz:expr , $b:expr
) => {
if $b.len() < $sz { if $b.len() < $sz {
return Err(err_msg("not enough data")); return Err(err_msg("not enough data"));
} }
@ -220,6 +243,7 @@ pub const fn ident(b: &[u8]) -> Ident {Ident([b[0], b[1], b[2], b[3]])}
/// ///
/// assert_eq!(u32b(&[0x00, 0x0B, 0xDE, 0x31]), 777_777u32); /// assert_eq!(u32b(&[0x00, 0x0B, 0xDE, 0x31]), 777_777u32);
/// ``` /// ```
#[inline]
pub fn u32b(b: &[u8]) -> u32 {u32::from_be_bytes([b[0], b[1], b[2], b[3]])} pub fn u32b(b: &[u8]) -> u32 {u32::from_be_bytes([b[0], b[1], b[2], b[3]])}
/// Applies `u16::from_be_bytes` to a slice. /// Applies `u16::from_be_bytes` to a slice.
@ -235,6 +259,7 @@ pub fn u32b(b: &[u8]) -> u32 {u32::from_be_bytes([b[0], b[1], b[2], b[3]])}
/// ///
/// assert_eq!(u16b(&[0x1E, 0x61]), 7_777u16); /// assert_eq!(u16b(&[0x1E, 0x61]), 7_777u16);
/// ``` /// ```
#[inline]
pub fn u16b(b: &[u8]) -> u16 {u16::from_be_bytes([b[0], b[1]])} pub fn u16b(b: &[u8]) -> u16 {u16::from_be_bytes([b[0], b[1]])}
/// Applies `i32::from_be_bytes` to a slice. /// Applies `i32::from_be_bytes` to a slice.
@ -250,6 +275,7 @@ pub fn u16b(b: &[u8]) -> u16 {u16::from_be_bytes([b[0], b[1]])}
/// ///
/// assert_eq!(i32b(&[0xFF, 0x89, 0x52, 0x0F]), -7_777_777i32); /// assert_eq!(i32b(&[0xFF, 0x89, 0x52, 0x0F]), -7_777_777i32);
/// ``` /// ```
#[inline]
pub fn i32b(b: &[u8]) -> i32 {i32::from_be_bytes([b[0], b[1], b[2], b[3]])} pub fn i32b(b: &[u8]) -> i32 {i32::from_be_bytes([b[0], b[1], b[2], b[3]])}
/// Applies `i16::from_be_bytes` to a slice. /// Applies `i16::from_be_bytes` to a slice.
@ -265,6 +291,7 @@ pub fn i32b(b: &[u8]) -> i32 {i32::from_be_bytes([b[0], b[1], b[2], b[3]])}
/// ///
/// assert_eq!(i16b(&[0xE1, 0x9F]), -7_777i16); /// assert_eq!(i16b(&[0xE1, 0x9F]), -7_777i16);
/// ``` /// ```
#[inline]
pub fn i16b(b: &[u8]) -> i16 {i16::from_be_bytes([b[0], b[1]])} pub fn i16b(b: &[u8]) -> i16 {i16::from_be_bytes([b[0], b[1]])}
/// Applies a read function over a slice. /// Applies a read function over a slice.
@ -376,6 +403,46 @@ pub fn rd_ofstable<T, F>(b: &[u8],
Ok(v) Ok(v)
} }
impl From<u16> for OptU16
{
#[inline]
fn from(n: u16) -> Self
{
if n == u16::max_value() {
Self(None)
} else {
Self(NonZeroU16::new(n + 1))
}
}
}
impl Into<u16> for OptU16
{
/// Returns the `u16` representation.
///
/// # Examples
///
/// ```
/// use maraiah::durandal::bin::OptU16;
///
/// let u16_max = u16::max_value();
///
/// // These type annotations are necessary.
///
/// assert_eq!(<OptU16 as Into<u16>>::into(OptU16::from(500u16)), 500u16);
/// assert_eq!(<OptU16 as Into<u16>>::into(OptU16::from(u16_max)), u16_max);
/// assert_eq!(<OptU16 as Into<u16>>::into(OptU16::from(0u16)), 0u16);
/// ```
#[inline]
fn into(self) -> u16
{
match self.0 {
None => u16::max_value(),
Some(n) => n.get() - 1,
}
}
}
impl OptU16 impl OptU16
{ {
/// Creates an `OptU16` representing `None`. /// Creates an `OptU16` representing `None`.
@ -385,41 +452,11 @@ impl OptU16
/// ``` /// ```
/// use maraiah::durandal::bin::OptU16; /// use maraiah::durandal::bin::OptU16;
/// ///
/// assert_eq!(OptU16::none(), OptU16::from_repr(u16::max_value())); /// assert_eq!(OptU16::none(), OptU16::from(u16::max_value()));
/// ``` /// ```
#[inline]
pub const fn none() -> Self {Self(None)} pub const fn none() -> Self {Self(None)}
/// Creates an `OptU16` from a `u16`.
pub fn from_repr(n: u16) -> Self
{
if n == u16::max_value() {
Self(None)
} else {
Self(NonZeroU16::new(n + 1))
}
}
/// Returns the `u16` representation.
///
/// # Examples
///
/// ```
/// use maraiah::durandal::bin::OptU16;
///
/// let u16max = u16::max_value();
///
/// assert_eq!(OptU16::from_repr(500u16).get_repr(), 500u16);
/// assert_eq!(OptU16::from_repr(u16max).get_repr(), u16max);
/// assert_eq!(OptU16::from_repr(0u16).get_repr(), 0u16);
/// ```
pub fn get_repr(self) -> u16
{
match self.0 {
None => u16::max_value(),
Some(n) => n.get() - 1,
}
}
/// Returns the `Option` representation. /// Returns the `Option` representation.
/// ///
/// # Examples /// # Examples
@ -427,10 +464,11 @@ impl OptU16
/// ``` /// ```
/// use maraiah::durandal::bin::OptU16; /// use maraiah::durandal::bin::OptU16;
/// ///
/// assert_eq!(OptU16::from_repr(500u16).get(), Some(500u16)); /// assert_eq!(OptU16::from(500u16).get(), Some(500u16));
/// assert_eq!(OptU16::from_repr(u16::max_value()).get(), None); /// assert_eq!(OptU16::from(u16::max_value()).get(), None);
/// assert_eq!(OptU16::from_repr(0u16).get(), Some(0u16)); /// assert_eq!(OptU16::from(0u16).get(), Some(0u16));
/// ``` /// ```
#[inline]
pub fn get(self) -> Option<u16> pub fn get(self) -> Option<u16>
{ {
match self.0 { match self.0 {

View File

@ -6,7 +6,7 @@
/// The syntax is similar to the `bitflags` macro, but each value has the /// The syntax is similar to the `bitflags` macro, but each value has the
/// syntax `value => enumeration`. `enum` is used instead of `struct`. /// syntax `value => enumeration`. `enum` is used instead of `struct`.
/// ///
/// This will generate an `enum $t` as well as a function `$t::from_repr` which /// This will generate an `enum $t` as well as a function `$t::try_from` which
/// will return `Result<$t, ReprError>`. /// will return `Result<$t, ReprError>`.
/// ///
/// # Examples /// # Examples
@ -18,43 +18,44 @@
/// #[derive(Debug)] /// #[derive(Debug)]
/// enum MyEnum: u16 /// enum MyEnum: u16
/// { /// {
/// 0 => Zero, /// Zero = 0,
/// 1 => One, /// One = 1,
/// 2 => Two, /// Two = 2
/// } /// }
/// } /// }
/// ///
/// assert_eq!(MyEnum::from_repr(0), Ok(MyEnum::Zero)); /// assert_eq!(MyEnum::try_from(0), Ok(MyEnum::Zero));
/// assert_eq!(MyEnum::from_repr(1), Ok(MyEnum::One)); /// assert_eq!(MyEnum::try_from(1), Ok(MyEnum::One));
/// assert_eq!(MyEnum::from_repr(2), Ok(MyEnum::Two)); /// assert_eq!(MyEnum::try_from(2), Ok(MyEnum::Two));
/// assert_eq!(MyEnum::from_repr(3), Err(ReprError::new(3))); /// assert_eq!(MyEnum::try_from(3), Err(ReprError::new(3)));
/// assert_eq!(MyEnum::from_repr(4), Err(ReprError::new(4))); /// assert_eq!(MyEnum::try_from(4), Err(ReprError::new(4)));
/// assert_eq!(MyEnum::from_repr(5), Err(ReprError::new(5))); /// assert_eq!(MyEnum::try_from(5), Err(ReprError::new(5)));
/// ``` /// ```
#[macro_export] #[macro_export]
macro_rules! c_enum macro_rules! c_enum
{ {
( (
$(#[$outer:meta])* $(#[$outer:meta])*
$vi:vis enum $t:ident: $ti:ty $vi:vis enum $t:ident: $ti:ident
{ {
$($(#[$inner:meta])* $va:expr => $en:ident,)+ $($en:ident = $va:expr),+ $(,)?
} }
) => { ) => {
$(#[$outer])* $(#[$outer])*
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)] #[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[repr($ti)]
$vi enum $t $vi enum $t
{ {
$($en,)+ $($en = $va,)+
} }
impl $t impl $t
{ {
/// Returns, if representable, the variant of `Self` from `n`. /// Returns, if representable, the variant of `Self` from `n`.
$vi fn from_repr(n: $ti) -> Result<Self, ReprError> $vi fn try_from(n: $ti) -> Result<Self, ReprError>
{ {
match n { match n {
$($(#[$inner])* $va => Ok($t::$en),)+ $($va => Ok($t::$en),)+
n => Err(ReprError::new(n)) n => Err(ReprError::new(n))
} }
} }
@ -71,26 +72,26 @@ mod test
#[derive(Debug)] #[derive(Debug)]
enum TestEnum: u16 enum TestEnum: u16
{ {
0 => Zero, Zero = 0,
1 => One, One = 1,
2 => Two, Two = 2,
} }
} }
#[test] #[test]
fn c_enum_should_be_ok() fn c_enum_should_be_ok()
{ {
assert_eq!(TestEnum::from_repr(0), Ok(TestEnum::Zero)); assert_eq!(TestEnum::try_from(0), Ok(TestEnum::Zero));
assert_eq!(TestEnum::from_repr(1), Ok(TestEnum::One)); assert_eq!(TestEnum::try_from(1), Ok(TestEnum::One));
assert_eq!(TestEnum::from_repr(2), Ok(TestEnum::Two)); assert_eq!(TestEnum::try_from(2), Ok(TestEnum::Two));
assert_eq!(TestEnum::from_repr(3), Err(ReprError::new(3))); assert_eq!(TestEnum::try_from(3), Err(ReprError::new(3)));
assert_eq!(TestEnum::from_repr(4), Err(ReprError::new(4))); assert_eq!(TestEnum::try_from(4), Err(ReprError::new(4)));
assert_eq!(TestEnum::from_repr(5), Err(ReprError::new(5))); assert_eq!(TestEnum::try_from(5), Err(ReprError::new(5)));
} }
#[test] #[test]
#[should_panic] #[should_panic]
fn c_enum_should_error() {TestEnum::from_repr(3).unwrap();} fn c_enum_should_error() {TestEnum::try_from(3).unwrap();}
} }
// EOF // EOF

View File

@ -11,10 +11,11 @@ pub fn load_zlib_header(b: &[u8]) -> ResultS<usize>
const FDICT: u8 = 0b0010_0000; const FDICT: u8 = 0b0010_0000;
read_data! { read_data! {
2, BE in b => endian: BIG, buf: b, size: 2, start: 0, data {
fcheck = u16[0]; let fcheck = u16[0];
cmf = u8[0]; let cmf = u8[0];
flg = u8[1]; let flg = u8[1];
}
} }
let cm = cmf & CM; let cm = cmf & CM;
@ -49,10 +50,11 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
const FRESERVED: u8 = 0xE0; const FRESERVED: u8 = 0xE0;
read_data! { read_data! {
10, LE in b => endian: LITTLE, buf: b, size: 10, start: 0, data {
id = u16[0]; let id = u16[0];
cm = u8[2]; let cm = u8[2];
fl = u8[3]; let fl = u8[3];
}
} }
if id != 0x8B1F || cm != 8 { if id != 0x8B1F || cm != 8 {
@ -66,10 +68,15 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
} }
if fl & FEXTRA != 0 { if fl & FEXTRA != 0 {
read_data!(p + 2, LE in b => xlen = u16[p] usize;); read_data! {
check_data!(p + 2 + xlen, b); endian: LITTLE, buf: b, size: 2, start: p, data {
let xlen = u16[0] usize;
}
}
p += xlen; p += 2 + xlen;
check_data!(p, b);
} }
if fl & FNAME != 0 { if fl & FNAME != 0 {
@ -81,9 +88,9 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
} }
if fl & FHCRC != 0 { if fl & FHCRC != 0 {
check_data!(p + 2, b);
p += 2; p += 2;
check_data!(p, b);
} }
Ok(p) Ok(p)
@ -189,8 +196,9 @@ fn stream_literal(v: &mut Vec<u8>, b: &[u8], p: usize) -> ResultS<usize>
let mut p = p / 8 + 1; let mut p = p / 8 + 1;
read_data! { read_data! {
p + 4, LE in b => endian: LITTLE, buf: b, size: 4, start: p, data {
len = u16[p] usize; let len = u16[0] usize;
}
} }
p += 4; p += 4;

View File

@ -8,16 +8,15 @@ use bitflags::bitflags;
pub fn read_lightfunc(b: &[u8]) -> ResultS<LightFunc> pub fn read_lightfunc(b: &[u8]) -> ResultS<LightFunc>
{ {
read_data! { read_data! {
14, BE in b => endian: BIG, buf: b, size: 14, start: 0, data {
ftype = u16[0]; let ftype = u16[0] enum LightFuncType;
prd_nrm = u16[2]; let prd_nrm = u16[2];
prd_dta = u16[4]; let prd_dta = u16[4];
val_nrm = Fixed[6]; let val_nrm = Fixed[6];
val_dta = Fixed[10]; let val_dta = Fixed[10];
}
} }
let ftype = LightFuncType::from_repr(ftype)?;
Ok(LightFunc{ftype, prd_nrm, prd_dta, val_nrm, val_dta}) Ok(LightFunc{ftype, prd_nrm, prd_dta, val_nrm, val_dta})
} }
@ -25,9 +24,10 @@ pub fn read_lightfunc(b: &[u8]) -> ResultS<LightFunc>
pub fn read_sidetex(b: &[u8]) -> ResultS<SideTex> pub fn read_sidetex(b: &[u8]) -> ResultS<SideTex>
{ {
read_data! { read_data! {
6, BE in b => endian: BIG, buf: b, size: 6, start: 0, data {
offs = read_point[0..4]; let offs = read_point[0; 4];
tex_id = OptU16[4]; let tex_id = OptU16[4];
}
} }
Ok(SideTex{offs, tex_id}) Ok(SideTex{offs, tex_id})
@ -37,9 +37,10 @@ pub fn read_sidetex(b: &[u8]) -> ResultS<SideTex>
pub fn read_point(b: &[u8]) -> ResultS<Point> pub fn read_point(b: &[u8]) -> ResultS<Point>
{ {
read_data! { read_data! {
4, BE in b => endian: BIG, buf: b, size: 4, start: 0, data {
x = Unit[0]; let x = Unit[0];
y = Unit[2]; let y = Unit[2];
}
} }
Ok(Point{x, y}) Ok(Point{x, y})
@ -49,20 +50,17 @@ pub fn read_point(b: &[u8]) -> ResultS<Point>
pub fn read_minf(b: &[u8]) -> ResultS<Minf> pub fn read_minf(b: &[u8]) -> ResultS<Minf>
{ {
read_data! { read_data! {
88, BE in b => endian: BIG, buf: b, size: 88, start: 0, data {
texture_id = u16[0]; let texture_id = u16[0];
physics_id = u16[2]; let physics_id = u16[2];
skypict_id = u16[4]; let skypict_id = u16[4];
miss_flags = u16[6]; let miss_flags = u16[6] flag MsnFlags;
envi_flags = u16[8]; let envi_flags = u16[8] flag EnvFlags;
level_name = mac_roman_cstr[18..84] no_try; let level_name = mac_roman_cstr[18; 66] no_try;
entr_flags = u32[84]; let entr_flags = u32[84] flag EntFlags;
}
} }
let miss_flags = flag_ok!(MsnFlags, miss_flags)?;
let envi_flags = flag_ok!(EnvFlags, envi_flags)?;
let entr_flags = flag_ok!(EntFlags, entr_flags)?;
Ok(Minf{texture_id, physics_id, skypict_id, miss_flags, envi_flags, Ok(Minf{texture_id, physics_id, skypict_id, miss_flags, envi_flags,
entr_flags, level_name}) entr_flags, level_name})
} }
@ -97,8 +95,9 @@ pub fn read_iidx(b: &[u8]) -> ResultS<(u16, usize)>
pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)> pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)>
{ {
read_data! { read_data! {
16, BE in b => endian: BIG, buf: b, size: 16, start: 0, data {
pnt = read_point[6..10]; let pnt = read_point[6; 4];
}
} }
Ok((pnt, 16)) Ok((pnt, 16))
@ -114,18 +113,17 @@ pub fn read_pnts(b: &[u8]) -> ResultS<(Point, usize)>
pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)> pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)>
{ {
read_data! { read_data! {
32, BE in b => endian: BIG, buf: b, size: 32, start: 0, data {
pnt_beg = u16[0]; let pnt_beg = u16[0];
pnt_end = u16[2]; let pnt_end = u16[2];
flags = u16[4]; let flags = u16[4] flag LineFlags;
side_fr = OptU16[12]; let side_fr = OptU16[12];
side_bk = OptU16[14]; let side_bk = OptU16[14];
poly_fr = OptU16[16]; let poly_fr = OptU16[16];
poly_bk = OptU16[18]; let poly_bk = OptU16[18];
}
} }
let flags = flag_ok!(LineFlags, flags)?;
Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32)) Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32))
} }
@ -133,26 +131,21 @@ pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)>
pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)> pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)>
{ {
read_data! { read_data! {
64, BE in b => endian: BIG, buf: b, size: 64, start: 0, data {
stype = u16[0]; let stype = u16[0] enum SideType;
flags = u16[2]; let flags = u16[2] flag SideFlags;
tex_pri = read_sidetex[4..10]; let tex_pri = read_sidetex[4; 6];
tex_sec = read_sidetex[10..16]; let tex_sec = read_sidetex[10; 6];
tex_tra = read_sidetex[16..22]; let tex_tra = read_sidetex[16; 6];
paneltyp = u16[38]; let paneltyp = u16[38];
paneldat = i16[40]; let paneldat = i16[40];
xfer_pri = u16[42]; let xfer_pri = u16[42] enum TransferMode;
xfer_sec = u16[44]; let xfer_sec = u16[44] enum TransferMode;
xfer_tra = u16[46]; let xfer_tra = u16[46] enum TransferMode;
shade = Fixed[48]; let shade = Fixed[48];
}
} }
let flags = flag_ok!(SideFlags, flags)?;
let xfer_pri = TransferMode::from_repr(xfer_pri)?;
let xfer_sec = TransferMode::from_repr(xfer_sec)?;
let xfer_tra = TransferMode::from_repr(xfer_tra)?;
let stype = SideType::from_repr(stype)?;
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat, Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat,
xfer_pri, xfer_sec, xfer_tra, shade}, 64)) xfer_pri, xfer_sec, xfer_tra, shade}, 64))
} }
@ -172,20 +165,18 @@ pub fn read_old_sids(b: &[u8]) -> ResultS<(Side, usize)>
fn read_poly_inter(b: &[u8]) -> ResultS<Polygon> fn read_poly_inter(b: &[u8]) -> ResultS<Polygon>
{ {
read_data! { read_data! {
128, BE in b => endian: BIG, buf: b, size: 128, start: 0, data {
tex_flr = OptU16[40]; let tex_flr = OptU16[40];
tex_cei = OptU16[42]; let tex_cei = OptU16[42];
hei_flr = Unit[44]; let hei_flr = Unit[44];
hei_cei = Unit[46]; let hei_cei = Unit[46];
lit_flr = u16[48]; let lit_flr = u16[48];
lit_cei = u16[50]; let lit_cei = u16[50];
xfr_flr = u16[64]; let xfr_flr = u16[64] enum TransferMode;
xfr_cei = u16[66]; let xfr_cei = u16[66] enum TransferMode;
}
} }
let xfr_flr = TransferMode::from_repr(xfr_flr)?;
let xfr_cei = TransferMode::from_repr(xfr_cei)?;
Ok(Polygon{tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr, Ok(Polygon{tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr,
xfr_cei, ..Default::default()}) xfr_cei, ..Default::default()})
} }
@ -194,16 +185,17 @@ fn read_poly_inter(b: &[u8]) -> ResultS<Polygon>
pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)> pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)>
{ {
read_data! { read_data! {
128, BE in b => endian: BIG, buf: b, size: 128, start: 0, data {
ptype = u16[0]; let ptype = u16[0];
pdata = u16[4]; let pdata = u16[4];
ori_flr = read_point[108..112]; let ori_flr = read_point[108; 4];
ori_cei = read_point[112..116]; let ori_cei = read_point[112; 4];
med_ind = OptU16[116]; let med_ind = OptU16[116];
med_ctl = u16[118]; let med_ctl = u16[118];
snd_amb = OptU16[122]; let snd_amb = OptU16[122];
snd_ind = u16[120]; let snd_ind = u16[120];
snd_rnd = OptU16[124]; let snd_rnd = OptU16[124];
}
} }
let poly = read_poly_inter(b)?; let poly = read_poly_inter(b)?;
@ -217,9 +209,10 @@ pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)>
pub fn read_old_poly(b: &[u8]) -> ResultS<(Polygon, usize)> pub fn read_old_poly(b: &[u8]) -> ResultS<(Polygon, usize)>
{ {
read_data! { read_data! {
128, BE in b => endian: BIG, buf: b, size: 128, start: 0, data {
ptype = u16[0]; let ptype = u16[0];
pdata = u16[4]; let pdata = u16[4];
}
} }
let poly = read_poly_inter(b)?; let poly = read_poly_inter(b)?;
@ -232,22 +225,20 @@ pub fn read_old_poly(b: &[u8]) -> ResultS<(Polygon, usize)>
pub fn read_lite(b: &[u8]) -> ResultS<(Light, usize)> pub fn read_lite(b: &[u8]) -> ResultS<(Light, usize)>
{ {
read_data! { read_data! {
100, BE in b => endian: BIG, buf: b, size: 100, start: 0, data {
ltype = u16[0]; let ltype = u16[0] enum LightType;
flags = u16[2]; let flags = u16[2] flag LightFlags;
phase = i16[4]; let phase = i16[4];
act_pri = read_lightfunc[6..20]; let act_pri = read_lightfunc[6; 14];
act_sec = read_lightfunc[20..34]; let act_sec = read_lightfunc[20; 14];
act_mid = read_lightfunc[34..48]; let act_mid = read_lightfunc[34; 14];
ina_pri = read_lightfunc[48..62]; let ina_pri = read_lightfunc[48; 14];
ina_sec = read_lightfunc[62..76]; let ina_sec = read_lightfunc[62; 14];
ina_mid = read_lightfunc[76..90]; let ina_mid = read_lightfunc[76; 14];
tag = u16[90]; let tag = u16[90];
}
} }
let flags = flag_ok!(LightFlags, flags)?;
let ltype = LightType::from_repr(ltype)?;
Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec, Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec,
ina_mid, tag}, 100)) ina_mid, tag}, 100))
} }
@ -256,13 +247,14 @@ pub fn read_lite(b: &[u8]) -> ResultS<(Light, usize)>
pub fn read_old_lite(b: &[u8]) -> ResultS<(Light, usize)> pub fn read_old_lite(b: &[u8]) -> ResultS<(Light, usize)>
{ {
read_data! { read_data! {
32, BE in b => endian: BIG, buf: b, size: 32, start: 0, data {
ltype = u16[2] usize; let ltype = u16[2] usize;
mode = u16[4]; let mode = u16[4];
phase = i16[6]; let phase = i16[6];
min = Fixed[8]; let min = Fixed[8];
max = Fixed[12]; let max = Fixed[12];
prd = u16[16]; let prd = u16[16];
}
} }
if OLD_LIGHT_DEFINITIONS.len() < ltype { if OLD_LIGHT_DEFINITIONS.len() < ltype {
@ -299,15 +291,16 @@ pub fn read_old_lite(b: &[u8]) -> ResultS<(Light, usize)>
pub fn read_objs(b: &[u8]) -> ResultS<(Object, usize)> pub fn read_objs(b: &[u8]) -> ResultS<(Object, usize)>
{ {
read_data! { read_data! {
16, BE in b => endian: BIG, buf: b, size: 16, start: 0, data {
group = u16[0]; let group = u16[0];
index = u16[2]; let index = u16[2];
angle = Angle[4]; let angle = Angle[4];
poly = u16[6]; let poly = u16[6];
pos_x = Unit[8]; let pos_x = Unit[8];
pos_y = Unit[10]; let pos_y = Unit[10];
pos_z = Unit[12]; let pos_z = Unit[12];
flags = u16[14]; let flags = u16[14];
}
} }
let bias = flags & 0xF0_00; let bias = flags & 0xF0_00;
@ -322,13 +315,14 @@ pub fn read_objs(b: &[u8]) -> ResultS<(Object, usize)>
pub fn read_plac(b: &[u8]) -> ResultS<(ObjectFreq, usize)> pub fn read_plac(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
{ {
read_data! { read_data! {
12, BE in b => endian: BIG, buf: b, size: 12, start: 0, data {
flags = u16[0]; let flags = u16[0];
cnt_ini = u16[2]; let cnt_ini = u16[2];
cnt_min = u16[4]; let cnt_min = u16[4];
cnt_max = u16[6]; let cnt_max = u16[6];
cnt_rnd = u16[8]; let cnt_rnd = u16[8];
chance = u16[10]; let chance = u16[10];
}
} }
let rnd_loc = flags != 0; let rnd_loc = flags != 0;
@ -340,9 +334,10 @@ pub fn read_plac(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
pub fn read_ambi(b: &[u8]) -> ResultS<(SoundAmbi, usize)> pub fn read_ambi(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
{ {
read_data! { read_data! {
16, BE in b => endian: BIG, buf: b, size: 16, start: 0, data {
index = u16[2]; let index = u16[2];
volume = u16[4]; let volume = u16[4];
}
} }
Ok((SoundAmbi{index, volume}, 16)) Ok((SoundAmbi{index, volume}, 16))
@ -352,17 +347,18 @@ pub fn read_ambi(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
pub fn read_bonk(b: &[u8]) -> ResultS<(SoundRand, usize)> pub fn read_bonk(b: &[u8]) -> ResultS<(SoundRand, usize)>
{ {
read_data! { read_data! {
32, BE in b => endian: BIG, buf: b, size: 32, start: 0, data {
flags = u16[0]; let flags = u16[0];
index = u16[2]; let index = u16[2];
vol_nrm = u16[4]; let vol_nrm = u16[4];
vol_dta = u16[6]; let vol_dta = u16[6];
prd_nrm = u16[8]; let prd_nrm = u16[8];
prd_dta = u16[10]; let prd_dta = u16[10];
yaw_nrm = Angle[12]; let yaw_nrm = Angle[12];
yaw_dta = Angle[14]; let yaw_dta = Angle[14];
pit_nrm = Fixed[16]; let pit_nrm = Fixed[16];
pit_dta = Fixed[20]; let pit_dta = Fixed[20];
}
} }
let no_dir = flags != 0; let no_dir = flags != 0;
@ -375,23 +371,22 @@ pub fn read_bonk(b: &[u8]) -> ResultS<(SoundRand, usize)>
pub fn read_medi(b: &[u8]) -> ResultS<(Media, usize)> pub fn read_medi(b: &[u8]) -> ResultS<(Media, usize)>
{ {
read_data! { read_data! {
32, BE in b => endian: BIG, buf: b, size: 32, start: 0, data {
mtype = u16[0]; let mtype = u16[0] enum MediaType;
flags = u16[2]; let flags = u16[2];
control = u16[4]; let control = u16[4];
dir = Angle[6]; let dir = Angle[6];
mag = Unit[8]; let mag = Unit[8];
hei_lo = Unit[10]; let hei_lo = Unit[10];
hei_hi = Unit[12]; let hei_hi = Unit[12];
orig = read_point[14..18]; let orig = read_point[14; 4];
hei_nrm = Unit[18]; let hei_nrm = Unit[18];
min_lt = Fixed[20]; let min_lt = Fixed[20];
texture = OptU16[24]; let texture = OptU16[24];
xfer = u16[26]; let xfer = u16[26] enum TransferMode;
}
} }
let mtype = MediaType::from_repr(mtype)?;
let xfer = TransferMode::from_repr(xfer)?;
let flr_obs = flags != 0; let flr_obs = flags != 0;
Ok((Media{mtype, flr_obs, control, dir, mag, hei_lo, hei_hi, orig, hei_nrm, Ok((Media{mtype, flr_obs, control, dir, mag, hei_lo, hei_hi, orig, hei_nrm,
@ -402,19 +397,18 @@ pub fn read_medi(b: &[u8]) -> ResultS<(Media, usize)>
pub fn read_plat(b: &[u8]) -> ResultS<(Platform, usize)> pub fn read_plat(b: &[u8]) -> ResultS<(Platform, usize)>
{ {
read_data! { read_data! {
32, BE in b => endian: BIG, buf: b, size: 32, start: 0, data {
ptype = u16[0]; let ptype = u16[0];
speed = u16[2]; let speed = u16[2];
delay = u16[4]; let delay = u16[4];
hei_max = Unit[6]; let hei_max = Unit[6];
hei_min = Unit[8]; let hei_min = Unit[8];
flags = u32[10]; let flags = u32[10] flag PlatformFlags;
index = u16[14]; let index = u16[14];
tag = u16[16]; let tag = u16[16];
}
} }
let flags = flag_ok!(PlatformFlags, flags)?;
Ok((Platform{ptype, speed, delay, hei_min, hei_max, flags, index, tag}, 32)) Ok((Platform{ptype, speed, delay, hei_min, hei_max, flags, index, tag}, 32))
} }
@ -422,10 +416,11 @@ pub fn read_plat(b: &[u8]) -> ResultS<(Platform, usize)>
pub fn read_note(b: &[u8]) -> ResultS<(Note, usize)> pub fn read_note(b: &[u8]) -> ResultS<(Note, usize)>
{ {
read_data! { read_data! {
72, BE in b => endian: BIG, buf: b, size: 72, start: 0, data {
pos = read_point[2..6]; let pos = read_point[2; 4];
poly = u16[6]; let poly = u16[6];
text = mac_roman_cstr[8..72] no_try; let text = mac_roman_cstr[8; 64] no_try;
}
} }
Ok((Note{pos, poly, text}, 72)) Ok((Note{pos, poly, text}, 72))
@ -908,11 +903,11 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum SideType: u16 pub enum SideType: u16
{ {
0 => Full, Full = 0,
1 => High, High = 1,
2 => Low, Low = 2,
3 => Composite, Composite = 3,
4 => Split, Split = 4,
} }
} }
@ -922,12 +917,12 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum LightFuncType: u16 pub enum LightFuncType: u16
{ {
0 => Constant, Constant = 0,
1 => Linear, Linear = 1,
2 => Smooth, Smooth = 2,
3 => Flicker, Flicker = 3,
4 => Random, Random = 4,
5 => Fluorescent, Fluorescent = 5,
} }
} }
@ -937,9 +932,9 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum LightType: u16 pub enum LightType: u16
{ {
0 => Normal, Normal = 0,
1 => Strobe, Strobe = 1,
2 => Media, Media = 2,
} }
} }
@ -949,10 +944,10 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum MediaType: u16 pub enum MediaType: u16
{ {
0 => Water, Water = 0,
1 => Lava, Lava = 1,
2 => Goo, Goo = 2,
3 => Sewage, Sewage = 3,
} }
} }

View File

@ -7,33 +7,34 @@ use bitflags::bitflags;
pub fn read_pxpx(b: &[u8]) -> ResultS<(Physics, usize)> pub fn read_pxpx(b: &[u8]) -> ResultS<(Physics, usize)>
{ {
read_data! { read_data! {
104, BE in b => endian: BIG, buf: b, size: 104, start: 0, data {
vel_fwd = Fixed[0]; let vel_fwd = Fixed[0];
vel_bkw = Fixed[4]; let vel_bkw = Fixed[4];
vel_prp = Fixed[8]; let vel_prp = Fixed[8];
acc_nrm = Fixed[12]; let acc_nrm = Fixed[12];
dec_nrm = Fixed[16]; let dec_nrm = Fixed[16];
dec_air = Fixed[20]; let dec_air = Fixed[20];
acc_grv = Fixed[24]; let acc_grv = Fixed[24];
acc_cli = Fixed[28]; let acc_cli = Fixed[28];
vel_trm = Fixed[32]; let vel_trm = Fixed[32];
dec_ext = Fixed[36]; let dec_ext = Fixed[36];
acc_ang = Fixed[40]; let acc_ang = Fixed[40];
dec_ang = Fixed[44]; let dec_ang = Fixed[44];
vel_ang = Fixed[48]; let vel_ang = Fixed[48];
vel_rec = Fixed[52]; let vel_rec = Fixed[52];
fng_vel = Fixed[56]; let fng_vel = Fixed[56];
fng_max = Fixed[60]; let fng_max = Fixed[60];
ele_max = Fixed[64]; let ele_max = Fixed[64];
dec_xng = Fixed[68]; let dec_xng = Fixed[68];
stp_dta = Fixed[72]; let stp_dta = Fixed[72];
stp_amp = Fixed[76]; let stp_amp = Fixed[76];
ply_rad = Fixed[80]; let ply_rad = Fixed[80];
ply_hei = Fixed[84]; let ply_hei = Fixed[84];
ply_dhi = Fixed[88]; let ply_dhi = Fixed[88];
ply_cam = Fixed[92]; let ply_cam = Fixed[92];
ply_spl = Fixed[96]; let ply_spl = Fixed[96];
ply_hcm = Fixed[100]; let ply_hcm = Fixed[100];
}
} }
Ok((Physics{acc_ang, acc_cli, acc_grv, acc_nrm, dec_air, dec_ang, dec_ext, Ok((Physics{acc_ang, acc_cli, acc_grv, acc_nrm, dec_air, dec_ang, dec_ext,
@ -46,17 +47,16 @@ pub fn read_pxpx(b: &[u8]) -> ResultS<(Physics, usize)>
pub fn read_fxpx(b: &[u8]) -> ResultS<(Effect, usize)> pub fn read_fxpx(b: &[u8]) -> ResultS<(Effect, usize)>
{ {
read_data! { read_data! {
14, BE in b => endian: BIG, buf: b, size: 14, start: 0, data {
collection = u16[0]; let collection = u16[0];
shape = u16[2]; let shape = u16[2];
pitch = Fixed[4]; let pitch = Fixed[4];
flags = u16[8]; let flags = u16[8] flag EffectFlags;
delay = OptU16[10]; let delay = OptU16[10];
delay_snd = OptU16[12]; let delay_snd = OptU16[12];
}
} }
let flags = flag_ok!(EffectFlags, flags)?;
Ok((Effect{collection, shape, pitch, flags, delay, delay_snd}, 14)) Ok((Effect{collection, shape, pitch, flags, delay, delay_snd}, 14))
} }
@ -64,37 +64,35 @@ pub fn read_fxpx(b: &[u8]) -> ResultS<(Effect, usize)>
pub fn read_wppx(b: &[u8]) -> ResultS<(Weapon, usize)> pub fn read_wppx(b: &[u8]) -> ResultS<(Weapon, usize)>
{ {
read_data! { read_data! {
134, BE in b => endian: BIG, buf: b, size: 134, start: 0, data {
typ_item = u16[0]; let typ_item = u16[0];
typ_powerup = OptU16[2]; let typ_powerup = OptU16[2];
typ_weapon = u16[4]; let typ_weapon = u16[4] enum WeaponType;
flags = u16[6]; let flags = u16[6] flag WeaponFlags;
lit_value = Fixed[8]; let lit_value = Fixed[8];
lit_decay = u16[12]; let lit_decay = u16[12];
hei_idle = Fixed[14]; let hei_idle = Fixed[14];
amp_bob = Fixed[18]; let amp_bob = Fixed[18];
hei_kick = Fixed[22]; let hei_kick = Fixed[22];
hei_reload = Fixed[26]; let hei_reload = Fixed[26];
wid_idle = Fixed[30]; let wid_idle = Fixed[30];
amp_horz = Fixed[34]; let amp_horz = Fixed[34];
collection = u16[38]; let collection = u16[38];
frm_idle = u16[40]; let frm_idle = u16[40];
frm_firing = u16[42]; let frm_firing = u16[42];
frm_reload = OptU16[44]; let frm_reload = OptU16[44];
frm_charge = OptU16[48]; let frm_charge = OptU16[48];
frm_charged = OptU16[50]; let frm_charged = OptU16[50];
tic_ready = u16[52]; let tic_ready = u16[52];
tic_load_beg = u16[54]; let tic_load_beg = u16[54];
tic_load_mid = u16[56]; let tic_load_mid = u16[56];
tic_load_end = u16[58]; let tic_load_end = u16[58];
tic_powerup = u16[60]; let tic_powerup = u16[60];
trig_pri = read_trigger[62..98]; let trig_pri = read_trigger[62; 36];
trig_sec = read_trigger[98..134]; let trig_sec = read_trigger[98; 36];
}
} }
let typ_weapon = WeaponType::from_repr(typ_weapon)?;
let flags = flag_ok!(WeaponFlags, flags)?;
Ok((Weapon{amp_bob, amp_horz, collection, flags, frm_charge, frm_charged, Ok((Weapon{amp_bob, amp_horz, collection, flags, frm_charge, frm_charged,
frm_firing, frm_idle, frm_reload, hei_idle, hei_kick, hei_reload, frm_firing, frm_idle, frm_reload, hei_idle, hei_kick, hei_reload,
lit_decay, lit_value, tic_load_beg, tic_load_end, tic_load_mid, lit_decay, lit_value, tic_load_beg, tic_load_end, tic_load_mid,
@ -106,28 +104,27 @@ pub fn read_wppx(b: &[u8]) -> ResultS<(Weapon, usize)>
pub fn read_prpx(b: &[u8]) -> ResultS<(Projectile, usize)> pub fn read_prpx(b: &[u8]) -> ResultS<(Projectile, usize)>
{ {
read_data! { read_data! {
48, BE in b => endian: BIG, buf: b, size: 48, start: 0, data {
collection = OptU16[0]; let collection = OptU16[0];
shape = u16[2]; let shape = u16[2];
fxt_explode = OptU16[4]; let fxt_explode = OptU16[4];
fxt_exp_media = OptU16[6]; let fxt_exp_media = OptU16[6];
fxt_trail = OptU16[8]; let fxt_trail = OptU16[8];
tic_trail = u16[10]; let tic_trail = u16[10];
max_trail = OptU16[12]; let max_trail = OptU16[12];
typ_media = OptU16[14]; let typ_media = OptU16[14];
radius = Unit[16]; let radius = Unit[16];
dmg_rad = Unit[18]; let dmg_rad = Unit[18];
dmg_def = read_damage[20..32]; let dmg_def = read_damage[20; 12];
flags = u32[32]; let flags = u32[32] flag ProjectileFlags;
speed = Unit[36]; let speed = Unit[36];
range = Unit[38]; let range = Unit[38];
snd_pitch = Fixed[40]; let snd_pitch = Fixed[40];
snd_fly = OptU16[44]; let snd_fly = OptU16[44];
snd_bounce = OptU16[46]; let snd_bounce = OptU16[46];
}
} }
let flags = flag_ok!(ProjectileFlags, flags)?;
Ok((Projectile{collection, shape, fxt_explode, fxt_exp_media, fxt_trail, Ok((Projectile{collection, shape, fxt_explode, fxt_exp_media, fxt_trail,
tic_trail, max_trail, typ_media, radius, dmg_rad, dmg_def, tic_trail, max_trail, typ_media, radius, dmg_rad, dmg_def,
flags, speed, range, snd_pitch, snd_fly, snd_bounce}, 48)) flags, speed, range, snd_pitch, snd_fly, snd_bounce}, 48))
@ -137,67 +134,64 @@ pub fn read_prpx(b: &[u8]) -> ResultS<(Projectile, usize)>
pub fn read_mnpx(b: &[u8]) -> ResultS<(Monster, usize)> pub fn read_mnpx(b: &[u8]) -> ResultS<(Monster, usize)>
{ {
read_data! { read_data! {
156, BE in b => endian: BIG, buf: b, size: 156, start: 0, data {
collection = u16[0]; let collection = u16[0];
vitality = u16[2]; let vitality = u16[2];
dty_immune = u32[4]; let dty_immune = u32[4] flag DamageTypeFlags;
dty_weak = u32[8]; let dty_weak = u32[8] flag DamageTypeFlags;
flags = u32[12]; let flags = u32[12] flag MonsterFlags;
cls_self = u32[16]; let cls_self = u32[16] flag MonsterClass;
cls_friend = u32[20]; let cls_friend = u32[20];
cls_enemy = u32[24]; let cls_enemy = u32[24];
snd_pitch = Fixed[28]; let snd_pitch = Fixed[28];
snd_see_enemy = OptU16[32]; let snd_see_enemy = OptU16[32];
snd_see_friend = OptU16[34]; let snd_see_friend = OptU16[34];
snd_seeclear = OptU16[36]; let snd_seeclear = OptU16[36];
snd_kill = OptU16[38]; let snd_kill = OptU16[38];
snd_apologize = OptU16[40]; let snd_apologize = OptU16[40];
snd_amicide = OptU16[42]; let snd_amicide = OptU16[42];
snd_flaming = OptU16[44]; let snd_flaming = OptU16[44];
snd_active = OptU16[46]; let snd_active = OptU16[46];
snd_active_mask = u16[48]; let snd_active_mask = u16[48];
typ_item = OptU16[50]; let typ_item = OptU16[50];
radius = Unit[52]; let radius = Unit[52];
height = Unit[54]; let height = Unit[54];
height_hover = Unit[56]; let height_hover = Unit[56];
ledge_min = Unit[58]; let ledge_min = Unit[58];
ledge_max = Unit[60]; let ledge_max = Unit[60];
ext_vel_scale = Fixed[62]; let ext_vel_scale = Fixed[62];
fxt_impact = OptU16[66]; let fxt_impact = OptU16[66];
fxt_impact_melee = OptU16[68]; let fxt_impact_melee = OptU16[68];
fxt_trail = OptU16[70]; let fxt_trail = OptU16[70];
half_fov_horz = u16[72]; let half_fov_horz = u16[72];
half_fov_vert = u16[74]; let half_fov_vert = u16[74];
view_range = Unit[76]; let view_range = Unit[76];
view_range_dark = Unit[78]; let view_range_dark = Unit[78];
intelligence = u16[80]; let intelligence = u16[80];
speed = u16[82]; let speed = u16[82];
gravity = u16[84]; let gravity = u16[84];
vel_terminal = u16[86]; let vel_terminal = u16[86];
door_try_mask = u16[88]; let door_try_mask = u16[88];
expl_radius = OptU16[90]; let expl_radius = OptU16[90];
expl_damage = read_damage[92..104]; let expl_damage = read_damage[92; 12];
seq_hit = OptU16[104]; let seq_hit = OptU16[104];
seq_dying_hard = OptU16[106]; let seq_dying_hard = OptU16[106];
seq_dying_soft = OptU16[108]; let seq_dying_soft = OptU16[108];
seq_dead_hard = OptU16[110]; let seq_dead_hard = OptU16[110];
seq_dead_soft = OptU16[112]; let seq_dead_soft = OptU16[112];
seq_standing = u16[114]; let seq_standing = u16[114];
seq_moving = u16[116]; let seq_moving = u16[116];
seq_tele_in = OptU16[118]; let seq_tele_in = OptU16[118];
seq_tele_out = OptU16[120]; let seq_tele_out = OptU16[120];
atk_frequency = u16[122]; let atk_frequency = u16[122];
atk_melee = read_attack[124..140]; let atk_melee = read_attack[124; 16];
atk_range = read_attack[140..156]; let atk_range = read_attack[140; 16];
}
} }
// friend and enemy fields MUST truncate because the original source code // friend and enemy fields MUST truncate because the original source code
// used `-1` to represent "all classes" which should be invalid normally // used `-1` to represent "all classes" which should be invalid normally
let dty_immune = flag_ok!(DamageTypeFlags, dty_immune)?;
let dty_weak = flag_ok!(DamageTypeFlags, dty_weak)?;
let flags = flag_ok!(MonsterFlags, flags)?;
let cls_self = flag_ok!(MonsterClass, cls_self)?;
let cls_friend = MonsterClass::from_bits_truncate(cls_friend); let cls_friend = MonsterClass::from_bits_truncate(cls_friend);
let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy); let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy);
@ -218,29 +212,28 @@ pub fn read_mnpx(b: &[u8]) -> ResultS<(Monster, usize)>
fn read_trigger(b: &[u8]) -> ResultS<Trigger> fn read_trigger(b: &[u8]) -> ResultS<Trigger>
{ {
read_data! { read_data! {
36, BE in b => endian: BIG, buf: b, size: 36, start: 0, data {
magazine = u16[0]; let magazine = u16[0];
typ_ammo = OptU16[2]; let typ_ammo = OptU16[2];
tic_round = OptU16[4]; let tic_round = OptU16[4];
tic_recover = u16[6]; let tic_recover = u16[6];
tic_charge = u16[8]; let tic_charge = u16[8];
recoil = Unit[10]; let recoil = Unit[10];
snd_fire = OptU16[12]; let snd_fire = OptU16[12];
snd_click = OptU16[14]; let snd_click = OptU16[14];
snd_charge = OptU16[16]; let snd_charge = OptU16[16];
snd_casing = OptU16[18]; let snd_casing = OptU16[18];
snd_reload = OptU16[20]; let snd_reload = OptU16[20];
snd_charged = OptU16[22]; let snd_charged = OptU16[22];
typ_proj = u16[24]; let typ_proj = u16[24];
theta = u16[26]; let theta = u16[26];
dx = i16[28]; let dx = i16[28];
dz = i16[30]; let dz = i16[30];
typ_casing = u16[32]; let typ_casing = u16[32] enum CasingType;
burst = u16[34]; let burst = u16[34];
}
} }
let typ_casing = CasingType::from_repr(typ_casing)?;
Ok(Trigger{burst, dx, dz, magazine, recoil, snd_casing, snd_charge, Ok(Trigger{burst, dx, dz, magazine, recoil, snd_casing, snd_charge,
snd_charged, snd_click, snd_fire, snd_reload, theta, tic_charge, snd_charged, snd_click, snd_fire, snd_reload, theta, tic_charge,
tic_recover, tic_round, typ_ammo, typ_casing, typ_proj}) tic_recover, tic_round, typ_ammo, typ_casing, typ_proj})
@ -250,15 +243,15 @@ fn read_trigger(b: &[u8]) -> ResultS<Trigger>
fn read_damage(b: &[u8]) -> ResultS<Damage> fn read_damage(b: &[u8]) -> ResultS<Damage>
{ {
read_data! { read_data! {
12, BE in b => endian: BIG, buf: b, size: 12, start: 0, data {
dtype = u16[0]; let dtype = u16[0] enum DamageType;
flags = u16[2]; let flags = u16[2];
dmg_base = u16[4]; let dmg_base = u16[4];
dmg_rand = u16[6]; let dmg_rand = u16[6];
scale = Fixed[8]; let scale = Fixed[8];
}
} }
let dtype = DamageType::from_repr(dtype)?;
let alien = flags != 0; let alien = flags != 0;
Ok(Damage{dtype, alien, dmg_base, dmg_rand, scale}) Ok(Damage{dtype, alien, dmg_base, dmg_rand, scale})
@ -268,15 +261,16 @@ fn read_damage(b: &[u8]) -> ResultS<Damage>
fn read_attack(b: &[u8]) -> ResultS<Attack> fn read_attack(b: &[u8]) -> ResultS<Attack>
{ {
read_data! { read_data! {
16, BE in b => endian: BIG, buf: b, size: 16, start: 0, data {
ptype = OptU16[0]; let ptype = OptU16[0];
rep = u16[2]; let rep = u16[2];
error = Angle[4]; let error = Angle[4];
range = Unit[6]; let range = Unit[6];
shape = u16[8]; let shape = u16[8];
ofs_x = Unit[10]; let ofs_x = Unit[10];
ofs_y = Unit[12]; let ofs_y = Unit[12];
ofs_z = Unit[14]; let ofs_z = Unit[14];
}
} }
Ok(Attack{ptype, rep, error, range, shape, ofs_x, ofs_y, ofs_z}) Ok(Attack{ptype, rep, error, range, shape, ofs_x, ofs_y, ofs_z})
@ -653,12 +647,12 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum CasingType: u16 pub enum CasingType: u16
{ {
0 => Rifle, Rifle = 0,
1 => Pistol, Pistol = 1,
2 => PistolLeft, PistolLeft = 2,
3 => PistolRight, PistolRight = 3,
4 => SMG, SMG = 4,
0xFFFF => None, None = 0xFFFF,
} }
} }
@ -668,11 +662,11 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum WeaponType: u16 pub enum WeaponType: u16
{ {
0 => Melee, Melee = 0,
1 => Normal, Normal = 1,
2 => DualFunc, DualFunc = 2,
3 => DualPistol, DualPistol = 3,
4 => Multipurpose, Multipurpose = 4,
} }
} }
@ -682,31 +676,31 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum DamageType: u16 pub enum DamageType: u16
{ {
0 => Explosion, Explosion = 0,
1 => ElectricalStaff, ElectricalStaff = 1,
2 => Projectile, Projectile = 2,
3 => Absorbed, Absorbed = 3,
4 => Flame, Flame = 4,
5 => HoundClaws, HoundClaws = 5,
6 => AlienProjectile, AlienProjectile = 6,
7 => HulkSlap, HulkSlap = 7,
8 => CompilerBolt, CompilerBolt = 8,
9 => FusionBolt, FusionBolt = 9,
10 => HunterBolt, HunterBolt = 10,
11 => Fist, Fist = 11,
12 => Teleporter, Teleporter = 12,
13 => Defender, Defender = 13,
14 => YetiClaws, YetiClaws = 14,
15 => YetiProjectile, YetiProjectile = 15,
16 => Crushing, Crushing = 16,
17 => Lava, Lava = 17,
18 => Suffocation, Suffocation = 18,
19 => Goo, Goo = 19,
20 => EnergyDrain, EnergyDrain = 20,
21 => OxygenDrain, OxygenDrain = 21,
22 => HummerBolt, HummerBolt = 22,
23 => ShotgunProjectile, ShotgunProjectile = 23,
0xFFFF => None, None = 0xFFFF,
} }
} }

View File

@ -10,19 +10,17 @@ fn read_pm_header<'a>(b: &'a [u8],
-> ResultS<(&'a [u8], Header)> -> ResultS<(&'a [u8], Header)>
{ {
read_data! { read_data! {
36, BE in b => endian: BIG, buf: b, size: 36, start: 0, data {
pt_fl = u16[0]; let pt_fl = u16[0];
top = u16[2] usize; let top = u16[2] usize;
left = u16[4] usize; let left = u16[4] usize;
bottom = u16[6] usize; let bottom = u16[6] usize;
right = u16[8] usize; let right = u16[8] usize;
pack_t = u16[12]; let pack_t = u16[12] enum PackType;
depth = u16[28]; let depth = u16[28] enum Depth;
}
} }
let pack_t = PackType::from_repr(pack_t)?;
let depth = Depth::from_repr(depth)?;
if pt_fl & 0x8000 == 0 { if pt_fl & 0x8000 == 0 {
bail!("PICT1 not supported"); bail!("PICT1 not supported");
} }
@ -153,10 +151,11 @@ fn read_pm_32(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
} }
read_data! { read_data! {
p + 3, BE in b => endian: BIG, buf: b, size: 3, start: p, data {
r = u8[p]; let r = u8[0];
g = u8[p + 1]; let g = u8[1];
b = u8[p + 2]; let b = u8[2];
}
} }
im.cr.push(Color8::new(r, g, b)); im.cr.push(Color8::new(r, g, b));
@ -209,9 +208,10 @@ fn read_pm_area(im: Image8, b: &[u8], pack: bool, clip: bool)
pub fn load_pict(b: &[u8]) -> ResultS<Image8> pub fn load_pict(b: &[u8]) -> ResultS<Image8>
{ {
read_data! { read_data! {
10, BE in b => endian: BIG, buf: b, size: 10, start: 0, data {
h = u16[6] usize; let h = u16[6] usize;
w = u16[8] usize; let w = u16[8] usize;
}
} }
if w * h > 16_000_000 { if w * h > 16_000_000 {
@ -224,8 +224,9 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
while p < b.len() { while p < b.len() {
read_data! { read_data! {
p + 2, BE in b => endian: BIG, buf: b, size: 2, start: p, data {
op = u16[p]; let op = u16[0];
}
} }
p += 2; p += 2;
@ -315,9 +316,10 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)> pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
{ {
read_data! { read_data! {
8, BE in b => endian: BIG, buf: b, size: 8, start: 0, data {
dev = u16[4]; let dev = u16[4];
num = u16[6] usize; let num = u16[6] usize;
}
} }
let dev = dev & 0x8000 != 0; let dev = dev & 0x8000 != 0;
@ -328,11 +330,12 @@ pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
for i in 0..num { for i in 0..num {
read_data! { read_data! {
p + 8, BE in b => endian: BIG, buf: b, size: 8, start: p, data {
n = u16[p] usize; let n = u16[0] usize;
r = u8[p + 2]; let r = u8[2];
g = u8[p + 4]; let g = u8[4];
b = u8[p + 6]; let b = u8[6];
}
} }
// with device mapping, we ignore the index entirely // with device mapping, we ignore the index entirely
@ -481,23 +484,23 @@ struct Header
c_enum! { c_enum! {
enum Depth: u16 enum Depth: u16
{ {
1 => Bits1, Bits1 = 1,
2 => Bits2, Bits2 = 2,
4 => Bits4, Bits4 = 4,
8 => Bits8, Bits8 = 8,
16 => Bits16, Bits16 = 16,
32 => Bits32, Bits32 = 32,
} }
} }
c_enum! { c_enum! {
enum PackType: u16 enum PackType: u16
{ {
0 => Default, Default = 0,
1 => None, None = 1,
2 => NoPad, NoPad = 2,
3 => Rle16, Rle16 = 3,
4 => Rle32, Rle32 = 4,
} }
} }

View File

@ -8,12 +8,13 @@ use bitflags::bitflags;
fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()> fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
{ {
read_data! { read_data! {
8, BE in b => endian: BIG, buf: b, size: 8, start: 0, data {
flag = u8[0]; let flag = u8[0];
ind = u8[1]; let ind = u8[1];
r = u16[2]; let r = u16[2];
g = u16[4]; let g = u16[4];
b = u16[6]; let b = u16[6];
}
} }
let cr = ok!(clut.get_mut(usize::from(ind)), "bad index")?; let cr = ok!(clut.get_mut(usize::from(ind)), "bad index")?;
@ -57,16 +58,16 @@ fn color_tables(b: &[u8],
pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap> pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap>
{ {
read_data! { read_data! {
26, BE in b => endian: BIG, buf: b, size: 26, start: 0, data {
width = u16[0] usize; let width = u16[0] usize;
height = u16[2] usize; let height = u16[2] usize;
compr = u16[4]; let compr = u16[4];
flags = u16[6]; let flags = u16[6] flag BmpFlags;
depth = u16[8]; let depth = u16[8];
}
} }
let compr = compr == u16::max_value(); let compr = compr == u16::max_value();
let flags = flag_ok!(BmpFlags, flags)?;
let alpha = flags.contains(BmpFlags::TRANSPARENT); let alpha = flags.contains(BmpFlags::TRANSPARENT);
let cmajr = flags.contains(BmpFlags::COLUMN_MAJOR); let cmajr = flags.contains(BmpFlags::COLUMN_MAJOR);
@ -84,9 +85,10 @@ pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap>
// compressed scanlines (transparency RLE) // compressed scanlines (transparency RLE)
for _ in 0..scanlines { for _ in 0..scanlines {
read_data! { read_data! {
p + 4, BE in b => endian: BIG, buf: b, size: 4, start: p, data {
fst = u16[p] usize; let fst = u16[0] usize;
lst = u16[p + 2] usize; let lst = u16[2] usize;
}
} }
let end = lst - fst; let end = lst - fst;
@ -122,20 +124,19 @@ pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap>
pub fn read_frame(b: &[u8]) -> ResultS<Frame> pub fn read_frame(b: &[u8]) -> ResultS<Frame>
{ {
read_data! { read_data! {
36, BE in b => endian: BIG, buf: b, size: 36, start: 0, data {
flags = u16[0]; let flags = u16[0] flag FrameFlags;
min_lt = Fixed[2]; let min_lt = Fixed[2];
bmp_ind = u16[6] usize; let bmp_ind = u16[6] usize;
wrl_l = Unit[16]; let wrl_l = Unit[16];
wrl_r = Unit[18]; let wrl_r = Unit[18];
wrl_t = Unit[20]; let wrl_t = Unit[20];
wrl_b = Unit[22]; let wrl_b = Unit[22];
wrl_x = Unit[24]; let wrl_x = Unit[24];
wrl_y = Unit[26]; let wrl_y = Unit[26];
}
} }
let flags = flag_ok!(FrameFlags, flags)?;
Ok(Frame{flags, min_lt, bmp_ind, wrl_l, wrl_r, wrl_t, wrl_b, wrl_x, wrl_y}) Ok(Frame{flags, min_lt, bmp_ind, wrl_l, wrl_r, wrl_t, wrl_b, wrl_x, wrl_y})
} }
@ -143,23 +144,22 @@ pub fn read_frame(b: &[u8]) -> ResultS<Frame>
pub fn read_sequence(b: &[u8]) -> ResultS<Sequence> pub fn read_sequence(b: &[u8]) -> ResultS<Sequence>
{ {
read_data! { read_data! {
88, BE in b => endian: BIG, buf: b, size: 88, start: 0, data {
name = u8[4..38] slice; let name = u8[4; 34];
v_type = u16[38]; let v_type = u16[38] enum ViewType;
frames = u16[40]; let frames = u16[40];
ticks = u16[42]; let ticks = u16[42];
key = u16[44]; let key = u16[44];
xfer = u16[46]; let xfer = u16[46] enum TransferMode;
xfer_pd = u16[48]; let xfer_pd = u16[48];
snd_beg = OptU16[50]; let snd_beg = OptU16[50];
snd_key = OptU16[52]; let snd_key = OptU16[52];
snd_end = OptU16[54]; let snd_end = OptU16[54];
loop_f = u16[58]; let loop_f = u16[58];
}
} }
let name = mac_roman_conv(ok!(pascal_str(name), "bad string")?); let name = mac_roman_conv(ok!(pascal_str(name), "bad string")?);
let xfer = TransferMode::from_repr(xfer)?;
let v_type = ViewType::from_repr(v_type)?;
Ok(Sequence{name, v_type, frames, ticks, key, xfer, xfer_pd, snd_beg, Ok(Sequence{name, v_type, frames, ticks, key, xfer, xfer_pd, snd_beg,
snd_key, snd_end, loop_f}) snd_key, snd_end, loop_f})
@ -169,22 +169,21 @@ pub fn read_sequence(b: &[u8]) -> ResultS<Sequence>
pub fn read_collection(b: &[u8]) -> ResultS<Collection> pub fn read_collection(b: &[u8]) -> ResultS<Collection>
{ {
read_data! { read_data! {
544, BE in b => endian: BIG, buf: b, size: 544, start: 0, data {
version = u16[0]; let version = u16[0];
cl_type = u16[2]; let cl_type = u16[2] enum CollectionType;
clr_num = u16[6] usize; let clr_num = u16[6] usize;
tab_num = u16[8] usize; let tab_num = u16[8] usize;
tab_ofs = u32[10] usize; let tab_ofs = u32[10] usize;
seq_num = u16[14] usize; let seq_num = u16[14] usize;
seq_ofs = u32[16] usize; let seq_ofs = u32[16] usize;
frm_num = u16[20] usize; let frm_num = u16[20] usize;
frm_ofs = u32[22] usize; let frm_ofs = u32[22] usize;
bmp_num = u16[26] usize; let bmp_num = u16[26] usize;
bmp_ofs = u32[28] usize; let bmp_ofs = u32[28] usize;
}
} }
let cl_type = CollectionType::from_repr(cl_type)?;
if version != 3 { if version != 3 {
bail!("invalid collection definition"); bail!("invalid collection definition");
} }
@ -205,11 +204,12 @@ pub fn read_shapes(b: &[u8]) -> ResultS<Vec<CollectionDef>>
for _ in 0..32 { for _ in 0..32 {
read_data! { read_data! {
p + 32, BE in b => endian: BIG, buf: b, size: 32, start: p, data {
lo_ofs = u32[p + 4] usize; let lo_ofs = u32[4] usize;
lo_len = u32[p + 8] usize; let lo_len = u32[8] usize;
hi_ofs = u32[p + 12] usize; let hi_ofs = u32[12] usize;
hi_len = u32[p + 16] usize; let hi_len = u32[16] usize;
}
} }
let c_lo = if lo_ofs == usize_from_u32(u32::max_value()) { let c_lo = if lo_ofs == usize_from_u32(u32::max_value()) {
@ -478,11 +478,11 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum CollectionType: u16 pub enum CollectionType: u16
{ {
0 => Unused, Unused = 0,
1 => Wall, Wall = 1,
2 => Object, Object = 2,
3 => Interface, Interface = 3,
4 => Scenery, Scenery = 4,
} }
} }
@ -492,15 +492,15 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum ViewType: u16 pub enum ViewType: u16
{ {
1 => Anim, Anim = 1,
2 => Anim8from2, Anim8from2 = 2,
3 => Anim4from3, Anim4from3 = 3,
4 => Anim4, Anim4 = 4,
5 => Anim8from5, Anim8from5 = 5,
8 => Anim8, Anim8 = 8,
9 => Anim5from3, Anim5from3 = 9,
10 => Still, Still = 10,
11 => Anim5, Anim5 = 11,
} }
} }

View File

@ -8,12 +8,13 @@ use std::collections::BTreeMap;
pub fn read_sound(b: &[u8]) -> ResultS<Sound16> pub fn read_sound(b: &[u8]) -> ResultS<Sound16>
{ {
read_data! { read_data! {
21, BE in b => endian: BIG, buf: b, size: 21, start: 0, data {
len = u32[4] usize; let len = u32[4] usize;
rate = u16[8]; let rate = u16[8];
lp_beg = u32[12] usize; let lp_beg = u32[12] usize;
lp_end = u32[16] usize; let lp_end = u32[16] usize;
magic = u8[20]; let magic = u8[20];
}
} }
match magic { match magic {
@ -23,9 +24,10 @@ pub fn read_sound(b: &[u8]) -> ResultS<Sound16>
} }
0xFF => { 0xFF => {
read_data! { read_data! {
63, BE in b => endian: BIG, buf: b, size: 42, start: 22, data {
len = u32[22] usize; let len = u32[0] usize;
bps = u16[48]; let bps = u16[26];
}
} }
match bps { match bps {
@ -48,20 +50,18 @@ pub fn read_sound(b: &[u8]) -> ResultS<Sound16>
pub fn read_sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>> pub fn read_sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
{ {
read_data! { read_data! {
64, BE in b => endian: BIG, buf: b, size: 64, start: 0, data {
index = u16[0]; let index = u16[0];
volume = u16[2]; let volume = u16[2] enum Volume;
flags = u16[4]; let flags = u16[4] flag SoundFlags;
chance = u16[6]; let chance = u16[6];
pitch_lo = Fixed[8]; let pitch_lo = Fixed[8];
pitch_hi = Fixed[12]; let pitch_hi = Fixed[12];
n_sounds = u16[16] usize; let n_sounds = u16[16] usize;
grp_ofs = u32[20] usize; let grp_ofs = u32[20] usize;
}
} }
let flags = flag_ok!(SoundFlags, flags)?;
let volume = Volume::from_repr(volume)?;
if index == u16::max_value() { if index == u16::max_value() {
return Ok(None); return Ok(None);
} }
@ -88,11 +88,12 @@ pub fn read_sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>> pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>>
{ {
read_data! { read_data! {
260, BE in b => endian: BIG, buf: b, size: 260, start: 0, data {
version = u32[0]; let version = u32[0];
magic = u8[4..8] slice; let magic = Ident[4];
src_num = u16[8] usize; let src_num = u16[8] usize;
snd_num = u16[10] usize; let snd_num = u16[10] usize;
}
} }
if version != 1 || magic != b"snd2" { if version != 1 || magic != b"snd2" {
@ -177,9 +178,9 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum Volume: u16 pub enum Volume: u16
{ {
0 => Quiet, Quiet = 0,
1 => Normal, Normal = 1,
2 => Loud, Loud = 2,
} }
} }

View File

@ -7,16 +7,16 @@ use bitflags::bitflags;
pub fn read_group(b: &[u8]) -> ResultS<(InterGroup, usize)> pub fn read_group(b: &[u8]) -> ResultS<(InterGroup, usize)>
{ {
read_data! { read_data! {
12, BE in b => endian: BIG, buf: b, size: 12, start: 0, data {
flags = u16[0]; let flags = u16[0] flag GroupFlags;
ttype = u16[2]; let ttype = u16[2];
pdata = u16[4]; let pdata = u16[4];
beg = u16[6] usize; let beg = u16[6] usize;
len = u16[8] usize; let len = u16[8] usize;
lines = u16[10]; let lines = u16[10];
}
} }
let flags = flag_ok!(GroupFlags, flags)?;
let ttype = match ttype { let ttype = match ttype {
0 => GroupType::Logon(pdata), 0 => GroupType::Logon(pdata),
1 => GroupType::Unfinished, 1 => GroupType::Unfinished,
@ -45,10 +45,11 @@ pub fn read_group(b: &[u8]) -> ResultS<(InterGroup, usize)>
pub fn read_face(b: &[u8]) -> ResultS<(Face, usize)> pub fn read_face(b: &[u8]) -> ResultS<(Face, usize)>
{ {
read_data! { read_data! {
6, BE in b => endian: BIG, buf: b, size: 6, start: 0, data {
start = u16[0] usize; let start = u16[0] usize;
face = u16[2]; let face = u16[2];
color = u16[4]; let color = u16[4];
}
} }
Ok((Face{start, face, color}, 6)) Ok((Face{start, face, color}, 6))
@ -58,12 +59,13 @@ pub fn read_face(b: &[u8]) -> ResultS<(Face, usize)>
pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)> pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
{ {
read_data! { read_data! {
10, BE in b => endian: BIG, buf: b, size: 10, start: 0, data {
end = u16[0] usize; let end = u16[0] usize;
encoded = u16[2]; let encoded = u16[2];
lines = u16[4]; let lines = u16[4];
group_n = u16[6] usize; let group_n = u16[6] usize;
face_n = u16[8] usize; let face_n = u16[8] usize;
}
} }
let encoded = encoded != 0; let encoded = encoded != 0;

View File

@ -18,9 +18,10 @@ pub fn read_chunks(b: &[u8], old_dat: bool, siz_cnk: usize)
while p < b.len() { while p < b.len() {
read_data! { read_data! {
p + siz_cnk, BE in b => endian: BIG, buf: b, size: siz_cnk, start: p, data {
iden = Ident[p]; let iden = Ident[0];
size = u32[p + 8] usize; let size = u32[8] usize;
}
} }
let beg = p + siz_cnk; let beg = p + siz_cnk;
@ -69,9 +70,10 @@ pub fn read_entries(b: &[u8],
-> ResultS<BTreeMap<u16, Entry>> -> ResultS<BTreeMap<u16, Entry>>
{ {
read_data! { read_data! {
128, BE in b => endian: BIG, buf: b, size: 128, start: 0, data {
dirofs = u32[72] usize; let dirofs = u32[72] usize;
numents = u16[76] usize; let numents = u16[76] usize;
}
} }
let mut entries = BTreeMap::new(); let mut entries = BTreeMap::new();
@ -79,10 +81,11 @@ pub fn read_entries(b: &[u8],
for i in 0..numents { for i in 0..numents {
read_data! { read_data! {
p + siz_ent, BE in b => endian: BIG, buf: b, size: siz_ent, start: p, data {
offset = u32[p] usize; let offset = u32[0] usize;
size = u32[p + 4] usize; let size = u32[4] usize;
index = u16[p + 8]; let index = u16[8];
}
} }
let index = if old_wad {i as u16} else {index}; let index = if old_wad {i as u16} else {index};
@ -102,17 +105,18 @@ pub fn read_entries(b: &[u8],
pub fn read_wad(b: &[u8]) -> ResultS<Wad> pub fn read_wad(b: &[u8]) -> ResultS<Wad>
{ {
read_data! { read_data! {
128, BE in b => endian: BIG, buf: b, size: 128, start: 0, data {
ver_wad = u16[0]; let ver_wad = u16[0] enum Ver;
ver_dat = u16[2]; let ver_dat = u16[2];
name = mac_roman_cstr[4..68] no_try; let name = mac_roman_cstr[4; 64] no_try;
siz_app = u16[78] usize; let siz_app = u16[78] usize;
siz_wcnk = u16[80] usize; let siz_wcnk = u16[80] usize;
siz_went = u16[82] usize; let siz_went = u16[82] usize;
}
} }
let old_dat = ver_dat == 0; let old_dat = ver_dat == 0;
let old_wad = match Ver::from_repr(ver_wad)? { let old_wad = match ver_wad {
Ver::Base => true, Ver::Base => true,
_ => false, _ => false,
}; };
@ -217,10 +221,10 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
enum Ver: u16 enum Ver: u16
{ {
0 => Base, Base = 0,
1 => Dir, Dir = 1,
2 => Over, Over = 2,
4 => Inf, Inf = 4,
} }
} }

View File

@ -13,28 +13,28 @@ c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum TransferMode: u16 pub enum TransferMode: u16
{ {
0 => Normal, Normal = 0,
1 => FadeBlack, FadeBlack = 1,
2 => Invisibility, Invisibility = 2,
3 => Invisibility2, Invisibility2 = 3,
4 => Pulsate, Pulsate = 4,
5 => Wobble, Wobble = 5,
6 => Wobble2, Wobble2 = 6,
7 => Static, Static = 7,
8 => Static2, Static2 = 8,
9 => Sky, Sky = 9,
10 => Smear, Smear = 10,
11 => StaticFade, StaticFade = 11,
12 => StaticPulse, StaticPulse = 12,
13 => FoldIn, FoldIn = 13,
14 => FoldOut, FoldOut = 14,
15 => SlideHorz, SlideHorz = 15,
16 => SlideHorz2, SlideHorz2 = 16,
17 => SlideVert, SlideVert = 17,
18 => SlideVert2, SlideVert2 = 18,
19 => Wander, Wander = 19,
20 => Wander2, Wander2 = 20,
21 => BigSky, BigSky = 21,
} }
} }