add documentation for everything
parent
789e3de93f
commit
fc27d2d0f4
|
@ -5,67 +5,70 @@ use serde::Serialize;
|
|||
use std::{fmt, num::NonZeroU16};
|
||||
|
||||
#[doc(hidden)]
|
||||
macro_rules! rd_1 {
|
||||
#[macro_export]
|
||||
macro_rules! _durandal_read_impl {
|
||||
// big endian
|
||||
(BE $b:ident $nam:ident u16 $n:expr) => {
|
||||
rd_1!($b u16::from_be_bytes, $nam 2 $n);
|
||||
_durandal_read_impl!($b u16::from_be_bytes, $nam 2 $n);
|
||||
};
|
||||
(BE $b:ident $nam:ident i16 $n:expr) => {
|
||||
rd_1!($b i16::from_be_bytes, $nam 2 $n);
|
||||
_durandal_read_impl!($b i16::from_be_bytes, $nam 2 $n);
|
||||
};
|
||||
(BE $b:ident $nam:ident u32 $n:expr) => {
|
||||
rd_1!($b u32::from_be_bytes, $nam 4 $n);
|
||||
_durandal_read_impl!($b u32::from_be_bytes, $nam 4 $n);
|
||||
};
|
||||
(BE $b:ident $nam:ident i32 $n:expr) => {
|
||||
rd_1!($b i32::from_be_bytes, $nam 4 $n);
|
||||
_durandal_read_impl!($b i32::from_be_bytes, $nam 4 $n);
|
||||
};
|
||||
(BE $b:ident $nam:ident as usize u16 $n:expr) => {
|
||||
rd_1!($b u16::from_be_bytes, $nam 2 $n);
|
||||
_durandal_read_impl!($b u16::from_be_bytes, $nam 2 $n);
|
||||
let $nam = $nam as usize;
|
||||
};
|
||||
(BE $b:ident $nam:ident as usize u32 $n:expr) => {
|
||||
rd_1!($b u32::from_be_bytes, $nam 4 $n);
|
||||
_durandal_read_impl!($b u32::from_be_bytes, $nam 4 $n);
|
||||
let $nam = $nam as usize;
|
||||
};
|
||||
(BE $b:ident $nam:ident Angle $n:expr) => {
|
||||
rd_1!($b u16::from_be_bytes, $nam 2 $n);
|
||||
let $nam = Angle::from_bits($nam);
|
||||
};
|
||||
(BE $b:ident $nam:ident Fixed $n:expr) => {
|
||||
rd_1!($b u32::from_be_bytes, $nam 4 $n);
|
||||
let $nam = Fixed::from_bits($nam);
|
||||
};
|
||||
(BE $b:ident $nam:ident Unit $n:expr) => {
|
||||
rd_1!($b u16::from_be_bytes, $nam 2 $n);
|
||||
let $nam = Unit::from_bits($nam);
|
||||
};
|
||||
(BE $b:ident $nam:ident OptU16 $n:expr) => {
|
||||
rd_1!($b u16::from_be_bytes, $nam 2 $n);
|
||||
let $nam = OptU16::from_repr($nam);
|
||||
};
|
||||
|
||||
// little endian
|
||||
(LE $b:ident $nam:ident u16 $n:expr) => {
|
||||
rd_1!($b u16::from_le_bytes $nam 2 $n);
|
||||
_durandal_read_impl!($b u16::from_le_bytes $nam 2 $n);
|
||||
};
|
||||
(LE $b:ident $nam:ident i16 $n:expr) => {
|
||||
rd_1!($b i16::from_le_bytes $nam 2 $n);
|
||||
_durandal_read_impl!($b i16::from_le_bytes $nam 2 $n);
|
||||
};
|
||||
(LE $b:ident $nam:ident u32 $n:expr) => {
|
||||
rd_1!($b u32::from_le_bytes $nam 4 $n);
|
||||
_durandal_read_impl!($b u32::from_le_bytes $nam 4 $n);
|
||||
};
|
||||
(LE $b:ident $nam:ident i32 $n:expr) => {
|
||||
rd_1!($b i32::from_le_bytes $nam 4 $n);
|
||||
_durandal_read_impl!($b i32::from_le_bytes $nam 4 $n);
|
||||
};
|
||||
(LE $b:ident $nam:ident as usize u16 $n:expr) => {
|
||||
rd_1!($b u16::from_le_bytes $nam 2 $n);
|
||||
_durandal_read_impl!($b u16::from_le_bytes $nam 2 $n);
|
||||
let $nam = $nam as usize;
|
||||
};
|
||||
(LE $b:ident $nam:ident as usize u32 $n:expr) => {
|
||||
rd_1!($b u32::from_le_bytes $nam 4 $n);
|
||||
_durandal_read_impl!($b u32::from_le_bytes $nam 4 $n);
|
||||
let $nam = $nam as usize;
|
||||
};
|
||||
|
||||
// either endianness
|
||||
($e:ident $b:ident $nam:ident Angle $n:expr) => {
|
||||
_durandal_read_impl!($e $b $nam u16 $n);
|
||||
let $nam = Angle::from_bits($nam);
|
||||
};
|
||||
($e:ident $b:ident $nam:ident Fixed $n:expr) => {
|
||||
_durandal_read_impl!($e $b $nam u32 $n);
|
||||
let $nam = Fixed::from_bits($nam);
|
||||
};
|
||||
($e:ident $b:ident $nam:ident Unit $n:expr) => {
|
||||
_durandal_read_impl!($e $b $nam u16 $n);
|
||||
let $nam = Unit::from_bits($nam);
|
||||
};
|
||||
($e:ident $b:ident $nam:ident OptU16 $n:expr) => {
|
||||
_durandal_read_impl!($e $b $nam u16 $n);
|
||||
let $nam = OptU16::from_repr($nam);
|
||||
};
|
||||
|
||||
// generic endianness
|
||||
($_:ident $b:ident $nam:ident u8 $n:expr) => {
|
||||
let $nam = $b[$n];
|
||||
|
@ -76,7 +79,7 @@ macro_rules! rd_1 {
|
|||
($_:ident $b:ident $nam:ident i8 $n:expr) => {
|
||||
let $nam = $b[$n] as i8;
|
||||
};
|
||||
($_:ident $b:ident $nam:ident iden $n:expr) => {
|
||||
($_:ident $b:ident $nam:ident Ident $n:expr) => {
|
||||
let $nam = [$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]];
|
||||
};
|
||||
($_:ident $b:ident $nam:ident $f:ident $n:expr) => {
|
||||
|
@ -95,6 +98,48 @@ macro_rules! rd_1 {
|
|||
};
|
||||
}
|
||||
|
||||
/// Reads structured data from a byte array.
|
||||
///
|
||||
/// First start by specifying the endianness, size and source using the syntax
|
||||
/// `endian, size in source =>` 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.
|
||||
///
|
||||
/// After the initializer line, all lines have the syntax
|
||||
/// `name = type[place] 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
|
||||
/// 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.
|
||||
/// - `Fixed`: same as `u32`, but the result is passed to
|
||||
/// `fixed::Fixed::from_bits`, resulting in a `fixed::Fixed` object.
|
||||
/// - `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:
|
||||
/// - `array` when `type` is `u8`: `place` is a range specifying a `u8` slice
|
||||
/// to be taken from `source`.
|
||||
/// - `as usize` when `type` is `u16` or `u32`: converts the resulting
|
||||
/// integer to `usize` by primitive cast.
|
||||
/// - `nt` 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.
|
||||
#[macro_export]
|
||||
macro_rules! read_data {
|
||||
(
|
||||
$sz:expr , $ty:ident in $b:ident =>
|
||||
|
@ -104,16 +149,41 @@ macro_rules! read_data {
|
|||
bail!("not enough data");
|
||||
}
|
||||
|
||||
$(rd_1!($ty $b $nam $($ex)* $t $n);)*
|
||||
$($crate::_durandal_read_impl!($ty $b $nam $($ex)* $t $n);)*
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates an `Ident` from a slice.
|
||||
///
|
||||
/// `b` must be at least 4 bytes, or a panic will occur.
|
||||
pub fn ident(b: &[u8]) -> Ident {[b[0], b[1], b[2], b[3]]}
|
||||
|
||||
/// Applies `u32::from_be_bytes` to a slice.
|
||||
///
|
||||
/// `b` must be at least 4 bytes, or a panic will occur.
|
||||
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.
|
||||
///
|
||||
/// `b` must be at least 2 bytes, or a panic will occur.
|
||||
pub fn u16b(b: &[u8]) -> u16 {u16::from_be_bytes([b[0], b[1]])}
|
||||
|
||||
/// Applies `i32::from_be_bytes` to a slice.
|
||||
///
|
||||
/// `b` must be at least 4 bytes, or a panic will occur.
|
||||
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.
|
||||
///
|
||||
/// `b` must be at least 2 bytes, or a panic will occur.
|
||||
pub fn i16b(b: &[u8]) -> i16 {i16::from_be_bytes([b[0], b[1]])}
|
||||
|
||||
/// Applies a read function over a slice.
|
||||
///
|
||||
/// Applies `read` over `b`, resulting in a vector of its return values. Each
|
||||
/// iteration will pass a slice of `b` to `read` for it to read from, and then
|
||||
/// increments the slice index by the second return value. When there is no
|
||||
/// data left in `b`, the function returns.
|
||||
pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
|
||||
where T: Sized,
|
||||
F: Fn(&[u8]) -> ResultS<(T, usize)>
|
||||
|
@ -130,6 +200,13 @@ pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
|
|||
Ok(v)
|
||||
}
|
||||
|
||||
/// Applies a read function over a slice with an offset table.
|
||||
///
|
||||
/// Applies `read` over each offset in `b`, of which there are `num` amount of
|
||||
/// starting at `p`, resulting in a vector of its return values. Each iteration
|
||||
/// reads a 32-bit big endian offset from `b`, and then passes a slice of `b`
|
||||
/// to `read` starting at that offset. When all offsets have been read, the
|
||||
/// function returns.
|
||||
pub fn rd_ofstable<T, F>(b: &[u8],
|
||||
mut p: usize,
|
||||
num: usize,
|
||||
|
@ -141,7 +218,7 @@ pub fn rd_ofstable<T, F>(b: &[u8],
|
|||
let mut v = Vec::with_capacity(num);
|
||||
|
||||
for _ in 0..num {
|
||||
let ofs = u32b(&b[p..]) as usize;
|
||||
let ofs = u32b(&b[p..p + 4]) as usize;
|
||||
|
||||
if ofs >= b.len() {
|
||||
bail!("not enough data");
|
||||
|
@ -166,7 +243,7 @@ impl OptU16
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the `u16` representation of an `OptU16`.
|
||||
/// Returns the `u16` representation.
|
||||
pub fn get_repr(&self) -> u16
|
||||
{
|
||||
match self.0 {
|
||||
|
@ -175,7 +252,7 @@ impl OptU16
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the `Option` representation of an `OptU16`.
|
||||
/// Returns the `Option` representation.
|
||||
pub fn get(&self) -> Option<u16>
|
||||
{
|
||||
match self.0 {
|
||||
|
@ -200,7 +277,7 @@ impl fmt::Debug for OptU16
|
|||
pub type Ident = [u8; 4];
|
||||
|
||||
/// An object identified by a `u16` which may be `u16::max_value()` to
|
||||
/// represent None.
|
||||
/// represent a nulled value.
|
||||
#[derive(Serialize)]
|
||||
pub struct OptU16(Option<NonZeroU16>);
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
//! C representation enumerations.
|
||||
#![doc(hidden)]
|
||||
|
||||
/// Creates an enumeration and function for converting a representation into
|
||||
/// the enumeration type.
|
||||
///
|
||||
/// 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 E` as well as a function `E::from_repr` which
|
||||
/// will return `Result<E, ReprError>`.
|
||||
#[macro_export]
|
||||
macro_rules! c_enum
|
||||
{
|
||||
|
@ -20,11 +26,12 @@ macro_rules! c_enum
|
|||
|
||||
impl $E
|
||||
{
|
||||
$V fn from_repr(n: $T) -> Result<$E, ReprError>
|
||||
/// Returns, if representable, the variant of `Self` from `n`.
|
||||
$V fn from_repr(n: $T) -> Result<Self, ReprError>
|
||||
{
|
||||
match n {
|
||||
$($value => Ok($E::$Enum),)+
|
||||
n => Err(ReprError(n.into()))
|
||||
$($value => Ok($E::$Enum),)+
|
||||
n => Err(ReprError(n.into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ fn crc_init() -> [u32; 256]
|
|||
t
|
||||
}
|
||||
|
||||
/// Creates a CRC-32 of all bytes in `b` with the starting sum `s`.
|
||||
pub fn crc32(b: &[u8], s: u32) -> u32
|
||||
{
|
||||
let t = crc_init();
|
||||
|
|
|
@ -28,6 +28,7 @@ macro_rules! bail {
|
|||
};
|
||||
}
|
||||
|
||||
/// Returns an `Error` with a static string.
|
||||
pub fn err_msg(msg: &'static str) -> Error {Error::from(ErrMsg(msg))}
|
||||
|
||||
impl Fail for ReprError {}
|
||||
|
@ -62,11 +63,13 @@ impl fmt::Debug for ErrMsg
|
|||
}
|
||||
}
|
||||
|
||||
/// A representation error for an integer.
|
||||
#[derive(PartialEq)]
|
||||
pub struct ReprError(pub i64);
|
||||
|
||||
struct ErrMsg(&'static str);
|
||||
|
||||
/// A generic `failure` based `Result` type.
|
||||
pub type ResultS<T> = Result<T, Error>;
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use crate::durandal::err::*;
|
||||
use std::fs;
|
||||
|
||||
/// Confirms that the path `p` is a folder.
|
||||
pub fn validate_folder_path(p: &str) -> ResultS<()>
|
||||
{
|
||||
let at = fs::metadata(p)?;
|
||||
|
|
|
@ -5,23 +5,55 @@ use std::{fmt::{self, Write},
|
|||
ops};
|
||||
|
||||
macro_rules! define_fixed_type {
|
||||
($Type:ident : $IT:ident, $UT:ident, $LT:ident, $FracBits:expr) => {
|
||||
(
|
||||
$(#[$outer:meta])*
|
||||
struct $Type:ident ($IT:ident) : $UT:ident, $LT:ident, $FracBits:expr;
|
||||
) => {
|
||||
$(#[$outer])*
|
||||
#[derive(Clone, PartialEq, Serialize)]
|
||||
pub struct $Type($IT);
|
||||
|
||||
impl $Type
|
||||
{
|
||||
const FRACBITS: $UT = $FracBits;
|
||||
const FRACMASK: $UT = (1 << Self::FRACBITS) - 1;
|
||||
const ONE: $IT = 1 << Self::FRACBITS;
|
||||
/// The number of fractional bits in this type.
|
||||
pub const FRACBITS: $UT = $FracBits;
|
||||
/// The integer mask for the fractional bits.
|
||||
pub const FRACMASK: $UT = (1 << Self::FRACBITS) - 1;
|
||||
/// The representation of `1.0` in this type.
|
||||
pub const ONE: $IT = 1 << Self::FRACBITS;
|
||||
|
||||
pub fn to_bits(&self) -> $UT {self.0 as $UT}
|
||||
pub fn set_bits(&mut self, bits: $UT) {self.0 = bits as $IT}
|
||||
/// Creates a value of this type with the bit pattern `bits`.
|
||||
#[inline]
|
||||
pub const fn from_bits(bits: $UT) -> Self {$Type(bits as $IT)}
|
||||
|
||||
/// Returns the raw bit pattern.
|
||||
#[inline]
|
||||
pub fn to_bits(&self) -> $UT {self.0 as $UT}
|
||||
|
||||
/// Sets the raw bit pattern to `bits`.
|
||||
#[inline]
|
||||
pub fn set_bits(&mut self, bits: $UT) {self.0 = bits as $IT}
|
||||
|
||||
/// Returns the integral portion.
|
||||
#[inline]
|
||||
pub fn integ(&self) -> $LT {(self.0 >> Self::FRACBITS) as $LT}
|
||||
|
||||
/// Returns the fractional portion.
|
||||
///
|
||||
/// This is a value of `1` to `FRACMASK`.
|
||||
#[allow(trivial_numeric_casts)]
|
||||
pub fn fract(&self) -> u16 {(self.0 as $UT & Self::FRACMASK) as u16}
|
||||
|
||||
/// Returns a multiplication by integer.
|
||||
///
|
||||
/// Panics if the result overflows.
|
||||
#[inline]
|
||||
pub fn mul_i(&self, n: $LT) -> Self {$Type(self.0 * $IT::from(n))}
|
||||
|
||||
/// Returns a division by integer.
|
||||
///
|
||||
/// Panics if `n` is `0`.
|
||||
#[inline]
|
||||
pub fn div_i(&self, n: $LT) -> Self {$Type(self.0 / $IT::from(n))}
|
||||
|
||||
#[inline]
|
||||
|
@ -39,6 +71,7 @@ macro_rules! define_fixed_type {
|
|||
|
||||
impl From<$LT> for $Type
|
||||
{
|
||||
#[inline]
|
||||
fn from(n: $LT) -> Self {$Type($IT::from(n) << Self::FRACBITS)}
|
||||
}
|
||||
|
||||
|
@ -46,6 +79,7 @@ macro_rules! define_fixed_type {
|
|||
{
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, o: Self) -> Self {$Type(self.0 + o.0)}
|
||||
}
|
||||
|
||||
|
@ -53,6 +87,7 @@ macro_rules! define_fixed_type {
|
|||
{
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, o: Self) -> Self {$Type(self.0 - o.0)}
|
||||
}
|
||||
|
||||
|
@ -60,6 +95,7 @@ macro_rules! define_fixed_type {
|
|||
{
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, o: Self) -> Self {$Type(Self::fx_mul(self.0, o.0))}
|
||||
}
|
||||
|
||||
|
@ -67,6 +103,7 @@ macro_rules! define_fixed_type {
|
|||
{
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn div(self, o: Self) -> Self {$Type(Self::fx_div(self.0, o.0))}
|
||||
}
|
||||
|
||||
|
@ -74,6 +111,7 @@ macro_rules! define_fixed_type {
|
|||
{
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Self {$Type(-self.0)}
|
||||
}
|
||||
|
||||
|
@ -81,6 +119,7 @@ macro_rules! define_fixed_type {
|
|||
{
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn not(self) -> Self {$Type(!self.0)}
|
||||
}
|
||||
|
||||
|
@ -115,9 +154,27 @@ macro_rules! define_fixed_type {
|
|||
};
|
||||
}
|
||||
|
||||
define_fixed_type!(Fixed: i32, u32, i16, 16);
|
||||
define_fixed_type!(Unit: i16, u16, i8, 10);
|
||||
define_fixed_type!(Angle: i16, u16, i8, 9);
|
||||
define_fixed_type! {
|
||||
/// A fixed point type representing an angle.
|
||||
///
|
||||
/// The format of this type is `0.9s`, but because of the implementation,
|
||||
/// the real format is `7.9s`.
|
||||
struct Angle(i16) : u16, i8, 9;
|
||||
}
|
||||
|
||||
define_fixed_type! {
|
||||
/// A fixed point type representing a world unit.
|
||||
///
|
||||
/// The format of this type is `5.10s`. This has caused eternal suffering.
|
||||
struct Unit(i16) : u16, i8, 10;
|
||||
}
|
||||
|
||||
define_fixed_type! {
|
||||
/// A generic fixed point type.
|
||||
///
|
||||
/// The format of this type is `15.16s`.
|
||||
struct Fixed(i32) : u32, i16, 16;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixed_basic_ops()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Image and color representations.
|
||||
|
||||
use crate::durandal::err::*;
|
||||
use serde::Serialize;
|
||||
use std::io;
|
||||
|
||||
/// Creates a RGB8 color from a R5G5B5 format color.
|
||||
|
@ -70,14 +71,25 @@ pub fn write_tga(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// A generic color matrix image.
|
||||
pub trait Image
|
||||
{
|
||||
/// The type of color this image uses for each pixel.
|
||||
type Output: Color;
|
||||
|
||||
/// Returns the width of the image.
|
||||
fn w(&self) -> usize;
|
||||
|
||||
/// Returns the height of the image.
|
||||
fn h(&self) -> usize;
|
||||
|
||||
/// Returns the color of the pixel at column `x` at row `y`.
|
||||
///
|
||||
/// Panics if `x` is greater than the width of the image or `y` is greater
|
||||
/// than the height of the image.
|
||||
fn index(&self, x: usize, y: usize) -> &Self::Output;
|
||||
|
||||
/// The same as `index`, but will not panic if out of bounds.
|
||||
fn get(&self, x: usize, y: usize) -> Option<&Self::Output>
|
||||
{
|
||||
if x < self.w() && y < self.h() {
|
||||
|
@ -88,11 +100,19 @@ pub trait Image
|
|||
}
|
||||
}
|
||||
|
||||
/// Any color which may be represented as RGBA16.
|
||||
pub trait Color
|
||||
{
|
||||
/// Returns the red component.
|
||||
fn r(&self) -> u16;
|
||||
|
||||
/// Returns the green component.
|
||||
fn g(&self) -> u16;
|
||||
|
||||
/// Returns the blue component.
|
||||
fn b(&self) -> u16;
|
||||
|
||||
/// Returns the alpha component.
|
||||
fn a(&self) -> u16;
|
||||
}
|
||||
|
||||
|
@ -166,15 +186,16 @@ impl Color for Color8
|
|||
fn a(&self) -> u16 {u16::max_value()}
|
||||
}
|
||||
|
||||
/// A RGB16 color.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
/// An RGB16 color.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
pub struct Color16(u16, u16, u16);
|
||||
|
||||
/// A RGB8 color.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
/// An RGB8 color.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
pub struct Color8(u8, u8, u8);
|
||||
|
||||
/// RGB16 image.
|
||||
/// An RGB16 image.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Image16
|
||||
{
|
||||
w: usize,
|
||||
|
@ -182,7 +203,8 @@ pub struct Image16
|
|||
pub cr: Vec<Color16>,
|
||||
}
|
||||
|
||||
/// RGB16 image.
|
||||
/// An RGB8 image.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Image8
|
||||
{
|
||||
w: usize,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Library for various utilities.
|
||||
//! Library for utilities.
|
||||
|
||||
#[macro_use]
|
||||
pub mod err;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use crate::durandal::err::*;
|
||||
use std::io;
|
||||
|
||||
/// Writes a WAVE file from a sound.
|
||||
pub fn write_wav(out: &mut impl io::Write, snd: &impl Sound) -> ResultS<()>
|
||||
{
|
||||
let rate = u32::from(snd.rate());
|
||||
|
@ -32,20 +33,34 @@ pub fn write_wav(out: &mut impl io::Write, snd: &impl Sound) -> ResultS<()>
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Any PCM stream which may be represented as a 16-bit PCM stream.
|
||||
pub trait Sound
|
||||
{
|
||||
/// Returns the sample rate.
|
||||
fn rate(&self) -> u16;
|
||||
|
||||
/// Returns the number of samples.
|
||||
fn len(&self) -> usize;
|
||||
fn index(&self, p: usize) -> i16;
|
||||
|
||||
/// Returns the `n`th sample.
|
||||
///
|
||||
/// May panic if `n` exceeds the length of this sound.
|
||||
fn index(&self, n: usize) -> i16;
|
||||
|
||||
/// Returns the number of the first sample of the loop, or `0`.
|
||||
fn lp_beg(&self) -> usize;
|
||||
|
||||
/// Returns the number of the last sample of the loop, or `0`.
|
||||
fn lp_end(&self) -> usize;
|
||||
|
||||
/// Returns `true` if there are no samples in this sound.
|
||||
fn is_empty(&self) -> bool {self.len() == 0}
|
||||
|
||||
fn get(&self, p: usize) -> Option<i16>
|
||||
/// The same as `index`, but will not panic if out of bounds.
|
||||
fn get(&self, n: usize) -> Option<i16>
|
||||
{
|
||||
if p < self.len() {
|
||||
Some(self.index(p))
|
||||
if n < self.len() {
|
||||
Some(self.index(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -99,6 +114,7 @@ impl Sound for Sound16
|
|||
fn lp_end(&self) -> usize {self.lp_end}
|
||||
}
|
||||
|
||||
/// A 16-bit PCM stream.
|
||||
pub struct Sound16
|
||||
{
|
||||
rate: u16,
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
//! Structures used by Marathon's Map format.
|
||||
|
||||
use crate::{durandal::{bin::*, err::*, fixed::*, text::mac_roman_conv},
|
||||
marathon::xfer::TransferMode};
|
||||
use bitflags::bitflags;
|
||||
use serde::Serialize;
|
||||
|
||||
/// Reads a `Minf` chunk.
|
||||
pub fn read_minf(b: &[u8]) -> ResultS<Minf>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -23,6 +26,7 @@ pub fn read_minf(b: &[u8]) -> ResultS<Minf>
|
|||
level_name})
|
||||
}
|
||||
|
||||
/// Reads a `LightFunc` object.
|
||||
pub fn read_lightfunc(b: &[u8]) -> ResultS<LightFunc>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -39,6 +43,7 @@ pub fn read_lightfunc(b: &[u8]) -> ResultS<LightFunc>
|
|||
Ok(LightFunc{ftype, prd_nrm, prd_dta, val_nrm, val_dta})
|
||||
}
|
||||
|
||||
/// Reads a `SideTex` object.
|
||||
pub fn read_sidetex(b: &[u8]) -> ResultS<SideTex>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -50,6 +55,7 @@ pub fn read_sidetex(b: &[u8]) -> ResultS<SideTex>
|
|||
Ok(SideTex{offs, tex_id})
|
||||
}
|
||||
|
||||
/// Reads a `Point` object.
|
||||
pub fn read_point(b: &[u8]) -> ResultS<Point>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -61,6 +67,7 @@ pub fn read_point(b: &[u8]) -> ResultS<Point>
|
|||
Ok(Point{x, y})
|
||||
}
|
||||
|
||||
/// Reads an `EPNT` chunk.
|
||||
pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -71,11 +78,13 @@ pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)>
|
|||
Ok((pnt, 16))
|
||||
}
|
||||
|
||||
/// Reads a `PNTS` chunk.
|
||||
pub fn read_pnts(b: &[u8]) -> ResultS<(Point, usize)>
|
||||
{
|
||||
Ok((read_point(b)?, 4))
|
||||
}
|
||||
|
||||
/// Reads a `LINS` chunk.
|
||||
pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -94,6 +103,7 @@ pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)>
|
|||
Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32))
|
||||
}
|
||||
|
||||
/// Reads a `SIDS` chunk.
|
||||
pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -121,6 +131,7 @@ pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)>
|
|||
xfer_pri, xfer_sec, xfer_tra, shade}, 64))
|
||||
}
|
||||
|
||||
/// Reads a `POLY` chunk.
|
||||
pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -153,6 +164,7 @@ pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)>
|
|||
snd_ind, snd_amb, snd_rnd}, 128))
|
||||
}
|
||||
|
||||
/// Reads a `LITE` chunk.
|
||||
pub fn read_lite(b: &[u8]) -> ResultS<(Light, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -176,6 +188,7 @@ pub fn read_lite(b: &[u8]) -> ResultS<(Light, usize)>
|
|||
ina_mid, tag}, 100))
|
||||
}
|
||||
|
||||
/// Reads an `OBJS` chunk.
|
||||
pub fn read_objs(b: &[u8]) -> ResultS<(Object, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -198,6 +211,7 @@ pub fn read_objs(b: &[u8]) -> ResultS<(Object, usize)>
|
|||
Ok((Object{group, index, angle, poly, pos_x, pos_y, pos_z, flags, bias}, 16))
|
||||
}
|
||||
|
||||
/// Reads a `plac` chunk.
|
||||
pub fn read_plac(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -215,6 +229,7 @@ pub fn read_plac(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
|
|||
Ok((ObjectFreq{rnd_loc, cnt_ini, cnt_min, cnt_max, cnt_rnd, chance}, 12))
|
||||
}
|
||||
|
||||
/// Reads an `ambi` chunk.
|
||||
pub fn read_ambi(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -226,6 +241,7 @@ pub fn read_ambi(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
|
|||
Ok((SoundAmbi{index, volume}, 16))
|
||||
}
|
||||
|
||||
/// Reads a `bonk` chunk.
|
||||
pub fn read_bonk(b: &[u8]) -> ResultS<(SoundRand, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -248,6 +264,7 @@ pub fn read_bonk(b: &[u8]) -> ResultS<(SoundRand, usize)>
|
|||
yaw_dta, pit_nrm, pit_dta}, 32))
|
||||
}
|
||||
|
||||
/// Reads a `medi` chunk.
|
||||
pub fn read_medi(b: &[u8]) -> ResultS<(Media, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -274,6 +291,7 @@ pub fn read_medi(b: &[u8]) -> ResultS<(Media, usize)>
|
|||
min_lt, texture, xfer}, 32))
|
||||
}
|
||||
|
||||
/// Reads a `plat` chunk.
|
||||
pub fn read_plat(b: &[u8]) -> ResultS<(Platform, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -293,6 +311,7 @@ pub fn read_plat(b: &[u8]) -> ResultS<(Platform, usize)>
|
|||
Ok((Platform{ptype, speed, delay, hei_min, hei_max, flags, index, tag}, 32))
|
||||
}
|
||||
|
||||
/// A point in world-space.
|
||||
#[derive(Clone, PartialEq, Serialize)]
|
||||
pub struct Point
|
||||
{
|
||||
|
@ -300,6 +319,7 @@ pub struct Point
|
|||
pub y: Unit,
|
||||
}
|
||||
|
||||
/// A line segment.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Line
|
||||
{
|
||||
|
@ -312,6 +332,7 @@ pub struct Line
|
|||
pub poly_bk: OptU16,
|
||||
}
|
||||
|
||||
/// The texture of a side segment.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct SideTex
|
||||
{
|
||||
|
@ -319,6 +340,7 @@ pub struct SideTex
|
|||
pub tex_id: OptU16,
|
||||
}
|
||||
|
||||
/// One side of a line segment.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Side
|
||||
{
|
||||
|
@ -335,6 +357,7 @@ pub struct Side
|
|||
pub shade: Fixed,
|
||||
}
|
||||
|
||||
/// A polygon segment.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Polygon
|
||||
{
|
||||
|
@ -357,6 +380,7 @@ pub struct Polygon
|
|||
pub snd_rnd: OptU16,
|
||||
}
|
||||
|
||||
/// A light function.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct LightFunc
|
||||
{
|
||||
|
@ -367,6 +391,7 @@ pub struct LightFunc
|
|||
pub val_dta: u16,
|
||||
}
|
||||
|
||||
/// A dynamic polygon light.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Light
|
||||
{
|
||||
|
@ -382,6 +407,7 @@ pub struct Light
|
|||
pub tag: u16,
|
||||
}
|
||||
|
||||
/// An object in the world.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Object
|
||||
{
|
||||
|
@ -396,6 +422,7 @@ pub struct Object
|
|||
pub bias: u16,
|
||||
}
|
||||
|
||||
/// The difficulty definition for various object types.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct ObjectFreq
|
||||
{
|
||||
|
@ -407,6 +434,7 @@ pub struct ObjectFreq
|
|||
pub chance: u16,
|
||||
}
|
||||
|
||||
/// An ambient sound definition.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct SoundAmbi
|
||||
{
|
||||
|
@ -414,6 +442,7 @@ pub struct SoundAmbi
|
|||
pub volume: u16,
|
||||
}
|
||||
|
||||
/// A randomly played sound definition.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct SoundRand
|
||||
{
|
||||
|
@ -429,6 +458,7 @@ pub struct SoundRand
|
|||
pub pit_dta: Fixed,
|
||||
}
|
||||
|
||||
/// A media, as in a part of a polygon which goes up the middle of the wall.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Media
|
||||
{
|
||||
|
@ -446,6 +476,7 @@ pub struct Media
|
|||
pub xfer: TransferMode,
|
||||
}
|
||||
|
||||
/// Extra information for polygons with platforms.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Platform
|
||||
{
|
||||
|
@ -459,6 +490,7 @@ pub struct Platform
|
|||
pub tag: u16,
|
||||
}
|
||||
|
||||
/// Static map information.
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
pub struct Minf
|
||||
{
|
||||
|
@ -472,6 +504,7 @@ pub struct Minf
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Line`.
|
||||
#[derive(Serialize)]
|
||||
pub struct LineFlags: u16
|
||||
{
|
||||
|
@ -485,6 +518,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Side`.
|
||||
#[derive(Serialize)]
|
||||
pub struct SideFlags: u16
|
||||
{
|
||||
|
@ -500,6 +534,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Static environment flags.
|
||||
#[derive(Serialize)]
|
||||
pub struct EnvFlags: u16
|
||||
{
|
||||
|
@ -520,6 +555,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Static entry point flags.
|
||||
#[derive(Serialize)]
|
||||
pub struct EntFlags: u32
|
||||
{
|
||||
|
@ -535,6 +571,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Static mission flags.
|
||||
#[derive(Serialize)]
|
||||
pub struct MsnFlags: u16
|
||||
{
|
||||
|
@ -547,6 +584,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Polygon`.
|
||||
#[derive(Serialize)]
|
||||
pub struct PolyFlags: u16
|
||||
{
|
||||
|
@ -555,6 +593,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Light`.
|
||||
#[derive(Serialize)]
|
||||
pub struct LightFlags: u16
|
||||
{
|
||||
|
@ -565,6 +604,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Object`.
|
||||
#[derive(Serialize)]
|
||||
pub struct ObjectFlags: u16
|
||||
{
|
||||
|
@ -578,6 +618,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Platform`.
|
||||
#[derive(Serialize)]
|
||||
pub struct PlatformFlags: u32
|
||||
{
|
||||
|
@ -612,6 +653,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The texture type of a `Side`.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum SideType: u16
|
||||
{
|
||||
|
@ -624,6 +666,7 @@ c_enum! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The action type of a `Polygon`.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum PolyType: u16
|
||||
{
|
||||
|
@ -650,6 +693,7 @@ c_enum! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of function for a `LightFunc`.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum LightFuncType: u16
|
||||
{
|
||||
|
@ -661,6 +705,7 @@ c_enum! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of a `Light`.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum LightType: u16
|
||||
{
|
||||
|
@ -671,6 +716,7 @@ c_enum! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The liquid type of a `Media`.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum MediaType: u16
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Library for file data formats.
|
||||
//! Library for file format data readers.
|
||||
|
||||
pub mod machdr;
|
||||
pub mod map;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
//! Structures used by Marathon's Physics format.
|
||||
|
||||
use crate::{durandal::{bin::*, err::*, fixed::*}};
|
||||
use bitflags::bitflags;
|
||||
use serde::Serialize;
|
||||
|
||||
/// Reads a `PXpx` chunk.
|
||||
pub fn read_pxpx(b: &[u8]) -> ResultS<(Physics, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -40,6 +43,7 @@ pub fn read_pxpx(b: &[u8]) -> ResultS<(Physics, usize)>
|
|||
vel_bkw, vel_fwd, vel_prp, vel_rec, vel_trm}, 104))
|
||||
}
|
||||
|
||||
/// Reads a `FXpx` chunk.
|
||||
pub fn read_fxpx(b: &[u8]) -> ResultS<(Effect, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -57,6 +61,7 @@ pub fn read_fxpx(b: &[u8]) -> ResultS<(Effect, usize)>
|
|||
Ok((Effect{collection, shape, pitch, flags, delay, delay_snd}, 14))
|
||||
}
|
||||
|
||||
/// Reads a `WPpx` chunk.
|
||||
pub fn read_wppx(b: &[u8]) -> ResultS<(Weapon, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -98,6 +103,7 @@ pub fn read_wppx(b: &[u8]) -> ResultS<(Weapon, usize)>
|
|||
typ_powerup, typ_weapon, wid_idle}, 134))
|
||||
}
|
||||
|
||||
/// Reads a `PRpx` chunk.
|
||||
pub fn read_prpx(b: &[u8]) -> ResultS<(Projectile, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -128,6 +134,7 @@ pub fn read_prpx(b: &[u8]) -> ResultS<(Projectile, usize)>
|
|||
flags, speed, range, snd_pitch, snd_fly, snd_bounce}, 48))
|
||||
}
|
||||
|
||||
/// Reads a `MNpx` chunk.
|
||||
pub fn read_mnpx(b: &[u8]) -> ResultS<(Monster, usize)>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -208,6 +215,7 @@ pub fn read_mnpx(b: &[u8]) -> ResultS<(Monster, usize)>
|
|||
atk_frequency, atk_melee, atk_range}, 156))
|
||||
}
|
||||
|
||||
/// Reads a `Trigger` object.
|
||||
fn read_trigger(b: &[u8]) -> ResultS<Trigger>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -239,6 +247,7 @@ fn read_trigger(b: &[u8]) -> ResultS<Trigger>
|
|||
tic_recover, tic_round, typ_ammo, typ_casing, typ_proj})
|
||||
}
|
||||
|
||||
/// Reads a `Damage` object.
|
||||
fn read_damage(b: &[u8]) -> ResultS<Damage>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -256,6 +265,7 @@ fn read_damage(b: &[u8]) -> ResultS<Damage>
|
|||
Ok(Damage{dtype, alien, dmg_base, dmg_rand, scale})
|
||||
}
|
||||
|
||||
/// Reads an `Attack` object.
|
||||
fn read_attack(b: &[u8]) -> ResultS<Attack>
|
||||
{
|
||||
read_data! {
|
||||
|
@ -273,6 +283,7 @@ fn read_attack(b: &[u8]) -> ResultS<Attack>
|
|||
Ok(Attack{ptype, rep, error, range, shape, ofs_x, ofs_y, ofs_z})
|
||||
}
|
||||
|
||||
/// Static physics information.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Physics
|
||||
{
|
||||
|
@ -304,6 +315,7 @@ pub struct Physics
|
|||
pub vel_trm: Fixed,
|
||||
}
|
||||
|
||||
/// An effect definition.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Effect
|
||||
{
|
||||
|
@ -315,6 +327,7 @@ pub struct Effect
|
|||
pub delay_snd: OptU16,
|
||||
}
|
||||
|
||||
/// A weapon definition.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Weapon
|
||||
{
|
||||
|
@ -345,6 +358,7 @@ pub struct Weapon
|
|||
pub wid_idle: Fixed,
|
||||
}
|
||||
|
||||
/// The definition of one of two triggers for a weapon.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Trigger
|
||||
{
|
||||
|
@ -368,6 +382,7 @@ pub struct Trigger
|
|||
pub typ_proj: u16,
|
||||
}
|
||||
|
||||
/// A projectile definition.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Projectile
|
||||
{
|
||||
|
@ -390,6 +405,7 @@ pub struct Projectile
|
|||
pub snd_bounce: OptU16,
|
||||
}
|
||||
|
||||
/// A monster definition.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Monster
|
||||
{
|
||||
|
@ -446,6 +462,7 @@ pub struct Monster
|
|||
pub atk_range: Attack,
|
||||
}
|
||||
|
||||
/// A damage definition.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Damage
|
||||
{
|
||||
|
@ -456,6 +473,7 @@ pub struct Damage
|
|||
pub scale: Fixed,
|
||||
}
|
||||
|
||||
/// The definition of a monster's attack.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Attack
|
||||
{
|
||||
|
@ -470,6 +488,7 @@ pub struct Attack
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for an effect.
|
||||
#[derive(Serialize)]
|
||||
pub struct EffectFlags: u16
|
||||
{
|
||||
|
@ -482,6 +501,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a weapon.
|
||||
#[derive(Serialize)]
|
||||
pub struct WeaponFlags: u16
|
||||
{
|
||||
|
@ -500,6 +520,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a projectile.
|
||||
#[derive(Serialize)]
|
||||
pub struct ProjectileFlags: u32
|
||||
{
|
||||
|
@ -528,6 +549,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for a monster.
|
||||
#[derive(Serialize)]
|
||||
pub struct MonsterFlags: u32
|
||||
{
|
||||
|
@ -563,6 +585,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// The composite type of a monster.
|
||||
#[derive(Serialize)]
|
||||
pub struct MonsterClass: u32
|
||||
{
|
||||
|
@ -586,6 +609,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// The composite type of damage taken by something.
|
||||
#[derive(Serialize)]
|
||||
pub struct DamageTypeFlags: u32
|
||||
{
|
||||
|
@ -617,6 +641,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// A bullet shell casing emitted by a weapon.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum CasingType: u16
|
||||
{
|
||||
|
@ -630,6 +655,7 @@ c_enum! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of functionality a weapon provides.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum WeaponType: u16
|
||||
{
|
||||
|
@ -642,6 +668,7 @@ c_enum! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// A named type of damage taken by something.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum DamageType: u16
|
||||
{
|
||||
|
|
|
@ -5,7 +5,8 @@ use crate::{durandal::{bin::*, err::*, fixed::*, image::*, text::*},
|
|||
use bitflags::bitflags;
|
||||
use serde::Serialize;
|
||||
|
||||
fn color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
|
||||
/// Reads a color from a color table into `clut`.
|
||||
fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
|
||||
{
|
||||
read_data! {
|
||||
8, BE in b =>
|
||||
|
@ -27,11 +28,12 @@ fn color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn color_tables(b: &[u8],
|
||||
tab_ofs: usize,
|
||||
tab_num: usize,
|
||||
clr_num: usize)
|
||||
-> ResultS<Vec<Vec<ColorShp>>>
|
||||
/// Reads all color tables.
|
||||
pub fn color_tables(b: &[u8],
|
||||
tab_ofs: usize,
|
||||
tab_num: usize,
|
||||
clr_num: usize)
|
||||
-> ResultS<Vec<Vec<ColorShp>>>
|
||||
{
|
||||
let end = tab_num * clr_num * 8;
|
||||
|
||||
|
@ -42,7 +44,7 @@ fn color_tables(b: &[u8],
|
|||
|
||||
for clut in v.iter_mut().take(tab_num) {
|
||||
for _ in 0..clr_num {
|
||||
color(&b[p..p + 8], clut)?;
|
||||
read_color(&b[p..p + 8], clut)?;
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +52,8 @@ fn color_tables(b: &[u8],
|
|||
Ok(v)
|
||||
}
|
||||
|
||||
fn bitmap(b: &[u8]) -> ResultS<Bitmap>
|
||||
/// Reads a `Bitmap`.
|
||||
pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap>
|
||||
{
|
||||
read_data! {
|
||||
26, BE in b =>
|
||||
|
@ -116,7 +119,8 @@ fn bitmap(b: &[u8]) -> ResultS<Bitmap>
|
|||
Ok(bmp)
|
||||
}
|
||||
|
||||
fn frame(b: &[u8]) -> ResultS<Frame>
|
||||
/// Reads a `Frame`.
|
||||
pub fn read_frame(b: &[u8]) -> ResultS<Frame>
|
||||
{
|
||||
read_data! {
|
||||
36, BE in b =>
|
||||
|
@ -136,7 +140,8 @@ fn frame(b: &[u8]) -> ResultS<Frame>
|
|||
Ok(Frame{flags, min_lt, bmp_ind, wrl_l, wrl_r, wrl_t, wrl_b, wrl_x, wrl_y})
|
||||
}
|
||||
|
||||
fn sequence(b: &[u8]) -> ResultS<Sequence>
|
||||
/// Reads a `Sequence`.
|
||||
pub fn read_sequence(b: &[u8]) -> ResultS<Sequence>
|
||||
{
|
||||
read_data! {
|
||||
88, BE in b =>
|
||||
|
@ -161,7 +166,8 @@ fn sequence(b: &[u8]) -> ResultS<Sequence>
|
|||
snd_key, snd_end, loop_f})
|
||||
}
|
||||
|
||||
fn collection(b: &[u8]) -> ResultS<Collection>
|
||||
/// Reads a `Collection`.
|
||||
pub fn read_collection(b: &[u8]) -> ResultS<Collection>
|
||||
{
|
||||
read_data! {
|
||||
544, BE in b =>
|
||||
|
@ -185,13 +191,14 @@ fn collection(b: &[u8]) -> ResultS<Collection>
|
|||
}
|
||||
|
||||
let tabs = color_tables(b, tab_ofs, tab_num, clr_num)?;
|
||||
let bmps = rd_ofstable(b, bmp_ofs, bmp_num, bitmap)?;
|
||||
let frms = rd_ofstable(b, frm_ofs, frm_num, frame)?;
|
||||
let seqs = rd_ofstable(b, seq_ofs, seq_num, sequence)?;
|
||||
let bmps = rd_ofstable(b, bmp_ofs, bmp_num, read_bitmap)?;
|
||||
let frms = rd_ofstable(b, frm_ofs, frm_num, read_frame)?;
|
||||
let seqs = rd_ofstable(b, seq_ofs, seq_num, read_sequence)?;
|
||||
|
||||
Ok(Collection{ctyp: cl_type, tabs, bmps, frms, seqs})
|
||||
}
|
||||
|
||||
/// Read all of the collections in a Shapes file.
|
||||
pub fn read_shapes(b: &[u8]) -> ResultS<Vec<CollectionDef>>
|
||||
{
|
||||
let mut cl = Vec::with_capacity(32);
|
||||
|
@ -209,13 +216,13 @@ pub fn read_shapes(b: &[u8]) -> ResultS<Vec<CollectionDef>>
|
|||
let c_lo = if lo_ofs == u32::max_value() as usize {
|
||||
None
|
||||
} else {
|
||||
Some(collection(&b[lo_ofs..lo_ofs + lo_len])?)
|
||||
Some(read_collection(&b[lo_ofs..lo_ofs + lo_len])?)
|
||||
};
|
||||
|
||||
let c_hi = if hi_ofs == u32::max_value() as usize {
|
||||
None
|
||||
} else {
|
||||
Some(collection(&b[hi_ofs..hi_ofs + hi_len])?)
|
||||
Some(read_collection(&b[hi_ofs..hi_ofs + hi_len])?)
|
||||
};
|
||||
|
||||
cl.push((c_lo, c_hi));
|
||||
|
@ -228,7 +235,8 @@ pub fn read_shapes(b: &[u8]) -> ResultS<Vec<CollectionDef>>
|
|||
|
||||
impl Bitmap
|
||||
{
|
||||
fn new(w: usize, h: usize, alpha: bool, cmajr: bool) -> Self
|
||||
/// Creates an empty bitmap.
|
||||
pub fn new(w: usize, h: usize, alpha: bool, cmajr: bool) -> Self
|
||||
{
|
||||
Self{w, h, alpha, cmajr, cr: Vec::with_capacity(w * h)}
|
||||
}
|
||||
|
@ -236,6 +244,7 @@ impl Bitmap
|
|||
|
||||
impl<'a, 'b> ImageShp<'a, 'b>
|
||||
{
|
||||
/// Creates an `ImageShp` with the given bitmap.
|
||||
pub fn new(bmp: &'a Bitmap, clut: &'b [ColorShp]) -> Self
|
||||
{
|
||||
Self{bmp, clut}
|
||||
|
@ -302,6 +311,7 @@ impl Color for ColorShp
|
|||
}
|
||||
}
|
||||
|
||||
/// A color in an `ImageShp`'s color table.
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum ColorShp
|
||||
{
|
||||
|
@ -315,6 +325,7 @@ pub enum ColorShp
|
|||
},
|
||||
}
|
||||
|
||||
/// An unpacked Shape bitmap.
|
||||
#[derive(Debug)]
|
||||
pub struct Bitmap
|
||||
{
|
||||
|
@ -325,12 +336,15 @@ pub struct Bitmap
|
|||
cmajr: bool,
|
||||
}
|
||||
|
||||
/// An image from a Shape. This mainly just exists so that `Bitmap` can use the
|
||||
/// `Image` trait.
|
||||
pub struct ImageShp<'a, 'b>
|
||||
{
|
||||
bmp: &'a Bitmap,
|
||||
clut: &'b [ColorShp],
|
||||
}
|
||||
|
||||
/// A frame, also known as a low level shape.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Frame
|
||||
{
|
||||
|
@ -345,6 +359,7 @@ pub struct Frame
|
|||
wrl_y: Unit,
|
||||
}
|
||||
|
||||
/// A sequence, also known as a high level shape.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Sequence
|
||||
{
|
||||
|
@ -361,6 +376,7 @@ pub struct Sequence
|
|||
loop_f: u16,
|
||||
}
|
||||
|
||||
/// A collection of color tables, bitmaps, frames and sequences.
|
||||
#[derive(Debug)]
|
||||
pub struct Collection
|
||||
{
|
||||
|
@ -371,6 +387,7 @@ pub struct Collection
|
|||
pub seqs: Vec<Sequence>,
|
||||
}
|
||||
|
||||
/// A collection, which may have low- and high-definition variations, or none.
|
||||
pub type CollectionDef = (Option<Collection>, Option<Collection>);
|
||||
|
||||
bitflags! {
|
||||
|
@ -382,6 +399,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Frame`.
|
||||
#[derive(Serialize)]
|
||||
pub struct FrameFlags: u16
|
||||
{
|
||||
|
@ -392,6 +410,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of a collection.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum CollectionType: u16
|
||||
{
|
||||
|
@ -404,6 +423,7 @@ c_enum! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of or number of views for a sequence.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum ViewType: u16
|
||||
{
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
use crate::durandal::{bin::*, err::*, fixed::*, sound::*};
|
||||
use bitflags::bitflags;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
fn sound(b: &[u8]) -> ResultS<Sound16>
|
||||
/// Reads a sound.
|
||||
pub fn read_sound(b: &[u8]) -> ResultS<Sound16>
|
||||
{
|
||||
read_data! {
|
||||
21, BE in b =>
|
||||
|
@ -44,7 +45,8 @@ fn sound(b: &[u8]) -> ResultS<Sound16>
|
|||
}
|
||||
}
|
||||
|
||||
fn sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
|
||||
/// Reads a sound definition.
|
||||
pub fn read_sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
|
||||
{
|
||||
read_data! {
|
||||
64, BE in b =>
|
||||
|
@ -83,12 +85,13 @@ fn sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
|
|||
Ok(Some((ofs, index, SoundDef{header, sounds})))
|
||||
}
|
||||
|
||||
/// Reads all sounds from a Sound file.
|
||||
pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>>
|
||||
{
|
||||
read_data! {
|
||||
260, BE in b =>
|
||||
version = u32[0];
|
||||
magic = iden[4];
|
||||
magic = Ident[4];
|
||||
src_num = u16[8] as usize;
|
||||
snd_num = u16[10] as usize;
|
||||
}
|
||||
|
@ -101,12 +104,12 @@ pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>>
|
|||
let mut p = 260;
|
||||
|
||||
for _ in 0..src_num {
|
||||
let mut st = HashMap::with_capacity(snd_num);
|
||||
let mut st = BTreeMap::new();
|
||||
|
||||
for _ in 0..snd_num {
|
||||
if let Some((ofs, idx, mut def)) = sound_def(&b[p..p + 64])? {
|
||||
if let Some((ofs, idx, mut def)) = read_sound_def(&b[p..p + 64])? {
|
||||
for &ofs in &ofs {
|
||||
def.sounds.push(sound(&b[ofs..])?);
|
||||
def.sounds.push(read_sound(&b[ofs..])?);
|
||||
}
|
||||
|
||||
st.insert(idx, def);
|
||||
|
@ -121,6 +124,7 @@ pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>>
|
|||
Ok(sc)
|
||||
}
|
||||
|
||||
/// The header of a sound definition.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct SoundHead
|
||||
{
|
||||
|
@ -131,15 +135,18 @@ pub struct SoundHead
|
|||
pub pitch_hi: Fixed,
|
||||
}
|
||||
|
||||
/// A sound definition containing one, many or no sounds.
|
||||
pub struct SoundDef
|
||||
{
|
||||
pub header: SoundHead,
|
||||
pub sounds: Vec<Sound16>,
|
||||
}
|
||||
|
||||
pub type SoundTable = HashMap<u16, SoundDef>;
|
||||
/// A table of sound definitions.
|
||||
pub type SoundTable = BTreeMap<u16, SoundDef>;
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `SoundHead`.
|
||||
#[derive(Serialize)]
|
||||
pub struct SoundFlags: u16
|
||||
{
|
||||
|
@ -154,6 +161,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The type of volume this sound has.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum Volume: u16
|
||||
{
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
//! Structures used by Marathon's Map format's terminal definitions.
|
||||
|
||||
use crate::durandal::{err::*, text::*};
|
||||
use bitflags::bitflags;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
|
||||
fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
|
||||
/// Reads a `Group`.
|
||||
pub fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
|
||||
{
|
||||
read_data! {
|
||||
12, BE in b =>
|
||||
|
@ -22,7 +25,8 @@ fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
|
|||
Ok(Group{flags, ttype, pdata, lines, text})
|
||||
}
|
||||
|
||||
fn read_face(b: &[u8]) -> ResultS<Face>
|
||||
/// Reads a `Face`.
|
||||
pub fn read_face(b: &[u8]) -> ResultS<Face>
|
||||
{
|
||||
read_data! {
|
||||
6, BE in b =>
|
||||
|
@ -34,6 +38,7 @@ fn read_face(b: &[u8]) -> ResultS<Face>
|
|||
Ok(Face{start, face, color})
|
||||
}
|
||||
|
||||
/// Reads a `term` chunk.
|
||||
pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
|
||||
{
|
||||
const SIZE_GROUP: usize = 12;
|
||||
|
@ -76,6 +81,7 @@ pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
|
|||
Ok((Terminal{lines, groups, faces}, end))
|
||||
}
|
||||
|
||||
/// A terminal definition, with collections of groups and faces.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Terminal
|
||||
{
|
||||
|
@ -84,6 +90,7 @@ pub struct Terminal
|
|||
faces: Vec<Face>,
|
||||
}
|
||||
|
||||
/// A text face.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Face
|
||||
{
|
||||
|
@ -92,6 +99,7 @@ pub struct Face
|
|||
color: u16,
|
||||
}
|
||||
|
||||
/// A terminal command grouping.
|
||||
#[derive(Serialize)]
|
||||
pub struct Group
|
||||
{
|
||||
|
@ -103,6 +111,7 @@ pub struct Group
|
|||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags for `Group`.
|
||||
#[derive(Serialize)]
|
||||
pub struct GroupFlags: u16
|
||||
{
|
||||
|
@ -112,6 +121,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
c_enum! {
|
||||
/// The command of a `Group`.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum GroupType: u16
|
||||
{
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
//! Transfer Mode type.
|
||||
|
||||
use crate::durandal::err::*;
|
||||
use serde::Serialize;
|
||||
|
||||
c_enum! {
|
||||
/// A rendering style for many things.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum TransferMode: u16
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue