Compare commits

...

7 Commits

Author SHA1 Message Date
an 7e92521e2e crap 2019-03-22 01:34:21 -04:00
an aa0f6cf537 output resources to the correct directory and handle errors 2019-03-21 21:20:53 -04:00
an 708f2e106c Merge branch 'master' into gui-branch 2019-03-18 16:31:45 -04:00
an 7e5375f32c change read_data API 2019-03-18 15:31:14 -04:00
an b830718258 simplify c_enum API 2019-03-18 12:22:10 -04:00
an ee35332b23 make c_enum use primitive repr 2019-03-18 12:08:49 -04:00
an 6ee6140ba8 simplify OptU16 API 2019-03-18 12:07:44 -04:00
36 changed files with 1023 additions and 912 deletions

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
/target
/out
*.res
**/*.rs.bk
Cargo.lock
perf.data*
*.bat

View File

@ -1,6 +1,6 @@
Some of the data contained in tests/data and benches/data is
Copyright © Bungie Software. I do not own them, but am permitted to
redistribute them. Everything else is:
redistribute them. Everything else is public domain, as stated:
To the extent possible under law, I, Alison Sanderson, have waived all
copyright and related or neighboring rights to this Document as described by

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);
let $nam = OptU16::from_repr($nam);
($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.
@ -114,25 +139,21 @@ macro_rules! _durandal_read_impl {
/// - `Unit`: same as `u16`, but the result is passed to
/// `fixed::Unit::from_bits`, resulting in a `fixed::Unit` object.
/// - `OptU16`: same as `u16`, but the result is passed to
/// `OptU16::from_repr`, 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.
/// `OptU16::from`, resulting in an `OptU16` object.
/// - 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.
@ -376,6 +403,46 @@ pub fn rd_ofstable<T, F>(b: &[u8],
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
{
/// Creates an `OptU16` representing `None`.
@ -385,41 +452,11 @@ impl 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)}
/// 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.
///
/// # Examples
@ -427,10 +464,11 @@ impl OptU16
/// ```
/// use maraiah::durandal::bin::OptU16;
///
/// assert_eq!(OptU16::from_repr(500u16).get(), Some(500u16));
/// assert_eq!(OptU16::from_repr(u16::max_value()).get(), None);
/// assert_eq!(OptU16::from_repr(0u16).get(), Some(0u16));
/// assert_eq!(OptU16::from(500u16).get(), Some(500u16));
/// assert_eq!(OptU16::from(u16::max_value()).get(), None);
/// assert_eq!(OptU16::from(0u16).get(), Some(0u16));
/// ```
#[inline]
pub fn get(self) -> Option<u16>
{
match self.0 {

View File

@ -6,7 +6,7 @@
/// The syntax is similar to the `bitflags` macro, but each value has the
/// 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>`.
///
/// # Examples
@ -18,43 +18,44 @@
/// #[derive(Debug)]
/// enum MyEnum: u16
/// {
/// 0 => Zero,
/// 1 => One,
/// 2 => Two,
/// Zero = 0,
/// One = 1,
/// Two = 2
/// }
/// }
///
/// assert_eq!(MyEnum::from_repr(0), Ok(MyEnum::Zero));
/// assert_eq!(MyEnum::from_repr(1), Ok(MyEnum::One));
/// assert_eq!(MyEnum::from_repr(2), Ok(MyEnum::Two));
/// assert_eq!(MyEnum::from_repr(3), Err(ReprError::new(3)));
/// assert_eq!(MyEnum::from_repr(4), Err(ReprError::new(4)));
/// assert_eq!(MyEnum::from_repr(5), Err(ReprError::new(5)));
/// assert_eq!(MyEnum::try_from(0), Ok(MyEnum::Zero));
/// assert_eq!(MyEnum::try_from(1), Ok(MyEnum::One));
/// assert_eq!(MyEnum::try_from(2), Ok(MyEnum::Two));
/// assert_eq!(MyEnum::try_from(3), Err(ReprError::new(3)));
/// assert_eq!(MyEnum::try_from(4), Err(ReprError::new(4)));
/// assert_eq!(MyEnum::try_from(5), Err(ReprError::new(5)));
/// ```
#[macro_export]
macro_rules! c_enum
{
(
$(#[$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])*
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[repr($ti)]
$vi enum $t
{
$($en,)+
$($en = $va,)+
}
impl $t
{
/// 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 {
$($(#[$inner])* $va => Ok($t::$en),)+
$($va => Ok($t::$en),)+
n => Err(ReprError::new(n))
}
}
@ -71,26 +72,26 @@ mod test
#[derive(Debug)]
enum TestEnum: u16
{
0 => Zero,
1 => One,
2 => Two,
Zero = 0,
One = 1,
Two = 2,
}
}
#[test]
fn c_enum_should_be_ok()
{
assert_eq!(TestEnum::from_repr(0), Ok(TestEnum::Zero));
assert_eq!(TestEnum::from_repr(1), Ok(TestEnum::One));
assert_eq!(TestEnum::from_repr(2), Ok(TestEnum::Two));
assert_eq!(TestEnum::from_repr(3), Err(ReprError::new(3)));
assert_eq!(TestEnum::from_repr(4), Err(ReprError::new(4)));
assert_eq!(TestEnum::from_repr(5), Err(ReprError::new(5)));
assert_eq!(TestEnum::try_from(0), Ok(TestEnum::Zero));
assert_eq!(TestEnum::try_from(1), Ok(TestEnum::One));
assert_eq!(TestEnum::try_from(2), Ok(TestEnum::Two));
assert_eq!(TestEnum::try_from(3), Err(ReprError::new(3)));
assert_eq!(TestEnum::try_from(4), Err(ReprError::new(4)));
assert_eq!(TestEnum::try_from(5), Err(ReprError::new(5)));
}
#[test]
#[should_panic]
fn c_enum_should_error() {TestEnum::from_repr(3).unwrap();}
fn c_enum_should_error() {TestEnum::try_from(3).unwrap();}
}
// EOF

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::from_repr(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::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,
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::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,
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::from_repr(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::from_repr(mtype)?;
let xfer = TransferMode::from_repr(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))
@ -908,11 +903,11 @@ c_enum! {
#[derive(Debug)]
pub enum SideType: u16
{
0 => Full,
1 => High,
2 => Low,
3 => Composite,
4 => Split,
Full = 0,
High = 1,
Low = 2,
Composite = 3,
Split = 4,
}
}
@ -922,12 +917,12 @@ c_enum! {
#[derive(Debug)]
pub enum LightFuncType: u16
{
0 => Constant,
1 => Linear,
2 => Smooth,
3 => Flicker,
4 => Random,
5 => Fluorescent,
Constant = 0,
Linear = 1,
Smooth = 2,
Flicker = 3,
Random = 4,
Fluorescent = 5,
}
}
@ -937,9 +932,9 @@ c_enum! {
#[derive(Debug)]
pub enum LightType: u16
{
0 => Normal,
1 => Strobe,
2 => Media,
Normal = 0,
Strobe = 1,
Media = 2,
}
}
@ -949,10 +944,10 @@ c_enum! {
#[derive(Debug)]
pub enum MediaType: u16
{
0 => Water,
1 => Lava,
2 => Goo,
3 => Sewage,
Water = 0,
Lava = 1,
Goo = 2,
Sewage = 3,
}
}

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::from_repr(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::from_repr(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::from_repr(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})
@ -653,12 +647,12 @@ c_enum! {
#[derive(Debug)]
pub enum CasingType: u16
{
0 => Rifle,
1 => Pistol,
2 => PistolLeft,
3 => PistolRight,
4 => SMG,
0xFFFF => None,
Rifle = 0,
Pistol = 1,
PistolLeft = 2,
PistolRight = 3,
SMG = 4,
None = 0xFFFF,
}
}
@ -668,11 +662,11 @@ c_enum! {
#[derive(Debug)]
pub enum WeaponType: u16
{
0 => Melee,
1 => Normal,
2 => DualFunc,
3 => DualPistol,
4 => Multipurpose,
Melee = 0,
Normal = 1,
DualFunc = 2,
DualPistol = 3,
Multipurpose = 4,
}
}
@ -682,31 +676,31 @@ c_enum! {
#[derive(Debug)]
pub enum DamageType: u16
{
0 => Explosion,
1 => ElectricalStaff,
2 => Projectile,
3 => Absorbed,
4 => Flame,
5 => HoundClaws,
6 => AlienProjectile,
7 => HulkSlap,
8 => CompilerBolt,
9 => FusionBolt,
10 => HunterBolt,
11 => Fist,
12 => Teleporter,
13 => Defender,
14 => YetiClaws,
15 => YetiProjectile,
16 => Crushing,
17 => Lava,
18 => Suffocation,
19 => Goo,
20 => EnergyDrain,
21 => OxygenDrain,
22 => HummerBolt,
23 => ShotgunProjectile,
0xFFFF => None,
Explosion = 0,
ElectricalStaff = 1,
Projectile = 2,
Absorbed = 3,
Flame = 4,
HoundClaws = 5,
AlienProjectile = 6,
HulkSlap = 7,
CompilerBolt = 8,
FusionBolt = 9,
HunterBolt = 10,
Fist = 11,
Teleporter = 12,
Defender = 13,
YetiClaws = 14,
YetiProjectile = 15,
Crushing = 16,
Lava = 17,
Suffocation = 18,
Goo = 19,
EnergyDrain = 20,
OxygenDrain = 21,
HummerBolt = 22,
ShotgunProjectile = 23,
None = 0xFFFF,
}
}

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::from_repr(pack_t)?;
let depth = Depth::from_repr(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
@ -481,23 +484,23 @@ struct Header
c_enum! {
enum Depth: u16
{
1 => Bits1,
2 => Bits2,
4 => Bits4,
8 => Bits8,
16 => Bits16,
32 => Bits32,
Bits1 = 1,
Bits2 = 2,
Bits4 = 4,
Bits8 = 8,
Bits16 = 16,
Bits32 = 32,
}
}
c_enum! {
enum PackType: u16
{
0 => Default,
1 => None,
2 => NoPad,
3 => Rle16,
4 => Rle32,
Default = 0,
None = 1,
NoPad = 2,
Rle16 = 3,
Rle32 = 4,
}
}

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::from_repr(xfer)?;
let v_type = ViewType::from_repr(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::from_repr(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()) {
@ -478,11 +478,11 @@ c_enum! {
#[derive(Debug)]
pub enum CollectionType: u16
{
0 => Unused,
1 => Wall,
2 => Object,
3 => Interface,
4 => Scenery,
Unused = 0,
Wall = 1,
Object = 2,
Interface = 3,
Scenery = 4,
}
}
@ -492,15 +492,15 @@ c_enum! {
#[derive(Debug)]
pub enum ViewType: u16
{
1 => Anim,
2 => Anim8from2,
3 => Anim4from3,
4 => Anim4,
5 => Anim8from5,
8 => Anim8,
9 => Anim5from3,
10 => Still,
11 => Anim5,
Anim = 1,
Anim8from2 = 2,
Anim4from3 = 3,
Anim4 = 4,
Anim8from5 = 5,
Anim8 = 8,
Anim5from3 = 9,
Still = 10,
Anim5 = 11,
}
}

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::from_repr(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" {
@ -177,9 +178,9 @@ c_enum! {
#[derive(Debug)]
pub enum Volume: u16
{
0 => Quiet,
1 => Normal,
2 => Loud,
Quiet = 0,
Normal = 1,
Loud = 2,
}
}

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::from_repr(ver_wad)? {
let old_wad = match ver_wad {
Ver::Base => true,
_ => false,
};
@ -217,10 +221,10 @@ c_enum! {
#[derive(Debug)]
enum Ver: u16
{
0 => Base,
1 => Dir,
2 => Over,
4 => Inf,
Base = 0,
Dir = 1,
Over = 2,
Inf = 4,
}
}

View File

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

View File

@ -1,13 +1,23 @@
use std::process::Command;
fn main()
fn main() -> std::io::Result<()>
{
let out_file = std::env::var("OUT_DIR").unwrap();
let out_file = format!("--target={}/resources", out_file);
println!("cargo:rerun-if-changed=data");
Command::new("glib-compile-resources").arg("data/tycho_res.xml")
.arg("--target=data/tycho.res")
.status()
.unwrap();
let o = Command::new("glib-compile-resources").arg("data/resources.xml")
.arg(out_file)
.output()
.unwrap();
if !o.status.success() {
dbg!(o);
Err(std::io::Error::new(std::io::ErrorKind::Other, "failed to compile resources"))
} else {
Ok(())
}
}
// EOF

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,15 @@
[Icon Theme]
Name=hicolor
Inherits=HighContrast
DisplayDepth=32
Directories=48x48/actions,48x48/apps
[48x48/actions]
Size=48
Context=Actions
Type=Fixed
[48x48/apps]
Size=48
Context=Applications
Type=Fixed

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<!-- Toplevel namespace. Contains UI and helpers. -->
<gresource prefix="/net/greyserv/maraiah/tycho">
<file compressed="true" alias="tycho1.png">data/misc/tycho1.png</file>
<file compressed="true" alias="tycho2.png">data/misc/tycho2.png</file>
<file compressed="true" alias="css">data/styles.css</file>
<file compressed="true" preprocess="xml-stripblanks" alias="ui">data/ui.xml</file>
</gresource>
<!-- Icons, color. We can't make highcolor yet. -->
<gresource prefix="/net/greyserv/maraiah/tycho/icons/48x48/actions">
<file compressed="true" alias="tycho-polys.png">data/color/polygons.png</file>
<file compressed="true" alias="tycho-lines.png">data/color/lines.png</file>
<file compressed="true" alias="tycho-points.png">data/color/points.png</file>
</gresource>
<gresource prefix="/net/greyserv/maraiah/tycho/icons/48x48/apps">
<file compressed="true" alias="tycho-map.png">data/color/map.png</file>
</gresource>
</gresources>

Binary file not shown.

View File

@ -0,0 +1 @@
/* EOF */

View File

@ -1,5 +0,0 @@
.first-start-window {
background-color: #000000;
color: #AAAAAA;
font: 16px "FixedSys", "Monospace";
}

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/net/greyserv/maraiah/tycho">
<file compressed="true" alias="tycho1">data/tycho1.png</file>
<file compressed="true" alias="tycho2">data/tycho2.png</file>
<file compressed="true" alias="polys">data/polys.png</file>
<file compressed="true" alias="lines">data/lines.png</file>
<file compressed="true" alias="points">data/points.png</file>
<file compressed="true" preprocess="xml-stripblanks" alias="ui">data/tycho.xml</file>
<file compressed="true" alias="css">data/tycho.css</file>
</gresource>
</gresources>

View File

@ -98,7 +98,6 @@ Author: Alison Sanderson
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">The name of the map. Unicode symbols that are supported by the Mac OS Roman encoding are converted automatically when saved.</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
@ -110,6 +109,7 @@ Author: Alison Sanderson
<object class="GtkEntry" id="ent-map-name">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">The name of the map. Unicode symbols that are supported by the Mac OS Roman encoding are converted automatically when saved.</property>
</object>
</child>
</object>
@ -144,7 +144,6 @@ Author: Alison Sanderson
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">The texture collection to use for the map. This is one of five bitmap collections stored in the Shapes file.</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
@ -159,6 +158,7 @@ Author: Alison Sanderson
<object class="GtkComboBoxText">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">The texture collection to use for the map. This is one of five bitmap collections stored in the Shapes file.</property>
<property name="active">0</property>
<items>
<item translatable="yes">Water</item>
@ -189,7 +189,6 @@ Author: Alison Sanderson
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">The sky to display on sides which are marked as "Landscape." This is the sole bitmap of one of four collections in the Shapes file.</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
@ -204,6 +203,7 @@ Author: Alison Sanderson
<object class="GtkComboBoxText">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">The sky to display on sides which are marked as "Landscape." This is the sole bitmap of one of four collections in the Shapes file.</property>
<property name="active">0</property>
<items>
<item translatable="yes">Lh'owon Day</item>
@ -627,96 +627,41 @@ Author: Alison Sanderson
<property name="orientation">vertical</property>
<property name="spacing">5</property>
<child>
<object class="GtkBox">
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkFrame">
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<property name="left_padding">12</property>
<child>
<object class="GtkAlignment">
<object class="GtkSpinButton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<property name="left_padding">12</property>
<child>
<object class="GtkSpinButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">This field is unused and must be either 0 or 1. It used to be used to give different physics to the map editor and low gravity before it was made into an environment flag.</property>
<property name="text" translatable="yes">0</property>
<property name="truncate_multiline">True</property>
<property name="adjustment">adj-phys-id</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
<property name="wrap">True</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Physics ID</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">This field is unused and must be either 0 or 1. It used to be used to give different physics to the map editor and low gravity before it was made into an environment flag.</property>
<property name="text" translatable="yes">0</property>
<property name="truncate_multiline">True</property>
<property name="adjustment">adj-phys-id</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
<property name="wrap">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">This field overrides the Landscape value, since Marathon 1 used that field for the music number.</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<property name="left_padding">12</property>
<child>
<object class="GtkSpinButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="text" translatable="yes">0</property>
<property name="truncate_multiline">True</property>
<property name="adjustment">adj-phys-id</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
<property name="wrap">True</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Song ID</property>
</object>
</child>
<property name="label" translatable="yes">Physics ID</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
@ -734,6 +679,7 @@ Author: Alison Sanderson
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">These flags were added by Aleph One but are hidden and probably not meant to be used.</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
@ -799,7 +745,7 @@ Author: Alison Sanderson
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Aleph Mission Flags</property>
<property name="label" translatable="yes">Hidden Mission Flags</property>
</object>
</child>
</object>
@ -813,6 +759,7 @@ Author: Alison Sanderson
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">These flags were added by Aleph One but are hidden and probably not meant to be used.</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
@ -938,7 +885,7 @@ Author: Alison Sanderson
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Aleph Environment Flags</property>
<property name="label" translatable="yes">Hidden Environment Flags</property>
</object>
</child>
</object>
@ -979,17 +926,20 @@ Author: Alison Sanderson
<object class="GtkImage" id="img-lines">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="resource">/net/greyserv/maraiah/tycho/lines</property>
<property name="pixel_size">24</property>
<property name="icon_name">tycho-lines</property>
</object>
<object class="GtkImage" id="img-points">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="resource">/net/greyserv/maraiah/tycho/points</property>
<property name="pixel_size">24</property>
<property name="icon_name">tycho-points</property>
</object>
<object class="GtkImage" id="img-polys">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="resource">/net/greyserv/maraiah/tycho/polys</property>
<property name="pixel_size">24</property>
<property name="icon_name">tycho-polys</property>
</object>
<object class="GtkWindow" id="win-map-tools">
<property name="can_focus">False</property>
@ -1095,11 +1045,137 @@ Author: Alison Sanderson
<property name="modal">True</property>
<property name="type_hint">dialog</property>
<property name="program_name">Tycho Map Editor</property>
<property name="copyright" translatable="yes">Copyright © 2018-2019 Alison Sanderson</property>
<property name="copyright" translatable="yes">By Alison Sanderson. Public domain.</property>
<property name="comments" translatable="yes">greetigs i am tico the of superior ai to durdumbal go shoot my soldiers because its funny or ill put you in space</property>
<property name="website_label" translatable="yes">Home Page</property>
<property name="license" translatable="yes">To the extent possible under law, I, Alison Sanderson, have waived all
copyright and related or neighboring rights to this Document as described by
the Creative Commons Zero license as follows:
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
</property>
<property name="logo_icon_name">image-loading</property>
<property name="license_type">mit-x11</property>
<property name="license_type">custom</property>
<child>
<placeholder/>
</child>
@ -1132,44 +1208,6 @@ Author: Alison Sanderson
</object>
</child>
</object>
<object class="GtkWindow" id="win-first-start">
<property name="can_focus">False</property>
<property name="title" translatable="yes">First Startup</property>
<property name="resizable">False</property>
<child>
<object class="GtkAlignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">10</property>
<property name="bottom_padding">10</property>
<property name="left_padding">10</property>
<property name="right_padding">10</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">II. A word from the Programmer:
This entire program was written in Vim. Emacs users beware,
IDEs beware, all beware! For I have the power of Vim! Hahahaha
hahahahahaha! Anyway, hopefully you enjoy the program. It's
my first serious effort at writing a GUI program. This toolset
is made to encourage people to try out Marathon and hopefully
start making stuff. Modding should be a fun journey for
every one just as it has helped me to further my abilities at
many things, including programming.
Also, 3 space tabs win. --- Alison Sanderson
Programmer of Maraiah</property>
<property name="angle">4</property>
</object>
</child>
</object>
</child>
<style>
<class name="first-start-window"/>
</style>
</object>
<object class="GtkWindow" id="win-main">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Tycho</property>

