Merge branch 'master' into gui-branch
commit
708f2e106c
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue