add documentation for everything

png-branch
an 2019-03-01 04:27:14 -05:00
parent 789e3de93f
commit fc27d2d0f4
16 changed files with 385 additions and 87 deletions

View File

@ -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>);

View File

@ -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()))
}
}
}

View File

@ -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();

View File

@ -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

View File

@ -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)?;

View File

@ -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()

View File

@ -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,

View File

@ -1,4 +1,4 @@
//! Library for various utilities.
//! Library for utilities.
#[macro_use]
pub mod err;

View File

@ -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,

View File

@ -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
{

View File

@ -1,4 +1,4 @@
//! Library for file data formats.
//! Library for file format data readers.
pub mod machdr;
pub mod map;

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{