View File

@ -22,7 +22,7 @@ fn mk_draw_area(b: &gtk::Builder)
let ax: gtk::Adjustment = get_obj(b, "adj-map-horz");
let ay: gtk::Adjustment = get_obj(b, "adj-map-vert");
let im = CairoPixbuf(load_img("/net/greyserv/maraiah/tycho/tycho1"));
let im = CairoPixbuf(load_img("/net/greyserv/maraiah/tycho/tycho1.png"));
area.connect_draw(move |area, cr| {
let w = f64::from(area.get_allocated_width());
@ -44,8 +44,6 @@ fn mk_draw_area(b: &gtk::Builder)
fn run_app(app: &gtk::Application)
{
let b = &gtk::Builder::new_from_resource("/net/greyserv/maraiah/tycho/ui");
let prv = gtk::CssProvider::new();
prv.load_from_resource("/net/greyserv/maraiah/tycho/css");
@ -53,6 +51,9 @@ fn run_app(app: &gtk::Application)
let pri = gtk::STYLE_PROVIDER_PRIORITY_APPLICATION;
gtk::StyleContext::add_provider_for_screen(&scr, &prv, pri);
let b = &gtk::Builder::new_from_resource("/net/greyserv/maraiah/tycho/ui");
// TODO: signal quit instead of quitting directly to not add a ref here
let app_ = app.downgrade();
let btn: gtk::MenuItem = get_obj(b, "btn-quit");
btn.connect_activate(move |_| {
@ -86,10 +87,7 @@ fn run_app(app: &gtk::Application)
win.set_authors(&env!("CARGO_PKG_AUTHORS").split(';').collect::<Vec<_>>());
win.set_version(env!("CARGO_PKG_VERSION"));
win.set_website(env!("CARGO_PKG_HOMEPAGE"));
win.set_logo(&load_img("/net/greyserv/maraiah/tycho/tycho2"));
let win: gtk::Window = get_obj(b, "win-first-start");
win.show_all();
win.set_logo(&load_img("/net/greyserv/maraiah/tycho/tycho2.png"));
let win: gtk::Window = get_obj(b, "win-main");
win.set_application(app);
@ -110,7 +108,8 @@ fn get_obj<T>(b: &gtk::Builder, name: &str) -> T
fn main() -> ResultS<()>
{
// get jacked, punk. opaque data structures are for nerds.
const RESOURCE_DATA: &[u8] = include_bytes!("data/tycho.res");
const RESOURCE_DATA: &[u8] =
include_bytes!(concat!(env!("OUT_DIR"), "/resources"));
// first we create the static resource header, which is really simple
let mut static_resource =