change read_data API

gui-branch
an 2019-03-18 15:31:14 -04:00
parent b830718258
commit 7e5375f32c
9 changed files with 620 additions and 586 deletions

View File

@ -5,75 +5,92 @@ use std::{fmt, num::NonZeroU16};
#[doc(hidden)]
#[macro_export]
macro_rules! _durandal_read_impl {
macro_rules! _rd_impl {
// big endian
(BE $b:expr; $nam:ident u16 $n:expr) => {
_durandal_read_impl!($b; u16::from_be_bytes, $nam 2 $n);
(BIG $b:expr; $nam:ident u16 $n:expr; $at:expr) => {
_rd_impl!($b; u16::from_be_bytes, $nam 2 $n + $at);
};
(BE $b:expr; $nam:ident i16 $n:expr) => {
_durandal_read_impl!($b; i16::from_be_bytes, $nam 2 $n);
(BIG $b:expr; $nam:ident i16 $n:expr; $at:expr) => {
_rd_impl!($b; i16::from_be_bytes, $nam 2 $n + $at);
};
(BE $b:expr; $nam:ident u32 $n:expr) => {
_durandal_read_impl!($b; u32::from_be_bytes, $nam 4 $n);
(BIG $b:expr; $nam:ident u32 $n:expr; $at:expr) => {
_rd_impl!($b; u32::from_be_bytes, $nam 4 $n + $at);
};
(BE $b:expr; $nam:ident i32 $n:expr) => {
_durandal_read_impl!($b; i32::from_be_bytes, $nam 4 $n);
(BIG $b:expr; $nam:ident i32 $n:expr; $at:expr) => {
_rd_impl!($b; i32::from_be_bytes, $nam 4 $n + $at);
};
// little endian
(LE $b:expr; $nam:ident u16 $n:expr) => {
_durandal_read_impl!($b; u16::from_le_bytes, $nam 2 $n);
(LITTLE $b:expr; $nam:ident u16 $n:expr; $at:expr) => {
_rd_impl!($b; u16::from_le_bytes, $nam 2 $n + $at);
};
(LE $b:expr; $nam:ident i16 $n:expr) => {
_durandal_read_impl!($b; i16::from_le_bytes, $nam 2 $n);
(LITTLE $b:expr; $nam:ident i16 $n:expr; $at:expr) => {
_rd_impl!($b; i16::from_le_bytes, $nam 2 $n + $at);
};
(LE $b:expr; $nam:ident u32 $n:expr) => {
_durandal_read_impl!($b; u32::from_le_bytes, $nam 4 $n);
(LITTLE $b:expr; $nam:ident u32 $n:expr; $at:expr) => {
_rd_impl!($b; u32::from_le_bytes, $nam 4 $n + $at);
};
(LE $b:expr; $nam:ident i32 $n:expr) => {
_durandal_read_impl!($b; i32::from_le_bytes, $nam 4 $n);
(LITTLE $b:expr; $nam:ident i32 $n:expr; $at:expr) => {
_rd_impl!($b; i32::from_le_bytes, $nam 4 $n + $at);
};
// either endianness
($e:ident $b:expr; $nam:ident Angle $n:expr) => {
_durandal_read_impl!($e $b; $nam u16 $n);
($e:ident $b:expr; $nam:ident Angle $n:expr; $at:expr) => {
_rd_impl!($e $b; $nam u16 $n; $at);
let $nam = Angle::from_bits($nam);
};
($e:ident $b:expr; $nam:ident Fixed $n:expr) => {
_durandal_read_impl!($e $b; $nam u32 $n);
($e:ident $b:expr; $nam:ident Fixed $n:expr; $at:expr) => {
_rd_impl!($e $b; $nam u32 $n; $at);
let $nam = Fixed::from_bits($nam);
};
($e:ident $b:expr; $nam:ident Unit $n:expr) => {
_durandal_read_impl!($e $b; $nam u16 $n);
($e:ident $b:expr; $nam:ident Unit $n:expr; $at:expr) => {
_rd_impl!($e $b; $nam u16 $n; $at);
let $nam = Unit::from_bits($nam);
};
($e:ident $b:expr; $nam:ident OptU16 $n:expr) => {
_durandal_read_impl!($e $b; $nam u16 $n);
($e:ident $b:expr; $nam:ident OptU16 $n:expr; $at:expr) => {
_rd_impl!($e $b; $nam u16 $n; $at);
let $nam = OptU16::from($nam);
};
($e:ident $b:expr; $nam:ident usize u16 $n:expr) => {
_durandal_read_impl!($e $b; $nam u16 $n);
($e:ident $b:expr; $nam:ident usize u16 $n:expr; $at:expr) => {
_rd_impl!($e $b; $nam u16 $n; $at);
let $nam = usize::from($nam);
};
($e:ident $b:expr; $nam:ident usize u32 $n:expr) => {
_durandal_read_impl!($e $b; $nam u32 $n);
($e:ident $b:expr; $nam:ident usize u32 $n:expr; $at:expr) => {
_rd_impl!($e $b; $nam u32 $n; $at);
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
($_:ident $b:expr; $nam:ident u8 $n:expr) => {let $nam = $b[$n];};
($_:ident $b:expr; $nam:ident slice u8 $n:expr) => {let $nam = &$b[$n];};
($_:ident $b:expr; $nam:ident i8 $n:expr) => {
let $nam = i8::from_ne_bytes([$b[$n]]);
($_:ident $b:expr; $nam:ident u8 $n:expr; $at:expr) => {
let $nam = $b[$n + $at];
};
($_:ident $b:expr; $nam:ident Ident $n:expr) => {
let $nam = Ident([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]);
($_:ident $b:expr; $nam:ident i8 $n:expr; $at:expr) => {
let $nam = $b[$n + $at] as i8;
};
($_:ident $b:expr; $nam:ident $f:ident $n:expr) => {
let $nam = $f(&$b[$n])?;
($_:ident $b:expr; $nam:ident u8 $n:expr; $rn:expr; $at:expr) => {
let $nam = &$b[$n + $at..$n + $at + $rn];
};
($_:ident $b:expr; $nam:ident no_try $f:ident $n:expr) => {
let $nam = $f(&$b[$n]);
($_:ident $b:expr; $nam:ident Ident $n:expr; $at:expr) => {
_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
@ -89,23 +106,31 @@ macro_rules! _durandal_read_impl {
///
/// # Syntax
///
/// First start by specifying the endianness, size and source using the syntax
/// `endian, size in source =>` where:
/// First start by specifying the basic information, using the syntax:
/// `endian: ENDIAN, buf: BUFFER, size: SIZE, start: START,` where:
///
/// - `endian` is `BE` or `LE` for big- or little-endian respectively.
/// - `size` is an expression specifying the last index that should be used by
/// this macro in `source`.
/// - `source` is a `u8` slice to read data from.
/// - `ENDIAN` is `BIG` or `LITTLE` for big- or little-endian respectively.
/// - `BUFFER` is a `u8` slice to read data from. This expression will be
/// evaluated many times, so be careful when specifying it.
/// - `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
/// `name = type[place] opts;` where:
/// Following that is a block with the syntax `data { ... }`. All lines within
/// this block have the syntax `let NAME = TYPE[INDEX] OPTS;` where:
///
/// - `name` is the binding to put the resulting data in.
/// - `type` is one of:
/// - `u8` or `i8`: one byte will be read at `place`.
/// - `u16` or `i16`: two bytes will be read at `place` with `from_*_bytes`.
/// - `u32` or `i32`: four bytes will be read at `place` with `from_*_bytes`.
/// - `Ident`: four bytes will be read at `place` into an array, disregarding
/// - `NAME` is the binding to put the resulting data in.
/// - `TYPE` is one of:
/// - `u8` or `i8`: one byte will be read at `INDEX`. If `INDEX` is a range,
/// this will be a slice into `BUFFER` instead.
/// - `u16` or `i16`: two 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` 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.
/// - `Angle`: same as `u16`, but the result is passed to
/// `fixed::Angle::from_bits`, resulting in a `fixed::Angle` object.
@ -115,24 +140,20 @@ macro_rules! _durandal_read_impl {
/// `fixed::Unit::from_bits`, resulting in a `fixed::Unit` object.
/// - `OptU16`: same as `u16`, but the result is passed to
/// `OptU16::from`, resulting in an `OptU16` object.
/// - The name of a function, which is passed `&source[place]` as its only
/// argument. The function's result has the `?` operator applied to it.
/// - `opts` may be one of:
/// - `slice` when `type` is `u8`: `place` is a range specifying a `u8` slice
/// to be taken from `source`.
/// - `usize` when `type` is `u16` or `u32`: converts the resulting integer to
/// `usize` by `usize_to_u32` for `u32` or by `from` for `u16`.
/// - `no_try` when `type` is a function name: does not use the `?` operator
/// on the resulting function call.
/// - 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.
/// - 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,
/// unless `OPTS` is `no_try`.
/// - `OPT`, if not one of the things listed above, may be `enum TYPE` to apply
/// an enumeration made by `c_enum!`, or `flag TYPE` to apply a bitfield made
/// by `bitflags!`.
/// - `INDEX` is either an integer literal which must be representable as
/// `usize`, or a range with the syntax `INDEX; SIZE` denoting the beginning
/// and size of the range.
///
/// # Panics
///
/// 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
///
@ -144,35 +165,37 @@ macro_rules! _durandal_read_impl {
/// let buffer = &[4, 0, 2, 0, 0, 0, 6];
///
/// read_data! {
/// 7, LE in buffer =>
/// four = u16[0];
/// two = u32[2];
/// six = u8 [6];
/// endian: LITTLE, buf: buffer, size: 7, start: 0, data {
/// let four = u16[0];
/// let two = u32[2];
/// let six = u8[6];
/// let byte = u8[2; 4];
/// }
/// }
///
/// assert_eq!(four, 4_u16);
/// assert_eq!(two, 2_u32);
/// assert_eq!(six, 6_u8);
/// assert_eq!(byte, &[2, 0, 0, 0]);
/// # Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! read_data {
(
$sz:expr , $ty:ident in $b:expr =>
$( $nam:ident = $t:ident [ $n:expr ] $( $ex:ident )* ; )*
endian: $ty:ident, buf: $b:expr, size: $sz:expr, start: $at:expr, data {
$(let $nam:ident = $t:ident[$n:expr $(; $rn:expr)?] $($ex:ident)*;)*
}
) => {
$crate::check_data!($sz, $b);
$($crate::_durandal_read_impl!($ty $b; $nam $($ex)* $t $n);)*
$crate::check_data!($at + $sz, $b);
$($crate::_rd_impl!($ty $b; $nam $($ex)* $t ($n); $(($rn);)? ($at));)*
};
}
/// Checks if there is enough data in `b`.
#[macro_export]
macro_rules! check_data {
(
$sz:expr , $b:expr
) => {
($sz:expr, $b:expr) => {
if $b.len() < $sz {
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);
/// ```
#[inline]
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.
@ -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);
/// ```
#[inline]
pub fn u16b(b: &[u8]) -> u16 {u16::from_be_bytes([b[0], b[1]])}
/// 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);
/// ```
#[inline]
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.
@ -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);
/// ```
#[inline]
pub fn i16b(b: &[u8]) -> i16 {i16::from_be_bytes([b[0], b[1]])}
/// Applies a read function over a slice.

View File

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

View File

@ -8,16 +8,15 @@ use bitflags::bitflags;
pub fn read_lightfunc(b: &[u8]) -> ResultS<LightFunc>
{
read_data! {
14, BE in b =>
ftype = u16[0];
prd_nrm = u16[2];
prd_dta = u16[4];
val_nrm = Fixed[6];
val_dta = Fixed[10];
endian: BIG, buf: b, size: 14, start: 0, data {
let ftype = u16[0] enum LightFuncType;
let prd_nrm = u16[2];
let prd_dta = u16[4];
let val_nrm = Fixed[6];
let val_dta = Fixed[10];
}
}
let ftype = LightFuncType::try_from(ftype)?;
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>
{
read_data! {
6, BE in b =>
offs = read_point[0..4];
tex_id = OptU16[4];
endian: BIG, buf: b, size: 6, start: 0, data {
let offs = read_point[0; 4];
let tex_id = OptU16[4];
}
}
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>
{
read_data! {
4, BE in b =>
x = Unit[0];
y = Unit[2];
endian: BIG, buf: b, size: 4, start: 0, data {
let x = Unit[0];
let y = Unit[2];
}
}
Ok(Point{x, y})
@ -49,20 +50,17 @@ pub fn read_point(b: &[u8]) -> ResultS<Point>
pub fn read_minf(b: &[u8]) -> ResultS<Minf>
{
read_data! {
88, BE in b =>
texture_id = u16[0];
physics_id = u16[2];
skypict_id = u16[4];
miss_flags = u16[6];
envi_flags = u16[8];
level_name = mac_roman_cstr[18..84] no_try;
entr_flags = u32[84];
endian: BIG, buf: b, size: 88, start: 0, data {
let texture_id = u16[0];
let physics_id = u16[2];
let skypict_id = u16[4];
let miss_flags = u16[6] flag MsnFlags;
let envi_flags = u16[8] flag EnvFlags;
let level_name = mac_roman_cstr[18; 66] no_try;
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,
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)>
{
read_data! {
16, BE in b =>
pnt = read_point[6..10];
endian: BIG, buf: b, size: 16, start: 0, data {
let pnt = read_point[6; 4];
}
}
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)>
{
read_data! {
32, BE in b =>
pnt_beg = u16[0];
pnt_end = u16[2];
flags = u16[4];
side_fr = OptU16[12];
side_bk = OptU16[14];
poly_fr = OptU16[16];
poly_bk = OptU16[18];
endian: BIG, buf: b, size: 32, start: 0, data {
let pnt_beg = u16[0];
let pnt_end = u16[2];
let flags = u16[4] flag LineFlags;
let side_fr = OptU16[12];
let side_bk = OptU16[14];
let poly_fr = OptU16[16];
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))
}
@ -133,26 +131,21 @@ pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)>
pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)>
{
read_data! {
64, BE in b =>
stype = u16[0];
flags = u16[2];
tex_pri = read_sidetex[4..10];
tex_sec = read_sidetex[10..16];
tex_tra = read_sidetex[16..22];
paneltyp = u16[38];
paneldat = i16[40];
xfer_pri = u16[42];
xfer_sec = u16[44];
xfer_tra = u16[46];
shade = Fixed[48];
endian: BIG, buf: b, size: 64, start: 0, data {
let stype = u16[0] enum SideType;
let flags = u16[2] flag SideFlags;
let tex_pri = read_sidetex[4; 6];
let tex_sec = read_sidetex[10; 6];
let tex_tra = read_sidetex[16; 6];
let paneltyp = u16[38];
let paneldat = i16[40];
let xfer_pri = u16[42] enum TransferMode;
let xfer_sec = u16[44] enum TransferMode;
let xfer_tra = u16[46] enum TransferMode;
let shade = Fixed[48];
}
}
let flags = flag_ok!(SideFlags, flags)?;
let xfer_pri = TransferMode::try_from(xfer_pri)?;
let xfer_sec = TransferMode::try_from(xfer_sec)?;
let xfer_tra = TransferMode::try_from(xfer_tra)?;
let stype = SideType::try_from(stype)?;
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat,
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>
{
read_data! {
128, BE in b =>
tex_flr = OptU16[40];
tex_cei = OptU16[42];
hei_flr = Unit[44];
hei_cei = Unit[46];
lit_flr = u16[48];
lit_cei = u16[50];
xfr_flr = u16[64];
xfr_cei = u16[66];
endian: BIG, buf: b, size: 128, start: 0, data {
let tex_flr = OptU16[40];
let tex_cei = OptU16[42];
let hei_flr = Unit[44];
let hei_cei = Unit[46];
let lit_flr = u16[48];
let lit_cei = u16[50];
let xfr_flr = u16[64] enum TransferMode;
let xfr_cei = u16[66] enum TransferMode;
}
}
let xfr_flr = TransferMode::try_from(xfr_flr)?;
let xfr_cei = TransferMode::try_from(xfr_cei)?;
Ok(Polygon{tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr,
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)>
{
read_data! {
128, BE in b =>
ptype = u16[0];
pdata = u16[4];
ori_flr = read_point[108..112];
ori_cei = read_point[112..116];
med_ind = OptU16[116];
med_ctl = u16[118];
snd_amb = OptU16[122];
snd_ind = u16[120];
snd_rnd = OptU16[124];
endian: BIG, buf: b, size: 128, start: 0, data {
let ptype = u16[0];
let pdata = u16[4];
let ori_flr = read_point[108; 4];
let ori_cei = read_point[112; 4];
let med_ind = OptU16[116];
let med_ctl = u16[118];
let snd_amb = OptU16[122];
let snd_ind = u16[120];
let snd_rnd = OptU16[124];
}
}
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)>
{
read_data! {
128, BE in b =>
ptype = u16[0];
pdata = u16[4];
endian: BIG, buf: b, size: 128, start: 0, data {
let ptype = u16[0];
let pdata = u16[4];
}
}
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)>
{
read_data! {
100, BE in b =>
ltype = u16[0];
flags = u16[2];
phase = i16[4];
act_pri = read_lightfunc[6..20];
act_sec = read_lightfunc[20..34];
act_mid = read_lightfunc[34..48];
ina_pri = read_lightfunc[48..62];
ina_sec = read_lightfunc[62..76];
ina_mid = read_lightfunc[76..90];
tag = u16[90];
endian: BIG, buf: b, size: 100, start: 0, data {
let ltype = u16[0] enum LightType;
let flags = u16[2] flag LightFlags;
let phase = i16[4];
let act_pri = read_lightfunc[6; 14];
let act_sec = read_lightfunc[20; 14];
let act_mid = read_lightfunc[34; 14];
let ina_pri = read_lightfunc[48; 14];
let ina_sec = read_lightfunc[62; 14];
let ina_mid = read_lightfunc[76; 14];
let tag = u16[90];
}
}
let flags = flag_ok!(LightFlags, flags)?;
let ltype = LightType::try_from(ltype)?;
Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec,
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)>
{
read_data! {
32, BE in b =>
ltype = u16[2] usize;
mode = u16[4];
phase = i16[6];
min = Fixed[8];
max = Fixed[12];
prd = u16[16];
endian: BIG, buf: b, size: 32, start: 0, data {
let ltype = u16[2] usize;
let mode = u16[4];
let phase = i16[6];
let min = Fixed[8];
let max = Fixed[12];
let prd = u16[16];
}
}
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)>
{
read_data! {
16, BE in b =>
group = u16[0];
index = u16[2];
angle = Angle[4];
poly = u16[6];
pos_x = Unit[8];
pos_y = Unit[10];
pos_z = Unit[12];
flags = u16[14];
endian: BIG, buf: b, size: 16, start: 0, data {
let group = u16[0];
let index = u16[2];
let angle = Angle[4];
let poly = u16[6];
let pos_x = Unit[8];
let pos_y = Unit[10];
let pos_z = Unit[12];
let flags = u16[14];
}
}
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)>
{
read_data! {
12, BE in b =>
flags = u16[0];
cnt_ini = u16[2];
cnt_min = u16[4];
cnt_max = u16[6];
cnt_rnd = u16[8];
chance = u16[10];
endian: BIG, buf: b, size: 12, start: 0, data {
let flags = u16[0];
let cnt_ini = u16[2];
let cnt_min = u16[4];
let cnt_max = u16[6];
let cnt_rnd = u16[8];
let chance = u16[10];
}
}
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)>
{
read_data! {
16, BE in b =>
index = u16[2];
volume = u16[4];
endian: BIG, buf: b, size: 16, start: 0, data {
let index = u16[2];
let volume = u16[4];
}
}
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)>
{
read_data! {
32, BE in b =>
flags = u16[0];
index = u16[2];
vol_nrm = u16[4];
vol_dta = u16[6];
prd_nrm = u16[8];
prd_dta = u16[10];
yaw_nrm = Angle[12];
yaw_dta = Angle[14];
pit_nrm = Fixed[16];
pit_dta = Fixed[20];
endian: BIG, buf: b, size: 32, start: 0, data {
let flags = u16[0];
let index = u16[2];
let vol_nrm = u16[4];
let vol_dta = u16[6];
let prd_nrm = u16[8];
let prd_dta = u16[10];
let yaw_nrm = Angle[12];
let yaw_dta = Angle[14];
let pit_nrm = Fixed[16];
let pit_dta = Fixed[20];
}
}
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)>
{
read_data! {
32, BE in b =>
mtype = u16[0];
flags = u16[2];
control = u16[4];
dir = Angle[6];
mag = Unit[8];
hei_lo = Unit[10];
hei_hi = Unit[12];
orig = read_point[14..18];
hei_nrm = Unit[18];
min_lt = Fixed[20];
texture = OptU16[24];
xfer = u16[26];
endian: BIG, buf: b, size: 32, start: 0, data {
let mtype = u16[0] enum MediaType;
let flags = u16[2];
let control = u16[4];
let dir = Angle[6];
let mag = Unit[8];
let hei_lo = Unit[10];
let hei_hi = Unit[12];
let orig = read_point[14; 4];
let hei_nrm = Unit[18];
let min_lt = Fixed[20];
let texture = OptU16[24];
let xfer = u16[26] enum TransferMode;
}
}
let mtype = MediaType::try_from(mtype)?;
let xfer = TransferMode::try_from(xfer)?;
let flr_obs = flags != 0;
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)>
{
read_data! {
32, BE in b =>
ptype = u16[0];
speed = u16[2];
delay = u16[4];
hei_max = Unit[6];
hei_min = Unit[8];
flags = u32[10];
index = u16[14];
tag = u16[16];
endian: BIG, buf: b, size: 32, start: 0, data {
let ptype = u16[0];
let speed = u16[2];
let delay = u16[4];
let hei_max = Unit[6];
let hei_min = Unit[8];
let flags = u32[10] flag PlatformFlags;
let index = u16[14];
let tag = u16[16];
}
}
let flags = flag_ok!(PlatformFlags, flags)?;
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)>
{
read_data! {
72, BE in b =>
pos = read_point[2..6];
poly = u16[6];
text = mac_roman_cstr[8..72] no_try;
endian: BIG, buf: b, size: 72, start: 0, data {
let pos = read_point[2; 4];
let poly = u16[6];
let text = mac_roman_cstr[8; 64] no_try;
}
}
Ok((Note{pos, poly, text}, 72))

View File

@ -7,33 +7,34 @@ use bitflags::bitflags;
pub fn read_pxpx(b: &[u8]) -> ResultS<(Physics, usize)>
{
read_data! {
104, BE in b =>
vel_fwd = Fixed[0];
vel_bkw = Fixed[4];
vel_prp = Fixed[8];
acc_nrm = Fixed[12];
dec_nrm = Fixed[16];
dec_air = Fixed[20];
acc_grv = Fixed[24];
acc_cli = Fixed[28];
vel_trm = Fixed[32];
dec_ext = Fixed[36];
acc_ang = Fixed[40];
dec_ang = Fixed[44];
vel_ang = Fixed[48];
vel_rec = Fixed[52];
fng_vel = Fixed[56];
fng_max = Fixed[60];
ele_max = Fixed[64];
dec_xng = Fixed[68];
stp_dta = Fixed[72];
stp_amp = Fixed[76];
ply_rad = Fixed[80];
ply_hei = Fixed[84];
ply_dhi = Fixed[88];
ply_cam = Fixed[92];
ply_spl = Fixed[96];
ply_hcm = Fixed[100];
endian: BIG, buf: b, size: 104, start: 0, data {
let vel_fwd = Fixed[0];
let vel_bkw = Fixed[4];
let vel_prp = Fixed[8];
let acc_nrm = Fixed[12];
let dec_nrm = Fixed[16];
let dec_air = Fixed[20];
let acc_grv = Fixed[24];
let acc_cli = Fixed[28];
let vel_trm = Fixed[32];
let dec_ext = Fixed[36];
let acc_ang = Fixed[40];
let dec_ang = Fixed[44];
let vel_ang = Fixed[48];
let vel_rec = Fixed[52];
let fng_vel = Fixed[56];
let fng_max = Fixed[60];
let ele_max = Fixed[64];
let dec_xng = Fixed[68];
let stp_dta = Fixed[72];
let stp_amp = Fixed[76];
let ply_rad = Fixed[80];
let ply_hei = Fixed[84];
let ply_dhi = Fixed[88];
let ply_cam = Fixed[92];
let ply_spl = Fixed[96];
let ply_hcm = Fixed[100];
}
}
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)>
{
read_data! {
14, BE in b =>
collection = u16[0];
shape = u16[2];
pitch = Fixed[4];
flags = u16[8];
delay = OptU16[10];
delay_snd = OptU16[12];
endian: BIG, buf: b, size: 14, start: 0, data {
let collection = u16[0];
let shape = u16[2];
let pitch = Fixed[4];
let flags = u16[8] flag EffectFlags;
let delay = OptU16[10];
let delay_snd = OptU16[12];
}
}
let flags = flag_ok!(EffectFlags, flags)?;
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)>
{
read_data! {
134, BE in b =>
typ_item = u16[0];
typ_powerup = OptU16[2];
typ_weapon = u16[4];
flags = u16[6];
lit_value = Fixed[8];
lit_decay = u16[12];
hei_idle = Fixed[14];
amp_bob = Fixed[18];
hei_kick = Fixed[22];
hei_reload = Fixed[26];
wid_idle = Fixed[30];
amp_horz = Fixed[34];
collection = u16[38];
frm_idle = u16[40];
frm_firing = u16[42];
frm_reload = OptU16[44];
frm_charge = OptU16[48];
frm_charged = OptU16[50];
tic_ready = u16[52];
tic_load_beg = u16[54];
tic_load_mid = u16[56];
tic_load_end = u16[58];
tic_powerup = u16[60];
trig_pri = read_trigger[62..98];
trig_sec = read_trigger[98..134];
endian: BIG, buf: b, size: 134, start: 0, data {
let typ_item = u16[0];
let typ_powerup = OptU16[2];
let typ_weapon = u16[4] enum WeaponType;
let flags = u16[6] flag WeaponFlags;
let lit_value = Fixed[8];
let lit_decay = u16[12];
let hei_idle = Fixed[14];
let amp_bob = Fixed[18];
let hei_kick = Fixed[22];
let hei_reload = Fixed[26];
let wid_idle = Fixed[30];
let amp_horz = Fixed[34];
let collection = u16[38];
let frm_idle = u16[40];
let frm_firing = u16[42];
let frm_reload = OptU16[44];
let frm_charge = OptU16[48];
let frm_charged = OptU16[50];
let tic_ready = u16[52];
let tic_load_beg = u16[54];
let tic_load_mid = u16[56];
let tic_load_end = u16[58];
let tic_powerup = u16[60];
let trig_pri = read_trigger[62; 36];
let trig_sec = read_trigger[98; 36];
}
}
let typ_weapon = WeaponType::try_from(typ_weapon)?;
let flags = flag_ok!(WeaponFlags, flags)?;
Ok((Weapon{amp_bob, amp_horz, collection, flags, frm_charge, frm_charged,
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,
@ -106,28 +104,27 @@ pub fn read_wppx(b: &[u8]) -> ResultS<(Weapon, usize)>
pub fn read_prpx(b: &[u8]) -> ResultS<(Projectile, usize)>
{
read_data! {
48, BE in b =>
collection = OptU16[0];
shape = u16[2];
fxt_explode = OptU16[4];
fxt_exp_media = OptU16[6];
fxt_trail = OptU16[8];
tic_trail = u16[10];
max_trail = OptU16[12];
typ_media = OptU16[14];
radius = Unit[16];
dmg_rad = Unit[18];
dmg_def = read_damage[20..32];
flags = u32[32];
speed = Unit[36];
range = Unit[38];
snd_pitch = Fixed[40];
snd_fly = OptU16[44];
snd_bounce = OptU16[46];
endian: BIG, buf: b, size: 48, start: 0, data {
let collection = OptU16[0];
let shape = u16[2];
let fxt_explode = OptU16[4];
let fxt_exp_media = OptU16[6];
let fxt_trail = OptU16[8];
let tic_trail = u16[10];
let max_trail = OptU16[12];
let typ_media = OptU16[14];
let radius = Unit[16];
let dmg_rad = Unit[18];
let dmg_def = read_damage[20; 12];
let flags = u32[32] flag ProjectileFlags;
let speed = Unit[36];
let range = Unit[38];
let snd_pitch = Fixed[40];
let snd_fly = OptU16[44];
let snd_bounce = OptU16[46];
}
}
let flags = flag_ok!(ProjectileFlags, flags)?;
Ok((Projectile{collection, shape, fxt_explode, fxt_exp_media, fxt_trail,
tic_trail, max_trail, typ_media, radius, dmg_rad, dmg_def,
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)>
{
read_data! {
156, BE in b =>
collection = u16[0];
vitality = u16[2];
dty_immune = u32[4];
dty_weak = u32[8];
flags = u32[12];
cls_self = u32[16];
cls_friend = u32[20];
cls_enemy = u32[24];
snd_pitch = Fixed[28];
snd_see_enemy = OptU16[32];
snd_see_friend = OptU16[34];
snd_seeclear = OptU16[36];
snd_kill = OptU16[38];
snd_apologize = OptU16[40];
snd_amicide = OptU16[42];
snd_flaming = OptU16[44];
snd_active = OptU16[46];
snd_active_mask = u16[48];
typ_item = OptU16[50];
radius = Unit[52];
height = Unit[54];
height_hover = Unit[56];
ledge_min = Unit[58];
ledge_max = Unit[60];
ext_vel_scale = Fixed[62];
fxt_impact = OptU16[66];
fxt_impact_melee = OptU16[68];
fxt_trail = OptU16[70];
half_fov_horz = u16[72];
half_fov_vert = u16[74];
view_range = Unit[76];
view_range_dark = Unit[78];
intelligence = u16[80];
speed = u16[82];
gravity = u16[84];
vel_terminal = u16[86];
door_try_mask = u16[88];
expl_radius = OptU16[90];
expl_damage = read_damage[92..104];
seq_hit = OptU16[104];
seq_dying_hard = OptU16[106];
seq_dying_soft = OptU16[108];
seq_dead_hard = OptU16[110];
seq_dead_soft = OptU16[112];
seq_standing = u16[114];
seq_moving = u16[116];
seq_tele_in = OptU16[118];
seq_tele_out = OptU16[120];
atk_frequency = u16[122];
atk_melee = read_attack[124..140];
atk_range = read_attack[140..156];
endian: BIG, buf: b, size: 156, start: 0, data {
let collection = u16[0];
let vitality = u16[2];
let dty_immune = u32[4] flag DamageTypeFlags;
let dty_weak = u32[8] flag DamageTypeFlags;
let flags = u32[12] flag MonsterFlags;
let cls_self = u32[16] flag MonsterClass;
let cls_friend = u32[20];
let cls_enemy = u32[24];
let snd_pitch = Fixed[28];
let snd_see_enemy = OptU16[32];
let snd_see_friend = OptU16[34];
let snd_seeclear = OptU16[36];
let snd_kill = OptU16[38];
let snd_apologize = OptU16[40];
let snd_amicide = OptU16[42];
let snd_flaming = OptU16[44];
let snd_active = OptU16[46];
let snd_active_mask = u16[48];
let typ_item = OptU16[50];
let radius = Unit[52];
let height = Unit[54];
let height_hover = Unit[56];
let ledge_min = Unit[58];
let ledge_max = Unit[60];
let ext_vel_scale = Fixed[62];
let fxt_impact = OptU16[66];
let fxt_impact_melee = OptU16[68];
let fxt_trail = OptU16[70];
let half_fov_horz = u16[72];
let half_fov_vert = u16[74];
let view_range = Unit[76];
let view_range_dark = Unit[78];
let intelligence = u16[80];
let speed = u16[82];
let gravity = u16[84];
let vel_terminal = u16[86];
let door_try_mask = u16[88];
let expl_radius = OptU16[90];
let expl_damage = read_damage[92; 12];
let seq_hit = OptU16[104];
let seq_dying_hard = OptU16[106];
let seq_dying_soft = OptU16[108];
let seq_dead_hard = OptU16[110];
let seq_dead_soft = OptU16[112];
let seq_standing = u16[114];
let seq_moving = u16[116];
let seq_tele_in = OptU16[118];
let seq_tele_out = OptU16[120];
let atk_frequency = u16[122];
let atk_melee = read_attack[124; 16];
let atk_range = read_attack[140; 16];
}
}
// friend and enemy fields MUST truncate because the original source code
// 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_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>
{
read_data! {
36, BE in b =>
magazine = u16[0];
typ_ammo = OptU16[2];
tic_round = OptU16[4];
tic_recover = u16[6];
tic_charge = u16[8];
recoil = Unit[10];
snd_fire = OptU16[12];
snd_click = OptU16[14];
snd_charge = OptU16[16];
snd_casing = OptU16[18];
snd_reload = OptU16[20];
snd_charged = OptU16[22];
typ_proj = u16[24];
theta = u16[26];
dx = i16[28];
dz = i16[30];
typ_casing = u16[32];
burst = u16[34];
endian: BIG, buf: b, size: 36, start: 0, data {
let magazine = u16[0];
let typ_ammo = OptU16[2];
let tic_round = OptU16[4];
let tic_recover = u16[6];
let tic_charge = u16[8];
let recoil = Unit[10];
let snd_fire = OptU16[12];
let snd_click = OptU16[14];
let snd_charge = OptU16[16];
let snd_casing = OptU16[18];
let snd_reload = OptU16[20];
let snd_charged = OptU16[22];
let typ_proj = u16[24];
let theta = u16[26];
let dx = i16[28];
let dz = i16[30];
let typ_casing = u16[32] enum CasingType;
let burst = u16[34];
}
}
let typ_casing = CasingType::try_from(typ_casing)?;
Ok(Trigger{burst, dx, dz, magazine, recoil, snd_casing, snd_charge,
snd_charged, snd_click, snd_fire, snd_reload, theta, tic_charge,
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>
{
read_data! {
12, BE in b =>
dtype = u16[0];
flags = u16[2];
dmg_base = u16[4];
dmg_rand = u16[6];
scale = Fixed[8];
endian: BIG, buf: b, size: 12, start: 0, data {
let dtype = u16[0] enum DamageType;
let flags = u16[2];
let dmg_base = u16[4];
let dmg_rand = u16[6];
let scale = Fixed[8];
}
}
let dtype = DamageType::try_from(dtype)?;
let alien = flags != 0;
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>
{
read_data! {
16, BE in b =>
ptype = OptU16[0];
rep = u16[2];
error = Angle[4];
range = Unit[6];
shape = u16[8];
ofs_x = Unit[10];
ofs_y = Unit[12];
ofs_z = Unit[14];
endian: BIG, buf: b, size: 16, start: 0, data {
let ptype = OptU16[0];
let rep = u16[2];
let error = Angle[4];
let range = Unit[6];
let shape = u16[8];
let ofs_x = Unit[10];
let ofs_y = Unit[12];
let ofs_z = Unit[14];
}
}
Ok(Attack{ptype, rep, error, range, shape, ofs_x, ofs_y, ofs_z})

View File

@ -10,19 +10,17 @@ fn read_pm_header<'a>(b: &'a [u8],
-> ResultS<(&'a [u8], Header)>
{
read_data! {
36, BE in b =>
pt_fl = u16[0];
top = u16[2] usize;
left = u16[4] usize;
bottom = u16[6] usize;
right = u16[8] usize;
pack_t = u16[12];
depth = u16[28];
endian: BIG, buf: b, size: 36, start: 0, data {
let pt_fl = u16[0];
let top = u16[2] usize;
let left = u16[4] usize;
let bottom = u16[6] usize;
let right = u16[8] usize;
let pack_t = u16[12] enum PackType;
let depth = u16[28] enum Depth;
}
}
let pack_t = PackType::try_from(pack_t)?;
let depth = Depth::try_from(depth)?;
if pt_fl & 0x8000 == 0 {
bail!("PICT1 not supported");
}
@ -153,10 +151,11 @@ fn read_pm_32(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
}
read_data! {
p + 3, BE in b =>
r = u8[p];
g = u8[p + 1];
b = u8[p + 2];
endian: BIG, buf: b, size: 3, start: p, data {
let r = u8[0];
let g = u8[1];
let b = u8[2];
}
}
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>
{
read_data! {
10, BE in b =>
h = u16[6] usize;
w = u16[8] usize;
endian: BIG, buf: b, size: 10, start: 0, data {
let h = u16[6] usize;
let w = u16[8] usize;
}
}
if w * h > 16_000_000 {
@ -224,8 +224,9 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
while p < b.len() {
read_data! {
p + 2, BE in b =>
op = u16[p];
endian: BIG, buf: b, size: 2, start: p, data {
let op = u16[0];
}
}
p += 2;
@ -315,9 +316,10 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
{
read_data! {
8, BE in b =>
dev = u16[4];
num = u16[6] usize;
endian: BIG, buf: b, size: 8, start: 0, data {
let dev = u16[4];
let num = u16[6] usize;
}
}
let dev = dev & 0x8000 != 0;
@ -328,11 +330,12 @@ pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
for i in 0..num {
read_data! {
p + 8, BE in b =>
n = u16[p] usize;
r = u8[p + 2];
g = u8[p + 4];
b = u8[p + 6];
endian: BIG, buf: b, size: 8, start: p, data {
let n = u16[0] usize;
let r = u8[2];
let g = u8[4];
let b = u8[6];
}
}
// with device mapping, we ignore the index entirely

View File

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

View File

@ -8,12 +8,13 @@ use std::collections::BTreeMap;
pub fn read_sound(b: &[u8]) -> ResultS<Sound16>
{
read_data! {
21, BE in b =>
len = u32[4] usize;
rate = u16[8];
lp_beg = u32[12] usize;
lp_end = u32[16] usize;
magic = u8[20];
endian: BIG, buf: b, size: 21, start: 0, data {
let len = u32[4] usize;
let rate = u16[8];
let lp_beg = u32[12] usize;
let lp_end = u32[16] usize;
let magic = u8[20];
}
}
match magic {
@ -23,9 +24,10 @@ pub fn read_sound(b: &[u8]) -> ResultS<Sound16>
}
0xFF => {
read_data! {
63, BE in b =>
len = u32[22] usize;
bps = u16[48];
endian: BIG, buf: b, size: 42, start: 22, data {
let len = u32[0] usize;
let bps = u16[26];
}
}
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)>>
{
read_data! {
64, BE in b =>
index = u16[0];
volume = u16[2];
flags = u16[4];
chance = u16[6];
pitch_lo = Fixed[8];
pitch_hi = Fixed[12];
n_sounds = u16[16] usize;
grp_ofs = u32[20] usize;
endian: BIG, buf: b, size: 64, start: 0, data {
let index = u16[0];
let volume = u16[2] enum Volume;
let flags = u16[4] flag SoundFlags;
let chance = u16[6];
let pitch_lo = Fixed[8];
let pitch_hi = Fixed[12];
let n_sounds = u16[16] usize;
let grp_ofs = u32[20] usize;
}
}
let flags = flag_ok!(SoundFlags, flags)?;
let volume = Volume::try_from(volume)?;
if index == u16::max_value() {
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>>
{
read_data! {
260, BE in b =>
version = u32[0];
magic = u8[4..8] slice;
src_num = u16[8] usize;
snd_num = u16[10] usize;
endian: BIG, buf: b, size: 260, start: 0, data {
let version = u32[0];
let magic = Ident[4];
let src_num = u16[8] usize;
let snd_num = u16[10] usize;
}
}
if version != 1 || magic != b"snd2" {

View File

@ -7,16 +7,16 @@ use bitflags::bitflags;
pub fn read_group(b: &[u8]) -> ResultS<(InterGroup, usize)>
{
read_data! {
12, BE in b =>
flags = u16[0];
ttype = u16[2];
pdata = u16[4];
beg = u16[6] usize;
len = u16[8] usize;
lines = u16[10];
endian: BIG, buf: b, size: 12, start: 0, data {
let flags = u16[0] flag GroupFlags;
let ttype = u16[2];
let pdata = u16[4];
let beg = u16[6] usize;
let len = u16[8] usize;
let lines = u16[10];
}
}
let flags = flag_ok!(GroupFlags, flags)?;
let ttype = match ttype {
0 => GroupType::Logon(pdata),
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)>
{
read_data! {
6, BE in b =>
start = u16[0] usize;
face = u16[2];
color = u16[4];
endian: BIG, buf: b, size: 6, start: 0, data {
let start = u16[0] usize;
let face = u16[2];
let color = u16[4];
}
}
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)>
{
read_data! {
10, BE in b =>
end = u16[0] usize;
encoded = u16[2];
lines = u16[4];
group_n = u16[6] usize;
face_n = u16[8] usize;
endian: BIG, buf: b, size: 10, start: 0, data {
let end = u16[0] usize;
let encoded = u16[2];
let lines = u16[4];
let group_n = u16[6] usize;
let face_n = u16[8] usize;
}
}
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() {
read_data! {
p + siz_cnk, BE in b =>
iden = Ident[p];
size = u32[p + 8] usize;
endian: BIG, buf: b, size: siz_cnk, start: p, data {
let iden = Ident[0];
let size = u32[8] usize;
}
}
let beg = p + siz_cnk;
@ -69,9 +70,10 @@ pub fn read_entries(b: &[u8],
-> ResultS<BTreeMap<u16, Entry>>
{
read_data! {
128, BE in b =>
dirofs = u32[72] usize;
numents = u16[76] usize;
endian: BIG, buf: b, size: 128, start: 0, data {
let dirofs = u32[72] usize;
let numents = u16[76] usize;
}
}
let mut entries = BTreeMap::new();
@ -79,10 +81,11 @@ pub fn read_entries(b: &[u8],
for i in 0..numents {
read_data! {
p + siz_ent, BE in b =>
offset = u32[p] usize;
size = u32[p + 4] usize;
index = u16[p + 8];
endian: BIG, buf: b, size: siz_ent, start: p, data {
let offset = u32[0] usize;
let size = u32[4] usize;
let index = u16[8];
}
}
let index = if old_wad {i as u16} else {index};
@ -102,17 +105,18 @@ pub fn read_entries(b: &[u8],
pub fn read_wad(b: &[u8]) -> ResultS<Wad>
{
read_data! {
128, BE in b =>
ver_wad = u16[0];
ver_dat = u16[2];
name = mac_roman_cstr[4..68] no_try;
siz_app = u16[78] usize;
siz_wcnk = u16[80] usize;
siz_went = u16[82] usize;
endian: BIG, buf: b, size: 128, start: 0, data {
let ver_wad = u16[0] enum Ver;
let ver_dat = u16[2];
let name = mac_roman_cstr[4; 64] no_try;
let siz_app = u16[78] usize;
let siz_wcnk = u16[80] usize;
let siz_went = u16[82] usize;
}
}
let old_dat = ver_dat == 0;
let old_wad = match Ver::try_from(ver_wad)? {
let old_wad = match ver_wad {
Ver::Base => true,
_ => false,
};